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