]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - sys/contrib/ngatm/netnatm/api/cc_dump.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / sys / contrib / ngatm / netnatm / api / cc_dump.c
1 /*
2  * Copyright (c) 2003-2004
3  *      Hartmut Brandt
4  *      All rights reserved.
5  *
6  * Author: Harti Brandt <harti@freebsd.org>
7  *
8  * Redistribution of this software and documentation and use in source and
9  * binary forms, with or without modification, are permitted provided that
10  * the following conditions are met:
11  *
12  * 1. Redistributions of source code or documentation must retain the above
13  *    copyright notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE AND DOCUMENTATION IS PROVIDED BY THE AUTHOR
19  * AND ITS CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
20  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
21  * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
22  * THE AUTHOR OR ITS CONTRIBUTORS  BE LIABLE FOR ANY DIRECT, INDIRECT,
23  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
25  * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
26  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
27  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
28  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  *
30  * $Begemot: libunimsg/netnatm/api/cc_dump.c,v 1.3 2004/08/05 07:10:56 brandt Exp $
31  *
32  * ATM API as defined per af-saa-0108
33  */
34
35 #include <netnatm/unimsg.h>
36 #include <netnatm/msg/unistruct.h>
37 #include <netnatm/msg/unimsglib.h>
38 #include <netnatm/api/unisap.h>
39 #include <netnatm/sig/unidef.h>
40 #include <netnatm/api/atmapi.h>
41 #include <netnatm/api/ccatm.h>
42 #include <netnatm/api/ccpriv.h>
43
44 #ifdef _KERNEL
45 #ifdef __FreeBSD__
46 #include <machine/stdarg.h>
47 #endif
48 #else   /* !_KERNEL */
49 #include <stdarg.h>
50 #endif
51
52 /*
53  * local structure to reduce number of arguments to functions
54  */
55 struct dump {
56         struct ccdata   *cc;    /* what to dump */
57         size_t          maxsiz; /* size of user buffer */
58         cc_dump_f       func;   /* user function */
59         void            *uarg;  /* user supplied argument */
60         char            *buf;   /* user buffer */
61         size_t          len;    /* current string length */
62         int             ret;    /* return code */
63 };
64
65 static void cc_dumpf(struct dump *, const char *, ...) __printflike(2, 3);
66
67 static void
68 cc_dumpf(struct dump *d, const char *fmt, ...)
69 {
70         va_list ap;
71         int n;
72
73         if (d->ret != 0)
74                 return;
75         if (d->len >= d->maxsiz - 1) {
76                 d->ret = d->func(d->cc, d->uarg, d->buf);
77                 if (d->ret != 0)
78                         return;
79                 d->buf[0] = '\0';
80                 d->len = 0;
81         }
82         va_start(ap, fmt);
83         n = vsnprintf(d->buf + d->len, d->maxsiz - d->len, fmt, ap);
84         va_end(ap);
85
86         if (n < 0) {
87                 d->ret = CCGETERRNO();
88                 return;
89         }
90         if ((size_t)n < d->maxsiz - d->len) {
91                 d->len += n;
92                 return;
93         }
94
95         /* undo the vsnprintf() and flush */
96         d->buf[d->len] = '\0';
97         d->ret = d->func(d->cc, d->uarg, d->buf);
98         if (d->ret != 0)
99                 return;
100         d->buf[0] = '\0';
101         d->len = 0;
102
103         va_start(ap, fmt);
104         n = vsnprintf(d->buf, d->maxsiz, fmt, ap);
105         va_end(ap);
106
107         if (n < 0) {
108                 d->ret = CCGETERRNO();
109                 return;
110         }
111         if ((size_t)n >= d->maxsiz) {
112                 /* ok, truncate */
113                 d->len = d->maxsiz - 1;
114                 return;
115         }
116         d->len = n;
117 }
118
119 /*
120  * Dump a SAP
121  */
122 static void
123 cc_dump_sap(struct dump *d, const struct uni_sap *sap)
124 {
125         static const char *const tagtab[] = {
126                 [UNISVE_ABSENT] =       "absent",
127                 [UNISVE_ANY] =          "any",
128                 [UNISVE_PRESENT] =      "present"
129         };
130         static const char *const plantab[] = {
131                 [UNI_ADDR_E164] =       "E164",
132                 [UNI_ADDR_ATME] =       "ATME",
133         };
134         static const char *const hlitab[] = {
135                 [UNI_BHLI_ISO] =        "ISO",
136                 [UNI_BHLI_VENDOR] =     "VENDOR",
137                 [UNI_BHLI_USER] =       "USER"
138         };
139         u_int i;
140
141         cc_dumpf(d, "  sap(%p):\n", sap);
142         cc_dumpf(d, "    addr=%s", tagtab[sap->addr.tag]);
143         if (sap->addr.tag == UNISVE_PRESENT) {
144                 cc_dumpf(d, " %s %u ", plantab[sap->addr.plan], sap->addr.len);
145                 if (sap->addr.plan == UNI_ADDR_E164)
146                         for (i = 0; i < sap->addr.len; i++)
147                                 cc_dumpf(d, "%c", sap->addr.addr[i]);
148                 else
149                         for (i = 0; i < sap->addr.len; i++)
150                                 cc_dumpf(d, "%02x", sap->addr.addr[i]);
151         }
152         cc_dumpf(d, "\n");
153
154         cc_dumpf(d, "    selector=%s", tagtab[sap->selector.tag]);
155         if (sap->selector.tag == UNISVE_PRESENT)
156                 cc_dumpf(d, " %02x", sap->selector.selector);
157         cc_dumpf(d, "\n");
158
159         cc_dumpf(d, "    blli_id2=%s", tagtab[sap->blli_id2.tag]);
160         if (sap->blli_id2.tag == UNISVE_PRESENT)
161                 cc_dumpf(d, " %02x %02x", sap->blli_id2.proto,
162                     sap->blli_id2.user);
163         cc_dumpf(d, "\n");
164
165         cc_dumpf(d, "    blli_id3=%s", tagtab[sap->blli_id3.tag]);
166         if (sap->blli_id3.tag == UNISVE_PRESENT)
167                 cc_dumpf(d, " %02x,%02x, %02x(%d),%03x,%02x",
168                     sap->blli_id3.proto, sap->blli_id3.user,
169                     sap->blli_id3.ipi, sap->blli_id3.noipi,
170                     sap->blli_id3.oui, sap->blli_id3.pid);
171         cc_dumpf(d, "\n");
172
173         cc_dumpf(d, "    bhli=%s", tagtab[sap->bhli.tag]);
174         if (sap->bhli.tag == UNISVE_PRESENT) {
175                 cc_dumpf(d, " %s ", hlitab[sap->bhli.type]);
176                 for (i = 0; i < sap->bhli.len; i++)
177                         cc_dumpf(d, "%02x", sap->bhli.info[i]);
178         }
179         cc_dumpf(d, "\n");
180 }
181
182 /*
183  * Dump a user.
184  */
185 static void
186 cc_dump_user(struct dump *d, const struct ccuser *user)
187 {
188         struct ccconn *conn;
189
190         cc_dumpf(d, "user(%p): %s '%s' %s\n", user,
191             cc_user_state2str(user->state), user->name,
192             (user->config == USER_P2P) ? "p2p" :
193             (user->config == USER_ROOT) ? "root" :
194             (user->config == USER_LEAF) ? "leaf" : "?");
195         if (user->sap)
196                 cc_dump_sap(d, user->sap);
197
198         cc_dumpf(d, "  queue=%u/%u accepted=%p aborted=%u\n", user->queue_max,
199             user->queue_act, user->accepted, user->aborted);
200
201         cc_dumpf(d, "  connq:");
202         TAILQ_FOREACH(conn, &user->connq, connq_link)
203                 cc_dumpf(d, "%p", conn);
204         cc_dumpf(d, "\n");
205 }
206
207 /*
208  * Dump a party
209  */
210 static void
211 cc_dump_party(struct dump *d, const struct ccparty *party, const char *pfx)
212 {
213
214         cc_dumpf(d, "%s  party(%p): %u.%u %s\n", pfx, party,
215             party->epref.flag, party->epref.epref,
216             cc_party_state2str(party->state));
217 }
218
219 /*
220  * Dump a connection
221  */
222 static void
223 cc_dump_conn(struct dump *d, const struct ccconn *conn, const char *pfx)
224 {
225         const struct ccparty *party;
226
227         cc_dumpf(d, "%sconn(%p): %s\n", pfx, conn,
228             cc_conn_state2str(conn->state));
229         cc_dumpf(d, "%s  user=%p cref=%u.%u acceptor=%p\n", pfx,
230             conn->user, conn->cref.cref, conn->cref.flag,
231             conn->acceptor);
232
233         cc_dumpf(d, "%s  blli_sel=%u\n", pfx, conn->blli_selector);
234
235         LIST_FOREACH(party, &conn->parties, link)
236                 cc_dump_party(d, party, pfx);
237 }
238
239 /*
240  * Dump a port
241  */
242 static void
243 cc_dump_port(struct dump *d, const struct ccport *p)
244 {
245         u_int i;
246         const struct ccaddr *a;
247         const struct ccconn *c;
248         const struct ccreq *r;
249
250         static const char *const ttab[] = {
251                 [UNI_ADDR_UNKNOWN] =            "unknown",
252                 [UNI_ADDR_INTERNATIONAL] =      "international",
253                 [UNI_ADDR_NATIONAL] =           "national",
254                 [UNI_ADDR_NETWORK] =            "network",
255                 [UNI_ADDR_SUBSCR] =             "subscr",
256                 [UNI_ADDR_ABBR] =               "abbr",
257         };
258         static const char *const ptab[] = {
259                 [UNI_ADDR_UNKNOWN] =    "unknown",
260                 [UNI_ADDR_E164] =       "e164",
261                 [UNI_ADDR_ATME] =       "atme",
262                 [UNI_ADDR_DATA] =       "data",
263                 [UNI_ADDR_PRIVATE] =    "private",
264         };
265
266         cc_dumpf(d, "port(%p) %u: %s\n", p, p->param.port,
267             (p->admin == CCPORT_STOPPED) ? "STOPPED" :
268             (p->admin == CCPORT_RUNNING) ? "RUNNING" : "????");
269         cc_dumpf(d, "  pcr=%u bits=%u.%u ids=%u/%u/%u esi=%02x:%02x:"
270             "%02x:%02x:%02x:%02x naddrs=%u\n", p->param.pcr,
271             p->param.max_vpi_bits, p->param.max_vci_bits, p->param.max_svpc_vpi,
272             p->param.max_svcc_vpi, p->param.min_svcc_vci, p->param.esi[0],
273             p->param.esi[1], p->param.esi[2], p->param.esi[3], p->param.esi[4],
274             p->param.esi[5], p->param.num_addrs);
275
276         cc_dumpf(d, "  cookies:");
277         TAILQ_FOREACH(r, &p->cookies, link)
278                 cc_dumpf(d, " %u(%p,%u)", r->cookie, r->conn, r->req);
279         cc_dumpf(d, "\n");
280
281         TAILQ_FOREACH(a, &p->addr_list, port_link) {
282                 cc_dumpf(d, "  addr(%p): %s %s %u ", a,
283                     (a->addr.type < sizeof(ttab) / sizeof(ttab[0]) &&
284                     ttab[a->addr.type] != NULL) ? ttab[a->addr.type] : "?", 
285                     (a->addr.plan < sizeof(ptab) / sizeof(ptab[0]) &&
286                     ptab[a->addr.plan] != NULL) ? ptab[a->addr.plan] : "?", 
287                     a->addr.len);
288                 for (i = 0; i < a->addr.len; i++)
289                         cc_dumpf(d, "%02x", a->addr.addr[i]);
290                 cc_dumpf(d, "\n");
291         }
292         LIST_FOREACH(c, &p->conn_list, port_link)
293                 cc_dump_conn(d, c, "  ");
294 }
295
296 /*
297  * Produce a textual dump of the state
298  */
299 int
300 cc_dump(struct ccdata *cc, size_t maxsiz, cc_dump_f func, void *uarg)
301 {
302         struct dump d;
303         struct ccuser *user;
304         struct ccconn *conn;
305         struct ccport *port;
306
307         d.ret = 0;
308         d.uarg = uarg;
309         d.maxsiz = maxsiz;
310         d.cc = cc;
311         d.func = func;
312         d.buf = CCMALLOC(maxsiz);
313         if (d.buf == NULL)
314                 return (ENOMEM);
315         d.len = 0;
316
317         cc_dumpf(&d, "dump of node %p\n", cc);
318
319         TAILQ_FOREACH(port, &cc->port_list, node_link)
320                 cc_dump_port(&d, port);
321
322         LIST_FOREACH(user, &cc->user_list, node_link)
323                 cc_dump_user(&d, user);
324
325         cc_dumpf(&d, "orphaned conns:\n");
326         LIST_FOREACH(conn, &cc->orphaned_conns, port_link)
327                 cc_dump_conn(&d, conn, "");
328
329         if (d.len > 0 && d.ret == 0)
330                 d.ret = d.func(d.cc, d.uarg, d.buf);
331
332         CCFREE(d.buf);
333         return (d.ret);
334 }