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