aboutsummaryrefslogtreecommitdiff
path: root/pcap-linux.c
diff options
context:
space:
mode:
authorGuy Harris <guy@alum.mit.edu>2018-11-30 22:59:34 -0800
committerGuy Harris <guy@alum.mit.edu>2018-11-30 22:59:34 -0800
commit357a8a25bf018485352c5046009f12aa21907504 (patch)
tree2828c1f259c45adeb893b2a3b84d64efe06626e8 /pcap-linux.c
parente06e9b39da8d38553028af204cb691cf794325ed (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.c82
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