482 lines
12 KiB
C
482 lines
12 KiB
C
/*****************************************************************************
|
|
* sdladump.c WANPIPE(tm) Adapter Memeory Dump Utility.
|
|
*
|
|
* Author: Gene Kozin <genek@compuserve.com>
|
|
*
|
|
* Copyright: (c) 1995-1996 Sangoma Technologies Inc.
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version
|
|
* 2 of the License, or (at your option) any later version.
|
|
* ----------------------------------------------------------------------------
|
|
* Nov 29, 1996 Gene Kozin Initial version based on WANPIPE configurator.
|
|
*****************************************************************************/
|
|
|
|
/*****************************************************************************
|
|
* Usage:
|
|
* sdladump [{switches}] {device} [{offset} [{length}]]
|
|
*
|
|
* Where:
|
|
* {device} WANPIPE device name in /proc/net/wanrouter directory
|
|
* {offset} address of adapter's on-board memory. Default is 0.
|
|
* {length} size of memory to dump. Default is 0x100 (256 bytes).
|
|
* {switches} one of the following:
|
|
* -v verbose mode
|
|
* -h | -? show help
|
|
*****************************************************************************/
|
|
|
|
#include <stddef.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <ctype.h>
|
|
#include <errno.h>
|
|
#include <stdio.h>
|
|
#include <fcntl.h>
|
|
#include <time.h>
|
|
#include <sys/stat.h>
|
|
#include <sys/ioctl.h>
|
|
#include <sys/types.h>
|
|
#if defined(CONFIG_PRODUCT_WANPIPE_GENERIC)
|
|
# include <sys/socket.h>
|
|
# include <netinet/in.h>
|
|
# if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__)
|
|
# include <net/if.h>
|
|
# else
|
|
# include <linux/if.h>
|
|
# include <linux/if_wanpipe.h>
|
|
# endif
|
|
#endif
|
|
|
|
#if defined(__LINUX__)
|
|
# include <linux/wanpipe_defines.h>
|
|
# include <linux/wanpipe_cfg.h>
|
|
# include <linux/wanpipe.h> /* WANPIPE user API definitions */
|
|
#else
|
|
# include <wanpipe_defines.h>
|
|
# include <wanpipe_cfg.h>
|
|
# include <wanpipe.h> /* WANPIPE user API definitions */
|
|
#endif
|
|
|
|
/****** Defines *************************************************************/
|
|
|
|
#ifndef min
|
|
#define min(a,b) (((a)<(b))?(a):(b))
|
|
#endif
|
|
|
|
/* Error exit codes */
|
|
enum ErrCodes
|
|
{
|
|
ERR_SYSTEM = 1, /* System error */
|
|
ERR_SYNTAX, /* Command line syntax error */
|
|
ERR_LIMIT
|
|
};
|
|
|
|
/* Command line parsing stuff */
|
|
#define ARG_SWITCH '-' /* switch follows */
|
|
#define SWITCH_GETHELP 'h' /* show help screen */
|
|
#define SWITCH_ALTHELP '?' /* same */
|
|
#define SWITCH_VERBOSE 'v' /* enable verbose output */
|
|
#define SWITCH_DEBUG 'd' /* read debug messages */
|
|
|
|
/* Defaults */
|
|
#define DEFAULT_OFFSET 0
|
|
#define DEFAULT_LENGTH 0x100
|
|
|
|
/* FreeBSD/OpenBSD */
|
|
#define WANDEV_NAME "/dev/wanrouter"
|
|
|
|
/****** Data Types **********************************************************/
|
|
|
|
/****** Function Prototypes *************************************************/
|
|
|
|
int arg_proc (int argc, char* argv[]);
|
|
int do_dump (int argc, char* argv[]);
|
|
int do_debug(int argc, char *argv[]);
|
|
void show_dump (char* buf, unsigned long len, unsigned long addr);
|
|
void show_error (int err);
|
|
int hexdump (char* str, int, char* data, int length, int limit);
|
|
|
|
extern int close (int);
|
|
|
|
/****** Global Data *********************************************************/
|
|
|
|
/*
|
|
* Strings & message tables.
|
|
*/
|
|
char progname[] = "sdladump";
|
|
char wandev_dir[] = "/proc/net/wanrouter"; /* location of WAN devices */
|
|
#if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__)
|
|
wan_conf_t config;
|
|
#endif
|
|
|
|
char banner[] =
|
|
"WANPIPE Memory Dump Utility. v3.0.0 "
|
|
"(c) 1995-1996 Sangoma Technologies Inc."
|
|
;
|
|
char helptext[] =
|
|
"\n"
|
|
"sdladump: Wanpipe Memory Dump Utility\n\n"
|
|
#if defined(CONFIG_PRODUCT_WANPIPE_GENERIC)
|
|
"Usage:\tsdladump [{switches}] {ifname} [{offset} [{length}]]\n"
|
|
#else
|
|
"Usage:\tsdladump [{switches}] {device} [{offset} [{length}]]\n"
|
|
#endif
|
|
"\nWhere:"
|
|
#if defined(CONFIG_PRODUCT_WANPIPE_GENERIC)
|
|
"\t{ifname}\tWANPIPE (LITE) interface name (hdlcN, where N=0,1..)\n"
|
|
#else
|
|
"\t{device}\tWANPIPE device name from /proc/net/wanrouter directory\n"
|
|
#endif
|
|
"\t{offset}\taddress of adapter's on-board memory (default is 0)\n"
|
|
"\t{length}\tsize of memory to dump (default is 256 bytes)\n"
|
|
"\t{switches}\tone of the following:\n"
|
|
"\t\t\t-v\tverbose mode\n"
|
|
"\t\t\t-h|?\tshow this help\n"
|
|
;
|
|
|
|
char* err_messages[] = /* Error messages */
|
|
{
|
|
"Invalid command line syntax", /* ERR_SYNTAX */
|
|
"Unknown error code", /* ERR_LIMIT */
|
|
};
|
|
|
|
enum /* execution modes */
|
|
{
|
|
DO_DUMP,
|
|
DO_DEBUG,
|
|
DO_HELP
|
|
} action;
|
|
int verbose; /* verbosity level */
|
|
|
|
/****** Entry Point *********************************************************/
|
|
|
|
int main (int argc, char *argv[])
|
|
{
|
|
int err = 0; /* return code */
|
|
int skip;
|
|
|
|
/* Process command line switches */
|
|
for (skip = 0, --argc, ++argv;
|
|
argc && (**argv == ARG_SWITCH);
|
|
argc -= skip, argv += skip)
|
|
{
|
|
skip = arg_proc(argc, argv);
|
|
if (skip == 0)
|
|
{
|
|
err = ERR_SYNTAX;
|
|
show_error(err);
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* Perform requested action */
|
|
if (verbose) puts(banner);
|
|
if (!err) switch (action)
|
|
{
|
|
case DO_DUMP:
|
|
err = do_dump(argc, argv);
|
|
break;
|
|
|
|
case DO_DEBUG:
|
|
err = do_debug(argc, argv);
|
|
break;
|
|
|
|
default:
|
|
err = ERR_SYNTAX;
|
|
}
|
|
if (err == ERR_SYNTAX) puts(helptext);
|
|
return err;
|
|
}
|
|
|
|
/*============================================================================
|
|
* Process command line.
|
|
* Return number of successfully processed arguments, or 0 in case of
|
|
* syntax error.
|
|
*/
|
|
int arg_proc (int argc, char *argv[])
|
|
{
|
|
int cnt = 0;
|
|
|
|
switch (argv[0][1])
|
|
{
|
|
case SWITCH_GETHELP:
|
|
case SWITCH_ALTHELP:
|
|
action = DO_HELP;
|
|
cnt = 1;
|
|
break;
|
|
|
|
case SWITCH_DEBUG:
|
|
action = DO_DEBUG;
|
|
cnt = 1;
|
|
break;
|
|
|
|
case SWITCH_VERBOSE:
|
|
verbose = 1;
|
|
cnt = 1;
|
|
break;
|
|
}
|
|
return cnt;
|
|
}
|
|
|
|
/*============================================================================
|
|
* Dump adapter memory.
|
|
* argv[0]: device name
|
|
* argv[1]: offset
|
|
* argv[2]: length
|
|
*/
|
|
int do_dump (int argc, char *argv[])
|
|
{
|
|
int err = 0;
|
|
int dev;
|
|
#if defined(CONFIG_PRODUCT_WANPIPE_GENERIC)
|
|
struct ifreq req;
|
|
#else
|
|
int max_flen = sizeof(wandev_dir) + WAN_DRVNAME_SZ;
|
|
char filename[max_flen + 2];
|
|
#endif
|
|
sdla_dump_t dump;
|
|
|
|
if (!argc || (strlen(argv[0]) > WAN_DRVNAME_SZ))
|
|
{
|
|
show_error(ERR_SYNTAX);
|
|
return ERR_SYNTAX;
|
|
}
|
|
|
|
dump.magic = WANPIPE_MAGIC;
|
|
dump.offset = (argc > 1) ? strtoul(argv[1], NULL, 0) : DEFAULT_OFFSET;
|
|
dump.length = (argc > 2) ? strtoul(argv[2], NULL, 0) : DEFAULT_LENGTH;
|
|
if (!dump.length)
|
|
{
|
|
show_error(ERR_SYNTAX);
|
|
return ERR_SYNTAX;
|
|
}
|
|
|
|
if (verbose) printf(
|
|
"Dumping %lu bytes from offset %lu from device %s ...\n",
|
|
dump.length, dump.offset, argv[0])
|
|
;
|
|
|
|
dump.ptr = malloc(dump.length);
|
|
if (dump.ptr == NULL)
|
|
{
|
|
show_error(ERR_SYSTEM);
|
|
return ERR_SYSTEM;
|
|
}
|
|
|
|
#if defined(CONFIG_PRODUCT_WANPIPE_GENERIC)
|
|
if ((dev = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP)) < 0){
|
|
err = ERR_SYSTEM;
|
|
show_error(err);
|
|
goto do_dump_done;
|
|
}
|
|
strcpy(req.ifr_name, argv[0]);
|
|
req.ifr_data = (void*)&dump;
|
|
err = ioctl(dev, SIOC_WANPIPE_DUMP, &req);
|
|
#else
|
|
# if defined(__LINUX__)
|
|
snprintf(filename, max_flen, "%s/%s", wandev_dir, argv[0]);
|
|
# else
|
|
snprintf(filename, max_flen, "%s", WANDEV_NAME);
|
|
# endif
|
|
if ((dev = open(filename, O_RDONLY)) < 0){
|
|
err = ERR_SYSTEM;
|
|
show_error(err);
|
|
goto do_dump_done;
|
|
}
|
|
# if defined(__LINUX__)
|
|
err = ioctl(dev, WANPIPE_DUMP, &dump);
|
|
# else
|
|
strlcpy(config.devname, argv[0], WAN_DRVNAME_SZ);
|
|
config.arg = &dump;
|
|
err = ioctl(dev, WANPIPE_DUMP, &config);
|
|
# endif
|
|
#endif
|
|
if (err < 0){
|
|
err = ERR_SYSTEM;
|
|
show_error(err);
|
|
}
|
|
else show_dump(dump.ptr, dump.length, dump.offset);
|
|
do_dump_done:
|
|
if (dev >= 0) close(dev);
|
|
free(dump.ptr);
|
|
return err;
|
|
}
|
|
|
|
/*============================================================================
|
|
* Print hex memory dump to standard output.
|
|
* argv[0]: device name
|
|
* argv[1]: offset
|
|
* argv[2]: length
|
|
*/
|
|
void show_dump (char* buf, unsigned long len, unsigned long addr)
|
|
{
|
|
char str[80];
|
|
int cnt;
|
|
|
|
memset(str, 0, 80);
|
|
if (len > 16)
|
|
{
|
|
/* see if ajustment is needed and adjust to 16-byte
|
|
* boundary, if necessary.
|
|
*/
|
|
cnt = 16 - addr % 16;
|
|
if (cnt)
|
|
{
|
|
printf("%05lX: ", addr);
|
|
hexdump(str, 80, buf, cnt, 16);
|
|
puts(str);
|
|
}
|
|
}
|
|
else cnt = 0;
|
|
|
|
while (cnt < len)
|
|
{
|
|
memset(str, 0, 80);
|
|
printf("%05lX: ", addr + cnt);
|
|
cnt += hexdump(str, 80, &buf[cnt], min(16, len - cnt), 16);
|
|
puts(str);
|
|
}
|
|
}
|
|
|
|
/*============================================================================
|
|
* Dump data into a string in the following format:
|
|
* XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX AAAAAAAAAAAAAAAA
|
|
*
|
|
* Return number of bytes dumped.
|
|
* NOTE: string buffer must be at least (limit * 4 + 2) bytes long.
|
|
*/
|
|
int hexdump (char* str, int max_len, char* data, int length, int limit)
|
|
{
|
|
int i, n, off = 0;
|
|
|
|
n = min(limit, length);
|
|
if (n)
|
|
{
|
|
for (i = 0; i < n; ++i){
|
|
off += snprintf(&str[off], max_len-off, "%02X ", data[i]);
|
|
}
|
|
for (i = 0; i < limit - n; ++i){
|
|
off += snprintf(&str[off], max_len-off, " ");
|
|
}
|
|
off += snprintf(&str[off], max_len-off, " ");
|
|
for (i = 0; i < n; ++i){
|
|
off += snprintf(&str[off], max_len-off,
|
|
"%c", (isprint(data[i])) ? data[i] : '.');
|
|
}
|
|
for (i = 0; i < limit - n; ++i){
|
|
off += snprintf(&str[off], max_len-off, " ");
|
|
}
|
|
}
|
|
*str = '\0';
|
|
return n;
|
|
}
|
|
|
|
|
|
/*============================================================================
|
|
* Get debuggin messages.
|
|
*/
|
|
int do_debug(int argc, char *argv[])
|
|
{
|
|
int dev;
|
|
wan_kernel_msg_t wan_debug;
|
|
wanpipe_kernel_msg_hdr_t* dbg_msg;
|
|
struct tm* time_tm;
|
|
char buf[200], tmp_time[50];
|
|
int offset = 0, len = 0, is_more = 1,
|
|
max_flen = sizeof(wandev_dir) + WAN_DRVNAME_SZ;
|
|
char filename[max_flen + 2];
|
|
|
|
if (!argc || (strlen(argv[0]) > WAN_DRVNAME_SZ))
|
|
{
|
|
show_error(ERR_SYNTAX);
|
|
return ERR_SYNTAX;
|
|
}
|
|
|
|
#if defined(__LINUX__)
|
|
snprintf(filename, max_flen, "%s/%s", wandev_dir, argv[0]);
|
|
#else
|
|
snprintf(filename, max_flen, "%s", WANDEV_NAME);
|
|
#endif
|
|
|
|
dev = open(filename, O_RDONLY);
|
|
if (dev == -1){
|
|
fprintf(stderr, "\n\n\tFAILED open device %s!\n",
|
|
filename);
|
|
show_error(ERR_SYSTEM);
|
|
return ERR_SYNTAX;
|
|
}
|
|
/* Clear configuration structure */
|
|
is_more = 1;
|
|
while(is_more){
|
|
wan_debug.magic = ROUTER_MAGIC;
|
|
wan_debug.len = 0;
|
|
wan_debug.is_more = 0;
|
|
wan_debug.max_len = 1024;
|
|
wan_debug.data = malloc(1024);
|
|
if (wan_debug.data == NULL){
|
|
show_error(ERR_SYSTEM);
|
|
if (dev >= 0) close(dev);
|
|
return ERR_SYSTEM;
|
|
}
|
|
|
|
#if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__)
|
|
strlcpy(config.devname, argv[0], WAN_DRVNAME_SZ);
|
|
config.arg = &wan_debug;
|
|
if (ioctl(dev, ROUTER_DEBUG_READ, &config) < 0){
|
|
#else
|
|
if (ioctl(dev, ROUTER_DEBUG_READ, &wan_debug)){
|
|
#endif
|
|
fprintf(stderr, "\n\n\tROUTER DEBUG READ failed!!\n");
|
|
show_error(ERR_SYSTEM);
|
|
if (dev >= 0) close(dev);
|
|
return ERR_SYSTEM;
|
|
}
|
|
is_more = wan_debug.is_more;
|
|
len = wan_debug.len;
|
|
offset = 0;
|
|
while(offset < len){
|
|
dbg_msg = (wanpipe_kernel_msg_hdr_t*)&wan_debug.data[offset];
|
|
offset += sizeof(wanpipe_kernel_msg_hdr_t);
|
|
if (dbg_msg->len == 0) continue;
|
|
memcpy(buf, &wan_debug.data[offset], dbg_msg->len);
|
|
offset += dbg_msg->len;
|
|
buf[dbg_msg->len] = '\0';
|
|
time_tm = localtime((time_t*)&dbg_msg->time);
|
|
strftime(tmp_time, sizeof(tmp_time),"%a",time_tm);
|
|
printf("%s ",tmp_time);
|
|
strftime(tmp_time, sizeof(tmp_time),"%b",time_tm);
|
|
printf("%s ",tmp_time);
|
|
strftime(tmp_time, sizeof(tmp_time),"%d",time_tm);
|
|
printf("%s ",tmp_time);
|
|
strftime(tmp_time, sizeof(tmp_time),"%H",time_tm);
|
|
printf("%s:",tmp_time);
|
|
strftime(tmp_time, sizeof(tmp_time),"%M",time_tm);
|
|
printf("%s:",tmp_time);
|
|
strftime(tmp_time, sizeof(tmp_time),"%S",time_tm);
|
|
printf("%s ",tmp_time);
|
|
printf("%s", buf);
|
|
}
|
|
}
|
|
if (dev >= 0){
|
|
close(dev);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
/*============================================================================
|
|
* Show error message.
|
|
*/
|
|
void show_error (int err)
|
|
{
|
|
if (err == ERR_SYSTEM) fprintf(stderr, "%s: SYSTEM ERROR %d: %s!\n",
|
|
progname, errno, strerror(errno))
|
|
;
|
|
else fprintf(stderr, "%s: %s!\n", progname,
|
|
err_messages[min(err, ERR_LIMIT) - 2])
|
|
;
|
|
}
|
|
/****** End *****************************************************************/
|