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 $
35 * ATM call control and API
38 #include <sys/cdefs.h>
39 __FBSDID("$FreeBSD: src/sys/netgraph/atm/ccatm/ng_ccatm.c,v 1.3 2006/09/30 12:37:43 netchild Exp $");
41 #include <sys/param.h>
42 #include <sys/systm.h>
43 #include <sys/kernel.h>
44 #include <sys/malloc.h>
46 #include <sys/errno.h>
47 #include <sys/socket.h>
48 #include <sys/socketvar.h>
50 #include <machine/stdarg.h>
52 #include <netgraph/ng_message.h>
53 #include <netgraph/netgraph.h>
54 #include <netgraph/ng_parse.h>
55 #include <netnatm/unimsg.h>
56 #include <netnatm/msg/unistruct.h>
57 #include <netnatm/api/unisap.h>
58 #include <netnatm/sig/unidef.h>
59 #include <netgraph/atm/ngatmbase.h>
60 #include <netgraph/atm/ng_uni.h>
61 #include <netnatm/api/atmapi.h>
62 #include <netgraph/atm/ng_ccatm.h>
63 #include <netnatm/api/ccatm.h>
65 MODULE_DEPEND(ng_ccatm
, ngatmbase
, 1, 1, 1);
67 MALLOC_DEFINE(M_NG_CCATM
, "ng_ccatm", "netgraph uni api node");
70 * Command structure parsing
74 static const struct ng_parse_fixedarray_info ng_ccatm_esi_type_info
=
76 static const struct ng_parse_type ng_ccatm_esi_type
= {
77 &ng_parse_fixedarray_type
,
78 &ng_ccatm_esi_type_info
82 static const struct ng_parse_struct_field ng_ccatm_atm_port_type_info
[] =
83 NGM_CCATM_ATM_PORT_INFO
;
84 static const struct ng_parse_type ng_ccatm_atm_port_type
= {
85 &ng_parse_struct_type
,
86 ng_ccatm_atm_port_type_info
90 static const struct ng_parse_struct_field ng_ccatm_port_type_info
[] =
92 static const struct ng_parse_type ng_ccatm_port_type
= {
93 &ng_parse_struct_type
,
94 ng_ccatm_port_type_info
97 /* the ADDRESS array itself */
98 static const struct ng_parse_fixedarray_info ng_ccatm_addr_array_type_info
=
99 NGM_CCATM_ADDR_ARRAY_INFO
;
100 static const struct ng_parse_type ng_ccatm_addr_array_type
= {
101 &ng_parse_fixedarray_type
,
102 &ng_ccatm_addr_array_type_info
106 static const struct ng_parse_struct_field ng_ccatm_uni_addr_type_info
[] =
107 NGM_CCATM_UNI_ADDR_INFO
;
108 static const struct ng_parse_type ng_ccatm_uni_addr_type
= {
109 &ng_parse_struct_type
,
110 ng_ccatm_uni_addr_type_info
113 /* ADDRESS request */
114 static const struct ng_parse_struct_field ng_ccatm_addr_req_type_info
[] =
115 NGM_CCATM_ADDR_REQ_INFO
;
116 static const struct ng_parse_type ng_ccatm_addr_req_type
= {
117 &ng_parse_struct_type
,
118 ng_ccatm_addr_req_type_info
121 /* ADDRESS var-array */
123 ng_ccatm_addr_req_array_getlen(const struct ng_parse_type
*type
,
124 const u_char
*start
, const u_char
*buf
)
126 const struct ngm_ccatm_get_addresses
*p
;
128 p
= (const struct ngm_ccatm_get_addresses
*)
129 (buf
- offsetof(struct ngm_ccatm_get_addresses
, addr
));
132 static const struct ng_parse_array_info ng_ccatm_addr_req_array_type_info
=
133 NGM_CCATM_ADDR_REQ_ARRAY_INFO
;
134 static const struct ng_parse_type ng_ccatm_addr_req_array_type
= {
135 &ng_parse_array_type
,
136 &ng_ccatm_addr_req_array_type_info
139 /* Outer get_ADDRESSes structure */
140 static const struct ng_parse_struct_field ng_ccatm_get_addresses_type_info
[] =
141 NGM_CCATM_GET_ADDRESSES_INFO
;
142 static const struct ng_parse_type ng_ccatm_get_addresses_type
= {
143 &ng_parse_struct_type
,
144 ng_ccatm_get_addresses_type_info
149 ng_ccatm_port_array_getlen(const struct ng_parse_type
*type
,
150 const u_char
*start
, const u_char
*buf
)
152 const struct ngm_ccatm_portlist
*p
;
154 p
= (const struct ngm_ccatm_portlist
*)
155 (buf
- offsetof(struct ngm_ccatm_portlist
, ports
));
158 static const struct ng_parse_array_info ng_ccatm_port_array_type_info
=
159 NGM_CCATM_PORT_ARRAY_INFO
;
160 static const struct ng_parse_type ng_ccatm_port_array_type
= {
161 &ng_parse_array_type
,
162 &ng_ccatm_port_array_type_info
165 /* Portlist structure */
166 static const struct ng_parse_struct_field ng_ccatm_portlist_type_info
[] =
167 NGM_CCATM_PORTLIST_INFO
;
168 static const struct ng_parse_type ng_ccatm_portlist_type
= {
169 &ng_parse_struct_type
,
170 ng_ccatm_portlist_type_info
176 static const struct ng_cmdlist ng_ccatm_cmdlist
[] = {
203 &ng_parse_uint32_type
207 NGM_CCATM_GET_ADDRESSES
,
210 &ng_ccatm_get_addresses_type
221 NGM_CCATM_ADDRESS_REGISTERED
,
223 &ng_ccatm_addr_req_type
,
228 NGM_CCATM_ADDRESS_UNREGISTERED
,
230 &ng_ccatm_addr_req_type
,
235 NGM_CCATM_SET_PORT_PARAM
,
237 &ng_ccatm_atm_port_type
,
242 NGM_CCATM_GET_PORT_PARAM
,
245 &ng_ccatm_atm_port_type
,
249 NGM_CCATM_GET_PORTLIST
,
252 &ng_ccatm_portlist_type
,
258 &ng_parse_hint32_type
,
259 &ng_parse_hint32_type
,
274 static ng_constructor_t ng_ccatm_constructor
;
275 static ng_rcvmsg_t ng_ccatm_rcvmsg
;
276 static ng_shutdown_t ng_ccatm_shutdown
;
277 static ng_newhook_t ng_ccatm_newhook
;
278 static ng_rcvdata_t ng_ccatm_rcvdata
;
279 static ng_disconnect_t ng_ccatm_disconnect
;
280 static int ng_ccatm_mod_event(module_t
, int, void *);
282 static struct ng_type ng_ccatm_typestruct
= {
283 .version
= NG_ABI_VERSION
,
284 .name
= NG_CCATM_NODE_TYPE
,
285 .mod_event
= ng_ccatm_mod_event
,
286 .constructor
= ng_ccatm_constructor
, /* Node constructor */
287 .rcvmsg
= ng_ccatm_rcvmsg
, /* Control messages */
288 .shutdown
= ng_ccatm_shutdown
, /* Node destructor */
289 .newhook
= ng_ccatm_newhook
, /* Arrival of new hook */
290 .rcvdata
= ng_ccatm_rcvdata
, /* receive data */
291 .disconnect
= ng_ccatm_disconnect
, /* disconnect a hook */
292 .cmdlist
= ng_ccatm_cmdlist
,
294 NETGRAPH_INIT(ccatm
, &ng_ccatm_typestruct
);
296 static ng_rcvdata_t ng_ccatm_rcvuni
;
297 static ng_rcvdata_t ng_ccatm_rcvdump
;
298 static ng_rcvdata_t ng_ccatm_rcvmanage
;
304 node_p node
; /* the owning node */
305 hook_p dump
; /* dump hook */
306 hook_p manage
; /* hook to ILMI */
309 struct mbuf
*dump_first
;
310 struct mbuf
*dump_last
; /* first and last mbuf when dumping */
312 u_int hook_cnt
; /* count user and port hooks */
316 * Private UNI hook data
319 int is_uni
; /* true if uni hook, user otherwise */
320 struct ccnode
*node
; /* the owning node */
322 void *inst
; /* port or user */
325 static void ng_ccatm_send_user(struct ccuser
*, void *, u_int
, void *, size_t);
326 static void ng_ccatm_respond_user(struct ccuser
*, void *, int, u_int
,
328 static void ng_ccatm_send_uni(struct ccconn
*, void *, u_int
, u_int
,
330 static void ng_ccatm_send_uni_glob(struct ccport
*, void *, u_int
, u_int
,
332 static void ng_ccatm_log(const char *, ...) __printflike(1, 2);
334 static const struct cc_funcs cc_funcs
= {
335 .send_user
= ng_ccatm_send_user
,
336 .respond_user
= ng_ccatm_respond_user
,
337 .send_uni
= ng_ccatm_send_uni
,
338 .send_uni_glob
= ng_ccatm_send_uni_glob
,
342 /************************************************************
347 ng_ccatm_constructor(node_p node
)
351 priv
= malloc(sizeof(*priv
), M_NG_CCATM
, M_NOWAIT
| M_ZERO
);
356 priv
->data
= cc_create(&cc_funcs
);
357 if (priv
->data
== NULL
) {
358 free(priv
, M_NG_CCATM
);
362 NG_NODE_SET_PRIVATE(node
, priv
);
368 * Destroy a node. The user list is empty here, because all hooks are
369 * previously disconnected. The connection lists may not be empty, because
370 * connections may be waiting for responses from the stack. This also means,
371 * that no orphaned connections will be made by the port_destroy routine.
374 ng_ccatm_shutdown(node_p node
)
376 struct ccnode
*priv
= NG_NODE_PRIVATE(node
);
378 cc_destroy(priv
->data
);
380 free(priv
, M_NG_CCATM
);
381 NG_NODE_SET_PRIVATE(node
, NULL
);
389 * Retrieve the registered addresses for one port or all ports.
390 * Returns an error code or 0 on success.
393 ng_ccatm_get_addresses(node_p node
, uint32_t portno
, struct ng_mesg
*msg
,
394 struct ng_mesg
**resp
)
396 struct ccnode
*priv
= NG_NODE_PRIVATE(node
);
397 struct uni_addr
*addrs
;
399 struct ngm_ccatm_get_addresses
*list
;
404 err
= cc_get_addrs(priv
->data
, portno
, &addrs
, &ports
, &count
);
408 len
= sizeof(*list
) + count
* sizeof(list
->addr
[0]);
409 NG_MKRESPONSE(*resp
, msg
, len
, M_NOWAIT
);
411 free(addrs
, M_NG_CCATM
);
412 free(ports
, M_NG_CCATM
);
415 list
= (struct ngm_ccatm_get_addresses
*)(*resp
)->data
;
418 for (i
= 0; i
< count
; i
++) {
419 list
->addr
[i
].port
= ports
[i
];
420 list
->addr
[i
].addr
= addrs
[i
];
423 free(addrs
, M_NG_CCATM
);
424 free(ports
, M_NG_CCATM
);
430 * Dumper function. Pack the data into an mbuf chain.
433 send_dump(struct ccdata
*data
, void *uarg
, const char *buf
)
436 struct ccnode
*priv
= uarg
;
438 if (priv
->dump
== NULL
) {
439 m
= m_getcl(M_DONTWAIT
, MT_DATA
, M_PKTHDR
);
442 priv
->dump_first
= priv
->dump_last
= m
;
445 m
= m_getcl(M_DONTWAIT
, MT_DATA
, 0);
447 m_freem(priv
->dump_first
);
450 priv
->dump_last
->m_next
= m
;
454 strcpy(m
->m_data
, buf
);
455 priv
->dump_first
->m_pkthdr
.len
+= (m
->m_len
= strlen(buf
));
461 * Dump current status to dump hook
464 ng_ccatm_dump(node_p node
)
466 struct ccnode
*priv
= NG_NODE_PRIVATE(node
);
470 priv
->dump_first
= priv
->dump_last
= NULL
;
471 error
= cc_dump(priv
->data
, MCLBYTES
, send_dump
, priv
);
475 if ((m
= priv
->dump_first
) != NULL
) {
476 priv
->dump_first
= priv
->dump_last
= NULL
;
477 NG_SEND_DATA_ONLY(error
, priv
->dump
, m
);
487 ng_ccatm_rcvmsg(node_p node
, item_p item
, hook_p lasthook
)
489 struct ng_mesg
*resp
= NULL
;
491 struct ccnode
*priv
= NG_NODE_PRIVATE(node
);
494 NGI_GET_MSG(item
, msg
);
496 switch (msg
->header
.typecookie
) {
498 case NGM_CCATM_COOKIE
:
499 switch (msg
->header
.cmd
) {
503 error
= ng_ccatm_dump(node
);
510 struct ngm_ccatm_port
*arg
;
512 if (msg
->header
.arglen
!= sizeof(*arg
)) {
516 arg
= (struct ngm_ccatm_port
*)msg
->data
;
517 error
= cc_port_stop(priv
->data
, arg
->port
);
521 case NGM_CCATM_START
:
523 struct ngm_ccatm_port
*arg
;
525 if (msg
->header
.arglen
!= sizeof(*arg
)) {
529 arg
= (struct ngm_ccatm_port
*)msg
->data
;
530 error
= cc_port_start(priv
->data
, arg
->port
);
534 case NGM_CCATM_GETSTATE
:
536 struct ngm_ccatm_port
*arg
;
539 if (msg
->header
.arglen
!= sizeof(*arg
)) {
543 arg
= (struct ngm_ccatm_port
*)msg
->data
;
544 error
= cc_port_isrunning(priv
->data
, arg
->port
,
547 NG_MKRESPONSE(resp
, msg
, sizeof(uint32_t),
553 *(uint32_t *)resp
->data
= state
;
558 case NGM_CCATM_GET_ADDRESSES
:
560 struct ngm_ccatm_port
*arg
;
562 if (msg
->header
.arglen
!= sizeof(*arg
)) {
566 arg
= (struct ngm_ccatm_port
*)msg
->data
;
567 error
= ng_ccatm_get_addresses(node
, arg
->port
, msg
,
572 case NGM_CCATM_CLEAR
:
574 struct ngm_ccatm_port
*arg
;
576 if (msg
->header
.arglen
!= sizeof(*arg
)) {
580 arg
= (struct ngm_ccatm_port
*)msg
->data
;
581 error
= cc_port_clear(priv
->data
, arg
->port
);
585 case NGM_CCATM_ADDRESS_REGISTERED
:
587 struct ngm_ccatm_addr_req
*arg
;
589 if (msg
->header
.arglen
!= sizeof(*arg
)) {
593 arg
= (struct ngm_ccatm_addr_req
*)msg
->data
;
594 error
= cc_addr_register(priv
->data
, arg
->port
,
599 case NGM_CCATM_ADDRESS_UNREGISTERED
:
601 struct ngm_ccatm_addr_req
*arg
;
603 if (msg
->header
.arglen
!= sizeof(*arg
)) {
607 arg
= (struct ngm_ccatm_addr_req
*)msg
->data
;
608 error
= cc_addr_unregister(priv
->data
, arg
->port
,
613 case NGM_CCATM_GET_PORT_PARAM
:
615 struct ngm_ccatm_port
*arg
;
617 if (msg
->header
.arglen
!= sizeof(*arg
)) {
621 arg
= (struct ngm_ccatm_port
*)msg
->data
;
622 NG_MKRESPONSE(resp
, msg
, sizeof(struct atm_port_info
),
628 error
= cc_port_get_param(priv
->data
, arg
->port
,
629 (struct atm_port_info
*)resp
->data
);
631 free(resp
, M_NETGRAPH_MSG
);
637 case NGM_CCATM_SET_PORT_PARAM
:
639 struct atm_port_info
*arg
;
641 if (msg
->header
.arglen
!= sizeof(*arg
)) {
645 arg
= (struct atm_port_info
*)msg
->data
;
646 error
= cc_port_set_param(priv
->data
, arg
);
650 case NGM_CCATM_GET_PORTLIST
:
652 struct ngm_ccatm_portlist
*arg
;
655 if (msg
->header
.arglen
!= 0) {
659 error
= cc_port_getlist(priv
->data
, &n
, &ports
);
663 NG_MKRESPONSE(resp
, msg
, sizeof(*arg
) +
664 n
* sizeof(arg
->ports
[0]), M_NOWAIT
);
666 free(ports
, M_NG_CCATM
);
670 arg
= (struct ngm_ccatm_portlist
*)resp
->data
;
673 for (arg
->nports
= 0; arg
->nports
< n
; arg
->nports
++)
674 arg
->ports
[arg
->nports
] = ports
[arg
->nports
];
675 free(ports
, M_NG_CCATM
);
679 case NGM_CCATM_SETLOG
:
683 log_level
= cc_get_log(priv
->data
);
684 if (msg
->header
.arglen
!= 0) {
685 if (msg
->header
.arglen
!= sizeof(log_level
)) {
689 cc_set_log(priv
->data
, *(uint32_t *)msg
->data
);
692 NG_MKRESPONSE(resp
, msg
, sizeof(uint32_t), M_NOWAIT
);
695 if (msg
->header
.arglen
!= 0)
696 cc_set_log(priv
->data
, log_level
);
699 *(uint32_t *)resp
->data
= log_level
;
703 case NGM_CCATM_RESET
:
704 if (msg
->header
.arglen
!= 0) {
709 if (priv
->hook_cnt
!= 0) {
713 cc_reset(priv
->data
);
716 case NGM_CCATM_GET_EXSTAT
:
718 struct atm_exstatus s
;
719 struct atm_exstatus_ep
*eps
;
720 struct atm_exstatus_port
*ports
;
721 struct atm_exstatus_conn
*conns
;
722 struct atm_exstatus_party
*parties
;
725 if (msg
->header
.arglen
!= 0) {
729 error
= cc_get_extended_status(priv
->data
,
730 &s
, &eps
, &ports
, &conns
, &parties
);
734 offs
= sizeof(s
) + s
.neps
* sizeof(*eps
) +
735 s
.nports
* sizeof(*ports
) +
736 s
.nconns
* sizeof(*conns
) +
737 s
.nparties
* sizeof(*parties
);
739 NG_MKRESPONSE(resp
, msg
, offs
, M_NOWAIT
);
745 memcpy(resp
->data
, &s
, sizeof(s
));
748 memcpy(resp
->data
+ offs
, eps
,
749 sizeof(*eps
) * s
.neps
);
750 offs
+= sizeof(*eps
) * s
.neps
;
752 memcpy(resp
->data
+ offs
, ports
,
753 sizeof(*ports
) * s
.nports
);
754 offs
+= sizeof(*ports
) * s
.nports
;
756 memcpy(resp
->data
+ offs
, conns
,
757 sizeof(*conns
) * s
.nconns
);
758 offs
+= sizeof(*conns
) * s
.nconns
;
760 memcpy(resp
->data
+ offs
, parties
,
761 sizeof(*parties
) * s
.nparties
);
762 offs
+= sizeof(*parties
) * s
.nparties
;
764 free(eps
, M_NG_CCATM
);
765 free(ports
, M_NG_CCATM
);
766 free(conns
, M_NG_CCATM
);
767 free(parties
, M_NG_CCATM
);
784 NG_RESPOND_MSG(error
, node
, item
, resp
);
789 /************************************************************
794 ng_ccatm_newhook(node_p node
, hook_p hook
, const char *name
)
796 struct ccnode
*priv
= NG_NODE_PRIVATE(node
);
803 if (strncmp(name
, "uni", 3) == 0) {
805 * This is a UNI hook. Should be a new port.
809 lport
= strtoul(name
+ 3, &end
, 10);
810 if (*end
!= '\0' || lport
== 0 || lport
> 0xffffffff)
813 hd
= malloc(sizeof(*hd
), M_NG_CCATM
, M_NOWAIT
);
820 port
= cc_port_create(priv
->data
, hd
, (u_int
)lport
);
822 free(hd
, M_NG_CCATM
);
827 NG_HOOK_SET_PRIVATE(hook
, hd
);
828 NG_HOOK_SET_RCVDATA(hook
, ng_ccatm_rcvuni
);
829 NG_HOOK_FORCE_QUEUE(hook
);
836 if (strcmp(name
, "dump") == 0) {
838 NG_HOOK_SET_RCVDATA(hook
, ng_ccatm_rcvdump
);
842 if (strcmp(name
, "manage") == 0) {
844 NG_HOOK_SET_RCVDATA(hook
, ng_ccatm_rcvmanage
);
851 hd
= malloc(sizeof(*hd
), M_NG_CCATM
, M_NOWAIT
);
858 user
= cc_user_create(priv
->data
, hd
, NG_HOOK_NAME(hook
));
860 free(hd
, M_NG_CCATM
);
865 NG_HOOK_SET_PRIVATE(hook
, hd
);
866 NG_HOOK_FORCE_QUEUE(hook
);
877 ng_ccatm_disconnect(hook_p hook
)
879 node_p node
= NG_HOOK_NODE(hook
);
880 struct ccnode
*priv
= NG_NODE_PRIVATE(node
);
881 struct cchook
*hd
= NG_HOOK_PRIVATE(hook
);
884 if (hook
== priv
->dump
) {
887 } else if (hook
== priv
->manage
) {
889 cc_unmanage(priv
->data
);
893 cc_port_destroy(hd
->inst
, 0);
895 cc_user_destroy(hd
->inst
);
899 free(hd
, M_NG_CCATM
);
900 NG_HOOK_SET_PRIVATE(hook
, NULL
);
908 * When the number of hooks drops to zero, delete the node.
910 if (NG_NODE_NUMHOOKS(node
) == 0 && NG_NODE_IS_VALID(node
))
911 ng_rmnode_self(node
);
916 /************************************************************
918 * Receive data from user hook
921 ng_ccatm_rcvdata(hook_p hook
, item_p item
)
923 struct cchook
*hd
= NG_HOOK_PRIVATE(hook
);
932 if ((err
= uni_msg_unpack_mbuf(m
, &msg
)) != 0) {
938 if (uni_msg_len(msg
) < sizeof(op
)) {
939 printf("%s: packet too short\n", __func__
);
940 uni_msg_destroy(msg
);
944 bcopy(msg
->b_rptr
, &op
, sizeof(op
));
945 msg
->b_rptr
+= sizeof(op
);
947 err
= cc_user_signal(hd
->inst
, op
.op
, msg
);
948 cc_work(hd
->node
->data
);
953 * Pack a header and a data area into an mbuf chain
956 pack_buf(void *h
, size_t hlen
, void *t
, size_t tlen
)
958 struct mbuf
*m
, *m0
, *last
;
959 u_char
*buf
= (u_char
*)t
;
962 /* header should fit into a normal mbuf */
963 MGETHDR(m0
, M_NOWAIT
, MT_DATA
);
967 KASSERT(hlen
<= MHLEN
, ("hlen > MHLEN"));
969 bcopy(h
, m0
->m_data
, hlen
);
971 m0
->m_pkthdr
.len
= hlen
;
974 while ((n
= tlen
) != 0) {
976 m
= m_getcl(M_NOWAIT
, MT_DATA
, 0);
980 MGET(m
, M_NOWAIT
, MT_DATA
);
988 bcopy(buf
, m
->m_data
, n
);
992 m0
->m_pkthdr
.len
+= n
;
1003 * Send an indication to the user.
1006 ng_ccatm_send_user(struct ccuser
*user
, void *uarg
, u_int op
,
1007 void *val
, size_t len
)
1009 struct cchook
*hd
= uarg
;
1015 m
= pack_buf(&h
, sizeof(h
), val
, len
);
1019 NG_SEND_DATA_ONLY(error
, hd
->hook
, m
);
1021 printf("%s: error=%d\n", __func__
, error
);
1025 * Send a response to the user.
1028 ng_ccatm_respond_user(struct ccuser
*user
, void *uarg
, int err
, u_int data
,
1029 void *val
, size_t len
)
1031 struct cchook
*hd
= uarg
;
1035 struct atm_resp resp
;
1039 resp
.op
.op
= ATMOP_RESP
;
1040 resp
.resp
.resp
= err
;
1041 resp
.resp
.data
= data
;
1042 m
= pack_buf(&resp
, sizeof(resp
), val
, len
);
1046 NG_SEND_DATA_ONLY(error
, hd
->hook
, m
);
1048 printf("%s: error=%d\n", __func__
, error
);
1052 * Receive data from UNI.
1055 ng_ccatm_rcvuni(hook_p hook
, item_p item
)
1057 struct cchook
*hd
= NG_HOOK_PRIVATE(hook
);
1058 struct uni_msg
*msg
;
1066 if ((err
= uni_msg_unpack_mbuf(m
, &msg
)) != 0) {
1072 if (uni_msg_len(msg
) < sizeof(arg
)) {
1073 printf("%s: packet too short\n", __func__
);
1074 uni_msg_destroy(msg
);
1078 bcopy(msg
->b_rptr
, &arg
, sizeof(arg
));
1079 msg
->b_rptr
+= sizeof(arg
);
1081 if (arg
.sig
== UNIAPI_ERROR
) {
1082 if (uni_msg_len(msg
) != sizeof(struct uniapi_error
)) {
1083 printf("%s: bad UNIAPI_ERROR size %zu\n", __func__
,
1085 uni_msg_destroy(msg
);
1088 err
= cc_uni_response(hd
->inst
, arg
.cookie
,
1089 ((struct uniapi_error
*)msg
->b_rptr
)->reason
,
1090 ((struct uniapi_error
*)msg
->b_rptr
)->state
);
1091 uni_msg_destroy(msg
);
1093 err
= cc_uni_signal(hd
->inst
, arg
.cookie
, arg
.sig
, msg
);
1095 cc_work(hd
->node
->data
);
1100 * Uarg is the port's uarg.
1103 ng_ccatm_send_uni(struct ccconn
*conn
, void *uarg
, u_int op
, u_int cookie
,
1104 struct uni_msg
*msg
)
1106 struct cchook
*hd
= uarg
;
1112 arg
.cookie
= cookie
;
1114 m
= uni_msg_pack_mbuf(msg
, &arg
, sizeof(arg
));
1115 uni_msg_destroy(msg
);
1119 NG_SEND_DATA_ONLY(error
, hd
->hook
, m
);
1121 printf("%s: error=%d\n", __func__
, error
);
1125 * Send a global message to the UNI
1128 ng_ccatm_send_uni_glob(struct ccport
*port
, void *uarg
, u_int op
, u_int cookie
,
1129 struct uni_msg
*msg
)
1131 struct cchook
*hd
= uarg
;
1137 arg
.cookie
= cookie
;
1139 m
= uni_msg_pack_mbuf(msg
, &arg
, sizeof(arg
));
1141 uni_msg_destroy(msg
);
1145 NG_SEND_DATA_ONLY(error
, hd
->hook
, m
);
1147 printf("%s: error=%d\n", __func__
, error
);
1150 * Receive from ILMID
1153 ng_ccatm_rcvmanage(hook_p hook
, item_p item
)
1160 ng_ccatm_rcvdump(hook_p hook
, item_p item
)
1167 ng_ccatm_log(const char *fmt
, ...)
1178 * Loading and unloading of node type
1181 ng_ccatm_mod_event(module_t mod
, int event
, void *data
)