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/atm/ccatm/ng_ccatm.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) 2001-2002
    3  *      Fraunhofer Institute for Open Communication Systems (FhG Fokus).
    4  *      All rights reserved.
    5  * Copyright (c) 2003-2004
    6  *      Hartmut Brandt
    7  *      All rights reserved.
    8  *
    9  * Author: Harti Brandt <harti@freebsd.org>
   10  *
   11  * Redistribution of this software and documentation and use in source and
   12  * binary forms, with or without modification, are permitted provided that
   13  * the following conditions are met:
   14  *
   15  * 1. Redistributions of source code or documentation must retain the above
   16  *    copyright notice, this list of conditions and the following disclaimer.
   17  * 2. Redistributions in binary form must reproduce the above copyright
   18  *    notice, this list of conditions and the following disclaimer in the
   19  *    documentation and/or other materials provided with the distribution.
   20  *
   21  * THIS SOFTWARE AND DOCUMENTATION IS PROVIDED BY THE AUTHOR
   22  * AND ITS CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
   23  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
   24  * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
   25  * THE AUTHOR OR ITS CONTRIBUTORS  BE LIABLE FOR ANY DIRECT, INDIRECT,
   26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   27  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
   28  * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
   29  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
   30  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
   31  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   32  *
   33  * $FreeBSD$
   34  *
   35  * ATM call control and API
   36  */
   37 
   38 #include <sys/cdefs.h>
   39 __FBSDID("$FreeBSD$");
   40 
   41 #include <sys/param.h>
   42 #include <sys/systm.h>
   43 #include <sys/kernel.h>
   44 #include <sys/malloc.h>
   45 #include <sys/mbuf.h>
   46 #include <sys/errno.h>
   47 #include <sys/socket.h>
   48 #include <sys/socketvar.h>
   49 #include <sys/sbuf.h>
   50 #include <machine/stdarg.h>
   51 
   52 #include <netgraph/ng_message.h>
   53 #include <netgraph/netgraph.h>
   54 #include <netgraph/ng_parse.h>
   55 #include <netnatm/unimsg.h>
   56 #include <netnatm/msg/unistruct.h>
   57 #include <netnatm/api/unisap.h>
   58 #include <netnatm/sig/unidef.h>
   59 #include <netgraph/atm/ngatmbase.h>
   60 #include <netgraph/atm/ng_uni.h>
   61 #include <netnatm/api/atmapi.h>
   62 #include <netgraph/atm/ng_ccatm.h>
   63 #include <netnatm/api/ccatm.h>
   64 
   65 MODULE_DEPEND(ng_ccatm, ngatmbase, 1, 1, 1);
   66 
   67 MALLOC_DEFINE(M_NG_CCATM, "ng_ccatm", "netgraph uni api node");
   68 
   69 /*
   70  * Command structure parsing
   71  */
   72 
   73 /* ESI */
   74 static const struct ng_parse_fixedarray_info ng_ccatm_esi_type_info =
   75     NGM_CCATM_ESI_INFO;
   76 static const struct ng_parse_type ng_ccatm_esi_type = {
   77         &ng_parse_fixedarray_type,
   78         &ng_ccatm_esi_type_info
   79 };
   80 
   81 /* PORT PARAMETERS */
   82 static const struct ng_parse_struct_field ng_ccatm_atm_port_type_info[] =
   83     NGM_CCATM_ATM_PORT_INFO;
   84 static const struct ng_parse_type ng_ccatm_atm_port_type = {
   85         &ng_parse_struct_type,
   86         ng_ccatm_atm_port_type_info
   87 };
   88 
   89 /* PORT structure */
   90 static const struct ng_parse_struct_field ng_ccatm_port_type_info[] =
   91     NGM_CCATM_PORT_INFO;
   92 static const struct ng_parse_type ng_ccatm_port_type = {
   93         &ng_parse_struct_type,
   94         ng_ccatm_port_type_info
   95 };
   96 
   97 /* the ADDRESS array itself */
   98 static const struct ng_parse_fixedarray_info ng_ccatm_addr_array_type_info =
   99     NGM_CCATM_ADDR_ARRAY_INFO;
  100 static const struct ng_parse_type ng_ccatm_addr_array_type = {
  101         &ng_parse_fixedarray_type,
  102         &ng_ccatm_addr_array_type_info
  103 };
  104 
  105 /* one ADDRESS */
  106 static const struct ng_parse_struct_field ng_ccatm_uni_addr_type_info[] =
  107     NGM_CCATM_UNI_ADDR_INFO;
  108 static const struct ng_parse_type ng_ccatm_uni_addr_type = {
  109         &ng_parse_struct_type,
  110         ng_ccatm_uni_addr_type_info
  111 };
  112 
  113 /* ADDRESS request */
  114 static const struct ng_parse_struct_field ng_ccatm_addr_req_type_info[] =
  115     NGM_CCATM_ADDR_REQ_INFO;
  116 static const struct ng_parse_type ng_ccatm_addr_req_type = {
  117         &ng_parse_struct_type,
  118         ng_ccatm_addr_req_type_info
  119 };
  120 
  121 /* ADDRESS var-array */
  122 static int
  123 ng_ccatm_addr_req_array_getlen(const struct ng_parse_type *type,
  124     const u_char *start, const u_char *buf)
  125 {
  126         const struct ngm_ccatm_get_addresses *p;
  127 
  128         p = (const struct ngm_ccatm_get_addresses *)
  129             (buf - offsetof(struct ngm_ccatm_get_addresses, addr));
  130         return (p->count);
  131 }
  132 static const struct ng_parse_array_info ng_ccatm_addr_req_array_type_info =
  133     NGM_CCATM_ADDR_REQ_ARRAY_INFO;
  134 static const struct ng_parse_type ng_ccatm_addr_req_array_type = {
  135         &ng_parse_array_type,
  136         &ng_ccatm_addr_req_array_type_info
  137 };
  138 
  139 /* Outer get_ADDRESSes structure */
  140 static const struct ng_parse_struct_field ng_ccatm_get_addresses_type_info[] =
  141     NGM_CCATM_GET_ADDRESSES_INFO;
  142 static const struct ng_parse_type ng_ccatm_get_addresses_type = {
  143         &ng_parse_struct_type,
  144         ng_ccatm_get_addresses_type_info
  145 };
  146 
  147 /* Port array */
  148 static int
  149 ng_ccatm_port_array_getlen(const struct ng_parse_type *type,
  150     const u_char *start, const u_char *buf)
  151 {
  152         const struct ngm_ccatm_portlist *p;
  153 
  154         p = (const struct ngm_ccatm_portlist *)
  155             (buf - offsetof(struct ngm_ccatm_portlist, ports));
  156         return (p->nports);
  157 }
  158 static const struct ng_parse_array_info ng_ccatm_port_array_type_info =
  159     NGM_CCATM_PORT_ARRAY_INFO;
  160 static const struct ng_parse_type ng_ccatm_port_array_type = {
  161         &ng_parse_array_type,
  162         &ng_ccatm_port_array_type_info
  163 };
  164 
  165 /* Portlist structure */
  166 static const struct ng_parse_struct_field ng_ccatm_portlist_type_info[] =
  167     NGM_CCATM_PORTLIST_INFO;
  168 static const struct ng_parse_type ng_ccatm_portlist_type = {
  169         &ng_parse_struct_type,
  170         ng_ccatm_portlist_type_info
  171 };
  172 
  173 /*
  174  * Command list
  175  */
  176 static const struct ng_cmdlist ng_ccatm_cmdlist[] = {
  177         {
  178           NGM_CCATM_COOKIE,
  179           NGM_CCATM_DUMP,
  180           "dump",
  181           NULL,
  182           NULL
  183         },
  184         {
  185           NGM_CCATM_COOKIE,
  186           NGM_CCATM_STOP,
  187           "stop",
  188           &ng_ccatm_port_type,
  189           NULL
  190         },
  191         {
  192           NGM_CCATM_COOKIE,
  193           NGM_CCATM_START,
  194           "start",
  195           &ng_ccatm_port_type,
  196           NULL
  197         },
  198         {
  199           NGM_CCATM_COOKIE,
  200           NGM_CCATM_GETSTATE,
  201           "getstate",
  202           &ng_ccatm_port_type,
  203           &ng_parse_uint32_type
  204         },
  205         {
  206           NGM_CCATM_COOKIE,
  207           NGM_CCATM_GET_ADDRESSES,
  208           "get_addresses",
  209           &ng_ccatm_port_type,
  210           &ng_ccatm_get_addresses_type
  211         },
  212         {
  213           NGM_CCATM_COOKIE,
  214           NGM_CCATM_CLEAR,
  215           "clear",
  216           &ng_ccatm_port_type,
  217           NULL
  218         },
  219         {
  220           NGM_CCATM_COOKIE,
  221           NGM_CCATM_ADDRESS_REGISTERED,
  222           "address_reg",
  223           &ng_ccatm_addr_req_type,
  224           NULL
  225         },
  226         {
  227           NGM_CCATM_COOKIE,
  228           NGM_CCATM_ADDRESS_UNREGISTERED,
  229           "address_unreg",
  230           &ng_ccatm_addr_req_type,
  231           NULL
  232         },
  233         {
  234           NGM_CCATM_COOKIE,
  235           NGM_CCATM_SET_PORT_PARAM,
  236           "set_port_param",
  237           &ng_ccatm_atm_port_type,
  238           NULL
  239         },
  240         {
  241           NGM_CCATM_COOKIE,
  242           NGM_CCATM_GET_PORT_PARAM,
  243           "get_port_param",
  244           &ng_ccatm_port_type,
  245           &ng_ccatm_atm_port_type,
  246         },
  247         {
  248           NGM_CCATM_COOKIE,
  249           NGM_CCATM_GET_PORTLIST,
  250           "get_portlist",
  251           NULL,
  252           &ng_ccatm_portlist_type,
  253         },
  254         {
  255           NGM_CCATM_COOKIE,
  256           NGM_CCATM_SETLOG,
  257           "setlog",
  258           &ng_parse_hint32_type,
  259           &ng_parse_hint32_type,
  260         },
  261         {
  262           NGM_CCATM_COOKIE,
  263           NGM_CCATM_RESET,
  264           "reset",
  265           NULL,
  266           NULL,
  267         },
  268         { 0 }
  269 };
  270 
  271 /*
  272  * Module data
  273  */
  274 static ng_constructor_t         ng_ccatm_constructor;
  275 static ng_rcvmsg_t              ng_ccatm_rcvmsg;
  276 static ng_shutdown_t            ng_ccatm_shutdown;
  277 static ng_newhook_t             ng_ccatm_newhook;
  278 static ng_rcvdata_t             ng_ccatm_rcvdata;
  279 static ng_disconnect_t          ng_ccatm_disconnect;
  280 static int ng_ccatm_mod_event(module_t, int, void *);
  281 
  282 static struct ng_type ng_ccatm_typestruct = {
  283         .version =      NG_ABI_VERSION,
  284         .name =         NG_CCATM_NODE_TYPE,
  285         .mod_event =    ng_ccatm_mod_event,
  286         .constructor =  ng_ccatm_constructor,   /* Node constructor */
  287         .rcvmsg =       ng_ccatm_rcvmsg,        /* Control messages */
  288         .shutdown =     ng_ccatm_shutdown,      /* Node destructor */
  289         .newhook =      ng_ccatm_newhook,       /* Arrival of new hook */
  290         .rcvdata =      ng_ccatm_rcvdata,       /* receive data */
  291         .disconnect =   ng_ccatm_disconnect,    /* disconnect a hook */
  292         .cmdlist =      ng_ccatm_cmdlist,
  293 };
  294 NETGRAPH_INIT(ccatm, &ng_ccatm_typestruct);
  295 
  296 static ng_rcvdata_t     ng_ccatm_rcvuni;
  297 static ng_rcvdata_t     ng_ccatm_rcvdump;
  298 static ng_rcvdata_t     ng_ccatm_rcvmanage;
  299 
  300 /*
  301  * Private node data.
  302  */
  303 struct ccnode {
  304         node_p  node;           /* the owning node */
  305         hook_p  dump;           /* dump hook */
  306         hook_p  manage;         /* hook to ILMI */
  307 
  308         struct ccdata *data;
  309         struct mbuf *dump_first;
  310         struct mbuf *dump_last; /* first and last mbuf when dumping */
  311 
  312         u_int   hook_cnt;       /* count user and port hooks */
  313 };
  314 
  315 /*
  316  * Private UNI hook data
  317  */
  318 struct cchook {
  319         int             is_uni; /* true if uni hook, user otherwise */
  320         struct ccnode   *node;  /* the owning node */
  321         hook_p          hook;
  322         void            *inst;  /* port or user */
  323 };
  324 
  325 static void ng_ccatm_send_user(struct ccuser *, void *, u_int, void *, size_t);
  326 static void ng_ccatm_respond_user(struct ccuser *, void *, int, u_int,
  327     void *, size_t);
  328 static void ng_ccatm_send_uni(struct ccconn *, void *, u_int, u_int,
  329     struct uni_msg *);
  330 static void ng_ccatm_send_uni_glob(struct ccport *, void *, u_int, u_int,
  331     struct uni_msg *);
  332 static void ng_ccatm_log(const char *, ...) __printflike(1, 2);
  333 
  334 static const struct cc_funcs cc_funcs = {
  335         .send_user =            ng_ccatm_send_user,
  336         .respond_user =         ng_ccatm_respond_user,
  337         .send_uni =             ng_ccatm_send_uni,
  338         .send_uni_glob =        ng_ccatm_send_uni_glob,
  339         .log =                  ng_ccatm_log,
  340 };
  341 
  342 /************************************************************
  343  *
  344  * Create a new node
  345  */
  346 static int
  347 ng_ccatm_constructor(node_p node)
  348 {
  349         struct ccnode *priv;
  350 
  351         priv = malloc(sizeof(*priv), M_NG_CCATM, M_WAITOK | M_ZERO);
  352 
  353         priv->node = node;
  354         priv->data = cc_create(&cc_funcs);
  355         if (priv->data == NULL) {
  356                 free(priv, M_NG_CCATM);
  357                 return (ENOMEM);
  358         }
  359 
  360         NG_NODE_SET_PRIVATE(node, priv);
  361 
  362         return (0);
  363 }
  364 
  365 /*
  366  * Destroy a node. The user list is empty here, because all hooks are
  367  * previously disconnected. The connection lists may not be empty, because
  368  * connections may be waiting for responses from the stack. This also means,
  369  * that no orphaned connections will be made by the port_destroy routine.
  370  */
  371 static int
  372 ng_ccatm_shutdown(node_p node)
  373 {
  374         struct ccnode *priv = NG_NODE_PRIVATE(node);
  375 
  376         cc_destroy(priv->data);
  377 
  378         free(priv, M_NG_CCATM);
  379         NG_NODE_SET_PRIVATE(node, NULL);
  380 
  381         NG_NODE_UNREF(node);
  382 
  383         return (0);
  384 }
  385 
  386 /*
  387  * Retrieve the registered addresses for one port or all ports.
  388  * Returns an error code or 0 on success.
  389  */
  390 static int
  391 ng_ccatm_get_addresses(node_p node, uint32_t portno, struct ng_mesg *msg,
  392     struct ng_mesg **resp)
  393 {
  394         struct ccnode *priv = NG_NODE_PRIVATE(node);
  395         struct uni_addr *addrs;
  396         u_int *ports;
  397         struct ngm_ccatm_get_addresses *list;
  398         u_int count, i;
  399         size_t len;
  400         int err;
  401 
  402         err = cc_get_addrs(priv->data, portno, &addrs, &ports, &count);
  403         if (err != 0)
  404                 return (err);
  405 
  406         len = sizeof(*list) + count * sizeof(list->addr[0]);
  407         NG_MKRESPONSE(*resp, msg, len, M_NOWAIT);
  408         if (*resp == NULL) {
  409                 free(addrs, M_NG_CCATM);
  410                 free(ports, M_NG_CCATM);
  411                 return (ENOMEM);
  412         }
  413         list = (struct ngm_ccatm_get_addresses *)(*resp)->data;
  414 
  415         list->count = count;
  416         for (i = 0; i < count; i++) {
  417                 list->addr[i].port = ports[i];
  418                 list->addr[i].addr = addrs[i];
  419         }
  420 
  421         free(addrs, M_NG_CCATM);
  422         free(ports, M_NG_CCATM);
  423 
  424         return (0);
  425 }
  426 
  427 /*
  428  * Dumper function. Pack the data into an mbuf chain.
  429  */
  430 static int
  431 send_dump(struct ccdata *data, void *uarg, const char *buf)
  432 {
  433         struct mbuf *m;
  434         struct ccnode *priv = uarg;
  435 
  436         if (priv->dump == NULL) {
  437                 m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
  438                 if (m == NULL)
  439                         return (ENOBUFS);
  440                 priv->dump_first = priv->dump_last = m;
  441                 m->m_pkthdr.len = 0;
  442         } else {
  443                 m = m_getcl(M_NOWAIT, MT_DATA, 0);
  444                 if (m == NULL) {
  445                         m_freem(priv->dump_first);
  446                         return (ENOBUFS);
  447                 }
  448                 priv->dump_last->m_next = m;
  449                 priv->dump_last = m;
  450         }
  451 
  452         strcpy(m->m_data, buf);
  453         priv->dump_first->m_pkthdr.len += (m->m_len = strlen(buf));
  454 
  455         return (0);
  456 }
  457 
  458 /*
  459  * Dump current status to dump hook
  460  */
  461 static int
  462 ng_ccatm_dump(node_p node)
  463 {
  464         struct ccnode *priv = NG_NODE_PRIVATE(node);
  465         struct mbuf *m;
  466         int error;
  467 
  468         priv->dump_first = priv->dump_last = NULL;
  469         error = cc_dump(priv->data, MCLBYTES, send_dump, priv);
  470         if (error != 0)
  471                 return (error);
  472 
  473         if ((m = priv->dump_first) != NULL) {
  474                 priv->dump_first = priv->dump_last = NULL;
  475                 NG_SEND_DATA_ONLY(error, priv->dump, m);
  476                 return (error);
  477         }
  478         return (0);
  479 }
  480 
  481 /*
  482  * Control message
  483  */
  484 static int
  485 ng_ccatm_rcvmsg(node_p node, item_p item, hook_p lasthook)
  486 {
  487         struct ng_mesg *resp = NULL;
  488         struct ng_mesg *msg;
  489         struct ccnode *priv = NG_NODE_PRIVATE(node);
  490         int error = 0;
  491 
  492         NGI_GET_MSG(item, msg);
  493 
  494         switch (msg->header.typecookie) {
  495           case NGM_CCATM_COOKIE:
  496                 switch (msg->header.cmd) {
  497                   case NGM_CCATM_DUMP:
  498                         if (priv->dump)
  499                                 error = ng_ccatm_dump(node);
  500                         else
  501                                 error = ENOTCONN;
  502                         break;
  503 
  504                   case NGM_CCATM_STOP:
  505                     {
  506                         struct ngm_ccatm_port *arg;
  507 
  508                         if (msg->header.arglen != sizeof(*arg)) {
  509                                 error = EINVAL;
  510                                 break;
  511                         }
  512                         arg = (struct ngm_ccatm_port *)msg->data;
  513                         error = cc_port_stop(priv->data, arg->port);
  514                         break;
  515                     }
  516 
  517                   case NGM_CCATM_START:
  518                     {
  519                         struct ngm_ccatm_port *arg;
  520 
  521                         if (msg->header.arglen != sizeof(*arg)) {
  522                                 error = EINVAL;
  523                                 break;
  524                         }
  525                         arg = (struct ngm_ccatm_port *)msg->data;
  526                         error = cc_port_start(priv->data, arg->port);
  527                         break;
  528                     }
  529 
  530                   case NGM_CCATM_GETSTATE:
  531                     {
  532                         struct ngm_ccatm_port *arg;
  533                         int state;
  534 
  535                         if (msg->header.arglen != sizeof(*arg)) {
  536                                 error = EINVAL;
  537                                 break;
  538                         }
  539                         arg = (struct ngm_ccatm_port *)msg->data;
  540                         error = cc_port_isrunning(priv->data, arg->port,
  541                             &state);
  542                         if (error == 0) {
  543                                 NG_MKRESPONSE(resp, msg, sizeof(uint32_t),
  544                                     M_NOWAIT);
  545                                 if (resp == NULL) {
  546                                         error = ENOMEM;
  547                                         break;
  548                                 }
  549                                 *(uint32_t *)resp->data = state;
  550                         }
  551                         break;
  552                     }
  553 
  554                   case NGM_CCATM_GET_ADDRESSES:
  555                    {
  556                         struct ngm_ccatm_port *arg;
  557 
  558                         if (msg->header.arglen != sizeof(*arg)) {
  559                                 error = EINVAL;
  560                                 break;
  561                         }
  562                         arg = (struct ngm_ccatm_port *)msg->data;
  563                         error = ng_ccatm_get_addresses(node, arg->port, msg,
  564                             &resp);
  565                         break;
  566                     }
  567 
  568                   case NGM_CCATM_CLEAR:
  569                     {
  570                         struct ngm_ccatm_port *arg;
  571 
  572                         if (msg->header.arglen != sizeof(*arg)) {
  573                                 error = EINVAL;
  574                                 break;
  575                         }
  576                         arg = (struct ngm_ccatm_port *)msg->data;
  577                         error = cc_port_clear(priv->data, arg->port);
  578                         break;
  579                     }
  580 
  581                   case NGM_CCATM_ADDRESS_REGISTERED:
  582                     {
  583                         struct ngm_ccatm_addr_req *arg;
  584 
  585                         if (msg->header.arglen != sizeof(*arg)) {
  586                                 error = EINVAL;
  587                                 break;
  588                         }
  589                         arg = (struct ngm_ccatm_addr_req *)msg->data;
  590                         error = cc_addr_register(priv->data, arg->port,
  591                             &arg->addr);
  592                         break;
  593                     }
  594 
  595                   case NGM_CCATM_ADDRESS_UNREGISTERED:
  596                     {
  597                         struct ngm_ccatm_addr_req *arg;
  598 
  599                         if (msg->header.arglen != sizeof(*arg)) {
  600                                 error = EINVAL;
  601                                 break;
  602                         }
  603                         arg = (struct ngm_ccatm_addr_req *)msg->data;
  604                         error = cc_addr_unregister(priv->data, arg->port,
  605                             &arg->addr);
  606                         break;
  607                     }
  608 
  609                   case NGM_CCATM_GET_PORT_PARAM:
  610                     {
  611                         struct ngm_ccatm_port *arg;
  612 
  613                         if (msg->header.arglen != sizeof(*arg)) {
  614                                 error = EINVAL;
  615                                 break;
  616                         }
  617                         arg = (struct ngm_ccatm_port *)msg->data;
  618                         NG_MKRESPONSE(resp, msg, sizeof(struct atm_port_info),
  619                             M_NOWAIT);
  620                         if (resp == NULL) {
  621                                 error = ENOMEM;
  622                                 break;
  623                         }
  624                         error = cc_port_get_param(priv->data, arg->port,
  625                             (struct atm_port_info *)resp->data);
  626                         if (error != 0) {
  627                                 free(resp, M_NETGRAPH_MSG);
  628                                 resp = NULL;
  629                         }
  630                         break;
  631                     }
  632 
  633                   case NGM_CCATM_SET_PORT_PARAM:
  634                     {
  635                         struct atm_port_info *arg;
  636 
  637                         if (msg->header.arglen != sizeof(*arg)) {
  638                                 error = EINVAL;
  639                                 break;
  640                         }
  641                         arg = (struct atm_port_info *)msg->data;
  642                         error = cc_port_set_param(priv->data, arg);
  643                         break;
  644                     }
  645 
  646                   case NGM_CCATM_GET_PORTLIST:
  647                     {
  648                         struct ngm_ccatm_portlist *arg;
  649                         u_int n, *ports;
  650 
  651                         if (msg->header.arglen != 0) {
  652                                 error = EINVAL;
  653                                 break;
  654                         }
  655                         error = cc_port_getlist(priv->data, &n, &ports);
  656                         if (error != 0)
  657                                 break;
  658 
  659                         NG_MKRESPONSE(resp, msg, sizeof(*arg) +
  660                             n * sizeof(arg->ports[0]), M_NOWAIT);
  661                         if (resp == NULL) {
  662                                 free(ports, M_NG_CCATM);
  663                                 error = ENOMEM;
  664                                 break;
  665                         }
  666                         arg = (struct ngm_ccatm_portlist *)resp->data;
  667 
  668                         arg->nports = 0;
  669                         for (arg->nports = 0; arg->nports < n; arg->nports++)
  670                                 arg->ports[arg->nports] = ports[arg->nports];
  671                         free(ports, M_NG_CCATM);
  672                         break;
  673                     }
  674 
  675                   case NGM_CCATM_SETLOG:
  676                     {
  677                         uint32_t log_level;
  678 
  679                         log_level = cc_get_log(priv->data);
  680                         if (msg->header.arglen != 0) {
  681                                 if (msg->header.arglen != sizeof(log_level)) {
  682                                         error = EINVAL;
  683                                         break;
  684                                 }
  685                                 cc_set_log(priv->data, *(uint32_t *)msg->data);
  686                         }
  687 
  688                         NG_MKRESPONSE(resp, msg, sizeof(uint32_t), M_NOWAIT);
  689                         if (resp == NULL) {
  690                                 error = ENOMEM;
  691                                 if (msg->header.arglen != 0)
  692                                         cc_set_log(priv->data, log_level);
  693                                 break;
  694                         }
  695                         *(uint32_t *)resp->data = log_level;
  696                         break;
  697                     }
  698 
  699                   case NGM_CCATM_RESET:
  700                         if (msg->header.arglen != 0) {
  701                                 error = EINVAL;
  702                                 break;
  703                         }
  704 
  705                         if (priv->hook_cnt != 0) {
  706                                 error = EBUSY;
  707                                 break;
  708                         }
  709                         cc_reset(priv->data);
  710                         break;
  711 
  712                   case NGM_CCATM_GET_EXSTAT:
  713                     {
  714                         struct atm_exstatus s;
  715                         struct atm_exstatus_ep *eps;
  716                         struct atm_exstatus_port *ports;
  717                         struct atm_exstatus_conn *conns;
  718                         struct atm_exstatus_party *parties;
  719                         size_t offs;
  720 
  721                         if (msg->header.arglen != 0) {
  722                                 error = EINVAL;
  723                                 break;
  724                         }
  725                         error = cc_get_extended_status(priv->data,
  726                             &s, &eps, &ports, &conns, &parties);
  727                         if (error != 0)
  728                                 break;
  729 
  730                         offs = sizeof(s) + s.neps * sizeof(*eps) +
  731                             s.nports * sizeof(*ports) +
  732                             s.nconns * sizeof(*conns) +
  733                             s.nparties * sizeof(*parties);
  734 
  735                         NG_MKRESPONSE(resp, msg, offs, M_NOWAIT);
  736                         if (resp == NULL) {
  737                                 error = ENOMEM;
  738                                 break;
  739                         }
  740 
  741                         memcpy(resp->data, &s, sizeof(s));
  742                         offs = sizeof(s);
  743 
  744                         memcpy(resp->data + offs, eps,
  745                             sizeof(*eps) * s.neps);
  746                         offs += sizeof(*eps) * s.neps;
  747 
  748                         memcpy(resp->data + offs, ports,
  749                             sizeof(*ports) * s.nports);
  750                         offs += sizeof(*ports) * s.nports;
  751 
  752                         memcpy(resp->data + offs, conns,
  753                             sizeof(*conns) * s.nconns);
  754                         offs += sizeof(*conns) * s.nconns;
  755 
  756                         memcpy(resp->data + offs, parties,
  757                             sizeof(*parties) * s.nparties);
  758                         offs += sizeof(*parties) * s.nparties;
  759 
  760                         free(eps, M_NG_CCATM);
  761                         free(ports, M_NG_CCATM);
  762                         free(conns, M_NG_CCATM);
  763                         free(parties, M_NG_CCATM);
  764                         break;
  765                     }
  766 
  767                   default:
  768                         error = EINVAL;
  769                         break;
  770                 }
  771                 break;
  772 
  773           default:
  774                 error = EINVAL;
  775                 break;
  776         }
  777 
  778         NG_RESPOND_MSG(error, node, item, resp);
  779         NG_FREE_MSG(msg);
  780         return (error);
  781 }
  782 
  783 /************************************************************
  784  *
  785  * New hook arrival
  786  */
  787 static int
  788 ng_ccatm_newhook(node_p node, hook_p hook, const char *name)
  789 {
  790         struct ccnode *priv = NG_NODE_PRIVATE(node);
  791         struct ccport *port;
  792         struct ccuser *user;
  793         struct cchook *hd;
  794         u_long lport;
  795         char *end;
  796 
  797         if (strncmp(name, "uni", 3) == 0) {
  798                 /*
  799                  * This is a UNI hook. Should be a new port.
  800                  */
  801                 if (name[3] == '\0')
  802                         return (EINVAL);
  803                 lport = strtoul(name + 3, &end, 10);
  804                 if (*end != '\0' || lport == 0 || lport > 0xffffffff)
  805                         return (EINVAL);
  806 
  807                 hd = malloc(sizeof(*hd), M_NG_CCATM, M_NOWAIT);
  808                 if (hd == NULL)
  809                         return (ENOMEM);
  810                 hd->is_uni = 1;
  811                 hd->node = priv;
  812                 hd->hook = hook;
  813 
  814                 port = cc_port_create(priv->data, hd, (u_int)lport);
  815                 if (port == NULL) {
  816                         free(hd, M_NG_CCATM);
  817                         return (ENOMEM);
  818                 }
  819                 hd->inst = port;
  820 
  821                 NG_HOOK_SET_PRIVATE(hook, hd);
  822                 NG_HOOK_SET_RCVDATA(hook, ng_ccatm_rcvuni);
  823                 NG_HOOK_FORCE_QUEUE(hook);
  824 
  825                 priv->hook_cnt++;
  826 
  827                 return (0);
  828         }
  829 
  830         if (strcmp(name, "dump") == 0) {
  831                 priv->dump = hook;
  832                 NG_HOOK_SET_RCVDATA(hook, ng_ccatm_rcvdump);
  833                 return (0);
  834         }
  835 
  836         if (strcmp(name, "manage") == 0) {
  837                 priv->manage = hook;
  838                 NG_HOOK_SET_RCVDATA(hook, ng_ccatm_rcvmanage);
  839                 return (0);
  840         }
  841 
  842         /*
  843          * User hook
  844          */
  845         hd = malloc(sizeof(*hd), M_NG_CCATM, M_NOWAIT);
  846         if (hd == NULL)
  847                 return (ENOMEM);
  848         hd->is_uni = 0;
  849         hd->node = priv;
  850         hd->hook = hook;
  851 
  852         user = cc_user_create(priv->data, hd, NG_HOOK_NAME(hook));
  853         if (user == NULL) {
  854                 free(hd, M_NG_CCATM);
  855                 return (ENOMEM);
  856         }
  857 
  858         hd->inst = user;
  859         NG_HOOK_SET_PRIVATE(hook, hd);
  860         NG_HOOK_FORCE_QUEUE(hook);
  861 
  862         priv->hook_cnt++;
  863 
  864         return (0);
  865 }
  866 
  867 /*
  868  * Disconnect a hook
  869  */
  870 static int
  871 ng_ccatm_disconnect(hook_p hook)
  872 {
  873         node_p node = NG_HOOK_NODE(hook);
  874         struct ccnode *priv = NG_NODE_PRIVATE(node);
  875         struct cchook *hd = NG_HOOK_PRIVATE(hook);
  876         struct ccdata *cc;
  877 
  878         if (hook == priv->dump) {
  879                 priv->dump = NULL;
  880 
  881         } else if (hook == priv->manage) {
  882                 priv->manage = NULL;
  883                 cc_unmanage(priv->data);
  884 
  885         } else {
  886                 if (hd->is_uni)
  887                         cc_port_destroy(hd->inst, 0);
  888                 else
  889                         cc_user_destroy(hd->inst);
  890 
  891                 cc = hd->node->data;
  892 
  893                 free(hd, M_NG_CCATM);
  894                 NG_HOOK_SET_PRIVATE(hook, NULL);
  895 
  896                 priv->hook_cnt--;
  897 
  898                 cc_work(cc);
  899         }
  900 
  901         /*
  902          * When the number of hooks drops to zero, delete the node.
  903          */
  904         if (NG_NODE_NUMHOOKS(node) == 0 && NG_NODE_IS_VALID(node))
  905                 ng_rmnode_self(node);
  906 
  907         return (0);
  908 }
  909 
  910 /************************************************************
  911  *
  912  * Receive data from user hook
  913  */
  914 static int
  915 ng_ccatm_rcvdata(hook_p hook, item_p item)
  916 {
  917         struct cchook *hd = NG_HOOK_PRIVATE(hook);
  918         struct uni_msg *msg;
  919         struct mbuf *m;
  920         struct ccatm_op op;
  921         int err;
  922 
  923         NGI_GET_M(item, m);
  924         NG_FREE_ITEM(item);
  925 
  926         if ((err = uni_msg_unpack_mbuf(m, &msg)) != 0) {
  927                 m_freem(m);
  928                 return (err);
  929         }
  930         m_freem(m);
  931 
  932         if (uni_msg_len(msg) < sizeof(op)) {
  933                 printf("%s: packet too short\n", __func__);
  934                 uni_msg_destroy(msg);
  935                 return (EINVAL);
  936         }
  937 
  938         bcopy(msg->b_rptr, &op, sizeof(op));
  939         msg->b_rptr += sizeof(op);
  940 
  941         err = cc_user_signal(hd->inst, op.op, msg);
  942         cc_work(hd->node->data);
  943         return (err);
  944 }
  945 
  946 /*
  947  * Pack a header and a data area into an mbuf chain
  948  */
  949 static struct mbuf *
  950 pack_buf(void *h, size_t hlen, void *t, size_t tlen)
  951 {
  952         struct mbuf *m, *m0, *last;
  953         u_char *buf = (u_char *)t;
  954         size_t n;
  955 
  956         /* header should fit into a normal mbuf */
  957         MGETHDR(m0, M_NOWAIT, MT_DATA);
  958         if (m0 == NULL)
  959                 return NULL;
  960 
  961         KASSERT(hlen <= MHLEN, ("hlen > MHLEN"));
  962 
  963         bcopy(h, m0->m_data, hlen);
  964         m0->m_len = hlen;
  965         m0->m_pkthdr.len = hlen;
  966 
  967         last = m0;
  968         while ((n = tlen) != 0) {
  969                 if (n > MLEN) {
  970                         m = m_getcl(M_NOWAIT, MT_DATA, 0);
  971                         if (n > MCLBYTES)
  972                                 n = MCLBYTES;
  973                 } else
  974                         MGET(m, M_NOWAIT, MT_DATA);
  975 
  976                 if(m == NULL)
  977                         goto drop;
  978 
  979                 last->m_next = m;
  980                 last = m;
  981 
  982                 bcopy(buf, m->m_data, n);
  983                 buf += n;
  984                 tlen -= n;
  985                 m->m_len = n;
  986                 m0->m_pkthdr.len += n;
  987         }
  988 
  989         return (m0);
  990 
  991   drop:
  992         m_freem(m0);
  993         return NULL;
  994 }
  995 
  996 /*
  997  * Send an indication to the user.
  998  */
  999 static void
 1000 ng_ccatm_send_user(struct ccuser *user, void *uarg, u_int op,
 1001     void *val, size_t len)
 1002 {
 1003         struct cchook *hd = uarg;
 1004         struct mbuf *m;
 1005         struct ccatm_op h;
 1006         int error;
 1007 
 1008         h.op = op;
 1009         m = pack_buf(&h, sizeof(h), val, len);
 1010         if (m == NULL)
 1011                 return;
 1012 
 1013         NG_SEND_DATA_ONLY(error, hd->hook, m);
 1014         if (error != 0)
 1015                 printf("%s: error=%d\n", __func__, error);
 1016 }
 1017 
 1018 /*
 1019  * Send a response to the user.
 1020  */
 1021 static void
 1022 ng_ccatm_respond_user(struct ccuser *user, void *uarg, int err, u_int data,
 1023     void *val, size_t len)
 1024 {
 1025         struct cchook *hd = uarg;
 1026         struct mbuf *m;
 1027         struct {
 1028                 struct ccatm_op op;
 1029                 struct atm_resp resp;
 1030         } resp;
 1031         int error;
 1032 
 1033         resp.op.op = ATMOP_RESP;
 1034         resp.resp.resp = err;
 1035         resp.resp.data = data;
 1036         m = pack_buf(&resp, sizeof(resp), val, len);
 1037         if (m == NULL)
 1038                 return;
 1039 
 1040         NG_SEND_DATA_ONLY(error, hd->hook, m);
 1041         if (error != 0)
 1042                 printf("%s: error=%d\n", __func__, error);
 1043 }
 1044 
 1045 /*
 1046  * Receive data from UNI.
 1047  */
 1048 static int
 1049 ng_ccatm_rcvuni(hook_p hook, item_p item)
 1050 {
 1051         struct cchook *hd = NG_HOOK_PRIVATE(hook);
 1052         struct uni_msg *msg;
 1053         struct uni_arg arg;
 1054         struct mbuf *m;
 1055         int err;
 1056 
 1057         NGI_GET_M(item, m);
 1058         NG_FREE_ITEM(item);
 1059 
 1060         if ((err = uni_msg_unpack_mbuf(m, &msg)) != 0) {
 1061                 m_freem(m);
 1062                 return (err);
 1063         }
 1064         m_freem(m);
 1065 
 1066         if (uni_msg_len(msg) < sizeof(arg)) {
 1067                 printf("%s: packet too short\n", __func__);
 1068                 uni_msg_destroy(msg);
 1069                 return (EINVAL);
 1070         }
 1071 
 1072         bcopy(msg->b_rptr, &arg, sizeof(arg));
 1073         msg->b_rptr += sizeof(arg);
 1074 
 1075         if (arg.sig == UNIAPI_ERROR) {
 1076                 if (uni_msg_len(msg) != sizeof(struct uniapi_error)) {
 1077                         printf("%s: bad UNIAPI_ERROR size %zu\n", __func__,
 1078                             uni_msg_len(msg));
 1079                         uni_msg_destroy(msg);
 1080                         return (EINVAL);
 1081                 }
 1082                 err = cc_uni_response(hd->inst, arg.cookie,
 1083                     ((struct uniapi_error *)msg->b_rptr)->reason,
 1084                     ((struct uniapi_error *)msg->b_rptr)->state);
 1085                 uni_msg_destroy(msg);
 1086         } else
 1087                 err = cc_uni_signal(hd->inst, arg.cookie, arg.sig, msg);
 1088 
 1089         cc_work(hd->node->data);
 1090         return (err);
 1091 }
 1092 
 1093 /*
 1094  * Uarg is the port's uarg.
 1095  */
 1096 static void
 1097 ng_ccatm_send_uni(struct ccconn *conn, void *uarg, u_int op, u_int cookie,
 1098     struct uni_msg *msg)
 1099 {
 1100         struct cchook *hd = uarg;
 1101         struct uni_arg arg;
 1102         struct mbuf *m;
 1103         int error;
 1104 
 1105         arg.sig = op;
 1106         arg.cookie = cookie;
 1107 
 1108         m = uni_msg_pack_mbuf(msg, &arg, sizeof(arg));
 1109         uni_msg_destroy(msg);
 1110         if (m == NULL)
 1111                 return;
 1112 
 1113         NG_SEND_DATA_ONLY(error, hd->hook, m);
 1114         if (error != 0)
 1115                 printf("%s: error=%d\n", __func__, error);
 1116 }
 1117 
 1118 /*
 1119  * Send a global message to the UNI
 1120  */
 1121 static void
 1122 ng_ccatm_send_uni_glob(struct ccport *port, void *uarg, u_int op, u_int cookie,
 1123     struct uni_msg *msg)
 1124 {
 1125         struct cchook *hd = uarg;
 1126         struct uni_arg arg;
 1127         struct mbuf *m;
 1128         int error;
 1129 
 1130         arg.sig = op;
 1131         arg.cookie = cookie;
 1132 
 1133         m = uni_msg_pack_mbuf(msg, &arg, sizeof(arg));
 1134         if (msg != NULL)
 1135                 uni_msg_destroy(msg);
 1136         if (m == NULL)
 1137                 return;
 1138 
 1139         NG_SEND_DATA_ONLY(error, hd->hook, m);
 1140         if (error != 0)
 1141                 printf("%s: error=%d\n", __func__, error);
 1142 }
 1143 /*
 1144  * Receive from ILMID
 1145  */
 1146 static int
 1147 ng_ccatm_rcvmanage(hook_p hook, item_p item)
 1148 {
 1149         NG_FREE_ITEM(item);
 1150         return (0);
 1151 }
 1152 
 1153 static int
 1154 ng_ccatm_rcvdump(hook_p hook, item_p item)
 1155 {
 1156         NG_FREE_ITEM(item);
 1157         return (0);
 1158 }
 1159 
 1160 static void
 1161 ng_ccatm_log(const char *fmt, ...)
 1162 {
 1163         va_list ap;
 1164 
 1165         va_start(ap, fmt);
 1166         vprintf(fmt, ap);
 1167         printf("\n");
 1168         va_end(ap);
 1169 }
 1170 
 1171 /*
 1172  * Loading and unloading of node type
 1173  */
 1174 static int
 1175 ng_ccatm_mod_event(module_t mod, int event, void *data)
 1176 {
 1177         int error = 0;
 1178 
 1179         switch (event) {
 1180           case MOD_LOAD:
 1181                 break;
 1182 
 1183           case MOD_UNLOAD:
 1184                 break;
 1185 
 1186           default:
 1187                 error = EOPNOTSUPP;
 1188                 break;
 1189         }
 1190         return (error);
 1191 }

Cache object: 5f7b6ba525e5bb58be6bbbc87c9ac164


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