(root)/
coreutils-9.4/
gnulib-tests/
test-getaddrinfo.c
       1  /* Test the getaddrinfo module.
       2  
       3     Copyright (C) 2006-2023 Free Software Foundation, Inc.
       4  
       5     This program is free software: you can redistribute it and/or modify
       6     it under the terms of the GNU General Public License as published by
       7     the Free Software Foundation, either version 3 of the License, or
       8     (at your option) any later version.
       9  
      10     This program 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
      13     GNU General Public License for more details.
      14  
      15     You should have received a copy of the GNU General Public License
      16     along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
      17  
      18  /* Written by Simon Josefsson.  */
      19  
      20  #include <config.h>
      21  
      22  #include <netdb.h>
      23  
      24  #include "signature.h"
      25  SIGNATURE_CHECK (gai_strerror, char const *, (int));
      26  /* On native Windows, these two functions may have the __stdcall calling
      27     convention.  But the SIGNATURE_CHECK works only for functions with __cdecl
      28     calling convention.  */
      29  #if !(defined _WIN32 && !defined __CYGWIN__)
      30  SIGNATURE_CHECK (freeaddrinfo, void, (struct addrinfo *));
      31  SIGNATURE_CHECK (getaddrinfo, int, (char const *, char const *,
      32                                      struct addrinfo const *,
      33                                      struct addrinfo **));
      34  #endif
      35  
      36  #include <arpa/inet.h>
      37  #include <errno.h>
      38  #include <netinet/in.h>
      39  #include <stdio.h>
      40  #include <string.h>
      41  
      42  #include "sockets.h"
      43  
      44  /* Whether to print debugging messages.  */
      45  #define ENABLE_DEBUGGING 0
      46  
      47  #if ENABLE_DEBUGGING
      48  # define dbgprintf printf
      49  #else
      50  # define dbgprintf if (0) printf
      51  #endif
      52  
      53  /* BeOS does not have AF_UNSPEC.  */
      54  #ifndef AF_UNSPEC
      55  # define AF_UNSPEC 0
      56  #endif
      57  
      58  #ifndef EAI_SERVICE
      59  # define EAI_SERVICE 0
      60  #endif
      61  
      62  static int
      63  simple (char const *host, char const *service)
      64  {
      65    char buf[BUFSIZ];
      66    static int skip = 0;
      67    struct addrinfo hints;
      68    struct addrinfo *ai0, *ai;
      69    int res;
      70    int err;
      71  
      72    /* Once we skipped the test, do not try anything else */
      73    if (skip)
      74      return 0;
      75  
      76    dbgprintf ("Finding %s service %s...\n", host, service);
      77  
      78    /* This initializes "hints" but does not use it.  Is there a reason
      79       for this?  If so, please fix this comment.  */
      80    memset (&hints, 0, sizeof (hints));
      81    hints.ai_flags = AI_CANONNAME;
      82    hints.ai_family = AF_UNSPEC;
      83    hints.ai_socktype = SOCK_STREAM;
      84  
      85    res = getaddrinfo (host, service, 0, &ai0);
      86    err = errno;
      87  
      88    dbgprintf ("res %d: %s\n", res, gai_strerror (res));
      89  
      90    if (res != 0)
      91      {
      92        /* EAI_AGAIN is returned if no network is available. Don't fail
      93           the test merely because someone is down the country on their
      94           in-law's farm. */
      95        if (res == EAI_AGAIN)
      96          {
      97            skip++;
      98            fprintf (stderr, "skipping getaddrinfo test: no network?\n");
      99            return 77;
     100          }
     101        /* IRIX reports EAI_NONAME for "https".  Don't fail the test
     102           merely because of this.  */
     103        if (res == EAI_NONAME)
     104          return 0;
     105        /* Solaris reports EAI_SERVICE for "http" and "https".  Don't
     106           fail the test merely because of this.  */
     107        if (res == EAI_SERVICE)
     108          return 0;
     109  #ifdef EAI_NODATA
     110        /* AIX reports EAI_NODATA for "https".  Don't fail the test
     111           merely because of this.  */
     112        if (res == EAI_NODATA)
     113          return 0;
     114  #endif
     115        /* Provide details if errno was set.  */
     116        if (res == EAI_SYSTEM)
     117          fprintf (stderr, "system error: %s\n", strerror (err));
     118  
     119        return 1;
     120      }
     121  
     122    for (ai = ai0; ai; ai = ai->ai_next)
     123      {
     124        void *ai_addr = ai->ai_addr;
     125        struct sockaddr_in *sock_addr = ai_addr;
     126        dbgprintf ("\tflags %x\n", ai->ai_flags + 0u);
     127        dbgprintf ("\tfamily %x\n", ai->ai_family + 0u);
     128        dbgprintf ("\tsocktype %x\n", ai->ai_socktype + 0u);
     129        dbgprintf ("\tprotocol %x\n", ai->ai_protocol + 0u);
     130        dbgprintf ("\taddrlen %lu: ", (unsigned long) ai->ai_addrlen);
     131        dbgprintf ("\tFound %s\n",
     132                   inet_ntop (ai->ai_family,
     133                              &sock_addr->sin_addr,
     134                              buf, sizeof (buf) - 1));
     135        if (ai->ai_canonname)
     136          dbgprintf ("\tFound %s...\n", ai->ai_canonname);
     137  
     138        {
     139          char ipbuf[BUFSIZ];
     140          char portbuf[BUFSIZ];
     141  
     142          res = getnameinfo (ai->ai_addr, ai->ai_addrlen,
     143                             ipbuf, sizeof (ipbuf) - 1,
     144                             portbuf, sizeof (portbuf) - 1,
     145                             NI_NUMERICHOST|NI_NUMERICSERV);
     146          dbgprintf ("\t\tgetnameinfo %d: %s\n", res, gai_strerror (res));
     147          if (res == 0)
     148            {
     149              dbgprintf ("\t\tip %s\n", ipbuf);
     150              dbgprintf ("\t\tport %s\n", portbuf);
     151            }
     152        }
     153  
     154      }
     155  
     156    freeaddrinfo (ai0);
     157  
     158    return 0;
     159  }
     160  
     161  #define HOST1 "www.gnu.org"
     162  #define SERV1 "http"
     163  #define HOST2 "www.ibm.com"
     164  #define SERV2 "https"
     165  #define HOST3 "microsoft.com"
     166  #define SERV3 "http"
     167  #define HOST4 "google.org"
     168  #define SERV4 "ldap"
     169  
     170  int main (void)
     171  {
     172    (void) gl_sockets_startup (SOCKETS_1_1);
     173  
     174    return simple (HOST1, SERV1)
     175      + simple (HOST2, SERV2)
     176      + simple (HOST3, SERV3)
     177      + simple (HOST4, SERV4);
     178  }