debug.c revision 201123
1164190Sjkoshy/* 2164190Sjkoshy * debug.c 3164190Sjkoshy * 4164190Sjkoshy * Copyright (c) 1996-1999 Whistle Communications, Inc. 5164190Sjkoshy * All rights reserved. 6164190Sjkoshy * 7164190Sjkoshy * Subject to the following obligations and disclaimer of warranty, use and 8164190Sjkoshy * redistribution of this software, in source or object code forms, with or 9164190Sjkoshy * without modifications are expressly permitted by Whistle Communications; 10164190Sjkoshy * provided, however, that: 11164190Sjkoshy * 1. Any and all reproductions of the source or object code must include the 12164190Sjkoshy * copyright notice above and the following disclaimer of warranties; and 13164190Sjkoshy * 2. No rights are granted, in any manner or form, to use Whistle 14164190Sjkoshy * Communications, Inc. trademarks, including the mark "WHISTLE 15164190Sjkoshy * COMMUNICATIONS" on advertising, endorsements, or otherwise except as 16164190Sjkoshy * such appears in the above copyright notice or in the software. 17164190Sjkoshy * 18164190Sjkoshy * THIS SOFTWARE IS BEING PROVIDED BY WHISTLE COMMUNICATIONS "AS IS", AND 19164190Sjkoshy * TO THE MAXIMUM EXTENT PERMITTED BY LAW, WHISTLE COMMUNICATIONS MAKES NO 20164190Sjkoshy * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING THIS SOFTWARE, 21164190Sjkoshy * INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED WARRANTIES OF 22164190Sjkoshy * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. 23164190Sjkoshy * WHISTLE COMMUNICATIONS DOES NOT WARRANT, GUARANTEE, OR MAKE ANY 24164190Sjkoshy * REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS OF THE USE OF THIS 25164190Sjkoshy * SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY, RELIABILITY OR OTHERWISE. 26164190Sjkoshy * IN NO EVENT SHALL WHISTLE COMMUNICATIONS BE LIABLE FOR ANY DAMAGES 27164190Sjkoshy * RESULTING FROM OR ARISING OUT OF ANY USE OF THIS SOFTWARE, INCLUDING 28164190Sjkoshy * WITHOUT LIMITATION, ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 29164190Sjkoshy * PUNITIVE, OR CONSEQUENTIAL DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR 30164190Sjkoshy * SERVICES, LOSS OF USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY 31164190Sjkoshy * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 32164190Sjkoshy * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 33164190Sjkoshy * THIS SOFTWARE, EVEN IF WHISTLE COMMUNICATIONS IS ADVISED OF THE POSSIBILITY 34164190Sjkoshy * OF SUCH DAMAGE. 35164190Sjkoshy * 36164190Sjkoshy * Author: Archie Cobbs <archie@whistle.com> 37164190Sjkoshy * 38164190Sjkoshy * $Whistle: debug.c,v 1.24 1999/01/24 01:15:33 archie Exp $ 39164190Sjkoshy */ 40164190Sjkoshy 41164190Sjkoshy#include <sys/cdefs.h> 42164190Sjkoshy__FBSDID("$FreeBSD: head/lib/libnetgraph/debug.c 201123 2009-12-28 10:48:01Z luigi $"); 43164190Sjkoshy 44164190Sjkoshy#include <sys/types.h> 45164190Sjkoshy#include <sys/time.h> 46164190Sjkoshy#include <sys/ioctl.h> 47164190Sjkoshy 48164190Sjkoshy#include <stdarg.h> 49164190Sjkoshy 50164190Sjkoshy#include <netinet/in.h> 51164190Sjkoshy#include <net/ethernet.h> 52164190Sjkoshy#include <net/bpf.h> 53164190Sjkoshy 54164190Sjkoshy#include <netgraph/ng_message.h> 55164190Sjkoshy#include <netgraph/ng_socket.h> 56164190Sjkoshy 57164190Sjkoshy#include "netgraph.h" 58164190Sjkoshy#include "internal.h" 59164190Sjkoshy 60164190Sjkoshy#include <netgraph/ng_UI.h> 61164190Sjkoshy#include <netgraph/ng_async.h> 62164190Sjkoshy#include <netgraph/ng_atmllc.h> 63164190Sjkoshy#include <netgraph/ng_bpf.h> 64164190Sjkoshy#include <netgraph/ng_bridge.h> 65164190Sjkoshy#include <netgraph/ng_cisco.h> 66164190Sjkoshy#include <netgraph/ng_device.h> 67164190Sjkoshy#include <netgraph/ng_echo.h> 68164190Sjkoshy#include <netgraph/ng_eiface.h> 69164190Sjkoshy#include <netgraph/ng_etf.h> 70164190Sjkoshy#include <netgraph/ng_ether.h> 71164190Sjkoshy#include <netgraph/ng_fec.h> 72164190Sjkoshy#include <netgraph/ng_frame_relay.h> 73164190Sjkoshy#include <netgraph/ng_gif.h> 74164190Sjkoshy#include <netgraph/ng_gif_demux.h> 75164190Sjkoshy#include <netgraph/ng_hole.h> 76164190Sjkoshy#include <netgraph/ng_hub.h> 77164190Sjkoshy#include <netgraph/ng_iface.h> 78164190Sjkoshy#include <netgraph/ng_ip_input.h> 79164190Sjkoshy#include <netinet/ip_fw.h> 80164190Sjkoshy#include <netinet/ip_fw_private.h> /* the NGM cookie is here */ 81176727Sjkoshy#include <netgraph/ng_ipfw.h> 82176727Sjkoshy#include <netgraph/ng_ksocket.h> 83176727Sjkoshy#include <netgraph/ng_l2tp.h> 84164190Sjkoshy#include <netgraph/ng_lmi.h> 85164190Sjkoshy#include <netgraph/ng_mppc.h> 86164190Sjkoshy#include <netgraph/ng_nat.h> 87164190Sjkoshy#include <netgraph/ng_one2many.h> 88164190Sjkoshy#include <netgraph/ng_ppp.h> 89164190Sjkoshy#include <netgraph/ng_pppoe.h> 90164190Sjkoshy#include <netgraph/ng_pptpgre.h> 91164190Sjkoshy#include <netgraph/ng_rfc1490.h> 92164190Sjkoshy#include <netgraph/ng_socket.h> 93164190Sjkoshy#include <netgraph/ng_source.h> 94164190Sjkoshy#include <netgraph/ng_split.h> 95164190Sjkoshy#include <netgraph/ng_sppp.h> 96164190Sjkoshy#include <netgraph/ng_tcpmss.h> 97164190Sjkoshy#include <netgraph/ng_tee.h> 98164190Sjkoshy#include <netgraph/ng_tty.h> 99164190Sjkoshy#include <netgraph/ng_vjc.h> 100164190Sjkoshy#include <netgraph/ng_vlan.h> 101164190Sjkoshy#ifdef WHISTLE 102164190Sjkoshy#include <machine/../isa/df_def.h> 103164190Sjkoshy#include <machine/../isa/if_wfra.h> 104164190Sjkoshy#include <machine/../isa/ipac.h> 105164190Sjkoshy#include <netgraph/ng_df.h> 106164190Sjkoshy#include <netgraph/ng_ipac.h> 107164190Sjkoshy#include <netgraph/ng_tn.h> 108164190Sjkoshy#endif 109164190Sjkoshy 110164190Sjkoshy/* Global debug level */ 111164190Sjkoshyint _gNgDebugLevel = 0; 112164190Sjkoshy 113164190Sjkoshy/* Debug printing functions */ 114164190Sjkoshyvoid (*_NgLog) (const char *fmt,...) = warn; 115164190Sjkoshyvoid (*_NgLogx) (const char *fmt,...) = warnx; 116164190Sjkoshy 117164190Sjkoshy/* Internal functions */ 118164190Sjkoshystatic const char *NgCookie(int cookie); 119164190Sjkoshy 120164190Sjkoshy/* Known typecookie list */ 121164190Sjkoshystruct ng_cookie { 122164190Sjkoshy int cookie; 123164190Sjkoshy const char *type; 124164190Sjkoshy}; 125164190Sjkoshy 126164190Sjkoshy#define COOKIE(c) { NGM_ ## c ## _COOKIE, #c } 127164190Sjkoshy 128164190Sjkoshy/* List of known cookies */ 129164190Sjkoshystatic const struct ng_cookie cookies[] = { 130164190Sjkoshy COOKIE(UI), 131164190Sjkoshy COOKIE(ASYNC), 132164190Sjkoshy COOKIE(ATMLLC), 133164190Sjkoshy COOKIE(BPF), 134164190Sjkoshy COOKIE(BRIDGE), 135164190Sjkoshy COOKIE(CISCO), 136164190Sjkoshy COOKIE(DEVICE), 137164190Sjkoshy COOKIE(ECHO), 138176727Sjkoshy COOKIE(EIFACE), 139176727Sjkoshy COOKIE(ETF), 140176727Sjkoshy COOKIE(ETHER), 141176727Sjkoshy COOKIE(FEC), 142176727Sjkoshy COOKIE(FRAMERELAY), 143176727Sjkoshy COOKIE(GIF), 144176727Sjkoshy COOKIE(GIF_DEMUX), 145176727Sjkoshy COOKIE(GENERIC), 146164190Sjkoshy COOKIE(HOLE), 147164190Sjkoshy COOKIE(HUB), 148164190Sjkoshy COOKIE(IFACE), 149164190Sjkoshy COOKIE(IP_INPUT), 150164190Sjkoshy COOKIE(IPFW), 151164190Sjkoshy COOKIE(KSOCKET), 152164190Sjkoshy COOKIE(L2TP), 153164190Sjkoshy COOKIE(LMI), 154 COOKIE(MPPC), 155 COOKIE(NAT), 156 COOKIE(ONE2MANY), 157 COOKIE(PPP), 158 COOKIE(PPPOE), 159 COOKIE(PPTPGRE), 160 COOKIE(RFC1490), 161 COOKIE(SOCKET), 162 COOKIE(SOURCE), 163 COOKIE(SPLIT), 164 COOKIE(SPPP), 165 COOKIE(TCPMSS), 166 COOKIE(TEE), 167 COOKIE(TTY), 168 COOKIE(VJC), 169 COOKIE(VLAN), 170#ifdef WHISTLE 171 COOKIE(DF), 172 COOKIE(IPAC), 173 COOKIE(TN), 174 COOKIE(WFRA), 175#endif 176 { 0, NULL } 177}; 178 179/* 180 * Set debug level, ie, verbosity, if "level" is non-negative. 181 * Returns old debug level. 182 */ 183int 184NgSetDebug(int level) 185{ 186 int old = _gNgDebugLevel; 187 188 if (level < 0) 189 level = old; 190 _gNgDebugLevel = level; 191 return (old); 192} 193 194/* 195 * Set debug logging functions. 196 */ 197void 198NgSetErrLog(void (*log) (const char *fmt,...), 199 void (*logx) (const char *fmt,...)) 200{ 201 _NgLog = log; 202 _NgLogx = logx; 203} 204 205/* 206 * Display a netgraph sockaddr 207 */ 208void 209_NgDebugSockaddr(const struct sockaddr_ng *sg) 210{ 211 NGLOGX("SOCKADDR: { fam=%d len=%d addr=\"%s\" }", 212 sg->sg_family, sg->sg_len, sg->sg_data); 213} 214 215#define ARGS_BUFSIZE 2048 216#define RECURSIVE_DEBUG_ADJUST 4 217 218/* 219 * Display a negraph message 220 */ 221void 222_NgDebugMsg(const struct ng_mesg *msg, const char *path) 223{ 224 u_char buf[2 * sizeof(struct ng_mesg) + ARGS_BUFSIZE]; 225 struct ng_mesg *const req = (struct ng_mesg *)buf; 226 struct ng_mesg *const bin = (struct ng_mesg *)req->data; 227 int arglen, csock = -1; 228 229 /* Display header stuff */ 230 NGLOGX("NG_MESG :"); 231 NGLOGX(" vers %d", msg->header.version); 232 NGLOGX(" arglen %d", msg->header.arglen); 233 NGLOGX(" flags %ld", msg->header.flags); 234 NGLOGX(" token %lu", (u_long)msg->header.token); 235 NGLOGX(" cookie %s (%d)", 236 NgCookie(msg->header.typecookie), msg->header.typecookie); 237 238 /* At lower debugging levels, skip ASCII translation */ 239 if (_gNgDebugLevel <= 2) 240 goto fail2; 241 242 /* If path is not absolute, don't bother trying to use relative 243 address on a different socket for the ASCII translation */ 244 if (strchr(path, ':') == NULL) 245 goto fail2; 246 247 /* Get a temporary socket */ 248 if (NgMkSockNode(NULL, &csock, NULL) < 0) 249 goto fail; 250 251 /* Copy binary message into request message payload */ 252 arglen = msg->header.arglen; 253 if (arglen > ARGS_BUFSIZE) 254 arglen = ARGS_BUFSIZE; 255 memcpy(bin, msg, sizeof(*msg) + arglen); 256 bin->header.arglen = arglen; 257 258 /* Lower debugging to avoid infinite recursion */ 259 _gNgDebugLevel -= RECURSIVE_DEBUG_ADJUST; 260 261 /* Ask the node to translate the binary message to ASCII for us */ 262 if (NgSendMsg(csock, path, NGM_GENERIC_COOKIE, 263 NGM_BINARY2ASCII, bin, sizeof(*bin) + bin->header.arglen) < 0) { 264 _gNgDebugLevel += RECURSIVE_DEBUG_ADJUST; 265 goto fail; 266 } 267 if (NgRecvMsg(csock, req, sizeof(buf), NULL) < 0) { 268 _gNgDebugLevel += RECURSIVE_DEBUG_ADJUST; 269 goto fail; 270 } 271 272 /* Restore debugging level */ 273 _gNgDebugLevel += RECURSIVE_DEBUG_ADJUST; 274 275 /* Display command string and arguments */ 276 NGLOGX(" cmd %s (%d)", bin->header.cmdstr, bin->header.cmd); 277 NGLOGX(" args %s", bin->data); 278 goto done; 279 280fail: 281 /* Just display binary version */ 282 NGLOGX(" [error decoding message: %s]", strerror(errno)); 283fail2: 284 NGLOGX(" cmd %d", msg->header.cmd); 285 NGLOGX(" args (%d bytes)", msg->header.arglen); 286 _NgDebugBytes((u_char *)msg->data, msg->header.arglen); 287 288done: 289 if (csock != -1) 290 (void)close(csock); 291} 292 293/* 294 * Return the name of the node type corresponding to the cookie 295 */ 296static const char * 297NgCookie(int cookie) 298{ 299 int k; 300 301 for (k = 0; cookies[k].cookie != 0; k++) { 302 if (cookies[k].cookie == cookie) 303 return cookies[k].type; 304 } 305 return "??"; 306} 307 308/* 309 * Dump bytes in hex 310 */ 311void 312_NgDebugBytes(const u_char *ptr, int len) 313{ 314 char buf[100]; 315 int k, count; 316 317#define BYPERLINE 16 318 319 for (count = 0; count < len; ptr += BYPERLINE, count += BYPERLINE) { 320 321 /* Do hex */ 322 snprintf(buf, sizeof(buf), "%04x: ", count); 323 for (k = 0; k < BYPERLINE; k++, count++) 324 if (count < len) 325 snprintf(buf + strlen(buf), 326 sizeof(buf) - strlen(buf), "%02x ", ptr[k]); 327 else 328 snprintf(buf + strlen(buf), 329 sizeof(buf) - strlen(buf), " "); 330 snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " "); 331 count -= BYPERLINE; 332 333 /* Do ASCII */ 334 for (k = 0; k < BYPERLINE; k++, count++) 335 if (count < len) 336 snprintf(buf + strlen(buf), 337 sizeof(buf) - strlen(buf), 338 "%c", isprint(ptr[k]) ? ptr[k] : '.'); 339 else 340 snprintf(buf + strlen(buf), 341 sizeof(buf) - strlen(buf), " "); 342 count -= BYPERLINE; 343 344 /* Print it */ 345 NGLOGX("%s", buf); 346 } 347} 348 349