(root)/
Python-3.11.7/
Modules/
getnameinfo.c
       1  /*
       2   * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
       3   * All rights reserved.
       4   *
       5   * Redistribution and use in source and binary forms, with or without
       6   * modification, are permitted provided that the following conditions
       7   * are met:
       8   * 1. Redistributions of source code must retain the above copyright
       9   *    notice, this list of conditions and the following disclaimer.
      10   * 2. Redistributions in binary form must reproduce the above copyright
      11   *    notice, this list of conditions and the following disclaimer in the
      12   *    documentation and/or other materials provided with the distribution.
      13   * 3. Neither the name of the project nor the names of its contributors
      14   *    may be used to endorse or promote products derived from this software
      15   *    without specific prior written permission.
      16   *
      17   * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
      18   * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      19   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      20   * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
      21   * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
      22   * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
      23   * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
      24   * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
      25   * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
      26   * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
      27   * SUCH DAMAGE.
      28   */
      29  
      30  /*
      31   * Issues to be discussed:
      32   * - Thread safe-ness must be checked
      33   * - Return values.  There seems to be no standard for return value (RFC2133)
      34   *   but INRIA implementation returns EAI_xxx defined for getaddrinfo().
      35   */
      36  
      37  #if 0
      38  #include <sys/types.h>
      39  #include <sys/socket.h>
      40  #include <netinet/in.h>
      41  #include <arpa/inet.h>
      42  #include <arpa/nameser.h>
      43  #include <netdb.h>
      44  #include <resolv.h>
      45  #include <string.h>
      46  #include <stddef.h>
      47  
      48  #include "addrinfo.h"
      49  #endif
      50  
      51  #ifdef HAVE_NETDB_H
      52  #define HAVE_GETNAMEINFO 1
      53  
      54  #define SUCCESS 0
      55  #define YES 1
      56  #define NO  0
      57  
      58  static struct gni_afd {
      59      int a_af;
      60      int a_addrlen;
      61      int a_socklen;
      62      int a_off;
      63  } gni_afdl [] = {
      64  #ifdef ENABLE_IPV6
      65      {PF_INET6, sizeof(struct in6_addr), sizeof(struct sockaddr_in6),
      66          offsetof(struct sockaddr_in6, sin6_addr)},
      67  #endif
      68      {PF_INET, sizeof(struct in_addr), sizeof(struct sockaddr_in),
      69          offsetof(struct sockaddr_in, sin_addr)},
      70      {0, 0, 0},
      71  };
      72  
      73  struct gni_sockinet {
      74      u_char      si_len;
      75      u_char      si_family;
      76      u_short     si_port;
      77  };
      78  
      79  #define ENI_NOSOCKET    0
      80  #define ENI_NOSERVNAME  1
      81  #define ENI_NOHOSTNAME  2
      82  #define ENI_MEMORY      3
      83  #define ENI_SYSTEM      4
      84  #define ENI_FAMILY      5
      85  #define ENI_SALEN       6
      86  
      87  /* forward declaration to make gcc happy */
      88  int getnameinfo(const struct sockaddr *, size_t, char *, size_t,
      89                            char *, size_t, int);
      90  
      91  int
      92  getnameinfo(sa, salen, host, hostlen, serv, servlen, flags)
      93      const struct sockaddr *sa;
      94      size_t salen;
      95      char *host;
      96      size_t hostlen;
      97      char *serv;
      98      size_t servlen;
      99      int flags;
     100  {
     101      struct gni_afd *gni_afd;
     102      struct servent *sp;
     103      struct hostent *hp;
     104      u_short port;
     105      int family, len, i;
     106      char *addr, *p;
     107      u_long v4a;
     108  #ifdef ENABLE_IPV6
     109      u_char pfx;
     110      int h_error;
     111  #endif
     112      char numserv[512];
     113      char numaddr[512];
     114  
     115      if (sa == NULL)
     116          return ENI_NOSOCKET;
     117  
     118  #ifdef HAVE_SOCKADDR_SA_LEN
     119      len = sa->sa_len;
     120      if (len != salen) return ENI_SALEN;
     121  #else
     122      len = salen;
     123  #endif
     124  
     125      family = sa->sa_family;
     126      for (i = 0; gni_afdl[i].a_af; i++)
     127          if (gni_afdl[i].a_af == family) {
     128              gni_afd = &gni_afdl[i];
     129              goto found;
     130          }
     131      return ENI_FAMILY;
     132  
     133   found:
     134      if (len != gni_afd->a_socklen) return ENI_SALEN;
     135  
     136      port = ((struct gni_sockinet *)sa)->si_port; /* network byte order */
     137      addr = (char *)sa + gni_afd->a_off;
     138  
     139      if (serv == NULL || servlen == 0) {
     140          /* what we should do? */
     141      } else if (flags & NI_NUMERICSERV) {
     142          sprintf(numserv, "%d", ntohs(port));
     143          if (strlen(numserv) > servlen)
     144              return ENI_MEMORY;
     145          strcpy(serv, numserv);
     146      } else {
     147          sp = getservbyport(port, (flags & NI_DGRAM) ? "udp" : "tcp");
     148          if (sp) {
     149              if (strlen(sp->s_name) > servlen)
     150                  return ENI_MEMORY;
     151              strcpy(serv, sp->s_name);
     152          } else
     153              return ENI_NOSERVNAME;
     154      }
     155  
     156      switch (sa->sa_family) {
     157      case AF_INET:
     158          v4a = ((struct sockaddr_in *)sa)->sin_addr.s_addr;
     159          if (IN_MULTICAST(v4a) || IN_EXPERIMENTAL(v4a))
     160              flags |= NI_NUMERICHOST;
     161          v4a >>= IN_CLASSA_NSHIFT;
     162          if (v4a == 0 || v4a == IN_LOOPBACKNET)
     163              flags |= NI_NUMERICHOST;
     164          break;
     165  #ifdef ENABLE_IPV6
     166      case AF_INET6:
     167          pfx = ((struct sockaddr_in6 *)sa)->sin6_addr.s6_addr[0];
     168          if (pfx == 0 || pfx == 0xfe || pfx == 0xff)
     169              flags |= NI_NUMERICHOST;
     170          break;
     171  #endif
     172      }
     173      if (host == NULL || hostlen == 0) {
     174          /* what should we do? */
     175      } else if (flags & NI_NUMERICHOST) {
     176          if (inet_ntop(gni_afd->a_af, addr, numaddr, sizeof(numaddr))
     177              == NULL)
     178              return ENI_SYSTEM;
     179          if (strlen(numaddr) > hostlen)
     180              return ENI_MEMORY;
     181          strcpy(host, numaddr);
     182      } else {
     183  #ifdef ENABLE_IPV6
     184          hp = getipnodebyaddr(addr, gni_afd->a_addrlen, gni_afd->a_af, &h_error);
     185  #else
     186          hp = gethostbyaddr(addr, gni_afd->a_addrlen, gni_afd->a_af);
     187  #endif
     188  
     189          if (hp) {
     190              if (flags & NI_NOFQDN) {
     191                  p = strchr(hp->h_name, '.');
     192                  if (p) *p = '\0';
     193              }
     194              if (strlen(hp->h_name) > hostlen) {
     195  #ifdef ENABLE_IPV6
     196                  freehostent(hp);
     197  #endif
     198                  return ENI_MEMORY;
     199              }
     200              strcpy(host, hp->h_name);
     201  #ifdef ENABLE_IPV6
     202              freehostent(hp);
     203  #endif
     204          } else {
     205              if (flags & NI_NAMEREQD)
     206                  return ENI_NOHOSTNAME;
     207              if (inet_ntop(gni_afd->a_af, addr, numaddr, sizeof(numaddr))
     208                  == NULL)
     209                  return ENI_NOHOSTNAME;
     210              if (strlen(numaddr) > hostlen)
     211                  return ENI_MEMORY;
     212              strcpy(host, numaddr);
     213          }
     214      }
     215      return SUCCESS;
     216  }
     217  #endif // HAVE_NETDB_H