From: pwolfe@kai.com (Patrick Wolfe)
Subject: Re: Indigo-Indigo Ethernet problem
Organization: Kuck and Associates, Champaign IL
Distribution: na
Date: Fri, 16 Oct 1992 01:52:18 GMT

>olson@anchor.esd.sgi.com (Dave Olson) writes:
>>You could watch it with netsnoop if you have that software.  There
>>are also some similar packages for Sun's.

dave@imax.imax.com (Dave Martindale) writes:
>Unfortunately, I don't have any snooping software at the moment.

Fortunately, Irix comes with the wonderful SNOOP(7P) routines for this
purpose.  I'm including the source to a tool I wrote a long time ago,
when we had network troubles, and didn't have any snooping software.

It requires root privs to run, and compiles and runs under Irix 4.0.x.
I originally wrote it under irix 3.3, but don't know what changes would be
neccessary to compile it there anymore.

-- cut here --- cut here --- cut here --- cut here --- cut here --- cut here --
#!/bin/sh
# This is a shell archive (produced by shar 3.49)
# To extract the files from this archive, save it to a file, remove
# everything above the "!/bin/sh" line above, and type "sh file_name".
#
# made 10/16/1992 01:45 UTC by pwolfe@blizzard
# Source directory /usr/src/etc/network/netmon
#
# existing files will NOT be overwritten unless -c is specified
#
# This shar contains:
# length  mode       name
# ------ ---------- ------------------------------------------
#   1598 -rw-r--r-- Readme
#    825 -rw-rw-rw- Makefile
#   4071 -rw-r--r-- main.c
#   2241 -r--r--r-- ip.c
#   8299 -rw-r--r-- udp.c
#   7601 -rw-r--r-- misc.c
#     48 -rw-r--r-- arp_table
#   2176 -rw-rw-rw- netmon.h
#   4305 -r--r--r-- udp.h
#
# ============= Readme ==============
if test -f 'Readme' -a X"$1" != X"-c"; then
	echo 'x - skipping Readme (File already exists)'
else
echo 'x - extracting Readme (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'Readme' &&
This is my network monitor.  It runs on SGI Irix 4.0.x.  Hopefully you will
find this useful, either as is, or as a base for something fancier.
X
I've used this as a base for a slew of other more specialized tools.  It's
not too hard to use SGI's SNOOP(7P) protocol for network monitoring, but it
does require root privs to put the network interface into promiscous mode.
X
Basically, the usage is:
X
X	netmon [-b] [[host1] [host2]]
X
-b watches broadcast packets
X
If no options are given, every packet on the net is listed.
X
You can specify just one hostname when one host is giving you trouble (I
usually also use -b), or two hostnames to watch just one conversation.  I wrote
this because we were having networking troubles, and there was nothing
available on the Internet - just commercial packages.
X
I have hardcoded our hostnames and ethernet hardware addresses in
/etc/arp_table.  I later learned about the /etc/ethers file, which we aren't
using, but if you want to, the file to modify is misc.c When you want to put
your hosts in "arp_table", access it via rsh or even ping, then run "arp
-a".
X
X
Interprets and identifies lots of different packet types, including
the following protocols:
X
X	IP
X	TCP
X	rlogin
X	X windows
X	UDP
X	NFS
X	ARP
X	PUP
X
The NFS packets are interpreted down to the request level.  I haven't had time
to interpret them any further.  Rlogin and X windows packets are recognized by
the common ports they use, not by their protocol.
X
Good Luck!
X
X        Patrick Wolfe  (pwolfe@kai.com, uunet!uiucuxc!kailand!pwolfe)
X        System Programmer/Operations Manager, Kuck & Associates
SHAR_EOF
chmod 0644 Readme ||
echo 'restore of Readme failed'
Wc_c="`wc -c < 'Readme'`"
test 1598 -eq "$Wc_c" ||
	echo 'Readme: original size 1598, current size' "$Wc_c"
fi
# ============= Makefile ==============
if test -f 'Makefile' -a X"$1" != X"-c"; then
	echo 'x - skipping Makefile (File already exists)'
else
echo 'x - extracting Makefile (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'Makefile' &&
# Makefile for netmon - network monitor for SGI Irix
# known to run on Irix 4.0
#
# requires /etc/arp_table file of ethernet hardware addresses and hostnames
#	- see arp(1M) -f option for format
X
# had problems with getopt with -O and -O3, hmmmm.
X
#CFLAGS = -g -DDEBUG
CFLAGS = -O -s
BIN = /usr/local/etc
LIBS = -lsun
LINTOPTS =
X
FILES = Readme Makefile $(SRCS) arp_table netmon.h udp.h
SRCS = main.c ip.c udp.c misc.c
OBJS = main.o ip.o udp.o misc.o
X
netmon: $(OBJS)
X	$(CC) $(CFLAGS) -o netmon $(OBJS) $(LIBS)
X
install: netmon
X	install -r -l -c -o root -m 4711 netmon $(BIN)
X
lint:
X	lint $(LINTOPTS) $(SRCS)
X
clean:
X	rm -f a.out core mklog netmon *.o netmon.shar
X
shar: $(FILES)
X	shar $(FILES) > netmon.shar
X
tar: $(FILES)
X	tar cvf netmon.tar $(FILES)
X
main.o: netmon.h
ip.o: netmon.h
misc.o: netmon.h
udp.o: netmon.h udp.h
SHAR_EOF
chmod 0666 Makefile ||
echo 'restore of Makefile failed'
Wc_c="`wc -c < 'Makefile'`"
test 825 -eq "$Wc_c" ||
	echo 'Makefile: original size 825, current size' "$Wc_c"
fi
# ============= main.c ==============
if test -f 'main.c' -a X"$1" != X"-c"; then
	echo 'x - skipping main.c (File already exists)'
else
echo 'x - extracting main.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'main.c' &&
/*
X * network monitor program
X * Original Author: Patrick Wolfe (pwolfe@kai.com, kailand!pwolfe)
X */
#include "netmon.h"
X	/* for schedctl() */
#include <limits.h>
#include <sys/prctl.h>
#include <sys/schedctl.h>
X
extern void ip_interpret (struct IPpacket *),
X	arp_interpret (struct ether_arp *);
X
short	trace_broadcast = 0,
X	trace_unknown = 0;
int	NumHosts = -1,
X	stopit = 0,
X	debug = 0;
u_char	eaddr_table[MaxHosts][6];
char	hostname[MaxHosts][64];
X
X
/*
X * need to speed this up a LOT - sorting the table at read time
X * and doing a binary search here would probably work better
X */
int
findhost (u_char eaddr[6])
{
int hostctr, bytectr;
X
for (hostctr = 1; (hostctr <= NumHosts); hostctr++) {
X	for (bytectr = 0; (bytectr <= 5) && (eaddr[bytectr] == eaddr_table[hostctr][bytectr]); bytectr++);
X	if (bytectr > 5) {
X		return (hostctr);
X		}
X	}
return (0);
}
X
X
main (argc, argv)
int argc;
char **argv;
{
struct etherpacket ep;
struct tm *tp;
int s, cc;
int shost, dhost;
X
parse_cmdline (argc, argv);
read_arp_table (ARP_TABLE);
catch_sigs ();
fprintf (stdout, "netmon starting\n");
(void) schedctl (NDPRI, 0, NDPHIMIN);
s = start_snooping ();
X
/*
X *	read some packets
X */
while (stopit == 0) {
X	cc = read (s, (char *) &ep, sizeof ep);
X	if ((cc < 0) && (errno == EINTR)) {
X		continue;
X		}
X	if (cc <= 0) {
X		break;
X		}
X
X	shost = findhost (ep.ether.ether_shost);
X	dhost = findhost (ep.ether.ether_dhost);
X
X	/* when looking for unknown hosts, skip packets for known hosts */
X	if (trace_unknown && (shost > 0) && (dhost > 0)) {
X		/* also check to see if we're interested in broadcast packets */
X		if (! trace_broadcast || (shost > 2) && (dhost > 2)) {
X			continue;
X			}
X		}
X
X	tp = localtime (&ep.snoop.snoop_timestamp.tv_sec);
X	fprintf (stdout, "%02d:%02d:%02d ", tp->tm_hour, tp->tm_min, tp->tm_sec);
X
X	if (shost > 0) {
#ifdef USE_FPUTS
X		fputs (hostname[shost], stdout);
#else
X		fprintf (stdout, "%-10s", hostname[shost]);
#endif
X		}
X	else	{
X		fprintf (stdout, "%X:%X:%X:%X:%X:%X",
X		  	ep.ether.ether_shost[0], ep.ether.ether_shost[1], ep.ether.ether_shost[2],
X		  	ep.ether.ether_shost[3], ep.ether.ether_shost[4], ep.ether.ether_shost[5]);
X		}
X	fputs (" > ", stdout);
X
X	if (dhost > 0) {
#ifdef USE_FPUTS
X		fputs (hostname[dhost], stdout);
#else
X		fprintf (stdout, "%-10s", hostname[dhost]);
#endif
X		}
X	else	{
X		fprintf (stdout, "%X:%X:%X:%X:%X:%X",
X		  	ep.ether.ether_dhost[0], ep.ether.ether_dhost[1], ep.ether.ether_dhost[2],
X		  	ep.ether.ether_dhost[3], ep.ether.ether_dhost[4], ep.ether.ether_dhost[5]);
X		}
X	fprintf (stdout, " %5d ", ep.snoop.snoop_packetlen);
X
X	switch (ep.ether.ether_type) {
X
X	case ETHERTYPE_IP:		IP_Interpret ((struct IPpacket *) ep.data); break;
X	case ETHERTYPE_ARP:		ARP_Interpret ((struct ether_arp *) ep.data); break;
X	case ETHERTYPE_PUP:		fputs ("PUP ", stdout); break;
X	case ETHERTYPE_REVARP:		fputs ("REVARP ", stdout); break;
X	case ETHERTYPE_DECMOP:		fputs ("DEC MOP ", stdout); break;
X	case ETHERTYPE_DECCON:		fputs ("DEC console ", stdout); break;
X	case ETHERTYPE_DECnet:		fputs ("DECnet ", stdout); break;
X	case ETHERTYPE_DECLAT:		fputs ("DEC LAT ", stdout); break;
X	case ETHERTYPE_SG_DIAG:		fputs ("SGI diag ", stdout); break;
X	case ETHERTYPE_SG_NETGAMES:	fputs ("SGI netgames ", stdout); break;
X	case ETHERTYPE_SG_RESV:		fputs ("SGI reserved ", stdout); break;
X	case ETHERTYPE_SG_BOUNCE:	fputs ("SGI bounce ", stdout); break;
X	case ETHERTYPE_APPLETALK:	fputs ("appletalk ", stdout); break;
X	case ETHERTYPE_AARP:		fputs ("appletalk arp ", stdout); break;
X	case ETHERTYPE_XTP:		fputs ("XTP ", stdout); break;
X
X	default:
X		fprintf (stdout, "unknown packet type 0x%X ", ep.ether.ether_type);
X		break;
X		}
X
X	if (ep.snoop.snoop_flags & SN_ERROR) {
X		fputs ("ERROR", stdout);
X		}
X
X	fputc ('\n', stdout);
X	}
X
if ((stopit == 0) && (cc < 0)) {
X	perror ("read");
X	}
X
/* turn snooping OFF */
cc = 0;
if (ioctl (s, SIOCSNOOPING, &cc) < 0) {
X	perror ("ioctl: SIOCSNOOPING OFF");
X	exit (1);
X	}
close (s);
X
if (stopit > 0) {
X	fprintf (stdout, "received signal %d\n", stopit);
X	}
X
fprintf (stdout, "exiting netmon\r\n");
fflush (stdout);
X
exit (0);
}
SHAR_EOF
chmod 0644 main.c ||
echo 'restore of main.c failed'
Wc_c="`wc -c < 'main.c'`"
test 4071 -eq "$Wc_c" ||
	echo 'main.c: original size 4071, current size' "$Wc_c"
fi
# ============= ip.c ==============
if test -f 'ip.c' -a X"$1" != X"-c"; then
	echo 'x - skipping ip.c (File already exists)'
else
echo 'x - extracting ip.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'ip.c' &&
/*
X * network monitor program
X * Original Author: Patrick Wolfe (pwolfe@kai.com, kailand!pwolfe)
X */
#include "netmon.h"
X
extern int debug;
X
X
void
TCP_Interpret (struct TCPpacket *tcpak)
{
if ((tcpak->Source_port == 6000) || (tcpak->Dest_port == 6000)) {
X	fprintf (stdout, "X windows", tcpak->Dest_port);
X	}
else if ((tcpak->Source_port == 513) || (tcpak->Dest_port == 513)) {
X	fprintf (stdout, "rlogin", tcpak->Dest_port);
X	}
else	{
X	fprintf (stdout, "tcp %d>%d", tcpak->Source_port, tcpak->Dest_port);
X	}
}
X
X
void
ARP_Interpret (struct ether_arp *arpak)
{
fputs ("arp ", stdout);
switch (arpak->ea_hdr.ar_op) {
case 0x100:
X	fputs ("request", stdout);
X	break;
case 0x200:
X	fputs ("reply", stdout);
X	break;
case 0x1: /* byteswapped? */
X	fputs ("request (bs)", stdout);
X	break;
case 0x2:
X	fputs ("reply (bs)", stdout);
X	break;
default:
X	fprintf (stdout, "opcode %X  ", arpak->ea_hdr.ar_op);
X	return;
X	}
switch (arpak->ea_hdr.ar_pro) {
case 0x008:		/* IP */
case 0x800: /* byteswapped? */
X	fprintf (stdout, " %X:%X:%X:%X:%X:%X (%d.%d.%d.%d) -> %X:%X:%X:%X:%X:%X (%d.%d.%d.%d)",
X		arpak->arp_sha[0], arpak->arp_sha[1], arpak->arp_sha[2],
X		arpak->arp_sha[3], arpak->arp_sha[4], arpak->arp_sha[5],
X		arpak->arp_spa[0], arpak->arp_spa[1], arpak->arp_spa[2], arpak->arp_spa[3],
X		arpak->arp_tha[0], arpak->arp_tha[1], arpak->arp_tha[2],
X		arpak->arp_tha[3], arpak->arp_tha[4], arpak->arp_tha[5],
X		arpak->arp_tpa[0], arpak->arp_tpa[1], arpak->arp_tpa[2], arpak->arp_tpa[3]);
X	break;
default:
X	fprintf (stdout, "protocol 0x%X ", arpak->ea_hdr.ar_pro);
X	}
}
X
X
void
IP_Interpret (struct IPpacket *ipak)
{
switch (ipak->Protocol) {
case IPPROTO_TCP:	TCP_Interpret ((struct TCPpacket *) ipak->Data); break;
case IPPROTO_UDP:	UDP_Interpret ((struct UDPpacket *) ipak->Data); break;
case IPPROTO_IP:	fputs ("IP/IP ", stdout); break;
case IPPROTO_ICMP:	fputs ("ICMP ", stdout); break;
case IPPROTO_IGMP:	fputs ("IGMP ", stdout); break;
case IPPROTO_GGP:	fputs ("GGP ", stdout); break;
case IPPROTO_EGP:	fputs ("EGP ", stdout); break;
case IPPROTO_PUP:	fputs ("IP/PUP ", stdout); break;
case IPPROTO_IDP:	fputs ("IDP ", stdout); break;
case IPPROTO_RAW:	fputs ("IP/RAW ", stdout); break;
default:		fprintf (stdout, "IP protocol %d ", ipak->Protocol);
X	}
}
SHAR_EOF
chmod 0444 ip.c ||
echo 'restore of ip.c failed'
Wc_c="`wc -c < 'ip.c'`"
test 2241 -eq "$Wc_c" ||
	echo 'ip.c: original size 2241, current size' "$Wc_c"
fi
# ============= udp.c ==============
if test -f 'udp.c' -a X"$1" != X"-c"; then
	echo 'x - skipping udp.c (File already exists)'
else
echo 'x - extracting udp.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'udp.c' &&
/*
X * network monitor program
X * Original Author: Patrick Wolfe (pwolfe@kai.com, kailand!pwolfe)
X */
#include "netmon.h"
#include "udp.h"
X
X
static void
NFS_Interpret (struct rpc_msg *rpcpak, struct UDPpacket *udpak)
{
u_long nfs_proc;
X
nfs_proc = rpcpak->rm_call.cb_proc;
fputs ("nfs ", stdout);
X
if (nfs_proc < RFS_NPROC) {
X	fputs (nfs_procedure[nfs_proc], stdout);
X	}
else	{
X	fprintf (stdout, "procedure 0x%X", nfs_proc);
X	}
}
X
X
static void
RPCcall_Interpret (struct rpc_msg *rpcpak, struct UDPpacket *udpak)
{
switch (rpcpak->rm_call.cb_prog) {
case RPC_NFSPROG:		NFS_Interpret (rpcpak, udpak); break;
case RPC_YPPROG:		fputs ("yp", stdout); break;
case RPC_YPBINDPROG:		fputs ("ypbind", stdout); break;
case RPC_YPPASSWDPROG:		fputs ("yppasswd", stdout); break;
case RPC_MOUNTPROG:		fputs ("nfs mountd", stdout); break;
case RPC_PMAPPROG:		fputs ("portmap", stdout); break;
case RPC_RSTATPROG:		fputs ("rstatd", stdout); break;
case RPC_PCNFSDPROG:		fputs ("pcnfsd", stdout); break;
case RPC_WALLPROG:		fputs ("rwalld", stdout); break;
case RPC_ETHERSTATPROG:		fputs ("etherstat", stdout); break;
case RPC_YPUPDATEPROG:		fputs ("ypupdate", stdout); break;
case RPC_RQUOTAPROG:		fputs ("rquotad", stdout); break;
case RPC_SPRAYPROG:		fputs ("rsprayd", stdout); break;
case RPC_SELNSVCPROG:		fputs ("selection service", stdout); break;
case RPC_RDATABASEPROG:		fputs ("rdatabase", stdout); break;
case RPC_REXECPROG:		fputs ("rexecd", stdout); break;
case RPC_ALICEPROG:		fputs ("alice", stdout); break;
case RPC_SCHEDPROG:		fputs ("sched", stdout); break;
case RPC_LOCKPROG:		fputs ("lock", stdout); break;
case RPC_NETLOCKPROG:		fputs ("netlock", stdout); break;
case RPC_X25PROG:		fputs ("x25", stdout); break;
case RPC_STATMON1PROG:		fputs ("statmon1", stdout); break;
case RPC_STATMON2PROG:		fputs ("statmon2", stdout); break;
case RPC_SELNLIBPROG:		fputs ("selnlib", stdout); break;
case RPC_BOOTPARAMPROG:		fputs ("boot param", stdout); break;
case RPC_KEYSERVEPROG:		fputs ("keyserver", stdout); break;
case RPC_SECURECMDPROG:		fputs ("secure cmd", stdout); break;
case RPC_NETFWDIPROG:		fputs ("NFS netfwd init", stdout); break;
case RPC_NETFWDTPROG:		fputs ("NFS netfwd trans", stdout); break;
case RPC_SUNLINKMAP_PROG:	fputs ("sunlink map", stdout); break;
case RPC_NETMONPROG:		fputs ("netmon", stdout); break;
case RPC_DBASEPROG:		fputs ("dbase", stdout); break;
case RPC_PWDAUTHPROG:		fputs ("pwdauth", stdout); break;
case RPC_TFSPROG:		fputs ("tfs", stdout); break;
case RPC_NSEPROG:		fputs ("nse server", stdout); break;
case RPC_NSE_ACTIVATE_PROG:	fputs ("nse activate", stdout); break;
case RPC_IBM3270PROG:		fputs ("3270 mapper", stdout); break;
case RPC_IBMRJEPROG:		fputs ("rje mapper", stdout); break;
case RPC_PYRAMIDLOCKINGPROG:	fputs ("pyramid lock", stdout); break;
case RPC_PYRAMIDSYS5:		fputs ("pyramid sys5", stdout); break;
case RPC_CADDS_IMAGE:		fputs ("cadds image", stdout); break;
case RPC_ADT_RFLOCKPROG:	fputs ("adt rflock", stdout); break;
case RPC_DBXPROG:		fputs ("rdbx", stdout); break;
case RPC_MAZEPROG:		fputs ("mazewars", stdout); break;
X
default:
X	/* unknown udp packet type - it might be an rpc call, and it might not */
X	fprintf (stdout, "rpc pgm 0x%X (%d>%d)", rpcpak->rm_call.cb_prog,
X		udpak->Source_port, udpak->Dest_port);
X	}
}
X
X
static void
RPCreply_Interpret (struct rpc_msg *rpcpak)
{
fputs ("rpc reply ", stdout);
switch (rpcpak->rm_reply.rp_stat) {
case MSG_ACCEPTED:
X	switch (rpcpak->rm_reply.rp_acpt.ar_stat) {
X	case NFS_OK:		fputs ("okay", stdout); break;
X	case NFSERR_PERM:	fputs ("Not Owner", stdout); break;
X	case NFSERR_NOENT:	fputs ("No such file or directory", stdout); break;
X	case NFSERR_IO:		fputs ("I/O error", stdout); break;
X	case NFSERR_NXIO:	fputs ("No such device or address", stdout); break;
X	case NFSERR_ACCES:	fputs ("Permission denied", stdout); break;
X	case NFSERR_EXIST:	fputs ("file exists", stdout); break;
X	case NFSERR_NODEV:	fputs ("no such device", stdout); break;
X	case NFSERR_NOTDIR:	fputs ("not a directory", stdout); break;
X	case NFSERR_ISDIR:	fputs ("is a directory", stdout); break;
X	case NFSERR_FBIG:	fputs ("file too large", stdout); break;
X	case NFSERR_NOSPC:	fputs ("no space left on device", stdout); break;
X	case NFSERR_ROFS:	fputs ("read only filesystem", stdout); break;
X	case NFSERR_NAMETOOLONG:	fputs ("file name too long", stdout); break;
X	case NFSERR_NOTEMPTY:	fputs ("directory not empty", stdout); break;
X	case NFSERR_DQUOT:	fputs ("disk quota exceeded", stdout); break;
X	case NFSERR_STALE:	fputs ("stale file handle", stdout); break;
X	case NFSERR_WFLUSH:	fputs ("write cache flushed", stdout); break;
X
X	default:
X		fprintf (stdout, "accepted 0x%X", rpcpak->rm_reply.rp_acpt.ar_stat);
X		}
X	break;
X
case MSG_DENIED:
X	switch (rpcpak->rm_reply.rp_rjct.rj_stat) {
X	case RPC_MISMATCH:	fputs ("reject - rpc mismatch", stdout); break;
X	case AUTH_ERROR:	fputs ("reject - auth error", stdout); break;
X
X	default:
X		fprintf (stdout, "rejected 0x%X", rpcpak->rm_reply.rp_rjct.rj_stat);
X		}
X	break;
X
default:
X	/* unknown udp packet type - might be an rpc reply, might not */
X	fprintf (stdout, "unknown 0x%X", rpcpak->rm_reply.rp_stat);
X	}
}
X
X
static int
RPC_Interpret (struct UDPpacket *udpak)
{
struct rpc_msg *rpcpak;
rpcpak = (struct rpc_msg *) udpak->Data;
X
/* might be an RPC message - let's find out */
switch (rpcpak->rm_direction) {
case CALL:	RPCcall_Interpret (rpcpak, udpak); break;
case REPLY:	RPCreply_Interpret (rpcpak); break;
X
default:
X	return 1;
X	}
return 0;
}
X
X
static int
udp_type (int port)
{
switch (port) {
case 7:			fputs ("echo ", stdout); break;
case 9:			fputs ("discard ", stdout); break;
case 13:		fputs ("daytime ", stdout); break;
case 19:		fputs ("chargen ", stdout); break;
case 37:		fputs ("timeserver ", stdout); break;
case 39:		fputs ("resource ", stdout); break;
case 42:		fputs ("nameserver ", stdout); break;
case 53:		fputs ("bind ", stdout); break;
case 67:		fputs ("bootp server ", stdout); break;
case 68:		fputs ("bootp client ", stdout); break;
case 69:		fputs ("tftp ", stdout); break;
case 111:		fputs ("sun-rpc ", stdout); break;
case 121:		fputs ("annex-rpc ", stdout); break;
case 123:		fputs ("ntp ", stdout); break;
case 135:		fputs ("loc-srv ", stdout); break;
case 137:		fputs ("netbios_ns ", stdout); break;
case 138:		fputs ("netbios_dgm ", stdout); break;
case 139:		fputs ("netbios_ssn ", stdout); break;
case 161:		fputs ("snmp ", stdout); break;
case 162:		fputs ("snmp-trap ", stdout); break;
case 177:		fputs ("xdmcp ", stdout); break;
case 200:		fputs ("src ", stdout); break;
case 512:		fputs ("biffudp ", stdout); break;
case 513:		fputs ("whod ", stdout); break;
case 514:		fputs ("syslog ", stdout); break;
case 517:		fputs ("talk ", stdout); break;
case 518:		fputs ("ntalk ", stdout); break;
case 520:		fputs ("routed ", stdout); break;
case 525:		fputs ("timed ", stdout); break;
case 533:		fputs ("netwall ", stdout); break;
case 550:		fputs ("new-rwho ", stdout); break;
case 560:		fputs ("rmonitor ", stdout); break;
case 561:		fputs ("monitor ", stdout); break;
case 570:		fputs ("lansrm ", stdout); break;
case 750:		fputs ("kerberos ", stdout); break;
case 777:		fputs ("rsend ", stdout); break;
case 1167:		fputs ("phone ", stdout); break;
case 1527:		fputs ("man ", stdout); break;
case 1990:		fputs ("snmp-mib ", stdout); break;
case 1991:		fputs ("snmp-conf ", stdout); break;
case 2049:		fputs ("nfsd ", stdout); break;
case 5130:		fputs ("sgi-dog ", stdout); break;
case 5131:		fputs ("sgi-arena ", stdout); break;
case 45231:		fputs ("mcp-ctl ", stdout); break;
case 45232:		fputs ("mcp ", stdout); break;
case 54319:		fputs ("radio-bctl ", stdout); break;
case 54320:		fputs ("radio-ctl ", stdout); break;
case 54321:		fputs ("radio-rcv ", stdout); break;
case 54318:		fputs ("radio-send ", stdout); break;
X
default:
X	return 1;
X	}
return 0;
}
X
X
/*
X * Interpret UDP packets.
X */
void
UDP_Interpret (char *data)
{
struct UDPpacket *udpak;
udpak = (struct UDPpacket *) data;
X
/* try to type the source port, then see if it's an rpc packet */
if (udp_type(ntohs(udpak->Source_port)) && RPC_Interpret (udpak)) {
X	fprintf (stdout, "udp %d ", udpak->Source_port);
X	/* try to type the dest port */
X	if (udp_type(ntohs(udpak->Dest_port))) {
X		/* unknown udp packet type */
X		fprintf (stdout, "> %d ", udpak->Dest_port);
X		}
X	}
}
SHAR_EOF
chmod 0644 udp.c ||
echo 'restore of udp.c failed'
Wc_c="`wc -c < 'udp.c'`"
test 8299 -eq "$Wc_c" ||
	echo 'udp.c: original size 8299, current size' "$Wc_c"
fi
# ============= misc.c ==============
if test -f 'misc.c' -a X"$1" != X"-c"; then
	echo 'x - skipping misc.c (File already exists)'
else
echo 'x - extracting misc.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'misc.c' &&
/*
X * network monitor program
X * Original Author: Patrick Wolfe (pwolfe@kai.com, kailand!pwolfe)
X */
#include "netmon.h"
#include <string.h>
X
extern short	trace_broadcast,
X		trace_unknown;
extern int	NumHosts,
X		stopit,
X		debug;
extern u_char	eaddr_table[MaxHosts][6];
extern char	hostname[MaxHosts][64];
X
static char	trace_host[2][64];
X
X
void
StopIt (sig)
int sig;
{
stopit = sig;
}
X
X
/* catch as many signals as you can - and shutdown when you catch them */
void catch_sigs ()
{
signal (SIGHUP, StopIt);	signal (SIGINT, StopIt);	signal (SIGQUIT, StopIt);	signal (SIGILL, StopIt);
signal (SIGTRAP, StopIt);	signal (SIGABRT, StopIt);	signal (SIGIOT, StopIt);	signal (SIGEMT, StopIt);
signal (SIGFPE, StopIt);	signal (SIGBUS, StopIt);	signal (SIGSEGV, StopIt);	signal (SIGSYS, StopIt);
signal (SIGPIPE, StopIt);	signal (SIGALRM, StopIt);	signal (SIGTERM, StopIt);	signal (SIGUSR1, StopIt);
signal (SIGUSR2, StopIt);	signal (SIGCLD, StopIt);	signal (SIGPWR, StopIt);	signal (SIGURG, StopIt);
signal (SIGVTALRM, StopIt);	signal (SIGPROF, StopIt);	signal (SIGCONT, StopIt);	signal (SIGTTIN, StopIt);
signal (SIGTTOU, StopIt);
}
X
X
/*
X * read /etc/arp_table to get a list of known hostnames and ethernet hardware addresses
X * someday we'll learn how to access the system's arp table directly for immediate ethernet to internet
X * address resolution.  For how, we use a file with them hardcoded.  This is the same file we feed to
X * "arp -f" at boottime.
X */
X
read_arp_table (char *filename)
{
FILE *fp;
int linectr = 0;
int b0, b1, b2, b3, b4, b5;
char line[LINELEN];
X
DEBUG ((stderr, "reading %s\n", filename));
X
if ((fp = fopen (filename, "r")) == NULL) {
X	perror ("fopen");
X	fprintf (stderr, "cannot open file %s for input\n", filename);
X	exit (1);
X	}
X
/* add entries for the "unknown" host (entry zero) and the two known broadcast addresses */
NumHosts++;
strcpy (hostname[NumHosts], "UNKNOWN");
eaddr_table[NumHosts][0] = eaddr_table[NumHosts][1] = eaddr_table[NumHosts][2] =
eaddr_table[NumHosts][3] = eaddr_table[NumHosts][4] = eaddr_table[NumHosts][5] = 0;
NumHosts++;
strcpy (hostname[NumHosts], "BROADCAST0");
eaddr_table[NumHosts][0] = eaddr_table[NumHosts][1] = eaddr_table[NumHosts][2] =
eaddr_table[NumHosts][3] = eaddr_table[NumHosts][4] = eaddr_table[NumHosts][5] = 0;
NumHosts++;
strcpy (hostname[NumHosts], "BROADCAST1");
eaddr_table[NumHosts][0] = eaddr_table[NumHosts][1] = eaddr_table[NumHosts][2] =
eaddr_table[NumHosts][3] = eaddr_table[NumHosts][4] = eaddr_table[NumHosts][5] = 0xff;
X
while (fgets(line, LINELEN, fp) != NULL) {
X	linectr++;
/*	DEBUG ((stderr, "%2d: read line %s", linectr, line));*/
X	if (line[0] == '#') {
X		continue;
X		}
X	if (NumHosts >= MaxHosts) {
X		fprintf (stderr, "recompile netmon with a larger hostname and eaddr table (%d is just too small)\n", NumHosts);
X		break;
X		}
X	NumHosts++;
X	if (sscanf (line, "%s %x:%x:%x:%x:%x:%x\n", hostname[NumHosts], &b0, &b1, &b2, &b3, &b4, &b5) == EOF) {
X		fprintf (stderr, "invalid format of line #%d: %s", linectr, line);
X		NumHosts--;
X		}
X	else	{
X		eaddr_table[NumHosts][0] = b0;
X		eaddr_table[NumHosts][1] = b1;
X		eaddr_table[NumHosts][2] = b2;
X		eaddr_table[NumHosts][3] = b3;
X		eaddr_table[NumHosts][4] = b4;
X		eaddr_table[NumHosts][5] = b5;
X		DEBUG ((stderr, "added entry %s (%X:%X:%X:%X:%X:%X)", hostname[NumHosts], b0, b1, b2, b3, b4, b5));
X		}
X	}
X
DEBUG ( (stderr, "finished reading arp table\n"));
fclose (fp);
}
X
X
void
parse_cmdline (int argc, char *argv[])
{
#if defined(USE_GETHOST)
struct hostent *he;
#endif
int errors = 0;
int args, c, thc;
char *x;
X
trace_host[0][0] = '\0';
trace_host[1][0] = '\0';
X
for (args = 1; (args < argc) && (errors == 0) && (argv[args][0] == '-'); args++) {
X	switch (argv[args][1]) {
X	case 'b':
X		trace_broadcast++;
X		break;
X
X	case 'u':
X		trace_unknown++;
X		break;
X
X	case 'x':
X		debug++;	/* to actually get DEBUG output, include -DDEBUG at compile time */ 
X		DEBUG ((stderr, "debug enabled\n"));
X		break;
X
X	default:
X		fprintf (stderr, "unrecognized command line option %s\n", argv[args]);
X		errors++;
X		}
X	}
X
/* get hostname(s) from the command line */
for (thc = 0; (errors == 0) && (args < argc) && (thc < 2); args++, thc++) {
#if defined(USE_GETHOST)
X	if ((he = gethostbyname (argv[args])) == NULL) {
X		errors++;
X		fprintf (stderr, "unknown host %s\n", argv[args]); 
X		}
X	else	{
X		strcpy (&trace_host[thc][0], he->h_name);
X		/* cut off hostname at the dot - some hosts use bind,
X		 * and hostnames in our arp_table don't include the domain name
X		 */
X		if ((x = strchr(&trace_host[thc][0], '.')) != NULL) {
X			*x = '\0';
X			}
X		}
#else /* ! USE_GETHOST */
X	strcpy (&trace_host[thc][0], argv[args]);
#endif /* USE_GETHOST */
X	}
X
if (errors > 0) {
X	fprintf (stderr, "usage:  netmon [-b] [hostname [hostname]]\n");
X	exit (1);
X	}
}
X
X
void
add_snoop_filter (int s, char *from_host, char *to_host)
{
struct ether_header *eh;
struct snoopfilter sf1;
int from = -1, to = -1;
X
/* clear the whole structure */
bzero ((char *) &sf1, sizeof sf1);
X
/* get index into hostname/eaddr tables on hostname */
if (from_host != NULL) {
X	for (from = NumHosts - 1; (from > 0) && (strcmp (from_host, hostname[from]) != 0); from--);
X	}
if (to_host != NULL) {
X	for (to = NumHosts - 1; (to > 0) && (strcmp (to_host, hostname[to]) != 0); to--);
X	}
X
/* if not watching all packets, set mask and match fields */
if ((from != -1) || (to != -1)) {
X	/* set mask field */
X	eh = RAW_HDR(sf1.sf_mask, struct ether_header);
X	if (from != -1) {
X		memset (eh->ether_shost, 0xff, sizeof(eh->ether_shost));
X		}
X	if (to != -1) {
X		memset (eh->ether_dhost, 0xff, sizeof(eh->ether_dhost));
X		}
X
X	/* set match field */
X	eh = RAW_HDR(sf1.sf_match, struct ether_header);
X	if (from != -1) {
X		bcopy (eaddr_table[from], eh->ether_shost, sizeof(eh->ether_shost));
X		}
X	if (to != -1) {
X		bcopy (eaddr_table[to], eh->ether_dhost, sizeof(eh->ether_dhost));
X		}
X	}
X
X
X
if (ioctl (s, SIOCADDSNOOP, (struct snoopfilter *)&sf1) < 0) {
X	perror ("ioctl: SIOCADDSNOOP");
X	exit (1);
X	}
}
X
X
int
start_snooping()
{
struct sockaddr_raw sr;
int s, cc;
/*
X *	create a raw protocol socket
X */
X
s = socket (AF_RAW, SOCK_RAW, RAWPROTO_SNOOP);
if (s < 0) {
X	perror ("socket");
X	exit (1);
X	}
X
/*
X *	bind the socket to the primary ethernet interface
X *
X *	to bind to a specific ethernet interface, use:
X *		stncpy (sr.sr_ifname, "et0", sizeof sr.sr_ifname);
X */
bzero (sr.sr_ifname, RAW_IFNAMSIZ);
X
sr.sr_family = AF_RAW;
sr.sr_port = 0;
if (bind (s, &sr, sizeof sr) < 0) {
X	perror ("bind");
X	exit (1);
X	}
X
if ((trace_host[0][0] == '\0') && (trace_host[1][0] == '\0')) {
X	if (trace_unknown) {
X		printf ("watching for unknown hosts\n");
X		}
X	else	{
X		printf ("watching all packets\n");
X		}
X	add_snoop_filter (s, NULL, NULL);
X	}
else	{
X	if ((trace_host[0][0] != '\0') && (trace_host[1][0] == '\0')) {
X		printf ("watching packets coming from or going to host %s\n", trace_host[0]);
X		add_snoop_filter (s, trace_host[0], NULL);
X		add_snoop_filter (s, NULL, trace_host[0]);
X		}
X	else	{
X		printf ("watching packets between hosts %s and %s\n", trace_host[0], trace_host[1]);
X		add_snoop_filter (s, trace_host[0], trace_host[1]);
X		add_snoop_filter (s, trace_host[1], trace_host[0]);
X		}
X	if (trace_broadcast) {
X		printf ("watching broadcast packets\n");
X		add_snoop_filter (s, NULL, "BROADCAST1");
X		}
X	}
X
X
/*
X *	increase receive buffer size to deal with copious amounts of ethernet traffic
X */
cc = 60000;
if (setsockopt (s, SOL_SOCKET, SO_RCVBUF, (char *) &cc, sizeof cc) < 0) {
X	perror ("setsockopt");
X	exit (1);
X	}
X
/*
X *	start snooping!
X */
cc = 1;
if (ioctl (s, SIOCSNOOPING, &cc) < 0) {
X	perror ("ioctl: SIOCSNOOPING ON");
X	exit (1);
X	}
X
return (s);
}
SHAR_EOF
chmod 0644 misc.c ||
echo 'restore of misc.c failed'
Wc_c="`wc -c < 'misc.c'`"
test 7601 -eq "$Wc_c" ||
	echo 'misc.c: original size 7601, current size' "$Wc_c"
fi
# ============= arp_table ==============
if test -f 'arp_table' -a X"$1" != X"-c"; then
	echo 'x - skipping arp_table (File already exists)'
else
echo 'x - extracting arp_table (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'arp_table' &&
blizzard	8:0:69:6:2a:98
kailand		8:0:47:0:1f:d0
SHAR_EOF
chmod 0644 arp_table ||
echo 'restore of arp_table failed'
Wc_c="`wc -c < 'arp_table'`"
test 48 -eq "$Wc_c" ||
	echo 'arp_table: original size 48, current size' "$Wc_c"
fi
# ============= netmon.h ==============
if test -f 'netmon.h' -a X"$1" != X"-c"; then
	echo 'x - skipping netmon.h (File already exists)'
else
echo 'x - extracting netmon.h (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'netmon.h' &&
X
#include <stdio.h>
#include <sys/types.h>
#include <net/raw.h>
#include <netinet/if_ether.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <rpc/rpc.h>
#include <sys/fs/nfs.h>
#include <errno.h>
#include <signal.h>
#include <netdb.h>
#include <getopt.h>
X
/* the DEBUG macro allows compile time included debug code */
#ifdef DEBUG
#undef DEBUG
#define DEBUG(x) if (debug) fprintf x
#else
#define DEBUG(x)
#endif
X
/* maximum number of hostname/ethernet addresses to store in a table */
#define MaxHosts	128
X
/* maximum line length of /etc/arp_table */
#define LINELEN		128
X
/* filename of arp table - same format as that fed to the "-f" option of arp(1M) */
#define ARP_TABLE	"/etc/arp_table"
X
#define ETHERHDRPAD	  RAW_HDRPAD(sizeof(struct ether_header))
X
struct etherpacket {
X	struct snoopheader	snoop;
X	char			pad[ETHERHDRPAD];
X	struct ether_header	ether;
X	char			data[ETHERMTU];
X	};
X
/* IP datagram header length in bytes	*/
#define IP_hdrlen	20
/* Maximum IP datagram length (hosts & gateways only required to recognize 576 bytes) */
#define IP_maxlen	1200
X
struct IPpacket {
X	u_char	VersLen;
X	u_char	Service_type; /* 0 = normal service */
X	short	Packet_len;
X	u_short	Id;
X	short	Fragment_offset; /* 0 for 1st fragment */
X	u_char	Time_to_live;
X	u_char	Protocol;
X	u_short	Checksum;	/* 1s compl. of sum of shorts in header */
X	struct in_addr	Source_IPaddr;
X	struct in_addr	Dest_IPaddr;
X	u_char	Data[1];
X	};
X
#define TCP_hdrlen	5
X
struct TCPpacket {
X	u_short	Source_port;
X	u_short	Dest_port;
X	u_long	Seq;
X	u_long	Ack;
X	u_char	Data_offset:4,
X		x2:4; /* unused */
X	u_char	Flags;
X	u_short	Window;
X	u_short	Checksum;
X	u_short	Urgent_ptr;
X	u_char  Data[1];
X	};
X
#define UDP_hdrlen	8
X
struct UDPpacket {
X	u_short	Source_port;
X	u_short	Dest_port;
X	u_short	Data_length;
X	u_short	Checksum;	/* 0 means no checksum */
X	u_char	Data[1];
X	};
X
#ifndef ETHERTYPE_REVARP
#define ETHERTYPE_REVARP	0x8035		/* Reverse ARP */
#endif
X
#ifndef ETHERTYPE_APPLETALK
#define ETHERTYPE_APPLETALK     0x809B          /* AppleTalk */
#endif
X
#ifndef ETHERTYPE_AARP
#define ETHERTYPE_AARP          0x80F3          /* AppleTalk ARP */
#endif
SHAR_EOF
chmod 0666 netmon.h ||
echo 'restore of netmon.h failed'
Wc_c="`wc -c < 'netmon.h'`"
test 2176 -eq "$Wc_c" ||
	echo 'netmon.h: original size 2176, current size' "$Wc_c"
fi
# ============= udp.h ==============
if test -f 'udp.h' -a X"$1" != X"-c"; then
	echo 'x - skipping udp.h (File already exists)'
else
echo 'x - extracting udp.h (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'udp.h' &&
/*
X * udp.h
X */
X
#define NFS_READ		0
#define NFS_WRITE		1
X
/*
X * RPC programs, from "Remote Procedure Call Programming Guide",
X * Revision A, 9 May 1988, pp. 64-65.
X */
#define RPC_PMAPPROG		((u_long) 100000) /* portmapper		     */
#define RPC_RSTATPROG		((u_long) 100001) /* remote stats	     */
#define RPC_RUSERSPROG		((u_long) 100002) /* remote users	     */
#define RPC_NFSPROG		((u_long) 100003) /* NFS		     */
#define RPC_YPPROG		((u_long) 100004) /* Yellow Pages	     */
#define RPC_MOUNTPROG		((u_long) 100005) /* mount daemon	     */
#define RPC_DBXPROG		((u_long) 100006) /* remote dbx		     */
#define RPC_YPBINDPROG		((u_long) 100007) /* yp binder		     */
#define RPC_WALLPROG		((u_long) 100008) /* shutdown msg	     */
#define RPC_YPPASSWDPROG	((u_long) 100009) /* yppasswd server	     */
#define RPC_ETHERSTATPROG	((u_long) 100010) /* ether stats	     */
#define RPC_RQUOTAPROG		((u_long) 100011) /* disk quotas	     */
#define RPC_SPRAYPROG		((u_long) 100012) /* spray packets	     */
#define RPC_IBM3270PROG		((u_long) 100013) /* 3270 mapper	     */
#define RPC_IBMRJEPROG		((u_long) 100014) /* RJE mapper		     */
#define RPC_SELNSVCPROG		((u_long) 100015) /* selection service	     */
#define RPC_RDATABASEPROG	((u_long) 100016) /* remote database access  */
#define RPC_REXECPROG		((u_long) 100017) /* remote execution	     */
#define RPC_ALICEPROG		((u_long) 100018) /* Alice Office Automation */
#define RPC_SCHEDPROG		((u_long) 100019) /* scheduling service      */
#define RPC_LOCKPROG		((u_long) 100020) /* local lock manager      */
#define RPC_NETLOCKPROG		((u_long) 100021) /* network lock manager    */
#define RPC_X25PROG		((u_long) 100022) /* X.25 inr protocol	     */
#define RPC_STATMON1PROG	((u_long) 100023) /* status monitor 1	     */
#define RPC_STATMON2PROG	((u_long) 100024) /* status monitor 2	     */
#define RPC_SELNLIBPROG		((u_long) 100025) /* selection library	     */
#define RPC_BOOTPARAMPROG	((u_long) 100026) /* boot parameters service */
#define RPC_MAZEPROG		((u_long) 100027) /* mazewars game	     */
#define RPC_YPUPDATEPROG	((u_long) 100028) /* yp update		     */
#define RPC_KEYSERVEPROG	((u_long) 100029) /* key server		     */
#define RPC_SECURECMDPROG	((u_long) 100030) /* secure login	     */
#define RPC_NETFWDIPROG		((u_long) 100031) /* NFS net forwarder init  */
#define RPC_NETFWDTPROG		((u_long) 100032) /* NFS net forwarder trans */
#define RPC_SUNLINKMAP_PROG	((u_long) 100033) /* sunlink MAP	     */
#define RPC_NETMONPROG		((u_long) 100034) /* network monitor	     */
#define RPC_DBASEPROG		((u_long) 100035) /* lightweight database    */
#define RPC_PWDAUTHPROG		((u_long) 100036) /* password authorization  */
#define RPC_TFSPROG		((u_long) 100037) /* translucent file svc    */
#define RPC_NSEPROG		((u_long) 100038) /* nse server		     */
#define RPC_NSE_ACTIVATE_PROG	((u_long) 100039) /* nse activate daemon     */
X
#define RPC_PCNFSDPROG		((u_long) 150001) /* pc passwd authorization */
X
#define RPC_PYRAMIDLOCKINGPROG	((u_long) 200000) /* Pyramid-locking	     */
#define RPC_PYRAMIDSYS5		((u_long) 200001) /* Pyramid-sys5	     */
#define RPC_CADDS_IMAGE		((u_long) 200002) /* CV cadds_image	     */
X
#define RPC_ADT_RFLOCKPROG	((u_long) 300001) /* ADT file locking	     */
X
static char *nfs_procedure[] = {
X	"do nothing",		/* 0 */
X	"getfileattr",		/* 1 */
X	"setfileattr",		/* 2 */
X	"getfsroot",		/* 3 */
X	"lookup",		/* 4 */
X	"read symlink",		/* 5 */
X	"read",			/* 6 */
X	"writecache",		/* 7 */
X	"write",		/* 8 */
X	"createfile",		/* 9 */
X	"rm",			/* 10 */
X	"mv",			/* 11 */
X	"ln",			/* 12 */
X	"ln -s",		/* 13 */
X	"mkdir",		/* 14 */
X	"rmdir",		/* 15 */
X	"readdir",		/* 16 */
X	"getfsattr"		/* 17 */
X	};
X
/*
X * IP port numbers - why did SGI remove them from <netinet/in.h> in 4.0.1?
X */
X
#define	IPPORT_ECHO		7
#define	IPPORT_DISCARD		9
#define	IPPORT_SYSTAT		11
#define	IPPORT_DAYTIME		13
#define	IPPORT_NETSTAT		15
#define	IPPORT_FTP		21
#define	IPPORT_TELNET		23
#define	IPPORT_SMTP		25
#define	IPPORT_TIMESERVER	37
#define	IPPORT_NAMESERVER	42
#define	IPPORT_WHOIS		43
#define	IPPORT_MTP		57
#define	IPPORT_TFTP		69
#define	IPPORT_RJE		77
#define	IPPORT_FINGER		79
#define	IPPORT_TTYLINK		87
#define	IPPORT_SUPDUP		95
#define	IPPORT_BIFFUDP		512
#define	IPPORT_WHOSERVER	513
#define	IPPORT_ROUTESERVER	520	/* 520+1 also used */
SHAR_EOF
chmod 0444 udp.h ||
echo 'restore of udp.h failed'
Wc_c="`wc -c < 'udp.h'`"
test 4305 -eq "$Wc_c" ||
	echo 'udp.h: original size 4305, current size' "$Wc_c"
fi
exit 0
-- 

	Patrick Wolfe (pwolfe@kai.com)
	System Manager, Kuck and Associates