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 /* 23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* 28 * The ipnet device defined here provides access to packets at the IP layer. To 29 * provide access to packets at this layer it registers a callback function in 30 * the ip module and when there are open instances of the device ip will pass 31 * packets into the device. Packets from ip are passed on the input, output and 32 * loopback paths. Internally the module returns to ip as soon as possible by 33 * deferring processing using a taskq. 34 * 35 * Management of the devices in /dev/ipnet/ is handled by the devname 36 * filesystem and use of the neti interfaces. This module registers for NIC 37 * events using the neti framework so that when IP interfaces are bought up, 38 * taken down etc. the ipnet module is notified and its view of the interfaces 39 * configured on the system adjusted. On attach, the module gets an initial 40 * view of the system again using the neti framework but as it has already 41 * registered for IP interface events, it is still up-to-date with any changes. 42 */ 43 44 #include <sys/types.h> 45 #include <sys/conf.h> 46 #include <sys/cred.h> 47 #include <sys/stat.h> 48 #include <sys/ddi.h> 49 #include <sys/sunddi.h> 50 #include <sys/modctl.h> 51 #include <sys/dlpi.h> 52 #include <sys/strsun.h> 53 #include <sys/id_space.h> 54 #include <sys/kmem.h> 55 #include <sys/mkdev.h> 56 #include <sys/neti.h> 57 #include <net/if.h> 58 #include <sys/errno.h> 59 #include <sys/list.h> 60 #include <sys/ksynch.h> 61 #include <sys/hook_event.h> 62 #include <sys/sdt.h> 63 #include <sys/stropts.h> 64 #include <sys/sysmacros.h> 65 #include <inet/ip.h> 66 #include <inet/ip_if.h> 67 #include <inet/ip_multi.h> 68 #include <inet/ip6.h> 69 #include <inet/ipnet.h> 70 #include <net/bpf.h> 71 #include <net/bpfdesc.h> 72 #include <net/dlt.h> 73 74 static struct module_info ipnet_minfo = { 75 1, /* mi_idnum */ 76 "ipnet", /* mi_idname */ 77 0, /* mi_minpsz */ 78 INFPSZ, /* mi_maxpsz */ 79 2048, /* mi_hiwat */ 80 0 /* mi_lowat */ 81 }; 82 83 /* 84 * List to hold static view of ipnetif_t's on the system. This is needed to 85 * avoid holding the lock protecting the avl tree of ipnetif's over the 86 * callback into the dev filesystem. 87 */ 88 typedef struct ipnetif_cbdata { 89 char ic_ifname[LIFNAMSIZ]; 90 dev_t ic_dev; 91 list_node_t ic_next; 92 } ipnetif_cbdata_t; 93 94 /* 95 * Convenience enumerated type for ipnet_accept(). It describes the 96 * properties of a given ipnet_addrp_t relative to a single ipnet_t 97 * client stream. The values represent whether the address is ... 98 */ 99 typedef enum { 100 IPNETADDR_MYADDR, /* an address on my ipnetif_t. */ 101 IPNETADDR_MBCAST, /* a multicast or broadcast address. */ 102 IPNETADDR_UNKNOWN /* none of the above. */ 103 } ipnet_addrtype_t; 104 105 /* Argument used for the ipnet_nicevent_taskq callback. */ 106 typedef struct ipnet_nicevent_s { 107 nic_event_t ipne_event; 108 net_handle_t ipne_protocol; 109 netstackid_t ipne_stackid; 110 uint64_t ipne_ifindex; 111 uint64_t ipne_lifindex; 112 char ipne_ifname[LIFNAMSIZ]; 113 } ipnet_nicevent_t; 114 115 static dev_info_t *ipnet_dip; 116 static major_t ipnet_major; 117 static ddi_taskq_t *ipnet_taskq; /* taskq for packets */ 118 static ddi_taskq_t *ipnet_nicevent_taskq; /* taskq for NIC events */ 119 static id_space_t *ipnet_minor_space; 120 static const int IPNET_MINOR_LO = 1; /* minor number for /dev/lo0 */ 121 static const int IPNET_MINOR_MIN = 2; /* start of dynamic minors */ 122 static dl_info_ack_t ipnet_infoack = IPNET_INFO_ACK_INIT; 123 static ipnet_acceptfn_t ipnet_accept, ipnet_loaccept; 124 static bpf_itap_fn_t ipnet_itap; 125 126 static void ipnet_input(mblk_t *); 127 static int ipnet_wput(queue_t *, mblk_t *); 128 static int ipnet_rsrv(queue_t *); 129 static int ipnet_open(queue_t *, dev_t *, int, int, cred_t *); 130 static int ipnet_close(queue_t *); 131 static void ipnet_ioctl(queue_t *, mblk_t *); 132 static void ipnet_iocdata(queue_t *, mblk_t *); 133 static void ipnet_wputnondata(queue_t *, mblk_t *); 134 static int ipnet_attach(dev_info_t *, ddi_attach_cmd_t); 135 static int ipnet_detach(dev_info_t *, ddi_detach_cmd_t); 136 static int ipnet_devinfo(dev_info_t *, ddi_info_cmd_t, void *, void **); 137 static void ipnet_inforeq(queue_t *q, mblk_t *mp); 138 static void ipnet_bindreq(queue_t *q, mblk_t *mp); 139 static void ipnet_unbindreq(queue_t *q, mblk_t *mp); 140 static void ipnet_dlpromisconreq(queue_t *q, mblk_t *mp); 141 static void ipnet_dlpromiscoffreq(queue_t *q, mblk_t *mp); 142 static int ipnet_join_allmulti(ipnetif_t *, ipnet_stack_t *); 143 static void ipnet_leave_allmulti(ipnetif_t *, ipnet_stack_t *); 144 static int ipnet_nicevent_cb(hook_event_token_t, hook_data_t, void *); 145 static void ipnet_nicevent_task(void *); 146 static ipnetif_t *ipnetif_create(const char *, uint64_t, ipnet_stack_t *, 147 uint64_t); 148 static void ipnetif_remove(ipnetif_t *, ipnet_stack_t *); 149 static ipnetif_addr_t *ipnet_match_lif(ipnetif_t *, lif_if_t, boolean_t); 150 static ipnetif_t *ipnetif_getby_index(uint64_t, ipnet_stack_t *); 151 static ipnetif_t *ipnetif_getby_dev(dev_t, ipnet_stack_t *); 152 static boolean_t ipnetif_in_zone(ipnetif_t *, zoneid_t, ipnet_stack_t *); 153 static void ipnetif_zonecheck(ipnetif_t *, ipnet_stack_t *); 154 static int ipnet_populate_if(net_handle_t, ipnet_stack_t *, boolean_t); 155 static int ipnetif_compare_name(const void *, const void *); 156 static int ipnetif_compare_name_zone(const void *, const void *); 157 static int ipnetif_compare_index(const void *, const void *); 158 static void ipnet_add_ifaddr(uint64_t, ipnetif_t *, net_handle_t); 159 static void ipnet_delete_ifaddr(ipnetif_addr_t *, ipnetif_t *, boolean_t); 160 static void ipnetif_refhold(ipnetif_t *); 161 static void ipnetif_refrele(ipnetif_t *); 162 static void ipnet_walkers_inc(ipnet_stack_t *); 163 static void ipnet_walkers_dec(ipnet_stack_t *); 164 static void ipnet_register_netihook(ipnet_stack_t *); 165 static void *ipnet_stack_init(netstackid_t, netstack_t *); 166 static void ipnet_stack_fini(netstackid_t, void *); 167 static void ipnet_dispatch(void *); 168 static int ipobs_bounce_func(hook_event_token_t, hook_data_t, void *); 169 static int ipnet_bpf_bounce(hook_event_token_t, hook_data_t, void *); 170 static ipnetif_t *ipnetif_clone_create(ipnetif_t *, zoneid_t); 171 static void ipnetif_clone_release(ipnetif_t *); 172 173 static struct qinit ipnet_rinit = { 174 NULL, /* qi_putp */ 175 ipnet_rsrv, /* qi_srvp */ 176 ipnet_open, /* qi_qopen */ 177 ipnet_close, /* qi_qclose */ 178 NULL, /* qi_qadmin */ 179 &ipnet_minfo, /* qi_minfo */ 180 }; 181 182 static struct qinit ipnet_winit = { 183 ipnet_wput, /* qi_putp */ 184 NULL, /* qi_srvp */ 185 NULL, /* qi_qopen */ 186 NULL, /* qi_qclose */ 187 NULL, /* qi_qadmin */ 188 &ipnet_minfo, /* qi_minfo */ 189 }; 190 191 static struct streamtab ipnet_info = { 192 &ipnet_rinit, &ipnet_winit 193 }; 194 195 DDI_DEFINE_STREAM_OPS(ipnet_ops, nulldev, nulldev, ipnet_attach, 196 ipnet_detach, nodev, ipnet_devinfo, D_MP | D_MTPERMOD, &ipnet_info, 197 ddi_quiesce_not_supported); 198 199 static struct modldrv modldrv = { 200 &mod_driverops, 201 "STREAMS ipnet driver", 202 &ipnet_ops 203 }; 204 205 static struct modlinkage modlinkage = { 206 MODREV_1, &modldrv, NULL 207 }; 208 209 /* 210 * This structure contains the template data (names and type) that is 211 * copied, in bulk, into the new kstats structure created by net_kstat_create. 212 * No actual statistical information is stored in this instance of the 213 * ipnet_kstats_t structure. 214 */ 215 static ipnet_kstats_t stats_template = { 216 { "duplicationFail", KSTAT_DATA_UINT64 }, 217 { "dispatchOk", KSTAT_DATA_UINT64 }, 218 { "dispatchFail", KSTAT_DATA_UINT64 }, 219 { "dispatchHeaderDrop", KSTAT_DATA_UINT64 }, 220 { "dispatchDupDrop", KSTAT_DATA_UINT64 }, 221 { "dispatchDeliver", KSTAT_DATA_UINT64 }, 222 { "acceptOk", KSTAT_DATA_UINT64 }, 223 { "acceptFail", KSTAT_DATA_UINT64 } 224 }; 225 226 /* 227 * Walk the list of physical interfaces on the machine, for each 228 * interface create a new ipnetif_t and add any addresses to it. We 229 * need to do the walk twice, once for IPv4 and once for IPv6. 230 * 231 * The interfaces are destroyed as part of ipnet_stack_fini() for each 232 * stack. Note that we cannot do this initialization in 233 * ipnet_stack_init(), since ipnet_stack_init() cannot fail. 234 */ 235 static int 236 ipnetif_init(void) 237 { 238 netstack_handle_t nh; 239 netstack_t *ns; 240 ipnet_stack_t *ips; 241 int ret = 0; 242 243 netstack_next_init(&nh); 244 while ((ns = netstack_next(&nh)) != NULL) { 245 ips = ns->netstack_ipnet; 246 if ((ret = ipnet_populate_if(ips->ips_ndv4, ips, B_FALSE)) == 0) 247 ret = ipnet_populate_if(ips->ips_ndv6, ips, B_TRUE); 248 netstack_rele(ns); 249 if (ret != 0) 250 break; 251 } 252 netstack_next_fini(&nh); 253 return (ret); 254 } 255 256 /* 257 * Standard module entry points. 258 */ 259 int 260 _init(void) 261 { 262 int ret; 263 boolean_t netstack_registered = B_FALSE; 264 265 if ((ipnet_major = ddi_name_to_major("ipnet")) == (major_t)-1) 266 return (ENODEV); 267 ipnet_minor_space = id_space_create("ipnet_minor_space", 268 IPNET_MINOR_MIN, MAXMIN32); 269 270 /* 271 * We call ddi_taskq_create() with nthread == 1 to ensure in-order 272 * delivery of packets to clients. Note that we need to create the 273 * taskqs before calling netstack_register() since ipnet_stack_init() 274 * registers callbacks that use 'em. 275 */ 276 ipnet_taskq = ddi_taskq_create(NULL, "ipnet", 1, TASKQ_DEFAULTPRI, 0); 277 ipnet_nicevent_taskq = ddi_taskq_create(NULL, "ipnet_nic_event_queue", 278 1, TASKQ_DEFAULTPRI, 0); 279 if (ipnet_taskq == NULL || ipnet_nicevent_taskq == NULL) { 280 ret = ENOMEM; 281 goto done; 282 } 283 284 netstack_register(NS_IPNET, ipnet_stack_init, NULL, ipnet_stack_fini); 285 netstack_registered = B_TRUE; 286 287 if ((ret = ipnetif_init()) == 0) 288 ret = mod_install(&modlinkage); 289 done: 290 if (ret != 0) { 291 if (ipnet_taskq != NULL) 292 ddi_taskq_destroy(ipnet_taskq); 293 if (ipnet_nicevent_taskq != NULL) 294 ddi_taskq_destroy(ipnet_nicevent_taskq); 295 if (netstack_registered) 296 netstack_unregister(NS_IPNET); 297 id_space_destroy(ipnet_minor_space); 298 } 299 return (ret); 300 } 301 302 int 303 _fini(void) 304 { 305 int err; 306 307 if ((err = mod_remove(&modlinkage)) != 0) 308 return (err); 309 310 netstack_unregister(NS_IPNET); 311 ddi_taskq_destroy(ipnet_nicevent_taskq); 312 ddi_taskq_destroy(ipnet_taskq); 313 id_space_destroy(ipnet_minor_space); 314 return (0); 315 } 316 317 int 318 _info(struct modinfo *modinfop) 319 { 320 return (mod_info(&modlinkage, modinfop)); 321 } 322 323 static void 324 ipnet_register_netihook(ipnet_stack_t *ips) 325 { 326 int ret; 327 zoneid_t zoneid; 328 netid_t netid; 329 330 HOOK_INIT(ips->ips_nicevents, ipnet_nicevent_cb, "ipnet_nicevents", 331 ips); 332 333 /* 334 * It is possible for an exclusive stack to be in the process of 335 * shutting down here, and the netid and protocol lookups could fail 336 * in that case. 337 */ 338 zoneid = netstackid_to_zoneid(ips->ips_netstack->netstack_stackid); 339 if ((netid = net_zoneidtonetid(zoneid)) == -1) 340 return; 341 342 if ((ips->ips_ndv4 = net_protocol_lookup(netid, NHF_INET)) != NULL) { 343 if ((ret = net_hook_register(ips->ips_ndv4, NH_NIC_EVENTS, 344 ips->ips_nicevents)) != 0) { 345 VERIFY(net_protocol_release(ips->ips_ndv4) == 0); 346 ips->ips_ndv4 = NULL; 347 cmn_err(CE_WARN, "unable to register IPv4 netinfo hooks" 348 " in zone %d: %d", zoneid, ret); 349 } 350 } 351 if ((ips->ips_ndv6 = net_protocol_lookup(netid, NHF_INET6)) != NULL) { 352 if ((ret = net_hook_register(ips->ips_ndv6, NH_NIC_EVENTS, 353 ips->ips_nicevents)) != 0) { 354 VERIFY(net_protocol_release(ips->ips_ndv6) == 0); 355 ips->ips_ndv6 = NULL; 356 cmn_err(CE_WARN, "unable to register IPv6 netinfo hooks" 357 " in zone %d: %d", zoneid, ret); 358 } 359 } 360 361 /* 362 * Create a local set of kstats for each zone. 363 */ 364 ips->ips_kstatp = net_kstat_create(netid, "ipnet", 0, "ipnet_stats", 365 "misc", KSTAT_TYPE_NAMED, 366 sizeof (ipnet_kstats_t) / sizeof (kstat_named_t), 0); 367 if (ips->ips_kstatp != NULL) { 368 bcopy(&stats_template, &ips->ips_stats, 369 sizeof (ips->ips_stats)); 370 ips->ips_kstatp->ks_data = &ips->ips_stats; 371 ips->ips_kstatp->ks_private = 372 (void *)(uintptr_t)ips->ips_netstack->netstack_stackid; 373 kstat_install(ips->ips_kstatp); 374 } else { 375 cmn_err(CE_WARN, "net_kstat_create(%s,%s,%s) failed", 376 "ipnet", "ipnet_stats", "misc"); 377 } 378 } 379 380 /* 381 * This function is called on attach to build an initial view of the 382 * interfaces on the system. It will be called once for IPv4 and once 383 * for IPv6, although there is only one ipnet interface for both IPv4 384 * and IPv6 there are separate address lists. 385 */ 386 static int 387 ipnet_populate_if(net_handle_t nd, ipnet_stack_t *ips, boolean_t isv6) 388 { 389 phy_if_t phyif; 390 lif_if_t lif; 391 ipnetif_t *ipnetif; 392 char name[LIFNAMSIZ]; 393 boolean_t new_if = B_FALSE; 394 uint64_t ifflags; 395 int ret = 0; 396 397 /* 398 * If ipnet_register_netihook() was unable to initialize this 399 * stack's net_handle_t, then we cannot populate any interface 400 * information. This usually happens when we attempted to 401 * grab a net_handle_t as a stack was shutting down. We don't 402 * want to fail the entire _init() operation because of a 403 * stack shutdown (other stacks will continue to work just 404 * fine), so we silently return success here. 405 */ 406 if (nd == NULL) 407 return (0); 408 409 /* 410 * Make sure we're not processing NIC events during the 411 * population of our interfaces and address lists. 412 */ 413 mutex_enter(&ips->ips_event_lock); 414 415 for (phyif = net_phygetnext(nd, 0); phyif != 0; 416 phyif = net_phygetnext(nd, phyif)) { 417 if (net_getifname(nd, phyif, name, LIFNAMSIZ) != 0) 418 continue; 419 ifflags = 0; 420 (void) net_getlifflags(nd, phyif, 0, &ifflags); 421 if ((ipnetif = ipnetif_getby_index(phyif, ips)) == NULL) { 422 ipnetif = ipnetif_create(name, phyif, ips, ifflags); 423 if (ipnetif == NULL) { 424 ret = ENOMEM; 425 goto done; 426 } 427 new_if = B_TRUE; 428 } 429 ipnetif->if_flags |= 430 isv6 ? IPNETIF_IPV6PLUMBED : IPNETIF_IPV4PLUMBED; 431 432 for (lif = net_lifgetnext(nd, phyif, 0); lif != 0; 433 lif = net_lifgetnext(nd, phyif, lif)) { 434 /* 435 * Skip addresses that aren't up. We'll add 436 * them when we receive an NE_LIF_UP event. 437 */ 438 if (net_getlifflags(nd, phyif, lif, &ifflags) != 0 || 439 !(ifflags & IFF_UP)) 440 continue; 441 /* Don't add it if we already have it. */ 442 if (ipnet_match_lif(ipnetif, lif, isv6) != NULL) 443 continue; 444 ipnet_add_ifaddr(lif, ipnetif, nd); 445 } 446 if (!new_if) 447 ipnetif_refrele(ipnetif); 448 } 449 450 done: 451 mutex_exit(&ips->ips_event_lock); 452 return (ret); 453 } 454 455 static int 456 ipnet_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 457 { 458 if (cmd != DDI_ATTACH) 459 return (DDI_FAILURE); 460 461 if (ddi_create_minor_node(dip, "lo0", S_IFCHR, IPNET_MINOR_LO, 462 DDI_PSEUDO, 0) == DDI_FAILURE) 463 return (DDI_FAILURE); 464 465 ipnet_dip = dip; 466 return (DDI_SUCCESS); 467 } 468 469 static int 470 ipnet_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 471 { 472 if (cmd != DDI_DETACH) 473 return (DDI_FAILURE); 474 475 ASSERT(dip == ipnet_dip); 476 ddi_remove_minor_node(ipnet_dip, NULL); 477 ipnet_dip = NULL; 478 return (DDI_SUCCESS); 479 } 480 481 /* ARGSUSED */ 482 static int 483 ipnet_devinfo(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result) 484 { 485 int error = DDI_FAILURE; 486 487 switch (infocmd) { 488 case DDI_INFO_DEVT2INSTANCE: 489 *result = (void *)0; 490 error = DDI_SUCCESS; 491 break; 492 case DDI_INFO_DEVT2DEVINFO: 493 if (ipnet_dip != NULL) { 494 *result = ipnet_dip; 495 error = DDI_SUCCESS; 496 } 497 break; 498 } 499 return (error); 500 } 501 502 /* ARGSUSED */ 503 static int 504 ipnet_open(queue_t *rq, dev_t *dev, int oflag, int sflag, cred_t *crp) 505 { 506 ipnet_t *ipnet; 507 netstack_t *ns = NULL; 508 ipnet_stack_t *ips; 509 int err = 0; 510 zoneid_t zoneid = crgetzoneid(crp); 511 512 /* 513 * If the system is labeled, only the global zone is allowed to open 514 * IP observability nodes. 515 */ 516 if (is_system_labeled() && zoneid != GLOBAL_ZONEID) 517 return (EACCES); 518 519 /* We don't support open as a module */ 520 if (sflag & MODOPEN) 521 return (ENOTSUP); 522 523 /* This driver is self-cloning, we don't support re-open. */ 524 if (rq->q_ptr != NULL) 525 return (EBUSY); 526 527 if ((ipnet = kmem_zalloc(sizeof (*ipnet), KM_NOSLEEP)) == NULL) 528 return (ENOMEM); 529 530 VERIFY((ns = netstack_find_by_cred(crp)) != NULL); 531 ips = ns->netstack_ipnet; 532 533 rq->q_ptr = WR(rq)->q_ptr = ipnet; 534 ipnet->ipnet_rq = rq; 535 ipnet->ipnet_minor = (minor_t)id_alloc(ipnet_minor_space); 536 ipnet->ipnet_zoneid = zoneid; 537 ipnet->ipnet_dlstate = DL_UNBOUND; 538 ipnet->ipnet_ns = ns; 539 540 /* 541 * We need to hold ips_event_lock here as any NE_LIF_DOWN events need 542 * to be processed after ipnet_if is set and the ipnet_t has been 543 * inserted in the ips_str_list. 544 */ 545 mutex_enter(&ips->ips_event_lock); 546 if (getminor(*dev) == IPNET_MINOR_LO) { 547 ipnet->ipnet_flags |= IPNET_LOMODE; 548 ipnet->ipnet_acceptfn = ipnet_loaccept; 549 } else { 550 ipnet->ipnet_acceptfn = ipnet_accept; 551 ipnet->ipnet_if = ipnetif_getby_dev(*dev, ips); 552 if (ipnet->ipnet_if == NULL || 553 !ipnetif_in_zone(ipnet->ipnet_if, zoneid, ips)) { 554 err = ENODEV; 555 goto done; 556 } 557 } 558 559 mutex_enter(&ips->ips_walkers_lock); 560 while (ips->ips_walkers_cnt != 0) 561 cv_wait(&ips->ips_walkers_cv, &ips->ips_walkers_lock); 562 list_insert_head(&ips->ips_str_list, ipnet); 563 *dev = makedevice(getmajor(*dev), ipnet->ipnet_minor); 564 qprocson(rq); 565 566 /* 567 * Only register our callback if we're the first open client; we call 568 * unregister in close() for the last open client. 569 */ 570 if (list_head(&ips->ips_str_list) == list_tail(&ips->ips_str_list)) 571 ips->ips_hook = ipobs_register_hook(ns, ipnet_input); 572 mutex_exit(&ips->ips_walkers_lock); 573 574 done: 575 mutex_exit(&ips->ips_event_lock); 576 if (err != 0) { 577 netstack_rele(ns); 578 id_free(ipnet_minor_space, ipnet->ipnet_minor); 579 if (ipnet->ipnet_if != NULL) 580 ipnetif_refrele(ipnet->ipnet_if); 581 kmem_free(ipnet, sizeof (*ipnet)); 582 } 583 return (err); 584 } 585 586 static int 587 ipnet_close(queue_t *rq) 588 { 589 ipnet_t *ipnet = rq->q_ptr; 590 ipnet_stack_t *ips = ipnet->ipnet_ns->netstack_ipnet; 591 592 if (ipnet->ipnet_flags & IPNET_PROMISC_PHYS) 593 ipnet_leave_allmulti(ipnet->ipnet_if, ips); 594 if (ipnet->ipnet_flags & IPNET_PROMISC_MULTI) 595 ipnet_leave_allmulti(ipnet->ipnet_if, ips); 596 597 mutex_enter(&ips->ips_walkers_lock); 598 while (ips->ips_walkers_cnt != 0) 599 cv_wait(&ips->ips_walkers_cv, &ips->ips_walkers_lock); 600 601 qprocsoff(rq); 602 603 list_remove(&ips->ips_str_list, ipnet); 604 if (ipnet->ipnet_if != NULL) 605 ipnetif_refrele(ipnet->ipnet_if); 606 id_free(ipnet_minor_space, ipnet->ipnet_minor); 607 608 if (list_is_empty(&ips->ips_str_list)) { 609 ipobs_unregister_hook(ips->ips_netstack, ips->ips_hook); 610 ips->ips_hook = NULL; 611 } 612 613 kmem_free(ipnet, sizeof (*ipnet)); 614 615 mutex_exit(&ips->ips_walkers_lock); 616 netstack_rele(ips->ips_netstack); 617 return (0); 618 } 619 620 static int 621 ipnet_wput(queue_t *q, mblk_t *mp) 622 { 623 switch (mp->b_datap->db_type) { 624 case M_FLUSH: 625 if (*mp->b_rptr & FLUSHW) { 626 flushq(q, FLUSHDATA); 627 *mp->b_rptr &= ~FLUSHW; 628 } 629 if (*mp->b_rptr & FLUSHR) 630 qreply(q, mp); 631 else 632 freemsg(mp); 633 break; 634 case M_PROTO: 635 case M_PCPROTO: 636 ipnet_wputnondata(q, mp); 637 break; 638 case M_IOCTL: 639 ipnet_ioctl(q, mp); 640 break; 641 case M_IOCDATA: 642 ipnet_iocdata(q, mp); 643 break; 644 default: 645 freemsg(mp); 646 break; 647 } 648 return (0); 649 } 650 651 static int 652 ipnet_rsrv(queue_t *q) 653 { 654 mblk_t *mp; 655 656 while ((mp = getq(q)) != NULL) { 657 ASSERT(DB_TYPE(mp) == M_DATA); 658 if (canputnext(q)) { 659 putnext(q, mp); 660 } else { 661 (void) putbq(q, mp); 662 break; 663 } 664 } 665 return (0); 666 } 667 668 static void 669 ipnet_ioctl(queue_t *q, mblk_t *mp) 670 { 671 struct iocblk *iocp = (struct iocblk *)mp->b_rptr; 672 673 switch (iocp->ioc_cmd) { 674 case DLIOCRAW: 675 miocack(q, mp, 0, 0); 676 break; 677 case DLIOCIPNETINFO: 678 if (iocp->ioc_count == TRANSPARENT) { 679 mcopyin(mp, NULL, sizeof (uint_t), NULL); 680 qreply(q, mp); 681 break; 682 } 683 /* Fallthrough, we don't support I_STR with DLIOCIPNETINFO. */ 684 default: 685 miocnak(q, mp, 0, EINVAL); 686 break; 687 } 688 } 689 690 static void 691 ipnet_iocdata(queue_t *q, mblk_t *mp) 692 { 693 struct iocblk *iocp = (struct iocblk *)mp->b_rptr; 694 ipnet_t *ipnet = q->q_ptr; 695 696 switch (iocp->ioc_cmd) { 697 case DLIOCIPNETINFO: 698 if (*(int *)mp->b_cont->b_rptr == 1) 699 ipnet->ipnet_flags |= IPNET_INFO; 700 else if (*(int *)mp->b_cont->b_rptr == 0) 701 ipnet->ipnet_flags &= ~IPNET_INFO; 702 else 703 goto iocnak; 704 miocack(q, mp, 0, DL_IPNETINFO_VERSION); 705 break; 706 default: 707 iocnak: 708 miocnak(q, mp, 0, EINVAL); 709 break; 710 } 711 } 712 713 static void 714 ipnet_wputnondata(queue_t *q, mblk_t *mp) 715 { 716 union DL_primitives *dlp = (union DL_primitives *)mp->b_rptr; 717 t_uscalar_t prim = dlp->dl_primitive; 718 719 switch (prim) { 720 case DL_INFO_REQ: 721 ipnet_inforeq(q, mp); 722 break; 723 case DL_UNBIND_REQ: 724 ipnet_unbindreq(q, mp); 725 break; 726 case DL_BIND_REQ: 727 ipnet_bindreq(q, mp); 728 break; 729 case DL_PROMISCON_REQ: 730 ipnet_dlpromisconreq(q, mp); 731 break; 732 case DL_PROMISCOFF_REQ: 733 ipnet_dlpromiscoffreq(q, mp); 734 break; 735 case DL_UNITDATA_REQ: 736 case DL_DETACH_REQ: 737 case DL_PHYS_ADDR_REQ: 738 case DL_SET_PHYS_ADDR_REQ: 739 case DL_ENABMULTI_REQ: 740 case DL_DISABMULTI_REQ: 741 case DL_ATTACH_REQ: 742 dlerrorack(q, mp, prim, DL_UNSUPPORTED, 0); 743 break; 744 default: 745 dlerrorack(q, mp, prim, DL_BADPRIM, 0); 746 break; 747 } 748 } 749 750 static void 751 ipnet_inforeq(queue_t *q, mblk_t *mp) 752 { 753 dl_info_ack_t *dlip; 754 size_t size = sizeof (dl_info_ack_t) + sizeof (ushort_t); 755 756 if (MBLKL(mp) < DL_INFO_REQ_SIZE) { 757 dlerrorack(q, mp, DL_INFO_REQ, DL_BADPRIM, 0); 758 return; 759 } 760 761 if ((mp = mexchange(q, mp, size, M_PCPROTO, DL_INFO_ACK)) == NULL) 762 return; 763 764 dlip = (dl_info_ack_t *)mp->b_rptr; 765 *dlip = ipnet_infoack; 766 qreply(q, mp); 767 } 768 769 static void 770 ipnet_bindreq(queue_t *q, mblk_t *mp) 771 { 772 union DL_primitives *dlp = (union DL_primitives *)mp->b_rptr; 773 ipnet_t *ipnet = q->q_ptr; 774 775 if (MBLKL(mp) < DL_BIND_REQ_SIZE) { 776 dlerrorack(q, mp, DL_BIND_REQ, DL_BADPRIM, 0); 777 return; 778 } 779 780 switch (dlp->bind_req.dl_sap) { 781 case 0 : 782 ipnet->ipnet_family = AF_UNSPEC; 783 break; 784 case IPV4_VERSION : 785 ipnet->ipnet_family = AF_INET; 786 break; 787 case IPV6_VERSION : 788 ipnet->ipnet_family = AF_INET6; 789 break; 790 default : 791 dlerrorack(q, mp, DL_BIND_REQ, DL_BADSAP, 0); 792 return; 793 /*NOTREACHED*/ 794 } 795 796 ipnet->ipnet_dlstate = DL_IDLE; 797 dlbindack(q, mp, dlp->bind_req.dl_sap, 0, 0, 0, 0); 798 } 799 800 static void 801 ipnet_unbindreq(queue_t *q, mblk_t *mp) 802 { 803 ipnet_t *ipnet = q->q_ptr; 804 805 if (MBLKL(mp) < DL_UNBIND_REQ_SIZE) { 806 dlerrorack(q, mp, DL_UNBIND_REQ, DL_BADPRIM, 0); 807 return; 808 } 809 810 if (ipnet->ipnet_dlstate != DL_IDLE) { 811 dlerrorack(q, mp, DL_UNBIND_REQ, DL_OUTSTATE, 0); 812 } else { 813 ipnet->ipnet_dlstate = DL_UNBOUND; 814 ipnet->ipnet_family = AF_UNSPEC; 815 dlokack(q, mp, DL_UNBIND_REQ); 816 } 817 } 818 819 static void 820 ipnet_dlpromisconreq(queue_t *q, mblk_t *mp) 821 { 822 ipnet_t *ipnet = q->q_ptr; 823 t_uscalar_t level; 824 int err; 825 826 if (MBLKL(mp) < DL_PROMISCON_REQ_SIZE) { 827 dlerrorack(q, mp, DL_PROMISCON_REQ, DL_BADPRIM, 0); 828 return; 829 } 830 831 if (ipnet->ipnet_flags & IPNET_LOMODE) { 832 dlokack(q, mp, DL_PROMISCON_REQ); 833 return; 834 } 835 836 level = ((dl_promiscon_req_t *)mp->b_rptr)->dl_level; 837 if (level == DL_PROMISC_PHYS || level == DL_PROMISC_MULTI) { 838 if ((err = ipnet_join_allmulti(ipnet->ipnet_if, 839 ipnet->ipnet_ns->netstack_ipnet)) != 0) { 840 dlerrorack(q, mp, DL_PROMISCON_REQ, DL_SYSERR, err); 841 return; 842 } 843 } 844 845 switch (level) { 846 case DL_PROMISC_PHYS: 847 ipnet->ipnet_flags |= IPNET_PROMISC_PHYS; 848 break; 849 case DL_PROMISC_SAP: 850 ipnet->ipnet_flags |= IPNET_PROMISC_SAP; 851 break; 852 case DL_PROMISC_MULTI: 853 ipnet->ipnet_flags |= IPNET_PROMISC_MULTI; 854 break; 855 default: 856 dlerrorack(q, mp, DL_PROMISCON_REQ, DL_BADPRIM, 0); 857 return; 858 } 859 860 dlokack(q, mp, DL_PROMISCON_REQ); 861 } 862 863 static void 864 ipnet_dlpromiscoffreq(queue_t *q, mblk_t *mp) 865 { 866 ipnet_t *ipnet = q->q_ptr; 867 t_uscalar_t level; 868 uint16_t orig_ipnet_flags = ipnet->ipnet_flags; 869 870 if (MBLKL(mp) < DL_PROMISCOFF_REQ_SIZE) { 871 dlerrorack(q, mp, DL_PROMISCOFF_REQ, DL_BADPRIM, 0); 872 return; 873 } 874 875 if (ipnet->ipnet_flags & IPNET_LOMODE) { 876 dlokack(q, mp, DL_PROMISCOFF_REQ); 877 return; 878 } 879 880 level = ((dl_promiscon_req_t *)mp->b_rptr)->dl_level; 881 switch (level) { 882 case DL_PROMISC_PHYS: 883 if (ipnet->ipnet_flags & IPNET_PROMISC_PHYS) 884 ipnet->ipnet_flags &= ~IPNET_PROMISC_PHYS; 885 break; 886 case DL_PROMISC_SAP: 887 if (ipnet->ipnet_flags & IPNET_PROMISC_SAP) 888 ipnet->ipnet_flags &= ~IPNET_PROMISC_SAP; 889 break; 890 case DL_PROMISC_MULTI: 891 if (ipnet->ipnet_flags & IPNET_PROMISC_MULTI) 892 ipnet->ipnet_flags &= ~IPNET_PROMISC_MULTI; 893 break; 894 default: 895 dlerrorack(q, mp, DL_PROMISCOFF_REQ, DL_BADPRIM, 0); 896 return; 897 } 898 899 if (orig_ipnet_flags == ipnet->ipnet_flags) { 900 dlerrorack(q, mp, DL_PROMISCOFF_REQ, DL_NOTENAB, 0); 901 return; 902 } 903 904 if (level == DL_PROMISC_PHYS || level == DL_PROMISC_MULTI) { 905 ipnet_leave_allmulti(ipnet->ipnet_if, 906 ipnet->ipnet_ns->netstack_ipnet); 907 } 908 909 dlokack(q, mp, DL_PROMISCOFF_REQ); 910 } 911 912 static int 913 ipnet_join_allmulti(ipnetif_t *ipnetif, ipnet_stack_t *ips) 914 { 915 int err = 0; 916 ip_stack_t *ipst = ips->ips_netstack->netstack_ip; 917 uint64_t index = ipnetif->if_index; 918 919 mutex_enter(&ips->ips_event_lock); 920 if (ipnetif->if_multicnt == 0) { 921 ASSERT((ipnetif->if_flags & 922 (IPNETIF_IPV4ALLMULTI | IPNETIF_IPV6ALLMULTI)) == 0); 923 if (ipnetif->if_flags & IPNETIF_IPV4PLUMBED) { 924 err = ip_join_allmulti(index, B_FALSE, ipst); 925 if (err != 0) 926 goto done; 927 ipnetif->if_flags |= IPNETIF_IPV4ALLMULTI; 928 } 929 if (ipnetif->if_flags & IPNETIF_IPV6PLUMBED) { 930 err = ip_join_allmulti(index, B_TRUE, ipst); 931 if (err != 0 && 932 (ipnetif->if_flags & IPNETIF_IPV4ALLMULTI)) { 933 (void) ip_leave_allmulti(index, B_FALSE, ipst); 934 ipnetif->if_flags &= ~IPNETIF_IPV4ALLMULTI; 935 goto done; 936 } 937 ipnetif->if_flags |= IPNETIF_IPV6ALLMULTI; 938 } 939 } 940 ipnetif->if_multicnt++; 941 942 done: 943 mutex_exit(&ips->ips_event_lock); 944 return (err); 945 } 946 947 static void 948 ipnet_leave_allmulti(ipnetif_t *ipnetif, ipnet_stack_t *ips) 949 { 950 int err; 951 ip_stack_t *ipst = ips->ips_netstack->netstack_ip; 952 uint64_t index = ipnetif->if_index; 953 954 mutex_enter(&ips->ips_event_lock); 955 ASSERT(ipnetif->if_multicnt != 0); 956 if (--ipnetif->if_multicnt == 0) { 957 if (ipnetif->if_flags & IPNETIF_IPV4ALLMULTI) { 958 err = ip_leave_allmulti(index, B_FALSE, ipst); 959 ASSERT(err == 0 || err == ENODEV); 960 ipnetif->if_flags &= ~IPNETIF_IPV4ALLMULTI; 961 } 962 if (ipnetif->if_flags & IPNETIF_IPV6ALLMULTI) { 963 err = ip_leave_allmulti(index, B_TRUE, ipst); 964 ASSERT(err == 0 || err == ENODEV); 965 ipnetif->if_flags &= ~IPNETIF_IPV6ALLMULTI; 966 } 967 } 968 mutex_exit(&ips->ips_event_lock); 969 } 970 971 /* 972 * Allocate a new mblk_t and put a dl_ipnetinfo_t in it. 973 * The structure it copies the header information from, 974 * hook_pkt_observe_t, is constructed using network byte 975 * order in ipobs_hook(), so there is no conversion here. 976 */ 977 static mblk_t * 978 ipnet_addheader(hook_pkt_observe_t *hdr, mblk_t *mp) 979 { 980 mblk_t *dlhdr; 981 dl_ipnetinfo_t *dl; 982 983 if ((dlhdr = allocb(sizeof (dl_ipnetinfo_t), BPRI_HI)) == NULL) { 984 freemsg(mp); 985 return (NULL); 986 } 987 dl = (dl_ipnetinfo_t *)dlhdr->b_rptr; 988 dl->dli_version = DL_IPNETINFO_VERSION; 989 dl->dli_family = hdr->hpo_family; 990 dl->dli_htype = hdr->hpo_htype; 991 dl->dli_pktlen = hdr->hpo_pktlen; 992 dl->dli_ifindex = hdr->hpo_ifindex; 993 dl->dli_grifindex = hdr->hpo_grifindex; 994 dl->dli_zsrc = hdr->hpo_zsrc; 995 dl->dli_zdst = hdr->hpo_zdst; 996 dlhdr->b_wptr += sizeof (*dl); 997 dlhdr->b_cont = mp; 998 999 return (dlhdr); 1000 } 1001 1002 static ipnet_addrtype_t 1003 ipnet_get_addrtype(ipnet_t *ipnet, ipnet_addrp_t *addr) 1004 { 1005 list_t *list; 1006 ipnetif_t *ipnetif = ipnet->ipnet_if; 1007 ipnetif_addr_t *ifaddr; 1008 ipnet_addrtype_t addrtype = IPNETADDR_UNKNOWN; 1009 1010 /* First check if the address is multicast or limited broadcast. */ 1011 switch (addr->iap_family) { 1012 case AF_INET: 1013 if (CLASSD(*(addr->iap_addr4)) || 1014 *(addr->iap_addr4) == INADDR_BROADCAST) 1015 return (IPNETADDR_MBCAST); 1016 break; 1017 case AF_INET6: 1018 if (IN6_IS_ADDR_MULTICAST(addr->iap_addr6)) 1019 return (IPNETADDR_MBCAST); 1020 break; 1021 } 1022 1023 /* 1024 * Walk the address list to see if the address belongs to our 1025 * interface or is one of our subnet broadcast addresses. 1026 */ 1027 mutex_enter(&ipnetif->if_addr_lock); 1028 list = (addr->iap_family == AF_INET) ? 1029 &ipnetif->if_ip4addr_list : &ipnetif->if_ip6addr_list; 1030 for (ifaddr = list_head(list); 1031 ifaddr != NULL && addrtype == IPNETADDR_UNKNOWN; 1032 ifaddr = list_next(list, ifaddr)) { 1033 /* 1034 * If we're not in the global zone, then only look at 1035 * addresses in our zone. 1036 */ 1037 if (ipnet->ipnet_zoneid != GLOBAL_ZONEID && 1038 ipnet->ipnet_zoneid != ifaddr->ifa_zone) 1039 continue; 1040 switch (addr->iap_family) { 1041 case AF_INET: 1042 if (ifaddr->ifa_ip4addr != INADDR_ANY && 1043 *(addr->iap_addr4) == ifaddr->ifa_ip4addr) 1044 addrtype = IPNETADDR_MYADDR; 1045 else if (ifaddr->ifa_brdaddr != INADDR_ANY && 1046 *(addr->iap_addr4) == ifaddr->ifa_brdaddr) 1047 addrtype = IPNETADDR_MBCAST; 1048 break; 1049 case AF_INET6: 1050 if (IN6_ARE_ADDR_EQUAL(addr->iap_addr6, 1051 &ifaddr->ifa_ip6addr)) 1052 addrtype = IPNETADDR_MYADDR; 1053 break; 1054 } 1055 } 1056 mutex_exit(&ipnetif->if_addr_lock); 1057 1058 return (addrtype); 1059 } 1060 1061 /* 1062 * Verify if the packet contained in hdr should be passed up to the 1063 * ipnet client stream. 1064 */ 1065 static boolean_t 1066 ipnet_accept(ipnet_t *ipnet, hook_pkt_observe_t *hdr, ipnet_addrp_t *src, 1067 ipnet_addrp_t *dst) 1068 { 1069 boolean_t obsif; 1070 uint64_t ifindex = ipnet->ipnet_if->if_index; 1071 ipnet_addrtype_t srctype; 1072 ipnet_addrtype_t dsttype; 1073 1074 srctype = ipnet_get_addrtype(ipnet, src); 1075 dsttype = ipnet_get_addrtype(ipnet, dst); 1076 1077 /* 1078 * If the packet's ifindex matches ours, or the packet's group ifindex 1079 * matches ours, it's on the interface we're observing. (Thus, 1080 * observing on the group ifindex matches all ifindexes in the group.) 1081 */ 1082 obsif = (ntohl(hdr->hpo_ifindex) == ifindex || 1083 ntohl(hdr->hpo_grifindex) == ifindex); 1084 1085 DTRACE_PROBE5(ipnet_accept__addr, 1086 ipnet_addrtype_t, srctype, ipnet_addrp_t *, src, 1087 ipnet_addrtype_t, dsttype, ipnet_addrp_t *, dst, 1088 boolean_t, obsif); 1089 1090 /* 1091 * Do not allow an ipnet stream to see packets that are not from or to 1092 * its zone. The exception is when zones are using the shared stack 1093 * model. In this case, streams in the global zone have visibility 1094 * into other shared-stack zones, and broadcast and multicast traffic 1095 * is visible by all zones in the stack. 1096 */ 1097 if (ipnet->ipnet_zoneid != GLOBAL_ZONEID && 1098 dsttype != IPNETADDR_MBCAST) { 1099 if (ipnet->ipnet_zoneid != ntohl(hdr->hpo_zsrc) && 1100 ipnet->ipnet_zoneid != ntohl(hdr->hpo_zdst)) 1101 return (B_FALSE); 1102 } 1103 1104 /* 1105 * If DL_PROMISC_SAP isn't enabled, then the bound SAP must match the 1106 * packet's IP version. 1107 */ 1108 if (!(ipnet->ipnet_flags & IPNET_PROMISC_SAP) && 1109 ipnet->ipnet_family != hdr->hpo_family) 1110 return (B_FALSE); 1111 1112 /* If the destination address is ours, then accept the packet. */ 1113 if (dsttype == IPNETADDR_MYADDR) 1114 return (B_TRUE); 1115 1116 /* 1117 * If DL_PROMISC_PHYS is enabled, then we can see all packets that are 1118 * sent or received on the interface we're observing, or packets that 1119 * have our source address (this allows us to see packets we send). 1120 */ 1121 if (ipnet->ipnet_flags & IPNET_PROMISC_PHYS) { 1122 if (srctype == IPNETADDR_MYADDR || obsif) 1123 return (B_TRUE); 1124 } 1125 1126 /* 1127 * We accept multicast and broadcast packets transmitted or received 1128 * on the interface we're observing. 1129 */ 1130 if (dsttype == IPNETADDR_MBCAST && obsif) 1131 return (B_TRUE); 1132 1133 return (B_FALSE); 1134 } 1135 1136 /* 1137 * Verify if the packet contained in hdr should be passed up to the ipnet 1138 * client stream that's in IPNET_LOMODE. 1139 */ 1140 /* ARGSUSED */ 1141 static boolean_t 1142 ipnet_loaccept(ipnet_t *ipnet, hook_pkt_observe_t *hdr, ipnet_addrp_t *src, 1143 ipnet_addrp_t *dst) 1144 { 1145 if (hdr->hpo_htype != htons(IPOBS_HOOK_LOCAL)) { 1146 /* 1147 * ipnet_if is only NULL for IPNET_MINOR_LO devices. 1148 */ 1149 if (ipnet->ipnet_if == NULL) 1150 return (B_FALSE); 1151 } 1152 1153 /* 1154 * An ipnet stream must not see packets that are not from/to its zone. 1155 */ 1156 if (ipnet->ipnet_zoneid != GLOBAL_ZONEID) { 1157 if (ipnet->ipnet_zoneid != ntohl(hdr->hpo_zsrc) && 1158 ipnet->ipnet_zoneid != ntohl(hdr->hpo_zdst)) 1159 return (B_FALSE); 1160 } 1161 1162 return (ipnet->ipnet_family == AF_UNSPEC || 1163 ipnet->ipnet_family == hdr->hpo_family); 1164 } 1165 1166 static void 1167 ipnet_dispatch(void *arg) 1168 { 1169 mblk_t *mp = arg; 1170 hook_pkt_observe_t *hdr = (hook_pkt_observe_t *)mp->b_rptr; 1171 ipnet_t *ipnet; 1172 mblk_t *netmp; 1173 list_t *list; 1174 ipnet_stack_t *ips; 1175 ipnet_addrp_t src; 1176 ipnet_addrp_t dst; 1177 1178 ips = ((netstack_t *)hdr->hpo_ctx)->netstack_ipnet; 1179 1180 netmp = hdr->hpo_pkt->b_cont; 1181 src.iap_family = hdr->hpo_family; 1182 dst.iap_family = hdr->hpo_family; 1183 1184 if (hdr->hpo_family == AF_INET) { 1185 src.iap_addr4 = &((ipha_t *)(netmp->b_rptr))->ipha_src; 1186 dst.iap_addr4 = &((ipha_t *)(netmp->b_rptr))->ipha_dst; 1187 } else { 1188 src.iap_addr6 = &((ip6_t *)(netmp->b_rptr))->ip6_src; 1189 dst.iap_addr6 = &((ip6_t *)(netmp->b_rptr))->ip6_dst; 1190 } 1191 1192 ipnet_walkers_inc(ips); 1193 1194 list = &ips->ips_str_list; 1195 for (ipnet = list_head(list); ipnet != NULL; 1196 ipnet = list_next(list, ipnet)) { 1197 if (!(*ipnet->ipnet_acceptfn)(ipnet, hdr, &src, &dst)) { 1198 IPSK_BUMP(ips, ik_acceptFail); 1199 continue; 1200 } 1201 IPSK_BUMP(ips, ik_acceptOk); 1202 1203 if (list_next(list, ipnet) == NULL) { 1204 netmp = hdr->hpo_pkt->b_cont; 1205 hdr->hpo_pkt->b_cont = NULL; 1206 } else { 1207 if ((netmp = dupmsg(hdr->hpo_pkt->b_cont)) == NULL && 1208 (netmp = copymsg(hdr->hpo_pkt->b_cont)) == NULL) { 1209 IPSK_BUMP(ips, ik_duplicationFail); 1210 continue; 1211 } 1212 } 1213 1214 if (ipnet->ipnet_flags & IPNET_INFO) { 1215 if ((netmp = ipnet_addheader(hdr, netmp)) == NULL) { 1216 IPSK_BUMP(ips, ik_dispatchHeaderDrop); 1217 continue; 1218 } 1219 } 1220 1221 if (ipnet->ipnet_rq->q_first == NULL && 1222 canputnext(ipnet->ipnet_rq)) { 1223 putnext(ipnet->ipnet_rq, netmp); 1224 IPSK_BUMP(ips, ik_dispatchDeliver); 1225 } else if (canput(ipnet->ipnet_rq)) { 1226 (void) putq(ipnet->ipnet_rq, netmp); 1227 IPSK_BUMP(ips, ik_dispatchDeliver); 1228 } else { 1229 freemsg(netmp); 1230 IPSK_BUMP(ips, ik_dispatchPutDrop); 1231 } 1232 } 1233 1234 ipnet_walkers_dec(ips); 1235 1236 freemsg(mp); 1237 } 1238 1239 static void 1240 ipnet_input(mblk_t *mp) 1241 { 1242 hook_pkt_observe_t *hdr = (hook_pkt_observe_t *)mp->b_rptr; 1243 ipnet_stack_t *ips; 1244 1245 ips = ((netstack_t *)hdr->hpo_ctx)->netstack_ipnet; 1246 1247 if (ddi_taskq_dispatch(ipnet_taskq, ipnet_dispatch, mp, DDI_NOSLEEP) != 1248 DDI_SUCCESS) { 1249 IPSK_BUMP(ips, ik_dispatchFail); 1250 freemsg(mp); 1251 } else { 1252 IPSK_BUMP(ips, ik_dispatchOk); 1253 } 1254 } 1255 1256 static ipnetif_t * 1257 ipnet_alloc_if(ipnet_stack_t *ips) 1258 { 1259 ipnetif_t *ipnetif; 1260 1261 if ((ipnetif = kmem_zalloc(sizeof (*ipnetif), KM_NOSLEEP)) == NULL) 1262 return (NULL); 1263 1264 mutex_init(&ipnetif->if_addr_lock, NULL, MUTEX_DEFAULT, 0); 1265 list_create(&ipnetif->if_ip4addr_list, sizeof (ipnetif_addr_t), 1266 offsetof(ipnetif_addr_t, ifa_link)); 1267 list_create(&ipnetif->if_ip6addr_list, sizeof (ipnetif_addr_t), 1268 offsetof(ipnetif_addr_t, ifa_link)); 1269 mutex_init(&ipnetif->if_reflock, NULL, MUTEX_DEFAULT, 0); 1270 1271 ipnetif->if_stackp = ips; 1272 1273 return (ipnetif); 1274 } 1275 1276 /* 1277 * Create a new ipnetif_t and new minor node for it. If creation is 1278 * successful the new ipnetif_t is inserted into an avl_tree 1279 * containing ipnetif's for this stack instance. 1280 */ 1281 static ipnetif_t * 1282 ipnetif_create(const char *name, uint64_t index, ipnet_stack_t *ips, 1283 uint64_t ifflags) 1284 { 1285 ipnetif_t *ipnetif; 1286 avl_index_t where = 0; 1287 minor_t ifminor; 1288 1289 /* 1290 * Because ipnetif_create() can be called from a NIC event 1291 * callback, it should not block. 1292 */ 1293 ifminor = (minor_t)id_alloc_nosleep(ipnet_minor_space); 1294 if (ifminor == (minor_t)-1) 1295 return (NULL); 1296 if ((ipnetif = ipnet_alloc_if(ips)) == NULL) { 1297 id_free(ipnet_minor_space, ifminor); 1298 return (NULL); 1299 } 1300 1301 (void) strlcpy(ipnetif->if_name, name, LIFNAMSIZ); 1302 ipnetif->if_index = (uint_t)index; 1303 ipnetif->if_zoneid = netstack_get_zoneid(ips->ips_netstack); 1304 ipnetif->if_dev = makedevice(ipnet_major, ifminor); 1305 1306 ipnetif->if_refcnt = 1; 1307 if ((ifflags & IFF_LOOPBACK) != 0) 1308 ipnetif->if_flags = IPNETIF_LOOPBACK; 1309 1310 mutex_enter(&ips->ips_avl_lock); 1311 VERIFY(avl_find(&ips->ips_avl_by_index, &index, &where) == NULL); 1312 avl_insert(&ips->ips_avl_by_index, ipnetif, where); 1313 VERIFY(avl_find(&ips->ips_avl_by_name, (void *)name, &where) == NULL); 1314 avl_insert(&ips->ips_avl_by_name, ipnetif, where); 1315 mutex_exit(&ips->ips_avl_lock); 1316 1317 return (ipnetif); 1318 } 1319 1320 static void 1321 ipnetif_remove(ipnetif_t *ipnetif, ipnet_stack_t *ips) 1322 { 1323 ipnet_t *ipnet; 1324 1325 ipnet_walkers_inc(ips); 1326 /* Send a SIGHUP to all open streams associated with this ipnetif. */ 1327 for (ipnet = list_head(&ips->ips_str_list); ipnet != NULL; 1328 ipnet = list_next(&ips->ips_str_list, ipnet)) { 1329 if (ipnet->ipnet_if == ipnetif) 1330 (void) putnextctl(ipnet->ipnet_rq, M_HANGUP); 1331 } 1332 ipnet_walkers_dec(ips); 1333 mutex_enter(&ips->ips_avl_lock); 1334 avl_remove(&ips->ips_avl_by_index, ipnetif); 1335 avl_remove(&ips->ips_avl_by_name, ipnetif); 1336 mutex_exit(&ips->ips_avl_lock); 1337 /* 1338 * Release the reference we implicitly held in ipnetif_create(). 1339 */ 1340 ipnetif_refrele(ipnetif); 1341 } 1342 1343 static void 1344 ipnet_purge_addrlist(list_t *addrlist) 1345 { 1346 ipnetif_addr_t *ifa; 1347 1348 while ((ifa = list_head(addrlist)) != NULL) { 1349 list_remove(addrlist, ifa); 1350 if (ifa->ifa_shared != NULL) 1351 ipnetif_clone_release(ifa->ifa_shared); 1352 kmem_free(ifa, sizeof (*ifa)); 1353 } 1354 } 1355 1356 static void 1357 ipnetif_free(ipnetif_t *ipnetif) 1358 { 1359 ASSERT(ipnetif->if_refcnt == 0); 1360 ASSERT(ipnetif->if_sharecnt == 0); 1361 1362 /* Remove IPv4/v6 address lists from the ipnetif */ 1363 ipnet_purge_addrlist(&ipnetif->if_ip4addr_list); 1364 list_destroy(&ipnetif->if_ip4addr_list); 1365 ipnet_purge_addrlist(&ipnetif->if_ip6addr_list); 1366 list_destroy(&ipnetif->if_ip6addr_list); 1367 mutex_destroy(&ipnetif->if_addr_lock); 1368 mutex_destroy(&ipnetif->if_reflock); 1369 if (ipnetif->if_dev != 0) 1370 id_free(ipnet_minor_space, getminor(ipnetif->if_dev)); 1371 kmem_free(ipnetif, sizeof (*ipnetif)); 1372 } 1373 1374 /* 1375 * Create an ipnetif_addr_t with the given logical interface id (lif) 1376 * and add it to the supplied ipnetif. The lif is the netinfo 1377 * representation of logical interface id, and we use this id to match 1378 * incoming netinfo events against our lists of addresses. 1379 */ 1380 static void 1381 ipnet_add_ifaddr(uint64_t lif, ipnetif_t *ipnetif, net_handle_t nd) 1382 { 1383 ipnetif_addr_t *ifaddr; 1384 zoneid_t zoneid; 1385 struct sockaddr_in bcast; 1386 struct sockaddr_storage addr; 1387 net_ifaddr_t type = NA_ADDRESS; 1388 uint64_t phyif = ipnetif->if_index; 1389 1390 if (net_getlifaddr(nd, phyif, lif, 1, &type, &addr) != 0 || 1391 net_getlifzone(nd, phyif, lif, &zoneid) != 0) 1392 return; 1393 1394 if ((ifaddr = kmem_alloc(sizeof (*ifaddr), KM_NOSLEEP)) == NULL) 1395 return; 1396 ifaddr->ifa_zone = zoneid; 1397 ifaddr->ifa_id = lif; 1398 ifaddr->ifa_shared = NULL; 1399 1400 switch (addr.ss_family) { 1401 case AF_INET: 1402 ifaddr->ifa_ip4addr = 1403 ((struct sockaddr_in *)&addr)->sin_addr.s_addr; 1404 /* 1405 * Try and get the broadcast address. Note that it's okay for 1406 * an interface to not have a broadcast address, so we don't 1407 * fail the entire operation if net_getlifaddr() fails here. 1408 */ 1409 type = NA_BROADCAST; 1410 if (net_getlifaddr(nd, phyif, lif, 1, &type, &bcast) == 0) 1411 ifaddr->ifa_brdaddr = bcast.sin_addr.s_addr; 1412 break; 1413 case AF_INET6: 1414 ifaddr->ifa_ip6addr = ((struct sockaddr_in6 *)&addr)->sin6_addr; 1415 break; 1416 } 1417 1418 /* 1419 * The zoneid stored in ipnetif_t needs to correspond to the actual 1420 * zone the address is being used in. This facilitates finding the 1421 * correct netstack_t pointer, amongst other things, later. 1422 */ 1423 if (zoneid == ALL_ZONES) 1424 zoneid = GLOBAL_ZONEID; 1425 1426 mutex_enter(&ipnetif->if_addr_lock); 1427 if (zoneid != ipnetif->if_zoneid) { 1428 ipnetif_t *ifp2; 1429 1430 ifp2 = ipnetif_clone_create(ipnetif, zoneid); 1431 ifaddr->ifa_shared = ifp2; 1432 } 1433 list_insert_tail(addr.ss_family == AF_INET ? 1434 &ipnetif->if_ip4addr_list : &ipnetif->if_ip6addr_list, ifaddr); 1435 mutex_exit(&ipnetif->if_addr_lock); 1436 } 1437 1438 static void 1439 ipnet_delete_ifaddr(ipnetif_addr_t *ifaddr, ipnetif_t *ipnetif, boolean_t isv6) 1440 { 1441 mutex_enter(&ipnetif->if_addr_lock); 1442 if (ifaddr->ifa_shared != NULL) 1443 ipnetif_clone_release(ifaddr->ifa_shared); 1444 1445 list_remove(isv6 ? 1446 &ipnetif->if_ip6addr_list : &ipnetif->if_ip4addr_list, ifaddr); 1447 mutex_exit(&ipnetif->if_addr_lock); 1448 kmem_free(ifaddr, sizeof (*ifaddr)); 1449 } 1450 1451 static void 1452 ipnet_plumb_ev(ipnet_nicevent_t *ipne, ipnet_stack_t *ips, boolean_t isv6) 1453 { 1454 ipnetif_t *ipnetif; 1455 boolean_t refrele_needed = B_TRUE; 1456 uint64_t ifflags; 1457 uint64_t ifindex; 1458 char *ifname; 1459 1460 ifflags = 0; 1461 ifname = ipne->ipne_ifname; 1462 ifindex = ipne->ipne_ifindex; 1463 1464 (void) net_getlifflags(ipne->ipne_protocol, ifindex, 0, &ifflags); 1465 1466 if ((ipnetif = ipnetif_getby_index(ifindex, ips)) == NULL) { 1467 ipnetif = ipnetif_create(ifname, ifindex, ips, ifflags); 1468 refrele_needed = B_FALSE; 1469 } 1470 if (ipnetif != NULL) { 1471 ipnetif->if_flags |= 1472 isv6 ? IPNETIF_IPV6PLUMBED : IPNETIF_IPV4PLUMBED; 1473 } 1474 1475 if (ipnetif->if_multicnt != 0) { 1476 if (ip_join_allmulti(ifindex, isv6, 1477 ips->ips_netstack->netstack_ip) == 0) { 1478 ipnetif->if_flags |= 1479 isv6 ? IPNETIF_IPV6ALLMULTI : IPNETIF_IPV4ALLMULTI; 1480 } 1481 } 1482 1483 if (refrele_needed) 1484 ipnetif_refrele(ipnetif); 1485 } 1486 1487 static void 1488 ipnet_unplumb_ev(uint64_t ifindex, ipnet_stack_t *ips, boolean_t isv6) 1489 { 1490 ipnetif_t *ipnetif; 1491 1492 if ((ipnetif = ipnetif_getby_index(ifindex, ips)) == NULL) 1493 return; 1494 1495 mutex_enter(&ipnetif->if_addr_lock); 1496 ipnet_purge_addrlist(isv6 ? 1497 &ipnetif->if_ip6addr_list : &ipnetif->if_ip4addr_list); 1498 mutex_exit(&ipnetif->if_addr_lock); 1499 1500 /* 1501 * Note that we have one ipnetif for both IPv4 and IPv6, but we receive 1502 * separate NE_UNPLUMB events for IPv4 and IPv6. We remove the ipnetif 1503 * if both IPv4 and IPv6 interfaces have been unplumbed. 1504 */ 1505 ipnetif->if_flags &= isv6 ? ~IPNETIF_IPV6PLUMBED : ~IPNETIF_IPV4PLUMBED; 1506 if (!(ipnetif->if_flags & (IPNETIF_IPV4PLUMBED | IPNETIF_IPV6PLUMBED))) 1507 ipnetif_remove(ipnetif, ips); 1508 ipnetif_refrele(ipnetif); 1509 } 1510 1511 static void 1512 ipnet_lifup_ev(uint64_t ifindex, uint64_t lifindex, net_handle_t nd, 1513 ipnet_stack_t *ips, boolean_t isv6) 1514 { 1515 ipnetif_t *ipnetif; 1516 ipnetif_addr_t *ifaddr; 1517 1518 if ((ipnetif = ipnetif_getby_index(ifindex, ips)) == NULL) 1519 return; 1520 if ((ifaddr = ipnet_match_lif(ipnetif, lifindex, isv6)) != NULL) { 1521 /* 1522 * We must have missed a NE_LIF_DOWN event. Delete this 1523 * ifaddr and re-create it. 1524 */ 1525 ipnet_delete_ifaddr(ifaddr, ipnetif, isv6); 1526 } 1527 1528 ipnet_add_ifaddr(lifindex, ipnetif, nd); 1529 ipnetif_refrele(ipnetif); 1530 } 1531 1532 static void 1533 ipnet_lifdown_ev(uint64_t ifindex, uint64_t lifindex, ipnet_stack_t *ips, 1534 boolean_t isv6) 1535 { 1536 ipnetif_t *ipnetif; 1537 ipnetif_addr_t *ifaddr; 1538 1539 if ((ipnetif = ipnetif_getby_index(ifindex, ips)) == NULL) 1540 return; 1541 if ((ifaddr = ipnet_match_lif(ipnetif, lifindex, isv6)) != NULL) 1542 ipnet_delete_ifaddr(ifaddr, ipnetif, isv6); 1543 ipnetif_refrele(ipnetif); 1544 /* 1545 * Make sure that open streams on this ipnetif are still allowed to 1546 * have it open. 1547 */ 1548 ipnetif_zonecheck(ipnetif, ips); 1549 } 1550 1551 /* 1552 * This callback from the NIC event framework dispatches a taskq as the event 1553 * handlers may block. 1554 */ 1555 /* ARGSUSED */ 1556 static int 1557 ipnet_nicevent_cb(hook_event_token_t token, hook_data_t info, void *arg) 1558 { 1559 ipnet_stack_t *ips = arg; 1560 hook_nic_event_t *hn = (hook_nic_event_t *)info; 1561 ipnet_nicevent_t *ipne; 1562 1563 if ((ipne = kmem_alloc(sizeof (ipnet_nicevent_t), KM_NOSLEEP)) == NULL) 1564 return (0); 1565 ipne->ipne_event = hn->hne_event; 1566 ipne->ipne_protocol = hn->hne_protocol; 1567 ipne->ipne_stackid = ips->ips_netstack->netstack_stackid; 1568 ipne->ipne_ifindex = hn->hne_nic; 1569 ipne->ipne_lifindex = hn->hne_lif; 1570 if (hn->hne_datalen != 0) { 1571 (void) strlcpy(ipne->ipne_ifname, hn->hne_data, 1572 sizeof (ipne->ipne_ifname)); 1573 } 1574 (void) ddi_taskq_dispatch(ipnet_nicevent_taskq, ipnet_nicevent_task, 1575 ipne, DDI_NOSLEEP); 1576 return (0); 1577 } 1578 1579 static void 1580 ipnet_nicevent_task(void *arg) 1581 { 1582 ipnet_nicevent_t *ipne = arg; 1583 netstack_t *ns; 1584 ipnet_stack_t *ips; 1585 boolean_t isv6; 1586 1587 if ((ns = netstack_find_by_stackid(ipne->ipne_stackid)) == NULL) 1588 goto done; 1589 ips = ns->netstack_ipnet; 1590 isv6 = (ipne->ipne_protocol == ips->ips_ndv6); 1591 1592 mutex_enter(&ips->ips_event_lock); 1593 switch (ipne->ipne_event) { 1594 case NE_PLUMB: 1595 ipnet_plumb_ev(ipne, ips, isv6); 1596 break; 1597 case NE_UNPLUMB: 1598 ipnet_unplumb_ev(ipne->ipne_ifindex, ips, isv6); 1599 break; 1600 case NE_LIF_UP: 1601 ipnet_lifup_ev(ipne->ipne_ifindex, ipne->ipne_lifindex, 1602 ipne->ipne_protocol, ips, isv6); 1603 break; 1604 case NE_LIF_DOWN: 1605 ipnet_lifdown_ev(ipne->ipne_ifindex, ipne->ipne_lifindex, ips, 1606 isv6); 1607 break; 1608 default: 1609 break; 1610 } 1611 mutex_exit(&ips->ips_event_lock); 1612 done: 1613 if (ns != NULL) 1614 netstack_rele(ns); 1615 kmem_free(ipne, sizeof (ipnet_nicevent_t)); 1616 } 1617 1618 dev_t 1619 ipnet_if_getdev(char *name, zoneid_t zoneid) 1620 { 1621 netstack_t *ns; 1622 ipnet_stack_t *ips; 1623 ipnetif_t *ipnetif; 1624 dev_t dev = (dev_t)-1; 1625 1626 if (is_system_labeled() && zoneid != GLOBAL_ZONEID) 1627 return (dev); 1628 if ((ns = netstack_find_by_zoneid(zoneid)) == NULL) 1629 return (dev); 1630 1631 ips = ns->netstack_ipnet; 1632 mutex_enter(&ips->ips_avl_lock); 1633 if ((ipnetif = avl_find(&ips->ips_avl_by_name, name, NULL)) != NULL) { 1634 if (ipnetif_in_zone(ipnetif, zoneid, ips)) 1635 dev = ipnetif->if_dev; 1636 } 1637 mutex_exit(&ips->ips_avl_lock); 1638 netstack_rele(ns); 1639 1640 return (dev); 1641 } 1642 1643 static ipnetif_t * 1644 ipnetif_getby_index(uint64_t id, ipnet_stack_t *ips) 1645 { 1646 ipnetif_t *ipnetif; 1647 1648 mutex_enter(&ips->ips_avl_lock); 1649 if ((ipnetif = avl_find(&ips->ips_avl_by_index, &id, NULL)) != NULL) 1650 ipnetif_refhold(ipnetif); 1651 mutex_exit(&ips->ips_avl_lock); 1652 return (ipnetif); 1653 } 1654 1655 static ipnetif_t * 1656 ipnetif_getby_dev(dev_t dev, ipnet_stack_t *ips) 1657 { 1658 ipnetif_t *ipnetif; 1659 avl_tree_t *tree; 1660 1661 mutex_enter(&ips->ips_avl_lock); 1662 tree = &ips->ips_avl_by_index; 1663 for (ipnetif = avl_first(tree); ipnetif != NULL; 1664 ipnetif = avl_walk(tree, ipnetif, AVL_AFTER)) { 1665 if (ipnetif->if_dev == dev) { 1666 ipnetif_refhold(ipnetif); 1667 break; 1668 } 1669 } 1670 mutex_exit(&ips->ips_avl_lock); 1671 return (ipnetif); 1672 } 1673 1674 static ipnetif_addr_t * 1675 ipnet_match_lif(ipnetif_t *ipnetif, lif_if_t lid, boolean_t isv6) 1676 { 1677 ipnetif_addr_t *ifaddr; 1678 list_t *list; 1679 1680 mutex_enter(&ipnetif->if_addr_lock); 1681 list = isv6 ? &ipnetif->if_ip6addr_list : &ipnetif->if_ip4addr_list; 1682 for (ifaddr = list_head(list); ifaddr != NULL; 1683 ifaddr = list_next(list, ifaddr)) { 1684 if (lid == ifaddr->ifa_id) 1685 break; 1686 } 1687 mutex_exit(&ipnetif->if_addr_lock); 1688 return (ifaddr); 1689 } 1690 1691 /* ARGSUSED */ 1692 static void * 1693 ipnet_stack_init(netstackid_t stackid, netstack_t *ns) 1694 { 1695 ipnet_stack_t *ips; 1696 1697 ips = kmem_zalloc(sizeof (*ips), KM_SLEEP); 1698 ips->ips_netstack = ns; 1699 mutex_init(&ips->ips_avl_lock, NULL, MUTEX_DEFAULT, 0); 1700 avl_create(&ips->ips_avl_by_index, ipnetif_compare_index, 1701 sizeof (ipnetif_t), offsetof(ipnetif_t, if_avl_by_index)); 1702 avl_create(&ips->ips_avl_by_name, ipnetif_compare_name, 1703 sizeof (ipnetif_t), offsetof(ipnetif_t, if_avl_by_name)); 1704 avl_create(&ips->ips_avl_by_shared, ipnetif_compare_name_zone, 1705 sizeof (ipnetif_t), offsetof(ipnetif_t, if_avl_by_shared)); 1706 mutex_init(&ips->ips_walkers_lock, NULL, MUTEX_DEFAULT, NULL); 1707 cv_init(&ips->ips_walkers_cv, NULL, CV_DRIVER, NULL); 1708 list_create(&ips->ips_str_list, sizeof (ipnet_t), 1709 offsetof(ipnet_t, ipnet_next)); 1710 ipnet_register_netihook(ips); 1711 return (ips); 1712 } 1713 1714 /* ARGSUSED */ 1715 static void 1716 ipnet_stack_fini(netstackid_t stackid, void *arg) 1717 { 1718 ipnet_stack_t *ips = arg; 1719 ipnetif_t *ipnetif, *nipnetif; 1720 1721 if (ips->ips_kstatp != NULL) { 1722 zoneid_t zoneid; 1723 1724 zoneid = netstackid_to_zoneid(stackid); 1725 net_kstat_delete(net_zoneidtonetid(zoneid), ips->ips_kstatp); 1726 } 1727 if (ips->ips_ndv4 != NULL) { 1728 VERIFY(net_hook_unregister(ips->ips_ndv4, NH_NIC_EVENTS, 1729 ips->ips_nicevents) == 0); 1730 VERIFY(net_protocol_release(ips->ips_ndv4) == 0); 1731 } 1732 if (ips->ips_ndv6 != NULL) { 1733 VERIFY(net_hook_unregister(ips->ips_ndv6, NH_NIC_EVENTS, 1734 ips->ips_nicevents) == 0); 1735 VERIFY(net_protocol_release(ips->ips_ndv6) == 0); 1736 } 1737 hook_free(ips->ips_nicevents); 1738 1739 for (ipnetif = avl_first(&ips->ips_avl_by_index); ipnetif != NULL; 1740 ipnetif = nipnetif) { 1741 nipnetif = AVL_NEXT(&ips->ips_avl_by_index, ipnetif); 1742 ipnetif_remove(ipnetif, ips); 1743 } 1744 avl_destroy(&ips->ips_avl_by_shared); 1745 avl_destroy(&ips->ips_avl_by_index); 1746 avl_destroy(&ips->ips_avl_by_name); 1747 mutex_destroy(&ips->ips_avl_lock); 1748 mutex_destroy(&ips->ips_walkers_lock); 1749 cv_destroy(&ips->ips_walkers_cv); 1750 list_destroy(&ips->ips_str_list); 1751 kmem_free(ips, sizeof (*ips)); 1752 } 1753 1754 /* Do any of the addresses in addrlist belong the supplied zoneid? */ 1755 static boolean_t 1756 ipnet_addrs_in_zone(list_t *addrlist, zoneid_t zoneid) 1757 { 1758 ipnetif_addr_t *ifa; 1759 1760 for (ifa = list_head(addrlist); ifa != NULL; 1761 ifa = list_next(addrlist, ifa)) { 1762 if (ifa->ifa_zone == zoneid) 1763 return (B_TRUE); 1764 } 1765 return (B_FALSE); 1766 } 1767 1768 /* Should the supplied ipnetif be visible from the supplied zoneid? */ 1769 static boolean_t 1770 ipnetif_in_zone(ipnetif_t *ipnetif, zoneid_t zoneid, ipnet_stack_t *ips) 1771 { 1772 int ret; 1773 1774 /* 1775 * The global zone has visibility into all interfaces in the global 1776 * stack, and exclusive stack zones have visibility into all 1777 * interfaces in their stack. 1778 */ 1779 if (zoneid == GLOBAL_ZONEID || 1780 ips->ips_netstack->netstack_stackid != GLOBAL_NETSTACKID) 1781 return (B_TRUE); 1782 1783 /* 1784 * Shared-stack zones only have visibility for interfaces that have 1785 * addresses in their zone. 1786 */ 1787 mutex_enter(&ipnetif->if_addr_lock); 1788 ret = ipnet_addrs_in_zone(&ipnetif->if_ip4addr_list, zoneid) || 1789 ipnet_addrs_in_zone(&ipnetif->if_ip6addr_list, zoneid); 1790 mutex_exit(&ipnetif->if_addr_lock); 1791 return (ret); 1792 } 1793 1794 /* 1795 * Verify that any ipnet_t that has a reference to the supplied ipnetif should 1796 * still be allowed to have it open. A given ipnet_t may no longer be allowed 1797 * to have an ipnetif open if there are no longer any addresses that belong to 1798 * the ipnetif in the ipnet_t's non-global shared-stack zoneid. If that's the 1799 * case, send the ipnet_t an M_HANGUP. 1800 */ 1801 static void 1802 ipnetif_zonecheck(ipnetif_t *ipnetif, ipnet_stack_t *ips) 1803 { 1804 list_t *strlist = &ips->ips_str_list; 1805 ipnet_t *ipnet; 1806 1807 ipnet_walkers_inc(ips); 1808 for (ipnet = list_head(strlist); ipnet != NULL; 1809 ipnet = list_next(strlist, ipnet)) { 1810 if (ipnet->ipnet_if != ipnetif) 1811 continue; 1812 if (!ipnetif_in_zone(ipnetif, ipnet->ipnet_zoneid, ips)) 1813 (void) putnextctl(ipnet->ipnet_rq, M_HANGUP); 1814 } 1815 ipnet_walkers_dec(ips); 1816 } 1817 1818 void 1819 ipnet_walk_if(ipnet_walkfunc_t *cb, void *arg, zoneid_t zoneid) 1820 { 1821 ipnetif_t *ipnetif; 1822 list_t cbdata; 1823 ipnetif_cbdata_t *cbnode; 1824 netstack_t *ns; 1825 ipnet_stack_t *ips; 1826 1827 /* 1828 * On labeled systems, non-global zones shouldn't see anything 1829 * in /dev/ipnet. 1830 */ 1831 if (is_system_labeled() && zoneid != GLOBAL_ZONEID) 1832 return; 1833 1834 if ((ns = netstack_find_by_zoneid(zoneid)) == NULL) 1835 return; 1836 1837 ips = ns->netstack_ipnet; 1838 list_create(&cbdata, sizeof (ipnetif_cbdata_t), 1839 offsetof(ipnetif_cbdata_t, ic_next)); 1840 1841 mutex_enter(&ips->ips_avl_lock); 1842 for (ipnetif = avl_first(&ips->ips_avl_by_index); ipnetif != NULL; 1843 ipnetif = avl_walk(&ips->ips_avl_by_index, ipnetif, AVL_AFTER)) { 1844 if (!ipnetif_in_zone(ipnetif, zoneid, ips)) 1845 continue; 1846 cbnode = kmem_zalloc(sizeof (ipnetif_cbdata_t), KM_SLEEP); 1847 (void) strlcpy(cbnode->ic_ifname, ipnetif->if_name, LIFNAMSIZ); 1848 cbnode->ic_dev = ipnetif->if_dev; 1849 list_insert_head(&cbdata, cbnode); 1850 } 1851 mutex_exit(&ips->ips_avl_lock); 1852 1853 while ((cbnode = list_head(&cbdata)) != NULL) { 1854 cb(cbnode->ic_ifname, arg, cbnode->ic_dev); 1855 list_remove(&cbdata, cbnode); 1856 kmem_free(cbnode, sizeof (ipnetif_cbdata_t)); 1857 } 1858 list_destroy(&cbdata); 1859 netstack_rele(ns); 1860 } 1861 1862 static int 1863 ipnetif_compare_index(const void *index_ptr, const void *ipnetifp) 1864 { 1865 int64_t index1 = *((int64_t *)index_ptr); 1866 int64_t index2 = (int64_t)((ipnetif_t *)ipnetifp)->if_index; 1867 1868 return (SIGNOF(index2 - index1)); 1869 } 1870 1871 static int 1872 ipnetif_compare_name(const void *name_ptr, const void *ipnetifp) 1873 { 1874 int res; 1875 1876 res = strcmp(((ipnetif_t *)ipnetifp)->if_name, name_ptr); 1877 return (SIGNOF(res)); 1878 } 1879 1880 static int 1881 ipnetif_compare_name_zone(const void *key_ptr, const void *ipnetifp) 1882 { 1883 const uintptr_t *ptr = key_ptr; 1884 const ipnetif_t *ifp; 1885 int res; 1886 1887 ifp = ipnetifp; 1888 res = ifp->if_zoneid - ptr[0]; 1889 if (res != 0) 1890 return (SIGNOF(res)); 1891 res = strcmp(ifp->if_name, (char *)ptr[1]); 1892 return (SIGNOF(res)); 1893 } 1894 1895 static void 1896 ipnetif_refhold(ipnetif_t *ipnetif) 1897 { 1898 mutex_enter(&ipnetif->if_reflock); 1899 ipnetif->if_refcnt++; 1900 mutex_exit(&ipnetif->if_reflock); 1901 } 1902 1903 static void 1904 ipnetif_refrele(ipnetif_t *ipnetif) 1905 { 1906 mutex_enter(&ipnetif->if_reflock); 1907 ASSERT(ipnetif->if_refcnt > 0); 1908 if (--ipnetif->if_refcnt == 0) 1909 ipnetif_free(ipnetif); 1910 else 1911 mutex_exit(&ipnetif->if_reflock); 1912 } 1913 1914 static void 1915 ipnet_walkers_inc(ipnet_stack_t *ips) 1916 { 1917 mutex_enter(&ips->ips_walkers_lock); 1918 ips->ips_walkers_cnt++; 1919 mutex_exit(&ips->ips_walkers_lock); 1920 } 1921 1922 static void 1923 ipnet_walkers_dec(ipnet_stack_t *ips) 1924 { 1925 mutex_enter(&ips->ips_walkers_lock); 1926 ASSERT(ips->ips_walkers_cnt != 0); 1927 if (--ips->ips_walkers_cnt == 0) 1928 cv_broadcast(&ips->ips_walkers_cv); 1929 mutex_exit(&ips->ips_walkers_lock); 1930 } 1931 1932 /*ARGSUSED*/ 1933 static int 1934 ipobs_bounce_func(hook_event_token_t token, hook_data_t info, void *arg) 1935 { 1936 hook_pkt_observe_t *hdr; 1937 pfv_t func = (pfv_t)arg; 1938 mblk_t *mp; 1939 1940 hdr = (hook_pkt_observe_t *)info; 1941 /* 1942 * Code in ip_input() expects that it is the only one accessing the 1943 * packet. 1944 */ 1945 mp = copymsg(hdr->hpo_pkt); 1946 if (mp == NULL) { 1947 netstack_t *ns = hdr->hpo_ctx; 1948 ipnet_stack_t *ips = ns->netstack_ipnet; 1949 1950 IPSK_BUMP(ips, ik_dispatchDupDrop); 1951 return (0); 1952 } 1953 1954 hdr = (hook_pkt_observe_t *)mp->b_rptr; 1955 hdr->hpo_pkt = mp; 1956 1957 func(mp); 1958 1959 return (0); 1960 } 1961 1962 hook_t * 1963 ipobs_register_hook(netstack_t *ns, pfv_t func) 1964 { 1965 ip_stack_t *ipst = ns->netstack_ip; 1966 char name[32]; 1967 hook_t *hook; 1968 1969 HOOK_INIT(hook, ipobs_bounce_func, "", (void *)func); 1970 VERIFY(hook != NULL); 1971 1972 /* 1973 * To register multiple hooks with he same callback function, 1974 * a unique name is needed. 1975 */ 1976 (void) snprintf(name, sizeof (name), "ipobserve_%p", (void *)hook); 1977 hook->h_name = strdup(name); 1978 1979 (void) net_hook_register(ipst->ips_ip4_observe_pr, NH_OBSERVE, hook); 1980 (void) net_hook_register(ipst->ips_ip6_observe_pr, NH_OBSERVE, hook); 1981 1982 return (hook); 1983 } 1984 1985 void 1986 ipobs_unregister_hook(netstack_t *ns, hook_t *hook) 1987 { 1988 ip_stack_t *ipst = ns->netstack_ip; 1989 1990 (void) net_hook_unregister(ipst->ips_ip4_observe_pr, NH_OBSERVE, hook); 1991 1992 (void) net_hook_unregister(ipst->ips_ip6_observe_pr, NH_OBSERVE, hook); 1993 1994 strfree(hook->h_name); 1995 1996 hook_free(hook); 1997 } 1998 1999 /* ******************************************************************** */ 2000 /* BPF Functions below */ 2001 /* ******************************************************************** */ 2002 2003 /* 2004 * Convenience function to make mapping a zoneid to an ipnet_stack_t easy. 2005 */ 2006 ipnet_stack_t * 2007 ipnet_find_by_zoneid(zoneid_t zoneid) 2008 { 2009 netstack_t *ns; 2010 2011 VERIFY((ns = netstack_find_by_zoneid(zoneid)) != NULL); 2012 return (ns->netstack_ipnet); 2013 } 2014 2015 /* 2016 * Functions, such as the above ipnet_find_by_zoneid(), will return a 2017 * pointer to ipnet_stack_t by calling a netstack lookup function. 2018 * The netstack_find_*() functions return a pointer after doing a "hold" 2019 * on the data structure and thereby require a "release" when the caller 2020 * is finished with it. We need to mirror that API here and thus a caller 2021 * of ipnet_find_by_zoneid() is required to call ipnet_rele(). 2022 */ 2023 void 2024 ipnet_rele(ipnet_stack_t *ips) 2025 { 2026 netstack_rele(ips->ips_netstack); 2027 } 2028 2029 /* 2030 */ 2031 void 2032 ipnet_set_itap(bpf_itap_fn_t tapfunc) 2033 { 2034 ipnet_itap = tapfunc; 2035 } 2036 2037 /* 2038 * The list of interfaces available via ipnet is private for each zone, 2039 * so the AVL tree of each zone must be searched for a given name, even 2040 * if all names are unique. 2041 */ 2042 int 2043 ipnet_open_byname(const char *name, ipnetif_t **ptr, zoneid_t zoneid) 2044 { 2045 ipnet_stack_t *ips; 2046 ipnetif_t *ipnetif; 2047 2048 ASSERT(ptr != NULL); 2049 VERIFY((ips = ipnet_find_by_zoneid(zoneid)) != NULL); 2050 2051 mutex_enter(&ips->ips_avl_lock); 2052 2053 /* 2054 * Shared instance zone? 2055 */ 2056 if (netstackid_to_zoneid(zoneid_to_netstackid(zoneid)) != zoneid) { 2057 uintptr_t key[2] = { zoneid, (uintptr_t)name }; 2058 2059 ipnetif = avl_find(&ips->ips_avl_by_shared, (void *)key, NULL); 2060 } else { 2061 ipnetif = avl_find(&ips->ips_avl_by_name, (void *)name, NULL); 2062 } 2063 if (ipnetif != NULL) 2064 ipnetif_refhold(ipnetif); 2065 mutex_exit(&ips->ips_avl_lock); 2066 2067 *ptr = ipnetif; 2068 ipnet_rele(ips); 2069 2070 if (ipnetif == NULL) 2071 return (ESRCH); 2072 return (0); 2073 } 2074 2075 void 2076 ipnet_close_byhandle(ipnetif_t *ifp) 2077 { 2078 ASSERT(ifp != NULL); 2079 ipnetif_refrele(ifp); 2080 } 2081 2082 const char * 2083 ipnet_name(ipnetif_t *ifp) 2084 { 2085 ASSERT(ifp != NULL); 2086 return (ifp->if_name); 2087 } 2088 2089 /* 2090 * To find the linkid for a given name, it is necessary to know which zone 2091 * the interface name belongs to and to search the avl tree for that zone 2092 * as there is no master list of all interfaces and which zone they belong 2093 * to. It is assumed that the caller of this function is somehow already 2094 * working with the ipnet interfaces and hence the ips_event_lock is held. 2095 * When BPF calls into this function, it is doing so because of an event 2096 * in ipnet, and thus ipnet holds the ips_event_lock. Thus the datalink id 2097 * value returned has meaning without the need for grabbing a hold on the 2098 * owning structure. 2099 */ 2100 int 2101 ipnet_get_linkid_byname(const char *name, uint_t *idp, zoneid_t zoneid) 2102 { 2103 ipnet_stack_t *ips; 2104 ipnetif_t *ifp; 2105 2106 VERIFY((ips = ipnet_find_by_zoneid(zoneid)) != NULL); 2107 ASSERT(mutex_owned(&ips->ips_event_lock)); 2108 2109 mutex_enter(&ips->ips_avl_lock); 2110 ifp = avl_find(&ips->ips_avl_by_name, (void *)name, NULL); 2111 if (ifp != NULL) 2112 *idp = (uint_t)ifp->if_index; 2113 2114 /* 2115 * Shared instance zone? 2116 */ 2117 if (netstackid_to_zoneid(zoneid_to_netstackid(zoneid)) != zoneid) { 2118 uintptr_t key[2] = { zoneid, (uintptr_t)name }; 2119 2120 ifp = avl_find(&ips->ips_avl_by_shared, (void *)key, NULL); 2121 if (ifp != NULL) 2122 *idp = (uint_t)ifp->if_index; 2123 } 2124 2125 mutex_exit(&ips->ips_avl_lock); 2126 ipnet_rele(ips); 2127 2128 if (ifp == NULL) 2129 return (ESRCH); 2130 return (0); 2131 } 2132 2133 /* 2134 * Strictly speaking, there is no such thing as a "client" in ipnet, like 2135 * there is in mac. BPF only needs to have this because it is required as 2136 * part of interfacing correctly with mac. The reuse of the original 2137 * ipnetif_t as a client poses no danger, so long as it is done with its 2138 * own ref-count'd hold that is given up on close. 2139 */ 2140 int 2141 ipnet_client_open(ipnetif_t *ptr, ipnetif_t **result) 2142 { 2143 ASSERT(ptr != NULL); 2144 ASSERT(result != NULL); 2145 ipnetif_refhold(ptr); 2146 *result = ptr; 2147 2148 return (0); 2149 } 2150 2151 void 2152 ipnet_client_close(ipnetif_t *ptr) 2153 { 2154 ASSERT(ptr != NULL); 2155 ipnetif_refrele(ptr); 2156 } 2157 2158 /* 2159 * This is called from BPF when it needs to start receiving packets 2160 * from ipnet. 2161 * 2162 * The use of the ipnet_t structure here is somewhat lightweight when 2163 * compared to how it is used elsewhere but it already has all of the 2164 * right fields in it, so reuse here doesn't seem out of order. Its 2165 * primary purpose here is to provide the means to store pointers for 2166 * use when ipnet_promisc_remove() needs to be called. 2167 * 2168 * This should never be called for the IPNET_MINOR_LO device as it is 2169 * never created via ipnetif_create. 2170 */ 2171 /*ARGSUSED*/ 2172 int 2173 ipnet_promisc_add(void *handle, uint_t how, void *data, uintptr_t *mhandle, 2174 int flags) 2175 { 2176 ip_stack_t *ipst; 2177 netstack_t *ns; 2178 ipnetif_t *ifp; 2179 ipnet_t *ipnet; 2180 char name[32]; 2181 int error; 2182 2183 ifp = (ipnetif_t *)handle; 2184 ns = netstack_find_by_zoneid(ifp->if_zoneid); 2185 2186 if ((how == DL_PROMISC_PHYS) || (how == DL_PROMISC_MULTI)) { 2187 error = ipnet_join_allmulti(ifp, ns->netstack_ipnet); 2188 if (error != 0) 2189 return (error); 2190 } else { 2191 return (EINVAL); 2192 } 2193 2194 ipnet = kmem_zalloc(sizeof (*ipnet), KM_SLEEP); 2195 ipnet->ipnet_if = ifp; 2196 ipnet->ipnet_ns = ns; 2197 ipnet->ipnet_flags = flags; 2198 2199 if ((ifp->if_flags & IPNETIF_LOOPBACK) != 0) { 2200 ipnet->ipnet_acceptfn = ipnet_loaccept; 2201 } else { 2202 ipnet->ipnet_acceptfn = ipnet_accept; 2203 } 2204 2205 /* 2206 * To register multiple hooks with the same callback function, 2207 * a unique name is needed. 2208 */ 2209 HOOK_INIT(ipnet->ipnet_hook, ipnet_bpf_bounce, "", ipnet); 2210 (void) snprintf(name, sizeof (name), "ipnet_promisc_%p", 2211 (void *)ipnet->ipnet_hook); 2212 ipnet->ipnet_hook->h_name = strdup(name); 2213 ipnet->ipnet_data = data; 2214 ipnet->ipnet_zoneid = ifp->if_zoneid; 2215 2216 ipst = ns->netstack_ip; 2217 2218 error = net_hook_register(ipst->ips_ip4_observe_pr, NH_OBSERVE, 2219 ipnet->ipnet_hook); 2220 if (error != 0) 2221 goto regfail; 2222 2223 error = net_hook_register(ipst->ips_ip6_observe_pr, NH_OBSERVE, 2224 ipnet->ipnet_hook); 2225 if (error != 0) { 2226 (void) net_hook_unregister(ipst->ips_ip4_observe_pr, 2227 NH_OBSERVE, ipnet->ipnet_hook); 2228 goto regfail; 2229 } 2230 2231 *mhandle = (uintptr_t)ipnet; 2232 netstack_rele(ns); 2233 2234 return (0); 2235 2236 regfail: 2237 cmn_err(CE_WARN, "net_hook_register failed: %d", error); 2238 strfree(ipnet->ipnet_hook->h_name); 2239 hook_free(ipnet->ipnet_hook); 2240 netstack_rele(ns); 2241 return (error); 2242 } 2243 2244 void 2245 ipnet_promisc_remove(void *data) 2246 { 2247 ip_stack_t *ipst; 2248 ipnet_t *ipnet; 2249 hook_t *hook; 2250 2251 ipnet = data; 2252 ipst = ipnet->ipnet_ns->netstack_ip; 2253 hook = ipnet->ipnet_hook; 2254 2255 VERIFY(net_hook_unregister(ipst->ips_ip4_observe_pr, NH_OBSERVE, 2256 hook) == 0); 2257 2258 VERIFY(net_hook_unregister(ipst->ips_ip6_observe_pr, NH_OBSERVE, 2259 hook) == 0); 2260 2261 strfree(hook->h_name); 2262 2263 hook_free(hook); 2264 2265 kmem_free(ipnet, sizeof (*ipnet)); 2266 } 2267 2268 /* 2269 * arg here comes from the ipnet_t allocated in ipnet_promisc_add. 2270 * An important field from that structure is "ipnet_data" that 2271 * contains the "data" pointer passed into ipnet_promisc_add: it needs 2272 * to be passed back to bpf when we call into ipnet_itap. 2273 * 2274 * ipnet_itap is set by ipnet_set_bpfattach, which in turn is called 2275 * from BPF. 2276 */ 2277 /*ARGSUSED*/ 2278 static int 2279 ipnet_bpf_bounce(hook_event_token_t token, hook_data_t info, void *arg) 2280 { 2281 hook_pkt_observe_t *hdr; 2282 ipnet_addrp_t src; 2283 ipnet_addrp_t dst; 2284 ipnet_stack_t *ips; 2285 ipnet_t *ipnet; 2286 mblk_t *netmp; 2287 mblk_t *mp; 2288 2289 hdr = (hook_pkt_observe_t *)info; 2290 mp = hdr->hpo_pkt; 2291 ipnet = (ipnet_t *)arg; 2292 ips = ((netstack_t *)hdr->hpo_ctx)->netstack_ipnet; 2293 2294 netmp = hdr->hpo_pkt->b_cont; 2295 src.iap_family = hdr->hpo_family; 2296 dst.iap_family = hdr->hpo_family; 2297 2298 if (hdr->hpo_family == AF_INET) { 2299 src.iap_addr4 = &((ipha_t *)(netmp->b_rptr))->ipha_src; 2300 dst.iap_addr4 = &((ipha_t *)(netmp->b_rptr))->ipha_dst; 2301 } else { 2302 src.iap_addr6 = &((ip6_t *)(netmp->b_rptr))->ip6_src; 2303 dst.iap_addr6 = &((ip6_t *)(netmp->b_rptr))->ip6_dst; 2304 } 2305 2306 if (!(*ipnet->ipnet_acceptfn)(ipnet, hdr, &src, &dst)) { 2307 IPSK_BUMP(ips, ik_acceptFail); 2308 return (0); 2309 } 2310 IPSK_BUMP(ips, ik_acceptOk); 2311 2312 ipnet_itap(ipnet->ipnet_data, mp, 2313 hdr->hpo_htype == htons(IPOBS_HOOK_OUTBOUND), 2314 ntohl(hdr->hpo_pktlen) + MBLKL(mp)); 2315 2316 return (0); 2317 } 2318 2319 /* 2320 * clone'd ipnetif_t's are created when a shared IP instance zone comes 2321 * to life and configures an IP address. The model that BPF uses is that 2322 * each interface must have a unique pointer and each interface must be 2323 * representative of what it can capture. They are limited to one DLT 2324 * per interface and one zone per interface. Thus every interface that 2325 * can be seen in a zone must be announced via an attach to bpf. For 2326 * shared instance zones, this means the ipnet driver needs to detect 2327 * when an address is added to an interface in a zone for the first 2328 * time (and also when the last address is removed.) 2329 */ 2330 static ipnetif_t * 2331 ipnetif_clone_create(ipnetif_t *ifp, zoneid_t zoneid) 2332 { 2333 uintptr_t key[2] = { zoneid, (uintptr_t)ifp->if_name }; 2334 ipnet_stack_t *ips = ifp->if_stackp; 2335 avl_index_t where = 0; 2336 ipnetif_t *newif; 2337 2338 mutex_enter(&ips->ips_avl_lock); 2339 newif = avl_find(&ips->ips_avl_by_shared, (void *)key, &where); 2340 if (newif != NULL) { 2341 ipnetif_refhold(newif); 2342 newif->if_sharecnt++; 2343 mutex_exit(&ips->ips_avl_lock); 2344 return (newif); 2345 } 2346 2347 newif = ipnet_alloc_if(ips); 2348 if (newif == NULL) { 2349 mutex_exit(&ips->ips_avl_lock); 2350 return (NULL); 2351 } 2352 2353 newif->if_refcnt = 1; 2354 newif->if_sharecnt = 1; 2355 newif->if_zoneid = zoneid; 2356 (void) strlcpy(newif->if_name, ifp->if_name, LIFNAMSIZ); 2357 newif->if_flags = ifp->if_flags & IPNETIF_LOOPBACK; 2358 newif->if_index = ifp->if_index; 2359 2360 avl_insert(&ips->ips_avl_by_shared, newif, where); 2361 mutex_exit(&ips->ips_avl_lock); 2362 2363 return (newif); 2364 } 2365 2366 static void 2367 ipnetif_clone_release(ipnetif_t *ipnetif) 2368 { 2369 boolean_t dofree = B_FALSE; 2370 boolean_t doremove = B_FALSE; 2371 ipnet_stack_t *ips = ipnetif->if_stackp; 2372 2373 mutex_enter(&ipnetif->if_reflock); 2374 ASSERT(ipnetif->if_refcnt > 0); 2375 if (--ipnetif->if_refcnt == 0) 2376 dofree = B_TRUE; 2377 ASSERT(ipnetif->if_sharecnt > 0); 2378 if (--ipnetif->if_sharecnt == 0) 2379 doremove = B_TRUE; 2380 mutex_exit(&ipnetif->if_reflock); 2381 if (doremove) { 2382 mutex_enter(&ips->ips_avl_lock); 2383 avl_remove(&ips->ips_avl_by_shared, ipnetif); 2384 mutex_exit(&ips->ips_avl_lock); 2385 } 2386 if (dofree) { 2387 ASSERT(ipnetif->if_sharecnt == 0); 2388 ipnetif_free(ipnetif); 2389 } 2390 }