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