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_gre.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_gre.c,v 1.49 2003/12/11 00:22:29 itojun Exp $ */
    2 /*       $FreeBSD: releng/10.0/sys/net/if_gre.c 255471 2013-09-11 09:19:44Z glebius $ */
    3 
    4 /*-
    5  * Copyright (c) 1998 The NetBSD Foundation, Inc.
    6  * All rights reserved.
    7  *
    8  * This code is derived from software contributed to The NetBSD Foundation
    9  * by Heiko W.Rupp <hwr@pilhuhn.de>
   10  *
   11  * IPv6-over-GRE contributed by Gert Doering <gert@greenie.muc.de>
   12  *
   13  * Redistribution and use in source and binary forms, with or without
   14  * modification, are permitted provided that the following conditions
   15  * are met:
   16  * 1. Redistributions of source code must retain the above copyright
   17  *    notice, this list of conditions and the following disclaimer.
   18  * 2. Redistributions in binary form must reproduce the above copyright
   19  *    notice, this list of conditions and the following disclaimer in the
   20  *    documentation and/or other materials provided with the distribution.
   21  *
   22  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   23  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   24  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   25  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   26  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   27  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   28  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   29  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   30  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   31  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   32  * POSSIBILITY OF SUCH DAMAGE.
   33  */
   34 
   35 /*
   36  * Encapsulate L3 protocols into IP
   37  * See RFC 2784 (successor of RFC 1701 and 1702) for more details.
   38  * If_gre is compatible with Cisco GRE tunnels, so you can
   39  * have a NetBSD box as the other end of a tunnel interface of a Cisco
   40  * router. See gre(4) for more details.
   41  * Also supported:  IP in IP encaps (proto 55) as of RFC 2004
   42  */
   43 
   44 #include "opt_atalk.h"
   45 #include "opt_inet.h"
   46 #include "opt_inet6.h"
   47 
   48 #include <sys/param.h>
   49 #include <sys/jail.h>
   50 #include <sys/kernel.h>
   51 #include <sys/libkern.h>
   52 #include <sys/malloc.h>
   53 #include <sys/module.h>
   54 #include <sys/mbuf.h>
   55 #include <sys/priv.h>
   56 #include <sys/proc.h>
   57 #include <sys/protosw.h>
   58 #include <sys/socket.h>
   59 #include <sys/sockio.h>
   60 #include <sys/sysctl.h>
   61 #include <sys/systm.h>
   62 
   63 #include <net/ethernet.h>
   64 #include <net/if.h>
   65 #include <net/if_clone.h>
   66 #include <net/if_types.h>
   67 #include <net/route.h>
   68 #include <net/vnet.h>
   69 
   70 #ifdef INET
   71 #include <netinet/in.h>
   72 #include <netinet/in_systm.h>
   73 #include <netinet/in_var.h>
   74 #include <netinet/ip.h>
   75 #include <netinet/ip_gre.h>
   76 #include <netinet/ip_var.h>
   77 #include <netinet/ip_encap.h>
   78 #else
   79 #error "Huh? if_gre without inet?"
   80 #endif
   81 
   82 #include <net/bpf.h>
   83 
   84 #include <net/if_gre.h>
   85 
   86 /*
   87  * It is not easy to calculate the right value for a GRE MTU.
   88  * We leave this task to the admin and use the same default that
   89  * other vendors use.
   90  */
   91 #define GREMTU  1476
   92 
   93 #define MTAG_COOKIE_GRE         1307983903
   94 #define MTAG_GRE_NESTING        1
   95 struct mtag_gre_nesting {
   96         uint16_t        count;
   97         uint16_t        max;
   98         struct ifnet    *ifp[];
   99 };
  100 
  101 /*
  102  * gre_mtx protects all global variables in if_gre.c.
  103  * XXX: gre_softc data not protected yet.
  104  */
  105 struct mtx gre_mtx;
  106 static const char grename[] = "gre";
  107 static MALLOC_DEFINE(M_GRE, grename, "Generic Routing Encapsulation");
  108 
  109 struct gre_softc_head gre_softc_list;
  110 
  111 static int      gre_clone_create(struct if_clone *, int, caddr_t);
  112 static void     gre_clone_destroy(struct ifnet *);
  113 static struct if_clone *gre_cloner;
  114 
  115 static int      gre_ioctl(struct ifnet *, u_long, caddr_t);
  116 static int      gre_output(struct ifnet *, struct mbuf *,
  117                     const struct sockaddr *, struct route *);
  118 
  119 static int gre_compute_route(struct gre_softc *sc);
  120 
  121 static void     greattach(void);
  122 
  123 #ifdef INET
  124 extern struct domain inetdomain;
  125 static const struct protosw in_gre_protosw = {
  126         .pr_type =              SOCK_RAW,
  127         .pr_domain =            &inetdomain,
  128         .pr_protocol =          IPPROTO_GRE,
  129         .pr_flags =             PR_ATOMIC|PR_ADDR,
  130         .pr_input =             gre_input,
  131         .pr_output =            (pr_output_t *)rip_output,
  132         .pr_ctlinput =          rip_ctlinput,
  133         .pr_ctloutput =         rip_ctloutput,
  134         .pr_usrreqs =           &rip_usrreqs
  135 };
  136 static const struct protosw in_mobile_protosw = {
  137         .pr_type =              SOCK_RAW,
  138         .pr_domain =            &inetdomain,
  139         .pr_protocol =          IPPROTO_MOBILE,
  140         .pr_flags =             PR_ATOMIC|PR_ADDR,
  141         .pr_input =             gre_mobile_input,
  142         .pr_output =            (pr_output_t *)rip_output,
  143         .pr_ctlinput =          rip_ctlinput,
  144         .pr_ctloutput =         rip_ctloutput,
  145         .pr_usrreqs =           &rip_usrreqs
  146 };
  147 #endif
  148 
  149 SYSCTL_DECL(_net_link);
  150 static SYSCTL_NODE(_net_link, IFT_TUNNEL, gre, CTLFLAG_RW, 0,
  151     "Generic Routing Encapsulation");
  152 #ifndef MAX_GRE_NEST
  153 /*
  154  * This macro controls the default upper limitation on nesting of gre tunnels.
  155  * Since, setting a large value to this macro with a careless configuration
  156  * may introduce system crash, we don't allow any nestings by default.
  157  * If you need to configure nested gre tunnels, you can define this macro
  158  * in your kernel configuration file.  However, if you do so, please be
  159  * careful to configure the tunnels so that it won't make a loop.
  160  */
  161 #define MAX_GRE_NEST 1
  162 #endif
  163 static int max_gre_nesting = MAX_GRE_NEST;
  164 SYSCTL_INT(_net_link_gre, OID_AUTO, max_nesting, CTLFLAG_RW,
  165     &max_gre_nesting, 0, "Max nested tunnels");
  166 
  167 /* ARGSUSED */
  168 static void
  169 greattach(void)
  170 {
  171 
  172         mtx_init(&gre_mtx, "gre_mtx", NULL, MTX_DEF);
  173         LIST_INIT(&gre_softc_list);
  174         gre_cloner = if_clone_simple(grename, gre_clone_create,
  175             gre_clone_destroy, 0);
  176 }
  177 
  178 static int
  179 gre_clone_create(ifc, unit, params)
  180         struct if_clone *ifc;
  181         int unit;
  182         caddr_t params;
  183 {
  184         struct gre_softc *sc;
  185 
  186         sc = malloc(sizeof(struct gre_softc), M_GRE, M_WAITOK | M_ZERO);
  187 
  188         GRE2IFP(sc) = if_alloc(IFT_TUNNEL);
  189         if (GRE2IFP(sc) == NULL) {
  190                 free(sc, M_GRE);
  191                 return (ENOSPC);
  192         }
  193 
  194         GRE2IFP(sc)->if_softc = sc;
  195         if_initname(GRE2IFP(sc), grename, unit);
  196 
  197         GRE2IFP(sc)->if_snd.ifq_maxlen = ifqmaxlen;
  198         GRE2IFP(sc)->if_addrlen = 0;
  199         GRE2IFP(sc)->if_hdrlen = 24; /* IP + GRE */
  200         GRE2IFP(sc)->if_mtu = GREMTU;
  201         GRE2IFP(sc)->if_flags = IFF_POINTOPOINT|IFF_MULTICAST;
  202         GRE2IFP(sc)->if_output = gre_output;
  203         GRE2IFP(sc)->if_ioctl = gre_ioctl;
  204         sc->g_dst.s_addr = sc->g_src.s_addr = INADDR_ANY;
  205         sc->g_proto = IPPROTO_GRE;
  206         GRE2IFP(sc)->if_flags |= IFF_LINK0;
  207         sc->encap = NULL;
  208         sc->gre_fibnum = curthread->td_proc->p_fibnum;
  209         sc->wccp_ver = WCCP_V1;
  210         sc->key = 0;
  211         if_attach(GRE2IFP(sc));
  212         bpfattach(GRE2IFP(sc), DLT_NULL, sizeof(u_int32_t));
  213         mtx_lock(&gre_mtx);
  214         LIST_INSERT_HEAD(&gre_softc_list, sc, sc_list);
  215         mtx_unlock(&gre_mtx);
  216         return (0);
  217 }
  218 
  219 static void
  220 gre_clone_destroy(ifp)
  221         struct ifnet *ifp;
  222 {
  223         struct gre_softc *sc = ifp->if_softc;
  224 
  225         mtx_lock(&gre_mtx);
  226         LIST_REMOVE(sc, sc_list);
  227         mtx_unlock(&gre_mtx);
  228 
  229 #ifdef INET
  230         if (sc->encap != NULL)
  231                 encap_detach(sc->encap);
  232 #endif
  233         bpfdetach(ifp);
  234         if_detach(ifp);
  235         if_free(ifp);
  236         free(sc, M_GRE);
  237 }
  238 
  239 /*
  240  * The output routine. Takes a packet and encapsulates it in the protocol
  241  * given by sc->g_proto. See also RFC 1701 and RFC 2004
  242  */
  243 static int
  244 gre_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst,
  245            struct route *ro)
  246 {
  247         int error = 0;
  248         struct gre_softc *sc = ifp->if_softc;
  249         struct greip *gh;
  250         struct ip *ip;
  251         struct m_tag *mtag;
  252         struct mtag_gre_nesting *gt;
  253         size_t len;
  254         u_short gre_ip_id = 0;
  255         uint8_t gre_ip_tos = 0;
  256         u_int16_t etype = 0;
  257         struct mobile_h mob_h;
  258         u_int32_t af;
  259         int extra = 0, max;
  260 
  261         /*
  262          * gre may cause infinite recursion calls when misconfigured.  High
  263          * nesting level may cause stack exhaustion.  We'll prevent this by
  264          * detecting loops and by introducing upper limit.
  265          */
  266         mtag = m_tag_locate(m, MTAG_COOKIE_GRE, MTAG_GRE_NESTING, NULL);
  267         if (mtag != NULL) {
  268                 struct ifnet **ifp2;
  269 
  270                 gt = (struct mtag_gre_nesting *)(mtag + 1);
  271                 gt->count++;
  272                 if (gt->count > min(gt->max,max_gre_nesting)) {
  273                         printf("%s: hit maximum recursion limit %u on %s\n",
  274                                 __func__, gt->count - 1, ifp->if_xname);
  275                         m_freem(m);
  276                         error = EIO;    /* is there better errno? */
  277                         goto end;
  278                 }
  279 
  280                 ifp2 = gt->ifp;
  281                 for (max = gt->count - 1; max > 0; max--) {
  282                         if (*ifp2 == ifp)
  283                                 break;
  284                         ifp2++;
  285                 }
  286                 if (*ifp2 == ifp) {
  287                         printf("%s: detected loop with nexting %u on %s\n",
  288                                 __func__, gt->count-1, ifp->if_xname);
  289                         m_freem(m);
  290                         error = EIO;    /* is there better errno? */
  291                         goto end;
  292                 }
  293                 *ifp2 = ifp;
  294 
  295         } else {
  296                 /*
  297                  * Given that people should NOT increase max_gre_nesting beyond
  298                  * their real needs, we allocate once per packet rather than
  299                  * allocating an mtag once per passing through gre.
  300                  *
  301                  * Note: the sysctl does not actually check for saneness, so we
  302                  * limit the maximum numbers of possible recursions here.
  303                  */
  304                 max = imin(max_gre_nesting, 256);
  305                 /* If someone sets the sysctl <= 0, we want at least 1. */
  306                 max = imax(max, 1);
  307                 len = sizeof(struct mtag_gre_nesting) +
  308                     max * sizeof(struct ifnet *);
  309                 mtag = m_tag_alloc(MTAG_COOKIE_GRE, MTAG_GRE_NESTING, len,
  310                     M_NOWAIT);
  311                 if (mtag == NULL) {
  312                         m_freem(m);
  313                         error = ENOMEM;
  314                         goto end;
  315                 }
  316                 gt = (struct mtag_gre_nesting *)(mtag + 1);
  317                 bzero(gt, len);
  318                 gt->count = 1;
  319                 gt->max = max;
  320                 *gt->ifp = ifp;
  321                 m_tag_prepend(m, mtag);
  322         }
  323 
  324         if (!((ifp->if_flags & IFF_UP) &&
  325             (ifp->if_drv_flags & IFF_DRV_RUNNING)) ||
  326             sc->g_src.s_addr == INADDR_ANY || sc->g_dst.s_addr == INADDR_ANY) {
  327                 m_freem(m);
  328                 error = ENETDOWN;
  329                 goto end;
  330         }
  331 
  332         gh = NULL;
  333         ip = NULL;
  334 
  335         /* BPF writes need to be handled specially. */
  336         if (dst->sa_family == AF_UNSPEC)
  337                 bcopy(dst->sa_data, &af, sizeof(af));
  338         else
  339                 af = dst->sa_family;
  340 
  341         if (bpf_peers_present(ifp->if_bpf))
  342                 bpf_mtap2(ifp->if_bpf, &af, sizeof(af), m);
  343 
  344         if ((ifp->if_flags & IFF_MONITOR) != 0) {
  345                 m_freem(m);
  346                 error = ENETDOWN;
  347                 goto end;
  348         }
  349 
  350         m->m_flags &= ~(M_BCAST|M_MCAST);
  351 
  352         if (sc->g_proto == IPPROTO_MOBILE) {
  353                 if (af == AF_INET) {
  354                         struct mbuf *m0;
  355                         int msiz;
  356 
  357                         ip = mtod(m, struct ip *);
  358 
  359                         /*
  360                          * RFC2004 specifies that fragmented diagrams shouldn't
  361                          * be encapsulated.
  362                          */
  363                         if (ip->ip_off & htons(IP_MF | IP_OFFMASK)) {
  364                                 _IF_DROP(&ifp->if_snd);
  365                                 m_freem(m);
  366                                 error = EINVAL;    /* is there better errno? */
  367                                 goto end;
  368                         }
  369                         memset(&mob_h, 0, MOB_H_SIZ_L);
  370                         mob_h.proto = (ip->ip_p) << 8;
  371                         mob_h.odst = ip->ip_dst.s_addr;
  372                         ip->ip_dst.s_addr = sc->g_dst.s_addr;
  373 
  374                         /*
  375                          * If the packet comes from our host, we only change
  376                          * the destination address in the IP header.
  377                          * Else we also need to save and change the source
  378                          */
  379                         if (in_hosteq(ip->ip_src, sc->g_src)) {
  380                                 msiz = MOB_H_SIZ_S;
  381                         } else {
  382                                 mob_h.proto |= MOB_H_SBIT;
  383                                 mob_h.osrc = ip->ip_src.s_addr;
  384                                 ip->ip_src.s_addr = sc->g_src.s_addr;
  385                                 msiz = MOB_H_SIZ_L;
  386                         }
  387                         mob_h.proto = htons(mob_h.proto);
  388                         mob_h.hcrc = gre_in_cksum((u_int16_t *)&mob_h, msiz);
  389 
  390                         if ((m->m_data - msiz) < m->m_pktdat) {
  391                                 m0 = m_gethdr(M_NOWAIT, MT_DATA);
  392                                 if (m0 == NULL) {
  393                                         _IF_DROP(&ifp->if_snd);
  394                                         m_freem(m);
  395                                         error = ENOBUFS;
  396                                         goto end;
  397                                 }
  398                                 m0->m_next = m;
  399                                 m->m_data += sizeof(struct ip);
  400                                 m->m_len -= sizeof(struct ip);
  401                                 m0->m_pkthdr.len = m->m_pkthdr.len + msiz;
  402                                 m0->m_len = msiz + sizeof(struct ip);
  403                                 m0->m_data += max_linkhdr;
  404                                 memcpy(mtod(m0, caddr_t), (caddr_t)ip,
  405                                        sizeof(struct ip));
  406                                 m = m0;
  407                         } else {  /* we have some space left in the old one */
  408                                 m->m_data -= msiz;
  409                                 m->m_len += msiz;
  410                                 m->m_pkthdr.len += msiz;
  411                                 bcopy(ip, mtod(m, caddr_t),
  412                                         sizeof(struct ip));
  413                         }
  414                         ip = mtod(m, struct ip *);
  415                         memcpy((caddr_t)(ip + 1), &mob_h, (unsigned)msiz);
  416                         ip->ip_len = htons(ntohs(ip->ip_len) + msiz);
  417                 } else {  /* AF_INET */
  418                         _IF_DROP(&ifp->if_snd);
  419                         m_freem(m);
  420                         error = EINVAL;
  421                         goto end;
  422                 }
  423         } else if (sc->g_proto == IPPROTO_GRE) {
  424                 switch (af) {
  425                 case AF_INET:
  426                         ip = mtod(m, struct ip *);
  427                         gre_ip_tos = ip->ip_tos;
  428                         gre_ip_id = ip->ip_id;
  429                         if (sc->wccp_ver == WCCP_V2) {
  430                                 extra = sizeof(uint32_t);
  431                                 etype =  WCCP_PROTOCOL_TYPE;
  432                         } else {
  433                                 etype = ETHERTYPE_IP;
  434                         }
  435                         break;
  436 #ifdef INET6
  437                 case AF_INET6:
  438                         gre_ip_id = ip_newid();
  439                         etype = ETHERTYPE_IPV6;
  440                         break;
  441 #endif
  442 #ifdef NETATALK
  443                 case AF_APPLETALK:
  444                         etype = ETHERTYPE_ATALK;
  445                         break;
  446 #endif
  447                 default:
  448                         _IF_DROP(&ifp->if_snd);
  449                         m_freem(m);
  450                         error = EAFNOSUPPORT;
  451                         goto end;
  452                 }
  453                         
  454                 /* Reserve space for GRE header + optional GRE key */
  455                 int hdrlen = sizeof(struct greip) + extra;
  456                 if (sc->key)
  457                         hdrlen += sizeof(uint32_t);
  458                 M_PREPEND(m, hdrlen, M_NOWAIT);
  459         } else {
  460                 _IF_DROP(&ifp->if_snd);
  461                 m_freem(m);
  462                 error = EINVAL;
  463                 goto end;
  464         }
  465 
  466         if (m == NULL) {        /* mbuf allocation failed */
  467                 _IF_DROP(&ifp->if_snd);
  468                 error = ENOBUFS;
  469                 goto end;
  470         }
  471 
  472         M_SETFIB(m, sc->gre_fibnum); /* The envelope may use a different FIB */
  473 
  474         gh = mtod(m, struct greip *);
  475         if (sc->g_proto == IPPROTO_GRE) {
  476                 uint32_t *options = gh->gi_options;
  477 
  478                 memset((void *)gh, 0, sizeof(struct greip) + extra);
  479                 gh->gi_ptype = htons(etype);
  480                 gh->gi_flags = 0;
  481 
  482                 /* Add key option */
  483                 if (sc->key)
  484                 {
  485                         gh->gi_flags |= htons(GRE_KP);
  486                         *(options++) = htonl(sc->key);
  487                 }
  488         }
  489 
  490         gh->gi_pr = sc->g_proto;
  491         if (sc->g_proto != IPPROTO_MOBILE) {
  492                 gh->gi_src = sc->g_src;
  493                 gh->gi_dst = sc->g_dst;
  494                 ((struct ip*)gh)->ip_v = IPPROTO_IPV4;
  495                 ((struct ip*)gh)->ip_hl = (sizeof(struct ip)) >> 2;
  496                 ((struct ip*)gh)->ip_ttl = GRE_TTL;
  497                 ((struct ip*)gh)->ip_tos = gre_ip_tos;
  498                 ((struct ip*)gh)->ip_id = gre_ip_id;
  499                 gh->gi_len = htons(m->m_pkthdr.len);
  500         }
  501 
  502         ifp->if_opackets++;
  503         ifp->if_obytes += m->m_pkthdr.len;
  504         /*
  505          * Send it off and with IP_FORWARD flag to prevent it from
  506          * overwriting the ip_id again.  ip_id is already set to the
  507          * ip_id of the encapsulated packet.
  508          */
  509         error = ip_output(m, NULL, &sc->route, IP_FORWARDING,
  510             (struct ip_moptions *)NULL, (struct inpcb *)NULL);
  511   end:
  512         if (error)
  513                 ifp->if_oerrors++;
  514         return (error);
  515 }
  516 
  517 static int
  518 gre_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
  519 {
  520         struct ifreq *ifr = (struct ifreq *)data;
  521         struct if_laddrreq *lifr = (struct if_laddrreq *)data;
  522         struct in_aliasreq *aifr = (struct in_aliasreq *)data;
  523         struct gre_softc *sc = ifp->if_softc;
  524         struct sockaddr_in si;
  525         struct sockaddr *sa = NULL;
  526         int error, adj;
  527         struct sockaddr_in sp, sm, dp, dm;
  528         uint32_t key;
  529 
  530         error = 0;
  531         adj = 0;
  532 
  533         switch (cmd) {
  534         case SIOCSIFADDR:
  535                 ifp->if_flags |= IFF_UP;
  536                 break;
  537         case SIOCSIFFLAGS:
  538                 /*
  539                  * XXXRW: Isn't this priv_check() redundant to the ifnet
  540                  * layer check?
  541                  */
  542                 if ((error = priv_check(curthread, PRIV_NET_SETIFFLAGS)) != 0)
  543                         break;
  544                 if ((ifr->ifr_flags & IFF_LINK0) != 0)
  545                         sc->g_proto = IPPROTO_GRE;
  546                 else
  547                         sc->g_proto = IPPROTO_MOBILE;
  548                 if ((ifr->ifr_flags & IFF_LINK2) != 0)
  549                         sc->wccp_ver = WCCP_V2;
  550                 else
  551                         sc->wccp_ver = WCCP_V1;
  552                 goto recompute;
  553         case SIOCSIFMTU:
  554                 /*
  555                  * XXXRW: Isn't this priv_check() redundant to the ifnet
  556                  * layer check?
  557                  */
  558                 if ((error = priv_check(curthread, PRIV_NET_SETIFMTU)) != 0)
  559                         break;
  560                 if (ifr->ifr_mtu < 576) {
  561                         error = EINVAL;
  562                         break;
  563                 }
  564                 ifp->if_mtu = ifr->ifr_mtu;
  565                 break;
  566         case SIOCGIFMTU:
  567                 ifr->ifr_mtu = GRE2IFP(sc)->if_mtu;
  568                 break;
  569         case SIOCADDMULTI:
  570                 /*
  571                  * XXXRW: Isn't this priv_checkr() redundant to the ifnet
  572                  * layer check?
  573                  */
  574                 if ((error = priv_check(curthread, PRIV_NET_ADDMULTI)) != 0)
  575                         break;
  576                 if (ifr == 0) {
  577                         error = EAFNOSUPPORT;
  578                         break;
  579                 }
  580                 switch (ifr->ifr_addr.sa_family) {
  581 #ifdef INET
  582                 case AF_INET:
  583                         break;
  584 #endif
  585 #ifdef INET6
  586                 case AF_INET6:
  587                         break;
  588 #endif
  589                 default:
  590                         error = EAFNOSUPPORT;
  591                         break;
  592                 }
  593                 break;
  594         case SIOCDELMULTI:
  595                 /*
  596                  * XXXRW: Isn't this priv_check() redundant to the ifnet
  597                  * layer check?
  598                  */
  599                 if ((error = priv_check(curthread, PRIV_NET_DELIFGROUP)) != 0)
  600                         break;
  601                 if (ifr == 0) {
  602                         error = EAFNOSUPPORT;
  603                         break;
  604                 }
  605                 switch (ifr->ifr_addr.sa_family) {
  606 #ifdef INET
  607                 case AF_INET:
  608                         break;
  609 #endif
  610 #ifdef INET6
  611                 case AF_INET6:
  612                         break;
  613 #endif
  614                 default:
  615                         error = EAFNOSUPPORT;
  616                         break;
  617                 }
  618                 break;
  619         case GRESPROTO:
  620                 /*
  621                  * XXXRW: Isn't this priv_check() redundant to the ifnet
  622                  * layer check?
  623                  */
  624                 if ((error = priv_check(curthread, PRIV_NET_GRE)) != 0)
  625                         break;
  626                 sc->g_proto = ifr->ifr_flags;
  627                 switch (sc->g_proto) {
  628                 case IPPROTO_GRE:
  629                         ifp->if_flags |= IFF_LINK0;
  630                         break;
  631                 case IPPROTO_MOBILE:
  632                         ifp->if_flags &= ~IFF_LINK0;
  633                         break;
  634                 default:
  635                         error = EPROTONOSUPPORT;
  636                         break;
  637                 }
  638                 goto recompute;
  639         case GREGPROTO:
  640                 ifr->ifr_flags = sc->g_proto;
  641                 break;
  642         case GRESADDRS:
  643         case GRESADDRD:
  644                 error = priv_check(curthread, PRIV_NET_GRE);
  645                 if (error)
  646                         return (error);
  647                 /*
  648                  * set tunnel endpoints, compute a less specific route
  649                  * to the remote end and mark if as up
  650                  */
  651                 sa = &ifr->ifr_addr;
  652                 if (cmd == GRESADDRS)
  653                         sc->g_src = (satosin(sa))->sin_addr;
  654                 if (cmd == GRESADDRD)
  655                         sc->g_dst = (satosin(sa))->sin_addr;
  656         recompute:
  657 #ifdef INET
  658                 if (sc->encap != NULL) {
  659                         encap_detach(sc->encap);
  660                         sc->encap = NULL;
  661                 }
  662 #endif
  663                 if ((sc->g_src.s_addr != INADDR_ANY) &&
  664                     (sc->g_dst.s_addr != INADDR_ANY)) {
  665                         bzero(&sp, sizeof(sp));
  666                         bzero(&sm, sizeof(sm));
  667                         bzero(&dp, sizeof(dp));
  668                         bzero(&dm, sizeof(dm));
  669                         sp.sin_len = sm.sin_len = dp.sin_len = dm.sin_len =
  670                             sizeof(struct sockaddr_in);
  671                         sp.sin_family = sm.sin_family = dp.sin_family =
  672                             dm.sin_family = AF_INET;
  673                         sp.sin_addr = sc->g_src;
  674                         dp.sin_addr = sc->g_dst;
  675                         sm.sin_addr.s_addr = dm.sin_addr.s_addr =
  676                             INADDR_BROADCAST;
  677 #ifdef INET
  678                         sc->encap = encap_attach(AF_INET, sc->g_proto,
  679                             sintosa(&sp), sintosa(&sm), sintosa(&dp),
  680                             sintosa(&dm), (sc->g_proto == IPPROTO_GRE) ?
  681                                 &in_gre_protosw : &in_mobile_protosw, sc);
  682                         if (sc->encap == NULL)
  683                                 printf("%s: unable to attach encap\n",
  684                                     if_name(GRE2IFP(sc)));
  685 #endif
  686                         if (sc->route.ro_rt != 0) /* free old route */
  687                                 RTFREE(sc->route.ro_rt);
  688                         if (gre_compute_route(sc) == 0)
  689                                 ifp->if_drv_flags |= IFF_DRV_RUNNING;
  690                         else
  691                                 ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
  692                 }
  693                 break;
  694         case GREGADDRS:
  695                 memset(&si, 0, sizeof(si));
  696                 si.sin_family = AF_INET;
  697                 si.sin_len = sizeof(struct sockaddr_in);
  698                 si.sin_addr.s_addr = sc->g_src.s_addr;
  699                 sa = sintosa(&si);
  700                 error = prison_if(curthread->td_ucred, sa);
  701                 if (error != 0)
  702                         break;
  703                 ifr->ifr_addr = *sa;
  704                 break;
  705         case GREGADDRD:
  706                 memset(&si, 0, sizeof(si));
  707                 si.sin_family = AF_INET;
  708                 si.sin_len = sizeof(struct sockaddr_in);
  709                 si.sin_addr.s_addr = sc->g_dst.s_addr;
  710                 sa = sintosa(&si);
  711                 error = prison_if(curthread->td_ucred, sa);
  712                 if (error != 0)
  713                         break;
  714                 ifr->ifr_addr = *sa;
  715                 break;
  716         case SIOCSIFPHYADDR:
  717                 /*
  718                  * XXXRW: Isn't this priv_check() redundant to the ifnet
  719                  * layer check?
  720                  */
  721                 if ((error = priv_check(curthread, PRIV_NET_SETIFPHYS)) != 0)
  722                         break;
  723                 if (aifr->ifra_addr.sin_family != AF_INET ||
  724                     aifr->ifra_dstaddr.sin_family != AF_INET) {
  725                         error = EAFNOSUPPORT;
  726                         break;
  727                 }
  728                 if (aifr->ifra_addr.sin_len != sizeof(si) ||
  729                     aifr->ifra_dstaddr.sin_len != sizeof(si)) {
  730                         error = EINVAL;
  731                         break;
  732                 }
  733                 sc->g_src = aifr->ifra_addr.sin_addr;
  734                 sc->g_dst = aifr->ifra_dstaddr.sin_addr;
  735                 goto recompute;
  736         case SIOCSLIFPHYADDR:
  737                 /*
  738                  * XXXRW: Isn't this priv_check() redundant to the ifnet
  739                  * layer check?
  740                  */
  741                 if ((error = priv_check(curthread, PRIV_NET_SETIFPHYS)) != 0)
  742                         break;
  743                 if (lifr->addr.ss_family != AF_INET ||
  744                     lifr->dstaddr.ss_family != AF_INET) {
  745                         error = EAFNOSUPPORT;
  746                         break;
  747                 }
  748                 if (lifr->addr.ss_len != sizeof(si) ||
  749                     lifr->dstaddr.ss_len != sizeof(si)) {
  750                         error = EINVAL;
  751                         break;
  752                 }
  753                 sc->g_src = (satosin(&lifr->addr))->sin_addr;
  754                 sc->g_dst =
  755                     (satosin(&lifr->dstaddr))->sin_addr;
  756                 goto recompute;
  757         case SIOCDIFPHYADDR:
  758                 /*
  759                  * XXXRW: Isn't this priv_check() redundant to the ifnet
  760                  * layer check?
  761                  */
  762                 if ((error = priv_check(curthread, PRIV_NET_SETIFPHYS)) != 0)
  763                         break;
  764                 sc->g_src.s_addr = INADDR_ANY;
  765                 sc->g_dst.s_addr = INADDR_ANY;
  766                 goto recompute;
  767         case SIOCGLIFPHYADDR:
  768                 if (sc->g_src.s_addr == INADDR_ANY ||
  769                     sc->g_dst.s_addr == INADDR_ANY) {
  770                         error = EADDRNOTAVAIL;
  771                         break;
  772                 }
  773                 memset(&si, 0, sizeof(si));
  774                 si.sin_family = AF_INET;
  775                 si.sin_len = sizeof(struct sockaddr_in);
  776                 si.sin_addr.s_addr = sc->g_src.s_addr;
  777                 error = prison_if(curthread->td_ucred, (struct sockaddr *)&si);
  778                 if (error != 0)
  779                         break;
  780                 memcpy(&lifr->addr, &si, sizeof(si));
  781                 si.sin_addr.s_addr = sc->g_dst.s_addr;
  782                 error = prison_if(curthread->td_ucred, (struct sockaddr *)&si);
  783                 if (error != 0)
  784                         break;
  785                 memcpy(&lifr->dstaddr, &si, sizeof(si));
  786                 break;
  787         case SIOCGIFPSRCADDR:
  788 #ifdef INET6
  789         case SIOCGIFPSRCADDR_IN6:
  790 #endif
  791                 if (sc->g_src.s_addr == INADDR_ANY) {
  792                         error = EADDRNOTAVAIL;
  793                         break;
  794                 }
  795                 memset(&si, 0, sizeof(si));
  796                 si.sin_family = AF_INET;
  797                 si.sin_len = sizeof(struct sockaddr_in);
  798                 si.sin_addr.s_addr = sc->g_src.s_addr;
  799                 error = prison_if(curthread->td_ucred, (struct sockaddr *)&si);
  800                 if (error != 0)
  801                         break;
  802                 bcopy(&si, &ifr->ifr_addr, sizeof(ifr->ifr_addr));
  803                 break;
  804         case SIOCGIFPDSTADDR:
  805 #ifdef INET6
  806         case SIOCGIFPDSTADDR_IN6:
  807 #endif
  808                 if (sc->g_dst.s_addr == INADDR_ANY) {
  809                         error = EADDRNOTAVAIL;
  810                         break;
  811                 }
  812                 memset(&si, 0, sizeof(si));
  813                 si.sin_family = AF_INET;
  814                 si.sin_len = sizeof(struct sockaddr_in);
  815                 si.sin_addr.s_addr = sc->g_dst.s_addr;
  816                 error = prison_if(curthread->td_ucred, (struct sockaddr *)&si);
  817                 if (error != 0)
  818                         break;
  819                 bcopy(&si, &ifr->ifr_addr, sizeof(ifr->ifr_addr));
  820                 break;
  821         case GRESKEY:
  822                 error = priv_check(curthread, PRIV_NET_GRE);
  823                 if (error)
  824                         break;
  825                 error = copyin(ifr->ifr_data, &key, sizeof(key));
  826                 if (error)
  827                         break;
  828                 /* adjust MTU for option header */
  829                 if (key == 0 && sc->key != 0)           /* clear */
  830                         adj += sizeof(key);
  831                 else if (key != 0 && sc->key == 0)      /* set */
  832                         adj -= sizeof(key);
  833 
  834                 if (ifp->if_mtu + adj < 576) {
  835                         error = EINVAL;
  836                         break;
  837                 }
  838                 ifp->if_mtu += adj;
  839                 sc->key = key;
  840                 break;
  841         case GREGKEY:
  842                 error = copyout(&sc->key, ifr->ifr_data, sizeof(sc->key));
  843                 break;
  844 
  845         default:
  846                 error = EINVAL;
  847                 break;
  848         }
  849 
  850         return (error);
  851 }
  852 
  853 /*
  854  * computes a route to our destination that is not the one
  855  * which would be taken by ip_output(), as this one will loop back to
  856  * us. If the interface is p2p as  a--->b, then a routing entry exists
  857  * If we now send a packet to b (e.g. ping b), this will come down here
  858  * gets src=a, dst=b tacked on and would from ip_output() sent back to
  859  * if_gre.
  860  * Goal here is to compute a route to b that is less specific than
  861  * a-->b. We know that this one exists as in normal operation we have
  862  * at least a default route which matches.
  863  */
  864 static int
  865 gre_compute_route(struct gre_softc *sc)
  866 {
  867         struct route *ro;
  868 
  869         ro = &sc->route;
  870 
  871         memset(ro, 0, sizeof(struct route));
  872         ((struct sockaddr_in *)&ro->ro_dst)->sin_addr = sc->g_dst;
  873         ro->ro_dst.sa_family = AF_INET;
  874         ro->ro_dst.sa_len = sizeof(ro->ro_dst);
  875 
  876         /*
  877          * toggle last bit, so our interface is not found, but a less
  878          * specific route. I'd rather like to specify a shorter mask,
  879          * but this is not possible. Should work though. XXX
  880          * XXX MRT Use a different FIB for the tunnel to solve this problem.
  881          */
  882         if ((GRE2IFP(sc)->if_flags & IFF_LINK1) == 0) {
  883                 ((struct sockaddr_in *)&ro->ro_dst)->sin_addr.s_addr ^=
  884                     htonl(0x01);
  885         }
  886 
  887 #ifdef DIAGNOSTIC
  888         printf("%s: searching for a route to %s", if_name(GRE2IFP(sc)),
  889             inet_ntoa(((struct sockaddr_in *)&ro->ro_dst)->sin_addr));
  890 #endif
  891 
  892         rtalloc_fib(ro, sc->gre_fibnum);
  893 
  894         /*
  895          * check if this returned a route at all and this route is no
  896          * recursion to ourself
  897          */
  898         if (ro->ro_rt == NULL || ro->ro_rt->rt_ifp->if_softc == sc) {
  899 #ifdef DIAGNOSTIC
  900                 if (ro->ro_rt == NULL)
  901                         printf(" - no route found!\n");
  902                 else
  903                         printf(" - route loops back to ourself!\n");
  904 #endif
  905                 return EADDRNOTAVAIL;
  906         }
  907 
  908         /*
  909          * now change it back - else ip_output will just drop
  910          * the route and search one to this interface ...
  911          */
  912         if ((GRE2IFP(sc)->if_flags & IFF_LINK1) == 0)
  913                 ((struct sockaddr_in *)&ro->ro_dst)->sin_addr = sc->g_dst;
  914 
  915 #ifdef DIAGNOSTIC
  916         printf(", choosing %s with gateway %s", if_name(ro->ro_rt->rt_ifp),
  917             inet_ntoa(((struct sockaddr_in *)(ro->ro_rt->rt_gateway))->sin_addr));
  918         printf("\n");
  919 #endif
  920 
  921         return 0;
  922 }
  923 
  924 /*
  925  * do a checksum of a buffer - much like in_cksum, which operates on
  926  * mbufs.
  927  */
  928 u_int16_t
  929 gre_in_cksum(u_int16_t *p, u_int len)
  930 {
  931         u_int32_t sum = 0;
  932         int nwords = len >> 1;
  933 
  934         while (nwords-- != 0)
  935                 sum += *p++;
  936 
  937         if (len & 1) {
  938                 union {
  939                         u_short w;
  940                         u_char c[2];
  941                 } u;
  942                 u.c[0] = *(u_char *)p;
  943                 u.c[1] = 0;
  944                 sum += u.w;
  945         }
  946 
  947         /* end-around-carry */
  948         sum = (sum >> 16) + (sum & 0xffff);
  949         sum += (sum >> 16);
  950         return (~sum);
  951 }
  952 
  953 static int
  954 gremodevent(module_t mod, int type, void *data)
  955 {
  956 
  957         switch (type) {
  958         case MOD_LOAD:
  959                 greattach();
  960                 break;
  961         case MOD_UNLOAD:
  962                 if_clone_detach(gre_cloner);
  963                 mtx_destroy(&gre_mtx);
  964                 break;
  965         default:
  966                 return EOPNOTSUPP;
  967         }
  968         return 0;
  969 }
  970 
  971 static moduledata_t gre_mod = {
  972         "if_gre",
  973         gremodevent,
  974         0
  975 };
  976 
  977 DECLARE_MODULE(if_gre, gre_mod, SI_SUB_PSEUDO, SI_ORDER_ANY);
  978 MODULE_VERSION(if_gre, 1);

Cache object: 93e62d2b908b05dd167f67816878cd6e


[ 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.