14cf49a43SJulian Elischer /* 24cf49a43SJulian Elischer * debug.c 34cf49a43SJulian Elischer * 44cf49a43SJulian Elischer * Copyright (c) 1996-1999 Whistle Communications, Inc. 54cf49a43SJulian Elischer * All rights reserved. 64cf49a43SJulian Elischer * 74cf49a43SJulian Elischer * Subject to the following obligations and disclaimer of warranty, use and 84cf49a43SJulian Elischer * redistribution of this software, in source or object code forms, with or 94cf49a43SJulian Elischer * without modifications are expressly permitted by Whistle Communications; 104cf49a43SJulian Elischer * provided, however, that: 114cf49a43SJulian Elischer * 1. Any and all reproductions of the source or object code must include the 124cf49a43SJulian Elischer * copyright notice above and the following disclaimer of warranties; and 134cf49a43SJulian Elischer * 2. No rights are granted, in any manner or form, to use Whistle 144cf49a43SJulian Elischer * Communications, Inc. trademarks, including the mark "WHISTLE 154cf49a43SJulian Elischer * COMMUNICATIONS" on advertising, endorsements, or otherwise except as 164cf49a43SJulian Elischer * such appears in the above copyright notice or in the software. 174cf49a43SJulian Elischer * 184cf49a43SJulian Elischer * THIS SOFTWARE IS BEING PROVIDED BY WHISTLE COMMUNICATIONS "AS IS", AND 194cf49a43SJulian Elischer * TO THE MAXIMUM EXTENT PERMITTED BY LAW, WHISTLE COMMUNICATIONS MAKES NO 204cf49a43SJulian Elischer * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING THIS SOFTWARE, 214cf49a43SJulian Elischer * INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED WARRANTIES OF 224cf49a43SJulian Elischer * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. 234cf49a43SJulian Elischer * WHISTLE COMMUNICATIONS DOES NOT WARRANT, GUARANTEE, OR MAKE ANY 244cf49a43SJulian Elischer * REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS OF THE USE OF THIS 254cf49a43SJulian Elischer * SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY, RELIABILITY OR OTHERWISE. 264cf49a43SJulian Elischer * IN NO EVENT SHALL WHISTLE COMMUNICATIONS BE LIABLE FOR ANY DAMAGES 274cf49a43SJulian Elischer * RESULTING FROM OR ARISING OUT OF ANY USE OF THIS SOFTWARE, INCLUDING 284cf49a43SJulian Elischer * WITHOUT LIMITATION, ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 294cf49a43SJulian Elischer * PUNITIVE, OR CONSEQUENTIAL DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR 304cf49a43SJulian Elischer * SERVICES, LOSS OF USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY 314cf49a43SJulian Elischer * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 324cf49a43SJulian Elischer * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 334cf49a43SJulian Elischer * THIS SOFTWARE, EVEN IF WHISTLE COMMUNICATIONS IS ADVISED OF THE POSSIBILITY 344cf49a43SJulian Elischer * OF SUCH DAMAGE. 354cf49a43SJulian Elischer * 364cf49a43SJulian Elischer * Author: Archie Cobbs <archie@whistle.com> 374cf49a43SJulian Elischer * 384cf49a43SJulian Elischer * $Whistle: debug.c,v 1.24 1999/01/24 01:15:33 archie Exp $ 394cf49a43SJulian Elischer */ 404cf49a43SJulian Elischer 41fd0d00c5SMatthew Dillon #include <sys/cdefs.h> 42fd0d00c5SMatthew Dillon __FBSDID("$FreeBSD$"); 43fd0d00c5SMatthew Dillon 444cf49a43SJulian Elischer #include <sys/types.h> 45baa60a3bSArchie Cobbs #include <sys/time.h> 46baa60a3bSArchie Cobbs #include <sys/ioctl.h> 47f8307e12SArchie Cobbs 484cf49a43SJulian Elischer #include <stdarg.h> 49f8307e12SArchie Cobbs 50f8307e12SArchie Cobbs #include <netinet/in.h> 51f8307e12SArchie Cobbs #include <net/ethernet.h> 52baa60a3bSArchie Cobbs #include <net/bpf.h> 53f8307e12SArchie Cobbs 544cf49a43SJulian Elischer #include <netgraph/ng_message.h> 554cf49a43SJulian Elischer #include <netgraph/ng_socket.h> 564cf49a43SJulian Elischer 574cf49a43SJulian Elischer #include "netgraph.h" 584cf49a43SJulian Elischer #include "internal.h" 594cf49a43SJulian Elischer 60f8307e12SArchie Cobbs #include <netgraph/ng_UI.h> 614cf49a43SJulian Elischer #include <netgraph/ng_async.h> 6241fa1ea9SRuslan Ermilov #include <netgraph/ng_atmllc.h> 63baa60a3bSArchie Cobbs #include <netgraph/ng_bpf.h> 6441fa1ea9SRuslan Ermilov #include <netgraph/ng_bridge.h> 65*78a786f9SAlexander Motin #include <netgraph/ng_car.h> 66f8307e12SArchie Cobbs #include <netgraph/ng_cisco.h> 67*78a786f9SAlexander Motin #include <netgraph/ng_deflate.h> 6841fa1ea9SRuslan Ermilov #include <netgraph/ng_device.h> 69f8307e12SArchie Cobbs #include <netgraph/ng_echo.h> 7041fa1ea9SRuslan Ermilov #include <netgraph/ng_eiface.h> 7141fa1ea9SRuslan Ermilov #include <netgraph/ng_etf.h> 72f8307e12SArchie Cobbs #include <netgraph/ng_ether.h> 73*78a786f9SAlexander Motin #include <netgraph/ng_ether_echo.h> 744cf49a43SJulian Elischer #include <netgraph/ng_frame_relay.h> 7541fa1ea9SRuslan Ermilov #include <netgraph/ng_gif.h> 7641fa1ea9SRuslan Ermilov #include <netgraph/ng_gif_demux.h> 77f8307e12SArchie Cobbs #include <netgraph/ng_hole.h> 7841fa1ea9SRuslan Ermilov #include <netgraph/ng_hub.h> 79f8307e12SArchie Cobbs #include <netgraph/ng_iface.h> 8041fa1ea9SRuslan Ermilov #include <netgraph/ng_ip_input.h> 8141fa1ea9SRuslan Ermilov #include <netgraph/ng_ipfw.h> 82f8307e12SArchie Cobbs #include <netgraph/ng_ksocket.h> 8341fa1ea9SRuslan Ermilov #include <netgraph/ng_l2tp.h> 844cf49a43SJulian Elischer #include <netgraph/ng_lmi.h> 8541fa1ea9SRuslan Ermilov #include <netgraph/ng_mppc.h> 8641fa1ea9SRuslan Ermilov #include <netgraph/ng_nat.h> 87*78a786f9SAlexander Motin #include <netgraph/netflow/ng_netflow.h> 8841fa1ea9SRuslan Ermilov #include <netgraph/ng_one2many.h> 89*78a786f9SAlexander Motin #include <netgraph/ng_patch.h> 90*78a786f9SAlexander Motin #include <netgraph/ng_pipe.h> 91f8307e12SArchie Cobbs #include <netgraph/ng_ppp.h> 92f8307e12SArchie Cobbs #include <netgraph/ng_pppoe.h> 9341fa1ea9SRuslan Ermilov #include <netgraph/ng_pptpgre.h> 94*78a786f9SAlexander Motin #include <netgraph/ng_pred1.h> 95f8307e12SArchie Cobbs #include <netgraph/ng_rfc1490.h> 96f8307e12SArchie Cobbs #include <netgraph/ng_socket.h> 9741fa1ea9SRuslan Ermilov #include <netgraph/ng_source.h> 9841fa1ea9SRuslan Ermilov #include <netgraph/ng_split.h> 9941fa1ea9SRuslan Ermilov #include <netgraph/ng_sppp.h> 100*78a786f9SAlexander Motin #include <netgraph/ng_tag.h> 10141fa1ea9SRuslan Ermilov #include <netgraph/ng_tcpmss.h> 102f8307e12SArchie Cobbs #include <netgraph/ng_tee.h> 1034cf49a43SJulian Elischer #include <netgraph/ng_tty.h> 104f8307e12SArchie Cobbs #include <netgraph/ng_vjc.h> 10541fa1ea9SRuslan Ermilov #include <netgraph/ng_vlan.h> 106f8307e12SArchie Cobbs #ifdef WHISTLE 107f8307e12SArchie Cobbs #include <machine/../isa/df_def.h> 108f8307e12SArchie Cobbs #include <machine/../isa/if_wfra.h> 109f8307e12SArchie Cobbs #include <machine/../isa/ipac.h> 110f8307e12SArchie Cobbs #include <netgraph/ng_df.h> 111f8307e12SArchie Cobbs #include <netgraph/ng_ipac.h> 112f8307e12SArchie Cobbs #include <netgraph/ng_tn.h> 113f8307e12SArchie Cobbs #endif 1144cf49a43SJulian Elischer 1154cf49a43SJulian Elischer /* Global debug level */ 1164cf49a43SJulian Elischer int _gNgDebugLevel = 0; 1174cf49a43SJulian Elischer 1184cf49a43SJulian Elischer /* Debug printing functions */ 1194cf49a43SJulian Elischer void (*_NgLog) (const char *fmt,...) = warn; 1204cf49a43SJulian Elischer void (*_NgLogx) (const char *fmt,...) = warnx; 1214cf49a43SJulian Elischer 1224cf49a43SJulian Elischer /* Internal functions */ 1234cf49a43SJulian Elischer static const char *NgCookie(int cookie); 124f8307e12SArchie Cobbs 125f8307e12SArchie Cobbs /* Known typecookie list */ 126f8307e12SArchie Cobbs struct ng_cookie { 127f8307e12SArchie Cobbs int cookie; 128f8307e12SArchie Cobbs const char *type; 129f8307e12SArchie Cobbs }; 130f8307e12SArchie Cobbs 131f8307e12SArchie Cobbs #define COOKIE(c) { NGM_ ## c ## _COOKIE, #c } 132f8307e12SArchie Cobbs 133f8307e12SArchie Cobbs /* List of known cookies */ 134f8307e12SArchie Cobbs static const struct ng_cookie cookies[] = { 135f8307e12SArchie Cobbs COOKIE(UI), 136f8307e12SArchie Cobbs COOKIE(ASYNC), 13741fa1ea9SRuslan Ermilov COOKIE(ATMLLC), 138e489a907SArchie Cobbs COOKIE(BPF), 13941fa1ea9SRuslan Ermilov COOKIE(BRIDGE), 140*78a786f9SAlexander Motin COOKIE(CAR), 141f8307e12SArchie Cobbs COOKIE(CISCO), 142*78a786f9SAlexander Motin COOKIE(DEFLATE), 14341fa1ea9SRuslan Ermilov COOKIE(DEVICE), 144f8307e12SArchie Cobbs COOKIE(ECHO), 14541fa1ea9SRuslan Ermilov COOKIE(EIFACE), 14641fa1ea9SRuslan Ermilov COOKIE(ETF), 147f8307e12SArchie Cobbs COOKIE(ETHER), 148*78a786f9SAlexander Motin COOKIE(ETHER_ECHO), 149f8307e12SArchie Cobbs COOKIE(FRAMERELAY), 15041fa1ea9SRuslan Ermilov COOKIE(GIF), 15141fa1ea9SRuslan Ermilov COOKIE(GIF_DEMUX), 152f8307e12SArchie Cobbs COOKIE(GENERIC), 153f8307e12SArchie Cobbs COOKIE(HOLE), 15441fa1ea9SRuslan Ermilov COOKIE(HUB), 155f8307e12SArchie Cobbs COOKIE(IFACE), 15641fa1ea9SRuslan Ermilov COOKIE(IP_INPUT), 15741fa1ea9SRuslan Ermilov COOKIE(IPFW), 158f8307e12SArchie Cobbs COOKIE(KSOCKET), 15941fa1ea9SRuslan Ermilov COOKIE(L2TP), 160f8307e12SArchie Cobbs COOKIE(LMI), 16141fa1ea9SRuslan Ermilov COOKIE(MPPC), 16241fa1ea9SRuslan Ermilov COOKIE(NAT), 163*78a786f9SAlexander Motin COOKIE(NETFLOW), 16441fa1ea9SRuslan Ermilov COOKIE(ONE2MANY), 165*78a786f9SAlexander Motin COOKIE(PATCH), 166*78a786f9SAlexander Motin COOKIE(PIPE), 167f8307e12SArchie Cobbs COOKIE(PPP), 168f8307e12SArchie Cobbs COOKIE(PPPOE), 16941fa1ea9SRuslan Ermilov COOKIE(PPTPGRE), 170*78a786f9SAlexander Motin COOKIE(PRED1), 171f8307e12SArchie Cobbs COOKIE(RFC1490), 172f8307e12SArchie Cobbs COOKIE(SOCKET), 17341fa1ea9SRuslan Ermilov COOKIE(SOURCE), 17441fa1ea9SRuslan Ermilov COOKIE(SPLIT), 17541fa1ea9SRuslan Ermilov COOKIE(SPPP), 176*78a786f9SAlexander Motin COOKIE(TAG), 17741fa1ea9SRuslan Ermilov COOKIE(TCPMSS), 178f8307e12SArchie Cobbs COOKIE(TEE), 179f8307e12SArchie Cobbs COOKIE(TTY), 180f8307e12SArchie Cobbs COOKIE(VJC), 18141fa1ea9SRuslan Ermilov COOKIE(VLAN), 182f8307e12SArchie Cobbs #ifdef WHISTLE 183f8307e12SArchie Cobbs COOKIE(DF), 184f8307e12SArchie Cobbs COOKIE(IPAC), 185f8307e12SArchie Cobbs COOKIE(TN), 186f8307e12SArchie Cobbs COOKIE(WFRA), 187f8307e12SArchie Cobbs #endif 188f8307e12SArchie Cobbs { 0, NULL } 189f8307e12SArchie Cobbs }; 1904cf49a43SJulian Elischer 1914cf49a43SJulian Elischer /* 1924cf49a43SJulian Elischer * Set debug level, ie, verbosity, if "level" is non-negative. 1934cf49a43SJulian Elischer * Returns old debug level. 1944cf49a43SJulian Elischer */ 1954cf49a43SJulian Elischer int 1964cf49a43SJulian Elischer NgSetDebug(int level) 1974cf49a43SJulian Elischer { 1984cf49a43SJulian Elischer int old = _gNgDebugLevel; 1994cf49a43SJulian Elischer 200*78a786f9SAlexander Motin if (level >= 0) 2014cf49a43SJulian Elischer _gNgDebugLevel = level; 2024cf49a43SJulian Elischer return (old); 2034cf49a43SJulian Elischer } 2044cf49a43SJulian Elischer 2054cf49a43SJulian Elischer /* 2064cf49a43SJulian Elischer * Set debug logging functions. 2074cf49a43SJulian Elischer */ 2084cf49a43SJulian Elischer void 2094cf49a43SJulian Elischer NgSetErrLog(void (*log) (const char *fmt,...), 2104cf49a43SJulian Elischer void (*logx) (const char *fmt,...)) 2114cf49a43SJulian Elischer { 2124cf49a43SJulian Elischer _NgLog = log; 2134cf49a43SJulian Elischer _NgLogx = logx; 2144cf49a43SJulian Elischer } 2154cf49a43SJulian Elischer 2164cf49a43SJulian Elischer /* 2174cf49a43SJulian Elischer * Display a netgraph sockaddr 2184cf49a43SJulian Elischer */ 2194cf49a43SJulian Elischer void 220f8307e12SArchie Cobbs _NgDebugSockaddr(const struct sockaddr_ng *sg) 2214cf49a43SJulian Elischer { 2224cf49a43SJulian Elischer NGLOGX("SOCKADDR: { fam=%d len=%d addr=\"%s\" }", 2234cf49a43SJulian Elischer sg->sg_family, sg->sg_len, sg->sg_data); 2244cf49a43SJulian Elischer } 2254cf49a43SJulian Elischer 2261816e452SArchie Cobbs #define ARGS_BUFSIZE 2048 2271816e452SArchie Cobbs #define RECURSIVE_DEBUG_ADJUST 4 228f8307e12SArchie Cobbs 2294cf49a43SJulian Elischer /* 2304cf49a43SJulian Elischer * Display a negraph message 2314cf49a43SJulian Elischer */ 2324cf49a43SJulian Elischer void 233f8307e12SArchie Cobbs _NgDebugMsg(const struct ng_mesg *msg, const char *path) 2344cf49a43SJulian Elischer { 235f8307e12SArchie Cobbs u_char buf[2 * sizeof(struct ng_mesg) + ARGS_BUFSIZE]; 236f8307e12SArchie Cobbs struct ng_mesg *const req = (struct ng_mesg *)buf; 237f8307e12SArchie Cobbs struct ng_mesg *const bin = (struct ng_mesg *)req->data; 2381816e452SArchie Cobbs int arglen, csock = -1; 239f8307e12SArchie Cobbs 240f8307e12SArchie Cobbs /* Display header stuff */ 2414cf49a43SJulian Elischer NGLOGX("NG_MESG :"); 2424cf49a43SJulian Elischer NGLOGX(" vers %d", msg->header.version); 243*78a786f9SAlexander Motin NGLOGX(" arglen %u", msg->header.arglen); 244*78a786f9SAlexander Motin NGLOGX(" flags %x", msg->header.flags); 245*78a786f9SAlexander Motin NGLOGX(" token %u", msg->header.token); 246*78a786f9SAlexander Motin NGLOGX(" cookie %s (%u)", 247f8307e12SArchie Cobbs NgCookie(msg->header.typecookie), msg->header.typecookie); 248f8307e12SArchie Cobbs 249f8307e12SArchie Cobbs /* At lower debugging levels, skip ASCII translation */ 250f8307e12SArchie Cobbs if (_gNgDebugLevel <= 2) 251f8307e12SArchie Cobbs goto fail2; 252f8307e12SArchie Cobbs 253f8307e12SArchie Cobbs /* If path is not absolute, don't bother trying to use relative 254f8307e12SArchie Cobbs address on a different socket for the ASCII translation */ 255f8307e12SArchie Cobbs if (strchr(path, ':') == NULL) 256f8307e12SArchie Cobbs goto fail2; 257f8307e12SArchie Cobbs 258f8307e12SArchie Cobbs /* Get a temporary socket */ 259f8307e12SArchie Cobbs if (NgMkSockNode(NULL, &csock, NULL) < 0) 260f8307e12SArchie Cobbs goto fail; 261f8307e12SArchie Cobbs 262f8307e12SArchie Cobbs /* Copy binary message into request message payload */ 263f8307e12SArchie Cobbs arglen = msg->header.arglen; 264f8307e12SArchie Cobbs if (arglen > ARGS_BUFSIZE) 265f8307e12SArchie Cobbs arglen = ARGS_BUFSIZE; 266f8307e12SArchie Cobbs memcpy(bin, msg, sizeof(*msg) + arglen); 267f8307e12SArchie Cobbs bin->header.arglen = arglen; 268f8307e12SArchie Cobbs 2691816e452SArchie Cobbs /* Lower debugging to avoid infinite recursion */ 2701816e452SArchie Cobbs _gNgDebugLevel -= RECURSIVE_DEBUG_ADJUST; 2711816e452SArchie Cobbs 272f8307e12SArchie Cobbs /* Ask the node to translate the binary message to ASCII for us */ 273f8307e12SArchie Cobbs if (NgSendMsg(csock, path, NGM_GENERIC_COOKIE, 2741816e452SArchie Cobbs NGM_BINARY2ASCII, bin, sizeof(*bin) + bin->header.arglen) < 0) { 2751816e452SArchie Cobbs _gNgDebugLevel += RECURSIVE_DEBUG_ADJUST; 276f8307e12SArchie Cobbs goto fail; 2771816e452SArchie Cobbs } 2781816e452SArchie Cobbs if (NgRecvMsg(csock, req, sizeof(buf), NULL) < 0) { 2791816e452SArchie Cobbs _gNgDebugLevel += RECURSIVE_DEBUG_ADJUST; 280f8307e12SArchie Cobbs goto fail; 2811816e452SArchie Cobbs } 2821816e452SArchie Cobbs 2831816e452SArchie Cobbs /* Restore debugging level */ 2841816e452SArchie Cobbs _gNgDebugLevel += RECURSIVE_DEBUG_ADJUST; 285f8307e12SArchie Cobbs 286f8307e12SArchie Cobbs /* Display command string and arguments */ 287f8307e12SArchie Cobbs NGLOGX(" cmd %s (%d)", bin->header.cmdstr, bin->header.cmd); 288f8307e12SArchie Cobbs NGLOGX(" args %s", bin->data); 289f8307e12SArchie Cobbs goto done; 290f8307e12SArchie Cobbs 291f8307e12SArchie Cobbs fail: 292f8307e12SArchie Cobbs /* Just display binary version */ 293f8307e12SArchie Cobbs NGLOGX(" [error decoding message: %s]", strerror(errno)); 294f8307e12SArchie Cobbs fail2: 295f8307e12SArchie Cobbs NGLOGX(" cmd %d", msg->header.cmd); 296f8307e12SArchie Cobbs NGLOGX(" args (%d bytes)", msg->header.arglen); 297b9236794SMaxime Henrion _NgDebugBytes((u_char *)msg->data, msg->header.arglen); 298f8307e12SArchie Cobbs 299f8307e12SArchie Cobbs done: 300f8307e12SArchie Cobbs if (csock != -1) 301f8307e12SArchie Cobbs (void)close(csock); 3024cf49a43SJulian Elischer } 3034cf49a43SJulian Elischer 3044cf49a43SJulian Elischer /* 3054cf49a43SJulian Elischer * Return the name of the node type corresponding to the cookie 3064cf49a43SJulian Elischer */ 3074cf49a43SJulian Elischer static const char * 3084cf49a43SJulian Elischer NgCookie(int cookie) 3094cf49a43SJulian Elischer { 310f8307e12SArchie Cobbs int k; 3114cf49a43SJulian Elischer 312f8307e12SArchie Cobbs for (k = 0; cookies[k].cookie != 0; k++) { 313f8307e12SArchie Cobbs if (cookies[k].cookie == cookie) 314f8307e12SArchie Cobbs return cookies[k].type; 3154cf49a43SJulian Elischer } 316f8307e12SArchie Cobbs return "??"; 3174cf49a43SJulian Elischer } 3184cf49a43SJulian Elischer 3194cf49a43SJulian Elischer /* 3204cf49a43SJulian Elischer * Dump bytes in hex 3214cf49a43SJulian Elischer */ 3224cf49a43SJulian Elischer void 3234cf49a43SJulian Elischer _NgDebugBytes(const u_char *ptr, int len) 3244cf49a43SJulian Elischer { 3254cf49a43SJulian Elischer char buf[100]; 3264cf49a43SJulian Elischer int k, count; 3274cf49a43SJulian Elischer 3284cf49a43SJulian Elischer #define BYPERLINE 16 3294cf49a43SJulian Elischer 3304cf49a43SJulian Elischer for (count = 0; count < len; ptr += BYPERLINE, count += BYPERLINE) { 3314cf49a43SJulian Elischer 3324cf49a43SJulian Elischer /* Do hex */ 3334cf49a43SJulian Elischer snprintf(buf, sizeof(buf), "%04x: ", count); 3344cf49a43SJulian Elischer for (k = 0; k < BYPERLINE; k++, count++) 3354cf49a43SJulian Elischer if (count < len) 3364cf49a43SJulian Elischer snprintf(buf + strlen(buf), 3374cf49a43SJulian Elischer sizeof(buf) - strlen(buf), "%02x ", ptr[k]); 3384cf49a43SJulian Elischer else 3394cf49a43SJulian Elischer snprintf(buf + strlen(buf), 3404cf49a43SJulian Elischer sizeof(buf) - strlen(buf), " "); 3414cf49a43SJulian Elischer snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " "); 3424cf49a43SJulian Elischer count -= BYPERLINE; 3434cf49a43SJulian Elischer 3444cf49a43SJulian Elischer /* Do ASCII */ 3454cf49a43SJulian Elischer for (k = 0; k < BYPERLINE; k++, count++) 3464cf49a43SJulian Elischer if (count < len) 3474cf49a43SJulian Elischer snprintf(buf + strlen(buf), 3484cf49a43SJulian Elischer sizeof(buf) - strlen(buf), 3494cf49a43SJulian Elischer "%c", isprint(ptr[k]) ? ptr[k] : '.'); 3504cf49a43SJulian Elischer else 3514cf49a43SJulian Elischer snprintf(buf + strlen(buf), 3524cf49a43SJulian Elischer sizeof(buf) - strlen(buf), " "); 3534cf49a43SJulian Elischer count -= BYPERLINE; 3544cf49a43SJulian Elischer 3554cf49a43SJulian Elischer /* Print it */ 3564cf49a43SJulian Elischer NGLOGX("%s", buf); 3574cf49a43SJulian Elischer } 3584cf49a43SJulian Elischer } 3594cf49a43SJulian Elischer 360