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