1 /* 2 * GRUB -- GRand Unified Bootloader 3 * Copyright (C) 2000,2001,2002 Free Software Foundation, Inc. 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation; either version 2 of the License, or 8 * (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program; if not, write to the Free Software 17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 18 */ 19 20 /* Based on "src/main.c" in etherboot-5.0.5. */ 21 22 /************************************************************************** 23 ETHERBOOT - BOOTP/TFTP Bootstrap Program 24 25 Author: Martin Renters 26 Date: Dec/93 27 28 Literature dealing with the network protocols: 29 ARP - RFC826 30 RARP - RFC903 31 UDP - RFC768 32 BOOTP - RFC951, RFC2132 (vendor extensions) 33 DHCP - RFC2131, RFC2132 (options) 34 TFTP - RFC1350, RFC2347 (options), RFC2348 (blocksize), RFC2349 (tsize) 35 RPC - RFC1831, RFC1832 (XDR), RFC1833 (rpcbind/portmapper) 36 NFS - RFC1094, RFC1813 (v3, useful for clarifications, not implemented) 37 38 **************************************************************************/ 39 40 #define GRUB 1 41 #include <etherboot.h> 42 #include <nic.h> 43 44 /* #define DEBUG 1 */ 45 46 struct arptable_t arptable[MAX_ARP]; 47 48 /* Set if the user pushes Control-C. */ 49 int ip_abort = 0; 50 /* Set if an ethernet card is probed and IP addresses are set. */ 51 int network_ready = 0; 52 53 struct rom_info rom; 54 55 static int vendorext_isvalid; 56 static unsigned long netmask; 57 static struct bootpd_t bootp_data; 58 static unsigned long xid; 59 static unsigned char *end_of_rfc1533 = NULL; 60 61 #ifndef NO_DHCP_SUPPORT 62 #endif /* NO_DHCP_SUPPORT */ 63 64 /* Eth */ 65 static unsigned char vendorext_magic[] = {0xE4, 0x45, 0x74, 0x68}; 66 static const unsigned char broadcast[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; 67 68 #ifdef NO_DHCP_SUPPORT 69 70 static unsigned char rfc1533_cookie[5] = {RFC1533_COOKIE, RFC1533_END}; 71 72 #else /* ! NO_DHCP_SUPPORT */ 73 74 static int dhcp_reply; 75 static in_addr dhcp_server = {0L}; 76 static in_addr dhcp_addr = {0L}; 77 static unsigned char rfc1533_cookie[] = {RFC1533_COOKIE}; 78 static unsigned char rfc1533_end[] = {RFC1533_END}; 79 80 static const unsigned char dhcpdiscover[] = 81 { 82 RFC2132_MSG_TYPE, 1, DHCPDISCOVER, 83 RFC2132_MAX_SIZE,2, /* request as much as we can */ 84 ETH_MAX_MTU / 256, ETH_MAX_MTU % 256, 85 RFC2132_PARAM_LIST, 4, RFC1533_NETMASK, RFC1533_GATEWAY, 86 RFC1533_HOSTNAME, RFC1533_EXTENSIONPATH 87 }; 88 89 static const unsigned char dhcprequest[] = 90 { 91 RFC2132_MSG_TYPE, 1, DHCPREQUEST, 92 RFC2132_SRV_ID, 4, 0, 0, 0, 0, 93 RFC2132_REQ_ADDR, 4, 0, 0, 0, 0, 94 RFC2132_MAX_SIZE, 2, /* request as much as we can */ 95 ETH_MAX_MTU / 256, ETH_MAX_MTU % 256, 96 /* request parameters */ 97 RFC2132_PARAM_LIST, 98 /* 4 standard + 2 vendortags */ 99 4 + 2, 100 /* Standard parameters */ 101 RFC1533_NETMASK, RFC1533_GATEWAY, 102 RFC1533_HOSTNAME, RFC1533_EXTENSIONPATH, 103 /* Etherboot vendortags */ 104 RFC1533_VENDOR_MAGIC, 105 RFC1533_VENDOR_CONFIGFILE, 106 }; 107 108 #endif /* ! NO_DHCP_SUPPORT */ 109 110 static unsigned short ipchksum (unsigned short *ip, int len); 111 static unsigned short udpchksum (struct iphdr *packet); 112 113 void 114 print_network_configuration (void) 115 { 116 if (! eth_probe ()) 117 grub_printf ("No ethernet card found.\n"); 118 else if (! network_ready) 119 grub_printf ("Not initialized yet.\n"); 120 else 121 { 122 etherboot_printf ("Address: %@\n", arptable[ARP_CLIENT].ipaddr.s_addr); 123 etherboot_printf ("Netmask: %@\n", netmask); 124 etherboot_printf ("Server: %@\n", arptable[ARP_SERVER].ipaddr.s_addr); 125 etherboot_printf ("Gateway: %@\n", arptable[ARP_GATEWAY].ipaddr.s_addr); 126 } 127 } 128 129 130 /************************************************************************** 131 DEFAULT_NETMASK - Return default netmask for IP address 132 **************************************************************************/ 133 static inline unsigned long 134 default_netmask (void) 135 { 136 int net = ntohl (arptable[ARP_CLIENT].ipaddr.s_addr) >> 24; 137 if (net <= 127) 138 return (htonl (0xff000000)); 139 else if (net < 192) 140 return (htonl (0xffff0000)); 141 else 142 return (htonl (0xffffff00)); 143 } 144 145 /* ifconfig - configure network interface. */ 146 int 147 ifconfig (char *ip, char *sm, char *gw, char *svr) 148 { 149 in_addr tmp; 150 151 if (sm) 152 { 153 if (! inet_aton (sm, &tmp)) 154 return 0; 155 156 netmask = tmp.s_addr; 157 } 158 159 if (ip) 160 { 161 if (! inet_aton (ip, &arptable[ARP_CLIENT].ipaddr)) 162 return 0; 163 164 if (! netmask && ! sm) 165 netmask = default_netmask (); 166 } 167 168 if (gw && ! inet_aton (gw, &arptable[ARP_GATEWAY].ipaddr)) 169 return 0; 170 171 /* Clear out the ARP entry. */ 172 grub_memset (arptable[ARP_GATEWAY].node, 0, ETH_ALEN); 173 174 if (svr && ! inet_aton (svr, &arptable[ARP_SERVER].ipaddr)) 175 return 0; 176 177 /* Likewise. */ 178 grub_memset (arptable[ARP_SERVER].node, 0, ETH_ALEN); 179 180 if (ip || sm) 181 { 182 if (IP_BROADCAST == (netmask | arptable[ARP_CLIENT].ipaddr.s_addr) 183 || netmask == (netmask | arptable[ARP_CLIENT].ipaddr.s_addr) 184 || ! netmask) 185 network_ready = 0; 186 else 187 network_ready = 1; 188 } 189 190 return 1; 191 } 192 193 194 /************************************************************************** 195 UDP_TRANSMIT - Send a UDP datagram 196 **************************************************************************/ 197 int 198 udp_transmit (unsigned long destip, unsigned int srcsock, 199 unsigned int destsock, int len, const void *buf) 200 { 201 struct iphdr *ip; 202 struct udphdr *udp; 203 struct arprequest arpreq; 204 int arpentry, i; 205 int retry; 206 207 ip = (struct iphdr *) buf; 208 udp = (struct udphdr *) ((unsigned long) buf + sizeof (struct iphdr)); 209 ip->verhdrlen = 0x45; 210 ip->service = 0; 211 ip->len = htons (len); 212 ip->ident = 0; 213 ip->frags = 0; 214 ip->ttl = 60; 215 ip->protocol = IP_UDP; 216 ip->chksum = 0; 217 ip->src.s_addr = arptable[ARP_CLIENT].ipaddr.s_addr; 218 ip->dest.s_addr = destip; 219 ip->chksum = ipchksum ((unsigned short *) buf, sizeof (struct iphdr)); 220 udp->src = htons (srcsock); 221 udp->dest = htons (destsock); 222 udp->len = htons (len - sizeof (struct iphdr)); 223 udp->chksum = 0; 224 udp->chksum = htons (udpchksum (ip)); 225 226 if (udp->chksum == 0) 227 udp->chksum = 0xffff; 228 229 if (destip == IP_BROADCAST) 230 { 231 eth_transmit (broadcast, IP, len, buf); 232 } 233 else 234 { 235 if (((destip & netmask) 236 != (arptable[ARP_CLIENT].ipaddr.s_addr & netmask)) 237 && arptable[ARP_GATEWAY].ipaddr.s_addr) 238 destip = arptable[ARP_GATEWAY].ipaddr.s_addr; 239 240 for (arpentry = 0; arpentry < MAX_ARP; arpentry++) 241 if (arptable[arpentry].ipaddr.s_addr == destip) 242 break; 243 244 if (arpentry == MAX_ARP) 245 { 246 etherboot_printf ("%@ is not in my arp table!\n", destip); 247 return 0; 248 } 249 250 for (i = 0; i < ETH_ALEN; i++) 251 if (arptable[arpentry].node[i]) 252 break; 253 254 if (i == ETH_ALEN) 255 { 256 /* Need to do arp request. */ 257 #ifdef DEBUG 258 grub_printf ("arp request.\n"); 259 #endif 260 arpreq.hwtype = htons (1); 261 arpreq.protocol = htons (IP); 262 arpreq.hwlen = ETH_ALEN; 263 arpreq.protolen = 4; 264 arpreq.opcode = htons (ARP_REQUEST); 265 grub_memmove (arpreq.shwaddr, arptable[ARP_CLIENT].node, 266 ETH_ALEN); 267 grub_memmove (arpreq.sipaddr, (char *) &arptable[ARP_CLIENT].ipaddr, 268 sizeof (in_addr)); 269 grub_memset (arpreq.thwaddr, 0, ETH_ALEN); 270 grub_memmove (arpreq.tipaddr, (char *) &destip, sizeof (in_addr)); 271 272 for (retry = 1; retry <= MAX_ARP_RETRIES; retry++) 273 { 274 long timeout; 275 276 eth_transmit (broadcast, ARP, sizeof (arpreq), &arpreq); 277 timeout = rfc2131_sleep_interval (TIMEOUT, retry); 278 279 if (await_reply (AWAIT_ARP, arpentry, arpreq.tipaddr, timeout)) 280 goto xmit; 281 282 if (ip_abort) 283 return 0; 284 } 285 286 return 0; 287 } 288 289 xmit: 290 eth_transmit (arptable[arpentry].node, IP, len, buf); 291 } 292 293 return 1; 294 } 295 296 /************************************************************************** 297 TFTP - Download extended BOOTP data, or kernel image 298 **************************************************************************/ 299 static int 300 tftp (const char *name, int (*fnc) (unsigned char *, int, int, int)) 301 { 302 int retry = 0; 303 static unsigned short iport = 2000; 304 unsigned short oport = 0; 305 unsigned short len, block = 0, prevblock = 0; 306 int bcounter = 0; 307 struct tftp_t *tr; 308 struct tftpreq_t tp; 309 int rc; 310 int packetsize = TFTP_DEFAULTSIZE_PACKET; 311 312 /* Clear out the Rx queue first. It contains nothing of interest, 313 * except possibly ARP requests from the DHCP/TFTP server. We use 314 * polling throughout Etherboot, so some time may have passed since we 315 * last polled the receive queue, which may now be filled with 316 * broadcast packets. This will cause the reply to the packets we are 317 * about to send to be lost immediately. Not very clever. */ 318 await_reply (AWAIT_QDRAIN, 0, NULL, 0); 319 320 tp.opcode = htons (TFTP_RRQ); 321 len = (grub_sprintf ((char *) tp.u.rrq, "%s%coctet%cblksize%c%d", 322 name, 0, 0, 0, TFTP_MAX_PACKET) 323 + sizeof (tp.ip) + sizeof (tp.udp) + sizeof (tp.opcode) + 1); 324 if (! udp_transmit (arptable[ARP_SERVER].ipaddr.s_addr, ++iport, 325 TFTP_PORT, len, &tp)) 326 return 0; 327 328 for (;;) 329 { 330 long timeout; 331 332 #ifdef CONGESTED 333 timeout = rfc2131_sleep_interval (block ? TFTP_REXMT : TIMEOUT, retry); 334 #else 335 timeout = rfc2131_sleep_interval (TIMEOUT, retry); 336 #endif 337 338 if (! await_reply (AWAIT_TFTP, iport, NULL, timeout)) 339 { 340 if (! block && retry++ < MAX_TFTP_RETRIES) 341 { 342 /* Maybe initial request was lost. */ 343 if (! udp_transmit (arptable[ARP_SERVER].ipaddr.s_addr, 344 ++iport, TFTP_PORT, len, &tp)) 345 return 0; 346 347 continue; 348 } 349 350 #ifdef CONGESTED 351 if (block && ((retry += TFTP_REXMT) < TFTP_TIMEOUT)) 352 { 353 /* We resend our last ack. */ 354 #ifdef MDEBUG 355 grub_printf ("<REXMT>\n"); 356 #endif 357 udp_transmit (arptable[ARP_SERVER].ipaddr.s_addr, 358 iport, oport, 359 TFTP_MIN_PACKET, &tp); 360 continue; 361 } 362 #endif 363 /* Timeout. */ 364 break; 365 } 366 367 tr = (struct tftp_t *) &nic.packet[ETH_HLEN]; 368 if (tr->opcode == ntohs (TFTP_ERROR)) 369 { 370 grub_printf ("TFTP error %d (%s)\n", 371 ntohs (tr->u.err.errcode), 372 tr->u.err.errmsg); 373 break; 374 } 375 376 if (tr->opcode == ntohs (TFTP_OACK)) 377 { 378 char *p = tr->u.oack.data, *e; 379 380 /* Shouldn't happen. */ 381 if (prevblock) 382 /* Ignore it. */ 383 continue; 384 385 len = ntohs (tr->udp.len) - sizeof (struct udphdr) - 2; 386 if (len > TFTP_MAX_PACKET) 387 goto noak; 388 389 e = p + len; 390 while (*p != '\000' && p < e) 391 { 392 if (! grub_strcmp ("blksize", p)) 393 { 394 p += 8; 395 if ((packetsize = getdec (&p)) < TFTP_DEFAULTSIZE_PACKET) 396 goto noak; 397 398 while (p < e && *p) 399 p++; 400 401 if (p < e) 402 p++; 403 } 404 else 405 { 406 noak: 407 tp.opcode = htons (TFTP_ERROR); 408 tp.u.err.errcode = 8; 409 len = (grub_sprintf ((char *) tp.u.err.errmsg, 410 "RFC1782 error") 411 + sizeof (tp.ip) + sizeof (tp.udp) 412 + sizeof (tp.opcode) + sizeof (tp.u.err.errcode) 413 + 1); 414 udp_transmit (arptable[ARP_SERVER].ipaddr.s_addr, 415 iport, ntohs (tr->udp.src), 416 len, &tp); 417 return 0; 418 } 419 } 420 421 if (p > e) 422 goto noak; 423 424 /* This ensures that the packet does not get processed as data! */ 425 block = tp.u.ack.block = 0; 426 } 427 else if (tr->opcode == ntohs (TFTP_DATA)) 428 { 429 len = ntohs (tr->udp.len) - sizeof (struct udphdr) - 4; 430 /* Shouldn't happen. */ 431 if (len > packetsize) 432 /* Ignore it. */ 433 continue; 434 435 block = ntohs (tp.u.ack.block = tr->u.data.block); 436 } 437 else 438 /* Neither TFTP_OACK nor TFTP_DATA. */ 439 break; 440 441 if ((block || bcounter) && (block != prevblock + 1)) 442 /* Block order should be continuous */ 443 tp.u.ack.block = htons (block = prevblock); 444 445 /* Should be continuous. */ 446 tp.opcode = htons (TFTP_ACK); 447 oport = ntohs (tr->udp.src); 448 /* Ack. */ 449 udp_transmit (arptable[ARP_SERVER].ipaddr.s_addr, iport, 450 oport, TFTP_MIN_PACKET, &tp); 451 452 if ((unsigned short) (block - prevblock) != 1) 453 /* Retransmission or OACK, don't process via callback 454 * and don't change the value of prevblock. */ 455 continue; 456 457 prevblock = block; 458 /* Is it the right place to zero the timer? */ 459 retry = 0; 460 461 if ((rc = fnc (tr->u.data.download, 462 ++bcounter, len, len < packetsize)) >= 0) 463 return rc; 464 465 /* End of data. */ 466 if (len < packetsize) 467 return 1; 468 } 469 470 return 0; 471 } 472 473 /************************************************************************** 474 RARP - Get my IP address and load information 475 **************************************************************************/ 476 int 477 rarp (void) 478 { 479 int retry; 480 481 /* arp and rarp requests share the same packet structure. */ 482 struct arprequest rarpreq; 483 484 /* Make sure that an ethernet is probed. */ 485 if (! eth_probe ()) 486 return 0; 487 488 /* Clear the ready flag. */ 489 network_ready = 0; 490 491 grub_memset (&rarpreq, 0, sizeof (rarpreq)); 492 493 rarpreq.hwtype = htons (1); 494 rarpreq.protocol = htons (IP); 495 rarpreq.hwlen = ETH_ALEN; 496 rarpreq.protolen = 4; 497 rarpreq.opcode = htons (RARP_REQUEST); 498 grub_memmove ((char *) &rarpreq.shwaddr, arptable[ARP_CLIENT].node, 499 ETH_ALEN); 500 /* sipaddr is already zeroed out */ 501 grub_memmove ((char *) &rarpreq.thwaddr, arptable[ARP_CLIENT].node, 502 ETH_ALEN); 503 /* tipaddr is already zeroed out */ 504 505 for (retry = 0; retry < MAX_ARP_RETRIES; ++retry) 506 { 507 long timeout; 508 509 eth_transmit (broadcast, RARP, sizeof (rarpreq), &rarpreq); 510 511 timeout = rfc2131_sleep_interval (TIMEOUT, retry); 512 if (await_reply (AWAIT_RARP, 0, rarpreq.shwaddr, timeout)) 513 break; 514 515 if (ip_abort) 516 return 0; 517 } 518 519 if (retry < MAX_ARP_RETRIES) 520 { 521 network_ready = 1; 522 return 1; 523 } 524 525 return 0; 526 } 527 528 /************************************************************************** 529 BOOTP - Get my IP address and load information 530 **************************************************************************/ 531 int 532 bootp (void) 533 { 534 int retry; 535 #ifndef NO_DHCP_SUPPORT 536 int reqretry; 537 #endif /* ! NO_DHCP_SUPPORT */ 538 struct bootpip_t ip; 539 unsigned long starttime; 540 541 /* Make sure that an ethernet is probed. */ 542 if (! eth_probe ()) 543 return 0; 544 545 /* Clear the ready flag. */ 546 network_ready = 0; 547 548 #ifdef DEBUG 549 grub_printf ("network is ready.\n"); 550 #endif 551 552 grub_memset (&ip, 0, sizeof (struct bootpip_t)); 553 ip.bp.bp_op = BOOTP_REQUEST; 554 ip.bp.bp_htype = 1; 555 ip.bp.bp_hlen = ETH_ALEN; 556 starttime = currticks (); 557 /* Use lower 32 bits of node address, more likely to be 558 distinct than the time since booting */ 559 grub_memmove (&xid, &arptable[ARP_CLIENT].node[2], sizeof(xid)); 560 ip.bp.bp_xid = xid += htonl (starttime); 561 grub_memmove (ip.bp.bp_hwaddr, arptable[ARP_CLIENT].node, ETH_ALEN); 562 #ifdef DEBUG 563 etherboot_printf ("bp_op = %d\n", ip.bp.bp_op); 564 etherboot_printf ("bp_htype = %d\n", ip.bp.bp_htype); 565 etherboot_printf ("bp_hlen = %d\n", ip.bp.bp_hlen); 566 etherboot_printf ("bp_xid = %d\n", ip.bp.bp_xid); 567 etherboot_printf ("bp_hwaddr = %!\n", ip.bp.bp_hwaddr); 568 etherboot_printf ("bp_hops = %d\n", (int) ip.bp.bp_hops); 569 etherboot_printf ("bp_secs = %d\n", (int) ip.bp.bp_hwaddr); 570 #endif 571 572 #ifdef NO_DHCP_SUPPORT 573 /* Request RFC-style options. */ 574 grub_memmove (ip.bp.bp_vend, rfc1533_cookie, 5); 575 #else 576 /* Request RFC-style options. */ 577 grub_memmove (ip.bp.bp_vend, rfc1533_cookie, sizeof rfc1533_cookie); 578 grub_memmove (ip.bp.bp_vend + sizeof rfc1533_cookie, dhcpdiscover, 579 sizeof dhcpdiscover); 580 grub_memmove (ip.bp.bp_vend + sizeof rfc1533_cookie + sizeof dhcpdiscover, 581 rfc1533_end, sizeof rfc1533_end); 582 #endif /* ! NO_DHCP_SUPPORT */ 583 584 for (retry = 0; retry < MAX_BOOTP_RETRIES;) 585 { 586 long timeout; 587 588 #ifdef DEBUG 589 grub_printf ("retry = %d\n", retry); 590 #endif 591 592 /* Clear out the Rx queue first. It contains nothing of 593 * interest, except possibly ARP requests from the DHCP/TFTP 594 * server. We use polling throughout Etherboot, so some time 595 * may have passed since we last polled the receive queue, 596 * which may now be filled with broadcast packets. This will 597 * cause the reply to the packets we are about to send to be 598 * lost immediately. Not very clever. */ 599 await_reply (AWAIT_QDRAIN, 0, NULL, 0); 600 601 udp_transmit (IP_BROADCAST, BOOTP_CLIENT, BOOTP_SERVER, 602 sizeof (struct bootpip_t), &ip); 603 timeout = rfc2131_sleep_interval (TIMEOUT, retry++); 604 #ifdef NO_DHCP_SUPPORT 605 if (await_reply (AWAIT_BOOTP, 0, NULL, timeout)) 606 { 607 network_ready = 1; 608 return 1; 609 } 610 #else /* ! NO_DHCP_SUPPORT */ 611 if (await_reply (AWAIT_BOOTP, 0, NULL, timeout)) 612 { 613 if (dhcp_reply != DHCPOFFER) 614 { 615 network_ready = 1; 616 return 1; 617 } 618 619 dhcp_reply = 0; 620 #ifdef DEBUG 621 etherboot_printf ("bp_op = %d\n", (int) ip.bp.bp_op); 622 etherboot_printf ("bp_htype = %d\n", (int) ip.bp.bp_htype); 623 etherboot_printf ("bp_hlen = %d\n", (int) ip.bp.bp_hlen); 624 etherboot_printf ("bp_xid = %d\n", (int) ip.bp.bp_xid); 625 etherboot_printf ("bp_hwaddr = %!\n", ip.bp.bp_hwaddr); 626 etherboot_printf ("bp_hops = %d\n", (int) ip.bp.bp_hops); 627 etherboot_printf ("bp_secs = %d\n", (int) ip.bp.bp_hwaddr); 628 #endif 629 grub_memmove (ip.bp.bp_vend, rfc1533_cookie, sizeof rfc1533_cookie); 630 grub_memmove (ip.bp.bp_vend + sizeof rfc1533_cookie, 631 dhcprequest, sizeof dhcprequest); 632 grub_memmove (ip.bp.bp_vend + sizeof rfc1533_cookie 633 + sizeof dhcprequest, 634 rfc1533_end, sizeof rfc1533_end); 635 grub_memmove (ip.bp.bp_vend + 9, (char *) &dhcp_server, 636 sizeof (in_addr)); 637 grub_memmove (ip.bp.bp_vend + 15, (char *) &dhcp_addr, 638 sizeof (in_addr)); 639 #ifdef DEBUG 640 grub_printf ("errnum = %d\n", errnum); 641 #endif 642 for (reqretry = 0; reqretry < MAX_BOOTP_RETRIES;) 643 { 644 int ret; 645 #ifdef DEBUG 646 grub_printf ("reqretry = %d\n", reqretry); 647 #endif 648 649 ret = udp_transmit (IP_BROADCAST, BOOTP_CLIENT, BOOTP_SERVER, 650 sizeof (struct bootpip_t), &ip); 651 if (! ret) 652 grub_printf ("udp_transmit failed.\n"); 653 654 dhcp_reply = 0; 655 timeout = rfc2131_sleep_interval (TIMEOUT, reqretry++); 656 if (await_reply (AWAIT_BOOTP, 0, NULL, timeout)) 657 if (dhcp_reply == DHCPACK) 658 { 659 network_ready = 1; 660 return 1; 661 } 662 663 #ifdef DEBUG 664 grub_printf ("dhcp_reply = %d\n", dhcp_reply); 665 #endif 666 667 if (ip_abort) 668 return 0; 669 } 670 } 671 #endif /* ! NO_DHCP_SUPPORT */ 672 673 if (ip_abort) 674 return 0; 675 676 ip.bp.bp_secs = htons ((currticks () - starttime) / TICKS_PER_SEC); 677 } 678 679 /* Timeout. */ 680 return 0; 681 } 682 683 /************************************************************************** 684 UDPCHKSUM - Checksum UDP Packet (one of the rare cases when assembly is 685 actually simpler...) 686 RETURNS: checksum, 0 on checksum error. This 687 allows for using the same routine for RX and TX summing: 688 RX if (packet->udp.chksum && udpchksum(packet)) 689 error("checksum error"); 690 TX packet->udp.chksum=0; 691 if (0==(packet->udp.chksum=udpchksum(packet))) 692 packet->upd.chksum=0xffff; 693 **************************************************************************/ 694 static inline void 695 dosum (unsigned short *start, unsigned int len, unsigned short *sum) 696 { 697 __asm__ __volatile__ 698 ("clc\n" 699 "1:\tlodsw\n\t" 700 "xchg %%al,%%ah\n\t" /* convert to host byte order */ 701 "adcw %%ax,%0\n\t" /* add carry of previous iteration */ 702 "loop 1b\n\t" 703 "adcw $0,%0" /* add carry of last iteration */ 704 : "=b" (*sum), "=S"(start), "=c"(len) 705 : "0"(*sum), "1"(start), "2"(len) 706 : "ax", "cc" 707 ); 708 } 709 710 /* UDP sum: 711 * proto, src_ip, dst_ip, udp_dport, udp_sport, 2*udp_len, payload 712 */ 713 static unsigned short 714 udpchksum (struct iphdr *packet) 715 { 716 int len = ntohs (packet->len); 717 unsigned short rval; 718 719 /* add udplength + protocol number */ 720 rval = (len - sizeof (struct iphdr)) + IP_UDP; 721 722 /* pad to an even number of bytes */ 723 if (len % 2) { 724 ((char *) packet)[len++] = 0; 725 } 726 727 /* sum over src/dst ipaddr + udp packet */ 728 len -= (char *) &packet->src - (char *) packet; 729 dosum ((unsigned short *) &packet->src, len >> 1, &rval); 730 731 /* take one's complement */ 732 return ~rval; 733 } 734 735 /************************************************************************** 736 AWAIT_REPLY - Wait until we get a response for our request 737 **************************************************************************/ 738 int 739 await_reply (int type, int ival, void *ptr, int timeout) 740 { 741 unsigned long time; 742 struct iphdr *ip; 743 struct udphdr *udp; 744 struct arprequest *arpreply; 745 struct bootp_t *bootpreply; 746 unsigned short ptype; 747 unsigned int protohdrlen = (ETH_HLEN + sizeof (struct iphdr) 748 + sizeof (struct udphdr)); 749 750 /* Clear the abort flag. */ 751 ip_abort = 0; 752 753 time = timeout + currticks (); 754 /* The timeout check is done below. The timeout is only checked if 755 * there is no packet in the Rx queue. This assumes that eth_poll() 756 * needs a negligible amount of time. */ 757 for (;;) 758 { 759 if (eth_poll ()) 760 { 761 /* We have something! */ 762 763 /* Check for ARP - No IP hdr. */ 764 if (nic.packetlen >= ETH_HLEN) 765 { 766 ptype = (((unsigned short) nic.packet[12]) << 8 767 | ((unsigned short) nic.packet[13])); 768 } 769 else 770 /* What else could we do with it? */ 771 continue; 772 773 if (nic.packetlen >= ETH_HLEN + sizeof (struct arprequest) 774 && ptype == ARP) 775 { 776 unsigned long tmp; 777 778 arpreply = (struct arprequest *) &nic.packet[ETH_HLEN]; 779 780 if (arpreply->opcode == htons (ARP_REPLY) 781 && ! grub_memcmp (arpreply->sipaddr, ptr, sizeof (in_addr)) 782 && type == AWAIT_ARP) 783 { 784 grub_memmove ((char *) arptable[ival].node, 785 arpreply->shwaddr, 786 ETH_ALEN); 787 return 1; 788 } 789 790 grub_memmove ((char *) &tmp, arpreply->tipaddr, 791 sizeof (in_addr)); 792 793 if (arpreply->opcode == htons (ARP_REQUEST) 794 && tmp == arptable[ARP_CLIENT].ipaddr.s_addr) 795 { 796 arpreply->opcode = htons (ARP_REPLY); 797 grub_memmove (arpreply->tipaddr, arpreply->sipaddr, 798 sizeof (in_addr)); 799 grub_memmove (arpreply->thwaddr, (char *) arpreply->shwaddr, 800 ETH_ALEN); 801 grub_memmove (arpreply->sipaddr, 802 (char *) &arptable[ARP_CLIENT].ipaddr, 803 sizeof (in_addr)); 804 grub_memmove (arpreply->shwaddr, 805 arptable[ARP_CLIENT].node, 806 ETH_ALEN); 807 eth_transmit (arpreply->thwaddr, ARP, 808 sizeof (struct arprequest), 809 arpreply); 810 #ifdef MDEBUG 811 grub_memmove (&tmp, arpreply->tipaddr, sizeof (in_addr)); 812 etherboot_printf ("Sent ARP reply to: %@\n", tmp); 813 #endif /* MDEBUG */ 814 } 815 816 continue; 817 } 818 819 if (type == AWAIT_QDRAIN) 820 continue; 821 822 /* Check for RARP - No IP hdr. */ 823 if (type == AWAIT_RARP 824 && nic.packetlen >= ETH_HLEN + sizeof (struct arprequest) 825 && ptype == RARP) 826 { 827 arpreply = (struct arprequest *) &nic.packet[ETH_HLEN]; 828 829 if (arpreply->opcode == htons (RARP_REPLY) 830 && ! grub_memcmp (arpreply->thwaddr, ptr, ETH_ALEN)) 831 { 832 grub_memmove ((char *) arptable[ARP_SERVER].node, 833 arpreply->shwaddr, ETH_ALEN); 834 grub_memmove ((char *) &arptable[ARP_SERVER].ipaddr, 835 arpreply->sipaddr, sizeof (in_addr)); 836 grub_memmove ((char *) &arptable[ARP_CLIENT].ipaddr, 837 arpreply->tipaddr, sizeof (in_addr)); 838 return 1; 839 } 840 841 continue; 842 } 843 844 /* Anything else has IP header. */ 845 if (nic.packetlen < protohdrlen || ptype != IP) 846 continue; 847 848 ip = (struct iphdr *) &nic.packet[ETH_HLEN]; 849 if (ip->verhdrlen != 0x45 850 || ipchksum ((unsigned short *) ip, sizeof (struct iphdr)) 851 || ip->protocol != IP_UDP) 852 continue; 853 854 /* 855 - Till Straumann <Till.Straumann (at) TU-Berlin.de> 856 added udp checksum (safer on a wireless link) 857 added fragmentation check: I had a corrupted image 858 in memory due to fragmented TFTP packets - took me 859 3 days to find the cause for this :-( 860 */ 861 862 /* If More Fragments bit and Fragment Offset field 863 are non-zero then packet is fragmented */ 864 if (ip->frags & htons(0x3FFF)) 865 { 866 grub_printf ("ALERT: got a fragmented packet - reconfigure your server\n"); 867 continue; 868 } 869 870 udp = (struct udphdr *) &nic.packet[(ETH_HLEN 871 + sizeof (struct iphdr))]; 872 if (udp->chksum && udpchksum (ip)) 873 { 874 grub_printf ("UDP checksum error\n"); 875 continue; 876 } 877 878 /* BOOTP ? */ 879 bootpreply = (struct bootp_t *) 880 &nic.packet[(ETH_HLEN + sizeof (struct iphdr) 881 + sizeof (struct udphdr))]; 882 if (type == AWAIT_BOOTP 883 #ifdef NO_DHCP_SUPPORT 884 && (nic.packetlen 885 >= (ETH_HLEN + sizeof (struct bootp_t) - BOOTP_VENDOR_LEN)) 886 #else 887 && (nic.packetlen 888 >= (ETH_HLEN + sizeof (struct bootp_t) - DHCP_OPT_LEN)) 889 #endif /* ! NO_DHCP_SUPPORT */ 890 && udp->dest == htons (BOOTP_CLIENT) 891 && bootpreply->bp_op == BOOTP_REPLY 892 && bootpreply->bp_xid == xid 893 && (! grub_memcmp (broadcast, bootpreply->bp_hwaddr, ETH_ALEN) 894 || ! grub_memcmp (arptable[ARP_CLIENT].node, 895 bootpreply->bp_hwaddr, ETH_ALEN))) 896 { 897 #ifdef DEBUG 898 grub_printf ("BOOTP packet was received.\n"); 899 #endif 900 arptable[ARP_CLIENT].ipaddr.s_addr 901 = bootpreply->bp_yiaddr.s_addr; 902 #ifndef NO_DHCP_SUPPORT 903 dhcp_addr.s_addr = bootpreply->bp_yiaddr.s_addr; 904 #ifdef DEBUG 905 etherboot_printf ("dhcp_addr = %@\n", dhcp_addr.s_addr); 906 #endif 907 #endif /* ! NO_DHCP_SUPPORT */ 908 netmask = default_netmask (); 909 arptable[ARP_SERVER].ipaddr.s_addr 910 = bootpreply->bp_siaddr.s_addr; 911 /* Kill arp. */ 912 grub_memset (arptable[ARP_SERVER].node, 0, ETH_ALEN); 913 arptable[ARP_GATEWAY].ipaddr.s_addr 914 = bootpreply->bp_giaddr.s_addr; 915 /* Kill arp. */ 916 grub_memset (arptable[ARP_GATEWAY].node, 0, ETH_ALEN); 917 918 grub_memmove ((char *) BOOTP_DATA_ADDR, (char *) bootpreply, 919 sizeof (struct bootpd_t)); 920 #ifdef NO_DHCP_SUPPORT 921 decode_rfc1533 (BOOTP_DATA_ADDR->bootp_reply.bp_vend, 922 0, BOOTP_VENDOR_LEN + MAX_BOOTP_EXTLEN, 1); 923 #else 924 decode_rfc1533 (BOOTP_DATA_ADDR->bootp_reply.bp_vend, 925 0, DHCP_OPT_LEN + MAX_BOOTP_EXTLEN, 1); 926 #endif /* ! NO_DHCP_SUPPORT */ 927 928 return 1; 929 } 930 931 /* TFTP ? */ 932 if (type == AWAIT_TFTP && ntohs (udp->dest) == ival) 933 return 1; 934 } 935 else 936 { 937 /* Check for abort key only if the Rx queue is empty - 938 * as long as we have something to process, don't 939 * assume that something failed. It is unlikely that 940 * we have no processing time left between packets. */ 941 if (checkkey () != -1 && ASCII_CHAR (getkey ()) == CTRL_C) 942 { 943 ip_abort = 1; 944 return 0; 945 } 946 947 /* Do the timeout after at least a full queue walk. */ 948 if ((timeout == 0) || (currticks() > time)) 949 { 950 break; 951 } 952 } 953 } 954 955 return 0; 956 } 957 958 /************************************************************************** 959 DECODE_RFC1533 - Decodes RFC1533 header 960 **************************************************************************/ 961 int 962 decode_rfc1533 (unsigned char *p, int block, int len, int eof) 963 { 964 static unsigned char *extdata = NULL, *extend = NULL; 965 unsigned char *extpath = NULL; 966 unsigned char *endp; 967 968 if (block == 0) 969 { 970 end_of_rfc1533 = NULL; 971 vendorext_isvalid = 0; 972 973 if (grub_memcmp (p, rfc1533_cookie, 4)) 974 /* no RFC 1533 header found */ 975 return 0; 976 977 p += 4; 978 endp = p + len; 979 } 980 else 981 { 982 if (block == 1) 983 { 984 if (grub_memcmp (p, rfc1533_cookie, 4)) 985 /* no RFC 1533 header found */ 986 return 0; 987 988 p += 4; 989 len -= 4; 990 } 991 992 if (extend + len 993 <= ((unsigned char *) 994 &(BOOTP_DATA_ADDR->bootp_extension[MAX_BOOTP_EXTLEN]))) 995 { 996 grub_memmove (extend, p, len); 997 extend += len; 998 } 999 else 1000 { 1001 grub_printf ("Overflow in vendor data buffer! Aborting...\n"); 1002 *extdata = RFC1533_END; 1003 return 0; 1004 } 1005 1006 p = extdata; 1007 endp = extend; 1008 } 1009 1010 if (! eof) 1011 return -1; 1012 1013 while (p < endp) 1014 { 1015 unsigned char c = *p; 1016 1017 if (c == RFC1533_PAD) 1018 { 1019 p++; 1020 continue; 1021 } 1022 else if (c == RFC1533_END) 1023 { 1024 end_of_rfc1533 = endp = p; 1025 continue; 1026 } 1027 else if (c == RFC1533_NETMASK) 1028 { 1029 grub_memmove ((char *) &netmask, p + 2, sizeof (in_addr)); 1030 } 1031 else if (c == RFC1533_GATEWAY) 1032 { 1033 /* This is a little simplistic, but it will 1034 usually be sufficient. 1035 Take only the first entry. */ 1036 if (TAG_LEN (p) >= sizeof (in_addr)) 1037 grub_memmove ((char *) &arptable[ARP_GATEWAY].ipaddr, p + 2, 1038 sizeof (in_addr)); 1039 } 1040 else if (c == RFC1533_EXTENSIONPATH) 1041 extpath = p; 1042 #ifndef NO_DHCP_SUPPORT 1043 else if (c == RFC2132_MSG_TYPE) 1044 { 1045 dhcp_reply = *(p + 2); 1046 } 1047 else if (c == RFC2132_SRV_ID) 1048 { 1049 grub_memmove ((char *) &dhcp_server, p + 2, sizeof (in_addr)); 1050 #ifdef DEBUG 1051 etherboot_printf ("dhcp_server = %@\n", dhcp_server.s_addr); 1052 #endif 1053 } 1054 #endif /* ! NO_DHCP_SUPPORT */ 1055 else if (c == RFC1533_VENDOR_MAGIC 1056 && TAG_LEN(p) >= 6 1057 && ! grub_memcmp (p + 2, vendorext_magic, 4) 1058 && p[6] == RFC1533_VENDOR_MAJOR) 1059 vendorext_isvalid++; 1060 /* GRUB now handles its own tag. Get the name of a configuration 1061 file from the network. Cool... */ 1062 else if (c == RFC1533_VENDOR_CONFIGFILE) 1063 { 1064 int l = TAG_LEN (p); 1065 1066 /* Eliminate the trailing NULs according to RFC 2132. */ 1067 while (*(p + 2 + l - 1) == '\000' && l > 0) 1068 l--; 1069 1070 /* XXX: Should check if LEN is less than the maximum length 1071 of CONFIG_FILE. This kind of robustness will be a goal 1072 in GRUB 1.0. */ 1073 grub_memmove (config_file, p + 2, l); 1074 config_file[l] = 0; 1075 } 1076 1077 p += TAG_LEN (p) + 2; 1078 } 1079 1080 extdata = extend = endp; 1081 1082 /* Perhaps we can eliminate this because we doesn't require so 1083 much information, but I leave this alone. */ 1084 if (block == 0 && extpath != NULL) 1085 { 1086 char fname[64]; 1087 int fnamelen = TAG_LEN (extpath); 1088 1089 while (*(extpath + 2 + fnamelen - 1) == '\000' && fnamelen > 0) 1090 fnamelen--; 1091 1092 if (fnamelen + 1 > sizeof (fname)) 1093 { 1094 grub_printf ("Too long file name for Extensions Path\n"); 1095 return 0; 1096 } 1097 else if (! fnamelen) 1098 { 1099 grub_printf ("Empty file name for Extensions Path\n"); 1100 return 0; 1101 } 1102 1103 grub_memmove (fname, extpath + 2, fnamelen); 1104 fname[fnamelen] = '\000'; 1105 grub_printf ("Loading BOOTP-extension file: %s\n", fname); 1106 tftp (fname, decode_rfc1533); 1107 } 1108 1109 /* Proceed with next block. */ 1110 return -1; 1111 } 1112 1113 /************************************************************************** 1114 IPCHKSUM - Checksum IP Header 1115 **************************************************************************/ 1116 static unsigned short 1117 ipchksum (unsigned short *ip, int len) 1118 { 1119 unsigned long sum = 0; 1120 len >>= 1; 1121 while (len--) 1122 { 1123 sum += *(ip++); 1124 if (sum > 0xFFFF) 1125 sum -= 0xFFFF; 1126 } 1127 return (~sum) & 0x0000FFFF; 1128 } 1129 1130 #define TWO_SECOND_DIVISOR (2147483647l/TICKS_PER_SEC) 1131 1132 /************************************************************************** 1133 RFC2131_SLEEP_INTERVAL - sleep for expotentially longer times 1134 **************************************************************************/ 1135 long 1136 rfc2131_sleep_interval (int base, int exp) 1137 { 1138 static long seed = 0; 1139 long q; 1140 unsigned long tmo; 1141 1142 #ifdef BACKOFF_LIMIT 1143 if (exp > BACKOFF_LIMIT) 1144 exp = BACKOFF_LIMIT; 1145 #endif 1146 if (!seed) 1147 /* Initialize linear congruential generator */ 1148 seed = (currticks () + *((long *) &arptable[ARP_CLIENT].node) 1149 + ((short *) arptable[ARP_CLIENT].node)[2]); 1150 /* simplified version of the LCG given in Bruce Schneier's 1151 "Applied Cryptography" */ 1152 q = seed / 53668; 1153 if ((seed = 40014 * (seed - 53668 * q) - 12211 *q ) < 0) 1154 seed += 2147483563L; 1155 tmo = (base << exp) + (TICKS_PER_SEC - (seed / TWO_SECOND_DIVISOR)); 1156 return tmo; 1157 } 1158 1159 /************************************************************************** 1160 CLEANUP - shut down networking 1161 **************************************************************************/ 1162 void 1163 cleanup_net (void) 1164 { 1165 if (network_ready) 1166 { 1167 /* Stop receiving packets. */ 1168 eth_disable (); 1169 network_ready = 0; 1170 } 1171 } 1172