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