GUI: Fix Tomato RAF theme for all builds. Compilation typo.
[tomato.git] / release / src-rt-6.x.4708 / cfe / cfe / net / net_dhcp.c
blob58fdbb15ab540294b428fffadba62a58fb658a27
1 /* *********************************************************************
2 * Broadcom Common Firmware Environment (CFE)
3 *
4 * DHCP Client File: net_dhcp.c
5 *
6 * This module contains a DHCP client.
7 *
8 * Author: Mitch Lichtenberg (mpl@broadcom.com)
9 *
10 *********************************************************************
12 * Copyright 2000,2001,2002,2003
13 * Broadcom Corporation. All rights reserved.
15 * This software is furnished under license and may be used and
16 * copied only in accordance with the following terms and
17 * conditions. Subject to these conditions, you may download,
18 * copy, install, use, modify and distribute modified or unmodified
19 * copies of this software in source and/or binary form. No title
20 * or ownership is transferred hereby.
22 * 1) Any source code used, modified or distributed must reproduce
23 * and retain this copyright notice and list of conditions
24 * as they appear in the source file.
26 * 2) No right is granted to use any trade name, trademark, or
27 * logo of Broadcom Corporation. The "Broadcom Corporation"
28 * name may not be used to endorse or promote products derived
29 * from this software without the prior written permission of
30 * Broadcom Corporation.
32 * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
33 * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
34 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
35 * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
36 * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
37 * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT,
38 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
39 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
40 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
41 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
42 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
43 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF
44 * THE POSSIBILITY OF SUCH DAMAGE.
45 ********************************************************************* */
47 #include "lib_types.h"
48 #include "lib_string.h"
49 #include "lib_queue.h"
50 #include "lib_malloc.h"
51 #include "lib_printf.h"
53 #include "env_subr.h"
55 #include "cfe_iocb.h"
56 #include "cfe_devfuncs.h"
57 #include "cfe_ioctl.h"
58 #include "cfe_timer.h"
59 #include "cfe_error.h"
61 #include "net_ebuf.h"
62 #include "net_ether.h"
64 #include "cfe.h"
65 #include "bsp_config.h"
67 #include "net_api.h"
69 #if CFG_DHCP
71 /* *********************************************************************
72 * Constants
73 ********************************************************************* */
76 #define UDP_PORT_BOOTPS 67
77 #define UDP_PORT_BOOTPC 68
79 #define DHCP_REQ_TIMEOUT (1*CFE_HZ)
80 #define DHCP_NUM_RETRIES 8
82 #define DHCP_OP_BOOTREQUEST 1
83 #define DHCP_OP_BOOTREPLY 2
85 #define DHCP_HWTYPE_ETHERNET 1
87 #define DHCP_TAG_FUNCTION 53
88 #define DHCP_FUNCTION_DISCOVER 1
89 #define DHCP_FUNCTION_OFFER 2
90 #define DHCP_FUNCTION_REQUEST 3
91 #define DHCP_FUNCTION_ACK 5
93 #define DHCP_TAG_NETMASK 1
94 #define DHCP_TAG_DOMAINNAME 0x0F
95 #define DHCP_TAG_GATEWAY 0x03
96 #define DHCP_TAG_NAMESERVER 0x06
97 #define DHCP_TAG_SWAPSERVER 0x10
98 #define DHCP_TAG_ROOTPATH 0x11
99 #define DHCP_TAG_EXTENSIONS 0x12
100 #define DHCP_TAG_SERVERIDENT 54
101 #define DHCP_TAG_PARAMLIST 55
102 #define DHCP_TAG_CLIENTID 61
103 #define DHCP_TAG_CLASSID 60
104 #define DHCP_TAG_REQADDR 50
105 #define DHCP_TAG_LEASE_TIME 51
106 #define DHCP_TAG_SCRIPT 130 /* CFE extended option */
107 #define DHCP_TAG_OPTIONS 131 /* CFE extended option */
109 #define DHCP_TAG_END 0xFF
111 #define DHCP_MAGIC_NUMBER 0x63825363
113 /*#define _DEBUG_*/
116 /* *********************************************************************
117 * dhcp_set_envvars(reply)
119 * Using the supplied DHCP reply data, set environment variables
120 * to contain data from the reply.
122 * Input parameters:
123 * reply - dhcp reply
125 * Return value:
126 * nothing
127 ********************************************************************* */
129 void dhcp_set_envvars(dhcpreply_t *reply)
131 char buffer[50];
133 env_delenv("BOOT_SERVER");
134 env_delenv("BOOT_FILE");
135 env_delenv("BOOT_SCRIPT");
136 env_delenv("BOOT_OPTIONS");
138 if (reply->dr_bootserver[0] | reply->dr_bootserver[1] |
139 reply->dr_bootserver[2] | reply->dr_bootserver[3]) {
140 sprintf(buffer,"%I",reply->dr_bootserver);
141 env_setenv("BOOT_SERVER",buffer,ENV_FLG_BUILTIN);
144 if (reply->dr_bootfile && reply->dr_bootfile[0]) {
145 env_setenv("BOOT_FILE",reply->dr_bootfile,ENV_FLG_BUILTIN);
148 if (reply->dr_script && reply->dr_script[0]) {
149 env_setenv("BOOT_SCRIPT",reply->dr_script,ENV_FLG_BUILTIN);
152 if (reply->dr_options && reply->dr_options[0]) {
153 env_setenv("BOOT_OPTIONS",reply->dr_options,ENV_FLG_BUILTIN);
157 /* *********************************************************************
158 * dhcp_dumptag(tag,len,buf)
160 * Dump out information from a DHCP tag
162 * Input parameters:
163 * tag - tag ID
164 * len - length of data
165 * buf - data
167 * Return value:
168 * nothing
169 ********************************************************************* */
171 #ifdef _DEBUG_
172 static void dhcp_dumptag(uint8_t tag,uint8_t len,uint8_t *buf)
174 unsigned int idx;
176 xprintf("DHCP: ");
178 switch (tag) {
179 case DHCP_TAG_FUNCTION:
180 xprintf("DHCP Function: %d\n",buf[0]);
181 break;
182 case DHCP_TAG_LEASE_TIME:
183 idx = (((unsigned int) buf[0]) << 24) |
184 (((unsigned int) buf[1]) << 16) |
185 (((unsigned int) buf[2]) << 8) |
186 (((unsigned int) buf[3]) << 0);
187 xprintf("Lease Time: %d seconds\n",idx);
188 break;
189 case DHCP_TAG_SERVERIDENT:
190 xprintf("DHCP Server ID: %d.%d.%d.%d\n",
191 buf[0],buf[1],buf[2],buf[3]);
192 break;
193 case DHCP_TAG_NETMASK:
194 xprintf("Netmask: %d.%d.%d.%d\n",buf[0],buf[1],buf[2],buf[3]);
195 break;
196 case DHCP_TAG_DOMAINNAME:
197 buf[len] = 0;
198 xprintf("Domain: %s\n",buf);
199 break;
200 case DHCP_TAG_GATEWAY:
201 xprintf("Gateway: %d.%d.%d.%d\n",buf[0],buf[1],buf[2],buf[3]);
202 break;
203 case DHCP_TAG_NAMESERVER:
204 xprintf("Nameserver: %d.%d.%d.%d\n",buf[0],buf[1],buf[2],buf[3]);
205 break;
206 case DHCP_TAG_SWAPSERVER:
207 buf[len] = 0;
208 xprintf("Swapserver: %s\n",buf);
209 break;
210 case DHCP_TAG_ROOTPATH:
211 buf[len] = 0;
212 xprintf("Rootpath: %s\n",buf);
213 break;
214 case DHCP_TAG_SCRIPT:
215 buf[len] = 0;
216 xprintf("CFE Script: %s\n",buf);
217 break;
218 case DHCP_TAG_OPTIONS:
219 buf[len] = 0;
220 xprintf("CFE Boot Options: %s\n",buf);
221 break;
222 default:
223 xprintf("Tag %d len %d [",tag,len);
224 for (idx = 0; idx < len; idx++) {
225 if ((buf[idx] >= 32) && (buf[idx] < 127)) xprintf("%c",buf[idx]);
227 xprintf("]\n");
228 break;
232 #endif
234 /* *********************************************************************
235 * dhcp_free_reply(reply)
237 * Free memory associated with a DHCP reply.
239 * Input parameters:
240 * reply - pointer to DHCP reply
242 * Return value:
243 * nothing
244 ********************************************************************* */
246 void dhcp_free_reply(dhcpreply_t *reply)
248 if (reply->dr_hostname) KFREE(reply->dr_hostname);
249 if (reply->dr_domainname) KFREE(reply->dr_domainname);
250 if (reply->dr_bootfile) KFREE(reply->dr_bootfile);
251 if (reply->dr_rootpath) KFREE(reply->dr_rootpath);
252 if (reply->dr_swapserver) KFREE(reply->dr_swapserver);
253 if (reply->dr_script) KFREE(reply->dr_script);
254 if (reply->dr_options) KFREE(reply->dr_options);
255 KFREE(reply);
258 /* *********************************************************************
259 * dhcp_build_discover()
261 * Build a DHCP DISCOVER packet
263 * Input parameters:
264 * hwaddr - our hardware address
265 * idptr - pointer to int to receive the DHCP packet ID
266 * serveraddr - pointer to server address (REQUEST) or
267 * NULL (DISCOVER)
268 * ebufptr - receives pointer to ebuf
270 * Return value:
271 * 0 if ok, else error code
272 ********************************************************************* */
274 static int dhcp_build_discover(uint8_t *hwaddr,
275 uint32_t id,
276 ebuf_t **ebufptr)
278 uint8_t ipaddr[IP_ADDR_LEN];
279 ebuf_t *buf;
280 uint8_t junk[128];
283 * Get a buffer and fill it in.
286 ipaddr[0] = 0; ipaddr[1] = 0; ipaddr[2] = 0; ipaddr[3] = 0;
287 memset(junk,0,sizeof(junk));
289 buf = udp_alloc();
291 if (buf == NULL) {
292 return CFE_ERR_NOMEM;
295 memset(buf->eb_ptr,0,548);
297 ebuf_append_u8(buf,DHCP_OP_BOOTREQUEST);
298 ebuf_append_u8(buf,DHCP_HWTYPE_ETHERNET);
299 ebuf_append_u8(buf,ENET_ADDR_LEN);
300 ebuf_append_u8(buf,0); /* hops */
301 ebuf_append_u32_be(buf,id);
302 ebuf_append_u16_be(buf,0); /* sec since boot */
303 ebuf_append_u16_be(buf,0); /* flags */
305 ebuf_append_bytes(buf,ipaddr,IP_ADDR_LEN); /* ciaddr */
306 ebuf_append_bytes(buf,ipaddr,IP_ADDR_LEN); /* yiaddr */
307 ebuf_append_bytes(buf,ipaddr,IP_ADDR_LEN); /* siaddr */
308 ebuf_append_bytes(buf,ipaddr,IP_ADDR_LEN); /* giaddr */
310 ebuf_append_bytes(buf,hwaddr,ENET_ADDR_LEN); /* chaddr */
311 ebuf_append_bytes(buf,junk,10); /* rest of chaddr */
312 ebuf_append_bytes(buf,junk,64); /* sname */
313 ebuf_append_bytes(buf,junk,128); /* file */
315 ebuf_append_u32_be(buf,DHCP_MAGIC_NUMBER);
317 ebuf_append_u8(buf,DHCP_TAG_FUNCTION); /* function code */
318 ebuf_append_u8(buf,1);
319 ebuf_append_u8(buf,DHCP_FUNCTION_DISCOVER);
321 ebuf_append_u8(buf,DHCP_TAG_PARAMLIST);
322 ebuf_append_u8(buf,8); /* count of tags that follow */
323 ebuf_append_u8(buf,DHCP_TAG_NETMASK);
324 ebuf_append_u8(buf,DHCP_TAG_DOMAINNAME);
325 ebuf_append_u8(buf,DHCP_TAG_GATEWAY);
326 ebuf_append_u8(buf,DHCP_TAG_NAMESERVER);
327 ebuf_append_u8(buf,DHCP_TAG_SWAPSERVER);
328 ebuf_append_u8(buf,DHCP_TAG_ROOTPATH);
329 ebuf_append_u8(buf,DHCP_TAG_SCRIPT);
330 ebuf_append_u8(buf,DHCP_TAG_OPTIONS);
333 ebuf_append_u8(buf,DHCP_TAG_END); /* terminator */
336 * Return the packet
339 *ebufptr = buf;
341 return 0;
344 /* *********************************************************************
345 * dhcp_build_request()
347 * Build a DHCP DISCOVER or REQUEST packet
349 * Input parameters:
350 * hwaddr - our hardware address
351 * idptr - pointer to int to receive the DHCP packet ID
352 * serveraddr - pointer to server address (REQUEST) or
353 * NULL (DISCOVER)
354 * ebufptr - receives pointer to ebuf
356 * Return value:
357 * 0 if ok, else error code
358 ********************************************************************* */
360 static int dhcp_build_request(uint8_t *hwaddr,
361 uint32_t id,
362 uint8_t *serveraddr,
363 uint8_t *reqip,
364 ebuf_t **ebufptr)
366 uint8_t ipaddr[IP_ADDR_LEN];
367 ebuf_t *buf;
368 uint8_t junk[128];
371 * Get a buffer and fill it in.
374 ipaddr[0] = 0; ipaddr[1] = 0; ipaddr[2] = 0; ipaddr[3] = 0;
375 memset(junk,0,sizeof(junk));
377 buf = udp_alloc();
379 if (buf == NULL) {
380 return CFE_ERR_NOMEM;
383 memset(buf->eb_ptr,0,548);
385 ebuf_append_u8(buf,DHCP_OP_BOOTREQUEST);
386 ebuf_append_u8(buf,DHCP_HWTYPE_ETHERNET);
387 ebuf_append_u8(buf,ENET_ADDR_LEN);
388 ebuf_append_u8(buf,0); /* hops */
389 ebuf_append_u32_be(buf,id);
390 ebuf_append_u16_be(buf,0); /* sec since boot */
391 ebuf_append_u16_be(buf,0); /* flags */
393 ebuf_append_bytes(buf,ipaddr,IP_ADDR_LEN); /* ciaddr */
394 ebuf_append_bytes(buf,ipaddr,IP_ADDR_LEN); /* yiaddr */
395 ebuf_append_bytes(buf,ipaddr,IP_ADDR_LEN); /* siaddr */
396 ebuf_append_bytes(buf,ipaddr,IP_ADDR_LEN); /* giaddr */
398 ebuf_append_bytes(buf,hwaddr,ENET_ADDR_LEN); /* chaddr */
399 ebuf_append_bytes(buf,junk,10); /* rest of chaddr */
401 ebuf_append_bytes(buf,junk,64); /* sname */
403 ebuf_append_bytes(buf,junk,128); /* file */
405 ebuf_append_u32_be(buf,DHCP_MAGIC_NUMBER);
407 ebuf_append_u8(buf,DHCP_TAG_FUNCTION); /* function code */
408 ebuf_append_u8(buf,1);
410 ebuf_append_u8(buf,DHCP_FUNCTION_REQUEST);
412 ebuf_append_u8(buf,DHCP_TAG_REQADDR);
413 ebuf_append_u8(buf,IP_ADDR_LEN);
414 ebuf_append_bytes(buf,reqip,IP_ADDR_LEN);
416 ebuf_append_u8(buf,DHCP_TAG_SERVERIDENT); /* server ID */
417 ebuf_append_u8(buf,IP_ADDR_LEN);
418 ebuf_append_bytes(buf,serveraddr,IP_ADDR_LEN);
420 ebuf_append_u8(buf,DHCP_TAG_CLIENTID); /* client ID */
421 ebuf_append_u8(buf,7);
422 ebuf_append_u8(buf,1);
423 ebuf_append_bytes(buf,hwaddr,ENET_ADDR_LEN);
425 ebuf_append_u8(buf,DHCP_TAG_PARAMLIST);
426 ebuf_append_u8(buf,8); /* count of tags that follow */
427 ebuf_append_u8(buf,DHCP_TAG_NETMASK);
428 ebuf_append_u8(buf,DHCP_TAG_DOMAINNAME);
429 ebuf_append_u8(buf,DHCP_TAG_GATEWAY);
430 ebuf_append_u8(buf,DHCP_TAG_NAMESERVER);
431 ebuf_append_u8(buf,DHCP_TAG_SWAPSERVER);
432 ebuf_append_u8(buf,DHCP_TAG_ROOTPATH);
433 ebuf_append_u8(buf,DHCP_TAG_SCRIPT);
434 ebuf_append_u8(buf,DHCP_TAG_OPTIONS);
437 ebuf_append_u8(buf,DHCP_TAG_END); /* terminator */
440 * Return the packet
443 *ebufptr = buf;
445 return 0;
449 /* *********************************************************************
450 * dhcp_wait_reply(s,id,reply,serveraddr)
452 * Wait for a reply from the DHCP server
454 * Input parameters:
455 * s - socket
456 * id - ID of request we sent
457 * reply - structure to store results in
458 * expfcode - expected DHCP_FUNCTION tag value
460 * Return value:
461 * 0 if ok (reply found)
462 * else error
463 ********************************************************************* */
465 static int dhcp_wait_reply(int s,uint32_t id,dhcpreply_t *reply,int expfcode)
467 uint32_t tmpd;
468 uint8_t tmpb;
469 int64_t timer;
470 int nres = 0;
471 uint8_t ciaddr[IP_ADDR_LEN];
472 uint8_t yiaddr[IP_ADDR_LEN];
473 uint8_t siaddr[IP_ADDR_LEN];
474 uint8_t giaddr[IP_ADDR_LEN];
475 int8_t junk[128];
476 char *hostname;
477 char *bootfile;
478 ebuf_t *buf;
479 int fcode = -1;
482 * Set a timer for the response
485 TIMER_SET(timer,DHCP_REQ_TIMEOUT);
488 * Start waiting...
491 while (!TIMER_EXPIRED(timer)) {
492 POLL();
494 buf = udp_recv(s);
495 if (!buf) continue;
497 ebuf_get_u8(buf,tmpb);
498 if (tmpb != DHCP_OP_BOOTREPLY) {
499 goto drop;
502 ebuf_get_u8(buf,tmpb);
503 if (tmpb != DHCP_HWTYPE_ETHERNET) {
504 goto drop;
507 ebuf_get_u8(buf,tmpb);
508 if (tmpb != ENET_ADDR_LEN) {
509 goto drop;
512 ebuf_skip(buf,1); /* hops */
514 ebuf_get_u32_be(buf,tmpd); /* check ID */
515 if (tmpd != id) {
516 goto drop;
519 ebuf_skip(buf,2); /* seconds since boot */
520 ebuf_skip(buf,2); /* flags */
522 ebuf_get_bytes(buf,ciaddr,IP_ADDR_LEN);
523 ebuf_get_bytes(buf,yiaddr,IP_ADDR_LEN);
524 ebuf_get_bytes(buf,siaddr,IP_ADDR_LEN);
525 ebuf_get_bytes(buf,giaddr,IP_ADDR_LEN);
527 ebuf_skip(buf,16); /* hardware address */
528 hostname = (char *)ebuf_ptr(buf);
529 ebuf_skip(buf,64);
530 bootfile = (char *)ebuf_ptr(buf);
532 ebuf_skip(buf,128);
534 #ifdef _DEBUG_
535 xprintf("Client IP: %d.%d.%d.%d\n",ciaddr[0],ciaddr[1],ciaddr[2],ciaddr[3]);
536 xprintf("Your IP: %d.%d.%d.%d\n",yiaddr[0],yiaddr[1],yiaddr[2],yiaddr[3]);
537 xprintf("Server IP: %d.%d.%d.%d\n",siaddr[0],siaddr[1],siaddr[2],siaddr[3]);
538 xprintf("Gateway IP: %d.%d.%d.%d\n",giaddr[0],giaddr[1],giaddr[2],giaddr[3]);
539 xprintf("hostname: %s\n",hostname);
540 xprintf("boot file: %s\n",bootfile);
541 #endif
543 memcpy(reply->dr_ipaddr,yiaddr,IP_ADDR_LEN);
544 memcpy(reply->dr_gateway,giaddr,IP_ADDR_LEN);
545 memcpy(reply->dr_bootserver,siaddr,IP_ADDR_LEN);
546 if (*hostname) reply->dr_hostname = strdup(hostname);
547 if (*bootfile) reply->dr_bootfile = strdup(bootfile);
550 * Test for options - look for magic number
553 ebuf_get_u32_be(buf,tmpd);
555 memcpy(reply->dr_dhcpserver,buf->eb_usrptr,IP_ADDR_LEN);
557 if (tmpd == DHCP_MAGIC_NUMBER) {
558 uint8_t tag;
559 uint8_t len;
561 while (buf->eb_length > 0) {
562 ebuf_get_u8(buf,tag);
563 if (tag == DHCP_TAG_END) break;
564 ebuf_get_u8(buf,len);
565 ebuf_get_bytes(buf,junk,len);
567 #ifdef _DEBUG_
568 dhcp_dumptag(tag,len,junk);
569 #endif
571 switch (tag) {
572 case DHCP_TAG_FUNCTION:
573 fcode = (uint8_t) junk[0];
574 break;
575 case DHCP_TAG_NETMASK:
576 memcpy(reply->dr_netmask,junk,IP_ADDR_LEN);
577 break;
578 case DHCP_TAG_GATEWAY:
579 memcpy(reply->dr_gateway,junk,IP_ADDR_LEN);
580 break;
581 case DHCP_TAG_NAMESERVER:
582 memcpy(reply->dr_nameserver,junk,IP_ADDR_LEN);
583 break;
584 case DHCP_TAG_DOMAINNAME:
585 junk[len] = 0;
586 if (len) reply->dr_domainname = strdup(junk);
587 break;
588 case DHCP_TAG_SWAPSERVER:
589 junk[len] = 0;
590 if (len) reply->dr_swapserver = strdup(junk);
591 break;
592 case DHCP_TAG_SERVERIDENT:
593 if (len == IP_ADDR_LEN) {
594 memcpy(reply->dr_dhcpserver,junk,len);
596 break;
597 case DHCP_TAG_ROOTPATH:
598 junk[len] = 0;
599 if (len) reply->dr_rootpath = strdup(junk);
600 break;
601 case DHCP_TAG_SCRIPT:
602 junk[len] = 0;
603 if (len) reply->dr_script = strdup(junk);
604 break;
605 case DHCP_TAG_OPTIONS:
606 junk[len] = 0;
607 if (len) reply->dr_options = strdup(junk);
608 break;
613 if (fcode != expfcode) {
614 goto drop;
617 udp_free(buf);
618 nres++;
619 break;
621 drop:
622 udp_free(buf);
625 if (nres > 0) return 0;
626 else return CFE_ERR_TIMEOUT;
630 /* *********************************************************************
631 * dhcp_do_dhcpdiscover(s,hwaddr,reply)
633 * Request an IP address from the DHCP server. On success, the
634 * dhcpreply_t structure will be filled in
636 * Input parameters:
637 * s - udp socket
638 * hwaddr - our hardware address
639 * reply - pointer to reply buffer.
641 * Return value:
642 * 0 if a response was received
643 * else error code
644 ********************************************************************* */
646 static int dhcp_do_dhcpdiscover(int s,uint8_t *hwaddr,dhcpreply_t *reply)
648 ebuf_t *buf;
649 uint32_t id;
650 uint8_t ipaddr[IP_ADDR_LEN];
651 int res;
654 * Packet ID is the current time
657 id = (uint32_t)cfe_ticks;
660 * Build the DISCOVER request
663 res = dhcp_build_discover(hwaddr,id,&buf);
664 if (res != 0) return res;
667 * Send the packet to the IP broadcast (255.255.255.255)
670 ipaddr[0] = 0xFF; ipaddr[1] = 0xFF; ipaddr[2] = 0xFF; ipaddr[3] = 0xFF;
671 udp_send(s,buf,ipaddr);
674 * Wait for a reply
677 res = dhcp_wait_reply(s,id,reply,DHCP_FUNCTION_OFFER);
679 return res;
683 /* *********************************************************************
684 * dhcp_do_dhcprequest(s,hwaddr,reply,discover_reply)
686 * Request an IP address from the DHCP server. On success, the
687 * dhcpreply_t structure will be filled in
689 * Input parameters:
690 * s - udp socket
691 * hwaddr - our hardware address
692 * reply - pointer to reply buffer.
693 * discover_reply - pointer to previously received DISCOVER data
695 * Return value:
696 * 0 if a response was received
697 * else error code
698 ********************************************************************* */
700 static int dhcp_do_dhcprequest(int s,uint8_t *hwaddr,
701 dhcpreply_t *reply,
702 dhcpreply_t *discover_reply)
704 ebuf_t *buf;
705 uint32_t id;
706 uint8_t ipaddr[IP_ADDR_LEN];
707 int res;
710 * Packet ID is the current time
713 id = (uint32_t)cfe_ticks;
716 * Build the DHCP REQUEST request
719 res = dhcp_build_request(hwaddr,
721 discover_reply->dr_dhcpserver,
722 discover_reply->dr_ipaddr,
723 &buf);
725 if (res != 0) return res;
728 * Send the packet to the IP broadcast (255.255.255.255)
731 ipaddr[0] = 0xFF; ipaddr[1] = 0xFF; ipaddr[2] = 0xFF; ipaddr[3] = 0xFF;
732 udp_send(s,buf,ipaddr);
735 * Wait for a reply
738 res = dhcp_wait_reply(s,id,reply,DHCP_FUNCTION_ACK);
740 return res;
744 /* *********************************************************************
745 * dhcp_bootrequest(reply)
747 * Request an IP address from the DHCP server. On success, the
748 * dhcpreply_t structure will be allocated.
750 * Input parameters:
751 * reply - pointer to pointer to reply.
753 * Return value:
754 * 0 if no responses received
755 * >0 for some responses received
756 * else error code
757 ********************************************************************* */
759 int dhcp_bootrequest(dhcpreply_t **rep)
761 uint8_t *hwaddr;
762 int s;
763 dhcpreply_t *discover_reply;
764 dhcpreply_t *request_reply;
765 int nres = 0;
766 int retries;
767 uint32_t id;
769 id = (uint32_t) cfe_ticks;
772 * Start with empty reply buffers. Since we use a portion of the
773 * discover reply in the request, we'll keep two of them.
776 discover_reply = KMALLOC(sizeof(dhcpreply_t),0);
777 if (discover_reply == NULL) {
778 return CFE_ERR_NOMEM;
780 memset(discover_reply,0,sizeof(dhcpreply_t));
782 request_reply = KMALLOC(sizeof(dhcpreply_t),0);
783 if (request_reply == NULL) {
784 KFREE(discover_reply);
785 return CFE_ERR_NOMEM;
787 memset(request_reply,0,sizeof(dhcpreply_t));
791 * Get our hw addr
794 hwaddr = net_getparam(NET_HWADDR);
795 if (!hwaddr) {
796 KFREE(discover_reply);
797 KFREE(request_reply);
798 return CFE_ERR_NETDOWN;
802 * Open UDP port
805 s = udp_socket(UDP_PORT_BOOTPS);
806 if (s < 0) {
807 KFREE(discover_reply);
808 KFREE(request_reply);
809 return CFE_ERR_NOHANDLES;
812 udp_bind(s,UDP_PORT_BOOTPC);
815 * Do the boot request. Start by sending the OFFER message
818 nres = CFE_ERR_TIMEOUT;
819 for (retries = 0; retries < DHCP_NUM_RETRIES; retries++) {
820 nres = dhcp_do_dhcpdiscover(s,hwaddr,discover_reply);
821 if (nres == 0) break;
822 if (nres == CFE_ERR_TIMEOUT) continue;
823 break;
827 * If someone sent us a response, send the REQUEST message
828 * to get a lease.
831 if (nres == 0) {
834 * Now, send the REQUEST message and get a response.
837 for (retries = 0; retries < DHCP_NUM_RETRIES; retries++) {
838 nres = dhcp_do_dhcprequest(s,hwaddr,
839 request_reply,
840 discover_reply);
841 if (nres == 0) break;
842 if (nres == CFE_ERR_TIMEOUT) continue;
843 break;
848 * All done with the discover reply.
851 dhcp_free_reply(discover_reply);
854 * All done with UDP
857 udp_close(s);
860 * Return the reply info.
863 if (nres == 0) {
864 *rep = request_reply;
866 else {
867 *rep = NULL;
868 dhcp_free_reply(request_reply);
871 return nres;
873 #endif /* CFG_DHCP */