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_gif.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 /*      $FreeBSD: releng/8.0/sys/net/if_gif.c 196019 2009-08-01 19:26:27Z rwatson $     */
    2 /*      $KAME: if_gif.c,v 1.87 2001/10/19 08:50:27 itojun Exp $ */
    3 
    4 /*-
    5  * Copyright (C) 1995, 1996, 1997, and 1998 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 #include "opt_inet.h"
   34 #include "opt_inet6.h"
   35 
   36 #include <sys/param.h>
   37 #include <sys/systm.h>
   38 #include <sys/kernel.h>
   39 #include <sys/malloc.h>
   40 #include <sys/mbuf.h>
   41 #include <sys/module.h>
   42 #include <sys/socket.h>
   43 #include <sys/sockio.h>
   44 #include <sys/errno.h>
   45 #include <sys/time.h>
   46 #include <sys/sysctl.h>
   47 #include <sys/syslog.h>
   48 #include <sys/priv.h>
   49 #include <sys/proc.h>
   50 #include <sys/protosw.h>
   51 #include <sys/conf.h>
   52 #include <machine/cpu.h>
   53 
   54 #include <net/if.h>
   55 #include <net/if_clone.h>
   56 #include <net/if_types.h>
   57 #include <net/netisr.h>
   58 #include <net/route.h>
   59 #include <net/bpf.h>
   60 #include <net/vnet.h>
   61 
   62 #include <netinet/in.h>
   63 #include <netinet/in_systm.h>
   64 #include <netinet/ip.h>
   65 #ifdef  INET
   66 #include <netinet/in_var.h>
   67 #include <netinet/in_gif.h>
   68 #include <netinet/ip_var.h>
   69 #endif  /* INET */
   70 
   71 #ifdef INET6
   72 #ifndef INET
   73 #include <netinet/in.h>
   74 #endif
   75 #include <netinet6/in6_var.h>
   76 #include <netinet/ip6.h>
   77 #include <netinet6/ip6_var.h>
   78 #include <netinet6/scope6_var.h>
   79 #include <netinet6/in6_gif.h>
   80 #include <netinet6/ip6protosw.h>
   81 #endif /* INET6 */
   82 
   83 #include <netinet/ip_encap.h>
   84 #include <net/ethernet.h>
   85 #include <net/if_bridgevar.h>
   86 #include <net/if_gif.h>
   87 
   88 #include <security/mac/mac_framework.h>
   89 
   90 #define GIFNAME         "gif"
   91 
   92 /*
   93  * gif_mtx protects the global gif_softc_list.
   94  */
   95 static struct mtx gif_mtx;
   96 static MALLOC_DEFINE(M_GIF, "gif", "Generic Tunnel Interface");
   97 
   98 static VNET_DEFINE(LIST_HEAD(, gif_softc), gif_softc_list);
   99 
  100 #define V_gif_softc_list        VNET(gif_softc_list)
  101 
  102 #ifdef INET
  103 VNET_DEFINE(int, ip_gif_ttl) = GIF_TTL;
  104 #define V_ip_gif_ttl            VNET(ip_gif_ttl)
  105 #endif
  106 #ifdef INET6
  107 VNET_DEFINE(int, ip6_gif_hlim) = GIF_HLIM;
  108 #define V_ip6_gif_hlim          VNET(ip6_gif_hlim)
  109 #endif
  110 
  111 void    (*ng_gif_input_p)(struct ifnet *ifp, struct mbuf **mp, int af);
  112 void    (*ng_gif_input_orphan_p)(struct ifnet *ifp, struct mbuf *m, int af);
  113 void    (*ng_gif_attach_p)(struct ifnet *ifp);
  114 void    (*ng_gif_detach_p)(struct ifnet *ifp);
  115 
  116 static void     gif_start(struct ifnet *);
  117 static int      gif_clone_create(struct if_clone *, int, caddr_t);
  118 static void     gif_clone_destroy(struct ifnet *);
  119 
  120 IFC_SIMPLE_DECLARE(gif, 0);
  121 
  122 static int gifmodevent(module_t, int, void *);
  123 
  124 SYSCTL_DECL(_net_link);
  125 SYSCTL_NODE(_net_link, IFT_GIF, gif, CTLFLAG_RW, 0,
  126     "Generic Tunnel Interface");
  127 #ifndef MAX_GIF_NEST
  128 /*
  129  * This macro controls the default upper limitation on nesting of gif tunnels.
  130  * Since, setting a large value to this macro with a careless configuration
  131  * may introduce system crash, we don't allow any nestings by default.
  132  * If you need to configure nested gif tunnels, you can define this macro
  133  * in your kernel configuration file.  However, if you do so, please be
  134  * careful to configure the tunnels so that it won't make a loop.
  135  */
  136 #define MAX_GIF_NEST 1
  137 #endif
  138 
  139 static VNET_DEFINE(int, max_gif_nesting) = MAX_GIF_NEST;
  140 #define V_max_gif_nesting       VNET(max_gif_nesting)
  141 
  142 SYSCTL_VNET_INT(_net_link_gif, OID_AUTO, max_nesting, CTLFLAG_RW,
  143     &VNET_NAME(max_gif_nesting), 0, "Max nested tunnels");
  144 
  145 #ifdef INET6
  146 SYSCTL_DECL(_net_inet6_ip6);
  147 SYSCTL_VNET_INT(_net_inet6_ip6, IPV6CTL_GIF_HLIM, gifhlim, CTLFLAG_RW,
  148     &VNET_NAME(ip6_gif_hlim), 0, "");
  149 #endif
  150 
  151 /*
  152  * By default, we disallow creation of multiple tunnels between the same
  153  * pair of addresses.  Some applications require this functionality so
  154  * we allow control over this check here.
  155  */
  156 #ifdef XBONEHACK
  157 static VNET_DEFINE(int, parallel_tunnels) = 1;
  158 #else
  159 static VNET_DEFINE(int, parallel_tunnels) = 0;
  160 #endif
  161 #define V_parallel_tunnels      VNET(parallel_tunnels)
  162 
  163 SYSCTL_VNET_INT(_net_link_gif, OID_AUTO, parallel_tunnels, CTLFLAG_RW,
  164     &VNET_NAME(parallel_tunnels), 0, "Allow parallel tunnels?");
  165 
  166 /* copy from src/sys/net/if_ethersubr.c */
  167 static const u_char etherbroadcastaddr[ETHER_ADDR_LEN] =
  168                         { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
  169 #ifndef ETHER_IS_BROADCAST
  170 #define ETHER_IS_BROADCAST(addr) \
  171         (bcmp(etherbroadcastaddr, (addr), ETHER_ADDR_LEN) == 0)
  172 #endif
  173 
  174 static int
  175 gif_clone_create(ifc, unit, params)
  176         struct if_clone *ifc;
  177         int unit;
  178         caddr_t params;
  179 {
  180         struct gif_softc *sc;
  181 
  182         sc = malloc(sizeof(struct gif_softc), M_GIF, M_WAITOK | M_ZERO);
  183         sc->gif_fibnum = curthread->td_proc->p_fibnum;
  184         GIF2IFP(sc) = if_alloc(IFT_GIF);
  185         if (GIF2IFP(sc) == NULL) {
  186                 free(sc, M_GIF);
  187                 return (ENOSPC);
  188         }
  189 
  190         GIF_LOCK_INIT(sc);
  191 
  192         GIF2IFP(sc)->if_softc = sc;
  193         if_initname(GIF2IFP(sc), ifc->ifc_name, unit);
  194 
  195         sc->encap_cookie4 = sc->encap_cookie6 = NULL;
  196         sc->gif_options = GIF_ACCEPT_REVETHIP;
  197 
  198         GIF2IFP(sc)->if_addrlen = 0;
  199         GIF2IFP(sc)->if_mtu    = GIF_MTU;
  200         GIF2IFP(sc)->if_flags  = IFF_POINTOPOINT | IFF_MULTICAST;
  201 #if 0
  202         /* turn off ingress filter */
  203         GIF2IFP(sc)->if_flags  |= IFF_LINK2;
  204 #endif
  205         GIF2IFP(sc)->if_ioctl  = gif_ioctl;
  206         GIF2IFP(sc)->if_start  = gif_start;
  207         GIF2IFP(sc)->if_output = gif_output;
  208         GIF2IFP(sc)->if_snd.ifq_maxlen = IFQ_MAXLEN;
  209         if_attach(GIF2IFP(sc));
  210         bpfattach(GIF2IFP(sc), DLT_NULL, sizeof(u_int32_t));
  211         if (ng_gif_attach_p != NULL)
  212                 (*ng_gif_attach_p)(GIF2IFP(sc));
  213 
  214         mtx_lock(&gif_mtx);
  215         LIST_INSERT_HEAD(&V_gif_softc_list, sc, gif_list);
  216         mtx_unlock(&gif_mtx);
  217 
  218         return (0);
  219 }
  220 
  221 static void
  222 gif_clone_destroy(ifp)
  223         struct ifnet *ifp;
  224 {
  225 #if defined(INET) || defined(INET6)
  226         int err;
  227 #endif
  228         struct gif_softc *sc = ifp->if_softc;
  229 
  230         mtx_lock(&gif_mtx);
  231         LIST_REMOVE(sc, gif_list);
  232         mtx_unlock(&gif_mtx);
  233 
  234         gif_delete_tunnel(ifp);
  235 #ifdef INET6
  236         if (sc->encap_cookie6 != NULL) {
  237                 err = encap_detach(sc->encap_cookie6);
  238                 KASSERT(err == 0, ("Unexpected error detaching encap_cookie6"));
  239         }
  240 #endif
  241 #ifdef INET
  242         if (sc->encap_cookie4 != NULL) {
  243                 err = encap_detach(sc->encap_cookie4);
  244                 KASSERT(err == 0, ("Unexpected error detaching encap_cookie4"));
  245         }
  246 #endif
  247 
  248         if (ng_gif_detach_p != NULL)
  249                 (*ng_gif_detach_p)(ifp);
  250         bpfdetach(ifp);
  251         if_detach(ifp);
  252         if_free(ifp);
  253 
  254         GIF_LOCK_DESTROY(sc);
  255 
  256         free(sc, M_GIF);
  257 }
  258 
  259 static void
  260 vnet_gif_init(const void *unused __unused)
  261 {
  262 
  263         LIST_INIT(&V_gif_softc_list);
  264 }
  265 VNET_SYSINIT(vnet_gif_init, SI_SUB_PSEUDO, SI_ORDER_MIDDLE, vnet_gif_init,
  266     NULL);
  267 
  268 static int
  269 gifmodevent(mod, type, data)
  270         module_t mod;
  271         int type;
  272         void *data;
  273 {
  274 
  275         switch (type) {
  276         case MOD_LOAD:
  277                 mtx_init(&gif_mtx, "gif_mtx", NULL, MTX_DEF);
  278                 if_clone_attach(&gif_cloner);
  279                 break;
  280 
  281         case MOD_UNLOAD:
  282                 if_clone_detach(&gif_cloner);
  283                 mtx_destroy(&gif_mtx);
  284                 break;
  285         default:
  286                 return EOPNOTSUPP;
  287         }
  288         return 0;
  289 }
  290 
  291 static moduledata_t gif_mod = {
  292         "if_gif",
  293         gifmodevent,
  294         0
  295 };
  296 
  297 DECLARE_MODULE(if_gif, gif_mod, SI_SUB_PSEUDO, SI_ORDER_ANY);
  298 MODULE_VERSION(if_gif, 1);
  299 
  300 int
  301 gif_encapcheck(m, off, proto, arg)
  302         const struct mbuf *m;
  303         int off;
  304         int proto;
  305         void *arg;
  306 {
  307         struct ip ip;
  308         struct gif_softc *sc;
  309 
  310         sc = (struct gif_softc *)arg;
  311         if (sc == NULL)
  312                 return 0;
  313 
  314         if ((GIF2IFP(sc)->if_flags & IFF_UP) == 0)
  315                 return 0;
  316 
  317         /* no physical address */
  318         if (!sc->gif_psrc || !sc->gif_pdst)
  319                 return 0;
  320 
  321         switch (proto) {
  322 #ifdef INET
  323         case IPPROTO_IPV4:
  324                 break;
  325 #endif
  326 #ifdef INET6
  327         case IPPROTO_IPV6:
  328                 break;
  329 #endif
  330         case IPPROTO_ETHERIP:
  331                 break;
  332 
  333         default:
  334                 return 0;
  335         }
  336 
  337         /* Bail on short packets */
  338         if (m->m_pkthdr.len < sizeof(ip))
  339                 return 0;
  340 
  341         m_copydata(m, 0, sizeof(ip), (caddr_t)&ip);
  342 
  343         switch (ip.ip_v) {
  344 #ifdef INET
  345         case 4:
  346                 if (sc->gif_psrc->sa_family != AF_INET ||
  347                     sc->gif_pdst->sa_family != AF_INET)
  348                         return 0;
  349                 return gif_encapcheck4(m, off, proto, arg);
  350 #endif
  351 #ifdef INET6
  352         case 6:
  353                 if (m->m_pkthdr.len < sizeof(struct ip6_hdr))
  354                         return 0;
  355                 if (sc->gif_psrc->sa_family != AF_INET6 ||
  356                     sc->gif_pdst->sa_family != AF_INET6)
  357                         return 0;
  358                 return gif_encapcheck6(m, off, proto, arg);
  359 #endif
  360         default:
  361                 return 0;
  362         }
  363 }
  364 
  365 static void
  366 gif_start(struct ifnet *ifp)
  367 {
  368         struct gif_softc *sc;
  369         struct mbuf *m;
  370 
  371         sc = ifp->if_softc;
  372 
  373         ifp->if_drv_flags |= IFF_DRV_OACTIVE;
  374         for (;;) {
  375                 IFQ_DEQUEUE(&ifp->if_snd, m);
  376                 if (m == 0)
  377                         break;
  378 
  379                 gif_output(ifp, m, sc->gif_pdst, NULL);
  380 
  381         }
  382         ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
  383 
  384         return;
  385 }
  386 
  387 int
  388 gif_output(ifp, m, dst, ro)
  389         struct ifnet *ifp;
  390         struct mbuf *m;
  391         struct sockaddr *dst;
  392         struct route *ro;
  393 {
  394         struct gif_softc *sc = ifp->if_softc;
  395         struct m_tag *mtag;
  396         int error = 0;
  397         int gif_called;
  398         u_int32_t af;
  399 
  400 #ifdef MAC
  401         error = mac_ifnet_check_transmit(ifp, m);
  402         if (error) {
  403                 m_freem(m);
  404                 goto end;
  405         }
  406 #endif
  407 
  408         /*
  409          * gif may cause infinite recursion calls when misconfigured.
  410          * We'll prevent this by detecting loops.
  411          *
  412          * High nesting level may cause stack exhaustion.
  413          * We'll prevent this by introducing upper limit.
  414          */
  415         gif_called = 1;
  416         mtag = m_tag_locate(m, MTAG_GIF, MTAG_GIF_CALLED, NULL);
  417         while (mtag != NULL) {
  418                 if (*(struct ifnet **)(mtag + 1) == ifp) {
  419                         log(LOG_NOTICE,
  420                             "gif_output: loop detected on %s\n",
  421                             (*(struct ifnet **)(mtag + 1))->if_xname);
  422                         m_freem(m);
  423                         error = EIO;    /* is there better errno? */
  424                         goto end;
  425                 }
  426                 mtag = m_tag_locate(m, MTAG_GIF, MTAG_GIF_CALLED, mtag);
  427                 gif_called++;
  428         }
  429         if (gif_called > V_max_gif_nesting) {
  430                 log(LOG_NOTICE,
  431                     "gif_output: recursively called too many times(%d)\n",
  432                     gif_called);
  433                 m_freem(m);
  434                 error = EIO;    /* is there better errno? */
  435                 goto end;
  436         }
  437         mtag = m_tag_alloc(MTAG_GIF, MTAG_GIF_CALLED, sizeof(struct ifnet *),
  438             M_NOWAIT);
  439         if (mtag == NULL) {
  440                 m_freem(m);
  441                 error = ENOMEM;
  442                 goto end;
  443         }
  444         *(struct ifnet **)(mtag + 1) = ifp;
  445         m_tag_prepend(m, mtag);
  446 
  447         m->m_flags &= ~(M_BCAST|M_MCAST);
  448 
  449         GIF_LOCK(sc);
  450 
  451         if (!(ifp->if_flags & IFF_UP) ||
  452             sc->gif_psrc == NULL || sc->gif_pdst == NULL) {
  453                 GIF_UNLOCK(sc);
  454                 m_freem(m);
  455                 error = ENETDOWN;
  456                 goto end;
  457         }
  458 
  459         /* BPF writes need to be handled specially. */
  460         if (dst->sa_family == AF_UNSPEC) {
  461                 bcopy(dst->sa_data, &af, sizeof(af));
  462                 dst->sa_family = af;
  463         }
  464 
  465         af = dst->sa_family;
  466         BPF_MTAP2(ifp, &af, sizeof(af), m);
  467         ifp->if_opackets++;     
  468         ifp->if_obytes += m->m_pkthdr.len;
  469 
  470         /* override to IPPROTO_ETHERIP for bridged traffic */
  471         if (ifp->if_bridge)
  472                 af = AF_LINK;
  473 
  474         M_SETFIB(m, sc->gif_fibnum);
  475         /* inner AF-specific encapsulation */
  476 
  477         /* XXX should we check if our outer source is legal? */
  478 
  479         /* dispatch to output logic based on outer AF */
  480         switch (sc->gif_psrc->sa_family) {
  481 #ifdef INET
  482         case AF_INET:
  483                 error = in_gif_output(ifp, af, m);
  484                 break;
  485 #endif
  486 #ifdef INET6
  487         case AF_INET6:
  488                 error = in6_gif_output(ifp, af, m);
  489                 break;
  490 #endif
  491         default:
  492                 m_freem(m);             
  493                 error = ENETDOWN;
  494         }
  495 
  496         GIF_UNLOCK(sc);
  497   end:
  498         if (error)
  499                 ifp->if_oerrors++;
  500         return (error);
  501 }
  502 
  503 void
  504 gif_input(m, af, ifp)
  505         struct mbuf *m;
  506         int af;
  507         struct ifnet *ifp;
  508 {
  509         int isr, n;
  510         struct gif_softc *sc = ifp->if_softc;
  511         struct etherip_header *eip;
  512         struct ether_header *eh;
  513         struct ifnet *oldifp;
  514 
  515         if (ifp == NULL) {
  516                 /* just in case */
  517                 m_freem(m);
  518                 return;
  519         }
  520 
  521         m->m_pkthdr.rcvif = ifp;
  522 
  523 #ifdef MAC
  524         mac_ifnet_create_mbuf(ifp, m);
  525 #endif
  526 
  527         if (bpf_peers_present(ifp->if_bpf)) {
  528                 u_int32_t af1 = af;
  529                 bpf_mtap2(ifp->if_bpf, &af1, sizeof(af1), m);
  530         }
  531 
  532         if (ng_gif_input_p != NULL) {
  533                 (*ng_gif_input_p)(ifp, &m, af);
  534                 if (m == NULL)
  535                         return;
  536         }
  537 
  538         /*
  539          * Put the packet to the network layer input queue according to the
  540          * specified address family.
  541          * Note: older versions of gif_input directly called network layer
  542          * input functions, e.g. ip6_input, here.  We changed the policy to
  543          * prevent too many recursive calls of such input functions, which
  544          * might cause kernel panic.  But the change may introduce another
  545          * problem; if the input queue is full, packets are discarded.
  546          * The kernel stack overflow really happened, and we believed
  547          * queue-full rarely occurs, so we changed the policy.
  548          */
  549         switch (af) {
  550 #ifdef INET
  551         case AF_INET:
  552                 isr = NETISR_IP;
  553                 break;
  554 #endif
  555 #ifdef INET6
  556         case AF_INET6:
  557                 isr = NETISR_IPV6;
  558                 break;
  559 #endif
  560         case AF_LINK:
  561                 n = sizeof(struct etherip_header) + sizeof(struct ether_header);
  562                 if (n > m->m_len) {
  563                         m = m_pullup(m, n);
  564                         if (m == NULL) {
  565                                 ifp->if_ierrors++;
  566                                 return;
  567                         }
  568                 }
  569 
  570                 eip = mtod(m, struct etherip_header *);
  571                 /* 
  572                  * GIF_ACCEPT_REVETHIP (enabled by default) intentionally
  573                  * accepts an EtherIP packet with revered version field in
  574                  * the header.  This is a knob for backward compatibility
  575                  * with FreeBSD 7.2R or prior.
  576                  */
  577                 if (sc->gif_options & GIF_ACCEPT_REVETHIP) {
  578                         if (eip->eip_resvl != ETHERIP_VERSION
  579                             && eip->eip_ver != ETHERIP_VERSION) {
  580                                 /* discard unknown versions */
  581                                 m_freem(m);
  582                                 return;
  583                         }
  584                 } else {
  585                         if (eip->eip_ver != ETHERIP_VERSION) {
  586                                 /* discard unknown versions */
  587                                 m_freem(m);
  588                                 return;
  589                         }
  590                 }
  591                 m_adj(m, sizeof(struct etherip_header));
  592 
  593                 m->m_flags &= ~(M_BCAST|M_MCAST);
  594                 m->m_pkthdr.rcvif = ifp;
  595 
  596                 if (ifp->if_bridge) {
  597                         oldifp = ifp;
  598                         eh = mtod(m, struct ether_header *);
  599                         if (ETHER_IS_MULTICAST(eh->ether_dhost)) {
  600                                 if (ETHER_IS_BROADCAST(eh->ether_dhost))
  601                                         m->m_flags |= M_BCAST;
  602                                 else
  603                                         m->m_flags |= M_MCAST;
  604                                 ifp->if_imcasts++;
  605                         }
  606                         BRIDGE_INPUT(ifp, m);
  607 
  608                         if (m != NULL && ifp != oldifp) {
  609                                 /*
  610                                  * The bridge gave us back itself or one of the
  611                                  * members for which the frame is addressed.
  612                                  */
  613                                 ether_demux(ifp, m);
  614                                 return;
  615                         }
  616                 }
  617                 if (m != NULL)
  618                         m_freem(m);
  619                 return;
  620 
  621         default:
  622                 if (ng_gif_input_orphan_p != NULL)
  623                         (*ng_gif_input_orphan_p)(ifp, m, af);
  624                 else
  625                         m_freem(m);
  626                 return;
  627         }
  628 
  629         ifp->if_ipackets++;
  630         ifp->if_ibytes += m->m_pkthdr.len;
  631         netisr_dispatch(isr, m);
  632 }
  633 
  634 /* XXX how should we handle IPv6 scope on SIOC[GS]IFPHYADDR? */
  635 int
  636 gif_ioctl(ifp, cmd, data)
  637         struct ifnet *ifp;
  638         u_long cmd;
  639         caddr_t data;
  640 {
  641         struct gif_softc *sc  = ifp->if_softc;
  642         struct ifreq     *ifr = (struct ifreq*)data;
  643         int error = 0, size;
  644         u_int   options;
  645         struct sockaddr *dst, *src;
  646 #ifdef  SIOCSIFMTU /* xxx */
  647         u_long mtu;
  648 #endif
  649 
  650         switch (cmd) {
  651         case SIOCSIFADDR:
  652                 ifp->if_flags |= IFF_UP;
  653                 break;
  654                 
  655         case SIOCSIFDSTADDR:
  656                 break;
  657 
  658         case SIOCADDMULTI:
  659         case SIOCDELMULTI:
  660                 break;
  661 
  662 #ifdef  SIOCSIFMTU /* xxx */
  663         case SIOCGIFMTU:
  664                 break;
  665 
  666         case SIOCSIFMTU:
  667                 mtu = ifr->ifr_mtu;
  668                 if (mtu < GIF_MTU_MIN || mtu > GIF_MTU_MAX)
  669                         return (EINVAL);
  670                 ifp->if_mtu = mtu;
  671                 break;
  672 #endif /* SIOCSIFMTU */
  673 
  674 #ifdef INET
  675         case SIOCSIFPHYADDR:
  676 #endif
  677 #ifdef INET6
  678         case SIOCSIFPHYADDR_IN6:
  679 #endif /* INET6 */
  680         case SIOCSLIFPHYADDR:
  681                 switch (cmd) {
  682 #ifdef INET
  683                 case SIOCSIFPHYADDR:
  684                         src = (struct sockaddr *)
  685                                 &(((struct in_aliasreq *)data)->ifra_addr);
  686                         dst = (struct sockaddr *)
  687                                 &(((struct in_aliasreq *)data)->ifra_dstaddr);
  688                         break;
  689 #endif
  690 #ifdef INET6
  691                 case SIOCSIFPHYADDR_IN6:
  692                         src = (struct sockaddr *)
  693                                 &(((struct in6_aliasreq *)data)->ifra_addr);
  694                         dst = (struct sockaddr *)
  695                                 &(((struct in6_aliasreq *)data)->ifra_dstaddr);
  696                         break;
  697 #endif
  698                 case SIOCSLIFPHYADDR:
  699                         src = (struct sockaddr *)
  700                                 &(((struct if_laddrreq *)data)->addr);
  701                         dst = (struct sockaddr *)
  702                                 &(((struct if_laddrreq *)data)->dstaddr);
  703                         break;
  704                 default:
  705                         return EINVAL;
  706                 }
  707 
  708                 /* sa_family must be equal */
  709                 if (src->sa_family != dst->sa_family)
  710                         return EINVAL;
  711 
  712                 /* validate sa_len */
  713                 switch (src->sa_family) {
  714 #ifdef INET
  715                 case AF_INET:
  716                         if (src->sa_len != sizeof(struct sockaddr_in))
  717                                 return EINVAL;
  718                         break;
  719 #endif
  720 #ifdef INET6
  721                 case AF_INET6:
  722                         if (src->sa_len != sizeof(struct sockaddr_in6))
  723                                 return EINVAL;
  724                         break;
  725 #endif
  726                 default:
  727                         return EAFNOSUPPORT;
  728                 }
  729                 switch (dst->sa_family) {
  730 #ifdef INET
  731                 case AF_INET:
  732                         if (dst->sa_len != sizeof(struct sockaddr_in))
  733                                 return EINVAL;
  734                         break;
  735 #endif
  736 #ifdef INET6
  737                 case AF_INET6:
  738                         if (dst->sa_len != sizeof(struct sockaddr_in6))
  739                                 return EINVAL;
  740                         break;
  741 #endif
  742                 default:
  743                         return EAFNOSUPPORT;
  744                 }
  745 
  746                 /* check sa_family looks sane for the cmd */
  747                 switch (cmd) {
  748                 case SIOCSIFPHYADDR:
  749                         if (src->sa_family == AF_INET)
  750                                 break;
  751                         return EAFNOSUPPORT;
  752 #ifdef INET6
  753                 case SIOCSIFPHYADDR_IN6:
  754                         if (src->sa_family == AF_INET6)
  755                                 break;
  756                         return EAFNOSUPPORT;
  757 #endif /* INET6 */
  758                 case SIOCSLIFPHYADDR:
  759                         /* checks done in the above */
  760                         break;
  761                 }
  762 
  763                 error = gif_set_tunnel(GIF2IFP(sc), src, dst);
  764                 break;
  765 
  766 #ifdef SIOCDIFPHYADDR
  767         case SIOCDIFPHYADDR:
  768                 gif_delete_tunnel(GIF2IFP(sc));
  769                 break;
  770 #endif
  771                         
  772         case SIOCGIFPSRCADDR:
  773 #ifdef INET6
  774         case SIOCGIFPSRCADDR_IN6:
  775 #endif /* INET6 */
  776                 if (sc->gif_psrc == NULL) {
  777                         error = EADDRNOTAVAIL;
  778                         goto bad;
  779                 }
  780                 src = sc->gif_psrc;
  781                 switch (cmd) {
  782 #ifdef INET
  783                 case SIOCGIFPSRCADDR:
  784                         dst = &ifr->ifr_addr;
  785                         size = sizeof(ifr->ifr_addr);
  786                         break;
  787 #endif /* INET */
  788 #ifdef INET6
  789                 case SIOCGIFPSRCADDR_IN6:
  790                         dst = (struct sockaddr *)
  791                                 &(((struct in6_ifreq *)data)->ifr_addr);
  792                         size = sizeof(((struct in6_ifreq *)data)->ifr_addr);
  793                         break;
  794 #endif /* INET6 */
  795                 default:
  796                         error = EADDRNOTAVAIL;
  797                         goto bad;
  798                 }
  799                 if (src->sa_len > size)
  800                         return EINVAL;
  801                 bcopy((caddr_t)src, (caddr_t)dst, src->sa_len);
  802 #ifdef INET6
  803                 if (dst->sa_family == AF_INET6) {
  804                         error = sa6_recoverscope((struct sockaddr_in6 *)dst);
  805                         if (error != 0)
  806                                 return (error);
  807                 }
  808 #endif
  809                 break;
  810                         
  811         case SIOCGIFPDSTADDR:
  812 #ifdef INET6
  813         case SIOCGIFPDSTADDR_IN6:
  814 #endif /* INET6 */
  815                 if (sc->gif_pdst == NULL) {
  816                         error = EADDRNOTAVAIL;
  817                         goto bad;
  818                 }
  819                 src = sc->gif_pdst;
  820                 switch (cmd) {
  821 #ifdef INET
  822                 case SIOCGIFPDSTADDR:
  823                         dst = &ifr->ifr_addr;
  824                         size = sizeof(ifr->ifr_addr);
  825                         break;
  826 #endif /* INET */
  827 #ifdef INET6
  828                 case SIOCGIFPDSTADDR_IN6:
  829                         dst = (struct sockaddr *)
  830                                 &(((struct in6_ifreq *)data)->ifr_addr);
  831                         size = sizeof(((struct in6_ifreq *)data)->ifr_addr);
  832                         break;
  833 #endif /* INET6 */
  834                 default:
  835                         error = EADDRNOTAVAIL;
  836                         goto bad;
  837                 }
  838                 if (src->sa_len > size)
  839                         return EINVAL;
  840                 bcopy((caddr_t)src, (caddr_t)dst, src->sa_len);
  841 #ifdef INET6
  842                 if (dst->sa_family == AF_INET6) {
  843                         error = sa6_recoverscope((struct sockaddr_in6 *)dst);
  844                         if (error != 0)
  845                                 return (error);
  846                 }
  847 #endif
  848                 break;
  849 
  850         case SIOCGLIFPHYADDR:
  851                 if (sc->gif_psrc == NULL || sc->gif_pdst == NULL) {
  852                         error = EADDRNOTAVAIL;
  853                         goto bad;
  854                 }
  855 
  856                 /* copy src */
  857                 src = sc->gif_psrc;
  858                 dst = (struct sockaddr *)
  859                         &(((struct if_laddrreq *)data)->addr);
  860                 size = sizeof(((struct if_laddrreq *)data)->addr);
  861                 if (src->sa_len > size)
  862                         return EINVAL;
  863                 bcopy((caddr_t)src, (caddr_t)dst, src->sa_len);
  864 
  865                 /* copy dst */
  866                 src = sc->gif_pdst;
  867                 dst = (struct sockaddr *)
  868                         &(((struct if_laddrreq *)data)->dstaddr);
  869                 size = sizeof(((struct if_laddrreq *)data)->dstaddr);
  870                 if (src->sa_len > size)
  871                         return EINVAL;
  872                 bcopy((caddr_t)src, (caddr_t)dst, src->sa_len);
  873                 break;
  874 
  875         case SIOCSIFFLAGS:
  876                 /* if_ioctl() takes care of it */
  877                 break;
  878 
  879         case GIFGOPTS:
  880                 options = sc->gif_options;
  881                 error = copyout(&options, ifr->ifr_data,
  882                                 sizeof(options));
  883                 break;
  884 
  885         case GIFSOPTS:
  886                 if ((error = priv_check(curthread, PRIV_NET_GIF)) != 0)
  887                         break;
  888                 error = copyin(ifr->ifr_data, &options, sizeof(options));
  889                 if (error)
  890                         break;
  891                 if (options & ~GIF_OPTMASK)
  892                         error = EINVAL;
  893                 else
  894                         sc->gif_options = options;
  895                 break;
  896 
  897         default:
  898                 error = EINVAL;
  899                 break;
  900         }
  901  bad:
  902         return error;
  903 }
  904 
  905 /*
  906  * XXXRW: There's a general event-ordering issue here: the code to check
  907  * if a given tunnel is already present happens before we perform a
  908  * potentially blocking setup of the tunnel.  This code needs to be
  909  * re-ordered so that the check and replacement can be atomic using
  910  * a mutex.
  911  */
  912 int
  913 gif_set_tunnel(ifp, src, dst)
  914         struct ifnet *ifp;
  915         struct sockaddr *src;
  916         struct sockaddr *dst;
  917 {
  918         struct gif_softc *sc = ifp->if_softc;
  919         struct gif_softc *sc2;
  920         struct sockaddr *osrc, *odst, *sa;
  921         int error = 0; 
  922 
  923         mtx_lock(&gif_mtx);
  924         LIST_FOREACH(sc2, &V_gif_softc_list, gif_list) {
  925                 if (sc2 == sc)
  926                         continue;
  927                 if (!sc2->gif_pdst || !sc2->gif_psrc)
  928                         continue;
  929                 if (sc2->gif_pdst->sa_family != dst->sa_family ||
  930                     sc2->gif_pdst->sa_len != dst->sa_len ||
  931                     sc2->gif_psrc->sa_family != src->sa_family ||
  932                     sc2->gif_psrc->sa_len != src->sa_len)
  933                         continue;
  934 
  935                 /*
  936                  * Disallow parallel tunnels unless instructed
  937                  * otherwise.
  938                  */
  939                 if (!V_parallel_tunnels &&
  940                     bcmp(sc2->gif_pdst, dst, dst->sa_len) == 0 &&
  941                     bcmp(sc2->gif_psrc, src, src->sa_len) == 0) {
  942                         error = EADDRNOTAVAIL;
  943                         mtx_unlock(&gif_mtx);
  944                         goto bad;
  945                 }
  946 
  947                 /* XXX both end must be valid? (I mean, not 0.0.0.0) */
  948         }
  949         mtx_unlock(&gif_mtx);
  950 
  951         /* XXX we can detach from both, but be polite just in case */
  952         if (sc->gif_psrc)
  953                 switch (sc->gif_psrc->sa_family) {
  954 #ifdef INET
  955                 case AF_INET:
  956                         (void)in_gif_detach(sc);
  957                         break;
  958 #endif
  959 #ifdef INET6
  960                 case AF_INET6:
  961                         (void)in6_gif_detach(sc);
  962                         break;
  963 #endif
  964                 }
  965 
  966         osrc = sc->gif_psrc;
  967         sa = (struct sockaddr *)malloc(src->sa_len, M_IFADDR, M_WAITOK);
  968         bcopy((caddr_t)src, (caddr_t)sa, src->sa_len);
  969         sc->gif_psrc = sa;
  970 
  971         odst = sc->gif_pdst;
  972         sa = (struct sockaddr *)malloc(dst->sa_len, M_IFADDR, M_WAITOK);
  973         bcopy((caddr_t)dst, (caddr_t)sa, dst->sa_len);
  974         sc->gif_pdst = sa;
  975 
  976         switch (sc->gif_psrc->sa_family) {
  977 #ifdef INET
  978         case AF_INET:
  979                 error = in_gif_attach(sc);
  980                 break;
  981 #endif
  982 #ifdef INET6
  983         case AF_INET6:
  984                 /*
  985                  * Check validity of the scope zone ID of the addresses, and
  986                  * convert it into the kernel internal form if necessary.
  987                  */
  988                 error = sa6_embedscope((struct sockaddr_in6 *)sc->gif_psrc, 0);
  989                 if (error != 0)
  990                         break;
  991                 error = sa6_embedscope((struct sockaddr_in6 *)sc->gif_pdst, 0);
  992                 if (error != 0)
  993                         break;
  994                 error = in6_gif_attach(sc);
  995                 break;
  996 #endif
  997         }
  998         if (error) {
  999                 /* rollback */
 1000                 free((caddr_t)sc->gif_psrc, M_IFADDR);
 1001                 free((caddr_t)sc->gif_pdst, M_IFADDR);
 1002                 sc->gif_psrc = osrc;
 1003                 sc->gif_pdst = odst;
 1004                 goto bad;
 1005         }
 1006 
 1007         if (osrc)
 1008                 free((caddr_t)osrc, M_IFADDR);
 1009         if (odst)
 1010                 free((caddr_t)odst, M_IFADDR);
 1011 
 1012  bad:
 1013         if (sc->gif_psrc && sc->gif_pdst)
 1014                 ifp->if_drv_flags |= IFF_DRV_RUNNING;
 1015         else
 1016                 ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
 1017 
 1018         return error;
 1019 }
 1020 
 1021 void
 1022 gif_delete_tunnel(ifp)
 1023         struct ifnet *ifp;
 1024 {
 1025         struct gif_softc *sc = ifp->if_softc;
 1026 
 1027         if (sc->gif_psrc) {
 1028                 free((caddr_t)sc->gif_psrc, M_IFADDR);
 1029                 sc->gif_psrc = NULL;
 1030         }
 1031         if (sc->gif_pdst) {
 1032                 free((caddr_t)sc->gif_pdst, M_IFADDR);
 1033                 sc->gif_pdst = NULL;
 1034         }
 1035         /* it is safe to detach from both */
 1036 #ifdef INET
 1037         (void)in_gif_detach(sc);
 1038 #endif
 1039 #ifdef INET6
 1040         (void)in6_gif_detach(sc);
 1041 #endif
 1042         ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
 1043 }

Cache object: 5f095af6ff28f8681a84f2dd9e9f6616


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