1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 #include <sys/param.h> 29 #include <sys/types.h> 30 #include <sys/user.h> 31 #include <sys/vfs.h> 32 #include <sys/vnode.h> 33 #include <sys/file.h> 34 #include <sys/stream.h> 35 #include <sys/stropts.h> 36 #include <sys/strsubr.h> 37 #include <sys/dlpi.h> 38 #include <sys/vnode.h> 39 #include <sys/socket.h> 40 #include <sys/sockio.h> 41 #include <net/if.h> 42 43 #include <sys/cred.h> 44 #include <sys/sysmacros.h> 45 46 #include <sys/sad.h> 47 #include <sys/kstr.h> 48 #include <sys/bootconf.h> 49 #include <sys/bootprops.h> 50 51 #include <sys/errno.h> 52 #include <sys/modctl.h> 53 #include <sys/sunddi.h> 54 #include <sys/sunldi.h> 55 #include <sys/esunddi.h> 56 #include <sys/promif.h> 57 58 #include <netinet/in.h> 59 #include <netinet/ip6.h> 60 #include <netinet/icmp6.h> 61 #include <netinet/sctp.h> 62 #include <inet/common.h> 63 #include <inet/ip.h> 64 #include <inet/ip6.h> 65 #include <inet/tcp.h> 66 #include <inet/sctp_ip.h> 67 68 #include <sys/strlog.h> 69 #include <sys/log.h> 70 #include <sys/ethernet.h> 71 #include <sys/ddi_implfuncs.h> 72 73 #include <sys/dld.h> 74 75 /* 76 * Debug Macros 77 */ 78 int strplumbdebug = 0; 79 80 #define DBG0(_f) \ 81 if (strplumbdebug != 0) \ 82 printf("strplumb: " _f) 83 84 #define DBG1(_f, _a) \ 85 if (strplumbdebug != 0) \ 86 printf("strplumb: " _f, (_a)) 87 88 #define DBG2(_f, _a, _b) \ 89 if (strplumbdebug != 0) \ 90 printf("strplumb: " _f, (_a), (_b)) 91 92 #define DBG3(_f, _a, _b, _c) \ 93 if (strplumbdebug != 0) \ 94 printf("strplumb: " _f, (_a), (_b), (_c)) 95 96 /* 97 * Module linkage information for the kernel. 98 */ 99 #define STRPLUMB_IDENT "STREAMS Plumbing Module v%I%" 100 101 static struct modlmisc modlmisc = { 102 &mod_miscops, 103 STRPLUMB_IDENT 104 }; 105 106 static struct modlinkage modlinkage = { 107 MODREV_1, 108 &modlmisc, 109 NULL 110 }; 111 112 int 113 _init(void) 114 { 115 return (mod_install(&modlinkage)); 116 } 117 118 int 119 _fini(void) 120 { 121 return (mod_remove(&modlinkage)); 122 } 123 124 int 125 _info(struct modinfo *modinfop) 126 { 127 return (mod_info(&modlinkage, modinfop)); 128 } 129 130 #define ARP "arp" 131 #define TCP "tcp" 132 #define TCP6 "tcp6" 133 #define UDP "udp" 134 #define UDP6 "udp6" 135 #define SCTP "sctp" 136 #define SCTP6 "sctp6" 137 #define ICMP "icmp" 138 #define ICMP6 "icmp6" 139 #define IP "ip" 140 #define IP6 "ip6" 141 #define TIMOD "timod" 142 143 #define UDPDEV "/devices/pseudo/udp@0:udp" 144 #define TCP6DEV "/devices/pseudo/tcp6@0:tcp6" 145 #define SCTP6DEV "/devices/pseudo/sctp6@0:sctp6" 146 #define IP6DEV "/devices/pseudo/ip6@0:ip6" 147 148 typedef struct strplumb_modspec { 149 char *sm_type; 150 char *sm_name; 151 } strplumb_modspec_t; 152 153 static strplumb_modspec_t strplumb_modlist[] = { 154 { "drv", DLD_DRIVER_NAME }, 155 { "drv", IP }, 156 { "drv", IP6 }, 157 { "drv", TCP }, 158 { "drv", TCP6 }, 159 { "drv", UDP }, 160 { "drv", UDP6 }, 161 { "drv", SCTP }, 162 { "drv", SCTP6 }, 163 { "drv", ICMP }, 164 { "drv", ICMP6 }, 165 { "drv", ARP }, 166 { "strmod", TIMOD } 167 }; 168 169 /* 170 * Called from swapgeneric.c:loadrootmodules() in the network boot case. 171 */ 172 int 173 strplumb_load(void) 174 { 175 uint_t i; 176 strplumb_modspec_t *p; 177 178 DBG0("loading modules\n"); 179 180 for (i = 0, p = strplumb_modlist; 181 i < sizeof (strplumb_modlist) / sizeof (strplumb_modlist[0]); 182 i++, p++) { 183 if (modloadonly(p->sm_type, p->sm_name) < 0) { 184 printf("strplumb: failed to load %s/%s\n", 185 p->sm_type, p->sm_name); 186 return (EFAULT); 187 } 188 } 189 190 return (0); 191 } 192 193 static int 194 strplumb_init(void) 195 { 196 uint_t i; 197 strplumb_modspec_t *p; 198 int err; 199 200 DBG0("initializing modules\n"); 201 202 for (i = 0, p = strplumb_modlist; 203 i < sizeof (strplumb_modlist) / sizeof (strplumb_modlist[0]); 204 i++, p++) { 205 if (strcmp(p->sm_type, "drv") == 0) 206 err = (i_ddi_attach_pseudo_node(p->sm_name) != NULL) ? 207 0 : EFAULT; 208 else 209 err = (modload(p->sm_type, p->sm_name) < 0) ? 210 EFAULT : 0; 211 212 if (err != 0) { 213 printf("strplumb: failed to initialize %s/%s\n", 214 p->sm_type, p->sm_name); 215 return (err); 216 } 217 } 218 219 return (0); 220 } 221 222 static int 223 strplumb_autopush(void) 224 { 225 major_t maj; 226 minor_t min; 227 char *mods[5]; 228 uint_t anchor = 1; 229 int err; 230 231 min = (minor_t)-1; 232 mods[1] = NULL; 233 234 /* 235 * UDP 236 */ 237 DBG0("setting up udp autopush\n"); 238 239 mods[0] = UDP; 240 241 maj = ddi_name_to_major(UDP); 242 if ((err = kstr_autopush(SET_AUTOPUSH, &maj, &min, NULL, &anchor, 243 mods)) != 0) { 244 printf("strplumb: kstr_autopush(SET/UDP) failed: %d\n", err); 245 return (err); 246 } 247 248 maj = ddi_name_to_major(UDP6); 249 if ((err = kstr_autopush(SET_AUTOPUSH, &maj, &min, NULL, &anchor, 250 mods)) != 0) { 251 printf("strplumb: kstr_autopush(SET/UDP6) failed: %d\n", err); 252 return (err); 253 } 254 255 /* 256 * ICMP 257 */ 258 DBG0("setting up icmp autopush\n"); 259 260 mods[0] = ICMP; 261 262 maj = ddi_name_to_major(ICMP); 263 if ((err = kstr_autopush(SET_AUTOPUSH, &maj, &min, NULL, NULL, 264 mods)) != 0) { 265 printf("strplumb: kstr_autopush(SET/ICMP) failed: %d\n", err); 266 return (err); 267 } 268 269 maj = ddi_name_to_major(ICMP6); 270 if ((err = kstr_autopush(SET_AUTOPUSH, &maj, &min, NULL, NULL, 271 mods)) != 0) { 272 printf("strplumb: kstr_autopush(SET/ICMP6) failed: %d\n", err); 273 return (err); 274 } 275 276 /* 277 * ARP 278 */ 279 DBG0("setting up arp autopush\n"); 280 281 mods[0] = ARP; 282 283 maj = ddi_name_to_major(ARP); 284 if ((err = kstr_autopush(SET_AUTOPUSH, &maj, &min, NULL, &anchor, 285 mods)) != 0) { 286 printf("strplumb: kstr_autopush(SET/ARP) failed: %d\n", err); 287 return (err); 288 } 289 290 return (0); 291 } 292 293 static int 294 strplumb_sctpq(ldi_ident_t li) 295 { 296 ldi_handle_t lh = NULL; 297 int err; 298 int rval; 299 300 DBG0("configuring SCTP default queue\n"); 301 302 if ((err = ldi_open_by_name(SCTP6DEV, FREAD|FWRITE, CRED(), &lh, 303 li)) != 0) { 304 printf("strplumb: open of SCTP6DEV failed: %d\n", err); 305 return (err); 306 } 307 308 if ((err = ldi_ioctl(lh, SCTP_IOC_DEFAULT_Q, (intptr_t)0, FKIOCTL, 309 CRED(), &rval)) != 0) { 310 printf("strplumb: failed to set SCTP default queue: %d\n", 311 err); 312 (void) ldi_close(lh, FREAD|FWRITE, CRED()); 313 return (err); 314 } 315 316 return (0); 317 } 318 319 static int 320 strplumb_tcpq(ldi_ident_t li) 321 { 322 ldi_handle_t lh = NULL; 323 ldi_handle_t ip_lh = NULL; 324 int err; 325 int rval; 326 327 DBG0("configuring TCP default queue\n"); 328 329 /* 330 * We open IP6DEV here because we need to have it open to in 331 * order to open TCP6DEV successfully. 332 */ 333 if ((err = ldi_open_by_name(IP6DEV, FREAD|FWRITE, CRED(), &ip_lh, 334 li)) != 0) { 335 printf("strplumb: open of IP6DEV failed: %d\n", err); 336 return (err); 337 } 338 339 /* 340 * We set the tcp default queue to IPv6 because IPv4 falls back to 341 * IPv6 when it can't find a client, but IPv6 does not fall back to 342 * IPv4. 343 */ 344 if ((err = ldi_open_by_name(TCP6DEV, FREAD|FWRITE, CRED(), &lh, 345 li)) != 0) { 346 printf("strplumb: open of TCP6DEV failed: %d\n", err); 347 goto done; 348 } 349 350 if ((err = ldi_ioctl(lh, TCP_IOC_DEFAULT_Q, (intptr_t)0, FKIOCTL, 351 CRED(), &rval)) != 0) { 352 printf("strplumb: failed to set TCP default queue: %d\n", 353 err); 354 goto done; 355 } 356 357 done: 358 (void) ldi_close(ip_lh, FREAD|FWRITE, CRED()); 359 return (err); 360 } 361 362 /* 363 * Can be set in /etc/system in the case of local booting. See comment below. 364 */ 365 char *ndev_name = 0; 366 int ndev_unit = 0; 367 368 /* 369 * If we booted diskless then strplumb() will have been called from 370 * swapgeneric.c:rootconf(). All we can do in that case is plumb the 371 * network device that we booted from. 372 * 373 * If we booted from a local disk, we will have been called from main(), 374 * and normally we defer the plumbing of interfaces until network/physical. 375 * This can be overridden by setting "ndev_name" in /etc/system. 376 */ 377 static int 378 resolve_boot_path(void) 379 { 380 char *devpath = NULL; 381 dev_info_t *dip; 382 const char *driver; 383 int instance; 384 385 if (strncmp(rootfs.bo_fstype, "nfs", 3) == 0) 386 devpath = rootfs.bo_name; 387 #ifndef __sparc 388 else 389 devpath = strplumb_get_netdev_path(); 390 #endif 391 392 if (devpath != NULL) { 393 DBG1("resolving boot-path: %s\n", devpath); 394 395 /* 396 * Hold the devi since this is the root device. 397 */ 398 if ((dip = e_ddi_hold_devi_by_path(devpath, 0)) == NULL) { 399 printf("strplumb: unable to hold root device: %s\n", 400 devpath); 401 return (ENXIO); 402 } 403 404 driver = ddi_driver_name(dip); 405 instance = ddi_get_instance(dip); 406 } else { 407 if (ndev_name == NULL) 408 return (ENODEV); 409 410 DBG2("using ndev_name (%s) ndev_unit (%d)\n", ndev_name, 411 ndev_unit); 412 413 if (i_ddi_attach_hw_nodes(ndev_name) != DDI_SUCCESS) { 414 printf("strplumb: cannot load ndev_name '%s'\n", 415 ndev_name); 416 return (ENXIO); 417 } 418 419 driver = ndev_name; 420 instance = ndev_unit; 421 } 422 423 (void) snprintf(rootfs.bo_devname, BO_MAXOBJNAME, 424 "/devices/pseudo/clone@0:%s", driver); 425 (void) snprintf(rootfs.bo_ifname, BO_MAXOBJNAME, "%s%d", 426 driver, instance); 427 rootfs.bo_ppa = instance; 428 return (0); 429 } 430 431 static int 432 getifflags(ldi_handle_t lh, struct lifreq *lifrp) 433 { 434 struct strioctl iocb; 435 int rval; 436 437 iocb.ic_cmd = SIOCGLIFFLAGS; 438 iocb.ic_timout = 15; 439 iocb.ic_len = sizeof (struct lifreq); 440 iocb.ic_dp = (char *)lifrp; 441 442 return (ldi_ioctl(lh, I_STR, (intptr_t)&iocb, FKIOCTL, CRED(), &rval)); 443 444 } 445 446 static int 447 setifname(ldi_handle_t lh, struct lifreq *lifrp) 448 { 449 struct strioctl iocb; 450 int rval; 451 452 iocb.ic_cmd = SIOCSLIFNAME; 453 iocb.ic_timout = 15; 454 iocb.ic_len = sizeof (struct lifreq); 455 iocb.ic_dp = (char *)lifrp; 456 457 return (ldi_ioctl(lh, I_STR, (intptr_t)&iocb, FKIOCTL, CRED(), &rval)); 458 } 459 460 static int 461 strplumb_dev(ldi_ident_t li) 462 { 463 ldi_handle_t lh = NULL; 464 ldi_handle_t mux_lh = NULL; 465 int err; 466 struct lifreq lifr; 467 struct ifreq ifr; 468 int rval; 469 470 bzero(&lifr, sizeof (struct lifreq)); 471 bzero(&ifr, sizeof (ifr)); 472 473 /* 474 * Now set up the links. Ultimately, we should have two streams 475 * permanently linked underneath UDP (which is actually IP with UDP 476 * autopushed). One stream consists of the ARP-[ifname] combination, 477 * while the other consists of ARP-IP-[ifname]. The second combination 478 * seems a little weird, but is linked underneath UDP just to keep it 479 * around. 480 * 481 * We pin underneath UDP here to match what is done in ifconfig(1m); 482 * otherwise, ifconfig will be unable to unplumb the stream (the major 483 * number and mux id must both match for a successful I_PUNLINK). 484 * 485 * There are subtleties in the plumbing which make it essential to 486 * follow the logic used in ifconfig(1m) very closely. 487 */ 488 489 /* 490 * Plumb UDP-ARP-IP-<dev> 491 */ 492 493 if ((err = ldi_open_by_name(rootfs.bo_devname, FREAD|FWRITE, CRED(), 494 &lh, li)) != 0) { 495 printf("strplumb: open %s failed: %d\n", rootfs.bo_devname, 496 err); 497 goto done; 498 } 499 500 501 if ((err = ldi_ioctl(lh, I_PUSH, (intptr_t)IP, FKIOCTL, CRED(), 502 &rval)) != 0) { 503 printf("strplumb: push IP failed: %d\n", err); 504 goto done; 505 } 506 507 if ((err = getifflags(lh, &lifr)) != 0) 508 goto done; 509 510 lifr.lifr_flags |= IFF_IPV4; 511 lifr.lifr_flags &= ~IFF_IPV6; 512 513 if ((err = ldi_ioctl(lh, I_PUSH, (intptr_t)ARP, FKIOCTL, CRED(), 514 &rval)) != 0) { 515 printf("strplumb: push ARP failed: %d\n", err); 516 goto done; 517 } 518 519 (void) strlcpy(lifr.lifr_name, rootfs.bo_ifname, 520 sizeof (lifr.lifr_name)); 521 lifr.lifr_ppa = rootfs.bo_ppa; 522 523 if ((err = setifname(lh, &lifr)) != 0) 524 goto done; 525 526 /* Get the flags and check if ARP is needed */ 527 if ((err = getifflags(lh, &lifr)) != 0) { 528 printf("strplumb: getifflags %s IP failed, error %d\n", 529 lifr.lifr_name, err); 530 goto done; 531 } 532 533 /* Pop out ARP if not needed */ 534 if (lifr.lifr_flags & IFF_NOARP) { 535 err = ldi_ioctl(lh, I_POP, (intptr_t)0, FKIOCTL, CRED(), 536 &rval); 537 if (err != 0) { 538 printf("strplumb: pop ARP failed, error %d\n", err); 539 goto done; 540 } 541 } 542 543 if ((err = ldi_open_by_name(UDPDEV, FREAD|FWRITE, CRED(), &mux_lh, 544 li)) != 0) { 545 printf("strplumb: open of UDPDEV failed: %d\n", err); 546 goto done; 547 } 548 549 if ((err = ldi_ioctl(mux_lh, I_PLINK, (intptr_t)lh, 550 FREAD|FWRITE|FNOCTTY|FKIOCTL, CRED(), 551 &(ifr.ifr_ip_muxid))) != 0) { 552 printf("strplumb: plink UDP-ARP-IP-%s failed: %d\n", 553 rootfs.bo_ifname, err); 554 goto done; 555 } 556 557 DBG2("UDP-ARP-IP-%s muxid: %d\n", rootfs.bo_ifname, ifr.ifr_ip_muxid); 558 559 (void) ldi_close(lh, FREAD|FWRITE, CRED()); 560 lh = NULL; 561 562 /* 563 * Plumb UDP-ARP-<dev> 564 */ 565 566 if ((err = ldi_open_by_name(rootfs.bo_devname, FREAD|FWRITE, CRED(), 567 &lh, li)) != 0) { 568 printf("strplumb: open %s failed: %d\n", rootfs.bo_devname, 569 err); 570 goto done; 571 } 572 573 if ((err = ldi_ioctl(lh, I_PUSH, (intptr_t)ARP, FKIOCTL, CRED(), 574 &rval)) != 0) { 575 printf("strplumb: push ARP failed: %d\n", err); 576 goto done; 577 } 578 579 if ((err = setifname(lh, &lifr)) != 0) 580 goto done; 581 582 if ((err = ldi_ioctl(mux_lh, I_PLINK, (intptr_t)lh, 583 FREAD|FWRITE|FNOCTTY|FKIOCTL, CRED(), 584 &(ifr.ifr_arp_muxid))) != 0) { 585 printf("strplumb: plink UDP-ARP-%s failed: %d\n", 586 rootfs.bo_ifname, err); 587 goto done; 588 } 589 590 DBG2("UDP-ARP-%s muxid: %d\n", rootfs.bo_ifname, ifr.ifr_arp_muxid); 591 592 /* 593 * Cache the mux ids. 594 */ 595 (void) strlcpy(ifr.ifr_name, rootfs.bo_ifname, sizeof (ifr.ifr_name)); 596 597 if ((err = ldi_ioctl(mux_lh, SIOCSIFMUXID, (intptr_t)&ifr, FKIOCTL, 598 CRED(), &rval)) != 0) { 599 printf("strplumb: SIOCSIFMUXID failed: %d\n", err); 600 goto done; 601 } 602 603 done: 604 if (lh != NULL) 605 (void) ldi_close(lh, FREAD|FWRITE, CRED()); 606 607 if (mux_lh != NULL) 608 (void) ldi_close(mux_lh, FREAD|FWRITE, CRED()); 609 610 return (err); 611 } 612 613 /* 614 * Do streams plumbing for internet protocols. 615 */ 616 int 617 strplumb(void) 618 { 619 ldi_ident_t li; 620 int err; 621 622 if ((err = strplumb_init()) != 0) 623 return (err); 624 625 if ((err = strplumb_autopush()) != 0) 626 return (err); 627 628 if ((err = ldi_ident_from_mod(&modlinkage, &li)) != 0) 629 return (err); 630 631 /* 632 * Setup the TCP and SCTP default queues for the global stack. 633 * tcp/sctp_stack_init will do this for additional stack instances. 634 */ 635 if ((err = strplumb_sctpq(li)) != 0) 636 goto done; 637 638 if ((err = strplumb_tcpq(li)) != 0) 639 goto done; 640 641 if ((err = resolve_boot_path()) != 0) 642 goto done; 643 644 DBG1("rootfs.bo_devname: %s\n", rootfs.bo_devname); 645 DBG1("rootfs.bo_ifname: %s\n", rootfs.bo_ifname); 646 DBG1("rootfs.bo_ppa: %d\n", rootfs.bo_ppa); 647 648 if ((err = strplumb_dev(li)) != 0) 649 goto done; 650 651 done: 652 ldi_ident_release(li); 653 654 return (err); 655 } 656 657 /* multiboot: diskless boot interface discovery */ 658 659 #ifndef __sparc 660 661 static uchar_t boot_macaddr[16]; 662 static int boot_maclen; 663 static uchar_t *getmacaddr(dev_info_t *dip, int *maclen); 664 static int matchmac(dev_info_t *dip, void *arg); 665 int dl_attach(ldi_handle_t lh, int unit); 666 int dl_bind(ldi_handle_t lh, uint_t sap, uint_t max_conn, 667 uint_t service, uint_t conn_mgmt); 668 int dl_phys_addr(ldi_handle_t lh, struct ether_addr *eaddr); 669 670 #endif /* !__sparc */ 671 672 char * 673 strplumb_get_netdev_path(void) 674 { 675 #ifndef __sparc 676 char *macstr, *devpath = NULL; 677 uchar_t *bootp; 678 uint_t bootp_len, len; 679 680 if (ddi_prop_lookup_string(DDI_DEV_T_ANY, ddi_root_node(), 681 DDI_PROP_DONTPASS, BP_BOOT_MAC, &macstr) == DDI_SUCCESS) { 682 /* 683 * hard coded ether mac len for booting floppy on 684 * machines with old cards 685 */ 686 boot_maclen = ether_aton(macstr, boot_macaddr); 687 if (boot_maclen != 6) { 688 cmn_err(CE_WARN, 689 "malformed boot_mac property, %d bytes", 690 boot_maclen); 691 } 692 ddi_prop_free(macstr); 693 } else if (ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, ddi_root_node(), 694 DDI_PROP_DONTPASS, BP_BOOTP_RESPONSE, &bootp, &bootp_len) 695 == DDI_SUCCESS) { 696 697 /* 698 * These offsets are defined by dhcp standard 699 * Should use structure offsets 700 */ 701 boot_maclen = *(bootp + 2); 702 ASSERT(boot_maclen <= 16); 703 (void) bcopy(bootp + 28, boot_macaddr, boot_maclen); 704 705 /* encode to ascii string to match what sparc OBP exports */ 706 dhcack = kmem_zalloc(bootp_len * 2 + IFNAMSIZ + 2, KM_SLEEP); 707 len = bootp_len * 2 + 2; 708 (void) octet_to_hexascii(bootp, bootp_len, dhcack + IFNAMSIZ, 709 &len); 710 ASSERT(len < bootp_len * 2 + 2); 711 ddi_prop_free(bootp); 712 } else 713 return (NULL); 714 715 ddi_walk_devs(ddi_root_node(), matchmac, (void *)&devpath); 716 return (devpath); 717 718 #else 719 return (NULL); 720 #endif /* !__sparc */ 721 } 722 723 #ifndef __sparc 724 725 /* 726 * Get boot path from the boot_mac address 727 */ 728 /*ARGSUSED*/ 729 static int 730 matchmac(dev_info_t *dip, void *arg) 731 { 732 char **devpathp = (char **)arg; 733 char *model_str; 734 uchar_t *macaddr; 735 int maclen; 736 737 /* XXX Should use "device-type" per IEEE 1275 */ 738 if (ddi_prop_lookup_string(DDI_DEV_T_ANY, dip, 0, 739 "model", &model_str) != DDI_SUCCESS) 740 return (DDI_WALK_CONTINUE); 741 742 if (strcmp(model_str, "Ethernet controller") != 0) { 743 ddi_prop_free(model_str); 744 return (DDI_WALK_CONTINUE); 745 } 746 ddi_prop_free(model_str); 747 748 /* We have a network device now */ 749 if (i_ddi_attach_node_hierarchy(dip) != DDI_SUCCESS) { 750 return (DDI_WALK_CONTINUE); 751 } 752 753 ASSERT(boot_maclen != 0); 754 macaddr = getmacaddr(dip, &maclen); 755 if (macaddr == NULL) 756 return (DDI_WALK_CONTINUE); 757 758 if (maclen != boot_maclen || 759 bcmp(macaddr, boot_macaddr, maclen) != 0) { 760 kmem_free(macaddr, maclen); 761 return (DDI_WALK_CONTINUE); 762 } 763 764 /* found hardware with the mac address */ 765 (void) localetheraddr((struct ether_addr *)macaddr, NULL); 766 kmem_free(macaddr, maclen); 767 768 *devpathp = kmem_alloc(MAXPATHLEN, KM_SLEEP); 769 (void) ddi_pathname(dip, *devpathp); 770 771 /* fill in the name portion of dhcack */ 772 if (dhcack) 773 (void) snprintf(dhcack, IFNAMSIZ, "%s%d", 774 ddi_driver_name(dip), i_ddi_devi_get_ppa(dip)); 775 return (DDI_WALK_TERMINATE); 776 } 777 778 static uchar_t * 779 getmacaddr_gldv3(char *drv, int inst, int *maclenp) 780 { 781 char ifname[16]; 782 mac_handle_t mh; 783 uchar_t *macaddr; 784 785 (void) snprintf(ifname, sizeof (ifname), "%s%d", drv, inst); 786 if (mac_open(ifname, inst, &mh) < 0) { 787 return (NULL); 788 } 789 *maclenp = sizeof (struct ether_addr); 790 macaddr = kmem_alloc(*maclenp, KM_SLEEP); 791 mac_unicst_get(mh, macaddr); 792 mac_close(mh); 793 794 return (macaddr); 795 } 796 797 static uchar_t * 798 getmacaddr(dev_info_t *dip, int *maclenp) 799 { 800 int rc, ppa; 801 ldi_ident_t li; 802 ldi_handle_t lh; 803 char *drv_name = (char *)ddi_driver_name(dip); 804 char *clonepath; 805 uchar_t *macaddr = NULL; 806 807 /* a simpler way to get mac address for GLDv3 drivers */ 808 if (GLDV3_DRV(ddi_name_to_major(drv_name))) { 809 return (getmacaddr_gldv3(drv_name, ddi_get_instance(dip), 810 maclenp)); 811 } 812 813 if (rc = ldi_ident_from_mod(&modlinkage, &li)) { 814 cmn_err(CE_WARN, 815 "getmacaddr: ldi_ident_from_mod failed: %d\n", rc); 816 return (NULL); 817 } 818 819 clonepath = kmem_alloc(MAXPATHLEN, KM_SLEEP); 820 (void) snprintf(clonepath, MAXPATHLEN, 821 "/devices/pseudo/clone@0:%s", drv_name); 822 823 rc = ldi_open_by_name(clonepath, FREAD|FWRITE, CRED(), &lh, li); 824 ldi_ident_release(li); 825 if (rc) { 826 cmn_err(CE_WARN, 827 "getmacaddr: ldi_open_by_name(%s) failed: %d\n", 828 clonepath, rc); 829 kmem_free(clonepath, MAXPATHLEN); 830 return (NULL); 831 } 832 kmem_free(clonepath, MAXPATHLEN); 833 834 ppa = i_ddi_devi_get_ppa(dip); 835 if ((dl_attach(lh, ppa) != 0) || 836 (dl_bind(lh, ETHERTYPE_IP, 0, DL_CLDLS, 0) != 0)) { 837 (void) ldi_close(lh, FREAD|FWRITE, CRED()); 838 cmn_err(CE_WARN, 839 "getmacaddr: dl_attach/bind(%s%d) failed: %d\n", 840 drv_name, ppa, rc); 841 return (NULL); 842 } 843 *maclenp = sizeof (struct ether_addr); 844 macaddr = kmem_alloc(*maclenp, KM_SLEEP); 845 if (dl_phys_addr(lh, (struct ether_addr *)macaddr) != 0) { 846 kmem_free(macaddr, *maclenp); 847 macaddr = NULL; 848 *maclenp = 0; 849 cmn_err(CE_WARN, 850 "getmacaddr: dl_macaddr(%s%d) failed: %d\n", 851 drv_name, ppa, rc); 852 } 853 (void) ldi_close(lh, FREAD|FWRITE, CRED()); 854 return (macaddr); 855 } 856 857 #endif /* !__sparc */ 858 859 int 860 dl_attach(ldi_handle_t lh, int unit) 861 { 862 dl_attach_req_t *attach_req; 863 dl_error_ack_t *error_ack; 864 union DL_primitives *dl_prim; 865 mblk_t *mp; 866 int error; 867 868 if ((mp = allocb(sizeof (dl_attach_req_t), BPRI_MED)) == NULL) { 869 cmn_err(CE_WARN, "dl_attach: allocb failed"); 870 return (ENOSR); 871 } 872 mp->b_datap->db_type = M_PROTO; 873 mp->b_wptr += sizeof (dl_attach_req_t); 874 875 attach_req = (dl_attach_req_t *)mp->b_rptr; 876 attach_req->dl_primitive = DL_ATTACH_REQ; 877 attach_req->dl_ppa = unit; 878 879 (void) ldi_putmsg(lh, mp); 880 if ((error = ldi_getmsg(lh, &mp, (timestruc_t *)NULL)) != 0) { 881 printf("dl_attach: ldi_getmsg failed: %d\n", error); 882 return (error); 883 } 884 885 dl_prim = (union DL_primitives *)mp->b_rptr; 886 switch (dl_prim->dl_primitive) { 887 case DL_OK_ACK: 888 if ((mp->b_wptr-mp->b_rptr) < sizeof (dl_ok_ack_t)) { 889 printf("dl_attach: DL_OK_ACK protocol error\n"); 890 break; 891 } 892 if (((dl_ok_ack_t *)dl_prim)->dl_correct_primitive != 893 DL_ATTACH_REQ) { 894 printf("dl_attach: DL_OK_ACK rtnd prim %u\n", 895 ((dl_ok_ack_t *)dl_prim)->dl_correct_primitive); 896 break; 897 } 898 freemsg(mp); 899 return (0); 900 901 case DL_ERROR_ACK: 902 if ((mp->b_wptr-mp->b_rptr) < sizeof (dl_error_ack_t)) { 903 printf("dl_attach: DL_ERROR_ACK protocol error\n"); 904 break; 905 } 906 907 error_ack = (dl_error_ack_t *)dl_prim; 908 switch (error_ack->dl_errno) { 909 case DL_BADPPA: 910 printf("dl_attach: DL_ERROR_ACK bad PPA\n"); 911 break; 912 913 case DL_ACCESS: 914 printf("dl_attach: DL_ERROR_ACK access error\n"); 915 break; 916 917 default: 918 printf("dl_attach: DLPI error %u\n", 919 error_ack->dl_errno); 920 break; 921 } 922 break; 923 924 default: 925 printf("dl_attach: bad ACK header %u\n", dl_prim->dl_primitive); 926 break; 927 } 928 929 /* 930 * Error return only. 931 */ 932 freemsg(mp); 933 return (-1); 934 } 935 936 int 937 dl_bind(ldi_handle_t lh, uint_t sap, uint_t max_conn, uint_t service, 938 uint_t conn_mgmt) 939 { 940 dl_bind_req_t *bind_req; 941 dl_error_ack_t *error_ack; 942 union DL_primitives *dl_prim; 943 mblk_t *mp; 944 int error; 945 946 if ((mp = allocb(sizeof (dl_bind_req_t), BPRI_MED)) == NULL) { 947 cmn_err(CE_WARN, "dl_bind: allocb failed"); 948 return (ENOSR); 949 } 950 mp->b_datap->db_type = M_PROTO; 951 952 bind_req = (dl_bind_req_t *)mp->b_wptr; 953 mp->b_wptr += sizeof (dl_bind_req_t); 954 bind_req->dl_primitive = DL_BIND_REQ; 955 bind_req->dl_sap = sap; 956 bind_req->dl_max_conind = max_conn; 957 bind_req->dl_service_mode = service; 958 bind_req->dl_conn_mgmt = conn_mgmt; 959 bind_req->dl_xidtest_flg = 0; 960 961 (void) ldi_putmsg(lh, mp); 962 if ((error = ldi_getmsg(lh, &mp, (timestruc_t *)NULL)) != 0) { 963 printf("dl_bind: ldi_getmsg failed: %d\n", error); 964 return (error); 965 } 966 967 dl_prim = (union DL_primitives *)mp->b_rptr; 968 switch (dl_prim->dl_primitive) { 969 case DL_BIND_ACK: 970 if ((mp->b_wptr-mp->b_rptr) < sizeof (dl_bind_ack_t)) { 971 printf("dl_bind: DL_BIND_ACK protocol error\n"); 972 break; 973 } 974 if (((dl_bind_ack_t *)dl_prim)->dl_sap != sap) { 975 printf("dl_bind: DL_BIND_ACK bad sap %u\n", 976 ((dl_bind_ack_t *)dl_prim)->dl_sap); 977 break; 978 } 979 freemsg(mp); 980 return (0); 981 982 case DL_ERROR_ACK: 983 if ((mp->b_wptr-mp->b_rptr) < sizeof (dl_error_ack_t)) { 984 printf("dl_bind: DL_ERROR_ACK protocol error\n"); 985 break; 986 } 987 988 error_ack = (dl_error_ack_t *)dl_prim; 989 printf("dl_bind: DLPI error %u\n", error_ack->dl_errno); 990 break; 991 992 default: 993 printf("dl_bind: bad ACK header %u\n", dl_prim->dl_primitive); 994 break; 995 } 996 997 /* 998 * Error return only. 999 */ 1000 freemsg(mp); 1001 return (-1); 1002 } 1003 1004 int 1005 dl_phys_addr(ldi_handle_t lh, struct ether_addr *eaddr) 1006 { 1007 dl_phys_addr_req_t *phys_addr_req; 1008 dl_phys_addr_ack_t *phys_addr_ack; 1009 dl_error_ack_t *error_ack; 1010 union DL_primitives *dl_prim; 1011 mblk_t *mp; 1012 int error; 1013 uchar_t *addrp; 1014 timestruc_t tv; 1015 1016 if ((mp = allocb(sizeof (dl_phys_addr_req_t), BPRI_MED)) == 1017 (mblk_t *)NULL) { 1018 cmn_err(CE_WARN, "dl_phys_addr: allocb failed"); 1019 return (ENOSR); 1020 } 1021 mp->b_datap->db_type = M_PROTO; 1022 mp->b_wptr += sizeof (dl_phys_addr_req_t); 1023 1024 phys_addr_req = (dl_phys_addr_req_t *)mp->b_rptr; 1025 phys_addr_req->dl_primitive = DL_PHYS_ADDR_REQ; 1026 phys_addr_req->dl_addr_type = DL_CURR_PHYS_ADDR; 1027 1028 /* 1029 * In case some provider doesn't implement or nack the 1030 * request just wait for 15 seconds. 1031 */ 1032 tv.tv_sec = 15; 1033 tv.tv_nsec = 0; 1034 1035 (void) ldi_putmsg(lh, mp); 1036 error = ldi_getmsg(lh, &mp, &tv); 1037 if (error == ETIME) { 1038 printf("dl_phys_addr: timed out\n"); 1039 return (-1); 1040 } else if (error != 0) { 1041 printf("dl_phys_addr: ldi_getmsg failed: %d\n", error); 1042 return (error); 1043 } 1044 1045 dl_prim = (union DL_primitives *)mp->b_rptr; 1046 switch (dl_prim->dl_primitive) { 1047 case DL_PHYS_ADDR_ACK: 1048 if ((mp->b_wptr-mp->b_rptr) < sizeof (dl_phys_addr_ack_t)) { 1049 printf("dl_phys_addr: " 1050 "DL_PHYS_ADDR_ACK protocol error\n"); 1051 break; 1052 } 1053 phys_addr_ack = &dl_prim->physaddr_ack; 1054 if (phys_addr_ack->dl_addr_length != sizeof (*eaddr)) { 1055 printf("dl_phys_addr: DL_PHYS_ADDR_ACK bad len %u\n", 1056 phys_addr_ack->dl_addr_length); 1057 break; 1058 } 1059 if (phys_addr_ack->dl_addr_length + 1060 phys_addr_ack->dl_addr_offset > (mp->b_wptr-mp->b_rptr)) { 1061 printf("dl_phys_addr: DL_PHYS_ADDR_ACK bad len %u\n", 1062 phys_addr_ack->dl_addr_length); 1063 break; 1064 } 1065 addrp = mp->b_rptr + phys_addr_ack->dl_addr_offset; 1066 bcopy(addrp, eaddr, sizeof (*eaddr)); 1067 freemsg(mp); 1068 return (0); 1069 1070 case DL_ERROR_ACK: 1071 if ((mp->b_wptr-mp->b_rptr) < sizeof (dl_error_ack_t)) { 1072 printf("dl_phys_addr: DL_ERROR_ACK protocol error\n"); 1073 break; 1074 } 1075 1076 error_ack = (dl_error_ack_t *)dl_prim; 1077 printf("dl_phys_addr: DLPI error %u\n", 1078 error_ack->dl_errno); 1079 break; 1080 1081 default: 1082 printf("dl_phys_addr: bad ACK header %u\n", 1083 dl_prim->dl_primitive); 1084 break; 1085 } 1086 1087 /* 1088 * Error return only. 1089 */ 1090 freemsg(mp); 1091 return (-1); 1092 } 1093