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