1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #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 char *name; 572 573 ASSERT(buffer != NULL); 574 575 ill = ill_lookup_on_ifindex((uint_t)phy_ifdata, isv6, NULL, NULL, 576 NULL, NULL, ipst); 577 if (ill != NULL) { 578 name = ill->ill_name; 579 } else { 580 /* Fallback to group names only if hook_emulation is set */ 581 if (ipst->ips_ipmp_hook_emulation) { 582 ill = ill_group_lookup_on_ifindex((uint_t)phy_ifdata, 583 isv6, ipst); 584 } 585 if (ill == NULL) 586 return (1); 587 name = ill->ill_phyint->phyint_groupname; 588 } 589 if (name != NULL) { 590 (void) strlcpy(buffer, name, buflen); 591 ill_refrele(ill); 592 return (0); 593 } else { 594 ill_refrele(ill); 595 return (1); 596 } 597 598 } 599 600 /* 601 * Determine the MTU of an IPv4 network interface 602 */ 603 static int 604 ip_getmtu(net_handle_t neti, phy_if_t phy_ifdata, lif_if_t ifdata) 605 { 606 netstack_t *ns; 607 608 ns = neti->netd_stack->nts_netstack; 609 ASSERT(ns != NULL); 610 return (ip_getmtu_impl(phy_ifdata, ifdata, B_FALSE, ns->netstack_ip)); 611 } 612 613 /* 614 * Determine the MTU of an IPv6 network interface 615 */ 616 static int 617 ipv6_getmtu(net_handle_t neti, phy_if_t phy_ifdata, lif_if_t ifdata) 618 { 619 netstack_t *ns; 620 621 ns = neti->netd_stack->nts_netstack; 622 ASSERT(ns != NULL); 623 return (ip_getmtu_impl(phy_ifdata, ifdata, B_TRUE, ns->netstack_ip)); 624 } 625 626 /* 627 * Shared implementation to determine the MTU of a network interface 628 * 629 * Note: this does not handle a non-zero ifdata when ipmp_hook_emulation is set. 630 * But IP Filter only uses a zero ifdata. 631 */ 632 /* ARGSUSED */ 633 static int 634 ip_getmtu_impl(phy_if_t phy_ifdata, lif_if_t ifdata, boolean_t isv6, 635 ip_stack_t *ipst) 636 { 637 lif_if_t ipifid; 638 ipif_t *ipif; 639 int mtu; 640 641 ipifid = UNMAP_IPIF_ID(ifdata); 642 643 ipif = ipif_getby_indexes((uint_t)phy_ifdata, (uint_t)ipifid, 644 isv6, ipst); 645 if (ipif == NULL) 646 return (0); 647 648 mtu = ipif->ipif_mtu; 649 ipif_refrele(ipif); 650 651 if (mtu == 0) { 652 ill_t *ill; 653 654 if ((ill = ill_lookup_on_ifindex((uint_t)phy_ifdata, isv6, 655 NULL, NULL, NULL, NULL, ipst)) == NULL) { 656 /* 657 * Fallback to group names only if hook_emulation 658 * is set 659 */ 660 if (ipst->ips_ipmp_hook_emulation) { 661 ill = ill_group_lookup_on_ifindex( 662 (uint_t)phy_ifdata, isv6, ipst); 663 } 664 if (ill == NULL) 665 return (0); 666 } 667 mtu = ill->ill_max_frag; 668 ill_refrele(ill); 669 } 670 671 return (mtu); 672 } 673 674 /* 675 * Determine if path MTU discovery is enabled for IP 676 */ 677 static int 678 ip_getpmtuenabled(net_handle_t neti) 679 { 680 netstack_t *ns; 681 682 ns = neti->netd_stack->nts_netstack; 683 ASSERT(ns != NULL); 684 return (ns->netstack_ip->ips_ip_path_mtu_discovery); 685 } 686 687 /* 688 * Get next interface from the current list of IPv4 physical network interfaces 689 * 690 * Note: this does not handle the case when ipmp_hook_emulation is set. 691 * But IP Filter does not use this function. 692 */ 693 static phy_if_t 694 ip_phygetnext(net_handle_t neti, phy_if_t phy_ifdata) 695 { 696 netstack_t *ns; 697 698 ns = neti->netd_stack->nts_netstack; 699 ASSERT(ns != NULL); 700 return (ill_get_next_ifindex(phy_ifdata, B_FALSE, ns->netstack_ip)); 701 } 702 703 /* 704 * Get next interface from the current list of IPv6 physical network interfaces 705 */ 706 static phy_if_t 707 ipv6_phygetnext(net_handle_t neti, phy_if_t phy_ifdata) 708 { 709 netstack_t *ns; 710 711 ns = neti->netd_stack->nts_netstack; 712 ASSERT(ns != NULL); 713 return (ill_get_next_ifindex(phy_ifdata, B_TRUE, ns->netstack_ip)); 714 } 715 716 /* 717 * Determine if a network interface name exists for IPv4 718 */ 719 static phy_if_t 720 ip_phylookup(net_handle_t neti, const char *name) 721 { 722 netstack_t *ns; 723 724 ns = neti->netd_stack->nts_netstack; 725 ASSERT(ns != NULL); 726 return (ip_phylookup_impl(name, B_FALSE, ns->netstack_ip)); 727 } 728 729 /* 730 * Determine if a network interface name exists for IPv6 731 */ 732 static phy_if_t 733 ipv6_phylookup(net_handle_t neti, const char *name) 734 { 735 netstack_t *ns; 736 737 ns = neti->netd_stack->nts_netstack; 738 ASSERT(ns != NULL); 739 return (ip_phylookup_impl(name, B_TRUE, ns->netstack_ip)); 740 } 741 742 /* 743 * Implement looking up an ill_t based on the name supplied and matching 744 * it up with either IPv4 or IPv6. ill_get_ifindex_by_name() is not used 745 * because it does not match on the address family in addition to the name. 746 */ 747 static phy_if_t 748 ip_phylookup_impl(const char *name, boolean_t isv6, ip_stack_t *ipst) 749 { 750 phy_if_t phy; 751 ill_t *ill; 752 753 ill = ill_lookup_on_name((char *)name, B_FALSE, isv6, NULL, NULL, 754 NULL, NULL, NULL, ipst); 755 756 /* Fallback to group names only if hook_emulation is set */ 757 if (ill == NULL && ipst->ips_ipmp_hook_emulation) { 758 ill = ill_group_lookup_on_name((char *)name, isv6, ipst); 759 } 760 if (ill == NULL) 761 return (0); 762 763 phy = ill->ill_phyint->phyint_hook_ifindex; 764 765 ill_refrele(ill); 766 767 return (phy); 768 } 769 770 /* 771 * Get next interface from the current list of IPv4 logical network interfaces 772 */ 773 static lif_if_t 774 ip_lifgetnext(net_handle_t neti, phy_if_t phy_ifdata, lif_if_t ifdata) 775 { 776 netstack_t *ns; 777 778 ns = neti->netd_stack->nts_netstack; 779 ASSERT(ns != NULL); 780 return (ip_lifgetnext_impl(phy_ifdata, ifdata, B_FALSE, 781 ns->netstack_ip)); 782 } 783 784 /* 785 * Get next interface from the current list of IPv6 logical network interfaces 786 */ 787 static lif_if_t 788 ipv6_lifgetnext(net_handle_t neti, phy_if_t phy_ifdata, lif_if_t ifdata) 789 { 790 netstack_t *ns; 791 792 ns = neti->netd_stack->nts_netstack; 793 ASSERT(ns != NULL); 794 return (ip_lifgetnext_impl(phy_ifdata, ifdata, B_TRUE, 795 ns->netstack_ip)); 796 } 797 798 /* 799 * Shared implementation to get next interface from the current list of 800 * logical network interfaces 801 * 802 * Note: this does not handle the case when ipmp_hook_emulation is set. 803 * But IP Filter does not use this function. 804 */ 805 static lif_if_t 806 ip_lifgetnext_impl(phy_if_t phy_ifdata, lif_if_t ifdata, boolean_t isv6, 807 ip_stack_t *ipst) 808 { 809 lif_if_t newidx, oldidx; 810 boolean_t nextok; 811 ipif_t *ipif; 812 ill_t *ill; 813 814 ill = ill_lookup_on_ifindex(phy_ifdata, isv6, NULL, NULL, 815 NULL, NULL, ipst); 816 if (ill == NULL) 817 return (0); 818 819 if (ifdata != 0) { 820 oldidx = UNMAP_IPIF_ID(ifdata); 821 nextok = B_FALSE; 822 } else { 823 oldidx = 0; 824 nextok = B_TRUE; 825 } 826 827 mutex_enter(&ill->ill_lock); 828 if (ill->ill_state_flags & ILL_CONDEMNED) { 829 mutex_exit(&ill->ill_lock); 830 ill_refrele(ill); 831 return (0); 832 } 833 834 /* 835 * It's safe to iterate the ill_ipif list when holding an ill_lock. 836 * And it's also safe to access ipif_id without ipif refhold. 837 * See ipif_get_id(). 838 */ 839 for (ipif = ill->ill_ipif; ipif != NULL; ipif = ipif->ipif_next) { 840 if (!IPIF_CAN_LOOKUP(ipif)) 841 continue; 842 if (nextok) { 843 ipif_refhold_locked(ipif); 844 break; 845 } else if (oldidx == ipif->ipif_id) { 846 nextok = B_TRUE; 847 } 848 } 849 850 mutex_exit(&ill->ill_lock); 851 ill_refrele(ill); 852 853 if (ipif == NULL) 854 return (0); 855 856 newidx = ipif->ipif_id; 857 ipif_refrele(ipif); 858 859 return (MAP_IPIF_ID(newidx)); 860 } 861 862 /* 863 * Inject an IPv4 packet to or from an interface 864 */ 865 static int 866 ip_inject(net_handle_t neti, inject_t style, net_inject_t *packet) 867 { 868 netstack_t *ns; 869 870 ns = neti->netd_stack->nts_netstack; 871 ASSERT(ns != NULL); 872 return (ip_inject_impl(style, packet, B_FALSE, ns->netstack_ip)); 873 } 874 875 876 /* 877 * Inject an IPv6 packet to or from an interface 878 */ 879 static int 880 ipv6_inject(net_handle_t neti, inject_t style, net_inject_t *packet) 881 { 882 netstack_t *ns; 883 884 ns = neti->netd_stack->nts_netstack; 885 return (ip_inject_impl(style, packet, B_TRUE, ns->netstack_ip)); 886 } 887 888 /* 889 * Shared implementation to inject a packet to or from an interface 890 * Return value: 891 * 0: successful 892 * -1: memory allocation failed 893 * 1: other errors 894 */ 895 static int 896 ip_inject_impl(inject_t style, net_inject_t *packet, boolean_t isv6, 897 ip_stack_t *ipst) 898 { 899 struct sockaddr_in6 *sin6; 900 ddi_taskq_t *tq = NULL; 901 void (* func)(void *); 902 injection_t *inject; 903 ip6_t *ip6h; 904 ire_t *ire; 905 mblk_t *mp; 906 zoneid_t zoneid; 907 908 ASSERT(packet != NULL); 909 ASSERT(packet->ni_packet != NULL); 910 ASSERT(packet->ni_packet->b_datap->db_type == M_DATA); 911 912 switch (style) { 913 case NI_QUEUE_IN: 914 inject = kmem_alloc(sizeof (*inject), KM_NOSLEEP); 915 if (inject == NULL) 916 return (-1); 917 inject->inj_data = *packet; 918 inject->inj_isv6 = isv6; 919 /* 920 * deliver up into the kernel, immitating its reception by a 921 * network interface, add to list and schedule timeout 922 */ 923 func = ip_ni_queue_in_func; 924 tq = eventq_queue_in; 925 break; 926 927 case NI_QUEUE_OUT: 928 inject = kmem_alloc(sizeof (*inject), KM_NOSLEEP); 929 if (inject == NULL) 930 return (-1); 931 inject->inj_data = *packet; 932 inject->inj_isv6 = isv6; 933 /* 934 * deliver out of the kernel, as if it were being sent via a 935 * raw socket so that IPFilter will see it again, add to list 936 * and schedule timeout 937 */ 938 func = ip_ni_queue_out_func; 939 tq = eventq_queue_out; 940 break; 941 942 case NI_DIRECT_OUT: 943 /* 944 * Note: 945 * For IPv4, the code path below will be greatly simplified 946 * with the delivery of surya - it will become a single 947 * function call to X. A follow on project is aimed to 948 * provide similar functionality for IPv6. 949 */ 950 mp = packet->ni_packet; 951 zoneid = 952 netstackid_to_zoneid(ipst->ips_netstack->netstack_stackid); 953 954 if (!isv6) { 955 struct sockaddr *sock; 956 957 sock = (struct sockaddr *)&packet->ni_addr; 958 /* 959 * ipfil_sendpkt was provided by surya to ease the 960 * problems associated with sending out a packet. 961 * Currently this function only supports IPv4. 962 */ 963 switch (ipfil_sendpkt(sock, mp, packet->ni_physical, 964 zoneid)) { 965 case 0 : 966 case EINPROGRESS: 967 return (0); 968 case ECOMM : 969 case ENONET : 970 return (1); 971 default : 972 return (1); 973 } 974 /* NOTREACHED */ 975 976 } 977 978 ip6h = (ip6_t *)mp->b_rptr; 979 sin6 = (struct sockaddr_in6 *)&packet->ni_addr; 980 ASSERT(sin6->sin6_family == AF_INET6); 981 982 ire = ire_route_lookup_v6(&sin6->sin6_addr, 0, 0, 0, 983 NULL, NULL, ALL_ZONES, NULL, 984 MATCH_IRE_DSTONLY|MATCH_IRE_DEFAULT|MATCH_IRE_RECURSIVE, 985 ipst); 986 987 if (ire == NULL) { 988 ip2dbg(("ip_inject: ire_cache_lookup failed\n")); 989 freemsg(mp); 990 return (1); 991 } 992 993 if (ire->ire_stq == NULL) { 994 /* Send to loopback destination. */ 995 if (ire->ire_rfq == NULL) { 996 ip2dbg(("ip_inject: bad nexthop\n")); 997 ire_refrele(ire); 998 freemsg(mp); 999 return (1); 1000 } 1001 DTRACE_IP7(send, mblk_t *, mp, conn_t *, NULL, 1002 void_ip_t *, ip6h, __dtrace_ipsr_ill_t *, 1003 ire->ire_ipif->ipif_ill, ipha_t *, NULL, ip6_t *, 1004 ip6h, int, 1); 1005 ip_wput_local_v6(ire->ire_rfq, 1006 ire->ire_ipif->ipif_ill, ip6h, mp, ire, 0, zoneid); 1007 ire_refrele(ire); 1008 return (0); 1009 } 1010 1011 mp->b_queue = ire->ire_stq; 1012 1013 if (ire->ire_nce == NULL || 1014 ire->ire_nce->nce_fp_mp == NULL && 1015 ire->ire_nce->nce_res_mp == NULL) { 1016 ip_newroute_v6(ire->ire_stq, mp, 1017 &sin6->sin6_addr, NULL, NULL, ALL_ZONES, ipst); 1018 1019 ire_refrele(ire); 1020 return (0); 1021 } else { 1022 /* prepend L2 header for IPv6 packets. */ 1023 mblk_t *llmp; 1024 1025 /* 1026 * Lock IREs, see 6420438 1027 */ 1028 mutex_enter(&ire->ire_lock); 1029 llmp = ire->ire_nce->nce_fp_mp ? 1030 ire->ire_nce->nce_fp_mp : 1031 ire->ire_nce->nce_res_mp; 1032 1033 if ((mp = dupb(llmp)) == NULL && 1034 (mp = copyb(llmp)) == NULL) { 1035 ip2dbg(("ip_inject: llhdr failed\n")); 1036 mutex_exit(&ire->ire_lock); 1037 ire_refrele(ire); 1038 freemsg(mp); 1039 return (1); 1040 } 1041 mutex_exit(&ire->ire_lock); 1042 linkb(mp, packet->ni_packet); 1043 } 1044 1045 mp->b_queue = ire->ire_stq; 1046 1047 break; 1048 default: 1049 freemsg(packet->ni_packet); 1050 return (1); 1051 } 1052 1053 if (tq) { 1054 inject->inj_ptr = ipst; 1055 if (ddi_taskq_dispatch(tq, func, (void *)inject, 1056 DDI_SLEEP) == DDI_FAILURE) { 1057 ip2dbg(("ip_inject: ddi_taskq_dispatch failed\n")); 1058 freemsg(packet->ni_packet); 1059 return (1); 1060 } 1061 } else { 1062 putnext(ire->ire_stq, mp); 1063 ire_refrele(ire); 1064 } 1065 1066 return (0); 1067 } 1068 1069 /* 1070 * Find the interface used for traffic to a given IPv4 address 1071 */ 1072 static phy_if_t 1073 ip_routeto(net_handle_t neti, struct sockaddr *address, struct sockaddr *next) 1074 { 1075 netstack_t *ns; 1076 1077 ASSERT(address != NULL); 1078 1079 if (address->sa_family != AF_INET) 1080 return (0); 1081 1082 ns = neti->netd_stack->nts_netstack; 1083 ASSERT(ns != NULL); 1084 1085 return (ip_routeto_impl(address, next, ns->netstack_ip)); 1086 } 1087 1088 /* 1089 * Find the interface used for traffic to a given IPv6 address 1090 */ 1091 static phy_if_t 1092 ipv6_routeto(net_handle_t neti, struct sockaddr *address, struct sockaddr *next) 1093 { 1094 netstack_t *ns; 1095 1096 ASSERT(address != NULL); 1097 1098 if (address->sa_family != AF_INET6) 1099 return (0); 1100 1101 ns = neti->netd_stack->nts_netstack; 1102 ASSERT(ns != NULL); 1103 1104 return (ip_routeto_impl(address, next, ns->netstack_ip)); 1105 } 1106 1107 1108 /* 1109 * Find the interface used for traffic to an address. 1110 * For lint reasons, next/next6/sin/sin6 are all declared and assigned 1111 * a value at the top. The alternative would end up with two bunches 1112 * of assignments, with each bunch setting half to NULL. 1113 */ 1114 static phy_if_t 1115 ip_routeto_impl(struct sockaddr *address, struct sockaddr *nexthop, 1116 ip_stack_t *ipst) 1117 { 1118 struct sockaddr_in6 *next6 = (struct sockaddr_in6 *)nexthop; 1119 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)address; 1120 struct sockaddr_in *next = (struct sockaddr_in *)nexthop; 1121 struct sockaddr_in *sin = (struct sockaddr_in *)address; 1122 ire_t *sire = NULL; 1123 ire_t *ire; 1124 ill_t *ill; 1125 phy_if_t phy_if; 1126 1127 if (address->sa_family == AF_INET6) { 1128 ire = ire_route_lookup_v6(&sin6->sin6_addr, NULL, 1129 0, 0, NULL, &sire, ALL_ZONES, NULL, 1130 MATCH_IRE_DSTONLY|MATCH_IRE_DEFAULT|MATCH_IRE_RECURSIVE, 1131 ipst); 1132 } else { 1133 ire = ire_route_lookup(sin->sin_addr.s_addr, 0, 1134 0, 0, NULL, &sire, ALL_ZONES, NULL, 1135 MATCH_IRE_DSTONLY|MATCH_IRE_DEFAULT|MATCH_IRE_RECURSIVE, 1136 ipst); 1137 } 1138 1139 if (ire == NULL) 1140 return (0); 1141 1142 /* 1143 * For some destinations, we have routes that are dead ends, so 1144 * return to indicate that no physical interface can be used to 1145 * reach the destination. 1146 */ 1147 if ((ire->ire_flags & (RTF_REJECT | RTF_BLACKHOLE)) != 0) { 1148 if (sire != NULL) 1149 ire_refrele(sire); 1150 ire_refrele(ire); 1151 return (0); 1152 } 1153 1154 ill = ire_to_ill(ire); 1155 if (ill == NULL) { 1156 if (sire != NULL) 1157 ire_refrele(sire); 1158 ire_refrele(ire); 1159 return (0); 1160 } 1161 1162 if (nexthop != NULL) { 1163 if (address->sa_family == AF_INET6) { 1164 next->sin_addr.s_addr = sire ? sire->ire_gateway_addr : 1165 sin->sin_addr.s_addr; 1166 } else { 1167 next6->sin6_addr = sire ? sire->ire_gateway_addr_v6 : 1168 sin6->sin6_addr; 1169 } 1170 } 1171 1172 ASSERT(ill != NULL); 1173 phy_if = (phy_if_t)ill->ill_phyint->phyint_hook_ifindex; 1174 if (sire != NULL) 1175 ire_refrele(sire); 1176 ire_refrele(ire); 1177 1178 return (phy_if); 1179 } 1180 1181 /* 1182 * Determine if checksumming is being used for the given packet. 1183 * 1184 * Return value: 1185 * NET_HCK_NONE: full checksum recalculation is required 1186 * NET_HCK_L3_FULL: full layer 3 checksum 1187 * NET_HCK_L4_FULL: full layer 4 checksum 1188 * NET_HCK_L4_PART: partial layer 4 checksum 1189 */ 1190 /*ARGSUSED*/ 1191 static int 1192 ip_ispartialchecksum(net_handle_t neti, mblk_t *mp) 1193 { 1194 int ret = 0; 1195 1196 ASSERT(mp != NULL); 1197 1198 if ((DB_CKSUMFLAGS(mp) & HCK_FULLCKSUM) != 0) { 1199 ret |= (int)NET_HCK_L4_FULL; 1200 if ((DB_CKSUMFLAGS(mp) & HCK_IPV4_HDRCKSUM) != 0) 1201 ret |= (int)NET_HCK_L3_FULL; 1202 } 1203 if ((DB_CKSUMFLAGS(mp) & HCK_PARTIALCKSUM) != 0) { 1204 ret |= (int)NET_HCK_L4_PART; 1205 if ((DB_CKSUMFLAGS(mp) & HCK_IPV4_HDRCKSUM) != 0) 1206 ret |= (int)NET_HCK_L3_FULL; 1207 } 1208 1209 return (ret); 1210 } 1211 1212 /* 1213 * Return true or false, indicating whether the network and transport 1214 * headers are correct. Use the capabilities flags and flags set in the 1215 * dblk_t to determine whether or not the checksum is valid. 1216 * 1217 * Return: 1218 * 0: the checksum was incorrect 1219 * 1: the original checksum was correct 1220 */ 1221 /*ARGSUSED*/ 1222 static int 1223 ip_isvalidchecksum(net_handle_t neti, mblk_t *mp) 1224 { 1225 unsigned char *wptr; 1226 ipha_t *ipha = (ipha_t *)mp->b_rptr; 1227 int hlen; 1228 int ret; 1229 1230 ASSERT(mp != NULL); 1231 1232 if (dohwcksum && 1233 DB_CKSUM16(mp) != 0xFFFF && 1234 (DB_CKSUMFLAGS(mp) & HCK_FULLCKSUM) && 1235 (DB_CKSUMFLAGS(mp) & HCK_FULLCKSUM_OK) && 1236 (DB_CKSUMFLAGS(mp) & HCK_IPV4_HDRCKSUM)) 1237 return (1); 1238 1239 hlen = (ipha->ipha_version_and_hdr_length & 0x0F) << 2; 1240 1241 /* 1242 * Check that the mblk being passed in has enough data in it 1243 * before blindly checking ip_cksum. 1244 */ 1245 if (msgdsize(mp) < hlen) 1246 return (0); 1247 1248 if (mp->b_wptr < mp->b_rptr + hlen) { 1249 if (pullupmsg(mp, hlen) == 0) 1250 return (0); 1251 wptr = mp->b_wptr; 1252 } else { 1253 wptr = mp->b_wptr; 1254 mp->b_wptr = mp->b_rptr + hlen; 1255 } 1256 1257 if (ipha->ipha_hdr_checksum == ip_cksum(mp, 0, ipha->ipha_hdr_checksum)) 1258 ret = 1; 1259 else 1260 ret = 0; 1261 mp->b_wptr = wptr; 1262 1263 return (ret); 1264 } 1265 1266 /* 1267 * Unsupported with IPv6 1268 */ 1269 /*ARGSUSED*/ 1270 static int 1271 ipv6_isvalidchecksum(net_handle_t neti, mblk_t *mp) 1272 { 1273 return (-1); 1274 } 1275 1276 /* 1277 * Determine the network addresses for an IPv4 interface 1278 */ 1279 static int 1280 ip_getlifaddr(net_handle_t neti, phy_if_t phy_ifdata, lif_if_t ifdata, 1281 size_t nelem, net_ifaddr_t type[], void *storage) 1282 { 1283 netstack_t *ns; 1284 1285 ns = neti->netd_stack->nts_netstack; 1286 ASSERT(ns != NULL); 1287 return (ip_getlifaddr_impl(AF_INET, phy_ifdata, ifdata, 1288 nelem, type, storage, ns->netstack_ip)); 1289 } 1290 1291 /* 1292 * Determine the network addresses for an IPv6 interface 1293 */ 1294 static int 1295 ipv6_getlifaddr(net_handle_t neti, phy_if_t phy_ifdata, lif_if_t ifdata, 1296 size_t nelem, net_ifaddr_t type[], void *storage) 1297 { 1298 netstack_t *ns; 1299 1300 ns = neti->netd_stack->nts_netstack; 1301 ASSERT(ns != NULL); 1302 return (ip_getlifaddr_impl(AF_INET6, phy_ifdata, ifdata, 1303 nelem, type, storage, ns->netstack_ip)); 1304 } 1305 1306 /* 1307 * Shared implementation to determine the network addresses for an interface 1308 * 1309 * Note: this does not handle a non-zero ifdata when ipmp_hook_emulation is set. 1310 * But IP Filter only uses a zero ifdata. 1311 */ 1312 /* ARGSUSED */ 1313 static int 1314 ip_getlifaddr_impl(sa_family_t family, phy_if_t phy_ifdata, 1315 lif_if_t ifdata, size_t nelem, net_ifaddr_t type[], 1316 struct sockaddr *storage, ip_stack_t *ipst) 1317 { 1318 struct sockaddr_in6 *sin6; 1319 struct sockaddr_in *sin; 1320 lif_if_t ipifid; 1321 ipif_t *ipif; 1322 int i; 1323 1324 ASSERT(type != NULL); 1325 ASSERT(storage != NULL); 1326 1327 ipifid = UNMAP_IPIF_ID(ifdata); 1328 1329 if (family == AF_INET) { 1330 if ((ipif = ipif_getby_indexes((uint_t)phy_ifdata, 1331 (uint_t)ipifid, B_FALSE, ipst)) == NULL) 1332 return (1); 1333 1334 sin = (struct sockaddr_in *)storage; 1335 for (i = 0; i < nelem; i++, sin++) { 1336 if (ip_getifaddr_type(AF_INET, ipif, type[i], 1337 &sin->sin_addr) < 0) { 1338 ip2dbg(("ip_getlifaddr_impl failed type %d\n", 1339 type[i])); 1340 ipif_refrele(ipif); 1341 return (1); 1342 } 1343 sin->sin_family = AF_INET; 1344 } 1345 } else { 1346 if ((ipif = ipif_getby_indexes((uint_t)phy_ifdata, 1347 (uint_t)ipifid, B_TRUE, ipst)) == NULL) 1348 return (1); 1349 1350 sin6 = (struct sockaddr_in6 *)storage; 1351 for (i = 0; i < nelem; i++, sin6++) { 1352 if (ip_getifaddr_type(AF_INET6, ipif, type[i], 1353 &sin6->sin6_addr) < 0) { 1354 ip2dbg(("ip_getlifaddr_impl failed type %d\n", 1355 type[i])); 1356 ipif_refrele(ipif); 1357 return (1); 1358 } 1359 sin6->sin6_family = AF_INET6; 1360 } 1361 } 1362 ipif_refrele(ipif); 1363 return (0); 1364 } 1365 1366 /* 1367 * ip_getlifaddr private function 1368 */ 1369 static int 1370 ip_getifaddr_type(sa_family_t family, ipif_t *ill_ipif, 1371 lif_if_t type, void *storage) 1372 { 1373 void *src_addr; 1374 int mem_size; 1375 1376 ASSERT(ill_ipif != NULL); 1377 ASSERT(storage != NULL); 1378 1379 if (family == AF_INET) { 1380 mem_size = sizeof (struct in_addr); 1381 1382 switch (type) { 1383 case NA_ADDRESS: 1384 src_addr = &(ill_ipif->ipif_lcl_addr); 1385 break; 1386 case NA_PEER: 1387 src_addr = &(ill_ipif->ipif_pp_dst_addr); 1388 break; 1389 case NA_BROADCAST: 1390 src_addr = &(ill_ipif->ipif_brd_addr); 1391 break; 1392 case NA_NETMASK: 1393 src_addr = &(ill_ipif->ipif_net_mask); 1394 break; 1395 default: 1396 return (-1); 1397 /*NOTREACHED*/ 1398 } 1399 } else { 1400 mem_size = sizeof (struct in6_addr); 1401 1402 switch (type) { 1403 case NA_ADDRESS: 1404 src_addr = &(ill_ipif->ipif_v6lcl_addr); 1405 break; 1406 case NA_PEER: 1407 src_addr = &(ill_ipif->ipif_v6pp_dst_addr); 1408 break; 1409 case NA_BROADCAST: 1410 src_addr = &(ill_ipif->ipif_v6brd_addr); 1411 break; 1412 case NA_NETMASK: 1413 src_addr = &(ill_ipif->ipif_v6net_mask); 1414 break; 1415 default: 1416 return (-1); 1417 /*NOTREACHED*/ 1418 } 1419 } 1420 1421 (void) memcpy(storage, src_addr, mem_size); 1422 return (1); 1423 } 1424 1425 /* 1426 * Shared implementation to determine the zoneid associated with an IPv4/IPv6 1427 * address 1428 */ 1429 static int 1430 ip_getlifzone_impl(sa_family_t family, phy_if_t phy_ifdata, lif_if_t ifdata, 1431 ip_stack_t *ipst, zoneid_t *zoneid) 1432 { 1433 ipif_t *ipif; 1434 1435 ipif = ipif_getby_indexes((uint_t)phy_ifdata, 1436 UNMAP_IPIF_ID((uint_t)ifdata), (family == AF_INET6), ipst); 1437 if (ipif == NULL) 1438 return (-1); 1439 *zoneid = IP_REAL_ZONEID(ipif->ipif_zoneid, ipst); 1440 ipif_refrele(ipif); 1441 return (0); 1442 } 1443 1444 /* 1445 * Determine the zoneid associated with an IPv4 address 1446 */ 1447 static int 1448 ip_getlifzone(net_handle_t neti, phy_if_t phy_ifdata, lif_if_t ifdata, 1449 zoneid_t *zoneid) 1450 { 1451 return (ip_getlifzone_impl(AF_INET, phy_ifdata, ifdata, 1452 neti->netd_stack->nts_netstack->netstack_ip, zoneid)); 1453 } 1454 1455 /* 1456 * Determine the zoneid associated with an IPv6 address 1457 */ 1458 static int 1459 ipv6_getlifzone(net_handle_t neti, phy_if_t phy_ifdata, lif_if_t ifdata, 1460 zoneid_t *zoneid) 1461 { 1462 return (ip_getlifzone_impl(AF_INET6, phy_ifdata, ifdata, 1463 neti->netd_stack->nts_netstack->netstack_ip, zoneid)); 1464 } 1465 1466 static int 1467 ip_getlifflags_impl(sa_family_t family, phy_if_t phy_ifdata, lif_if_t ifdata, 1468 ip_stack_t *ipst, uint64_t *flags) 1469 { 1470 ipif_t *ipif; 1471 1472 ipif = ipif_getby_indexes((uint_t)phy_ifdata, 1473 UNMAP_IPIF_ID((uint_t)ifdata), (family == AF_INET6), ipst); 1474 if (ipif == NULL) 1475 return (-1); 1476 *flags = ipif->ipif_flags; 1477 ipif_refrele(ipif); 1478 return (0); 1479 } 1480 1481 static int 1482 ip_getlifflags(net_handle_t neti, phy_if_t phy_ifdata, lif_if_t ifdata, 1483 uint64_t *flags) 1484 { 1485 return (ip_getlifflags_impl(AF_INET, phy_ifdata, ifdata, 1486 neti->netd_stack->nts_netstack->netstack_ip, flags)); 1487 } 1488 1489 static int 1490 ipv6_getlifflags(net_handle_t neti, phy_if_t phy_ifdata, lif_if_t ifdata, 1491 uint64_t *flags) 1492 { 1493 return (ip_getlifflags_impl(AF_INET6, phy_ifdata, ifdata, 1494 neti->netd_stack->nts_netstack->netstack_ip, flags)); 1495 } 1496 1497 /* 1498 * Deliver packet up into the kernel, immitating its reception by a 1499 * network interface. 1500 */ 1501 static void 1502 ip_ni_queue_in_func(void *inject) 1503 { 1504 ip_ni_queue_func_impl(inject, B_FALSE); 1505 } 1506 1507 /* 1508 * Deliver out of the kernel, as if it were being sent via a 1509 * raw socket so that IPFilter will see it again. 1510 */ 1511 static void 1512 ip_ni_queue_out_func(void *inject) 1513 { 1514 ip_ni_queue_func_impl(inject, B_TRUE); 1515 } 1516 1517 /* 1518 * Shared implementation for inject via ip_output and ip_input 1519 */ 1520 static void 1521 ip_ni_queue_func_impl(injection_t *inject, boolean_t out) 1522 { 1523 net_inject_t *packet; 1524 conn_t *conn; 1525 ill_t *ill; 1526 ip_stack_t *ipst = (ip_stack_t *)inject->inj_ptr; 1527 1528 ASSERT(inject != NULL); 1529 packet = &inject->inj_data; 1530 ASSERT(packet->ni_packet != NULL); 1531 1532 ill = ill_lookup_on_ifindex((uint_t)packet->ni_physical, 1533 B_FALSE, NULL, NULL, NULL, NULL, ipst); 1534 1535 /* Fallback to group names only if hook_emulation is set */ 1536 if (ill == NULL && ipst->ips_ipmp_hook_emulation) { 1537 ill = ill_group_lookup_on_ifindex((uint_t)packet->ni_physical, 1538 B_FALSE, ipst); 1539 } 1540 if (ill == NULL) { 1541 kmem_free(inject, sizeof (*inject)); 1542 return; 1543 } 1544 1545 if (out == 0) { 1546 if (inject->inj_isv6) { 1547 ip_rput_v6(ill->ill_rq, packet->ni_packet); 1548 } else { 1549 ip_input(ill, NULL, packet->ni_packet, 0); 1550 } 1551 kmem_free(inject, sizeof (*inject)); 1552 ill_refrele(ill); 1553 return; 1554 } 1555 1556 /* 1557 * Even though ipcl_conn_create requests that it be passed 1558 * a different value for "TCP", in this case there may not 1559 * be a TCP connection backing the packet and more than 1560 * likely, non-TCP packets will go here too. 1561 */ 1562 conn = ipcl_conn_create(IPCL_IPCCONN, KM_NOSLEEP, ipst->ips_netstack); 1563 if (conn != NULL) { 1564 if (inject->inj_isv6) { 1565 conn->conn_flags |= IPCL_ISV6; 1566 conn->conn_af_isv6 = B_TRUE; 1567 conn->conn_src_preferences = IPV6_PREFER_SRC_DEFAULT; 1568 conn->conn_multicast_loop = IP_DEFAULT_MULTICAST_LOOP; 1569 ip_output_v6(conn, packet->ni_packet, ill->ill_wq, 1570 IP_WPUT); 1571 } else { 1572 conn->conn_af_isv6 = B_FALSE; 1573 conn->conn_pkt_isv6 = B_FALSE; 1574 conn->conn_multicast_loop = IP_DEFAULT_MULTICAST_LOOP; 1575 ip_output(conn, packet->ni_packet, ill->ill_wq, 1576 IP_WPUT); 1577 } 1578 1579 CONN_DEC_REF(conn); 1580 } 1581 1582 kmem_free(inject, sizeof (*inject)); 1583 ill_refrele(ill); 1584 } 1585 1586 /* 1587 * taskq function for nic events. 1588 */ 1589 void 1590 ip_ne_queue_func(void *arg) 1591 { 1592 hook_event_token_t hr; 1593 hook_nic_event_int_t *info = (hook_nic_event_int_t *)arg; 1594 ip_stack_t *ipst; 1595 netstack_t *ns; 1596 1597 ns = netstack_find_by_stackid(info->hnei_stackid); 1598 if (ns == NULL) 1599 goto done; 1600 1601 ipst = ns->netstack_ip; 1602 if (ipst == NULL) 1603 goto done; 1604 1605 hr = (info->hnei_event.hne_protocol == ipst->ips_ipv6_net_data) ? 1606 ipst->ips_ipv6nicevents : ipst->ips_ipv4nicevents; 1607 (void) hook_run(info->hnei_event.hne_protocol->netd_hooks, hr, 1608 (hook_data_t)&info->hnei_event); 1609 1610 done: 1611 if (ns != NULL) 1612 netstack_rele(ns); 1613 kmem_free(info->hnei_event.hne_data, info->hnei_event.hne_datalen); 1614 kmem_free(arg, sizeof (hook_nic_event_int_t)); 1615 } 1616 1617 /* 1618 * Temporary function to support IPMP emulation for IP Filter. 1619 * Lookup an ill based on the ifindex assigned to the group. 1620 * Skips unusable ones i.e. where any of these flags are set: 1621 * (PHYI_FAILED|PHYI_OFFLINE|PHYI_INACTIVE) 1622 */ 1623 ill_t * 1624 ill_group_lookup_on_ifindex(uint_t index, boolean_t isv6, ip_stack_t *ipst) 1625 { 1626 ill_t *ill; 1627 phyint_t *phyi; 1628 1629 rw_enter(&ipst->ips_ill_g_lock, RW_READER); 1630 phyi = phyint_lookup_group_ifindex(index, ipst); 1631 if (phyi != NULL) { 1632 ill = isv6 ? phyi->phyint_illv6: phyi->phyint_illv4; 1633 if (ill != NULL) { 1634 mutex_enter(&ill->ill_lock); 1635 if (ILL_CAN_LOOKUP(ill)) { 1636 ill_refhold_locked(ill); 1637 mutex_exit(&ill->ill_lock); 1638 rw_exit(&ipst->ips_ill_g_lock); 1639 return (ill); 1640 } 1641 mutex_exit(&ill->ill_lock); 1642 } 1643 } 1644 rw_exit(&ipst->ips_ill_g_lock); 1645 return (NULL); 1646 } 1647 1648 /* 1649 * Temporary function to support IPMP emulation for IP Filter. 1650 * Lookup an ill based on the group name. 1651 * Skips unusable ones i.e. where any of these flags are set: 1652 * (PHYI_FAILED|PHYI_OFFLINE|PHYI_INACTIVE) 1653 */ 1654 ill_t * 1655 ill_group_lookup_on_name(char *name, boolean_t isv6, ip_stack_t *ipst) 1656 { 1657 ill_t *ill; 1658 phyint_t *phyi; 1659 1660 rw_enter(&ipst->ips_ill_g_lock, RW_READER); 1661 phyi = phyint_lookup_group(name, B_TRUE, ipst); 1662 if (phyi != NULL) { 1663 ill = isv6 ? phyi->phyint_illv6: phyi->phyint_illv4; 1664 if (ill != NULL) { 1665 mutex_enter(&ill->ill_lock); 1666 if (ILL_CAN_LOOKUP(ill)) { 1667 ill_refhold_locked(ill); 1668 mutex_exit(&ill->ill_lock); 1669 rw_exit(&ipst->ips_ill_g_lock); 1670 return (ill); 1671 } 1672 mutex_exit(&ill->ill_lock); 1673 } 1674 } 1675 rw_exit(&ipst->ips_ill_g_lock); 1676 return (NULL); 1677 } 1678