2 * Copyright (c) 2001-2002
3 * Fraunhofer Institute for Open Communication Systems (FhG Fokus).
5 * Copyright (c) 2003-2004
9 * Author: Harti Brandt <harti@freebsd.org>
11 * Redistribution of this software and documentation and use in source and
12 * binary forms, with or without modification, are permitted provided that
13 * the following conditions are met:
15 * 1. Redistributions of source code or documentation must retain the above
16 * copyright notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
21 * THIS SOFTWARE AND DOCUMENTATION IS PROVIDED BY THE AUTHOR
22 * AND ITS CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
23 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
24 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
25 * THE AUTHOR OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
28 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
29 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
31 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 * $FreeBSD: src/sys/netgraph/atm/ccatm/ng_ccatm.c,v 1.3 2006/09/30 12:37:43 netchild Exp $
34 * $DragonFly: src/sys/netgraph7/atm/ccatm/ng_ccatm.c,v 1.2 2008/06/26 23:05:39 dillon Exp $
35 * $DragonFly: src/sys/netgraph7/atm/ccatm/ng_ccatm.c,v 1.2 2008/06/26 23:05:39 dillon Exp $
37 * ATM call control and API
40 #include <sys/param.h>
41 #include <sys/systm.h>
42 #include <sys/kernel.h>
43 #include <sys/malloc.h>
45 #include <sys/errno.h>
46 #include <sys/socket.h>
47 #include <sys/socketvar.h>
49 #include <machine/stdarg.h>
51 #include "ng_message.h"
54 #include <netnatm/unimsg.h>
55 #include <netnatm/msg/unistruct.h>
56 #include <netnatm/api/unisap.h>
57 #include <netnatm/sig/unidef.h>
58 #include "atm/ngatmbase.h"
59 #include "atm/ng_uni.h"
60 #include <netnatm/api/atmapi.h>
61 #include "atm/ng_ccatm.h"
62 #include <netnatm/api/ccatm.h>
64 MODULE_DEPEND(ng_ccatm, ngatmbase, 1, 1, 1);
66 MALLOC_DEFINE(M_NG_CCATM, "ng_ccatm", "netgraph uni api node");
69 * Command structure parsing
73 static const struct ng_parse_fixedarray_info ng_ccatm_esi_type_info =
75 static const struct ng_parse_type ng_ccatm_esi_type = {
76 &ng_parse_fixedarray_type,
77 &ng_ccatm_esi_type_info
81 static const struct ng_parse_struct_field ng_ccatm_atm_port_type_info[] =
82 NGM_CCATM_ATM_PORT_INFO;
83 static const struct ng_parse_type ng_ccatm_atm_port_type = {
84 &ng_parse_struct_type,
85 ng_ccatm_atm_port_type_info
89 static const struct ng_parse_struct_field ng_ccatm_port_type_info[] =
91 static const struct ng_parse_type ng_ccatm_port_type = {
92 &ng_parse_struct_type,
93 ng_ccatm_port_type_info
96 /* the ADDRESS array itself */
97 static const struct ng_parse_fixedarray_info ng_ccatm_addr_array_type_info =
98 NGM_CCATM_ADDR_ARRAY_INFO;
99 static const struct ng_parse_type ng_ccatm_addr_array_type = {
100 &ng_parse_fixedarray_type,
101 &ng_ccatm_addr_array_type_info
105 static const struct ng_parse_struct_field ng_ccatm_uni_addr_type_info[] =
106 NGM_CCATM_UNI_ADDR_INFO;
107 static const struct ng_parse_type ng_ccatm_uni_addr_type = {
108 &ng_parse_struct_type,
109 ng_ccatm_uni_addr_type_info
112 /* ADDRESS request */
113 static const struct ng_parse_struct_field ng_ccatm_addr_req_type_info[] =
114 NGM_CCATM_ADDR_REQ_INFO;
115 static const struct ng_parse_type ng_ccatm_addr_req_type = {
116 &ng_parse_struct_type,
117 ng_ccatm_addr_req_type_info
120 /* ADDRESS var-array */
122 ng_ccatm_addr_req_array_getlen(const struct ng_parse_type *type,
123 const u_char *start, const u_char *buf)
125 const struct ngm_ccatm_get_addresses *p;
127 p = (const struct ngm_ccatm_get_addresses *)
128 (buf - offsetof(struct ngm_ccatm_get_addresses, addr));
131 static const struct ng_parse_array_info ng_ccatm_addr_req_array_type_info =
132 NGM_CCATM_ADDR_REQ_ARRAY_INFO;
133 static const struct ng_parse_type ng_ccatm_addr_req_array_type = {
134 &ng_parse_array_type,
135 &ng_ccatm_addr_req_array_type_info
138 /* Outer get_ADDRESSes structure */
139 static const struct ng_parse_struct_field ng_ccatm_get_addresses_type_info[] =
140 NGM_CCATM_GET_ADDRESSES_INFO;
141 static const struct ng_parse_type ng_ccatm_get_addresses_type = {
142 &ng_parse_struct_type,
143 ng_ccatm_get_addresses_type_info
148 ng_ccatm_port_array_getlen(const struct ng_parse_type *type,
149 const u_char *start, const u_char *buf)
151 const struct ngm_ccatm_portlist *p;
153 p = (const struct ngm_ccatm_portlist *)
154 (buf - offsetof(struct ngm_ccatm_portlist, ports));
157 static const struct ng_parse_array_info ng_ccatm_port_array_type_info =
158 NGM_CCATM_PORT_ARRAY_INFO;
159 static const struct ng_parse_type ng_ccatm_port_array_type = {
160 &ng_parse_array_type,
161 &ng_ccatm_port_array_type_info
164 /* Portlist structure */
165 static const struct ng_parse_struct_field ng_ccatm_portlist_type_info[] =
166 NGM_CCATM_PORTLIST_INFO;
167 static const struct ng_parse_type ng_ccatm_portlist_type = {
168 &ng_parse_struct_type,
169 ng_ccatm_portlist_type_info
175 static const struct ng_cmdlist ng_ccatm_cmdlist[] = {
202 &ng_parse_uint32_type
206 NGM_CCATM_GET_ADDRESSES,
209 &ng_ccatm_get_addresses_type
220 NGM_CCATM_ADDRESS_REGISTERED,
222 &ng_ccatm_addr_req_type,
227 NGM_CCATM_ADDRESS_UNREGISTERED,
229 &ng_ccatm_addr_req_type,
234 NGM_CCATM_SET_PORT_PARAM,
236 &ng_ccatm_atm_port_type,
241 NGM_CCATM_GET_PORT_PARAM,
244 &ng_ccatm_atm_port_type,
248 NGM_CCATM_GET_PORTLIST,
251 &ng_ccatm_portlist_type,
257 &ng_parse_hint32_type,
258 &ng_parse_hint32_type,
273 static ng_constructor_t ng_ccatm_constructor;
274 static ng_rcvmsg_t ng_ccatm_rcvmsg;
275 static ng_shutdown_t ng_ccatm_shutdown;
276 static ng_newhook_t ng_ccatm_newhook;
277 static ng_rcvdata_t ng_ccatm_rcvdata;
278 static ng_disconnect_t ng_ccatm_disconnect;
279 static int ng_ccatm_mod_event(module_t, int, void *);
281 static struct ng_type ng_ccatm_typestruct = {
282 .version = NG_ABI_VERSION,
283 .name = NG_CCATM_NODE_TYPE,
284 .mod_event = ng_ccatm_mod_event,
285 .constructor = ng_ccatm_constructor, /* Node constructor */
286 .rcvmsg = ng_ccatm_rcvmsg, /* Control messages */
287 .shutdown = ng_ccatm_shutdown, /* Node destructor */
288 .newhook = ng_ccatm_newhook, /* Arrival of new hook */
289 .rcvdata = ng_ccatm_rcvdata, /* receive data */
290 .disconnect = ng_ccatm_disconnect, /* disconnect a hook */
291 .cmdlist = ng_ccatm_cmdlist,
293 NETGRAPH_INIT(ccatm, &ng_ccatm_typestruct);
295 static ng_rcvdata_t ng_ccatm_rcvuni;
296 static ng_rcvdata_t ng_ccatm_rcvdump;
297 static ng_rcvdata_t ng_ccatm_rcvmanage;
303 node_p node; /* the owning node */
304 hook_p dump; /* dump hook */
305 hook_p manage; /* hook to ILMI */
308 struct mbuf *dump_first;
309 struct mbuf *dump_last; /* first and last mbuf when dumping */
311 u_int hook_cnt; /* count user and port hooks */
315 * Private UNI hook data
318 int is_uni; /* true if uni hook, user otherwise */
319 struct ccnode *node; /* the owning node */
321 void *inst; /* port or user */
324 static void ng_ccatm_send_user(struct ccuser *, void *, u_int, void *, size_t);
325 static void ng_ccatm_respond_user(struct ccuser *, void *, int, u_int,
327 static void ng_ccatm_send_uni(struct ccconn *, void *, u_int, u_int,
329 static void ng_ccatm_send_uni_glob(struct ccport *, void *, u_int, u_int,
331 static void ng_ccatm_log(const char *, ...) __printflike(1, 2);
333 static const struct cc_funcs cc_funcs = {
334 .send_user = ng_ccatm_send_user,
335 .respond_user = ng_ccatm_respond_user,
336 .send_uni = ng_ccatm_send_uni,
337 .send_uni_glob = ng_ccatm_send_uni_glob,
341 /************************************************************
346 ng_ccatm_constructor(node_p node)
350 priv = kmalloc(sizeof(*priv), M_NG_CCATM, M_WAITOK | M_NULLOK | M_ZERO);
355 priv->data = cc_create(&cc_funcs);
356 if (priv->data == NULL) {
357 kfree(priv, M_NG_CCATM);
361 NG_NODE_SET_PRIVATE(node, priv);
367 * Destroy a node. The user list is empty here, because all hooks are
368 * previously disconnected. The connection lists may not be empty, because
369 * connections may be waiting for responses from the stack. This also means,
370 * that no orphaned connections will be made by the port_destroy routine.
373 ng_ccatm_shutdown(node_p node)
375 struct ccnode *priv = NG_NODE_PRIVATE(node);
377 cc_destroy(priv->data);
379 kfree(priv, M_NG_CCATM);
380 NG_NODE_SET_PRIVATE(node, NULL);
388 * Retrieve the registered addresses for one port or all ports.
389 * Returns an error code or 0 on success.
392 ng_ccatm_get_addresses(node_p node, uint32_t portno, struct ng_mesg *msg,
393 struct ng_mesg **resp)
395 struct ccnode *priv = NG_NODE_PRIVATE(node);
396 struct uni_addr *addrs;
398 struct ngm_ccatm_get_addresses *list;
403 err = cc_get_addrs(priv->data, portno, &addrs, &ports, &count);
407 len = sizeof(*list) + count * sizeof(list->addr[0]);
408 NG_MKRESPONSE(*resp, msg, len, M_WAITOK | M_NULLOK);
410 kfree(addrs, M_NG_CCATM);
411 kfree(ports, M_NG_CCATM);
414 list = (struct ngm_ccatm_get_addresses *)(*resp)->data;
417 for (i = 0; i < count; i++) {
418 list->addr[i].port = ports[i];
419 list->addr[i].addr = addrs[i];
422 kfree(addrs, M_NG_CCATM);
423 kfree(ports, M_NG_CCATM);
429 * Dumper function. Pack the data into an mbuf chain.
432 send_dump(struct ccdata *data, void *uarg, const char *buf)
435 struct ccnode *priv = uarg;
437 if (priv->dump == NULL) {
438 m = m_getcl(MB_DONTWAIT, MT_DATA, M_PKTHDR);
441 priv->dump_first = priv->dump_last = m;
444 m = m_getcl(MB_DONTWAIT, MT_DATA, 0);
446 m_freem(priv->dump_first);
449 priv->dump_last->m_next = m;
453 strcpy(m->m_data, buf);
454 priv->dump_first->m_pkthdr.len += (m->m_len = strlen(buf));
460 * Dump current status to dump hook
463 ng_ccatm_dump(node_p node)
465 struct ccnode *priv = NG_NODE_PRIVATE(node);
469 priv->dump_first = priv->dump_last = NULL;
470 error = cc_dump(priv->data, MCLBYTES, send_dump, priv);
474 if ((m = priv->dump_first) != NULL) {
475 priv->dump_first = priv->dump_last = NULL;
476 NG_SEND_DATA_ONLY(error, priv->dump, m);
486 ng_ccatm_rcvmsg(node_p node, item_p item, hook_p lasthook)
488 struct ng_mesg *resp = NULL;
490 struct ccnode *priv = NG_NODE_PRIVATE(node);
493 NGI_GET_MSG(item, msg);
495 switch (msg->header.typecookie) {
497 case NGM_CCATM_COOKIE:
498 switch (msg->header.cmd) {
502 error = ng_ccatm_dump(node);
509 struct ngm_ccatm_port *arg;
511 if (msg->header.arglen != sizeof(*arg)) {
515 arg = (struct ngm_ccatm_port *)msg->data;
516 error = cc_port_stop(priv->data, arg->port);
520 case NGM_CCATM_START:
522 struct ngm_ccatm_port *arg;
524 if (msg->header.arglen != sizeof(*arg)) {
528 arg = (struct ngm_ccatm_port *)msg->data;
529 error = cc_port_start(priv->data, arg->port);
533 case NGM_CCATM_GETSTATE:
535 struct ngm_ccatm_port *arg;
538 if (msg->header.arglen != sizeof(*arg)) {
542 arg = (struct ngm_ccatm_port *)msg->data;
543 error = cc_port_isrunning(priv->data, arg->port,
546 NG_MKRESPONSE(resp, msg, sizeof(uint32_t),
547 M_WAITOK | M_NULLOK);
552 *(uint32_t *)resp->data = state;
557 case NGM_CCATM_GET_ADDRESSES:
559 struct ngm_ccatm_port *arg;
561 if (msg->header.arglen != sizeof(*arg)) {
565 arg = (struct ngm_ccatm_port *)msg->data;
566 error = ng_ccatm_get_addresses(node, arg->port, msg,
571 case NGM_CCATM_CLEAR:
573 struct ngm_ccatm_port *arg;
575 if (msg->header.arglen != sizeof(*arg)) {
579 arg = (struct ngm_ccatm_port *)msg->data;
580 error = cc_port_clear(priv->data, arg->port);
584 case NGM_CCATM_ADDRESS_REGISTERED:
586 struct ngm_ccatm_addr_req *arg;
588 if (msg->header.arglen != sizeof(*arg)) {
592 arg = (struct ngm_ccatm_addr_req *)msg->data;
593 error = cc_addr_register(priv->data, arg->port,
598 case NGM_CCATM_ADDRESS_UNREGISTERED:
600 struct ngm_ccatm_addr_req *arg;
602 if (msg->header.arglen != sizeof(*arg)) {
606 arg = (struct ngm_ccatm_addr_req *)msg->data;
607 error = cc_addr_unregister(priv->data, arg->port,
612 case NGM_CCATM_GET_PORT_PARAM:
614 struct ngm_ccatm_port *arg;
616 if (msg->header.arglen != sizeof(*arg)) {
620 arg = (struct ngm_ccatm_port *)msg->data;
621 NG_MKRESPONSE(resp, msg, sizeof(struct atm_port_info),
622 M_WAITOK | M_NULLOK);
627 error = cc_port_get_param(priv->data, arg->port,
628 (struct atm_port_info *)resp->data);
630 kfree(resp, M_NETGRAPH_MSG);
636 case NGM_CCATM_SET_PORT_PARAM:
638 struct atm_port_info *arg;
640 if (msg->header.arglen != sizeof(*arg)) {
644 arg = (struct atm_port_info *)msg->data;
645 error = cc_port_set_param(priv->data, arg);
649 case NGM_CCATM_GET_PORTLIST:
651 struct ngm_ccatm_portlist *arg;
654 if (msg->header.arglen != 0) {
658 error = cc_port_getlist(priv->data, &n, &ports);
662 NG_MKRESPONSE(resp, msg, sizeof(*arg) +
663 n * sizeof(arg->ports[0]), M_WAITOK | M_NULLOK);
665 kfree(ports, M_NG_CCATM);
669 arg = (struct ngm_ccatm_portlist *)resp->data;
672 for (arg->nports = 0; arg->nports < n; arg->nports++)
673 arg->ports[arg->nports] = ports[arg->nports];
674 kfree(ports, M_NG_CCATM);
678 case NGM_CCATM_SETLOG:
682 log_level = cc_get_log(priv->data);
683 if (msg->header.arglen != 0) {
684 if (msg->header.arglen != sizeof(log_level)) {
688 cc_set_log(priv->data, *(uint32_t *)msg->data);
691 NG_MKRESPONSE(resp, msg, sizeof(uint32_t), M_WAITOK | M_NULLOK);
694 if (msg->header.arglen != 0)
695 cc_set_log(priv->data, log_level);
698 *(uint32_t *)resp->data = log_level;
702 case NGM_CCATM_RESET:
703 if (msg->header.arglen != 0) {
708 if (priv->hook_cnt != 0) {
712 cc_reset(priv->data);
715 case NGM_CCATM_GET_EXSTAT:
717 struct atm_exstatus s;
718 struct atm_exstatus_ep *eps;
719 struct atm_exstatus_port *ports;
720 struct atm_exstatus_conn *conns;
721 struct atm_exstatus_party *parties;
724 if (msg->header.arglen != 0) {
728 error = cc_get_extended_status(priv->data,
729 &s, &eps, &ports, &conns, &parties);
733 offs = sizeof(s) + s.neps * sizeof(*eps) +
734 s.nports * sizeof(*ports) +
735 s.nconns * sizeof(*conns) +
736 s.nparties * sizeof(*parties);
738 NG_MKRESPONSE(resp, msg, offs, M_WAITOK | M_NULLOK);
744 memcpy(resp->data, &s, sizeof(s));
747 memcpy(resp->data + offs, eps,
748 sizeof(*eps) * s.neps);
749 offs += sizeof(*eps) * s.neps;
751 memcpy(resp->data + offs, ports,
752 sizeof(*ports) * s.nports);
753 offs += sizeof(*ports) * s.nports;
755 memcpy(resp->data + offs, conns,
756 sizeof(*conns) * s.nconns);
757 offs += sizeof(*conns) * s.nconns;
759 memcpy(resp->data + offs, parties,
760 sizeof(*parties) * s.nparties);
761 offs += sizeof(*parties) * s.nparties;
763 kfree(eps, M_NG_CCATM);
764 kfree(ports, M_NG_CCATM);
765 kfree(conns, M_NG_CCATM);
766 kfree(parties, M_NG_CCATM);
783 NG_RESPOND_MSG(error, node, item, resp);
788 /************************************************************
793 ng_ccatm_newhook(node_p node, hook_p hook, const char *name)
795 struct ccnode *priv = NG_NODE_PRIVATE(node);
802 if (strncmp(name, "uni", 3) == 0) {
804 * This is a UNI hook. Should be a new port.
808 lport = strtoul(name + 3, &end, 10);
809 if (*end != '\0' || lport == 0 || lport > 0xffffffff)
812 hd = kmalloc(sizeof(*hd), M_NG_CCATM, M_WAITOK | M_NULLOK);
819 port = cc_port_create(priv->data, hd, (u_int)lport);
821 kfree(hd, M_NG_CCATM);
826 NG_HOOK_SET_PRIVATE(hook, hd);
827 NG_HOOK_SET_RCVDATA(hook, ng_ccatm_rcvuni);
828 NG_HOOK_FORCE_QUEUE(hook);
835 if (strcmp(name, "dump") == 0) {
837 NG_HOOK_SET_RCVDATA(hook, ng_ccatm_rcvdump);
841 if (strcmp(name, "manage") == 0) {
843 NG_HOOK_SET_RCVDATA(hook, ng_ccatm_rcvmanage);
850 hd = kmalloc(sizeof(*hd), M_NG_CCATM, M_WAITOK | M_NULLOK);
857 user = cc_user_create(priv->data, hd, NG_HOOK_NAME(hook));
859 kfree(hd, M_NG_CCATM);
864 NG_HOOK_SET_PRIVATE(hook, hd);
865 NG_HOOK_FORCE_QUEUE(hook);
876 ng_ccatm_disconnect(hook_p hook)
878 node_p node = NG_HOOK_NODE(hook);
879 struct ccnode *priv = NG_NODE_PRIVATE(node);
880 struct cchook *hd = NG_HOOK_PRIVATE(hook);
883 if (hook == priv->dump) {
886 } else if (hook == priv->manage) {
888 cc_unmanage(priv->data);
892 cc_port_destroy(hd->inst, 0);
894 cc_user_destroy(hd->inst);
898 kfree(hd, M_NG_CCATM);
899 NG_HOOK_SET_PRIVATE(hook, NULL);
907 * When the number of hooks drops to zero, delete the node.
909 if (NG_NODE_NUMHOOKS(node) == 0 && NG_NODE_IS_VALID(node))
910 ng_rmnode_self(node);
915 /************************************************************
917 * Receive data from user hook
920 ng_ccatm_rcvdata(hook_p hook, item_p item)
922 struct cchook *hd = NG_HOOK_PRIVATE(hook);
931 if ((err = uni_msg_unpack_mbuf(m, &msg)) != 0) {
937 if (uni_msg_len(msg) < sizeof(op)) {
938 printf("%s: packet too short\n", __func__);
939 uni_msg_destroy(msg);
943 bcopy(msg->b_rptr, &op, sizeof(op));
944 msg->b_rptr += sizeof(op);
946 err = cc_user_signal(hd->inst, op.op, msg);
947 cc_work(hd->node->data);
952 * Pack a header and a data area into an mbuf chain
955 pack_buf(void *h, size_t hlen, void *t, size_t tlen)
957 struct mbuf *m, *m0, *last;
958 u_char *buf = (u_char *)t;
961 /* header should fit into a normal mbuf */
962 MGETHDR(m0, MB_DONTWAIT, MT_DATA);
966 KASSERT(hlen <= MHLEN, ("hlen > MHLEN"));
968 bcopy(h, m0->m_data, hlen);
970 m0->m_pkthdr.len = hlen;
973 while ((n = tlen) != 0) {
975 m = m_getcl(MB_DONTWAIT, MT_DATA, 0);
979 MGET(m, MB_DONTWAIT, MT_DATA);
987 bcopy(buf, m->m_data, n);
991 m0->m_pkthdr.len += n;
1002 * Send an indication to the user.
1005 ng_ccatm_send_user(struct ccuser *user, void *uarg, u_int op,
1006 void *val, size_t len)
1008 struct cchook *hd = uarg;
1014 m = pack_buf(&h, sizeof(h), val, len);
1018 NG_SEND_DATA_ONLY(error, hd->hook, m);
1020 printf("%s: error=%d\n", __func__, error);
1024 * Send a response to the user.
1027 ng_ccatm_respond_user(struct ccuser *user, void *uarg, int err, u_int data,
1028 void *val, size_t len)
1030 struct cchook *hd = uarg;
1034 struct atm_resp resp;
1038 resp.op.op = ATMOP_RESP;
1039 resp.resp.resp = err;
1040 resp.resp.data = data;
1041 m = pack_buf(&resp, sizeof(resp), val, len);
1045 NG_SEND_DATA_ONLY(error, hd->hook, m);
1047 printf("%s: error=%d\n", __func__, error);
1051 * Receive data from UNI.
1054 ng_ccatm_rcvuni(hook_p hook, item_p item)
1056 struct cchook *hd = NG_HOOK_PRIVATE(hook);
1057 struct uni_msg *msg;
1065 if ((err = uni_msg_unpack_mbuf(m, &msg)) != 0) {
1071 if (uni_msg_len(msg) < sizeof(arg)) {
1072 printf("%s: packet too short\n", __func__);
1073 uni_msg_destroy(msg);
1077 bcopy(msg->b_rptr, &arg, sizeof(arg));
1078 msg->b_rptr += sizeof(arg);
1080 if (arg.sig == UNIAPI_ERROR) {
1081 if (uni_msg_len(msg) != sizeof(struct uniapi_error)) {
1082 printf("%s: bad UNIAPI_ERROR size %zu\n", __func__,
1084 uni_msg_destroy(msg);
1087 err = cc_uni_response(hd->inst, arg.cookie,
1088 ((struct uniapi_error *)msg->b_rptr)->reason,
1089 ((struct uniapi_error *)msg->b_rptr)->state);
1090 uni_msg_destroy(msg);
1092 err = cc_uni_signal(hd->inst, arg.cookie, arg.sig, msg);
1094 cc_work(hd->node->data);
1099 * Uarg is the port's uarg.
1102 ng_ccatm_send_uni(struct ccconn *conn, void *uarg, u_int op, u_int cookie,
1103 struct uni_msg *msg)
1105 struct cchook *hd = uarg;
1111 arg.cookie = cookie;
1113 m = uni_msg_pack_mbuf(msg, &arg, sizeof(arg));
1114 uni_msg_destroy(msg);
1118 NG_SEND_DATA_ONLY(error, hd->hook, m);
1120 printf("%s: error=%d\n", __func__, error);
1124 * Send a global message to the UNI
1127 ng_ccatm_send_uni_glob(struct ccport *port, void *uarg, u_int op, u_int cookie,
1128 struct uni_msg *msg)
1130 struct cchook *hd = uarg;
1136 arg.cookie = cookie;
1138 m = uni_msg_pack_mbuf(msg, &arg, sizeof(arg));
1140 uni_msg_destroy(msg);
1144 NG_SEND_DATA_ONLY(error, hd->hook, m);
1146 printf("%s: error=%d\n", __func__, error);
1149 * Receive from ILMID
1152 ng_ccatm_rcvmanage(hook_p hook, item_p item)
1159 ng_ccatm_rcvdump(hook_p hook, item_p item)
1166 ng_ccatm_log(const char *fmt, ...)
1177 * Loading and unloading of node type
1180 ng_ccatm_mod_event(module_t mod, int event, void *data)