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