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