1 /* *********************************************************************
2 * Broadcom Common Firmware Environment (CFE)
4 * DHCP Client File: net_dhcp.c
6 * This module contains a DHCP client.
8 * Author: Mitch Lichtenberg (mpl@broadcom.com)
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"
56 #include "cfe_devfuncs.h"
57 #include "cfe_ioctl.h"
58 #include "cfe_timer.h"
59 #include "cfe_error.h"
62 #include "net_ether.h"
65 #include "bsp_config.h"
71 /* *********************************************************************
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
116 /* *********************************************************************
117 * dhcp_set_envvars(reply)
119 * Using the supplied DHCP reply data, set environment variables
120 * to contain data from the reply.
127 ********************************************************************* */
129 void dhcp_set_envvars(dhcpreply_t
*reply
)
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
164 * len - length of data
169 ********************************************************************* */
172 static void dhcp_dumptag(uint8_t tag
,uint8_t len
,uint8_t *buf
)
179 case DHCP_TAG_FUNCTION
:
180 xprintf("DHCP Function: %d\n",buf
[0]);
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
);
189 case DHCP_TAG_SERVERIDENT
:
190 xprintf("DHCP Server ID: %d.%d.%d.%d\n",
191 buf
[0],buf
[1],buf
[2],buf
[3]);
193 case DHCP_TAG_NETMASK
:
194 xprintf("Netmask: %d.%d.%d.%d\n",buf
[0],buf
[1],buf
[2],buf
[3]);
196 case DHCP_TAG_DOMAINNAME
:
198 xprintf("Domain: %s\n",buf
);
200 case DHCP_TAG_GATEWAY
:
201 xprintf("Gateway: %d.%d.%d.%d\n",buf
[0],buf
[1],buf
[2],buf
[3]);
203 case DHCP_TAG_NAMESERVER
:
204 xprintf("Nameserver: %d.%d.%d.%d\n",buf
[0],buf
[1],buf
[2],buf
[3]);
206 case DHCP_TAG_SWAPSERVER
:
208 xprintf("Swapserver: %s\n",buf
);
210 case DHCP_TAG_ROOTPATH
:
212 xprintf("Rootpath: %s\n",buf
);
214 case DHCP_TAG_SCRIPT
:
216 xprintf("CFE Script: %s\n",buf
);
218 case DHCP_TAG_OPTIONS
:
220 xprintf("CFE Boot Options: %s\n",buf
);
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
]);
234 /* *********************************************************************
235 * dhcp_free_reply(reply)
237 * Free memory associated with a DHCP reply.
240 * reply - pointer to DHCP reply
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
);
258 /* *********************************************************************
259 * dhcp_build_discover()
261 * Build a DHCP DISCOVER packet
264 * hwaddr - our hardware address
265 * idptr - pointer to int to receive the DHCP packet ID
266 * serveraddr - pointer to server address (REQUEST) or
268 * ebufptr - receives pointer to ebuf
271 * 0 if ok, else error code
272 ********************************************************************* */
274 static int dhcp_build_discover(uint8_t *hwaddr
,
278 uint8_t ipaddr
[IP_ADDR_LEN
];
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
));
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 */
344 /* *********************************************************************
345 * dhcp_build_request()
347 * Build a DHCP DISCOVER or REQUEST packet
350 * hwaddr - our hardware address
351 * idptr - pointer to int to receive the DHCP packet ID
352 * serveraddr - pointer to server address (REQUEST) or
354 * ebufptr - receives pointer to ebuf
357 * 0 if ok, else error code
358 ********************************************************************* */
360 static int dhcp_build_request(uint8_t *hwaddr
,
366 uint8_t ipaddr
[IP_ADDR_LEN
];
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
));
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 */
449 /* *********************************************************************
450 * dhcp_wait_reply(s,id,reply,serveraddr)
452 * Wait for a reply from the DHCP server
456 * id - ID of request we sent
457 * reply - structure to store results in
458 * expfcode - expected DHCP_FUNCTION tag value
461 * 0 if ok (reply found)
463 ********************************************************************* */
465 static int dhcp_wait_reply(int s
,uint32_t id
,dhcpreply_t
*reply
,int expfcode
)
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
];
482 * Set a timer for the response
485 TIMER_SET(timer
,DHCP_REQ_TIMEOUT
);
491 while (!TIMER_EXPIRED(timer
)) {
497 ebuf_get_u8(buf
,tmpb
);
498 if (tmpb
!= DHCP_OP_BOOTREPLY
) {
502 ebuf_get_u8(buf
,tmpb
);
503 if (tmpb
!= DHCP_HWTYPE_ETHERNET
) {
507 ebuf_get_u8(buf
,tmpb
);
508 if (tmpb
!= ENET_ADDR_LEN
) {
512 ebuf_skip(buf
,1); /* hops */
514 ebuf_get_u32_be(buf
,tmpd
); /* check ID */
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
);
530 bootfile
= (char *)ebuf_ptr(buf
);
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
);
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
) {
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
);
568 dhcp_dumptag(tag
,len
,junk
);
572 case DHCP_TAG_FUNCTION
:
573 fcode
= (uint8_t) junk
[0];
575 case DHCP_TAG_NETMASK
:
576 memcpy(reply
->dr_netmask
,junk
,IP_ADDR_LEN
);
578 case DHCP_TAG_GATEWAY
:
579 memcpy(reply
->dr_gateway
,junk
,IP_ADDR_LEN
);
581 case DHCP_TAG_NAMESERVER
:
582 memcpy(reply
->dr_nameserver
,junk
,IP_ADDR_LEN
);
584 case DHCP_TAG_DOMAINNAME
:
586 if (len
) reply
->dr_domainname
= strdup(junk
);
588 case DHCP_TAG_SWAPSERVER
:
590 if (len
) reply
->dr_swapserver
= strdup(junk
);
592 case DHCP_TAG_SERVERIDENT
:
593 if (len
== IP_ADDR_LEN
) {
594 memcpy(reply
->dr_dhcpserver
,junk
,len
);
597 case DHCP_TAG_ROOTPATH
:
599 if (len
) reply
->dr_rootpath
= strdup(junk
);
601 case DHCP_TAG_SCRIPT
:
603 if (len
) reply
->dr_script
= strdup(junk
);
605 case DHCP_TAG_OPTIONS
:
607 if (len
) reply
->dr_options
= strdup(junk
);
613 if (fcode
!= expfcode
) {
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
638 * hwaddr - our hardware address
639 * reply - pointer to reply buffer.
642 * 0 if a response was received
644 ********************************************************************* */
646 static int dhcp_do_dhcpdiscover(int s
,uint8_t *hwaddr
,dhcpreply_t
*reply
)
650 uint8_t ipaddr
[IP_ADDR_LEN
];
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
);
677 res
= dhcp_wait_reply(s
,id
,reply
,DHCP_FUNCTION_OFFER
);
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
691 * hwaddr - our hardware address
692 * reply - pointer to reply buffer.
693 * discover_reply - pointer to previously received DISCOVER data
696 * 0 if a response was received
698 ********************************************************************* */
700 static int dhcp_do_dhcprequest(int s
,uint8_t *hwaddr
,
702 dhcpreply_t
*discover_reply
)
706 uint8_t ipaddr
[IP_ADDR_LEN
];
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
,
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
);
738 res
= dhcp_wait_reply(s
,id
,reply
,DHCP_FUNCTION_ACK
);
744 /* *********************************************************************
745 * dhcp_bootrequest(reply)
747 * Request an IP address from the DHCP server. On success, the
748 * dhcpreply_t structure will be allocated.
751 * reply - pointer to pointer to reply.
754 * 0 if no responses received
755 * >0 for some responses received
757 ********************************************************************* */
759 int dhcp_bootrequest(dhcpreply_t
**rep
)
763 dhcpreply_t
*discover_reply
;
764 dhcpreply_t
*request_reply
;
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
));
794 hwaddr
= net_getparam(NET_HWADDR
);
796 KFREE(discover_reply
);
797 KFREE(request_reply
);
798 return CFE_ERR_NETDOWN
;
805 s
= udp_socket(UDP_PORT_BOOTPS
);
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;
827 * If someone sent us a response, send the REQUEST message
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
,
841 if (nres
== 0) break;
842 if (nres
== CFE_ERR_TIMEOUT
) continue;
848 * All done with the discover reply.
851 dhcp_free_reply(discover_reply
);
860 * Return the reply info.
864 *rep
= request_reply
;
868 dhcp_free_reply(request_reply
);
873 #endif /* CFG_DHCP */