Add regression test for UDP broadcast

This commit is contained in:
jiangjianfeng 2025-11-11 03:17:05 +00:00 committed by Ruihan Li
parent 3208fcc101
commit 66b3dcc388
2 changed files with 165 additions and 0 deletions

View File

@ -0,0 +1,164 @@
// SPDX-License-Identifier: MPL-2.0
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "../test.h"
#define SENDER_BIND_ADDR "127.0.0.1"
#define SENDER_PORT 12345
#define BROADCAST_ADDR "127.255.255.255"
#define RECEIVE_PORT 12346
#define MESSAGE "Hello from broadcast"
#define MESSAGE_LEN sizeof(MESSAGE)
int sender;
int receiver;
char buf[128] = { 0 };
struct sockaddr_in broadcast_addr;
struct sockaddr_in received_addr;
socklen_t addr_len = sizeof(struct sockaddr_in);
int broadcast_opt;
socklen_t broadcast_opt_len = sizeof(broadcast_opt);
FN_SETUP(create_and_bind)
{
// Initialize the broadcast address
CHECK(inet_aton(BROADCAST_ADDR, &broadcast_addr.sin_addr));
broadcast_addr.sin_port = htons(RECEIVE_PORT);
broadcast_addr.sin_family = AF_INET;
// Bind sender to SENDER_BIND_ADDR:SENDER_PORT
struct sockaddr_in sk_addr;
sk_addr.sin_family = AF_INET;
CHECK(inet_aton(SENDER_BIND_ADDR, &sk_addr.sin_addr));
sk_addr.sin_port = htons(SENDER_PORT);
sender = CHECK(socket(AF_INET, SOCK_DGRAM, 0));
CHECK(bind(sender, (struct sockaddr *)&sk_addr, addr_len));
// Bind receiver to BROADCAST_ADDR:RECEIVE_PORT
receiver = CHECK(socket(AF_INET, SOCK_DGRAM, 0));
// FIXME: Asterinas cannot support binding to broadcast addresses now.
// So all below code related to receiver is commented out.
// CHECK(bind(receiver, (struct sockaddr *)&broadcast_addr, addr_len));
}
END_SETUP()
FN_TEST(enable_broadcast)
{
TEST_RES(getsockopt(sender, SOL_SOCKET, SO_BROADCAST, &broadcast_opt,
&broadcast_opt_len),
broadcast_opt == 0 && broadcast_opt_len == 4);
TEST_RES(getsockopt(receiver, SOL_SOCKET, SO_BROADCAST, &broadcast_opt,
&broadcast_opt_len),
broadcast_opt == 0 && broadcast_opt_len == 4);
broadcast_opt = 100;
TEST_SUCC(setsockopt(sender, SOL_SOCKET, SO_BROADCAST, &broadcast_opt,
broadcast_opt_len));
broadcast_opt = -1;
TEST_SUCC(setsockopt(receiver, SOL_SOCKET, SO_BROADCAST, &broadcast_opt,
broadcast_opt_len));
TEST_RES(getsockopt(sender, SOL_SOCKET, SO_BROADCAST, &broadcast_opt,
&broadcast_opt_len),
broadcast_opt == 1 && broadcast_opt_len == 4);
TEST_RES(getsockopt(receiver, SOL_SOCKET, SO_BROADCAST, &broadcast_opt,
&broadcast_opt_len),
broadcast_opt == 1 && broadcast_opt_len == 4);
}
END_TEST()
// Both sender and receiver have SO_BROADCAST enabled.
FN_TEST(basic_broadcast)
{
TEST_SUCC(sendto(sender, MESSAGE, MESSAGE_LEN, 0,
(struct sockaddr *)&broadcast_addr, addr_len));
// TEST_SUCC(recvfrom(receiver, buf, sizeof(buf), 0,
// (struct sockaddr *)&received_addr, &addr_len));
}
END_TEST()
// Sender attempts to send broadcast without SO_BROADCAST enabled.
FN_TEST(disable_sender_broadcast)
{
broadcast_opt = 0;
TEST_SUCC(setsockopt(sender, SOL_SOCKET, SO_BROADCAST, &broadcast_opt,
broadcast_opt_len));
TEST_ERRNO(sendto(sender, MESSAGE, MESSAGE_LEN, 0,
(struct sockaddr *)&broadcast_addr, addr_len),
EACCES);
TEST_ERRNO(connect(sender, (struct sockaddr *)&broadcast_addr,
addr_len),
EACCES);
TEST_ERRNO(send(sender, MESSAGE, MESSAGE_LEN, 0), EDESTADDRREQ);
}
END_TEST()
// Sender enables SO_BROADCAST, receiver disables SO_BROADCAST.
FN_TEST(disable_receiver_broadcast)
{
broadcast_opt = 1;
TEST_SUCC(setsockopt(sender, SOL_SOCKET, SO_BROADCAST, &broadcast_opt,
broadcast_opt_len));
broadcast_opt = 0;
TEST_SUCC(setsockopt(receiver, SOL_SOCKET, SO_BROADCAST, &broadcast_opt,
broadcast_opt_len));
TEST_SUCC(sendto(sender, MESSAGE, MESSAGE_LEN, 0,
(struct sockaddr *)&broadcast_addr, addr_len));
// TEST_SUCC(recvfrom(receiver, buf, sizeof(buf), 0,
// (struct sockaddr *)&received_addr, &addr_len));
}
END_TEST()
// Connect sender to broadcast address, then send.
// Then disable SO_BROADCAST on sender and try to send again.
FN_TEST(connect_then_disable_broadcast)
{
TEST_SUCC(
connect(sender, (struct sockaddr *)&broadcast_addr, addr_len));
TEST_SUCC(send(sender, MESSAGE, MESSAGE_LEN, 0));
// TEST_SUCC(recvfrom(receiver, buf, sizeof(buf), 0,
// (struct sockaddr *)&received_addr, &addr_len));
broadcast_opt = 0;
TEST_SUCC(setsockopt(sender, SOL_SOCKET, SO_BROADCAST, &broadcast_opt,
broadcast_opt_len));
TEST_SUCC(send(sender, MESSAGE, MESSAGE_LEN, 0));
// TEST_SUCC(recvfrom(receiver, buf, sizeof(buf), 0,
// (struct sockaddr *)&received_addr, &addr_len));
TEST_ERRNO(sendto(sender, MESSAGE, MESSAGE_LEN, 0,
(struct sockaddr *)&broadcast_addr, addr_len),
EACCES);
TEST_ERRNO(connect(sender, (struct sockaddr *)&broadcast_addr,
addr_len),
EACCES);
// FIXME: Asterinas cannot pass the following case.
// The problem may be that we should invalidate the connected state
// once the above connect fails.
// TEST_ERRNO(send(sender, MESSAGE, MESSAGE_LEN, 0), EACCES);
}
END_TEST()
FN_SETUP(cleanup)
{
CHECK(close(sender));
CHECK(close(receiver));
}
END_SETUP()

View File

@ -33,6 +33,7 @@ sleep 0.2
./tcp_err
./tcp_poll
./tcp_reuseaddr
./udp_broadcast
./udp_err
./unix_stream_err
./unix_seqpacket_err