f-stack/tools/libnetgraph/debug.c

360 lines
9.2 KiB
C

/*
* debug.c
*
* Copyright (c) 1996-1999 Whistle Communications, Inc.
* All rights reserved.
*
* Subject to the following obligations and disclaimer of warranty, use and
* redistribution of this software, in source or object code forms, with or
* without modifications are expressly permitted by Whistle Communications;
* provided, however, that:
* 1. Any and all reproductions of the source or object code must include the
* copyright notice above and the following disclaimer of warranties; and
* 2. No rights are granted, in any manner or form, to use Whistle
* Communications, Inc. trademarks, including the mark "WHISTLE
* COMMUNICATIONS" on advertising, endorsements, or otherwise except as
* such appears in the above copyright notice or in the software.
*
* THIS SOFTWARE IS BEING PROVIDED BY WHISTLE COMMUNICATIONS "AS IS", AND
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, WHISTLE COMMUNICATIONS MAKES NO
* REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING THIS SOFTWARE,
* INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
* WHISTLE COMMUNICATIONS DOES NOT WARRANT, GUARANTEE, OR MAKE ANY
* REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS OF THE USE OF THIS
* SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY, RELIABILITY OR OTHERWISE.
* IN NO EVENT SHALL WHISTLE COMMUNICATIONS BE LIABLE FOR ANY DAMAGES
* RESULTING FROM OR ARISING OUT OF ANY USE OF THIS SOFTWARE, INCLUDING
* WITHOUT LIMITATION, ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* PUNITIVE, OR CONSEQUENTIAL DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES, LOSS OF USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF WHISTLE COMMUNICATIONS IS ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* Author: Archie Cobbs <archie@whistle.com>
*
* $Whistle: debug.c,v 1.24 1999/01/24 01:15:33 archie Exp $
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/types.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#include <stdarg.h>
#include <netinet/in.h>
#include <net/ethernet.h>
#include <net/bpf.h>
#include <netgraph/ng_message.h>
#include <netgraph/ng_socket.h>
#include "netgraph.h"
#include "internal.h"
#include <netgraph/ng_UI.h>
#include <netgraph/ng_async.h>
#include <netgraph/ng_atmllc.h>
#include <netgraph/ng_bpf.h>
#include <netgraph/ng_bridge.h>
#include <netgraph/ng_car.h>
#include <netgraph/ng_cisco.h>
#include <netgraph/ng_deflate.h>
#include <netgraph/ng_device.h>
#include <netgraph/ng_echo.h>
#include <netgraph/ng_eiface.h>
#include <netgraph/ng_etf.h>
#include <netgraph/ng_ether.h>
#include <netgraph/ng_ether_echo.h>
#include <netgraph/ng_frame_relay.h>
#include <netgraph/ng_gif.h>
#include <netgraph/ng_gif_demux.h>
#include <netgraph/ng_hole.h>
#include <netgraph/ng_hub.h>
#include <netgraph/ng_iface.h>
#include <netgraph/ng_ip_input.h>
#include <netgraph/ng_ipfw.h>
#include <netgraph/ng_ksocket.h>
#include <netgraph/ng_l2tp.h>
#include <netgraph/ng_lmi.h>
#include <netgraph/ng_mppc.h>
#include <netgraph/ng_nat.h>
#include <netgraph/netflow/ng_netflow.h>
#include <netgraph/ng_one2many.h>
#include <netgraph/ng_patch.h>
#include <netgraph/ng_pipe.h>
#include <netgraph/ng_ppp.h>
#include <netgraph/ng_pppoe.h>
#include <netgraph/ng_pptpgre.h>
#include <netgraph/ng_pred1.h>
#include <netgraph/ng_rfc1490.h>
#include <netgraph/ng_socket.h>
#include <netgraph/ng_source.h>
#include <netgraph/ng_split.h>
#include <netgraph/ng_sppp.h>
#include <netgraph/ng_tag.h>
#include <netgraph/ng_tcpmss.h>
#include <netgraph/ng_tee.h>
#include <netgraph/ng_tty.h>
#include <netgraph/ng_vjc.h>
#include <netgraph/ng_vlan.h>
#ifdef WHISTLE
#include <machine/../isa/df_def.h>
#include <machine/../isa/if_wfra.h>
#include <machine/../isa/ipac.h>
#include <netgraph/ng_df.h>
#include <netgraph/ng_ipac.h>
#include <netgraph/ng_tn.h>
#endif
/* Global debug level */
int _gNgDebugLevel = 0;
/* Debug printing functions */
void (*_NgLog) (const char *fmt,...) = warn;
void (*_NgLogx) (const char *fmt,...) = warnx;
/* Internal functions */
static const char *NgCookie(int cookie);
/* Known typecookie list */
struct ng_cookie {
int cookie;
const char *type;
};
#define COOKIE(c) { NGM_ ## c ## _COOKIE, #c }
/* List of known cookies */
static const struct ng_cookie cookies[] = {
COOKIE(UI),
COOKIE(ASYNC),
COOKIE(ATMLLC),
COOKIE(BPF),
COOKIE(BRIDGE),
COOKIE(CAR),
COOKIE(CISCO),
COOKIE(DEFLATE),
COOKIE(DEVICE),
COOKIE(ECHO),
COOKIE(EIFACE),
COOKIE(ETF),
COOKIE(ETHER),
COOKIE(ETHER_ECHO),
COOKIE(FRAMERELAY),
COOKIE(GIF),
COOKIE(GIF_DEMUX),
COOKIE(GENERIC),
COOKIE(HOLE),
COOKIE(HUB),
COOKIE(IFACE),
COOKIE(IP_INPUT),
COOKIE(IPFW),
COOKIE(KSOCKET),
COOKIE(L2TP),
COOKIE(LMI),
COOKIE(MPPC),
COOKIE(NAT),
COOKIE(NETFLOW),
COOKIE(ONE2MANY),
COOKIE(PATCH),
COOKIE(PIPE),
COOKIE(PPP),
COOKIE(PPPOE),
COOKIE(PPTPGRE),
COOKIE(PRED1),
COOKIE(RFC1490),
COOKIE(SOCKET),
COOKIE(SOURCE),
COOKIE(SPLIT),
COOKIE(SPPP),
COOKIE(TAG),
COOKIE(TCPMSS),
COOKIE(TEE),
COOKIE(TTY),
COOKIE(VJC),
COOKIE(VLAN),
#ifdef WHISTLE
COOKIE(DF),
COOKIE(IPAC),
COOKIE(TN),
COOKIE(WFRA),
#endif
{ 0, NULL }
};
/*
* Set debug level, ie, verbosity, if "level" is non-negative.
* Returns old debug level.
*/
int
NgSetDebug(int level)
{
int old = _gNgDebugLevel;
if (level >= 0)
_gNgDebugLevel = level;
return (old);
}
/*
* Set debug logging functions.
*/
void
NgSetErrLog(void (*log) (const char *fmt,...),
void (*logx) (const char *fmt,...))
{
_NgLog = log;
_NgLogx = logx;
}
/*
* Display a netgraph sockaddr
*/
void
_NgDebugSockaddr(const struct sockaddr_ng *sg)
{
NGLOGX("SOCKADDR: { fam=%d len=%d addr=\"%s\" }",
sg->sg_family, sg->sg_len, sg->sg_data);
}
#define ARGS_BUFSIZE 2048
#define RECURSIVE_DEBUG_ADJUST 4
/*
* Display a negraph message
*/
void
_NgDebugMsg(const struct ng_mesg *msg, const char *path)
{
u_char buf[2 * sizeof(struct ng_mesg) + ARGS_BUFSIZE];
struct ng_mesg *const req = (struct ng_mesg *)buf;
struct ng_mesg *const bin = (struct ng_mesg *)req->data;
int arglen, csock = -1;
/* Display header stuff */
NGLOGX("NG_MESG :");
NGLOGX(" vers %d", msg->header.version);
NGLOGX(" arglen %u", msg->header.arglen);
NGLOGX(" flags %x", msg->header.flags);
NGLOGX(" token %u", msg->header.token);
NGLOGX(" cookie %s (%u)",
NgCookie(msg->header.typecookie), msg->header.typecookie);
/* At lower debugging levels, skip ASCII translation */
if (_gNgDebugLevel <= 2)
goto fail2;
/* If path is not absolute, don't bother trying to use relative
address on a different socket for the ASCII translation */
if (strchr(path, ':') == NULL)
goto fail2;
/* Get a temporary socket */
if (NgMkSockNode(NULL, &csock, NULL) < 0)
goto fail;
/* Copy binary message into request message payload */
arglen = msg->header.arglen;
if (arglen > ARGS_BUFSIZE)
arglen = ARGS_BUFSIZE;
memcpy(bin, msg, sizeof(*msg) + arglen);
bin->header.arglen = arglen;
/* Lower debugging to avoid infinite recursion */
_gNgDebugLevel -= RECURSIVE_DEBUG_ADJUST;
/* Ask the node to translate the binary message to ASCII for us */
if (NgSendMsg(csock, path, NGM_GENERIC_COOKIE,
NGM_BINARY2ASCII, bin, sizeof(*bin) + bin->header.arglen) < 0) {
_gNgDebugLevel += RECURSIVE_DEBUG_ADJUST;
goto fail;
}
if (NgRecvMsg(csock, req, sizeof(buf), NULL) < 0) {
_gNgDebugLevel += RECURSIVE_DEBUG_ADJUST;
goto fail;
}
/* Restore debugging level */
_gNgDebugLevel += RECURSIVE_DEBUG_ADJUST;
/* Display command string and arguments */
NGLOGX(" cmd %s (%d)", bin->header.cmdstr, bin->header.cmd);
NGLOGX(" args %s", bin->data);
goto done;
fail:
/* Just display binary version */
NGLOGX(" [error decoding message: %s]", strerror(errno));
fail2:
NGLOGX(" cmd %d", msg->header.cmd);
NGLOGX(" args (%d bytes)", msg->header.arglen);
_NgDebugBytes((u_char *)msg->data, msg->header.arglen);
done:
if (csock != -1)
(void)close(csock);
}
/*
* Return the name of the node type corresponding to the cookie
*/
static const char *
NgCookie(int cookie)
{
int k;
for (k = 0; cookies[k].cookie != 0; k++) {
if (cookies[k].cookie == cookie)
return cookies[k].type;
}
return "??";
}
/*
* Dump bytes in hex
*/
void
_NgDebugBytes(const u_char *ptr, int len)
{
char buf[100];
int k, count;
#define BYPERLINE 16
for (count = 0; count < len; ptr += BYPERLINE, count += BYPERLINE) {
/* Do hex */
snprintf(buf, sizeof(buf), "%04x: ", count);
for (k = 0; k < BYPERLINE; k++, count++)
if (count < len)
snprintf(buf + strlen(buf),
sizeof(buf) - strlen(buf), "%02x ", ptr[k]);
else
snprintf(buf + strlen(buf),
sizeof(buf) - strlen(buf), " ");
snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " ");
count -= BYPERLINE;
/* Do ASCII */
for (k = 0; k < BYPERLINE; k++, count++)
if (count < len)
snprintf(buf + strlen(buf),
sizeof(buf) - strlen(buf),
"%c", isprint(ptr[k]) ? ptr[k] : '.');
else
snprintf(buf + strlen(buf),
sizeof(buf) - strlen(buf), " ");
count -= BYPERLINE;
/* Print it */
NGLOGX("%s", buf);
}
}