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 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #include <sys/param.h> 27 #include <sys/types.h> 28 #include <sys/systm.h> 29 #include <sys/stream.h> 30 #include <sys/strsubr.h> 31 #include <sys/pattr.h> 32 #include <sys/dlpi.h> 33 #include <sys/atomic.h> 34 #include <sys/sunddi.h> 35 #include <sys/socket.h> 36 #include <sys/neti.h> 37 #include <sys/sdt.h> 38 #include <sys/cmn_err.h> 39 40 #include <netinet/in.h> 41 #include <inet/ipsec_impl.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(net_handle_t, phy_if_t, char *, 58 const size_t); 59 static int ip_getmtu(net_handle_t, phy_if_t, lif_if_t); 60 static int ip_getpmtuenabled(net_handle_t); 61 static int ip_getlifaddr(net_handle_t, phy_if_t, lif_if_t, 62 size_t, net_ifaddr_t [], void *); 63 static int ip_getlifzone(net_handle_t, phy_if_t, lif_if_t, 64 zoneid_t *); 65 static int ip_getlifflags(net_handle_t, phy_if_t, lif_if_t, 66 uint64_t *); 67 static phy_if_t ip_phygetnext(net_handle_t, phy_if_t); 68 static phy_if_t ip_phylookup(net_handle_t, const char *); 69 static lif_if_t ip_lifgetnext(net_handle_t, phy_if_t, lif_if_t); 70 static int ip_inject(net_handle_t, inject_t, net_inject_t *); 71 static phy_if_t ip_routeto(net_handle_t, struct sockaddr *, 72 struct sockaddr *); 73 static int ip_ispartialchecksum(net_handle_t, mblk_t *); 74 static int ip_isvalidchecksum(net_handle_t, mblk_t *); 75 76 static int ipv6_getifname(net_handle_t, phy_if_t, char *, 77 const size_t); 78 static int ipv6_getmtu(net_handle_t, phy_if_t, lif_if_t); 79 static int ipv6_getlifaddr(net_handle_t, phy_if_t, lif_if_t, 80 size_t, net_ifaddr_t [], void *); 81 static int ipv6_getlifzone(net_handle_t, phy_if_t, lif_if_t, 82 zoneid_t *); 83 static int ipv6_getlifflags(net_handle_t, phy_if_t, lif_if_t, 84 uint64_t *); 85 static phy_if_t ipv6_phygetnext(net_handle_t, phy_if_t); 86 static phy_if_t ipv6_phylookup(net_handle_t, const char *); 87 static lif_if_t ipv6_lifgetnext(net_handle_t, phy_if_t, lif_if_t); 88 static int ipv6_inject(net_handle_t, inject_t, net_inject_t *); 89 static phy_if_t ipv6_routeto(net_handle_t, struct sockaddr *, 90 struct sockaddr *); 91 static int ipv6_isvalidchecksum(net_handle_t, mblk_t *); 92 93 static int net_no_getmtu(net_handle_t, phy_if_t, lif_if_t); 94 static int net_no_getpmtuenabled(net_handle_t); 95 static lif_if_t net_no_lifgetnext(net_handle_t, phy_if_t, lif_if_t); 96 static int net_no_inject(net_handle_t, inject_t, net_inject_t *); 97 static phy_if_t net_no_routeto(net_handle_t, struct sockaddr *, 98 struct sockaddr *); 99 static int net_no_ispartialchecksum(net_handle_t, mblk_t *); 100 static int net_no_getlifaddr(net_handle_t, phy_if_t, lif_if_t, 101 size_t, net_ifaddr_t [], void *); 102 static int net_no_getlifzone(net_handle_t, phy_if_t, lif_if_t, 103 zoneid_t *); 104 static int net_no_getlifflags(net_handle_t, phy_if_t, lif_if_t, 105 uint64_t *); 106 107 /* Netinfo private functions */ 108 static int ip_getifname_impl(phy_if_t, char *, 109 const size_t, boolean_t, ip_stack_t *); 110 static int ip_getmtu_impl(phy_if_t, lif_if_t, boolean_t, 111 ip_stack_t *); 112 static phy_if_t ip_phylookup_impl(const char *, boolean_t, 113 ip_stack_t *); 114 static lif_if_t ip_lifgetnext_impl(phy_if_t, lif_if_t, boolean_t, 115 ip_stack_t *); 116 static int ip_inject_impl(inject_t, net_inject_t *, boolean_t, 117 ip_stack_t *); 118 static int ip_getifaddr_type(sa_family_t, ipif_t *, lif_if_t, 119 void *); 120 static phy_if_t ip_routeto_impl(struct sockaddr *, struct sockaddr *, 121 ip_stack_t *); 122 static int ip_getlifaddr_impl(sa_family_t, phy_if_t, lif_if_t, 123 size_t, net_ifaddr_t [], struct sockaddr *, 124 ip_stack_t *); 125 static void ip_ni_queue_in_func(void *); 126 static void ip_ni_queue_out_func(void *); 127 static void ip_ni_queue_func_impl(injection_t *, boolean_t); 128 129 static net_protocol_t ipv4info = { 130 NETINFO_VERSION, 131 NHF_INET, 132 ip_getifname, 133 ip_getmtu, 134 ip_getpmtuenabled, 135 ip_getlifaddr, 136 ip_getlifzone, 137 ip_getlifflags, 138 ip_phygetnext, 139 ip_phylookup, 140 ip_lifgetnext, 141 ip_inject, 142 ip_routeto, 143 ip_ispartialchecksum, 144 ip_isvalidchecksum 145 }; 146 147 148 static net_protocol_t ipv6info = { 149 NETINFO_VERSION, 150 NHF_INET6, 151 ipv6_getifname, 152 ipv6_getmtu, 153 ip_getpmtuenabled, 154 ipv6_getlifaddr, 155 ipv6_getlifzone, 156 ipv6_getlifflags, 157 ipv6_phygetnext, 158 ipv6_phylookup, 159 ipv6_lifgetnext, 160 ipv6_inject, 161 ipv6_routeto, 162 ip_ispartialchecksum, 163 ipv6_isvalidchecksum 164 }; 165 166 static net_protocol_t arp_netinfo = { 167 NETINFO_VERSION, 168 NHF_ARP, 169 ip_getifname, 170 net_no_getmtu, 171 net_no_getpmtuenabled, 172 net_no_getlifaddr, 173 net_no_getlifzone, 174 net_no_getlifflags, 175 ip_phygetnext, 176 ip_phylookup, 177 net_no_lifgetnext, 178 net_no_inject, 179 net_no_routeto, 180 net_no_ispartialchecksum, 181 ip_isvalidchecksum 182 }; 183 184 /* 185 * The taskq eventq_queue_in is used to process the upside inject messages. 186 * The taskq eventq_queue_out is used to process the downside inject messages. 187 * The taskq eventq_queue_nic is used to process the nic event messages. 188 */ 189 static ddi_taskq_t *eventq_queue_in = NULL; 190 static ddi_taskq_t *eventq_queue_out = NULL; 191 ddi_taskq_t *eventq_queue_nic = NULL; 192 193 /* 194 * Initialize queues for inject. 195 */ 196 void 197 ip_net_g_init() 198 { 199 if (eventq_queue_out == NULL) { 200 eventq_queue_out = ddi_taskq_create(NULL, 201 "IP_INJECT_QUEUE_OUT", 1, TASKQ_DEFAULTPRI, 0); 202 203 if (eventq_queue_out == NULL) 204 cmn_err(CE_NOTE, "ipv4_net_init: " 205 "ddi_taskq_create failed for IP_INJECT_QUEUE_OUT"); 206 } 207 208 if (eventq_queue_in == NULL) { 209 eventq_queue_in = ddi_taskq_create(NULL, 210 "IP_INJECT_QUEUE_IN", 1, TASKQ_DEFAULTPRI, 0); 211 212 if (eventq_queue_in == NULL) 213 cmn_err(CE_NOTE, "ipv4_net_init: " 214 "ddi_taskq_create failed for IP_INJECT_QUEUE_IN"); 215 } 216 217 if (eventq_queue_nic == NULL) { 218 eventq_queue_nic = ddi_taskq_create(NULL, 219 "IP_NIC_EVENT_QUEUE", 1, TASKQ_DEFAULTPRI, 0); 220 221 if (eventq_queue_nic == NULL) 222 cmn_err(CE_NOTE, "ipv4_net_init: " 223 "ddi_taskq_create failed for IP_NIC_EVENT_QUEUE"); 224 } 225 } 226 227 /* 228 * Destroy inject queues 229 */ 230 void 231 ip_net_g_destroy() 232 { 233 if (eventq_queue_nic != NULL) { 234 ddi_taskq_destroy(eventq_queue_nic); 235 eventq_queue_nic = NULL; 236 } 237 238 if (eventq_queue_in != NULL) { 239 ddi_taskq_destroy(eventq_queue_in); 240 eventq_queue_in = NULL; 241 } 242 243 if (eventq_queue_out != NULL) { 244 ddi_taskq_destroy(eventq_queue_out); 245 eventq_queue_out = NULL; 246 } 247 } 248 249 /* 250 * Register IPv4 and IPv6 netinfo functions and initialize queues for inject. 251 */ 252 void 253 ip_net_init(ip_stack_t *ipst, netstack_t *ns) 254 { 255 netid_t id; 256 257 id = net_getnetidbynetstackid(ns->netstack_stackid); 258 ASSERT(id != -1); 259 260 ipst->ips_ipv4_net_data = net_protocol_register(id, &ipv4info); 261 ASSERT(ipst->ips_ipv4_net_data != NULL); 262 263 ipst->ips_ipv6_net_data = net_protocol_register(id, &ipv6info); 264 ASSERT(ipst->ips_ipv6_net_data != NULL); 265 266 ipst->ips_arp_net_data = net_protocol_register(id, &arp_netinfo); 267 ASSERT(ipst->ips_ipv6_net_data != NULL); 268 } 269 270 271 /* 272 * Unregister IPv4 and IPv6 functions. 273 */ 274 void 275 ip_net_destroy(ip_stack_t *ipst) 276 { 277 if (ipst->ips_ipv4_net_data != NULL) { 278 if (net_protocol_unregister(ipst->ips_ipv4_net_data) == 0) 279 ipst->ips_ipv4_net_data = NULL; 280 } 281 282 if (ipst->ips_ipv6_net_data != NULL) { 283 if (net_protocol_unregister(ipst->ips_ipv6_net_data) == 0) 284 ipst->ips_ipv6_net_data = NULL; 285 } 286 287 if (ipst->ips_arp_net_data != NULL) { 288 if (net_protocol_unregister(ipst->ips_arp_net_data) == 0) 289 ipst->ips_arp_net_data = NULL; 290 } 291 } 292 293 /* 294 * Initialize IPv4 hooks family the event 295 */ 296 void 297 ipv4_hook_init(ip_stack_t *ipst) 298 { 299 HOOK_FAMILY_INIT(&ipst->ips_ipv4root, Hn_IPV4); 300 if (net_family_register(ipst->ips_ipv4_net_data, &ipst->ips_ipv4root) 301 != 0) { 302 cmn_err(CE_NOTE, "ipv4_hook_init: " 303 "net_family_register failed for ipv4"); 304 } 305 306 HOOK_EVENT_INIT(&ipst->ips_ip4_physical_in_event, NH_PHYSICAL_IN); 307 ipst->ips_ipv4firewall_physical_in = net_event_register( 308 ipst->ips_ipv4_net_data, &ipst->ips_ip4_physical_in_event); 309 if (ipst->ips_ipv4firewall_physical_in == NULL) { 310 cmn_err(CE_NOTE, "ipv4_hook_init: " 311 "net_event_register failed for ipv4/physical_in"); 312 } 313 314 HOOK_EVENT_INIT(&ipst->ips_ip4_physical_out_event, NH_PHYSICAL_OUT); 315 ipst->ips_ipv4firewall_physical_out = net_event_register( 316 ipst->ips_ipv4_net_data, &ipst->ips_ip4_physical_out_event); 317 if (ipst->ips_ipv4firewall_physical_out == NULL) { 318 cmn_err(CE_NOTE, "ipv4_hook_init: " 319 "net_event_register failed for ipv4/physical_out"); 320 } 321 322 HOOK_EVENT_INIT(&ipst->ips_ip4_forwarding_event, NH_FORWARDING); 323 ipst->ips_ipv4firewall_forwarding = net_event_register( 324 ipst->ips_ipv4_net_data, &ipst->ips_ip4_forwarding_event); 325 if (ipst->ips_ipv4firewall_forwarding == NULL) { 326 cmn_err(CE_NOTE, "ipv4_hook_init: " 327 "net_event_register failed for ipv4/forwarding"); 328 } 329 330 HOOK_EVENT_INIT(&ipst->ips_ip4_loopback_in_event, NH_LOOPBACK_IN); 331 ipst->ips_ipv4firewall_loopback_in = net_event_register( 332 ipst->ips_ipv4_net_data, &ipst->ips_ip4_loopback_in_event); 333 if (ipst->ips_ipv4firewall_loopback_in == NULL) { 334 cmn_err(CE_NOTE, "ipv4_hook_init: " 335 "net_event_register failed for ipv4/loopback_in"); 336 } 337 338 HOOK_EVENT_INIT(&ipst->ips_ip4_loopback_out_event, NH_LOOPBACK_OUT); 339 ipst->ips_ipv4firewall_loopback_out = net_event_register( 340 ipst->ips_ipv4_net_data, &ipst->ips_ip4_loopback_out_event); 341 if (ipst->ips_ipv4firewall_loopback_out == NULL) { 342 cmn_err(CE_NOTE, "ipv4_hook_init: " 343 "net_event_register failed for ipv4/loopback_out"); 344 } 345 346 HOOK_EVENT_INIT(&ipst->ips_ip4_nic_events, NH_NIC_EVENTS); 347 ipst->ips_ip4_nic_events.he_flags = HOOK_RDONLY; 348 ipst->ips_ipv4nicevents = net_event_register( 349 ipst->ips_ipv4_net_data, &ipst->ips_ip4_nic_events); 350 if (ipst->ips_ipv4nicevents == NULL) { 351 cmn_err(CE_NOTE, "ipv4_hook_init: " 352 "net_event_register failed for ipv4/nic_events"); 353 } 354 355 HOOK_EVENT_INIT(&ipst->ips_ip4_observe, NH_OBSERVE); 356 ipst->ips_ip4_observe.he_flags = HOOK_RDONLY; 357 ipst->ips_ipv4observing = net_event_register( 358 ipst->ips_ipv4_net_data, &ipst->ips_ip4_observe); 359 if (ipst->ips_ipv4observing == NULL) { 360 cmn_err(CE_NOTE, "ipv4_hook_init: " 361 "net_event_register failed for ipv4/observe"); 362 } 363 364 } 365 366 void 367 ipv4_hook_shutdown(ip_stack_t *ipst) 368 { 369 if (ipst->ips_ipv4firewall_forwarding != NULL) { 370 (void) net_event_shutdown(ipst->ips_ipv4_net_data, 371 &ipst->ips_ip4_forwarding_event); 372 } 373 374 if (ipst->ips_ipv4firewall_physical_in != NULL) { 375 (void) net_event_shutdown(ipst->ips_ipv4_net_data, 376 &ipst->ips_ip4_physical_in_event); 377 } 378 379 if (ipst->ips_ipv4firewall_physical_out != NULL) { 380 (void) net_event_shutdown(ipst->ips_ipv4_net_data, 381 &ipst->ips_ip4_physical_out_event); 382 } 383 384 if (ipst->ips_ipv4firewall_loopback_in != NULL) { 385 (void) net_event_shutdown(ipst->ips_ipv4_net_data, 386 &ipst->ips_ip4_loopback_in_event); 387 } 388 389 if (ipst->ips_ipv4firewall_loopback_out != NULL) { 390 (void) net_event_shutdown(ipst->ips_ipv4_net_data, 391 &ipst->ips_ip4_loopback_out_event); 392 } 393 394 if (ipst->ips_ipv4nicevents != NULL) { 395 (void) net_event_shutdown(ipst->ips_ipv4_net_data, 396 &ipst->ips_ip4_nic_events); 397 } 398 399 if (ipst->ips_ipv4observing != NULL) { 400 (void) net_event_shutdown(ipst->ips_ipv4_net_data, 401 &ipst->ips_ip4_observe); 402 } 403 404 (void) net_family_shutdown(ipst->ips_ipv4_net_data, 405 &ipst->ips_ipv4root); 406 } 407 408 void 409 ipv4_hook_destroy(ip_stack_t *ipst) 410 { 411 if (ipst->ips_ipv4firewall_forwarding != NULL) { 412 if (net_event_unregister(ipst->ips_ipv4_net_data, 413 &ipst->ips_ip4_forwarding_event) == 0) 414 ipst->ips_ipv4firewall_forwarding = NULL; 415 } 416 417 if (ipst->ips_ipv4firewall_physical_in != NULL) { 418 if (net_event_unregister(ipst->ips_ipv4_net_data, 419 &ipst->ips_ip4_physical_in_event) == 0) 420 ipst->ips_ipv4firewall_physical_in = NULL; 421 } 422 423 if (ipst->ips_ipv4firewall_physical_out != NULL) { 424 if (net_event_unregister(ipst->ips_ipv4_net_data, 425 &ipst->ips_ip4_physical_out_event) == 0) 426 ipst->ips_ipv4firewall_physical_out = NULL; 427 } 428 429 if (ipst->ips_ipv4firewall_loopback_in != NULL) { 430 if (net_event_unregister(ipst->ips_ipv4_net_data, 431 &ipst->ips_ip4_loopback_in_event) == 0) 432 ipst->ips_ipv4firewall_loopback_in = NULL; 433 } 434 435 if (ipst->ips_ipv4firewall_loopback_out != NULL) { 436 if (net_event_unregister(ipst->ips_ipv4_net_data, 437 &ipst->ips_ip4_loopback_out_event) == 0) 438 ipst->ips_ipv4firewall_loopback_out = NULL; 439 } 440 441 if (ipst->ips_ipv4nicevents != NULL) { 442 if (net_event_unregister(ipst->ips_ipv4_net_data, 443 &ipst->ips_ip4_nic_events) == 0) 444 ipst->ips_ipv4nicevents = NULL; 445 } 446 447 if (ipst->ips_ipv4observing != NULL) { 448 if (net_event_unregister(ipst->ips_ipv4_net_data, 449 &ipst->ips_ip4_observe) == 0) 450 ipst->ips_ipv4observing = NULL; 451 } 452 453 (void) net_family_unregister(ipst->ips_ipv4_net_data, 454 &ipst->ips_ipv4root); 455 } 456 457 /* 458 * Initialize IPv6 hooks family and event 459 */ 460 void 461 ipv6_hook_init(ip_stack_t *ipst) 462 { 463 464 HOOK_FAMILY_INIT(&ipst->ips_ipv6root, Hn_IPV6); 465 if (net_family_register(ipst->ips_ipv6_net_data, &ipst->ips_ipv6root) 466 != 0) { 467 cmn_err(CE_NOTE, "ipv6_hook_init: " 468 "net_family_register failed for ipv6"); 469 } 470 471 HOOK_EVENT_INIT(&ipst->ips_ip6_physical_in_event, NH_PHYSICAL_IN); 472 ipst->ips_ipv6firewall_physical_in = net_event_register( 473 ipst->ips_ipv6_net_data, &ipst->ips_ip6_physical_in_event); 474 if (ipst->ips_ipv6firewall_physical_in == NULL) { 475 cmn_err(CE_NOTE, "ipv6_hook_init: " 476 "net_event_register failed for ipv6/physical_in"); 477 } 478 479 HOOK_EVENT_INIT(&ipst->ips_ip6_physical_out_event, NH_PHYSICAL_OUT); 480 ipst->ips_ipv6firewall_physical_out = net_event_register( 481 ipst->ips_ipv6_net_data, &ipst->ips_ip6_physical_out_event); 482 if (ipst->ips_ipv6firewall_physical_out == NULL) { 483 cmn_err(CE_NOTE, "ipv6_hook_init: " 484 "net_event_register failed for ipv6/physical_out"); 485 } 486 487 HOOK_EVENT_INIT(&ipst->ips_ip6_forwarding_event, NH_FORWARDING); 488 ipst->ips_ipv6firewall_forwarding = net_event_register( 489 ipst->ips_ipv6_net_data, &ipst->ips_ip6_forwarding_event); 490 if (ipst->ips_ipv6firewall_forwarding == NULL) { 491 cmn_err(CE_NOTE, "ipv6_hook_init: " 492 "net_event_register failed for ipv6/forwarding"); 493 } 494 495 HOOK_EVENT_INIT(&ipst->ips_ip6_loopback_in_event, NH_LOOPBACK_IN); 496 ipst->ips_ipv6firewall_loopback_in = net_event_register( 497 ipst->ips_ipv6_net_data, &ipst->ips_ip6_loopback_in_event); 498 if (ipst->ips_ipv6firewall_loopback_in == NULL) { 499 cmn_err(CE_NOTE, "ipv6_hook_init: " 500 "net_event_register failed for ipv6/loopback_in"); 501 } 502 503 HOOK_EVENT_INIT(&ipst->ips_ip6_loopback_out_event, NH_LOOPBACK_OUT); 504 ipst->ips_ipv6firewall_loopback_out = net_event_register( 505 ipst->ips_ipv6_net_data, &ipst->ips_ip6_loopback_out_event); 506 if (ipst->ips_ipv6firewall_loopback_out == NULL) { 507 cmn_err(CE_NOTE, "ipv6_hook_init: " 508 "net_event_register failed for ipv6/loopback_out"); 509 } 510 511 HOOK_EVENT_INIT(&ipst->ips_ip6_nic_events, NH_NIC_EVENTS); 512 ipst->ips_ip6_nic_events.he_flags = HOOK_RDONLY; 513 ipst->ips_ipv6nicevents = net_event_register( 514 ipst->ips_ipv6_net_data, &ipst->ips_ip6_nic_events); 515 if (ipst->ips_ipv6nicevents == NULL) { 516 cmn_err(CE_NOTE, "ipv6_hook_init: " 517 "net_event_register failed for ipv6/nic_events"); 518 } 519 520 HOOK_EVENT_INIT(&ipst->ips_ip6_observe, NH_OBSERVE); 521 ipst->ips_ip6_observe.he_flags = HOOK_RDONLY; 522 ipst->ips_ipv6observing = net_event_register( 523 ipst->ips_ipv6_net_data, &ipst->ips_ip6_observe); 524 if (ipst->ips_ipv6observing == NULL) { 525 cmn_err(CE_NOTE, "ipv6_hook_init: " 526 "net_event_register failed for ipv6/observe"); 527 } 528 } 529 530 void 531 ipv6_hook_shutdown(ip_stack_t *ipst) 532 { 533 if (ipst->ips_ipv6firewall_forwarding != NULL) { 534 (void) net_event_shutdown(ipst->ips_ipv6_net_data, 535 &ipst->ips_ip6_forwarding_event); 536 } 537 538 if (ipst->ips_ipv6firewall_physical_in != NULL) { 539 (void) net_event_shutdown(ipst->ips_ipv6_net_data, 540 &ipst->ips_ip6_physical_in_event); 541 } 542 543 if (ipst->ips_ipv6firewall_physical_out != NULL) { 544 (void) net_event_shutdown(ipst->ips_ipv6_net_data, 545 &ipst->ips_ip6_physical_out_event); 546 } 547 548 if (ipst->ips_ipv6firewall_loopback_in != NULL) { 549 (void) net_event_shutdown(ipst->ips_ipv6_net_data, 550 &ipst->ips_ip6_loopback_in_event); 551 } 552 553 if (ipst->ips_ipv6firewall_loopback_out != NULL) { 554 (void) net_event_shutdown(ipst->ips_ipv6_net_data, 555 &ipst->ips_ip6_loopback_out_event); 556 } 557 558 if (ipst->ips_ipv6nicevents != NULL) { 559 (void) net_event_shutdown(ipst->ips_ipv6_net_data, 560 &ipst->ips_ip6_nic_events); 561 } 562 563 if (ipst->ips_ipv6observing != NULL) { 564 (void) net_event_shutdown(ipst->ips_ipv6_net_data, 565 &ipst->ips_ip6_observe); 566 } 567 568 (void) net_family_shutdown(ipst->ips_ipv6_net_data, 569 &ipst->ips_ipv6root); 570 } 571 572 void 573 ipv6_hook_destroy(ip_stack_t *ipst) 574 { 575 if (ipst->ips_ipv6firewall_forwarding != NULL) { 576 if (net_event_unregister(ipst->ips_ipv6_net_data, 577 &ipst->ips_ip6_forwarding_event) == 0) 578 ipst->ips_ipv6firewall_forwarding = NULL; 579 } 580 581 if (ipst->ips_ipv6firewall_physical_in != NULL) { 582 if (net_event_unregister(ipst->ips_ipv6_net_data, 583 &ipst->ips_ip6_physical_in_event) == 0) 584 ipst->ips_ipv6firewall_physical_in = NULL; 585 } 586 587 if (ipst->ips_ipv6firewall_physical_out != NULL) { 588 if (net_event_unregister(ipst->ips_ipv6_net_data, 589 &ipst->ips_ip6_physical_out_event) == 0) 590 ipst->ips_ipv6firewall_physical_out = NULL; 591 } 592 593 if (ipst->ips_ipv6firewall_loopback_in != NULL) { 594 if (net_event_unregister(ipst->ips_ipv6_net_data, 595 &ipst->ips_ip6_loopback_in_event) == 0) 596 ipst->ips_ipv6firewall_loopback_in = NULL; 597 } 598 599 if (ipst->ips_ipv6firewall_loopback_out != NULL) { 600 if (net_event_unregister(ipst->ips_ipv6_net_data, 601 &ipst->ips_ip6_loopback_out_event) == 0) 602 ipst->ips_ipv6firewall_loopback_out = NULL; 603 } 604 605 if (ipst->ips_ipv6nicevents != NULL) { 606 if (net_event_unregister(ipst->ips_ipv6_net_data, 607 &ipst->ips_ip6_nic_events) == 0) 608 ipst->ips_ipv6nicevents = NULL; 609 } 610 611 if (ipst->ips_ipv6observing != NULL) { 612 if (net_event_unregister(ipst->ips_ipv6_net_data, 613 &ipst->ips_ip6_observe) == 0) 614 ipst->ips_ipv6observing = NULL; 615 } 616 617 (void) net_family_unregister(ipst->ips_ipv6_net_data, 618 &ipst->ips_ipv6root); 619 } 620 621 /* 622 * Determine the name of an IPv4 interface 623 */ 624 static int 625 ip_getifname(net_handle_t neti, phy_if_t phy_ifdata, char *buffer, 626 const size_t buflen) 627 { 628 return (ip_getifname_impl(phy_ifdata, buffer, buflen, B_FALSE, 629 neti->netd_stack->nts_netstack->netstack_ip)); 630 } 631 632 /* 633 * Determine the name of an IPv6 interface 634 */ 635 static int 636 ipv6_getifname(net_handle_t neti, phy_if_t phy_ifdata, char *buffer, 637 const size_t buflen) 638 { 639 return (ip_getifname_impl(phy_ifdata, buffer, buflen, B_TRUE, 640 neti->netd_stack->nts_netstack->netstack_ip)); 641 } 642 643 /* 644 * Shared implementation to determine the name of a given network interface 645 */ 646 /* ARGSUSED */ 647 static int 648 ip_getifname_impl(phy_if_t phy_ifdata, 649 char *buffer, const size_t buflen, boolean_t isv6, ip_stack_t *ipst) 650 { 651 ill_t *ill; 652 653 ASSERT(buffer != NULL); 654 655 ill = ill_lookup_on_ifindex((uint_t)phy_ifdata, isv6, ipst); 656 if (ill == NULL) 657 return (1); 658 659 (void) strlcpy(buffer, ill->ill_name, buflen); 660 ill_refrele(ill); 661 return (0); 662 } 663 664 /* 665 * Determine the MTU of an IPv4 network interface 666 */ 667 static int 668 ip_getmtu(net_handle_t neti, phy_if_t phy_ifdata, lif_if_t ifdata) 669 { 670 netstack_t *ns; 671 672 ns = neti->netd_stack->nts_netstack; 673 ASSERT(ns != NULL); 674 return (ip_getmtu_impl(phy_ifdata, ifdata, B_FALSE, ns->netstack_ip)); 675 } 676 677 /* 678 * Determine the MTU of an IPv6 network interface 679 */ 680 static int 681 ipv6_getmtu(net_handle_t neti, phy_if_t phy_ifdata, lif_if_t ifdata) 682 { 683 netstack_t *ns; 684 685 ns = neti->netd_stack->nts_netstack; 686 ASSERT(ns != NULL); 687 return (ip_getmtu_impl(phy_ifdata, ifdata, B_TRUE, ns->netstack_ip)); 688 } 689 690 /* 691 * Shared implementation to determine the MTU of a network interface 692 */ 693 /* ARGSUSED */ 694 static int 695 ip_getmtu_impl(phy_if_t phy_ifdata, lif_if_t ifdata, boolean_t isv6, 696 ip_stack_t *ipst) 697 { 698 lif_if_t ipifid; 699 ipif_t *ipif; 700 int mtu; 701 702 ipifid = UNMAP_IPIF_ID(ifdata); 703 704 ipif = ipif_getby_indexes((uint_t)phy_ifdata, (uint_t)ipifid, 705 isv6, ipst); 706 if (ipif == NULL) 707 return (0); 708 709 mtu = ipif->ipif_ill->ill_mtu; 710 ipif_refrele(ipif); 711 712 if (mtu == 0) { 713 ill_t *ill; 714 715 if ((ill = ill_lookup_on_ifindex((uint_t)phy_ifdata, isv6, 716 ipst)) == NULL) { 717 return (0); 718 } 719 mtu = ill->ill_mtu; 720 ill_refrele(ill); 721 } 722 723 return (mtu); 724 } 725 726 /* 727 * Determine if path MTU discovery is enabled for IP 728 */ 729 static int 730 ip_getpmtuenabled(net_handle_t neti) 731 { 732 netstack_t *ns; 733 734 ns = neti->netd_stack->nts_netstack; 735 ASSERT(ns != NULL); 736 return (ns->netstack_ip->ips_ip_path_mtu_discovery); 737 } 738 739 /* 740 * Get next interface from the current list of IPv4 physical network interfaces 741 */ 742 static phy_if_t 743 ip_phygetnext(net_handle_t neti, phy_if_t phy_ifdata) 744 { 745 netstack_t *ns; 746 747 ns = neti->netd_stack->nts_netstack; 748 ASSERT(ns != NULL); 749 return (ill_get_next_ifindex(phy_ifdata, B_FALSE, ns->netstack_ip)); 750 } 751 752 /* 753 * Get next interface from the current list of IPv6 physical network interfaces 754 */ 755 static phy_if_t 756 ipv6_phygetnext(net_handle_t neti, phy_if_t phy_ifdata) 757 { 758 netstack_t *ns; 759 760 ns = neti->netd_stack->nts_netstack; 761 ASSERT(ns != NULL); 762 return (ill_get_next_ifindex(phy_ifdata, B_TRUE, ns->netstack_ip)); 763 } 764 765 /* 766 * Determine if a network interface name exists for IPv4 767 */ 768 static phy_if_t 769 ip_phylookup(net_handle_t neti, const char *name) 770 { 771 netstack_t *ns; 772 773 ns = neti->netd_stack->nts_netstack; 774 ASSERT(ns != NULL); 775 return (ip_phylookup_impl(name, B_FALSE, ns->netstack_ip)); 776 } 777 778 /* 779 * Determine if a network interface name exists for IPv6 780 */ 781 static phy_if_t 782 ipv6_phylookup(net_handle_t neti, const char *name) 783 { 784 netstack_t *ns; 785 786 ns = neti->netd_stack->nts_netstack; 787 ASSERT(ns != NULL); 788 return (ip_phylookup_impl(name, B_TRUE, ns->netstack_ip)); 789 } 790 791 /* 792 * Implement looking up an ill_t based on the name supplied and matching 793 * it up with either IPv4 or IPv6. ill_get_ifindex_by_name() is not used 794 * because it does not match on the address family in addition to the name. 795 */ 796 static phy_if_t 797 ip_phylookup_impl(const char *name, boolean_t isv6, ip_stack_t *ipst) 798 { 799 phy_if_t phy; 800 ill_t *ill; 801 802 ill = ill_lookup_on_name((char *)name, B_FALSE, isv6, NULL, ipst); 803 if (ill == NULL) 804 return (0); 805 806 phy = ill->ill_phyint->phyint_ifindex; 807 808 ill_refrele(ill); 809 810 return (phy); 811 } 812 813 /* 814 * Get next interface from the current list of IPv4 logical network interfaces 815 */ 816 static lif_if_t 817 ip_lifgetnext(net_handle_t neti, phy_if_t phy_ifdata, lif_if_t ifdata) 818 { 819 netstack_t *ns; 820 821 ns = neti->netd_stack->nts_netstack; 822 ASSERT(ns != NULL); 823 return (ip_lifgetnext_impl(phy_ifdata, ifdata, B_FALSE, 824 ns->netstack_ip)); 825 } 826 827 /* 828 * Get next interface from the current list of IPv6 logical network interfaces 829 */ 830 static lif_if_t 831 ipv6_lifgetnext(net_handle_t neti, phy_if_t phy_ifdata, lif_if_t ifdata) 832 { 833 netstack_t *ns; 834 835 ns = neti->netd_stack->nts_netstack; 836 ASSERT(ns != NULL); 837 return (ip_lifgetnext_impl(phy_ifdata, ifdata, B_TRUE, 838 ns->netstack_ip)); 839 } 840 841 /* 842 * Shared implementation to get next interface from the current list of 843 * logical network interfaces 844 */ 845 static lif_if_t 846 ip_lifgetnext_impl(phy_if_t phy_ifdata, lif_if_t ifdata, boolean_t isv6, 847 ip_stack_t *ipst) 848 { 849 lif_if_t newidx, oldidx; 850 boolean_t nextok; 851 ipif_t *ipif; 852 ill_t *ill; 853 854 ill = ill_lookup_on_ifindex(phy_ifdata, isv6, ipst); 855 if (ill == NULL) 856 return (0); 857 858 if (ifdata != 0) { 859 oldidx = UNMAP_IPIF_ID(ifdata); 860 nextok = B_FALSE; 861 } else { 862 oldidx = 0; 863 nextok = B_TRUE; 864 } 865 866 mutex_enter(&ill->ill_lock); 867 if (ill->ill_state_flags & ILL_CONDEMNED) { 868 mutex_exit(&ill->ill_lock); 869 ill_refrele(ill); 870 return (0); 871 } 872 873 /* 874 * It's safe to iterate the ill_ipif list when holding an ill_lock. 875 * And it's also safe to access ipif_id without ipif refhold. 876 * See the field access rules in ip.h. 877 */ 878 for (ipif = ill->ill_ipif; ipif != NULL; ipif = ipif->ipif_next) { 879 if (!IPIF_CAN_LOOKUP(ipif)) 880 continue; 881 if (nextok) { 882 ipif_refhold_locked(ipif); 883 break; 884 } else if (oldidx == ipif->ipif_id) { 885 nextok = B_TRUE; 886 } 887 } 888 889 mutex_exit(&ill->ill_lock); 890 ill_refrele(ill); 891 892 if (ipif == NULL) 893 return (0); 894 895 newidx = ipif->ipif_id; 896 ipif_refrele(ipif); 897 898 return (MAP_IPIF_ID(newidx)); 899 } 900 901 /* 902 * Inject an IPv4 packet to or from an interface 903 */ 904 static int 905 ip_inject(net_handle_t neti, inject_t style, net_inject_t *packet) 906 { 907 netstack_t *ns; 908 909 ns = neti->netd_stack->nts_netstack; 910 ASSERT(ns != NULL); 911 return (ip_inject_impl(style, packet, B_FALSE, ns->netstack_ip)); 912 } 913 914 915 /* 916 * Inject an IPv6 packet to or from an interface 917 */ 918 static int 919 ipv6_inject(net_handle_t neti, inject_t style, net_inject_t *packet) 920 { 921 netstack_t *ns; 922 923 ns = neti->netd_stack->nts_netstack; 924 return (ip_inject_impl(style, packet, B_TRUE, ns->netstack_ip)); 925 } 926 927 /* 928 * Shared implementation to inject a packet to or from an interface 929 * Return value: 930 * 0: successful 931 * -1: memory allocation failed 932 * 1: other errors 933 */ 934 static int 935 ip_inject_impl(inject_t style, net_inject_t *packet, boolean_t isv6, 936 ip_stack_t *ipst) 937 { 938 ddi_taskq_t *tq = NULL; 939 void (* func)(void *); 940 injection_t *inject; 941 mblk_t *mp; 942 943 ASSERT(packet != NULL); 944 ASSERT(packet->ni_packet != NULL); 945 ASSERT(packet->ni_packet->b_datap->db_type == M_DATA); 946 947 switch (style) { 948 case NI_QUEUE_IN: 949 inject = kmem_alloc(sizeof (*inject), KM_NOSLEEP); 950 if (inject == NULL) 951 return (-1); 952 inject->inj_data = *packet; 953 inject->inj_isv6 = isv6; 954 /* 955 * deliver up into the kernel, immitating its reception by a 956 * network interface, add to list and schedule timeout 957 */ 958 func = ip_ni_queue_in_func; 959 tq = eventq_queue_in; 960 break; 961 962 case NI_QUEUE_OUT: 963 inject = kmem_alloc(sizeof (*inject), KM_NOSLEEP); 964 if (inject == NULL) 965 return (-1); 966 inject->inj_data = *packet; 967 inject->inj_isv6 = isv6; 968 /* 969 * deliver out of the kernel, as if it were being sent via a 970 * raw socket so that IPFilter will see it again, add to list 971 * and schedule timeout 972 */ 973 func = ip_ni_queue_out_func; 974 tq = eventq_queue_out; 975 break; 976 977 case NI_DIRECT_OUT: { 978 struct sockaddr *sock; 979 980 mp = packet->ni_packet; 981 982 sock = (struct sockaddr *)&packet->ni_addr; 983 /* 984 * ipfil_sendpkt was provided by surya to ease the 985 * problems associated with sending out a packet. 986 */ 987 switch (ipfil_sendpkt(sock, mp, packet->ni_physical, 988 netstackid_to_zoneid( 989 ipst->ips_netstack->netstack_stackid))) { 990 case 0 : 991 case EINPROGRESS: 992 return (0); 993 case ECOMM : 994 case ENONET : 995 return (1); 996 default : 997 return (1); 998 } 999 /* NOTREACHED */ 1000 } 1001 default: 1002 freemsg(packet->ni_packet); 1003 return (1); 1004 } 1005 1006 ASSERT(tq != NULL); 1007 1008 inject->inj_ptr = ipst; 1009 if (ddi_taskq_dispatch(tq, func, (void *)inject, 1010 DDI_SLEEP) == DDI_FAILURE) { 1011 ip2dbg(("ip_inject: ddi_taskq_dispatch failed\n")); 1012 freemsg(packet->ni_packet); 1013 return (1); 1014 } 1015 return (0); 1016 } 1017 1018 /* 1019 * Find the interface used for traffic to a given IPv4 address 1020 */ 1021 static phy_if_t 1022 ip_routeto(net_handle_t neti, struct sockaddr *address, struct sockaddr *next) 1023 { 1024 netstack_t *ns; 1025 1026 ASSERT(address != NULL); 1027 1028 if (address->sa_family != AF_INET) 1029 return (0); 1030 1031 ns = neti->netd_stack->nts_netstack; 1032 ASSERT(ns != NULL); 1033 1034 return (ip_routeto_impl(address, next, ns->netstack_ip)); 1035 } 1036 1037 /* 1038 * Find the interface used for traffic to a given IPv6 address 1039 */ 1040 static phy_if_t 1041 ipv6_routeto(net_handle_t neti, struct sockaddr *address, struct sockaddr *next) 1042 { 1043 netstack_t *ns; 1044 1045 ASSERT(address != NULL); 1046 1047 if (address->sa_family != AF_INET6) 1048 return (0); 1049 1050 ns = neti->netd_stack->nts_netstack; 1051 ASSERT(ns != NULL); 1052 1053 return (ip_routeto_impl(address, next, ns->netstack_ip)); 1054 } 1055 1056 1057 /* 1058 * Find the interface used for traffic to an address. 1059 * For lint reasons, next/next6/sin/sin6 are all declared and assigned 1060 * a value at the top. The alternative would end up with two bunches 1061 * of assignments, with each bunch setting half to NULL. 1062 */ 1063 static phy_if_t 1064 ip_routeto_impl(struct sockaddr *address, struct sockaddr *nexthop, 1065 ip_stack_t *ipst) 1066 { 1067 struct sockaddr_in6 *next6 = (struct sockaddr_in6 *)nexthop; 1068 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)address; 1069 struct sockaddr_in *next = (struct sockaddr_in *)nexthop; 1070 struct sockaddr_in *sin = (struct sockaddr_in *)address; 1071 ire_t *ire; 1072 ire_t *nexthop_ire; 1073 phy_if_t phy_if; 1074 zoneid_t zoneid; 1075 1076 zoneid = netstackid_to_zoneid(ipst->ips_netstack->netstack_stackid); 1077 1078 if (address->sa_family == AF_INET6) { 1079 ire = ire_route_recursive_v6(&sin6->sin6_addr, 0, NULL, 1080 zoneid, NULL, MATCH_IRE_DSTONLY, B_TRUE, 0, ipst, NULL, 1081 NULL, NULL); 1082 } else { 1083 ire = ire_route_recursive_v4(sin->sin_addr.s_addr, 0, NULL, 1084 zoneid, NULL, MATCH_IRE_DSTONLY, B_TRUE, 0, ipst, NULL, 1085 NULL, NULL); 1086 } 1087 ASSERT(ire != NULL); 1088 /* 1089 * For some destinations, we have routes that are dead ends, so 1090 * return to indicate that no physical interface can be used to 1091 * reach the destination. 1092 */ 1093 if (ire->ire_flags & (RTF_REJECT|RTF_BLACKHOLE)) { 1094 ire_refrele(ire); 1095 return (NULL); 1096 } 1097 1098 nexthop_ire = ire_nexthop(ire); 1099 if (nexthop_ire == NULL) { 1100 ire_refrele(ire); 1101 return (0); 1102 } 1103 if (nexthop_ire->ire_flags & (RTF_REJECT|RTF_BLACKHOLE)) { 1104 ire_refrele(nexthop_ire); 1105 ire_refrele(ire); 1106 return (0); 1107 } 1108 1109 ASSERT(nexthop_ire->ire_ill != NULL); 1110 1111 if (nexthop != NULL) { 1112 if (address->sa_family == AF_INET6) { 1113 next6->sin6_addr = nexthop_ire->ire_addr_v6; 1114 } else { 1115 next->sin_addr.s_addr = nexthop_ire->ire_addr; 1116 } 1117 } 1118 1119 phy_if = (phy_if_t)nexthop_ire->ire_ill->ill_phyint->phyint_ifindex; 1120 ire_refrele(ire); 1121 ire_refrele(nexthop_ire); 1122 1123 return (phy_if); 1124 } 1125 1126 /* 1127 * Determine if checksumming is being used for the given packet. 1128 * 1129 * Return value: 1130 * NET_HCK_NONE: full checksum recalculation is required 1131 * NET_HCK_L3_FULL: full layer 3 checksum 1132 * NET_HCK_L4_FULL: full layer 4 checksum 1133 * NET_HCK_L4_PART: partial layer 4 checksum 1134 */ 1135 /*ARGSUSED*/ 1136 static int 1137 ip_ispartialchecksum(net_handle_t neti, mblk_t *mp) 1138 { 1139 int ret = 0; 1140 1141 ASSERT(mp != NULL); 1142 1143 if ((DB_CKSUMFLAGS(mp) & HCK_FULLCKSUM) != 0) { 1144 ret |= (int)NET_HCK_L4_FULL; 1145 if ((DB_CKSUMFLAGS(mp) & HCK_IPV4_HDRCKSUM) != 0) 1146 ret |= (int)NET_HCK_L3_FULL; 1147 } 1148 if ((DB_CKSUMFLAGS(mp) & HCK_PARTIALCKSUM) != 0) { 1149 ret |= (int)NET_HCK_L4_PART; 1150 if ((DB_CKSUMFLAGS(mp) & HCK_IPV4_HDRCKSUM) != 0) 1151 ret |= (int)NET_HCK_L3_FULL; 1152 } 1153 1154 return (ret); 1155 } 1156 1157 /* 1158 * Return true or false, indicating whether the network and transport 1159 * headers are correct. Use the capabilities flags and flags set in the 1160 * dblk_t to determine whether or not the checksum is valid. 1161 * 1162 * Return: 1163 * 0: the checksum was incorrect 1164 * 1: the original checksum was correct 1165 */ 1166 /*ARGSUSED*/ 1167 static int 1168 ip_isvalidchecksum(net_handle_t neti, mblk_t *mp) 1169 { 1170 unsigned char *wptr; 1171 ipha_t *ipha = (ipha_t *)mp->b_rptr; 1172 int hlen; 1173 int ret; 1174 1175 ASSERT(mp != NULL); 1176 1177 if (dohwcksum && 1178 DB_CKSUM16(mp) != 0xFFFF && 1179 (DB_CKSUMFLAGS(mp) & HCK_FULLCKSUM) && 1180 (DB_CKSUMFLAGS(mp) & HCK_FULLCKSUM_OK) && 1181 (DB_CKSUMFLAGS(mp) & HCK_IPV4_HDRCKSUM)) 1182 return (1); 1183 1184 hlen = (ipha->ipha_version_and_hdr_length & 0x0F) << 2; 1185 1186 /* 1187 * Check that the mblk being passed in has enough data in it 1188 * before blindly checking ip_cksum. 1189 */ 1190 if (msgdsize(mp) < hlen) 1191 return (0); 1192 1193 if (mp->b_wptr < mp->b_rptr + hlen) { 1194 if (pullupmsg(mp, hlen) == 0) 1195 return (0); 1196 wptr = mp->b_wptr; 1197 } else { 1198 wptr = mp->b_wptr; 1199 mp->b_wptr = mp->b_rptr + hlen; 1200 } 1201 1202 if (ipha->ipha_hdr_checksum == ip_cksum(mp, 0, ipha->ipha_hdr_checksum)) 1203 ret = 1; 1204 else 1205 ret = 0; 1206 mp->b_wptr = wptr; 1207 1208 return (ret); 1209 } 1210 1211 /* 1212 * Unsupported with IPv6 1213 */ 1214 /*ARGSUSED*/ 1215 static int 1216 ipv6_isvalidchecksum(net_handle_t neti, mblk_t *mp) 1217 { 1218 return (-1); 1219 } 1220 1221 /* 1222 * Determine the network addresses for an IPv4 interface 1223 */ 1224 static int 1225 ip_getlifaddr(net_handle_t neti, phy_if_t phy_ifdata, lif_if_t ifdata, 1226 size_t nelem, net_ifaddr_t type[], void *storage) 1227 { 1228 netstack_t *ns; 1229 1230 ns = neti->netd_stack->nts_netstack; 1231 ASSERT(ns != NULL); 1232 return (ip_getlifaddr_impl(AF_INET, phy_ifdata, ifdata, 1233 nelem, type, storage, ns->netstack_ip)); 1234 } 1235 1236 /* 1237 * Determine the network addresses for an IPv6 interface 1238 */ 1239 static int 1240 ipv6_getlifaddr(net_handle_t neti, phy_if_t phy_ifdata, lif_if_t ifdata, 1241 size_t nelem, net_ifaddr_t type[], void *storage) 1242 { 1243 netstack_t *ns; 1244 1245 ns = neti->netd_stack->nts_netstack; 1246 ASSERT(ns != NULL); 1247 return (ip_getlifaddr_impl(AF_INET6, phy_ifdata, ifdata, 1248 nelem, type, storage, ns->netstack_ip)); 1249 } 1250 1251 /* 1252 * Shared implementation to determine the network addresses for an interface 1253 */ 1254 /* ARGSUSED */ 1255 static int 1256 ip_getlifaddr_impl(sa_family_t family, phy_if_t phy_ifdata, 1257 lif_if_t ifdata, size_t nelem, net_ifaddr_t type[], 1258 struct sockaddr *storage, ip_stack_t *ipst) 1259 { 1260 struct sockaddr_in6 *sin6; 1261 struct sockaddr_in *sin; 1262 lif_if_t ipifid; 1263 ipif_t *ipif; 1264 int i; 1265 1266 ASSERT(type != NULL); 1267 ASSERT(storage != NULL); 1268 1269 ipifid = UNMAP_IPIF_ID(ifdata); 1270 1271 if (family == AF_INET) { 1272 if ((ipif = ipif_getby_indexes((uint_t)phy_ifdata, 1273 (uint_t)ipifid, B_FALSE, ipst)) == NULL) 1274 return (1); 1275 1276 sin = (struct sockaddr_in *)storage; 1277 for (i = 0; i < nelem; i++, sin++) { 1278 if (ip_getifaddr_type(AF_INET, ipif, type[i], 1279 &sin->sin_addr) < 0) { 1280 ip2dbg(("ip_getlifaddr_impl failed type %d\n", 1281 type[i])); 1282 ipif_refrele(ipif); 1283 return (1); 1284 } 1285 sin->sin_family = AF_INET; 1286 } 1287 } else { 1288 if ((ipif = ipif_getby_indexes((uint_t)phy_ifdata, 1289 (uint_t)ipifid, B_TRUE, ipst)) == NULL) 1290 return (1); 1291 1292 sin6 = (struct sockaddr_in6 *)storage; 1293 for (i = 0; i < nelem; i++, sin6++) { 1294 if (ip_getifaddr_type(AF_INET6, ipif, type[i], 1295 &sin6->sin6_addr) < 0) { 1296 ip2dbg(("ip_getlifaddr_impl failed type %d\n", 1297 type[i])); 1298 ipif_refrele(ipif); 1299 return (1); 1300 } 1301 sin6->sin6_family = AF_INET6; 1302 } 1303 } 1304 ipif_refrele(ipif); 1305 return (0); 1306 } 1307 1308 /* 1309 * ip_getlifaddr private function 1310 */ 1311 static int 1312 ip_getifaddr_type(sa_family_t family, ipif_t *ill_ipif, 1313 lif_if_t type, void *storage) 1314 { 1315 void *src_addr; 1316 int mem_size; 1317 1318 ASSERT(ill_ipif != NULL); 1319 ASSERT(storage != NULL); 1320 1321 if (family == AF_INET) { 1322 mem_size = sizeof (struct in_addr); 1323 1324 switch (type) { 1325 case NA_ADDRESS: 1326 src_addr = &(ill_ipif->ipif_lcl_addr); 1327 break; 1328 case NA_PEER: 1329 src_addr = &(ill_ipif->ipif_pp_dst_addr); 1330 break; 1331 case NA_BROADCAST: 1332 src_addr = &(ill_ipif->ipif_brd_addr); 1333 break; 1334 case NA_NETMASK: 1335 src_addr = &(ill_ipif->ipif_net_mask); 1336 break; 1337 default: 1338 return (-1); 1339 /*NOTREACHED*/ 1340 } 1341 } else { 1342 mem_size = sizeof (struct in6_addr); 1343 1344 switch (type) { 1345 case NA_ADDRESS: 1346 src_addr = &(ill_ipif->ipif_v6lcl_addr); 1347 break; 1348 case NA_PEER: 1349 src_addr = &(ill_ipif->ipif_v6pp_dst_addr); 1350 break; 1351 case NA_BROADCAST: 1352 src_addr = &(ill_ipif->ipif_v6brd_addr); 1353 break; 1354 case NA_NETMASK: 1355 src_addr = &(ill_ipif->ipif_v6net_mask); 1356 break; 1357 default: 1358 return (-1); 1359 /*NOTREACHED*/ 1360 } 1361 } 1362 1363 (void) memcpy(storage, src_addr, mem_size); 1364 return (1); 1365 } 1366 1367 /* 1368 * Shared implementation to determine the zoneid associated with an IPv4/IPv6 1369 * address 1370 */ 1371 static int 1372 ip_getlifzone_impl(sa_family_t family, phy_if_t phy_ifdata, lif_if_t ifdata, 1373 ip_stack_t *ipst, zoneid_t *zoneid) 1374 { 1375 ipif_t *ipif; 1376 1377 ipif = ipif_getby_indexes((uint_t)phy_ifdata, 1378 UNMAP_IPIF_ID((uint_t)ifdata), (family == AF_INET6), ipst); 1379 if (ipif == NULL) 1380 return (-1); 1381 *zoneid = IP_REAL_ZONEID(ipif->ipif_zoneid, ipst); 1382 ipif_refrele(ipif); 1383 return (0); 1384 } 1385 1386 /* 1387 * Determine the zoneid associated with an IPv4 address 1388 */ 1389 static int 1390 ip_getlifzone(net_handle_t neti, phy_if_t phy_ifdata, lif_if_t ifdata, 1391 zoneid_t *zoneid) 1392 { 1393 return (ip_getlifzone_impl(AF_INET, phy_ifdata, ifdata, 1394 neti->netd_stack->nts_netstack->netstack_ip, zoneid)); 1395 } 1396 1397 /* 1398 * Determine the zoneid associated with an IPv6 address 1399 */ 1400 static int 1401 ipv6_getlifzone(net_handle_t neti, phy_if_t phy_ifdata, lif_if_t ifdata, 1402 zoneid_t *zoneid) 1403 { 1404 return (ip_getlifzone_impl(AF_INET6, phy_ifdata, ifdata, 1405 neti->netd_stack->nts_netstack->netstack_ip, zoneid)); 1406 } 1407 1408 /* 1409 * The behaviour here mirrors that for the SIOCFLIFFLAGS ioctl where the 1410 * union of all of the relevant flags is returned. 1411 */ 1412 static int 1413 ip_getlifflags_impl(sa_family_t family, phy_if_t phy_ifdata, lif_if_t ifdata, 1414 ip_stack_t *ipst, uint64_t *flags) 1415 { 1416 phyint_t *phyi; 1417 ipif_t *ipif; 1418 ill_t *ill; 1419 1420 ill = ill_lookup_on_ifindex(phy_ifdata, (family == AF_INET6), ipst); 1421 if (ill == NULL) 1422 return (-1); 1423 phyi = ill->ill_phyint; 1424 1425 ipif = ipif_getby_indexes((uint_t)phy_ifdata, 1426 UNMAP_IPIF_ID((uint_t)ifdata), (family == AF_INET6), ipst); 1427 if (ipif == NULL) { 1428 ill_refrele(ill); 1429 return (-1); 1430 } 1431 *flags = ipif->ipif_flags | ill->ill_flags | phyi->phyint_flags; 1432 ipif_refrele(ipif); 1433 ill_refrele(ill); 1434 return (0); 1435 } 1436 1437 static int 1438 ip_getlifflags(net_handle_t neti, phy_if_t phy_ifdata, lif_if_t ifdata, 1439 uint64_t *flags) 1440 { 1441 return (ip_getlifflags_impl(AF_INET, phy_ifdata, ifdata, 1442 neti->netd_stack->nts_netstack->netstack_ip, flags)); 1443 } 1444 1445 static int 1446 ipv6_getlifflags(net_handle_t neti, phy_if_t phy_ifdata, lif_if_t ifdata, 1447 uint64_t *flags) 1448 { 1449 return (ip_getlifflags_impl(AF_INET6, phy_ifdata, ifdata, 1450 neti->netd_stack->nts_netstack->netstack_ip, flags)); 1451 } 1452 1453 /* 1454 * Deliver packet up into the kernel, immitating its reception by a 1455 * network interface. 1456 */ 1457 static void 1458 ip_ni_queue_in_func(void *inject) 1459 { 1460 ip_ni_queue_func_impl(inject, B_FALSE); 1461 } 1462 1463 /* 1464 * Deliver out of the kernel, as if it were being sent via a 1465 * raw socket so that IPFilter will see it again. 1466 */ 1467 static void 1468 ip_ni_queue_out_func(void *inject) 1469 { 1470 ip_ni_queue_func_impl(inject, B_TRUE); 1471 } 1472 1473 /* 1474 * Shared implementation for inject via ip_output and ip_input 1475 */ 1476 static void 1477 ip_ni_queue_func_impl(injection_t *inject, boolean_t out) 1478 { 1479 net_inject_t *packet; 1480 ill_t *ill; 1481 ip_stack_t *ipst = (ip_stack_t *)inject->inj_ptr; 1482 ip_xmit_attr_t ixas; 1483 1484 ASSERT(inject != NULL); 1485 packet = &inject->inj_data; 1486 ASSERT(packet->ni_packet != NULL); 1487 1488 if (out == 0) { 1489 ill = ill_lookup_on_ifindex((uint_t)packet->ni_physical, 1490 inject->inj_isv6, ipst); 1491 1492 if (ill == NULL) { 1493 kmem_free(inject, sizeof (*inject)); 1494 return; 1495 } 1496 1497 if (inject->inj_isv6) { 1498 ip_input_v6(ill, NULL, packet->ni_packet, NULL); 1499 } else { 1500 ip_input(ill, NULL, packet->ni_packet, NULL); 1501 } 1502 ill_refrele(ill); 1503 } else { 1504 bzero(&ixas, sizeof (ixas)); 1505 ixas.ixa_ifindex = packet->ni_physical; 1506 ixas.ixa_ipst = ipst; 1507 if (inject->inj_isv6) { 1508 ixas.ixa_flags = IXAF_BASIC_SIMPLE_V6; 1509 } else { 1510 ixas.ixa_flags = IXAF_BASIC_SIMPLE_V4; 1511 } 1512 (void) ip_output_simple(packet->ni_packet, &ixas); 1513 ixa_cleanup(&ixas); 1514 } 1515 1516 kmem_free(inject, sizeof (*inject)); 1517 } 1518 1519 /* 1520 * taskq function for nic events. 1521 */ 1522 void 1523 ip_ne_queue_func(void *arg) 1524 { 1525 hook_event_token_t hr; 1526 hook_nic_event_int_t *info = (hook_nic_event_int_t *)arg; 1527 ip_stack_t *ipst; 1528 netstack_t *ns; 1529 1530 ns = netstack_find_by_stackid(info->hnei_stackid); 1531 if (ns == NULL) 1532 goto done; 1533 1534 ipst = ns->netstack_ip; 1535 if (ipst == NULL) 1536 goto done; 1537 1538 hr = (info->hnei_event.hne_protocol == ipst->ips_ipv6_net_data) ? 1539 ipst->ips_ipv6nicevents : ipst->ips_ipv4nicevents; 1540 (void) hook_run(info->hnei_event.hne_protocol->netd_hooks, hr, 1541 (hook_data_t)&info->hnei_event); 1542 1543 done: 1544 if (ns != NULL) 1545 netstack_rele(ns); 1546 kmem_free(info->hnei_event.hne_data, info->hnei_event.hne_datalen); 1547 kmem_free(arg, sizeof (hook_nic_event_int_t)); 1548 } 1549 1550 /* 1551 * Initialize ARP hook family and events 1552 */ 1553 void 1554 arp_hook_init(ip_stack_t *ipst) 1555 { 1556 HOOK_FAMILY_INIT(&ipst->ips_arproot, Hn_ARP); 1557 if (net_family_register(ipst->ips_arp_net_data, &ipst->ips_arproot) 1558 != 0) { 1559 cmn_err(CE_NOTE, "arp_hook_init" 1560 "net_family_register failed for arp"); 1561 } 1562 1563 HOOK_EVENT_INIT(&ipst->ips_arp_physical_in_event, NH_PHYSICAL_IN); 1564 ipst->ips_arp_physical_in = net_event_register(ipst->ips_arp_net_data, 1565 &ipst->ips_arp_physical_in_event); 1566 if (ipst->ips_arp_physical_in == NULL) { 1567 cmn_err(CE_NOTE, "arp_hook_init: " 1568 "net_event_register failed for arp/physical_in"); 1569 } 1570 1571 HOOK_EVENT_INIT(&ipst->ips_arp_physical_out_event, NH_PHYSICAL_OUT); 1572 ipst->ips_arp_physical_out = net_event_register(ipst->ips_arp_net_data, 1573 &ipst->ips_arp_physical_out_event); 1574 if (ipst->ips_arp_physical_out == NULL) { 1575 cmn_err(CE_NOTE, "arp_hook_init: " 1576 "net_event_register failed for arp/physical_out"); 1577 } 1578 1579 HOOK_EVENT_INIT(&ipst->ips_arp_nic_events, NH_NIC_EVENTS); 1580 ipst->ips_arpnicevents = net_event_register(ipst->ips_arp_net_data, 1581 &ipst->ips_arp_nic_events); 1582 if (ipst->ips_arpnicevents == NULL) { 1583 cmn_err(CE_NOTE, "arp_hook_init: " 1584 "net_event_register failed for arp/nic_events"); 1585 } 1586 } 1587 1588 void 1589 arp_hook_destroy(ip_stack_t *ipst) 1590 { 1591 if (ipst->ips_arpnicevents != NULL) { 1592 if (net_event_unregister(ipst->ips_arp_net_data, 1593 &ipst->ips_arp_nic_events) == 0) 1594 ipst->ips_arpnicevents = NULL; 1595 } 1596 1597 if (ipst->ips_arp_physical_out != NULL) { 1598 if (net_event_unregister(ipst->ips_arp_net_data, 1599 &ipst->ips_arp_physical_out_event) == 0) 1600 ipst->ips_arp_physical_out = NULL; 1601 } 1602 1603 if (ipst->ips_arp_physical_in != NULL) { 1604 if (net_event_unregister(ipst->ips_arp_net_data, 1605 &ipst->ips_arp_physical_in_event) == 0) 1606 ipst->ips_arp_physical_in = NULL; 1607 } 1608 1609 (void) net_family_unregister(ipst->ips_arp_net_data, 1610 &ipst->ips_arproot); 1611 } 1612 1613 void 1614 arp_hook_shutdown(ip_stack_t *ipst) 1615 { 1616 if (ipst->ips_arp_physical_in != NULL) { 1617 (void) net_event_shutdown(ipst->ips_arp_net_data, 1618 &ipst->ips_arp_physical_in_event); 1619 } 1620 if (ipst->ips_arp_physical_out != NULL) { 1621 (void) net_event_shutdown(ipst->ips_arp_net_data, 1622 &ipst->ips_arp_physical_out_event); 1623 } 1624 if (ipst->ips_arpnicevents != NULL) { 1625 (void) net_event_shutdown(ipst->ips_arp_net_data, 1626 &ipst->ips_arp_nic_events); 1627 } 1628 } 1629 1630 /* netinfo routines for the unsupported cases */ 1631 1632 /* ARGSUSED */ 1633 int 1634 net_no_getmtu(net_handle_t handle, phy_if_t phy_ifdata, lif_if_t ifdata) 1635 { 1636 return (-1); 1637 } 1638 1639 /* ARGSUSED */ 1640 static int 1641 net_no_getpmtuenabled(net_handle_t neti) 1642 { 1643 return (-1); 1644 } 1645 1646 /* ARGSUSED */ 1647 static lif_if_t 1648 net_no_lifgetnext(net_handle_t neti, phy_if_t phy_ifdata, lif_if_t ifdata) 1649 { 1650 return (-1); 1651 } 1652 1653 /* ARGSUSED */ 1654 static int 1655 net_no_inject(net_handle_t neti, inject_t style, net_inject_t *packet) 1656 { 1657 return (-1); 1658 } 1659 1660 /* ARGSUSED */ 1661 static phy_if_t 1662 net_no_routeto(net_handle_t neti, struct sockaddr *address, 1663 struct sockaddr *next) 1664 { 1665 return ((phy_if_t)-1); 1666 } 1667 1668 /* ARGSUSED */ 1669 static int 1670 net_no_ispartialchecksum(net_handle_t neti, mblk_t *mp) 1671 { 1672 return (-1); 1673 } 1674 1675 /* ARGSUSED */ 1676 static int 1677 net_no_getlifaddr(net_handle_t neti, phy_if_t phy_ifdata, lif_if_t ifdata, 1678 size_t nelem, net_ifaddr_t type[], void *storage) 1679 { 1680 return (-1); 1681 } 1682 1683 /* ARGSUSED */ 1684 static int 1685 net_no_getlifzone(net_handle_t neti, phy_if_t phy_ifdata, lif_if_t ifdata, 1686 zoneid_t *zoneid) 1687 { 1688 return (-1); 1689 } 1690 1691 /* ARGSUSED */ 1692 static int 1693 net_no_getlifflags(net_handle_t neti, phy_if_t phy_ifdata, lif_if_t ifdata, 1694 uint64_t *flags) 1695 { 1696 return (-1); 1697 } 1698