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/bsd/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 /*
    2  * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
    3  *
    4  * @APPLE_LICENSE_HEADER_START@
    5  * 
    6  * Copyright (c) 1999-2003 Apple Computer, Inc.  All Rights Reserved.
    7  * 
    8  * This file contains Original Code and/or Modifications of Original Code
    9  * as defined in and that are subject to the Apple Public Source License
   10  * Version 2.0 (the 'License'). You may not use this file except in
   11  * compliance with the License. Please obtain a copy of the License at
   12  * http://www.opensource.apple.com/apsl/ and read it before using this
   13  * file.
   14  * 
   15  * The Original Code and all software distributed under the License are
   16  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
   17  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
   18  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
   19  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
   20  * Please see the License for the specific language governing rights and
   21  * limitations under the License.
   22  * 
   23  * @APPLE_LICENSE_HEADER_END@
   24  */
   25 /*      $FreeBSD: src/sys/net/if_gif.c,v 1.4.2.6 2001/07/24 19:10:18 brooks Exp $       */
   26 /*      $KAME: if_gif.c,v 1.47 2001/05/01 05:28:42 itojun Exp $ */
   27 
   28 /*
   29  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
   30  * All rights reserved.
   31  *
   32  * Redistribution and use in source and binary forms, with or without
   33  * modification, are permitted provided that the following conditions
   34  * are met:
   35  * 1. Redistributions of source code must retain the above copyright
   36  *    notice, this list of conditions and the following disclaimer.
   37  * 2. Redistributions in binary form must reproduce the above copyright
   38  *    notice, this list of conditions and the following disclaimer in the
   39  *    documentation and/or other materials provided with the distribution.
   40  * 3. Neither the name of the project nor the names of its contributors
   41  *    may be used to endorse or promote products derived from this software
   42  *    without specific prior written permission.
   43  *
   44  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
   45  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   46  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   47  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
   48  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   49  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   50  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   51  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   52  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   53  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   54  * SUCH DAMAGE.
   55  */
   56 
   57 #include <sys/param.h>
   58 #include <sys/systm.h>
   59 #include <sys/kernel.h>
   60 #include <sys/malloc.h>
   61 #include <sys/mbuf.h>
   62 #include <sys/socket.h>
   63 #include <sys/sockio.h>
   64 #include <sys/errno.h>
   65 #include <sys/time.h>
   66 #include <sys/syslog.h>
   67 #include <sys/protosw.h>
   68 #include <kern/cpu_number.h>
   69 
   70 #include <net/if.h>
   71 #include <net/if_types.h>
   72 #include <net/netisr.h>
   73 #include <net/route.h>
   74 #include <net/bpf.h>
   75 
   76 #include <netinet/in.h>
   77 #include <netinet/in_systm.h>
   78 #include <netinet/ip.h>
   79 #if     INET
   80 #include <netinet/in_var.h>
   81 #include <netinet/in_gif.h>
   82 #include <netinet/ip_var.h>
   83 #endif  /* INET */
   84 
   85 #if INET6
   86 #include <netinet6/in6_var.h>
   87 #include <netinet/ip6.h>
   88 #include <netinet6/ip6_var.h>
   89 #include <netinet6/in6_gif.h>
   90 #include <netinet6/ip6protosw.h>
   91 #endif /* INET6 */
   92 
   93 #include <netinet/ip_encap.h>
   94 #include <net/dlil.h>
   95 #include <net/if_gif.h>
   96 
   97 #include <net/net_osdep.h>
   98 
   99 #define GIFNAME         "gif"
  100 #define GIFDEV          "if_gif"
  101 #define GIF_MAXUNIT     0x7fff  /* ifp->if_unit is only 15 bits */
  102 
  103 #ifndef __APPLE__
  104 static MALLOC_DEFINE(M_GIF, "gif", "Generic Tunnel Interface");
  105 #endif
  106 
  107 TAILQ_HEAD(gifhead, gif_softc) gifs = TAILQ_HEAD_INITIALIZER(gifs);
  108 
  109 #ifdef __APPLE__
  110 void gifattach __P((void));
  111 int gif_pre_output __P((struct ifnet *, register struct mbuf **, struct sockaddr *,
  112         caddr_t, char *, char *, u_long));
  113 static void gif_create_dev(void);
  114 static int gif_encapcheck(const struct mbuf*, int, int, void*);
  115 
  116 
  117 int ngif = 0;           /* number of interfaces */
  118 #endif
  119 
  120 #if INET
  121 struct protosw in_gif_protosw =
  122 { SOCK_RAW,     0,      0/*IPPROTO_IPV[46]*/,   PR_ATOMIC|PR_ADDR,
  123   in_gif_input, 0,      0,              0,
  124   0,
  125   0,            0,              0,              0,
  126   0,
  127   &rip_usrreqs
  128 };
  129 #endif
  130 #if INET6
  131 struct ip6protosw in6_gif_protosw =
  132 { SOCK_RAW,     0,      0/*IPPROTO_IPV[46]*/,   PR_ATOMIC|PR_ADDR,
  133   in6_gif_input,
  134   0,    0,              0,
  135   0,
  136   0,            0,              0,              0,
  137   0,
  138   &rip6_usrreqs
  139 };
  140 #endif
  141 
  142 #ifndef MAX_GIF_NEST
  143 /*
  144  * This macro controls the upper limitation on nesting of gif tunnels.
  145  * Since, setting a large value to this macro with a careless configuration
  146  * may introduce system crash, we don't allow any nestings by default.
  147  * If you need to configure nested gif tunnels, you can define this macro
  148  * in your kernel configuration file. However, if you do so, please be
  149  * careful to configure the tunnels so that it won't make a loop.
  150  */
  151 #define MAX_GIF_NEST 1
  152 #endif
  153 static int max_gif_nesting = MAX_GIF_NEST;
  154 
  155 
  156 
  157 #ifdef __APPLE__
  158 /*
  159  * Theory of operation: initially, one gif interface is created.
  160  * Any time a gif interface is configured, if there are no other
  161  * unconfigured gif interfaces, a new gif interface is created.
  162  * BSD uses the clone mechanism to dynamically create more
  163  * gif interfaces.
  164  *
  165  * We have some extra glue to support DLIL.
  166  */
  167 
  168 /* GIF interface module support */
  169 int gif_demux(ifp, m, frame_header, proto)
  170     struct ifnet *ifp;
  171     struct mbuf  *m;
  172     char         *frame_header;
  173     struct if_proto **proto;
  174 {
  175         struct gif_softc* gif = (struct gif_softc*)ifp->if_softc;
  176         
  177         /* Only one protocol may be attached to a gif interface. */
  178         *proto = gif->gif_proto;
  179         
  180         return 0;
  181 }
  182 
  183 static
  184 int  gif_add_if(struct ifnet *ifp) 
  185 {
  186     ifp->if_demux  = gif_demux;
  187     ifp->if_framer = 0;
  188     return 0;
  189 }       
  190 
  191 static
  192 int  gif_del_if(struct ifnet *ifp)
  193 {       
  194     return 0;
  195 }   
  196 
  197 static
  198 int  gif_add_proto(struct ddesc_head_str *desc_head, struct if_proto *proto, u_long dl_tag)
  199 {
  200         /* Only one protocol may be attached at a time */
  201         struct gif_softc* gif = (struct gif_softc*)proto->ifp;
  202 
  203         if (gif->gif_proto != NULL)
  204                 printf("gif_add_proto: request add_proto for gif%d\n", gif->gif_if.if_unit);
  205 
  206         gif->gif_proto = proto;
  207 
  208         return 0;
  209 }
  210 
  211 static
  212 int  gif_del_proto(struct if_proto *proto, u_long dl_tag)
  213 {
  214         if (((struct gif_softc*)proto->ifp)->gif_proto == proto)
  215                 ((struct gif_softc*)proto->ifp)->gif_proto = NULL;
  216         else
  217                 return ENOENT;
  218 
  219         return 0;
  220 }
  221 
  222 int gif_shutdown()
  223 {
  224         return 0;
  225 }
  226 
  227 void gif_reg_if_mods()
  228 {
  229      struct dlil_ifmod_reg_str  gif_ifmod;
  230 
  231      bzero(&gif_ifmod, sizeof(gif_ifmod));
  232      gif_ifmod.add_if = gif_add_if;
  233      gif_ifmod.del_if = gif_del_if;
  234      gif_ifmod.add_proto = gif_add_proto;
  235      gif_ifmod.del_proto = gif_del_proto;
  236      gif_ifmod.ifmod_ioctl = 0;
  237      gif_ifmod.shutdown    = gif_shutdown;
  238 
  239     if (dlil_reg_if_modules(APPLE_IF_FAM_GIF, &gif_ifmod))
  240         panic("Couldn't register gif modules\n");
  241 
  242 }
  243 
  244 /* Glue code to attach inet to a gif interface through DLIL */
  245 
  246 u_long  gif_attach_proto_family(struct ifnet *ifp, int af)
  247 {
  248     struct dlil_proto_reg_str   reg;
  249     struct dlil_demux_desc      desc;
  250     u_long                      dl_tag=0;
  251     short native=0;     
  252     int   stat;
  253 
  254         /* Check if we're already attached */
  255         stat = dlil_find_dltag(ifp->if_family, ifp->if_unit, af, &dl_tag);
  256         if (stat == 0)
  257                 return dl_tag;
  258 
  259     TAILQ_INIT(&reg.demux_desc_head);
  260     desc.type = DLIL_DESC_RAW;
  261     desc.variants.bitmask.proto_id_length = 0;
  262     desc.variants.bitmask.proto_id = 0;
  263     desc.variants.bitmask.proto_id_mask = 0;
  264     desc.native_type = (char *) &native;
  265     TAILQ_INSERT_TAIL(&reg.demux_desc_head, &desc, next);
  266     reg.interface_family = ifp->if_family;
  267     reg.unit_number      = ifp->if_unit;
  268     reg.input            = gif_input;
  269     reg.pre_output       = gif_pre_output;
  270     reg.event            = 0;
  271     reg.offer            = 0;
  272     reg.ioctl            = 0;
  273     reg.default_proto    = 0;
  274     reg.protocol_family  = af;
  275 
  276     stat = dlil_attach_protocol(&reg, &dl_tag);
  277     if (stat) {
  278         panic("gif_attach_proto_family can't attach interface fam=%d\n", af);
  279     }
  280 
  281     return dl_tag;
  282 }
  283 
  284 u_long  gif_detach_proto_family(struct ifnet *ifp, int af)
  285 {
  286     u_long      ip_dl_tag = 0;
  287     int         stat;
  288 
  289     stat = dlil_find_dltag(ifp->if_family, ifp->if_unit, af, &ip_dl_tag);
  290     if (stat == 0) {
  291         stat = dlil_detach_protocol(ip_dl_tag);
  292         if (stat) {
  293             printf("WARNING: gif_detach can't detach IP fam=%d from interface\n", af);
  294         }
  295     }
  296     return (stat);
  297 }
  298 
  299 int gif_attach_inet(struct ifnet *ifp, u_long *dl_tag) {
  300         *dl_tag = gif_attach_proto_family(ifp, AF_INET);
  301         return 0;
  302 }
  303 
  304 int gif_detach_inet(struct ifnet *ifp, u_long dl_tag) {
  305         gif_detach_proto_family(ifp, AF_INET);
  306         return 0;
  307 }
  308 
  309 int gif_attach_inet6(struct ifnet *ifp, u_long *dl_tag) {
  310         *dl_tag = gif_attach_proto_family(ifp, AF_INET6);
  311         return 0;
  312 }
  313 
  314 int gif_detach_inet6(struct ifnet *ifp, u_long dl_tag) {
  315         gif_detach_proto_family(ifp, AF_INET6);
  316         return 0;
  317 }
  318 #endif
  319 
  320 /* Function to setup the first gif interface */
  321 void
  322 gifattach(void)
  323 {
  324         struct dlil_protomod_reg_str gif_protoreg;
  325         int error;
  326 
  327         /* Init the list of interfaces */
  328         TAILQ_INIT(&gifs);
  329 
  330         gif_reg_if_mods(); /* DLIL modules */
  331 
  332         /* Register protocol registration functions */
  333 
  334         bzero(&gif_protoreg, sizeof(gif_protoreg));
  335         gif_protoreg.attach_proto = gif_attach_inet;
  336         gif_protoreg.detach_proto = gif_detach_inet;
  337         
  338         if ( error = dlil_reg_proto_module(AF_INET, APPLE_IF_FAM_GIF, &gif_protoreg) != 0)
  339                 printf("dlil_reg_proto_module failed for AF_INET error=%d\n", error);
  340 
  341         gif_protoreg.attach_proto = gif_attach_inet6;
  342         gif_protoreg.detach_proto = gif_detach_inet6;
  343         
  344         if ( error = dlil_reg_proto_module(AF_INET6, APPLE_IF_FAM_GIF, &gif_protoreg) != 0)
  345                 printf("dlil_reg_proto_module failed for AF_INET6 error=%d\n", error);
  346 
  347 
  348         /* Create first device */
  349         gif_create_dev();
  350 }
  351 
  352 /* Creates another gif device if there are none free */
  353 static void
  354 gif_create_dev(void)
  355 {
  356         struct gif_softc *sc;
  357         
  358         
  359         /* Can't create more than GIF_MAXUNIT */
  360         if (ngif >= GIF_MAXUNIT)
  361                 return;
  362         
  363         /* Check for unused gif interface */
  364         TAILQ_FOREACH(sc, &gifs, gif_link) {
  365                 /* If unused, return, no need to create a new interface */
  366                 if ((sc->gif_if.if_flags & IFF_RUNNING) == 0)
  367                         return;
  368         }
  369 
  370         sc = _MALLOC(sizeof(struct gif_softc), M_DEVBUF, M_WAITOK);
  371         if (sc == NULL) {
  372                 log(LOG_ERR, "gifattach: failed to allocate gif%d\n", ngif);
  373                 return;
  374         }
  375 
  376         bzero(sc, sizeof(struct gif_softc));
  377         sc->gif_if.if_softc     = sc;
  378         sc->gif_if.if_name      = GIFNAME;
  379         sc->gif_if.if_unit      = ngif;
  380         
  381         sc->encap_cookie4 = sc->encap_cookie6 = NULL;
  382 #ifdef INET
  383         sc->encap_cookie4 = encap_attach_func(AF_INET, -1,
  384             gif_encapcheck, &in_gif_protosw, sc);
  385         if (sc->encap_cookie4 == NULL) {
  386                 printf("%s: unable to attach encap4\n", if_name(&sc->gif_if));
  387                 FREE(sc, M_DEVBUF);
  388                 return;
  389         }
  390 #endif
  391 #ifdef INET6
  392         sc->encap_cookie6 = encap_attach_func(AF_INET6, -1,
  393             gif_encapcheck, (struct protosw*)&in6_gif_protosw, sc);
  394         if (sc->encap_cookie6 == NULL) {
  395                 if (sc->encap_cookie4) {
  396                         encap_detach(sc->encap_cookie4);
  397                         sc->encap_cookie4 = NULL;
  398                 }
  399                 printf("%s: unable to attach encap6\n", if_name(&sc->gif_if));
  400                 FREE(sc, M_DEVBUF);
  401                 return;
  402         }
  403 #endif
  404         
  405         sc->gif_if.if_family= APPLE_IF_FAM_GIF;
  406         sc->gif_if.if_mtu       = GIF_MTU;
  407         sc->gif_if.if_flags  = IFF_POINTOPOINT | IFF_MULTICAST;
  408 #if 0
  409         /* turn off ingress filter */
  410         sc->gif_if.if_flags  |= IFF_LINK2;
  411 #endif
  412         sc->gif_if.if_ioctl     = gif_ioctl;
  413         sc->gif_if.if_output = NULL;    /* pre_output returns error or EJUSTRETURN */
  414         sc->gif_if.if_type   = IFT_GIF;
  415         dlil_if_attach(&sc->gif_if);
  416         bpfattach(&sc->gif_if, DLT_NULL, sizeof(u_int));
  417         TAILQ_INSERT_TAIL(&gifs, sc, gif_link);
  418         ngif++;
  419 }
  420 
  421 static int
  422 gif_encapcheck(m, off, proto, arg)
  423         const struct mbuf *m;
  424         int off;
  425         int proto;
  426         void *arg;
  427 {
  428         struct ip ip;
  429         struct gif_softc *sc;
  430 
  431         sc = (struct gif_softc *)arg;
  432         if (sc == NULL)
  433                 return 0;
  434 
  435         if ((sc->gif_if.if_flags & IFF_UP) == 0)
  436                 return 0;
  437 
  438         /* no physical address */
  439         if (!sc->gif_psrc || !sc->gif_pdst)
  440                 return 0;
  441 
  442         switch (proto) {
  443 #if INET
  444         case IPPROTO_IPV4:
  445                 break;
  446 #endif
  447 #if INET6
  448         case IPPROTO_IPV6:
  449                 break;
  450 #endif
  451         default:
  452                 return 0;
  453         }
  454 
  455         /* LINTED const cast */
  456         m_copydata((struct mbuf *)m, 0, sizeof(ip), (caddr_t)&ip);
  457 
  458         switch (ip.ip_v) {
  459 #if INET
  460         case 4:
  461                 if (sc->gif_psrc->sa_family != AF_INET ||
  462                     sc->gif_pdst->sa_family != AF_INET)
  463                         return 0;
  464                 return gif_encapcheck4(m, off, proto, arg);
  465 #endif
  466 #if INET6
  467         case 6:
  468                 if (sc->gif_psrc->sa_family != AF_INET6 ||
  469                     sc->gif_pdst->sa_family != AF_INET6)
  470                         return 0;
  471                 return gif_encapcheck6(m, off, proto, arg);
  472 #endif
  473         default:
  474                 return 0;
  475         }
  476 }
  477 
  478 int
  479 gif_pre_output(ifp, m0, dst, rt, frame, address, dl_tag)
  480         struct ifnet *ifp;
  481         struct mbuf **m0;
  482         struct sockaddr *dst;
  483         caddr_t rt;
  484         char *frame;
  485         char *address;
  486         u_long dl_tag;
  487 {
  488         struct gif_softc *sc = (struct gif_softc*)ifp;
  489         register struct mbuf * m = *m0;
  490         int error = 0;
  491         static int called = 0;  /* XXX: MUTEX */
  492 
  493         /*
  494          * gif may cause infinite recursion calls when misconfigured.
  495          * We'll prevent this by introducing upper limit.
  496          * XXX: this mechanism may introduce another problem about
  497          *      mutual exclusion of the variable CALLED, especially if we
  498          *      use kernel thread.
  499          */
  500         if (++called > max_gif_nesting) {
  501                 log(LOG_NOTICE,
  502                     "gif_output: recursively called too many times(%d)\n",
  503                     called);
  504                 m_freem(m);     /* free it here not in dlil_output*/
  505                 error = EIO;    /* is there better errno? */
  506                 goto end;
  507         }
  508 
  509         getmicrotime(&ifp->if_lastchange);
  510         m->m_flags &= ~(M_BCAST|M_MCAST);
  511         if (!(ifp->if_flags & IFF_UP) ||
  512             sc->gif_psrc == NULL || sc->gif_pdst == NULL) {
  513                 m_freem(m);     /* free it here not in dlil_output */
  514                 error = ENETDOWN;
  515                 goto end;
  516         }
  517 
  518         if (ifp->if_bpf) {
  519                 /*
  520                  * We need to prepend the address family as
  521                  * a four byte field.  Cons up a dummy header
  522                  * to pacify bpf.  This is safe because bpf
  523                  * will only read from the mbuf (i.e., it won't
  524                  * try to free it or keep a pointer a to it).
  525                  */
  526                 struct mbuf m0;
  527                 u_int32_t af = dst->sa_family;
  528 
  529                 m0.m_next = m;
  530                 m0.m_len = 4;
  531                 m0.m_data = (char *)&af;
  532                 
  533                 bpf_mtap(ifp, &m0);
  534         }
  535         ifp->if_opackets++;     
  536         ifp->if_obytes += m->m_pkthdr.len;
  537 
  538         /* inner AF-specific encapsulation */
  539 
  540         /* XXX should we check if our outer source is legal? */
  541 
  542         /* dispatch to output logic based on outer AF */
  543         switch (sc->gif_psrc->sa_family) {
  544 #if INET
  545         case AF_INET:
  546                 error = in_gif_output(ifp, dst->sa_family, m, (struct rtentry*)rt);
  547                 break;
  548 #endif
  549 #if INET6
  550         case AF_INET6:
  551                 error = in6_gif_output(ifp, dst->sa_family, m, (struct rtentry*)rt);
  552                 break;
  553 #endif
  554         default:
  555                 error = ENETDOWN;
  556                 goto end;
  557         }
  558 
  559   end:
  560         called = 0;             /* reset recursion counter */
  561         if (error) {
  562                 /* the mbuf was freed either by in_gif_output or in here */
  563                 *m0 = NULL; /* avoid getting dlil_output freeing it */
  564                 ifp->if_oerrors++;
  565         }
  566         if (error == 0) 
  567                 error = EJUSTRETURN; /* if no error, packet got sent already */
  568         return error;
  569 }
  570 
  571 int
  572 gif_input(m, frame_header, gifp, dl_tag, sync_ok)
  573         struct mbuf *m;
  574         char* frame_header;
  575         struct ifnet* gifp;
  576         u_long dl_tag;
  577         int sync_ok;
  578 {
  579         int s, isr;
  580         struct ifqueue *ifq = 0;
  581         int af;
  582 
  583         if (gifp == NULL) {
  584                 /* just in case */
  585                 m_freem(m);
  586                 return;
  587         }
  588 
  589         /* Assume packet is of type of protocol attached to this interface */
  590         af = ((struct gif_softc*)(gifp->if_softc))->gif_proto->protocol_family;
  591 
  592         if (m->m_pkthdr.rcvif)
  593                 m->m_pkthdr.rcvif = gifp;
  594         
  595         if (gifp->if_bpf) {
  596                 /*
  597                  * We need to prepend the address family as
  598                  * a four byte field.  Cons up a dummy header
  599                  * to pacify bpf.  This is safe because bpf
  600                  * will only read from the mbuf (i.e., it won't
  601                  * try to free it or keep a pointer a to it).
  602                  */
  603                 struct mbuf m0;
  604                 u_int32_t af1 = af;
  605                 
  606                 m0.m_next = m;
  607                 m0.m_len = 4;
  608                 m0.m_data = (char *)&af1;
  609                 
  610                 bpf_mtap(gifp, &m0);
  611         }
  612 
  613         /*
  614          * Put the packet to the network layer input queue according to the
  615          * specified address family.
  616          * Note: older versions of gif_input directly called network layer
  617          * input functions, e.g. ip6_input, here. We changed the policy to
  618          * prevent too many recursive calls of such input functions, which
  619          * might cause kernel panic. But the change may introduce another
  620          * problem; if the input queue is full, packets are discarded.
  621          * We believed it rarely occurs and changed the policy. If we find
  622          * it occurs more times than we thought, we may change the policy
  623          * again.
  624          */
  625         switch (af) {
  626 #if INET
  627         case AF_INET:
  628                 ifq = &ipintrq;
  629                 isr = NETISR_IP;
  630                 break;
  631 #endif
  632 #if INET6
  633         case AF_INET6:
  634                 ifq = &ip6intrq;
  635                 isr = NETISR_IPV6;
  636                 break;
  637 #endif
  638         default:
  639                 m_freem(m);
  640                 return (EJUSTRETURN);
  641         }
  642 
  643         s = splimp();
  644         if (IF_QFULL(ifq)) {
  645                 IF_DROP(ifq);   /* update statistics */
  646                 m_freem(m);
  647                 splx(s);
  648                 return (EJUSTRETURN);
  649         }
  650         IF_ENQUEUE(ifq, m);
  651         /* we need schednetisr since the address family may change */
  652         schednetisr(isr);
  653         gifp->if_ipackets++;
  654         gifp->if_ibytes += m->m_pkthdr.len;
  655         splx(s);
  656 
  657         return (0);
  658 }
  659 
  660 /* XXX how should we handle IPv6 scope on SIOC[GS]IFPHYADDR? */
  661 int
  662 gif_ioctl(ifp, cmd, data)
  663         struct ifnet *ifp;
  664         u_long cmd;
  665         void* data;
  666 {
  667         struct gif_softc *sc  = (struct gif_softc*)ifp;
  668         struct ifreq     *ifr = (struct ifreq*)data;
  669         int error = 0, size;
  670         struct sockaddr *dst, *src;
  671         struct sockaddr *sa;
  672         int s;
  673         struct ifnet *ifp2;
  674         struct gif_softc *sc2;
  675                 
  676         switch (cmd) {
  677         case SIOCSIFADDR:
  678                 break;
  679                 
  680         case SIOCSIFDSTADDR:
  681                 break;
  682 
  683         case SIOCADDMULTI:
  684         case SIOCDELMULTI:
  685                 break;
  686 
  687 #ifdef  SIOCSIFMTU /* xxx */
  688         case SIOCGIFMTU:
  689                 break;
  690 
  691         case SIOCSIFMTU:
  692                 {
  693                         u_long mtu;
  694                         mtu = ifr->ifr_mtu;
  695                         if (mtu < GIF_MTU_MIN || mtu > GIF_MTU_MAX) {
  696                                 return (EINVAL);
  697                         }
  698                         ifp->if_mtu = mtu;
  699                 }
  700                 break;
  701 #endif /* SIOCSIFMTU */
  702 
  703         case SIOCSIFPHYADDR:
  704 #if INET6
  705         case SIOCSIFPHYADDR_IN6:
  706 #endif /* INET6 */
  707         case SIOCSLIFPHYADDR:
  708                 switch (cmd) {
  709 #if INET
  710                 case SIOCSIFPHYADDR:
  711                         src = (struct sockaddr *)
  712                                 &(((struct in_aliasreq *)data)->ifra_addr);
  713                         dst = (struct sockaddr *)
  714                                 &(((struct in_aliasreq *)data)->ifra_dstaddr);
  715                         break;
  716 #endif
  717 #if INET6
  718                 case SIOCSIFPHYADDR_IN6:
  719                         src = (struct sockaddr *)
  720                                 &(((struct in6_aliasreq *)data)->ifra_addr);
  721                         dst = (struct sockaddr *)
  722                                 &(((struct in6_aliasreq *)data)->ifra_dstaddr);
  723                         break;
  724 #endif
  725                 case SIOCSLIFPHYADDR:
  726                         src = (struct sockaddr *)
  727                                 &(((struct if_laddrreq *)data)->addr);
  728                         dst = (struct sockaddr *)
  729                                 &(((struct if_laddrreq *)data)->dstaddr);
  730                 }
  731 
  732                 /* sa_family must be equal */
  733                 if (src->sa_family != dst->sa_family)
  734                         return EINVAL;
  735 
  736                 /* validate sa_len */
  737                 switch (src->sa_family) {
  738 #if INET
  739                 case AF_INET:
  740                         if (src->sa_len != sizeof(struct sockaddr_in))
  741                                 return EINVAL;
  742                         break;
  743 #endif
  744 #if INET6
  745                 case AF_INET6:
  746                         if (src->sa_len != sizeof(struct sockaddr_in6))
  747                                 return EINVAL;
  748                         break;
  749 #endif
  750                 default:
  751                         return EAFNOSUPPORT;
  752                 }
  753                 switch (dst->sa_family) {
  754 #if INET
  755                 case AF_INET:
  756                         if (dst->sa_len != sizeof(struct sockaddr_in))
  757                                 return EINVAL;
  758                         break;
  759 #endif
  760 #if INET6
  761                 case AF_INET6:
  762                         if (dst->sa_len != sizeof(struct sockaddr_in6))
  763                                 return EINVAL;
  764                         break;
  765 #endif
  766                 default:
  767                         return EAFNOSUPPORT;
  768                 }
  769 
  770                 /* check sa_family looks sane for the cmd */
  771                 switch (cmd) {
  772                 case SIOCSIFPHYADDR:
  773                         if (src->sa_family == AF_INET)
  774                                 break;
  775                         return EAFNOSUPPORT;
  776 #if INET6
  777                 case SIOCSIFPHYADDR_IN6:
  778                         if (src->sa_family == AF_INET6)
  779                                 break;
  780                         return EAFNOSUPPORT;
  781 #endif /* INET6 */
  782                 case SIOCSLIFPHYADDR:
  783                         /* checks done in the above */
  784                         break;
  785                 }
  786 
  787                 TAILQ_FOREACH(ifp2, &ifnet, if_link) {
  788                         if (strcmp(ifp2->if_name, GIFNAME) != 0)
  789                                 continue;
  790                         sc2 = ifp2->if_softc;
  791                         if (sc2 == sc)
  792                                 continue;
  793                         if (!sc2->gif_pdst || !sc2->gif_psrc)
  794                                 continue;
  795                         if (sc2->gif_pdst->sa_family != dst->sa_family ||
  796                             sc2->gif_pdst->sa_len != dst->sa_len ||
  797                             sc2->gif_psrc->sa_family != src->sa_family ||
  798                             sc2->gif_psrc->sa_len != src->sa_len)
  799                                 continue;
  800 #ifndef XBONEHACK
  801                         /* can't configure same pair of address onto two gifs */
  802                         if (bcmp(sc2->gif_pdst, dst, dst->sa_len) == 0 &&
  803                             bcmp(sc2->gif_psrc, src, src->sa_len) == 0) {
  804                                 error = EADDRNOTAVAIL;
  805                                 goto bad;
  806                         }
  807 #endif
  808 
  809                         /* can't configure multiple multi-dest interfaces */
  810 #define multidest(x) \
  811         (((struct sockaddr_in *)(x))->sin_addr.s_addr == INADDR_ANY)
  812 #if INET6
  813 #define multidest6(x) \
  814         (IN6_IS_ADDR_UNSPECIFIED(&((struct sockaddr_in6 *)(x))->sin6_addr))
  815 #endif
  816                         if (dst->sa_family == AF_INET &&
  817                             multidest(dst) && multidest(sc2->gif_pdst)) {
  818                                 error = EADDRNOTAVAIL;
  819                                 goto bad;
  820                         }
  821 #if INET6
  822                         if (dst->sa_family == AF_INET6 &&
  823                             multidest6(dst) && multidest6(sc2->gif_pdst)) {
  824                                 error = EADDRNOTAVAIL;
  825                                 goto bad;
  826                         }
  827 #endif
  828                 }
  829 
  830                 if (sc->gif_psrc)
  831                         FREE((caddr_t)sc->gif_psrc, M_IFADDR);
  832                 sa = (struct sockaddr *)_MALLOC(src->sa_len, M_IFADDR, M_WAITOK);
  833                 bcopy((caddr_t)src, (caddr_t)sa, src->sa_len);
  834                 sc->gif_psrc = sa;
  835 
  836                 if (sc->gif_pdst)
  837                         FREE((caddr_t)sc->gif_pdst, M_IFADDR);
  838                 sa = (struct sockaddr *)_MALLOC(dst->sa_len, M_IFADDR, M_WAITOK);
  839                 bcopy((caddr_t)dst, (caddr_t)sa, dst->sa_len);
  840                 sc->gif_pdst = sa;
  841 
  842                 ifp->if_flags |= IFF_RUNNING;
  843 
  844                 gif_attach_proto_family(ifp, src->sa_family);
  845 
  846                 s = splimp();
  847                 if_up(ifp);     /* mark interface UP and send up RTM_IFINFO */
  848 #ifdef __APPLE__
  849                 /* Make sure at least one unused device is still available */
  850                 gif_create_dev();
  851 #endif
  852                 splx(s);
  853 
  854                 error = 0;
  855                 break;
  856 
  857 #ifdef SIOCDIFPHYADDR
  858         case SIOCDIFPHYADDR:
  859                 if (sc->gif_psrc) {
  860                         FREE((caddr_t)sc->gif_psrc, M_IFADDR);
  861                         sc->gif_psrc = NULL;
  862                 }
  863                 if (sc->gif_pdst) {
  864                         FREE((caddr_t)sc->gif_pdst, M_IFADDR);
  865                         sc->gif_pdst = NULL;
  866                 }
  867                 /* change the IFF_{UP, RUNNING} flag as well? */
  868                 break;
  869 #endif
  870                         
  871         case SIOCGIFPSRCADDR:
  872 #if INET6
  873         case SIOCGIFPSRCADDR_IN6:
  874 #endif /* INET6 */
  875                 if (sc->gif_psrc == NULL) {
  876                         error = EADDRNOTAVAIL;
  877                         goto bad;
  878                 }
  879                 src = sc->gif_psrc;
  880                 switch (cmd) {
  881 #if INET
  882                 case SIOCGIFPSRCADDR:
  883                         dst = &ifr->ifr_addr;
  884                         size = sizeof(ifr->ifr_addr);
  885                         break;
  886 #endif /* INET */
  887 #if INET6
  888                 case SIOCGIFPSRCADDR_IN6:
  889                         dst = (struct sockaddr *)
  890                                 &(((struct in6_ifreq *)data)->ifr_addr);
  891                         size = sizeof(((struct in6_ifreq *)data)->ifr_addr);
  892                         break;
  893 #endif /* INET6 */
  894                 default:
  895                         error = EADDRNOTAVAIL;
  896                         goto bad;
  897                 }
  898                 if (src->sa_len > size)
  899                         return EINVAL;
  900                 bcopy((caddr_t)src, (caddr_t)dst, src->sa_len);
  901                 break;
  902                         
  903         case SIOCGIFPDSTADDR:
  904 #if INET6
  905         case SIOCGIFPDSTADDR_IN6:
  906 #endif /* INET6 */
  907                 if (sc->gif_pdst == NULL) {
  908                         error = EADDRNOTAVAIL;
  909                         goto bad;
  910                 }
  911                 src = sc->gif_pdst;
  912                 switch (cmd) {
  913 #if INET
  914                 case SIOCGIFPDSTADDR:
  915                         dst = &ifr->ifr_addr;
  916                         size = sizeof(ifr->ifr_addr);
  917                         break;
  918 #endif /* INET */
  919 #if INET6
  920                 case SIOCGIFPDSTADDR_IN6:
  921                         dst = (struct sockaddr *)
  922                                 &(((struct in6_ifreq *)data)->ifr_addr);
  923                         size = sizeof(((struct in6_ifreq *)data)->ifr_addr);
  924                         break;
  925 #endif /* INET6 */
  926                 default:
  927                         error = EADDRNOTAVAIL;
  928                         goto bad;
  929                 }
  930                 if (src->sa_len > size)
  931                         return EINVAL;
  932                 bcopy((caddr_t)src, (caddr_t)dst, src->sa_len);
  933                 break;
  934 
  935         case SIOCGLIFPHYADDR:
  936                 if (sc->gif_psrc == NULL || sc->gif_pdst == NULL) {
  937                         error = EADDRNOTAVAIL;
  938                         goto bad;
  939                 }
  940 
  941                 /* copy src */
  942                 src = sc->gif_psrc;
  943                 dst = (struct sockaddr *)
  944                         &(((struct if_laddrreq *)data)->addr);
  945                 size = sizeof(((struct if_laddrreq *)data)->addr);
  946                 if (src->sa_len > size)
  947                         return EINVAL;
  948                 bcopy((caddr_t)src, (caddr_t)dst, src->sa_len);
  949 
  950                 /* copy dst */
  951                 src = sc->gif_pdst;
  952                 dst = (struct sockaddr *)
  953                         &(((struct if_laddrreq *)data)->dstaddr);
  954                 size = sizeof(((struct if_laddrreq *)data)->dstaddr);
  955                 if (src->sa_len > size)
  956                         return EINVAL;
  957                 bcopy((caddr_t)src, (caddr_t)dst, src->sa_len);
  958                 break;
  959 
  960         case SIOCSIFFLAGS:
  961                 /* if_ioctl() takes care of it */
  962                 break;
  963 
  964         default:
  965                 error = EOPNOTSUPP;
  966                 break;
  967         }
  968  bad:
  969         return error;
  970 }
  971 
  972 void
  973 gif_delete_tunnel(sc)
  974         struct gif_softc *sc;
  975 {
  976         /* XXX: NetBSD protects this function with splsoftnet() */
  977 
  978         if (sc->gif_psrc) {
  979                 FREE((caddr_t)sc->gif_psrc, M_IFADDR);
  980                 sc->gif_psrc = NULL;
  981         }
  982         if (sc->gif_pdst) {
  983                 FREE((caddr_t)sc->gif_pdst, M_IFADDR);
  984                 sc->gif_pdst = NULL;
  985         }
  986         /* change the IFF_UP flag as well? */
  987 }

Cache object: 18d0203653ff1ddff776214269928d25


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