xref: /dragonfly/lib/libnetgraph/debug.c (revision 768af85b)
1 
2 /*
3  * debug.c
4  *
5  * Copyright (c) 1996-1999 Whistle Communications, Inc.
6  * All rights reserved.
7  *
8  * Subject to the following obligations and disclaimer of warranty, use and
9  * redistribution of this software, in source or object code forms, with or
10  * without modifications are expressly permitted by Whistle Communications;
11  * provided, however, that:
12  * 1. Any and all reproductions of the source or object code must include the
13  *    copyright notice above and the following disclaimer of warranties; and
14  * 2. No rights are granted, in any manner or form, to use Whistle
15  *    Communications, Inc. trademarks, including the mark "WHISTLE
16  *    COMMUNICATIONS" on advertising, endorsements, or otherwise except as
17  *    such appears in the above copyright notice or in the software.
18  *
19  * THIS SOFTWARE IS BEING PROVIDED BY WHISTLE COMMUNICATIONS "AS IS", AND
20  * TO THE MAXIMUM EXTENT PERMITTED BY LAW, WHISTLE COMMUNICATIONS MAKES NO
21  * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING THIS SOFTWARE,
22  * INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED WARRANTIES OF
23  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
24  * WHISTLE COMMUNICATIONS DOES NOT WARRANT, GUARANTEE, OR MAKE ANY
25  * REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS OF THE USE OF THIS
26  * SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY, RELIABILITY OR OTHERWISE.
27  * IN NO EVENT SHALL WHISTLE COMMUNICATIONS BE LIABLE FOR ANY DAMAGES
28  * RESULTING FROM OR ARISING OUT OF ANY USE OF THIS SOFTWARE, INCLUDING
29  * WITHOUT LIMITATION, ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
30  * PUNITIVE, OR CONSEQUENTIAL DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR
31  * SERVICES, LOSS OF USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY
32  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
33  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
34  * THIS SOFTWARE, EVEN IF WHISTLE COMMUNICATIONS IS ADVISED OF THE POSSIBILITY
35  * OF SUCH DAMAGE.
36  *
37  * Author: Archie Cobbs <archie@whistle.com>
38  *
39  * $FreeBSD: src/lib/libnetgraph/debug.c,v 1.5.2.1 2000/05/01 18:09:54 archie Exp $
40  * $DragonFly: src/lib/libnetgraph/debug.c,v 1.4 2007/06/17 20:33:14 swildner Exp $
41  * $Whistle: debug.c,v 1.24 1999/01/24 01:15:33 archie Exp $
42  */
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/socket/ng_socket.h>
56 
57 #include "netgraph.h"
58 #include "internal.h"
59 
60 #include <netgraph/UI/ng_UI.h>
61 #include <netgraph/async/ng_async.h>
62 #include <netgraph/bpf/ng_bpf.h>
63 #include <netgraph/bridge/ng_bridge.h>
64 #include <netgraph/cisco/ng_cisco.h>
65 #include <netgraph/echo/ng_echo.h>
66 #include <netgraph/eiface/ng_eiface.h>
67 #include <netgraph/etf/ng_etf.h>
68 #include <netgraph/ether/ng_ether.h>
69 #include <netgraph/frame_relay/ng_frame_relay.h>
70 #include <netgraph/hole/ng_hole.h>
71 #include <netgraph/iface/ng_iface.h>
72 #include <netgraph/ksocket/ng_ksocket.h>
73 #include <netgraph/l2tp/ng_l2tp.h>
74 #include <netgraph/lmi/ng_lmi.h>
75 #include <netgraph/mppc/ng_mppc.h>
76 #include <netgraph/one2many/ng_one2many.h>
77 #include <netgraph/ppp/ng_ppp.h>
78 #include <netgraph/pppoe/ng_pppoe.h>
79 #include <netgraph/pptpgre/ng_pptpgre.h>
80 #include <netgraph/rfc1490/ng_rfc1490.h>
81 #include <netgraph/socket/ng_socket.h>
82 #include <netgraph/tee/ng_tee.h>
83 #include <netgraph/tty/ng_tty.h>
84 #include <netgraph/vjc/ng_vjc.h>
85 #ifdef	WHISTLE
86 #include <machine/../isa/df_def.h>
87 #include <machine/../isa/if_wfra.h>
88 #include <machine/../isa/ipac.h>
89 #include <netgraph/ng_df.h>
90 #include <netgraph/ng_ipac.h>
91 #include <netgraph/ng_tn.h>
92 #endif
93 
94 /* Global debug level */
95 int     _gNgDebugLevel = 0;
96 
97 /* Debug printing functions */
98 void    (*_NgLog) (const char *fmt,...) = warn;
99 void    (*_NgLogx) (const char *fmt,...) = warnx;
100 
101 /* Internal functions */
102 static const	char *NgCookie(int cookie);
103 
104 /* Known typecookie list */
105 struct ng_cookie {
106 	int		cookie;
107 	const char	*type;
108 };
109 
110 #define COOKIE(c)	{ NGM_ ## c ## _COOKIE, #c }
111 
112 /* List of known cookies */
113 static const struct ng_cookie cookies[] = {
114 	COOKIE(UI),
115 	COOKIE(ASYNC),
116 	COOKIE(BPF),
117 	COOKIE(BRIDGE),
118 	COOKIE(CISCO),
119 	COOKIE(ECHO),
120 	COOKIE(EIFACE),
121 	COOKIE(ETF),
122 	COOKIE(ETHER),
123 	COOKIE(FRAMERELAY),
124 	COOKIE(GENERIC),
125 	COOKIE(HOLE),
126 	COOKIE(IFACE),
127 	COOKIE(KSOCKET),
128 	COOKIE(L2TP),
129 	COOKIE(LMI),
130 	COOKIE(MPPC),
131 	COOKIE(ONE2MANY),
132 	COOKIE(PPP),
133 	COOKIE(PPPOE),
134 	COOKIE(PPTPGRE),
135 	COOKIE(RFC1490),
136 	COOKIE(SOCKET),
137 	COOKIE(TEE),
138 	COOKIE(TTY),
139 	COOKIE(VJC),
140 #ifdef WHISTLE
141 	COOKIE(DF),
142 	COOKIE(IPAC),
143 	COOKIE(TN),
144 	COOKIE(WFRA),
145 #endif
146 	{ 0, NULL }
147 };
148 
149 /*
150  * Set debug level, ie, verbosity, if "level" is non-negative.
151  * Returns old debug level.
152  */
153 int
154 NgSetDebug(int level)
155 {
156 	int old = _gNgDebugLevel;
157 
158 	if (level < 0)
159 		level = old;
160 	_gNgDebugLevel = level;
161 	return (old);
162 }
163 
164 /*
165  * Set debug logging functions.
166  */
167 void
168 NgSetErrLog(void (*log) (const char *fmt,...),
169 		void (*logx) (const char *fmt,...))
170 {
171 	_NgLog = log;
172 	_NgLogx = logx;
173 }
174 
175 /*
176  * Display a netgraph sockaddr
177  */
178 void
179 _NgDebugSockaddr(const struct sockaddr_ng *sg)
180 {
181 	NGLOGX("SOCKADDR: { fam=%d len=%d addr=\"%s\" }",
182 	       sg->sg_family, sg->sg_len, sg->sg_data);
183 }
184 
185 #define ARGS_BUFSIZE		2048
186 #define RECURSIVE_DEBUG_ADJUST	4
187 
188 /*
189  * Display a negraph message
190  */
191 void
192 _NgDebugMsg(const struct ng_mesg *msg, const char *path)
193 {
194 	u_char buf[2 * sizeof(struct ng_mesg) + ARGS_BUFSIZE];
195 	struct ng_mesg *const req = (struct ng_mesg *)buf;
196 	struct ng_mesg *const bin = (struct ng_mesg *)req->data;
197 	int arglen, csock = -1;
198 
199 	/* Display header stuff */
200 	NGLOGX("NG_MESG :");
201 	NGLOGX("  vers   %d", msg->header.version);
202 	NGLOGX("  arglen %d", msg->header.arglen);
203 	NGLOGX("  flags  %ld", msg->header.flags);
204 	NGLOGX("  token  %lu", (u_long)msg->header.token);
205 	NGLOGX("  cookie %s (%d)",
206 	    NgCookie(msg->header.typecookie), msg->header.typecookie);
207 
208 	/* At lower debugging levels, skip ASCII translation */
209 	if (_gNgDebugLevel <= 2)
210 		goto fail2;
211 
212 	/* If path is not absolute, don't bother trying to use relative
213 	   address on a different socket for the ASCII translation */
214 	if (strchr(path, ':') == NULL)
215 		goto fail2;
216 
217 	/* Get a temporary socket */
218 	if (NgMkSockNode(NULL, &csock, NULL) < 0)
219 		goto fail;
220 
221 	/* Copy binary message into request message payload */
222 	arglen = msg->header.arglen;
223 	if (arglen > ARGS_BUFSIZE)
224 		arglen = ARGS_BUFSIZE;
225 	memcpy(bin, msg, sizeof(*msg) + arglen);
226 	bin->header.arglen = arglen;
227 
228 	/* Lower debugging to avoid infinite recursion */
229 	_gNgDebugLevel -= RECURSIVE_DEBUG_ADJUST;
230 
231 	/* Ask the node to translate the binary message to ASCII for us */
232 	if (NgSendMsg(csock, path, NGM_GENERIC_COOKIE,
233 	    NGM_BINARY2ASCII, bin, sizeof(*bin) + bin->header.arglen) < 0) {
234 		_gNgDebugLevel += RECURSIVE_DEBUG_ADJUST;
235 		goto fail;
236 	}
237 	if (NgRecvMsg(csock, req, sizeof(buf), NULL) < 0) {
238 		_gNgDebugLevel += RECURSIVE_DEBUG_ADJUST;
239 		goto fail;
240 	}
241 
242 	/* Restore debugging level */
243 	_gNgDebugLevel += RECURSIVE_DEBUG_ADJUST;
244 
245 	/* Display command string and arguments */
246 	NGLOGX("  cmd    %s (%d)", bin->header.cmdstr, bin->header.cmd);
247 	NGLOGX("  args   %s", bin->data);
248 	goto done;
249 
250 fail:
251 	/* Just display binary version */
252 	NGLOGX("  [error decoding message: %s]", strerror(errno));
253 fail2:
254 	NGLOGX("  cmd    %d", msg->header.cmd);
255 	NGLOGX("  args (%d bytes)", msg->header.arglen);
256 	_NgDebugBytes(msg->data, msg->header.arglen);
257 
258 done:
259 	if (csock != -1)
260 		(void)close(csock);
261 }
262 
263 /*
264  * Return the name of the node type corresponding to the cookie
265  */
266 static const char *
267 NgCookie(int cookie)
268 {
269 	int k;
270 
271 	for (k = 0; cookies[k].cookie != 0; k++) {
272 		if (cookies[k].cookie == cookie)
273 			return cookies[k].type;
274 	}
275 	return "??";
276 }
277 
278 /*
279  * Dump bytes in hex
280  */
281 void
282 _NgDebugBytes(const u_char *ptr, int len)
283 {
284 	char    buf[100];
285 	int     k, count;
286 
287 #define BYPERLINE	16
288 
289 	for (count = 0; count < len; ptr += BYPERLINE, count += BYPERLINE) {
290 
291 		/* Do hex */
292 		snprintf(buf, sizeof(buf), "%04x:  ", count);
293 		for (k = 0; k < BYPERLINE; k++, count++)
294 			if (count < len)
295 				snprintf(buf + strlen(buf),
296 				    sizeof(buf) - strlen(buf), "%02x ", ptr[k]);
297 			else
298 				snprintf(buf + strlen(buf),
299 				    sizeof(buf) - strlen(buf), "   ");
300 		snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "  ");
301 		count -= BYPERLINE;
302 
303 		/* Do ASCII */
304 		for (k = 0; k < BYPERLINE; k++, count++)
305 			if (count < len)
306 				snprintf(buf + strlen(buf),
307 				    sizeof(buf) - strlen(buf),
308 				    "%c", isprint(ptr[k]) ? ptr[k] : '.');
309 			else
310 				snprintf(buf + strlen(buf),
311 				    sizeof(buf) - strlen(buf), "  ");
312 		count -= BYPERLINE;
313 
314 		/* Print it */
315 		NGLOGX("%s", buf);
316 	}
317 }
318 
319