1
0
mirror of https://git.FreeBSD.org/ports.git synced 2025-01-24 09:25:01 +00:00

This is a development fork of arpwatch. This has been

threaded in order to better deal with the requirements of
multi-interface routers. Information regarding MAC addresses
and interfaces is maintained by the program, and an alert is
issued should a device move between interfaces.  In addition,
event processing has been refactored, and some bugs have been
fixed.

PR:		59180
Submitted by:	Matthew George <mdg@secureworks.net>
Approved by:	portmgr
This commit is contained in:
Kirill Ponomarev 2004-01-19 23:34:48 +00:00
parent 0af9b9f294
commit 486518fcaa
Notes: svn2git 2021-03-31 03:12:20 +00:00
svn path=/head/; revision=98614
43 changed files with 2401 additions and 536 deletions

View File

@ -1,19 +1,19 @@
# New ports collection makefile for: arpwatch
# Date created: March 24 1997
# Whom: Brian Somers <brian@FreeBSD.org>
# New ports collection makefile for: arpwatch-devel
# Date created: 11 November 2003
# Whom: Matthew George <mdg@secureworks.net>
#
# $FreeBSD$
#
PORTNAME= arpwatch
PORTVERSION= 2.1.a11
PORTREVISION= 3
CATEGORIES= net
MASTER_SITES= http://www.Awfulhak.org/arpwatch/ \
ftp://ftp.ee.lbl.gov/
PKGNAMESUFFIX= -devel
DISTNAME= arpwatch-2.1a11
MAINTAINER= krion@FreeBSD.org
MAINTAINER= mdg@secureworks.net
COMMENT= Monitor arp & rarp requests
GNU_CONFIGURE= yes
@ -30,13 +30,12 @@ post-install:
fi
${TOUCH} ${PREFIX}/arpwatch/arp.dat
${CHMOD} 644 ${PREFIX}/arpwatch/arp.dat
${TOUCH} ${PREFIX}/arpwatch/ether.dat
${CHMOD} 644 ${PREFIX}/arpwatch/ether.dat
for file in ethercodes.dat d.awk e.awk p.awk; do \
${INSTALL_DATA} ${WRKSRC}/$$file ${PREFIX}/arpwatch; \
${INSTALL_DATA} ${WRKSRC}/$$file ${PREFIX}/arpwatch/.; \
done
${INSTALL_SCRIPT} ${WRKSRC}/arp2ethers ${PREFIX}/arpwatch
${INSTALL_SCRIPT} ${WRKSRC}/arp2ethers ${PREFIX}/arpwatch/.
${INSTALL_SCRIPT} ${FILESDIR}/arpwatch.sh ${PREFIX}/etc/rc.d/arpwatch.sh.sample
@${ECHO_MSG} "#####################################################################"
@${ECHO_MSG} "Installing ${PREFIX}/etc/rc.d/arpwatch.sh.sample file."
@${ECHO_MSG} "#####################################################################"
.include <bsd.port.mk>

View File

@ -21,22 +21,29 @@ case $1 in
start)
if [ ! -e "$PREFIX"/arpwatch/arp.dat ]; then
if [ -e "$PREFIX"/arpwatch/arp.dat- ]; then
cp "$PREFIX"/arpwatch/arp.dat- "$PREFIX"/arpwatch/arp.dat
cp "$PREFIX"/arpwatch/arp.dat- "$PREFIX"/arpwatch/arp.dat
else
touch "$PREFIX"/arpwatch/arp.dat
fi
fi
if [ ! -e "$PREFIX"/arpwatch/ether.dat ]; then
if [ -e "$PREFIX"/arpwatch/ether.dat- ]; then
cp "$PREFIX"/arpwatch/ether.dat- "$PREFIX"/arpwatch/ether.dat
else
touch "$PREFIX"/arpwatch/ether.dat
fi
fi
case ${arpwatch_interfaces} in
'')
if [ -x "$PREFIX"/sbin/arpwatch -a -d "$PREFIX"/arpwatch ]; then
"$PREFIX"/sbin/arpwatch && echo -n ' arpwatch'
"$PREFIX"/sbin/arpwatch ${arpwatch_flags} && echo -n ' arpwatch'
fi
;;
*)
for interface in ${arpwatch_interfaces}; do
touch "$PREFIX"/arpwatch/arp.${interface}.dat
"$PREFIX"/sbin/arpwatch -i "${interface}" -f arp.${interface}.dat && echo -n " arpwatch(${interface})"
"$PREFIX"/sbin/arpwatch -i "${interface}" && echo -n " arpwatch(${interface})"
done
;;
esac

View File

@ -0,0 +1,22 @@
--- ../arpwatch.orig/Makefile.in Wed Jun 14 20:39:55 2000
+++ ./Makefile.in Mon Sep 15 14:31:33 2003
@@ -45,7 +45,7 @@
PROG = arpwatch
CCOPT = @V_CCOPT@
INCLS = -I. @V_INCLS@
-DEFS = -DDEBUG @DEFS@ -DARPDIR=\"$(ARPDIR)\" -DPATH_SENDMAIL=\"$(SENDMAIL)\"
+DEFS = @DEFS@ -pthread -DARPDIR=\"$(ARPDIR)\" -DPATH_SENDMAIL=\"$(SENDMAIL)\"
# Standard CFLAGS
CFLAGS = $(CCOPT) $(DEFS) $(INCLS)
@@ -110,8 +110,8 @@
$(CC) $(CFLAGS) -o $@ zap.o intoa.o -lutil
install: force
- $(INSTALL) -m 555 -o bin -g bin arpwatch $(DESTDIR)$(BINDEST)
- $(INSTALL) -m 555 -o bin -g bin arpsnmp $(DESTDIR)$(BINDEST)
+ $(INSTALL) -s -m 555 -o bin -g bin arpwatch $(DESTDIR)$(BINDEST)
+ $(INSTALL) -s -m 555 -o bin -g bin arpsnmp $(DESTDIR)$(BINDEST)
install-man: force
$(INSTALL) -m 444 -o bin -g bin $(srcdir)/arpwatch.8 \

View File

@ -1,22 +1,25 @@
--- Makefile.in.orig Wed Jul 29 06:16:45 1998
+++ Makefile.in Fri Aug 21 10:57:51 1998
@@ -44,7 +44,7 @@
CC = @CC@
CCOPT = @V_CCOPT@
INCLS = -I. @V_INCLS@
-DEFS = -DDEBUG @DEFS@ -DARPDIR=\"$(ARPDIR)\" -DPATH_SENDMAIL=\"$(SENDMAIL)\"
+DEFS = @DEFS@ -DARPDIR=\"$(ARPDIR)\" -DPATH_SENDMAIL=\"$(SENDMAIL)\"
# Standard CFLAGS
CFLAGS = $(CCOPT) $(DEFS) $(INCLS)
@@ -109,8 +109,8 @@
$(CC) $(CFLAGS) -o $@ zap.o intoa.o -lutil
install: force
- $(INSTALL) -m 555 -o bin -g bin arpwatch $(DESTDIR)$(BINDEST)
- $(INSTALL) -m 555 -o bin -g bin arpsnmp $(DESTDIR)$(BINDEST)
+ $(INSTALL) -s -m 555 -o bin -g bin arpwatch $(DESTDIR)$(BINDEST)
+ $(INSTALL) -s -m 555 -o bin -g bin arpsnmp $(DESTDIR)$(BINDEST)
install-man: force
$(INSTALL) -m 444 -o bin -g bin $(srcdir)/arpwatch.8 \
--- ../arpwatch.orig/arpsnmp.8 Sun Sep 17 16:34:48 2000
+++ ./arpsnmp.8 Fri Sep 5 14:46:55 2003
@@ -30,6 +30,9 @@
] [
.B -f
.I datafile
+] [
+.B -m
+.I email
]
.I file
[
@@ -54,6 +57,12 @@
flag is used to set the ethernet/ip address database filename.
The default is
.IR arp.dat .
+.LP
+The
+.B -m
+flag specifies the address that will receive the emails.
+The default is
+.IR root .
.LP
Note that an empty
.I arp.dat

View File

@ -0,0 +1,67 @@
--- ../arpwatch.orig/arpsnmp.c Sun Jan 17 20:47:40 1999
+++ ./arpsnmp.c Mon Sep 15 14:31:33 2003
@@ -63,14 +63,17 @@
/* Forwards */
int main(int, char **);
int readsnmp(char *);
-int snmp_add(u_int32_t, u_char *, time_t, char *);
+int snmp_add(u_int32_t, u_char *, time_t, char *, char *);
__dead void usage(void) __attribute__((volatile));
char *prog;
+char *Watcher;
+
extern int optind;
extern int opterr;
extern char *optarg;
+char *interface = NULL;
int
main(int argc, char **argv)
@@ -90,7 +93,7 @@
}
opterr = 0;
- while ((op = getopt(argc, argv, "df:")) != EOF)
+ while ((op = getopt(argc, argv, "df:m:")) != EOF)
switch (op) {
case 'd':
@@ -105,6 +108,10 @@
arpfile = optarg;
break;
+ case 'm':
+ Watcher = optarg;
+ break;
+
default:
usage();
}
@@ -138,7 +145,7 @@
static time_t now;
int
-snmp_add(register u_int32_t a, register u_char *e, time_t t, register char *h)
+snmp_add(register u_int32_t a, register u_char *e, time_t t, register char *h, register char *i)
{
/* Watch for ethernet broadcast */
if (MEMCMP(e, zero, 6) == 0 || MEMCMP(e, allones, 6) == 0) {
@@ -153,7 +160,7 @@
}
/* Use current time (although it would be nice to subtract idle time) */
- return (ent_add(a, e, now, h));
+ return (ent_add(a, e, now, h, interface));
}
/* Process an snmp file */
@@ -184,6 +191,6 @@
(void)fprintf(stderr, "Version %s\n", version);
(void)fprintf(stderr,
- "usage: %s [-d] [-f datafile] file [...]\n", prog);
+ "usage: %s [-d] [-f datafile] [-m email] file [...]\n", prog);
exit(1);
}

View File

@ -0,0 +1,101 @@
--- ../arpwatch-2.1a11/arpwatch.8 Sun Oct 8 16:31:28 2000
+++ ./arpwatch.8 Mon Sep 15 17:30:45 2003
@@ -30,7 +30,10 @@
.B -dN
] [
.B -f
-.I datafile
+.I arpfile
+] [
+.B -e
+.I etherfile
] [
.B -i
.I interface
@@ -38,6 +41,9 @@
.br
.ti +8
[
+.B -m
+.I email
+] [
.B -n
.IR net [/ width
]] [
@@ -67,8 +73,24 @@
.IR arp.dat .
.LP
The
+.B -e
+flag is used to set the ethernet/interface database filename.
+The default is
+.IR ether.dat .
+.LP
+The
+.B -i
+flag is used to specify a single interface. By default,
+.B arpwatch
+will listen to all non-loopback interfaces. Using more than one
.B -i
-flag is used to override the default interface.
+option on the same command line is not supported.
+.LP
+The
+.B -m
+flag specifies the address that will receive the emails.
+The default is
+.IR root .
.LP
The
.B -n
@@ -81,6 +103,8 @@
The
.B -N
flag disables reporting any bogons.
+It is highly recommended that this flag be used on machines with
+multiple interfaces.
.LP
The
.B -r
@@ -96,6 +120,8 @@
.LP
Note that an empty
.I arp.dat
+and
+.I ether.dat
file must be created before the first time you run
.BR arpwatch .
.LP
@@ -105,12 +131,19 @@
(and
.BR arpsnmp (1)):
.TP
+.B "new ethernet device"
+The ethernet address has not been seen before.
+.TP
+.B "ethernet device changed interfaces"
+An ethernet address associated with one interface has moved to a
+different interface.
+.TP
.B "new activity"
This ethernet/ip address pair has been used for the first time six
months or more.
.TP
-.B "new station"
-The ethernet address has not been seen before.
+.B "new active IP address"
+The IP address has not been seen before.
.TP
.B "flip flop"
The ethernet address has changed from the most recently seen address to
@@ -152,8 +185,9 @@
.na
.nh
.nf
-/usr/operator/arpwatch - default directory
+/usr/local/arpwatch - default directory
arp.dat - ethernet/ip address database
+ether.dat - ethernet/interface address database
ethercodes.dat - vendor ethernet block list
.ad
.hy

View File

@ -1,20 +1,316 @@
--- configure.orig Thu Jun 15 01:37:53 2000
+++ configure Tue Sep 5 02:57:33 2000
@@ -649,7 +649,7 @@
:
fi
--- arpwatch.c.orig Sat Oct 14 04:07:35 2000
+++ arpwatch.c Tue Jan 20 00:22:23 2004
@@ -36,6 +36,7 @@
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/time.h>
+#include <pthread.h>
- V_CCOPT="-O"
+# V_CCOPT="-O"
V_INCLS=""
if test "${srcdir}" != "." ; then
V_INCLS="-I\$\(srcdir\)"
@@ -2599,7 +2599,7 @@
fi
V_CCOPT="$V_CCOPT -Wall"
if test $ac_cv_lbl_gcc_vers -gt 1 ; then
- V_CCOPT="$V_CCOPT -Wmissing-prototypes -Wstrict-prototypes"
+# V_CCOPT="$V_CCOPT -Wmissing-prototypes -Wstrict-prototypes"
fi
fi
else
#if __STDC__
struct mbuf;
@@ -107,6 +108,8 @@
char *prog;
+char *Watcher = NULL;
+
int can_checkpoint;
int swapped;
int nobogons;
@@ -123,6 +126,14 @@
static int nets_ind;
static int nets_size;
+struct aw_threads {
+ char *interface;
+ pthread_t thread;
+};
+
+struct aw_threads *threads = NULL;
+extern pthread_mutex_t mtx_einfo, mtx_ainfo;
+
extern int optind;
extern int opterr;
extern char *optarg;
@@ -145,14 +156,14 @@
main(int argc, char **argv)
{
register char *cp;
- register int op, pid, snaplen, timeout, linktype, status;
+ register int op, pid, if_cnt, i;
#ifdef TIOCNOTTY
register int fd;
#endif
- register pcap_t *pd;
- register char *interface, *rfilename;
- struct bpf_program code;
+ register char *rfilename;
char errbuf[PCAP_ERRBUF_SIZE];
+ pcap_if_t *adp, *alldevsp = NULL;
+ char *interface = NULL;
if (argv[0] == NULL)
prog = "arpwatch";
@@ -167,10 +178,8 @@
}
opterr = 0;
- interface = NULL;
rfilename = NULL;
- pd = NULL;
- while ((op = getopt(argc, argv, "df:i:n:Nr:")) != EOF)
+ while ((op = getopt(argc, argv, "de:f:i:m:n:Nr:")) != EOF)
switch (op) {
case 'd':
@@ -181,6 +190,10 @@
#endif
break;
+ case 'e':
+ etherfile = optarg;
+ break;
+
case 'f':
arpfile = optarg;
break;
@@ -202,6 +215,10 @@
rfilename = optarg;
break;
+ case 'm':
+ Watcher = optarg;
+ break;
+
default:
usage();
}
@@ -213,19 +230,23 @@
net = 0;
netmask = 0;
} else {
- /* Determine interface if not specified */
- if (interface == NULL &&
- (interface = pcap_lookupdev(errbuf)) == NULL) {
- (void)fprintf(stderr, "%s: lookup_device: %s\n",
- prog, errbuf);
- exit(1);
- }
+ /* if not specified, do all non loopback interfaces */
+ if (interface == NULL) {
- /* Determine network and netmask */
- if (pcap_lookupnet(interface, &net, &netmask, errbuf) < 0) {
- (void)fprintf(stderr, "%s: bad interface %s: %s\n",
- prog, interface, errbuf);
- exit(1);
+ pcap_findalldevs(&alldevsp, errbuf);
+ if (alldevsp == NULL) {
+ (void)fprintf(stderr, "no suitable interfaces\n");
+ exit(1);
+ }
+
+ if_cnt = 0;
+ for(adp = alldevsp; adp != NULL; adp = adp->next) {
+ if (adp->flags != PCAP_IF_LOOPBACK)
+ ++if_cnt;
+ }
+
+ } else {
+ if_cnt = 1;
}
/* Drop into the background if not debugging */
@@ -238,7 +259,7 @@
exit(0);
(void)close(fileno(stdin));
(void)close(fileno(stdout));
- (void)close(fileno(stderr));
+
#ifdef TIOCNOTTY
fd = open("/dev/tty", O_RDWR);
if (fd >= 0) {
@@ -251,12 +272,82 @@
}
}
- openlog(prog, 0, LOG_DAEMON);
+ if (debug)
+ openlog(prog, LOG_PERROR, LOG_DAEMON);
+ else
+ openlog(prog, 0, LOG_DAEMON);
if (chdir(arpdir) < 0) {
syslog(LOG_ERR, "chdir(%s): %m", arpdir);
syslog(LOG_ERR, "(using current working directory)");
}
+ /* Read in database */
+ initializing = 1;
+ if (!readdata())
+ exit(1);
+ sorteinfo();
+#ifdef DEBUG
+ if (debug > 2) {
+ debugdump();
+ exit(0);
+ }
+#endif
+ initializing = 0;
+
+ (void)setsignal(SIGINT, die);
+ (void)setsignal(SIGTERM, die);
+ (void)setsignal(SIGHUP, die);
+ if (rfilename == NULL) {
+ (void)setsignal(SIGQUIT, checkpoint);
+ (void)setsignal(SIGALRM, checkpoint);
+ (void)alarm(CHECKPOINT);
+ }
+
+ threads = (struct aw_threads *) malloc(sizeof(struct aw_threads) * (if_cnt + 1));
+ memset((char *)threads, 0, sizeof(*threads) * (if_cnt + 1));
+ pthread_mutex_init(&mtx_einfo, NULL);
+ pthread_mutex_init(&mtx_ainfo, NULL);
+
+ if (interface != NULL)
+ {
+ threads[0].interface = interface;
+ pthread_create(&threads[0].thread, NULL, (void *)pcap_thread, interface);
+ }
+ else
+ {
+ i = 0;
+
+ for (adp = alldevsp; adp != NULL; adp = adp->next)
+ if (adp->flags != PCAP_IF_LOOPBACK)
+ {
+ threads[i].interface = adp->name;
+ pthread_create(&threads[i++].thread, NULL, (void *)pcap_thread, adp->name);
+ }
+ }
+
+ for (i=0; i < if_cnt; i++)
+ pthread_join(threads[i].thread, NULL);
+
+ if (!dump())
+ exit(1);
+ exit(0);
+}
+
+int
+pcap_thread(char *interface)
+{
+ register char *rfilename = NULL;
+ char errbuf[PCAP_ERRBUF_SIZE];
+ register pcap_t *pd = NULL;
+ register int snaplen, timeout, linktype, status;
+ struct bpf_program code;
+
+ /* Determine network and netmask */
+ if (pcap_lookupnet(interface, &net, &netmask, errbuf) < 0) {
+ (void)fprintf(stderr, "%s: bad interface %s: %s\n",
+ prog, interface, errbuf);
+ return(1);
+ }
if (rfilename != NULL) {
pd = pcap_open_offline(rfilename, errbuf);
@@ -306,27 +397,7 @@
if (rfilename == NULL)
syslog(LOG_INFO, "listening on %s", interface);
- /* Read in database */
- initializing = 1;
- if (!readdata())
- exit(1);
- sorteinfo();
-#ifdef DEBUG
- if (debug > 2) {
- debugdump();
- exit(0);
- }
-#endif
- initializing = 0;
- (void)setsignal(SIGINT, die);
- (void)setsignal(SIGTERM, die);
- (void)setsignal(SIGHUP, die);
- if (rfilename == NULL) {
- (void)setsignal(SIGQUIT, checkpoint);
- (void)setsignal(SIGALRM, checkpoint);
- (void)alarm(CHECKPOINT);
- }
switch (linktype) {
@@ -347,9 +418,7 @@
exit(1);
}
pcap_close(pd);
- if (!dump())
- exit(1);
- exit(0);
+ return(0);
}
/* Process an ethernet arp/rarp packet */
@@ -362,6 +431,8 @@
register u_char *sea, *sha;
register time_t t;
u_int32_t sia;
+ register pthread_t thread_self = NULL;
+ register struct aw_threads *atp = threads;
eh = (struct ether_header *)p;
ea = (struct ether_arp *)(eh + 1);
@@ -400,9 +471,16 @@
/* Got a live one */
t = h->ts.tv_sec;
can_checkpoint = 0;
- if (!ent_add(sia, sea, t, NULL))
+ thread_self = pthread_self();
+
+ for (atp = threads; atp != NULL; atp++)
+ if (pthread_equal(atp->thread, thread_self))
+ break;
+
+ if (!ent_add(sia, sea, t, NULL, atp->interface))
syslog(LOG_ERR, "ent_add(%s, %s, %ld) failed",
intoa(sia), e2str(sea), t);
+
can_checkpoint = 1;
}
@@ -507,6 +585,8 @@
register u_char *sea, *sha;
register time_t t;
u_int32_t sia;
+ register pthread_t thread_self = NULL;
+ register struct aw_threads *atp = threads;
fh = (struct fddi_header *)p;
ea = (struct ether_arp *)(fh + 1);
@@ -549,7 +629,13 @@
/* Got a live one */
t = h->ts.tv_sec;
can_checkpoint = 0;
- if (!ent_add(sia, sea, t, NULL))
+ thread_self = pthread_self();
+
+ for (atp = threads; atp != NULL; atp++)
+ if (atp->thread == thread_self)
+ break;
+
+ if (!ent_add(sia, sea, t, NULL, atp->interface))
syslog(LOG_ERR, "ent_add(%s, %s, %ld) failed",
intoa(sia), e2str(sea), t);
can_checkpoint = 1;
@@ -750,7 +836,7 @@
extern char version[];
(void)fprintf(stderr, "Version %s\n", version);
- (void)fprintf(stderr, "usage: %s [-dN] [-f datafile] [-i interface]"
- " [-n net[/width]] [-r file]\n", prog);
+ (void)fprintf(stderr, "usage: %s [-dN] [-f arpfile] [-e etherfile] [-i interface]"
+ " [-m email] [-n net[/width]] [-r file]\n", prog);
exit(1);
}

View File

@ -1,17 +1,16 @@
--- ethercodes.dat.orig Thu May 3 21:59:10 2001
+++ ethercodes.dat Tue Nov 11 10:59:56 2003
@@ -4419,7 +4419,7 @@
0:d0:b4 KATSUJIMA CO., LTD.
0:d0:b5 DOTCOM
0:d0:b6 CRESCENT NETWORKS, INC.
-0:d0:b7 INTEL CORPOTATION
+0:d0:b7 INTEL CORPORATION
0:d0:b8 IOMEGA CORP.
0:d0:b9 MICROTEK INTERNATIONAL, INC.
0:d0:ba CISCO SYSTEMS, INC.
@@ -4964,3 +4964,5 @@
c0:0:0 Western Digital (may be reversed 00 00 C0?)
e2:c:f Kingston Technologies
ec:10:0 Enance Source Co., Ltd. PC clones(?)
+0:bd:11 VMWare Inc
+0:bd:fb VMWare Inc
--- ../arpwatch-2.1a11/arpwatch.h Sat Sep 30 19:40:55 2000
+++ ./arpwatch.h Fri Sep 12 17:01:42 2003
@@ -1,6 +1,7 @@
/* @(#) $Id: arpwatch.h,v 1.29 2000/09/30 23:40:49 leres Exp $ (LBL) */
#define ARPFILE "arp.dat"
+#define ETHERFILE "ether.dat"
#define ETHERCODES "ethercodes.dat"
#define CHECKPOINT (15*60) /* Checkpoint time in seconds */
@@ -40,3 +41,5 @@
#define SPA(ap) ((ap)->arp_spa)
#define TPA(ap) ((ap)->arp_tpa)
#endif
+
+int pcap_thread(char *);

View File

@ -1,39 +1,14 @@
--- arpwatch.c.orig Thu Feb 22 22:47:29 2001
+++ arpwatch.c Thu Feb 22 22:47:29 2001
@@ -107,6 +107,8 @@
char *prog;
+char *Watcher = NULL;
--- ../arpwatch.orig/configure.in Sat Oct 14 14:19:10 2000
+++ ./configure.in Wed Sep 10 13:08:05 2003
@@ -170,6 +170,11 @@
if test ! -f arp.dat ; then
echo 'creating empty arp.dat file'
touch arp.dat
+fi
+
int can_checkpoint;
int swapped;
int nobogons;
@@ -170,7 +172,7 @@
interface = NULL;
rfilename = NULL;
pd = NULL;
- while ((op = getopt(argc, argv, "df:i:n:Nr:")) != EOF)
+ while ((op = getopt(argc, argv, "df:i:m:n:Nr:")) != EOF)
switch (op) {
case 'd':
@@ -202,6 +204,10 @@
rfilename = optarg;
break;
+ case 'm':
+ Watcher = optarg;
+ break;
+
default:
usage();
}
@@ -751,6 +757,6 @@
(void)fprintf(stderr, "Version %s\n", version);
(void)fprintf(stderr, "usage: %s [-dN] [-f datafile] [-i interface]"
- " [-n net[/width]] [-r file]\n", prog);
+ " [-m email] [-n net[/width]] [-r file]\n", prog);
exit(1);
}
+if test ! -f ether.dat ; then
+ echo 'creating empty ether.dat file'
+ touch ether.dat
fi
if test -f .devel ; then

View File

@ -1,55 +1,32 @@
--- report.c.orig Sun Oct 1 00:41:10 2000
+++ report.c Thu May 16 11:34:33 2002
@@ -45,6 +45,8 @@
#include <ctype.h>
#include <errno.h>
+#include <fcntl.h>
+#include <paths.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
@@ -70,6 +72,8 @@
#define PLURAL(n) ((n) == 1 || (n) == -1 ? "" : "s")
+extern char *Watcher;
--- ../arpwatch.orig/configure Wed May 16 14:26:11 2001
+++ ./configure Wed Sep 10 13:08:05 2003
@@ -649,7 +649,7 @@
:
fi
- V_CCOPT="-O"
+# V_CCOPT="-O"
V_INCLS=""
if test "${srcdir}" != "." ; then
V_INCLS="-I\$\(srcdir\)"
@@ -2496,7 +2496,7 @@
fi
V_CCOPT="$V_CCOPT -Wall"
if test $ac_cv_lbl_gcc_vers -gt 1 ; then
- V_CCOPT="$V_CCOPT -Wmissing-prototypes -Wstrict-prototypes"
+# V_CCOPT="$V_CCOPT -Wmissing-prototypes -Wstrict-prototypes"
fi
fi
else
@@ -3075,6 +3075,11 @@
if test ! -f arp.dat ; then
echo 'creating empty arp.dat file'
touch arp.dat
+fi
+
static int cdepth; /* number of outstanding children */
static char *fmtdate(time_t);
@@ -240,7 +244,7 @@
register FILE *f;
char tempfile[64], cpu[64], os[64];
char *fmt = "%20s: %s\n";
- char *watcher = WATCHER;
+ char *watcher = Watcher ? Watcher : WATCHER;
char *watchee = WATCHEE;
char *sendmail = PATH_SENDMAIL;
char *unknown = "<unknown>";
@@ -344,6 +348,25 @@
exit(1);
}
/* XXX Need to freopen()? */
+
+ /*
+ * Open /dev/null as stdout and stderr so that sendmail 8.12.1 (and
+ * above ?) won't complain about missing file descriptors.
+ */
+ if ((fd = open(_PATH_DEVNULL, O_RDWR)) == -1) {
+ syslog(LOG_ERR, "Cannot open %s: %m", _PATH_DEVNULL);
+ exit(1);
+ }
+ if (dup2(fd, STDOUT_FILENO) == -1) {
+ syslog(LOG_ERR, "Cannot dup2 %s to stdout: %m", _PATH_DEVNULL);
+ exit(1);
+ }
+ if (dup2(fd, STDERR_FILENO) == -1) {
+ syslog(LOG_ERR, "Cannot dup2 %s to stderr: %m", _PATH_DEVNULL);
+ exit(1);
+ }
+ close(fd);
+
/* Always Deliver interactively (pause when child depth gets large) */
execl(sendmail, "sendmail", "-odi", watcher, NULL);
syslog(LOG_ERR, "execl: %s: %m", sendmail);
+if test ! -f ether.dat ; then
+ echo 'creating empty ether.dat file'
+ touch ether.dat
fi
if test -f .devel ; then

View File

@ -1,39 +1,271 @@
--- arpsnmp.c.orig Mon Jan 18 01:47:40 1999
+++ arpsnmp.c Thu Feb 22 22:47:29 2001
@@ -68,6 +68,8 @@
char *prog;
+char *Watcher;
--- ../arpwatch.orig/db.c Sat Sep 30 19:39:58 2000
+++ ./db.c Mon Sep 15 13:17:07 2003
@@ -41,6 +41,7 @@
#include <string.h>
#include <syslog.h>
#include <unistd.h>
+#include <pthread.h>
#include "gnuc.h"
#ifdef HAVE_OS_PROTO_H
@@ -54,18 +55,9 @@
#include "report.h"
#include "util.h"
-#define HASHSIZE (2 << 15)
-
#define NEWACTIVITY_DELTA (6*30*24*60*60) /* 6 months in seconds */
#define FLIPFLIP_DELTA (24*60*60) /* 24 hours in seconds */
-/* Ethernet info */
-struct einfo {
- u_char e[6]; /* ether address */
- char h[34]; /* simple hostname */
- time_t t; /* timestamp */
-};
-
/* Address info */
struct ainfo {
u_int32_t a; /* ip address */
@@ -78,22 +70,69 @@
/* Address hash table */
static struct ainfo ainfo_table[HASHSIZE];
+
extern int optind;
extern int opterr;
extern char *optarg;
@@ -90,7 +92,7 @@
}
opterr = 0;
- while ((op = getopt(argc, argv, "df:")) != EOF)
+ while ((op = getopt(argc, argv, "df:m:")) != EOF)
switch (op) {
case 'd':
@@ -105,6 +107,10 @@
arpfile = optarg;
break;
+ case 'm':
+ Watcher = optarg;
+ break;
+/* Ethernet hash table */
+struct einfo einfo_table[HASHSIZE];
+int et_cnt = 0;
+
default:
usage();
static void alist_alloc(struct ainfo *);
int cmpeinfo(const void *, const void *);
-static struct einfo *elist_alloc(u_int32_t, u_char *, time_t, char *);
+static struct einfo *elist_alloc(u_int32_t, u_char *, time_t, char *, char *);
static struct ainfo *ainfo_find(u_int32_t);
+static struct einfo *einfo_find(u_char *);
static void check_hname(struct ainfo *);
struct ainfo *newainfo(void);
+pthread_mutex_t mtx_einfo, mtx_ainfo;
+
int
-ent_add(register u_int32_t a, register u_char *e, time_t t, register char *h)
+ent_add(register u_int32_t a, register u_char *e, time_t t, register char *h, register char *interface)
{
register struct ainfo *ap;
- register struct einfo *ep;
+ struct einfo *ep;
register int i;
register u_int len;
u_char *e2;
time_t t2;
+ register evt_type event = NULL;
+ char *if2 = NULL;
+
+ pthread_mutex_lock(&mtx_einfo);
+
+ /* Lookup ethernet address */
+ ep = einfo_find(e);
+
+ /* New einfo? (elist_alloc makes 16 at a time -- no thanks) */
+ if (ep == NULL && ! initializing) {
+ if (et_cnt >= HASHSIZE) {
+ syslog(LOG_ERR, "ERROR: einfo_table too big");
+ } else {
+ ep = &einfo_table[et_cnt++];
+ BCOPY(e, ep->e, sizeof(ep->e));
+ if (h == NULL)
+ h = getsname(a);
+ if (h != NULL && !isdigit((int)*h))
+ strncpy(ep->h, h, sizeof(ep->h));
+ ep->t = t;
+ strncpy(ep->iface, interface, sizeof(ep->iface));
+ event |= ETHER_NEW;
+ e2 = NULL;
+ t2 = NULL;
+ }
+ } else if (! initializing) {
+ if (strncmp(ep->iface, interface, sizeof(ep->iface)) != 0) {
+ event |= ETHER_IFCHG;
+ asprintf(&if2, "%s", ep->iface);
+ memset((char *)ep->iface, 0, sizeof(ep->iface));
+ BCOPY(interface, ep->iface, sizeof(ep->iface));
+ e2 = NULL;
+ t2 = ep->t;
+ ep->t = t;
+ }
+ }
+
+ pthread_mutex_unlock(&mtx_einfo);
+ pthread_mutex_lock(&mtx_ainfo);
/* Lookup ip address */
ap = ainfo_find(a);
@@ -101,28 +140,30 @@
/* Check for the usual case first */
if (ap->ecount > 0) {
ep = ap->elist[0];
- if (MEMCMP(e, ep->e, 6) == 0) {
+ if (MEMCMP(e, ep->e, sizeof(ep->e)) == 0) {
if (t - ep->t > NEWACTIVITY_DELTA) {
- report("new activity", a, e, NULL, &t, &ep->t);
+ event |= ACTIVITY_NEW;
+ e2 = NULL;
+ t2 = ep->t;
check_hname(ap);
}
ep->t = t;
- return (1);
}
@@ -184,6 +190,6 @@
(void)fprintf(stderr, "Version %s\n", version);
(void)fprintf(stderr,
- "usage: %s [-d] [-f datafile] file [...]\n", prog);
+ "usage: %s [-d] [-f datafile] [-m email] file [...]\n", prog);
exit(1);
}
/* Check for a virgin ainfo record */
if (ap->ecount == 0) {
ap->ecount = 1;
- ap->elist[0] = elist_alloc(a, e, t, h);
- report("new station", a, e, NULL, &t, NULL);
- return (1);
+ ap->elist[0] = elist_alloc(a, e, t, h, interface);
+ event |= IP_NEW;
+ e2 = NULL;
+ t2 = NULL;
}
/* Check for a flip-flop */
if (ap->ecount > 1) {
ep = ap->elist[1];
- if (MEMCMP(e, ep->e, 6) == 0) {
+ if (MEMCMP(e, ep->e, sizeof(ep->e)) == 0) {
/*
* Suppress report when less than
* FLIPFLOP_DELTA and one of the two ethernet
@@ -131,48 +172,76 @@
t2 = ap->elist[0]->t;
e2 = ap->elist[0]->e;
if (t - t2 < FLIPFLIP_DELTA &&
- (isdecnet(e) || isdecnet(e2)))
+ (isdecnet(e) || isdecnet(e2))) {
dosyslog(LOG_INFO,
"suppressed DECnet flip flop", a, e, e2);
- else
- report("flip flop", a, e, e2, &t, &t2);
+ event |= FLIPFLOP_DECNET;
+ } else {
+ event |= FLIPFLOP;
+ }
+
ap->elist[1] = ap->elist[0];
ap->elist[0] = ep;
ep->t = t;
check_hname(ap);
- return (1);
}
}
for (i = 2; i < ap->ecount; ++i) {
ep = ap->elist[i];
- if (MEMCMP(e, ep->e, 6) == 0) {
+ if (MEMCMP(e, ep->e, sizeof(ep->e)) == 0) {
/* An old entry comes to life */
e2 = ap->elist[0]->e;
t2 = ap->elist[0]->t;
dosyslog(LOG_NOTICE, "reused old ethernet address",
a, e, e2);
+ event |= IP_ETHER_REUSE;
/* Shift entries down */
len = i * sizeof(ap->elist[0]);
BCOPY(&ap->elist[0], &ap->elist[1], len);
ap->elist[0] = ep;
ep->t = t;
check_hname(ap);
- return (1);
}
}
- /* New ether address */
- e2 = ap->elist[0]->e;
- t2 = ap->elist[0]->t;
- report("changed ethernet address", a, e, e2, &t, &t2);
- /* Make room at head of list */
- alist_alloc(ap);
- len = ap->ecount * sizeof(ap->elist[0]);
- BCOPY(&ap->elist[0], &ap->elist[1], len);
- ap->elist[0] = elist_alloc(a, e, t, h);
- ++ap->ecount;
- return (1);
+ /* as originally written, any of these conditions would cause this
+ * block never to be reached. ETHER_NEW and ETHER_IFCHG have been added to that list.
+ */
+ if (event & ~(ACTIVITY_NEW | IP_NEW | FLIPFLOP | FLIPFLOP_DECNET | IP_ETHER_REUSE | ETHER_NEW | ETHER_IFCHG)) {
+ /* New ether address */
+ e2 = ap->elist[0]->e;
+ t2 = ap->elist[0]->t;
+ event |= IP_ETHERCHG;
+ /* Make room at head of list */
+ alist_alloc(ap);
+ len = ap->ecount * sizeof(ap->elist[0]);
+ BCOPY(&ap->elist[0], &ap->elist[1], len);
+ ap->elist[0] = elist_alloc(a, e, t, h, interface);
+ ++ap->ecount;
+ }
+
+ pthread_mutex_unlock(&mtx_ainfo);
+
+ report(event, a, e, e2, &t, &t2, interface, if2);
+
+ if (if2 != NULL)
+ free(if2);
+
+ return(1);
+}
+
+static struct einfo *
+einfo_find(register u_char *e)
+{
+ register int i;
+
+ for (i=0; i < et_cnt; i++) {
+ if (MEMCMP(einfo_table[i].e, e, sizeof(einfo_table[i].e)) == 0)
+ return(&einfo_table[i]);
+ }
+
+ return(NULL);
}
static struct ainfo *
@@ -259,7 +328,7 @@
/* Allocate and initialize a elist struct */
static struct einfo *
elist_alloc(register u_int32_t a, register u_char *e, register time_t t,
- register char *h)
+ register char *h, register char *interface)
{
register struct einfo *ep;
register u_int size;
@@ -280,12 +349,16 @@
ep = elist++;
--eleft;
- BCOPY(e, ep->e, 6);
+ BCOPY(e, ep->e, sizeof(ep->e));
if (h == NULL && !initializing)
h = getsname(a);
if (h != NULL && !isdigit((int)*h))
- strcpy(ep->h, h);
+ strncpy(ep->h, h, sizeof(ep->h));
ep->t = t;
+
+ if (interface != NULL)
+ strncpy(ep->iface, interface, sizeof(ep->iface));
+
return (ep);
}
@@ -304,7 +377,7 @@
if (!isdigit((int)*h) && strcmp(h, ep->h) != 0) {
syslog(LOG_INFO, "hostname changed %s %s %s -> %s",
intoa(ap->a), e2str(ep->e), ep->h, h);
- strcpy(ep->h, h);
+ strncpy(ep->h, h, sizeof(ep->h));
}
}

View File

@ -1,25 +1,25 @@
--- arpwatch.8.orig Sun Oct 8 21:31:28 2000
+++ arpwatch.8 Thu Feb 22 22:47:29 2001
@@ -38,6 +38,9 @@
.br
.ti +8
[
+.B -m
+.I email
+] [
.B -n
.IR net [/ width
]] [
@@ -69,6 +72,12 @@
The
.B -i
flag is used to override the default interface.
+.LP
+The
+.B -m
+flag specifies the address that will receive the emails.
+The default is
+.IR root .
.LP
The
.B -n
--- ../arpwatch.orig/db.h Wed Jun 5 01:39:30 1996
+++ ./db.h Mon Sep 15 14:55:27 2003
@@ -1,10 +1,21 @@
/* @(#) $Header: db.h,v 1.8 96/06/04 22:39:29 leres Exp $ (LBL) */
+#define HASHSIZE (2 << 15)
+
typedef void (*ent_process)(u_int32_t, u_char *, time_t, char *);
#ifdef DEBUG
void debugdump(void);
#endif
-int ent_add(u_int32_t, u_char *, time_t, char *);
+int ent_add(u_int32_t, u_char *, time_t, char *, char *);
int ent_loop(ent_process);
void sorteinfo(void);
+
+/* Ethernet info */
+struct einfo {
+ u_char e[6]; /* ether address */
+ char h[34]; /* simple hostname */
+ time_t t; /* timestamp */
+ char iface[10]; /* interface name */
+};
+

View File

@ -1,25 +1,17 @@
--- arpsnmp.8.orig Sun Sep 17 21:34:48 2000
+++ arpsnmp.8 Thu Feb 22 22:47:29 2001
@@ -30,6 +30,9 @@
] [
.B -f
.I datafile
+] [
+.B -m
+.I email
]
.I file
[
@@ -54,6 +57,12 @@
flag is used to set the ethernet/ip address database filename.
The default is
.IR arp.dat .
+.LP
+The
+.B -m
+flag specifies the address that will receive the emails.
+The default is
+.IR root .
.LP
Note that an empty
.I arp.dat
--- ethercodes.dat.orig Thu May 3 21:59:10 2001
+++ ethercodes.dat Tue Nov 11 09:35:25 2003
@@ -4419,7 +4419,7 @@
0:d0:b4 KATSUJIMA CO., LTD.
0:d0:b5 DOTCOM
0:d0:b6 CRESCENT NETWORKS, INC.
-0:d0:b7 INTEL CORPOTATION
+0:d0:b7 INTEL CORPORATION
0:d0:b8 IOMEGA CORP.
0:d0:b9 MICROTEK INTERNATIONAL, INC.
0:d0:ba CISCO SYSTEMS, INC.
@@ -4964,3 +4964,5 @@
c0:0:0 Western Digital (may be reversed 00 00 C0?)
e2:c:f Kingston Technologies
ec:10:0 Enance Source Co., Ltd. PC clones(?)
+0:bd:11 VMWare Inc
+0:bd:fb VMWare Inc

View File

@ -0,0 +1,26 @@
--- ../arpwatch.orig/file.c Fri Oct 13 18:29:43 2000
+++ ./file.c Fri Sep 12 17:01:42 2003
@@ -20,7 +20,7 @@
*/
#ifndef lint
static const char rcsid[] =
- "@(#) $Id: file.c,v 1.25 2000/10/13 22:29:42 leres Exp $ (LBL)";
+ "@(#) $Id: file.c,v 1.2 2003/09/12 21:01:42 mdg Exp $ (LBL)";
#endif
/*
@@ -130,7 +130,13 @@
}
}
- if (!(*fn)(a, e, t, h))
+ /* NULL for the interface here is ok because we don't do
+ * anything in ent_add() for einfo when initializing,
+ * and the only time this code section is reached is
+ * during initialization (via readdata()). snmp_add()
+ * is irrelevant, as no ether tracking has been added to it.
+ */
+ if (!(*fn)(a, e, t, h, NULL))
return(0);
}

View File

@ -0,0 +1,9 @@
--- ../arpwatch.orig/file.h Sun Jan 17 20:46:04 1999
+++ ./file.h Fri Sep 12 17:01:42 2003
@@ -1,5 +1,5 @@
/* @(#) $Header: file.h,v 1.4 99/01/17 17:46:03 leres Exp $ (LBL) */
-typedef int (*file_process)(u_int32_t, u_char *, time_t, char *);
+typedef int (*file_process)(u_int32_t, u_char *, time_t, char *, char *);
int file_loop(FILE *, file_process, const char *);

View File

@ -0,0 +1,126 @@
--- ../arpwatch.orig/report.c Sat Sep 30 19:41:10 2000
+++ ./report.c Fri Sep 12 18:57:04 2003
@@ -45,6 +45,8 @@
#include <ctype.h>
#include <errno.h>
+#include <fcntl.h>
+#include <paths.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
@@ -70,6 +72,8 @@
#define PLURAL(n) ((n) == 1 || (n) == -1 ? "" : "s")
+extern char *Watcher;
+
static int cdepth; /* number of outstanding children */
static char *fmtdate(time_t);
@@ -232,15 +236,16 @@
}
void
-report(register char *title, register u_int32_t a, register u_char *e1,
- register u_char *e2, register time_t *t1p, register time_t *t2p)
+report(evt_type event, register u_int32_t a, register u_char *e1,
+ register u_char *e2, register time_t *t1p, register time_t *t2p,
+ register char *interface, register char *old_interface)
{
register char *cp, *hn;
register int fd, pid;
register FILE *f;
char tempfile[64], cpu[64], os[64];
char *fmt = "%20s: %s\n";
- char *watcher = WATCHER;
+ char *watcher = Watcher ? Watcher : WATCHER;
char *watchee = WATCHEE;
char *sendmail = PATH_SENDMAIL;
char *unknown = "<unknown>";
@@ -251,9 +256,15 @@
if (initializing)
return;
+ /* these types are sent to syslog instead of reported on.
+ * only continue if there are other events as well
+ */
+ if (event == NULL || (event & ~(IP_ETHER_REUSE | FLIPFLOP_DECNET) == 0))
+ return;
+
if (debug) {
if (debug > 1) {
- dosyslog(LOG_NOTICE, title, a, e1, e2);
+ dosyslog(LOG_NOTICE, "event", a, e1, e2);
return;
}
f = stdout;
@@ -270,7 +281,7 @@
}
/* Syslog this event too */
- dosyslog(LOG_NOTICE, title, a, e1, e2);
+ dosyslog(LOG_NOTICE, "event", a, e1, e2);
/* Update child depth */
++cdepth;
@@ -304,12 +315,31 @@
(void)fprintf(f, "To: %s\n", watcher);
hn = gethname(a);
if (!isdigit(*hn))
- (void)fprintf(f, "Subject: %s (%s)\n", title, hn);
+ (void)fprintf(f, "Subject: Arpwatch Event (%s)\n", hn);
else {
- (void)fprintf(f, "Subject: %s\n", title);
+ (void)fprintf(f, "Subject: Arpwatch Event\n");
hn = unknown;
}
(void)putc('\n', f);
+
+ if (event & ETHER_NEW)
+ (void)fprintf(f, fmt, "event", "new ethernet device");
+ if (event & ETHER_IFCHG)
+ (void)fprintf(f, fmt, "event", "ethernet device changed interfaces");
+ if (event & ACTIVITY_NEW)
+ (void)fprintf(f, fmt, "event", "new activity");
+ if (event & IP_NEW)
+ (void)fprintf(f, fmt, "event", "new active IP address");
+ if (event & IP_ETHERCHG)
+ (void)fprintf(f, fmt, "event", "IP changed ethernet address");
+ if (event & FLIPFLOP)
+ (void)fprintf(f, fmt, "event", "flip flop");
+
+ (void)fprintf(f, fmt, "interface", interface);
+
+ if (old_interface != NULL)
+ (void)fprintf(f, fmt, "old interface", old_interface);
+
(void)fprintf(f, fmt, "hostname", hn);
(void)fprintf(f, fmt, "ip address", intoa(a));
(void)fprintf(f, fmt, "ethernet address", e2str(e1));
@@ -344,6 +374,25 @@
exit(1);
}
/* XXX Need to freopen()? */
+
+ /*
+ * Open /dev/null as stdout and stderr so that sendmail 8.12.1 (and
+ * above ?) won't complain about missing file descriptors.
+ */
+ if ((fd = open(_PATH_DEVNULL, O_RDWR)) == -1) {
+ syslog(LOG_ERR, "Cannot open %s: %m", _PATH_DEVNULL);
+ exit(1);
+ }
+ if (dup2(fd, STDOUT_FILENO) == -1) {
+ syslog(LOG_ERR, "Cannot dup2 %s to stdout: %m", _PATH_DEVNULL);
+ exit(1);
+ }
+ if (dup2(fd, STDERR_FILENO) == -1) {
+ syslog(LOG_ERR, "Cannot dup2 %s to stderr: %m", _PATH_DEVNULL);
+ exit(1);
+ }
+ close(fd);
+
/* Always Deliver interactively (pause when child depth gets large) */
execl(sendmail, "sendmail", "-odi", watcher, NULL);
syslog(LOG_ERR, "execl: %s: %m", sendmail);

View File

@ -0,0 +1,20 @@
--- ../arpwatch.orig/report.h Wed Jun 5 01:40:54 1996
+++ ./report.h Mon Sep 15 15:03:20 2003
@@ -1,3 +1,16 @@
/* @(#) $Header: report.h,v 1.3 96/06/04 22:40:53 leres Exp $ (LBL) */
-void report(char *, u_int32_t, u_char *, u_char *, time_t *, time_t *);
+
+typedef enum
+ {
+ ETHER_NEW=1,
+ ETHER_IFCHG=2,
+ ACTIVITY_NEW=4,
+ IP_NEW=8,
+ IP_ETHERCHG=16,
+ IP_ETHER_REUSE=32,
+ FLIPFLOP=64,
+ FLIPFLOP_DECNET=128
+ } evt_type;
+
+void report(evt_type, u_int32_t, u_char *, u_char *, time_t *, time_t *, char *, char *);

View File

@ -0,0 +1,78 @@
--- ../arpwatch.orig/util.c Fri Oct 13 18:49:03 2000
+++ ./util.c Wed Sep 10 13:03:27 2003
@@ -53,6 +53,7 @@
char *arpdir = ARPDIR;
char *arpfile = ARPFILE;
+char *etherfile = ETHERFILE;
char *ethercodes = ETHERCODES;
/* Broadcast ethernet addresses */
@@ -105,7 +106,7 @@
dump(void)
{
register int fd;
- char oldarpfile[256], newarpfile[256];
+ char oldarpfile[256], newarpfile[256], *oldetherfile, *newetherfile;
(void)sprintf(oldarpfile, "%s-", arpfile);
(void)sprintf(newarpfile, "%s.new", arpfile);
@@ -130,6 +131,32 @@
syslog(LOG_ERR, "rename %s -> %s: %m", newarpfile, arpfile);
return(0);
}
+
+ /* ether info */
+ (void)asprintf(&oldetherfile, "%s-", etherfile);
+ (void)asprintf(&newetherfile, "%s.new", etherfile);
+
+ if ((fd = creat(newetherfile, 0644)) < 0) {
+ syslog(LOG_ERR, "creat(%s): %m", newetherfile);
+ return(0);
+ }
+ if ((dumpf = fdopen(fd, "w")) == NULL) {
+ syslog(LOG_ERR, "fdopen(%s): %m", newetherfile);
+ return(0);
+ }
+
+ fwrite(einfo_table, sizeof(struct einfo), et_cnt, dumpf);
+
+ (void)fclose(dumpf);
+ if (rename(etherfile, oldetherfile) < 0) {
+ syslog(LOG_ERR, "rename %s -> %s: %m", etherfile, oldetherfile);
+ return(0);
+ }
+ if (rename(newetherfile, etherfile) < 0) {
+ syslog(LOG_ERR, "rename %s -> %s: %m", newetherfile, etherfile);
+ return(0);
+ }
+
return(1);
}
@@ -138,7 +165,9 @@
readdata(void)
{
register FILE *f;
+ char line[1024];
+ /* arp.dat */
if ((f = fopen(arpfile, "r")) == NULL) {
syslog(LOG_ERR, "fopen(%s): %m", arpfile);
return(0);
@@ -147,6 +176,15 @@
(void)fclose(f);
return(0);
}
+ (void)fclose(f);
+
+ /* ether.dat */
+ if ((f = fopen(etherfile, "r")) == NULL) {
+ syslog(LOG_ERR, "fopen(%s): %m", etherfile);
+ return(0);
+ }
+
+ et_cnt = fread(einfo_table, sizeof(struct einfo), HASHSIZE, f);
(void)fclose(f);
/* It's not fatal if we can't open the ethercodes file */

View File

@ -0,0 +1,12 @@
--- ../arpwatch.orig/util.h Sun Oct 6 06:22:14 1996
+++ ./util.h Wed Sep 10 13:03:27 2003
@@ -11,6 +11,9 @@
extern char *arpfile;
extern char *oldarpfile;
extern char *ethercodes;
+extern char *etherfile;
+extern struct einfo einfo_table[];
+extern int et_cnt;
extern u_char zero[6];
extern u_char allones[6];

View File

@ -1,21 +1,10 @@
ARPWATCH 2.0
Lawrence Berkeley National Laboratory
Network Research Group
arpwatch@ee.lbl.gov
ftp://ftp.ee.lbl.gov/arpwatch.tar.Z
This is a development fork of arpwatch. This has been threaded in
order to better deal with the requirements of multi-interface
routers. Information regarding MAC addresses and interfaces is
maintained by the program, and an alert is issued should a device
move between interfaces. In addition, event processing has been
refactored, and some bugs have been fixed.
This directory contains source code for arpwatch and arpsnmp, tools
that monitors ethernet activity and maintain a database of ethernet/ip
address pairings. It also reports certain changes via email.
see net/arpwatch/pkg-descr for more information about arpwatch 2.x
Arpsnmp has the same database features of arpwatch but relies on an
external agent to collect the arp data. This distribution contains a
script, arpfetch, that uses snmpwalk from the CMU SNMP package. This
package is available from:
ftp://ftp.net.cmu.edu/pub/snmp-dist/cmu-snmp*.tar.Z
It should be trivial to adaptive the output of any snmp query program
for use with arpsnmp.
Please send bugs and comments to arpwatch@ee.lbl.gov.
Matthew George <mdg@secureworks.net>

View File

@ -7,5 +7,7 @@ arpwatch/e.awk
arpwatch/p.awk
etc/rc.d/arpwatch.sh.sample
@unexec test -f %D/arpwatch/arp.dat && test -s %D/arpwatch/arp.dat || rm -f %D/arpwatch/arp.dat
@unexec test -f %D/arpwatch/ether.dat && test -s %D/arpwatch/ether.dat || rm -f %D/arpwatch/ether.dat
@exec test -f %D/arpwatch/arp.dat || touch %D/arpwatch/arp.dat
@exec test -f %D/arpwatch/ether.dat || touch %D/arpwatch/ether.dat
@dirrm arpwatch

View File

@ -30,6 +30,7 @@
SUBDIR += arping
SUBDIR += arprelease
SUBDIR += arpwatch
SUBDIR += arpwatch-devel
SUBDIR += arts++
SUBDIR += asfrecorder
SUBDIR += aslookup

View File

@ -1,19 +1,19 @@
# New ports collection makefile for: arpwatch
# Date created: March 24 1997
# Whom: Brian Somers <brian@FreeBSD.org>
# New ports collection makefile for: arpwatch-devel
# Date created: 11 November 2003
# Whom: Matthew George <mdg@secureworks.net>
#
# $FreeBSD$
#
PORTNAME= arpwatch
PORTVERSION= 2.1.a11
PORTREVISION= 3
CATEGORIES= net
MASTER_SITES= http://www.Awfulhak.org/arpwatch/ \
ftp://ftp.ee.lbl.gov/
PKGNAMESUFFIX= -devel
DISTNAME= arpwatch-2.1a11
MAINTAINER= krion@FreeBSD.org
MAINTAINER= mdg@secureworks.net
COMMENT= Monitor arp & rarp requests
GNU_CONFIGURE= yes
@ -30,13 +30,12 @@ post-install:
fi
${TOUCH} ${PREFIX}/arpwatch/arp.dat
${CHMOD} 644 ${PREFIX}/arpwatch/arp.dat
${TOUCH} ${PREFIX}/arpwatch/ether.dat
${CHMOD} 644 ${PREFIX}/arpwatch/ether.dat
for file in ethercodes.dat d.awk e.awk p.awk; do \
${INSTALL_DATA} ${WRKSRC}/$$file ${PREFIX}/arpwatch; \
${INSTALL_DATA} ${WRKSRC}/$$file ${PREFIX}/arpwatch/.; \
done
${INSTALL_SCRIPT} ${WRKSRC}/arp2ethers ${PREFIX}/arpwatch
${INSTALL_SCRIPT} ${WRKSRC}/arp2ethers ${PREFIX}/arpwatch/.
${INSTALL_SCRIPT} ${FILESDIR}/arpwatch.sh ${PREFIX}/etc/rc.d/arpwatch.sh.sample
@${ECHO_MSG} "#####################################################################"
@${ECHO_MSG} "Installing ${PREFIX}/etc/rc.d/arpwatch.sh.sample file."
@${ECHO_MSG} "#####################################################################"
.include <bsd.port.mk>

View File

@ -21,22 +21,29 @@ case $1 in
start)
if [ ! -e "$PREFIX"/arpwatch/arp.dat ]; then
if [ -e "$PREFIX"/arpwatch/arp.dat- ]; then
cp "$PREFIX"/arpwatch/arp.dat- "$PREFIX"/arpwatch/arp.dat
cp "$PREFIX"/arpwatch/arp.dat- "$PREFIX"/arpwatch/arp.dat
else
touch "$PREFIX"/arpwatch/arp.dat
fi
fi
if [ ! -e "$PREFIX"/arpwatch/ether.dat ]; then
if [ -e "$PREFIX"/arpwatch/ether.dat- ]; then
cp "$PREFIX"/arpwatch/ether.dat- "$PREFIX"/arpwatch/ether.dat
else
touch "$PREFIX"/arpwatch/ether.dat
fi
fi
case ${arpwatch_interfaces} in
'')
if [ -x "$PREFIX"/sbin/arpwatch -a -d "$PREFIX"/arpwatch ]; then
"$PREFIX"/sbin/arpwatch && echo -n ' arpwatch'
"$PREFIX"/sbin/arpwatch ${arpwatch_flags} && echo -n ' arpwatch'
fi
;;
*)
for interface in ${arpwatch_interfaces}; do
touch "$PREFIX"/arpwatch/arp.${interface}.dat
"$PREFIX"/sbin/arpwatch -i "${interface}" -f arp.${interface}.dat && echo -n " arpwatch(${interface})"
"$PREFIX"/sbin/arpwatch -i "${interface}" && echo -n " arpwatch(${interface})"
done
;;
esac

View File

@ -0,0 +1,22 @@
--- ../arpwatch.orig/Makefile.in Wed Jun 14 20:39:55 2000
+++ ./Makefile.in Mon Sep 15 14:31:33 2003
@@ -45,7 +45,7 @@
PROG = arpwatch
CCOPT = @V_CCOPT@
INCLS = -I. @V_INCLS@
-DEFS = -DDEBUG @DEFS@ -DARPDIR=\"$(ARPDIR)\" -DPATH_SENDMAIL=\"$(SENDMAIL)\"
+DEFS = @DEFS@ -pthread -DARPDIR=\"$(ARPDIR)\" -DPATH_SENDMAIL=\"$(SENDMAIL)\"
# Standard CFLAGS
CFLAGS = $(CCOPT) $(DEFS) $(INCLS)
@@ -110,8 +110,8 @@
$(CC) $(CFLAGS) -o $@ zap.o intoa.o -lutil
install: force
- $(INSTALL) -m 555 -o bin -g bin arpwatch $(DESTDIR)$(BINDEST)
- $(INSTALL) -m 555 -o bin -g bin arpsnmp $(DESTDIR)$(BINDEST)
+ $(INSTALL) -s -m 555 -o bin -g bin arpwatch $(DESTDIR)$(BINDEST)
+ $(INSTALL) -s -m 555 -o bin -g bin arpsnmp $(DESTDIR)$(BINDEST)
install-man: force
$(INSTALL) -m 444 -o bin -g bin $(srcdir)/arpwatch.8 \

View File

@ -1,22 +1,25 @@
--- Makefile.in.orig Wed Jul 29 06:16:45 1998
+++ Makefile.in Fri Aug 21 10:57:51 1998
@@ -44,7 +44,7 @@
CC = @CC@
CCOPT = @V_CCOPT@
INCLS = -I. @V_INCLS@
-DEFS = -DDEBUG @DEFS@ -DARPDIR=\"$(ARPDIR)\" -DPATH_SENDMAIL=\"$(SENDMAIL)\"
+DEFS = @DEFS@ -DARPDIR=\"$(ARPDIR)\" -DPATH_SENDMAIL=\"$(SENDMAIL)\"
# Standard CFLAGS
CFLAGS = $(CCOPT) $(DEFS) $(INCLS)
@@ -109,8 +109,8 @@
$(CC) $(CFLAGS) -o $@ zap.o intoa.o -lutil
install: force
- $(INSTALL) -m 555 -o bin -g bin arpwatch $(DESTDIR)$(BINDEST)
- $(INSTALL) -m 555 -o bin -g bin arpsnmp $(DESTDIR)$(BINDEST)
+ $(INSTALL) -s -m 555 -o bin -g bin arpwatch $(DESTDIR)$(BINDEST)
+ $(INSTALL) -s -m 555 -o bin -g bin arpsnmp $(DESTDIR)$(BINDEST)
install-man: force
$(INSTALL) -m 444 -o bin -g bin $(srcdir)/arpwatch.8 \
--- ../arpwatch.orig/arpsnmp.8 Sun Sep 17 16:34:48 2000
+++ ./arpsnmp.8 Fri Sep 5 14:46:55 2003
@@ -30,6 +30,9 @@
] [
.B -f
.I datafile
+] [
+.B -m
+.I email
]
.I file
[
@@ -54,6 +57,12 @@
flag is used to set the ethernet/ip address database filename.
The default is
.IR arp.dat .
+.LP
+The
+.B -m
+flag specifies the address that will receive the emails.
+The default is
+.IR root .
.LP
Note that an empty
.I arp.dat

View File

@ -0,0 +1,67 @@
--- ../arpwatch.orig/arpsnmp.c Sun Jan 17 20:47:40 1999
+++ ./arpsnmp.c Mon Sep 15 14:31:33 2003
@@ -63,14 +63,17 @@
/* Forwards */
int main(int, char **);
int readsnmp(char *);
-int snmp_add(u_int32_t, u_char *, time_t, char *);
+int snmp_add(u_int32_t, u_char *, time_t, char *, char *);
__dead void usage(void) __attribute__((volatile));
char *prog;
+char *Watcher;
+
extern int optind;
extern int opterr;
extern char *optarg;
+char *interface = NULL;
int
main(int argc, char **argv)
@@ -90,7 +93,7 @@
}
opterr = 0;
- while ((op = getopt(argc, argv, "df:")) != EOF)
+ while ((op = getopt(argc, argv, "df:m:")) != EOF)
switch (op) {
case 'd':
@@ -105,6 +108,10 @@
arpfile = optarg;
break;
+ case 'm':
+ Watcher = optarg;
+ break;
+
default:
usage();
}
@@ -138,7 +145,7 @@
static time_t now;
int
-snmp_add(register u_int32_t a, register u_char *e, time_t t, register char *h)
+snmp_add(register u_int32_t a, register u_char *e, time_t t, register char *h, register char *i)
{
/* Watch for ethernet broadcast */
if (MEMCMP(e, zero, 6) == 0 || MEMCMP(e, allones, 6) == 0) {
@@ -153,7 +160,7 @@
}
/* Use current time (although it would be nice to subtract idle time) */
- return (ent_add(a, e, now, h));
+ return (ent_add(a, e, now, h, interface));
}
/* Process an snmp file */
@@ -184,6 +191,6 @@
(void)fprintf(stderr, "Version %s\n", version);
(void)fprintf(stderr,
- "usage: %s [-d] [-f datafile] file [...]\n", prog);
+ "usage: %s [-d] [-f datafile] [-m email] file [...]\n", prog);
exit(1);
}

View File

@ -0,0 +1,101 @@
--- ../arpwatch-2.1a11/arpwatch.8 Sun Oct 8 16:31:28 2000
+++ ./arpwatch.8 Mon Sep 15 17:30:45 2003
@@ -30,7 +30,10 @@
.B -dN
] [
.B -f
-.I datafile
+.I arpfile
+] [
+.B -e
+.I etherfile
] [
.B -i
.I interface
@@ -38,6 +41,9 @@
.br
.ti +8
[
+.B -m
+.I email
+] [
.B -n
.IR net [/ width
]] [
@@ -67,8 +73,24 @@
.IR arp.dat .
.LP
The
+.B -e
+flag is used to set the ethernet/interface database filename.
+The default is
+.IR ether.dat .
+.LP
+The
+.B -i
+flag is used to specify a single interface. By default,
+.B arpwatch
+will listen to all non-loopback interfaces. Using more than one
.B -i
-flag is used to override the default interface.
+option on the same command line is not supported.
+.LP
+The
+.B -m
+flag specifies the address that will receive the emails.
+The default is
+.IR root .
.LP
The
.B -n
@@ -81,6 +103,8 @@
The
.B -N
flag disables reporting any bogons.
+It is highly recommended that this flag be used on machines with
+multiple interfaces.
.LP
The
.B -r
@@ -96,6 +120,8 @@
.LP
Note that an empty
.I arp.dat
+and
+.I ether.dat
file must be created before the first time you run
.BR arpwatch .
.LP
@@ -105,12 +131,19 @@
(and
.BR arpsnmp (1)):
.TP
+.B "new ethernet device"
+The ethernet address has not been seen before.
+.TP
+.B "ethernet device changed interfaces"
+An ethernet address associated with one interface has moved to a
+different interface.
+.TP
.B "new activity"
This ethernet/ip address pair has been used for the first time six
months or more.
.TP
-.B "new station"
-The ethernet address has not been seen before.
+.B "new active IP address"
+The IP address has not been seen before.
.TP
.B "flip flop"
The ethernet address has changed from the most recently seen address to
@@ -152,8 +185,9 @@
.na
.nh
.nf
-/usr/operator/arpwatch - default directory
+/usr/local/arpwatch - default directory
arp.dat - ethernet/ip address database
+ether.dat - ethernet/interface address database
ethercodes.dat - vendor ethernet block list
.ad
.hy

View File

@ -1,20 +1,316 @@
--- configure.orig Thu Jun 15 01:37:53 2000
+++ configure Tue Sep 5 02:57:33 2000
@@ -649,7 +649,7 @@
:
fi
--- arpwatch.c.orig Sat Oct 14 04:07:35 2000
+++ arpwatch.c Tue Jan 20 00:22:23 2004
@@ -36,6 +36,7 @@
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/time.h>
+#include <pthread.h>
- V_CCOPT="-O"
+# V_CCOPT="-O"
V_INCLS=""
if test "${srcdir}" != "." ; then
V_INCLS="-I\$\(srcdir\)"
@@ -2599,7 +2599,7 @@
fi
V_CCOPT="$V_CCOPT -Wall"
if test $ac_cv_lbl_gcc_vers -gt 1 ; then
- V_CCOPT="$V_CCOPT -Wmissing-prototypes -Wstrict-prototypes"
+# V_CCOPT="$V_CCOPT -Wmissing-prototypes -Wstrict-prototypes"
fi
fi
else
#if __STDC__
struct mbuf;
@@ -107,6 +108,8 @@
char *prog;
+char *Watcher = NULL;
+
int can_checkpoint;
int swapped;
int nobogons;
@@ -123,6 +126,14 @@
static int nets_ind;
static int nets_size;
+struct aw_threads {
+ char *interface;
+ pthread_t thread;
+};
+
+struct aw_threads *threads = NULL;
+extern pthread_mutex_t mtx_einfo, mtx_ainfo;
+
extern int optind;
extern int opterr;
extern char *optarg;
@@ -145,14 +156,14 @@
main(int argc, char **argv)
{
register char *cp;
- register int op, pid, snaplen, timeout, linktype, status;
+ register int op, pid, if_cnt, i;
#ifdef TIOCNOTTY
register int fd;
#endif
- register pcap_t *pd;
- register char *interface, *rfilename;
- struct bpf_program code;
+ register char *rfilename;
char errbuf[PCAP_ERRBUF_SIZE];
+ pcap_if_t *adp, *alldevsp = NULL;
+ char *interface = NULL;
if (argv[0] == NULL)
prog = "arpwatch";
@@ -167,10 +178,8 @@
}
opterr = 0;
- interface = NULL;
rfilename = NULL;
- pd = NULL;
- while ((op = getopt(argc, argv, "df:i:n:Nr:")) != EOF)
+ while ((op = getopt(argc, argv, "de:f:i:m:n:Nr:")) != EOF)
switch (op) {
case 'd':
@@ -181,6 +190,10 @@
#endif
break;
+ case 'e':
+ etherfile = optarg;
+ break;
+
case 'f':
arpfile = optarg;
break;
@@ -202,6 +215,10 @@
rfilename = optarg;
break;
+ case 'm':
+ Watcher = optarg;
+ break;
+
default:
usage();
}
@@ -213,19 +230,23 @@
net = 0;
netmask = 0;
} else {
- /* Determine interface if not specified */
- if (interface == NULL &&
- (interface = pcap_lookupdev(errbuf)) == NULL) {
- (void)fprintf(stderr, "%s: lookup_device: %s\n",
- prog, errbuf);
- exit(1);
- }
+ /* if not specified, do all non loopback interfaces */
+ if (interface == NULL) {
- /* Determine network and netmask */
- if (pcap_lookupnet(interface, &net, &netmask, errbuf) < 0) {
- (void)fprintf(stderr, "%s: bad interface %s: %s\n",
- prog, interface, errbuf);
- exit(1);
+ pcap_findalldevs(&alldevsp, errbuf);
+ if (alldevsp == NULL) {
+ (void)fprintf(stderr, "no suitable interfaces\n");
+ exit(1);
+ }
+
+ if_cnt = 0;
+ for(adp = alldevsp; adp != NULL; adp = adp->next) {
+ if (adp->flags != PCAP_IF_LOOPBACK)
+ ++if_cnt;
+ }
+
+ } else {
+ if_cnt = 1;
}
/* Drop into the background if not debugging */
@@ -238,7 +259,7 @@
exit(0);
(void)close(fileno(stdin));
(void)close(fileno(stdout));
- (void)close(fileno(stderr));
+
#ifdef TIOCNOTTY
fd = open("/dev/tty", O_RDWR);
if (fd >= 0) {
@@ -251,12 +272,82 @@
}
}
- openlog(prog, 0, LOG_DAEMON);
+ if (debug)
+ openlog(prog, LOG_PERROR, LOG_DAEMON);
+ else
+ openlog(prog, 0, LOG_DAEMON);
if (chdir(arpdir) < 0) {
syslog(LOG_ERR, "chdir(%s): %m", arpdir);
syslog(LOG_ERR, "(using current working directory)");
}
+ /* Read in database */
+ initializing = 1;
+ if (!readdata())
+ exit(1);
+ sorteinfo();
+#ifdef DEBUG
+ if (debug > 2) {
+ debugdump();
+ exit(0);
+ }
+#endif
+ initializing = 0;
+
+ (void)setsignal(SIGINT, die);
+ (void)setsignal(SIGTERM, die);
+ (void)setsignal(SIGHUP, die);
+ if (rfilename == NULL) {
+ (void)setsignal(SIGQUIT, checkpoint);
+ (void)setsignal(SIGALRM, checkpoint);
+ (void)alarm(CHECKPOINT);
+ }
+
+ threads = (struct aw_threads *) malloc(sizeof(struct aw_threads) * (if_cnt + 1));
+ memset((char *)threads, 0, sizeof(*threads) * (if_cnt + 1));
+ pthread_mutex_init(&mtx_einfo, NULL);
+ pthread_mutex_init(&mtx_ainfo, NULL);
+
+ if (interface != NULL)
+ {
+ threads[0].interface = interface;
+ pthread_create(&threads[0].thread, NULL, (void *)pcap_thread, interface);
+ }
+ else
+ {
+ i = 0;
+
+ for (adp = alldevsp; adp != NULL; adp = adp->next)
+ if (adp->flags != PCAP_IF_LOOPBACK)
+ {
+ threads[i].interface = adp->name;
+ pthread_create(&threads[i++].thread, NULL, (void *)pcap_thread, adp->name);
+ }
+ }
+
+ for (i=0; i < if_cnt; i++)
+ pthread_join(threads[i].thread, NULL);
+
+ if (!dump())
+ exit(1);
+ exit(0);
+}
+
+int
+pcap_thread(char *interface)
+{
+ register char *rfilename = NULL;
+ char errbuf[PCAP_ERRBUF_SIZE];
+ register pcap_t *pd = NULL;
+ register int snaplen, timeout, linktype, status;
+ struct bpf_program code;
+
+ /* Determine network and netmask */
+ if (pcap_lookupnet(interface, &net, &netmask, errbuf) < 0) {
+ (void)fprintf(stderr, "%s: bad interface %s: %s\n",
+ prog, interface, errbuf);
+ return(1);
+ }
if (rfilename != NULL) {
pd = pcap_open_offline(rfilename, errbuf);
@@ -306,27 +397,7 @@
if (rfilename == NULL)
syslog(LOG_INFO, "listening on %s", interface);
- /* Read in database */
- initializing = 1;
- if (!readdata())
- exit(1);
- sorteinfo();
-#ifdef DEBUG
- if (debug > 2) {
- debugdump();
- exit(0);
- }
-#endif
- initializing = 0;
- (void)setsignal(SIGINT, die);
- (void)setsignal(SIGTERM, die);
- (void)setsignal(SIGHUP, die);
- if (rfilename == NULL) {
- (void)setsignal(SIGQUIT, checkpoint);
- (void)setsignal(SIGALRM, checkpoint);
- (void)alarm(CHECKPOINT);
- }
switch (linktype) {
@@ -347,9 +418,7 @@
exit(1);
}
pcap_close(pd);
- if (!dump())
- exit(1);
- exit(0);
+ return(0);
}
/* Process an ethernet arp/rarp packet */
@@ -362,6 +431,8 @@
register u_char *sea, *sha;
register time_t t;
u_int32_t sia;
+ register pthread_t thread_self = NULL;
+ register struct aw_threads *atp = threads;
eh = (struct ether_header *)p;
ea = (struct ether_arp *)(eh + 1);
@@ -400,9 +471,16 @@
/* Got a live one */
t = h->ts.tv_sec;
can_checkpoint = 0;
- if (!ent_add(sia, sea, t, NULL))
+ thread_self = pthread_self();
+
+ for (atp = threads; atp != NULL; atp++)
+ if (pthread_equal(atp->thread, thread_self))
+ break;
+
+ if (!ent_add(sia, sea, t, NULL, atp->interface))
syslog(LOG_ERR, "ent_add(%s, %s, %ld) failed",
intoa(sia), e2str(sea), t);
+
can_checkpoint = 1;
}
@@ -507,6 +585,8 @@
register u_char *sea, *sha;
register time_t t;
u_int32_t sia;
+ register pthread_t thread_self = NULL;
+ register struct aw_threads *atp = threads;
fh = (struct fddi_header *)p;
ea = (struct ether_arp *)(fh + 1);
@@ -549,7 +629,13 @@
/* Got a live one */
t = h->ts.tv_sec;
can_checkpoint = 0;
- if (!ent_add(sia, sea, t, NULL))
+ thread_self = pthread_self();
+
+ for (atp = threads; atp != NULL; atp++)
+ if (atp->thread == thread_self)
+ break;
+
+ if (!ent_add(sia, sea, t, NULL, atp->interface))
syslog(LOG_ERR, "ent_add(%s, %s, %ld) failed",
intoa(sia), e2str(sea), t);
can_checkpoint = 1;
@@ -750,7 +836,7 @@
extern char version[];
(void)fprintf(stderr, "Version %s\n", version);
- (void)fprintf(stderr, "usage: %s [-dN] [-f datafile] [-i interface]"
- " [-n net[/width]] [-r file]\n", prog);
+ (void)fprintf(stderr, "usage: %s [-dN] [-f arpfile] [-e etherfile] [-i interface]"
+ " [-m email] [-n net[/width]] [-r file]\n", prog);
exit(1);
}

View File

@ -1,17 +1,16 @@
--- ethercodes.dat.orig Thu May 3 21:59:10 2001
+++ ethercodes.dat Tue Nov 11 10:59:56 2003
@@ -4419,7 +4419,7 @@
0:d0:b4 KATSUJIMA CO., LTD.
0:d0:b5 DOTCOM
0:d0:b6 CRESCENT NETWORKS, INC.
-0:d0:b7 INTEL CORPOTATION
+0:d0:b7 INTEL CORPORATION
0:d0:b8 IOMEGA CORP.
0:d0:b9 MICROTEK INTERNATIONAL, INC.
0:d0:ba CISCO SYSTEMS, INC.
@@ -4964,3 +4964,5 @@
c0:0:0 Western Digital (may be reversed 00 00 C0?)
e2:c:f Kingston Technologies
ec:10:0 Enance Source Co., Ltd. PC clones(?)
+0:bd:11 VMWare Inc
+0:bd:fb VMWare Inc
--- ../arpwatch-2.1a11/arpwatch.h Sat Sep 30 19:40:55 2000
+++ ./arpwatch.h Fri Sep 12 17:01:42 2003
@@ -1,6 +1,7 @@
/* @(#) $Id: arpwatch.h,v 1.29 2000/09/30 23:40:49 leres Exp $ (LBL) */
#define ARPFILE "arp.dat"
+#define ETHERFILE "ether.dat"
#define ETHERCODES "ethercodes.dat"
#define CHECKPOINT (15*60) /* Checkpoint time in seconds */
@@ -40,3 +41,5 @@
#define SPA(ap) ((ap)->arp_spa)
#define TPA(ap) ((ap)->arp_tpa)
#endif
+
+int pcap_thread(char *);

View File

@ -1,39 +1,14 @@
--- arpwatch.c.orig Thu Feb 22 22:47:29 2001
+++ arpwatch.c Thu Feb 22 22:47:29 2001
@@ -107,6 +107,8 @@
char *prog;
+char *Watcher = NULL;
--- ../arpwatch.orig/configure.in Sat Oct 14 14:19:10 2000
+++ ./configure.in Wed Sep 10 13:08:05 2003
@@ -170,6 +170,11 @@
if test ! -f arp.dat ; then
echo 'creating empty arp.dat file'
touch arp.dat
+fi
+
int can_checkpoint;
int swapped;
int nobogons;
@@ -170,7 +172,7 @@
interface = NULL;
rfilename = NULL;
pd = NULL;
- while ((op = getopt(argc, argv, "df:i:n:Nr:")) != EOF)
+ while ((op = getopt(argc, argv, "df:i:m:n:Nr:")) != EOF)
switch (op) {
case 'd':
@@ -202,6 +204,10 @@
rfilename = optarg;
break;
+ case 'm':
+ Watcher = optarg;
+ break;
+
default:
usage();
}
@@ -751,6 +757,6 @@
(void)fprintf(stderr, "Version %s\n", version);
(void)fprintf(stderr, "usage: %s [-dN] [-f datafile] [-i interface]"
- " [-n net[/width]] [-r file]\n", prog);
+ " [-m email] [-n net[/width]] [-r file]\n", prog);
exit(1);
}
+if test ! -f ether.dat ; then
+ echo 'creating empty ether.dat file'
+ touch ether.dat
fi
if test -f .devel ; then

View File

@ -1,55 +1,32 @@
--- report.c.orig Sun Oct 1 00:41:10 2000
+++ report.c Thu May 16 11:34:33 2002
@@ -45,6 +45,8 @@
#include <ctype.h>
#include <errno.h>
+#include <fcntl.h>
+#include <paths.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
@@ -70,6 +72,8 @@
#define PLURAL(n) ((n) == 1 || (n) == -1 ? "" : "s")
+extern char *Watcher;
--- ../arpwatch.orig/configure Wed May 16 14:26:11 2001
+++ ./configure Wed Sep 10 13:08:05 2003
@@ -649,7 +649,7 @@
:
fi
- V_CCOPT="-O"
+# V_CCOPT="-O"
V_INCLS=""
if test "${srcdir}" != "." ; then
V_INCLS="-I\$\(srcdir\)"
@@ -2496,7 +2496,7 @@
fi
V_CCOPT="$V_CCOPT -Wall"
if test $ac_cv_lbl_gcc_vers -gt 1 ; then
- V_CCOPT="$V_CCOPT -Wmissing-prototypes -Wstrict-prototypes"
+# V_CCOPT="$V_CCOPT -Wmissing-prototypes -Wstrict-prototypes"
fi
fi
else
@@ -3075,6 +3075,11 @@
if test ! -f arp.dat ; then
echo 'creating empty arp.dat file'
touch arp.dat
+fi
+
static int cdepth; /* number of outstanding children */
static char *fmtdate(time_t);
@@ -240,7 +244,7 @@
register FILE *f;
char tempfile[64], cpu[64], os[64];
char *fmt = "%20s: %s\n";
- char *watcher = WATCHER;
+ char *watcher = Watcher ? Watcher : WATCHER;
char *watchee = WATCHEE;
char *sendmail = PATH_SENDMAIL;
char *unknown = "<unknown>";
@@ -344,6 +348,25 @@
exit(1);
}
/* XXX Need to freopen()? */
+
+ /*
+ * Open /dev/null as stdout and stderr so that sendmail 8.12.1 (and
+ * above ?) won't complain about missing file descriptors.
+ */
+ if ((fd = open(_PATH_DEVNULL, O_RDWR)) == -1) {
+ syslog(LOG_ERR, "Cannot open %s: %m", _PATH_DEVNULL);
+ exit(1);
+ }
+ if (dup2(fd, STDOUT_FILENO) == -1) {
+ syslog(LOG_ERR, "Cannot dup2 %s to stdout: %m", _PATH_DEVNULL);
+ exit(1);
+ }
+ if (dup2(fd, STDERR_FILENO) == -1) {
+ syslog(LOG_ERR, "Cannot dup2 %s to stderr: %m", _PATH_DEVNULL);
+ exit(1);
+ }
+ close(fd);
+
/* Always Deliver interactively (pause when child depth gets large) */
execl(sendmail, "sendmail", "-odi", watcher, NULL);
syslog(LOG_ERR, "execl: %s: %m", sendmail);
+if test ! -f ether.dat ; then
+ echo 'creating empty ether.dat file'
+ touch ether.dat
fi
if test -f .devel ; then

View File

@ -1,39 +1,271 @@
--- arpsnmp.c.orig Mon Jan 18 01:47:40 1999
+++ arpsnmp.c Thu Feb 22 22:47:29 2001
@@ -68,6 +68,8 @@
char *prog;
+char *Watcher;
--- ../arpwatch.orig/db.c Sat Sep 30 19:39:58 2000
+++ ./db.c Mon Sep 15 13:17:07 2003
@@ -41,6 +41,7 @@
#include <string.h>
#include <syslog.h>
#include <unistd.h>
+#include <pthread.h>
#include "gnuc.h"
#ifdef HAVE_OS_PROTO_H
@@ -54,18 +55,9 @@
#include "report.h"
#include "util.h"
-#define HASHSIZE (2 << 15)
-
#define NEWACTIVITY_DELTA (6*30*24*60*60) /* 6 months in seconds */
#define FLIPFLIP_DELTA (24*60*60) /* 24 hours in seconds */
-/* Ethernet info */
-struct einfo {
- u_char e[6]; /* ether address */
- char h[34]; /* simple hostname */
- time_t t; /* timestamp */
-};
-
/* Address info */
struct ainfo {
u_int32_t a; /* ip address */
@@ -78,22 +70,69 @@
/* Address hash table */
static struct ainfo ainfo_table[HASHSIZE];
+
extern int optind;
extern int opterr;
extern char *optarg;
@@ -90,7 +92,7 @@
}
opterr = 0;
- while ((op = getopt(argc, argv, "df:")) != EOF)
+ while ((op = getopt(argc, argv, "df:m:")) != EOF)
switch (op) {
case 'd':
@@ -105,6 +107,10 @@
arpfile = optarg;
break;
+ case 'm':
+ Watcher = optarg;
+ break;
+/* Ethernet hash table */
+struct einfo einfo_table[HASHSIZE];
+int et_cnt = 0;
+
default:
usage();
static void alist_alloc(struct ainfo *);
int cmpeinfo(const void *, const void *);
-static struct einfo *elist_alloc(u_int32_t, u_char *, time_t, char *);
+static struct einfo *elist_alloc(u_int32_t, u_char *, time_t, char *, char *);
static struct ainfo *ainfo_find(u_int32_t);
+static struct einfo *einfo_find(u_char *);
static void check_hname(struct ainfo *);
struct ainfo *newainfo(void);
+pthread_mutex_t mtx_einfo, mtx_ainfo;
+
int
-ent_add(register u_int32_t a, register u_char *e, time_t t, register char *h)
+ent_add(register u_int32_t a, register u_char *e, time_t t, register char *h, register char *interface)
{
register struct ainfo *ap;
- register struct einfo *ep;
+ struct einfo *ep;
register int i;
register u_int len;
u_char *e2;
time_t t2;
+ register evt_type event = NULL;
+ char *if2 = NULL;
+
+ pthread_mutex_lock(&mtx_einfo);
+
+ /* Lookup ethernet address */
+ ep = einfo_find(e);
+
+ /* New einfo? (elist_alloc makes 16 at a time -- no thanks) */
+ if (ep == NULL && ! initializing) {
+ if (et_cnt >= HASHSIZE) {
+ syslog(LOG_ERR, "ERROR: einfo_table too big");
+ } else {
+ ep = &einfo_table[et_cnt++];
+ BCOPY(e, ep->e, sizeof(ep->e));
+ if (h == NULL)
+ h = getsname(a);
+ if (h != NULL && !isdigit((int)*h))
+ strncpy(ep->h, h, sizeof(ep->h));
+ ep->t = t;
+ strncpy(ep->iface, interface, sizeof(ep->iface));
+ event |= ETHER_NEW;
+ e2 = NULL;
+ t2 = NULL;
+ }
+ } else if (! initializing) {
+ if (strncmp(ep->iface, interface, sizeof(ep->iface)) != 0) {
+ event |= ETHER_IFCHG;
+ asprintf(&if2, "%s", ep->iface);
+ memset((char *)ep->iface, 0, sizeof(ep->iface));
+ BCOPY(interface, ep->iface, sizeof(ep->iface));
+ e2 = NULL;
+ t2 = ep->t;
+ ep->t = t;
+ }
+ }
+
+ pthread_mutex_unlock(&mtx_einfo);
+ pthread_mutex_lock(&mtx_ainfo);
/* Lookup ip address */
ap = ainfo_find(a);
@@ -101,28 +140,30 @@
/* Check for the usual case first */
if (ap->ecount > 0) {
ep = ap->elist[0];
- if (MEMCMP(e, ep->e, 6) == 0) {
+ if (MEMCMP(e, ep->e, sizeof(ep->e)) == 0) {
if (t - ep->t > NEWACTIVITY_DELTA) {
- report("new activity", a, e, NULL, &t, &ep->t);
+ event |= ACTIVITY_NEW;
+ e2 = NULL;
+ t2 = ep->t;
check_hname(ap);
}
ep->t = t;
- return (1);
}
@@ -184,6 +190,6 @@
(void)fprintf(stderr, "Version %s\n", version);
(void)fprintf(stderr,
- "usage: %s [-d] [-f datafile] file [...]\n", prog);
+ "usage: %s [-d] [-f datafile] [-m email] file [...]\n", prog);
exit(1);
}
/* Check for a virgin ainfo record */
if (ap->ecount == 0) {
ap->ecount = 1;
- ap->elist[0] = elist_alloc(a, e, t, h);
- report("new station", a, e, NULL, &t, NULL);
- return (1);
+ ap->elist[0] = elist_alloc(a, e, t, h, interface);
+ event |= IP_NEW;
+ e2 = NULL;
+ t2 = NULL;
}
/* Check for a flip-flop */
if (ap->ecount > 1) {
ep = ap->elist[1];
- if (MEMCMP(e, ep->e, 6) == 0) {
+ if (MEMCMP(e, ep->e, sizeof(ep->e)) == 0) {
/*
* Suppress report when less than
* FLIPFLOP_DELTA and one of the two ethernet
@@ -131,48 +172,76 @@
t2 = ap->elist[0]->t;
e2 = ap->elist[0]->e;
if (t - t2 < FLIPFLIP_DELTA &&
- (isdecnet(e) || isdecnet(e2)))
+ (isdecnet(e) || isdecnet(e2))) {
dosyslog(LOG_INFO,
"suppressed DECnet flip flop", a, e, e2);
- else
- report("flip flop", a, e, e2, &t, &t2);
+ event |= FLIPFLOP_DECNET;
+ } else {
+ event |= FLIPFLOP;
+ }
+
ap->elist[1] = ap->elist[0];
ap->elist[0] = ep;
ep->t = t;
check_hname(ap);
- return (1);
}
}
for (i = 2; i < ap->ecount; ++i) {
ep = ap->elist[i];
- if (MEMCMP(e, ep->e, 6) == 0) {
+ if (MEMCMP(e, ep->e, sizeof(ep->e)) == 0) {
/* An old entry comes to life */
e2 = ap->elist[0]->e;
t2 = ap->elist[0]->t;
dosyslog(LOG_NOTICE, "reused old ethernet address",
a, e, e2);
+ event |= IP_ETHER_REUSE;
/* Shift entries down */
len = i * sizeof(ap->elist[0]);
BCOPY(&ap->elist[0], &ap->elist[1], len);
ap->elist[0] = ep;
ep->t = t;
check_hname(ap);
- return (1);
}
}
- /* New ether address */
- e2 = ap->elist[0]->e;
- t2 = ap->elist[0]->t;
- report("changed ethernet address", a, e, e2, &t, &t2);
- /* Make room at head of list */
- alist_alloc(ap);
- len = ap->ecount * sizeof(ap->elist[0]);
- BCOPY(&ap->elist[0], &ap->elist[1], len);
- ap->elist[0] = elist_alloc(a, e, t, h);
- ++ap->ecount;
- return (1);
+ /* as originally written, any of these conditions would cause this
+ * block never to be reached. ETHER_NEW and ETHER_IFCHG have been added to that list.
+ */
+ if (event & ~(ACTIVITY_NEW | IP_NEW | FLIPFLOP | FLIPFLOP_DECNET | IP_ETHER_REUSE | ETHER_NEW | ETHER_IFCHG)) {
+ /* New ether address */
+ e2 = ap->elist[0]->e;
+ t2 = ap->elist[0]->t;
+ event |= IP_ETHERCHG;
+ /* Make room at head of list */
+ alist_alloc(ap);
+ len = ap->ecount * sizeof(ap->elist[0]);
+ BCOPY(&ap->elist[0], &ap->elist[1], len);
+ ap->elist[0] = elist_alloc(a, e, t, h, interface);
+ ++ap->ecount;
+ }
+
+ pthread_mutex_unlock(&mtx_ainfo);
+
+ report(event, a, e, e2, &t, &t2, interface, if2);
+
+ if (if2 != NULL)
+ free(if2);
+
+ return(1);
+}
+
+static struct einfo *
+einfo_find(register u_char *e)
+{
+ register int i;
+
+ for (i=0; i < et_cnt; i++) {
+ if (MEMCMP(einfo_table[i].e, e, sizeof(einfo_table[i].e)) == 0)
+ return(&einfo_table[i]);
+ }
+
+ return(NULL);
}
static struct ainfo *
@@ -259,7 +328,7 @@
/* Allocate and initialize a elist struct */
static struct einfo *
elist_alloc(register u_int32_t a, register u_char *e, register time_t t,
- register char *h)
+ register char *h, register char *interface)
{
register struct einfo *ep;
register u_int size;
@@ -280,12 +349,16 @@
ep = elist++;
--eleft;
- BCOPY(e, ep->e, 6);
+ BCOPY(e, ep->e, sizeof(ep->e));
if (h == NULL && !initializing)
h = getsname(a);
if (h != NULL && !isdigit((int)*h))
- strcpy(ep->h, h);
+ strncpy(ep->h, h, sizeof(ep->h));
ep->t = t;
+
+ if (interface != NULL)
+ strncpy(ep->iface, interface, sizeof(ep->iface));
+
return (ep);
}
@@ -304,7 +377,7 @@
if (!isdigit((int)*h) && strcmp(h, ep->h) != 0) {
syslog(LOG_INFO, "hostname changed %s %s %s -> %s",
intoa(ap->a), e2str(ep->e), ep->h, h);
- strcpy(ep->h, h);
+ strncpy(ep->h, h, sizeof(ep->h));
}
}

View File

@ -1,25 +1,25 @@
--- arpwatch.8.orig Sun Oct 8 21:31:28 2000
+++ arpwatch.8 Thu Feb 22 22:47:29 2001
@@ -38,6 +38,9 @@
.br
.ti +8
[
+.B -m
+.I email
+] [
.B -n
.IR net [/ width
]] [
@@ -69,6 +72,12 @@
The
.B -i
flag is used to override the default interface.
+.LP
+The
+.B -m
+flag specifies the address that will receive the emails.
+The default is
+.IR root .
.LP
The
.B -n
--- ../arpwatch.orig/db.h Wed Jun 5 01:39:30 1996
+++ ./db.h Mon Sep 15 14:55:27 2003
@@ -1,10 +1,21 @@
/* @(#) $Header: db.h,v 1.8 96/06/04 22:39:29 leres Exp $ (LBL) */
+#define HASHSIZE (2 << 15)
+
typedef void (*ent_process)(u_int32_t, u_char *, time_t, char *);
#ifdef DEBUG
void debugdump(void);
#endif
-int ent_add(u_int32_t, u_char *, time_t, char *);
+int ent_add(u_int32_t, u_char *, time_t, char *, char *);
int ent_loop(ent_process);
void sorteinfo(void);
+
+/* Ethernet info */
+struct einfo {
+ u_char e[6]; /* ether address */
+ char h[34]; /* simple hostname */
+ time_t t; /* timestamp */
+ char iface[10]; /* interface name */
+};
+

View File

@ -1,25 +1,17 @@
--- arpsnmp.8.orig Sun Sep 17 21:34:48 2000
+++ arpsnmp.8 Thu Feb 22 22:47:29 2001
@@ -30,6 +30,9 @@
] [
.B -f
.I datafile
+] [
+.B -m
+.I email
]
.I file
[
@@ -54,6 +57,12 @@
flag is used to set the ethernet/ip address database filename.
The default is
.IR arp.dat .
+.LP
+The
+.B -m
+flag specifies the address that will receive the emails.
+The default is
+.IR root .
.LP
Note that an empty
.I arp.dat
--- ethercodes.dat.orig Thu May 3 21:59:10 2001
+++ ethercodes.dat Tue Nov 11 09:35:25 2003
@@ -4419,7 +4419,7 @@
0:d0:b4 KATSUJIMA CO., LTD.
0:d0:b5 DOTCOM
0:d0:b6 CRESCENT NETWORKS, INC.
-0:d0:b7 INTEL CORPOTATION
+0:d0:b7 INTEL CORPORATION
0:d0:b8 IOMEGA CORP.
0:d0:b9 MICROTEK INTERNATIONAL, INC.
0:d0:ba CISCO SYSTEMS, INC.
@@ -4964,3 +4964,5 @@
c0:0:0 Western Digital (may be reversed 00 00 C0?)
e2:c:f Kingston Technologies
ec:10:0 Enance Source Co., Ltd. PC clones(?)
+0:bd:11 VMWare Inc
+0:bd:fb VMWare Inc

View File

@ -0,0 +1,26 @@
--- ../arpwatch.orig/file.c Fri Oct 13 18:29:43 2000
+++ ./file.c Fri Sep 12 17:01:42 2003
@@ -20,7 +20,7 @@
*/
#ifndef lint
static const char rcsid[] =
- "@(#) $Id: file.c,v 1.25 2000/10/13 22:29:42 leres Exp $ (LBL)";
+ "@(#) $Id: file.c,v 1.2 2003/09/12 21:01:42 mdg Exp $ (LBL)";
#endif
/*
@@ -130,7 +130,13 @@
}
}
- if (!(*fn)(a, e, t, h))
+ /* NULL for the interface here is ok because we don't do
+ * anything in ent_add() for einfo when initializing,
+ * and the only time this code section is reached is
+ * during initialization (via readdata()). snmp_add()
+ * is irrelevant, as no ether tracking has been added to it.
+ */
+ if (!(*fn)(a, e, t, h, NULL))
return(0);
}

View File

@ -0,0 +1,9 @@
--- ../arpwatch.orig/file.h Sun Jan 17 20:46:04 1999
+++ ./file.h Fri Sep 12 17:01:42 2003
@@ -1,5 +1,5 @@
/* @(#) $Header: file.h,v 1.4 99/01/17 17:46:03 leres Exp $ (LBL) */
-typedef int (*file_process)(u_int32_t, u_char *, time_t, char *);
+typedef int (*file_process)(u_int32_t, u_char *, time_t, char *, char *);
int file_loop(FILE *, file_process, const char *);

View File

@ -0,0 +1,126 @@
--- ../arpwatch.orig/report.c Sat Sep 30 19:41:10 2000
+++ ./report.c Fri Sep 12 18:57:04 2003
@@ -45,6 +45,8 @@
#include <ctype.h>
#include <errno.h>
+#include <fcntl.h>
+#include <paths.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
@@ -70,6 +72,8 @@
#define PLURAL(n) ((n) == 1 || (n) == -1 ? "" : "s")
+extern char *Watcher;
+
static int cdepth; /* number of outstanding children */
static char *fmtdate(time_t);
@@ -232,15 +236,16 @@
}
void
-report(register char *title, register u_int32_t a, register u_char *e1,
- register u_char *e2, register time_t *t1p, register time_t *t2p)
+report(evt_type event, register u_int32_t a, register u_char *e1,
+ register u_char *e2, register time_t *t1p, register time_t *t2p,
+ register char *interface, register char *old_interface)
{
register char *cp, *hn;
register int fd, pid;
register FILE *f;
char tempfile[64], cpu[64], os[64];
char *fmt = "%20s: %s\n";
- char *watcher = WATCHER;
+ char *watcher = Watcher ? Watcher : WATCHER;
char *watchee = WATCHEE;
char *sendmail = PATH_SENDMAIL;
char *unknown = "<unknown>";
@@ -251,9 +256,15 @@
if (initializing)
return;
+ /* these types are sent to syslog instead of reported on.
+ * only continue if there are other events as well
+ */
+ if (event == NULL || (event & ~(IP_ETHER_REUSE | FLIPFLOP_DECNET) == 0))
+ return;
+
if (debug) {
if (debug > 1) {
- dosyslog(LOG_NOTICE, title, a, e1, e2);
+ dosyslog(LOG_NOTICE, "event", a, e1, e2);
return;
}
f = stdout;
@@ -270,7 +281,7 @@
}
/* Syslog this event too */
- dosyslog(LOG_NOTICE, title, a, e1, e2);
+ dosyslog(LOG_NOTICE, "event", a, e1, e2);
/* Update child depth */
++cdepth;
@@ -304,12 +315,31 @@
(void)fprintf(f, "To: %s\n", watcher);
hn = gethname(a);
if (!isdigit(*hn))
- (void)fprintf(f, "Subject: %s (%s)\n", title, hn);
+ (void)fprintf(f, "Subject: Arpwatch Event (%s)\n", hn);
else {
- (void)fprintf(f, "Subject: %s\n", title);
+ (void)fprintf(f, "Subject: Arpwatch Event\n");
hn = unknown;
}
(void)putc('\n', f);
+
+ if (event & ETHER_NEW)
+ (void)fprintf(f, fmt, "event", "new ethernet device");
+ if (event & ETHER_IFCHG)
+ (void)fprintf(f, fmt, "event", "ethernet device changed interfaces");
+ if (event & ACTIVITY_NEW)
+ (void)fprintf(f, fmt, "event", "new activity");
+ if (event & IP_NEW)
+ (void)fprintf(f, fmt, "event", "new active IP address");
+ if (event & IP_ETHERCHG)
+ (void)fprintf(f, fmt, "event", "IP changed ethernet address");
+ if (event & FLIPFLOP)
+ (void)fprintf(f, fmt, "event", "flip flop");
+
+ (void)fprintf(f, fmt, "interface", interface);
+
+ if (old_interface != NULL)
+ (void)fprintf(f, fmt, "old interface", old_interface);
+
(void)fprintf(f, fmt, "hostname", hn);
(void)fprintf(f, fmt, "ip address", intoa(a));
(void)fprintf(f, fmt, "ethernet address", e2str(e1));
@@ -344,6 +374,25 @@
exit(1);
}
/* XXX Need to freopen()? */
+
+ /*
+ * Open /dev/null as stdout and stderr so that sendmail 8.12.1 (and
+ * above ?) won't complain about missing file descriptors.
+ */
+ if ((fd = open(_PATH_DEVNULL, O_RDWR)) == -1) {
+ syslog(LOG_ERR, "Cannot open %s: %m", _PATH_DEVNULL);
+ exit(1);
+ }
+ if (dup2(fd, STDOUT_FILENO) == -1) {
+ syslog(LOG_ERR, "Cannot dup2 %s to stdout: %m", _PATH_DEVNULL);
+ exit(1);
+ }
+ if (dup2(fd, STDERR_FILENO) == -1) {
+ syslog(LOG_ERR, "Cannot dup2 %s to stderr: %m", _PATH_DEVNULL);
+ exit(1);
+ }
+ close(fd);
+
/* Always Deliver interactively (pause when child depth gets large) */
execl(sendmail, "sendmail", "-odi", watcher, NULL);
syslog(LOG_ERR, "execl: %s: %m", sendmail);

View File

@ -0,0 +1,20 @@
--- ../arpwatch.orig/report.h Wed Jun 5 01:40:54 1996
+++ ./report.h Mon Sep 15 15:03:20 2003
@@ -1,3 +1,16 @@
/* @(#) $Header: report.h,v 1.3 96/06/04 22:40:53 leres Exp $ (LBL) */
-void report(char *, u_int32_t, u_char *, u_char *, time_t *, time_t *);
+
+typedef enum
+ {
+ ETHER_NEW=1,
+ ETHER_IFCHG=2,
+ ACTIVITY_NEW=4,
+ IP_NEW=8,
+ IP_ETHERCHG=16,
+ IP_ETHER_REUSE=32,
+ FLIPFLOP=64,
+ FLIPFLOP_DECNET=128
+ } evt_type;
+
+void report(evt_type, u_int32_t, u_char *, u_char *, time_t *, time_t *, char *, char *);

View File

@ -0,0 +1,78 @@
--- ../arpwatch.orig/util.c Fri Oct 13 18:49:03 2000
+++ ./util.c Wed Sep 10 13:03:27 2003
@@ -53,6 +53,7 @@
char *arpdir = ARPDIR;
char *arpfile = ARPFILE;
+char *etherfile = ETHERFILE;
char *ethercodes = ETHERCODES;
/* Broadcast ethernet addresses */
@@ -105,7 +106,7 @@
dump(void)
{
register int fd;
- char oldarpfile[256], newarpfile[256];
+ char oldarpfile[256], newarpfile[256], *oldetherfile, *newetherfile;
(void)sprintf(oldarpfile, "%s-", arpfile);
(void)sprintf(newarpfile, "%s.new", arpfile);
@@ -130,6 +131,32 @@
syslog(LOG_ERR, "rename %s -> %s: %m", newarpfile, arpfile);
return(0);
}
+
+ /* ether info */
+ (void)asprintf(&oldetherfile, "%s-", etherfile);
+ (void)asprintf(&newetherfile, "%s.new", etherfile);
+
+ if ((fd = creat(newetherfile, 0644)) < 0) {
+ syslog(LOG_ERR, "creat(%s): %m", newetherfile);
+ return(0);
+ }
+ if ((dumpf = fdopen(fd, "w")) == NULL) {
+ syslog(LOG_ERR, "fdopen(%s): %m", newetherfile);
+ return(0);
+ }
+
+ fwrite(einfo_table, sizeof(struct einfo), et_cnt, dumpf);
+
+ (void)fclose(dumpf);
+ if (rename(etherfile, oldetherfile) < 0) {
+ syslog(LOG_ERR, "rename %s -> %s: %m", etherfile, oldetherfile);
+ return(0);
+ }
+ if (rename(newetherfile, etherfile) < 0) {
+ syslog(LOG_ERR, "rename %s -> %s: %m", newetherfile, etherfile);
+ return(0);
+ }
+
return(1);
}
@@ -138,7 +165,9 @@
readdata(void)
{
register FILE *f;
+ char line[1024];
+ /* arp.dat */
if ((f = fopen(arpfile, "r")) == NULL) {
syslog(LOG_ERR, "fopen(%s): %m", arpfile);
return(0);
@@ -147,6 +176,15 @@
(void)fclose(f);
return(0);
}
+ (void)fclose(f);
+
+ /* ether.dat */
+ if ((f = fopen(etherfile, "r")) == NULL) {
+ syslog(LOG_ERR, "fopen(%s): %m", etherfile);
+ return(0);
+ }
+
+ et_cnt = fread(einfo_table, sizeof(struct einfo), HASHSIZE, f);
(void)fclose(f);
/* It's not fatal if we can't open the ethercodes file */

View File

@ -0,0 +1,12 @@
--- ../arpwatch.orig/util.h Sun Oct 6 06:22:14 1996
+++ ./util.h Wed Sep 10 13:03:27 2003
@@ -11,6 +11,9 @@
extern char *arpfile;
extern char *oldarpfile;
extern char *ethercodes;
+extern char *etherfile;
+extern struct einfo einfo_table[];
+extern int et_cnt;
extern u_char zero[6];
extern u_char allones[6];

View File

@ -1,21 +1,10 @@
ARPWATCH 2.0
Lawrence Berkeley National Laboratory
Network Research Group
arpwatch@ee.lbl.gov
ftp://ftp.ee.lbl.gov/arpwatch.tar.Z
This is a development fork of arpwatch. This has been threaded in
order to better deal with the requirements of multi-interface
routers. Information regarding MAC addresses and interfaces is
maintained by the program, and an alert is issued should a device
move between interfaces. In addition, event processing has been
refactored, and some bugs have been fixed.
This directory contains source code for arpwatch and arpsnmp, tools
that monitors ethernet activity and maintain a database of ethernet/ip
address pairings. It also reports certain changes via email.
see net/arpwatch/pkg-descr for more information about arpwatch 2.x
Arpsnmp has the same database features of arpwatch but relies on an
external agent to collect the arp data. This distribution contains a
script, arpfetch, that uses snmpwalk from the CMU SNMP package. This
package is available from:
ftp://ftp.net.cmu.edu/pub/snmp-dist/cmu-snmp*.tar.Z
It should be trivial to adaptive the output of any snmp query program
for use with arpsnmp.
Please send bugs and comments to arpwatch@ee.lbl.gov.
Matthew George <mdg@secureworks.net>

View File

@ -7,5 +7,7 @@ arpwatch/e.awk
arpwatch/p.awk
etc/rc.d/arpwatch.sh.sample
@unexec test -f %D/arpwatch/arp.dat && test -s %D/arpwatch/arp.dat || rm -f %D/arpwatch/arp.dat
@unexec test -f %D/arpwatch/ether.dat && test -s %D/arpwatch/ether.dat || rm -f %D/arpwatch/ether.dat
@exec test -f %D/arpwatch/arp.dat || touch %D/arpwatch/arp.dat
@exec test -f %D/arpwatch/ether.dat || touch %D/arpwatch/ether.dat
@dirrm arpwatch