*/
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/libpcap/pcap-bpf.c,v 1.99.2.11 2008-04-14 20:41:51 guy Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/libpcap/pcap-bpf.c,v 1.99.2.12 2008-07-01 08:04:02 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
*/
(void)strncpy(ifr.ifr_name, p->opt.source, sizeof(ifr.ifr_name));
if (ioctl(fd, BIOCSETIF, (caddr_t)&ifr) < 0) {
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
- "BIOCSETIF: %s: %s",
- p->opt.source, pcap_strerror(errno));
- close(fd);
- return (PCAP_ERROR);
+ if (errno == ENETDOWN) {
+ /*
+ * Return a "network down" indication, so that
+ * the application can report that rather than
+ * saying we had a mysterious failure and
+ * suggest that they report a problem to the
+ * libpcap developers.
+ */
+ close(fd);
+ return (PCAP_ERROR_IFACE_NOT_UP);
+ } else {
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "BIOCSETIF: %s: %s",
+ p->opt.source, pcap_strerror(errno));
+ close(fd);
+ return (PCAP_ERROR);
+ }
}
/*
*/
strcpy(p->errbuf, "");
return (PCAP_ERROR_NO_SUCH_DEVICE);
+ } else if (errno == ENETDOWN) {
+ /*
+ * Return a "network down" indication, so that
+ * the application can report that rather than
+ * saying we had a mysterious failure and
+ * suggest that they report a problem to the
+ * libpcap developers.
+ */
+ return (PCAP_ERROR_IFACE_NOT_UP);
} else {
/*
* Some other error; fill in the error string, and
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/libpcap/pcap-linux.c,v 1.129.2.20 2008-06-24 06:45:04 guy Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/libpcap/pcap-linux.c,v 1.129.2.21 2008-07-01 08:04:03 guy Exp $ (LBL)";
#endif
/*
offset = 0;
#endif
- /* Receive a single packet from the kernel */
-
+ /*
+ * Receive a single packet from the kernel.
+ * We ignore EINTR, as that might just be due to a signal
+ * being delivered - if the signal should interrupt the
+ * loop, the signal handler should call pcap_breakloop()
+ * to set handle->break_loop (we ignore it on other
+ * platforms as well).
+ * We also ignore ENETDOWN, so that we can continue to
+ * capture traffic if the interface goes down and comes
+ * back up again; comments in the kernel indicate that
+ * we'll just block waiting for packets if we try to
+ * receive from a socket that delivered ENETDOWN, and,
+ * if we're using a memory-mapped buffer, we won't even
+ * get notified of "network down" events.
+ */
bp = handle->buffer + handle->offset;
do {
/*
handle->fd, bp + offset,
handle->bufsize - offset, MSG_TRUNC,
(struct sockaddr *) &from, &fromlen);
- } while (packet_len == -1 && errno == EINTR);
+ } while (packet_len == -1 && (errno == EINTR || errno == ENETDOWN));
/* Check if an error occured */
}
if ((err = iface_bind(sock_fd, handle->md.ifindex,
- handle->errbuf)) < 0) {
+ handle->errbuf)) != 1) {
close(sock_fd);
- if (err == -2)
- return PCAP_ERROR;
+ if (err < 0)
+ return err;
else
return 0; /* try old mechanism */
}
/*
* Bind the socket associated with FD to the given device.
+ * Return 1 on success, 0 if we should try a SOCK_PACKET socket,
+ * or a PCAP_ERROR_ value on a hard error.
*/
static int
iface_bind(int fd, int ifindex, char *ebuf)
sll.sll_protocol = htons(ETH_P_ALL);
if (bind(fd, (struct sockaddr *) &sll, sizeof(sll)) == -1) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE,
- "bind: %s", pcap_strerror(errno));
- return -1;
+ if (errno == ENETDOWN) {
+ /*
+ * Return a "network down" indication, so that
+ * the application can report that rather than
+ * saying we had a mysterious failure and
+ * suggest that they report a problem to the
+ * libpcap developers.
+ */
+ return PCAP_ERROR_IFACE_NOT_UP;
+ } else {
+ snprintf(ebuf, PCAP_ERRBUF_SIZE,
+ "bind: %s", pcap_strerror(errno));
+ return PCAP_ERROR;
+ }
}
/* Any pending errors, e.g., network is down? */
if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, &errlen) == -1) {
snprintf(ebuf, PCAP_ERRBUF_SIZE,
"getsockopt: %s", pcap_strerror(errno));
- return -2;
+ return 0;
}
- if (err > 0) {
+ if (err == ENETDOWN) {
+ /*
+ * Return a "network down" indication, so that
+ * the application can report that rather than
+ * saying we had a mysterious failure and
+ * suggest that they report a problem to the
+ * libpcap developers.
+ */
+ return PCAP_ERROR_IFACE_NOT_UP;
+ } else if (err > 0) {
snprintf(ebuf, PCAP_ERRBUF_SIZE,
"bind: %s", pcap_strerror(err));
- return -2;
+ return 0;
}
- return 0;
+ return 1;
}
/*