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