--- arpwatch-2.1a15-dist/arpwatch.c 2012-07-23 09:55:35.832458313 +0200 +++ arpwatch-2.1a15-new/arpwatch.c 2012-07-24 11:36:59.013953071 +0200 @@ -161,15 +161,63 @@ void dropprivileges(const char* user) syslog(LOG_DEBUG, "Running as uid=%d gid=%d", getuid(), getgid()); } +char * +get_first_dev(pcap_t **pd, int *linktype, char *errbuf) +{ + static char interface[IF_NAMESIZE + 1]; + register int snaplen, timeout; + pcap_if_t *alldevs; + pcap_if_t *dev; + char *ret = NULL; + + snaplen = max(sizeof(struct ether_header), + sizeof(struct fddi_header)) + sizeof(struct ether_arp); + timeout = 1000; + + if (pcap_findalldevs(&alldevs, errbuf) == -1) { + (void)fprintf(stderr, "%s: lookup_device: %s\n", + prog, errbuf); + exit(1); + } + + for (dev = alldevs; dev; dev = dev->next) { + strncpy(interface, dev->name, strlen(dev->name)+1); + + *pd = pcap_open_live(interface, snaplen, 1, timeout, errbuf); + if (*pd == NULL) { + syslog(LOG_ERR, "pcap open %s: %s, trying next...", interface, errbuf); + continue; + /* exit(1); */ + } + + *linktype = pcap_datalink(*pd); + /* Must be ethernet or fddi */ + if (*linktype != DLT_EN10MB && *linktype != DLT_FDDI) { + syslog(LOG_ERR, "(%s) Link layer type %d not ethernet or fddi, trying next...", + interface, *linktype); + pcap_close(*pd); + } + else { + /* First match, use it */ + ret = interface; + break; + } + + } + pcap_freealldevs(alldevs); + return (ret); +} + int main(int argc, char **argv) { register char *cp; - register int op, pid, snaplen, timeout, linktype, status; + register int op, pid, status; + int linktype; #ifdef TIOCNOTTY register int fd; #endif - register pcap_t *pd; + pcap_t *pd; register char *interface, *rfilename; struct bpf_program code; char errbuf[PCAP_ERRBUF_SIZE]; @@ -189,6 +237,7 @@ main(int argc, char **argv) opterr = 0; interface = NULL; + linktype = -1; rfilename = NULL; pd = NULL; while ((op = getopt(argc, argv, "df:i:n:Nr:u:e:s:")) != EOF) @@ -264,11 +313,12 @@ main(int argc, char **argv) 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); + (interface = get_first_dev(&pd, &linktype, errbuf)) == NULL) { + (void)fprintf(stderr, "%s: lookup_device: no suitable interface found\n", + prog); exit(1); } @@ -317,10 +367,6 @@ main(int argc, char **argv) } swapped = pcap_is_swapped(pd); } else { - snaplen = max(sizeof(struct ether_header), - sizeof(struct fddi_header)) + sizeof(struct ether_arp); - timeout = 1000; - pd = pcap_open_live(interface, snaplen, 1, timeout, errbuf); if (pd == NULL) { syslog(LOG_ERR, "pcap open %s: %s", interface, errbuf); exit(1); @@ -340,14 +386,6 @@ main(int argc, char **argv) dropprivileges( serveruser ); } - /* Must be ethernet or fddi */ - linktype = pcap_datalink(pd); - if (linktype != DLT_EN10MB && linktype != DLT_FDDI) { - syslog(LOG_ERR, "Link layer type %d not ethernet or fddi", - linktype); - exit(1); - } - /* Compile and install filter */ if (pcap_compile(pd, &code, "arp or rarp", 1, netmask) < 0) { syslog(LOG_ERR, "pcap_compile: %s", pcap_geterr(pd));