1 2 /* 3 * debug.c 4 * 5 * Copyright (c) 1996-1999 Whistle Communications, Inc. 6 * All rights reserved. 7 * 8 * Subject to the following obligations and disclaimer of warranty, use and 9 * redistribution of this software, in source or object code forms, with or 10 * without modifications are expressly permitted by Whistle Communications; 11 * provided, however, that: 12 * 1. Any and all reproductions of the source or object code must include the 13 * copyright notice above and the following disclaimer of warranties; and 14 * 2. No rights are granted, in any manner or form, to use Whistle 15 * Communications, Inc. trademarks, including the mark "WHISTLE 16 * COMMUNICATIONS" on advertising, endorsements, or otherwise except as 17 * such appears in the above copyright notice or in the software. 18 * 19 * THIS SOFTWARE IS BEING PROVIDED BY WHISTLE COMMUNICATIONS "AS IS", AND 20 * TO THE MAXIMUM EXTENT PERMITTED BY LAW, WHISTLE COMMUNICATIONS MAKES NO 21 * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING THIS SOFTWARE, 22 * INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED WARRANTIES OF 23 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. 24 * WHISTLE COMMUNICATIONS DOES NOT WARRANT, GUARANTEE, OR MAKE ANY 25 * REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS OF THE USE OF THIS 26 * SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY, RELIABILITY OR OTHERWISE. 27 * IN NO EVENT SHALL WHISTLE COMMUNICATIONS BE LIABLE FOR ANY DAMAGES 28 * RESULTING FROM OR ARISING OUT OF ANY USE OF THIS SOFTWARE, INCLUDING 29 * WITHOUT LIMITATION, ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 30 * PUNITIVE, OR CONSEQUENTIAL DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR 31 * SERVICES, LOSS OF USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY 32 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 33 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 34 * THIS SOFTWARE, EVEN IF WHISTLE COMMUNICATIONS IS ADVISED OF THE POSSIBILITY 35 * OF SUCH DAMAGE. 36 * 37 * Author: Archie Cobbs <archie@whistle.com> 38 * 39 * $FreeBSD: src/lib/libnetgraph/debug.c,v 1.5.2.1 2000/05/01 18:09:54 archie Exp $ 40 * $DragonFly: src/lib/libnetgraph/debug.c,v 1.4 2007/06/17 20:33:14 swildner Exp $ 41 * $Whistle: debug.c,v 1.24 1999/01/24 01:15:33 archie Exp $ 42 */ 43 44 #include <sys/types.h> 45 #include <sys/time.h> 46 #include <sys/ioctl.h> 47 48 #include <stdarg.h> 49 50 #include <netinet/in.h> 51 #include <net/ethernet.h> 52 #include <net/bpf.h> 53 54 #include <netgraph/ng_message.h> 55 #include <netgraph/socket/ng_socket.h> 56 57 #include "netgraph.h" 58 #include "internal.h" 59 60 #include <netgraph/UI/ng_UI.h> 61 #include <netgraph/async/ng_async.h> 62 #include <netgraph/bpf/ng_bpf.h> 63 #include <netgraph/bridge/ng_bridge.h> 64 #include <netgraph/cisco/ng_cisco.h> 65 #include <netgraph/echo/ng_echo.h> 66 #include <netgraph/eiface/ng_eiface.h> 67 #include <netgraph/etf/ng_etf.h> 68 #include <netgraph/ether/ng_ether.h> 69 #include <netgraph/frame_relay/ng_frame_relay.h> 70 #include <netgraph/hole/ng_hole.h> 71 #include <netgraph/iface/ng_iface.h> 72 #include <netgraph/ksocket/ng_ksocket.h> 73 #include <netgraph/l2tp/ng_l2tp.h> 74 #include <netgraph/lmi/ng_lmi.h> 75 #include <netgraph/mppc/ng_mppc.h> 76 #include <netgraph/one2many/ng_one2many.h> 77 #include <netgraph/ppp/ng_ppp.h> 78 #include <netgraph/pppoe/ng_pppoe.h> 79 #include <netgraph/pptpgre/ng_pptpgre.h> 80 #include <netgraph/rfc1490/ng_rfc1490.h> 81 #include <netgraph/socket/ng_socket.h> 82 #include <netgraph/tee/ng_tee.h> 83 #include <netgraph/tty/ng_tty.h> 84 #include <netgraph/vjc/ng_vjc.h> 85 #ifdef WHISTLE 86 #include <machine/../isa/df_def.h> 87 #include <machine/../isa/if_wfra.h> 88 #include <machine/../isa/ipac.h> 89 #include <netgraph/ng_df.h> 90 #include <netgraph/ng_ipac.h> 91 #include <netgraph/ng_tn.h> 92 #endif 93 94 /* Global debug level */ 95 int _gNgDebugLevel = 0; 96 97 /* Debug printing functions */ 98 void (*_NgLog) (const char *fmt,...) = warn; 99 void (*_NgLogx) (const char *fmt,...) = warnx; 100 101 /* Internal functions */ 102 static const char *NgCookie(int cookie); 103 104 /* Known typecookie list */ 105 struct ng_cookie { 106 int cookie; 107 const char *type; 108 }; 109 110 #define COOKIE(c) { NGM_ ## c ## _COOKIE, #c } 111 112 /* List of known cookies */ 113 static const struct ng_cookie cookies[] = { 114 COOKIE(UI), 115 COOKIE(ASYNC), 116 COOKIE(BPF), 117 COOKIE(BRIDGE), 118 COOKIE(CISCO), 119 COOKIE(ECHO), 120 COOKIE(EIFACE), 121 COOKIE(ETF), 122 COOKIE(ETHER), 123 COOKIE(FRAMERELAY), 124 COOKIE(GENERIC), 125 COOKIE(HOLE), 126 COOKIE(IFACE), 127 COOKIE(KSOCKET), 128 COOKIE(L2TP), 129 COOKIE(LMI), 130 COOKIE(MPPC), 131 COOKIE(ONE2MANY), 132 COOKIE(PPP), 133 COOKIE(PPPOE), 134 COOKIE(PPTPGRE), 135 COOKIE(RFC1490), 136 COOKIE(SOCKET), 137 COOKIE(TEE), 138 COOKIE(TTY), 139 COOKIE(VJC), 140 #ifdef WHISTLE 141 COOKIE(DF), 142 COOKIE(IPAC), 143 COOKIE(TN), 144 COOKIE(WFRA), 145 #endif 146 { 0, NULL } 147 }; 148 149 /* 150 * Set debug level, ie, verbosity, if "level" is non-negative. 151 * Returns old debug level. 152 */ 153 int 154 NgSetDebug(int level) 155 { 156 int old = _gNgDebugLevel; 157 158 if (level < 0) 159 level = old; 160 _gNgDebugLevel = level; 161 return (old); 162 } 163 164 /* 165 * Set debug logging functions. 166 */ 167 void 168 NgSetErrLog(void (*log) (const char *fmt,...), 169 void (*logx) (const char *fmt,...)) 170 { 171 _NgLog = log; 172 _NgLogx = logx; 173 } 174 175 /* 176 * Display a netgraph sockaddr 177 */ 178 void 179 _NgDebugSockaddr(const struct sockaddr_ng *sg) 180 { 181 NGLOGX("SOCKADDR: { fam=%d len=%d addr=\"%s\" }", 182 sg->sg_family, sg->sg_len, sg->sg_data); 183 } 184 185 #define ARGS_BUFSIZE 2048 186 #define RECURSIVE_DEBUG_ADJUST 4 187 188 /* 189 * Display a negraph message 190 */ 191 void 192 _NgDebugMsg(const struct ng_mesg *msg, const char *path) 193 { 194 u_char buf[2 * sizeof(struct ng_mesg) + ARGS_BUFSIZE]; 195 struct ng_mesg *const req = (struct ng_mesg *)buf; 196 struct ng_mesg *const bin = (struct ng_mesg *)req->data; 197 int arglen, csock = -1; 198 199 /* Display header stuff */ 200 NGLOGX("NG_MESG :"); 201 NGLOGX(" vers %d", msg->header.version); 202 NGLOGX(" arglen %d", msg->header.arglen); 203 NGLOGX(" flags %ld", msg->header.flags); 204 NGLOGX(" token %lu", (u_long)msg->header.token); 205 NGLOGX(" cookie %s (%d)", 206 NgCookie(msg->header.typecookie), msg->header.typecookie); 207 208 /* At lower debugging levels, skip ASCII translation */ 209 if (_gNgDebugLevel <= 2) 210 goto fail2; 211 212 /* If path is not absolute, don't bother trying to use relative 213 address on a different socket for the ASCII translation */ 214 if (strchr(path, ':') == NULL) 215 goto fail2; 216 217 /* Get a temporary socket */ 218 if (NgMkSockNode(NULL, &csock, NULL) < 0) 219 goto fail; 220 221 /* Copy binary message into request message payload */ 222 arglen = msg->header.arglen; 223 if (arglen > ARGS_BUFSIZE) 224 arglen = ARGS_BUFSIZE; 225 memcpy(bin, msg, sizeof(*msg) + arglen); 226 bin->header.arglen = arglen; 227 228 /* Lower debugging to avoid infinite recursion */ 229 _gNgDebugLevel -= RECURSIVE_DEBUG_ADJUST; 230 231 /* Ask the node to translate the binary message to ASCII for us */ 232 if (NgSendMsg(csock, path, NGM_GENERIC_COOKIE, 233 NGM_BINARY2ASCII, bin, sizeof(*bin) + bin->header.arglen) < 0) { 234 _gNgDebugLevel += RECURSIVE_DEBUG_ADJUST; 235 goto fail; 236 } 237 if (NgRecvMsg(csock, req, sizeof(buf), NULL) < 0) { 238 _gNgDebugLevel += RECURSIVE_DEBUG_ADJUST; 239 goto fail; 240 } 241 242 /* Restore debugging level */ 243 _gNgDebugLevel += RECURSIVE_DEBUG_ADJUST; 244 245 /* Display command string and arguments */ 246 NGLOGX(" cmd %s (%d)", bin->header.cmdstr, bin->header.cmd); 247 NGLOGX(" args %s", bin->data); 248 goto done; 249 250 fail: 251 /* Just display binary version */ 252 NGLOGX(" [error decoding message: %s]", strerror(errno)); 253 fail2: 254 NGLOGX(" cmd %d", msg->header.cmd); 255 NGLOGX(" args (%d bytes)", msg->header.arglen); 256 _NgDebugBytes(msg->data, msg->header.arglen); 257 258 done: 259 if (csock != -1) 260 (void)close(csock); 261 } 262 263 /* 264 * Return the name of the node type corresponding to the cookie 265 */ 266 static const char * 267 NgCookie(int cookie) 268 { 269 int k; 270 271 for (k = 0; cookies[k].cookie != 0; k++) { 272 if (cookies[k].cookie == cookie) 273 return cookies[k].type; 274 } 275 return "??"; 276 } 277 278 /* 279 * Dump bytes in hex 280 */ 281 void 282 _NgDebugBytes(const u_char *ptr, int len) 283 { 284 char buf[100]; 285 int k, count; 286 287 #define BYPERLINE 16 288 289 for (count = 0; count < len; ptr += BYPERLINE, count += BYPERLINE) { 290 291 /* Do hex */ 292 snprintf(buf, sizeof(buf), "%04x: ", count); 293 for (k = 0; k < BYPERLINE; k++, count++) 294 if (count < len) 295 snprintf(buf + strlen(buf), 296 sizeof(buf) - strlen(buf), "%02x ", ptr[k]); 297 else 298 snprintf(buf + strlen(buf), 299 sizeof(buf) - strlen(buf), " "); 300 snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " "); 301 count -= BYPERLINE; 302 303 /* Do ASCII */ 304 for (k = 0; k < BYPERLINE; k++, count++) 305 if (count < len) 306 snprintf(buf + strlen(buf), 307 sizeof(buf) - strlen(buf), 308 "%c", isprint(ptr[k]) ? ptr[k] : '.'); 309 else 310 snprintf(buf + strlen(buf), 311 sizeof(buf) - strlen(buf), " "); 312 count -= BYPERLINE; 313 314 /* Print it */ 315 NGLOGX("%s", buf); 316 } 317 } 318 319