Commit d53cf1fe3d for openssl.org
commit d53cf1fe3dd9a9ea6066481c6e4bb39128636c11
Author: Sashan <anedvedicky@gmail.com>
Date: Mon Sep 21 17:11:11 2026 +0200
Update doc/man3/BIO_s_dgram_pair.pod
Co-authored-by: Jakub Zelenka <bukka@php.net>
Reviewed-by: Norbert Pocs <norbertp@openssl.org>
Reviewed-by: Neil Horman <nhorman@openssl.org>
Merge-date: Thu Oct 29 11:29:37 2026
Merged-from: https://github.com/openssl/openssl/pull/32266
diff --git a/.github/workflows/run-checker-ci.yml b/.github/workflows/run-checker-ci.yml
index c46561a679..89186ff03c 100644
--- a/.github/workflows/run-checker-ci.yml
+++ b/.github/workflows/run-checker-ci.yml
@@ -59,7 +59,6 @@ jobs:
no-tls1_2,
no-tls1_3,
enable-trace enable-fips,
- no-pcap,
no-quic,
-DOPENSSL_USE_IPV6=0
]
diff --git a/.github/workflows/run-checker-daily.yml b/.github/workflows/run-checker-daily.yml
index 7516a4c9ba..6ea8dc0ec1 100644
--- a/.github/workflows/run-checker-daily.yml
+++ b/.github/workflows/run-checker-daily.yml
@@ -166,6 +166,7 @@ jobs:
no-x942kdf,
no-x963kdf,
enable-zlib-dynamic,
+ enable-pcap,
-DOPENSSL_PEDANTIC_ZEROIZATION,
-DOPENSSL_PEDANTIC_ZEROIZATION enable-fips,
-DOPENSSL_NO_BUILTIN_OVERFLOW_CHECKING,
diff --git a/CHANGES.md b/CHANGES.md
index cb595bd69b..227f0ea594 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -33,6 +33,14 @@ OpenSSL 4.2
### Changes between 4.1 and 4.2 [xx XXX xxxx]
+ * Added `BIO_dgram_pair_set0_pcap_file()` which intercepts and writes UDP
+ datagrams exchanged of over `BIO_dgram_pair` bio memory object to file
+ in libpcap format. To enable `BIO_dgram_pair_set0_pcap_file()` the build
+ must be configured with `enable-pcap` option.
+ <!-- https://github.com/openssl/openssl/pull/32266 -->
+
+ *Alexandr Nedvedicky*
+
* s390x: Disable mod-expo offloading to a crypto card for small exponents.
Add a new keyword `cex_min_bits:<bits>` for the `OPENSSL_s390xcap`
environment variable to specify the minimum number of bits that the
@@ -68,6 +76,7 @@ OpenSSL 4.2
*Viktor Dukhovni*
+
* `EVP_SKEY_get0_raw_key()` now accepts a NULL key pointer to retrieve only
the key length. The length is obtained from the `OSSL_SKEY_PARAM_KEY_LENGTH`
key parameter without exporting the key, so it is also available for keys
diff --git a/crypto/bio/bss_dgram_pair.c b/crypto/bio/bss_dgram_pair.c
index 0eeff94cd4..71146c147d 100644
--- a/crypto/bio/bss_dgram_pair.c
+++ b/crypto/bio/bss_dgram_pair.c
@@ -316,6 +316,11 @@ struct bio_dgram_peer_st {
* indexed one per direction.
*/
struct rbuf_map_st map[2];
+#ifndef OPENSSL_NO_PCAP
+ FILE *tcpdump_f;
+ CRYPTO_MUTEX *pcap_mutex;
+ uint16_t ip_id;
+#endif
};
struct bio_dgram_pair_st {
@@ -341,12 +346,6 @@ struct bio_dgram_pair_st {
unsigned int local_addr_enable : 1; /* Can use BIO_MSG->local? */
unsigned int role : 1; /* Determines lock order */
unsigned int grows_on_write : 1; /* Set for BIO_s_dgram_mem only */
-#ifndef OPENSSL_NO_PCAP
- FILE *tcpdump_f;
- CRYPTO_MUTEX *pcap_mutex;
- int owner;
- uint64_t packet_num;
-#endif
};
/*
@@ -482,10 +481,6 @@ static int dgram_pair_free(BIO *bio)
ring_buf_destroy(&b->rbuf);
BIO_ADDR_free(b->local_addr);
CRYPTO_THREAD_lock_free(b->lock);
-#ifndef OPENSSL_NO_PCAP
- if (b->tcpdump_f != NULL)
- fclose(b->tcpdump_f);
-#endif
OPENSSL_free(b);
return 1;
}
@@ -608,7 +603,7 @@ static int dgram_pair_ctrl_set_pcap_file(BIO *bio, void *ptr)
#ifndef OPENSSL_NO_PCAP
#define LINKTYPE_IPV4 0x00e4 /* IANA type */
- struct bio_dgram_pair_st *b1, *b2;
+ struct bio_dgram_pair_st *bp;
char *filename = (char *)ptr;
static struct {
uint32_t pcap_magic;
@@ -628,30 +623,23 @@ static int dgram_pair_ctrl_set_pcap_file(BIO *bio, void *ptr)
.pcap_ltype = LINKTYPE_IPV4,
};
- b1 = (struct bio_dgram_pair_st *)bio->ptr;
- if (b1 == NULL)
+ bp = (struct bio_dgram_pair_st *)bio->ptr;
+ if (bp == NULL)
return 0;
- if (b1->peer == NULL)
- return 0;
-
- b2 = (struct bio_dgram_pair_st *)b1->peer->ptr;
- if (b2 == NULL)
+ if (bp->pair == NULL || bp->pair->peer_state == PEER_STATE_ORPHANED)
return 0;
if (filename != NULL) {
- if (b1->tcpdump_f == NULL) {
- b1->pcap_mutex = ossl_crypto_mutex_new();
- if (b1->pcap_mutex != NULL) {
- b1->tcpdump_f = fopen(filename, "wb");
- if (b1->tcpdump_f != NULL) {
- b1->owner = 1;
- b2->tcpdump_f = b1->tcpdump_f;
- b2->pcap_mutex = b1->pcap_mutex;
+ if (bp->pair->tcpdump_f == NULL) {
+ bp->pair->pcap_mutex = ossl_crypto_mutex_new();
+ if (bp->pair->pcap_mutex != NULL) {
+ bp->pair->tcpdump_f = fopen(filename, "wb");
+ if (bp->pair->tcpdump_f != NULL) {
ret = fwrite(&pcap_f_header, sizeof(pcap_f_header), 1,
- b1->tcpdump_f);
+ bp->pair->tcpdump_f);
} else {
- ossl_crypto_mutex_free(&b1->pcap_mutex);
+ ossl_crypto_mutex_free(&bp->pair->pcap_mutex);
}
}
}
@@ -692,26 +680,19 @@ static int dgram_pair_ctrl_destroy_bio_pair(BIO *bio1)
* The last half of the pair is leaving, clean up the
* shared data
*/
-#ifndef OPENSSL_NO_PCAP
- if (b1->tcpdump_f != NULL || b2->tcpdump_f != NULL) {
- if (b1->owner && b1->tcpdump_f) {
- fclose(b1->tcpdump_f);
- ossl_crypto_mutex_free(&b1->pcap_mutex);
- }
- if (b2->owner && b2->tcpdump_f) {
- fclose(b2->tcpdump_f);
- ossl_crypto_mutex_free(&b2->pcap_mutex);
- }
- b1->tcpdump_f = NULL;
- b2->tcpdump_f = NULL;
- }
-#endif
CRYPTO_FREE_REF(&b1->pair->ref_cnt);
CRYPTO_THREAD_lock_free(b1->pair->map[0].lock);
CRYPTO_THREAD_lock_free(b1->pair->map[1].lock);
CRYPTO_THREAD_lock_free(b1->pair->peerlock);
ring_buf_destroy(&b1->pair->map[0].rbuf);
ring_buf_destroy(&b1->pair->map[1].rbuf);
+#ifndef OPENSSL_NO_PCAP
+ if (b1->pair->tcpdump_f != NULL) {
+ fclose(b1->pair->tcpdump_f);
+ ossl_crypto_mutex_free(&b1->pair->pcap_mutex);
+ b1->pair->tcpdump_f = NULL;
+ }
+#endif
OPENSSL_free(b1->pair);
}
/*
@@ -1578,7 +1559,7 @@ static void dgram_pcap(struct bio_dgram_pair_st *b, const char *buf, size_t sz)
OSSL_TIME now;
struct bio_dgram_pair_st *peer;
- if (b->tcpdump_f == NULL || sz == 0)
+ if (b->pair->tcpdump_f == NULL || sz == 0)
return;
if ((sz + sizeof(ip_hdr) + sizeof(udp_hdr)) > 65535)
@@ -1595,15 +1576,23 @@ static void dgram_pcap(struct bio_dgram_pair_st *b, const char *buf, size_t sz)
ip_hdr.ip_hv = 0x45;
ip_hdr.ip_tos = 0;
ip_hdr.ip_len = htons(len);
- RAND_bytes((unsigned char *)&ip_hdr.ip_id, 2);
+ ip_hdr.ip_id = b->pair->ip_id++;
ip_hdr.ip_frag = 0x40; /* don't fragment */
ip_hdr.ip_foff = 0;
ip_hdr.ip_ttl = 64;
ip_hdr.ip_proto = 17;
ip_hdr.ip_csum = 0; /* wireshark will complain with ?chksum offload? */
- ip_hdr.ip_src = (b->local_addr == NULL) ? htonl(0x7f000001) : b->local_addr->s_in.sin_addr.s_addr;
- peer = (struct bio_dgram_pair_st *)b->peer->ptr;
- ip_hdr.ip_dst = (peer == NULL || peer->local_addr == NULL) ? htonl(0x7f000001) : peer->local_addr->s_in.sin_addr.s_addr;
+ ip_hdr.ip_src = (b->local_addr == NULL)
+ ? htonl(0x7f000001)
+ : b->local_addr->s_in.sin_addr.s_addr;
+ if (b->pair->map[0].self == b) {
+ peer = b->pair->map[1].self;
+ } else {
+ peer = b->pair->map[0].self;
+ }
+ ip_hdr.ip_dst = (peer == NULL || peer->local_addr == NULL)
+ ? htonl(0x7f000001)
+ : peer->local_addr->s_in.sin_addr.s_addr;
/*
* use some fake port numbers
@@ -1612,12 +1601,12 @@ static void dgram_pcap(struct bio_dgram_pair_st *b, const char *buf, size_t sz)
udp_hdr.uh_dport = (peer == NULL || peer->local_addr == NULL) ? htons(4040) : peer->local_addr->s_in.sin_port;
udp_hdr.uh_csum = 0;
udp_hdr.uh_len = htons((uint16_t)(sz + sizeof(udp_hdr)));
- ossl_crypto_mutex_lock(b->pcap_mutex);
- fwrite(&pcap_hdr, sizeof(pcap_hdr), 1, b->tcpdump_f);
- fwrite(&ip_hdr, sizeof(ip_hdr), 1, b->tcpdump_f);
- fwrite(&udp_hdr, sizeof(udp_hdr), 1, b->tcpdump_f);
- fwrite(buf, sz, 1, b->tcpdump_f);
- ossl_crypto_mutex_unlock(b->pcap_mutex);
+ ossl_crypto_mutex_lock(b->pair->pcap_mutex);
+ fwrite(&pcap_hdr, sizeof(pcap_hdr), 1, b->pair->tcpdump_f);
+ fwrite(&ip_hdr, sizeof(ip_hdr), 1, b->pair->tcpdump_f);
+ fwrite(&udp_hdr, sizeof(udp_hdr), 1, b->pair->tcpdump_f);
+ fwrite(buf, sz, 1, b->pair->tcpdump_f);
+ ossl_crypto_mutex_unlock(b->pair->pcap_mutex);
}
#endif
diff --git a/doc/man3/BIO_s_dgram_pair.pod b/doc/man3/BIO_s_dgram_pair.pod
index 1d2893c86a..1596fd907b 100644
--- a/doc/man3/BIO_s_dgram_pair.pod
+++ b/doc/man3/BIO_s_dgram_pair.pod
@@ -5,7 +5,7 @@
BIO_s_dgram_pair, BIO_new_bio_dgram_pair, BIO_dgram_set_no_trunc,
BIO_dgram_get_no_trunc, BIO_dgram_get_effective_caps, BIO_dgram_get_caps,
BIO_dgram_set_caps, BIO_dgram_set_mtu, BIO_dgram_get_mtu,
-BIO_dgram_set0_local_addr, BIO_dgram_pair_set0_pcap_file - datagram pair BIO
+BIO_dgram_set0_local_addr, BIO_dgram_pair_set0_pcap_file - datagram pair BIO
=head1 SYNOPSIS
@@ -242,6 +242,8 @@ BIO_dgram_set_mtu(), BIO_dgram_set_no_trunc() were added in OpenSSL 3.2.
BIO_dgram_set0_local_addr() was added in OpenSSL 3.5.
+BIO_dgram_pair_set0_pcap_file() was added in OpenSSL 4.2
+
=head1 COPYRIGHT
Copyright 2022-2025 The OpenSSL Project Authors. All Rights Reserved.
diff --git a/util/other.syms b/util/other.syms
index b3ce2ecb4a..0ece2234cc 100644
--- a/util/other.syms
+++ b/util/other.syms
@@ -916,3 +916,4 @@ OPENSSL_store_u64_be inline
OPENSSL_store_u64_le inline
OSSL_BEGIN_ALLOW_DEPRECATED define
OSSL_END_ALLOW_DEPRECATED define
+BIO_dgram_pair_set0_pcap_file define