tests: adapt existing tests to new LWIP service

Change-Id: Id744e9d3fbe19733557011f8803593cf3768c35d
This commit is contained in:
David van Moolenbroek 2016-09-29 23:08:31 +00:00
parent bb9622b5ed
commit ad920fc485
6 changed files with 148 additions and 241 deletions

View File

@ -169,10 +169,15 @@ void test_getsockname(const struct socket_test_info *info)
{ {
int sd; int sd;
int rc; int rc;
int on;
struct sockaddr_storage sock_addr; struct sockaddr_storage sock_addr;
socklen_t sock_addr_len; socklen_t sock_addr_len;
SOCKET(sd, info->domain, info->type, 0); SOCKET(sd, info->domain, info->type, 0);
on = 1;
(void)setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
rc = bind(sd, info->serveraddr, info->serveraddrlen); rc = bind(sd, info->serveraddr, info->serveraddrlen);
if (rc == -1) { if (rc == -1) {
test_fail("bind() should have worked"); test_fail("bind() should have worked");
@ -201,6 +206,7 @@ void test_bind(const struct socket_test_info *info)
int sd; int sd;
int sd2; int sd2;
int rc; int rc;
int on;
debug("entering test_bind()"); debug("entering test_bind()");
info->callback_cleanup(); info->callback_cleanup();
@ -208,6 +214,10 @@ void test_bind(const struct socket_test_info *info)
debug("Test bind() success"); debug("Test bind() success");
SOCKET(sd, info->domain, info->type, 0); SOCKET(sd, info->domain, info->type, 0);
on = 1;
(void)setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
rc = bind(sd, info->serveraddr, info->serveraddrlen); rc = bind(sd, info->serveraddr, info->serveraddrlen);
if (rc == -1) { if (rc == -1) {
test_fail("bind() should have worked"); test_fail("bind() should have worked");
@ -231,15 +241,13 @@ void test_bind(const struct socket_test_info *info)
SOCKET(sd2, info->domain, info->type, 0); SOCKET(sd2, info->domain, info->type, 0);
errno = 0; errno = 0;
rc = bind(sd2, info->serveraddr, info->serveraddrlen); rc = bind(sd2, info->serveraddr, info->serveraddrlen);
if (!((rc == -1) && (errno == EADDRINUSE)) && if (!((rc == -1) && (errno == EADDRINUSE))) {
!info->bug_bind_in_use) {
test_fail("bind() should have failed with EADDRINUSE"); test_fail("bind() should have failed with EADDRINUSE");
} }
CLOSE(sd2); CLOSE(sd2);
CLOSE(sd); CLOSE(sd);
info->callback_cleanup(); info->callback_cleanup();
if (!info->bug_bind_null) {
debug("Test bind() with a NULL address"); debug("Test bind() with a NULL address");
SOCKET(sd, info->domain, info->type, 0); SOCKET(sd, info->domain, info->type, 0);
@ -250,7 +258,6 @@ void test_bind(const struct socket_test_info *info)
test_fail("bind() should have failed with EFAULT"); test_fail("bind() should have failed with EFAULT");
} }
CLOSE(sd); CLOSE(sd);
}
debug("leaving test_bind()"); debug("leaving test_bind()");
} }
@ -296,13 +303,11 @@ void test_shutdown(const struct socket_test_info *info)
/* test for each direction (read, write, read-write) */ /* test for each direction (read, write, read-write) */
for (i = 0; i < 3; i++) { for (i = 0; i < 3; i++) {
if (info->bug_shutdown_read && how[i] == SHUT_RD) continue;
debug("test shutdown() with an invalid descriptor"); debug("test shutdown() with an invalid descriptor");
errno = 0; errno = 0;
rc = shutdown(-1, how[i]); rc = shutdown(-1, how[i]);
if (!(rc == -1 && errno == EBADF) && !info->bug_shutdown) { if (!(rc == -1 && errno == EBADF)) {
test_fail("shutdown(-1, how[i]) should have failed"); test_fail("shutdown(-1, how[i]) should have failed");
} }
@ -310,7 +315,7 @@ void test_shutdown(const struct socket_test_info *info)
errno = 0; errno = 0;
rc = shutdown(0, how[i]); rc = shutdown(0, how[i]);
if (!(rc == -1 && errno == ENOTSOCK) && !info->bug_shutdown) { if (!(rc == -1 && errno == ENOTSOCK)) {
test_fail("shutdown() should have failed with " test_fail("shutdown() should have failed with "
"ENOTSOCK"); "ENOTSOCK");
} }
@ -320,9 +325,7 @@ void test_shutdown(const struct socket_test_info *info)
SOCKET(sd, info->domain, info->type, 0); SOCKET(sd, info->domain, info->type, 0);
errno = 0; errno = 0;
rc = shutdown(sd, how[i]); rc = shutdown(sd, how[i]);
if (rc != 0 && !(rc == -1 && errno == ENOTCONN) && if (rc != 0 && !(rc == -1 && errno == ENOTCONN)) {
!info->bug_shutdown_not_conn &&
!info->bug_shutdown) {
test_fail("shutdown() should have failed"); test_fail("shutdown() should have failed");
} }
CLOSE(sd); CLOSE(sd);
@ -331,9 +334,7 @@ void test_shutdown(const struct socket_test_info *info)
SOCKET(sd, info->domain, info->type, 0); SOCKET(sd, info->domain, info->type, 0);
errno = 0; errno = 0;
rc = shutdown(sd, -1); rc = shutdown(sd, -1);
if (!(rc == -1 && errno == EINVAL) && if (!(rc == -1 && errno == EINVAL)) {
!info->bug_shutdown_not_conn &&
!info->bug_shutdown) {
test_fail("shutdown(sd, -1) should have failed with EINVAL"); test_fail("shutdown(sd, -1) should have failed with EINVAL");
} }
CLOSE(sd); CLOSE(sd);
@ -344,7 +345,7 @@ void test_shutdown(const struct socket_test_info *info)
void test_close(const struct socket_test_info *info) void test_close(const struct socket_test_info *info)
{ {
int sd, sd2; int sd, sd2;
int rc, i; int rc, i, on;
debug("entering test_close()"); debug("entering test_close()");
@ -353,6 +354,10 @@ void test_close(const struct socket_test_info *info)
debug("Test close() success"); debug("Test close() success");
SOCKET(sd, info->domain, info->type, 0); SOCKET(sd, info->domain, info->type, 0);
on = 1;
(void)setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
rc = bind(sd, info->serveraddr, info->serveraddrlen); rc = bind(sd, info->serveraddr, info->serveraddrlen);
if (rc != 0) { if (rc != 0) {
test_fail("bind() should have worked"); test_fail("bind() should have worked");
@ -373,6 +378,10 @@ void test_close(const struct socket_test_info *info)
debug("dup()'ing a file descriptor and closing both should work"); debug("dup()'ing a file descriptor and closing both should work");
SOCKET(sd, info->domain, info->type, 0); SOCKET(sd, info->domain, info->type, 0);
on = 1;
(void)setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
rc = bind(sd, info->serveraddr, info->serveraddrlen); rc = bind(sd, info->serveraddr, info->serveraddrlen);
if (rc != 0) { if (rc != 0) {
test_fail("bind() should have worked"); test_fail("bind() should have worked");
@ -442,13 +451,9 @@ void test_sockopts(const struct socket_test_info *info)
option_len = sizeof(option_value); option_len = sizeof(option_value);
errno = 0; errno = 0;
rc = getsockopt(sd, SOL_SOCKET, SO_SNDBUF, &option_value, &option_len); rc = getsockopt(sd, SOL_SOCKET, SO_SNDBUF, &option_value, &option_len);
if (rc != 0 && !info->bug_sockopt_sndbuf) {
test_fail("getsockopt() should have worked");
}
if (info->expected_sndbuf >= 0 && if (info->expected_sndbuf >= 0 &&
option_value != info->expected_sndbuf && option_value != info->expected_sndbuf) {
!info->bug_sockopt_sndbuf) {
test_fail("SO_SNDBUF didn't seem to work."); test_fail("SO_SNDBUF didn't seem to work.");
} }
@ -463,13 +468,12 @@ void test_sockopts(const struct socket_test_info *info)
option_len = sizeof(option_value); option_len = sizeof(option_value);
errno = 0; errno = 0;
rc = getsockopt(sd, SOL_SOCKET, SO_RCVBUF, &option_value, &option_len); rc = getsockopt(sd, SOL_SOCKET, SO_RCVBUF, &option_value, &option_len);
if (rc != 0 && !info->bug_sockopt_rcvbuf) { if (rc != 0) {
test_fail("getsockopt() should have worked"); test_fail("getsockopt() should have worked");
} }
if (info->expected_rcvbuf >= 0 && if (info->expected_rcvbuf >= 0 &&
option_value != info->expected_rcvbuf && option_value != info->expected_rcvbuf) {
!info->bug_sockopt_rcvbuf) {
test_fail("SO_RCVBUF didn't seem to work."); test_fail("SO_RCVBUF didn't seem to work.");
} }
@ -525,7 +529,7 @@ void test_dup(const struct socket_test_info *info)
struct stat info2; struct stat info2;
int sd, sd2; int sd, sd2;
int rc; int rc;
int i; int i, on;
debug("entering test_dup()"); debug("entering test_dup()");
@ -534,6 +538,10 @@ void test_dup(const struct socket_test_info *info)
debug("Test dup()"); debug("Test dup()");
SOCKET(sd, info->domain, info->type, 0); SOCKET(sd, info->domain, info->type, 0);
on = 1;
(void)setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
rc = bind(sd, info->serveraddr, info->serveraddrlen); rc = bind(sd, info->serveraddr, info->serveraddrlen);
if (rc != 0) { if (rc != 0) {
test_fail("bind() should have worked"); test_fail("bind() should have worked");
@ -611,12 +619,16 @@ void test_dup2(const struct socket_test_info *info)
int sd; int sd;
int fd; int fd;
int rc; int rc;
int on;
debug("entering test_dup2()"); debug("entering test_dup2()");
info->callback_cleanup(); info->callback_cleanup();
SOCKET(sd, info->domain, info->type, 0); SOCKET(sd, info->domain, info->type, 0);
on = 1;
(void)setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
rc = bind(sd, info->serveraddr, info->serveraddrlen); rc = bind(sd, info->serveraddr, info->serveraddrlen);
if (rc != 0) { if (rc != 0) {
test_fail("bind() should have worked"); test_fail("bind() should have worked");
@ -671,6 +683,7 @@ static void test_xfer_server(const struct socket_test_info *info, pid_t pid)
int status; int status;
int rc; int rc;
int sd; int sd;
int on;
unsigned char buf[BUFSIZE]; unsigned char buf[BUFSIZE];
socklen_t client_addr_size; socklen_t client_addr_size;
int client_sd; int client_sd;
@ -687,6 +700,9 @@ static void test_xfer_server(const struct socket_test_info *info, pid_t pid)
SOCKET(sd, info->domain, info->type, 0); SOCKET(sd, info->domain, info->type, 0);
on = 1;
(void)setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
rc = bind(sd, info->serveraddr, info->serveraddrlen); rc = bind(sd, info->serveraddr, info->serveraddrlen);
if (rc == -1) { if (rc == -1) {
test_fail("bind() should have worked"); test_fail("bind() should have worked");
@ -1129,7 +1145,7 @@ static void test_simple_server(const struct socket_test_info *info, int type,
pid_t pid) pid_t pid)
{ {
char buf[BUFSIZE]; char buf[BUFSIZE];
int sd, rc, client_sd, status; int sd, rc, client_sd, status, on;
struct sockaddr_storage addr; struct sockaddr_storage addr;
socklen_t addr_len; socklen_t addr_len;
@ -1140,6 +1156,9 @@ static void test_simple_server(const struct socket_test_info *info, int type,
test_fail("socket"); test_fail("socket");
} }
on = 1;
(void)setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
assert(info->clientaddrlen <= sizeof(addr)); assert(info->clientaddrlen <= sizeof(addr));
memcpy(&addr, info->clientaddr, info->clientaddrlen); memcpy(&addr, info->clientaddr, info->clientaddrlen);
@ -1314,7 +1333,7 @@ static void test_abort_server(const struct socket_test_info *info,
pid_t pid, int abort_type) pid_t pid, int abort_type)
{ {
char buf[BUFSIZE]; char buf[BUFSIZE];
int sd, rc, client_sd, status; int sd, rc, client_sd, status, on;
struct sockaddr_storage addr; struct sockaddr_storage addr;
socklen_t addr_len; socklen_t addr_len;
@ -1325,6 +1344,9 @@ static void test_abort_server(const struct socket_test_info *info,
test_fail("socket"); test_fail("socket");
} }
on = 1;
(void)setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
assert(sizeof(addr) >= info->clientaddrlen); assert(sizeof(addr) >= info->clientaddrlen);
memcpy(&addr, info->clientaddr, info->clientaddrlen); memcpy(&addr, info->clientaddr, info->clientaddrlen);
@ -1588,13 +1610,16 @@ test_nonblock(const struct socket_test_info *info)
socklen_t len; socklen_t len;
int server_sd, client_sd; int server_sd, client_sd;
struct sockaddr_storage addr; struct sockaddr_storage addr;
int status; int status, on;
debug("entering test_nonblock()"); debug("entering test_nonblock()");
memset(buf, 0, sizeof(buf)); memset(buf, 0, sizeof(buf));
SOCKET(server_sd, info->domain, info->type, 0); SOCKET(server_sd, info->domain, info->type, 0);
on = 1;
(void)setsockopt(server_sd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
if (bind(server_sd, info->serveraddr, info->serveraddrlen) == -1) if (bind(server_sd, info->serveraddr, info->serveraddrlen) == -1)
test_fail("bind() should have worked"); test_fail("bind() should have worked");
@ -1724,11 +1749,14 @@ test_connect_nb(const struct socket_test_info *info)
socklen_t len; socklen_t len;
int server_sd, client_sd; int server_sd, client_sd;
struct sockaddr_storage addr; struct sockaddr_storage addr;
int status; int status, on;
debug("entering test_connect_nb()"); debug("entering test_connect_nb()");
SOCKET(server_sd, info->domain, info->type, 0); SOCKET(server_sd, info->domain, info->type, 0);
on = 1;
(void)setsockopt(server_sd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
if (bind(server_sd, info->serveraddr, info->serveraddrlen) == -1) if (bind(server_sd, info->serveraddr, info->serveraddrlen) == -1)
test_fail("bind() should have worked"); test_fail("bind() should have worked");
@ -1801,13 +1829,16 @@ test_intr(const struct socket_test_info *info)
socklen_t len; socklen_t len;
int server_sd, client_sd; int server_sd, client_sd;
struct sockaddr_storage addr; struct sockaddr_storage addr;
int r, status; int r, status, on;
debug("entering test_intr()"); debug("entering test_intr()");
memset(buf, 0, sizeof(buf)); memset(buf, 0, sizeof(buf));
SOCKET(server_sd, info->domain, info->type, 0); SOCKET(server_sd, info->domain, info->type, 0);
on = 1;
(void)setsockopt(server_sd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
if (bind(server_sd, info->serveraddr, info->serveraddrlen) == -1) if (bind(server_sd, info->serveraddr, info->serveraddrlen) == -1)
test_fail("bind() should have worked"); test_fail("bind() should have worked");
@ -1926,13 +1957,16 @@ test_intr(const struct socket_test_info *info)
void void
test_connect_close(const struct socket_test_info *info) test_connect_close(const struct socket_test_info *info)
{ {
int server_sd, client_sd; int server_sd, client_sd, sd, on;
struct sockaddr_storage addr; struct sockaddr_storage addr;
socklen_t len; socklen_t len;
debug("entering test_connect_close()"); debug("entering test_connect_close()");
SOCKET(server_sd, info->domain, info->type, 0); SOCKET(server_sd, info->domain, info->type, 0);
on = 1;
(void)setsockopt(server_sd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
if (bind(server_sd, info->serveraddr, info->serveraddrlen) == -1) if (bind(server_sd, info->serveraddr, info->serveraddrlen) == -1)
test_fail("bind() should have worked"); test_fail("bind() should have worked");
@ -1966,10 +2000,11 @@ test_connect_close(const struct socket_test_info *info)
len = sizeof(addr); len = sizeof(addr);
errno = 0; errno = 0;
if (accept(server_sd, (struct sockaddr *) &addr, &len) != -1) { if ((sd = accept(server_sd, (struct sockaddr *) &addr, &len)) != -1) {
if (!info->ignore_accept_delay) { if (!info->ignore_accept_delay) {
test_fail("accept() should have failed"); test_fail("accept() should have failed");
} }
close(sd);
} else if (errno != EAGAIN) { } else if (errno != EAGAIN) {
test_fail("accept() should have yielded EAGAIN"); test_fail("accept() should have yielded EAGAIN");
} }
@ -1981,18 +2016,23 @@ test_connect_close(const struct socket_test_info *info)
/* /*
* Verify that closing a listening socket will cause a blocking connect to fail * Verify that closing a listening socket will cause a blocking connect to fail
* with ECONNRESET, and that a subsequent write will yield EPIPE. * with ECONNRESET, and that a subsequent write will yield EPIPE. This test
* works only if the connect(2) does not succeed before accept(2) is called at
* all, which means it is limited to UDS with LOCAL_CONNWAIT right now.
*/ */
void void
test_listen_close(const struct socket_test_info *info) test_listen_close(const struct socket_test_info *info)
{ {
int server_sd, client_sd; int server_sd, client_sd;
int status; int status, on;
char byte; char byte;
debug("entering test_listen_close()"); debug("entering test_listen_close()");
SOCKET(server_sd, info->domain, info->type, 0); SOCKET(server_sd, info->domain, info->type, 0);
on = 1;
(void)setsockopt(server_sd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
if (bind(server_sd, info->serveraddr, info->serveraddrlen) == -1) if (bind(server_sd, info->serveraddr, info->serveraddrlen) == -1)
test_fail("bind() should have worked"); test_fail("bind() should have worked");
@ -2022,24 +2062,18 @@ test_listen_close(const struct socket_test_info *info)
test_fail("write() should have yielded ENOTCONN"); test_fail("write() should have yielded ENOTCONN");
if (connect(client_sd, info->clientaddr, info->clientaddrlen) != -1) { if (connect(client_sd, info->clientaddr, info->clientaddrlen) != -1) {
if (!info->bug_connect_after_close) {
test_fail("connect() should have failed"); test_fail("connect() should have failed");
}
} else if (errno != ECONNRESET) { } else if (errno != ECONNRESET) {
test_fail("connect() should have yielded ECONNRESET"); test_fail("connect() should have yielded ECONNRESET");
} }
/* /*
* The error we get on the next write() depends on whether the socket * The error we get on the next write() depends on whether the socket
* may be reused after a failed connect: for TCP/IP, it may not, so we * may be reused after a failed connect. For UDS, it may be, so we get
* get EPIPE; for UDS, it may be reused, so we get ENOTCONN. * ENOTCONN. Otherwise we would expect EPIPE.
*/ */
if (!info->bug_connect_after_close) { if (write(client_sd, &byte, 1) != -1 || errno != ENOTCONN)
if (write(client_sd, &byte, 1) != -1 || test_fail("write() should have yielded ENOTCONN");
(errno != EPIPE && errno != ENOTCONN))
test_fail("write() should have yielded "
"EPIPE/ENOTCONN");
}
close(client_sd); close(client_sd);
@ -2061,12 +2095,15 @@ void
test_listen_close_nb(const struct socket_test_info *info) test_listen_close_nb(const struct socket_test_info *info)
{ {
int server_sd, client_sd; int server_sd, client_sd;
int status; int status, on;
char byte; char byte;
debug("entering test_listen_close_nb()"); debug("entering test_listen_close_nb()");
SOCKET(server_sd, info->domain, info->type, 0); SOCKET(server_sd, info->domain, info->type, 0);
on = 1;
(void)setsockopt(server_sd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
if (bind(server_sd, info->serveraddr, info->serveraddrlen) == -1) if (bind(server_sd, info->serveraddr, info->serveraddrlen) == -1)
test_fail("bind() should have worked"); test_fail("bind() should have worked");

View File

@ -75,16 +75,6 @@ struct socket_test_info {
const int *types; const int *types;
size_t typecount; size_t typecount;
int buf_accept_intr; /* accept can return success when interrupted */
int bug_bind_in_use; /* bind does not return EADDRINUSE */
int bug_bind_null; /* bind segfaults with NULL pointer */
int bug_connect_after_close; /* connect succeeds after server closed */
int bug_select_nonblock; /* select unexpected results for nb sockets */
int bug_shutdown; /* shutdown not supported */
int bug_shutdown_not_conn; /* shutdown does not return ENOTCONN */
int bug_shutdown_read; /* shutdown does not support SHUT_RD */
int bug_sockopt_rcvbuf; /* get/setsockopt does not support SO_RCVBUF */
int bug_sockopt_sndbuf; /* get/setsockopt does not support SO_SNDBUF */
int ignore_accept_delay; /* success from accept after aborted connect */ int ignore_accept_delay; /* success from accept after aborted connect */
int ignore_connect_delay; /* nb connect not instant */ int ignore_connect_delay; /* nb connect not instant */
int ignore_connect_unaccepted; /* connect succeeds without accept */ int ignore_connect_unaccepted; /* connect succeeds without accept */

View File

@ -165,6 +165,17 @@ static void test_getaddrinfo(
ai_count_stream = 0; ai_count_stream = 0;
while (ai_cur) while (ai_cur)
{ {
/*
* TODO: this test was written for IPv4. For now, skip IPv6
* results altogether. Later, we should add additional code
* for IPv6. However, since this test now largely exercises
* NetBSD code, it is not as important as it once was.
*/
if (ai_cur->ai_family == AF_INET6) {
ai_cur = ai_cur->ai_next;
continue;
}
/* test result fields */ /* test result fields */
if (ai_cur->ai_family != AF_INET) if (ai_cur->ai_family != AF_INET)
test_getaddrinfo_err_nr(2, TEST_GETADDRINFO_ERR_PARAMS, test_getaddrinfo_err_nr(2, TEST_GETADDRINFO_ERR_PARAMS,
@ -316,8 +327,6 @@ static struct
{ "127.0.0.1", 0x7f000001, 1, 0, 0, 0 }, { "127.0.0.1", 0x7f000001, 1, 0, 0, 0 },
{ "localhost", 0x7f000001, 0, 1, 0, 0, }, { "localhost", 0x7f000001, 0, 1, 0, 0, },
{ "test48.minix3.org", 0x7f010203, 0, 1, 1, 0, }, { "test48.minix3.org", 0x7f010203, 0, 1, 1, 0, },
{ "", 0x00000000, 1, 0, 0, (1<<EAI_NONAME)|(1<<EAI_FAIL)|(1<<EAI_NODATA)},
{ "256.256.256.256",0x00000000, 1, 0, 0, (1<<EAI_NONAME)|(1<<EAI_FAIL)|(1<<EAI_NODATA)},
{ "minix3.example.com", 0x00000000, 0, 0, 1, (1<<EAI_NONAME)|(1<<EAI_FAIL)|(1<<EAI_NODATA)}}; { "minix3.example.com", 0x00000000, 0, 0, 1, (1<<EAI_NONAME)|(1<<EAI_FAIL)|(1<<EAI_NODATA)}};
static struct static struct

View File

@ -88,11 +88,13 @@ int main(int argc, char *argv[])
.types = &info.type, .types = &info.type,
.typecount = 1, .typecount = 1,
.bug_bind_in_use = 1, /*
.bug_bind_null = 1, * Maintainer's note: common-socket was adapted from test56 in
.bug_connect_after_close = 1, * a time that UDS's LOCAL_CONNWAIT was the default. Due to
.bug_shutdown_not_conn = 1, * this as well as inherent behavioral differences between TCP
.bug_shutdown_read = 1, * and UDS, these exceptions basically work around the fact
* that common-socket was not designed for its current task.
*/
.ignore_accept_delay = 1, .ignore_accept_delay = 1,
.ignore_connect_unaccepted = 1, .ignore_connect_unaccepted = 1,
.ignore_connect_delay = 1, .ignore_connect_delay = 1,
@ -130,7 +132,7 @@ int main(int argc, char *argv[])
test_connect_nb(&info); test_connect_nb(&info);
test_intr(&info); test_intr(&info);
test_connect_close(&info); test_connect_close(&info);
test_listen_close(&info); /* test_listen_close(&info); -- not suitable for TCP */
test_listen_close_nb(&info); test_listen_close_nb(&info);
quit(); quit();

View File

@ -78,8 +78,8 @@ int main(int argc, char *argv[])
.clientaddrsym = (struct sockaddr *) &clientaddr, .clientaddrsym = (struct sockaddr *) &clientaddr,
.clientaddrsymlen = sizeof(clientaddr), .clientaddrsymlen = sizeof(clientaddr),
.domain = PF_INET, .domain = PF_INET,
.expected_rcvbuf = -1, .expected_rcvbuf = 32768,
.expected_sndbuf = -1, .expected_sndbuf = 8192,
.serveraddr = (struct sockaddr *) &serveraddr, .serveraddr = (struct sockaddr *) &serveraddr,
.serveraddrlen = sizeof(serveraddr), .serveraddrlen = sizeof(serveraddr),
.serveraddr2 = (struct sockaddr *) &serveraddr2, .serveraddr2 = (struct sockaddr *) &serveraddr2,
@ -87,22 +87,6 @@ int main(int argc, char *argv[])
.type = SOCK_DGRAM, .type = SOCK_DGRAM,
.types = &info.type, .types = &info.type,
.typecount = 1, .typecount = 1,
.bug_bind_in_use = 1,
.bug_bind_null = 1,
.bug_connect_after_close = 1,
.bug_shutdown = 1, /* UDP only problem */
.bug_shutdown_not_conn = 1,
.bug_shutdown_read = 1,
.bug_sockopt_rcvbuf = 1, /* UDP only problem */
.bug_sockopt_sndbuf = 1, /* UDP only problem */
.ignore_accept_delay = 1,
.ignore_connect_unaccepted = 1,
.ignore_connect_delay = 1,
.ignore_select_delay = 1,
.ignore_send_waiting = 1,
.ignore_write_conn_reset = 1,
.callback_check_sockaddr = callback_check_sockaddr, .callback_check_sockaddr = callback_check_sockaddr,
.callback_cleanup = callback_cleanup, .callback_cleanup = callback_cleanup,
.callback_xfer_prepclient = NULL, .callback_xfer_prepclient = NULL,

View File

@ -38,11 +38,6 @@
#include <sys/time.h> #include <sys/time.h>
#include <sys/wait.h> #include <sys/wait.h>
#include <net/gen/ether.h>
#include <net/gen/eth_io.h>
#include <net/gen/in.h>
#include <net/gen/ip_io.h>
#include "common.h" #include "common.h"
int max_error = 100; int max_error = 100;
@ -124,16 +119,11 @@ static const size_t payloadsizes[] = {
65535 - sizeof(struct header_ip) - sizeof(struct header_udp), 65535 - sizeof(struct header_ip) - sizeof(struct header_udp),
}; };
#define ADDR_COUNT_MAX 10 /* In its current configuration, this test uses the loopback interface only. */
static size_t addr_count; static uint32_t addrsrc = INADDR_LOOPBACK; /* 127.0.0.1 (localhost) */
static uint32_t addrsrc = 0xc0000201; /* 192.0.2.1 (TEST-NET) */ static uint32_t addrdst = INADDR_LOOPBACK; /* 127.0.0.1 (localhost) */
static uint32_t addrdst = 0x7f000001; /* 127.0.0.1 (localhost) */ static uint32_t addrs[] = {
static uint32_t addrs[ADDR_COUNT_MAX] = { INADDR_LOOPBACK, /* 127.0.0.1 (localhost) */
0x00000000, /* 0.0.0.0 (INADDR_NONE) */
0x7f000001, /* 127.0.0.1 (localhost) */
0xc0000201, /* 192.0.2.1 (TEST-NET) */
0xffffffff, /* 255.255.255.255 (broadcast) */
/* local addresses will be added */
}; };
#define CLOSE(fd) do { assert(fd >= 0); if (close((fd)) != 0) efmt("close failed"); } while (0); #define CLOSE(fd) do { assert(fd >= 0); if (close((fd)) != 0) efmt("close failed"); } while (0);
@ -472,7 +462,7 @@ static pid_t server_start(int type, int port, enum server_action action) {
.sin_port = htons(port), .sin_port = htons(port),
.sin_addr = { htonl(INADDR_ANY) }, .sin_addr = { htonl(INADDR_ANY) },
}; };
int fd; int fd, on;
pid_t pid = -1; pid_t pid = -1;
dbgprintf("server_start port %d\n", port); dbgprintf("server_start port %d\n", port);
@ -484,6 +474,12 @@ static pid_t server_start(int type, int port, enum server_action action) {
goto cleanup; goto cleanup;
} }
on = 1;
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) != 0) {
efmt("cannot set SO_REUSEADDR option on socket");
goto cleanup;
}
/* bind socket */ /* bind socket */
if (bind(fd, (struct sockaddr *) &addr, sizeof(addr)) != 0) { if (bind(fd, (struct sockaddr *) &addr, sizeof(addr)) != 0) {
efmt("cannot bind socket"); efmt("cannot bind socket");
@ -524,7 +520,13 @@ cleanup:
} }
static ssize_t send_packet_raw(int fd, const void *buf, size_t size) { static ssize_t send_packet_raw(int fd, const void *buf, size_t size) {
return write(fd, buf, size); struct sockaddr_in sin;
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
return sendto(fd, buf, size, 0, (struct sockaddr *)&sin, sizeof(sin));
} }
enum settings_ip { enum settings_ip {
@ -604,7 +606,7 @@ static void send_packet_ip_base(
struct header_ip header = { struct header_ip header = {
.tos = tos, .tos = tos,
.id = htons(id), .id = htons(id),
.fl_fo = htons((fl << 13) | fo), .fl_fo = (fl << 13) | fo, /* no htons(), lwip swaps this */
.ttl = ttl, .ttl = ttl,
.prot = prot, .prot = prot,
.cs = 0, .cs = 0,
@ -652,7 +654,7 @@ static void send_packet_ip_base(
if (ipsettings & si_bad_len_small) len = ihl * 4 - 1; if (ipsettings & si_bad_len_small) len = ihl * 4 - 1;
if (ipsettings & si_bad_len_big) len += 1; if (ipsettings & si_bad_len_big) len += 1;
if (ipsettings & si_bad_len_huge) len = 0xffff; if (ipsettings & si_bad_len_huge) len = 0xffff;
header.len = htons(len); header.len = len; /* no htons(), lwip swaps this */
packetsize = ihl * 4 + payloadsize; packetsize = ihl * 4 + payloadsize;
if (packetsize > sizeof(packet)) { if (packetsize > sizeof(packet)) {
@ -973,8 +975,8 @@ static void send_packets_ip(int fd) {
/* send packets with various addresses and corruptions */ /* send packets with various addresses and corruptions */
params = paramsbase; params = paramsbase;
for (i = 0; i < addr_count; i++) { for (i = 0; i < __arraycount(addrs); i++) {
for (j = 0; j < addr_count; j++) { for (j = 0; j < __arraycount(addrs); j++) {
params.srcip = addrs[i]; params.srcip = addrs[i];
params.dstip = addrs[j]; params.dstip = addrs[j];
send_packets_ip_settings(&params); send_packets_ip_settings(&params);
@ -1050,8 +1052,8 @@ static void send_packets_udp(int fd) {
/* send packets with various addresses and ports */ /* send packets with various addresses and ports */
params = paramsbase; params = paramsbase;
for (i = 0; i < addr_count; i++) { for (i = 0; i < __arraycount(addrs); i++) {
for (j = 0; j < addr_count; j++) { for (j = 0; j < __arraycount(addrs); j++) {
for (k = 0; k < 5; k++) { for (k = 0; k < 5; k++) {
params.srcip = addrs[i]; params.srcip = addrs[i];
params.dstip = addrs[j]; params.dstip = addrs[j];
@ -1061,7 +1063,7 @@ static void send_packets_udp(int fd) {
} }
} }
params = paramsbase; params = paramsbase;
for (i = 0; i < addr_count; i++) { for (i = 0; i < __arraycount(addrs); i++) {
for (j = 0; j < 5; j++) { for (j = 0; j < 5; j++) {
for (k = 0; k < 5; k++) { for (k = 0; k < 5; k++) {
params.dstip = addrs[i]; params.dstip = addrs[i];
@ -1307,8 +1309,8 @@ static void send_packets_tcp(int fd) {
/* send packets with various addresses and ports */ /* send packets with various addresses and ports */
params = paramsbase; params = paramsbase;
for (i = 0; i < addr_count; i++) { for (i = 0; i < __arraycount(addrs); i++) {
for (j = 0; j < addr_count; j++) { for (j = 0; j < __arraycount(addrs); j++) {
for (k = 0; k < 7; k++) { for (k = 0; k < 7; k++) {
params.srcip = addrs[i]; params.srcip = addrs[i];
params.dstip = addrs[j]; params.dstip = addrs[j];
@ -1318,7 +1320,7 @@ static void send_packets_tcp(int fd) {
} }
} }
params = paramsbase; params = paramsbase;
for (i = 0; i < addr_count; i++) { for (i = 0; i < __arraycount(addrs); i++) {
for (j = 0; j < 7; j++) { for (j = 0; j < 7; j++) {
for (k = 0; k < 7; k++) { for (k = 0; k < 7; k++) {
params.dstip = addrs[i]; params.dstip = addrs[i];
@ -1477,65 +1479,14 @@ static void recv_packets_select(int fd) {
} }
static int open_raw_socket(int broadcast) { static int open_raw_socket(int broadcast) {
int fd; int fd, on;
struct nwio_ethopt opt = { };
struct nwio_ethstat stat = { };
fd = open("/dev/eth", O_RDWR); fd = socket(AF_INET, SOCK_RAW, IPPROTO_IP);
if (fd < 0) efmt("cannot open /dev/eth"); if (fd < 0) efmt("cannot create raw socket");
/* test NWIOGETHOPT */ on = 1;
if (ioctl(fd, NWIOGETHOPT, &opt) != 0) { if (setsockopt(fd, IPPROTO_IP, IP_HDRINCL, &on, sizeof(on)) != 0)
efmt("ioctl(NWIOGETHOPT) failed"); efmt("ioctl(IP_HDRINCL) failed");
}
/* test NWIOGETHSTAT */
if (ioctl(fd, NWIOGETHSTAT, &stat) != 0) {
efmt("ioctl(NWIOGETHSTAT) failed");
}
/* test invalid NWIOSETHOPT input */
opt.nweo_flags = NWEO_COPY << 16;
if (ioctl(fd, NWIOSETHOPT, &opt) != -1 && errno != EBADMODE) {
efmt("ioctl(NWIOSETHOPT) should have returned EBADMODE");
}
opt.nweo_flags = NWEO_EN_LOC | NWEO_DI_LOC;
if (ioctl(fd, NWIOSETHOPT, &opt) != -1 && errno != EBADMODE) {
efmt("ioctl(NWIOSETHOPT) should have returned EBADMODE");
}
/* test NWIOSETHOPT with defaults */
opt.nweo_flags = 0;
if (ioctl(fd, NWIOSETHOPT, &opt) != 0) {
efmt("ioctl(NWIOSETHOPT) failed");
}
/* test NWIOGETHSTAT right after reconfiguring */
opt.nweo_flags = NWEO_EN_BROAD | NWEO_EN_MULTI | NWEO_EN_PROMISC;
if (ioctl(fd, NWIOSETHOPT, &opt) != 0) {
efmt("ioctl(NWIOSETHOPT) failed");
}
opt.nweo_flags = NWEO_DI_BROAD | NWEO_DI_MULTI | NWEO_DI_PROMISC;
if (ioctl(fd, NWIOSETHOPT, &opt) != 0) {
efmt("ioctl(NWIOSETHOPT) failed");
}
if (ioctl(fd, NWIOGETHSTAT, &stat) != 0) {
efmt("ioctl(NWIOGETHSTAT) failed");
}
/* configure /dev/eth the way we want it for the rest of the test */
opt.nweo_flags = NWEO_COPY | NWEO_EN_LOC | NWEO_EN_BROAD |
NWEO_EN_MULTI | NWEO_EN_PROMISC |
(broadcast ? NWEO_REMANY : NWEO_REMSPEC) |
NWEO_TYPESPEC | NWEO_RWDATONLY;
opt.nweo_type = htons(ETH_IP_PROTO);
memcpy(&opt.nweo_rem, &stat.nwes_addr, sizeof(opt.nweo_rem));
if (ioctl(fd, NWIOSETHOPT, &opt) != 0) {
efmt("ioctl(NWIOSETHOPT) failed");
}
return fd; return fd;
} }
@ -1563,71 +1514,6 @@ static void do_packets(void) {
CLOSE(fd); CLOSE(fd);
} }
static void add_local_ip(uint32_t ip) {
static int first = 1;
int i;
for (i = 0; i < addr_count; i++) {
if (addrs[i] == ip) return;
}
dbgprintf("found local IP: %d.%d.%d.%d\n",
(uint8_t) (ip >> 24), (uint8_t) (ip >> 16),
(uint8_t) (ip >> 8), (uint8_t) (ip >> 0));
if (addr_count < ADDR_COUNT_MAX) {
addrs[addr_count++] = ip;
}
if (first) {
addrdst = ip;
first = 0;
}
}
static void get_local_ip(void) {
char device[16];
int flags;
int ifno;
nwio_ipconf_t ipconf;
int ip_fd;
/* inspired by ifconfig */
for (ifno = 0; ifno < 32; ifno++) {
snprintf(device, sizeof(device), "/dev/ip%d", ifno);
ip_fd = open(device, O_RDWR);
if (ip_fd < 0) {
if (errno != ENOENT && errno != ENXIO) {
efmt("cannot open %s", device);
}
continue;
}
flags = fcntl(ip_fd, F_GETFL);
if (flags == -1) {
efmt("cannot get flags for %s", device);
goto next;
}
if (fcntl(ip_fd, F_SETFL, flags | O_NONBLOCK) == -1) {
efmt("cannot set flags for %s", device);
goto next;
}
if (ioctl(ip_fd, NWIOGIPCONF, &ipconf) == -1) {
if (errno != EAGAIN) {
efmt("cannot get IP address for %s", device);
}
goto next;
}
if (fcntl(ip_fd, F_SETFL, flags) == -1) {
efmt("cannot restore flags for %s", device);
}
add_local_ip(ntohl(ipconf.nwic_ipaddr));
next:
CLOSE(ip_fd);
}
}
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
int i; int i;
@ -1644,8 +1530,7 @@ int main(int argc, char **argv)
pids[5] = server_start(SOCK_DGRAM, PORT_BASE + 1, sa_selectr); pids[5] = server_start(SOCK_DGRAM, PORT_BASE + 1, sa_selectr);
/* send some bogus packets */ /* send some bogus packets */
get_local_ip(); do_packets();
if (get_setting_use_network()) do_packets();
/* stop the servers */ /* stop the servers */
for (i = 0; i < PORT_COUNT; i++) server_stop(pids[i]); for (i = 0; i < PORT_COUNT; i++) server_stop(pids[i]);