If attempting to turn memory-mapped access on fails for any reason other
than "the kernel doesn't support memory-mapped access to PF_PACKET sockets", treat that as an error. If it fails for that reason, don't leave gunk behind in the pcap_t's error buffer. Clean up the error messages a bit (the result of strerror() suffices; we don't need the numeric value of errno, nor do we need the file descriptor number of the socket on which we're working).
This commit is contained in:
parent
8fa17a5a55
commit
5cf5f7c1c8
90
pcap-linux.c
90
pcap-linux.c
|
@ -34,7 +34,7 @@
|
|||
|
||||
#ifndef lint
|
||||
static const char rcsid[] _U_ =
|
||||
"@(#) $Header: /tcpdump/master/libpcap/pcap-linux.c,v 1.159 2008-11-19 08:20:39 guy Exp $ (LBL)";
|
||||
"@(#) $Header: /tcpdump/master/libpcap/pcap-linux.c,v 1.160 2008-11-19 10:01:30 guy Exp $ (LBL)";
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
@ -508,7 +508,6 @@ pcap_activate_linux(pcap_t *handle)
|
|||
{
|
||||
const char *device;
|
||||
int status = 0;
|
||||
int activate_ok = 0;
|
||||
|
||||
device = handle->opt.source;
|
||||
|
||||
|
@ -555,27 +554,56 @@ pcap_activate_linux(pcap_t *handle)
|
|||
*/
|
||||
|
||||
if ((status = activate_new(handle)) == 1) {
|
||||
activate_ok = 1;
|
||||
/*
|
||||
* Success.
|
||||
* Try to use memory-mapped access.
|
||||
*/
|
||||
if (activate_mmap(handle) == 1)
|
||||
return 0; /* we succeeded; nothing more to do */
|
||||
switch (activate_mmap(handle)) {
|
||||
|
||||
case 1:
|
||||
/* we succeeded; nothing more to do */
|
||||
return 0;
|
||||
|
||||
case 0:
|
||||
/*
|
||||
* Kernel doesn't support it - just continue
|
||||
* with non-memory-mapped access.
|
||||
*/
|
||||
break;
|
||||
|
||||
case -1:
|
||||
/*
|
||||
* We failed to set up to use it, or kernel
|
||||
* supports it, but we failed to enable it;
|
||||
* return an error. handle->errbuf contains
|
||||
* an error message.
|
||||
*/
|
||||
status = PCAP_ERROR;
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
else if (status == 0) {
|
||||
/* Non-fatal error; try old way */
|
||||
if ((status = activate_old(handle)) == 1)
|
||||
activate_ok = 1;
|
||||
}
|
||||
if (!activate_ok) {
|
||||
if ((status = activate_old(handle)) != 1) {
|
||||
/*
|
||||
* Both methods to open the packet socket failed.
|
||||
* Tidy up and report our failure (handle->errbuf
|
||||
* is expected to be set by the functions above).
|
||||
*/
|
||||
goto fail;
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* Both methods to open the packet socket failed. Tidy
|
||||
* up and report our failure (ebuf is expected to be
|
||||
* set by the functions above).
|
||||
* Fatal error with the new way; just fail.
|
||||
* status has the error return; if it's PCAP_ERROR,
|
||||
* handle->errbuf has been set appropriately.
|
||||
*/
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/*
|
||||
* We set up the socket, but not with memory-mapped access.
|
||||
*/
|
||||
if (handle->opt.buffer_size != 0) {
|
||||
/*
|
||||
* Set the socket buffer size to the specified value.
|
||||
|
@ -1941,10 +1969,10 @@ activate_mmap(pcap_t *handle)
|
|||
handle->opt.buffer_size = 2*1024*1024;
|
||||
}
|
||||
ret = prepare_tpacket_socket(handle);
|
||||
if (ret == 0)
|
||||
if (ret != 1)
|
||||
return ret;
|
||||
ret = create_ring(handle);
|
||||
if (ret == 0)
|
||||
if (ret != 1)
|
||||
return ret;
|
||||
|
||||
/* override some defaults and inherit the other fields from
|
||||
|
@ -1981,11 +2009,13 @@ prepare_tpacket_socket(pcap_t *handle)
|
|||
len = sizeof(val);
|
||||
if (getsockopt(handle->fd, SOL_PACKET, PACKET_HDRLEN, &val, &len) < 0) {
|
||||
if (errno == ENOPROTOOPT)
|
||||
return 1;
|
||||
return 1; /* no - just drive on */
|
||||
|
||||
/* Yes - treat as a failure. */
|
||||
snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
|
||||
"can't get TPACKET_V2 header len on socket %d: %d-%s",
|
||||
handle->fd, errno, pcap_strerror(errno));
|
||||
return 0;
|
||||
"can't get TPACKET_V2 header len on packet socket: %s",
|
||||
pcap_strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
handle->md.tp_hdrlen = val;
|
||||
|
||||
|
@ -1993,9 +2023,9 @@ prepare_tpacket_socket(pcap_t *handle)
|
|||
if (setsockopt(handle->fd, SOL_PACKET, PACKET_VERSION, &val,
|
||||
sizeof(val)) < 0) {
|
||||
snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
|
||||
"can't activate TPACKET_V2 on socket %d: %d-%s",
|
||||
handle->fd, errno, pcap_strerror(errno));
|
||||
return 0;
|
||||
"can't activate TPACKET_V2 on packet socket: %s",
|
||||
pcap_strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
handle->md.tp_version = TPACKET_V2;
|
||||
|
||||
|
@ -2004,9 +2034,9 @@ prepare_tpacket_socket(pcap_t *handle)
|
|||
if (setsockopt(handle->fd, SOL_PACKET, PACKET_RESERVE, &val,
|
||||
sizeof(val)) < 0) {
|
||||
snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
|
||||
"can't set up reserve on socket %d: %d-%s",
|
||||
handle->fd, errno, pcap_strerror(errno));
|
||||
return 0;
|
||||
"can't set up reserve on packet socket: %s",
|
||||
pcap_strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
#endif /* HAVE_TPACKET2 */
|
||||
|
@ -2058,9 +2088,15 @@ retry:
|
|||
req.tp_block_nr = req.tp_frame_nr/frames_per_block;
|
||||
goto retry;
|
||||
}
|
||||
snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "can't create rx ring on "
|
||||
"packet socket %d: %d-%s", handle->fd, errno,
|
||||
pcap_strerror(errno));
|
||||
if (errno == ENOPROTOOPT) {
|
||||
/*
|
||||
* We don't have ring buffer support in this kernel.
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
|
||||
"can't create rx ring on packet socket: %s",
|
||||
pcap_strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
Reference in New Issue