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