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