Blame support/tst-support-namespace.c

Packit 6c4009
/* Test entering namespaces.
Packit 6c4009
   Copyright (C) 2016-2018 Free Software Foundation, Inc.
Packit 6c4009
   This file is part of the GNU C Library.
Packit 6c4009
Packit 6c4009
   The GNU C Library is free software; you can redistribute it and/or
Packit 6c4009
   modify it under the terms of the GNU Lesser General Public
Packit 6c4009
   License as published by the Free Software Foundation; either
Packit 6c4009
   version 2.1 of the License, or (at your option) any later version.
Packit 6c4009
Packit 6c4009
   The GNU C Library is distributed in the hope that it will be useful,
Packit 6c4009
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 6c4009
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 6c4009
   Lesser General Public License for more details.
Packit 6c4009
Packit 6c4009
   You should have received a copy of the GNU Lesser General Public
Packit 6c4009
   License along with the GNU C Library; if not, see
Packit 6c4009
   <http://www.gnu.org/licenses/>.  */
Packit 6c4009
Packit 6c4009
#include <errno.h>
Packit 6c4009
#include <netdb.h>
Packit 6c4009
#include <stdio.h>
Packit 6c4009
#include <support/check.h>
Packit 6c4009
#include <support/namespace.h>
Packit 6c4009
#include <support/xsocket.h>
Packit 6c4009
#include <support/xunistd.h>
Packit 6c4009
Packit 6c4009
/* Check that the loopback interface provides multiple addresses which
Packit 6c4009
   can be used to run independent servers.  */
Packit 6c4009
static void
Packit 6c4009
test_localhost_bind (void)
Packit 6c4009
{
Packit 6c4009
  printf ("info: testing loopback interface with multiple addresses\n");
Packit 6c4009
Packit 6c4009
  /* Create the two server addresses.  */
Packit 6c4009
  static const struct addrinfo hints =
Packit 6c4009
    {
Packit 6c4009
      .ai_family = AF_INET,
Packit 6c4009
      .ai_socktype = SOCK_DGRAM,
Packit 6c4009
      .ai_protocol = IPPROTO_UDP,
Packit 6c4009
    };
Packit 6c4009
  struct addrinfo *ai[3];
Packit 6c4009
  TEST_VERIFY_EXIT (getaddrinfo ("127.0.0.1", "53", &hints, ai + 0) == 0);
Packit 6c4009
  TEST_VERIFY_EXIT (getaddrinfo ("127.0.0.2", "53", &hints, ai + 1) == 0);
Packit 6c4009
  TEST_VERIFY_EXIT (getaddrinfo ("127.0.0.3", "53", &hints, ai + 2) == 0);
Packit 6c4009
Packit 6c4009
  /* Create the server scokets and bind them to these addresses.  */
Packit 6c4009
  int sockets[3];
Packit 6c4009
  for (int i = 0; i < 3; ++i)
Packit 6c4009
    {
Packit 6c4009
      sockets[i] = xsocket
Packit 6c4009
        (ai[i]->ai_family, ai[i]->ai_socktype, ai[i]->ai_protocol);
Packit 6c4009
      xbind (sockets[i], ai[i]->ai_addr, ai[i]->ai_addrlen);
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  /* Send two packets to each server.  */
Packit 6c4009
  int client = xsocket (AF_INET, SOCK_DGRAM, IPPROTO_UDP);
Packit 6c4009
  for (int i = 0; i < 3; ++i)
Packit 6c4009
    {
Packit 6c4009
      TEST_VERIFY (sendto (client, &i, sizeof (i), 0,
Packit 6c4009
                           ai[i]->ai_addr, ai[i]->ai_addrlen) == sizeof (i));
Packit 6c4009
      int j = i + 256;
Packit 6c4009
      TEST_VERIFY (sendto (client, &j, sizeof (j), 0,
Packit 6c4009
                           ai[i]->ai_addr, ai[i]->ai_addrlen) == sizeof (j));
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  /* Check that the packets can be received with the expected
Packit 6c4009
     contents.  Note that the receive calls interleave differently,
Packit 6c4009
     which hopefully proves that the sockets are, indeed,
Packit 6c4009
     independent.  */
Packit 6c4009
  for (int i = 0; i < 3; ++i)
Packit 6c4009
    {
Packit 6c4009
      int buf;
Packit 6c4009
      TEST_VERIFY (recv (sockets[i], &buf, sizeof (buf), 0) == sizeof (buf));
Packit 6c4009
      TEST_VERIFY (buf == i);
Packit 6c4009
    }
Packit 6c4009
  for (int i = 0; i < 3; ++i)
Packit 6c4009
    {
Packit 6c4009
      int buf;
Packit 6c4009
      TEST_VERIFY (recv (sockets[i], &buf, sizeof (buf), 0) == sizeof (buf));
Packit 6c4009
      TEST_VERIFY (buf == i + 256);
Packit 6c4009
      /* Check that there is no more data to receive.  */
Packit 6c4009
      TEST_VERIFY (recv (sockets[i], &buf, sizeof (buf), MSG_DONTWAIT) == -1);
Packit 6c4009
      TEST_VERIFY (errno == EWOULDBLOCK || errno == EAGAIN);
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  /* Close all sockets and free the addresses.  */
Packit 6c4009
  for (int i = 0; i < 3; ++i)
Packit 6c4009
    {
Packit 6c4009
      freeaddrinfo (ai[i]);
Packit 6c4009
      xclose (sockets[i]);
Packit 6c4009
    }
Packit 6c4009
  xclose (client);
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
Packit 6c4009
static int
Packit 6c4009
do_test (void)
Packit 6c4009
{
Packit 6c4009
  bool root = support_become_root ();
Packit 6c4009
  if (root)
Packit 6c4009
    printf ("info: acquired root-like privileges\n");
Packit 6c4009
  bool netns = support_enter_network_namespace ();
Packit 6c4009
  if (netns)
Packit 6c4009
    printf ("info: entered network namespace\n");
Packit 6c4009
  if (support_in_uts_namespace ())
Packit 6c4009
    printf ("info: also entered UTS namespace\n");
Packit 6c4009
Packit 6c4009
  if (root && netns)
Packit 6c4009
    test_localhost_bind ();
Packit 6c4009
Packit 6c4009
  return 0;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
#include <support/test-driver.c>