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