📄 pcdbug.c
字号:
/*
* WatTCP protocol debugger. Writes to `debug.file' specified in
* config-file. File may be stdout/stderr/nul.
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <ctype.h>
#include <io.h>
#ifdef __DJGPP__
#include <unistd.h>
#endif
#include "wattcp.h"
#include "strings.h"
#include "udp_dom.h"
#include "misc.h"
#include "sock_ini.h"
#include "chksum.h"
#include "pctcp.h"
#include "pcbsd.h"
#include "pcsed.h"
#include "pcarp.h"
#include "pcqueue.h"
#include "pcpkt.h"
#include "pcstat.h"
#include "pcconfig.h"
#include "pcicmp.h"
#include "pppoe.h"
#include "pcdbug.h"
#define DEBUG_DNS 1 /* 1 = include detailed DNS debugging */
#define DEBUG_RTP 1 /* 1 = include detailed RTP debugging, to-do */
/*
* tcpState[] is also used in sock_dbu.c/sock_dat.c
*/
const char *tcpState[] = {
"LISTEN", "SYNSENT", "SYNREC", "ESTAB",
"ESTCLOSE", "FINWT1", "FINWT2", "CLOSWT",
"CLOSING", "LASTACK", "TIMEWT", "CLOSED"
};
#if defined(USE_DEBUG)
#if (DEBUG_DNS)
#include <arpa/nameser.h>
#include <resolv.h>
#endif
/*@-observertrans@*/
/*
* We don't use language translation in printouts (only in the ourinit()
* routine). That would make debug-dumps / problem-reports difficult.
*/
#ifdef __HIGHC__ /* disable stack-checking here */
#pragma Off (check_stack)
#pragma stack_size_warn (220000)
#endif
#ifdef __WATCOMC__
#pragma Off (check_stack)
#endif
#ifdef __TURBOC__
#ifndef OLD_TURBOC
#pragma option -N-
#endif
extern unsigned _stklen = 20000;
#endif
#if (DOSX) && defined(USE_FRAGMENTS)
#define STK_BUF_SIZE 200000
#else
#define STK_BUF_SIZE 8500
#endif
#ifndef STDOUT_FILENO
#define STDOUT_FILENO 1
#endif
static int db_fprintf (const char *format, ...)
#ifdef __GNUC__
__attribute__((format(printf,1,2)))
#endif
;
static int db_write (const char *buf);
static void db_putc (int ch);
static void db_flush (void);
static void DumpData (const BYTE *data, unsigned datalen);
static void DumpOptions (int is_ip, const BYTE *opt, int len);
#if (DEBUG_DNS)
static void dns_dump (const BYTE *, unsigned);
static BYTE *dns_resource(BYTE *, BYTE *, BYTE *);
static BYTE *dns_labels (BYTE *, BYTE *, BYTE *);
#endif
static void (*prev_hook) (const char*, const char*) = NULL;
static char debugName [128] = "WATTCP.DBG";
static char ip_src [20];
static char ip_dst [20];
static int handle = -1;
static DWORD now; /* ticks or milli-sec */
static int outbound; /* transmitting packet? */
static int is_frag; /* is this a fragment? */
static int first_frag; /* is this 1st fragment? */
static int last_frag; /* is this last fragment? */
static char *op; /* out-buffer pointer */
static char *op_min; /* first position for 'op' */
static char *op_max; /* last position for 'op' */
static struct {
char MAC;
char ARP;
char RARP;
char IP;
char BCAST;
} filter = { 0,0,0,0,0 };
static struct {
char MAC;
char ARP;
char RARP;
char IP;
char UDP;
char TCP;
char ICMP;
char IGMP;
} debug = { 0,1,1,1,1,1,1,1 };
/* These are public so they can be set by application if
* running without a config-file
*/
BOOL dbg_mode_all = 1;
BOOL dbg_print_stat = 1;
BOOL dbg_dns_details = DEBUG_DNS;
BOOL dbg_rtp_details = DEBUG_RTP; /* !!to-do */
/*----------------------------------------------------------------------*/
/*
* Other link-layer drivers (ppp/capi/pktdrvr32) can write to same file,
* but NOT close it.
*/
const int dbug_handle (void)
{
return (handle);
}
void dbug_open (void)
{
if (handle < 0)
{
if (!stricmp(debugName,"con"))
handle = STDOUT_FILENO;
else
{
int mode = _fmode;
_fmode = O_BINARY; /* Borland defaults to O_TEXT */
handle = creat (debugName, S_IWRITE);
_fmode = mode;
}
if (handle < 0)
{
outsnl ("ERROR: unable to open debug file!");
exit (3);
}
}
}
/*
* Return TRUE if MAC destination address of received/sent link-layer
* packet:
* - matches our link-layer address.
* - is broadcast and we don't filter broadcast.
*/
static __inline int MatchLinkDestination (const mac_address *dst)
{
if (!memcmp(dst, &_eth_addr, sizeof(_eth_addr)) ||
(!filter.BCAST && !memcmp(dst, &_eth_brdcast, sizeof(_eth_brdcast))))
return (1);
return (0);
}
/*
* Return TRUE if destination address of received/sent ARP packet:
* - matches our ether-address.
* - is broadcast and we don't filter broadcast.
*/
static __inline int MatchArpRarp (const arp_Header *arp)
{
if (!memcmp(&arp->dstEthAddr, &_eth_addr, sizeof(_eth_addr)))
return (1);
if (!filter.BCAST &&
!memcmp(&arp->dstEthAddr, &_eth_brdcast, sizeof(_eth_brdcast)))
return (1);
return (0);
}
/*
* Return TRUE if destination address of received/sent IP packet:
* - matches our IP-address.
* - is broadcast and we don't filter (directed) IP-broadcast.
*/
static __inline int MatchIpDest (const in_Header *ip)
{
DWORD destin = intel (ip->destination);
if (is_local_addr(destin) ||
(!filter.BCAST && is_ip_brdcast(ip)))
return (1);
return (0);
}
/*
* Return checksum and print "ok" or "ERROR"
*/
static __inline const char *DoCheckSum (WORD value, const void *p, int len)
{
static char buf[20];
sprintf (buf, "%04X (%s)", value,
checksum(p,len) == 0xFFFF ? "ok" : "ERROR");
return (buf);
}
/*
* Return name of some known link-layer protocols.
*/
static __inline const char *LinkProtocol (WORD type)
{
switch (intel16(type))
{
case IP_TYPE: return ("IP");
case ARP_TYPE: return ("ARP");
case RARP_TYPE: return ("RARP");
default: return ("unknown");
}
}
/*
* Return name of known IP-protocols.
*/
static __inline const char *IpProtocol (WORD prot)
{
switch (prot)
{
case UDP_PROTO: return ("UDP");
case TCP_PROTO: return ("TCP");
case ICMP_PROTO: return ("ICMP");
case IGMP_PROTO: return ("IGMP");
default: return ("unknown");
}
}
/*
* Return name for IP's "Type Of Service".
*/
static __inline const char *TypeOfService (BYTE tos)
{
static char buf[20];
buf[0] = 0;
if (tos & 0x04) strcat (buf," Rel");
if (tos & 0x08) strcat (buf," ThPut");
if (tos & 0x10) strcat (buf," LwDly");
if (buf[0] == 0)
sprintf (buf, " %d", tos);
return (buf);
}
/*
* Format time for "Round Trip Time".
*/
static __inline const char *RTT_str (DWORD delta)
{
return (delta > 0UL ? time_str(delta) : "--");
}
/*
* Return string for ARP/RARP opcodes.
*/
static __inline const char *ArpOpcode (WORD code)
{
if (code == ARP_REQUEST || code == RARP_REQUEST)
return ("Request");
if (code == ARP_REPLY || code == RARP_REPLY)
return ("Reply");
return ("? op");
}
/*
* Return hexa-decimal string for an 6 byte MAC-address.
* Use 2 buffers in round-robin.
*/
static __inline const char *MAC_addr (const void *adr)
{
static char buf[2][20];
static char idx = 0;
char *rc = buf [(int)idx];
char *a = (char*)adr;
sprintf (rc, "%02X:%02X:%02X:%02X:%02X:%02X",
a[0] & 255, a[1] & 255, a[2] & 255,
a[3] & 255, a[4] & 255, a[5] & 255);
idx ^= 1;
return (rc);
}
/*
* Print IP source/destination addresses and ports;
* "host1 (a) -> host2 (b)"
*/
static void DumpAdrPort (const char *proto,
const tcp_Socket *sock,
const in_Header *ip)
{
const tcp_Header *tcp = (const tcp_Header*) ((BYTE*)ip + in_GetHdrLen(ip));
char dst[20];
char src[20];
if (!sock)
db_fprintf ("%s: NO SOCKET : %s (%d) -> %s (%d)\n", proto,
ip_src, intel16(tcp->srcPort),
ip_dst, intel16(tcp->dstPort));
else if (outbound)
db_fprintf ("%s: %s (%d) -> %s (%d)\n", proto,
_inet_ntoa(src,my_ip_addr), sock->myport,
_inet_ntoa(dst,sock->hisaddr),sock->hisport);
else db_fprintf ("%s: %s (%d) -> %s (%d)\n", proto,
_inet_ntoa(src,sock->hisaddr),sock->hisport,
_inet_ntoa(dst,my_ip_addr), sock->myport);
}
/*----------------------------------------------------------------------*/
static int link_head_dump (const union link_Packet *pkt)
{
WORD type;
int len;
if (_pktdevclass == PD_TOKEN)
{
const struct tok_Header *tok = &pkt->tok.head;
if (filter.MAC && !outbound && !MatchLinkDestination(&tok->destination))
return (0);
db_fprintf ("TR: destin %s, AC %02X, FC %02X\r\n"
" source %s, DSAP %02X, SSAP %02X, Ctrl %02X\r\n",
MAC_addr (&tok->destination), tok->accessCtrl, tok->frameCtrl,
MAC_addr (&tok->source), tok->DSAP, tok->SSAP, tok->ctrl);
type = intel16 (tok->type);
len = db_fprintf (" type %s (%04X)", LinkProtocol(type), type);
}
else if (_pktdevclass == PD_FDDI)
{
const struct fddi_Header *fddi = &pkt->fddi.head;
if (filter.MAC && !outbound && !MatchLinkDestination(&fddi->destination))
return (0);
db_fprintf ("FDDI: destin %s, FC %02X\r\n"
" source %s, DSAP %02X, SSAP %02X, Ctrl %02X\r\n",
MAC_addr (&fddi->destination), fddi->frameCtrl,
MAC_addr (&fddi->source), fddi->DSAP, fddi->SSAP, fddi->ctrl);
type = intel16 (fddi->type);
len = db_fprintf (" type %s (%04X)", LinkProtocol(type), type);
}
else /* PD_ETHER */
{
const struct eth_Header *eth = &pkt->eth.head;
if (filter.MAC && !outbound && !MatchLinkDestination(ð->destination))
return (0);
db_fprintf ("ETH: destin %s\r\n"
" source %s\r\n",
MAC_addr (ð->destination),
MAC_addr (ð->source));
type = intel16 (eth->type);
if (type < ETH_MAX_DATA) /* LLC length field */
len = db_fprintf (" IEEE 802.3 encap (LLC) not supported");
else len = db_fprintf (" type %s (%04X)", LinkProtocol(type), type);
}
db_putc ('\n');
return (len);
}
/*----------------------------------------------------------------------*/
static void dump_arp_data (void)
{
char buf[30];
int i, printed;
db_fprintf ("Routing data:\r\n");
for (i = 0; i < arp_last_gateway; i++)
{
struct gate_table *gw = arp_gate_list + i;
db_write (" ");
db_fprintf ("network: %-15s ", _inet_ntoa(buf, gw->subnet));
db_fprintf ("router: %-15s ", _inet_ntoa(buf, gw->gate_ip));
db_fprintf ("mask: %s\n", _inet_ntoa(buf, gw->mask ? gw->mask : sin_mask));
}
for (i = printed = 0; i < MAX_ARP_DATA; i++)
{
struct arp_table *arp = arp_cache_data + i;
if (arp->flags >= ARP_FLAG_FOUND)
{
if (!printed)
db_fprintf ("ARP Cache:\r\n");
printed = 1;
db_fprintf (" IP: %-15s -> %s, expires: ",
_inet_ntoa(buf, arp->ip), MAC_addr (&arp->hardware));
if (arp->flags == ARP_FLAG_FIXED)
db_write ("never");
else if (arp->expiry > now)
db_fprintf ("%ss", time_str(arp->expiry - now));
else db_write ("yes");
db_putc ('\n');
}
}
if (_bootpon || _dhcpon || _rarpon)
db_write (" Above routing data may be overridden by "
"DHCP/BOOTP/RARP\r\n");
db_putc ('\n');
}
/*----------------------------------------------------------------------*/
static int arp_dump (const arp_Header *arp)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -