]> git.saurik.com Git - apple/xnu.git/blame - bsd/net/if_stf.c
xnu-517.11.1.tar.gz
[apple/xnu.git] / bsd / net / if_stf.c
CommitLineData
9bccf70c
A
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/*
34 * 6to4 interface, based on RFC3056.
35 *
36 * 6to4 interface is NOT capable of link-layer (I mean, IPv4) multicasting.
37 * There is no address mapping defined from IPv6 multicast address to IPv4
38 * address. Therefore, we do not have IFF_MULTICAST on the interface.
39 *
40 * Due to the lack of address mapping for link-local addresses, we cannot
41 * throw packets toward link-local addresses (fe80::x). Also, we cannot throw
42 * packets to link-local multicast addresses (ff02::x).
43 *
44 * Here are interesting symptoms due to the lack of link-local address:
45 *
46 * Unicast routing exchange:
47 * - RIPng: Impossible. Uses link-local multicast packet toward ff02::9,
48 * and link-local addresses as nexthop.
49 * - OSPFv6: Impossible. OSPFv6 assumes that there's link-local address
50 * assigned to the link, and makes use of them. Also, HELLO packets use
51 * link-local multicast addresses (ff02::5 and ff02::6).
52 * - BGP4+: Maybe. You can only use global address as nexthop, and global
53 * address as TCP endpoint address.
54 *
55 * Multicast routing protocols:
56 * - PIM: Hello packet cannot be used to discover adjacent PIM routers.
57 * Adjacent PIM routers must be configured manually (is it really spec-wise
58 * correct thing to do?).
59 *
60 * ICMPv6:
61 * - Redirects cannot be used due to the lack of link-local address.
62 *
63 * stf interface does not have, and will not need, a link-local address.
64 * It seems to have no real benefit and does not help the above symptoms much.
65 * Even if we assign link-locals to interface, we cannot really
66 * use link-local unicast/multicast on top of 6to4 cloud (since there's no
67 * encapsulation defined for link-local address), and the above analysis does
68 * not change. RFC3056 does not mandate the assignment of link-local address
69 * either.
70 *
71 * 6to4 interface has security issues. Refer to
72 * http://playground.iijlab.net/i-d/draft-itojun-ipv6-transition-abuse-00.txt
73 * for details. The code tries to filter out some of malicious packets.
74 * Note that there is no way to be 100% secure.
75 */
76
77#include <sys/param.h>
78#include <sys/systm.h>
79#include <sys/socket.h>
80#include <sys/sockio.h>
81#include <sys/mbuf.h>
82#include <sys/errno.h>
83#include <sys/protosw.h>
84#include <sys/kernel.h>
85#include <sys/syslog.h>
86#include <machine/cpu.h>
87
88#include <sys/malloc.h>
89
90#include <net/if.h>
91#include <net/route.h>
92#include <net/netisr.h>
93#include <net/if_types.h>
94#include <net/if_stf.h>
95
96#include <netinet/in.h>
97#include <netinet/in_systm.h>
98#include <netinet/ip.h>
99#include <netinet/ip_var.h>
100#include <netinet/in_var.h>
101
102#include <netinet/ip6.h>
103#include <netinet6/ip6_var.h>
104#include <netinet6/in6_var.h>
105#include <netinet/ip_ecn.h>
106
107#include <netinet/ip_encap.h>
108#include <net/dlil.h>
109
110
111#include <net/net_osdep.h>
112
113#include <net/bpf.h>
114
115#define IN6_IS_ADDR_6TO4(x) (ntohs((x)->s6_addr16[0]) == 0x2002)
116#define GET_V4(x) ((struct in_addr *)(&(x)->s6_addr16[1]))
117
118struct stf_softc {
119 struct ifnet sc_if; /* common area */
120#ifdef __APPLE__
121 struct if_proto *stf_proto; /* dlil protocol attached */
122#endif
123 union {
124 struct route __sc_ro4;
125 struct route_in6 __sc_ro6; /* just for safety */
126 } __sc_ro46;
127#define sc_ro __sc_ro46.__sc_ro4
128 const struct encaptab *encap_cookie;
129};
130
131static struct stf_softc *stf;
132
133#ifdef __APPLE__
134void stfattach __P((void));
135int stf_pre_output __P((struct ifnet *, register struct mbuf **, struct sockaddr *,
136 caddr_t, char *, char *, u_long));
137static u_long stf_dl_tag=0;
138#endif
139
140#ifndef __APPLE__
141static MALLOC_DEFINE(M_STF, "stf", "6to4 Tunnel Interface");
142#endif
143static int ip_stf_ttl = 40;
144
145extern struct domain inetdomain;
146struct protosw in_stf_protosw =
147{ SOCK_RAW, &inetdomain, IPPROTO_IPV6, PR_ATOMIC|PR_ADDR,
55e303ae 148 in_stf_input, 0, 0, rip_ctloutput,
9bccf70c
A
149 0,
150 0, 0, 0, 0,
151 0,
152 &rip_usrreqs
153};
154
155static int stf_encapcheck __P((const struct mbuf *, int, int, void *));
156static struct in6_ifaddr *stf_getsrcifa6 __P((struct ifnet *));
157int stf_pre_output __P((struct ifnet *, register struct mbuf **, struct sockaddr *,
158 caddr_t, char *, char *, u_long));
159static int stf_checkaddr4 __P((struct stf_softc *, struct in_addr *,
160 struct ifnet *));
161static int stf_checkaddr6 __P((struct stf_softc *, struct in6_addr *,
162 struct ifnet *));
163static void stf_rtrequest __P((int, struct rtentry *, struct sockaddr *));
164int stf_ioctl __P((struct ifnet *, u_long, void *));
165
166
167static
168int stf_add_if(struct ifnet *ifp)
169{
170 ifp->if_demux = 0;
171 ifp->if_framer = 0;
172 return 0;
173}
174
175static
176int stf_del_if(struct ifnet *ifp)
177{
178 return 0;
179}
180
181static
182int stf_add_proto(struct ddesc_head_str *desc_head, struct if_proto *proto, u_long dl_tag)
183{
184 /* Only one protocol may be attached at a time */
185 struct stf_softc* stf = (struct stf_softc*)proto->ifp;
186 if (stf->stf_proto == NULL)
187 stf->stf_proto = proto;
188 else {
189 printf("stf_add_proto: stf already has a proto\n");
190 return (EBUSY);
191 }
192
193 return (0);
194}
195
196static
197int stf_del_proto(struct if_proto *proto, u_long dl_tag)
198{
199 if (((struct stf_softc*)proto->ifp)->stf_proto == proto)
200 ((struct stf_softc*)proto->ifp)->stf_proto = NULL;
201 else
202 return ENOENT;
203
204 return 0;
205}
206
207int stf_shutdown()
208{
209 return 0;
210}
211
55e303ae 212int stf_attach_inet6(struct ifnet *ifp, u_long *dl_tag)
9bccf70c
A
213{
214 struct dlil_proto_reg_str reg;
215 struct dlil_demux_desc desc;
216 short native=0;
217 int stat, i;
218
55e303ae
A
219 if (stf_dl_tag != 0) {
220 *dl_tag = stf_dl_tag;
221 return 0;
222 }
9bccf70c
A
223
224 TAILQ_INIT(&reg.demux_desc_head);
225 desc.type = DLIL_DESC_RAW;
226 desc.variants.bitmask.proto_id_length = 0;
227 desc.variants.bitmask.proto_id = 0;
228 desc.variants.bitmask.proto_id_mask = 0;
229 desc.native_type = (char *) &native;
230 TAILQ_INSERT_TAIL(&reg.demux_desc_head, &desc, next);
231 reg.interface_family = ifp->if_family;
232 reg.unit_number = ifp->if_unit;
233 reg.input = 0;
234 reg.pre_output = stf_pre_output;
235 reg.event = 0;
236 reg.offer = 0;
237 reg.ioctl = 0;
238 reg.default_proto = 0;
239 reg.protocol_family = PF_INET6;
240
241 stat = dlil_attach_protocol(&reg, &stf_dl_tag);
55e303ae 242 *dl_tag = stf_dl_tag;
9bccf70c 243
55e303ae 244 return stat;
9bccf70c
A
245}
246
55e303ae 247int stf_detach_inet6(struct ifnet *ifp, u_long dl_tag)
9bccf70c 248{
9bccf70c
A
249 int stat;
250
55e303ae 251 stat = dlil_find_dltag(ifp->if_family, ifp->if_unit, AF_INET6, &dl_tag);
9bccf70c 252 if (stat == 0) {
55e303ae 253 stat = dlil_detach_protocol(dl_tag);
9bccf70c
A
254 if (stat) {
255 printf("WARNING: stf_detach can't detach IP AF_INET6 from interface\n");
256 }
257 }
258 return (stat);
259}
260
55e303ae
A
261void stf_reg_if_mods()
262{
263 struct dlil_ifmod_reg_str stf_ifmod;
264 struct dlil_protomod_reg_str stf_protoreg;
265 int error;
266
267 bzero(&stf_ifmod, sizeof(stf_ifmod));
268 stf_ifmod.add_if = stf_add_if;
269 stf_ifmod.del_if = stf_del_if;
270 stf_ifmod.add_proto = stf_add_proto;
271 stf_ifmod.del_proto = stf_del_proto;
272 stf_ifmod.ifmod_ioctl = 0;
273 stf_ifmod.shutdown = stf_shutdown;
274
275
276 if (dlil_reg_if_modules(APPLE_IF_FAM_STF, &stf_ifmod))
277 panic("Couldn't register stf modules\n");
278
279 /* Register protocol registration functions */
280
281 bzero(&stf_protoreg, sizeof(stf_protoreg));
282 stf_protoreg.attach_proto = stf_attach_inet6;
283 stf_protoreg.detach_proto = stf_detach_inet6;
284
285 if ( error = dlil_reg_proto_module(AF_INET6, APPLE_IF_FAM_STF, &stf_protoreg) != 0)
286 kprintf("dlil_reg_proto_module failed for AF_INET6 error=%d\n", error);
287}
9bccf70c
A
288
289void
290stfattach(void)
291{
292 struct ifnet *ifp;
293 struct stf_softc *sc;
294 int i, error;
295
296
297 int err;
298 const struct encaptab *p;
299
300 stf_reg_if_mods(); /* DLIL modules */
301
302 sc = _MALLOC(sizeof(struct stf_softc), M_DEVBUF, M_WAITOK);
303 if (sc == 0) {
304 printf("stf softc attach failed\n" );
305 return;
306 }
307
308 bzero(sc, sizeof(*sc));
309 sc->sc_if.if_name = "stf";
310 sc->sc_if.if_unit = 0;
311
312 p = encap_attach_func(AF_INET, IPPROTO_IPV6, stf_encapcheck,
313 &in_stf_protosw, sc);
314 if (p == NULL) {
315 printf("%s: attach failed\n", if_name(&sc->sc_if));
316 FREE(sc, M_DEVBUF);
317 return;
318 }
319 sc->encap_cookie = p;
320 sc->sc_if.if_mtu = IPV6_MMTU;
321 sc->sc_if.if_flags = 0;
322 sc->sc_if.if_ioctl = stf_ioctl;
323 sc->sc_if.if_output = NULL; /* processing done in pre_output */
324 sc->sc_if.if_type = IFT_STF;
325 sc->sc_if.if_family= APPLE_IF_FAM_STF;
326#if 0
327 /* turn off ingress filter */
328 sc->sc_if.if_flags |= IFF_LINK2;
329#endif
330 sc->sc_if.if_snd.ifq_maxlen = IFQ_MAXLEN;
331
332 if (error = dlil_if_attach(&sc->sc_if))
333 printf("stfattach: can't dlil_if_attach error=%d\n");
334 else
335 bpfattach(&sc->sc_if, DLT_NULL, sizeof(u_int));
336
337 return ;
338}
339
340static int
341stf_encapcheck(m, off, proto, arg)
342 const struct mbuf *m;
343 int off;
344 int proto;
345 void *arg;
346{
347 struct ip ip;
348 struct in6_ifaddr *ia6;
349 struct stf_softc *sc;
350 struct in_addr a, b;
351
352 sc = (struct stf_softc *)arg;
353 if (sc == NULL)
354 return 0;
355
356 if ((sc->sc_if.if_flags & IFF_UP) == 0)
357 return 0;
358
359 /* IFF_LINK0 means "no decapsulation" */
360 if ((sc->sc_if.if_flags & IFF_LINK0) != 0)
361 return 0;
362
363 if (proto != IPPROTO_IPV6)
364 return 0;
365
366 /* LINTED const cast */
367 m_copydata((struct mbuf *)m, 0, sizeof(ip), (caddr_t)&ip);
368
369 if (ip.ip_v != 4)
370 return 0;
371
372 ia6 = stf_getsrcifa6(&sc->sc_if);
373 if (ia6 == NULL)
374 return 0;
375
376 /*
377 * check if IPv4 dst matches the IPv4 address derived from the
378 * local 6to4 address.
379 * success on: dst = 10.1.1.1, ia6->ia_addr = 2002:0a01:0101:...
380 */
381 if (bcmp(GET_V4(&ia6->ia_addr.sin6_addr), &ip.ip_dst,
382 sizeof(ip.ip_dst)) != 0)
383 return 0;
384
385 /*
386 * check if IPv4 src matches the IPv4 address derived from the
387 * local 6to4 address masked by prefixmask.
388 * success on: src = 10.1.1.1, ia6->ia_addr = 2002:0a00:.../24
389 * fail on: src = 10.1.1.1, ia6->ia_addr = 2002:0b00:.../24
390 */
391 bzero(&a, sizeof(a));
392 a.s_addr = GET_V4(&ia6->ia_addr.sin6_addr)->s_addr;
393 a.s_addr &= GET_V4(&ia6->ia_prefixmask.sin6_addr)->s_addr;
394 b = ip.ip_src;
395 b.s_addr &= GET_V4(&ia6->ia_prefixmask.sin6_addr)->s_addr;
396 if (a.s_addr != b.s_addr)
397 return 0;
398
399 /* stf interface makes single side match only */
400 return 32;
401}
402
403static struct in6_ifaddr *
404stf_getsrcifa6(ifp)
405 struct ifnet *ifp;
406{
407 struct ifaddr *ia;
408 struct in_ifaddr *ia4;
409 struct sockaddr_in6 *sin6;
410 struct in_addr in;
411
412 for (ia = ifp->if_addrlist.tqh_first;
413 ia;
414 ia = ia->ifa_list.tqe_next)
415 {
416 if (ia->ifa_addr == NULL)
417 continue;
418 if (ia->ifa_addr->sa_family != AF_INET6)
419 continue;
420 sin6 = (struct sockaddr_in6 *)ia->ifa_addr;
421 if (!IN6_IS_ADDR_6TO4(&sin6->sin6_addr))
422 continue;
423
424 bcopy(GET_V4(&sin6->sin6_addr), &in, sizeof(in));
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 if (ia4 == NULL)
433 continue;
434
435 return (struct in6_ifaddr *)ia;
436 }
437
438 return NULL;
439}
440
441int
442stf_pre_output(ifp, m0, dst, rt, frame_type, address, dl_tag)
443 struct ifnet *ifp;
444 register struct mbuf **m0;
445 struct sockaddr *dst;
446 caddr_t rt;
447 char *frame_type;
448 char *address;
449 u_long dl_tag;
450{
451 register struct mbuf *m = *m0;
452 struct stf_softc *sc;
453 struct sockaddr_in6 *dst6;
454 struct in_addr *in4;
455 struct sockaddr_in *dst4;
456 u_int8_t tos;
457 struct ip *ip;
458 struct ip6_hdr *ip6;
459 struct in6_ifaddr *ia6;
460 int error = 0 ;
461
462 sc = (struct stf_softc*)ifp;
463 dst6 = (struct sockaddr_in6 *)dst;
464
465 /* just in case */
466 if ((ifp->if_flags & IFF_UP) == 0) {
467 printf("stf: IFF_DOWN\n");
468 return ENETDOWN;
469 }
470
471 /*
472 * If we don't have an ip4 address that match my inner ip6 address,
473 * we shouldn't generate output. Without this check, we'll end up
474 * using wrong IPv4 source.
475 */
476 ia6 = stf_getsrcifa6(ifp);
477 if (ia6 == NULL) {
478 return ENETDOWN;
479 }
480
481 if (m->m_len < sizeof(*ip6)) {
482 m = m_pullup(m, sizeof(*ip6));
483 if (!m)
484 return ENOBUFS;
485 }
486 ip6 = mtod(m, struct ip6_hdr *);
487 tos = (ntohl(ip6->ip6_flow) >> 20) & 0xff;
488
489 /*
490 * Pickup the right outer dst addr from the list of candidates.
491 * ip6_dst has priority as it may be able to give us shorter IPv4 hops.
492 */
493 if (IN6_IS_ADDR_6TO4(&ip6->ip6_dst))
494 in4 = GET_V4(&ip6->ip6_dst);
495 else if (IN6_IS_ADDR_6TO4(&dst6->sin6_addr))
496 in4 = GET_V4(&dst6->sin6_addr);
497 else {
498 return ENETUNREACH;
499 }
500
501 if (ifp->if_bpf) {
502 /*
503 * We need to prepend the address family as
504 * a four byte field. Cons up a dummy header
505 * to pacify bpf. This is safe because bpf
506 * will only read from the mbuf (i.e., it won't
507 * try to free it or keep a pointer a to it).
508 */
509 struct mbuf m0;
510 u_int32_t af = AF_INET6;
511
512 m0.m_next = m;
513 m0.m_len = 4;
514 m0.m_data = (char *)&af;
515
516 bpf_mtap(ifp, &m0);
517 }
518
519 M_PREPEND(m, sizeof(struct ip), M_DONTWAIT);
520 if (m && m->m_len < sizeof(struct ip))
521 m = m_pullup(m, sizeof(struct ip));
522 if (m == NULL)
523 return ENOBUFS;
524 ip = mtod(m, struct ip *);
525
526 bzero(ip, sizeof(*ip));
527
528 bcopy(GET_V4(&((struct sockaddr_in6 *)&ia6->ia_addr)->sin6_addr),
529 &ip->ip_src, sizeof(ip->ip_src));
530 bcopy(in4, &ip->ip_dst, sizeof(ip->ip_dst));
531 ip->ip_p = IPPROTO_IPV6;
532 ip->ip_ttl = ip_stf_ttl;
533 ip->ip_len = m->m_pkthdr.len; /*host order*/
534 if (ifp->if_flags & IFF_LINK1)
535 ip_ecn_ingress(ECN_ALLOWED, &ip->ip_tos, &tos);
536 else
537 ip_ecn_ingress(ECN_NOCARE, &ip->ip_tos, &tos);
538
539 dst4 = (struct sockaddr_in *)&sc->sc_ro.ro_dst;
540 if (dst4->sin_family != AF_INET ||
541 bcmp(&dst4->sin_addr, &ip->ip_dst, sizeof(ip->ip_dst)) != 0) {
542 /* cache route doesn't match */
543 dst4->sin_family = AF_INET;
544 dst4->sin_len = sizeof(struct sockaddr_in);
545 bcopy(&ip->ip_dst, &dst4->sin_addr, sizeof(dst4->sin_addr));
546 if (sc->sc_ro.ro_rt) {
547 RTFREE(sc->sc_ro.ro_rt);
548 sc->sc_ro.ro_rt = NULL;
549 }
550 }
551
552 if (sc->sc_ro.ro_rt == NULL) {
553 rtalloc(&sc->sc_ro);
554 if (sc->sc_ro.ro_rt == NULL) {
555 return ENETUNREACH;
556 }
557 }
558
559 error = ip_output(m, NULL, &sc->sc_ro, 0, NULL);
560 if (error == 0)
561 return EJUSTRETURN;
562}
563
564static int
565stf_checkaddr4(sc, in, inifp)
566 struct stf_softc *sc;
567 struct in_addr *in;
568 struct ifnet *inifp; /* incoming interface */
569{
570 struct in_ifaddr *ia4;
571
572 /*
573 * reject packets with the following address:
574 * 224.0.0.0/4 0.0.0.0/8 127.0.0.0/8 255.0.0.0/8
575 */
576 if (IN_MULTICAST(ntohl(in->s_addr)))
577 return -1;
578 switch ((ntohl(in->s_addr) & 0xff000000) >> 24) {
579 case 0: case 127: case 255:
580 return -1;
581 }
582
583 /*
584 * reject packets with broadcast
585 */
586 for (ia4 = TAILQ_FIRST(&in_ifaddrhead);
587 ia4;
588 ia4 = TAILQ_NEXT(ia4, ia_link))
589 {
590 if ((ia4->ia_ifa.ifa_ifp->if_flags & IFF_BROADCAST) == 0)
591 continue;
592 if (in->s_addr == ia4->ia_broadaddr.sin_addr.s_addr)
593 return -1;
594 }
595
596 /*
597 * perform ingress filter
598 */
599 if (sc && (sc->sc_if.if_flags & IFF_LINK2) == 0 && inifp) {
600 struct sockaddr_in sin;
601 struct rtentry *rt;
602
603 bzero(&sin, sizeof(sin));
604 sin.sin_family = AF_INET;
605 sin.sin_len = sizeof(struct sockaddr_in);
606 sin.sin_addr = *in;
607 rt = rtalloc1((struct sockaddr *)&sin, 0, 0UL);
608 if (!rt || rt->rt_ifp != inifp) {
609#if 1
610 log(LOG_WARNING, "%s: packet from 0x%x dropped "
611 "due to ingress filter\n", if_name(&sc->sc_if),
612 (u_int32_t)ntohl(sin.sin_addr.s_addr));
613#endif
614 if (rt)
615 rtfree(rt);
616 return -1;
617 }
618 rtfree(rt);
619 }
620
621 return 0;
622}
623
624static int
625stf_checkaddr6(sc, in6, inifp)
626 struct stf_softc *sc;
627 struct in6_addr *in6;
628 struct ifnet *inifp; /* incoming interface */
629{
630 /*
631 * check 6to4 addresses
632 */
633 if (IN6_IS_ADDR_6TO4(in6))
634 return stf_checkaddr4(sc, GET_V4(in6), inifp);
635
636 /*
637 * reject anything that look suspicious. the test is implemented
638 * in ip6_input too, but we check here as well to
639 * (1) reject bad packets earlier, and
640 * (2) to be safe against future ip6_input change.
641 */
642 if (IN6_IS_ADDR_V4COMPAT(in6) || IN6_IS_ADDR_V4MAPPED(in6))
643 return -1;
644
645 return 0;
646}
647
648void
649in_stf_input(m, off)
650 struct mbuf *m;
651 int off;
652{
653 struct stf_softc *sc;
654 struct ip *ip;
655 struct ip6_hdr *ip6;
656 u_int8_t otos, itos;
657 int s, isr, proto;
658 struct ifqueue *ifq = NULL;
659 struct ifnet *ifp;
660
661 ip = mtod(m, struct ip *);
662 proto = ip->ip_p;
663
664
665 if (proto != IPPROTO_IPV6) {
666 m_freem(m);
667 return;
668 }
669
670 ip = mtod(m, struct ip *);
671
672 sc = (struct stf_softc *)encap_getarg(m);
673
674 if (sc == NULL || (sc->sc_if.if_flags & IFF_UP) == 0) {
675 m_freem(m);
676 return;
677 }
678
679 ifp = &sc->sc_if;
680
681 /*
682 * perform sanity check against outer src/dst.
683 * for source, perform ingress filter as well.
684 */
685 if (stf_checkaddr4(sc, &ip->ip_dst, NULL) < 0 ||
686 stf_checkaddr4(sc, &ip->ip_src, m->m_pkthdr.rcvif) < 0) {
687 m_freem(m);
688 return;
689 }
690
691 otos = ip->ip_tos;
692 m_adj(m, off);
693
694 if (m->m_len < sizeof(*ip6)) {
695 m = m_pullup(m, sizeof(*ip6));
696 if (!m)
697 return;
698 }
699 ip6 = mtod(m, struct ip6_hdr *);
700
701 /*
702 * perform sanity check against inner src/dst.
703 * for source, perform ingress filter as well.
704 */
705 if (stf_checkaddr6(sc, &ip6->ip6_dst, NULL) < 0 ||
706 stf_checkaddr6(sc, &ip6->ip6_src, m->m_pkthdr.rcvif) < 0) {
707 m_freem(m);
708 return;
709 }
710
711 itos = (ntohl(ip6->ip6_flow) >> 20) & 0xff;
712 if ((ifp->if_flags & IFF_LINK1) != 0)
713 ip_ecn_egress(ECN_ALLOWED, &otos, &itos);
714 else
715 ip_ecn_egress(ECN_NOCARE, &otos, &itos);
716 ip6->ip6_flow &= ~htonl(0xff << 20);
717 ip6->ip6_flow |= htonl((u_int32_t)itos << 20);
718
719 m->m_pkthdr.rcvif = ifp;
720
721 if (ifp->if_bpf) {
722 /*
723 * We need to prepend the address family as
724 * a four byte field. Cons up a dummy header
725 * to pacify bpf. This is safe because bpf
726 * will only read from the mbuf (i.e., it won't
727 * try to free it or keep a pointer a to it).
728 */
729 struct mbuf m0;
730 u_int32_t af = AF_INET6;
731
732 m0.m_next = m;
733 m0.m_len = 4;
734 m0.m_data = (char *)&af;
735
736#ifdef HAVE_OLD_BPF
737 bpf_mtap(ifp, &m0);
738#else
739 bpf_mtap(ifp->if_bpf, &m0);
740#endif
741 }
742
743 /*
744 * Put the packet to the network layer input queue according to the
745 * specified address family.
746 * See net/if_gif.c for possible issues with packet processing
747 * reorder due to extra queueing.
748 */
749 ifq = &ip6intrq;
750 isr = NETISR_IPV6;
751
752 s = splimp();
753 if (IF_QFULL(ifq)) {
754 IF_DROP(ifq); /* update statistics */
755 m_freem(m);
756 splx(s);
757 return;
758 }
759 IF_ENQUEUE(ifq, m);
760 schednetisr(isr);
761 ifp->if_ipackets++;
762 ifp->if_ibytes += m->m_pkthdr.len;
763 splx(s);
55e303ae
A
764
765 return;
9bccf70c
A
766}
767
768/* ARGSUSED */
769static void
770stf_rtrequest(cmd, rt, sa)
771 int cmd;
772 struct rtentry *rt;
773 struct sockaddr *sa;
774{
775
776 if (rt)
777 rt->rt_rmx.rmx_mtu = IPV6_MMTU;
778}
779
780int
781stf_ioctl(ifp, cmd, data)
782 struct ifnet *ifp;
783 u_long cmd;
784 void *data;
785{
786 struct ifaddr *ifa;
787 struct ifreq *ifr;
788 struct sockaddr_in6 *sin6;
789 int error;
790
791 error = 0;
792 switch (cmd) {
793 case SIOCSIFADDR:
794 ifa = (struct ifaddr *)data;
795 if (ifa == NULL || ifa->ifa_addr->sa_family != AF_INET6) {
796 error = EAFNOSUPPORT;
797 break;
798 }
799 sin6 = (struct sockaddr_in6 *)ifa->ifa_addr;
800 if (IN6_IS_ADDR_6TO4(&sin6->sin6_addr)) {
801 ifa->ifa_rtrequest = stf_rtrequest;
802 ifp->if_flags |= IFF_UP;
803 } else
804 error = EINVAL;
805 break;
806
807 case SIOCADDMULTI:
808 case SIOCDELMULTI:
809 ifr = (struct ifreq *)data;
810 if (ifr && ifr->ifr_addr.sa_family == AF_INET6)
811 ;
812 else
813 error = EAFNOSUPPORT;
814 break;
815
816 default:
817 error = EINVAL;
818 break;
819 }
820
821 return error;
822}