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