Merge commit 'b1e7e97d3b60469b243b3b2e22c7d8cbd11c7c90'
[unleashed.git] / kernel / net / ip / ip_netinfo.c
blob14c74cf6f0e2cb04179f0f181d21f8ed9b605e39
1 /*
2 * CDDL HEADER START
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]
19 * CDDL HEADER END
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>
32 #include <sys/dlpi.h>
33 #include <sys/atomic.h>
34 #include <sys/sunddi.h>
35 #include <sys/socket.h>
36 #include <sys/neti.h>
37 #include <sys/sdt.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>
44 #include <inet/ip.h>
45 #include <inet/ip6.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 *,
58 const size_t);
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,
64 zoneid_t *);
65 static int ip_getlifflags(net_handle_t, phy_if_t, lif_if_t,
66 uint64_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 *,
72 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 *,
77 const size_t);
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,
82 zoneid_t *);
83 static int ipv6_getlifflags(net_handle_t, phy_if_t, lif_if_t,
84 uint64_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 *,
90 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 *,
98 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,
103 zoneid_t *);
104 static int net_no_getlifflags(net_handle_t, phy_if_t, lif_if_t,
105 uint64_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,
111 ip_stack_t *);
112 static phy_if_t ip_phylookup_impl(const char *, boolean_t,
113 ip_stack_t *);
114 static lif_if_t ip_lifgetnext_impl(phy_if_t, lif_if_t, boolean_t,
115 ip_stack_t *);
116 static int ip_inject_impl(inject_t, net_inject_t *, boolean_t,
117 ip_stack_t *);
118 static int ip_getifaddr_type(sa_family_t, ipif_t *, lif_if_t,
119 void *);
120 static phy_if_t ip_routeto_impl(struct sockaddr *, struct sockaddr *,
121 ip_stack_t *);
122 static int ip_getlifaddr_impl(sa_family_t, phy_if_t, lif_if_t,
123 size_t, net_ifaddr_t [], struct sockaddr *,
124 ip_stack_t *);
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 = {
130 NETINFO_VERSION,
131 NHF_INET,
132 ip_getifname,
133 ip_getmtu,
134 ip_getpmtuenabled,
135 ip_getlifaddr,
136 ip_getlifzone,
137 ip_getlifflags,
138 ip_phygetnext,
139 ip_phylookup,
140 ip_lifgetnext,
141 ip_inject,
142 ip_routeto,
143 ip_ispartialchecksum,
144 ip_isvalidchecksum
148 static net_protocol_t ipv6info = {
149 NETINFO_VERSION,
150 NHF_INET6,
151 ipv6_getifname,
152 ipv6_getmtu,
153 ip_getpmtuenabled,
154 ipv6_getlifaddr,
155 ipv6_getlifzone,
156 ipv6_getlifflags,
157 ipv6_phygetnext,
158 ipv6_phylookup,
159 ipv6_lifgetnext,
160 ipv6_inject,
161 ipv6_routeto,
162 ip_ispartialchecksum,
163 ipv6_isvalidchecksum
166 static net_protocol_t arp_netinfo = {
167 NETINFO_VERSION,
168 NHF_ARP,
169 ip_getifname,
170 net_no_getmtu,
171 net_no_getpmtuenabled,
172 net_no_getlifaddr,
173 net_no_getlifzone,
174 net_no_getlifflags,
175 ip_phygetnext,
176 ip_phylookup,
177 net_no_lifgetnext,
178 net_no_inject,
179 net_no_routeto,
180 net_no_ispartialchecksum,
181 ip_isvalidchecksum
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.
196 void
197 ip_net_g_init()
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
230 void
231 ip_net_g_destroy()
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.
252 void
253 ip_net_init(ip_stack_t *ipst, netstack_t *ns)
255 netid_t id;
257 id = net_getnetidbynetstackid(ns->netstack_stackid);
258 ASSERT(id != -1);
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.
274 void
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
296 void
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)
301 != 0) {
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");
366 void
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);
408 void
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
460 void
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)
466 != 0) {
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");
530 void
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);
572 void
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
624 static int
625 ip_getifname(net_handle_t neti, phy_if_t phy_ifdata, char *buffer,
626 const size_t buflen)
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
635 static int
636 ipv6_getifname(net_handle_t neti, phy_if_t phy_ifdata, char *buffer,
637 const size_t buflen)
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
646 /* ARGSUSED */
647 static int
648 ip_getifname_impl(phy_if_t phy_ifdata,
649 char *buffer, const size_t buflen, boolean_t isv6, ip_stack_t *ipst)
651 ill_t *ill;
653 ASSERT(buffer != NULL);
655 ill = ill_lookup_on_ifindex((uint_t)phy_ifdata, isv6, ipst);
656 if (ill == NULL)
657 return (1);
659 (void) strlcpy(buffer, ill->ill_name, buflen);
660 ill_refrele(ill);
661 return (0);
665 * Determine the MTU of an IPv4 network interface
667 static int
668 ip_getmtu(net_handle_t neti, phy_if_t phy_ifdata, lif_if_t ifdata)
670 netstack_t *ns;
672 ns = neti->netd_stack->nts_netstack;
673 ASSERT(ns != NULL);
674 return (ip_getmtu_impl(phy_ifdata, ifdata, B_FALSE, ns->netstack_ip));
678 * Determine the MTU of an IPv6 network interface
680 static int
681 ipv6_getmtu(net_handle_t neti, phy_if_t phy_ifdata, lif_if_t ifdata)
683 netstack_t *ns;
685 ns = neti->netd_stack->nts_netstack;
686 ASSERT(ns != NULL);
687 return (ip_getmtu_impl(phy_ifdata, ifdata, B_TRUE, ns->netstack_ip));
691 * Shared implementation to determine the MTU of a network interface
693 /* ARGSUSED */
694 static int
695 ip_getmtu_impl(phy_if_t phy_ifdata, lif_if_t ifdata, boolean_t isv6,
696 ip_stack_t *ipst)
698 lif_if_t ipifid;
699 ipif_t *ipif;
700 int mtu;
702 ipifid = UNMAP_IPIF_ID(ifdata);
704 ipif = ipif_getby_indexes((uint_t)phy_ifdata, (uint_t)ipifid,
705 isv6, ipst);
706 if (ipif == NULL)
707 return (0);
709 mtu = ipif->ipif_ill->ill_mtu;
710 ipif_refrele(ipif);
712 if (mtu == 0) {
713 ill_t *ill;
715 if ((ill = ill_lookup_on_ifindex((uint_t)phy_ifdata, isv6,
716 ipst)) == NULL) {
717 return (0);
719 mtu = ill->ill_mtu;
720 ill_refrele(ill);
723 return (mtu);
727 * Determine if path MTU discovery is enabled for IP
729 static int
730 ip_getpmtuenabled(net_handle_t neti)
732 netstack_t *ns;
734 ns = neti->netd_stack->nts_netstack;
735 ASSERT(ns != NULL);
736 return (ns->netstack_ip->ips_ip_path_mtu_discovery);
740 * Get next interface from the current list of IPv4 physical network interfaces
742 static phy_if_t
743 ip_phygetnext(net_handle_t neti, phy_if_t phy_ifdata)
745 netstack_t *ns;
747 ns = neti->netd_stack->nts_netstack;
748 ASSERT(ns != NULL);
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
755 static phy_if_t
756 ipv6_phygetnext(net_handle_t neti, phy_if_t phy_ifdata)
758 netstack_t *ns;
760 ns = neti->netd_stack->nts_netstack;
761 ASSERT(ns != NULL);
762 return (ill_get_next_ifindex(phy_ifdata, B_TRUE, ns->netstack_ip));
766 * Determine if a network interface name exists for IPv4
768 static phy_if_t
769 ip_phylookup(net_handle_t neti, const char *name)
771 netstack_t *ns;
773 ns = neti->netd_stack->nts_netstack;
774 ASSERT(ns != NULL);
775 return (ip_phylookup_impl(name, B_FALSE, ns->netstack_ip));
779 * Determine if a network interface name exists for IPv6
781 static phy_if_t
782 ipv6_phylookup(net_handle_t neti, const char *name)
784 netstack_t *ns;
786 ns = neti->netd_stack->nts_netstack;
787 ASSERT(ns != NULL);
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.
796 static phy_if_t
797 ip_phylookup_impl(const char *name, boolean_t isv6, ip_stack_t *ipst)
799 phy_if_t phy;
800 ill_t *ill;
802 ill = ill_lookup_on_name((char *)name, B_FALSE, isv6, NULL, ipst);
803 if (ill == NULL)
804 return (0);
806 phy = ill->ill_phyint->phyint_ifindex;
808 ill_refrele(ill);
810 return (phy);
814 * Get next interface from the current list of IPv4 logical network interfaces
816 static lif_if_t
817 ip_lifgetnext(net_handle_t neti, phy_if_t phy_ifdata, lif_if_t ifdata)
819 netstack_t *ns;
821 ns = neti->netd_stack->nts_netstack;
822 ASSERT(ns != NULL);
823 return (ip_lifgetnext_impl(phy_ifdata, ifdata, B_FALSE,
824 ns->netstack_ip));
828 * Get next interface from the current list of IPv6 logical network interfaces
830 static lif_if_t
831 ipv6_lifgetnext(net_handle_t neti, phy_if_t phy_ifdata, lif_if_t ifdata)
833 netstack_t *ns;
835 ns = neti->netd_stack->nts_netstack;
836 ASSERT(ns != NULL);
837 return (ip_lifgetnext_impl(phy_ifdata, ifdata, B_TRUE,
838 ns->netstack_ip));
842 * Shared implementation to get next interface from the current list of
843 * logical network interfaces
845 static lif_if_t
846 ip_lifgetnext_impl(phy_if_t phy_ifdata, lif_if_t ifdata, boolean_t isv6,
847 ip_stack_t *ipst)
849 lif_if_t newidx, oldidx;
850 boolean_t nextok;
851 ipif_t *ipif;
852 ill_t *ill;
854 ill = ill_lookup_on_ifindex(phy_ifdata, isv6, ipst);
855 if (ill == NULL)
856 return (0);
858 if (ifdata != 0) {
859 oldidx = UNMAP_IPIF_ID(ifdata);
860 nextok = B_FALSE;
861 } else {
862 oldidx = 0;
863 nextok = B_TRUE;
866 mutex_enter(&ill->ill_lock);
867 if (ill->ill_state_flags & ILL_CONDEMNED) {
868 mutex_exit(&ill->ill_lock);
869 ill_refrele(ill);
870 return (0);
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))
880 continue;
881 if (nextok) {
882 ipif_refhold_locked(ipif);
883 break;
884 } else if (oldidx == ipif->ipif_id) {
885 nextok = B_TRUE;
889 mutex_exit(&ill->ill_lock);
890 ill_refrele(ill);
892 if (ipif == NULL)
893 return (0);
895 newidx = ipif->ipif_id;
896 ipif_refrele(ipif);
898 return (MAP_IPIF_ID(newidx));
902 * Inject an IPv4 packet to or from an interface
904 static int
905 ip_inject(net_handle_t neti, inject_t style, net_inject_t *packet)
907 netstack_t *ns;
909 ns = neti->netd_stack->nts_netstack;
910 ASSERT(ns != NULL);
911 return (ip_inject_impl(style, packet, B_FALSE, ns->netstack_ip));
916 * Inject an IPv6 packet to or from an interface
918 static int
919 ipv6_inject(net_handle_t neti, inject_t style, net_inject_t *packet)
921 netstack_t *ns;
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
929 * Return value:
930 * 0: successful
931 * -1: memory allocation failed
932 * 1: other errors
934 static int
935 ip_inject_impl(inject_t style, net_inject_t *packet, boolean_t isv6,
936 ip_stack_t *ipst)
938 ddi_taskq_t *tq = NULL;
939 void (* func)(void *);
940 injection_t *inject;
941 mblk_t *mp;
943 ASSERT(packet != NULL);
944 ASSERT(packet->ni_packet != NULL);
945 ASSERT(packet->ni_packet->b_datap->db_type == M_DATA);
947 switch (style) {
948 case NI_QUEUE_IN:
949 inject = kmem_alloc(sizeof (*inject), KM_NOSLEEP);
950 if (inject == NULL)
951 return (-1);
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;
960 break;
962 case NI_QUEUE_OUT:
963 inject = kmem_alloc(sizeof (*inject), KM_NOSLEEP);
964 if (inject == NULL)
965 return (-1);
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;
975 break;
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))) {
990 case 0 :
991 case EINPROGRESS:
992 return (0);
993 case ECOMM :
994 case ENONET :
995 return (1);
996 default :
997 return (1);
999 /* NOTREACHED */
1001 default:
1002 freemsg(packet->ni_packet);
1003 return (1);
1006 ASSERT(tq != NULL);
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);
1013 return (1);
1015 return (0);
1019 * Find the interface used for traffic to a given IPv4 address
1021 static phy_if_t
1022 ip_routeto(net_handle_t neti, struct sockaddr *address, struct sockaddr *next)
1024 netstack_t *ns;
1026 ASSERT(address != NULL);
1028 if (address->sa_family != AF_INET)
1029 return (0);
1031 ns = neti->netd_stack->nts_netstack;
1032 ASSERT(ns != NULL);
1034 return (ip_routeto_impl(address, next, ns->netstack_ip));
1038 * Find the interface used for traffic to a given IPv6 address
1040 static phy_if_t
1041 ipv6_routeto(net_handle_t neti, struct sockaddr *address, struct sockaddr *next)
1043 netstack_t *ns;
1045 ASSERT(address != NULL);
1047 if (address->sa_family != AF_INET6)
1048 return (0);
1050 ns = neti->netd_stack->nts_netstack;
1051 ASSERT(ns != NULL);
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.
1063 static phy_if_t
1064 ip_routeto_impl(struct sockaddr *address, struct sockaddr *nexthop,
1065 ip_stack_t *ipst)
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;
1071 ire_t *ire;
1072 ire_t *nexthop_ire;
1073 phy_if_t phy_if;
1074 zoneid_t zoneid;
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,
1081 NULL);
1082 } else {
1083 ire = ire_route_recursive_v4(sin->sin_addr.s_addr, 0, NULL,
1084 zoneid, MATCH_IRE_DSTONLY, IRR_ALLOCATE, 0, ipst, NULL,
1085 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)) {
1094 ire_refrele(ire);
1095 return (0);
1098 nexthop_ire = ire_nexthop(ire);
1099 if (nexthop_ire == NULL) {
1100 ire_refrele(ire);
1101 return (0);
1103 if (nexthop_ire->ire_flags & (RTF_REJECT|RTF_BLACKHOLE)) {
1104 ire_refrele(nexthop_ire);
1105 ire_refrele(ire);
1106 return (0);
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;
1114 } else {
1115 next->sin_addr.s_addr = nexthop_ire->ire_addr;
1119 phy_if = (phy_if_t)nexthop_ire->ire_ill->ill_phyint->phyint_ifindex;
1120 ire_refrele(ire);
1121 ire_refrele(nexthop_ire);
1123 return (phy_if);
1127 * Determine if checksumming is being used for the given packet.
1129 * Return value:
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
1135 /*ARGSUSED*/
1136 static int
1137 ip_ispartialchecksum(net_handle_t neti, mblk_t *mp)
1139 int ret = 0;
1141 ASSERT(mp != NULL);
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;
1154 return (ret);
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.
1162 * Return:
1163 * 0: the checksum was incorrect
1164 * 1: the original checksum was correct
1166 /*ARGSUSED*/
1167 static int
1168 ip_isvalidchecksum(net_handle_t neti, mblk_t *mp)
1170 unsigned char *wptr;
1171 ipha_t *ipha = (ipha_t *)mp->b_rptr;
1172 int hlen;
1173 int ret;
1175 ASSERT(mp != NULL);
1177 if (dohwcksum &&
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))
1182 return (1);
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)
1191 return (0);
1193 if (mp->b_wptr < mp->b_rptr + hlen) {
1194 if (pullupmsg(mp, hlen) == 0)
1195 return (0);
1196 wptr = mp->b_wptr;
1197 } else {
1198 wptr = mp->b_wptr;
1199 mp->b_wptr = mp->b_rptr + hlen;
1202 if (ipha->ipha_hdr_checksum == ip_cksum(mp, 0, ipha->ipha_hdr_checksum))
1203 ret = 1;
1204 else
1205 ret = 0;
1206 mp->b_wptr = wptr;
1208 return (ret);
1212 * Unsupported with IPv6
1214 /*ARGSUSED*/
1215 static int
1216 ipv6_isvalidchecksum(net_handle_t neti, mblk_t *mp)
1218 return (-1);
1222 * Determine the network addresses for an IPv4 interface
1224 static int
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)
1228 netstack_t *ns;
1230 ns = neti->netd_stack->nts_netstack;
1231 ASSERT(ns != NULL);
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
1239 static int
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)
1243 netstack_t *ns;
1245 ns = neti->netd_stack->nts_netstack;
1246 ASSERT(ns != NULL);
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
1254 /* ARGSUSED */
1255 static int
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;
1262 lif_if_t ipifid;
1263 ipif_t *ipif;
1264 int i;
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)
1274 return (1);
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",
1281 type[i]));
1282 ipif_refrele(ipif);
1283 return (1);
1285 sin->sin_family = AF_INET;
1287 } else {
1288 if ((ipif = ipif_getby_indexes((uint_t)phy_ifdata,
1289 (uint_t)ipifid, B_TRUE, ipst)) == NULL)
1290 return (1);
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",
1297 type[i]));
1298 ipif_refrele(ipif);
1299 return (1);
1301 sin6->sin6_family = AF_INET6;
1304 ipif_refrele(ipif);
1305 return (0);
1309 * ip_getlifaddr private function
1311 static int
1312 ip_getifaddr_type(sa_family_t family, ipif_t *ill_ipif,
1313 lif_if_t type, void *storage)
1315 void *src_addr;
1316 int mem_size;
1318 ASSERT(ill_ipif != NULL);
1319 ASSERT(storage != NULL);
1321 if (family == AF_INET) {
1322 mem_size = sizeof (struct in_addr);
1324 switch (type) {
1325 case NA_ADDRESS:
1326 src_addr = &(ill_ipif->ipif_lcl_addr);
1327 break;
1328 case NA_PEER:
1329 src_addr = &(ill_ipif->ipif_pp_dst_addr);
1330 break;
1331 case NA_BROADCAST:
1332 src_addr = &(ill_ipif->ipif_brd_addr);
1333 break;
1334 case NA_NETMASK:
1335 src_addr = &(ill_ipif->ipif_net_mask);
1336 break;
1337 default:
1338 return (-1);
1339 /*NOTREACHED*/
1341 } else {
1342 mem_size = sizeof (struct in6_addr);
1344 switch (type) {
1345 case NA_ADDRESS:
1346 src_addr = &(ill_ipif->ipif_v6lcl_addr);
1347 break;
1348 case NA_PEER:
1349 src_addr = &(ill_ipif->ipif_v6pp_dst_addr);
1350 break;
1351 case NA_BROADCAST:
1352 src_addr = &(ill_ipif->ipif_v6brd_addr);
1353 break;
1354 case NA_NETMASK:
1355 src_addr = &(ill_ipif->ipif_v6net_mask);
1356 break;
1357 default:
1358 return (-1);
1359 /*NOTREACHED*/
1363 (void) memcpy(storage, src_addr, mem_size);
1364 return (1);
1368 * Shared implementation to determine the zoneid associated with an IPv4/IPv6
1369 * address
1371 static int
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)
1375 ipif_t *ipif;
1377 ipif = ipif_getby_indexes((uint_t)phy_ifdata,
1378 UNMAP_IPIF_ID((uint_t)ifdata), (family == AF_INET6), ipst);
1379 if (ipif == NULL)
1380 return (-1);
1381 *zoneid = IP_REAL_ZONEID(ipif->ipif_zoneid, ipst);
1382 ipif_refrele(ipif);
1383 return (0);
1387 * Determine the zoneid associated with an IPv4 address
1389 static int
1390 ip_getlifzone(net_handle_t neti, phy_if_t phy_ifdata, lif_if_t ifdata,
1391 zoneid_t *zoneid)
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
1400 static int
1401 ipv6_getlifzone(net_handle_t neti, phy_if_t phy_ifdata, lif_if_t ifdata,
1402 zoneid_t *zoneid)
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.
1412 static int
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)
1416 phyint_t *phyi;
1417 ipif_t *ipif;
1418 ill_t *ill;
1420 ill = ill_lookup_on_ifindex(phy_ifdata, (family == AF_INET6), ipst);
1421 if (ill == NULL)
1422 return (-1);
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);
1427 if (ipif == NULL) {
1428 ill_refrele(ill);
1429 return (-1);
1431 *flags = ipif->ipif_flags | ill->ill_flags | phyi->phyint_flags;
1432 ipif_refrele(ipif);
1433 ill_refrele(ill);
1434 return (0);
1437 static int
1438 ip_getlifflags(net_handle_t neti, phy_if_t phy_ifdata, lif_if_t ifdata,
1439 uint64_t *flags)
1441 return (ip_getlifflags_impl(AF_INET, phy_ifdata, ifdata,
1442 neti->netd_stack->nts_netstack->netstack_ip, flags));
1445 static int
1446 ipv6_getlifflags(net_handle_t neti, phy_if_t phy_ifdata, lif_if_t ifdata,
1447 uint64_t *flags)
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.
1457 static void
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.
1467 static void
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
1476 static void
1477 ip_ni_queue_func_impl(injection_t *inject, boolean_t out)
1479 net_inject_t *packet;
1480 ill_t *ill;
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);
1488 if (out == 0) {
1489 ill = ill_lookup_on_ifindex((uint_t)packet->ni_physical,
1490 inject->inj_isv6, ipst);
1492 if (ill == NULL) {
1493 kmem_free(inject, sizeof (*inject));
1494 return;
1497 if (inject->inj_isv6) {
1498 ip_input_v6(ill, NULL, packet->ni_packet, NULL);
1499 } else {
1500 ip_input(ill, NULL, packet->ni_packet, NULL);
1502 ill_refrele(ill);
1503 } else {
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;
1509 } else {
1510 ixas.ixa_flags = IXAF_BASIC_SIMPLE_V4;
1512 ixas.ixa_flags &= ~IXAF_VERIFY_SOURCE;
1513 (void) ip_output_simple(packet->ni_packet, &ixas);
1514 ixa_cleanup(&ixas);
1517 kmem_free(inject, sizeof (*inject));
1521 * taskq function for nic events.
1523 void
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;
1528 ip_stack_t *ipst;
1529 netstack_t *ns;
1531 ns = netstack_find_by_stackid(info->hnei_stackid);
1532 if (ns == NULL)
1533 goto done;
1535 ipst = ns->netstack_ip;
1536 if (ipst == NULL)
1537 goto done;
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);
1544 done:
1545 if (ns != NULL)
1546 netstack_rele(ns);
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
1554 void
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)
1559 != 0) {
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");
1589 void
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);
1614 void
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 */
1633 /* ARGSUSED */
1635 net_no_getmtu(net_handle_t handle, phy_if_t phy_ifdata, lif_if_t ifdata)
1637 return (-1);
1640 /* ARGSUSED */
1641 static int
1642 net_no_getpmtuenabled(net_handle_t neti)
1644 return (-1);
1647 /* ARGSUSED */
1648 static lif_if_t
1649 net_no_lifgetnext(net_handle_t neti, phy_if_t phy_ifdata, lif_if_t ifdata)
1651 return (-1);
1654 /* ARGSUSED */
1655 static int
1656 net_no_inject(net_handle_t neti, inject_t style, net_inject_t *packet)
1658 return (-1);
1661 /* ARGSUSED */
1662 static phy_if_t
1663 net_no_routeto(net_handle_t neti, struct sockaddr *address,
1664 struct sockaddr *next)
1666 return ((phy_if_t)-1);
1669 /* ARGSUSED */
1670 static int
1671 net_no_ispartialchecksum(net_handle_t neti, mblk_t *mp)
1673 return (-1);
1676 /* ARGSUSED */
1677 static int
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)
1681 return (-1);
1684 /* ARGSUSED */
1685 static int
1686 net_no_getlifzone(net_handle_t neti, phy_if_t phy_ifdata, lif_if_t ifdata,
1687 zoneid_t *zoneid)
1689 return (-1);
1692 /* ARGSUSED */
1693 static int
1694 net_no_getlifflags(net_handle_t neti, phy_if_t phy_ifdata, lif_if_t ifdata,
1695 uint64_t *flags)
1697 return (-1);