1 /**************************************************************************
2 Etherboot - Network Bootstrap Program
4 Literature dealing with the network protocols:
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
16 **************************************************************************/
17 #include "etherboot.h"
24 #include "background.h"
25 #include "elf.h" /* FOR EM_CURRENT */
27 struct arptable_t arptable[MAX_ARP];
28 /* Put rom_info in .nocompress section so romprefix.S can write to it */
29 struct rom_info rom __attribute__ ((section (".text16.nocompress"))) = {0,0};
30 static unsigned long netmask;
35 unsigned char *end_of_rfc1533 = NULL;
36 static int vendorext_isvalid;
37 static const unsigned char vendorext_magic[] = {0xE4,0x45,0x74,0x68}; /* äEth */
38 static const unsigned char broadcast[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
39 static const in_addr zeroIP = { 0L };
41 struct bootpd_t bootp_data;
43 #ifdef NO_DHCP_SUPPORT
44 static unsigned char rfc1533_cookie[5] = { RFC1533_COOKIE, RFC1533_END };
45 #else /* !NO_DHCP_SUPPORT */
46 static int dhcp_reply;
47 static in_addr dhcp_server = { 0L };
48 static in_addr dhcp_addr = { 0L };
49 static unsigned char rfc1533_cookie[] = { RFC1533_COOKIE };
50 #define DHCP_MACHINE_INFO_SIZE (sizeof dhcp_machine_info)
51 static unsigned char dhcp_machine_info[] = {
52 /* Our enclosing DHCP tag */
53 RFC1533_VENDOR_ETHERBOOT_ENCAP, 11,
55 RFC1533_VENDOR_NIC_DEV_ID, 5, 0, 0, 0, 0, 0,
56 /* Our current architecture */
57 RFC1533_VENDOR_ARCH, 2, EM_CURRENT & 0xff, (EM_CURRENT >> 8) & 0xff,
59 /* The 64bit version of our current architecture */
60 RFC1533_VENDOR_ARCH, 2, EM_CURRENT_64 & 0xff, (EM_CURRENT_64 >> 8) & 0xff,
61 #undef DHCP_MACHINE_INFO_SIZE
62 #define DHCP_MACHINE_INFO_SIZE (sizeof(dhcp_machine_info) - (EM_CURRENT_64_PRESENT? 0: 4))
63 #endif /* EM_CURRENT_64 */
65 static const unsigned char dhcpdiscover[] = {
66 RFC2132_MSG_TYPE,1,DHCPDISCOVER,
67 RFC2132_MAX_SIZE,2, /* request as much as we can */
68 ETH_MAX_MTU / 256, ETH_MAX_MTU % 256,
69 #ifdef PXE_DHCP_STRICT
70 RFC3679_PXE_CLIENT_UUID,RFC3679_PXE_CLIENT_UUID_LENGTH,RFC3679_PXE_CLIENT_UUID_DEFAULT,
71 RFC3679_PXE_CLIENT_ARCH,RFC3679_PXE_CLIENT_ARCH_LENGTH,RFC3679_PXE_CLIENT_ARCH_IAX86PC,
72 RFC3679_PXE_CLIENT_NDI, RFC3679_PXE_CLIENT_NDI_LENGTH, RFC3679_PXE_CLIENT_NDI_21,
73 RFC2132_VENDOR_CLASS_ID,RFC2132_VENDOR_CLASS_ID_PXE_LENGTH,RFC2132_VENDOR_CLASS_ID_PXE,
75 RFC2132_VENDOR_CLASS_ID,13,'E','t','h','e','r','b','o','o','t',
76 '-',VERSION_MAJOR+'0','.',VERSION_MINOR+'0',
77 #endif /* PXE_DHCP_STRICT */
79 /* Client ID Option */
80 RFC2132_CLIENT_ID, ( DHCP_CLIENT_ID_LEN + 1 ),
81 DHCP_CLIENT_ID_TYPE, DHCP_CLIENT_ID,
82 #endif /* DHCP_CLIENT_ID */
83 #ifdef DHCP_USER_CLASS
84 /* User Class Option */
85 RFC3004_USER_CLASS, DHCP_USER_CLASS_LEN, DHCP_USER_CLASS,
86 #endif /* DHCP_USER_CLASS */
88 #define DHCPDISCOVER_PARAMS_BASE 4
89 #ifdef PXE_DHCP_STRICT
90 #define DHCPDISCOVER_PARAMS_PXE ( 1 + 8 )
92 #define DHCPDISCOVER_PARAMS_PXE 0
93 #endif /* PXE_DHCP_STRICT */
94 #define DHCPDISCOVER_PARAMS_DNS 1
95 ( DHCPDISCOVER_PARAMS_BASE +
96 DHCPDISCOVER_PARAMS_PXE+
97 DHCPDISCOVER_PARAMS_DNS ),
102 #ifdef PXE_DHCP_STRICT
103 ,RFC2132_VENDOR_CLASS_ID,
104 RFC1533_VENDOR_PXE_OPT128,
105 RFC1533_VENDOR_PXE_OPT129,
106 RFC1533_VENDOR_PXE_OPT130,
107 RFC1533_VENDOR_PXE_OPT131,
108 RFC1533_VENDOR_PXE_OPT132,
109 RFC1533_VENDOR_PXE_OPT133,
110 RFC1533_VENDOR_PXE_OPT134,
111 RFC1533_VENDOR_PXE_OPT135,
112 #endif /* PXE_DHCP_STRICT */
115 static const unsigned char dhcprequest [] = {
116 RFC2132_MSG_TYPE,1,DHCPREQUEST,
117 RFC2132_SRV_ID,4,0,0,0,0,
118 RFC2132_REQ_ADDR,4,0,0,0,0,
119 RFC2132_MAX_SIZE,2, /* request as much as we can */
120 ETH_MAX_MTU / 256, ETH_MAX_MTU % 256,
121 #ifdef PXE_DHCP_STRICT
122 RFC3679_PXE_CLIENT_UUID,RFC3679_PXE_CLIENT_UUID_LENGTH,RFC3679_PXE_CLIENT_UUID_DEFAULT,
123 RFC3679_PXE_CLIENT_ARCH,RFC3679_PXE_CLIENT_ARCH_LENGTH,RFC3679_PXE_CLIENT_ARCH_IAX86PC,
124 RFC3679_PXE_CLIENT_NDI, RFC3679_PXE_CLIENT_NDI_LENGTH, RFC3679_PXE_CLIENT_NDI_21,
125 RFC2132_VENDOR_CLASS_ID,RFC2132_VENDOR_CLASS_ID_PXE_LENGTH,RFC2132_VENDOR_CLASS_ID_PXE,
127 RFC2132_VENDOR_CLASS_ID,13,'E','t','h','e','r','b','o','o','t',
128 '-',VERSION_MAJOR+'0','.',VERSION_MINOR+'0',
129 #endif /* PXE_DHCP_STRICT */
130 #ifdef DHCP_CLIENT_ID
131 /* Client ID Option */
132 RFC2132_CLIENT_ID, ( DHCP_CLIENT_ID_LEN + 1 ),
133 DHCP_CLIENT_ID_TYPE, DHCP_CLIENT_ID,
134 #endif /* DHCP_CLIENT_ID */
135 #ifdef DHCP_USER_CLASS
136 /* User Class Option */
137 RFC3004_USER_CLASS, DHCP_USER_CLASS_LEN, DHCP_USER_CLASS,
138 #endif /* DHCP_USER_CLASS */
139 /* request parameters */
141 #define DHCPREQUEST_PARAMS_BASE 5
142 #ifdef PXE_DHCP_STRICT
143 #define DHCPREQUEST_PARAMS_PXE 1
144 #define DHCPREQUEST_PARAMS_VENDOR_PXE 8
145 #define DHCPREQUEST_PARAMS_VENDOR_EB 0
147 #define DHCPREQUEST_PARAMS_PXE 0
148 #define DHCPREQUEST_PARAMS_VENDOR_PXE 0
149 #define DHCPREQUEST_PARAMS_VENDOR_EB 4
150 #endif /* PXE_DHCP_STRICT */
152 #define DHCPREQUEST_PARAMS_FREEBSD 2
154 #define DHCPREQUEST_PARAMS_FREEBSD 0
155 #endif /* IMAGE_FREEBSD */
156 #define DHCPREQUEST_PARAMS_DNS 1
157 ( DHCPREQUEST_PARAMS_BASE +
158 DHCPREQUEST_PARAMS_PXE +
159 DHCPREQUEST_PARAMS_VENDOR_PXE +
160 DHCPREQUEST_PARAMS_VENDOR_EB +
161 DHCPREQUEST_PARAMS_DNS +
162 DHCPREQUEST_PARAMS_FREEBSD ),
163 /* 5 Standard parameters */
168 RFC1533_ROOTPATH, /* only passed to the booted image */
169 #ifndef PXE_DHCP_STRICT
170 /* 4 Etherboot vendortags */
171 RFC1533_VENDOR_MAGIC,
172 RFC1533_VENDOR_ADDPARM,
173 RFC1533_VENDOR_ETHDEV,
174 RFC1533_VENDOR_ETHERBOOT_ENCAP,
175 #endif /* ! PXE_DHCP_STRICT */
177 /* 2 FreeBSD options */
178 RFC1533_VENDOR_HOWTO,
179 RFC1533_VENDOR_KERNEL_ENV,
183 #ifdef PXE_DHCP_STRICT
184 RFC2132_VENDOR_CLASS_ID,
185 RFC1533_VENDOR_PXE_OPT128,
186 RFC1533_VENDOR_PXE_OPT129,
187 RFC1533_VENDOR_PXE_OPT130,
188 RFC1533_VENDOR_PXE_OPT131,
189 RFC1533_VENDOR_PXE_OPT132,
190 RFC1533_VENDOR_PXE_OPT133,
191 RFC1533_VENDOR_PXE_OPT134,
192 RFC1533_VENDOR_PXE_OPT135,
193 #endif /* PXE_DHCP_STRICT */
196 static const unsigned char proxydhcprequest [] = {
197 RFC2132_MSG_TYPE,1,DHCPREQUEST,
198 RFC2132_MAX_SIZE,2, /* request as much as we can */
199 ETH_MAX_MTU / 256, ETH_MAX_MTU % 256,
200 #ifdef PXE_DHCP_STRICT
201 RFC3679_PXE_CLIENT_UUID,RFC3679_PXE_CLIENT_UUID_LENGTH,RFC3679_PXE_CLIENT_UUID_DEFAULT,
202 RFC3679_PXE_CLIENT_ARCH,RFC3679_PXE_CLIENT_ARCH_LENGTH,RFC3679_PXE_CLIENT_ARCH_IAX86PC,
203 RFC3679_PXE_CLIENT_NDI, RFC3679_PXE_CLIENT_NDI_LENGTH, RFC3679_PXE_CLIENT_NDI_21,
204 RFC2132_VENDOR_CLASS_ID,RFC2132_VENDOR_CLASS_ID_PXE_LENGTH,RFC2132_VENDOR_CLASS_ID_PXE,
205 #endif /* PXE_DHCP_STRICT */
209 #ifdef REQUIRE_VCI_ETHERBOOT
212 #endif /* NO_DHCP_SUPPORT */
214 #ifdef RARP_NOT_BOOTP
215 static int rarp(void);
217 static int bootp(void);
222 * Find out what our boot parameters are
224 static int nic_configure ( struct type_dev *type_dev ) {
225 struct nic *nic = ( struct nic * ) type_dev;
228 if ( ! nic->nic_op->connect ( nic ) ) {
229 printf ( "No connection to network\n" );
233 /* Find a server to get BOOTP reply from */
234 #ifdef RARP_NOT_BOOTP
235 printf("Searching for server (RARP)...");
237 #ifndef NO_DHCP_SUPPORT
238 printf("Searching for server (DHCP)...");
240 printf("Searching for server (BOOTP)...");
244 #ifdef RARP_NOT_BOOTP
245 server_found = rarp();
247 server_found = bootp();
250 printf("No Server found\n");
254 printf("\nMe: %@", arptable[ARP_CLIENT].ipaddr.s_addr );
255 #ifndef NO_DHCP_SUPPORT
256 printf(", DHCP: %@", dhcp_server );
258 if (arptable[ARP_PROXYDHCP].ipaddr.s_addr)
260 arptable[ARP_PROXYDHCP].ipaddr.s_addr);
261 #endif /* PXE_EXPORT */
262 #endif /* ! NO_DHCP_SUPPORT */
263 printf(", TFTP: %@", arptable[ARP_SERVER].ipaddr.s_addr);
264 if (BOOTP_DATA_ADDR->bootp_reply.bp_giaddr.s_addr)
265 printf(", Relay: %@",
266 BOOTP_DATA_ADDR->bootp_reply.bp_giaddr.s_addr);
267 if (arptable[ARP_GATEWAY].ipaddr.s_addr)
268 printf(", Gateway %@", arptable[ARP_GATEWAY].ipaddr.s_addr);
269 if (arptable[ARP_NAMESERVER].ipaddr.s_addr)
270 printf(", Nameserver %@", arptable[ARP_NAMESERVER].ipaddr.s_addr);
274 printf("\n=>>"); getchar();
282 * Download a file from the specified URL into the specified buffer
285 int download_url ( char *url, struct buffer *buffer ) {
286 struct protocol *proto;
287 struct sockaddr_in server;
290 printf ( "Loading %s\n", url );
293 if ( ! parse_url ( url, &proto, &server, &filename ) ) {
294 DBG ( "Unusable URL %s\n", url );
298 /* Call protocol's method to download the file */
299 return proto->load ( url, &server, filename, buffer );
305 /**************************************************************************
306 LOAD - Try to get booted
307 **************************************************************************/
308 static int nic_load ( struct type_dev *type_dev, struct buffer *buffer ) {
311 /* Now use TFTP to load file */
312 kernel = KERNEL_BUF[0] == '\0' ?
313 #ifdef DEFAULT_BOOTFILE
320 return download_url ( kernel, buffer );
322 printf("No filename\n");
327 void nic_disable ( struct nic *nic __unused ) {
328 #ifdef MULTICAST_LEVEL2
330 for(i = 0; i < MAX_IGMP; i++) {
336 static char * nic_describe_device ( struct type_dev *type_dev ) {
337 struct nic *nic = ( struct nic * ) type_dev;
338 static char nic_description[] = "MAC 00:00:00:00:00:00";
340 sprintf ( nic_description + 4, "%!", nic->node_addr );
341 return nic_description;
345 * Device operations tables
348 struct type_driver nic_driver = {
350 .type_dev = ( struct type_dev * ) &nic,
351 .describe_device = nic_describe_device,
352 .configure = nic_configure,
356 /* Careful. We need an aligned buffer to avoid problems on machines
357 * that care about alignment. To trivally align the ethernet data
358 * (the ip hdr and arp requests) we offset the packet by 2 bytes.
359 * leaving the ethernet data 16 byte aligned. Beyond this
360 * we use memmove but this makes the common cast simple and fast.
362 static char packet[ETH_FRAME_LEN + ETH_DATA_ALIGN] __aligned;
365 .node_addr = arptable[ARP_CLIENT].node,
366 .packet = packet + ETH_DATA_ALIGN,
371 int dummy_connect ( struct nic *nic __unused ) {
375 void dummy_irq ( struct nic *nic __unused, irq_action_t irq_action __unused ) {
379 /**************************************************************************
380 DEFAULT_NETMASK - Return default netmask for IP address
381 **************************************************************************/
382 static inline unsigned long default_netmask(void)
384 int net = ntohl(arptable[ARP_CLIENT].ipaddr.s_addr) >> 24;
386 return(htonl(0xff000000));
388 return(htonl(0xffff0000));
390 return(htonl(0xffffff00));
393 /**************************************************************************
394 IP_TRANSMIT - Send an IP datagram
395 **************************************************************************/
396 static int await_arp(int ival, void *ptr,
397 unsigned short ptype, struct iphdr *ip __unused, struct udphdr *udp __unused,
398 struct tcphdr *tcp __unused)
400 struct arprequest *arpreply;
401 if (ptype != ETH_P_ARP)
403 if (nic.packetlen < ETH_HLEN + sizeof(struct arprequest))
405 arpreply = (struct arprequest *)&nic.packet[ETH_HLEN];
407 if (arpreply->opcode != htons(ARP_REPLY))
409 if (memcmp(arpreply->sipaddr, ptr, sizeof(in_addr)) != 0)
411 memcpy(arptable[ival].node, arpreply->shwaddr, ETH_ALEN);
415 int ip_transmit(int len, const void *buf)
417 unsigned long destip;
419 struct arprequest arpreq;
423 ip = (struct iphdr *)buf;
424 destip = ip->dest.s_addr;
425 if (destip == IP_BROADCAST) {
426 eth_transmit(broadcast, ETH_P_IP, len, buf);
427 #ifdef MULTICAST_LEVEL1
428 } else if ((destip & htonl(MULTICAST_MASK)) == htonl(MULTICAST_NETWORK)) {
429 unsigned char multicast[6];
430 unsigned long hdestip;
431 hdestip = ntohl(destip);
435 multicast[3] = (hdestip >> 16) & 0x7;
436 multicast[4] = (hdestip >> 8) & 0xff;
437 multicast[5] = hdestip & 0xff;
438 eth_transmit(multicast, ETH_P_IP, len, buf);
441 if (((destip & netmask) !=
442 (arptable[ARP_CLIENT].ipaddr.s_addr & netmask)) &&
443 arptable[ARP_GATEWAY].ipaddr.s_addr)
444 destip = arptable[ARP_GATEWAY].ipaddr.s_addr;
445 for(arpentry = 0; arpentry<MAX_ARP; arpentry++)
446 if (arptable[arpentry].ipaddr.s_addr == destip) break;
447 if (arpentry == MAX_ARP) {
448 printf("%@ is not in my arp table!\n", destip);
451 for (i = 0; i < ETH_ALEN; i++)
452 if (arptable[arpentry].node[i])
454 if (i == ETH_ALEN) { /* Need to do arp request */
455 arpreq.hwtype = htons(1);
456 arpreq.protocol = htons(IP);
457 arpreq.hwlen = ETH_ALEN;
459 arpreq.opcode = htons(ARP_REQUEST);
460 memcpy(arpreq.shwaddr, arptable[ARP_CLIENT].node, ETH_ALEN);
461 memcpy(arpreq.sipaddr, &arptable[ARP_CLIENT].ipaddr, sizeof(in_addr));
462 memset(arpreq.thwaddr, 0, ETH_ALEN);
463 memcpy(arpreq.tipaddr, &destip, sizeof(in_addr));
464 for (retry = 1; retry <= MAX_ARP_RETRIES; retry++) {
466 eth_transmit(broadcast, ETH_P_ARP, sizeof(arpreq),
468 timeout = rfc2131_sleep_interval(TIMEOUT, retry);
469 if (await_reply(await_arp, arpentry,
470 arpreq.tipaddr, timeout)) goto xmit;
475 eth_transmit(arptable[arpentry].node, ETH_P_IP, len, buf);
480 void build_ip_hdr(unsigned long destip, int ttl, int protocol, int option_len,
481 int len, const void *buf)
484 ip = (struct iphdr *)buf;
485 ip->verhdrlen = 0x45;
486 ip->verhdrlen += (option_len/4);
488 ip->len = htons(len);
490 ip->frags = 0; /* Should we set don't fragment? */
492 ip->protocol = protocol;
494 ip->src.s_addr = arptable[ARP_CLIENT].ipaddr.s_addr;
495 ip->dest.s_addr = destip;
496 ip->chksum = ipchksum(buf, sizeof(struct iphdr) + option_len);
499 void build_udp_hdr(unsigned long destip,
500 unsigned int srcsock, unsigned int destsock, int ttl,
501 int len, const void *buf)
505 ip = (struct iphdr *)buf;
506 build_ip_hdr(destip, ttl, IP_UDP, 0, len, buf);
507 udp = (struct udphdr *)((char *)buf + sizeof(struct iphdr));
508 udp->src = htons(srcsock);
509 udp->dest = htons(destsock);
510 udp->len = htons(len - sizeof(struct iphdr));
512 if ((udp->chksum = tcpudpchksum(ip)) == 0)
513 udp->chksum = 0xffff;
516 /**************************************************************************
517 UDP_TRANSMIT - Send an UDP datagram
518 **************************************************************************/
519 int udp_transmit(unsigned long destip, unsigned int srcsock,
520 unsigned int destsock, int len, const void *buf)
522 build_udp_hdr(destip, srcsock, destsock, 60, len, buf);
523 return ip_transmit(len, buf);
527 /**************************************************************************
528 QDRAIN - clear the nic's receive queue
529 **************************************************************************/
530 static int await_qdrain(int ival __unused, void *ptr __unused,
531 unsigned short ptype __unused,
532 struct iphdr *ip __unused, struct udphdr *udp __unused,
533 struct tcphdr *tcp __unused)
540 /* Clear out the Rx queue first. It contains nothing of interest,
541 * except possibly ARP requests from the DHCP/TFTP server. We use
542 * polling throughout Etherboot, so some time may have passed since we
543 * last polled the receive queue, which may now be filled with
544 * broadcast packets. This will cause the reply to the packets we are
545 * about to send to be lost immediately. Not very clever. */
546 await_reply(await_qdrain, 0, NULL, 0);
549 #ifdef RARP_NOT_BOOTP
550 /**************************************************************************
551 RARP - Get my IP address and load information
552 **************************************************************************/
553 static int await_rarp(int ival, void *ptr,
554 unsigned short ptype, struct iphdr *ip, struct udphdr *udp,
555 struct tcphdr *tcp __unused)
557 struct arprequest *arpreply;
558 if (ptype != ETH_P_RARP)
560 if (nic.packetlen < ETH_HLEN + sizeof(struct arprequest))
562 arpreply = (struct arprequest *)&nic.packet[ETH_HLEN];
563 if (arpreply->opcode != htons(RARP_REPLY))
565 if ((arpreply->opcode == htons(RARP_REPLY)) &&
566 (memcmp(arpreply->thwaddr, ptr, ETH_ALEN) == 0)) {
567 memcpy(arptable[ARP_SERVER].node, arpreply->shwaddr, ETH_ALEN);
568 memcpy(&arptable[ARP_SERVER].ipaddr, arpreply->sipaddr, sizeof(in_addr));
569 memcpy(&arptable[ARP_CLIENT].ipaddr, arpreply->tipaddr, sizeof(in_addr));
575 static int rarp(void)
579 /* arp and rarp requests share the same packet structure. */
580 struct arprequest rarpreq;
582 memset(&rarpreq, 0, sizeof(rarpreq));
584 rarpreq.hwtype = htons(1);
585 rarpreq.protocol = htons(IP);
586 rarpreq.hwlen = ETH_ALEN;
587 rarpreq.protolen = 4;
588 rarpreq.opcode = htons(RARP_REQUEST);
589 memcpy(&rarpreq.shwaddr, arptable[ARP_CLIENT].node, ETH_ALEN);
590 /* sipaddr is already zeroed out */
591 memcpy(&rarpreq.thwaddr, arptable[ARP_CLIENT].node, ETH_ALEN);
592 /* tipaddr is already zeroed out */
594 for (retry = 0; retry < MAX_ARP_RETRIES; ++retry) {
596 eth_transmit(broadcast, ETH_P_RARP, sizeof(rarpreq), &rarpreq);
598 timeout = rfc2131_sleep_interval(TIMEOUT, retry);
599 if (await_reply(await_rarp, 0, rarpreq.shwaddr, timeout))
603 if (retry < MAX_ARP_RETRIES) {
604 (void)sprintf(KERNEL_BUF, DEFAULT_KERNELPATH, arptable[ARP_CLIENT].ipaddr);
613 /**************************************************************************
614 BOOTP - Get my IP address and load information
615 **************************************************************************/
616 static int await_bootp(int ival __unused, void *ptr __unused,
617 unsigned short ptype __unused, struct iphdr *ip __unused,
618 struct udphdr *udp, struct tcphdr *tcp __unused)
620 struct bootp_t *bootpreply;
624 bootpreply = (struct bootp_t *)&nic.packet[ETH_HLEN +
625 sizeof(struct iphdr) + sizeof(struct udphdr)];
626 if (nic.packetlen < ETH_HLEN + sizeof(struct iphdr) +
627 sizeof(struct udphdr) +
628 #ifdef NO_DHCP_SUPPORT
629 sizeof(struct bootp_t)
631 sizeof(struct bootp_t) - DHCP_OPT_LEN
632 #endif /* NO_DHCP_SUPPORT */
636 if (udp->dest != htons(BOOTP_CLIENT))
638 if (bootpreply->bp_op != BOOTP_REPLY)
640 if (bootpreply->bp_xid != xid)
642 if (memcmp(&bootpreply->bp_siaddr, &zeroIP, sizeof(in_addr)) == 0)
644 if ((memcmp(broadcast, bootpreply->bp_hwaddr, ETH_ALEN) != 0) &&
645 (memcmp(arptable[ARP_CLIENT].node, bootpreply->bp_hwaddr, ETH_ALEN) != 0)) {
648 if ( bootpreply->bp_siaddr.s_addr ) {
649 arptable[ARP_SERVER].ipaddr.s_addr = bootpreply->bp_siaddr.s_addr;
650 memset(arptable[ARP_SERVER].node, 0, ETH_ALEN); /* Kill arp */
652 if ( bootpreply->bp_giaddr.s_addr ) {
653 arptable[ARP_GATEWAY].ipaddr.s_addr = bootpreply->bp_giaddr.s_addr;
654 memset(arptable[ARP_GATEWAY].node, 0, ETH_ALEN); /* Kill arp */
656 if (bootpreply->bp_yiaddr.s_addr) {
657 /* Offer with an IP address */
658 arptable[ARP_CLIENT].ipaddr.s_addr = bootpreply->bp_yiaddr.s_addr;
659 #ifndef NO_DHCP_SUPPORT
660 dhcp_addr.s_addr = bootpreply->bp_yiaddr.s_addr;
661 #endif /* NO_DHCP_SUPPORT */
662 netmask = default_netmask();
663 /* bootpreply->bp_file will be copied to KERNEL_BUF in the memcpy */
664 memcpy((char *)BOOTP_DATA_ADDR, (char *)bootpreply, sizeof(struct bootpd_t));
665 decode_rfc1533(BOOTP_DATA_ADDR->bootp_reply.bp_vend, 0,
666 #ifdef NO_DHCP_SUPPORT
667 BOOTP_VENDOR_LEN + MAX_BOOTP_EXTLEN,
669 DHCP_OPT_LEN + MAX_BOOTP_EXTLEN,
670 #endif /* NO_DHCP_SUPPORT */
674 /* Offer without an IP address - use as ProxyDHCP server */
675 arptable[ARP_PROXYDHCP].ipaddr.s_addr = bootpreply->bp_siaddr.s_addr;
676 memset(arptable[ARP_PROXYDHCP].node, 0, ETH_ALEN); /* Kill arp */
677 /* Grab only the bootfile name from a ProxyDHCP packet */
678 memcpy(KERNEL_BUF, bootpreply->bp_file, sizeof(KERNEL_BUF));
679 #endif /* PXE_EXPORT */
681 #ifdef REQUIRE_VCI_ETHERBOOT
688 static int bootp(void)
691 #ifndef NO_DHCP_SUPPORT
693 #endif /* NO_DHCP_SUPPORT */
695 unsigned long starttime;
696 unsigned char *bp_vend;
698 #ifndef NO_DHCP_SUPPORT
699 * ( ( struct dhcp_dev_id * ) &dhcp_machine_info[4] ) = nic.dhcp_dev_id;
700 #endif /* NO_DHCP_SUPPORT */
701 memset(&ip, 0, sizeof(struct bootpip_t));
702 ip.bp.bp_op = BOOTP_REQUEST;
704 ip.bp.bp_hlen = ETH_ALEN;
705 starttime = currticks();
706 /* Use lower 32 bits of node address, more likely to be
707 distinct than the time since booting */
708 memcpy(&xid, &arptable[ARP_CLIENT].node[2], sizeof(xid));
709 ip.bp.bp_xid = xid += htonl(starttime);
710 memcpy(ip.bp.bp_hwaddr, arptable[ARP_CLIENT].node, ETH_ALEN);
711 #ifdef NO_DHCP_SUPPORT
712 memcpy(ip.bp.bp_vend, rfc1533_cookie, 5); /* request RFC-style options */
714 memcpy(ip.bp.bp_vend, rfc1533_cookie, sizeof rfc1533_cookie); /* request RFC-style options */
715 memcpy(ip.bp.bp_vend + sizeof rfc1533_cookie, dhcpdiscover, sizeof dhcpdiscover);
716 /* Append machine_info to end, in encapsulated option */
717 bp_vend = ip.bp.bp_vend + sizeof rfc1533_cookie + sizeof dhcpdiscover;
718 memcpy(bp_vend, dhcp_machine_info, DHCP_MACHINE_INFO_SIZE);
719 bp_vend += DHCP_MACHINE_INFO_SIZE;
720 *bp_vend++ = RFC1533_END;
721 #endif /* NO_DHCP_SUPPORT */
723 for (retry = 0; retry < MAX_BOOTP_RETRIES; ) {
724 uint8_t my_hwaddr[ETH_ALEN];
725 unsigned long stop_time;
730 /* Kill arptable to avoid keeping stale entries */
731 memcpy ( my_hwaddr, arptable[ARP_CLIENT].node, ETH_ALEN );
732 memset ( arptable, 0, sizeof(arptable) );
733 memcpy ( arptable[ARP_CLIENT].node, my_hwaddr, ETH_ALEN );
735 udp_transmit(IP_BROADCAST, BOOTP_CLIENT, BOOTP_SERVER,
736 sizeof(struct bootpip_t), &ip);
737 remaining_time = rfc2131_sleep_interval(BOOTP_TIMEOUT, retry++);
738 stop_time = currticks() + remaining_time;
739 #ifdef NO_DHCP_SUPPORT
740 if (await_reply(await_bootp, 0, NULL, remaining_time))
743 while ( remaining_time > 0 ) {
744 if (await_reply(await_bootp, 0, NULL, remaining_time)){
746 remaining_time = stop_time - currticks();
748 if ( ! arptable[ARP_CLIENT].ipaddr.s_addr ) {
749 printf("No IP address\n");
752 /* If not a DHCPOFFER then must be just a BOOTP reply,
753 * be backward compatible with BOOTP then */
754 if (dhcp_reply != DHCPOFFER)
757 /* Construct the DHCPREQUEST packet */
758 memcpy(ip.bp.bp_vend, rfc1533_cookie, sizeof rfc1533_cookie);
759 memcpy(ip.bp.bp_vend + sizeof rfc1533_cookie, dhcprequest, sizeof dhcprequest);
760 /* Beware: the magic numbers 9 and 15 depend on
761 the layout of dhcprequest */
762 memcpy(&ip.bp.bp_vend[9], &dhcp_server, sizeof(in_addr));
763 memcpy(&ip.bp.bp_vend[15], &dhcp_addr, sizeof(in_addr));
764 bp_vend = ip.bp.bp_vend + sizeof rfc1533_cookie + sizeof dhcprequest;
765 /* Append machine_info to end, in encapsulated option */
766 memcpy(bp_vend, dhcp_machine_info, DHCP_MACHINE_INFO_SIZE);
767 bp_vend += DHCP_MACHINE_INFO_SIZE;
768 *bp_vend++ = RFC1533_END;
769 for (reqretry = 0; reqretry < MAX_BOOTP_RETRIES; ) {
770 unsigned long timeout;
772 udp_transmit(IP_BROADCAST, BOOTP_CLIENT, BOOTP_SERVER,
773 sizeof(struct bootpip_t), &ip);
775 timeout = rfc2131_sleep_interval(TIMEOUT, reqretry++);
776 if (!await_reply(await_bootp, 0, NULL, timeout))
778 if (dhcp_reply != DHCPACK)
782 if ( arptable[ARP_PROXYDHCP].ipaddr.s_addr ) {
783 /* Construct the ProxyDHCPREQUEST packet */
784 memcpy(ip.bp.bp_vend, rfc1533_cookie, sizeof rfc1533_cookie);
785 memcpy(ip.bp.bp_vend + sizeof rfc1533_cookie, proxydhcprequest, sizeof proxydhcprequest);
786 for (reqretry = 0; reqretry < MAX_BOOTP_RETRIES; ) {
787 printf ( "\nSending ProxyDHCP request to %@...", arptable[ARP_PROXYDHCP].ipaddr.s_addr);
788 udp_transmit(arptable[ARP_PROXYDHCP].ipaddr.s_addr, BOOTP_CLIENT, PROXYDHCP_SERVER,
789 sizeof(struct bootpip_t), &ip);
790 timeout = rfc2131_sleep_interval(TIMEOUT, reqretry++);
791 if (await_reply(await_bootp, 0, NULL, timeout)) {
796 #endif /* PXE_EXPORT */
799 #endif /* NO_DHCP_SUPPORT */
800 ip.bp.bp_secs = htons((currticks()-starttime)/TICKS_PER_SEC);
804 #endif /* RARP_NOT_BOOTP */
806 uint16_t tcpudpchksum(struct iphdr *ip)
808 struct udp_pseudo_hdr pseudo;
811 /* Compute the pseudo header */
812 pseudo.src.s_addr = ip->src.s_addr;
813 pseudo.dest.s_addr = ip->dest.s_addr;
815 pseudo.protocol = ip->protocol;
816 pseudo.len = htons(ntohs(ip->len) - sizeof(struct iphdr));
818 /* Sum the pseudo header */
819 checksum = ipchksum(&pseudo, 12);
821 /* Sum the rest of the tcp/udp packet */
822 checksum = add_ipchksums(12, checksum, ipchksum(ip + 1,
823 ntohs(ip->len) - sizeof(struct iphdr)));
828 #include "proto_eth_slow.c"
831 /**************************************************************************
832 AWAIT_REPLY - Wait until we get a response for our request
833 ************f**************************************************************/
834 int await_reply(reply_t reply, int ival, void *ptr, long timeout)
836 unsigned long time, now;
841 unsigned short ptype;
844 time = timeout + currticks();
845 /* The timeout check is done below. The timeout is only checked if
846 * there is no packet in the Rx queue. This assumes that eth_poll()
847 * needs a negligible amount of time.
851 background_send(now);
852 send_eth_slow_reports(now);
853 result = eth_poll(1);
855 /* We don't have anything */
857 /* Check for abort key only if the Rx queue is empty -
858 * as long as we have something to process, don't
859 * assume that something failed. It is unlikely that
860 * we have no processing time left between packets. */
861 poll_interruptions();
862 /* Do the timeout after at least a full queue walk. */
863 if ((timeout == 0) || (currticks() > time)) {
869 /* We have something! */
871 /* Find the Ethernet packet type */
872 if (nic.packetlen >= ETH_HLEN) {
873 ptype = ((unsigned short) nic.packet[12]) << 8
874 | ((unsigned short) nic.packet[13]);
875 } else continue; /* what else could we do with it? */
876 /* Verify an IP header */
878 if ((ptype == ETH_P_IP) && (nic.packetlen >= ETH_HLEN + sizeof(struct iphdr))) {
880 ip = (struct iphdr *)&nic.packet[ETH_HLEN];
881 if ((ip->verhdrlen < 0x45) || (ip->verhdrlen > 0x4F))
883 iplen = (ip->verhdrlen & 0xf) * 4;
884 if (ipchksum(ip, iplen) != 0)
886 if (ip->frags & htons(0x3FFF)) {
887 static int warned_fragmentation = 0;
888 if (!warned_fragmentation) {
889 printf("ALERT: got a fragmented packet - reconfigure your server\n");
890 warned_fragmentation = 1;
894 if (ntohs(ip->len) > ETH_MAX_MTU)
897 ipoptlen = iplen - sizeof(struct iphdr);
899 /* Delete the ip options, to guarantee
900 * good alignment, and make etherboot simpler.
902 memmove(&nic.packet[ETH_HLEN + sizeof(struct iphdr)],
903 &nic.packet[ETH_HLEN + iplen],
904 nic.packetlen - ipoptlen);
905 nic.packetlen -= ipoptlen;
909 if (ip && (ip->protocol == IP_UDP) &&
911 ETH_HLEN + sizeof(struct iphdr) + sizeof(struct udphdr))) {
912 udp = (struct udphdr *)&nic.packet[ETH_HLEN + sizeof(struct iphdr)];
914 /* Make certain we have a reasonable packet length */
915 if (ntohs(udp->len) > (ntohs(ip->len) - iplen))
918 if (udp->chksum && tcpudpchksum(ip)) {
919 printf("UDP checksum error\n");
924 if (ip && (ip->protocol == IP_TCP) &&
926 ETH_HLEN + sizeof(struct iphdr) + sizeof(struct tcphdr))){
927 tcp = (struct tcphdr *)&nic.packet[ETH_HLEN +
928 sizeof(struct iphdr)];
929 /* Make certain we have a reasonable packet length */
930 if (((ntohs(tcp->ctrl) >> 10) & 0x3C) >
931 ntohs(ip->len) - (int)iplen)
933 if (tcpudpchksum(ip)) {
934 printf("TCP checksum error\n");
939 result = reply(ival, ptr, ptype, ip, udp, tcp);
944 /* If it isn't a packet the upper layer wants see if there is a default
945 * action. This allows us reply to arp, igmp, and lacp queries.
947 if ((ptype == ETH_P_ARP) &&
948 (nic.packetlen >= ETH_HLEN + sizeof(struct arprequest))) {
949 struct arprequest *arpreply;
952 arpreply = (struct arprequest *)&nic.packet[ETH_HLEN];
953 memcpy(&tmp, arpreply->tipaddr, sizeof(in_addr));
954 if ((arpreply->opcode == htons(ARP_REQUEST)) &&
955 (tmp == arptable[ARP_CLIENT].ipaddr.s_addr)) {
956 arpreply->opcode = htons(ARP_REPLY);
957 memcpy(arpreply->tipaddr, arpreply->sipaddr, sizeof(in_addr));
958 memcpy(arpreply->thwaddr, arpreply->shwaddr, ETH_ALEN);
959 memcpy(arpreply->sipaddr, &arptable[ARP_CLIENT].ipaddr, sizeof(in_addr));
960 memcpy(arpreply->shwaddr, arptable[ARP_CLIENT].node, ETH_ALEN);
961 eth_transmit(arpreply->thwaddr, ETH_P_ARP,
962 sizeof(struct arprequest),
965 memcpy(&tmp, arpreply->tipaddr, sizeof(in_addr));
966 printf("Sent ARP reply to: %@\n",tmp);
970 background_process(now, ptype, ip);
971 process_eth_slow(ptype, now);
976 #ifdef REQUIRE_VCI_ETHERBOOT
977 /**************************************************************************
978 FIND_VCI_ETHERBOOT - Looks for "Etherboot" in Vendor Encapsulated Identifiers
979 On entry p points to byte count of VCI options
980 **************************************************************************/
981 static int find_vci_etherboot(unsigned char *p)
983 unsigned char *end = p + 1 + *p;
985 for (p++; p < end; ) {
986 if (*p == RFC2132_VENDOR_CLASS_ID) {
987 if (strncmp("Etherboot", p + 2, sizeof("Etherboot") - 1) == 0)
989 } else if (*p == RFC1533_END)
995 #endif /* REQUIRE_VCI_ETHERBOOT */
997 /**************************************************************************
998 DECODE_RFC1533 - Decodes RFC1533 header
999 **************************************************************************/
1000 int decode_rfc1533(unsigned char *p, unsigned int block, unsigned int len, int eof)
1002 static unsigned char *extdata = NULL, *extend = NULL;
1003 unsigned char *extpath = NULL;
1004 unsigned char *endp;
1005 static unsigned char in_encapsulated_options = 0;
1008 /* Encapsulated option block */
1011 else if (block == 0) {
1012 #ifdef REQUIRE_VCI_ETHERBOOT
1015 end_of_rfc1533 = NULL;
1016 #ifdef IMAGE_FREEBSD
1017 /* yes this is a pain FreeBSD uses this for swap, however,
1018 there are cases when you don't want swap and then
1019 you want this set to get the extra features so lets
1020 just set if dealing with FreeBSD. I haven't run into
1021 any troubles with this but I have without it
1023 vendorext_isvalid = 1;
1024 #ifdef FREEBSD_KERNEL_ENV
1025 memcpy(freebsd_kernel_env, FREEBSD_KERNEL_ENV,
1026 sizeof(FREEBSD_KERNEL_ENV));
1027 /* FREEBSD_KERNEL_ENV had better be a string constant */
1029 freebsd_kernel_env[0]='\0';
1032 vendorext_isvalid = 0;
1034 if (memcmp(p, rfc1533_cookie, 4))
1035 return(0); /* no RFC 1533 header found */
1040 if (memcmp(p, rfc1533_cookie, 4))
1041 return(0); /* no RFC 1533 header found */
1044 if (extend + len <= (unsigned char *)&(BOOTP_DATA_ADDR->bootp_extension[MAX_BOOTP_EXTLEN])) {
1045 memcpy(extend, p, len);
1048 printf("Overflow in vendor data buffer! Aborting...\n");
1049 *extdata = RFC1533_END;
1052 p = extdata; endp = extend;
1057 unsigned char c = *p;
1058 if (c == RFC1533_PAD) {
1062 else if (c == RFC1533_END) {
1063 end_of_rfc1533 = endp = p;
1066 else if (NON_ENCAP_OPT c == RFC1533_NETMASK)
1067 memcpy(&netmask, p+2, sizeof(in_addr));
1068 else if (NON_ENCAP_OPT c == RFC1533_GATEWAY) {
1069 /* This is a little simplistic, but it will
1070 usually be sufficient.
1071 Take only the first entry */
1072 if (TAG_LEN(p) >= sizeof(in_addr))
1073 memcpy(&arptable[ARP_GATEWAY].ipaddr, p+2, sizeof(in_addr));
1075 else if (c == RFC1533_EXTENSIONPATH)
1077 #ifndef NO_DHCP_SUPPORT
1078 #ifdef REQUIRE_VCI_ETHERBOOT
1079 else if (NON_ENCAP_OPT c == RFC1533_VENDOR) {
1080 vci_etherboot = find_vci_etherboot(p+1);
1082 printf("vci_etherboot %d\n", vci_etherboot);
1085 #endif /* REQUIRE_VCI_ETHERBOOT */
1086 else if (NON_ENCAP_OPT c == RFC2132_MSG_TYPE)
1088 else if (NON_ENCAP_OPT c == RFC2132_SRV_ID)
1089 memcpy(&dhcp_server, p+2, sizeof(in_addr));
1090 #endif /* NO_DHCP_SUPPORT */
1091 else if (NON_ENCAP_OPT c == RFC1533_HOSTNAME) {
1093 hostnamelen = *(p + 1);
1095 else if (ENCAP_OPT c == RFC1533_VENDOR_MAGIC
1096 && TAG_LEN(p) >= 6 &&
1097 !memcmp(p+2,vendorext_magic,4) &&
1098 p[6] == RFC1533_VENDOR_MAJOR
1100 vendorext_isvalid++;
1101 else if (NON_ENCAP_OPT c == RFC1533_VENDOR_ETHERBOOT_ENCAP) {
1102 in_encapsulated_options = 1;
1103 decode_rfc1533(p+2, 0, TAG_LEN(p), -1);
1104 in_encapsulated_options = 0;
1106 #ifdef IMAGE_FREEBSD
1107 else if (NON_ENCAP_OPT c == RFC1533_VENDOR_HOWTO)
1108 freebsd_howto = ((p[2]*256+p[3])*256+p[4])*256+p[5];
1109 else if (NON_ENCAP_OPT c == RFC1533_VENDOR_KERNEL_ENV){
1110 if(*(p + 1) < sizeof(freebsd_kernel_env)){
1111 memcpy(freebsd_kernel_env,p+2,*(p+1));
1113 printf("Only support %ld bytes in Kernel Env\n",
1114 sizeof(freebsd_kernel_env));
1118 else if (NON_ENCAP_OPT c == RFC1533_DNS) {
1119 // TODO: Copy the DNS IP somewhere reasonable
1120 if (TAG_LEN(p) >= sizeof(in_addr))
1121 memcpy(&arptable[ARP_NAMESERVER].ipaddr, p+2, sizeof(in_addr));
1126 printf("Unknown RFC1533-tag ");
1127 for(q=p;q<p+2+TAG_LEN(p);q++)
1132 p += TAG_LEN(p) + 2;
1134 extdata = extend = endp;
1135 if (block <= 0 && extpath != NULL) {
1137 memcpy(fname, extpath+2, TAG_LEN(extpath));
1138 fname[(int)TAG_LEN(extpath)] = '\0';
1139 printf("Loading BOOTP-extension file: %s\n",fname);
1140 #warning "BOOTP extension files are broken"
1141 /* tftp(fname, decode_rfc1533); */
1143 return 1; /* proceed with next block */
1147 /* FIXME double check TWO_SECOND_DIVISOR */
1148 #define TWO_SECOND_DIVISOR (RAND_MAX/TICKS_PER_SEC)
1149 /**************************************************************************
1150 RFC2131_SLEEP_INTERVAL - sleep for expotentially longer times (base << exp) +- 1 sec)
1151 **************************************************************************/
1152 long rfc2131_sleep_interval(long base, int exp)
1155 #ifdef BACKOFF_LIMIT
1156 if (exp > BACKOFF_LIMIT)
1157 exp = BACKOFF_LIMIT;
1159 tmo = (base << exp) + (TICKS_PER_SEC - (random()/TWO_SECOND_DIVISOR));