mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-09 13:26:48 +00:00
Add netlink regression test and gVisor test
This commit is contained in:
parent
7d24e63216
commit
5e9f537222
@ -70,6 +70,9 @@ $(INITRAMFS)/lib/x86_64-linux-gnu: | $(VDSO_LIB)
|
|||||||
@cp -L /lib/x86_64-linux-gnu/libevent-2.1.so.7 $@
|
@cp -L /lib/x86_64-linux-gnu/libevent-2.1.so.7 $@
|
||||||
@# required for VDSO
|
@# required for VDSO
|
||||||
@cp -L $(VDSO_LIB) $@
|
@cp -L $(VDSO_LIB) $@
|
||||||
|
@# required for netlink test
|
||||||
|
@cp -L /lib/x86_64-linux-gnu/libnl-3.so.200 $@
|
||||||
|
@cp -L /lib/x86_64-linux-gnu/libnl-route-3.so.200 $@
|
||||||
|
|
||||||
$(VDSO_LIB): | $(VDSO_DIR) $(BINARY_CACHE_DIR)/vdso64.so
|
$(VDSO_LIB): | $(VDSO_DIR) $(BINARY_CACHE_DIR)/vdso64.so
|
||||||
@# TODO: use a custom compiled vdso.so file in the future.
|
@# TODO: use a custom compiled vdso.so file in the future.
|
||||||
|
@ -2,4 +2,4 @@
|
|||||||
|
|
||||||
include ../test_common.mk
|
include ../test_common.mk
|
||||||
|
|
||||||
EXTRA_C_FLAGS :=
|
EXTRA_C_FLAGS := -I/usr/include/libnl3 -lnl-3 -lnl-route-3
|
||||||
|
227
test/apps/network/netlink_route.c
Normal file
227
test/apps/network/netlink_route.c
Normal file
@ -0,0 +1,227 @@
|
|||||||
|
// SPDX-License-Identifier: MPL-2.0
|
||||||
|
|
||||||
|
#include <netlink/netlink.h>
|
||||||
|
#include <netlink/route/link.h>
|
||||||
|
#include <netlink/route/addr.h>
|
||||||
|
#include <net/if.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "test.h"
|
||||||
|
|
||||||
|
#define ETHER_NAME "eth0"
|
||||||
|
#define LOOPBACK_NAME "lo"
|
||||||
|
|
||||||
|
#define SUCC(expr) ((expr), 0)
|
||||||
|
|
||||||
|
int find_lo_and_eth0_by_libc(struct if_nameindex *if_ni)
|
||||||
|
{
|
||||||
|
int found_links = 0;
|
||||||
|
|
||||||
|
for (struct if_nameindex *i = if_ni;
|
||||||
|
!(i->if_index == 0 && i->if_name == NULL); i++) {
|
||||||
|
if (strcmp(i->if_name, LOOPBACK_NAME) == 0) {
|
||||||
|
found_links++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcmp(i->if_name, ETHER_NAME) == 0) {
|
||||||
|
found_links++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return found_links;
|
||||||
|
}
|
||||||
|
|
||||||
|
FN_TEST(if_nameindex)
|
||||||
|
{
|
||||||
|
struct if_nameindex *if_ni;
|
||||||
|
|
||||||
|
CHECK_WITH(SUCC(if_ni = if_nameindex()), if_ni != NULL);
|
||||||
|
|
||||||
|
TEST_RES(find_lo_and_eth0_by_libc(if_ni), _ret == 2);
|
||||||
|
|
||||||
|
if_freenameindex(if_ni);
|
||||||
|
}
|
||||||
|
END_TEST()
|
||||||
|
|
||||||
|
void find_lo_and_eth0_by_libnl(struct nl_object *obj, void *arg)
|
||||||
|
{
|
||||||
|
int *found_links = (int *)arg;
|
||||||
|
struct rtnl_link *link = (struct rtnl_link *)obj;
|
||||||
|
|
||||||
|
if (strcmp(rtnl_link_get_name(link), LOOPBACK_NAME) == 0) {
|
||||||
|
*found_links += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcmp(rtnl_link_get_name(link), ETHER_NAME) == 0) {
|
||||||
|
*found_links += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FN_TEST(get_link_by_libnl)
|
||||||
|
{
|
||||||
|
struct nl_sock *sock;
|
||||||
|
struct nl_cache *link_cache;
|
||||||
|
|
||||||
|
// 1. Create netlink socket and connect
|
||||||
|
sock = nl_socket_alloc();
|
||||||
|
TEST_RES(nl_connect(sock, NETLINK_ROUTE), _ret >= 0);
|
||||||
|
|
||||||
|
// 2. Allocate and retrieve link cache
|
||||||
|
TEST_RES(rtnl_link_alloc_cache(sock, AF_UNSPEC, &link_cache),
|
||||||
|
_ret >= 0);
|
||||||
|
|
||||||
|
// 3. Iterate over all links to find lo and eth0
|
||||||
|
int found_links = 0;
|
||||||
|
TEST_RES(SUCC(nl_cache_foreach(link_cache, find_lo_and_eth0_by_libnl,
|
||||||
|
&found_links)),
|
||||||
|
found_links == 2);
|
||||||
|
|
||||||
|
// 4. Cleanup
|
||||||
|
nl_cache_free(link_cache);
|
||||||
|
nl_close(sock);
|
||||||
|
nl_socket_free(sock);
|
||||||
|
}
|
||||||
|
END_TEST()
|
||||||
|
|
||||||
|
void find_loopback_address(struct nl_object *obj, void *arg)
|
||||||
|
{
|
||||||
|
int *found_loopback = (int *)arg;
|
||||||
|
struct rtnl_addr *addr = (struct rtnl_addr *)obj;
|
||||||
|
struct nl_addr *local;
|
||||||
|
char buf[INET_ADDRSTRLEN];
|
||||||
|
|
||||||
|
int family = rtnl_addr_get_family(addr);
|
||||||
|
if (family != AF_INET) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
local = rtnl_addr_get_local(addr);
|
||||||
|
if (local) {
|
||||||
|
nl_addr2str(local, buf, sizeof(buf));
|
||||||
|
if (strcmp(buf, "127.0.0.1/8") == 0) {
|
||||||
|
*found_loopback = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FN_TEST(get_loopback_address)
|
||||||
|
{
|
||||||
|
struct nl_sock *sock;
|
||||||
|
struct nl_cache *addr_cache;
|
||||||
|
|
||||||
|
// 1. Create netlink socket and connect
|
||||||
|
sock = nl_socket_alloc();
|
||||||
|
TEST_RES(nl_connect(sock, NETLINK_ROUTE), _ret >= 0);
|
||||||
|
|
||||||
|
// 2. Allocate and retrieve address cache
|
||||||
|
TEST_RES(rtnl_addr_alloc_cache(sock, &addr_cache), _ret >= 0);
|
||||||
|
|
||||||
|
// 3. Iterate over all addresses to find loopback address
|
||||||
|
int found_loopback = 0;
|
||||||
|
TEST_RES(SUCC(nl_cache_foreach(addr_cache, find_loopback_address,
|
||||||
|
&found_loopback)),
|
||||||
|
found_loopback == 1);
|
||||||
|
|
||||||
|
// 4. Cleanup
|
||||||
|
nl_cache_free(addr_cache);
|
||||||
|
nl_close(sock);
|
||||||
|
nl_socket_free(sock);
|
||||||
|
}
|
||||||
|
END_TEST()
|
||||||
|
|
||||||
|
int find_new_addr_until_done(char *buffer, size_t len, int *found_new_addr)
|
||||||
|
{
|
||||||
|
struct nlmsghdr *nlh = (struct nlmsghdr *)buffer;
|
||||||
|
|
||||||
|
for (; NLMSG_OK(nlh, len); nlh = NLMSG_NEXT(nlh, len)) {
|
||||||
|
if (nlh->nlmsg_type == NLMSG_DONE) {
|
||||||
|
return *found_new_addr ? 1 : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nlh->nlmsg_type == RTM_NEWADDR) {
|
||||||
|
*found_new_addr += 1;
|
||||||
|
} else {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
FN_TEST(get_addr_error)
|
||||||
|
{
|
||||||
|
#define BUFFER_SIZE 8192
|
||||||
|
|
||||||
|
struct nl_req {
|
||||||
|
struct nlmsghdr hdr;
|
||||||
|
struct ifaddrmsg ifa;
|
||||||
|
};
|
||||||
|
|
||||||
|
int sock_fd;
|
||||||
|
struct sockaddr_nl sa;
|
||||||
|
char buffer[BUFFER_SIZE];
|
||||||
|
|
||||||
|
sock_fd = TEST_SUCC(socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE));
|
||||||
|
|
||||||
|
memset(&sa, 0, sizeof(sa));
|
||||||
|
sa.nl_family = AF_NETLINK;
|
||||||
|
|
||||||
|
TEST_SUCC(bind(sock_fd, (struct sockaddr *)&sa, sizeof(sa)));
|
||||||
|
|
||||||
|
// 1. Without NLM_F_DUMP flag
|
||||||
|
struct nl_req req;
|
||||||
|
memset(&req, 0, sizeof(req));
|
||||||
|
req.hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
|
||||||
|
req.hdr.nlmsg_type = RTM_GETADDR;
|
||||||
|
req.hdr.nlmsg_flags = NLM_F_REQUEST;
|
||||||
|
req.hdr.nlmsg_seq = 1;
|
||||||
|
req.ifa.ifa_family = AF_UNSPEC;
|
||||||
|
|
||||||
|
struct iovec iov = { &req, req.hdr.nlmsg_len };
|
||||||
|
struct msghdr msg = { &sa, sizeof(sa), &iov, 1, NULL, 0, 0 };
|
||||||
|
|
||||||
|
TEST_SUCC(sendmsg(sock_fd, &msg, 0));
|
||||||
|
TEST_RES(recv(sock_fd, buffer, BUFFER_SIZE, 0),
|
||||||
|
((struct nlmsghdr *)buffer)->nlmsg_type == NLMSG_ERROR &&
|
||||||
|
((struct nlmsgerr *)NLMSG_DATA(buffer))->error ==
|
||||||
|
-EOPNOTSUPP);
|
||||||
|
|
||||||
|
// 2. Invalid required index
|
||||||
|
req.hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP | NLM_F_ACK;
|
||||||
|
req.ifa.ifa_index = 9999;
|
||||||
|
TEST_SUCC(sendmsg(sock_fd, &msg, 0));
|
||||||
|
|
||||||
|
int found_new_addr = 0;
|
||||||
|
while (1) {
|
||||||
|
size_t recv_len =
|
||||||
|
TEST_SUCC(recv(sock_fd, buffer, BUFFER_SIZE, 0));
|
||||||
|
|
||||||
|
int found_done = TEST_SUCC(find_new_addr_until_done(
|
||||||
|
buffer, recv_len, &found_new_addr));
|
||||||
|
|
||||||
|
if (found_done != 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. Invalid required family
|
||||||
|
req.ifa.ifa_family = 255;
|
||||||
|
req.ifa.ifa_index = 0;
|
||||||
|
TEST_SUCC(sendmsg(sock_fd, &msg, 0));
|
||||||
|
|
||||||
|
found_new_addr = 0;
|
||||||
|
while (1) {
|
||||||
|
size_t recv_len =
|
||||||
|
TEST_SUCC(recv(sock_fd, buffer, BUFFER_SIZE, 0));
|
||||||
|
|
||||||
|
int found_done = TEST_SUCC(find_new_addr_until_done(
|
||||||
|
buffer, recv_len, &found_new_addr));
|
||||||
|
|
||||||
|
if (found_done != 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
END_TEST()
|
@ -22,7 +22,7 @@ $(OBJ_OUTPUT_DIR) $(DEP_OUTPUT_DIR):
|
|||||||
@mkdir -p $@
|
@mkdir -p $@
|
||||||
|
|
||||||
$(OBJ_OUTPUT_DIR)/%: %.c | $(OBJ_OUTPUT_DIR) $(DEP_OUTPUT_DIR)
|
$(OBJ_OUTPUT_DIR)/%: %.c | $(OBJ_OUTPUT_DIR) $(DEP_OUTPUT_DIR)
|
||||||
@$(CC) $(C_FLAGS) $(EXTRA_C_FLAGS) $< -o $@ \
|
@$(CC) $(C_FLAGS) $< -o $@ $(EXTRA_C_FLAGS) \
|
||||||
-MMD -MF $(DEP_OUTPUT_DIR)/$*.d
|
-MMD -MF $(DEP_OUTPUT_DIR)/$*.d
|
||||||
@echo "CC <= $@"
|
@echo "CC <= $@"
|
||||||
|
|
||||||
|
@ -46,6 +46,7 @@ TESTS ?= \
|
|||||||
sigaction_test \
|
sigaction_test \
|
||||||
sigaltstack_test \
|
sigaltstack_test \
|
||||||
signalfd_test \
|
signalfd_test \
|
||||||
|
socket_netlink_route_test \
|
||||||
stat_test \
|
stat_test \
|
||||||
stat_times_test \
|
stat_times_test \
|
||||||
statfs_test \
|
statfs_test \
|
||||||
|
12
test/syscall_test/blocklists/socket_netlink_route_test
Normal file
12
test/syscall_test/blocklists/socket_netlink_route_test
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
NetlinkRouteTest.MsgHdrMsgUnsuppType
|
||||||
|
NetlinkRouteTest.MsgHdrMsgTrunc
|
||||||
|
NetlinkRouteTest.MsgTruncMsgHdrMsgTrunc
|
||||||
|
NetlinkRouteTest.ControlMessageIgnored
|
||||||
|
NetlinkRouteTest.AddAddr
|
||||||
|
NetlinkRouteTest.GetRouteDump
|
||||||
|
NetlinkRouteTest.GetRouteRequest
|
||||||
|
NetlinkRouteTest.RecvmsgTrunc
|
||||||
|
NetlinkRouteTest.RecvmsgTruncPeek
|
||||||
|
NetlinkRouteTest.NoPasscredNoCreds
|
||||||
|
NetlinkRouteTest.PasscredCreds
|
||||||
|
NetlinkRouteTest/SockOptTest.GetSockOpt/*
|
Loading…
x
Reference in New Issue
Block a user