1131826Sharti/*
2131826Sharti * Copyright (c) 2003-2004
3131826Sharti *	Hartmut Brandt
4131826Sharti *	All rights reserved.
5131826Sharti *
6131826Sharti * Author: Harti Brandt <harti@freebsd.org>
7131826Sharti *
8131826Sharti * Redistribution of this software and documentation and use in source and
9131826Sharti * binary forms, with or without modification, are permitted provided that
10131826Sharti * the following conditions are met:
11131826Sharti *
12131826Sharti * 1. Redistributions of source code or documentation must retain the above
13131826Sharti *    copyright notice, this list of conditions and the following disclaimer.
14131826Sharti * 2. Redistributions in binary form must reproduce the above copyright
15131826Sharti *    notice, this list of conditions and the following disclaimer in the
16131826Sharti *    documentation and/or other materials provided with the distribution.
17131826Sharti *
18131826Sharti * THIS SOFTWARE AND DOCUMENTATION IS PROVIDED BY THE AUTHOR
19131826Sharti * AND ITS CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
20131826Sharti * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
21131826Sharti * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
22131826Sharti * THE AUTHOR OR ITS CONTRIBUTORS  BE LIABLE FOR ANY DIRECT, INDIRECT,
23131826Sharti * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24131826Sharti * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
25131826Sharti * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
26131826Sharti * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
27131826Sharti * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
28131826Sharti * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29131826Sharti *
30133492Sharti * $Begemot: libunimsg/netnatm/api/cc_dump.c,v 1.3 2004/08/05 07:10:56 brandt Exp $
31131826Sharti *
32131826Sharti * ATM API as defined per af-saa-0108
33131826Sharti */
34131826Sharti
35131826Sharti#include <netnatm/unimsg.h>
36131826Sharti#include <netnatm/msg/unistruct.h>
37131826Sharti#include <netnatm/msg/unimsglib.h>
38131826Sharti#include <netnatm/api/unisap.h>
39131826Sharti#include <netnatm/sig/unidef.h>
40131826Sharti#include <netnatm/api/atmapi.h>
41131826Sharti#include <netnatm/api/ccatm.h>
42131826Sharti#include <netnatm/api/ccpriv.h>
43131826Sharti
44131826Sharti#ifdef _KERNEL
45131826Sharti#ifdef __FreeBSD__
46133492Sharti#include <machine/stdarg.h>
47131826Sharti#endif
48131826Sharti#else	/* !_KERNEL */
49131826Sharti#include <stdarg.h>
50131826Sharti#endif
51131826Sharti
52131826Sharti/*
53131826Sharti * local structure to reduce number of arguments to functions
54131826Sharti */
55131826Shartistruct dump {
56131826Sharti	struct ccdata	*cc;	/* what to dump */
57131826Sharti	size_t		maxsiz;	/* size of user buffer */
58131826Sharti	cc_dump_f	func;	/* user function */
59131826Sharti	void		*uarg;	/* user supplied argument */
60131826Sharti	char		*buf;	/* user buffer */
61131826Sharti	size_t		len;	/* current string length */
62131826Sharti	int		ret;	/* return code */
63131826Sharti};
64131826Sharti
65131826Shartistatic void cc_dumpf(struct dump *, const char *, ...) __printflike(2, 3);
66131826Sharti
67131826Shartistatic void
68131826Sharticc_dumpf(struct dump *d, const char *fmt, ...)
69131826Sharti{
70131826Sharti	va_list ap;
71131826Sharti	int n;
72131826Sharti
73131826Sharti	if (d->ret != 0)
74131826Sharti		return;
75131826Sharti	if (d->len >= d->maxsiz - 1) {
76131826Sharti		d->ret = d->func(d->cc, d->uarg, d->buf);
77131826Sharti		if (d->ret != 0)
78131826Sharti			return;
79131826Sharti		d->buf[0] = '\0';
80131826Sharti		d->len = 0;
81131826Sharti	}
82131826Sharti	va_start(ap, fmt);
83131826Sharti	n = vsnprintf(d->buf + d->len, d->maxsiz - d->len, fmt, ap);
84131826Sharti	va_end(ap);
85131826Sharti
86131826Sharti	if (n < 0) {
87133492Sharti		d->ret = CCGETERRNO();
88131826Sharti		return;
89131826Sharti	}
90131826Sharti	if ((size_t)n < d->maxsiz - d->len) {
91131826Sharti		d->len += n;
92131826Sharti		return;
93131826Sharti	}
94131826Sharti
95131826Sharti	/* undo the vsnprintf() and flush */
96131826Sharti	d->buf[d->len] = '\0';
97131826Sharti	d->ret = d->func(d->cc, d->uarg, d->buf);
98131826Sharti	if (d->ret != 0)
99131826Sharti		return;
100131826Sharti	d->buf[0] = '\0';
101131826Sharti	d->len = 0;
102131826Sharti
103131826Sharti	va_start(ap, fmt);
104131826Sharti	n = vsnprintf(d->buf, d->maxsiz, fmt, ap);
105131826Sharti	va_end(ap);
106131826Sharti
107131826Sharti	if (n < 0) {
108133492Sharti		d->ret = CCGETERRNO();
109131826Sharti		return;
110131826Sharti	}
111131826Sharti	if ((size_t)n >= d->maxsiz) {
112131826Sharti		/* ok, truncate */
113131826Sharti		d->len = d->maxsiz - 1;
114131826Sharti		return;
115131826Sharti	}
116131826Sharti	d->len = n;
117131826Sharti}
118131826Sharti
119131826Sharti/*
120131826Sharti * Dump a SAP
121131826Sharti */
122131826Shartistatic void
123131826Sharticc_dump_sap(struct dump *d, const struct uni_sap *sap)
124131826Sharti{
125131826Sharti	static const char *const tagtab[] = {
126133492Sharti		[UNISVE_ABSENT] =	"absent",
127133492Sharti		[UNISVE_ANY] =		"any",
128133492Sharti		[UNISVE_PRESENT] =	"present"
129131826Sharti	};
130131826Sharti	static const char *const plantab[] = {
131133492Sharti		[UNI_ADDR_E164] =	"E164",
132133492Sharti		[UNI_ADDR_ATME] =	"ATME",
133131826Sharti	};
134131826Sharti	static const char *const hlitab[] = {
135133492Sharti		[UNI_BHLI_ISO] =	"ISO",
136133492Sharti		[UNI_BHLI_VENDOR] =	"VENDOR",
137133492Sharti		[UNI_BHLI_USER] =	"USER"
138131826Sharti	};
139131826Sharti	u_int i;
140131826Sharti
141131826Sharti	cc_dumpf(d, "  sap(%p):\n", sap);
142131826Sharti	cc_dumpf(d, "    addr=%s", tagtab[sap->addr.tag]);
143131826Sharti	if (sap->addr.tag == UNISVE_PRESENT) {
144131826Sharti		cc_dumpf(d, " %s %u ", plantab[sap->addr.plan], sap->addr.len);
145131826Sharti		if (sap->addr.plan == UNI_ADDR_E164)
146131826Sharti			for (i = 0; i < sap->addr.len; i++)
147131826Sharti				cc_dumpf(d, "%c", sap->addr.addr[i]);
148131826Sharti		else
149131826Sharti			for (i = 0; i < sap->addr.len; i++)
150131826Sharti				cc_dumpf(d, "%02x", sap->addr.addr[i]);
151131826Sharti	}
152131826Sharti	cc_dumpf(d, "\n");
153131826Sharti
154131826Sharti	cc_dumpf(d, "    selector=%s", tagtab[sap->selector.tag]);
155131826Sharti	if (sap->selector.tag == UNISVE_PRESENT)
156131826Sharti		cc_dumpf(d, " %02x", sap->selector.selector);
157131826Sharti	cc_dumpf(d, "\n");
158131826Sharti
159131826Sharti	cc_dumpf(d, "    blli_id2=%s", tagtab[sap->blli_id2.tag]);
160131826Sharti	if (sap->blli_id2.tag == UNISVE_PRESENT)
161131826Sharti		cc_dumpf(d, " %02x %02x", sap->blli_id2.proto,
162131826Sharti		    sap->blli_id2.user);
163131826Sharti	cc_dumpf(d, "\n");
164131826Sharti
165131826Sharti	cc_dumpf(d, "    blli_id3=%s", tagtab[sap->blli_id3.tag]);
166131826Sharti	if (sap->blli_id3.tag == UNISVE_PRESENT)
167131826Sharti		cc_dumpf(d, " %02x,%02x, %02x(%d),%03x,%02x",
168131826Sharti		    sap->blli_id3.proto, sap->blli_id3.user,
169131826Sharti		    sap->blli_id3.ipi, sap->blli_id3.noipi,
170131826Sharti		    sap->blli_id3.oui, sap->blli_id3.pid);
171131826Sharti	cc_dumpf(d, "\n");
172131826Sharti
173131826Sharti	cc_dumpf(d, "    bhli=%s", tagtab[sap->bhli.tag]);
174131826Sharti	if (sap->bhli.tag == UNISVE_PRESENT) {
175131826Sharti		cc_dumpf(d, " %s ", hlitab[sap->bhli.type]);
176131826Sharti		for (i = 0; i < sap->bhli.len; i++)
177131826Sharti			cc_dumpf(d, "%02x", sap->bhli.info[i]);
178131826Sharti	}
179131826Sharti	cc_dumpf(d, "\n");
180131826Sharti}
181131826Sharti
182131826Sharti/*
183131826Sharti * Dump a user.
184131826Sharti */
185131826Shartistatic void
186131826Sharticc_dump_user(struct dump *d, const struct ccuser *user)
187131826Sharti{
188131826Sharti	struct ccconn *conn;
189131826Sharti
190131826Sharti	cc_dumpf(d, "user(%p): %s '%s' %s\n", user,
191131826Sharti	    cc_user_state2str(user->state), user->name,
192131826Sharti	    (user->config == USER_P2P) ? "p2p" :
193131826Sharti	    (user->config == USER_ROOT) ? "root" :
194131826Sharti	    (user->config == USER_LEAF) ? "leaf" : "?");
195131826Sharti	if (user->sap)
196131826Sharti		cc_dump_sap(d, user->sap);
197131826Sharti
198131826Sharti	cc_dumpf(d, "  queue=%u/%u accepted=%p aborted=%u\n", user->queue_max,
199131826Sharti	    user->queue_act, user->accepted, user->aborted);
200131826Sharti
201131826Sharti	cc_dumpf(d, "  connq:");
202131826Sharti	TAILQ_FOREACH(conn, &user->connq, connq_link)
203131826Sharti		cc_dumpf(d, "%p", conn);
204131826Sharti	cc_dumpf(d, "\n");
205131826Sharti}
206131826Sharti
207131826Sharti/*
208131826Sharti * Dump a party
209131826Sharti */
210131826Shartistatic void
211131826Sharticc_dump_party(struct dump *d, const struct ccparty *party, const char *pfx)
212131826Sharti{
213131826Sharti
214131826Sharti	cc_dumpf(d, "%s  party(%p): %u.%u %s\n", pfx, party,
215131826Sharti	    party->epref.flag, party->epref.epref,
216131826Sharti	    cc_party_state2str(party->state));
217131826Sharti}
218131826Sharti
219131826Sharti/*
220131826Sharti * Dump a connection
221131826Sharti */
222131826Shartistatic void
223131826Sharticc_dump_conn(struct dump *d, const struct ccconn *conn, const char *pfx)
224131826Sharti{
225131826Sharti	const struct ccparty *party;
226131826Sharti
227131826Sharti	cc_dumpf(d, "%sconn(%p): %s\n", pfx, conn,
228131826Sharti	    cc_conn_state2str(conn->state));
229131826Sharti	cc_dumpf(d, "%s  user=%p cref=%u.%u acceptor=%p\n", pfx,
230131826Sharti	    conn->user, conn->cref.cref, conn->cref.flag,
231131826Sharti	    conn->acceptor);
232131826Sharti
233131826Sharti	cc_dumpf(d, "%s  blli_sel=%u\n", pfx, conn->blli_selector);
234131826Sharti
235131826Sharti	LIST_FOREACH(party, &conn->parties, link)
236131826Sharti		cc_dump_party(d, party, pfx);
237131826Sharti}
238131826Sharti
239131826Sharti/*
240131826Sharti * Dump a port
241131826Sharti */
242131826Shartistatic void
243131826Sharticc_dump_port(struct dump *d, const struct ccport *p)
244131826Sharti{
245131826Sharti	u_int i;
246131826Sharti	const struct ccaddr *a;
247131826Sharti	const struct ccconn *c;
248131826Sharti	const struct ccreq *r;
249131826Sharti
250131826Sharti	static const char *const ttab[] = {
251131826Sharti		[UNI_ADDR_UNKNOWN] =		"unknown",
252131826Sharti		[UNI_ADDR_INTERNATIONAL] =	"international",
253131826Sharti		[UNI_ADDR_NATIONAL] =		"national",
254131826Sharti		[UNI_ADDR_NETWORK] =		"network",
255131826Sharti		[UNI_ADDR_SUBSCR] =		"subscr",
256131826Sharti		[UNI_ADDR_ABBR] =		"abbr",
257131826Sharti	};
258131826Sharti	static const char *const ptab[] = {
259131826Sharti		[UNI_ADDR_UNKNOWN] =	"unknown",
260131826Sharti		[UNI_ADDR_E164] =	"e164",
261131826Sharti		[UNI_ADDR_ATME] =	"atme",
262131826Sharti		[UNI_ADDR_DATA] =	"data",
263131826Sharti		[UNI_ADDR_PRIVATE] =	"private",
264131826Sharti	};
265131826Sharti
266131826Sharti	cc_dumpf(d, "port(%p) %u: %s\n", p, p->param.port,
267131826Sharti	    (p->admin == CCPORT_STOPPED) ? "STOPPED" :
268131826Sharti	    (p->admin == CCPORT_RUNNING) ? "RUNNING" : "????");
269131826Sharti	cc_dumpf(d, "  pcr=%u bits=%u.%u ids=%u/%u/%u esi=%02x:%02x:"
270131826Sharti	    "%02x:%02x:%02x:%02x naddrs=%u\n", p->param.pcr,
271131826Sharti	    p->param.max_vpi_bits, p->param.max_vci_bits, p->param.max_svpc_vpi,
272131826Sharti	    p->param.max_svcc_vpi, p->param.min_svcc_vci, p->param.esi[0],
273131826Sharti	    p->param.esi[1], p->param.esi[2], p->param.esi[3], p->param.esi[4],
274131826Sharti	    p->param.esi[5], p->param.num_addrs);
275131826Sharti
276131826Sharti	cc_dumpf(d, "  cookies:");
277131826Sharti	TAILQ_FOREACH(r, &p->cookies, link)
278131826Sharti		cc_dumpf(d, " %u(%p,%u)", r->cookie, r->conn, r->req);
279131826Sharti	cc_dumpf(d, "\n");
280131826Sharti
281131826Sharti	TAILQ_FOREACH(a, &p->addr_list, port_link) {
282131826Sharti		cc_dumpf(d, "  addr(%p): %s %s %u ", a,
283131826Sharti		    (a->addr.type < sizeof(ttab) / sizeof(ttab[0]) &&
284131826Sharti		    ttab[a->addr.type] != NULL) ? ttab[a->addr.type] : "?",
285131826Sharti		    (a->addr.plan < sizeof(ptab) / sizeof(ptab[0]) &&
286131826Sharti		    ptab[a->addr.plan] != NULL) ? ptab[a->addr.plan] : "?",
287131826Sharti		    a->addr.len);
288131826Sharti		for (i = 0; i < a->addr.len; i++)
289131826Sharti			cc_dumpf(d, "%02x", a->addr.addr[i]);
290131826Sharti		cc_dumpf(d, "\n");
291131826Sharti	}
292131826Sharti	LIST_FOREACH(c, &p->conn_list, port_link)
293131826Sharti		cc_dump_conn(d, c, "  ");
294131826Sharti}
295131826Sharti
296131826Sharti/*
297131826Sharti * Produce a textual dump of the state
298131826Sharti */
299131826Shartiint
300131826Sharticc_dump(struct ccdata *cc, size_t maxsiz, cc_dump_f func, void *uarg)
301131826Sharti{
302131826Sharti	struct dump d;
303131826Sharti	struct ccuser *user;
304131826Sharti	struct ccconn *conn;
305131826Sharti	struct ccport *port;
306131826Sharti
307131826Sharti	d.ret = 0;
308131826Sharti	d.uarg = uarg;
309131826Sharti	d.maxsiz = maxsiz;
310131826Sharti	d.cc = cc;
311131826Sharti	d.func = func;
312131826Sharti	d.buf = CCMALLOC(maxsiz);
313131826Sharti	if (d.buf == NULL)
314131826Sharti		return (ENOMEM);
315131826Sharti	d.len = 0;
316131826Sharti
317131826Sharti	cc_dumpf(&d, "dump of node %p\n", cc);
318131826Sharti
319131826Sharti	TAILQ_FOREACH(port, &cc->port_list, node_link)
320131826Sharti		cc_dump_port(&d, port);
321131826Sharti
322131826Sharti	LIST_FOREACH(user, &cc->user_list, node_link)
323131826Sharti		cc_dump_user(&d, user);
324131826Sharti
325131826Sharti	cc_dumpf(&d, "orphaned conns:\n");
326131826Sharti	LIST_FOREACH(conn, &cc->orphaned_conns, port_link)
327131826Sharti		cc_dump_conn(&d, conn, "");
328131826Sharti
329131826Sharti	if (d.len > 0 && d.ret == 0)
330131826Sharti		d.ret = d.func(d.cc, d.uarg, d.buf);
331131826Sharti
332131826Sharti	CCFREE(d.buf);
333131826Sharti	return (d.ret);
334131826Sharti}
335