When activating a device, return PCAP_ERROR_IFACE_NOT_UP if the device
isn't up, so applications can report that differently from a generic error (the latter could mean there's a bug somewhere in libpcap). When capturing on a device without mmap on Linux, 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.
This commit is contained in:
parent
a8e63c60ed
commit
34624f128f
33
pcap-bpf.c
33
pcap-bpf.c
|
@ -20,7 +20,7 @@
|
|||
*/
|
||||
#ifndef lint
|
||||
static const char rcsid[] _U_ =
|
||||
"@(#) $Header: /tcpdump/master/libpcap/pcap-bpf.c,v 1.110 2008-04-14 20:40:58 guy Exp $ (LBL)";
|
||||
"@(#) $Header: /tcpdump/master/libpcap/pcap-bpf.c,v 1.111 2008-07-01 08:02:33 guy Exp $ (LBL)";
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
|
@ -413,11 +413,23 @@ pcap_can_set_rfmon_bpf(pcap_t *p)
|
|||
*/
|
||||
(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);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1016,6 +1028,15 @@ check_setif_failure(pcap_t *p, int 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
|
||||
|
|
63
pcap-linux.c
63
pcap-linux.c
|
@ -34,7 +34,7 @@
|
|||
|
||||
#ifndef lint
|
||||
static const char rcsid[] _U_ =
|
||||
"@(#) $Header: /tcpdump/master/libpcap/pcap-linux.c,v 1.149 2008-06-24 06:44:32 guy Exp $ (LBL)";
|
||||
"@(#) $Header: /tcpdump/master/libpcap/pcap-linux.c,v 1.150 2008-07-01 08:02:33 guy Exp $ (LBL)";
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
@ -646,8 +646,21 @@ pcap_read_packet(pcap_t *handle, pcap_handler callback, u_char *userdata)
|
|||
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 {
|
||||
/*
|
||||
|
@ -667,7 +680,7 @@ pcap_read_packet(pcap_t *handle, pcap_handler callback, u_char *userdata)
|
|||
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 */
|
||||
|
||||
|
@ -1722,10 +1735,10 @@ activate_new(pcap_t *handle)
|
|||
}
|
||||
|
||||
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 */
|
||||
}
|
||||
|
@ -2183,6 +2196,8 @@ iface_get_id(int fd, const char *device, char *ebuf)
|
|||
|
||||
/*
|
||||
* 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)
|
||||
|
@ -2197,9 +2212,20 @@ 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? */
|
||||
|
@ -2207,16 +2233,25 @@ iface_bind(int fd, int ifindex, char *ebuf)
|
|||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
5
pcap.c
5
pcap.c
|
@ -33,7 +33,7 @@
|
|||
|
||||
#ifndef lint
|
||||
static const char rcsid[] _U_ =
|
||||
"@(#) $Header: /tcpdump/master/libpcap/pcap.c,v 1.122 2008-05-26 19:58:06 guy Exp $ (LBL)";
|
||||
"@(#) $Header: /tcpdump/master/libpcap/pcap.c,v 1.123 2008-07-01 08:02:33 guy Exp $ (LBL)";
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
|
@ -951,6 +951,9 @@ pcap_statustostr(int errnum)
|
|||
|
||||
case PCAP_ERROR_PERM_DENIED:
|
||||
return ("You don't have permission to capture on that device");
|
||||
|
||||
case PCAP_ERROR_IFACE_NOT_UP:
|
||||
return ("That device is not up");
|
||||
}
|
||||
(void)snprintf(ebuf, sizeof ebuf, "Unknown error: %d", errnum);
|
||||
return(ebuf);
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#) $Header: /tcpdump/master/libpcap/pcap/pcap.h,v 1.13 2008-05-30 01:35:33 guy Exp $ (LBL)
|
||||
* @(#) $Header: /tcpdump/master/libpcap/pcap/pcap.h,v 1.14 2008-07-01 08:02:33 guy Exp $ (LBL)
|
||||
*/
|
||||
|
||||
#ifndef lib_pcap_pcap_h
|
||||
|
@ -243,6 +243,7 @@ typedef void (*pcap_handler)(u_char *, const struct pcap_pkthdr *,
|
|||
#define PCAP_ERROR_RFMON_NOTSUP -6 /* this device doesn't support rfmon (monitor) mode */
|
||||
#define PCAP_ERROR_NOT_RFMON -7 /* operation supported only in monitor mode */
|
||||
#define PCAP_ERROR_PERM_DENIED -8 /* no permission to open the device */
|
||||
#define PCAP_ERROR_IFACE_NOT_UP -9 /* interface isn't up */
|
||||
|
||||
/*
|
||||
* Warning codes for the pcap API.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
.\" @(#) $Header: /tcpdump/master/libpcap/pcap_activate.3pcap,v 1.4 2008-04-09 21:26:12 guy Exp $
|
||||
.\" @(#) $Header: /tcpdump/master/libpcap/pcap_activate.3pcap,v 1.5 2008-07-01 08:02:33 guy Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 1994, 1996, 1997
|
||||
.\" The Regents of the University of California. All rights reserved.
|
||||
|
@ -54,9 +54,11 @@ exist,
|
|||
if the process doesn't have permission to open the capture source,
|
||||
.B PCAP_ERROR_RFMON_NOTSUP
|
||||
if monitor mode was specified but the capture source doesn't support
|
||||
monitor mode, and
|
||||
monitor mode,
|
||||
.B PCAP_ERROR_IFACE_NOT_UP
|
||||
if the capture source is not up, and
|
||||
.B PCAP_ERROR
|
||||
if an error occurred.
|
||||
if another error occurred.
|
||||
If
|
||||
.B PCAP_WARNING
|
||||
or
|
||||
|
|
Reference in New Issue