diff options
Diffstat (limited to 'sys/contrib/ngatm/netnatm/api/cc_dump.c')
-rw-r--r-- | sys/contrib/ngatm/netnatm/api/cc_dump.c | 334 |
1 files changed, 334 insertions, 0 deletions
diff --git a/sys/contrib/ngatm/netnatm/api/cc_dump.c b/sys/contrib/ngatm/netnatm/api/cc_dump.c new file mode 100644 index 000000000000..d3b0c5819133 --- /dev/null +++ b/sys/contrib/ngatm/netnatm/api/cc_dump.c @@ -0,0 +1,334 @@ +/* + * Copyright (c) 2003-2004 + * Hartmut Brandt + * All rights reserved. + * + * Author: Harti Brandt <harti@freebsd.org> + * + * Redistribution of this software and documentation and use in source and + * binary forms, with or without modification, are permitted provided that + * the following conditions are met: + * + * 1. Redistributions of source code or documentation must retain the above + * copyright notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE AND DOCUMENTATION IS PROVIDED BY THE AUTHOR + * AND ITS CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE AUTHOR OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $Begemot: libunimsg/netnatm/api/cc_dump.c,v 1.1 2004/07/08 08:21:51 brandt Exp $ + * + * ATM API as defined per af-saa-0108 + */ + +#include <netnatm/unimsg.h> +#include <netnatm/msg/unistruct.h> +#include <netnatm/msg/unimsglib.h> +#include <netnatm/api/unisap.h> +#include <netnatm/sig/unidef.h> +#include <netnatm/api/atmapi.h> +#include <netnatm/api/ccatm.h> +#include <netnatm/api/ccpriv.h> + +#ifdef _KERNEL +#ifdef __FreeBSD__ +#include <sys/stdarg.h> +#endif +#else /* !_KERNEL */ +#include <stdarg.h> +#endif + +/* + * local structure to reduce number of arguments to functions + */ +struct dump { + struct ccdata *cc; /* what to dump */ + size_t maxsiz; /* size of user buffer */ + cc_dump_f func; /* user function */ + void *uarg; /* user supplied argument */ + char *buf; /* user buffer */ + size_t len; /* current string length */ + int ret; /* return code */ +}; + +static void cc_dumpf(struct dump *, const char *, ...) __printflike(2, 3); + +static void +cc_dumpf(struct dump *d, const char *fmt, ...) +{ + va_list ap; + int n; + + if (d->ret != 0) + return; + if (d->len >= d->maxsiz - 1) { + d->ret = d->func(d->cc, d->uarg, d->buf); + if (d->ret != 0) + return; + d->buf[0] = '\0'; + d->len = 0; + } + va_start(ap, fmt); + n = vsnprintf(d->buf + d->len, d->maxsiz - d->len, fmt, ap); + va_end(ap); + + if (n < 0) { + d->ret = errno; + return; + } + if ((size_t)n < d->maxsiz - d->len) { + d->len += n; + return; + } + + /* undo the vsnprintf() and flush */ + d->buf[d->len] = '\0'; + d->ret = d->func(d->cc, d->uarg, d->buf); + if (d->ret != 0) + return; + d->buf[0] = '\0'; + d->len = 0; + + va_start(ap, fmt); + n = vsnprintf(d->buf, d->maxsiz, fmt, ap); + va_end(ap); + + if (n < 0) { + d->ret = errno; + return; + } + if ((size_t)n >= d->maxsiz) { + /* ok, truncate */ + d->len = d->maxsiz - 1; + return; + } + d->len = n; +} + +/* + * Dump a SAP + */ +static void +cc_dump_sap(struct dump *d, const struct uni_sap *sap) +{ + static const char *const tagtab[] = { + [UNISVE_ABSENT] "absent", + [UNISVE_ANY] "any", + [UNISVE_PRESENT]"present" + }; + static const char *const plantab[] = { + [UNI_ADDR_E164] "E164", + [UNI_ADDR_ATME] "ATME", + }; + static const char *const hlitab[] = { + [UNI_BHLI_ISO] "ISO", + [UNI_BHLI_VENDOR] "VENDOR", + [UNI_BHLI_USER] "USER" + }; + u_int i; + + cc_dumpf(d, " sap(%p):\n", sap); + cc_dumpf(d, " addr=%s", tagtab[sap->addr.tag]); + if (sap->addr.tag == UNISVE_PRESENT) { + cc_dumpf(d, " %s %u ", plantab[sap->addr.plan], sap->addr.len); + if (sap->addr.plan == UNI_ADDR_E164) + for (i = 0; i < sap->addr.len; i++) + cc_dumpf(d, "%c", sap->addr.addr[i]); + else + for (i = 0; i < sap->addr.len; i++) + cc_dumpf(d, "%02x", sap->addr.addr[i]); + } + cc_dumpf(d, "\n"); + + cc_dumpf(d, " selector=%s", tagtab[sap->selector.tag]); + if (sap->selector.tag == UNISVE_PRESENT) + cc_dumpf(d, " %02x", sap->selector.selector); + cc_dumpf(d, "\n"); + + cc_dumpf(d, " blli_id2=%s", tagtab[sap->blli_id2.tag]); + if (sap->blli_id2.tag == UNISVE_PRESENT) + cc_dumpf(d, " %02x %02x", sap->blli_id2.proto, + sap->blli_id2.user); + cc_dumpf(d, "\n"); + + cc_dumpf(d, " blli_id3=%s", tagtab[sap->blli_id3.tag]); + if (sap->blli_id3.tag == UNISVE_PRESENT) + cc_dumpf(d, " %02x,%02x, %02x(%d),%03x,%02x", + sap->blli_id3.proto, sap->blli_id3.user, + sap->blli_id3.ipi, sap->blli_id3.noipi, + sap->blli_id3.oui, sap->blli_id3.pid); + cc_dumpf(d, "\n"); + + cc_dumpf(d, " bhli=%s", tagtab[sap->bhli.tag]); + if (sap->bhli.tag == UNISVE_PRESENT) { + cc_dumpf(d, " %s ", hlitab[sap->bhli.type]); + for (i = 0; i < sap->bhli.len; i++) + cc_dumpf(d, "%02x", sap->bhli.info[i]); + } + cc_dumpf(d, "\n"); +} + +/* + * Dump a user. + */ +static void +cc_dump_user(struct dump *d, const struct ccuser *user) +{ + struct ccconn *conn; + + cc_dumpf(d, "user(%p): %s '%s' %s\n", user, + cc_user_state2str(user->state), user->name, + (user->config == USER_P2P) ? "p2p" : + (user->config == USER_ROOT) ? "root" : + (user->config == USER_LEAF) ? "leaf" : "?"); + if (user->sap) + cc_dump_sap(d, user->sap); + + cc_dumpf(d, " queue=%u/%u accepted=%p aborted=%u\n", user->queue_max, + user->queue_act, user->accepted, user->aborted); + + cc_dumpf(d, " connq:"); + TAILQ_FOREACH(conn, &user->connq, connq_link) + cc_dumpf(d, "%p", conn); + cc_dumpf(d, "\n"); +} + +/* + * Dump a party + */ +static void +cc_dump_party(struct dump *d, const struct ccparty *party, const char *pfx) +{ + + cc_dumpf(d, "%s party(%p): %u.%u %s\n", pfx, party, + party->epref.flag, party->epref.epref, + cc_party_state2str(party->state)); +} + +/* + * Dump a connection + */ +static void +cc_dump_conn(struct dump *d, const struct ccconn *conn, const char *pfx) +{ + const struct ccparty *party; + + cc_dumpf(d, "%sconn(%p): %s\n", pfx, conn, + cc_conn_state2str(conn->state)); + cc_dumpf(d, "%s user=%p cref=%u.%u acceptor=%p\n", pfx, + conn->user, conn->cref.cref, conn->cref.flag, + conn->acceptor); + + cc_dumpf(d, "%s blli_sel=%u\n", pfx, conn->blli_selector); + + LIST_FOREACH(party, &conn->parties, link) + cc_dump_party(d, party, pfx); +} + +/* + * Dump a port + */ +static void +cc_dump_port(struct dump *d, const struct ccport *p) +{ + u_int i; + const struct ccaddr *a; + const struct ccconn *c; + const struct ccreq *r; + + static const char *const ttab[] = { + [UNI_ADDR_UNKNOWN] = "unknown", + [UNI_ADDR_INTERNATIONAL] = "international", + [UNI_ADDR_NATIONAL] = "national", + [UNI_ADDR_NETWORK] = "network", + [UNI_ADDR_SUBSCR] = "subscr", + [UNI_ADDR_ABBR] = "abbr", + }; + static const char *const ptab[] = { + [UNI_ADDR_UNKNOWN] = "unknown", + [UNI_ADDR_E164] = "e164", + [UNI_ADDR_ATME] = "atme", + [UNI_ADDR_DATA] = "data", + [UNI_ADDR_PRIVATE] = "private", + }; + + cc_dumpf(d, "port(%p) %u: %s\n", p, p->param.port, + (p->admin == CCPORT_STOPPED) ? "STOPPED" : + (p->admin == CCPORT_RUNNING) ? "RUNNING" : "????"); + cc_dumpf(d, " pcr=%u bits=%u.%u ids=%u/%u/%u esi=%02x:%02x:" + "%02x:%02x:%02x:%02x naddrs=%u\n", p->param.pcr, + p->param.max_vpi_bits, p->param.max_vci_bits, p->param.max_svpc_vpi, + p->param.max_svcc_vpi, p->param.min_svcc_vci, p->param.esi[0], + p->param.esi[1], p->param.esi[2], p->param.esi[3], p->param.esi[4], + p->param.esi[5], p->param.num_addrs); + + cc_dumpf(d, " cookies:"); + TAILQ_FOREACH(r, &p->cookies, link) + cc_dumpf(d, " %u(%p,%u)", r->cookie, r->conn, r->req); + cc_dumpf(d, "\n"); + + TAILQ_FOREACH(a, &p->addr_list, port_link) { + cc_dumpf(d, " addr(%p): %s %s %u ", a, + (a->addr.type < sizeof(ttab) / sizeof(ttab[0]) && + ttab[a->addr.type] != NULL) ? ttab[a->addr.type] : "?", + (a->addr.plan < sizeof(ptab) / sizeof(ptab[0]) && + ptab[a->addr.plan] != NULL) ? ptab[a->addr.plan] : "?", + a->addr.len); + for (i = 0; i < a->addr.len; i++) + cc_dumpf(d, "%02x", a->addr.addr[i]); + cc_dumpf(d, "\n"); + } + LIST_FOREACH(c, &p->conn_list, port_link) + cc_dump_conn(d, c, " "); +} + +/* + * Produce a textual dump of the state + */ +int +cc_dump(struct ccdata *cc, size_t maxsiz, cc_dump_f func, void *uarg) +{ + struct dump d; + struct ccuser *user; + struct ccconn *conn; + struct ccport *port; + + d.ret = 0; + d.uarg = uarg; + d.maxsiz = maxsiz; + d.cc = cc; + d.func = func; + d.buf = CCMALLOC(maxsiz); + if (d.buf == NULL) + return (ENOMEM); + d.len = 0; + + cc_dumpf(&d, "dump of node %p\n", cc); + + TAILQ_FOREACH(port, &cc->port_list, node_link) + cc_dump_port(&d, port); + + LIST_FOREACH(user, &cc->user_list, node_link) + cc_dump_user(&d, user); + + cc_dumpf(&d, "orphaned conns:\n"); + LIST_FOREACH(conn, &cc->orphaned_conns, port_link) + cc_dump_conn(&d, conn, ""); + + if (d.len > 0 && d.ret == 0) + d.ret = d.func(d.cc, d.uarg, d.buf); + + CCFREE(d.buf); + return (d.ret); +} |