1381a2a9aSdr146992 /* 2381a2a9aSdr146992 * CDDL HEADER START 3381a2a9aSdr146992 * 4381a2a9aSdr146992 * The contents of this file are subject to the terms of the 5381a2a9aSdr146992 * Common Development and Distribution License (the "License"). 6381a2a9aSdr146992 * You may not use this file except in compliance with the License. 7381a2a9aSdr146992 * 8381a2a9aSdr146992 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9381a2a9aSdr146992 * or http://www.opensolaris.org/os/licensing. 10381a2a9aSdr146992 * See the License for the specific language governing permissions 11381a2a9aSdr146992 * and limitations under the License. 12381a2a9aSdr146992 * 13381a2a9aSdr146992 * When distributing Covered Code, include this CDDL HEADER in each 14381a2a9aSdr146992 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15381a2a9aSdr146992 * If applicable, add the following below this CDDL HEADER, with the 16381a2a9aSdr146992 * fields enclosed by brackets "[]" replaced with your own identifying 17381a2a9aSdr146992 * information: Portions Copyright [yyyy] [name of copyright owner] 18381a2a9aSdr146992 * 19381a2a9aSdr146992 * CDDL HEADER END 20381a2a9aSdr146992 */ 21381a2a9aSdr146992 /* 229e3469d3SErik Nordmark * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 23381a2a9aSdr146992 * Use is subject to license terms. 24381a2a9aSdr146992 */ 25381a2a9aSdr146992 26381a2a9aSdr146992 #include <sys/param.h> 27381a2a9aSdr146992 #include <sys/types.h> 28381a2a9aSdr146992 #include <sys/systm.h> 29381a2a9aSdr146992 #include <sys/stream.h> 30381a2a9aSdr146992 #include <sys/strsubr.h> 31381a2a9aSdr146992 #include <sys/pattr.h> 32381a2a9aSdr146992 #include <sys/dlpi.h> 33381a2a9aSdr146992 #include <sys/atomic.h> 34381a2a9aSdr146992 #include <sys/sunddi.h> 35381a2a9aSdr146992 #include <sys/socket.h> 36381a2a9aSdr146992 #include <sys/neti.h> 3710e6dadfSbrendan #include <sys/sdt.h> 387ddc9b1aSDarren Reed #include <sys/cmn_err.h> 39381a2a9aSdr146992 40381a2a9aSdr146992 #include <netinet/in.h> 41bd670b35SErik Nordmark #include <inet/ipsec_impl.h> 42381a2a9aSdr146992 #include <inet/common.h> 43381a2a9aSdr146992 #include <inet/mib2.h> 44381a2a9aSdr146992 #include <inet/ip.h> 45381a2a9aSdr146992 #include <inet/ip6.h> 46381a2a9aSdr146992 #include <inet/ip_if.h> 47381a2a9aSdr146992 #include <inet/ip_ire.h> 48381a2a9aSdr146992 #include <inet/ip_impl.h> 49381a2a9aSdr146992 #include <inet/ip_ndp.h> 50381a2a9aSdr146992 #include <inet/ipclassifier.h> 51381a2a9aSdr146992 #include <inet/ipp_common.h> 52381a2a9aSdr146992 #include <inet/ip_ftable.h> 53381a2a9aSdr146992 54381a2a9aSdr146992 /* 55381a2a9aSdr146992 * IPv4 netinfo entry point declarations. 56381a2a9aSdr146992 */ 577ddc9b1aSDarren Reed static int ip_getifname(net_handle_t, phy_if_t, char *, 587ddc9b1aSDarren Reed const size_t); 597ddc9b1aSDarren Reed static int ip_getmtu(net_handle_t, phy_if_t, lif_if_t); 607ddc9b1aSDarren Reed static int ip_getpmtuenabled(net_handle_t); 617ddc9b1aSDarren Reed static int ip_getlifaddr(net_handle_t, phy_if_t, lif_if_t, 627ddc9b1aSDarren Reed size_t, net_ifaddr_t [], void *); 63b127ac41SPhilip Kirk static int ip_getlifzone(net_handle_t, phy_if_t, lif_if_t, 64b127ac41SPhilip Kirk zoneid_t *); 65b127ac41SPhilip Kirk static int ip_getlifflags(net_handle_t, phy_if_t, lif_if_t, 66b127ac41SPhilip Kirk uint64_t *); 677ddc9b1aSDarren Reed static phy_if_t ip_phygetnext(net_handle_t, phy_if_t); 687ddc9b1aSDarren Reed static phy_if_t ip_phylookup(net_handle_t, const char *); 697ddc9b1aSDarren Reed static lif_if_t ip_lifgetnext(net_handle_t, phy_if_t, lif_if_t); 707ddc9b1aSDarren Reed static int ip_inject(net_handle_t, inject_t, net_inject_t *); 717ddc9b1aSDarren Reed static phy_if_t ip_routeto(net_handle_t, struct sockaddr *, 727ddc9b1aSDarren Reed struct sockaddr *); 737ddc9b1aSDarren Reed static int ip_ispartialchecksum(net_handle_t, mblk_t *); 747ddc9b1aSDarren Reed static int ip_isvalidchecksum(net_handle_t, mblk_t *); 75381a2a9aSdr146992 767ddc9b1aSDarren Reed static int ipv6_getifname(net_handle_t, phy_if_t, char *, 777ddc9b1aSDarren Reed const size_t); 787ddc9b1aSDarren Reed static int ipv6_getmtu(net_handle_t, phy_if_t, lif_if_t); 797ddc9b1aSDarren Reed static int ipv6_getlifaddr(net_handle_t, phy_if_t, lif_if_t, 807ddc9b1aSDarren Reed size_t, net_ifaddr_t [], void *); 81b127ac41SPhilip Kirk static int ipv6_getlifzone(net_handle_t, phy_if_t, lif_if_t, 82b127ac41SPhilip Kirk zoneid_t *); 83b127ac41SPhilip Kirk static int ipv6_getlifflags(net_handle_t, phy_if_t, lif_if_t, 84b127ac41SPhilip Kirk uint64_t *); 857ddc9b1aSDarren Reed static phy_if_t ipv6_phygetnext(net_handle_t, phy_if_t); 867ddc9b1aSDarren Reed static phy_if_t ipv6_phylookup(net_handle_t, const char *); 877ddc9b1aSDarren Reed static lif_if_t ipv6_lifgetnext(net_handle_t, phy_if_t, lif_if_t); 887ddc9b1aSDarren Reed static int ipv6_inject(net_handle_t, inject_t, net_inject_t *); 897ddc9b1aSDarren Reed static phy_if_t ipv6_routeto(net_handle_t, struct sockaddr *, 907ddc9b1aSDarren Reed struct sockaddr *); 917ddc9b1aSDarren Reed static int ipv6_isvalidchecksum(net_handle_t, mblk_t *); 92381a2a9aSdr146992 93bd670b35SErik Nordmark static int net_no_getmtu(net_handle_t, phy_if_t, lif_if_t); 94bd670b35SErik Nordmark static int net_no_getpmtuenabled(net_handle_t); 95bd670b35SErik Nordmark static lif_if_t net_no_lifgetnext(net_handle_t, phy_if_t, lif_if_t); 96bd670b35SErik Nordmark static int net_no_inject(net_handle_t, inject_t, net_inject_t *); 97bd670b35SErik Nordmark static phy_if_t net_no_routeto(net_handle_t, struct sockaddr *, 98bd670b35SErik Nordmark struct sockaddr *); 99bd670b35SErik Nordmark static int net_no_ispartialchecksum(net_handle_t, mblk_t *); 100bd670b35SErik Nordmark static int net_no_getlifaddr(net_handle_t, phy_if_t, lif_if_t, 101bd670b35SErik Nordmark size_t, net_ifaddr_t [], void *); 102bd670b35SErik Nordmark static int net_no_getlifzone(net_handle_t, phy_if_t, lif_if_t, 103bd670b35SErik Nordmark zoneid_t *); 104bd670b35SErik Nordmark static int net_no_getlifflags(net_handle_t, phy_if_t, lif_if_t, 105bd670b35SErik Nordmark uint64_t *); 106bd670b35SErik Nordmark 107381a2a9aSdr146992 /* Netinfo private functions */ 108381a2a9aSdr146992 static int ip_getifname_impl(phy_if_t, char *, 109f4b3ec61Sdh155122 const size_t, boolean_t, ip_stack_t *); 110f4b3ec61Sdh155122 static int ip_getmtu_impl(phy_if_t, lif_if_t, boolean_t, 111f4b3ec61Sdh155122 ip_stack_t *); 112f4b3ec61Sdh155122 static phy_if_t ip_phylookup_impl(const char *, boolean_t, 1137ddc9b1aSDarren Reed ip_stack_t *); 114f4b3ec61Sdh155122 static lif_if_t ip_lifgetnext_impl(phy_if_t, lif_if_t, boolean_t, 1157ddc9b1aSDarren Reed ip_stack_t *); 116f4b3ec61Sdh155122 static int ip_inject_impl(inject_t, net_inject_t *, boolean_t, 117f4b3ec61Sdh155122 ip_stack_t *); 118381a2a9aSdr146992 static int ip_getifaddr_type(sa_family_t, ipif_t *, lif_if_t, 119381a2a9aSdr146992 void *); 1207ddc9b1aSDarren Reed static phy_if_t ip_routeto_impl(struct sockaddr *, struct sockaddr *, 1217ddc9b1aSDarren Reed ip_stack_t *); 122381a2a9aSdr146992 static int ip_getlifaddr_impl(sa_family_t, phy_if_t, lif_if_t, 123f4b3ec61Sdh155122 size_t, net_ifaddr_t [], struct sockaddr *, 124f4b3ec61Sdh155122 ip_stack_t *); 125381a2a9aSdr146992 static void ip_ni_queue_in_func(void *); 126381a2a9aSdr146992 static void ip_ni_queue_out_func(void *); 127381a2a9aSdr146992 static void ip_ni_queue_func_impl(injection_t *, boolean_t); 128381a2a9aSdr146992 1297ddc9b1aSDarren Reed static net_protocol_t ipv4info = { 130381a2a9aSdr146992 NETINFO_VERSION, 131381a2a9aSdr146992 NHF_INET, 132381a2a9aSdr146992 ip_getifname, 133381a2a9aSdr146992 ip_getmtu, 134381a2a9aSdr146992 ip_getpmtuenabled, 135381a2a9aSdr146992 ip_getlifaddr, 136b127ac41SPhilip Kirk ip_getlifzone, 137b127ac41SPhilip Kirk ip_getlifflags, 138381a2a9aSdr146992 ip_phygetnext, 139381a2a9aSdr146992 ip_phylookup, 140381a2a9aSdr146992 ip_lifgetnext, 141381a2a9aSdr146992 ip_inject, 142381a2a9aSdr146992 ip_routeto, 143381a2a9aSdr146992 ip_ispartialchecksum, 144381a2a9aSdr146992 ip_isvalidchecksum 145381a2a9aSdr146992 }; 146381a2a9aSdr146992 147381a2a9aSdr146992 1487ddc9b1aSDarren Reed static net_protocol_t ipv6info = { 149381a2a9aSdr146992 NETINFO_VERSION, 150381a2a9aSdr146992 NHF_INET6, 151381a2a9aSdr146992 ipv6_getifname, 152381a2a9aSdr146992 ipv6_getmtu, 153381a2a9aSdr146992 ip_getpmtuenabled, 154381a2a9aSdr146992 ipv6_getlifaddr, 155b127ac41SPhilip Kirk ipv6_getlifzone, 156b127ac41SPhilip Kirk ipv6_getlifflags, 157381a2a9aSdr146992 ipv6_phygetnext, 158381a2a9aSdr146992 ipv6_phylookup, 159381a2a9aSdr146992 ipv6_lifgetnext, 160381a2a9aSdr146992 ipv6_inject, 161381a2a9aSdr146992 ipv6_routeto, 162381a2a9aSdr146992 ip_ispartialchecksum, 163381a2a9aSdr146992 ipv6_isvalidchecksum 164381a2a9aSdr146992 }; 165381a2a9aSdr146992 166bd670b35SErik Nordmark static net_protocol_t arp_netinfo = { 167bd670b35SErik Nordmark NETINFO_VERSION, 168bd670b35SErik Nordmark NHF_ARP, 169bd670b35SErik Nordmark ip_getifname, 170bd670b35SErik Nordmark net_no_getmtu, 171bd670b35SErik Nordmark net_no_getpmtuenabled, 172bd670b35SErik Nordmark net_no_getlifaddr, 173bd670b35SErik Nordmark net_no_getlifzone, 174bd670b35SErik Nordmark net_no_getlifflags, 175bd670b35SErik Nordmark ip_phygetnext, 176bd670b35SErik Nordmark ip_phylookup, 177bd670b35SErik Nordmark net_no_lifgetnext, 178bd670b35SErik Nordmark net_no_inject, 179bd670b35SErik Nordmark net_no_routeto, 180bd670b35SErik Nordmark net_no_ispartialchecksum, 181bd670b35SErik Nordmark ip_isvalidchecksum 182bd670b35SErik Nordmark }; 183bd670b35SErik Nordmark 184381a2a9aSdr146992 /* 185381a2a9aSdr146992 * The taskq eventq_queue_in is used to process the upside inject messages. 186381a2a9aSdr146992 * The taskq eventq_queue_out is used to process the downside inject messages. 187381a2a9aSdr146992 * The taskq eventq_queue_nic is used to process the nic event messages. 188381a2a9aSdr146992 */ 189381a2a9aSdr146992 static ddi_taskq_t *eventq_queue_in = NULL; 190381a2a9aSdr146992 static ddi_taskq_t *eventq_queue_out = NULL; 191381a2a9aSdr146992 ddi_taskq_t *eventq_queue_nic = NULL; 192381a2a9aSdr146992 193381a2a9aSdr146992 /* 194f4b3ec61Sdh155122 * Initialize queues for inject. 195381a2a9aSdr146992 */ 196381a2a9aSdr146992 void 197f4b3ec61Sdh155122 ip_net_g_init() 198381a2a9aSdr146992 { 199381a2a9aSdr146992 if (eventq_queue_out == NULL) { 200381a2a9aSdr146992 eventq_queue_out = ddi_taskq_create(NULL, 201381a2a9aSdr146992 "IP_INJECT_QUEUE_OUT", 1, TASKQ_DEFAULTPRI, 0); 202381a2a9aSdr146992 203381a2a9aSdr146992 if (eventq_queue_out == NULL) 204381a2a9aSdr146992 cmn_err(CE_NOTE, "ipv4_net_init: " 205381a2a9aSdr146992 "ddi_taskq_create failed for IP_INJECT_QUEUE_OUT"); 206381a2a9aSdr146992 } 207381a2a9aSdr146992 208381a2a9aSdr146992 if (eventq_queue_in == NULL) { 209381a2a9aSdr146992 eventq_queue_in = ddi_taskq_create(NULL, 210381a2a9aSdr146992 "IP_INJECT_QUEUE_IN", 1, TASKQ_DEFAULTPRI, 0); 211381a2a9aSdr146992 212381a2a9aSdr146992 if (eventq_queue_in == NULL) 213381a2a9aSdr146992 cmn_err(CE_NOTE, "ipv4_net_init: " 214381a2a9aSdr146992 "ddi_taskq_create failed for IP_INJECT_QUEUE_IN"); 215381a2a9aSdr146992 } 216381a2a9aSdr146992 217381a2a9aSdr146992 if (eventq_queue_nic == NULL) { 218381a2a9aSdr146992 eventq_queue_nic = ddi_taskq_create(NULL, 219381a2a9aSdr146992 "IP_NIC_EVENT_QUEUE", 1, TASKQ_DEFAULTPRI, 0); 220381a2a9aSdr146992 221381a2a9aSdr146992 if (eventq_queue_nic == NULL) 222381a2a9aSdr146992 cmn_err(CE_NOTE, "ipv4_net_init: " 223381a2a9aSdr146992 "ddi_taskq_create failed for IP_NIC_EVENT_QUEUE"); 224381a2a9aSdr146992 } 225381a2a9aSdr146992 } 226381a2a9aSdr146992 227381a2a9aSdr146992 /* 228f4b3ec61Sdh155122 * Destroy inject queues 229381a2a9aSdr146992 */ 230381a2a9aSdr146992 void 231f4b3ec61Sdh155122 ip_net_g_destroy() 232381a2a9aSdr146992 { 233381a2a9aSdr146992 if (eventq_queue_nic != NULL) { 234381a2a9aSdr146992 ddi_taskq_destroy(eventq_queue_nic); 235381a2a9aSdr146992 eventq_queue_nic = NULL; 236381a2a9aSdr146992 } 237381a2a9aSdr146992 238381a2a9aSdr146992 if (eventq_queue_in != NULL) { 239381a2a9aSdr146992 ddi_taskq_destroy(eventq_queue_in); 240381a2a9aSdr146992 eventq_queue_in = NULL; 241381a2a9aSdr146992 } 242381a2a9aSdr146992 243381a2a9aSdr146992 if (eventq_queue_out != NULL) { 244381a2a9aSdr146992 ddi_taskq_destroy(eventq_queue_out); 245381a2a9aSdr146992 eventq_queue_out = NULL; 246381a2a9aSdr146992 } 247381a2a9aSdr146992 } 248381a2a9aSdr146992 249f4b3ec61Sdh155122 /* 250f4b3ec61Sdh155122 * Register IPv4 and IPv6 netinfo functions and initialize queues for inject. 251f4b3ec61Sdh155122 */ 252f4b3ec61Sdh155122 void 253f4b3ec61Sdh155122 ip_net_init(ip_stack_t *ipst, netstack_t *ns) 254f4b3ec61Sdh155122 { 2557ddc9b1aSDarren Reed netid_t id; 256f4b3ec61Sdh155122 2577ddc9b1aSDarren Reed id = net_getnetidbynetstackid(ns->netstack_stackid); 2587ddc9b1aSDarren Reed ASSERT(id != -1); 2597ddc9b1aSDarren Reed 2607ddc9b1aSDarren Reed ipst->ips_ipv4_net_data = net_protocol_register(id, &ipv4info); 261f4b3ec61Sdh155122 ASSERT(ipst->ips_ipv4_net_data != NULL); 262f4b3ec61Sdh155122 2637ddc9b1aSDarren Reed ipst->ips_ipv6_net_data = net_protocol_register(id, &ipv6info); 264f4b3ec61Sdh155122 ASSERT(ipst->ips_ipv6_net_data != NULL); 265bd670b35SErik Nordmark 266bd670b35SErik Nordmark ipst->ips_arp_net_data = net_protocol_register(id, &arp_netinfo); 267bd670b35SErik Nordmark ASSERT(ipst->ips_ipv6_net_data != NULL); 268f4b3ec61Sdh155122 } 269f4b3ec61Sdh155122 270f4b3ec61Sdh155122 271f4b3ec61Sdh155122 /* 2728ad74188SDarren Reed * Unregister IPv4 and IPv6 functions. 273f4b3ec61Sdh155122 */ 274f4b3ec61Sdh155122 void 275f4b3ec61Sdh155122 ip_net_destroy(ip_stack_t *ipst) 276f4b3ec61Sdh155122 { 277f4b3ec61Sdh155122 if (ipst->ips_ipv4_net_data != NULL) { 2787ddc9b1aSDarren Reed if (net_protocol_unregister(ipst->ips_ipv4_net_data) == 0) 279f4b3ec61Sdh155122 ipst->ips_ipv4_net_data = NULL; 280f4b3ec61Sdh155122 } 281f4b3ec61Sdh155122 282f4b3ec61Sdh155122 if (ipst->ips_ipv6_net_data != NULL) { 2837ddc9b1aSDarren Reed if (net_protocol_unregister(ipst->ips_ipv6_net_data) == 0) 284f4b3ec61Sdh155122 ipst->ips_ipv6_net_data = NULL; 285381a2a9aSdr146992 } 286bd670b35SErik Nordmark 287bd670b35SErik Nordmark if (ipst->ips_arp_net_data != NULL) { 288bd670b35SErik Nordmark if (net_protocol_unregister(ipst->ips_arp_net_data) == 0) 289bd670b35SErik Nordmark ipst->ips_arp_net_data = NULL; 290bd670b35SErik Nordmark } 291381a2a9aSdr146992 } 292381a2a9aSdr146992 293381a2a9aSdr146992 /* 294381a2a9aSdr146992 * Initialize IPv4 hooks family the event 295381a2a9aSdr146992 */ 296381a2a9aSdr146992 void 297f4b3ec61Sdh155122 ipv4_hook_init(ip_stack_t *ipst) 298381a2a9aSdr146992 { 299f4b3ec61Sdh155122 HOOK_FAMILY_INIT(&ipst->ips_ipv4root, Hn_IPV4); 3007ddc9b1aSDarren Reed if (net_family_register(ipst->ips_ipv4_net_data, &ipst->ips_ipv4root) 301f4b3ec61Sdh155122 != 0) { 302381a2a9aSdr146992 cmn_err(CE_NOTE, "ipv4_hook_init: " 3037ddc9b1aSDarren Reed "net_family_register failed for ipv4"); 304381a2a9aSdr146992 } 305381a2a9aSdr146992 306f4b3ec61Sdh155122 HOOK_EVENT_INIT(&ipst->ips_ip4_physical_in_event, NH_PHYSICAL_IN); 3077ddc9b1aSDarren Reed ipst->ips_ipv4firewall_physical_in = net_event_register( 308f4b3ec61Sdh155122 ipst->ips_ipv4_net_data, &ipst->ips_ip4_physical_in_event); 309f4b3ec61Sdh155122 if (ipst->ips_ipv4firewall_physical_in == NULL) { 310381a2a9aSdr146992 cmn_err(CE_NOTE, "ipv4_hook_init: " 3117ddc9b1aSDarren Reed "net_event_register failed for ipv4/physical_in"); 312381a2a9aSdr146992 } 313381a2a9aSdr146992 314f4b3ec61Sdh155122 HOOK_EVENT_INIT(&ipst->ips_ip4_physical_out_event, NH_PHYSICAL_OUT); 3157ddc9b1aSDarren Reed ipst->ips_ipv4firewall_physical_out = net_event_register( 316f4b3ec61Sdh155122 ipst->ips_ipv4_net_data, &ipst->ips_ip4_physical_out_event); 317f4b3ec61Sdh155122 if (ipst->ips_ipv4firewall_physical_out == NULL) { 318381a2a9aSdr146992 cmn_err(CE_NOTE, "ipv4_hook_init: " 3197ddc9b1aSDarren Reed "net_event_register failed for ipv4/physical_out"); 320381a2a9aSdr146992 } 321381a2a9aSdr146992 322f4b3ec61Sdh155122 HOOK_EVENT_INIT(&ipst->ips_ip4_forwarding_event, NH_FORWARDING); 3237ddc9b1aSDarren Reed ipst->ips_ipv4firewall_forwarding = net_event_register( 324f4b3ec61Sdh155122 ipst->ips_ipv4_net_data, &ipst->ips_ip4_forwarding_event); 325f4b3ec61Sdh155122 if (ipst->ips_ipv4firewall_forwarding == NULL) { 326381a2a9aSdr146992 cmn_err(CE_NOTE, "ipv4_hook_init: " 3277ddc9b1aSDarren Reed "net_event_register failed for ipv4/forwarding"); 328381a2a9aSdr146992 } 329381a2a9aSdr146992 330f4b3ec61Sdh155122 HOOK_EVENT_INIT(&ipst->ips_ip4_loopback_in_event, NH_LOOPBACK_IN); 3317ddc9b1aSDarren Reed ipst->ips_ipv4firewall_loopback_in = net_event_register( 332f4b3ec61Sdh155122 ipst->ips_ipv4_net_data, &ipst->ips_ip4_loopback_in_event); 333f4b3ec61Sdh155122 if (ipst->ips_ipv4firewall_loopback_in == NULL) { 334381a2a9aSdr146992 cmn_err(CE_NOTE, "ipv4_hook_init: " 3357ddc9b1aSDarren Reed "net_event_register failed for ipv4/loopback_in"); 336381a2a9aSdr146992 } 337381a2a9aSdr146992 338f4b3ec61Sdh155122 HOOK_EVENT_INIT(&ipst->ips_ip4_loopback_out_event, NH_LOOPBACK_OUT); 3397ddc9b1aSDarren Reed ipst->ips_ipv4firewall_loopback_out = net_event_register( 340f4b3ec61Sdh155122 ipst->ips_ipv4_net_data, &ipst->ips_ip4_loopback_out_event); 341f4b3ec61Sdh155122 if (ipst->ips_ipv4firewall_loopback_out == NULL) { 342381a2a9aSdr146992 cmn_err(CE_NOTE, "ipv4_hook_init: " 3437ddc9b1aSDarren Reed "net_event_register failed for ipv4/loopback_out"); 344381a2a9aSdr146992 } 345381a2a9aSdr146992 346f4b3ec61Sdh155122 HOOK_EVENT_INIT(&ipst->ips_ip4_nic_events, NH_NIC_EVENTS); 347f4b3ec61Sdh155122 ipst->ips_ip4_nic_events.he_flags = HOOK_RDONLY; 3487ddc9b1aSDarren Reed ipst->ips_ipv4nicevents = net_event_register( 349f4b3ec61Sdh155122 ipst->ips_ipv4_net_data, &ipst->ips_ip4_nic_events); 350f4b3ec61Sdh155122 if (ipst->ips_ipv4nicevents == NULL) { 351381a2a9aSdr146992 cmn_err(CE_NOTE, "ipv4_hook_init: " 3527ddc9b1aSDarren Reed "net_event_register failed for ipv4/nic_events"); 353381a2a9aSdr146992 } 3540a0e9771SDarren Reed 3550a0e9771SDarren Reed HOOK_EVENT_INIT(&ipst->ips_ip4_observe, NH_OBSERVE); 3560a0e9771SDarren Reed ipst->ips_ip4_observe.he_flags = HOOK_RDONLY; 3570a0e9771SDarren Reed ipst->ips_ipv4observing = net_event_register( 3580a0e9771SDarren Reed ipst->ips_ipv4_net_data, &ipst->ips_ip4_observe); 3590a0e9771SDarren Reed if (ipst->ips_ipv4observing == NULL) { 3600a0e9771SDarren Reed cmn_err(CE_NOTE, "ipv4_hook_init: " 3610a0e9771SDarren Reed "net_event_register failed for ipv4/observe"); 3620a0e9771SDarren Reed } 3630a0e9771SDarren Reed 364381a2a9aSdr146992 } 365381a2a9aSdr146992 366381a2a9aSdr146992 void 3678ad74188SDarren Reed ipv4_hook_shutdown(ip_stack_t *ipst) 3688ad74188SDarren Reed { 3698ad74188SDarren Reed if (ipst->ips_ipv4firewall_forwarding != NULL) { 3708ad74188SDarren Reed (void) net_event_shutdown(ipst->ips_ipv4_net_data, 3718ad74188SDarren Reed &ipst->ips_ip4_forwarding_event); 3728ad74188SDarren Reed } 3738ad74188SDarren Reed 3748ad74188SDarren Reed if (ipst->ips_ipv4firewall_physical_in != NULL) { 3758ad74188SDarren Reed (void) net_event_shutdown(ipst->ips_ipv4_net_data, 3768ad74188SDarren Reed &ipst->ips_ip4_physical_in_event); 3778ad74188SDarren Reed } 3788ad74188SDarren Reed 3798ad74188SDarren Reed if (ipst->ips_ipv4firewall_physical_out != NULL) { 3808ad74188SDarren Reed (void) net_event_shutdown(ipst->ips_ipv4_net_data, 3818ad74188SDarren Reed &ipst->ips_ip4_physical_out_event); 3828ad74188SDarren Reed } 3838ad74188SDarren Reed 3848ad74188SDarren Reed if (ipst->ips_ipv4firewall_loopback_in != NULL) { 3858ad74188SDarren Reed (void) net_event_shutdown(ipst->ips_ipv4_net_data, 3868ad74188SDarren Reed &ipst->ips_ip4_loopback_in_event); 3878ad74188SDarren Reed } 3888ad74188SDarren Reed 3898ad74188SDarren Reed if (ipst->ips_ipv4firewall_loopback_out != NULL) { 3908ad74188SDarren Reed (void) net_event_shutdown(ipst->ips_ipv4_net_data, 3918ad74188SDarren Reed &ipst->ips_ip4_loopback_out_event); 3928ad74188SDarren Reed } 3938ad74188SDarren Reed 3948ad74188SDarren Reed if (ipst->ips_ipv4nicevents != NULL) { 3958ad74188SDarren Reed (void) net_event_shutdown(ipst->ips_ipv4_net_data, 3968ad74188SDarren Reed &ipst->ips_ip4_nic_events); 3978ad74188SDarren Reed } 3988ad74188SDarren Reed 3990a0e9771SDarren Reed if (ipst->ips_ipv4observing != NULL) { 4000a0e9771SDarren Reed (void) net_event_shutdown(ipst->ips_ipv4_net_data, 4010a0e9771SDarren Reed &ipst->ips_ip4_observe); 4020a0e9771SDarren Reed } 4030a0e9771SDarren Reed 4048ad74188SDarren Reed (void) net_family_shutdown(ipst->ips_ipv4_net_data, 4058ad74188SDarren Reed &ipst->ips_ipv4root); 4068ad74188SDarren Reed } 4078ad74188SDarren Reed 4088ad74188SDarren Reed void 409f4b3ec61Sdh155122 ipv4_hook_destroy(ip_stack_t *ipst) 410381a2a9aSdr146992 { 411f4b3ec61Sdh155122 if (ipst->ips_ipv4firewall_forwarding != NULL) { 4127ddc9b1aSDarren Reed if (net_event_unregister(ipst->ips_ipv4_net_data, 413f4b3ec61Sdh155122 &ipst->ips_ip4_forwarding_event) == 0) 414f4b3ec61Sdh155122 ipst->ips_ipv4firewall_forwarding = NULL; 415381a2a9aSdr146992 } 416381a2a9aSdr146992 417f4b3ec61Sdh155122 if (ipst->ips_ipv4firewall_physical_in != NULL) { 4187ddc9b1aSDarren Reed if (net_event_unregister(ipst->ips_ipv4_net_data, 419f4b3ec61Sdh155122 &ipst->ips_ip4_physical_in_event) == 0) 420f4b3ec61Sdh155122 ipst->ips_ipv4firewall_physical_in = NULL; 421381a2a9aSdr146992 } 422381a2a9aSdr146992 423f4b3ec61Sdh155122 if (ipst->ips_ipv4firewall_physical_out != NULL) { 4247ddc9b1aSDarren Reed if (net_event_unregister(ipst->ips_ipv4_net_data, 425f4b3ec61Sdh155122 &ipst->ips_ip4_physical_out_event) == 0) 426f4b3ec61Sdh155122 ipst->ips_ipv4firewall_physical_out = NULL; 427381a2a9aSdr146992 } 428381a2a9aSdr146992 429f4b3ec61Sdh155122 if (ipst->ips_ipv4firewall_loopback_in != NULL) { 4307ddc9b1aSDarren Reed if (net_event_unregister(ipst->ips_ipv4_net_data, 431f4b3ec61Sdh155122 &ipst->ips_ip4_loopback_in_event) == 0) 432f4b3ec61Sdh155122 ipst->ips_ipv4firewall_loopback_in = NULL; 433381a2a9aSdr146992 } 434381a2a9aSdr146992 435f4b3ec61Sdh155122 if (ipst->ips_ipv4firewall_loopback_out != NULL) { 4367ddc9b1aSDarren Reed if (net_event_unregister(ipst->ips_ipv4_net_data, 437f4b3ec61Sdh155122 &ipst->ips_ip4_loopback_out_event) == 0) 438f4b3ec61Sdh155122 ipst->ips_ipv4firewall_loopback_out = NULL; 439381a2a9aSdr146992 } 440381a2a9aSdr146992 441f4b3ec61Sdh155122 if (ipst->ips_ipv4nicevents != NULL) { 4427ddc9b1aSDarren Reed if (net_event_unregister(ipst->ips_ipv4_net_data, 443f4b3ec61Sdh155122 &ipst->ips_ip4_nic_events) == 0) 444f4b3ec61Sdh155122 ipst->ips_ipv4nicevents = NULL; 445381a2a9aSdr146992 } 446381a2a9aSdr146992 4470a0e9771SDarren Reed if (ipst->ips_ipv4observing != NULL) { 4480a0e9771SDarren Reed if (net_event_unregister(ipst->ips_ipv4_net_data, 4490a0e9771SDarren Reed &ipst->ips_ip4_observe) == 0) 4500a0e9771SDarren Reed ipst->ips_ipv4observing = NULL; 4510a0e9771SDarren Reed } 4520a0e9771SDarren Reed 4537ddc9b1aSDarren Reed (void) net_family_unregister(ipst->ips_ipv4_net_data, 454f4b3ec61Sdh155122 &ipst->ips_ipv4root); 455381a2a9aSdr146992 } 456381a2a9aSdr146992 457381a2a9aSdr146992 /* 458381a2a9aSdr146992 * Initialize IPv6 hooks family and event 459381a2a9aSdr146992 */ 460381a2a9aSdr146992 void 461f4b3ec61Sdh155122 ipv6_hook_init(ip_stack_t *ipst) 462381a2a9aSdr146992 { 463381a2a9aSdr146992 464f4b3ec61Sdh155122 HOOK_FAMILY_INIT(&ipst->ips_ipv6root, Hn_IPV6); 4657ddc9b1aSDarren Reed if (net_family_register(ipst->ips_ipv6_net_data, &ipst->ips_ipv6root) 466f4b3ec61Sdh155122 != 0) { 467381a2a9aSdr146992 cmn_err(CE_NOTE, "ipv6_hook_init: " 4687ddc9b1aSDarren Reed "net_family_register failed for ipv6"); 469381a2a9aSdr146992 } 470381a2a9aSdr146992 471f4b3ec61Sdh155122 HOOK_EVENT_INIT(&ipst->ips_ip6_physical_in_event, NH_PHYSICAL_IN); 4727ddc9b1aSDarren Reed ipst->ips_ipv6firewall_physical_in = net_event_register( 473f4b3ec61Sdh155122 ipst->ips_ipv6_net_data, &ipst->ips_ip6_physical_in_event); 474f4b3ec61Sdh155122 if (ipst->ips_ipv6firewall_physical_in == NULL) { 475381a2a9aSdr146992 cmn_err(CE_NOTE, "ipv6_hook_init: " 4767ddc9b1aSDarren Reed "net_event_register failed for ipv6/physical_in"); 477381a2a9aSdr146992 } 478381a2a9aSdr146992 479f4b3ec61Sdh155122 HOOK_EVENT_INIT(&ipst->ips_ip6_physical_out_event, NH_PHYSICAL_OUT); 4807ddc9b1aSDarren Reed ipst->ips_ipv6firewall_physical_out = net_event_register( 481f4b3ec61Sdh155122 ipst->ips_ipv6_net_data, &ipst->ips_ip6_physical_out_event); 482f4b3ec61Sdh155122 if (ipst->ips_ipv6firewall_physical_out == NULL) { 483381a2a9aSdr146992 cmn_err(CE_NOTE, "ipv6_hook_init: " 4847ddc9b1aSDarren Reed "net_event_register failed for ipv6/physical_out"); 485381a2a9aSdr146992 } 486381a2a9aSdr146992 487f4b3ec61Sdh155122 HOOK_EVENT_INIT(&ipst->ips_ip6_forwarding_event, NH_FORWARDING); 4887ddc9b1aSDarren Reed ipst->ips_ipv6firewall_forwarding = net_event_register( 489f4b3ec61Sdh155122 ipst->ips_ipv6_net_data, &ipst->ips_ip6_forwarding_event); 490f4b3ec61Sdh155122 if (ipst->ips_ipv6firewall_forwarding == NULL) { 491381a2a9aSdr146992 cmn_err(CE_NOTE, "ipv6_hook_init: " 4927ddc9b1aSDarren Reed "net_event_register failed for ipv6/forwarding"); 493381a2a9aSdr146992 } 494381a2a9aSdr146992 495f4b3ec61Sdh155122 HOOK_EVENT_INIT(&ipst->ips_ip6_loopback_in_event, NH_LOOPBACK_IN); 4967ddc9b1aSDarren Reed ipst->ips_ipv6firewall_loopback_in = net_event_register( 497f4b3ec61Sdh155122 ipst->ips_ipv6_net_data, &ipst->ips_ip6_loopback_in_event); 498f4b3ec61Sdh155122 if (ipst->ips_ipv6firewall_loopback_in == NULL) { 499381a2a9aSdr146992 cmn_err(CE_NOTE, "ipv6_hook_init: " 5007ddc9b1aSDarren Reed "net_event_register failed for ipv6/loopback_in"); 501381a2a9aSdr146992 } 502381a2a9aSdr146992 503f4b3ec61Sdh155122 HOOK_EVENT_INIT(&ipst->ips_ip6_loopback_out_event, NH_LOOPBACK_OUT); 5047ddc9b1aSDarren Reed ipst->ips_ipv6firewall_loopback_out = net_event_register( 505f4b3ec61Sdh155122 ipst->ips_ipv6_net_data, &ipst->ips_ip6_loopback_out_event); 506f4b3ec61Sdh155122 if (ipst->ips_ipv6firewall_loopback_out == NULL) { 507381a2a9aSdr146992 cmn_err(CE_NOTE, "ipv6_hook_init: " 5087ddc9b1aSDarren Reed "net_event_register failed for ipv6/loopback_out"); 509381a2a9aSdr146992 } 510381a2a9aSdr146992 511f4b3ec61Sdh155122 HOOK_EVENT_INIT(&ipst->ips_ip6_nic_events, NH_NIC_EVENTS); 512f4b3ec61Sdh155122 ipst->ips_ip6_nic_events.he_flags = HOOK_RDONLY; 5137ddc9b1aSDarren Reed ipst->ips_ipv6nicevents = net_event_register( 514f4b3ec61Sdh155122 ipst->ips_ipv6_net_data, &ipst->ips_ip6_nic_events); 515f4b3ec61Sdh155122 if (ipst->ips_ipv6nicevents == NULL) { 516381a2a9aSdr146992 cmn_err(CE_NOTE, "ipv6_hook_init: " 5177ddc9b1aSDarren Reed "net_event_register failed for ipv6/nic_events"); 518381a2a9aSdr146992 } 5190a0e9771SDarren Reed 5200a0e9771SDarren Reed HOOK_EVENT_INIT(&ipst->ips_ip6_observe, NH_OBSERVE); 5210a0e9771SDarren Reed ipst->ips_ip6_observe.he_flags = HOOK_RDONLY; 5220a0e9771SDarren Reed ipst->ips_ipv6observing = net_event_register( 5230a0e9771SDarren Reed ipst->ips_ipv6_net_data, &ipst->ips_ip6_observe); 5240a0e9771SDarren Reed if (ipst->ips_ipv6observing == NULL) { 5250a0e9771SDarren Reed cmn_err(CE_NOTE, "ipv6_hook_init: " 5260a0e9771SDarren Reed "net_event_register failed for ipv6/observe"); 5270a0e9771SDarren Reed } 528381a2a9aSdr146992 } 529381a2a9aSdr146992 530381a2a9aSdr146992 void 5318ad74188SDarren Reed ipv6_hook_shutdown(ip_stack_t *ipst) 5328ad74188SDarren Reed { 5338ad74188SDarren Reed if (ipst->ips_ipv6firewall_forwarding != NULL) { 5348ad74188SDarren Reed (void) net_event_shutdown(ipst->ips_ipv6_net_data, 5358ad74188SDarren Reed &ipst->ips_ip6_forwarding_event); 5368ad74188SDarren Reed } 5378ad74188SDarren Reed 5388ad74188SDarren Reed if (ipst->ips_ipv6firewall_physical_in != NULL) { 5398ad74188SDarren Reed (void) net_event_shutdown(ipst->ips_ipv6_net_data, 5408ad74188SDarren Reed &ipst->ips_ip6_physical_in_event); 5418ad74188SDarren Reed } 5428ad74188SDarren Reed 5438ad74188SDarren Reed if (ipst->ips_ipv6firewall_physical_out != NULL) { 5448ad74188SDarren Reed (void) net_event_shutdown(ipst->ips_ipv6_net_data, 5458ad74188SDarren Reed &ipst->ips_ip6_physical_out_event); 5468ad74188SDarren Reed } 5478ad74188SDarren Reed 5488ad74188SDarren Reed if (ipst->ips_ipv6firewall_loopback_in != NULL) { 5498ad74188SDarren Reed (void) net_event_shutdown(ipst->ips_ipv6_net_data, 5508ad74188SDarren Reed &ipst->ips_ip6_loopback_in_event); 5518ad74188SDarren Reed } 5528ad74188SDarren Reed 5538ad74188SDarren Reed if (ipst->ips_ipv6firewall_loopback_out != NULL) { 5548ad74188SDarren Reed (void) net_event_shutdown(ipst->ips_ipv6_net_data, 5558ad74188SDarren Reed &ipst->ips_ip6_loopback_out_event); 5568ad74188SDarren Reed } 5578ad74188SDarren Reed 5588ad74188SDarren Reed if (ipst->ips_ipv6nicevents != NULL) { 5598ad74188SDarren Reed (void) net_event_shutdown(ipst->ips_ipv6_net_data, 5608ad74188SDarren Reed &ipst->ips_ip6_nic_events); 5618ad74188SDarren Reed } 5628ad74188SDarren Reed 5630a0e9771SDarren Reed if (ipst->ips_ipv6observing != NULL) { 5640a0e9771SDarren Reed (void) net_event_shutdown(ipst->ips_ipv6_net_data, 5650a0e9771SDarren Reed &ipst->ips_ip6_observe); 5660a0e9771SDarren Reed } 5670a0e9771SDarren Reed 5688ad74188SDarren Reed (void) net_family_shutdown(ipst->ips_ipv6_net_data, 5698ad74188SDarren Reed &ipst->ips_ipv6root); 5708ad74188SDarren Reed } 5718ad74188SDarren Reed 5728ad74188SDarren Reed void 573f4b3ec61Sdh155122 ipv6_hook_destroy(ip_stack_t *ipst) 574381a2a9aSdr146992 { 575f4b3ec61Sdh155122 if (ipst->ips_ipv6firewall_forwarding != NULL) { 5767ddc9b1aSDarren Reed if (net_event_unregister(ipst->ips_ipv6_net_data, 577f4b3ec61Sdh155122 &ipst->ips_ip6_forwarding_event) == 0) 578f4b3ec61Sdh155122 ipst->ips_ipv6firewall_forwarding = NULL; 579381a2a9aSdr146992 } 580381a2a9aSdr146992 581f4b3ec61Sdh155122 if (ipst->ips_ipv6firewall_physical_in != NULL) { 5827ddc9b1aSDarren Reed if (net_event_unregister(ipst->ips_ipv6_net_data, 583f4b3ec61Sdh155122 &ipst->ips_ip6_physical_in_event) == 0) 584f4b3ec61Sdh155122 ipst->ips_ipv6firewall_physical_in = NULL; 585381a2a9aSdr146992 } 586381a2a9aSdr146992 587f4b3ec61Sdh155122 if (ipst->ips_ipv6firewall_physical_out != NULL) { 5887ddc9b1aSDarren Reed if (net_event_unregister(ipst->ips_ipv6_net_data, 589f4b3ec61Sdh155122 &ipst->ips_ip6_physical_out_event) == 0) 590f4b3ec61Sdh155122 ipst->ips_ipv6firewall_physical_out = NULL; 591381a2a9aSdr146992 } 592381a2a9aSdr146992 593f4b3ec61Sdh155122 if (ipst->ips_ipv6firewall_loopback_in != NULL) { 5947ddc9b1aSDarren Reed if (net_event_unregister(ipst->ips_ipv6_net_data, 595f4b3ec61Sdh155122 &ipst->ips_ip6_loopback_in_event) == 0) 596f4b3ec61Sdh155122 ipst->ips_ipv6firewall_loopback_in = NULL; 597381a2a9aSdr146992 } 598381a2a9aSdr146992 599f4b3ec61Sdh155122 if (ipst->ips_ipv6firewall_loopback_out != NULL) { 6007ddc9b1aSDarren Reed if (net_event_unregister(ipst->ips_ipv6_net_data, 601f4b3ec61Sdh155122 &ipst->ips_ip6_loopback_out_event) == 0) 602f4b3ec61Sdh155122 ipst->ips_ipv6firewall_loopback_out = NULL; 603381a2a9aSdr146992 } 604381a2a9aSdr146992 605f4b3ec61Sdh155122 if (ipst->ips_ipv6nicevents != NULL) { 6067ddc9b1aSDarren Reed if (net_event_unregister(ipst->ips_ipv6_net_data, 607f4b3ec61Sdh155122 &ipst->ips_ip6_nic_events) == 0) 608f4b3ec61Sdh155122 ipst->ips_ipv6nicevents = NULL; 609381a2a9aSdr146992 } 610381a2a9aSdr146992 6110a0e9771SDarren Reed if (ipst->ips_ipv6observing != NULL) { 6120a0e9771SDarren Reed if (net_event_unregister(ipst->ips_ipv6_net_data, 6130a0e9771SDarren Reed &ipst->ips_ip6_observe) == 0) 6140a0e9771SDarren Reed ipst->ips_ipv6observing = NULL; 6150a0e9771SDarren Reed } 6160a0e9771SDarren Reed 6177ddc9b1aSDarren Reed (void) net_family_unregister(ipst->ips_ipv6_net_data, 618f4b3ec61Sdh155122 &ipst->ips_ipv6root); 619381a2a9aSdr146992 } 620381a2a9aSdr146992 621381a2a9aSdr146992 /* 622381a2a9aSdr146992 * Determine the name of an IPv4 interface 623381a2a9aSdr146992 */ 624381a2a9aSdr146992 static int 6257ddc9b1aSDarren Reed ip_getifname(net_handle_t neti, phy_if_t phy_ifdata, char *buffer, 6267ddc9b1aSDarren Reed const size_t buflen) 627381a2a9aSdr146992 { 628f4b3ec61Sdh155122 return (ip_getifname_impl(phy_ifdata, buffer, buflen, B_FALSE, 6297ddc9b1aSDarren Reed neti->netd_stack->nts_netstack->netstack_ip)); 630381a2a9aSdr146992 } 631381a2a9aSdr146992 632381a2a9aSdr146992 /* 633381a2a9aSdr146992 * Determine the name of an IPv6 interface 634381a2a9aSdr146992 */ 635381a2a9aSdr146992 static int 6367ddc9b1aSDarren Reed ipv6_getifname(net_handle_t neti, phy_if_t phy_ifdata, char *buffer, 6377ddc9b1aSDarren Reed const size_t buflen) 638381a2a9aSdr146992 { 639f4b3ec61Sdh155122 return (ip_getifname_impl(phy_ifdata, buffer, buflen, B_TRUE, 6407ddc9b1aSDarren Reed neti->netd_stack->nts_netstack->netstack_ip)); 641381a2a9aSdr146992 } 642381a2a9aSdr146992 643381a2a9aSdr146992 /* 644381a2a9aSdr146992 * Shared implementation to determine the name of a given network interface 645381a2a9aSdr146992 */ 646381a2a9aSdr146992 /* ARGSUSED */ 647381a2a9aSdr146992 static int 648381a2a9aSdr146992 ip_getifname_impl(phy_if_t phy_ifdata, 649f4b3ec61Sdh155122 char *buffer, const size_t buflen, boolean_t isv6, ip_stack_t *ipst) 650381a2a9aSdr146992 { 651381a2a9aSdr146992 ill_t *ill; 652381a2a9aSdr146992 653381a2a9aSdr146992 ASSERT(buffer != NULL); 654381a2a9aSdr146992 655bd670b35SErik Nordmark ill = ill_lookup_on_ifindex((uint_t)phy_ifdata, isv6, ipst); 656381a2a9aSdr146992 if (ill == NULL) 657381a2a9aSdr146992 return (1); 658e11c3f44Smeem 659e11c3f44Smeem (void) strlcpy(buffer, ill->ill_name, buflen); 660381a2a9aSdr146992 ill_refrele(ill); 661381a2a9aSdr146992 return (0); 662381a2a9aSdr146992 } 663381a2a9aSdr146992 664381a2a9aSdr146992 /* 665381a2a9aSdr146992 * Determine the MTU of an IPv4 network interface 666381a2a9aSdr146992 */ 667381a2a9aSdr146992 static int 6687ddc9b1aSDarren Reed ip_getmtu(net_handle_t neti, phy_if_t phy_ifdata, lif_if_t ifdata) 669381a2a9aSdr146992 { 6707ddc9b1aSDarren Reed netstack_t *ns; 6717ddc9b1aSDarren Reed 6727ddc9b1aSDarren Reed ns = neti->netd_stack->nts_netstack; 673f4b3ec61Sdh155122 ASSERT(ns != NULL); 674f4b3ec61Sdh155122 return (ip_getmtu_impl(phy_ifdata, ifdata, B_FALSE, ns->netstack_ip)); 675381a2a9aSdr146992 } 676381a2a9aSdr146992 677381a2a9aSdr146992 /* 678381a2a9aSdr146992 * Determine the MTU of an IPv6 network interface 679381a2a9aSdr146992 */ 680381a2a9aSdr146992 static int 6817ddc9b1aSDarren Reed ipv6_getmtu(net_handle_t neti, phy_if_t phy_ifdata, lif_if_t ifdata) 682381a2a9aSdr146992 { 6837ddc9b1aSDarren Reed netstack_t *ns; 6847ddc9b1aSDarren Reed 6857ddc9b1aSDarren Reed ns = neti->netd_stack->nts_netstack; 686f4b3ec61Sdh155122 ASSERT(ns != NULL); 687f4b3ec61Sdh155122 return (ip_getmtu_impl(phy_ifdata, ifdata, B_TRUE, ns->netstack_ip)); 688381a2a9aSdr146992 } 689381a2a9aSdr146992 690381a2a9aSdr146992 /* 691381a2a9aSdr146992 * Shared implementation to determine the MTU of a network interface 692381a2a9aSdr146992 */ 693381a2a9aSdr146992 /* ARGSUSED */ 694381a2a9aSdr146992 static int 695f4b3ec61Sdh155122 ip_getmtu_impl(phy_if_t phy_ifdata, lif_if_t ifdata, boolean_t isv6, 696f4b3ec61Sdh155122 ip_stack_t *ipst) 697381a2a9aSdr146992 { 698381a2a9aSdr146992 lif_if_t ipifid; 699381a2a9aSdr146992 ipif_t *ipif; 700381a2a9aSdr146992 int mtu; 701381a2a9aSdr146992 702381a2a9aSdr146992 ipifid = UNMAP_IPIF_ID(ifdata); 703381a2a9aSdr146992 704f4b3ec61Sdh155122 ipif = ipif_getby_indexes((uint_t)phy_ifdata, (uint_t)ipifid, 705f4b3ec61Sdh155122 isv6, ipst); 706381a2a9aSdr146992 if (ipif == NULL) 707381a2a9aSdr146992 return (0); 708381a2a9aSdr146992 709bd670b35SErik Nordmark mtu = ipif->ipif_ill->ill_mtu; 710381a2a9aSdr146992 ipif_refrele(ipif); 711381a2a9aSdr146992 712381a2a9aSdr146992 if (mtu == 0) { 713381a2a9aSdr146992 ill_t *ill; 714381a2a9aSdr146992 715381a2a9aSdr146992 if ((ill = ill_lookup_on_ifindex((uint_t)phy_ifdata, isv6, 716bd670b35SErik Nordmark ipst)) == NULL) { 717381a2a9aSdr146992 return (0); 718381a2a9aSdr146992 } 719bd670b35SErik Nordmark mtu = ill->ill_mtu; 720381a2a9aSdr146992 ill_refrele(ill); 721381a2a9aSdr146992 } 722381a2a9aSdr146992 723381a2a9aSdr146992 return (mtu); 724381a2a9aSdr146992 } 725381a2a9aSdr146992 726381a2a9aSdr146992 /* 727381a2a9aSdr146992 * Determine if path MTU discovery is enabled for IP 728381a2a9aSdr146992 */ 729381a2a9aSdr146992 static int 7307ddc9b1aSDarren Reed ip_getpmtuenabled(net_handle_t neti) 731381a2a9aSdr146992 { 7327ddc9b1aSDarren Reed netstack_t *ns; 7337ddc9b1aSDarren Reed 7347ddc9b1aSDarren Reed ns = neti->netd_stack->nts_netstack; 735f4b3ec61Sdh155122 ASSERT(ns != NULL); 7367ddc9b1aSDarren Reed return (ns->netstack_ip->ips_ip_path_mtu_discovery); 737381a2a9aSdr146992 } 738381a2a9aSdr146992 739381a2a9aSdr146992 /* 740381a2a9aSdr146992 * Get next interface from the current list of IPv4 physical network interfaces 741381a2a9aSdr146992 */ 742381a2a9aSdr146992 static phy_if_t 7437ddc9b1aSDarren Reed ip_phygetnext(net_handle_t neti, phy_if_t phy_ifdata) 744381a2a9aSdr146992 { 7457ddc9b1aSDarren Reed netstack_t *ns; 7467ddc9b1aSDarren Reed 7477ddc9b1aSDarren Reed ns = neti->netd_stack->nts_netstack; 748f4b3ec61Sdh155122 ASSERT(ns != NULL); 749f4b3ec61Sdh155122 return (ill_get_next_ifindex(phy_ifdata, B_FALSE, ns->netstack_ip)); 750381a2a9aSdr146992 } 751381a2a9aSdr146992 752381a2a9aSdr146992 /* 753381a2a9aSdr146992 * Get next interface from the current list of IPv6 physical network interfaces 754381a2a9aSdr146992 */ 755381a2a9aSdr146992 static phy_if_t 7567ddc9b1aSDarren Reed ipv6_phygetnext(net_handle_t neti, phy_if_t phy_ifdata) 757381a2a9aSdr146992 { 7587ddc9b1aSDarren Reed netstack_t *ns; 7597ddc9b1aSDarren Reed 7607ddc9b1aSDarren Reed ns = neti->netd_stack->nts_netstack; 761f4b3ec61Sdh155122 ASSERT(ns != NULL); 762f4b3ec61Sdh155122 return (ill_get_next_ifindex(phy_ifdata, B_TRUE, ns->netstack_ip)); 763381a2a9aSdr146992 } 764381a2a9aSdr146992 765381a2a9aSdr146992 /* 766381a2a9aSdr146992 * Determine if a network interface name exists for IPv4 767381a2a9aSdr146992 */ 768381a2a9aSdr146992 static phy_if_t 7697ddc9b1aSDarren Reed ip_phylookup(net_handle_t neti, const char *name) 770381a2a9aSdr146992 { 7717ddc9b1aSDarren Reed netstack_t *ns; 7727ddc9b1aSDarren Reed 7737ddc9b1aSDarren Reed ns = neti->netd_stack->nts_netstack; 774f4b3ec61Sdh155122 ASSERT(ns != NULL); 775f4b3ec61Sdh155122 return (ip_phylookup_impl(name, B_FALSE, ns->netstack_ip)); 776381a2a9aSdr146992 } 777381a2a9aSdr146992 778381a2a9aSdr146992 /* 779381a2a9aSdr146992 * Determine if a network interface name exists for IPv6 780381a2a9aSdr146992 */ 781381a2a9aSdr146992 static phy_if_t 7827ddc9b1aSDarren Reed ipv6_phylookup(net_handle_t neti, const char *name) 783381a2a9aSdr146992 { 7847ddc9b1aSDarren Reed netstack_t *ns; 7857ddc9b1aSDarren Reed 7867ddc9b1aSDarren Reed ns = neti->netd_stack->nts_netstack; 787f4b3ec61Sdh155122 ASSERT(ns != NULL); 788f4b3ec61Sdh155122 return (ip_phylookup_impl(name, B_TRUE, ns->netstack_ip)); 789381a2a9aSdr146992 } 790381a2a9aSdr146992 791381a2a9aSdr146992 /* 792381a2a9aSdr146992 * Implement looking up an ill_t based on the name supplied and matching 793381a2a9aSdr146992 * it up with either IPv4 or IPv6. ill_get_ifindex_by_name() is not used 794381a2a9aSdr146992 * because it does not match on the address family in addition to the name. 795381a2a9aSdr146992 */ 796381a2a9aSdr146992 static phy_if_t 797f4b3ec61Sdh155122 ip_phylookup_impl(const char *name, boolean_t isv6, ip_stack_t *ipst) 798381a2a9aSdr146992 { 799381a2a9aSdr146992 phy_if_t phy; 800381a2a9aSdr146992 ill_t *ill; 801381a2a9aSdr146992 802bd670b35SErik Nordmark ill = ill_lookup_on_name((char *)name, B_FALSE, isv6, NULL, ipst); 803381a2a9aSdr146992 if (ill == NULL) 804381a2a9aSdr146992 return (0); 805381a2a9aSdr146992 806e11c3f44Smeem phy = ill->ill_phyint->phyint_ifindex; 807381a2a9aSdr146992 808381a2a9aSdr146992 ill_refrele(ill); 809381a2a9aSdr146992 810381a2a9aSdr146992 return (phy); 811381a2a9aSdr146992 } 812381a2a9aSdr146992 813381a2a9aSdr146992 /* 814381a2a9aSdr146992 * Get next interface from the current list of IPv4 logical network interfaces 815381a2a9aSdr146992 */ 816381a2a9aSdr146992 static lif_if_t 8177ddc9b1aSDarren Reed ip_lifgetnext(net_handle_t neti, phy_if_t phy_ifdata, lif_if_t ifdata) 818381a2a9aSdr146992 { 8197ddc9b1aSDarren Reed netstack_t *ns; 8207ddc9b1aSDarren Reed 8217ddc9b1aSDarren Reed ns = neti->netd_stack->nts_netstack; 822f4b3ec61Sdh155122 ASSERT(ns != NULL); 823f4b3ec61Sdh155122 return (ip_lifgetnext_impl(phy_ifdata, ifdata, B_FALSE, 824f4b3ec61Sdh155122 ns->netstack_ip)); 825381a2a9aSdr146992 } 826381a2a9aSdr146992 827381a2a9aSdr146992 /* 828381a2a9aSdr146992 * Get next interface from the current list of IPv6 logical network interfaces 829381a2a9aSdr146992 */ 830381a2a9aSdr146992 static lif_if_t 8317ddc9b1aSDarren Reed ipv6_lifgetnext(net_handle_t neti, phy_if_t phy_ifdata, lif_if_t ifdata) 832381a2a9aSdr146992 { 8337ddc9b1aSDarren Reed netstack_t *ns; 8347ddc9b1aSDarren Reed 8357ddc9b1aSDarren Reed ns = neti->netd_stack->nts_netstack; 836f4b3ec61Sdh155122 ASSERT(ns != NULL); 837f4b3ec61Sdh155122 return (ip_lifgetnext_impl(phy_ifdata, ifdata, B_TRUE, 838f4b3ec61Sdh155122 ns->netstack_ip)); 839381a2a9aSdr146992 } 840381a2a9aSdr146992 841381a2a9aSdr146992 /* 842381a2a9aSdr146992 * Shared implementation to get next interface from the current list of 843381a2a9aSdr146992 * logical network interfaces 844381a2a9aSdr146992 */ 845381a2a9aSdr146992 static lif_if_t 846f4b3ec61Sdh155122 ip_lifgetnext_impl(phy_if_t phy_ifdata, lif_if_t ifdata, boolean_t isv6, 847f4b3ec61Sdh155122 ip_stack_t *ipst) 848381a2a9aSdr146992 { 849381a2a9aSdr146992 lif_if_t newidx, oldidx; 850381a2a9aSdr146992 boolean_t nextok; 851381a2a9aSdr146992 ipif_t *ipif; 852381a2a9aSdr146992 ill_t *ill; 853381a2a9aSdr146992 854bd670b35SErik Nordmark ill = ill_lookup_on_ifindex(phy_ifdata, isv6, ipst); 855381a2a9aSdr146992 if (ill == NULL) 856381a2a9aSdr146992 return (0); 857381a2a9aSdr146992 858381a2a9aSdr146992 if (ifdata != 0) { 859381a2a9aSdr146992 oldidx = UNMAP_IPIF_ID(ifdata); 860381a2a9aSdr146992 nextok = B_FALSE; 861381a2a9aSdr146992 } else { 862381a2a9aSdr146992 oldidx = 0; 863381a2a9aSdr146992 nextok = B_TRUE; 864381a2a9aSdr146992 } 865381a2a9aSdr146992 866381a2a9aSdr146992 mutex_enter(&ill->ill_lock); 867381a2a9aSdr146992 if (ill->ill_state_flags & ILL_CONDEMNED) { 868381a2a9aSdr146992 mutex_exit(&ill->ill_lock); 869381a2a9aSdr146992 ill_refrele(ill); 870381a2a9aSdr146992 return (0); 871381a2a9aSdr146992 } 872381a2a9aSdr146992 873381a2a9aSdr146992 /* 874381a2a9aSdr146992 * It's safe to iterate the ill_ipif list when holding an ill_lock. 875381a2a9aSdr146992 * And it's also safe to access ipif_id without ipif refhold. 876e11c3f44Smeem * See the field access rules in ip.h. 877381a2a9aSdr146992 */ 878381a2a9aSdr146992 for (ipif = ill->ill_ipif; ipif != NULL; ipif = ipif->ipif_next) { 879381a2a9aSdr146992 if (!IPIF_CAN_LOOKUP(ipif)) 880381a2a9aSdr146992 continue; 881381a2a9aSdr146992 if (nextok) { 882381a2a9aSdr146992 ipif_refhold_locked(ipif); 883381a2a9aSdr146992 break; 884381a2a9aSdr146992 } else if (oldidx == ipif->ipif_id) { 885381a2a9aSdr146992 nextok = B_TRUE; 886381a2a9aSdr146992 } 887381a2a9aSdr146992 } 888381a2a9aSdr146992 889381a2a9aSdr146992 mutex_exit(&ill->ill_lock); 890381a2a9aSdr146992 ill_refrele(ill); 891381a2a9aSdr146992 892381a2a9aSdr146992 if (ipif == NULL) 893381a2a9aSdr146992 return (0); 894381a2a9aSdr146992 895381a2a9aSdr146992 newidx = ipif->ipif_id; 896381a2a9aSdr146992 ipif_refrele(ipif); 897381a2a9aSdr146992 898381a2a9aSdr146992 return (MAP_IPIF_ID(newidx)); 899381a2a9aSdr146992 } 900381a2a9aSdr146992 901381a2a9aSdr146992 /* 902381a2a9aSdr146992 * Inject an IPv4 packet to or from an interface 903381a2a9aSdr146992 */ 904381a2a9aSdr146992 static int 9057ddc9b1aSDarren Reed ip_inject(net_handle_t neti, inject_t style, net_inject_t *packet) 906381a2a9aSdr146992 { 9077ddc9b1aSDarren Reed netstack_t *ns; 9087ddc9b1aSDarren Reed 9097ddc9b1aSDarren Reed ns = neti->netd_stack->nts_netstack; 910f4b3ec61Sdh155122 ASSERT(ns != NULL); 911f4b3ec61Sdh155122 return (ip_inject_impl(style, packet, B_FALSE, ns->netstack_ip)); 912381a2a9aSdr146992 } 913381a2a9aSdr146992 914381a2a9aSdr146992 915381a2a9aSdr146992 /* 916381a2a9aSdr146992 * Inject an IPv6 packet to or from an interface 917381a2a9aSdr146992 */ 918381a2a9aSdr146992 static int 9197ddc9b1aSDarren Reed ipv6_inject(net_handle_t neti, inject_t style, net_inject_t *packet) 920381a2a9aSdr146992 { 9217ddc9b1aSDarren Reed netstack_t *ns; 9227ddc9b1aSDarren Reed 9237ddc9b1aSDarren Reed ns = neti->netd_stack->nts_netstack; 924f4b3ec61Sdh155122 return (ip_inject_impl(style, packet, B_TRUE, ns->netstack_ip)); 925381a2a9aSdr146992 } 926381a2a9aSdr146992 927381a2a9aSdr146992 /* 928381a2a9aSdr146992 * Shared implementation to inject a packet to or from an interface 929381a2a9aSdr146992 * Return value: 930381a2a9aSdr146992 * 0: successful 931381a2a9aSdr146992 * -1: memory allocation failed 932381a2a9aSdr146992 * 1: other errors 933381a2a9aSdr146992 */ 934381a2a9aSdr146992 static int 935f4b3ec61Sdh155122 ip_inject_impl(inject_t style, net_inject_t *packet, boolean_t isv6, 936f4b3ec61Sdh155122 ip_stack_t *ipst) 937381a2a9aSdr146992 { 938381a2a9aSdr146992 ddi_taskq_t *tq = NULL; 939381a2a9aSdr146992 void (* func)(void *); 940381a2a9aSdr146992 injection_t *inject; 941381a2a9aSdr146992 mblk_t *mp; 942381a2a9aSdr146992 943381a2a9aSdr146992 ASSERT(packet != NULL); 944381a2a9aSdr146992 ASSERT(packet->ni_packet != NULL); 945381a2a9aSdr146992 ASSERT(packet->ni_packet->b_datap->db_type == M_DATA); 946381a2a9aSdr146992 947381a2a9aSdr146992 switch (style) { 948381a2a9aSdr146992 case NI_QUEUE_IN: 949381a2a9aSdr146992 inject = kmem_alloc(sizeof (*inject), KM_NOSLEEP); 950381a2a9aSdr146992 if (inject == NULL) 951381a2a9aSdr146992 return (-1); 952381a2a9aSdr146992 inject->inj_data = *packet; 953381a2a9aSdr146992 inject->inj_isv6 = isv6; 954381a2a9aSdr146992 /* 955381a2a9aSdr146992 * deliver up into the kernel, immitating its reception by a 956381a2a9aSdr146992 * network interface, add to list and schedule timeout 957381a2a9aSdr146992 */ 958381a2a9aSdr146992 func = ip_ni_queue_in_func; 959381a2a9aSdr146992 tq = eventq_queue_in; 960381a2a9aSdr146992 break; 961381a2a9aSdr146992 962381a2a9aSdr146992 case NI_QUEUE_OUT: 963381a2a9aSdr146992 inject = kmem_alloc(sizeof (*inject), KM_NOSLEEP); 964381a2a9aSdr146992 if (inject == NULL) 965381a2a9aSdr146992 return (-1); 966381a2a9aSdr146992 inject->inj_data = *packet; 967381a2a9aSdr146992 inject->inj_isv6 = isv6; 968381a2a9aSdr146992 /* 969381a2a9aSdr146992 * deliver out of the kernel, as if it were being sent via a 970381a2a9aSdr146992 * raw socket so that IPFilter will see it again, add to list 971381a2a9aSdr146992 * and schedule timeout 972381a2a9aSdr146992 */ 973381a2a9aSdr146992 func = ip_ni_queue_out_func; 974381a2a9aSdr146992 tq = eventq_queue_out; 975381a2a9aSdr146992 break; 976381a2a9aSdr146992 977bd670b35SErik Nordmark case NI_DIRECT_OUT: { 978381a2a9aSdr146992 struct sockaddr *sock; 979381a2a9aSdr146992 980bd670b35SErik Nordmark mp = packet->ni_packet; 981bd670b35SErik Nordmark 982381a2a9aSdr146992 sock = (struct sockaddr *)&packet->ni_addr; 983381a2a9aSdr146992 /* 984381a2a9aSdr146992 * ipfil_sendpkt was provided by surya to ease the 985381a2a9aSdr146992 * problems associated with sending out a packet. 986381a2a9aSdr146992 */ 987381a2a9aSdr146992 switch (ipfil_sendpkt(sock, mp, packet->ni_physical, 988bd670b35SErik Nordmark netstackid_to_zoneid( 989bd670b35SErik Nordmark ipst->ips_netstack->netstack_stackid))) { 990381a2a9aSdr146992 case 0 : 991381a2a9aSdr146992 case EINPROGRESS: 992381a2a9aSdr146992 return (0); 993381a2a9aSdr146992 case ECOMM : 994381a2a9aSdr146992 case ENONET : 995381a2a9aSdr146992 return (1); 996381a2a9aSdr146992 default : 997381a2a9aSdr146992 return (1); 998381a2a9aSdr146992 } 999381a2a9aSdr146992 /* NOTREACHED */ 1000381a2a9aSdr146992 } 1001381a2a9aSdr146992 default: 1002381a2a9aSdr146992 freemsg(packet->ni_packet); 1003381a2a9aSdr146992 return (1); 1004381a2a9aSdr146992 } 1005381a2a9aSdr146992 1006bd670b35SErik Nordmark ASSERT(tq != NULL); 1007bd670b35SErik Nordmark 1008f4b3ec61Sdh155122 inject->inj_ptr = ipst; 1009381a2a9aSdr146992 if (ddi_taskq_dispatch(tq, func, (void *)inject, 1010381a2a9aSdr146992 DDI_SLEEP) == DDI_FAILURE) { 1011381a2a9aSdr146992 ip2dbg(("ip_inject: ddi_taskq_dispatch failed\n")); 1012381a2a9aSdr146992 freemsg(packet->ni_packet); 1013381a2a9aSdr146992 return (1); 1014381a2a9aSdr146992 } 1015381a2a9aSdr146992 return (0); 1016381a2a9aSdr146992 } 1017381a2a9aSdr146992 1018381a2a9aSdr146992 /* 1019381a2a9aSdr146992 * Find the interface used for traffic to a given IPv4 address 1020381a2a9aSdr146992 */ 1021381a2a9aSdr146992 static phy_if_t 10227ddc9b1aSDarren Reed ip_routeto(net_handle_t neti, struct sockaddr *address, struct sockaddr *next) 1023381a2a9aSdr146992 { 10247ddc9b1aSDarren Reed netstack_t *ns; 10257ddc9b1aSDarren Reed 1026381a2a9aSdr146992 ASSERT(address != NULL); 1027381a2a9aSdr146992 1028381a2a9aSdr146992 if (address->sa_family != AF_INET) 1029381a2a9aSdr146992 return (0); 10307ddc9b1aSDarren Reed 10317ddc9b1aSDarren Reed ns = neti->netd_stack->nts_netstack; 10327ddc9b1aSDarren Reed ASSERT(ns != NULL); 10337ddc9b1aSDarren Reed 10347ddc9b1aSDarren Reed return (ip_routeto_impl(address, next, ns->netstack_ip)); 1035381a2a9aSdr146992 } 1036381a2a9aSdr146992 1037381a2a9aSdr146992 /* 1038381a2a9aSdr146992 * Find the interface used for traffic to a given IPv6 address 1039381a2a9aSdr146992 */ 1040381a2a9aSdr146992 static phy_if_t 10417ddc9b1aSDarren Reed ipv6_routeto(net_handle_t neti, struct sockaddr *address, struct sockaddr *next) 1042381a2a9aSdr146992 { 10437ddc9b1aSDarren Reed netstack_t *ns; 10447ddc9b1aSDarren Reed 1045381a2a9aSdr146992 ASSERT(address != NULL); 1046381a2a9aSdr146992 1047381a2a9aSdr146992 if (address->sa_family != AF_INET6) 1048381a2a9aSdr146992 return (0); 10497ddc9b1aSDarren Reed 10507ddc9b1aSDarren Reed ns = neti->netd_stack->nts_netstack; 10517ddc9b1aSDarren Reed ASSERT(ns != NULL); 10527ddc9b1aSDarren Reed 10537ddc9b1aSDarren Reed return (ip_routeto_impl(address, next, ns->netstack_ip)); 1054381a2a9aSdr146992 } 1055381a2a9aSdr146992 1056381a2a9aSdr146992 1057381a2a9aSdr146992 /* 10587ddc9b1aSDarren Reed * Find the interface used for traffic to an address. 10597ddc9b1aSDarren Reed * For lint reasons, next/next6/sin/sin6 are all declared and assigned 10607ddc9b1aSDarren Reed * a value at the top. The alternative would end up with two bunches 10617ddc9b1aSDarren Reed * of assignments, with each bunch setting half to NULL. 1062381a2a9aSdr146992 */ 1063381a2a9aSdr146992 static phy_if_t 10647ddc9b1aSDarren Reed ip_routeto_impl(struct sockaddr *address, struct sockaddr *nexthop, 10657ddc9b1aSDarren Reed ip_stack_t *ipst) 1066381a2a9aSdr146992 { 10677ddc9b1aSDarren Reed struct sockaddr_in6 *next6 = (struct sockaddr_in6 *)nexthop; 10687ddc9b1aSDarren Reed struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)address; 10697ddc9b1aSDarren Reed struct sockaddr_in *next = (struct sockaddr_in *)nexthop; 10707ddc9b1aSDarren Reed struct sockaddr_in *sin = (struct sockaddr_in *)address; 1071381a2a9aSdr146992 ire_t *ire; 1072bd670b35SErik Nordmark ire_t *nexthop_ire; 1073381a2a9aSdr146992 phy_if_t phy_if; 107472680cf5SDarren Reed zoneid_t zoneid; 107572680cf5SDarren Reed 107672680cf5SDarren Reed zoneid = netstackid_to_zoneid(ipst->ips_netstack->netstack_stackid); 1077381a2a9aSdr146992 1078381a2a9aSdr146992 if (address->sa_family == AF_INET6) { 1079bd670b35SErik Nordmark ire = ire_route_recursive_v6(&sin6->sin6_addr, 0, NULL, 10809e3469d3SErik Nordmark zoneid, NULL, MATCH_IRE_DSTONLY, IRR_ALLOCATE, 0, ipst, 10819e3469d3SErik Nordmark NULL, NULL, NULL); 1082381a2a9aSdr146992 } else { 1083bd670b35SErik Nordmark ire = ire_route_recursive_v4(sin->sin_addr.s_addr, 0, NULL, 10849e3469d3SErik Nordmark zoneid, NULL, MATCH_IRE_DSTONLY, IRR_ALLOCATE, 0, ipst, 10859e3469d3SErik Nordmark NULL, NULL, NULL); 1086381a2a9aSdr146992 } 1087bd670b35SErik Nordmark ASSERT(ire != NULL); 10887ddc9b1aSDarren Reed /* 10897ddc9b1aSDarren Reed * For some destinations, we have routes that are dead ends, so 10907ddc9b1aSDarren Reed * return to indicate that no physical interface can be used to 10917ddc9b1aSDarren Reed * reach the destination. 10927ddc9b1aSDarren Reed */ 1093bd670b35SErik Nordmark if (ire->ire_flags & (RTF_REJECT|RTF_BLACKHOLE)) { 1094bd670b35SErik Nordmark ire_refrele(ire); 1095bd670b35SErik Nordmark return (NULL); 1096bd670b35SErik Nordmark } 1097bd670b35SErik Nordmark 1098bd670b35SErik Nordmark nexthop_ire = ire_nexthop(ire); 1099bd670b35SErik Nordmark if (nexthop_ire == NULL) { 1100bd670b35SErik Nordmark ire_refrele(ire); 1101bd670b35SErik Nordmark return (0); 1102bd670b35SErik Nordmark } 1103bd670b35SErik Nordmark if (nexthop_ire->ire_flags & (RTF_REJECT|RTF_BLACKHOLE)) { 1104bd670b35SErik Nordmark ire_refrele(nexthop_ire); 110567c1caeeSnordmark ire_refrele(ire); 1106381a2a9aSdr146992 return (0); 110767c1caeeSnordmark } 1108381a2a9aSdr146992 1109bd670b35SErik Nordmark ASSERT(nexthop_ire->ire_ill != NULL); 11107ddc9b1aSDarren Reed 11117ddc9b1aSDarren Reed if (nexthop != NULL) { 11127ddc9b1aSDarren Reed if (address->sa_family == AF_INET6) { 1113bd670b35SErik Nordmark next6->sin6_addr = nexthop_ire->ire_addr_v6; 11147ddc9b1aSDarren Reed } else { 1115bd670b35SErik Nordmark next->sin_addr.s_addr = nexthop_ire->ire_addr; 11167ddc9b1aSDarren Reed } 11177ddc9b1aSDarren Reed } 11187ddc9b1aSDarren Reed 1119bd670b35SErik Nordmark phy_if = (phy_if_t)nexthop_ire->ire_ill->ill_phyint->phyint_ifindex; 1120381a2a9aSdr146992 ire_refrele(ire); 1121bd670b35SErik Nordmark ire_refrele(nexthop_ire); 1122381a2a9aSdr146992 1123381a2a9aSdr146992 return (phy_if); 1124381a2a9aSdr146992 } 1125381a2a9aSdr146992 1126381a2a9aSdr146992 /* 1127381a2a9aSdr146992 * Determine if checksumming is being used for the given packet. 1128381a2a9aSdr146992 * 1129381a2a9aSdr146992 * Return value: 1130381a2a9aSdr146992 * NET_HCK_NONE: full checksum recalculation is required 1131381a2a9aSdr146992 * NET_HCK_L3_FULL: full layer 3 checksum 1132381a2a9aSdr146992 * NET_HCK_L4_FULL: full layer 4 checksum 1133381a2a9aSdr146992 * NET_HCK_L4_PART: partial layer 4 checksum 1134381a2a9aSdr146992 */ 11357ddc9b1aSDarren Reed /*ARGSUSED*/ 1136381a2a9aSdr146992 static int 11377ddc9b1aSDarren Reed ip_ispartialchecksum(net_handle_t neti, mblk_t *mp) 1138381a2a9aSdr146992 { 1139381a2a9aSdr146992 int ret = 0; 1140381a2a9aSdr146992 1141381a2a9aSdr146992 ASSERT(mp != NULL); 1142381a2a9aSdr146992 1143381a2a9aSdr146992 if ((DB_CKSUMFLAGS(mp) & HCK_FULLCKSUM) != 0) { 1144381a2a9aSdr146992 ret |= (int)NET_HCK_L4_FULL; 1145381a2a9aSdr146992 if ((DB_CKSUMFLAGS(mp) & HCK_IPV4_HDRCKSUM) != 0) 1146381a2a9aSdr146992 ret |= (int)NET_HCK_L3_FULL; 1147381a2a9aSdr146992 } 1148381a2a9aSdr146992 if ((DB_CKSUMFLAGS(mp) & HCK_PARTIALCKSUM) != 0) { 1149381a2a9aSdr146992 ret |= (int)NET_HCK_L4_PART; 1150381a2a9aSdr146992 if ((DB_CKSUMFLAGS(mp) & HCK_IPV4_HDRCKSUM) != 0) 1151381a2a9aSdr146992 ret |= (int)NET_HCK_L3_FULL; 1152381a2a9aSdr146992 } 1153381a2a9aSdr146992 1154381a2a9aSdr146992 return (ret); 1155381a2a9aSdr146992 } 1156381a2a9aSdr146992 1157381a2a9aSdr146992 /* 1158381a2a9aSdr146992 * Return true or false, indicating whether the network and transport 1159381a2a9aSdr146992 * headers are correct. Use the capabilities flags and flags set in the 1160381a2a9aSdr146992 * dblk_t to determine whether or not the checksum is valid. 1161381a2a9aSdr146992 * 1162381a2a9aSdr146992 * Return: 1163381a2a9aSdr146992 * 0: the checksum was incorrect 1164381a2a9aSdr146992 * 1: the original checksum was correct 1165381a2a9aSdr146992 */ 11667ddc9b1aSDarren Reed /*ARGSUSED*/ 1167381a2a9aSdr146992 static int 11687ddc9b1aSDarren Reed ip_isvalidchecksum(net_handle_t neti, mblk_t *mp) 1169381a2a9aSdr146992 { 1170381a2a9aSdr146992 unsigned char *wptr; 1171381a2a9aSdr146992 ipha_t *ipha = (ipha_t *)mp->b_rptr; 1172381a2a9aSdr146992 int hlen; 1173381a2a9aSdr146992 int ret; 1174381a2a9aSdr146992 1175381a2a9aSdr146992 ASSERT(mp != NULL); 1176381a2a9aSdr146992 1177381a2a9aSdr146992 if (dohwcksum && 11780dc2366fSVenugopal Iyer ((DB_CKSUM16(mp) != 0xFFFF && 11790dc2366fSVenugopal Iyer (DB_CKSUMFLAGS(mp) & HCK_FULLCKSUM)) || 11800dc2366fSVenugopal Iyer (DB_CKSUMFLAGS(mp) & HCK_FULLCKSUM_OK)) && 11810dc2366fSVenugopal Iyer (DB_CKSUMFLAGS(mp) & HCK_IPV4_HDRCKSUM_OK)) 1182381a2a9aSdr146992 return (1); 1183381a2a9aSdr146992 1184381a2a9aSdr146992 hlen = (ipha->ipha_version_and_hdr_length & 0x0F) << 2; 1185381a2a9aSdr146992 1186381a2a9aSdr146992 /* 1187381a2a9aSdr146992 * Check that the mblk being passed in has enough data in it 1188381a2a9aSdr146992 * before blindly checking ip_cksum. 1189381a2a9aSdr146992 */ 1190381a2a9aSdr146992 if (msgdsize(mp) < hlen) 1191381a2a9aSdr146992 return (0); 1192381a2a9aSdr146992 1193381a2a9aSdr146992 if (mp->b_wptr < mp->b_rptr + hlen) { 1194381a2a9aSdr146992 if (pullupmsg(mp, hlen) == 0) 1195381a2a9aSdr146992 return (0); 1196381a2a9aSdr146992 wptr = mp->b_wptr; 1197381a2a9aSdr146992 } else { 1198381a2a9aSdr146992 wptr = mp->b_wptr; 1199381a2a9aSdr146992 mp->b_wptr = mp->b_rptr + hlen; 1200381a2a9aSdr146992 } 1201381a2a9aSdr146992 1202381a2a9aSdr146992 if (ipha->ipha_hdr_checksum == ip_cksum(mp, 0, ipha->ipha_hdr_checksum)) 1203381a2a9aSdr146992 ret = 1; 1204381a2a9aSdr146992 else 1205381a2a9aSdr146992 ret = 0; 1206381a2a9aSdr146992 mp->b_wptr = wptr; 1207381a2a9aSdr146992 1208381a2a9aSdr146992 return (ret); 1209381a2a9aSdr146992 } 1210381a2a9aSdr146992 1211381a2a9aSdr146992 /* 1212381a2a9aSdr146992 * Unsupported with IPv6 1213381a2a9aSdr146992 */ 1214381a2a9aSdr146992 /*ARGSUSED*/ 1215381a2a9aSdr146992 static int 12167ddc9b1aSDarren Reed ipv6_isvalidchecksum(net_handle_t neti, mblk_t *mp) 1217381a2a9aSdr146992 { 1218381a2a9aSdr146992 return (-1); 1219381a2a9aSdr146992 } 1220381a2a9aSdr146992 1221381a2a9aSdr146992 /* 1222381a2a9aSdr146992 * Determine the network addresses for an IPv4 interface 1223381a2a9aSdr146992 */ 1224381a2a9aSdr146992 static int 12257ddc9b1aSDarren Reed ip_getlifaddr(net_handle_t neti, phy_if_t phy_ifdata, lif_if_t ifdata, 12267ddc9b1aSDarren Reed size_t nelem, net_ifaddr_t type[], void *storage) 1227381a2a9aSdr146992 { 12287ddc9b1aSDarren Reed netstack_t *ns; 12297ddc9b1aSDarren Reed 12307ddc9b1aSDarren Reed ns = neti->netd_stack->nts_netstack; 1231f4b3ec61Sdh155122 ASSERT(ns != NULL); 1232381a2a9aSdr146992 return (ip_getlifaddr_impl(AF_INET, phy_ifdata, ifdata, 1233f4b3ec61Sdh155122 nelem, type, storage, ns->netstack_ip)); 1234381a2a9aSdr146992 } 1235381a2a9aSdr146992 1236381a2a9aSdr146992 /* 1237381a2a9aSdr146992 * Determine the network addresses for an IPv6 interface 1238381a2a9aSdr146992 */ 1239381a2a9aSdr146992 static int 12407ddc9b1aSDarren Reed ipv6_getlifaddr(net_handle_t neti, phy_if_t phy_ifdata, lif_if_t ifdata, 12417ddc9b1aSDarren Reed size_t nelem, net_ifaddr_t type[], void *storage) 1242381a2a9aSdr146992 { 12437ddc9b1aSDarren Reed netstack_t *ns; 12447ddc9b1aSDarren Reed 12457ddc9b1aSDarren Reed ns = neti->netd_stack->nts_netstack; 1246f4b3ec61Sdh155122 ASSERT(ns != NULL); 1247381a2a9aSdr146992 return (ip_getlifaddr_impl(AF_INET6, phy_ifdata, ifdata, 1248f4b3ec61Sdh155122 nelem, type, storage, ns->netstack_ip)); 1249381a2a9aSdr146992 } 1250381a2a9aSdr146992 1251381a2a9aSdr146992 /* 1252381a2a9aSdr146992 * Shared implementation to determine the network addresses for an interface 1253381a2a9aSdr146992 */ 1254381a2a9aSdr146992 /* ARGSUSED */ 1255381a2a9aSdr146992 static int 1256381a2a9aSdr146992 ip_getlifaddr_impl(sa_family_t family, phy_if_t phy_ifdata, 1257381a2a9aSdr146992 lif_if_t ifdata, size_t nelem, net_ifaddr_t type[], 1258f4b3ec61Sdh155122 struct sockaddr *storage, ip_stack_t *ipst) 1259381a2a9aSdr146992 { 1260381a2a9aSdr146992 struct sockaddr_in6 *sin6; 1261381a2a9aSdr146992 struct sockaddr_in *sin; 1262381a2a9aSdr146992 lif_if_t ipifid; 1263381a2a9aSdr146992 ipif_t *ipif; 1264381a2a9aSdr146992 int i; 1265381a2a9aSdr146992 1266381a2a9aSdr146992 ASSERT(type != NULL); 1267381a2a9aSdr146992 ASSERT(storage != NULL); 1268381a2a9aSdr146992 1269381a2a9aSdr146992 ipifid = UNMAP_IPIF_ID(ifdata); 1270381a2a9aSdr146992 1271381a2a9aSdr146992 if (family == AF_INET) { 1272381a2a9aSdr146992 if ((ipif = ipif_getby_indexes((uint_t)phy_ifdata, 1273f4b3ec61Sdh155122 (uint_t)ipifid, B_FALSE, ipst)) == NULL) 1274381a2a9aSdr146992 return (1); 1275381a2a9aSdr146992 1276381a2a9aSdr146992 sin = (struct sockaddr_in *)storage; 1277381a2a9aSdr146992 for (i = 0; i < nelem; i++, sin++) { 1278381a2a9aSdr146992 if (ip_getifaddr_type(AF_INET, ipif, type[i], 1279381a2a9aSdr146992 &sin->sin_addr) < 0) { 1280381a2a9aSdr146992 ip2dbg(("ip_getlifaddr_impl failed type %d\n", 1281381a2a9aSdr146992 type[i])); 1282381a2a9aSdr146992 ipif_refrele(ipif); 1283381a2a9aSdr146992 return (1); 1284381a2a9aSdr146992 } 12858ad74188SDarren Reed sin->sin_family = AF_INET; 1286381a2a9aSdr146992 } 1287381a2a9aSdr146992 } else { 1288381a2a9aSdr146992 if ((ipif = ipif_getby_indexes((uint_t)phy_ifdata, 1289f4b3ec61Sdh155122 (uint_t)ipifid, B_TRUE, ipst)) == NULL) 1290381a2a9aSdr146992 return (1); 1291381a2a9aSdr146992 1292381a2a9aSdr146992 sin6 = (struct sockaddr_in6 *)storage; 1293381a2a9aSdr146992 for (i = 0; i < nelem; i++, sin6++) { 1294381a2a9aSdr146992 if (ip_getifaddr_type(AF_INET6, ipif, type[i], 1295381a2a9aSdr146992 &sin6->sin6_addr) < 0) { 1296381a2a9aSdr146992 ip2dbg(("ip_getlifaddr_impl failed type %d\n", 1297381a2a9aSdr146992 type[i])); 1298381a2a9aSdr146992 ipif_refrele(ipif); 1299381a2a9aSdr146992 return (1); 1300381a2a9aSdr146992 } 13018ad74188SDarren Reed sin6->sin6_family = AF_INET6; 1302381a2a9aSdr146992 } 1303381a2a9aSdr146992 } 1304381a2a9aSdr146992 ipif_refrele(ipif); 1305381a2a9aSdr146992 return (0); 1306381a2a9aSdr146992 } 1307381a2a9aSdr146992 1308381a2a9aSdr146992 /* 1309381a2a9aSdr146992 * ip_getlifaddr private function 1310381a2a9aSdr146992 */ 1311381a2a9aSdr146992 static int 1312381a2a9aSdr146992 ip_getifaddr_type(sa_family_t family, ipif_t *ill_ipif, 1313381a2a9aSdr146992 lif_if_t type, void *storage) 1314381a2a9aSdr146992 { 1315381a2a9aSdr146992 void *src_addr; 1316381a2a9aSdr146992 int mem_size; 1317381a2a9aSdr146992 1318381a2a9aSdr146992 ASSERT(ill_ipif != NULL); 1319381a2a9aSdr146992 ASSERT(storage != NULL); 1320381a2a9aSdr146992 1321381a2a9aSdr146992 if (family == AF_INET) { 1322381a2a9aSdr146992 mem_size = sizeof (struct in_addr); 1323381a2a9aSdr146992 1324381a2a9aSdr146992 switch (type) { 1325381a2a9aSdr146992 case NA_ADDRESS: 1326381a2a9aSdr146992 src_addr = &(ill_ipif->ipif_lcl_addr); 1327381a2a9aSdr146992 break; 1328381a2a9aSdr146992 case NA_PEER: 1329381a2a9aSdr146992 src_addr = &(ill_ipif->ipif_pp_dst_addr); 1330381a2a9aSdr146992 break; 1331381a2a9aSdr146992 case NA_BROADCAST: 1332381a2a9aSdr146992 src_addr = &(ill_ipif->ipif_brd_addr); 1333381a2a9aSdr146992 break; 1334381a2a9aSdr146992 case NA_NETMASK: 1335381a2a9aSdr146992 src_addr = &(ill_ipif->ipif_net_mask); 1336381a2a9aSdr146992 break; 1337381a2a9aSdr146992 default: 1338381a2a9aSdr146992 return (-1); 1339381a2a9aSdr146992 /*NOTREACHED*/ 1340381a2a9aSdr146992 } 1341381a2a9aSdr146992 } else { 1342381a2a9aSdr146992 mem_size = sizeof (struct in6_addr); 1343381a2a9aSdr146992 1344381a2a9aSdr146992 switch (type) { 1345381a2a9aSdr146992 case NA_ADDRESS: 1346381a2a9aSdr146992 src_addr = &(ill_ipif->ipif_v6lcl_addr); 1347381a2a9aSdr146992 break; 1348381a2a9aSdr146992 case NA_PEER: 1349381a2a9aSdr146992 src_addr = &(ill_ipif->ipif_v6pp_dst_addr); 1350381a2a9aSdr146992 break; 1351381a2a9aSdr146992 case NA_BROADCAST: 1352381a2a9aSdr146992 src_addr = &(ill_ipif->ipif_v6brd_addr); 1353381a2a9aSdr146992 break; 1354381a2a9aSdr146992 case NA_NETMASK: 1355381a2a9aSdr146992 src_addr = &(ill_ipif->ipif_v6net_mask); 1356381a2a9aSdr146992 break; 1357381a2a9aSdr146992 default: 1358381a2a9aSdr146992 return (-1); 1359381a2a9aSdr146992 /*NOTREACHED*/ 1360381a2a9aSdr146992 } 1361381a2a9aSdr146992 } 1362381a2a9aSdr146992 1363381a2a9aSdr146992 (void) memcpy(storage, src_addr, mem_size); 1364381a2a9aSdr146992 return (1); 1365381a2a9aSdr146992 } 1366381a2a9aSdr146992 1367381a2a9aSdr146992 /* 1368b127ac41SPhilip Kirk * Shared implementation to determine the zoneid associated with an IPv4/IPv6 1369b127ac41SPhilip Kirk * address 1370b127ac41SPhilip Kirk */ 1371b127ac41SPhilip Kirk static int 1372b127ac41SPhilip Kirk ip_getlifzone_impl(sa_family_t family, phy_if_t phy_ifdata, lif_if_t ifdata, 1373b127ac41SPhilip Kirk ip_stack_t *ipst, zoneid_t *zoneid) 1374b127ac41SPhilip Kirk { 1375b127ac41SPhilip Kirk ipif_t *ipif; 1376b127ac41SPhilip Kirk 1377b127ac41SPhilip Kirk ipif = ipif_getby_indexes((uint_t)phy_ifdata, 1378b127ac41SPhilip Kirk UNMAP_IPIF_ID((uint_t)ifdata), (family == AF_INET6), ipst); 1379b127ac41SPhilip Kirk if (ipif == NULL) 1380b127ac41SPhilip Kirk return (-1); 1381b127ac41SPhilip Kirk *zoneid = IP_REAL_ZONEID(ipif->ipif_zoneid, ipst); 1382b127ac41SPhilip Kirk ipif_refrele(ipif); 1383b127ac41SPhilip Kirk return (0); 1384b127ac41SPhilip Kirk } 1385b127ac41SPhilip Kirk 1386b127ac41SPhilip Kirk /* 1387b127ac41SPhilip Kirk * Determine the zoneid associated with an IPv4 address 1388b127ac41SPhilip Kirk */ 1389b127ac41SPhilip Kirk static int 1390b127ac41SPhilip Kirk ip_getlifzone(net_handle_t neti, phy_if_t phy_ifdata, lif_if_t ifdata, 1391b127ac41SPhilip Kirk zoneid_t *zoneid) 1392b127ac41SPhilip Kirk { 1393b127ac41SPhilip Kirk return (ip_getlifzone_impl(AF_INET, phy_ifdata, ifdata, 1394b127ac41SPhilip Kirk neti->netd_stack->nts_netstack->netstack_ip, zoneid)); 1395b127ac41SPhilip Kirk } 1396b127ac41SPhilip Kirk 1397b127ac41SPhilip Kirk /* 1398b127ac41SPhilip Kirk * Determine the zoneid associated with an IPv6 address 1399b127ac41SPhilip Kirk */ 1400b127ac41SPhilip Kirk static int 1401b127ac41SPhilip Kirk ipv6_getlifzone(net_handle_t neti, phy_if_t phy_ifdata, lif_if_t ifdata, 1402b127ac41SPhilip Kirk zoneid_t *zoneid) 1403b127ac41SPhilip Kirk { 1404b127ac41SPhilip Kirk return (ip_getlifzone_impl(AF_INET6, phy_ifdata, ifdata, 1405b127ac41SPhilip Kirk neti->netd_stack->nts_netstack->netstack_ip, zoneid)); 1406b127ac41SPhilip Kirk } 1407b127ac41SPhilip Kirk 14080a0e9771SDarren Reed /* 14090a0e9771SDarren Reed * The behaviour here mirrors that for the SIOCFLIFFLAGS ioctl where the 14100a0e9771SDarren Reed * union of all of the relevant flags is returned. 14110a0e9771SDarren Reed */ 1412b127ac41SPhilip Kirk static int 1413b127ac41SPhilip Kirk ip_getlifflags_impl(sa_family_t family, phy_if_t phy_ifdata, lif_if_t ifdata, 1414b127ac41SPhilip Kirk ip_stack_t *ipst, uint64_t *flags) 1415b127ac41SPhilip Kirk { 14160a0e9771SDarren Reed phyint_t *phyi; 1417b127ac41SPhilip Kirk ipif_t *ipif; 14180a0e9771SDarren Reed ill_t *ill; 14190a0e9771SDarren Reed 1420bd670b35SErik Nordmark ill = ill_lookup_on_ifindex(phy_ifdata, (family == AF_INET6), ipst); 14210a0e9771SDarren Reed if (ill == NULL) 14220a0e9771SDarren Reed return (-1); 14230a0e9771SDarren Reed phyi = ill->ill_phyint; 1424b127ac41SPhilip Kirk 1425b127ac41SPhilip Kirk ipif = ipif_getby_indexes((uint_t)phy_ifdata, 1426b127ac41SPhilip Kirk UNMAP_IPIF_ID((uint_t)ifdata), (family == AF_INET6), ipst); 14270a0e9771SDarren Reed if (ipif == NULL) { 14280a0e9771SDarren Reed ill_refrele(ill); 1429b127ac41SPhilip Kirk return (-1); 14300a0e9771SDarren Reed } 14310a0e9771SDarren Reed *flags = ipif->ipif_flags | ill->ill_flags | phyi->phyint_flags; 1432b127ac41SPhilip Kirk ipif_refrele(ipif); 14330a0e9771SDarren Reed ill_refrele(ill); 1434b127ac41SPhilip Kirk return (0); 1435b127ac41SPhilip Kirk } 1436b127ac41SPhilip Kirk 1437b127ac41SPhilip Kirk static int 1438b127ac41SPhilip Kirk ip_getlifflags(net_handle_t neti, phy_if_t phy_ifdata, lif_if_t ifdata, 1439b127ac41SPhilip Kirk uint64_t *flags) 1440b127ac41SPhilip Kirk { 1441b127ac41SPhilip Kirk return (ip_getlifflags_impl(AF_INET, phy_ifdata, ifdata, 1442b127ac41SPhilip Kirk neti->netd_stack->nts_netstack->netstack_ip, flags)); 1443b127ac41SPhilip Kirk } 1444b127ac41SPhilip Kirk 1445b127ac41SPhilip Kirk static int 1446b127ac41SPhilip Kirk ipv6_getlifflags(net_handle_t neti, phy_if_t phy_ifdata, lif_if_t ifdata, 1447b127ac41SPhilip Kirk uint64_t *flags) 1448b127ac41SPhilip Kirk { 1449b127ac41SPhilip Kirk return (ip_getlifflags_impl(AF_INET6, phy_ifdata, ifdata, 1450b127ac41SPhilip Kirk neti->netd_stack->nts_netstack->netstack_ip, flags)); 1451b127ac41SPhilip Kirk } 1452b127ac41SPhilip Kirk 1453b127ac41SPhilip Kirk /* 1454381a2a9aSdr146992 * Deliver packet up into the kernel, immitating its reception by a 1455381a2a9aSdr146992 * network interface. 1456381a2a9aSdr146992 */ 1457381a2a9aSdr146992 static void 1458381a2a9aSdr146992 ip_ni_queue_in_func(void *inject) 1459381a2a9aSdr146992 { 1460381a2a9aSdr146992 ip_ni_queue_func_impl(inject, B_FALSE); 1461381a2a9aSdr146992 } 1462381a2a9aSdr146992 1463381a2a9aSdr146992 /* 1464381a2a9aSdr146992 * Deliver out of the kernel, as if it were being sent via a 1465381a2a9aSdr146992 * raw socket so that IPFilter will see it again. 1466381a2a9aSdr146992 */ 1467381a2a9aSdr146992 static void 1468381a2a9aSdr146992 ip_ni_queue_out_func(void *inject) 1469381a2a9aSdr146992 { 1470381a2a9aSdr146992 ip_ni_queue_func_impl(inject, B_TRUE); 1471381a2a9aSdr146992 } 1472381a2a9aSdr146992 1473381a2a9aSdr146992 /* 1474381a2a9aSdr146992 * Shared implementation for inject via ip_output and ip_input 1475381a2a9aSdr146992 */ 1476381a2a9aSdr146992 static void 1477381a2a9aSdr146992 ip_ni_queue_func_impl(injection_t *inject, boolean_t out) 1478381a2a9aSdr146992 { 1479381a2a9aSdr146992 net_inject_t *packet; 1480381a2a9aSdr146992 ill_t *ill; 1481f4b3ec61Sdh155122 ip_stack_t *ipst = (ip_stack_t *)inject->inj_ptr; 1482bd670b35SErik Nordmark ip_xmit_attr_t ixas; 1483381a2a9aSdr146992 1484381a2a9aSdr146992 ASSERT(inject != NULL); 1485381a2a9aSdr146992 packet = &inject->inj_data; 1486381a2a9aSdr146992 ASSERT(packet->ni_packet != NULL); 1487381a2a9aSdr146992 1488bd670b35SErik Nordmark if (out == 0) { 148967c1caeeSnordmark ill = ill_lookup_on_ifindex((uint_t)packet->ni_physical, 1490bd670b35SErik Nordmark inject->inj_isv6, ipst); 1491bd670b35SErik Nordmark 149267c1caeeSnordmark if (ill == NULL) { 1493381a2a9aSdr146992 kmem_free(inject, sizeof (*inject)); 1494381a2a9aSdr146992 return; 1495381a2a9aSdr146992 } 1496381a2a9aSdr146992 1497381a2a9aSdr146992 if (inject->inj_isv6) { 1498bd670b35SErik Nordmark ip_input_v6(ill, NULL, packet->ni_packet, NULL); 1499381a2a9aSdr146992 } else { 1500da14cebeSEric Cheng ip_input(ill, NULL, packet->ni_packet, NULL); 1501381a2a9aSdr146992 } 1502381a2a9aSdr146992 ill_refrele(ill); 1503381a2a9aSdr146992 } else { 1504bd670b35SErik Nordmark bzero(&ixas, sizeof (ixas)); 1505bd670b35SErik Nordmark ixas.ixa_ifindex = packet->ni_physical; 1506bd670b35SErik Nordmark ixas.ixa_ipst = ipst; 1507bd670b35SErik Nordmark if (inject->inj_isv6) { 1508bd670b35SErik Nordmark ixas.ixa_flags = IXAF_BASIC_SIMPLE_V6; 1509bd670b35SErik Nordmark } else { 1510bd670b35SErik Nordmark ixas.ixa_flags = IXAF_BASIC_SIMPLE_V4; 1511381a2a9aSdr146992 } 1512*3e87ae12SSowmini Varadhan ixas.ixa_flags &= ~IXAF_VERIFY_SOURCE; 1513bd670b35SErik Nordmark (void) ip_output_simple(packet->ni_packet, &ixas); 1514bd670b35SErik Nordmark ixa_cleanup(&ixas); 1515381a2a9aSdr146992 } 1516381a2a9aSdr146992 1517381a2a9aSdr146992 kmem_free(inject, sizeof (*inject)); 1518381a2a9aSdr146992 } 1519381a2a9aSdr146992 1520381a2a9aSdr146992 /* 1521381a2a9aSdr146992 * taskq function for nic events. 1522381a2a9aSdr146992 */ 1523381a2a9aSdr146992 void 1524381a2a9aSdr146992 ip_ne_queue_func(void *arg) 1525381a2a9aSdr146992 { 15267ddc9b1aSDarren Reed hook_event_token_t hr; 15277ddc9b1aSDarren Reed hook_nic_event_int_t *info = (hook_nic_event_int_t *)arg; 15287ddc9b1aSDarren Reed ip_stack_t *ipst; 15297ddc9b1aSDarren Reed netstack_t *ns; 1530381a2a9aSdr146992 15317ddc9b1aSDarren Reed ns = netstack_find_by_stackid(info->hnei_stackid); 15327ddc9b1aSDarren Reed if (ns == NULL) 15337ddc9b1aSDarren Reed goto done; 15347ddc9b1aSDarren Reed 15357ddc9b1aSDarren Reed ipst = ns->netstack_ip; 15367ddc9b1aSDarren Reed if (ipst == NULL) 15377ddc9b1aSDarren Reed goto done; 15387ddc9b1aSDarren Reed 15397ddc9b1aSDarren Reed hr = (info->hnei_event.hne_protocol == ipst->ips_ipv6_net_data) ? 1540f4b3ec61Sdh155122 ipst->ips_ipv6nicevents : ipst->ips_ipv4nicevents; 15417ddc9b1aSDarren Reed (void) hook_run(info->hnei_event.hne_protocol->netd_hooks, hr, 15427ddc9b1aSDarren Reed (hook_data_t)&info->hnei_event); 1543381a2a9aSdr146992 15447ddc9b1aSDarren Reed done: 15457ddc9b1aSDarren Reed if (ns != NULL) 15467ddc9b1aSDarren Reed netstack_rele(ns); 15477ddc9b1aSDarren Reed kmem_free(info->hnei_event.hne_data, info->hnei_event.hne_datalen); 15487ddc9b1aSDarren Reed kmem_free(arg, sizeof (hook_nic_event_int_t)); 1549381a2a9aSdr146992 } 1550bd670b35SErik Nordmark 1551bd670b35SErik Nordmark /* 1552bd670b35SErik Nordmark * Initialize ARP hook family and events 1553bd670b35SErik Nordmark */ 1554bd670b35SErik Nordmark void 1555bd670b35SErik Nordmark arp_hook_init(ip_stack_t *ipst) 1556bd670b35SErik Nordmark { 1557bd670b35SErik Nordmark HOOK_FAMILY_INIT(&ipst->ips_arproot, Hn_ARP); 1558bd670b35SErik Nordmark if (net_family_register(ipst->ips_arp_net_data, &ipst->ips_arproot) 1559bd670b35SErik Nordmark != 0) { 1560bd670b35SErik Nordmark cmn_err(CE_NOTE, "arp_hook_init" 1561bd670b35SErik Nordmark "net_family_register failed for arp"); 1562bd670b35SErik Nordmark } 1563bd670b35SErik Nordmark 1564bd670b35SErik Nordmark HOOK_EVENT_INIT(&ipst->ips_arp_physical_in_event, NH_PHYSICAL_IN); 1565bd670b35SErik Nordmark ipst->ips_arp_physical_in = net_event_register(ipst->ips_arp_net_data, 1566bd670b35SErik Nordmark &ipst->ips_arp_physical_in_event); 1567bd670b35SErik Nordmark if (ipst->ips_arp_physical_in == NULL) { 1568bd670b35SErik Nordmark cmn_err(CE_NOTE, "arp_hook_init: " 1569bd670b35SErik Nordmark "net_event_register failed for arp/physical_in"); 1570bd670b35SErik Nordmark } 1571bd670b35SErik Nordmark 1572bd670b35SErik Nordmark HOOK_EVENT_INIT(&ipst->ips_arp_physical_out_event, NH_PHYSICAL_OUT); 1573bd670b35SErik Nordmark ipst->ips_arp_physical_out = net_event_register(ipst->ips_arp_net_data, 1574bd670b35SErik Nordmark &ipst->ips_arp_physical_out_event); 1575bd670b35SErik Nordmark if (ipst->ips_arp_physical_out == NULL) { 1576bd670b35SErik Nordmark cmn_err(CE_NOTE, "arp_hook_init: " 1577bd670b35SErik Nordmark "net_event_register failed for arp/physical_out"); 1578bd670b35SErik Nordmark } 1579bd670b35SErik Nordmark 1580bd670b35SErik Nordmark HOOK_EVENT_INIT(&ipst->ips_arp_nic_events, NH_NIC_EVENTS); 1581bd670b35SErik Nordmark ipst->ips_arpnicevents = net_event_register(ipst->ips_arp_net_data, 1582bd670b35SErik Nordmark &ipst->ips_arp_nic_events); 1583bd670b35SErik Nordmark if (ipst->ips_arpnicevents == NULL) { 1584bd670b35SErik Nordmark cmn_err(CE_NOTE, "arp_hook_init: " 1585bd670b35SErik Nordmark "net_event_register failed for arp/nic_events"); 1586bd670b35SErik Nordmark } 1587bd670b35SErik Nordmark } 1588bd670b35SErik Nordmark 1589bd670b35SErik Nordmark void 1590bd670b35SErik Nordmark arp_hook_destroy(ip_stack_t *ipst) 1591bd670b35SErik Nordmark { 1592bd670b35SErik Nordmark if (ipst->ips_arpnicevents != NULL) { 1593bd670b35SErik Nordmark if (net_event_unregister(ipst->ips_arp_net_data, 1594bd670b35SErik Nordmark &ipst->ips_arp_nic_events) == 0) 1595bd670b35SErik Nordmark ipst->ips_arpnicevents = NULL; 1596bd670b35SErik Nordmark } 1597bd670b35SErik Nordmark 1598bd670b35SErik Nordmark if (ipst->ips_arp_physical_out != NULL) { 1599bd670b35SErik Nordmark if (net_event_unregister(ipst->ips_arp_net_data, 1600bd670b35SErik Nordmark &ipst->ips_arp_physical_out_event) == 0) 1601bd670b35SErik Nordmark ipst->ips_arp_physical_out = NULL; 1602bd670b35SErik Nordmark } 1603bd670b35SErik Nordmark 1604bd670b35SErik Nordmark if (ipst->ips_arp_physical_in != NULL) { 1605bd670b35SErik Nordmark if (net_event_unregister(ipst->ips_arp_net_data, 1606bd670b35SErik Nordmark &ipst->ips_arp_physical_in_event) == 0) 1607bd670b35SErik Nordmark ipst->ips_arp_physical_in = NULL; 1608bd670b35SErik Nordmark } 1609bd670b35SErik Nordmark 1610bd670b35SErik Nordmark (void) net_family_unregister(ipst->ips_arp_net_data, 1611bd670b35SErik Nordmark &ipst->ips_arproot); 1612bd670b35SErik Nordmark } 1613bd670b35SErik Nordmark 1614bd670b35SErik Nordmark void 1615bd670b35SErik Nordmark arp_hook_shutdown(ip_stack_t *ipst) 1616bd670b35SErik Nordmark { 1617bd670b35SErik Nordmark if (ipst->ips_arp_physical_in != NULL) { 1618bd670b35SErik Nordmark (void) net_event_shutdown(ipst->ips_arp_net_data, 1619bd670b35SErik Nordmark &ipst->ips_arp_physical_in_event); 1620bd670b35SErik Nordmark } 1621bd670b35SErik Nordmark if (ipst->ips_arp_physical_out != NULL) { 1622bd670b35SErik Nordmark (void) net_event_shutdown(ipst->ips_arp_net_data, 1623bd670b35SErik Nordmark &ipst->ips_arp_physical_out_event); 1624bd670b35SErik Nordmark } 1625bd670b35SErik Nordmark if (ipst->ips_arpnicevents != NULL) { 1626bd670b35SErik Nordmark (void) net_event_shutdown(ipst->ips_arp_net_data, 1627bd670b35SErik Nordmark &ipst->ips_arp_nic_events); 1628bd670b35SErik Nordmark } 1629bd670b35SErik Nordmark } 1630bd670b35SErik Nordmark 1631bd670b35SErik Nordmark /* netinfo routines for the unsupported cases */ 1632bd670b35SErik Nordmark 1633bd670b35SErik Nordmark /* ARGSUSED */ 1634bd670b35SErik Nordmark int 1635bd670b35SErik Nordmark net_no_getmtu(net_handle_t handle, phy_if_t phy_ifdata, lif_if_t ifdata) 1636bd670b35SErik Nordmark { 1637bd670b35SErik Nordmark return (-1); 1638bd670b35SErik Nordmark } 1639bd670b35SErik Nordmark 1640bd670b35SErik Nordmark /* ARGSUSED */ 1641bd670b35SErik Nordmark static int 1642bd670b35SErik Nordmark net_no_getpmtuenabled(net_handle_t neti) 1643bd670b35SErik Nordmark { 1644bd670b35SErik Nordmark return (-1); 1645bd670b35SErik Nordmark } 1646bd670b35SErik Nordmark 1647bd670b35SErik Nordmark /* ARGSUSED */ 1648bd670b35SErik Nordmark static lif_if_t 1649bd670b35SErik Nordmark net_no_lifgetnext(net_handle_t neti, phy_if_t phy_ifdata, lif_if_t ifdata) 1650bd670b35SErik Nordmark { 1651bd670b35SErik Nordmark return (-1); 1652bd670b35SErik Nordmark } 1653bd670b35SErik Nordmark 1654bd670b35SErik Nordmark /* ARGSUSED */ 1655bd670b35SErik Nordmark static int 1656bd670b35SErik Nordmark net_no_inject(net_handle_t neti, inject_t style, net_inject_t *packet) 1657bd670b35SErik Nordmark { 1658bd670b35SErik Nordmark return (-1); 1659bd670b35SErik Nordmark } 1660bd670b35SErik Nordmark 1661bd670b35SErik Nordmark /* ARGSUSED */ 1662bd670b35SErik Nordmark static phy_if_t 1663bd670b35SErik Nordmark net_no_routeto(net_handle_t neti, struct sockaddr *address, 1664bd670b35SErik Nordmark struct sockaddr *next) 1665bd670b35SErik Nordmark { 1666bd670b35SErik Nordmark return ((phy_if_t)-1); 1667bd670b35SErik Nordmark } 1668bd670b35SErik Nordmark 1669bd670b35SErik Nordmark /* ARGSUSED */ 1670bd670b35SErik Nordmark static int 1671bd670b35SErik Nordmark net_no_ispartialchecksum(net_handle_t neti, mblk_t *mp) 1672bd670b35SErik Nordmark { 1673bd670b35SErik Nordmark return (-1); 1674bd670b35SErik Nordmark } 1675bd670b35SErik Nordmark 1676bd670b35SErik Nordmark /* ARGSUSED */ 1677bd670b35SErik Nordmark static int 1678bd670b35SErik Nordmark net_no_getlifaddr(net_handle_t neti, phy_if_t phy_ifdata, lif_if_t ifdata, 1679bd670b35SErik Nordmark size_t nelem, net_ifaddr_t type[], void *storage) 1680bd670b35SErik Nordmark { 1681bd670b35SErik Nordmark return (-1); 1682bd670b35SErik Nordmark } 1683bd670b35SErik Nordmark 1684bd670b35SErik Nordmark /* ARGSUSED */ 1685bd670b35SErik Nordmark static int 1686bd670b35SErik Nordmark net_no_getlifzone(net_handle_t neti, phy_if_t phy_ifdata, lif_if_t ifdata, 1687bd670b35SErik Nordmark zoneid_t *zoneid) 1688bd670b35SErik Nordmark { 1689bd670b35SErik Nordmark return (-1); 1690bd670b35SErik Nordmark } 1691bd670b35SErik Nordmark 1692bd670b35SErik Nordmark /* ARGSUSED */ 1693bd670b35SErik Nordmark static int 1694bd670b35SErik Nordmark net_no_getlifflags(net_handle_t neti, phy_if_t phy_ifdata, lif_if_t ifdata, 1695bd670b35SErik Nordmark uint64_t *flags) 1696bd670b35SErik Nordmark { 1697bd670b35SErik Nordmark return (-1); 1698bd670b35SErik Nordmark } 1699