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