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