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