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$ 40 * $Whistle: debug.c,v 1.24 1999/01/24 01:15:33 archie Exp $ 41 */ 42 43 #include <sys/types.h> 44 #include <sys/time.h> 45 #include <sys/ioctl.h> 46 47 #include <stdarg.h> 48 49 #include <netinet/in.h> 50 #include <net/ethernet.h> 51 #include <net/bpf.h> 52 53 #include <netgraph/ng_message.h> 54 #include <netgraph/ng_socket.h> 55 56 #include "netgraph.h" 57 #include "internal.h" 58 59 #include <netgraph/ng_UI.h> 60 #include <netgraph/ng_async.h> 61 #include <netgraph/ng_bpf.h> 62 #include <netgraph/ng_cisco.h> 63 #include <netgraph/ng_echo.h> 64 #include <netgraph/ng_ether.h> 65 #include <netgraph/ng_frame_relay.h> 66 #include <netgraph/ng_hole.h> 67 #include <netgraph/ng_iface.h> 68 #include <netgraph/ng_ksocket.h> 69 #include <netgraph/ng_lmi.h> 70 #include <netgraph/ng_ppp.h> 71 #include <netgraph/ng_pppoe.h> 72 #include <netgraph/ng_rfc1490.h> 73 #include <netgraph/ng_socket.h> 74 #include <netgraph/ng_tee.h> 75 #include <netgraph/ng_tty.h> 76 #include <netgraph/ng_vjc.h> 77 #ifdef WHISTLE 78 #include <machine/../isa/df_def.h> 79 #include <machine/../isa/if_wfra.h> 80 #include <machine/../isa/ipac.h> 81 #include <netgraph/ng_df.h> 82 #include <netgraph/ng_ipac.h> 83 #include <netgraph/ng_mppc.h> 84 #include <netgraph/ng_pptpgre.h> 85 #include <netgraph/ng_tn.h> 86 #endif 87 88 /* Global debug level */ 89 int _gNgDebugLevel = 0; 90 91 /* Debug printing functions */ 92 void (*_NgLog) (const char *fmt,...) = warn; 93 void (*_NgLogx) (const char *fmt,...) = warnx; 94 95 /* Internal functions */ 96 static const char *NgCookie(int cookie); 97 98 /* Known typecookie list */ 99 struct ng_cookie { 100 int cookie; 101 const char *type; 102 }; 103 104 #define COOKIE(c) { NGM_ ## c ## _COOKIE, #c } 105 106 /* List of known cookies */ 107 static const struct ng_cookie cookies[] = { 108 COOKIE(UI), 109 COOKIE(ASYNC), 110 COOKIE(BPF), 111 COOKIE(CISCO), 112 COOKIE(ECHO), 113 COOKIE(ETHER), 114 COOKIE(FRAMERELAY), 115 COOKIE(GENERIC), 116 COOKIE(HOLE), 117 COOKIE(IFACE), 118 COOKIE(KSOCKET), 119 COOKIE(LMI), 120 COOKIE(PPP), 121 COOKIE(PPPOE), 122 COOKIE(RFC1490), 123 COOKIE(SOCKET), 124 COOKIE(TEE), 125 COOKIE(TTY), 126 COOKIE(VJC), 127 #ifdef WHISTLE 128 COOKIE(DF), 129 COOKIE(IPAC), 130 COOKIE(MPPC), 131 COOKIE(PPTPGRE), 132 COOKIE(TN), 133 COOKIE(WFRA), 134 #endif 135 { 0, NULL } 136 }; 137 138 /* 139 * Set debug level, ie, verbosity, if "level" is non-negative. 140 * Returns old debug level. 141 */ 142 int 143 NgSetDebug(int level) 144 { 145 int old = _gNgDebugLevel; 146 147 if (level < 0) 148 level = old; 149 _gNgDebugLevel = level; 150 return (old); 151 } 152 153 /* 154 * Set debug logging functions. 155 */ 156 void 157 NgSetErrLog(void (*log) (const char *fmt,...), 158 void (*logx) (const char *fmt,...)) 159 { 160 _NgLog = log; 161 _NgLogx = logx; 162 } 163 164 /* 165 * Display a netgraph sockaddr 166 */ 167 void 168 _NgDebugSockaddr(const struct sockaddr_ng *sg) 169 { 170 NGLOGX("SOCKADDR: { fam=%d len=%d addr=\"%s\" }", 171 sg->sg_family, sg->sg_len, sg->sg_data); 172 } 173 174 #define ARGS_BUFSIZE 2048 175 #define RECURSIVE_DEBUG_ADJUST 4 176 177 /* 178 * Display a negraph message 179 */ 180 void 181 _NgDebugMsg(const struct ng_mesg *msg, const char *path) 182 { 183 u_char buf[2 * sizeof(struct ng_mesg) + ARGS_BUFSIZE]; 184 struct ng_mesg *const req = (struct ng_mesg *)buf; 185 struct ng_mesg *const bin = (struct ng_mesg *)req->data; 186 int arglen, csock = -1; 187 188 /* Display header stuff */ 189 NGLOGX("NG_MESG :"); 190 NGLOGX(" vers %d", msg->header.version); 191 NGLOGX(" arglen %d", msg->header.arglen); 192 NGLOGX(" flags %ld", msg->header.flags); 193 NGLOGX(" token %lu", (u_long)msg->header.token); 194 NGLOGX(" cookie %s (%d)", 195 NgCookie(msg->header.typecookie), msg->header.typecookie); 196 197 /* At lower debugging levels, skip ASCII translation */ 198 if (_gNgDebugLevel <= 2) 199 goto fail2; 200 201 /* If path is not absolute, don't bother trying to use relative 202 address on a different socket for the ASCII translation */ 203 if (strchr(path, ':') == NULL) 204 goto fail2; 205 206 /* Get a temporary socket */ 207 if (NgMkSockNode(NULL, &csock, NULL) < 0) 208 goto fail; 209 210 /* Copy binary message into request message payload */ 211 arglen = msg->header.arglen; 212 if (arglen > ARGS_BUFSIZE) 213 arglen = ARGS_BUFSIZE; 214 memcpy(bin, msg, sizeof(*msg) + arglen); 215 bin->header.arglen = arglen; 216 217 /* Lower debugging to avoid infinite recursion */ 218 _gNgDebugLevel -= RECURSIVE_DEBUG_ADJUST; 219 220 /* Ask the node to translate the binary message to ASCII for us */ 221 if (NgSendMsg(csock, path, NGM_GENERIC_COOKIE, 222 NGM_BINARY2ASCII, bin, sizeof(*bin) + bin->header.arglen) < 0) { 223 _gNgDebugLevel += RECURSIVE_DEBUG_ADJUST; 224 goto fail; 225 } 226 if (NgRecvMsg(csock, req, sizeof(buf), NULL) < 0) { 227 _gNgDebugLevel += RECURSIVE_DEBUG_ADJUST; 228 goto fail; 229 } 230 231 /* Restore debugging level */ 232 _gNgDebugLevel += RECURSIVE_DEBUG_ADJUST; 233 234 /* Display command string and arguments */ 235 NGLOGX(" cmd %s (%d)", bin->header.cmdstr, bin->header.cmd); 236 NGLOGX(" args %s", bin->data); 237 goto done; 238 239 fail: 240 /* Just display binary version */ 241 NGLOGX(" [error decoding message: %s]", strerror(errno)); 242 fail2: 243 NGLOGX(" cmd %d", msg->header.cmd); 244 NGLOGX(" args (%d bytes)", msg->header.arglen); 245 _NgDebugBytes(msg->data, msg->header.arglen); 246 247 done: 248 if (csock != -1) 249 (void)close(csock); 250 } 251 252 /* 253 * Return the name of the node type corresponding to the cookie 254 */ 255 static const char * 256 NgCookie(int cookie) 257 { 258 int k; 259 260 for (k = 0; cookies[k].cookie != 0; k++) { 261 if (cookies[k].cookie == cookie) 262 return cookies[k].type; 263 } 264 return "??"; 265 } 266 267 /* 268 * Dump bytes in hex 269 */ 270 void 271 _NgDebugBytes(const u_char *ptr, int len) 272 { 273 char buf[100]; 274 int k, count; 275 276 #define BYPERLINE 16 277 278 for (count = 0; count < len; ptr += BYPERLINE, count += BYPERLINE) { 279 280 /* Do hex */ 281 snprintf(buf, sizeof(buf), "%04x: ", count); 282 for (k = 0; k < BYPERLINE; k++, count++) 283 if (count < len) 284 snprintf(buf + strlen(buf), 285 sizeof(buf) - strlen(buf), "%02x ", ptr[k]); 286 else 287 snprintf(buf + strlen(buf), 288 sizeof(buf) - strlen(buf), " "); 289 snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " "); 290 count -= BYPERLINE; 291 292 /* Do ASCII */ 293 for (k = 0; k < BYPERLINE; k++, count++) 294 if (count < len) 295 snprintf(buf + strlen(buf), 296 sizeof(buf) - strlen(buf), 297 "%c", isprint(ptr[k]) ? ptr[k] : '.'); 298 else 299 snprintf(buf + strlen(buf), 300 sizeof(buf) - strlen(buf), " "); 301 count -= BYPERLINE; 302 303 /* Print it */ 304 NGLOGX("%s", buf); 305 } 306 } 307 308