INCLUDE[quic_client_test]=../include ../apps/include
DEPEND[quic_client_test]=../libcrypto.a ../libssl.a libtestutil.a
- SOURCE[quic_multistream_test]=quic_multistream_test.c helpers/ssltestlib.c helpers/quictestlib.c helpers/noisydgrambio.c
+ $QUICTESTHELPERS=helpers/quictestlib.c helpers/noisydgrambio.c helpers/pktsplitbio.c
+
+ SOURCE[quic_multistream_test]=quic_multistream_test.c helpers/ssltestlib.c $QUICTESTHELPERS
INCLUDE[quic_multistream_test]=../include ../apps/include
DEPEND[quic_multistream_test]=../libcrypto.a ../libssl.a libtestutil.a
INCLUDE[event_queue_test]=../include ../apps/include
DEPEND[event_queue_test]=../libcrypto ../libssl.a libtestutil.a
- SOURCE[quicfaultstest]=quicfaultstest.c helpers/ssltestlib.c helpers/quictestlib.c helpers/noisydgrambio.c
+ SOURCE[quicfaultstest]=quicfaultstest.c helpers/ssltestlib.c $QUICTESTHELPERS
INCLUDE[quicfaultstest]=../include ../apps/include ..
DEPEND[quicfaultstest]=../libcrypto.a ../libssl.a libtestutil.a
- SOURCE[quicapitest]=quicapitest.c helpers/ssltestlib.c helpers/quictestlib.c helpers/noisydgrambio.c
+ SOURCE[quicapitest]=quicapitest.c helpers/ssltestlib.c $QUICTESTHELPERS
INCLUDE[quicapitest]=../include ../apps/include
DEPEND[quicapitest]=../libcrypto.a ../libssl.a libtestutil.a
- SOURCE[quic_newcid_test]=quic_newcid_test.c helpers/ssltestlib.c helpers/quictestlib.c helpers/noisydgrambio.c
+ SOURCE[quic_newcid_test]=quic_newcid_test.c helpers/ssltestlib.c $QUICTESTHELPERS
INCLUDE[quic_newcid_test]=../include ../apps/include ..
DEPEND[quic_newcid_test]=../libcrypto.a ../libssl.a libtestutil.a
ENDIF
*delay += (uint64_t)(*should_drop);
}
-/* There isn't a public function to do BIO_ADDR_copy() so we create one */
-static int bio_addr_copy(BIO_ADDR *dst, BIO_ADDR *src)
-{
- size_t len;
- void *data = NULL;
- int res = 0;
- int family;
-
- if (src == NULL || dst == NULL)
- return 0;
-
- family = BIO_ADDR_family(src);
- if (family == AF_UNSPEC) {
- BIO_ADDR_clear(dst);
- return 1;
- }
-
- if (!BIO_ADDR_rawaddress(src, NULL, &len))
- return 0;
-
- if (len > 0) {
- data = OPENSSL_malloc(len);
- if (!TEST_ptr(data))
- return 0;
- }
-
- if (!BIO_ADDR_rawaddress(src, data, &len))
- goto err;
-
- if (!BIO_ADDR_rawmake(src, family, data, len, BIO_ADDR_rawport(src)))
- goto err;
-
- res = 1;
- err:
- OPENSSL_free(data);
- return res;
-}
-
-static int bio_msg_copy(BIO_MSG *dst, BIO_MSG *src)
-{
- /*
- * Note it is assumed that the originally allocated data sizes for dst and
- * src are the same
- */
- memcpy(dst->data, src->data, src->data_len);
- dst->data_len = src->data_len;
- dst->flags = src->flags;
- if (dst->local != NULL) {
- if (src->local != NULL) {
- if (!TEST_true(bio_addr_copy(dst->local, src->local)))
- return 0;
- } else {
- BIO_ADDR_clear(dst->local);
- }
- }
- if (!TEST_true(bio_addr_copy(dst->peer, src->peer)))
- return 0;
-
- return 1;
-}
-
static int noisy_dgram_recvmmsg(BIO *bio, BIO_MSG *msg, size_t stride,
size_t num_msg, uint64_t flags,
size_t *msgs_processed)
--- /dev/null
+/*
+ * Copyright 2023 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/bio.h>
+#include "quictestlib.h"
+#include "../testutil.h"
+
+static int pkt_split_dgram_read(BIO *bio, char *out, int outl)
+{
+ /* We don't support this - not needed anyway */
+ return -1;
+}
+
+static int pkt_split_dgram_write(BIO *bio, const char *in, int inl)
+{
+ /* We don't support this - not needed anyway */
+ return -1;
+}
+
+static long pkt_split_dgram_ctrl(BIO *bio, int cmd, long num, void *ptr)
+{
+ long ret;
+ BIO *next = BIO_next(bio);
+
+ if (next == NULL)
+ return 0;
+
+ switch (cmd) {
+ case BIO_CTRL_DUP:
+ ret = 0L;
+ break;
+ default:
+ ret = BIO_ctrl(next, cmd, num, ptr);
+ break;
+ }
+ return ret;
+}
+
+static int pkt_split_dgram_gets(BIO *bio, char *buf, int size)
+{
+ /* We don't support this - not needed anyway */
+ return -1;
+}
+
+static int pkt_split_dgram_puts(BIO *bio, const char *str)
+{
+ /* We don't support this - not needed anyway */
+ return -1;
+}
+
+static int pkt_split_dgram_sendmmsg(BIO *bio, BIO_MSG *msg, size_t stride,
+ size_t num_msg, uint64_t flags,
+ size_t *msgs_processed)
+{
+ BIO *next = BIO_next(bio);
+
+ if (next == NULL)
+ return 0;
+
+ /*
+ * We only introduce noise when receiving messages. We just pass this on
+ * to the underlying BIO.
+ */
+ return BIO_sendmmsg(next, msg, stride, num_msg, flags, msgs_processed);
+}
+
+static int pkt_split_dgram_recvmmsg(BIO *bio, BIO_MSG *msg, size_t stride,
+ size_t num_msg, uint64_t flags,
+ size_t *msgs_processed)
+{
+ BIO *next = BIO_next(bio);
+ size_t i, j, data_len = 0, msg_cnt = 0;
+ BIO_MSG *thismsg;
+
+ if (!TEST_ptr(next))
+ return 0;
+
+ /*
+ * For simplicity we assume that all elements in the msg array have the
+ * same data_len. They are not required to by the API, but it would be quite
+ * strange for that not to be the case - and our code that calls
+ * BIO_recvmmsg does do this (which is all that is important for this test
+ * code). We test the invariant here.
+ */
+ for (i = 0; i < num_msg; i++) {
+ if (i == 0)
+ data_len = msg[i].data_len;
+ else if (!TEST_size_t_eq(msg[i].data_len, data_len))
+ return 0;
+ }
+
+ if (!BIO_recvmmsg(next, msg, stride, num_msg, flags, msgs_processed))
+ return 0;
+
+ msg_cnt = *msgs_processed;
+ if (msg_cnt == num_msg)
+ return 1; /* We've used all our slots and can't split any more */
+ assert(msg_cnt < num_msg);
+
+ for (i = 0, thismsg = msg; i < msg_cnt; i++, thismsg++) {
+ QUIC_PKT_HDR hdr;
+ PACKET pkt;
+ size_t remain;
+
+ if (!PACKET_buf_init(&pkt, thismsg->data, thismsg->data_len))
+ return 0;
+
+ /* Decode the packet header */
+ /*
+ * TODO(QUIC SERVER): We need to query the short connection id len
+ * here, e.g. via some API SSL_get_short_conn_id_len()
+ */
+ if (ossl_quic_wire_decode_pkt_hdr(&pkt, 0, 0, 0, &hdr, NULL) != 1)
+ return 0;
+ remain = PACKET_remaining(&pkt);
+ if (remain > 0) {
+ for (j = msg_cnt; j > i; j--) {
+ if (!bio_msg_copy(&msg[j], &msg[j - 1]))
+ return 0;
+ }
+ thismsg->data_len -= remain;
+ msg[i + 1].data_len = remain;
+ memmove(msg[i + 1].data,
+ (unsigned char *)msg[i + 1].data + thismsg->data_len,
+ remain);
+ msg_cnt++;
+ }
+ }
+
+ *msgs_processed = msg_cnt;
+ return 1;
+}
+
+/* Choose a sufficiently large type likely to be unused for this custom BIO */
+#define BIO_TYPE_PKT_SPLIT_DGRAM_FILTER (0x81 | BIO_TYPE_FILTER)
+
+static BIO_METHOD *method_pkt_split_dgram = NULL;
+
+/* Note: Not thread safe! */
+const BIO_METHOD *bio_f_pkt_split_dgram_filter(void)
+{
+ if (method_pkt_split_dgram == NULL) {
+ method_pkt_split_dgram = BIO_meth_new(BIO_TYPE_PKT_SPLIT_DGRAM_FILTER,
+ "Packet splitting datagram filter");
+ if (method_pkt_split_dgram == NULL
+ || !BIO_meth_set_write(method_pkt_split_dgram, pkt_split_dgram_write)
+ || !BIO_meth_set_read(method_pkt_split_dgram, pkt_split_dgram_read)
+ || !BIO_meth_set_puts(method_pkt_split_dgram, pkt_split_dgram_puts)
+ || !BIO_meth_set_gets(method_pkt_split_dgram, pkt_split_dgram_gets)
+ || !BIO_meth_set_ctrl(method_pkt_split_dgram, pkt_split_dgram_ctrl)
+ || !BIO_meth_set_sendmmsg(method_pkt_split_dgram,
+ pkt_split_dgram_sendmmsg)
+ || !BIO_meth_set_recvmmsg(method_pkt_split_dgram,
+ pkt_split_dgram_recvmmsg))
+ return NULL;
+ }
+ return method_pkt_split_dgram;
+}
+
+void bio_f_pkt_split_dgram_filter_free(void)
+{
+ BIO_meth_free(method_pkt_split_dgram);
+}
return 1;
}
+
+/* There isn't a public function to do BIO_ADDR_copy() so we create one */
+int bio_addr_copy(BIO_ADDR *dst, BIO_ADDR *src)
+{
+ size_t len;
+ void *data = NULL;
+ int res = 0;
+ int family;
+
+ if (src == NULL || dst == NULL)
+ return 0;
+
+ family = BIO_ADDR_family(src);
+ if (family == AF_UNSPEC) {
+ BIO_ADDR_clear(dst);
+ return 1;
+ }
+
+ if (!BIO_ADDR_rawaddress(src, NULL, &len))
+ return 0;
+
+ if (len > 0) {
+ data = OPENSSL_malloc(len);
+ if (!TEST_ptr(data))
+ return 0;
+ }
+
+ if (!BIO_ADDR_rawaddress(src, data, &len))
+ goto err;
+
+ if (!BIO_ADDR_rawmake(src, family, data, len, BIO_ADDR_rawport(src)))
+ goto err;
+
+ res = 1;
+ err:
+ OPENSSL_free(data);
+ return res;
+}
+
+int bio_msg_copy(BIO_MSG *dst, BIO_MSG *src)
+{
+ /*
+ * Note it is assumed that the originally allocated data sizes for dst and
+ * src are the same
+ */
+ memcpy(dst->data, src->data, src->data_len);
+ dst->data_len = src->data_len;
+ dst->flags = src->flags;
+ if (dst->local != NULL) {
+ if (src->local != NULL) {
+ if (!TEST_true(bio_addr_copy(dst->local, src->local)))
+ return 0;
+ } else {
+ BIO_ADDR_clear(dst->local);
+ }
+ }
+ if (!TEST_true(bio_addr_copy(dst->peer, src->peer)))
+ return 0;
+
+ return 1;
+}