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