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