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