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"
21 #include "elf.h" /* FOR EM_CURRENT */
23 struct arptable_t arptable[MAX_ARP];
25 unsigned long last_igmpv1 = 0;
26 struct igmptable_t igmptable[MAX_IGMP];
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 */
95 #define DHCPDISCOVER_PARAMS_DNS 1
97 #define DHCPDISCOVER_PARAMS_DNS 0
98 #endif /* DNS_RESOLVER */
99 ( DHCPDISCOVER_PARAMS_BASE +
100 DHCPDISCOVER_PARAMS_PXE+
101 DHCPDISCOVER_PARAMS_DNS ),
106 #ifdef PXE_DHCP_STRICT
107 ,RFC2132_VENDOR_CLASS_ID,
108 RFC1533_VENDOR_PXE_OPT128,
109 RFC1533_VENDOR_PXE_OPT129,
110 RFC1533_VENDOR_PXE_OPT130,
111 RFC1533_VENDOR_PXE_OPT131,
112 RFC1533_VENDOR_PXE_OPT132,
113 RFC1533_VENDOR_PXE_OPT133,
114 RFC1533_VENDOR_PXE_OPT134,
115 RFC1533_VENDOR_PXE_OPT135
116 #endif /* PXE_DHCP_STRICT */
121 static const unsigned char dhcprequest [] = {
122 RFC2132_MSG_TYPE,1,DHCPREQUEST,
123 RFC2132_SRV_ID,4,0,0,0,0,
124 RFC2132_REQ_ADDR,4,0,0,0,0,
125 RFC2132_MAX_SIZE,2, /* request as much as we can */
126 ETH_MAX_MTU / 256, ETH_MAX_MTU % 256,
127 #ifdef PXE_DHCP_STRICT
128 RFC3679_PXE_CLIENT_UUID,RFC3679_PXE_CLIENT_UUID_LENGTH,RFC3679_PXE_CLIENT_UUID_DEFAULT,
129 RFC3679_PXE_CLIENT_ARCH,RFC3679_PXE_CLIENT_ARCH_LENGTH,RFC3679_PXE_CLIENT_ARCH_IAX86PC,
130 RFC3679_PXE_CLIENT_NDI, RFC3679_PXE_CLIENT_NDI_LENGTH, RFC3679_PXE_CLIENT_NDI_21,
131 RFC2132_VENDOR_CLASS_ID,RFC2132_VENDOR_CLASS_ID_PXE_LENGTH,RFC2132_VENDOR_CLASS_ID_PXE,
133 RFC2132_VENDOR_CLASS_ID,13,'E','t','h','e','r','b','o','o','t',
134 '-',VERSION_MAJOR+'0','.',VERSION_MINOR+'0',
135 #endif /* PXE_DHCP_STRICT */
136 #ifdef DHCP_CLIENT_ID
137 /* Client ID Option */
138 RFC2132_CLIENT_ID, ( DHCP_CLIENT_ID_LEN + 1 ),
139 DHCP_CLIENT_ID_TYPE, DHCP_CLIENT_ID,
140 #endif /* DHCP_CLIENT_ID */
141 #ifdef DHCP_USER_CLASS
142 /* User Class Option */
143 RFC3004_USER_CLASS, DHCP_USER_CLASS_LEN, DHCP_USER_CLASS,
144 #endif /* DHCP_USER_CLASS */
145 /* request parameters */
147 #define DHCPREQUEST_PARAMS_BASE 5
148 #ifdef PXE_DHCP_STRICT
149 #define DHCPREQUEST_PARAMS_PXE 1
150 #define DHCPREQUEST_PARAMS_VENDOR_PXE 8
151 #define DHCPREQUEST_PARAMS_VENDOR_EB 0
153 #define DHCPREQUEST_PARAMS_PXE 0
154 #define DHCPREQUEST_PARAMS_VENDOR_PXE 0
155 #define DHCPREQUEST_PARAMS_VENDOR_EB 4
156 #endif /* PXE_DHCP_STRICT */
158 #define DHCPREQUEST_PARAMS_FREEBSD 2
160 #define DHCPREQUEST_PARAMS_FREEBSD 0
161 #endif /* IMAGE_FREEBSD */
163 #define DHCPREQUEST_PARAMS_DNS 1
165 #define DHCPREQUEST_PARAMS_DNS 0
166 #endif /* DNS_RESOLVER */
167 ( DHCPREQUEST_PARAMS_BASE +
168 DHCPREQUEST_PARAMS_PXE +
169 DHCPREQUEST_PARAMS_VENDOR_PXE +
170 DHCPREQUEST_PARAMS_VENDOR_EB +
171 DHCPREQUEST_PARAMS_DNS +
172 DHCPREQUEST_PARAMS_FREEBSD ),
173 /* 5 Standard parameters */
178 RFC1533_ROOTPATH, /* only passed to the booted image */
179 #ifndef PXE_DHCP_STRICT
180 /* 4 Etherboot vendortags */
181 RFC1533_VENDOR_MAGIC,
182 RFC1533_VENDOR_ADDPARM,
183 RFC1533_VENDOR_ETHDEV,
184 RFC1533_VENDOR_ETHERBOOT_ENCAP,
185 #endif /* ! PXE_DHCP_STRICT */
187 /* 2 FreeBSD options */
188 RFC1533_VENDOR_HOWTO,
189 RFC1533_VENDOR_KERNEL_ENV,
195 #ifdef PXE_DHCP_STRICT
196 RFC2132_VENDOR_CLASS_ID,
197 RFC1533_VENDOR_PXE_OPT128,
198 RFC1533_VENDOR_PXE_OPT129,
199 RFC1533_VENDOR_PXE_OPT130,
200 RFC1533_VENDOR_PXE_OPT131,
201 RFC1533_VENDOR_PXE_OPT132,
202 RFC1533_VENDOR_PXE_OPT133,
203 RFC1533_VENDOR_PXE_OPT134,
204 RFC1533_VENDOR_PXE_OPT135,
205 #endif /* PXE_DHCP_STRICT */
208 static const unsigned char proxydhcprequest [] = {
209 RFC2132_MSG_TYPE,1,DHCPREQUEST,
210 RFC2132_MAX_SIZE,2, /* request as much as we can */
211 ETH_MAX_MTU / 256, ETH_MAX_MTU % 256,
212 #ifdef PXE_DHCP_STRICT
213 RFC3679_PXE_CLIENT_UUID,RFC3679_PXE_CLIENT_UUID_LENGTH,RFC3679_PXE_CLIENT_UUID_DEFAULT,
214 RFC3679_PXE_CLIENT_ARCH,RFC3679_PXE_CLIENT_ARCH_LENGTH,RFC3679_PXE_CLIENT_ARCH_IAX86PC,
215 RFC3679_PXE_CLIENT_NDI, RFC3679_PXE_CLIENT_NDI_LENGTH, RFC3679_PXE_CLIENT_NDI_21,
216 RFC2132_VENDOR_CLASS_ID,RFC2132_VENDOR_CLASS_ID_PXE_LENGTH,RFC2132_VENDOR_CLASS_ID_PXE,
217 #endif /* PXE_DHCP_STRICT */
221 #ifdef REQUIRE_VCI_ETHERBOOT
224 #endif /* NO_DHCP_SUPPORT */
226 #ifdef RARP_NOT_BOOTP
227 static int rarp(void);
229 static int bootp(void);
231 static unsigned short tcpudpchksum(struct iphdr *ip);
235 * Find out what our boot parameters are
237 static int nic_configure ( struct type_dev *type_dev ) {
238 struct nic *nic = ( struct nic * ) type_dev;
241 if ( ! nic->nic_op->connect ( nic ) ) {
242 printf ( "No connection to network\n" );
246 /* Find a server to get BOOTP reply from */
247 #ifdef RARP_NOT_BOOTP
248 printf("Searching for server (RARP)...");
250 #ifndef NO_DHCP_SUPPORT
251 printf("Searching for server (DHCP)...");
253 printf("Searching for server (BOOTP)...");
257 #ifdef RARP_NOT_BOOTP
258 server_found = rarp();
260 server_found = bootp();
263 printf("No Server found\n");
267 printf("\nMe: %@", arptable[ARP_CLIENT].ipaddr.s_addr );
268 #ifndef NO_DHCP_SUPPORT
269 printf(", DHCP: %@", dhcp_server );
271 if (arptable[ARP_PROXYDHCP].ipaddr.s_addr)
273 arptable[ARP_PROXYDHCP].ipaddr.s_addr);
274 #endif /* PXE_EXPORT */
275 #endif /* ! NO_DHCP_SUPPORT */
276 printf(", TFTP: %@", arptable[ARP_SERVER].ipaddr.s_addr);
277 if (BOOTP_DATA_ADDR->bootp_reply.bp_giaddr.s_addr)
278 printf(", Relay: %@",
279 BOOTP_DATA_ADDR->bootp_reply.bp_giaddr.s_addr);
280 if (arptable[ARP_GATEWAY].ipaddr.s_addr)
281 printf(", Gateway %@", arptable[ARP_GATEWAY].ipaddr.s_addr);
283 if (arptable[ARP_NAMESERVER].ipaddr.s_addr)
284 printf(", Nameserver %@", arptable[ARP_NAMESERVER].ipaddr.s_addr);
289 printf("\n=>>"); getchar();
296 /**************************************************************************
297 LOAD - Try to get booted
298 **************************************************************************/
299 static int nic_load ( struct type_dev *type_dev,
300 int ( * process ) ( unsigned char *data,
301 unsigned int blocknum,
302 unsigned int size, int eof ) ) {
305 /* Now use TFTP to load file */
306 #ifdef DOWNLOAD_PROTO_NFS
309 kernel = KERNEL_BUF[0] == '\0' ?
310 #ifdef DEFAULT_BOOTFILE
317 loadkernel(kernel,process); /* We don't return except on error */
318 printf("Unable to load file.\n");
320 printf("No filename\n");
322 interruptible_sleep(2); /* lay off the server for a while */
326 void nic_disable ( struct nic *nic __unused ) {
327 #ifdef MULTICAST_LEVEL2
329 for(i = 0; i < MAX_IGMP; i++) {
335 static char * nic_describe_device ( struct type_dev *type_dev ) {
336 struct nic *nic = ( struct nic * ) type_dev;
337 static char nic_description[] = "MAC 00:00:00:00:00:00";
339 sprintf ( nic_description + 4, "%!", nic->node_addr );
340 return nic_description;
344 * Device operations tables
347 struct type_driver nic_driver = {
349 .type_dev = ( struct type_dev * ) &nic,
350 .describe_device = nic_describe_device,
351 .configure = nic_configure,
355 /* Careful. We need an aligned buffer to avoid problems on machines
356 * that care about alignment. To trivally align the ethernet data
357 * (the ip hdr and arp requests) we offset the packet by 2 bytes.
358 * leaving the ethernet data 16 byte aligned. Beyond this
359 * we use memmove but this makes the common cast simple and fast.
361 static char packet[ETH_FRAME_LEN + ETH_DATA_ALIGN] __aligned;
364 .node_addr = arptable[ARP_CLIENT].node,
365 .packet = packet + ETH_DATA_ALIGN,
370 int dummy_connect ( struct nic *nic __unused ) {
374 void dummy_irq ( struct nic *nic __unused, irq_action_t irq_action __unused ) {
378 /**************************************************************************
379 DEFAULT_NETMASK - Return default netmask for IP address
380 **************************************************************************/
381 static inline unsigned long default_netmask(void)
383 int net = ntohl(arptable[ARP_CLIENT].ipaddr.s_addr) >> 24;
385 return(htonl(0xff000000));
387 return(htonl(0xffff0000));
389 return(htonl(0xffffff00));
392 /**************************************************************************
393 IP_TRANSMIT - Send an IP datagram
394 **************************************************************************/
395 static int await_arp(int ival, void *ptr,
396 unsigned short ptype, struct iphdr *ip __unused, struct udphdr *udp __unused,
397 struct tcphdr *tcp __unused)
399 struct arprequest *arpreply;
400 if (ptype != ETH_P_ARP)
402 if (nic.packetlen < ETH_HLEN + sizeof(struct arprequest))
404 arpreply = (struct arprequest *)&nic.packet[ETH_HLEN];
406 if (arpreply->opcode != htons(ARP_REPLY))
408 if (memcmp(arpreply->sipaddr, ptr, sizeof(in_addr)) != 0)
410 memcpy(arptable[ival].node, arpreply->shwaddr, ETH_ALEN);
414 int ip_transmit(int len, const void *buf)
416 unsigned long destip;
418 struct arprequest arpreq;
422 ip = (struct iphdr *)buf;
423 destip = ip->dest.s_addr;
424 if (destip == IP_BROADCAST) {
425 eth_transmit(broadcast, ETH_P_IP, len, buf);
426 #ifdef MULTICAST_LEVEL1
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);
440 if (((destip & netmask) !=
441 (arptable[ARP_CLIENT].ipaddr.s_addr & netmask)) &&
442 arptable[ARP_GATEWAY].ipaddr.s_addr)
443 destip = arptable[ARP_GATEWAY].ipaddr.s_addr;
444 for(arpentry = 0; arpentry<MAX_ARP; arpentry++)
445 if (arptable[arpentry].ipaddr.s_addr == destip) break;
446 if (arpentry == MAX_ARP) {
447 printf("%@ is not in my arp table!\n", destip);
450 for (i = 0; i < ETH_ALEN; i++)
451 if (arptable[arpentry].node[i])
453 if (i == ETH_ALEN) { /* Need to do arp request */
454 arpreq.hwtype = htons(1);
455 arpreq.protocol = htons(IP);
456 arpreq.hwlen = ETH_ALEN;
458 arpreq.opcode = htons(ARP_REQUEST);
459 memcpy(arpreq.shwaddr, arptable[ARP_CLIENT].node, ETH_ALEN);
460 memcpy(arpreq.sipaddr, &arptable[ARP_CLIENT].ipaddr, sizeof(in_addr));
461 memset(arpreq.thwaddr, 0, ETH_ALEN);
462 memcpy(arpreq.tipaddr, &destip, sizeof(in_addr));
463 for (retry = 1; retry <= MAX_ARP_RETRIES; retry++) {
465 eth_transmit(broadcast, ETH_P_ARP, sizeof(arpreq),
467 timeout = rfc2131_sleep_interval(TIMEOUT, retry);
468 if (await_reply(await_arp, arpentry,
469 arpreq.tipaddr, timeout)) goto xmit;
474 eth_transmit(arptable[arpentry].node, ETH_P_IP, len, buf);
479 void build_ip_hdr(unsigned long destip, int ttl, int protocol, int option_len,
480 int len, const void *buf)
483 ip = (struct iphdr *)buf;
484 ip->verhdrlen = 0x45;
485 ip->verhdrlen += (option_len/4);
487 ip->len = htons(len);
489 ip->frags = 0; /* Should we set don't fragment? */
491 ip->protocol = protocol;
493 ip->src.s_addr = arptable[ARP_CLIENT].ipaddr.s_addr;
494 ip->dest.s_addr = destip;
495 ip->chksum = ipchksum(buf, sizeof(struct iphdr) + option_len);
498 void build_udp_hdr(unsigned long destip,
499 unsigned int srcsock, unsigned int destsock, int ttl,
500 int len, const void *buf)
504 ip = (struct iphdr *)buf;
505 build_ip_hdr(destip, ttl, IP_UDP, 0, len, buf);
506 udp = (struct udphdr *)((char *)buf + sizeof(struct iphdr));
507 udp->src = htons(srcsock);
508 udp->dest = htons(destsock);
509 udp->len = htons(len - sizeof(struct iphdr));
511 if ((udp->chksum = tcpudpchksum(ip)) == 0)
512 udp->chksum = 0xffff;
515 #ifdef DOWNLOAD_PROTO_HTTP
516 void build_tcp_hdr(unsigned long destip, unsigned int srcsock,
517 unsigned int destsock, long send_seq, long recv_seq,
518 int window, int flags, int ttl, int len, const void *buf)
522 ip = (struct iphdr *)buf;
523 build_ip_hdr(destip, ttl, IP_TCP, 0, len, buf);
524 tcp = (struct tcphdr *)(ip + 1);
525 tcp->src = htons(srcsock);
526 tcp->dst = htons(destsock);
527 tcp->seq = htonl(send_seq);
528 tcp->ack = htonl(recv_seq);
529 tcp->ctrl = htons(flags + (5 << 12)); /* No TCP options */
530 tcp->window = htons(window);
532 if ((tcp->chksum = tcpudpchksum(ip)) == 0)
533 tcp->chksum = 0xffff;
538 /**************************************************************************
539 UDP_TRANSMIT - Send an UDP datagram
540 **************************************************************************/
541 int udp_transmit(unsigned long destip, unsigned int srcsock,
542 unsigned int destsock, int len, const void *buf)
544 build_udp_hdr(destip, srcsock, destsock, 60, len, buf);
545 return ip_transmit(len, buf);
548 /**************************************************************************
549 TCP_TRANSMIT - Send a TCP packet
550 **************************************************************************/
551 #ifdef DOWNLOAD_PROTO_HTTP
552 int tcp_transmit(unsigned long destip, unsigned int srcsock,
553 unsigned int destsock, long send_seq, long recv_seq,
554 int window, int flags, int len, const void *buf)
556 build_tcp_hdr(destip, srcsock, destsock, send_seq, recv_seq,
557 window, flags, 60, len, buf);
558 return ip_transmit(len, buf);
561 int tcp_reset(struct iphdr *ip) {
562 struct tcphdr *tcp = (struct tcphdr *)(ip + 1);
563 char buf[sizeof(struct iphdr) + sizeof(struct tcphdr)];
565 if (!(tcp->ctrl & htons(RST))) {
566 long seq = ntohl(tcp->seq) + ntohs(ip->len) -
567 sizeof(struct iphdr) -
568 ((ntohs(tcp->ctrl) >> 10) & 0x3C);
569 if (tcp->ctrl & htons(SYN|FIN))
571 return tcp_transmit(ntohl(ip->src.s_addr),
572 ntohs(tcp->dst), ntohs(tcp->src),
573 tcp->ctrl&htons(ACK) ? ntohl(tcp->ack) : 0,
574 seq, TCP_MAX_WINDOW, RST, sizeof(buf), buf);
580 /**************************************************************************
581 QDRAIN - clear the nic's receive queue
582 **************************************************************************/
583 static int await_qdrain(int ival __unused, void *ptr __unused,
584 unsigned short ptype __unused,
585 struct iphdr *ip __unused, struct udphdr *udp __unused,
586 struct tcphdr *tcp __unused)
593 /* Clear out the Rx queue first. It contains nothing of interest,
594 * except possibly ARP requests from the DHCP/TFTP server. We use
595 * polling throughout Etherboot, so some time may have passed since we
596 * last polled the receive queue, which may now be filled with
597 * broadcast packets. This will cause the reply to the packets we are
598 * about to send to be lost immediately. Not very clever. */
599 await_reply(await_qdrain, 0, NULL, 0);
602 #ifdef DOWNLOAD_PROTO_TFTP
603 /**************************************************************************
604 TFTP - Download extended BOOTP data, or kernel image
605 **************************************************************************/
606 static int await_tftp(int ival, void *ptr __unused,
607 unsigned short ptype __unused, struct iphdr *ip, struct udphdr *udp,
608 struct tcphdr *tcp __unused)
613 if (arptable[ARP_CLIENT].ipaddr.s_addr != ip->dest.s_addr)
615 if (ntohs(udp->dest) != ival)
620 int tftp ( const char *name,
621 int (*fnc)(unsigned char *, unsigned int, unsigned int, int) )
623 struct tftpreq_info_t request_data =
624 { name, TFTP_PORT, TFTP_MAX_PACKET };
625 struct tftpreq_info_t *request = &request_data;
626 struct tftpblk_info_t block;
629 while ( tftp_block ( request, &block ) ) {
630 request = NULL; /* Send request only once */
631 rc = fnc ( block.data, block.block, block.len, block.eof );
632 if ( rc <= 0 ) return (rc);
634 /* fnc should not have returned */
635 printf ( "TFTP download complete, but\n" );
642 int tftp_block ( struct tftpreq_info_t *request, struct tftpblk_info_t *block )
644 static unsigned short lport = 2000; /* local port */
645 static unsigned short rport = TFTP_PORT; /* remote port */
646 struct tftp_t *rcvd = NULL;
647 static struct tftpreq_t xmit;
648 static unsigned short xmitlen = 0;
649 static unsigned short blockidx = 0; /* Last block received */
650 static unsigned short retry = 0; /* Retry attempts on last block */
651 static int blksize = 0;
652 unsigned short recvlen = 0;
654 /* If this is a new request (i.e. if name is set), fill in
655 * transmit block with RRQ and send it.
658 rx_qdrain(); /* Flush receive queue */
659 xmit.opcode = htons(TFTP_RRQ);
660 xmitlen = (void*)&xmit.u.rrq - (void*)&xmit +
661 sprintf((char*)xmit.u.rrq, "%s%coctet%cblksize%c%d",
662 request->name, 0, 0, 0, request->blksize)
663 + 1; /* null terminator */
664 blockidx = 0; /* Reset counters */
666 blksize = TFTP_DEFAULTSIZE_PACKET;
667 lport++; /* Use new local port */
668 rport = request->port;
669 if ( !udp_transmit(arptable[ARP_SERVER].ipaddr.s_addr, lport,
670 rport, xmitlen, &xmit) )
673 /* Exit if no transfer in progress */
674 if ( !blksize ) return (0);
675 /* Loop to wait until we get a packet we're interested in */
676 block->data = NULL; /* Used as flag */
677 while ( block->data == NULL ) {
678 long timeout = rfc2131_sleep_interval ( blockidx ? TFTP_REXMT :
680 if ( !await_reply(await_tftp, lport, NULL, timeout) ) {
681 /* No packet received */
682 if ( retry++ > MAX_TFTP_RETRIES ) break;
683 /* Retransmit last packet */
684 if ( !blockidx ) lport++; /* New lport if new RRQ */
685 if ( !udp_transmit(arptable[ARP_SERVER].ipaddr.s_addr,
686 lport, rport, xmitlen, &xmit) )
688 continue; /* Back to waiting for packet */
690 /* Packet has been received */
691 rcvd = (struct tftp_t *)&nic.packet[ETH_HLEN];
692 recvlen = ntohs(rcvd->udp.len) - sizeof(struct udphdr)
693 - sizeof(rcvd->opcode);
694 rport = ntohs(rcvd->udp.src);
695 retry = 0; /* Reset retry counter */
696 switch ( htons(rcvd->opcode) ) {
698 printf ( "TFTP error %d (%s)\n",
699 ntohs(rcvd->u.err.errcode),
700 rcvd->u.err.errmsg );
701 return (0); /* abort */
704 const char *p = rcvd->u.oack.data;
705 const char *e = p + recvlen - 10; /* "blksize\0\d\0" */
707 *((char*)(p+recvlen-1)) = '\0'; /* Force final 0 */
708 if ( blockidx || !request ) break; /* Too late */
709 if ( recvlen <= TFTP_MAX_PACKET ) /* sanity */ {
710 /* Check for blksize option honoured */
712 if ( strcasecmp("blksize",p) == 0 &&
714 blksize = strtoul(p+8,&p,10);
720 if ( blksize < TFTP_DEFAULTSIZE_PACKET || blksize > request->blksize ) {
721 /* Incorrect blksize - error and abort */
722 xmit.opcode = htons(TFTP_ERROR);
723 xmit.u.err.errcode = 8;
724 xmitlen = (void*)&xmit.u.err.errmsg
726 + sprintf((char*)xmit.u.err.errmsg,
730 arptable[ARP_SERVER].ipaddr.s_addr,
731 lport, rport, xmitlen, &xmit);
736 if ( ntohs(rcvd->u.data.block) != ( blockidx + 1 ) )
737 break; /* Re-ACK last block sent */
738 if ( recvlen > ( blksize+sizeof(rcvd->u.data.block) ) )
739 break; /* Too large; ignore */
740 block->data = rcvd->u.data.download;
741 block->block = ++blockidx;
742 block->len = recvlen - sizeof(rcvd->u.data.block);
743 block->eof = ( (unsigned short)block->len < blksize );
744 /* If EOF, zero blksize to indicate transfer done */
745 if ( block->eof ) blksize = 0;
747 default: break; /* Do nothing */
750 xmit.opcode = htons(TFTP_ACK);
751 xmit.u.ack.block = htons(blockidx);
752 xmitlen = TFTP_MIN_PACKET;
753 udp_transmit ( arptable[ARP_SERVER].ipaddr.s_addr,
754 lport, rport, xmitlen, &xmit );
756 return ( block->data ? 1 : 0 );
758 #endif /* DOWNLOAD_PROTO_TFTP */
760 #ifdef RARP_NOT_BOOTP
761 /**************************************************************************
762 RARP - Get my IP address and load information
763 **************************************************************************/
764 static int await_rarp(int ival, void *ptr,
765 unsigned short ptype, struct iphdr *ip, struct udphdr *udp,
766 struct tcphdr *tcp __unused)
768 struct arprequest *arpreply;
769 if (ptype != ETH_P_RARP)
771 if (nic.packetlen < ETH_HLEN + sizeof(struct arprequest))
773 arpreply = (struct arprequest *)&nic.packet[ETH_HLEN];
774 if (arpreply->opcode != htons(RARP_REPLY))
776 if ((arpreply->opcode == htons(RARP_REPLY)) &&
777 (memcmp(arpreply->thwaddr, ptr, ETH_ALEN) == 0)) {
778 memcpy(arptable[ARP_SERVER].node, arpreply->shwaddr, ETH_ALEN);
779 memcpy(&arptable[ARP_SERVER].ipaddr, arpreply->sipaddr, sizeof(in_addr));
780 memcpy(&arptable[ARP_CLIENT].ipaddr, arpreply->tipaddr, sizeof(in_addr));
786 static int rarp(void)
790 /* arp and rarp requests share the same packet structure. */
791 struct arprequest rarpreq;
793 memset(&rarpreq, 0, sizeof(rarpreq));
795 rarpreq.hwtype = htons(1);
796 rarpreq.protocol = htons(IP);
797 rarpreq.hwlen = ETH_ALEN;
798 rarpreq.protolen = 4;
799 rarpreq.opcode = htons(RARP_REQUEST);
800 memcpy(&rarpreq.shwaddr, arptable[ARP_CLIENT].node, ETH_ALEN);
801 /* sipaddr is already zeroed out */
802 memcpy(&rarpreq.thwaddr, arptable[ARP_CLIENT].node, ETH_ALEN);
803 /* tipaddr is already zeroed out */
805 for (retry = 0; retry < MAX_ARP_RETRIES; ++retry) {
807 eth_transmit(broadcast, ETH_P_RARP, sizeof(rarpreq), &rarpreq);
809 timeout = rfc2131_sleep_interval(TIMEOUT, retry);
810 if (await_reply(await_rarp, 0, rarpreq.shwaddr, timeout))
814 if (retry < MAX_ARP_RETRIES) {
815 (void)sprintf(KERNEL_BUF, DEFAULT_KERNELPATH, arptable[ARP_CLIENT].ipaddr);
824 /**************************************************************************
825 BOOTP - Get my IP address and load information
826 **************************************************************************/
827 static int await_bootp(int ival __unused, void *ptr __unused,
828 unsigned short ptype __unused, struct iphdr *ip __unused,
829 struct udphdr *udp, struct tcphdr *tcp __unused)
831 struct bootp_t *bootpreply;
835 bootpreply = (struct bootp_t *)&nic.packet[ETH_HLEN +
836 sizeof(struct iphdr) + sizeof(struct udphdr)];
837 if (nic.packetlen < ETH_HLEN + sizeof(struct iphdr) +
838 sizeof(struct udphdr) +
839 #ifdef NO_DHCP_SUPPORT
840 sizeof(struct bootp_t)
842 sizeof(struct bootp_t) - DHCP_OPT_LEN
843 #endif /* NO_DHCP_SUPPORT */
847 if (udp->dest != htons(BOOTP_CLIENT))
849 if (bootpreply->bp_op != BOOTP_REPLY)
851 if (bootpreply->bp_xid != xid)
853 if (memcmp(&bootpreply->bp_siaddr, &zeroIP, sizeof(in_addr)) == 0)
855 if ((memcmp(broadcast, bootpreply->bp_hwaddr, ETH_ALEN) != 0) &&
856 (memcmp(arptable[ARP_CLIENT].node, bootpreply->bp_hwaddr, ETH_ALEN) != 0)) {
859 if ( bootpreply->bp_siaddr.s_addr ) {
860 arptable[ARP_SERVER].ipaddr.s_addr = bootpreply->bp_siaddr.s_addr;
861 memset(arptable[ARP_SERVER].node, 0, ETH_ALEN); /* Kill arp */
863 if ( bootpreply->bp_giaddr.s_addr ) {
864 arptable[ARP_GATEWAY].ipaddr.s_addr = bootpreply->bp_giaddr.s_addr;
865 memset(arptable[ARP_GATEWAY].node, 0, ETH_ALEN); /* Kill arp */
867 if (bootpreply->bp_yiaddr.s_addr) {
868 /* Offer with an IP address */
869 arptable[ARP_CLIENT].ipaddr.s_addr = bootpreply->bp_yiaddr.s_addr;
870 #ifndef NO_DHCP_SUPPORT
871 dhcp_addr.s_addr = bootpreply->bp_yiaddr.s_addr;
872 #endif /* NO_DHCP_SUPPORT */
873 netmask = default_netmask();
874 /* bootpreply->bp_file will be copied to KERNEL_BUF in the memcpy */
875 memcpy((char *)BOOTP_DATA_ADDR, (char *)bootpreply, sizeof(struct bootpd_t));
876 decode_rfc1533(BOOTP_DATA_ADDR->bootp_reply.bp_vend, 0,
877 #ifdef NO_DHCP_SUPPORT
878 BOOTP_VENDOR_LEN + MAX_BOOTP_EXTLEN,
880 DHCP_OPT_LEN + MAX_BOOTP_EXTLEN,
881 #endif /* NO_DHCP_SUPPORT */
885 /* Offer without an IP address - use as ProxyDHCP server */
886 arptable[ARP_PROXYDHCP].ipaddr.s_addr = bootpreply->bp_siaddr.s_addr;
887 memset(arptable[ARP_PROXYDHCP].node, 0, ETH_ALEN); /* Kill arp */
888 /* Grab only the bootfile name from a ProxyDHCP packet */
889 memcpy(KERNEL_BUF, bootpreply->bp_file, sizeof(KERNEL_BUF));
890 #endif /* PXE_EXPORT */
892 #ifdef REQUIRE_VCI_ETHERBOOT
899 static int bootp(void)
902 #ifndef NO_DHCP_SUPPORT
904 #endif /* NO_DHCP_SUPPORT */
906 unsigned long starttime;
907 unsigned char *bp_vend;
909 #ifndef NO_DHCP_SUPPORT
910 * ( ( struct dhcp_dev_id * ) &dhcp_machine_info[4] ) = nic.dhcp_dev_id;
911 #endif /* NO_DHCP_SUPPORT */
912 memset(&ip, 0, sizeof(struct bootpip_t));
913 ip.bp.bp_op = BOOTP_REQUEST;
915 ip.bp.bp_hlen = ETH_ALEN;
916 starttime = currticks();
917 /* Use lower 32 bits of node address, more likely to be
918 distinct than the time since booting */
919 memcpy(&xid, &arptable[ARP_CLIENT].node[2], sizeof(xid));
920 ip.bp.bp_xid = xid += htonl(starttime);
921 memcpy(ip.bp.bp_hwaddr, arptable[ARP_CLIENT].node, ETH_ALEN);
922 #ifdef NO_DHCP_SUPPORT
923 memcpy(ip.bp.bp_vend, rfc1533_cookie, 5); /* request RFC-style options */
925 memcpy(ip.bp.bp_vend, rfc1533_cookie, sizeof rfc1533_cookie); /* request RFC-style options */
926 memcpy(ip.bp.bp_vend + sizeof rfc1533_cookie, dhcpdiscover, sizeof dhcpdiscover);
927 /* Append machine_info to end, in encapsulated option */
928 bp_vend = ip.bp.bp_vend + sizeof rfc1533_cookie + sizeof dhcpdiscover;
929 memcpy(bp_vend, dhcp_machine_info, DHCP_MACHINE_INFO_SIZE);
930 bp_vend += DHCP_MACHINE_INFO_SIZE;
931 *bp_vend++ = RFC1533_END;
932 #endif /* NO_DHCP_SUPPORT */
934 for (retry = 0; retry < MAX_BOOTP_RETRIES; ) {
935 uint8_t my_hwaddr[ETH_ALEN];
936 unsigned long stop_time;
941 /* Kill arptable to avoid keeping stale entries */
942 memcpy ( my_hwaddr, arptable[ARP_CLIENT].node, ETH_ALEN );
943 memset ( arptable, 0, sizeof(arptable) );
944 memcpy ( arptable[ARP_CLIENT].node, my_hwaddr, ETH_ALEN );
946 udp_transmit(IP_BROADCAST, BOOTP_CLIENT, BOOTP_SERVER,
947 sizeof(struct bootpip_t), &ip);
948 remaining_time = rfc2131_sleep_interval(BOOTP_TIMEOUT, retry++);
949 stop_time = currticks() + remaining_time;
950 #ifdef NO_DHCP_SUPPORT
951 if (await_reply(await_bootp, 0, NULL, timeout))
954 while ( remaining_time > 0 ) {
955 if (await_reply(await_bootp, 0, NULL, remaining_time)){
957 remaining_time = stop_time - currticks();
959 if ( ! arptable[ARP_CLIENT].ipaddr.s_addr ) {
960 printf("No IP address\n");
963 /* If not a DHCPOFFER then must be just a BOOTP reply,
964 * be backward compatible with BOOTP then */
965 if (dhcp_reply != DHCPOFFER)
968 /* Construct the DHCPREQUEST packet */
969 memcpy(ip.bp.bp_vend, rfc1533_cookie, sizeof rfc1533_cookie);
970 memcpy(ip.bp.bp_vend + sizeof rfc1533_cookie, dhcprequest, sizeof dhcprequest);
971 /* Beware: the magic numbers 9 and 15 depend on
972 the layout of dhcprequest */
973 memcpy(&ip.bp.bp_vend[9], &dhcp_server, sizeof(in_addr));
974 memcpy(&ip.bp.bp_vend[15], &dhcp_addr, sizeof(in_addr));
975 bp_vend = ip.bp.bp_vend + sizeof rfc1533_cookie + sizeof dhcprequest;
976 /* Append machine_info to end, in encapsulated option */
977 memcpy(bp_vend, dhcp_machine_info, DHCP_MACHINE_INFO_SIZE);
978 bp_vend += DHCP_MACHINE_INFO_SIZE;
979 *bp_vend++ = RFC1533_END;
980 for (reqretry = 0; reqretry < MAX_BOOTP_RETRIES; ) {
981 unsigned long timeout;
983 udp_transmit(IP_BROADCAST, BOOTP_CLIENT, BOOTP_SERVER,
984 sizeof(struct bootpip_t), &ip);
986 timeout = rfc2131_sleep_interval(TIMEOUT, reqretry++);
987 if (!await_reply(await_bootp, 0, NULL, timeout))
989 if (dhcp_reply != DHCPACK)
993 if ( arptable[ARP_PROXYDHCP].ipaddr.s_addr ) {
994 /* Construct the ProxyDHCPREQUEST packet */
995 memcpy(ip.bp.bp_vend, rfc1533_cookie, sizeof rfc1533_cookie);
996 memcpy(ip.bp.bp_vend + sizeof rfc1533_cookie, proxydhcprequest, sizeof proxydhcprequest);
997 for (reqretry = 0; reqretry < MAX_BOOTP_RETRIES; ) {
998 printf ( "\nSending ProxyDHCP request to %@...", arptable[ARP_PROXYDHCP].ipaddr.s_addr);
999 udp_transmit(arptable[ARP_PROXYDHCP].ipaddr.s_addr, BOOTP_CLIENT, PROXYDHCP_SERVER,
1000 sizeof(struct bootpip_t), &ip);
1001 timeout = rfc2131_sleep_interval(TIMEOUT, reqretry++);
1002 if (await_reply(await_bootp, 0, NULL, timeout)) {
1007 #endif /* PXE_EXPORT */
1010 #endif /* NO_DHCP_SUPPORT */
1011 ip.bp.bp_secs = htons((currticks()-starttime)/TICKS_PER_SEC);
1015 #endif /* RARP_NOT_BOOTP */
1017 static uint16_t tcpudpchksum(struct iphdr *ip)
1019 struct udp_pseudo_hdr pseudo;
1022 /* Compute the pseudo header */
1023 pseudo.src.s_addr = ip->src.s_addr;
1024 pseudo.dest.s_addr = ip->dest.s_addr;
1026 pseudo.protocol = ip->protocol;
1027 pseudo.len = htons(ntohs(ip->len) - sizeof(struct iphdr));
1029 /* Sum the pseudo header */
1030 checksum = ipchksum(&pseudo, 12);
1032 /* Sum the rest of the tcp/udp packet */
1033 checksum = add_ipchksums(12, checksum, ipchksum(ip + 1,
1034 ntohs(ip->len) - sizeof(struct iphdr)));
1038 #ifdef MULTICAST_LEVEL2
1039 static void send_igmp_reports(unsigned long now)
1042 for(i = 0; i < MAX_IGMP; i++) {
1043 if (igmptable[i].time && (now >= igmptable[i].time)) {
1044 struct igmp_ip_t igmp;
1045 igmp.router_alert[0] = 0x94;
1046 igmp.router_alert[1] = 0x04;
1047 igmp.router_alert[2] = 0;
1048 igmp.router_alert[3] = 0;
1049 build_ip_hdr(igmptable[i].group.s_addr,
1050 1, IP_IGMP, sizeof(igmp.router_alert), sizeof(igmp), &igmp);
1051 igmp.igmp.type = IGMPv2_REPORT;
1053 (now < last_igmpv1 + IGMPv1_ROUTER_PRESENT_TIMEOUT)) {
1054 igmp.igmp.type = IGMPv1_REPORT;
1056 igmp.igmp.response_time = 0;
1057 igmp.igmp.chksum = 0;
1058 igmp.igmp.group.s_addr = igmptable[i].group.s_addr;
1059 igmp.igmp.chksum = ipchksum(&igmp.igmp, sizeof(igmp.igmp));
1060 ip_transmit(sizeof(igmp), &igmp);
1062 printf("Sent IGMP report to: %@\n", igmp.igmp.group.s_addr);
1064 /* Don't send another igmp report until asked */
1065 igmptable[i].time = 0;
1070 static void process_igmp(struct iphdr *ip, unsigned long now)
1075 if (!ip || (ip->protocol == IP_IGMP) ||
1076 (nic.packetlen < sizeof(struct iphdr) + sizeof(struct igmp))) {
1079 iplen = (ip->verhdrlen & 0xf)*4;
1080 igmp = (struct igmp *)&nic.packet[sizeof(struct iphdr)];
1081 if (ipchksum(igmp, ntohs(ip->len) - iplen) != 0)
1083 if ((igmp->type == IGMP_QUERY) &&
1084 (ip->dest.s_addr == htonl(GROUP_ALL_HOSTS))) {
1085 unsigned long interval = IGMP_INTERVAL;
1086 if (igmp->response_time == 0) {
1089 interval = (igmp->response_time * TICKS_PER_SEC)/10;
1093 printf("Received IGMP query for: %@\n", igmp->group.s_addr);
1095 for(i = 0; i < MAX_IGMP; i++) {
1096 uint32_t group = igmptable[i].group.s_addr;
1097 if ((group == 0) || (group == igmp->group.s_addr)) {
1099 time = currticks() + rfc1112_sleep_interval(interval, 0);
1100 if (time < igmptable[i].time) {
1101 igmptable[i].time = time;
1106 if (((igmp->type == IGMPv1_REPORT) || (igmp->type == IGMPv2_REPORT)) &&
1107 (ip->dest.s_addr == igmp->group.s_addr)) {
1109 printf("Received IGMP report for: %@\n", igmp->group.s_addr);
1111 for(i = 0; i < MAX_IGMP; i++) {
1112 if ((igmptable[i].group.s_addr == igmp->group.s_addr) &&
1113 igmptable[i].time != 0) {
1114 igmptable[i].time = 0;
1120 void leave_group(int slot)
1122 /* Be very stupid and always send a leave group message if
1123 * I have subscribed. Imperfect but it is standards
1124 * compliant, easy and reliable to implement.
1126 * The optimal group leave method is to only send leave when,
1127 * we were the last host to respond to a query on this group,
1128 * and igmpv1 compatibility is not enabled.
1130 if (igmptable[slot].group.s_addr) {
1131 struct igmp_ip_t igmp;
1132 igmp.router_alert[0] = 0x94;
1133 igmp.router_alert[1] = 0x04;
1134 igmp.router_alert[2] = 0;
1135 igmp.router_alert[3] = 0;
1136 build_ip_hdr(htonl(GROUP_ALL_HOSTS),
1137 1, IP_IGMP, sizeof(igmp.router_alert), sizeof(igmp), &igmp);
1138 igmp.igmp.type = IGMP_LEAVE;
1139 igmp.igmp.response_time = 0;
1140 igmp.igmp.chksum = 0;
1141 igmp.igmp.group.s_addr = igmptable[slot].group.s_addr;
1142 igmp.igmp.chksum = ipchksum(&igmp.igmp, sizeof(igmp));
1143 ip_transmit(sizeof(igmp), &igmp);
1145 printf("Sent IGMP leave for: %@\n", igmp.igmp.group.s_addr);
1148 memset(&igmptable[slot], 0, sizeof(igmptable[0]));
1151 void join_group(int slot, unsigned long group)
1153 /* I have already joined */
1154 if (igmptable[slot].group.s_addr == group)
1156 if (igmptable[slot].group.s_addr) {
1159 /* Only join a group if we are given a multicast ip, this way
1160 * code can be given a non-multicast (broadcast or unicast ip)
1163 if ((group & htonl(MULTICAST_MASK)) == htonl(MULTICAST_NETWORK)) {
1164 igmptable[slot].group.s_addr = group;
1165 igmptable[slot].time = currticks();
1169 #define send_igmp_reports(now) do {} while(0)
1170 #define process_igmp(ip, now) do {} while(0)
1173 #include "proto_eth_slow.c"
1175 /**************************************************************************
1176 TCP - Simple-minded TCP stack. Can only send data once and then
1177 receive the response. The algorithm for computing window
1178 sizes and delaying ack's is currently broken, and thus
1179 disabled. Performance would probably improve a little, if
1180 this gets fixed. FIXME
1181 **************************************************************************/
1182 #ifdef DOWNLOAD_PROTO_HTTP
1183 static int await_tcp(int ival, void *ptr, unsigned short ptype __unused,
1184 struct iphdr *ip, struct udphdr *udp __unused,
1190 if (arptable[ARP_CLIENT].ipaddr.s_addr != ip->dest.s_addr)
1192 if (ntohs(tcp->dst) != ival) {
1196 *(void **)ptr = tcp;
1200 int tcp_transaction(unsigned long destip, unsigned int destsock, void *ptr,
1201 int (*send)(int len, void *buf, void *ptr),
1202 int (*recv)(int len, const void *buf, void *ptr)) {
1203 static uint16_t srcsock = 0;
1205 long send_seq = currticks();
1212 char buf[128]; /* Small outgoing buffer */
1215 int window = 3*TCP_MIN_WINDOW;
1220 long rto = TCP_INITIAL_TIMEOUT;
1221 int retry = TCP_MAX_TIMEOUT/TCP_INITIAL_TIMEOUT;
1222 enum { CLOSED, SYN_RCVD, ESTABLISHED,
1223 FIN_WAIT_1, FIN_WAIT_2 } state = CLOSED;
1226 srcsock = currticks();
1228 if (++srcsock < 1024)
1231 await_reply(await_qdrain, 0, NULL, 0);
1235 last_ack = recv_seq;
1236 if (!tcp_transmit(destip, srcsock, destsock, send_seq,
1237 recv_seq, window, ctrl,
1238 sizeof(struct iphdr) + sizeof(struct tcphdr)+
1242 last_sent = currticks();
1245 if (!await_reply(await_tcp, srcsock, &tcp,
1246 (state == ESTABLISHED && !can_send)
1247 ? TCP_MAX_TIMEOUT : rto)) {
1248 if (state == ESTABLISHED) {
1256 if (state == FIN_WAIT_1 || state == FIN_WAIT_2)
1261 if (state == SYN_RCVD) {
1262 tcp_transmit(destip, srcsock, destsock,
1263 send_seq, 0, window, RST,
1264 sizeof(struct iphdr) +
1265 sizeof(struct tcphdr), buf);
1273 retry = TCP_MAX_RETRY;
1275 if (tcp->ctrl & htons(ACK) ) {
1277 int syn_ack, consumed;
1279 if (state == FIN_WAIT_1 || state == FIN_WAIT_2) {
1284 syn_ack = state == CLOSED || state == SYN_RCVD;
1285 consumed = ntohl(tcp->ack) - send_seq - syn_ack;
1286 if (consumed < 0 || consumed > can_send) {
1287 tcp_reset((struct iphdr *)&nic.packet[ETH_HLEN]);
1291 rtt = currticks() - last_sent;
1292 srtt = !srtt ? rtt : (srtt*4 + rtt)/5;
1293 rto = srtt + srtt/2;
1294 if (rto < TCP_MIN_TIMEOUT)
1295 rto = TCP_MIN_TIMEOUT;
1296 else if (rto > TCP_MAX_TIMEOUT)
1297 rto = TCP_MAX_TIMEOUT;
1299 can_send -= consumed;
1300 send_seq += consumed + syn_ack;
1301 data = buf + sizeof(struct iphdr) + sizeof(struct tcphdr);
1303 memmove(data, data + consumed, can_send);
1308 more_data = buf + sizeof(buf) - data;
1309 if (more_data > 0) {
1310 more_data = send(more_data, data, ptr);
1311 can_send += more_data;
1313 sent_all = !more_data;
1315 if (state == SYN_RCVD) {
1316 state = ESTABLISHED;
1320 if (tcp->ctrl & htons(RST))
1322 } else if (tcp->ctrl & htons(RST)) {
1323 if (state == CLOSED)
1329 ip = (struct iphdr *)&nic.packet[ETH_HLEN];
1330 header_size = sizeof(struct iphdr) + ((ntohs(tcp->ctrl)>>10)&0x3C);
1331 payload = ntohs(ip->len) - header_size;
1332 if (payload > 0 && state == ESTABLISHED) {
1333 int old_bytes = recv_seq - (long)ntohl(tcp->seq);
1334 if (old_bytes >= 0 && payload - old_bytes > 0) {
1335 recv_seq += payload - old_bytes;
1336 if (state != FIN_WAIT_1 && state != FIN_WAIT_2 &&
1337 !recv(payload - old_bytes,
1338 &nic.packet[ETH_HLEN+header_size+old_bytes],
1342 if ((state == ESTABLISHED || state == SYN_RCVD) &&
1343 !(tcp->ctrl & htons(FIN))) {
1344 int in_window = window - 2*TCP_MIN_WINDOW >
1345 recv_seq - last_ack;
1346 ctrl = can_send ? PSH|ACK : ACK;
1347 if (!can_send && in_window) {
1348 /* Window scaling is broken right now, just fall back to acknowledging every */
1349 /* packet immediately and unconditionally. FIXME */ /***/
1350 /* if (await_reply(await_tcp, srcsock,
1357 window += TCP_MIN_WINDOW;
1358 if (window > TCP_MAX_WINDOW)
1359 window = TCP_MAX_WINDOW;
1364 /* saw old data again, must have lost packets */
1366 if (window < 2*TCP_MIN_WINDOW)
1367 window = 2*TCP_MIN_WINDOW;
1371 if (tcp->ctrl & htons(FIN)) {
1372 if (state == ESTABLISHED) {
1374 } else if (state == FIN_WAIT_1 || state == FIN_WAIT_2) {
1379 return (tcp_transmit(destip, srcsock, destsock,
1380 send_seq, recv_seq + 1, window, ctrl,
1381 sizeof(struct iphdr) +
1382 sizeof(struct tcphdr), buf) &&
1383 (state == ESTABLISHED ||
1384 state == FIN_WAIT_1 || state == FIN_WAIT_2) &&
1388 if (state == CLOSED) {
1389 if (tcp->ctrl & htons(SYN)) {
1390 recv_seq = ntohl(tcp->seq) + 1;
1391 if (!(tcp->ctrl & htons(ACK))) {
1396 state = ESTABLISHED;
1402 if (can_send || payload) {
1409 /**************************************************************************
1410 AWAIT_REPLY - Wait until we get a response for our request
1411 ************f**************************************************************/
1412 int await_reply(reply_t reply, int ival, void *ptr, long timeout)
1414 unsigned long time, now;
1419 unsigned short ptype;
1422 time = timeout + currticks();
1423 /* The timeout check is done below. The timeout is only checked if
1424 * there is no packet in the Rx queue. This assumes that eth_poll()
1425 * needs a negligible amount of time.
1429 send_eth_slow_reports(now);
1430 send_igmp_reports(now);
1431 result = eth_poll(1);
1433 /* We don't have anything */
1435 /* Check for abort key only if the Rx queue is empty -
1436 * as long as we have something to process, don't
1437 * assume that something failed. It is unlikely that
1438 * we have no processing time left between packets. */
1439 poll_interruptions();
1440 /* Do the timeout after at least a full queue walk. */
1441 if ((timeout == 0) || (currticks() > time)) {
1447 /* We have something! */
1449 /* Find the Ethernet packet type */
1450 if (nic.packetlen >= ETH_HLEN) {
1451 ptype = ((unsigned short) nic.packet[12]) << 8
1452 | ((unsigned short) nic.packet[13]);
1453 } else continue; /* what else could we do with it? */
1454 /* Verify an IP header */
1456 if ((ptype == ETH_P_IP) && (nic.packetlen >= ETH_HLEN + sizeof(struct iphdr))) {
1458 ip = (struct iphdr *)&nic.packet[ETH_HLEN];
1459 if ((ip->verhdrlen < 0x45) || (ip->verhdrlen > 0x4F))
1461 iplen = (ip->verhdrlen & 0xf) * 4;
1462 if (ipchksum(ip, iplen) != 0)
1464 if (ip->frags & htons(0x3FFF)) {
1465 static int warned_fragmentation = 0;
1466 if (!warned_fragmentation) {
1467 printf("ALERT: got a fragmented packet - reconfigure your server\n");
1468 warned_fragmentation = 1;
1472 if (ntohs(ip->len) > ETH_MAX_MTU)
1475 ipoptlen = iplen - sizeof(struct iphdr);
1477 /* Delete the ip options, to guarantee
1478 * good alignment, and make etherboot simpler.
1480 memmove(&nic.packet[ETH_HLEN + sizeof(struct iphdr)],
1481 &nic.packet[ETH_HLEN + iplen],
1482 nic.packetlen - ipoptlen);
1483 nic.packetlen -= ipoptlen;
1487 if (ip && (ip->protocol == IP_UDP) &&
1489 ETH_HLEN + sizeof(struct iphdr) + sizeof(struct udphdr))) {
1490 udp = (struct udphdr *)&nic.packet[ETH_HLEN + sizeof(struct iphdr)];
1492 /* Make certain we have a reasonable packet length */
1493 if (ntohs(udp->len) > (ntohs(ip->len) - iplen))
1496 if (udp->chksum && tcpudpchksum(ip)) {
1497 printf("UDP checksum error\n");
1502 #ifdef DOWNLOAD_PROTO_HTTP
1503 if (ip && (ip->protocol == IP_TCP) &&
1505 ETH_HLEN + sizeof(struct iphdr) + sizeof(struct tcphdr))){
1506 tcp = (struct tcphdr *)&nic.packet[ETH_HLEN +
1507 sizeof(struct iphdr)];
1508 /* Make certain we have a reasonable packet length */
1509 if (((ntohs(tcp->ctrl) >> 10) & 0x3C) >
1510 ntohs(ip->len) - (int)iplen)
1512 if (tcpudpchksum(ip)) {
1513 printf("TCP checksum error\n");
1519 result = reply(ival, ptr, ptype, ip, udp, tcp);
1524 /* If it isn't a packet the upper layer wants see if there is a default
1525 * action. This allows us reply to arp, igmp, and lacp queries.
1527 if ((ptype == ETH_P_ARP) &&
1528 (nic.packetlen >= ETH_HLEN + sizeof(struct arprequest))) {
1529 struct arprequest *arpreply;
1532 arpreply = (struct arprequest *)&nic.packet[ETH_HLEN];
1533 memcpy(&tmp, arpreply->tipaddr, sizeof(in_addr));
1534 if ((arpreply->opcode == htons(ARP_REQUEST)) &&
1535 (tmp == arptable[ARP_CLIENT].ipaddr.s_addr)) {
1536 arpreply->opcode = htons(ARP_REPLY);
1537 memcpy(arpreply->tipaddr, arpreply->sipaddr, sizeof(in_addr));
1538 memcpy(arpreply->thwaddr, arpreply->shwaddr, ETH_ALEN);
1539 memcpy(arpreply->sipaddr, &arptable[ARP_CLIENT].ipaddr, sizeof(in_addr));
1540 memcpy(arpreply->shwaddr, arptable[ARP_CLIENT].node, ETH_ALEN);
1541 eth_transmit(arpreply->thwaddr, ETH_P_ARP,
1542 sizeof(struct arprequest),
1545 memcpy(&tmp, arpreply->tipaddr, sizeof(in_addr));
1546 printf("Sent ARP reply to: %@\n",tmp);
1550 process_eth_slow(ptype, now);
1551 process_igmp(ip, now);
1556 #ifdef REQUIRE_VCI_ETHERBOOT
1557 /**************************************************************************
1558 FIND_VCI_ETHERBOOT - Looks for "Etherboot" in Vendor Encapsulated Identifiers
1559 On entry p points to byte count of VCI options
1560 **************************************************************************/
1561 static int find_vci_etherboot(unsigned char *p)
1563 unsigned char *end = p + 1 + *p;
1565 for (p++; p < end; ) {
1566 if (*p == RFC2132_VENDOR_CLASS_ID) {
1567 if (strncmp("Etherboot", p + 2, sizeof("Etherboot") - 1) == 0)
1569 } else if (*p == RFC1533_END)
1571 p += TAG_LEN(p) + 2;
1575 #endif /* REQUIRE_VCI_ETHERBOOT */
1577 /**************************************************************************
1578 DECODE_RFC1533 - Decodes RFC1533 header
1579 **************************************************************************/
1580 int decode_rfc1533(unsigned char *p, unsigned int block, unsigned int len, int eof)
1582 static unsigned char *extdata = NULL, *extend = NULL;
1583 unsigned char *extpath = NULL;
1584 unsigned char *endp;
1585 static unsigned char in_encapsulated_options = 0;
1588 /* Encapsulated option block */
1591 else if (block == 0) {
1592 #ifdef REQUIRE_VCI_ETHERBOOT
1595 end_of_rfc1533 = NULL;
1596 #ifdef IMAGE_FREEBSD
1597 /* yes this is a pain FreeBSD uses this for swap, however,
1598 there are cases when you don't want swap and then
1599 you want this set to get the extra features so lets
1600 just set if dealing with FreeBSD. I haven't run into
1601 any troubles with this but I have without it
1603 vendorext_isvalid = 1;
1604 #ifdef FREEBSD_KERNEL_ENV
1605 memcpy(freebsd_kernel_env, FREEBSD_KERNEL_ENV,
1606 sizeof(FREEBSD_KERNEL_ENV));
1607 /* FREEBSD_KERNEL_ENV had better be a string constant */
1609 freebsd_kernel_env[0]='\0';
1612 vendorext_isvalid = 0;
1614 if (memcmp(p, rfc1533_cookie, 4))
1615 return(0); /* no RFC 1533 header found */
1620 if (memcmp(p, rfc1533_cookie, 4))
1621 return(0); /* no RFC 1533 header found */
1624 if (extend + len <= (unsigned char *)&(BOOTP_DATA_ADDR->bootp_extension[MAX_BOOTP_EXTLEN])) {
1625 memcpy(extend, p, len);
1628 printf("Overflow in vendor data buffer! Aborting...\n");
1629 *extdata = RFC1533_END;
1632 p = extdata; endp = extend;
1637 unsigned char c = *p;
1638 if (c == RFC1533_PAD) {
1642 else if (c == RFC1533_END) {
1643 end_of_rfc1533 = endp = p;
1646 else if (NON_ENCAP_OPT c == RFC1533_NETMASK)
1647 memcpy(&netmask, p+2, sizeof(in_addr));
1648 else if (NON_ENCAP_OPT c == RFC1533_GATEWAY) {
1649 /* This is a little simplistic, but it will
1650 usually be sufficient.
1651 Take only the first entry */
1652 if (TAG_LEN(p) >= sizeof(in_addr))
1653 memcpy(&arptable[ARP_GATEWAY].ipaddr, p+2, sizeof(in_addr));
1655 else if (c == RFC1533_EXTENSIONPATH)
1657 #ifndef NO_DHCP_SUPPORT
1658 #ifdef REQUIRE_VCI_ETHERBOOT
1659 else if (NON_ENCAP_OPT c == RFC1533_VENDOR) {
1660 vci_etherboot = find_vci_etherboot(p+1);
1662 printf("vci_etherboot %d\n", vci_etherboot);
1665 #endif /* REQUIRE_VCI_ETHERBOOT */
1666 else if (NON_ENCAP_OPT c == RFC2132_MSG_TYPE)
1668 else if (NON_ENCAP_OPT c == RFC2132_SRV_ID)
1669 memcpy(&dhcp_server, p+2, sizeof(in_addr));
1670 #endif /* NO_DHCP_SUPPORT */
1671 else if (NON_ENCAP_OPT c == RFC1533_HOSTNAME) {
1673 hostnamelen = *(p + 1);
1675 else if (ENCAP_OPT c == RFC1533_VENDOR_MAGIC
1676 && TAG_LEN(p) >= 6 &&
1677 !memcmp(p+2,vendorext_magic,4) &&
1678 p[6] == RFC1533_VENDOR_MAJOR
1680 vendorext_isvalid++;
1681 else if (NON_ENCAP_OPT c == RFC1533_VENDOR_ETHERBOOT_ENCAP) {
1682 in_encapsulated_options = 1;
1683 decode_rfc1533(p+2, 0, TAG_LEN(p), -1);
1684 in_encapsulated_options = 0;
1686 #ifdef IMAGE_FREEBSD
1687 else if (NON_ENCAP_OPT c == RFC1533_VENDOR_HOWTO)
1688 freebsd_howto = ((p[2]*256+p[3])*256+p[4])*256+p[5];
1689 else if (NON_ENCAP_OPT c == RFC1533_VENDOR_KERNEL_ENV){
1690 if(*(p + 1) < sizeof(freebsd_kernel_env)){
1691 memcpy(freebsd_kernel_env,p+2,*(p+1));
1693 printf("Only support %ld bytes in Kernel Env\n",
1694 sizeof(freebsd_kernel_env));
1699 else if (NON_ENCAP_OPT c == RFC1533_DNS) {
1700 // TODO: Copy the DNS IP somewhere reasonable
1701 if (TAG_LEN(p) >= sizeof(in_addr))
1702 memcpy(&arptable[ARP_NAMESERVER].ipaddr, p+2, sizeof(in_addr));
1708 printf("Unknown RFC1533-tag ");
1709 for(q=p;q<p+2+TAG_LEN(p);q++)
1714 p += TAG_LEN(p) + 2;
1716 extdata = extend = endp;
1717 if (block <= 0 && extpath != NULL) {
1719 memcpy(fname, extpath+2, TAG_LEN(extpath));
1720 fname[(int)TAG_LEN(extpath)] = '\0';
1721 printf("Loading BOOTP-extension file: %s\n",fname);
1722 tftp(fname, decode_rfc1533);
1724 return 1; /* proceed with next block */
1728 /* FIXME double check TWO_SECOND_DIVISOR */
1729 #define TWO_SECOND_DIVISOR (RAND_MAX/TICKS_PER_SEC)
1730 /**************************************************************************
1731 RFC2131_SLEEP_INTERVAL - sleep for expotentially longer times (base << exp) +- 1 sec)
1732 **************************************************************************/
1733 long rfc2131_sleep_interval(long base, int exp)
1736 #ifdef BACKOFF_LIMIT
1737 if (exp > BACKOFF_LIMIT)
1738 exp = BACKOFF_LIMIT;
1740 tmo = (base << exp) + (TICKS_PER_SEC - (random()/TWO_SECOND_DIVISOR));
1744 #ifdef MULTICAST_LEVEL2
1745 /**************************************************************************
1746 RFC1112_SLEEP_INTERVAL - sleep for expotentially longer times, up to (base << exp)
1747 **************************************************************************/
1748 long rfc1112_sleep_interval(long base, int exp)
1750 unsigned long divisor, tmo;
1751 #ifdef BACKOFF_LIMIT
1752 if (exp > BACKOFF_LIMIT)
1753 exp = BACKOFF_LIMIT;
1755 divisor = RAND_MAX/(base << exp);
1756 tmo = random()/divisor;
1759 #endif /* MULTICAST_LEVEL_2 */