TCP debugging aid for 4.2BSD

Chris Torek chris at umcp-cs.UUCP
Wed May 29 01:07:58 AEST 1985


If you decide to do some TCP hacking on your 4.2BSD system (considering
that 4.2 needs a lot of TCP hacking) this program can be invaluable.
(It's pointed out a retransmit timing bug, for example; look closely at
tcp_output.c ...)  Sorry, no manual page; but it's only useful for tcp
hackers, who ought to be able to figure out how to use it anyway.
Without further ado, here it is:

: Run this shell script with "sh" not "csh"
PATH=:/bin:/usr/bin:/usr/ucb
export PATH
all=FALSE
if [ $1x = -ax ]; then
	all=TRUE
fi
/bin/echo 'Extracting tcpdbug.c'
sed 's/^X//' <<'//go.sysin dd *' >tcpdbug.c
#ifndef lint
static char rcsid[] = "$Header$";
#endif

X/*
 * tcpdbug
 *
 * snapshot tcpcbs
 */

#include <stdio.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/mbuf.h>
#include <sys/socket.h>
#include <sys/socketvar.h>
#include <sys/protosw.h>
#include <net/route.h>
#include <net/if.h>
#include <netinet/in.h>
#include <netinet/in_pcb.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/ip_var.h>
#include <netinet/ip_icmp.h>
#include <netinet/tcp.h>
#define TCPSTATES
#include <netinet/tcp_fsm.h>
#include <netinet/tcp_seq.h>
#include <netinet/tcp_timer.h>
#include <netinet/tcp_var.h>
#include <netinet/tcpip.h>

#include <nlist.h>
#include <netdb.h>

struct nlist nl[] = {
    {"_tcb"},
#define X_TCB	0
    {0}
};

int kmem;
struct inpcb tcb, inpcb;
struct tcpcb tcpcb;

int AFlag, FFlag, LFlag;
struct in_addr FAddr;
u_short FPort;

ReadKernelItem (kaddr, caddr, size)
caddr_t kaddr, caddr;
int size;
{
    (void) lseek (kmem, (long) kaddr, 0);
    if (read (kmem, caddr, size) != size) {
	perror ("kmem read");
	exit (1);
    }
}

OpenKmem () {
    if ((kmem = open ("/dev/kmem", 0)) < 0) {
	perror ("/dev/kmem");
	exit (1);
    }
}

GetNames () {
    nlist ("/vmunix", nl);
    if (nl[0].n_type == 0) {
	fprintf (stderr, "/vmunix: no namelist\n");
	exit (1);
    }
}

LoopThrough () {
    register struct inpcb *inp, *endp;
    register struct tcpcb *tp;

    endp = (struct inpcb *) nl[X_TCB].n_value;
    ReadKernelItem ((caddr_t) endp, (caddr_t) &tcb, sizeof tcb);
    for (inp = tcb.inp_next; inp != endp; inp = inpcb.inp_next) {
	ReadKernelItem ((caddr_t) inp, (caddr_t) &inpcb, sizeof inpcb);
	tp = (struct tcpcb *) inpcb.inp_ppcb;
	if (tp == 0)
	    continue;
	ReadKernelItem ((caddr_t) tp, (caddr_t) &tcpcb, sizeof tcpcb);
	DumpTCP (tp, &tcpcb);
    }
}

DumpTCP (ktp, tp) register struct tcpcb *ktp, *tp; {
#define flag(x) ((x) ? "true" : "false")
    struct timeval tv;
    struct timezone tz;

    if (FFlag) {		/* ignore mismatches */
	if (inpcb.inp_faddr.s_addr != FAddr.s_addr)
	    return;
	if (FPort && inpcb.inp_fport != FPort)
	    return;
    }
    else {
	if (tp -> t_state == TCPS_LISTEN && !AFlag)
	    return;		/* ignore LISTENers */
    }
    (void) gettimeofday (&tv, &tz);
    printf ("time = %d.%03d\n", tv.tv_sec, tv.tv_usec);
    printf ("\
tcpcb:\n\
\tlocal addr = %d.%d.%d.%d.%d\tforeign addr = %d.%d.%d.%d.%d\n\
\taddr = 0x%x\tstate = %s\n\
\ttimers: rexmt = %d, persist = %d, keep = %d, 2msl = %d\n\
\trxtshift = %d\tmaxseg = %d\tforce %s\n\
\tflags: ack now %s, del ack %s, don't keep %s, no opt %s\n\
\tsend seq: unack = 0x%x, next = 0x%x, urg = 0x%x,\n\
\t\twl1 = 0x%x, wl2 = 0x%x,\n\
\t\tiss= 0x%x, window = 0x%x\n\
\trecv seq: window = 0x%x, next = 0x%x, urg = 0x%x, irs = 0x%x\n\
\tadvertised window = 0x%x, highest seq sent = 0x%x\n\
\tidle = %d, rtt = %d, rttseq = 0x%x, srtt = %12.6f\n\
\toobflag %s, iobc = 0x%x\n\n",
#define xpand(x) (x).S_un.S_un_b.s_b1, (x).S_un.S_un_b.s_b2, \
		 (x).S_un.S_un_b.s_b3, (x).S_un.S_un_b.s_b4
	    xpand (inpcb.inp_laddr), ntohs (inpcb.inp_lport),
	    xpand (inpcb.inp_faddr), ntohs (inpcb.inp_fport),
#undef xpand
	    ktp, tcpstates[tp -> t_state],
	    tp -> t_timer[TCPT_REXMT], tp -> t_timer[TCPT_PERSIST],
	    tp -> t_timer[TCPT_KEEP], tp -> t_timer[TCPT_2MSL],
	    tp -> t_rxtshift, tp -> t_maxseg, flag (tp -> t_force),
	    flag (tp -> t_flags & TF_ACKNOW),
	    flag (tp -> t_flags & TF_DELACK),
	    flag (tp -> t_flags & TF_DONTKEEP),
	    flag (tp -> t_flags & TF_NOOPT),
	    tp -> snd_una, tp -> snd_nxt, tp -> snd_up, tp -> snd_wl1,
	    tp -> snd_wl2, tp -> iss, tp -> snd_wnd,
	    tp -> rcv_wnd, tp -> rcv_nxt, tp -> rcv_up, tp -> irs,
	    tp -> rcv_adv, tp -> snd_max,
	    tp -> t_idle, tp -> t_rtt, tp -> t_rtseq, tp -> t_srtt,
	    flag (tp -> t_oobflags), tp -> t_iobc & 0xff);
}

GetAddr (s) register char *s; {
    register char  *dotp;
    register struct hostent *hp;
    char   *rindex ();

    dotp = rindex (s, '.');
    if (!dotp) {
	fprintf (stderr, "%s: bad address format (should be host.port)\n", s);
	exit (1);
    }
    *dotp++ = 0;
    hp = gethostbyname (s);
    if (hp == 0) {
	fprintf (stderr, "%s: unknown host\n", s);
	exit (1);
    }
    FAddr.s_addr = *(n_long *) hp -> h_addr;
    FPort = htons (atoi (dotp));
}

Options (argc, argv)
register int argc;
register char **argv; {
    register char *s;

    argc--, argv++;
    while (--argc >= 0) {
	s = *argv++;
	if (*s++ != '-')
	    return;
	switch (*s) {
	    case 'a':
		AFlag++;
		break;
	    case 'f':
		if (*++s == 0) {
		    if (--argc >= 0)
			s = *argv++;
		    else
			return;
		}
		FFlag++;
		GetAddr (s);
		break;
	    case 'l':
		LFlag++;
		break;
	}
    }
}

main (argc, argv) char **argv; {
    Options (argc, argv);
    if (argc > 1 && strcmp (argv[1], "-a", 0) == 0)
	AFlag++;
    OpenKmem ();
    GetNames ();
    if (LFlag) {
	for (;;) {
	    LoopThrough ();
	    fflush (stdout);
	    nap (500);
	}
    }
    else
	LoopThrough ();
    exit (0);
}

nap (ms) {
    struct timeval tv;

    tv.tv_sec = 0;
    tv.tv_usec = ms * 1000;
    (void) select (0, (int *) 0, (int *) 0, (int *) 0, &tv);
}
//go.sysin dd *
made=TRUE
if [ $made = TRUE ]; then
	/bin/chmod 644 tcpdbug.c
	/bin/echo -n '	'; /bin/ls -ld tcpdbug.c
fi
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 4251)
UUCP:	seismo!umcp-cs!chris
CSNet:	chris at umcp-cs		ARPA:	chris at maryland



More information about the Comp.sources.unix mailing list