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