#ifndef _NET_ROUTING_RTSOCK_CONFIG_H_
#define _NET_ROUTING_RTSOCK_CONFIG_H_
#include "params.h"
struct rtsock_config_options {
int num_interfaces;
};
struct rtsock_test_config {
int ifindex;
char net4_str[INET_ADDRSTRLEN];
char addr4_str[INET_ADDRSTRLEN];
char net6_str[INET6_ADDRSTRLEN];
char addr6_str[INET6_ADDRSTRLEN];
struct sockaddr_in net4;
struct sockaddr_in mask4;
struct sockaddr_in addr4;
struct sockaddr_in6 net6;
struct sockaddr_in6 mask6;
struct sockaddr_in6 addr6;
int plen4;
int plen6;
char *remote_lladdr;
char *ifname;
char **ifnames;
bool autocreated_interface;
int rtsock_fd;
int num_interfaces;
};
struct rtsock_test_config *
config_setup(const atf_tc_t *tc, struct rtsock_config_options *co)
{
struct rtsock_config_options default_co;
struct rtsock_test_config *c;
char buf[64], *s;
const char *key;
int mask;
if (co == NULL) {
bzero(&default_co, sizeof(default_co));
co = &default_co;
co->num_interfaces = 1;
}
c = calloc(1, sizeof(struct rtsock_test_config));
c->rtsock_fd = -1;
key = atf_tc_get_config_var_wd(tc, "rtsock.v4prefix", "192.0.2.0/24");
strlcpy(buf, key, sizeof(buf));
if ((s = strchr(buf, '/')) == NULL)
return (NULL);
*s++ = '\0';
mask = strtol(s, NULL, 10);
if (mask < 0 || mask > 32)
return (NULL);
c->plen4 = mask;
inet_pton(AF_INET, buf, &c->net4.sin_addr);
c->net4.sin_len = sizeof(struct sockaddr_in);
c->net4.sin_family = AF_INET;
c->addr4.sin_len = sizeof(struct sockaddr_in);
c->addr4.sin_family = AF_INET;
sa_fill_mask4(&c->mask4, c->plen4);
c->addr4.sin_addr.s_addr = htonl(ntohl(c->net4.sin_addr.s_addr) + 1);
inet_ntop(AF_INET, &c->net4.sin_addr, c->net4_str, INET_ADDRSTRLEN);
inet_ntop(AF_INET, &c->addr4.sin_addr, c->addr4_str, INET_ADDRSTRLEN);
key = atf_tc_get_config_var_wd(tc, "rtsock.v6prefix", "2001:DB8::/32");
strlcpy(buf, key, sizeof(buf));
if ((s = strchr(buf, '/')) == NULL)
return (NULL);
*s++ = '\0';
mask = strtol(s, NULL, 10);
if (mask < 0 || mask > 128)
return (NULL);
c->plen6 = mask;
inet_pton(AF_INET6, buf, &c->net6.sin6_addr);
c->net6.sin6_len = sizeof(struct sockaddr_in6);
c->net6.sin6_family = AF_INET6;
c->addr6.sin6_len = sizeof(struct sockaddr_in6);
c->addr6.sin6_family = AF_INET6;
sa_fill_mask6(&c->mask6, c->plen6);
memcpy(&c->addr6.sin6_addr, &c->net6.sin6_addr, sizeof(struct in6_addr));
#define _s6_addr32 __u6_addr.__u6_addr32
c->addr6.sin6_addr._s6_addr32[3] = htonl(ntohl(c->net6.sin6_addr._s6_addr32[3]) + 1);
#undef _s6_addr32
inet_ntop(AF_INET6, &c->net6.sin6_addr, c->net6_str, INET6_ADDRSTRLEN);
inet_ntop(AF_INET6, &c->addr6.sin6_addr, c->addr6_str, INET6_ADDRSTRLEN);
ATF_CHECK_ERRNO(0, true);
if (co->num_interfaces > 0) {
kldload("if_epair");
ATF_REQUIRE_KERNEL_MODULE("if_epair");
errno = 0;
c->ifnames = calloc(co->num_interfaces, sizeof(char *));
for (int i = 0; i < co->num_interfaces; i++)
c->ifnames[i] = iface_create("epair");
c->ifname = c->ifnames[0];
c->ifindex = if_nametoindex(c->ifname);
ATF_REQUIRE_MSG(c->ifindex != 0, "interface %s not found",
c->ifname);
}
c->num_interfaces = co->num_interfaces;
c->remote_lladdr = strdup(atf_tc_get_config_var_wd(tc,
"rtsock.remote_lladdr", "00:00:5E:00:53:42"));
return (c);
}
void
config_generic_cleanup(const atf_tc_t *tc)
{
const char *srcdir = atf_tc_get_config_var(tc, "srcdir");
char cmd[512];
int ret;
snprintf(cmd, sizeof(cmd), "%s/generic_cleanup.sh", srcdir);
ret = system(cmd);
if (ret != 0)
RLOG("'%s' failed, error %d", cmd, ret);
}
void
config_describe_root_test(atf_tc_t *tc, char *test_descr)
{
atf_tc_set_md_var(tc, "descr", test_descr);
atf_tc_set_md_var(tc, "require.user", "root");
}
#endif