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  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
    3  *
    4  * Copyright (c) 2003-2004 Benno Rice <benno@eloquent.com.au>
    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  *
   16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR  ``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  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/kernel.h>
   34 #include <sys/malloc.h>
   35 #include <sys/mbuf.h>
   36 #include <sys/socket.h>
   37 #include <sys/sockio.h>
   38 
   39 #include <netgraph/ng_message.h>
   40 #include <netgraph/netgraph.h>
   41 #include <netgraph/ng_atmllc.h>
   42 
   43 #include <net/if.h>
   44 #include <net/ethernet.h>       /* for M_HASFCS and ETHER_HDR_LEN */
   45 
   46 #define NG_ATMLLC_HEADER                "\252\252\3\0\200\302"
   47 #define NG_ATMLLC_HEADER_LEN            (sizeof(struct atmllc))
   48 #define NG_ATMLLC_TYPE_ETHERNET_FCS     0x0001
   49 #define NG_ATMLLC_TYPE_FDDI_FCS         0x0004
   50 #define NG_ATMLLC_TYPE_ETHERNET_NOFCS   0x0007
   51 #define NG_ATMLLC_TYPE_FDDI_NOFCS       0x000A
   52 
   53 struct ng_atmllc_priv {
   54         hook_p          atm;
   55         hook_p          ether;
   56         hook_p          fddi;
   57 };
   58 
   59 struct atmllc {
   60         uint8_t         llchdr[6];      /* aa.aa.03.00.00.00 */
   61         uint8_t         type[2];        /* "ethernet" type */
   62 };
   63 
   64 /* ATM_LLC macros: note type code in host byte order */
   65 #define ATM_LLC_TYPE(X) (((X)->type[0] << 8) | ((X)->type[1]))
   66 #define ATM_LLC_SETTYPE(X, V) do {              \
   67         (X)->type[0] = ((V) >> 8) & 0xff;       \
   68         (X)->type[1] = ((V) & 0xff);            \
   69     } while (0)
   70 
   71 /* Netgraph methods. */
   72 static ng_constructor_t         ng_atmllc_constructor;
   73 static ng_shutdown_t            ng_atmllc_shutdown;
   74 static ng_rcvmsg_t              ng_atmllc_rcvmsg;
   75 static ng_newhook_t             ng_atmllc_newhook;
   76 static ng_rcvdata_t             ng_atmllc_rcvdata;
   77 static ng_disconnect_t          ng_atmllc_disconnect;
   78 
   79 static struct ng_type ng_atmllc_typestruct = {
   80         .version =      NG_ABI_VERSION, 
   81         .name =         NG_ATMLLC_NODE_TYPE,
   82         .constructor =  ng_atmllc_constructor,
   83         .rcvmsg =       ng_atmllc_rcvmsg,
   84         .shutdown =     ng_atmllc_shutdown,
   85         .newhook =      ng_atmllc_newhook,
   86         .rcvdata =      ng_atmllc_rcvdata,
   87         .disconnect =   ng_atmllc_disconnect,
   88 };
   89 NETGRAPH_INIT(atmllc, &ng_atmllc_typestruct);
   90 
   91 static int
   92 ng_atmllc_constructor(node_p node)
   93 {
   94         struct  ng_atmllc_priv *priv;
   95 
   96         priv = malloc(sizeof(*priv), M_NETGRAPH, M_WAITOK | M_ZERO);
   97         NG_NODE_SET_PRIVATE(node, priv);
   98 
   99         return (0);
  100 }
  101 
  102 static int
  103 ng_atmllc_rcvmsg(node_p node, item_p item, hook_p lasthook)
  104 {
  105         struct  ng_mesg *msg;
  106         int     error;
  107 
  108         error = 0;
  109         NGI_GET_MSG(item, msg);
  110         msg->header.flags |= NGF_RESP;
  111         NG_RESPOND_MSG(error, node, item, msg);
  112         return (error);
  113 }
  114 
  115 static int
  116 ng_atmllc_shutdown(node_p node)
  117 {
  118         struct  ng_atmllc_priv *priv;
  119 
  120         priv = NG_NODE_PRIVATE(node);
  121 
  122         free(priv, M_NETGRAPH);
  123 
  124         NG_NODE_UNREF(node);
  125 
  126         return (0);
  127 }
  128 
  129 static int
  130 ng_atmllc_newhook(node_p node, hook_p hook, const char *name)
  131 {
  132         struct  ng_atmllc_priv *priv;
  133 
  134         priv = NG_NODE_PRIVATE(node);
  135 
  136         if (strcmp(name, NG_ATMLLC_HOOK_ATM) == 0) {
  137                 if (priv->atm != NULL) {
  138                         return (EISCONN);
  139                 }
  140                 priv->atm = hook;
  141         } else if (strcmp(name, NG_ATMLLC_HOOK_ETHER) == 0) {
  142                 if (priv->ether != NULL) {
  143                         return (EISCONN);
  144                 }
  145                 priv->ether = hook;
  146         } else if (strcmp(name, NG_ATMLLC_HOOK_FDDI) == 0) {
  147                 if (priv->fddi != NULL) {
  148                         return (EISCONN);
  149                 }
  150                 priv->fddi = hook;
  151         } else {
  152                 return (EINVAL);
  153         }
  154 
  155         return (0);
  156 }
  157 
  158 static int
  159 ng_atmllc_rcvdata(hook_p hook, item_p item)
  160 {
  161         struct  ng_atmllc_priv *priv;
  162         struct  mbuf *m;
  163         struct  atmllc *hdr;
  164         hook_p  outhook;
  165         u_int   padding;
  166         int     error;
  167 
  168         priv = NG_NODE_PRIVATE(NG_HOOK_NODE(hook));
  169         NGI_GET_M(item, m);
  170         outhook = NULL;
  171         padding = 0;
  172 
  173         if (hook == priv->atm) {
  174                 /* Ditch the pseudoheader. */
  175                 hdr = mtod(m, struct atmllc *);
  176                 /* m_adj(m, sizeof(struct atm_pseudohdr)); */
  177 
  178                 /*
  179                  * Make sure we have the LLC and ethernet headers.
  180                  * The ethernet header size is slightly larger than the FDDI
  181                  * header, which is convenient.
  182                  */
  183                 if (m->m_len < sizeof(struct atmllc) + ETHER_HDR_LEN) {
  184                         m = m_pullup(m, sizeof(struct atmllc) + ETHER_HDR_LEN);
  185                         if (m == NULL) {
  186                                 NG_FREE_ITEM(item);
  187                                 return (ENOMEM);
  188                         }
  189                 }
  190 
  191                 /* Decode the LLC header. */
  192                 hdr = mtod(m, struct atmllc *);
  193                 if (ATM_LLC_TYPE(hdr) == NG_ATMLLC_TYPE_ETHERNET_NOFCS) {
  194                         m->m_flags &= ~M_HASFCS;
  195                         outhook = priv->ether;
  196                         padding = 2;
  197                 } else if (ATM_LLC_TYPE(hdr) == NG_ATMLLC_TYPE_ETHERNET_FCS) {
  198                         m->m_flags |= M_HASFCS;
  199                         outhook = priv->ether;
  200                         padding = 2;
  201                 } else if (ATM_LLC_TYPE(hdr) == NG_ATMLLC_TYPE_FDDI_NOFCS) {
  202                         m->m_flags &= ~M_HASFCS;
  203                         outhook = priv->fddi;
  204                         padding = 3;
  205                 } else if (ATM_LLC_TYPE(hdr) == NG_ATMLLC_TYPE_FDDI_FCS) {
  206                         m->m_flags |= M_HASFCS;
  207                         outhook = priv->fddi;
  208                         padding = 3;
  209                 } else {
  210                         printf("ng_atmllc: unknown type: %x\n",
  211                             ATM_LLC_TYPE(hdr));
  212                 }
  213 
  214                 /* Remove the LLC header and any padding*/
  215                 m_adj(m, sizeof(struct atmllc) + padding);
  216         } else if (hook == priv->ether) {
  217                 /* Add the LLC header */
  218                 M_PREPEND(m, NG_ATMLLC_HEADER_LEN + 2, M_NOWAIT);
  219                 if (m == NULL) {
  220                         printf("ng_atmllc: M_PREPEND failed\n");
  221                         NG_FREE_ITEM(item);
  222                         return (ENOMEM);
  223                 }
  224                 hdr = mtod(m, struct atmllc *);
  225                 bzero((void *)hdr, sizeof(struct atmllc) + 2);
  226                 bcopy(NG_ATMLLC_HEADER, hdr->llchdr, 6);
  227                 if ((m->m_flags & M_HASFCS) != 0) {
  228                         ATM_LLC_SETTYPE(hdr, NG_ATMLLC_TYPE_ETHERNET_FCS);
  229                 } else {
  230                         ATM_LLC_SETTYPE(hdr, NG_ATMLLC_TYPE_ETHERNET_NOFCS);
  231                 }
  232                 outhook = priv->atm;
  233         } else if (hook == priv->fddi) {
  234                 /* Add the LLC header */
  235                 M_PREPEND(m, NG_ATMLLC_HEADER_LEN + 3, M_NOWAIT);
  236                 if (m == NULL) {
  237                         printf("ng_atmllc: M_PREPEND failed\n");
  238                         NG_FREE_ITEM(item);
  239                         return (ENOMEM);
  240                 }
  241                 hdr = mtod(m, struct atmllc *);
  242                 bzero((void *)hdr, sizeof(struct atmllc) + 3);
  243                 bcopy(NG_ATMLLC_HEADER, hdr->llchdr, 6);
  244                 if ((m->m_flags & M_HASFCS) != 0) {
  245                         ATM_LLC_SETTYPE(hdr, NG_ATMLLC_TYPE_FDDI_FCS);
  246                 } else {
  247                         ATM_LLC_SETTYPE(hdr, NG_ATMLLC_TYPE_FDDI_NOFCS);
  248                 }
  249                 outhook = priv->atm;
  250         }
  251 
  252         if (outhook == NULL) {
  253                 NG_FREE_M(m);
  254                 NG_FREE_ITEM(item);
  255                 return (0);
  256         }
  257 
  258         NG_FWD_NEW_DATA(error, item, outhook, m);
  259         return (error);
  260 }
  261 
  262 static int
  263 ng_atmllc_disconnect(hook_p hook)
  264 {
  265         node_p  node;
  266         struct  ng_atmllc_priv *priv;
  267 
  268         node = NG_HOOK_NODE(hook);
  269         priv = NG_NODE_PRIVATE(node);
  270 
  271         if (hook == priv->atm) {
  272                 priv->atm = NULL;
  273         } else if (hook == priv->ether) {
  274                 priv->ether = NULL;
  275         } else if (hook == priv->fddi) {
  276                 priv->fddi = NULL;
  277         }
  278 
  279         if (NG_NODE_NUMHOOKS(node) == 0 && NG_NODE_IS_VALID(node)) {
  280                 ng_rmnode_self(node);
  281         }
  282 
  283         return (0);
  284 }

Cache object: d40efb85a758952a3bb2f3773b9dbeb9


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