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
20 #define CONFIG_BOOTP_RANDOM_DELAY
21 #define BOOTP_VENDOR_MAGIC 0x63825363 /* RFC1048 Magic Cookie */
23 #if (CONFIG_COMMANDS & CFG_CMD_NET)
25 DECLARE_GLOBAL_DATA_PTR;
27 #define TIMEOUT 5 /* Seconds before trying BOOTP again */
29 #ifndef CONFIG_NET_RETRY_COUNT
30 #define TIMEOUT_COUNT 5 /* # of timeouts before giving up */
32 #define TIMEOUT_COUNT (CONFIG_NET_RETRY_COUNT)
35 #define PORT_BOOTPS 67 /* BOOTP server UDP port */
36 #define PORT_BOOTPC 68 /* BOOTP client UDP port */
38 #ifndef CONFIG_DHCP_MIN_EXT_LEN /* minimal length of extension list */
39 #define CONFIG_DHCP_MIN_EXT_LEN 64
45 #ifdef CONFIG_BOOTP_RANDOM_DELAY
49 #if (CONFIG_COMMANDS & CFG_CMD_DHCP)
50 dhcp_state_t dhcp_state = INIT;
51 unsigned long dhcp_leasetime = 0;
52 IPaddr_t NetDHCPServerIP = 0;
53 static void DhcpHandler(uchar * pkt, unsigned dest, unsigned src, unsigned len);
57 static char *dhcpmsg2str(int type){
60 return("DHCPDISCOVER");
66 return("DHCPREQUEST");
69 return("DHCPDECLINE");
78 return("DHCPRELEASE");
81 return("UNKNOWN/INVALID MSG TYPE");
87 #if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_VENDOREX)
88 extern u8 *dhcp_vendorex_prep (u8 *e); /*rtn new e after add own opts. */
89 extern u8 *dhcp_vendorex_proc (u8 *e); /*rtn next e if mine,else NULL */
92 #endif /* CFG_CMD_DHCP */
94 static int BootpCheckPkt(uchar *pkt, unsigned dest, unsigned src, unsigned len){
95 Bootp_t *bp = (Bootp_t *) pkt;
98 if(dest != PORT_BOOTPC || src != PORT_BOOTPS){
100 } else if(len < sizeof (Bootp_t) - OPT_SIZE){
102 } else if(bp->bp_op != OP_BOOTREQUEST &&
103 bp->bp_op != OP_BOOTREPLY &&
104 bp->bp_op != DHCP_OFFER &&
105 bp->bp_op != DHCP_ACK &&
106 bp->bp_op != DHCP_NAK){
108 } else if(bp->bp_htype != HWT_ETHER){
110 } else if(bp->bp_hlen != HWL_ETHER){
112 } else if(NetReadLong((ulong*)&bp->bp_id) != BootpID){
117 printf("Filtering pkt = %d\n", retval);
124 * Copy parameters of interest from BOOTP_REPLY/DHCP_OFFER packet
126 static void BootpCopyNetParams(Bootp_t *bp){
129 NetCopyIP(&NetOurIP, &bp->bp_yiaddr);
130 NetCopyIP(&tmp_ip, &bp->bp_siaddr);
133 NetCopyIP(&NetServerIP, &bp->bp_siaddr);
136 memcpy(NetServerEther, ((Ethernet_t *)NetRxPkt)->et_src, 6);
138 if(strlen(bp->bp_file) > 0){
139 copy_filename(BootFile, bp->bp_file, sizeof(BootFile));
143 printf("Bootfile: %s\n", BootFile);
147 * Propagate to environment:
148 * don't delete exising entry when BOOTP / DHCP reply does
149 * not contain a new value
152 setenv("bootfile", BootFile);
156 static int truncate_sz(const char *name, int maxlen, int curlen){
157 if(curlen >= maxlen){
158 printf("** Warning: %s is too long (%d - max: %d) - truncated\n", name, curlen, maxlen);
165 #if !(CONFIG_COMMANDS & CFG_CMD_DHCP)
167 static void BootpVendorFieldProcess(u8 * ext){
168 int size = *(ext + 1);
173 /* Fixed length fields */
174 case 1: /* Subnet mask */
175 if (NetOurSubnetMask == 0){
176 NetCopyIP(&NetOurSubnetMask, (IPaddr_t *)(ext + 2));
180 case 2: /* Time offset - Not yet supported */
183 /* Variable length fields */
184 case 3: /* Gateways list */
185 if(NetOurGatewayIP == 0){
186 NetCopyIP(&NetOurGatewayIP, (IPaddr_t *)(ext + 2));
190 case 4: /* Time server - Not yet supported */
193 case 5: /* IEN-116 name server - Not yet supported */
197 if(NetOurDNSIP == 0){
198 NetCopyIP(&NetOurDNSIP, (IPaddr_t *)(ext + 2));
200 #if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_DNS2)
201 if((NetOurDNS2IP == 0) && (size > 4)){
202 NetCopyIP(&NetOurDNS2IP, (IPaddr_t *)(ext + 2 + 4));
207 case 7: /* Log server - Not yet supported */
210 case 8: /* Cookie/Quote server - Not yet supported */
213 case 9: /* LPR server - Not yet supported */
216 case 10: /* Impress server - Not yet supported */
219 case 11: /* RPL server - Not yet supported */
222 case 12: /* Host name */
223 if(NetOurHostName[0] == 0){
224 size = truncate_sz("Host Name", sizeof(NetOurHostName), size);
225 memcpy(&NetOurHostName, ext + 2, size);
226 NetOurHostName[size] = 0;
230 case 13: /* Boot file size */
232 NetBootFileSize = ntohs(*(ushort *)(ext + 2));
233 } else if(size == 4){
234 NetBootFileSize = ntohl(*(ulong *)(ext + 2));
238 case 14: /* Merit dump file - Not yet supported */
241 case 15: /* Domain name - Not yet supported */
244 case 16: /* Swap server - Not yet supported */
247 case 17: /* Root path */
248 if(NetOurRootPath[0] == 0){
249 size = truncate_sz("Root Path", sizeof(NetOurRootPath), size);
250 memcpy(&NetOurRootPath, ext + 2, size);
251 NetOurRootPath[size] = 0;
255 case 18: /* Extension path - Not yet supported */
257 * This can be used to send the information of the
258 * vendor area in another file that the client can
263 /* IP host layer fields */
264 case 40: /* NIS Domain name */
265 if(NetOurNISDomain[0] == 0){
266 size = truncate_sz("NIS Domain Name", sizeof(NetOurNISDomain), size);
267 memcpy(&NetOurNISDomain, ext + 2, size);
268 NetOurNISDomain[size] = 0;
272 /* Application layer fields */
273 case 43: /* Vendor specific info - Not yet supported */
275 * Binary information to exchange specific
276 * product information.
279 /* Reserved (custom) fields (128..254) */
284 static void BootpVendorProcess(u8 * ext, int size){
285 u8 *end = ext + size;
287 while((ext < end) && (*ext != 0xff)){
295 BootpVendorFieldProcess(opt);
301 puts("[BOOTP] Received fields: \n");
303 if(NetOurSubnetMask){
304 puts("NetOurSubnetMask : ");
305 print_IPaddr(NetOurSubnetMask);
310 puts("NetOurGatewayIP : ");
311 print_IPaddr(NetOurGatewayIP);
316 printf("NetBootFileSize : %d\n", NetBootFileSize);
319 if(NetOurHostName[0]){
320 printf("NetOurHostName : %s\n", NetOurHostName);
323 if(NetOurRootPath[0]){
324 printf("NetOurRootPath : %s\n", NetOurRootPath);
327 if(NetOurNISDomain[0]){
328 printf("NetOurNISDomain : %s\n", NetOurNISDomain);
332 printf("NetBootFileSize: %d\n", NetBootFileSize);
334 #endif /* DEBUG_BOOTP_EXT */
338 * Handle a BOOTP received packet.
340 static void BootpHandler(uchar * pkt, unsigned dest, unsigned src, unsigned len){
345 printf("got BOOTP packet (src=%d, dst=%d, len=%d want_len=%d)\n", src, dest, len, sizeof(Bootp_t));
350 if(BootpCheckPkt(pkt, dest, src, len)){ /* Filter out pkts we don't want */
355 * Got a good BOOTP reply. Copy the data into our variables.
357 BootpCopyNetParams(bp); /* Store net parameters from reply */
359 /* Retrieve extended information (we must parse the vendor area) */
360 if(NetReadLong((ulong*)&bp->bp_vend[0]) == htonl(BOOTP_VENDOR_MAGIC)){
361 BootpVendorProcess((uchar *)&bp->bp_vend[4], len);
364 NetSetTimeout(0, (thand_f *)0);
367 printf("Got good BOOTP\n");
370 if((s = getenv("autoload")) != NULL){
373 * Just use BOOTP to configure system;
374 * Do not use TFTP to load the bootfile.
376 NetState = NETLOOP_SUCCESS;
378 #if (CONFIG_COMMANDS & CFG_CMD_NFS)
379 } else if(strcmp(s, "NFS") == 0){
381 * Use NFS to load the bootfile.
391 #endif /* !CFG_CMD_DHCP */
394 * Timeout on BOOTP/DHCP request.
396 static void BootpTimeout(void){
399 if(BootpTry >= TIMEOUT_COUNT){
400 puts("\n## Error: retry count exceeded, starting again!\n\n");
403 NetSetTimeout(TIMEOUT * CFG_HZ, BootpTimeout);
409 * Initialize BOOTP extension fields in the request.
411 #if (CONFIG_COMMANDS & CFG_CMD_DHCP)
412 static int DhcpExtended(u8 * e, int message_type, IPaddr_t ServerID, IPaddr_t RequestedIP){
416 #if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_VENDOREX)
420 #if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_SEND_HOSTNAME)
424 *e++ = 99; /* RFC1048 Magic Cookie */
429 *e++ = 53; /* DHCP Message Type */
433 *e++ = 57; /* Maximum DHCP Message Size */
435 *e++ = (576 - 312 + OPT_SIZE) >> 8;
436 *e++ = (576 - 312 + OPT_SIZE) & 0xff;
439 int tmp = ntohl(ServerID);
441 *e++ = 54; /* ServerID */
450 int tmp = ntohl(RequestedIP);
452 *e++ = 50; /* Requested IP */
460 #if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_SEND_HOSTNAME)
461 if((hostname = getenv("hostname"))){
462 int hostnamelen = strlen (hostname);
464 *e++ = 12; /* Hostname */
467 memcpy(e, hostname, hostnamelen);
472 #if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_VENDOREX)
473 if((x = dhcp_vendorex_prep (e))){
478 *e++ = 55; /* Parameter Request List */
479 cnt = e++; /* Pointer to count of requested items */
482 #if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_SUBNETMASK)
483 *e++ = 1; /* Subnet Mask */
487 #if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_TIMEOFFSET)
492 #if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_GATEWAY)
493 *e++ = 3; /* Router Option */
497 #if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_DNS)
498 *e++ = 6; /* DNS Server(s) */
502 #if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_HOSTNAME)
503 *e++ = 12; /* Hostname */
507 #if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_BOOTFILESIZE)
508 *e++ = 13; /* Boot File Size */
512 #if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_BOOTPATH)
513 *e++ = 17; /* Boot path */
517 #if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_NISDOMAIN)
518 *e++ = 40; /* NIS Domain name request */
522 #if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_NTPSERVER)
526 *e++ = 255; /* End of the list */
528 /* Pad to minimal length */
529 #ifdef CONFIG_DHCP_MIN_EXT_LEN
530 while((e - start) <= CONFIG_DHCP_MIN_EXT_LEN){
538 #else /* CFG_CMD_DHCP */
541 * Warning: no field size check - change CONFIG_BOOTP_MASK at your own risk!
543 static int BootpExtended(u8 * e){
546 *e++ = 99; /* RFC1048 Magic Cookie */
551 #if (CONFIG_COMMANDS & CFG_CMD_DHCP)
552 *e++ = 53; /* DHCP Message Type */
554 *e++ = DHCP_DISCOVER;
556 *e++ = 57; /* Maximum DHCP Message Size */
558 *e++ = (576 - 312 + OPT_SIZE) >> 16;
559 *e++ = (576 - 312 + OPT_SIZE) & 0xff;
560 #endif /* CFG_CMD_DHCP */
562 #if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_SUBNETMASK)
563 *e++ = 1; /* Subnet mask request */
568 #if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_GATEWAY)
569 *e++ = 3; /* Default gateway request */
574 #if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_DNS)
575 *e++ = 6; /* Domain Name Server */
580 #if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_HOSTNAME)
581 *e++ = 12; /* Host name request */
586 #if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_BOOTFILESIZE)
587 *e++ = 13; /* Boot file size */
592 #if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_BOOTPATH)
593 *e++ = 17; /* Boot path */
598 #if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_NISDOMAIN)
599 *e++ = 40; /* NIS Domain name request */
604 *e++ = 255; /* End of the list */
608 #endif /* CFG_CMD_DHCP */
610 void BootpRequest(void){
612 volatile uchar *pkt, *iphdr;
614 int ext_len, pktlen, iplen;
616 #if (CONFIG_COMMANDS & CFG_CMD_DHCP)
620 #ifdef CONFIG_BOOTP_RANDOM_DELAY /* Random BOOTP delay */
621 unsigned char bi_enetaddr[6];
623 ulong tst1, tst2, sum, m_mask, m_value = 0;
627 memcpy(bi_enetaddr, NetOurEther, 6);
630 puts("BootpRequest => Our Mac: ");
632 for(reg = 0; reg < 6; reg++){
633 printf("%x%c", bi_enetaddr[reg], reg == 5 ? '\n' : ':');
637 /* Mac-Manipulation 2 get seed1 */
641 for(reg = 2; reg < 6; reg++){
643 tst1 = tst1 | bi_enetaddr[reg];
646 for(reg = 0; reg < 2; reg++){
647 tst2 = tst2 | bi_enetaddr[reg];
656 for(reg = 1;reg <= 32; reg++){
657 m_value |= (m_mask & seed1);
659 m_value = m_value << 1;
666 /* Random Number Generator */
667 for(reg = 0; reg <= 0; reg++){
670 if(sum < seed1 || sum < seed2){
677 if(BootpTry<=2){ /* Start with max 1024 * 1ms */
678 sum = sum >> (22-BootpTry);
679 } else { /*After 3rd BOOTP request max 8192 * 1ms */
684 printf("\nRandom delay: %ld ms...\n", sum);
686 for(reg = 0; reg < sum; reg++){
687 udelay(1000); /* Wait 1ms */
689 #endif /* CONFIG_BOOTP_RANDOM_DELAY */
691 printf("Sending DHCP discover... %d\n", ++BootpTry);
694 memset((void*)pkt, 0, PKTSIZE);
696 pkt += NetSetEther(pkt, NetBcastAddr, PROT_IP);
699 * Next line results in incorrect packet size being transmitted, resulting
700 * in errors in some DHCP servers, reporting missing bytes. Size must be
701 * set in packet header after extension length has been determined.
702 * C. Hallinan, DS4.COM, Inc.
704 /* NetSetIP(pkt, 0xFFFFFFFFL, PORT_BOOTPS, PORT_BOOTPC, sizeof (Bootp_t)); */
705 iphdr = pkt; /* We need this later for NetSetIP() */
710 bp->bp_op = OP_BOOTREQUEST;
711 bp->bp_htype = HWT_ETHER;
712 bp->bp_hlen = HWL_ETHER;
714 bp->bp_secs = htons(get_timer(0) / CFG_HZ);
716 NetWriteIP(&bp->bp_ciaddr, 0);
717 NetWriteIP(&bp->bp_yiaddr, 0);
718 NetWriteIP(&bp->bp_siaddr, 0);
719 NetWriteIP(&bp->bp_giaddr, 0);
721 memcpy(bp->bp_chaddr, NetOurEther, 6);
723 copy_filename(bp->bp_file, BootFile, sizeof(bp->bp_file));
725 /* Request additional information from the BOOTP/DHCP server */
726 #if (CONFIG_COMMANDS & CFG_CMD_DHCP)
727 ext_len = DhcpExtended((u8 *)bp->bp_vend, DHCP_DISCOVER, 0, 0);
729 ext_len = BootpExtended((u8 *)bp->bp_vend);
730 #endif /* CFG_CMD_DHCP */
733 * Bootp ID is the lower 4 bytes of our ethernet address
734 * plus the current time in HZ.
736 BootpID = ((ulong)NetOurEther[2] << 24)
737 | ((ulong)NetOurEther[3] << 16)
738 | ((ulong)NetOurEther[4] << 8)
739 | (ulong)NetOurEther[5];
741 BootpID += get_timer(0);
742 BootpID = htonl(BootpID);
744 NetCopyLong(&bp->bp_id, &BootpID);
747 * Calculate proper packet lengths taking into account the
748 * variable size of the options field
750 pktlen = BOOTP_SIZE - sizeof(bp->bp_vend) + ext_len;
751 iplen = BOOTP_HDR_SIZE - sizeof(bp->bp_vend) + ext_len;
753 NetSetIP(iphdr, 0xFFFFFFFFL, PORT_BOOTPS, PORT_BOOTPC, iplen);
754 NetSetTimeout(SELECT_TIMEOUT * CFG_HZ, BootpTimeout);
756 #if (CONFIG_COMMANDS & CFG_CMD_DHCP)
757 dhcp_state = SELECTING;
758 NetSetHandler(DhcpHandler);
760 NetSetHandler(BootpHandler);
761 #endif /* CFG_CMD_DHCP */
763 NetSendPacket(NetTxPacket, pktlen);
766 #if (CONFIG_COMMANDS & CFG_CMD_DHCP)
767 static void DhcpOptionsProcess(uchar * popt, Bootp_t *bp){
768 uchar *end = popt + BOOTP_HDR_SIZE;
771 while(popt < end && *popt != 0xff){
776 NetCopyIP(&NetOurSubnetMask, (popt + 2));
779 #if (CONFIG_COMMANDS & CFG_CMD_SNTP) && (CONFIG_BOOTP_MASK & CONFIG_BOOTP_TIMEOFFSET)
780 case 2: /* Time offset */
781 NetCopyLong(&NetTimeOffset, (ulong *)(popt + 2));
782 NetTimeOffset = ntohl(NetTimeOffset);
787 NetCopyIP(&NetOurGatewayIP, (popt + 2));
791 NetCopyIP(&NetOurDNSIP, (popt + 2));
792 #if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_DNS2)
794 NetCopyIP(&NetOurDNS2IP, (popt + 2 + 4));
800 size = truncate_sz("Host Name", sizeof(NetOurHostName), oplen);
801 memcpy(&NetOurHostName, popt + 2, size);
802 NetOurHostName[size] = 0;
805 case 15: /* Ignore Domain Name Option */
809 size = truncate_sz("Root Path", sizeof(NetOurRootPath), oplen);
810 memcpy(&NetOurRootPath, popt + 2, size);
811 NetOurRootPath[size] = 0;
814 case 28: /* Ignore Broadcast Address Option */
817 #if (CONFIG_COMMANDS & CFG_CMD_SNTP) && (CONFIG_BOOTP_MASK & CONFIG_BOOTP_NTPSERVER)
818 case 42: /* NTP server IP */
819 NetCopyIP(&NetNtpServerIP, (popt + 2));
824 NetCopyLong(&dhcp_leasetime, (ulong *)(popt + 2));
827 case 53: /* Ignore Message Type Option */
831 NetCopyIP(&NetDHCPServerIP, (popt + 2));
834 case 58: /* Ignore Renewal Time Option */
837 case 59: /* Ignore Rebinding Time Option */
840 case 66: /* Ignore TFTP server name */
843 case 67: /* vendor opt bootfile */
845 * I can't use dhcp_vendorex_proc here because I need
846 * to write into the bootp packet - even then I had to
847 * pass the bootp packet pointer into here as the
850 size = truncate_sz("Opt Boot File", sizeof(bp->bp_file), oplen);
852 if(bp->bp_file[0] == '\0' && size > 0){
854 * only use vendor boot file if we didn't
855 * receive a boot file in the main non-vendor
856 * part of the packet - god only knows why
857 * some vendors chose not to use this perfectly
858 * good spot to store the boot file (join on
859 * Tru64 Unix) it seems mind bogglingly crazy
862 printf("** Warning: using vendor optional boot file\n");
863 memcpy(bp->bp_file, popt + 2, size);
864 bp->bp_file[size] = '\0';
869 #if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_VENDOREX)
870 if(dhcp_vendorex_proc(popt)){
874 printf("** Warning: unhandled DHCP option in OFFER/ACK: %d\n", *popt);
878 popt += oplen + 2; /* Process next option */
882 static int DhcpMessageType(unsigned char *popt){
883 if(NetReadLong((ulong*)popt) != htonl(BOOTP_VENDOR_MAGIC)){
889 while(*popt != 0xff){
890 if(*popt == 53){ /* DHCP Message Type */
894 popt += *(popt + 1) + 2; /* Scan through all options */
900 static void DhcpSendRequestPkt(Bootp_t *bp_offer){
902 volatile uchar *pkt, *iphdr;
904 int pktlen, iplen, extlen;
908 puts("DhcpSendRequestPkt: Sending DHCPREQUEST\n");
912 memset((void*)pkt, 0, PKTSIZE);
914 pkt += NetSetEther(pkt, NetBcastAddr, PROT_IP);
916 iphdr = pkt; /* We'll need this later to set proper pkt size */
921 bp->bp_op = OP_BOOTREQUEST;
922 bp->bp_htype = HWT_ETHER;
923 bp->bp_hlen = HWL_ETHER;
925 bp->bp_secs = htons(get_timer(0) / CFG_HZ);
927 NetCopyIP(&bp->bp_ciaddr, &bp_offer->bp_ciaddr); /* both in network byte order */
928 NetCopyIP(&bp->bp_yiaddr, &bp_offer->bp_yiaddr);
929 NetCopyIP(&bp->bp_siaddr, &bp_offer->bp_siaddr);
930 NetCopyIP(&bp->bp_giaddr, &bp_offer->bp_giaddr);
932 memcpy(bp->bp_chaddr, NetOurEther, 6);
935 * ID is the id of the OFFER packet
937 NetCopyLong(&bp->bp_id, &bp_offer->bp_id);
940 * Copy options from OFFER packet if present
942 NetCopyIP(&OfferedIP, &bp->bp_yiaddr);
943 extlen = DhcpExtended((u8 *)bp->bp_vend, DHCP_REQUEST, NetDHCPServerIP, OfferedIP);
945 pktlen = BOOTP_SIZE - sizeof(bp->bp_vend) + extlen;
946 iplen = BOOTP_HDR_SIZE - sizeof(bp->bp_vend) + extlen;
948 NetSetIP(iphdr, 0xFFFFFFFFL, PORT_BOOTPS, PORT_BOOTPC, iplen);
951 printf("Transmitting DHCPREQUEST packet: len = %d\n", pktlen);
954 NetSendPacket(NetTxPacket, pktlen);
958 * Handle DHCP received packets.
960 static void DhcpHandler(uchar * pkt, unsigned dest, unsigned src, unsigned len){
962 Bootp_t *bp = (Bootp_t *)pkt;
966 printf("DHCPHandler: got packet: (src=%d, dst=%d, len=%d) state: %d\n", src, dest, len, dhcp_state);
969 if(BootpCheckPkt(pkt, dest, src, len)){ /* Filter out pkts we don't want */
974 printf("DHCPHandler: got DHCP packet: (src=%d, dst=%d, len=%d) state: %d\n", src, dest, len, dhcp_state);
980 * Wait an appropriate time for any potential DHCPOFFER packets
981 * to arrive. Then select one, and generate DHCPREQUEST response.
982 * If filename is in format we recognize, assume it is a valid
983 * OFFER from a server we want.
986 printf("DHCP: state=SELECTING bp_file: \"%s\"\n", bp->bp_file);
989 #ifdef CFG_BOOTFILE_PREFIX
990 if(strncmp(bp->bp_file, CFG_BOOTFILE_PREFIX, strlen(CFG_BOOTFILE_PREFIX)) == 0 ){
991 #endif /* CFG_BOOTFILE_PREFIX */
994 puts("TRANSITIONING TO REQUESTING STATE\n");
997 dhcp_state = REQUESTING;
999 if(NetReadLong((ulong*)&bp->bp_vend[0]) == htonl(BOOTP_VENDOR_MAGIC)){
1000 DhcpOptionsProcess((u8 *)&bp->bp_vend[4], bp);
1003 BootpCopyNetParams(bp); /* Store net params from reply */
1005 NetSetTimeout(TIMEOUT * CFG_HZ, BootpTimeout);
1006 DhcpSendRequestPkt(bp);
1008 #ifdef CFG_BOOTFILE_PREFIX
1010 #endif /* CFG_BOOTFILE_PREFIX */
1017 puts("DHCP State: REQUESTING\n");
1020 if(DhcpMessageType((u8 *)bp->bp_vend) == DHCP_ACK ){
1023 if(NetReadLong((ulong*)&bp->bp_vend[0]) == htonl(BOOTP_VENDOR_MAGIC)){
1024 DhcpOptionsProcess((u8 *)&bp->bp_vend[4], bp);
1027 BootpCopyNetParams(bp); /* Store net params from reply */
1031 puts("\nReceived DHCP offer!\n New IP: ");
1032 print_IPaddr(NetOurIP);
1035 // save our new IP to env
1037 ip_to_string(NetOurIP, tmp);
1038 setenv("ipaddr", tmp);
1041 puts(" Server IP: ");
1042 print_IPaddr(NetServerIP);
1045 // save new server IP to env
1047 ip_to_string(NetServerIP, tmp);
1048 setenv("serverip", tmp);
1051 /* Obey the 'autoload' setting */
1052 if((s = getenv("autoload")) != NULL){
1055 * Just use BOOTP to configure system;
1056 * Do not use TFTP to load the bootfile.
1058 NetState = NETLOOP_SUCCESS;
1060 #if (CONFIG_COMMANDS & CFG_CMD_NFS)
1061 } else if(strcmp(s, "NFS") == 0){
1063 * Use NFS to load the bootfile.
1077 puts("## Error: DHCP in INVALID STATE\n");
1083 void DhcpRequest(void){
1086 #endif /* CFG_CMD_DHCP */
1088 #endif /* CFG_CMD_NET */