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.
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.
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]
22 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 #include <sys/param.h>
27 #include <sys/types.h>
28 #include <sys/systm.h>
29 #include <sys/stream.h>
30 #include <sys/strsubr.h>
31 #include <sys/pattr.h>
33 #include <sys/atomic.h>
34 #include <sys/sunddi.h>
35 #include <sys/socket.h>
38 #include <sys/cmn_err.h>
40 #include <netinet/in.h>
41 #include <inet/ipsec_impl.h>
42 #include <inet/common.h>
43 #include <inet/mib2.h>
46 #include <inet/ip_if.h>
47 #include <inet/ip_ire.h>
48 #include <inet/ip_impl.h>
49 #include <inet/ip_ndp.h>
50 #include <inet/ipclassifier.h>
51 #include <inet/ipp_common.h>
52 #include <inet/ip_ftable.h>
55 * IPv4 netinfo entry point declarations.
57 static int ip_getifname(net_handle_t
, phy_if_t
, char *,
59 static int ip_getmtu(net_handle_t
, phy_if_t
, lif_if_t
);
60 static int ip_getpmtuenabled(net_handle_t
);
61 static int ip_getlifaddr(net_handle_t
, phy_if_t
, lif_if_t
,
62 size_t, net_ifaddr_t
[], void *);
63 static int ip_getlifzone(net_handle_t
, phy_if_t
, lif_if_t
,
65 static int ip_getlifflags(net_handle_t
, phy_if_t
, lif_if_t
,
67 static phy_if_t
ip_phygetnext(net_handle_t
, phy_if_t
);
68 static phy_if_t
ip_phylookup(net_handle_t
, const char *);
69 static lif_if_t
ip_lifgetnext(net_handle_t
, phy_if_t
, lif_if_t
);
70 static int ip_inject(net_handle_t
, inject_t
, net_inject_t
*);
71 static phy_if_t
ip_routeto(net_handle_t
, struct sockaddr
*,
73 static int ip_ispartialchecksum(net_handle_t
, mblk_t
*);
74 static int ip_isvalidchecksum(net_handle_t
, mblk_t
*);
76 static int ipv6_getifname(net_handle_t
, phy_if_t
, char *,
78 static int ipv6_getmtu(net_handle_t
, phy_if_t
, lif_if_t
);
79 static int ipv6_getlifaddr(net_handle_t
, phy_if_t
, lif_if_t
,
80 size_t, net_ifaddr_t
[], void *);
81 static int ipv6_getlifzone(net_handle_t
, phy_if_t
, lif_if_t
,
83 static int ipv6_getlifflags(net_handle_t
, phy_if_t
, lif_if_t
,
85 static phy_if_t
ipv6_phygetnext(net_handle_t
, phy_if_t
);
86 static phy_if_t
ipv6_phylookup(net_handle_t
, const char *);
87 static lif_if_t
ipv6_lifgetnext(net_handle_t
, phy_if_t
, lif_if_t
);
88 static int ipv6_inject(net_handle_t
, inject_t
, net_inject_t
*);
89 static phy_if_t
ipv6_routeto(net_handle_t
, struct sockaddr
*,
91 static int ipv6_isvalidchecksum(net_handle_t
, mblk_t
*);
93 static int net_no_getmtu(net_handle_t
, phy_if_t
, lif_if_t
);
94 static int net_no_getpmtuenabled(net_handle_t
);
95 static lif_if_t
net_no_lifgetnext(net_handle_t
, phy_if_t
, lif_if_t
);
96 static int net_no_inject(net_handle_t
, inject_t
, net_inject_t
*);
97 static phy_if_t
net_no_routeto(net_handle_t
, struct sockaddr
*,
99 static int net_no_ispartialchecksum(net_handle_t
, mblk_t
*);
100 static int net_no_getlifaddr(net_handle_t
, phy_if_t
, lif_if_t
,
101 size_t, net_ifaddr_t
[], void *);
102 static int net_no_getlifzone(net_handle_t
, phy_if_t
, lif_if_t
,
104 static int net_no_getlifflags(net_handle_t
, phy_if_t
, lif_if_t
,
107 /* Netinfo private functions */
108 static int ip_getifname_impl(phy_if_t
, char *,
109 const size_t, boolean_t
, ip_stack_t
*);
110 static int ip_getmtu_impl(phy_if_t
, lif_if_t
, boolean_t
,
112 static phy_if_t
ip_phylookup_impl(const char *, boolean_t
,
114 static lif_if_t
ip_lifgetnext_impl(phy_if_t
, lif_if_t
, boolean_t
,
116 static int ip_inject_impl(inject_t
, net_inject_t
*, boolean_t
,
118 static int ip_getifaddr_type(sa_family_t
, ipif_t
*, lif_if_t
,
120 static phy_if_t
ip_routeto_impl(struct sockaddr
*, struct sockaddr
*,
122 static int ip_getlifaddr_impl(sa_family_t
, phy_if_t
, lif_if_t
,
123 size_t, net_ifaddr_t
[], struct sockaddr
*,
125 static void ip_ni_queue_in_func(void *);
126 static void ip_ni_queue_out_func(void *);
127 static void ip_ni_queue_func_impl(injection_t
*, boolean_t
);
129 static net_protocol_t ipv4info
= {
143 ip_ispartialchecksum
,
148 static net_protocol_t ipv6info
= {
162 ip_ispartialchecksum
,
166 static net_protocol_t arp_netinfo
= {
171 net_no_getpmtuenabled
,
180 net_no_ispartialchecksum
,
185 * The taskq eventq_queue_in is used to process the upside inject messages.
186 * The taskq eventq_queue_out is used to process the downside inject messages.
187 * The taskq eventq_queue_nic is used to process the nic event messages.
189 static ddi_taskq_t
*eventq_queue_in
= NULL
;
190 static ddi_taskq_t
*eventq_queue_out
= NULL
;
191 ddi_taskq_t
*eventq_queue_nic
= NULL
;
194 * Initialize queues for inject.
199 if (eventq_queue_out
== NULL
) {
200 eventq_queue_out
= ddi_taskq_create(NULL
,
201 "IP_INJECT_QUEUE_OUT", 1, TASKQ_DEFAULTPRI
, 0);
203 if (eventq_queue_out
== NULL
)
204 cmn_err(CE_NOTE
, "ipv4_net_init: "
205 "ddi_taskq_create failed for IP_INJECT_QUEUE_OUT");
208 if (eventq_queue_in
== NULL
) {
209 eventq_queue_in
= ddi_taskq_create(NULL
,
210 "IP_INJECT_QUEUE_IN", 1, TASKQ_DEFAULTPRI
, 0);
212 if (eventq_queue_in
== NULL
)
213 cmn_err(CE_NOTE
, "ipv4_net_init: "
214 "ddi_taskq_create failed for IP_INJECT_QUEUE_IN");
217 if (eventq_queue_nic
== NULL
) {
218 eventq_queue_nic
= ddi_taskq_create(NULL
,
219 "IP_NIC_EVENT_QUEUE", 1, TASKQ_DEFAULTPRI
, 0);
221 if (eventq_queue_nic
== NULL
)
222 cmn_err(CE_NOTE
, "ipv4_net_init: "
223 "ddi_taskq_create failed for IP_NIC_EVENT_QUEUE");
228 * Destroy inject queues
233 if (eventq_queue_nic
!= NULL
) {
234 ddi_taskq_destroy(eventq_queue_nic
);
235 eventq_queue_nic
= NULL
;
238 if (eventq_queue_in
!= NULL
) {
239 ddi_taskq_destroy(eventq_queue_in
);
240 eventq_queue_in
= NULL
;
243 if (eventq_queue_out
!= NULL
) {
244 ddi_taskq_destroy(eventq_queue_out
);
245 eventq_queue_out
= NULL
;
250 * Register IPv4 and IPv6 netinfo functions and initialize queues for inject.
253 ip_net_init(ip_stack_t
*ipst
, netstack_t
*ns
)
257 id
= net_getnetidbynetstackid(ns
->netstack_stackid
);
260 ipst
->ips_ipv4_net_data
= net_protocol_register(id
, &ipv4info
);
261 ASSERT(ipst
->ips_ipv4_net_data
!= NULL
);
263 ipst
->ips_ipv6_net_data
= net_protocol_register(id
, &ipv6info
);
264 ASSERT(ipst
->ips_ipv6_net_data
!= NULL
);
266 ipst
->ips_arp_net_data
= net_protocol_register(id
, &arp_netinfo
);
267 ASSERT(ipst
->ips_ipv6_net_data
!= NULL
);
272 * Unregister IPv4 and IPv6 functions.
275 ip_net_destroy(ip_stack_t
*ipst
)
277 if (ipst
->ips_ipv4_net_data
!= NULL
) {
278 if (net_protocol_unregister(ipst
->ips_ipv4_net_data
) == 0)
279 ipst
->ips_ipv4_net_data
= NULL
;
282 if (ipst
->ips_ipv6_net_data
!= NULL
) {
283 if (net_protocol_unregister(ipst
->ips_ipv6_net_data
) == 0)
284 ipst
->ips_ipv6_net_data
= NULL
;
287 if (ipst
->ips_arp_net_data
!= NULL
) {
288 if (net_protocol_unregister(ipst
->ips_arp_net_data
) == 0)
289 ipst
->ips_arp_net_data
= NULL
;
294 * Initialize IPv4 hooks family the event
297 ipv4_hook_init(ip_stack_t
*ipst
)
299 HOOK_FAMILY_INIT(&ipst
->ips_ipv4root
, Hn_IPV4
);
300 if (net_family_register(ipst
->ips_ipv4_net_data
, &ipst
->ips_ipv4root
)
302 cmn_err(CE_NOTE
, "ipv4_hook_init: "
303 "net_family_register failed for ipv4");
306 HOOK_EVENT_INIT(&ipst
->ips_ip4_physical_in_event
, NH_PHYSICAL_IN
);
307 ipst
->ips_ipv4firewall_physical_in
= net_event_register(
308 ipst
->ips_ipv4_net_data
, &ipst
->ips_ip4_physical_in_event
);
309 if (ipst
->ips_ipv4firewall_physical_in
== NULL
) {
310 cmn_err(CE_NOTE
, "ipv4_hook_init: "
311 "net_event_register failed for ipv4/physical_in");
314 HOOK_EVENT_INIT(&ipst
->ips_ip4_physical_out_event
, NH_PHYSICAL_OUT
);
315 ipst
->ips_ipv4firewall_physical_out
= net_event_register(
316 ipst
->ips_ipv4_net_data
, &ipst
->ips_ip4_physical_out_event
);
317 if (ipst
->ips_ipv4firewall_physical_out
== NULL
) {
318 cmn_err(CE_NOTE
, "ipv4_hook_init: "
319 "net_event_register failed for ipv4/physical_out");
322 HOOK_EVENT_INIT(&ipst
->ips_ip4_forwarding_event
, NH_FORWARDING
);
323 ipst
->ips_ipv4firewall_forwarding
= net_event_register(
324 ipst
->ips_ipv4_net_data
, &ipst
->ips_ip4_forwarding_event
);
325 if (ipst
->ips_ipv4firewall_forwarding
== NULL
) {
326 cmn_err(CE_NOTE
, "ipv4_hook_init: "
327 "net_event_register failed for ipv4/forwarding");
330 HOOK_EVENT_INIT(&ipst
->ips_ip4_loopback_in_event
, NH_LOOPBACK_IN
);
331 ipst
->ips_ipv4firewall_loopback_in
= net_event_register(
332 ipst
->ips_ipv4_net_data
, &ipst
->ips_ip4_loopback_in_event
);
333 if (ipst
->ips_ipv4firewall_loopback_in
== NULL
) {
334 cmn_err(CE_NOTE
, "ipv4_hook_init: "
335 "net_event_register failed for ipv4/loopback_in");
338 HOOK_EVENT_INIT(&ipst
->ips_ip4_loopback_out_event
, NH_LOOPBACK_OUT
);
339 ipst
->ips_ipv4firewall_loopback_out
= net_event_register(
340 ipst
->ips_ipv4_net_data
, &ipst
->ips_ip4_loopback_out_event
);
341 if (ipst
->ips_ipv4firewall_loopback_out
== NULL
) {
342 cmn_err(CE_NOTE
, "ipv4_hook_init: "
343 "net_event_register failed for ipv4/loopback_out");
346 HOOK_EVENT_INIT(&ipst
->ips_ip4_nic_events
, NH_NIC_EVENTS
);
347 ipst
->ips_ip4_nic_events
.he_flags
= HOOK_RDONLY
;
348 ipst
->ips_ipv4nicevents
= net_event_register(
349 ipst
->ips_ipv4_net_data
, &ipst
->ips_ip4_nic_events
);
350 if (ipst
->ips_ipv4nicevents
== NULL
) {
351 cmn_err(CE_NOTE
, "ipv4_hook_init: "
352 "net_event_register failed for ipv4/nic_events");
355 HOOK_EVENT_INIT(&ipst
->ips_ip4_observe
, NH_OBSERVE
);
356 ipst
->ips_ip4_observe
.he_flags
= HOOK_RDONLY
;
357 ipst
->ips_ipv4observing
= net_event_register(
358 ipst
->ips_ipv4_net_data
, &ipst
->ips_ip4_observe
);
359 if (ipst
->ips_ipv4observing
== NULL
) {
360 cmn_err(CE_NOTE
, "ipv4_hook_init: "
361 "net_event_register failed for ipv4/observe");
367 ipv4_hook_shutdown(ip_stack_t
*ipst
)
369 if (ipst
->ips_ipv4firewall_forwarding
!= NULL
) {
370 (void) net_event_shutdown(ipst
->ips_ipv4_net_data
,
371 &ipst
->ips_ip4_forwarding_event
);
374 if (ipst
->ips_ipv4firewall_physical_in
!= NULL
) {
375 (void) net_event_shutdown(ipst
->ips_ipv4_net_data
,
376 &ipst
->ips_ip4_physical_in_event
);
379 if (ipst
->ips_ipv4firewall_physical_out
!= NULL
) {
380 (void) net_event_shutdown(ipst
->ips_ipv4_net_data
,
381 &ipst
->ips_ip4_physical_out_event
);
384 if (ipst
->ips_ipv4firewall_loopback_in
!= NULL
) {
385 (void) net_event_shutdown(ipst
->ips_ipv4_net_data
,
386 &ipst
->ips_ip4_loopback_in_event
);
389 if (ipst
->ips_ipv4firewall_loopback_out
!= NULL
) {
390 (void) net_event_shutdown(ipst
->ips_ipv4_net_data
,
391 &ipst
->ips_ip4_loopback_out_event
);
394 if (ipst
->ips_ipv4nicevents
!= NULL
) {
395 (void) net_event_shutdown(ipst
->ips_ipv4_net_data
,
396 &ipst
->ips_ip4_nic_events
);
399 if (ipst
->ips_ipv4observing
!= NULL
) {
400 (void) net_event_shutdown(ipst
->ips_ipv4_net_data
,
401 &ipst
->ips_ip4_observe
);
404 (void) net_family_shutdown(ipst
->ips_ipv4_net_data
,
405 &ipst
->ips_ipv4root
);
409 ipv4_hook_destroy(ip_stack_t
*ipst
)
411 if (ipst
->ips_ipv4firewall_forwarding
!= NULL
) {
412 if (net_event_unregister(ipst
->ips_ipv4_net_data
,
413 &ipst
->ips_ip4_forwarding_event
) == 0)
414 ipst
->ips_ipv4firewall_forwarding
= NULL
;
417 if (ipst
->ips_ipv4firewall_physical_in
!= NULL
) {
418 if (net_event_unregister(ipst
->ips_ipv4_net_data
,
419 &ipst
->ips_ip4_physical_in_event
) == 0)
420 ipst
->ips_ipv4firewall_physical_in
= NULL
;
423 if (ipst
->ips_ipv4firewall_physical_out
!= NULL
) {
424 if (net_event_unregister(ipst
->ips_ipv4_net_data
,
425 &ipst
->ips_ip4_physical_out_event
) == 0)
426 ipst
->ips_ipv4firewall_physical_out
= NULL
;
429 if (ipst
->ips_ipv4firewall_loopback_in
!= NULL
) {
430 if (net_event_unregister(ipst
->ips_ipv4_net_data
,
431 &ipst
->ips_ip4_loopback_in_event
) == 0)
432 ipst
->ips_ipv4firewall_loopback_in
= NULL
;
435 if (ipst
->ips_ipv4firewall_loopback_out
!= NULL
) {
436 if (net_event_unregister(ipst
->ips_ipv4_net_data
,
437 &ipst
->ips_ip4_loopback_out_event
) == 0)
438 ipst
->ips_ipv4firewall_loopback_out
= NULL
;
441 if (ipst
->ips_ipv4nicevents
!= NULL
) {
442 if (net_event_unregister(ipst
->ips_ipv4_net_data
,
443 &ipst
->ips_ip4_nic_events
) == 0)
444 ipst
->ips_ipv4nicevents
= NULL
;
447 if (ipst
->ips_ipv4observing
!= NULL
) {
448 if (net_event_unregister(ipst
->ips_ipv4_net_data
,
449 &ipst
->ips_ip4_observe
) == 0)
450 ipst
->ips_ipv4observing
= NULL
;
453 (void) net_family_unregister(ipst
->ips_ipv4_net_data
,
454 &ipst
->ips_ipv4root
);
458 * Initialize IPv6 hooks family and event
461 ipv6_hook_init(ip_stack_t
*ipst
)
464 HOOK_FAMILY_INIT(&ipst
->ips_ipv6root
, Hn_IPV6
);
465 if (net_family_register(ipst
->ips_ipv6_net_data
, &ipst
->ips_ipv6root
)
467 cmn_err(CE_NOTE
, "ipv6_hook_init: "
468 "net_family_register failed for ipv6");
471 HOOK_EVENT_INIT(&ipst
->ips_ip6_physical_in_event
, NH_PHYSICAL_IN
);
472 ipst
->ips_ipv6firewall_physical_in
= net_event_register(
473 ipst
->ips_ipv6_net_data
, &ipst
->ips_ip6_physical_in_event
);
474 if (ipst
->ips_ipv6firewall_physical_in
== NULL
) {
475 cmn_err(CE_NOTE
, "ipv6_hook_init: "
476 "net_event_register failed for ipv6/physical_in");
479 HOOK_EVENT_INIT(&ipst
->ips_ip6_physical_out_event
, NH_PHYSICAL_OUT
);
480 ipst
->ips_ipv6firewall_physical_out
= net_event_register(
481 ipst
->ips_ipv6_net_data
, &ipst
->ips_ip6_physical_out_event
);
482 if (ipst
->ips_ipv6firewall_physical_out
== NULL
) {
483 cmn_err(CE_NOTE
, "ipv6_hook_init: "
484 "net_event_register failed for ipv6/physical_out");
487 HOOK_EVENT_INIT(&ipst
->ips_ip6_forwarding_event
, NH_FORWARDING
);
488 ipst
->ips_ipv6firewall_forwarding
= net_event_register(
489 ipst
->ips_ipv6_net_data
, &ipst
->ips_ip6_forwarding_event
);
490 if (ipst
->ips_ipv6firewall_forwarding
== NULL
) {
491 cmn_err(CE_NOTE
, "ipv6_hook_init: "
492 "net_event_register failed for ipv6/forwarding");
495 HOOK_EVENT_INIT(&ipst
->ips_ip6_loopback_in_event
, NH_LOOPBACK_IN
);
496 ipst
->ips_ipv6firewall_loopback_in
= net_event_register(
497 ipst
->ips_ipv6_net_data
, &ipst
->ips_ip6_loopback_in_event
);
498 if (ipst
->ips_ipv6firewall_loopback_in
== NULL
) {
499 cmn_err(CE_NOTE
, "ipv6_hook_init: "
500 "net_event_register failed for ipv6/loopback_in");
503 HOOK_EVENT_INIT(&ipst
->ips_ip6_loopback_out_event
, NH_LOOPBACK_OUT
);
504 ipst
->ips_ipv6firewall_loopback_out
= net_event_register(
505 ipst
->ips_ipv6_net_data
, &ipst
->ips_ip6_loopback_out_event
);
506 if (ipst
->ips_ipv6firewall_loopback_out
== NULL
) {
507 cmn_err(CE_NOTE
, "ipv6_hook_init: "
508 "net_event_register failed for ipv6/loopback_out");
511 HOOK_EVENT_INIT(&ipst
->ips_ip6_nic_events
, NH_NIC_EVENTS
);
512 ipst
->ips_ip6_nic_events
.he_flags
= HOOK_RDONLY
;
513 ipst
->ips_ipv6nicevents
= net_event_register(
514 ipst
->ips_ipv6_net_data
, &ipst
->ips_ip6_nic_events
);
515 if (ipst
->ips_ipv6nicevents
== NULL
) {
516 cmn_err(CE_NOTE
, "ipv6_hook_init: "
517 "net_event_register failed for ipv6/nic_events");
520 HOOK_EVENT_INIT(&ipst
->ips_ip6_observe
, NH_OBSERVE
);
521 ipst
->ips_ip6_observe
.he_flags
= HOOK_RDONLY
;
522 ipst
->ips_ipv6observing
= net_event_register(
523 ipst
->ips_ipv6_net_data
, &ipst
->ips_ip6_observe
);
524 if (ipst
->ips_ipv6observing
== NULL
) {
525 cmn_err(CE_NOTE
, "ipv6_hook_init: "
526 "net_event_register failed for ipv6/observe");
531 ipv6_hook_shutdown(ip_stack_t
*ipst
)
533 if (ipst
->ips_ipv6firewall_forwarding
!= NULL
) {
534 (void) net_event_shutdown(ipst
->ips_ipv6_net_data
,
535 &ipst
->ips_ip6_forwarding_event
);
538 if (ipst
->ips_ipv6firewall_physical_in
!= NULL
) {
539 (void) net_event_shutdown(ipst
->ips_ipv6_net_data
,
540 &ipst
->ips_ip6_physical_in_event
);
543 if (ipst
->ips_ipv6firewall_physical_out
!= NULL
) {
544 (void) net_event_shutdown(ipst
->ips_ipv6_net_data
,
545 &ipst
->ips_ip6_physical_out_event
);
548 if (ipst
->ips_ipv6firewall_loopback_in
!= NULL
) {
549 (void) net_event_shutdown(ipst
->ips_ipv6_net_data
,
550 &ipst
->ips_ip6_loopback_in_event
);
553 if (ipst
->ips_ipv6firewall_loopback_out
!= NULL
) {
554 (void) net_event_shutdown(ipst
->ips_ipv6_net_data
,
555 &ipst
->ips_ip6_loopback_out_event
);
558 if (ipst
->ips_ipv6nicevents
!= NULL
) {
559 (void) net_event_shutdown(ipst
->ips_ipv6_net_data
,
560 &ipst
->ips_ip6_nic_events
);
563 if (ipst
->ips_ipv6observing
!= NULL
) {
564 (void) net_event_shutdown(ipst
->ips_ipv6_net_data
,
565 &ipst
->ips_ip6_observe
);
568 (void) net_family_shutdown(ipst
->ips_ipv6_net_data
,
569 &ipst
->ips_ipv6root
);
573 ipv6_hook_destroy(ip_stack_t
*ipst
)
575 if (ipst
->ips_ipv6firewall_forwarding
!= NULL
) {
576 if (net_event_unregister(ipst
->ips_ipv6_net_data
,
577 &ipst
->ips_ip6_forwarding_event
) == 0)
578 ipst
->ips_ipv6firewall_forwarding
= NULL
;
581 if (ipst
->ips_ipv6firewall_physical_in
!= NULL
) {
582 if (net_event_unregister(ipst
->ips_ipv6_net_data
,
583 &ipst
->ips_ip6_physical_in_event
) == 0)
584 ipst
->ips_ipv6firewall_physical_in
= NULL
;
587 if (ipst
->ips_ipv6firewall_physical_out
!= NULL
) {
588 if (net_event_unregister(ipst
->ips_ipv6_net_data
,
589 &ipst
->ips_ip6_physical_out_event
) == 0)
590 ipst
->ips_ipv6firewall_physical_out
= NULL
;
593 if (ipst
->ips_ipv6firewall_loopback_in
!= NULL
) {
594 if (net_event_unregister(ipst
->ips_ipv6_net_data
,
595 &ipst
->ips_ip6_loopback_in_event
) == 0)
596 ipst
->ips_ipv6firewall_loopback_in
= NULL
;
599 if (ipst
->ips_ipv6firewall_loopback_out
!= NULL
) {
600 if (net_event_unregister(ipst
->ips_ipv6_net_data
,
601 &ipst
->ips_ip6_loopback_out_event
) == 0)
602 ipst
->ips_ipv6firewall_loopback_out
= NULL
;
605 if (ipst
->ips_ipv6nicevents
!= NULL
) {
606 if (net_event_unregister(ipst
->ips_ipv6_net_data
,
607 &ipst
->ips_ip6_nic_events
) == 0)
608 ipst
->ips_ipv6nicevents
= NULL
;
611 if (ipst
->ips_ipv6observing
!= NULL
) {
612 if (net_event_unregister(ipst
->ips_ipv6_net_data
,
613 &ipst
->ips_ip6_observe
) == 0)
614 ipst
->ips_ipv6observing
= NULL
;
617 (void) net_family_unregister(ipst
->ips_ipv6_net_data
,
618 &ipst
->ips_ipv6root
);
622 * Determine the name of an IPv4 interface
625 ip_getifname(net_handle_t neti
, phy_if_t phy_ifdata
, char *buffer
,
628 return (ip_getifname_impl(phy_ifdata
, buffer
, buflen
, B_FALSE
,
629 neti
->netd_stack
->nts_netstack
->netstack_ip
));
633 * Determine the name of an IPv6 interface
636 ipv6_getifname(net_handle_t neti
, phy_if_t phy_ifdata
, char *buffer
,
639 return (ip_getifname_impl(phy_ifdata
, buffer
, buflen
, B_TRUE
,
640 neti
->netd_stack
->nts_netstack
->netstack_ip
));
644 * Shared implementation to determine the name of a given network interface
648 ip_getifname_impl(phy_if_t phy_ifdata
,
649 char *buffer
, const size_t buflen
, boolean_t isv6
, ip_stack_t
*ipst
)
653 ASSERT(buffer
!= NULL
);
655 ill
= ill_lookup_on_ifindex((uint_t
)phy_ifdata
, isv6
, ipst
);
659 (void) strlcpy(buffer
, ill
->ill_name
, buflen
);
665 * Determine the MTU of an IPv4 network interface
668 ip_getmtu(net_handle_t neti
, phy_if_t phy_ifdata
, lif_if_t ifdata
)
672 ns
= neti
->netd_stack
->nts_netstack
;
674 return (ip_getmtu_impl(phy_ifdata
, ifdata
, B_FALSE
, ns
->netstack_ip
));
678 * Determine the MTU of an IPv6 network interface
681 ipv6_getmtu(net_handle_t neti
, phy_if_t phy_ifdata
, lif_if_t ifdata
)
685 ns
= neti
->netd_stack
->nts_netstack
;
687 return (ip_getmtu_impl(phy_ifdata
, ifdata
, B_TRUE
, ns
->netstack_ip
));
691 * Shared implementation to determine the MTU of a network interface
695 ip_getmtu_impl(phy_if_t phy_ifdata
, lif_if_t ifdata
, boolean_t isv6
,
702 ipifid
= UNMAP_IPIF_ID(ifdata
);
704 ipif
= ipif_getby_indexes((uint_t
)phy_ifdata
, (uint_t
)ipifid
,
709 mtu
= ipif
->ipif_ill
->ill_mtu
;
715 if ((ill
= ill_lookup_on_ifindex((uint_t
)phy_ifdata
, isv6
,
727 * Determine if path MTU discovery is enabled for IP
730 ip_getpmtuenabled(net_handle_t neti
)
734 ns
= neti
->netd_stack
->nts_netstack
;
736 return (ns
->netstack_ip
->ips_ip_path_mtu_discovery
);
740 * Get next interface from the current list of IPv4 physical network interfaces
743 ip_phygetnext(net_handle_t neti
, phy_if_t phy_ifdata
)
747 ns
= neti
->netd_stack
->nts_netstack
;
749 return (ill_get_next_ifindex(phy_ifdata
, B_FALSE
, ns
->netstack_ip
));
753 * Get next interface from the current list of IPv6 physical network interfaces
756 ipv6_phygetnext(net_handle_t neti
, phy_if_t phy_ifdata
)
760 ns
= neti
->netd_stack
->nts_netstack
;
762 return (ill_get_next_ifindex(phy_ifdata
, B_TRUE
, ns
->netstack_ip
));
766 * Determine if a network interface name exists for IPv4
769 ip_phylookup(net_handle_t neti
, const char *name
)
773 ns
= neti
->netd_stack
->nts_netstack
;
775 return (ip_phylookup_impl(name
, B_FALSE
, ns
->netstack_ip
));
779 * Determine if a network interface name exists for IPv6
782 ipv6_phylookup(net_handle_t neti
, const char *name
)
786 ns
= neti
->netd_stack
->nts_netstack
;
788 return (ip_phylookup_impl(name
, B_TRUE
, ns
->netstack_ip
));
792 * Implement looking up an ill_t based on the name supplied and matching
793 * it up with either IPv4 or IPv6. ill_get_ifindex_by_name() is not used
794 * because it does not match on the address family in addition to the name.
797 ip_phylookup_impl(const char *name
, boolean_t isv6
, ip_stack_t
*ipst
)
802 ill
= ill_lookup_on_name((char *)name
, B_FALSE
, isv6
, NULL
, ipst
);
806 phy
= ill
->ill_phyint
->phyint_ifindex
;
814 * Get next interface from the current list of IPv4 logical network interfaces
817 ip_lifgetnext(net_handle_t neti
, phy_if_t phy_ifdata
, lif_if_t ifdata
)
821 ns
= neti
->netd_stack
->nts_netstack
;
823 return (ip_lifgetnext_impl(phy_ifdata
, ifdata
, B_FALSE
,
828 * Get next interface from the current list of IPv6 logical network interfaces
831 ipv6_lifgetnext(net_handle_t neti
, phy_if_t phy_ifdata
, lif_if_t ifdata
)
835 ns
= neti
->netd_stack
->nts_netstack
;
837 return (ip_lifgetnext_impl(phy_ifdata
, ifdata
, B_TRUE
,
842 * Shared implementation to get next interface from the current list of
843 * logical network interfaces
846 ip_lifgetnext_impl(phy_if_t phy_ifdata
, lif_if_t ifdata
, boolean_t isv6
,
849 lif_if_t newidx
, oldidx
;
854 ill
= ill_lookup_on_ifindex(phy_ifdata
, isv6
, ipst
);
859 oldidx
= UNMAP_IPIF_ID(ifdata
);
866 mutex_enter(&ill
->ill_lock
);
867 if (ill
->ill_state_flags
& ILL_CONDEMNED
) {
868 mutex_exit(&ill
->ill_lock
);
874 * It's safe to iterate the ill_ipif list when holding an ill_lock.
875 * And it's also safe to access ipif_id without ipif refhold.
876 * See the field access rules in ip.h.
878 for (ipif
= ill
->ill_ipif
; ipif
!= NULL
; ipif
= ipif
->ipif_next
) {
879 if (!IPIF_CAN_LOOKUP(ipif
))
882 ipif_refhold_locked(ipif
);
884 } else if (oldidx
== ipif
->ipif_id
) {
889 mutex_exit(&ill
->ill_lock
);
895 newidx
= ipif
->ipif_id
;
898 return (MAP_IPIF_ID(newidx
));
902 * Inject an IPv4 packet to or from an interface
905 ip_inject(net_handle_t neti
, inject_t style
, net_inject_t
*packet
)
909 ns
= neti
->netd_stack
->nts_netstack
;
911 return (ip_inject_impl(style
, packet
, B_FALSE
, ns
->netstack_ip
));
916 * Inject an IPv6 packet to or from an interface
919 ipv6_inject(net_handle_t neti
, inject_t style
, net_inject_t
*packet
)
923 ns
= neti
->netd_stack
->nts_netstack
;
924 return (ip_inject_impl(style
, packet
, B_TRUE
, ns
->netstack_ip
));
928 * Shared implementation to inject a packet to or from an interface
931 * -1: memory allocation failed
935 ip_inject_impl(inject_t style
, net_inject_t
*packet
, boolean_t isv6
,
938 ddi_taskq_t
*tq
= NULL
;
939 void (* func
)(void *);
943 ASSERT(packet
!= NULL
);
944 ASSERT(packet
->ni_packet
!= NULL
);
945 ASSERT(packet
->ni_packet
->b_datap
->db_type
== M_DATA
);
949 inject
= kmem_alloc(sizeof (*inject
), KM_NOSLEEP
);
952 inject
->inj_data
= *packet
;
953 inject
->inj_isv6
= isv6
;
955 * deliver up into the kernel, immitating its reception by a
956 * network interface, add to list and schedule timeout
958 func
= ip_ni_queue_in_func
;
959 tq
= eventq_queue_in
;
963 inject
= kmem_alloc(sizeof (*inject
), KM_NOSLEEP
);
966 inject
->inj_data
= *packet
;
967 inject
->inj_isv6
= isv6
;
969 * deliver out of the kernel, as if it were being sent via a
970 * raw socket so that IPFilter will see it again, add to list
971 * and schedule timeout
973 func
= ip_ni_queue_out_func
;
974 tq
= eventq_queue_out
;
977 case NI_DIRECT_OUT
: {
978 struct sockaddr
*sock
;
980 mp
= packet
->ni_packet
;
982 sock
= (struct sockaddr
*)&packet
->ni_addr
;
984 * ipfil_sendpkt was provided by surya to ease the
985 * problems associated with sending out a packet.
987 switch (ipfil_sendpkt(sock
, mp
, packet
->ni_physical
,
988 netstackid_to_zoneid(
989 ipst
->ips_netstack
->netstack_stackid
))) {
1002 freemsg(packet
->ni_packet
);
1008 inject
->inj_ptr
= ipst
;
1009 if (ddi_taskq_dispatch(tq
, func
, (void *)inject
,
1010 DDI_SLEEP
) == DDI_FAILURE
) {
1011 ip2dbg(("ip_inject: ddi_taskq_dispatch failed\n"));
1012 freemsg(packet
->ni_packet
);
1019 * Find the interface used for traffic to a given IPv4 address
1022 ip_routeto(net_handle_t neti
, struct sockaddr
*address
, struct sockaddr
*next
)
1026 ASSERT(address
!= NULL
);
1028 if (address
->sa_family
!= AF_INET
)
1031 ns
= neti
->netd_stack
->nts_netstack
;
1034 return (ip_routeto_impl(address
, next
, ns
->netstack_ip
));
1038 * Find the interface used for traffic to a given IPv6 address
1041 ipv6_routeto(net_handle_t neti
, struct sockaddr
*address
, struct sockaddr
*next
)
1045 ASSERT(address
!= NULL
);
1047 if (address
->sa_family
!= AF_INET6
)
1050 ns
= neti
->netd_stack
->nts_netstack
;
1053 return (ip_routeto_impl(address
, next
, ns
->netstack_ip
));
1058 * Find the interface used for traffic to an address.
1059 * For lint reasons, next/next6/sin/sin6 are all declared and assigned
1060 * a value at the top. The alternative would end up with two bunches
1061 * of assignments, with each bunch setting half to NULL.
1064 ip_routeto_impl(struct sockaddr
*address
, struct sockaddr
*nexthop
,
1067 struct sockaddr_in6
*next6
= (struct sockaddr_in6
*)nexthop
;
1068 struct sockaddr_in6
*sin6
= (struct sockaddr_in6
*)address
;
1069 struct sockaddr_in
*next
= (struct sockaddr_in
*)nexthop
;
1070 struct sockaddr_in
*sin
= (struct sockaddr_in
*)address
;
1076 zoneid
= netstackid_to_zoneid(ipst
->ips_netstack
->netstack_stackid
);
1078 if (address
->sa_family
== AF_INET6
) {
1079 ire
= ire_route_recursive_v6(&sin6
->sin6_addr
, 0, NULL
,
1080 zoneid
, MATCH_IRE_DSTONLY
, IRR_ALLOCATE
, 0, ipst
, NULL
,
1083 ire
= ire_route_recursive_v4(sin
->sin_addr
.s_addr
, 0, NULL
,
1084 zoneid
, MATCH_IRE_DSTONLY
, IRR_ALLOCATE
, 0, ipst
, NULL
,
1087 ASSERT(ire
!= NULL
);
1089 * For some destinations, we have routes that are dead ends, so
1090 * return to indicate that no physical interface can be used to
1091 * reach the destination.
1093 if (ire
->ire_flags
& (RTF_REJECT
|RTF_BLACKHOLE
)) {
1098 nexthop_ire
= ire_nexthop(ire
);
1099 if (nexthop_ire
== NULL
) {
1103 if (nexthop_ire
->ire_flags
& (RTF_REJECT
|RTF_BLACKHOLE
)) {
1104 ire_refrele(nexthop_ire
);
1109 ASSERT(nexthop_ire
->ire_ill
!= NULL
);
1111 if (nexthop
!= NULL
) {
1112 if (address
->sa_family
== AF_INET6
) {
1113 next6
->sin6_addr
= nexthop_ire
->ire_addr_v6
;
1115 next
->sin_addr
.s_addr
= nexthop_ire
->ire_addr
;
1119 phy_if
= (phy_if_t
)nexthop_ire
->ire_ill
->ill_phyint
->phyint_ifindex
;
1121 ire_refrele(nexthop_ire
);
1127 * Determine if checksumming is being used for the given packet.
1130 * NET_HCK_NONE: full checksum recalculation is required
1131 * NET_HCK_L3_FULL: full layer 3 checksum
1132 * NET_HCK_L4_FULL: full layer 4 checksum
1133 * NET_HCK_L4_PART: partial layer 4 checksum
1137 ip_ispartialchecksum(net_handle_t neti
, mblk_t
*mp
)
1143 if ((DB_CKSUMFLAGS(mp
) & HCK_FULLCKSUM
) != 0) {
1144 ret
|= (int)NET_HCK_L4_FULL
;
1145 if ((DB_CKSUMFLAGS(mp
) & HCK_IPV4_HDRCKSUM
) != 0)
1146 ret
|= (int)NET_HCK_L3_FULL
;
1148 if ((DB_CKSUMFLAGS(mp
) & HCK_PARTIALCKSUM
) != 0) {
1149 ret
|= (int)NET_HCK_L4_PART
;
1150 if ((DB_CKSUMFLAGS(mp
) & HCK_IPV4_HDRCKSUM
) != 0)
1151 ret
|= (int)NET_HCK_L3_FULL
;
1158 * Return true or false, indicating whether the network and transport
1159 * headers are correct. Use the capabilities flags and flags set in the
1160 * dblk_t to determine whether or not the checksum is valid.
1163 * 0: the checksum was incorrect
1164 * 1: the original checksum was correct
1168 ip_isvalidchecksum(net_handle_t neti
, mblk_t
*mp
)
1170 unsigned char *wptr
;
1171 ipha_t
*ipha
= (ipha_t
*)mp
->b_rptr
;
1178 ((DB_CKSUM16(mp
) != 0xFFFF &&
1179 (DB_CKSUMFLAGS(mp
) & HCK_FULLCKSUM
)) ||
1180 (DB_CKSUMFLAGS(mp
) & HCK_FULLCKSUM_OK
)) &&
1181 (DB_CKSUMFLAGS(mp
) & HCK_IPV4_HDRCKSUM_OK
))
1184 hlen
= (ipha
->ipha_version_and_hdr_length
& 0x0F) << 2;
1187 * Check that the mblk being passed in has enough data in it
1188 * before blindly checking ip_cksum.
1190 if (msgdsize(mp
) < hlen
)
1193 if (mp
->b_wptr
< mp
->b_rptr
+ hlen
) {
1194 if (pullupmsg(mp
, hlen
) == 0)
1199 mp
->b_wptr
= mp
->b_rptr
+ hlen
;
1202 if (ipha
->ipha_hdr_checksum
== ip_cksum(mp
, 0, ipha
->ipha_hdr_checksum
))
1212 * Unsupported with IPv6
1216 ipv6_isvalidchecksum(net_handle_t neti
, mblk_t
*mp
)
1222 * Determine the network addresses for an IPv4 interface
1225 ip_getlifaddr(net_handle_t neti
, phy_if_t phy_ifdata
, lif_if_t ifdata
,
1226 size_t nelem
, net_ifaddr_t type
[], void *storage
)
1230 ns
= neti
->netd_stack
->nts_netstack
;
1232 return (ip_getlifaddr_impl(AF_INET
, phy_ifdata
, ifdata
,
1233 nelem
, type
, storage
, ns
->netstack_ip
));
1237 * Determine the network addresses for an IPv6 interface
1240 ipv6_getlifaddr(net_handle_t neti
, phy_if_t phy_ifdata
, lif_if_t ifdata
,
1241 size_t nelem
, net_ifaddr_t type
[], void *storage
)
1245 ns
= neti
->netd_stack
->nts_netstack
;
1247 return (ip_getlifaddr_impl(AF_INET6
, phy_ifdata
, ifdata
,
1248 nelem
, type
, storage
, ns
->netstack_ip
));
1252 * Shared implementation to determine the network addresses for an interface
1256 ip_getlifaddr_impl(sa_family_t family
, phy_if_t phy_ifdata
,
1257 lif_if_t ifdata
, size_t nelem
, net_ifaddr_t type
[],
1258 struct sockaddr
*storage
, ip_stack_t
*ipst
)
1260 struct sockaddr_in6
*sin6
;
1261 struct sockaddr_in
*sin
;
1266 ASSERT(type
!= NULL
);
1267 ASSERT(storage
!= NULL
);
1269 ipifid
= UNMAP_IPIF_ID(ifdata
);
1271 if (family
== AF_INET
) {
1272 if ((ipif
= ipif_getby_indexes((uint_t
)phy_ifdata
,
1273 (uint_t
)ipifid
, B_FALSE
, ipst
)) == NULL
)
1276 sin
= (struct sockaddr_in
*)storage
;
1277 for (i
= 0; i
< nelem
; i
++, sin
++) {
1278 if (ip_getifaddr_type(AF_INET
, ipif
, type
[i
],
1279 &sin
->sin_addr
) < 0) {
1280 ip2dbg(("ip_getlifaddr_impl failed type %d\n",
1285 sin
->sin_family
= AF_INET
;
1288 if ((ipif
= ipif_getby_indexes((uint_t
)phy_ifdata
,
1289 (uint_t
)ipifid
, B_TRUE
, ipst
)) == NULL
)
1292 sin6
= (struct sockaddr_in6
*)storage
;
1293 for (i
= 0; i
< nelem
; i
++, sin6
++) {
1294 if (ip_getifaddr_type(AF_INET6
, ipif
, type
[i
],
1295 &sin6
->sin6_addr
) < 0) {
1296 ip2dbg(("ip_getlifaddr_impl failed type %d\n",
1301 sin6
->sin6_family
= AF_INET6
;
1309 * ip_getlifaddr private function
1312 ip_getifaddr_type(sa_family_t family
, ipif_t
*ill_ipif
,
1313 lif_if_t type
, void *storage
)
1318 ASSERT(ill_ipif
!= NULL
);
1319 ASSERT(storage
!= NULL
);
1321 if (family
== AF_INET
) {
1322 mem_size
= sizeof (struct in_addr
);
1326 src_addr
= &(ill_ipif
->ipif_lcl_addr
);
1329 src_addr
= &(ill_ipif
->ipif_pp_dst_addr
);
1332 src_addr
= &(ill_ipif
->ipif_brd_addr
);
1335 src_addr
= &(ill_ipif
->ipif_net_mask
);
1342 mem_size
= sizeof (struct in6_addr
);
1346 src_addr
= &(ill_ipif
->ipif_v6lcl_addr
);
1349 src_addr
= &(ill_ipif
->ipif_v6pp_dst_addr
);
1352 src_addr
= &(ill_ipif
->ipif_v6brd_addr
);
1355 src_addr
= &(ill_ipif
->ipif_v6net_mask
);
1363 (void) memcpy(storage
, src_addr
, mem_size
);
1368 * Shared implementation to determine the zoneid associated with an IPv4/IPv6
1372 ip_getlifzone_impl(sa_family_t family
, phy_if_t phy_ifdata
, lif_if_t ifdata
,
1373 ip_stack_t
*ipst
, zoneid_t
*zoneid
)
1377 ipif
= ipif_getby_indexes((uint_t
)phy_ifdata
,
1378 UNMAP_IPIF_ID((uint_t
)ifdata
), (family
== AF_INET6
), ipst
);
1381 *zoneid
= IP_REAL_ZONEID(ipif
->ipif_zoneid
, ipst
);
1387 * Determine the zoneid associated with an IPv4 address
1390 ip_getlifzone(net_handle_t neti
, phy_if_t phy_ifdata
, lif_if_t ifdata
,
1393 return (ip_getlifzone_impl(AF_INET
, phy_ifdata
, ifdata
,
1394 neti
->netd_stack
->nts_netstack
->netstack_ip
, zoneid
));
1398 * Determine the zoneid associated with an IPv6 address
1401 ipv6_getlifzone(net_handle_t neti
, phy_if_t phy_ifdata
, lif_if_t ifdata
,
1404 return (ip_getlifzone_impl(AF_INET6
, phy_ifdata
, ifdata
,
1405 neti
->netd_stack
->nts_netstack
->netstack_ip
, zoneid
));
1409 * The behaviour here mirrors that for the SIOCFLIFFLAGS ioctl where the
1410 * union of all of the relevant flags is returned.
1413 ip_getlifflags_impl(sa_family_t family
, phy_if_t phy_ifdata
, lif_if_t ifdata
,
1414 ip_stack_t
*ipst
, uint64_t *flags
)
1420 ill
= ill_lookup_on_ifindex(phy_ifdata
, (family
== AF_INET6
), ipst
);
1423 phyi
= ill
->ill_phyint
;
1425 ipif
= ipif_getby_indexes((uint_t
)phy_ifdata
,
1426 UNMAP_IPIF_ID((uint_t
)ifdata
), (family
== AF_INET6
), ipst
);
1431 *flags
= ipif
->ipif_flags
| ill
->ill_flags
| phyi
->phyint_flags
;
1438 ip_getlifflags(net_handle_t neti
, phy_if_t phy_ifdata
, lif_if_t ifdata
,
1441 return (ip_getlifflags_impl(AF_INET
, phy_ifdata
, ifdata
,
1442 neti
->netd_stack
->nts_netstack
->netstack_ip
, flags
));
1446 ipv6_getlifflags(net_handle_t neti
, phy_if_t phy_ifdata
, lif_if_t ifdata
,
1449 return (ip_getlifflags_impl(AF_INET6
, phy_ifdata
, ifdata
,
1450 neti
->netd_stack
->nts_netstack
->netstack_ip
, flags
));
1454 * Deliver packet up into the kernel, immitating its reception by a
1455 * network interface.
1458 ip_ni_queue_in_func(void *inject
)
1460 ip_ni_queue_func_impl(inject
, B_FALSE
);
1464 * Deliver out of the kernel, as if it were being sent via a
1465 * raw socket so that IPFilter will see it again.
1468 ip_ni_queue_out_func(void *inject
)
1470 ip_ni_queue_func_impl(inject
, B_TRUE
);
1474 * Shared implementation for inject via ip_output and ip_input
1477 ip_ni_queue_func_impl(injection_t
*inject
, boolean_t out
)
1479 net_inject_t
*packet
;
1481 ip_stack_t
*ipst
= (ip_stack_t
*)inject
->inj_ptr
;
1482 ip_xmit_attr_t ixas
;
1484 ASSERT(inject
!= NULL
);
1485 packet
= &inject
->inj_data
;
1486 ASSERT(packet
->ni_packet
!= NULL
);
1489 ill
= ill_lookup_on_ifindex((uint_t
)packet
->ni_physical
,
1490 inject
->inj_isv6
, ipst
);
1493 kmem_free(inject
, sizeof (*inject
));
1497 if (inject
->inj_isv6
) {
1498 ip_input_v6(ill
, NULL
, packet
->ni_packet
, NULL
);
1500 ip_input(ill
, NULL
, packet
->ni_packet
, NULL
);
1504 bzero(&ixas
, sizeof (ixas
));
1505 ixas
.ixa_ifindex
= packet
->ni_physical
;
1506 ixas
.ixa_ipst
= ipst
;
1507 if (inject
->inj_isv6
) {
1508 ixas
.ixa_flags
= IXAF_BASIC_SIMPLE_V6
;
1510 ixas
.ixa_flags
= IXAF_BASIC_SIMPLE_V4
;
1512 ixas
.ixa_flags
&= ~IXAF_VERIFY_SOURCE
;
1513 (void) ip_output_simple(packet
->ni_packet
, &ixas
);
1517 kmem_free(inject
, sizeof (*inject
));
1521 * taskq function for nic events.
1524 ip_ne_queue_func(void *arg
)
1526 hook_event_token_t hr
;
1527 hook_nic_event_int_t
*info
= (hook_nic_event_int_t
*)arg
;
1531 ns
= netstack_find_by_stackid(info
->hnei_stackid
);
1535 ipst
= ns
->netstack_ip
;
1539 hr
= (info
->hnei_event
.hne_protocol
== ipst
->ips_ipv6_net_data
) ?
1540 ipst
->ips_ipv6nicevents
: ipst
->ips_ipv4nicevents
;
1541 (void) hook_run(info
->hnei_event
.hne_protocol
->netd_hooks
, hr
,
1542 (hook_data_t
)&info
->hnei_event
);
1547 kmem_free(info
->hnei_event
.hne_data
, info
->hnei_event
.hne_datalen
);
1548 kmem_free(arg
, sizeof (hook_nic_event_int_t
));
1552 * Initialize ARP hook family and events
1555 arp_hook_init(ip_stack_t
*ipst
)
1557 HOOK_FAMILY_INIT(&ipst
->ips_arproot
, Hn_ARP
);
1558 if (net_family_register(ipst
->ips_arp_net_data
, &ipst
->ips_arproot
)
1560 cmn_err(CE_NOTE
, "arp_hook_init"
1561 "net_family_register failed for arp");
1564 HOOK_EVENT_INIT(&ipst
->ips_arp_physical_in_event
, NH_PHYSICAL_IN
);
1565 ipst
->ips_arp_physical_in
= net_event_register(ipst
->ips_arp_net_data
,
1566 &ipst
->ips_arp_physical_in_event
);
1567 if (ipst
->ips_arp_physical_in
== NULL
) {
1568 cmn_err(CE_NOTE
, "arp_hook_init: "
1569 "net_event_register failed for arp/physical_in");
1572 HOOK_EVENT_INIT(&ipst
->ips_arp_physical_out_event
, NH_PHYSICAL_OUT
);
1573 ipst
->ips_arp_physical_out
= net_event_register(ipst
->ips_arp_net_data
,
1574 &ipst
->ips_arp_physical_out_event
);
1575 if (ipst
->ips_arp_physical_out
== NULL
) {
1576 cmn_err(CE_NOTE
, "arp_hook_init: "
1577 "net_event_register failed for arp/physical_out");
1580 HOOK_EVENT_INIT(&ipst
->ips_arp_nic_events
, NH_NIC_EVENTS
);
1581 ipst
->ips_arpnicevents
= net_event_register(ipst
->ips_arp_net_data
,
1582 &ipst
->ips_arp_nic_events
);
1583 if (ipst
->ips_arpnicevents
== NULL
) {
1584 cmn_err(CE_NOTE
, "arp_hook_init: "
1585 "net_event_register failed for arp/nic_events");
1590 arp_hook_destroy(ip_stack_t
*ipst
)
1592 if (ipst
->ips_arpnicevents
!= NULL
) {
1593 if (net_event_unregister(ipst
->ips_arp_net_data
,
1594 &ipst
->ips_arp_nic_events
) == 0)
1595 ipst
->ips_arpnicevents
= NULL
;
1598 if (ipst
->ips_arp_physical_out
!= NULL
) {
1599 if (net_event_unregister(ipst
->ips_arp_net_data
,
1600 &ipst
->ips_arp_physical_out_event
) == 0)
1601 ipst
->ips_arp_physical_out
= NULL
;
1604 if (ipst
->ips_arp_physical_in
!= NULL
) {
1605 if (net_event_unregister(ipst
->ips_arp_net_data
,
1606 &ipst
->ips_arp_physical_in_event
) == 0)
1607 ipst
->ips_arp_physical_in
= NULL
;
1610 (void) net_family_unregister(ipst
->ips_arp_net_data
,
1611 &ipst
->ips_arproot
);
1615 arp_hook_shutdown(ip_stack_t
*ipst
)
1617 if (ipst
->ips_arp_physical_in
!= NULL
) {
1618 (void) net_event_shutdown(ipst
->ips_arp_net_data
,
1619 &ipst
->ips_arp_physical_in_event
);
1621 if (ipst
->ips_arp_physical_out
!= NULL
) {
1622 (void) net_event_shutdown(ipst
->ips_arp_net_data
,
1623 &ipst
->ips_arp_physical_out_event
);
1625 if (ipst
->ips_arpnicevents
!= NULL
) {
1626 (void) net_event_shutdown(ipst
->ips_arp_net_data
,
1627 &ipst
->ips_arp_nic_events
);
1631 /* netinfo routines for the unsupported cases */
1635 net_no_getmtu(net_handle_t handle
, phy_if_t phy_ifdata
, lif_if_t ifdata
)
1642 net_no_getpmtuenabled(net_handle_t neti
)
1649 net_no_lifgetnext(net_handle_t neti
, phy_if_t phy_ifdata
, lif_if_t ifdata
)
1656 net_no_inject(net_handle_t neti
, inject_t style
, net_inject_t
*packet
)
1663 net_no_routeto(net_handle_t neti
, struct sockaddr
*address
,
1664 struct sockaddr
*next
)
1666 return ((phy_if_t
)-1);
1671 net_no_ispartialchecksum(net_handle_t neti
, mblk_t
*mp
)
1678 net_no_getlifaddr(net_handle_t neti
, phy_if_t phy_ifdata
, lif_if_t ifdata
,
1679 size_t nelem
, net_ifaddr_t type
[], void *storage
)
1686 net_no_getlifzone(net_handle_t neti
, phy_if_t phy_ifdata
, lif_if_t ifdata
,
1694 net_no_getlifflags(net_handle_t neti
, phy_if_t phy_ifdata
, lif_if_t ifdata
,