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 2010 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
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>
39
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>
53
54 /*
55 * IPv4 netinfo entry point declarations.
56 */
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 *);
75
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 *);
92
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 *);
106
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);
128
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
145 };
146
147
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
164 };
165
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
182 };
183
184 /*
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.
188 */
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;
192
193 /*
194 * Initialize queues for inject.
195 */
196 void
ip_net_g_init()197 ip_net_g_init()
198 {
199 if (eventq_queue_out == NULL) {
200 eventq_queue_out = ddi_taskq_create(NULL,
201 "IP_INJECT_QUEUE_OUT", 1, TASKQ_DEFAULTPRI, 0);
202
203 if (eventq_queue_out == NULL)
204 cmn_err(CE_NOTE, "ipv4_net_init: "
205 "ddi_taskq_create failed for IP_INJECT_QUEUE_OUT");
206 }
207
208 if (eventq_queue_in == NULL) {
209 eventq_queue_in = ddi_taskq_create(NULL,
210 "IP_INJECT_QUEUE_IN", 1, TASKQ_DEFAULTPRI, 0);
211
212 if (eventq_queue_in == NULL)
213 cmn_err(CE_NOTE, "ipv4_net_init: "
214 "ddi_taskq_create failed for IP_INJECT_QUEUE_IN");
215 }
216
217 if (eventq_queue_nic == NULL) {
218 eventq_queue_nic = ddi_taskq_create(NULL,
219 "IP_NIC_EVENT_QUEUE", 1, TASKQ_DEFAULTPRI, 0);
220
221 if (eventq_queue_nic == NULL)
222 cmn_err(CE_NOTE, "ipv4_net_init: "
223 "ddi_taskq_create failed for IP_NIC_EVENT_QUEUE");
224 }
225 }
226
227 /*
228 * Destroy inject queues
229 */
230 void
ip_net_g_destroy()231 ip_net_g_destroy()
232 {
233 if (eventq_queue_nic != NULL) {
234 ddi_taskq_destroy(eventq_queue_nic);
235 eventq_queue_nic = NULL;
236 }
237
238 if (eventq_queue_in != NULL) {
239 ddi_taskq_destroy(eventq_queue_in);
240 eventq_queue_in = NULL;
241 }
242
243 if (eventq_queue_out != NULL) {
244 ddi_taskq_destroy(eventq_queue_out);
245 eventq_queue_out = NULL;
246 }
247 }
248
249 /*
250 * Register IPv4 and IPv6 netinfo functions and initialize queues for inject.
251 */
252 void
ip_net_init(ip_stack_t * ipst,netstack_t * ns)253 ip_net_init(ip_stack_t *ipst, netstack_t *ns)
254 {
255 netid_t id;
256
257 id = net_getnetidbynetstackid(ns->netstack_stackid);
258 ASSERT(id != -1);
259
260 ipst->ips_ipv4_net_data = net_protocol_register(id, &ipv4info);
261 ASSERT(ipst->ips_ipv4_net_data != NULL);
262
263 ipst->ips_ipv6_net_data = net_protocol_register(id, &ipv6info);
264 ASSERT(ipst->ips_ipv6_net_data != NULL);
265
266 ipst->ips_arp_net_data = net_protocol_register(id, &arp_netinfo);
267 ASSERT(ipst->ips_ipv6_net_data != NULL);
268 }
269
270
271 /*
272 * Unregister IPv4 and IPv6 functions.
273 */
274 void
ip_net_destroy(ip_stack_t * ipst)275 ip_net_destroy(ip_stack_t *ipst)
276 {
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;
280 }
281
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;
285 }
286
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;
290 }
291 }
292
293 /*
294 * Initialize IPv4 hooks family the event
295 */
296 void
ipv4_hook_init(ip_stack_t * ipst)297 ipv4_hook_init(ip_stack_t *ipst)
298 {
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");
304 }
305
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");
312 }
313
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");
320 }
321
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");
328 }
329
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");
336 }
337
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");
344 }
345
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");
353 }
354
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");
362 }
363
364 }
365
366 void
ipv4_hook_shutdown(ip_stack_t * ipst)367 ipv4_hook_shutdown(ip_stack_t *ipst)
368 {
369 if (ipst->ips_ipv4firewall_forwarding != NULL) {
370 (void) net_event_shutdown(ipst->ips_ipv4_net_data,
371 &ipst->ips_ip4_forwarding_event);
372 }
373
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);
377 }
378
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);
382 }
383
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);
387 }
388
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);
392 }
393
394 if (ipst->ips_ipv4nicevents != NULL) {
395 (void) net_event_shutdown(ipst->ips_ipv4_net_data,
396 &ipst->ips_ip4_nic_events);
397 }
398
399 if (ipst->ips_ipv4observing != NULL) {
400 (void) net_event_shutdown(ipst->ips_ipv4_net_data,
401 &ipst->ips_ip4_observe);
402 }
403
404 (void) net_family_shutdown(ipst->ips_ipv4_net_data,
405 &ipst->ips_ipv4root);
406 }
407
408 void
ipv4_hook_destroy(ip_stack_t * ipst)409 ipv4_hook_destroy(ip_stack_t *ipst)
410 {
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;
415 }
416
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;
421 }
422
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;
427 }
428
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;
433 }
434
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;
439 }
440
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;
445 }
446
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;
451 }
452
453 (void) net_family_unregister(ipst->ips_ipv4_net_data,
454 &ipst->ips_ipv4root);
455 }
456
457 /*
458 * Initialize IPv6 hooks family and event
459 */
460 void
ipv6_hook_init(ip_stack_t * ipst)461 ipv6_hook_init(ip_stack_t *ipst)
462 {
463
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");
469 }
470
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");
477 }
478
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");
485 }
486
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");
493 }
494
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");
501 }
502
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");
509 }
510
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");
518 }
519
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");
527 }
528 }
529
530 void
ipv6_hook_shutdown(ip_stack_t * ipst)531 ipv6_hook_shutdown(ip_stack_t *ipst)
532 {
533 if (ipst->ips_ipv6firewall_forwarding != NULL) {
534 (void) net_event_shutdown(ipst->ips_ipv6_net_data,
535 &ipst->ips_ip6_forwarding_event);
536 }
537
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);
541 }
542
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);
546 }
547
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);
551 }
552
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);
556 }
557
558 if (ipst->ips_ipv6nicevents != NULL) {
559 (void) net_event_shutdown(ipst->ips_ipv6_net_data,
560 &ipst->ips_ip6_nic_events);
561 }
562
563 if (ipst->ips_ipv6observing != NULL) {
564 (void) net_event_shutdown(ipst->ips_ipv6_net_data,
565 &ipst->ips_ip6_observe);
566 }
567
568 (void) net_family_shutdown(ipst->ips_ipv6_net_data,
569 &ipst->ips_ipv6root);
570 }
571
572 void
ipv6_hook_destroy(ip_stack_t * ipst)573 ipv6_hook_destroy(ip_stack_t *ipst)
574 {
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;
579 }
580
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;
585 }
586
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;
591 }
592
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;
597 }
598
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;
603 }
604
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;
609 }
610
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;
615 }
616
617 (void) net_family_unregister(ipst->ips_ipv6_net_data,
618 &ipst->ips_ipv6root);
619 }
620
621 /*
622 * Determine the name of an IPv4 interface
623 */
624 static int
ip_getifname(net_handle_t neti,phy_if_t phy_ifdata,char * buffer,const size_t buflen)625 ip_getifname(net_handle_t neti, phy_if_t phy_ifdata, char *buffer,
626 const size_t buflen)
627 {
628 return (ip_getifname_impl(phy_ifdata, buffer, buflen, B_FALSE,
629 neti->netd_stack->nts_netstack->netstack_ip));
630 }
631
632 /*
633 * Determine the name of an IPv6 interface
634 */
635 static int
ipv6_getifname(net_handle_t neti,phy_if_t phy_ifdata,char * buffer,const size_t buflen)636 ipv6_getifname(net_handle_t neti, phy_if_t phy_ifdata, char *buffer,
637 const size_t buflen)
638 {
639 return (ip_getifname_impl(phy_ifdata, buffer, buflen, B_TRUE,
640 neti->netd_stack->nts_netstack->netstack_ip));
641 }
642
643 /*
644 * Shared implementation to determine the name of a given network interface
645 */
646 /* ARGSUSED */
647 static int
ip_getifname_impl(phy_if_t phy_ifdata,char * buffer,const size_t buflen,boolean_t isv6,ip_stack_t * ipst)648 ip_getifname_impl(phy_if_t phy_ifdata,
649 char *buffer, const size_t buflen, boolean_t isv6, ip_stack_t *ipst)
650 {
651 ill_t *ill;
652
653 ASSERT(buffer != NULL);
654
655 ill = ill_lookup_on_ifindex((uint_t)phy_ifdata, isv6, ipst);
656 if (ill == NULL)
657 return (1);
658
659 (void) strlcpy(buffer, ill->ill_name, buflen);
660 ill_refrele(ill);
661 return (0);
662 }
663
664 /*
665 * Determine the MTU of an IPv4 network interface
666 */
667 static int
ip_getmtu(net_handle_t neti,phy_if_t phy_ifdata,lif_if_t ifdata)668 ip_getmtu(net_handle_t neti, phy_if_t phy_ifdata, lif_if_t ifdata)
669 {
670 netstack_t *ns;
671
672 ns = neti->netd_stack->nts_netstack;
673 ASSERT(ns != NULL);
674 return (ip_getmtu_impl(phy_ifdata, ifdata, B_FALSE, ns->netstack_ip));
675 }
676
677 /*
678 * Determine the MTU of an IPv6 network interface
679 */
680 static int
ipv6_getmtu(net_handle_t neti,phy_if_t phy_ifdata,lif_if_t ifdata)681 ipv6_getmtu(net_handle_t neti, phy_if_t phy_ifdata, lif_if_t ifdata)
682 {
683 netstack_t *ns;
684
685 ns = neti->netd_stack->nts_netstack;
686 ASSERT(ns != NULL);
687 return (ip_getmtu_impl(phy_ifdata, ifdata, B_TRUE, ns->netstack_ip));
688 }
689
690 /*
691 * Shared implementation to determine the MTU of a network interface
692 */
693 /* ARGSUSED */
694 static int
ip_getmtu_impl(phy_if_t phy_ifdata,lif_if_t ifdata,boolean_t isv6,ip_stack_t * ipst)695 ip_getmtu_impl(phy_if_t phy_ifdata, lif_if_t ifdata, boolean_t isv6,
696 ip_stack_t *ipst)
697 {
698 lif_if_t ipifid;
699 ipif_t *ipif;
700 int mtu;
701
702 ipifid = UNMAP_IPIF_ID(ifdata);
703
704 ipif = ipif_getby_indexes((uint_t)phy_ifdata, (uint_t)ipifid,
705 isv6, ipst);
706 if (ipif == NULL)
707 return (0);
708
709 mtu = ipif->ipif_ill->ill_mtu;
710 ipif_refrele(ipif);
711
712 if (mtu == 0) {
713 ill_t *ill;
714
715 if ((ill = ill_lookup_on_ifindex((uint_t)phy_ifdata, isv6,
716 ipst)) == NULL) {
717 return (0);
718 }
719 mtu = ill->ill_mtu;
720 ill_refrele(ill);
721 }
722
723 return (mtu);
724 }
725
726 /*
727 * Determine if path MTU discovery is enabled for IP
728 */
729 static int
ip_getpmtuenabled(net_handle_t neti)730 ip_getpmtuenabled(net_handle_t neti)
731 {
732 netstack_t *ns;
733
734 ns = neti->netd_stack->nts_netstack;
735 ASSERT(ns != NULL);
736 return (ns->netstack_ip->ips_ip_path_mtu_discovery);
737 }
738
739 /*
740 * Get next interface from the current list of IPv4 physical network interfaces
741 */
742 static phy_if_t
ip_phygetnext(net_handle_t neti,phy_if_t phy_ifdata)743 ip_phygetnext(net_handle_t neti, phy_if_t phy_ifdata)
744 {
745 netstack_t *ns;
746
747 ns = neti->netd_stack->nts_netstack;
748 ASSERT(ns != NULL);
749 return (ill_get_next_ifindex(phy_ifdata, B_FALSE, ns->netstack_ip));
750 }
751
752 /*
753 * Get next interface from the current list of IPv6 physical network interfaces
754 */
755 static phy_if_t
ipv6_phygetnext(net_handle_t neti,phy_if_t phy_ifdata)756 ipv6_phygetnext(net_handle_t neti, phy_if_t phy_ifdata)
757 {
758 netstack_t *ns;
759
760 ns = neti->netd_stack->nts_netstack;
761 ASSERT(ns != NULL);
762 return (ill_get_next_ifindex(phy_ifdata, B_TRUE, ns->netstack_ip));
763 }
764
765 /*
766 * Determine if a network interface name exists for IPv4
767 */
768 static phy_if_t
ip_phylookup(net_handle_t neti,const char * name)769 ip_phylookup(net_handle_t neti, const char *name)
770 {
771 netstack_t *ns;
772
773 ns = neti->netd_stack->nts_netstack;
774 ASSERT(ns != NULL);
775 return (ip_phylookup_impl(name, B_FALSE, ns->netstack_ip));
776 }
777
778 /*
779 * Determine if a network interface name exists for IPv6
780 */
781 static phy_if_t
ipv6_phylookup(net_handle_t neti,const char * name)782 ipv6_phylookup(net_handle_t neti, const char *name)
783 {
784 netstack_t *ns;
785
786 ns = neti->netd_stack->nts_netstack;
787 ASSERT(ns != NULL);
788 return (ip_phylookup_impl(name, B_TRUE, ns->netstack_ip));
789 }
790
791 /*
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.
795 */
796 static phy_if_t
ip_phylookup_impl(const char * name,boolean_t isv6,ip_stack_t * ipst)797 ip_phylookup_impl(const char *name, boolean_t isv6, ip_stack_t *ipst)
798 {
799 phy_if_t phy;
800 ill_t *ill;
801
802 ill = ill_lookup_on_name((char *)name, B_FALSE, isv6, NULL, ipst);
803 if (ill == NULL)
804 return (0);
805
806 phy = ill->ill_phyint->phyint_ifindex;
807
808 ill_refrele(ill);
809
810 return (phy);
811 }
812
813 /*
814 * Get next interface from the current list of IPv4 logical network interfaces
815 */
816 static lif_if_t
ip_lifgetnext(net_handle_t neti,phy_if_t phy_ifdata,lif_if_t ifdata)817 ip_lifgetnext(net_handle_t neti, phy_if_t phy_ifdata, lif_if_t ifdata)
818 {
819 netstack_t *ns;
820
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));
825 }
826
827 /*
828 * Get next interface from the current list of IPv6 logical network interfaces
829 */
830 static lif_if_t
ipv6_lifgetnext(net_handle_t neti,phy_if_t phy_ifdata,lif_if_t ifdata)831 ipv6_lifgetnext(net_handle_t neti, phy_if_t phy_ifdata, lif_if_t ifdata)
832 {
833 netstack_t *ns;
834
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));
839 }
840
841 /*
842 * Shared implementation to get next interface from the current list of
843 * logical network interfaces
844 */
845 static lif_if_t
ip_lifgetnext_impl(phy_if_t phy_ifdata,lif_if_t ifdata,boolean_t isv6,ip_stack_t * ipst)846 ip_lifgetnext_impl(phy_if_t phy_ifdata, lif_if_t ifdata, boolean_t isv6,
847 ip_stack_t *ipst)
848 {
849 lif_if_t newidx, oldidx;
850 boolean_t nextok;
851 ipif_t *ipif;
852 ill_t *ill;
853
854 ill = ill_lookup_on_ifindex(phy_ifdata, isv6, ipst);
855 if (ill == NULL)
856 return (0);
857
858 if (ifdata != 0) {
859 oldidx = UNMAP_IPIF_ID(ifdata);
860 nextok = B_FALSE;
861 } else {
862 oldidx = 0;
863 nextok = B_TRUE;
864 }
865
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);
871 }
872
873 /*
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.
877 */
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;
886 }
887 }
888
889 mutex_exit(&ill->ill_lock);
890 ill_refrele(ill);
891
892 if (ipif == NULL)
893 return (0);
894
895 newidx = ipif->ipif_id;
896 ipif_refrele(ipif);
897
898 return (MAP_IPIF_ID(newidx));
899 }
900
901 /*
902 * Inject an IPv4 packet to or from an interface
903 */
904 static int
ip_inject(net_handle_t neti,inject_t style,net_inject_t * packet)905 ip_inject(net_handle_t neti, inject_t style, net_inject_t *packet)
906 {
907 netstack_t *ns;
908
909 ns = neti->netd_stack->nts_netstack;
910 ASSERT(ns != NULL);
911 return (ip_inject_impl(style, packet, B_FALSE, ns->netstack_ip));
912 }
913
914
915 /*
916 * Inject an IPv6 packet to or from an interface
917 */
918 static int
ipv6_inject(net_handle_t neti,inject_t style,net_inject_t * packet)919 ipv6_inject(net_handle_t neti, inject_t style, net_inject_t *packet)
920 {
921 netstack_t *ns;
922
923 ns = neti->netd_stack->nts_netstack;
924 return (ip_inject_impl(style, packet, B_TRUE, ns->netstack_ip));
925 }
926
927 /*
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
933 */
934 static int
ip_inject_impl(inject_t style,net_inject_t * packet,boolean_t isv6,ip_stack_t * ipst)935 ip_inject_impl(inject_t style, net_inject_t *packet, boolean_t isv6,
936 ip_stack_t *ipst)
937 {
938 ddi_taskq_t *tq = NULL;
939 void (* func)(void *);
940 injection_t *inject;
941 mblk_t *mp;
942
943 ASSERT(packet != NULL);
944 ASSERT(packet->ni_packet != NULL);
945 ASSERT(packet->ni_packet->b_datap->db_type == M_DATA);
946
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;
954 /*
955 * deliver up into the kernel, immitating its reception by a
956 * network interface, add to list and schedule timeout
957 */
958 func = ip_ni_queue_in_func;
959 tq = eventq_queue_in;
960 break;
961
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;
968 /*
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
972 */
973 func = ip_ni_queue_out_func;
974 tq = eventq_queue_out;
975 break;
976
977 case NI_DIRECT_OUT: {
978 struct sockaddr *sock;
979
980 mp = packet->ni_packet;
981
982 sock = (struct sockaddr *)&packet->ni_addr;
983 /*
984 * ipfil_sendpkt was provided by surya to ease the
985 * problems associated with sending out a packet.
986 */
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);
998 }
999 /* NOTREACHED */
1000 }
1001 default:
1002 freemsg(packet->ni_packet);
1003 return (1);
1004 }
1005
1006 ASSERT(tq != NULL);
1007
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);
1014 }
1015 return (0);
1016 }
1017
1018 /*
1019 * Find the interface used for traffic to a given IPv4 address
1020 */
1021 static phy_if_t
ip_routeto(net_handle_t neti,struct sockaddr * address,struct sockaddr * next)1022 ip_routeto(net_handle_t neti, struct sockaddr *address, struct sockaddr *next)
1023 {
1024 netstack_t *ns;
1025
1026 ASSERT(address != NULL);
1027
1028 if (address->sa_family != AF_INET)
1029 return (0);
1030
1031 ns = neti->netd_stack->nts_netstack;
1032 ASSERT(ns != NULL);
1033
1034 return (ip_routeto_impl(address, next, ns->netstack_ip));
1035 }
1036
1037 /*
1038 * Find the interface used for traffic to a given IPv6 address
1039 */
1040 static phy_if_t
ipv6_routeto(net_handle_t neti,struct sockaddr * address,struct sockaddr * next)1041 ipv6_routeto(net_handle_t neti, struct sockaddr *address, struct sockaddr *next)
1042 {
1043 netstack_t *ns;
1044
1045 ASSERT(address != NULL);
1046
1047 if (address->sa_family != AF_INET6)
1048 return (0);
1049
1050 ns = neti->netd_stack->nts_netstack;
1051 ASSERT(ns != NULL);
1052
1053 return (ip_routeto_impl(address, next, ns->netstack_ip));
1054 }
1055
1056
1057 /*
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.
1062 */
1063 static phy_if_t
ip_routeto_impl(struct sockaddr * address,struct sockaddr * nexthop,ip_stack_t * ipst)1064 ip_routeto_impl(struct sockaddr *address, struct sockaddr *nexthop,
1065 ip_stack_t *ipst)
1066 {
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;
1075
1076 zoneid = netstackid_to_zoneid(ipst->ips_netstack->netstack_stackid);
1077
1078 if (address->sa_family == AF_INET6) {
1079 ire = ire_route_recursive_v6(&sin6->sin6_addr, 0, NULL,
1080 zoneid, NULL, MATCH_IRE_DSTONLY, IRR_ALLOCATE, 0, ipst,
1081 NULL, NULL, NULL);
1082 } else {
1083 ire = ire_route_recursive_v4(sin->sin_addr.s_addr, 0, NULL,
1084 zoneid, NULL, MATCH_IRE_DSTONLY, IRR_ALLOCATE, 0, ipst,
1085 NULL, NULL, NULL);
1086 }
1087 ASSERT(ire != NULL);
1088 /*
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.
1092 */
1093 if (ire->ire_flags & (RTF_REJECT|RTF_BLACKHOLE)) {
1094 ire_refrele(ire);
1095 return (NULL);
1096 }
1097
1098 nexthop_ire = ire_nexthop(ire);
1099 if (nexthop_ire == NULL) {
1100 ire_refrele(ire);
1101 return (0);
1102 }
1103 if (nexthop_ire->ire_flags & (RTF_REJECT|RTF_BLACKHOLE)) {
1104 ire_refrele(nexthop_ire);
1105 ire_refrele(ire);
1106 return (0);
1107 }
1108
1109 ASSERT(nexthop_ire->ire_ill != NULL);
1110
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;
1116 }
1117 }
1118
1119 phy_if = (phy_if_t)nexthop_ire->ire_ill->ill_phyint->phyint_ifindex;
1120 ire_refrele(ire);
1121 ire_refrele(nexthop_ire);
1122
1123 return (phy_if);
1124 }
1125
1126 /*
1127 * Determine if checksumming is being used for the given packet.
1128 *
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
1134 */
1135 /*ARGSUSED*/
1136 static int
ip_ispartialchecksum(net_handle_t neti,mblk_t * mp)1137 ip_ispartialchecksum(net_handle_t neti, mblk_t *mp)
1138 {
1139 int ret = 0;
1140
1141 ASSERT(mp != NULL);
1142
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;
1147 }
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;
1152 }
1153
1154 return (ret);
1155 }
1156
1157 /*
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.
1161 *
1162 * Return:
1163 * 0: the checksum was incorrect
1164 * 1: the original checksum was correct
1165 */
1166 /*ARGSUSED*/
1167 static int
ip_isvalidchecksum(net_handle_t neti,mblk_t * mp)1168 ip_isvalidchecksum(net_handle_t neti, mblk_t *mp)
1169 {
1170 unsigned char *wptr;
1171 ipha_t *ipha = (ipha_t *)mp->b_rptr;
1172 int hlen;
1173 int ret;
1174
1175 ASSERT(mp != NULL);
1176
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);
1183
1184 hlen = (ipha->ipha_version_and_hdr_length & 0x0F) << 2;
1185
1186 /*
1187 * Check that the mblk being passed in has enough data in it
1188 * before blindly checking ip_cksum.
1189 */
1190 if (msgdsize(mp) < hlen)
1191 return (0);
1192
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;
1200 }
1201
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;
1207
1208 return (ret);
1209 }
1210
1211 /*
1212 * Unsupported with IPv6
1213 */
1214 /*ARGSUSED*/
1215 static int
ipv6_isvalidchecksum(net_handle_t neti,mblk_t * mp)1216 ipv6_isvalidchecksum(net_handle_t neti, mblk_t *mp)
1217 {
1218 return (-1);
1219 }
1220
1221 /*
1222 * Determine the network addresses for an IPv4 interface
1223 */
1224 static int
ip_getlifaddr(net_handle_t neti,phy_if_t phy_ifdata,lif_if_t ifdata,size_t nelem,net_ifaddr_t type[],void * storage)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)
1227 {
1228 netstack_t *ns;
1229
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));
1234 }
1235
1236 /*
1237 * Determine the network addresses for an IPv6 interface
1238 */
1239 static int
ipv6_getlifaddr(net_handle_t neti,phy_if_t phy_ifdata,lif_if_t ifdata,size_t nelem,net_ifaddr_t type[],void * storage)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)
1242 {
1243 netstack_t *ns;
1244
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));
1249 }
1250
1251 /*
1252 * Shared implementation to determine the network addresses for an interface
1253 */
1254 /* ARGSUSED */
1255 static int
ip_getlifaddr_impl(sa_family_t family,phy_if_t phy_ifdata,lif_if_t ifdata,size_t nelem,net_ifaddr_t type[],struct sockaddr * storage,ip_stack_t * ipst)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)
1259 {
1260 struct sockaddr_in6 *sin6;
1261 struct sockaddr_in *sin;
1262 lif_if_t ipifid;
1263 ipif_t *ipif;
1264 int i;
1265
1266 ASSERT(type != NULL);
1267 ASSERT(storage != NULL);
1268
1269 ipifid = UNMAP_IPIF_ID(ifdata);
1270
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);
1275
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);
1284 }
1285 sin->sin_family = AF_INET;
1286 }
1287 } else {
1288 if ((ipif = ipif_getby_indexes((uint_t)phy_ifdata,
1289 (uint_t)ipifid, B_TRUE, ipst)) == NULL)
1290 return (1);
1291
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);
1300 }
1301 sin6->sin6_family = AF_INET6;
1302 }
1303 }
1304 ipif_refrele(ipif);
1305 return (0);
1306 }
1307
1308 /*
1309 * ip_getlifaddr private function
1310 */
1311 static int
ip_getifaddr_type(sa_family_t family,ipif_t * ill_ipif,lif_if_t type,void * storage)1312 ip_getifaddr_type(sa_family_t family, ipif_t *ill_ipif,
1313 lif_if_t type, void *storage)
1314 {
1315 void *src_addr;
1316 int mem_size;
1317
1318 ASSERT(ill_ipif != NULL);
1319 ASSERT(storage != NULL);
1320
1321 if (family == AF_INET) {
1322 mem_size = sizeof (struct in_addr);
1323
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*/
1340 }
1341 } else {
1342 mem_size = sizeof (struct in6_addr);
1343
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*/
1360 }
1361 }
1362
1363 (void) memcpy(storage, src_addr, mem_size);
1364 return (1);
1365 }
1366
1367 /*
1368 * Shared implementation to determine the zoneid associated with an IPv4/IPv6
1369 * address
1370 */
1371 static int
ip_getlifzone_impl(sa_family_t family,phy_if_t phy_ifdata,lif_if_t ifdata,ip_stack_t * ipst,zoneid_t * zoneid)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)
1374 {
1375 ipif_t *ipif;
1376
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);
1384 }
1385
1386 /*
1387 * Determine the zoneid associated with an IPv4 address
1388 */
1389 static int
ip_getlifzone(net_handle_t neti,phy_if_t phy_ifdata,lif_if_t ifdata,zoneid_t * zoneid)1390 ip_getlifzone(net_handle_t neti, phy_if_t phy_ifdata, lif_if_t ifdata,
1391 zoneid_t *zoneid)
1392 {
1393 return (ip_getlifzone_impl(AF_INET, phy_ifdata, ifdata,
1394 neti->netd_stack->nts_netstack->netstack_ip, zoneid));
1395 }
1396
1397 /*
1398 * Determine the zoneid associated with an IPv6 address
1399 */
1400 static int
ipv6_getlifzone(net_handle_t neti,phy_if_t phy_ifdata,lif_if_t ifdata,zoneid_t * zoneid)1401 ipv6_getlifzone(net_handle_t neti, phy_if_t phy_ifdata, lif_if_t ifdata,
1402 zoneid_t *zoneid)
1403 {
1404 return (ip_getlifzone_impl(AF_INET6, phy_ifdata, ifdata,
1405 neti->netd_stack->nts_netstack->netstack_ip, zoneid));
1406 }
1407
1408 /*
1409 * The behaviour here mirrors that for the SIOCFLIFFLAGS ioctl where the
1410 * union of all of the relevant flags is returned.
1411 */
1412 static int
ip_getlifflags_impl(sa_family_t family,phy_if_t phy_ifdata,lif_if_t ifdata,ip_stack_t * ipst,uint64_t * flags)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)
1415 {
1416 phyint_t *phyi;
1417 ipif_t *ipif;
1418 ill_t *ill;
1419
1420 ill = ill_lookup_on_ifindex(phy_ifdata, (family == AF_INET6), ipst);
1421 if (ill == NULL)
1422 return (-1);
1423 phyi = ill->ill_phyint;
1424
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);
1430 }
1431 *flags = ipif->ipif_flags | ill->ill_flags | phyi->phyint_flags;
1432 ipif_refrele(ipif);
1433 ill_refrele(ill);
1434 return (0);
1435 }
1436
1437 static int
ip_getlifflags(net_handle_t neti,phy_if_t phy_ifdata,lif_if_t ifdata,uint64_t * flags)1438 ip_getlifflags(net_handle_t neti, phy_if_t phy_ifdata, lif_if_t ifdata,
1439 uint64_t *flags)
1440 {
1441 return (ip_getlifflags_impl(AF_INET, phy_ifdata, ifdata,
1442 neti->netd_stack->nts_netstack->netstack_ip, flags));
1443 }
1444
1445 static int
ipv6_getlifflags(net_handle_t neti,phy_if_t phy_ifdata,lif_if_t ifdata,uint64_t * flags)1446 ipv6_getlifflags(net_handle_t neti, phy_if_t phy_ifdata, lif_if_t ifdata,
1447 uint64_t *flags)
1448 {
1449 return (ip_getlifflags_impl(AF_INET6, phy_ifdata, ifdata,
1450 neti->netd_stack->nts_netstack->netstack_ip, flags));
1451 }
1452
1453 /*
1454 * Deliver packet up into the kernel, immitating its reception by a
1455 * network interface.
1456 */
1457 static void
ip_ni_queue_in_func(void * inject)1458 ip_ni_queue_in_func(void *inject)
1459 {
1460 ip_ni_queue_func_impl(inject, B_FALSE);
1461 }
1462
1463 /*
1464 * Deliver out of the kernel, as if it were being sent via a
1465 * raw socket so that IPFilter will see it again.
1466 */
1467 static void
ip_ni_queue_out_func(void * inject)1468 ip_ni_queue_out_func(void *inject)
1469 {
1470 ip_ni_queue_func_impl(inject, B_TRUE);
1471 }
1472
1473 /*
1474 * Shared implementation for inject via ip_output and ip_input
1475 */
1476 static void
ip_ni_queue_func_impl(injection_t * inject,boolean_t out)1477 ip_ni_queue_func_impl(injection_t *inject, boolean_t out)
1478 {
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;
1483
1484 ASSERT(inject != NULL);
1485 packet = &inject->inj_data;
1486 ASSERT(packet->ni_packet != NULL);
1487
1488 if (out == 0) {
1489 ill = ill_lookup_on_ifindex((uint_t)packet->ni_physical,
1490 inject->inj_isv6, ipst);
1491
1492 if (ill == NULL) {
1493 kmem_free(inject, sizeof (*inject));
1494 return;
1495 }
1496
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);
1501 }
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;
1511 }
1512 ixas.ixa_flags &= ~IXAF_VERIFY_SOURCE;
1513 (void) ip_output_simple(packet->ni_packet, &ixas);
1514 ixa_cleanup(&ixas);
1515 }
1516
1517 kmem_free(inject, sizeof (*inject));
1518 }
1519
1520 /*
1521 * taskq function for nic events.
1522 */
1523 void
ip_ne_queue_func(void * arg)1524 ip_ne_queue_func(void *arg)
1525 {
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;
1530
1531 ns = netstack_find_by_stackid(info->hnei_stackid);
1532 if (ns == NULL)
1533 goto done;
1534
1535 ipst = ns->netstack_ip;
1536 if (ipst == NULL)
1537 goto done;
1538
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);
1543
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));
1549 }
1550
1551 /*
1552 * Initialize ARP hook family and events
1553 */
1554 void
arp_hook_init(ip_stack_t * ipst)1555 arp_hook_init(ip_stack_t *ipst)
1556 {
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");
1562 }
1563
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");
1570 }
1571
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");
1578 }
1579
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");
1586 }
1587 }
1588
1589 void
arp_hook_destroy(ip_stack_t * ipst)1590 arp_hook_destroy(ip_stack_t *ipst)
1591 {
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;
1596 }
1597
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;
1602 }
1603
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;
1608 }
1609
1610 (void) net_family_unregister(ipst->ips_arp_net_data,
1611 &ipst->ips_arproot);
1612 }
1613
1614 void
arp_hook_shutdown(ip_stack_t * ipst)1615 arp_hook_shutdown(ip_stack_t *ipst)
1616 {
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);
1620 }
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);
1624 }
1625 if (ipst->ips_arpnicevents != NULL) {
1626 (void) net_event_shutdown(ipst->ips_arp_net_data,
1627 &ipst->ips_arp_nic_events);
1628 }
1629 }
1630
1631 /* netinfo routines for the unsupported cases */
1632
1633 /* ARGSUSED */
1634 int
net_no_getmtu(net_handle_t handle,phy_if_t phy_ifdata,lif_if_t ifdata)1635 net_no_getmtu(net_handle_t handle, phy_if_t phy_ifdata, lif_if_t ifdata)
1636 {
1637 return (-1);
1638 }
1639
1640 /* ARGSUSED */
1641 static int
net_no_getpmtuenabled(net_handle_t neti)1642 net_no_getpmtuenabled(net_handle_t neti)
1643 {
1644 return (-1);
1645 }
1646
1647 /* ARGSUSED */
1648 static lif_if_t
net_no_lifgetnext(net_handle_t neti,phy_if_t phy_ifdata,lif_if_t ifdata)1649 net_no_lifgetnext(net_handle_t neti, phy_if_t phy_ifdata, lif_if_t ifdata)
1650 {
1651 return (-1);
1652 }
1653
1654 /* ARGSUSED */
1655 static int
net_no_inject(net_handle_t neti,inject_t style,net_inject_t * packet)1656 net_no_inject(net_handle_t neti, inject_t style, net_inject_t *packet)
1657 {
1658 return (-1);
1659 }
1660
1661 /* ARGSUSED */
1662 static phy_if_t
net_no_routeto(net_handle_t neti,struct sockaddr * address,struct sockaddr * next)1663 net_no_routeto(net_handle_t neti, struct sockaddr *address,
1664 struct sockaddr *next)
1665 {
1666 return ((phy_if_t)-1);
1667 }
1668
1669 /* ARGSUSED */
1670 static int
net_no_ispartialchecksum(net_handle_t neti,mblk_t * mp)1671 net_no_ispartialchecksum(net_handle_t neti, mblk_t *mp)
1672 {
1673 return (-1);
1674 }
1675
1676 /* ARGSUSED */
1677 static int
net_no_getlifaddr(net_handle_t neti,phy_if_t phy_ifdata,lif_if_t ifdata,size_t nelem,net_ifaddr_t type[],void * storage)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)
1680 {
1681 return (-1);
1682 }
1683
1684 /* ARGSUSED */
1685 static int
net_no_getlifzone(net_handle_t neti,phy_if_t phy_ifdata,lif_if_t ifdata,zoneid_t * zoneid)1686 net_no_getlifzone(net_handle_t neti, phy_if_t phy_ifdata, lif_if_t ifdata,
1687 zoneid_t *zoneid)
1688 {
1689 return (-1);
1690 }
1691
1692 /* ARGSUSED */
1693 static int
net_no_getlifflags(net_handle_t neti,phy_if_t phy_ifdata,lif_if_t ifdata,uint64_t * flags)1694 net_no_getlifflags(net_handle_t neti, phy_if_t phy_ifdata, lif_if_t ifdata,
1695 uint64_t *flags)
1696 {
1697 return (-1);
1698 }
1699