]> git.saurik.com Git - apple/xnu.git/blob - bsd/net/if_stf.c
xnu-1228.0.2.tar.gz
[apple/xnu.git] / bsd / net / if_stf.c
1 /* $FreeBSD: src/sys/net/if_stf.c,v 1.1.2.6 2001/07/24 19:10:18 brooks Exp $ */
2 /* $KAME: if_stf.c,v 1.62 2001/06/07 22:32:16 itojun Exp $ */
3
4 /*
5 * Copyright (C) 2000 WIDE Project.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the project nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32 /*
33 * NOTICE: This file was modified by SPARTA, Inc. in 2006 to introduce
34 * support for mandatory and extensible security protections. This notice
35 * is included in support of clause 2.2 (b) of the Apple Public License,
36 * Version 2.0.
37 */
38
39 /*
40 * 6to4 interface, based on RFC3056.
41 *
42 * 6to4 interface is NOT capable of link-layer (I mean, IPv4) multicasting.
43 * There is no address mapping defined from IPv6 multicast address to IPv4
44 * address. Therefore, we do not have IFF_MULTICAST on the interface.
45 *
46 * Due to the lack of address mapping for link-local addresses, we cannot
47 * throw packets toward link-local addresses (fe80::x). Also, we cannot throw
48 * packets to link-local multicast addresses (ff02::x).
49 *
50 * Here are interesting symptoms due to the lack of link-local address:
51 *
52 * Unicast routing exchange:
53 * - RIPng: Impossible. Uses link-local multicast packet toward ff02::9,
54 * and link-local addresses as nexthop.
55 * - OSPFv6: Impossible. OSPFv6 assumes that there's link-local address
56 * assigned to the link, and makes use of them. Also, HELLO packets use
57 * link-local multicast addresses (ff02::5 and ff02::6).
58 * - BGP4+: Maybe. You can only use global address as nexthop, and global
59 * address as TCP endpoint address.
60 *
61 * Multicast routing protocols:
62 * - PIM: Hello packet cannot be used to discover adjacent PIM routers.
63 * Adjacent PIM routers must be configured manually (is it really spec-wise
64 * correct thing to do?).
65 *
66 * ICMPv6:
67 * - Redirects cannot be used due to the lack of link-local address.
68 *
69 * stf interface does not have, and will not need, a link-local address.
70 * It seems to have no real benefit and does not help the above symptoms much.
71 * Even if we assign link-locals to interface, we cannot really
72 * use link-local unicast/multicast on top of 6to4 cloud (since there's no
73 * encapsulation defined for link-local address), and the above analysis does
74 * not change. RFC3056 does not mandate the assignment of link-local address
75 * either.
76 *
77 * 6to4 interface has security issues. Refer to
78 * http://playground.iijlab.net/i-d/draft-itojun-ipv6-transition-abuse-00.txt
79 * for details. The code tries to filter out some of malicious packets.
80 * Note that there is no way to be 100% secure.
81 */
82
83 #include <sys/param.h>
84 #include <sys/systm.h>
85 #include <sys/socket.h>
86 #include <sys/sockio.h>
87 #include <sys/mbuf.h>
88 #include <sys/errno.h>
89 #include <sys/protosw.h>
90 #include <sys/kernel.h>
91 #include <sys/syslog.h>
92
93 #include <sys/malloc.h>
94
95 #include <net/if.h>
96 #include <net/route.h>
97 #include <net/if_types.h>
98
99 #include <netinet/in.h>
100 #include <netinet/in_systm.h>
101 #include <netinet/ip.h>
102 #include <netinet/ip_var.h>
103 #include <netinet/in_var.h>
104
105 #include <netinet/ip6.h>
106 #include <netinet6/ip6_var.h>
107 #include <netinet6/in6_var.h>
108 #include <netinet/ip_ecn.h>
109
110 #include <netinet/ip_encap.h>
111 #include <net/kpi_interface.h>
112 #include <net/kpi_protocol.h>
113
114
115 #include <net/net_osdep.h>
116
117 #include <net/bpf.h>
118
119 #if CONFIG_MACF_NET
120 #include <security/mac_framework.h>
121 #endif
122
123 #define IN6_IS_ADDR_6TO4(x) (ntohs((x)->s6_addr16[0]) == 0x2002)
124 #define GET_V4(x) ((const struct in_addr *)(&(x)->s6_addr16[1]))
125
126 struct stf_softc {
127 ifnet_t sc_if; /* common area */
128 u_long sc_protocol_family; /* dlil protocol attached */
129 union {
130 struct route __sc_ro4;
131 struct route_in6 __sc_ro6; /* just for safety */
132 } __sc_ro46;
133 #define sc_ro __sc_ro46.__sc_ro4
134 const struct encaptab *encap_cookie;
135 bpf_tap_mode tap_mode;
136 bpf_packet_func tap_callback;
137 };
138
139 void stfattach (void);
140
141 static int ip_stf_ttl = 40;
142
143 static void in_stf_input(struct mbuf *, int);
144 extern struct domain inetdomain;
145 struct protosw in_stf_protosw =
146 { SOCK_RAW, &inetdomain, IPPROTO_IPV6, PR_ATOMIC|PR_ADDR,
147 in_stf_input, NULL, NULL, rip_ctloutput,
148 NULL,
149 NULL, NULL, NULL, NULL,
150 NULL,
151 &rip_usrreqs,
152 NULL, rip_unlock, NULL, {NULL, NULL}, NULL, {0}
153 };
154
155 static int stf_encapcheck(const struct mbuf *, int, int, void *);
156 static struct in6_ifaddr *stf_getsrcifa6(struct ifnet *);
157 int stf_pre_output(struct ifnet *, protocol_family_t, struct mbuf **,
158 const struct sockaddr *, void *, char *, char *);
159 static int stf_checkaddr4(struct stf_softc *, const struct in_addr *,
160 struct ifnet *);
161 static int stf_checkaddr6(struct stf_softc *, struct in6_addr *,
162 struct ifnet *);
163 static void stf_rtrequest(int, struct rtentry *, struct sockaddr *);
164 static errno_t stf_ioctl(ifnet_t ifp, u_int32_t cmd, void *data);
165 static errno_t stf_output(ifnet_t ifp, mbuf_t m);
166
167 /*
168 * gif_input is the input handler for IP and IPv6 attached to gif
169 */
170 static errno_t
171 stf_media_input(
172 __unused ifnet_t ifp,
173 protocol_family_t protocol_family,
174 mbuf_t m,
175 __unused char *frame_header)
176 {
177 proto_input(protocol_family, m);
178
179 return (0);
180 }
181
182
183
184 static errno_t
185 stf_add_proto(
186 ifnet_t ifp,
187 protocol_family_t protocol_family,
188 __unused const struct ifnet_demux_desc *demux_array,
189 __unused u_int32_t demux_count)
190 {
191 /* Only one protocol may be attached at a time */
192 struct stf_softc* stf = ifnet_softc(ifp);
193 if (stf->sc_protocol_family == 0)
194 stf->sc_protocol_family = protocol_family;
195 else {
196 printf("stf_add_proto: stf already has a proto\n");
197 return EBUSY;
198 }
199
200 return 0;
201 }
202
203 static errno_t
204 stf_del_proto(
205 ifnet_t ifp,
206 protocol_family_t protocol_family)
207 {
208 if (((struct stf_softc*)ifnet_softc(ifp))->sc_protocol_family == protocol_family)
209 ((struct stf_softc*)ifnet_softc(ifp))->sc_protocol_family = 0;
210
211 return 0;
212 }
213
214 static errno_t
215 stf_attach_inet6(
216 ifnet_t ifp,
217 protocol_family_t protocol_family)
218 {
219 struct ifnet_attach_proto_param reg;
220 errno_t stat;
221
222 if (protocol_family != PF_INET6)
223 return EPROTONOSUPPORT;
224
225 bzero(&reg, sizeof(reg));
226 reg.input = stf_media_input;
227 reg.pre_output = stf_pre_output;
228
229 stat = ifnet_attach_protocol(ifp, protocol_family, &reg);
230 if (stat && stat != EEXIST) {
231 printf("stf_attach_proto_family can't attach interface fam=%d\n",
232 protocol_family);
233 }
234
235 return stat;
236 }
237
238 static errno_t
239 stf_demux(
240 ifnet_t ifp,
241 __unused mbuf_t m,
242 __unused char *frame_ptr,
243 protocol_family_t *protocol_family)
244 {
245 struct stf_softc* stf = ifnet_softc(ifp);
246 *protocol_family = stf->sc_protocol_family;
247 return 0;
248 }
249
250 static errno_t
251 stf_set_bpf_tap(
252 ifnet_t ifp,
253 bpf_tap_mode mode,
254 bpf_packet_func callback)
255 {
256 struct stf_softc *sc = ifnet_softc(ifp);
257
258 sc->tap_mode = mode;
259 sc->tap_callback = callback;
260
261 return 0;
262 }
263
264 void
265 stfattach(void)
266 {
267 struct stf_softc *sc;
268 int error;
269 const struct encaptab *p;
270 struct ifnet_init_params stf_init;
271
272 error = proto_register_plumber(PF_INET6, APPLE_IF_FAM_STF,
273 stf_attach_inet6, NULL);
274 if (error != 0)
275 printf("proto_register_plumber failed for AF_INET6 error=%d\n", error);
276
277 sc = _MALLOC(sizeof(struct stf_softc), M_DEVBUF, M_WAITOK);
278 if (sc == 0) {
279 printf("stf softc attach failed\n" );
280 return;
281 }
282
283 bzero(sc, sizeof(*sc));
284
285 p = encap_attach_func(AF_INET, IPPROTO_IPV6, stf_encapcheck,
286 &in_stf_protosw, sc);
287 if (p == NULL) {
288 printf("sftattach encap_attach_func failed\n");
289 FREE(sc, M_DEVBUF);
290 return;
291 }
292 sc->encap_cookie = p;
293
294 bzero(&stf_init, sizeof(stf_init));
295 stf_init.name = "stf";
296 stf_init.unit = 0;
297 stf_init.type = IFT_STF;
298 stf_init.family = IFNET_FAMILY_STF;
299 stf_init.output = stf_output;
300 stf_init.demux = stf_demux;
301 stf_init.add_proto = stf_add_proto;
302 stf_init.del_proto = stf_del_proto;
303 stf_init.softc = sc;
304 stf_init.ioctl = stf_ioctl;
305 stf_init.set_bpf_tap = stf_set_bpf_tap;
306
307 error = ifnet_allocate(&stf_init, &sc->sc_if);
308 if (error != 0) {
309 printf("stfattach, ifnet_allocate failed - %d\n", error);
310 encap_detach(sc->encap_cookie);
311 FREE(sc, M_DEVBUF);
312 return;
313 }
314 ifnet_set_mtu(sc->sc_if, IPV6_MMTU);
315 ifnet_set_flags(sc->sc_if, 0, 0xffff); /* clear all flags */
316 #if 0
317 /* turn off ingress filter */
318 ifnet_set_flags(sc->sc_if, IFF_LINK2, IFF_LINK2);
319 #endif
320
321 #if CONFIG_MACF_NET
322 mac_ifnet_label_init(&sc->sc_if);
323 #endif
324
325 error = ifnet_attach(sc->sc_if, NULL);
326 if (error != 0) {
327 printf("stfattach: ifnet_attach returned error=%d\n", error);
328 encap_detach(sc->encap_cookie);
329 ifnet_release(sc->sc_if);
330 FREE(sc, M_DEVBUF);
331 return;
332 }
333
334 bpfattach(sc->sc_if, DLT_NULL, sizeof(u_int));
335
336 return;
337 }
338
339 static int
340 stf_encapcheck(
341 const struct mbuf *m,
342 __unused int off,
343 int proto,
344 void *arg)
345 {
346 struct ip ip;
347 struct in6_ifaddr *ia6;
348 struct stf_softc *sc;
349 struct in_addr a, b;
350
351 sc = (struct stf_softc *)arg;
352 if (sc == NULL)
353 return 0;
354
355 if ((ifnet_flags(sc->sc_if) & IFF_UP) == 0)
356 return 0;
357
358 /* IFF_LINK0 means "no decapsulation" */
359 if ((ifnet_flags(sc->sc_if) & IFF_LINK0) != 0)
360 return 0;
361
362 if (proto != IPPROTO_IPV6)
363 return 0;
364
365 /* LINTED const cast */
366 mbuf_copydata(m, 0, sizeof(ip), &ip);
367
368 if (ip.ip_v != 4)
369 return 0;
370
371 ia6 = stf_getsrcifa6(sc->sc_if);
372 if (ia6 == NULL)
373 return 0;
374
375 /*
376 * check if IPv4 dst matches the IPv4 address derived from the
377 * local 6to4 address.
378 * success on: dst = 10.1.1.1, ia6->ia_addr = 2002:0a01:0101:...
379 */
380 if (bcmp(GET_V4(&ia6->ia_addr.sin6_addr), &ip.ip_dst,
381 sizeof(ip.ip_dst)) != 0)
382 return 0;
383
384 /*
385 * check if IPv4 src matches the IPv4 address derived from the
386 * local 6to4 address masked by prefixmask.
387 * success on: src = 10.1.1.1, ia6->ia_addr = 2002:0a00:.../24
388 * fail on: src = 10.1.1.1, ia6->ia_addr = 2002:0b00:.../24
389 */
390 bzero(&a, sizeof(a));
391 a.s_addr = GET_V4(&ia6->ia_addr.sin6_addr)->s_addr;
392 a.s_addr &= GET_V4(&ia6->ia_prefixmask.sin6_addr)->s_addr;
393 b = ip.ip_src;
394 b.s_addr &= GET_V4(&ia6->ia_prefixmask.sin6_addr)->s_addr;
395 if (a.s_addr != b.s_addr)
396 return 0;
397
398 /* stf interface makes single side match only */
399 return 32;
400 }
401
402 static struct in6_ifaddr *
403 stf_getsrcifa6(struct ifnet *ifp)
404 {
405 struct ifaddr *ia;
406 struct in_ifaddr *ia4;
407 struct sockaddr_in6 *sin6;
408 struct in_addr in;
409
410 ifnet_lock_shared(ifp);
411 for (ia = ifp->if_addrlist.tqh_first;
412 ia;
413 ia = ia->ifa_list.tqe_next)
414 {
415 if (ia->ifa_addr == NULL)
416 continue;
417 if (ia->ifa_addr->sa_family != AF_INET6)
418 continue;
419 sin6 = (struct sockaddr_in6 *)ia->ifa_addr;
420 if (!IN6_IS_ADDR_6TO4(&sin6->sin6_addr))
421 continue;
422
423 bcopy(GET_V4(&sin6->sin6_addr), &in, sizeof(in));
424 lck_mtx_lock(rt_mtx);
425 for (ia4 = TAILQ_FIRST(&in_ifaddrhead);
426 ia4;
427 ia4 = TAILQ_NEXT(ia4, ia_link))
428 {
429 if (ia4->ia_addr.sin_addr.s_addr == in.s_addr)
430 break;
431 }
432 lck_mtx_unlock(rt_mtx);
433 if (ia4 == NULL)
434 continue;
435
436 ifnet_lock_done(ifp);
437 return (struct in6_ifaddr *)ia;
438 }
439 ifnet_lock_done(ifp);
440
441 return NULL;
442 }
443
444 int
445 stf_pre_output(
446 struct ifnet *ifp,
447 __unused protocol_family_t protocol_family,
448 struct mbuf **m0,
449 const struct sockaddr *dst,
450 __unused void *route,
451 __unused char *desk_linkaddr,
452 __unused char *frame_type)
453 {
454 struct mbuf *m = *m0;
455 struct stf_softc *sc;
456 const struct sockaddr_in6 *dst6;
457 const struct in_addr *in4;
458 u_int8_t tos;
459 struct ip *ip;
460 struct ip6_hdr *ip6;
461 struct in6_ifaddr *ia6;
462 struct sockaddr_in *dst4;
463 errno_t result = 0;
464
465 sc = ifnet_softc(ifp);
466 dst6 = (const struct sockaddr_in6 *)dst;
467
468 /* just in case */
469 if ((ifnet_flags(ifp) & IFF_UP) == 0) {
470 printf("stf: IFF_DOWN\n");
471 return ENETDOWN;
472 }
473
474 /*
475 * If we don't have an ip4 address that match my inner ip6 address,
476 * we shouldn't generate output. Without this check, we'll end up
477 * using wrong IPv4 source.
478 */
479 ia6 = stf_getsrcifa6(ifp);
480 if (ia6 == NULL) {
481 return ENETDOWN;
482 }
483
484 if (mbuf_len(m) < sizeof(*ip6)) {
485 m = m_pullup(m, sizeof(*ip6));
486 if (!m) {
487 *m0 = NULL; /* makes sure this won't be double freed */
488 return ENOBUFS;
489 }
490 }
491 ip6 = mtod(m, struct ip6_hdr *);
492 tos = (ntohl(ip6->ip6_flow) >> 20) & 0xff;
493
494 /*
495 * Pickup the right outer dst addr from the list of candidates.
496 * ip6_dst has priority as it may be able to give us shorter IPv4 hops.
497 */
498 if (IN6_IS_ADDR_6TO4(&ip6->ip6_dst))
499 in4 = GET_V4(&ip6->ip6_dst);
500 else if (IN6_IS_ADDR_6TO4(&dst6->sin6_addr))
501 in4 = GET_V4(&dst6->sin6_addr);
502 else {
503 return ENETUNREACH;
504 }
505
506 if (ifp->if_bpf) {
507 /* We need to prepend the address family as a four byte field. */
508 u_int32_t af = AF_INET6;
509
510 bpf_tap_out(ifp, 0, m, &af, sizeof(af));
511 }
512
513 M_PREPEND(m, sizeof(struct ip), M_DONTWAIT);
514 if (m && mbuf_len(m) < sizeof(struct ip))
515 m = m_pullup(m, sizeof(struct ip));
516 if (m == NULL) {
517 *m0 = NULL;
518 return ENOBUFS;
519 }
520 ip = mtod(m, struct ip *);
521
522 bzero(ip, sizeof(*ip));
523
524 bcopy(GET_V4(&((struct sockaddr_in6 *)&ia6->ia_addr)->sin6_addr),
525 &ip->ip_src, sizeof(ip->ip_src));
526 bcopy(in4, &ip->ip_dst, sizeof(ip->ip_dst));
527 ip->ip_p = IPPROTO_IPV6;
528 ip->ip_ttl = ip_stf_ttl;
529 ip->ip_len = m->m_pkthdr.len; /*host order*/
530 if (ifp->if_flags & IFF_LINK1)
531 ip_ecn_ingress(ECN_ALLOWED, &ip->ip_tos, &tos);
532 else
533 ip_ecn_ingress(ECN_NOCARE, &ip->ip_tos, &tos);
534
535 dst4 = (struct sockaddr_in *)&sc->sc_ro.ro_dst;
536 if (dst4->sin_family != AF_INET ||
537 bcmp(&dst4->sin_addr, &ip->ip_dst, sizeof(ip->ip_dst)) != 0) {
538 /* cache route doesn't match */
539 printf("stf_output: cached route doesn't match \n");
540 dst4->sin_family = AF_INET;
541 dst4->sin_len = sizeof(struct sockaddr_in);
542 bcopy(&ip->ip_dst, &dst4->sin_addr, sizeof(dst4->sin_addr));
543 if (sc->sc_ro.ro_rt) {
544 rtfree(sc->sc_ro.ro_rt);
545 sc->sc_ro.ro_rt = NULL;
546 }
547 }
548
549 if (sc->sc_ro.ro_rt == NULL) {
550 rtalloc(&sc->sc_ro);
551 if (sc->sc_ro.ro_rt == NULL) {
552 return ENETUNREACH;
553 }
554 }
555
556 result = ip_output_list(m, 0, NULL, &sc->sc_ro, 0, NULL, NULL);
557 /* Assumption: ip_output will free mbuf on errors */
558 /* All the output processing is done here, don't let stf_output be called */
559 if (result == 0)
560 result = EJUSTRETURN;
561 *m0 = NULL;
562 return result;
563 }
564 static errno_t
565 stf_output(
566 __unused ifnet_t ifp,
567 __unused mbuf_t m)
568 {
569 /* All processing is done in stf_pre_output
570 * this shouldn't be called as the pre_output returns "EJUSTRETURN"
571 */
572 return 0;
573 }
574
575 static int
576 stf_checkaddr4(
577 struct stf_softc *sc,
578 const struct in_addr *in,
579 struct ifnet *inifp) /* incoming interface */
580 {
581 struct in_ifaddr *ia4;
582
583 /*
584 * reject packets with the following address:
585 * 224.0.0.0/4 0.0.0.0/8 127.0.0.0/8 255.0.0.0/8
586 */
587 if (IN_MULTICAST(ntohl(in->s_addr)))
588 return -1;
589 switch ((ntohl(in->s_addr) & 0xff000000) >> 24) {
590 case 0: case 127: case 255:
591 return -1;
592 }
593
594 /*
595 * reject packets with broadcast
596 */
597 lck_mtx_lock(rt_mtx);
598 for (ia4 = TAILQ_FIRST(&in_ifaddrhead);
599 ia4;
600 ia4 = TAILQ_NEXT(ia4, ia_link))
601 {
602 if ((ia4->ia_ifa.ifa_ifp->if_flags & IFF_BROADCAST) == 0)
603 continue;
604 if (in->s_addr == ia4->ia_broadaddr.sin_addr.s_addr) {
605 lck_mtx_unlock(rt_mtx);
606 return -1;
607 }
608 }
609 lck_mtx_unlock(rt_mtx);
610
611 /*
612 * perform ingress filter
613 */
614 if (sc && (ifnet_flags(sc->sc_if) & IFF_LINK2) == 0 && inifp) {
615 struct sockaddr_in sin;
616 struct rtentry *rt;
617
618 bzero(&sin, sizeof(sin));
619 sin.sin_family = AF_INET;
620 sin.sin_len = sizeof(struct sockaddr_in);
621 sin.sin_addr = *in;
622 rt = rtalloc1((struct sockaddr *)&sin, 0, 0UL);
623 if (!rt || rt->rt_ifp != inifp) {
624 #if 1
625 log(LOG_WARNING, "%s: packet from 0x%x dropped "
626 "due to ingress filter\n", if_name(sc->sc_if),
627 (u_int32_t)ntohl(sin.sin_addr.s_addr));
628 #endif
629 if (rt)
630 rtfree(rt);
631 return -1;
632 }
633 rtfree(rt);
634 }
635
636 return 0;
637 }
638
639 static int
640 stf_checkaddr6(
641 struct stf_softc *sc,
642 struct in6_addr *in6,
643 struct ifnet *inifp) /* incoming interface */
644 {
645 /*
646 * check 6to4 addresses
647 */
648 if (IN6_IS_ADDR_6TO4(in6))
649 return stf_checkaddr4(sc, GET_V4(in6), inifp);
650
651 /*
652 * reject anything that look suspicious. the test is implemented
653 * in ip6_input too, but we check here as well to
654 * (1) reject bad packets earlier, and
655 * (2) to be safe against future ip6_input change.
656 */
657 if (IN6_IS_ADDR_V4COMPAT(in6) || IN6_IS_ADDR_V4MAPPED(in6))
658 return -1;
659
660 return 0;
661 }
662
663 static void
664 in_stf_input(
665 struct mbuf *m,
666 int off)
667 {
668 struct stf_softc *sc;
669 struct ip *ip;
670 struct ip6_hdr ip6;
671 u_int8_t otos, itos;
672 int proto;
673 struct ifnet *ifp;
674 struct ifnet_stat_increment_param stats;
675
676 ip = mtod(m, struct ip *);
677 proto = ip->ip_p;
678
679 if (proto != IPPROTO_IPV6) {
680 m_freem(m);
681 return;
682 }
683
684 ip = mtod(m, struct ip *);
685
686 sc = (struct stf_softc *)encap_getarg(m);
687
688 if (sc == NULL || (ifnet_flags(sc->sc_if) & IFF_UP) == 0) {
689 m_freem(m);
690 return;
691 }
692
693 ifp = sc->sc_if;
694
695 #if MAC_LABEL
696 mac_mbuf_label_associate_ifnet(ifp, m);
697 #endif
698
699 /*
700 * perform sanity check against outer src/dst.
701 * for source, perform ingress filter as well.
702 */
703 if (stf_checkaddr4(sc, &ip->ip_dst, NULL) < 0 ||
704 stf_checkaddr4(sc, &ip->ip_src, m->m_pkthdr.rcvif) < 0) {
705 m_freem(m);
706 return;
707 }
708
709 otos = ip->ip_tos;
710 mbuf_copydata(m, off, sizeof(ip6), &ip6);
711
712 /*
713 * perform sanity check against inner src/dst.
714 * for source, perform ingress filter as well.
715 */
716 if (stf_checkaddr6(sc, &ip6.ip6_dst, NULL) < 0 ||
717 stf_checkaddr6(sc, &ip6.ip6_src, m->m_pkthdr.rcvif) < 0) {
718 m_freem(m);
719 return;
720 }
721
722 itos = (ntohl(ip6.ip6_flow) >> 20) & 0xff;
723 if ((ifnet_flags(ifp) & IFF_LINK1) != 0)
724 ip_ecn_egress(ECN_ALLOWED, &otos, &itos);
725 else
726 ip_ecn_egress(ECN_NOCARE, &otos, &itos);
727 ip6.ip6_flow &= ~htonl(0xff << 20);
728 ip6.ip6_flow |= htonl((u_int32_t)itos << 20);
729
730 m->m_pkthdr.rcvif = ifp;
731 mbuf_pkthdr_setheader(m, mbuf_data(m));
732 mbuf_adj(m, off);
733
734 if (ifp->if_bpf) {
735 /* We need to prepend the address family as a four byte field. */
736 u_int32_t af = AF_INET6;
737 bpf_tap_in(ifp, 0, m, &af, sizeof(af));
738 }
739
740 /*
741 * Put the packet to the network layer input queue according to the
742 * specified address family.
743 * See net/if_gif.c for possible issues with packet processing
744 * reorder due to extra queueing.
745 */
746 bzero(&stats, sizeof(stats));
747 stats.packets_in = 1;
748 stats.bytes_in = mbuf_pkthdr_len(m);
749 mbuf_pkthdr_setrcvif(m, ifp);
750 ifnet_input(ifp, m, &stats);
751
752 return;
753 }
754
755 static void
756 stf_rtrequest(
757 __unused int cmd,
758 struct rtentry *rt,
759 __unused struct sockaddr *sa)
760 {
761
762 if (rt)
763 rt->rt_rmx.rmx_mtu = IPV6_MMTU;
764 }
765
766 static errno_t
767 stf_ioctl(
768 ifnet_t ifp,
769 u_int32_t cmd,
770 void *data)
771 {
772 struct ifaddr *ifa;
773 struct ifreq *ifr;
774 struct sockaddr_in6 *sin6;
775 int error;
776
777 error = 0;
778 switch (cmd) {
779 case SIOCSIFADDR:
780 ifa = (struct ifaddr *)data;
781 if (ifa == NULL || ifa->ifa_addr->sa_family != AF_INET6) {
782 error = EAFNOSUPPORT;
783 break;
784 }
785 sin6 = (struct sockaddr_in6 *)ifa->ifa_addr;
786 if (IN6_IS_ADDR_6TO4(&sin6->sin6_addr)) {
787 if ( !(ifnet_flags( ifp ) & IFF_UP) ) {
788 /* do this only if the interface is not already up */
789 ifa->ifa_rtrequest = stf_rtrequest;
790 ifnet_set_flags(ifp, IFF_UP, IFF_UP);
791 }
792 } else
793 error = EINVAL;
794 break;
795
796 case SIOCADDMULTI:
797 case SIOCDELMULTI:
798 ifr = (struct ifreq *)data;
799 if (ifr && ifr->ifr_addr.sa_family == AF_INET6)
800 ;
801 else
802 error = EAFNOSUPPORT;
803 break;
804
805 default:
806 error = EINVAL;
807 break;
808 }
809
810 return error;
811 }