debug.c revision 59732
1
2/*
3 * debug.c
4 *
5 * Copyright (c) 1996-1999 Whistle Communications, Inc.
6 * All rights reserved.
7 *
8 * Subject to the following obligations and disclaimer of warranty, use and
9 * redistribution of this software, in source or object code forms, with or
10 * without modifications are expressly permitted by Whistle Communications;
11 * provided, however, that:
12 * 1. Any and all reproductions of the source or object code must include the
13 *    copyright notice above and the following disclaimer of warranties; and
14 * 2. No rights are granted, in any manner or form, to use Whistle
15 *    Communications, Inc. trademarks, including the mark "WHISTLE
16 *    COMMUNICATIONS" on advertising, endorsements, or otherwise except as
17 *    such appears in the above copyright notice or in the software.
18 *
19 * THIS SOFTWARE IS BEING PROVIDED BY WHISTLE COMMUNICATIONS "AS IS", AND
20 * TO THE MAXIMUM EXTENT PERMITTED BY LAW, WHISTLE COMMUNICATIONS MAKES NO
21 * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING THIS SOFTWARE,
22 * INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED WARRANTIES OF
23 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
24 * WHISTLE COMMUNICATIONS DOES NOT WARRANT, GUARANTEE, OR MAKE ANY
25 * REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS OF THE USE OF THIS
26 * SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY, RELIABILITY OR OTHERWISE.
27 * IN NO EVENT SHALL WHISTLE COMMUNICATIONS BE LIABLE FOR ANY DAMAGES
28 * RESULTING FROM OR ARISING OUT OF ANY USE OF THIS SOFTWARE, INCLUDING
29 * WITHOUT LIMITATION, ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
30 * PUNITIVE, OR CONSEQUENTIAL DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR
31 * SERVICES, LOSS OF USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY
32 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
33 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
34 * THIS SOFTWARE, EVEN IF WHISTLE COMMUNICATIONS IS ADVISED OF THE POSSIBILITY
35 * OF SUCH DAMAGE.
36 *
37 * Author: Archie Cobbs <archie@whistle.com>
38 *
39 * $FreeBSD: head/lib/libnetgraph/debug.c 59732 2000-04-28 18:41:21Z archie $
40 * $Whistle: debug.c,v 1.24 1999/01/24 01:15:33 archie Exp $
41 */
42
43#include <sys/types.h>
44#include <sys/time.h>
45#include <sys/ioctl.h>
46
47#include <stdarg.h>
48
49#include <netinet/in.h>
50#include <net/ethernet.h>
51#include <net/bpf.h>
52
53#include <netgraph/ng_message.h>
54#include <netgraph/ng_socket.h>
55
56#include "netgraph.h"
57#include "internal.h"
58
59#include <netgraph/ng_UI.h>
60#include <netgraph/ng_async.h>
61#include <netgraph/ng_bpf.h>
62#include <netgraph/ng_cisco.h>
63#include <netgraph/ng_echo.h>
64#include <netgraph/ng_ether.h>
65#include <netgraph/ng_frame_relay.h>
66#include <netgraph/ng_hole.h>
67#include <netgraph/ng_iface.h>
68#include <netgraph/ng_ksocket.h>
69#include <netgraph/ng_lmi.h>
70#include <netgraph/ng_ppp.h>
71#include <netgraph/ng_pppoe.h>
72#include <netgraph/ng_rfc1490.h>
73#include <netgraph/ng_socket.h>
74#include <netgraph/ng_tee.h>
75#include <netgraph/ng_tty.h>
76#include <netgraph/ng_vjc.h>
77#ifdef	WHISTLE
78#include <machine/../isa/df_def.h>
79#include <machine/../isa/if_wfra.h>
80#include <machine/../isa/ipac.h>
81#include <netgraph/ng_df.h>
82#include <netgraph/ng_ipac.h>
83#include <netgraph/ng_mppc.h>
84#include <netgraph/ng_pptpgre.h>
85#include <netgraph/ng_tn.h>
86#endif
87
88/* Global debug level */
89int     _gNgDebugLevel = 0;
90
91/* Debug printing functions */
92void    (*_NgLog) (const char *fmt,...) = warn;
93void    (*_NgLogx) (const char *fmt,...) = warnx;
94
95/* Internal functions */
96static const	char *NgCookie(int cookie);
97
98/* Known typecookie list */
99struct ng_cookie {
100	int		cookie;
101	const char	*type;
102};
103
104#define COOKIE(c)	{ NGM_ ## c ## _COOKIE, #c }
105
106/* List of known cookies */
107static const struct ng_cookie cookies[] = {
108	COOKIE(UI),
109	COOKIE(ASYNC),
110	COOKIE(BPF),
111	COOKIE(CISCO),
112	COOKIE(ECHO),
113	COOKIE(ETHER),
114	COOKIE(FRAMERELAY),
115	COOKIE(GENERIC),
116	COOKIE(HOLE),
117	COOKIE(IFACE),
118	COOKIE(KSOCKET),
119	COOKIE(LMI),
120	COOKIE(PPP),
121	COOKIE(PPPOE),
122	COOKIE(RFC1490),
123	COOKIE(SOCKET),
124	COOKIE(TEE),
125	COOKIE(TTY),
126	COOKIE(VJC),
127#ifdef WHISTLE
128	COOKIE(DF),
129	COOKIE(IPAC),
130	COOKIE(MPPC),
131	COOKIE(PPTPGRE),
132	COOKIE(TN),
133	COOKIE(WFRA),
134#endif
135	{ 0, NULL }
136};
137
138/*
139 * Set debug level, ie, verbosity, if "level" is non-negative.
140 * Returns old debug level.
141 */
142int
143NgSetDebug(int level)
144{
145	int old = _gNgDebugLevel;
146
147	if (level < 0)
148		level = old;
149	_gNgDebugLevel = level;
150	return (old);
151}
152
153/*
154 * Set debug logging functions.
155 */
156void
157NgSetErrLog(void (*log) (const char *fmt,...),
158		void (*logx) (const char *fmt,...))
159{
160	_NgLog = log;
161	_NgLogx = logx;
162}
163
164/*
165 * Display a netgraph sockaddr
166 */
167void
168_NgDebugSockaddr(const struct sockaddr_ng *sg)
169{
170	NGLOGX("SOCKADDR: { fam=%d len=%d addr=\"%s\" }",
171	       sg->sg_family, sg->sg_len, sg->sg_data);
172}
173
174#define ARGS_BUFSIZE		2048
175#define RECURSIVE_DEBUG_ADJUST	4
176
177/*
178 * Display a negraph message
179 */
180void
181_NgDebugMsg(const struct ng_mesg *msg, const char *path)
182{
183	u_char buf[2 * sizeof(struct ng_mesg) + ARGS_BUFSIZE];
184	struct ng_mesg *const req = (struct ng_mesg *)buf;
185	struct ng_mesg *const bin = (struct ng_mesg *)req->data;
186	int arglen, csock = -1;
187
188	/* Display header stuff */
189	NGLOGX("NG_MESG :");
190	NGLOGX("  vers   %d", msg->header.version);
191	NGLOGX("  arglen %d", msg->header.arglen);
192	NGLOGX("  flags  %ld", msg->header.flags);
193	NGLOGX("  token  %lu", (u_long)msg->header.token);
194	NGLOGX("  cookie %s (%d)",
195	    NgCookie(msg->header.typecookie), msg->header.typecookie);
196
197	/* At lower debugging levels, skip ASCII translation */
198	if (_gNgDebugLevel <= 2)
199		goto fail2;
200
201	/* If path is not absolute, don't bother trying to use relative
202	   address on a different socket for the ASCII translation */
203	if (strchr(path, ':') == NULL)
204		goto fail2;
205
206	/* Get a temporary socket */
207	if (NgMkSockNode(NULL, &csock, NULL) < 0)
208		goto fail;
209
210	/* Copy binary message into request message payload */
211	arglen = msg->header.arglen;
212	if (arglen > ARGS_BUFSIZE)
213		arglen = ARGS_BUFSIZE;
214	memcpy(bin, msg, sizeof(*msg) + arglen);
215	bin->header.arglen = arglen;
216
217	/* Lower debugging to avoid infinite recursion */
218	_gNgDebugLevel -= RECURSIVE_DEBUG_ADJUST;
219
220	/* Ask the node to translate the binary message to ASCII for us */
221	if (NgSendMsg(csock, path, NGM_GENERIC_COOKIE,
222	    NGM_BINARY2ASCII, bin, sizeof(*bin) + bin->header.arglen) < 0) {
223		_gNgDebugLevel += RECURSIVE_DEBUG_ADJUST;
224		goto fail;
225	}
226	if (NgRecvMsg(csock, req, sizeof(buf), NULL) < 0) {
227		_gNgDebugLevel += RECURSIVE_DEBUG_ADJUST;
228		goto fail;
229	}
230
231	/* Restore debugging level */
232	_gNgDebugLevel += RECURSIVE_DEBUG_ADJUST;
233
234	/* Display command string and arguments */
235	NGLOGX("  cmd    %s (%d)", bin->header.cmdstr, bin->header.cmd);
236	NGLOGX("  args   %s", bin->data);
237	goto done;
238
239fail:
240	/* Just display binary version */
241	NGLOGX("  [error decoding message: %s]", strerror(errno));
242fail2:
243	NGLOGX("  cmd    %d", msg->header.cmd);
244	NGLOGX("  args (%d bytes)", msg->header.arglen);
245	_NgDebugBytes(msg->data, msg->header.arglen);
246
247done:
248	if (csock != -1)
249		(void)close(csock);
250}
251
252/*
253 * Return the name of the node type corresponding to the cookie
254 */
255static const char *
256NgCookie(int cookie)
257{
258	int k;
259
260	for (k = 0; cookies[k].cookie != 0; k++) {
261		if (cookies[k].cookie == cookie)
262			return cookies[k].type;
263	}
264	return "??";
265}
266
267/*
268 * Dump bytes in hex
269 */
270void
271_NgDebugBytes(const u_char *ptr, int len)
272{
273	char    buf[100];
274	int     k, count;
275
276#define BYPERLINE	16
277
278	for (count = 0; count < len; ptr += BYPERLINE, count += BYPERLINE) {
279
280		/* Do hex */
281		snprintf(buf, sizeof(buf), "%04x:  ", count);
282		for (k = 0; k < BYPERLINE; k++, count++)
283			if (count < len)
284				snprintf(buf + strlen(buf),
285				    sizeof(buf) - strlen(buf), "%02x ", ptr[k]);
286			else
287				snprintf(buf + strlen(buf),
288				    sizeof(buf) - strlen(buf), "   ");
289		snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "  ");
290		count -= BYPERLINE;
291
292		/* Do ASCII */
293		for (k = 0; k < BYPERLINE; k++, count++)
294			if (count < len)
295				snprintf(buf + strlen(buf),
296				    sizeof(buf) - strlen(buf),
297				    "%c", isprint(ptr[k]) ? ptr[k] : '.');
298			else
299				snprintf(buf + strlen(buf),
300				    sizeof(buf) - strlen(buf), "  ");
301		count -= BYPERLINE;
302
303		/* Print it */
304		NGLOGX("%s", buf);
305	}
306}
307
308