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 } else if ((destip & htonl(MULTICAST_MASK)) == htonl(MULTICAST_NETWORK)) {
428 unsigned char multicast[6];
429 unsigned long hdestip;
430 hdestip = ntohl(destip);
434 multicast[3] = (hdestip >> 16) & 0x7;
435 multicast[4] = (hdestip >> 8) & 0xff;
436 multicast[5] = hdestip & 0xff;
437 eth_transmit(multicast, ETH_P_IP, len, buf);
439 if (((destip & netmask) !=
440 (arptable[ARP_CLIENT].ipaddr.s_addr & netmask)) &&
441 arptable[ARP_GATEWAY].ipaddr.s_addr)
442 destip = arptable[ARP_GATEWAY].ipaddr.s_addr;
443 for(arpentry = 0; arpentry<MAX_ARP; arpentry++)
444 if (arptable[arpentry].ipaddr.s_addr == destip) break;
445 if (arpentry == MAX_ARP) {
446 printf("%@ is not in my arp table!\n", destip);
449 for (i = 0; i < ETH_ALEN; i++)
450 if (arptable[arpentry].node[i])
452 if (i == ETH_ALEN) { /* Need to do arp request */
453 arpreq.hwtype = htons(1);
454 arpreq.protocol = htons(IP);
455 arpreq.hwlen = ETH_ALEN;
457 arpreq.opcode = htons(ARP_REQUEST);
458 memcpy(arpreq.shwaddr, arptable[ARP_CLIENT].node, ETH_ALEN);
459 memcpy(arpreq.sipaddr, &arptable[ARP_CLIENT].ipaddr, sizeof(in_addr));
460 memset(arpreq.thwaddr, 0, ETH_ALEN);
461 memcpy(arpreq.tipaddr, &destip, sizeof(in_addr));
462 for (retry = 1; retry <= MAX_ARP_RETRIES; retry++) {
464 eth_transmit(broadcast, ETH_P_ARP, sizeof(arpreq),
466 timeout = rfc2131_sleep_interval(TIMEOUT, retry);
467 if (await_reply(await_arp, arpentry,
468 arpreq.tipaddr, timeout)) goto xmit;
473 eth_transmit(arptable[arpentry].node, ETH_P_IP, len, buf);
478 void build_ip_hdr(unsigned long destip, int ttl, int protocol, int option_len,
479 int len, const void *buf)
482 ip = (struct iphdr *)buf;
483 ip->verhdrlen = 0x45;
484 ip->verhdrlen += (option_len/4);
486 ip->len = htons(len);
488 ip->frags = 0; /* Should we set don't fragment? */
490 ip->protocol = protocol;
492 ip->src.s_addr = arptable[ARP_CLIENT].ipaddr.s_addr;
493 ip->dest.s_addr = destip;
494 ip->chksum = ipchksum(buf, sizeof(struct iphdr) + option_len);
497 void build_udp_hdr(unsigned long destip,
498 unsigned int srcsock, unsigned int destsock, int ttl,
499 int len, const void *buf)
503 ip = (struct iphdr *)buf;
504 build_ip_hdr(destip, ttl, IP_UDP, 0, len, buf);
505 udp = (struct udphdr *)((char *)buf + sizeof(struct iphdr));
506 udp->src = htons(srcsock);
507 udp->dest = htons(destsock);
508 udp->len = htons(len - sizeof(struct iphdr));
510 if ((udp->chksum = tcpudpchksum(ip)) == 0)
511 udp->chksum = 0xffff;
514 /**************************************************************************
515 UDP_TRANSMIT - Send an UDP datagram
516 **************************************************************************/
517 int udp_transmit(unsigned long destip, unsigned int srcsock,
518 unsigned int destsock, int len, const void *buf)
520 build_udp_hdr(destip, srcsock, destsock, 60, len, buf);
521 return ip_transmit(len, buf);
525 /**************************************************************************
526 QDRAIN - clear the nic's receive queue
527 **************************************************************************/
528 static int await_qdrain(int ival __unused, void *ptr __unused,
529 unsigned short ptype __unused,
530 struct iphdr *ip __unused, struct udphdr *udp __unused,
531 struct tcphdr *tcp __unused)
538 /* Clear out the Rx queue first. It contains nothing of interest,
539 * except possibly ARP requests from the DHCP/TFTP server. We use
540 * polling throughout Etherboot, so some time may have passed since we
541 * last polled the receive queue, which may now be filled with
542 * broadcast packets. This will cause the reply to the packets we are
543 * about to send to be lost immediately. Not very clever. */
544 await_reply(await_qdrain, 0, NULL, 0);
547 #ifdef RARP_NOT_BOOTP
548 /**************************************************************************
549 RARP - Get my IP address and load information
550 **************************************************************************/
551 static int await_rarp(int ival, void *ptr,
552 unsigned short ptype, struct iphdr *ip, struct udphdr *udp,
553 struct tcphdr *tcp __unused)
555 struct arprequest *arpreply;
556 if (ptype != ETH_P_RARP)
558 if (nic.packetlen < ETH_HLEN + sizeof(struct arprequest))
560 arpreply = (struct arprequest *)&nic.packet[ETH_HLEN];
561 if (arpreply->opcode != htons(RARP_REPLY))
563 if ((arpreply->opcode == htons(RARP_REPLY)) &&
564 (memcmp(arpreply->thwaddr, ptr, ETH_ALEN) == 0)) {
565 memcpy(arptable[ARP_SERVER].node, arpreply->shwaddr, ETH_ALEN);
566 memcpy(&arptable[ARP_SERVER].ipaddr, arpreply->sipaddr, sizeof(in_addr));
567 memcpy(&arptable[ARP_CLIENT].ipaddr, arpreply->tipaddr, sizeof(in_addr));
573 static int rarp(void)
577 /* arp and rarp requests share the same packet structure. */
578 struct arprequest rarpreq;
580 memset(&rarpreq, 0, sizeof(rarpreq));
582 rarpreq.hwtype = htons(1);
583 rarpreq.protocol = htons(IP);
584 rarpreq.hwlen = ETH_ALEN;
585 rarpreq.protolen = 4;
586 rarpreq.opcode = htons(RARP_REQUEST);
587 memcpy(&rarpreq.shwaddr, arptable[ARP_CLIENT].node, ETH_ALEN);
588 /* sipaddr is already zeroed out */
589 memcpy(&rarpreq.thwaddr, arptable[ARP_CLIENT].node, ETH_ALEN);
590 /* tipaddr is already zeroed out */
592 for (retry = 0; retry < MAX_ARP_RETRIES; ++retry) {
594 eth_transmit(broadcast, ETH_P_RARP, sizeof(rarpreq), &rarpreq);
596 timeout = rfc2131_sleep_interval(TIMEOUT, retry);
597 if (await_reply(await_rarp, 0, rarpreq.shwaddr, timeout))
601 if (retry < MAX_ARP_RETRIES) {
602 (void)sprintf(KERNEL_BUF, DEFAULT_KERNELPATH, arptable[ARP_CLIENT].ipaddr);
611 /**************************************************************************
612 BOOTP - Get my IP address and load information
613 **************************************************************************/
614 static int await_bootp(int ival __unused, void *ptr __unused,
615 unsigned short ptype __unused, struct iphdr *ip __unused,
616 struct udphdr *udp, struct tcphdr *tcp __unused)
618 struct bootp_t *bootpreply;
622 bootpreply = (struct bootp_t *)&nic.packet[ETH_HLEN +
623 sizeof(struct iphdr) + sizeof(struct udphdr)];
624 if (nic.packetlen < ETH_HLEN + sizeof(struct iphdr) +
625 sizeof(struct udphdr) +
626 #ifdef NO_DHCP_SUPPORT
627 sizeof(struct bootp_t)
629 sizeof(struct bootp_t) - DHCP_OPT_LEN
630 #endif /* NO_DHCP_SUPPORT */
634 if (udp->dest != htons(BOOTP_CLIENT))
636 if (bootpreply->bp_op != BOOTP_REPLY)
638 if (bootpreply->bp_xid != xid)
640 if (memcmp(&bootpreply->bp_siaddr, &zeroIP, sizeof(in_addr)) == 0)
642 if ((memcmp(broadcast, bootpreply->bp_hwaddr, ETH_ALEN) != 0) &&
643 (memcmp(arptable[ARP_CLIENT].node, bootpreply->bp_hwaddr, ETH_ALEN) != 0)) {
646 if ( bootpreply->bp_siaddr.s_addr ) {
647 arptable[ARP_SERVER].ipaddr.s_addr = bootpreply->bp_siaddr.s_addr;
648 memset(arptable[ARP_SERVER].node, 0, ETH_ALEN); /* Kill arp */
650 if ( bootpreply->bp_giaddr.s_addr ) {
651 arptable[ARP_GATEWAY].ipaddr.s_addr = bootpreply->bp_giaddr.s_addr;
652 memset(arptable[ARP_GATEWAY].node, 0, ETH_ALEN); /* Kill arp */
654 if (bootpreply->bp_yiaddr.s_addr) {
655 /* Offer with an IP address */
656 arptable[ARP_CLIENT].ipaddr.s_addr = bootpreply->bp_yiaddr.s_addr;
657 #ifndef NO_DHCP_SUPPORT
658 dhcp_addr.s_addr = bootpreply->bp_yiaddr.s_addr;
659 #endif /* NO_DHCP_SUPPORT */
660 netmask = default_netmask();
661 /* bootpreply->bp_file will be copied to KERNEL_BUF in the memcpy */
662 memcpy((char *)BOOTP_DATA_ADDR, (char *)bootpreply, sizeof(struct bootpd_t));
663 decode_rfc1533(BOOTP_DATA_ADDR->bootp_reply.bp_vend, 0,
664 #ifdef NO_DHCP_SUPPORT
665 BOOTP_VENDOR_LEN + MAX_BOOTP_EXTLEN,
667 DHCP_OPT_LEN + MAX_BOOTP_EXTLEN,
668 #endif /* NO_DHCP_SUPPORT */
672 /* Offer without an IP address - use as ProxyDHCP server */
673 arptable[ARP_PROXYDHCP].ipaddr.s_addr = bootpreply->bp_siaddr.s_addr;
674 memset(arptable[ARP_PROXYDHCP].node, 0, ETH_ALEN); /* Kill arp */
675 /* Grab only the bootfile name from a ProxyDHCP packet */
676 memcpy(KERNEL_BUF, bootpreply->bp_file, sizeof(KERNEL_BUF));
677 #endif /* PXE_EXPORT */
679 #ifdef REQUIRE_VCI_ETHERBOOT
686 static int bootp(void)
689 #ifndef NO_DHCP_SUPPORT
691 #endif /* NO_DHCP_SUPPORT */
693 unsigned long starttime;
694 unsigned char *bp_vend;
696 #ifndef NO_DHCP_SUPPORT
697 * ( ( struct dhcp_dev_id * ) &dhcp_machine_info[4] ) = nic.dhcp_dev_id;
698 #endif /* NO_DHCP_SUPPORT */
699 memset(&ip, 0, sizeof(struct bootpip_t));
700 ip.bp.bp_op = BOOTP_REQUEST;
702 ip.bp.bp_hlen = ETH_ALEN;
703 starttime = currticks();
704 /* Use lower 32 bits of node address, more likely to be
705 distinct than the time since booting */
706 memcpy(&xid, &arptable[ARP_CLIENT].node[2], sizeof(xid));
707 ip.bp.bp_xid = xid += htonl(starttime);
708 memcpy(ip.bp.bp_hwaddr, arptable[ARP_CLIENT].node, ETH_ALEN);
709 #ifdef NO_DHCP_SUPPORT
710 memcpy(ip.bp.bp_vend, rfc1533_cookie, 5); /* request RFC-style options */
712 memcpy(ip.bp.bp_vend, rfc1533_cookie, sizeof rfc1533_cookie); /* request RFC-style options */
713 memcpy(ip.bp.bp_vend + sizeof rfc1533_cookie, dhcpdiscover, sizeof dhcpdiscover);
714 /* Append machine_info to end, in encapsulated option */
715 bp_vend = ip.bp.bp_vend + sizeof rfc1533_cookie + sizeof dhcpdiscover;
716 memcpy(bp_vend, dhcp_machine_info, DHCP_MACHINE_INFO_SIZE);
717 bp_vend += DHCP_MACHINE_INFO_SIZE;
718 *bp_vend++ = RFC1533_END;
719 #endif /* NO_DHCP_SUPPORT */
721 for (retry = 0; retry < MAX_BOOTP_RETRIES; ) {
722 uint8_t my_hwaddr[ETH_ALEN];
723 unsigned long stop_time;
728 /* Kill arptable to avoid keeping stale entries */
729 memcpy ( my_hwaddr, arptable[ARP_CLIENT].node, ETH_ALEN );
730 memset ( arptable, 0, sizeof(arptable) );
731 memcpy ( arptable[ARP_CLIENT].node, my_hwaddr, ETH_ALEN );
733 udp_transmit(IP_BROADCAST, BOOTP_CLIENT, BOOTP_SERVER,
734 sizeof(struct bootpip_t), &ip);
735 remaining_time = rfc2131_sleep_interval(BOOTP_TIMEOUT, retry++);
736 stop_time = currticks() + remaining_time;
737 #ifdef NO_DHCP_SUPPORT
738 if (await_reply(await_bootp, 0, NULL, remaining_time))
741 while ( remaining_time > 0 ) {
742 if (await_reply(await_bootp, 0, NULL, remaining_time)){
744 remaining_time = stop_time - currticks();
746 if ( ! arptable[ARP_CLIENT].ipaddr.s_addr ) {
747 printf("No IP address\n");
750 /* If not a DHCPOFFER then must be just a BOOTP reply,
751 * be backward compatible with BOOTP then */
752 if (dhcp_reply != DHCPOFFER)
755 /* Construct the DHCPREQUEST packet */
756 memcpy(ip.bp.bp_vend, rfc1533_cookie, sizeof rfc1533_cookie);
757 memcpy(ip.bp.bp_vend + sizeof rfc1533_cookie, dhcprequest, sizeof dhcprequest);
758 /* Beware: the magic numbers 9 and 15 depend on
759 the layout of dhcprequest */
760 memcpy(&ip.bp.bp_vend[9], &dhcp_server, sizeof(in_addr));
761 memcpy(&ip.bp.bp_vend[15], &dhcp_addr, sizeof(in_addr));
762 bp_vend = ip.bp.bp_vend + sizeof rfc1533_cookie + sizeof dhcprequest;
763 /* Append machine_info to end, in encapsulated option */
764 memcpy(bp_vend, dhcp_machine_info, DHCP_MACHINE_INFO_SIZE);
765 bp_vend += DHCP_MACHINE_INFO_SIZE;
766 *bp_vend++ = RFC1533_END;
767 for (reqretry = 0; reqretry < MAX_BOOTP_RETRIES; ) {
768 unsigned long timeout;
770 udp_transmit(IP_BROADCAST, BOOTP_CLIENT, BOOTP_SERVER,
771 sizeof(struct bootpip_t), &ip);
773 timeout = rfc2131_sleep_interval(TIMEOUT, reqretry++);
774 if (!await_reply(await_bootp, 0, NULL, timeout))
776 if (dhcp_reply != DHCPACK)
780 if ( arptable[ARP_PROXYDHCP].ipaddr.s_addr ) {
781 /* Construct the ProxyDHCPREQUEST packet */
782 memcpy(ip.bp.bp_vend, rfc1533_cookie, sizeof rfc1533_cookie);
783 memcpy(ip.bp.bp_vend + sizeof rfc1533_cookie, proxydhcprequest, sizeof proxydhcprequest);
784 for (reqretry = 0; reqretry < MAX_BOOTP_RETRIES; ) {
785 printf ( "\nSending ProxyDHCP request to %@...", arptable[ARP_PROXYDHCP].ipaddr.s_addr);
786 udp_transmit(arptable[ARP_PROXYDHCP].ipaddr.s_addr, BOOTP_CLIENT, PROXYDHCP_SERVER,
787 sizeof(struct bootpip_t), &ip);
788 timeout = rfc2131_sleep_interval(TIMEOUT, reqretry++);
789 if (await_reply(await_bootp, 0, NULL, timeout)) {
794 #endif /* PXE_EXPORT */
797 #endif /* NO_DHCP_SUPPORT */
798 ip.bp.bp_secs = htons((currticks()-starttime)/TICKS_PER_SEC);
802 #endif /* RARP_NOT_BOOTP */
804 uint16_t tcpudpchksum(struct iphdr *ip)
806 struct udp_pseudo_hdr pseudo;
809 /* Compute the pseudo header */
810 pseudo.src.s_addr = ip->src.s_addr;
811 pseudo.dest.s_addr = ip->dest.s_addr;
813 pseudo.protocol = ip->protocol;
814 pseudo.len = htons(ntohs(ip->len) - sizeof(struct iphdr));
816 /* Sum the pseudo header */
817 checksum = ipchksum(&pseudo, 12);
819 /* Sum the rest of the tcp/udp packet */
820 checksum = add_ipchksums(12, checksum, ipchksum(ip + 1,
821 ntohs(ip->len) - sizeof(struct iphdr)));
826 #include "proto_eth_slow.c"
829 /**************************************************************************
830 AWAIT_REPLY - Wait until we get a response for our request
831 ************f**************************************************************/
832 int await_reply(reply_t reply, int ival, void *ptr, long timeout)
834 unsigned long time, now;
839 unsigned short ptype;
842 time = timeout + currticks();
843 /* The timeout check is done below. The timeout is only checked if
844 * there is no packet in the Rx queue. This assumes that eth_poll()
845 * needs a negligible amount of time.
849 background_send(now);
850 send_eth_slow_reports(now);
851 result = eth_poll(1);
853 /* We don't have anything */
855 /* Check for abort key only if the Rx queue is empty -
856 * as long as we have something to process, don't
857 * assume that something failed. It is unlikely that
858 * we have no processing time left between packets. */
859 poll_interruptions();
860 /* Do the timeout after at least a full queue walk. */
861 if ((timeout == 0) || (currticks() > time)) {
867 /* We have something! */
869 /* Find the Ethernet packet type */
870 if (nic.packetlen >= ETH_HLEN) {
871 ptype = ((unsigned short) nic.packet[12]) << 8
872 | ((unsigned short) nic.packet[13]);
873 } else continue; /* what else could we do with it? */
874 /* Verify an IP header */
876 if ((ptype == ETH_P_IP) && (nic.packetlen >= ETH_HLEN + sizeof(struct iphdr))) {
878 ip = (struct iphdr *)&nic.packet[ETH_HLEN];
879 if ((ip->verhdrlen < 0x45) || (ip->verhdrlen > 0x4F))
881 iplen = (ip->verhdrlen & 0xf) * 4;
882 if (ipchksum(ip, iplen) != 0)
884 if (ip->frags & htons(0x3FFF)) {
885 static int warned_fragmentation = 0;
886 if (!warned_fragmentation) {
887 printf("ALERT: got a fragmented packet - reconfigure your server\n");
888 warned_fragmentation = 1;
892 if (ntohs(ip->len) > ETH_MAX_MTU)
895 ipoptlen = iplen - sizeof(struct iphdr);
897 /* Delete the ip options, to guarantee
898 * good alignment, and make etherboot simpler.
900 memmove(&nic.packet[ETH_HLEN + sizeof(struct iphdr)],
901 &nic.packet[ETH_HLEN + iplen],
902 nic.packetlen - ipoptlen);
903 nic.packetlen -= ipoptlen;
907 if (ip && (ip->protocol == IP_UDP) &&
909 ETH_HLEN + sizeof(struct iphdr) + sizeof(struct udphdr))) {
910 udp = (struct udphdr *)&nic.packet[ETH_HLEN + sizeof(struct iphdr)];
912 /* Make certain we have a reasonable packet length */
913 if (ntohs(udp->len) > (ntohs(ip->len) - iplen))
916 if (udp->chksum && tcpudpchksum(ip)) {
917 printf("UDP checksum error\n");
922 if (ip && (ip->protocol == IP_TCP) &&
924 ETH_HLEN + sizeof(struct iphdr) + sizeof(struct tcphdr))){
925 tcp = (struct tcphdr *)&nic.packet[ETH_HLEN +
926 sizeof(struct iphdr)];
927 /* Make certain we have a reasonable packet length */
928 if (((ntohs(tcp->ctrl) >> 10) & 0x3C) >
929 ntohs(ip->len) - (int)iplen)
931 if (tcpudpchksum(ip)) {
932 printf("TCP checksum error\n");
937 result = reply(ival, ptr, ptype, ip, udp, tcp);
942 /* If it isn't a packet the upper layer wants see if there is a default
943 * action. This allows us reply to arp, igmp, and lacp queries.
945 if ((ptype == ETH_P_ARP) &&
946 (nic.packetlen >= ETH_HLEN + sizeof(struct arprequest))) {
947 struct arprequest *arpreply;
950 arpreply = (struct arprequest *)&nic.packet[ETH_HLEN];
951 memcpy(&tmp, arpreply->tipaddr, sizeof(in_addr));
952 if ((arpreply->opcode == htons(ARP_REQUEST)) &&
953 (tmp == arptable[ARP_CLIENT].ipaddr.s_addr)) {
954 arpreply->opcode = htons(ARP_REPLY);
955 memcpy(arpreply->tipaddr, arpreply->sipaddr, sizeof(in_addr));
956 memcpy(arpreply->thwaddr, arpreply->shwaddr, ETH_ALEN);
957 memcpy(arpreply->sipaddr, &arptable[ARP_CLIENT].ipaddr, sizeof(in_addr));
958 memcpy(arpreply->shwaddr, arptable[ARP_CLIENT].node, ETH_ALEN);
959 eth_transmit(arpreply->thwaddr, ETH_P_ARP,
960 sizeof(struct arprequest),
963 memcpy(&tmp, arpreply->tipaddr, sizeof(in_addr));
964 printf("Sent ARP reply to: %@\n",tmp);
968 background_process(now, ptype, ip);
969 process_eth_slow(ptype, now);
974 #ifdef REQUIRE_VCI_ETHERBOOT
975 /**************************************************************************
976 FIND_VCI_ETHERBOOT - Looks for "Etherboot" in Vendor Encapsulated Identifiers
977 On entry p points to byte count of VCI options
978 **************************************************************************/
979 static int find_vci_etherboot(unsigned char *p)
981 unsigned char *end = p + 1 + *p;
983 for (p++; p < end; ) {
984 if (*p == RFC2132_VENDOR_CLASS_ID) {
985 if (strncmp("Etherboot", p + 2, sizeof("Etherboot") - 1) == 0)
987 } else if (*p == RFC1533_END)
993 #endif /* REQUIRE_VCI_ETHERBOOT */
995 /**************************************************************************
996 DECODE_RFC1533 - Decodes RFC1533 header
997 **************************************************************************/
998 int decode_rfc1533(unsigned char *p, unsigned int block, unsigned int len, int eof)
1000 static unsigned char *extdata = NULL, *extend = NULL;
1001 unsigned char *extpath = NULL;
1002 unsigned char *endp;
1003 static unsigned char in_encapsulated_options = 0;
1006 /* Encapsulated option block */
1009 else if (block == 0) {
1010 #ifdef REQUIRE_VCI_ETHERBOOT
1013 end_of_rfc1533 = NULL;
1014 #ifdef IMAGE_FREEBSD
1015 /* yes this is a pain FreeBSD uses this for swap, however,
1016 there are cases when you don't want swap and then
1017 you want this set to get the extra features so lets
1018 just set if dealing with FreeBSD. I haven't run into
1019 any troubles with this but I have without it
1021 vendorext_isvalid = 1;
1022 #ifdef FREEBSD_KERNEL_ENV
1023 memcpy(freebsd_kernel_env, FREEBSD_KERNEL_ENV,
1024 sizeof(FREEBSD_KERNEL_ENV));
1025 /* FREEBSD_KERNEL_ENV had better be a string constant */
1027 freebsd_kernel_env[0]='\0';
1030 vendorext_isvalid = 0;
1032 if (memcmp(p, rfc1533_cookie, 4))
1033 return(0); /* no RFC 1533 header found */
1038 if (memcmp(p, rfc1533_cookie, 4))
1039 return(0); /* no RFC 1533 header found */
1042 if (extend + len <= (unsigned char *)&(BOOTP_DATA_ADDR->bootp_extension[MAX_BOOTP_EXTLEN])) {
1043 memcpy(extend, p, len);
1046 printf("Overflow in vendor data buffer! Aborting...\n");
1047 *extdata = RFC1533_END;
1050 p = extdata; endp = extend;
1055 unsigned char c = *p;
1056 if (c == RFC1533_PAD) {
1060 else if (c == RFC1533_END) {
1061 end_of_rfc1533 = endp = p;
1064 else if (NON_ENCAP_OPT c == RFC1533_NETMASK)
1065 memcpy(&netmask, p+2, sizeof(in_addr));
1066 else if (NON_ENCAP_OPT c == RFC1533_GATEWAY) {
1067 /* This is a little simplistic, but it will
1068 usually be sufficient.
1069 Take only the first entry */
1070 if (TAG_LEN(p) >= sizeof(in_addr))
1071 memcpy(&arptable[ARP_GATEWAY].ipaddr, p+2, sizeof(in_addr));
1073 else if (c == RFC1533_EXTENSIONPATH)
1075 #ifndef NO_DHCP_SUPPORT
1076 #ifdef REQUIRE_VCI_ETHERBOOT
1077 else if (NON_ENCAP_OPT c == RFC1533_VENDOR) {
1078 vci_etherboot = find_vci_etherboot(p+1);
1080 printf("vci_etherboot %d\n", vci_etherboot);
1083 #endif /* REQUIRE_VCI_ETHERBOOT */
1084 else if (NON_ENCAP_OPT c == RFC2132_MSG_TYPE)
1086 else if (NON_ENCAP_OPT c == RFC2132_SRV_ID)
1087 memcpy(&dhcp_server, p+2, sizeof(in_addr));
1088 #endif /* NO_DHCP_SUPPORT */
1089 else if (NON_ENCAP_OPT c == RFC1533_HOSTNAME) {
1091 hostnamelen = *(p + 1);
1093 else if (ENCAP_OPT c == RFC1533_VENDOR_MAGIC
1094 && TAG_LEN(p) >= 6 &&
1095 !memcmp(p+2,vendorext_magic,4) &&
1096 p[6] == RFC1533_VENDOR_MAJOR
1098 vendorext_isvalid++;
1099 else if (NON_ENCAP_OPT c == RFC1533_VENDOR_ETHERBOOT_ENCAP) {
1100 in_encapsulated_options = 1;
1101 decode_rfc1533(p+2, 0, TAG_LEN(p), -1);
1102 in_encapsulated_options = 0;
1104 #ifdef IMAGE_FREEBSD
1105 else if (NON_ENCAP_OPT c == RFC1533_VENDOR_HOWTO)
1106 freebsd_howto = ((p[2]*256+p[3])*256+p[4])*256+p[5];
1107 else if (NON_ENCAP_OPT c == RFC1533_VENDOR_KERNEL_ENV){
1108 if(*(p + 1) < sizeof(freebsd_kernel_env)){
1109 memcpy(freebsd_kernel_env,p+2,*(p+1));
1111 printf("Only support %ld bytes in Kernel Env\n",
1112 sizeof(freebsd_kernel_env));
1116 else if (NON_ENCAP_OPT c == RFC1533_DNS) {
1117 // TODO: Copy the DNS IP somewhere reasonable
1118 if (TAG_LEN(p) >= sizeof(in_addr))
1119 memcpy(&arptable[ARP_NAMESERVER].ipaddr, p+2, sizeof(in_addr));
1124 printf("Unknown RFC1533-tag ");
1125 for(q=p;q<p+2+TAG_LEN(p);q++)
1130 p += TAG_LEN(p) + 2;
1132 extdata = extend = endp;
1133 if (block <= 0 && extpath != NULL) {
1135 memcpy(fname, extpath+2, TAG_LEN(extpath));
1136 fname[(int)TAG_LEN(extpath)] = '\0';
1137 printf("Loading BOOTP-extension file: %s\n",fname);
1138 #warning "BOOTP extension files are broken"
1139 /* tftp(fname, decode_rfc1533); */
1141 return 1; /* proceed with next block */
1145 /* FIXME double check TWO_SECOND_DIVISOR */
1146 #define TWO_SECOND_DIVISOR (RAND_MAX/TICKS_PER_SEC)
1147 /**************************************************************************
1148 RFC2131_SLEEP_INTERVAL - sleep for expotentially longer times (base << exp) +- 1 sec)
1149 **************************************************************************/
1150 long rfc2131_sleep_interval(long base, int exp)
1153 if (exp > BACKOFF_LIMIT)
1154 exp = BACKOFF_LIMIT;
1155 tmo = (base << exp) + (TICKS_PER_SEC - (random()/TWO_SECOND_DIVISOR));