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_car.h>
66 #include <netgraph/ng_cisco.h>
67 #include <netgraph/ng_deflate.h>
68 #include <netgraph/ng_device.h>
69 #include <netgraph/ng_echo.h>
70 #include <netgraph/ng_eiface.h>
71 #include <netgraph/ng_etf.h>
72 #include <netgraph/ng_ether.h>
73 #include <netgraph/ng_fec.h>
74 #include <netgraph/ng_ether_echo.h>
75 #include <netgraph/ng_frame_relay.h>
76 #include <netgraph/ng_gif.h>
77 #include <netgraph/ng_gif_demux.h>
78 #include <netgraph/ng_hole.h>
79 #include <netgraph/ng_hub.h>
80 #include <netgraph/ng_iface.h>
81 #include <netgraph/ng_ip_input.h>
82 #include <netgraph/ng_ipfw.h>
83 #include <netgraph/ng_ksocket.h>
84 #include <netgraph/ng_l2tp.h>
85 #include <netgraph/ng_lmi.h>
86 #include <netgraph/ng_mppc.h>
87 #include <netgraph/ng_nat.h>
88 #include <netgraph/netflow/ng_netflow.h>
89 #include <netgraph/ng_one2many.h>
90 #include <netgraph/ng_patch.h>
91 #include <netgraph/ng_pipe.h>
92 #include <netgraph/ng_ppp.h>
93 #include <netgraph/ng_pppoe.h>
94 #include <netgraph/ng_pptpgre.h>
95 #include <netgraph/ng_pred1.h>
96 #include <netgraph/ng_rfc1490.h>
97 #include <netgraph/ng_socket.h>
98 #include <netgraph/ng_source.h>
99 #include <netgraph/ng_split.h>
100 #include <netgraph/ng_sppp.h>
101 #include <netgraph/ng_tag.h>
102 #include <netgraph/ng_tcpmss.h>
103 #include <netgraph/ng_tee.h>
104 #include <netgraph/ng_tty.h>
105 #include <netgraph/ng_vjc.h>
106 #include <netgraph/ng_vlan.h>
107 #ifdef WHISTLE
108 #include <machine/../isa/df_def.h>
109 #include <machine/../isa/if_wfra.h>
110 #include <machine/../isa/ipac.h>
111 #include <netgraph/ng_df.h>
112 #include <netgraph/ng_ipac.h>
113 #include <netgraph/ng_tn.h>
114 #endif
115
116 /* Global debug level */
117 int _gNgDebugLevel = 0;
118
119 /* Debug printing functions */
120 void (*_NgLog) (const char *fmt,...) = warn;
121 void (*_NgLogx) (const char *fmt,...) = warnx;
122
123 /* Internal functions */
124 static const char *NgCookie(int cookie);
125
126 /* Known typecookie list */
127 struct ng_cookie {
128 int cookie;
129 const char *type;
130 };
131
132 #define COOKIE(c) { NGM_ ## c ## _COOKIE, #c }
133
134 /* List of known cookies */
135 static const struct ng_cookie cookies[] = {
136 COOKIE(UI),
137 COOKIE(ASYNC),
138 COOKIE(ATMLLC),
139 COOKIE(BPF),
140 COOKIE(BRIDGE),
141 COOKIE(CAR),
142 COOKIE(CISCO),
143 COOKIE(DEFLATE),
144 COOKIE(DEVICE),
145 COOKIE(ECHO),
146 COOKIE(EIFACE),
147 COOKIE(ETF),
148 COOKIE(ETHER),
149 COOKIE(FEC),
150 COOKIE(ETHER_ECHO),
151 COOKIE(FRAMERELAY),
152 COOKIE(GIF),
153 COOKIE(GIF_DEMUX),
154 COOKIE(GENERIC),
155 COOKIE(HOLE),
156 COOKIE(HUB),
157 COOKIE(IFACE),
158 COOKIE(IP_INPUT),
159 COOKIE(IPFW),
160 COOKIE(KSOCKET),
161 COOKIE(L2TP),
162 COOKIE(LMI),
163 COOKIE(MPPC),
164 COOKIE(NAT),
165 COOKIE(NETFLOW),
166 COOKIE(ONE2MANY),
167 COOKIE(PATCH),
168 COOKIE(PIPE),
169 COOKIE(PPP),
170 COOKIE(PPPOE),
171 COOKIE(PPTPGRE),
172 COOKIE(PRED1),
173 COOKIE(RFC1490),
174 COOKIE(SOCKET),
175 COOKIE(SOURCE),
176 COOKIE(SPLIT),
177 COOKIE(SPPP),
178 COOKIE(TAG),
179 COOKIE(TCPMSS),
180 COOKIE(TEE),
181 COOKIE(TTY),
182 COOKIE(VJC),
183 COOKIE(VLAN),
184 #ifdef WHISTLE
185 COOKIE(DF),
186 COOKIE(IPAC),
187 COOKIE(TN),
188 COOKIE(WFRA),
189 #endif
190 { 0, NULL }
191 };
192
193 /*
194 * Set debug level, ie, verbosity, if "level" is non-negative.
195 * Returns old debug level.
196 */
197 int
NgSetDebug(int level)198 NgSetDebug(int level)
199 {
200 int old = _gNgDebugLevel;
201
202 if (level >= 0)
203 _gNgDebugLevel = level;
204 return (old);
205 }
206
207 /*
208 * Set debug logging functions.
209 */
210 void
NgSetErrLog(void (* log)(const char * fmt,...),void (* logx)(const char * fmt,...))211 NgSetErrLog(void (*log) (const char *fmt,...),
212 void (*logx) (const char *fmt,...))
213 {
214 _NgLog = log;
215 _NgLogx = logx;
216 }
217
218 /*
219 * Display a netgraph sockaddr
220 */
221 void
_NgDebugSockaddr(const struct sockaddr_ng * sg)222 _NgDebugSockaddr(const struct sockaddr_ng *sg)
223 {
224 NGLOGX("SOCKADDR: { fam=%d len=%d addr=\"%s\" }",
225 sg->sg_family, sg->sg_len, sg->sg_data);
226 }
227
228 #define ARGS_BUFSIZE 2048
229 #define RECURSIVE_DEBUG_ADJUST 4
230
231 /*
232 * Display a negraph message
233 */
234 void
_NgDebugMsg(const struct ng_mesg * msg,const char * path)235 _NgDebugMsg(const struct ng_mesg *msg, const char *path)
236 {
237 u_char buf[2 * sizeof(struct ng_mesg) + ARGS_BUFSIZE];
238 struct ng_mesg *const req = (struct ng_mesg *)buf;
239 struct ng_mesg *const bin = (struct ng_mesg *)req->data;
240 int arglen, csock = -1;
241
242 /* Display header stuff */
243 NGLOGX("NG_MESG :");
244 NGLOGX(" vers %d", msg->header.version);
245 NGLOGX(" arglen %u", msg->header.arglen);
246 NGLOGX(" flags %x", msg->header.flags);
247 NGLOGX(" token %u", msg->header.token);
248 NGLOGX(" cookie %s (%u)",
249 NgCookie(msg->header.typecookie), msg->header.typecookie);
250
251 /* At lower debugging levels, skip ASCII translation */
252 if (_gNgDebugLevel <= 2)
253 goto fail2;
254
255 /* If path is not absolute, don't bother trying to use relative
256 address on a different socket for the ASCII translation */
257 if (strchr(path, ':') == NULL)
258 goto fail2;
259
260 /* Get a temporary socket */
261 if (NgMkSockNode(NULL, &csock, NULL) < 0)
262 goto fail;
263
264 /* Copy binary message into request message payload */
265 arglen = msg->header.arglen;
266 if (arglen > ARGS_BUFSIZE)
267 arglen = ARGS_BUFSIZE;
268 memcpy(bin, msg, sizeof(*msg) + arglen);
269 bin->header.arglen = arglen;
270
271 /* Lower debugging to avoid infinite recursion */
272 _gNgDebugLevel -= RECURSIVE_DEBUG_ADJUST;
273
274 /* Ask the node to translate the binary message to ASCII for us */
275 if (NgSendMsg(csock, path, NGM_GENERIC_COOKIE,
276 NGM_BINARY2ASCII, bin, sizeof(*bin) + bin->header.arglen) < 0) {
277 _gNgDebugLevel += RECURSIVE_DEBUG_ADJUST;
278 goto fail;
279 }
280 if (NgRecvMsg(csock, req, sizeof(buf), NULL) < 0) {
281 _gNgDebugLevel += RECURSIVE_DEBUG_ADJUST;
282 goto fail;
283 }
284
285 /* Restore debugging level */
286 _gNgDebugLevel += RECURSIVE_DEBUG_ADJUST;
287
288 /* Display command string and arguments */
289 NGLOGX(" cmd %s (%d)", bin->header.cmdstr, bin->header.cmd);
290 NGLOGX(" args %s", bin->data);
291 goto done;
292
293 fail:
294 /* Just display binary version */
295 NGLOGX(" [error decoding message: %s]", strerror(errno));
296 fail2:
297 NGLOGX(" cmd %d", msg->header.cmd);
298 NGLOGX(" args (%d bytes)", msg->header.arglen);
299 _NgDebugBytes((u_char *)msg->data, msg->header.arglen);
300
301 done:
302 if (csock != -1)
303 (void)close(csock);
304 }
305
306 /*
307 * Return the name of the node type corresponding to the cookie
308 */
309 static const char *
NgCookie(int cookie)310 NgCookie(int cookie)
311 {
312 int k;
313
314 for (k = 0; cookies[k].cookie != 0; k++) {
315 if (cookies[k].cookie == cookie)
316 return cookies[k].type;
317 }
318 return "??";
319 }
320
321 /*
322 * Dump bytes in hex
323 */
324 void
_NgDebugBytes(const u_char * ptr,int len)325 _NgDebugBytes(const u_char *ptr, int len)
326 {
327 char buf[100];
328 int k, count;
329
330 #define BYPERLINE 16
331
332 for (count = 0; count < len; ptr += BYPERLINE, count += BYPERLINE) {
333
334 /* Do hex */
335 snprintf(buf, sizeof(buf), "%04x: ", count);
336 for (k = 0; k < BYPERLINE; k++, count++)
337 if (count < len)
338 snprintf(buf + strlen(buf),
339 sizeof(buf) - strlen(buf), "%02x ", ptr[k]);
340 else
341 snprintf(buf + strlen(buf),
342 sizeof(buf) - strlen(buf), " ");
343 snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " ");
344 count -= BYPERLINE;
345
346 /* Do ASCII */
347 for (k = 0; k < BYPERLINE; k++, count++)
348 if (count < len)
349 snprintf(buf + strlen(buf),
350 sizeof(buf) - strlen(buf),
351 "%c", isprint(ptr[k]) ? ptr[k] : '.');
352 else
353 snprintf(buf + strlen(buf),
354 sizeof(buf) - strlen(buf), " ");
355 count -= BYPERLINE;
356
357 /* Print it */
358 NGLOGX("%s", buf);
359 }
360 }
361
362