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/uni/ng_uni.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) 2001-2003
    5  *      Fraunhofer Institute for Open Communication Systems (FhG Fokus).
    6  *      All rights reserved.
    7  *
    8  * Author: Hartmut Brandt <harti@freebsd.org>
    9  *
   10  * Redistribution and use in source and binary forms, with or without
   11  * modification, are permitted provided that the following conditions
   12  * are met:
   13  * 1. Redistributions of source code must retain the above copyright
   14  *    notice, this list of conditions and the following disclaimer.
   15  * 2. Redistributions in binary form must reproduce the above copyright
   16  *    notice, this list of conditions and the following disclaimer in the
   17  *    documentation and/or other materials provided with the distribution.
   18  *
   19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   29  * SUCH DAMAGE.
   30  *
   31  * Netgraph module for ATM-Forum UNI 4.0 signalling
   32  */
   33 
   34 #include <sys/cdefs.h>
   35 __FBSDID("$FreeBSD$");
   36 
   37 #include <sys/param.h>
   38 #include <sys/systm.h>
   39 #include <sys/kernel.h>
   40 #include <sys/malloc.h>
   41 #include <sys/mbuf.h>
   42 #include <sys/errno.h>
   43 #include <sys/syslog.h>
   44 #include <sys/socket.h>
   45 #include <sys/socketvar.h>
   46 #include <sys/callout.h>
   47 #include <sys/sbuf.h>
   48 #include <machine/stdarg.h>
   49 
   50 #include <netgraph/ng_message.h>
   51 #include <netgraph/netgraph.h>
   52 #include <netgraph/ng_parse.h>
   53 #include <netnatm/unimsg.h>
   54 #include <netnatm/msg/unistruct.h>
   55 #include <netgraph/atm/ngatmbase.h>
   56 #include <netnatm/saal/sscopdef.h>
   57 #include <netnatm/saal/sscfudef.h>
   58 #include <netgraph/atm/uni/ng_uni_cust.h>
   59 #include <netnatm/sig/uni.h>
   60 #include <netnatm/sig/unisig.h>
   61 #include <netgraph/atm/ng_sscop.h>
   62 #include <netgraph/atm/ng_sscfu.h>
   63 #include <netgraph/atm/ng_uni.h>
   64 
   65 static MALLOC_DEFINE(M_NG_UNI, "netgraph_uni_node", "netgraph uni node");
   66 static MALLOC_DEFINE(M_UNI, "netgraph_uni_data", "uni protocol data");
   67 
   68 MODULE_DEPEND(ng_uni, ngatmbase, 1, 1, 1);
   69 
   70 /*
   71  * Private node data
   72  */
   73 struct priv {
   74         hook_p  upper;
   75         hook_p  lower;
   76         struct uni *uni;
   77         int     enabled;
   78 };
   79 
   80 /* UNI CONFIG MASK */
   81 static const struct ng_parse_struct_field ng_uni_config_mask_type_info[] =
   82         NGM_UNI_CONFIG_MASK_INFO;
   83 static const struct ng_parse_type ng_uni_config_mask_type = {
   84         &ng_parse_struct_type,
   85         ng_uni_config_mask_type_info
   86 };
   87 
   88 /* UNI_CONFIG */
   89 static const struct ng_parse_struct_field ng_uni_config_type_info[] =
   90         NGM_UNI_CONFIG_INFO;
   91 static const struct ng_parse_type ng_uni_config_type = {
   92         &ng_parse_struct_type,
   93         ng_uni_config_type_info
   94 };
   95 
   96 /* SET CONFIG */
   97 static const struct ng_parse_struct_field ng_uni_set_config_type_info[] =
   98         NGM_UNI_SET_CONFIG_INFO;
   99 static const struct ng_parse_type ng_uni_set_config_type = {
  100         &ng_parse_struct_type,
  101         ng_uni_set_config_type_info
  102 };
  103 
  104 /*
  105  * Parse DEBUG
  106  */
  107 static const struct ng_parse_fixedarray_info ng_uni_debuglevel_type_info =
  108     NGM_UNI_DEBUGLEVEL_INFO;
  109 static const struct ng_parse_type ng_uni_debuglevel_type = {
  110         &ng_parse_fixedarray_type,
  111         &ng_uni_debuglevel_type_info
  112 };
  113 static const struct ng_parse_struct_field ng_uni_debug_type_info[] =
  114     NGM_UNI_DEBUG_INFO;
  115 static const struct ng_parse_type ng_uni_debug_type = {
  116         &ng_parse_struct_type,
  117         ng_uni_debug_type_info
  118 };
  119 
  120 /*
  121  * Command list
  122  */
  123 static const struct ng_cmdlist ng_uni_cmdlist[] = {
  124         {
  125           NGM_UNI_COOKIE,
  126           NGM_UNI_GETDEBUG,
  127           "getdebug",
  128           NULL,
  129           &ng_uni_debug_type
  130         },
  131         {
  132           NGM_UNI_COOKIE,
  133           NGM_UNI_SETDEBUG,
  134           "setdebug",
  135           &ng_uni_debug_type,
  136           NULL
  137         },
  138         {
  139           NGM_UNI_COOKIE,
  140           NGM_UNI_GET_CONFIG,
  141           "get_config",
  142           NULL,
  143           &ng_uni_config_type
  144         },
  145         {
  146           NGM_UNI_COOKIE,
  147           NGM_UNI_SET_CONFIG,
  148           "set_config",
  149           &ng_uni_set_config_type,
  150           &ng_uni_config_mask_type,
  151         },
  152         {
  153           NGM_UNI_COOKIE,
  154           NGM_UNI_ENABLE,
  155           "enable",
  156           NULL,
  157           NULL,
  158         },
  159         {
  160           NGM_UNI_COOKIE,
  161           NGM_UNI_DISABLE,
  162           "disable",
  163           NULL,
  164           NULL,
  165         },
  166         {
  167           NGM_UNI_COOKIE,
  168           NGM_UNI_GETSTATE,
  169           "getstate",
  170           NULL,
  171           &ng_parse_uint32_type
  172         },
  173         { 0 }
  174 };
  175 
  176 /*
  177  * Netgraph module data
  178  */
  179 static ng_constructor_t ng_uni_constructor;
  180 static ng_shutdown_t    ng_uni_shutdown;
  181 static ng_rcvmsg_t      ng_uni_rcvmsg;
  182 static ng_newhook_t     ng_uni_newhook;
  183 static ng_disconnect_t  ng_uni_disconnect;
  184 static ng_rcvdata_t     ng_uni_rcvlower;
  185 static ng_rcvdata_t     ng_uni_rcvupper;
  186 
  187 static int ng_uni_mod_event(module_t, int, void *);
  188 
  189 static struct ng_type ng_uni_typestruct = {
  190         .version =      NG_ABI_VERSION,
  191         .name =         NG_UNI_NODE_TYPE,
  192         .mod_event =    ng_uni_mod_event,
  193         .constructor =  ng_uni_constructor,
  194         .rcvmsg =       ng_uni_rcvmsg,
  195         .shutdown =     ng_uni_shutdown,
  196         .newhook =      ng_uni_newhook,
  197         .rcvdata =      ng_uni_rcvlower,
  198         .disconnect =   ng_uni_disconnect,
  199         .cmdlist =      ng_uni_cmdlist,
  200 };
  201 NETGRAPH_INIT(uni, &ng_uni_typestruct);
  202 
  203 static void uni_uni_output(struct uni *, void *, enum uni_sig, u_int32_t,
  204     struct uni_msg *);
  205 static void uni_saal_output(struct uni *, void *, enum saal_sig,
  206     struct uni_msg *);
  207 static void uni_verbose(struct uni *, void *, u_int, const char *, ...)
  208     __printflike(4, 5);
  209 static void uni_do_status(struct uni *, void *, void *, const char *, ...)
  210     __printflike(4, 5);
  211 
  212 static const struct uni_funcs uni_funcs = {
  213         uni_uni_output,
  214         uni_saal_output,
  215         uni_verbose,
  216         uni_do_status
  217 };
  218 
  219 /************************************************************/
  220 /*
  221  * NODE MANAGEMENT
  222  */
  223 static int
  224 ng_uni_constructor(node_p node)
  225 {
  226         struct priv *priv;
  227 
  228         priv = malloc(sizeof(*priv), M_NG_UNI, M_WAITOK | M_ZERO);
  229 
  230         if ((priv->uni = uni_create(node, &uni_funcs)) == NULL) {
  231                 free(priv, M_NG_UNI);
  232                 return (ENOMEM);
  233         }
  234 
  235         NG_NODE_SET_PRIVATE(node, priv);
  236         NG_NODE_FORCE_WRITER(node);
  237 
  238         return (0);
  239 }
  240 
  241 static int
  242 ng_uni_shutdown(node_p node)
  243 {
  244         struct priv *priv = NG_NODE_PRIVATE(node);
  245 
  246         uni_destroy(priv->uni);
  247 
  248         free(priv, M_NG_UNI);
  249         NG_NODE_SET_PRIVATE(node, NULL);
  250 
  251         NG_NODE_UNREF(node);
  252 
  253         return (0);
  254 }
  255 
  256 /************************************************************/
  257 /*
  258  * CONTROL MESSAGES
  259  */
  260 static void
  261 uni_do_status(struct uni *uni, void *uarg, void *sbuf, const char *fmt, ...)
  262 {
  263         va_list ap;
  264 
  265         va_start(ap, fmt);
  266         sbuf_printf(sbuf, fmt, ap);
  267         va_end(ap);
  268 }
  269 
  270 static int
  271 text_status(node_p node, struct priv *priv, char *buf, u_int len)
  272 {
  273         struct sbuf sbuf;
  274         u_int f;
  275 
  276         sbuf_new(&sbuf, buf, len, 0);
  277 
  278         if (priv->lower != NULL)
  279                 sbuf_printf(&sbuf, "lower hook: connected to %s:%s\n",
  280                     NG_NODE_NAME(NG_HOOK_NODE(NG_HOOK_PEER(priv->lower))),
  281                     NG_HOOK_NAME(NG_HOOK_PEER(priv->lower)));
  282         else
  283                 sbuf_printf(&sbuf, "lower hook: <not connected>\n");
  284 
  285         if (priv->upper != NULL)
  286                 sbuf_printf(&sbuf, "upper hook: connected to %s:%s\n",
  287                     NG_NODE_NAME(NG_HOOK_NODE(NG_HOOK_PEER(priv->upper))),
  288                     NG_HOOK_NAME(NG_HOOK_PEER(priv->upper)));
  289         else
  290                 sbuf_printf(&sbuf, "upper hook: <not connected>\n");
  291 
  292         sbuf_printf(&sbuf, "debugging:");
  293         for (f = 0; f < UNI_MAXFACILITY; f++)
  294                 if (uni_get_debug(priv->uni, f) != 0)
  295                         sbuf_printf(&sbuf, " %s=%u", uni_facname(f),
  296                             uni_get_debug(priv->uni, f));
  297         sbuf_printf(&sbuf, "\n");
  298 
  299         if (priv->uni)
  300                 uni_status(priv->uni, &sbuf);
  301 
  302         sbuf_finish(&sbuf);
  303         return (sbuf_len(&sbuf));
  304 }
  305 
  306 static int
  307 ng_uni_rcvmsg(node_p node, item_p item, hook_p lasthook)
  308 {
  309         struct priv *priv = NG_NODE_PRIVATE(node);
  310         struct ng_mesg *resp = NULL;
  311         struct ng_mesg *msg;
  312         int error = 0;
  313         u_int i;
  314 
  315         NGI_GET_MSG(item, msg);
  316 
  317         switch (msg->header.typecookie) {
  318           case NGM_GENERIC_COOKIE:
  319                 switch (msg->header.cmd) {
  320                   case NGM_TEXT_STATUS:
  321                         NG_MKRESPONSE(resp, msg, NG_TEXTRESPONSE, M_NOWAIT);
  322                         if (resp == NULL) {
  323                                 error = ENOMEM;
  324                                 break;
  325                         }
  326 
  327                         resp->header.arglen = text_status(node, priv,
  328                             (char *)resp->data, resp->header.arglen) + 1;
  329                         break;
  330 
  331                   default:
  332                         error = EINVAL;
  333                         break;
  334                 }
  335                 break;
  336 
  337           case NGM_UNI_COOKIE:
  338                 switch (msg->header.cmd) {
  339                   case NGM_UNI_SETDEBUG:
  340                     {
  341                         struct ngm_uni_debug *arg;
  342 
  343                         if (msg->header.arglen > sizeof(*arg)) {
  344                                 error = EINVAL;
  345                                 break;
  346                         }
  347                         arg = (struct ngm_uni_debug *)msg->data;
  348                         for (i = 0; i < UNI_MAXFACILITY; i++)
  349                                 uni_set_debug(priv->uni, i, arg->level[i]);
  350                         break;
  351                     }
  352 
  353                   case NGM_UNI_GETDEBUG:
  354                     {
  355                         struct ngm_uni_debug *arg;
  356 
  357                         NG_MKRESPONSE(resp, msg, sizeof(*arg), M_NOWAIT);
  358                         if(resp == NULL) {
  359                                 error = ENOMEM;
  360                                 break;
  361                         }
  362                         arg = (struct ngm_uni_debug *)resp->data;
  363                         for (i = 0; i < UNI_MAXFACILITY; i++)
  364                                 arg->level[i] = uni_get_debug(priv->uni, i);
  365                         break;
  366                     }
  367 
  368                   case NGM_UNI_GET_CONFIG:
  369                     {
  370                         struct uni_config *config;
  371 
  372                         if (msg->header.arglen != 0) {
  373                                 error = EINVAL;
  374                                 break;
  375                         }
  376                         NG_MKRESPONSE(resp, msg, sizeof(*config), M_NOWAIT);
  377                         if (resp == NULL) {
  378                                 error = ENOMEM;
  379                                 break;
  380                         }
  381                         config = (struct uni_config *)resp->data;
  382                         uni_get_config(priv->uni, config);
  383 
  384                         break;
  385                     }
  386 
  387                   case NGM_UNI_SET_CONFIG:
  388                     {
  389                         struct ngm_uni_set_config *arg;
  390                         struct ngm_uni_config_mask *mask;
  391 
  392                         if (msg->header.arglen != sizeof(*arg)) {
  393                                 error = EINVAL;
  394                                 break;
  395                         }
  396                         arg = (struct ngm_uni_set_config *)msg->data;
  397 
  398                         NG_MKRESPONSE(resp, msg, sizeof(*mask), M_NOWAIT);
  399                         if (resp == NULL) {
  400                                 error = ENOMEM;
  401                                 break;
  402                         }
  403                         mask = (struct ngm_uni_config_mask *)resp->data;
  404 
  405                         *mask = arg->mask;
  406 
  407                         uni_set_config(priv->uni, &arg->config,
  408                             &mask->mask, &mask->popt_mask, &mask->option_mask);
  409 
  410                         break;
  411                     }
  412 
  413                   case NGM_UNI_ENABLE:
  414                         if (msg->header.arglen != 0) {
  415                                 error = EINVAL;
  416                                 break;
  417                         }
  418                         if (priv->enabled) {
  419                                 error = EISCONN;
  420                                 break;
  421                         }
  422                         priv->enabled = 1;
  423                         break;
  424 
  425                   case NGM_UNI_DISABLE:
  426                         if (msg->header.arglen != 0) {
  427                                 error = EINVAL;
  428                                 break;
  429                         }
  430                         if (!priv->enabled) {
  431                                 error = ENOTCONN;
  432                                 break;
  433                         }
  434                         priv->enabled = 0;
  435                         uni_reset(priv->uni);
  436                         break;
  437 
  438                   case NGM_UNI_GETSTATE:
  439                         if (msg->header.arglen != 0) {
  440                                 error = EINVAL;
  441                                 break;
  442                         }
  443                         NG_MKRESPONSE(resp, msg, sizeof(u_int32_t), M_NOWAIT);
  444                         if(resp == NULL) {
  445                                 error = ENOMEM;
  446                                 break;
  447                         }
  448                         *(u_int32_t *)resp->data =
  449                             priv->enabled ? (uni_getcustate(priv->uni) + 1)
  450                                           : 0;
  451                         break;
  452 
  453                   default:
  454                         error = EINVAL;
  455                         break;
  456                 }
  457                 break;
  458 
  459           default:
  460                 error = EINVAL;
  461                 break;
  462         }
  463 
  464         NG_RESPOND_MSG(error, node, item, resp);
  465         NG_FREE_MSG(msg);
  466         return (error);
  467 }
  468 
  469 /************************************************************/
  470 /*
  471  * HOOK MANAGEMENT
  472  */
  473 static int
  474 ng_uni_newhook(node_p node, hook_p hook, const char *name)
  475 {
  476         struct priv *priv = NG_NODE_PRIVATE(node);
  477 
  478         if (strcmp(name, "lower") == 0) {
  479                 priv->lower = hook;
  480         } else if(strcmp(name, "upper") == 0) {
  481                 priv->upper = hook;
  482                 NG_HOOK_SET_RCVDATA(hook, ng_uni_rcvupper);
  483         } else
  484                 return EINVAL;
  485 
  486         return 0;
  487 }
  488 
  489 static int
  490 ng_uni_disconnect(hook_p hook)
  491 {
  492         node_p node = NG_HOOK_NODE(hook);
  493         struct priv *priv = NG_NODE_PRIVATE(node);
  494 
  495         if(hook == priv->lower)
  496                 priv->lower = NULL;
  497         else if(hook == priv->upper)
  498                 priv->upper = NULL;
  499         else
  500                 printf("%s: bogus hook %s\n", __func__, NG_HOOK_NAME(hook));
  501 
  502         if (NG_NODE_NUMHOOKS(node) == 0) {
  503                 if (NG_NODE_IS_VALID(node))
  504                         ng_rmnode_self(node);
  505         }
  506 
  507         return (0);
  508 }
  509 
  510 /************************************************************/
  511 /*
  512  * DATA
  513  */
  514 /*
  515  * Receive signal from USER.
  516  *
  517  * Repackage the data into one large buffer.
  518  */
  519 static int
  520 ng_uni_rcvupper(hook_p hook, item_p item)
  521 {
  522         node_p node = NG_HOOK_NODE(hook);
  523         struct priv *priv = NG_NODE_PRIVATE(node);
  524         struct mbuf *m;
  525         struct uni_arg arg;
  526         struct uni_msg *msg;
  527         int error;
  528 
  529         if (!priv->enabled) {
  530                 NG_FREE_ITEM(item);
  531                 return (ENOTCONN);
  532         }
  533 
  534         NGI_GET_M(item, m);
  535         NG_FREE_ITEM(item);
  536 
  537         if ((error = uni_msg_unpack_mbuf(m, &msg)) != 0) {
  538                 m_freem(m);
  539                 return (error);
  540         }
  541         m_freem(m);
  542 
  543         if (uni_msg_len(msg) < sizeof(arg)) {
  544                 printf("%s: packet too short\n", __func__);
  545                 uni_msg_destroy(msg);
  546                 return (EINVAL);
  547         }
  548 
  549         bcopy(msg->b_rptr, &arg, sizeof(arg));
  550         msg->b_rptr += sizeof(arg);
  551 
  552         if (arg.sig >= UNIAPI_MAXSIG) {
  553                 printf("%s: bogus signal\n", __func__);
  554                 uni_msg_destroy(msg);
  555                 return (EINVAL);
  556         }
  557         uni_uni_input(priv->uni, arg.sig, arg.cookie, msg);
  558         uni_work(priv->uni);
  559 
  560         return (0);
  561 }
  562 
  563 /*
  564  * Upper layer signal from UNI
  565  */
  566 static void
  567 uni_uni_output(struct uni *uni, void *varg, enum uni_sig sig, u_int32_t cookie,
  568     struct uni_msg *msg)
  569 {
  570         node_p node = (node_p)varg;
  571         struct priv *priv = NG_NODE_PRIVATE(node);
  572         struct mbuf *m;
  573         struct uni_arg arg;
  574         int error;
  575 
  576         if (priv->upper == NULL) {
  577                 if (msg != NULL)
  578                         uni_msg_destroy(msg);
  579                 return;
  580         }
  581         arg.sig = sig;
  582         arg.cookie = cookie;
  583 
  584         m = uni_msg_pack_mbuf(msg, &arg, sizeof(arg));
  585         if (msg != NULL)
  586                 uni_msg_destroy(msg);
  587         if (m == NULL)
  588                 return;
  589 
  590         NG_SEND_DATA_ONLY(error, priv->upper, m);
  591 }
  592 
  593 static void
  594 dump_uni_msg(struct uni_msg *msg)
  595 {
  596         u_int pos;
  597 
  598         for (pos = 0; pos < uni_msg_len(msg); pos++) {
  599                 if (pos % 16 == 0)
  600                         printf("%06o ", pos);
  601                 if (pos % 16 == 8)
  602                         printf("  ");
  603                 printf(" %02x", msg->b_rptr[pos]);
  604                 if (pos % 16 == 15)
  605                         printf("\n");
  606         }
  607         if (pos % 16 != 0)
  608                 printf("\n");
  609 }
  610 
  611 /*
  612  * Dump a SAAL signal in either direction
  613  */
  614 static void
  615 dump_saal_signal(node_p node, enum saal_sig sig, struct uni_msg *msg, int to)
  616 {
  617         struct priv *priv = NG_NODE_PRIVATE(node);
  618 
  619         printf("signal %s SAAL: ", to ? "to" : "from");
  620 
  621         switch (sig) {
  622 #define D(S) case S: printf("%s", #S); break
  623 
  624         D(SAAL_ESTABLISH_request);
  625         D(SAAL_ESTABLISH_indication);
  626         D(SAAL_ESTABLISH_confirm);
  627         D(SAAL_RELEASE_request);
  628         D(SAAL_RELEASE_confirm);
  629         D(SAAL_RELEASE_indication);
  630         D(SAAL_DATA_request);
  631         D(SAAL_DATA_indication);
  632         D(SAAL_UDATA_request);
  633         D(SAAL_UDATA_indication);
  634 
  635 #undef D
  636           default:
  637                 printf("sig=%d", sig); break;
  638         }
  639         if (msg != NULL) {
  640                 printf(" data=%zu\n", uni_msg_len(msg));
  641                 if (uni_get_debug(priv->uni, UNI_FAC_SAAL) > 1)
  642                         dump_uni_msg(msg);
  643         } else
  644                 printf("\n");
  645 }
  646 
  647 /*
  648  * Receive signal from SSCOP.
  649  *
  650  * If this is a data signal, repackage the data into one large buffer.
  651  * UNI shouldn't be the bottleneck in a system and this greatly simplifies
  652  * parsing in UNI.
  653  */
  654 static int
  655 ng_uni_rcvlower(hook_p hook __unused, item_p item)
  656 {
  657         node_p node = NG_HOOK_NODE(hook);
  658         struct priv *priv = NG_NODE_PRIVATE(node);
  659         struct mbuf *m;
  660         struct sscfu_arg arg;
  661         struct uni_msg *msg;
  662         int error;
  663 
  664         if (!priv->enabled) {
  665                 NG_FREE_ITEM(item);
  666                 return (ENOTCONN);
  667         }
  668 
  669         NGI_GET_M(item, m);
  670         NG_FREE_ITEM(item);
  671 
  672         if ((error = uni_msg_unpack_mbuf(m, &msg)) != 0) {
  673                 m_freem(m);
  674                 return (error);
  675         }
  676         m_freem(m);
  677 
  678         if (uni_msg_len(msg) < sizeof(arg)) {
  679                 uni_msg_destroy(msg);
  680                 printf("%s: packet too short\n", __func__);
  681                 return (EINVAL);
  682         }
  683         bcopy(msg->b_rptr, &arg, sizeof(arg));
  684         msg->b_rptr += sizeof(arg);
  685 
  686         if (arg.sig > SAAL_UDATA_indication) {
  687                 uni_msg_destroy(msg);
  688                 printf("%s: bogus signal\n", __func__);
  689                 return (EINVAL);
  690         }
  691 
  692         if (uni_get_debug(priv->uni, UNI_FAC_SAAL) > 0)
  693                 dump_saal_signal(node, arg.sig, msg, 0);
  694 
  695         uni_saal_input(priv->uni, arg.sig, msg);
  696         uni_work(priv->uni);
  697 
  698         return (0);
  699 }
  700 
  701 /*
  702  * Send signal to sscop.
  703  * Pack the message into an mbuf chain.
  704  */
  705 static void
  706 uni_saal_output(struct uni *uni, void *varg, enum saal_sig sig, struct uni_msg *msg)
  707 {
  708         node_p node = (node_p)varg;
  709         struct priv *priv = NG_NODE_PRIVATE(node);
  710         struct mbuf *m;
  711         struct sscfu_arg arg;
  712         int error;
  713 
  714         if (uni_get_debug(priv->uni, UNI_FAC_SAAL) > 0)
  715                 dump_saal_signal(node, sig, msg, 1);
  716 
  717         if (priv->lower == NULL) {
  718                 if (msg != NULL)
  719                         uni_msg_destroy(msg);
  720                 return;
  721         }
  722 
  723         arg.sig = sig;
  724 
  725         m = uni_msg_pack_mbuf(msg, &arg, sizeof(arg));
  726         if (msg != NULL)
  727                 uni_msg_destroy(msg);
  728         if (m == NULL)
  729                 return;
  730 
  731         NG_SEND_DATA_ONLY(error, priv->lower, m);
  732 }
  733 
  734 static void
  735 uni_verbose(struct uni *uni, void *varg, u_int fac, const char *fmt, ...)
  736 {
  737         va_list ap;
  738 
  739         static char *facnames[] = {
  740 #define UNI_DEBUG_DEFINE(D) [UNI_FAC_##D] = #D,
  741                 UNI_DEBUG_FACILITIES
  742 #undef UNI_DEBUG_DEFINE
  743         };
  744 
  745         printf("%s: ", facnames[fac]);
  746 
  747         va_start(ap, fmt);
  748         vprintf(fmt, ap);
  749         va_end(ap);
  750 
  751         printf("\n");
  752 }
  753 
  754 /************************************************************/
  755 /*
  756  * Memory debugging
  757  */
  758 struct unimem_debug {
  759         const char      *file;
  760         u_int           lno;
  761         LIST_ENTRY(unimem_debug) link;
  762         char            data[0];
  763 };
  764 LIST_HEAD(unimem_debug_list, unimem_debug);
  765 
  766 static struct unimem_debug_list nguni_freemem[UNIMEM_TYPES] = {
  767     LIST_HEAD_INITIALIZER(nguni_freemem[0]),
  768     LIST_HEAD_INITIALIZER(nguni_freemem[1]),
  769     LIST_HEAD_INITIALIZER(nguni_freemem[2]),
  770     LIST_HEAD_INITIALIZER(nguni_freemem[3]),
  771     LIST_HEAD_INITIALIZER(nguni_freemem[4]),
  772 };
  773 static struct unimem_debug_list nguni_usedmem[UNIMEM_TYPES] = {
  774     LIST_HEAD_INITIALIZER(nguni_usedmem[0]),
  775     LIST_HEAD_INITIALIZER(nguni_usedmem[1]),
  776     LIST_HEAD_INITIALIZER(nguni_usedmem[2]),
  777     LIST_HEAD_INITIALIZER(nguni_usedmem[3]),
  778     LIST_HEAD_INITIALIZER(nguni_usedmem[4]),
  779 };
  780 
  781 static struct mtx nguni_unilist_mtx;
  782 
  783 static const char *unimem_names[UNIMEM_TYPES] = {
  784         "instance",
  785         "all",
  786         "signal",
  787         "call",
  788         "party"
  789 };
  790 
  791 static void
  792 uni_init(void)
  793 {
  794         mtx_init(&nguni_unilist_mtx, "netgraph UNI structure lists", NULL,
  795             MTX_DEF);
  796 }
  797 
  798 static void
  799 uni_fini(void)
  800 {
  801         u_int type;
  802         struct unimem_debug *h;
  803 
  804         for (type = 0; type < UNIMEM_TYPES; type++) {
  805                 while ((h = LIST_FIRST(&nguni_freemem[type])) != NULL) {
  806                         LIST_REMOVE(h, link);
  807                         free(h, M_UNI);
  808                 }
  809 
  810                 while ((h = LIST_FIRST(&nguni_usedmem[type])) != NULL) {
  811                         LIST_REMOVE(h, link);
  812                         printf("ng_uni: %s in use: %p (%s,%u)\n",
  813                             unimem_names[type], (caddr_t)h->data,
  814                             h->file, h->lno);
  815                         free(h, M_UNI);
  816                 }
  817         }
  818 
  819         mtx_destroy(&nguni_unilist_mtx);
  820 }
  821 
  822 /*
  823  * Allocate a chunk of memory from a given type.
  824  */
  825 void *
  826 ng_uni_malloc(enum unimem type, const char *file, u_int lno)
  827 {
  828         struct unimem_debug *d;
  829         size_t full;
  830 
  831         /*
  832          * Try to allocate
  833          */
  834         mtx_lock(&nguni_unilist_mtx);
  835         if ((d = LIST_FIRST(&nguni_freemem[type])) != NULL)
  836                 LIST_REMOVE(d, link);
  837         mtx_unlock(&nguni_unilist_mtx);
  838 
  839         if (d == NULL) {
  840                 /*
  841                  * allocate
  842                  */
  843                 full = unimem_sizes[type] + offsetof(struct unimem_debug, data);
  844                 if ((d = malloc(full, M_UNI, M_NOWAIT | M_ZERO)) == NULL)
  845                         return (NULL);
  846         } else {
  847                 bzero(d->data, unimem_sizes[type]);
  848         }
  849         d->file = file;
  850         d->lno = lno;
  851 
  852         mtx_lock(&nguni_unilist_mtx);
  853         LIST_INSERT_HEAD(&nguni_usedmem[type], d, link);
  854         mtx_unlock(&nguni_unilist_mtx);
  855         return (d->data);
  856 }
  857 
  858 void
  859 ng_uni_free(enum unimem type, void *ptr, const char *file, u_int lno)
  860 {
  861         struct unimem_debug *d, *h;
  862 
  863         d = (struct unimem_debug *)
  864             ((char *)ptr - offsetof(struct unimem_debug, data));
  865 
  866         mtx_lock(&nguni_unilist_mtx);
  867 
  868         LIST_FOREACH(h, &nguni_usedmem[type], link)
  869                 if (d == h)
  870                         break;
  871 
  872         if (h != NULL) {
  873                 LIST_REMOVE(d, link);
  874                 LIST_INSERT_HEAD(&nguni_freemem[type], d, link);
  875         } else {
  876                 /*
  877                  * Not on used list - try free list.
  878                  */
  879                 LIST_FOREACH(h, &nguni_freemem[type], link)
  880                         if (d == h)
  881                                 break;
  882                 if (h == NULL)
  883                         printf("ng_uni: %s,%u: %p(%s) was never allocated\n",
  884                             file, lno, ptr, unimem_names[type]);
  885                 else
  886                         printf("ng_uni: %s,%u: %p(%s) was already destroyed "
  887                             "in %s,%u\n",
  888                             file, lno, ptr, unimem_names[type],
  889                             h->file, h->lno);
  890         }
  891         mtx_unlock(&nguni_unilist_mtx);
  892 }
  893 /************************************************************/
  894 /*
  895  * INITIALISATION
  896  */
  897 
  898 /*
  899  * Loading and unloading of node type
  900  */
  901 static int
  902 ng_uni_mod_event(module_t mod, int event, void *data)
  903 {
  904         int error = 0;
  905 
  906         switch(event) {
  907           case MOD_LOAD:
  908                 uni_init();
  909                 break;
  910 
  911           case MOD_UNLOAD:
  912                 uni_fini();
  913                 break;
  914 
  915           default:
  916                 error = EOPNOTSUPP;
  917                 break;
  918         }
  919         return (error);
  920 }

Cache object: 74a738d60d9035c1a5adc0c3d12716c8


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