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