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