152419Sjulian/*
252419Sjulian * debug.c
352419Sjulian *
452419Sjulian * Copyright (c) 1996-1999 Whistle Communications, Inc.
552419Sjulian * All rights reserved.
652419Sjulian *
752419Sjulian * Subject to the following obligations and disclaimer of warranty, use and
852419Sjulian * redistribution of this software, in source or object code forms, with or
952419Sjulian * without modifications are expressly permitted by Whistle Communications;
1052419Sjulian * provided, however, that:
1152419Sjulian * 1. Any and all reproductions of the source or object code must include the
1252419Sjulian *    copyright notice above and the following disclaimer of warranties; and
1352419Sjulian * 2. No rights are granted, in any manner or form, to use Whistle
1452419Sjulian *    Communications, Inc. trademarks, including the mark "WHISTLE
1552419Sjulian *    COMMUNICATIONS" on advertising, endorsements, or otherwise except as
1652419Sjulian *    such appears in the above copyright notice or in the software.
1752419Sjulian *
1852419Sjulian * THIS SOFTWARE IS BEING PROVIDED BY WHISTLE COMMUNICATIONS "AS IS", AND
1952419Sjulian * TO THE MAXIMUM EXTENT PERMITTED BY LAW, WHISTLE COMMUNICATIONS MAKES NO
2052419Sjulian * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING THIS SOFTWARE,
2152419Sjulian * INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED WARRANTIES OF
2252419Sjulian * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
2352419Sjulian * WHISTLE COMMUNICATIONS DOES NOT WARRANT, GUARANTEE, OR MAKE ANY
2452419Sjulian * REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS OF THE USE OF THIS
2552419Sjulian * SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY, RELIABILITY OR OTHERWISE.
2652419Sjulian * IN NO EVENT SHALL WHISTLE COMMUNICATIONS BE LIABLE FOR ANY DAMAGES
2752419Sjulian * RESULTING FROM OR ARISING OUT OF ANY USE OF THIS SOFTWARE, INCLUDING
2852419Sjulian * WITHOUT LIMITATION, ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
2952419Sjulian * PUNITIVE, OR CONSEQUENTIAL DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR
3052419Sjulian * SERVICES, LOSS OF USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY
3152419Sjulian * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3252419Sjulian * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
3352419Sjulian * THIS SOFTWARE, EVEN IF WHISTLE COMMUNICATIONS IS ADVISED OF THE POSSIBILITY
3452419Sjulian * OF SUCH DAMAGE.
3552419Sjulian *
3652419Sjulian * Author: Archie Cobbs <archie@whistle.com>
3752419Sjulian *
3852419Sjulian * $Whistle: debug.c,v 1.24 1999/01/24 01:15:33 archie Exp $
3952419Sjulian */
4052419Sjulian
4184215Sdillon#include <sys/cdefs.h>
4284215Sdillon__FBSDID("$FreeBSD$");
4384215Sdillon
4452419Sjulian#include <sys/types.h>
4554100Sarchie#include <sys/time.h>
4654100Sarchie#include <sys/ioctl.h>
4753913Sarchie
4852419Sjulian#include <stdarg.h>
4953913Sarchie
5053913Sarchie#include <netinet/in.h>
5153913Sarchie#include <net/ethernet.h>
5254100Sarchie#include <net/bpf.h>
5353913Sarchie
5452419Sjulian#include <netgraph/ng_message.h>
5552419Sjulian#include <netgraph/ng_socket.h>
5652419Sjulian
5752419Sjulian#include "netgraph.h"
5852419Sjulian#include "internal.h"
5952419Sjulian
6053913Sarchie#include <netgraph/ng_UI.h>
6153913Sarchie#include <netgraph/ng_async.h>
62151677Sru#include <netgraph/ng_atmllc.h>
6354100Sarchie#include <netgraph/ng_bpf.h>
64151677Sru#include <netgraph/ng_bridge.h>
6552419Sjulian#include <netgraph/ng_cisco.h>
66151677Sru#include <netgraph/ng_device.h>
6753913Sarchie#include <netgraph/ng_echo.h>
68151677Sru#include <netgraph/ng_eiface.h>
69151677Sru#include <netgraph/ng_etf.h>
7053913Sarchie#include <netgraph/ng_ether.h>
71151677Sru#include <netgraph/ng_fec.h>
7252419Sjulian#include <netgraph/ng_frame_relay.h>
73151677Sru#include <netgraph/ng_gif.h>
74151677Sru#include <netgraph/ng_gif_demux.h>
7553913Sarchie#include <netgraph/ng_hole.h>
76151677Sru#include <netgraph/ng_hub.h>
7753913Sarchie#include <netgraph/ng_iface.h>
78151677Sru#include <netgraph/ng_ip_input.h>
79151677Sru#include <netgraph/ng_ipfw.h>
8053913Sarchie#include <netgraph/ng_ksocket.h>
81151677Sru#include <netgraph/ng_l2tp.h>
8252419Sjulian#include <netgraph/ng_lmi.h>
83151677Sru#include <netgraph/ng_mppc.h>
84151677Sru#include <netgraph/ng_nat.h>
85151677Sru#include <netgraph/ng_one2many.h>
8653913Sarchie#include <netgraph/ng_ppp.h>
8753913Sarchie#include <netgraph/ng_pppoe.h>
88151677Sru#include <netgraph/ng_pptpgre.h>
8953913Sarchie#include <netgraph/ng_rfc1490.h>
9053913Sarchie#include <netgraph/ng_socket.h>
91151677Sru#include <netgraph/ng_source.h>
92151677Sru#include <netgraph/ng_split.h>
93151677Sru#include <netgraph/ng_sppp.h>
94151677Sru#include <netgraph/ng_tcpmss.h>
9553913Sarchie#include <netgraph/ng_tee.h>
9652419Sjulian#include <netgraph/ng_tty.h>
9753913Sarchie#include <netgraph/ng_vjc.h>
98151677Sru#include <netgraph/ng_vlan.h>
9953913Sarchie#ifdef	WHISTLE
10053913Sarchie#include <machine/../isa/df_def.h>
10153913Sarchie#include <machine/../isa/if_wfra.h>
10253913Sarchie#include <machine/../isa/ipac.h>
10353913Sarchie#include <netgraph/ng_df.h>
10453913Sarchie#include <netgraph/ng_ipac.h>
10553913Sarchie#include <netgraph/ng_tn.h>
10653913Sarchie#endif
10752419Sjulian
10852419Sjulian/* Global debug level */
10952419Sjulianint     _gNgDebugLevel = 0;
11052419Sjulian
11152419Sjulian/* Debug printing functions */
11252419Sjulianvoid    (*_NgLog) (const char *fmt,...) = warn;
11352419Sjulianvoid    (*_NgLogx) (const char *fmt,...) = warnx;
11452419Sjulian
11552419Sjulian/* Internal functions */
11652419Sjulianstatic const	char *NgCookie(int cookie);
11752419Sjulian
11853913Sarchie/* Known typecookie list */
11953913Sarchiestruct ng_cookie {
12053913Sarchie	int		cookie;
12153913Sarchie	const char	*type;
12253913Sarchie};
12353913Sarchie
12453913Sarchie#define COOKIE(c)	{ NGM_ ## c ## _COOKIE, #c }
12553913Sarchie
12653913Sarchie/* List of known cookies */
12753913Sarchiestatic const struct ng_cookie cookies[] = {
12853913Sarchie	COOKIE(UI),
12953913Sarchie	COOKIE(ASYNC),
130151677Sru	COOKIE(ATMLLC),
13154098Sarchie	COOKIE(BPF),
132151677Sru	COOKIE(BRIDGE),
13353913Sarchie	COOKIE(CISCO),
134151677Sru	COOKIE(DEVICE),
13553913Sarchie	COOKIE(ECHO),
136151677Sru	COOKIE(EIFACE),
137151677Sru	COOKIE(ETF),
13853913Sarchie	COOKIE(ETHER),
139151677Sru	COOKIE(FEC),
14053913Sarchie	COOKIE(FRAMERELAY),
141151677Sru	COOKIE(GIF),
142151677Sru	COOKIE(GIF_DEMUX),
14353913Sarchie	COOKIE(GENERIC),
14453913Sarchie	COOKIE(HOLE),
145151677Sru	COOKIE(HUB),
14653913Sarchie	COOKIE(IFACE),
147151677Sru	COOKIE(IP_INPUT),
148151677Sru	COOKIE(IPFW),
14953913Sarchie	COOKIE(KSOCKET),
150151677Sru	COOKIE(L2TP),
15153913Sarchie	COOKIE(LMI),
152151677Sru	COOKIE(MPPC),
153151677Sru	COOKIE(NAT),
154151677Sru	COOKIE(ONE2MANY),
15553913Sarchie	COOKIE(PPP),
15653913Sarchie	COOKIE(PPPOE),
157151677Sru	COOKIE(PPTPGRE),
15853913Sarchie	COOKIE(RFC1490),
15953913Sarchie	COOKIE(SOCKET),
160151677Sru	COOKIE(SOURCE),
161151677Sru	COOKIE(SPLIT),
162151677Sru	COOKIE(SPPP),
163151677Sru	COOKIE(TCPMSS),
16453913Sarchie	COOKIE(TEE),
16553913Sarchie	COOKIE(TTY),
16653913Sarchie	COOKIE(VJC),
167151677Sru	COOKIE(VLAN),
16853913Sarchie#ifdef WHISTLE
16953913Sarchie	COOKIE(DF),
17053913Sarchie	COOKIE(IPAC),
17153913Sarchie	COOKIE(TN),
17253913Sarchie	COOKIE(WFRA),
17353913Sarchie#endif
17453913Sarchie	{ 0, NULL }
17553913Sarchie};
17653913Sarchie
17752419Sjulian/*
17852419Sjulian * Set debug level, ie, verbosity, if "level" is non-negative.
17952419Sjulian * Returns old debug level.
18052419Sjulian */
18152419Sjulianint
18252419SjulianNgSetDebug(int level)
18352419Sjulian{
18452419Sjulian	int old = _gNgDebugLevel;
18552419Sjulian
18652419Sjulian	if (level < 0)
18752419Sjulian		level = old;
18852419Sjulian	_gNgDebugLevel = level;
18952419Sjulian	return (old);
19052419Sjulian}
19152419Sjulian
19252419Sjulian/*
19352419Sjulian * Set debug logging functions.
19452419Sjulian */
19552419Sjulianvoid
19652419SjulianNgSetErrLog(void (*log) (const char *fmt,...),
19752419Sjulian		void (*logx) (const char *fmt,...))
19852419Sjulian{
19952419Sjulian	_NgLog = log;
20052419Sjulian	_NgLogx = logx;
20152419Sjulian}
20252419Sjulian
20352419Sjulian/*
20452419Sjulian * Display a netgraph sockaddr
20552419Sjulian */
20652419Sjulianvoid
20753913Sarchie_NgDebugSockaddr(const struct sockaddr_ng *sg)
20852419Sjulian{
20952419Sjulian	NGLOGX("SOCKADDR: { fam=%d len=%d addr=\"%s\" }",
21052419Sjulian	       sg->sg_family, sg->sg_len, sg->sg_data);
21152419Sjulian}
21252419Sjulian
21359732Sarchie#define ARGS_BUFSIZE		2048
21459732Sarchie#define RECURSIVE_DEBUG_ADJUST	4
21553913Sarchie
21652419Sjulian/*
21752419Sjulian * Display a negraph message
21852419Sjulian */
21952419Sjulianvoid
22053913Sarchie_NgDebugMsg(const struct ng_mesg *msg, const char *path)
22152419Sjulian{
22253913Sarchie	u_char buf[2 * sizeof(struct ng_mesg) + ARGS_BUFSIZE];
22353913Sarchie	struct ng_mesg *const req = (struct ng_mesg *)buf;
22453913Sarchie	struct ng_mesg *const bin = (struct ng_mesg *)req->data;
22559732Sarchie	int arglen, csock = -1;
22653913Sarchie
22753913Sarchie	/* Display header stuff */
22852419Sjulian	NGLOGX("NG_MESG :");
22952419Sjulian	NGLOGX("  vers   %d", msg->header.version);
23052419Sjulian	NGLOGX("  arglen %d", msg->header.arglen);
23152419Sjulian	NGLOGX("  flags  %ld", msg->header.flags);
23253913Sarchie	NGLOGX("  token  %lu", (u_long)msg->header.token);
23353913Sarchie	NGLOGX("  cookie %s (%d)",
23453913Sarchie	    NgCookie(msg->header.typecookie), msg->header.typecookie);
23552419Sjulian
23653913Sarchie	/* At lower debugging levels, skip ASCII translation */
23753913Sarchie	if (_gNgDebugLevel <= 2)
23853913Sarchie		goto fail2;
23952419Sjulian
24053913Sarchie	/* If path is not absolute, don't bother trying to use relative
24153913Sarchie	   address on a different socket for the ASCII translation */
24253913Sarchie	if (strchr(path, ':') == NULL)
24353913Sarchie		goto fail2;
24452419Sjulian
24553913Sarchie	/* Get a temporary socket */
24653913Sarchie	if (NgMkSockNode(NULL, &csock, NULL) < 0)
24753913Sarchie		goto fail;
24852419Sjulian
24953913Sarchie	/* Copy binary message into request message payload */
25053913Sarchie	arglen = msg->header.arglen;
25153913Sarchie	if (arglen > ARGS_BUFSIZE)
25253913Sarchie		arglen = ARGS_BUFSIZE;
25353913Sarchie	memcpy(bin, msg, sizeof(*msg) + arglen);
25453913Sarchie	bin->header.arglen = arglen;
25553913Sarchie
25659732Sarchie	/* Lower debugging to avoid infinite recursion */
25759732Sarchie	_gNgDebugLevel -= RECURSIVE_DEBUG_ADJUST;
25859732Sarchie
25953913Sarchie	/* Ask the node to translate the binary message to ASCII for us */
26053913Sarchie	if (NgSendMsg(csock, path, NGM_GENERIC_COOKIE,
26159732Sarchie	    NGM_BINARY2ASCII, bin, sizeof(*bin) + bin->header.arglen) < 0) {
26259732Sarchie		_gNgDebugLevel += RECURSIVE_DEBUG_ADJUST;
26353913Sarchie		goto fail;
26459732Sarchie	}
26559732Sarchie	if (NgRecvMsg(csock, req, sizeof(buf), NULL) < 0) {
26659732Sarchie		_gNgDebugLevel += RECURSIVE_DEBUG_ADJUST;
26753913Sarchie		goto fail;
26859732Sarchie	}
26953913Sarchie
27059732Sarchie	/* Restore debugging level */
27159732Sarchie	_gNgDebugLevel += RECURSIVE_DEBUG_ADJUST;
27259732Sarchie
27353913Sarchie	/* Display command string and arguments */
27453913Sarchie	NGLOGX("  cmd    %s (%d)", bin->header.cmdstr, bin->header.cmd);
27553913Sarchie	NGLOGX("  args   %s", bin->data);
27653913Sarchie	goto done;
27753913Sarchie
27853913Sarchiefail:
27953913Sarchie	/* Just display binary version */
28053913Sarchie	NGLOGX("  [error decoding message: %s]", strerror(errno));
28153913Sarchiefail2:
28253913Sarchie	NGLOGX("  cmd    %d", msg->header.cmd);
28353913Sarchie	NGLOGX("  args (%d bytes)", msg->header.arglen);
284145546Smux	_NgDebugBytes((u_char *)msg->data, msg->header.arglen);
28553913Sarchie
28653913Sarchiedone:
28753913Sarchie	if (csock != -1)
28853913Sarchie		(void)close(csock);
28952419Sjulian}
29052419Sjulian
29152419Sjulian/*
29253913Sarchie * Return the name of the node type corresponding to the cookie
29352419Sjulian */
29453913Sarchiestatic const char *
29553913SarchieNgCookie(int cookie)
29652419Sjulian{
29753913Sarchie	int k;
29852419Sjulian
29953913Sarchie	for (k = 0; cookies[k].cookie != 0; k++) {
30053913Sarchie		if (cookies[k].cookie == cookie)
30153913Sarchie			return cookies[k].type;
30252419Sjulian	}
30353913Sarchie	return "??";
30452419Sjulian}
30552419Sjulian
30652419Sjulian/*
30752419Sjulian * Dump bytes in hex
30852419Sjulian */
30952419Sjulianvoid
31053913Sarchie_NgDebugBytes(const u_char *ptr, int len)
31152419Sjulian{
31252419Sjulian	char    buf[100];
31352419Sjulian	int     k, count;
31452419Sjulian
31552419Sjulian#define BYPERLINE	16
31652419Sjulian
31752419Sjulian	for (count = 0; count < len; ptr += BYPERLINE, count += BYPERLINE) {
31852419Sjulian
31952419Sjulian		/* Do hex */
32052419Sjulian		snprintf(buf, sizeof(buf), "%04x:  ", count);
32152419Sjulian		for (k = 0; k < BYPERLINE; k++, count++)
32252419Sjulian			if (count < len)
32352419Sjulian				snprintf(buf + strlen(buf),
32452419Sjulian				    sizeof(buf) - strlen(buf), "%02x ", ptr[k]);
32552419Sjulian			else
32652419Sjulian				snprintf(buf + strlen(buf),
32752419Sjulian				    sizeof(buf) - strlen(buf), "   ");
32852419Sjulian		snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "  ");
32952419Sjulian		count -= BYPERLINE;
33052419Sjulian
33152419Sjulian		/* Do ASCII */
33252419Sjulian		for (k = 0; k < BYPERLINE; k++, count++)
33352419Sjulian			if (count < len)
33452419Sjulian				snprintf(buf + strlen(buf),
33552419Sjulian				    sizeof(buf) - strlen(buf),
33652419Sjulian				    "%c", isprint(ptr[k]) ? ptr[k] : '.');
33752419Sjulian			else
33852419Sjulian				snprintf(buf + strlen(buf),
33952419Sjulian				    sizeof(buf) - strlen(buf), "  ");
34052419Sjulian		count -= BYPERLINE;
34152419Sjulian
34252419Sjulian		/* Print it */
34352419Sjulian		NGLOGX("%s", buf);
34452419Sjulian	}
34552419Sjulian}
34652419Sjulian
347