xref: /onnv-gate/usr/src/uts/common/inet/ip/ip_netinfo.c (revision 11983:15804d064f0c)
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 /*
2211457SErik.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
ip_net_g_init()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
ip_net_g_destroy()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
ip_net_init(ip_stack_t * ipst,netstack_t * ns)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
ip_net_destroy(ip_stack_t * ipst)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
ipv4_hook_init(ip_stack_t * ipst)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
ipv4_hook_shutdown(ip_stack_t * ipst)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
ipv4_hook_destroy(ip_stack_t * ipst)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
ipv6_hook_init(ip_stack_t * ipst)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
ipv6_hook_shutdown(ip_stack_t * ipst)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
ipv6_hook_destroy(ip_stack_t * ipst)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
ip_getifname(net_handle_t neti,phy_if_t phy_ifdata,char * buffer,const size_t buflen)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
ipv6_getifname(net_handle_t neti,phy_if_t phy_ifdata,char * buffer,const size_t buflen)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
ip_getifname_impl(phy_if_t phy_ifdata,char * buffer,const size_t buflen,boolean_t isv6,ip_stack_t * ipst)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
ip_getmtu(net_handle_t neti,phy_if_t phy_ifdata,lif_if_t ifdata)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
ipv6_getmtu(net_handle_t neti,phy_if_t phy_ifdata,lif_if_t ifdata)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
ip_getmtu_impl(phy_if_t phy_ifdata,lif_if_t ifdata,boolean_t isv6,ip_stack_t * ipst)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
ip_getpmtuenabled(net_handle_t neti)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
ip_phygetnext(net_handle_t neti,phy_if_t phy_ifdata)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
ipv6_phygetnext(net_handle_t neti,phy_if_t phy_ifdata)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
ip_phylookup(net_handle_t neti,const char * name)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
ipv6_phylookup(net_handle_t neti,const char * name)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
ip_phylookup_impl(const char * name,boolean_t isv6,ip_stack_t * ipst)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
ip_lifgetnext(net_handle_t neti,phy_if_t phy_ifdata,lif_if_t ifdata)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
ipv6_lifgetnext(net_handle_t neti,phy_if_t phy_ifdata,lif_if_t ifdata)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
ip_lifgetnext_impl(phy_if_t phy_ifdata,lif_if_t ifdata,boolean_t isv6,ip_stack_t * ipst)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
ip_inject(net_handle_t neti,inject_t style,net_inject_t * packet)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
ipv6_inject(net_handle_t neti,inject_t style,net_inject_t * packet)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
ip_inject_impl(inject_t style,net_inject_t * packet,boolean_t isv6,ip_stack_t * ipst)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
ip_routeto(net_handle_t neti,struct sockaddr * address,struct sockaddr * next)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
ipv6_routeto(net_handle_t neti,struct sockaddr * address,struct sockaddr * next)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
ip_routeto_impl(struct sockaddr * address,struct sockaddr * nexthop,ip_stack_t * ipst)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,
108011457SErik.Nordmark@Sun.COM 		    zoneid, NULL, MATCH_IRE_DSTONLY, IRR_ALLOCATE, 0, ipst,
108111457SErik.Nordmark@Sun.COM 		    NULL, NULL, NULL);
10822958Sdr146992 	} else {
108311042SErik.Nordmark@Sun.COM 		ire = ire_route_recursive_v4(sin->sin_addr.s_addr, 0, NULL,
108411457SErik.Nordmark@Sun.COM 		    zoneid, NULL, MATCH_IRE_DSTONLY, IRR_ALLOCATE, 0, ipst,
108511457SErik.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
ip_ispartialchecksum(net_handle_t neti,mblk_t * mp)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
ip_isvalidchecksum(net_handle_t neti,mblk_t * mp)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 &&
117811878SVenu.Iyer@Sun.COM 	    ((DB_CKSUM16(mp) != 0xFFFF &&
117911878SVenu.Iyer@Sun.COM 	    (DB_CKSUMFLAGS(mp) & HCK_FULLCKSUM)) ||
118011878SVenu.Iyer@Sun.COM 	    (DB_CKSUMFLAGS(mp) & HCK_FULLCKSUM_OK)) &&
118111878SVenu.Iyer@Sun.COM 	    (DB_CKSUMFLAGS(mp) & HCK_IPV4_HDRCKSUM_OK))
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
ipv6_isvalidchecksum(net_handle_t neti,mblk_t * mp)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
ip_getlifaddr(net_handle_t neti,phy_if_t phy_ifdata,lif_if_t ifdata,size_t nelem,net_ifaddr_t type[],void * storage)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
ipv6_getlifaddr(net_handle_t neti,phy_if_t phy_ifdata,lif_if_t ifdata,size_t nelem,net_ifaddr_t type[],void * storage)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
ip_getlifaddr_impl(sa_family_t family,phy_if_t phy_ifdata,lif_if_t ifdata,size_t nelem,net_ifaddr_t type[],struct sockaddr * storage,ip_stack_t * ipst)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
ip_getifaddr_type(sa_family_t family,ipif_t * ill_ipif,lif_if_t type,void * storage)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
ip_getlifzone_impl(sa_family_t family,phy_if_t phy_ifdata,lif_if_t ifdata,ip_stack_t * ipst,zoneid_t * zoneid)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
ip_getlifzone(net_handle_t neti,phy_if_t phy_ifdata,lif_if_t ifdata,zoneid_t * zoneid)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
ipv6_getlifzone(net_handle_t neti,phy_if_t phy_ifdata,lif_if_t ifdata,zoneid_t * zoneid)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
ip_getlifflags_impl(sa_family_t family,phy_if_t phy_ifdata,lif_if_t ifdata,ip_stack_t * ipst,uint64_t * flags)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
ip_getlifflags(net_handle_t neti,phy_if_t phy_ifdata,lif_if_t ifdata,uint64_t * flags)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
ipv6_getlifflags(net_handle_t neti,phy_if_t phy_ifdata,lif_if_t ifdata,uint64_t * flags)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
ip_ni_queue_in_func(void * inject)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
ip_ni_queue_out_func(void * inject)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
ip_ni_queue_func_impl(injection_t * inject,boolean_t out)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 		}
1512*11983SSowmini.Varadhan@Sun.COM 		ixas.ixa_flags &= ~IXAF_VERIFY_SOURCE;
151311042SErik.Nordmark@Sun.COM 		(void) ip_output_simple(packet->ni_packet, &ixas);
151411042SErik.Nordmark@Sun.COM 		ixa_cleanup(&ixas);
15152958Sdr146992 	}
15162958Sdr146992 
15172958Sdr146992 	kmem_free(inject, sizeof (*inject));
15182958Sdr146992 }
15192958Sdr146992 
15202958Sdr146992 /*
15212958Sdr146992  * taskq function for nic events.
15222958Sdr146992  */
15232958Sdr146992 void
ip_ne_queue_func(void * arg)15242958Sdr146992 ip_ne_queue_func(void *arg)
15252958Sdr146992 {
15267513SDarren.Reed@Sun.COM 	hook_event_token_t hr;
15277513SDarren.Reed@Sun.COM 	hook_nic_event_int_t *info = (hook_nic_event_int_t *)arg;
15287513SDarren.Reed@Sun.COM 	ip_stack_t *ipst;
15297513SDarren.Reed@Sun.COM 	netstack_t *ns;
15307513SDarren.Reed@Sun.COM 
15317513SDarren.Reed@Sun.COM 	ns = netstack_find_by_stackid(info->hnei_stackid);
15327513SDarren.Reed@Sun.COM 	if (ns == NULL)
15337513SDarren.Reed@Sun.COM 		goto done;
15342958Sdr146992 
15357513SDarren.Reed@Sun.COM 	ipst = ns->netstack_ip;
15367513SDarren.Reed@Sun.COM 	if (ipst == NULL)
15377513SDarren.Reed@Sun.COM 		goto done;
15382958Sdr146992 
15397513SDarren.Reed@Sun.COM 	hr = (info->hnei_event.hne_protocol == ipst->ips_ipv6_net_data) ?
15407513SDarren.Reed@Sun.COM 	    ipst->ips_ipv6nicevents : ipst->ips_ipv4nicevents;
15417513SDarren.Reed@Sun.COM 	(void) hook_run(info->hnei_event.hne_protocol->netd_hooks, hr,
15427513SDarren.Reed@Sun.COM 	    (hook_data_t)&info->hnei_event);
15437513SDarren.Reed@Sun.COM 
15447513SDarren.Reed@Sun.COM done:
15457513SDarren.Reed@Sun.COM 	if (ns != NULL)
15467513SDarren.Reed@Sun.COM 		netstack_rele(ns);
15477513SDarren.Reed@Sun.COM 	kmem_free(info->hnei_event.hne_data, info->hnei_event.hne_datalen);
15487513SDarren.Reed@Sun.COM 	kmem_free(arg, sizeof (hook_nic_event_int_t));
15492958Sdr146992 }
155011042SErik.Nordmark@Sun.COM 
155111042SErik.Nordmark@Sun.COM /*
155211042SErik.Nordmark@Sun.COM  * Initialize ARP hook family and events
155311042SErik.Nordmark@Sun.COM  */
155411042SErik.Nordmark@Sun.COM void
arp_hook_init(ip_stack_t * ipst)155511042SErik.Nordmark@Sun.COM arp_hook_init(ip_stack_t *ipst)
155611042SErik.Nordmark@Sun.COM {
155711042SErik.Nordmark@Sun.COM 	HOOK_FAMILY_INIT(&ipst->ips_arproot, Hn_ARP);
155811042SErik.Nordmark@Sun.COM 	if (net_family_register(ipst->ips_arp_net_data, &ipst->ips_arproot)
155911042SErik.Nordmark@Sun.COM 	    != 0) {
156011042SErik.Nordmark@Sun.COM 		cmn_err(CE_NOTE, "arp_hook_init"
156111042SErik.Nordmark@Sun.COM 		    "net_family_register failed for arp");
156211042SErik.Nordmark@Sun.COM 	}
156311042SErik.Nordmark@Sun.COM 
156411042SErik.Nordmark@Sun.COM 	HOOK_EVENT_INIT(&ipst->ips_arp_physical_in_event, NH_PHYSICAL_IN);
156511042SErik.Nordmark@Sun.COM 	ipst->ips_arp_physical_in = net_event_register(ipst->ips_arp_net_data,
156611042SErik.Nordmark@Sun.COM 	    &ipst->ips_arp_physical_in_event);
156711042SErik.Nordmark@Sun.COM 	if (ipst->ips_arp_physical_in == NULL) {
156811042SErik.Nordmark@Sun.COM 		cmn_err(CE_NOTE, "arp_hook_init: "
156911042SErik.Nordmark@Sun.COM 		    "net_event_register failed for arp/physical_in");
157011042SErik.Nordmark@Sun.COM 	}
157111042SErik.Nordmark@Sun.COM 
157211042SErik.Nordmark@Sun.COM 	HOOK_EVENT_INIT(&ipst->ips_arp_physical_out_event, NH_PHYSICAL_OUT);
157311042SErik.Nordmark@Sun.COM 	ipst->ips_arp_physical_out = net_event_register(ipst->ips_arp_net_data,
157411042SErik.Nordmark@Sun.COM 	    &ipst->ips_arp_physical_out_event);
157511042SErik.Nordmark@Sun.COM 	if (ipst->ips_arp_physical_out == NULL) {
157611042SErik.Nordmark@Sun.COM 		cmn_err(CE_NOTE, "arp_hook_init: "
157711042SErik.Nordmark@Sun.COM 		    "net_event_register failed for arp/physical_out");
157811042SErik.Nordmark@Sun.COM 	}
157911042SErik.Nordmark@Sun.COM 
158011042SErik.Nordmark@Sun.COM 	HOOK_EVENT_INIT(&ipst->ips_arp_nic_events, NH_NIC_EVENTS);
158111042SErik.Nordmark@Sun.COM 	ipst->ips_arpnicevents = net_event_register(ipst->ips_arp_net_data,
158211042SErik.Nordmark@Sun.COM 	    &ipst->ips_arp_nic_events);
158311042SErik.Nordmark@Sun.COM 	if (ipst->ips_arpnicevents == NULL) {
158411042SErik.Nordmark@Sun.COM 		cmn_err(CE_NOTE, "arp_hook_init: "
158511042SErik.Nordmark@Sun.COM 		    "net_event_register failed for arp/nic_events");
158611042SErik.Nordmark@Sun.COM 	}
158711042SErik.Nordmark@Sun.COM }
158811042SErik.Nordmark@Sun.COM 
158911042SErik.Nordmark@Sun.COM void
arp_hook_destroy(ip_stack_t * ipst)159011042SErik.Nordmark@Sun.COM arp_hook_destroy(ip_stack_t *ipst)
159111042SErik.Nordmark@Sun.COM {
159211042SErik.Nordmark@Sun.COM 	if (ipst->ips_arpnicevents != NULL) {
159311042SErik.Nordmark@Sun.COM 		if (net_event_unregister(ipst->ips_arp_net_data,
159411042SErik.Nordmark@Sun.COM 		    &ipst->ips_arp_nic_events) == 0)
159511042SErik.Nordmark@Sun.COM 			ipst->ips_arpnicevents = NULL;
159611042SErik.Nordmark@Sun.COM 	}
159711042SErik.Nordmark@Sun.COM 
159811042SErik.Nordmark@Sun.COM 	if (ipst->ips_arp_physical_out != NULL) {
159911042SErik.Nordmark@Sun.COM 		if (net_event_unregister(ipst->ips_arp_net_data,
160011042SErik.Nordmark@Sun.COM 		    &ipst->ips_arp_physical_out_event) == 0)
160111042SErik.Nordmark@Sun.COM 			ipst->ips_arp_physical_out = NULL;
160211042SErik.Nordmark@Sun.COM 	}
160311042SErik.Nordmark@Sun.COM 
160411042SErik.Nordmark@Sun.COM 	if (ipst->ips_arp_physical_in != NULL) {
160511042SErik.Nordmark@Sun.COM 		if (net_event_unregister(ipst->ips_arp_net_data,
160611042SErik.Nordmark@Sun.COM 		    &ipst->ips_arp_physical_in_event) == 0)
160711042SErik.Nordmark@Sun.COM 			ipst->ips_arp_physical_in = NULL;
160811042SErik.Nordmark@Sun.COM 	}
160911042SErik.Nordmark@Sun.COM 
161011042SErik.Nordmark@Sun.COM 	(void) net_family_unregister(ipst->ips_arp_net_data,
161111042SErik.Nordmark@Sun.COM 	    &ipst->ips_arproot);
161211042SErik.Nordmark@Sun.COM }
161311042SErik.Nordmark@Sun.COM 
161411042SErik.Nordmark@Sun.COM void
arp_hook_shutdown(ip_stack_t * ipst)161511042SErik.Nordmark@Sun.COM arp_hook_shutdown(ip_stack_t *ipst)
161611042SErik.Nordmark@Sun.COM {
161711042SErik.Nordmark@Sun.COM 	if (ipst->ips_arp_physical_in != NULL) {
161811042SErik.Nordmark@Sun.COM 		(void) net_event_shutdown(ipst->ips_arp_net_data,
161911042SErik.Nordmark@Sun.COM 		    &ipst->ips_arp_physical_in_event);
162011042SErik.Nordmark@Sun.COM 	}
162111042SErik.Nordmark@Sun.COM 	if (ipst->ips_arp_physical_out != NULL) {
162211042SErik.Nordmark@Sun.COM 		(void) net_event_shutdown(ipst->ips_arp_net_data,
162311042SErik.Nordmark@Sun.COM 		    &ipst->ips_arp_physical_out_event);
162411042SErik.Nordmark@Sun.COM 	}
162511042SErik.Nordmark@Sun.COM 	if (ipst->ips_arpnicevents != NULL) {
162611042SErik.Nordmark@Sun.COM 		(void) net_event_shutdown(ipst->ips_arp_net_data,
162711042SErik.Nordmark@Sun.COM 		    &ipst->ips_arp_nic_events);
162811042SErik.Nordmark@Sun.COM 	}
162911042SErik.Nordmark@Sun.COM }
163011042SErik.Nordmark@Sun.COM 
163111042SErik.Nordmark@Sun.COM /* netinfo routines for the unsupported cases */
163211042SErik.Nordmark@Sun.COM 
163311042SErik.Nordmark@Sun.COM /* ARGSUSED */
163411042SErik.Nordmark@Sun.COM int
net_no_getmtu(net_handle_t handle,phy_if_t phy_ifdata,lif_if_t ifdata)163511042SErik.Nordmark@Sun.COM net_no_getmtu(net_handle_t handle, phy_if_t phy_ifdata, lif_if_t ifdata)
163611042SErik.Nordmark@Sun.COM {
163711042SErik.Nordmark@Sun.COM 	return (-1);
163811042SErik.Nordmark@Sun.COM }
163911042SErik.Nordmark@Sun.COM 
164011042SErik.Nordmark@Sun.COM /* ARGSUSED */
164111042SErik.Nordmark@Sun.COM static int
net_no_getpmtuenabled(net_handle_t neti)164211042SErik.Nordmark@Sun.COM net_no_getpmtuenabled(net_handle_t neti)
164311042SErik.Nordmark@Sun.COM {
164411042SErik.Nordmark@Sun.COM 	return (-1);
164511042SErik.Nordmark@Sun.COM }
164611042SErik.Nordmark@Sun.COM 
164711042SErik.Nordmark@Sun.COM /* ARGSUSED */
164811042SErik.Nordmark@Sun.COM static lif_if_t
net_no_lifgetnext(net_handle_t neti,phy_if_t phy_ifdata,lif_if_t ifdata)164911042SErik.Nordmark@Sun.COM net_no_lifgetnext(net_handle_t neti, phy_if_t phy_ifdata, lif_if_t ifdata)
165011042SErik.Nordmark@Sun.COM {
165111042SErik.Nordmark@Sun.COM 	return (-1);
165211042SErik.Nordmark@Sun.COM }
165311042SErik.Nordmark@Sun.COM 
165411042SErik.Nordmark@Sun.COM /* ARGSUSED */
165511042SErik.Nordmark@Sun.COM static int
net_no_inject(net_handle_t neti,inject_t style,net_inject_t * packet)165611042SErik.Nordmark@Sun.COM net_no_inject(net_handle_t neti, inject_t style, net_inject_t *packet)
165711042SErik.Nordmark@Sun.COM {
165811042SErik.Nordmark@Sun.COM 	return (-1);
165911042SErik.Nordmark@Sun.COM }
166011042SErik.Nordmark@Sun.COM 
166111042SErik.Nordmark@Sun.COM /* ARGSUSED */
166211042SErik.Nordmark@Sun.COM static phy_if_t
net_no_routeto(net_handle_t neti,struct sockaddr * address,struct sockaddr * next)166311042SErik.Nordmark@Sun.COM net_no_routeto(net_handle_t neti, struct sockaddr *address,
166411042SErik.Nordmark@Sun.COM     struct sockaddr *next)
166511042SErik.Nordmark@Sun.COM {
166611042SErik.Nordmark@Sun.COM 	return ((phy_if_t)-1);
166711042SErik.Nordmark@Sun.COM }
166811042SErik.Nordmark@Sun.COM 
166911042SErik.Nordmark@Sun.COM /* ARGSUSED */
167011042SErik.Nordmark@Sun.COM static int
net_no_ispartialchecksum(net_handle_t neti,mblk_t * mp)167111042SErik.Nordmark@Sun.COM net_no_ispartialchecksum(net_handle_t neti, mblk_t *mp)
167211042SErik.Nordmark@Sun.COM {
167311042SErik.Nordmark@Sun.COM 	return (-1);
167411042SErik.Nordmark@Sun.COM }
167511042SErik.Nordmark@Sun.COM 
167611042SErik.Nordmark@Sun.COM /* ARGSUSED */
167711042SErik.Nordmark@Sun.COM static int
net_no_getlifaddr(net_handle_t neti,phy_if_t phy_ifdata,lif_if_t ifdata,size_t nelem,net_ifaddr_t type[],void * storage)167811042SErik.Nordmark@Sun.COM net_no_getlifaddr(net_handle_t neti, phy_if_t phy_ifdata, lif_if_t ifdata,
167911042SErik.Nordmark@Sun.COM     size_t nelem, net_ifaddr_t type[], void *storage)
168011042SErik.Nordmark@Sun.COM {
168111042SErik.Nordmark@Sun.COM 	return (-1);
168211042SErik.Nordmark@Sun.COM }
168311042SErik.Nordmark@Sun.COM 
168411042SErik.Nordmark@Sun.COM /* ARGSUSED */
168511042SErik.Nordmark@Sun.COM static int
net_no_getlifzone(net_handle_t neti,phy_if_t phy_ifdata,lif_if_t ifdata,zoneid_t * zoneid)168611042SErik.Nordmark@Sun.COM net_no_getlifzone(net_handle_t neti, phy_if_t phy_ifdata, lif_if_t ifdata,
168711042SErik.Nordmark@Sun.COM     zoneid_t *zoneid)
168811042SErik.Nordmark@Sun.COM {
168911042SErik.Nordmark@Sun.COM 	return (-1);
169011042SErik.Nordmark@Sun.COM }
169111042SErik.Nordmark@Sun.COM 
169211042SErik.Nordmark@Sun.COM /* ARGSUSED */
169311042SErik.Nordmark@Sun.COM static int
net_no_getlifflags(net_handle_t neti,phy_if_t phy_ifdata,lif_if_t ifdata,uint64_t * flags)169411042SErik.Nordmark@Sun.COM net_no_getlifflags(net_handle_t neti, phy_if_t phy_ifdata, lif_if_t ifdata,
169511042SErik.Nordmark@Sun.COM     uint64_t *flags)
169611042SErik.Nordmark@Sun.COM {
169711042SErik.Nordmark@Sun.COM 	return (-1);
169811042SErik.Nordmark@Sun.COM }
1699