1  /* IPv4-only variant of gethostbyname.
       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 License as
       7     published by the Free Software Foundation; either version 2.1 of the
       8     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; see the file COPYING.LIB.  If
      17     not, see <https://www.gnu.org/licenses/>.  */
      18  
      19  #include <errno.h>
      20  #include <netdb.h>
      21  #include <rpc/rpc.h>
      22  #include <scratch_buffer.h>
      23  #include <string.h>
      24  
      25  int
      26  __libc_rpc_gethostbyname (const char *host, struct sockaddr_in *addr)
      27  {
      28    struct hostent hostbuf;
      29    struct hostent *hp = NULL;
      30    int herr;
      31    struct scratch_buffer tmpbuf;
      32    scratch_buffer_init (&tmpbuf);
      33  
      34    while (__gethostbyname2_r (host, AF_INET,
      35                               &hostbuf, tmpbuf.data, tmpbuf.length, &hp,
      36                               &herr) != 0
      37           || hp == NULL)
      38      if (herr != NETDB_INTERNAL || errno != ERANGE)
      39        {
      40          struct rpc_createerr *ce = &get_rpc_createerr ();
      41          ce->cf_stat = RPC_UNKNOWNHOST;
      42          scratch_buffer_free (&tmpbuf);
      43          return -1;
      44        }
      45      else
      46        {
      47          if (!scratch_buffer_grow (&tmpbuf))
      48            {
      49              /* If memory allocation failed, allocating the RPC error
      50                 structure might could as well, so this could lead to a
      51                 crash.  */
      52              struct rpc_createerr *ce = &get_rpc_createerr ();
      53              ce->cf_stat = RPC_SYSTEMERROR;
      54              ce->cf_error.re_errno = ENOMEM;
      55              return -1;
      56            }
      57        }
      58  
      59    if (hp->h_addrtype != AF_INET || hp->h_length != sizeof (addr->sin_addr))
      60      {
      61        struct rpc_createerr *ce = &get_rpc_createerr ();
      62        ce->cf_stat = RPC_SYSTEMERROR;
      63        ce->cf_error.re_errno = EAFNOSUPPORT;
      64        scratch_buffer_free (&tmpbuf);
      65        return -1;
      66      }
      67  
      68    addr->sin_family = AF_INET;
      69    addr->sin_port = htons (0);
      70    memcpy (&addr->sin_addr, hp->h_addr, sizeof (addr->sin_addr));
      71    scratch_buffer_free (&tmpbuf);
      72    return 0;
      73  }