diff -U 3 arpwatch-2.1a13/arpsnmp.c arpwatch-2.1a13-NEW/arpsnmp.c --- arpwatch-2.1a13/arpsnmp.c Thu Jan 22 17:25:17 2004 +++ arpwatch-2.1a13-NEW/arpsnmp.c Mon Jul 25 10:20:48 2005 @@ -154,7 +154,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, now, h)); } /* Process an snmp file */ @@ -188,3 +188,5 @@ "usage: %s [-d] [-f datafile] file [...]\n", prog); exit(1); } + +void set_can_checkpoint(int i) {} /* dummy */ diff -U 3 arpwatch-2.1a13/arpwatch.c arpwatch-2.1a13-NEW/arpwatch.c --- arpwatch-2.1a13/arpwatch.c Thu Jan 22 17:18:20 2004 +++ arpwatch-2.1a13-NEW/arpwatch.c Mon Jul 25 10:24:26 2005 @@ -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, t, NULL)) 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, t, NULL)) syslog(LOG_ERR, "ent_add(%s, %s, %ld) failed", intoa(sia), e2str(sea), t); can_checkpoint = 1; @@ -719,6 +719,11 @@ if ((sia & np->netmask) == np->net) return (0); return (1); +} + +void set_can_checkpoint(int can_do_it) +{ + can_checkpoint = can_do_it; } RETSIGTYPE diff -U 3 arpwatch-2.1a13/arpwatch.h arpwatch-2.1a13-NEW/arpwatch.h --- arpwatch-2.1a13/arpwatch.h Sat Sep 30 19:40:55 2000 +++ arpwatch-2.1a13-NEW/arpwatch.h Mon Jul 25 10:17:09 2005 @@ -3,6 +3,7 @@ #define ARPFILE "arp.dat" #define ETHERCODES "ethercodes.dat" #define CHECKPOINT (15*60) /* Checkpoint time in seconds */ +void set_can_checkpoint(int); #define MEMCMP(a, b, n) memcmp((char *)a, (char *)b, n) #define BCOPY(a, b, n) memmove((char *)b, (char *)a, n) diff -U 3 arpwatch-2.1a13/db.c arpwatch-2.1a13-NEW/db.c --- arpwatch-2.1a13/db.c Sat Sep 30 19:39:58 2000 +++ arpwatch-2.1a13-NEW/db.c Mon Jul 25 10:48:03 2005 @@ -54,7 +54,7 @@ #include "report.h" #include "util.h" -#define HASHSIZE (2 << 15) +#define HASHSIZE (2 << 11) /* dgajewsk perfect for our /21 network */ #define NEWACTIVITY_DELTA (6*30*24*60*60) /* 6 months in seconds */ #define FLIPFLIP_DELTA (24*60*60) /* 24 hours in seconds */ @@ -64,6 +64,7 @@ u_char e[6]; /* ether address */ char h[34]; /* simple hostname */ time_t t; /* timestamp */ + time_t tprev; /* timestamp */ }; /* Address info */ @@ -77,16 +78,19 @@ /* Address hash table */ static struct ainfo ainfo_table[HASHSIZE]; +static struct ainfo ainfo_special; +static struct einfo einfo_special; 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, time_t, char *); static struct ainfo *ainfo_find(u_int32_t); static void check_hname(struct ainfo *); 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, time_t tprev, +register char *h) { register struct ainfo *ap; register struct einfo *ep; @@ -94,6 +98,7 @@ register u_int len; u_char *e2; time_t t2; + static int do_once; /* Lookup ip address */ ap = ainfo_find(a); @@ -114,11 +119,12 @@ /* Check for a virgin ainfo record */ if (ap->ecount == 0) { ap->ecount = 1; - ap->elist[0] = elist_alloc(a, e, t, h); + ap->elist[0] = elist_alloc(a, e, t, tprev, h); report("new station", a, e, NULL, &t, NULL); return (1); } +#if 0 /* dgajewsk - Eng only wants updates on changes */ /* Check for a flip-flop */ if (ap->ecount > 1) { ep = ap->elist[1]; @@ -170,8 +176,37 @@ 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->elist[0] = elist_alloc(a, e, t, tprev, h); ++ap->ecount; +#endif + if( do_once == 0) { + ainfo_special.elist = + (struct einfo **)malloc(sizeof(ainfo_special.elist[0])); + if (ainfo_special.elist == NULL) { + syslog(LOG_ERR, "ainfo_special malloc: %m"); + exit(1); + } + ainfo_special.elist[0] = &einfo_special; + do_once = 1; + } + + /* log changes to IP->ethernet mappings, keep only most current */ + ainfo_special.a = ap->a; + ainfo_special.ecount = 1; + BCOPY(ap->elist[0], ainfo_special.elist[0], sizeof(struct einfo)); + + ep = ap->elist[0]; + BCOPY(e, ep->e, 6); + if (h == NULL && !initializing) + h = getsname(a); + if (h != NULL && !isdigit((int)*h)) + strcpy(ep->h, h); + ep->t = t; + ep->tprev = tprev; + + report("arp change for IP", a, e, NULL, &t, NULL); + dumpchange(); + return (1); } @@ -227,12 +262,24 @@ for (ap = &ainfo_table[i]; ap != NULL; ap = ap->next) for (j = 0; j < ap->ecount; ++j) { ep = ap->elist[j]; - (*fn)(ap->a, ep->e, ep->t, ep->h); + (*fn)(ap->a, ep->e, ep->t, ep->tprev, ep->h); ++n; } return (n); } +int +ent_getspecial(ent_process fn) +{ + register struct ainfo *ap; + register struct einfo *ep; + + ap = &ainfo_special; + ep = ap->elist[0]; + (*fn)(ap->a, ep->e, ep->t, ep->tprev, ep->h); + return (1); +} + /* Insure enough room for at least one more einfo pointer */ static void alist_alloc(register struct ainfo *ap) @@ -259,7 +306,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) + time_t tprev, register char *h) { register struct einfo *ep; register u_int size; @@ -286,6 +333,7 @@ if (h != NULL && !isdigit((int)*h)) strcpy(ep->h, h); ep->t = t; + ep->tprev = tprev; return (ep); } diff -U 3 arpwatch-2.1a13/db.h arpwatch-2.1a13-NEW/db.h --- arpwatch-2.1a13/db.h Wed Jun 5 01:39:30 1996 +++ arpwatch-2.1a13-NEW/db.h Fri Jul 22 11:13:20 2005 @@ -1,10 +1,11 @@ /* @(#) $Header: db.h,v 1.8 96/06/04 22:39:29 leres Exp $ (LBL) */ -typedef void (*ent_process)(u_int32_t, u_char *, time_t, char *); +typedef void (*ent_process)(u_int32_t, u_char *, time_t, 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, time_t, char *); int ent_loop(ent_process); +int ent_getspecial(ent_process); void sorteinfo(void); diff -U 3 arpwatch-2.1a13/ec.c arpwatch-2.1a13-NEW/ec.c --- arpwatch-2.1a13/ec.c Fri Oct 13 18:49:16 2000 +++ arpwatch-2.1a13-NEW/ec.c Wed Jul 20 16:06:55 2005 @@ -218,7 +218,8 @@ { static char str[32]; - (void)sprintf(str, "%x:%x:%x:%x:%x:%x", + /* (void)sprintf(str, "%x:%x:%x:%x:%x:%x", */ /* 2003/11/13 grg */ + (void)sprintf(str, "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x", /* 2003/11/13 grg */ e[0], e[1], e[2], e[3], e[4], e[5]); return (str); } diff -U 3 arpwatch-2.1a13/file.c arpwatch-2.1a13-NEW/file.c --- arpwatch-2.1a13/file.c Fri Oct 13 18:29:43 2000 +++ arpwatch-2.1a13-NEW/file.c Thu Jul 21 16:00:02 2005 @@ -67,7 +67,7 @@ register int n; register char *cp, *cp2, *h; u_int32_t a; - register time_t t; + time_t t, tprev; register struct hostent *hp; char line[1024]; u_char e[6]; @@ -116,9 +116,29 @@ /* timestamp and hostname are optional */ if (cp2 == NULL) { t = 0; + tprev = 0; h = NULL; } else { - t = atoi(cp2); + /*code to convert the time string to epoch seconds + the time string is of format %Y/%m/%d-%T*/ + struct tm time_struct, *temp_struct; + + t = time(NULL); + temp_struct = localtime(&t); + + strptime(cp2,"%Y/%m/%d-%T",&time_struct); + time_struct.tm_isdst = temp_struct->tm_isdst; + tprev = mktime(&time_struct); + + cp2 = strchr(cp2, '\t'); + *cp2++; + + strptime(cp2,"%Y/%m/%d-%T",&time_struct); + /* dgajewsk get DST info */ + time_struct.tm_isdst = temp_struct->tm_isdst; + t = mktime(&time_struct); + + /* t = atoi(cp2); 2003/11/13 grg */ h = strchr(cp2, '\t'); if (h != NULL) { ++h; @@ -130,7 +150,7 @@ } } - if (!(*fn)(a, e, t, h)) + if (!(*fn)(a, e, t, tprev, h)) return(0); } diff -U 3 arpwatch-2.1a13/file.h arpwatch-2.1a13-NEW/file.h --- arpwatch-2.1a13/file.h Sun Jan 17 20:46:04 1999 +++ arpwatch-2.1a13-NEW/file.h Thu Jul 21 15:34:10 2005 @@ -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, time_t, char *); int file_loop(FILE *, file_process, const char *); Common subdirectories: arpwatch-2.1a13/lbl and arpwatch-2.1a13-NEW/lbl Common subdirectories: arpwatch-2.1a13/linux-include and arpwatch-2.1a13-NEW/linux-include diff -U 3 arpwatch-2.1a13/report.c arpwatch-2.1a13-NEW/report.c --- arpwatch-2.1a13/report.c Sat Sep 30 19:41:10 2000 +++ arpwatch-2.1a13-NEW/report.c Mon Jul 25 10:43:20 2005 @@ -257,7 +257,7 @@ return; } f = stdout; - (void)putc('\n', f); + /* (void)putc('\n', f); */ /* 2003/10/30 grg */ } else { /* Setup child reaper if we haven't already */ if (!init) { @@ -300,6 +300,8 @@ syslog(LOG_ERR, "unlink(%s): %m", tempfile); } + /* 2003/10/30 grg no email, simply formatted messages */ +#if 0 (void)fprintf(f, "From: %s\n", watchee); (void)fprintf(f, "To: %s\n", watcher); hn = gethname(a); @@ -348,4 +350,6 @@ execl(sendmail, "sendmail", "-odi", watcher, NULL); syslog(LOG_ERR, "execl: %s: %m", sendmail); exit(1); +#endif + /* grg */ } diff -U 3 arpwatch-2.1a13/util.c arpwatch-2.1a13-NEW/util.c --- arpwatch-2.1a13/util.c Thu Jan 22 17:25:39 2004 +++ arpwatch-2.1a13-NEW/util.c Mon Jul 25 10:53:02 2005 @@ -90,12 +90,18 @@ static FILE *dumpf; void -dumpone(register u_int32_t a, register u_char *e, register time_t t, +dumpone(register u_int32_t a, register u_char *e, time_t t, time_t tprev, register char *h) { (void)fprintf(dumpf, "%s\t%s", e2str(e), intoa(a)); if (t != 0 || h != NULL) - (void)fprintf(dumpf, "\t%u", (u_int32_t)t); + /* (void)fprintf(dumpf, "\t%u", (u_int32_t)t); 20031111 grg*/ + { char s[256] ; + strftime(s,256,"%Y/%m/%d-%T",localtime(&tprev)) ; + (void)fprintf(dumpf, "\t%s", s) ; + strftime(s,256,"%Y/%m/%d-%T",localtime(&t)) ; /* 20031111 grg*/ + (void)fprintf(dumpf, "\t%s", s) ; + } if (h != NULL && *h != '\0') (void)fprintf(dumpf, "\t%s", h); (void)putc('\n', dumpf); @@ -134,6 +140,39 @@ syslog(LOG_ERR, "rename %s -> %s: %m", newarpfile, arpfile); return(0); } + return(1); +} + +int +dumpchange(void) +{ + register int fd; + char arpfilechange[256]; + + set_can_checkpoint(0); /* dumpf would get overwritten */ + (void)sprintf(arpfilechange, "%s.changes", arpfile); + + if ((fd = open(arpfilechange, O_WRONLY | O_CREAT, 0644)) < 0) { + syslog(LOG_ERR, "open(%s): %m", arpfilechange); + set_can_checkpoint(1); + return(0); + } + if ((dumpf = fdopen(fd, "a")) == NULL) { + syslog(LOG_ERR, "fdopen(%s): %m", arpfilechange); + set_can_checkpoint(1); + return(0); + } + + (void)ent_getspecial(dumpone); + if (ferror(dumpf)) { + syslog(LOG_ERR, "ferror %s: %m", arpfilechange); + set_can_checkpoint(1); + return(0); + } + + (void)fclose(dumpf); + set_can_checkpoint(1); + return(1); } diff -U 3 arpwatch-2.1a13/util.h arpwatch-2.1a13-NEW/util.h --- arpwatch-2.1a13/util.h Sun Oct 6 06:22:14 1996 +++ arpwatch-2.1a13-NEW/util.h Fri Jul 22 11:13:34 2005 @@ -2,7 +2,8 @@ void dosyslog(int, char *, u_int32_t, u_char *, u_char *); int dump(void); -void dumpone(u_int32_t, u_char *, time_t, char *); +int dumpchange(void); +void dumpone(u_int32_t, u_char *, time_t, time_t, char *); int readdata(void); char *savestr(const char *);