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