1139823Simp/*-
2133578Sharti * Copyright (c) 2001-2002
3133578Sharti *	Fraunhofer Institute for Open Communication Systems (FhG Fokus).
4133578Sharti *	All rights reserved.
5133578Sharti * Copyright (c) 2003-2004
6133578Sharti *	Hartmut Brandt
7133578Sharti *	All rights reserved.
8133578Sharti *
9133578Sharti * Author: Harti Brandt <harti@freebsd.org>
10133578Sharti *
11133578Sharti * Redistribution of this software and documentation and use in source and
12133578Sharti * binary forms, with or without modification, are permitted provided that
13133578Sharti * the following conditions are met:
14133578Sharti *
15133578Sharti * 1. Redistributions of source code or documentation must retain the above
16133578Sharti *    copyright notice, this list of conditions and the following disclaimer.
17133578Sharti * 2. Redistributions in binary form must reproduce the above copyright
18133578Sharti *    notice, this list of conditions and the following disclaimer in the
19133578Sharti *    documentation and/or other materials provided with the distribution.
20133578Sharti *
21133578Sharti * THIS SOFTWARE AND DOCUMENTATION IS PROVIDED BY THE AUTHOR
22133578Sharti * AND ITS CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
23133578Sharti * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
24133578Sharti * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
25133578Sharti * THE AUTHOR OR ITS CONTRIBUTORS  BE LIABLE FOR ANY DIRECT, INDIRECT,
26133578Sharti * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27133578Sharti * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
28133578Sharti * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
29133578Sharti * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30133578Sharti * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
31133578Sharti * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32133578Sharti *
33133578Sharti * $FreeBSD$
34133578Sharti *
35133578Sharti * ATM call control and API
36133578Sharti */
37133578Sharti
38133578Sharti#include <sys/cdefs.h>
39133578Sharti__FBSDID("$FreeBSD$");
40133578Sharti
41133578Sharti#include <sys/param.h>
42133578Sharti#include <sys/systm.h>
43133578Sharti#include <sys/kernel.h>
44133578Sharti#include <sys/malloc.h>
45133578Sharti#include <sys/mbuf.h>
46133578Sharti#include <sys/errno.h>
47133578Sharti#include <sys/socket.h>
48133578Sharti#include <sys/socketvar.h>
49133578Sharti#include <sys/sbuf.h>
50133578Sharti#include <machine/stdarg.h>
51133578Sharti
52133578Sharti#include <netgraph/ng_message.h>
53133578Sharti#include <netgraph/netgraph.h>
54133578Sharti#include <netgraph/ng_parse.h>
55133578Sharti#include <netnatm/unimsg.h>
56133578Sharti#include <netnatm/msg/unistruct.h>
57133578Sharti#include <netnatm/api/unisap.h>
58133578Sharti#include <netnatm/sig/unidef.h>
59133578Sharti#include <netgraph/atm/ngatmbase.h>
60133578Sharti#include <netgraph/atm/ng_uni.h>
61133578Sharti#include <netnatm/api/atmapi.h>
62133578Sharti#include <netgraph/atm/ng_ccatm.h>
63133578Sharti#include <netnatm/api/ccatm.h>
64133578Sharti
65133578ShartiMODULE_DEPEND(ng_ccatm, ngatmbase, 1, 1, 1);
66133578Sharti
67133578ShartiMALLOC_DEFINE(M_NG_CCATM, "ng_ccatm", "netgraph uni api node");
68133578Sharti
69133578Sharti/*
70133578Sharti * Command structure parsing
71133578Sharti */
72133578Sharti
73133578Sharti/* ESI */
74133578Shartistatic const struct ng_parse_fixedarray_info ng_ccatm_esi_type_info =
75133578Sharti    NGM_CCATM_ESI_INFO;
76133578Shartistatic const struct ng_parse_type ng_ccatm_esi_type = {
77133578Sharti	&ng_parse_fixedarray_type,
78133578Sharti	&ng_ccatm_esi_type_info
79133578Sharti};
80133578Sharti
81133578Sharti/* PORT PARAMETERS */
82133578Shartistatic const struct ng_parse_struct_field ng_ccatm_atm_port_type_info[] =
83133578Sharti    NGM_CCATM_ATM_PORT_INFO;
84133578Shartistatic const struct ng_parse_type ng_ccatm_atm_port_type = {
85133578Sharti	&ng_parse_struct_type,
86133578Sharti	ng_ccatm_atm_port_type_info
87133578Sharti};
88133578Sharti
89133578Sharti/* PORT structure */
90133578Shartistatic const struct ng_parse_struct_field ng_ccatm_port_type_info[] =
91133578Sharti    NGM_CCATM_PORT_INFO;
92133578Shartistatic const struct ng_parse_type ng_ccatm_port_type = {
93133578Sharti	&ng_parse_struct_type,
94133578Sharti	ng_ccatm_port_type_info
95133578Sharti};
96133578Sharti
97133578Sharti/* the ADDRESS array itself */
98133578Shartistatic const struct ng_parse_fixedarray_info ng_ccatm_addr_array_type_info =
99133578Sharti    NGM_CCATM_ADDR_ARRAY_INFO;
100133578Shartistatic const struct ng_parse_type ng_ccatm_addr_array_type = {
101133578Sharti	&ng_parse_fixedarray_type,
102133578Sharti	&ng_ccatm_addr_array_type_info
103133578Sharti};
104133578Sharti
105133578Sharti/* one ADDRESS */
106133578Shartistatic const struct ng_parse_struct_field ng_ccatm_uni_addr_type_info[] =
107133578Sharti    NGM_CCATM_UNI_ADDR_INFO;
108133578Shartistatic const struct ng_parse_type ng_ccatm_uni_addr_type = {
109133578Sharti	&ng_parse_struct_type,
110133578Sharti	ng_ccatm_uni_addr_type_info
111133578Sharti};
112133578Sharti
113133578Sharti/* ADDRESS request */
114133578Shartistatic const struct ng_parse_struct_field ng_ccatm_addr_req_type_info[] =
115133578Sharti    NGM_CCATM_ADDR_REQ_INFO;
116133578Shartistatic const struct ng_parse_type ng_ccatm_addr_req_type = {
117133578Sharti	&ng_parse_struct_type,
118133578Sharti	ng_ccatm_addr_req_type_info
119133578Sharti};
120133578Sharti
121133578Sharti/* ADDRESS var-array */
122133578Shartistatic int
123133578Sharting_ccatm_addr_req_array_getlen(const struct ng_parse_type *type,
124133578Sharti    const u_char *start, const u_char *buf)
125133578Sharti{
126133578Sharti	const struct ngm_ccatm_get_addresses *p;
127133578Sharti
128133578Sharti	p = (const struct ngm_ccatm_get_addresses *)
129133578Sharti	    (buf - offsetof(struct ngm_ccatm_get_addresses, addr));
130133578Sharti	return (p->count);
131133578Sharti}
132133578Shartistatic const struct ng_parse_array_info ng_ccatm_addr_req_array_type_info =
133133578Sharti    NGM_CCATM_ADDR_REQ_ARRAY_INFO;
134133578Shartistatic const struct ng_parse_type ng_ccatm_addr_req_array_type = {
135133578Sharti	&ng_parse_array_type,
136133578Sharti	&ng_ccatm_addr_req_array_type_info
137133578Sharti};
138133578Sharti
139133578Sharti/* Outer get_ADDRESSes structure */
140133578Shartistatic const struct ng_parse_struct_field ng_ccatm_get_addresses_type_info[] =
141133578Sharti    NGM_CCATM_GET_ADDRESSES_INFO;
142133578Shartistatic const struct ng_parse_type ng_ccatm_get_addresses_type = {
143133578Sharti	&ng_parse_struct_type,
144133578Sharti	ng_ccatm_get_addresses_type_info
145133578Sharti};
146133578Sharti
147133578Sharti/* Port array */
148133578Shartistatic int
149133578Sharting_ccatm_port_array_getlen(const struct ng_parse_type *type,
150133578Sharti    const u_char *start, const u_char *buf)
151133578Sharti{
152133578Sharti	const struct ngm_ccatm_portlist *p;
153133578Sharti
154133578Sharti	p = (const struct ngm_ccatm_portlist *)
155133578Sharti	    (buf - offsetof(struct ngm_ccatm_portlist, ports));
156133578Sharti	return (p->nports);
157133578Sharti}
158133578Shartistatic const struct ng_parse_array_info ng_ccatm_port_array_type_info =
159133578Sharti    NGM_CCATM_PORT_ARRAY_INFO;
160133578Shartistatic const struct ng_parse_type ng_ccatm_port_array_type = {
161133578Sharti	&ng_parse_array_type,
162133578Sharti	&ng_ccatm_port_array_type_info
163133578Sharti};
164133578Sharti
165133578Sharti/* Portlist structure */
166133578Shartistatic const struct ng_parse_struct_field ng_ccatm_portlist_type_info[] =
167133578Sharti    NGM_CCATM_PORTLIST_INFO;
168133578Shartistatic const struct ng_parse_type ng_ccatm_portlist_type = {
169133578Sharti	&ng_parse_struct_type,
170133578Sharti	ng_ccatm_portlist_type_info
171133578Sharti};
172133578Sharti
173133578Sharti/*
174133578Sharti * Command list
175133578Sharti */
176133578Shartistatic const struct ng_cmdlist ng_ccatm_cmdlist[] = {
177133578Sharti	{
178133578Sharti	  NGM_CCATM_COOKIE,
179133578Sharti	  NGM_CCATM_DUMP,
180133578Sharti	  "dump",
181133578Sharti	  NULL,
182133578Sharti	  NULL
183133578Sharti	},
184133578Sharti	{
185133578Sharti	  NGM_CCATM_COOKIE,
186133578Sharti	  NGM_CCATM_STOP,
187133578Sharti	  "stop",
188133578Sharti	  &ng_ccatm_port_type,
189133578Sharti	  NULL
190133578Sharti	},
191133578Sharti	{
192133578Sharti	  NGM_CCATM_COOKIE,
193133578Sharti	  NGM_CCATM_START,
194133578Sharti	  "start",
195133578Sharti	  &ng_ccatm_port_type,
196133578Sharti	  NULL
197133578Sharti	},
198133578Sharti	{
199133578Sharti	  NGM_CCATM_COOKIE,
200133578Sharti	  NGM_CCATM_GETSTATE,
201133578Sharti	  "getstate",
202133578Sharti	  &ng_ccatm_port_type,
203133578Sharti	  &ng_parse_uint32_type
204133578Sharti	},
205133578Sharti	{
206133578Sharti	  NGM_CCATM_COOKIE,
207133578Sharti	  NGM_CCATM_GET_ADDRESSES,
208133578Sharti	  "get_addresses",
209133578Sharti	  &ng_ccatm_port_type,
210133578Sharti	  &ng_ccatm_get_addresses_type
211133578Sharti	},
212133578Sharti	{
213133578Sharti	  NGM_CCATM_COOKIE,
214133578Sharti	  NGM_CCATM_CLEAR,
215133578Sharti	  "clear",
216133578Sharti	  &ng_ccatm_port_type,
217133578Sharti	  NULL
218133578Sharti	},
219133578Sharti	{
220133578Sharti	  NGM_CCATM_COOKIE,
221133578Sharti	  NGM_CCATM_ADDRESS_REGISTERED,
222133578Sharti	  "address_reg",
223133578Sharti	  &ng_ccatm_addr_req_type,
224133578Sharti	  NULL
225133578Sharti	},
226133578Sharti	{
227133578Sharti	  NGM_CCATM_COOKIE,
228133578Sharti	  NGM_CCATM_ADDRESS_UNREGISTERED,
229133578Sharti	  "address_unreg",
230133578Sharti	  &ng_ccatm_addr_req_type,
231133578Sharti	  NULL
232133578Sharti	},
233133578Sharti	{
234133578Sharti	  NGM_CCATM_COOKIE,
235133578Sharti	  NGM_CCATM_SET_PORT_PARAM,
236133578Sharti	  "set_port_param",
237133578Sharti	  &ng_ccatm_atm_port_type,
238133578Sharti	  NULL
239133578Sharti	},
240133578Sharti	{
241133578Sharti	  NGM_CCATM_COOKIE,
242133578Sharti	  NGM_CCATM_GET_PORT_PARAM,
243133578Sharti	  "get_port_param",
244133578Sharti	  &ng_ccatm_port_type,
245133578Sharti	  &ng_ccatm_atm_port_type,
246133578Sharti	},
247133578Sharti	{
248133578Sharti	  NGM_CCATM_COOKIE,
249133578Sharti	  NGM_CCATM_GET_PORTLIST,
250133578Sharti	  "get_portlist",
251133578Sharti	  NULL,
252133578Sharti	  &ng_ccatm_portlist_type,
253133578Sharti	},
254133578Sharti	{
255133578Sharti	  NGM_CCATM_COOKIE,
256133578Sharti	  NGM_CCATM_SETLOG,
257133578Sharti	  "setlog",
258133578Sharti	  &ng_parse_hint32_type,
259133578Sharti	  &ng_parse_hint32_type,
260133578Sharti	},
261133578Sharti	{
262133578Sharti	  NGM_CCATM_COOKIE,
263133578Sharti	  NGM_CCATM_RESET,
264133578Sharti	  "reset",
265133578Sharti	  NULL,
266133578Sharti	  NULL,
267133578Sharti	},
268133578Sharti	{ 0 }
269133578Sharti};
270133578Sharti
271133578Sharti/*
272133578Sharti * Module data
273133578Sharti */
274133578Shartistatic ng_constructor_t		ng_ccatm_constructor;
275133578Shartistatic ng_rcvmsg_t		ng_ccatm_rcvmsg;
276133578Shartistatic ng_shutdown_t		ng_ccatm_shutdown;
277133578Shartistatic ng_newhook_t		ng_ccatm_newhook;
278133578Shartistatic ng_rcvdata_t		ng_ccatm_rcvdata;
279133578Shartistatic ng_disconnect_t		ng_ccatm_disconnect;
280133578Shartistatic int ng_ccatm_mod_event(module_t, int, void *);
281133578Sharti
282133578Shartistatic struct ng_type ng_ccatm_typestruct = {
283133578Sharti	.version =	NG_ABI_VERSION,
284133578Sharti	.name =		NG_CCATM_NODE_TYPE,
285133578Sharti	.mod_event =	ng_ccatm_mod_event,
286133578Sharti	.constructor =	ng_ccatm_constructor,	/* Node constructor */
287133578Sharti	.rcvmsg =	ng_ccatm_rcvmsg,	/* Control messages */
288133578Sharti	.shutdown =	ng_ccatm_shutdown,	/* Node destructor */
289133578Sharti	.newhook =	ng_ccatm_newhook,	/* Arrival of new hook */
290133578Sharti	.rcvdata =	ng_ccatm_rcvdata,	/* receive data */
291133578Sharti	.disconnect =	ng_ccatm_disconnect,	/* disconnect a hook */
292133578Sharti	.cmdlist =	ng_ccatm_cmdlist,
293133578Sharti};
294133578ShartiNETGRAPH_INIT(ccatm, &ng_ccatm_typestruct);
295133578Sharti
296133578Shartistatic ng_rcvdata_t	ng_ccatm_rcvuni;
297133578Shartistatic ng_rcvdata_t	ng_ccatm_rcvdump;
298133578Shartistatic ng_rcvdata_t	ng_ccatm_rcvmanage;
299133578Sharti
300133578Sharti/*
301133578Sharti * Private node data.
302133578Sharti */
303133578Shartistruct ccnode {
304133578Sharti	node_p	node;		/* the owning node */
305133578Sharti	hook_p	dump;		/* dump hook */
306133578Sharti	hook_p	manage;		/* hook to ILMI */
307133578Sharti
308133578Sharti	struct ccdata *data;
309133578Sharti	struct mbuf *dump_first;
310133578Sharti	struct mbuf *dump_last;	/* first and last mbuf when dumping */
311133578Sharti
312133578Sharti	u_int	hook_cnt;	/* count user and port hooks */
313133578Sharti};
314133578Sharti
315133578Sharti/*
316133578Sharti * Private UNI hook data
317133578Sharti */
318133578Shartistruct cchook {
319133578Sharti	int		is_uni;	/* true if uni hook, user otherwise */
320133578Sharti	struct ccnode	*node;	/* the owning node */
321133578Sharti	hook_p		hook;
322133578Sharti	void		*inst;	/* port or user */
323133578Sharti};
324133578Sharti
325133578Shartistatic void ng_ccatm_send_user(struct ccuser *, void *, u_int, void *, size_t);
326133578Shartistatic void ng_ccatm_respond_user(struct ccuser *, void *, int, u_int,
327133578Sharti    void *, size_t);
328133578Shartistatic void ng_ccatm_send_uni(struct ccconn *, void *, u_int, u_int,
329133578Sharti    struct uni_msg *);
330133578Shartistatic void ng_ccatm_send_uni_glob(struct ccport *, void *, u_int, u_int,
331133578Sharti    struct uni_msg *);
332133578Shartistatic void ng_ccatm_log(const char *, ...) __printflike(1, 2);
333133578Sharti
334133578Shartistatic const struct cc_funcs cc_funcs = {
335133578Sharti	.send_user =		ng_ccatm_send_user,
336133578Sharti	.respond_user =		ng_ccatm_respond_user,
337133578Sharti	.send_uni =		ng_ccatm_send_uni,
338133578Sharti	.send_uni_glob =	ng_ccatm_send_uni_glob,
339133578Sharti	.log =			ng_ccatm_log,
340133578Sharti};
341133578Sharti
342133578Sharti/************************************************************
343133578Sharti *
344133578Sharti * Create a new node
345133578Sharti */
346133578Shartistatic int
347133578Sharting_ccatm_constructor(node_p node)
348133578Sharti{
349133578Sharti	struct ccnode *priv;
350133578Sharti
351220768Sglebius	priv = malloc(sizeof(*priv), M_NG_CCATM, M_WAITOK | M_ZERO);
352133578Sharti
353133578Sharti	priv->node = node;
354133578Sharti	priv->data = cc_create(&cc_funcs);
355133578Sharti	if (priv->data == NULL) {
356133578Sharti		free(priv, M_NG_CCATM);
357133578Sharti		return (ENOMEM);
358133578Sharti	}
359133578Sharti
360133578Sharti	NG_NODE_SET_PRIVATE(node, priv);
361133578Sharti
362133578Sharti	return (0);
363133578Sharti}
364133578Sharti
365133578Sharti/*
366133578Sharti * Destroy a node. The user list is empty here, because all hooks are
367133578Sharti * previously disconnected. The connection lists may not be empty, because
368133578Sharti * connections may be waiting for responses from the stack. This also means,
369133578Sharti * that no orphaned connections will be made by the port_destroy routine.
370133578Sharti */
371133578Shartistatic int
372133578Sharting_ccatm_shutdown(node_p node)
373133578Sharti{
374133578Sharti	struct ccnode *priv = NG_NODE_PRIVATE(node);
375133578Sharti
376133578Sharti	cc_destroy(priv->data);
377133578Sharti
378133578Sharti	free(priv, M_NG_CCATM);
379133578Sharti	NG_NODE_SET_PRIVATE(node, NULL);
380133578Sharti
381133578Sharti	NG_NODE_UNREF(node);
382133578Sharti
383133578Sharti	return (0);
384133578Sharti}
385133578Sharti
386133578Sharti/*
387133578Sharti * Retrieve the registered addresses for one port or all ports.
388133578Sharti * Returns an error code or 0 on success.
389133578Sharti */
390133578Shartistatic int
391133578Sharting_ccatm_get_addresses(node_p node, uint32_t portno, struct ng_mesg *msg,
392133578Sharti    struct ng_mesg **resp)
393133578Sharti{
394133578Sharti	struct ccnode *priv = NG_NODE_PRIVATE(node);
395133578Sharti	struct uni_addr *addrs;
396133578Sharti	u_int *ports;
397133578Sharti	struct ngm_ccatm_get_addresses *list;
398133578Sharti	u_int count, i;
399133578Sharti	size_t len;
400133578Sharti	int err;
401133578Sharti
402133578Sharti	err = cc_get_addrs(priv->data, portno, &addrs, &ports, &count);
403133578Sharti	if (err != 0)
404133578Sharti		return (err);
405133578Sharti
406133578Sharti	len = sizeof(*list) + count * sizeof(list->addr[0]);
407133578Sharti	NG_MKRESPONSE(*resp, msg, len, M_NOWAIT);
408133578Sharti	if (*resp == NULL) {
409133578Sharti		free(addrs, M_NG_CCATM);
410133578Sharti		free(ports, M_NG_CCATM);
411133578Sharti		return (ENOMEM);
412133578Sharti	}
413133578Sharti	list = (struct ngm_ccatm_get_addresses *)(*resp)->data;
414133578Sharti
415133578Sharti	list->count = count;
416133578Sharti	for (i = 0; i < count; i++) {
417133578Sharti		list->addr[i].port = ports[i];
418133578Sharti		list->addr[i].addr = addrs[i];
419133578Sharti	}
420133578Sharti
421133578Sharti	free(addrs, M_NG_CCATM);
422133578Sharti	free(ports, M_NG_CCATM);
423133578Sharti
424133578Sharti	return (0);
425133578Sharti}
426133578Sharti
427133578Sharti/*
428133578Sharti * Dumper function. Pack the data into an mbuf chain.
429133578Sharti */
430133578Shartistatic int
431133578Shartisend_dump(struct ccdata *data, void *uarg, const char *buf)
432133578Sharti{
433133578Sharti	struct mbuf *m;
434133578Sharti	struct ccnode *priv = uarg;
435133578Sharti
436133578Sharti	if (priv->dump == NULL) {
437243882Sglebius		m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
438133578Sharti		if (m == NULL)
439133578Sharti			return (ENOBUFS);
440133578Sharti		priv->dump_first = priv->dump_last = m;
441133578Sharti		m->m_pkthdr.len = 0;
442133578Sharti	} else {
443243882Sglebius		m = m_getcl(M_NOWAIT, MT_DATA, 0);
444133578Sharti		if (m == 0) {
445133578Sharti			m_freem(priv->dump_first);
446133578Sharti			return (ENOBUFS);
447133578Sharti		}
448133578Sharti		priv->dump_last->m_next = m;
449133578Sharti		priv->dump_last = m;
450133578Sharti	}
451133578Sharti
452133578Sharti	strcpy(m->m_data, buf);
453133578Sharti	priv->dump_first->m_pkthdr.len += (m->m_len = strlen(buf));
454133578Sharti
455133578Sharti	return (0);
456133578Sharti}
457133578Sharti
458133578Sharti/*
459133578Sharti * Dump current status to dump hook
460133578Sharti */
461133578Shartistatic int
462133578Sharting_ccatm_dump(node_p node)
463133578Sharti{
464133578Sharti	struct ccnode *priv = NG_NODE_PRIVATE(node);
465133578Sharti	struct mbuf *m;
466133578Sharti	int error;
467133578Sharti
468133578Sharti	priv->dump_first = priv->dump_last = NULL;
469133578Sharti	error = cc_dump(priv->data, MCLBYTES, send_dump, priv);
470133578Sharti	if (error != 0)
471133578Sharti		return (error);
472133578Sharti
473133578Sharti	if ((m = priv->dump_first) != NULL) {
474133578Sharti		priv->dump_first = priv->dump_last = NULL;
475133578Sharti		NG_SEND_DATA_ONLY(error, priv->dump, m);
476133578Sharti		return (error);
477133578Sharti	}
478133578Sharti	return (0);
479133578Sharti}
480133578Sharti
481133578Sharti/*
482133578Sharti * Control message
483133578Sharti */
484133578Shartistatic int
485133578Sharting_ccatm_rcvmsg(node_p node, item_p item, hook_p lasthook)
486133578Sharti{
487133578Sharti	struct ng_mesg *resp = NULL;
488133578Sharti	struct ng_mesg *msg;
489133578Sharti	struct ccnode *priv = NG_NODE_PRIVATE(node);
490133578Sharti	int error = 0;
491133578Sharti
492133578Sharti	NGI_GET_MSG(item, msg);
493133578Sharti
494133578Sharti	switch (msg->header.typecookie) {
495133578Sharti
496133578Sharti	  case NGM_CCATM_COOKIE:
497133578Sharti		switch (msg->header.cmd) {
498133578Sharti
499133578Sharti		  case NGM_CCATM_DUMP:
500133578Sharti			if (priv->dump)
501133578Sharti				error = ng_ccatm_dump(node);
502133578Sharti			else
503133578Sharti				error = ENOTCONN;
504133578Sharti			break;
505133578Sharti
506133578Sharti		  case NGM_CCATM_STOP:
507133578Sharti		    {
508133578Sharti			struct ngm_ccatm_port *arg;
509133578Sharti
510133578Sharti			if (msg->header.arglen != sizeof(*arg)) {
511133578Sharti				error = EINVAL;
512133578Sharti				break;
513133578Sharti			}
514133578Sharti			arg = (struct ngm_ccatm_port *)msg->data;
515133578Sharti			error = cc_port_stop(priv->data, arg->port);
516133578Sharti			break;
517133578Sharti		    }
518133578Sharti
519133578Sharti		  case NGM_CCATM_START:
520133578Sharti		    {
521133578Sharti			struct ngm_ccatm_port *arg;
522133578Sharti
523133578Sharti			if (msg->header.arglen != sizeof(*arg)) {
524133578Sharti				error = EINVAL;
525133578Sharti				break;
526133578Sharti			}
527133578Sharti			arg = (struct ngm_ccatm_port *)msg->data;
528133578Sharti			error = cc_port_start(priv->data, arg->port);
529133578Sharti			break;
530133578Sharti		    }
531133578Sharti
532133578Sharti		  case NGM_CCATM_GETSTATE:
533133578Sharti		    {
534133578Sharti			struct ngm_ccatm_port *arg;
535133578Sharti			int state;
536133578Sharti
537133578Sharti			if (msg->header.arglen != sizeof(*arg)) {
538133578Sharti				error = EINVAL;
539133578Sharti				break;
540133578Sharti			}
541133578Sharti			arg = (struct ngm_ccatm_port *)msg->data;
542133578Sharti			error = cc_port_isrunning(priv->data, arg->port,
543133578Sharti			    &state);
544133578Sharti			if (error == 0) {
545133578Sharti				NG_MKRESPONSE(resp, msg, sizeof(uint32_t),
546133578Sharti				    M_NOWAIT);
547133578Sharti				if (resp == NULL) {
548133578Sharti					error = ENOMEM;
549133578Sharti					break;
550133578Sharti				}
551133578Sharti				*(uint32_t *)resp->data = state;
552133578Sharti			}
553133578Sharti			break;
554133578Sharti		    }
555133578Sharti
556133578Sharti		  case NGM_CCATM_GET_ADDRESSES:
557133578Sharti		   {
558133578Sharti			struct ngm_ccatm_port *arg;
559133578Sharti
560133578Sharti			if (msg->header.arglen != sizeof(*arg)) {
561133578Sharti				error = EINVAL;
562133578Sharti				break;
563133578Sharti			}
564133578Sharti			arg = (struct ngm_ccatm_port *)msg->data;
565133578Sharti			error = ng_ccatm_get_addresses(node, arg->port, msg,
566133578Sharti			    &resp);
567133578Sharti			break;
568133578Sharti		    }
569133578Sharti
570133578Sharti		  case NGM_CCATM_CLEAR:
571133578Sharti		    {
572133578Sharti			struct ngm_ccatm_port *arg;
573133578Sharti
574133578Sharti			if (msg->header.arglen != sizeof(*arg)) {
575133578Sharti				error = EINVAL;
576133578Sharti				break;
577133578Sharti			}
578133578Sharti			arg = (struct ngm_ccatm_port *)msg->data;
579133578Sharti			error = cc_port_clear(priv->data, arg->port);
580133578Sharti			break;
581133578Sharti		    }
582133578Sharti
583133578Sharti		  case NGM_CCATM_ADDRESS_REGISTERED:
584133578Sharti		    {
585133578Sharti			struct ngm_ccatm_addr_req *arg;
586133578Sharti
587133578Sharti			if (msg->header.arglen != sizeof(*arg)) {
588133578Sharti				error = EINVAL;
589133578Sharti				break;
590133578Sharti			}
591133578Sharti			arg = (struct ngm_ccatm_addr_req *)msg->data;
592133578Sharti			error = cc_addr_register(priv->data, arg->port,
593133578Sharti			    &arg->addr);
594133578Sharti			break;
595133578Sharti		    }
596133578Sharti
597133578Sharti		  case NGM_CCATM_ADDRESS_UNREGISTERED:
598133578Sharti		    {
599133578Sharti			struct ngm_ccatm_addr_req *arg;
600133578Sharti
601133578Sharti			if (msg->header.arglen != sizeof(*arg)) {
602133578Sharti				error = EINVAL;
603133578Sharti				break;
604133578Sharti			}
605133578Sharti			arg = (struct ngm_ccatm_addr_req *)msg->data;
606133578Sharti			error = cc_addr_unregister(priv->data, arg->port,
607133578Sharti			    &arg->addr);
608133578Sharti			break;
609133578Sharti		    }
610133578Sharti
611133578Sharti		  case NGM_CCATM_GET_PORT_PARAM:
612133578Sharti		    {
613133578Sharti			struct ngm_ccatm_port *arg;
614133578Sharti
615133578Sharti			if (msg->header.arglen != sizeof(*arg)) {
616133578Sharti				error = EINVAL;
617133578Sharti				break;
618133578Sharti			}
619133578Sharti			arg = (struct ngm_ccatm_port *)msg->data;
620133578Sharti			NG_MKRESPONSE(resp, msg, sizeof(struct atm_port_info),
621133578Sharti			    M_NOWAIT);
622133578Sharti			if (resp == NULL) {
623133578Sharti				error = ENOMEM;
624133578Sharti				break;
625133578Sharti			}
626133578Sharti			error = cc_port_get_param(priv->data, arg->port,
627133578Sharti			    (struct atm_port_info *)resp->data);
628133578Sharti			if (error != 0) {
629133578Sharti				free(resp, M_NETGRAPH_MSG);
630133578Sharti				resp = NULL;
631133578Sharti			}
632133578Sharti			break;
633133578Sharti		    }
634133578Sharti
635133578Sharti		  case NGM_CCATM_SET_PORT_PARAM:
636133578Sharti		    {
637133578Sharti			struct atm_port_info *arg;
638133578Sharti
639133578Sharti			if (msg->header.arglen != sizeof(*arg)) {
640133578Sharti				error = EINVAL;
641133578Sharti				break;
642133578Sharti			}
643133578Sharti			arg = (struct atm_port_info *)msg->data;
644133578Sharti			error = cc_port_set_param(priv->data, arg);
645133578Sharti			break;
646133578Sharti		    }
647133578Sharti
648133578Sharti		  case NGM_CCATM_GET_PORTLIST:
649133578Sharti		    {
650133578Sharti			struct ngm_ccatm_portlist *arg;
651133578Sharti			u_int n, *ports;
652133578Sharti
653133578Sharti			if (msg->header.arglen != 0) {
654133578Sharti				error = EINVAL;
655133578Sharti				break;
656133578Sharti			}
657133578Sharti			error = cc_port_getlist(priv->data, &n, &ports);
658133578Sharti			if (error != 0)
659133578Sharti				break;
660133578Sharti
661133578Sharti			NG_MKRESPONSE(resp, msg, sizeof(*arg) +
662133578Sharti			    n * sizeof(arg->ports[0]), M_NOWAIT);
663133578Sharti			if (resp == NULL) {
664133578Sharti				free(ports, M_NG_CCATM);
665133578Sharti				error = ENOMEM;
666133578Sharti				break;
667133578Sharti			}
668133578Sharti			arg = (struct ngm_ccatm_portlist *)resp->data;
669133578Sharti
670133578Sharti			arg->nports = 0;
671133578Sharti			for (arg->nports = 0; arg->nports < n; arg->nports++)
672133578Sharti				arg->ports[arg->nports] = ports[arg->nports];
673133578Sharti			free(ports, M_NG_CCATM);
674133578Sharti			break;
675133578Sharti		    }
676133578Sharti
677133578Sharti		  case NGM_CCATM_SETLOG:
678133578Sharti		    {
679133578Sharti			uint32_t log_level;
680133578Sharti
681133578Sharti			log_level = cc_get_log(priv->data);
682133578Sharti			if (msg->header.arglen != 0) {
683133578Sharti				if (msg->header.arglen != sizeof(log_level)) {
684133578Sharti					error = EINVAL;
685133578Sharti					break;
686133578Sharti				}
687133578Sharti				cc_set_log(priv->data, *(uint32_t *)msg->data);
688133578Sharti			}
689133578Sharti
690133578Sharti			NG_MKRESPONSE(resp, msg, sizeof(uint32_t), M_NOWAIT);
691133578Sharti			if (resp == NULL) {
692133578Sharti				error = ENOMEM;
693133578Sharti				if (msg->header.arglen != 0)
694133578Sharti					cc_set_log(priv->data, log_level);
695133578Sharti				break;
696133578Sharti			}
697133578Sharti			*(uint32_t *)resp->data = log_level;
698133578Sharti			break;
699133578Sharti		    }
700133578Sharti
701133578Sharti		  case NGM_CCATM_RESET:
702133578Sharti			if (msg->header.arglen != 0) {
703133578Sharti				error = EINVAL;
704133578Sharti				break;
705133578Sharti			}
706133578Sharti
707133578Sharti			if (priv->hook_cnt != 0) {
708133578Sharti				error = EBUSY;
709133578Sharti				break;
710133578Sharti			}
711133578Sharti			cc_reset(priv->data);
712133578Sharti			break;
713133578Sharti
714133578Sharti		  case NGM_CCATM_GET_EXSTAT:
715133578Sharti		    {
716133578Sharti			struct atm_exstatus s;
717133578Sharti			struct atm_exstatus_ep *eps;
718133578Sharti			struct atm_exstatus_port *ports;
719133578Sharti			struct atm_exstatus_conn *conns;
720133578Sharti			struct atm_exstatus_party *parties;
721133578Sharti			size_t offs;
722133578Sharti
723133578Sharti			if (msg->header.arglen != 0) {
724133578Sharti				error = EINVAL;
725133578Sharti				break;
726133578Sharti			}
727133578Sharti			error = cc_get_extended_status(priv->data,
728133578Sharti			    &s, &eps, &ports, &conns, &parties);
729133578Sharti			if (error != 0)
730133578Sharti				break;
731133578Sharti
732133578Sharti			offs = sizeof(s) + s.neps * sizeof(*eps) +
733133578Sharti			    s.nports * sizeof(*ports) +
734133578Sharti			    s.nconns * sizeof(*conns) +
735133578Sharti			    s.nparties * sizeof(*parties);
736133578Sharti
737133578Sharti			NG_MKRESPONSE(resp, msg, offs, M_NOWAIT);
738133578Sharti			if (resp == NULL) {
739133578Sharti				error = ENOMEM;
740133578Sharti				break;
741133578Sharti			}
742133578Sharti
743133578Sharti			memcpy(resp->data, &s, sizeof(s));
744133578Sharti			offs = sizeof(s);
745133578Sharti
746133578Sharti			memcpy(resp->data + offs, eps,
747133578Sharti			    sizeof(*eps) * s.neps);
748133578Sharti			offs += sizeof(*eps) * s.neps;
749133578Sharti
750133578Sharti			memcpy(resp->data + offs, ports,
751133578Sharti			    sizeof(*ports) * s.nports);
752133578Sharti			offs += sizeof(*ports) * s.nports;
753133578Sharti
754133578Sharti			memcpy(resp->data + offs, conns,
755133578Sharti			    sizeof(*conns) * s.nconns);
756133578Sharti			offs += sizeof(*conns) * s.nconns;
757133578Sharti
758133578Sharti			memcpy(resp->data + offs, parties,
759133578Sharti			    sizeof(*parties) * s.nparties);
760133578Sharti			offs += sizeof(*parties) * s.nparties;
761133578Sharti
762133578Sharti			free(eps, M_NG_CCATM);
763133578Sharti			free(ports, M_NG_CCATM);
764133578Sharti			free(conns, M_NG_CCATM);
765133578Sharti			free(parties, M_NG_CCATM);
766133578Sharti			break;
767133578Sharti		    }
768133578Sharti
769133578Sharti		  default:
770133578Sharti			error = EINVAL;
771133578Sharti			break;
772133578Sharti
773133578Sharti		}
774133578Sharti		break;
775133578Sharti
776133578Sharti	  default:
777133578Sharti		error = EINVAL;
778133578Sharti		break;
779133578Sharti
780133578Sharti	}
781133578Sharti
782133578Sharti	NG_RESPOND_MSG(error, node, item, resp);
783133578Sharti	NG_FREE_MSG(msg);
784133578Sharti	return (error);
785133578Sharti}
786133578Sharti
787133578Sharti/************************************************************
788133578Sharti *
789133578Sharti * New hook arrival
790133578Sharti */
791133578Shartistatic int
792133578Sharting_ccatm_newhook(node_p node, hook_p hook, const char *name)
793133578Sharti{
794133578Sharti	struct ccnode *priv = NG_NODE_PRIVATE(node);
795133578Sharti	struct ccport *port;
796133578Sharti	struct ccuser *user;
797133578Sharti	struct cchook *hd;
798133578Sharti	u_long lport;
799133578Sharti	char *end;
800133578Sharti
801133578Sharti	if (strncmp(name, "uni", 3) == 0) {
802133578Sharti		/*
803133578Sharti		 * This is a UNI hook. Should be a new port.
804133578Sharti		 */
805133578Sharti		if (name[3] == '\0')
806133578Sharti			return (EINVAL);
807133578Sharti		lport = strtoul(name + 3, &end, 10);
808133578Sharti		if (*end != '\0' || lport == 0 || lport > 0xffffffff)
809133578Sharti			return (EINVAL);
810133578Sharti
811133578Sharti		hd = malloc(sizeof(*hd), M_NG_CCATM, M_NOWAIT);
812133578Sharti		if (hd == NULL)
813133578Sharti			return (ENOMEM);
814133578Sharti		hd->is_uni = 1;
815133578Sharti		hd->node = priv;
816133578Sharti		hd->hook = hook;
817133578Sharti
818133578Sharti		port = cc_port_create(priv->data, hd, (u_int)lport);
819133578Sharti		if (port == NULL) {
820133578Sharti			free(hd, M_NG_CCATM);
821133578Sharti			return (ENOMEM);
822133578Sharti		}
823133578Sharti		hd->inst = port;
824133578Sharti
825133578Sharti		NG_HOOK_SET_PRIVATE(hook, hd);
826133578Sharti		NG_HOOK_SET_RCVDATA(hook, ng_ccatm_rcvuni);
827133578Sharti		NG_HOOK_FORCE_QUEUE(hook);
828133578Sharti
829133578Sharti		priv->hook_cnt++;
830133578Sharti
831133578Sharti		return (0);
832133578Sharti	}
833133578Sharti
834133578Sharti	if (strcmp(name, "dump") == 0) {
835133578Sharti		priv->dump = hook;
836133578Sharti		NG_HOOK_SET_RCVDATA(hook, ng_ccatm_rcvdump);
837133578Sharti		return (0);
838133578Sharti	}
839133578Sharti
840133578Sharti	if (strcmp(name, "manage") == 0) {
841133578Sharti		priv->manage = hook;
842133578Sharti		NG_HOOK_SET_RCVDATA(hook, ng_ccatm_rcvmanage);
843133578Sharti		return (0);
844133578Sharti	}
845133578Sharti
846133578Sharti	/*
847133578Sharti	 * User hook
848133578Sharti	 */
849133578Sharti	hd = malloc(sizeof(*hd), M_NG_CCATM, M_NOWAIT);
850133578Sharti	if (hd == NULL)
851133578Sharti		return (ENOMEM);
852133578Sharti	hd->is_uni = 0;
853133578Sharti	hd->node = priv;
854133578Sharti	hd->hook = hook;
855133578Sharti
856133578Sharti	user = cc_user_create(priv->data, hd, NG_HOOK_NAME(hook));
857133578Sharti	if (user == NULL) {
858133578Sharti		free(hd, M_NG_CCATM);
859133578Sharti		return (ENOMEM);
860133578Sharti	}
861133578Sharti
862133578Sharti	hd->inst = user;
863133578Sharti	NG_HOOK_SET_PRIVATE(hook, hd);
864133578Sharti	NG_HOOK_FORCE_QUEUE(hook);
865133578Sharti
866133578Sharti	priv->hook_cnt++;
867133578Sharti
868133578Sharti	return (0);
869133578Sharti}
870133578Sharti
871133578Sharti/*
872133578Sharti * Disconnect a hook
873133578Sharti */
874133578Shartistatic int
875133578Sharting_ccatm_disconnect(hook_p hook)
876133578Sharti{
877133578Sharti	node_p node = NG_HOOK_NODE(hook);
878133578Sharti	struct ccnode *priv = NG_NODE_PRIVATE(node);
879133578Sharti	struct cchook *hd = NG_HOOK_PRIVATE(hook);
880162849Snetchild	struct ccdata *cc;
881133578Sharti
882133578Sharti	if (hook == priv->dump) {
883133578Sharti		priv->dump = NULL;
884133578Sharti
885133578Sharti	} else if (hook == priv->manage) {
886133578Sharti		priv->manage = NULL;
887133578Sharti		cc_unmanage(priv->data);
888133578Sharti
889133578Sharti	} else {
890133578Sharti		if (hd->is_uni)
891133578Sharti			cc_port_destroy(hd->inst, 0);
892133578Sharti		else
893133578Sharti			cc_user_destroy(hd->inst);
894133578Sharti
895162849Snetchild		cc = hd->node->data;
896162849Snetchild
897133578Sharti		free(hd, M_NG_CCATM);
898133578Sharti		NG_HOOK_SET_PRIVATE(hook, NULL);
899133578Sharti
900133578Sharti		priv->hook_cnt--;
901133578Sharti
902162849Snetchild		cc_work(cc);
903133578Sharti	}
904133578Sharti
905133578Sharti	/*
906133578Sharti	 * When the number of hooks drops to zero, delete the node.
907133578Sharti	 */
908133578Sharti	if (NG_NODE_NUMHOOKS(node) == 0 && NG_NODE_IS_VALID(node))
909133578Sharti		ng_rmnode_self(node);
910133578Sharti
911133578Sharti	return (0);
912133578Sharti}
913133578Sharti
914133578Sharti/************************************************************
915133578Sharti *
916133578Sharti * Receive data from user hook
917133578Sharti */
918133578Shartistatic int
919133578Sharting_ccatm_rcvdata(hook_p hook, item_p item)
920133578Sharti{
921133578Sharti	struct cchook *hd = NG_HOOK_PRIVATE(hook);
922133578Sharti	struct uni_msg *msg;
923133578Sharti	struct mbuf *m;
924133578Sharti	struct ccatm_op op;
925133578Sharti	int err;
926133578Sharti
927133578Sharti	NGI_GET_M(item, m);
928133578Sharti	NG_FREE_ITEM(item);
929133578Sharti
930133578Sharti	if ((err = uni_msg_unpack_mbuf(m, &msg)) != 0) {
931133578Sharti		m_freem(m);
932133578Sharti		return (err);
933133578Sharti	}
934133578Sharti	m_freem(m);
935133578Sharti
936133578Sharti	if (uni_msg_len(msg) < sizeof(op)) {
937133578Sharti		printf("%s: packet too short\n", __func__);
938133578Sharti		uni_msg_destroy(msg);
939133578Sharti		return (EINVAL);
940133578Sharti	}
941133578Sharti
942133578Sharti	bcopy(msg->b_rptr, &op, sizeof(op));
943133578Sharti	msg->b_rptr += sizeof(op);
944133578Sharti
945133578Sharti	err = cc_user_signal(hd->inst, op.op, msg);
946133578Sharti	cc_work(hd->node->data);
947133578Sharti	return (err);
948133578Sharti}
949133578Sharti
950133578Sharti/*
951133578Sharti * Pack a header and a data area into an mbuf chain
952133578Sharti */
953133578Shartistatic struct mbuf *
954133578Shartipack_buf(void *h, size_t hlen, void *t, size_t tlen)
955133578Sharti{
956133578Sharti	struct mbuf *m, *m0, *last;
957133578Sharti	u_char *buf = (u_char *)t;
958133578Sharti	size_t n;
959133578Sharti
960133578Sharti	/* header should fit into a normal mbuf */
961133578Sharti	MGETHDR(m0, M_NOWAIT, MT_DATA);
962133578Sharti	if (m0 == NULL)
963133578Sharti		return NULL;
964133578Sharti
965133578Sharti	KASSERT(hlen <= MHLEN, ("hlen > MHLEN"));
966133578Sharti
967133578Sharti	bcopy(h, m0->m_data, hlen);
968133578Sharti	m0->m_len = hlen;
969133578Sharti	m0->m_pkthdr.len = hlen;
970133578Sharti
971133578Sharti	last = m0;
972133578Sharti	while ((n = tlen) != 0) {
973133578Sharti		if (n > MLEN) {
974133578Sharti			m = m_getcl(M_NOWAIT, MT_DATA, 0);
975133578Sharti			if (n > MCLBYTES)
976133578Sharti				n = MCLBYTES;
977133578Sharti		} else
978133578Sharti			MGET(m, M_NOWAIT, MT_DATA);
979133578Sharti
980133578Sharti		if(m == NULL)
981133578Sharti			goto drop;
982133578Sharti
983133578Sharti		last->m_next = m;
984133578Sharti		last = m;
985133578Sharti
986133578Sharti		bcopy(buf, m->m_data, n);
987133578Sharti		buf += n;
988133578Sharti		tlen -= n;
989133578Sharti		m->m_len = n;
990133578Sharti		m0->m_pkthdr.len += n;
991133578Sharti	}
992133578Sharti
993133578Sharti	return (m0);
994133578Sharti
995133578Sharti  drop:
996133578Sharti	m_freem(m0);
997133578Sharti	return NULL;
998133578Sharti}
999133578Sharti
1000133578Sharti/*
1001133578Sharti * Send an indication to the user.
1002133578Sharti */
1003133578Shartistatic void
1004133578Sharting_ccatm_send_user(struct ccuser *user, void *uarg, u_int op,
1005133578Sharti    void *val, size_t len)
1006133578Sharti{
1007133578Sharti	struct cchook *hd = uarg;
1008133578Sharti	struct mbuf *m;
1009133578Sharti	struct ccatm_op	h;
1010133578Sharti	int error;
1011133578Sharti
1012133578Sharti	h.op = op;
1013133578Sharti	m = pack_buf(&h, sizeof(h), val, len);
1014133578Sharti	if (m == NULL)
1015133578Sharti		return;
1016133578Sharti
1017133578Sharti	NG_SEND_DATA_ONLY(error, hd->hook, m);
1018133578Sharti	if (error != 0)
1019133578Sharti		printf("%s: error=%d\n", __func__, error);
1020133578Sharti}
1021133578Sharti
1022133578Sharti/*
1023133578Sharti * Send a response to the user.
1024133578Sharti */
1025133578Shartistatic void
1026133578Sharting_ccatm_respond_user(struct ccuser *user, void *uarg, int err, u_int data,
1027133578Sharti    void *val, size_t len)
1028133578Sharti{
1029133578Sharti	struct cchook *hd = uarg;
1030133578Sharti	struct mbuf *m;
1031133578Sharti	struct {
1032133578Sharti		struct ccatm_op	op;
1033133578Sharti		struct atm_resp resp;
1034133578Sharti	} resp;
1035133578Sharti	int error;
1036133578Sharti
1037133578Sharti	resp.op.op = ATMOP_RESP;
1038133578Sharti	resp.resp.resp = err;
1039133578Sharti	resp.resp.data = data;
1040133578Sharti	m = pack_buf(&resp, sizeof(resp), val, len);
1041133578Sharti	if (m == NULL)
1042133578Sharti		return;
1043133578Sharti
1044133578Sharti	NG_SEND_DATA_ONLY(error, hd->hook, m);
1045133578Sharti	if (error != 0)
1046133578Sharti		printf("%s: error=%d\n", __func__, error);
1047133578Sharti}
1048133578Sharti
1049133578Sharti/*
1050133578Sharti * Receive data from UNI.
1051133578Sharti */
1052133578Shartistatic int
1053133578Sharting_ccatm_rcvuni(hook_p hook, item_p item)
1054133578Sharti{
1055133578Sharti	struct cchook *hd = NG_HOOK_PRIVATE(hook);
1056133578Sharti	struct uni_msg *msg;
1057133578Sharti	struct uni_arg arg;
1058133578Sharti	struct mbuf *m;
1059133578Sharti	int err;
1060133578Sharti
1061133578Sharti	NGI_GET_M(item, m);
1062133578Sharti	NG_FREE_ITEM(item);
1063133578Sharti
1064133578Sharti	if ((err = uni_msg_unpack_mbuf(m, &msg)) != 0) {
1065133578Sharti		m_freem(m);
1066133578Sharti		return (err);
1067133578Sharti	}
1068133578Sharti	m_freem(m);
1069133578Sharti
1070133578Sharti	if (uni_msg_len(msg) < sizeof(arg)) {
1071133578Sharti		printf("%s: packet too short\n", __func__);
1072133578Sharti		uni_msg_destroy(msg);
1073133578Sharti		return (EINVAL);
1074133578Sharti	}
1075133578Sharti
1076133578Sharti	bcopy(msg->b_rptr, &arg, sizeof(arg));
1077133578Sharti	msg->b_rptr += sizeof(arg);
1078133578Sharti
1079133578Sharti	if (arg.sig == UNIAPI_ERROR) {
1080133578Sharti		if (uni_msg_len(msg) != sizeof(struct uniapi_error)) {
1081133578Sharti			printf("%s: bad UNIAPI_ERROR size %zu\n", __func__,
1082133578Sharti			    uni_msg_len(msg));
1083133578Sharti			uni_msg_destroy(msg);
1084133578Sharti			return (EINVAL);
1085133578Sharti		}
1086133578Sharti		err = cc_uni_response(hd->inst, arg.cookie,
1087133578Sharti		    ((struct uniapi_error *)msg->b_rptr)->reason,
1088133578Sharti		    ((struct uniapi_error *)msg->b_rptr)->state);
1089133578Sharti		uni_msg_destroy(msg);
1090133578Sharti	} else
1091133578Sharti		err = cc_uni_signal(hd->inst, arg.cookie, arg.sig, msg);
1092133578Sharti
1093133578Sharti	cc_work(hd->node->data);
1094133578Sharti	return (err);
1095133578Sharti}
1096133578Sharti
1097133578Sharti/*
1098133578Sharti * Uarg is the port's uarg.
1099133578Sharti */
1100133578Shartistatic void
1101133578Sharting_ccatm_send_uni(struct ccconn *conn, void *uarg, u_int op, u_int cookie,
1102133578Sharti    struct uni_msg *msg)
1103133578Sharti{
1104133578Sharti	struct cchook *hd = uarg;
1105133578Sharti	struct uni_arg arg;
1106133578Sharti	struct mbuf *m;
1107133578Sharti	int error;
1108133578Sharti
1109133578Sharti	arg.sig = op;
1110133578Sharti	arg.cookie = cookie;
1111133578Sharti
1112133578Sharti	m = uni_msg_pack_mbuf(msg, &arg, sizeof(arg));
1113133578Sharti	uni_msg_destroy(msg);
1114133578Sharti	if (m == NULL)
1115133578Sharti		return;
1116133578Sharti
1117133578Sharti	NG_SEND_DATA_ONLY(error, hd->hook, m);
1118133578Sharti	if (error != 0)
1119133578Sharti		printf("%s: error=%d\n", __func__, error);
1120133578Sharti}
1121133578Sharti
1122133578Sharti/*
1123133578Sharti * Send a global message to the UNI
1124133578Sharti */
1125133578Shartistatic void
1126133578Sharting_ccatm_send_uni_glob(struct ccport *port, void *uarg, u_int op, u_int cookie,
1127133578Sharti    struct uni_msg *msg)
1128133578Sharti{
1129133578Sharti	struct cchook *hd = uarg;
1130133578Sharti	struct uni_arg arg;
1131133578Sharti	struct mbuf *m;
1132133578Sharti	int error;
1133133578Sharti
1134133578Sharti	arg.sig = op;
1135133578Sharti	arg.cookie = cookie;
1136133578Sharti
1137133578Sharti	m = uni_msg_pack_mbuf(msg, &arg, sizeof(arg));
1138133578Sharti	if (msg != NULL)
1139133578Sharti		uni_msg_destroy(msg);
1140133578Sharti	if (m == NULL)
1141133578Sharti		return;
1142133578Sharti
1143133578Sharti	NG_SEND_DATA_ONLY(error, hd->hook, m);
1144133578Sharti	if (error != 0)
1145133578Sharti		printf("%s: error=%d\n", __func__, error);
1146133578Sharti}
1147133578Sharti/*
1148133578Sharti * Receive from ILMID
1149133578Sharti */
1150133578Shartistatic int
1151133578Sharting_ccatm_rcvmanage(hook_p hook, item_p item)
1152133578Sharti{
1153133578Sharti	NG_FREE_ITEM(item);
1154133578Sharti	return (0);
1155133578Sharti}
1156133578Sharti
1157133578Shartistatic int
1158133578Sharting_ccatm_rcvdump(hook_p hook, item_p item)
1159133578Sharti{
1160133578Sharti	NG_FREE_ITEM(item);
1161133578Sharti	return (0);
1162133578Sharti}
1163133578Sharti
1164133578Shartistatic void
1165133578Sharting_ccatm_log(const char *fmt, ...)
1166133578Sharti{
1167133578Sharti	va_list ap;
1168133578Sharti
1169133578Sharti	va_start(ap, fmt);
1170133578Sharti	vprintf(fmt, ap);
1171133578Sharti	printf("\n");
1172133578Sharti	va_end(ap);
1173133578Sharti}
1174133578Sharti
1175133578Sharti/*
1176133578Sharti * Loading and unloading of node type
1177133578Sharti */
1178133578Shartistatic int
1179133578Sharting_ccatm_mod_event(module_t mod, int event, void *data)
1180133578Sharti{
1181133578Sharti	int error = 0;
1182133578Sharti
1183133578Sharti	switch (event) {
1184133578Sharti
1185133578Sharti	  case MOD_LOAD:
1186133578Sharti		break;
1187133578Sharti
1188133578Sharti	  case MOD_UNLOAD:
1189133578Sharti		break;
1190133578Sharti
1191133578Sharti	  default:
1192133578Sharti		error = EOPNOTSUPP;
1193133578Sharti		break;
1194133578Sharti	}
1195133578Sharti	return (error);
1196133578Sharti}
1197