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