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