summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGuy Harris <gharris@sonic.net>2023-01-16 00:42:46 -0800
committerGitHub <noreply@github.com>2023-01-16 00:42:46 -0800
commit7b955929deb75804ec74dffc2934cbef7c1196c6 (patch)
treed2041a9baf6050d454b13871c9be66e9a5c2cad1
parent56b17aaab04148851bd3ea0f7580c0834dc49906 (diff)
parenta9487778d264f8e272ddb6c8b9dc4897a05d4fdb (diff)
downloadlibpcap-7b955929deb75804ec74dffc2934cbef7c1196c6.tar.gz
Merge pull request #1142 from hansleidekker/mmap
Add an option to force memory-mapped buffers to be mapped as accessible to 32-bit code
-rw-r--r--pcap-bpf.c8
-rw-r--r--pcap-int.h5
-rw-r--r--pcap-linux.c22
-rw-r--r--pcap.c5
-rw-r--r--pcap/pcap.h1
-rw-r--r--pcap_init.3pcap3
6 files changed, 34 insertions, 10 deletions
diff --git a/pcap-bpf.c b/pcap-bpf.c
index 2898e598..92e73adf 100644
--- a/pcap-bpf.c
+++ b/pcap-bpf.c
@@ -1790,6 +1790,7 @@ pcap_activate_bpf(pcap_t *p)
#ifdef HAVE_ZEROCOPY_BPF
struct bpf_zbuf bz;
u_int bufmode, zbufmax;
+ int flags = MAP_ANON;
#endif
fd = bpf_open(p->errbuf);
@@ -2092,10 +2093,13 @@ pcap_activate_bpf(pcap_t *p)
pb->zbufsize = roundup(v, getpagesize());
if (pb->zbufsize > zbufmax)
pb->zbufsize = zbufmax;
+#ifdef MAP_32BIT
+ if (pcap_mmap_32bit) flags |= MAP_32BIT;
+#endif
pb->zbuf1 = mmap(NULL, pb->zbufsize, PROT_READ | PROT_WRITE,
- MAP_ANON, -1, 0);
+ flags, -1, 0);
pb->zbuf2 = mmap(NULL, pb->zbufsize, PROT_READ | PROT_WRITE,
- MAP_ANON, -1, 0);
+ flags, -1, 0);
if (pb->zbuf1 == MAP_FAILED || pb->zbuf2 == MAP_FAILED) {
pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
errno, "mmap");
diff --git a/pcap-int.h b/pcap-int.h
index fc703bf8..661ba542 100644
--- a/pcap-int.h
+++ b/pcap-int.h
@@ -108,6 +108,11 @@ extern int pcap_new_api;
extern int pcap_utf_8_mode;
/*
+ * Map packet buffers with 32-bit addresses.
+ */
+extern int pcap_mmap_32bit;
+
+/*
* Swap byte ordering of unsigned long long timestamp on a big endian
* machine.
*/
diff --git a/pcap-linux.c b/pcap-linux.c
index 43d2a9f0..871cb662 100644
--- a/pcap-linux.c
+++ b/pcap-linux.c
@@ -829,7 +829,7 @@ static void pcap_cleanup_linux( pcap_t *handle )
}
if (handlep->oneshot_buffer != NULL) {
- free(handlep->oneshot_buffer);
+ munmap(handlep->oneshot_buffer, handle->snapshot);
handlep->oneshot_buffer = NULL;
}
@@ -2661,14 +2661,17 @@ static int
setup_mmapped(pcap_t *handle, int *status)
{
struct pcap_linux *handlep = handle->priv;
- int ret;
+ int ret, flags = MAP_ANONYMOUS | MAP_PRIVATE;
/*
* Attempt to allocate a buffer to hold the contents of one
* packet, for use by the oneshot callback.
*/
- handlep->oneshot_buffer = malloc(handle->snapshot);
- if (handlep->oneshot_buffer == NULL) {
+#ifdef MAP_32BIT
+ if (pcap_mmap_32bit) flags |= MAP_32BIT;
+#endif
+ handlep->oneshot_buffer = mmap(0, handle->snapshot, PROT_READ | PROT_WRITE, flags, -1, 0);
+ if (handlep->oneshot_buffer == MAP_FAILED) {
pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
errno, "can't allocate oneshot buffer");
*status = PCAP_ERROR;
@@ -2681,7 +2684,7 @@ setup_mmapped(pcap_t *handle, int *status)
}
ret = prepare_tpacket_socket(handle);
if (ret == -1) {
- free(handlep->oneshot_buffer);
+ munmap(handlep->oneshot_buffer, handle->snapshot);
handlep->oneshot_buffer = NULL;
*status = PCAP_ERROR;
return ret;
@@ -2692,7 +2695,7 @@ setup_mmapped(pcap_t *handle, int *status)
* Error attempting to enable memory-mapped capture;
* fail. create_ring() has set *status.
*/
- free(handlep->oneshot_buffer);
+ munmap(handlep->oneshot_buffer, handle->snapshot);
handlep->oneshot_buffer = NULL;
return -1;
}
@@ -2870,6 +2873,7 @@ create_ring(pcap_t *handle, int *status)
{
struct pcap_linux *handlep = handle->priv;
unsigned i, j, frames_per_block;
+ int flags = MAP_SHARED;
#ifdef HAVE_TPACKET3
/*
* For sockets using TPACKET_V2, the extra stuff at the end of a
@@ -3252,8 +3256,10 @@ retry:
/* memory map the rx ring */
handlep->mmapbuflen = req.tp_block_nr * req.tp_block_size;
- handlep->mmapbuf = mmap(0, handlep->mmapbuflen,
- PROT_READ|PROT_WRITE, MAP_SHARED, handle->fd, 0);
+#ifdef MAP_32BIT
+ if (pcap_mmap_32bit) flags |= MAP_32BIT;
+#endif
+ handlep->mmapbuf = mmap(0, handlep->mmapbuflen, PROT_READ | PROT_WRITE, flags, handle->fd, 0);
if (handlep->mmapbuf == MAP_FAILED) {
pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
errno, "can't mmap rx ring");
diff --git a/pcap.c b/pcap.c
index 005103b9..86246048 100644
--- a/pcap.c
+++ b/pcap.c
@@ -230,6 +230,7 @@ pcap_wsockinit(void)
*/
int pcap_new_api; /* pcap_lookupdev() always fails */
int pcap_utf_8_mode; /* Strings should be in UTF-8. */
+int pcap_mmap_32bit; /* Map packet buffers with 32-bit addresses. */
int
pcap_init(unsigned int opts, char *errbuf)
@@ -267,6 +268,10 @@ pcap_init(unsigned int opts, char *errbuf)
pcap_utf_8_mode = 1;
break;
+ case PCAP_MMAP_32BIT:
+ pcap_mmap_32bit = 1;
+ break;
+
default:
snprintf(errbuf, PCAP_ERRBUF_SIZE, "Unknown options specified");
return (PCAP_ERROR);
diff --git a/pcap/pcap.h b/pcap/pcap.h
index 78570744..88b96847 100644
--- a/pcap/pcap.h
+++ b/pcap/pcap.h
@@ -429,6 +429,7 @@ typedef void (*pcap_handler)(u_char *, const struct pcap_pkthdr *,
*/
#define PCAP_CHAR_ENC_LOCAL 0x00000000U /* strings are in the local character encoding */
#define PCAP_CHAR_ENC_UTF_8 0x00000001U /* strings are in UTF-8 */
+#define PCAP_MMAP_32BIT 0x00000002U /* map packet buffers with 32-bit addresses */
PCAP_AVAILABLE_1_10
PCAP_API int pcap_init(unsigned int, char *);
diff --git a/pcap_init.3pcap b/pcap_init.3pcap
index a807d0ec..f9876d63 100644
--- a/pcap_init.3pcap
+++ b/pcap_init.3pcap
@@ -49,6 +49,9 @@ caller, as being in the local character encoding.
.B PCAP_CHAR_ENC_UTF_8
Treat all strings supplied as arguments, and return all strings to the
caller, as being in UTF-8.
+.B PCAP_MMAP_32BIT
+Map packet buffers with 32-bit addresses.
+.TP
.PP
On UNIX-like systems, the local character encoding is assumed to be
UTF-8, so no character encoding transformations are done.