xref: /freebsd/lib/libnetgraph/debug.c (revision de7b456e596ff18032d2cbfdf244c66f36770da4)
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_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 */
108 int     _gNgDebugLevel = 0;
109 
110 /* Debug printing functions */
111 void    (*_NgLog) (const char *fmt,...) = warn;
112 void    (*_NgLogx) (const char *fmt,...) = warnx;
113 
114 /* Internal functions */
115 static const	char *NgCookie(int cookie);
116 
117 /* Known typecookie list */
118 struct 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 */
126 static 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  */
179 int
180 NgSetDebug(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  */
193 void
194 NgSetErrLog(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  */
204 void
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  */
217 void
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 
276 fail:
277 	/* Just display binary version */
278 	NGLOGX("  [error decoding message: %s]", strerror(errno));
279 fail2:
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 
284 done:
285 	if (csock != -1)
286 		(void)close(csock);
287 }
288 
289 /*
290  * Return the name of the node type corresponding to the cookie
291  */
292 static const char *
293 NgCookie(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  */
307 void
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