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/netgraph/ng_eiface.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  *
    3  * Copyright (c) 1999-2001, Vitaly V Belekhov
    4  * All rights reserved.
    5  *
    6  * Redistribution and use in source and binary forms, with or without
    7  * modification, are permitted provided that the following conditions
    8  * are met:
    9  * 1. Redistributions of source code must retain the above copyright
   10  *    notice unmodified, this list of conditions, and the following
   11  *    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  *
   16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   26  * SUCH DAMAGE.
   27  *
   28  * $FreeBSD$
   29  */
   30 
   31 #include <sys/param.h>
   32 #include <sys/systm.h>
   33 #include <sys/errno.h>
   34 #include <sys/kernel.h>
   35 #include <sys/malloc.h>
   36 #include <sys/mbuf.h>
   37 #include <sys/errno.h>
   38 #include <sys/sockio.h>
   39 #include <sys/socket.h>
   40 #include <sys/syslog.h>
   41 
   42 #include <net/if.h>
   43 #include <net/if_dl.h>
   44 #include <net/if_types.h>
   45 #include <net/netisr.h>
   46 
   47 #include <netgraph/ng_message.h>
   48 #include <netgraph/netgraph.h>
   49 #include <netgraph/ng_parse.h>
   50 #include <netgraph/ng_eiface.h>
   51 
   52 #include <net/bpf.h>
   53 #include <net/ethernet.h>
   54 #include <net/if_arp.h>
   55 
   56 static const struct ng_cmdlist ng_eiface_cmdlist[] = {
   57         {
   58           NGM_EIFACE_COOKIE,
   59           NGM_EIFACE_GET_IFNAME,
   60           "getifname",
   61           NULL,
   62           &ng_parse_string_type
   63         },
   64         {
   65           NGM_EIFACE_COOKIE,
   66           NGM_EIFACE_SET,
   67           "set",
   68           &ng_parse_enaddr_type,
   69           NULL
   70         },
   71         { 0 }
   72 };
   73 
   74 /* Node private data */
   75 struct ng_eiface_private {
   76         struct arpcom   arpcom;         /* per-interface network data */
   77         struct ifnet    *ifp;           /* This interface */
   78         int             unit;           /* Interface unit number */
   79         node_p          node;           /* Our netgraph node */
   80         hook_p          ether;          /* Hook for ethernet stream */
   81 };
   82 typedef struct ng_eiface_private *priv_p;
   83 
   84 /* Interface methods */
   85 static void     ng_eiface_init(void *xsc);
   86 static void     ng_eiface_start(struct ifnet *ifp);
   87 static int      ng_eiface_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data);
   88 #ifdef DEBUG
   89 static void     ng_eiface_print_ioctl(struct ifnet *ifp, int cmd, caddr_t data);
   90 #endif
   91 
   92 /* Netgraph methods */
   93 static ng_constructor_t ng_eiface_constructor;
   94 static ng_rcvmsg_t      ng_eiface_rcvmsg;
   95 static ng_shutdown_t    ng_eiface_rmnode;
   96 static ng_newhook_t     ng_eiface_newhook;
   97 static ng_rcvdata_t     ng_eiface_rcvdata;
   98 static ng_connect_t     ng_eiface_connect;
   99 static ng_disconnect_t  ng_eiface_disconnect;
  100 
  101 /* Node type descriptor */
  102 static struct ng_type typestruct = {
  103         .version =      NG_ABI_VERSION,
  104         .name =         NG_EIFACE_NODE_TYPE,
  105         .constructor =  ng_eiface_constructor,
  106         .rcvmsg =       ng_eiface_rcvmsg,
  107         .shutdown =     ng_eiface_rmnode,
  108         .newhook =      ng_eiface_newhook,
  109         .connect =      ng_eiface_connect,
  110         .rcvdata =      ng_eiface_rcvdata,
  111         .rcvdataq =     ng_eiface_rcvdata,
  112         .disconnect =   ng_eiface_disconnect,
  113         .cmdlist =      ng_eiface_cmdlist
  114 };
  115 NETGRAPH_INIT(eiface, &typestruct);
  116 
  117 /* We keep a bitmap indicating which unit numbers are free.
  118    One means the unit number is free, zero means it's taken. */
  119 static int      *ng_eiface_units = NULL;
  120 static int      ng_eiface_units_len = 0;
  121 static int      ng_units_in_use = 0;
  122 
  123 #define UNITS_BITSPERWORD       (sizeof(*ng_eiface_units) * NBBY)
  124 
  125 /************************************************************************
  126                         HELPER STUFF
  127  ************************************************************************/
  128 /*
  129  * Find the first free unit number for a new interface.
  130  * Increase the size of the unit bitmap as necessary.
  131  */
  132 static __inline int
  133 ng_eiface_get_unit(int *unit)
  134 {
  135         int index, bit;
  136 
  137         for (index = 0; index < ng_eiface_units_len
  138             && ng_eiface_units[index] == 0; index++);
  139         if (index == ng_eiface_units_len) {             /* extend array */
  140                 int i, *newarray, newlen;
  141 
  142                 newlen = (2 * ng_eiface_units_len) + 4;
  143                 MALLOC(newarray, int *, newlen * sizeof(*ng_eiface_units),
  144                     M_NETGRAPH, M_NOWAIT);
  145                 if (newarray == NULL) {
  146                         return (ENOMEM);
  147                 }
  148                 bcopy(ng_eiface_units, newarray,
  149                     ng_eiface_units_len * sizeof(*ng_eiface_units));
  150                 for (i = ng_eiface_units_len; i < newlen; i++)
  151                         newarray[i] = ~0;
  152                 if (ng_eiface_units != NULL)
  153                         FREE(ng_eiface_units, M_NETGRAPH);
  154                 ng_eiface_units = newarray;
  155                 ng_eiface_units_len = newlen;
  156         }
  157         bit = ffs(ng_eiface_units[index]) - 1;
  158         KASSERT(bit >= 0 && bit <= UNITS_BITSPERWORD - 1,
  159             ("%s: word=%d bit=%d", __func__, ng_eiface_units[index], bit));
  160         ng_eiface_units[index] &= ~(1 << bit);
  161         *unit = (index * UNITS_BITSPERWORD) + bit;
  162         ng_units_in_use++;
  163         return (0);
  164 }
  165 
  166 /*
  167  * Free a no longer needed unit number.
  168  */
  169 static __inline void
  170 ng_eiface_free_unit(int unit)
  171 {
  172         int index, bit;
  173 
  174         index = unit / UNITS_BITSPERWORD;
  175         bit = unit % UNITS_BITSPERWORD;
  176         KASSERT(index < ng_eiface_units_len,
  177             ("%s: unit=%d len=%d", __func__, unit, ng_eiface_units_len));
  178         KASSERT((ng_eiface_units[index] & (1 << bit)) == 0,
  179             ("%s: unit=%d is free", __func__, unit));
  180         ng_eiface_units[index] |= (1 << bit);
  181         /*
  182          * XXX We could think about reducing the size of ng_eiface_units[]
  183          * XXX here if the last portion is all ones
  184          * XXX At least free it if no more units.
  185          * Needed if we are to eventually be able to unload.
  186          */
  187         ng_units_in_use--;
  188         if (ng_units_in_use == 0) { /* XXX make SMP safe */
  189                 FREE(ng_eiface_units, M_NETGRAPH);
  190                 ng_eiface_units_len = 0;
  191                 ng_eiface_units = NULL;
  192         }
  193 }
  194 
  195 /************************************************************************
  196                         INTERFACE STUFF
  197  ************************************************************************/
  198 
  199 /*
  200  * Process an ioctl for the virtual interface
  201  */
  202 static int
  203 ng_eiface_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
  204 {
  205         struct ifreq *const ifr = (struct ifreq *)data;
  206         int s, error = 0;
  207 
  208 #ifdef DEBUG
  209         ng_eiface_print_ioctl(ifp, command, data);
  210 #endif
  211         s = splimp();
  212         switch (command) {
  213 
  214         /* These two are mostly handled at a higher layer */
  215         case SIOCSIFADDR:
  216                 error = ether_ioctl(ifp, command, data);
  217                 break;
  218         case SIOCGIFADDR:
  219                 break;
  220 
  221         /* Set flags */
  222         case SIOCSIFFLAGS:
  223                 /*
  224                  * If the interface is marked up and stopped, then start it.
  225                  * If it is marked down and running, then stop it.
  226                  */
  227                 if (ifr->ifr_flags & IFF_UP) {
  228                         if (!(ifp->if_flags & IFF_RUNNING)) {
  229                                 ifp->if_flags &= ~(IFF_OACTIVE);
  230                                 ifp->if_flags |= IFF_RUNNING;
  231                         }
  232                 } else {
  233                         if (ifp->if_flags & IFF_RUNNING)
  234                                 ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
  235                 }
  236                 break;
  237 
  238         /* Set the interface MTU */
  239         case SIOCSIFMTU:
  240                 if (ifr->ifr_mtu > NG_EIFACE_MTU_MAX ||
  241                     ifr->ifr_mtu < NG_EIFACE_MTU_MIN)
  242                         error = EINVAL;
  243                 else
  244                         ifp->if_mtu = ifr->ifr_mtu;
  245                 break;
  246 
  247         /* Stuff that's not supported */
  248         case SIOCADDMULTI:
  249         case SIOCDELMULTI:
  250                 error = 0;
  251                 break;
  252         case SIOCSIFPHYS:
  253                 error = EOPNOTSUPP;
  254                 break;
  255 
  256         default:
  257                 error = EINVAL;
  258                 break;
  259         }
  260         splx(s);
  261         return (error);
  262 }
  263 
  264 static void
  265 ng_eiface_init(void *xsc)
  266 {
  267         priv_p sc = xsc;
  268         struct ifnet *ifp = sc->ifp;
  269         int s;
  270 
  271         s = splimp();
  272 
  273         ifp->if_flags |= IFF_RUNNING;
  274         ifp->if_flags &= ~IFF_OACTIVE;
  275 
  276         splx(s);
  277 }
  278 
  279 /*
  280  * This routine is called to deliver a packet out the interface.
  281  * We simply relay the packet to
  282  * the ether hook, if it is connected.
  283  */
  284 static void
  285 ng_eiface_start(struct ifnet *ifp)
  286 {
  287         const priv_p priv = (priv_p)ifp->if_softc;
  288         meta_p meta = NULL;
  289         int len, error = 0;
  290         struct mbuf *m;
  291 
  292         /* Check interface flags */
  293         if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) != (IFF_UP | IFF_RUNNING))
  294                 return;
  295 
  296         /* Don't do anything if output is active */
  297         if (ifp->if_flags & IFF_OACTIVE)
  298                 return;
  299 
  300         ifp->if_flags |= IFF_OACTIVE;
  301 
  302         /*
  303          * Grab a packet to transmit.
  304          */
  305         IF_DEQUEUE(&ifp->if_snd, m);
  306 
  307         /* If there's nothing to send, return. */
  308         if (m == NULL) {
  309                 ifp->if_flags &= ~IFF_OACTIVE;
  310                 return;
  311         }
  312 
  313         /*
  314          * Berkeley packet filter.
  315          * Pass packet to bpf if there is a listener.
  316          */
  317         if (ifp->if_bpf)
  318                 bpf_mtap(ifp, m);
  319 
  320         /* Copy length before the mbuf gets invalidated */
  321         len = m->m_pkthdr.len;
  322 
  323         /*
  324          * Send packet; if hook is not connected, mbuf will get
  325          * freed.
  326          */
  327         NG_SEND_DATA(error, priv->ether, m, meta);
  328 
  329         /* Update stats */
  330         if (error == 0) {
  331                 ifp->if_obytes += len;
  332                 ifp->if_opackets++;
  333         }
  334 
  335         ifp->if_flags &= ~IFF_OACTIVE;
  336 
  337         return;
  338 }
  339 
  340 #ifdef DEBUG
  341 /*
  342  * Display an ioctl to the virtual interface
  343  */
  344 
  345 static void
  346 ng_eiface_print_ioctl(struct ifnet *ifp, int command, caddr_t data)
  347 {
  348         char *str;
  349 
  350         switch (command & IOC_DIRMASK) {
  351         case IOC_VOID:
  352                 str = "IO";
  353                 break;
  354         case IOC_OUT:
  355                 str = "IOR";
  356                 break;
  357         case IOC_IN:
  358                 str = "IOW";
  359                 break;
  360         case IOC_INOUT:
  361                 str = "IORW";
  362                 break;
  363         default:
  364                 str = "IO??";
  365         }
  366         log(LOG_DEBUG, "%s%d: %s('%c', %d, char[%d])\n",
  367             ifp->if_name, ifp->if_unit,
  368             str,
  369             IOCGROUP(command),
  370             command & 0xff,
  371             IOCPARM_LEN(command));
  372 }
  373 #endif /* DEBUG */
  374 
  375 /************************************************************************
  376                         NETGRAPH NODE STUFF
  377  ************************************************************************/
  378 
  379 /*
  380  * Constructor for a node
  381  */
  382 static int
  383 ng_eiface_constructor(node_p *nodep)
  384 {
  385         struct ifnet *ifp;
  386         node_p node;
  387         priv_p priv;
  388         int error = 0;
  389 
  390         /* Allocate node and interface private structures */
  391         MALLOC(priv, priv_p, sizeof(*priv), M_NETGRAPH, M_WAITOK);
  392         if (priv == NULL)
  393                 return (ENOMEM);
  394         bzero(priv, sizeof(*priv));
  395 
  396         ifp = &(priv->arpcom.ac_if);
  397 
  398         /* Link them together */
  399         ifp->if_softc = priv;
  400         priv->ifp = ifp;
  401 
  402         /* Get an interface unit number */
  403         if ((error = ng_eiface_get_unit(&priv->unit)) != 0) {
  404                 FREE(priv, M_NETGRAPH);
  405                 return (error);
  406         }
  407 
  408         /* Call generic node constructor */
  409         if ((error = ng_make_node_common(&typestruct, nodep))) {
  410                 ng_eiface_free_unit(priv->unit);
  411                 FREE(priv, M_NETGRAPH);
  412                 return (error);
  413         }
  414         node = *nodep;
  415 
  416         /* Link together node and private info */
  417         NG_NODE_SET_PRIVATE(node, priv);
  418         priv->node = node;
  419 
  420         /* Initialize interface structure */
  421         ifp->if_name = NG_EIFACE_EIFACE_NAME;
  422         ifp->if_unit = priv->unit;
  423         ifp->if_init = ng_eiface_init;
  424         ifp->if_output = ether_output;
  425         ifp->if_start = ng_eiface_start;
  426         ifp->if_ioctl = ng_eiface_ioctl;
  427         ifp->if_watchdog = NULL;
  428         ifp->if_snd.ifq_maxlen = IFQ_MAXLEN;
  429         ifp->if_flags = (IFF_SIMPLEX | IFF_BROADCAST | IFF_MULTICAST);
  430 
  431 #if 0
  432         /* Give this node name */
  433         bzero(ifname, sizeof(ifname));
  434         sprintf(ifname, "if%s%d", ifp->if_name, ifp->if_unit);
  435         (void)ng_name_node(node, ifname);
  436 #endif
  437 
  438         /* Attach the interface */
  439         ether_ifattach(ifp, ETHER_BPF_SUPPORTED);
  440 
  441         /* Done */
  442         return (0);
  443 }
  444 
  445 /*
  446  * Give our ok for a hook to be added
  447  */
  448 static int
  449 ng_eiface_newhook(node_p node, hook_p hook, const char *name)
  450 {
  451         priv_p priv = NG_NODE_PRIVATE(node);
  452 
  453         if (strcmp(name, NG_EIFACE_HOOK_ETHER))
  454                 return (EPFNOSUPPORT);
  455         if (priv->ether != NULL)
  456                 return (EISCONN);
  457         priv->ether = hook;
  458         NG_HOOK_SET_PRIVATE(hook, &priv->ether);
  459 
  460         return (0);
  461 }
  462 
  463 /*
  464  * Receive a control message
  465  */
  466 static int
  467 ng_eiface_rcvmsg(node_p node, struct ng_mesg *msg,
  468     const char *retaddr, struct ng_mesg **rptr)
  469 {
  470         const priv_p priv = NG_NODE_PRIVATE(node);
  471         struct ifnet *const ifp = priv->ifp;
  472         struct ng_mesg *resp = NULL;
  473         int error = 0;
  474 
  475         switch (msg->header.typecookie) {
  476         case NGM_EIFACE_COOKIE:
  477                 switch (msg->header.cmd) {
  478 
  479                 case NGM_EIFACE_SET:
  480                     {
  481                         struct ether_addr *eaddr;
  482                         struct ifaddr *ifa;
  483                         struct sockaddr_dl *sdl;
  484 
  485                         if (msg->header.arglen != sizeof(struct ether_addr)) {
  486                                 error = EINVAL;
  487                                 break;
  488                         }
  489                         eaddr = (struct ether_addr *)(msg->data);
  490                         bcopy(eaddr, priv->arpcom.ac_enaddr, ETHER_ADDR_LEN);
  491 
  492                         /* And put it in the ifaddr list */
  493 #define IFP2AC(ifp) ((struct arpcom *)(ifp))
  494                         TAILQ_FOREACH(ifa, &(ifp->if_addrhead), ifa_link) {
  495                                 sdl = (struct sockaddr_dl *)ifa->ifa_addr;
  496                                 if (sdl->sdl_type == IFT_ETHER) {
  497                                         bcopy((IFP2AC(ifp))->ac_enaddr,
  498                                                 LLADDR(sdl), ifp->if_addrlen);
  499                                         break;
  500                                 }
  501                         }
  502                         break;
  503                     }
  504 
  505                 case NGM_EIFACE_GET_IFNAME:
  506                         NG_MKRESPONSE(resp, msg, IFNAMSIZ + 1, M_NOWAIT);
  507                         if (resp == NULL) {
  508                                 error = ENOMEM;
  509                                 break;
  510                         }
  511                         snprintf(resp->data, IFNAMSIZ + 1,
  512                             "%s%d", ifp->if_name, ifp->if_unit);
  513                         break;
  514 
  515                 case NGM_EIFACE_GET_IFADDRS:
  516                     {
  517                         struct ifaddr *ifa;
  518                         caddr_t ptr;
  519                         int buflen;
  520 
  521 #define SA_SIZE(s)      ((s)->sa_len<sizeof(*(s))? sizeof(*(s)):(s)->sa_len)
  522 
  523                         /* Determine size of response and allocate it */
  524                         buflen = 0;
  525                         TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link)
  526                                 buflen += SA_SIZE(ifa->ifa_addr);
  527                         NG_MKRESPONSE(resp, msg, buflen, M_NOWAIT);
  528                         if (resp == NULL) {
  529                                 error = ENOMEM;
  530                                 break;
  531                         }
  532 
  533                         /* Add addresses */
  534                         ptr = resp->data;
  535                         TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
  536                                 const int len = SA_SIZE(ifa->ifa_addr);
  537 
  538                                 if (buflen < len) {
  539                                         log(LOG_ERR, "%s%d: len changed?\n",
  540                                             ifp->if_name, ifp->if_unit);
  541                                         break;
  542                                 }
  543                                 bcopy(ifa->ifa_addr, ptr, len);
  544                                 ptr += len;
  545                                 buflen -= len;
  546                         }
  547                         break;
  548 #undef SA_SIZE
  549                     }
  550 
  551                 default:
  552                         error = EINVAL;
  553                         break;
  554                 } /* end of inner switch() */
  555                 break;
  556         default:
  557                 error = EINVAL;
  558                 break;
  559         }
  560         NG_RESPOND_MSG(error, node, retaddr, resp, rptr);
  561         NG_FREE_MSG(msg);
  562         return (error);
  563 }
  564 
  565 /*
  566  * Receive data from a hook. Pass the packet to the ether_input routine.
  567  */
  568 static int
  569 ng_eiface_rcvdata(hook_p hook, struct mbuf *m, meta_p meta)
  570 {
  571         const priv_p priv = NG_NODE_PRIVATE(NG_HOOK_NODE(hook));
  572         struct ifnet *const ifp = priv->ifp;
  573 
  574         NG_FREE_META(meta);
  575 
  576         if (m == NULL) {
  577                 printf("ng_eiface: mbuf is null.\n");
  578                 return (EINVAL);
  579         }
  580 
  581         if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) !=
  582             (IFF_UP | IFF_RUNNING)) {
  583                 NG_FREE_M(m);
  584                 return (ENETDOWN);
  585         }
  586 
  587         if (m->m_len < ETHER_HDR_LEN) {
  588                 m = m_pullup(m, ETHER_HDR_LEN);
  589                 if (m == NULL)
  590                         return (EINVAL);
  591         }
  592 
  593         /* Note receiving interface */
  594         m->m_pkthdr.rcvif = ifp;
  595 
  596         /* Update interface stats */
  597         ifp->if_ipackets++;
  598 
  599         ether_input(ifp, NULL, m);
  600 
  601         /* Done */
  602         return (0);
  603 }
  604 
  605 /*
  606  * Shutdown processing.
  607  */
  608 static int
  609 ng_eiface_rmnode(node_p node)
  610 {
  611         const priv_p priv = NG_NODE_PRIVATE(node);
  612         struct ifnet *const ifp = priv->ifp;
  613 
  614         node->flags |= NG_INVALID;
  615         ether_ifdetach(ifp, ETHER_BPF_SUPPORTED);
  616         ng_eiface_free_unit(priv->unit);
  617         ng_cutlinks(node);
  618         ng_unname(node);
  619         FREE(priv, M_NETGRAPH);
  620         NG_NODE_SET_PRIVATE(node, NULL);
  621         NG_NODE_UNREF(node);
  622         return (0);
  623 }
  624 
  625 
  626 /*
  627  * This is called once we've already connected a new hook to the other node.
  628  * It gives us a chance to balk at the last minute.
  629  */
  630 static int
  631 ng_eiface_connect(hook_p hook)
  632 {
  633         /* be really amiable and just say "YUP that's OK by me! " */
  634         return (0);
  635 }
  636 
  637 /*
  638  * Hook disconnection
  639  */
  640 static int
  641 ng_eiface_disconnect(hook_p hook)
  642 {
  643         const priv_p priv = NG_NODE_PRIVATE(NG_HOOK_NODE(hook));
  644 
  645         priv->ether = NULL;
  646         return (0);
  647 }

Cache object: 577042a53ae0851970cc93251e848b9a


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