diff options
-rw-r--r-- | ChangeLog | 6 | ||||
-rw-r--r-- | support/tst-support-namespace.c | 84 |
2 files changed, 88 insertions, 2 deletions
diff --git a/ChangeLog b/ChangeLog index 7f67b658f3..42ffe74254 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2017-07-05 Florian Weimer <fweimer@redhat.com> + + Add subtest to check isolation of multiple loopback addresses. + * support/tst-support-namespace.c (test_localhost_bind): New function. + (do_test): Call it. + 2017-07-04 Szabolcs Nagy <szabolcs.nagy@arm.com> * libio/libio.h (_IO_FLAGS2_NEED_LOCK, _IO_need_lock): Define. diff --git a/support/tst-support-namespace.c b/support/tst-support-namespace.c index a50b074f5e..dbe7cc07c8 100644 --- a/support/tst-support-namespace.c +++ b/support/tst-support-namespace.c @@ -16,18 +16,98 @@ License along with the GNU C Library; if not, see <http://www.gnu.org/licenses/>. */ +#include <errno.h> +#include <netdb.h> #include <stdio.h> +#include <support/check.h> #include <support/namespace.h> +#include <support/xsocket.h> +#include <support/xunistd.h> + +/* Check that the loopback interface provides multiple addresses which + can be used to run independent servers. */ +static void +test_localhost_bind (void) +{ + printf ("info: testing loopback interface with multiple addresses\n"); + + /* Create the two server addresses. */ + static const struct addrinfo hints = + { + .ai_family = AF_INET, + .ai_socktype = SOCK_DGRAM, + .ai_protocol = IPPROTO_UDP, + }; + struct addrinfo *ai[3]; + TEST_VERIFY_EXIT (getaddrinfo ("127.0.0.1", "53", &hints, ai + 0) == 0); + TEST_VERIFY_EXIT (getaddrinfo ("127.0.0.2", "53", &hints, ai + 1) == 0); + TEST_VERIFY_EXIT (getaddrinfo ("127.0.0.3", "53", &hints, ai + 2) == 0); + + /* Create the server scokets and bind them to these addresses. */ + int sockets[3]; + for (int i = 0; i < 3; ++i) + { + sockets[i] = xsocket + (ai[i]->ai_family, ai[i]->ai_socktype, ai[i]->ai_protocol); + xbind (sockets[i], ai[i]->ai_addr, ai[i]->ai_addrlen); + } + + /* Send two packets to each server. */ + int client = xsocket (AF_INET, SOCK_DGRAM, IPPROTO_UDP); + for (int i = 0; i < 3; ++i) + { + TEST_VERIFY (sendto (client, &i, sizeof (i), 0, + ai[i]->ai_addr, ai[i]->ai_addrlen) == sizeof (i)); + int j = i + 256; + TEST_VERIFY (sendto (client, &j, sizeof (j), 0, + ai[i]->ai_addr, ai[i]->ai_addrlen) == sizeof (j)); + } + + /* Check that the packets can be received with the expected + contents. Note that the receive calls interleave differently, + which hopefully proves that the sockets are, indeed, + independent. */ + for (int i = 0; i < 3; ++i) + { + int buf; + TEST_VERIFY (recv (sockets[i], &buf, sizeof (buf), 0) == sizeof (buf)); + TEST_VERIFY (buf == i); + } + for (int i = 0; i < 3; ++i) + { + int buf; + TEST_VERIFY (recv (sockets[i], &buf, sizeof (buf), 0) == sizeof (buf)); + TEST_VERIFY (buf == i + 256); + /* Check that there is no more data to receive. */ + TEST_VERIFY (recv (sockets[i], &buf, sizeof (buf), MSG_DONTWAIT) == -1); + TEST_VERIFY (errno == EWOULDBLOCK || errno == EAGAIN); + } + + /* Close all sockets and free the addresses. */ + for (int i = 0; i < 3; ++i) + { + freeaddrinfo (ai[i]); + xclose (sockets[i]); + } + xclose (client); +} + static int do_test (void) { - if (support_become_root ()) + bool root = support_become_root (); + if (root) printf ("info: acquired root-like privileges\n"); - if (support_enter_network_namespace ()) + bool netns = support_enter_network_namespace (); + if (netns) printf ("info: entered network namespace\n"); if (support_in_uts_namespace ()) printf ("info: also entered UTS namespace\n"); + + if (root && netns) + test_localhost_bind (); + return 0; } |