(root)/
glibc-2.38/
resolv/
tst-bug18665.c
       1  /* Test for __libc_res_nsend buffer mismanagent (bug 18665), UDP case.
       2     Copyright (C) 2016-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 <errno.h>
      20  #include <netdb.h>
      21  #include <resolv.h>
      22  #include <stdio.h>
      23  #include <string.h>
      24  #include <support/check.h>
      25  #include <support/resolv_test.h>
      26  #include <support/xthread.h>
      27  
      28  static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
      29  
      30  static int initial_address_count;
      31  static int response_count;
      32  
      33  static void
      34  response (const struct resolv_response_context *ctx,
      35            struct resolv_response_builder *b,
      36            const char *qname, uint16_t qclass, uint16_t qtype)
      37  {
      38    TEST_VERIFY_EXIT (qname != NULL);
      39    struct resolv_response_flags flags = {};
      40    resolv_response_init (b, flags);
      41    resolv_response_add_question (b, qname, qclass, qtype);
      42  
      43    resolv_response_section (b, ns_s_an);
      44  
      45    /* Add many A/AAAA records to the second response.  */
      46    int address_count;
      47    xpthread_mutex_lock (&lock);
      48    if (response_count == 0)
      49      address_count = initial_address_count;
      50    else
      51      address_count = 2000;
      52    ++response_count;
      53    xpthread_mutex_unlock (&lock);
      54  
      55    for (int i = 0; i < address_count; ++i)
      56      {
      57        resolv_response_open_record (b, qname, qclass, qtype, 0);
      58        switch (qtype)
      59          {
      60          case T_A:
      61            {
      62              char ipv4[4] = {10, i >> 8, i, 0};
      63              ipv4[3] = 2 * ctx->tcp + 4 * ctx->server_index;
      64              resolv_response_add_data (b, &ipv4, sizeof (ipv4));
      65            }
      66            break;
      67          case T_AAAA:
      68            {
      69              char ipv6[16]
      70                = {0x20, 0x01, 0xd, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0,
      71                   i >> 8, i, 0};
      72              ipv6[15] = 2 * ctx->tcp + 4 * ctx->server_index;
      73              resolv_response_add_data (b, &ipv6, sizeof (ipv6));
      74            }
      75            break;
      76          default:
      77            support_record_failure ();
      78            printf ("error: unexpected QTYPE: %s/%u/%u\n",
      79                    qname, qclass, qtype);
      80          }
      81        resolv_response_close_record (b);
      82      }
      83  }
      84  
      85  static void
      86  test_different_sizes (void)
      87  {
      88    struct addrinfo hints = { .ai_family = AF_UNSPEC, };
      89    struct addrinfo *ai;
      90    int ret;
      91  
      92    /* This magic number produces a response size close to 2048
      93       bytes.  */
      94    initial_address_count = 126;
      95    response_count = 0;
      96  
      97    ret = getaddrinfo ("www.example", "80", &hints, &ai);
      98    if (ret == 0)
      99      freeaddrinfo (ai);
     100  
     101    response_count = 0;
     102    ret = getaddrinfo ("www123.example", "80", &hints, &ai);
     103    if (ret == 0)
     104      freeaddrinfo (ai);
     105  
     106    response_count = 0;
     107    ret = getaddrinfo ("www1234.example", "80", &hints, &ai);
     108    if (ret == 0)
     109      freeaddrinfo (ai);
     110  
     111    response_count = 0;
     112    ret = getaddrinfo ("www12345.example", "80", &hints, &ai);
     113    if (ret == 0)
     114      freeaddrinfo (ai);
     115  }
     116  
     117  static int
     118  do_test (void)
     119  {
     120    struct resolv_test *obj = resolv_test_start
     121      ((struct resolv_redirect_config)
     122       {
     123         .response_callback = response
     124       });
     125  
     126    test_different_sizes ();
     127  
     128    _res.options |= RES_SNGLKUP;
     129    test_different_sizes ();
     130  
     131    _res.options |= RES_SNGLKUPREOP;
     132    test_different_sizes ();
     133  
     134    resolv_test_end (obj);
     135    return 0;
     136  }
     137  
     138  #include <support/test-driver.c>