64b7a6afd1ca335c1a739165ae09f1a2f8bbea29
[dragonfly.git] / lib / libnetgraph / debug.c
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