diff options
author | Guy Harris <guy@alum.mit.edu> | 2018-11-30 22:59:34 -0800 |
---|---|---|
committer | Guy Harris <guy@alum.mit.edu> | 2018-11-30 22:59:34 -0800 |
commit | 357a8a25bf018485352c5046009f12aa21907504 (patch) | |
tree | 2828c1f259c45adeb893b2a3b84d64efe06626e8 /pcap-linux.c | |
parent | e06e9b39da8d38553028af204cb691cf794325ed (diff) |
Don't try PACKET_RESERVE if we can't use TPACKET_V2 or later.
If we're using TPACKET_V1, it's because we have a kernel that doesn't
support TPACKET_V2; such a kernel also doesn't support PACKET_RESERVE,
as TPACKET_V2 and PACKET_RESERVE were both added in 2.6.27.
If we *aren't* using TPACKET_V1, treat any failure of PACKET_RESERVE as
an error, as it should be supported, and we should never get ENOPROTOOPT.
Diffstat (limited to 'pcap-linux.c')
-rw-r--r-- | pcap-linux.c | 82 |
1 files changed, 44 insertions, 38 deletions
diff --git a/pcap-linux.c b/pcap-linux.c index 0b787496..f0862d7f 100644 --- a/pcap-linux.c +++ b/pcap-linux.c @@ -4359,49 +4359,54 @@ create_ring(pcap_t *handle, int *status) */ *status = 0; -#ifdef PACKET_RESERVE +#ifdef TPACKET_RESERVE /* - * Reserve space for VLAN tag reconstruction. + * TPACKET_V2 and PACKET_RESERVE were both introduced in + * 2.6.27. If tp_version is for TPACKET_V1, that means + * the kernel doesn't support TPACKET_V2, so it won't + * support PACKET_RESERVE, either. */ - tp_reserve = VLAN_TAG_LEN; + if (handle->tp_version != TPACKET_V1 && + handle->tp_version != TPACKET_V1_64) { + /* + * Reserve space for VLAN tag reconstruction. + */ + tp_reserve = VLAN_TAG_LEN; - /* - * If we're using DLT_LINUX_SLL2, reserve space for a - * DLT_LINUX_SLL2 header. - * - * XXX - we assume that the kernel is still adding - * 16 bytes of extra space; that happens to - * correspond to SLL_HDR_LEN (whether intentionally - * or not - the kernel code has a raw "16" in - * the expression), so we subtract SLL_HDR_LEN - * from SLL2_HDR_LEN to get the additional space - * needed. - * - * XXX - should we reserve space for a DLT_LINUX_SLL header - * if we're using DLT_LINUX_SLL? - * - * XXX - should we use TPACKET_ALIGN(SLL2_HDR_LEN - SLL_HDR_LEN)? - */ - if (handle->linktype == DLT_LINUX_SLL2) - tp_reserve += SLL2_HDR_LEN - SLL_HDR_LEN; + /* + * If we're using DLT_LINUX_SLL2, reserve space for a + * DLT_LINUX_SLL2 header. + * + * XXX - we assume that the kernel is still adding + * 16 bytes of extra space; that happens to + * correspond to SLL_HDR_LEN (whether intentionally + * or not - the kernel code has a raw "16" in + * the expression), so we subtract SLL_HDR_LEN + * from SLL2_HDR_LEN to get the additional space + * needed. That also means we don't bother reserving + * any additional space if we're using DLT_LINUX_SLL. + * + * XXX - should we use TPACKET_ALIGN(SLL2_HDR_LEN - SLL_HDR_LEN)? + */ + if (handle->linktype == DLT_LINUX_SLL2) + tp_reserve += SLL2_HDR_LEN - SLL_HDR_LEN; - /* - * Try to request that amount of reserve space. - * This must be done before creating the ring buffer. - * If PACKET_RESERVE is supported, creating the ring - * buffer should be, although if creating the ring - * buffer fails, the PACKET_RESERVE call has no effect, - * so falling back on read-from-the-socket capturing - * won't be affected. - */ - len = sizeof(tp_reserve); - if (setsockopt(handle->fd, SOL_PACKET, PACKET_RESERVE, - &tp_reserve, len) < 0) { - if (errno != ENOPROTOOPT) { + /* + * Try to request that amount of reserve space. + * This must be done before creating the ring buffer. + * If PACKET_RESERVE is supported, creating the ring + * buffer should be, although if creating the ring + * buffer fails, the PACKET_RESERVE call has no effect, + * so falling back on read-from-the-socket capturing + * won't be affected. + */ + len = sizeof(tp_reserve); + if (setsockopt(handle->fd, SOL_PACKET, PACKET_RESERVE, + &tp_reserve, len) < 0) { /* - * ENOPROTOOPT means "kernel doesn't support - * PACKET_RESERVE", in which case we fall back - * as best we can. + * We treat ENOPROTOOPT as an error, as we + * already determined that we support + * TPACKET_V2 and later; see above. */ pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE, errno, @@ -4409,6 +4414,7 @@ create_ring(pcap_t *handle, int *status) *status = PCAP_ERROR; return -1; } + } else { /* * Older kernel, so we can't use PACKET_RESERVE; * this means we can't reserver extra space |