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