2 * Based on LiMon - BOOTP.
4 * Copyright 1994, 1995, 2000 Neil Russell.
6 * Copyright 2000 Roland Borde
7 * Copyright 2000 Paolo Scaffardi
8 * Copyright 2000-2004 Wolfgang Denk, wd@denx.de
17 #ifdef CONFIG_STATUS_LED
18 #include <status_led.h>
20 #ifdef CONFIG_BOOTP_RANDOM_DELAY
24 #define BOOTP_VENDOR_MAGIC 0x63825363 /* RFC1048 Magic Cookie */
27 * The timeout for the initial BOOTP/DHCP request used to be described by a
28 * counter of fixed-length timeout periods. TIMEOUT_COUNT represents
31 * Now that the timeout periods are variable (exponential backoff and retry)
32 * we convert the timeout count to the absolute time it would have take to
33 * execute that many retries, and keep sending retry packets until that time
36 #ifndef CONFIG_NET_RETRY_COUNT
37 # define TIMEOUT_COUNT 5 /* # of timeouts before giving up */
39 # define TIMEOUT_COUNT (CONFIG_NET_RETRY_COUNT)
41 #define TIMEOUT_MS ((3 + (TIMEOUT_COUNT * 5)) * 1000)
43 #define PORT_BOOTPS 67 /* BOOTP server UDP port */
44 #define PORT_BOOTPC 68 /* BOOTP client UDP port */
46 #ifndef CONFIG_DHCP_MIN_EXT_LEN /* minimal length of extension list */
47 #define CONFIG_DHCP_MIN_EXT_LEN 64
50 #ifndef CONFIG_BOOTP_ID_CACHE_SIZE
51 #define CONFIG_BOOTP_ID_CACHE_SIZE 4
54 ulong bootp_ids
[CONFIG_BOOTP_ID_CACHE_SIZE
];
55 unsigned int bootp_num_ids
;
60 #if defined(CONFIG_CMD_DHCP)
61 static dhcp_state_t dhcp_state
= INIT
;
62 static unsigned long dhcp_leasetime
;
63 static IPaddr_t NetDHCPServerIP
;
64 static void DhcpHandler(uchar
*pkt
, unsigned dest
, IPaddr_t sip
, unsigned src
,
69 static char *dhcpmsg2str(int type
)
72 case 1: return "DHCPDISCOVER"; break;
73 case 2: return "DHCPOFFER"; break;
74 case 3: return "DHCPREQUEST"; break;
75 case 4: return "DHCPDECLINE"; break;
76 case 5: return "DHCPACK"; break;
77 case 6: return "DHCPNACK"; break;
78 case 7: return "DHCPRELEASE"; break;
79 default: return "UNKNOWN/INVALID MSG TYPE"; break;
85 static void bootp_add_id(ulong id
)
87 if (bootp_num_ids
>= ARRAY_SIZE(bootp_ids
)) {
88 size_t size
= sizeof(bootp_ids
) - sizeof(id
);
90 memmove(bootp_ids
, &bootp_ids
[1], size
);
91 bootp_ids
[bootp_num_ids
- 1] = id
;
93 bootp_ids
[bootp_num_ids
] = id
;
98 static bool bootp_match_id(ulong id
)
102 for (i
= 0; i
< bootp_num_ids
; i
++)
103 if (bootp_ids
[i
] == id
)
109 static int BootpCheckPkt(uchar
*pkt
, unsigned dest
, unsigned src
, unsigned len
)
111 struct Bootp_t
*bp
= (struct Bootp_t
*) pkt
;
114 if (dest
!= PORT_BOOTPC
|| src
!= PORT_BOOTPS
)
116 else if (len
< sizeof(struct Bootp_t
) - OPT_FIELD_SIZE
)
118 else if (bp
->bp_op
!= OP_BOOTREQUEST
&&
119 bp
->bp_op
!= OP_BOOTREPLY
&&
120 bp
->bp_op
!= DHCP_OFFER
&&
121 bp
->bp_op
!= DHCP_ACK
&&
122 bp
->bp_op
!= DHCP_NAK
)
124 else if (bp
->bp_htype
!= HWT_ETHER
)
126 else if (bp
->bp_hlen
!= HWL_ETHER
)
128 else if (!bootp_match_id(NetReadLong((ulong
*)&bp
->bp_id
)))
131 debug("Filtering pkt = %d\n", retval
);
137 * Copy parameters of interest from BOOTP_REPLY/DHCP_OFFER packet
139 static void BootpCopyNetParams(struct Bootp_t
*bp
)
141 #if !defined(CONFIG_BOOTP_SERVERIP)
144 NetCopyIP(&tmp_ip
, &bp
->bp_siaddr
);
146 NetCopyIP(&NetServerIP
, &bp
->bp_siaddr
);
147 memcpy(NetServerEther
, ((struct ethernet_hdr
*)NetRxPacket
)->et_src
, 6);
148 if (strlen(bp
->bp_file
) > 0)
149 copy_filename(BootFile
, bp
->bp_file
, sizeof(BootFile
));
151 debug("Bootfile: %s\n", BootFile
);
153 /* Propagate to environment:
154 * don't delete exising entry when BOOTP / DHCP reply does
155 * not contain a new value
158 setenv("bootfile", BootFile
);
160 NetCopyIP(&NetOurIP
, &bp
->bp_yiaddr
);
163 static int truncate_sz(const char *name
, int maxlen
, int curlen
)
165 if (curlen
>= maxlen
) {
166 printf("*** WARNING: %s is too long (%d - max: %d)"
167 " - truncated\n", name
, curlen
, maxlen
);
173 #if !defined(CONFIG_CMD_DHCP)
175 static void BootpVendorFieldProcess(u8
*ext
)
177 int size
= *(ext
+ 1);
179 debug("[BOOTP] Processing extension %d... (%d bytes)\n", *ext
,
185 /* Fixed length fields */
186 case 1: /* Subnet mask */
187 if (NetOurSubnetMask
== 0)
188 NetCopyIP(&NetOurSubnetMask
, (IPaddr_t
*) (ext
+ 2));
190 case 2: /* Time offset - Not yet supported */
192 /* Variable length fields */
193 case 3: /* Gateways list */
194 if (NetOurGatewayIP
== 0)
195 NetCopyIP(&NetOurGatewayIP
, (IPaddr_t
*) (ext
+ 2));
197 case 4: /* Time server - Not yet supported */
199 case 5: /* IEN-116 name server - Not yet supported */
202 if (NetOurDNSIP
== 0)
203 NetCopyIP(&NetOurDNSIP
, (IPaddr_t
*) (ext
+ 2));
204 #if defined(CONFIG_BOOTP_DNS2)
205 if ((NetOurDNS2IP
== 0) && (size
> 4))
206 NetCopyIP(&NetOurDNS2IP
, (IPaddr_t
*) (ext
+ 2 + 4));
209 case 7: /* Log server - Not yet supported */
211 case 8: /* Cookie/Quote server - Not yet supported */
213 case 9: /* LPR server - Not yet supported */
215 case 10: /* Impress server - Not yet supported */
217 case 11: /* RPL server - Not yet supported */
219 case 12: /* Host name */
220 if (NetOurHostName
[0] == 0) {
221 size
= truncate_sz("Host Name",
222 sizeof(NetOurHostName
), size
);
223 memcpy(&NetOurHostName
, ext
+ 2, size
);
224 NetOurHostName
[size
] = 0;
227 case 13: /* Boot file size */
229 NetBootFileSize
= ntohs(*(ushort
*) (ext
+ 2));
231 NetBootFileSize
= ntohl(*(ulong
*) (ext
+ 2));
233 case 14: /* Merit dump file - Not yet supported */
235 case 15: /* Domain name - Not yet supported */
237 case 16: /* Swap server - Not yet supported */
239 case 17: /* Root path */
240 if (NetOurRootPath
[0] == 0) {
241 size
= truncate_sz("Root Path",
242 sizeof(NetOurRootPath
), size
);
243 memcpy(&NetOurRootPath
, ext
+ 2, size
);
244 NetOurRootPath
[size
] = 0;
247 case 18: /* Extension path - Not yet supported */
249 * This can be used to send the information of the
250 * vendor area in another file that the client can
254 /* IP host layer fields */
255 case 40: /* NIS Domain name */
256 if (NetOurNISDomain
[0] == 0) {
257 size
= truncate_sz("NIS Domain Name",
258 sizeof(NetOurNISDomain
), size
);
259 memcpy(&NetOurNISDomain
, ext
+ 2, size
);
260 NetOurNISDomain
[size
] = 0;
263 #if defined(CONFIG_CMD_SNTP) && defined(CONFIG_BOOTP_NTPSERVER)
264 case 42: /* NTP server IP */
265 NetCopyIP(&NetNtpServerIP
, (IPaddr_t
*) (ext
+ 2));
268 /* Application layer fields */
269 case 43: /* Vendor specific info - Not yet supported */
271 * Binary information to exchange specific
272 * product information.
275 /* Reserved (custom) fields (128..254) */
279 static void BootpVendorProcess(u8
*ext
, int size
)
281 u8
*end
= ext
+ size
;
283 debug("[BOOTP] Checking extension (%d bytes)...\n", size
);
285 while ((ext
< end
) && (*ext
!= 0xff)) {
293 BootpVendorFieldProcess(opt
);
297 debug("[BOOTP] Received fields:\n");
298 if (NetOurSubnetMask
)
299 debug("NetOurSubnetMask : %pI4\n", &NetOurSubnetMask
);
302 debug("NetOurGatewayIP : %pI4", &NetOurGatewayIP
);
305 debug("NetBootFileSize : %d\n", NetBootFileSize
);
307 if (NetOurHostName
[0])
308 debug("NetOurHostName : %s\n", NetOurHostName
);
310 if (NetOurRootPath
[0])
311 debug("NetOurRootPath : %s\n", NetOurRootPath
);
313 if (NetOurNISDomain
[0])
314 debug("NetOurNISDomain : %s\n", NetOurNISDomain
);
317 debug("NetBootFileSize: %d\n", NetBootFileSize
);
319 #if defined(CONFIG_CMD_SNTP) && defined(CONFIG_BOOTP_NTPSERVER)
321 debug("NetNtpServerIP : %pI4\n", &NetNtpServerIP
);
326 * Handle a BOOTP received packet.
329 BootpHandler(uchar
*pkt
, unsigned dest
, IPaddr_t sip
, unsigned src
,
334 debug("got BOOTP packet (src=%d, dst=%d, len=%d want_len=%zu)\n",
335 src
, dest
, len
, sizeof(struct Bootp_t
));
337 bp
= (struct Bootp_t
*)pkt
;
339 /* Filter out pkts we don't want */
340 if (BootpCheckPkt(pkt
, dest
, src
, len
))
344 * Got a good BOOTP reply. Copy the data into our variables.
346 #ifdef CONFIG_STATUS_LED
347 status_led_set(STATUS_LED_BOOT
, STATUS_LED_OFF
);
350 BootpCopyNetParams(bp
); /* Store net parameters from reply */
352 /* Retrieve extended information (we must parse the vendor area) */
353 if (NetReadLong((ulong
*)&bp
->bp_vend
[0]) == htonl(BOOTP_VENDOR_MAGIC
))
354 BootpVendorProcess((uchar
*)&bp
->bp_vend
[4], len
);
356 NetSetTimeout(0, (thand_f
*)0);
357 bootstage_mark_name(BOOTSTAGE_ID_BOOTP_STOP
, "bootp_stop");
359 debug("Got good BOOTP\n");
366 * Timeout on BOOTP/DHCP request.
371 ulong time_taken
= get_timer(bootp_start
);
373 if (time_taken
>= TIMEOUT_MS
) {
374 #ifdef CONFIG_BOOTP_MAY_FAIL
375 puts("\nRetry time exceeded\n");
376 net_set_state(NETLOOP_FAIL
);
378 puts("\nRetry time exceeded; starting again\n");
383 if (bootp_timeout
> 2000)
384 bootp_timeout
= 2000;
385 NetSetTimeout(bootp_timeout
, BootpTimeout
);
390 #define put_vci(e, str) \
392 size_t vci_strlen = strlen(str); \
393 *e++ = 60; /* Vendor Class Identifier */ \
395 memcpy(e, str, vci_strlen); \
400 * Initialize BOOTP extension fields in the request.
402 #if defined(CONFIG_CMD_DHCP)
403 static int DhcpExtended(u8
*e
, int message_type
, IPaddr_t ServerID
,
404 IPaddr_t RequestedIP
)
408 #if defined(CONFIG_BOOTP_PXE)
413 #if defined(CONFIG_BOOTP_VENDOREX)
416 #if defined(CONFIG_BOOTP_SEND_HOSTNAME)
420 *e
++ = 99; /* RFC1048 Magic Cookie */
425 *e
++ = 53; /* DHCP Message Type */
429 *e
++ = 57; /* Maximum DHCP Message Size */
431 *e
++ = (576 - 312 + OPT_FIELD_SIZE
) >> 8;
432 *e
++ = (576 - 312 + OPT_FIELD_SIZE
) & 0xff;
435 int tmp
= ntohl(ServerID
);
437 *e
++ = 54; /* ServerID */
446 int tmp
= ntohl(RequestedIP
);
448 *e
++ = 50; /* Requested IP */
455 #if defined(CONFIG_BOOTP_SEND_HOSTNAME)
456 hostname
= getenv("hostname");
458 int hostnamelen
= strlen(hostname
);
460 *e
++ = 12; /* Hostname */
462 memcpy(e
, hostname
, hostnamelen
);
467 #if defined(CONFIG_BOOTP_PXE)
468 clientarch
= CONFIG_BOOTP_PXE_CLIENTARCH
;
469 *e
++ = 93; /* Client System Architecture */
471 *e
++ = (clientarch
>> 8) & 0xff;
472 *e
++ = clientarch
& 0xff;
474 *e
++ = 94; /* Client Network Interface Identifier */
476 *e
++ = 1; /* type field for UNDI */
477 *e
++ = 0; /* major revision */
478 *e
++ = 0; /* minor revision */
480 uuid
= getenv("pxeuuid");
483 if (uuid_str_valid(uuid
)) {
484 *e
++ = 97; /* Client Machine Identifier */
486 *e
++ = 0; /* type 0 - UUID */
488 uuid_str_to_bin(uuid
, e
, UUID_STR_FORMAT_STD
);
491 printf("Invalid pxeuuid: %s\n", uuid
);
496 #ifdef CONFIG_BOOTP_VCI_STRING
497 put_vci(e
, CONFIG_BOOTP_VCI_STRING
);
500 #if defined(CONFIG_BOOTP_VENDOREX)
501 x
= dhcp_vendorex_prep(e
);
506 *e
++ = 55; /* Parameter Request List */
507 cnt
= e
++; /* Pointer to count of requested items */
509 #if defined(CONFIG_BOOTP_SUBNETMASK)
510 *e
++ = 1; /* Subnet Mask */
513 #if defined(CONFIG_BOOTP_TIMEOFFSET)
517 #if defined(CONFIG_BOOTP_GATEWAY)
518 *e
++ = 3; /* Router Option */
521 #if defined(CONFIG_BOOTP_DNS)
522 *e
++ = 6; /* DNS Server(s) */
525 #if defined(CONFIG_BOOTP_HOSTNAME)
526 *e
++ = 12; /* Hostname */
529 #if defined(CONFIG_BOOTP_BOOTFILESIZE)
530 *e
++ = 13; /* Boot File Size */
533 #if defined(CONFIG_BOOTP_BOOTPATH)
534 *e
++ = 17; /* Boot path */
537 #if defined(CONFIG_BOOTP_NISDOMAIN)
538 *e
++ = 40; /* NIS Domain name request */
541 #if defined(CONFIG_BOOTP_NTPSERVER)
545 /* no options, so back up to avoid sending an empty request list */
549 *e
++ = 255; /* End of the list */
551 /* Pad to minimal length */
552 #ifdef CONFIG_DHCP_MIN_EXT_LEN
553 while ((e
- start
) < CONFIG_DHCP_MIN_EXT_LEN
)
562 * Warning: no field size check - change CONFIG_BOOTP_* at your own risk!
564 static int BootpExtended(u8
*e
)
568 *e
++ = 99; /* RFC1048 Magic Cookie */
573 #if defined(CONFIG_CMD_DHCP)
574 *e
++ = 53; /* DHCP Message Type */
576 *e
++ = DHCP_DISCOVER
;
578 *e
++ = 57; /* Maximum DHCP Message Size */
580 *e
++ = (576 - 312 + OPT_FIELD_SIZE
) >> 16;
581 *e
++ = (576 - 312 + OPT_FIELD_SIZE
) & 0xff;
584 #if defined(CONFIG_BOOTP_VCI_STRING) || \
585 (defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_NET_VCI_STRING))
586 #ifdef CONFIG_SPL_BUILD
587 put_vci(e
, CONFIG_SPL_NET_VCI_STRING
);
589 put_vci(e
, CONFIG_BOOTP_VCI_STRING
);
593 #if defined(CONFIG_BOOTP_SUBNETMASK)
594 *e
++ = 1; /* Subnet mask request */
599 #if defined(CONFIG_BOOTP_GATEWAY)
600 *e
++ = 3; /* Default gateway request */
605 #if defined(CONFIG_BOOTP_DNS)
606 *e
++ = 6; /* Domain Name Server */
611 #if defined(CONFIG_BOOTP_HOSTNAME)
612 *e
++ = 12; /* Host name request */
617 #if defined(CONFIG_BOOTP_BOOTFILESIZE)
618 *e
++ = 13; /* Boot file size */
623 #if defined(CONFIG_BOOTP_BOOTPATH)
624 *e
++ = 17; /* Boot path */
629 #if defined(CONFIG_BOOTP_NISDOMAIN)
630 *e
++ = 40; /* NIS Domain name request */
634 #if defined(CONFIG_BOOTP_NTPSERVER)
640 *e
++ = 255; /* End of the list */
646 void BootpReset(void)
650 bootp_start
= get_timer(0);
659 int extlen
, pktlen
, iplen
;
661 #ifdef CONFIG_BOOTP_RANDOM_DELAY
666 bootstage_mark_name(BOOTSTAGE_ID_BOOTP_START
, "bootp_start");
667 #if defined(CONFIG_CMD_DHCP)
671 #ifdef CONFIG_BOOTP_RANDOM_DELAY /* Random BOOTP delay */
675 if (BootpTry
<= 2) /* Start with max 1024 * 1ms */
676 rand_ms
= rand() >> (22 - BootpTry
);
677 else /* After 3rd BOOTP request max 8192 * 1ms */
678 rand_ms
= rand() >> 19;
680 printf("Random delay: %ld ms...\n", rand_ms
);
683 #endif /* CONFIG_BOOTP_RANDOM_DELAY */
685 printf("BOOTP broadcast %d\n", ++BootpTry
);
687 memset((void *)pkt
, 0, PKTSIZE
);
689 eth_hdr_size
= NetSetEther(pkt
, NetBcastAddr
, PROT_IP
);
693 * Next line results in incorrect packet size being transmitted,
694 * resulting in errors in some DHCP servers, reporting missing bytes.
695 * Size must be set in packet header after extension length has been
697 * C. Hallinan, DS4.COM, Inc.
699 /* net_set_udp_header(pkt, 0xFFFFFFFFL, PORT_BOOTPS, PORT_BOOTPC,
700 sizeof (struct Bootp_t)); */
701 iphdr
= pkt
; /* We need this later for net_set_udp_header() */
702 pkt
+= IP_UDP_HDR_SIZE
;
704 bp
= (struct Bootp_t
*)pkt
;
705 bp
->bp_op
= OP_BOOTREQUEST
;
706 bp
->bp_htype
= HWT_ETHER
;
707 bp
->bp_hlen
= HWL_ETHER
;
709 bp
->bp_secs
= htons(get_timer(0) / 1000);
710 NetWriteIP(&bp
->bp_ciaddr
, 0);
711 NetWriteIP(&bp
->bp_yiaddr
, 0);
712 NetWriteIP(&bp
->bp_siaddr
, 0);
713 NetWriteIP(&bp
->bp_giaddr
, 0);
714 memcpy(bp
->bp_chaddr
, NetOurEther
, 6);
715 copy_filename(bp
->bp_file
, BootFile
, sizeof(bp
->bp_file
));
717 /* Request additional information from the BOOTP/DHCP server */
718 #if defined(CONFIG_CMD_DHCP)
719 extlen
= DhcpExtended((u8
*)bp
->bp_vend
, DHCP_DISCOVER
, 0, 0);
721 extlen
= BootpExtended((u8
*)bp
->bp_vend
);
725 * Bootp ID is the lower 4 bytes of our ethernet address
726 * plus the current time in ms.
728 BootpID
= ((ulong
)NetOurEther
[2] << 24)
729 | ((ulong
)NetOurEther
[3] << 16)
730 | ((ulong
)NetOurEther
[4] << 8)
731 | (ulong
)NetOurEther
[5];
732 BootpID
+= get_timer(0);
733 BootpID
= htonl(BootpID
);
734 bootp_add_id(BootpID
);
735 NetCopyLong(&bp
->bp_id
, &BootpID
);
738 * Calculate proper packet lengths taking into account the
739 * variable size of the options field
741 iplen
= BOOTP_HDR_SIZE
- OPT_FIELD_SIZE
+ extlen
;
742 pktlen
= eth_hdr_size
+ IP_UDP_HDR_SIZE
+ iplen
;
743 net_set_udp_header(iphdr
, 0xFFFFFFFFL
, PORT_BOOTPS
, PORT_BOOTPC
, iplen
);
744 NetSetTimeout(bootp_timeout
, BootpTimeout
);
746 #if defined(CONFIG_CMD_DHCP)
747 dhcp_state
= SELECTING
;
748 net_set_udp_handler(DhcpHandler
);
750 net_set_udp_handler(BootpHandler
);
752 NetSendPacket(NetTxPacket
, pktlen
);
755 #if defined(CONFIG_CMD_DHCP)
756 static void DhcpOptionsProcess(uchar
*popt
, struct Bootp_t
*bp
)
758 uchar
*end
= popt
+ BOOTP_HDR_SIZE
;
760 #if defined(CONFIG_CMD_SNTP) && defined(CONFIG_BOOTP_TIMEOFFSET)
764 while (popt
< end
&& *popt
!= 0xff) {
768 NetCopyIP(&NetOurSubnetMask
, (popt
+ 2));
770 #if defined(CONFIG_CMD_SNTP) && defined(CONFIG_BOOTP_TIMEOFFSET)
771 case 2: /* Time offset */
772 to_ptr
= &NetTimeOffset
;
773 NetCopyLong((ulong
*)to_ptr
, (ulong
*)(popt
+ 2));
774 NetTimeOffset
= ntohl(NetTimeOffset
);
778 NetCopyIP(&NetOurGatewayIP
, (popt
+ 2));
781 NetCopyIP(&NetOurDNSIP
, (popt
+ 2));
782 #if defined(CONFIG_BOOTP_DNS2)
784 NetCopyIP(&NetOurDNS2IP
, (popt
+ 2 + 4));
788 size
= truncate_sz("Host Name",
789 sizeof(NetOurHostName
), oplen
);
790 memcpy(&NetOurHostName
, popt
+ 2, size
);
791 NetOurHostName
[size
] = 0;
793 case 15: /* Ignore Domain Name Option */
796 size
= truncate_sz("Root Path",
797 sizeof(NetOurRootPath
), oplen
);
798 memcpy(&NetOurRootPath
, popt
+ 2, size
);
799 NetOurRootPath
[size
] = 0;
801 case 28: /* Ignore Broadcast Address Option */
803 #if defined(CONFIG_CMD_SNTP) && defined(CONFIG_BOOTP_NTPSERVER)
804 case 42: /* NTP server IP */
805 NetCopyIP(&NetNtpServerIP
, (popt
+ 2));
809 NetCopyLong(&dhcp_leasetime
, (ulong
*) (popt
+ 2));
811 case 53: /* Ignore Message Type Option */
814 NetCopyIP(&NetDHCPServerIP
, (popt
+ 2));
816 case 58: /* Ignore Renewal Time Option */
818 case 59: /* Ignore Rebinding Time Option */
820 case 66: /* Ignore TFTP server name */
822 case 67: /* vendor opt bootfile */
824 * I can't use dhcp_vendorex_proc here because I need
825 * to write into the bootp packet - even then I had to
826 * pass the bootp packet pointer into here as the
829 size
= truncate_sz("Opt Boot File",
832 if (bp
->bp_file
[0] == '\0' && size
> 0) {
834 * only use vendor boot file if we didn't
835 * receive a boot file in the main non-vendor
836 * part of the packet - god only knows why
837 * some vendors chose not to use this perfectly
838 * good spot to store the boot file (join on
839 * Tru64 Unix) it seems mind bogglingly crazy
842 printf("*** WARNING: using vendor "
843 "optional boot file\n");
844 memcpy(bp
->bp_file
, popt
+ 2, size
);
845 bp
->bp_file
[size
] = '\0';
849 #if defined(CONFIG_BOOTP_VENDOREX)
850 if (dhcp_vendorex_proc(popt
))
853 printf("*** Unhandled DHCP Option in OFFER/ACK:"
857 popt
+= oplen
+ 2; /* Process next option */
861 static int DhcpMessageType(unsigned char *popt
)
863 if (NetReadLong((ulong
*)popt
) != htonl(BOOTP_VENDOR_MAGIC
))
867 while (*popt
!= 0xff) {
868 if (*popt
== 53) /* DHCP Message Type */
870 popt
+= *(popt
+ 1) + 2; /* Scan through all options */
875 static void DhcpSendRequestPkt(struct Bootp_t
*bp_offer
)
879 int pktlen
, iplen
, extlen
;
883 debug("DhcpSendRequestPkt: Sending DHCPREQUEST\n");
885 memset((void *)pkt
, 0, PKTSIZE
);
887 eth_hdr_size
= NetSetEther(pkt
, NetBcastAddr
, PROT_IP
);
890 iphdr
= pkt
; /* We'll need this later to set proper pkt size */
891 pkt
+= IP_UDP_HDR_SIZE
;
893 bp
= (struct Bootp_t
*)pkt
;
894 bp
->bp_op
= OP_BOOTREQUEST
;
895 bp
->bp_htype
= HWT_ETHER
;
896 bp
->bp_hlen
= HWL_ETHER
;
898 bp
->bp_secs
= htons(get_timer(0) / 1000);
899 /* Do not set the client IP, your IP, or server IP yet, since it
900 * hasn't been ACK'ed by the server yet */
903 * RFC3046 requires Relay Agents to discard packets with
904 * nonzero and offered giaddr
906 NetWriteIP(&bp
->bp_giaddr
, 0);
908 memcpy(bp
->bp_chaddr
, NetOurEther
, 6);
911 * ID is the id of the OFFER packet
914 NetCopyLong(&bp
->bp_id
, &bp_offer
->bp_id
);
917 * Copy options from OFFER packet if present
920 /* Copy offered IP into the parameters request list */
921 NetCopyIP(&OfferedIP
, &bp_offer
->bp_yiaddr
);
922 extlen
= DhcpExtended((u8
*)bp
->bp_vend
, DHCP_REQUEST
,
923 NetDHCPServerIP
, OfferedIP
);
925 iplen
= BOOTP_HDR_SIZE
- OPT_FIELD_SIZE
+ extlen
;
926 pktlen
= eth_hdr_size
+ IP_UDP_HDR_SIZE
+ iplen
;
927 net_set_udp_header(iphdr
, 0xFFFFFFFFL
, PORT_BOOTPS
, PORT_BOOTPC
, iplen
);
929 #ifdef CONFIG_BOOTP_DHCP_REQUEST_DELAY
930 udelay(CONFIG_BOOTP_DHCP_REQUEST_DELAY
);
931 #endif /* CONFIG_BOOTP_DHCP_REQUEST_DELAY */
932 debug("Transmitting DHCPREQUEST packet: len = %d\n", pktlen
);
933 NetSendPacket(NetTxPacket
, pktlen
);
937 * Handle DHCP received packets.
940 DhcpHandler(uchar
*pkt
, unsigned dest
, IPaddr_t sip
, unsigned src
,
943 struct Bootp_t
*bp
= (struct Bootp_t
*)pkt
;
945 debug("DHCPHandler: got packet: (src=%d, dst=%d, len=%d) state: %d\n",
946 src
, dest
, len
, dhcp_state
);
948 /* Filter out pkts we don't want */
949 if (BootpCheckPkt(pkt
, dest
, src
, len
))
952 debug("DHCPHandler: got DHCP packet: (src=%d, dst=%d, len=%d) state:"
953 " %d\n", src
, dest
, len
, dhcp_state
);
955 switch (dhcp_state
) {
958 * Wait an appropriate time for any potential DHCPOFFER packets
959 * to arrive. Then select one, and generate DHCPREQUEST
960 * response. If filename is in format we recognize, assume it
961 * is a valid OFFER from a server we want.
963 debug("DHCP: state=SELECTING bp_file: \"%s\"\n", bp
->bp_file
);
964 #ifdef CONFIG_SYS_BOOTFILE_PREFIX
965 if (strncmp(bp
->bp_file
,
966 CONFIG_SYS_BOOTFILE_PREFIX
,
967 strlen(CONFIG_SYS_BOOTFILE_PREFIX
)) == 0) {
968 #endif /* CONFIG_SYS_BOOTFILE_PREFIX */
970 debug("TRANSITIONING TO REQUESTING STATE\n");
971 dhcp_state
= REQUESTING
;
973 if (NetReadLong((ulong
*)&bp
->bp_vend
[0]) ==
974 htonl(BOOTP_VENDOR_MAGIC
))
975 DhcpOptionsProcess((u8
*)&bp
->bp_vend
[4], bp
);
977 NetSetTimeout(5000, BootpTimeout
);
978 DhcpSendRequestPkt(bp
);
979 #ifdef CONFIG_SYS_BOOTFILE_PREFIX
981 #endif /* CONFIG_SYS_BOOTFILE_PREFIX */
986 debug("DHCP State: REQUESTING\n");
988 if (DhcpMessageType((u8
*)bp
->bp_vend
) == DHCP_ACK
) {
989 if (NetReadLong((ulong
*)&bp
->bp_vend
[0]) ==
990 htonl(BOOTP_VENDOR_MAGIC
))
991 DhcpOptionsProcess((u8
*)&bp
->bp_vend
[4], bp
);
992 /* Store net params from reply */
993 BootpCopyNetParams(bp
);
995 printf("DHCP client bound to address %pI4 (%lu ms)\n",
996 &NetOurIP
, get_timer(bootp_start
));
997 bootstage_mark_name(BOOTSTAGE_ID_BOOTP_STOP
,
1005 /* DHCP client bound to address */
1008 puts("DHCP: INVALID STATE\n");
1014 void DhcpRequest(void)
1018 #endif /* CONFIG_CMD_DHCP */