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 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 #include <sys/param.h> 29 #include <sys/types.h> 30 #include <sys/systm.h> 31 #include <sys/stream.h> 32 #include <sys/strsubr.h> 33 #include <sys/pattr.h> 34 #include <sys/dlpi.h> 35 #include <sys/atomic.h> 36 #include <sys/sunddi.h> 37 #include <sys/socket.h> 38 #include <sys/neti.h> 39 #include <sys/sdt.h> 40 41 #include <netinet/in.h> 42 #include <inet/common.h> 43 #include <inet/mib2.h> 44 #include <inet/ip.h> 45 #include <inet/ip6.h> 46 #include <inet/ip_if.h> 47 #include <inet/ip_ire.h> 48 #include <inet/ip_impl.h> 49 #include <inet/ip_ndp.h> 50 #include <inet/ipclassifier.h> 51 #include <inet/ipp_common.h> 52 #include <inet/ip_ftable.h> 53 54 /* 55 * IPv4 netinfo entry point declarations. 56 */ 57 static int ip_getifname(phy_if_t, char *, const size_t, 58 netstack_t *); 59 static int ip_getmtu(phy_if_t, lif_if_t, netstack_t *); 60 static int ip_getpmtuenabled(netstack_t *); 61 static int ip_getlifaddr(phy_if_t, lif_if_t, size_t, 62 net_ifaddr_t [], void *, netstack_t *); 63 static phy_if_t ip_phygetnext(phy_if_t, netstack_t *); 64 static phy_if_t ip_phylookup(const char *, netstack_t *); 65 static lif_if_t ip_lifgetnext(phy_if_t, lif_if_t, netstack_t *); 66 static int ip_inject(inject_t, net_inject_t *, netstack_t *); 67 static phy_if_t ip_routeto(struct sockaddr *, netstack_t *); 68 static int ip_ispartialchecksum(mblk_t *); 69 static int ip_isvalidchecksum(mblk_t *); 70 71 static int ipv6_getifname(phy_if_t, char *, const size_t, 72 netstack_t *); 73 static int ipv6_getmtu(phy_if_t, lif_if_t, netstack_t *); 74 static int ipv6_getlifaddr(phy_if_t, lif_if_t, size_t, 75 net_ifaddr_t [], void *, netstack_t *); 76 static phy_if_t ipv6_phygetnext(phy_if_t, netstack_t *); 77 static phy_if_t ipv6_phylookup(const char *, netstack_t *); 78 static lif_if_t ipv6_lifgetnext(phy_if_t, lif_if_t, netstack_t *); 79 static int ipv6_inject(inject_t, net_inject_t *, netstack_t *); 80 static phy_if_t ipv6_routeto(struct sockaddr *, netstack_t *); 81 static int ipv6_isvalidchecksum(mblk_t *); 82 83 /* Netinfo private functions */ 84 static int ip_getifname_impl(phy_if_t, char *, 85 const size_t, boolean_t, ip_stack_t *); 86 static int ip_getmtu_impl(phy_if_t, lif_if_t, boolean_t, 87 ip_stack_t *); 88 static phy_if_t ip_phylookup_impl(const char *, boolean_t, 89 ip_stack_t *ipst); 90 static lif_if_t ip_lifgetnext_impl(phy_if_t, lif_if_t, boolean_t, 91 ip_stack_t *ipst); 92 static int ip_inject_impl(inject_t, net_inject_t *, boolean_t, 93 ip_stack_t *); 94 static int ip_getifaddr_type(sa_family_t, ipif_t *, lif_if_t, 95 void *); 96 static phy_if_t ip_routeto_impl(struct sockaddr *, ip_stack_t *); 97 static int ip_getlifaddr_impl(sa_family_t, phy_if_t, lif_if_t, 98 size_t, net_ifaddr_t [], struct sockaddr *, 99 ip_stack_t *); 100 static void ip_ni_queue_in_func(void *); 101 static void ip_ni_queue_out_func(void *); 102 static void ip_ni_queue_func_impl(injection_t *, boolean_t); 103 104 105 static net_info_t ipv4info = { 106 NETINFO_VERSION, 107 NHF_INET, 108 ip_getifname, 109 ip_getmtu, 110 ip_getpmtuenabled, 111 ip_getlifaddr, 112 ip_phygetnext, 113 ip_phylookup, 114 ip_lifgetnext, 115 ip_inject, 116 ip_routeto, 117 ip_ispartialchecksum, 118 ip_isvalidchecksum 119 }; 120 121 122 static net_info_t ipv6info = { 123 NETINFO_VERSION, 124 NHF_INET6, 125 ipv6_getifname, 126 ipv6_getmtu, 127 ip_getpmtuenabled, 128 ipv6_getlifaddr, 129 ipv6_phygetnext, 130 ipv6_phylookup, 131 ipv6_lifgetnext, 132 ipv6_inject, 133 ipv6_routeto, 134 ip_ispartialchecksum, 135 ipv6_isvalidchecksum 136 }; 137 138 /* 139 * The taskq eventq_queue_in is used to process the upside inject messages. 140 * The taskq eventq_queue_out is used to process the downside inject messages. 141 * The taskq eventq_queue_nic is used to process the nic event messages. 142 */ 143 static ddi_taskq_t *eventq_queue_in = NULL; 144 static ddi_taskq_t *eventq_queue_out = NULL; 145 ddi_taskq_t *eventq_queue_nic = NULL; 146 147 /* 148 * Initialize queues for inject. 149 */ 150 void 151 ip_net_g_init() 152 { 153 if (eventq_queue_out == NULL) { 154 eventq_queue_out = ddi_taskq_create(NULL, 155 "IP_INJECT_QUEUE_OUT", 1, TASKQ_DEFAULTPRI, 0); 156 157 if (eventq_queue_out == NULL) 158 cmn_err(CE_NOTE, "ipv4_net_init: " 159 "ddi_taskq_create failed for IP_INJECT_QUEUE_OUT"); 160 } 161 162 if (eventq_queue_in == NULL) { 163 eventq_queue_in = ddi_taskq_create(NULL, 164 "IP_INJECT_QUEUE_IN", 1, TASKQ_DEFAULTPRI, 0); 165 166 if (eventq_queue_in == NULL) 167 cmn_err(CE_NOTE, "ipv4_net_init: " 168 "ddi_taskq_create failed for IP_INJECT_QUEUE_IN"); 169 } 170 171 if (eventq_queue_nic == NULL) { 172 eventq_queue_nic = ddi_taskq_create(NULL, 173 "IP_NIC_EVENT_QUEUE", 1, TASKQ_DEFAULTPRI, 0); 174 175 if (eventq_queue_nic == NULL) 176 cmn_err(CE_NOTE, "ipv4_net_init: " 177 "ddi_taskq_create failed for IP_NIC_EVENT_QUEUE"); 178 } 179 } 180 181 /* 182 * Destroy inject queues 183 */ 184 void 185 ip_net_g_destroy() 186 { 187 if (eventq_queue_nic != NULL) { 188 ddi_taskq_destroy(eventq_queue_nic); 189 eventq_queue_nic = NULL; 190 } 191 192 if (eventq_queue_in != NULL) { 193 ddi_taskq_destroy(eventq_queue_in); 194 eventq_queue_in = NULL; 195 } 196 197 if (eventq_queue_out != NULL) { 198 ddi_taskq_destroy(eventq_queue_out); 199 eventq_queue_out = NULL; 200 } 201 } 202 203 /* 204 * Register IPv4 and IPv6 netinfo functions and initialize queues for inject. 205 */ 206 void 207 ip_net_init(ip_stack_t *ipst, netstack_t *ns) 208 { 209 210 ipst->ips_ipv4_net_data = net_register_impl(&ipv4info, ns); 211 ASSERT(ipst->ips_ipv4_net_data != NULL); 212 213 ipst->ips_ipv6_net_data = net_register_impl(&ipv6info, ns); 214 ASSERT(ipst->ips_ipv6_net_data != NULL); 215 } 216 217 218 /* 219 * Unregister IPv4 and IPv6 functions and inject queues 220 */ 221 void 222 ip_net_destroy(ip_stack_t *ipst) 223 { 224 if (ipst->ips_ipv4_net_data != NULL) { 225 if (net_unregister(ipst->ips_ipv4_net_data) == 0) 226 ipst->ips_ipv4_net_data = NULL; 227 } 228 229 if (ipst->ips_ipv6_net_data != NULL) { 230 if (net_unregister(ipst->ips_ipv6_net_data) == 0) 231 ipst->ips_ipv6_net_data = NULL; 232 } 233 } 234 235 /* 236 * Initialize IPv4 hooks family the event 237 */ 238 void 239 ipv4_hook_init(ip_stack_t *ipst) 240 { 241 HOOK_FAMILY_INIT(&ipst->ips_ipv4root, Hn_IPV4); 242 if (net_register_family(ipst->ips_ipv4_net_data, &ipst->ips_ipv4root) 243 != 0) { 244 cmn_err(CE_NOTE, "ipv4_hook_init: " 245 "net_register_family failed for ipv4"); 246 } 247 248 HOOK_EVENT_INIT(&ipst->ips_ip4_physical_in_event, NH_PHYSICAL_IN); 249 ipst->ips_ipv4firewall_physical_in = net_register_event( 250 ipst->ips_ipv4_net_data, &ipst->ips_ip4_physical_in_event); 251 if (ipst->ips_ipv4firewall_physical_in == NULL) { 252 cmn_err(CE_NOTE, "ipv4_hook_init: " 253 "net_register_event failed for ipv4/physical_in"); 254 } 255 256 HOOK_EVENT_INIT(&ipst->ips_ip4_physical_out_event, NH_PHYSICAL_OUT); 257 ipst->ips_ipv4firewall_physical_out = net_register_event( 258 ipst->ips_ipv4_net_data, &ipst->ips_ip4_physical_out_event); 259 if (ipst->ips_ipv4firewall_physical_out == NULL) { 260 cmn_err(CE_NOTE, "ipv4_hook_init: " 261 "net_register_event failed for ipv4/physical_out"); 262 } 263 264 HOOK_EVENT_INIT(&ipst->ips_ip4_forwarding_event, NH_FORWARDING); 265 ipst->ips_ipv4firewall_forwarding = net_register_event( 266 ipst->ips_ipv4_net_data, &ipst->ips_ip4_forwarding_event); 267 if (ipst->ips_ipv4firewall_forwarding == NULL) { 268 cmn_err(CE_NOTE, "ipv4_hook_init: " 269 "net_register_event failed for ipv4/forwarding"); 270 } 271 272 HOOK_EVENT_INIT(&ipst->ips_ip4_loopback_in_event, NH_LOOPBACK_IN); 273 ipst->ips_ipv4firewall_loopback_in = net_register_event( 274 ipst->ips_ipv4_net_data, &ipst->ips_ip4_loopback_in_event); 275 if (ipst->ips_ipv4firewall_loopback_in == NULL) { 276 cmn_err(CE_NOTE, "ipv4_hook_init: " 277 "net_register_event failed for ipv4/loopback_in"); 278 } 279 280 HOOK_EVENT_INIT(&ipst->ips_ip4_loopback_out_event, NH_LOOPBACK_OUT); 281 ipst->ips_ipv4firewall_loopback_out = net_register_event( 282 ipst->ips_ipv4_net_data, &ipst->ips_ip4_loopback_out_event); 283 if (ipst->ips_ipv4firewall_loopback_out == NULL) { 284 cmn_err(CE_NOTE, "ipv4_hook_init: " 285 "net_register_event failed for ipv4/loopback_out"); 286 } 287 288 HOOK_EVENT_INIT(&ipst->ips_ip4_nic_events, NH_NIC_EVENTS); 289 ipst->ips_ip4_nic_events.he_flags = HOOK_RDONLY; 290 ipst->ips_ipv4nicevents = net_register_event( 291 ipst->ips_ipv4_net_data, &ipst->ips_ip4_nic_events); 292 if (ipst->ips_ipv4nicevents == NULL) { 293 cmn_err(CE_NOTE, "ipv4_hook_init: " 294 "net_register_event failed for ipv4/nic_events"); 295 } 296 } 297 298 void 299 ipv4_hook_destroy(ip_stack_t *ipst) 300 { 301 if (ipst->ips_ipv4firewall_forwarding != NULL) { 302 if (net_unregister_event(ipst->ips_ipv4_net_data, 303 &ipst->ips_ip4_forwarding_event) == 0) 304 ipst->ips_ipv4firewall_forwarding = NULL; 305 } 306 307 if (ipst->ips_ipv4firewall_physical_in != NULL) { 308 if (net_unregister_event(ipst->ips_ipv4_net_data, 309 &ipst->ips_ip4_physical_in_event) == 0) 310 ipst->ips_ipv4firewall_physical_in = NULL; 311 } 312 313 if (ipst->ips_ipv4firewall_physical_out != NULL) { 314 if (net_unregister_event(ipst->ips_ipv4_net_data, 315 &ipst->ips_ip4_physical_out_event) == 0) 316 ipst->ips_ipv4firewall_physical_out = NULL; 317 } 318 319 if (ipst->ips_ipv4firewall_loopback_in != NULL) { 320 if (net_unregister_event(ipst->ips_ipv4_net_data, 321 &ipst->ips_ip4_loopback_in_event) == 0) 322 ipst->ips_ipv4firewall_loopback_in = NULL; 323 } 324 325 if (ipst->ips_ipv4firewall_loopback_out != NULL) { 326 if (net_unregister_event(ipst->ips_ipv4_net_data, 327 &ipst->ips_ip4_loopback_out_event) == 0) 328 ipst->ips_ipv4firewall_loopback_out = NULL; 329 } 330 331 if (ipst->ips_ipv4nicevents != NULL) { 332 if (net_unregister_event(ipst->ips_ipv4_net_data, 333 &ipst->ips_ip4_nic_events) == 0) 334 ipst->ips_ipv4nicevents = NULL; 335 } 336 337 (void) net_unregister_family(ipst->ips_ipv4_net_data, 338 &ipst->ips_ipv4root); 339 } 340 341 /* 342 * Initialize IPv6 hooks family and event 343 */ 344 void 345 ipv6_hook_init(ip_stack_t *ipst) 346 { 347 348 HOOK_FAMILY_INIT(&ipst->ips_ipv6root, Hn_IPV6); 349 if (net_register_family(ipst->ips_ipv6_net_data, &ipst->ips_ipv6root) 350 != 0) { 351 cmn_err(CE_NOTE, "ipv6_hook_init: " 352 "net_register_family failed for ipv6"); 353 } 354 355 HOOK_EVENT_INIT(&ipst->ips_ip6_physical_in_event, NH_PHYSICAL_IN); 356 ipst->ips_ipv6firewall_physical_in = net_register_event( 357 ipst->ips_ipv6_net_data, &ipst->ips_ip6_physical_in_event); 358 if (ipst->ips_ipv6firewall_physical_in == NULL) { 359 cmn_err(CE_NOTE, "ipv6_hook_init: " 360 "net_register_event failed for ipv6/physical_in"); 361 } 362 363 HOOK_EVENT_INIT(&ipst->ips_ip6_physical_out_event, NH_PHYSICAL_OUT); 364 ipst->ips_ipv6firewall_physical_out = net_register_event( 365 ipst->ips_ipv6_net_data, &ipst->ips_ip6_physical_out_event); 366 if (ipst->ips_ipv6firewall_physical_out == NULL) { 367 cmn_err(CE_NOTE, "ipv6_hook_init: " 368 "net_register_event failed for ipv6/physical_out"); 369 } 370 371 HOOK_EVENT_INIT(&ipst->ips_ip6_forwarding_event, NH_FORWARDING); 372 ipst->ips_ipv6firewall_forwarding = net_register_event( 373 ipst->ips_ipv6_net_data, &ipst->ips_ip6_forwarding_event); 374 if (ipst->ips_ipv6firewall_forwarding == NULL) { 375 cmn_err(CE_NOTE, "ipv6_hook_init: " 376 "net_register_event failed for ipv6/forwarding"); 377 } 378 379 HOOK_EVENT_INIT(&ipst->ips_ip6_loopback_in_event, NH_LOOPBACK_IN); 380 ipst->ips_ipv6firewall_loopback_in = net_register_event( 381 ipst->ips_ipv6_net_data, &ipst->ips_ip6_loopback_in_event); 382 if (ipst->ips_ipv6firewall_loopback_in == NULL) { 383 cmn_err(CE_NOTE, "ipv6_hook_init: " 384 "net_register_event failed for ipv6/loopback_in"); 385 } 386 387 HOOK_EVENT_INIT(&ipst->ips_ip6_loopback_out_event, NH_LOOPBACK_OUT); 388 ipst->ips_ipv6firewall_loopback_out = net_register_event( 389 ipst->ips_ipv6_net_data, &ipst->ips_ip6_loopback_out_event); 390 if (ipst->ips_ipv6firewall_loopback_out == NULL) { 391 cmn_err(CE_NOTE, "ipv6_hook_init: " 392 "net_register_event failed for ipv6/loopback_out"); 393 } 394 395 HOOK_EVENT_INIT(&ipst->ips_ip6_nic_events, NH_NIC_EVENTS); 396 ipst->ips_ip6_nic_events.he_flags = HOOK_RDONLY; 397 ipst->ips_ipv6nicevents = net_register_event( 398 ipst->ips_ipv6_net_data, &ipst->ips_ip6_nic_events); 399 if (ipst->ips_ipv6nicevents == NULL) { 400 cmn_err(CE_NOTE, "ipv6_hook_init: " 401 "net_register_event failed for ipv6/nic_events"); 402 } 403 } 404 405 void 406 ipv6_hook_destroy(ip_stack_t *ipst) 407 { 408 if (ipst->ips_ipv6firewall_forwarding != NULL) { 409 if (net_unregister_event(ipst->ips_ipv6_net_data, 410 &ipst->ips_ip6_forwarding_event) == 0) 411 ipst->ips_ipv6firewall_forwarding = NULL; 412 } 413 414 if (ipst->ips_ipv6firewall_physical_in != NULL) { 415 if (net_unregister_event(ipst->ips_ipv6_net_data, 416 &ipst->ips_ip6_physical_in_event) == 0) 417 ipst->ips_ipv6firewall_physical_in = NULL; 418 } 419 420 if (ipst->ips_ipv6firewall_physical_out != NULL) { 421 if (net_unregister_event(ipst->ips_ipv6_net_data, 422 &ipst->ips_ip6_physical_out_event) == 0) 423 ipst->ips_ipv6firewall_physical_out = NULL; 424 } 425 426 if (ipst->ips_ipv6firewall_loopback_in != NULL) { 427 if (net_unregister_event(ipst->ips_ipv6_net_data, 428 &ipst->ips_ip6_loopback_in_event) == 0) 429 ipst->ips_ipv6firewall_loopback_in = NULL; 430 } 431 432 if (ipst->ips_ipv6firewall_loopback_out != NULL) { 433 if (net_unregister_event(ipst->ips_ipv6_net_data, 434 &ipst->ips_ip6_loopback_out_event) == 0) 435 ipst->ips_ipv6firewall_loopback_out = NULL; 436 } 437 438 if (ipst->ips_ipv6nicevents != NULL) { 439 if (net_unregister_event(ipst->ips_ipv6_net_data, 440 &ipst->ips_ip6_nic_events) == 0) 441 ipst->ips_ipv6nicevents = NULL; 442 } 443 444 (void) net_unregister_family(ipst->ips_ipv6_net_data, 445 &ipst->ips_ipv6root); 446 } 447 448 /* 449 * Determine the name of an IPv4 interface 450 */ 451 static int 452 ip_getifname(phy_if_t phy_ifdata, char *buffer, const size_t buflen, 453 netstack_t *ns) 454 { 455 return (ip_getifname_impl(phy_ifdata, buffer, buflen, B_FALSE, 456 ns->netstack_ip)); 457 } 458 459 /* 460 * Determine the name of an IPv6 interface 461 */ 462 static int 463 ipv6_getifname(phy_if_t phy_ifdata, char *buffer, const size_t buflen, 464 netstack_t *ns) 465 { 466 return (ip_getifname_impl(phy_ifdata, buffer, buflen, B_TRUE, 467 ns->netstack_ip)); 468 } 469 470 /* 471 * Shared implementation to determine the name of a given network interface 472 */ 473 /* ARGSUSED */ 474 static int 475 ip_getifname_impl(phy_if_t phy_ifdata, 476 char *buffer, const size_t buflen, boolean_t isv6, ip_stack_t *ipst) 477 { 478 ill_t *ill; 479 char *name; 480 481 ASSERT(buffer != NULL); 482 483 ill = ill_lookup_on_ifindex((uint_t)phy_ifdata, isv6, NULL, NULL, 484 NULL, NULL, ipst); 485 if (ill != NULL) { 486 name = ill->ill_name; 487 } else { 488 /* Fallback to group names only if hook_emulation is set */ 489 if (ipst->ips_ipmp_hook_emulation) { 490 ill = ill_group_lookup_on_ifindex((uint_t)phy_ifdata, 491 isv6, ipst); 492 } 493 if (ill == NULL) 494 return (1); 495 name = ill->ill_phyint->phyint_groupname; 496 } 497 if (name != NULL) { 498 (void) strlcpy(buffer, name, buflen); 499 ill_refrele(ill); 500 return (0); 501 } else { 502 ill_refrele(ill); 503 return (1); 504 } 505 506 } 507 508 /* 509 * Determine the MTU of an IPv4 network interface 510 */ 511 static int 512 ip_getmtu(phy_if_t phy_ifdata, lif_if_t ifdata, netstack_t *ns) 513 { 514 ASSERT(ns != NULL); 515 return (ip_getmtu_impl(phy_ifdata, ifdata, B_FALSE, ns->netstack_ip)); 516 } 517 518 /* 519 * Determine the MTU of an IPv6 network interface 520 */ 521 static int 522 ipv6_getmtu(phy_if_t phy_ifdata, lif_if_t ifdata, netstack_t *ns) 523 { 524 ASSERT(ns != NULL); 525 return (ip_getmtu_impl(phy_ifdata, ifdata, B_TRUE, ns->netstack_ip)); 526 } 527 528 /* 529 * Shared implementation to determine the MTU of a network interface 530 * 531 * Note: this does not handle a non-zero ifdata when ipmp_hook_emulation is set. 532 * But IP Filter only uses a zero ifdata. 533 */ 534 /* ARGSUSED */ 535 static int 536 ip_getmtu_impl(phy_if_t phy_ifdata, lif_if_t ifdata, boolean_t isv6, 537 ip_stack_t *ipst) 538 { 539 lif_if_t ipifid; 540 ipif_t *ipif; 541 int mtu; 542 543 ipifid = UNMAP_IPIF_ID(ifdata); 544 545 ipif = ipif_getby_indexes((uint_t)phy_ifdata, (uint_t)ipifid, 546 isv6, ipst); 547 if (ipif == NULL) 548 return (0); 549 550 mtu = ipif->ipif_mtu; 551 ipif_refrele(ipif); 552 553 if (mtu == 0) { 554 ill_t *ill; 555 556 if ((ill = ill_lookup_on_ifindex((uint_t)phy_ifdata, isv6, 557 NULL, NULL, NULL, NULL, ipst)) == NULL) { 558 /* 559 * Fallback to group names only if hook_emulation 560 * is set 561 */ 562 if (ipst->ips_ipmp_hook_emulation) { 563 ill = ill_group_lookup_on_ifindex( 564 (uint_t)phy_ifdata, isv6, ipst); 565 } 566 if (ill == NULL) 567 return (0); 568 } 569 mtu = ill->ill_max_frag; 570 ill_refrele(ill); 571 } 572 573 return (mtu); 574 } 575 576 /* 577 * Determine if path MTU discovery is enabled for IP 578 */ 579 static int 580 ip_getpmtuenabled(netstack_t *ns) 581 { 582 ASSERT(ns != NULL); 583 return ((ns->netstack_ip)->ips_ip_path_mtu_discovery); 584 } 585 586 /* 587 * Get next interface from the current list of IPv4 physical network interfaces 588 * 589 * Note: this does not handle the case when ipmp_hook_emulation is set. 590 * But IP Filter does not use this function. 591 */ 592 static phy_if_t 593 ip_phygetnext(phy_if_t phy_ifdata, netstack_t *ns) 594 { 595 ASSERT(ns != NULL); 596 return (ill_get_next_ifindex(phy_ifdata, B_FALSE, ns->netstack_ip)); 597 } 598 599 /* 600 * Get next interface from the current list of IPv6 physical network interfaces 601 */ 602 static phy_if_t 603 ipv6_phygetnext(phy_if_t phy_ifdata, netstack_t *ns) 604 { 605 ASSERT(ns != NULL); 606 return (ill_get_next_ifindex(phy_ifdata, B_TRUE, ns->netstack_ip)); 607 } 608 609 /* 610 * Determine if a network interface name exists for IPv4 611 */ 612 static phy_if_t 613 ip_phylookup(const char *name, netstack_t *ns) 614 { 615 ASSERT(ns != NULL); 616 return (ip_phylookup_impl(name, B_FALSE, ns->netstack_ip)); 617 } 618 619 /* 620 * Determine if a network interface name exists for IPv6 621 */ 622 static phy_if_t 623 ipv6_phylookup(const char *name, netstack_t *ns) 624 { 625 ASSERT(ns != NULL); 626 return (ip_phylookup_impl(name, B_TRUE, ns->netstack_ip)); 627 } 628 629 /* 630 * Implement looking up an ill_t based on the name supplied and matching 631 * it up with either IPv4 or IPv6. ill_get_ifindex_by_name() is not used 632 * because it does not match on the address family in addition to the name. 633 */ 634 static phy_if_t 635 ip_phylookup_impl(const char *name, boolean_t isv6, ip_stack_t *ipst) 636 { 637 phy_if_t phy; 638 ill_t *ill; 639 640 ill = ill_lookup_on_name((char *)name, B_FALSE, isv6, NULL, NULL, 641 NULL, NULL, NULL, ipst); 642 643 /* Fallback to group names only if hook_emulation is set */ 644 if (ill == NULL && ipst->ips_ipmp_hook_emulation) { 645 ill = ill_group_lookup_on_name((char *)name, isv6, ipst); 646 } 647 if (ill == NULL) 648 return (0); 649 650 phy = ill->ill_phyint->phyint_hook_ifindex; 651 652 ill_refrele(ill); 653 654 return (phy); 655 } 656 657 /* 658 * Get next interface from the current list of IPv4 logical network interfaces 659 */ 660 static lif_if_t 661 ip_lifgetnext(phy_if_t phy_ifdata, lif_if_t ifdata, netstack_t *ns) 662 { 663 ASSERT(ns != NULL); 664 return (ip_lifgetnext_impl(phy_ifdata, ifdata, B_FALSE, 665 ns->netstack_ip)); 666 } 667 668 /* 669 * Get next interface from the current list of IPv6 logical network interfaces 670 */ 671 static lif_if_t 672 ipv6_lifgetnext(phy_if_t phy_ifdata, lif_if_t ifdata, netstack_t *ns) 673 { 674 ASSERT(ns != NULL); 675 return (ip_lifgetnext_impl(phy_ifdata, ifdata, B_TRUE, 676 ns->netstack_ip)); 677 } 678 679 /* 680 * Shared implementation to get next interface from the current list of 681 * logical network interfaces 682 * 683 * Note: this does not handle the case when ipmp_hook_emulation is set. 684 * But IP Filter does not use this function. 685 */ 686 static lif_if_t 687 ip_lifgetnext_impl(phy_if_t phy_ifdata, lif_if_t ifdata, boolean_t isv6, 688 ip_stack_t *ipst) 689 { 690 lif_if_t newidx, oldidx; 691 boolean_t nextok; 692 ipif_t *ipif; 693 ill_t *ill; 694 695 ill = ill_lookup_on_ifindex(phy_ifdata, isv6, NULL, NULL, 696 NULL, NULL, ipst); 697 if (ill == NULL) 698 return (0); 699 700 if (ifdata != 0) { 701 oldidx = UNMAP_IPIF_ID(ifdata); 702 nextok = B_FALSE; 703 } else { 704 oldidx = 0; 705 nextok = B_TRUE; 706 } 707 708 mutex_enter(&ill->ill_lock); 709 if (ill->ill_state_flags & ILL_CONDEMNED) { 710 mutex_exit(&ill->ill_lock); 711 ill_refrele(ill); 712 return (0); 713 } 714 715 /* 716 * It's safe to iterate the ill_ipif list when holding an ill_lock. 717 * And it's also safe to access ipif_id without ipif refhold. 718 * See ipif_get_id(). 719 */ 720 for (ipif = ill->ill_ipif; ipif != NULL; ipif = ipif->ipif_next) { 721 if (!IPIF_CAN_LOOKUP(ipif)) 722 continue; 723 if (nextok) { 724 ipif_refhold_locked(ipif); 725 break; 726 } else if (oldidx == ipif->ipif_id) { 727 nextok = B_TRUE; 728 } 729 } 730 731 mutex_exit(&ill->ill_lock); 732 ill_refrele(ill); 733 734 if (ipif == NULL) 735 return (0); 736 737 newidx = ipif->ipif_id; 738 ipif_refrele(ipif); 739 740 return (MAP_IPIF_ID(newidx)); 741 } 742 743 /* 744 * Inject an IPv4 packet to or from an interface 745 */ 746 static int 747 ip_inject(inject_t style, net_inject_t *packet, netstack_t *ns) 748 { 749 ASSERT(ns != NULL); 750 return (ip_inject_impl(style, packet, B_FALSE, ns->netstack_ip)); 751 } 752 753 754 /* 755 * Inject an IPv6 packet to or from an interface 756 */ 757 static int 758 ipv6_inject(inject_t style, net_inject_t *packet, netstack_t *ns) 759 { 760 ASSERT(ns != NULL); 761 return (ip_inject_impl(style, packet, B_TRUE, ns->netstack_ip)); 762 } 763 764 /* 765 * Shared implementation to inject a packet to or from an interface 766 * Return value: 767 * 0: successful 768 * -1: memory allocation failed 769 * 1: other errors 770 */ 771 static int 772 ip_inject_impl(inject_t style, net_inject_t *packet, boolean_t isv6, 773 ip_stack_t *ipst) 774 { 775 struct sockaddr_in6 *sin6; 776 ddi_taskq_t *tq = NULL; 777 void (* func)(void *); 778 injection_t *inject; 779 ip6_t *ip6h; 780 ire_t *ire; 781 mblk_t *mp; 782 783 ASSERT(packet != NULL); 784 ASSERT(packet->ni_packet != NULL); 785 ASSERT(packet->ni_packet->b_datap->db_type == M_DATA); 786 787 switch (style) { 788 case NI_QUEUE_IN: 789 inject = kmem_alloc(sizeof (*inject), KM_NOSLEEP); 790 if (inject == NULL) 791 return (-1); 792 inject->inj_data = *packet; 793 inject->inj_isv6 = isv6; 794 /* 795 * deliver up into the kernel, immitating its reception by a 796 * network interface, add to list and schedule timeout 797 */ 798 func = ip_ni_queue_in_func; 799 tq = eventq_queue_in; 800 break; 801 802 case NI_QUEUE_OUT: 803 inject = kmem_alloc(sizeof (*inject), KM_NOSLEEP); 804 if (inject == NULL) 805 return (-1); 806 inject->inj_data = *packet; 807 inject->inj_isv6 = isv6; 808 /* 809 * deliver out of the kernel, as if it were being sent via a 810 * raw socket so that IPFilter will see it again, add to list 811 * and schedule timeout 812 */ 813 func = ip_ni_queue_out_func; 814 tq = eventq_queue_out; 815 break; 816 817 case NI_DIRECT_OUT: 818 /* 819 * Note: 820 * For IPv4, the code path below will be greatly simplified 821 * with the delivery of surya - it will become a single 822 * function call to X. A follow on project is aimed to 823 * provide similar functionality for IPv6. 824 */ 825 mp = packet->ni_packet; 826 827 if (!isv6) { 828 struct sockaddr *sock; 829 830 sock = (struct sockaddr *)&packet->ni_addr; 831 /* 832 * ipfil_sendpkt was provided by surya to ease the 833 * problems associated with sending out a packet. 834 * Currently this function only supports IPv4. 835 */ 836 switch (ipfil_sendpkt(sock, mp, packet->ni_physical, 837 netstackid_to_zoneid( 838 ipst->ips_netstack->netstack_stackid))) { 839 case 0 : 840 case EINPROGRESS: 841 return (0); 842 case ECOMM : 843 case ENONET : 844 return (1); 845 default : 846 return (1); 847 } 848 /* NOTREACHED */ 849 850 } 851 852 ip6h = (ip6_t *)mp->b_rptr; 853 sin6 = (struct sockaddr_in6 *)&packet->ni_addr; 854 ASSERT(sin6->sin6_family == AF_INET6); 855 856 ire = ire_route_lookup_v6(&sin6->sin6_addr, 0, 0, 0, 857 NULL, NULL, ALL_ZONES, NULL, 858 MATCH_IRE_DSTONLY|MATCH_IRE_DEFAULT|MATCH_IRE_RECURSIVE, 859 ipst); 860 861 if (ire == NULL) { 862 ip2dbg(("ip_inject: ire_cache_lookup failed\n")); 863 freemsg(mp); 864 return (1); 865 } 866 867 if (ire->ire_stq == NULL) { 868 /* Send to loopback destination. */ 869 if (ire->ire_rfq == NULL) { 870 ip2dbg(("ip_inject: bad nexthop\n")); 871 ire_refrele(ire); 872 freemsg(mp); 873 return (1); 874 } 875 DTRACE_IP7(send, mblk_t *, mp, conn_t *, NULL, 876 void_ip_t *, ip6h, __dtrace_ipsr_ill_t *, 877 ire->ire_ipif->ipif_ill, ipha_t *, NULL, ip6_t *, 878 ip6h, int, 1); 879 ip_wput_local_v6(ire->ire_rfq, 880 ire->ire_ipif->ipif_ill, ip6h, mp, ire, 0); 881 ire_refrele(ire); 882 return (0); 883 } 884 885 mp->b_queue = ire->ire_stq; 886 887 if (ire->ire_nce == NULL || 888 ire->ire_nce->nce_fp_mp == NULL && 889 ire->ire_nce->nce_res_mp == NULL) { 890 ip_newroute_v6(ire->ire_stq, mp, 891 &sin6->sin6_addr, NULL, NULL, ALL_ZONES, ipst); 892 893 ire_refrele(ire); 894 return (0); 895 } else { 896 /* prepend L2 header for IPv6 packets. */ 897 mblk_t *llmp; 898 899 /* 900 * Lock IREs, see 6420438 901 */ 902 mutex_enter(&ire->ire_lock); 903 llmp = ire->ire_nce->nce_fp_mp ? 904 ire->ire_nce->nce_fp_mp : 905 ire->ire_nce->nce_res_mp; 906 907 if ((mp = dupb(llmp)) == NULL && 908 (mp = copyb(llmp)) == NULL) { 909 ip2dbg(("ip_inject: llhdr failed\n")); 910 mutex_exit(&ire->ire_lock); 911 ire_refrele(ire); 912 freemsg(mp); 913 return (1); 914 } 915 mutex_exit(&ire->ire_lock); 916 linkb(mp, packet->ni_packet); 917 } 918 919 mp->b_queue = ire->ire_stq; 920 921 break; 922 default: 923 freemsg(packet->ni_packet); 924 return (1); 925 } 926 927 if (tq) { 928 inject->inj_ptr = ipst; 929 if (ddi_taskq_dispatch(tq, func, (void *)inject, 930 DDI_SLEEP) == DDI_FAILURE) { 931 ip2dbg(("ip_inject: ddi_taskq_dispatch failed\n")); 932 freemsg(packet->ni_packet); 933 return (1); 934 } 935 } else { 936 putnext(ire->ire_stq, mp); 937 ire_refrele(ire); 938 } 939 940 return (0); 941 } 942 943 /* 944 * Find the interface used for traffic to a given IPv4 address 945 */ 946 static phy_if_t 947 ip_routeto(struct sockaddr *address, netstack_t *ns) 948 { 949 ASSERT(address != NULL); 950 ASSERT(ns != NULL); 951 952 if (address->sa_family != AF_INET) 953 return (0); 954 return (ip_routeto_impl(address, ns->netstack_ip)); 955 } 956 957 /* 958 * Find the interface used for traffic to a given IPv6 address 959 */ 960 static phy_if_t 961 ipv6_routeto(struct sockaddr *address, netstack_t *ns) 962 { 963 ASSERT(address != NULL); 964 ASSERT(ns != NULL); 965 966 if (address->sa_family != AF_INET6) 967 return (0); 968 return (ip_routeto_impl(address, ns->netstack_ip)); 969 } 970 971 972 /* 973 * Find the interface used for traffic to an address 974 */ 975 static phy_if_t 976 ip_routeto_impl(struct sockaddr *address, ip_stack_t *ipst) 977 { 978 ire_t *ire; 979 ill_t *ill; 980 phy_if_t phy_if; 981 982 if (address->sa_family == AF_INET6) { 983 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)address; 984 ire = ire_route_lookup_v6(&sin6->sin6_addr, NULL, 985 0, 0, NULL, NULL, ALL_ZONES, NULL, 986 MATCH_IRE_DSTONLY|MATCH_IRE_DEFAULT|MATCH_IRE_RECURSIVE, 987 ipst); 988 } else { 989 struct sockaddr_in *sin = (struct sockaddr_in *)address; 990 ire = ire_route_lookup(sin->sin_addr.s_addr, 0, 991 0, 0, NULL, NULL, ALL_ZONES, NULL, 992 MATCH_IRE_DSTONLY|MATCH_IRE_DEFAULT|MATCH_IRE_RECURSIVE, 993 ipst); 994 } 995 996 if (ire == NULL) 997 return (0); 998 999 ill = ire_to_ill(ire); 1000 if (ill == NULL) { 1001 ire_refrele(ire); 1002 return (0); 1003 } 1004 1005 ASSERT(ill != NULL); 1006 phy_if = (phy_if_t)ill->ill_phyint->phyint_hook_ifindex; 1007 ire_refrele(ire); 1008 1009 return (phy_if); 1010 } 1011 1012 /* 1013 * Determine if checksumming is being used for the given packet. 1014 * 1015 * Return value: 1016 * NET_HCK_NONE: full checksum recalculation is required 1017 * NET_HCK_L3_FULL: full layer 3 checksum 1018 * NET_HCK_L4_FULL: full layer 4 checksum 1019 * NET_HCK_L4_PART: partial layer 4 checksum 1020 */ 1021 static int 1022 ip_ispartialchecksum(mblk_t *mp) 1023 { 1024 int ret = 0; 1025 1026 ASSERT(mp != NULL); 1027 1028 if ((DB_CKSUMFLAGS(mp) & HCK_FULLCKSUM) != 0) { 1029 ret |= (int)NET_HCK_L4_FULL; 1030 if ((DB_CKSUMFLAGS(mp) & HCK_IPV4_HDRCKSUM) != 0) 1031 ret |= (int)NET_HCK_L3_FULL; 1032 } 1033 if ((DB_CKSUMFLAGS(mp) & HCK_PARTIALCKSUM) != 0) { 1034 ret |= (int)NET_HCK_L4_PART; 1035 if ((DB_CKSUMFLAGS(mp) & HCK_IPV4_HDRCKSUM) != 0) 1036 ret |= (int)NET_HCK_L3_FULL; 1037 } 1038 1039 return (ret); 1040 } 1041 1042 /* 1043 * Return true or false, indicating whether the network and transport 1044 * headers are correct. Use the capabilities flags and flags set in the 1045 * dblk_t to determine whether or not the checksum is valid. 1046 * 1047 * Return: 1048 * 0: the checksum was incorrect 1049 * 1: the original checksum was correct 1050 */ 1051 static int 1052 ip_isvalidchecksum(mblk_t *mp) 1053 { 1054 unsigned char *wptr; 1055 ipha_t *ipha = (ipha_t *)mp->b_rptr; 1056 int hlen; 1057 int ret; 1058 1059 ASSERT(mp != NULL); 1060 1061 if (dohwcksum && 1062 DB_CKSUM16(mp) != 0xFFFF && 1063 (DB_CKSUMFLAGS(mp) & HCK_FULLCKSUM) && 1064 (DB_CKSUMFLAGS(mp) & HCK_FULLCKSUM_OK) && 1065 (DB_CKSUMFLAGS(mp) & HCK_IPV4_HDRCKSUM)) 1066 return (1); 1067 1068 hlen = (ipha->ipha_version_and_hdr_length & 0x0F) << 2; 1069 1070 /* 1071 * Check that the mblk being passed in has enough data in it 1072 * before blindly checking ip_cksum. 1073 */ 1074 if (msgdsize(mp) < hlen) 1075 return (0); 1076 1077 if (mp->b_wptr < mp->b_rptr + hlen) { 1078 if (pullupmsg(mp, hlen) == 0) 1079 return (0); 1080 wptr = mp->b_wptr; 1081 } else { 1082 wptr = mp->b_wptr; 1083 mp->b_wptr = mp->b_rptr + hlen; 1084 } 1085 1086 if (ipha->ipha_hdr_checksum == ip_cksum(mp, 0, ipha->ipha_hdr_checksum)) 1087 ret = 1; 1088 else 1089 ret = 0; 1090 mp->b_wptr = wptr; 1091 1092 return (ret); 1093 } 1094 1095 /* 1096 * Unsupported with IPv6 1097 */ 1098 /*ARGSUSED*/ 1099 static int 1100 ipv6_isvalidchecksum(mblk_t *mp) 1101 { 1102 return (-1); 1103 } 1104 1105 /* 1106 * Determine the network addresses for an IPv4 interface 1107 */ 1108 static int 1109 ip_getlifaddr(phy_if_t phy_ifdata, lif_if_t ifdata, size_t nelem, 1110 net_ifaddr_t type[], void *storage, netstack_t *ns) 1111 { 1112 ASSERT(ns != NULL); 1113 return (ip_getlifaddr_impl(AF_INET, phy_ifdata, ifdata, 1114 nelem, type, storage, ns->netstack_ip)); 1115 } 1116 1117 /* 1118 * Determine the network addresses for an IPv6 interface 1119 */ 1120 static int 1121 ipv6_getlifaddr(phy_if_t phy_ifdata, lif_if_t ifdata, size_t nelem, 1122 net_ifaddr_t type[], void *storage, netstack_t *ns) 1123 { 1124 ASSERT(ns != NULL); 1125 return (ip_getlifaddr_impl(AF_INET6, phy_ifdata, ifdata, 1126 nelem, type, storage, ns->netstack_ip)); 1127 } 1128 1129 /* 1130 * Shared implementation to determine the network addresses for an interface 1131 * 1132 * Note: this does not handle a non-zero ifdata when ipmp_hook_emulation is set. 1133 * But IP Filter only uses a zero ifdata. 1134 */ 1135 /* ARGSUSED */ 1136 static int 1137 ip_getlifaddr_impl(sa_family_t family, phy_if_t phy_ifdata, 1138 lif_if_t ifdata, size_t nelem, net_ifaddr_t type[], 1139 struct sockaddr *storage, ip_stack_t *ipst) 1140 { 1141 struct sockaddr_in6 *sin6; 1142 struct sockaddr_in *sin; 1143 lif_if_t ipifid; 1144 ipif_t *ipif; 1145 int i; 1146 1147 ASSERT(type != NULL); 1148 ASSERT(storage != NULL); 1149 1150 ipifid = UNMAP_IPIF_ID(ifdata); 1151 1152 if (family == AF_INET) { 1153 if ((ipif = ipif_getby_indexes((uint_t)phy_ifdata, 1154 (uint_t)ipifid, B_FALSE, ipst)) == NULL) 1155 return (1); 1156 1157 sin = (struct sockaddr_in *)storage; 1158 for (i = 0; i < nelem; i++, sin++) { 1159 if (ip_getifaddr_type(AF_INET, ipif, type[i], 1160 &sin->sin_addr) < 0) { 1161 ip2dbg(("ip_getlifaddr_impl failed type %d\n", 1162 type[i])); 1163 ipif_refrele(ipif); 1164 return (1); 1165 } 1166 } 1167 } else { 1168 if ((ipif = ipif_getby_indexes((uint_t)phy_ifdata, 1169 (uint_t)ipifid, B_TRUE, ipst)) == NULL) 1170 return (1); 1171 1172 sin6 = (struct sockaddr_in6 *)storage; 1173 for (i = 0; i < nelem; i++, sin6++) { 1174 if (ip_getifaddr_type(AF_INET6, ipif, type[i], 1175 &sin6->sin6_addr) < 0) { 1176 ip2dbg(("ip_getlifaddr_impl failed type %d\n", 1177 type[i])); 1178 ipif_refrele(ipif); 1179 return (1); 1180 } 1181 } 1182 } 1183 ipif_refrele(ipif); 1184 return (0); 1185 } 1186 1187 /* 1188 * ip_getlifaddr private function 1189 */ 1190 static int 1191 ip_getifaddr_type(sa_family_t family, ipif_t *ill_ipif, 1192 lif_if_t type, void *storage) 1193 { 1194 void *src_addr; 1195 int mem_size; 1196 1197 ASSERT(ill_ipif != NULL); 1198 ASSERT(storage != NULL); 1199 1200 if (family == AF_INET) { 1201 mem_size = sizeof (struct in_addr); 1202 1203 switch (type) { 1204 case NA_ADDRESS: 1205 src_addr = &(ill_ipif->ipif_lcl_addr); 1206 break; 1207 case NA_PEER: 1208 src_addr = &(ill_ipif->ipif_pp_dst_addr); 1209 break; 1210 case NA_BROADCAST: 1211 src_addr = &(ill_ipif->ipif_brd_addr); 1212 break; 1213 case NA_NETMASK: 1214 src_addr = &(ill_ipif->ipif_net_mask); 1215 break; 1216 default: 1217 return (-1); 1218 /*NOTREACHED*/ 1219 } 1220 } else { 1221 mem_size = sizeof (struct in6_addr); 1222 1223 switch (type) { 1224 case NA_ADDRESS: 1225 src_addr = &(ill_ipif->ipif_v6lcl_addr); 1226 break; 1227 case NA_PEER: 1228 src_addr = &(ill_ipif->ipif_v6pp_dst_addr); 1229 break; 1230 case NA_BROADCAST: 1231 src_addr = &(ill_ipif->ipif_v6brd_addr); 1232 break; 1233 case NA_NETMASK: 1234 src_addr = &(ill_ipif->ipif_v6net_mask); 1235 break; 1236 default: 1237 return (-1); 1238 /*NOTREACHED*/ 1239 } 1240 } 1241 1242 (void) memcpy(storage, src_addr, mem_size); 1243 return (1); 1244 } 1245 1246 /* 1247 * Deliver packet up into the kernel, immitating its reception by a 1248 * network interface. 1249 */ 1250 static void 1251 ip_ni_queue_in_func(void *inject) 1252 { 1253 ip_ni_queue_func_impl(inject, B_FALSE); 1254 } 1255 1256 /* 1257 * Deliver out of the kernel, as if it were being sent via a 1258 * raw socket so that IPFilter will see it again. 1259 */ 1260 static void 1261 ip_ni_queue_out_func(void *inject) 1262 { 1263 ip_ni_queue_func_impl(inject, B_TRUE); 1264 } 1265 1266 /* 1267 * Shared implementation for inject via ip_output and ip_input 1268 */ 1269 static void 1270 ip_ni_queue_func_impl(injection_t *inject, boolean_t out) 1271 { 1272 net_inject_t *packet; 1273 conn_t *conn; 1274 ill_t *ill; 1275 ip_stack_t *ipst = (ip_stack_t *)inject->inj_ptr; 1276 1277 ASSERT(inject != NULL); 1278 packet = &inject->inj_data; 1279 ASSERT(packet->ni_packet != NULL); 1280 1281 ill = ill_lookup_on_ifindex((uint_t)packet->ni_physical, 1282 B_FALSE, NULL, NULL, NULL, NULL, ipst); 1283 1284 /* Fallback to group names only if hook_emulation is set */ 1285 if (ill == NULL && ipst->ips_ipmp_hook_emulation) { 1286 ill = ill_group_lookup_on_ifindex((uint_t)packet->ni_physical, 1287 B_FALSE, ipst); 1288 } 1289 if (ill == NULL) { 1290 kmem_free(inject, sizeof (*inject)); 1291 return; 1292 } 1293 1294 if (out == 0) { 1295 if (inject->inj_isv6) { 1296 ip_rput_v6(ill->ill_rq, packet->ni_packet); 1297 } else { 1298 ip_input(ill, NULL, packet->ni_packet, 0); 1299 } 1300 kmem_free(inject, sizeof (*inject)); 1301 ill_refrele(ill); 1302 return; 1303 } 1304 1305 /* 1306 * Even though ipcl_conn_create requests that it be passed 1307 * a different value for "TCP", in this case there may not 1308 * be a TCP connection backing the packet and more than 1309 * likely, non-TCP packets will go here too. 1310 */ 1311 conn = ipcl_conn_create(IPCL_IPCCONN, KM_NOSLEEP, ipst->ips_netstack); 1312 if (conn != NULL) { 1313 if (inject->inj_isv6) { 1314 conn->conn_flags |= IPCL_ISV6; 1315 conn->conn_af_isv6 = B_TRUE; 1316 conn->conn_src_preferences = IPV6_PREFER_SRC_DEFAULT; 1317 conn->conn_multicast_loop = IP_DEFAULT_MULTICAST_LOOP; 1318 ip_output_v6(conn, packet->ni_packet, ill->ill_wq, 1319 IP_WPUT); 1320 } else { 1321 conn->conn_af_isv6 = B_FALSE; 1322 conn->conn_pkt_isv6 = B_FALSE; 1323 conn->conn_multicast_loop = IP_DEFAULT_MULTICAST_LOOP; 1324 ip_output(conn, packet->ni_packet, ill->ill_wq, 1325 IP_WPUT); 1326 } 1327 1328 CONN_DEC_REF(conn); 1329 } 1330 1331 kmem_free(inject, sizeof (*inject)); 1332 ill_refrele(ill); 1333 } 1334 1335 /* 1336 * taskq function for nic events. 1337 */ 1338 void 1339 ip_ne_queue_func(void *arg) 1340 { 1341 hook_event_int_t *hr; 1342 hook_nic_event_t *info = (hook_nic_event_t *)arg; 1343 netstack_t *ns = info->hne_family->netd_netstack; 1344 ip_stack_t *ipst = ns->netstack_ip; 1345 1346 hr = (info->hne_family == ipst->ips_ipv6_net_data) ? 1347 ipst->ips_ipv6nicevents : ipst->ips_ipv4nicevents; 1348 (void) hook_run(hr, (hook_data_t)info, ns); 1349 1350 if (info->hne_data != NULL) 1351 kmem_free(info->hne_data, info->hne_datalen); 1352 kmem_free(arg, sizeof (hook_nic_event_t)); 1353 } 1354 1355 /* 1356 * Temporary function to support IPMP emulation for IP Filter. 1357 * Lookup an ill based on the ifindex assigned to the group. 1358 * Skips unusable ones i.e. where any of these flags are set: 1359 * (PHYI_FAILED|PHYI_OFFLINE|PHYI_INACTIVE) 1360 */ 1361 ill_t * 1362 ill_group_lookup_on_ifindex(uint_t index, boolean_t isv6, ip_stack_t *ipst) 1363 { 1364 ill_t *ill; 1365 phyint_t *phyi; 1366 1367 rw_enter(&ipst->ips_ill_g_lock, RW_READER); 1368 phyi = phyint_lookup_group_ifindex(index, ipst); 1369 if (phyi != NULL) { 1370 ill = isv6 ? phyi->phyint_illv6: phyi->phyint_illv4; 1371 if (ill != NULL) { 1372 mutex_enter(&ill->ill_lock); 1373 if (ILL_CAN_LOOKUP(ill)) { 1374 ill_refhold_locked(ill); 1375 mutex_exit(&ill->ill_lock); 1376 rw_exit(&ipst->ips_ill_g_lock); 1377 return (ill); 1378 } 1379 mutex_exit(&ill->ill_lock); 1380 } 1381 } 1382 rw_exit(&ipst->ips_ill_g_lock); 1383 return (NULL); 1384 } 1385 1386 /* 1387 * Temporary function to support IPMP emulation for IP Filter. 1388 * Lookup an ill based on the group name. 1389 * Skips unusable ones i.e. where any of these flags are set: 1390 * (PHYI_FAILED|PHYI_OFFLINE|PHYI_INACTIVE) 1391 */ 1392 ill_t * 1393 ill_group_lookup_on_name(char *name, boolean_t isv6, ip_stack_t *ipst) 1394 { 1395 ill_t *ill; 1396 phyint_t *phyi; 1397 1398 rw_enter(&ipst->ips_ill_g_lock, RW_READER); 1399 phyi = phyint_lookup_group(name, B_TRUE, ipst); 1400 if (phyi != NULL) { 1401 ill = isv6 ? phyi->phyint_illv6: phyi->phyint_illv4; 1402 if (ill != NULL) { 1403 mutex_enter(&ill->ill_lock); 1404 if (ILL_CAN_LOOKUP(ill)) { 1405 ill_refhold_locked(ill); 1406 mutex_exit(&ill->ill_lock); 1407 rw_exit(&ipst->ips_ill_g_lock); 1408 return (ill); 1409 } 1410 mutex_exit(&ill->ill_lock); 1411 } 1412 } 1413 rw_exit(&ipst->ips_ill_g_lock); 1414 return (NULL); 1415 } 1416