cap_net tests: Skip tests if there is no connectivity
When testing cap_connect() and name/addr lookup functions, skip tests if we fail and the error is not ENOTCAPABLE. This makes the tests amenable to running in CI without Internet connectivity. Reviewed by: oshogbo MFC after: 2 weeks Differential Revision: https://reviews.freebsd.org/D39242
This commit is contained in:
parent
014e03411f
commit
7ee4066db1
@ -68,21 +68,24 @@ test_getnameinfo_v4(cap_channel_t *chan, int family, const char *ip)
|
|||||||
struct sockaddr_in ipaddr;
|
struct sockaddr_in ipaddr;
|
||||||
char capfn[MAXHOSTNAMELEN];
|
char capfn[MAXHOSTNAMELEN];
|
||||||
char origfn[MAXHOSTNAMELEN];
|
char origfn[MAXHOSTNAMELEN];
|
||||||
int ret;
|
int capret, sysret;
|
||||||
|
|
||||||
memset(&ipaddr, 0, sizeof(ipaddr));
|
memset(&ipaddr, 0, sizeof(ipaddr));
|
||||||
ipaddr.sin_family = family;
|
ipaddr.sin_family = family;
|
||||||
inet_pton(family, ip, &ipaddr.sin_addr);
|
inet_pton(family, ip, &ipaddr.sin_addr);
|
||||||
|
|
||||||
ret = cap_getnameinfo(chan, (struct sockaddr *)&ipaddr, sizeof(ipaddr),
|
capret = cap_getnameinfo(chan, (struct sockaddr *)&ipaddr, sizeof(ipaddr),
|
||||||
capfn, sizeof(capfn), NULL, 0, NI_NAMEREQD);
|
capfn, sizeof(capfn), NULL, 0, NI_NAMEREQD);
|
||||||
if (ret != 0) {
|
if (capret != 0 && capret == ENOTCAPABLE)
|
||||||
return (ret);
|
return (ENOTCAPABLE);
|
||||||
}
|
|
||||||
|
|
||||||
ret = getnameinfo((struct sockaddr *)&ipaddr, sizeof(ipaddr), origfn,
|
sysret = getnameinfo((struct sockaddr *)&ipaddr, sizeof(ipaddr), origfn,
|
||||||
sizeof(origfn), NULL, 0, NI_NAMEREQD);
|
sizeof(origfn), NULL, 0, NI_NAMEREQD);
|
||||||
ATF_REQUIRE(ret == 0);
|
if (sysret != 0) {
|
||||||
|
atf_tc_skip("getnameinfo(%s) failed: %s",
|
||||||
|
ip, gai_strerror(sysret));
|
||||||
|
}
|
||||||
|
ATF_REQUIRE(capret == 0);
|
||||||
ATF_REQUIRE(strcmp(origfn, capfn) == 0);
|
ATF_REQUIRE(strcmp(origfn, capfn) == 0);
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
@ -94,21 +97,24 @@ test_getnameinfo_v6(cap_channel_t *chan, const char *ip)
|
|||||||
struct sockaddr_in6 ipaddr;
|
struct sockaddr_in6 ipaddr;
|
||||||
char capfn[MAXHOSTNAMELEN];
|
char capfn[MAXHOSTNAMELEN];
|
||||||
char origfn[MAXHOSTNAMELEN];
|
char origfn[MAXHOSTNAMELEN];
|
||||||
int ret;
|
int capret, sysret;
|
||||||
|
|
||||||
memset(&ipaddr, 0, sizeof(ipaddr));
|
memset(&ipaddr, 0, sizeof(ipaddr));
|
||||||
ipaddr.sin6_family = AF_INET6;
|
ipaddr.sin6_family = AF_INET6;
|
||||||
inet_pton(AF_INET6, ip, &ipaddr.sin6_addr);
|
inet_pton(AF_INET6, ip, &ipaddr.sin6_addr);
|
||||||
|
|
||||||
ret = cap_getnameinfo(chan, (struct sockaddr *)&ipaddr, sizeof(ipaddr),
|
capret = cap_getnameinfo(chan, (struct sockaddr *)&ipaddr, sizeof(ipaddr),
|
||||||
capfn, sizeof(capfn), NULL, 0, NI_NAMEREQD);
|
capfn, sizeof(capfn), NULL, 0, NI_NAMEREQD);
|
||||||
if (ret != 0) {
|
if (capret != 0 && capret == ENOTCAPABLE)
|
||||||
return (ret);
|
return (ENOTCAPABLE);
|
||||||
}
|
|
||||||
|
|
||||||
ret = getnameinfo((struct sockaddr *)&ipaddr, sizeof(ipaddr), origfn,
|
sysret = getnameinfo((struct sockaddr *)&ipaddr, sizeof(ipaddr), origfn,
|
||||||
sizeof(origfn), NULL, 0, NI_NAMEREQD);
|
sizeof(origfn), NULL, 0, NI_NAMEREQD);
|
||||||
ATF_REQUIRE(ret == 0);
|
if (sysret != 0) {
|
||||||
|
atf_tc_skip("getnameinfo(%s) failed: %s",
|
||||||
|
ip, gai_strerror(sysret));
|
||||||
|
}
|
||||||
|
ATF_REQUIRE(capret == 0);
|
||||||
ATF_REQUIRE(strcmp(origfn, capfn) == 0);
|
ATF_REQUIRE(strcmp(origfn, capfn) == 0);
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
@ -135,13 +141,14 @@ test_gethostbyaddr_v4(cap_channel_t *chan, int family, const char *ip)
|
|||||||
inet_pton(AF_INET, ip, &ipaddr);
|
inet_pton(AF_INET, ip, &ipaddr);
|
||||||
|
|
||||||
caphp = cap_gethostbyaddr(chan, &ipaddr, sizeof(ipaddr), family);
|
caphp = cap_gethostbyaddr(chan, &ipaddr, sizeof(ipaddr), family);
|
||||||
if (caphp == NULL) {
|
if (caphp == NULL && h_errno == ENOTCAPABLE)
|
||||||
return (h_errno);
|
return (ENOTCAPABLE);
|
||||||
}
|
|
||||||
|
|
||||||
orighp = gethostbyaddr(&ipaddr, sizeof(ipaddr), family);
|
orighp = gethostbyaddr(&ipaddr, sizeof(ipaddr), family);
|
||||||
ATF_REQUIRE(orighp != NULL);
|
if (orighp == NULL)
|
||||||
ATF_REQUIRE(strcmp(caphp->h_name, caphp->h_name) == 0);
|
atf_tc_skip("gethostbyaddr(%s) failed", ip);
|
||||||
|
ATF_REQUIRE(caphp != NULL);
|
||||||
|
ATF_REQUIRE(strcmp(orighp->h_name, caphp->h_name) == 0);
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
@ -156,12 +163,14 @@ test_gethostbyaddr_v6(cap_channel_t *chan, const char *ip)
|
|||||||
inet_pton(AF_INET6, ip, &ipaddr);
|
inet_pton(AF_INET6, ip, &ipaddr);
|
||||||
|
|
||||||
caphp = cap_gethostbyaddr(chan, &ipaddr, sizeof(ipaddr), AF_INET6);
|
caphp = cap_gethostbyaddr(chan, &ipaddr, sizeof(ipaddr), AF_INET6);
|
||||||
if (caphp == NULL)
|
if (caphp == NULL && h_errno == ENOTCAPABLE)
|
||||||
return (h_errno);
|
return (ENOTCAPABLE);
|
||||||
|
|
||||||
orighp = gethostbyaddr(&ipaddr, sizeof(ipaddr), AF_INET6);
|
orighp = gethostbyaddr(&ipaddr, sizeof(ipaddr), AF_INET6);
|
||||||
ATF_REQUIRE(orighp != NULL);
|
if (orighp == NULL)
|
||||||
ATF_REQUIRE(strcmp(caphp->h_name, caphp->h_name) == 0);
|
atf_tc_skip("gethostbyaddr(%s) failed", ip);
|
||||||
|
ATF_REQUIRE(caphp != NULL);
|
||||||
|
ATF_REQUIRE(strcmp(orighp->h_name, caphp->h_name) == 0);
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
@ -183,19 +192,21 @@ test_getaddrinfo(cap_channel_t *chan, int family, const char *domain,
|
|||||||
{
|
{
|
||||||
struct addrinfo hints, *capres, *origres, *res0, *res1;
|
struct addrinfo hints, *capres, *origres, *res0, *res1;
|
||||||
bool found;
|
bool found;
|
||||||
int ret;
|
int capret, sysret;
|
||||||
|
|
||||||
memset(&hints, 0, sizeof(hints));
|
memset(&hints, 0, sizeof(hints));
|
||||||
hints.ai_family = family;
|
hints.ai_family = family;
|
||||||
hints.ai_socktype = SOCK_STREAM;
|
hints.ai_socktype = SOCK_STREAM;
|
||||||
|
|
||||||
ret = cap_getaddrinfo(chan, domain, servname, &hints, &capres);
|
capret = cap_getaddrinfo(chan, domain, servname, &hints, &capres);
|
||||||
if (ret != 0) {
|
if (capret != 0 && capret == ENOTCAPABLE)
|
||||||
return (ret);
|
return (capret);
|
||||||
}
|
|
||||||
|
|
||||||
ret = getaddrinfo(domain, servname, &hints, &origres);
|
sysret = getaddrinfo(domain, servname, &hints, &origres);
|
||||||
ATF_REQUIRE(ret == 0);
|
if (sysret != 0)
|
||||||
|
atf_tc_skip("getaddrinfo(%s) failed: %s",
|
||||||
|
domain, gai_strerror(sysret));
|
||||||
|
ATF_REQUIRE(capret == 0);
|
||||||
|
|
||||||
for (res0 = capres; res0 != NULL; res0 = res0->ai_next) {
|
for (res0 = capres; res0 != NULL; res0 = res0->ai_next) {
|
||||||
found = false;
|
found = false;
|
||||||
@ -221,14 +232,15 @@ test_gethostbyname(cap_channel_t *chan, int family, const char *domain)
|
|||||||
struct hostent *caphp, *orighp;
|
struct hostent *caphp, *orighp;
|
||||||
|
|
||||||
caphp = cap_gethostbyname2(chan, domain, family);
|
caphp = cap_gethostbyname2(chan, domain, family);
|
||||||
if (caphp == NULL) {
|
if (caphp == NULL && h_errno == ENOTCAPABLE)
|
||||||
return (h_errno);
|
return (h_errno);
|
||||||
}
|
|
||||||
|
|
||||||
orighp = gethostbyname2(domain, family);
|
orighp = gethostbyname2(domain, family);
|
||||||
ATF_REQUIRE(orighp != NULL);
|
if (orighp == NULL)
|
||||||
ATF_REQUIRE(strcmp(caphp->h_name, orighp->h_name) == 0);
|
atf_tc_skip("gethostbyname2(%s) failed", domain);
|
||||||
|
|
||||||
|
ATF_REQUIRE(caphp != NULL);
|
||||||
|
ATF_REQUIRE(strcmp(caphp->h_name, orighp->h_name) == 0);
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -259,7 +271,7 @@ test_connect(cap_channel_t *chan, const char *ip, unsigned short port)
|
|||||||
int capfd, ret, serrno;
|
int capfd, ret, serrno;
|
||||||
|
|
||||||
capfd = socket(AF_INET, SOCK_STREAM, 0);
|
capfd = socket(AF_INET, SOCK_STREAM, 0);
|
||||||
ATF_REQUIRE(capfd > 0);
|
ATF_REQUIRE(capfd >= 0);
|
||||||
|
|
||||||
memset(&ipv4, 0, sizeof(ipv4));
|
memset(&ipv4, 0, sizeof(ipv4));
|
||||||
ipv4.sin_family = AF_INET;
|
ipv4.sin_family = AF_INET;
|
||||||
@ -268,7 +280,31 @@ test_connect(cap_channel_t *chan, const char *ip, unsigned short port)
|
|||||||
|
|
||||||
ret = cap_connect(chan, capfd, (struct sockaddr *)&ipv4, sizeof(ipv4));
|
ret = cap_connect(chan, capfd, (struct sockaddr *)&ipv4, sizeof(ipv4));
|
||||||
serrno = errno;
|
serrno = errno;
|
||||||
close(capfd);
|
ATF_REQUIRE(close(capfd) == 0);
|
||||||
|
|
||||||
|
if (ret < 0 && serrno != ENOTCAPABLE) {
|
||||||
|
int sd;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the connection failed, it might be because we can't reach
|
||||||
|
* the destination host. To check, try a plain connect() and
|
||||||
|
* see if it fails with the same error.
|
||||||
|
*/
|
||||||
|
sd = socket(AF_INET, SOCK_STREAM, 0);
|
||||||
|
ATF_REQUIRE(sd >= 0);
|
||||||
|
|
||||||
|
memset(&ipv4, 0, sizeof(ipv4));
|
||||||
|
ipv4.sin_family = AF_INET;
|
||||||
|
ipv4.sin_port = htons(port);
|
||||||
|
inet_pton(AF_INET, ip, &ipv4.sin_addr);
|
||||||
|
ret = connect(sd, (struct sockaddr *)&ipv4, sizeof(ipv4));
|
||||||
|
ATF_REQUIRE(ret < 0);
|
||||||
|
ATF_REQUIRE_MSG(errno == serrno, "errno %d != serrno %d",
|
||||||
|
errno, serrno);
|
||||||
|
ATF_REQUIRE(close(sd) == 0);
|
||||||
|
atf_tc_skip("connect(%s:%d) failed: %s",
|
||||||
|
ip, port, strerror(serrno));
|
||||||
|
}
|
||||||
|
|
||||||
return (ret < 0 ? serrno : 0);
|
return (ret < 0 ? serrno : 0);
|
||||||
}
|
}
|
||||||
@ -1192,6 +1228,7 @@ ATF_TC_BODY(capnet__limits_connecttodns, tc)
|
|||||||
cap_net_limit_t *limit;
|
cap_net_limit_t *limit;
|
||||||
struct addrinfo hints, *capres, *res;
|
struct addrinfo hints, *capres, *res;
|
||||||
int family[] = { AF_INET };
|
int family[] = { AF_INET };
|
||||||
|
int error;
|
||||||
|
|
||||||
capnet = create_network_service();
|
capnet = create_network_service();
|
||||||
|
|
||||||
@ -1220,9 +1257,12 @@ ATF_TC_BODY(capnet__limits_connecttodns, tc)
|
|||||||
s = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
|
s = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
|
||||||
ATF_REQUIRE(s >= 0);
|
ATF_REQUIRE(s >= 0);
|
||||||
|
|
||||||
ATF_REQUIRE(cap_connect(capnet, s, res->ai_addr,
|
error = cap_connect(capnet, s, res->ai_addr,
|
||||||
res->ai_addrlen) == 0);
|
res->ai_addrlen);
|
||||||
close(s);
|
if (error != 0 && errno != ENOTCAPABLE)
|
||||||
|
atf_tc_skip("unable to connect: %s", strerror(errno));
|
||||||
|
ATF_REQUIRE(error == 0);
|
||||||
|
ATF_REQUIRE(close(s) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
freeaddrinfo(capres);
|
freeaddrinfo(capres);
|
||||||
@ -1239,7 +1279,7 @@ ATF_TC_BODY(capnet__limits_deprecated_connecttodns, tc)
|
|||||||
struct in_addr ipaddr;
|
struct in_addr ipaddr;
|
||||||
struct sockaddr_in connaddr;
|
struct sockaddr_in connaddr;
|
||||||
int family[] = { AF_INET };
|
int family[] = { AF_INET };
|
||||||
int i;
|
int error, i;
|
||||||
|
|
||||||
capnet = create_network_service();
|
capnet = create_network_service();
|
||||||
|
|
||||||
@ -1271,9 +1311,12 @@ ATF_TC_BODY(capnet__limits_deprecated_connecttodns, tc)
|
|||||||
(char *)caphp->h_addr_list[i], caphp->h_length);
|
(char *)caphp->h_addr_list[i], caphp->h_length);
|
||||||
connaddr.sin_port = htons(80);
|
connaddr.sin_port = htons(80);
|
||||||
|
|
||||||
ATF_REQUIRE(cap_connect(capnet, s, (struct sockaddr *)&connaddr,
|
error = cap_connect(capnet, s, (struct sockaddr *)&connaddr,
|
||||||
sizeof(connaddr)) == 0);
|
sizeof(connaddr));
|
||||||
close(s);
|
if (error != 0 && errno != ENOTCAPABLE)
|
||||||
|
atf_tc_skip("unable to connect: %s", strerror(errno));
|
||||||
|
ATF_REQUIRE(error == 0);
|
||||||
|
ATF_REQUIRE(close(s) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
cap_close(capnet);
|
cap_close(capnet);
|
||||||
|
Loading…
Reference in New Issue
Block a user