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