/*
* Copyright 2022-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 <string.h>
#include <openssl/bio.h>
#include <openssl/rand.h>
#include "testutil.h"
#include "internal/sockets.h"
#if !defined(OPENSSL_NO_DGRAM) && !defined(OPENSSL_NO_SOCK)
static int compare_addr(const BIO_ADDR *a, const BIO_ADDR *b)
{
struct in_addr xa, xb;
#if OPENSSL_USE_IPV6
struct in6_addr xa6, xb6;
#endif
void *pa, *pb;
size_t slen, tmplen;
if (BIO_ADDR_family(a) != BIO_ADDR_family(b))
return 0;
if (BIO_ADDR_family(a) == AF_INET) {
pa = &xa;
pb = &xb;
slen = sizeof(xa);
}
#if OPENSSL_USE_IPV6
else if (BIO_ADDR_family(a) == AF_INET6) {
pa = &xa6;
pb = &xb6;
slen = sizeof(xa6);
}
#endif
else {
return 0;
}
tmplen = slen;
if (!TEST_int_eq(BIO_ADDR_rawaddress(a, pa, &tmplen), 1))
return 0;
tmplen = slen;
if (!TEST_int_eq(BIO_ADDR_rawaddress(b, pb, &tmplen), 1))
return 0;
if (!TEST_mem_eq(pa, slen, pb, slen))
return 0;
if (!TEST_int_eq(BIO_ADDR_rawport(a), BIO_ADDR_rawport(b)))
return 0;
return 1;
}
static int do_sendmmsg(BIO *b, BIO_MSG *msg,
size_t num_msg, uint64_t flags,
size_t *num_processed)
{
size_t done;
for (done = 0; done < num_msg; ) {
if (!BIO_sendmmsg(b, msg + done, sizeof(BIO_MSG),
num_msg - done, flags, num_processed))
return 0;
done += *num_processed;
}
*num_processed = done;
return 1;
}
static int do_recvmmsg(BIO *b, BIO_MSG *msg,
size_t num_msg, uint64_t flags,
size_t *num_processed)
{
size_t done;
for (done = 0; done < num_msg; ) {
if (!BIO_recvmmsg(b, msg + done, sizeof(BIO_MSG),
num_msg - done, flags, num_processed))
return 0;
done += *num_processed;
}
*num_processed = done;
return 1;
}
static int test_bio_dgram_impl(int af, int use_local)
{
int testresult = 0;
BIO *b1 = NULL, *b2 = NULL;
int fd1 = -1, fd2 = -1;
BIO_ADDR *addr1 = NULL, *addr2 = NULL, *addr3 = NULL, *addr4 = NULL,
*addr5 = NULL, *addr6 = NULL;
struct in_addr ina;
#if OPENSSL_USE_IPV6
struct in6_addr ina6;
#endif
void *pina;
size_t inal, i;
union BIO_sock_info_u info1 = {0}, info2 = {0};
char rx_buf[128], rx_buf2[128];
BIO_MSG tx_msg[128], rx_msg[128];
char tx_buf[128];
size_t num_processed = 0;
if (af == AF_INET) {
TEST_info("# Testing with AF_INET, local=%d\n", use_local);
pina = &ina;
inal = sizeof(ina);
}
#if OPENSSL_USE_IPV6
else if (af == AF_INET6) {
TEST_info("# Testing with AF_INET6, local=%d\n", use_local);
pina = &ina6;
inal = sizeof(ina6);
}
#endif
else {
goto err;
}
memset(pina, 0, inal);
ina.s_addr = htonl(0x7f000001UL);
#if OPENSSL_USE_IPV6
ina6.s6_addr[15] = 1;
#endif
addr1 = BIO_ADDR_new();
if (!TEST_ptr(addr1))
goto err;
addr2 = BIO_ADDR_new();
if (!TEST_ptr(addr2))
goto err;
addr3 = BIO_ADDR_new();
if (!TEST_ptr(addr3))
goto err;
addr4 = BIO_ADDR_new();
if (!TEST_ptr(addr4))
goto err;
addr5 = BIO_ADDR_new();
if (!TEST_ptr(addr5))
goto err;
addr6 = BIO_ADDR_new();
if (!TEST_ptr(addr6))
goto err;
if (!TEST_int_eq(BIO_ADDR_rawmake(addr1, af, pina, inal, 0), 1))
goto err;
if (!TEST_int_eq(BIO_ADDR_rawmake(addr2,