| 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 | * $FreeBSD: src/lib/libnetgraph/debug.c,v 1.9 2005/10/25 20:58:30 ru Exp $ |
| 39 | * $DragonFly: src/lib/libnetgraph/debug.c,v 1.4 2007/06/17 20:33:14 swildner 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 <netgraph7/ng_message.h> |
| 54 | #include <netgraph7/socket/ng_socket.h> |
| 55 | |
| 56 | #include "netgraph.h" |
| 57 | #include "internal.h" |
| 58 | |
| 59 | #include <netgraph7/UI/ng_UI.h> |
| 60 | #include <netgraph7/async/ng_async.h> |
| 61 | #include <netgraph7/atmllc/ng_atmllc.h> |
| 62 | #include <netgraph7/bpf/ng_bpf.h> |
| 63 | #include <netgraph/bridge/ng_bridge.h> |
| 64 | #include <netgraph7/cisco/ng_cisco.h> |
| 65 | #include <netgraph7/deflate/ng_deflate.h> |
| 66 | #include <netgraph7/echo/ng_echo.h> |
| 67 | /* |
| 68 | #include <netgraph7/eiface/ng_eiface.h> |
| 69 | */ |
| 70 | #include <netgraph7/etf/ng_etf.h> |
| 71 | #include <netgraph7/ether/ng_ether.h> |
| 72 | /* |
| 73 | #include <netgraph7/fec/ng_fec.h> |
| 74 | */ |
| 75 | #include <netgraph7/frame_relay/ng_frame_relay.h> |
| 76 | #include <netgraph7/hole/ng_hole.h> |
| 77 | /* |
| 78 | #include <netgraph7/hub/ng_hub.h> |
| 79 | */ |
| 80 | #include <netgraph7/iface/ng_iface.h> |
| 81 | /* |
| 82 | #include <netgraph7/ip_input/ng_ip_input.h> |
| 83 | */ |
| 84 | #include <netgraph7/ksocket/ng_ksocket.h> |
| 85 | #include <netgraph7/l2tp/ng_l2tp.h> |
| 86 | #include <netgraph7/lmi/ng_lmi.h> |
| 87 | #include <netgraph7/mppc/ng_mppc.h> |
| 88 | #include <netgraph7/one2many/ng_one2many.h> |
| 89 | #include <netgraph7/ppp/ng_ppp.h> |
| 90 | /* |
| 91 | #include <netgraph7/pppoe/ng_pppoe.h> |
| 92 | */ |
| 93 | #include <netgraph7/pptpgre/ng_pptpgre.h> |
| 94 | /* |
| 95 | #include <netgraph7/rfc1490/ng_rfc1490.h> |
| 96 | #include <netgraph7/socket/ng_socket.h> |
| 97 | #include <netgraph7/source/ng_source.h> |
| 98 | #include <netgraph7/split/ng_split.h> |
| 99 | #include <netgraph7/tcpmss/ng_tcpmss.h> |
| 100 | */ |
| 101 | #include <netgraph7/tee/ng_tee.h> |
| 102 | /* |
| 103 | #include <netgraph7/tty/ng_tty.h> |
| 104 | */ |
| 105 | #include <netgraph7/vjc/ng_vjc.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(CISCO), |
| 141 | COOKIE(DEFLATE), |
| 142 | COOKIE(ECHO), |
| 143 | /* |
| 144 | COOKIE(EIFACE), |
| 145 | */ |
| 146 | COOKIE(ETF), |
| 147 | COOKIE(ETHER), |
| 148 | /* |
| 149 | COOKIE(FEC), |
| 150 | */ |
| 151 | COOKIE(FRAMERELAY), |
| 152 | COOKIE(GENERIC), |
| 153 | COOKIE(HOLE), |
| 154 | /* |
| 155 | COOKIE(HUB), |
| 156 | */ |
| 157 | COOKIE(IFACE), |
| 158 | /* |
| 159 | COOKIE(IP_INPUT), |
| 160 | */ |
| 161 | COOKIE(KSOCKET), |
| 162 | COOKIE(L2TP), |
| 163 | COOKIE(LMI), |
| 164 | COOKIE(MPPC), |
| 165 | COOKIE(ONE2MANY), |
| 166 | COOKIE(PPP), |
| 167 | /* |
| 168 | COOKIE(PPPOE), |
| 169 | */ |
| 170 | COOKIE(PPTPGRE), |
| 171 | /* |
| 172 | COOKIE(RFC1490), |
| 173 | */ |
| 174 | COOKIE(SOCKET), |
| 175 | /* |
| 176 | COOKIE(SOURCE), |
| 177 | COOKIE(SPLIT), |
| 178 | COOKIE(TCPMSS), |
| 179 | */ |
| 180 | COOKIE(TEE), |
| 181 | /* |
| 182 | COOKIE(TTY), |
| 183 | */ |
| 184 | COOKIE(VJC), |
| 185 | #ifdef WHISTLE |
| 186 | COOKIE(DF), |
| 187 | COOKIE(IPAC), |
| 188 | COOKIE(TN), |
| 189 | COOKIE(WFRA), |
| 190 | #endif |
| 191 | { 0, NULL } |
| 192 | }; |
| 193 | |
| 194 | /* |
| 195 | * Set debug level, ie, verbosity, if "level" is non-negative. |
| 196 | * Returns old debug level. |
| 197 | */ |
| 198 | int |
| 199 | NgSetDebug(int level) |
| 200 | { |
| 201 | int old = _gNgDebugLevel; |
| 202 | |
| 203 | if (level < 0) |
| 204 | level = old; |
| 205 | _gNgDebugLevel = level; |
| 206 | return (old); |
| 207 | } |
| 208 | |
| 209 | /* |
| 210 | * Set debug logging functions. |
| 211 | */ |
| 212 | void |
| 213 | NgSetErrLog(void (*log) (const char *fmt,...), |
| 214 | void (*logx) (const char *fmt,...)) |
| 215 | { |
| 216 | _NgLog = log; |
| 217 | _NgLogx = logx; |
| 218 | } |
| 219 | |
| 220 | /* |
| 221 | * Display a netgraph sockaddr |
| 222 | */ |
| 223 | void |
| 224 | _NgDebugSockaddr(const struct sockaddr_ng *sg) |
| 225 | { |
| 226 | NGLOGX("SOCKADDR: { fam=%d len=%d addr=\"%s\" }", |
| 227 | sg->sg_family, sg->sg_len, sg->sg_data); |
| 228 | } |
| 229 | |
| 230 | #define ARGS_BUFSIZE 2048 |
| 231 | #define RECURSIVE_DEBUG_ADJUST 4 |
| 232 | |
| 233 | /* |
| 234 | * Display a negraph message |
| 235 | */ |
| 236 | void |
| 237 | _NgDebugMsg(const struct ng_mesg *msg, const char *path) |
| 238 | { |
| 239 | u_char buf[2 * sizeof(struct ng_mesg) + ARGS_BUFSIZE]; |
| 240 | struct ng_mesg *const req = (struct ng_mesg *)buf; |
| 241 | struct ng_mesg *const bin = (struct ng_mesg *)req->data; |
| 242 | int arglen, csock = -1; |
| 243 | |
| 244 | /* Display header stuff */ |
| 245 | NGLOGX("NG_MESG :"); |
| 246 | NGLOGX(" vers %d", msg->header.version); |
| 247 | NGLOGX(" arglen %d", msg->header.arglen); |
| 248 | NGLOGX(" flags %ld", msg->header.flags); |
| 249 | NGLOGX(" token %lu", (u_long)msg->header.token); |
| 250 | NGLOGX(" cookie %s (%d)", |
| 251 | NgCookie(msg->header.typecookie), msg->header.typecookie); |
| 252 | |
| 253 | /* At lower debugging levels, skip ASCII translation */ |
| 254 | if (_gNgDebugLevel <= 2) |
| 255 | goto fail2; |
| 256 | |
| 257 | /* If path is not absolute, don't bother trying to use relative |
| 258 | address on a different socket for the ASCII translation */ |
| 259 | if (strchr(path, ':') == NULL) |
| 260 | goto fail2; |
| 261 | |
| 262 | /* Get a temporary socket */ |
| 263 | if (NgMkSockNode(NULL, &csock, NULL) < 0) |
| 264 | goto fail; |
| 265 | |
| 266 | /* Copy binary message into request message payload */ |
| 267 | arglen = msg->header.arglen; |
| 268 | if (arglen > ARGS_BUFSIZE) |
| 269 | arglen = ARGS_BUFSIZE; |
| 270 | memcpy(bin, msg, sizeof(*msg) + arglen); |
| 271 | bin->header.arglen = arglen; |
| 272 | |
| 273 | /* Lower debugging to avoid infinite recursion */ |
| 274 | _gNgDebugLevel -= RECURSIVE_DEBUG_ADJUST; |
| 275 | |
| 276 | /* Ask the node to translate the binary message to ASCII for us */ |
| 277 | if (NgSendMsg(csock, path, NGM_GENERIC_COOKIE, |
| 278 | NGM_BINARY2ASCII, bin, sizeof(*bin) + bin->header.arglen) < 0) { |
| 279 | _gNgDebugLevel += RECURSIVE_DEBUG_ADJUST; |
| 280 | goto fail; |
| 281 | } |
| 282 | if (NgRecvMsg(csock, req, sizeof(buf), NULL) < 0) { |
| 283 | _gNgDebugLevel += RECURSIVE_DEBUG_ADJUST; |
| 284 | goto fail; |
| 285 | } |
| 286 | |
| 287 | /* Restore debugging level */ |
| 288 | _gNgDebugLevel += RECURSIVE_DEBUG_ADJUST; |
| 289 | |
| 290 | /* Display command string and arguments */ |
| 291 | NGLOGX(" cmd %s (%d)", bin->header.cmdstr, bin->header.cmd); |
| 292 | NGLOGX(" args %s", bin->data); |
| 293 | goto done; |
| 294 | |
| 295 | fail: |
| 296 | /* Just display binary version */ |
| 297 | NGLOGX(" [error decoding message: %s]", strerror(errno)); |
| 298 | fail2: |
| 299 | NGLOGX(" cmd %d", msg->header.cmd); |
| 300 | NGLOGX(" args (%d bytes)", msg->header.arglen); |
| 301 | _NgDebugBytes(msg->data, msg->header.arglen); |
| 302 | |
| 303 | done: |
| 304 | if (csock != -1) |
| 305 | (void)close(csock); |
| 306 | } |
| 307 | |
| 308 | /* |
| 309 | * Return the name of the node type corresponding to the cookie |
| 310 | */ |
| 311 | static const char * |
| 312 | NgCookie(int cookie) |
| 313 | { |
| 314 | int k; |
| 315 | |
| 316 | for (k = 0; cookies[k].cookie != 0; k++) { |
| 317 | if (cookies[k].cookie == cookie) |
| 318 | return cookies[k].type; |
| 319 | } |
| 320 | return "??"; |
| 321 | } |
| 322 | |
| 323 | /* |
| 324 | * Dump bytes in hex |
| 325 | */ |
| 326 | void |
| 327 | _NgDebugBytes(const u_char *ptr, int len) |
| 328 | { |
| 329 | char buf[100]; |
| 330 | int k, count; |
| 331 | |
| 332 | #define BYPERLINE 16 |
| 333 | |
| 334 | for (count = 0; count < len; ptr += BYPERLINE, count += BYPERLINE) { |
| 335 | |
| 336 | /* Do hex */ |
| 337 | snprintf(buf, sizeof(buf), "%04x: ", count); |
| 338 | for (k = 0; k < BYPERLINE; k++, count++) |
| 339 | if (count < len) |
| 340 | snprintf(buf + strlen(buf), |
| 341 | sizeof(buf) - strlen(buf), "%02x ", ptr[k]); |
| 342 | else |
| 343 | snprintf(buf + strlen(buf), |
| 344 | sizeof(buf) - strlen(buf), " "); |
| 345 | snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " "); |
| 346 | count -= BYPERLINE; |
| 347 | |
| 348 | /* Do ASCII */ |
| 349 | for (k = 0; k < BYPERLINE; k++, count++) |
| 350 | if (count < len) |
| 351 | snprintf(buf + strlen(buf), |
| 352 | sizeof(buf) - strlen(buf), |
| 353 | "%c", isprint(ptr[k]) ? ptr[k] : '.'); |
| 354 | else |
| 355 | snprintf(buf + strlen(buf), |
| 356 | sizeof(buf) - strlen(buf), " "); |
| 357 | count -= BYPERLINE; |
| 358 | |
| 359 | /* Print it */ |
| 360 | NGLOGX("%s", buf); |
| 361 | } |
| 362 | } |
| 363 | |