The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/net/if_stf.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: if_stf.c,v 1.109 2022/09/03 02:47:59 thorpej 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/cdefs.h>
   78 __KERNEL_RCSID(0, "$NetBSD: if_stf.c,v 1.109 2022/09/03 02:47:59 thorpej Exp $");
   79 
   80 #ifdef _KERNEL_OPT
   81 #include "opt_inet.h"
   82 #include "stf.h"
   83 #endif
   84 
   85 #ifndef INET6
   86         #error "pseudo-device stf requires options INET6"
   87 #endif
   88 
   89 #include <sys/param.h>
   90 #include <sys/systm.h>
   91 #include <sys/socket.h>
   92 #include <sys/sockio.h>
   93 #include <sys/mbuf.h>
   94 #include <sys/errno.h>
   95 #include <sys/ioctl.h>
   96 #include <sys/proc.h>
   97 #include <sys/queue.h>
   98 #include <sys/syslog.h>
   99 #include <sys/device.h>
  100 #include <sys/module.h>
  101 
  102 #include <sys/cpu.h>
  103 
  104 #include <net/if.h>
  105 #include <net/route.h>
  106 #include <net/if_types.h>
  107 #include <net/if_stf.h>
  108 
  109 #include <netinet/in.h>
  110 #include <netinet/in_systm.h>
  111 #include <netinet/ip.h>
  112 #include <netinet/ip_var.h>
  113 #include <netinet/in_var.h>
  114 
  115 #include <netinet/ip6.h>
  116 #include <netinet6/ip6_var.h>
  117 #include <netinet6/in6_var.h>
  118 #include <netinet/ip_ecn.h>
  119 
  120 #include <netinet/ip_encap.h>
  121 
  122 #include <net/bpf.h>
  123 
  124 #include "ioconf.h"
  125 
  126 #define IN6_IS_ADDR_6TO4(x)     (ntohs((x)->s6_addr16[0]) == 0x2002)
  127 #define GET_V4(x)       ((const struct in_addr *)(&(x)->s6_addr16[1]))
  128 
  129 struct stf_softc {
  130         struct ifnet    sc_if;     /* common area */
  131         struct route    sc_ro;
  132         const struct encaptab *encap_cookie;
  133         LIST_ENTRY(stf_softc) sc_list;
  134 };
  135 
  136 static LIST_HEAD(, stf_softc) stf_softc_list;
  137 
  138 static int      stf_clone_create(struct if_clone *, int);
  139 static int      stf_clone_destroy(struct ifnet *);
  140 
  141 struct if_clone stf_cloner =
  142     IF_CLONE_INITIALIZER("stf", stf_clone_create, stf_clone_destroy);
  143 
  144 static int ip_stf_ttl = STF_TTL;
  145 
  146 extern struct domain inetdomain;
  147 
  148 static const struct encapsw in_stf_encapsw =
  149 {
  150         .encapsw4 = {
  151                 .pr_input       = in_stf_input,
  152                 .pr_ctlinput    = NULL,
  153         }
  154 };
  155 
  156 static int stf_encapcheck(struct mbuf *, int, int, void *);
  157 static struct in6_ifaddr *stf_getsrcifa6(struct ifnet *);
  158 static int stf_output(struct ifnet *, struct mbuf *, const struct sockaddr *,
  159         const struct rtentry *);
  160 static int isrfc1918addr(const struct in_addr *);
  161 static int stf_checkaddr4(struct stf_softc *, const struct in_addr *,
  162         struct ifnet *);
  163 static int stf_checkaddr6(struct stf_softc *, const struct in6_addr *,
  164         struct ifnet *);
  165 static void stf_rtrequest(int, struct rtentry *, const struct rt_addrinfo *);
  166 static int stf_ioctl(struct ifnet *, u_long, void *);
  167 
  168 /* ARGSUSED */
  169 void
  170 stfattach(int count)
  171 {
  172 
  173         /*
  174          * Nothing to do here, initialization is handled by the
  175          * module initialization code in stfinit() below).
  176          */
  177 }
  178 
  179 static void
  180 stfinit(void)
  181 {
  182 
  183         LIST_INIT(&stf_softc_list);
  184         if_clone_attach(&stf_cloner);
  185 }
  186 
  187 static int
  188 stfdetach(void)
  189 {
  190         int error = 0;
  191 
  192         if (!LIST_EMPTY(&stf_softc_list))
  193                 error = EBUSY;
  194 
  195         if (error == 0)
  196                 if_clone_detach(&stf_cloner);
  197 
  198         return error;
  199 }
  200 
  201 static int
  202 stf_clone_create(struct if_clone *ifc, int unit)
  203 {
  204         struct stf_softc *sc;
  205         int error;
  206 
  207         sc = malloc(sizeof(struct stf_softc), M_DEVBUF, M_WAIT|M_ZERO);
  208         if_initname(&sc->sc_if, ifc->ifc_name, unit);
  209 
  210         error = encap_lock_enter();
  211         if (error) {
  212                 free(sc, M_DEVBUF);
  213                 return error;
  214         }
  215 
  216         if (LIST_FIRST(&stf_softc_list) != NULL) {
  217                 /* Only one stf interface is allowed. */
  218                 encap_lock_exit();
  219                 free(sc, M_DEVBUF);
  220                 return EEXIST;
  221         }
  222 
  223         sc->encap_cookie = encap_attach_func(AF_INET, IPPROTO_IPV6,
  224             stf_encapcheck, &in_stf_encapsw, sc);
  225         encap_lock_exit();
  226         if (sc->encap_cookie == NULL) {
  227                 printf("%s: unable to attach encap\n", if_name(&sc->sc_if));
  228                 free(sc, M_DEVBUF);
  229                 return EIO;     /* XXX */
  230         }
  231 
  232         sc->sc_if.if_mtu    = STF_MTU;
  233         sc->sc_if.if_flags  = 0;
  234         sc->sc_if.if_ioctl  = stf_ioctl;
  235         sc->sc_if.if_output = stf_output;
  236         sc->sc_if.if_type   = IFT_STF;
  237         sc->sc_if.if_dlt    = DLT_NULL;
  238         if_attach(&sc->sc_if);
  239         if_alloc_sadl(&sc->sc_if);
  240         bpf_attach(&sc->sc_if, DLT_NULL, sizeof(u_int));
  241         LIST_INSERT_HEAD(&stf_softc_list, sc, sc_list);
  242         return 0;
  243 }
  244 
  245 static int
  246 stf_clone_destroy(struct ifnet *ifp)
  247 {
  248         struct stf_softc *sc = (void *) ifp;
  249 
  250         encap_lock_enter();
  251         LIST_REMOVE(sc, sc_list);
  252         encap_detach(sc->encap_cookie);
  253         encap_lock_exit();
  254         bpf_detach(ifp);
  255         if_detach(ifp);
  256         rtcache_free(&sc->sc_ro);
  257         free(sc, M_DEVBUF);
  258 
  259         return 0;
  260 }
  261 
  262 static int
  263 stf_encapcheck(struct mbuf *m, int off, int proto, void *arg)
  264 {
  265         struct ip ip;
  266         struct in6_ifaddr *ia6;
  267         struct stf_softc *sc;
  268         struct in_addr a, b;
  269 
  270         sc = (struct stf_softc *)arg;
  271         if (sc == NULL)
  272                 return 0;
  273 
  274         if ((sc->sc_if.if_flags & IFF_UP) == 0)
  275                 return 0;
  276 
  277         /* IFF_LINK0 means "no decapsulation" */
  278         if ((sc->sc_if.if_flags & IFF_LINK0) != 0)
  279                 return 0;
  280 
  281         if (proto != IPPROTO_IPV6)
  282                 return 0;
  283 
  284         m_copydata(m, 0, sizeof(ip), (void *)&ip);
  285 
  286         if (ip.ip_v != 4)
  287                 return 0;
  288 
  289         ia6 = stf_getsrcifa6(&sc->sc_if);
  290         if (ia6 == NULL)
  291                 return 0;
  292 
  293         /*
  294          * check if IPv4 dst matches the IPv4 address derived from the
  295          * local 6to4 address.
  296          * success on: dst = 10.1.1.1, ia6->ia_addr = 2002:0a01:0101:...
  297          */
  298         if (memcmp(GET_V4(&ia6->ia_addr.sin6_addr), &ip.ip_dst,
  299             sizeof(ip.ip_dst)) != 0)
  300                 return 0;
  301 
  302         /*
  303          * check if IPv4 src matches the IPv4 address derived from the
  304          * local 6to4 address masked by prefixmask.
  305          * success on: src = 10.1.1.1, ia6->ia_addr = 2002:0a00:.../24
  306          * fail on: src = 10.1.1.1, ia6->ia_addr = 2002:0b00:.../24
  307          */
  308         memset(&a, 0, sizeof(a));
  309         a.s_addr = GET_V4(&ia6->ia_addr.sin6_addr)->s_addr;
  310         a.s_addr &= GET_V4(&ia6->ia_prefixmask.sin6_addr)->s_addr;
  311         b = ip.ip_src;
  312         b.s_addr &= GET_V4(&ia6->ia_prefixmask.sin6_addr)->s_addr;
  313         if (a.s_addr != b.s_addr)
  314                 return 0;
  315 
  316         /* stf interface makes single side match only */
  317         return 32;
  318 }
  319 
  320 static struct in6_ifaddr *
  321 stf_getsrcifa6(struct ifnet *ifp)
  322 {
  323         struct ifaddr *ifa;
  324         struct in_ifaddr *ia4;
  325         struct sockaddr_in6 *sin6;
  326         struct in_addr in;
  327         int s;
  328 
  329         s = pserialize_read_enter();
  330         IFADDR_READER_FOREACH(ifa, ifp) {
  331                 if (ifa->ifa_addr->sa_family != AF_INET6)
  332                         continue;
  333                 sin6 = (struct sockaddr_in6 *)ifa->ifa_addr;
  334                 if (!IN6_IS_ADDR_6TO4(&sin6->sin6_addr))
  335                         continue;
  336 
  337                 memcpy(&in, GET_V4(&sin6->sin6_addr), sizeof(in));
  338                 ia4 = in_get_ia(in);
  339                 if (ia4 == NULL)
  340                         continue;
  341 
  342                 pserialize_read_exit(s);
  343                 /* TODO NOMPSAFE */
  344                 return (struct in6_ifaddr *)ifa;
  345         }
  346         pserialize_read_exit(s);
  347 
  348         return NULL;
  349 }
  350 
  351 static int
  352 stf_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst,
  353     const struct rtentry *rt0)
  354 {
  355         struct rtentry *rt;
  356         struct stf_softc *sc;
  357         const struct sockaddr_in6 *dst6;
  358         const struct in_addr *in4;
  359         uint8_t tos;
  360         struct ip *ip;
  361         struct ip6_hdr *ip6;
  362         struct in6_ifaddr *ia6;
  363         union {
  364                 struct sockaddr         dst;
  365                 struct sockaddr_in      dst4;
  366         } u;
  367 
  368         sc = (struct stf_softc*)ifp;
  369         dst6 = (const struct sockaddr_in6 *)dst;
  370 
  371         /* just in case */
  372         if ((ifp->if_flags & IFF_UP) == 0) {
  373                 m_freem(m);
  374                 return ENETDOWN;
  375         }
  376 
  377         /*
  378          * If we don't have an ip4 address that match my inner ip6 address,
  379          * we shouldn't generate output.  Without this check, we'll end up
  380          * using wrong IPv4 source.
  381          */
  382         ia6 = stf_getsrcifa6(ifp);
  383         if (ia6 == NULL) {
  384                 m_freem(m);
  385                 if_statinc(ifp, if_oerrors);
  386                 return ENETDOWN;
  387         }
  388 
  389         if (m->m_len < sizeof(*ip6)) {
  390                 m = m_pullup(m, sizeof(*ip6));
  391                 if (m == NULL) {
  392                         if_statinc(ifp, if_oerrors);
  393                         return ENOBUFS;
  394                 }
  395         }
  396         ip6 = mtod(m, struct ip6_hdr *);
  397         tos = (ntohl(ip6->ip6_flow) >> 20) & 0xff;
  398 
  399         /*
  400          * Pickup the right outer dst addr from the list of candidates.
  401          * ip6_dst has priority as it may be able to give us shorter IPv4 hops.
  402          */
  403         if (IN6_IS_ADDR_6TO4(&ip6->ip6_dst))
  404                 in4 = GET_V4(&ip6->ip6_dst);
  405         else if (IN6_IS_ADDR_6TO4(&dst6->sin6_addr))
  406                 in4 = GET_V4(&dst6->sin6_addr);
  407         else {
  408                 m_freem(m);
  409                 if_statinc(ifp, if_oerrors);
  410                 return ENETUNREACH;
  411         }
  412 
  413         bpf_mtap_af(ifp, AF_INET6, m, BPF_D_OUT);
  414 
  415         M_PREPEND(m, sizeof(struct ip), M_DONTWAIT);
  416         if (m && m->m_len < sizeof(struct ip))
  417                 m = m_pullup(m, sizeof(struct ip));
  418         if (m == NULL) {
  419                 if_statinc(ifp, if_oerrors);
  420                 return ENOBUFS;
  421         }
  422         ip = mtod(m, struct ip *);
  423 
  424         memset(ip, 0, sizeof(*ip));
  425 
  426         bcopy(GET_V4(&((struct sockaddr_in6 *)&ia6->ia_addr)->sin6_addr),
  427             &ip->ip_src, sizeof(ip->ip_src));
  428         memcpy(&ip->ip_dst, in4, sizeof(ip->ip_dst));
  429         ip->ip_p = IPPROTO_IPV6;
  430         ip->ip_ttl = ip_stf_ttl;
  431         ip->ip_len = htons(m->m_pkthdr.len);
  432         if (ifp->if_flags & IFF_LINK1)
  433                 ip_ecn_ingress(ECN_ALLOWED, &ip->ip_tos, &tos);
  434         else
  435                 ip_ecn_ingress(ECN_NOCARE, &ip->ip_tos, &tos);
  436 
  437         sockaddr_in_init(&u.dst4, &ip->ip_dst, 0);
  438         if ((rt = rtcache_lookup(&sc->sc_ro, &u.dst)) == NULL) {
  439                 m_freem(m);
  440                 if_statinc(ifp, if_oerrors);
  441                 return ENETUNREACH;
  442         }
  443 
  444         /* If the route constitutes infinite encapsulation, punt. */
  445         if (rt->rt_ifp == ifp) {
  446                 rtcache_unref(rt, &sc->sc_ro);
  447                 rtcache_free(&sc->sc_ro);
  448                 m_freem(m);
  449                 if_statinc(ifp, if_oerrors);
  450                 return ENETUNREACH;
  451         }
  452         rtcache_unref(rt, &sc->sc_ro);
  453 
  454         if_statadd2(ifp, if_opackets, 1,
  455             if_obytes, m->m_pkthdr.len - sizeof(struct ip));
  456         return ip_output(m, NULL, &sc->sc_ro, 0, NULL, NULL);
  457 }
  458 
  459 static int
  460 isrfc1918addr(const struct in_addr *in)
  461 {
  462         /*
  463          * returns 1 if private address range:
  464          * 10.0.0.0/8 172.16.0.0/12 192.168.0.0/16
  465          */
  466         if ((ntohl(in->s_addr) & 0xff000000) >> 24 == 10 ||
  467             (ntohl(in->s_addr) & 0xfff00000) >> 16 == 172 * 256 + 16 ||
  468             (ntohl(in->s_addr) & 0xffff0000) >> 16 == 192 * 256 + 168)
  469                 return 1;
  470 
  471         return 0;
  472 }
  473 
  474 static int
  475 stf_checkaddr4(struct stf_softc *sc, const struct in_addr *in,
  476     struct ifnet *inifp /*incoming interface*/)
  477 {
  478         struct in_ifaddr *ia4;
  479 
  480         /*
  481          * reject packets with the following address:
  482          * 224.0.0.0/4 0.0.0.0/8 127.0.0.0/8 255.0.0.0/8
  483          */
  484         if (IN_MULTICAST(in->s_addr))
  485                 return -1;
  486         switch ((ntohl(in->s_addr) & 0xff000000) >> 24) {
  487         case 0: case 127: case 255:
  488                 return -1;
  489         }
  490 
  491         /*
  492          * reject packets with private address range.
  493          * (requirement from RFC3056 section 2 1st paragraph)
  494          */
  495         if (isrfc1918addr(in))
  496                 return -1;
  497 
  498         /*
  499          * reject packet with IPv4 link-local (169.254.0.0/16),
  500          * as suggested in draft-savola-v6ops-6to4-security-00.txt
  501          */
  502         if (((ntohl(in->s_addr) & 0xff000000) >> 24) == 169 &&
  503             ((ntohl(in->s_addr) & 0x00ff0000) >> 16) == 254)
  504                 return -1;
  505 
  506         /*
  507          * reject packets with broadcast
  508          */
  509         IN_ADDRLIST_READER_FOREACH(ia4) {
  510                 if ((ia4->ia_ifa.ifa_ifp->if_flags & IFF_BROADCAST) == 0)
  511                         continue;
  512                 if (in->s_addr == ia4->ia_broadaddr.sin_addr.s_addr)
  513                         return -1;
  514         }
  515 
  516         /*
  517          * perform ingress filter
  518          */
  519         if (sc && (sc->sc_if.if_flags & IFF_LINK2) == 0 && inifp) {
  520                 struct sockaddr_in sin;
  521                 struct rtentry *rt;
  522 
  523                 memset(&sin, 0, sizeof(sin));
  524                 sin.sin_family = AF_INET;
  525                 sin.sin_len = sizeof(struct sockaddr_in);
  526                 sin.sin_addr = *in;
  527                 rt = rtalloc1((struct sockaddr *)&sin, 0);
  528                 if (!rt || rt->rt_ifp != inifp) {
  529 #if 0
  530                         log(LOG_WARNING, "%s: packet from 0x%x dropped "
  531                             "due to ingress filter\n", if_name(&sc->sc_if),
  532                             (uint32_t)ntohl(sin.sin_addr.s_addr));
  533 #endif
  534                         if (rt)
  535                                 rt_unref(rt);
  536                         return -1;
  537                 }
  538                 rt_unref(rt);
  539         }
  540 
  541         return 0;
  542 }
  543 
  544 static int
  545 stf_checkaddr6(struct stf_softc *sc, const struct in6_addr *in6,
  546     struct ifnet *inifp /*incoming interface*/)
  547 {
  548 
  549         /*
  550          * check 6to4 addresses
  551          */
  552         if (IN6_IS_ADDR_6TO4(in6))
  553                 return stf_checkaddr4(sc, GET_V4(in6), inifp);
  554 
  555         /*
  556          * reject anything that look suspicious.  the test is implemented
  557          * in ip6_input too, but we check here as well to
  558          * (1) reject bad packets earlier, and
  559          * (2) to be safe against future ip6_input change.
  560          */
  561         if (IN6_IS_ADDR_V4COMPAT(in6) || IN6_IS_ADDR_V4MAPPED(in6))
  562                 return -1;
  563 
  564         /*
  565          * reject link-local and site-local unicast
  566          * as suggested in draft-savola-v6ops-6to4-security-00.txt
  567          */
  568         if (IN6_IS_ADDR_LINKLOCAL(in6) || IN6_IS_ADDR_SITELOCAL(in6))
  569                 return -1;
  570 
  571         /*
  572          * reject node-local and link-local multicast
  573          * as suggested in draft-savola-v6ops-6to4-security-00.txt
  574          */
  575         if (IN6_IS_ADDR_MC_NODELOCAL(in6) || IN6_IS_ADDR_MC_LINKLOCAL(in6))
  576                 return -1;
  577 
  578         return 0;
  579 }
  580 
  581 void
  582 in_stf_input(struct mbuf *m, int off, int proto, void *eparg)
  583 {
  584         int s;
  585         struct stf_softc *sc = eparg;
  586         struct ip *ip;
  587         struct ip6_hdr *ip6;
  588         uint8_t otos, itos;
  589         struct ifnet *ifp;
  590         size_t pktlen;
  591 
  592         KASSERT(sc != NULL);
  593 
  594         if (proto != IPPROTO_IPV6) {
  595                 m_freem(m);
  596                 return;
  597         }
  598 
  599         ip = mtod(m, struct ip *);
  600 
  601         if ((sc->sc_if.if_flags & IFF_UP) == 0) {
  602                 m_freem(m);
  603                 return;
  604         }
  605 
  606         ifp = &sc->sc_if;
  607 
  608         /*
  609          * perform sanity check against outer src/dst.
  610          * for source, perform ingress filter as well.
  611          */
  612         if (stf_checkaddr4(sc, &ip->ip_dst, NULL) < 0 ||
  613             stf_checkaddr4(sc, &ip->ip_src, m_get_rcvif_NOMPSAFE(m)) < 0) {
  614                 m_freem(m);
  615                 return;
  616         }
  617 
  618         otos = ip->ip_tos;
  619         m_adj(m, off);
  620 
  621         if (m->m_len < sizeof(*ip6)) {
  622                 m = m_pullup(m, sizeof(*ip6));
  623                 if (!m)
  624                         return;
  625         }
  626         ip6 = mtod(m, struct ip6_hdr *);
  627 
  628         /*
  629          * perform sanity check against inner src/dst.
  630          * for source, perform ingress filter as well.
  631          */
  632         if (stf_checkaddr6(sc, &ip6->ip6_dst, NULL) < 0 ||
  633             stf_checkaddr6(sc, &ip6->ip6_src, m_get_rcvif_NOMPSAFE(m)) < 0) {
  634                 m_freem(m);
  635                 return;
  636         }
  637 
  638         itos = (ntohl(ip6->ip6_flow) >> 20) & 0xff;
  639         if ((ifp->if_flags & IFF_LINK1) != 0)
  640                 ip_ecn_egress(ECN_ALLOWED, &otos, &itos);
  641         else
  642                 ip_ecn_egress(ECN_NOCARE, &otos, &itos);
  643         ip6->ip6_flow &= ~htonl(0xff << 20);
  644         ip6->ip6_flow |= htonl((uint32_t)itos << 20);
  645 
  646         pktlen = m->m_pkthdr.len;
  647         m_set_rcvif(m, ifp);
  648 
  649         bpf_mtap_af(ifp, AF_INET6, m, BPF_D_IN);
  650 
  651         /*
  652          * Put the packet to the network layer input queue according to the
  653          * specified address family.
  654          * See net/if_gif.c for possible issues with packet processing
  655          * reorder due to extra queueing.
  656          */
  657 
  658         s = splnet();
  659         if (__predict_true(pktq_enqueue(ip6_pktq, m, 0))) {
  660                 if_statadd2(ifp, if_ipackets, 1, if_ibytes, pktlen);
  661         } else {
  662                 m_freem(m);
  663         }
  664         splx(s);
  665 
  666         return;
  667 }
  668 
  669 /* ARGSUSED */
  670 static void
  671 stf_rtrequest(int cmd, struct rtentry *rt,
  672     const struct rt_addrinfo *info)
  673 {
  674         if (rt != NULL) {
  675                 struct stf_softc *sc;
  676 
  677                 sc = LIST_FIRST(&stf_softc_list);
  678                 rt->rt_rmx.rmx_mtu = (sc != NULL) ? sc->sc_if.if_mtu : STF_MTU;
  679         }
  680 }
  681 
  682 static int
  683 stf_ioctl(struct ifnet *ifp, u_long cmd, void *data)
  684 {
  685         struct ifaddr           *ifa;
  686         struct ifreq            *ifr = data;
  687         struct sockaddr_in6     *sin6;
  688         int                     error;
  689 
  690         error = 0;
  691         switch (cmd) {
  692         case SIOCINITIFADDR:
  693                 ifa = (struct ifaddr *)data;
  694                 if (ifa == NULL || ifa->ifa_addr->sa_family != AF_INET6) {
  695                         error = EAFNOSUPPORT;
  696                         break;
  697                 }
  698                 sin6 = (struct sockaddr_in6 *)ifa->ifa_addr;
  699                 if (IN6_IS_ADDR_6TO4(&sin6->sin6_addr) &&
  700                     !isrfc1918addr(GET_V4(&sin6->sin6_addr))) {
  701                         ifa->ifa_rtrequest = stf_rtrequest;
  702                         ifp->if_flags |= IFF_UP;
  703                 } else
  704                         error = EINVAL;
  705                 break;
  706 
  707         case SIOCADDMULTI:
  708         case SIOCDELMULTI:
  709                 if (ifr != NULL &&
  710                     ifreq_getaddr(cmd, ifr)->sa_family == AF_INET6)
  711                         ;
  712                 else
  713                         error = EAFNOSUPPORT;
  714                 break;
  715 
  716         case SIOCSIFMTU:
  717                 if (ifr->ifr_mtu < STF_MTU_MIN || ifr->ifr_mtu > STF_MTU_MAX)
  718                         return EINVAL;
  719                 else if ((error = ifioctl_common(ifp, cmd, data)) == ENETRESET)
  720                         error = 0;
  721                 break;
  722 
  723         default:
  724                 error = ifioctl_common(ifp, cmd, data);
  725                 break;
  726         }
  727 
  728         return error;
  729 }
  730 
  731 /*
  732  * Module infrastructure
  733  */
  734 #include "if_module.h"
  735 
  736 IF_MODULE(MODULE_CLASS_DRIVER, stf, NULL)

Cache object: 8275f36d729b4b68b337749d66cfc0ec


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.