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