(root)/
glibc-2.38/
sunrpc/
tst-udp-garbage.c
       1  /* Test that garbage packets do not affect timeout handling.
       2     Copyright (C) 2017-2023 Free Software Foundation, Inc.
       3     This file is part of the GNU C Library.
       4  
       5     The GNU C Library is free software; you can redistribute it and/or
       6     modify it under the terms of the GNU Lesser General Public
       7     License as published by the Free Software Foundation; either
       8     version 2.1 of the License, or (at your option) any later version.
       9  
      10     The GNU C Library is distributed in the hope that it will be useful,
      11     but WITHOUT ANY WARRANTY; without even the implied warranty of
      12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      13     Lesser General Public License for more details.
      14  
      15     You should have received a copy of the GNU Lesser General Public
      16     License along with the GNU C Library; if not, see
      17     <https://www.gnu.org/licenses/>.  */
      18  
      19  #include <netinet/in.h>
      20  #include <rpc/clnt.h>
      21  #include <rpc/svc.h>
      22  #include <stdbool.h>
      23  #include <support/check.h>
      24  #include <support/namespace.h>
      25  #include <support/xsocket.h>
      26  #include <support/xthread.h>
      27  #include <sys/socket.h>
      28  #include <unistd.h>
      29  
      30  /* Descriptor for the server UDP socket.  */
      31  static int server_fd;
      32  
      33  static void *
      34  garbage_sender_thread (void *unused)
      35  {
      36    while (true)
      37      {
      38        struct sockaddr_storage sa;
      39        socklen_t salen = sizeof (sa);
      40        char buf[1];
      41        if (recvfrom (server_fd, buf, sizeof (buf), 0,
      42                      (struct sockaddr *) &sa, &salen) < 0)
      43          FAIL_EXIT1 ("recvfrom: %m");
      44  
      45        /* Send garbage packets indefinitely.  */
      46        buf[0] = 0;
      47        while (true)
      48          {
      49            /* sendto can fail if the client closed the socket.  */
      50            if (sendto (server_fd, buf, sizeof (buf), 0,
      51                        (struct sockaddr *) &sa, salen) < 0)
      52              break;
      53  
      54            /* Wait a bit, to avoid burning too many CPU cycles in a
      55               tight loop.  The wait period must be much shorter than
      56               the client timeouts configured below.  */
      57            usleep (50 * 1000);
      58          }
      59      }
      60  }
      61  
      62  static int
      63  do_test (void)
      64  {
      65    support_become_root ();
      66    support_enter_network_namespace ();
      67  
      68    server_fd = xsocket (AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, IPPROTO_UDP);
      69    struct sockaddr_in server_address =
      70      {
      71        .sin_family = AF_INET,
      72        .sin_addr.s_addr = htonl (INADDR_LOOPBACK),
      73      };
      74    xbind (server_fd,
      75           (struct sockaddr *) &server_address, sizeof (server_address));
      76    {
      77      socklen_t sinlen = sizeof (server_address);
      78      xgetsockname (server_fd, (struct sockaddr *) &server_address, &sinlen);
      79      TEST_VERIFY (sizeof (server_address) == sinlen);
      80    }
      81  
      82    /* Garbage packet source.  */
      83    xpthread_detach (xpthread_create (NULL, garbage_sender_thread, NULL));
      84  
      85    /* Test client.  Use an arbitrary timeout of one second, which is
      86       much longer than the garbage packet interval, but still
      87       reasonably short, so that the test completes quickly.  */
      88    int client_fd = RPC_ANYSOCK;
      89    CLIENT *clnt = clntudp_create (&server_address,
      90                                   1, 2, /* Arbitrary RPC endpoint numbers.  */
      91                                   (struct timeval) { 1, 0 },
      92                                   &client_fd);
      93    if (clnt == NULL)
      94      FAIL_EXIT1 ("clntudp_create: %m");
      95  
      96    TEST_VERIFY (clnt_call (clnt, 3, /* Arbitrary RPC procedure number.  */
      97                            (xdrproc_t) xdr_void, NULL,
      98                            (xdrproc_t) xdr_void, NULL,
      99                            ((struct timeval) { 1, 0 })));
     100  
     101    return 0;
     102  }
     103  
     104  #include <support/test-driver.c>