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