1 /************************************************************************** 2 Etherboot - Network Bootstrap Program 3 4 Literature dealing with the network protocols: 5 ARP - RFC826 6 RARP - RFC903 7 IP - RFC791 8 UDP - RFC768 9 BOOTP - RFC951, RFC2132 (vendor extensions) 10 DHCP - RFC2131, RFC2132 (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 15 16 **************************************************************************/ 17 #include "etherboot.h" 18 #include "grub.h" 19 #include "nic.h" 20 #include "elf.h" /* FOR EM_CURRENT */ 21 #include "bootp.h" 22 #include "if_arp.h" 23 #include "tftp.h" 24 #include "timer.h" 25 #include "ip.h" 26 #include "udp.h" 27 28 /* Currently no other module uses rom, but it is available */ 29 struct rom_info rom; 30 struct arptable_t arptable[MAX_ARP]; 31 #ifdef MULTICAST_LEVEL2 32 unsigned long last_igmpv1 = 0; 33 struct igmptable_t igmptable[MAX_IGMP]; 34 #endif 35 static unsigned long netmask; 36 /* Used by nfs.c */ 37 char *hostname = ""; 38 int hostnamelen = 0; 39 /* Used by fsys_tftp.c */ 40 int use_bios_pxe = 0; 41 static uint32_t xid; 42 static unsigned char *end_of_rfc1533 = NULL; 43 static const unsigned char broadcast[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; 44 static const in_addr zeroIP = { 0L }; 45 static char rfc1533_venddata[MAX_RFC1533_VENDLEN]; 46 static unsigned char rfc1533_cookie[4] = { RFC1533_COOKIE }; 47 static unsigned char rfc1533_cookie_bootp[5] = { RFC1533_COOKIE, RFC1533_END }; 48 static unsigned char rfc1533_cookie_dhcp[] = { RFC1533_COOKIE }; 49 static int dhcp_reply; 50 static in_addr dhcp_server = { 0L }; 51 static in_addr dhcp_addr = { 0L }; 52 53 static const unsigned char dhcpdiscover[] = { 54 RFC2132_MSG_TYPE, 1, DHCPDISCOVER, 55 RFC2132_MAX_SIZE, 2, /* request as much as we can */ 56 ETH_MAX_MTU / 256, ETH_MAX_MTU % 256, 57 /* Vendor class identifier */ 58 #ifdef SOLARIS_NETBOOT 59 RFC2132_VENDOR_CLASS_ID,32,'P','X','E','C','l','i','e','n','t',':', 60 'A','r','c','h',':','0','0','0','0','0',':','U','N','D','I',':', 61 '0','0','2','0','0','1', 62 #else 63 RFC2132_VENDOR_CLASS_ID, 10, 'G', 'R', 'U', 'B', 'C', 'l', 'i', 'e', 'n', 't', 64 #endif 65 RFC2132_PARAM_LIST, 4, RFC1533_NETMASK, RFC1533_GATEWAY, 66 RFC1533_HOSTNAME, RFC1533_EXTENSIONPATH, RFC1533_END 67 }; 68 static const unsigned char dhcprequest [] = { 69 RFC2132_MSG_TYPE,1,DHCPREQUEST, 70 RFC2132_SRV_ID,4,0,0,0,0, 71 RFC2132_REQ_ADDR,4,0,0,0,0, 72 RFC2132_MAX_SIZE,2, /* request as much as we can */ 73 ETH_MAX_MTU / 256, ETH_MAX_MTU % 256, 74 /* Vendor class identifier */ 75 #ifdef SOLARIS_NETBOOT 76 RFC2132_VENDOR_CLASS_ID,32,'P','X','E','C','l','i','e','n','t',':', 77 'A','r','c','h',':','0','0','0','0','0',':','U','N','D','I',':', 78 '0','0','2','0','0','1', 79 #else 80 RFC2132_VENDOR_CLASS_ID, 10, 'G', 'R', 'U', 'B', 'C', 'l', 'i', 'e', 'n', 't', 81 #endif 82 RFC2132_PARAM_LIST, 83 /* 4 standard + 2 vendortags */ 84 4 + 2, 85 /* Standard parameters */ 86 RFC1533_NETMASK, RFC1533_GATEWAY, 87 RFC1533_HOSTNAME, RFC1533_EXTENSIONPATH, 88 /* Etherboot vendortags */ 89 RFC1533_VENDOR_MAGIC, 90 RFC1533_VENDOR_CONFIGFILE, 91 RFC1533_END 92 }; 93 94 /* See nic.h */ 95 int user_abort = 0; 96 int network_ready = 0; 97 98 #ifdef REQUIRE_VCI_ETHERBOOT 99 int vci_etherboot; 100 #endif 101 102 static void update_network_configuration(void); 103 104 static int dummy(void *unused __unused) 105 { 106 return (0); 107 } 108 109 /* Careful. We need an aligned buffer to avoid problems on machines 110 * that care about alignment. To trivally align the ethernet data 111 * (the ip hdr and arp requests) we offset the packet by 2 bytes. 112 * leaving the ethernet data 16 byte aligned. Beyond this 113 * we use memmove but this makes the common cast simple and fast. 114 */ 115 static char packet[ETH_FRAME_LEN + ETH_DATA_ALIGN] __aligned; 116 117 struct nic nic = 118 { 119 { 120 0, /* dev.disable */ 121 { 122 0, 123 0, 124 PCI_BUS_TYPE, 125 }, /* dev.devid */ 126 0, /* index */ 127 0, /* type */ 128 PROBE_FIRST, /* how_pobe */ 129 PROBE_NONE, /* to_probe */ 130 0, /* failsafe */ 131 0, /* type_index */ 132 {}, /* state */ 133 }, 134 (int (*)(struct nic *, int))dummy, /* poll */ 135 (void (*)(struct nic *, const char *, 136 unsigned int, unsigned int, 137 const char *))dummy, /* transmit */ 138 (void (*)(struct nic *, irq_action_t))dummy, /* irq */ 139 0, /* flags */ 140 &rom, /* rom_info */ 141 arptable[ARP_CLIENT].node, /* node_addr */ 142 packet + ETH_DATA_ALIGN, /* packet */ 143 0, /* packetlen */ 144 0, /* ioaddr */ 145 0, /* irqno */ 146 NULL, /* priv_data */ 147 }; 148 149 150 151 int grub_eth_probe(void) 152 { 153 static int probed = 0; 154 struct dev *dev; 155 156 EnterFunction("grub_eth_probe"); 157 158 if (probed) 159 return 1; 160 161 network_ready = 0; 162 grub_memset((char *)arptable, 0, MAX_ARP * sizeof(struct arptable_t)); 163 dev = &nic.dev; 164 dev->how_probe = -1; 165 dev->type = NIC_DRIVER; 166 dev->failsafe = 1; 167 rom = *((struct rom_info *)ROM_INFO_LOCATION); 168 169 probed = (eth_probe(dev) == PROBE_WORKED); 170 171 LeaveFunction("grub_eth_probe"); 172 return probed; 173 } 174 175 int eth_probe(struct dev *dev) 176 { 177 return probe(dev); 178 } 179 180 int eth_poll(int retrieve) 181 { 182 return ((*nic.poll)(&nic, retrieve)); 183 } 184 185 void eth_transmit(const char *d, unsigned int t, unsigned int s, const void *p) 186 { 187 (*nic.transmit)(&nic, d, t, s, p); 188 if (t == IP) twiddle(); 189 } 190 191 void eth_disable(void) 192 { 193 #ifdef MULTICAST_LEVEL2 194 int i; 195 for(i = 0; i < MAX_IGMP; i++) { 196 leave_group(i); 197 } 198 #endif 199 disable(&nic.dev); 200 } 201 202 void eth_irq (irq_action_t action) 203 { 204 (*nic.irq)(&nic,action); 205 } 206 207 /************************************************************************** 208 IPCHKSUM - Checksum IP Header 209 **************************************************************************/ 210 uint16_t ipchksum(const void *data, unsigned long length) 211 { 212 unsigned long sum; 213 unsigned long i; 214 const uint8_t *ptr; 215 216 /* In the most straight forward way possible, 217 * compute an ip style checksum. 218 */ 219 sum = 0; 220 ptr = data; 221 for(i = 0; i < length; i++) { 222 unsigned long value; 223 value = ptr[i]; 224 if (i & 1) { 225 value <<= 8; 226 } 227 /* Add the new value */ 228 sum += value; 229 /* Wrap around the carry */ 230 if (sum > 0xFFFF) { 231 sum = (sum + (sum >> 16)) & 0xFFFF; 232 } 233 } 234 return (~cpu_to_le16(sum)) & 0xFFFF; 235 } 236 237 uint16_t add_ipchksums(unsigned long offset, uint16_t sum, uint16_t new) 238 { 239 unsigned long checksum; 240 sum = ~sum & 0xFFFF; 241 new = ~new & 0xFFFF; 242 if (offset & 1) { 243 /* byte swap the sum if it came from an odd offset 244 * since the computation is endian independant this 245 * works. 246 */ 247 new = bswap_16(new); 248 } 249 checksum = sum + new; 250 if (checksum > 0xFFFF) { 251 checksum -= 0xFFFF; 252 } 253 return (~checksum) & 0xFFFF; 254 } 255 256 /************************************************************************** 257 DEFAULT_NETMASK - Return default netmask for IP address 258 **************************************************************************/ 259 static inline unsigned long default_netmask(void) 260 { 261 int net = ntohl(arptable[ARP_CLIENT].ipaddr.s_addr) >> 24; 262 if (net <= 127) 263 return(htonl(0xff000000)); 264 else if (net < 192) 265 return(htonl(0xffff0000)); 266 else 267 return(htonl(0xffffff00)); 268 } 269 270 /************************************************************************** 271 IP_TRANSMIT - Send an IP datagram 272 **************************************************************************/ 273 static int await_arp(int ival, void *ptr, 274 unsigned short ptype, struct iphdr *ip __unused, struct udphdr *udp __unused) 275 { 276 struct arprequest *arpreply; 277 if (ptype != ARP) 278 return 0; 279 if (nic.packetlen < ETH_HLEN + sizeof(struct arprequest)) 280 return 0; 281 arpreply = (struct arprequest *)&nic.packet[ETH_HLEN]; 282 283 if (arpreply->opcode != htons(ARP_REPLY)) 284 return 0; 285 if (memcmp(arpreply->sipaddr, ptr, sizeof(in_addr)) != 0) 286 return 0; 287 memcpy(arptable[ival].node, arpreply->shwaddr, ETH_ALEN); 288 return 1; 289 } 290 291 int ip_transmit(int len, const void *buf) 292 { 293 unsigned long destip; 294 struct iphdr *ip; 295 struct arprequest arpreq; 296 int arpentry, i; 297 int retry; 298 299 ip = (struct iphdr *)buf; 300 destip = ip->dest.s_addr; 301 if (destip == IP_BROADCAST) { 302 eth_transmit(broadcast, IP, len, buf); 303 #ifdef MULTICAST_LEVEL1 304 } else if ((destip & htonl(MULTICAST_MASK)) == htonl(MULTICAST_NETWORK)) { 305 unsigned char multicast[6]; 306 unsigned long hdestip; 307 hdestip = ntohl(destip); 308 multicast[0] = 0x01; 309 multicast[1] = 0x00; 310 multicast[2] = 0x5e; 311 multicast[3] = (hdestip >> 16) & 0x7; 312 multicast[4] = (hdestip >> 8) & 0xff; 313 multicast[5] = hdestip & 0xff; 314 eth_transmit(multicast, IP, len, buf); 315 #endif 316 } else { 317 if (((destip & netmask) != 318 (arptable[ARP_CLIENT].ipaddr.s_addr & netmask)) && 319 arptable[ARP_GATEWAY].ipaddr.s_addr) 320 destip = arptable[ARP_GATEWAY].ipaddr.s_addr; 321 for(arpentry = 0; arpentry<MAX_ARP; arpentry++) 322 if (arptable[arpentry].ipaddr.s_addr == destip) break; 323 if (arpentry == MAX_ARP) { 324 printf("%@ is not in my arp table!\n", destip); 325 return(0); 326 } 327 for (i = 0; i < ETH_ALEN; i++) 328 if (arptable[arpentry].node[i]) 329 break; 330 if (i == ETH_ALEN) { /* Need to do arp request */ 331 arpreq.hwtype = htons(1); 332 arpreq.protocol = htons(IP); 333 arpreq.hwlen = ETH_ALEN; 334 arpreq.protolen = 4; 335 arpreq.opcode = htons(ARP_REQUEST); 336 memcpy(arpreq.shwaddr, arptable[ARP_CLIENT].node, ETH_ALEN); 337 memcpy(arpreq.sipaddr, &arptable[ARP_CLIENT].ipaddr, sizeof(in_addr)); 338 memset(arpreq.thwaddr, 0, ETH_ALEN); 339 memcpy(arpreq.tipaddr, &destip, sizeof(in_addr)); 340 for (retry = 1; retry <= MAX_ARP_RETRIES; retry++) { 341 long timeout; 342 eth_transmit(broadcast, ARP, sizeof(arpreq), 343 &arpreq); 344 timeout = rfc2131_sleep_interval(TIMEOUT, retry); 345 if (await_reply(await_arp, arpentry, 346 arpreq.tipaddr, timeout)) goto xmit; 347 } 348 return(0); 349 } 350 xmit: 351 eth_transmit(arptable[arpentry].node, IP, len, buf); 352 } 353 return 1; 354 } 355 356 void build_ip_hdr(unsigned long destip, int ttl, int protocol, int option_len, 357 int len, const void *buf) 358 { 359 struct iphdr *ip; 360 ip = (struct iphdr *)buf; 361 ip->verhdrlen = 0x45; 362 ip->verhdrlen += (option_len/4); 363 ip->service = 0; 364 ip->len = htons(len); 365 ip->ident = 0; 366 ip->frags = 0; /* Should we set don't fragment? */ 367 ip->ttl = ttl; 368 ip->protocol = protocol; 369 ip->chksum = 0; 370 ip->src.s_addr = arptable[ARP_CLIENT].ipaddr.s_addr; 371 ip->dest.s_addr = destip; 372 ip->chksum = ipchksum(buf, sizeof(struct iphdr) + option_len); 373 } 374 375 static uint16_t udpchksum(struct iphdr *ip, struct udphdr *udp) 376 { 377 struct udp_pseudo_hdr pseudo; 378 uint16_t checksum; 379 380 /* Compute the pseudo header */ 381 pseudo.src.s_addr = ip->src.s_addr; 382 pseudo.dest.s_addr = ip->dest.s_addr; 383 pseudo.unused = 0; 384 pseudo.protocol = IP_UDP; 385 pseudo.len = udp->len; 386 387 /* Sum the pseudo header */ 388 checksum = ipchksum(&pseudo, 12); 389 390 /* Sum the rest of the udp packet */ 391 checksum = add_ipchksums(12, checksum, ipchksum(udp, ntohs(udp->len))); 392 return checksum; 393 } 394 395 396 void build_udp_hdr(unsigned long destip, 397 unsigned int srcsock, unsigned int destsock, int ttl, 398 int len, const void *buf) 399 { 400 struct iphdr *ip; 401 struct udphdr *udp; 402 ip = (struct iphdr *)buf; 403 build_ip_hdr(destip, ttl, IP_UDP, 0, len, buf); 404 udp = (struct udphdr *)((char *)buf + sizeof(struct iphdr)); 405 udp->src = htons(srcsock); 406 udp->dest = htons(destsock); 407 udp->len = htons(len - sizeof(struct iphdr)); 408 udp->chksum = 0; 409 if ((udp->chksum = udpchksum(ip, udp)) == 0) 410 udp->chksum = 0xffff; 411 } 412 413 414 /************************************************************************** 415 UDP_TRANSMIT - Send an UDP datagram 416 **************************************************************************/ 417 int udp_transmit(unsigned long destip, unsigned int srcsock, 418 unsigned int destsock, int len, const void *buf) 419 { 420 build_udp_hdr(destip, srcsock, destsock, 60, len, buf); 421 return ip_transmit(len, buf); 422 } 423 424 /************************************************************************** 425 QDRAIN - clear the nic's receive queue 426 **************************************************************************/ 427 static int await_qdrain(int ival __unused, void *ptr __unused, 428 unsigned short ptype __unused, 429 struct iphdr *ip __unused, struct udphdr *udp __unused) 430 { 431 return 0; 432 } 433 434 void rx_qdrain(void) 435 { 436 /* Clear out the Rx queue first. It contains nothing of interest, 437 * except possibly ARP requests from the DHCP/TFTP server. We use 438 * polling throughout Etherboot, so some time may have passed since we 439 * last polled the receive queue, which may now be filled with 440 * broadcast packets. This will cause the reply to the packets we are 441 * about to send to be lost immediately. Not very clever. */ 442 await_reply(await_qdrain, 0, NULL, 0); 443 } 444 445 /** 446 * rarp 447 * 448 * Get IP address by rarp. Just copy from etherboot 449 **/ 450 static int await_rarp(int ival, void *ptr, unsigned short ptype, 451 struct iphdr *ip, struct udphdr *udp) 452 { 453 struct arprequest *arpreply; 454 if (ptype != RARP) 455 return 0; 456 if (nic.packetlen < ETH_HLEN + sizeof(struct arprequest)) 457 return 0; 458 arpreply = (struct arprequest *)&nic.packet[ETH_HLEN]; 459 if (arpreply->opcode != htons(RARP_REPLY)) 460 return 0; 461 if (memcmp(arpreply->thwaddr, ptr, ETH_ALEN) == 0){ 462 memcpy(arptable[ARP_SERVER].node, arpreply->shwaddr, ETH_ALEN); 463 memcpy(&arptable[ARP_SERVER].ipaddr, arpreply->sipaddr, sizeof(in_addr)); 464 memcpy(&arptable[ARP_CLIENT].ipaddr, arpreply->tipaddr, sizeof(in_addr)); 465 memset(&arptable[ARP_GATEWAY].ipaddr, 0, sizeof(in_addr)); 466 return 1; 467 } 468 return 0; 469 } 470 471 int rarp(void) 472 { 473 int retry; 474 475 /* arp and rarp requests share the same packet structure. */ 476 struct arprequest rarpreq; 477 478 if(!grub_eth_probe()) 479 return 0; 480 network_ready = 0; 481 482 memset(&rarpreq, 0, sizeof(rarpreq)); 483 484 rarpreq.hwtype = htons(1); 485 rarpreq.protocol = htons(IP); 486 rarpreq.hwlen = ETH_ALEN; 487 rarpreq.protolen = 4; 488 rarpreq.opcode = htons(RARP_REQUEST); 489 memcpy(&rarpreq.shwaddr, arptable[ARP_CLIENT].node, ETH_ALEN); 490 /* sipaddr is already zeroed out */ 491 memcpy(&rarpreq.thwaddr, arptable[ARP_CLIENT].node, ETH_ALEN); 492 /* tipaddr is already zeroed out */ 493 494 for (retry = 0; retry < MAX_ARP_RETRIES; ++retry) { 495 long timeout; 496 eth_transmit(broadcast, RARP, sizeof(rarpreq), &rarpreq); 497 498 timeout = rfc2131_sleep_interval(TIMEOUT, retry); 499 if (await_reply(await_rarp, 0, rarpreq.shwaddr, timeout)) 500 break; 501 if (user_abort) 502 return 0; 503 } 504 505 if (retry == MAX_ARP_RETRIES) { 506 return (0); 507 } 508 509 network_ready = 1; 510 update_network_configuration(); 511 return (1); 512 } 513 514 /** 515 * bootp 516 * 517 * Get IP address by bootp, segregate from bootp in etherboot. 518 **/ 519 static int await_bootp(int ival __unused, void *ptr __unused, 520 unsigned short ptype __unused, struct iphdr *ip __unused, 521 struct udphdr *udp) 522 { 523 struct bootp_t *bootpreply; 524 int len; /* Length of vendor */ 525 526 if (!udp) { 527 return 0; 528 } 529 bootpreply = (struct bootp_t *) 530 &nic.packet[ETH_HLEN + sizeof(struct iphdr) + sizeof(struct udphdr)]; 531 len = nic.packetlen - (ETH_HLEN + sizeof(struct iphdr) + 532 sizeof(struct udphdr) + sizeof(struct bootp_t) - BOOTP_VENDOR_LEN); 533 if (len < 0) { 534 return 0; 535 } 536 if (udp->dest != htons(BOOTP_CLIENT)) 537 return 0; 538 if (bootpreply->bp_op != BOOTP_REPLY) 539 return 0; 540 if (bootpreply->bp_xid != xid) 541 return 0; 542 if (memcmp((char *)&bootpreply->bp_siaddr, (char *)&zeroIP, sizeof(in_addr)) == 0) 543 return 0; 544 if ((memcmp(broadcast, bootpreply->bp_hwaddr, ETH_ALEN) != 0) && 545 (memcmp(arptable[ARP_CLIENT].node, bootpreply->bp_hwaddr, ETH_ALEN) != 0)) { 546 return 0; 547 } 548 549 #ifdef SOLARIS_NETBOOT 550 /* fill in netinfo */ 551 dhcpack_length = len + sizeof (struct bootp_t) - BOOTP_VENDOR_LEN; 552 memcpy((char *)dhcpack_buf, (char *)bootpreply, dhcpack_length); 553 #endif 554 555 arptable[ARP_CLIENT].ipaddr.s_addr = bootpreply->bp_yiaddr.s_addr; 556 netmask = default_netmask(); 557 arptable[ARP_SERVER].ipaddr.s_addr = bootpreply->bp_siaddr.s_addr; 558 memset(arptable[ARP_SERVER].node, 0, ETH_ALEN); /* Kill arp */ 559 arptable[ARP_GATEWAY].ipaddr.s_addr = bootpreply->bp_giaddr.s_addr; 560 memset(arptable[ARP_GATEWAY].node, 0, ETH_ALEN); /* Kill arp */ 561 /* We don't care bootpreply->bp_file, it must be 'pxegrub':-) */ 562 memcpy((char *)rfc1533_venddata, (char *)(bootpreply->bp_vend), len); 563 decode_rfc1533(rfc1533_venddata, 0, len, 1); 564 return(1); 565 } 566 567 int bootp(void) 568 { 569 int retry; 570 struct bootpip_t ip; 571 unsigned long starttime; 572 573 EnterFunction("bootp"); 574 575 if(!grub_eth_probe()) 576 return 0; 577 network_ready = 0; 578 579 memset(&ip, 0, sizeof(struct bootpip_t)); 580 ip.bp.bp_op = BOOTP_REQUEST; 581 ip.bp.bp_htype = 1; 582 ip.bp.bp_hlen = ETH_ALEN; 583 starttime = currticks(); 584 /* Use lower 32 bits of node address, more likely to be 585 distinct than the time since booting */ 586 memcpy(&xid, &arptable[ARP_CLIENT].node[2], sizeof(xid)); 587 ip.bp.bp_xid = xid += htonl(starttime); 588 /* bp_secs defaults to zero */ 589 memcpy(ip.bp.bp_hwaddr, arptable[ARP_CLIENT].node, ETH_ALEN); 590 memcpy(ip.bp.bp_vend, rfc1533_cookie_bootp, sizeof(rfc1533_cookie_bootp)); /* request RFC-style options */ 591 592 for (retry = 0; retry < MAX_BOOTP_RETRIES; ) { 593 long timeout; 594 595 rx_qdrain(); 596 597 udp_transmit(IP_BROADCAST, BOOTP_CLIENT, BOOTP_SERVER, 598 sizeof(struct bootpip_t), &ip); 599 timeout = rfc2131_sleep_interval(TIMEOUT, retry++); 600 if (await_reply(await_bootp, 0, NULL, timeout)){ 601 network_ready = 1; 602 return(1); 603 } 604 if (user_abort) 605 return 0; 606 ip.bp.bp_secs = htons((currticks()-starttime)/TICKS_PER_SEC); 607 } 608 return(0); 609 } 610 611 /** 612 * dhcp 613 * 614 * Get IP address by dhcp, segregate from bootp in etherboot. 615 **/ 616 static int await_dhcp(int ival __unused, void *ptr __unused, 617 unsigned short ptype __unused, struct iphdr *ip __unused, 618 struct udphdr *udp) 619 { 620 struct dhcp_t *dhcpreply; 621 int len; 622 623 if (!udp) { 624 return 0; 625 } 626 dhcpreply = (struct dhcp_t *) 627 &nic.packet[ETH_HLEN + sizeof(struct iphdr) + sizeof(struct udphdr)]; 628 len = nic.packetlen - (ETH_HLEN + sizeof(struct iphdr) + 629 sizeof(struct udphdr) + sizeof(struct dhcp_t) - DHCP_OPT_LEN); 630 if (len < 0){ 631 return 0; 632 } 633 if (udp->dest != htons(BOOTP_CLIENT)) 634 return 0; 635 if (dhcpreply->bp_op != BOOTP_REPLY) 636 return 0; 637 if (dhcpreply->bp_xid != xid) 638 return 0; 639 if (memcmp((char *)&dhcpreply->bp_siaddr, (char *)&zeroIP, sizeof(in_addr)) == 0) 640 return 0; 641 if ((memcmp(broadcast, dhcpreply->bp_hwaddr, ETH_ALEN) != 0) && 642 (memcmp(arptable[ARP_CLIENT].node, dhcpreply->bp_hwaddr, ETH_ALEN) != 0)) { 643 return 0; 644 } 645 646 #ifdef SOLARIS_NETBOOT 647 /* fill in netinfo */ 648 dhcpack_length = len + sizeof (struct dhcp_t) - DHCP_OPT_LEN; 649 memcpy((char *)dhcpack_buf, (char *)dhcpreply, dhcpack_length); 650 #endif 651 652 arptable[ARP_CLIENT].ipaddr.s_addr = dhcpreply->bp_yiaddr.s_addr; 653 dhcp_addr.s_addr = dhcpreply->bp_yiaddr.s_addr; 654 netmask = default_netmask(); 655 arptable[ARP_SERVER].ipaddr.s_addr = dhcpreply->bp_siaddr.s_addr; 656 memset(arptable[ARP_SERVER].node, 0, ETH_ALEN); /* Kill arp */ 657 arptable[ARP_GATEWAY].ipaddr.s_addr = dhcpreply->bp_giaddr.s_addr; 658 memset(arptable[ARP_GATEWAY].node, 0, ETH_ALEN); /* Kill arp */ 659 /* We don't care bootpreply->bp_file. It must be 'pxegrub' */ 660 memcpy((char *)rfc1533_venddata, (char *)(dhcpreply->bp_vend), len); 661 decode_rfc1533(rfc1533_venddata, 0, len, 1); 662 return(1); 663 } 664 665 int dhcp(void) 666 { 667 int retry; 668 int reqretry; 669 struct dhcpip_t ip; 670 unsigned long starttime; 671 672 /* try bios pxe stack first */ 673 if (dhcp_undi()) 674 return 1; 675 676 if(!grub_eth_probe()) 677 return 0; 678 679 network_ready = 0; 680 681 memset(&ip, 0, sizeof(ip)); 682 ip.bp.bp_op = BOOTP_REQUEST; 683 ip.bp.bp_htype = 1; 684 ip.bp.bp_hlen = ETH_ALEN; 685 starttime = currticks(); 686 /* Use lower 32 bits of node address, more likely to be 687 distinct than the time since booting */ 688 memcpy(&xid, &arptable[ARP_CLIENT].node[2], sizeof(xid)); 689 ip.bp.bp_xid = xid += htonl(starttime); 690 memcpy(ip.bp.bp_hwaddr, arptable[ARP_CLIENT].node, ETH_ALEN); 691 memcpy(ip.bp.bp_vend, rfc1533_cookie_dhcp, sizeof rfc1533_cookie_dhcp); /* request RFC-style options */ 692 memcpy(ip.bp.bp_vend + sizeof rfc1533_cookie_dhcp, dhcpdiscover, sizeof dhcpdiscover); 693 694 for (retry = 0; retry < MAX_BOOTP_RETRIES; ) { 695 long timeout; 696 697 rx_qdrain(); 698 699 udp_transmit(IP_BROADCAST, BOOTP_CLIENT, BOOTP_SERVER, 700 sizeof(ip), &ip); 701 timeout = rfc2131_sleep_interval(TIMEOUT, retry++); 702 if (await_reply(await_dhcp, 0, NULL, timeout)) { 703 /* If not a DHCPOFFER then must be just a 704 BOOTP reply, be backward compatible with 705 BOOTP then. Jscott report a bug here, but I 706 don't know how it happened */ 707 if (dhcp_reply != DHCPOFFER){ 708 network_ready = 1; 709 return(1); 710 } 711 dhcp_reply = 0; 712 memcpy(ip.bp.bp_vend, rfc1533_cookie_dhcp, sizeof rfc1533_cookie_dhcp); 713 memcpy(ip.bp.bp_vend + sizeof rfc1533_cookie_dhcp, dhcprequest, sizeof dhcprequest); 714 /* Beware: the magic numbers 9 and 15 depend on 715 the layout of dhcprequest */ 716 memcpy(&ip.bp.bp_vend[9], &dhcp_server, sizeof(in_addr)); 717 memcpy(&ip.bp.bp_vend[15], &dhcp_addr, sizeof(in_addr)); 718 for (reqretry = 0; reqretry < MAX_BOOTP_RETRIES; ) { 719 udp_transmit(IP_BROADCAST, BOOTP_CLIENT, BOOTP_SERVER, 720 sizeof(ip), &ip); 721 dhcp_reply=0; 722 timeout = rfc2131_sleep_interval(TIMEOUT, reqretry++); 723 if (await_reply(await_dhcp, 0, NULL, timeout)) 724 if (dhcp_reply == DHCPACK){ 725 network_ready = 1; 726 return(1); 727 } 728 if (user_abort) 729 return 0; 730 } 731 } 732 if (user_abort) 733 return 0; 734 ip.bp.bp_secs = htons((currticks()-starttime)/TICKS_PER_SEC); 735 } 736 return(0); 737 } 738 739 #ifdef MULTICAST_LEVEL2 740 static void send_igmp_reports(unsigned long now) 741 { 742 int i; 743 for(i = 0; i < MAX_IGMP; i++) { 744 if (igmptable[i].time && (now >= igmptable[i].time)) { 745 struct igmp_ip_t igmp; 746 igmp.router_alert[0] = 0x94; 747 igmp.router_alert[1] = 0x04; 748 igmp.router_alert[2] = 0; 749 igmp.router_alert[3] = 0; 750 build_ip_hdr(igmptable[i].group.s_addr, 751 1, IP_IGMP, sizeof(igmp.router_alert), sizeof(igmp), &igmp); 752 igmp.igmp.type = IGMPv2_REPORT; 753 if (last_igmpv1 && 754 (now < last_igmpv1 + IGMPv1_ROUTER_PRESENT_TIMEOUT)) { 755 igmp.igmp.type = IGMPv1_REPORT; 756 } 757 igmp.igmp.response_time = 0; 758 igmp.igmp.chksum = 0; 759 igmp.igmp.group.s_addr = igmptable[i].group.s_addr; 760 igmp.igmp.chksum = ipchksum(&igmp.igmp, sizeof(igmp.igmp)); 761 ip_transmit(sizeof(igmp), &igmp); 762 #ifdef MDEBUG 763 printf("Sent IGMP report to: %@\n", igmp.igmp.group.s_addr); 764 #endif 765 /* Don't send another igmp report until asked */ 766 igmptable[i].time = 0; 767 } 768 } 769 } 770 771 static void process_igmp(struct iphdr *ip, unsigned long now) 772 { 773 struct igmp *igmp; 774 int i; 775 unsigned iplen = 0; 776 if (!ip || (ip->protocol == IP_IGMP) || 777 (nic.packetlen < sizeof(struct iphdr) + sizeof(struct igmp))) { 778 return; 779 } 780 iplen = (ip->verhdrlen & 0xf)*4; 781 igmp = (struct igmp *)&nic.packet[sizeof(struct iphdr)]; 782 if (ipchksum(igmp, ntohs(ip->len) - iplen) != 0) 783 return; 784 if ((igmp->type == IGMP_QUERY) && 785 (ip->dest.s_addr == htonl(GROUP_ALL_HOSTS))) { 786 unsigned long interval = IGMP_INTERVAL; 787 if (igmp->response_time == 0) { 788 last_igmpv1 = now; 789 } else { 790 interval = (igmp->response_time * TICKS_PER_SEC)/10; 791 } 792 793 #ifdef MDEBUG 794 printf("Received IGMP query for: %@\n", igmp->group.s_addr); 795 #endif 796 for(i = 0; i < MAX_IGMP; i++) { 797 uint32_t group = igmptable[i].group.s_addr; 798 if ((group == 0) || (group == igmp->group.s_addr)) { 799 unsigned long time; 800 time = currticks() + rfc1112_sleep_interval(interval, 0); 801 if (time < igmptable[i].time) { 802 igmptable[i].time = time; 803 } 804 } 805 } 806 } 807 if (((igmp->type == IGMPv1_REPORT) || (igmp->type == IGMPv2_REPORT)) && 808 (ip->dest.s_addr == igmp->group.s_addr)) { 809 #ifdef MDEBUG 810 printf("Received IGMP report for: %@\n", igmp->group.s_addr); 811 #endif 812 for(i = 0; i < MAX_IGMP; i++) { 813 if ((igmptable[i].group.s_addr == igmp->group.s_addr) && 814 igmptable[i].time != 0) { 815 igmptable[i].time = 0; 816 } 817 } 818 } 819 } 820 821 void leave_group(int slot) 822 { 823 /* Be very stupid and always send a leave group message if 824 * I have subscribed. Imperfect but it is standards 825 * compliant, easy and reliable to implement. 826 * 827 * The optimal group leave method is to only send leave when, 828 * we were the last host to respond to a query on this group, 829 * and igmpv1 compatibility is not enabled. 830 */ 831 if (igmptable[slot].group.s_addr) { 832 struct igmp_ip_t igmp; 833 igmp.router_alert[0] = 0x94; 834 igmp.router_alert[1] = 0x04; 835 igmp.router_alert[2] = 0; 836 igmp.router_alert[3] = 0; 837 build_ip_hdr(htonl(GROUP_ALL_HOSTS), 838 1, IP_IGMP, sizeof(igmp.router_alert), sizeof(igmp), &igmp); 839 igmp.igmp.type = IGMP_LEAVE; 840 igmp.igmp.response_time = 0; 841 igmp.igmp.chksum = 0; 842 igmp.igmp.group.s_addr = igmptable[slot].group.s_addr; 843 igmp.igmp.chksum = ipchksum(&igmp.igmp, sizeof(igmp)); 844 ip_transmit(sizeof(igmp), &igmp); 845 #ifdef MDEBUG 846 printf("Sent IGMP leave for: %@\n", igmp.igmp.group.s_addr); 847 #endif 848 } 849 memset(&igmptable[slot], 0, sizeof(igmptable[0])); 850 } 851 852 void join_group(int slot, unsigned long group) 853 { 854 /* I have already joined */ 855 if (igmptable[slot].group.s_addr == group) 856 return; 857 if (igmptable[slot].group.s_addr) { 858 leave_group(slot); 859 } 860 /* Only join a group if we are given a multicast ip, this way 861 * code can be given a non-multicast (broadcast or unicast ip) 862 * and still work... 863 */ 864 if ((group & htonl(MULTICAST_MASK)) == htonl(MULTICAST_NETWORK)) { 865 igmptable[slot].group.s_addr = group; 866 igmptable[slot].time = currticks(); 867 } 868 } 869 #else 870 #define send_igmp_reports(now); 871 #define process_igmp(ip, now) 872 #endif 873 874 /************************************************************************** 875 AWAIT_REPLY - Wait until we get a response for our request 876 ************f**************************************************************/ 877 int await_reply(reply_t reply, int ival, void *ptr, long timeout) 878 { 879 unsigned long time, now; 880 struct iphdr *ip; 881 unsigned iplen = 0; 882 struct udphdr *udp; 883 unsigned short ptype; 884 int result; 885 886 user_abort = 0; 887 888 time = timeout + currticks(); 889 /* The timeout check is done below. The timeout is only checked if 890 * there is no packet in the Rx queue. This assumes that eth_poll() 891 * needs a negligible amount of time. 892 */ 893 for (;;) { 894 now = currticks(); 895 send_igmp_reports(now); 896 result = eth_poll(1); 897 if (result == 0) { 898 /* We don't have anything */ 899 900 /* Check for abort key only if the Rx queue is empty - 901 * as long as we have something to process, don't 902 * assume that something failed. It is unlikely that 903 * we have no processing time left between packets. */ 904 poll_interruptions(); 905 /* Do the timeout after at least a full queue walk. */ 906 if ((timeout == 0) || (currticks() > time) || user_abort == 1) { 907 break; 908 } 909 continue; 910 } 911 912 /* We have something! */ 913 914 /* Find the Ethernet packet type */ 915 if (nic.packetlen >= ETH_HLEN) { 916 ptype = ((unsigned short) nic.packet[12]) << 8 917 | ((unsigned short) nic.packet[13]); 918 } else continue; /* what else could we do with it? */ 919 /* Verify an IP header */ 920 ip = 0; 921 if ((ptype == IP) && (nic.packetlen >= ETH_HLEN + sizeof(struct iphdr))) { 922 unsigned ipoptlen; 923 ip = (struct iphdr *)&nic.packet[ETH_HLEN]; 924 if ((ip->verhdrlen < 0x45) || (ip->verhdrlen > 0x4F)) 925 continue; 926 iplen = (ip->verhdrlen & 0xf) * 4; 927 if (ipchksum(ip, iplen) != 0) 928 continue; 929 if (ip->frags & htons(0x3FFF)) { 930 static int warned_fragmentation = 0; 931 if (!warned_fragmentation) { 932 printf("ALERT: got a fragmented packet - reconfigure your server\n"); 933 warned_fragmentation = 1; 934 } 935 continue; 936 } 937 if (ntohs(ip->len) > ETH_MAX_MTU) 938 continue; 939 940 ipoptlen = iplen - sizeof(struct iphdr); 941 if (ipoptlen) { 942 /* Delete the ip options, to guarantee 943 * good alignment, and make etherboot simpler. 944 */ 945 memmove(&nic.packet[ETH_HLEN + sizeof(struct iphdr)], 946 &nic.packet[ETH_HLEN + iplen], 947 nic.packetlen - ipoptlen); 948 nic.packetlen -= ipoptlen; 949 } 950 } 951 udp = 0; 952 if (ip && (ip->protocol == IP_UDP) && 953 (nic.packetlen >= ETH_HLEN + sizeof(struct iphdr) + sizeof(struct udphdr))) { 954 udp = (struct udphdr *)&nic.packet[ETH_HLEN + sizeof(struct iphdr)]; 955 956 /* Make certain we have a reasonable packet length */ 957 if (ntohs(udp->len) > (ntohs(ip->len) - iplen)) 958 continue; 959 960 if (udp->chksum && udpchksum(ip, udp)) { 961 printf("UDP checksum error\n"); 962 continue; 963 } 964 } 965 result = reply(ival, ptr, ptype, ip, udp); 966 if (result > 0) { 967 return result; 968 } 969 970 /* If it isn't a packet the upper layer wants see if there is a default 971 * action. This allows us reply to arp and igmp queryies. 972 */ 973 if ((ptype == ARP) && 974 (nic.packetlen >= ETH_HLEN + sizeof(struct arprequest))) { 975 struct arprequest *arpreply; 976 unsigned long tmp; 977 978 arpreply = (struct arprequest *)&nic.packet[ETH_HLEN]; 979 memcpy(&tmp, arpreply->tipaddr, sizeof(in_addr)); 980 if ((arpreply->opcode == htons(ARP_REQUEST)) && 981 (tmp == arptable[ARP_CLIENT].ipaddr.s_addr)) { 982 arpreply->opcode = htons(ARP_REPLY); 983 memcpy(arpreply->tipaddr, arpreply->sipaddr, sizeof(in_addr)); 984 memcpy(arpreply->thwaddr, arpreply->shwaddr, ETH_ALEN); 985 memcpy(arpreply->sipaddr, &arptable[ARP_CLIENT].ipaddr, sizeof(in_addr)); 986 memcpy(arpreply->shwaddr, arptable[ARP_CLIENT].node, ETH_ALEN); 987 eth_transmit(arpreply->thwaddr, ARP, 988 sizeof(struct arprequest), 989 arpreply); 990 #ifdef MDEBUG 991 memcpy(&tmp, arpreply->tipaddr, sizeof(in_addr)); 992 printf("Sent ARP reply to: %@\n",tmp); 993 #endif /* MDEBUG */ 994 } 995 } 996 process_igmp(ip, now); 997 } 998 return(0); 999 } 1000 1001 #ifdef REQUIRE_VCI_ETHERBOOT 1002 /************************************************************************** 1003 FIND_VCI_ETHERBOOT - Looks for "Etherboot" in Vendor Encapsulated Identifiers 1004 On entry p points to byte count of VCI options 1005 **************************************************************************/ 1006 static int find_vci_etherboot(unsigned char *p) 1007 { 1008 unsigned char *end = p + 1 + *p; 1009 1010 for (p++; p < end; ) { 1011 if (*p == RFC2132_VENDOR_CLASS_ID) { 1012 if (strncmp("Etherboot", p + 2, sizeof("Etherboot") - 1) == 0) 1013 return (1); 1014 } else if (*p == RFC1533_END) 1015 return (0); 1016 p += TAG_LEN(p) + 2; 1017 } 1018 return (0); 1019 } 1020 #endif /* REQUIRE_VCI_ETHERBOOT */ 1021 1022 /** 1023 * decode_rfc1533 1024 * 1025 * Decodes RFC1533 header 1026 **/ 1027 int decode_rfc1533(unsigned char *p, unsigned int block, unsigned int len, int eof) 1028 { 1029 static unsigned char *extdata = NULL, *extend = NULL; 1030 unsigned char *extpath = NULL; 1031 unsigned char *endp; 1032 1033 if (block == 0) { 1034 end_of_rfc1533 = NULL; 1035 if (memcmp(p, rfc1533_cookie, sizeof(rfc1533_cookie))) 1036 return(0); /* no RFC 1533 header found */ 1037 p += 4; 1038 endp = p + len; 1039 } else { 1040 if (block == 1) { 1041 if (memcmp(p, rfc1533_cookie, sizeof(rfc1533_cookie))) 1042 return(0); /* no RFC 1533 header found */ 1043 p += 4; 1044 len -= 4; } 1045 if (extend + len <= (unsigned char *) 1046 rfc1533_venddata + sizeof(rfc1533_venddata)) { 1047 memcpy(extend, p, len); 1048 extend += len; 1049 } else { 1050 printf("Overflow in vendor data buffer! Aborting...\n"); 1051 *extdata = RFC1533_END; 1052 return(0); 1053 } 1054 p = extdata; endp = extend; 1055 } 1056 if (!eof) 1057 return 1; 1058 while (p < endp) { 1059 unsigned char c = *p; 1060 if (c == RFC1533_PAD) { 1061 p++; 1062 continue; 1063 } 1064 else if (c == RFC1533_END) { 1065 end_of_rfc1533 = endp = p; 1066 continue; 1067 } 1068 else if (c == RFC1533_NETMASK) 1069 memcpy(&netmask, p+2, sizeof(in_addr)); 1070 else if (c == RFC1533_GATEWAY) { 1071 /* This is a little simplistic, but it will 1072 usually be sufficient. 1073 Take only the first entry */ 1074 if (TAG_LEN(p) >= sizeof(in_addr)) 1075 memcpy(&arptable[ARP_GATEWAY].ipaddr, p+2, sizeof(in_addr)); 1076 } 1077 else if (c == RFC1533_EXTENSIONPATH) 1078 extpath = p; 1079 else if (c == RFC2132_MSG_TYPE) 1080 dhcp_reply=*(p+2); 1081 else if (c == RFC2132_SRV_ID) 1082 memcpy(&dhcp_server, p+2, sizeof(in_addr)); 1083 else if (c == RFC1533_HOSTNAME) { 1084 hostname = p + 2; 1085 hostnamelen = *(p + 1); 1086 } 1087 else if (c == RFC1533_VENDOR_CONFIGFILE){ 1088 int l = TAG_LEN (p); 1089 1090 /* Eliminate the trailing NULs according to RFC 2132. */ 1091 while (*(p + 2 + l - 1) == '\000' && l > 0) 1092 l--; 1093 1094 /* XXX: Should check if LEN is less than the maximum length 1095 of CONFIG_FILE. This kind of robustness will be a goal 1096 in GRUB 1.0. */ 1097 memcpy (config_file, p + 2, l); 1098 config_file[l] = 0; 1099 } 1100 else { 1101 ; 1102 } 1103 p += TAG_LEN(p) + 2; 1104 } 1105 extdata = extend = endp; 1106 if (block <= 0 && extpath != NULL) { 1107 char fname[64]; 1108 if (TAG_LEN(extpath) >= sizeof(fname)){ 1109 printf("Overflow in vendor data buffer! Aborting...\n"); 1110 *extdata = RFC1533_END; 1111 return(0); 1112 } 1113 memcpy(fname, extpath+2, TAG_LEN(extpath)); 1114 fname[(int)TAG_LEN(extpath)] = '\0'; 1115 printf("Loading BOOTP-extension file: %s\n",fname); 1116 tftp_file_read(fname, decode_rfc1533); 1117 } 1118 return 1; /* proceed with next block */ 1119 } 1120 1121 1122 /* FIXME double check TWO_SECOND_DIVISOR */ 1123 #define TWO_SECOND_DIVISOR (RAND_MAX/TICKS_PER_SEC) 1124 /************************************************************************** 1125 RFC2131_SLEEP_INTERVAL - sleep for expotentially longer times (base << exp) +- 1 sec) 1126 **************************************************************************/ 1127 long rfc2131_sleep_interval(long base, int exp) 1128 { 1129 unsigned long tmo; 1130 #ifdef BACKOFF_LIMIT 1131 if (exp > BACKOFF_LIMIT) 1132 exp = BACKOFF_LIMIT; 1133 #endif 1134 tmo = (base << exp) + (TICKS_PER_SEC - (random()/TWO_SECOND_DIVISOR)); 1135 return tmo; 1136 } 1137 1138 #ifdef MULTICAST_LEVEL2 1139 /************************************************************************** 1140 RFC1112_SLEEP_INTERVAL - sleep for expotentially longer times, up to (base << exp) 1141 **************************************************************************/ 1142 long rfc1112_sleep_interval(long base, int exp) 1143 { 1144 unsigned long divisor, tmo; 1145 #ifdef BACKOFF_LIMIT 1146 if (exp > BACKOFF_LIMIT) 1147 exp = BACKOFF_LIMIT; 1148 #endif 1149 divisor = RAND_MAX/(base << exp); 1150 tmo = random()/divisor; 1151 return tmo; 1152 } 1153 #endif /* MULTICAST_LEVEL_2 */ 1154 /* ifconfig - configure network interface. */ 1155 int 1156 ifconfig (char *ip, char *sm, char *gw, char *svr) 1157 { 1158 in_addr tmp; 1159 1160 if (sm) 1161 { 1162 if (! inet_aton (sm, &tmp)) 1163 return 0; 1164 1165 netmask = tmp.s_addr; 1166 } 1167 1168 if (ip) 1169 { 1170 if (! inet_aton (ip, &arptable[ARP_CLIENT].ipaddr)) 1171 return 0; 1172 1173 if (! netmask && ! sm) 1174 netmask = default_netmask (); 1175 } 1176 1177 if (gw && ! inet_aton (gw, &arptable[ARP_GATEWAY].ipaddr)) 1178 return 0; 1179 1180 /* Clear out the ARP entry. */ 1181 grub_memset (arptable[ARP_GATEWAY].node, 0, ETH_ALEN); 1182 1183 if (svr && ! inet_aton (svr, &arptable[ARP_SERVER].ipaddr)) 1184 return 0; 1185 1186 /* Likewise. */ 1187 grub_memset (arptable[ARP_SERVER].node, 0, ETH_ALEN); 1188 1189 if (ip || sm) 1190 { 1191 if (IP_BROADCAST == (netmask | arptable[ARP_CLIENT].ipaddr.s_addr) 1192 || netmask == (netmask | arptable[ARP_CLIENT].ipaddr.s_addr) 1193 || ! netmask) 1194 network_ready = 0; 1195 else 1196 network_ready = 1; 1197 } 1198 1199 update_network_configuration(); 1200 return 1; 1201 } 1202 1203 /* 1204 * print_network_configuration 1205 * 1206 * Output the network configuration. It may broke the graphic console now.:-( 1207 */ 1208 void print_network_configuration (void) 1209 { 1210 EnterFunction("print_network_configuration"); 1211 if (! network_ready) 1212 grub_printf ("Network interface not initialized yet.\n"); 1213 else { 1214 etherboot_printf ("Address: %@\n", arptable[ARP_CLIENT].ipaddr.s_addr); 1215 etherboot_printf ("Netmask: %@\n", netmask); 1216 etherboot_printf ("Server: %@\n", arptable[ARP_SERVER].ipaddr.s_addr); 1217 etherboot_printf ("Gateway: %@\n", arptable[ARP_GATEWAY].ipaddr.s_addr); 1218 } 1219 LeaveFunction("print_network_configuration"); 1220 } 1221 1222 /* 1223 * update_network_configuration 1224 * 1225 * Update network configuration for diskless clients (Solaris only) 1226 */ 1227 static void update_network_configuration (void) 1228 { 1229 #ifdef SOLARIS_NETBOOT 1230 struct sol_netinfo { 1231 uint8_t sn_infotype; 1232 uint8_t sn_mactype; 1233 uint8_t sn_maclen; 1234 uint8_t sn_padding; 1235 unsigned long sn_ciaddr; 1236 unsigned long sn_siaddr; 1237 unsigned long sn_giaddr; 1238 unsigned long sn_netmask; 1239 uint8_t sn_macaddr[1]; 1240 } *sip; 1241 1242 if (! network_ready) 1243 return; 1244 1245 sip = (struct sol_netinfo *)dhcpack_buf; 1246 sip->sn_infotype = 0xf0; /* something not BOOTP_REPLY */ 1247 sip->sn_mactype = 4; /* DL_ETHER */ 1248 sip->sn_maclen = ETH_ALEN; 1249 sip->sn_ciaddr = arptable[ARP_CLIENT].ipaddr.s_addr; 1250 sip->sn_siaddr = arptable[ARP_SERVER].ipaddr.s_addr; 1251 sip->sn_giaddr = arptable[ARP_GATEWAY].ipaddr.s_addr; 1252 sip->sn_netmask = netmask; 1253 memcpy(sip->sn_macaddr, arptable[ARP_CLIENT].node, ETH_ALEN); 1254 dhcpack_length = sizeof (*sip) + sip->sn_maclen - 1; 1255 #endif /* SOLARIS_NETBOOT */ 1256 } 1257 1258 /** 1259 * cleanup_net 1260 * 1261 * Mark network unusable, and disable NICs 1262 */ 1263 void cleanup_net (void) 1264 { 1265 if (network_ready){ 1266 /* Stop receiving packets. */ 1267 if (use_bios_pxe) 1268 undi_pxe_disable(); 1269 else 1270 eth_disable (); 1271 network_ready = 0; 1272 } 1273 } 1274 1275 /******************************************************************* 1276 * dhcp implementation reusing the BIOS pxe stack 1277 */ 1278 static void 1279 dhcp_copy(struct dhcp_t *dhcpreply) 1280 { 1281 unsigned long time; 1282 int ret, len = DHCP_OPT_LEN; 1283 1284 /* fill in netinfo */ 1285 dhcpack_length = sizeof (struct dhcp_t); 1286 memcpy((char *)dhcpack_buf, (char *)dhcpreply, dhcpack_length); 1287 1288 memcpy(arptable[ARP_CLIENT].node, dhcpreply->bp_hwaddr, ETH_ALEN); 1289 arptable[ARP_CLIENT].ipaddr.s_addr = dhcpreply->bp_yiaddr.s_addr; 1290 dhcp_addr.s_addr = dhcpreply->bp_yiaddr.s_addr; 1291 netmask = default_netmask(); 1292 arptable[ARP_SERVER].ipaddr.s_addr = dhcpreply->bp_siaddr.s_addr; 1293 memset(arptable[ARP_SERVER].node, 0, ETH_ALEN); /* Kill arp */ 1294 arptable[ARP_GATEWAY].ipaddr.s_addr = dhcpreply->bp_giaddr.s_addr; 1295 memset(arptable[ARP_GATEWAY].node, 0, ETH_ALEN); /* Kill arp */ 1296 /* We don't care bootpreply->bp_file. It must be 'pxegrub' */ 1297 memcpy((char *)rfc1533_venddata, (char *)(dhcpreply->bp_vend), len); 1298 decode_rfc1533(rfc1533_venddata, 0, len, 1); 1299 } 1300 1301 int dhcp_undi(void) 1302 { 1303 struct dhcp_t *dhcpreply; 1304 1305 if (!undi_bios_pxe((void **)&dhcpreply)) 1306 return 0; 1307 1308 dhcp_copy(dhcpreply); 1309 network_ready = 1; 1310 use_bios_pxe = 1; 1311 return (1); 1312 } 1313