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_load_configuration ( struct nic *nic ) {
240 if ( ! nic->nic_op->connect ( nic ) ) {
241 printf ( "No connection to network\n" );
245 /* Find a server to get BOOTP reply from */
246 #ifdef RARP_NOT_BOOTP
247 printf("Searching for server (RARP)...");
249 #ifndef NO_DHCP_SUPPORT
250 printf("Searching for server (DHCP)...");
252 printf("Searching for server (BOOTP)...");
256 #ifdef RARP_NOT_BOOTP
257 server_found = rarp();
259 server_found = bootp();
262 printf("No Server found\n");
269 /**************************************************************************
270 LOAD - Try to get booted
271 **************************************************************************/
272 static int nic_load(struct dev *dev __unused)
275 printf("\nMe: %@", arptable[ARP_CLIENT].ipaddr.s_addr );
276 #ifndef NO_DHCP_SUPPORT
277 printf(", DHCP: %@", dhcp_server );
279 if (arptable[ARP_PROXYDHCP].ipaddr.s_addr)
281 arptable[ARP_PROXYDHCP].ipaddr.s_addr);
282 #endif /* PXE_EXPORT */
283 #endif /* ! NO_DHCP_SUPPORT */
284 printf(", TFTP: %@", arptable[ARP_SERVER].ipaddr.s_addr);
285 if (BOOTP_DATA_ADDR->bootp_reply.bp_giaddr.s_addr)
286 printf(", Relay: %@",
287 BOOTP_DATA_ADDR->bootp_reply.bp_giaddr.s_addr);
288 if (arptable[ARP_GATEWAY].ipaddr.s_addr)
289 printf(", Gateway %@", arptable[ARP_GATEWAY].ipaddr.s_addr);
291 if (arptable[ARP_NAMESERVER].ipaddr.s_addr)
292 printf(", Nameserver %@", arptable[ARP_NAMESERVER].ipaddr.s_addr);
297 printf("\n=>>"); getchar();
300 /* Now use TFTP to load file */
301 #ifdef DOWNLOAD_PROTO_NFS
304 kernel = KERNEL_BUF[0] == '\0' ?
305 #ifdef DEFAULT_BOOTFILE
312 loadkernel(kernel); /* We don't return except on error */
313 printf("Unable to load file.\n");
315 printf("No filename\n");
317 interruptible_sleep(2); /* lay off the server for a while */
321 void nic_disable ( struct nic *nic __unused ) {
322 #ifdef MULTICAST_LEVEL2
324 for(i = 0; i < MAX_IGMP; i++) {
330 static char * nic_describe_device ( struct type_dev *type_dev ) {
331 struct nic *nic = ( struct nic * ) type_dev;
332 static char nic_description[] = "MAC 00:00:00:00:00:00";
334 sprintf ( nic_description + 4, "%!", nic->node_addr );
335 return nic_description;
339 * Device operations tables
342 struct type_driver nic_driver = {
344 .type_dev = ( struct type_dev * ) &nic,
345 .describe_device = nic_describe_device,
348 /* Careful. We need an aligned buffer to avoid problems on machines
349 * that care about alignment. To trivally align the ethernet data
350 * (the ip hdr and arp requests) we offset the packet by 2 bytes.
351 * leaving the ethernet data 16 byte aligned. Beyond this
352 * we use memmove but this makes the common cast simple and fast.
354 static char packet[ETH_FRAME_LEN + ETH_DATA_ALIGN] __aligned;
357 .node_addr = arptable[ARP_CLIENT].node,
358 .packet = packet + ETH_DATA_ALIGN,
363 int dummy_connect ( struct nic *nic __unused ) {
367 void dummy_irq ( struct nic *nic __unused, irq_action_t irq_action __unused ) {
371 /**************************************************************************
372 DEFAULT_NETMASK - Return default netmask for IP address
373 **************************************************************************/
374 static inline unsigned long default_netmask(void)
376 int net = ntohl(arptable[ARP_CLIENT].ipaddr.s_addr) >> 24;
378 return(htonl(0xff000000));
380 return(htonl(0xffff0000));
382 return(htonl(0xffffff00));
385 /**************************************************************************
386 IP_TRANSMIT - Send an IP datagram
387 **************************************************************************/
388 static int await_arp(int ival, void *ptr,
389 unsigned short ptype, struct iphdr *ip __unused, struct udphdr *udp __unused,
390 struct tcphdr *tcp __unused)
392 struct arprequest *arpreply;
393 if (ptype != ETH_P_ARP)
395 if (nic.packetlen < ETH_HLEN + sizeof(struct arprequest))
397 arpreply = (struct arprequest *)&nic.packet[ETH_HLEN];
399 if (arpreply->opcode != htons(ARP_REPLY))
401 if (memcmp(arpreply->sipaddr, ptr, sizeof(in_addr)) != 0)
403 memcpy(arptable[ival].node, arpreply->shwaddr, ETH_ALEN);
407 int ip_transmit(int len, const void *buf)
409 unsigned long destip;
411 struct arprequest arpreq;
415 ip = (struct iphdr *)buf;
416 destip = ip->dest.s_addr;
417 if (destip == IP_BROADCAST) {
418 eth_transmit(broadcast, ETH_P_IP, len, buf);
419 #ifdef MULTICAST_LEVEL1
420 } else if ((destip & htonl(MULTICAST_MASK)) == htonl(MULTICAST_NETWORK)) {
421 unsigned char multicast[6];
422 unsigned long hdestip;
423 hdestip = ntohl(destip);
427 multicast[3] = (hdestip >> 16) & 0x7;
428 multicast[4] = (hdestip >> 8) & 0xff;
429 multicast[5] = hdestip & 0xff;
430 eth_transmit(multicast, ETH_P_IP, len, buf);
433 if (((destip & netmask) !=
434 (arptable[ARP_CLIENT].ipaddr.s_addr & netmask)) &&
435 arptable[ARP_GATEWAY].ipaddr.s_addr)
436 destip = arptable[ARP_GATEWAY].ipaddr.s_addr;
437 for(arpentry = 0; arpentry<MAX_ARP; arpentry++)
438 if (arptable[arpentry].ipaddr.s_addr == destip) break;
439 if (arpentry == MAX_ARP) {
440 printf("%@ is not in my arp table!\n", destip);
443 for (i = 0; i < ETH_ALEN; i++)
444 if (arptable[arpentry].node[i])
446 if (i == ETH_ALEN) { /* Need to do arp request */
447 arpreq.hwtype = htons(1);
448 arpreq.protocol = htons(IP);
449 arpreq.hwlen = ETH_ALEN;
451 arpreq.opcode = htons(ARP_REQUEST);
452 memcpy(arpreq.shwaddr, arptable[ARP_CLIENT].node, ETH_ALEN);
453 memcpy(arpreq.sipaddr, &arptable[ARP_CLIENT].ipaddr, sizeof(in_addr));
454 memset(arpreq.thwaddr, 0, ETH_ALEN);
455 memcpy(arpreq.tipaddr, &destip, sizeof(in_addr));
456 for (retry = 1; retry <= MAX_ARP_RETRIES; retry++) {
458 eth_transmit(broadcast, ETH_P_ARP, sizeof(arpreq),
460 timeout = rfc2131_sleep_interval(TIMEOUT, retry);
461 if (await_reply(await_arp, arpentry,
462 arpreq.tipaddr, timeout)) goto xmit;
467 eth_transmit(arptable[arpentry].node, ETH_P_IP, len, buf);
472 void build_ip_hdr(unsigned long destip, int ttl, int protocol, int option_len,
473 int len, const void *buf)
476 ip = (struct iphdr *)buf;
477 ip->verhdrlen = 0x45;
478 ip->verhdrlen += (option_len/4);
480 ip->len = htons(len);
482 ip->frags = 0; /* Should we set don't fragment? */
484 ip->protocol = protocol;
486 ip->src.s_addr = arptable[ARP_CLIENT].ipaddr.s_addr;
487 ip->dest.s_addr = destip;
488 ip->chksum = ipchksum(buf, sizeof(struct iphdr) + option_len);
491 void build_udp_hdr(unsigned long destip,
492 unsigned int srcsock, unsigned int destsock, int ttl,
493 int len, const void *buf)
497 ip = (struct iphdr *)buf;
498 build_ip_hdr(destip, ttl, IP_UDP, 0, len, buf);
499 udp = (struct udphdr *)((char *)buf + sizeof(struct iphdr));
500 udp->src = htons(srcsock);
501 udp->dest = htons(destsock);
502 udp->len = htons(len - sizeof(struct iphdr));
504 if ((udp->chksum = tcpudpchksum(ip)) == 0)
505 udp->chksum = 0xffff;
508 #ifdef DOWNLOAD_PROTO_HTTP
509 void build_tcp_hdr(unsigned long destip, unsigned int srcsock,
510 unsigned int destsock, long send_seq, long recv_seq,
511 int window, int flags, int ttl, int len, const void *buf)
515 ip = (struct iphdr *)buf;
516 build_ip_hdr(destip, ttl, IP_TCP, 0, len, buf);
517 tcp = (struct tcphdr *)(ip + 1);
518 tcp->src = htons(srcsock);
519 tcp->dst = htons(destsock);
520 tcp->seq = htonl(send_seq);
521 tcp->ack = htonl(recv_seq);
522 tcp->ctrl = htons(flags + (5 << 12)); /* No TCP options */
523 tcp->window = htons(window);
525 if ((tcp->chksum = tcpudpchksum(ip)) == 0)
526 tcp->chksum = 0xffff;
531 /**************************************************************************
532 UDP_TRANSMIT - Send an UDP datagram
533 **************************************************************************/
534 int udp_transmit(unsigned long destip, unsigned int srcsock,
535 unsigned int destsock, int len, const void *buf)
537 build_udp_hdr(destip, srcsock, destsock, 60, len, buf);
538 return ip_transmit(len, buf);
541 /**************************************************************************
542 TCP_TRANSMIT - Send a TCP packet
543 **************************************************************************/
544 #ifdef DOWNLOAD_PROTO_HTTP
545 int tcp_transmit(unsigned long destip, unsigned int srcsock,
546 unsigned int destsock, long send_seq, long recv_seq,
547 int window, int flags, int len, const void *buf)
549 build_tcp_hdr(destip, srcsock, destsock, send_seq, recv_seq,
550 window, flags, 60, len, buf);
551 return ip_transmit(len, buf);
554 int tcp_reset(struct iphdr *ip) {
555 struct tcphdr *tcp = (struct tcphdr *)(ip + 1);
556 char buf[sizeof(struct iphdr) + sizeof(struct tcphdr)];
558 if (!(tcp->ctrl & htons(RST))) {
559 long seq = ntohl(tcp->seq) + ntohs(ip->len) -
560 sizeof(struct iphdr) -
561 ((ntohs(tcp->ctrl) >> 10) & 0x3C);
562 if (tcp->ctrl & htons(SYN|FIN))
564 return tcp_transmit(ntohl(ip->src.s_addr),
565 ntohs(tcp->dst), ntohs(tcp->src),
566 tcp->ctrl&htons(ACK) ? ntohl(tcp->ack) : 0,
567 seq, TCP_MAX_WINDOW, RST, sizeof(buf), buf);
573 /**************************************************************************
574 QDRAIN - clear the nic's receive queue
575 **************************************************************************/
576 static int await_qdrain(int ival __unused, void *ptr __unused,
577 unsigned short ptype __unused,
578 struct iphdr *ip __unused, struct udphdr *udp __unused,
579 struct tcphdr *tcp __unused)
586 /* Clear out the Rx queue first. It contains nothing of interest,
587 * except possibly ARP requests from the DHCP/TFTP server. We use
588 * polling throughout Etherboot, so some time may have passed since we
589 * last polled the receive queue, which may now be filled with
590 * broadcast packets. This will cause the reply to the packets we are
591 * about to send to be lost immediately. Not very clever. */
592 await_reply(await_qdrain, 0, NULL, 0);
595 #ifdef DOWNLOAD_PROTO_TFTP
596 /**************************************************************************
597 TFTP - Download extended BOOTP data, or kernel image
598 **************************************************************************/
599 static int await_tftp(int ival, void *ptr __unused,
600 unsigned short ptype __unused, struct iphdr *ip, struct udphdr *udp,
601 struct tcphdr *tcp __unused)
606 if (arptable[ARP_CLIENT].ipaddr.s_addr != ip->dest.s_addr)
608 if (ntohs(udp->dest) != ival)
613 int tftp ( const char *name,
614 int (*fnc)(unsigned char *, unsigned int, unsigned int, int) )
616 struct tftpreq_info_t request_data =
617 { name, TFTP_PORT, TFTP_MAX_PACKET };
618 struct tftpreq_info_t *request = &request_data;
619 struct tftpblk_info_t block;
622 while ( tftp_block ( request, &block ) ) {
623 request = NULL; /* Send request only once */
624 rc = fnc ( block.data, block.block, block.len, block.eof );
625 if ( rc <= 0 ) return (rc);
627 /* fnc should not have returned */
628 printf ( "TFTP download complete, but\n" );
635 int tftp_block ( struct tftpreq_info_t *request, struct tftpblk_info_t *block )
637 static unsigned short lport = 2000; /* local port */
638 static unsigned short rport = TFTP_PORT; /* remote port */
639 struct tftp_t *rcvd = NULL;
640 static struct tftpreq_t xmit;
641 static unsigned short xmitlen = 0;
642 static unsigned short blockidx = 0; /* Last block received */
643 static unsigned short retry = 0; /* Retry attempts on last block */
644 static int blksize = 0;
645 unsigned short recvlen = 0;
647 /* If this is a new request (i.e. if name is set), fill in
648 * transmit block with RRQ and send it.
651 rx_qdrain(); /* Flush receive queue */
652 xmit.opcode = htons(TFTP_RRQ);
653 xmitlen = (void*)&xmit.u.rrq - (void*)&xmit +
654 sprintf((char*)xmit.u.rrq, "%s%coctet%cblksize%c%d",
655 request->name, 0, 0, 0, request->blksize)
656 + 1; /* null terminator */
657 blockidx = 0; /* Reset counters */
659 blksize = TFTP_DEFAULTSIZE_PACKET;
660 lport++; /* Use new local port */
661 rport = request->port;
662 if ( !udp_transmit(arptable[ARP_SERVER].ipaddr.s_addr, lport,
663 rport, xmitlen, &xmit) )
666 /* Exit if no transfer in progress */
667 if ( !blksize ) return (0);
668 /* Loop to wait until we get a packet we're interested in */
669 block->data = NULL; /* Used as flag */
670 while ( block->data == NULL ) {
671 long timeout = rfc2131_sleep_interval ( blockidx ? TFTP_REXMT :
673 if ( !await_reply(await_tftp, lport, NULL, timeout) ) {
674 /* No packet received */
675 if ( retry++ > MAX_TFTP_RETRIES ) break;
676 /* Retransmit last packet */
677 if ( !blockidx ) lport++; /* New lport if new RRQ */
678 if ( !udp_transmit(arptable[ARP_SERVER].ipaddr.s_addr,
679 lport, rport, xmitlen, &xmit) )
681 continue; /* Back to waiting for packet */
683 /* Packet has been received */
684 rcvd = (struct tftp_t *)&nic.packet[ETH_HLEN];
685 recvlen = ntohs(rcvd->udp.len) - sizeof(struct udphdr)
686 - sizeof(rcvd->opcode);
687 rport = ntohs(rcvd->udp.src);
688 retry = 0; /* Reset retry counter */
689 switch ( htons(rcvd->opcode) ) {
691 printf ( "TFTP error %d (%s)\n",
692 ntohs(rcvd->u.err.errcode),
693 rcvd->u.err.errmsg );
694 return (0); /* abort */
697 const char *p = rcvd->u.oack.data;
698 const char *e = p + recvlen - 10; /* "blksize\0\d\0" */
700 *((char*)(p+recvlen-1)) = '\0'; /* Force final 0 */
701 if ( blockidx || !request ) break; /* Too late */
702 if ( recvlen <= TFTP_MAX_PACKET ) /* sanity */ {
703 /* Check for blksize option honoured */
705 if ( strcasecmp("blksize",p) == 0 &&
707 blksize = strtoul(p+8,&p,10);
713 if ( blksize < TFTP_DEFAULTSIZE_PACKET || blksize > request->blksize ) {
714 /* Incorrect blksize - error and abort */
715 xmit.opcode = htons(TFTP_ERROR);
716 xmit.u.err.errcode = 8;
717 xmitlen = (void*)&xmit.u.err.errmsg
719 + sprintf((char*)xmit.u.err.errmsg,
723 arptable[ARP_SERVER].ipaddr.s_addr,
724 lport, rport, xmitlen, &xmit);
729 if ( ntohs(rcvd->u.data.block) != ( blockidx + 1 ) )
730 break; /* Re-ACK last block sent */
731 if ( recvlen > ( blksize+sizeof(rcvd->u.data.block) ) )
732 break; /* Too large; ignore */
733 block->data = rcvd->u.data.download;
734 block->block = ++blockidx;
735 block->len = recvlen - sizeof(rcvd->u.data.block);
736 block->eof = ( (unsigned short)block->len < blksize );
737 /* If EOF, zero blksize to indicate transfer done */
738 if ( block->eof ) blksize = 0;
740 default: break; /* Do nothing */
743 xmit.opcode = htons(TFTP_ACK);
744 xmit.u.ack.block = htons(blockidx);
745 xmitlen = TFTP_MIN_PACKET;
746 udp_transmit ( arptable[ARP_SERVER].ipaddr.s_addr,
747 lport, rport, xmitlen, &xmit );
749 return ( block->data ? 1 : 0 );
751 #endif /* DOWNLOAD_PROTO_TFTP */
753 #ifdef RARP_NOT_BOOTP
754 /**************************************************************************
755 RARP - Get my IP address and load information
756 **************************************************************************/
757 static int await_rarp(int ival, void *ptr,
758 unsigned short ptype, struct iphdr *ip, struct udphdr *udp,
759 struct tcphdr *tcp __unused)
761 struct arprequest *arpreply;
762 if (ptype != ETH_P_RARP)
764 if (nic.packetlen < ETH_HLEN + sizeof(struct arprequest))
766 arpreply = (struct arprequest *)&nic.packet[ETH_HLEN];
767 if (arpreply->opcode != htons(RARP_REPLY))
769 if ((arpreply->opcode == htons(RARP_REPLY)) &&
770 (memcmp(arpreply->thwaddr, ptr, ETH_ALEN) == 0)) {
771 memcpy(arptable[ARP_SERVER].node, arpreply->shwaddr, ETH_ALEN);
772 memcpy(&arptable[ARP_SERVER].ipaddr, arpreply->sipaddr, sizeof(in_addr));
773 memcpy(&arptable[ARP_CLIENT].ipaddr, arpreply->tipaddr, sizeof(in_addr));
779 static int rarp(void)
783 /* arp and rarp requests share the same packet structure. */
784 struct arprequest rarpreq;
786 memset(&rarpreq, 0, sizeof(rarpreq));
788 rarpreq.hwtype = htons(1);
789 rarpreq.protocol = htons(IP);
790 rarpreq.hwlen = ETH_ALEN;
791 rarpreq.protolen = 4;
792 rarpreq.opcode = htons(RARP_REQUEST);
793 memcpy(&rarpreq.shwaddr, arptable[ARP_CLIENT].node, ETH_ALEN);
794 /* sipaddr is already zeroed out */
795 memcpy(&rarpreq.thwaddr, arptable[ARP_CLIENT].node, ETH_ALEN);
796 /* tipaddr is already zeroed out */
798 for (retry = 0; retry < MAX_ARP_RETRIES; ++retry) {
800 eth_transmit(broadcast, ETH_P_RARP, sizeof(rarpreq), &rarpreq);
802 timeout = rfc2131_sleep_interval(TIMEOUT, retry);
803 if (await_reply(await_rarp, 0, rarpreq.shwaddr, timeout))
807 if (retry < MAX_ARP_RETRIES) {
808 (void)sprintf(KERNEL_BUF, DEFAULT_KERNELPATH, arptable[ARP_CLIENT].ipaddr);
817 /**************************************************************************
818 BOOTP - Get my IP address and load information
819 **************************************************************************/
820 static int await_bootp(int ival __unused, void *ptr __unused,
821 unsigned short ptype __unused, struct iphdr *ip __unused,
822 struct udphdr *udp, struct tcphdr *tcp __unused)
824 struct bootp_t *bootpreply;
828 bootpreply = (struct bootp_t *)&nic.packet[ETH_HLEN +
829 sizeof(struct iphdr) + sizeof(struct udphdr)];
830 if (nic.packetlen < ETH_HLEN + sizeof(struct iphdr) +
831 sizeof(struct udphdr) +
832 #ifdef NO_DHCP_SUPPORT
833 sizeof(struct bootp_t)
835 sizeof(struct bootp_t) - DHCP_OPT_LEN
836 #endif /* NO_DHCP_SUPPORT */
840 if (udp->dest != htons(BOOTP_CLIENT))
842 if (bootpreply->bp_op != BOOTP_REPLY)
844 if (bootpreply->bp_xid != xid)
846 if (memcmp(&bootpreply->bp_siaddr, &zeroIP, sizeof(in_addr)) == 0)
848 if ((memcmp(broadcast, bootpreply->bp_hwaddr, ETH_ALEN) != 0) &&
849 (memcmp(arptable[ARP_CLIENT].node, bootpreply->bp_hwaddr, ETH_ALEN) != 0)) {
852 if ( bootpreply->bp_siaddr.s_addr ) {
853 arptable[ARP_SERVER].ipaddr.s_addr = bootpreply->bp_siaddr.s_addr;
854 memset(arptable[ARP_SERVER].node, 0, ETH_ALEN); /* Kill arp */
856 if ( bootpreply->bp_giaddr.s_addr ) {
857 arptable[ARP_GATEWAY].ipaddr.s_addr = bootpreply->bp_giaddr.s_addr;
858 memset(arptable[ARP_GATEWAY].node, 0, ETH_ALEN); /* Kill arp */
860 if (bootpreply->bp_yiaddr.s_addr) {
861 /* Offer with an IP address */
862 arptable[ARP_CLIENT].ipaddr.s_addr = bootpreply->bp_yiaddr.s_addr;
863 #ifndef NO_DHCP_SUPPORT
864 dhcp_addr.s_addr = bootpreply->bp_yiaddr.s_addr;
865 #endif /* NO_DHCP_SUPPORT */
866 netmask = default_netmask();
867 /* bootpreply->bp_file will be copied to KERNEL_BUF in the memcpy */
868 memcpy((char *)BOOTP_DATA_ADDR, (char *)bootpreply, sizeof(struct bootpd_t));
869 decode_rfc1533(BOOTP_DATA_ADDR->bootp_reply.bp_vend, 0,
870 #ifdef NO_DHCP_SUPPORT
871 BOOTP_VENDOR_LEN + MAX_BOOTP_EXTLEN,
873 DHCP_OPT_LEN + MAX_BOOTP_EXTLEN,
874 #endif /* NO_DHCP_SUPPORT */
878 /* Offer without an IP address - use as ProxyDHCP server */
879 arptable[ARP_PROXYDHCP].ipaddr.s_addr = bootpreply->bp_siaddr.s_addr;
880 memset(arptable[ARP_PROXYDHCP].node, 0, ETH_ALEN); /* Kill arp */
881 /* Grab only the bootfile name from a ProxyDHCP packet */
882 memcpy(KERNEL_BUF, bootpreply->bp_file, sizeof(KERNEL_BUF));
883 #endif /* PXE_EXPORT */
885 #ifdef REQUIRE_VCI_ETHERBOOT
892 static int bootp(void)
895 #ifndef NO_DHCP_SUPPORT
897 #endif /* NO_DHCP_SUPPORT */
899 unsigned long starttime;
900 unsigned char *bp_vend;
902 #ifndef NO_DHCP_SUPPORT
903 * ( ( struct dhcp_dev_id * ) &dhcp_machine_info[4] ) = nic.dhcp_dev_id;
904 #endif /* NO_DHCP_SUPPORT */
905 memset(&ip, 0, sizeof(struct bootpip_t));
906 ip.bp.bp_op = BOOTP_REQUEST;
908 ip.bp.bp_hlen = ETH_ALEN;
909 starttime = currticks();
910 /* Use lower 32 bits of node address, more likely to be
911 distinct than the time since booting */
912 memcpy(&xid, &arptable[ARP_CLIENT].node[2], sizeof(xid));
913 ip.bp.bp_xid = xid += htonl(starttime);
914 memcpy(ip.bp.bp_hwaddr, arptable[ARP_CLIENT].node, ETH_ALEN);
915 #ifdef NO_DHCP_SUPPORT
916 memcpy(ip.bp.bp_vend, rfc1533_cookie, 5); /* request RFC-style options */
918 memcpy(ip.bp.bp_vend, rfc1533_cookie, sizeof rfc1533_cookie); /* request RFC-style options */
919 memcpy(ip.bp.bp_vend + sizeof rfc1533_cookie, dhcpdiscover, sizeof dhcpdiscover);
920 /* Append machine_info to end, in encapsulated option */
921 bp_vend = ip.bp.bp_vend + sizeof rfc1533_cookie + sizeof dhcpdiscover;
922 memcpy(bp_vend, dhcp_machine_info, DHCP_MACHINE_INFO_SIZE);
923 bp_vend += DHCP_MACHINE_INFO_SIZE;
924 *bp_vend++ = RFC1533_END;
925 #endif /* NO_DHCP_SUPPORT */
927 for (retry = 0; retry < MAX_BOOTP_RETRIES; ) {
928 uint8_t my_hwaddr[ETH_ALEN];
929 unsigned long stop_time;
934 /* Kill arptable to avoid keeping stale entries */
935 memcpy ( my_hwaddr, arptable[ARP_CLIENT].node, ETH_ALEN );
936 memset ( arptable, 0, sizeof(arptable) );
937 memcpy ( arptable[ARP_CLIENT].node, my_hwaddr, ETH_ALEN );
939 udp_transmit(IP_BROADCAST, BOOTP_CLIENT, BOOTP_SERVER,
940 sizeof(struct bootpip_t), &ip);
941 remaining_time = rfc2131_sleep_interval(BOOTP_TIMEOUT, retry++);
942 stop_time = currticks() + remaining_time;
943 #ifdef NO_DHCP_SUPPORT
944 if (await_reply(await_bootp, 0, NULL, timeout))
947 while ( remaining_time > 0 ) {
948 if (await_reply(await_bootp, 0, NULL, remaining_time)){
950 remaining_time = stop_time - currticks();
952 if ( ! arptable[ARP_CLIENT].ipaddr.s_addr ) {
953 printf("No IP address\n");
956 /* If not a DHCPOFFER then must be just a BOOTP reply,
957 * be backward compatible with BOOTP then */
958 if (dhcp_reply != DHCPOFFER)
961 /* Construct the DHCPREQUEST packet */
962 memcpy(ip.bp.bp_vend, rfc1533_cookie, sizeof rfc1533_cookie);
963 memcpy(ip.bp.bp_vend + sizeof rfc1533_cookie, dhcprequest, sizeof dhcprequest);
964 /* Beware: the magic numbers 9 and 15 depend on
965 the layout of dhcprequest */
966 memcpy(&ip.bp.bp_vend[9], &dhcp_server, sizeof(in_addr));
967 memcpy(&ip.bp.bp_vend[15], &dhcp_addr, sizeof(in_addr));
968 bp_vend = ip.bp.bp_vend + sizeof rfc1533_cookie + sizeof dhcprequest;
969 /* Append machine_info to end, in encapsulated option */
970 memcpy(bp_vend, dhcp_machine_info, DHCP_MACHINE_INFO_SIZE);
971 bp_vend += DHCP_MACHINE_INFO_SIZE;
972 *bp_vend++ = RFC1533_END;
973 for (reqretry = 0; reqretry < MAX_BOOTP_RETRIES; ) {
974 unsigned long timeout;
976 udp_transmit(IP_BROADCAST, BOOTP_CLIENT, BOOTP_SERVER,
977 sizeof(struct bootpip_t), &ip);
979 timeout = rfc2131_sleep_interval(TIMEOUT, reqretry++);
980 if (!await_reply(await_bootp, 0, NULL, timeout))
982 if (dhcp_reply != DHCPACK)
986 if ( arptable[ARP_PROXYDHCP].ipaddr.s_addr ) {
987 /* Construct the ProxyDHCPREQUEST packet */
988 memcpy(ip.bp.bp_vend, rfc1533_cookie, sizeof rfc1533_cookie);
989 memcpy(ip.bp.bp_vend + sizeof rfc1533_cookie, proxydhcprequest, sizeof proxydhcprequest);
990 for (reqretry = 0; reqretry < MAX_BOOTP_RETRIES; ) {
991 printf ( "\nSending ProxyDHCP request to %@...", arptable[ARP_PROXYDHCP].ipaddr.s_addr);
992 udp_transmit(arptable[ARP_PROXYDHCP].ipaddr.s_addr, BOOTP_CLIENT, PROXYDHCP_SERVER,
993 sizeof(struct bootpip_t), &ip);
994 timeout = rfc2131_sleep_interval(TIMEOUT, reqretry++);
995 if (await_reply(await_bootp, 0, NULL, timeout)) {
1000 #endif /* PXE_EXPORT */
1003 #endif /* NO_DHCP_SUPPORT */
1004 ip.bp.bp_secs = htons((currticks()-starttime)/TICKS_PER_SEC);
1008 #endif /* RARP_NOT_BOOTP */
1010 static uint16_t tcpudpchksum(struct iphdr *ip)
1012 struct udp_pseudo_hdr pseudo;
1015 /* Compute the pseudo header */
1016 pseudo.src.s_addr = ip->src.s_addr;
1017 pseudo.dest.s_addr = ip->dest.s_addr;
1019 pseudo.protocol = ip->protocol;
1020 pseudo.len = htons(ntohs(ip->len) - sizeof(struct iphdr));
1022 /* Sum the pseudo header */
1023 checksum = ipchksum(&pseudo, 12);
1025 /* Sum the rest of the tcp/udp packet */
1026 checksum = add_ipchksums(12, checksum, ipchksum(ip + 1,
1027 ntohs(ip->len) - sizeof(struct iphdr)));
1031 #ifdef MULTICAST_LEVEL2
1032 static void send_igmp_reports(unsigned long now)
1035 for(i = 0; i < MAX_IGMP; i++) {
1036 if (igmptable[i].time && (now >= igmptable[i].time)) {
1037 struct igmp_ip_t igmp;
1038 igmp.router_alert[0] = 0x94;
1039 igmp.router_alert[1] = 0x04;
1040 igmp.router_alert[2] = 0;
1041 igmp.router_alert[3] = 0;
1042 build_ip_hdr(igmptable[i].group.s_addr,
1043 1, IP_IGMP, sizeof(igmp.router_alert), sizeof(igmp), &igmp);
1044 igmp.igmp.type = IGMPv2_REPORT;
1046 (now < last_igmpv1 + IGMPv1_ROUTER_PRESENT_TIMEOUT)) {
1047 igmp.igmp.type = IGMPv1_REPORT;
1049 igmp.igmp.response_time = 0;
1050 igmp.igmp.chksum = 0;
1051 igmp.igmp.group.s_addr = igmptable[i].group.s_addr;
1052 igmp.igmp.chksum = ipchksum(&igmp.igmp, sizeof(igmp.igmp));
1053 ip_transmit(sizeof(igmp), &igmp);
1055 printf("Sent IGMP report to: %@\n", igmp.igmp.group.s_addr);
1057 /* Don't send another igmp report until asked */
1058 igmptable[i].time = 0;
1063 static void process_igmp(struct iphdr *ip, unsigned long now)
1068 if (!ip || (ip->protocol == IP_IGMP) ||
1069 (nic.packetlen < sizeof(struct iphdr) + sizeof(struct igmp))) {
1072 iplen = (ip->verhdrlen & 0xf)*4;
1073 igmp = (struct igmp *)&nic.packet[sizeof(struct iphdr)];
1074 if (ipchksum(igmp, ntohs(ip->len) - iplen) != 0)
1076 if ((igmp->type == IGMP_QUERY) &&
1077 (ip->dest.s_addr == htonl(GROUP_ALL_HOSTS))) {
1078 unsigned long interval = IGMP_INTERVAL;
1079 if (igmp->response_time == 0) {
1082 interval = (igmp->response_time * TICKS_PER_SEC)/10;
1086 printf("Received IGMP query for: %@\n", igmp->group.s_addr);
1088 for(i = 0; i < MAX_IGMP; i++) {
1089 uint32_t group = igmptable[i].group.s_addr;
1090 if ((group == 0) || (group == igmp->group.s_addr)) {
1092 time = currticks() + rfc1112_sleep_interval(interval, 0);
1093 if (time < igmptable[i].time) {
1094 igmptable[i].time = time;
1099 if (((igmp->type == IGMPv1_REPORT) || (igmp->type == IGMPv2_REPORT)) &&
1100 (ip->dest.s_addr == igmp->group.s_addr)) {
1102 printf("Received IGMP report for: %@\n", igmp->group.s_addr);
1104 for(i = 0; i < MAX_IGMP; i++) {
1105 if ((igmptable[i].group.s_addr == igmp->group.s_addr) &&
1106 igmptable[i].time != 0) {
1107 igmptable[i].time = 0;
1113 void leave_group(int slot)
1115 /* Be very stupid and always send a leave group message if
1116 * I have subscribed. Imperfect but it is standards
1117 * compliant, easy and reliable to implement.
1119 * The optimal group leave method is to only send leave when,
1120 * we were the last host to respond to a query on this group,
1121 * and igmpv1 compatibility is not enabled.
1123 if (igmptable[slot].group.s_addr) {
1124 struct igmp_ip_t igmp;
1125 igmp.router_alert[0] = 0x94;
1126 igmp.router_alert[1] = 0x04;
1127 igmp.router_alert[2] = 0;
1128 igmp.router_alert[3] = 0;
1129 build_ip_hdr(htonl(GROUP_ALL_HOSTS),
1130 1, IP_IGMP, sizeof(igmp.router_alert), sizeof(igmp), &igmp);
1131 igmp.igmp.type = IGMP_LEAVE;
1132 igmp.igmp.response_time = 0;
1133 igmp.igmp.chksum = 0;
1134 igmp.igmp.group.s_addr = igmptable[slot].group.s_addr;
1135 igmp.igmp.chksum = ipchksum(&igmp.igmp, sizeof(igmp));
1136 ip_transmit(sizeof(igmp), &igmp);
1138 printf("Sent IGMP leave for: %@\n", igmp.igmp.group.s_addr);
1141 memset(&igmptable[slot], 0, sizeof(igmptable[0]));
1144 void join_group(int slot, unsigned long group)
1146 /* I have already joined */
1147 if (igmptable[slot].group.s_addr == group)
1149 if (igmptable[slot].group.s_addr) {
1152 /* Only join a group if we are given a multicast ip, this way
1153 * code can be given a non-multicast (broadcast or unicast ip)
1156 if ((group & htonl(MULTICAST_MASK)) == htonl(MULTICAST_NETWORK)) {
1157 igmptable[slot].group.s_addr = group;
1158 igmptable[slot].time = currticks();
1162 #define send_igmp_reports(now) do {} while(0)
1163 #define process_igmp(ip, now) do {} while(0)
1166 #include "proto_eth_slow.c"
1168 /**************************************************************************
1169 TCP - Simple-minded TCP stack. Can only send data once and then
1170 receive the response. The algorithm for computing window
1171 sizes and delaying ack's is currently broken, and thus
1172 disabled. Performance would probably improve a little, if
1173 this gets fixed. FIXME
1174 **************************************************************************/
1175 #ifdef DOWNLOAD_PROTO_HTTP
1176 static int await_tcp(int ival, void *ptr, unsigned short ptype __unused,
1177 struct iphdr *ip, struct udphdr *udp __unused,
1183 if (arptable[ARP_CLIENT].ipaddr.s_addr != ip->dest.s_addr)
1185 if (ntohs(tcp->dst) != ival) {
1189 *(void **)ptr = tcp;
1193 int tcp_transaction(unsigned long destip, unsigned int destsock, void *ptr,
1194 int (*send)(int len, void *buf, void *ptr),
1195 int (*recv)(int len, const void *buf, void *ptr)) {
1196 static uint16_t srcsock = 0;
1198 long send_seq = currticks();
1205 char buf[128]; /* Small outgoing buffer */
1208 int window = 3*TCP_MIN_WINDOW;
1213 long rto = TCP_INITIAL_TIMEOUT;
1214 int retry = TCP_MAX_TIMEOUT/TCP_INITIAL_TIMEOUT;
1215 enum { CLOSED, SYN_RCVD, ESTABLISHED,
1216 FIN_WAIT_1, FIN_WAIT_2 } state = CLOSED;
1219 srcsock = currticks();
1221 if (++srcsock < 1024)
1224 await_reply(await_qdrain, 0, NULL, 0);
1228 last_ack = recv_seq;
1229 if (!tcp_transmit(destip, srcsock, destsock, send_seq,
1230 recv_seq, window, ctrl,
1231 sizeof(struct iphdr) + sizeof(struct tcphdr)+
1235 last_sent = currticks();
1238 if (!await_reply(await_tcp, srcsock, &tcp,
1239 (state == ESTABLISHED && !can_send)
1240 ? TCP_MAX_TIMEOUT : rto)) {
1241 if (state == ESTABLISHED) {
1249 if (state == FIN_WAIT_1 || state == FIN_WAIT_2)
1254 if (state == SYN_RCVD) {
1255 tcp_transmit(destip, srcsock, destsock,
1256 send_seq, 0, window, RST,
1257 sizeof(struct iphdr) +
1258 sizeof(struct tcphdr), buf);
1266 retry = TCP_MAX_RETRY;
1268 if (tcp->ctrl & htons(ACK) ) {
1270 int syn_ack, consumed;
1272 if (state == FIN_WAIT_1 || state == FIN_WAIT_2) {
1277 syn_ack = state == CLOSED || state == SYN_RCVD;
1278 consumed = ntohl(tcp->ack) - send_seq - syn_ack;
1279 if (consumed < 0 || consumed > can_send) {
1280 tcp_reset((struct iphdr *)&nic.packet[ETH_HLEN]);
1284 rtt = currticks() - last_sent;
1285 srtt = !srtt ? rtt : (srtt*4 + rtt)/5;
1286 rto = srtt + srtt/2;
1287 if (rto < TCP_MIN_TIMEOUT)
1288 rto = TCP_MIN_TIMEOUT;
1289 else if (rto > TCP_MAX_TIMEOUT)
1290 rto = TCP_MAX_TIMEOUT;
1292 can_send -= consumed;
1293 send_seq += consumed + syn_ack;
1294 data = buf + sizeof(struct iphdr) + sizeof(struct tcphdr);
1296 memmove(data, data + consumed, can_send);
1301 more_data = buf + sizeof(buf) - data;
1302 if (more_data > 0) {
1303 more_data = send(more_data, data, ptr);
1304 can_send += more_data;
1306 sent_all = !more_data;
1308 if (state == SYN_RCVD) {
1309 state = ESTABLISHED;
1313 if (tcp->ctrl & htons(RST))
1315 } else if (tcp->ctrl & htons(RST)) {
1316 if (state == CLOSED)
1322 ip = (struct iphdr *)&nic.packet[ETH_HLEN];
1323 header_size = sizeof(struct iphdr) + ((ntohs(tcp->ctrl)>>10)&0x3C);
1324 payload = ntohs(ip->len) - header_size;
1325 if (payload > 0 && state == ESTABLISHED) {
1326 int old_bytes = recv_seq - (long)ntohl(tcp->seq);
1327 if (old_bytes >= 0 && payload - old_bytes > 0) {
1328 recv_seq += payload - old_bytes;
1329 if (state != FIN_WAIT_1 && state != FIN_WAIT_2 &&
1330 !recv(payload - old_bytes,
1331 &nic.packet[ETH_HLEN+header_size+old_bytes],
1335 if ((state == ESTABLISHED || state == SYN_RCVD) &&
1336 !(tcp->ctrl & htons(FIN))) {
1337 int in_window = window - 2*TCP_MIN_WINDOW >
1338 recv_seq - last_ack;
1339 ctrl = can_send ? PSH|ACK : ACK;
1340 if (!can_send && in_window) {
1341 /* Window scaling is broken right now, just fall back to acknowledging every */
1342 /* packet immediately and unconditionally. FIXME */ /***/
1343 /* if (await_reply(await_tcp, srcsock,
1350 window += TCP_MIN_WINDOW;
1351 if (window > TCP_MAX_WINDOW)
1352 window = TCP_MAX_WINDOW;
1357 /* saw old data again, must have lost packets */
1359 if (window < 2*TCP_MIN_WINDOW)
1360 window = 2*TCP_MIN_WINDOW;
1364 if (tcp->ctrl & htons(FIN)) {
1365 if (state == ESTABLISHED) {
1367 } else if (state == FIN_WAIT_1 || state == FIN_WAIT_2) {
1372 return (tcp_transmit(destip, srcsock, destsock,
1373 send_seq, recv_seq + 1, window, ctrl,
1374 sizeof(struct iphdr) +
1375 sizeof(struct tcphdr), buf) &&
1376 (state == ESTABLISHED ||
1377 state == FIN_WAIT_1 || state == FIN_WAIT_2) &&
1381 if (state == CLOSED) {
1382 if (tcp->ctrl & htons(SYN)) {
1383 recv_seq = ntohl(tcp->seq) + 1;
1384 if (!(tcp->ctrl & htons(ACK))) {
1389 state = ESTABLISHED;
1395 if (can_send || payload) {
1402 /**************************************************************************
1403 AWAIT_REPLY - Wait until we get a response for our request
1404 ************f**************************************************************/
1405 int await_reply(reply_t reply, int ival, void *ptr, long timeout)
1407 unsigned long time, now;
1412 unsigned short ptype;
1415 time = timeout + currticks();
1416 /* The timeout check is done below. The timeout is only checked if
1417 * there is no packet in the Rx queue. This assumes that eth_poll()
1418 * needs a negligible amount of time.
1422 send_eth_slow_reports(now);
1423 send_igmp_reports(now);
1424 result = eth_poll(1);
1426 /* We don't have anything */
1428 /* Check for abort key only if the Rx queue is empty -
1429 * as long as we have something to process, don't
1430 * assume that something failed. It is unlikely that
1431 * we have no processing time left between packets. */
1432 poll_interruptions();
1433 /* Do the timeout after at least a full queue walk. */
1434 if ((timeout == 0) || (currticks() > time)) {
1440 /* We have something! */
1442 /* Find the Ethernet packet type */
1443 if (nic.packetlen >= ETH_HLEN) {
1444 ptype = ((unsigned short) nic.packet[12]) << 8
1445 | ((unsigned short) nic.packet[13]);
1446 } else continue; /* what else could we do with it? */
1447 /* Verify an IP header */
1449 if ((ptype == ETH_P_IP) && (nic.packetlen >= ETH_HLEN + sizeof(struct iphdr))) {
1451 ip = (struct iphdr *)&nic.packet[ETH_HLEN];
1452 if ((ip->verhdrlen < 0x45) || (ip->verhdrlen > 0x4F))
1454 iplen = (ip->verhdrlen & 0xf) * 4;
1455 if (ipchksum(ip, iplen) != 0)
1457 if (ip->frags & htons(0x3FFF)) {
1458 static int warned_fragmentation = 0;
1459 if (!warned_fragmentation) {
1460 printf("ALERT: got a fragmented packet - reconfigure your server\n");
1461 warned_fragmentation = 1;
1465 if (ntohs(ip->len) > ETH_MAX_MTU)
1468 ipoptlen = iplen - sizeof(struct iphdr);
1470 /* Delete the ip options, to guarantee
1471 * good alignment, and make etherboot simpler.
1473 memmove(&nic.packet[ETH_HLEN + sizeof(struct iphdr)],
1474 &nic.packet[ETH_HLEN + iplen],
1475 nic.packetlen - ipoptlen);
1476 nic.packetlen -= ipoptlen;
1480 if (ip && (ip->protocol == IP_UDP) &&
1482 ETH_HLEN + sizeof(struct iphdr) + sizeof(struct udphdr))) {
1483 udp = (struct udphdr *)&nic.packet[ETH_HLEN + sizeof(struct iphdr)];
1485 /* Make certain we have a reasonable packet length */
1486 if (ntohs(udp->len) > (ntohs(ip->len) - iplen))
1489 if (udp->chksum && tcpudpchksum(ip)) {
1490 printf("UDP checksum error\n");
1495 #ifdef DOWNLOAD_PROTO_HTTP
1496 if (ip && (ip->protocol == IP_TCP) &&
1498 ETH_HLEN + sizeof(struct iphdr) + sizeof(struct tcphdr))){
1499 tcp = (struct tcphdr *)&nic.packet[ETH_HLEN +
1500 sizeof(struct iphdr)];
1501 /* Make certain we have a reasonable packet length */
1502 if (((ntohs(tcp->ctrl) >> 10) & 0x3C) >
1503 ntohs(ip->len) - (int)iplen)
1505 if (tcpudpchksum(ip)) {
1506 printf("TCP checksum error\n");
1512 result = reply(ival, ptr, ptype, ip, udp, tcp);
1517 /* If it isn't a packet the upper layer wants see if there is a default
1518 * action. This allows us reply to arp, igmp, and lacp queries.
1520 if ((ptype == ETH_P_ARP) &&
1521 (nic.packetlen >= ETH_HLEN + sizeof(struct arprequest))) {
1522 struct arprequest *arpreply;
1525 arpreply = (struct arprequest *)&nic.packet[ETH_HLEN];
1526 memcpy(&tmp, arpreply->tipaddr, sizeof(in_addr));
1527 if ((arpreply->opcode == htons(ARP_REQUEST)) &&
1528 (tmp == arptable[ARP_CLIENT].ipaddr.s_addr)) {
1529 arpreply->opcode = htons(ARP_REPLY);
1530 memcpy(arpreply->tipaddr, arpreply->sipaddr, sizeof(in_addr));
1531 memcpy(arpreply->thwaddr, arpreply->shwaddr, ETH_ALEN);
1532 memcpy(arpreply->sipaddr, &arptable[ARP_CLIENT].ipaddr, sizeof(in_addr));
1533 memcpy(arpreply->shwaddr, arptable[ARP_CLIENT].node, ETH_ALEN);
1534 eth_transmit(arpreply->thwaddr, ETH_P_ARP,
1535 sizeof(struct arprequest),
1538 memcpy(&tmp, arpreply->tipaddr, sizeof(in_addr));
1539 printf("Sent ARP reply to: %@\n",tmp);
1543 process_eth_slow(ptype, now);
1544 process_igmp(ip, now);
1549 #ifdef REQUIRE_VCI_ETHERBOOT
1550 /**************************************************************************
1551 FIND_VCI_ETHERBOOT - Looks for "Etherboot" in Vendor Encapsulated Identifiers
1552 On entry p points to byte count of VCI options
1553 **************************************************************************/
1554 static int find_vci_etherboot(unsigned char *p)
1556 unsigned char *end = p + 1 + *p;
1558 for (p++; p < end; ) {
1559 if (*p == RFC2132_VENDOR_CLASS_ID) {
1560 if (strncmp("Etherboot", p + 2, sizeof("Etherboot") - 1) == 0)
1562 } else if (*p == RFC1533_END)
1564 p += TAG_LEN(p) + 2;
1568 #endif /* REQUIRE_VCI_ETHERBOOT */
1570 /**************************************************************************
1571 DECODE_RFC1533 - Decodes RFC1533 header
1572 **************************************************************************/
1573 int decode_rfc1533(unsigned char *p, unsigned int block, unsigned int len, int eof)
1575 static unsigned char *extdata = NULL, *extend = NULL;
1576 unsigned char *extpath = NULL;
1577 unsigned char *endp;
1578 static unsigned char in_encapsulated_options = 0;
1581 /* Encapsulated option block */
1584 else if (block == 0) {
1585 #ifdef REQUIRE_VCI_ETHERBOOT
1588 end_of_rfc1533 = NULL;
1589 #ifdef IMAGE_FREEBSD
1590 /* yes this is a pain FreeBSD uses this for swap, however,
1591 there are cases when you don't want swap and then
1592 you want this set to get the extra features so lets
1593 just set if dealing with FreeBSD. I haven't run into
1594 any troubles with this but I have without it
1596 vendorext_isvalid = 1;
1597 #ifdef FREEBSD_KERNEL_ENV
1598 memcpy(freebsd_kernel_env, FREEBSD_KERNEL_ENV,
1599 sizeof(FREEBSD_KERNEL_ENV));
1600 /* FREEBSD_KERNEL_ENV had better be a string constant */
1602 freebsd_kernel_env[0]='\0';
1605 vendorext_isvalid = 0;
1607 if (memcmp(p, rfc1533_cookie, 4))
1608 return(0); /* no RFC 1533 header found */
1613 if (memcmp(p, rfc1533_cookie, 4))
1614 return(0); /* no RFC 1533 header found */
1617 if (extend + len <= (unsigned char *)&(BOOTP_DATA_ADDR->bootp_extension[MAX_BOOTP_EXTLEN])) {
1618 memcpy(extend, p, len);
1621 printf("Overflow in vendor data buffer! Aborting...\n");
1622 *extdata = RFC1533_END;
1625 p = extdata; endp = extend;
1630 unsigned char c = *p;
1631 if (c == RFC1533_PAD) {
1635 else if (c == RFC1533_END) {
1636 end_of_rfc1533 = endp = p;
1639 else if (NON_ENCAP_OPT c == RFC1533_NETMASK)
1640 memcpy(&netmask, p+2, sizeof(in_addr));
1641 else if (NON_ENCAP_OPT c == RFC1533_GATEWAY) {
1642 /* This is a little simplistic, but it will
1643 usually be sufficient.
1644 Take only the first entry */
1645 if (TAG_LEN(p) >= sizeof(in_addr))
1646 memcpy(&arptable[ARP_GATEWAY].ipaddr, p+2, sizeof(in_addr));
1648 else if (c == RFC1533_EXTENSIONPATH)
1650 #ifndef NO_DHCP_SUPPORT
1651 #ifdef REQUIRE_VCI_ETHERBOOT
1652 else if (NON_ENCAP_OPT c == RFC1533_VENDOR) {
1653 vci_etherboot = find_vci_etherboot(p+1);
1655 printf("vci_etherboot %d\n", vci_etherboot);
1658 #endif /* REQUIRE_VCI_ETHERBOOT */
1659 else if (NON_ENCAP_OPT c == RFC2132_MSG_TYPE)
1661 else if (NON_ENCAP_OPT c == RFC2132_SRV_ID)
1662 memcpy(&dhcp_server, p+2, sizeof(in_addr));
1663 #endif /* NO_DHCP_SUPPORT */
1664 else if (NON_ENCAP_OPT c == RFC1533_HOSTNAME) {
1666 hostnamelen = *(p + 1);
1668 else if (ENCAP_OPT c == RFC1533_VENDOR_MAGIC
1669 && TAG_LEN(p) >= 6 &&
1670 !memcmp(p+2,vendorext_magic,4) &&
1671 p[6] == RFC1533_VENDOR_MAJOR
1673 vendorext_isvalid++;
1674 else if (NON_ENCAP_OPT c == RFC1533_VENDOR_ETHERBOOT_ENCAP) {
1675 in_encapsulated_options = 1;
1676 decode_rfc1533(p+2, 0, TAG_LEN(p), -1);
1677 in_encapsulated_options = 0;
1679 #ifdef IMAGE_FREEBSD
1680 else if (NON_ENCAP_OPT c == RFC1533_VENDOR_HOWTO)
1681 freebsd_howto = ((p[2]*256+p[3])*256+p[4])*256+p[5];
1682 else if (NON_ENCAP_OPT c == RFC1533_VENDOR_KERNEL_ENV){
1683 if(*(p + 1) < sizeof(freebsd_kernel_env)){
1684 memcpy(freebsd_kernel_env,p+2,*(p+1));
1686 printf("Only support %ld bytes in Kernel Env\n",
1687 sizeof(freebsd_kernel_env));
1692 else if (NON_ENCAP_OPT c == RFC1533_DNS) {
1693 // TODO: Copy the DNS IP somewhere reasonable
1694 if (TAG_LEN(p) >= sizeof(in_addr))
1695 memcpy(&arptable[ARP_NAMESERVER].ipaddr, p+2, sizeof(in_addr));
1701 printf("Unknown RFC1533-tag ");
1702 for(q=p;q<p+2+TAG_LEN(p);q++)
1707 p += TAG_LEN(p) + 2;
1709 extdata = extend = endp;
1710 if (block <= 0 && extpath != NULL) {
1712 memcpy(fname, extpath+2, TAG_LEN(extpath));
1713 fname[(int)TAG_LEN(extpath)] = '\0';
1714 printf("Loading BOOTP-extension file: %s\n",fname);
1715 tftp(fname, decode_rfc1533);
1717 return 1; /* proceed with next block */
1721 /* FIXME double check TWO_SECOND_DIVISOR */
1722 #define TWO_SECOND_DIVISOR (RAND_MAX/TICKS_PER_SEC)
1723 /**************************************************************************
1724 RFC2131_SLEEP_INTERVAL - sleep for expotentially longer times (base << exp) +- 1 sec)
1725 **************************************************************************/
1726 long rfc2131_sleep_interval(long base, int exp)
1729 #ifdef BACKOFF_LIMIT
1730 if (exp > BACKOFF_LIMIT)
1731 exp = BACKOFF_LIMIT;
1733 tmo = (base << exp) + (TICKS_PER_SEC - (random()/TWO_SECOND_DIVISOR));
1737 #ifdef MULTICAST_LEVEL2
1738 /**************************************************************************
1739 RFC1112_SLEEP_INTERVAL - sleep for expotentially longer times, up to (base << exp)
1740 **************************************************************************/
1741 long rfc1112_sleep_interval(long base, int exp)
1743 unsigned long divisor, tmo;
1744 #ifdef BACKOFF_LIMIT
1745 if (exp > BACKOFF_LIMIT)
1746 exp = BACKOFF_LIMIT;
1748 divisor = RAND_MAX/(base << exp);
1749 tmo = random()/divisor;
1752 #endif /* MULTICAST_LEVEL_2 */