[comp.sources.sun] v01i037: Ethernet tools for SunOS 3.X, Part02/02

mcgrew@dartagnan.rutgers.edu (Charles Mcgrew) (06/22/89)

Submitted-by: budd@bu-it.bu.edu
Posting-number: Volume 1, Issue 37
Archive-name: ethertools-3.X/part02

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 2 (of 2)."
# Contents:  ctp.c if_ctp.c nit.c packet.h rlog.c
# Wrapped by budd@buita on Sat Aug 13 01:14:42 1988
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f ctp.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"ctp.c\"
else
echo shar: Extracting \"ctp.c\" \(10642 characters\)
sed "s/^X//" >ctp.c <<'END_OF_ctp.c'
X/*
X * Copyright (c) 1988 Philip L. Budne and The Trustees of Boston University
X * All Rights Reserved
X *
X * Permission is granted to any individual or institution to use, copy,
X * or redistribute this software so long as it is not sold for profit,
X * provided that this notice and the original copyright notices are
X * retained.  Boston University makes no representations about the
X * suitability of this software for any purpose.  It is provided "as is"
X * without express or implied warranty.
X */
X/*
X *	CTP -- Ethernet v2 Configuration Test Protocol User Process
X *	Philip L. Budne @ Boston University / Distributed Systems
X *
X */
X
X# include <sys/types.h>
X# include <sys/time.h>
X# include <net/nit.h>
X# include <signal.h>
X# include <stdio.h>
X# include "ctp.h"
X
X/*
X * SIGH.  Move sender to child?
X * print loss.
X * print variance.
X */
X
X# define SHM
X
Xtypedef u_char ea_t[6];			/* ethernet address type */
X
X# ifdef SHM
X# include <sys/ipc.h>
X# include <sys/shm.h>
X
Xint shmid;
Xchar *shmaddr, *shmat();
X
X# define NCOUNTS 8
X# define NCOUNT (1<<(NCOUNTS))
Xstruct stats {
X    int total;				/* total count */
X    int highseq;			/* highest seq seen */
X    int outofseq;			/* number recvd out of sequence */
X    int min, max;			/* min and max times */
X    int sum, sumsq;			/* sum of times, sum of squares */
X    int counts[ NCOUNT ];
X    /* array of addrs? */
X};
X
Xint lastseq = 0;
Xint nsent = 0;
X# endif /* SHM defined */
X
Xint seq = 0;
X
Xstruct packet {				/* CTP packet layout */
X    ea_t    p_dst;			/* Ethernet dest */
X    ea_t    p_src;			/* Ethernet src */
X    u_short p_type;			/* Ethernet type (802 length) */
X    u_short p_skip;			/* CTP skip */
X    u_char  p_data[ 2048 ];		/* ... */
X};
X
Xstruct ctp_forward {			/* forward subpacket */
X    u_short cf_function;		/* CTP_FWD */
X    ea_t    cf_addr;
X};
X
Xstruct ctp_reply {			/* reply subpacket */
X    u_short cr_function;		/* CTP_REP */
X    /* The following is data that we use for own purposes */
X    u_short cr_pid;			/* pid of sender -- not swapped */
X    u_short cr_seq;			/* sequence number -- not swapped */
X    struct timeval cr_sendt;		/* time packet was sent */
X    /* more data here.. */
X};
X
Xea_t localaddr;				/* our ethernet address */
X
X# define MAXPATH 200			/* !! (more than can fit in a packet) */
Xea_t path[ MAXPATH];			/* path list */
Xint pathcount = 0;			/* length of path list */
X
X# define MINPACK 60			/* minimum ether packet */
X# define MAXPACK 1516			/* maximum ether packet */
X
Xint count = -1;				/* number of packets to send */
Xchar ifbuf[ 100 ];
Xchar *interface = ifbuf;		/* interface to use */
Xint verbose = 0;			/* extra output */
Xint noreturn = 0;			/* don't force final forward back */
Xint debug = 0;				/* don't fork */
Xint packlen = MINPACK;			/* default total packet length */
Xint slptim = 1000;			/* sleep time in ms */
X
Xint pid;				/* parent pid */
Xint child;				/* child pid */
X
Xmain(argc, argv)
X    int argc;
X    char *argv[];
X{
X    extern char *optarg;
X    extern int optind, opterr;
X    int s, c, errs;
X    void nit_input();			/* forward */
X
X    errs = 0;
X    while( (c = getopt( argc, argv, "c:di:l:ns:v" )) != EOF ) {
X	switch( c ) {
X	case 'c':
X	    count = atoi( optarg );
X	    break;
X	case 'd':
X	    debug ^= 1;
X	    break;
X	case 'i':
X	    interface = optarg;
X	    break;
X	case 'l':
X	    packlen = atoi( optarg );
X	    if( packlen < MINPACK )
X		packlen = MINPACK;
X	    else if( packlen > MAXPACK )
X		packlen = MAXPACK;
X	    break;
X	case 'n':
X	    noreturn ^= 1;
X	    break;
X	case 's':
X	    slptim = atoi( optarg );
X	    break;
X	case 'v':
X	    verbose ^= 1;
X	    break;
X	default:
X	    errs++;
X	} /* switch */
X    } /* while getopt */
X    if( errs > 0 ) {
X	fprintf( stderr, "Usage: %s [-c count] [-d] [-i ifn] ", argv[0] );
X	fprintf( stderr, "[-l len] [-n] [-s sleep] [-v] [addr ...]\n");
X	fprintf( stderr, "addr <- ether-addr | ipaddr | iphost | ");
X	fprintf( stderr, "etherhost | 'BCAST' | 'MCAST'\n" );
X	exit( 1 );
X    }
X
X    pid = getpid();			/* get parent pid */
X    s = nit_open( interface, ETHERTYPE_CTP, localaddr, 0 );
X    printf("%s address ", interface );
X    petaddr( localaddr );
X    puts( "" );
X
X    pathcount = 0;
X    while( optind < argc && pathcount < MAXPATH && argv[optind] != NULL ) {
X	if( strcmp( argv[optind], "MCAST" ) == 0 ) {	/* CTP mcast addr */
X	    register u_char *ea;
X	    ea = path[pathcount];
X	    *ea++ = 0XCF;
X	    *ea++ = 0x00;
X	    *ea++ = 0x00;
X	    *ea++ = 0x00;
X	    *ea++ = 0x00;
X	    *ea   = 0x00;
X	}
X	else if( !htoea( argv[ optind ], path[pathcount] ) ) {
X	    fprintf( stderr, "%s: unknown host %s\n",
X		    argv[0], argv[optind] );
X	    exit( 1 );
X	} /* bad host */
X	pathcount++;
X	optind++;
X    } /* while hosts */
X
X    if( pathcount == 0 ) {		/* if no hosts */
X	bcopy( bcast, path[0], sizeof( ea_t ) ); /* broadcast */
X	pathcount++;			/* fake count */
X    } /* empty path */
X
X    if( debug )
X	ctp_send( s );			/* just send */
X    else {
X# ifdef SHM
X	void gotint(), die(), poop();
X	struct stats *sp;
X
X	signal( SIGINT, gotint );
X	signal( SIGHUP, die );
X	signal( SIGKILL, die );
X
X	shmid = shmget( IPC_PRIVATE, sizeof( struct stats ), 0600 );
X	shmaddr = shmat( shmid, 0, 0 );
X	sp = (struct stats *)shmaddr;
X	bzero( sp, sizeof( struct stats ) );
X	sp->min = 100000;
X	sp->max = -1;
X# endif /* SHM defined */
X
X	switch( (child = fork()) ) {
X	case -1:
X	    perror( "fork" );
X	    exit( 1 );
X	    /* NOTREACHED */
X
X	case 0:
X# ifdef SHM
X	    signal( SIGINT,  poop );
X	    signal( SIGHUP,  poop );
X	    signal( SIGKILL, poop );
X# endif /* SHM defined */
X	    nit_loop( s, nit_input );	/* input in child */
X	    /* NOTREACHED */
X
X	default:
X	    ctp_send(s);		/* output in parent */
X	    /* NOTREACHED */
X	} /* switch */
X    }
X} /* main */
X
X# ifdef SHM
Xvoid
Xdie() {
X    (void) shmdt( shmaddr );
X    (void) shmctl( shmid, IPC_RMID, 0 );
X    exit( 0 );
X}
X
Xvoid
Xpoop() {
X    exit( 1 );
X}
X
Xvoid
Xstats() {
X    register struct stats *sp;
X
X    sp = (struct stats *) shmaddr;
X    printf("----CTP statistics----\n");
X    printf("%d Packet%s Sent, %d Recieved\n",
X	   nsent, (nsent == 1 ? "" : "s"), sp->total );
X    if( sp->total > 0 )
X	printf("round-trip (ms)  min/avg/max = %d/%d/%d var=%d\n",
X	       sp->min, sp->sum / sp->total, sp->max,
X	       0 );
X} /* stats */
X
Xvoid
Xgotint() {
X    puts("");
X    stats();
X    die();
X}
X
X# endif /* SHM defined */
X
X/****************************************************************/
X
Xvoid
Xnit_input( s, nh )
X    int s;
X    struct nit_hdr *nh;
X{
X    int l;
X    u_char *p2;
X    int len, l2, ms;
X    short f, skip, seq;
X    struct packet *pp;
X    struct ctp_reply *cr;
X# ifdef SHM
X    register struct stats *sp;
X    sp = (struct stats *) shmaddr;
X# endif /* SHM defined */
X
X    l = nh->nh_datalen;
X    pp = (struct packet *) (((u_char *)nh) + sizeof( struct nit_hdr ));
X    
X    skip = pp->p_skip;			/* fetch skip */
X    skip = SSWAP( skip );		/* swap it */
X
X    if( skip & 1 )
X	return;				/* skip must not be odd */
X
X    p2 = (u_char *) pp->p_data + skip;
X    len = l - 14 - skip - 2;		/* length of data */
X
X    if( len < 2 )			/* no room for function */
X	return;
X
X    cr = (struct ctp_reply *) p2;	/* get reply struct */
X    f = CTP_SHORT( p2 );		/* get function */
X    p2 += 2;				/* advance past function */
X    len -= 2;				/* account for function length */
X    switch( f ) {
X    case CTP_REP:			/* reply */
X	break;
X
X    case CTP_FWD:
X	return;				/* we are a client. */
X	break;
X
X    default:
X/*	printf(" fncn %d. data: ", f );	/* !! */
X	return;
X    }
X
X    if( cr->cr_pid != pid )		/* check for parent pid */
X	return;
X
X    p2 += 2;				/* advance past pid */
X    len -= 4;				/* pid, seq */
X
X    printf("%d bytes from ", l );
X    petaddr( pp->p_src );
X    seq = CTP_SHORT( p2 );
X    ms = delta( &nh->nh_timestamp, &cr->cr_sendt );
X    printf(": seq %2d. time=%dms\n", seq, ms );
X
X# ifdef SHM
X    sp->total++;
X    if( seq != lastseq && seq != lastseq+1 )
X	sp->outofseq++;
X    lastseq = seq;
X    if( ms > sp->max )
X	sp->max = ms;
X    if( ms < sp->min )
X	sp->min = ms;
X    if( seq > sp->highseq )
X	sp->highseq = seq;
X    sp->sum += ms;
X    sp->sumsq = ms * ms;
X    sp->counts[ seq & (NCOUNT-1) ]++;
X# endif /* SHM defined */
X} /* nit_input */
X
Xdelta( a, b )
X    struct timeval *a, *b;
X{
X    int usec, sec;
X    usec = a->tv_usec - b->tv_usec;
X    sec  = a->tv_sec  - b->tv_sec;
X
X    if( usec < 0 )   {
X	sec--;
X	usec += 1000000;
X    }
X    usec += 999;			/* round to ms */
X    sec = sec * 1000 + usec / 1000;	/* get ms */
X    if( sec < 0 ) {
X	printf("a: %d %d b: %d %d\n",
X	       a->tv_sec, a->tv_usec,
X	       b->tv_sec, b->tv_usec );
X	return( 0 );
X    } /* sec < 0 */
X    return( sec );
X} /* delta */
X
X/****************************************************************/
X
Xctp_send( s )
X    int s;
X{
X    struct timezone tz;
X    struct ctp_forward *cf;
X    struct ctp_reply *cr, *ocr;
X    struct packet p;
X    u_char *cp;
X    int i, c;
X
X    printf("to ");
X    for( i = 0; i < pathcount; i++ ) {
X	if( i > 0 )
X	    printf(", ");
X	petaddr( path[i] );
X    }
X
X    /* fill in ether packet header */
X    bcopy( path[ 0 ], p.p_dst, sizeof( p.p_dst ) ); /* fill in initial dest */
X    p.p_type = ETHERTYPE_CTP;		/* fill in type */
X    p.p_skip = SSWAP( 0 );		/* fill in initial CTP skip */
X
X    cf = (struct ctp_forward *) p.p_data; /* get data pointer */
X    for( i = 1; i < pathcount; i++ ) {
X	cf->cf_function = SSWAP( CTP_FWD );
X	bcopy( path[i], cf->cf_addr, sizeof( ea_t ) );
X	cf++;				/* advance pointer */
X    }
X
X    /* ensure packet gets back -- append forward to ourselves */
X    if( !noreturn &&
X       bcmp( path[pathcount-1], localaddr, sizeof( localaddr ) ) != 0 ) {
X	cf->cf_function = SSWAP( CTP_FWD );
X	bcopy( localaddr, cf->cf_addr, sizeof( localaddr ) );
X	cf++;
X    }
X
X    /* create reply data */
X    cr = (struct ctp_reply *) cf;
X    cr->cr_function = SSWAP( CTP_REP );
X    cr->cr_pid = pid;			/* pid of parent */
X    ocr = cr;				/* save pointer for timestamp */
X    cr++;				/* advance past reply */
X
X    cp = (u_char *) cr;			/* get pointer to reply data */
X    i = cp - (u_char *)&p;		/* get length of packet so far */
X
X    if( i > packlen )
X	if( i > MAXPACK ) {
X	    fprintf( stderr, "Packet too large without data (%d)\n", i );
X	    exit( 1 );
X	}
X	else
X	    packlen = i;
X
X    printf(": %d data bytes (%d total)\n", packlen - i, packlen );
X    fflush( stdout );
X
X    while( i < packlen )
X	*cp++ = i++ & 0xff;
X
X    slptim *= 1000;			/* convert to usec */
X    while( count != 0 ) {
X	if( count > 0 )
X	    count--;
X	ocr->cr_seq = SSWAP( seq );
X	seq++;				/* update sequence */
X	gettimeofday( &ocr->cr_sendt, &tz );
X
X	if( nit_output( s, &p, packlen ) < 0 )
X	    perror( "write" );
X	else
X	    nsent++;
X	usleep( slptim ); 
X    }
X    kill( child, SIGINT );
X    stats();
X    die();
X} /* ctp_send */ 
END_OF_ctp.c
if test 10642 -ne `wc -c <ctp.c`; then
    echo shar: \"ctp.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f if_ctp.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"if_ctp.c\"
else
echo shar: Extracting \"if_ctp.c\" \(5585 characters\)
sed "s/^X//" >if_ctp.c <<'END_OF_if_ctp.c'
X/*
X * Copyright (c) 1988 Philip L. Budne and The Trustees of Boston University
X * All Rights Reserved
X *
X * Permission is granted to any individual or institution to use, copy,
X * or redistribute this software so long as it is not sold for profit,
X * provided that this notice and the original copyright notices are
X * retained.  Boston University makes no representations about the
X * suitability of this software for any purpose.  It is provided "as is"
X * without express or implied warranty.
X */
X/*
X * if_ctp.c -- Ethernet Version 2 Configuation Test Protocol (CTP)
X *
X * DEC DEUNA does this at the controller level??
X */
X
X
X/*
X * Called from do_protocol in sunif/if_subr.c;
X *
X *#endif INET
X>*#ifdef ETHERPUP_CTPTYPE:
X>*	case ETHERPUP_CTPTYPE:
X>*		ctp_input( header, m, &ap->ac_if );
X>*		break;
X>*#endif ETHERPUP_CTPTYPE:
X *	default:
X */
X
X/*
X * add to /sys/conf/files;
X * sunif/if_ctp.c		optional ether
X */
X
X/* add to netinet/if_ether.h;
X/* #define ETHERTYPE_CTP	0x9000		/* Config. Test Protocol */
X/* ... */
X/* #define ETHERPUP_CTPTYPE	0x9000		/* Config. Test Protocol */
X
X
X# include "ether.h"
X
X# if NETHER > 0
X# include "../h/param.h"
X# include "../h/systm.h"
X# include "../h/mbuf.h"
X# include "../h/socket.h"
X# include "../h/time.h"
X# include "../h/kernel.h"
X# include "../h/errno.h"
X# include "../h/ioctl.h"
X
X# include "../net/if.h"
X# include "../netinet/in.h"		/* for if_ether */
X# include "../netinet/if_ether.h"	/* for ether_header */
X
X# define DEBUG
X
X# define CTP_REP 1
X# define CTP_FWD 2
X
X# if defined(vax) || defined(ns32000)	/* machine is a byteswapper? */
X# define SWAP(s) (s)			/* CTP wants them swapped!! */
X# else /* not defined(vax) || defined(ns32000) */
X# define SWAP(s) ((((s)>>8) & 0xff) | (((s)<<8) & 0xff00))
X# endif /* not defined(vax) || defined(ns32000) */
X
X# ifndef ETHERTYPE_CTP
X# define ETHERTYPE_CTP 0x9000		/* 90-00 */
X# endif /* ETHERTYPE_CTP not defined */
X
X# define SP(s) ((u_short *)s)
X# define SS (sizeof(short))
X
Xint ctp_rawinput;			/* total input */
Xint ctp_reply;				/* replies to us */
Xint ctp_forward;			/* packets forwarded */
Xint ctp_multicast;			/* err: forward to multicast!! */
Xint ctp_badfunction;			/* err: bad function */
Xint ctp_errs;				/* other errs */
Xctp_input( h, m, myif )
X    register struct ether_header *h;
X    register struct mbuf *m;
X    struct ifnet *myif;
X{
X    ctp_rawinput++;
X
X    if( !ctp_process( h, m ) )		/* no reply generated?? */
X	m_freem(m);			/* discard buffer */
X}
X
Xstatic ctp_process( h, m, myif )
X    register struct ether_header *h;
X    register struct mbuf *m;
X    struct ifnet *myif;
X{
X    register u_short func, skip;
X    register u_char *cp;
X    register int l;
X
X    struct ether_header *eh;
X    struct sockaddr sa;
X
X    l = m->m_len;			/* get data length */
X    cp = mtod(m, u_char *);		/* get data pointer */
X
X    /****************************************************************
X     * process skip
X     */
X
X    l -= SS;
X    if( l < 0 ) {
X# ifdef DEBUG
X	ctp_msg( h );
X	printf("-- too short for skip\n", skip );
X# endif /* DEBUG defined */
X	ctp_errs++;
X	return( 0 );			/* no reply generated */
X    }
X
X    skip = *SP( cp );			/* get skip */
X    skip = SWAP( skip );		/* byte swap if needed */
X    cp += SS;
X
X    if( skip & 1 ) {
X# ifdef DEBUG
X	ctp_msg( h );
X	printf("-- odd skip %d\n", skip );
X# endif /* DEBUG defined */
X	ctp_errs++;
X	return( 0 );			/* no reply generated */
X    }
X
X    /****************************************************************
X     * process function
X     */
X
X    l -= skip;
X    if( l < 0 ) {
X# ifdef DEBUG
X	ctp_msg( h );
X	printf("-- skip too large (%d.)\n", skip );
X# endif /* DEBUG defined */
X	ctp_errs++;
X	return( 0 );			/* no reply generated */
X    }
X
X    cp += skip;				/* get address of function */
X
X    func = *SP( cp );			/* get function */
X    func = SWAP( func );		/* byte swap if needed */
X
X    l -= SS;				/* deduct function length */
X    cp += SS;				/* advance past function */
X
X    switch( func ) {
X
X    case CTP_REP:			/* reply */
X# ifdef DEBUG
X	ctp_msg( h );
X	printf("-- reply, %d bytes\n", l);
X# endif /* DEBUG defined */
X	/* create AF_CTP and pass up to users?? */
X	ctp_reply++;
X	return( 0 );			/* no reply generated */
X	break;
X
X    case CTP_FWD:
X	l -= sizeof( struct ether_addr );
X	if( l < 0 ) {
X# ifdef DEBUG
X	    ctp_msg( h );
X	    printf("-- forward too short\n");
X# endif /* DEBUG defined */
X	    ctp_errs++;
X	    return( 0 );
X	}
X	if( *cp & 1 ) {			/* multicast bit */
X	    ctp_msg( h );
X	    printf(" -- forward to multicast address ");
X	    ether_print( cp );
X	    printf(" ignored\n");
X	    ctp_multicast++;
X	    return( 0 );		/* no reply generated */
X	}
X# ifdef DEBUG
X	ctp_msg( h );
X	printf("-- forwarding %d bytes to ", l);
X	ether_print( cp );
X# endif /* DEBUG defined */
X	skip += SS + sizeof( struct ether_addr ); /* skip forward function */
X					/* and address */
X	*mtod(m, u_short *) = SWAP( skip ); /* update in packet */
X
X	sa.sa_family = AF_UNSPEC;		/* set family */
X	eh = (struct ether_header *)sa.sa_data;	/* get sockaddr */
X	eh->ether_type = ETHERTYPE_CTP;		/* set ether type */
X	eh->ether_dhost = *(struct ether_addr *) cp; /* copy dest */
X	(myif->if_output)( myif, m, &sa );
X
X	ctp_forward++;
X	return( 1 );			/* AH-HAH!! we generated a reply!! */
X	break;
X
X    default:
X# ifdef DEBUG
X	ctp_msg( h );
X	printf("-- bad function %d.\n", func );
X# endif /* DEBUG defined */
X	ctp_badfunction++;
X	return( 0 );
X	break;
X    }
X    return( 0 );			/* just in case */
X} /* ctp_process */
X
Xctp_msg( h )
X    register struct ether_header *h;
X{
X    printf("CTP packet from ");
X    ether_print( &h->ether_shost );
X} /* ctp_msg */
X
X# endif /* NETHER > 0 */
END_OF_if_ctp.c
if test 5585 -ne `wc -c <if_ctp.c`; then
    echo shar: \"if_ctp.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f nit.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"nit.c\"
else
echo shar: Extracting \"nit.c\" \(5414 characters\)
sed "s/^X//" >nit.c <<'END_OF_nit.c'
X/*
X * Copyright (c) 1988 Philip L. Budne and The Trustees of Boston University
X * All Rights Reserved
X *
X * Permission is granted to any individual or institution to use, copy,
X * or redistribute this software so long as it is not sold for profit,
X * provided that this notice and the original copyright notices are
X * retained.  Boston University makes no representations about the
X * suitability of this software for any purpose.  It is provided "as is"
X * without express or implied warranty.
X */
X# include <sys/types.h>
X# include <sys/time.h>
X# include <sys/socket.h>
X# include <sys/ioctl.h>
X# include <net/nit.h>
X# include <net/if.h>
X# include <stdio.h>
X
X# define GLOBAL
X
X# ifdef DEBUG
X# define IFDEB(x) (x)
X# else /* DEBUG not defined */
X# define IFDEB(x)
X# endif /* DEBUG not defined */
X
X# define ALIGNSIZE sizeof( int )
X# define ALIGN(a) (((a) + ALIGNSIZE - 1) & ~(ALIGNSIZE - 1))
X/* NITBUFSIZ == 1K */
X# define BUFSPACE (NITBUFSIZ * 256)
X# define CHUNKSIZE (NITBUFSIZ * 64)
X/****************************************************************/
X
X
XGLOBAL int nit_errors = 1;		/* display errors */
XGLOBAL int nit_exit = 1;		/* exit on errors */
XGLOBAL int nit_bufspace = BUFSPACE;
XGLOBAL int nit_chunksize = CHUNKSIZE;
XGLOBAL int nit_snaplen = 2000;
X
Xtypedef void (*FPTR)();
X
XGLOBAL int
Xnit_loop( s, input_handlr )
X    int s;
X    FPTR input_handlr;
X{
X    for( ;; ) {
X	static char buf[ BUFSPACE ];
X	register char *pp;
X	register struct nit_hdr *nh;
X	char *pe;
X	int cc;
X
X	cc = read( s, buf, sizeof( buf ) );
X	if( cc < sizeof( struct nit_hdr ) ) {
X	    if( nit_errors )
X		fprintf(stderr, "nit_loop: short read (%d)\n", cc );
X	    if( nit_exit )
X		exit( 1 );
X	    else
X		return( -1 );
X	} /* short read */
X
X	pp = buf;
X	pe = pp + cc;
X	while( pp < pe ) {
X	    nh = (struct nit_hdr *) pp;
X	    cc = process_nh( s, nh, input_handlr );
X	    if( cc < 0 )
X		break;
X	    else
X		pp += ALIGN( sizeof( struct nit_hdr ) + cc );
X	} /* while */
X    } /* for ever */
X} /* nit_process */
X
Xstatic int
Xprocess_nh( s, nh, input_handlr )
X    int s;
X    struct nit_hdr *nh;
X    FPTR input_handlr;
X{
X    switch( nh->nh_state ) {
X    case NIT_QUIET:
X	IFDEB( fprintf(stderr, "quiet\n") );
X	return( 0 );
X
X    case NIT_CATCH:
X	(*input_handlr)( s, nh );
X	return( nh->nh_datalen );
X
X    case NIT_NOMBUF:
X	fprintf(stderr, "out of mbufs, dropped %d packets\n",
X		nh->nh_dropped );
X	return( 0 );
X	
X    case NIT_NOCLUSTER:
X	fprintf(stderr, "out of mclusters, dropped %d packets\n",
X		nh->nh_dropped );
X	return( 0 );
X	
X    case NIT_NOSPACE:
X	fprintf(stderr, "bufspace exceeded, dropped %d packets\n",
X		nh->nh_dropped );
X	return( 0 );
X	
X    case NIT_SEQNO:
X	IFDEB( fprintf(stderr, "seqno %d\n", nh->nh_seqno ) );
X	return( 0 );
X
X    default:
X	fprintf(stderr, "bad NIT state: %d\n", nh->nh_state );
X	return( -1 );
X    } /* switch */
X}
X
XGLOBAL int
Xnit_open( ifa, type, la, pro )
X    char *ifa;
X    unsigned int type;
X    u_char *la;
X    int pro;
X{
X    struct sockaddr_nit snit;
X    struct nit_ioc nioc;
X    struct ifreq ifr;
X    int s;
X
X    if( ifa == NULL ) {
X	if( nit_errors )
X	    fprintf( stderr, "nit_open: must have interface pointer\n" );
X	if( nit_exit )
X	    exit( 1 );
X	else
X	    return( -1 );
X    } /* no ifa */
X
X    if( (s = socket(AF_NIT, SOCK_RAW, NITPROTO_RAW)) < 0 ) {
X	if( nit_errors )
X	    perror( "socket" );
X	if( nit_exit )
X	    exit( 1 );
X	else
X	    return( -1 );
X    } /* socket */
X
X    if( *ifa == '\0' ) {		/* no interface specified */
X	struct ifconf ifc;
X	char ifbuf[ 100 ];
X
X	ifc.ifc_len = sizeof( ifbuf );
X	ifc.ifc_buf = ifbuf;
X
X	if( ioctl(s, SIOCGIFCONF, (char *)&ifc) < 0 ) {
X	    if( nit_errors )
X		perror( "ifconf ioctl");
X	    close( s );
X	    if( nit_exit )
X		exit( 1 );
X	    else
X		return( -1 );
X	} /* ifconf failed */
X	strcpy( ifa, ifc.ifc_req->ifr_name ); /* copy back to buffer */
X    } /* try to find an interface */
X
X    snit.snit_family = AF_NIT;
X    strncpy( snit.snit_ifname, ifa, sizeof(snit.snit_ifname ) );
X    if( bind(s, (struct sockaddr *)&snit, sizeof( snit ) ) < 0 ) {
X	if( nit_errors )
X	    perror( ifa );
X	close( s );
X	if( nit_exit )
X	    exit( 1 );
X	else
X	    return( -1 );
X    } /* bind failed */
X
X    bzero(&nioc, sizeof(nioc));
X    nioc.nioc_bufspace = nit_bufspace;
X    nioc.nioc_chunksize = nit_chunksize;
X    nioc.nioc_typetomatch = type;
X    nioc.nioc_snaplen = nit_snaplen;
X    nioc.nioc_bufalign = ALIGNSIZE;
X    nioc.nioc_bufoffset = 0;
X    nioc.nioc_flags = (pro ? NF_PROMISC : 0 ) | NF_TIMEOUT;   
X    nioc.nioc_timeout.tv_sec = 1;
X    nioc.nioc_timeout.tv_usec = 0;
X    if (ioctl(s, SIOCSNIT, &nioc) != 0) {
X	if( nit_errors )
X	    perror("nit ioctl");
X	close( s );
X	if( nit_exit )
X	    exit(1);
X	else
X	    return( -1 );
X    } /* nit ioctl */
X
X    strncpy(ifr.ifr_name, ifa, sizeof ifr.ifr_name);
X    if( ioctl(s, SIOCGIFADDR, (caddr_t) &ifr) < 0 ) {
X	if( nit_errors )
X	    fprintf(stderr, "cannot find ether address for %s\n", ifa );
X	close( s );
X	if( nit_exit )
X	    exit( 1 );
X	else
X	    return( -1 );
X    } /* interface address ioctl */
X    bcopy( ifr.ifr_addr.sa_data, la, 6 );
X    return( s );
X} /* nit_open */
X
XGLOBAL int
Xnit_output(fd, buf, len)
X    int fd, len;
X    char *buf;
X{
X    struct sockaddr sa;
X    int offset = sizeof(sa.sa_data);
X    int result;
X
X    sa.sa_family = AF_UNSPEC;
X    bcopy(buf, sa.sa_data, offset);
X    result = sendto(fd, buf+offset, len-offset, 0, &sa, sizeof(sa));
X    if( result < 0 )
X	return( result );
X    return( result+offset );
X} /* nit_output */
END_OF_nit.c
if test 5414 -ne `wc -c <nit.c`; then
    echo shar: \"nit.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f packet.h -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"packet.h\"
else
echo shar: Extracting \"packet.h\" \(6347 characters\)
sed "s/^X//" >packet.h <<'END_OF_packet.h'
X/*
X * Copyright (c) 1988 Philip L. Budne and The Trustees of Boston University
X * All Rights Reserved
X *
X * Permission is granted to any individual or institution to use, copy,
X * or redistribute this software so long as it is not sold for profit,
X * provided that this notice and the original copyright notices are
X * retained.  Boston University makes no representations about the
X * suitability of this software for any purpose.  It is provided "as is"
X * without express or implied warranty.
X */
Xtypedef unsigned char byte;
Xtypedef unsigned short u_short;
Xtypedef unsigned long ip_addr;
Xtypedef unsigned long u_long;
Xtypedef byte EA[6];
X
X/****************************************************************/
Xstruct ipheader {
X# ifdef SWAP
X    int ip_ihl : 4;		/* Internet header length in 32 bit words */
X    int ip_ver : 4;		/* Header version */
X# else /* SWAP not defined */
X    int ip_ver : 4;		/* Header version */
X    int ip_ihl : 4;		/* Internet header length in 32 bit words */
X# endif /* SWAP not defined */
X    byte ip_tsrv;		/* Type of service */
X    u_short ip_len;		/* Total packet length including header */
X    u_short ip_id;		/* ID for fragmentation */
X# ifdef SWAP
X    u_short ip_foff : 13;	/* Fragment offset */
X    u_short ip_flgs : 3;	/* flags */
X# else /* SWAP not defined */
X    u_short ip_flgs : 3;	/* flags */
X    u_short ip_foff : 13;	/* Fragment offset */
X# endif /* SWAP not defined */
X# define IP_FLG_DF 01
X# define IP_FLG_MF 02
X
X    byte ip_ttl;		/* Time to live (secs) */
X    byte ip_prot;		/* protocol */
X    u_short ip_chksum;		/* Header checksum */
X    ip_addr ip_src;		/* Source addrt */
X    ip_addr ip_dst;		/* Destination addr */
X    byte ip_options[1];		/* options... */
X};
X					/* from RFC990 */
X# define IP_PROT_ICMP	1		/* control messages */
X# define IP_PROT_GGP	2		/* gave vs gate */
X					/* 5 - ST - stream */
X# define IP_PROT_TCP	6		/* tcp */
X# define IP_PROT_EGP	8		/* ext gateways */
X					/* 9 - any igp */
X# define IP_PROT_PUP	12		/* pup */
X					/* 13 - ARGUS */
X					/* 14 - EMCON */
X					/* 15 - XNET - cross net debugger */
X					/* 16 - Chaos */
X# define IP_PROT_UDP	17		/* user datagrams */
X					/* 18 - MUX - Multiplexing */
X					/* 19 - DCN-MEAS */
X					/* 20 - HMP host monitoring */
X					/* 21 PRM */
X# define IP_PROT_IDP	22		/* xns idp */
X					/* 23 TRUNK1 */
X					/* 24 TRUNK2 */
X					/* 25 LEAF1 */
X					/* 26 LEAF2 */
X					/* 27 RDP */
X					/* 28 IRTP - reliable transaction */
X					/* 29 ISO-TP4 */
X					/* 30 NETBLT */
X					/* 61 any host internal protocol */
X					/* 62 CFTP */
X					/* 63 any local network */
X					/* 64 SAT-EXPAK */
X					/* 65 MIT-SUBNET */
X					/* 66 - RVD */
X					/* 67 IPPC */
X					/* 68 any DFS */
X					/* 69 SAT-MON */
X					/* 71 IPCV */
X					/* 76 BR-SAT-MON */
X					/* 78 WB-MON */
X					/* 79 WB-EXPAK */
X# define IP_PROT_ND	77		/* net disk (SUN, unoff) */
X
X
X/****************************************************************/
Xstruct udpheader {
X    u_short udp_srcp;			/* source port */
X    u_short udp_dstp;			/* dest port */
X    u_short udp_len;			/* length of UDP packet */
X    u_short udp_cksum;			/* UDP checksum */
X};
X
X/****************************************************************/
Xstruct tcpheader {			/* a tcp header */
X    u_short tcp_srcp;			/* source port */
X    u_short tcp_dstp;			/* dest port */
X    u_long tcp_seq;			/* sequence number */
X    u_long tcp_ack;			/* acknowledgement number */
X# if 0
X    u_short tcp_flags;
X# define tcp_thl	tcp_flags >> 12
X# define tcp_fin	tcp_flags & 001
X# define tcp_syn	tcp_flags & 002
X# define tcp_rst	tcp_flags & 004
X# define tcp_psh	tcp_flags & 010
X# define tcp_fack	tcp_flags & 020
X# define tcp_furg	tcp_flags & 040
X# else /* not 0 */
X    unsigned tcp_thl : 4;		/* tcp header length */
X    unsigned tcp_uu1 : 6;		/* unused */
X    unsigned tcp_furg : 1;		/* urgent ptr. valid */
X    unsigned tcp_fack : 1;		/* ack valid */
X    unsigned tcp_psh : 1;		/* push bit */
X    unsigned tcp_rst : 1;		/* reset bit */
X    unsigned tcp_syn : 1;		/* syn bit */
X    unsigned tcp_fin : 1;		/* fin bit */
X# endif /* not 0 */
X    u_short tcp_win;			/* window */
X    u_short tcp_cksum;			/* checksum */
X    u_short tcp_urg;			/* urgent pointer */
X};
X
X/****************************************************************/
Xstruct ndpacket {
X    byte nd_op, nd_dev, nd_err, nd_ver;
X    u_long nd_seq, nd_blk, nd_count, nd_res, nd_off, nd_data;
X};
X
X/****************************************************************/
Xstruct arppacket {
X    u_short	arp_hw;			/* should be 1 */
X    u_short	arp_pro;
X    byte	arp_hln;		/* hdw addr len */
X    byte	arp_pln;		/* proto addr len */
X    u_short	arp_op;			/* arp opcode */
X    byte	arp_data[1];		/* data... */
X/*  EA		arp_xsha;		/* sender hardware address */
X/*  ip_addr	arp_xspa;		/* sender protocol address */
X/*  EA		arp_xtha;		/* target hardware address */
X/*  ip_addr	arp_xtpa;		/* target protocol address */
X};
X
X# define ARP_REQUEST	1		/* request to resolve address */
X# define ARP_REPLY	2		/* response to previous request */
X# define RARP_REQUEST	3		/* request to resolve address */
X# define RARP_REPLY	4		/* response to previous request */
X
X/* as of rfc990 */
X# define ARP_HW_ETHER	1		/* 10mb ether */
X# define ARP_HW_XETHER	2		/* 3mb ether */
X# define ARP_HW_AX25	3		/* amateur radio */
X# define ARP_HW_PRONET	4
X# define ARP_HW_CHAOS	5
X# define ARP_HW_IEEE802	6
X
X/****************************************************************/
Xstruct puppacket {
X    u_short pup_len;
X    byte pup_transport;
X    byte pup_type;
X    u_long pup_id;
X    struct {
X	byte pup_port_net;
X	byte pup_port_host;		/* swapped? */
X	u_short pup_port_sock1, pup_port_sock2;
X    } pup_src, pup_dst;
X};
X
X/****************************************************************/
Xstruct xns_addr {
X    byte xnsa_net[4];
X    byte xnsa_host[6];
X    u_short xnsa_port;
X};
X
Xstruct xnspacket {			/* xns idp */
X    u_short xns_sum, xns_len;		/* cksum, len */
X    byte xns_tc, xns_pt;		/* hops(transport), packet type */
X    struct xns_addr xns_dst;
X    struct xns_addr xns_src;
X};
X/****************************************************************/
X
Xunion {
X    byte p_bytes[ 2000 ];
X    struct etherpacket {
X	EA e_dst;
X	EA e_src;
X	u_short e_type;
X	union {
X	    byte d_bytes[1];
X	    struct ipheader  d_ip;
X	    struct arppacket d_arp;
X	    struct puppacket d_pup;
X	    struct xnspacket d_xns;
X	} e_data;
X    } p_ether;
X} packet;
END_OF_packet.h
if test 6347 -ne `wc -c <packet.h`; then
    echo shar: \"packet.h\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f rlog.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"rlog.c\"
else
echo shar: Extracting \"rlog.c\" \(20469 characters\)
sed "s/^X//" >rlog.c <<'END_OF_rlog.c'
X/*
X * Copyright (c) 1988 Philip L. Budne and The Trustees of Boston University
X * All Rights Reserved
X *
X * Permission is granted to any individual or institution to use, copy,
X * or redistribute this software so long as it is not sold for profit,
X * provided that this notice and the original copyright notices are
X * retained.  Boston University makes no representations about the
X * suitability of this software for any purpose.  It is provided "as is"
X * without express or implied warranty.
X */
X# include <stdio.h>
X# include <ctype.h>
X# include "packet.h"
X
X# define EP_PUP		0x0200
X# define EP_XNS		0x0600
X# define EP_IP		0x0800
X# define EP_CHAOS	0x0804
X# define EP_ARP		0x0806
X# define EP_TRAIL	0x1000		/* TO DO! */
X# define EP_RARP	0x8035		/* TO DO! */
X# define EP_CTP		0x9000
X
Xint	dumpdata = 1;
Xint	indent = 0;
X
X/* counts: */
Xint	count		= 0;
Xint	 ipcount	= 0;
Xint	  icmpcount	= 0;
Xint	  tcpcount	= 0;
Xint	  udpcount	= 0;
Xint	  ndcount	= 0;
Xint	  ippupcount	= 0;
Xint	  ipidpcount	= 0;
Xint	  egpcount	= 0;
Xint	  ggpcount	= 0;
Xint	  ipfragcount   = 0;
Xint	  ipothercount	= 0;
Xint	  ipbadvercount	= 0;
Xint	 arpcount	= 0;
Xint	 rarpcount	= 0;
Xint	 ieeecount	= 0;
Xint	 pupcount	= 0;
Xint	 xnscount	= 0;
Xint	 othercount	= 0;
Xint	 ctpcount	= 0;
X
X/****************************************************************/
X# include "protocol.h"
Xint pr_count[ NPROTO ];
X/****************************************************************/
X
Xint pc;					/* packet byte count */
X
Xmain() {
X    char line[ 4096 ];
X    register byte *pp;
X    register char *lp;
X
X    pc = 0;
X    pp = packet.p_bytes;
X    while( gets( line ) ) {
X	if( line[0] == ' ' || line[0] == '*' || line[0] == '\0' ) {
X	    if( pc > 0 )
X		process();
X	    pp = packet.p_bytes;
X	    pc = 0;
X	    continue;
X	}
X
X	for( lp = line; *lp; lp++ ) {
X	    if( isspace( *lp ) )
X		continue;
X	    else if( isxdigit( *lp ) && isxdigit( lp[1] ) ) {
X		*pp++ = xval( *lp, lp[1] );
X		lp++;
X		pc++;
X	    }
X	    else
X		fprintf( stderr, "you lose: %s\n", lp );
X	}
X    }
X    if( pc > 0 )
X	process();
X    dump_stats();
X}
X
Xprocess() {
X    register struct etherpacket *e = (struct etherpacket *) &packet;
X    u_short type;
X
X    count++;
X
X    terpri();
X    printf("Packet #%d\n", count );
X
X    type = packet.p_ether.e_type;
X    printf("Ether type %02X-%02X len %d ",
X	   (type >> 8) & 255, type & 255, pc );
X
X
X    petaddr( e->e_src );
X    putchar(' ');
X    putchar('>');
X    putchar(' ');
X    petaddr( e->e_dst );
X    terpri();
X
X    switch( type ) {
X    case EP_PUP:
X	process_pup();
X	break;
X    case EP_IP:
X	process_ip( 1, &packet.p_ether.e_data.d_ip );
X	break;
X    case EP_ARP:
X	process_arp();
X	break;
X    case EP_RARP:
X	process_rarp();
X	break;
X    case EP_XNS:
X	process_xns();
X	break;
X    case EP_CTP:
X	process_ctp();
X	break;
X    default:
X# ifdef IEEE
X	if( packet.p_ether.e_type < 0x0600 )
X	    process_ieee( type );
X	else
X# endif /* IEEE defined */
X	    process_other( type );
X	break;
X    }
X    fflush( stdout );
X    fflush( stderr );
X}
X
Xprocess_ip( live, i )
X    int live;				/* true if a real packet */
X					/* false for icmp sent headers */
X    register struct ipheader *i;
X{
X    register byte *d, *op;
X    int size;
X
X    if( live) 
X	ipcount++;
X
X    if( i->ip_ver != 4 ) {
X	printf("IP version not 4 (%d)", i->ip_ver );
X	terpri();
X	ipbadvercount++;
X	return;
X    }
X
X    printf("IP ");
X    pipaddr( 1, i->ip_src );
X    printf(" > ");
X    pipaddr( 1, i->ip_dst );
X
X    printf(" len %d",i->ip_len );
X
X    if( i->ip_flgs & IP_FLG_DF )	/* don't frag */
X	printf(" df");
X
X    if( i->ip_flgs & IP_FLG_MF )	/* more frags/last frag */
X	printf(" mf");
X
X/*    if( i->ip_ttl != 0 && i->ip_ttl != 255 ) /**/
X	printf(" ttl %d", i->ip_ttl );
X
X    if( i->ip_tsrv != 0 ) {
X	if( (i->ip_tsrv>>5) & 07 )
X	    printf(" prec %d", ((i->ip_tsrv>>5) & 07) );
X	if( i->ip_tsrv & 020 )
X	    printf(" low_delay");
X	if( i->ip_tsrv & 010 )
X	    printf(" hi_thruput");
X	if( i->ip_tsrv & 04 )
X	    printf(" hi_rely");
X    }
X
X    /* more frags or offset? */
X    printf(" id %d", i->ip_id );
X    printf(" off %d", i->ip_foff << 3 );
X
X    if( (i->ip_flgs & (IP_FLG_MF|IP_FLG_DF)) || i->ip_foff != 0 ) {
X	if( i->ip_foff ) {
X	    if( live )
X		ipfragcount++;
X	}
X    }
X    terpri();
X
X    d = ((byte *)(i)) + (i->ip_ihl << 2); /* point to data */
X
X    /* options processing!! never tested */
X    op = i->ip_options;
X    while( op < d ) {
X	if( *op & 0200 )
X	    printf(" copy");
X
X	switch( ((*op)>>5)&03 ) {	/* print option class */
X					/* perhaps only for unkn types? */
X	case 0:
X	    printf(" control");
X	    break;
X	case 2:
X	    printf(" debug/meas");
X	    break;
X	case 1:
X	    printf(" reserved1");
X	    break;
X	case 3:
X	    printf(" reserved3");
X	    break;
X	}
X
X	switch( (*op) & 017 ) {
X	case 0:				/* end of list */
X	    goto end_of_options;
X	    
X	case 1:
X	    printf(" noop");
X	    op++;
X	    break;
X	    
X	case 2:
X	    printf(" security %02X %02X", op[2], op[3] );
X	    op += op[1];			/* should be 11 */
X	    break;
X	    
X	case 3:
X	    printf(" LS+RR");		/* loose source */
X	    /* print more info! */
X	    op += op[1];
X	    break;
X	    
X	case 4:
X	    printf(" TIMESTAMP");
X	    switch( op[3] &0xf ) {
X	    case 0:
X		break;			/* time stamps only */
X	    case 1:
X		printf("+ADDRESS");
X		break;
X		
X	    case 2:
X		printf(" ?flag 2?");
X		break;
X		
X	    case 3:
X		printf(" (prespec)");
X		break;
X	    }
X	    
X	    if( op[3] & 0xf0 )
X		printf(" %d overflows", (op[3]>>4)&0xf );
X	    
X	    op += op[1];
X	    break;
X	    
X	case 7:
X	    printf(" RR");
X	    /* print more info! */
X	    op += op[1];
X	    break;
X	    
X	case 8:
X	    printf(" SATNET_Stream_ID");
X	    /* print more info! */
X	    op += op[1];			/* should be 4 */
X	    break;
X	    
X	case 9:
X	    printf(" SS+RR");		/* strict source */
X	    /* print more info! */
X	    op += op[1];
X	    break;
X	    
X	default:
X	    printf(" option %d.", *op&017 );
X	    op += op[1];
X	    break;
X	} /* switch on option number */
X	terpri();
X    } /* while op */
X
Xend_of_options: ;
X
X    if( i->ip_foff != 0 && live ) {
X	printf("  FRAGMENT (proto %d.)", i->ip_prot );
X	terpri();
X	return;				/* ?? */
X    }
X
X    size = pc - (d - packet.p_bytes);
X
X    switch( i->ip_prot ) {
X    case IP_PROT_UDP:
X	if( live )
X	    udpcount++;
X	process_ip_udp( d, size );
X	break;
X    case IP_PROT_TCP:
X	if( live )
X	    tcpcount++;
X	process_ip_tcp( d, size );
X	break;
X    case IP_PROT_ND:
X	if( live )
X	    ndcount++;
X	process_ip_nd( d, size );
X	break;
X    case IP_PROT_ICMP:
X	if( live )
X	    icmpcount++;
X	process_ip_icmp( d );
X	break;
X    case IP_PROT_GGP:
X	printf("GGP");
X	terpri();
X	if( live )
X	    ggpcount++;
X	/* process?? */
X	break;
X    case IP_PROT_EGP:
X	printf("EGP");
X	terpri();
X	if( live )
X	    egpcount++;
X	/* process?? */
X	break;
X    case IP_PROT_PUP:
X	printf("PUP-IP");
X	terpri();
X	if( live )
X	    ippupcount++;
X	break;
X    case IP_PROT_IDP:			/* xns idp */
X	printf("IDP-IP (xns)");
X	terpri();
X	if( live )
X	    ipidpcount++;
X	/* process?? */
X	break;
X    default:
X	printf(" ipproto %d", i->ip_prot );
X	terpri();
X	if( live )
X	    ipothercount++;
X    }
X}
X
Xprocess_ip_udp( d )
Xbyte *d;
X{
X    register struct udpheader *u = (struct udpheader *) d;
X    printf("UDP srcp: %d destp: %d", u->udp_srcp, u->udp_dstp );
X    terpri();
X}
X
Xprocess_ip_tcp( d, size )
Xbyte *d;
X{
X    register struct tcpheader *t = (struct tcpheader *) d;
X    register byte *o, *td;
X    int c, l;
X
X    printf("TCP srcp: %d destp: %d", t->tcp_srcp, t->tcp_dstp );
X
X    if( t->tcp_furg )
X	printf(" urg %#x", t->tcp_urg );
X    if( t->tcp_fack )
X	printf(" ack %#x", t->tcp_ack );
X    if( t->tcp_psh )
X	printf(" psh");
X    if( t->tcp_rst )
X	printf(" rst");
X    if( t->tcp_syn )
X	printf(" syn");
X    if( t->tcp_fin )
X	printf(" fin");
X    printf(" window %d.", t->tcp_win );
X
X    c = ((t->tcp_thl) << 2);		/* get tcp data offset */
X
X    size -= c;				/* get size of data */
X    td = d + c;				/* start of tcp data */
X
X    printf(" data %d.", size );
X
X    o = d + sizeof( struct tcpheader );	/* get start of options */
X    c -= sizeof( struct tcpheader );	/* get size of options */
X
X    while( c > 0 ) {			/* process tcp options */
X	switch( *o ) {
X	case 0:				/* end of list */
X	    goto break_options_loop;
X
X	case 1:				/* nop */
X	    l = 1;
X	    break;
X
X	case 2:				/* mss */
X	    l = o[1];
X	    if( l != 4 ) {
X		printf("BAD_mss"); 
X	    }
X	    else
X		printf(" mss %d", *((u_short *)(&o[2])) );
X	    break;
X
X	default:
X	    l = o[1];
X	    printf(" option %d. (len %d.)", *o, l );
X	    break;
X	} /* switch */
X	o += l;
X	c -= l;
X    } /* tcp options loop */
X break_options_loop:;
X
X    terpri();
X
X    if( dumpdata ) {
X	while( size-- > 0 )
X	    putbyte( *td++ );
X	terpri();
X    }
X} /* process_ip_tcp */
X
Xputbyte( c ) {
X    if( c >= ' ' && c <= 0176 )
X	putchar( c );
X    else
X	switch( c ) {
X	case '\n':
X	    printf("\\n");
X	    break;
X	case '\r':
X	    printf("\\r");
X	    break;
X	case '\f':
X	    printf("\\f");
X	    break;
X	/* ** MORE ESCAPES ** @@ */
X	default:
X	    printf("\\%#o", c & 0xff );
X	    break;
X	} /* switch */
X} /* putbyte */
X
Xprocess_ip_icmp( d )
Xbyte *d;
X{
X    register struct icmppacket {
X	byte icmp_type, icmp_code;
X	u_short icmp_cksum;
X	union {
X	    u_short id_short[2];
X	    u_long  id_long[1];
X	    byte    id_byte[4];
X	} icmp_data;
X	struct ipheader icmp_ip;
X    } *i = (struct icmppacket *) d;
X
X    static char *icmp_unreach_names[] = {
X	"net", "host", "proto", "port", "need frag", "srcroute failed" };
X# define N_ICMP_UNREACH_NAMES (sizeof( icmp_unreach_names ) / sizeof( char * ))
X
X    printf("ICMP ");
X    switch( i->icmp_type ) {
X    case 0:				/* ECHOREPLY */
X    case 8:				/* ECHO */
X	printf("echo");
X	if( i->icmp_type == 0 )
X	    printf(" reply");
X	printf(" id %d seq %d data: ",
X	       i->icmp_data.id_short[0], i->icmp_data.id_short[1] );
X	pbytes( &i->icmp_data.id_byte[4], 16 );
X	terpri();
X	return;
X	break;
X
X    case 3:				/* ICMP_UNREACH */
X	if( i->icmp_code < N_ICMP_UNREACH_NAMES )
X	    printf("unreachable %s", icmp_unreach_names[ i->icmp_code ] );
X	else
X	    printf("unreachable (code %d)", i->icmp_code );
X	break;
X
X    case 4:
X	printf("source quench");
X	break;
X
X    case 5:				/* ICMP_REDIRECT */
X	printf("redirect");
X	if( i->icmp_code == 0 )
X	    printf(" net");
X	else if( i->icmp_code == 1 )
X	    printf(" host");
X	else if( i->icmp_code == 2 )
X	    printf(" tos/net");
X	else if( i->icmp_code == 3 )
X	    printf(" tos/host");
X	else
X	    printf(" (code %d)", i->icmp_code );
X	printf(" to ");
X	pipaddr( 1, i->icmp_data.id_long[0] );
X	break;
X
X    case 11:
X	switch( i->icmp_code ) {
X	case 0:
X	    printf("ttl exceeded");
X	    break;
X	case 1:
X	    printf("reassembly ttl exceeded");
X	    break;
X	default:
X	    printf("time exceeded code %d", i->icmp_code );
X	    break;
X	}
X	break;
X
X    case 12:
X	printf("parmeter problem at %d", i->icmp_data.id_byte[0] );
X	break;
X
X    case 13:
X    case 14:
X	printf("timestamp");
X	if( i->icmp_type == 14 )
X	    printf(" reply");
X	printf(" id %d seq %d",
X	       i->icmp_data.id_short[0], i->icmp_data.id_short[1] );
X	terpri();
X	printf("orig ");
X	ptime( i->icmp_data.id_long[1] );
X
X	if( i->icmp_type == 14 ) {	/* reply */
X	    printf(" rcv ");
X	    ptime( i->icmp_data.id_long[2] );
X	    printf(" xmit ");
X	    ptime( i->icmp_data.id_long[3] );
X	}
X	terpri();
X	return;
X	break;
X
X    case 15:
X	printf("info request id %d seq %d",
X	       i->icmp_data.id_short[0], i->icmp_data.id_short[1] );
X	terpri();
X	return;
X	break;
X
X    case 16:
X	printf("info reply id %d seq %d",
X	       i->icmp_data.id_short[0], i->icmp_data.id_short[1] );
X	terpri();
X	return;
X	break;
X
X    case 17:
X	printf("mask request id %d seq %d",
X	       i->icmp_data.id_short[0], i->icmp_data.id_short[1] );
X	terpri();
X	return;				/* no enacpsulated packet */
X	break;
X
X    case 18:
X	printf("mask reply id %d seq %d ",
X	       i->icmp_data.id_short[0], i->icmp_data.id_short[1] );
X	pipaddr( 0, i->icmp_data.id_long[1] );
X	terpri();
X	return;				/* no enacpsulated packet */
X	break;
X
X    default:
X	printf("type %d", i->icmp_type );
X	if( i->icmp_code != 0 )
X	    printf(" (code %d)", i->icmp_code );
X	printf(" data: ");
X	pbytes( i->icmp_data.id_byte, 4 );
X	terpri();
X	return;				/* no enacpsulated packet?? */
X	break;
X    }
X
X    indent += 4;
X    terpri();
X    process_ip( 0, &i->icmp_ip );	/* RECURSE!! */
X    indent -= 4;
X    terpri();
X}
X
Xptime( t )
Xu_long t;
X{
X    int h, m, s;
X    if( t & 0x40000000 ) {
X	printf( "%d.", t & 0xbfffffff );
X	return;
X    }
X    s = t / 1000;
X    m = s / 60;
X    h = m / 60;
X
X    m %= 60;
X    s %= 60;
X    t %= 1000;
X    if( h > 0 )
X	printf("%dh", h );
X    if( m > 0 )
X	printf("%dm", m  );
X    printf("%d.%03d", s, t );
X}
X
Xprocess_ip_nd( d )
Xbyte *d;
X{
X    register struct ndpacket *n = (struct ndpacket *) d;
X
X    printf("ND");
X
X    switch( n->nd_op & 7 ) {
X    case 1:
X	printf(" read");
X	break;
X    case 2:
X	printf(" write");
X	break;
X    case 3:
X	printf(" error");
X	break;
X    default:
X	printf(" op %d", n->nd_op & 7 );
X	break;
X    }
X    if( n->nd_op & 010 )
X	printf(" wait");
X    if( n->nd_op & 020 )
X	printf(" done");
X
X    printf(" /dev/nd");
X    if( n->nd_dev > 0177 )
X	putchar('l');
X    else if( n->nd_dev > 077 )
X	putchar('p');
X    printf("%d seq %d",  n->nd_dev & 077, n->nd_seq );
X    printf(" block %d count %d",
X	   n->nd_blk, n->nd_count);
X    if( n->nd_res > 0 )
X	printf(" resid %d", n->nd_res );
X    if( n->nd_off > 0 )
X	printf(" off %d",
X	       n->nd_off );
X    if( n->nd_data > 0 )
X	printf(" data %d",
X	       n->nd_data );
X    terpri();
X}
X
Xprocess_arp() {
X    arpcount++;
X    printf("ARP");
X    process_arp2(0);
X}
X
X# define EA_NZERO(p) ( (*(long *)p) != 0 && (*(short *)(p+4)) != 0 )
X
Xprocess_arp2(israrp) {
X    register struct arppacket *a = &packet.p_ether.e_data.d_arp;
X    register struct protocol *pp;
X    int xsha, xspa, xtha, xtpa;
X    ip_addr i;
X
X    xsha = 0;				/* sender hdw addr */
X    xspa = a->arp_hln;			/* sender proto addr */
X    xtha = xspa + a->arp_pln;		/* target hdw addr */
X    xtpa = xtha + a->arp_hln;		/* target proto addr */
X
X    switch( a->arp_hw ) {
X    case ARP_HW_ETHER:
X	break;
X    case ARP_HW_XETHER:
X	printf(" 3Mb ether");
X	break;
X    case ARP_HW_AX25:
X	printf(" AX.25");
X	break;
X    case ARP_HW_PRONET:
X	printf(" PROnet");
X	break;
X    case ARP_HW_CHAOS:
X	printf(" Chaos");
X	break;
X    case ARP_HW_IEEE802:
X	printf(" IEEE 802");
X	break;
X    }
X
X    switch( a->arp_pro ) {
X    case EP_IP:
X    case EP_TRAIL:
X	printf(" IP");
X	if( a->arp_pro == EP_TRAIL )
X	    printf(" trailers");
X	if( a->arp_op == ARP_REQUEST )
X	    printf(" request ");
X	else if( a->arp_op == RARP_REQUEST )
X	    printf(" reverse request ");
X	else if( a->arp_op == RARP_REPLY )
X	    printf(" reverse reply ");
X	else
X	    printf(" op %d ", a->arp_op );
X
X	printf("source");
X	if( EA_NZERO( a->arp_data + xsha ) ) {
X	    putchar(' ');
X	    petaddr( a->arp_data + xsha );
X	}
X	i = * (ip_addr *) (a->arp_data + xspa);
X	if( i != 0 ) {
X	    putchar(' ');
X	    pipaddr( 1, i );
X	}
X	terpri();
X
X	printf("target");
X	if( EA_NZERO( a->arp_data + xtha ) ) {
X	    putchar(' ');
X	    petaddr( a->arp_data + xtha );
X	}
X	i = * (ip_addr *) (a->arp_data + xtpa);
X	if( i != 0 ) {
X	    putchar(' ');
X	    pipaddr( 1, i );
X	}
X	terpri();
X	return;
X
X    case EP_CHAOS:
X	printf(" CHAOS ");
X	if( a->arp_op == ARP_REQUEST )
X	    printf(" request ");
X	else if( a->arp_op == ARP_REPLY )
X	    printf(" reply to ");
X	else
X	    printf("op %d ", a->arp_op );
X
X	printf("source ");
X	petaddr( a->arp_data + xsha );
X	putchar( ' ' );
X	printf("%#o ", * (u_short *) (a->arp_data + xspa) );
X	terpri();
X
X	printf("target ");
X	petaddr( a->arp_data + xtha );
X	putchar(' ');
X	printf("%#o ", * (u_short *) (a->arp_data + xtpa) );
X	terpri();
X
X	return;
X
X    default:
X	for( pp = protocols; pp->pr_type != 0; pp++ )
X	    if( a->arp_pro == pp->pr_type ) {
X		printf("%s ???", pp->pr_name );
X		terpri();
X		return;
X	    }
X	printf("%02X-%02X ???", (a->arp_pro >> 8) & 255,
X	       a->arp_pro & 255 );
X	terpri();
X    }
X}
X
Xprocess_ieee( l )
Xu_short l;
X{
X    ieeecount++;
X    printf("IEEE len %d", l );
X    terpri();
X}
X
Xprocess_pup() {
X    register struct puppacket *p = &packet.p_ether.e_data.d_pup;
X    pupcount++;
X    printf("PUP len %d transport %d type %#o id %d",
X	   p->pup_len, p->pup_transport, p->pup_type );
X    terpri();
X    printf("src net %#o host %#o socket %#o",
X	   p->pup_src.pup_port_net,
X	   p->pup_src.pup_port_host,
X	   (p->pup_src.pup_port_sock1) << 16 +
X	   p->pup_src.pup_port_sock2 );
X    terpri();
X    printf("dst net %#o host %#o socket %#o",
X	   p->pup_dst.pup_port_net,
X	   p->pup_dst.pup_port_host,
X	   (p->pup_dst.pup_port_sock1) << 16 +
X	   p->pup_dst.pup_port_sock2 );
X    terpri();
X}
X
Xprocess_rarp() {
X    rarpcount++;
X    printf("RARP");
X    process_arp2(1);
X}
X
X# define CTP_REP 1
X# define CTP_FWD 2
X# define CTP_SHORT(sp) (*sp | (sp[1]<<8))
X
Xprocess_ctp() {
X    byte *p2, *p = packet.p_ether.e_data.d_bytes;
X    short f, skip;
X    int len, l2;
X
X    ctpcount++;
X    skip = CTP_SHORT(p);
X    p2 = p + skip + 2;			/* point to data (skip skip!) */
X    len = pc - 14 - skip - 2;		/* length of data */
X
X    printf("CTP skip %d.", skip );
X    terpri();
X    for( ; ; ) {
X	if( len < 2 )
X	    return;
X
X	f = CTP_SHORT( p2 );		/* get function */
X	p2 += 2;			/* advance past function */
X	len -= 2;			/* account for function length */
X	switch( f ) {
X	case CTP_REP:			/* reply */
X	    printf(" REPLY data: ");
X	    goto break_for;
X	    break;
X
X	case CTP_FWD:			/* forward */
X	    if( len < 6 ) {
X		printf("Too little data for FORWARD packet");
X		terpri();
X		return;
X	    }
X	    printf(" FORWARD to: ");
X	    petaddr( p2 );		/* print ether addr */
X	    terpri();
X	    p2 += 6;			/* advance data */
X	    len -=6;			/* account for len */
X	    break;
X
X	default:
X	    printf(" fncn %d. data: ", f );
X	    goto break_for;
X	}
X    }
X break_for: ;
X    l2 = len;
X    if( l2 > 32 )
X	l2 = 32;
X    pbytes( p2, l2 );
X    if( len > 32 )
X	printf("...");
X    terpri();
X}
X
Xprocess_xns() {
X    register struct xnspacket *x = &packet.p_ether.e_data.d_xns;
X    xnscount++;
X    printf("XNS IDP len %d transport %d type %d",
X	   x->xns_len, x->xns_tc, x->xns_pt );
X    terpri();
X    printf("src: ");
X    pxnsaddr( &x->xns_src );
X    terpri();
X
X    printf("dst: ");
X    pxnsaddr( &x->xns_dst );
X    terpri();
X}
X
Xpxnsaddr( xa )
X    register struct xns_addr *xa;
X{
X    pbytes( xa->xnsa_net, 4 );
X    putchar(':');
X    pbytes( xa->xnsa_host, 6 );
X    printf(" port %d", xa->xnsa_port );
X}
X
Xprocess_other( type )
Xint type;
X{
X    register struct protocol *pp;
X    register int i;
X
X    for( i = 0, pp = protocols; pp->pr_type != 0; i++, pp++ )
X	if( type == pp->pr_type ) {
X	    printf( "%s", pp->pr_name );
X	    terpri();
X	    pr_count[ i ]++;
X	    pbytes( packet.p_ether.e_data.d_bytes, 32 );
X	    printf("...");
X	    terpri();
X	    return;
X	}
X	else if( type < pp->pr_type )
X	    break;
X    pbytes( packet.p_ether.e_data.d_bytes, 32 );
X    printf("...");
X    terpri();
X    othercount++;
X}
X
Xdump_stats() {
X    register struct protocol *pp;
X    int i;
X
X    if( count > 0 )
X	fprintf( stderr, "count: %d\n", count );
X    if( ipcount > 0 )
X	fprintf( stderr, " ipcount: %d\n", ipcount );
X    if( icmpcount > 0 )
X	fprintf( stderr, "  icmpcount: %d\n", icmpcount );
X    if( tcpcount > 0 )
X	fprintf( stderr, "  tcpcount: %d\n", tcpcount );
X    if( udpcount > 0 )
X	fprintf( stderr, "  udpcount: %d\n", udpcount );
X    if( ndcount > 0 )
X	fprintf( stderr, "  ndcount: %d\n", ndcount );
X    if( egpcount > 0 )
X	fprintf( stderr, "  egpcount: %d\n", egpcount );
X    if( ggpcount > 0 )
X	fprintf( stderr, "  ggpcount: %d\n", ggpcount );
X    if( ippupcount > 0 )
X	fprintf( stderr, "  ippupcount: %d\n", ippupcount );
X    if( ipidpcount > 0 )
X	fprintf( stderr, "  ipidpcount: %d\n", ipidpcount );
X    if( ipfragcount > 0 )
X	fprintf( stderr, "  ipfragcount: %d\n", ipfragcount );
X    if( ipothercount > 0 )
X	fprintf( stderr, "  ipothercount: %d\n", ipothercount );
X    if( ipbadvercount > 0 )
X	fprintf( stderr, "  ipbadvercount: %d\n", ipbadvercount );
X    if( arpcount > 0 )
X	fprintf( stderr, " arpcount: %d\n", arpcount );
X    if( rarpcount > 0 )
X	fprintf( stderr, " rarpcount: %d\n", rarpcount );
X    if( ieeecount > 0 )
X	fprintf( stderr, " ieeecount: %d\n", ieeecount );
X    if( pupcount > 0 )
X	fprintf( stderr, " pupcount: %d\n", pupcount );
X    if( xnscount > 0 )
X	fprintf( stderr, " xnscount: %d\n", xnscount );
X    if( ctpcount > 0 )
X	fprintf( stderr, " ctpcount: %d\n", ctpcount );
X
X    for( i = 0, pp = protocols; pp->pr_type != 0; i++, pp++ )
X	if( pr_count[i] > 0 )
X	    fprintf( stderr, " %s: %d\n", pp->pr_name, pr_count[i] );
X
X    if( othercount > 0 )
X	fprintf( stderr, " othercount: %d\n", othercount );
X}
X
Xterpri() {
X    register int i = indent;
X    putchar( '\n' );
X    while( i-- > 0 )
X	putchar( ' ' );
X}
END_OF_rlog.c
if test 20469 -ne `wc -c <rlog.c`; then
    echo shar: \"rlog.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
echo shar: End of archive 2 \(of 2\).
cp /dev/null ark2isdone
MISSING=""
for I in 1 2 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked both archives.
    rm -f ark[1-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0