Merge from Etherboot 5.4
[people/xl0/gpxe.git] / src / core / nic.c
1 /**************************************************************************
2 Etherboot -  Network Bootstrap Program
3
4 Literature dealing with the network protocols:
5         ARP - RFC826
6         RARP - RFC903
7         IP - RFC791
8         UDP - RFC768
9         BOOTP - RFC951, RFC2132 (vendor extensions)
10         DHCP - RFC2131, RFC2132, RFC3004 (options)
11         TFTP - RFC1350, RFC2347 (options), RFC2348 (blocksize), RFC2349 (tsize)
12         RPC - RFC1831, RFC1832 (XDR), RFC1833 (rpcbind/portmapper)
13         NFS - RFC1094, RFC1813 (v3, useful for clarifications, not implemented)
14         IGMP - RFC1112, RFC2113, RFC2365, RFC2236, RFC3171
15
16 **************************************************************************/
17 #include "etherboot.h"
18 #include "console.h"
19 #include "url.h"
20 #include "proto.h"
21 #include "resolv.h"
22 #include "dev.h"
23 #include "nic.h"
24 #include "background.h"
25 #include "elf.h" /* FOR EM_CURRENT */
26
27 struct arptable_t       arptable[MAX_ARP];
28 /* Put rom_info in .nocompress section so romprefix.S can write to it */
29 struct rom_info rom __attribute__ ((section (".text16.nocompress"))) = {0,0};
30 static unsigned long    netmask;
31 /* Used by nfs.c */
32 char *hostname = "";
33 int hostnamelen = 0;
34 static uint32_t xid;
35 unsigned char *end_of_rfc1533 = NULL;
36 static int vendorext_isvalid;
37 static const unsigned char vendorext_magic[] = {0xE4,0x45,0x74,0x68}; /* √§Eth */
38 static const unsigned char broadcast[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
39 static const in_addr zeroIP = { 0L };
40
41 struct bootpd_t bootp_data;
42
43 #ifdef  NO_DHCP_SUPPORT
44 static unsigned char    rfc1533_cookie[5] = { RFC1533_COOKIE, RFC1533_END };
45 #else   /* !NO_DHCP_SUPPORT */
46 static int dhcp_reply;
47 static in_addr dhcp_server = { 0L };
48 static in_addr dhcp_addr = { 0L };
49 static unsigned char    rfc1533_cookie[] = { RFC1533_COOKIE };
50 #define DHCP_MACHINE_INFO_SIZE (sizeof dhcp_machine_info)
51 static unsigned char dhcp_machine_info[] = {
52         /* Our enclosing DHCP tag */
53         RFC1533_VENDOR_ETHERBOOT_ENCAP, 11,
54         /* Our boot device */
55         RFC1533_VENDOR_NIC_DEV_ID, 5, 0, 0, 0, 0, 0,
56         /* Our current architecture */
57         RFC1533_VENDOR_ARCH, 2, EM_CURRENT & 0xff, (EM_CURRENT >> 8) & 0xff,
58 #ifdef EM_CURRENT_64
59         /* The 64bit version of our current architecture */
60         RFC1533_VENDOR_ARCH, 2, EM_CURRENT_64 & 0xff, (EM_CURRENT_64 >> 8) & 0xff,
61 #undef DHCP_MACHINE_INFO_SIZE
62 #define DHCP_MACHINE_INFO_SIZE (sizeof(dhcp_machine_info) - (EM_CURRENT_64_PRESENT? 0: 4))
63 #endif /* EM_CURRENT_64 */
64 };
65 static const unsigned char dhcpdiscover[] = {
66         RFC2132_MSG_TYPE,1,DHCPDISCOVER,
67         RFC2132_MAX_SIZE,2,     /* request as much as we can */
68         ETH_MAX_MTU / 256, ETH_MAX_MTU % 256,
69 #ifdef PXE_DHCP_STRICT
70         RFC3679_PXE_CLIENT_UUID,RFC3679_PXE_CLIENT_UUID_LENGTH,RFC3679_PXE_CLIENT_UUID_DEFAULT,
71         RFC3679_PXE_CLIENT_ARCH,RFC3679_PXE_CLIENT_ARCH_LENGTH,RFC3679_PXE_CLIENT_ARCH_IAX86PC,
72         RFC3679_PXE_CLIENT_NDI, RFC3679_PXE_CLIENT_NDI_LENGTH, RFC3679_PXE_CLIENT_NDI_21,
73         RFC2132_VENDOR_CLASS_ID,RFC2132_VENDOR_CLASS_ID_PXE_LENGTH,RFC2132_VENDOR_CLASS_ID_PXE,
74 #else
75         RFC2132_VENDOR_CLASS_ID,13,'E','t','h','e','r','b','o','o','t',
76         '-',VERSION_MAJOR+'0','.',VERSION_MINOR+'0',
77 #endif /* PXE_DHCP_STRICT */
78 #ifdef DHCP_CLIENT_ID
79         /* Client ID Option */
80         RFC2132_CLIENT_ID, ( DHCP_CLIENT_ID_LEN + 1 ),
81         DHCP_CLIENT_ID_TYPE, DHCP_CLIENT_ID,
82 #endif /* DHCP_CLIENT_ID */
83 #ifdef DHCP_USER_CLASS
84         /* User Class Option */
85         RFC3004_USER_CLASS, DHCP_USER_CLASS_LEN, DHCP_USER_CLASS,
86 #endif /* DHCP_USER_CLASS */
87         RFC2132_PARAM_LIST,
88 #define DHCPDISCOVER_PARAMS_BASE 4
89 #ifdef  PXE_DHCP_STRICT
90 #define DHCPDISCOVER_PARAMS_PXE ( 1 + 8 )
91 #else
92 #define DHCPDISCOVER_PARAMS_PXE 0
93 #endif /* PXE_DHCP_STRICT */
94 #define DHCPDISCOVER_PARAMS_DNS  1
95         ( DHCPDISCOVER_PARAMS_BASE +
96           DHCPDISCOVER_PARAMS_PXE+
97           DHCPDISCOVER_PARAMS_DNS ),
98         RFC1533_NETMASK,
99         RFC1533_GATEWAY,
100         RFC1533_HOSTNAME,
101         RFC1533_VENDOR,
102 #ifdef PXE_DHCP_STRICT
103         ,RFC2132_VENDOR_CLASS_ID,
104         RFC1533_VENDOR_PXE_OPT128,
105         RFC1533_VENDOR_PXE_OPT129,
106         RFC1533_VENDOR_PXE_OPT130,
107         RFC1533_VENDOR_PXE_OPT131,
108         RFC1533_VENDOR_PXE_OPT132,
109         RFC1533_VENDOR_PXE_OPT133,
110         RFC1533_VENDOR_PXE_OPT134,
111         RFC1533_VENDOR_PXE_OPT135,
112 #endif /* PXE_DHCP_STRICT */
113         RFC1533_DNS
114 };
115 static const unsigned char dhcprequest [] = {
116         RFC2132_MSG_TYPE,1,DHCPREQUEST,
117         RFC2132_SRV_ID,4,0,0,0,0,
118         RFC2132_REQ_ADDR,4,0,0,0,0,
119         RFC2132_MAX_SIZE,2,     /* request as much as we can */
120         ETH_MAX_MTU / 256, ETH_MAX_MTU % 256,
121 #ifdef PXE_DHCP_STRICT
122         RFC3679_PXE_CLIENT_UUID,RFC3679_PXE_CLIENT_UUID_LENGTH,RFC3679_PXE_CLIENT_UUID_DEFAULT,
123         RFC3679_PXE_CLIENT_ARCH,RFC3679_PXE_CLIENT_ARCH_LENGTH,RFC3679_PXE_CLIENT_ARCH_IAX86PC,
124         RFC3679_PXE_CLIENT_NDI, RFC3679_PXE_CLIENT_NDI_LENGTH, RFC3679_PXE_CLIENT_NDI_21,
125         RFC2132_VENDOR_CLASS_ID,RFC2132_VENDOR_CLASS_ID_PXE_LENGTH,RFC2132_VENDOR_CLASS_ID_PXE,
126 #else
127         RFC2132_VENDOR_CLASS_ID,13,'E','t','h','e','r','b','o','o','t',
128         '-',VERSION_MAJOR+'0','.',VERSION_MINOR+'0',
129 #endif /* PXE_DHCP_STRICT */
130 #ifdef DHCP_CLIENT_ID
131         /* Client ID Option */
132         RFC2132_CLIENT_ID, ( DHCP_CLIENT_ID_LEN + 1 ),
133         DHCP_CLIENT_ID_TYPE, DHCP_CLIENT_ID,
134 #endif /* DHCP_CLIENT_ID */
135 #ifdef DHCP_USER_CLASS
136         /* User Class Option */
137         RFC3004_USER_CLASS, DHCP_USER_CLASS_LEN, DHCP_USER_CLASS,
138 #endif /* DHCP_USER_CLASS */
139         /* request parameters */
140         RFC2132_PARAM_LIST,
141 #define DHCPREQUEST_PARAMS_BASE 5  
142 #ifdef  PXE_DHCP_STRICT
143 #define DHCPREQUEST_PARAMS_PXE 1
144 #define DHCPREQUEST_PARAMS_VENDOR_PXE 8
145 #define DHCPREQUEST_PARAMS_VENDOR_EB 0
146 #else
147 #define DHCPREQUEST_PARAMS_PXE 0
148 #define DHCPREQUEST_PARAMS_VENDOR_PXE 0
149 #define DHCPREQUEST_PARAMS_VENDOR_EB 4
150 #endif /* PXE_DHCP_STRICT */
151 #ifdef  IMAGE_FREEBSD
152 #define DHCPREQUEST_PARAMS_FREEBSD 2
153 #else
154 #define DHCPREQUEST_PARAMS_FREEBSD 0
155 #endif /* IMAGE_FREEBSD */
156 #define DHCPREQUEST_PARAMS_DNS     1
157         ( DHCPREQUEST_PARAMS_BASE +
158           DHCPREQUEST_PARAMS_PXE +
159           DHCPREQUEST_PARAMS_VENDOR_PXE +
160           DHCPREQUEST_PARAMS_VENDOR_EB +
161           DHCPREQUEST_PARAMS_DNS +
162           DHCPREQUEST_PARAMS_FREEBSD ),
163         /* 5 Standard parameters */
164         RFC1533_NETMASK,
165         RFC1533_GATEWAY,
166         RFC1533_HOSTNAME,
167         RFC1533_VENDOR,
168         RFC1533_ROOTPATH,       /* only passed to the booted image */
169 #ifndef PXE_DHCP_STRICT
170         /* 4 Etherboot vendortags */
171         RFC1533_VENDOR_MAGIC,
172         RFC1533_VENDOR_ADDPARM,
173         RFC1533_VENDOR_ETHDEV,
174         RFC1533_VENDOR_ETHERBOOT_ENCAP,
175 #endif /* ! PXE_DHCP_STRICT */
176 #ifdef  IMAGE_FREEBSD
177         /* 2 FreeBSD options */
178         RFC1533_VENDOR_HOWTO,
179         RFC1533_VENDOR_KERNEL_ENV,
180 #endif
181         /* 1 DNS option */
182         RFC1533_DNS,
183 #ifdef  PXE_DHCP_STRICT
184         RFC2132_VENDOR_CLASS_ID,
185         RFC1533_VENDOR_PXE_OPT128,
186         RFC1533_VENDOR_PXE_OPT129,
187         RFC1533_VENDOR_PXE_OPT130,
188         RFC1533_VENDOR_PXE_OPT131,
189         RFC1533_VENDOR_PXE_OPT132,
190         RFC1533_VENDOR_PXE_OPT133,
191         RFC1533_VENDOR_PXE_OPT134,
192         RFC1533_VENDOR_PXE_OPT135,
193 #endif /* PXE_DHCP_STRICT */
194 };
195 #ifdef PXE_EXPORT
196 static const unsigned char proxydhcprequest [] = {
197         RFC2132_MSG_TYPE,1,DHCPREQUEST,
198         RFC2132_MAX_SIZE,2,     /* request as much as we can */
199         ETH_MAX_MTU / 256, ETH_MAX_MTU % 256,
200 #ifdef  PXE_DHCP_STRICT
201         RFC3679_PXE_CLIENT_UUID,RFC3679_PXE_CLIENT_UUID_LENGTH,RFC3679_PXE_CLIENT_UUID_DEFAULT,
202         RFC3679_PXE_CLIENT_ARCH,RFC3679_PXE_CLIENT_ARCH_LENGTH,RFC3679_PXE_CLIENT_ARCH_IAX86PC,
203         RFC3679_PXE_CLIENT_NDI, RFC3679_PXE_CLIENT_NDI_LENGTH, RFC3679_PXE_CLIENT_NDI_21,
204         RFC2132_VENDOR_CLASS_ID,RFC2132_VENDOR_CLASS_ID_PXE_LENGTH,RFC2132_VENDOR_CLASS_ID_PXE,
205 #endif /* PXE_DHCP_STRICT */
206 };
207 #endif
208
209 #ifdef  REQUIRE_VCI_ETHERBOOT
210 int     vci_etherboot;
211 #endif
212 #endif  /* NO_DHCP_SUPPORT */
213
214 #ifdef RARP_NOT_BOOTP
215 static int rarp(void);
216 #else
217 static int bootp(void);
218 #endif
219
220
221 /*
222  * Find out what our boot parameters are
223  */
224 static int nic_configure ( struct type_dev *type_dev ) {
225         struct nic *nic = ( struct nic * ) type_dev;
226         int server_found;
227
228         if ( ! nic->nic_op->connect ( nic ) ) {
229                 printf ( "No connection to network\n" );
230                 return 0;
231         }
232
233         /* Find a server to get BOOTP reply from */
234 #ifdef  RARP_NOT_BOOTP
235         printf("Searching for server (RARP)...");
236 #else
237 #ifndef NO_DHCP_SUPPORT
238         printf("Searching for server (DHCP)...");
239 #else
240         printf("Searching for server (BOOTP)...");
241 #endif
242 #endif
243
244 #ifdef  RARP_NOT_BOOTP
245         server_found = rarp();
246 #else
247         server_found = bootp();
248 #endif
249         if (!server_found) {
250                 printf("No Server found\n");
251                 return 0;
252         }
253
254         printf("\nMe: %@", arptable[ARP_CLIENT].ipaddr.s_addr );
255 #ifndef NO_DHCP_SUPPORT
256         printf(", DHCP: %@", dhcp_server );
257 #ifdef PXE_EXPORT       
258         if (arptable[ARP_PROXYDHCP].ipaddr.s_addr)
259                 printf(" (& %@)",
260                        arptable[ARP_PROXYDHCP].ipaddr.s_addr);
261 #endif /* PXE_EXPORT */
262 #endif /* ! NO_DHCP_SUPPORT */
263         printf(", TFTP: %@", arptable[ARP_SERVER].ipaddr.s_addr);
264         if (BOOTP_DATA_ADDR->bootp_reply.bp_giaddr.s_addr)
265                 printf(", Relay: %@",
266                         BOOTP_DATA_ADDR->bootp_reply.bp_giaddr.s_addr);
267         if (arptable[ARP_GATEWAY].ipaddr.s_addr)
268                 printf(", Gateway %@", arptable[ARP_GATEWAY].ipaddr.s_addr);
269         if (arptable[ARP_NAMESERVER].ipaddr.s_addr)
270                 printf(", Nameserver %@", arptable[ARP_NAMESERVER].ipaddr.s_addr);
271         putchar('\n');
272
273 #ifdef  MDEBUG
274         printf("\n=>>"); getchar();
275 #endif
276
277         return 1;
278 }
279
280
281 /*
282  * Download a file from the specified URL into the specified buffer
283  *
284  */
285 int download_url ( char *url, struct buffer *buffer ) {
286         struct protocol *proto;
287         struct sockaddr_in server;
288         char *filename;
289         
290         printf ( "Loading %s\n", url );
291
292         /* Parse URL */
293         if ( ! parse_url ( url, &proto, &server, &filename ) ) {
294                 DBG ( "Unusable URL %s\n", url );
295                 return 0;
296         }
297         
298         /* Call protocol's method to download the file */
299         return proto->load ( url, &server, filename, buffer );
300 }
301
302
303
304
305 /**************************************************************************
306 LOAD - Try to get booted
307 **************************************************************************/
308 static int nic_load ( struct type_dev *type_dev, struct buffer *buffer ) {
309         char    *kernel;
310
311         /* Now use TFTP to load file */
312         kernel = KERNEL_BUF[0] == '\0' ? 
313 #ifdef  DEFAULT_BOOTFILE
314                 DEFAULT_BOOTFILE
315 #else
316                 NULL
317 #endif
318                 : KERNEL_BUF;
319         if ( kernel ) {
320                 return download_url ( kernel, buffer );
321         } else {        
322                 printf("No filename\n");
323         }
324         return 0;
325 }
326
327 void nic_disable ( struct nic *nic __unused ) {
328 #ifdef MULTICAST_LEVEL2
329         int i;
330         for(i = 0; i < MAX_IGMP; i++) {
331                 leave_group(i);
332         }
333 #endif
334 }
335
336 static char * nic_describe_device ( struct type_dev *type_dev ) {
337         struct nic *nic = ( struct nic * ) type_dev;
338         static char nic_description[] = "MAC 00:00:00:00:00:00";
339         
340         sprintf ( nic_description + 4, "%!", nic->node_addr );
341         return nic_description;
342 }
343
344 /* 
345  * Device operations tables
346  *
347  */
348 struct type_driver nic_driver = {
349         .name                   = "NIC",
350         .type_dev               = ( struct type_dev * ) &nic,
351         .describe_device        = nic_describe_device,
352         .configure              = nic_configure,
353         .load                   = nic_load,
354 };
355
356 /* Careful.  We need an aligned buffer to avoid problems on machines
357  * that care about alignment.  To trivally align the ethernet data
358  * (the ip hdr and arp requests) we offset the packet by 2 bytes.
359  * leaving the ethernet data 16 byte aligned.  Beyond this
360  * we use memmove but this makes the common cast simple and fast.
361  */
362 static char     packet[ETH_FRAME_LEN + ETH_DATA_ALIGN] __aligned;
363
364 struct nic nic = {
365         .node_addr = arptable[ARP_CLIENT].node,
366         .packet = packet + ETH_DATA_ALIGN,
367 };
368
369
370
371 int dummy_connect ( struct nic *nic __unused ) {
372         return 1;
373 }
374
375 void dummy_irq ( struct nic *nic __unused, irq_action_t irq_action __unused ) {
376         return;
377 }
378
379 /**************************************************************************
380 DEFAULT_NETMASK - Return default netmask for IP address
381 **************************************************************************/
382 static inline unsigned long default_netmask(void)
383 {
384         int net = ntohl(arptable[ARP_CLIENT].ipaddr.s_addr) >> 24;
385         if (net <= 127)
386                 return(htonl(0xff000000));
387         else if (net < 192)
388                 return(htonl(0xffff0000));
389         else
390                 return(htonl(0xffffff00));
391 }
392
393 /**************************************************************************
394 IP_TRANSMIT - Send an IP datagram
395 **************************************************************************/
396 static int await_arp(int ival, void *ptr,
397         unsigned short ptype, struct iphdr *ip __unused, struct udphdr *udp __unused,
398         struct tcphdr *tcp __unused)
399 {
400         struct  arprequest *arpreply;
401         if (ptype != ETH_P_ARP)
402                 return 0;
403         if (nic.packetlen < ETH_HLEN + sizeof(struct arprequest))
404                 return 0;
405         arpreply = (struct arprequest *)&nic.packet[ETH_HLEN];
406
407         if (arpreply->opcode != htons(ARP_REPLY)) 
408                 return 0;
409         if (memcmp(arpreply->sipaddr, ptr, sizeof(in_addr)) != 0)
410                 return 0;
411         memcpy(arptable[ival].node, arpreply->shwaddr, ETH_ALEN);
412         return 1;
413 }
414
415 int ip_transmit(int len, const void *buf)
416 {
417         unsigned long destip;
418         struct iphdr *ip;
419         struct arprequest arpreq;
420         int arpentry, i;
421         int retry;
422
423         ip = (struct iphdr *)buf;
424         destip = ip->dest.s_addr;
425         if (destip == IP_BROADCAST) {
426                 eth_transmit(broadcast, ETH_P_IP, len, buf);
427         } else if ((destip & htonl(MULTICAST_MASK)) == htonl(MULTICAST_NETWORK)) {
428                 unsigned char multicast[6];
429                 unsigned long hdestip;
430                 hdestip = ntohl(destip);
431                 multicast[0] = 0x01;
432                 multicast[1] = 0x00;
433                 multicast[2] = 0x5e;
434                 multicast[3] = (hdestip >> 16) & 0x7;
435                 multicast[4] = (hdestip >> 8) & 0xff;
436                 multicast[5] = hdestip & 0xff;
437                 eth_transmit(multicast, ETH_P_IP, len, buf);
438         } else {
439                 if (((destip & netmask) !=
440                         (arptable[ARP_CLIENT].ipaddr.s_addr & netmask)) &&
441                         arptable[ARP_GATEWAY].ipaddr.s_addr)
442                                 destip = arptable[ARP_GATEWAY].ipaddr.s_addr;
443                 for(arpentry = 0; arpentry<MAX_ARP; arpentry++)
444                         if (arptable[arpentry].ipaddr.s_addr == destip) break;
445                 if (arpentry == MAX_ARP) {
446                         printf("%@ is not in my arp table!\n", destip);
447                         return(0);
448                 }
449                 for (i = 0; i < ETH_ALEN; i++)
450                         if (arptable[arpentry].node[i])
451                                 break;
452                 if (i == ETH_ALEN) {    /* Need to do arp request */
453                         arpreq.hwtype = htons(1);
454                         arpreq.protocol = htons(IP);
455                         arpreq.hwlen = ETH_ALEN;
456                         arpreq.protolen = 4;
457                         arpreq.opcode = htons(ARP_REQUEST);
458                         memcpy(arpreq.shwaddr, arptable[ARP_CLIENT].node, ETH_ALEN);
459                         memcpy(arpreq.sipaddr, &arptable[ARP_CLIENT].ipaddr, sizeof(in_addr));
460                         memset(arpreq.thwaddr, 0, ETH_ALEN);
461                         memcpy(arpreq.tipaddr, &destip, sizeof(in_addr));
462                         for (retry = 1; retry <= MAX_ARP_RETRIES; retry++) {
463                                 long timeout;
464                                 eth_transmit(broadcast, ETH_P_ARP, sizeof(arpreq),
465                                         &arpreq);
466                                 timeout = rfc2131_sleep_interval(TIMEOUT, retry);
467                                 if (await_reply(await_arp, arpentry,
468                                         arpreq.tipaddr, timeout)) goto xmit;
469                         }
470                         return(0);
471                 }
472 xmit:
473                 eth_transmit(arptable[arpentry].node, ETH_P_IP, len, buf);
474         }
475         return 1;
476 }
477
478 void build_ip_hdr(unsigned long destip, int ttl, int protocol, int option_len,
479         int len, const void *buf)
480 {
481         struct iphdr *ip;
482         ip = (struct iphdr *)buf;
483         ip->verhdrlen = 0x45;
484         ip->verhdrlen += (option_len/4);
485         ip->service = 0;
486         ip->len = htons(len);
487         ip->ident = 0;
488         ip->frags = 0; /* Should we set don't fragment? */
489         ip->ttl = ttl;
490         ip->protocol = protocol;
491         ip->chksum = 0;
492         ip->src.s_addr = arptable[ARP_CLIENT].ipaddr.s_addr;
493         ip->dest.s_addr = destip;
494         ip->chksum = ipchksum(buf, sizeof(struct iphdr) + option_len);
495 }
496
497 void build_udp_hdr(unsigned long destip, 
498         unsigned int srcsock, unsigned int destsock, int ttl,
499         int len, const void *buf)
500 {
501         struct iphdr *ip;
502         struct udphdr *udp;
503         ip = (struct iphdr *)buf;
504         build_ip_hdr(destip, ttl, IP_UDP, 0, len, buf);
505         udp = (struct udphdr *)((char *)buf + sizeof(struct iphdr));
506         udp->src = htons(srcsock);
507         udp->dest = htons(destsock);
508         udp->len = htons(len - sizeof(struct iphdr));
509         udp->chksum = 0;
510         if ((udp->chksum = tcpudpchksum(ip)) == 0)
511                 udp->chksum = 0xffff;
512 }
513
514 /**************************************************************************
515 UDP_TRANSMIT - Send an UDP datagram
516 **************************************************************************/
517 int udp_transmit(unsigned long destip, unsigned int srcsock,
518         unsigned int destsock, int len, const void *buf)
519 {
520         build_udp_hdr(destip, srcsock, destsock, 60, len, buf);
521         return ip_transmit(len, buf);
522 }
523
524
525 /**************************************************************************
526 QDRAIN - clear the nic's receive queue
527 **************************************************************************/
528 static int await_qdrain(int ival __unused, void *ptr __unused,
529         unsigned short ptype __unused, 
530         struct iphdr *ip __unused, struct udphdr *udp __unused,
531         struct tcphdr *tcp __unused)
532 {
533         return 0;
534 }
535
536 void rx_qdrain(void)
537 {
538         /* Clear out the Rx queue first.  It contains nothing of interest,
539          * except possibly ARP requests from the DHCP/TFTP server.  We use
540          * polling throughout Etherboot, so some time may have passed since we
541          * last polled the receive queue, which may now be filled with
542          * broadcast packets.  This will cause the reply to the packets we are
543          * about to send to be lost immediately.  Not very clever.  */
544         await_reply(await_qdrain, 0, NULL, 0);
545 }
546
547 #ifdef  RARP_NOT_BOOTP
548 /**************************************************************************
549 RARP - Get my IP address and load information
550 **************************************************************************/
551 static int await_rarp(int ival, void *ptr,
552         unsigned short ptype, struct iphdr *ip, struct udphdr *udp,
553         struct tcphdr *tcp __unused)
554 {
555         struct arprequest *arpreply;
556         if (ptype != ETH_P_RARP)
557                 return 0;
558         if (nic.packetlen < ETH_HLEN + sizeof(struct arprequest))
559                 return 0;
560         arpreply = (struct arprequest *)&nic.packet[ETH_HLEN];
561         if (arpreply->opcode != htons(RARP_REPLY))
562                 return 0;
563         if ((arpreply->opcode == htons(RARP_REPLY)) &&
564                 (memcmp(arpreply->thwaddr, ptr, ETH_ALEN) == 0)) {
565                 memcpy(arptable[ARP_SERVER].node, arpreply->shwaddr, ETH_ALEN);
566                 memcpy(&arptable[ARP_SERVER].ipaddr, arpreply->sipaddr, sizeof(in_addr));
567                 memcpy(&arptable[ARP_CLIENT].ipaddr, arpreply->tipaddr, sizeof(in_addr));
568                 return 1;
569         }
570         return 0;
571 }
572
573 static int rarp(void)
574 {
575         int retry;
576
577         /* arp and rarp requests share the same packet structure. */
578         struct arprequest rarpreq;
579
580         memset(&rarpreq, 0, sizeof(rarpreq));
581
582         rarpreq.hwtype = htons(1);
583         rarpreq.protocol = htons(IP);
584         rarpreq.hwlen = ETH_ALEN;
585         rarpreq.protolen = 4;
586         rarpreq.opcode = htons(RARP_REQUEST);
587         memcpy(&rarpreq.shwaddr, arptable[ARP_CLIENT].node, ETH_ALEN);
588         /* sipaddr is already zeroed out */
589         memcpy(&rarpreq.thwaddr, arptable[ARP_CLIENT].node, ETH_ALEN);
590         /* tipaddr is already zeroed out */
591
592         for (retry = 0; retry < MAX_ARP_RETRIES; ++retry) {
593                 long timeout;
594                 eth_transmit(broadcast, ETH_P_RARP, sizeof(rarpreq), &rarpreq);
595
596                 timeout = rfc2131_sleep_interval(TIMEOUT, retry);
597                 if (await_reply(await_rarp, 0, rarpreq.shwaddr, timeout))
598                         break;
599         }
600
601         if (retry < MAX_ARP_RETRIES) {
602                 (void)sprintf(KERNEL_BUF, DEFAULT_KERNELPATH, arptable[ARP_CLIENT].ipaddr);
603
604                 return (1);
605         }
606         return (0);
607 }
608
609 #else
610
611 /**************************************************************************
612 BOOTP - Get my IP address and load information
613 **************************************************************************/
614 static int await_bootp(int ival __unused, void *ptr __unused,
615         unsigned short ptype __unused, struct iphdr *ip __unused, 
616         struct udphdr *udp, struct tcphdr *tcp __unused)
617 {
618         struct  bootp_t *bootpreply;
619         if (!udp) {
620                 return 0;
621         }
622         bootpreply = (struct bootp_t *)&nic.packet[ETH_HLEN + 
623                 sizeof(struct iphdr) + sizeof(struct udphdr)];
624         if (nic.packetlen < ETH_HLEN + sizeof(struct iphdr) + 
625                 sizeof(struct udphdr) + 
626 #ifdef NO_DHCP_SUPPORT
627                 sizeof(struct bootp_t)
628 #else
629                 sizeof(struct bootp_t) - DHCP_OPT_LEN
630 #endif  /* NO_DHCP_SUPPORT */
631                 ) {
632                 return 0;
633         }
634         if (udp->dest != htons(BOOTP_CLIENT))
635                 return 0;
636         if (bootpreply->bp_op != BOOTP_REPLY)
637                 return 0;
638         if (bootpreply->bp_xid != xid)
639                 return 0;
640         if (memcmp(&bootpreply->bp_siaddr, &zeroIP, sizeof(in_addr)) == 0)
641                 return 0;
642         if ((memcmp(broadcast, bootpreply->bp_hwaddr, ETH_ALEN) != 0) &&
643                 (memcmp(arptable[ARP_CLIENT].node, bootpreply->bp_hwaddr, ETH_ALEN) != 0)) {
644                 return 0;
645         }
646         if ( bootpreply->bp_siaddr.s_addr ) {
647                 arptable[ARP_SERVER].ipaddr.s_addr = bootpreply->bp_siaddr.s_addr;
648                 memset(arptable[ARP_SERVER].node, 0, ETH_ALEN);  /* Kill arp */
649         }
650         if ( bootpreply->bp_giaddr.s_addr ) {
651                 arptable[ARP_GATEWAY].ipaddr.s_addr = bootpreply->bp_giaddr.s_addr;
652                 memset(arptable[ARP_GATEWAY].node, 0, ETH_ALEN);  /* Kill arp */
653         }
654         if (bootpreply->bp_yiaddr.s_addr) {
655                 /* Offer with an IP address */
656                 arptable[ARP_CLIENT].ipaddr.s_addr = bootpreply->bp_yiaddr.s_addr;
657 #ifndef NO_DHCP_SUPPORT
658                 dhcp_addr.s_addr = bootpreply->bp_yiaddr.s_addr;
659 #endif  /* NO_DHCP_SUPPORT */
660                 netmask = default_netmask();
661                 /* bootpreply->bp_file will be copied to KERNEL_BUF in the memcpy */
662                 memcpy((char *)BOOTP_DATA_ADDR, (char *)bootpreply, sizeof(struct bootpd_t));
663                 decode_rfc1533(BOOTP_DATA_ADDR->bootp_reply.bp_vend, 0,
664 #ifdef  NO_DHCP_SUPPORT
665                                BOOTP_VENDOR_LEN + MAX_BOOTP_EXTLEN, 
666 #else
667                                DHCP_OPT_LEN + MAX_BOOTP_EXTLEN, 
668 #endif  /* NO_DHCP_SUPPORT */
669                                1);
670 #ifdef PXE_EXPORT
671         } else {
672                 /* Offer without an IP address - use as ProxyDHCP server */
673                 arptable[ARP_PROXYDHCP].ipaddr.s_addr = bootpreply->bp_siaddr.s_addr;
674                 memset(arptable[ARP_PROXYDHCP].node, 0, ETH_ALEN);       /* Kill arp */
675                 /* Grab only the bootfile name from a ProxyDHCP packet */
676                 memcpy(KERNEL_BUF, bootpreply->bp_file, sizeof(KERNEL_BUF));
677 #endif /* PXE_EXPORT */
678         }
679 #ifdef  REQUIRE_VCI_ETHERBOOT
680         if (!vci_etherboot)
681                 return (0);
682 #endif
683         return(1);
684 }
685
686 static int bootp(void)
687 {
688         int retry;
689 #ifndef NO_DHCP_SUPPORT
690         int reqretry;
691 #endif  /* NO_DHCP_SUPPORT */
692         struct bootpip_t ip;
693         unsigned long  starttime;
694         unsigned char *bp_vend;
695
696 #ifndef NO_DHCP_SUPPORT
697         * ( ( struct dhcp_dev_id * ) &dhcp_machine_info[4] ) = nic.dhcp_dev_id;
698 #endif  /* NO_DHCP_SUPPORT */
699         memset(&ip, 0, sizeof(struct bootpip_t));
700         ip.bp.bp_op = BOOTP_REQUEST;
701         ip.bp.bp_htype = 1;
702         ip.bp.bp_hlen = ETH_ALEN;
703         starttime = currticks();
704         /* Use lower 32 bits of node address, more likely to be
705            distinct than the time since booting */
706         memcpy(&xid, &arptable[ARP_CLIENT].node[2], sizeof(xid));
707         ip.bp.bp_xid = xid += htonl(starttime);
708         memcpy(ip.bp.bp_hwaddr, arptable[ARP_CLIENT].node, ETH_ALEN);
709 #ifdef  NO_DHCP_SUPPORT
710         memcpy(ip.bp.bp_vend, rfc1533_cookie, 5); /* request RFC-style options */
711 #else
712         memcpy(ip.bp.bp_vend, rfc1533_cookie, sizeof rfc1533_cookie); /* request RFC-style options */
713         memcpy(ip.bp.bp_vend + sizeof rfc1533_cookie, dhcpdiscover, sizeof dhcpdiscover);
714         /* Append machine_info to end, in encapsulated option */
715         bp_vend = ip.bp.bp_vend + sizeof rfc1533_cookie + sizeof dhcpdiscover;
716         memcpy(bp_vend, dhcp_machine_info, DHCP_MACHINE_INFO_SIZE);
717         bp_vend += DHCP_MACHINE_INFO_SIZE;
718         *bp_vend++ = RFC1533_END;
719 #endif  /* NO_DHCP_SUPPORT */
720
721         for (retry = 0; retry < MAX_BOOTP_RETRIES; ) {
722                 uint8_t my_hwaddr[ETH_ALEN];
723                 unsigned long stop_time;
724                 long remaining_time;
725
726                 rx_qdrain();
727
728                 /* Kill arptable to avoid keeping stale entries */
729                 memcpy ( my_hwaddr, arptable[ARP_CLIENT].node, ETH_ALEN );
730                 memset ( arptable, 0, sizeof(arptable) );
731                 memcpy ( arptable[ARP_CLIENT].node, my_hwaddr, ETH_ALEN );
732
733                 udp_transmit(IP_BROADCAST, BOOTP_CLIENT, BOOTP_SERVER,
734                         sizeof(struct bootpip_t), &ip);
735                 remaining_time = rfc2131_sleep_interval(BOOTP_TIMEOUT, retry++);
736                 stop_time = currticks() + remaining_time;
737 #ifdef  NO_DHCP_SUPPORT
738                 if (await_reply(await_bootp, 0, NULL, remaining_time))
739                         return(1);
740 #else
741                 while ( remaining_time > 0 ) {
742                         if (await_reply(await_bootp, 0, NULL, remaining_time)){
743                         }
744                         remaining_time = stop_time - currticks();
745                 }
746                 if ( ! arptable[ARP_CLIENT].ipaddr.s_addr ) {
747                         printf("No IP address\n");
748                         continue;
749                 }
750                 /* If not a DHCPOFFER then must be just a BOOTP reply,
751                  * be backward compatible with BOOTP then */
752                 if (dhcp_reply != DHCPOFFER)
753                         return(1);
754                 dhcp_reply = 0;
755                 /* Construct the DHCPREQUEST packet */
756                 memcpy(ip.bp.bp_vend, rfc1533_cookie, sizeof rfc1533_cookie);
757                 memcpy(ip.bp.bp_vend + sizeof rfc1533_cookie, dhcprequest, sizeof dhcprequest);
758                 /* Beware: the magic numbers 9 and 15 depend on
759                    the layout of dhcprequest */
760                 memcpy(&ip.bp.bp_vend[9], &dhcp_server, sizeof(in_addr));
761                 memcpy(&ip.bp.bp_vend[15], &dhcp_addr, sizeof(in_addr));
762                 bp_vend = ip.bp.bp_vend + sizeof rfc1533_cookie + sizeof dhcprequest;
763                 /* Append machine_info to end, in encapsulated option */
764                 memcpy(bp_vend, dhcp_machine_info, DHCP_MACHINE_INFO_SIZE);
765                 bp_vend += DHCP_MACHINE_INFO_SIZE;
766                 *bp_vend++ = RFC1533_END;
767                 for (reqretry = 0; reqretry < MAX_BOOTP_RETRIES; ) {
768                         unsigned long timeout;
769
770                         udp_transmit(IP_BROADCAST, BOOTP_CLIENT, BOOTP_SERVER,
771                                      sizeof(struct bootpip_t), &ip);
772                         dhcp_reply=0;
773                         timeout = rfc2131_sleep_interval(TIMEOUT, reqretry++);
774                         if (!await_reply(await_bootp, 0, NULL, timeout))
775                                 continue;
776                         if (dhcp_reply != DHCPACK)
777                                 continue;
778                         dhcp_reply = 0;
779 #ifdef PXE_EXPORT                       
780                         if ( arptable[ARP_PROXYDHCP].ipaddr.s_addr ) {
781                                 /* Construct the ProxyDHCPREQUEST packet */
782                                 memcpy(ip.bp.bp_vend, rfc1533_cookie, sizeof rfc1533_cookie);
783                                 memcpy(ip.bp.bp_vend + sizeof rfc1533_cookie, proxydhcprequest, sizeof proxydhcprequest);
784                                 for (reqretry = 0; reqretry < MAX_BOOTP_RETRIES; ) {
785                                         printf ( "\nSending ProxyDHCP request to %@...", arptable[ARP_PROXYDHCP].ipaddr.s_addr);
786                                         udp_transmit(arptable[ARP_PROXYDHCP].ipaddr.s_addr, BOOTP_CLIENT, PROXYDHCP_SERVER,
787                                                      sizeof(struct bootpip_t), &ip);
788                                         timeout = rfc2131_sleep_interval(TIMEOUT, reqretry++);
789                                         if (await_reply(await_bootp, 0, NULL, timeout)) {
790                                                 break;
791                                         }
792                                 }
793                         }
794 #endif /* PXE_EXPORT */
795                         return(1);
796                 }
797 #endif  /* NO_DHCP_SUPPORT */
798                 ip.bp.bp_secs = htons((currticks()-starttime)/TICKS_PER_SEC);
799         }
800         return(0);
801 }
802 #endif  /* RARP_NOT_BOOTP */
803
804 uint16_t tcpudpchksum(struct iphdr *ip)
805 {
806         struct udp_pseudo_hdr pseudo;
807         uint16_t checksum;
808
809         /* Compute the pseudo header */
810         pseudo.src.s_addr  = ip->src.s_addr;
811         pseudo.dest.s_addr = ip->dest.s_addr;
812         pseudo.unused      = 0;
813         pseudo.protocol    = ip->protocol;
814         pseudo.len         = htons(ntohs(ip->len) - sizeof(struct iphdr));
815
816         /* Sum the pseudo header */
817         checksum = ipchksum(&pseudo, 12);
818
819         /* Sum the rest of the tcp/udp packet */
820         checksum = add_ipchksums(12, checksum, ipchksum(ip + 1,
821                                  ntohs(ip->len) - sizeof(struct iphdr)));
822         return checksum;
823 }
824
825
826 #include "proto_eth_slow.c"
827
828
829 /**************************************************************************
830 AWAIT_REPLY - Wait until we get a response for our request
831 ************f**************************************************************/
832 int await_reply(reply_t reply, int ival, void *ptr, long timeout)
833 {
834         unsigned long time, now;
835         struct  iphdr *ip;
836         unsigned iplen = 0;
837         struct  udphdr *udp;
838         struct  tcphdr *tcp;
839         unsigned short ptype;
840         int result;
841
842         time = timeout + currticks();
843         /* The timeout check is done below.  The timeout is only checked if
844          * there is no packet in the Rx queue.  This assumes that eth_poll()
845          * needs a negligible amount of time.  
846          */
847         for (;;) {
848                 now = currticks();
849                 background_send(now);
850                 send_eth_slow_reports(now);
851                 result = eth_poll(1);
852                 if (result == 0) {
853                         /* We don't have anything */
854                 
855                         /* Check for abort key only if the Rx queue is empty -
856                          * as long as we have something to process, don't
857                          * assume that something failed.  It is unlikely that
858                          * we have no processing time left between packets.  */
859                         poll_interruptions();
860                         /* Do the timeout after at least a full queue walk.  */
861                         if ((timeout == 0) || (currticks() > time)) {
862                                 break;
863                         }
864                         continue;
865                 }
866         
867                 /* We have something! */
868
869                 /* Find the Ethernet packet type */
870                 if (nic.packetlen >= ETH_HLEN) {
871                         ptype = ((unsigned short) nic.packet[12]) << 8
872                                 | ((unsigned short) nic.packet[13]);
873                 } else continue; /* what else could we do with it? */
874                 /* Verify an IP header */
875                 ip = 0;
876                 if ((ptype == ETH_P_IP) && (nic.packetlen >= ETH_HLEN + sizeof(struct iphdr))) {
877                         unsigned ipoptlen;
878                         ip = (struct iphdr *)&nic.packet[ETH_HLEN];
879                         if ((ip->verhdrlen < 0x45) || (ip->verhdrlen > 0x4F)) 
880                                 continue;
881                         iplen = (ip->verhdrlen & 0xf) * 4;
882                         if (ipchksum(ip, iplen) != 0)
883                                 continue;
884                         if (ip->frags & htons(0x3FFF)) {
885                                 static int warned_fragmentation = 0;
886                                 if (!warned_fragmentation) {
887                                         printf("ALERT: got a fragmented packet - reconfigure your server\n");
888                                         warned_fragmentation = 1;
889                                 }
890                                 continue;
891                         }
892                         if (ntohs(ip->len) > ETH_MAX_MTU)
893                                 continue;
894
895                         ipoptlen = iplen - sizeof(struct iphdr);
896                         if (ipoptlen) {
897                                 /* Delete the ip options, to guarantee
898                                  * good alignment, and make etherboot simpler.
899                                  */
900                                 memmove(&nic.packet[ETH_HLEN + sizeof(struct iphdr)], 
901                                         &nic.packet[ETH_HLEN + iplen],
902                                         nic.packetlen - ipoptlen);
903                                 nic.packetlen -= ipoptlen;
904                         }
905                 }
906                 udp = 0;
907                 if (ip && (ip->protocol == IP_UDP) && 
908                         (nic.packetlen >= 
909                         ETH_HLEN + sizeof(struct iphdr) + sizeof(struct udphdr))) {
910                         udp = (struct udphdr *)&nic.packet[ETH_HLEN + sizeof(struct iphdr)];
911
912                         /* Make certain we have a reasonable packet length */
913                         if (ntohs(udp->len) > (ntohs(ip->len) - iplen))
914                                 continue;
915
916                         if (udp->chksum && tcpudpchksum(ip)) {
917                                 printf("UDP checksum error\n");
918                                 continue;
919                         }
920                 }
921                 tcp = 0;
922                 if (ip && (ip->protocol == IP_TCP) &&
923                     (nic.packetlen >=
924                      ETH_HLEN + sizeof(struct iphdr) + sizeof(struct tcphdr))){
925                         tcp = (struct tcphdr *)&nic.packet[ETH_HLEN +
926                                                          sizeof(struct iphdr)];
927                         /* Make certain we have a reasonable packet length */
928                         if (((ntohs(tcp->ctrl) >> 10) & 0x3C) >
929                             ntohs(ip->len) - (int)iplen)
930                                 continue;
931                         if (tcpudpchksum(ip)) {
932                                 printf("TCP checksum error\n");
933                                 continue;
934                         }
935
936                 }
937                 result = reply(ival, ptr, ptype, ip, udp, tcp);
938                 if (result > 0) {
939                         return result;
940                 }
941                 
942                 /* If it isn't a packet the upper layer wants see if there is a default
943                  * action.  This allows us reply to arp, igmp, and lacp queries.
944                  */
945                 if ((ptype == ETH_P_ARP) &&
946                         (nic.packetlen >= ETH_HLEN + sizeof(struct arprequest))) {
947                         struct  arprequest *arpreply;
948                         unsigned long tmp;
949                 
950                         arpreply = (struct arprequest *)&nic.packet[ETH_HLEN];
951                         memcpy(&tmp, arpreply->tipaddr, sizeof(in_addr));
952                         if ((arpreply->opcode == htons(ARP_REQUEST)) &&
953                                 (tmp == arptable[ARP_CLIENT].ipaddr.s_addr)) {
954                                 arpreply->opcode = htons(ARP_REPLY);
955                                 memcpy(arpreply->tipaddr, arpreply->sipaddr, sizeof(in_addr));
956                                 memcpy(arpreply->thwaddr, arpreply->shwaddr, ETH_ALEN);
957                                 memcpy(arpreply->sipaddr, &arptable[ARP_CLIENT].ipaddr, sizeof(in_addr));
958                                 memcpy(arpreply->shwaddr, arptable[ARP_CLIENT].node, ETH_ALEN);
959                                 eth_transmit(arpreply->thwaddr, ETH_P_ARP,
960                                         sizeof(struct  arprequest),
961                                         arpreply);
962 #ifdef  MDEBUG
963                                 memcpy(&tmp, arpreply->tipaddr, sizeof(in_addr));
964                                 printf("Sent ARP reply to: %@\n",tmp);
965 #endif  /* MDEBUG */
966                         }
967                 }
968                 background_process(now, ptype, ip);
969                 process_eth_slow(ptype, now);
970         }
971         return(0);
972 }
973
974 #ifdef  REQUIRE_VCI_ETHERBOOT
975 /**************************************************************************
976 FIND_VCI_ETHERBOOT - Looks for "Etherboot" in Vendor Encapsulated Identifiers
977 On entry p points to byte count of VCI options
978 **************************************************************************/
979 static int find_vci_etherboot(unsigned char *p)
980 {
981         unsigned char   *end = p + 1 + *p;
982
983         for (p++; p < end; ) {
984                 if (*p == RFC2132_VENDOR_CLASS_ID) {
985                         if (strncmp("Etherboot", p + 2, sizeof("Etherboot") - 1) == 0)
986                                 return (1);
987                 } else if (*p == RFC1533_END)
988                         return (0);
989                 p += TAG_LEN(p) + 2;
990         }
991         return (0);
992 }
993 #endif  /* REQUIRE_VCI_ETHERBOOT */
994
995 /**************************************************************************
996 DECODE_RFC1533 - Decodes RFC1533 header
997 **************************************************************************/
998 int decode_rfc1533(unsigned char *p, unsigned int block, unsigned int len, int eof)
999 {
1000         static unsigned char *extdata = NULL, *extend = NULL;
1001         unsigned char        *extpath = NULL;
1002         unsigned char        *endp;
1003         static unsigned char in_encapsulated_options = 0;
1004
1005         if (eof == -1) {
1006                 /* Encapsulated option block */
1007                 endp = p + len;
1008         }
1009         else if (block == 0) {
1010 #ifdef  REQUIRE_VCI_ETHERBOOT
1011                 vci_etherboot = 0;
1012 #endif
1013                 end_of_rfc1533 = NULL;
1014 #ifdef  IMAGE_FREEBSD
1015                 /* yes this is a pain FreeBSD uses this for swap, however,
1016                    there are cases when you don't want swap and then
1017                    you want this set to get the extra features so lets
1018                    just set if dealing with FreeBSD.  I haven't run into
1019                    any troubles with this but I have without it
1020                 */
1021                 vendorext_isvalid = 1;
1022 #ifdef FREEBSD_KERNEL_ENV
1023                 memcpy(freebsd_kernel_env, FREEBSD_KERNEL_ENV,
1024                        sizeof(FREEBSD_KERNEL_ENV));
1025                 /* FREEBSD_KERNEL_ENV had better be a string constant */
1026 #else
1027                 freebsd_kernel_env[0]='\0';
1028 #endif
1029 #else
1030                 vendorext_isvalid = 0;
1031 #endif
1032                 if (memcmp(p, rfc1533_cookie, 4))
1033                         return(0); /* no RFC 1533 header found */
1034                 p += 4;
1035                 endp = p + len;
1036         } else {
1037                 if (block == 1) {
1038                         if (memcmp(p, rfc1533_cookie, 4))
1039                                 return(0); /* no RFC 1533 header found */
1040                         p += 4;
1041                         len -= 4; }
1042                 if (extend + len <= (unsigned char *)&(BOOTP_DATA_ADDR->bootp_extension[MAX_BOOTP_EXTLEN])) {
1043                         memcpy(extend, p, len);
1044                         extend += len;
1045                 } else {
1046                         printf("Overflow in vendor data buffer! Aborting...\n");
1047                         *extdata = RFC1533_END;
1048                         return(0);
1049                 }
1050                 p = extdata; endp = extend;
1051         }
1052         if (!eof)
1053                 return 1;
1054         while (p < endp) {
1055                 unsigned char c = *p;
1056                 if (c == RFC1533_PAD) {
1057                         p++;
1058                         continue;
1059                 }
1060                 else if (c == RFC1533_END) {
1061                         end_of_rfc1533 = endp = p;
1062                         continue;
1063                 }
1064                 else if (NON_ENCAP_OPT c == RFC1533_NETMASK)
1065                         memcpy(&netmask, p+2, sizeof(in_addr));
1066                 else if (NON_ENCAP_OPT c == RFC1533_GATEWAY) {
1067                         /* This is a little simplistic, but it will
1068                            usually be sufficient.
1069                            Take only the first entry */
1070                         if (TAG_LEN(p) >= sizeof(in_addr))
1071                                 memcpy(&arptable[ARP_GATEWAY].ipaddr, p+2, sizeof(in_addr));
1072                 }
1073                 else if (c == RFC1533_EXTENSIONPATH)
1074                         extpath = p;
1075 #ifndef NO_DHCP_SUPPORT
1076 #ifdef  REQUIRE_VCI_ETHERBOOT
1077                 else if (NON_ENCAP_OPT c == RFC1533_VENDOR) {
1078                         vci_etherboot = find_vci_etherboot(p+1);
1079 #ifdef  MDEBUG
1080                         printf("vci_etherboot %d\n", vci_etherboot);
1081 #endif
1082                 }
1083 #endif  /* REQUIRE_VCI_ETHERBOOT */
1084                 else if (NON_ENCAP_OPT c == RFC2132_MSG_TYPE)
1085                         dhcp_reply=*(p+2);
1086                 else if (NON_ENCAP_OPT c == RFC2132_SRV_ID)
1087                         memcpy(&dhcp_server, p+2, sizeof(in_addr));
1088 #endif  /* NO_DHCP_SUPPORT */
1089                 else if (NON_ENCAP_OPT c == RFC1533_HOSTNAME) {
1090                         hostname = p + 2;
1091                         hostnamelen = *(p + 1);
1092                 }
1093                 else if (ENCAP_OPT c == RFC1533_VENDOR_MAGIC
1094                          && TAG_LEN(p) >= 6 &&
1095                           !memcmp(p+2,vendorext_magic,4) &&
1096                           p[6] == RFC1533_VENDOR_MAJOR
1097                         )
1098                         vendorext_isvalid++;
1099                 else if (NON_ENCAP_OPT c == RFC1533_VENDOR_ETHERBOOT_ENCAP) {
1100                         in_encapsulated_options = 1;
1101                         decode_rfc1533(p+2, 0, TAG_LEN(p), -1);
1102                         in_encapsulated_options = 0;
1103                 }
1104 #ifdef  IMAGE_FREEBSD
1105                 else if (NON_ENCAP_OPT c == RFC1533_VENDOR_HOWTO)
1106                         freebsd_howto = ((p[2]*256+p[3])*256+p[4])*256+p[5];
1107                 else if (NON_ENCAP_OPT c == RFC1533_VENDOR_KERNEL_ENV){
1108                         if(*(p + 1) < sizeof(freebsd_kernel_env)){
1109                                 memcpy(freebsd_kernel_env,p+2,*(p+1));
1110                         }else{
1111                                 printf("Only support %ld bytes in Kernel Env\n",
1112                                         sizeof(freebsd_kernel_env));
1113                         }
1114                 }
1115 #endif
1116                 else if (NON_ENCAP_OPT c == RFC1533_DNS) {
1117                         // TODO: Copy the DNS IP somewhere reasonable
1118                         if (TAG_LEN(p) >= sizeof(in_addr))
1119                                 memcpy(&arptable[ARP_NAMESERVER].ipaddr, p+2, sizeof(in_addr));
1120                 }
1121                 else {
1122 #if 0
1123                         unsigned char *q;
1124                         printf("Unknown RFC1533-tag ");
1125                         for(q=p;q<p+2+TAG_LEN(p);q++)
1126                                 printf("%hhX ",*q);
1127                         putchar('\n');
1128 #endif
1129                 }
1130                 p += TAG_LEN(p) + 2;
1131         }
1132         extdata = extend = endp;
1133         if (block <= 0 && extpath != NULL) {
1134                 char fname[64];
1135                 memcpy(fname, extpath+2, TAG_LEN(extpath));
1136                 fname[(int)TAG_LEN(extpath)] = '\0';
1137                 printf("Loading BOOTP-extension file: %s\n",fname);
1138 #warning "BOOTP extension files are broken"
1139                 /*              tftp(fname, decode_rfc1533); */
1140         }
1141         return 1;       /* proceed with next block */
1142 }
1143
1144
1145 /* FIXME double check TWO_SECOND_DIVISOR */
1146 #define TWO_SECOND_DIVISOR (RAND_MAX/TICKS_PER_SEC)
1147 /**************************************************************************
1148 RFC2131_SLEEP_INTERVAL - sleep for expotentially longer times (base << exp) +- 1 sec)
1149 **************************************************************************/
1150 long rfc2131_sleep_interval(long base, int exp)
1151 {
1152         unsigned long tmo;
1153         if (exp > BACKOFF_LIMIT)
1154                 exp = BACKOFF_LIMIT;
1155         tmo = (base << exp) + (TICKS_PER_SEC - (random()/TWO_SECOND_DIVISOR));
1156         return tmo;
1157 }
1158
1159