xref: /freebsd/lib/libnetgraph/debug.c (revision a9148abd9da5db2f1c682fb17bed791845fc41c9)
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