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