ng_ccatm.c revision 139823
1170530Ssam/*- 2178354Ssam * Copyright (c) 2001-2002 3170530Ssam * Fraunhofer Institute for Open Communication Systems (FhG Fokus). 4170530Ssam * All rights reserved. 5170530Ssam * Copyright (c) 2003-2004 6170530Ssam * Hartmut Brandt 7170530Ssam * All rights reserved. 8170530Ssam * 9170530Ssam * Author: Harti Brandt <harti@freebsd.org> 10170530Ssam * 11170530Ssam * Redistribution of this software and documentation and use in source and 12170530Ssam * binary forms, with or without modification, are permitted provided that 13170530Ssam * the following conditions are met: 14170530Ssam * 15170530Ssam * 1. Redistributions of source code or documentation must retain the above 16170530Ssam * copyright notice, this list of conditions and the following disclaimer. 17170530Ssam * 2. Redistributions in binary form must reproduce the above copyright 18170530Ssam * notice, this list of conditions and the following disclaimer in the 19170530Ssam * documentation and/or other materials provided with the distribution. 20170530Ssam * 21170530Ssam * THIS SOFTWARE AND DOCUMENTATION IS PROVIDED BY THE AUTHOR 22170530Ssam * AND ITS CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, 23170530Ssam * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 24170530Ssam * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 25170530Ssam * THE AUTHOR OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 26170530Ssam * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27170530Ssam * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 28170530Ssam * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 29170530Ssam * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 30170530Ssam * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 31170530Ssam * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32170530Ssam * 33170530Ssam * $FreeBSD: head/sys/netgraph/atm/ccatm/ng_ccatm.c 139823 2005-01-07 01:45:51Z imp $ 34170530Ssam * 35170530Ssam * ATM call control and API 36178354Ssam */ 37170530Ssam 38170530Ssam#include <sys/cdefs.h> 39170530Ssam__FBSDID("$FreeBSD: head/sys/netgraph/atm/ccatm/ng_ccatm.c 139823 2005-01-07 01:45:51Z imp $"); 40170530Ssam 41170530Ssam#include <sys/param.h> 42170530Ssam#include <sys/systm.h> 43170530Ssam#include <sys/kernel.h> 44170530Ssam#include <sys/malloc.h> 45170530Ssam#include <sys/mbuf.h> 46170530Ssam#include <sys/errno.h> 47170530Ssam#include <sys/socket.h> 48170530Ssam#include <sys/socketvar.h> 49170530Ssam#include <sys/sbuf.h> 50195377Ssam#include <machine/stdarg.h> 51178354Ssam 52170530Ssam#include <netgraph/ng_message.h> 53170530Ssam#include <netgraph/netgraph.h> 54170530Ssam#include <netgraph/ng_parse.h> 55170530Ssam#include <netnatm/unimsg.h> 56170530Ssam#include <netnatm/msg/unistruct.h> 57219456Sbschmidt#include <netnatm/api/unisap.h> 58219456Sbschmidt#include <netnatm/sig/unidef.h> 59219456Sbschmidt#include <netgraph/atm/ngatmbase.h> 60219456Sbschmidt#include <netgraph/atm/ng_uni.h> 61219456Sbschmidt#include <netnatm/api/atmapi.h> 62219456Sbschmidt#include <netgraph/atm/ng_ccatm.h> 63219456Sbschmidt#include <netnatm/api/ccatm.h> 64219456Sbschmidt 65219456SbschmidtMODULE_DEPEND(ng_ccatm, ngatmbase, 1, 1, 1); 66219456Sbschmidt 67219456SbschmidtMALLOC_DEFINE(M_NG_CCATM, "ng_ccatm", "netgraph uni api node"); 68219456Sbschmidt 69219456Sbschmidt/* 70219456Sbschmidt * Command structure parsing 71219456Sbschmidt */ 72219456Sbschmidt 73219456Sbschmidt/* ESI */ 74219456Sbschmidtstatic const struct ng_parse_fixedarray_info ng_ccatm_esi_type_info = 75219456Sbschmidt NGM_CCATM_ESI_INFO; 76219456Sbschmidtstatic const struct ng_parse_type ng_ccatm_esi_type = { 77219456Sbschmidt &ng_parse_fixedarray_type, 78219456Sbschmidt &ng_ccatm_esi_type_info 79219456Sbschmidt}; 80219456Sbschmidt 81219456Sbschmidt/* PORT PARAMETERS */ 82219456Sbschmidtstatic const struct ng_parse_struct_field ng_ccatm_atm_port_type_info[] = 83219456Sbschmidt NGM_CCATM_ATM_PORT_INFO; 84219456Sbschmidtstatic const struct ng_parse_type ng_ccatm_atm_port_type = { 85219456Sbschmidt &ng_parse_struct_type, 86219456Sbschmidt ng_ccatm_atm_port_type_info 87219456Sbschmidt}; 88219456Sbschmidt 89219456Sbschmidt/* PORT structure */ 90219456Sbschmidtstatic const struct ng_parse_struct_field ng_ccatm_port_type_info[] = 91219456Sbschmidt NGM_CCATM_PORT_INFO; 92219456Sbschmidtstatic const struct ng_parse_type ng_ccatm_port_type = { 93219456Sbschmidt &ng_parse_struct_type, 94219456Sbschmidt ng_ccatm_port_type_info 95219456Sbschmidt}; 96219456Sbschmidt 97219456Sbschmidt/* the ADDRESS array itself */ 98219456Sbschmidtstatic const struct ng_parse_fixedarray_info ng_ccatm_addr_array_type_info = 99219456Sbschmidt NGM_CCATM_ADDR_ARRAY_INFO; 100219456Sbschmidtstatic const struct ng_parse_type ng_ccatm_addr_array_type = { 101219456Sbschmidt &ng_parse_fixedarray_type, 102219456Sbschmidt &ng_ccatm_addr_array_type_info 103219456Sbschmidt}; 104219456Sbschmidt 105219456Sbschmidt/* one ADDRESS */ 106219456Sbschmidtstatic const struct ng_parse_struct_field ng_ccatm_uni_addr_type_info[] = 107219456Sbschmidt NGM_CCATM_UNI_ADDR_INFO; 108219456Sbschmidtstatic const struct ng_parse_type ng_ccatm_uni_addr_type = { 109219456Sbschmidt &ng_parse_struct_type, 110219456Sbschmidt ng_ccatm_uni_addr_type_info 111219456Sbschmidt}; 112219456Sbschmidt 113219456Sbschmidt/* ADDRESS request */ 114219456Sbschmidtstatic const struct ng_parse_struct_field ng_ccatm_addr_req_type_info[] = 115219456Sbschmidt NGM_CCATM_ADDR_REQ_INFO; 116219456Sbschmidtstatic const struct ng_parse_type ng_ccatm_addr_req_type = { 117219456Sbschmidt &ng_parse_struct_type, 118219456Sbschmidt ng_ccatm_addr_req_type_info 119219456Sbschmidt}; 120219456Sbschmidt 121219456Sbschmidt/* ADDRESS var-array */ 122219456Sbschmidtstatic int 123219456Sbschmidtng_ccatm_addr_req_array_getlen(const struct ng_parse_type *type, 124219456Sbschmidt const u_char *start, const u_char *buf) 125219456Sbschmidt{ 126219456Sbschmidt const struct ngm_ccatm_get_addresses *p; 127219456Sbschmidt 128219456Sbschmidt p = (const struct ngm_ccatm_get_addresses *) 129219456Sbschmidt (buf - offsetof(struct ngm_ccatm_get_addresses, addr)); 130219456Sbschmidt return (p->count); 131219456Sbschmidt} 132219456Sbschmidtstatic const struct ng_parse_array_info ng_ccatm_addr_req_array_type_info = 133219456Sbschmidt NGM_CCATM_ADDR_REQ_ARRAY_INFO; 134219456Sbschmidtstatic const struct ng_parse_type ng_ccatm_addr_req_array_type = { 135170530Ssam &ng_parse_array_type, 136170530Ssam &ng_ccatm_addr_req_array_type_info 137173273Ssam}; 138193115Ssam 139193115Ssam/* Outer get_ADDRESSes structure */ 140193115Ssamstatic const struct ng_parse_struct_field ng_ccatm_get_addresses_type_info[] = 141193115Ssam NGM_CCATM_GET_ADDRESSES_INFO; 142173273Ssamstatic const struct ng_parse_type ng_ccatm_get_addresses_type = { 143173273Ssam &ng_parse_struct_type, 144193115Ssam ng_ccatm_get_addresses_type_info 145193115Ssam}; 146193115Ssam 147193115Ssam/* Port array */ 148193115Ssamstatic int 149193115Ssamng_ccatm_port_array_getlen(const struct ng_parse_type *type, 150193115Ssam const u_char *start, const u_char *buf) 151193115Ssam{ 152193115Ssam const struct ngm_ccatm_portlist *p; 153193115Ssam 154193115Ssam p = (const struct ngm_ccatm_portlist *) 155193115Ssam (buf - offsetof(struct ngm_ccatm_portlist, ports)); 156193115Ssam return (p->nports); 157193115Ssam} 158193115Ssamstatic const struct ng_parse_array_info ng_ccatm_port_array_type_info = 159193115Ssam NGM_CCATM_PORT_ARRAY_INFO; 160193115Ssamstatic const struct ng_parse_type ng_ccatm_port_array_type = { 161193115Ssam &ng_parse_array_type, 162193115Ssam &ng_ccatm_port_array_type_info 163195377Ssam}; 164195377Ssam 165195377Ssam/* Portlist structure */ 166195377Ssamstatic const struct ng_parse_struct_field ng_ccatm_portlist_type_info[] = 167195377Ssam NGM_CCATM_PORTLIST_INFO; 168195377Ssamstatic const struct ng_parse_type ng_ccatm_portlist_type = { 169195377Ssam &ng_parse_struct_type, 170195377Ssam ng_ccatm_portlist_type_info 171195377Ssam}; 172195377Ssam 173178354Ssam/* 174195377Ssam * Command list 175178354Ssam */ 176195377Ssamstatic const struct ng_cmdlist ng_ccatm_cmdlist[] = { 177195377Ssam { 178195377Ssam NGM_CCATM_COOKIE, 179178354Ssam NGM_CCATM_DUMP, 180178354Ssam "dump", 181178354Ssam NULL, 182178354Ssam NULL 183178354Ssam }, 184184280Ssam { 185195377Ssam NGM_CCATM_COOKIE, 186195377Ssam NGM_CCATM_STOP, 187195377Ssam "stop", 188195377Ssam &ng_ccatm_port_type, 189195377Ssam NULL 190195377Ssam }, 191195377Ssam { 192195377Ssam NGM_CCATM_COOKIE, 193195377Ssam NGM_CCATM_START, 194195377Ssam "start", 195195377Ssam &ng_ccatm_port_type, 196195377Ssam NULL 197195377Ssam }, 198195377Ssam { 199195377Ssam NGM_CCATM_COOKIE, 200195377Ssam NGM_CCATM_GETSTATE, 201195377Ssam "getstate", 202195377Ssam &ng_ccatm_port_type, 203195377Ssam &ng_parse_uint32_type 204195377Ssam }, 205195377Ssam { 206195377Ssam NGM_CCATM_COOKIE, 207178354Ssam NGM_CCATM_GET_ADDRESSES, 208195377Ssam "get_addresses", 209170530Ssam &ng_ccatm_port_type, 210178354Ssam &ng_ccatm_get_addresses_type 211178354Ssam }, 212170530Ssam { 213170530Ssam NGM_CCATM_COOKIE, 214170530Ssam NGM_CCATM_CLEAR, 215170530Ssam "clear", 216170530Ssam &ng_ccatm_port_type, 217170530Ssam NULL 218170530Ssam }, 219170530Ssam { 220184280Ssam NGM_CCATM_COOKIE, 221184280Ssam NGM_CCATM_ADDRESS_REGISTERED, 222184280Ssam "address_reg", 223184280Ssam &ng_ccatm_addr_req_type, 224191552Ssam NULL 225191552Ssam }, 226191552Ssam { 227170530Ssam NGM_CCATM_COOKIE, 228170530Ssam NGM_CCATM_ADDRESS_UNREGISTERED, 229170530Ssam "address_unreg", 230170530Ssam &ng_ccatm_addr_req_type, 231170530Ssam NULL 232195377Ssam }, 233170530Ssam { 234178354Ssam NGM_CCATM_COOKIE, 235170530Ssam NGM_CCATM_SET_PORT_PARAM, 236170530Ssam "set_port_param", 237170530Ssam &ng_ccatm_atm_port_type, 238184280Ssam NULL 239191552Ssam }, 240191552Ssam { 241170530Ssam NGM_CCATM_COOKIE, 242173273Ssam NGM_CCATM_GET_PORT_PARAM, 243173273Ssam "get_port_param", 244178354Ssam &ng_ccatm_port_type, 245173273Ssam &ng_ccatm_atm_port_type, 246178354Ssam }, 247178354Ssam { 248178354Ssam NGM_CCATM_COOKIE, 249178354Ssam NGM_CCATM_GET_PORTLIST, 250173273Ssam "get_portlist", 251178354Ssam NULL, 252178354Ssam &ng_ccatm_portlist_type, 253178354Ssam }, 254178354Ssam { 255178354Ssam NGM_CCATM_COOKIE, 256178354Ssam NGM_CCATM_SETLOG, 257178354Ssam "setlog", 258178354Ssam &ng_parse_hint32_type, 259178354Ssam &ng_parse_hint32_type, 260178354Ssam }, 261178354Ssam { 262178354Ssam NGM_CCATM_COOKIE, 263178354Ssam NGM_CCATM_RESET, 264178354Ssam "reset", 265178354Ssam NULL, 266178354Ssam NULL, 267170530Ssam }, 268173273Ssam { 0 } 269173273Ssam}; 270170530Ssam 271170530Ssam/* 272193655Ssam * Module data 273193655Ssam */ 274193655Ssamstatic ng_constructor_t ng_ccatm_constructor; 275178354Ssamstatic ng_rcvmsg_t ng_ccatm_rcvmsg; 276193655Ssamstatic ng_shutdown_t ng_ccatm_shutdown; 277173273Ssamstatic ng_newhook_t ng_ccatm_newhook; 278178354Ssamstatic ng_rcvdata_t ng_ccatm_rcvdata; 279193655Ssamstatic ng_disconnect_t ng_ccatm_disconnect; 280178354Ssamstatic int ng_ccatm_mod_event(module_t, int, void *); 281193655Ssam 282170530Ssamstatic struct ng_type ng_ccatm_typestruct = { 283183256Ssam .version = NG_ABI_VERSION, 284183256Ssam .name = NG_CCATM_NODE_TYPE, 285193655Ssam .mod_event = ng_ccatm_mod_event, 286183256Ssam .constructor = ng_ccatm_constructor, /* Node constructor */ 287170530Ssam .rcvmsg = ng_ccatm_rcvmsg, /* Control messages */ 288193655Ssam .shutdown = ng_ccatm_shutdown, /* Node destructor */ 289178354Ssam .newhook = ng_ccatm_newhook, /* Arrival of new hook */ 290193655Ssam .rcvdata = ng_ccatm_rcvdata, /* receive data */ 291193655Ssam .disconnect = ng_ccatm_disconnect, /* disconnect a hook */ 292178354Ssam .cmdlist = ng_ccatm_cmdlist, 293193655Ssam}; 294170530SsamNETGRAPH_INIT(ccatm, &ng_ccatm_typestruct); 295178354Ssam 296178354Ssamstatic ng_rcvdata_t ng_ccatm_rcvuni; 297193655Ssamstatic ng_rcvdata_t ng_ccatm_rcvdump; 298170530Ssamstatic ng_rcvdata_t ng_ccatm_rcvmanage; 299170530Ssam 300170530Ssam/* 301178354Ssam * Private node data. 302170530Ssam */ 303170530Ssamstruct ccnode { 304170530Ssam node_p node; /* the owning node */ 305219598Sbschmidt hook_p dump; /* dump hook */ 306219598Sbschmidt hook_p manage; /* hook to ILMI */ 307219598Sbschmidt 308219598Sbschmidt struct ccdata *data; 309219598Sbschmidt struct mbuf *dump_first; 310219598Sbschmidt struct mbuf *dump_last; /* first and last mbuf when dumping */ 311219598Sbschmidt 312219598Sbschmidt u_int hook_cnt; /* count user and port hooks */ 313219598Sbschmidt}; 314219598Sbschmidt 315219598Sbschmidt/* 316219598Sbschmidt * Private UNI hook data 317219598Sbschmidt */ 318219598Sbschmidtstruct cchook { 319219598Sbschmidt int is_uni; /* true if uni hook, user otherwise */ 320219598Sbschmidt struct ccnode *node; /* the owning node */ 321219598Sbschmidt hook_p hook; 322219598Sbschmidt void *inst; /* port or user */ 323219598Sbschmidt}; 324219598Sbschmidt 325219598Sbschmidtstatic void ng_ccatm_send_user(struct ccuser *, void *, u_int, void *, size_t); 326219598Sbschmidtstatic void ng_ccatm_respond_user(struct ccuser *, void *, int, u_int, 327219598Sbschmidt void *, size_t); 328219598Sbschmidtstatic void ng_ccatm_send_uni(struct ccconn *, void *, u_int, u_int, 329219598Sbschmidt struct uni_msg *); 330219598Sbschmidtstatic void ng_ccatm_send_uni_glob(struct ccport *, void *, u_int, u_int, 331219598Sbschmidt struct uni_msg *); 332219598Sbschmidtstatic void ng_ccatm_log(const char *, ...) __printflike(1, 2); 333219598Sbschmidt 334219598Sbschmidtstatic const struct cc_funcs cc_funcs = { 335219598Sbschmidt .send_user = ng_ccatm_send_user, 336219598Sbschmidt .respond_user = ng_ccatm_respond_user, 337219598Sbschmidt .send_uni = ng_ccatm_send_uni, 338219598Sbschmidt .send_uni_glob = ng_ccatm_send_uni_glob, 339219598Sbschmidt .log = ng_ccatm_log, 340219598Sbschmidt}; 341219598Sbschmidt 342219598Sbschmidt/************************************************************ 343219598Sbschmidt * 344219598Sbschmidt * Create a new node 345219598Sbschmidt */ 346219598Sbschmidtstatic int 347219598Sbschmidtng_ccatm_constructor(node_p node) 348170530Ssam{ 349219598Sbschmidt struct ccnode *priv; 350170530Ssam 351219598Sbschmidt priv = malloc(sizeof(*priv), M_NG_CCATM, M_NOWAIT | M_ZERO); 352219598Sbschmidt if (priv == NULL) 353219598Sbschmidt return (ENOMEM); 354170530Ssam 355219598Sbschmidt priv->node = node; 356219598Sbschmidt priv->data = cc_create(&cc_funcs); 357170530Ssam if (priv->data == NULL) { 358219598Sbschmidt free(priv, M_NG_CCATM); 359219598Sbschmidt return (ENOMEM); 360219598Sbschmidt } 361219598Sbschmidt 362219598Sbschmidt NG_NODE_SET_PRIVATE(node, priv); 363219598Sbschmidt 364219598Sbschmidt return (0); 365219598Sbschmidt} 366219598Sbschmidt 367219598Sbschmidt/* 368219598Sbschmidt * Destroy a node. The user list is empty here, because all hooks are 369219598Sbschmidt * previously disconnected. The connection lists may not be empty, because 370219598Sbschmidt * connections may be waiting for responses from the stack. This also means, 371219598Sbschmidt * that no orphaned connections will be made by the port_destroy routine. 372219598Sbschmidt */ 373205277Srpaulostatic int 374170530Ssamng_ccatm_shutdown(node_p node) 375170530Ssam{ 376170530Ssam struct ccnode *priv = NG_NODE_PRIVATE(node); 377205277Srpaulo 378219598Sbschmidt cc_destroy(priv->data); 379205277Srpaulo 380205277Srpaulo free(priv, M_NG_CCATM); 381205277Srpaulo NG_NODE_SET_PRIVATE(node, NULL); 382219598Sbschmidt 383219606Sbschmidt NG_NODE_UNREF(node); 384219598Sbschmidt 385219598Sbschmidt return (0); 386219606Sbschmidt} 387219598Sbschmidt 388219598Sbschmidt/* 389219598Sbschmidt * Retrieve the registered addresses for one port or all ports. 390219606Sbschmidt * Returns an error code or 0 on success. 391219598Sbschmidt */ 392219598Sbschmidtstatic int 393219598Sbschmidtng_ccatm_get_addresses(node_p node, uint32_t portno, struct ng_mesg *msg, 394219598Sbschmidt struct ng_mesg **resp) 395219606Sbschmidt{ 396219598Sbschmidt struct ccnode *priv = NG_NODE_PRIVATE(node); 397219598Sbschmidt struct uni_addr *addrs; 398205277Srpaulo u_int *ports; 399205277Srpaulo struct ngm_ccatm_get_addresses *list; 400170530Ssam u_int count, i; 401170530Ssam size_t len; 402170530Ssam int err; 403219598Sbschmidt 404219598Sbschmidt err = cc_get_addrs(priv->data, portno, &addrs, &ports, &count); 405219598Sbschmidt if (err != 0) 406219598Sbschmidt return (err); 407219598Sbschmidt 408170530Ssam len = sizeof(*list) + count * sizeof(list->addr[0]); 409219598Sbschmidt NG_MKRESPONSE(*resp, msg, len, M_NOWAIT); 410170530Ssam if (*resp == NULL) { 411219598Sbschmidt free(addrs, M_NG_CCATM); 412170530Ssam free(ports, M_NG_CCATM); 413170530Ssam return (ENOMEM); 414219602Sbschmidt } 415219602Sbschmidt list = (struct ngm_ccatm_get_addresses *)(*resp)->data; 416170530Ssam 417170530Ssam list->count = count; 418219602Sbschmidt for (i = 0; i < count; i++) { 419170530Ssam list->addr[i].port = ports[i]; 420219602Sbschmidt list->addr[i].addr = addrs[i]; 421219602Sbschmidt } 422219602Sbschmidt 423219602Sbschmidt free(addrs, M_NG_CCATM); 424219602Sbschmidt free(ports, M_NG_CCATM); 425219602Sbschmidt 426219602Sbschmidt return (0); 427219602Sbschmidt} 428219602Sbschmidt 429219602Sbschmidt/* 430219602Sbschmidt * Dumper function. Pack the data into an mbuf chain. 431219602Sbschmidt */ 432219602Sbschmidtstatic int 433219602Sbschmidtsend_dump(struct ccdata *data, void *uarg, const char *buf) 434219602Sbschmidt{ 435219602Sbschmidt struct mbuf *m; 436219602Sbschmidt struct ccnode *priv = uarg; 437219602Sbschmidt 438219602Sbschmidt if (priv->dump == NULL) { 439219602Sbschmidt m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR); 440219602Sbschmidt if (m == NULL) 441219602Sbschmidt return (ENOBUFS); 442219602Sbschmidt priv->dump_first = priv->dump_last = m; 443219602Sbschmidt m->m_pkthdr.len = 0; 444219602Sbschmidt } else { 445219602Sbschmidt m = m_getcl(M_DONTWAIT, MT_DATA, 0); 446219602Sbschmidt if (m == 0) { 447219602Sbschmidt m_freem(priv->dump_first); 448170530Ssam return (ENOBUFS); 449170530Ssam } 450170530Ssam priv->dump_last->m_next = m; 451170530Ssam priv->dump_last = m; 452170530Ssam } 453170530Ssam 454170530Ssam strcpy(m->m_data, buf); 455170530Ssam priv->dump_first->m_pkthdr.len += (m->m_len = strlen(buf)); 456170530Ssam 457170530Ssam return (0); 458170530Ssam} 459170530Ssam 460170530Ssam/* 461170530Ssam * Dump current status to dump hook 462178354Ssam */ 463173462Ssamstatic int 464170530Ssamng_ccatm_dump(node_p node) 465170530Ssam{ 466170530Ssam struct ccnode *priv = NG_NODE_PRIVATE(node); 467170530Ssam struct mbuf *m; 468170530Ssam int error; 469178354Ssam 470170530Ssam priv->dump_first = priv->dump_last = NULL; 471170530Ssam error = cc_dump(priv->data, MCLBYTES, send_dump, priv); 472170530Ssam if (error != 0) 473170530Ssam return (error); 474170530Ssam 475170530Ssam if ((m = priv->dump_first) != NULL) { 476170530Ssam priv->dump_first = priv->dump_last = NULL; 477170530Ssam NG_SEND_DATA_ONLY(error, priv->dump, m); 478170530Ssam return (error); 479170530Ssam } 480178354Ssam return (0); 481173462Ssam} 482178354Ssam 483170530Ssam/* 484170530Ssam * Control message 485173462Ssam */ 486170530Ssamstatic int 487170530Ssamng_ccatm_rcvmsg(node_p node, item_p item, hook_p lasthook) 488170530Ssam{ 489178354Ssam struct ng_mesg *resp = NULL; 490170530Ssam struct ng_mesg *msg; 491170530Ssam struct ccnode *priv = NG_NODE_PRIVATE(node); 492178354Ssam int error = 0; 493170530Ssam 494170530Ssam NGI_GET_MSG(item, msg); 495170530Ssam 496178354Ssam switch (msg->header.typecookie) { 497170530Ssam 498170530Ssam case NGM_CCATM_COOKIE: 499170530Ssam switch (msg->header.cmd) { 500170530Ssam 501170530Ssam case NGM_CCATM_DUMP: 502170530Ssam if (priv->dump) 503170530Ssam error = ng_ccatm_dump(node); 504170530Ssam else 505170530Ssam error = ENOTCONN; 506170530Ssam break; 507170530Ssam 508170530Ssam case NGM_CCATM_STOP: 509170530Ssam { 510170530Ssam struct ngm_ccatm_port *arg; 511170530Ssam 512170530Ssam if (msg->header.arglen != sizeof(*arg)) { 513170530Ssam error = EINVAL; 514170530Ssam break; 515170530Ssam } 516170530Ssam arg = (struct ngm_ccatm_port *)msg->data; 517170530Ssam error = cc_port_stop(priv->data, arg->port); 518170530Ssam break; 519170530Ssam } 520170530Ssam 521170530Ssam case NGM_CCATM_START: 522170530Ssam { 523170530Ssam struct ngm_ccatm_port *arg; 524170530Ssam 525170530Ssam if (msg->header.arglen != sizeof(*arg)) { 526170530Ssam error = EINVAL; 527170530Ssam break; 528170530Ssam } 529170530Ssam arg = (struct ngm_ccatm_port *)msg->data; 530170530Ssam error = cc_port_start(priv->data, arg->port); 531170530Ssam break; 532170530Ssam } 533178354Ssam 534178354Ssam case NGM_CCATM_GETSTATE: 535191552Ssam { 536191552Ssam struct ngm_ccatm_port *arg; 537191552Ssam int state; 538178354Ssam 539191552Ssam if (msg->header.arglen != sizeof(*arg)) { 540191552Ssam error = EINVAL; 541178354Ssam break; 542178354Ssam } 543178354Ssam arg = (struct ngm_ccatm_port *)msg->data; 544178354Ssam error = cc_port_isrunning(priv->data, arg->port, 545178354Ssam &state); 546178354Ssam if (error == 0) { 547178354Ssam NG_MKRESPONSE(resp, msg, sizeof(uint32_t), 548178354Ssam M_NOWAIT); 549178354Ssam if (resp == NULL) { 550178354Ssam error = ENOMEM; 551191552Ssam break; 552178354Ssam } 553191552Ssam *(uint32_t *)resp->data = state; 554191552Ssam } 555178354Ssam break; 556178354Ssam } 557178354Ssam 558170530Ssam case NGM_CCATM_GET_ADDRESSES: 559170530Ssam { 560170530Ssam struct ngm_ccatm_port *arg; 561191552Ssam 562170530Ssam if (msg->header.arglen != sizeof(*arg)) { 563205277Srpaulo error = EINVAL; 564170530Ssam break; 565178354Ssam } 566170530Ssam arg = (struct ngm_ccatm_port *)msg->data; 567170530Ssam error = ng_ccatm_get_addresses(node, arg->port, msg, 568170530Ssam &resp); 569170530Ssam break; 570170530Ssam } 571183247Ssam 572170530Ssam case NGM_CCATM_CLEAR: 573170530Ssam { 574170530Ssam struct ngm_ccatm_port *arg; 575170530Ssam 576170530Ssam if (msg->header.arglen != sizeof(*arg)) { 577183247Ssam error = EINVAL; 578192468Ssam break; 579192468Ssam } 580170530Ssam arg = (struct ngm_ccatm_port *)msg->data; 581170530Ssam error = cc_port_clear(priv->data, arg->port); 582170530Ssam break; 583170530Ssam } 584170530Ssam 585170530Ssam case NGM_CCATM_ADDRESS_REGISTERED: 586170530Ssam { 587170530Ssam struct ngm_ccatm_addr_req *arg; 588170530Ssam 589170530Ssam if (msg->header.arglen != sizeof(*arg)) { 590170530Ssam error = EINVAL; 591170530Ssam break; 592170530Ssam } 593178354Ssam arg = (struct ngm_ccatm_addr_req *)msg->data; 594170530Ssam error = cc_addr_register(priv->data, arg->port, 595170530Ssam &arg->addr); 596170530Ssam break; 597170530Ssam } 598170530Ssam 599170530Ssam case NGM_CCATM_ADDRESS_UNREGISTERED: 600170530Ssam { 601170530Ssam struct ngm_ccatm_addr_req *arg; 602170530Ssam 603170530Ssam if (msg->header.arglen != sizeof(*arg)) { 604170530Ssam error = EINVAL; 605170530Ssam break; 606170530Ssam } 607170530Ssam arg = (struct ngm_ccatm_addr_req *)msg->data; 608170530Ssam error = cc_addr_unregister(priv->data, arg->port, 609170530Ssam &arg->addr); 610170530Ssam break; 611170530Ssam } 612170530Ssam 613170530Ssam case NGM_CCATM_GET_PORT_PARAM: 614170530Ssam { 615170530Ssam struct ngm_ccatm_port *arg; 616170530Ssam 617170530Ssam if (msg->header.arglen != sizeof(*arg)) { 618170530Ssam error = EINVAL; 619170530Ssam break; 620170530Ssam } 621170530Ssam arg = (struct ngm_ccatm_port *)msg->data; 622170530Ssam NG_MKRESPONSE(resp, msg, sizeof(struct atm_port_info), 623178354Ssam M_NOWAIT); 624170530Ssam if (resp == NULL) { 625173273Ssam error = ENOMEM; 626173273Ssam break; 627173273Ssam } 628173273Ssam error = cc_port_get_param(priv->data, arg->port, 629173273Ssam (struct atm_port_info *)resp->data); 630178354Ssam if (error != 0) { 631170530Ssam free(resp, M_NETGRAPH_MSG); 632170530Ssam resp = NULL; 633173273Ssam } 634170530Ssam break; 635173273Ssam } 636170530Ssam 637170530Ssam case NGM_CCATM_SET_PORT_PARAM: 638173273Ssam { 639170530Ssam struct atm_port_info *arg; 640178354Ssam 641170530Ssam if (msg->header.arglen != sizeof(*arg)) { 642170530Ssam error = EINVAL; 643170530Ssam break; 644173273Ssam } 645170530Ssam arg = (struct atm_port_info *)msg->data; 646170530Ssam error = cc_port_set_param(priv->data, arg); 647170530Ssam break; 648170530Ssam } 649170530Ssam 650173273Ssam case NGM_CCATM_GET_PORTLIST: 651178354Ssam { 652173273Ssam struct ngm_ccatm_portlist *arg; 653170530Ssam u_int n, *ports; 654173273Ssam 655170530Ssam if (msg->header.arglen != 0) { 656170530Ssam error = EINVAL; 657170530Ssam break; 658173273Ssam } 659170530Ssam error = cc_port_getlist(priv->data, &n, &ports); 660170530Ssam if (error != 0) 661173273Ssam break; 662173273Ssam 663173273Ssam NG_MKRESPONSE(resp, msg, sizeof(*arg) + 664173273Ssam n * sizeof(arg->ports[0]), M_NOWAIT); 665173273Ssam if (resp == NULL) { 666173273Ssam free(ports, M_NG_CCATM); 667173273Ssam error = ENOMEM; 668173273Ssam break; 669178354Ssam } 670173273Ssam arg = (struct ngm_ccatm_portlist *)resp->data; 671173273Ssam 672173273Ssam arg->nports = 0; 673173273Ssam for (arg->nports = 0; arg->nports < n; arg->nports++) 674173273Ssam arg->ports[arg->nports] = ports[arg->nports]; 675173273Ssam free(ports, M_NG_CCATM); 676173273Ssam break; 677173273Ssam } 678173273Ssam 679173273Ssam case NGM_CCATM_SETLOG: 680173273Ssam { 681173273Ssam uint32_t log_level; 682173273Ssam 683173273Ssam log_level = cc_get_log(priv->data); 684173273Ssam if (msg->header.arglen != 0) { 685173273Ssam if (msg->header.arglen != sizeof(log_level)) { 686173273Ssam error = EINVAL; 687173273Ssam break; 688178354Ssam } 689173273Ssam cc_set_log(priv->data, *(uint32_t *)msg->data); 690173273Ssam } 691173273Ssam 692173273Ssam NG_MKRESPONSE(resp, msg, sizeof(uint32_t), M_NOWAIT); 693173273Ssam if (resp == NULL) { 694173273Ssam error = ENOMEM; 695173273Ssam if (msg->header.arglen != 0) 696173273Ssam cc_set_log(priv->data, log_level); 697173273Ssam break; 698173273Ssam } 699173273Ssam *(uint32_t *)resp->data = log_level; 700173273Ssam break; 701173273Ssam } 702173273Ssam 703178354Ssam case NGM_CCATM_RESET: 704178354Ssam if (msg->header.arglen != 0) { 705178354Ssam error = EINVAL; 706178354Ssam break; 707173273Ssam } 708173273Ssam 709173273Ssam if (priv->hook_cnt != 0) { 710173273Ssam error = EBUSY; 711173273Ssam break; 712173273Ssam } 713173273Ssam cc_reset(priv->data); 714173273Ssam break; 715173273Ssam 716173273Ssam case NGM_CCATM_GET_EXSTAT: 717173273Ssam { 718173273Ssam struct atm_exstatus s; 719173273Ssam struct atm_exstatus_ep *eps; 720178354Ssam struct atm_exstatus_port *ports; 721173273Ssam struct atm_exstatus_conn *conns; 722173273Ssam struct atm_exstatus_party *parties; 723173273Ssam size_t offs; 724173273Ssam 725173273Ssam if (msg->header.arglen != 0) { 726173273Ssam error = EINVAL; 727173273Ssam break; 728173273Ssam } 729173273Ssam error = cc_get_extended_status(priv->data, 730173273Ssam &s, &eps, &ports, &conns, &parties); 731173273Ssam if (error != 0) 732170530Ssam break; 733170530Ssam 734170530Ssam offs = sizeof(s) + s.neps * sizeof(*eps) + 735173273Ssam s.nports * sizeof(*ports) + 736170530Ssam s.nconns * sizeof(*conns) + 737170530Ssam s.nparties * sizeof(*parties); 738170530Ssam 739170530Ssam NG_MKRESPONSE(resp, msg, offs, M_NOWAIT); 740170530Ssam if (resp == NULL) { 741170530Ssam error = ENOMEM; 742170530Ssam break; 743170530Ssam } 744173273Ssam 745173273Ssam memcpy(resp->data, &s, sizeof(s)); 746178354Ssam offs = sizeof(s); 747170530Ssam 748170530Ssam memcpy(resp->data + offs, eps, 749170530Ssam sizeof(*eps) * s.neps); 750170530Ssam offs += sizeof(*eps) * s.neps; 751170530Ssam 752170530Ssam memcpy(resp->data + offs, ports, 753183247Ssam sizeof(*ports) * s.nports); 754183247Ssam offs += sizeof(*ports) * s.nports; 755170530Ssam 756170530Ssam memcpy(resp->data + offs, conns, 757170530Ssam sizeof(*conns) * s.nconns); 758170530Ssam offs += sizeof(*conns) * s.nconns; 759183247Ssam 760183247Ssam memcpy(resp->data + offs, parties, 761183247Ssam sizeof(*parties) * s.nparties); 762183247Ssam offs += sizeof(*parties) * s.nparties; 763183247Ssam 764183247Ssam free(eps, M_NG_CCATM); 765183247Ssam free(ports, M_NG_CCATM); 766193840Ssam free(conns, M_NG_CCATM); 767173273Ssam free(parties, M_NG_CCATM); 768173273Ssam break; 769173273Ssam } 770173273Ssam 771170530Ssam default: 772170530Ssam error = EINVAL; 773170530Ssam break; 774170530Ssam 775170530Ssam } 776173273Ssam break; 777170530Ssam 778182827Ssam default: 779182827Ssam error = EINVAL; 780182827Ssam break; 781182827Ssam 782182827Ssam } 783182827Ssam 784182827Ssam NG_RESPOND_MSG(error, node, item, resp); 785182827Ssam NG_FREE_MSG(msg); 786182827Ssam return (error); 787182827Ssam} 788182827Ssam 789182827Ssam/************************************************************ 790182827Ssam * 791182827Ssam * New hook arrival 792182827Ssam */ 793173273Ssamstatic int 794173273Ssamng_ccatm_newhook(node_p node, hook_p hook, const char *name) 795170530Ssam{ 796170530Ssam struct ccnode *priv = NG_NODE_PRIVATE(node); 797170530Ssam struct ccport *port; 798170530Ssam struct ccuser *user; 799170530Ssam struct cchook *hd; 800170530Ssam u_long lport; 801170530Ssam char *end; 802170530Ssam 803170530Ssam if (strncmp(name, "uni", 3) == 0) { 804170530Ssam /* 805170530Ssam * This is a UNI hook. Should be a new port. 806173273Ssam */ 807170530Ssam if (name[3] == '\0') 808170530Ssam return (EINVAL); 809170530Ssam lport = strtoul(name + 3, &end, 10); 810170530Ssam if (*end != '\0' || lport == 0 || lport > 0xffffffff) 811170530Ssam return (EINVAL); 812170530Ssam 813173273Ssam hd = malloc(sizeof(*hd), M_NG_CCATM, M_NOWAIT); 814170530Ssam if (hd == NULL) 815170530Ssam return (ENOMEM); 816170530Ssam hd->is_uni = 1; 817173273Ssam hd->node = priv; 818170530Ssam hd->hook = hook; 819170530Ssam 820170530Ssam port = cc_port_create(priv->data, hd, (u_int)lport); 821173273Ssam if (port == NULL) { 822170530Ssam free(hd, M_NG_CCATM); 823173273Ssam return (ENOMEM); 824205277Srpaulo } 825173273Ssam hd->inst = port; 826173273Ssam 827173273Ssam NG_HOOK_SET_PRIVATE(hook, hd); 828173273Ssam NG_HOOK_SET_RCVDATA(hook, ng_ccatm_rcvuni); 829173273Ssam NG_HOOK_FORCE_QUEUE(hook); 830173273Ssam 831173273Ssam priv->hook_cnt++; 832173273Ssam 833173273Ssam return (0); 834173273Ssam } 835173273Ssam 836173273Ssam if (strcmp(name, "dump") == 0) { 837170530Ssam priv->dump = hook; 838173273Ssam NG_HOOK_SET_RCVDATA(hook, ng_ccatm_rcvdump); 839173273Ssam return (0); 840173273Ssam } 841173273Ssam 842173273Ssam if (strcmp(name, "manage") == 0) { 843170530Ssam priv->manage = hook; 844173273Ssam NG_HOOK_SET_RCVDATA(hook, ng_ccatm_rcvmanage); 845173273Ssam return (0); 846173273Ssam } 847173273Ssam 848173273Ssam /* 849173273Ssam * User hook 850173273Ssam */ 851173273Ssam hd = malloc(sizeof(*hd), M_NG_CCATM, M_NOWAIT); 852178354Ssam if (hd == NULL) 853173273Ssam return (ENOMEM); 854173273Ssam hd->is_uni = 0; 855173273Ssam hd->node = priv; 856173273Ssam hd->hook = hook; 857173273Ssam 858173273Ssam user = cc_user_create(priv->data, hd, NG_HOOK_NAME(hook)); 859173273Ssam if (user == NULL) { 860173273Ssam free(hd, M_NG_CCATM); 861173273Ssam return (ENOMEM); 862173273Ssam } 863173273Ssam 864173273Ssam hd->inst = user; 865173273Ssam NG_HOOK_SET_PRIVATE(hook, hd); 866173273Ssam NG_HOOK_FORCE_QUEUE(hook); 867173273Ssam 868173273Ssam priv->hook_cnt++; 869173273Ssam 870173273Ssam return (0); 871178354Ssam} 872173273Ssam 873178354Ssam/* 874173273Ssam * Disconnect a hook 875173273Ssam */ 876173273Ssamstatic int 877173273Ssamng_ccatm_disconnect(hook_p hook) 878173273Ssam{ 879178354Ssam node_p node = NG_HOOK_NODE(hook); 880173273Ssam struct ccnode *priv = NG_NODE_PRIVATE(node); 881173273Ssam struct cchook *hd = NG_HOOK_PRIVATE(hook); 882173273Ssam 883173273Ssam if (hook == priv->dump) { 884173273Ssam priv->dump = NULL; 885173273Ssam 886173273Ssam } else if (hook == priv->manage) { 887173273Ssam priv->manage = NULL; 888173273Ssam cc_unmanage(priv->data); 889205277Srpaulo 890173273Ssam } else { 891178354Ssam if (hd->is_uni) 892173273Ssam cc_port_destroy(hd->inst, 0); 893170530Ssam else 894173273Ssam cc_user_destroy(hd->inst); 895170530Ssam 896178354Ssam free(hd, M_NG_CCATM); 897170530Ssam NG_HOOK_SET_PRIVATE(hook, NULL); 898173273Ssam 899173273Ssam priv->hook_cnt--; 900173273Ssam 901173273Ssam cc_work(hd->node->data); 902173273Ssam } 903173273Ssam 904173273Ssam /* 905173273Ssam * When the number of hooks drops to zero, delete the node. 906173273Ssam */ 907173273Ssam if (NG_NODE_NUMHOOKS(node) == 0 && NG_NODE_IS_VALID(node)) 908173273Ssam ng_rmnode_self(node); 909173273Ssam 910170530Ssam return (0); 911170530Ssam} 912173273Ssam 913205277Srpaulo/************************************************************ 914170530Ssam * 915178354Ssam * Receive data from user hook 916173273Ssam */ 917178354Ssamstatic int 918173273Ssamng_ccatm_rcvdata(hook_p hook, item_p item) 919173273Ssam{ 920173273Ssam struct cchook *hd = NG_HOOK_PRIVATE(hook); 921173273Ssam struct uni_msg *msg; 922178354Ssam struct mbuf *m; 923173273Ssam struct ccatm_op op; 924170530Ssam int err; 925173273Ssam 926170530Ssam NGI_GET_M(item, m); 927173273Ssam NG_FREE_ITEM(item); 928173273Ssam 929170530Ssam if ((err = uni_msg_unpack_mbuf(m, &msg)) != 0) { 930170530Ssam m_freem(m); 931170530Ssam return (err); 932170530Ssam } 933170530Ssam m_freem(m); 934170530Ssam 935173273Ssam if (uni_msg_len(msg) < sizeof(op)) { 936170530Ssam printf("%s: packet too short\n", __func__); 937170530Ssam uni_msg_destroy(msg); 938170530Ssam return (EINVAL); 939170530Ssam } 940178354Ssam 941170530Ssam bcopy(msg->b_rptr, &op, sizeof(op)); 942170530Ssam msg->b_rptr += sizeof(op); 943170530Ssam 944170530Ssam err = cc_user_signal(hd->inst, op.op, msg); 945170530Ssam cc_work(hd->node->data); 946173273Ssam return (err); 947173273Ssam} 948178354Ssam 949173273Ssam/* 950173273Ssam * Pack a header and a data area into an mbuf chain 951178354Ssam */ 952173273Ssamstatic struct mbuf * 953173273Ssampack_buf(void *h, size_t hlen, void *t, size_t tlen) 954170530Ssam{ 955170530Ssam struct mbuf *m, *m0, *last; 956170530Ssam u_char *buf = (u_char *)t; 957170530Ssam size_t n; 958170530Ssam 959170530Ssam /* header should fit into a normal mbuf */ 960170530Ssam MGETHDR(m0, M_NOWAIT, MT_DATA); 961170530Ssam if (m0 == NULL) 962178354Ssam return NULL; 963170530Ssam 964170530Ssam KASSERT(hlen <= MHLEN, ("hlen > MHLEN")); 965178354Ssam 966170530Ssam bcopy(h, m0->m_data, hlen); 967170530Ssam m0->m_len = hlen; 968178354Ssam m0->m_pkthdr.len = hlen; 969170530Ssam 970173273Ssam last = m0; 971173273Ssam while ((n = tlen) != 0) { 972170530Ssam if (n > MLEN) { 973170530Ssam m = m_getcl(M_NOWAIT, MT_DATA, 0); 974173273Ssam if (n > MCLBYTES) 975170530Ssam n = MCLBYTES; 976173273Ssam } else 977205277Srpaulo MGET(m, M_NOWAIT, MT_DATA); 978170530Ssam 979178354Ssam if(m == NULL) 980173273Ssam goto drop; 981170530Ssam 982173273Ssam last->m_next = m; 983173273Ssam last = m; 984178354Ssam 985173273Ssam bcopy(buf, m->m_data, n); 986173273Ssam buf += n; 987173273Ssam tlen -= n; 988173273Ssam m->m_len = n; 989173273Ssam m0->m_pkthdr.len += n; 990173273Ssam } 991173273Ssam 992173273Ssam return (m0); 993173273Ssam 994170530Ssam drop: 995173273Ssam m_freem(m0); 996170530Ssam return NULL; 997173273Ssam} 998205277Srpaulo 999170530Ssam/* 1000178354Ssam * Send an indication to the user. 1001173273Ssam */ 1002173273Ssamstatic void 1003173273Ssamng_ccatm_send_user(struct ccuser *user, void *uarg, u_int op, 1004173273Ssam void *val, size_t len) 1005173273Ssam{ 1006173273Ssam struct cchook *hd = uarg; 1007178354Ssam struct mbuf *m; 1008173273Ssam struct ccatm_op h; 1009170530Ssam int error; 1010170530Ssam 1011170530Ssam h.op = op; 1012170530Ssam m = pack_buf(&h, sizeof(h), val, len); 1013170530Ssam if (m == NULL) 1014170530Ssam return; 1015170530Ssam 1016170530Ssam NG_SEND_DATA_ONLY(error, hd->hook, m); 1017170530Ssam if (error != 0) 1018183254Ssam printf("%s: error=%d\n", __func__, error); 1019170530Ssam} 1020170530Ssam 1021170530Ssam/* 1022170530Ssam * Send a response to the user. 1023173273Ssam */ 1024173273Ssamstatic void 1025173273Ssamng_ccatm_respond_user(struct ccuser *user, void *uarg, int err, u_int data, 1026173273Ssam void *val, size_t len) 1027173273Ssam{ 1028173273Ssam struct cchook *hd = uarg; 1029173273Ssam struct mbuf *m; 1030173273Ssam struct { 1031170530Ssam struct ccatm_op op; 1032170530Ssam struct atm_resp resp; 1033170530Ssam } resp; 1034184280Ssam int error; 1035173273Ssam 1036170530Ssam resp.op.op = ATMOP_RESP; 1037173273Ssam resp.resp.resp = err; 1038170530Ssam resp.resp.data = data; 1039170530Ssam m = pack_buf(&resp, sizeof(resp), val, len); 1040170530Ssam if (m == NULL) 1041170530Ssam return; 1042170530Ssam 1043170530Ssam NG_SEND_DATA_ONLY(error, hd->hook, m); 1044170530Ssam if (error != 0) 1045170530Ssam printf("%s: error=%d\n", __func__, error); 1046170530Ssam} 1047191552Ssam 1048170530Ssam/* 1049170530Ssam * Receive data from UNI. 1050170530Ssam */ 1051170530Ssamstatic int 1052170530Ssamng_ccatm_rcvuni(hook_p hook, item_p item) 1053170530Ssam{ 1054170530Ssam struct cchook *hd = NG_HOOK_PRIVATE(hook); 1055184280Ssam struct uni_msg *msg; 1056184280Ssam struct uni_arg arg; 1057170530Ssam struct mbuf *m; 1058170530Ssam int err; 1059191552Ssam 1060170530Ssam NGI_GET_M(item, m); 1061170530Ssam NG_FREE_ITEM(item); 1062182828Ssam 1063170530Ssam if ((err = uni_msg_unpack_mbuf(m, &msg)) != 0) { 1064170530Ssam m_freem(m); 1065178354Ssam return (err); 1066178354Ssam } 1067178354Ssam m_freem(m); 1068178354Ssam 1069178354Ssam if (uni_msg_len(msg) < sizeof(arg)) { 1070178354Ssam printf("%s: packet too short\n", __func__); 1071178354Ssam uni_msg_destroy(msg); 1072178354Ssam return (EINVAL); 1073178354Ssam } 1074178354Ssam 1075178354Ssam bcopy(msg->b_rptr, &arg, sizeof(arg)); 1076178354Ssam msg->b_rptr += sizeof(arg); 1077178354Ssam 1078178354Ssam if (arg.sig == UNIAPI_ERROR) { 1079178354Ssam if (uni_msg_len(msg) != sizeof(struct uniapi_error)) { 1080178354Ssam printf("%s: bad UNIAPI_ERROR size %zu\n", __func__, 1081178354Ssam uni_msg_len(msg)); 1082178354Ssam uni_msg_destroy(msg); 1083178354Ssam return (EINVAL); 1084178354Ssam } 1085178354Ssam err = cc_uni_response(hd->inst, arg.cookie, 1086178354Ssam ((struct uniapi_error *)msg->b_rptr)->reason, 1087178354Ssam ((struct uniapi_error *)msg->b_rptr)->state); 1088178354Ssam uni_msg_destroy(msg); 1089178354Ssam } else 1090178354Ssam err = cc_uni_signal(hd->inst, arg.cookie, arg.sig, msg); 1091178354Ssam 1092178354Ssam cc_work(hd->node->data); 1093178354Ssam return (err); 1094178354Ssam} 1095178354Ssam 1096178354Ssam/* 1097178354Ssam * Uarg is the port's uarg. 1098178354Ssam */ 1099178354Ssamstatic void 1100178354Ssamng_ccatm_send_uni(struct ccconn *conn, void *uarg, u_int op, u_int cookie, 1101178354Ssam struct uni_msg *msg) 1102178354Ssam{ 1103178354Ssam struct cchook *hd = uarg; 1104173273Ssam struct uni_arg arg; 1105173273Ssam struct mbuf *m; 1106173273Ssam int error; 1107173273Ssam 1108173273Ssam arg.sig = op; 1109173273Ssam arg.cookie = cookie; 1110173273Ssam 1111173273Ssam m = uni_msg_pack_mbuf(msg, &arg, sizeof(arg)); 1112173273Ssam uni_msg_destroy(msg); 1113173273Ssam if (m == NULL) 1114173273Ssam return; 1115173273Ssam 1116173273Ssam NG_SEND_DATA_ONLY(error, hd->hook, m); 1117173273Ssam if (error != 0) 1118173273Ssam printf("%s: error=%d\n", __func__, error); 1119173273Ssam} 1120193655Ssam 1121173273Ssam/* 1122193655Ssam * Send a global message to the UNI 1123173273Ssam */ 1124173273Ssamstatic void 1125173273Ssamng_ccatm_send_uni_glob(struct ccport *port, void *uarg, u_int op, u_int cookie, 1126173273Ssam struct uni_msg *msg) 1127173273Ssam{ 1128173273Ssam struct cchook *hd = uarg; 1129173273Ssam struct uni_arg arg; 1130173273Ssam struct mbuf *m; 1131173273Ssam int error; 1132173273Ssam 1133173273Ssam arg.sig = op; 1134173273Ssam arg.cookie = cookie; 1135173273Ssam 1136173273Ssam m = uni_msg_pack_mbuf(msg, &arg, sizeof(arg)); 1137173273Ssam if (msg != NULL) 1138173273Ssam uni_msg_destroy(msg); 1139173273Ssam if (m == NULL) 1140173273Ssam return; 1141173273Ssam 1142173273Ssam NG_SEND_DATA_ONLY(error, hd->hook, m); 1143173273Ssam if (error != 0) 1144173273Ssam printf("%s: error=%d\n", __func__, error); 1145173273Ssam} 1146173273Ssam/* 1147173273Ssam * Receive from ILMID 1148173273Ssam */ 1149173273Ssamstatic int 1150173273Ssamng_ccatm_rcvmanage(hook_p hook, item_p item) 1151173273Ssam{ 1152173273Ssam NG_FREE_ITEM(item); 1153173273Ssam return (0); 1154173273Ssam} 1155173273Ssam 1156178354Ssamstatic int 1157173273Ssamng_ccatm_rcvdump(hook_p hook, item_p item) 1158173273Ssam{ 1159173273Ssam NG_FREE_ITEM(item); 1160193655Ssam return (0); 1161173273Ssam} 1162173273Ssam 1163173273Ssamstatic void 1164173273Ssamng_ccatm_log(const char *fmt, ...) 1165173273Ssam{ 1166173273Ssam va_list ap; 1167173273Ssam 1168173273Ssam va_start(ap, fmt); 1169178354Ssam vprintf(fmt, ap); 1170178354Ssam printf("\n"); 1171173273Ssam va_end(ap); 1172173273Ssam} 1173193655Ssam 1174173273Ssam/* 1175173273Ssam * Loading and unloading of node type 1176173273Ssam */ 1177173273Ssamstatic int 1178173273Ssamng_ccatm_mod_event(module_t mod, int event, void *data) 1179173273Ssam{ 1180173273Ssam int s; 1181173273Ssam int error = 0; 1182193655Ssam 1183173273Ssam s = splnet(); 1184173273Ssam switch (event) { 1185173273Ssam 1186173273Ssam case MOD_LOAD: 1187173273Ssam break; 1188173273Ssam 1189193655Ssam case MOD_UNLOAD: 1190183256Ssam break; 1191183256Ssam 1192173273Ssam default: 1193173273Ssam error = EOPNOTSUPP; 1194173273Ssam break; 1195173273Ssam } 1196173273Ssam splx(s); 1197173273Ssam return (error); 1198173273Ssam} 1199173273Ssam