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
12 #define DEBUG 1 /* general debug */
13 #define DEBUG_BOOTP_EXT 1 /* Debug received vendor fields */
16 #ifdef DEBUG_BOOTP_EXT
17 #define debug_ext(fmt,args...) printf (fmt ,##args)
19 #define debug_ext(fmt,args...)
28 #ifdef CONFIG_STATUS_LED
29 #include <status_led.h>
32 #define BOOTP_VENDOR_MAGIC 0x63825363 /* RFC1048 Magic Cookie */
34 #if (CONFIG_COMMANDS & CFG_CMD_NET)
36 #define TIMEOUT 5 /* Seconds before trying BOOTP again */
37 #ifndef CONFIG_NET_RETRY_COUNT
38 # define TIMEOUT_COUNT 5 /* # of timeouts before giving up */
40 # define TIMEOUT_COUNT (CONFIG_NET_RETRY_COUNT)
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
52 #ifdef CONFIG_BOOTP_RANDOM_DELAY
56 #if (CONFIG_COMMANDS & CFG_CMD_DHCP)
57 dhcp_state_t dhcp_state = INIT;
58 unsigned long dhcp_leasetime = 0;
59 IPaddr_t NetDHCPServerIP = 0;
60 static void DhcpHandler(uchar * pkt, unsigned dest, unsigned src, unsigned len);
64 static char *dhcpmsg2str(int type)
67 case 1: return "DHCPDISCOVER"; break;
68 case 2: return "DHCPOFFER"; break;
69 case 3: return "DHCPREQUEST"; break;
70 case 4: return "DHCPDECLINE"; break;
71 case 5: return "DHCPACK"; break;
72 case 6: return "DHCPNACK"; break;
73 case 7: return "DHCPRELEASE"; break;
74 default: return "UNKNOWN/INVALID MSG TYPE"; break;
79 #if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_VENDOREX)
80 extern u8 *dhcp_vendorex_prep (u8 *e); /*rtn new e after add own opts. */
81 extern u8 *dhcp_vendorex_proc (u8 *e); /*rtn next e if mine,else NULL */
84 #endif /* CFG_CMD_DHCP */
86 static int BootpCheckPkt(uchar *pkt, unsigned dest, unsigned src, unsigned len)
88 Bootp_t *bp = (Bootp_t *) pkt;
91 if (dest != PORT_BOOTPC || src != PORT_BOOTPS)
93 else if (len < sizeof (Bootp_t) - OPT_SIZE)
95 else if (bp->bp_op != OP_BOOTREQUEST &&
96 bp->bp_op != OP_BOOTREPLY &&
97 bp->bp_op != DHCP_OFFER &&
98 bp->bp_op != DHCP_ACK &&
99 bp->bp_op != DHCP_NAK ) {
102 else if (bp->bp_htype != HWT_ETHER)
104 else if (bp->bp_hlen != HWL_ETHER)
106 else if (NetReadLong((ulong*)&bp->bp_id) != BootpID) {
110 debug ("Filtering pkt = %d\n", retval);
116 * Copy parameters of interest from BOOTP_REPLY/DHCP_OFFER packet
118 static void BootpCopyNetParams(Bootp_t *bp)
122 NetCopyIP(&NetOurIP, &bp->bp_yiaddr);
123 NetCopyIP(&tmp_ip, &bp->bp_siaddr);
125 NetCopyIP(&NetServerIP, &bp->bp_siaddr);
126 memcpy (NetServerEther, ((Ethernet_t *)NetRxPkt)->et_src, 6);
127 if (strlen(bp->bp_file) > 0)
128 copy_filename (BootFile, bp->bp_file, sizeof(BootFile));
130 debug ("Bootfile: %s\n", BootFile);
132 /* Propagate to environment:
133 * don't delete exising entry when BOOTP / DHCP reply does
134 * not contain a new value
137 setenv ("bootfile", BootFile);
141 static int truncate_sz (const char *name, int maxlen, int curlen)
143 if (curlen >= maxlen) {
144 printf("*** WARNING: %s is too long (%d - max: %d) - truncated\n",
145 name, curlen, maxlen);
151 #if !(CONFIG_COMMANDS & CFG_CMD_DHCP)
153 static void BootpVendorFieldProcess (u8 * ext)
155 int size = *(ext + 1);
157 debug_ext ("[BOOTP] Processing extension %d... (%d bytes)\n", *ext,
163 /* Fixed length fields */
164 case 1: /* Subnet mask */
165 if (NetOurSubnetMask == 0)
166 NetCopyIP (&NetOurSubnetMask, (IPaddr_t *) (ext + 2));
168 case 2: /* Time offset - Not yet supported */
170 /* Variable length fields */
171 case 3: /* Gateways list */
172 if (NetOurGatewayIP == 0) {
173 NetCopyIP (&NetOurGatewayIP, (IPaddr_t *) (ext + 2));
176 case 4: /* Time server - Not yet supported */
178 case 5: /* IEN-116 name server - Not yet supported */
181 if (NetOurDNSIP == 0) {
182 NetCopyIP (&NetOurDNSIP, (IPaddr_t *) (ext + 2));
184 #if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_DNS2)
185 if ((NetOurDNS2IP == 0) && (size > 4)) {
186 NetCopyIP (&NetOurDNS2IP, (IPaddr_t *) (ext + 2 + 4));
190 case 7: /* Log server - Not yet supported */
192 case 8: /* Cookie/Quote server - Not yet supported */
194 case 9: /* LPR server - Not yet supported */
196 case 10: /* Impress server - Not yet supported */
198 case 11: /* RPL server - Not yet supported */
200 case 12: /* Host name */
201 if (NetOurHostName[0] == 0) {
202 size = truncate_sz ("Host Name", sizeof (NetOurHostName), size);
203 memcpy (&NetOurHostName, ext + 2, size);
204 NetOurHostName[size] = 0;
207 case 13: /* Boot file size */
209 NetBootFileSize = ntohs (*(ushort *) (ext + 2));
211 NetBootFileSize = ntohl (*(ulong *) (ext + 2));
213 case 14: /* Merit dump file - Not yet supported */
215 case 15: /* Domain name - Not yet supported */
217 case 16: /* Swap server - Not yet supported */
219 case 17: /* Root path */
220 if (NetOurRootPath[0] == 0) {
221 size = truncate_sz ("Root Path", sizeof (NetOurRootPath), size);
222 memcpy (&NetOurRootPath, ext + 2, size);
223 NetOurRootPath[size] = 0;
226 case 18: /* Extension path - Not yet supported */
228 * This can be used to send the information of the
229 * vendor area in another file that the client can
233 /* IP host layer fields */
234 case 40: /* NIS Domain name */
235 if (NetOurNISDomain[0] == 0) {
236 size = truncate_sz ("NIS Domain Name", sizeof (NetOurNISDomain), size);
237 memcpy (&NetOurNISDomain, ext + 2, size);
238 NetOurNISDomain[size] = 0;
241 /* Application layer fields */
242 case 43: /* Vendor specific info - Not yet supported */
244 * Binary information to exchange specific
245 * product information.
248 /* Reserved (custom) fields (128..254) */
252 static void BootpVendorProcess (u8 * ext, int size)
254 u8 *end = ext + size;
256 debug_ext ("[BOOTP] Checking extension (%d bytes)...\n", size);
258 while ((ext < end) && (*ext != 0xff)) {
266 BootpVendorFieldProcess (opt);
270 #ifdef DEBUG_BOOTP_EXT
271 puts ("[BOOTP] Received fields: \n");
272 if (NetOurSubnetMask) {
273 puts ("NetOurSubnetMask : ");
274 print_IPaddr (NetOurSubnetMask);
278 if (NetOurGatewayIP) {
279 puts ("NetOurGatewayIP : ");
280 print_IPaddr (NetOurGatewayIP);
284 if (NetBootFileSize) {
285 printf ("NetBootFileSize : %d\n", NetBootFileSize);
288 if (NetOurHostName[0]) {
289 printf ("NetOurHostName : %s\n", NetOurHostName);
292 if (NetOurRootPath[0]) {
293 printf ("NetOurRootPath : %s\n", NetOurRootPath);
296 if (NetOurNISDomain[0]) {
297 printf ("NetOurNISDomain : %s\n", NetOurNISDomain);
300 if (NetBootFileSize) {
301 printf ("NetBootFileSize: %d\n", NetBootFileSize);
303 #endif /* DEBUG_BOOTP_EXT */
306 * Handle a BOOTP received packet.
309 BootpHandler(uchar * pkt, unsigned dest, unsigned src, unsigned len)
314 debug ("got BOOTP packet (src=%d, dst=%d, len=%d want_len=%d)\n",
315 src, dest, len, sizeof (Bootp_t));
319 if (BootpCheckPkt(pkt, dest, src, len)) /* Filter out pkts we don't want */
323 * Got a good BOOTP reply. Copy the data into our variables.
325 #ifdef CONFIG_STATUS_LED
326 status_led_set (STATUS_LED_BOOT, STATUS_LED_OFF);
329 BootpCopyNetParams(bp); /* Store net parameters from reply */
331 /* Retrieve extended information (we must parse the vendor area) */
332 if (NetReadLong((ulong*)&bp->bp_vend[0]) == htonl(BOOTP_VENDOR_MAGIC))
333 BootpVendorProcess((uchar *)&bp->bp_vend[4], len);
335 NetSetTimeout(0, (thand_f *)0);
337 debug ("Got good BOOTP\n");
339 if ((s = getenv("autoload")) != NULL) {
342 * Just use BOOTP to configure system;
343 * Do not use TFTP to load the bootfile.
345 NetState = NETLOOP_SUCCESS;
347 #if (CONFIG_COMMANDS & CFG_CMD_NFS)
348 } else if (strcmp(s, "NFS") == 0) {
350 * Use NFS to load the bootfile.
360 #endif /* !CFG_CMD_DHCP */
363 * Timeout on BOOTP/DHCP request.
368 if (BootpTry >= TIMEOUT_COUNT) {
369 puts ("\nRetry count exceeded; starting again\n");
372 NetSetTimeout (TIMEOUT * CFG_HZ, BootpTimeout);
378 * Initialize BOOTP extension fields in the request.
380 #if (CONFIG_COMMANDS & CFG_CMD_DHCP)
381 static int DhcpExtended (u8 * e, int message_type, IPaddr_t ServerID, IPaddr_t RequestedIP)
386 #if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_VENDOREX)
389 #if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_SEND_HOSTNAME)
393 *e++ = 99; /* RFC1048 Magic Cookie */
398 *e++ = 53; /* DHCP Message Type */
402 *e++ = 57; /* Maximum DHCP Message Size */
404 *e++ = (576 - 312 + OPT_SIZE) >> 8;
405 *e++ = (576 - 312 + OPT_SIZE) & 0xff;
408 int tmp = ntohl (ServerID);
410 *e++ = 54; /* ServerID */
419 int tmp = ntohl (RequestedIP);
421 *e++ = 50; /* Requested IP */
428 #if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_SEND_HOSTNAME)
429 if ((hostname = getenv ("hostname"))) {
430 int hostnamelen = strlen (hostname);
432 *e++ = 12; /* Hostname */
434 memcpy (e, hostname, hostnamelen);
439 #if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_VENDOREX)
440 if ((x = dhcp_vendorex_prep (e)))
444 *e++ = 55; /* Parameter Request List */
445 cnt = e++; /* Pointer to count of requested items */
447 #if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_SUBNETMASK)
448 *e++ = 1; /* Subnet Mask */
451 #if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_TIMEOFFSET)
455 #if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_GATEWAY)
456 *e++ = 3; /* Router Option */
459 #if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_DNS)
460 *e++ = 6; /* DNS Server(s) */
463 #if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_HOSTNAME)
464 *e++ = 12; /* Hostname */
467 #if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_BOOTFILESIZE)
468 *e++ = 13; /* Boot File Size */
471 #if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_BOOTPATH)
472 *e++ = 17; /* Boot path */
475 #if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_NISDOMAIN)
476 *e++ = 40; /* NIS Domain name request */
479 #if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_NTPSERVER)
483 *e++ = 255; /* End of the list */
485 /* Pad to minimal length */
486 #ifdef CONFIG_DHCP_MIN_EXT_LEN
487 while ((e - start) <= CONFIG_DHCP_MIN_EXT_LEN)
494 #else /* CFG_CMD_DHCP */
496 * Warning: no field size check - change CONFIG_BOOTP_MASK at your own risk!
498 static int BootpExtended (u8 * e)
502 *e++ = 99; /* RFC1048 Magic Cookie */
507 #if (CONFIG_COMMANDS & CFG_CMD_DHCP)
508 *e++ = 53; /* DHCP Message Type */
510 *e++ = DHCP_DISCOVER;
512 *e++ = 57; /* Maximum DHCP Message Size */
514 *e++ = (576 - 312 + OPT_SIZE) >> 16;
515 *e++ = (576 - 312 + OPT_SIZE) & 0xff;
516 #endif /* CFG_CMD_DHCP */
518 #if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_SUBNETMASK)
519 *e++ = 1; /* Subnet mask request */
524 #if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_GATEWAY)
525 *e++ = 3; /* Default gateway request */
530 #if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_DNS)
531 *e++ = 6; /* Domain Name Server */
536 #if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_HOSTNAME)
537 *e++ = 12; /* Host name request */
542 #if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_BOOTFILESIZE)
543 *e++ = 13; /* Boot file size */
548 #if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_BOOTPATH)
549 *e++ = 17; /* Boot path */
554 #if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_NISDOMAIN)
555 *e++ = 40; /* NIS Domain name request */
560 *e++ = 255; /* End of the list */
564 #endif /* CFG_CMD_DHCP */
569 volatile uchar *pkt, *iphdr;
571 int ext_len, pktlen, iplen;
573 #if (CONFIG_COMMANDS & CFG_CMD_DHCP)
577 #ifdef CONFIG_BOOTP_RANDOM_DELAY /* Random BOOTP delay */
578 unsigned char bi_enetaddr[6];
582 ulong tst1, tst2, sum, m_mask, m_value = 0;
586 reg = getenv_r ("ethaddr", tmp, sizeof(tmp));
587 s = (reg > 0) ? tmp : NULL;
589 for (reg=0; reg<6; ++reg) {
590 bi_enetaddr[reg] = s ? simple_strtoul(s, &e, 16) : 0;
596 puts ("BootpRequest => Our Mac: ");
597 for (reg=0; reg<6; reg++) {
600 reg==5 ? '\n' : ':');
604 /* Mac-Manipulation 2 get seed1 */
607 for (reg=2; reg<6; reg++) {
609 tst1 = tst1 | bi_enetaddr[reg];
611 for (reg=0; reg<2; reg++) {
612 tst2 = tst2 | bi_enetaddr[reg];
620 for (reg=1;reg<=32;reg++) {
621 m_value |= (m_mask & seed1);
623 m_value = m_value << 1;
629 /* Random Number Generator */
631 for (reg=0;reg<=0;reg++) {
633 if (sum < seed1 || sum < seed2)
638 if (BootpTry<=2) { /* Start with max 1024 * 1ms */
639 sum = sum >> (22-BootpTry);
640 } else { /*After 3rd BOOTP request max 8192 * 1ms */
645 printf ("Random delay: %ld ms...\n", sum);
646 for (reg=0; reg <sum; reg++) {
647 udelay(1000); /*Wait 1ms*/
649 #endif /* CONFIG_BOOTP_RANDOM_DELAY */
651 printf("BOOTP broadcast %d\n", ++BootpTry);
653 memset ((void*)pkt, 0, PKTSIZE);
655 pkt += NetSetEther(pkt, NetBcastAddr, PROT_IP);
658 * Next line results in incorrect packet size being transmitted, resulting
659 * in errors in some DHCP servers, reporting missing bytes. Size must be
660 * set in packet header after extension length has been determined.
661 * C. Hallinan, DS4.COM, Inc.
663 /* NetSetIP(pkt, 0xFFFFFFFFL, PORT_BOOTPS, PORT_BOOTPC, sizeof (Bootp_t)); */
664 iphdr = pkt; /* We need this later for NetSetIP() */
668 bp->bp_op = OP_BOOTREQUEST;
669 bp->bp_htype = HWT_ETHER;
670 bp->bp_hlen = HWL_ETHER;
672 bp->bp_secs = htons(get_timer(0) / CFG_HZ);
673 NetWriteIP(&bp->bp_ciaddr, 0);
674 NetWriteIP(&bp->bp_yiaddr, 0);
675 NetWriteIP(&bp->bp_siaddr, 0);
676 NetWriteIP(&bp->bp_giaddr, 0);
677 memcpy (bp->bp_chaddr, NetOurEther, 6);
678 copy_filename (bp->bp_file, BootFile, sizeof(bp->bp_file));
680 /* Request additional information from the BOOTP/DHCP server */
681 #if (CONFIG_COMMANDS & CFG_CMD_DHCP)
682 ext_len = DhcpExtended((u8 *)bp->bp_vend, DHCP_DISCOVER, 0, 0);
684 ext_len = BootpExtended((u8 *)bp->bp_vend);
685 #endif /* CFG_CMD_DHCP */
688 * Bootp ID is the lower 4 bytes of our ethernet address
689 * plus the current time in HZ.
691 BootpID = ((ulong)NetOurEther[2] << 24)
692 | ((ulong)NetOurEther[3] << 16)
693 | ((ulong)NetOurEther[4] << 8)
694 | (ulong)NetOurEther[5];
695 BootpID += get_timer(0);
696 BootpID = htonl(BootpID);
697 NetCopyLong(&bp->bp_id, &BootpID);
700 * Calculate proper packet lengths taking into account the
701 * variable size of the options field
703 pktlen = BOOTP_SIZE - sizeof(bp->bp_vend) + ext_len;
704 iplen = BOOTP_HDR_SIZE - sizeof(bp->bp_vend) + ext_len;
705 NetSetIP(iphdr, 0xFFFFFFFFL, PORT_BOOTPS, PORT_BOOTPC, iplen);
706 NetSetTimeout(SELECT_TIMEOUT * CFG_HZ, BootpTimeout);
708 #if (CONFIG_COMMANDS & CFG_CMD_DHCP)
709 dhcp_state = SELECTING;
710 NetSetHandler(DhcpHandler);
712 NetSetHandler(BootpHandler);
713 #endif /* CFG_CMD_DHCP */
714 NetSendPacket(NetTxPacket, pktlen);
717 #if (CONFIG_COMMANDS & CFG_CMD_DHCP)
718 static void DhcpOptionsProcess (uchar * popt, Bootp_t *bp)
720 uchar *end = popt + BOOTP_HDR_SIZE;
723 while (popt < end && *popt != 0xff) {
727 NetCopyIP (&NetOurSubnetMask, (popt + 2));
729 #if (CONFIG_COMMANDS & CFG_CMD_SNTP) && (CONFIG_BOOTP_MASK & CONFIG_BOOTP_TIMEOFFSET)
730 case 2: /* Time offset */
731 NetCopyLong (&NetTimeOffset, (ulong *) (popt + 2));
732 NetTimeOffset = ntohl (NetTimeOffset);
736 NetCopyIP (&NetOurGatewayIP, (popt + 2));
739 NetCopyIP (&NetOurDNSIP, (popt + 2));
740 #if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_DNS2)
741 if (*(popt + 1) > 4) {
742 NetCopyIP (&NetOurDNS2IP, (popt + 2 + 4));
747 size = truncate_sz ("Host Name", sizeof (NetOurHostName), oplen);
748 memcpy (&NetOurHostName, popt + 2, size);
749 NetOurHostName[size] = 0;
751 case 15: /* Ignore Domain Name Option */
754 size = truncate_sz ("Root Path", sizeof (NetOurRootPath), oplen);
755 memcpy (&NetOurRootPath, popt + 2, size);
756 NetOurRootPath[size] = 0;
758 #if (CONFIG_COMMANDS & CFG_CMD_SNTP) && (CONFIG_BOOTP_MASK & CONFIG_BOOTP_NTPSERVER)
759 case 42: /* NTP server IP */
760 NetCopyIP (&NetNtpServerIP, (popt + 2));
764 NetCopyLong (&dhcp_leasetime, (ulong *) (popt + 2));
766 case 53: /* Ignore Message Type Option */
769 NetCopyIP (&NetDHCPServerIP, (popt + 2));
771 case 58: /* Ignore Renewal Time Option */
773 case 59: /* Ignore Rebinding Time Option */
775 case 66: /* Ignore TFTP server name */
777 case 67: /* vendor opt bootfile */
779 * I can't use dhcp_vendorex_proc here because I need
780 * to write into the bootp packet - even then I had to
781 * pass the bootp packet pointer into here as the
784 size = truncate_sz ("Opt Boot File",
787 if (bp->bp_file[0] == '\0' && size > 0) {
789 * only use vendor boot file if we didn't
790 * receive a boot file in the main non-vendor
791 * part of the packet - god only knows why
792 * some vendors chose not to use this perfectly
793 * good spot to store the boot file (join on
794 * Tru64 Unix) it seems mind bogglingly crazy
797 printf("*** WARNING: using vendor "
798 "optional boot file\n");
799 memcpy(bp->bp_file, popt + 2, size);
800 bp->bp_file[size] = '\0';
804 #if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_VENDOREX)
805 if (dhcp_vendorex_proc (popt))
808 printf ("*** Unhandled DHCP Option in OFFER/ACK: %d\n", *popt);
811 popt += oplen + 2; /* Process next option */
815 static int DhcpMessageType(unsigned char *popt)
817 if (NetReadLong((ulong*)popt) != htonl(BOOTP_VENDOR_MAGIC))
821 while ( *popt != 0xff ) {
822 if ( *popt == 53 ) /* DHCP Message Type */
824 popt += *(popt + 1) + 2; /* Scan through all options */
829 static void DhcpSendRequestPkt(Bootp_t *bp_offer)
831 volatile uchar *pkt, *iphdr;
833 int pktlen, iplen, extlen;
836 debug ("DhcpSendRequestPkt: Sending DHCPREQUEST\n");
838 memset ((void*)pkt, 0, PKTSIZE);
840 pkt += NetSetEther(pkt, NetBcastAddr, PROT_IP);
842 iphdr = pkt; /* We'll need this later to set proper pkt size */
846 bp->bp_op = OP_BOOTREQUEST;
847 bp->bp_htype = HWT_ETHER;
848 bp->bp_hlen = HWL_ETHER;
850 bp->bp_secs = htons(get_timer(0) / CFG_HZ);
851 NetCopyIP(&bp->bp_ciaddr, &bp_offer->bp_ciaddr); /* both in network byte order */
852 NetCopyIP(&bp->bp_yiaddr, &bp_offer->bp_yiaddr);
853 NetCopyIP(&bp->bp_siaddr, &bp_offer->bp_siaddr);
855 * RFC3046 requires Relay Agents to discard packets with
856 * nonzero and offered giaddr
858 NetWriteIP(&bp->bp_giaddr, 0);
860 memcpy (bp->bp_chaddr, NetOurEther, 6);
863 * ID is the id of the OFFER packet
866 NetCopyLong(&bp->bp_id, &bp_offer->bp_id);
869 * Copy options from OFFER packet if present
871 NetCopyIP(&OfferedIP, &bp->bp_yiaddr);
872 extlen = DhcpExtended((u8 *)bp->bp_vend, DHCP_REQUEST, NetDHCPServerIP, OfferedIP);
874 pktlen = BOOTP_SIZE - sizeof(bp->bp_vend) + extlen;
875 iplen = BOOTP_HDR_SIZE - sizeof(bp->bp_vend) + extlen;
876 NetSetIP(iphdr, 0xFFFFFFFFL, PORT_BOOTPS, PORT_BOOTPC, iplen);
878 debug ("Transmitting DHCPREQUEST packet: len = %d\n", pktlen);
879 NetSendPacket(NetTxPacket, pktlen);
883 * Handle DHCP received packets.
886 DhcpHandler(uchar * pkt, unsigned dest, unsigned src, unsigned len)
888 Bootp_t *bp = (Bootp_t *)pkt;
890 debug ("DHCPHandler: got packet: (src=%d, dst=%d, len=%d) state: %d\n",
891 src, dest, len, dhcp_state);
893 if (BootpCheckPkt(pkt, dest, src, len)) /* Filter out pkts we don't want */
896 debug ("DHCPHandler: got DHCP packet: (src=%d, dst=%d, len=%d) state: %d\n",
897 src, dest, len, dhcp_state);
899 switch (dhcp_state) {
902 * Wait an appropriate time for any potential DHCPOFFER packets
903 * to arrive. Then select one, and generate DHCPREQUEST response.
904 * If filename is in format we recognize, assume it is a valid
905 * OFFER from a server we want.
907 debug ("DHCP: state=SELECTING bp_file: \"%s\"\n", bp->bp_file);
908 #ifdef CFG_BOOTFILE_PREFIX
909 if (strncmp(bp->bp_file,
911 strlen(CFG_BOOTFILE_PREFIX)) == 0 ) {
912 #endif /* CFG_BOOTFILE_PREFIX */
914 debug ("TRANSITIONING TO REQUESTING STATE\n");
915 dhcp_state = REQUESTING;
917 if (NetReadLong((ulong*)&bp->bp_vend[0]) == htonl(BOOTP_VENDOR_MAGIC))
918 DhcpOptionsProcess((u8 *)&bp->bp_vend[4], bp);
920 BootpCopyNetParams(bp); /* Store net params from reply */
922 NetSetTimeout(TIMEOUT * CFG_HZ, BootpTimeout);
923 DhcpSendRequestPkt(bp);
924 #ifdef CFG_BOOTFILE_PREFIX
926 #endif /* CFG_BOOTFILE_PREFIX */
931 debug ("DHCP State: REQUESTING\n");
933 if ( DhcpMessageType((u8 *)bp->bp_vend) == DHCP_ACK ) {
936 if (NetReadLong((ulong*)&bp->bp_vend[0]) == htonl(BOOTP_VENDOR_MAGIC))
937 DhcpOptionsProcess((u8 *)&bp->bp_vend[4], bp);
938 BootpCopyNetParams(bp); /* Store net params from reply */
940 puts ("DHCP client bound to address ");
941 print_IPaddr(NetOurIP);
944 /* Obey the 'autoload' setting */
945 if ((s = getenv("autoload")) != NULL) {
948 * Just use BOOTP to configure system;
949 * Do not use TFTP to load the bootfile.
951 NetState = NETLOOP_SUCCESS;
953 #if (CONFIG_COMMANDS & CFG_CMD_NFS)
954 } else if (strcmp(s, "NFS") == 0) {
956 * Use NFS to load the bootfile.
968 puts ("DHCP: INVALID STATE\n");
974 void DhcpRequest(void)
978 #endif /* CFG_CMD_DHCP */
980 #endif /* CFG_CMD_NET */