--- arpwatch.c.orig Fri Oct 13 22:07:35 2000 +++ arpwatch.c Wed Jul 7 17:08:21 2004 @@ -36,6 +36,7 @@ #include #include #include +#include #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,50 +230,107 @@ 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 */ if (!debug) { - pid = fork(); - if (pid < 0) { - syslog(LOG_ERR, "main fork(): %m"); - exit(1); - } else if (pid != 0) - 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) { - (void)ioctl(fd, TIOCNOTTY, 0); - (void)close(fd); - } -#else - (void) setsid(); -#endif + daemon(1, 0); } } - 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 +380,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 +401,7 @@ exit(1); } pcap_close(pd); - if (!dump()) - exit(1); - exit(0); + return(0); } /* Process an ethernet arp/rarp packet */ @@ -362,6 +414,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 +454,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 +568,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 +612,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 +819,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); }