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