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_etherip.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_etherip.c,v 1.22.4.2 2008/11/19 03:40:27 snj Exp $        */
    2 
    3 /*
    4  *  Copyright (c) 2006, Hans Rosenfeld <rosenfeld@grumpf.hope-2000.org>
    5  *  All rights reserved.
    6  *
    7  *  Redistribution and use in source and binary forms, with or without
    8  *  modification, are permitted provided that the following conditions
    9  *  are met:
   10  *  1. Redistributions of source code must retain the above copyright
   11  *     notice, this list of conditions and the following disclaimer.
   12  *  2. Redistributions in binary form must reproduce the above copyright
   13  *     notice, this list of conditions and the following disclaimer in the
   14  *     documentation and/or other materials provided with the distribution.
   15  *  3. Neither the name of Hans Rosenfeld nor the names of his
   16  *     contributors may be used to endorse or promote products derived
   17  *     from this software without specific prior written permission.
   18  *
   19  *  THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   20  *  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   21  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   22  *  ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   23  *  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   24  *  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   25  *  OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   26  *  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   27  *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   28  *  OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   29  *  SUCH DAMAGE.
   30  *
   31  *
   32  *  Copyright (c) 2003, 2004, 2008 The NetBSD Foundation.
   33  *  All rights reserved.
   34  *
   35  *  Redistribution and use in source and binary forms, with or without
   36  *  modification, are permitted provided that the following conditions
   37  *  are met:
   38  *  1. Redistributions of source code must retain the above copyright
   39  *     notice, this list of conditions and the following disclaimer.
   40  *  2. Redistributions in binary form must reproduce the above copyright
   41  *     notice, this list of conditions and the following disclaimer in the
   42  *     documentation and/or other materials provided with the distribution.
   43  *  3. Neither the name of The NetBSD Foundation nor the names of its
   44  *     contributors may be used to endorse or promote products derived
   45  *     from this software without specific prior written permission.
   46  *
   47  *  THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   48  *  ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   49  *  TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   50  *  PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   51  *  BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   52  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   53  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   54  *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   55  *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   56  *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   57  *  POSSIBILITY OF SUCH DAMAGE.
   58  *
   59  *
   60  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
   61  * All rights reserved.
   62  *
   63  * Redistribution and use in source and binary forms, with or without
   64  * modification, are permitted provided that the following conditions
   65  * are met:
   66  * 1. Redistributions of source code must retain the above copyright
   67  *    notice, this list of conditions and the following disclaimer.
   68  * 2. Redistributions in binary form must reproduce the above copyright
   69  *    notice, this list of conditions and the following disclaimer in the
   70  *    documentation and/or other materials provided with the distribution.
   71  * 3. Neither the name of the project nor the names of its contributors
   72  *    may be used to endorse or promote products derived from this software
   73  *    without specific prior written permission.
   74  *
   75  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
   76  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   77  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   78  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
   79  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   80  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   81  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   82  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   83  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   84  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   85  * SUCH DAMAGE.
   86  */
   87 
   88 #include <sys/cdefs.h>
   89 __KERNEL_RCSID(0, "$NetBSD: if_etherip.c,v 1.22.4.2 2008/11/19 03:40:27 snj Exp $");
   90 
   91 #include "opt_inet.h"
   92 #include "bpfilter.h"
   93 
   94 #include <sys/param.h>
   95 #include <sys/systm.h>
   96 #include <sys/kernel.h>
   97 #include <sys/malloc.h>
   98 #include <sys/conf.h>
   99 #include <sys/device.h>
  100 #include <sys/errno.h>
  101 #include <sys/time.h>
  102 #include <sys/sysctl.h>
  103 #include <sys/queue.h>
  104 #include <sys/kauth.h>
  105 #include <sys/socket.h>
  106 #include <sys/socketvar.h>
  107 #include <sys/intr.h>
  108 
  109 #include <net/if.h>
  110 #include <net/if_dl.h>
  111 #include <net/if_ether.h>
  112 #include <net/if_media.h>
  113 #include <net/route.h>
  114 #include <net/if_etherip.h>
  115 #if NBPFILTER > 0
  116 #include <net/bpf.h>
  117 #endif
  118 
  119 #include <netinet/in.h>
  120 #include <netinet/in_systm.h>
  121 #include <netinet/ip.h>
  122 #ifdef  INET
  123 #include <netinet/in_var.h>
  124 #endif  /* INET */
  125 #include <netinet/ip_etherip.h>
  126 
  127 #ifdef INET6
  128 #include <netinet6/ip6_etherip.h>
  129 #ifndef INET
  130 #include <netinet/in.h>
  131 #endif
  132 #include <netinet6/in6_var.h>
  133 #include <netinet/ip6.h>
  134 #include <netinet6/ip6_var.h>
  135 #include <netinet6/in6_gif.h>
  136 #include <netinet6/ip6protosw.h>
  137 #endif /* INET6 */
  138 
  139 #include <compat/sys/sockio.h>
  140 
  141 static int etherip_node;
  142 static int etherip_sysctl_handler(SYSCTLFN_PROTO);
  143 SYSCTL_SETUP_PROTO(sysctl_etherip_setup);
  144 
  145 void etheripattach(int);
  146 
  147 static int  etherip_match(device_t, cfdata_t, void *);
  148 static void etherip_attach(device_t, device_t, void *);
  149 static int  etherip_detach(device_t, int);
  150 
  151 CFATTACH_DECL_NEW(etherip, sizeof(struct etherip_softc),
  152               etherip_match, etherip_attach, etherip_detach, NULL);
  153 extern struct cfdriver etherip_cd;
  154 
  155 static void etherip_start(struct ifnet *);
  156 static void etherip_stop(struct ifnet *, int);
  157 static int  etherip_init(struct ifnet *);
  158 static int  etherip_ioctl(struct ifnet *, u_long, void *);
  159 
  160 static int  etherip_mediachange(struct ifnet *);
  161 static void etherip_mediastatus(struct ifnet *, struct ifmediareq *);
  162 
  163 static int  etherip_clone_create(struct if_clone *, int);
  164 static int  etherip_clone_destroy(struct ifnet *);
  165 
  166 static struct if_clone etherip_cloners = IF_CLONE_INITIALIZER(
  167         "etherip", etherip_clone_create, etherip_clone_destroy);
  168 
  169 static int  etherip_set_tunnel(struct ifnet *,
  170                                struct sockaddr *, struct sockaddr *);
  171 static void etherip_delete_tunnel(struct ifnet *);
  172 static void etheripintr(void *);
  173 
  174 void
  175 etheripattach(int count)
  176 {
  177         int error;
  178 
  179         error = config_cfattach_attach(etherip_cd.cd_name, &etherip_ca);
  180 
  181         if (error) {
  182                 aprint_error("%s: unable to register cfattach\n",
  183                              etherip_cd.cd_name);
  184                 (void)config_cfdriver_detach(&etherip_cd);
  185                 return;
  186         }
  187 
  188         LIST_INIT(&etherip_softc_list);
  189         if_clone_attach(&etherip_cloners);
  190 }
  191 
  192 /* Pretty much useless for a pseudo-device */
  193 static int
  194 etherip_match(device_t self, cfdata_t cfdata, void *arg)
  195 {
  196         return 1;
  197 }
  198 
  199 static void
  200 etherip_attach(device_t parent, device_t self, void *aux)
  201 {
  202         struct etherip_softc *sc = device_private(self);
  203         struct ifnet *ifp;
  204         const struct sysctlnode *node;
  205         uint8_t enaddr[ETHER_ADDR_LEN] =
  206                 { 0xf2, 0x0b, 0xa5, 0xff, 0xff, 0xff };
  207         char enaddrstr[3 * ETHER_ADDR_LEN];
  208         struct timeval tv;
  209         uint32_t ui;
  210         int error;
  211 
  212         sc->sc_dev = self;
  213         sc->sc_si  = NULL;
  214         sc->sc_src = NULL;
  215         sc->sc_dst = NULL;
  216 
  217         if (!pmf_device_register(self, NULL, NULL))
  218                 aprint_error_dev(self, "couldn't establish power handler\n");
  219 
  220         /*
  221          * In order to obtain unique initial Ethernet address on a host,
  222          * do some randomisation using the current uptime.  It's not meant
  223          * for anything but avoiding hard-coding an address.
  224          */
  225         getmicrouptime(&tv);
  226         ui = (tv.tv_sec ^ tv.tv_usec) & 0xffffff;
  227         memcpy(enaddr+3, (uint8_t *)&ui, 3);
  228         
  229         aprint_verbose_dev(self, "Ethernet address %s\n",
  230                        ether_snprintf(enaddrstr, sizeof(enaddrstr), enaddr));
  231 
  232         /*
  233          * Why 1000baseT? Why not? You can add more.
  234          *
  235          * Note that there are 3 steps: init, one or several additions to
  236          * list of supported media, and in the end, the selection of one
  237          * of them.
  238          */
  239         ifmedia_init(&sc->sc_im, 0, etherip_mediachange, etherip_mediastatus);
  240         ifmedia_add(&sc->sc_im, IFM_ETHER|IFM_1000_T, 0, NULL);
  241         ifmedia_add(&sc->sc_im, IFM_ETHER|IFM_1000_T|IFM_FDX, 0, NULL);
  242         ifmedia_add(&sc->sc_im, IFM_ETHER|IFM_100_TX, 0, NULL);
  243         ifmedia_add(&sc->sc_im, IFM_ETHER|IFM_100_TX|IFM_FDX, 0, NULL);
  244         ifmedia_add(&sc->sc_im, IFM_ETHER|IFM_10_T, 0, NULL);
  245         ifmedia_add(&sc->sc_im, IFM_ETHER|IFM_10_T|IFM_FDX, 0, NULL);
  246         ifmedia_add(&sc->sc_im, IFM_ETHER|IFM_AUTO, 0, NULL);
  247         ifmedia_set(&sc->sc_im, IFM_ETHER|IFM_AUTO);
  248         
  249         /*
  250          * One should note that an interface must do multicast in order
  251          * to support IPv6.
  252          */
  253         ifp = &sc->sc_ec.ec_if;
  254         strlcpy(ifp->if_xname, device_xname(self), IFNAMSIZ);
  255         ifp->if_softc = sc;
  256         ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
  257         ifp->if_ioctl = etherip_ioctl;
  258         ifp->if_start = etherip_start;
  259         ifp->if_stop  = etherip_stop;
  260         ifp->if_init  = etherip_init;
  261         IFQ_SET_READY(&ifp->if_snd);
  262         
  263         sc->sc_ec.ec_capabilities = ETHERCAP_VLAN_MTU | ETHERCAP_JUMBO_MTU;
  264         
  265         /* 
  266          * Those steps are mandatory for an Ethernet driver, the first call
  267          * being common to all network interface drivers.
  268          */
  269         if_attach(ifp);
  270         ether_ifattach(ifp, enaddr);
  271 
  272         /*
  273          * Add a sysctl node for that interface.
  274          *
  275          * The pointer transmitted is not a string, but instead a pointer to
  276          * the softc structure, which we can use to build the string value on
  277          * the fly in the helper function of the node.  See the comments for
  278          * etherip_sysctl_handler for details.
  279          */
  280         error = sysctl_createv(NULL, 0, NULL, &node, CTLFLAG_READWRITE, 
  281                                CTLTYPE_STRING, device_xname(self), NULL,
  282                                etherip_sysctl_handler, 0, sc, 18, CTL_NET,
  283                                AF_LINK, etherip_node, device_unit(self),
  284                                CTL_EOL);
  285         if (error)
  286                 aprint_error_dev(self, "sysctl_createv returned %d, ignoring\n",
  287                              error);
  288 
  289         /* insert into etherip_softc_list */
  290         LIST_INSERT_HEAD(&etherip_softc_list, sc, etherip_list);
  291 }
  292 
  293 /*
  294  * When detaching, we do the inverse of what is done in the attach
  295  * routine, in reversed order.
  296  */
  297 static int
  298 etherip_detach(device_t self, int flags)
  299 {
  300         struct etherip_softc *sc = device_private(self);
  301         struct ifnet *ifp = &sc->sc_ec.ec_if;
  302         int error, s;
  303 
  304         s = splnet();
  305         etherip_stop(ifp, 1);
  306         if_down(ifp);
  307         splx(s);
  308 
  309         /*
  310          * Destroying a single leaf is a very straightforward operation using
  311          * sysctl_destroyv.  One should be sure to always end the path with
  312          * CTL_EOL.
  313          */
  314         error = sysctl_destroyv(NULL, CTL_NET, AF_LINK, etherip_node,
  315                                 device_unit(self), CTL_EOL);
  316         if (error)
  317                 aprint_error_dev(self, "sysctl_destroyv returned %d, ignoring\n",
  318                              error);
  319 
  320         LIST_REMOVE(sc, etherip_list);
  321         etherip_delete_tunnel(ifp);
  322         ether_ifdetach(ifp);
  323         if_detach(ifp);
  324         rtcache_free(&sc->sc_ro);
  325         ifmedia_delete_instance(&sc->sc_im, IFM_INST_ANY);
  326 
  327         pmf_device_deregister(self);
  328 
  329         return 0;
  330 }
  331 
  332 /*
  333  * This function is called by the ifmedia layer to notify the driver
  334  * that the user requested a media change.  A real driver would
  335  * reconfigure the hardware.
  336  */
  337 static int
  338 etherip_mediachange(struct ifnet *ifp)
  339 {
  340         return 0;
  341 }
  342 
  343 /*
  344  * Here the user asks for the currently used media.
  345  */
  346 static void
  347 etherip_mediastatus(struct ifnet *ifp, struct ifmediareq *imr)
  348 {
  349         struct etherip_softc *sc = ifp->if_softc;
  350 
  351         imr->ifm_active = sc->sc_im.ifm_cur->ifm_media;
  352 }
  353 
  354 static void
  355 etherip_start(struct ifnet *ifp)
  356 {
  357         struct etherip_softc *sc = ifp->if_softc;
  358 
  359         if(sc->sc_si)
  360                 softint_schedule(sc->sc_si);
  361 }
  362 
  363 static void
  364 etheripintr(void *arg)
  365 {
  366         struct etherip_softc *sc = (struct etherip_softc *)arg;
  367         struct ifnet *ifp = &sc->sc_ec.ec_if;
  368         struct mbuf *m;
  369         int s, error;
  370 
  371         mutex_enter(softnet_lock);
  372         for (;;) {
  373                 s = splnet();
  374                 IFQ_DEQUEUE(&ifp->if_snd, m);
  375                 splx(s);
  376                 if (m == NULL)
  377                         break;
  378                 
  379 #if NBPFILTER > 0
  380                 if (ifp->if_bpf)
  381                         bpf_mtap(ifp->if_bpf, m);
  382 #endif
  383                 
  384                 ifp->if_opackets++;
  385                 if (sc->sc_src && sc->sc_dst) {
  386                         ifp->if_flags |= IFF_OACTIVE;
  387                         switch (sc->sc_src->sa_family) {
  388 #ifdef INET
  389                         case AF_INET:
  390                                 error = ip_etherip_output(ifp, m);
  391                                 break;
  392 #endif
  393 #ifdef INET6
  394                         case AF_INET6:
  395                                 error = ip6_etherip_output(ifp, m);
  396                                 break;
  397 #endif
  398                         default:
  399                                 error = ENETDOWN;
  400                         }
  401                         ifp->if_flags &= ~IFF_OACTIVE;
  402                 } else  m_freem(m);
  403         }
  404         mutex_exit(softnet_lock);
  405 }
  406 
  407 static int
  408 etherip_ioctl(struct ifnet *ifp, u_long cmd, void *data)
  409 {
  410         struct etherip_softc *sc = ifp->if_softc;
  411         struct ifreq *ifr = data;
  412         struct sockaddr *src, *dst;
  413         int s, error;
  414 
  415         switch (cmd) {
  416         case SIOCSLIFPHYADDR:
  417                 src = (struct sockaddr *)
  418                         &(((struct if_laddrreq *)data)->addr);
  419                 dst = (struct sockaddr *)
  420                         &(((struct if_laddrreq *)data)->dstaddr);
  421 
  422                 /* sa_family must be equal */
  423                 if (src->sa_family != dst->sa_family)
  424                         return EINVAL;
  425 
  426                 /* validate sa_len */
  427                 switch (src->sa_family) {
  428 #ifdef INET
  429                 case AF_INET:
  430                         if (src->sa_len != sizeof(struct sockaddr_in) ||
  431                             dst->sa_len != sizeof(struct sockaddr_in))
  432                                 return EINVAL;
  433                         break;
  434 #endif
  435 #ifdef INET6
  436                 case AF_INET6:
  437                         if (src->sa_len != sizeof(struct sockaddr_in6) ||
  438                             dst->sa_len != sizeof(struct sockaddr_in6))
  439                                 return EINVAL;
  440                         break;
  441 #endif
  442                 default:
  443                         return EAFNOSUPPORT;
  444                 }
  445                 
  446                 error = etherip_set_tunnel(ifp, src, dst);
  447                 break;
  448 
  449         case SIOCDIFPHYADDR:
  450                 etherip_delete_tunnel(ifp);
  451                 error = 0;
  452                 break;
  453 
  454         case SIOCGLIFPHYADDR:
  455                 if (sc->sc_src == NULL || sc->sc_dst == NULL)
  456                         return EADDRNOTAVAIL;
  457 
  458                 /* copy src */
  459                 src = sc->sc_src;
  460                 dst = (struct sockaddr *)
  461                         &(((struct if_laddrreq *)data)->addr);
  462                 if (src->sa_len > sizeof(((struct if_laddrreq *)data)->addr))
  463                         return EINVAL;
  464                 memcpy(dst, src, src->sa_len);
  465 
  466                 /* copy dst */
  467                 src = sc->sc_dst;
  468                 dst = (struct sockaddr *)
  469                         &(((struct if_laddrreq *)data)->dstaddr);
  470                 if (src->sa_len > sizeof(((struct if_laddrreq *)data)->dstaddr))
  471                         return EINVAL;
  472                 memcpy(dst, src, src->sa_len);
  473 
  474                 error = 0;
  475                 break;
  476 
  477 #ifdef OSIOCSIFMEDIA
  478         case OSIOCSIFMEDIA:
  479 #endif
  480         case SIOCSIFMEDIA:
  481         case SIOCGIFMEDIA:
  482                 s = splnet();
  483                 error = ifmedia_ioctl(ifp, ifr, &sc->sc_im, cmd);
  484                 splx(s);
  485                 break;
  486 
  487         default:
  488                 s = splnet();
  489                 error = ether_ioctl(ifp, cmd, data);
  490                 splx(s);
  491                 if (error == ENETRESET)
  492                         error = 0;
  493                 break;
  494         }
  495         
  496         return (error);
  497 }
  498 
  499 static int
  500 etherip_set_tunnel(struct ifnet *ifp, 
  501                    struct sockaddr *src, 
  502                    struct sockaddr *dst)
  503 {
  504         struct etherip_softc *sc = ifp->if_softc;
  505         struct etherip_softc *sc2;
  506         struct sockaddr *osrc, *odst;
  507         int s, error = 0;
  508 
  509         s = splsoftnet();
  510 
  511         LIST_FOREACH(sc2, &etherip_softc_list, etherip_list) {
  512                 if (sc2 == sc)
  513                         continue;
  514                 if (!sc2->sc_dst || !sc2->sc_src)
  515                         continue;
  516                 if (sc2->sc_dst->sa_family != dst->sa_family ||
  517                     sc2->sc_dst->sa_len    != dst->sa_len    ||
  518                     sc2->sc_src->sa_family != src->sa_family ||
  519                     sc2->sc_src->sa_len    != src->sa_len)
  520                         continue;
  521                 /* can't configure same pair of address onto two tunnels */
  522                 if (bcmp(sc2->sc_dst, dst, dst->sa_len) == 0 &&
  523                     bcmp(sc2->sc_src, src, src->sa_len) == 0) {
  524                         error = EADDRNOTAVAIL;
  525                         goto out;
  526                 }
  527                 /* XXX both end must be valid? (I mean, not 0.0.0.0) */
  528         }
  529 
  530         if (sc->sc_si) {
  531                 softint_disestablish(sc->sc_si);
  532                 sc->sc_si = NULL;
  533         }
  534 
  535         ifp->if_flags &= ~IFF_RUNNING;
  536 
  537         osrc = sc->sc_src; sc->sc_src = NULL;
  538         odst = sc->sc_dst; sc->sc_dst = NULL;
  539 
  540         sc->sc_src = sockaddr_dup(src, M_WAITOK);
  541         if (osrc)
  542                 sockaddr_free(osrc);
  543 
  544         sc->sc_dst = sockaddr_dup(dst, M_WAITOK);
  545         if (odst)
  546                 sockaddr_free(odst);
  547 
  548         ifp->if_flags |= IFF_RUNNING;
  549 
  550         sc->sc_si = softint_establish(SOFTINT_NET, etheripintr, sc);
  551         if (sc->sc_si == NULL)
  552                 error = ENOMEM;
  553 
  554 out:
  555         splx(s);
  556 
  557         return(error);
  558 }
  559 
  560 static void
  561 etherip_delete_tunnel(struct ifnet *ifp)
  562 {
  563         struct etherip_softc *sc = ifp->if_softc;
  564         int s;
  565 
  566         s = splsoftnet();
  567 
  568         if (sc->sc_si) {
  569                 softint_disestablish(sc->sc_si);
  570                 sc->sc_si = NULL;
  571         }
  572 
  573         if (sc->sc_src) {
  574                 sockaddr_free(sc->sc_src);
  575                 sc->sc_src = NULL;
  576         }
  577         if (sc->sc_dst) {
  578                 sockaddr_free(sc->sc_dst);
  579                 sc->sc_dst = NULL;
  580         }
  581 
  582         ifp->if_flags &= ~IFF_RUNNING;
  583         splx(s);
  584 }
  585 
  586 static int
  587 etherip_init(struct ifnet *ifp)
  588 {
  589         struct etherip_softc *sc = ifp->if_softc;
  590 
  591         if (sc->sc_si == NULL)
  592                 sc->sc_si = softint_establish(SOFTINT_NET, etheripintr, sc);
  593 
  594         if (sc->sc_si == NULL)
  595                 return(ENOMEM);
  596 
  597         ifp->if_flags |= IFF_RUNNING;
  598         etherip_start(ifp);
  599 
  600         return 0;
  601 }
  602 
  603 static void
  604 etherip_stop(struct ifnet *ifp, int disable)
  605 {
  606         ifp->if_flags &= ~IFF_RUNNING;
  607 }
  608 
  609 static int
  610 etherip_clone_create(struct if_clone *ifc, int unit)
  611 {
  612         cfdata_t cf;
  613 
  614         MALLOC(cf, cfdata_t, sizeof(struct cfdata), M_DEVBUF, M_WAITOK);
  615         cf->cf_name   = etherip_cd.cd_name;
  616         cf->cf_atname = etherip_ca.ca_name;
  617         cf->cf_unit   = unit;
  618         cf->cf_fstate = FSTATE_STAR;
  619 
  620         if (config_attach_pseudo(cf) == NULL) {
  621                 aprint_error("%s%d: unable to attach an instance\n",
  622                              etherip_cd.cd_name, unit);
  623                 return (ENXIO);
  624         }
  625 
  626         return 0;
  627 }
  628 
  629 static int
  630 etherip_clone_destroy(struct ifnet *ifp)
  631 {
  632         struct etherip_softc *sc = ifp->if_softc;
  633         cfdata_t cf = device_cfdata(sc->sc_dev);
  634         int error;
  635 
  636         if ((error = config_detach(sc->sc_dev, 0)) != 0)
  637                 aprint_error_dev(sc->sc_dev, "unable to detach instance\n");
  638         FREE(cf, M_DEVBUF);
  639 
  640         return error;
  641 }
  642 
  643 SYSCTL_SETUP(sysctl_etherip_setup, "sysctl net.link.etherip subtree setup")
  644 {
  645         const struct sysctlnode *node;
  646         int error = 0;
  647 
  648         error = sysctl_createv(clog, 0, NULL, NULL,
  649                                CTLFLAG_PERMANENT,
  650                                CTLTYPE_NODE, "net", NULL,
  651                                NULL, 0, NULL, 0,
  652                                CTL_NET, CTL_EOL);
  653         if (error)
  654                 return;
  655 
  656         error = sysctl_createv(clog, 0, NULL, NULL,
  657                                CTLFLAG_PERMANENT,
  658                                CTLTYPE_NODE, "link", NULL,
  659                                NULL, 0, NULL, 0,
  660                                CTL_NET, AF_LINK, CTL_EOL);
  661         if (error)
  662                 return;
  663 
  664         error = sysctl_createv(clog, 0, NULL, &node,
  665                                CTLFLAG_PERMANENT,
  666                                CTLTYPE_NODE, "etherip", NULL,
  667                                NULL, 0, NULL, 0,
  668                                CTL_NET, AF_LINK, CTL_CREATE, CTL_EOL);
  669         if (error)
  670                 return;
  671 
  672         etherip_node = node->sysctl_num;
  673 }
  674 
  675 static int
  676 etherip_sysctl_handler(SYSCTLFN_ARGS)
  677 {
  678         struct sysctlnode node;
  679         struct etherip_softc *sc;
  680         struct ifnet *ifp;
  681         int error;
  682         size_t len;
  683         char addr[3 * ETHER_ADDR_LEN];
  684         char enaddr[ETHER_ADDR_LEN];
  685 
  686         node = *rnode;
  687         sc = node.sysctl_data;
  688         ifp = &sc->sc_ec.ec_if;
  689         (void)ether_snprintf(addr, sizeof(addr), CLLADDR(ifp->if_sadl));
  690         node.sysctl_data = addr;
  691         error = sysctl_lookup(SYSCTLFN_CALL(&node));
  692         if (error || newp == NULL)
  693                 return error;
  694 
  695         len = strlen(addr);
  696         if (len < 11 || len > 17)
  697                 return EINVAL;
  698 
  699         /* Commit change */
  700         if (ether_nonstatic_aton(enaddr, addr) != 0)
  701                 return EINVAL;
  702 
  703         if_set_sadl(ifp, enaddr, ETHER_ADDR_LEN);
  704         return error;
  705 }
  706 

Cache object: a01cf0cb6087161d63de57fbfc1a4cd5


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