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