4 This file is (or should be) completely obsolete. It is thus
5 commented out with the "#if 0" above, to make sure that no
6 functions from it are in use. --mdc 2006-09-18
9 /**************************************************************************
10 Etherboot - Network Bootstrap Program
12 Literature dealing with the network protocols:
17 BOOTP - RFC951, RFC2132 (vendor extensions)
18 DHCP - RFC2131, RFC2132, RFC3004 (options)
19 TFTP - RFC1350, RFC2347 (options), RFC2348 (blocksize), RFC2349 (tsize)
20 RPC - RFC1831, RFC1832 (XDR), RFC1833 (rpcbind/portmapper)
21 NFS - RFC1094, RFC1813 (v3, useful for clarifications, not implemented)
22 IGMP - RFC1112, RFC2113, RFC2365, RFC2236, RFC3171
24 **************************************************************************/
25 #include "etherboot.h"
29 #include "gpxe/netdevice.h"
34 #include "background.h"
35 #include "elf.h" /* FOR EM_CURRENT */
49 struct arptable_t arptable[MAX_ARP];
50 /* Put rom_info in .nocompress section so romprefix.S can write to it */
51 struct rom_info rom __attribute__ ((section (".text16.nocompress"))) = {0,0};
52 static unsigned long netmask;
57 unsigned char *end_of_rfc1533 = NULL;
58 unsigned char *addparam;
62 int freebsd_howto = 0;
63 char freebsd_kernel_env[FREEBSD_KERNEL_ENV_SIZE];
64 #endif /* IMAGE_FREEBSD */
66 static int vendorext_isvalid;
67 static const unsigned char vendorext_magic[] = {0xE4,0x45,0x74,0x68}; /* äEth */
68 static const unsigned char broadcast[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
69 static const in_addr zeroIP = { 0L };
71 struct bootpd_t bootp_data;
73 #ifdef NO_DHCP_SUPPORT
74 static unsigned char rfc1533_cookie[5] = { RFC1533_COOKIE, RFC1533_END };
75 #else /* !NO_DHCP_SUPPORT */
76 static int dhcp_reply;
77 static in_addr dhcp_server = { 0L };
78 static in_addr dhcp_addr = { 0L };
79 static unsigned char rfc1533_cookie[] = { RFC1533_COOKIE };
80 #define DHCP_MACHINE_INFO_SIZE (sizeof dhcp_machine_info)
81 static unsigned char dhcp_machine_info[] = {
82 /* Our enclosing DHCP tag */
83 RFC1533_VENDOR_ETHERBOOT_ENCAP, 11,
85 RFC1533_VENDOR_NIC_DEV_ID, 5, 0, 0, 0, 0, 0,
86 /* Our current architecture */
87 RFC1533_VENDOR_ARCH, 2, EM_CURRENT & 0xff, (EM_CURRENT >> 8) & 0xff,
89 /* The 64bit version of our current architecture */
90 RFC1533_VENDOR_ARCH, 2, EM_CURRENT_64 & 0xff, (EM_CURRENT_64 >> 8) & 0xff,
91 #undef DHCP_MACHINE_INFO_SIZE
92 #define DHCP_MACHINE_INFO_SIZE (sizeof(dhcp_machine_info) - (EM_CURRENT_64_PRESENT? 0: 4))
93 #endif /* EM_CURRENT_64 */
95 static const unsigned char dhcpdiscover[] = {
96 RFC2132_MSG_TYPE,1,DHCPDISCOVER,
97 RFC2132_MAX_SIZE,2, /* request as much as we can */
98 ETH_MAX_MTU / 256, ETH_MAX_MTU % 256,
99 #ifdef PXE_DHCP_STRICT
100 RFC3679_PXE_CLIENT_UUID,RFC3679_PXE_CLIENT_UUID_LENGTH,RFC3679_PXE_CLIENT_UUID_DEFAULT,
101 RFC3679_PXE_CLIENT_ARCH,RFC3679_PXE_CLIENT_ARCH_LENGTH,RFC3679_PXE_CLIENT_ARCH_IAX86PC,
102 RFC3679_PXE_CLIENT_NDI, RFC3679_PXE_CLIENT_NDI_LENGTH, RFC3679_PXE_CLIENT_NDI_21,
103 RFC2132_VENDOR_CLASS_ID,RFC2132_VENDOR_CLASS_ID_PXE_LENGTH,RFC2132_VENDOR_CLASS_ID_PXE,
105 RFC2132_VENDOR_CLASS_ID,13,'E','t','h','e','r','b','o','o','t',
106 '-',VERSION_MAJOR+'0','.',VERSION_MINOR+'0',
107 #endif /* PXE_DHCP_STRICT */
108 #ifdef DHCP_CLIENT_ID
109 /* Client ID Option */
110 RFC2132_CLIENT_ID, ( DHCP_CLIENT_ID_LEN + 1 ),
111 DHCP_CLIENT_ID_TYPE, DHCP_CLIENT_ID,
112 #endif /* DHCP_CLIENT_ID */
113 #ifdef DHCP_USER_CLASS
114 /* User Class Option */
115 RFC3004_USER_CLASS, DHCP_USER_CLASS_LEN, DHCP_USER_CLASS,
116 #endif /* DHCP_USER_CLASS */
118 #define DHCPDISCOVER_PARAMS_BASE 4
119 #ifdef PXE_DHCP_STRICT
120 #define DHCPDISCOVER_PARAMS_PXE ( 1 + 8 )
122 #define DHCPDISCOVER_PARAMS_PXE 0
123 #endif /* PXE_DHCP_STRICT */
124 #define DHCPDISCOVER_PARAMS_DNS 1
125 ( DHCPDISCOVER_PARAMS_BASE +
126 DHCPDISCOVER_PARAMS_PXE+
127 DHCPDISCOVER_PARAMS_DNS ),
132 #ifdef PXE_DHCP_STRICT
133 ,RFC2132_VENDOR_CLASS_ID,
134 RFC1533_VENDOR_PXE_OPT128,
135 RFC1533_VENDOR_PXE_OPT129,
136 RFC1533_VENDOR_PXE_OPT130,
137 RFC1533_VENDOR_PXE_OPT131,
138 RFC1533_VENDOR_PXE_OPT132,
139 RFC1533_VENDOR_PXE_OPT133,
140 RFC1533_VENDOR_PXE_OPT134,
141 RFC1533_VENDOR_PXE_OPT135,
142 #endif /* PXE_DHCP_STRICT */
145 static const unsigned char dhcprequest [] = {
146 RFC2132_MSG_TYPE,1,DHCPREQUEST,
147 RFC2132_SRV_ID,4,0,0,0,0,
148 RFC2132_REQ_ADDR,4,0,0,0,0,
149 RFC2132_MAX_SIZE,2, /* request as much as we can */
150 ETH_MAX_MTU / 256, ETH_MAX_MTU % 256,
151 #ifdef PXE_DHCP_STRICT
152 RFC3679_PXE_CLIENT_UUID,RFC3679_PXE_CLIENT_UUID_LENGTH,RFC3679_PXE_CLIENT_UUID_DEFAULT,
153 RFC3679_PXE_CLIENT_ARCH,RFC3679_PXE_CLIENT_ARCH_LENGTH,RFC3679_PXE_CLIENT_ARCH_IAX86PC,
154 RFC3679_PXE_CLIENT_NDI, RFC3679_PXE_CLIENT_NDI_LENGTH, RFC3679_PXE_CLIENT_NDI_21,
155 RFC2132_VENDOR_CLASS_ID,RFC2132_VENDOR_CLASS_ID_PXE_LENGTH,RFC2132_VENDOR_CLASS_ID_PXE,
157 RFC2132_VENDOR_CLASS_ID,13,'E','t','h','e','r','b','o','o','t',
158 '-',VERSION_MAJOR+'0','.',VERSION_MINOR+'0',
159 #endif /* PXE_DHCP_STRICT */
160 #ifdef DHCP_CLIENT_ID
161 /* Client ID Option */
162 RFC2132_CLIENT_ID, ( DHCP_CLIENT_ID_LEN + 1 ),
163 DHCP_CLIENT_ID_TYPE, DHCP_CLIENT_ID,
164 #endif /* DHCP_CLIENT_ID */
165 #ifdef DHCP_USER_CLASS
166 /* User Class Option */
167 RFC3004_USER_CLASS, DHCP_USER_CLASS_LEN, DHCP_USER_CLASS,
168 #endif /* DHCP_USER_CLASS */
169 /* request parameters */
171 #define DHCPREQUEST_PARAMS_BASE 5
172 #ifdef PXE_DHCP_STRICT
173 #define DHCPREQUEST_PARAMS_PXE 1
174 #define DHCPREQUEST_PARAMS_VENDOR_PXE 8
175 #define DHCPREQUEST_PARAMS_VENDOR_EB 0
177 #define DHCPREQUEST_PARAMS_PXE 0
178 #define DHCPREQUEST_PARAMS_VENDOR_PXE 0
179 #define DHCPREQUEST_PARAMS_VENDOR_EB 4
180 #endif /* PXE_DHCP_STRICT */
182 #define DHCPREQUEST_PARAMS_FREEBSD 2
184 #define DHCPREQUEST_PARAMS_FREEBSD 0
185 #endif /* IMAGE_FREEBSD */
186 #define DHCPREQUEST_PARAMS_DNS 1
187 ( DHCPREQUEST_PARAMS_BASE +
188 DHCPREQUEST_PARAMS_PXE +
189 DHCPREQUEST_PARAMS_VENDOR_PXE +
190 DHCPREQUEST_PARAMS_VENDOR_EB +
191 DHCPREQUEST_PARAMS_DNS +
192 DHCPREQUEST_PARAMS_FREEBSD ),
193 /* 5 Standard parameters */
198 RFC1533_ROOTPATH, /* only passed to the booted image */
199 #ifndef PXE_DHCP_STRICT
200 /* 4 Etherboot vendortags */
201 RFC1533_VENDOR_MAGIC,
202 RFC1533_VENDOR_ADDPARM,
203 RFC1533_VENDOR_ETHDEV,
204 RFC1533_VENDOR_ETHERBOOT_ENCAP,
205 #endif /* ! PXE_DHCP_STRICT */
207 /* 2 FreeBSD options */
208 RFC1533_VENDOR_HOWTO,
209 RFC1533_VENDOR_KERNEL_ENV,
213 #ifdef PXE_DHCP_STRICT
214 RFC2132_VENDOR_CLASS_ID,
215 RFC1533_VENDOR_PXE_OPT128,
216 RFC1533_VENDOR_PXE_OPT129,
217 RFC1533_VENDOR_PXE_OPT130,
218 RFC1533_VENDOR_PXE_OPT131,
219 RFC1533_VENDOR_PXE_OPT132,
220 RFC1533_VENDOR_PXE_OPT133,
221 RFC1533_VENDOR_PXE_OPT134,
222 RFC1533_VENDOR_PXE_OPT135,
223 #endif /* PXE_DHCP_STRICT */
226 static const unsigned char proxydhcprequest [] = {
227 RFC2132_MSG_TYPE,1,DHCPREQUEST,
228 RFC2132_MAX_SIZE,2, /* request as much as we can */
229 ETH_MAX_MTU / 256, ETH_MAX_MTU % 256,
230 #ifdef PXE_DHCP_STRICT
231 RFC3679_PXE_CLIENT_UUID,RFC3679_PXE_CLIENT_UUID_LENGTH,RFC3679_PXE_CLIENT_UUID_DEFAULT,
232 RFC3679_PXE_CLIENT_ARCH,RFC3679_PXE_CLIENT_ARCH_LENGTH,RFC3679_PXE_CLIENT_ARCH_IAX86PC,
233 RFC3679_PXE_CLIENT_NDI, RFC3679_PXE_CLIENT_NDI_LENGTH, RFC3679_PXE_CLIENT_NDI_21,
234 RFC2132_VENDOR_CLASS_ID,RFC2132_VENDOR_CLASS_ID_PXE_LENGTH,RFC2132_VENDOR_CLASS_ID_PXE,
235 #endif /* PXE_DHCP_STRICT */
239 #ifdef REQUIRE_VCI_ETHERBOOT
242 #endif /* NO_DHCP_SUPPORT */
244 #ifdef RARP_NOT_BOOTP
245 static int rarp(void);
247 static int bootp(void);
252 * Find out what our boot parameters are
254 static int nic_configure ( struct type_dev *type_dev ) {
255 struct nic *nic = ( struct nic * ) type_dev;
258 if ( ! nic->nic_op->connect ( nic ) ) {
259 printf ( "No connection to network\n" );
263 /* Find a server to get BOOTP reply from */
264 #ifdef RARP_NOT_BOOTP
265 printf("Searching for server (RARP)...");
267 #ifndef NO_DHCP_SUPPORT
268 printf("Searching for server (DHCP)...");
270 printf("Searching for server (BOOTP)...");
274 #ifdef RARP_NOT_BOOTP
275 server_found = rarp();
277 server_found = bootp();
280 printf("No Server found\n");
285 printf( "\nMe: %s", inet_ntoa ( arptable[ARP_CLIENT].ipaddr ) );
287 #ifndef NO_DHCP_SUPPORT
288 printf( ", DHCP: %s", inet_ntoa (dhcp_server) );
290 if (arptable[ARP_PROXYDHCP].ipaddr.s_addr)
291 printf ( " (& %s)", inet_ntoa ( arptable[ARP_PROXYDHCP].ipaddr ) );
292 #endif /* PXE_EXPORT */
293 #endif /* ! NO_DHCP_SUPPORT */
294 printf(", TFTP: %s", inet_ntoa ( arptable[ARP_SERVER].ipaddr ) );
295 if (bootp_data.bootp_reply.bp_giaddr.s_addr)
296 printf ( ", Relay: %s", inet_ntoa ( bootp_data.bootp_reply.bp_giaddr ) );
297 if (arptable[ARP_GATEWAY].ipaddr.s_addr)
298 printf ( ", Gateway %s", inet_ntoa (arptable[ARP_GATEWAY].ipaddr ) );
299 if (arptable[ARP_NAMESERVER].ipaddr.s_addr)
300 printf ( ", Nameserver %s", inet_ntoa ( arptable[ARP_NAMESERVER].ipaddr ) );
304 printf("\n=>>"); getchar();
312 * Download a file from the specified URL into the specified buffer
315 int download_url ( char *url, struct buffer *buffer ) {
316 struct protocol *proto;
317 struct sockaddr_in server;
320 printf ( "Loading %s\n", url );
323 if ( ! parse_url ( url, &proto, &server, &filename ) ) {
324 DBG ( "Unusable URL %s\n", url );
328 /* Call protocol's method to download the file */
329 return proto->load ( url, &server, filename, buffer );
335 /**************************************************************************
336 LOAD - Try to get booted
337 **************************************************************************/
338 static int nic_load ( struct type_dev *type_dev, struct buffer *buffer ) {
341 /* Now use TFTP to load file */
342 kernel = KERNEL_BUF[0] == '\0' ?
343 #ifdef DEFAULT_BOOTFILE
349 #ifdef ZPXE_SUFFIX_STRIP
354 if(kernel[i - 6] == '.' &&
355 kernel[i - 5] == 'z' &&
356 kernel[i - 4] == 'p' &&
357 kernel[i - 3] == 'x' &&
358 kernel[i - 2] == 'e') {
359 printf("Trimming .zpxe extension\n");
366 return download_url ( kernel, buffer );
368 printf("No filename\n");
373 void nic_disable ( struct nic *nic __unused ) {
374 #ifdef MULTICAST_LEVEL2
376 for(i = 0; i < MAX_IGMP; i++) {
382 static char * nic_describe_device ( struct type_dev *type_dev ) {
383 struct nic *nic = ( struct nic * ) type_dev;
384 static char nic_description[] = "MAC 00:00:00:00:00:00";
386 sprintf ( nic_description + 4, "%s", netdev_name ( nic ) );
387 return nic_description;
391 * Device operations tables
394 struct type_driver nic_driver = {
396 .type_dev = ( struct type_dev * ) &nic,
397 .describe_device = nic_describe_device,
398 .configure = nic_configure,
403 /* Careful. We need an aligned buffer to avoid problems on machines
404 * that care about alignment. To trivally align the ethernet data
405 * (the ip hdr and arp requests) we offset the packet by 2 bytes.
406 * leaving the ethernet data 16 byte aligned. Beyond this
407 * we use memmove but this makes the common cast simple and fast.
409 static char packet[ETH_FRAME_LEN + ETH_DATA_ALIGN] __aligned;
412 .node_addr = arptable[ARP_CLIENT].node,
413 .packet = packet + ETH_DATA_ALIGN,
418 /**************************************************************************
419 DEFAULT_NETMASK - Return default netmask for IP address
420 **************************************************************************/
421 static inline unsigned long default_netmask(void)
423 int net = ntohl(arptable[ARP_CLIENT].ipaddr.s_addr) >> 24;
425 return(htonl(0xff000000));
427 return(htonl(0xffff0000));
429 return(htonl(0xffffff00));
432 /**************************************************************************
433 IP_TRANSMIT - Send an IP datagram
434 **************************************************************************/
435 static int await_arp(int ival, void *ptr,
436 unsigned short ptype, struct iphdr *ip __unused, struct udphdr *udp __unused,
437 struct tcphdr *tcp __unused)
439 struct arprequest *arpreply;
440 if (ptype != ETH_P_ARP)
442 if (nic.packetlen < ETH_HLEN + sizeof(struct arprequest))
444 arpreply = (struct arprequest *)&nic.packet[ETH_HLEN];
446 if (arpreply->opcode != htons(ARPOP_REPLY))
448 if (memcmp(arpreply->sipaddr, ptr, sizeof(in_addr)) != 0)
450 memcpy(arptable[ival].node, arpreply->shwaddr, ETH_ALEN);
454 int ip_transmit(int len, const void *buf)
456 unsigned long destip;
458 struct arprequest arpreq;
462 ip = (struct iphdr *)buf;
463 destip = ip->dest.s_addr;
464 if (destip == INADDR_BROADCAST) {
465 eth_transmit(broadcast, ETH_P_IP, len, buf);
466 } else if ((destip & htonl(MULTICAST_MASK)) == htonl(MULTICAST_NETWORK)) {
467 unsigned char multicast[6];
468 unsigned long hdestip;
469 hdestip = ntohl(destip);
473 multicast[3] = (hdestip >> 16) & 0x7;
474 multicast[4] = (hdestip >> 8) & 0xff;
475 multicast[5] = hdestip & 0xff;
476 eth_transmit(multicast, ETH_P_IP, len, buf);
478 if (((destip & netmask) !=
479 (arptable[ARP_CLIENT].ipaddr.s_addr & netmask)) &&
480 arptable[ARP_GATEWAY].ipaddr.s_addr)
481 destip = arptable[ARP_GATEWAY].ipaddr.s_addr;
482 for(arpentry = 0; arpentry<MAX_ARP; arpentry++)
483 if (arptable[arpentry].ipaddr.s_addr == destip) break;
484 if (arpentry == MAX_ARP) {
485 printf ( "%s is not in my arp table!\n", inet_ntoa (destip) );
488 for (i = 0; i < ETH_ALEN; i++)
489 if (arptable[arpentry].node[i])
491 if (i == ETH_ALEN) { /* Need to do arp request */
492 arpreq.hwtype = htons(1);
493 arpreq.protocol = htons(ETH_P_IP);
494 arpreq.hwlen = ETH_ALEN;
496 arpreq.opcode = htons(ARPOP_REQUEST);
497 memcpy(arpreq.shwaddr, arptable[ARP_CLIENT].node, ETH_ALEN);
498 memcpy(arpreq.sipaddr, &arptable[ARP_CLIENT].ipaddr, sizeof(in_addr));
499 memset(arpreq.thwaddr, 0, ETH_ALEN);
500 memcpy(arpreq.tipaddr, &destip, sizeof(in_addr));
501 for (retry = 1; retry <= MAX_ARP_RETRIES; retry++) {
503 eth_transmit(broadcast, ETH_P_ARP, sizeof(arpreq),
505 timeout = rfc2131_sleep_interval(TIMEOUT, retry);
506 if (await_reply(await_arp, arpentry,
507 arpreq.tipaddr, timeout)) goto xmit;
512 eth_transmit(arptable[arpentry].node, ETH_P_IP, len, buf);
517 void build_ip_hdr(unsigned long destip, int ttl, int protocol, int option_len,
518 int len, const void *buf)
521 ip = (struct iphdr *)buf;
522 ip->verhdrlen = 0x45;
523 ip->verhdrlen += (option_len/4);
525 ip->len = htons(len);
527 ip->frags = 0; /* Should we set don't fragment? */
529 ip->protocol = protocol;
531 ip->src.s_addr = arptable[ARP_CLIENT].ipaddr.s_addr;
532 ip->dest.s_addr = destip;
533 ip->chksum = ipchksum(buf, sizeof(struct iphdr) + option_len);
536 void build_udp_hdr(unsigned long destip,
537 unsigned int srcsock, unsigned int destsock, int ttl,
538 int len, const void *buf)
542 ip = (struct iphdr *)buf;
543 build_ip_hdr(destip, ttl, IP_UDP, 0, len, buf);
544 udp = (struct udphdr *)((char *)buf + sizeof(struct iphdr));
545 udp->src = htons(srcsock);
546 udp->dest = htons(destsock);
547 udp->len = htons(len - sizeof(struct iphdr));
549 if ((udp->chksum = tcpudpchksum(ip)) == 0)
550 udp->chksum = 0xffff;
553 /**************************************************************************
554 UDP_TRANSMIT - Send an UDP datagram
555 **************************************************************************/
556 int udp_transmit(unsigned long destip, unsigned int srcsock,
557 unsigned int destsock, int len, const void *buf)
559 build_udp_hdr(destip, srcsock, destsock, 60, len, buf);
560 return ip_transmit(len, buf);
564 /**************************************************************************
565 QDRAIN - clear the nic's receive queue
566 **************************************************************************/
567 static int await_qdrain(int ival __unused, void *ptr __unused,
568 unsigned short ptype __unused,
569 struct iphdr *ip __unused, struct udphdr *udp __unused,
570 struct tcphdr *tcp __unused)
577 /* Clear out the Rx queue first. It contains nothing of interest,
578 * except possibly ARP requests from the DHCP/TFTP server. We use
579 * polling throughout Etherboot, so some time may have passed since we
580 * last polled the receive queue, which may now be filled with
581 * broadcast packets. This will cause the reply to the packets we are
582 * about to send to be lost immediately. Not very clever. */
583 await_reply(await_qdrain, 0, NULL, 0);
586 #ifdef RARP_NOT_BOOTP
587 /**************************************************************************
588 RARP - Get my IP address and load information
589 **************************************************************************/
590 static int await_rarp(int ival, void *ptr,
591 unsigned short ptype, struct iphdr *ip, struct udphdr *udp,
592 struct tcphdr *tcp __unused)
594 struct arprequest *arpreply;
595 if (ptype != ETH_P_RARP)
597 if (nic.packetlen < ETH_HLEN + sizeof(struct arprequest))
599 arpreply = (struct arprequest *)&nic.packet[ETH_HLEN];
600 if (arpreply->opcode != htons(RARP_REPLY))
602 if ((arpreply->opcode == htons(RARP_REPLY)) &&
603 (memcmp(arpreply->thwaddr, ptr, ETH_ALEN) == 0)) {
604 memcpy(arptable[ARP_SERVER].node, arpreply->shwaddr, ETH_ALEN);
605 memcpy(&arptable[ARP_SERVER].ipaddr, arpreply->sipaddr, sizeof(in_addr));
606 memcpy(&arptable[ARP_CLIENT].ipaddr, arpreply->tipaddr, sizeof(in_addr));
612 static int rarp(void)
616 /* arp and rarp requests share the same packet structure. */
617 struct arprequest rarpreq;
619 memset(&rarpreq, 0, sizeof(rarpreq));
621 rarpreq.hwtype = htons(1);
622 rarpreq.protocol = htons(IP);
623 rarpreq.hwlen = ETH_ALEN;
624 rarpreq.protolen = 4;
625 rarpreq.opcode = htons(RARP_REQUEST);
626 memcpy(&rarpreq.shwaddr, arptable[ARP_CLIENT].node, ETH_ALEN);
627 /* sipaddr is already zeroed out */
628 memcpy(&rarpreq.thwaddr, arptable[ARP_CLIENT].node, ETH_ALEN);
629 /* tipaddr is already zeroed out */
631 for (retry = 0; retry < MAX_ARP_RETRIES; ++retry) {
633 eth_transmit(broadcast, ETH_P_RARP, sizeof(rarpreq), &rarpreq);
635 timeout = rfc2131_sleep_interval(TIMEOUT, retry);
636 if (await_reply(await_rarp, 0, rarpreq.shwaddr, timeout))
640 if (retry < MAX_ARP_RETRIES) {
641 (void)sprintf(KERNEL_BUF, DEFAULT_KERNELPATH, arptable[ARP_CLIENT].ipaddr);
650 /**************************************************************************
651 BOOTP - Get my IP address and load information
652 **************************************************************************/
653 static int await_bootp(int ival __unused, void *ptr __unused,
654 unsigned short ptype __unused, struct iphdr *ip __unused,
655 struct udphdr *udp, struct tcphdr *tcp __unused)
657 struct bootp_t *bootpreply;
661 bootpreply = (struct bootp_t *)&nic.packet[ETH_HLEN +
662 sizeof(struct iphdr) + sizeof(struct udphdr)];
663 if (nic.packetlen < ETH_HLEN + sizeof(struct iphdr) +
664 sizeof(struct udphdr) +
665 #ifdef NO_DHCP_SUPPORT
666 sizeof(struct bootp_t)
668 sizeof(struct bootp_t) - DHCP_OPT_LEN
669 #endif /* NO_DHCP_SUPPORT */
673 if (udp->dest != htons(BOOTP_CLIENT))
675 if (bootpreply->bp_op != BOOTP_REPLY)
677 if (bootpreply->bp_xid != xid)
679 if (memcmp(&bootpreply->bp_siaddr, &zeroIP, sizeof(in_addr)) == 0)
681 if ((memcmp(broadcast, bootpreply->bp_hwaddr, ETH_ALEN) != 0) &&
682 (memcmp(arptable[ARP_CLIENT].node, bootpreply->bp_hwaddr, ETH_ALEN) != 0)) {
685 if ( bootpreply->bp_siaddr.s_addr ) {
686 arptable[ARP_SERVER].ipaddr.s_addr = bootpreply->bp_siaddr.s_addr;
687 memset(arptable[ARP_SERVER].node, 0, ETH_ALEN); /* Kill arp */
689 if ( bootpreply->bp_giaddr.s_addr ) {
690 arptable[ARP_GATEWAY].ipaddr.s_addr = bootpreply->bp_giaddr.s_addr;
691 memset(arptable[ARP_GATEWAY].node, 0, ETH_ALEN); /* Kill arp */
693 if (bootpreply->bp_yiaddr.s_addr) {
694 /* Offer with an IP address */
695 arptable[ARP_CLIENT].ipaddr.s_addr = bootpreply->bp_yiaddr.s_addr;
696 #ifndef NO_DHCP_SUPPORT
697 dhcp_addr.s_addr = bootpreply->bp_yiaddr.s_addr;
698 #endif /* NO_DHCP_SUPPORT */
699 netmask = default_netmask();
700 /* bootpreply->bp_file will be copied to KERNEL_BUF in the memcpy */
701 memcpy((char *)&bootp_data, (char *)bootpreply, sizeof(struct bootpd_t));
702 decode_rfc1533(bootp_data.bootp_reply.bp_vend, 0,
703 #ifdef NO_DHCP_SUPPORT
704 BOOTP_VENDOR_LEN + MAX_BOOTP_EXTLEN,
706 DHCP_OPT_LEN + MAX_BOOTP_EXTLEN,
707 #endif /* NO_DHCP_SUPPORT */
711 /* Offer without an IP address - use as ProxyDHCP server */
712 arptable[ARP_PROXYDHCP].ipaddr.s_addr = bootpreply->bp_siaddr.s_addr;
713 memset(arptable[ARP_PROXYDHCP].node, 0, ETH_ALEN); /* Kill arp */
714 /* Grab only the bootfile name from a ProxyDHCP packet */
715 memcpy(KERNEL_BUF, bootpreply->bp_file, sizeof(KERNEL_BUF));
716 #endif /* PXE_EXPORT */
718 #ifdef REQUIRE_VCI_ETHERBOOT
725 static int bootp(void)
728 #ifndef NO_DHCP_SUPPORT
730 #endif /* NO_DHCP_SUPPORT */
732 unsigned long starttime;
733 unsigned char *bp_vend;
735 #ifndef NO_DHCP_SUPPORT
736 * ( ( struct dhcp_dev_id * ) &dhcp_machine_info[4] ) = nic.dhcp_dev_id;
737 #endif /* NO_DHCP_SUPPORT */
738 memset(&ip, 0, sizeof(struct bootpip_t));
739 ip.bp.bp_op = BOOTP_REQUEST;
741 ip.bp.bp_hlen = ETH_ALEN;
742 starttime = currticks();
743 /* Use lower 32 bits of node address, more likely to be
744 distinct than the time since booting */
745 memcpy(&xid, &arptable[ARP_CLIENT].node[2], sizeof(xid));
746 ip.bp.bp_xid = xid += htonl(starttime);
747 memcpy(ip.bp.bp_hwaddr, arptable[ARP_CLIENT].node, ETH_ALEN);
748 #ifdef NO_DHCP_SUPPORT
749 memcpy(ip.bp.bp_vend, rfc1533_cookie, 5); /* request RFC-style options */
751 memcpy(ip.bp.bp_vend, rfc1533_cookie, sizeof rfc1533_cookie); /* request RFC-style options */
752 memcpy(ip.bp.bp_vend + sizeof rfc1533_cookie, dhcpdiscover, sizeof dhcpdiscover);
753 /* Append machine_info to end, in encapsulated option */
754 bp_vend = ip.bp.bp_vend + sizeof rfc1533_cookie + sizeof dhcpdiscover;
755 memcpy(bp_vend, dhcp_machine_info, DHCP_MACHINE_INFO_SIZE);
756 bp_vend += DHCP_MACHINE_INFO_SIZE;
757 *bp_vend++ = RFC1533_END;
758 #endif /* NO_DHCP_SUPPORT */
760 for (retry = 0; retry < MAX_BOOTP_RETRIES; ) {
761 uint8_t my_hwaddr[ETH_ALEN];
762 unsigned long stop_time;
767 /* Kill arptable to avoid keeping stale entries */
768 memcpy ( my_hwaddr, arptable[ARP_CLIENT].node, ETH_ALEN );
769 memset ( arptable, 0, sizeof(arptable) );
770 memcpy ( arptable[ARP_CLIENT].node, my_hwaddr, ETH_ALEN );
772 udp_transmit(INADDR_BROADCAST, BOOTP_CLIENT, BOOTP_SERVER,
773 sizeof(struct bootpip_t), &ip);
774 remaining_time = rfc2131_sleep_interval(BOOTP_TIMEOUT, retry++);
775 stop_time = currticks() + remaining_time;
776 #ifdef NO_DHCP_SUPPORT
777 if (await_reply(await_bootp, 0, NULL, remaining_time))
780 while ( remaining_time > 0 ) {
781 if (await_reply(await_bootp, 0, NULL, remaining_time)){
782 if (arptable[ARP_CLIENT].ipaddr.s_addr)
785 remaining_time = stop_time - currticks();
787 if ( ! arptable[ARP_CLIENT].ipaddr.s_addr ) {
788 printf("No IP address\n");
791 /* If not a DHCPOFFER then must be just a BOOTP reply,
792 * be backward compatible with BOOTP then */
793 if (dhcp_reply != DHCPOFFER)
796 /* Construct the DHCPREQUEST packet */
797 memcpy(ip.bp.bp_vend, rfc1533_cookie, sizeof rfc1533_cookie);
798 memcpy(ip.bp.bp_vend + sizeof rfc1533_cookie, dhcprequest, sizeof dhcprequest);
799 /* Beware: the magic numbers 9 and 15 depend on
800 the layout of dhcprequest */
801 memcpy(&ip.bp.bp_vend[9], &dhcp_server, sizeof(in_addr));
802 memcpy(&ip.bp.bp_vend[15], &dhcp_addr, sizeof(in_addr));
803 bp_vend = ip.bp.bp_vend + sizeof rfc1533_cookie + sizeof dhcprequest;
804 /* Append machine_info to end, in encapsulated option */
805 memcpy(bp_vend, dhcp_machine_info, DHCP_MACHINE_INFO_SIZE);
806 bp_vend += DHCP_MACHINE_INFO_SIZE;
807 *bp_vend++ = RFC1533_END;
808 for (reqretry = 0; reqretry < MAX_BOOTP_RETRIES; ) {
809 unsigned long timeout;
811 udp_transmit(INADDR_BROADCAST, BOOTP_CLIENT,
812 BOOTP_SERVER, sizeof(struct bootpip_t),
815 timeout = rfc2131_sleep_interval(TIMEOUT, reqretry++);
816 if (!await_reply(await_bootp, 0, NULL, timeout))
818 if (dhcp_reply != DHCPACK)
822 if ( arptable[ARP_PROXYDHCP].ipaddr.s_addr ) {
823 /* Construct the ProxyDHCPREQUEST packet */
824 memcpy(ip.bp.bp_vend, rfc1533_cookie, sizeof rfc1533_cookie);
825 memcpy(ip.bp.bp_vend + sizeof rfc1533_cookie, proxydhcprequest, sizeof proxydhcprequest);
826 for (reqretry = 0; reqretry < MAX_BOOTP_RETRIES; ) {
827 printf ( "\nSending ProxyDHCP request to %s...",
828 inet_ntoa ( arptable[ARP_PROXYDHCP].ipaddr ) );
829 udp_transmit(arptable[ARP_PROXYDHCP].ipaddr.s_addr, BOOTP_CLIENT, PROXYDHCP_SERVER,
830 sizeof(struct bootpip_t), &ip);
831 timeout = rfc2131_sleep_interval(TIMEOUT, reqretry++);
832 if (await_reply(await_bootp, 0, NULL, timeout)) {
837 #endif /* PXE_EXPORT */
840 #endif /* NO_DHCP_SUPPORT */
841 ip.bp.bp_secs = htons((currticks()-starttime)/TICKS_PER_SEC);
845 #endif /* RARP_NOT_BOOTP */
847 uint16_t tcpudpchksum(struct iphdr *ip)
849 struct udp_pseudo_hdr pseudo;
852 /* Compute the pseudo header */
853 pseudo.src.s_addr = ip->src.s_addr;
854 pseudo.dest.s_addr = ip->dest.s_addr;
856 pseudo.protocol = ip->protocol;
857 pseudo.len = htons(ntohs(ip->len) - sizeof(struct iphdr));
859 /* Sum the pseudo header */
860 checksum = ipchksum(&pseudo, 12);
862 /* Sum the rest of the tcp/udp packet */
863 checksum = add_ipchksums(12, checksum, ipchksum(ip + 1,
864 ntohs(ip->len) - sizeof(struct iphdr)));
869 #include "proto_eth_slow.c"
872 /**************************************************************************
873 AWAIT_REPLY - Wait until we get a response for our request
874 ************f**************************************************************/
875 int await_reply(reply_t reply, int ival, void *ptr, long timeout)
877 unsigned long time, now;
882 unsigned short ptype;
885 time = timeout + currticks();
886 /* The timeout check is done below. The timeout is only checked if
887 * there is no packet in the Rx queue. This assumes that eth_poll()
888 * needs a negligible amount of time.
892 background_send(now);
893 send_eth_slow_reports(now);
894 result = eth_poll(1);
896 /* We don't have anything */
898 /* Do the timeout after at least a full queue walk. */
899 if ((timeout == 0) || (currticks() > time)) {
905 /* We have something! */
907 /* Find the Ethernet packet type */
908 if (nic.packetlen >= ETH_HLEN) {
909 ptype = ((unsigned short) nic.packet[12]) << 8
910 | ((unsigned short) nic.packet[13]);
911 } else continue; /* what else could we do with it? */
912 /* Verify an IP header */
914 if ((ptype == ETH_P_IP) && (nic.packetlen >= ETH_HLEN + sizeof(struct iphdr))) {
916 ip = (struct iphdr *)&nic.packet[ETH_HLEN];
917 if ((ip->verhdrlen < 0x45) || (ip->verhdrlen > 0x4F))
919 iplen = (ip->verhdrlen & 0xf) * 4;
920 if (ipchksum(ip, iplen) != 0)
922 if (ip->frags & htons(0x3FFF)) {
923 static int warned_fragmentation = 0;
924 if (!warned_fragmentation) {
925 printf("ALERT: got a fragmented packet - reconfigure your server\n");
926 warned_fragmentation = 1;
930 if (ntohs(ip->len) > ETH_MAX_MTU)
933 ipoptlen = iplen - sizeof(struct iphdr);
935 /* Delete the ip options, to guarantee
936 * good alignment, and make etherboot simpler.
938 memmove(&nic.packet[ETH_HLEN + sizeof(struct iphdr)],
939 &nic.packet[ETH_HLEN + iplen],
940 nic.packetlen - ipoptlen);
941 nic.packetlen -= ipoptlen;
945 if (ip && (ip->protocol == IP_UDP) &&
947 ETH_HLEN + sizeof(struct iphdr) + sizeof(struct udphdr))) {
948 udp = (struct udphdr *)&nic.packet[ETH_HLEN + sizeof(struct iphdr)];
950 /* Make certain we have a reasonable packet length */
951 if (ntohs(udp->len) > (ntohs(ip->len) - iplen))
954 if (udp->chksum && tcpudpchksum(ip)) {
955 printf("UDP checksum error\n");
960 if (ip && (ip->protocol == IP_TCP) &&
962 ETH_HLEN + sizeof(struct iphdr) + sizeof(struct tcphdr))){
963 tcp = (struct tcphdr *)&nic.packet[ETH_HLEN +
964 sizeof(struct iphdr)];
965 /* Make certain we have a reasonable packet length */
966 if (((ntohs(tcp->ctrl) >> 10) & 0x3C) >
967 ntohs(ip->len) - (int)iplen)
969 if (tcpudpchksum(ip)) {
970 printf("TCP checksum error\n");
975 result = reply(ival, ptr, ptype, ip, udp, tcp);
980 /* If it isn't a packet the upper layer wants see if there is a default
981 * action. This allows us reply to arp, igmp, and lacp queries.
983 if ((ptype == ETH_P_ARP) &&
984 (nic.packetlen >= ETH_HLEN + sizeof(struct arprequest))) {
985 struct arprequest *arpreply;
988 arpreply = (struct arprequest *)&nic.packet[ETH_HLEN];
989 memcpy(&tmp, arpreply->tipaddr, sizeof(in_addr));
990 if ((arpreply->opcode == htons(ARPOP_REQUEST)) &&
991 (tmp == arptable[ARP_CLIENT].ipaddr.s_addr)) {
992 arpreply->opcode = htons(ARPOP_REPLY);
993 memcpy(arpreply->tipaddr, arpreply->sipaddr, sizeof(in_addr));
994 memcpy(arpreply->thwaddr, arpreply->shwaddr, ETH_ALEN);
995 memcpy(arpreply->sipaddr, &arptable[ARP_CLIENT].ipaddr, sizeof(in_addr));
996 memcpy(arpreply->shwaddr, arptable[ARP_CLIENT].node, ETH_ALEN);
997 eth_transmit(arpreply->thwaddr, ETH_P_ARP,
998 sizeof(struct arprequest),
1001 memcpy(&tmp, arpreply->tipaddr, sizeof(in_addr));
1002 printf( "Sent ARP reply to: %s\n", inet_ntoa ( tmp ) );
1006 background_process(now, ptype, ip);
1007 process_eth_slow(ptype, now);
1012 #ifdef REQUIRE_VCI_ETHERBOOT
1013 /**************************************************************************
1014 FIND_VCI_ETHERBOOT - Looks for "Etherboot" in Vendor Encapsulated Identifiers
1015 On entry p points to byte count of VCI options
1016 **************************************************************************/
1017 static int find_vci_etherboot(unsigned char *p)
1019 unsigned char *end = p + 1 + *p;
1021 for (p++; p < end; ) {
1022 if (*p == RFC2132_VENDOR_CLASS_ID) {
1023 if (strncmp("Etherboot", p + 2, sizeof("Etherboot") - 1) == 0)
1025 } else if (*p == RFC1533_END)
1027 p += TAG_LEN(p) + 2;
1031 #endif /* REQUIRE_VCI_ETHERBOOT */
1033 /**************************************************************************
1034 DECODE_RFC1533 - Decodes RFC1533 header
1035 **************************************************************************/
1036 int decode_rfc1533(unsigned char *p, unsigned int block, unsigned int len, int eof)
1038 static unsigned char *extdata = NULL, *extend = NULL;
1039 unsigned char *extpath = NULL;
1040 unsigned char *endp;
1041 static unsigned char in_encapsulated_options = 0;
1044 /* Encapsulated option block */
1047 else if (block == 0) {
1048 #ifdef REQUIRE_VCI_ETHERBOOT
1051 end_of_rfc1533 = NULL;
1052 #ifdef IMAGE_FREEBSD
1053 /* yes this is a pain FreeBSD uses this for swap, however,
1054 there are cases when you don't want swap and then
1055 you want this set to get the extra features so lets
1056 just set if dealing with FreeBSD. I haven't run into
1057 any troubles with this but I have without it
1059 vendorext_isvalid = 1;
1060 #ifdef FREEBSD_KERNEL_ENV
1061 memcpy(freebsd_kernel_env, FREEBSD_KERNEL_ENV,
1062 sizeof(FREEBSD_KERNEL_ENV));
1063 /* FREEBSD_KERNEL_ENV had better be a string constant */
1065 freebsd_kernel_env[0]='\0';
1068 vendorext_isvalid = 0;
1072 if (memcmp(p, rfc1533_cookie, 4))
1073 return(0); /* no RFC 1533 header found */
1078 if (memcmp(p, rfc1533_cookie, 4))
1079 return(0); /* no RFC 1533 header found */
1082 if (extend + len <= (unsigned char *)&(bootp_data.bootp_extension[MAX_BOOTP_EXTLEN])) {
1083 memcpy(extend, p, len);
1086 printf("Overflow in vendor data buffer! Aborting...\n");
1087 *extdata = RFC1533_END;
1090 p = extdata; endp = extend;
1095 unsigned char c = *p;
1096 if (c == RFC1533_PAD) {
1100 else if (c == RFC1533_END) {
1101 end_of_rfc1533 = endp = p;
1104 else if (NON_ENCAP_OPT c == RFC1533_NETMASK)
1105 memcpy(&netmask, p+2, sizeof(in_addr));
1106 else if (NON_ENCAP_OPT c == RFC1533_GATEWAY) {
1107 /* This is a little simplistic, but it will
1108 usually be sufficient.
1109 Take only the first entry */
1110 if (TAG_LEN(p) >= sizeof(in_addr))
1111 memcpy(&arptable[ARP_GATEWAY].ipaddr, p+2, sizeof(in_addr));
1113 else if (c == RFC1533_EXTENSIONPATH)
1115 #ifndef NO_DHCP_SUPPORT
1116 #ifdef REQUIRE_VCI_ETHERBOOT
1117 else if (NON_ENCAP_OPT c == RFC1533_VENDOR) {
1118 vci_etherboot = find_vci_etherboot(p+1);
1120 printf("vci_etherboot %d\n", vci_etherboot);
1123 #endif /* REQUIRE_VCI_ETHERBOOT */
1124 else if (NON_ENCAP_OPT c == RFC2132_MSG_TYPE)
1126 else if (NON_ENCAP_OPT c == RFC2132_SRV_ID)
1127 memcpy(&dhcp_server, p+2, sizeof(in_addr));
1128 #endif /* NO_DHCP_SUPPORT */
1129 else if (NON_ENCAP_OPT c == RFC1533_HOSTNAME) {
1131 hostnamelen = *(p + 1);
1133 else if (ENCAP_OPT c == RFC1533_VENDOR_MAGIC
1134 && TAG_LEN(p) >= 6 &&
1135 !memcmp(p+2,vendorext_magic,4) &&
1136 p[6] == RFC1533_VENDOR_MAJOR
1138 vendorext_isvalid++;
1139 else if (c == RFC1533_VENDOR_ADDPARM) {
1140 /* This tag intentionally works for BOTH the encapsulated and
1141 * non-encapsulated case, since the current menu code (in mknbi)
1142 * creates this tag without encapsulation. In the future both the
1143 * menu from mknbi and this code should learn about the proper
1144 * encapsulation (which will require substantial changes to various
1145 * stuff from mknbi, which will break compatibility with older
1146 * versions of Etherboot). */
1148 addparamlen = *(p + 1);
1150 else if (NON_ENCAP_OPT c == RFC1533_VENDOR_ETHERBOOT_ENCAP) {
1151 in_encapsulated_options = 1;
1152 decode_rfc1533(p+2, 0, TAG_LEN(p), -1);
1153 in_encapsulated_options = 0;
1155 #ifdef IMAGE_FREEBSD
1156 else if (NON_ENCAP_OPT c == RFC1533_VENDOR_HOWTO)
1157 freebsd_howto = ((p[2]*256+p[3])*256+p[4])*256+p[5];
1158 else if (NON_ENCAP_OPT c == RFC1533_VENDOR_KERNEL_ENV){
1159 if(*(p + 1) < sizeof(freebsd_kernel_env)){
1160 memcpy(freebsd_kernel_env,p+2,*(p+1));
1162 printf("Only support %ld bytes in Kernel Env\n",
1163 sizeof(freebsd_kernel_env));
1167 else if (NON_ENCAP_OPT c == RFC1533_DNS) {
1168 // TODO: Copy the DNS IP somewhere reasonable
1169 if (TAG_LEN(p) >= sizeof(in_addr))
1170 memcpy(&arptable[ARP_NAMESERVER].ipaddr, p+2, sizeof(in_addr));
1175 printf("Unknown RFC1533-tag ");
1176 for(q=p;q<p+2+TAG_LEN(p);q++)
1181 p += TAG_LEN(p) + 2;
1183 extdata = extend = endp;
1184 if (block <= 0 && extpath != NULL) {
1186 memcpy(fname, extpath+2, TAG_LEN(extpath));
1187 fname[(int)TAG_LEN(extpath)] = '\0';
1188 printf("Loading BOOTP-extension file: %s\n",fname);
1189 #warning "BOOTP extension files are broken"
1190 /* tftp(fname, decode_rfc1533); */
1192 return 1; /* proceed with next block */
1196 /* FIXME double check TWO_SECOND_DIVISOR */
1197 #define TWO_SECOND_DIVISOR (RAND_MAX/TICKS_PER_SEC)
1198 /**************************************************************************
1199 RFC2131_SLEEP_INTERVAL - sleep for expotentially longer times (base << exp) +- 1 sec)
1200 **************************************************************************/
1201 long rfc2131_sleep_interval(long base, int exp)
1204 if (exp > BACKOFF_LIMIT)
1205 exp = BACKOFF_LIMIT;
1206 tmo = (base << exp) + (TICKS_PER_SEC - (random()/TWO_SECOND_DIVISOR));