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_iface.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  * ng_iface.c
    4  *
    5  * Copyright (c) 1996-1999 Whistle Communications, Inc.
    6  * All rights reserved.
    7  * 
    8  * Subject to the following obligations and disclaimer of warranty, use and
    9  * redistribution of this software, in source or object code forms, with or
   10  * without modifications are expressly permitted by Whistle Communications;
   11  * provided, however, that:
   12  * 1. Any and all reproductions of the source or object code must include the
   13  *    copyright notice above and the following disclaimer of warranties; and
   14  * 2. No rights are granted, in any manner or form, to use Whistle
   15  *    Communications, Inc. trademarks, including the mark "WHISTLE
   16  *    COMMUNICATIONS" on advertising, endorsements, or otherwise except as
   17  *    such appears in the above copyright notice or in the software.
   18  * 
   19  * THIS SOFTWARE IS BEING PROVIDED BY WHISTLE COMMUNICATIONS "AS IS", AND
   20  * TO THE MAXIMUM EXTENT PERMITTED BY LAW, WHISTLE COMMUNICATIONS MAKES NO
   21  * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING THIS SOFTWARE,
   22  * INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED WARRANTIES OF
   23  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
   24  * WHISTLE COMMUNICATIONS DOES NOT WARRANT, GUARANTEE, OR MAKE ANY
   25  * REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS OF THE USE OF THIS
   26  * SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY, RELIABILITY OR OTHERWISE.
   27  * IN NO EVENT SHALL WHISTLE COMMUNICATIONS BE LIABLE FOR ANY DAMAGES
   28  * RESULTING FROM OR ARISING OUT OF ANY USE OF THIS SOFTWARE, INCLUDING
   29  * WITHOUT LIMITATION, ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
   30  * PUNITIVE, OR CONSEQUENTIAL DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR
   31  * SERVICES, LOSS OF USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY
   32  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   33  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   34  * THIS SOFTWARE, EVEN IF WHISTLE COMMUNICATIONS IS ADVISED OF THE POSSIBILITY
   35  * OF SUCH DAMAGE.
   36  *
   37  * Author: Archie Cobbs <archie@freebsd.org>
   38  *
   39  * $FreeBSD$
   40  * $Whistle: ng_iface.c,v 1.33 1999/11/01 09:24:51 julian Exp $
   41  */
   42 
   43 /*
   44  * This node is also a system networking interface. It has
   45  * a hook for each protocol (IP, AppleTalk, IPX, etc). Packets
   46  * are simply relayed between the interface and the hooks.
   47  *
   48  * Interfaces are named ng0, ng1, .... FreeBSD does not support
   49  * the removal of interfaces, so iface nodes are persistent.
   50  *
   51  * This node also includes Berkeley packet filter support.
   52  */
   53 
   54 #include "opt_inet.h"
   55 #include "opt_atalk.h"
   56 #include "opt_ipx.h"
   57 
   58 #include <sys/param.h>
   59 #include <sys/systm.h>
   60 #include <sys/errno.h>
   61 #include <sys/kernel.h>
   62 #include <sys/malloc.h>
   63 #include <sys/mbuf.h>
   64 #include <sys/errno.h>
   65 #include <sys/sockio.h>
   66 #include <sys/socket.h>
   67 #include <sys/syslog.h>
   68 
   69 #include <net/if.h>
   70 #include <net/if_types.h>
   71 #include <net/netisr.h>
   72 
   73 #include <netinet/in.h>
   74 
   75 #include <netgraph/ng_message.h>
   76 #include <netgraph/netgraph.h>
   77 #include <netgraph/ng_iface.h>
   78 #include <netgraph/ng_cisco.h>
   79 
   80 #ifdef INET
   81 #include <netinet/in_systm.h>
   82 #include <netinet/in_var.h>
   83 #include <netinet/in_var.h>
   84 #endif
   85 
   86 #ifdef NETATALK
   87 #include <netatalk/at.h>
   88 #include <netatalk/at_var.h>
   89 #endif
   90 
   91 #ifdef IPX
   92 #include <netipx/ipx.h>
   93 #include <netipx/ipx_if.h>
   94 #endif
   95 
   96 #ifdef NS
   97 #include <netns/ns.h>
   98 #include <netns/ns_if.h>
   99 #endif
  100 
  101 #include "bpfilter.h"
  102 
  103 #if NBPFILTER > 0
  104 #include <net/bpf.h>
  105 #include <net/bpfdesc.h>
  106 #endif
  107 
  108 /* This struct describes one address family */
  109 struct iffam {
  110         char   *hookname;       /* Name for hook */
  111         u_char  af;             /* Family number */
  112         u_char  netisr;         /* or NETISR_NONE */
  113         union {
  114                 void    *_dummy;                        /* avoid warning */
  115                 struct  ifqueue *inq;                   /* if netisr */
  116                 void    (*input)(struct mbuf *m);       /* if direct input */
  117         }       u;
  118 };
  119 typedef const struct iffam *iffam_p;
  120 
  121 #define NETISR_NONE     0xff
  122 
  123 /* List of address families supported by our interface. Each address
  124    family has a way to input packets to it, either by calling a function
  125    directly (such as ip_input()) or by adding the packet to a queue and
  126    setting a NETISR bit. */
  127 const static struct iffam gFamilies[] = {
  128 #ifdef INET
  129         {
  130                 NG_IFACE_HOOK_INET,
  131                 AF_INET,
  132                 NETISR_NONE,
  133                 { ip_input }
  134         },
  135 #endif
  136 #ifdef NETATALK
  137         {
  138                 NG_IFACE_HOOK_ATALK,
  139                 AF_APPLETALK,
  140                 NETISR_ATALK,
  141                 { &atintrq2 }
  142         },
  143 #endif
  144 #ifdef IPX
  145         {
  146                 NG_IFACE_HOOK_IPX,
  147                 AF_IPX,
  148                 NETISR_IPX,
  149                 { &ipxintrq }
  150         },
  151 #endif
  152 #ifdef NS
  153         {
  154                 NG_IFACE_HOOK_NS,
  155                 AF_NS,
  156                 NETISR_NS,
  157                 { &nsintrq }
  158         },
  159 #endif
  160 };
  161 #define NUM_FAMILIES            (sizeof(gFamilies) / sizeof(*gFamilies))
  162 
  163 /* Node private data */
  164 struct ng_iface_private {
  165         struct  ifnet *ifp;             /* This interface */
  166         node_p  node;                   /* Our netgraph node */
  167         hook_p  hooks[NUM_FAMILIES];    /* Hook for each address family */
  168         struct  private *next;          /* When hung on the free list */
  169 };
  170 typedef struct ng_iface_private *priv_p;
  171 
  172 /* Interface methods */
  173 static void     ng_iface_start(struct ifnet *ifp);
  174 static int      ng_iface_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data);
  175 static int      ng_iface_output(struct ifnet *ifp, struct mbuf *m0,
  176                 struct sockaddr *dst, struct rtentry *rt0);
  177 #if NBPFILTER > 0
  178 static void     ng_iface_bpftap(struct ifnet *ifp, struct mbuf *m, u_int af);
  179 #endif
  180 #ifdef DEBUG
  181 static void     ng_iface_print_ioctl(struct ifnet *ifp, int cmd, caddr_t data);
  182 #endif
  183 
  184 /* Netgraph methods */
  185 static ng_constructor_t ng_iface_constructor;
  186 static ng_rcvmsg_t      ng_iface_rcvmsg;
  187 static ng_shutdown_t    ng_iface_rmnode;
  188 static ng_newhook_t     ng_iface_newhook;
  189 static ng_rcvdata_t     ng_iface_rcvdata;
  190 static ng_disconnect_t  ng_iface_disconnect;
  191 
  192 /* Helper stuff */
  193 static iffam_p  get_iffam_from_af(int af);
  194 static iffam_p  get_iffam_from_hook(priv_p priv, hook_p hook);
  195 static iffam_p  get_iffam_from_name(const char *name);
  196 static hook_p  *get_hook_from_iffam(priv_p priv, iffam_p iffam);
  197 
  198 /* Node type descriptor */
  199 static struct ng_type typestruct = {
  200         NG_VERSION,
  201         NG_IFACE_NODE_TYPE,
  202         NULL,
  203         ng_iface_constructor,
  204         ng_iface_rcvmsg,
  205         ng_iface_rmnode,
  206         ng_iface_newhook,
  207         NULL,
  208         NULL,
  209         ng_iface_rcvdata,
  210         ng_iface_rcvdata,
  211         ng_iface_disconnect,
  212         NULL
  213 };
  214 NETGRAPH_INIT(iface, &typestruct);
  215 
  216 static char ng_iface_ifname[] = NG_IFACE_IFACE_NAME;
  217 static int ng_iface_next_unit;
  218 
  219 /************************************************************************
  220                         HELPER STUFF
  221  ************************************************************************/
  222 
  223 /*
  224  * Get the family descriptor from the family ID
  225  */
  226 static __inline__ iffam_p
  227 get_iffam_from_af(int af)
  228 {
  229         iffam_p iffam;
  230         int k;
  231 
  232         for (k = 0; k < NUM_FAMILIES; k++) {
  233                 iffam = &gFamilies[k];
  234                 if (iffam->af == af)
  235                         return (iffam);
  236         }
  237         return (NULL);
  238 }
  239 
  240 /*
  241  * Get the family descriptor from the hook
  242  */
  243 static __inline__ iffam_p
  244 get_iffam_from_hook(priv_p priv, hook_p hook)
  245 {
  246         int k;
  247 
  248         for (k = 0; k < NUM_FAMILIES; k++)
  249                 if (priv->hooks[k] == hook)
  250                         return (&gFamilies[k]);
  251         return (NULL);
  252 }
  253 
  254 /*
  255  * Get the hook from the iffam descriptor
  256  */
  257 
  258 static __inline__ hook_p *
  259 get_hook_from_iffam(priv_p priv, iffam_p iffam)
  260 {
  261         return (&priv->hooks[iffam - gFamilies]);
  262 }
  263 
  264 /*
  265  * Get the iffam descriptor from the name
  266  */
  267 static __inline__ iffam_p
  268 get_iffam_from_name(const char *name)
  269 {
  270         iffam_p iffam;
  271         int k;
  272 
  273         for (k = 0; k < NUM_FAMILIES; k++) {
  274                 iffam = &gFamilies[k];
  275                 if (!strcmp(iffam->hookname, name))
  276                         return (iffam);
  277         }
  278         return (NULL);
  279 }
  280 
  281 /************************************************************************
  282                         INTERFACE STUFF
  283  ************************************************************************/
  284 
  285 /*
  286  * Process an ioctl for the virtual interface
  287  */
  288 static int
  289 ng_iface_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
  290 {
  291         struct ifreq *const ifr = (struct ifreq *) data;
  292         int s, error = 0;
  293 
  294 #ifdef DEBUG
  295         ng_iface_print_ioctl(ifp, command, data);
  296 #endif
  297         s = splimp();
  298         switch (command) {
  299 
  300         /* These two are mostly handled at a higher layer */
  301         case SIOCSIFADDR:
  302                 ifp->if_flags |= (IFF_UP | IFF_RUNNING);
  303                 ifp->if_flags &= ~(IFF_OACTIVE);
  304                 break;
  305         case SIOCGIFADDR:
  306                 break;
  307 
  308         /* Set flags */
  309         case SIOCSIFFLAGS:
  310                 /*
  311                  * If the interface is marked up and stopped, then start it.
  312                  * If it is marked down and running, then stop it.
  313                  */
  314                 if (ifr->ifr_flags & IFF_UP) {
  315                         if (!(ifp->if_flags & IFF_RUNNING)) {
  316                                 ifp->if_flags &= ~(IFF_OACTIVE);
  317                                 ifp->if_flags |= IFF_RUNNING;
  318                         }
  319                 } else {
  320                         if (ifp->if_flags & IFF_RUNNING)
  321                                 ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
  322                 }
  323                 break;
  324 
  325         /* Set the interface MTU */
  326         case SIOCSIFMTU:
  327                 if (ifr->ifr_mtu > NG_IFACE_MTU_MAX
  328                     || ifr->ifr_mtu < NG_IFACE_MTU_MIN)
  329                         error = EINVAL;
  330                 else
  331                         ifp->if_mtu = ifr->ifr_mtu;
  332                 break;
  333 
  334         /* Stuff that's not supported */
  335         case SIOCADDMULTI:
  336         case SIOCDELMULTI:
  337                 error = 0;
  338                 break;
  339         case SIOCSIFPHYS:
  340                 error = EOPNOTSUPP;
  341                 break;
  342 
  343         default:
  344                 error = EINVAL;
  345                 break;
  346         }
  347         (void) splx(s);
  348         return (error);
  349 }
  350 
  351 /*
  352  * This routine is called to deliver a packet out the interface.
  353  * We simply look at the address family and relay the packet to
  354  * the corresponding hook, if it exists and is connected.
  355  */
  356 
  357 static int
  358 ng_iface_output(struct ifnet *ifp, struct mbuf *m,
  359                 struct sockaddr *dst, struct rtentry *rt0)
  360 {
  361         const priv_p priv = (priv_p) ifp->if_softc;
  362         const iffam_p iffam = get_iffam_from_af(dst->sa_family);
  363         meta_p meta = NULL;
  364         int len, error = 0;
  365 
  366         /* Check interface flags */
  367         if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) {
  368                 m_freem(m);
  369                 return (ENETDOWN);
  370         }
  371 
  372         /* Berkeley packet filter */
  373 #if NBPFILTER > 0
  374         ng_iface_bpftap(ifp, m, dst->sa_family);
  375 #endif
  376 
  377         /* Check address family to determine hook (if known) */
  378         if (iffam == NULL) {
  379                 m_freem(m);
  380                 log(LOG_WARNING, "%s%d: can't handle af%d\n",
  381                        ifp->if_name, ifp->if_unit, dst->sa_family);
  382                 return (EAFNOSUPPORT);
  383         }
  384 
  385         /* Copy length before the mbuf gets invalidated */
  386         len = m->m_pkthdr.len;
  387 
  388         /* Send packet; if hook is not connected, mbuf will get freed. */
  389         NG_SEND_DATA(error, *get_hook_from_iffam(priv, iffam), m, meta);
  390 
  391         /* Update stats */
  392         if (error == 0) {
  393                 ifp->if_obytes += len;
  394                 ifp->if_opackets++;
  395         }
  396         return (error);
  397 }
  398 
  399 /*
  400  * This routine should never be called
  401  */
  402 
  403 static void
  404 ng_iface_start(struct ifnet *ifp)
  405 {
  406         printf("%s%d: %s called?", ifp->if_name, ifp->if_unit, __FUNCTION__);
  407 }
  408 
  409 #if NBPFILTER > 0
  410 /*
  411  * Flash a packet by the BPF (requires prepending 4 byte AF header)
  412  * Note the phoney mbuf; this is OK because BPF treats it read-only.
  413  */
  414 static void
  415 ng_iface_bpftap(struct ifnet *ifp, struct mbuf *m, u_int af)
  416 {
  417         struct mbuf m2;
  418 
  419         if (af == AF_UNSPEC) {
  420                 af = *(mtod(m, int *));
  421                 m->m_len -= sizeof(int);
  422                 m->m_pkthdr.len -= sizeof(int);
  423                 m->m_data += sizeof(int);
  424         }
  425         if (!ifp->if_bpf)
  426                 return;
  427         m2.m_next = m;
  428         m2.m_len = 4;
  429         m2.m_data = (char *) &af;
  430         bpf_mtap(ifp, &m2);
  431 }
  432 #endif /* NBPFILTER > 0 */
  433 
  434 #ifdef DEBUG
  435 /*
  436  * Display an ioctl to the virtual interface
  437  */
  438 
  439 static void
  440 ng_iface_print_ioctl(struct ifnet *ifp, int command, caddr_t data)
  441 {
  442         char   *str;
  443 
  444         switch (command & IOC_DIRMASK) {
  445         case IOC_VOID:
  446                 str = "IO";
  447                 break;
  448         case IOC_OUT:
  449                 str = "IOR";
  450                 break;
  451         case IOC_IN:
  452                 str = "IOW";
  453                 break;
  454         case IOC_INOUT:
  455                 str = "IORW";
  456                 break;
  457         default:
  458                 str = "IO??";
  459         }
  460         log(LOG_DEBUG, "%s%d: %s('%c', %d, char[%d])\n",
  461                ifp->if_name, ifp->if_unit,
  462                str,
  463                IOCGROUP(command),
  464                command & 0xff,
  465                IOCPARM_LEN(command));
  466 }
  467 #endif /* DEBUG */
  468 
  469 /************************************************************************
  470                         NETGRAPH NODE STUFF
  471  ************************************************************************/
  472 
  473 /*
  474  * Constructor for a node
  475  */
  476 static int
  477 ng_iface_constructor(node_p *nodep)
  478 {
  479         char ifname[NG_IFACE_IFACE_NAME_MAX + 1];
  480         struct ifnet *ifp;
  481         node_p node;
  482         priv_p priv;
  483         int error = 0;
  484 
  485         /* Allocate node and interface private structures */
  486         MALLOC(priv, priv_p, sizeof(*priv), M_NETGRAPH, M_WAITOK);
  487         if (priv == NULL)
  488                 return (ENOMEM);
  489         bzero(priv, sizeof(*priv));
  490         MALLOC(ifp, struct ifnet *, sizeof(*ifp), M_NETGRAPH, M_WAITOK);
  491         if (ifp == NULL) {
  492                 FREE(priv, M_NETGRAPH);
  493                 return (ENOMEM);
  494         }
  495         bzero(ifp, sizeof(*ifp));
  496 
  497         /* Link them together */
  498         ifp->if_softc = priv;
  499         priv->ifp = ifp;
  500 
  501         /* Call generic node constructor */
  502         if ((error = ng_make_node_common(&typestruct, nodep))) {
  503                 FREE(priv, M_NETGRAPH);
  504                 FREE(ifp, M_NETGRAPH);
  505                 return (error);
  506         }
  507         node = *nodep;
  508 
  509         /* Link together node and private info */
  510         node->private = priv;
  511         priv->node = node;
  512 
  513         /* Initialize interface structure */
  514         ifp->if_name = ng_iface_ifname;
  515         ifp->if_unit = ng_iface_next_unit++;
  516         ifp->if_output = ng_iface_output;
  517         ifp->if_start = ng_iface_start;
  518         ifp->if_ioctl = ng_iface_ioctl;
  519         ifp->if_watchdog = NULL;
  520         ifp->if_snd.ifq_maxlen = IFQ_MAXLEN;
  521         ifp->if_mtu = NG_IFACE_MTU_DEFAULT;
  522         ifp->if_flags = (IFF_SIMPLEX | IFF_POINTOPOINT | IFF_NOARP | IFF_MULTICAST);
  523         ifp->if_type = IFT_PROPVIRTUAL;         /* XXX */
  524         ifp->if_addrlen = 0;                    /* XXX */
  525         ifp->if_hdrlen = 0;                     /* XXX */
  526         ifp->if_baudrate = 64000;               /* XXX */
  527         TAILQ_INIT(&ifp->if_addrhead);
  528 
  529         /* Give this node the same name as the interface (if possible) */
  530         bzero(ifname, sizeof(ifname));
  531         sprintf(ifname, "%s%d", ifp->if_name, ifp->if_unit);
  532         (void) ng_name_node(node, ifname);
  533 
  534         /* Attach the interface */
  535         if_attach(ifp);
  536 #if NBPFILTER > 0
  537         bpfattach(ifp, DLT_NULL, sizeof(u_int));
  538 #endif
  539 
  540         /* Done */
  541         return (0);
  542 }
  543 
  544 /*
  545  * Give our ok for a hook to be added
  546  */
  547 static int
  548 ng_iface_newhook(node_p node, hook_p hook, const char *name)
  549 {
  550         const iffam_p iffam = get_iffam_from_name(name);
  551         hook_p *hookptr;
  552 
  553         if (iffam == NULL)
  554                 return (EPFNOSUPPORT);
  555         hookptr = get_hook_from_iffam((priv_p) node->private, iffam);
  556         if (*hookptr != NULL)
  557                 return (EISCONN);
  558         *hookptr = hook;
  559         return (0);
  560 }
  561 
  562 /*
  563  * Receive a control message
  564  */
  565 static int
  566 ng_iface_rcvmsg(node_p node, struct ng_mesg *msg,
  567                 const char *retaddr, struct ng_mesg **rptr)
  568 {
  569         const priv_p priv = node->private;
  570         struct ifnet *const ifp = priv->ifp;
  571         struct ng_mesg *resp = NULL;
  572         int error = 0;
  573 
  574         switch (msg->header.typecookie) {
  575         case NGM_IFACE_COOKIE:
  576                 switch (msg->header.cmd) {
  577                 case NGM_IFACE_GET_IFNAME:
  578                     {
  579                         struct ng_iface_ifname *arg;
  580 
  581                         NG_MKRESPONSE(resp, msg, sizeof(*arg), M_NOWAIT);
  582                         if (resp == NULL) {
  583                                 error = ENOMEM;
  584                                 break;
  585                         }
  586                         arg = (struct ng_iface_ifname *) resp->data;
  587                         sprintf(arg->ngif_name,
  588                             "%s%d", ifp->if_name, ifp->if_unit);
  589                         break;
  590                     }
  591 
  592                 case NGM_IFACE_GET_IFADDRS:
  593                     {
  594                         struct ifaddr *ifa;
  595                         caddr_t ptr;
  596                         int buflen;
  597 
  598 #define SA_SIZE(s)      ((s)->sa_len<sizeof(*(s))? sizeof(*(s)):(s)->sa_len)
  599 
  600                         /* Determine size of response and allocate it */
  601                         buflen = 0;
  602                         TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link)
  603                                 buflen += SA_SIZE(ifa->ifa_addr);
  604                         NG_MKRESPONSE(resp, msg, buflen, M_NOWAIT);
  605                         if (resp == NULL) {
  606                                 error = ENOMEM;
  607                                 break;
  608                         }
  609 
  610                         /* Add addresses */
  611                         ptr = resp->data;
  612                         TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
  613                                 const int len = SA_SIZE(ifa->ifa_addr);
  614 
  615                                 if (buflen < len) {
  616                                         log(LOG_ERR, "%s%d: len changed?\n",
  617                                             ifp->if_name, ifp->if_unit);
  618                                         break;
  619                                 }
  620                                 bcopy(ifa->ifa_addr, ptr, len);
  621                                 ptr += len;
  622                                 buflen -= len;
  623                         }
  624                         break;
  625 #undef SA_SIZE
  626                     }
  627 
  628                 default:
  629                         error = EINVAL;
  630                         break;
  631                 }
  632                 break;
  633         case NGM_CISCO_COOKIE:
  634                 switch (msg->header.cmd) {
  635                 case NGM_CISCO_GET_IPADDR:      /* we understand this too */
  636                     {
  637                         struct ifaddr *ifa;
  638 
  639                         /* Return the first configured IP address */
  640                         TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
  641                                 struct in_addr *ips;
  642 
  643                                 if (ifa->ifa_addr->sa_family != AF_INET)
  644                                         continue;
  645                                 NG_MKRESPONSE(resp, msg,
  646                                     2 * sizeof(*ips), M_NOWAIT);
  647                                 if (resp == NULL) {
  648                                         error = ENOMEM;
  649                                         break;
  650                                 }
  651                                 ips = (struct in_addr *) resp->data;
  652                                 ips[0] = ((struct sockaddr_in *)
  653                                                 ifa->ifa_addr)->sin_addr;
  654                                 ips[1] = ((struct sockaddr_in *)
  655                                                 ifa->ifa_netmask)->sin_addr;
  656                                 break;
  657                         }
  658 
  659                         /* No IP addresses on this interface? */
  660                         if (ifa == NULL)
  661                                 error = EADDRNOTAVAIL;
  662                         break;
  663                     }
  664                 default:
  665                         error = EINVAL;
  666                         break;
  667                 }
  668                 break;
  669         default:
  670                 error = EINVAL;
  671                 break;
  672         }
  673         if (rptr)
  674                 *rptr = resp;
  675         else if (resp)
  676                 FREE(resp, M_NETGRAPH);
  677         FREE(msg, M_NETGRAPH);
  678         return (error);
  679 }
  680 
  681 /*
  682  * Recive data from a hook. Pass the packet to the correct input routine.
  683  */
  684 static int
  685 ng_iface_rcvdata(hook_p hook, struct mbuf *m, meta_p meta)
  686 {
  687         const priv_p priv = hook->node->private;
  688         const iffam_p iffam = get_iffam_from_hook(priv, hook);
  689         struct ifnet *const ifp = priv->ifp;
  690         int s, error = 0;
  691 
  692         /* Sanity checks */
  693         KASSERT(iffam != NULL, ("%s: iffam", __FUNCTION__));
  694         KASSERT(m->m_flags & M_PKTHDR, ("%s: not pkthdr", __FUNCTION__));
  695         if (m == NULL)
  696                 return (EINVAL);
  697         if ((ifp->if_flags & IFF_UP) == 0) {
  698                 NG_FREE_DATA(m, meta);
  699                 return (ENETDOWN);
  700         }
  701 
  702         /* Update interface stats */
  703         ifp->if_ipackets++;
  704         ifp->if_ibytes += m->m_pkthdr.len;
  705 
  706         /* Note receiving interface */
  707         m->m_pkthdr.rcvif = ifp;
  708 
  709 #if NBPFILTER > 0
  710         /* Berkeley packet filter */
  711         ng_iface_bpftap(ifp, m, iffam->af);
  712 #endif
  713 
  714         /* Ignore any meta-data */
  715         NG_FREE_META(meta);
  716 
  717         /* Send packet, either by NETISR or use a direct input function */
  718         switch (iffam->netisr) {
  719         case NETISR_NONE:
  720                 (*iffam->u.input)(m);
  721                 break;
  722         default:
  723                 s = splimp();
  724                 schednetisr(iffam->netisr);
  725                 if (IF_QFULL(iffam->u.inq)) {
  726                         IF_DROP(iffam->u.inq);
  727                         m_freem(m);
  728                         error = ENOBUFS;
  729                 } else
  730                         IF_ENQUEUE(iffam->u.inq, m);
  731                 splx(s);
  732                 break;
  733         }
  734 
  735         /* Done */
  736         return (error);
  737 }
  738 
  739 /*
  740  * Because the BSD networking code doesn't support the removal of
  741  * networking interfaces, iface nodes (once created) are persistent.
  742  * So this method breaks all connections and marks the interface
  743  * down, but does not remove the node.
  744  */
  745 static int
  746 ng_iface_rmnode(node_p node)
  747 {
  748         const priv_p priv = node->private;
  749         struct ifnet *const ifp = priv->ifp;
  750 
  751         ng_cutlinks(node);
  752         node->flags &= ~NG_INVALID;
  753         ifp->if_flags &= ~(IFF_UP | IFF_RUNNING | IFF_OACTIVE);
  754         return (0);
  755 }
  756 
  757 /*
  758  * Hook disconnection
  759  */
  760 static int
  761 ng_iface_disconnect(hook_p hook)
  762 {
  763         const priv_p priv = hook->node->private;
  764         const iffam_p iffam = get_iffam_from_hook(priv, hook);
  765 
  766         if (iffam == NULL)
  767                 panic(__FUNCTION__);
  768         *get_hook_from_iffam(priv, iffam) = NULL;
  769         return (0);
  770 }
  771 

Cache object: 51c9a1d244a39766128ccd5ee07bfa23


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