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, zoneid, 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, zoneid, 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 zoneid_t zoneid; 1088 1089 zoneid = netstackid_to_zoneid(ipst->ips_netstack->netstack_stackid); 1090 1091 if (address->sa_family == AF_INET6) { 1092 ire = ire_route_lookup_v6(&sin6->sin6_addr, NULL, 1093 0, 0, NULL, &sire, zoneid, NULL, 1094 MATCH_IRE_DSTONLY|MATCH_IRE_DEFAULT|MATCH_IRE_RECURSIVE, 1095 ipst); 1096 } else { 1097 ire = ire_route_lookup(sin->sin_addr.s_addr, 0, 1098 0, 0, NULL, &sire, zoneid, NULL, 1099 MATCH_IRE_DSTONLY|MATCH_IRE_DEFAULT|MATCH_IRE_RECURSIVE, 1100 ipst); 1101 } 1102 1103 if (ire == NULL) 1104 return (0); 1105 1106 /* 1107 * For some destinations, we have routes that are dead ends, so 1108 * return to indicate that no physical interface can be used to 1109 * reach the destination. 1110 */ 1111 if ((ire->ire_flags & (RTF_REJECT | RTF_BLACKHOLE)) != 0) { 1112 if (sire != NULL) 1113 ire_refrele(sire); 1114 ire_refrele(ire); 1115 return (0); 1116 } 1117 1118 ill = ire_to_ill(ire); 1119 if (ill == NULL) { 1120 if (sire != NULL) 1121 ire_refrele(sire); 1122 ire_refrele(ire); 1123 return (0); 1124 } 1125 1126 if (nexthop != NULL) { 1127 if (address->sa_family == AF_INET6) { 1128 next->sin_addr.s_addr = sire ? sire->ire_gateway_addr : 1129 sin->sin_addr.s_addr; 1130 } else { 1131 next6->sin6_addr = sire ? sire->ire_gateway_addr_v6 : 1132 sin6->sin6_addr; 1133 } 1134 } 1135 1136 ASSERT(ill != NULL); 1137 phy_if = (phy_if_t)ill->ill_phyint->phyint_ifindex; 1138 if (sire != NULL) 1139 ire_refrele(sire); 1140 ire_refrele(ire); 1141 1142 return (phy_if); 1143 } 1144 1145 /* 1146 * Determine if checksumming is being used for the given packet. 1147 * 1148 * Return value: 1149 * NET_HCK_NONE: full checksum recalculation is required 1150 * NET_HCK_L3_FULL: full layer 3 checksum 1151 * NET_HCK_L4_FULL: full layer 4 checksum 1152 * NET_HCK_L4_PART: partial layer 4 checksum 1153 */ 1154 /*ARGSUSED*/ 1155 static int 1156 ip_ispartialchecksum(net_handle_t neti, mblk_t *mp) 1157 { 1158 int ret = 0; 1159 1160 ASSERT(mp != NULL); 1161 1162 if ((DB_CKSUMFLAGS(mp) & HCK_FULLCKSUM) != 0) { 1163 ret |= (int)NET_HCK_L4_FULL; 1164 if ((DB_CKSUMFLAGS(mp) & HCK_IPV4_HDRCKSUM) != 0) 1165 ret |= (int)NET_HCK_L3_FULL; 1166 } 1167 if ((DB_CKSUMFLAGS(mp) & HCK_PARTIALCKSUM) != 0) { 1168 ret |= (int)NET_HCK_L4_PART; 1169 if ((DB_CKSUMFLAGS(mp) & HCK_IPV4_HDRCKSUM) != 0) 1170 ret |= (int)NET_HCK_L3_FULL; 1171 } 1172 1173 return (ret); 1174 } 1175 1176 /* 1177 * Return true or false, indicating whether the network and transport 1178 * headers are correct. Use the capabilities flags and flags set in the 1179 * dblk_t to determine whether or not the checksum is valid. 1180 * 1181 * Return: 1182 * 0: the checksum was incorrect 1183 * 1: the original checksum was correct 1184 */ 1185 /*ARGSUSED*/ 1186 static int 1187 ip_isvalidchecksum(net_handle_t neti, mblk_t *mp) 1188 { 1189 unsigned char *wptr; 1190 ipha_t *ipha = (ipha_t *)mp->b_rptr; 1191 int hlen; 1192 int ret; 1193 1194 ASSERT(mp != NULL); 1195 1196 if (dohwcksum && 1197 DB_CKSUM16(mp) != 0xFFFF && 1198 (DB_CKSUMFLAGS(mp) & HCK_FULLCKSUM) && 1199 (DB_CKSUMFLAGS(mp) & HCK_FULLCKSUM_OK) && 1200 (DB_CKSUMFLAGS(mp) & HCK_IPV4_HDRCKSUM)) 1201 return (1); 1202 1203 hlen = (ipha->ipha_version_and_hdr_length & 0x0F) << 2; 1204 1205 /* 1206 * Check that the mblk being passed in has enough data in it 1207 * before blindly checking ip_cksum. 1208 */ 1209 if (msgdsize(mp) < hlen) 1210 return (0); 1211 1212 if (mp->b_wptr < mp->b_rptr + hlen) { 1213 if (pullupmsg(mp, hlen) == 0) 1214 return (0); 1215 wptr = mp->b_wptr; 1216 } else { 1217 wptr = mp->b_wptr; 1218 mp->b_wptr = mp->b_rptr + hlen; 1219 } 1220 1221 if (ipha->ipha_hdr_checksum == ip_cksum(mp, 0, ipha->ipha_hdr_checksum)) 1222 ret = 1; 1223 else 1224 ret = 0; 1225 mp->b_wptr = wptr; 1226 1227 return (ret); 1228 } 1229 1230 /* 1231 * Unsupported with IPv6 1232 */ 1233 /*ARGSUSED*/ 1234 static int 1235 ipv6_isvalidchecksum(net_handle_t neti, mblk_t *mp) 1236 { 1237 return (-1); 1238 } 1239 1240 /* 1241 * Determine the network addresses for an IPv4 interface 1242 */ 1243 static int 1244 ip_getlifaddr(net_handle_t neti, phy_if_t phy_ifdata, lif_if_t ifdata, 1245 size_t nelem, net_ifaddr_t type[], void *storage) 1246 { 1247 netstack_t *ns; 1248 1249 ns = neti->netd_stack->nts_netstack; 1250 ASSERT(ns != NULL); 1251 return (ip_getlifaddr_impl(AF_INET, phy_ifdata, ifdata, 1252 nelem, type, storage, ns->netstack_ip)); 1253 } 1254 1255 /* 1256 * Determine the network addresses for an IPv6 interface 1257 */ 1258 static int 1259 ipv6_getlifaddr(net_handle_t neti, phy_if_t phy_ifdata, lif_if_t ifdata, 1260 size_t nelem, net_ifaddr_t type[], void *storage) 1261 { 1262 netstack_t *ns; 1263 1264 ns = neti->netd_stack->nts_netstack; 1265 ASSERT(ns != NULL); 1266 return (ip_getlifaddr_impl(AF_INET6, phy_ifdata, ifdata, 1267 nelem, type, storage, ns->netstack_ip)); 1268 } 1269 1270 /* 1271 * Shared implementation to determine the network addresses for an interface 1272 */ 1273 /* ARGSUSED */ 1274 static int 1275 ip_getlifaddr_impl(sa_family_t family, phy_if_t phy_ifdata, 1276 lif_if_t ifdata, size_t nelem, net_ifaddr_t type[], 1277 struct sockaddr *storage, ip_stack_t *ipst) 1278 { 1279 struct sockaddr_in6 *sin6; 1280 struct sockaddr_in *sin; 1281 lif_if_t ipifid; 1282 ipif_t *ipif; 1283 int i; 1284 1285 ASSERT(type != NULL); 1286 ASSERT(storage != NULL); 1287 1288 ipifid = UNMAP_IPIF_ID(ifdata); 1289 1290 if (family == AF_INET) { 1291 if ((ipif = ipif_getby_indexes((uint_t)phy_ifdata, 1292 (uint_t)ipifid, B_FALSE, ipst)) == NULL) 1293 return (1); 1294 1295 sin = (struct sockaddr_in *)storage; 1296 for (i = 0; i < nelem; i++, sin++) { 1297 if (ip_getifaddr_type(AF_INET, ipif, type[i], 1298 &sin->sin_addr) < 0) { 1299 ip2dbg(("ip_getlifaddr_impl failed type %d\n", 1300 type[i])); 1301 ipif_refrele(ipif); 1302 return (1); 1303 } 1304 sin->sin_family = AF_INET; 1305 } 1306 } else { 1307 if ((ipif = ipif_getby_indexes((uint_t)phy_ifdata, 1308 (uint_t)ipifid, B_TRUE, ipst)) == NULL) 1309 return (1); 1310 1311 sin6 = (struct sockaddr_in6 *)storage; 1312 for (i = 0; i < nelem; i++, sin6++) { 1313 if (ip_getifaddr_type(AF_INET6, ipif, type[i], 1314 &sin6->sin6_addr) < 0) { 1315 ip2dbg(("ip_getlifaddr_impl failed type %d\n", 1316 type[i])); 1317 ipif_refrele(ipif); 1318 return (1); 1319 } 1320 sin6->sin6_family = AF_INET6; 1321 } 1322 } 1323 ipif_refrele(ipif); 1324 return (0); 1325 } 1326 1327 /* 1328 * ip_getlifaddr private function 1329 */ 1330 static int 1331 ip_getifaddr_type(sa_family_t family, ipif_t *ill_ipif, 1332 lif_if_t type, void *storage) 1333 { 1334 void *src_addr; 1335 int mem_size; 1336 1337 ASSERT(ill_ipif != NULL); 1338 ASSERT(storage != NULL); 1339 1340 if (family == AF_INET) { 1341 mem_size = sizeof (struct in_addr); 1342 1343 switch (type) { 1344 case NA_ADDRESS: 1345 src_addr = &(ill_ipif->ipif_lcl_addr); 1346 break; 1347 case NA_PEER: 1348 src_addr = &(ill_ipif->ipif_pp_dst_addr); 1349 break; 1350 case NA_BROADCAST: 1351 src_addr = &(ill_ipif->ipif_brd_addr); 1352 break; 1353 case NA_NETMASK: 1354 src_addr = &(ill_ipif->ipif_net_mask); 1355 break; 1356 default: 1357 return (-1); 1358 /*NOTREACHED*/ 1359 } 1360 } else { 1361 mem_size = sizeof (struct in6_addr); 1362 1363 switch (type) { 1364 case NA_ADDRESS: 1365 src_addr = &(ill_ipif->ipif_v6lcl_addr); 1366 break; 1367 case NA_PEER: 1368 src_addr = &(ill_ipif->ipif_v6pp_dst_addr); 1369 break; 1370 case NA_BROADCAST: 1371 src_addr = &(ill_ipif->ipif_v6brd_addr); 1372 break; 1373 case NA_NETMASK: 1374 src_addr = &(ill_ipif->ipif_v6net_mask); 1375 break; 1376 default: 1377 return (-1); 1378 /*NOTREACHED*/ 1379 } 1380 } 1381 1382 (void) memcpy(storage, src_addr, mem_size); 1383 return (1); 1384 } 1385 1386 /* 1387 * Shared implementation to determine the zoneid associated with an IPv4/IPv6 1388 * address 1389 */ 1390 static int 1391 ip_getlifzone_impl(sa_family_t family, phy_if_t phy_ifdata, lif_if_t ifdata, 1392 ip_stack_t *ipst, zoneid_t *zoneid) 1393 { 1394 ipif_t *ipif; 1395 1396 ipif = ipif_getby_indexes((uint_t)phy_ifdata, 1397 UNMAP_IPIF_ID((uint_t)ifdata), (family == AF_INET6), ipst); 1398 if (ipif == NULL) 1399 return (-1); 1400 *zoneid = IP_REAL_ZONEID(ipif->ipif_zoneid, ipst); 1401 ipif_refrele(ipif); 1402 return (0); 1403 } 1404 1405 /* 1406 * Determine the zoneid associated with an IPv4 address 1407 */ 1408 static int 1409 ip_getlifzone(net_handle_t neti, phy_if_t phy_ifdata, lif_if_t ifdata, 1410 zoneid_t *zoneid) 1411 { 1412 return (ip_getlifzone_impl(AF_INET, phy_ifdata, ifdata, 1413 neti->netd_stack->nts_netstack->netstack_ip, zoneid)); 1414 } 1415 1416 /* 1417 * Determine the zoneid associated with an IPv6 address 1418 */ 1419 static int 1420 ipv6_getlifzone(net_handle_t neti, phy_if_t phy_ifdata, lif_if_t ifdata, 1421 zoneid_t *zoneid) 1422 { 1423 return (ip_getlifzone_impl(AF_INET6, phy_ifdata, ifdata, 1424 neti->netd_stack->nts_netstack->netstack_ip, zoneid)); 1425 } 1426 1427 static int 1428 ip_getlifflags_impl(sa_family_t family, phy_if_t phy_ifdata, lif_if_t ifdata, 1429 ip_stack_t *ipst, uint64_t *flags) 1430 { 1431 ipif_t *ipif; 1432 1433 ipif = ipif_getby_indexes((uint_t)phy_ifdata, 1434 UNMAP_IPIF_ID((uint_t)ifdata), (family == AF_INET6), ipst); 1435 if (ipif == NULL) 1436 return (-1); 1437 *flags = ipif->ipif_flags; 1438 ipif_refrele(ipif); 1439 return (0); 1440 } 1441 1442 static int 1443 ip_getlifflags(net_handle_t neti, phy_if_t phy_ifdata, lif_if_t ifdata, 1444 uint64_t *flags) 1445 { 1446 return (ip_getlifflags_impl(AF_INET, phy_ifdata, ifdata, 1447 neti->netd_stack->nts_netstack->netstack_ip, flags)); 1448 } 1449 1450 static int 1451 ipv6_getlifflags(net_handle_t neti, phy_if_t phy_ifdata, lif_if_t ifdata, 1452 uint64_t *flags) 1453 { 1454 return (ip_getlifflags_impl(AF_INET6, phy_ifdata, ifdata, 1455 neti->netd_stack->nts_netstack->netstack_ip, flags)); 1456 } 1457 1458 /* 1459 * Deliver packet up into the kernel, immitating its reception by a 1460 * network interface. 1461 */ 1462 static void 1463 ip_ni_queue_in_func(void *inject) 1464 { 1465 ip_ni_queue_func_impl(inject, B_FALSE); 1466 } 1467 1468 /* 1469 * Deliver out of the kernel, as if it were being sent via a 1470 * raw socket so that IPFilter will see it again. 1471 */ 1472 static void 1473 ip_ni_queue_out_func(void *inject) 1474 { 1475 ip_ni_queue_func_impl(inject, B_TRUE); 1476 } 1477 1478 /* 1479 * Shared implementation for inject via ip_output and ip_input 1480 */ 1481 static void 1482 ip_ni_queue_func_impl(injection_t *inject, boolean_t out) 1483 { 1484 net_inject_t *packet; 1485 conn_t *conn; 1486 ill_t *ill; 1487 ip_stack_t *ipst = (ip_stack_t *)inject->inj_ptr; 1488 1489 ASSERT(inject != NULL); 1490 packet = &inject->inj_data; 1491 ASSERT(packet->ni_packet != NULL); 1492 1493 ill = ill_lookup_on_ifindex((uint_t)packet->ni_physical, 1494 B_FALSE, NULL, NULL, NULL, NULL, ipst); 1495 if (ill == NULL) { 1496 kmem_free(inject, sizeof (*inject)); 1497 return; 1498 } 1499 1500 if (out == 0) { 1501 if (inject->inj_isv6) { 1502 ip_rput_v6(ill->ill_rq, packet->ni_packet); 1503 } else { 1504 ip_input(ill, NULL, packet->ni_packet, NULL); 1505 } 1506 kmem_free(inject, sizeof (*inject)); 1507 ill_refrele(ill); 1508 return; 1509 } 1510 1511 /* 1512 * Even though ipcl_conn_create requests that it be passed 1513 * a different value for "TCP", in this case there may not 1514 * be a TCP connection backing the packet and more than 1515 * likely, non-TCP packets will go here too. 1516 */ 1517 conn = ipcl_conn_create(IPCL_IPCCONN, KM_NOSLEEP, ipst->ips_netstack); 1518 if (conn != NULL) { 1519 if (inject->inj_isv6) { 1520 conn->conn_flags |= IPCL_ISV6; 1521 conn->conn_af_isv6 = B_TRUE; 1522 conn->conn_src_preferences = IPV6_PREFER_SRC_DEFAULT; 1523 conn->conn_multicast_loop = IP_DEFAULT_MULTICAST_LOOP; 1524 ip_output_v6(conn, packet->ni_packet, ill->ill_wq, 1525 IP_WPUT); 1526 } else { 1527 conn->conn_af_isv6 = B_FALSE; 1528 conn->conn_pkt_isv6 = B_FALSE; 1529 conn->conn_multicast_loop = IP_DEFAULT_MULTICAST_LOOP; 1530 ip_output(conn, packet->ni_packet, ill->ill_wq, 1531 IP_WPUT); 1532 } 1533 1534 CONN_DEC_REF(conn); 1535 } 1536 1537 kmem_free(inject, sizeof (*inject)); 1538 ill_refrele(ill); 1539 } 1540 1541 /* 1542 * taskq function for nic events. 1543 */ 1544 void 1545 ip_ne_queue_func(void *arg) 1546 { 1547 hook_event_token_t hr; 1548 hook_nic_event_int_t *info = (hook_nic_event_int_t *)arg; 1549 ip_stack_t *ipst; 1550 netstack_t *ns; 1551 1552 ns = netstack_find_by_stackid(info->hnei_stackid); 1553 if (ns == NULL) 1554 goto done; 1555 1556 ipst = ns->netstack_ip; 1557 if (ipst == NULL) 1558 goto done; 1559 1560 hr = (info->hnei_event.hne_protocol == ipst->ips_ipv6_net_data) ? 1561 ipst->ips_ipv6nicevents : ipst->ips_ipv4nicevents; 1562 (void) hook_run(info->hnei_event.hne_protocol->netd_hooks, hr, 1563 (hook_data_t)&info->hnei_event); 1564 1565 done: 1566 if (ns != NULL) 1567 netstack_rele(ns); 1568 kmem_free(info->hnei_event.hne_data, info->hnei_event.hne_datalen); 1569 kmem_free(arg, sizeof (hook_nic_event_int_t)); 1570 } 1571