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