]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
Add the ablity to set a local address for BIO_dgram_pair
authorMatt Caswell <matt@openssl.org>
Tue, 26 Nov 2024 12:36:52 +0000 (12:36 +0000)
committerNeil Horman <nhorman@openssl.org>
Mon, 17 Feb 2025 16:27:33 +0000 (11:27 -0500)
BIOs created from a BIO_dgram_pair don't normally have a local BIO_ADDR
associated with them. This allows us to set one.

Fixes openssl/project#933

Reviewed-by: Tim Hudson <tjh@openssl.org>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
Reviewed-by: Saša Nedvědický <sashan@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/26066)

crypto/bio/bss_dgram_pair.c
include/openssl/bio.h.in
test/helpers/quictestlib.c

index 08dd802d8fd42a1b0b457175bde7a7a3693e6ea7..8a42d66bcc437d20808193a26498ffeecaec1310 100644 (file)
@@ -256,6 +256,8 @@ struct bio_dgram_pair_st {
     size_t mtu;
     /* Capability flags. */
     uint32_t cap;
+    /* The local address to use (if set) */
+    BIO_ADDR *local_addr;
     /*
      * This lock protects updates to our rbuf. Since writes are directed to our
      * own rbuf, this means we use this lock for writes and our peer's lock for
@@ -405,6 +407,8 @@ static int dgram_pair_ctrl_destroy_bio_pair(BIO *bio1)
     ring_buf_destroy(&b1->rbuf);
     bio1->init = 0;
 
+    BIO_ADDR_free(b1->local_addr);
+
     /* Early return if we don't have a peer. */
     if (b1->peer == NULL)
         return 1;
@@ -634,6 +638,16 @@ static int dgram_pair_ctrl_set_mtu(BIO *bio, size_t mtu)
     return 1;
 }
 
+/* BIO_dgram_set0_local_addr (BIO_CTRL_DGRAM_SET0_LOCAL_ADDR) */
+static int dgram_pair_ctrl_set0_local_addr(BIO *bio, BIO_ADDR *addr)
+{
+    struct bio_dgram_pair_st *b = bio->ptr;
+
+    BIO_ADDR_free(b->local_addr);
+    b->local_addr = addr;
+    return 1;
+}
+
 /* Partially threadsafe (some commands) */
 static long dgram_mem_ctrl(BIO *bio, int cmd, long num, void *ptr)
 {
@@ -731,6 +745,10 @@ static long dgram_mem_ctrl(BIO *bio, int cmd, long num, void *ptr)
         ret = (long)dgram_pair_ctrl_set_mtu(bio, (uint32_t)num);
         break;
 
+    case BIO_CTRL_DGRAM_SET0_LOCAL_ADDR:
+        ret = (long)dgram_pair_ctrl_set0_local_addr(bio, (BIO_ADDR *)ptr);
+        break;
+
     /*
      * BIO_eof: Returns whether this half of the BIO pair is empty of data to
      * read.
@@ -1230,6 +1248,8 @@ static ossl_ssize_t dgram_pair_write_actual(BIO *bio, const char *buf, size_t sz
 
     hdr.len = sz;
     hdr.dst_addr = (peer != NULL ? *peer : zero_addr);
+    if (local == NULL)
+        local = b->local_addr;
     hdr.src_addr = (local != NULL ? *local : zero_addr);
 
     saved_idx   = b->rbuf.idx[0];
index 7e684be5948921f13e21948ab0e5eac53d11e06d..d0a09cfe39389595010a929061e320ca381feacc 100644 (file)
@@ -194,6 +194,7 @@ extern "C" {
 # define BIO_CTRL_GET_RPOLL_DESCRIPTOR          91
 # define BIO_CTRL_GET_WPOLL_DESCRIPTOR          92
 # define BIO_CTRL_DGRAM_DETECT_PEER_ADDR        93
+# define BIO_CTRL_DGRAM_SET0_LOCAL_ADDR         94
 
 # define BIO_DGRAM_CAP_NONE                 0U
 # define BIO_DGRAM_CAP_HANDLES_SRC_ADDR     (1U << 0)
@@ -670,6 +671,8 @@ int BIO_ctrl_reset_read_request(BIO *b);
          (unsigned int)BIO_ctrl((b), BIO_CTRL_DGRAM_GET_MTU, 0, NULL)
 # define BIO_dgram_set_mtu(b, mtu) \
          (int)BIO_ctrl((b), BIO_CTRL_DGRAM_SET_MTU, (mtu), NULL)
+# define BIO_dgram_set0_local_addr(b, addr) \
+         (int)BIO_ctrl((b), BIO_CTRL_DGRAM_SET0_LOCAL_ADDR, 0, (addr))
 
 /* ctrl macros for BIO_f_prefix */
 # define BIO_set_prefix(b,p) BIO_ctrl((b), BIO_CTRL_SET_PREFIX, 0, (void *)(p))
index db39d659b16d56b3147bbb893cf02404a8aa6e58..83fe29c78cfb20013711a186467556c256a348dc 100644 (file)
@@ -193,6 +193,8 @@ int qtest_create_quic_objects(OSSL_LIB_CTX *libctx, SSL_CTX *clientctx,
         goto err;
 #endif
     } else {
+        BIO_ADDR *localaddr = NULL;
+
         if (!TEST_true(BIO_new_bio_dgram_pair(&cbio, 0, &sbio, 0)))
             goto err;
 
@@ -200,6 +202,18 @@ int qtest_create_quic_objects(OSSL_LIB_CTX *libctx, SSL_CTX *clientctx,
                 || !TEST_true(BIO_dgram_set_caps(sbio, BIO_DGRAM_CAP_HANDLES_DST_ADDR)))
             goto err;
 
+        if (!TEST_ptr(localaddr = BIO_ADDR_new()))
+            goto err;
+        /* Dummy client local addresses */
+        if (!TEST_true(BIO_ADDR_rawmake(localaddr, AF_INET, &ina, sizeof(ina),
+                                        htons(0)))) {
+            BIO_ADDR_free(localaddr);
+            goto err;
+        }
+        if (!TEST_int_eq(BIO_dgram_set0_local_addr(cbio, localaddr), 1)) {
+            BIO_ADDR_free(localaddr);
+            goto err;
+        }
         /* Dummy server address */
         if (!TEST_true(BIO_ADDR_rawmake(peeraddr, AF_INET, &ina, sizeof(ina),
                                         htons(0))))