diff -rNu arpwatch-2.1a11_orig/Makefile.in arpwatch-2.1a11/Makefile.in --- arpwatch-2.1a11_orig/Makefile.in 2000-06-15 02:39:55.000000000 +0200 +++ arpwatch-2.1a11/Makefile.in 2003-11-01 13:01:15.000000000 +0100 @@ -32,6 +32,8 @@ MANDEST = @mandir@ # Pathname of directory to install database file ARPDIR = $(prefix)/arpwatch +# Pathname of report script +REPORT_SCRIPT = $(ARPDIR)/arpwatch_report # VPATH srcdir = @srcdir@ @@ -45,7 +47,7 @@ PROG = arpwatch CCOPT = @V_CCOPT@ INCLS = -I. @V_INCLS@ -DEFS = -DDEBUG @DEFS@ -DARPDIR=\"$(ARPDIR)\" -DPATH_SENDMAIL=\"$(SENDMAIL)\" +DEFS = -DDEBUG @DEFS@ -DARPDIR=\"$(ARPDIR)\" -DPATH_SENDMAIL=\"$(SENDMAIL)\" -DPATH_REPORT_SCRIPT=\"$(REPORT_SCRIPT)\" # Standard CFLAGS CFLAGS = $(CCOPT) $(DEFS) $(INCLS) diff -rNu arpwatch-2.1a11_orig/README-arpwatch_report arpwatch-2.1a11/README-arpwatch_report --- arpwatch-2.1a11_orig/README-arpwatch_report 1970-01-01 01:00:00.000000000 +0100 +++ arpwatch-2.1a11/README-arpwatch_report 2003-11-05 11:12:16.000000000 +0100 @@ -0,0 +1,18 @@ +arpwatch_report - allows scripting for aprwatch +(c) Collin R. Mulliner + +arpwatch normally notifys root via email of any changes via sendmail. + +with arpwatch_report this has changed a little: arpwatch first trys to +run the arpwatch_report program (which is any type of executable) located in +the arpwatch directory (see arpwatch.8). arpwatch passes several parameters +to aprwatch_report and dumps the content of the email, that should be mailed +to root, to stdin of arpwatch_report (see sample arpwatch_report script). +If arpwatch_report can't run arpwatch falls back to sendmail. + +arpwatch_report (see sample script!) takes the following parameters: + +[interface] [ip] [new mac] [old mac] [old time] [new time] [arpwatch tag] + +example: +de0 10.0.1.1 00:00:00:00:00:00 00:11:22:33:44:55 0 1432432 "new station" diff -rNu arpwatch-2.1a11_orig/arpsnmp.c arpwatch-2.1a11/arpsnmp.c --- arpwatch-2.1a11_orig/arpsnmp.c 1999-01-18 02:47:40.000000000 +0100 +++ arpwatch-2.1a11/arpsnmp.c 2003-11-01 13:01:15.000000000 +0100 @@ -63,7 +63,7 @@ /* 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 *, u_char*); __dead void usage(void) __attribute__((volatile)); char *prog; @@ -138,7 +138,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 u_char *u) { /* Watch for ethernet broadcast */ if (MEMCMP(e, zero, 6) == 0 || MEMCMP(e, allones, 6) == 0) { @@ -153,7 +153,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, u)); } /* Process an snmp file */ diff -rNu arpwatch-2.1a11_orig/arpwatch.8 arpwatch-2.1a11/arpwatch.8 --- arpwatch-2.1a11_orig/arpwatch.8 2000-10-08 22:31:28.000000000 +0200 +++ arpwatch-2.1a11/arpwatch.8 2003-11-05 10:45:17.000000000 +0100 @@ -153,6 +153,7 @@ .nh .nf /usr/operator/arpwatch - default directory +arpwatch_report - report script arp.dat - ethernet/ip address database ethercodes.dat - vendor ethernet block list .ad diff -rNu arpwatch-2.1a11_orig/arpwatch.c arpwatch-2.1a11/arpwatch.c --- arpwatch-2.1a11_orig/arpwatch.c 2000-10-14 04:07:35.000000000 +0200 +++ arpwatch-2.1a11/arpwatch.c 2003-11-01 13:01:15.000000000 +0100 @@ -331,7 +331,7 @@ switch (linktype) { case DLT_EN10MB: - status = pcap_loop(pd, 0, process_ether, NULL); + status = pcap_loop(pd, 0, process_ether, interface); break; case DLT_FDDI: @@ -400,7 +400,7 @@ /* Got a live one */ t = h->ts.tv_sec; can_checkpoint = 0; - if (!ent_add(sia, sea, t, NULL)) + if (!ent_add(sia, sea, t, NULL, u)) syslog(LOG_ERR, "ent_add(%s, %s, %ld) failed", intoa(sia), e2str(sea), t); can_checkpoint = 1; @@ -549,7 +549,7 @@ /* Got a live one */ t = h->ts.tv_sec; can_checkpoint = 0; - if (!ent_add(sia, sea, t, NULL)) + if (!ent_add(sia, sea, t, NULL, u)) syslog(LOG_ERR, "ent_add(%s, %s, %ld) failed", intoa(sia), e2str(sea), t); can_checkpoint = 1; diff -rNu arpwatch-2.1a11_orig/arpwatch_report arpwatch-2.1a11/arpwatch_report --- arpwatch-2.1a11_orig/arpwatch_report 1970-01-01 01:00:00.000000000 +0100 +++ arpwatch-2.1a11/arpwatch_report 2003-11-01 13:08:56.000000000 +0100 @@ -0,0 +1,43 @@ +#!/usr/bin/perl + +# send reports to +$watcher = "root"; + +# DEBUG +#open FILE, ">> /var/log/arpwatch"; + +# read arpwatch 'mail' output +@arpwatch_mail = ; + +# read parameters + # interface + $if = $ARGV[0]; + # ip address + $ip = $ARGV[1]; + # new mac address + $mac_new = $ARGV[2]; + # old mac address + $mac_old = $ARGV[3]; + # new time stamp + $ts_new = $ARGV[4]; + # old time stamp + $ts_old = $ARGV[5]; + # arpwatch event title + $title = $ARGV[6]; + +# DEBUG +#print FILE "DEBUG [$if] title: $title ip: $ip MAC(old: $mac_old new: $mac_new) TIME(old: $ts_old new: $ts_new)\n"; + +# handle interfaces +if ($if eq "de0") { + open MAIL, "|/usr/sbin/sendmail -odi $watcher"; + print MAIL @arpwatch_mail; + close MAIL; +} +else { + open MAIL, "|/usr/sbin/sendmail -odi $watcher"; + print MAIL @arpwatch_mail; + close MAIL; +} +# DEBUG +#close FILE; diff -rNu arpwatch-2.1a11_orig/db.c arpwatch-2.1a11/db.c --- arpwatch-2.1a11_orig/db.c 2000-10-01 01:39:58.000000000 +0200 +++ arpwatch-2.1a11/db.c 2003-11-01 13:01:15.000000000 +0100 @@ -86,7 +86,7 @@ struct ainfo *newainfo(void); 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 u_char *u) { register struct ainfo *ap; register struct einfo *ep; @@ -103,7 +103,7 @@ ep = ap->elist[0]; if (MEMCMP(e, ep->e, 6) == 0) { if (t - ep->t > NEWACTIVITY_DELTA) { - report("new activity", a, e, NULL, &t, &ep->t); + report("new activity", a, e, NULL, &t, &ep->t, u); check_hname(ap); } ep->t = t; @@ -115,7 +115,7 @@ if (ap->ecount == 0) { ap->ecount = 1; ap->elist[0] = elist_alloc(a, e, t, h); - report("new station", a, e, NULL, &t, NULL); + report("new station", a, e, NULL, &t, NULL, u); return (1); } @@ -135,7 +135,7 @@ dosyslog(LOG_INFO, "suppressed DECnet flip flop", a, e, e2); else - report("flip flop", a, e, e2, &t, &t2); + report("flip flop", a, e, e2, &t, &t2, u); ap->elist[1] = ap->elist[0]; ap->elist[0] = ep; ep->t = t; @@ -165,7 +165,7 @@ /* New ether address */ e2 = ap->elist[0]->e; t2 = ap->elist[0]->t; - report("changed ethernet address", a, e, e2, &t, &t2); + report("changed ethernet address", a, e, e2, &t, &t2, u); /* Make room at head of list */ alist_alloc(ap); len = ap->ecount * sizeof(ap->elist[0]); diff -rNu arpwatch-2.1a11_orig/db.h arpwatch-2.1a11/db.h --- arpwatch-2.1a11_orig/db.h 1996-06-05 07:39:30.000000000 +0200 +++ arpwatch-2.1a11/db.h 2003-11-01 13:01:15.000000000 +0100 @@ -5,6 +5,6 @@ #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 *, u_char *); int ent_loop(ent_process); void sorteinfo(void); diff -rNu arpwatch-2.1a11_orig/ec.c arpwatch-2.1a11/ec.c --- arpwatch-2.1a11_orig/ec.c 2000-10-14 00:49:16.000000000 +0200 +++ arpwatch-2.1a11/ec.c 2003-11-01 13:01:15.000000000 +0100 @@ -218,7 +218,7 @@ { static char str[32]; - (void)sprintf(str, "%x:%x:%x:%x:%x:%x", + (void)sprintf(str, "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x", e[0], e[1], e[2], e[3], e[4], e[5]); return (str); } diff -rNu arpwatch-2.1a11_orig/file.c arpwatch-2.1a11/file.c --- arpwatch-2.1a11_orig/file.c 2000-10-14 00:29:43.000000000 +0200 +++ arpwatch-2.1a11/file.c 2003-11-01 13:01:15.000000000 +0100 @@ -130,7 +130,7 @@ } } - if (!(*fn)(a, e, t, h)) + if (!(*fn)(a, e, t, h, "")) return(0); } diff -rNu arpwatch-2.1a11_orig/file.h arpwatch-2.1a11/file.h --- arpwatch-2.1a11_orig/file.h 1999-01-18 02:46:04.000000000 +0100 +++ arpwatch-2.1a11/file.h 2003-11-01 13:01:15.000000000 +0100 @@ -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 *, u_char *); int file_loop(FILE *, file_process, const char *); diff -rNu arpwatch-2.1a11_orig/report.c arpwatch-2.1a11/report.c --- arpwatch-2.1a11_orig/report.c 2000-10-01 01:41:10.000000000 +0200 +++ arpwatch-2.1a11/report.c 2003-11-01 13:01:15.000000000 +0100 @@ -233,7 +233,7 @@ 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) + register u_char *e2, register time_t *t1p, register time_t *t2p, register u_char* u) { register char *cp, *hn; register int fd, pid; @@ -243,9 +243,15 @@ char *watcher = WATCHER; char *watchee = WATCHEE; char *sendmail = PATH_SENDMAIL; + char *script = PATH_REPORT_SCRIPT; char *unknown = ""; char buf[132]; static int init = 0; + char t1p_s[50]; + char t2p_s[50]; + char mac_old[30]; + char mac_new[30]; + /* No report until we're initialized */ if (initializing) @@ -313,6 +319,7 @@ (void)fprintf(f, fmt, "hostname", hn); (void)fprintf(f, fmt, "ip address", intoa(a)); (void)fprintf(f, fmt, "ethernet address", e2str(e1)); + sprintf(mac_new, e2str(e1)); if ((cp = ec_find(e1)) == NULL) cp = unknown; (void)fprintf(f, fmt, "ethernet vendor", cp); @@ -321,15 +328,23 @@ (void)fprintf(f, fmt, "dns cpu & os", buf); } if (e2) { + sprintf(mac_old, e2str(e2)); (void)fprintf(f, fmt, "old ethernet address", e2str(e2)); if ((cp = ec_find(e2)) == NULL) cp = unknown; (void)fprintf(f, fmt, "old ethernet vendor", cp); } - if (t1p) + else sprintf(mac_old, "00:00:00:00:00:00"); + if (t1p) { + sprintf(t1p_s, "%d", *t1p); (void)fprintf(f, fmt, "timestamp", fmtdate(*t1p)); - if (t2p) + } + else sprintf(t1p_s, "0"); + if (t2p) { + sprintf(t2p_s, "%d", *t2p); (void)fprintf(f, fmt, "previous timestamp", fmtdate(*t2p)); + } + else sprintf(t2p_s, "0"); if (t1p && t2p && *t1p && *t2p) (void)fprintf(f, fmt, "delta", fmtdelta(*t1p - *t2p)); @@ -345,6 +360,11 @@ } /* XXX Need to freopen()? */ /* Always Deliver interactively (pause when child depth gets large) */ + + /* first try to run the script */ + execl(script, script, u, intoa(a), mac_new, mac_old, t1p_s, t2p_s, title, NULL); + syslog(LOG_ERR, "execl: %s: %m, falling back to sendmail", script); + /* run sendmail if script can't execute */ execl(sendmail, "sendmail", "-odi", watcher, NULL); syslog(LOG_ERR, "execl: %s: %m", sendmail); exit(1); diff -rNu arpwatch-2.1a11_orig/report.h arpwatch-2.1a11/report.h --- arpwatch-2.1a11_orig/report.h 1996-06-05 07:40:54.000000000 +0200 +++ arpwatch-2.1a11/report.h 2003-11-01 13:01:15.000000000 +0100 @@ -1,3 +1,3 @@ /* @(#) $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 *); +void report(char *, u_int32_t, u_char *, u_char *, time_t *, time_t *i, u_char *u);