12958Sdr146992 /* 22958Sdr146992 * CDDL HEADER START 32958Sdr146992 * 42958Sdr146992 * The contents of this file are subject to the terms of the 52958Sdr146992 * Common Development and Distribution License (the "License"). 62958Sdr146992 * You may not use this file except in compliance with the License. 72958Sdr146992 * 82958Sdr146992 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 92958Sdr146992 * or http://www.opensolaris.org/os/licensing. 102958Sdr146992 * See the License for the specific language governing permissions 112958Sdr146992 * and limitations under the License. 122958Sdr146992 * 132958Sdr146992 * When distributing Covered Code, include this CDDL HEADER in each 142958Sdr146992 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 152958Sdr146992 * If applicable, add the following below this CDDL HEADER, with the 162958Sdr146992 * fields enclosed by brackets "[]" replaced with your own identifying 172958Sdr146992 * information: Portions Copyright [yyyy] [name of copyright owner] 182958Sdr146992 * 192958Sdr146992 * CDDL HEADER END 202958Sdr146992 */ 212958Sdr146992 /* 22*11457SErik.Nordmark@Sun.COM * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 232958Sdr146992 * Use is subject to license terms. 242958Sdr146992 */ 252958Sdr146992 262958Sdr146992 #include <sys/param.h> 272958Sdr146992 #include <sys/types.h> 282958Sdr146992 #include <sys/systm.h> 292958Sdr146992 #include <sys/stream.h> 302958Sdr146992 #include <sys/strsubr.h> 312958Sdr146992 #include <sys/pattr.h> 322958Sdr146992 #include <sys/dlpi.h> 332958Sdr146992 #include <sys/atomic.h> 342958Sdr146992 #include <sys/sunddi.h> 352958Sdr146992 #include <sys/socket.h> 362958Sdr146992 #include <sys/neti.h> 376878Sbrendan #include <sys/sdt.h> 387513SDarren.Reed@Sun.COM #include <sys/cmn_err.h> 392958Sdr146992 402958Sdr146992 #include <netinet/in.h> 4111042SErik.Nordmark@Sun.COM #include <inet/ipsec_impl.h> 422958Sdr146992 #include <inet/common.h> 432958Sdr146992 #include <inet/mib2.h> 442958Sdr146992 #include <inet/ip.h> 452958Sdr146992 #include <inet/ip6.h> 462958Sdr146992 #include <inet/ip_if.h> 472958Sdr146992 #include <inet/ip_ire.h> 482958Sdr146992 #include <inet/ip_impl.h> 492958Sdr146992 #include <inet/ip_ndp.h> 502958Sdr146992 #include <inet/ipclassifier.h> 512958Sdr146992 #include <inet/ipp_common.h> 522958Sdr146992 #include <inet/ip_ftable.h> 532958Sdr146992 542958Sdr146992 /* 552958Sdr146992 * IPv4 netinfo entry point declarations. 562958Sdr146992 */ 577513SDarren.Reed@Sun.COM static int ip_getifname(net_handle_t, phy_if_t, char *, 587513SDarren.Reed@Sun.COM const size_t); 597513SDarren.Reed@Sun.COM static int ip_getmtu(net_handle_t, phy_if_t, lif_if_t); 607513SDarren.Reed@Sun.COM static int ip_getpmtuenabled(net_handle_t); 617513SDarren.Reed@Sun.COM static int ip_getlifaddr(net_handle_t, phy_if_t, lif_if_t, 627513SDarren.Reed@Sun.COM size_t, net_ifaddr_t [], void *); 638023SPhil.Kirk@Sun.COM static int ip_getlifzone(net_handle_t, phy_if_t, lif_if_t, 648023SPhil.Kirk@Sun.COM zoneid_t *); 658023SPhil.Kirk@Sun.COM static int ip_getlifflags(net_handle_t, phy_if_t, lif_if_t, 668023SPhil.Kirk@Sun.COM uint64_t *); 677513SDarren.Reed@Sun.COM static phy_if_t ip_phygetnext(net_handle_t, phy_if_t); 687513SDarren.Reed@Sun.COM static phy_if_t ip_phylookup(net_handle_t, const char *); 697513SDarren.Reed@Sun.COM static lif_if_t ip_lifgetnext(net_handle_t, phy_if_t, lif_if_t); 707513SDarren.Reed@Sun.COM static int ip_inject(net_handle_t, inject_t, net_inject_t *); 717513SDarren.Reed@Sun.COM static phy_if_t ip_routeto(net_handle_t, struct sockaddr *, 727513SDarren.Reed@Sun.COM struct sockaddr *); 737513SDarren.Reed@Sun.COM static int ip_ispartialchecksum(net_handle_t, mblk_t *); 747513SDarren.Reed@Sun.COM static int ip_isvalidchecksum(net_handle_t, mblk_t *); 752958Sdr146992 767513SDarren.Reed@Sun.COM static int ipv6_getifname(net_handle_t, phy_if_t, char *, 777513SDarren.Reed@Sun.COM const size_t); 787513SDarren.Reed@Sun.COM static int ipv6_getmtu(net_handle_t, phy_if_t, lif_if_t); 797513SDarren.Reed@Sun.COM static int ipv6_getlifaddr(net_handle_t, phy_if_t, lif_if_t, 807513SDarren.Reed@Sun.COM size_t, net_ifaddr_t [], void *); 818023SPhil.Kirk@Sun.COM static int ipv6_getlifzone(net_handle_t, phy_if_t, lif_if_t, 828023SPhil.Kirk@Sun.COM zoneid_t *); 838023SPhil.Kirk@Sun.COM static int ipv6_getlifflags(net_handle_t, phy_if_t, lif_if_t, 848023SPhil.Kirk@Sun.COM uint64_t *); 857513SDarren.Reed@Sun.COM static phy_if_t ipv6_phygetnext(net_handle_t, phy_if_t); 867513SDarren.Reed@Sun.COM static phy_if_t ipv6_phylookup(net_handle_t, const char *); 877513SDarren.Reed@Sun.COM static lif_if_t ipv6_lifgetnext(net_handle_t, phy_if_t, lif_if_t); 887513SDarren.Reed@Sun.COM static int ipv6_inject(net_handle_t, inject_t, net_inject_t *); 897513SDarren.Reed@Sun.COM static phy_if_t ipv6_routeto(net_handle_t, struct sockaddr *, 907513SDarren.Reed@Sun.COM struct sockaddr *); 917513SDarren.Reed@Sun.COM static int ipv6_isvalidchecksum(net_handle_t, mblk_t *); 922958Sdr146992 9311042SErik.Nordmark@Sun.COM static int net_no_getmtu(net_handle_t, phy_if_t, lif_if_t); 9411042SErik.Nordmark@Sun.COM static int net_no_getpmtuenabled(net_handle_t); 9511042SErik.Nordmark@Sun.COM static lif_if_t net_no_lifgetnext(net_handle_t, phy_if_t, lif_if_t); 9611042SErik.Nordmark@Sun.COM static int net_no_inject(net_handle_t, inject_t, net_inject_t *); 9711042SErik.Nordmark@Sun.COM static phy_if_t net_no_routeto(net_handle_t, struct sockaddr *, 9811042SErik.Nordmark@Sun.COM struct sockaddr *); 9911042SErik.Nordmark@Sun.COM static int net_no_ispartialchecksum(net_handle_t, mblk_t *); 10011042SErik.Nordmark@Sun.COM static int net_no_getlifaddr(net_handle_t, phy_if_t, lif_if_t, 10111042SErik.Nordmark@Sun.COM size_t, net_ifaddr_t [], void *); 10211042SErik.Nordmark@Sun.COM static int net_no_getlifzone(net_handle_t, phy_if_t, lif_if_t, 10311042SErik.Nordmark@Sun.COM zoneid_t *); 10411042SErik.Nordmark@Sun.COM static int net_no_getlifflags(net_handle_t, phy_if_t, lif_if_t, 10511042SErik.Nordmark@Sun.COM uint64_t *); 10611042SErik.Nordmark@Sun.COM 1072958Sdr146992 /* Netinfo private functions */ 1082958Sdr146992 static int ip_getifname_impl(phy_if_t, char *, 1097513SDarren.Reed@Sun.COM const size_t, boolean_t, ip_stack_t *); 1103448Sdh155122 static int ip_getmtu_impl(phy_if_t, lif_if_t, boolean_t, 1117513SDarren.Reed@Sun.COM ip_stack_t *); 1123448Sdh155122 static phy_if_t ip_phylookup_impl(const char *, boolean_t, 1137513SDarren.Reed@Sun.COM ip_stack_t *); 1143448Sdh155122 static lif_if_t ip_lifgetnext_impl(phy_if_t, lif_if_t, boolean_t, 1157513SDarren.Reed@Sun.COM ip_stack_t *); 1163448Sdh155122 static int ip_inject_impl(inject_t, net_inject_t *, boolean_t, 1177513SDarren.Reed@Sun.COM ip_stack_t *); 1182958Sdr146992 static int ip_getifaddr_type(sa_family_t, ipif_t *, lif_if_t, 1192958Sdr146992 void *); 1207513SDarren.Reed@Sun.COM static phy_if_t ip_routeto_impl(struct sockaddr *, struct sockaddr *, 1217513SDarren.Reed@Sun.COM ip_stack_t *); 1222958Sdr146992 static int ip_getlifaddr_impl(sa_family_t, phy_if_t, lif_if_t, 1233448Sdh155122 size_t, net_ifaddr_t [], struct sockaddr *, 1243448Sdh155122 ip_stack_t *); 1252958Sdr146992 static void ip_ni_queue_in_func(void *); 1262958Sdr146992 static void ip_ni_queue_out_func(void *); 1272958Sdr146992 static void ip_ni_queue_func_impl(injection_t *, boolean_t); 1282958Sdr146992 1297513SDarren.Reed@Sun.COM static net_protocol_t ipv4info = { 1302958Sdr146992 NETINFO_VERSION, 1312958Sdr146992 NHF_INET, 1322958Sdr146992 ip_getifname, 1332958Sdr146992 ip_getmtu, 1342958Sdr146992 ip_getpmtuenabled, 1352958Sdr146992 ip_getlifaddr, 1368023SPhil.Kirk@Sun.COM ip_getlifzone, 1378023SPhil.Kirk@Sun.COM ip_getlifflags, 1382958Sdr146992 ip_phygetnext, 1392958Sdr146992 ip_phylookup, 1402958Sdr146992 ip_lifgetnext, 1412958Sdr146992 ip_inject, 1422958Sdr146992 ip_routeto, 1432958Sdr146992 ip_ispartialchecksum, 1442958Sdr146992 ip_isvalidchecksum 1452958Sdr146992 }; 1462958Sdr146992 1472958Sdr146992 1487513SDarren.Reed@Sun.COM static net_protocol_t ipv6info = { 1492958Sdr146992 NETINFO_VERSION, 1502958Sdr146992 NHF_INET6, 1512958Sdr146992 ipv6_getifname, 1522958Sdr146992 ipv6_getmtu, 1532958Sdr146992 ip_getpmtuenabled, 1542958Sdr146992 ipv6_getlifaddr, 1558023SPhil.Kirk@Sun.COM ipv6_getlifzone, 1568023SPhil.Kirk@Sun.COM ipv6_getlifflags, 1572958Sdr146992 ipv6_phygetnext, 1582958Sdr146992 ipv6_phylookup, 1592958Sdr146992 ipv6_lifgetnext, 1602958Sdr146992 ipv6_inject, 1612958Sdr146992 ipv6_routeto, 1622958Sdr146992 ip_ispartialchecksum, 1632958Sdr146992 ipv6_isvalidchecksum 1642958Sdr146992 }; 1652958Sdr146992 16611042SErik.Nordmark@Sun.COM static net_protocol_t arp_netinfo = { 16711042SErik.Nordmark@Sun.COM NETINFO_VERSION, 16811042SErik.Nordmark@Sun.COM NHF_ARP, 16911042SErik.Nordmark@Sun.COM ip_getifname, 17011042SErik.Nordmark@Sun.COM net_no_getmtu, 17111042SErik.Nordmark@Sun.COM net_no_getpmtuenabled, 17211042SErik.Nordmark@Sun.COM net_no_getlifaddr, 17311042SErik.Nordmark@Sun.COM net_no_getlifzone, 17411042SErik.Nordmark@Sun.COM net_no_getlifflags, 17511042SErik.Nordmark@Sun.COM ip_phygetnext, 17611042SErik.Nordmark@Sun.COM ip_phylookup, 17711042SErik.Nordmark@Sun.COM net_no_lifgetnext, 17811042SErik.Nordmark@Sun.COM net_no_inject, 17911042SErik.Nordmark@Sun.COM net_no_routeto, 18011042SErik.Nordmark@Sun.COM net_no_ispartialchecksum, 18111042SErik.Nordmark@Sun.COM ip_isvalidchecksum 18211042SErik.Nordmark@Sun.COM }; 18311042SErik.Nordmark@Sun.COM 1842958Sdr146992 /* 1852958Sdr146992 * The taskq eventq_queue_in is used to process the upside inject messages. 1862958Sdr146992 * The taskq eventq_queue_out is used to process the downside inject messages. 1872958Sdr146992 * The taskq eventq_queue_nic is used to process the nic event messages. 1882958Sdr146992 */ 1892958Sdr146992 static ddi_taskq_t *eventq_queue_in = NULL; 1902958Sdr146992 static ddi_taskq_t *eventq_queue_out = NULL; 1912958Sdr146992 ddi_taskq_t *eventq_queue_nic = NULL; 1922958Sdr146992 1932958Sdr146992 /* 1943448Sdh155122 * Initialize queues for inject. 1952958Sdr146992 */ 1962958Sdr146992 void 1973448Sdh155122 ip_net_g_init() 1982958Sdr146992 { 1992958Sdr146992 if (eventq_queue_out == NULL) { 2002958Sdr146992 eventq_queue_out = ddi_taskq_create(NULL, 2012958Sdr146992 "IP_INJECT_QUEUE_OUT", 1, TASKQ_DEFAULTPRI, 0); 2022958Sdr146992 2032958Sdr146992 if (eventq_queue_out == NULL) 2042958Sdr146992 cmn_err(CE_NOTE, "ipv4_net_init: " 2052958Sdr146992 "ddi_taskq_create failed for IP_INJECT_QUEUE_OUT"); 2062958Sdr146992 } 2072958Sdr146992 2082958Sdr146992 if (eventq_queue_in == NULL) { 2092958Sdr146992 eventq_queue_in = ddi_taskq_create(NULL, 2102958Sdr146992 "IP_INJECT_QUEUE_IN", 1, TASKQ_DEFAULTPRI, 0); 2112958Sdr146992 2122958Sdr146992 if (eventq_queue_in == NULL) 2132958Sdr146992 cmn_err(CE_NOTE, "ipv4_net_init: " 2142958Sdr146992 "ddi_taskq_create failed for IP_INJECT_QUEUE_IN"); 2152958Sdr146992 } 2162958Sdr146992 2172958Sdr146992 if (eventq_queue_nic == NULL) { 2182958Sdr146992 eventq_queue_nic = ddi_taskq_create(NULL, 2192958Sdr146992 "IP_NIC_EVENT_QUEUE", 1, TASKQ_DEFAULTPRI, 0); 2202958Sdr146992 2212958Sdr146992 if (eventq_queue_nic == NULL) 2222958Sdr146992 cmn_err(CE_NOTE, "ipv4_net_init: " 2232958Sdr146992 "ddi_taskq_create failed for IP_NIC_EVENT_QUEUE"); 2242958Sdr146992 } 2252958Sdr146992 } 2262958Sdr146992 2272958Sdr146992 /* 2283448Sdh155122 * Destroy inject queues 2292958Sdr146992 */ 2302958Sdr146992 void 2313448Sdh155122 ip_net_g_destroy() 2322958Sdr146992 { 2332958Sdr146992 if (eventq_queue_nic != NULL) { 2342958Sdr146992 ddi_taskq_destroy(eventq_queue_nic); 2352958Sdr146992 eventq_queue_nic = NULL; 2362958Sdr146992 } 2372958Sdr146992 2382958Sdr146992 if (eventq_queue_in != NULL) { 2392958Sdr146992 ddi_taskq_destroy(eventq_queue_in); 2402958Sdr146992 eventq_queue_in = NULL; 2412958Sdr146992 } 2422958Sdr146992 2432958Sdr146992 if (eventq_queue_out != NULL) { 2442958Sdr146992 ddi_taskq_destroy(eventq_queue_out); 2452958Sdr146992 eventq_queue_out = NULL; 2462958Sdr146992 } 2473448Sdh155122 } 2482958Sdr146992 2493448Sdh155122 /* 2503448Sdh155122 * Register IPv4 and IPv6 netinfo functions and initialize queues for inject. 2513448Sdh155122 */ 2523448Sdh155122 void 2533448Sdh155122 ip_net_init(ip_stack_t *ipst, netstack_t *ns) 2543448Sdh155122 { 2557513SDarren.Reed@Sun.COM netid_t id; 2563448Sdh155122 2577513SDarren.Reed@Sun.COM id = net_getnetidbynetstackid(ns->netstack_stackid); 2587513SDarren.Reed@Sun.COM ASSERT(id != -1); 2597513SDarren.Reed@Sun.COM 2607513SDarren.Reed@Sun.COM ipst->ips_ipv4_net_data = net_protocol_register(id, &ipv4info); 2613448Sdh155122 ASSERT(ipst->ips_ipv4_net_data != NULL); 2623448Sdh155122 2637513SDarren.Reed@Sun.COM ipst->ips_ipv6_net_data = net_protocol_register(id, &ipv6info); 2643448Sdh155122 ASSERT(ipst->ips_ipv6_net_data != NULL); 26511042SErik.Nordmark@Sun.COM 26611042SErik.Nordmark@Sun.COM ipst->ips_arp_net_data = net_protocol_register(id, &arp_netinfo); 26711042SErik.Nordmark@Sun.COM ASSERT(ipst->ips_ipv6_net_data != NULL); 2683448Sdh155122 } 2693448Sdh155122 2703448Sdh155122 2713448Sdh155122 /* 2727915SDarren.Reed@Sun.COM * Unregister IPv4 and IPv6 functions. 2733448Sdh155122 */ 2743448Sdh155122 void 2753448Sdh155122 ip_net_destroy(ip_stack_t *ipst) 2763448Sdh155122 { 2773448Sdh155122 if (ipst->ips_ipv4_net_data != NULL) { 2787513SDarren.Reed@Sun.COM if (net_protocol_unregister(ipst->ips_ipv4_net_data) == 0) 2793448Sdh155122 ipst->ips_ipv4_net_data = NULL; 2802958Sdr146992 } 2812958Sdr146992 2823448Sdh155122 if (ipst->ips_ipv6_net_data != NULL) { 2837513SDarren.Reed@Sun.COM if (net_protocol_unregister(ipst->ips_ipv6_net_data) == 0) 2843448Sdh155122 ipst->ips_ipv6_net_data = NULL; 2852958Sdr146992 } 28611042SErik.Nordmark@Sun.COM 28711042SErik.Nordmark@Sun.COM if (ipst->ips_arp_net_data != NULL) { 28811042SErik.Nordmark@Sun.COM if (net_protocol_unregister(ipst->ips_arp_net_data) == 0) 28911042SErik.Nordmark@Sun.COM ipst->ips_arp_net_data = NULL; 29011042SErik.Nordmark@Sun.COM } 2912958Sdr146992 } 2922958Sdr146992 2932958Sdr146992 /* 2942958Sdr146992 * Initialize IPv4 hooks family the event 2952958Sdr146992 */ 2962958Sdr146992 void 2973448Sdh155122 ipv4_hook_init(ip_stack_t *ipst) 2982958Sdr146992 { 2993448Sdh155122 HOOK_FAMILY_INIT(&ipst->ips_ipv4root, Hn_IPV4); 3007513SDarren.Reed@Sun.COM if (net_family_register(ipst->ips_ipv4_net_data, &ipst->ips_ipv4root) 3013448Sdh155122 != 0) { 3022958Sdr146992 cmn_err(CE_NOTE, "ipv4_hook_init: " 3037513SDarren.Reed@Sun.COM "net_family_register failed for ipv4"); 3042958Sdr146992 } 3052958Sdr146992 3063448Sdh155122 HOOK_EVENT_INIT(&ipst->ips_ip4_physical_in_event, NH_PHYSICAL_IN); 3077513SDarren.Reed@Sun.COM ipst->ips_ipv4firewall_physical_in = net_event_register( 3083448Sdh155122 ipst->ips_ipv4_net_data, &ipst->ips_ip4_physical_in_event); 3093448Sdh155122 if (ipst->ips_ipv4firewall_physical_in == NULL) { 3102958Sdr146992 cmn_err(CE_NOTE, "ipv4_hook_init: " 3117513SDarren.Reed@Sun.COM "net_event_register failed for ipv4/physical_in"); 3122958Sdr146992 } 3132958Sdr146992 3143448Sdh155122 HOOK_EVENT_INIT(&ipst->ips_ip4_physical_out_event, NH_PHYSICAL_OUT); 3157513SDarren.Reed@Sun.COM ipst->ips_ipv4firewall_physical_out = net_event_register( 3163448Sdh155122 ipst->ips_ipv4_net_data, &ipst->ips_ip4_physical_out_event); 3173448Sdh155122 if (ipst->ips_ipv4firewall_physical_out == NULL) { 3182958Sdr146992 cmn_err(CE_NOTE, "ipv4_hook_init: " 3197513SDarren.Reed@Sun.COM "net_event_register failed for ipv4/physical_out"); 3202958Sdr146992 } 3212958Sdr146992 3223448Sdh155122 HOOK_EVENT_INIT(&ipst->ips_ip4_forwarding_event, NH_FORWARDING); 3237513SDarren.Reed@Sun.COM ipst->ips_ipv4firewall_forwarding = net_event_register( 3243448Sdh155122 ipst->ips_ipv4_net_data, &ipst->ips_ip4_forwarding_event); 3253448Sdh155122 if (ipst->ips_ipv4firewall_forwarding == NULL) { 3262958Sdr146992 cmn_err(CE_NOTE, "ipv4_hook_init: " 3277513SDarren.Reed@Sun.COM "net_event_register failed for ipv4/forwarding"); 3282958Sdr146992 } 3292958Sdr146992 3303448Sdh155122 HOOK_EVENT_INIT(&ipst->ips_ip4_loopback_in_event, NH_LOOPBACK_IN); 3317513SDarren.Reed@Sun.COM ipst->ips_ipv4firewall_loopback_in = net_event_register( 3323448Sdh155122 ipst->ips_ipv4_net_data, &ipst->ips_ip4_loopback_in_event); 3333448Sdh155122 if (ipst->ips_ipv4firewall_loopback_in == NULL) { 3342958Sdr146992 cmn_err(CE_NOTE, "ipv4_hook_init: " 3357513SDarren.Reed@Sun.COM "net_event_register failed for ipv4/loopback_in"); 3362958Sdr146992 } 3372958Sdr146992 3383448Sdh155122 HOOK_EVENT_INIT(&ipst->ips_ip4_loopback_out_event, NH_LOOPBACK_OUT); 3397513SDarren.Reed@Sun.COM ipst->ips_ipv4firewall_loopback_out = net_event_register( 3403448Sdh155122 ipst->ips_ipv4_net_data, &ipst->ips_ip4_loopback_out_event); 3413448Sdh155122 if (ipst->ips_ipv4firewall_loopback_out == NULL) { 3422958Sdr146992 cmn_err(CE_NOTE, "ipv4_hook_init: " 3437513SDarren.Reed@Sun.COM "net_event_register failed for ipv4/loopback_out"); 3442958Sdr146992 } 3452958Sdr146992 3463448Sdh155122 HOOK_EVENT_INIT(&ipst->ips_ip4_nic_events, NH_NIC_EVENTS); 3473448Sdh155122 ipst->ips_ip4_nic_events.he_flags = HOOK_RDONLY; 3487513SDarren.Reed@Sun.COM ipst->ips_ipv4nicevents = net_event_register( 3493448Sdh155122 ipst->ips_ipv4_net_data, &ipst->ips_ip4_nic_events); 3503448Sdh155122 if (ipst->ips_ipv4nicevents == NULL) { 3512958Sdr146992 cmn_err(CE_NOTE, "ipv4_hook_init: " 3527513SDarren.Reed@Sun.COM "net_event_register failed for ipv4/nic_events"); 3532958Sdr146992 } 35410639SDarren.Reed@Sun.COM 35510639SDarren.Reed@Sun.COM HOOK_EVENT_INIT(&ipst->ips_ip4_observe, NH_OBSERVE); 35610639SDarren.Reed@Sun.COM ipst->ips_ip4_observe.he_flags = HOOK_RDONLY; 35710639SDarren.Reed@Sun.COM ipst->ips_ipv4observing = net_event_register( 35810639SDarren.Reed@Sun.COM ipst->ips_ipv4_net_data, &ipst->ips_ip4_observe); 35910639SDarren.Reed@Sun.COM if (ipst->ips_ipv4observing == NULL) { 36010639SDarren.Reed@Sun.COM cmn_err(CE_NOTE, "ipv4_hook_init: " 36110639SDarren.Reed@Sun.COM "net_event_register failed for ipv4/observe"); 36210639SDarren.Reed@Sun.COM } 36310639SDarren.Reed@Sun.COM 3642958Sdr146992 } 3652958Sdr146992 3662958Sdr146992 void 3677915SDarren.Reed@Sun.COM ipv4_hook_shutdown(ip_stack_t *ipst) 3687915SDarren.Reed@Sun.COM { 3697915SDarren.Reed@Sun.COM if (ipst->ips_ipv4firewall_forwarding != NULL) { 3707915SDarren.Reed@Sun.COM (void) net_event_shutdown(ipst->ips_ipv4_net_data, 3717915SDarren.Reed@Sun.COM &ipst->ips_ip4_forwarding_event); 3727915SDarren.Reed@Sun.COM } 3737915SDarren.Reed@Sun.COM 3747915SDarren.Reed@Sun.COM if (ipst->ips_ipv4firewall_physical_in != NULL) { 3757915SDarren.Reed@Sun.COM (void) net_event_shutdown(ipst->ips_ipv4_net_data, 3767915SDarren.Reed@Sun.COM &ipst->ips_ip4_physical_in_event); 3777915SDarren.Reed@Sun.COM } 3787915SDarren.Reed@Sun.COM 3797915SDarren.Reed@Sun.COM if (ipst->ips_ipv4firewall_physical_out != NULL) { 3807915SDarren.Reed@Sun.COM (void) net_event_shutdown(ipst->ips_ipv4_net_data, 3817915SDarren.Reed@Sun.COM &ipst->ips_ip4_physical_out_event); 3827915SDarren.Reed@Sun.COM } 3837915SDarren.Reed@Sun.COM 3847915SDarren.Reed@Sun.COM if (ipst->ips_ipv4firewall_loopback_in != NULL) { 3857915SDarren.Reed@Sun.COM (void) net_event_shutdown(ipst->ips_ipv4_net_data, 3867915SDarren.Reed@Sun.COM &ipst->ips_ip4_loopback_in_event); 3877915SDarren.Reed@Sun.COM } 3887915SDarren.Reed@Sun.COM 3897915SDarren.Reed@Sun.COM if (ipst->ips_ipv4firewall_loopback_out != NULL) { 3907915SDarren.Reed@Sun.COM (void) net_event_shutdown(ipst->ips_ipv4_net_data, 3917915SDarren.Reed@Sun.COM &ipst->ips_ip4_loopback_out_event); 3927915SDarren.Reed@Sun.COM } 3937915SDarren.Reed@Sun.COM 3947915SDarren.Reed@Sun.COM if (ipst->ips_ipv4nicevents != NULL) { 3957915SDarren.Reed@Sun.COM (void) net_event_shutdown(ipst->ips_ipv4_net_data, 3967915SDarren.Reed@Sun.COM &ipst->ips_ip4_nic_events); 3977915SDarren.Reed@Sun.COM } 3987915SDarren.Reed@Sun.COM 39910639SDarren.Reed@Sun.COM if (ipst->ips_ipv4observing != NULL) { 40010639SDarren.Reed@Sun.COM (void) net_event_shutdown(ipst->ips_ipv4_net_data, 40110639SDarren.Reed@Sun.COM &ipst->ips_ip4_observe); 40210639SDarren.Reed@Sun.COM } 40310639SDarren.Reed@Sun.COM 4047915SDarren.Reed@Sun.COM (void) net_family_shutdown(ipst->ips_ipv4_net_data, 4057915SDarren.Reed@Sun.COM &ipst->ips_ipv4root); 4067915SDarren.Reed@Sun.COM } 4077915SDarren.Reed@Sun.COM 4087915SDarren.Reed@Sun.COM void 4093448Sdh155122 ipv4_hook_destroy(ip_stack_t *ipst) 4102958Sdr146992 { 4113448Sdh155122 if (ipst->ips_ipv4firewall_forwarding != NULL) { 4127513SDarren.Reed@Sun.COM if (net_event_unregister(ipst->ips_ipv4_net_data, 4133448Sdh155122 &ipst->ips_ip4_forwarding_event) == 0) 4143448Sdh155122 ipst->ips_ipv4firewall_forwarding = NULL; 4152958Sdr146992 } 4162958Sdr146992 4173448Sdh155122 if (ipst->ips_ipv4firewall_physical_in != NULL) { 4187513SDarren.Reed@Sun.COM if (net_event_unregister(ipst->ips_ipv4_net_data, 4193448Sdh155122 &ipst->ips_ip4_physical_in_event) == 0) 4203448Sdh155122 ipst->ips_ipv4firewall_physical_in = NULL; 4212958Sdr146992 } 4222958Sdr146992 4233448Sdh155122 if (ipst->ips_ipv4firewall_physical_out != NULL) { 4247513SDarren.Reed@Sun.COM if (net_event_unregister(ipst->ips_ipv4_net_data, 4253448Sdh155122 &ipst->ips_ip4_physical_out_event) == 0) 4263448Sdh155122 ipst->ips_ipv4firewall_physical_out = NULL; 4272958Sdr146992 } 4282958Sdr146992 4293448Sdh155122 if (ipst->ips_ipv4firewall_loopback_in != NULL) { 4307513SDarren.Reed@Sun.COM if (net_event_unregister(ipst->ips_ipv4_net_data, 4313448Sdh155122 &ipst->ips_ip4_loopback_in_event) == 0) 4323448Sdh155122 ipst->ips_ipv4firewall_loopback_in = NULL; 4332958Sdr146992 } 4342958Sdr146992 4353448Sdh155122 if (ipst->ips_ipv4firewall_loopback_out != NULL) { 4367513SDarren.Reed@Sun.COM if (net_event_unregister(ipst->ips_ipv4_net_data, 4373448Sdh155122 &ipst->ips_ip4_loopback_out_event) == 0) 4383448Sdh155122 ipst->ips_ipv4firewall_loopback_out = NULL; 4392958Sdr146992 } 4402958Sdr146992 4413448Sdh155122 if (ipst->ips_ipv4nicevents != NULL) { 4427513SDarren.Reed@Sun.COM if (net_event_unregister(ipst->ips_ipv4_net_data, 4433448Sdh155122 &ipst->ips_ip4_nic_events) == 0) 4443448Sdh155122 ipst->ips_ipv4nicevents = NULL; 4452958Sdr146992 } 4462958Sdr146992 44710639SDarren.Reed@Sun.COM if (ipst->ips_ipv4observing != NULL) { 44810639SDarren.Reed@Sun.COM if (net_event_unregister(ipst->ips_ipv4_net_data, 44910639SDarren.Reed@Sun.COM &ipst->ips_ip4_observe) == 0) 45010639SDarren.Reed@Sun.COM ipst->ips_ipv4observing = NULL; 45110639SDarren.Reed@Sun.COM } 45210639SDarren.Reed@Sun.COM 4537513SDarren.Reed@Sun.COM (void) net_family_unregister(ipst->ips_ipv4_net_data, 4543448Sdh155122 &ipst->ips_ipv4root); 4552958Sdr146992 } 4562958Sdr146992 4572958Sdr146992 /* 4582958Sdr146992 * Initialize IPv6 hooks family and event 4592958Sdr146992 */ 4602958Sdr146992 void 4613448Sdh155122 ipv6_hook_init(ip_stack_t *ipst) 4622958Sdr146992 { 4632958Sdr146992 4643448Sdh155122 HOOK_FAMILY_INIT(&ipst->ips_ipv6root, Hn_IPV6); 4657513SDarren.Reed@Sun.COM if (net_family_register(ipst->ips_ipv6_net_data, &ipst->ips_ipv6root) 4663448Sdh155122 != 0) { 4672958Sdr146992 cmn_err(CE_NOTE, "ipv6_hook_init: " 4687513SDarren.Reed@Sun.COM "net_family_register failed for ipv6"); 4692958Sdr146992 } 4702958Sdr146992 4713448Sdh155122 HOOK_EVENT_INIT(&ipst->ips_ip6_physical_in_event, NH_PHYSICAL_IN); 4727513SDarren.Reed@Sun.COM ipst->ips_ipv6firewall_physical_in = net_event_register( 4733448Sdh155122 ipst->ips_ipv6_net_data, &ipst->ips_ip6_physical_in_event); 4743448Sdh155122 if (ipst->ips_ipv6firewall_physical_in == NULL) { 4752958Sdr146992 cmn_err(CE_NOTE, "ipv6_hook_init: " 4767513SDarren.Reed@Sun.COM "net_event_register failed for ipv6/physical_in"); 4772958Sdr146992 } 4782958Sdr146992 4793448Sdh155122 HOOK_EVENT_INIT(&ipst->ips_ip6_physical_out_event, NH_PHYSICAL_OUT); 4807513SDarren.Reed@Sun.COM ipst->ips_ipv6firewall_physical_out = net_event_register( 4813448Sdh155122 ipst->ips_ipv6_net_data, &ipst->ips_ip6_physical_out_event); 4823448Sdh155122 if (ipst->ips_ipv6firewall_physical_out == NULL) { 4832958Sdr146992 cmn_err(CE_NOTE, "ipv6_hook_init: " 4847513SDarren.Reed@Sun.COM "net_event_register failed for ipv6/physical_out"); 4852958Sdr146992 } 4862958Sdr146992 4873448Sdh155122 HOOK_EVENT_INIT(&ipst->ips_ip6_forwarding_event, NH_FORWARDING); 4887513SDarren.Reed@Sun.COM ipst->ips_ipv6firewall_forwarding = net_event_register( 4893448Sdh155122 ipst->ips_ipv6_net_data, &ipst->ips_ip6_forwarding_event); 4903448Sdh155122 if (ipst->ips_ipv6firewall_forwarding == NULL) { 4912958Sdr146992 cmn_err(CE_NOTE, "ipv6_hook_init: " 4927513SDarren.Reed@Sun.COM "net_event_register failed for ipv6/forwarding"); 4932958Sdr146992 } 4942958Sdr146992 4953448Sdh155122 HOOK_EVENT_INIT(&ipst->ips_ip6_loopback_in_event, NH_LOOPBACK_IN); 4967513SDarren.Reed@Sun.COM ipst->ips_ipv6firewall_loopback_in = net_event_register( 4973448Sdh155122 ipst->ips_ipv6_net_data, &ipst->ips_ip6_loopback_in_event); 4983448Sdh155122 if (ipst->ips_ipv6firewall_loopback_in == NULL) { 4992958Sdr146992 cmn_err(CE_NOTE, "ipv6_hook_init: " 5007513SDarren.Reed@Sun.COM "net_event_register failed for ipv6/loopback_in"); 5012958Sdr146992 } 5022958Sdr146992 5033448Sdh155122 HOOK_EVENT_INIT(&ipst->ips_ip6_loopback_out_event, NH_LOOPBACK_OUT); 5047513SDarren.Reed@Sun.COM ipst->ips_ipv6firewall_loopback_out = net_event_register( 5053448Sdh155122 ipst->ips_ipv6_net_data, &ipst->ips_ip6_loopback_out_event); 5063448Sdh155122 if (ipst->ips_ipv6firewall_loopback_out == NULL) { 5072958Sdr146992 cmn_err(CE_NOTE, "ipv6_hook_init: " 5087513SDarren.Reed@Sun.COM "net_event_register failed for ipv6/loopback_out"); 5092958Sdr146992 } 5102958Sdr146992 5113448Sdh155122 HOOK_EVENT_INIT(&ipst->ips_ip6_nic_events, NH_NIC_EVENTS); 5123448Sdh155122 ipst->ips_ip6_nic_events.he_flags = HOOK_RDONLY; 5137513SDarren.Reed@Sun.COM ipst->ips_ipv6nicevents = net_event_register( 5143448Sdh155122 ipst->ips_ipv6_net_data, &ipst->ips_ip6_nic_events); 5153448Sdh155122 if (ipst->ips_ipv6nicevents == NULL) { 5162958Sdr146992 cmn_err(CE_NOTE, "ipv6_hook_init: " 5177513SDarren.Reed@Sun.COM "net_event_register failed for ipv6/nic_events"); 5182958Sdr146992 } 51910639SDarren.Reed@Sun.COM 52010639SDarren.Reed@Sun.COM HOOK_EVENT_INIT(&ipst->ips_ip6_observe, NH_OBSERVE); 52110639SDarren.Reed@Sun.COM ipst->ips_ip6_observe.he_flags = HOOK_RDONLY; 52210639SDarren.Reed@Sun.COM ipst->ips_ipv6observing = net_event_register( 52310639SDarren.Reed@Sun.COM ipst->ips_ipv6_net_data, &ipst->ips_ip6_observe); 52410639SDarren.Reed@Sun.COM if (ipst->ips_ipv6observing == NULL) { 52510639SDarren.Reed@Sun.COM cmn_err(CE_NOTE, "ipv6_hook_init: " 52610639SDarren.Reed@Sun.COM "net_event_register failed for ipv6/observe"); 52710639SDarren.Reed@Sun.COM } 5282958Sdr146992 } 5292958Sdr146992 5302958Sdr146992 void 5317915SDarren.Reed@Sun.COM ipv6_hook_shutdown(ip_stack_t *ipst) 5327915SDarren.Reed@Sun.COM { 5337915SDarren.Reed@Sun.COM if (ipst->ips_ipv6firewall_forwarding != NULL) { 5347915SDarren.Reed@Sun.COM (void) net_event_shutdown(ipst->ips_ipv6_net_data, 5357915SDarren.Reed@Sun.COM &ipst->ips_ip6_forwarding_event); 5367915SDarren.Reed@Sun.COM } 5377915SDarren.Reed@Sun.COM 5387915SDarren.Reed@Sun.COM if (ipst->ips_ipv6firewall_physical_in != NULL) { 5397915SDarren.Reed@Sun.COM (void) net_event_shutdown(ipst->ips_ipv6_net_data, 5407915SDarren.Reed@Sun.COM &ipst->ips_ip6_physical_in_event); 5417915SDarren.Reed@Sun.COM } 5427915SDarren.Reed@Sun.COM 5437915SDarren.Reed@Sun.COM if (ipst->ips_ipv6firewall_physical_out != NULL) { 5447915SDarren.Reed@Sun.COM (void) net_event_shutdown(ipst->ips_ipv6_net_data, 5457915SDarren.Reed@Sun.COM &ipst->ips_ip6_physical_out_event); 5467915SDarren.Reed@Sun.COM } 5477915SDarren.Reed@Sun.COM 5487915SDarren.Reed@Sun.COM if (ipst->ips_ipv6firewall_loopback_in != NULL) { 5497915SDarren.Reed@Sun.COM (void) net_event_shutdown(ipst->ips_ipv6_net_data, 5507915SDarren.Reed@Sun.COM &ipst->ips_ip6_loopback_in_event); 5517915SDarren.Reed@Sun.COM } 5527915SDarren.Reed@Sun.COM 5537915SDarren.Reed@Sun.COM if (ipst->ips_ipv6firewall_loopback_out != NULL) { 5547915SDarren.Reed@Sun.COM (void) net_event_shutdown(ipst->ips_ipv6_net_data, 5557915SDarren.Reed@Sun.COM &ipst->ips_ip6_loopback_out_event); 5567915SDarren.Reed@Sun.COM } 5577915SDarren.Reed@Sun.COM 5587915SDarren.Reed@Sun.COM if (ipst->ips_ipv6nicevents != NULL) { 5597915SDarren.Reed@Sun.COM (void) net_event_shutdown(ipst->ips_ipv6_net_data, 5607915SDarren.Reed@Sun.COM &ipst->ips_ip6_nic_events); 5617915SDarren.Reed@Sun.COM } 5627915SDarren.Reed@Sun.COM 56310639SDarren.Reed@Sun.COM if (ipst->ips_ipv6observing != NULL) { 56410639SDarren.Reed@Sun.COM (void) net_event_shutdown(ipst->ips_ipv6_net_data, 56510639SDarren.Reed@Sun.COM &ipst->ips_ip6_observe); 56610639SDarren.Reed@Sun.COM } 56710639SDarren.Reed@Sun.COM 5687915SDarren.Reed@Sun.COM (void) net_family_shutdown(ipst->ips_ipv6_net_data, 5697915SDarren.Reed@Sun.COM &ipst->ips_ipv6root); 5707915SDarren.Reed@Sun.COM } 5717915SDarren.Reed@Sun.COM 5727915SDarren.Reed@Sun.COM void 5733448Sdh155122 ipv6_hook_destroy(ip_stack_t *ipst) 5742958Sdr146992 { 5753448Sdh155122 if (ipst->ips_ipv6firewall_forwarding != NULL) { 5767513SDarren.Reed@Sun.COM if (net_event_unregister(ipst->ips_ipv6_net_data, 5773448Sdh155122 &ipst->ips_ip6_forwarding_event) == 0) 5783448Sdh155122 ipst->ips_ipv6firewall_forwarding = NULL; 5792958Sdr146992 } 5802958Sdr146992 5813448Sdh155122 if (ipst->ips_ipv6firewall_physical_in != NULL) { 5827513SDarren.Reed@Sun.COM if (net_event_unregister(ipst->ips_ipv6_net_data, 5833448Sdh155122 &ipst->ips_ip6_physical_in_event) == 0) 5843448Sdh155122 ipst->ips_ipv6firewall_physical_in = NULL; 5852958Sdr146992 } 5862958Sdr146992 5873448Sdh155122 if (ipst->ips_ipv6firewall_physical_out != NULL) { 5887513SDarren.Reed@Sun.COM if (net_event_unregister(ipst->ips_ipv6_net_data, 5893448Sdh155122 &ipst->ips_ip6_physical_out_event) == 0) 5903448Sdh155122 ipst->ips_ipv6firewall_physical_out = NULL; 5912958Sdr146992 } 5922958Sdr146992 5933448Sdh155122 if (ipst->ips_ipv6firewall_loopback_in != NULL) { 5947513SDarren.Reed@Sun.COM if (net_event_unregister(ipst->ips_ipv6_net_data, 5953448Sdh155122 &ipst->ips_ip6_loopback_in_event) == 0) 5963448Sdh155122 ipst->ips_ipv6firewall_loopback_in = NULL; 5972958Sdr146992 } 5982958Sdr146992 5993448Sdh155122 if (ipst->ips_ipv6firewall_loopback_out != NULL) { 6007513SDarren.Reed@Sun.COM if (net_event_unregister(ipst->ips_ipv6_net_data, 6013448Sdh155122 &ipst->ips_ip6_loopback_out_event) == 0) 6023448Sdh155122 ipst->ips_ipv6firewall_loopback_out = NULL; 6032958Sdr146992 } 6042958Sdr146992 6053448Sdh155122 if (ipst->ips_ipv6nicevents != NULL) { 6067513SDarren.Reed@Sun.COM if (net_event_unregister(ipst->ips_ipv6_net_data, 6073448Sdh155122 &ipst->ips_ip6_nic_events) == 0) 6083448Sdh155122 ipst->ips_ipv6nicevents = NULL; 6092958Sdr146992 } 6102958Sdr146992 61110639SDarren.Reed@Sun.COM if (ipst->ips_ipv6observing != NULL) { 61210639SDarren.Reed@Sun.COM if (net_event_unregister(ipst->ips_ipv6_net_data, 61310639SDarren.Reed@Sun.COM &ipst->ips_ip6_observe) == 0) 61410639SDarren.Reed@Sun.COM ipst->ips_ipv6observing = NULL; 61510639SDarren.Reed@Sun.COM } 61610639SDarren.Reed@Sun.COM 6177513SDarren.Reed@Sun.COM (void) net_family_unregister(ipst->ips_ipv6_net_data, 6183448Sdh155122 &ipst->ips_ipv6root); 6192958Sdr146992 } 6202958Sdr146992 6212958Sdr146992 /* 6222958Sdr146992 * Determine the name of an IPv4 interface 6232958Sdr146992 */ 6242958Sdr146992 static int 6257513SDarren.Reed@Sun.COM ip_getifname(net_handle_t neti, phy_if_t phy_ifdata, char *buffer, 6267513SDarren.Reed@Sun.COM const size_t buflen) 6272958Sdr146992 { 6283448Sdh155122 return (ip_getifname_impl(phy_ifdata, buffer, buflen, B_FALSE, 6297513SDarren.Reed@Sun.COM neti->netd_stack->nts_netstack->netstack_ip)); 6302958Sdr146992 } 6312958Sdr146992 6322958Sdr146992 /* 6332958Sdr146992 * Determine the name of an IPv6 interface 6342958Sdr146992 */ 6352958Sdr146992 static int 6367513SDarren.Reed@Sun.COM ipv6_getifname(net_handle_t neti, phy_if_t phy_ifdata, char *buffer, 6377513SDarren.Reed@Sun.COM const size_t buflen) 6382958Sdr146992 { 6393448Sdh155122 return (ip_getifname_impl(phy_ifdata, buffer, buflen, B_TRUE, 6407513SDarren.Reed@Sun.COM neti->netd_stack->nts_netstack->netstack_ip)); 6412958Sdr146992 } 6422958Sdr146992 6432958Sdr146992 /* 6442958Sdr146992 * Shared implementation to determine the name of a given network interface 6452958Sdr146992 */ 6462958Sdr146992 /* ARGSUSED */ 6472958Sdr146992 static int 6482958Sdr146992 ip_getifname_impl(phy_if_t phy_ifdata, 6493448Sdh155122 char *buffer, const size_t buflen, boolean_t isv6, ip_stack_t *ipst) 6502958Sdr146992 { 6512958Sdr146992 ill_t *ill; 6522958Sdr146992 6532958Sdr146992 ASSERT(buffer != NULL); 6542958Sdr146992 65511042SErik.Nordmark@Sun.COM ill = ill_lookup_on_ifindex((uint_t)phy_ifdata, isv6, ipst); 6568485SPeter.Memishian@Sun.COM if (ill == NULL) 6572958Sdr146992 return (1); 6582958Sdr146992 6598485SPeter.Memishian@Sun.COM (void) strlcpy(buffer, ill->ill_name, buflen); 6608485SPeter.Memishian@Sun.COM ill_refrele(ill); 6618485SPeter.Memishian@Sun.COM return (0); 6622958Sdr146992 } 6632958Sdr146992 6642958Sdr146992 /* 6652958Sdr146992 * Determine the MTU of an IPv4 network interface 6662958Sdr146992 */ 6672958Sdr146992 static int 6687513SDarren.Reed@Sun.COM ip_getmtu(net_handle_t neti, phy_if_t phy_ifdata, lif_if_t ifdata) 6692958Sdr146992 { 6707513SDarren.Reed@Sun.COM netstack_t *ns; 6717513SDarren.Reed@Sun.COM 6727513SDarren.Reed@Sun.COM ns = neti->netd_stack->nts_netstack; 6733448Sdh155122 ASSERT(ns != NULL); 6743448Sdh155122 return (ip_getmtu_impl(phy_ifdata, ifdata, B_FALSE, ns->netstack_ip)); 6752958Sdr146992 } 6762958Sdr146992 6772958Sdr146992 /* 6782958Sdr146992 * Determine the MTU of an IPv6 network interface 6792958Sdr146992 */ 6802958Sdr146992 static int 6817513SDarren.Reed@Sun.COM ipv6_getmtu(net_handle_t neti, phy_if_t phy_ifdata, lif_if_t ifdata) 6822958Sdr146992 { 6837513SDarren.Reed@Sun.COM netstack_t *ns; 6847513SDarren.Reed@Sun.COM 6857513SDarren.Reed@Sun.COM ns = neti->netd_stack->nts_netstack; 6863448Sdh155122 ASSERT(ns != NULL); 6873448Sdh155122 return (ip_getmtu_impl(phy_ifdata, ifdata, B_TRUE, ns->netstack_ip)); 6882958Sdr146992 } 6892958Sdr146992 6902958Sdr146992 /* 6912958Sdr146992 * Shared implementation to determine the MTU of a network interface 6922958Sdr146992 */ 6932958Sdr146992 /* ARGSUSED */ 6942958Sdr146992 static int 6953448Sdh155122 ip_getmtu_impl(phy_if_t phy_ifdata, lif_if_t ifdata, boolean_t isv6, 6963448Sdh155122 ip_stack_t *ipst) 6972958Sdr146992 { 6982958Sdr146992 lif_if_t ipifid; 6992958Sdr146992 ipif_t *ipif; 7002958Sdr146992 int mtu; 7012958Sdr146992 7022958Sdr146992 ipifid = UNMAP_IPIF_ID(ifdata); 7032958Sdr146992 7043448Sdh155122 ipif = ipif_getby_indexes((uint_t)phy_ifdata, (uint_t)ipifid, 7053448Sdh155122 isv6, ipst); 7062958Sdr146992 if (ipif == NULL) 7072958Sdr146992 return (0); 7082958Sdr146992 70911042SErik.Nordmark@Sun.COM mtu = ipif->ipif_ill->ill_mtu; 7102958Sdr146992 ipif_refrele(ipif); 7112958Sdr146992 7122958Sdr146992 if (mtu == 0) { 7132958Sdr146992 ill_t *ill; 7142958Sdr146992 7152958Sdr146992 if ((ill = ill_lookup_on_ifindex((uint_t)phy_ifdata, isv6, 71611042SErik.Nordmark@Sun.COM ipst)) == NULL) { 7178485SPeter.Memishian@Sun.COM return (0); 7182958Sdr146992 } 71911042SErik.Nordmark@Sun.COM mtu = ill->ill_mtu; 7202958Sdr146992 ill_refrele(ill); 7212958Sdr146992 } 7222958Sdr146992 7232958Sdr146992 return (mtu); 7242958Sdr146992 } 7252958Sdr146992 7262958Sdr146992 /* 7272958Sdr146992 * Determine if path MTU discovery is enabled for IP 7282958Sdr146992 */ 7292958Sdr146992 static int 7307513SDarren.Reed@Sun.COM ip_getpmtuenabled(net_handle_t neti) 7312958Sdr146992 { 7327513SDarren.Reed@Sun.COM netstack_t *ns; 7337513SDarren.Reed@Sun.COM 7347513SDarren.Reed@Sun.COM ns = neti->netd_stack->nts_netstack; 7353448Sdh155122 ASSERT(ns != NULL); 7367513SDarren.Reed@Sun.COM return (ns->netstack_ip->ips_ip_path_mtu_discovery); 7372958Sdr146992 } 7382958Sdr146992 7392958Sdr146992 /* 7402958Sdr146992 * Get next interface from the current list of IPv4 physical network interfaces 7412958Sdr146992 */ 7422958Sdr146992 static phy_if_t 7437513SDarren.Reed@Sun.COM ip_phygetnext(net_handle_t neti, phy_if_t phy_ifdata) 7442958Sdr146992 { 7457513SDarren.Reed@Sun.COM netstack_t *ns; 7467513SDarren.Reed@Sun.COM 7477513SDarren.Reed@Sun.COM ns = neti->netd_stack->nts_netstack; 7483448Sdh155122 ASSERT(ns != NULL); 7493448Sdh155122 return (ill_get_next_ifindex(phy_ifdata, B_FALSE, ns->netstack_ip)); 7502958Sdr146992 } 7512958Sdr146992 7522958Sdr146992 /* 7532958Sdr146992 * Get next interface from the current list of IPv6 physical network interfaces 7542958Sdr146992 */ 7552958Sdr146992 static phy_if_t 7567513SDarren.Reed@Sun.COM ipv6_phygetnext(net_handle_t neti, phy_if_t phy_ifdata) 7572958Sdr146992 { 7587513SDarren.Reed@Sun.COM netstack_t *ns; 7597513SDarren.Reed@Sun.COM 7607513SDarren.Reed@Sun.COM ns = neti->netd_stack->nts_netstack; 7613448Sdh155122 ASSERT(ns != NULL); 7623448Sdh155122 return (ill_get_next_ifindex(phy_ifdata, B_TRUE, ns->netstack_ip)); 7632958Sdr146992 } 7642958Sdr146992 7652958Sdr146992 /* 7662958Sdr146992 * Determine if a network interface name exists for IPv4 7672958Sdr146992 */ 7682958Sdr146992 static phy_if_t 7697513SDarren.Reed@Sun.COM ip_phylookup(net_handle_t neti, const char *name) 7702958Sdr146992 { 7717513SDarren.Reed@Sun.COM netstack_t *ns; 7727513SDarren.Reed@Sun.COM 7737513SDarren.Reed@Sun.COM ns = neti->netd_stack->nts_netstack; 7743448Sdh155122 ASSERT(ns != NULL); 7753448Sdh155122 return (ip_phylookup_impl(name, B_FALSE, ns->netstack_ip)); 7762958Sdr146992 } 7772958Sdr146992 7782958Sdr146992 /* 7792958Sdr146992 * Determine if a network interface name exists for IPv6 7802958Sdr146992 */ 7812958Sdr146992 static phy_if_t 7827513SDarren.Reed@Sun.COM ipv6_phylookup(net_handle_t neti, const char *name) 7832958Sdr146992 { 7847513SDarren.Reed@Sun.COM netstack_t *ns; 7857513SDarren.Reed@Sun.COM 7867513SDarren.Reed@Sun.COM ns = neti->netd_stack->nts_netstack; 7873448Sdh155122 ASSERT(ns != NULL); 7883448Sdh155122 return (ip_phylookup_impl(name, B_TRUE, ns->netstack_ip)); 7892958Sdr146992 } 7902958Sdr146992 7912958Sdr146992 /* 7922958Sdr146992 * Implement looking up an ill_t based on the name supplied and matching 7932958Sdr146992 * it up with either IPv4 or IPv6. ill_get_ifindex_by_name() is not used 7942958Sdr146992 * because it does not match on the address family in addition to the name. 7952958Sdr146992 */ 7962958Sdr146992 static phy_if_t 7973448Sdh155122 ip_phylookup_impl(const char *name, boolean_t isv6, ip_stack_t *ipst) 7982958Sdr146992 { 7992958Sdr146992 phy_if_t phy; 8002958Sdr146992 ill_t *ill; 8012958Sdr146992 80211042SErik.Nordmark@Sun.COM ill = ill_lookup_on_name((char *)name, B_FALSE, isv6, NULL, ipst); 8032958Sdr146992 if (ill == NULL) 8042958Sdr146992 return (0); 8052958Sdr146992 8068485SPeter.Memishian@Sun.COM phy = ill->ill_phyint->phyint_ifindex; 8072958Sdr146992 8082958Sdr146992 ill_refrele(ill); 8092958Sdr146992 8102958Sdr146992 return (phy); 8112958Sdr146992 } 8122958Sdr146992 8132958Sdr146992 /* 8142958Sdr146992 * Get next interface from the current list of IPv4 logical network interfaces 8152958Sdr146992 */ 8162958Sdr146992 static lif_if_t 8177513SDarren.Reed@Sun.COM ip_lifgetnext(net_handle_t neti, phy_if_t phy_ifdata, lif_if_t ifdata) 8182958Sdr146992 { 8197513SDarren.Reed@Sun.COM netstack_t *ns; 8207513SDarren.Reed@Sun.COM 8217513SDarren.Reed@Sun.COM ns = neti->netd_stack->nts_netstack; 8223448Sdh155122 ASSERT(ns != NULL); 8233448Sdh155122 return (ip_lifgetnext_impl(phy_ifdata, ifdata, B_FALSE, 8243448Sdh155122 ns->netstack_ip)); 8252958Sdr146992 } 8262958Sdr146992 8272958Sdr146992 /* 8282958Sdr146992 * Get next interface from the current list of IPv6 logical network interfaces 8292958Sdr146992 */ 8302958Sdr146992 static lif_if_t 8317513SDarren.Reed@Sun.COM ipv6_lifgetnext(net_handle_t neti, phy_if_t phy_ifdata, lif_if_t ifdata) 8322958Sdr146992 { 8337513SDarren.Reed@Sun.COM netstack_t *ns; 8347513SDarren.Reed@Sun.COM 8357513SDarren.Reed@Sun.COM ns = neti->netd_stack->nts_netstack; 8363448Sdh155122 ASSERT(ns != NULL); 8373448Sdh155122 return (ip_lifgetnext_impl(phy_ifdata, ifdata, B_TRUE, 8383448Sdh155122 ns->netstack_ip)); 8392958Sdr146992 } 8402958Sdr146992 8412958Sdr146992 /* 8422958Sdr146992 * Shared implementation to get next interface from the current list of 8432958Sdr146992 * logical network interfaces 8442958Sdr146992 */ 8452958Sdr146992 static lif_if_t 8463448Sdh155122 ip_lifgetnext_impl(phy_if_t phy_ifdata, lif_if_t ifdata, boolean_t isv6, 8473448Sdh155122 ip_stack_t *ipst) 8482958Sdr146992 { 8492958Sdr146992 lif_if_t newidx, oldidx; 8502958Sdr146992 boolean_t nextok; 8512958Sdr146992 ipif_t *ipif; 8522958Sdr146992 ill_t *ill; 8532958Sdr146992 85411042SErik.Nordmark@Sun.COM ill = ill_lookup_on_ifindex(phy_ifdata, isv6, ipst); 8552958Sdr146992 if (ill == NULL) 8562958Sdr146992 return (0); 8572958Sdr146992 8582958Sdr146992 if (ifdata != 0) { 8592958Sdr146992 oldidx = UNMAP_IPIF_ID(ifdata); 8602958Sdr146992 nextok = B_FALSE; 8612958Sdr146992 } else { 8622958Sdr146992 oldidx = 0; 8632958Sdr146992 nextok = B_TRUE; 8642958Sdr146992 } 8652958Sdr146992 8662958Sdr146992 mutex_enter(&ill->ill_lock); 8672958Sdr146992 if (ill->ill_state_flags & ILL_CONDEMNED) { 8682958Sdr146992 mutex_exit(&ill->ill_lock); 8692958Sdr146992 ill_refrele(ill); 8702958Sdr146992 return (0); 8712958Sdr146992 } 8722958Sdr146992 8732958Sdr146992 /* 8742958Sdr146992 * It's safe to iterate the ill_ipif list when holding an ill_lock. 8752958Sdr146992 * And it's also safe to access ipif_id without ipif refhold. 8768485SPeter.Memishian@Sun.COM * See the field access rules in ip.h. 8772958Sdr146992 */ 8782958Sdr146992 for (ipif = ill->ill_ipif; ipif != NULL; ipif = ipif->ipif_next) { 8792958Sdr146992 if (!IPIF_CAN_LOOKUP(ipif)) 8802958Sdr146992 continue; 8812958Sdr146992 if (nextok) { 8822958Sdr146992 ipif_refhold_locked(ipif); 8832958Sdr146992 break; 8842958Sdr146992 } else if (oldidx == ipif->ipif_id) { 8852958Sdr146992 nextok = B_TRUE; 8862958Sdr146992 } 8872958Sdr146992 } 8882958Sdr146992 8892958Sdr146992 mutex_exit(&ill->ill_lock); 8902958Sdr146992 ill_refrele(ill); 8912958Sdr146992 8922958Sdr146992 if (ipif == NULL) 8932958Sdr146992 return (0); 8942958Sdr146992 8952958Sdr146992 newidx = ipif->ipif_id; 8962958Sdr146992 ipif_refrele(ipif); 8972958Sdr146992 8982958Sdr146992 return (MAP_IPIF_ID(newidx)); 8992958Sdr146992 } 9002958Sdr146992 9012958Sdr146992 /* 9022958Sdr146992 * Inject an IPv4 packet to or from an interface 9032958Sdr146992 */ 9042958Sdr146992 static int 9057513SDarren.Reed@Sun.COM ip_inject(net_handle_t neti, inject_t style, net_inject_t *packet) 9062958Sdr146992 { 9077513SDarren.Reed@Sun.COM netstack_t *ns; 9087513SDarren.Reed@Sun.COM 9097513SDarren.Reed@Sun.COM ns = neti->netd_stack->nts_netstack; 9103448Sdh155122 ASSERT(ns != NULL); 9113448Sdh155122 return (ip_inject_impl(style, packet, B_FALSE, ns->netstack_ip)); 9122958Sdr146992 } 9132958Sdr146992 9142958Sdr146992 9152958Sdr146992 /* 9162958Sdr146992 * Inject an IPv6 packet to or from an interface 9172958Sdr146992 */ 9182958Sdr146992 static int 9197513SDarren.Reed@Sun.COM ipv6_inject(net_handle_t neti, inject_t style, net_inject_t *packet) 9202958Sdr146992 { 9217513SDarren.Reed@Sun.COM netstack_t *ns; 9227513SDarren.Reed@Sun.COM 9237513SDarren.Reed@Sun.COM ns = neti->netd_stack->nts_netstack; 9243448Sdh155122 return (ip_inject_impl(style, packet, B_TRUE, ns->netstack_ip)); 9252958Sdr146992 } 9262958Sdr146992 9272958Sdr146992 /* 9282958Sdr146992 * Shared implementation to inject a packet to or from an interface 9292958Sdr146992 * Return value: 9302958Sdr146992 * 0: successful 9312958Sdr146992 * -1: memory allocation failed 9322958Sdr146992 * 1: other errors 9332958Sdr146992 */ 9342958Sdr146992 static int 9353448Sdh155122 ip_inject_impl(inject_t style, net_inject_t *packet, boolean_t isv6, 9363448Sdh155122 ip_stack_t *ipst) 9372958Sdr146992 { 9382958Sdr146992 ddi_taskq_t *tq = NULL; 9393448Sdh155122 void (* func)(void *); 9402958Sdr146992 injection_t *inject; 9412958Sdr146992 mblk_t *mp; 9422958Sdr146992 9432958Sdr146992 ASSERT(packet != NULL); 9442958Sdr146992 ASSERT(packet->ni_packet != NULL); 9452958Sdr146992 ASSERT(packet->ni_packet->b_datap->db_type == M_DATA); 9462958Sdr146992 9472958Sdr146992 switch (style) { 9482958Sdr146992 case NI_QUEUE_IN: 9492958Sdr146992 inject = kmem_alloc(sizeof (*inject), KM_NOSLEEP); 9502958Sdr146992 if (inject == NULL) 9512958Sdr146992 return (-1); 9522958Sdr146992 inject->inj_data = *packet; 9532958Sdr146992 inject->inj_isv6 = isv6; 9542958Sdr146992 /* 9552958Sdr146992 * deliver up into the kernel, immitating its reception by a 9562958Sdr146992 * network interface, add to list and schedule timeout 9572958Sdr146992 */ 9582958Sdr146992 func = ip_ni_queue_in_func; 9592958Sdr146992 tq = eventq_queue_in; 9602958Sdr146992 break; 9612958Sdr146992 9622958Sdr146992 case NI_QUEUE_OUT: 9632958Sdr146992 inject = kmem_alloc(sizeof (*inject), KM_NOSLEEP); 9642958Sdr146992 if (inject == NULL) 9652958Sdr146992 return (-1); 9662958Sdr146992 inject->inj_data = *packet; 9672958Sdr146992 inject->inj_isv6 = isv6; 9682958Sdr146992 /* 9692958Sdr146992 * deliver out of the kernel, as if it were being sent via a 9702958Sdr146992 * raw socket so that IPFilter will see it again, add to list 9712958Sdr146992 * and schedule timeout 9722958Sdr146992 */ 9732958Sdr146992 func = ip_ni_queue_out_func; 9742958Sdr146992 tq = eventq_queue_out; 9752958Sdr146992 break; 9762958Sdr146992 97711042SErik.Nordmark@Sun.COM case NI_DIRECT_OUT: { 97811042SErik.Nordmark@Sun.COM struct sockaddr *sock; 97911042SErik.Nordmark@Sun.COM 9802958Sdr146992 mp = packet->ni_packet; 9812958Sdr146992 98211042SErik.Nordmark@Sun.COM sock = (struct sockaddr *)&packet->ni_addr; 98311042SErik.Nordmark@Sun.COM /* 98411042SErik.Nordmark@Sun.COM * ipfil_sendpkt was provided by surya to ease the 98511042SErik.Nordmark@Sun.COM * problems associated with sending out a packet. 98611042SErik.Nordmark@Sun.COM */ 98711042SErik.Nordmark@Sun.COM switch (ipfil_sendpkt(sock, mp, packet->ni_physical, 98811042SErik.Nordmark@Sun.COM netstackid_to_zoneid( 98911042SErik.Nordmark@Sun.COM ipst->ips_netstack->netstack_stackid))) { 99011042SErik.Nordmark@Sun.COM case 0 : 99111042SErik.Nordmark@Sun.COM case EINPROGRESS: 99211042SErik.Nordmark@Sun.COM return (0); 99311042SErik.Nordmark@Sun.COM case ECOMM : 99411042SErik.Nordmark@Sun.COM case ENONET : 99511042SErik.Nordmark@Sun.COM return (1); 99611042SErik.Nordmark@Sun.COM default : 9972958Sdr146992 return (1); 9982958Sdr146992 } 99911042SErik.Nordmark@Sun.COM /* NOTREACHED */ 100011042SErik.Nordmark@Sun.COM } 10012958Sdr146992 default: 10022958Sdr146992 freemsg(packet->ni_packet); 10032958Sdr146992 return (1); 10042958Sdr146992 } 10052958Sdr146992 100611042SErik.Nordmark@Sun.COM ASSERT(tq != NULL); 100711042SErik.Nordmark@Sun.COM 100811042SErik.Nordmark@Sun.COM inject->inj_ptr = ipst; 100911042SErik.Nordmark@Sun.COM if (ddi_taskq_dispatch(tq, func, (void *)inject, 101011042SErik.Nordmark@Sun.COM DDI_SLEEP) == DDI_FAILURE) { 101111042SErik.Nordmark@Sun.COM ip2dbg(("ip_inject: ddi_taskq_dispatch failed\n")); 101211042SErik.Nordmark@Sun.COM freemsg(packet->ni_packet); 101311042SErik.Nordmark@Sun.COM return (1); 10142958Sdr146992 } 10152958Sdr146992 return (0); 10162958Sdr146992 } 10172958Sdr146992 10182958Sdr146992 /* 10192958Sdr146992 * Find the interface used for traffic to a given IPv4 address 10202958Sdr146992 */ 10212958Sdr146992 static phy_if_t 10227513SDarren.Reed@Sun.COM ip_routeto(net_handle_t neti, struct sockaddr *address, struct sockaddr *next) 10232958Sdr146992 { 10247513SDarren.Reed@Sun.COM netstack_t *ns; 10257513SDarren.Reed@Sun.COM 10262958Sdr146992 ASSERT(address != NULL); 10272958Sdr146992 10282958Sdr146992 if (address->sa_family != AF_INET) 10292958Sdr146992 return (0); 10307513SDarren.Reed@Sun.COM 10317513SDarren.Reed@Sun.COM ns = neti->netd_stack->nts_netstack; 10327513SDarren.Reed@Sun.COM ASSERT(ns != NULL); 10337513SDarren.Reed@Sun.COM 10347513SDarren.Reed@Sun.COM return (ip_routeto_impl(address, next, ns->netstack_ip)); 10352958Sdr146992 } 10362958Sdr146992 10372958Sdr146992 /* 10382958Sdr146992 * Find the interface used for traffic to a given IPv6 address 10392958Sdr146992 */ 10402958Sdr146992 static phy_if_t 10417513SDarren.Reed@Sun.COM ipv6_routeto(net_handle_t neti, struct sockaddr *address, struct sockaddr *next) 10422958Sdr146992 { 10437513SDarren.Reed@Sun.COM netstack_t *ns; 10447513SDarren.Reed@Sun.COM 10452958Sdr146992 ASSERT(address != NULL); 10462958Sdr146992 10472958Sdr146992 if (address->sa_family != AF_INET6) 10482958Sdr146992 return (0); 10497513SDarren.Reed@Sun.COM 10507513SDarren.Reed@Sun.COM ns = neti->netd_stack->nts_netstack; 10517513SDarren.Reed@Sun.COM ASSERT(ns != NULL); 10527513SDarren.Reed@Sun.COM 10537513SDarren.Reed@Sun.COM return (ip_routeto_impl(address, next, ns->netstack_ip)); 10542958Sdr146992 } 10552958Sdr146992 10562958Sdr146992 10572958Sdr146992 /* 10587513SDarren.Reed@Sun.COM * Find the interface used for traffic to an address. 10597513SDarren.Reed@Sun.COM * For lint reasons, next/next6/sin/sin6 are all declared and assigned 10607513SDarren.Reed@Sun.COM * a value at the top. The alternative would end up with two bunches 10617513SDarren.Reed@Sun.COM * of assignments, with each bunch setting half to NULL. 10622958Sdr146992 */ 10632958Sdr146992 static phy_if_t 10647513SDarren.Reed@Sun.COM ip_routeto_impl(struct sockaddr *address, struct sockaddr *nexthop, 10657513SDarren.Reed@Sun.COM ip_stack_t *ipst) 10662958Sdr146992 { 10677513SDarren.Reed@Sun.COM struct sockaddr_in6 *next6 = (struct sockaddr_in6 *)nexthop; 10687513SDarren.Reed@Sun.COM struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)address; 10697513SDarren.Reed@Sun.COM struct sockaddr_in *next = (struct sockaddr_in *)nexthop; 10707513SDarren.Reed@Sun.COM struct sockaddr_in *sin = (struct sockaddr_in *)address; 10712958Sdr146992 ire_t *ire; 107211042SErik.Nordmark@Sun.COM ire_t *nexthop_ire; 10732958Sdr146992 phy_if_t phy_if; 10749876SDarren.Reed@Sun.COM zoneid_t zoneid; 10759876SDarren.Reed@Sun.COM 10769876SDarren.Reed@Sun.COM zoneid = netstackid_to_zoneid(ipst->ips_netstack->netstack_stackid); 10772958Sdr146992 10782958Sdr146992 if (address->sa_family == AF_INET6) { 107911042SErik.Nordmark@Sun.COM ire = ire_route_recursive_v6(&sin6->sin6_addr, 0, NULL, 1080*11457SErik.Nordmark@Sun.COM zoneid, NULL, MATCH_IRE_DSTONLY, IRR_ALLOCATE, 0, ipst, 1081*11457SErik.Nordmark@Sun.COM NULL, NULL, NULL); 10822958Sdr146992 } else { 108311042SErik.Nordmark@Sun.COM ire = ire_route_recursive_v4(sin->sin_addr.s_addr, 0, NULL, 1084*11457SErik.Nordmark@Sun.COM zoneid, NULL, MATCH_IRE_DSTONLY, IRR_ALLOCATE, 0, ipst, 1085*11457SErik.Nordmark@Sun.COM NULL, NULL, NULL); 10862958Sdr146992 } 108711042SErik.Nordmark@Sun.COM ASSERT(ire != NULL); 10887513SDarren.Reed@Sun.COM /* 10897513SDarren.Reed@Sun.COM * For some destinations, we have routes that are dead ends, so 10907513SDarren.Reed@Sun.COM * return to indicate that no physical interface can be used to 10917513SDarren.Reed@Sun.COM * reach the destination. 10927513SDarren.Reed@Sun.COM */ 109311042SErik.Nordmark@Sun.COM if (ire->ire_flags & (RTF_REJECT|RTF_BLACKHOLE)) { 109411042SErik.Nordmark@Sun.COM ire_refrele(ire); 109511042SErik.Nordmark@Sun.COM return (NULL); 109611042SErik.Nordmark@Sun.COM } 109711042SErik.Nordmark@Sun.COM 109811042SErik.Nordmark@Sun.COM nexthop_ire = ire_nexthop(ire); 109911042SErik.Nordmark@Sun.COM if (nexthop_ire == NULL) { 11004041Snordmark ire_refrele(ire); 11012958Sdr146992 return (0); 11024041Snordmark } 110311042SErik.Nordmark@Sun.COM if (nexthop_ire->ire_flags & (RTF_REJECT|RTF_BLACKHOLE)) { 110411042SErik.Nordmark@Sun.COM ire_refrele(nexthop_ire); 11057513SDarren.Reed@Sun.COM ire_refrele(ire); 11067513SDarren.Reed@Sun.COM return (0); 11077513SDarren.Reed@Sun.COM } 11087513SDarren.Reed@Sun.COM 110911042SErik.Nordmark@Sun.COM ASSERT(nexthop_ire->ire_ill != NULL); 111011042SErik.Nordmark@Sun.COM 11117513SDarren.Reed@Sun.COM if (nexthop != NULL) { 11127513SDarren.Reed@Sun.COM if (address->sa_family == AF_INET6) { 111311042SErik.Nordmark@Sun.COM next6->sin6_addr = nexthop_ire->ire_addr_v6; 11147513SDarren.Reed@Sun.COM } else { 111511042SErik.Nordmark@Sun.COM next->sin_addr.s_addr = nexthop_ire->ire_addr; 11167513SDarren.Reed@Sun.COM } 11177513SDarren.Reed@Sun.COM } 11187513SDarren.Reed@Sun.COM 111911042SErik.Nordmark@Sun.COM phy_if = (phy_if_t)nexthop_ire->ire_ill->ill_phyint->phyint_ifindex; 11202958Sdr146992 ire_refrele(ire); 112111042SErik.Nordmark@Sun.COM ire_refrele(nexthop_ire); 11222958Sdr146992 11232958Sdr146992 return (phy_if); 11242958Sdr146992 } 11252958Sdr146992 11262958Sdr146992 /* 11272958Sdr146992 * Determine if checksumming is being used for the given packet. 11282958Sdr146992 * 11292958Sdr146992 * Return value: 11302958Sdr146992 * NET_HCK_NONE: full checksum recalculation is required 11312958Sdr146992 * NET_HCK_L3_FULL: full layer 3 checksum 11322958Sdr146992 * NET_HCK_L4_FULL: full layer 4 checksum 11332958Sdr146992 * NET_HCK_L4_PART: partial layer 4 checksum 11342958Sdr146992 */ 11357513SDarren.Reed@Sun.COM /*ARGSUSED*/ 11362958Sdr146992 static int 11377513SDarren.Reed@Sun.COM ip_ispartialchecksum(net_handle_t neti, mblk_t *mp) 11382958Sdr146992 { 11392958Sdr146992 int ret = 0; 11402958Sdr146992 11412958Sdr146992 ASSERT(mp != NULL); 11422958Sdr146992 11432958Sdr146992 if ((DB_CKSUMFLAGS(mp) & HCK_FULLCKSUM) != 0) { 11442958Sdr146992 ret |= (int)NET_HCK_L4_FULL; 11452958Sdr146992 if ((DB_CKSUMFLAGS(mp) & HCK_IPV4_HDRCKSUM) != 0) 11462958Sdr146992 ret |= (int)NET_HCK_L3_FULL; 11472958Sdr146992 } 11482958Sdr146992 if ((DB_CKSUMFLAGS(mp) & HCK_PARTIALCKSUM) != 0) { 11492958Sdr146992 ret |= (int)NET_HCK_L4_PART; 11502958Sdr146992 if ((DB_CKSUMFLAGS(mp) & HCK_IPV4_HDRCKSUM) != 0) 11512958Sdr146992 ret |= (int)NET_HCK_L3_FULL; 11522958Sdr146992 } 11532958Sdr146992 11542958Sdr146992 return (ret); 11552958Sdr146992 } 11562958Sdr146992 11572958Sdr146992 /* 11582958Sdr146992 * Return true or false, indicating whether the network and transport 11592958Sdr146992 * headers are correct. Use the capabilities flags and flags set in the 11602958Sdr146992 * dblk_t to determine whether or not the checksum is valid. 11612958Sdr146992 * 11622958Sdr146992 * Return: 11632958Sdr146992 * 0: the checksum was incorrect 11642958Sdr146992 * 1: the original checksum was correct 11652958Sdr146992 */ 11667513SDarren.Reed@Sun.COM /*ARGSUSED*/ 11672958Sdr146992 static int 11687513SDarren.Reed@Sun.COM ip_isvalidchecksum(net_handle_t neti, mblk_t *mp) 11692958Sdr146992 { 11702958Sdr146992 unsigned char *wptr; 11712958Sdr146992 ipha_t *ipha = (ipha_t *)mp->b_rptr; 11722958Sdr146992 int hlen; 11732958Sdr146992 int ret; 11742958Sdr146992 11752958Sdr146992 ASSERT(mp != NULL); 11762958Sdr146992 11772958Sdr146992 if (dohwcksum && 11782958Sdr146992 DB_CKSUM16(mp) != 0xFFFF && 11792958Sdr146992 (DB_CKSUMFLAGS(mp) & HCK_FULLCKSUM) && 11802958Sdr146992 (DB_CKSUMFLAGS(mp) & HCK_FULLCKSUM_OK) && 11812958Sdr146992 (DB_CKSUMFLAGS(mp) & HCK_IPV4_HDRCKSUM)) 11822958Sdr146992 return (1); 11832958Sdr146992 11842958Sdr146992 hlen = (ipha->ipha_version_and_hdr_length & 0x0F) << 2; 11852958Sdr146992 11862958Sdr146992 /* 11872958Sdr146992 * Check that the mblk being passed in has enough data in it 11882958Sdr146992 * before blindly checking ip_cksum. 11892958Sdr146992 */ 11902958Sdr146992 if (msgdsize(mp) < hlen) 11912958Sdr146992 return (0); 11922958Sdr146992 11932958Sdr146992 if (mp->b_wptr < mp->b_rptr + hlen) { 11942958Sdr146992 if (pullupmsg(mp, hlen) == 0) 11952958Sdr146992 return (0); 11962958Sdr146992 wptr = mp->b_wptr; 11972958Sdr146992 } else { 11982958Sdr146992 wptr = mp->b_wptr; 11992958Sdr146992 mp->b_wptr = mp->b_rptr + hlen; 12002958Sdr146992 } 12012958Sdr146992 12022958Sdr146992 if (ipha->ipha_hdr_checksum == ip_cksum(mp, 0, ipha->ipha_hdr_checksum)) 12032958Sdr146992 ret = 1; 12042958Sdr146992 else 12052958Sdr146992 ret = 0; 12062958Sdr146992 mp->b_wptr = wptr; 12072958Sdr146992 12082958Sdr146992 return (ret); 12092958Sdr146992 } 12102958Sdr146992 12112958Sdr146992 /* 12122958Sdr146992 * Unsupported with IPv6 12132958Sdr146992 */ 12142958Sdr146992 /*ARGSUSED*/ 12152958Sdr146992 static int 12167513SDarren.Reed@Sun.COM ipv6_isvalidchecksum(net_handle_t neti, mblk_t *mp) 12172958Sdr146992 { 12182958Sdr146992 return (-1); 12192958Sdr146992 } 12202958Sdr146992 12212958Sdr146992 /* 12222958Sdr146992 * Determine the network addresses for an IPv4 interface 12232958Sdr146992 */ 12242958Sdr146992 static int 12257513SDarren.Reed@Sun.COM ip_getlifaddr(net_handle_t neti, phy_if_t phy_ifdata, lif_if_t ifdata, 12267513SDarren.Reed@Sun.COM size_t nelem, net_ifaddr_t type[], void *storage) 12272958Sdr146992 { 12287513SDarren.Reed@Sun.COM netstack_t *ns; 12297513SDarren.Reed@Sun.COM 12307513SDarren.Reed@Sun.COM ns = neti->netd_stack->nts_netstack; 12313448Sdh155122 ASSERT(ns != NULL); 12322958Sdr146992 return (ip_getlifaddr_impl(AF_INET, phy_ifdata, ifdata, 12333448Sdh155122 nelem, type, storage, ns->netstack_ip)); 12342958Sdr146992 } 12352958Sdr146992 12362958Sdr146992 /* 12372958Sdr146992 * Determine the network addresses for an IPv6 interface 12382958Sdr146992 */ 12392958Sdr146992 static int 12407513SDarren.Reed@Sun.COM ipv6_getlifaddr(net_handle_t neti, phy_if_t phy_ifdata, lif_if_t ifdata, 12417513SDarren.Reed@Sun.COM size_t nelem, net_ifaddr_t type[], void *storage) 12422958Sdr146992 { 12437513SDarren.Reed@Sun.COM netstack_t *ns; 12447513SDarren.Reed@Sun.COM 12457513SDarren.Reed@Sun.COM ns = neti->netd_stack->nts_netstack; 12463448Sdh155122 ASSERT(ns != NULL); 12472958Sdr146992 return (ip_getlifaddr_impl(AF_INET6, phy_ifdata, ifdata, 12483448Sdh155122 nelem, type, storage, ns->netstack_ip)); 12492958Sdr146992 } 12502958Sdr146992 12512958Sdr146992 /* 12522958Sdr146992 * Shared implementation to determine the network addresses for an interface 12532958Sdr146992 */ 12542958Sdr146992 /* ARGSUSED */ 12552958Sdr146992 static int 12562958Sdr146992 ip_getlifaddr_impl(sa_family_t family, phy_if_t phy_ifdata, 12572958Sdr146992 lif_if_t ifdata, size_t nelem, net_ifaddr_t type[], 12583448Sdh155122 struct sockaddr *storage, ip_stack_t *ipst) 12592958Sdr146992 { 12602958Sdr146992 struct sockaddr_in6 *sin6; 12612958Sdr146992 struct sockaddr_in *sin; 12622958Sdr146992 lif_if_t ipifid; 12632958Sdr146992 ipif_t *ipif; 12642958Sdr146992 int i; 12652958Sdr146992 12662958Sdr146992 ASSERT(type != NULL); 12672958Sdr146992 ASSERT(storage != NULL); 12682958Sdr146992 12692958Sdr146992 ipifid = UNMAP_IPIF_ID(ifdata); 12702958Sdr146992 12712958Sdr146992 if (family == AF_INET) { 12722958Sdr146992 if ((ipif = ipif_getby_indexes((uint_t)phy_ifdata, 12733448Sdh155122 (uint_t)ipifid, B_FALSE, ipst)) == NULL) 12742958Sdr146992 return (1); 12752958Sdr146992 12762958Sdr146992 sin = (struct sockaddr_in *)storage; 12772958Sdr146992 for (i = 0; i < nelem; i++, sin++) { 12782958Sdr146992 if (ip_getifaddr_type(AF_INET, ipif, type[i], 12792958Sdr146992 &sin->sin_addr) < 0) { 12802958Sdr146992 ip2dbg(("ip_getlifaddr_impl failed type %d\n", 12812958Sdr146992 type[i])); 12822958Sdr146992 ipif_refrele(ipif); 12832958Sdr146992 return (1); 12842958Sdr146992 } 12857915SDarren.Reed@Sun.COM sin->sin_family = AF_INET; 12862958Sdr146992 } 12872958Sdr146992 } else { 12882958Sdr146992 if ((ipif = ipif_getby_indexes((uint_t)phy_ifdata, 12893448Sdh155122 (uint_t)ipifid, B_TRUE, ipst)) == NULL) 12902958Sdr146992 return (1); 12912958Sdr146992 12922958Sdr146992 sin6 = (struct sockaddr_in6 *)storage; 12932958Sdr146992 for (i = 0; i < nelem; i++, sin6++) { 12942958Sdr146992 if (ip_getifaddr_type(AF_INET6, ipif, type[i], 12952958Sdr146992 &sin6->sin6_addr) < 0) { 12962958Sdr146992 ip2dbg(("ip_getlifaddr_impl failed type %d\n", 12972958Sdr146992 type[i])); 12982958Sdr146992 ipif_refrele(ipif); 12992958Sdr146992 return (1); 13002958Sdr146992 } 13017915SDarren.Reed@Sun.COM sin6->sin6_family = AF_INET6; 13022958Sdr146992 } 13032958Sdr146992 } 13042958Sdr146992 ipif_refrele(ipif); 13052958Sdr146992 return (0); 13062958Sdr146992 } 13072958Sdr146992 13082958Sdr146992 /* 13092958Sdr146992 * ip_getlifaddr private function 13102958Sdr146992 */ 13112958Sdr146992 static int 13122958Sdr146992 ip_getifaddr_type(sa_family_t family, ipif_t *ill_ipif, 13132958Sdr146992 lif_if_t type, void *storage) 13142958Sdr146992 { 13152958Sdr146992 void *src_addr; 13162958Sdr146992 int mem_size; 13172958Sdr146992 13182958Sdr146992 ASSERT(ill_ipif != NULL); 13192958Sdr146992 ASSERT(storage != NULL); 13202958Sdr146992 13212958Sdr146992 if (family == AF_INET) { 13222958Sdr146992 mem_size = sizeof (struct in_addr); 13232958Sdr146992 13242958Sdr146992 switch (type) { 13252958Sdr146992 case NA_ADDRESS: 13262958Sdr146992 src_addr = &(ill_ipif->ipif_lcl_addr); 13272958Sdr146992 break; 13282958Sdr146992 case NA_PEER: 13292958Sdr146992 src_addr = &(ill_ipif->ipif_pp_dst_addr); 13302958Sdr146992 break; 13312958Sdr146992 case NA_BROADCAST: 13322958Sdr146992 src_addr = &(ill_ipif->ipif_brd_addr); 13332958Sdr146992 break; 13342958Sdr146992 case NA_NETMASK: 13352958Sdr146992 src_addr = &(ill_ipif->ipif_net_mask); 13362958Sdr146992 break; 13372958Sdr146992 default: 13382958Sdr146992 return (-1); 13392958Sdr146992 /*NOTREACHED*/ 13402958Sdr146992 } 13412958Sdr146992 } else { 13422958Sdr146992 mem_size = sizeof (struct in6_addr); 13432958Sdr146992 13442958Sdr146992 switch (type) { 13452958Sdr146992 case NA_ADDRESS: 13462958Sdr146992 src_addr = &(ill_ipif->ipif_v6lcl_addr); 13472958Sdr146992 break; 13482958Sdr146992 case NA_PEER: 13492958Sdr146992 src_addr = &(ill_ipif->ipif_v6pp_dst_addr); 13502958Sdr146992 break; 13512958Sdr146992 case NA_BROADCAST: 13522958Sdr146992 src_addr = &(ill_ipif->ipif_v6brd_addr); 13532958Sdr146992 break; 13542958Sdr146992 case NA_NETMASK: 13552958Sdr146992 src_addr = &(ill_ipif->ipif_v6net_mask); 13562958Sdr146992 break; 13572958Sdr146992 default: 13582958Sdr146992 return (-1); 13592958Sdr146992 /*NOTREACHED*/ 13602958Sdr146992 } 13612958Sdr146992 } 13622958Sdr146992 13632958Sdr146992 (void) memcpy(storage, src_addr, mem_size); 13642958Sdr146992 return (1); 13652958Sdr146992 } 13662958Sdr146992 13672958Sdr146992 /* 13688023SPhil.Kirk@Sun.COM * Shared implementation to determine the zoneid associated with an IPv4/IPv6 13698023SPhil.Kirk@Sun.COM * address 13708023SPhil.Kirk@Sun.COM */ 13718023SPhil.Kirk@Sun.COM static int 13728023SPhil.Kirk@Sun.COM ip_getlifzone_impl(sa_family_t family, phy_if_t phy_ifdata, lif_if_t ifdata, 13738023SPhil.Kirk@Sun.COM ip_stack_t *ipst, zoneid_t *zoneid) 13748023SPhil.Kirk@Sun.COM { 13758023SPhil.Kirk@Sun.COM ipif_t *ipif; 13768023SPhil.Kirk@Sun.COM 13778023SPhil.Kirk@Sun.COM ipif = ipif_getby_indexes((uint_t)phy_ifdata, 13788023SPhil.Kirk@Sun.COM UNMAP_IPIF_ID((uint_t)ifdata), (family == AF_INET6), ipst); 13798023SPhil.Kirk@Sun.COM if (ipif == NULL) 13808023SPhil.Kirk@Sun.COM return (-1); 13818023SPhil.Kirk@Sun.COM *zoneid = IP_REAL_ZONEID(ipif->ipif_zoneid, ipst); 13828023SPhil.Kirk@Sun.COM ipif_refrele(ipif); 13838023SPhil.Kirk@Sun.COM return (0); 13848023SPhil.Kirk@Sun.COM } 13858023SPhil.Kirk@Sun.COM 13868023SPhil.Kirk@Sun.COM /* 13878023SPhil.Kirk@Sun.COM * Determine the zoneid associated with an IPv4 address 13888023SPhil.Kirk@Sun.COM */ 13898023SPhil.Kirk@Sun.COM static int 13908023SPhil.Kirk@Sun.COM ip_getlifzone(net_handle_t neti, phy_if_t phy_ifdata, lif_if_t ifdata, 13918023SPhil.Kirk@Sun.COM zoneid_t *zoneid) 13928023SPhil.Kirk@Sun.COM { 13938023SPhil.Kirk@Sun.COM return (ip_getlifzone_impl(AF_INET, phy_ifdata, ifdata, 13948023SPhil.Kirk@Sun.COM neti->netd_stack->nts_netstack->netstack_ip, zoneid)); 13958023SPhil.Kirk@Sun.COM } 13968023SPhil.Kirk@Sun.COM 13978023SPhil.Kirk@Sun.COM /* 13988023SPhil.Kirk@Sun.COM * Determine the zoneid associated with an IPv6 address 13998023SPhil.Kirk@Sun.COM */ 14008023SPhil.Kirk@Sun.COM static int 14018023SPhil.Kirk@Sun.COM ipv6_getlifzone(net_handle_t neti, phy_if_t phy_ifdata, lif_if_t ifdata, 14028023SPhil.Kirk@Sun.COM zoneid_t *zoneid) 14038023SPhil.Kirk@Sun.COM { 14048023SPhil.Kirk@Sun.COM return (ip_getlifzone_impl(AF_INET6, phy_ifdata, ifdata, 14058023SPhil.Kirk@Sun.COM neti->netd_stack->nts_netstack->netstack_ip, zoneid)); 14068023SPhil.Kirk@Sun.COM } 14078023SPhil.Kirk@Sun.COM 140810639SDarren.Reed@Sun.COM /* 140910639SDarren.Reed@Sun.COM * The behaviour here mirrors that for the SIOCFLIFFLAGS ioctl where the 141010639SDarren.Reed@Sun.COM * union of all of the relevant flags is returned. 141110639SDarren.Reed@Sun.COM */ 14128023SPhil.Kirk@Sun.COM static int 14138023SPhil.Kirk@Sun.COM ip_getlifflags_impl(sa_family_t family, phy_if_t phy_ifdata, lif_if_t ifdata, 14148023SPhil.Kirk@Sun.COM ip_stack_t *ipst, uint64_t *flags) 14158023SPhil.Kirk@Sun.COM { 141610639SDarren.Reed@Sun.COM phyint_t *phyi; 14178023SPhil.Kirk@Sun.COM ipif_t *ipif; 141810639SDarren.Reed@Sun.COM ill_t *ill; 141910639SDarren.Reed@Sun.COM 142011042SErik.Nordmark@Sun.COM ill = ill_lookup_on_ifindex(phy_ifdata, (family == AF_INET6), ipst); 142110639SDarren.Reed@Sun.COM if (ill == NULL) 142210639SDarren.Reed@Sun.COM return (-1); 142310639SDarren.Reed@Sun.COM phyi = ill->ill_phyint; 14248023SPhil.Kirk@Sun.COM 14258023SPhil.Kirk@Sun.COM ipif = ipif_getby_indexes((uint_t)phy_ifdata, 14268023SPhil.Kirk@Sun.COM UNMAP_IPIF_ID((uint_t)ifdata), (family == AF_INET6), ipst); 142710639SDarren.Reed@Sun.COM if (ipif == NULL) { 142810639SDarren.Reed@Sun.COM ill_refrele(ill); 14298023SPhil.Kirk@Sun.COM return (-1); 143010639SDarren.Reed@Sun.COM } 143110639SDarren.Reed@Sun.COM *flags = ipif->ipif_flags | ill->ill_flags | phyi->phyint_flags; 14328023SPhil.Kirk@Sun.COM ipif_refrele(ipif); 143310639SDarren.Reed@Sun.COM ill_refrele(ill); 14348023SPhil.Kirk@Sun.COM return (0); 14358023SPhil.Kirk@Sun.COM } 14368023SPhil.Kirk@Sun.COM 14378023SPhil.Kirk@Sun.COM static int 14388023SPhil.Kirk@Sun.COM ip_getlifflags(net_handle_t neti, phy_if_t phy_ifdata, lif_if_t ifdata, 14398023SPhil.Kirk@Sun.COM uint64_t *flags) 14408023SPhil.Kirk@Sun.COM { 14418023SPhil.Kirk@Sun.COM return (ip_getlifflags_impl(AF_INET, phy_ifdata, ifdata, 14428023SPhil.Kirk@Sun.COM neti->netd_stack->nts_netstack->netstack_ip, flags)); 14438023SPhil.Kirk@Sun.COM } 14448023SPhil.Kirk@Sun.COM 14458023SPhil.Kirk@Sun.COM static int 14468023SPhil.Kirk@Sun.COM ipv6_getlifflags(net_handle_t neti, phy_if_t phy_ifdata, lif_if_t ifdata, 14478023SPhil.Kirk@Sun.COM uint64_t *flags) 14488023SPhil.Kirk@Sun.COM { 14498023SPhil.Kirk@Sun.COM return (ip_getlifflags_impl(AF_INET6, phy_ifdata, ifdata, 14508023SPhil.Kirk@Sun.COM neti->netd_stack->nts_netstack->netstack_ip, flags)); 14518023SPhil.Kirk@Sun.COM } 14528023SPhil.Kirk@Sun.COM 14538023SPhil.Kirk@Sun.COM /* 14542958Sdr146992 * Deliver packet up into the kernel, immitating its reception by a 14552958Sdr146992 * network interface. 14562958Sdr146992 */ 14572958Sdr146992 static void 14582958Sdr146992 ip_ni_queue_in_func(void *inject) 14592958Sdr146992 { 14602958Sdr146992 ip_ni_queue_func_impl(inject, B_FALSE); 14612958Sdr146992 } 14622958Sdr146992 14632958Sdr146992 /* 14642958Sdr146992 * Deliver out of the kernel, as if it were being sent via a 14652958Sdr146992 * raw socket so that IPFilter will see it again. 14662958Sdr146992 */ 14672958Sdr146992 static void 14682958Sdr146992 ip_ni_queue_out_func(void *inject) 14692958Sdr146992 { 14702958Sdr146992 ip_ni_queue_func_impl(inject, B_TRUE); 14712958Sdr146992 } 14722958Sdr146992 14732958Sdr146992 /* 14742958Sdr146992 * Shared implementation for inject via ip_output and ip_input 14752958Sdr146992 */ 14762958Sdr146992 static void 14772958Sdr146992 ip_ni_queue_func_impl(injection_t *inject, boolean_t out) 14782958Sdr146992 { 14792958Sdr146992 net_inject_t *packet; 14802958Sdr146992 ill_t *ill; 14813448Sdh155122 ip_stack_t *ipst = (ip_stack_t *)inject->inj_ptr; 148211042SErik.Nordmark@Sun.COM ip_xmit_attr_t ixas; 14832958Sdr146992 14842958Sdr146992 ASSERT(inject != NULL); 14852958Sdr146992 packet = &inject->inj_data; 14862958Sdr146992 ASSERT(packet->ni_packet != NULL); 14872958Sdr146992 148811042SErik.Nordmark@Sun.COM if (out == 0) { 148911042SErik.Nordmark@Sun.COM ill = ill_lookup_on_ifindex((uint_t)packet->ni_physical, 149011042SErik.Nordmark@Sun.COM inject->inj_isv6, ipst); 14912958Sdr146992 149211042SErik.Nordmark@Sun.COM if (ill == NULL) { 149311042SErik.Nordmark@Sun.COM kmem_free(inject, sizeof (*inject)); 149411042SErik.Nordmark@Sun.COM return; 149511042SErik.Nordmark@Sun.COM } 149611042SErik.Nordmark@Sun.COM 14972958Sdr146992 if (inject->inj_isv6) { 149811042SErik.Nordmark@Sun.COM ip_input_v6(ill, NULL, packet->ni_packet, NULL); 14992958Sdr146992 } else { 15008275SEric Cheng ip_input(ill, NULL, packet->ni_packet, NULL); 15012958Sdr146992 } 15022958Sdr146992 ill_refrele(ill); 150311042SErik.Nordmark@Sun.COM } else { 150411042SErik.Nordmark@Sun.COM bzero(&ixas, sizeof (ixas)); 150511042SErik.Nordmark@Sun.COM ixas.ixa_ifindex = packet->ni_physical; 150611042SErik.Nordmark@Sun.COM ixas.ixa_ipst = ipst; 15072958Sdr146992 if (inject->inj_isv6) { 150811042SErik.Nordmark@Sun.COM ixas.ixa_flags = IXAF_BASIC_SIMPLE_V6; 15092958Sdr146992 } else { 151011042SErik.Nordmark@Sun.COM ixas.ixa_flags = IXAF_BASIC_SIMPLE_V4; 15112958Sdr146992 } 151211042SErik.Nordmark@Sun.COM (void) ip_output_simple(packet->ni_packet, &ixas); 151311042SErik.Nordmark@Sun.COM ixa_cleanup(&ixas); 15142958Sdr146992 } 15152958Sdr146992 15162958Sdr146992 kmem_free(inject, sizeof (*inject)); 15172958Sdr146992 } 15182958Sdr146992 15192958Sdr146992 /* 15202958Sdr146992 * taskq function for nic events. 15212958Sdr146992 */ 15222958Sdr146992 void 15232958Sdr146992 ip_ne_queue_func(void *arg) 15242958Sdr146992 { 15257513SDarren.Reed@Sun.COM hook_event_token_t hr; 15267513SDarren.Reed@Sun.COM hook_nic_event_int_t *info = (hook_nic_event_int_t *)arg; 15277513SDarren.Reed@Sun.COM ip_stack_t *ipst; 15287513SDarren.Reed@Sun.COM netstack_t *ns; 15297513SDarren.Reed@Sun.COM 15307513SDarren.Reed@Sun.COM ns = netstack_find_by_stackid(info->hnei_stackid); 15317513SDarren.Reed@Sun.COM if (ns == NULL) 15327513SDarren.Reed@Sun.COM goto done; 15332958Sdr146992 15347513SDarren.Reed@Sun.COM ipst = ns->netstack_ip; 15357513SDarren.Reed@Sun.COM if (ipst == NULL) 15367513SDarren.Reed@Sun.COM goto done; 15372958Sdr146992 15387513SDarren.Reed@Sun.COM hr = (info->hnei_event.hne_protocol == ipst->ips_ipv6_net_data) ? 15397513SDarren.Reed@Sun.COM ipst->ips_ipv6nicevents : ipst->ips_ipv4nicevents; 15407513SDarren.Reed@Sun.COM (void) hook_run(info->hnei_event.hne_protocol->netd_hooks, hr, 15417513SDarren.Reed@Sun.COM (hook_data_t)&info->hnei_event); 15427513SDarren.Reed@Sun.COM 15437513SDarren.Reed@Sun.COM done: 15447513SDarren.Reed@Sun.COM if (ns != NULL) 15457513SDarren.Reed@Sun.COM netstack_rele(ns); 15467513SDarren.Reed@Sun.COM kmem_free(info->hnei_event.hne_data, info->hnei_event.hne_datalen); 15477513SDarren.Reed@Sun.COM kmem_free(arg, sizeof (hook_nic_event_int_t)); 15482958Sdr146992 } 154911042SErik.Nordmark@Sun.COM 155011042SErik.Nordmark@Sun.COM /* 155111042SErik.Nordmark@Sun.COM * Initialize ARP hook family and events 155211042SErik.Nordmark@Sun.COM */ 155311042SErik.Nordmark@Sun.COM void 155411042SErik.Nordmark@Sun.COM arp_hook_init(ip_stack_t *ipst) 155511042SErik.Nordmark@Sun.COM { 155611042SErik.Nordmark@Sun.COM HOOK_FAMILY_INIT(&ipst->ips_arproot, Hn_ARP); 155711042SErik.Nordmark@Sun.COM if (net_family_register(ipst->ips_arp_net_data, &ipst->ips_arproot) 155811042SErik.Nordmark@Sun.COM != 0) { 155911042SErik.Nordmark@Sun.COM cmn_err(CE_NOTE, "arp_hook_init" 156011042SErik.Nordmark@Sun.COM "net_family_register failed for arp"); 156111042SErik.Nordmark@Sun.COM } 156211042SErik.Nordmark@Sun.COM 156311042SErik.Nordmark@Sun.COM HOOK_EVENT_INIT(&ipst->ips_arp_physical_in_event, NH_PHYSICAL_IN); 156411042SErik.Nordmark@Sun.COM ipst->ips_arp_physical_in = net_event_register(ipst->ips_arp_net_data, 156511042SErik.Nordmark@Sun.COM &ipst->ips_arp_physical_in_event); 156611042SErik.Nordmark@Sun.COM if (ipst->ips_arp_physical_in == NULL) { 156711042SErik.Nordmark@Sun.COM cmn_err(CE_NOTE, "arp_hook_init: " 156811042SErik.Nordmark@Sun.COM "net_event_register failed for arp/physical_in"); 156911042SErik.Nordmark@Sun.COM } 157011042SErik.Nordmark@Sun.COM 157111042SErik.Nordmark@Sun.COM HOOK_EVENT_INIT(&ipst->ips_arp_physical_out_event, NH_PHYSICAL_OUT); 157211042SErik.Nordmark@Sun.COM ipst->ips_arp_physical_out = net_event_register(ipst->ips_arp_net_data, 157311042SErik.Nordmark@Sun.COM &ipst->ips_arp_physical_out_event); 157411042SErik.Nordmark@Sun.COM if (ipst->ips_arp_physical_out == NULL) { 157511042SErik.Nordmark@Sun.COM cmn_err(CE_NOTE, "arp_hook_init: " 157611042SErik.Nordmark@Sun.COM "net_event_register failed for arp/physical_out"); 157711042SErik.Nordmark@Sun.COM } 157811042SErik.Nordmark@Sun.COM 157911042SErik.Nordmark@Sun.COM HOOK_EVENT_INIT(&ipst->ips_arp_nic_events, NH_NIC_EVENTS); 158011042SErik.Nordmark@Sun.COM ipst->ips_arpnicevents = net_event_register(ipst->ips_arp_net_data, 158111042SErik.Nordmark@Sun.COM &ipst->ips_arp_nic_events); 158211042SErik.Nordmark@Sun.COM if (ipst->ips_arpnicevents == NULL) { 158311042SErik.Nordmark@Sun.COM cmn_err(CE_NOTE, "arp_hook_init: " 158411042SErik.Nordmark@Sun.COM "net_event_register failed for arp/nic_events"); 158511042SErik.Nordmark@Sun.COM } 158611042SErik.Nordmark@Sun.COM } 158711042SErik.Nordmark@Sun.COM 158811042SErik.Nordmark@Sun.COM void 158911042SErik.Nordmark@Sun.COM arp_hook_destroy(ip_stack_t *ipst) 159011042SErik.Nordmark@Sun.COM { 159111042SErik.Nordmark@Sun.COM if (ipst->ips_arpnicevents != NULL) { 159211042SErik.Nordmark@Sun.COM if (net_event_unregister(ipst->ips_arp_net_data, 159311042SErik.Nordmark@Sun.COM &ipst->ips_arp_nic_events) == 0) 159411042SErik.Nordmark@Sun.COM ipst->ips_arpnicevents = NULL; 159511042SErik.Nordmark@Sun.COM } 159611042SErik.Nordmark@Sun.COM 159711042SErik.Nordmark@Sun.COM if (ipst->ips_arp_physical_out != NULL) { 159811042SErik.Nordmark@Sun.COM if (net_event_unregister(ipst->ips_arp_net_data, 159911042SErik.Nordmark@Sun.COM &ipst->ips_arp_physical_out_event) == 0) 160011042SErik.Nordmark@Sun.COM ipst->ips_arp_physical_out = NULL; 160111042SErik.Nordmark@Sun.COM } 160211042SErik.Nordmark@Sun.COM 160311042SErik.Nordmark@Sun.COM if (ipst->ips_arp_physical_in != NULL) { 160411042SErik.Nordmark@Sun.COM if (net_event_unregister(ipst->ips_arp_net_data, 160511042SErik.Nordmark@Sun.COM &ipst->ips_arp_physical_in_event) == 0) 160611042SErik.Nordmark@Sun.COM ipst->ips_arp_physical_in = NULL; 160711042SErik.Nordmark@Sun.COM } 160811042SErik.Nordmark@Sun.COM 160911042SErik.Nordmark@Sun.COM (void) net_family_unregister(ipst->ips_arp_net_data, 161011042SErik.Nordmark@Sun.COM &ipst->ips_arproot); 161111042SErik.Nordmark@Sun.COM } 161211042SErik.Nordmark@Sun.COM 161311042SErik.Nordmark@Sun.COM void 161411042SErik.Nordmark@Sun.COM arp_hook_shutdown(ip_stack_t *ipst) 161511042SErik.Nordmark@Sun.COM { 161611042SErik.Nordmark@Sun.COM if (ipst->ips_arp_physical_in != NULL) { 161711042SErik.Nordmark@Sun.COM (void) net_event_shutdown(ipst->ips_arp_net_data, 161811042SErik.Nordmark@Sun.COM &ipst->ips_arp_physical_in_event); 161911042SErik.Nordmark@Sun.COM } 162011042SErik.Nordmark@Sun.COM if (ipst->ips_arp_physical_out != NULL) { 162111042SErik.Nordmark@Sun.COM (void) net_event_shutdown(ipst->ips_arp_net_data, 162211042SErik.Nordmark@Sun.COM &ipst->ips_arp_physical_out_event); 162311042SErik.Nordmark@Sun.COM } 162411042SErik.Nordmark@Sun.COM if (ipst->ips_arpnicevents != NULL) { 162511042SErik.Nordmark@Sun.COM (void) net_event_shutdown(ipst->ips_arp_net_data, 162611042SErik.Nordmark@Sun.COM &ipst->ips_arp_nic_events); 162711042SErik.Nordmark@Sun.COM } 162811042SErik.Nordmark@Sun.COM } 162911042SErik.Nordmark@Sun.COM 163011042SErik.Nordmark@Sun.COM /* netinfo routines for the unsupported cases */ 163111042SErik.Nordmark@Sun.COM 163211042SErik.Nordmark@Sun.COM /* ARGSUSED */ 163311042SErik.Nordmark@Sun.COM int 163411042SErik.Nordmark@Sun.COM net_no_getmtu(net_handle_t handle, phy_if_t phy_ifdata, lif_if_t ifdata) 163511042SErik.Nordmark@Sun.COM { 163611042SErik.Nordmark@Sun.COM return (-1); 163711042SErik.Nordmark@Sun.COM } 163811042SErik.Nordmark@Sun.COM 163911042SErik.Nordmark@Sun.COM /* ARGSUSED */ 164011042SErik.Nordmark@Sun.COM static int 164111042SErik.Nordmark@Sun.COM net_no_getpmtuenabled(net_handle_t neti) 164211042SErik.Nordmark@Sun.COM { 164311042SErik.Nordmark@Sun.COM return (-1); 164411042SErik.Nordmark@Sun.COM } 164511042SErik.Nordmark@Sun.COM 164611042SErik.Nordmark@Sun.COM /* ARGSUSED */ 164711042SErik.Nordmark@Sun.COM static lif_if_t 164811042SErik.Nordmark@Sun.COM net_no_lifgetnext(net_handle_t neti, phy_if_t phy_ifdata, lif_if_t ifdata) 164911042SErik.Nordmark@Sun.COM { 165011042SErik.Nordmark@Sun.COM return (-1); 165111042SErik.Nordmark@Sun.COM } 165211042SErik.Nordmark@Sun.COM 165311042SErik.Nordmark@Sun.COM /* ARGSUSED */ 165411042SErik.Nordmark@Sun.COM static int 165511042SErik.Nordmark@Sun.COM net_no_inject(net_handle_t neti, inject_t style, net_inject_t *packet) 165611042SErik.Nordmark@Sun.COM { 165711042SErik.Nordmark@Sun.COM return (-1); 165811042SErik.Nordmark@Sun.COM } 165911042SErik.Nordmark@Sun.COM 166011042SErik.Nordmark@Sun.COM /* ARGSUSED */ 166111042SErik.Nordmark@Sun.COM static phy_if_t 166211042SErik.Nordmark@Sun.COM net_no_routeto(net_handle_t neti, struct sockaddr *address, 166311042SErik.Nordmark@Sun.COM struct sockaddr *next) 166411042SErik.Nordmark@Sun.COM { 166511042SErik.Nordmark@Sun.COM return ((phy_if_t)-1); 166611042SErik.Nordmark@Sun.COM } 166711042SErik.Nordmark@Sun.COM 166811042SErik.Nordmark@Sun.COM /* ARGSUSED */ 166911042SErik.Nordmark@Sun.COM static int 167011042SErik.Nordmark@Sun.COM net_no_ispartialchecksum(net_handle_t neti, mblk_t *mp) 167111042SErik.Nordmark@Sun.COM { 167211042SErik.Nordmark@Sun.COM return (-1); 167311042SErik.Nordmark@Sun.COM } 167411042SErik.Nordmark@Sun.COM 167511042SErik.Nordmark@Sun.COM /* ARGSUSED */ 167611042SErik.Nordmark@Sun.COM static int 167711042SErik.Nordmark@Sun.COM net_no_getlifaddr(net_handle_t neti, phy_if_t phy_ifdata, lif_if_t ifdata, 167811042SErik.Nordmark@Sun.COM size_t nelem, net_ifaddr_t type[], void *storage) 167911042SErik.Nordmark@Sun.COM { 168011042SErik.Nordmark@Sun.COM return (-1); 168111042SErik.Nordmark@Sun.COM } 168211042SErik.Nordmark@Sun.COM 168311042SErik.Nordmark@Sun.COM /* ARGSUSED */ 168411042SErik.Nordmark@Sun.COM static int 168511042SErik.Nordmark@Sun.COM net_no_getlifzone(net_handle_t neti, phy_if_t phy_ifdata, lif_if_t ifdata, 168611042SErik.Nordmark@Sun.COM zoneid_t *zoneid) 168711042SErik.Nordmark@Sun.COM { 168811042SErik.Nordmark@Sun.COM return (-1); 168911042SErik.Nordmark@Sun.COM } 169011042SErik.Nordmark@Sun.COM 169111042SErik.Nordmark@Sun.COM /* ARGSUSED */ 169211042SErik.Nordmark@Sun.COM static int 169311042SErik.Nordmark@Sun.COM net_no_getlifflags(net_handle_t neti, phy_if_t phy_ifdata, lif_if_t ifdata, 169411042SErik.Nordmark@Sun.COM uint64_t *flags) 169511042SErik.Nordmark@Sun.COM { 169611042SErik.Nordmark@Sun.COM return (-1); 169711042SErik.Nordmark@Sun.COM } 1698