diff options
Diffstat (limited to 'support/tst-support-namespace.c')
-rw-r--r-- | support/tst-support-namespace.c | 84 |
1 files changed, 82 insertions, 2 deletions
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; } |