5b52bea1c78c26aa7766b1fc6192699048aabc73
[people/lynusvaz/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 "dev.h"
20 #include "nic.h"
21 #include "elf.h" /* FOR EM_CURRENT */
22
23 struct arptable_t       arptable[MAX_ARP];
24 #if MULTICAST_LEVEL2
25 unsigned long last_igmpv1 = 0;
26 struct igmptable_t      igmptable[MAX_IGMP];
27 #endif
28 /* Put rom_info in .nocompress section so romprefix.S can write to it */
29 struct rom_info rom __attribute__ ((section (".text16.nocompress"))) = {0,0};
30 static unsigned long    netmask;
31 /* Used by nfs.c */
32 char *hostname = "";
33 int hostnamelen = 0;
34 static uint32_t xid;
35 unsigned char *end_of_rfc1533 = NULL;
36 static int vendorext_isvalid;
37 static const unsigned char vendorext_magic[] = {0xE4,0x45,0x74,0x68}; /* √§Eth */
38 static const unsigned char broadcast[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
39 static const in_addr zeroIP = { 0L };
40
41 struct bootpd_t bootp_data;
42
43 #ifdef  NO_DHCP_SUPPORT
44 static unsigned char    rfc1533_cookie[5] = { RFC1533_COOKIE, RFC1533_END };
45 #else   /* !NO_DHCP_SUPPORT */
46 static int dhcp_reply;
47 static in_addr dhcp_server = { 0L };
48 static in_addr dhcp_addr = { 0L };
49 static unsigned char    rfc1533_cookie[] = { RFC1533_COOKIE };
50 #define DHCP_MACHINE_INFO_SIZE (sizeof dhcp_machine_info)
51 static unsigned char dhcp_machine_info[] = {
52         /* Our enclosing DHCP tag */
53         RFC1533_VENDOR_ETHERBOOT_ENCAP, 11,
54         /* Our boot device */
55         RFC1533_VENDOR_NIC_DEV_ID, 5, PCI_BUS_TYPE, 0, 0, 0, 0,
56         /* Our current architecture */
57         RFC1533_VENDOR_ARCH, 2, EM_CURRENT & 0xff, (EM_CURRENT >> 8) & 0xff,
58 #ifdef EM_CURRENT_64
59         /* The 64bit version of our current architecture */
60         RFC1533_VENDOR_ARCH, 2, EM_CURRENT_64 & 0xff, (EM_CURRENT_64 >> 8) & 0xff,
61 #undef DHCP_MACHINE_INFO_SIZE
62 #define DHCP_MACHINE_INFO_SIZE (sizeof(dhcp_machine_info) - (EM_CURRENT_64_PRESENT? 0: 4))
63 #endif /* EM_CURRENT_64 */
64 };
65 static const unsigned char dhcpdiscover[] = {
66         RFC2132_MSG_TYPE,1,DHCPDISCOVER,
67         RFC2132_MAX_SIZE,2,     /* request as much as we can */
68         ETH_MAX_MTU / 256, ETH_MAX_MTU % 256,
69 #ifdef PXE_DHCP_STRICT
70         RFC3679_PXE_CLIENT_UUID,RFC3679_PXE_CLIENT_UUID_LENGTH,RFC3679_PXE_CLIENT_UUID_DEFAULT,
71         RFC3679_PXE_CLIENT_ARCH,RFC3679_PXE_CLIENT_ARCH_LENGTH,RFC3679_PXE_CLIENT_ARCH_IAX86PC,
72         RFC3679_PXE_CLIENT_NDI, RFC3679_PXE_CLIENT_NDI_LENGTH, RFC3679_PXE_CLIENT_NDI_21,
73         RFC2132_VENDOR_CLASS_ID,RFC2132_VENDOR_CLASS_ID_PXE_LENGTH,RFC2132_VENDOR_CLASS_ID_PXE,
74 #else
75         RFC2132_VENDOR_CLASS_ID,13,'E','t','h','e','r','b','o','o','t',
76         '-',VERSION_MAJOR+'0','.',VERSION_MINOR+'0',
77 #endif /* PXE_DHCP_STRICT */
78 #ifdef DHCP_CLIENT_ID
79         /* Client ID Option */
80         RFC2132_CLIENT_ID, ( DHCP_CLIENT_ID_LEN + 1 ),
81         DHCP_CLIENT_ID_TYPE, DHCP_CLIENT_ID,
82 #endif /* DHCP_CLIENT_ID */
83 #ifdef DHCP_USER_CLASS
84         /* User Class Option */
85         RFC3004_USER_CLASS, DHCP_USER_CLASS_LEN, DHCP_USER_CLASS,
86 #endif /* DHCP_USER_CLASS */
87         RFC2132_PARAM_LIST,
88 #define DHCPDISCOVER_PARAMS_BASE 4
89 #ifdef  PXE_DHCP_STRICT
90 #define DHCPDISCOVER_PARAMS_PXE ( 1 + 8 )
91 #else
92 #define DHCPDISCOVER_PARAMS_PXE 0
93 #endif /* PXE_DHCP_STRICT */
94 #ifdef  DNS_RESOLVER
95 #define DHCPDISCOVER_PARAMS_DNS  1
96 #else
97 #define DHCPDISCOVER_PARAMS_DNS  0
98 #endif /* DNS_RESOLVER */
99         ( DHCPDISCOVER_PARAMS_BASE +
100           DHCPDISCOVER_PARAMS_PXE+
101           DHCPDISCOVER_PARAMS_DNS ),
102         RFC1533_NETMASK,
103         RFC1533_GATEWAY,
104         RFC1533_HOSTNAME,
105         RFC1533_VENDOR
106 #ifdef PXE_DHCP_STRICT
107         ,RFC2132_VENDOR_CLASS_ID,
108         RFC1533_VENDOR_PXE_OPT128,
109         RFC1533_VENDOR_PXE_OPT129,
110         RFC1533_VENDOR_PXE_OPT130,
111         RFC1533_VENDOR_PXE_OPT131,
112         RFC1533_VENDOR_PXE_OPT132,
113         RFC1533_VENDOR_PXE_OPT133,
114         RFC1533_VENDOR_PXE_OPT134,
115         RFC1533_VENDOR_PXE_OPT135
116 #endif /* PXE_DHCP_STRICT */
117 #ifdef  DNS_RESOLVER
118         ,RFC1533_DNS
119 #endif
120 };
121 static const unsigned char dhcprequest [] = {
122         RFC2132_MSG_TYPE,1,DHCPREQUEST,
123         RFC2132_SRV_ID,4,0,0,0,0,
124         RFC2132_REQ_ADDR,4,0,0,0,0,
125         RFC2132_MAX_SIZE,2,     /* request as much as we can */
126         ETH_MAX_MTU / 256, ETH_MAX_MTU % 256,
127 #ifdef PXE_DHCP_STRICT
128         RFC3679_PXE_CLIENT_UUID,RFC3679_PXE_CLIENT_UUID_LENGTH,RFC3679_PXE_CLIENT_UUID_DEFAULT,
129         RFC3679_PXE_CLIENT_ARCH,RFC3679_PXE_CLIENT_ARCH_LENGTH,RFC3679_PXE_CLIENT_ARCH_IAX86PC,
130         RFC3679_PXE_CLIENT_NDI, RFC3679_PXE_CLIENT_NDI_LENGTH, RFC3679_PXE_CLIENT_NDI_21,
131         RFC2132_VENDOR_CLASS_ID,RFC2132_VENDOR_CLASS_ID_PXE_LENGTH,RFC2132_VENDOR_CLASS_ID_PXE,
132 #else
133         RFC2132_VENDOR_CLASS_ID,13,'E','t','h','e','r','b','o','o','t',
134         '-',VERSION_MAJOR+'0','.',VERSION_MINOR+'0',
135 #endif /* PXE_DHCP_STRICT */
136 #ifdef DHCP_CLIENT_ID
137         /* Client ID Option */
138         RFC2132_CLIENT_ID, ( DHCP_CLIENT_ID_LEN + 1 ),
139         DHCP_CLIENT_ID_TYPE, DHCP_CLIENT_ID,
140 #endif /* DHCP_CLIENT_ID */
141 #ifdef DHCP_USER_CLASS
142         /* User Class Option */
143         RFC3004_USER_CLASS, DHCP_USER_CLASS_LEN, DHCP_USER_CLASS,
144 #endif /* DHCP_USER_CLASS */
145         /* request parameters */
146         RFC2132_PARAM_LIST,
147 #define DHCPREQUEST_PARAMS_BASE 5  
148 #ifdef  PXE_DHCP_STRICT
149 #define DHCPREQUEST_PARAMS_PXE 1
150 #define DHCPREQUEST_PARAMS_VENDOR_PXE 8
151 #define DHCPREQUEST_PARAMS_VENDOR_EB 0
152 #else
153 #define DHCPREQUEST_PARAMS_PXE 0
154 #define DHCPREQUEST_PARAMS_VENDOR_PXE 0
155 #define DHCPREQUEST_PARAMS_VENDOR_EB 4
156 #endif /* PXE_DHCP_STRICT */
157 #ifdef  IMAGE_FREEBSD
158 #define DHCPREQUEST_PARAMS_FREEBSD 2
159 #else
160 #define DHCPREQUEST_PARAMS_FREEBSD 0
161 #endif /* IMAGE_FREEBSD */
162 #ifdef  DNS_RESOLVER
163 #define DHCPREQUEST_PARAMS_DNS     1
164 #else
165 #define DHCPREQUEST_PARAMS_DNS     0
166 #endif /* DNS_RESOLVER */
167         ( DHCPREQUEST_PARAMS_BASE +
168           DHCPREQUEST_PARAMS_PXE +
169           DHCPREQUEST_PARAMS_VENDOR_PXE +
170           DHCPREQUEST_PARAMS_VENDOR_EB +
171           DHCPREQUEST_PARAMS_DNS +
172           DHCPREQUEST_PARAMS_FREEBSD ),
173         /* 5 Standard parameters */
174         RFC1533_NETMASK,
175         RFC1533_GATEWAY,
176         RFC1533_HOSTNAME,
177         RFC1533_VENDOR,
178         RFC1533_ROOTPATH,       /* only passed to the booted image */
179 #ifndef PXE_DHCP_STRICT
180         /* 4 Etherboot vendortags */
181         RFC1533_VENDOR_MAGIC,
182         RFC1533_VENDOR_ADDPARM,
183         RFC1533_VENDOR_ETHDEV,
184         RFC1533_VENDOR_ETHERBOOT_ENCAP,
185 #endif /* ! PXE_DHCP_STRICT */
186 #ifdef  IMAGE_FREEBSD
187         /* 2 FreeBSD options */
188         RFC1533_VENDOR_HOWTO,
189         RFC1533_VENDOR_KERNEL_ENV,
190 #endif
191 #ifdef  DNS_RESOLVER
192         /* 1 DNS option */
193         RFC1533_DNS,
194 #endif
195 #ifdef  PXE_DHCP_STRICT
196         RFC2132_VENDOR_CLASS_ID,
197         RFC1533_VENDOR_PXE_OPT128,
198         RFC1533_VENDOR_PXE_OPT129,
199         RFC1533_VENDOR_PXE_OPT130,
200         RFC1533_VENDOR_PXE_OPT131,
201         RFC1533_VENDOR_PXE_OPT132,
202         RFC1533_VENDOR_PXE_OPT133,
203         RFC1533_VENDOR_PXE_OPT134,
204         RFC1533_VENDOR_PXE_OPT135,
205 #endif /* PXE_DHCP_STRICT */
206 };
207 #ifdef PXE_EXPORT
208 static const unsigned char proxydhcprequest [] = {
209         RFC2132_MSG_TYPE,1,DHCPREQUEST,
210         RFC2132_MAX_SIZE,2,     /* request as much as we can */
211         ETH_MAX_MTU / 256, ETH_MAX_MTU % 256,
212 #ifdef  PXE_DHCP_STRICT
213         RFC3679_PXE_CLIENT_UUID,RFC3679_PXE_CLIENT_UUID_LENGTH,RFC3679_PXE_CLIENT_UUID_DEFAULT,
214         RFC3679_PXE_CLIENT_ARCH,RFC3679_PXE_CLIENT_ARCH_LENGTH,RFC3679_PXE_CLIENT_ARCH_IAX86PC,
215         RFC3679_PXE_CLIENT_NDI, RFC3679_PXE_CLIENT_NDI_LENGTH, RFC3679_PXE_CLIENT_NDI_21,
216         RFC2132_VENDOR_CLASS_ID,RFC2132_VENDOR_CLASS_ID_PXE_LENGTH,RFC2132_VENDOR_CLASS_ID_PXE,
217 #endif /* PXE_DHCP_STRICT */
218 };
219 #endif
220
221 #ifdef  REQUIRE_VCI_ETHERBOOT
222 int     vci_etherboot;
223 #endif
224 #endif  /* NO_DHCP_SUPPORT */
225
226 #ifdef RARP_NOT_BOOTP
227 static int rarp(void);
228 #else
229 static int bootp(void);
230 #endif
231 static unsigned short tcpudpchksum(struct iphdr *ip);
232
233
234 struct nic *nic = &dev.nic;
235
236 /*
237  * Find out what our boot parameters are
238  */
239 static int nic_load_configuration ( struct dev *dev ) {
240         struct nic *nic = &dev->nic;
241         int server_found;
242
243         if ( ! nic->nic_op->connect ( nic ) ) {
244                 printf ( "No connection to network\n" );
245                 return 0;
246         }
247
248         /* Find a server to get BOOTP reply from */
249 #ifdef  RARP_NOT_BOOTP
250         printf("Searching for server (RARP)...");
251 #else
252 #ifndef NO_DHCP_SUPPORT
253         printf("Searching for server (DHCP)...");
254 #else
255         printf("Searching for server (BOOTP)...");
256 #endif
257 #endif
258
259 #ifdef  RARP_NOT_BOOTP
260         server_found = rarp();
261 #else
262         server_found = bootp();
263 #endif
264         if (!server_found) {
265                 printf("No Server found\n");
266                 return 0;
267         }
268         return 1;
269 }
270
271
272 /**************************************************************************
273 LOAD - Try to get booted
274 **************************************************************************/
275 static int nic_load(struct dev *dev __unused)
276 {
277         const char      *kernel;
278         printf("\nMe: %@", arptable[ARP_CLIENT].ipaddr.s_addr );
279 #ifndef NO_DHCP_SUPPORT
280         printf(", DHCP: %@", dhcp_server );
281 #ifdef PXE_EXPORT       
282         if (arptable[ARP_PROXYDHCP].ipaddr.s_addr)
283                 printf(" (& %@)",
284                        arptable[ARP_PROXYDHCP].ipaddr.s_addr);
285 #endif /* PXE_EXPORT */
286 #endif /* ! NO_DHCP_SUPPORT */
287         printf(", TFTP: %@", arptable[ARP_SERVER].ipaddr.s_addr);
288         if (BOOTP_DATA_ADDR->bootp_reply.bp_giaddr.s_addr)
289                 printf(", Relay: %@",
290                         BOOTP_DATA_ADDR->bootp_reply.bp_giaddr.s_addr);
291         if (arptable[ARP_GATEWAY].ipaddr.s_addr)
292                 printf(", Gateway %@", arptable[ARP_GATEWAY].ipaddr.s_addr);
293 #ifdef  DNS_RESOLVER
294         if (arptable[ARP_NAMESERVER].ipaddr.s_addr)
295                 printf(", Nameserver %@", arptable[ARP_NAMESERVER].ipaddr.s_addr);
296 #endif
297         putchar('\n');
298
299 #ifdef  MDEBUG
300         printf("\n=>>"); getchar();
301 #endif
302
303         /* Now use TFTP to load file */
304 #ifdef  DOWNLOAD_PROTO_NFS
305         rpc_init();
306 #endif
307         kernel = KERNEL_BUF[0] == '\0' ? 
308 #ifdef  DEFAULT_BOOTFILE
309                 DEFAULT_BOOTFILE
310 #else
311                 NULL
312 #endif
313                 : KERNEL_BUF;
314         if ( kernel ) {
315                 loadkernel(kernel); /* We don't return except on error */
316                 printf("Unable to load file.\n");
317         } else {        
318                 printf("No filename\n");
319         }
320         interruptible_sleep(2);         /* lay off the server for a while */
321         return 0;
322 }
323
324
325 static void nic_disable ( struct dev *dev ) {
326         struct nic *nic = &dev->nic;
327
328 #ifdef MULTICAST_LEVEL2
329         int i;
330         for(i = 0; i < MAX_IGMP; i++) {
331                 leave_group(i);
332         }
333 #endif
334         
335         nic->nic_op->disable ( nic );
336 }
337
338 static void nic_print_info ( struct dev *dev ) {
339         struct nic *nic = &dev->nic;
340
341         printf ( "Found %s NIC (MAC %!)\n", dev->name, nic->node_addr );
342 }
343
344 /* 
345  * Device operations tables
346  *
347  */
348 static struct dev_operations nic_operations = {
349         .disable = nic_disable,
350         .print_info = nic_print_info,
351         .load_configuration = nic_load_configuration,
352         .load = nic_load,
353 };
354
355 /* Careful.  We need an aligned buffer to avoid problems on machines
356  * that care about alignment.  To trivally align the ethernet data
357  * (the ip hdr and arp requests) we offset the packet by 2 bytes.
358  * leaving the ethernet data 16 byte aligned.  Beyond this
359  * we use memmove but this makes the common cast simple and fast.
360  */
361 static char     packet[ETH_FRAME_LEN + ETH_DATA_ALIGN] __aligned;
362
363 /*
364  * Set up a struct dev to operate as a NIC, return the struct nic *
365  *
366  */
367 struct nic * nic_device ( struct dev *dev ) {
368         struct nic *nic = &dev->nic;
369
370         memset ( nic, 0, sizeof ( *nic ) );
371         nic->node_addr = arptable[ARP_CLIENT].node;
372         nic->packet = packet + ETH_DATA_ALIGN;
373         dev->dev_op = &nic_operations;
374         return nic;
375 }
376
377
378
379 int dummy_connect ( struct nic *nic __unused ) {
380         return 1;
381 }
382
383 void dummy_irq ( struct nic *nic __unused, irq_action_t irq_action __unused ) {
384         return;
385 }
386
387 /**************************************************************************
388 DEFAULT_NETMASK - Return default netmask for IP address
389 **************************************************************************/
390 static inline unsigned long default_netmask(void)
391 {
392         int net = ntohl(arptable[ARP_CLIENT].ipaddr.s_addr) >> 24;
393         if (net <= 127)
394                 return(htonl(0xff000000));
395         else if (net < 192)
396                 return(htonl(0xffff0000));
397         else
398                 return(htonl(0xffffff00));
399 }
400
401 /**************************************************************************
402 IP_TRANSMIT - Send an IP datagram
403 **************************************************************************/
404 static int await_arp(int ival, void *ptr,
405         unsigned short ptype, struct iphdr *ip __unused, struct udphdr *udp __unused,
406         struct tcphdr *tcp __unused)
407 {
408         struct  arprequest *arpreply;
409         if (ptype != ETH_P_ARP)
410                 return 0;
411         if (nic->packetlen < ETH_HLEN + sizeof(struct arprequest))
412                 return 0;
413         arpreply = (struct arprequest *)&nic->packet[ETH_HLEN];
414
415         if (arpreply->opcode != htons(ARP_REPLY)) 
416                 return 0;
417         if (memcmp(arpreply->sipaddr, ptr, sizeof(in_addr)) != 0)
418                 return 0;
419         memcpy(arptable[ival].node, arpreply->shwaddr, ETH_ALEN);
420         return 1;
421 }
422
423 int ip_transmit(int len, const void *buf)
424 {
425         unsigned long destip;
426         struct iphdr *ip;
427         struct arprequest arpreq;
428         int arpentry, i;
429         int retry;
430
431         ip = (struct iphdr *)buf;
432         destip = ip->dest.s_addr;
433         if (destip == IP_BROADCAST) {
434                 eth_transmit(broadcast, ETH_P_IP, len, buf);
435 #ifdef MULTICAST_LEVEL1 
436         } else if ((destip & htonl(MULTICAST_MASK)) == htonl(MULTICAST_NETWORK)) {
437                 unsigned char multicast[6];
438                 unsigned long hdestip;
439                 hdestip = ntohl(destip);
440                 multicast[0] = 0x01;
441                 multicast[1] = 0x00;
442                 multicast[2] = 0x5e;
443                 multicast[3] = (hdestip >> 16) & 0x7;
444                 multicast[4] = (hdestip >> 8) & 0xff;
445                 multicast[5] = hdestip & 0xff;
446                 eth_transmit(multicast, ETH_P_IP, len, buf);
447 #endif
448         } else {
449                 if (((destip & netmask) !=
450                         (arptable[ARP_CLIENT].ipaddr.s_addr & netmask)) &&
451                         arptable[ARP_GATEWAY].ipaddr.s_addr)
452                                 destip = arptable[ARP_GATEWAY].ipaddr.s_addr;
453                 for(arpentry = 0; arpentry<MAX_ARP; arpentry++)
454                         if (arptable[arpentry].ipaddr.s_addr == destip) break;
455                 if (arpentry == MAX_ARP) {
456                         printf("%@ is not in my arp table!\n", destip);
457                         return(0);
458                 }
459                 for (i = 0; i < ETH_ALEN; i++)
460                         if (arptable[arpentry].node[i])
461                                 break;
462                 if (i == ETH_ALEN) {    /* Need to do arp request */
463                         arpreq.hwtype = htons(1);
464                         arpreq.protocol = htons(IP);
465                         arpreq.hwlen = ETH_ALEN;
466                         arpreq.protolen = 4;
467                         arpreq.opcode = htons(ARP_REQUEST);
468                         memcpy(arpreq.shwaddr, arptable[ARP_CLIENT].node, ETH_ALEN);
469                         memcpy(arpreq.sipaddr, &arptable[ARP_CLIENT].ipaddr, sizeof(in_addr));
470                         memset(arpreq.thwaddr, 0, ETH_ALEN);
471                         memcpy(arpreq.tipaddr, &destip, sizeof(in_addr));
472                         for (retry = 1; retry <= MAX_ARP_RETRIES; retry++) {
473                                 long timeout;
474                                 eth_transmit(broadcast, ETH_P_ARP, sizeof(arpreq),
475                                         &arpreq);
476                                 timeout = rfc2131_sleep_interval(TIMEOUT, retry);
477                                 if (await_reply(await_arp, arpentry,
478                                         arpreq.tipaddr, timeout)) goto xmit;
479                         }
480                         return(0);
481                 }
482 xmit:
483                 eth_transmit(arptable[arpentry].node, ETH_P_IP, len, buf);
484         }
485         return 1;
486 }
487
488 void build_ip_hdr(unsigned long destip, int ttl, int protocol, int option_len,
489         int len, const void *buf)
490 {
491         struct iphdr *ip;
492         ip = (struct iphdr *)buf;
493         ip->verhdrlen = 0x45;
494         ip->verhdrlen += (option_len/4);
495         ip->service = 0;
496         ip->len = htons(len);
497         ip->ident = 0;
498         ip->frags = 0; /* Should we set don't fragment? */
499         ip->ttl = ttl;
500         ip->protocol = protocol;
501         ip->chksum = 0;
502         ip->src.s_addr = arptable[ARP_CLIENT].ipaddr.s_addr;
503         ip->dest.s_addr = destip;
504         ip->chksum = ipchksum(buf, sizeof(struct iphdr) + option_len);
505 }
506
507 void build_udp_hdr(unsigned long destip, 
508         unsigned int srcsock, unsigned int destsock, int ttl,
509         int len, const void *buf)
510 {
511         struct iphdr *ip;
512         struct udphdr *udp;
513         ip = (struct iphdr *)buf;
514         build_ip_hdr(destip, ttl, IP_UDP, 0, len, buf);
515         udp = (struct udphdr *)((char *)buf + sizeof(struct iphdr));
516         udp->src = htons(srcsock);
517         udp->dest = htons(destsock);
518         udp->len = htons(len - sizeof(struct iphdr));
519         udp->chksum = 0;
520         if ((udp->chksum = tcpudpchksum(ip)) == 0)
521                 udp->chksum = 0xffff;
522 }
523
524 #ifdef DOWNLOAD_PROTO_HTTP
525 void build_tcp_hdr(unsigned long destip, unsigned int srcsock,
526                   unsigned int destsock, long send_seq, long recv_seq,
527                   int window, int flags, int ttl, int len, const void *buf)
528 {
529        struct iphdr *ip;
530        struct tcphdr *tcp;
531        ip = (struct iphdr *)buf;
532        build_ip_hdr(destip, ttl, IP_TCP, 0, len, buf);
533        tcp = (struct tcphdr *)(ip + 1);
534        tcp->src = htons(srcsock);
535        tcp->dst = htons(destsock);
536        tcp->seq = htonl(send_seq);
537        tcp->ack = htonl(recv_seq);
538        tcp->ctrl = htons(flags + (5 << 12)); /* No TCP options */
539        tcp->window = htons(window);
540        tcp->chksum = 0;
541        if ((tcp->chksum = tcpudpchksum(ip)) == 0)
542                tcp->chksum = 0xffff;
543 }
544 #endif
545
546
547 /**************************************************************************
548 UDP_TRANSMIT - Send an UDP datagram
549 **************************************************************************/
550 int udp_transmit(unsigned long destip, unsigned int srcsock,
551         unsigned int destsock, int len, const void *buf)
552 {
553         build_udp_hdr(destip, srcsock, destsock, 60, len, buf);
554         return ip_transmit(len, buf);
555 }
556
557 /**************************************************************************
558 TCP_TRANSMIT - Send a TCP packet
559 **************************************************************************/
560 #ifdef DOWNLOAD_PROTO_HTTP
561 int tcp_transmit(unsigned long destip, unsigned int srcsock,
562                 unsigned int destsock, long send_seq, long recv_seq,
563                 int window, int flags, int len, const void *buf)
564 {
565        build_tcp_hdr(destip, srcsock, destsock, send_seq, recv_seq,
566                      window, flags, 60, len, buf);
567        return ip_transmit(len, buf);
568 }
569
570 int tcp_reset(struct iphdr *ip) {
571        struct tcphdr *tcp = (struct tcphdr *)(ip + 1);
572        char buf[sizeof(struct iphdr) + sizeof(struct tcphdr)];
573
574        if (!(tcp->ctrl & htons(RST))) {
575               long seq = ntohl(tcp->seq) + ntohs(ip->len) -
576                          sizeof(struct iphdr) -
577                          ((ntohs(tcp->ctrl) >> 10) & 0x3C);
578               if (tcp->ctrl & htons(SYN|FIN))
579                       seq++;
580               return tcp_transmit(ntohl(ip->src.s_addr),
581                                   ntohs(tcp->dst), ntohs(tcp->src),
582                                   tcp->ctrl&htons(ACK) ? ntohl(tcp->ack) : 0,
583                                   seq, TCP_MAX_WINDOW, RST, sizeof(buf), buf);
584        }
585        return (1);
586 }
587 #endif
588
589 /**************************************************************************
590 QDRAIN - clear the nic's receive queue
591 **************************************************************************/
592 static int await_qdrain(int ival __unused, void *ptr __unused,
593         unsigned short ptype __unused, 
594         struct iphdr *ip __unused, struct udphdr *udp __unused,
595         struct tcphdr *tcp __unused)
596 {
597         return 0;
598 }
599
600 void rx_qdrain(void)
601 {
602         /* Clear out the Rx queue first.  It contains nothing of interest,
603          * except possibly ARP requests from the DHCP/TFTP server.  We use
604          * polling throughout Etherboot, so some time may have passed since we
605          * last polled the receive queue, which may now be filled with
606          * broadcast packets.  This will cause the reply to the packets we are
607          * about to send to be lost immediately.  Not very clever.  */
608         await_reply(await_qdrain, 0, NULL, 0);
609 }
610
611 #ifdef  DOWNLOAD_PROTO_TFTP
612 /**************************************************************************
613 TFTP - Download extended BOOTP data, or kernel image
614 **************************************************************************/
615 static int await_tftp(int ival, void *ptr __unused,
616         unsigned short ptype __unused, struct iphdr *ip, struct udphdr *udp,
617         struct tcphdr *tcp __unused)
618 {
619         if (!udp) {
620                 return 0;
621         }
622         if (arptable[ARP_CLIENT].ipaddr.s_addr != ip->dest.s_addr)
623                 return 0;
624         if (ntohs(udp->dest) != ival)
625                 return 0;
626         return 1;
627 }
628
629 int tftp ( const char *name,
630            int (*fnc)(unsigned char *, unsigned int, unsigned int, int) )
631 {
632         struct tftpreq_info_t request_data =
633                 { name, TFTP_PORT, TFTP_MAX_PACKET };
634         struct tftpreq_info_t *request = &request_data;
635         struct tftpblk_info_t block;
636         int rc;
637
638         while ( tftp_block ( request, &block ) ) {
639                 request = NULL; /* Send request only once */
640                 rc = fnc ( block.data, block.block, block.len, block.eof );
641                 if ( rc <= 0 ) return (rc);
642                 if ( block.eof ) {
643                         /* fnc should not have returned */
644                         printf ( "TFTP download complete, but\n" );
645                         return (0);
646                 }
647         }
648         return (0);
649 }
650
651 int tftp_block ( struct tftpreq_info_t *request, struct tftpblk_info_t *block )
652 {
653         static unsigned short lport = 2000; /* local port */
654         static unsigned short rport = TFTP_PORT; /* remote port */
655         struct tftp_t *rcvd = NULL;
656         static struct tftpreq_t xmit;
657         static unsigned short xmitlen = 0;
658         static unsigned short blockidx = 0; /* Last block received */
659         static unsigned short retry = 0; /* Retry attempts on last block */
660         static int blksize = 0;
661         unsigned short recvlen = 0;
662
663         /* If this is a new request (i.e. if name is set), fill in
664          * transmit block with RRQ and send it.
665          */
666         if ( request ) {
667                 rx_qdrain(); /* Flush receive queue */
668                 xmit.opcode = htons(TFTP_RRQ);
669                 xmitlen = (void*)&xmit.u.rrq - (void*)&xmit +
670                         sprintf((char*)xmit.u.rrq, "%s%coctet%cblksize%c%d",
671                                 request->name, 0, 0, 0, request->blksize)
672                         + 1; /* null terminator */
673                 blockidx = 0; /* Reset counters */
674                 retry = 0;
675                 blksize = TFTP_DEFAULTSIZE_PACKET;
676                 lport++; /* Use new local port */
677                 rport = request->port;
678                 if ( !udp_transmit(arptable[ARP_SERVER].ipaddr.s_addr, lport,
679                                    rport, xmitlen, &xmit) )
680                         return (0);
681         }
682         /* Exit if no transfer in progress */
683         if ( !blksize ) return (0);
684         /* Loop to wait until we get a packet we're interested in */
685         block->data = NULL; /* Used as flag */
686         while ( block->data == NULL ) {
687                 long timeout = rfc2131_sleep_interval ( blockidx ? TFTP_REXMT :
688                                                         TIMEOUT, retry );
689                 if ( !await_reply(await_tftp, lport, NULL, timeout) ) {
690                         /* No packet received */
691                         if ( retry++ > MAX_TFTP_RETRIES ) break;
692                         /* Retransmit last packet */
693                         if ( !blockidx ) lport++; /* New lport if new RRQ */
694                         if ( !udp_transmit(arptable[ARP_SERVER].ipaddr.s_addr,
695                                            lport, rport, xmitlen, &xmit) )
696                                 return (0);
697                         continue; /* Back to waiting for packet */
698                 }
699                 /* Packet has been received */
700                 rcvd = (struct tftp_t *)&nic->packet[ETH_HLEN];
701                 recvlen = ntohs(rcvd->udp.len) - sizeof(struct udphdr)
702                         - sizeof(rcvd->opcode);
703                 rport = ntohs(rcvd->udp.src);
704                 retry = 0; /* Reset retry counter */
705                 switch ( htons(rcvd->opcode) ) {
706                 case TFTP_ERROR : {
707                         printf ( "TFTP error %d (%s)\n",
708                                  ntohs(rcvd->u.err.errcode),
709                                  rcvd->u.err.errmsg );
710                         return (0); /* abort */
711                 }
712                 case TFTP_OACK : {
713                         const char *p = rcvd->u.oack.data;
714                         const char *e = p + recvlen - 10; /* "blksize\0\d\0" */
715
716                         *((char*)(p+recvlen-1)) = '\0'; /* Force final 0 */
717                         if ( blockidx || !request ) break; /* Too late */
718                         if ( recvlen <= TFTP_MAX_PACKET ) /* sanity */ {
719                                 /* Check for blksize option honoured */
720                                 while ( p < e ) {
721                                         if ( strcasecmp("blksize",p) == 0 &&
722                                              p[7] == '\0' ) {
723                                                 blksize = strtoul(p+8,&p,10);
724                                                 p++; /* skip null */
725                                         }
726                                         while ( *(p++) ) {};
727                                 }
728                         }
729                         if ( blksize < TFTP_DEFAULTSIZE_PACKET || blksize > request->blksize ) {
730                                 /* Incorrect blksize - error and abort */
731                                 xmit.opcode = htons(TFTP_ERROR);
732                                 xmit.u.err.errcode = 8;
733                                 xmitlen = (void*)&xmit.u.err.errmsg
734                                         - (void*)&xmit
735                                         + sprintf((char*)xmit.u.err.errmsg,
736                                                   "RFC1782 error")
737                                         + 1;
738                                 udp_transmit(
739                                     arptable[ARP_SERVER].ipaddr.s_addr,
740                                     lport, rport, xmitlen, &xmit);
741                                 return (0);
742                         }
743                 } break;
744                 case TFTP_DATA :
745                         if ( ntohs(rcvd->u.data.block) != ( blockidx + 1 ) )
746                                 break; /* Re-ACK last block sent */
747                         if ( recvlen > ( blksize+sizeof(rcvd->u.data.block) ) )
748                                 break; /* Too large; ignore */
749                         block->data = rcvd->u.data.download;
750                         block->block = ++blockidx;
751                         block->len = recvlen - sizeof(rcvd->u.data.block);
752                         block->eof = ( (unsigned short)block->len < blksize );
753                         /* If EOF, zero blksize to indicate transfer done */
754                         if ( block->eof ) blksize = 0;
755                         break;
756                 default: break; /* Do nothing */
757                 }
758                 /* Send ACK */
759                 xmit.opcode = htons(TFTP_ACK);
760                 xmit.u.ack.block = htons(blockidx);
761                 xmitlen = TFTP_MIN_PACKET;
762                 udp_transmit ( arptable[ARP_SERVER].ipaddr.s_addr,
763                                lport, rport, xmitlen, &xmit );
764         }
765         return ( block->data ? 1 : 0 );
766 }
767 #endif  /* DOWNLOAD_PROTO_TFTP */
768
769 #ifdef  RARP_NOT_BOOTP
770 /**************************************************************************
771 RARP - Get my IP address and load information
772 **************************************************************************/
773 static int await_rarp(int ival, void *ptr,
774         unsigned short ptype, struct iphdr *ip, struct udphdr *udp,
775         struct tcphdr *tcp __unused)
776 {
777         struct arprequest *arpreply;
778         if (ptype != ETH_P_RARP)
779                 return 0;
780         if (nic->packetlen < ETH_HLEN + sizeof(struct arprequest))
781                 return 0;
782         arpreply = (struct arprequest *)&nic->packet[ETH_HLEN];
783         if (arpreply->opcode != htons(RARP_REPLY))
784                 return 0;
785         if ((arpreply->opcode == htons(RARP_REPLY)) &&
786                 (memcmp(arpreply->thwaddr, ptr, ETH_ALEN) == 0)) {
787                 memcpy(arptable[ARP_SERVER].node, arpreply->shwaddr, ETH_ALEN);
788                 memcpy(&arptable[ARP_SERVER].ipaddr, arpreply->sipaddr, sizeof(in_addr));
789                 memcpy(&arptable[ARP_CLIENT].ipaddr, arpreply->tipaddr, sizeof(in_addr));
790                 return 1;
791         }
792         return 0;
793 }
794
795 static int rarp(void)
796 {
797         int retry;
798
799         /* arp and rarp requests share the same packet structure. */
800         struct arprequest rarpreq;
801
802         memset(&rarpreq, 0, sizeof(rarpreq));
803
804         rarpreq.hwtype = htons(1);
805         rarpreq.protocol = htons(IP);
806         rarpreq.hwlen = ETH_ALEN;
807         rarpreq.protolen = 4;
808         rarpreq.opcode = htons(RARP_REQUEST);
809         memcpy(&rarpreq.shwaddr, arptable[ARP_CLIENT].node, ETH_ALEN);
810         /* sipaddr is already zeroed out */
811         memcpy(&rarpreq.thwaddr, arptable[ARP_CLIENT].node, ETH_ALEN);
812         /* tipaddr is already zeroed out */
813
814         for (retry = 0; retry < MAX_ARP_RETRIES; ++retry) {
815                 long timeout;
816                 eth_transmit(broadcast, ETH_P_RARP, sizeof(rarpreq), &rarpreq);
817
818                 timeout = rfc2131_sleep_interval(TIMEOUT, retry);
819                 if (await_reply(await_rarp, 0, rarpreq.shwaddr, timeout))
820                         break;
821         }
822
823         if (retry < MAX_ARP_RETRIES) {
824                 (void)sprintf(KERNEL_BUF, DEFAULT_KERNELPATH, arptable[ARP_CLIENT].ipaddr);
825
826                 return (1);
827         }
828         return (0);
829 }
830
831 #else
832
833 /**************************************************************************
834 BOOTP - Get my IP address and load information
835 **************************************************************************/
836 static int await_bootp(int ival __unused, void *ptr __unused,
837         unsigned short ptype __unused, struct iphdr *ip __unused, 
838         struct udphdr *udp, struct tcphdr *tcp __unused)
839 {
840         struct  bootp_t *bootpreply;
841         if (!udp) {
842                 return 0;
843         }
844         bootpreply = (struct bootp_t *)&nic->packet[ETH_HLEN + 
845                 sizeof(struct iphdr) + sizeof(struct udphdr)];
846         if (nic->packetlen < ETH_HLEN + sizeof(struct iphdr) + 
847                 sizeof(struct udphdr) + 
848 #ifdef NO_DHCP_SUPPORT
849                 sizeof(struct bootp_t)
850 #else
851                 sizeof(struct bootp_t) - DHCP_OPT_LEN
852 #endif  /* NO_DHCP_SUPPORT */
853                 ) {
854                 return 0;
855         }
856         if (udp->dest != htons(BOOTP_CLIENT))
857                 return 0;
858         if (bootpreply->bp_op != BOOTP_REPLY)
859                 return 0;
860         if (bootpreply->bp_xid != xid)
861                 return 0;
862         if (memcmp(&bootpreply->bp_siaddr, &zeroIP, sizeof(in_addr)) == 0)
863                 return 0;
864         if ((memcmp(broadcast, bootpreply->bp_hwaddr, ETH_ALEN) != 0) &&
865                 (memcmp(arptable[ARP_CLIENT].node, bootpreply->bp_hwaddr, ETH_ALEN) != 0)) {
866                 return 0;
867         }
868         if ( bootpreply->bp_siaddr.s_addr ) {
869                 arptable[ARP_SERVER].ipaddr.s_addr = bootpreply->bp_siaddr.s_addr;
870                 memset(arptable[ARP_SERVER].node, 0, ETH_ALEN);  /* Kill arp */
871         }
872         if ( bootpreply->bp_giaddr.s_addr ) {
873                 arptable[ARP_GATEWAY].ipaddr.s_addr = bootpreply->bp_giaddr.s_addr;
874                 memset(arptable[ARP_GATEWAY].node, 0, ETH_ALEN);  /* Kill arp */
875         }
876         if (bootpreply->bp_yiaddr.s_addr) {
877                 /* Offer with an IP address */
878                 arptable[ARP_CLIENT].ipaddr.s_addr = bootpreply->bp_yiaddr.s_addr;
879 #ifndef NO_DHCP_SUPPORT
880                 dhcp_addr.s_addr = bootpreply->bp_yiaddr.s_addr;
881 #endif  /* NO_DHCP_SUPPORT */
882                 netmask = default_netmask();
883                 /* bootpreply->bp_file will be copied to KERNEL_BUF in the memcpy */
884                 memcpy((char *)BOOTP_DATA_ADDR, (char *)bootpreply, sizeof(struct bootpd_t));
885                 decode_rfc1533(BOOTP_DATA_ADDR->bootp_reply.bp_vend, 0,
886 #ifdef  NO_DHCP_SUPPORT
887                                BOOTP_VENDOR_LEN + MAX_BOOTP_EXTLEN, 
888 #else
889                                DHCP_OPT_LEN + MAX_BOOTP_EXTLEN, 
890 #endif  /* NO_DHCP_SUPPORT */
891                                1);
892 #ifdef PXE_EXPORT
893         } else {
894                 /* Offer without an IP address - use as ProxyDHCP server */
895                 arptable[ARP_PROXYDHCP].ipaddr.s_addr = bootpreply->bp_siaddr.s_addr;
896                 memset(arptable[ARP_PROXYDHCP].node, 0, ETH_ALEN);       /* Kill arp */
897                 /* Grab only the bootfile name from a ProxyDHCP packet */
898                 memcpy(KERNEL_BUF, bootpreply->bp_file, sizeof(KERNEL_BUF));
899 #endif /* PXE_EXPORT */
900         }
901 #ifdef  REQUIRE_VCI_ETHERBOOT
902         if (!vci_etherboot)
903                 return (0);
904 #endif
905         return(1);
906 }
907
908 static int bootp(void)
909 {
910         int retry;
911 #ifndef NO_DHCP_SUPPORT
912         int reqretry;
913 #endif  /* NO_DHCP_SUPPORT */
914         struct bootpip_t ip;
915         unsigned long  starttime;
916         unsigned char *bp_vend;
917
918 #ifndef NO_DHCP_SUPPORT
919         dhcp_machine_info[4] = dev.devid.bus_type;
920         dhcp_machine_info[5] = dev.devid.vendor_id & 0xff;
921         dhcp_machine_info[6] = ((dev.devid.vendor_id) >> 8) & 0xff;
922         dhcp_machine_info[7] = dev.devid.device_id & 0xff;
923         dhcp_machine_info[8] = ((dev.devid.device_id) >> 8) & 0xff;
924 #endif  /* NO_DHCP_SUPPORT */
925         memset(&ip, 0, sizeof(struct bootpip_t));
926         ip.bp.bp_op = BOOTP_REQUEST;
927         ip.bp.bp_htype = 1;
928         ip.bp.bp_hlen = ETH_ALEN;
929         starttime = currticks();
930         /* Use lower 32 bits of node address, more likely to be
931            distinct than the time since booting */
932         memcpy(&xid, &arptable[ARP_CLIENT].node[2], sizeof(xid));
933         ip.bp.bp_xid = xid += htonl(starttime);
934         memcpy(ip.bp.bp_hwaddr, arptable[ARP_CLIENT].node, ETH_ALEN);
935 #ifdef  NO_DHCP_SUPPORT
936         memcpy(ip.bp.bp_vend, rfc1533_cookie, 5); /* request RFC-style options */
937 #else
938         memcpy(ip.bp.bp_vend, rfc1533_cookie, sizeof rfc1533_cookie); /* request RFC-style options */
939         memcpy(ip.bp.bp_vend + sizeof rfc1533_cookie, dhcpdiscover, sizeof dhcpdiscover);
940         /* Append machine_info to end, in encapsulated option */
941         bp_vend = ip.bp.bp_vend + sizeof rfc1533_cookie + sizeof dhcpdiscover;
942         memcpy(bp_vend, dhcp_machine_info, DHCP_MACHINE_INFO_SIZE);
943         bp_vend += DHCP_MACHINE_INFO_SIZE;
944         *bp_vend++ = RFC1533_END;
945 #endif  /* NO_DHCP_SUPPORT */
946
947         for (retry = 0; retry < MAX_BOOTP_RETRIES; ) {
948                 uint8_t my_hwaddr[ETH_ALEN];
949                 unsigned long stop_time;
950                 long remaining_time;
951
952                 rx_qdrain();
953
954                 /* Kill arptable to avoid keeping stale entries */
955                 memcpy ( my_hwaddr, arptable[ARP_CLIENT].node, ETH_ALEN );
956                 memset ( arptable, 0, sizeof(arptable) );
957                 memcpy ( arptable[ARP_CLIENT].node, my_hwaddr, ETH_ALEN );
958
959                 udp_transmit(IP_BROADCAST, BOOTP_CLIENT, BOOTP_SERVER,
960                         sizeof(struct bootpip_t), &ip);
961                 remaining_time = rfc2131_sleep_interval(BOOTP_TIMEOUT, retry++);
962                 stop_time = currticks() + remaining_time;
963 #ifdef  NO_DHCP_SUPPORT
964                 if (await_reply(await_bootp, 0, NULL, timeout))
965                         return(1);
966 #else
967                 while ( remaining_time > 0 ) {
968                         if (await_reply(await_bootp, 0, NULL, remaining_time)){
969                         }
970                         remaining_time = stop_time - currticks();
971                 }
972                 if ( ! arptable[ARP_CLIENT].ipaddr.s_addr ) {
973                         printf("No IP address\n");
974                         continue;
975                 }
976                 /* If not a DHCPOFFER then must be just a BOOTP reply,
977                  * be backward compatible with BOOTP then */
978                 if (dhcp_reply != DHCPOFFER)
979                         return(1);
980                 dhcp_reply = 0;
981                 /* Construct the DHCPREQUEST packet */
982                 memcpy(ip.bp.bp_vend, rfc1533_cookie, sizeof rfc1533_cookie);
983                 memcpy(ip.bp.bp_vend + sizeof rfc1533_cookie, dhcprequest, sizeof dhcprequest);
984                 /* Beware: the magic numbers 9 and 15 depend on
985                    the layout of dhcprequest */
986                 memcpy(&ip.bp.bp_vend[9], &dhcp_server, sizeof(in_addr));
987                 memcpy(&ip.bp.bp_vend[15], &dhcp_addr, sizeof(in_addr));
988                 bp_vend = ip.bp.bp_vend + sizeof rfc1533_cookie + sizeof dhcprequest;
989                 /* Append machine_info to end, in encapsulated option */
990                 memcpy(bp_vend, dhcp_machine_info, DHCP_MACHINE_INFO_SIZE);
991                 bp_vend += DHCP_MACHINE_INFO_SIZE;
992                 *bp_vend++ = RFC1533_END;
993                 for (reqretry = 0; reqretry < MAX_BOOTP_RETRIES; ) {
994                         unsigned long timeout;
995
996                         udp_transmit(IP_BROADCAST, BOOTP_CLIENT, BOOTP_SERVER,
997                                      sizeof(struct bootpip_t), &ip);
998                         dhcp_reply=0;
999                         timeout = rfc2131_sleep_interval(TIMEOUT, reqretry++);
1000                         if (!await_reply(await_bootp, 0, NULL, timeout))
1001                                 continue;
1002                         if (dhcp_reply != DHCPACK)
1003                                 continue;
1004                         dhcp_reply = 0;
1005 #ifdef PXE_EXPORT                       
1006                         if ( arptable[ARP_PROXYDHCP].ipaddr.s_addr ) {
1007                                 /* Construct the ProxyDHCPREQUEST packet */
1008                                 memcpy(ip.bp.bp_vend, rfc1533_cookie, sizeof rfc1533_cookie);
1009                                 memcpy(ip.bp.bp_vend + sizeof rfc1533_cookie, proxydhcprequest, sizeof proxydhcprequest);
1010                                 for (reqretry = 0; reqretry < MAX_BOOTP_RETRIES; ) {
1011                                         printf ( "\nSending ProxyDHCP request to %@...", arptable[ARP_PROXYDHCP].ipaddr.s_addr);
1012                                         udp_transmit(arptable[ARP_PROXYDHCP].ipaddr.s_addr, BOOTP_CLIENT, PROXYDHCP_SERVER,
1013                                                      sizeof(struct bootpip_t), &ip);
1014                                         timeout = rfc2131_sleep_interval(TIMEOUT, reqretry++);
1015                                         if (await_reply(await_bootp, 0, NULL, timeout)) {
1016                                                 break;
1017                                         }
1018                                 }
1019                         }
1020 #endif /* PXE_EXPORT */
1021                         return(1);
1022                 }
1023 #endif  /* NO_DHCP_SUPPORT */
1024                 ip.bp.bp_secs = htons((currticks()-starttime)/TICKS_PER_SEC);
1025         }
1026         return(0);
1027 }
1028 #endif  /* RARP_NOT_BOOTP */
1029
1030 static uint16_t tcpudpchksum(struct iphdr *ip)
1031 {
1032         struct udp_pseudo_hdr pseudo;
1033         uint16_t checksum;
1034
1035         /* Compute the pseudo header */
1036         pseudo.src.s_addr  = ip->src.s_addr;
1037         pseudo.dest.s_addr = ip->dest.s_addr;
1038         pseudo.unused      = 0;
1039         pseudo.protocol    = ip->protocol;
1040         pseudo.len         = htons(ntohs(ip->len) - sizeof(struct iphdr));
1041
1042         /* Sum the pseudo header */
1043         checksum = ipchksum(&pseudo, 12);
1044
1045         /* Sum the rest of the tcp/udp packet */
1046         checksum = add_ipchksums(12, checksum, ipchksum(ip + 1,
1047                                  ntohs(ip->len) - sizeof(struct iphdr)));
1048         return checksum;
1049 }
1050
1051 #ifdef MULTICAST_LEVEL2
1052 static void send_igmp_reports(unsigned long now)
1053 {
1054         int i;
1055         for(i = 0; i < MAX_IGMP; i++) {
1056                 if (igmptable[i].time && (now >= igmptable[i].time)) {
1057                         struct igmp_ip_t igmp;
1058                         igmp.router_alert[0] = 0x94;
1059                         igmp.router_alert[1] = 0x04;
1060                         igmp.router_alert[2] = 0;
1061                         igmp.router_alert[3] = 0;
1062                         build_ip_hdr(igmptable[i].group.s_addr, 
1063                                 1, IP_IGMP, sizeof(igmp.router_alert), sizeof(igmp), &igmp);
1064                         igmp.igmp.type = IGMPv2_REPORT;
1065                         if (last_igmpv1 && 
1066                                 (now < last_igmpv1 + IGMPv1_ROUTER_PRESENT_TIMEOUT)) {
1067                                 igmp.igmp.type = IGMPv1_REPORT;
1068                         }
1069                         igmp.igmp.response_time = 0;
1070                         igmp.igmp.chksum = 0;
1071                         igmp.igmp.group.s_addr = igmptable[i].group.s_addr;
1072                         igmp.igmp.chksum = ipchksum(&igmp.igmp, sizeof(igmp.igmp));
1073                         ip_transmit(sizeof(igmp), &igmp);
1074 #ifdef  MDEBUG
1075                         printf("Sent IGMP report to: %@\n", igmp.igmp.group.s_addr);
1076 #endif
1077                         /* Don't send another igmp report until asked */
1078                         igmptable[i].time = 0;
1079                 }
1080         }
1081 }
1082
1083 static void process_igmp(struct iphdr *ip, unsigned long now)
1084 {
1085         struct igmp *igmp;
1086         int i;
1087         unsigned iplen;
1088         if (!ip || (ip->protocol == IP_IGMP) ||
1089                 (nic->packetlen < sizeof(struct iphdr) + sizeof(struct igmp))) {
1090                 return;
1091         }
1092         iplen = (ip->verhdrlen & 0xf)*4;
1093         igmp = (struct igmp *)&nic->packet[sizeof(struct iphdr)];
1094         if (ipchksum(igmp, ntohs(ip->len) - iplen) != 0)
1095                 return;
1096         if ((igmp->type == IGMP_QUERY) && 
1097                 (ip->dest.s_addr == htonl(GROUP_ALL_HOSTS))) {
1098                 unsigned long interval = IGMP_INTERVAL;
1099                 if (igmp->response_time == 0) {
1100                         last_igmpv1 = now;
1101                 } else {
1102                         interval = (igmp->response_time * TICKS_PER_SEC)/10;
1103                 }
1104                 
1105 #ifdef  MDEBUG
1106                 printf("Received IGMP query for: %@\n", igmp->group.s_addr);
1107 #endif                         
1108                 for(i = 0; i < MAX_IGMP; i++) {
1109                         uint32_t group = igmptable[i].group.s_addr;
1110                         if ((group == 0) || (group == igmp->group.s_addr)) {
1111                                 unsigned long time;
1112                                 time = currticks() + rfc1112_sleep_interval(interval, 0);
1113                                 if (time < igmptable[i].time) {
1114                                         igmptable[i].time = time;
1115                                 }
1116                         }
1117                 }
1118         }
1119         if (((igmp->type == IGMPv1_REPORT) || (igmp->type == IGMPv2_REPORT)) &&
1120                 (ip->dest.s_addr == igmp->group.s_addr)) {
1121 #ifdef  MDEBUG
1122                 printf("Received IGMP report for: %@\n", igmp->group.s_addr);
1123 #endif                         
1124                 for(i = 0; i < MAX_IGMP; i++) {
1125                         if ((igmptable[i].group.s_addr == igmp->group.s_addr) &&
1126                                 igmptable[i].time != 0) {
1127                                 igmptable[i].time = 0;
1128                         }
1129                 }
1130         }
1131 }
1132
1133 void leave_group(int slot)
1134 {
1135         /* Be very stupid and always send a leave group message if 
1136          * I have subscribed.  Imperfect but it is standards
1137          * compliant, easy and reliable to implement.
1138          *
1139          * The optimal group leave method is to only send leave when,
1140          * we were the last host to respond to a query on this group,
1141          * and igmpv1 compatibility is not enabled.
1142          */
1143         if (igmptable[slot].group.s_addr) {
1144                 struct igmp_ip_t igmp;
1145                 igmp.router_alert[0] = 0x94;
1146                 igmp.router_alert[1] = 0x04;
1147                 igmp.router_alert[2] = 0;
1148                 igmp.router_alert[3] = 0;
1149                 build_ip_hdr(htonl(GROUP_ALL_HOSTS),
1150                         1, IP_IGMP, sizeof(igmp.router_alert), sizeof(igmp), &igmp);
1151                 igmp.igmp.type = IGMP_LEAVE;
1152                 igmp.igmp.response_time = 0;
1153                 igmp.igmp.chksum = 0;
1154                 igmp.igmp.group.s_addr = igmptable[slot].group.s_addr;
1155                 igmp.igmp.chksum = ipchksum(&igmp.igmp, sizeof(igmp));
1156                 ip_transmit(sizeof(igmp), &igmp);
1157 #ifdef  MDEBUG
1158                 printf("Sent IGMP leave for: %@\n", igmp.igmp.group.s_addr);
1159 #endif  
1160         }
1161         memset(&igmptable[slot], 0, sizeof(igmptable[0]));
1162 }
1163
1164 void join_group(int slot, unsigned long group)
1165 {
1166         /* I have already joined */
1167         if (igmptable[slot].group.s_addr == group)
1168                 return;
1169         if (igmptable[slot].group.s_addr) {
1170                 leave_group(slot);
1171         }
1172         /* Only join a group if we are given a multicast ip, this way
1173          * code can be given a non-multicast (broadcast or unicast ip)
1174          * and still work... 
1175          */
1176         if ((group & htonl(MULTICAST_MASK)) == htonl(MULTICAST_NETWORK)) {
1177                 igmptable[slot].group.s_addr = group;
1178                 igmptable[slot].time = currticks();
1179         }
1180 }
1181 #else
1182 #define send_igmp_reports(now) do {} while(0)
1183 #define process_igmp(ip, now)  do {} while(0)
1184 #endif
1185
1186 #include "proto_eth_slow.c"
1187
1188 /**************************************************************************
1189 TCP - Simple-minded TCP stack. Can only send data once and then
1190       receive the response. The algorithm for computing window
1191       sizes and delaying ack's is currently broken, and thus
1192       disabled. Performance would probably improve a little, if
1193       this gets fixed. FIXME
1194 **************************************************************************/
1195 #ifdef DOWNLOAD_PROTO_HTTP
1196 static int await_tcp(int ival, void *ptr, unsigned short ptype __unused,
1197                     struct iphdr *ip, struct udphdr *udp __unused,
1198                     struct tcphdr *tcp)
1199 {
1200        if (!tcp) {
1201                return 0;
1202        }
1203        if (arptable[ARP_CLIENT].ipaddr.s_addr != ip->dest.s_addr)
1204                return 0;
1205        if (ntohs(tcp->dst) != ival) {
1206                tcp_reset(ip);
1207                return 0;
1208        }
1209        *(void **)ptr = tcp;
1210        return 1;
1211 }
1212
1213 int tcp_transaction(unsigned long destip, unsigned int destsock, void *ptr,
1214                    int (*send)(int len, void *buf, void *ptr),
1215                    int (*recv)(int len, const void *buf, void *ptr)) {
1216        static uint16_t srcsock = 0;
1217        int             rc = 1;
1218        long            send_seq = currticks();
1219        long            recv_seq = 0;
1220        int             can_send = 0;
1221        int             sent_all = 0;
1222        struct iphdr   *ip;
1223        struct tcphdr  *tcp;
1224        int             ctrl = SYN;
1225        char            buf[128]; /* Small outgoing buffer */
1226        long            payload;
1227        int             header_size;
1228        int             window = 3*TCP_MIN_WINDOW;
1229        long            last_ack = 0;
1230        long            last_sent = 0;
1231        long            rtt = 0;
1232        long            srtt = 0;
1233        long            rto = TCP_INITIAL_TIMEOUT;
1234        int             retry = TCP_MAX_TIMEOUT/TCP_INITIAL_TIMEOUT;
1235        enum { CLOSED, SYN_RCVD, ESTABLISHED,
1236               FIN_WAIT_1, FIN_WAIT_2 } state = CLOSED;
1237
1238        if (!srcsock) {
1239                srcsock = currticks();
1240        }
1241        if (++srcsock < 1024)
1242                srcsock += 1024;
1243
1244        await_reply(await_qdrain, 0, NULL, 0);
1245
1246  send_data:
1247        if (ctrl & ACK)
1248                last_ack = recv_seq;
1249        if (!tcp_transmit(destip, srcsock, destsock, send_seq,
1250                          recv_seq, window, ctrl,
1251                          sizeof(struct iphdr) + sizeof(struct tcphdr)+
1252                          can_send, buf)) {
1253                return (0);
1254        }
1255        last_sent = currticks();
1256
1257  recv_data:
1258        if (!await_reply(await_tcp, srcsock, &tcp,
1259                         (state == ESTABLISHED && !can_send)
1260                         ? TCP_MAX_TIMEOUT : rto)) {
1261                if (state == ESTABLISHED) {
1262  close:
1263                        ctrl = FIN|ACK;
1264                        state = FIN_WAIT_1;
1265                        rc = 0;
1266                        goto send_data;
1267                }
1268
1269                if (state == FIN_WAIT_1 || state == FIN_WAIT_2)
1270                        return (rc);
1271
1272                if (--retry <= 0) {
1273                        /* time out */
1274                        if (state == SYN_RCVD) {
1275                                tcp_transmit(destip, srcsock, destsock,
1276                                             send_seq, 0, window, RST,
1277                                             sizeof(struct iphdr) +
1278                                             sizeof(struct tcphdr), buf);
1279                        }
1280                        return (0);
1281                }
1282                /* retransmit */
1283                goto send_data;
1284        }
1285  got_data:
1286        retry = TCP_MAX_RETRY;
1287
1288        if (tcp->ctrl & htons(ACK) ) {
1289                char *data;
1290                int syn_ack, consumed;
1291
1292                if (state == FIN_WAIT_1 || state == FIN_WAIT_2) {
1293                        state = FIN_WAIT_2;
1294                        ctrl = ACK;
1295                        goto consume_data;
1296                }
1297                syn_ack = state == CLOSED || state == SYN_RCVD;
1298                consumed = ntohl(tcp->ack) - send_seq - syn_ack;
1299                if (consumed < 0 || consumed > can_send) {
1300                        tcp_reset((struct iphdr *)&nic->packet[ETH_HLEN]);
1301                        goto recv_data;
1302                }
1303
1304                rtt = currticks() - last_sent;
1305                srtt = !srtt ? rtt : (srtt*4 + rtt)/5;
1306                rto = srtt + srtt/2;
1307                if (rto < TCP_MIN_TIMEOUT)
1308                        rto = TCP_MIN_TIMEOUT;
1309                else if (rto > TCP_MAX_TIMEOUT)
1310                        rto = TCP_MAX_TIMEOUT;
1311
1312                can_send -= consumed;
1313                send_seq += consumed + syn_ack;
1314                data = buf + sizeof(struct iphdr) + sizeof(struct tcphdr);
1315                if (can_send) {
1316                        memmove(data, data + consumed, can_send);
1317                }
1318                if (!sent_all) {
1319                        int more_data;
1320                        data += can_send;
1321                        more_data = buf + sizeof(buf) - data;
1322                        if (more_data > 0) {
1323                                more_data = send(more_data, data, ptr);
1324                                can_send += more_data;
1325                        }
1326                        sent_all = !more_data;
1327                }
1328                if (state == SYN_RCVD) {
1329                        state = ESTABLISHED;
1330                        ctrl = PSH|ACK;
1331                        goto consume_data;
1332                }
1333                if (tcp->ctrl & htons(RST))
1334                        return (0);
1335        } else if (tcp->ctrl & htons(RST)) {
1336                if (state == CLOSED)
1337                        goto recv_data;
1338                return (0);
1339        }
1340
1341  consume_data:
1342        ip  = (struct iphdr *)&nic->packet[ETH_HLEN];
1343        header_size = sizeof(struct iphdr) + ((ntohs(tcp->ctrl)>>10)&0x3C);
1344        payload = ntohs(ip->len) - header_size;
1345        if (payload > 0 && state == ESTABLISHED) {
1346                int old_bytes = recv_seq - (long)ntohl(tcp->seq);
1347                if (old_bytes >= 0 && payload - old_bytes > 0) {
1348                        recv_seq += payload - old_bytes;
1349                        if (state != FIN_WAIT_1 && state != FIN_WAIT_2 &&
1350                            !recv(payload - old_bytes,
1351                                  &nic->packet[ETH_HLEN+header_size+old_bytes],
1352                                  ptr)) {
1353                                goto close;
1354                        }
1355                        if ((state == ESTABLISHED || state == SYN_RCVD) &&
1356                            !(tcp->ctrl & htons(FIN))) {
1357                                int in_window = window - 2*TCP_MIN_WINDOW >
1358                                                 recv_seq - last_ack;
1359                                ctrl = can_send ? PSH|ACK : ACK;
1360                                if (!can_send && in_window) {
1361 /* Window scaling is broken right now, just fall back to acknowledging every */
1362 /* packet immediately and unconditionally. FIXME                       */ /***/
1363 /*                                     if (await_reply(await_tcp, srcsock,
1364                                                        &tcp, rto))
1365                                                goto got_data;
1366                                        else */
1367                                                goto send_data;
1368                                }
1369                                if (!in_window) {
1370                                        window += TCP_MIN_WINDOW;
1371                                        if (window > TCP_MAX_WINDOW)
1372                                                window = TCP_MAX_WINDOW;
1373                                }
1374                                goto send_data;
1375                        }
1376                } else {
1377                        /* saw old data again, must have lost packets */
1378                        window /= 2;
1379                        if (window < 2*TCP_MIN_WINDOW)
1380                                window = 2*TCP_MIN_WINDOW;
1381                }
1382        }
1383
1384        if (tcp->ctrl & htons(FIN)) {
1385                if (state == ESTABLISHED) {
1386                        ctrl = FIN|ACK;
1387                } else if (state == FIN_WAIT_1 || state == FIN_WAIT_2) {
1388                        ctrl = ACK;
1389                } else {
1390                        ctrl = RST;
1391                }
1392                return (tcp_transmit(destip, srcsock, destsock,
1393                                     send_seq, recv_seq + 1, window, ctrl,
1394                                     sizeof(struct iphdr) +
1395                                     sizeof(struct tcphdr), buf) &&
1396                        (state == ESTABLISHED ||
1397                         state == FIN_WAIT_1 || state == FIN_WAIT_2) &&
1398                        !can_send);
1399        }
1400
1401        if (state == CLOSED) {
1402                if (tcp->ctrl & htons(SYN)) {
1403                        recv_seq = ntohl(tcp->seq) + 1;
1404                        if (!(tcp->ctrl & htons(ACK))) {
1405                                state = SYN_RCVD;
1406                                ctrl = SYN|ACK|PSH;
1407                                goto send_data;
1408                        } else {
1409                                state = ESTABLISHED;
1410                                ctrl = PSH|ACK;
1411                        }
1412                }
1413        }
1414
1415        if (can_send || payload) {
1416                goto send_data;
1417        }
1418        goto recv_data;
1419 }
1420 #endif
1421
1422 /**************************************************************************
1423 AWAIT_REPLY - Wait until we get a response for our request
1424 ************f**************************************************************/
1425 int await_reply(reply_t reply, int ival, void *ptr, long timeout)
1426 {
1427         unsigned long time, now;
1428         struct  iphdr *ip;
1429         unsigned iplen = 0;
1430         struct  udphdr *udp;
1431         struct  tcphdr *tcp;
1432         unsigned short ptype;
1433         int result;
1434
1435         time = timeout + currticks();
1436         /* The timeout check is done below.  The timeout is only checked if
1437          * there is no packet in the Rx queue.  This assumes that eth_poll()
1438          * needs a negligible amount of time.  
1439          */
1440         for (;;) {
1441                 now = currticks();
1442                 send_eth_slow_reports(now);
1443                 send_igmp_reports(now);
1444                 result = eth_poll(1);
1445                 if (result == 0) {
1446                         /* We don't have anything */
1447                 
1448                         /* Check for abort key only if the Rx queue is empty -
1449                          * as long as we have something to process, don't
1450                          * assume that something failed.  It is unlikely that
1451                          * we have no processing time left between packets.  */
1452                         poll_interruptions();
1453                         /* Do the timeout after at least a full queue walk.  */
1454                         if ((timeout == 0) || (currticks() > time)) {
1455                                 break;
1456                         }
1457                         continue;
1458                 }
1459         
1460                 /* We have something! */
1461
1462                 /* Find the Ethernet packet type */
1463                 if (nic->packetlen >= ETH_HLEN) {
1464                         ptype = ((unsigned short) nic->packet[12]) << 8
1465                                 | ((unsigned short) nic->packet[13]);
1466                 } else continue; /* what else could we do with it? */
1467                 /* Verify an IP header */
1468                 ip = 0;
1469                 if ((ptype == ETH_P_IP) && (nic->packetlen >= ETH_HLEN + sizeof(struct iphdr))) {
1470                         unsigned ipoptlen;
1471                         ip = (struct iphdr *)&nic->packet[ETH_HLEN];
1472                         if ((ip->verhdrlen < 0x45) || (ip->verhdrlen > 0x4F)) 
1473                                 continue;
1474                         iplen = (ip->verhdrlen & 0xf) * 4;
1475                         if (ipchksum(ip, iplen) != 0)
1476                                 continue;
1477                         if (ip->frags & htons(0x3FFF)) {
1478                                 static int warned_fragmentation = 0;
1479                                 if (!warned_fragmentation) {
1480                                         printf("ALERT: got a fragmented packet - reconfigure your server\n");
1481                                         warned_fragmentation = 1;
1482                                 }
1483                                 continue;
1484                         }
1485                         if (ntohs(ip->len) > ETH_MAX_MTU)
1486                                 continue;
1487
1488                         ipoptlen = iplen - sizeof(struct iphdr);
1489                         if (ipoptlen) {
1490                                 /* Delete the ip options, to guarantee
1491                                  * good alignment, and make etherboot simpler.
1492                                  */
1493                                 memmove(&nic->packet[ETH_HLEN + sizeof(struct iphdr)], 
1494                                         &nic->packet[ETH_HLEN + iplen],
1495                                         nic->packetlen - ipoptlen);
1496                                 nic->packetlen -= ipoptlen;
1497                         }
1498                 }
1499                 udp = 0;
1500                 if (ip && (ip->protocol == IP_UDP) && 
1501                         (nic->packetlen >= 
1502                         ETH_HLEN + sizeof(struct iphdr) + sizeof(struct udphdr))) {
1503                         udp = (struct udphdr *)&nic->packet[ETH_HLEN + sizeof(struct iphdr)];
1504
1505                         /* Make certain we have a reasonable packet length */
1506                         if (ntohs(udp->len) > (ntohs(ip->len) - iplen))
1507                                 continue;
1508
1509                         if (udp->chksum && tcpudpchksum(ip)) {
1510                                 printf("UDP checksum error\n");
1511                                 continue;
1512                         }
1513                 }
1514                 tcp = 0;
1515 #ifdef DOWNLOAD_PROTO_HTTP
1516                 if (ip && (ip->protocol == IP_TCP) &&
1517                     (nic->packetlen >=
1518                      ETH_HLEN + sizeof(struct iphdr) + sizeof(struct tcphdr))){
1519                         tcp = (struct tcphdr *)&nic->packet[ETH_HLEN +
1520                                                          sizeof(struct iphdr)];
1521                         /* Make certain we have a reasonable packet length */
1522                         if (((ntohs(tcp->ctrl) >> 10) & 0x3C) >
1523                             ntohs(ip->len) - (int)iplen)
1524                                 continue;
1525                         if (tcpudpchksum(ip)) {
1526                                 printf("TCP checksum error\n");
1527                                 continue;
1528                         }
1529
1530                 }
1531 #endif
1532                 result = reply(ival, ptr, ptype, ip, udp, tcp);
1533                 if (result > 0) {
1534                         return result;
1535                 }
1536                 
1537                 /* If it isn't a packet the upper layer wants see if there is a default
1538                  * action.  This allows us reply to arp, igmp, and lacp queries.
1539                  */
1540                 if ((ptype == ETH_P_ARP) &&
1541                         (nic->packetlen >= ETH_HLEN + sizeof(struct arprequest))) {
1542                         struct  arprequest *arpreply;
1543                         unsigned long tmp;
1544                 
1545                         arpreply = (struct arprequest *)&nic->packet[ETH_HLEN];
1546                         memcpy(&tmp, arpreply->tipaddr, sizeof(in_addr));
1547                         if ((arpreply->opcode == htons(ARP_REQUEST)) &&
1548                                 (tmp == arptable[ARP_CLIENT].ipaddr.s_addr)) {
1549                                 arpreply->opcode = htons(ARP_REPLY);
1550                                 memcpy(arpreply->tipaddr, arpreply->sipaddr, sizeof(in_addr));
1551                                 memcpy(arpreply->thwaddr, arpreply->shwaddr, ETH_ALEN);
1552                                 memcpy(arpreply->sipaddr, &arptable[ARP_CLIENT].ipaddr, sizeof(in_addr));
1553                                 memcpy(arpreply->shwaddr, arptable[ARP_CLIENT].node, ETH_ALEN);
1554                                 eth_transmit(arpreply->thwaddr, ETH_P_ARP,
1555                                         sizeof(struct  arprequest),
1556                                         arpreply);
1557 #ifdef  MDEBUG
1558                                 memcpy(&tmp, arpreply->tipaddr, sizeof(in_addr));
1559                                 printf("Sent ARP reply to: %@\n",tmp);
1560 #endif  /* MDEBUG */
1561                         }
1562                 }
1563                 process_eth_slow(ptype, now);
1564                 process_igmp(ip, now);
1565         }
1566         return(0);
1567 }
1568
1569 #ifdef  REQUIRE_VCI_ETHERBOOT
1570 /**************************************************************************
1571 FIND_VCI_ETHERBOOT - Looks for "Etherboot" in Vendor Encapsulated Identifiers
1572 On entry p points to byte count of VCI options
1573 **************************************************************************/
1574 static int find_vci_etherboot(unsigned char *p)
1575 {
1576         unsigned char   *end = p + 1 + *p;
1577
1578         for (p++; p < end; ) {
1579                 if (*p == RFC2132_VENDOR_CLASS_ID) {
1580                         if (strncmp("Etherboot", p + 2, sizeof("Etherboot") - 1) == 0)
1581                                 return (1);
1582                 } else if (*p == RFC1533_END)
1583                         return (0);
1584                 p += TAG_LEN(p) + 2;
1585         }
1586         return (0);
1587 }
1588 #endif  /* REQUIRE_VCI_ETHERBOOT */
1589
1590 /**************************************************************************
1591 DECODE_RFC1533 - Decodes RFC1533 header
1592 **************************************************************************/
1593 int decode_rfc1533(unsigned char *p, unsigned int block, unsigned int len, int eof)
1594 {
1595         static unsigned char *extdata = NULL, *extend = NULL;
1596         unsigned char        *extpath = NULL;
1597         unsigned char        *endp;
1598         static unsigned char in_encapsulated_options = 0;
1599
1600         if (eof == -1) {
1601                 /* Encapsulated option block */
1602                 endp = p + len;
1603         }
1604         else if (block == 0) {
1605 #ifdef  REQUIRE_VCI_ETHERBOOT
1606                 vci_etherboot = 0;
1607 #endif
1608                 end_of_rfc1533 = NULL;
1609 #ifdef  IMAGE_FREEBSD
1610                 /* yes this is a pain FreeBSD uses this for swap, however,
1611                    there are cases when you don't want swap and then
1612                    you want this set to get the extra features so lets
1613                    just set if dealing with FreeBSD.  I haven't run into
1614                    any troubles with this but I have without it
1615                 */
1616                 vendorext_isvalid = 1;
1617 #ifdef FREEBSD_KERNEL_ENV
1618                 memcpy(freebsd_kernel_env, FREEBSD_KERNEL_ENV,
1619                        sizeof(FREEBSD_KERNEL_ENV));
1620                 /* FREEBSD_KERNEL_ENV had better be a string constant */
1621 #else
1622                 freebsd_kernel_env[0]='\0';
1623 #endif
1624 #else
1625                 vendorext_isvalid = 0;
1626 #endif
1627                 if (memcmp(p, rfc1533_cookie, 4))
1628                         return(0); /* no RFC 1533 header found */
1629                 p += 4;
1630                 endp = p + len;
1631         } else {
1632                 if (block == 1) {
1633                         if (memcmp(p, rfc1533_cookie, 4))
1634                                 return(0); /* no RFC 1533 header found */
1635                         p += 4;
1636                         len -= 4; }
1637                 if (extend + len <= (unsigned char *)&(BOOTP_DATA_ADDR->bootp_extension[MAX_BOOTP_EXTLEN])) {
1638                         memcpy(extend, p, len);
1639                         extend += len;
1640                 } else {
1641                         printf("Overflow in vendor data buffer! Aborting...\n");
1642                         *extdata = RFC1533_END;
1643                         return(0);
1644                 }
1645                 p = extdata; endp = extend;
1646         }
1647         if (!eof)
1648                 return 1;
1649         while (p < endp) {
1650                 unsigned char c = *p;
1651                 if (c == RFC1533_PAD) {
1652                         p++;
1653                         continue;
1654                 }
1655                 else if (c == RFC1533_END) {
1656                         end_of_rfc1533 = endp = p;
1657                         continue;
1658                 }
1659                 else if (NON_ENCAP_OPT c == RFC1533_NETMASK)
1660                         memcpy(&netmask, p+2, sizeof(in_addr));
1661                 else if (NON_ENCAP_OPT c == RFC1533_GATEWAY) {
1662                         /* This is a little simplistic, but it will
1663                            usually be sufficient.
1664                            Take only the first entry */
1665                         if (TAG_LEN(p) >= sizeof(in_addr))
1666                                 memcpy(&arptable[ARP_GATEWAY].ipaddr, p+2, sizeof(in_addr));
1667                 }
1668                 else if (c == RFC1533_EXTENSIONPATH)
1669                         extpath = p;
1670 #ifndef NO_DHCP_SUPPORT
1671 #ifdef  REQUIRE_VCI_ETHERBOOT
1672                 else if (NON_ENCAP_OPT c == RFC1533_VENDOR) {
1673                         vci_etherboot = find_vci_etherboot(p+1);
1674 #ifdef  MDEBUG
1675                         printf("vci_etherboot %d\n", vci_etherboot);
1676 #endif
1677                 }
1678 #endif  /* REQUIRE_VCI_ETHERBOOT */
1679                 else if (NON_ENCAP_OPT c == RFC2132_MSG_TYPE)
1680                         dhcp_reply=*(p+2);
1681                 else if (NON_ENCAP_OPT c == RFC2132_SRV_ID)
1682                         memcpy(&dhcp_server, p+2, sizeof(in_addr));
1683 #endif  /* NO_DHCP_SUPPORT */
1684                 else if (NON_ENCAP_OPT c == RFC1533_HOSTNAME) {
1685                         hostname = p + 2;
1686                         hostnamelen = *(p + 1);
1687                 }
1688                 else if (ENCAP_OPT c == RFC1533_VENDOR_MAGIC
1689                          && TAG_LEN(p) >= 6 &&
1690                           !memcmp(p+2,vendorext_magic,4) &&
1691                           p[6] == RFC1533_VENDOR_MAJOR
1692                         )
1693                         vendorext_isvalid++;
1694                 else if (NON_ENCAP_OPT c == RFC1533_VENDOR_ETHERBOOT_ENCAP) {
1695                         in_encapsulated_options = 1;
1696                         decode_rfc1533(p+2, 0, TAG_LEN(p), -1);
1697                         in_encapsulated_options = 0;
1698                 }
1699 #ifdef  IMAGE_FREEBSD
1700                 else if (NON_ENCAP_OPT c == RFC1533_VENDOR_HOWTO)
1701                         freebsd_howto = ((p[2]*256+p[3])*256+p[4])*256+p[5];
1702                 else if (NON_ENCAP_OPT c == RFC1533_VENDOR_KERNEL_ENV){
1703                         if(*(p + 1) < sizeof(freebsd_kernel_env)){
1704                                 memcpy(freebsd_kernel_env,p+2,*(p+1));
1705                         }else{
1706                                 printf("Only support %ld bytes in Kernel Env\n",
1707                                         sizeof(freebsd_kernel_env));
1708                         }
1709                 }
1710 #endif
1711 #ifdef  DNS_RESOLVER
1712                 else if (NON_ENCAP_OPT c == RFC1533_DNS) {
1713                         // TODO: Copy the DNS IP somewhere reasonable
1714                         if (TAG_LEN(p) >= sizeof(in_addr))
1715                                 memcpy(&arptable[ARP_NAMESERVER].ipaddr, p+2, sizeof(in_addr));
1716                 }
1717 #endif
1718                 else {
1719 #if 0
1720                         unsigned char *q;
1721                         printf("Unknown RFC1533-tag ");
1722                         for(q=p;q<p+2+TAG_LEN(p);q++)
1723                                 printf("%hhX ",*q);
1724                         putchar('\n');
1725 #endif
1726                 }
1727                 p += TAG_LEN(p) + 2;
1728         }
1729         extdata = extend = endp;
1730         if (block <= 0 && extpath != NULL) {
1731                 char fname[64];
1732                 memcpy(fname, extpath+2, TAG_LEN(extpath));
1733                 fname[(int)TAG_LEN(extpath)] = '\0';
1734                 printf("Loading BOOTP-extension file: %s\n",fname);
1735                 tftp(fname, decode_rfc1533);
1736         }
1737         return 1;       /* proceed with next block */
1738 }
1739
1740
1741 /* FIXME double check TWO_SECOND_DIVISOR */
1742 #define TWO_SECOND_DIVISOR (RAND_MAX/TICKS_PER_SEC)
1743 /**************************************************************************
1744 RFC2131_SLEEP_INTERVAL - sleep for expotentially longer times (base << exp) +- 1 sec)
1745 **************************************************************************/
1746 long rfc2131_sleep_interval(long base, int exp)
1747 {
1748         unsigned long tmo;
1749 #ifdef BACKOFF_LIMIT
1750         if (exp > BACKOFF_LIMIT)
1751                 exp = BACKOFF_LIMIT;
1752 #endif
1753         tmo = (base << exp) + (TICKS_PER_SEC - (random()/TWO_SECOND_DIVISOR));
1754         return tmo;
1755 }
1756
1757 #ifdef MULTICAST_LEVEL2
1758 /**************************************************************************
1759 RFC1112_SLEEP_INTERVAL - sleep for expotentially longer times, up to (base << exp)
1760 **************************************************************************/
1761 long rfc1112_sleep_interval(long base, int exp)
1762 {
1763         unsigned long divisor, tmo;
1764 #ifdef BACKOFF_LIMIT
1765         if (exp > BACKOFF_LIMIT)
1766                 exp = BACKOFF_LIMIT;
1767 #endif
1768         divisor = RAND_MAX/(base << exp);
1769         tmo = random()/divisor;
1770         return tmo;
1771 }
1772 #endif /* MULTICAST_LEVEL_2 */