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>
65279052Smav#include <netgraph/ng_car.h>
6652419Sjulian#include <netgraph/ng_cisco.h>
67279052Smav#include <netgraph/ng_deflate.h>
68151677Sru#include <netgraph/ng_device.h>
6953913Sarchie#include <netgraph/ng_echo.h>
70151677Sru#include <netgraph/ng_eiface.h>
71151677Sru#include <netgraph/ng_etf.h>
7253913Sarchie#include <netgraph/ng_ether.h>
73151677Sru#include <netgraph/ng_fec.h>
74279052Smav#include <netgraph/ng_ether_echo.h>
7552419Sjulian#include <netgraph/ng_frame_relay.h>
76151677Sru#include <netgraph/ng_gif.h>
77151677Sru#include <netgraph/ng_gif_demux.h>
7853913Sarchie#include <netgraph/ng_hole.h>
79151677Sru#include <netgraph/ng_hub.h>
8053913Sarchie#include <netgraph/ng_iface.h>
81151677Sru#include <netgraph/ng_ip_input.h>
82151677Sru#include <netgraph/ng_ipfw.h>
8353913Sarchie#include <netgraph/ng_ksocket.h>
84151677Sru#include <netgraph/ng_l2tp.h>
8552419Sjulian#include <netgraph/ng_lmi.h>
86151677Sru#include <netgraph/ng_mppc.h>
87151677Sru#include <netgraph/ng_nat.h>
88279052Smav#include <netgraph/netflow/ng_netflow.h>
89151677Sru#include <netgraph/ng_one2many.h>
90279052Smav#include <netgraph/ng_patch.h>
91279052Smav#include <netgraph/ng_pipe.h>
9253913Sarchie#include <netgraph/ng_ppp.h>
9353913Sarchie#include <netgraph/ng_pppoe.h>
94151677Sru#include <netgraph/ng_pptpgre.h>
95279052Smav#include <netgraph/ng_pred1.h>
9653913Sarchie#include <netgraph/ng_rfc1490.h>
9753913Sarchie#include <netgraph/ng_socket.h>
98151677Sru#include <netgraph/ng_source.h>
99151677Sru#include <netgraph/ng_split.h>
100151677Sru#include <netgraph/ng_sppp.h>
101279052Smav#include <netgraph/ng_tag.h>
102151677Sru#include <netgraph/ng_tcpmss.h>
10353913Sarchie#include <netgraph/ng_tee.h>
10452419Sjulian#include <netgraph/ng_tty.h>
10553913Sarchie#include <netgraph/ng_vjc.h>
106151677Sru#include <netgraph/ng_vlan.h>
10753913Sarchie#ifdef	WHISTLE
10853913Sarchie#include <machine/../isa/df_def.h>
10953913Sarchie#include <machine/../isa/if_wfra.h>
11053913Sarchie#include <machine/../isa/ipac.h>
11153913Sarchie#include <netgraph/ng_df.h>
11253913Sarchie#include <netgraph/ng_ipac.h>
11353913Sarchie#include <netgraph/ng_tn.h>
11453913Sarchie#endif
11552419Sjulian
11652419Sjulian/* Global debug level */
11752419Sjulianint     _gNgDebugLevel = 0;
11852419Sjulian
11952419Sjulian/* Debug printing functions */
12052419Sjulianvoid    (*_NgLog) (const char *fmt,...) = warn;
12152419Sjulianvoid    (*_NgLogx) (const char *fmt,...) = warnx;
12252419Sjulian
12352419Sjulian/* Internal functions */
12452419Sjulianstatic const	char *NgCookie(int cookie);
12552419Sjulian
12653913Sarchie/* Known typecookie list */
12753913Sarchiestruct ng_cookie {
12853913Sarchie	int		cookie;
12953913Sarchie	const char	*type;
13053913Sarchie};
13153913Sarchie
13253913Sarchie#define COOKIE(c)	{ NGM_ ## c ## _COOKIE, #c }
13353913Sarchie
13453913Sarchie/* List of known cookies */
13553913Sarchiestatic const struct ng_cookie cookies[] = {
13653913Sarchie	COOKIE(UI),
13753913Sarchie	COOKIE(ASYNC),
138151677Sru	COOKIE(ATMLLC),
13954098Sarchie	COOKIE(BPF),
140151677Sru	COOKIE(BRIDGE),
141279052Smav	COOKIE(CAR),
14253913Sarchie	COOKIE(CISCO),
143279052Smav	COOKIE(DEFLATE),
144151677Sru	COOKIE(DEVICE),
14553913Sarchie	COOKIE(ECHO),
146151677Sru	COOKIE(EIFACE),
147151677Sru	COOKIE(ETF),
14853913Sarchie	COOKIE(ETHER),
149151677Sru	COOKIE(FEC),
150279052Smav	COOKIE(ETHER_ECHO),
15153913Sarchie	COOKIE(FRAMERELAY),
152151677Sru	COOKIE(GIF),
153151677Sru	COOKIE(GIF_DEMUX),
15453913Sarchie	COOKIE(GENERIC),
15553913Sarchie	COOKIE(HOLE),
156151677Sru	COOKIE(HUB),
15753913Sarchie	COOKIE(IFACE),
158151677Sru	COOKIE(IP_INPUT),
159151677Sru	COOKIE(IPFW),
16053913Sarchie	COOKIE(KSOCKET),
161151677Sru	COOKIE(L2TP),
16253913Sarchie	COOKIE(LMI),
163151677Sru	COOKIE(MPPC),
164151677Sru	COOKIE(NAT),
165279052Smav	COOKIE(NETFLOW),
166151677Sru	COOKIE(ONE2MANY),
167279052Smav	COOKIE(PATCH),
168279052Smav	COOKIE(PIPE),
16953913Sarchie	COOKIE(PPP),
17053913Sarchie	COOKIE(PPPOE),
171151677Sru	COOKIE(PPTPGRE),
172279052Smav	COOKIE(PRED1),
17353913Sarchie	COOKIE(RFC1490),
17453913Sarchie	COOKIE(SOCKET),
175151677Sru	COOKIE(SOURCE),
176151677Sru	COOKIE(SPLIT),
177151677Sru	COOKIE(SPPP),
178279052Smav	COOKIE(TAG),
179151677Sru	COOKIE(TCPMSS),
18053913Sarchie	COOKIE(TEE),
18153913Sarchie	COOKIE(TTY),
18253913Sarchie	COOKIE(VJC),
183151677Sru	COOKIE(VLAN),
18453913Sarchie#ifdef WHISTLE
18553913Sarchie	COOKIE(DF),
18653913Sarchie	COOKIE(IPAC),
18753913Sarchie	COOKIE(TN),
18853913Sarchie	COOKIE(WFRA),
18953913Sarchie#endif
19053913Sarchie	{ 0, NULL }
19153913Sarchie};
19253913Sarchie
19352419Sjulian/*
19452419Sjulian * Set debug level, ie, verbosity, if "level" is non-negative.
19552419Sjulian * Returns old debug level.
19652419Sjulian */
19752419Sjulianint
19852419SjulianNgSetDebug(int level)
19952419Sjulian{
20052419Sjulian	int old = _gNgDebugLevel;
20152419Sjulian
202279052Smav	if (level >= 0)
203279052Smav		_gNgDebugLevel = level;
20452419Sjulian	return (old);
20552419Sjulian}
20652419Sjulian
20752419Sjulian/*
20852419Sjulian * Set debug logging functions.
20952419Sjulian */
21052419Sjulianvoid
21152419SjulianNgSetErrLog(void (*log) (const char *fmt,...),
21252419Sjulian		void (*logx) (const char *fmt,...))
21352419Sjulian{
21452419Sjulian	_NgLog = log;
21552419Sjulian	_NgLogx = logx;
21652419Sjulian}
21752419Sjulian
21852419Sjulian/*
21952419Sjulian * Display a netgraph sockaddr
22052419Sjulian */
22152419Sjulianvoid
22253913Sarchie_NgDebugSockaddr(const struct sockaddr_ng *sg)
22352419Sjulian{
22452419Sjulian	NGLOGX("SOCKADDR: { fam=%d len=%d addr=\"%s\" }",
22552419Sjulian	       sg->sg_family, sg->sg_len, sg->sg_data);
22652419Sjulian}
22752419Sjulian
22859732Sarchie#define ARGS_BUFSIZE		2048
22959732Sarchie#define RECURSIVE_DEBUG_ADJUST	4
23053913Sarchie
23152419Sjulian/*
23252419Sjulian * Display a negraph message
23352419Sjulian */
23452419Sjulianvoid
23553913Sarchie_NgDebugMsg(const struct ng_mesg *msg, const char *path)
23652419Sjulian{
23753913Sarchie	u_char buf[2 * sizeof(struct ng_mesg) + ARGS_BUFSIZE];
23853913Sarchie	struct ng_mesg *const req = (struct ng_mesg *)buf;
23953913Sarchie	struct ng_mesg *const bin = (struct ng_mesg *)req->data;
24059732Sarchie	int arglen, csock = -1;
24153913Sarchie
24253913Sarchie	/* Display header stuff */
24352419Sjulian	NGLOGX("NG_MESG :");
24452419Sjulian	NGLOGX("  vers   %d", msg->header.version);
245279052Smav	NGLOGX("  arglen %u", msg->header.arglen);
246279052Smav	NGLOGX("  flags  %x", msg->header.flags);
247279052Smav	NGLOGX("  token  %u", msg->header.token);
248279052Smav	NGLOGX("  cookie %s (%u)",
24953913Sarchie	    NgCookie(msg->header.typecookie), msg->header.typecookie);
25052419Sjulian
25153913Sarchie	/* At lower debugging levels, skip ASCII translation */
25253913Sarchie	if (_gNgDebugLevel <= 2)
25353913Sarchie		goto fail2;
25452419Sjulian
25553913Sarchie	/* If path is not absolute, don't bother trying to use relative
25653913Sarchie	   address on a different socket for the ASCII translation */
25753913Sarchie	if (strchr(path, ':') == NULL)
25853913Sarchie		goto fail2;
25952419Sjulian
26053913Sarchie	/* Get a temporary socket */
26153913Sarchie	if (NgMkSockNode(NULL, &csock, NULL) < 0)
26253913Sarchie		goto fail;
26352419Sjulian
26453913Sarchie	/* Copy binary message into request message payload */
26553913Sarchie	arglen = msg->header.arglen;
26653913Sarchie	if (arglen > ARGS_BUFSIZE)
26753913Sarchie		arglen = ARGS_BUFSIZE;
26853913Sarchie	memcpy(bin, msg, sizeof(*msg) + arglen);
26953913Sarchie	bin->header.arglen = arglen;
27053913Sarchie
27159732Sarchie	/* Lower debugging to avoid infinite recursion */
27259732Sarchie	_gNgDebugLevel -= RECURSIVE_DEBUG_ADJUST;
27359732Sarchie
27453913Sarchie	/* Ask the node to translate the binary message to ASCII for us */
27553913Sarchie	if (NgSendMsg(csock, path, NGM_GENERIC_COOKIE,
27659732Sarchie	    NGM_BINARY2ASCII, bin, sizeof(*bin) + bin->header.arglen) < 0) {
27759732Sarchie		_gNgDebugLevel += RECURSIVE_DEBUG_ADJUST;
27853913Sarchie		goto fail;
27959732Sarchie	}
28059732Sarchie	if (NgRecvMsg(csock, req, sizeof(buf), NULL) < 0) {
28159732Sarchie		_gNgDebugLevel += RECURSIVE_DEBUG_ADJUST;
28253913Sarchie		goto fail;
28359732Sarchie	}
28453913Sarchie
28559732Sarchie	/* Restore debugging level */
28659732Sarchie	_gNgDebugLevel += RECURSIVE_DEBUG_ADJUST;
28759732Sarchie
28853913Sarchie	/* Display command string and arguments */
28953913Sarchie	NGLOGX("  cmd    %s (%d)", bin->header.cmdstr, bin->header.cmd);
29053913Sarchie	NGLOGX("  args   %s", bin->data);
29153913Sarchie	goto done;
29253913Sarchie
29353913Sarchiefail:
29453913Sarchie	/* Just display binary version */
29553913Sarchie	NGLOGX("  [error decoding message: %s]", strerror(errno));
29653913Sarchiefail2:
29753913Sarchie	NGLOGX("  cmd    %d", msg->header.cmd);
29853913Sarchie	NGLOGX("  args (%d bytes)", msg->header.arglen);
299145546Smux	_NgDebugBytes((u_char *)msg->data, msg->header.arglen);
30053913Sarchie
30153913Sarchiedone:
30253913Sarchie	if (csock != -1)
30353913Sarchie		(void)close(csock);
30452419Sjulian}
30552419Sjulian
30652419Sjulian/*
30753913Sarchie * Return the name of the node type corresponding to the cookie
30852419Sjulian */
30953913Sarchiestatic const char *
31053913SarchieNgCookie(int cookie)
31152419Sjulian{
31253913Sarchie	int k;
31352419Sjulian
31453913Sarchie	for (k = 0; cookies[k].cookie != 0; k++) {
31553913Sarchie		if (cookies[k].cookie == cookie)
31653913Sarchie			return cookies[k].type;
31752419Sjulian	}
31853913Sarchie	return "??";
31952419Sjulian}
32052419Sjulian
32152419Sjulian/*
32252419Sjulian * Dump bytes in hex
32352419Sjulian */
32452419Sjulianvoid
32553913Sarchie_NgDebugBytes(const u_char *ptr, int len)
32652419Sjulian{
32752419Sjulian	char    buf[100];
32852419Sjulian	int     k, count;
32952419Sjulian
33052419Sjulian#define BYPERLINE	16
33152419Sjulian
33252419Sjulian	for (count = 0; count < len; ptr += BYPERLINE, count += BYPERLINE) {
33352419Sjulian
33452419Sjulian		/* Do hex */
33552419Sjulian		snprintf(buf, sizeof(buf), "%04x:  ", count);
33652419Sjulian		for (k = 0; k < BYPERLINE; k++, count++)
33752419Sjulian			if (count < len)
33852419Sjulian				snprintf(buf + strlen(buf),
33952419Sjulian				    sizeof(buf) - strlen(buf), "%02x ", ptr[k]);
34052419Sjulian			else
34152419Sjulian				snprintf(buf + strlen(buf),
34252419Sjulian				    sizeof(buf) - strlen(buf), "   ");
34352419Sjulian		snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "  ");
34452419Sjulian		count -= BYPERLINE;
34552419Sjulian
34652419Sjulian		/* Do ASCII */
34752419Sjulian		for (k = 0; k < BYPERLINE; k++, count++)
34852419Sjulian			if (count < len)
34952419Sjulian				snprintf(buf + strlen(buf),
35052419Sjulian				    sizeof(buf) - strlen(buf),
35152419Sjulian				    "%c", isprint(ptr[k]) ? ptr[k] : '.');
35252419Sjulian			else
35352419Sjulian				snprintf(buf + strlen(buf),
35452419Sjulian				    sizeof(buf) - strlen(buf), "  ");
35552419Sjulian		count -= BYPERLINE;
35652419Sjulian
35752419Sjulian		/* Print it */
35852419Sjulian		NGLOGX("%s", buf);
35952419Sjulian	}
36052419Sjulian}
36152419Sjulian
362