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_atmllc.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) 2003-2004 Benno Rice <benno@eloquent.com.au>
    3  * All Rights Reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer.
   10  * 2. Redistributions in binary form must reproduce the above copyright
   11  *    notice, this list of conditions and the following disclaimer in the
   12  *    documentation and/or other materials provided with the distribution.
   13  *
   14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR  ``AS IS'' AND
   15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR  BE LIABLE
   18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   24  * SUCH DAMAGE.
   25  *
   26  * $FreeBSD$
   27  */
   28 
   29 #include <sys/param.h>
   30 #include <sys/systm.h>
   31 #include <sys/kernel.h>
   32 #include <sys/malloc.h>
   33 #include <sys/mbuf.h>
   34 #include <sys/socket.h>
   35 #include <sys/sockio.h>
   36 
   37 #include <netgraph/ng_message.h>
   38 #include <netgraph/netgraph.h>
   39 #include <netgraph/ng_atmllc.h>
   40 
   41 #include <net/if.h>
   42 #include <net/ethernet.h>       /* for M_HASFCS and ETHER_HDR_LEN */
   43 #include <net/if_atm.h>         /* for struct atmllc */
   44 
   45 #define NG_ATMLLC_HEADER                "\252\252\3\0\200\302"
   46 #define NG_ATMLLC_HEADER_LEN            (sizeof(struct atmllc))
   47 #define NG_ATMLLC_TYPE_ETHERNET_FCS     0x0001
   48 #define NG_ATMLLC_TYPE_FDDI_FCS         0x0004
   49 #define NG_ATMLLC_TYPE_ETHERNET_NOFCS   0x0007
   50 #define NG_ATMLLC_TYPE_FDDI_NOFCS       0x000A
   51 
   52 struct ng_atmllc_priv {
   53         hook_p          atm;
   54         hook_p          ether;
   55         hook_p          fddi;
   56 };
   57 
   58 /* Netgraph methods. */
   59 static ng_constructor_t         ng_atmllc_constructor;
   60 static ng_shutdown_t            ng_atmllc_shutdown;
   61 static ng_rcvmsg_t              ng_atmllc_rcvmsg;
   62 static ng_newhook_t             ng_atmllc_newhook;
   63 static ng_rcvdata_t             ng_atmllc_rcvdata;
   64 static ng_disconnect_t          ng_atmllc_disconnect;
   65 
   66 static struct ng_type ng_atmllc_typestruct = {
   67         .version =      NG_ABI_VERSION, 
   68         .name =         NG_ATMLLC_NODE_TYPE,
   69         .constructor =  ng_atmllc_constructor,
   70         .rcvmsg =       ng_atmllc_rcvmsg,
   71         .shutdown =     ng_atmllc_shutdown,
   72         .newhook =      ng_atmllc_newhook,
   73         .rcvdata =      ng_atmllc_rcvdata,
   74         .disconnect =   ng_atmllc_disconnect,
   75 };
   76 NETGRAPH_INIT(atmllc, &ng_atmllc_typestruct);
   77 
   78 static int
   79 ng_atmllc_constructor(node_p node)
   80 {
   81         struct  ng_atmllc_priv *priv;
   82 
   83         MALLOC(priv, struct ng_atmllc_priv *, sizeof(*priv), M_NETGRAPH,
   84             M_NOWAIT | M_ZERO);
   85         if (priv == NULL) {
   86                 return (ENOMEM);
   87         }
   88 
   89         NG_NODE_SET_PRIVATE(node, priv);
   90 
   91         return (0);
   92 }
   93 
   94 static int
   95 ng_atmllc_rcvmsg(node_p node, item_p item, hook_p lasthook)
   96 {
   97         struct  ng_mesg *msg;
   98         int     error;
   99 
  100         error = 0;
  101         NGI_GET_MSG(item, msg);
  102         msg->header.flags |= NGF_RESP;
  103         NG_RESPOND_MSG(error, node, item, msg);
  104         return (error);
  105 }
  106 
  107 static int
  108 ng_atmllc_shutdown(node_p node)
  109 {
  110         struct  ng_atmllc_priv *priv;
  111 
  112         priv = NG_NODE_PRIVATE(node);
  113 
  114         FREE(priv, M_NETGRAPH);
  115 
  116         NG_NODE_UNREF(node);
  117 
  118         return (0);
  119 }
  120 
  121 static int
  122 ng_atmllc_newhook(node_p node, hook_p hook, const char *name)
  123 {
  124         struct  ng_atmllc_priv *priv;
  125 
  126         priv = NG_NODE_PRIVATE(node);
  127 
  128         if (strcmp(name, NG_ATMLLC_HOOK_ATM) == 0) {
  129                 if (priv->atm != NULL) {
  130                         return (EISCONN);
  131                 }
  132                 priv->atm = hook;
  133         } else if (strcmp(name, NG_ATMLLC_HOOK_ETHER) == 0) {
  134                 if (priv->ether != NULL) {
  135                         return (EISCONN);
  136                 }
  137                 priv->ether = hook;
  138         } else if (strcmp(name, NG_ATMLLC_HOOK_FDDI) == 0) {
  139                 if (priv->fddi != NULL) {
  140                         return (EISCONN);
  141                 }
  142                 priv->fddi = hook;
  143         } else {
  144                 return (EINVAL);
  145         }
  146 
  147         return (0);
  148 }
  149 
  150 static int
  151 ng_atmllc_rcvdata(hook_p hook, item_p item)
  152 {
  153         struct  ng_atmllc_priv *priv;
  154         struct  mbuf *m;
  155         struct  atmllc *hdr;
  156         hook_p  outhook;
  157         u_int   padding;
  158         int     error;
  159 
  160         priv = NG_NODE_PRIVATE(NG_HOOK_NODE(hook));
  161         m = NGI_M(item);
  162         outhook = NULL;
  163         padding = 0;
  164 
  165         if (hook == priv->atm) {
  166                 /* Ditch the psuedoheader. */
  167                 hdr = mtod(m, struct atmllc *);
  168                 /* m_adj(m, sizeof(struct atm_pseudohdr)); */
  169 
  170                 /*
  171                  * Make sure we have the LLC and ethernet headers.
  172                  * The ethernet header size is slightly larger than the FDDI
  173                  * header, which is convenient.
  174                  */
  175                 if (m->m_len < sizeof(struct atmllc) + ETHER_HDR_LEN) {
  176                         m = m_pullup(m, sizeof(struct atmllc) + ETHER_HDR_LEN);
  177                         if (m == NULL) {
  178                                 return (ENOMEM);
  179                         }
  180                 }
  181 
  182                 /* Decode the LLC header. */
  183                 hdr = mtod(m, struct atmllc *);
  184                 if (ATM_LLC_TYPE(hdr) == NG_ATMLLC_TYPE_ETHERNET_NOFCS) {
  185                         m->m_flags &= ~M_HASFCS;
  186                         outhook = priv->ether;
  187                         padding = 2;
  188                 } else if (ATM_LLC_TYPE(hdr) == NG_ATMLLC_TYPE_ETHERNET_FCS) {
  189                         m->m_flags |= M_HASFCS;
  190                         outhook = priv->ether;
  191                         padding = 2;
  192                 } else if (ATM_LLC_TYPE(hdr) == NG_ATMLLC_TYPE_FDDI_NOFCS) {
  193                         m->m_flags &= ~M_HASFCS;
  194                         outhook = priv->fddi;
  195                         padding = 3;
  196                 } else if (ATM_LLC_TYPE(hdr) == NG_ATMLLC_TYPE_FDDI_FCS) {
  197                         m->m_flags |= M_HASFCS;
  198                         outhook = priv->fddi;
  199                         padding = 3;
  200                 } else {
  201                         printf("ng_atmllc: unknown type: %x\n",
  202                             ATM_LLC_TYPE(hdr));
  203                 }
  204 
  205                 /* Remove the LLC header and any padding*/
  206                 m_adj(m, sizeof(struct atmllc) + padding);
  207         } else if (hook == priv->ether) {
  208                 /* Add the LLC header */
  209                 M_PREPEND(m, NG_ATMLLC_HEADER_LEN + 2, M_DONTWAIT);
  210                 if (m == NULL) {
  211                         printf("ng_atmllc: M_PREPEND failed\n");
  212                         NG_FREE_ITEM(item);
  213                         return (ENOMEM);
  214                 }
  215                 hdr = mtod(m, struct atmllc *);
  216                 bzero((void *)hdr, sizeof(struct atmllc) + 2);
  217                 bcopy(NG_ATMLLC_HEADER, hdr->llchdr, 6);
  218                 if ((m->m_flags & M_HASFCS) != 0) {
  219                         ATM_LLC_SETTYPE(hdr, NG_ATMLLC_TYPE_ETHERNET_FCS);
  220                 } else {
  221                         ATM_LLC_SETTYPE(hdr, NG_ATMLLC_TYPE_ETHERNET_NOFCS);
  222                 }
  223                 outhook = priv->atm;
  224         } else if (hook == priv->fddi) {
  225                 /* Add the LLC header */
  226                 M_PREPEND(m, NG_ATMLLC_HEADER_LEN + 3, M_DONTWAIT);
  227                 if (m == NULL) {
  228                         printf("ng_atmllc: M_PREPEND failed\n");
  229                         NG_FREE_ITEM(item);
  230                         return (ENOMEM);
  231                 }
  232                 hdr = mtod(m, struct atmllc *);
  233                 bzero((void *)hdr, sizeof(struct atmllc) + 3);
  234                 bcopy(NG_ATMLLC_HEADER, hdr->llchdr, 6);
  235                 if ((m->m_flags & M_HASFCS) != 0) {
  236                         ATM_LLC_SETTYPE(hdr, NG_ATMLLC_TYPE_FDDI_FCS);
  237                 } else {
  238                         ATM_LLC_SETTYPE(hdr, NG_ATMLLC_TYPE_FDDI_NOFCS);
  239                 }
  240                 outhook = priv->atm;
  241         }
  242 
  243         if (outhook == NULL) {
  244                 NG_FREE_ITEM(item);
  245                 return (0);
  246         }
  247 
  248         NG_FWD_NEW_DATA(error, item, outhook, m);
  249         return (error);
  250 }
  251 
  252 static int
  253 ng_atmllc_disconnect(hook_p hook)
  254 {
  255         node_p  node;
  256         struct  ng_atmllc_priv *priv;
  257 
  258         node = NG_HOOK_NODE(hook);
  259         priv = NG_NODE_PRIVATE(node);
  260 
  261         if (hook == priv->atm) {
  262                 priv->atm = NULL;
  263         } else if (hook == priv->ether) {
  264                 priv->ether = NULL;
  265         } else if (hook == priv->fddi) {
  266                 priv->fddi = NULL;
  267         }
  268 
  269         if (NG_NODE_NUMHOOKS(node) == 0 && NG_NODE_IS_VALID(node)) {
  270                 ng_rmnode_self(node);
  271         }
  272 
  273         return (0);
  274 }

Cache object: 9ae529bd98b247ec3646cd7adcf20250


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