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