xref: /titanic_50/usr/src/uts/common/inet/ip/ip_netinfo.c (revision 711890bc9379ceea66272dc8d4981812224ea86e)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 #include <sys/param.h>
29 #include <sys/types.h>
30 #include <sys/systm.h>
31 #include <sys/stream.h>
32 #include <sys/strsubr.h>
33 #include <sys/pattr.h>
34 #include <sys/dlpi.h>
35 #include <sys/atomic.h>
36 #include <sys/sunddi.h>
37 #include <sys/socket.h>
38 #include <sys/neti.h>
39 
40 #include <netinet/in.h>
41 #include <inet/common.h>
42 #include <inet/mib2.h>
43 #include <inet/ip.h>
44 #include <inet/ip6.h>
45 #include <inet/ip_if.h>
46 #include <inet/ip_ire.h>
47 #include <inet/ip_impl.h>
48 #include <inet/ip_ndp.h>
49 #include <inet/ipclassifier.h>
50 #include <inet/ipp_common.h>
51 #include <inet/ip_ftable.h>
52 
53 /*
54  * IPv4 netinfo entry point declarations.
55  */
56 static int 		ip_getifname(phy_if_t, char *, const size_t,
57     netstack_t *);
58 static int 		ip_getmtu(phy_if_t, lif_if_t, netstack_t *);
59 static int 		ip_getpmtuenabled(netstack_t *);
60 static int 		ip_getlifaddr(phy_if_t, lif_if_t, size_t,
61 			    net_ifaddr_t [], void *, netstack_t *);
62 static phy_if_t		ip_phygetnext(phy_if_t, netstack_t *);
63 static phy_if_t 	ip_phylookup(const char *, netstack_t *);
64 static lif_if_t 	ip_lifgetnext(phy_if_t, lif_if_t, netstack_t *);
65 static int 		ip_inject(inject_t, net_inject_t *, netstack_t *);
66 static phy_if_t 	ip_routeto(struct sockaddr *, netstack_t *);
67 static int 		ip_ispartialchecksum(mblk_t *);
68 static int 		ip_isvalidchecksum(mblk_t *);
69 
70 static int 		ipv6_getifname(phy_if_t, char *, const size_t,
71     netstack_t *);
72 static int 		ipv6_getmtu(phy_if_t, lif_if_t, netstack_t *);
73 static int 		ipv6_getlifaddr(phy_if_t, lif_if_t, size_t,
74 			    net_ifaddr_t [], void *, netstack_t *);
75 static phy_if_t 	ipv6_phygetnext(phy_if_t, netstack_t *);
76 static phy_if_t 	ipv6_phylookup(const char *, netstack_t *);
77 static lif_if_t 	ipv6_lifgetnext(phy_if_t, lif_if_t, netstack_t *);
78 static int 		ipv6_inject(inject_t, net_inject_t *, netstack_t *);
79 static phy_if_t 	ipv6_routeto(struct sockaddr *, netstack_t *);
80 static int 		ipv6_isvalidchecksum(mblk_t *);
81 
82 /* Netinfo private functions */
83 static	int		ip_getifname_impl(phy_if_t, char *,
84     const size_t, boolean_t, ip_stack_t *);
85 static	int		ip_getmtu_impl(phy_if_t, lif_if_t, boolean_t,
86     ip_stack_t *);
87 static	phy_if_t	ip_phylookup_impl(const char *, boolean_t,
88     ip_stack_t *ipst);
89 static	lif_if_t	ip_lifgetnext_impl(phy_if_t, lif_if_t, boolean_t,
90     ip_stack_t *ipst);
91 static	int		ip_inject_impl(inject_t, net_inject_t *, boolean_t,
92     ip_stack_t *);
93 static	int		ip_getifaddr_type(sa_family_t, ipif_t *, lif_if_t,
94 			    void *);
95 static	phy_if_t	ip_routeto_impl(struct sockaddr *, ip_stack_t *);
96 static	int		ip_getlifaddr_impl(sa_family_t, phy_if_t, lif_if_t,
97 			    size_t, net_ifaddr_t [], struct sockaddr *,
98 			    ip_stack_t *);
99 static	void		ip_ni_queue_in_func(void *);
100 static	void		ip_ni_queue_out_func(void *);
101 static	void		ip_ni_queue_func_impl(injection_t *,  boolean_t);
102 
103 
104 static net_info_t ipv4info = {
105 	NETINFO_VERSION,
106 	NHF_INET,
107 	ip_getifname,
108 	ip_getmtu,
109 	ip_getpmtuenabled,
110 	ip_getlifaddr,
111 	ip_phygetnext,
112 	ip_phylookup,
113 	ip_lifgetnext,
114 	ip_inject,
115 	ip_routeto,
116 	ip_ispartialchecksum,
117 	ip_isvalidchecksum
118 };
119 
120 
121 static net_info_t ipv6info = {
122 	NETINFO_VERSION,
123 	NHF_INET6,
124 	ipv6_getifname,
125 	ipv6_getmtu,
126 	ip_getpmtuenabled,
127 	ipv6_getlifaddr,
128 	ipv6_phygetnext,
129 	ipv6_phylookup,
130 	ipv6_lifgetnext,
131 	ipv6_inject,
132 	ipv6_routeto,
133 	ip_ispartialchecksum,
134 	ipv6_isvalidchecksum
135 };
136 
137 /*
138  * The taskq eventq_queue_in is used to process the upside inject messages.
139  * The taskq eventq_queue_out is used to process the downside inject messages.
140  * The taskq eventq_queue_nic is used to process the nic event messages.
141  */
142 static ddi_taskq_t 	*eventq_queue_in = NULL;
143 static ddi_taskq_t 	*eventq_queue_out = NULL;
144 ddi_taskq_t 	*eventq_queue_nic = NULL;
145 
146 /*
147  * Initialize queues for inject.
148  */
149 void
150 ip_net_g_init()
151 {
152 	if (eventq_queue_out == NULL) {
153 		eventq_queue_out = ddi_taskq_create(NULL,
154 		    "IP_INJECT_QUEUE_OUT", 1, TASKQ_DEFAULTPRI, 0);
155 
156 		if (eventq_queue_out == NULL)
157 			cmn_err(CE_NOTE, "ipv4_net_init: "
158 			    "ddi_taskq_create failed for IP_INJECT_QUEUE_OUT");
159 	}
160 
161 	if (eventq_queue_in == NULL) {
162 		eventq_queue_in = ddi_taskq_create(NULL,
163 		    "IP_INJECT_QUEUE_IN", 1, TASKQ_DEFAULTPRI, 0);
164 
165 		if (eventq_queue_in == NULL)
166 			cmn_err(CE_NOTE, "ipv4_net_init: "
167 			    "ddi_taskq_create failed for IP_INJECT_QUEUE_IN");
168 	}
169 
170 	if (eventq_queue_nic == NULL) {
171 		eventq_queue_nic = ddi_taskq_create(NULL,
172 		    "IP_NIC_EVENT_QUEUE", 1, TASKQ_DEFAULTPRI, 0);
173 
174 		if (eventq_queue_nic == NULL)
175 			cmn_err(CE_NOTE, "ipv4_net_init: "
176 			    "ddi_taskq_create failed for IP_NIC_EVENT_QUEUE");
177 	}
178 }
179 
180 /*
181  * Destroy inject queues
182  */
183 void
184 ip_net_g_destroy()
185 {
186 	if (eventq_queue_nic != NULL) {
187 		ddi_taskq_destroy(eventq_queue_nic);
188 		eventq_queue_nic = NULL;
189 	}
190 
191 	if (eventq_queue_in != NULL) {
192 		ddi_taskq_destroy(eventq_queue_in);
193 		eventq_queue_in = NULL;
194 	}
195 
196 	if (eventq_queue_out != NULL) {
197 		ddi_taskq_destroy(eventq_queue_out);
198 		eventq_queue_out = NULL;
199 	}
200 }
201 
202 /*
203  * Register IPv4 and IPv6 netinfo functions and initialize queues for inject.
204  */
205 void
206 ip_net_init(ip_stack_t *ipst, netstack_t *ns)
207 {
208 
209 	ipst->ips_ipv4_net_data = net_register_impl(&ipv4info, ns);
210 	ASSERT(ipst->ips_ipv4_net_data != NULL);
211 
212 	ipst->ips_ipv6_net_data = net_register_impl(&ipv6info, ns);
213 	ASSERT(ipst->ips_ipv6_net_data != NULL);
214 }
215 
216 
217 /*
218  * Unregister IPv4 and IPv6 functions and inject queues
219  */
220 void
221 ip_net_destroy(ip_stack_t *ipst)
222 {
223 	if (ipst->ips_ipv4_net_data != NULL) {
224 		if (net_unregister(ipst->ips_ipv4_net_data) == 0)
225 			ipst->ips_ipv4_net_data = NULL;
226 	}
227 
228 	if (ipst->ips_ipv6_net_data != NULL) {
229 		if (net_unregister(ipst->ips_ipv6_net_data) == 0)
230 			ipst->ips_ipv6_net_data = NULL;
231 	}
232 }
233 
234 /*
235  * Initialize IPv4 hooks family the event
236  */
237 void
238 ipv4_hook_init(ip_stack_t *ipst)
239 {
240 	HOOK_FAMILY_INIT(&ipst->ips_ipv4root, Hn_IPV4);
241 	if (net_register_family(ipst->ips_ipv4_net_data, &ipst->ips_ipv4root)
242 	    != 0) {
243 		cmn_err(CE_NOTE, "ipv4_hook_init: "
244 		    "net_register_family failed for ipv4");
245 	}
246 
247 	HOOK_EVENT_INIT(&ipst->ips_ip4_physical_in_event, NH_PHYSICAL_IN);
248 	ipst->ips_ipv4firewall_physical_in = net_register_event(
249 	    ipst->ips_ipv4_net_data, &ipst->ips_ip4_physical_in_event);
250 	if (ipst->ips_ipv4firewall_physical_in == NULL) {
251 		cmn_err(CE_NOTE, "ipv4_hook_init: "
252 		    "net_register_event failed for ipv4/physical_in");
253 	}
254 
255 	HOOK_EVENT_INIT(&ipst->ips_ip4_physical_out_event, NH_PHYSICAL_OUT);
256 	ipst->ips_ipv4firewall_physical_out = net_register_event(
257 	    ipst->ips_ipv4_net_data, &ipst->ips_ip4_physical_out_event);
258 	if (ipst->ips_ipv4firewall_physical_out == NULL) {
259 		cmn_err(CE_NOTE, "ipv4_hook_init: "
260 		    "net_register_event failed for ipv4/physical_out");
261 	}
262 
263 	HOOK_EVENT_INIT(&ipst->ips_ip4_forwarding_event, NH_FORWARDING);
264 	ipst->ips_ipv4firewall_forwarding = net_register_event(
265 	    ipst->ips_ipv4_net_data, &ipst->ips_ip4_forwarding_event);
266 	if (ipst->ips_ipv4firewall_forwarding == NULL) {
267 		cmn_err(CE_NOTE, "ipv4_hook_init: "
268 		    "net_register_event failed for ipv4/forwarding");
269 	}
270 
271 	HOOK_EVENT_INIT(&ipst->ips_ip4_loopback_in_event, NH_LOOPBACK_IN);
272 	ipst->ips_ipv4firewall_loopback_in = net_register_event(
273 	    ipst->ips_ipv4_net_data, &ipst->ips_ip4_loopback_in_event);
274 	if (ipst->ips_ipv4firewall_loopback_in == NULL) {
275 		cmn_err(CE_NOTE, "ipv4_hook_init: "
276 		    "net_register_event failed for ipv4/loopback_in");
277 	}
278 
279 	HOOK_EVENT_INIT(&ipst->ips_ip4_loopback_out_event, NH_LOOPBACK_OUT);
280 	ipst->ips_ipv4firewall_loopback_out = net_register_event(
281 	    ipst->ips_ipv4_net_data, &ipst->ips_ip4_loopback_out_event);
282 	if (ipst->ips_ipv4firewall_loopback_out == NULL) {
283 		cmn_err(CE_NOTE, "ipv4_hook_init: "
284 		    "net_register_event failed for ipv4/loopback_out");
285 	}
286 
287 	HOOK_EVENT_INIT(&ipst->ips_ip4_nic_events, NH_NIC_EVENTS);
288 	ipst->ips_ip4_nic_events.he_flags = HOOK_RDONLY;
289 	ipst->ips_ipv4nicevents = net_register_event(
290 	    ipst->ips_ipv4_net_data, &ipst->ips_ip4_nic_events);
291 	if (ipst->ips_ipv4nicevents == NULL) {
292 		cmn_err(CE_NOTE, "ipv4_hook_init: "
293 		    "net_register_event failed for ipv4/nic_events");
294 	}
295 }
296 
297 void
298 ipv4_hook_destroy(ip_stack_t *ipst)
299 {
300 	if (ipst->ips_ipv4firewall_forwarding != NULL) {
301 		if (net_unregister_event(ipst->ips_ipv4_net_data,
302 		    &ipst->ips_ip4_forwarding_event) == 0)
303 			ipst->ips_ipv4firewall_forwarding = NULL;
304 	}
305 
306 	if (ipst->ips_ipv4firewall_physical_in != NULL) {
307 		if (net_unregister_event(ipst->ips_ipv4_net_data,
308 		    &ipst->ips_ip4_physical_in_event) == 0)
309 			ipst->ips_ipv4firewall_physical_in = NULL;
310 	}
311 
312 	if (ipst->ips_ipv4firewall_physical_out != NULL) {
313 		if (net_unregister_event(ipst->ips_ipv4_net_data,
314 		    &ipst->ips_ip4_physical_out_event) == 0)
315 			ipst->ips_ipv4firewall_physical_out = NULL;
316 	}
317 
318 	if (ipst->ips_ipv4firewall_loopback_in != NULL) {
319 		if (net_unregister_event(ipst->ips_ipv4_net_data,
320 		    &ipst->ips_ip4_loopback_in_event) == 0)
321 			ipst->ips_ipv4firewall_loopback_in = NULL;
322 	}
323 
324 	if (ipst->ips_ipv4firewall_loopback_out != NULL) {
325 		if (net_unregister_event(ipst->ips_ipv4_net_data,
326 		    &ipst->ips_ip4_loopback_out_event) == 0)
327 			ipst->ips_ipv4firewall_loopback_out = NULL;
328 	}
329 
330 	if (ipst->ips_ipv4nicevents != NULL) {
331 		if (net_unregister_event(ipst->ips_ipv4_net_data,
332 		    &ipst->ips_ip4_nic_events) == 0)
333 			ipst->ips_ipv4nicevents = NULL;
334 	}
335 
336 	(void) net_unregister_family(ipst->ips_ipv4_net_data,
337 	    &ipst->ips_ipv4root);
338 }
339 
340 /*
341  * Initialize IPv6 hooks family and event
342  */
343 void
344 ipv6_hook_init(ip_stack_t *ipst)
345 {
346 
347 	HOOK_FAMILY_INIT(&ipst->ips_ipv6root, Hn_IPV6);
348 	if (net_register_family(ipst->ips_ipv6_net_data, &ipst->ips_ipv6root)
349 	    != 0) {
350 		cmn_err(CE_NOTE, "ipv6_hook_init: "
351 		    "net_register_family failed for ipv6");
352 	}
353 
354 	HOOK_EVENT_INIT(&ipst->ips_ip6_physical_in_event, NH_PHYSICAL_IN);
355 	ipst->ips_ipv6firewall_physical_in = net_register_event(
356 	    ipst->ips_ipv6_net_data, &ipst->ips_ip6_physical_in_event);
357 	if (ipst->ips_ipv6firewall_physical_in == NULL) {
358 		cmn_err(CE_NOTE, "ipv6_hook_init: "
359 		    "net_register_event failed for ipv6/physical_in");
360 	}
361 
362 	HOOK_EVENT_INIT(&ipst->ips_ip6_physical_out_event, NH_PHYSICAL_OUT);
363 	ipst->ips_ipv6firewall_physical_out = net_register_event(
364 	    ipst->ips_ipv6_net_data, &ipst->ips_ip6_physical_out_event);
365 	if (ipst->ips_ipv6firewall_physical_out == NULL) {
366 		cmn_err(CE_NOTE, "ipv6_hook_init: "
367 		    "net_register_event failed for ipv6/physical_out");
368 	}
369 
370 	HOOK_EVENT_INIT(&ipst->ips_ip6_forwarding_event, NH_FORWARDING);
371 	ipst->ips_ipv6firewall_forwarding = net_register_event(
372 	    ipst->ips_ipv6_net_data, &ipst->ips_ip6_forwarding_event);
373 	if (ipst->ips_ipv6firewall_forwarding == NULL) {
374 		cmn_err(CE_NOTE, "ipv6_hook_init: "
375 		    "net_register_event failed for ipv6/forwarding");
376 	}
377 
378 	HOOK_EVENT_INIT(&ipst->ips_ip6_loopback_in_event, NH_LOOPBACK_IN);
379 	ipst->ips_ipv6firewall_loopback_in = net_register_event(
380 	    ipst->ips_ipv6_net_data, &ipst->ips_ip6_loopback_in_event);
381 	if (ipst->ips_ipv6firewall_loopback_in == NULL) {
382 		cmn_err(CE_NOTE, "ipv6_hook_init: "
383 		    "net_register_event failed for ipv6/loopback_in");
384 	}
385 
386 	HOOK_EVENT_INIT(&ipst->ips_ip6_loopback_out_event, NH_LOOPBACK_OUT);
387 	ipst->ips_ipv6firewall_loopback_out = net_register_event(
388 	    ipst->ips_ipv6_net_data, &ipst->ips_ip6_loopback_out_event);
389 	if (ipst->ips_ipv6firewall_loopback_out == NULL) {
390 		cmn_err(CE_NOTE, "ipv6_hook_init: "
391 		    "net_register_event failed for ipv6/loopback_out");
392 	}
393 
394 	HOOK_EVENT_INIT(&ipst->ips_ip6_nic_events, NH_NIC_EVENTS);
395 	ipst->ips_ip6_nic_events.he_flags = HOOK_RDONLY;
396 	ipst->ips_ipv6nicevents = net_register_event(
397 	    ipst->ips_ipv6_net_data, &ipst->ips_ip6_nic_events);
398 	if (ipst->ips_ipv6nicevents == NULL) {
399 		cmn_err(CE_NOTE, "ipv6_hook_init: "
400 		    "net_register_event failed for ipv6/nic_events");
401 	}
402 }
403 
404 void
405 ipv6_hook_destroy(ip_stack_t *ipst)
406 {
407 	if (ipst->ips_ipv6firewall_forwarding != NULL) {
408 		if (net_unregister_event(ipst->ips_ipv6_net_data,
409 		    &ipst->ips_ip6_forwarding_event) == 0)
410 			ipst->ips_ipv6firewall_forwarding = NULL;
411 	}
412 
413 	if (ipst->ips_ipv6firewall_physical_in != NULL) {
414 		if (net_unregister_event(ipst->ips_ipv6_net_data,
415 		    &ipst->ips_ip6_physical_in_event) == 0)
416 			ipst->ips_ipv6firewall_physical_in = NULL;
417 	}
418 
419 	if (ipst->ips_ipv6firewall_physical_out != NULL) {
420 		if (net_unregister_event(ipst->ips_ipv6_net_data,
421 		    &ipst->ips_ip6_physical_out_event) == 0)
422 			ipst->ips_ipv6firewall_physical_out = NULL;
423 	}
424 
425 	if (ipst->ips_ipv6firewall_loopback_in != NULL) {
426 		if (net_unregister_event(ipst->ips_ipv6_net_data,
427 		    &ipst->ips_ip6_loopback_in_event) == 0)
428 			ipst->ips_ipv6firewall_loopback_in = NULL;
429 	}
430 
431 	if (ipst->ips_ipv6firewall_loopback_out != NULL) {
432 		if (net_unregister_event(ipst->ips_ipv6_net_data,
433 		    &ipst->ips_ip6_loopback_out_event) == 0)
434 			ipst->ips_ipv6firewall_loopback_out = NULL;
435 	}
436 
437 	if (ipst->ips_ipv6nicevents != NULL) {
438 		if (net_unregister_event(ipst->ips_ipv6_net_data,
439 		    &ipst->ips_ip6_nic_events) == 0)
440 			ipst->ips_ipv6nicevents = NULL;
441 	}
442 
443 	(void) net_unregister_family(ipst->ips_ipv6_net_data,
444 	    &ipst->ips_ipv6root);
445 }
446 
447 /*
448  * Determine the name of an IPv4 interface
449  */
450 static int
451 ip_getifname(phy_if_t phy_ifdata, char *buffer, const size_t buflen,
452     netstack_t *ns)
453 {
454 	return (ip_getifname_impl(phy_ifdata, buffer, buflen, B_FALSE,
455 	    ns->netstack_ip));
456 }
457 
458 /*
459  * Determine the name of an IPv6 interface
460  */
461 static int
462 ipv6_getifname(phy_if_t phy_ifdata, char *buffer, const size_t buflen,
463     netstack_t *ns)
464 {
465 	return (ip_getifname_impl(phy_ifdata, buffer, buflen, B_TRUE,
466 	    ns->netstack_ip));
467 }
468 
469 /*
470  * Shared implementation to determine the name of a given network interface
471  */
472 /* ARGSUSED */
473 static int
474 ip_getifname_impl(phy_if_t phy_ifdata,
475     char *buffer, const size_t buflen, boolean_t isv6, ip_stack_t *ipst)
476 {
477 	ill_t *ill;
478 
479 	ASSERT(buffer != NULL);
480 
481 	ill = ill_lookup_on_ifindex((uint_t)phy_ifdata, isv6, NULL, NULL,
482 	    NULL, NULL, ipst);
483 	if (ill == NULL)
484 		return (1);
485 
486 	if (ill->ill_name != NULL) {
487 		(void) strlcpy(buffer, ill->ill_name, buflen);
488 		ill_refrele(ill);
489 		return (0);
490 	} else {
491 		ill_refrele(ill);
492 		return (1);
493 	}
494 
495 }
496 
497 /*
498  * Determine the MTU of an IPv4 network interface
499  */
500 static int
501 ip_getmtu(phy_if_t phy_ifdata, lif_if_t ifdata, netstack_t *ns)
502 {
503 	ASSERT(ns != NULL);
504 	return (ip_getmtu_impl(phy_ifdata, ifdata, B_FALSE, ns->netstack_ip));
505 }
506 
507 /*
508  * Determine the MTU of an IPv6 network interface
509  */
510 static int
511 ipv6_getmtu(phy_if_t phy_ifdata, lif_if_t ifdata, netstack_t *ns)
512 {
513 	ASSERT(ns != NULL);
514 	return (ip_getmtu_impl(phy_ifdata, ifdata, B_TRUE, ns->netstack_ip));
515 }
516 
517 /*
518  * Shared implementation to determine the MTU of a network interface
519  */
520 /* ARGSUSED */
521 static int
522 ip_getmtu_impl(phy_if_t phy_ifdata, lif_if_t ifdata, boolean_t isv6,
523     ip_stack_t *ipst)
524 {
525 	lif_if_t ipifid;
526 	ipif_t *ipif;
527 	int mtu;
528 
529 	ipifid = UNMAP_IPIF_ID(ifdata);
530 
531 	ipif = ipif_getby_indexes((uint_t)phy_ifdata, (uint_t)ipifid,
532 	    isv6, ipst);
533 	if (ipif == NULL)
534 		return (0);
535 
536 	mtu = ipif->ipif_mtu;
537 	ipif_refrele(ipif);
538 
539 	if (mtu == 0) {
540 		ill_t *ill;
541 
542 		if ((ill = ill_lookup_on_ifindex((uint_t)phy_ifdata, isv6,
543 		    NULL, NULL, NULL, NULL, ipst)) == NULL) {
544 			return (0);
545 		}
546 		mtu = ill->ill_max_frag;
547 		ill_refrele(ill);
548 	}
549 
550 	return (mtu);
551 }
552 
553 /*
554  * Determine if path MTU discovery is enabled for IP
555  */
556 static int
557 ip_getpmtuenabled(netstack_t *ns)
558 {
559 	ASSERT(ns != NULL);
560 	return ((ns->netstack_ip)->ips_ip_path_mtu_discovery);
561 }
562 
563 /*
564  * Get next interface from the current list of IPv4 physical network interfaces
565  */
566 static phy_if_t
567 ip_phygetnext(phy_if_t phy_ifdata, netstack_t *ns)
568 {
569 	ASSERT(ns != NULL);
570 	return (ill_get_next_ifindex(phy_ifdata, B_FALSE, ns->netstack_ip));
571 }
572 
573 /*
574  * Get next interface from the current list of IPv6 physical network interfaces
575  */
576 static phy_if_t
577 ipv6_phygetnext(phy_if_t phy_ifdata, netstack_t *ns)
578 {
579 	ASSERT(ns != NULL);
580 	return (ill_get_next_ifindex(phy_ifdata, B_TRUE, ns->netstack_ip));
581 }
582 
583 /*
584  * Determine if a network interface name exists for IPv4
585  */
586 static phy_if_t
587 ip_phylookup(const char *name, netstack_t *ns)
588 {
589 	ASSERT(ns != NULL);
590 	return (ip_phylookup_impl(name, B_FALSE, ns->netstack_ip));
591 }
592 
593 /*
594  * Determine if a network interface name exists for IPv6
595  */
596 static phy_if_t
597 ipv6_phylookup(const char *name, netstack_t *ns)
598 {
599 	ASSERT(ns != NULL);
600 	return (ip_phylookup_impl(name, B_TRUE, ns->netstack_ip));
601 }
602 
603 /*
604  * Implement looking up an ill_t based on the name supplied and matching
605  * it up with either IPv4 or IPv6.  ill_get_ifindex_by_name() is not used
606  * because it does not match on the address family in addition to the name.
607  */
608 static phy_if_t
609 ip_phylookup_impl(const char *name, boolean_t isv6, ip_stack_t *ipst)
610 {
611 	phy_if_t phy;
612 	ill_t *ill;
613 
614 	ill = ill_lookup_on_name((char *)name, B_FALSE, isv6, NULL, NULL,
615 	    NULL, NULL, NULL, ipst);
616 
617 	if (ill == NULL)
618 		return (0);
619 
620 	phy = ill->ill_phyint->phyint_ifindex;
621 
622 	ill_refrele(ill);
623 
624 	return (phy);
625 }
626 
627 /*
628  * Get next interface from the current list of IPv4 logical network interfaces
629  */
630 static lif_if_t
631 ip_lifgetnext(phy_if_t phy_ifdata, lif_if_t ifdata, netstack_t *ns)
632 {
633 	ASSERT(ns != NULL);
634 	return (ip_lifgetnext_impl(phy_ifdata, ifdata, B_FALSE,
635 	    ns->netstack_ip));
636 }
637 
638 /*
639  * Get next interface from the current list of IPv6 logical network interfaces
640  */
641 static lif_if_t
642 ipv6_lifgetnext(phy_if_t phy_ifdata, lif_if_t ifdata, netstack_t *ns)
643 {
644 	ASSERT(ns != NULL);
645 	return (ip_lifgetnext_impl(phy_ifdata, ifdata, B_TRUE,
646 	    ns->netstack_ip));
647 }
648 
649 /*
650  * Shared implementation to get next interface from the current list of
651  * logical network interfaces
652  */
653 static lif_if_t
654 ip_lifgetnext_impl(phy_if_t phy_ifdata, lif_if_t ifdata, boolean_t isv6,
655     ip_stack_t *ipst)
656 {
657 	lif_if_t newidx, oldidx;
658 	boolean_t nextok;
659 	ipif_t *ipif;
660 	ill_t *ill;
661 
662 	ill = ill_lookup_on_ifindex(phy_ifdata, isv6, NULL, NULL,
663 	    NULL, NULL, ipst);
664 	if (ill == NULL)
665 		return (0);
666 
667 	if (ifdata != 0) {
668 		oldidx = UNMAP_IPIF_ID(ifdata);
669 		nextok = B_FALSE;
670 	} else {
671 		oldidx = 0;
672 		nextok = B_TRUE;
673 	}
674 
675 	mutex_enter(&ill->ill_lock);
676 	if (ill->ill_state_flags & ILL_CONDEMNED) {
677 		mutex_exit(&ill->ill_lock);
678 		ill_refrele(ill);
679 		return (0);
680 	}
681 
682 	/*
683 	 * It's safe to iterate the ill_ipif list when holding an ill_lock.
684 	 * And it's also safe to access ipif_id without ipif refhold.
685 	 * See ipif_get_id().
686 	 */
687 	for (ipif = ill->ill_ipif; ipif != NULL; ipif = ipif->ipif_next) {
688 		if (!IPIF_CAN_LOOKUP(ipif))
689 			continue;
690 		if (nextok) {
691 			ipif_refhold_locked(ipif);
692 			break;
693 		} else if (oldidx == ipif->ipif_id) {
694 			nextok = B_TRUE;
695 		}
696 	}
697 
698 	mutex_exit(&ill->ill_lock);
699 	ill_refrele(ill);
700 
701 	if (ipif == NULL)
702 		return (0);
703 
704 	newidx = ipif->ipif_id;
705 	ipif_refrele(ipif);
706 
707 	return (MAP_IPIF_ID(newidx));
708 }
709 
710 /*
711  * Inject an IPv4 packet to or from an interface
712  */
713 static int
714 ip_inject(inject_t style, net_inject_t *packet, netstack_t *ns)
715 {
716 	ASSERT(ns != NULL);
717 	return (ip_inject_impl(style, packet, B_FALSE, ns->netstack_ip));
718 }
719 
720 
721 /*
722  * Inject an IPv6 packet to or from an interface
723  */
724 static int
725 ipv6_inject(inject_t style, net_inject_t *packet, netstack_t *ns)
726 {
727 	ASSERT(ns != NULL);
728 	return (ip_inject_impl(style, packet, B_TRUE, ns->netstack_ip));
729 }
730 
731 /*
732  * Shared implementation to inject a packet to or from an interface
733  * Return value:
734  *   0: successful
735  *  -1: memory allocation failed
736  *   1: other errors
737  */
738 static int
739 ip_inject_impl(inject_t style, net_inject_t *packet, boolean_t isv6,
740     ip_stack_t *ipst)
741 {
742 	struct sockaddr_in6 *sin6;
743 	ddi_taskq_t *tq = NULL;
744 	void (* func)(void *);
745 	injection_t *inject;
746 	ip6_t *ip6h;
747 	ire_t *ire;
748 	mblk_t *mp;
749 
750 	ASSERT(packet != NULL);
751 	ASSERT(packet->ni_packet != NULL);
752 	ASSERT(packet->ni_packet->b_datap->db_type == M_DATA);
753 
754 	switch (style) {
755 	case NI_QUEUE_IN:
756 		inject = kmem_alloc(sizeof (*inject), KM_NOSLEEP);
757 		if (inject == NULL)
758 			return (-1);
759 		inject->inj_data = *packet;
760 		inject->inj_isv6 = isv6;
761 		/*
762 		 * deliver up into the kernel, immitating its reception by a
763 		 * network interface, add to list and schedule timeout
764 		 */
765 		func = ip_ni_queue_in_func;
766 		tq = eventq_queue_in;
767 		break;
768 
769 	case NI_QUEUE_OUT:
770 		inject = kmem_alloc(sizeof (*inject), KM_NOSLEEP);
771 		if (inject == NULL)
772 			return (-1);
773 		inject->inj_data = *packet;
774 		inject->inj_isv6 = isv6;
775 		/*
776 		 * deliver out of the kernel, as if it were being sent via a
777 		 * raw socket so that IPFilter will see it again, add to list
778 		 * and schedule timeout
779 		 */
780 		func = ip_ni_queue_out_func;
781 		tq = eventq_queue_out;
782 		break;
783 
784 	case NI_DIRECT_OUT:
785 		/*
786 		 * Note:
787 		 * For IPv4, the code path below will be greatly simplified
788 		 * with the delivery of surya - it will become a single
789 		 * function call to X.  A follow on project is aimed to
790 		 * provide similar functionality for IPv6.
791 		 */
792 		mp = packet->ni_packet;
793 
794 		if (!isv6) {
795 			struct sockaddr *sock;
796 
797 			sock = (struct sockaddr *)&packet->ni_addr;
798 			/*
799 			 * ipfil_sendpkt was provided by surya to ease the
800 			 * problems associated with sending out a packet.
801 			 * Currently this function only supports IPv4.
802 			 */
803 			switch (ipfil_sendpkt(sock, mp, packet->ni_physical,
804 			    netstackid_to_zoneid(
805 			    ipst->ips_netstack->netstack_stackid))) {
806 			case 0 :
807 			case EINPROGRESS:
808 				return (0);
809 			case ECOMM :
810 			case ENONET :
811 				return (1);
812 			default :
813 				return (1);
814 			}
815 			/* NOTREACHED */
816 
817 		}
818 
819 		ip6h = (ip6_t *)mp->b_rptr;
820 		sin6 = (struct sockaddr_in6 *)&packet->ni_addr;
821 		ASSERT(sin6->sin6_family == AF_INET6);
822 
823 		ire = ire_route_lookup_v6(&sin6->sin6_addr, 0, 0, 0,
824 		    NULL, NULL, ALL_ZONES, NULL,
825 		    MATCH_IRE_DSTONLY|MATCH_IRE_DEFAULT|MATCH_IRE_RECURSIVE,
826 		    ipst);
827 
828 		if (ire == NULL) {
829 			ip2dbg(("ip_inject: ire_cache_lookup failed\n"));
830 			freemsg(mp);
831 			return (1);
832 		}
833 
834 		if (ire->ire_stq == NULL) {
835 			/* Send to loopback destination. */
836 			if (ire->ire_rfq == NULL) {
837 				ip2dbg(("ip_inject: bad nexthop\n"));
838 				ire_refrele(ire);
839 				freemsg(mp);
840 				return (1);
841 			}
842 			ip_wput_local_v6(ire->ire_rfq,
843 			    ire->ire_ipif->ipif_ill, ip6h, mp, ire, 0);
844 			ire_refrele(ire);
845 			return (0);
846 		}
847 
848 		mp->b_queue = ire->ire_stq;
849 
850 		if (ire->ire_nce == NULL ||
851 		    ire->ire_nce->nce_fp_mp == NULL &&
852 		    ire->ire_nce->nce_res_mp == NULL) {
853 			ip_newroute_v6(ire->ire_stq, mp,
854 			    &sin6->sin6_addr, NULL, NULL, ALL_ZONES, ipst);
855 
856 			ire_refrele(ire);
857 			return (0);
858 		} else {
859 			/* prepend L2 header for IPv6 packets. */
860 			mblk_t *llmp;
861 
862 			/*
863 			 * Lock IREs, see 6420438
864 			 */
865 			mutex_enter(&ire->ire_lock);
866 			llmp = ire->ire_nce->nce_fp_mp ?
867 			    ire->ire_nce->nce_fp_mp :
868 			    ire->ire_nce->nce_res_mp;
869 
870 			if ((mp = dupb(llmp)) == NULL &&
871 			    (mp = copyb(llmp)) == NULL) {
872 				ip2dbg(("ip_inject: llhdr failed\n"));
873 				mutex_exit(&ire->ire_lock);
874 				ire_refrele(ire);
875 				freemsg(mp);
876 				return (1);
877 			}
878 			mutex_exit(&ire->ire_lock);
879 			linkb(mp, packet->ni_packet);
880 		}
881 
882 		mp->b_queue = ire->ire_stq;
883 
884 		break;
885 	default:
886 		freemsg(packet->ni_packet);
887 		return (1);
888 	}
889 
890 	if (tq) {
891 		inject->inj_ptr = ipst;
892 		if (ddi_taskq_dispatch(tq, func, (void *)inject,
893 		    DDI_SLEEP) == DDI_FAILURE) {
894 			ip2dbg(("ip_inject:  ddi_taskq_dispatch failed\n"));
895 			freemsg(packet->ni_packet);
896 			return (1);
897 		}
898 	} else {
899 		putnext(ire->ire_stq, mp);
900 		ire_refrele(ire);
901 	}
902 
903 	return (0);
904 }
905 
906 /*
907  * Find the interface used for traffic to a given IPv4 address
908  */
909 static phy_if_t
910 ip_routeto(struct sockaddr *address, netstack_t *ns)
911 {
912 	ASSERT(address != NULL);
913 	ASSERT(ns != NULL);
914 
915 	if (address->sa_family != AF_INET)
916 		return (0);
917 	return (ip_routeto_impl(address, ns->netstack_ip));
918 }
919 
920 /*
921  * Find the interface used for traffic to a given IPv6 address
922  */
923 static phy_if_t
924 ipv6_routeto(struct sockaddr *address, netstack_t *ns)
925 {
926 	ASSERT(address != NULL);
927 	ASSERT(ns != NULL);
928 
929 	if (address->sa_family != AF_INET6)
930 		return (0);
931 	return (ip_routeto_impl(address, ns->netstack_ip));
932 }
933 
934 
935 /*
936  * Find the interface used for traffic to an address
937  */
938 static phy_if_t
939 ip_routeto_impl(struct sockaddr *address, ip_stack_t *ipst)
940 {
941 	ire_t *ire;
942 	ill_t *ill;
943 	phy_if_t phy_if;
944 
945 	if (address->sa_family == AF_INET6) {
946 		struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)address;
947 		ire = ire_route_lookup_v6(&sin6->sin6_addr, NULL,
948 		    0, 0, NULL, NULL, ALL_ZONES, NULL,
949 		    MATCH_IRE_DSTONLY|MATCH_IRE_DEFAULT|MATCH_IRE_RECURSIVE,
950 		    ipst);
951 	} else {
952 		struct sockaddr_in *sin = (struct sockaddr_in *)address;
953 		ire = ire_route_lookup(sin->sin_addr.s_addr, 0,
954 		    0, 0, NULL, NULL, ALL_ZONES, NULL,
955 		    MATCH_IRE_DSTONLY|MATCH_IRE_DEFAULT|MATCH_IRE_RECURSIVE,
956 		    ipst);
957 	}
958 
959 	if (ire == NULL)
960 		return (0);
961 
962 	ill = ire_to_ill(ire);
963 	if (ill == NULL)
964 		return (0);
965 
966 	ASSERT(ill != NULL);
967 	phy_if = (phy_if_t)ill->ill_phyint->phyint_ifindex;
968 	ire_refrele(ire);
969 
970 	return (phy_if);
971 }
972 
973 /*
974  * Determine if checksumming is being used for the given packet.
975  *
976  * Return value:
977  *   NET_HCK_NONE: full checksum recalculation is required
978  *   NET_HCK_L3_FULL: full layer 3 checksum
979  *   NET_HCK_L4_FULL: full layer 4 checksum
980  *   NET_HCK_L4_PART: partial layer 4 checksum
981  */
982 static int
983 ip_ispartialchecksum(mblk_t *mp)
984 {
985 	int ret = 0;
986 
987 	ASSERT(mp != NULL);
988 
989 	if ((DB_CKSUMFLAGS(mp) & HCK_FULLCKSUM) != 0) {
990 		ret |= (int)NET_HCK_L4_FULL;
991 		if ((DB_CKSUMFLAGS(mp) & HCK_IPV4_HDRCKSUM) != 0)
992 			ret |= (int)NET_HCK_L3_FULL;
993 	}
994 	if ((DB_CKSUMFLAGS(mp) & HCK_PARTIALCKSUM) != 0) {
995 		ret |= (int)NET_HCK_L4_PART;
996 		if ((DB_CKSUMFLAGS(mp) & HCK_IPV4_HDRCKSUM) != 0)
997 			ret |= (int)NET_HCK_L3_FULL;
998 	}
999 
1000 	return (ret);
1001 }
1002 
1003 /*
1004  * Return true or false, indicating whether the network and transport
1005  * headers are correct.  Use the capabilities flags and flags set in the
1006  * dblk_t to determine whether or not the checksum is valid.
1007  *
1008  * Return:
1009  *   0: the checksum was incorrect
1010  *   1: the original checksum was correct
1011  */
1012 static int
1013 ip_isvalidchecksum(mblk_t *mp)
1014 {
1015 	unsigned char *wptr;
1016 	ipha_t *ipha = (ipha_t *)mp->b_rptr;
1017 	int hlen;
1018 	int ret;
1019 
1020 	ASSERT(mp != NULL);
1021 
1022 	if (dohwcksum &&
1023 	    DB_CKSUM16(mp) != 0xFFFF &&
1024 	    (DB_CKSUMFLAGS(mp) & HCK_FULLCKSUM) &&
1025 	    (DB_CKSUMFLAGS(mp) & HCK_FULLCKSUM_OK) &&
1026 	    (DB_CKSUMFLAGS(mp) & HCK_IPV4_HDRCKSUM))
1027 		return (1);
1028 
1029 	hlen = (ipha->ipha_version_and_hdr_length & 0x0F) << 2;
1030 
1031 	/*
1032 	 * Check that the mblk being passed in has enough data in it
1033 	 * before blindly checking ip_cksum.
1034 	 */
1035 	if (msgdsize(mp) < hlen)
1036 		return (0);
1037 
1038 	if (mp->b_wptr < mp->b_rptr + hlen) {
1039 		if (pullupmsg(mp, hlen) == 0)
1040 			return (0);
1041 		wptr = mp->b_wptr;
1042 	} else {
1043 		wptr = mp->b_wptr;
1044 		mp->b_wptr = mp->b_rptr + hlen;
1045 	}
1046 
1047 	if (ipha->ipha_hdr_checksum == ip_cksum(mp, 0, ipha->ipha_hdr_checksum))
1048 		ret = 1;
1049 	else
1050 		ret = 0;
1051 	mp->b_wptr = wptr;
1052 
1053 	return (ret);
1054 }
1055 
1056 /*
1057  * Unsupported with IPv6
1058  */
1059 /*ARGSUSED*/
1060 static int
1061 ipv6_isvalidchecksum(mblk_t *mp)
1062 {
1063 	return (-1);
1064 }
1065 
1066 /*
1067  * Determine the network addresses for an IPv4 interface
1068  */
1069 static int
1070 ip_getlifaddr(phy_if_t phy_ifdata, lif_if_t ifdata, size_t nelem,
1071 	net_ifaddr_t type[], void *storage, netstack_t *ns)
1072 {
1073 	ASSERT(ns != NULL);
1074 	return (ip_getlifaddr_impl(AF_INET, phy_ifdata, ifdata,
1075 	    nelem, type, storage, ns->netstack_ip));
1076 }
1077 
1078 /*
1079  * Determine the network addresses for an IPv6 interface
1080  */
1081 static int
1082 ipv6_getlifaddr(phy_if_t phy_ifdata, lif_if_t ifdata, size_t nelem,
1083 		net_ifaddr_t type[], void *storage, netstack_t *ns)
1084 {
1085 	ASSERT(ns != NULL);
1086 	return (ip_getlifaddr_impl(AF_INET6, phy_ifdata, ifdata,
1087 	    nelem, type, storage, ns->netstack_ip));
1088 }
1089 
1090 /*
1091  * Shared implementation to determine the network addresses for an interface
1092  */
1093 /* ARGSUSED */
1094 static int
1095 ip_getlifaddr_impl(sa_family_t family, phy_if_t phy_ifdata,
1096     lif_if_t ifdata, size_t nelem, net_ifaddr_t type[],
1097     struct sockaddr *storage, ip_stack_t *ipst)
1098 {
1099 	struct sockaddr_in6 *sin6;
1100 	struct sockaddr_in *sin;
1101 	lif_if_t ipifid;
1102 	ipif_t *ipif;
1103 	int i;
1104 
1105 	ASSERT(type != NULL);
1106 	ASSERT(storage != NULL);
1107 
1108 	ipifid = UNMAP_IPIF_ID(ifdata);
1109 
1110 	if (family == AF_INET) {
1111 		if ((ipif = ipif_getby_indexes((uint_t)phy_ifdata,
1112 		    (uint_t)ipifid, B_FALSE, ipst)) == NULL)
1113 			return (1);
1114 
1115 		sin = (struct sockaddr_in *)storage;
1116 		for (i = 0; i < nelem; i++, sin++) {
1117 			if (ip_getifaddr_type(AF_INET, ipif, type[i],
1118 			    &sin->sin_addr) < 0) {
1119 				ip2dbg(("ip_getlifaddr_impl failed type %d\n",
1120 				    type[i]));
1121 				ipif_refrele(ipif);
1122 				return (1);
1123 			}
1124 		}
1125 	} else {
1126 		if ((ipif = ipif_getby_indexes((uint_t)phy_ifdata,
1127 		    (uint_t)ipifid, B_TRUE, ipst)) == NULL)
1128 			return (1);
1129 
1130 		sin6 = (struct sockaddr_in6 *)storage;
1131 		for (i = 0; i < nelem; i++, sin6++) {
1132 			if (ip_getifaddr_type(AF_INET6, ipif, type[i],
1133 			    &sin6->sin6_addr) < 0) {
1134 				ip2dbg(("ip_getlifaddr_impl failed type %d\n",
1135 				    type[i]));
1136 				ipif_refrele(ipif);
1137 				return (1);
1138 			}
1139 		}
1140 	}
1141 	ipif_refrele(ipif);
1142 	return (0);
1143 }
1144 
1145 /*
1146  * ip_getlifaddr private function
1147  */
1148 static int
1149 ip_getifaddr_type(sa_family_t family, ipif_t *ill_ipif,
1150     lif_if_t type, void *storage)
1151 {
1152 	void *src_addr;
1153 	int mem_size;
1154 
1155 	ASSERT(ill_ipif != NULL);
1156 	ASSERT(storage != NULL);
1157 
1158 	if (family == AF_INET) {
1159 		mem_size = sizeof (struct in_addr);
1160 
1161 		switch (type) {
1162 		case NA_ADDRESS:
1163 			src_addr = &(ill_ipif->ipif_lcl_addr);
1164 			break;
1165 		case NA_PEER:
1166 			src_addr = &(ill_ipif->ipif_pp_dst_addr);
1167 			break;
1168 		case NA_BROADCAST:
1169 			src_addr = &(ill_ipif->ipif_brd_addr);
1170 			break;
1171 		case NA_NETMASK:
1172 			src_addr = &(ill_ipif->ipif_net_mask);
1173 			break;
1174 		default:
1175 			return (-1);
1176 			/*NOTREACHED*/
1177 		}
1178 	} else {
1179 		mem_size = sizeof (struct in6_addr);
1180 
1181 		switch (type) {
1182 		case NA_ADDRESS:
1183 			src_addr = &(ill_ipif->ipif_v6lcl_addr);
1184 			break;
1185 		case NA_PEER:
1186 			src_addr = &(ill_ipif->ipif_v6pp_dst_addr);
1187 			break;
1188 		case NA_BROADCAST:
1189 			src_addr = &(ill_ipif->ipif_v6brd_addr);
1190 			break;
1191 		case NA_NETMASK:
1192 			src_addr = &(ill_ipif->ipif_v6net_mask);
1193 			break;
1194 		default:
1195 			return (-1);
1196 			/*NOTREACHED*/
1197 		}
1198 	}
1199 
1200 	(void) memcpy(storage, src_addr, mem_size);
1201 	return (1);
1202 }
1203 
1204 /*
1205  * Deliver packet up into the kernel, immitating its reception by a
1206  * network interface.
1207  */
1208 static void
1209 ip_ni_queue_in_func(void *inject)
1210 {
1211 	ip_ni_queue_func_impl(inject, B_FALSE);
1212 }
1213 
1214 /*
1215  * Deliver out of the kernel, as if it were being sent via a
1216  * raw socket so that IPFilter will see it again.
1217  */
1218 static void
1219 ip_ni_queue_out_func(void *inject)
1220 {
1221 	ip_ni_queue_func_impl(inject, B_TRUE);
1222 }
1223 
1224 /*
1225  * Shared implementation for inject via ip_output and ip_input
1226  */
1227 static void
1228 ip_ni_queue_func_impl(injection_t *inject,  boolean_t out)
1229 {
1230 	net_inject_t *packet;
1231 	conn_t *conn;
1232 	ill_t *ill;
1233 	ip_stack_t *ipst = (ip_stack_t *)inject->inj_ptr;
1234 
1235 	ASSERT(inject != NULL);
1236 	packet = &inject->inj_data;
1237 	ASSERT(packet->ni_packet != NULL);
1238 
1239 	if ((ill = ill_lookup_on_ifindex((uint_t)packet->ni_physical,
1240 	    B_FALSE, NULL, NULL, NULL, NULL, ipst)) == NULL) {
1241 		kmem_free(inject, sizeof (*inject));
1242 		return;
1243 	}
1244 
1245 	if (out == 0) {
1246 		if (inject->inj_isv6) {
1247 			ip_rput_v6(ill->ill_rq, packet->ni_packet);
1248 		} else {
1249 			ip_input(ill, NULL, packet->ni_packet, 0);
1250 		}
1251 		kmem_free(inject, sizeof (*inject));
1252 		ill_refrele(ill);
1253 		return;
1254 	}
1255 
1256 	/*
1257 	 * Even though ipcl_conn_create requests that it be passed
1258 	 * a different value for "TCP", in this case there may not
1259 	 * be a TCP connection backing the packet and more than
1260 	 * likely, non-TCP packets will go here too.
1261 	 */
1262 	conn = ipcl_conn_create(IPCL_IPCCONN, KM_NOSLEEP, ipst->ips_netstack);
1263 	if (conn != NULL) {
1264 		if (inject->inj_isv6) {
1265 			conn->conn_flags |= IPCL_ISV6;
1266 			conn->conn_af_isv6 = B_TRUE;
1267 			conn->conn_src_preferences = IPV6_PREFER_SRC_DEFAULT;
1268 			conn->conn_multicast_loop = IP_DEFAULT_MULTICAST_LOOP;
1269 			ip_output_v6(conn, packet->ni_packet, ill->ill_wq,
1270 				IP_WPUT);
1271 		} else {
1272 			conn->conn_af_isv6 = B_FALSE;
1273 			conn->conn_pkt_isv6 = B_FALSE;
1274 			conn->conn_multicast_loop = IP_DEFAULT_MULTICAST_LOOP;
1275 			ip_output(conn, packet->ni_packet, ill->ill_wq,
1276 				IP_WPUT);
1277 		}
1278 
1279 		CONN_DEC_REF(conn);
1280 	}
1281 
1282 	kmem_free(inject, sizeof (*inject));
1283 	ill_refrele(ill);
1284 }
1285 
1286 /*
1287  * taskq function for nic events.
1288  */
1289 void
1290 ip_ne_queue_func(void *arg)
1291 {
1292 	hook_event_int_t *hr;
1293 	hook_nic_event_t *info = (hook_nic_event_t *)arg;
1294 	netstack_t *ns = info->hne_family->netd_netstack;
1295 	ip_stack_t *ipst = ns->netstack_ip;
1296 
1297 	hr = (info->hne_family == ipst->ips_ipv6_net_data) ?
1298 	    ipst->ips_ipv6nicevents : ipst->ips_ipv4nicevents;
1299 	(void) hook_run(hr, (hook_data_t)info, ns);
1300 
1301 	if (info->hne_data != NULL)
1302 		kmem_free(info->hne_data, info->hne_datalen);
1303 	kmem_free(arg, sizeof (hook_nic_event_t));
1304 }
1305