Kernel tree reorganization stage 2: Major cvs repository work.
[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.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