Blame sunrpc/tst-udp-garbage.c

Packit 6c4009
/* Test that garbage packets do not affect timeout handling.
Packit 6c4009
   Copyright (C) 2017-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 <netinet/in.h>
Packit 6c4009
#include <rpc/clnt.h>
Packit 6c4009
#include <rpc/svc.h>
Packit 6c4009
#include <stdbool.h>
Packit 6c4009
#include <support/check.h>
Packit 6c4009
#include <support/namespace.h>
Packit 6c4009
#include <support/xsocket.h>
Packit 6c4009
#include <support/xthread.h>
Packit 6c4009
#include <sys/socket.h>
Packit 6c4009
#include <unistd.h>
Packit 6c4009
Packit 6c4009
/* Descriptor for the server UDP socket.  */
Packit 6c4009
static int server_fd;
Packit 6c4009
Packit 6c4009
static void *
Packit 6c4009
garbage_sender_thread (void *unused)
Packit 6c4009
{
Packit 6c4009
  while (true)
Packit 6c4009
    {
Packit 6c4009
      struct sockaddr_storage sa;
Packit 6c4009
      socklen_t salen = sizeof (sa);
Packit 6c4009
      char buf[1];
Packit 6c4009
      if (recvfrom (server_fd, buf, sizeof (buf), 0,
Packit 6c4009
                    (struct sockaddr *) &sa, &salen) < 0)
Packit 6c4009
        FAIL_EXIT1 ("recvfrom: %m");
Packit 6c4009
Packit 6c4009
      /* Send garbage packets indefinitely.  */
Packit 6c4009
      buf[0] = 0;
Packit 6c4009
      while (true)
Packit 6c4009
        {
Packit 6c4009
          /* sendto can fail if the client closed the socket.  */
Packit 6c4009
          if (sendto (server_fd, buf, sizeof (buf), 0,
Packit 6c4009
                      (struct sockaddr *) &sa, salen) < 0)
Packit 6c4009
            break;
Packit 6c4009
Packit 6c4009
          /* Wait a bit, to avoid burning too many CPU cycles in a
Packit 6c4009
             tight loop.  The wait period must be much shorter than
Packit 6c4009
             the client timeouts configured below.  */
Packit 6c4009
          usleep (50 * 1000);
Packit 6c4009
        }
Packit 6c4009
    }
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
static int
Packit 6c4009
do_test (void)
Packit 6c4009
{
Packit 6c4009
  support_become_root ();
Packit 6c4009
  support_enter_network_namespace ();
Packit 6c4009
Packit 6c4009
  server_fd = xsocket (AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, IPPROTO_UDP);
Packit 6c4009
  struct sockaddr_in server_address =
Packit 6c4009
    {
Packit 6c4009
      .sin_family = AF_INET,
Packit 6c4009
      .sin_addr.s_addr = htonl (INADDR_LOOPBACK),
Packit 6c4009
    };
Packit 6c4009
  xbind (server_fd,
Packit 6c4009
         (struct sockaddr *) &server_address, sizeof (server_address));
Packit 6c4009
  {
Packit 6c4009
    socklen_t sinlen = sizeof (server_address);
Packit 6c4009
    xgetsockname (server_fd, (struct sockaddr *) &server_address, &sinlen);
Packit 6c4009
    TEST_VERIFY (sizeof (server_address) == sinlen);
Packit 6c4009
  }
Packit 6c4009
Packit 6c4009
  /* Garbage packet source.  */
Packit 6c4009
  xpthread_detach (xpthread_create (NULL, garbage_sender_thread, NULL));
Packit 6c4009
Packit 6c4009
  /* Test client.  Use an arbitrary timeout of one second, which is
Packit 6c4009
     much longer than the garbage packet interval, but still
Packit 6c4009
     reasonably short, so that the test completes quickly.  */
Packit 6c4009
  int client_fd = RPC_ANYSOCK;
Packit 6c4009
  CLIENT *clnt = clntudp_create (&server_address,
Packit 6c4009
                                 1, 2, /* Arbitrary RPC endpoint numbers.  */
Packit 6c4009
                                 (struct timeval) { 1, 0 },
Packit 6c4009
                                 &client_fd);
Packit 6c4009
  if (clnt == NULL)
Packit 6c4009
    FAIL_EXIT1 ("clntudp_create: %m");
Packit 6c4009
Packit 6c4009
  TEST_VERIFY (clnt_call (clnt, 3, /* Arbitrary RPC procedure number.  */
Packit 6c4009
                          (xdrproc_t) xdr_void, NULL,
Packit 6c4009
                          (xdrproc_t) xdr_void, NULL,
Packit 6c4009
                          ((struct timeval) { 1, 0 })));
Packit 6c4009
Packit 6c4009
  return 0;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
#include <support/test-driver.c>