xref: /dragonfly/lib/libnetgraph/debug.c (revision 86d7f5d305c6adaa56ff4582ece9859d73106103)
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
NgSetDebug(int level)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
NgSetErrLog(void (* log)(const char * fmt,...),void (* logx)(const char * fmt,...))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
_NgDebugSockaddr(const struct sockaddr_ng * sg)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
_NgDebugMsg(const struct ng_mesg * msg,const char * path)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 *
NgCookie(int cookie)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
_NgDebugBytes(const u_char * ptr,int len)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