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