#include "rtsock_common.h"
#include "rtsock_config.h"
static void
jump_vnet(struct rtsock_test_config *c, const atf_tc_t *tc)
{
char vnet_name[512];
snprintf(vnet_name, sizeof(vnet_name), "vt-%s", atf_tc_get_ident(tc));
RLOG("jumping to %s", vnet_name);
vnet_switch_one(vnet_name, c->ifname);
c->ifindex = if_nametoindex(c->ifname);
}
static inline struct rtsock_test_config *
presetup_ipv6(const atf_tc_t *tc)
{
struct rtsock_test_config *c;
int ret;
c = config_setup(tc, NULL);
jump_vnet(c, tc);
ret = iface_turn_up(c->ifname);
ATF_REQUIRE_MSG(ret == 0, "Unable to turn up %s", c->ifname);
ret = iface_enable_ipv6(c->ifname);
ATF_REQUIRE_MSG(ret == 0, "Unable to enable IPv6 on %s", c->ifname);
c->rtsock_fd = rtsock_setup_socket();
return (c);
}
static inline struct rtsock_test_config *
presetup_ipv4(const atf_tc_t *tc)
{
struct rtsock_test_config *c;
int ret;
c = config_setup(tc, NULL);
jump_vnet(c, tc);
ret = iface_setup_addr(c->ifname, c->addr4_str, c->plen4);
ATF_REQUIRE_MSG(ret == 0, "ifconfig failed");
c->rtsock_fd = rtsock_setup_socket();
return (c);
}
static void
prepare_route_message(struct rt_msghdr *rtm, int cmd, struct sockaddr *dst,
struct sockaddr *gw)
{
rtsock_prepare_route_message(rtm, cmd, dst, NULL, gw);
rtm->rtm_flags |= (RTF_HOST | RTF_STATIC | RTF_LLDATA);
}
#define DECLARE_TEST_VARS \
char buffer[2048], msg[512]; \
ssize_t len; \
int ret; \
struct rtsock_test_config *c; \
struct rt_msghdr *rtm = (struct rt_msghdr *)buffer; \
struct sockaddr *sa; \
\
#define DECLARE_CLEANUP_VARS \
struct rtsock_test_config *c = config_setup(tc); \
\
#define DESCRIBE_ROOT_TEST(_msg) config_describe_root_test(tc, _msg)
#define CLEANUP_AFTER_TEST config_generic_cleanup(tc)
#define RTM_DECLARE_ROOT_TEST(_name, _descr) \
ATF_TC_WITH_CLEANUP(_name); \
ATF_TC_HEAD(_name, tc) \
{ \
DESCRIBE_ROOT_TEST(_descr); \
} \
ATF_TC_CLEANUP(_name, tc) \
{ \
CLEANUP_AFTER_TEST; \
}
RTM_DECLARE_ROOT_TEST(rtm_add_v6_ll_lle_success, "Tests addition of link-local IPv6 ND entry");
ATF_TC_BODY(rtm_add_v6_ll_lle_success, tc)
{
DECLARE_TEST_VARS;
c = presetup_ipv6(tc);
char str_buf[128];
struct sockaddr_in6 sin6;
char *v6addr = "fe80::4242:4242";
snprintf(str_buf, sizeof(str_buf), "%s%%%s", v6addr, c->ifname);
sa_convert_str_to_sa(str_buf, (struct sockaddr *)&sin6);
struct sockaddr_dl ether;
snprintf(str_buf, sizeof(str_buf), "%s%%%s", c->remote_lladdr, c->ifname);
sa_convert_str_to_sa(str_buf, (struct sockaddr *)ðer);
prepare_route_message(rtm, RTM_ADD, (struct sockaddr *)&sin6, (struct sockaddr *)ðer);
rtsock_send_rtm(c->rtsock_fd, rtm);
rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq);
sa = rtsock_find_rtm_sa(rtm, RTA_DST);
ret = sa_equal_msg(sa, (struct sockaddr *)&sin6, msg, sizeof(msg));
RTSOCK_ATF_REQUIRE_MSG(rtm, ret != 0, "DST sa diff: %s", msg);
sa = rtsock_find_rtm_sa(rtm, RTA_GATEWAY);
int sa_flags = SA_F_IGNORE_IFNAME | SA_F_IGNORE_IFTYPE | SA_F_IGNORE_MEMCMP;
ret = sa_equal_msg_flags(sa, (struct sockaddr *)ðer, msg, sizeof(msg), sa_flags);
RTSOCK_ATF_REQUIRE_MSG(rtm, ret != 0, "GATEWAY sa diff: %s", msg);
#if 0
struct sockaddr_dl *sdl = (struct sockaddr_dl *)sa;
RTSOCK_ATF_REQUIRE_MSG(rtm, sdl->sdl_type > 0, "sdl_type not set");
#endif
}
RTM_DECLARE_ROOT_TEST(rtm_add_v6_gu_lle_success, "Tests addition of global IPv6 ND entry");
ATF_TC_BODY(rtm_add_v6_gu_lle_success, tc)
{
DECLARE_TEST_VARS;
c = presetup_ipv6(tc);
char str_buf[128];
struct sockaddr_in6 sin6;
sin6 = c->net6;
#define _s6_addr32 __u6_addr.__u6_addr32
sin6.sin6_addr._s6_addr32[3] = htonl(0x42424242);
#undef _s6_addr32
struct sockaddr_dl ether;
snprintf(str_buf, sizeof(str_buf), "%s%%%s", c->remote_lladdr, c->ifname);
sa_convert_str_to_sa(str_buf, (struct sockaddr *)ðer);
prepare_route_message(rtm, RTM_ADD, (struct sockaddr *)&sin6, (struct sockaddr *)ðer);
rtsock_send_rtm(c->rtsock_fd, rtm);
rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq);
sa = rtsock_find_rtm_sa(rtm, RTA_DST);
ret = sa_equal_msg(sa, (struct sockaddr *)&sin6, msg, sizeof(msg));
RTSOCK_ATF_REQUIRE_MSG(rtm, ret != 0, "DST sa diff: %s", msg);
sa = rtsock_find_rtm_sa(rtm, RTA_GATEWAY);
int sa_flags = SA_F_IGNORE_IFNAME | SA_F_IGNORE_IFTYPE | SA_F_IGNORE_MEMCMP;
ret = sa_equal_msg_flags(sa, (struct sockaddr *)ðer, msg, sizeof(msg), sa_flags);
RTSOCK_ATF_REQUIRE_MSG(rtm, ret != 0, "GATEWAY sa diff: %s", msg);
#if 0
struct sockaddr_dl *sdl = (struct sockaddr_dl *)sa;
RTSOCK_ATF_REQUIRE_MSG(rtm, sdl->sdl_type > 0, "sdl_type not set");
#endif
}
RTM_DECLARE_ROOT_TEST(rtm_add_v4_gu_lle_success, "Tests addition of IPv4 ARP entry");
ATF_TC_BODY(rtm_add_v4_gu_lle_success, tc)
{
DECLARE_TEST_VARS;
c = presetup_ipv4(tc);
char str_buf[128];
struct sockaddr_in sin;
sin = c->addr4;
sin.sin_addr.s_addr = htonl(ntohl(sin.sin_addr.s_addr) + 1);
struct sockaddr_dl ether;
snprintf(str_buf, sizeof(str_buf), "%s%%%s", c->remote_lladdr, c->ifname);
sa_convert_str_to_sa(str_buf, (struct sockaddr *)ðer);
prepare_route_message(rtm, RTM_ADD, (struct sockaddr *)&sin, (struct sockaddr *)ðer);
len = rtsock_send_rtm(c->rtsock_fd, rtm);
rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq);
sa = rtsock_find_rtm_sa(rtm, RTA_DST);
ret = sa_equal_msg(sa, (struct sockaddr *)&sin, msg, sizeof(msg));
RTSOCK_ATF_REQUIRE_MSG(rtm, ret != 0, "DST sa diff: %s", msg);
sa = rtsock_find_rtm_sa(rtm, RTA_GATEWAY);
int sa_flags = SA_F_IGNORE_IFNAME | SA_F_IGNORE_IFTYPE | SA_F_IGNORE_MEMCMP;
ret = sa_equal_msg_flags(sa, (struct sockaddr *)ðer, msg, sizeof(msg), sa_flags);
RTSOCK_ATF_REQUIRE_MSG(rtm, ret != 0, "GATEWAY sa diff: %s", msg);
}
RTM_DECLARE_ROOT_TEST(rtm_del_v6_ll_lle_success, "Tests removal of link-local IPv6 ND entry");
ATF_TC_BODY(rtm_del_v6_ll_lle_success, tc)
{
DECLARE_TEST_VARS;
c = presetup_ipv6(tc);
char str_buf[128];
struct sockaddr_in6 sin6;
char *v6addr = "fe80::4242:4242";
snprintf(str_buf, sizeof(str_buf), "%s%%%s", v6addr, c->ifname);
sa_convert_str_to_sa(str_buf, (struct sockaddr *)&sin6);
struct sockaddr_dl ether;
snprintf(str_buf, sizeof(str_buf), "%s%%%s", c->remote_lladdr, c->ifname);
sa_convert_str_to_sa(str_buf, (struct sockaddr *)ðer);
prepare_route_message(rtm, RTM_ADD, (struct sockaddr *)&sin6, (struct sockaddr *)ðer);
rtsock_send_rtm(c->rtsock_fd, rtm);
prepare_route_message(rtm, RTM_DELETE, (struct sockaddr *)&sin6, (struct sockaddr *)ðer);
rtsock_send_rtm(c->rtsock_fd, rtm);
rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq);
RTSOCK_ATF_REQUIRE_MSG(rtm, rtm->rtm_type == RTM_DELETE, "rtm_type is not delete");
sa = rtsock_find_rtm_sa(rtm, RTA_DST);
ret = sa_equal_msg(sa, (struct sockaddr *)&sin6, msg, sizeof(msg));
RTSOCK_ATF_REQUIRE_MSG(rtm, ret != 0, "DST sa diff: %s", msg);
sa = rtsock_find_rtm_sa(rtm, RTA_GATEWAY);
int sa_flags = SA_F_IGNORE_IFNAME | SA_F_IGNORE_IFTYPE | SA_F_IGNORE_MEMCMP;
ret = sa_equal_msg_flags(sa, (struct sockaddr *)ðer, msg, sizeof(msg), sa_flags);
RTSOCK_ATF_REQUIRE_MSG(rtm, ret != 0, "GATEWAY sa diff: %s", msg);
}
RTM_DECLARE_ROOT_TEST(rtm_del_v6_gu_lle_success, "Tests removal of global IPv6 ND entry");
ATF_TC_BODY(rtm_del_v6_gu_lle_success, tc)
{
DECLARE_TEST_VARS;
c = presetup_ipv6(tc);
char str_buf[128];
struct sockaddr_in6 sin6;
sin6 = c->net6;
#define _s6_addr32 __u6_addr.__u6_addr32
sin6.sin6_addr._s6_addr32[3] = htonl(0x42424242);
#undef _s6_addr32
struct sockaddr_dl ether;
snprintf(str_buf, sizeof(str_buf), "%s%%%s", c->remote_lladdr, c->ifname);
sa_convert_str_to_sa(str_buf, (struct sockaddr *)ðer);
prepare_route_message(rtm, RTM_ADD, (struct sockaddr *)&sin6, (struct sockaddr *)ðer);
len = rtsock_send_rtm(c->rtsock_fd, rtm);
prepare_route_message(rtm, RTM_DELETE, (struct sockaddr *)&sin6, (struct sockaddr *)ðer);
rtsock_send_rtm(c->rtsock_fd, rtm);
rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq);
RTSOCK_ATF_REQUIRE_MSG(rtm, rtm->rtm_type == RTM_DELETE, "rtm_type is not delete");
sa = rtsock_find_rtm_sa(rtm, RTA_DST);
ret = sa_equal_msg(sa, (struct sockaddr *)&sin6, msg, sizeof(msg));
RTSOCK_ATF_REQUIRE_MSG(rtm, ret != 0, "DST sa diff: %s", msg);
sa = rtsock_find_rtm_sa(rtm, RTA_GATEWAY);
int sa_flags = SA_F_IGNORE_IFNAME | SA_F_IGNORE_IFTYPE | SA_F_IGNORE_MEMCMP;
ret = sa_equal_msg_flags(sa, (struct sockaddr *)ðer, msg, sizeof(msg), sa_flags);
RTSOCK_ATF_REQUIRE_MSG(rtm, ret != 0, "GATEWAY sa diff: %s", msg);
}
RTM_DECLARE_ROOT_TEST(rtm_del_v4_gu_lle_success, "Tests removal of IPv4 ARP entry");
ATF_TC_BODY(rtm_del_v4_gu_lle_success, tc)
{
DECLARE_TEST_VARS;
c = presetup_ipv4(tc);
char str_buf[128];
struct sockaddr_in sin;
sin = c->addr4;
sin.sin_addr.s_addr = htonl(ntohl(sin.sin_addr.s_addr) + 1);
struct sockaddr_dl ether;
snprintf(str_buf, sizeof(str_buf), "%s%%%s", c->remote_lladdr, c->ifname);
sa_convert_str_to_sa(str_buf, (struct sockaddr *)ðer);
prepare_route_message(rtm, RTM_ADD, (struct sockaddr *)&sin, (struct sockaddr *)ðer);
rtsock_send_rtm(c->rtsock_fd, rtm);
prepare_route_message(rtm, RTM_DELETE, (struct sockaddr *)&sin, (struct sockaddr *)ðer);
rtsock_send_rtm(c->rtsock_fd, rtm);
rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq);
RTSOCK_ATF_REQUIRE_MSG(rtm, rtm->rtm_type == RTM_DELETE, "rtm_type is not delete");
sa = rtsock_find_rtm_sa(rtm, RTA_DST);
ret = sa_equal_msg(sa, (struct sockaddr *)&sin, msg, sizeof(msg));
RTSOCK_ATF_REQUIRE_MSG(rtm, ret != 0, "DST sa diff: %s", msg);
sa = rtsock_find_rtm_sa(rtm, RTA_GATEWAY);
int sa_flags = SA_F_IGNORE_IFNAME | SA_F_IGNORE_IFTYPE | SA_F_IGNORE_MEMCMP;
ret = sa_equal_msg_flags(sa, (struct sockaddr *)ðer, msg, sizeof(msg), sa_flags);
RTSOCK_ATF_REQUIRE_MSG(rtm, ret != 0, "GATEWAY sa diff: %s", msg);
}
ATF_TP_ADD_TCS(tp)
{
ATF_TP_ADD_TC(tp, rtm_add_v6_ll_lle_success);
ATF_TP_ADD_TC(tp, rtm_add_v6_gu_lle_success);
ATF_TP_ADD_TC(tp, rtm_add_v4_gu_lle_success);
ATF_TP_ADD_TC(tp, rtm_del_v6_ll_lle_success);
ATF_TP_ADD_TC(tp, rtm_del_v6_gu_lle_success);
ATF_TP_ADD_TC(tp, rtm_del_v4_gu_lle_success);
return (atf_no_error());
}