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 /* 29 * MAC Services Module 30 */ 31 32 #include <sys/types.h> 33 #include <sys/conf.h> 34 #include <sys/stat.h> 35 #include <sys/stream.h> 36 #include <sys/strsun.h> 37 #include <sys/strsubr.h> 38 #include <sys/dlpi.h> 39 #include <sys/modhash.h> 40 #include <sys/mac.h> 41 #include <sys/mac_impl.h> 42 #include <sys/dls.h> 43 #include <sys/dld.h> 44 #include <sys/modctl.h> 45 #include <sys/fs/dv_node.h> 46 #include <sys/atomic.h> 47 48 #define IMPL_HASHSZ 67 /* prime */ 49 50 static kmem_cache_t *i_mac_impl_cachep; 51 static mod_hash_t *i_mac_impl_hash; 52 krwlock_t i_mac_impl_lock; 53 uint_t i_mac_impl_count; 54 55 #define MACTYPE_KMODDIR "mac" 56 #define MACTYPE_HASHSZ 67 57 static mod_hash_t *i_mactype_hash; 58 /* 59 * i_mactype_lock synchronizes threads that obtain references to mactype_t 60 * structures through i_mactype_getplugin(). 61 */ 62 static kmutex_t i_mactype_lock; 63 64 static void i_mac_notify_task(void *); 65 66 /* 67 * Private functions. 68 */ 69 70 /*ARGSUSED*/ 71 static int 72 i_mac_constructor(void *buf, void *arg, int kmflag) 73 { 74 mac_impl_t *mip = buf; 75 76 bzero(buf, sizeof (mac_impl_t)); 77 78 mip->mi_linkstate = LINK_STATE_UNKNOWN; 79 80 rw_init(&mip->mi_state_lock, NULL, RW_DRIVER, NULL); 81 rw_init(&mip->mi_data_lock, NULL, RW_DRIVER, NULL); 82 rw_init(&mip->mi_notify_lock, NULL, RW_DRIVER, NULL); 83 rw_init(&mip->mi_rx_lock, NULL, RW_DRIVER, NULL); 84 rw_init(&mip->mi_txloop_lock, NULL, RW_DRIVER, NULL); 85 rw_init(&mip->mi_resource_lock, NULL, RW_DRIVER, NULL); 86 mutex_init(&mip->mi_activelink_lock, NULL, MUTEX_DEFAULT, NULL); 87 mutex_init(&mip->mi_notify_ref_lock, NULL, MUTEX_DRIVER, NULL); 88 cv_init(&mip->mi_notify_cv, NULL, CV_DRIVER, NULL); 89 return (0); 90 } 91 92 /*ARGSUSED*/ 93 static void 94 i_mac_destructor(void *buf, void *arg) 95 { 96 mac_impl_t *mip = buf; 97 98 ASSERT(mip->mi_ref == 0); 99 ASSERT(mip->mi_active == 0); 100 ASSERT(mip->mi_linkstate == LINK_STATE_UNKNOWN); 101 ASSERT(mip->mi_devpromisc == 0); 102 ASSERT(mip->mi_promisc == 0); 103 ASSERT(mip->mi_mmap == NULL); 104 ASSERT(mip->mi_mnfp == NULL); 105 ASSERT(mip->mi_resource_add == NULL); 106 ASSERT(mip->mi_ksp == NULL); 107 ASSERT(mip->mi_kstat_count == 0); 108 109 rw_destroy(&mip->mi_state_lock); 110 rw_destroy(&mip->mi_data_lock); 111 rw_destroy(&mip->mi_notify_lock); 112 rw_destroy(&mip->mi_rx_lock); 113 rw_destroy(&mip->mi_txloop_lock); 114 rw_destroy(&mip->mi_resource_lock); 115 mutex_destroy(&mip->mi_activelink_lock); 116 mutex_destroy(&mip->mi_notify_ref_lock); 117 cv_destroy(&mip->mi_notify_cv); 118 } 119 120 static void 121 i_mac_notify(mac_impl_t *mip, mac_notify_type_t type) 122 { 123 mac_notify_task_arg_t *mnta; 124 125 rw_enter(&i_mac_impl_lock, RW_READER); 126 if (mip->mi_disabled) 127 goto exit; 128 129 if ((mnta = kmem_alloc(sizeof (*mnta), KM_NOSLEEP)) == NULL) { 130 cmn_err(CE_WARN, "i_mac_notify(%s, 0x%x): memory " 131 "allocation failed", mip->mi_name, type); 132 goto exit; 133 } 134 135 mnta->mnt_mip = mip; 136 mnta->mnt_type = type; 137 138 mutex_enter(&mip->mi_notify_ref_lock); 139 mip->mi_notify_ref++; 140 mutex_exit(&mip->mi_notify_ref_lock); 141 142 rw_exit(&i_mac_impl_lock); 143 144 if (taskq_dispatch(system_taskq, i_mac_notify_task, mnta, 145 TQ_NOSLEEP) == NULL) { 146 cmn_err(CE_WARN, "i_mac_notify(%s, 0x%x): taskq dispatch " 147 "failed", mip->mi_name, type); 148 149 mutex_enter(&mip->mi_notify_ref_lock); 150 if (--mip->mi_notify_ref == 0) 151 cv_signal(&mip->mi_notify_cv); 152 mutex_exit(&mip->mi_notify_ref_lock); 153 154 kmem_free(mnta, sizeof (*mnta)); 155 } 156 return; 157 158 exit: 159 rw_exit(&i_mac_impl_lock); 160 } 161 162 static void 163 i_mac_log_link_state(mac_impl_t *mip) 164 { 165 /* 166 * If no change, then it is not interesting. 167 */ 168 if (mip->mi_lastlinkstate == mip->mi_linkstate) 169 return; 170 171 switch (mip->mi_linkstate) { 172 case LINK_STATE_UP: 173 if (mip->mi_type->mt_ops.mtops_ops & MTOPS_LINK_DETAILS) { 174 char det[200]; 175 176 mip->mi_type->mt_ops.mtops_link_details(det, 177 sizeof (det), (mac_handle_t)mip, mip->mi_pdata); 178 179 cmn_err(CE_NOTE, "!%s link up, %s", mip->mi_name, det); 180 } else { 181 cmn_err(CE_NOTE, "!%s link up", mip->mi_name); 182 } 183 break; 184 185 case LINK_STATE_DOWN: 186 /* 187 * Only transitions from UP to DOWN are interesting 188 */ 189 if (mip->mi_lastlinkstate != LINK_STATE_UNKNOWN) 190 cmn_err(CE_NOTE, "!%s link down", mip->mi_name); 191 break; 192 193 case LINK_STATE_UNKNOWN: 194 /* 195 * This case is normally not interesting. 196 */ 197 break; 198 } 199 mip->mi_lastlinkstate = mip->mi_linkstate; 200 } 201 202 static void 203 i_mac_notify_task(void *notify_arg) 204 { 205 mac_notify_task_arg_t *mnta = (mac_notify_task_arg_t *)notify_arg; 206 mac_impl_t *mip; 207 mac_notify_type_t type; 208 mac_notify_fn_t *mnfp; 209 mac_notify_t notify; 210 void *arg; 211 212 mip = mnta->mnt_mip; 213 type = mnta->mnt_type; 214 kmem_free(mnta, sizeof (*mnta)); 215 216 /* 217 * Log it. 218 */ 219 if (type == MAC_NOTE_LINK) 220 i_mac_log_link_state(mip); 221 222 /* 223 * Walk the list of notifications. 224 */ 225 rw_enter(&mip->mi_notify_lock, RW_READER); 226 for (mnfp = mip->mi_mnfp; mnfp != NULL; mnfp = mnfp->mnf_nextp) { 227 notify = mnfp->mnf_fn; 228 arg = mnfp->mnf_arg; 229 230 ASSERT(notify != NULL); 231 notify(arg, type); 232 } 233 rw_exit(&mip->mi_notify_lock); 234 mutex_enter(&mip->mi_notify_ref_lock); 235 if (--mip->mi_notify_ref == 0) 236 cv_signal(&mip->mi_notify_cv); 237 mutex_exit(&mip->mi_notify_ref_lock); 238 } 239 240 static mactype_t * 241 i_mactype_getplugin(const char *pname) 242 { 243 mactype_t *mtype = NULL; 244 boolean_t tried_modload = B_FALSE; 245 246 mutex_enter(&i_mactype_lock); 247 248 find_registered_mactype: 249 if (mod_hash_find(i_mactype_hash, (mod_hash_key_t)pname, 250 (mod_hash_val_t *)&mtype) != 0) { 251 if (!tried_modload) { 252 /* 253 * If the plugin has not yet been loaded, then 254 * attempt to load it now. If modload() succeeds, 255 * the plugin should have registered using 256 * mactype_register(), in which case we can go back 257 * and attempt to find it again. 258 */ 259 if (modload(MACTYPE_KMODDIR, (char *)pname) != -1) { 260 tried_modload = B_TRUE; 261 goto find_registered_mactype; 262 } 263 } 264 } else { 265 /* 266 * Note that there's no danger that the plugin we've loaded 267 * could be unloaded between the modload() step and the 268 * reference count bump here, as we're holding 269 * i_mactype_lock, which mactype_unregister() also holds. 270 */ 271 atomic_inc_32(&mtype->mt_ref); 272 } 273 274 mutex_exit(&i_mactype_lock); 275 return (mtype); 276 } 277 278 /* 279 * Module initialization functions. 280 */ 281 282 void 283 mac_init(void) 284 { 285 i_mac_impl_cachep = kmem_cache_create("mac_impl_cache", 286 sizeof (mac_impl_t), 0, i_mac_constructor, i_mac_destructor, 287 NULL, NULL, NULL, 0); 288 ASSERT(i_mac_impl_cachep != NULL); 289 290 i_mac_impl_hash = mod_hash_create_extended("mac_impl_hash", 291 IMPL_HASHSZ, mod_hash_null_keydtor, mod_hash_null_valdtor, 292 mod_hash_bystr, NULL, mod_hash_strkey_cmp, KM_SLEEP); 293 rw_init(&i_mac_impl_lock, NULL, RW_DEFAULT, NULL); 294 i_mac_impl_count = 0; 295 296 i_mactype_hash = mod_hash_create_extended("mactype_hash", 297 MACTYPE_HASHSZ, 298 mod_hash_null_keydtor, mod_hash_null_valdtor, 299 mod_hash_bystr, NULL, mod_hash_strkey_cmp, KM_SLEEP); 300 } 301 302 int 303 mac_fini(void) 304 { 305 if (i_mac_impl_count > 0) 306 return (EBUSY); 307 308 mod_hash_destroy_hash(i_mac_impl_hash); 309 rw_destroy(&i_mac_impl_lock); 310 311 kmem_cache_destroy(i_mac_impl_cachep); 312 313 mod_hash_destroy_hash(i_mactype_hash); 314 return (0); 315 } 316 317 /* 318 * Client functions. 319 */ 320 321 int 322 mac_open(const char *macname, uint_t ddi_instance, mac_handle_t *mhp) 323 { 324 char driver[MAXNAMELEN]; 325 uint_t instance; 326 major_t major; 327 dev_info_t *dip; 328 mac_impl_t *mip; 329 int err; 330 331 /* 332 * Check the device name length to make sure it won't overflow our 333 * buffer. 334 */ 335 if (strlen(macname) >= MAXNAMELEN) 336 return (EINVAL); 337 338 /* 339 * Split the device name into driver and instance components. 340 */ 341 if (ddi_parse(macname, driver, &instance) != DDI_SUCCESS) 342 return (EINVAL); 343 344 /* 345 * Get the major number of the driver. 346 */ 347 if ((major = ddi_name_to_major(driver)) == (major_t)-1) 348 return (EINVAL); 349 350 /* 351 * Hold the given instance to prevent it from being detached. 352 * This will also attach the instance if it is not currently attached. 353 * Currently we ensure that mac_register() (called by the driver's 354 * attach entry point) and all code paths under it cannot possibly 355 * call mac_open() because this would lead to a recursive attach 356 * panic. 357 */ 358 if ((dip = ddi_hold_devi_by_instance(major, ddi_instance, 0)) == NULL) 359 return (EINVAL); 360 361 /* 362 * Look up its entry in the global hash table. 363 */ 364 again: 365 rw_enter(&i_mac_impl_lock, RW_WRITER); 366 err = mod_hash_find(i_mac_impl_hash, (mod_hash_key_t)macname, 367 (mod_hash_val_t *)&mip); 368 if (err != 0) { 369 err = ENOENT; 370 goto failed; 371 } 372 373 if (mip->mi_disabled) { 374 rw_exit(&i_mac_impl_lock); 375 goto again; 376 } 377 378 mip->mi_ref++; 379 rw_exit(&i_mac_impl_lock); 380 381 *mhp = (mac_handle_t)mip; 382 return (0); 383 384 failed: 385 rw_exit(&i_mac_impl_lock); 386 ddi_release_devi(dip); 387 return (err); 388 } 389 390 void 391 mac_close(mac_handle_t mh) 392 { 393 mac_impl_t *mip = (mac_impl_t *)mh; 394 dev_info_t *dip = mip->mi_dip; 395 396 rw_enter(&i_mac_impl_lock, RW_WRITER); 397 398 ASSERT(mip->mi_ref != 0); 399 if (--mip->mi_ref == 0) { 400 ASSERT(!mip->mi_activelink); 401 } 402 ddi_release_devi(dip); 403 rw_exit(&i_mac_impl_lock); 404 } 405 406 const mac_info_t * 407 mac_info(mac_handle_t mh) 408 { 409 return (&((mac_impl_t *)mh)->mi_info); 410 } 411 412 dev_info_t * 413 mac_devinfo_get(mac_handle_t mh) 414 { 415 return (((mac_impl_t *)mh)->mi_dip); 416 } 417 418 uint64_t 419 mac_stat_get(mac_handle_t mh, uint_t stat) 420 { 421 mac_impl_t *mip = (mac_impl_t *)mh; 422 uint64_t val; 423 int ret; 424 425 /* 426 * The range of stat determines where it is maintained. Stat 427 * values from 0 up to (but not including) MAC_STAT_MIN are 428 * mainteined by the mac module itself. Everything else is 429 * maintained by the driver. 430 */ 431 if (stat < MAC_STAT_MIN) { 432 /* These stats are maintained by the mac module itself. */ 433 switch (stat) { 434 case MAC_STAT_LINK_STATE: 435 return (mip->mi_linkstate); 436 case MAC_STAT_LINK_UP: 437 return (mip->mi_linkstate == LINK_STATE_UP); 438 case MAC_STAT_PROMISC: 439 return (mip->mi_devpromisc != 0); 440 default: 441 ASSERT(B_FALSE); 442 } 443 } 444 445 /* 446 * Call the driver to get the given statistic. 447 */ 448 ret = mip->mi_getstat(mip->mi_driver, stat, &val); 449 if (ret != 0) { 450 /* 451 * The driver doesn't support this statistic. Get the 452 * statistic's default value. 453 */ 454 val = mac_stat_default(mip, stat); 455 } 456 return (val); 457 } 458 459 int 460 mac_start(mac_handle_t mh) 461 { 462 mac_impl_t *mip = (mac_impl_t *)mh; 463 int err; 464 465 ASSERT(mip->mi_start != NULL); 466 467 rw_enter(&(mip->mi_state_lock), RW_WRITER); 468 469 /* 470 * Check whether the device is already started. 471 */ 472 if (mip->mi_active++ != 0) { 473 /* 474 * It's already started so there's nothing more to do. 475 */ 476 err = 0; 477 goto done; 478 } 479 480 /* 481 * Start the device. 482 */ 483 if ((err = mip->mi_start(mip->mi_driver)) != 0) 484 --mip->mi_active; 485 486 done: 487 rw_exit(&(mip->mi_state_lock)); 488 return (err); 489 } 490 491 void 492 mac_stop(mac_handle_t mh) 493 { 494 mac_impl_t *mip = (mac_impl_t *)mh; 495 496 ASSERT(mip->mi_stop != NULL); 497 498 rw_enter(&(mip->mi_state_lock), RW_WRITER); 499 500 /* 501 * Check whether the device is still needed. 502 */ 503 ASSERT(mip->mi_active != 0); 504 if (--mip->mi_active != 0) { 505 /* 506 * It's still needed so there's nothing more to do. 507 */ 508 goto done; 509 } 510 511 /* 512 * Stop the device. 513 */ 514 mip->mi_stop(mip->mi_driver); 515 516 done: 517 rw_exit(&(mip->mi_state_lock)); 518 } 519 520 int 521 mac_multicst_add(mac_handle_t mh, const uint8_t *addr) 522 { 523 mac_impl_t *mip = (mac_impl_t *)mh; 524 mac_multicst_addr_t **pp; 525 mac_multicst_addr_t *p; 526 int err; 527 528 ASSERT(mip->mi_multicst != NULL); 529 530 /* 531 * Verify the address. 532 */ 533 if ((err = mip->mi_type->mt_ops.mtops_multicst_verify(addr, 534 mip->mi_pdata)) != 0) { 535 return (err); 536 } 537 538 /* 539 * Check whether the given address is already enabled. 540 */ 541 rw_enter(&(mip->mi_data_lock), RW_WRITER); 542 for (pp = &(mip->mi_mmap); (p = *pp) != NULL; pp = &(p->mma_nextp)) { 543 if (bcmp(p->mma_addr, addr, mip->mi_type->mt_addr_length) == 544 0) { 545 /* 546 * The address is already enabled so just bump the 547 * reference count. 548 */ 549 p->mma_ref++; 550 err = 0; 551 goto done; 552 } 553 } 554 555 /* 556 * Allocate a new list entry. 557 */ 558 if ((p = kmem_zalloc(sizeof (mac_multicst_addr_t), 559 KM_NOSLEEP)) == NULL) { 560 err = ENOMEM; 561 goto done; 562 } 563 564 /* 565 * Enable a new multicast address. 566 */ 567 if ((err = mip->mi_multicst(mip->mi_driver, B_TRUE, addr)) != 0) { 568 kmem_free(p, sizeof (mac_multicst_addr_t)); 569 goto done; 570 } 571 572 /* 573 * Add the address to the list of enabled addresses. 574 */ 575 bcopy(addr, p->mma_addr, mip->mi_type->mt_addr_length); 576 p->mma_ref++; 577 *pp = p; 578 579 done: 580 rw_exit(&(mip->mi_data_lock)); 581 return (err); 582 } 583 584 int 585 mac_multicst_remove(mac_handle_t mh, const uint8_t *addr) 586 { 587 mac_impl_t *mip = (mac_impl_t *)mh; 588 mac_multicst_addr_t **pp; 589 mac_multicst_addr_t *p; 590 int err; 591 592 ASSERT(mip->mi_multicst != NULL); 593 594 /* 595 * Find the entry in the list for the given address. 596 */ 597 rw_enter(&(mip->mi_data_lock), RW_WRITER); 598 for (pp = &(mip->mi_mmap); (p = *pp) != NULL; pp = &(p->mma_nextp)) { 599 if (bcmp(p->mma_addr, addr, mip->mi_type->mt_addr_length) == 600 0) { 601 if (--p->mma_ref == 0) 602 break; 603 604 /* 605 * There is still a reference to this address so 606 * there's nothing more to do. 607 */ 608 err = 0; 609 goto done; 610 } 611 } 612 613 /* 614 * We did not find an entry for the given address so it is not 615 * currently enabled. 616 */ 617 if (p == NULL) { 618 err = ENOENT; 619 goto done; 620 } 621 ASSERT(p->mma_ref == 0); 622 623 /* 624 * Disable the multicast address. 625 */ 626 if ((err = mip->mi_multicst(mip->mi_driver, B_FALSE, addr)) != 0) { 627 p->mma_ref++; 628 goto done; 629 } 630 631 /* 632 * Remove it from the list. 633 */ 634 *pp = p->mma_nextp; 635 kmem_free(p, sizeof (mac_multicst_addr_t)); 636 637 done: 638 rw_exit(&(mip->mi_data_lock)); 639 return (err); 640 } 641 642 /* 643 * mac_unicst_verify: Verifies the passed address. It fails 644 * if the passed address is a group address or has incorrect length. 645 */ 646 boolean_t 647 mac_unicst_verify(mac_handle_t mh, const uint8_t *addr, uint_t len) 648 { 649 mac_impl_t *mip = (mac_impl_t *)mh; 650 651 /* 652 * Verify the address. 653 */ 654 if ((len != mip->mi_type->mt_addr_length) || 655 (mip->mi_type->mt_ops.mtops_unicst_verify(addr, 656 mip->mi_pdata)) != 0) { 657 return (B_FALSE); 658 } else { 659 return (B_TRUE); 660 } 661 } 662 663 int 664 mac_unicst_set(mac_handle_t mh, const uint8_t *addr) 665 { 666 mac_impl_t *mip = (mac_impl_t *)mh; 667 int err; 668 boolean_t notify = B_FALSE; 669 670 ASSERT(mip->mi_unicst != NULL); 671 672 /* 673 * Verify the address. 674 */ 675 if ((err = mip->mi_type->mt_ops.mtops_unicst_verify(addr, 676 mip->mi_pdata)) != 0) { 677 return (err); 678 } 679 680 /* 681 * Program the new unicast address. 682 */ 683 rw_enter(&(mip->mi_data_lock), RW_WRITER); 684 685 /* 686 * If address doesn't change, do nothing. 687 * This check is necessary otherwise it may call into mac_unicst_set 688 * recursively. 689 */ 690 if (bcmp(addr, mip->mi_addr, mip->mi_type->mt_addr_length) == 0) { 691 err = 0; 692 goto done; 693 } 694 695 if ((err = mip->mi_unicst(mip->mi_driver, addr)) != 0) 696 goto done; 697 698 /* 699 * Save the address and flag that we need to send a notification. 700 */ 701 bcopy(addr, mip->mi_addr, mip->mi_type->mt_addr_length); 702 notify = B_TRUE; 703 704 done: 705 rw_exit(&(mip->mi_data_lock)); 706 707 if (notify) 708 i_mac_notify(mip, MAC_NOTE_UNICST); 709 710 return (err); 711 } 712 713 void 714 mac_unicst_get(mac_handle_t mh, uint8_t *addr) 715 { 716 mac_impl_t *mip = (mac_impl_t *)mh; 717 718 /* 719 * Copy out the current unicast source address. 720 */ 721 rw_enter(&(mip->mi_data_lock), RW_READER); 722 bcopy(mip->mi_addr, addr, mip->mi_type->mt_addr_length); 723 rw_exit(&(mip->mi_data_lock)); 724 } 725 726 void 727 mac_dest_get(mac_handle_t mh, uint8_t *addr) 728 { 729 mac_impl_t *mip = (mac_impl_t *)mh; 730 731 /* 732 * Copy out the current destination address. 733 */ 734 rw_enter(&(mip->mi_data_lock), RW_READER); 735 bcopy(mip->mi_dstaddr, addr, mip->mi_type->mt_addr_length); 736 rw_exit(&(mip->mi_data_lock)); 737 } 738 739 int 740 mac_promisc_set(mac_handle_t mh, boolean_t on, mac_promisc_type_t ptype) 741 { 742 mac_impl_t *mip = (mac_impl_t *)mh; 743 int err = 0; 744 745 ASSERT(mip->mi_setpromisc != NULL); 746 ASSERT(ptype == MAC_DEVPROMISC || ptype == MAC_PROMISC); 747 748 /* 749 * Determine whether we should enable or disable promiscuous mode. 750 * For details on the distinction between "device promiscuous mode" 751 * and "MAC promiscuous mode", see PSARC/2005/289. 752 */ 753 rw_enter(&(mip->mi_data_lock), RW_WRITER); 754 if (on) { 755 /* 756 * Enable promiscuous mode on the device if not yet enabled. 757 */ 758 if (mip->mi_devpromisc++ == 0) { 759 err = mip->mi_setpromisc(mip->mi_driver, B_TRUE); 760 if (err != 0) { 761 mip->mi_devpromisc--; 762 goto done; 763 } 764 i_mac_notify(mip, MAC_NOTE_DEVPROMISC); 765 } 766 767 /* 768 * Enable promiscuous mode on the MAC if not yet enabled. 769 */ 770 if (ptype == MAC_PROMISC && mip->mi_promisc++ == 0) 771 i_mac_notify(mip, MAC_NOTE_PROMISC); 772 } else { 773 if (mip->mi_devpromisc == 0) { 774 err = EPROTO; 775 goto done; 776 } 777 778 /* 779 * Disable promiscuous mode on the device if this is the last 780 * enabling. 781 */ 782 if (--mip->mi_devpromisc == 0) { 783 err = mip->mi_setpromisc(mip->mi_driver, B_FALSE); 784 if (err != 0) { 785 mip->mi_devpromisc++; 786 goto done; 787 } 788 i_mac_notify(mip, MAC_NOTE_DEVPROMISC); 789 } 790 791 /* 792 * Disable promiscuous mode on the MAC if this is the last 793 * enabling. 794 */ 795 if (ptype == MAC_PROMISC && --mip->mi_promisc == 0) 796 i_mac_notify(mip, MAC_NOTE_PROMISC); 797 } 798 799 done: 800 rw_exit(&(mip->mi_data_lock)); 801 return (err); 802 } 803 804 boolean_t 805 mac_promisc_get(mac_handle_t mh, mac_promisc_type_t ptype) 806 { 807 mac_impl_t *mip = (mac_impl_t *)mh; 808 809 ASSERT(ptype == MAC_DEVPROMISC || ptype == MAC_PROMISC); 810 811 /* 812 * Return the current promiscuity. 813 */ 814 if (ptype == MAC_DEVPROMISC) 815 return (mip->mi_devpromisc != 0); 816 else 817 return (mip->mi_promisc != 0); 818 } 819 820 void 821 mac_resources(mac_handle_t mh) 822 { 823 mac_impl_t *mip = (mac_impl_t *)mh; 824 825 /* 826 * If the driver supports resource registration, call the driver to 827 * ask it to register its resources. 828 */ 829 if (mip->mi_callbacks->mc_callbacks & MC_RESOURCES) 830 mip->mi_resources(mip->mi_driver); 831 } 832 833 void 834 mac_ioctl(mac_handle_t mh, queue_t *wq, mblk_t *bp) 835 { 836 mac_impl_t *mip = (mac_impl_t *)mh; 837 838 /* 839 * Call the driver to handle the ioctl. The driver may not support 840 * any ioctls, in which case we reply with a NAK on its behalf. 841 */ 842 if (mip->mi_callbacks->mc_callbacks & MC_IOCTL) 843 mip->mi_ioctl(mip->mi_driver, wq, bp); 844 else 845 miocnak(wq, bp, 0, EINVAL); 846 } 847 848 const mac_txinfo_t * 849 mac_tx_get(mac_handle_t mh) 850 { 851 mac_impl_t *mip = (mac_impl_t *)mh; 852 mac_txinfo_t *mtp; 853 854 /* 855 * Grab the lock to prevent us from racing with MAC_PROMISC being 856 * changed. This is sufficient since MAC clients are careful to always 857 * call mac_txloop_add() prior to enabling MAC_PROMISC, and to disable 858 * MAC_PROMISC prior to calling mac_txloop_remove(). 859 */ 860 rw_enter(&mip->mi_txloop_lock, RW_READER); 861 862 if (mac_promisc_get(mh, MAC_PROMISC)) { 863 ASSERT(mip->mi_mtfp != NULL); 864 mtp = &mip->mi_txloopinfo; 865 } else { 866 /* 867 * Note that we cannot ASSERT() that mip->mi_mtfp is NULL, 868 * because to satisfy the above ASSERT(), we have to disable 869 * MAC_PROMISC prior to calling mac_txloop_remove(). 870 */ 871 mtp = &mip->mi_txinfo; 872 } 873 874 rw_exit(&mip->mi_txloop_lock); 875 return (mtp); 876 } 877 878 link_state_t 879 mac_link_get(mac_handle_t mh) 880 { 881 return (((mac_impl_t *)mh)->mi_linkstate); 882 } 883 884 mac_notify_handle_t 885 mac_notify_add(mac_handle_t mh, mac_notify_t notify, void *arg) 886 { 887 mac_impl_t *mip = (mac_impl_t *)mh; 888 mac_notify_fn_t *mnfp; 889 890 mnfp = kmem_zalloc(sizeof (mac_notify_fn_t), KM_SLEEP); 891 mnfp->mnf_fn = notify; 892 mnfp->mnf_arg = arg; 893 894 /* 895 * Add it to the head of the 'notify' callback list. 896 */ 897 rw_enter(&mip->mi_notify_lock, RW_WRITER); 898 mnfp->mnf_nextp = mip->mi_mnfp; 899 mip->mi_mnfp = mnfp; 900 rw_exit(&mip->mi_notify_lock); 901 902 return ((mac_notify_handle_t)mnfp); 903 } 904 905 void 906 mac_notify_remove(mac_handle_t mh, mac_notify_handle_t mnh) 907 { 908 mac_impl_t *mip = (mac_impl_t *)mh; 909 mac_notify_fn_t *mnfp = (mac_notify_fn_t *)mnh; 910 mac_notify_fn_t **pp; 911 mac_notify_fn_t *p; 912 913 /* 914 * Search the 'notify' callback list for the function closure. 915 */ 916 rw_enter(&mip->mi_notify_lock, RW_WRITER); 917 for (pp = &(mip->mi_mnfp); (p = *pp) != NULL; 918 pp = &(p->mnf_nextp)) { 919 if (p == mnfp) 920 break; 921 } 922 ASSERT(p != NULL); 923 924 /* 925 * Remove it from the list. 926 */ 927 *pp = p->mnf_nextp; 928 rw_exit(&mip->mi_notify_lock); 929 930 /* 931 * Free it. 932 */ 933 kmem_free(mnfp, sizeof (mac_notify_fn_t)); 934 } 935 936 void 937 mac_notify(mac_handle_t mh) 938 { 939 mac_impl_t *mip = (mac_impl_t *)mh; 940 mac_notify_type_t type; 941 942 for (type = 0; type < MAC_NNOTE; type++) 943 i_mac_notify(mip, type); 944 } 945 946 mac_rx_handle_t 947 mac_rx_add(mac_handle_t mh, mac_rx_t rx, void *arg) 948 { 949 mac_impl_t *mip = (mac_impl_t *)mh; 950 mac_rx_fn_t *mrfp; 951 952 mrfp = kmem_zalloc(sizeof (mac_rx_fn_t), KM_SLEEP); 953 mrfp->mrf_fn = rx; 954 mrfp->mrf_arg = arg; 955 956 /* 957 * Add it to the head of the 'rx' callback list. 958 */ 959 rw_enter(&(mip->mi_rx_lock), RW_WRITER); 960 mrfp->mrf_nextp = mip->mi_mrfp; 961 mip->mi_mrfp = mrfp; 962 rw_exit(&(mip->mi_rx_lock)); 963 964 return ((mac_rx_handle_t)mrfp); 965 } 966 967 /* 968 * Unregister a receive function for this mac. This removes the function 969 * from the list of receive functions for this mac. 970 */ 971 void 972 mac_rx_remove(mac_handle_t mh, mac_rx_handle_t mrh) 973 { 974 mac_impl_t *mip = (mac_impl_t *)mh; 975 mac_rx_fn_t *mrfp = (mac_rx_fn_t *)mrh; 976 mac_rx_fn_t **pp; 977 mac_rx_fn_t *p; 978 979 /* 980 * Search the 'rx' callback list for the function closure. 981 */ 982 rw_enter(&(mip->mi_rx_lock), RW_WRITER); 983 for (pp = &(mip->mi_mrfp); (p = *pp) != NULL; pp = &(p->mrf_nextp)) { 984 if (p == mrfp) 985 break; 986 } 987 ASSERT(p != NULL); 988 989 /* Remove it from the list. */ 990 *pp = p->mrf_nextp; 991 kmem_free(mrfp, sizeof (mac_rx_fn_t)); 992 rw_exit(&(mip->mi_rx_lock)); 993 } 994 995 mac_txloop_handle_t 996 mac_txloop_add(mac_handle_t mh, mac_txloop_t tx, void *arg) 997 { 998 mac_impl_t *mip = (mac_impl_t *)mh; 999 mac_txloop_fn_t *mtfp; 1000 1001 mtfp = kmem_zalloc(sizeof (mac_txloop_fn_t), KM_SLEEP); 1002 mtfp->mtf_fn = tx; 1003 mtfp->mtf_arg = arg; 1004 1005 /* 1006 * Add it to the head of the 'tx' callback list. 1007 */ 1008 rw_enter(&(mip->mi_txloop_lock), RW_WRITER); 1009 mtfp->mtf_nextp = mip->mi_mtfp; 1010 mip->mi_mtfp = mtfp; 1011 rw_exit(&(mip->mi_txloop_lock)); 1012 1013 return ((mac_txloop_handle_t)mtfp); 1014 } 1015 1016 /* 1017 * Unregister a transmit function for this mac. This removes the function 1018 * from the list of transmit functions for this mac. 1019 */ 1020 void 1021 mac_txloop_remove(mac_handle_t mh, mac_txloop_handle_t mth) 1022 { 1023 mac_impl_t *mip = (mac_impl_t *)mh; 1024 mac_txloop_fn_t *mtfp = (mac_txloop_fn_t *)mth; 1025 mac_txloop_fn_t **pp; 1026 mac_txloop_fn_t *p; 1027 1028 /* 1029 * Search the 'tx' callback list for the function. 1030 */ 1031 rw_enter(&(mip->mi_txloop_lock), RW_WRITER); 1032 for (pp = &(mip->mi_mtfp); (p = *pp) != NULL; pp = &(p->mtf_nextp)) { 1033 if (p == mtfp) 1034 break; 1035 } 1036 ASSERT(p != NULL); 1037 1038 /* Remove it from the list. */ 1039 *pp = p->mtf_nextp; 1040 kmem_free(mtfp, sizeof (mac_txloop_fn_t)); 1041 rw_exit(&(mip->mi_txloop_lock)); 1042 } 1043 1044 void 1045 mac_resource_set(mac_handle_t mh, mac_resource_add_t add, void *arg) 1046 { 1047 mac_impl_t *mip = (mac_impl_t *)mh; 1048 1049 /* 1050 * Update the 'resource_add' callbacks. 1051 */ 1052 rw_enter(&(mip->mi_resource_lock), RW_WRITER); 1053 mip->mi_resource_add = add; 1054 mip->mi_resource_add_arg = arg; 1055 rw_exit(&(mip->mi_resource_lock)); 1056 } 1057 1058 /* 1059 * Driver support functions. 1060 */ 1061 1062 mac_register_t * 1063 mac_alloc(uint_t mac_version) 1064 { 1065 mac_register_t *mregp; 1066 1067 /* 1068 * Make sure there isn't a version mismatch between the driver and 1069 * the framework. In the future, if multiple versions are 1070 * supported, this check could become more sophisticated. 1071 */ 1072 if (mac_version != MAC_VERSION) 1073 return (NULL); 1074 1075 mregp = kmem_zalloc(sizeof (mac_register_t), KM_SLEEP); 1076 mregp->m_version = mac_version; 1077 return (mregp); 1078 } 1079 1080 void 1081 mac_free(mac_register_t *mregp) 1082 { 1083 kmem_free(mregp, sizeof (mac_register_t)); 1084 } 1085 1086 /* 1087 * mac_register() is how drivers register new MACs with the GLDv3 1088 * framework. The mregp argument is allocated by drivers using the 1089 * mac_alloc() function, and can be freed using mac_free() immediately upon 1090 * return from mac_register(). Upon success (0 return value), the mhp 1091 * opaque pointer becomes the driver's handle to its MAC interface, and is 1092 * the argument to all other mac module entry points. 1093 */ 1094 int 1095 mac_register(mac_register_t *mregp, mac_handle_t *mhp) 1096 { 1097 mac_impl_t *mip; 1098 mactype_t *mtype; 1099 int err = EINVAL; 1100 struct devnames *dnp; 1101 minor_t minor; 1102 boolean_t style1_created = B_FALSE, style2_created = B_FALSE; 1103 1104 /* Find the required MAC-Type plugin. */ 1105 if ((mtype = i_mactype_getplugin(mregp->m_type_ident)) == NULL) 1106 return (EINVAL); 1107 1108 /* Create a mac_impl_t to represent this MAC. */ 1109 mip = kmem_cache_alloc(i_mac_impl_cachep, KM_SLEEP); 1110 1111 /* 1112 * The mac is not ready for open yet. 1113 */ 1114 mip->mi_disabled = B_TRUE; 1115 1116 mip->mi_drvname = ddi_driver_name(mregp->m_dip); 1117 /* 1118 * Some drivers such as aggr need to register multiple MACs. Such 1119 * drivers must supply a non-zero "instance" argument so that each 1120 * MAC can be assigned a unique MAC name and can have unique 1121 * kstats. 1122 */ 1123 mip->mi_instance = ((mregp->m_instance == 0) ? 1124 ddi_get_instance(mregp->m_dip) : mregp->m_instance); 1125 1126 /* Construct the MAC name as <drvname><instance> */ 1127 (void) snprintf(mip->mi_name, sizeof (mip->mi_name), "%s%d", 1128 mip->mi_drvname, mip->mi_instance); 1129 1130 mip->mi_driver = mregp->m_driver; 1131 1132 mip->mi_type = mtype; 1133 mip->mi_info.mi_media = mtype->mt_type; 1134 mip->mi_info.mi_nativemedia = mtype->mt_nativetype; 1135 mip->mi_info.mi_sdu_min = mregp->m_min_sdu; 1136 if (mregp->m_max_sdu <= mregp->m_min_sdu) 1137 goto fail; 1138 mip->mi_info.mi_sdu_max = mregp->m_max_sdu; 1139 mip->mi_info.mi_addr_length = mip->mi_type->mt_addr_length; 1140 /* 1141 * If the media supports a broadcast address, cache a pointer to it 1142 * in the mac_info_t so that upper layers can use it. 1143 */ 1144 mip->mi_info.mi_brdcst_addr = mip->mi_type->mt_brdcst_addr; 1145 1146 /* 1147 * Copy the unicast source address into the mac_info_t, but only if 1148 * the MAC-Type defines a non-zero address length. We need to 1149 * handle MAC-Types that have an address length of 0 1150 * (point-to-point protocol MACs for example). 1151 */ 1152 if (mip->mi_type->mt_addr_length > 0) { 1153 if (mregp->m_src_addr == NULL) 1154 goto fail; 1155 mip->mi_info.mi_unicst_addr = 1156 kmem_alloc(mip->mi_type->mt_addr_length, KM_SLEEP); 1157 bcopy(mregp->m_src_addr, mip->mi_info.mi_unicst_addr, 1158 mip->mi_type->mt_addr_length); 1159 1160 /* 1161 * Copy the fixed 'factory' MAC address from the immutable 1162 * info. This is taken to be the MAC address currently in 1163 * use. 1164 */ 1165 bcopy(mip->mi_info.mi_unicst_addr, mip->mi_addr, 1166 mip->mi_type->mt_addr_length); 1167 /* Copy the destination address if one is provided. */ 1168 if (mregp->m_dst_addr != NULL) { 1169 bcopy(mregp->m_dst_addr, mip->mi_dstaddr, 1170 mip->mi_type->mt_addr_length); 1171 } 1172 } else if (mregp->m_src_addr != NULL) { 1173 goto fail; 1174 } 1175 1176 /* 1177 * The format of the m_pdata is specific to the plugin. It is 1178 * passed in as an argument to all of the plugin callbacks. The 1179 * driver can update this information by calling 1180 * mac_pdata_update(). 1181 */ 1182 if (mregp->m_pdata != NULL) { 1183 /* 1184 * Verify that the plugin supports MAC plugin data and that 1185 * the supplied data is valid. 1186 */ 1187 if (!(mip->mi_type->mt_ops.mtops_ops & MTOPS_PDATA_VERIFY)) 1188 goto fail; 1189 if (!mip->mi_type->mt_ops.mtops_pdata_verify(mregp->m_pdata, 1190 mregp->m_pdata_size)) { 1191 goto fail; 1192 } 1193 mip->mi_pdata = kmem_alloc(mregp->m_pdata_size, KM_SLEEP); 1194 bcopy(mregp->m_pdata, mip->mi_pdata, mregp->m_pdata_size); 1195 mip->mi_pdata_size = mregp->m_pdata_size; 1196 } 1197 1198 /* 1199 * Stash the driver callbacks into the mac_impl_t, but first sanity 1200 * check to make sure all mandatory callbacks are set. 1201 */ 1202 if (mregp->m_callbacks->mc_getstat == NULL || 1203 mregp->m_callbacks->mc_start == NULL || 1204 mregp->m_callbacks->mc_stop == NULL || 1205 mregp->m_callbacks->mc_setpromisc == NULL || 1206 mregp->m_callbacks->mc_multicst == NULL || 1207 mregp->m_callbacks->mc_unicst == NULL || 1208 mregp->m_callbacks->mc_tx == NULL) { 1209 goto fail; 1210 } 1211 mip->mi_callbacks = mregp->m_callbacks; 1212 1213 mip->mi_dip = mregp->m_dip; 1214 1215 /* 1216 * Set up the two possible transmit routines. 1217 */ 1218 mip->mi_txinfo.mt_fn = mip->mi_tx; 1219 mip->mi_txinfo.mt_arg = mip->mi_driver; 1220 mip->mi_txloopinfo.mt_fn = mac_txloop; 1221 mip->mi_txloopinfo.mt_arg = mip; 1222 1223 /* 1224 * Initialize the kstats for this device. 1225 */ 1226 mac_stat_create(mip); 1227 1228 err = EEXIST; 1229 /* Create a style-2 DLPI device */ 1230 if (ddi_create_minor_node(mip->mi_dip, (char *)mip->mi_drvname, 1231 S_IFCHR, 0, DDI_NT_NET, CLONE_DEV) != DDI_SUCCESS) 1232 goto fail; 1233 style2_created = B_TRUE; 1234 1235 /* Create a style-1 DLPI device */ 1236 minor = (minor_t)mip->mi_instance + 1; 1237 if (ddi_create_minor_node(mip->mi_dip, mip->mi_name, S_IFCHR, minor, 1238 DDI_NT_NET, 0) != DDI_SUCCESS) 1239 goto fail; 1240 style1_created = B_TRUE; 1241 1242 /* 1243 * Create a link for this MAC. The link name will be the same as 1244 * the MAC name. 1245 */ 1246 err = dls_create(mip->mi_name, mip->mi_name, 1247 ddi_get_instance(mip->mi_dip)); 1248 if (err != 0) 1249 goto fail; 1250 1251 /* set the gldv3 flag in dn_flags */ 1252 dnp = &devnamesp[ddi_driver_major(mip->mi_dip)]; 1253 LOCK_DEV_OPS(&dnp->dn_lock); 1254 dnp->dn_flags |= DN_GLDV3_DRIVER; 1255 UNLOCK_DEV_OPS(&dnp->dn_lock); 1256 1257 rw_enter(&i_mac_impl_lock, RW_WRITER); 1258 if (mod_hash_insert(i_mac_impl_hash, 1259 (mod_hash_key_t)mip->mi_name, (mod_hash_val_t)mip) != 0) { 1260 rw_exit(&i_mac_impl_lock); 1261 VERIFY(dls_destroy(mip->mi_name) == 0); 1262 err = EEXIST; 1263 goto fail; 1264 } 1265 1266 /* 1267 * Mark the MAC to be ready for open. 1268 */ 1269 mip->mi_disabled = B_FALSE; 1270 1271 cmn_err(CE_NOTE, "!%s registered", mip->mi_name); 1272 1273 rw_exit(&i_mac_impl_lock); 1274 1275 atomic_inc_32(&i_mac_impl_count); 1276 *mhp = (mac_handle_t)mip; 1277 return (0); 1278 1279 fail: 1280 if (mip->mi_info.mi_unicst_addr != NULL) { 1281 kmem_free(mip->mi_info.mi_unicst_addr, 1282 mip->mi_type->mt_addr_length); 1283 mip->mi_info.mi_unicst_addr = NULL; 1284 } 1285 if (style1_created) 1286 ddi_remove_minor_node(mip->mi_dip, mip->mi_name); 1287 if (style2_created) 1288 ddi_remove_minor_node(mip->mi_dip, (char *)mip->mi_drvname); 1289 1290 mac_stat_destroy(mip); 1291 1292 if (mip->mi_type != NULL) { 1293 atomic_dec_32(&mip->mi_type->mt_ref); 1294 mip->mi_type = NULL; 1295 } 1296 1297 if (mip->mi_pdata != NULL) { 1298 kmem_free(mip->mi_pdata, mip->mi_pdata_size); 1299 mip->mi_pdata = NULL; 1300 mip->mi_pdata_size = 0; 1301 } 1302 1303 kmem_cache_free(i_mac_impl_cachep, mip); 1304 return (err); 1305 } 1306 1307 int 1308 mac_unregister(mac_handle_t mh) 1309 { 1310 int err; 1311 mac_impl_t *mip = (mac_impl_t *)mh; 1312 mod_hash_val_t val; 1313 mac_multicst_addr_t *p, *nextp; 1314 1315 /* 1316 * See if there are any other references to this mac_t (e.g., VLAN's). 1317 * If not, set mi_disabled to prevent any new VLAN's from being 1318 * created while we're destroying this mac. 1319 */ 1320 rw_enter(&i_mac_impl_lock, RW_WRITER); 1321 if (mip->mi_ref > 0) { 1322 rw_exit(&i_mac_impl_lock); 1323 return (EBUSY); 1324 } 1325 mip->mi_disabled = B_TRUE; 1326 rw_exit(&i_mac_impl_lock); 1327 1328 /* 1329 * Wait for all taskqs which process the mac notifications to finish. 1330 */ 1331 mutex_enter(&mip->mi_notify_ref_lock); 1332 while (mip->mi_notify_ref != 0) 1333 cv_wait(&mip->mi_notify_cv, &mip->mi_notify_ref_lock); 1334 mutex_exit(&mip->mi_notify_ref_lock); 1335 1336 if ((err = dls_destroy(mip->mi_name)) != 0) { 1337 rw_enter(&i_mac_impl_lock, RW_WRITER); 1338 mip->mi_disabled = B_FALSE; 1339 rw_exit(&i_mac_impl_lock); 1340 return (err); 1341 } 1342 1343 /* 1344 * Remove both style 1 and style 2 minor nodes 1345 */ 1346 ddi_remove_minor_node(mip->mi_dip, (char *)mip->mi_drvname); 1347 ddi_remove_minor_node(mip->mi_dip, mip->mi_name); 1348 1349 ASSERT(!mip->mi_activelink); 1350 1351 mac_stat_destroy(mip); 1352 1353 (void) mod_hash_remove(i_mac_impl_hash, (mod_hash_key_t)mip->mi_name, 1354 &val); 1355 ASSERT(mip == (mac_impl_t *)val); 1356 1357 ASSERT(i_mac_impl_count > 0); 1358 atomic_dec_32(&i_mac_impl_count); 1359 1360 if (mip->mi_pdata != NULL) 1361 kmem_free(mip->mi_pdata, mip->mi_pdata_size); 1362 mip->mi_pdata = NULL; 1363 mip->mi_pdata_size = 0; 1364 1365 /* 1366 * Free the list of multicast addresses. 1367 */ 1368 for (p = mip->mi_mmap; p != NULL; p = nextp) { 1369 nextp = p->mma_nextp; 1370 kmem_free(p, sizeof (mac_multicst_addr_t)); 1371 } 1372 mip->mi_mmap = NULL; 1373 1374 mip->mi_linkstate = LINK_STATE_UNKNOWN; 1375 kmem_free(mip->mi_info.mi_unicst_addr, mip->mi_type->mt_addr_length); 1376 mip->mi_info.mi_unicst_addr = NULL; 1377 1378 atomic_dec_32(&mip->mi_type->mt_ref); 1379 mip->mi_type = NULL; 1380 1381 cmn_err(CE_NOTE, "!%s unregistered", mip->mi_name); 1382 1383 kmem_cache_free(i_mac_impl_cachep, mip); 1384 1385 return (0); 1386 } 1387 1388 void 1389 mac_rx(mac_handle_t mh, mac_resource_handle_t mrh, mblk_t *bp) 1390 { 1391 mac_impl_t *mip = (mac_impl_t *)mh; 1392 mac_rx_fn_t *mrfp; 1393 1394 /* 1395 * Call all registered receive functions. 1396 */ 1397 rw_enter(&mip->mi_rx_lock, RW_READER); 1398 mrfp = mip->mi_mrfp; 1399 if (mrfp == NULL) { 1400 /* There are no registered receive functions. */ 1401 freemsgchain(bp); 1402 rw_exit(&mip->mi_rx_lock); 1403 return; 1404 } 1405 do { 1406 mblk_t *recv_bp; 1407 1408 if (mrfp->mrf_nextp != NULL) { 1409 /* XXX Do we bump a counter if copymsgchain() fails? */ 1410 recv_bp = copymsgchain(bp); 1411 } else { 1412 recv_bp = bp; 1413 } 1414 if (recv_bp != NULL) 1415 mrfp->mrf_fn(mrfp->mrf_arg, mrh, recv_bp); 1416 mrfp = mrfp->mrf_nextp; 1417 } while (mrfp != NULL); 1418 rw_exit(&mip->mi_rx_lock); 1419 } 1420 1421 /* 1422 * Transmit function -- ONLY used when there are registered loopback listeners. 1423 */ 1424 mblk_t * 1425 mac_txloop(void *arg, mblk_t *bp) 1426 { 1427 mac_impl_t *mip = arg; 1428 mac_txloop_fn_t *mtfp; 1429 mblk_t *loop_bp, *resid_bp, *next_bp; 1430 1431 while (bp != NULL) { 1432 next_bp = bp->b_next; 1433 bp->b_next = NULL; 1434 1435 if ((loop_bp = copymsg(bp)) == NULL) 1436 goto noresources; 1437 1438 if ((resid_bp = mip->mi_tx(mip->mi_driver, bp)) != NULL) { 1439 ASSERT(resid_bp == bp); 1440 freemsg(loop_bp); 1441 goto noresources; 1442 } 1443 1444 rw_enter(&mip->mi_txloop_lock, RW_READER); 1445 mtfp = mip->mi_mtfp; 1446 while (mtfp != NULL && loop_bp != NULL) { 1447 bp = loop_bp; 1448 1449 /* XXX counter bump if copymsg() fails? */ 1450 if (mtfp->mtf_nextp != NULL) 1451 loop_bp = copymsg(bp); 1452 else 1453 loop_bp = NULL; 1454 1455 mtfp->mtf_fn(mtfp->mtf_arg, bp); 1456 mtfp = mtfp->mtf_nextp; 1457 } 1458 rw_exit(&mip->mi_txloop_lock); 1459 1460 /* 1461 * It's possible we've raced with the disabling of promiscuous 1462 * mode, in which case we can discard our copy. 1463 */ 1464 if (loop_bp != NULL) 1465 freemsg(loop_bp); 1466 1467 bp = next_bp; 1468 } 1469 1470 return (NULL); 1471 1472 noresources: 1473 bp->b_next = next_bp; 1474 return (bp); 1475 } 1476 1477 void 1478 mac_link_update(mac_handle_t mh, link_state_t link) 1479 { 1480 mac_impl_t *mip = (mac_impl_t *)mh; 1481 1482 /* 1483 * Save the link state. 1484 */ 1485 mip->mi_linkstate = link; 1486 1487 /* 1488 * Send a MAC_NOTE_LINK notification. 1489 */ 1490 i_mac_notify(mip, MAC_NOTE_LINK); 1491 } 1492 1493 void 1494 mac_unicst_update(mac_handle_t mh, const uint8_t *addr) 1495 { 1496 mac_impl_t *mip = (mac_impl_t *)mh; 1497 1498 if (mip->mi_type->mt_addr_length == 0) 1499 return; 1500 1501 /* 1502 * Save the address. 1503 */ 1504 bcopy(addr, mip->mi_addr, mip->mi_type->mt_addr_length); 1505 1506 /* 1507 * Send a MAC_NOTE_UNICST notification. 1508 */ 1509 i_mac_notify(mip, MAC_NOTE_UNICST); 1510 } 1511 1512 void 1513 mac_tx_update(mac_handle_t mh) 1514 { 1515 /* 1516 * Send a MAC_NOTE_TX notification. 1517 */ 1518 i_mac_notify((mac_impl_t *)mh, MAC_NOTE_TX); 1519 } 1520 1521 void 1522 mac_resource_update(mac_handle_t mh) 1523 { 1524 /* 1525 * Send a MAC_NOTE_RESOURCE notification. 1526 */ 1527 i_mac_notify((mac_impl_t *)mh, MAC_NOTE_RESOURCE); 1528 } 1529 1530 mac_resource_handle_t 1531 mac_resource_add(mac_handle_t mh, mac_resource_t *mrp) 1532 { 1533 mac_impl_t *mip = (mac_impl_t *)mh; 1534 mac_resource_handle_t mrh; 1535 mac_resource_add_t add; 1536 void *arg; 1537 1538 rw_enter(&mip->mi_resource_lock, RW_READER); 1539 add = mip->mi_resource_add; 1540 arg = mip->mi_resource_add_arg; 1541 1542 if (add != NULL) 1543 mrh = add(arg, mrp); 1544 else 1545 mrh = NULL; 1546 rw_exit(&mip->mi_resource_lock); 1547 1548 return (mrh); 1549 } 1550 1551 int 1552 mac_pdata_update(mac_handle_t mh, void *mac_pdata, size_t dsize) 1553 { 1554 mac_impl_t *mip = (mac_impl_t *)mh; 1555 1556 /* 1557 * Verify that the plugin supports MAC plugin data and that the 1558 * supplied data is valid. 1559 */ 1560 if (!(mip->mi_type->mt_ops.mtops_ops & MTOPS_PDATA_VERIFY)) 1561 return (EINVAL); 1562 if (!mip->mi_type->mt_ops.mtops_pdata_verify(mac_pdata, dsize)) 1563 return (EINVAL); 1564 1565 if (mip->mi_pdata != NULL) 1566 kmem_free(mip->mi_pdata, mip->mi_pdata_size); 1567 1568 mip->mi_pdata = kmem_alloc(dsize, KM_SLEEP); 1569 bcopy(mac_pdata, mip->mi_pdata, dsize); 1570 mip->mi_pdata_size = dsize; 1571 1572 /* 1573 * Since the MAC plugin data is used to construct MAC headers that 1574 * were cached in fast-path headers, we need to flush fast-path 1575 * information for links associated with this mac. 1576 */ 1577 i_mac_notify(mip, MAC_NOTE_FASTPATH_FLUSH); 1578 return (0); 1579 } 1580 1581 void 1582 mac_multicst_refresh(mac_handle_t mh, mac_multicst_t refresh, void *arg, 1583 boolean_t add) 1584 { 1585 mac_impl_t *mip = (mac_impl_t *)mh; 1586 mac_multicst_addr_t *p; 1587 1588 /* 1589 * If no specific refresh function was given then default to the 1590 * driver's m_multicst entry point. 1591 */ 1592 if (refresh == NULL) { 1593 refresh = mip->mi_multicst; 1594 arg = mip->mi_driver; 1595 } 1596 ASSERT(refresh != NULL); 1597 1598 /* 1599 * Walk the multicast address list and call the refresh function for 1600 * each address. 1601 */ 1602 rw_enter(&(mip->mi_data_lock), RW_READER); 1603 for (p = mip->mi_mmap; p != NULL; p = p->mma_nextp) 1604 refresh(arg, add, p->mma_addr); 1605 rw_exit(&(mip->mi_data_lock)); 1606 } 1607 1608 void 1609 mac_unicst_refresh(mac_handle_t mh, mac_unicst_t refresh, void *arg) 1610 { 1611 mac_impl_t *mip = (mac_impl_t *)mh; 1612 /* 1613 * If no specific refresh function was given then default to the 1614 * driver's mi_unicst entry point. 1615 */ 1616 if (refresh == NULL) { 1617 refresh = mip->mi_unicst; 1618 arg = mip->mi_driver; 1619 } 1620 ASSERT(refresh != NULL); 1621 1622 /* 1623 * Call the refresh function with the current unicast address. 1624 */ 1625 refresh(arg, mip->mi_addr); 1626 } 1627 1628 void 1629 mac_promisc_refresh(mac_handle_t mh, mac_setpromisc_t refresh, void *arg) 1630 { 1631 mac_impl_t *mip = (mac_impl_t *)mh; 1632 1633 /* 1634 * If no specific refresh function was given then default to the 1635 * driver's m_promisc entry point. 1636 */ 1637 if (refresh == NULL) { 1638 refresh = mip->mi_setpromisc; 1639 arg = mip->mi_driver; 1640 } 1641 ASSERT(refresh != NULL); 1642 1643 /* 1644 * Call the refresh function with the current promiscuity. 1645 */ 1646 refresh(arg, (mip->mi_devpromisc != 0)); 1647 } 1648 1649 boolean_t 1650 mac_active_set(mac_handle_t mh) 1651 { 1652 mac_impl_t *mip = (mac_impl_t *)mh; 1653 1654 mutex_enter(&mip->mi_activelink_lock); 1655 if (mip->mi_activelink) { 1656 mutex_exit(&mip->mi_activelink_lock); 1657 return (B_FALSE); 1658 } 1659 mip->mi_activelink = B_TRUE; 1660 mutex_exit(&mip->mi_activelink_lock); 1661 return (B_TRUE); 1662 } 1663 1664 void 1665 mac_active_clear(mac_handle_t mh) 1666 { 1667 mac_impl_t *mip = (mac_impl_t *)mh; 1668 1669 mutex_enter(&mip->mi_activelink_lock); 1670 ASSERT(mip->mi_activelink); 1671 mip->mi_activelink = B_FALSE; 1672 mutex_exit(&mip->mi_activelink_lock); 1673 } 1674 1675 /* 1676 * mac_info_get() is used for retrieving the mac_info when a DL_INFO_REQ is 1677 * issued before a DL_ATTACH_REQ. we walk the i_mac_impl_hash table and find 1678 * the first mac_impl_t with a matching driver name; then we copy its mac_info_t 1679 * to the caller. we do all this with i_mac_impl_lock held so the mac_impl_t 1680 * cannot disappear while we are accessing it. 1681 */ 1682 typedef struct i_mac_info_state_s { 1683 const char *mi_name; 1684 mac_info_t *mi_infop; 1685 } i_mac_info_state_t; 1686 1687 /*ARGSUSED*/ 1688 static uint_t 1689 i_mac_info_walker(mod_hash_key_t key, mod_hash_val_t *val, void *arg) 1690 { 1691 i_mac_info_state_t *statep = arg; 1692 mac_impl_t *mip = (mac_impl_t *)val; 1693 1694 if (mip->mi_disabled) 1695 return (MH_WALK_CONTINUE); 1696 1697 if (strcmp(statep->mi_name, 1698 ddi_driver_name(mip->mi_dip)) != 0) 1699 return (MH_WALK_CONTINUE); 1700 1701 statep->mi_infop = &mip->mi_info; 1702 return (MH_WALK_TERMINATE); 1703 } 1704 1705 boolean_t 1706 mac_info_get(const char *name, mac_info_t *minfop) 1707 { 1708 i_mac_info_state_t state; 1709 1710 rw_enter(&i_mac_impl_lock, RW_READER); 1711 state.mi_name = name; 1712 state.mi_infop = NULL; 1713 mod_hash_walk(i_mac_impl_hash, i_mac_info_walker, &state); 1714 if (state.mi_infop == NULL) { 1715 rw_exit(&i_mac_impl_lock); 1716 return (B_FALSE); 1717 } 1718 *minfop = *state.mi_infop; 1719 rw_exit(&i_mac_impl_lock); 1720 return (B_TRUE); 1721 } 1722 1723 boolean_t 1724 mac_capab_get(mac_handle_t mh, mac_capab_t cap, void *cap_data) 1725 { 1726 mac_impl_t *mip = (mac_impl_t *)mh; 1727 1728 if (mip->mi_callbacks->mc_callbacks & MC_GETCAPAB) 1729 return (mip->mi_getcapab(mip->mi_driver, cap, cap_data)); 1730 else 1731 return (B_FALSE); 1732 } 1733 1734 boolean_t 1735 mac_sap_verify(mac_handle_t mh, uint32_t sap, uint32_t *bind_sap) 1736 { 1737 mac_impl_t *mip = (mac_impl_t *)mh; 1738 return (mip->mi_type->mt_ops.mtops_sap_verify(sap, bind_sap, 1739 mip->mi_pdata)); 1740 } 1741 1742 mblk_t * 1743 mac_header(mac_handle_t mh, const uint8_t *daddr, uint32_t sap, mblk_t *payload, 1744 size_t extra_len) 1745 { 1746 mac_impl_t *mip = (mac_impl_t *)mh; 1747 return (mip->mi_type->mt_ops.mtops_header(mip->mi_addr, daddr, sap, 1748 mip->mi_pdata, payload, extra_len)); 1749 } 1750 1751 int 1752 mac_header_info(mac_handle_t mh, mblk_t *mp, mac_header_info_t *mhip) 1753 { 1754 mac_impl_t *mip = (mac_impl_t *)mh; 1755 return (mip->mi_type->mt_ops.mtops_header_info(mp, mip->mi_pdata, 1756 mhip)); 1757 } 1758 1759 mblk_t * 1760 mac_header_cook(mac_handle_t mh, mblk_t *mp) 1761 { 1762 mac_impl_t *mip = (mac_impl_t *)mh; 1763 if (mip->mi_type->mt_ops.mtops_ops & MTOPS_HEADER_COOK) { 1764 if (DB_REF(mp) > 1) { 1765 mblk_t *newmp = copymsg(mp); 1766 if (newmp == NULL) 1767 return (NULL); 1768 freemsg(mp); 1769 mp = newmp; 1770 } 1771 return (mip->mi_type->mt_ops.mtops_header_cook(mp, 1772 mip->mi_pdata)); 1773 } 1774 return (mp); 1775 } 1776 1777 mblk_t * 1778 mac_header_uncook(mac_handle_t mh, mblk_t *mp) 1779 { 1780 mac_impl_t *mip = (mac_impl_t *)mh; 1781 if (mip->mi_type->mt_ops.mtops_ops & MTOPS_HEADER_UNCOOK) { 1782 if (DB_REF(mp) > 1) { 1783 mblk_t *newmp = copymsg(mp); 1784 if (newmp == NULL) 1785 return (NULL); 1786 freemsg(mp); 1787 mp = newmp; 1788 } 1789 return (mip->mi_type->mt_ops.mtops_header_uncook(mp, 1790 mip->mi_pdata)); 1791 } 1792 return (mp); 1793 } 1794 1795 void 1796 mac_init_ops(struct dev_ops *ops, const char *name) 1797 { 1798 dld_init_ops(ops, name); 1799 } 1800 1801 void 1802 mac_fini_ops(struct dev_ops *ops) 1803 { 1804 dld_fini_ops(ops); 1805 } 1806 1807 /* 1808 * MAC Type Plugin functions. 1809 */ 1810 1811 mactype_register_t * 1812 mactype_alloc(uint_t mactype_version) 1813 { 1814 mactype_register_t *mtrp; 1815 1816 /* 1817 * Make sure there isn't a version mismatch between the plugin and 1818 * the framework. In the future, if multiple versions are 1819 * supported, this check could become more sophisticated. 1820 */ 1821 if (mactype_version != MACTYPE_VERSION) 1822 return (NULL); 1823 1824 mtrp = kmem_zalloc(sizeof (mactype_register_t), KM_SLEEP); 1825 mtrp->mtr_version = mactype_version; 1826 return (mtrp); 1827 } 1828 1829 void 1830 mactype_free(mactype_register_t *mtrp) 1831 { 1832 kmem_free(mtrp, sizeof (mactype_register_t)); 1833 } 1834 1835 int 1836 mactype_register(mactype_register_t *mtrp) 1837 { 1838 mactype_t *mtp; 1839 mactype_ops_t *ops = mtrp->mtr_ops; 1840 1841 /* Do some sanity checking before we register this MAC type. */ 1842 if (mtrp->mtr_ident == NULL || ops == NULL || mtrp->mtr_addrlen == 0) 1843 return (EINVAL); 1844 1845 /* 1846 * Verify that all mandatory callbacks are set in the ops 1847 * vector. 1848 */ 1849 if (ops->mtops_unicst_verify == NULL || 1850 ops->mtops_multicst_verify == NULL || 1851 ops->mtops_sap_verify == NULL || 1852 ops->mtops_header == NULL || 1853 ops->mtops_header_info == NULL) { 1854 return (EINVAL); 1855 } 1856 1857 mtp = kmem_zalloc(sizeof (*mtp), KM_SLEEP); 1858 mtp->mt_ident = mtrp->mtr_ident; 1859 mtp->mt_ops = *ops; 1860 mtp->mt_type = mtrp->mtr_mactype; 1861 mtp->mt_nativetype = mtrp->mtr_nativetype; 1862 mtp->mt_addr_length = mtrp->mtr_addrlen; 1863 if (mtrp->mtr_brdcst_addr != NULL) { 1864 mtp->mt_brdcst_addr = kmem_alloc(mtrp->mtr_addrlen, KM_SLEEP); 1865 bcopy(mtrp->mtr_brdcst_addr, mtp->mt_brdcst_addr, 1866 mtrp->mtr_addrlen); 1867 } 1868 1869 mtp->mt_stats = mtrp->mtr_stats; 1870 mtp->mt_statcount = mtrp->mtr_statcount; 1871 1872 if (mod_hash_insert(i_mactype_hash, 1873 (mod_hash_key_t)mtp->mt_ident, (mod_hash_val_t)mtp) != 0) { 1874 kmem_free(mtp->mt_brdcst_addr, mtp->mt_addr_length); 1875 kmem_free(mtp, sizeof (*mtp)); 1876 return (EEXIST); 1877 } 1878 return (0); 1879 } 1880 1881 int 1882 mactype_unregister(const char *ident) 1883 { 1884 mactype_t *mtp; 1885 mod_hash_val_t val; 1886 int err; 1887 1888 /* 1889 * Let's not allow MAC drivers to use this plugin while we're 1890 * trying to unregister it. Holding i_mactype_lock also prevents a 1891 * plugin from unregistering while a MAC driver is attempting to 1892 * hold a reference to it in i_mactype_getplugin(). 1893 */ 1894 mutex_enter(&i_mactype_lock); 1895 1896 if ((err = mod_hash_find(i_mactype_hash, (mod_hash_key_t)ident, 1897 (mod_hash_val_t *)&mtp)) != 0) { 1898 /* A plugin is trying to unregister, but it never registered. */ 1899 err = ENXIO; 1900 goto done; 1901 } 1902 1903 if (mtp->mt_ref != 0) { 1904 err = EBUSY; 1905 goto done; 1906 } 1907 1908 err = mod_hash_remove(i_mactype_hash, (mod_hash_key_t)ident, &val); 1909 ASSERT(err == 0); 1910 if (err != 0) { 1911 /* This should never happen, thus the ASSERT() above. */ 1912 err = EINVAL; 1913 goto done; 1914 } 1915 ASSERT(mtp == (mactype_t *)val); 1916 1917 kmem_free(mtp->mt_brdcst_addr, mtp->mt_addr_length); 1918 kmem_free(mtp, sizeof (mactype_t)); 1919 done: 1920 mutex_exit(&i_mactype_lock); 1921 return (err); 1922 } 1923 1924 int 1925 mac_vlan_create(mac_handle_t mh, const char *name, minor_t minor) 1926 { 1927 mac_impl_t *mip = (mac_impl_t *)mh; 1928 1929 /* Create a style-1 DLPI device */ 1930 if (ddi_create_minor_node(mip->mi_dip, (char *)name, S_IFCHR, minor, 1931 DDI_NT_NET, 0) != DDI_SUCCESS) { 1932 return (-1); 1933 } 1934 return (0); 1935 } 1936 1937 void 1938 mac_vlan_remove(mac_handle_t mh, const char *name) 1939 { 1940 mac_impl_t *mip = (mac_impl_t *)mh; 1941 dev_info_t *dipp; 1942 1943 ddi_remove_minor_node(mip->mi_dip, (char *)name); 1944 dipp = ddi_get_parent(mip->mi_dip); 1945 (void) devfs_clean(dipp, NULL, 0); 1946 } 1947