00001 /* 00002 * Copyright (C) 2001-2002 by egnite Software GmbH. All rights reserved. 00003 * 00004 * Redistribution and use in source and binary forms, with or without 00005 * modification, are permitted provided that the following conditions 00006 * are met: 00007 * 00008 * 1. Redistributions of source code must retain the above copyright 00009 * notice, this list of conditions and the following disclaimer. 00010 * 2. Redistributions in binary form must reproduce the above copyright 00011 * notice, this list of conditions and the following disclaimer in the 00012 * documentation and/or other materials provided with the distribution. 00013 * 3. All advertising materials mentioning features or use of this 00014 * software must display the following acknowledgement: 00015 * 00016 * This product includes software developed by egnite Software GmbH 00017 * and its contributors. 00018 * 00019 * THIS SOFTWARE IS PROVIDED BY EGNITE SOFTWARE GMBH AND CONTRIBUTORS 00020 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 00021 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 00022 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL EGNITE 00023 * SOFTWARE GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 00024 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 00025 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 00026 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 00027 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 00028 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 00029 * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 00030 * SUCH DAMAGE. 00031 * 00032 * For additional information see http://www.ethernut.de/ 00033 * 00034 * - 00035 * Portions Copyright (c) 1983, 1993 by 00036 * The Regents of the University of California. All rights reserved. 00037 * 00038 * Redistribution and use in source and binary forms, with or without 00039 * modification, are permitted provided that the following conditions 00040 * are met: 00041 * 1. Redistributions of source code must retain the above copyright 00042 * notice, this list of conditions and the following disclaimer. 00043 * 2. Redistributions in binary form must reproduce the above copyright 00044 * notice, this list of conditions and the following disclaimer in the 00045 * documentation and/or other materials provided with the distribution. 00046 * 3. All advertising materials mentioning features or use of this software 00047 * must display the following acknowledgement: 00048 * This product includes software developed by the University of 00049 * California, Berkeley and its contributors. 00050 * 4. Neither the name of the University nor the names of its contributors 00051 * may be used to endorse or promote products derived from this software 00052 * without specific prior written permission. 00053 * 00054 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 00055 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00056 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00057 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 00058 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 00059 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 00060 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 00061 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00062 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 00063 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 00064 * SUCH DAMAGE. 00065 * - 00066 * Portions Copyright (c) 1993 by Digital Equipment Corporation. 00067 * 00068 * Permission to use, copy, modify, and distribute this software for any 00069 * purpose with or without fee is hereby granted, provided that the above 00070 * copyright notice and this permission notice appear in all copies, and that 00071 * the name of Digital Equipment Corporation not be used in advertising or 00072 * publicity pertaining to distribution of the document or software without 00073 * specific, written prior permission. 00074 * 00075 * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL 00076 * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES 00077 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT 00078 * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 00079 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 00080 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS 00081 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 00082 * SOFTWARE. 00083 */ 00084 00085 /* 00086 * $Log: dhcp.c,v $ 00087 * Revision 1.1 2002/08/01 17:34:29 harald 00088 * First check in 00089 * 00090 */ 00091 00092 #include <string.h> 00093 00094 #include "eboot.h" 00095 #include "ip.h" 00096 #include "dhcp.h" 00097 00098 /*! 00099 * \addtogroup xgDhcp 00100 */ 00101 /*@{*/ 00102 00103 static u_char cookie[4] = { 0x63, 0x82, 0x53, 0x63 }; 00104 00105 /*! 00106 * \brief Initialize the global send frame for DHCP requests. 00107 * 00108 * \return Size of the frame. 00109 */ 00110 u_short DhcpFrameInit(void) 00111 { 00112 u_short i; 00113 BOOTPHDR *bp = &sframe.u.bootp; 00114 u_char *op = bp->bp_options; 00115 00116 for(i = 0; i < sizeof(BOOTFRAME); i++) 00117 *((u_char *)&sframe + i) = 0; 00118 00119 bp->bp_op = 1; 00120 bp->bp_xid = 0x04030201; 00121 bp->bp_htype = 1; 00122 bp->bp_hlen = sizeof(mac); 00123 for(i = 0; i < 6; i++) 00124 bp->bp_chaddr[i] = mac[i]; 00125 for(i = 0; i < 4; i++) 00126 *op++ = cookie[i]; 00127 00128 *op++ = DHCPOPT_MSGTYPE; 00129 *op++ = 1; 00130 *op++ = DHCP_DISCOVER; 00131 00132 *op++ = DHCPOPT_END; 00133 00134 return sizeof(BOOTPHDR) - sizeof(sframe.u.bootp.bp_options) + 8; 00135 } 00136 00137 u_short DhcpRequestFrame(void) 00138 { 00139 BOOTPHDR *bp = &sframe.u.bootp; 00140 u_char *op = &bp->bp_options[6]; 00141 00142 *op++ = DHCP_REQUEST; 00143 00144 *op++ = DHCPOPT_REQUESTIP; 00145 *op++ = 4; 00146 *op++ = (u_char)rframe.u.bootp.bp_yiaddr; 00147 *op++ = (u_char)(rframe.u.bootp.bp_yiaddr >> 8); 00148 *op++ = (u_char)(rframe.u.bootp.bp_yiaddr >> 16); 00149 *op++ = (u_char)(rframe.u.bootp.bp_yiaddr >> 24); 00150 00151 *op++ = DHCPOPT_SID; 00152 *op++ = 4; 00153 *op++ = (u_char)sid; 00154 *op++ = (u_char)(sid >> 8); 00155 *op++ = (u_char)(sid >> 16); 00156 *op++ = (u_char)(sid >> 24); 00157 00158 *op++ = DHCPOPT_END; 00159 00160 return sizeof(BOOTPHDR) - sizeof(sframe.u.bootp.bp_options) + 20; 00161 } 00162 00163 /*! 00164 * \brief Retrive the specified DCHP option. 00165 * 00166 * \param opt Option to look for. 00167 * \param ptr Pointer to the buffer that receives the option value. 00168 * \param size Size of the buffer. 00169 * 00170 * \return Size of the retrieved option value or zero, 00171 * if the specified option couldn't be found. 00172 */ 00173 u_char DhcpGetOption(u_char opt, void *ptr, u_char size) 00174 { 00175 register u_char *cp; 00176 u_char i; 00177 00178 cp = rframe.u.bootp.bp_options + 4; 00179 for(;;) { 00180 if(*cp == DHCPOPT_PAD) { 00181 cp++; 00182 continue; 00183 } 00184 if(*cp == DHCPOPT_END) 00185 break; 00186 if(*cp == opt) { 00187 if(*(cp + 1) < size) 00188 size = *(cp + 1); 00189 for(i = 0; i < size; i++) 00190 *(((u_char *)ptr) + i) = *(cp + i + 2); 00191 return *(cp + 1); 00192 } 00193 cp++; 00194 cp += *cp; 00195 cp++; 00196 } 00197 return 0; 00198 } 00199 00200 /*! 00201 * \brief Query any DHCP server on the local net. 00202 * 00203 * On success, this routine will fill some global 00204 * variables: 00205 * 00206 * - local_ip 00207 * - server_ip 00208 * - bootfile 00209 * - netmask 00210 * - broadcast 00211 * - gateway 00212 * - dns 00213 * - sid 00214 * 00215 * \return 0 on success, -1 otherwise. 00216 */ 00217 int DhcpQuery(void) 00218 { 00219 u_char type; 00220 u_char retry; 00221 int rlen; 00222 int slen; 00223 u_char i; 00224 u_char *cp; 00225 00226 /* 00227 * Discovery loop. 00228 */ 00229 slen = DhcpFrameInit(); 00230 for(rlen = retry = 0; rlen == 0 && retry < 10; retry++) { 00231 if(UdpOutput(INADDR_BROADCAST, DHCP_SERVERPORT, DHCP_CLIENTPORT, slen) < 0) 00232 return -1; 00233 if((rlen = UdpInput(DHCP_CLIENTPORT, 5000)) < 0) 00234 break; 00235 if(rlen && 00236 rframe.u.bootp.bp_xid == sframe.u.bootp.bp_xid && 00237 DhcpGetOption(DHCPOPT_MSGTYPE, &type, 1) == 1 && 00238 type == DHCP_OFFER) 00239 break; 00240 rlen = 0; 00241 } 00242 if(rlen == 0) { 00243 return -1; 00244 } 00245 00246 DhcpGetOption(DHCPOPT_SID, &sid, 4); 00247 00248 /* 00249 * Request loop. 00250 */ 00251 slen = DhcpRequestFrame(); 00252 for(rlen = retry = 0; rlen == 0 && retry < 10; retry++) { 00253 if(UdpOutput(INADDR_BROADCAST, DHCP_SERVERPORT, DHCP_CLIENTPORT, slen) < 0) 00254 return -1; 00255 if((rlen = UdpInput(DHCP_CLIENTPORT, 1000)) < 0) 00256 return -1; 00257 if(rlen && 00258 rframe.u.bootp.bp_xid == sframe.u.bootp.bp_xid && 00259 DhcpGetOption(DHCPOPT_MSGTYPE, &type, 1) == 1 && 00260 type == DHCP_ACK) 00261 break; 00262 rlen = 0; 00263 } 00264 if(rlen == 0) { 00265 return -1; 00266 } 00267 00268 local_ip = rframe.u.bootp.bp_yiaddr; 00269 server_ip = rframe.u.bootp.bp_siaddr; 00270 for(cp = rframe.u.bootp.bp_file, i = 0; *cp && i < sizeof(bootfile) - 1; cp++, i++) 00271 bootfile[i] = *cp; 00272 bootfile[i] = 0; 00273 00274 DhcpGetOption(DHCPOPT_NETMASK, &netmask, 4); 00275 DhcpGetOption(DHCPOPT_BROADCAST, &broadcast, 4); 00276 DhcpGetOption(DHCPOPT_GATEWAY, &gateway, 4); 00277 DhcpGetOption(DHCPOPT_DNS, &dns, 4); 00278 DhcpGetOption(DHCPOPT_SID, &sid, 4); 00279 00280 return 0; 00281 } 00282 00283 /*@}*/