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