ARM: bcm283x: Move BCM283x_BASE to a global variable
[oweals/u-boot.git] / net / bootp.c
1 /*
2  *      Based on LiMon - BOOTP.
3  *
4  *      Copyright 1994, 1995, 2000 Neil Russell.
5  *      (See License)
6  *      Copyright 2000 Roland Borde
7  *      Copyright 2000 Paolo Scaffardi
8  *      Copyright 2000-2004 Wolfgang Denk, wd@denx.de
9  */
10
11 #include <common.h>
12 #include <command.h>
13 #include <env.h>
14 #include <efi_loader.h>
15 #include <net.h>
16 #include <net/tftp.h>
17 #include "bootp.h"
18 #ifdef CONFIG_LED_STATUS
19 #include <status_led.h>
20 #endif
21 #ifdef CONFIG_BOOTP_RANDOM_DELAY
22 #include "net_rand.h"
23 #endif
24
25 #define BOOTP_VENDOR_MAGIC      0x63825363      /* RFC1048 Magic Cookie */
26
27 /*
28  * The timeout for the initial BOOTP/DHCP request used to be described by a
29  * counter of fixed-length timeout periods. TIMEOUT_COUNT represents
30  * that counter
31  *
32  * Now that the timeout periods are variable (exponential backoff and retry)
33  * we convert the timeout count to the absolute time it would have take to
34  * execute that many retries, and keep sending retry packets until that time
35  * is reached.
36  */
37 #ifndef CONFIG_NET_RETRY_COUNT
38 # define TIMEOUT_COUNT  5               /* # of timeouts before giving up */
39 #else
40 # define TIMEOUT_COUNT  (CONFIG_NET_RETRY_COUNT)
41 #endif
42 #define TIMEOUT_MS      ((3 + (TIMEOUT_COUNT * 5)) * 1000)
43
44 #define PORT_BOOTPS     67              /* BOOTP server UDP port */
45 #define PORT_BOOTPC     68              /* BOOTP client UDP port */
46
47 #ifndef CONFIG_DHCP_MIN_EXT_LEN         /* minimal length of extension list */
48 #define CONFIG_DHCP_MIN_EXT_LEN 64
49 #endif
50
51 #ifndef CONFIG_BOOTP_ID_CACHE_SIZE
52 #define CONFIG_BOOTP_ID_CACHE_SIZE 4
53 #endif
54
55 u32             bootp_ids[CONFIG_BOOTP_ID_CACHE_SIZE];
56 unsigned int    bootp_num_ids;
57 int             bootp_try;
58 ulong           bootp_start;
59 ulong           bootp_timeout;
60 char net_nis_domain[32] = {0,}; /* Our NIS domain */
61 char net_hostname[32] = {0,}; /* Our hostname */
62 char net_root_path[64] = {0,}; /* Our bootpath */
63
64 static ulong time_taken_max;
65
66 #if defined(CONFIG_CMD_DHCP)
67 static dhcp_state_t dhcp_state = INIT;
68 static u32 dhcp_leasetime;
69 static struct in_addr dhcp_server_ip;
70 static u8 dhcp_option_overload;
71 #define OVERLOAD_FILE 1
72 #define OVERLOAD_SNAME 2
73 static void dhcp_handler(uchar *pkt, unsigned dest, struct in_addr sip,
74                         unsigned src, unsigned len);
75
76 /* For Debug */
77 #if 0
78 static char *dhcpmsg2str(int type)
79 {
80         switch (type) {
81         case 1:  return "DHCPDISCOVER"; break;
82         case 2:  return "DHCPOFFER";    break;
83         case 3:  return "DHCPREQUEST";  break;
84         case 4:  return "DHCPDECLINE";  break;
85         case 5:  return "DHCPACK";      break;
86         case 6:  return "DHCPNACK";     break;
87         case 7:  return "DHCPRELEASE";  break;
88         default: return "UNKNOWN/INVALID MSG TYPE"; break;
89         }
90 }
91 #endif
92 #endif
93
94 static void bootp_add_id(ulong id)
95 {
96         if (bootp_num_ids >= ARRAY_SIZE(bootp_ids)) {
97                 size_t size = sizeof(bootp_ids) - sizeof(id);
98
99                 memmove(bootp_ids, &bootp_ids[1], size);
100                 bootp_ids[bootp_num_ids - 1] = id;
101         } else {
102                 bootp_ids[bootp_num_ids] = id;
103                 bootp_num_ids++;
104         }
105 }
106
107 static bool bootp_match_id(ulong id)
108 {
109         unsigned int i;
110
111         for (i = 0; i < bootp_num_ids; i++)
112                 if (bootp_ids[i] == id)
113                         return true;
114
115         return false;
116 }
117
118 static int check_reply_packet(uchar *pkt, unsigned dest, unsigned src,
119                               unsigned len)
120 {
121         struct bootp_hdr *bp = (struct bootp_hdr *)pkt;
122         int retval = 0;
123
124         if (dest != PORT_BOOTPC || src != PORT_BOOTPS)
125                 retval = -1;
126         else if (len < sizeof(struct bootp_hdr) - OPT_FIELD_SIZE)
127                 retval = -2;
128         else if (bp->bp_op != OP_BOOTREPLY)
129                 retval = -3;
130         else if (bp->bp_htype != HWT_ETHER)
131                 retval = -4;
132         else if (bp->bp_hlen != HWL_ETHER)
133                 retval = -5;
134         else if (!bootp_match_id(net_read_u32(&bp->bp_id)))
135                 retval = -6;
136         else if (memcmp(bp->bp_chaddr, net_ethaddr, HWL_ETHER) != 0)
137                 retval = -7;
138
139         debug("Filtering pkt = %d\n", retval);
140
141         return retval;
142 }
143
144 /*
145  * Copy parameters of interest from BOOTP_REPLY/DHCP_OFFER packet
146  */
147 static void store_net_params(struct bootp_hdr *bp)
148 {
149 #if !defined(CONFIG_BOOTP_SERVERIP)
150         struct in_addr tmp_ip;
151         bool overwrite_serverip = true;
152
153 #if defined(CONFIG_BOOTP_PREFER_SERVERIP)
154         overwrite_serverip = false;
155 #endif
156
157         net_copy_ip(&tmp_ip, &bp->bp_siaddr);
158         if (tmp_ip.s_addr != 0 && (overwrite_serverip || !net_server_ip.s_addr))
159                 net_copy_ip(&net_server_ip, &bp->bp_siaddr);
160         memcpy(net_server_ethaddr,
161                ((struct ethernet_hdr *)net_rx_packet)->et_src, 6);
162         if (
163 #if defined(CONFIG_CMD_DHCP)
164             !(dhcp_option_overload & OVERLOAD_FILE) &&
165 #endif
166             (strlen(bp->bp_file) > 0) &&
167             !net_boot_file_name_explicit) {
168                 copy_filename(net_boot_file_name, bp->bp_file,
169                               sizeof(net_boot_file_name));
170         }
171
172         debug("net_boot_file_name: %s\n", net_boot_file_name);
173
174         /* Propagate to environment:
175          * don't delete exising entry when BOOTP / DHCP reply does
176          * not contain a new value
177          */
178         if (*net_boot_file_name)
179                 env_set("bootfile", net_boot_file_name);
180 #endif
181         net_copy_ip(&net_ip, &bp->bp_yiaddr);
182 }
183
184 static int truncate_sz(const char *name, int maxlen, int curlen)
185 {
186         if (curlen >= maxlen) {
187                 printf("*** WARNING: %s is too long (%d - max: %d)"
188                         " - truncated\n", name, curlen, maxlen);
189                 curlen = maxlen - 1;
190         }
191         return curlen;
192 }
193
194 #if !defined(CONFIG_CMD_DHCP)
195
196 static void bootp_process_vendor_field(u8 *ext)
197 {
198         int size = *(ext + 1);
199
200         debug("[BOOTP] Processing extension %d... (%d bytes)\n", *ext,
201               *(ext + 1));
202
203         net_boot_file_expected_size_in_blocks = 0;
204
205         switch (*ext) {
206                 /* Fixed length fields */
207         case 1:                 /* Subnet mask */
208                 if (net_netmask.s_addr == 0)
209                         net_copy_ip(&net_netmask, (struct in_addr *)(ext + 2));
210                 break;
211         case 2:                 /* Time offset - Not yet supported */
212                 break;
213                 /* Variable length fields */
214         case 3:                 /* Gateways list */
215                 if (net_gateway.s_addr == 0)
216                         net_copy_ip(&net_gateway, (struct in_addr *)(ext + 2));
217                 break;
218         case 4:                 /* Time server - Not yet supported */
219                 break;
220         case 5:                 /* IEN-116 name server - Not yet supported */
221                 break;
222         case 6:
223                 if (net_dns_server.s_addr == 0)
224                         net_copy_ip(&net_dns_server,
225                                     (struct in_addr *)(ext + 2));
226 #if defined(CONFIG_BOOTP_DNS2)
227                 if ((net_dns_server2.s_addr == 0) && (size > 4))
228                         net_copy_ip(&net_dns_server2,
229                                     (struct in_addr *)(ext + 2 + 4));
230 #endif
231                 break;
232         case 7:                 /* Log server - Not yet supported */
233                 break;
234         case 8:                 /* Cookie/Quote server - Not yet supported */
235                 break;
236         case 9:                 /* LPR server - Not yet supported */
237                 break;
238         case 10:                /* Impress server - Not yet supported */
239                 break;
240         case 11:                /* RPL server - Not yet supported */
241                 break;
242         case 12:                /* Host name */
243                 if (net_hostname[0] == 0) {
244                         size = truncate_sz("Host Name",
245                                 sizeof(net_hostname), size);
246                         memcpy(&net_hostname, ext + 2, size);
247                         net_hostname[size] = 0;
248                 }
249                 break;
250         case 13:                /* Boot file size */
251                 if (size == 2)
252                         net_boot_file_expected_size_in_blocks =
253                                 ntohs(*(ushort *)(ext + 2));
254                 else if (size == 4)
255                         net_boot_file_expected_size_in_blocks =
256                                 ntohl(*(ulong *)(ext + 2));
257                 break;
258         case 14:                /* Merit dump file - Not yet supported */
259                 break;
260         case 15:                /* Domain name - Not yet supported */
261                 break;
262         case 16:                /* Swap server - Not yet supported */
263                 break;
264         case 17:                /* Root path */
265                 if (net_root_path[0] == 0) {
266                         size = truncate_sz("Root Path",
267                                 sizeof(net_root_path), size);
268                         memcpy(&net_root_path, ext + 2, size);
269                         net_root_path[size] = 0;
270                 }
271                 break;
272         case 18:                /* Extension path - Not yet supported */
273                 /*
274                  * This can be used to send the information of the
275                  * vendor area in another file that the client can
276                  * access via TFTP.
277                  */
278                 break;
279                 /* IP host layer fields */
280         case 40:                /* NIS Domain name */
281                 if (net_nis_domain[0] == 0) {
282                         size = truncate_sz("NIS Domain Name",
283                                 sizeof(net_nis_domain), size);
284                         memcpy(&net_nis_domain, ext + 2, size);
285                         net_nis_domain[size] = 0;
286                 }
287                 break;
288 #if defined(CONFIG_CMD_SNTP) && defined(CONFIG_BOOTP_NTPSERVER)
289         case 42:        /* NTP server IP */
290                 net_copy_ip(&net_ntp_server, (struct in_addr *)(ext + 2));
291                 break;
292 #endif
293                 /* Application layer fields */
294         case 43:                /* Vendor specific info - Not yet supported */
295                 /*
296                  * Binary information to exchange specific
297                  * product information.
298                  */
299                 break;
300                 /* Reserved (custom) fields (128..254) */
301         }
302 }
303
304 static void bootp_process_vendor(u8 *ext, int size)
305 {
306         u8 *end = ext + size;
307
308         debug("[BOOTP] Checking extension (%d bytes)...\n", size);
309
310         while ((ext < end) && (*ext != 0xff)) {
311                 if (*ext == 0) {
312                         ext++;
313                 } else {
314                         u8 *opt = ext;
315
316                         ext += ext[1] + 2;
317                         if (ext <= end)
318                                 bootp_process_vendor_field(opt);
319                 }
320         }
321
322         debug("[BOOTP] Received fields:\n");
323         if (net_netmask.s_addr)
324                 debug("net_netmask : %pI4\n", &net_netmask);
325
326         if (net_gateway.s_addr)
327                 debug("net_gateway      : %pI4", &net_gateway);
328
329         if (net_boot_file_expected_size_in_blocks)
330                 debug("net_boot_file_expected_size_in_blocks : %d\n",
331                       net_boot_file_expected_size_in_blocks);
332
333         if (net_hostname[0])
334                 debug("net_hostname  : %s\n", net_hostname);
335
336         if (net_root_path[0])
337                 debug("net_root_path  : %s\n", net_root_path);
338
339         if (net_nis_domain[0])
340                 debug("net_nis_domain : %s\n", net_nis_domain);
341
342 #if defined(CONFIG_CMD_SNTP) && defined(CONFIG_BOOTP_NTPSERVER)
343         if (net_ntp_server.s_addr)
344                 debug("net_ntp_server : %pI4\n", &net_ntp_server);
345 #endif
346 }
347
348 /*
349  *      Handle a BOOTP received packet.
350  */
351 static void bootp_handler(uchar *pkt, unsigned dest, struct in_addr sip,
352                           unsigned src, unsigned len)
353 {
354         struct bootp_hdr *bp;
355
356         debug("got BOOTP packet (src=%d, dst=%d, len=%d want_len=%zu)\n",
357               src, dest, len, sizeof(struct bootp_hdr));
358
359         bp = (struct bootp_hdr *)pkt;
360
361         /* Filter out pkts we don't want */
362         if (check_reply_packet(pkt, dest, src, len))
363                 return;
364
365         /*
366          *      Got a good BOOTP reply.  Copy the data into our variables.
367          */
368 #if defined(CONFIG_LED_STATUS) && defined(CONFIG_LED_STATUS_BOOT_ENABLE)
369         status_led_set(CONFIG_LED_STATUS_BOOT, CONFIG_LED_STATUS_OFF);
370 #endif
371
372         store_net_params(bp);           /* Store net parameters from reply */
373
374         /* Retrieve extended information (we must parse the vendor area) */
375         if (net_read_u32((u32 *)&bp->bp_vend[0]) == htonl(BOOTP_VENDOR_MAGIC))
376                 bootp_process_vendor((uchar *)&bp->bp_vend[4], len);
377
378         net_set_timeout_handler(0, (thand_f *)0);
379         bootstage_mark_name(BOOTSTAGE_ID_BOOTP_STOP, "bootp_stop");
380
381         debug("Got good BOOTP\n");
382
383         net_auto_load();
384 }
385 #endif
386
387 /*
388  *      Timeout on BOOTP/DHCP request.
389  */
390 static void bootp_timeout_handler(void)
391 {
392         ulong time_taken = get_timer(bootp_start);
393
394         if (time_taken >= time_taken_max) {
395 #ifdef CONFIG_BOOTP_MAY_FAIL
396                 char *ethrotate;
397
398                 ethrotate = env_get("ethrotate");
399                 if ((ethrotate && strcmp(ethrotate, "no") == 0) ||
400                     net_restart_wrap) {
401                         puts("\nRetry time exceeded\n");
402                         net_set_state(NETLOOP_FAIL);
403                 } else
404 #endif
405                 {
406                         puts("\nRetry time exceeded; starting again\n");
407                         net_start_again();
408                 }
409         } else {
410                 bootp_timeout *= 2;
411                 if (bootp_timeout > 2000)
412                         bootp_timeout = 2000;
413                 net_set_timeout_handler(bootp_timeout, bootp_timeout_handler);
414                 bootp_request();
415         }
416 }
417
418 #define put_vci(e, str)                                         \
419         do {                                                    \
420                 size_t vci_strlen = strlen(str);                \
421                 *e++ = 60;      /* Vendor Class Identifier */   \
422                 *e++ = vci_strlen;                              \
423                 memcpy(e, str, vci_strlen);                     \
424                 e += vci_strlen;                                \
425         } while (0)
426
427 static u8 *add_vci(u8 *e)
428 {
429         char *vci = NULL;
430         char *env_vci = env_get("bootp_vci");
431
432 #if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_NET_VCI_STRING)
433         vci = CONFIG_SPL_NET_VCI_STRING;
434 #elif defined(CONFIG_BOOTP_VCI_STRING)
435         vci = CONFIG_BOOTP_VCI_STRING;
436 #endif
437
438         if (env_vci)
439                 vci = env_vci;
440
441         if (vci)
442                 put_vci(e, vci);
443
444         return e;
445 }
446
447 /*
448  *      Initialize BOOTP extension fields in the request.
449  */
450 #if defined(CONFIG_CMD_DHCP)
451 static int dhcp_extended(u8 *e, int message_type, struct in_addr server_ip,
452                         struct in_addr requested_ip)
453 {
454         u8 *start = e;
455         u8 *cnt;
456 #ifdef CONFIG_LIB_UUID
457         char *uuid;
458 #endif
459         int clientarch = -1;
460
461 #if defined(CONFIG_BOOTP_VENDOREX)
462         u8 *x;
463 #endif
464 #if defined(CONFIG_BOOTP_SEND_HOSTNAME)
465         char *hostname;
466 #endif
467
468         *e++ = 99;              /* RFC1048 Magic Cookie */
469         *e++ = 130;
470         *e++ = 83;
471         *e++ = 99;
472
473         *e++ = 53;              /* DHCP Message Type */
474         *e++ = 1;
475         *e++ = message_type;
476
477         *e++ = 57;              /* Maximum DHCP Message Size */
478         *e++ = 2;
479         *e++ = (576 - 312 + OPT_FIELD_SIZE) >> 8;
480         *e++ = (576 - 312 + OPT_FIELD_SIZE) & 0xff;
481
482         if (server_ip.s_addr) {
483                 int tmp = ntohl(server_ip.s_addr);
484
485                 *e++ = 54;      /* ServerID */
486                 *e++ = 4;
487                 *e++ = tmp >> 24;
488                 *e++ = tmp >> 16;
489                 *e++ = tmp >> 8;
490                 *e++ = tmp & 0xff;
491         }
492
493         if (requested_ip.s_addr) {
494                 int tmp = ntohl(requested_ip.s_addr);
495
496                 *e++ = 50;      /* Requested IP */
497                 *e++ = 4;
498                 *e++ = tmp >> 24;
499                 *e++ = tmp >> 16;
500                 *e++ = tmp >> 8;
501                 *e++ = tmp & 0xff;
502         }
503 #if defined(CONFIG_BOOTP_SEND_HOSTNAME)
504         hostname = env_get("hostname");
505         if (hostname) {
506                 int hostnamelen = strlen(hostname);
507
508                 *e++ = 12;      /* Hostname */
509                 *e++ = hostnamelen;
510                 memcpy(e, hostname, hostnamelen);
511                 e += hostnamelen;
512         }
513 #endif
514
515 #ifdef CONFIG_BOOTP_PXE_CLIENTARCH
516         clientarch = CONFIG_BOOTP_PXE_CLIENTARCH;
517 #endif
518
519         if (env_get("bootp_arch"))
520                 clientarch = env_get_ulong("bootp_arch", 16, clientarch);
521
522         if (clientarch > 0) {
523                 *e++ = 93;      /* Client System Architecture */
524                 *e++ = 2;
525                 *e++ = (clientarch >> 8) & 0xff;
526                 *e++ = clientarch & 0xff;
527         }
528
529         *e++ = 94;      /* Client Network Interface Identifier */
530         *e++ = 3;
531         *e++ = 1;       /* type field for UNDI */
532         *e++ = 0;       /* major revision */
533         *e++ = 0;       /* minor revision */
534
535 #ifdef CONFIG_LIB_UUID
536         uuid = env_get("pxeuuid");
537
538         if (uuid) {
539                 if (uuid_str_valid(uuid)) {
540                         *e++ = 97;      /* Client Machine Identifier */
541                         *e++ = 17;
542                         *e++ = 0;       /* type 0 - UUID */
543
544                         uuid_str_to_bin(uuid, e, UUID_STR_FORMAT_STD);
545                         e += 16;
546                 } else {
547                         printf("Invalid pxeuuid: %s\n", uuid);
548                 }
549         }
550 #endif
551
552         e = add_vci(e);
553
554 #if defined(CONFIG_BOOTP_VENDOREX)
555         x = dhcp_vendorex_prep(e);
556         if (x)
557                 return x - start;
558 #endif
559
560         *e++ = 55;              /* Parameter Request List */
561          cnt = e++;             /* Pointer to count of requested items */
562         *cnt = 0;
563 #if defined(CONFIG_BOOTP_SUBNETMASK)
564         *e++  = 1;              /* Subnet Mask */
565         *cnt += 1;
566 #endif
567 #if defined(CONFIG_BOOTP_TIMEOFFSET)
568         *e++  = 2;
569         *cnt += 1;
570 #endif
571 #if defined(CONFIG_BOOTP_GATEWAY)
572         *e++  = 3;              /* Router Option */
573         *cnt += 1;
574 #endif
575 #if defined(CONFIG_BOOTP_DNS)
576         *e++  = 6;              /* DNS Server(s) */
577         *cnt += 1;
578 #endif
579 #if defined(CONFIG_BOOTP_HOSTNAME)
580         *e++  = 12;             /* Hostname */
581         *cnt += 1;
582 #endif
583 #if defined(CONFIG_BOOTP_BOOTFILESIZE)
584         *e++  = 13;             /* Boot File Size */
585         *cnt += 1;
586 #endif
587 #if defined(CONFIG_BOOTP_BOOTPATH)
588         *e++  = 17;             /* Boot path */
589         *cnt += 1;
590 #endif
591 #if defined(CONFIG_BOOTP_NISDOMAIN)
592         *e++  = 40;             /* NIS Domain name request */
593         *cnt += 1;
594 #endif
595 #if defined(CONFIG_BOOTP_NTPSERVER)
596         *e++  = 42;
597         *cnt += 1;
598 #endif
599         /* no options, so back up to avoid sending an empty request list */
600         if (*cnt == 0)
601                 e -= 2;
602
603         *e++  = 255;            /* End of the list */
604
605         /* Pad to minimal length */
606 #ifdef  CONFIG_DHCP_MIN_EXT_LEN
607         while ((e - start) < CONFIG_DHCP_MIN_EXT_LEN)
608                 *e++ = 0;
609 #endif
610
611         return e - start;
612 }
613
614 #else
615 /*
616  * Warning: no field size check - change CONFIG_BOOTP_* at your own risk!
617  */
618 static int bootp_extended(u8 *e)
619 {
620         u8 *start = e;
621
622         *e++ = 99;              /* RFC1048 Magic Cookie */
623         *e++ = 130;
624         *e++ = 83;
625         *e++ = 99;
626
627 #if defined(CONFIG_CMD_DHCP)
628         *e++ = 53;              /* DHCP Message Type */
629         *e++ = 1;
630         *e++ = DHCP_DISCOVER;
631
632         *e++ = 57;              /* Maximum DHCP Message Size */
633         *e++ = 2;
634         *e++ = (576 - 312 + OPT_FIELD_SIZE) >> 16;
635         *e++ = (576 - 312 + OPT_FIELD_SIZE) & 0xff;
636 #endif
637
638         add_vci(e);
639
640 #if defined(CONFIG_BOOTP_SUBNETMASK)
641         *e++ = 1;               /* Subnet mask request */
642         *e++ = 4;
643         e   += 4;
644 #endif
645
646 #if defined(CONFIG_BOOTP_GATEWAY)
647         *e++ = 3;               /* Default gateway request */
648         *e++ = 4;
649         e   += 4;
650 #endif
651
652 #if defined(CONFIG_BOOTP_DNS)
653         *e++ = 6;               /* Domain Name Server */
654         *e++ = 4;
655         e   += 4;
656 #endif
657
658 #if defined(CONFIG_BOOTP_HOSTNAME)
659         *e++ = 12;              /* Host name request */
660         *e++ = 32;
661         e   += 32;
662 #endif
663
664 #if defined(CONFIG_BOOTP_BOOTFILESIZE)
665         *e++ = 13;              /* Boot file size */
666         *e++ = 2;
667         e   += 2;
668 #endif
669
670 #if defined(CONFIG_BOOTP_BOOTPATH)
671         *e++ = 17;              /* Boot path */
672         *e++ = 32;
673         e   += 32;
674 #endif
675
676 #if defined(CONFIG_BOOTP_NISDOMAIN)
677         *e++ = 40;              /* NIS Domain name request */
678         *e++ = 32;
679         e   += 32;
680 #endif
681 #if defined(CONFIG_BOOTP_NTPSERVER)
682         *e++ = 42;
683         *e++ = 4;
684         e   += 4;
685 #endif
686
687         *e++ = 255;             /* End of the list */
688
689         /*
690          * If nothing in list, remove it altogether. Some DHCP servers get
691          * upset by this minor faux pas and do not respond at all.
692          */
693         if (e == start + 3) {
694                 printf("*** Warning: no DHCP options requested\n");
695                 e -= 3;
696         }
697
698         return e - start;
699 }
700 #endif
701
702 void bootp_reset(void)
703 {
704         bootp_num_ids = 0;
705         bootp_try = 0;
706         bootp_start = get_timer(0);
707         bootp_timeout = 250;
708 }
709
710 void bootp_request(void)
711 {
712         uchar *pkt, *iphdr;
713         struct bootp_hdr *bp;
714         int extlen, pktlen, iplen;
715         int eth_hdr_size;
716 #ifdef CONFIG_BOOTP_RANDOM_DELAY
717         ulong rand_ms;
718 #endif
719         u32 bootp_id;
720         struct in_addr zero_ip;
721         struct in_addr bcast_ip;
722         char *ep;  /* Environment pointer */
723
724         bootstage_mark_name(BOOTSTAGE_ID_BOOTP_START, "bootp_start");
725 #if defined(CONFIG_CMD_DHCP)
726         dhcp_state = INIT;
727 #endif
728
729         ep = env_get("bootpretryperiod");
730         if (ep != NULL)
731                 time_taken_max = simple_strtoul(ep, NULL, 10);
732         else
733                 time_taken_max = TIMEOUT_MS;
734
735 #ifdef CONFIG_BOOTP_RANDOM_DELAY                /* Random BOOTP delay */
736         if (bootp_try == 0)
737                 srand_mac();
738
739         if (bootp_try <= 2)     /* Start with max 1024 * 1ms */
740                 rand_ms = rand() >> (22 - bootp_try);
741         else            /* After 3rd BOOTP request max 8192 * 1ms */
742                 rand_ms = rand() >> 19;
743
744         printf("Random delay: %ld ms...\n", rand_ms);
745         mdelay(rand_ms);
746
747 #endif  /* CONFIG_BOOTP_RANDOM_DELAY */
748
749         printf("BOOTP broadcast %d\n", ++bootp_try);
750         pkt = net_tx_packet;
751         memset((void *)pkt, 0, PKTSIZE);
752
753         eth_hdr_size = net_set_ether(pkt, net_bcast_ethaddr, PROT_IP);
754         pkt += eth_hdr_size;
755
756         /*
757          * Next line results in incorrect packet size being transmitted,
758          * resulting in errors in some DHCP servers, reporting missing bytes.
759          * Size must be set in packet header after extension length has been
760          * determined.
761          * C. Hallinan, DS4.COM, Inc.
762          */
763         /* net_set_udp_header(pkt, 0xFFFFFFFFL, PORT_BOOTPS, PORT_BOOTPC,
764                 sizeof (struct bootp_hdr)); */
765         iphdr = pkt;    /* We need this later for net_set_udp_header() */
766         pkt += IP_UDP_HDR_SIZE;
767
768         bp = (struct bootp_hdr *)pkt;
769         bp->bp_op = OP_BOOTREQUEST;
770         bp->bp_htype = HWT_ETHER;
771         bp->bp_hlen = HWL_ETHER;
772         bp->bp_hops = 0;
773         /*
774          * according to RFC1542, should be 0 on first request, secs since
775          * first request otherwise
776          */
777         bp->bp_secs = htons(get_timer(bootp_start) / 1000);
778         zero_ip.s_addr = 0;
779         net_write_ip(&bp->bp_ciaddr, zero_ip);
780         net_write_ip(&bp->bp_yiaddr, zero_ip);
781         net_write_ip(&bp->bp_siaddr, zero_ip);
782         net_write_ip(&bp->bp_giaddr, zero_ip);
783         memcpy(bp->bp_chaddr, net_ethaddr, 6);
784         copy_filename(bp->bp_file, net_boot_file_name, sizeof(bp->bp_file));
785
786         /* Request additional information from the BOOTP/DHCP server */
787 #if defined(CONFIG_CMD_DHCP)
788         extlen = dhcp_extended((u8 *)bp->bp_vend, DHCP_DISCOVER, zero_ip,
789                                zero_ip);
790 #else
791         extlen = bootp_extended((u8 *)bp->bp_vend);
792 #endif
793
794         /*
795          *      Bootp ID is the lower 4 bytes of our ethernet address
796          *      plus the current time in ms.
797          */
798         bootp_id = ((u32)net_ethaddr[2] << 24)
799                 | ((u32)net_ethaddr[3] << 16)
800                 | ((u32)net_ethaddr[4] << 8)
801                 | (u32)net_ethaddr[5];
802         bootp_id += get_timer(0);
803         bootp_id = htonl(bootp_id);
804         bootp_add_id(bootp_id);
805         net_copy_u32(&bp->bp_id, &bootp_id);
806
807         /*
808          * Calculate proper packet lengths taking into account the
809          * variable size of the options field
810          */
811         iplen = BOOTP_HDR_SIZE - OPT_FIELD_SIZE + extlen;
812         pktlen = eth_hdr_size + IP_UDP_HDR_SIZE + iplen;
813         bcast_ip.s_addr = 0xFFFFFFFFL;
814         net_set_udp_header(iphdr, bcast_ip, PORT_BOOTPS, PORT_BOOTPC, iplen);
815         net_set_timeout_handler(bootp_timeout, bootp_timeout_handler);
816
817 #if defined(CONFIG_CMD_DHCP)
818         dhcp_state = SELECTING;
819         net_set_udp_handler(dhcp_handler);
820 #else
821         net_set_udp_handler(bootp_handler);
822 #endif
823         net_send_packet(net_tx_packet, pktlen);
824 }
825
826 #if defined(CONFIG_CMD_DHCP)
827 static void dhcp_process_options(uchar *popt, uchar *end)
828 {
829         int oplen, size;
830 #if defined(CONFIG_CMD_SNTP) && defined(CONFIG_BOOTP_TIMEOFFSET)
831         int *to_ptr;
832 #endif
833
834         while (popt < end && *popt != 0xff) {
835                 oplen = *(popt + 1);
836                 switch (*popt) {
837                 case 0:
838                         oplen = -1; /* Pad omits len byte */
839                         break;
840                 case 1:
841                         net_copy_ip(&net_netmask, (popt + 2));
842                         break;
843 #if defined(CONFIG_CMD_SNTP) && defined(CONFIG_BOOTP_TIMEOFFSET)
844                 case 2:         /* Time offset  */
845                         to_ptr = &net_ntp_time_offset;
846                         net_copy_u32((u32 *)to_ptr, (u32 *)(popt + 2));
847                         net_ntp_time_offset = ntohl(net_ntp_time_offset);
848                         break;
849 #endif
850                 case 3:
851                         net_copy_ip(&net_gateway, (popt + 2));
852                         break;
853                 case 6:
854                         net_copy_ip(&net_dns_server, (popt + 2));
855 #if defined(CONFIG_BOOTP_DNS2)
856                         if (*(popt + 1) > 4)
857                                 net_copy_ip(&net_dns_server2, (popt + 2 + 4));
858 #endif
859                         break;
860                 case 12:
861                         size = truncate_sz("Host Name",
862                                 sizeof(net_hostname), oplen);
863                         memcpy(&net_hostname, popt + 2, size);
864                         net_hostname[size] = 0;
865                         break;
866                 case 15:        /* Ignore Domain Name Option */
867                         break;
868                 case 17:
869                         size = truncate_sz("Root Path",
870                                 sizeof(net_root_path), oplen);
871                         memcpy(&net_root_path, popt + 2, size);
872                         net_root_path[size] = 0;
873                         break;
874                 case 28:        /* Ignore Broadcast Address Option */
875                         break;
876 #if defined(CONFIG_CMD_SNTP) && defined(CONFIG_BOOTP_NTPSERVER)
877                 case 42:        /* NTP server IP */
878                         net_copy_ip(&net_ntp_server, (popt + 2));
879                         break;
880 #endif
881                 case 51:
882                         net_copy_u32(&dhcp_leasetime, (u32 *)(popt + 2));
883                         break;
884                 case 52:
885                         dhcp_option_overload = popt[2];
886                         break;
887                 case 53:        /* Ignore Message Type Option */
888                         break;
889                 case 54:
890                         net_copy_ip(&dhcp_server_ip, (popt + 2));
891                         break;
892                 case 58:        /* Ignore Renewal Time Option */
893                         break;
894                 case 59:        /* Ignore Rebinding Time Option */
895                         break;
896                 case 66:        /* Ignore TFTP server name */
897                         break;
898                 case 67:        /* Bootfile option */
899                         if (!net_boot_file_name_explicit) {
900                                 size = truncate_sz("Bootfile",
901                                                    sizeof(net_boot_file_name),
902                                                    oplen);
903                                 memcpy(&net_boot_file_name, popt + 2, size);
904                                 net_boot_file_name[size] = 0;
905                         }
906                         break;
907                 default:
908 #if defined(CONFIG_BOOTP_VENDOREX)
909                         if (dhcp_vendorex_proc(popt))
910                                 break;
911 #endif
912                         printf("*** Unhandled DHCP Option in OFFER/ACK:"
913                                " %d\n", *popt);
914                         break;
915                 }
916                 popt += oplen + 2;      /* Process next option */
917         }
918 }
919
920 static void dhcp_packet_process_options(struct bootp_hdr *bp)
921 {
922         uchar *popt = (uchar *)&bp->bp_vend[4];
923         uchar *end = popt + BOOTP_HDR_SIZE;
924
925         if (net_read_u32((u32 *)&bp->bp_vend[0]) != htonl(BOOTP_VENDOR_MAGIC))
926                 return;
927
928         dhcp_option_overload = 0;
929
930         /*
931          * The 'options' field MUST be interpreted first, 'file' next,
932          * 'sname' last.
933          */
934         dhcp_process_options(popt, end);
935
936         if (dhcp_option_overload & OVERLOAD_FILE) {
937                 popt = (uchar *)bp->bp_file;
938                 end = popt + sizeof(bp->bp_file);
939                 dhcp_process_options(popt, end);
940         }
941
942         if (dhcp_option_overload & OVERLOAD_SNAME) {
943                 popt = (uchar *)bp->bp_sname;
944                 end = popt + sizeof(bp->bp_sname);
945                 dhcp_process_options(popt, end);
946         }
947 }
948
949 static int dhcp_message_type(unsigned char *popt)
950 {
951         if (net_read_u32((u32 *)popt) != htonl(BOOTP_VENDOR_MAGIC))
952                 return -1;
953
954         popt += 4;
955         while (*popt != 0xff) {
956                 if (*popt == 53)        /* DHCP Message Type */
957                         return *(popt + 2);
958                 if (*popt == 0) {
959                         /* Pad */
960                         popt += 1;
961                 } else {
962                         /* Scan through all options */
963                         popt += *(popt + 1) + 2;
964                 }
965         }
966         return -1;
967 }
968
969 static void dhcp_send_request_packet(struct bootp_hdr *bp_offer)
970 {
971         uchar *pkt, *iphdr;
972         struct bootp_hdr *bp;
973         int pktlen, iplen, extlen;
974         int eth_hdr_size;
975         struct in_addr offered_ip;
976         struct in_addr zero_ip;
977         struct in_addr bcast_ip;
978
979         debug("dhcp_send_request_packet: Sending DHCPREQUEST\n");
980         pkt = net_tx_packet;
981         memset((void *)pkt, 0, PKTSIZE);
982
983         eth_hdr_size = net_set_ether(pkt, net_bcast_ethaddr, PROT_IP);
984         pkt += eth_hdr_size;
985
986         iphdr = pkt;    /* We'll need this later to set proper pkt size */
987         pkt += IP_UDP_HDR_SIZE;
988
989         bp = (struct bootp_hdr *)pkt;
990         bp->bp_op = OP_BOOTREQUEST;
991         bp->bp_htype = HWT_ETHER;
992         bp->bp_hlen = HWL_ETHER;
993         bp->bp_hops = 0;
994         bp->bp_secs = htons(get_timer(bootp_start) / 1000);
995         /* Do not set the client IP, your IP, or server IP yet, since it
996          * hasn't been ACK'ed by the server yet */
997
998         /*
999          * RFC3046 requires Relay Agents to discard packets with
1000          * nonzero and offered giaddr
1001          */
1002         zero_ip.s_addr = 0;
1003         net_write_ip(&bp->bp_giaddr, zero_ip);
1004
1005         memcpy(bp->bp_chaddr, net_ethaddr, 6);
1006         copy_filename(bp->bp_file, net_boot_file_name, sizeof(bp->bp_file));
1007
1008         /*
1009          * ID is the id of the OFFER packet
1010          */
1011
1012         net_copy_u32(&bp->bp_id, &bp_offer->bp_id);
1013
1014         /*
1015          * Copy options from OFFER packet if present
1016          */
1017
1018         /* Copy offered IP into the parameters request list */
1019         net_copy_ip(&offered_ip, &bp_offer->bp_yiaddr);
1020         extlen = dhcp_extended((u8 *)bp->bp_vend, DHCP_REQUEST,
1021                 dhcp_server_ip, offered_ip);
1022
1023         iplen = BOOTP_HDR_SIZE - OPT_FIELD_SIZE + extlen;
1024         pktlen = eth_hdr_size + IP_UDP_HDR_SIZE + iplen;
1025         bcast_ip.s_addr = 0xFFFFFFFFL;
1026         net_set_udp_header(iphdr, bcast_ip, PORT_BOOTPS, PORT_BOOTPC, iplen);
1027
1028 #ifdef CONFIG_BOOTP_DHCP_REQUEST_DELAY
1029         udelay(CONFIG_BOOTP_DHCP_REQUEST_DELAY);
1030 #endif  /* CONFIG_BOOTP_DHCP_REQUEST_DELAY */
1031         debug("Transmitting DHCPREQUEST packet: len = %d\n", pktlen);
1032         net_send_packet(net_tx_packet, pktlen);
1033 }
1034
1035 /*
1036  *      Handle DHCP received packets.
1037  */
1038 static void dhcp_handler(uchar *pkt, unsigned dest, struct in_addr sip,
1039                          unsigned src, unsigned len)
1040 {
1041         struct bootp_hdr *bp = (struct bootp_hdr *)pkt;
1042
1043         debug("DHCPHandler: got packet: (src=%d, dst=%d, len=%d) state: %d\n",
1044               src, dest, len, dhcp_state);
1045
1046         /* Filter out pkts we don't want */
1047         if (check_reply_packet(pkt, dest, src, len))
1048                 return;
1049
1050         debug("DHCPHandler: got DHCP packet: (src=%d, dst=%d, len=%d) state: "
1051               "%d\n", src, dest, len, dhcp_state);
1052
1053         if (net_read_ip(&bp->bp_yiaddr).s_addr == 0)
1054                 return;
1055
1056         switch (dhcp_state) {
1057         case SELECTING:
1058                 /*
1059                  * Wait an appropriate time for any potential DHCPOFFER packets
1060                  * to arrive.  Then select one, and generate DHCPREQUEST
1061                  * response.  If filename is in format we recognize, assume it
1062                  * is a valid OFFER from a server we want.
1063                  */
1064                 debug("DHCP: state=SELECTING bp_file: \"%s\"\n", bp->bp_file);
1065 #ifdef CONFIG_SYS_BOOTFILE_PREFIX
1066                 if (strncmp(bp->bp_file,
1067                             CONFIG_SYS_BOOTFILE_PREFIX,
1068                             strlen(CONFIG_SYS_BOOTFILE_PREFIX)) == 0) {
1069 #endif  /* CONFIG_SYS_BOOTFILE_PREFIX */
1070                         dhcp_packet_process_options(bp);
1071                         efi_net_set_dhcp_ack(pkt, len);
1072
1073                         debug("TRANSITIONING TO REQUESTING STATE\n");
1074                         dhcp_state = REQUESTING;
1075
1076                         net_set_timeout_handler(5000, bootp_timeout_handler);
1077                         dhcp_send_request_packet(bp);
1078 #ifdef CONFIG_SYS_BOOTFILE_PREFIX
1079                 }
1080 #endif  /* CONFIG_SYS_BOOTFILE_PREFIX */
1081
1082                 return;
1083                 break;
1084         case REQUESTING:
1085                 debug("DHCP State: REQUESTING\n");
1086
1087                 if (dhcp_message_type((u8 *)bp->bp_vend) == DHCP_ACK) {
1088                         dhcp_packet_process_options(bp);
1089                         /* Store net params from reply */
1090                         store_net_params(bp);
1091                         dhcp_state = BOUND;
1092                         printf("DHCP client bound to address %pI4 (%lu ms)\n",
1093                                &net_ip, get_timer(bootp_start));
1094                         net_set_timeout_handler(0, (thand_f *)0);
1095                         bootstage_mark_name(BOOTSTAGE_ID_BOOTP_STOP,
1096                                             "bootp_stop");
1097
1098                         net_auto_load();
1099                         return;
1100                 }
1101                 break;
1102         case BOUND:
1103                 /* DHCP client bound to address */
1104                 break;
1105         default:
1106                 puts("DHCP: INVALID STATE\n");
1107                 break;
1108         }
1109 }
1110
1111 void dhcp_request(void)
1112 {
1113         bootp_request();
1114 }
1115 #endif  /* CONFIG_CMD_DHCP */