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