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