1139823Simp/*- 2122219Sharti * Copyright (c) 2001-2003 3122219Sharti * Fraunhofer Institute for Open Communication Systems (FhG Fokus). 4122219Sharti * All rights reserved. 5122219Sharti * 6122219Sharti * Author: Hartmut Brandt <harti@freebsd.org> 7122219Sharti * 8122219Sharti * Redistribution and use in source and binary forms, with or without 9122219Sharti * modification, are permitted provided that the following conditions 10122219Sharti * are met: 11122219Sharti * 1. Redistributions of source code must retain the above copyright 12122219Sharti * notice, this list of conditions and the following disclaimer. 13122219Sharti * 2. Redistributions in binary form must reproduce the above copyright 14122219Sharti * notice, this list of conditions and the following disclaimer in the 15122219Sharti * documentation and/or other materials provided with the distribution. 16122219Sharti * 17122219Sharti * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18122219Sharti * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19122219Sharti * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20122219Sharti * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21122219Sharti * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22122219Sharti * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23122219Sharti * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24122219Sharti * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25122219Sharti * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26122219Sharti * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27122219Sharti * SUCH DAMAGE. 28122219Sharti * 29122219Sharti * Netgraph module for ATM-Forum UNI 4.0 signalling 30122219Sharti */ 31122219Sharti 32122219Sharti#include <sys/cdefs.h> 33122219Sharti__FBSDID("$FreeBSD$"); 34122219Sharti 35122219Sharti#include <sys/param.h> 36122219Sharti#include <sys/systm.h> 37122219Sharti#include <sys/kernel.h> 38122219Sharti#include <sys/malloc.h> 39122219Sharti#include <sys/mbuf.h> 40122219Sharti#include <sys/errno.h> 41122219Sharti#include <sys/syslog.h> 42122219Sharti#include <sys/socket.h> 43122219Sharti#include <sys/socketvar.h> 44122219Sharti#include <sys/callout.h> 45122219Sharti#include <sys/sbuf.h> 46122219Sharti#include <machine/stdarg.h> 47122219Sharti 48122219Sharti#include <netgraph/ng_message.h> 49122219Sharti#include <netgraph/netgraph.h> 50122219Sharti#include <netgraph/ng_parse.h> 51122219Sharti#include <netnatm/unimsg.h> 52122219Sharti#include <netnatm/msg/unistruct.h> 53122219Sharti#include <netgraph/atm/ngatmbase.h> 54122219Sharti#include <netnatm/saal/sscopdef.h> 55122219Sharti#include <netnatm/saal/sscfudef.h> 56122219Sharti#include <netgraph/atm/uni/ng_uni_cust.h> 57122219Sharti#include <netnatm/sig/uni.h> 58122219Sharti#include <netnatm/sig/unisig.h> 59122219Sharti#include <netgraph/atm/ng_sscop.h> 60122219Sharti#include <netgraph/atm/ng_sscfu.h> 61122219Sharti#include <netgraph/atm/ng_uni.h> 62122219Sharti 63227293Sedstatic MALLOC_DEFINE(M_NG_UNI, "netgraph_uni_node", "netgraph uni node"); 64227293Sedstatic MALLOC_DEFINE(M_UNI, "netgraph_uni_data", "uni protocol data"); 65122219Sharti 66122219ShartiMODULE_DEPEND(ng_uni, ngatmbase, 1, 1, 1); 67122219Sharti 68122219Sharti/* 69122219Sharti * Private node data 70122219Sharti */ 71122219Shartistruct priv { 72122219Sharti hook_p upper; 73122219Sharti hook_p lower; 74122219Sharti struct uni *uni; 75122219Sharti int enabled; 76122219Sharti}; 77122219Sharti 78122219Sharti/* UNI CONFIG MASK */ 79122219Shartistatic const struct ng_parse_struct_field ng_uni_config_mask_type_info[] = 80122219Sharti NGM_UNI_CONFIG_MASK_INFO; 81122219Shartistatic const struct ng_parse_type ng_uni_config_mask_type = { 82122219Sharti &ng_parse_struct_type, 83122219Sharti ng_uni_config_mask_type_info 84122219Sharti}; 85122219Sharti 86122219Sharti/* UNI_CONFIG */ 87122219Shartistatic const struct ng_parse_struct_field ng_uni_config_type_info[] = 88122219Sharti NGM_UNI_CONFIG_INFO; 89122219Shartistatic const struct ng_parse_type ng_uni_config_type = { 90122219Sharti &ng_parse_struct_type, 91122219Sharti ng_uni_config_type_info 92122219Sharti}; 93122219Sharti 94122219Sharti/* SET CONFIG */ 95122219Shartistatic const struct ng_parse_struct_field ng_uni_set_config_type_info[] = 96122219Sharti NGM_UNI_SET_CONFIG_INFO; 97122219Shartistatic const struct ng_parse_type ng_uni_set_config_type = { 98122219Sharti &ng_parse_struct_type, 99122219Sharti ng_uni_set_config_type_info 100122219Sharti}; 101122219Sharti 102122219Sharti/* 103122219Sharti * Parse DEBUG 104122219Sharti */ 105122219Shartistatic const struct ng_parse_fixedarray_info ng_uni_debuglevel_type_info = 106122219Sharti NGM_UNI_DEBUGLEVEL_INFO; 107122219Shartistatic const struct ng_parse_type ng_uni_debuglevel_type = { 108122219Sharti &ng_parse_fixedarray_type, 109122219Sharti &ng_uni_debuglevel_type_info 110122219Sharti}; 111122219Shartistatic const struct ng_parse_struct_field ng_uni_debug_type_info[] = 112122219Sharti NGM_UNI_DEBUG_INFO; 113122219Shartistatic const struct ng_parse_type ng_uni_debug_type = { 114122219Sharti &ng_parse_struct_type, 115122219Sharti ng_uni_debug_type_info 116122219Sharti}; 117122219Sharti 118122219Sharti/* 119122219Sharti * Command list 120122219Sharti */ 121122219Shartistatic const struct ng_cmdlist ng_uni_cmdlist[] = { 122122219Sharti { 123122219Sharti NGM_UNI_COOKIE, 124122219Sharti NGM_UNI_GETDEBUG, 125122219Sharti "getdebug", 126122219Sharti NULL, 127122219Sharti &ng_uni_debug_type 128122219Sharti }, 129122219Sharti { 130122219Sharti NGM_UNI_COOKIE, 131122219Sharti NGM_UNI_SETDEBUG, 132122219Sharti "setdebug", 133122219Sharti &ng_uni_debug_type, 134122219Sharti NULL 135122219Sharti }, 136122219Sharti { 137122219Sharti NGM_UNI_COOKIE, 138122219Sharti NGM_UNI_GET_CONFIG, 139122219Sharti "get_config", 140122219Sharti NULL, 141122219Sharti &ng_uni_config_type 142122219Sharti }, 143122219Sharti { 144122219Sharti NGM_UNI_COOKIE, 145122219Sharti NGM_UNI_SET_CONFIG, 146122219Sharti "set_config", 147122219Sharti &ng_uni_set_config_type, 148122219Sharti &ng_uni_config_mask_type, 149122219Sharti }, 150122219Sharti { 151122219Sharti NGM_UNI_COOKIE, 152122219Sharti NGM_UNI_ENABLE, 153122219Sharti "enable", 154122219Sharti NULL, 155122219Sharti NULL, 156122219Sharti }, 157122219Sharti { 158122219Sharti NGM_UNI_COOKIE, 159122219Sharti NGM_UNI_DISABLE, 160122219Sharti "disable", 161122219Sharti NULL, 162122219Sharti NULL, 163122219Sharti }, 164122219Sharti { 165122219Sharti NGM_UNI_COOKIE, 166122219Sharti NGM_UNI_GETSTATE, 167122219Sharti "getstate", 168122219Sharti NULL, 169122219Sharti &ng_parse_uint32_type 170122219Sharti }, 171122219Sharti { 0 } 172122219Sharti}; 173122219Sharti 174122219Sharti/* 175122219Sharti * Netgraph module data 176122219Sharti */ 177122219Shartistatic ng_constructor_t ng_uni_constructor; 178122219Shartistatic ng_shutdown_t ng_uni_shutdown; 179122219Shartistatic ng_rcvmsg_t ng_uni_rcvmsg; 180122219Shartistatic ng_newhook_t ng_uni_newhook; 181122219Shartistatic ng_disconnect_t ng_uni_disconnect; 182122219Shartistatic ng_rcvdata_t ng_uni_rcvlower; 183122219Shartistatic ng_rcvdata_t ng_uni_rcvupper; 184122219Sharti 185122219Shartistatic int ng_uni_mod_event(module_t, int, void *); 186122219Sharti 187122219Shartistatic struct ng_type ng_uni_typestruct = { 188129823Sjulian .version = NG_ABI_VERSION, 189129823Sjulian .name = NG_UNI_NODE_TYPE, 190129823Sjulian .mod_event = ng_uni_mod_event, 191129823Sjulian .constructor = ng_uni_constructor, 192129823Sjulian .rcvmsg = ng_uni_rcvmsg, 193129823Sjulian .shutdown = ng_uni_shutdown, 194129823Sjulian .newhook = ng_uni_newhook, 195129823Sjulian .rcvdata = ng_uni_rcvlower, 196129823Sjulian .disconnect = ng_uni_disconnect, 197129823Sjulian .cmdlist = ng_uni_cmdlist, 198122219Sharti}; 199122219ShartiNETGRAPH_INIT(uni, &ng_uni_typestruct); 200122219Sharti 201122219Shartistatic void uni_uni_output(struct uni *, void *, enum uni_sig, u_int32_t, 202122219Sharti struct uni_msg *); 203122219Shartistatic void uni_saal_output(struct uni *, void *, enum saal_sig, 204122219Sharti struct uni_msg *); 205122219Shartistatic void uni_verbose(struct uni *, void *, u_int, const char *, ...) 206122219Sharti __printflike(4, 5); 207122219Shartistatic void uni_do_status(struct uni *, void *, void *, const char *, ...) 208122219Sharti __printflike(4, 5); 209122219Sharti 210122219Shartistatic const struct uni_funcs uni_funcs = { 211122219Sharti uni_uni_output, 212122219Sharti uni_saal_output, 213122219Sharti uni_verbose, 214122219Sharti uni_do_status 215122219Sharti}; 216122219Sharti 217122219Sharti/************************************************************/ 218122219Sharti/* 219122219Sharti * NODE MANAGEMENT 220122219Sharti */ 221122219Shartistatic int 222122219Sharting_uni_constructor(node_p node) 223122219Sharti{ 224122219Sharti struct priv *priv; 225122219Sharti 226220768Sglebius priv = malloc(sizeof(*priv), M_NG_UNI, M_WAITOK | M_ZERO); 227122219Sharti 228122219Sharti if ((priv->uni = uni_create(node, &uni_funcs)) == NULL) { 229122219Sharti free(priv, M_NG_UNI); 230122219Sharti return (ENOMEM); 231122219Sharti } 232122219Sharti 233122219Sharti NG_NODE_SET_PRIVATE(node, priv); 234122219Sharti NG_NODE_FORCE_WRITER(node); 235122219Sharti 236122219Sharti return (0); 237122219Sharti} 238122219Sharti 239122219Shartistatic int 240122219Sharting_uni_shutdown(node_p node) 241122219Sharti{ 242122219Sharti struct priv *priv = NG_NODE_PRIVATE(node); 243122219Sharti 244122219Sharti uni_destroy(priv->uni); 245122219Sharti 246122219Sharti free(priv, M_NG_UNI); 247122219Sharti NG_NODE_SET_PRIVATE(node, NULL); 248122219Sharti 249122219Sharti NG_NODE_UNREF(node); 250122219Sharti 251122219Sharti return (0); 252122219Sharti} 253122219Sharti 254122219Sharti/************************************************************/ 255122219Sharti/* 256122219Sharti * CONTROL MESSAGES 257122219Sharti */ 258122219Shartistatic void 259122219Shartiuni_do_status(struct uni *uni, void *uarg, void *sbuf, const char *fmt, ...) 260122219Sharti{ 261122219Sharti va_list ap; 262122219Sharti 263122219Sharti va_start(ap, fmt); 264122219Sharti sbuf_printf(sbuf, fmt, ap); 265122219Sharti va_end(ap); 266122219Sharti} 267122219Sharti 268122219Shartistatic int 269122219Shartitext_status(node_p node, struct priv *priv, char *buf, u_int len) 270122219Sharti{ 271122219Sharti struct sbuf sbuf; 272122219Sharti u_int f; 273122219Sharti 274122219Sharti sbuf_new(&sbuf, buf, len, 0); 275122219Sharti 276122219Sharti if (priv->lower != NULL) 277122219Sharti sbuf_printf(&sbuf, "lower hook: connected to %s:%s\n", 278122219Sharti NG_NODE_NAME(NG_HOOK_NODE(NG_HOOK_PEER(priv->lower))), 279122219Sharti NG_HOOK_NAME(NG_HOOK_PEER(priv->lower))); 280122219Sharti else 281122219Sharti sbuf_printf(&sbuf, "lower hook: <not connected>\n"); 282122219Sharti 283122219Sharti if (priv->upper != NULL) 284122219Sharti sbuf_printf(&sbuf, "upper hook: connected to %s:%s\n", 285122219Sharti NG_NODE_NAME(NG_HOOK_NODE(NG_HOOK_PEER(priv->upper))), 286122219Sharti NG_HOOK_NAME(NG_HOOK_PEER(priv->upper))); 287122219Sharti else 288122219Sharti sbuf_printf(&sbuf, "upper hook: <not connected>\n"); 289122219Sharti 290122219Sharti sbuf_printf(&sbuf, "debugging:"); 291122219Sharti for (f = 0; f < UNI_MAXFACILITY; f++) 292122219Sharti if (uni_get_debug(priv->uni, f) != 0) 293122219Sharti sbuf_printf(&sbuf, " %s=%u", uni_facname(f), 294122219Sharti uni_get_debug(priv->uni, f)); 295122219Sharti sbuf_printf(&sbuf, "\n"); 296122219Sharti 297122219Sharti if (priv->uni) 298122219Sharti uni_status(priv->uni, &sbuf); 299122219Sharti 300122219Sharti sbuf_finish(&sbuf); 301122219Sharti return (sbuf_len(&sbuf)); 302122219Sharti} 303122219Sharti 304122219Shartistatic int 305122219Sharting_uni_rcvmsg(node_p node, item_p item, hook_p lasthook) 306122219Sharti{ 307122219Sharti struct priv *priv = NG_NODE_PRIVATE(node); 308122219Sharti struct ng_mesg *resp = NULL; 309122219Sharti struct ng_mesg *msg; 310122219Sharti int error = 0; 311122219Sharti u_int i; 312122219Sharti 313122219Sharti NGI_GET_MSG(item, msg); 314122219Sharti 315122219Sharti switch (msg->header.typecookie) { 316122219Sharti 317122219Sharti case NGM_GENERIC_COOKIE: 318122219Sharti switch (msg->header.cmd) { 319122219Sharti 320122219Sharti case NGM_TEXT_STATUS: 321122219Sharti NG_MKRESPONSE(resp, msg, NG_TEXTRESPONSE, M_NOWAIT); 322122219Sharti if (resp == NULL) { 323122219Sharti error = ENOMEM; 324122219Sharti break; 325122219Sharti } 326122219Sharti 327122219Sharti resp->header.arglen = text_status(node, priv, 328122219Sharti (char *)resp->data, resp->header.arglen) + 1; 329122219Sharti break; 330122219Sharti 331122219Sharti default: 332122219Sharti error = EINVAL; 333122219Sharti break; 334122219Sharti } 335122219Sharti break; 336122219Sharti 337122219Sharti case NGM_UNI_COOKIE: 338122219Sharti switch (msg->header.cmd) { 339122219Sharti 340122219Sharti case NGM_UNI_SETDEBUG: 341122219Sharti { 342122219Sharti struct ngm_uni_debug *arg; 343122219Sharti 344122219Sharti if (msg->header.arglen > sizeof(*arg)) { 345122219Sharti error = EINVAL; 346122219Sharti break; 347122219Sharti } 348122219Sharti arg = (struct ngm_uni_debug *)msg->data; 349122219Sharti for (i = 0; i < UNI_MAXFACILITY; i++) 350122219Sharti uni_set_debug(priv->uni, i, arg->level[i]); 351122219Sharti break; 352122219Sharti } 353122219Sharti 354122219Sharti case NGM_UNI_GETDEBUG: 355122219Sharti { 356122219Sharti struct ngm_uni_debug *arg; 357122219Sharti 358122219Sharti NG_MKRESPONSE(resp, msg, sizeof(*arg), M_NOWAIT); 359122219Sharti if(resp == NULL) { 360122219Sharti error = ENOMEM; 361122219Sharti break; 362122219Sharti } 363122219Sharti arg = (struct ngm_uni_debug *)resp->data; 364122219Sharti for (i = 0; i < UNI_MAXFACILITY; i++) 365122219Sharti arg->level[i] = uni_get_debug(priv->uni, i); 366122219Sharti break; 367122219Sharti } 368122219Sharti 369122219Sharti case NGM_UNI_GET_CONFIG: 370122219Sharti { 371122219Sharti struct uni_config *config; 372122219Sharti 373122219Sharti if (msg->header.arglen != 0) { 374122219Sharti error = EINVAL; 375122219Sharti break; 376122219Sharti } 377122219Sharti NG_MKRESPONSE(resp, msg, sizeof(*config), M_NOWAIT); 378122219Sharti if (resp == NULL) { 379122219Sharti error = ENOMEM; 380122219Sharti break; 381122219Sharti } 382122219Sharti config = (struct uni_config *)resp->data; 383122219Sharti uni_get_config(priv->uni, config); 384122219Sharti 385122219Sharti break; 386122219Sharti } 387122219Sharti 388122219Sharti case NGM_UNI_SET_CONFIG: 389122219Sharti { 390122219Sharti struct ngm_uni_set_config *arg; 391122219Sharti struct ngm_uni_config_mask *mask; 392122219Sharti 393122219Sharti if (msg->header.arglen != sizeof(*arg)) { 394122219Sharti error = EINVAL; 395122219Sharti break; 396122219Sharti } 397122219Sharti arg = (struct ngm_uni_set_config *)msg->data; 398122219Sharti 399122219Sharti NG_MKRESPONSE(resp, msg, sizeof(*mask), M_NOWAIT); 400122219Sharti if (resp == NULL) { 401122219Sharti error = ENOMEM; 402122219Sharti break; 403122219Sharti } 404122219Sharti mask = (struct ngm_uni_config_mask *)resp->data; 405122219Sharti 406122219Sharti *mask = arg->mask; 407122219Sharti 408122219Sharti uni_set_config(priv->uni, &arg->config, 409122219Sharti &mask->mask, &mask->popt_mask, &mask->option_mask); 410122219Sharti 411122219Sharti break; 412122219Sharti } 413122219Sharti 414122219Sharti case NGM_UNI_ENABLE: 415122219Sharti if (msg->header.arglen != 0) { 416122219Sharti error = EINVAL; 417122219Sharti break; 418122219Sharti } 419122219Sharti if (priv->enabled) { 420122219Sharti error = EISCONN; 421122219Sharti break; 422122219Sharti } 423122219Sharti priv->enabled = 1; 424122219Sharti break; 425122219Sharti 426122219Sharti case NGM_UNI_DISABLE: 427122219Sharti if (msg->header.arglen != 0) { 428122219Sharti error = EINVAL; 429122219Sharti break; 430122219Sharti } 431122219Sharti if (!priv->enabled) { 432122219Sharti error = ENOTCONN; 433122219Sharti break; 434122219Sharti } 435122219Sharti priv->enabled = 0; 436122219Sharti uni_reset(priv->uni); 437122219Sharti break; 438122219Sharti 439122219Sharti case NGM_UNI_GETSTATE: 440122219Sharti if (msg->header.arglen != 0) { 441122219Sharti error = EINVAL; 442122219Sharti break; 443122219Sharti } 444122219Sharti NG_MKRESPONSE(resp, msg, sizeof(u_int32_t), M_NOWAIT); 445122219Sharti if(resp == NULL) { 446122219Sharti error = ENOMEM; 447122219Sharti break; 448122219Sharti } 449122219Sharti *(u_int32_t *)resp->data = 450122219Sharti priv->enabled ? (uni_getcustate(priv->uni) + 1) 451122219Sharti : 0; 452122219Sharti break; 453122219Sharti 454122219Sharti default: 455122219Sharti error = EINVAL; 456122219Sharti break; 457122219Sharti } 458122219Sharti break; 459122219Sharti 460122219Sharti default: 461122219Sharti error = EINVAL; 462122219Sharti break; 463122219Sharti } 464122219Sharti 465122219Sharti NG_RESPOND_MSG(error, node, item, resp); 466122219Sharti NG_FREE_MSG(msg); 467122219Sharti return (error); 468122219Sharti} 469122219Sharti 470122219Sharti/************************************************************/ 471122219Sharti/* 472122219Sharti * HOOK MANAGEMENT 473122219Sharti */ 474122219Shartistatic int 475122219Sharting_uni_newhook(node_p node, hook_p hook, const char *name) 476122219Sharti{ 477122219Sharti struct priv *priv = NG_NODE_PRIVATE(node); 478122219Sharti 479122219Sharti if (strcmp(name, "lower") == 0) { 480122219Sharti priv->lower = hook; 481122219Sharti } else if(strcmp(name, "upper") == 0) { 482122219Sharti priv->upper = hook; 483122219Sharti NG_HOOK_SET_RCVDATA(hook, ng_uni_rcvupper); 484122219Sharti } else 485122219Sharti return EINVAL; 486122219Sharti 487122219Sharti return 0; 488122219Sharti} 489122219Sharti 490122219Shartistatic int 491122219Sharting_uni_disconnect(hook_p hook) 492122219Sharti{ 493122219Sharti node_p node = NG_HOOK_NODE(hook); 494122219Sharti struct priv *priv = NG_NODE_PRIVATE(node); 495122219Sharti 496122219Sharti if(hook == priv->lower) 497122219Sharti priv->lower = NULL; 498122219Sharti else if(hook == priv->upper) 499122219Sharti priv->upper = NULL; 500122219Sharti else 501148915Sobrien printf("%s: bogus hook %s\n", __func__, NG_HOOK_NAME(hook)); 502122219Sharti 503122219Sharti if (NG_NODE_NUMHOOKS(node) == 0) { 504122219Sharti if (NG_NODE_IS_VALID(node)) 505122219Sharti ng_rmnode_self(node); 506122219Sharti } 507122219Sharti 508122219Sharti return (0); 509122219Sharti} 510122219Sharti 511122219Sharti/************************************************************/ 512122219Sharti/* 513122219Sharti * DATA 514122219Sharti */ 515122219Sharti/* 516122219Sharti * Receive signal from USER. 517122219Sharti * 518122219Sharti * Repackage the data into one large buffer. 519122219Sharti */ 520122219Shartistatic int 521122219Sharting_uni_rcvupper(hook_p hook, item_p item) 522122219Sharti{ 523122219Sharti node_p node = NG_HOOK_NODE(hook); 524122219Sharti struct priv *priv = NG_NODE_PRIVATE(node); 525122219Sharti struct mbuf *m; 526122219Sharti struct uni_arg arg; 527122219Sharti struct uni_msg *msg; 528122219Sharti int error; 529122219Sharti 530122219Sharti if (!priv->enabled) { 531122219Sharti NG_FREE_ITEM(item); 532122219Sharti return (ENOTCONN); 533122219Sharti } 534122219Sharti 535122219Sharti NGI_GET_M(item, m); 536122219Sharti NG_FREE_ITEM(item); 537122219Sharti 538122219Sharti if ((error = uni_msg_unpack_mbuf(m, &msg)) != 0) { 539122219Sharti m_freem(m); 540122219Sharti return (error); 541122219Sharti } 542122219Sharti m_freem(m); 543122219Sharti 544122219Sharti if (uni_msg_len(msg) < sizeof(arg)) { 545148915Sobrien printf("%s: packet too short\n", __func__); 546122219Sharti uni_msg_destroy(msg); 547122219Sharti return (EINVAL); 548122219Sharti } 549122219Sharti 550122219Sharti bcopy(msg->b_rptr, &arg, sizeof(arg)); 551122219Sharti msg->b_rptr += sizeof(arg); 552122219Sharti 553122219Sharti if (arg.sig >= UNIAPI_MAXSIG) { 554148915Sobrien printf("%s: bogus signal\n", __func__); 555122219Sharti uni_msg_destroy(msg); 556122219Sharti return (EINVAL); 557122219Sharti } 558122219Sharti uni_uni_input(priv->uni, arg.sig, arg.cookie, msg); 559122219Sharti uni_work(priv->uni); 560122219Sharti 561122219Sharti return (0); 562122219Sharti} 563122219Sharti 564122219Sharti 565122219Sharti/* 566122219Sharti * Upper layer signal from UNI 567122219Sharti */ 568122219Shartistatic void 569122219Shartiuni_uni_output(struct uni *uni, void *varg, enum uni_sig sig, u_int32_t cookie, 570122219Sharti struct uni_msg *msg) 571122219Sharti{ 572122219Sharti node_p node = (node_p)varg; 573122219Sharti struct priv *priv = NG_NODE_PRIVATE(node); 574122219Sharti struct mbuf *m; 575122219Sharti struct uni_arg arg; 576122219Sharti int error; 577122219Sharti 578122219Sharti if (priv->upper == NULL) { 579122219Sharti if (msg != NULL) 580122219Sharti uni_msg_destroy(msg); 581122219Sharti return; 582122219Sharti } 583122219Sharti arg.sig = sig; 584122219Sharti arg.cookie = cookie; 585122219Sharti 586122219Sharti m = uni_msg_pack_mbuf(msg, &arg, sizeof(arg)); 587122219Sharti if (msg != NULL) 588122219Sharti uni_msg_destroy(msg); 589122219Sharti if (m == NULL) 590122219Sharti return; 591122219Sharti 592122219Sharti NG_SEND_DATA_ONLY(error, priv->upper, m); 593122219Sharti} 594122219Sharti 595122219Sharti 596122219Shartistatic void 597122219Shartidump_uni_msg(struct uni_msg *msg) 598122219Sharti{ 599122219Sharti u_int pos; 600122219Sharti 601122219Sharti for (pos = 0; pos < uni_msg_len(msg); pos++) { 602122219Sharti if (pos % 16 == 0) 603122219Sharti printf("%06o ", pos); 604122219Sharti if (pos % 16 == 8) 605122219Sharti printf(" "); 606122219Sharti printf(" %02x", msg->b_rptr[pos]); 607122219Sharti if (pos % 16 == 15) 608122219Sharti printf("\n"); 609122219Sharti } 610122219Sharti if (pos % 16 != 0) 611122219Sharti printf("\n"); 612122219Sharti} 613122219Sharti 614122219Sharti 615122219Sharti/* 616122219Sharti * Dump a SAAL signal in either direction 617122219Sharti */ 618122219Shartistatic void 619122219Shartidump_saal_signal(node_p node, enum saal_sig sig, struct uni_msg *msg, int to) 620122219Sharti{ 621122219Sharti struct priv *priv = NG_NODE_PRIVATE(node); 622122219Sharti 623122219Sharti printf("signal %s SAAL: ", to ? "to" : "from"); 624122219Sharti 625122219Sharti switch (sig) { 626122219Sharti 627122219Sharti#define D(S) case S: printf("%s", #S); break 628122219Sharti 629122219Sharti D(SAAL_ESTABLISH_request); 630122219Sharti D(SAAL_ESTABLISH_indication); 631122219Sharti D(SAAL_ESTABLISH_confirm); 632122219Sharti D(SAAL_RELEASE_request); 633122219Sharti D(SAAL_RELEASE_confirm); 634122219Sharti D(SAAL_RELEASE_indication); 635122219Sharti D(SAAL_DATA_request); 636122219Sharti D(SAAL_DATA_indication); 637122219Sharti D(SAAL_UDATA_request); 638122219Sharti D(SAAL_UDATA_indication); 639122219Sharti 640122219Sharti#undef D 641122219Sharti default: 642122219Sharti printf("sig=%d", sig); break; 643122219Sharti } 644122219Sharti if (msg != NULL) { 645122219Sharti printf(" data=%zu\n", uni_msg_len(msg)); 646122219Sharti if (uni_get_debug(priv->uni, UNI_FAC_SAAL) > 1) 647122219Sharti dump_uni_msg(msg); 648122219Sharti } else 649122219Sharti printf("\n"); 650122219Sharti} 651122219Sharti 652122219Sharti/* 653122219Sharti * Receive signal from SSCOP. 654122219Sharti * 655122219Sharti * If this is a data signal, repackage the data into one large buffer. 656122219Sharti * UNI shouldn't be the bottleneck in a system and this greatly simplifies 657122219Sharti * parsing in UNI. 658122219Sharti */ 659122219Shartistatic int 660122219Sharting_uni_rcvlower(hook_p hook __unused, item_p item) 661122219Sharti{ 662122219Sharti node_p node = NG_HOOK_NODE(hook); 663122219Sharti struct priv *priv = NG_NODE_PRIVATE(node); 664122219Sharti struct mbuf *m; 665122219Sharti struct sscfu_arg arg; 666122219Sharti struct uni_msg *msg; 667122219Sharti int error; 668122219Sharti 669122219Sharti if (!priv->enabled) { 670122219Sharti NG_FREE_ITEM(item); 671122219Sharti return (ENOTCONN); 672122219Sharti } 673122219Sharti 674122219Sharti NGI_GET_M(item, m); 675122219Sharti NG_FREE_ITEM(item); 676122219Sharti 677122219Sharti if ((error = uni_msg_unpack_mbuf(m, &msg)) != 0) { 678122219Sharti m_freem(m); 679122219Sharti return (error); 680122219Sharti } 681122219Sharti m_freem(m); 682122219Sharti 683122219Sharti if (uni_msg_len(msg) < sizeof(arg)) { 684122219Sharti uni_msg_destroy(msg); 685148915Sobrien printf("%s: packet too short\n", __func__); 686122219Sharti return (EINVAL); 687122219Sharti } 688122219Sharti bcopy(msg->b_rptr, &arg, sizeof(arg)); 689122219Sharti msg->b_rptr += sizeof(arg); 690122219Sharti 691122219Sharti if (arg.sig > SAAL_UDATA_indication) { 692122219Sharti uni_msg_destroy(msg); 693148915Sobrien printf("%s: bogus signal\n", __func__); 694122219Sharti return (EINVAL); 695122219Sharti } 696122219Sharti 697122219Sharti if (uni_get_debug(priv->uni, UNI_FAC_SAAL) > 0) 698122219Sharti dump_saal_signal(node, arg.sig, msg, 0); 699122219Sharti 700122219Sharti uni_saal_input(priv->uni, arg.sig, msg); 701122219Sharti uni_work(priv->uni); 702122219Sharti 703122219Sharti return (0); 704122219Sharti} 705122219Sharti 706122219Sharti/* 707122219Sharti * Send signal to sscop. 708122219Sharti * Pack the message into an mbuf chain. 709122219Sharti */ 710122219Shartistatic void 711122219Shartiuni_saal_output(struct uni *uni, void *varg, enum saal_sig sig, struct uni_msg *msg) 712122219Sharti{ 713122219Sharti node_p node = (node_p)varg; 714122219Sharti struct priv *priv = NG_NODE_PRIVATE(node); 715122219Sharti struct mbuf *m; 716122219Sharti struct sscfu_arg arg; 717122219Sharti int error; 718122219Sharti 719122219Sharti if (uni_get_debug(priv->uni, UNI_FAC_SAAL) > 0) 720122219Sharti dump_saal_signal(node, sig, msg, 1); 721122219Sharti 722122219Sharti if (priv->lower == NULL) { 723122219Sharti if (msg != NULL) 724122219Sharti uni_msg_destroy(msg); 725122219Sharti return; 726122219Sharti } 727122219Sharti 728122219Sharti arg.sig = sig; 729122219Sharti 730122219Sharti m = uni_msg_pack_mbuf(msg, &arg, sizeof(arg)); 731122219Sharti if (msg != NULL) 732122219Sharti uni_msg_destroy(msg); 733122219Sharti if (m == NULL) 734122219Sharti return; 735122219Sharti 736122219Sharti NG_SEND_DATA_ONLY(error, priv->lower, m); 737122219Sharti} 738122219Sharti 739122219Shartistatic void 740122219Shartiuni_verbose(struct uni *uni, void *varg, u_int fac, const char *fmt, ...) 741122219Sharti{ 742122219Sharti va_list ap; 743122219Sharti 744122219Sharti static char *facnames[] = { 745194825Srdivacky#define UNI_DEBUG_DEFINE(D) [UNI_FAC_##D] = #D, 746122219Sharti UNI_DEBUG_FACILITIES 747122219Sharti#undef UNI_DEBUG_DEFINE 748122219Sharti }; 749122219Sharti 750122219Sharti printf("%s: ", facnames[fac]); 751122219Sharti 752122219Sharti va_start(ap, fmt); 753122219Sharti vprintf(fmt, ap); 754122219Sharti va_end(ap); 755122219Sharti 756122219Sharti printf("\n"); 757122219Sharti} 758122219Sharti 759122219Sharti 760122219Sharti/************************************************************/ 761122219Sharti/* 762122219Sharti * Memory debugging 763122219Sharti */ 764122219Shartistruct unimem_debug { 765122219Sharti const char *file; 766122219Sharti u_int lno; 767122219Sharti LIST_ENTRY(unimem_debug) link; 768122219Sharti char data[0]; 769122219Sharti}; 770122219ShartiLIST_HEAD(unimem_debug_list, unimem_debug); 771122219Sharti 772122219Shartistatic struct unimem_debug_list nguni_freemem[UNIMEM_TYPES] = { 773201145Santoine LIST_HEAD_INITIALIZER(nguni_freemem[0]), 774201145Santoine LIST_HEAD_INITIALIZER(nguni_freemem[1]), 775201145Santoine LIST_HEAD_INITIALIZER(nguni_freemem[2]), 776201145Santoine LIST_HEAD_INITIALIZER(nguni_freemem[3]), 777201145Santoine LIST_HEAD_INITIALIZER(nguni_freemem[4]), 778122219Sharti}; 779122219Shartistatic struct unimem_debug_list nguni_usedmem[UNIMEM_TYPES] = { 780201145Santoine LIST_HEAD_INITIALIZER(nguni_usedmem[0]), 781201145Santoine LIST_HEAD_INITIALIZER(nguni_usedmem[1]), 782201145Santoine LIST_HEAD_INITIALIZER(nguni_usedmem[2]), 783201145Santoine LIST_HEAD_INITIALIZER(nguni_usedmem[3]), 784201145Santoine LIST_HEAD_INITIALIZER(nguni_usedmem[4]), 785122219Sharti}; 786122219Sharti 787122219Shartistatic struct mtx nguni_unilist_mtx; 788122219Sharti 789122219Shartistatic const char *unimem_names[UNIMEM_TYPES] = { 790122219Sharti "instance", 791122219Sharti "all", 792122219Sharti "signal", 793122219Sharti "call", 794122219Sharti "party" 795122219Sharti}; 796122219Sharti 797122219Shartistatic void 798122219Shartiuni_init(void) 799122219Sharti{ 800123541Struckman mtx_init(&nguni_unilist_mtx, "netgraph UNI structure lists", NULL, 801123541Struckman MTX_DEF); 802122219Sharti} 803122219Sharti 804122219Shartistatic void 805122219Shartiuni_fini(void) 806122219Sharti{ 807122219Sharti u_int type; 808122219Sharti struct unimem_debug *h; 809122219Sharti 810122219Sharti for (type = 0; type < UNIMEM_TYPES; type++) { 811122219Sharti while ((h = LIST_FIRST(&nguni_freemem[type])) != NULL) { 812122219Sharti LIST_REMOVE(h, link); 813122219Sharti free(h, M_UNI); 814122219Sharti } 815122219Sharti 816122219Sharti while ((h = LIST_FIRST(&nguni_usedmem[type])) != NULL) { 817122219Sharti LIST_REMOVE(h, link); 818122219Sharti printf("ng_uni: %s in use: %p (%s,%u)\n", 819122219Sharti unimem_names[type], (caddr_t)h->data, 820122219Sharti h->file, h->lno); 821122219Sharti free(h, M_UNI); 822122219Sharti } 823122219Sharti } 824122219Sharti 825122219Sharti mtx_destroy(&nguni_unilist_mtx); 826122219Sharti} 827122219Sharti 828122219Sharti/* 829122219Sharti * Allocate a chunk of memory from a given type. 830122219Sharti */ 831122219Shartivoid * 832122219Sharting_uni_malloc(enum unimem type, const char *file, u_int lno) 833122219Sharti{ 834122219Sharti struct unimem_debug *d; 835122219Sharti size_t full; 836122219Sharti 837122219Sharti /* 838122219Sharti * Try to allocate 839122219Sharti */ 840122219Sharti mtx_lock(&nguni_unilist_mtx); 841122219Sharti if ((d = LIST_FIRST(&nguni_freemem[type])) != NULL) 842122219Sharti LIST_REMOVE(d, link); 843122219Sharti mtx_unlock(&nguni_unilist_mtx); 844122219Sharti 845122219Sharti if (d == NULL) { 846122219Sharti /* 847122219Sharti * allocate 848122219Sharti */ 849122219Sharti full = unimem_sizes[type] + offsetof(struct unimem_debug, data); 850122219Sharti if ((d = malloc(full, M_UNI, M_NOWAIT | M_ZERO)) == NULL) 851122219Sharti return (NULL); 852122219Sharti } else { 853122219Sharti bzero(d->data, unimem_sizes[type]); 854122219Sharti } 855122219Sharti d->file = file; 856122219Sharti d->lno = lno; 857122219Sharti 858122219Sharti mtx_lock(&nguni_unilist_mtx); 859122219Sharti LIST_INSERT_HEAD(&nguni_usedmem[type], d, link); 860122219Sharti mtx_unlock(&nguni_unilist_mtx); 861122219Sharti return (d->data); 862122219Sharti} 863122219Sharti 864122219Shartivoid 865122219Sharting_uni_free(enum unimem type, void *ptr, const char *file, u_int lno) 866122219Sharti{ 867122219Sharti struct unimem_debug *d, *h; 868122219Sharti 869122219Sharti d = (struct unimem_debug *) 870122219Sharti ((char *)ptr - offsetof(struct unimem_debug, data)); 871122219Sharti 872122219Sharti mtx_lock(&nguni_unilist_mtx); 873122219Sharti 874122219Sharti LIST_FOREACH(h, &nguni_usedmem[type], link) 875122219Sharti if (d == h) 876122219Sharti break; 877122219Sharti 878122219Sharti if (h != NULL) { 879122219Sharti LIST_REMOVE(d, link); 880122219Sharti LIST_INSERT_HEAD(&nguni_freemem[type], d, link); 881122219Sharti } else { 882122219Sharti /* 883122219Sharti * Not on used list - try free list. 884122219Sharti */ 885122219Sharti LIST_FOREACH(h, &nguni_freemem[type], link) 886122219Sharti if (d == h) 887122219Sharti break; 888122219Sharti if (h == NULL) 889122219Sharti printf("ng_uni: %s,%u: %p(%s) was never allocated\n", 890122219Sharti file, lno, ptr, unimem_names[type]); 891122219Sharti else 892122219Sharti printf("ng_uni: %s,%u: %p(%s) was already destroyed " 893122219Sharti "in %s,%u\n", 894122219Sharti file, lno, ptr, unimem_names[type], 895122219Sharti h->file, h->lno); 896122219Sharti } 897122219Sharti mtx_unlock(&nguni_unilist_mtx); 898122219Sharti} 899122219Sharti/************************************************************/ 900122219Sharti/* 901122219Sharti * INITIALISATION 902122219Sharti */ 903122219Sharti 904122219Sharti/* 905122219Sharti * Loading and unloading of node type 906122219Sharti */ 907122219Shartistatic int 908122219Sharting_uni_mod_event(module_t mod, int event, void *data) 909122219Sharti{ 910122219Sharti int error = 0; 911122219Sharti 912122219Sharti switch(event) { 913122219Sharti 914122219Sharti case MOD_LOAD: 915122219Sharti uni_init(); 916122219Sharti break; 917122219Sharti 918122219Sharti case MOD_UNLOAD: 919122219Sharti uni_fini(); 920122219Sharti break; 921122219Sharti 922122219Sharti default: 923122219Sharti error = EOPNOTSUPP; 924122219Sharti break; 925122219Sharti } 926122219Sharti return (error); 927122219Sharti} 928