arpwatch/SOURCES/arpwatch-2.1a15-devlookup.p...

119 lines
3.3 KiB
Diff

--- 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));