diff options
Diffstat (limited to 'inet/getnameinfo.c')
-rw-r--r-- | inet/getnameinfo.c | 561 |
1 files changed, 0 insertions, 561 deletions
diff --git a/inet/getnameinfo.c b/inet/getnameinfo.c deleted file mode 100644 index 40c20b4be6..0000000000 --- a/inet/getnameinfo.c +++ /dev/null @@ -1,561 +0,0 @@ -/* Convert socket address to string using Name Service Switch modules. - Copyright (C) 1997-2023 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <https://www.gnu.org/licenses/>. */ - -/* The Inner Net License, Version 2.00 - - The author(s) grant permission for redistribution and use in source and -binary forms, with or without modification, of the software and documentation -provided that the following conditions are met: - -0. If you receive a version of the software that is specifically labelled - as not being for redistribution (check the version message and/or README), - you are not permitted to redistribute that version of the software in any - way or form. -1. All terms of the all other applicable copyrights and licenses must be - followed. -2. Redistributions of source code must retain the authors' copyright - notice(s), this list of conditions, and the following disclaimer. -3. Redistributions in binary form must reproduce the authors' copyright - notice(s), this list of conditions, and the following disclaimer in the - documentation and/or other materials provided with the distribution. -4. [The copyright holder has authorized the removal of this clause.] -5. Neither the name(s) of the author(s) nor the names of its contributors - may be used to endorse or promote products derived from this software - without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY ITS AUTHORS AND CONTRIBUTORS ``AS IS'' AND ANY -EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY -DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - If these license terms cause you a real problem, contact the author. */ - -/* This software is Copyright 1996 by Craig Metz, All Rights Reserved. */ - -#include <errno.h> -#include <netdb.h> -#include <stddef.h> -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <unistd.h> -#include <stdint.h> -#include <arpa/inet.h> -#include <net/if.h> -#include <netinet/in.h> -#include <sys/param.h> -#include <sys/socket.h> -#include <sys/types.h> -#include <sys/un.h> -#include <sys/utsname.h> -#include <libc-lock.h> -#include <scratch_buffer.h> -#include <net-internal.h> -#include <set-freeres.h> - -#ifndef min -# define min(x,y) (((x) > (y)) ? (y) : (x)) -#endif /* min */ - -static char *domain; - -/* Former NI_IDN_ALLOW_UNASSIGNED, NI_IDN_USE_STD3_ASCII_RULES flags, - now ignored. */ -#define DEPRECATED_NI_IDN 192 - -/* Return true if no memory allocation failure happened (even if domain - name could not be obtained) or false otherwise. */ -static bool -nrl_domainname_core (struct scratch_buffer *tmpbuf) -{ - char *c; - struct hostent *h, th; - int herror; - - while (__gethostbyname_r ("localhost", &th, tmpbuf->data, tmpbuf->length, - &h, &herror)) - { - if (herror == NETDB_INTERNAL && errno == ERANGE) - { - if (!scratch_buffer_grow (tmpbuf)) - return false; - } - else - break; - } - - if (h != NULL && (c = strchr (h->h_name, '.')) != NULL) - { - domain = __strdup (++c); - return domain != NULL; - } - - /* The name contains no domain information. Use the name - now to get more information. */ - while (__gethostname (tmpbuf->data, tmpbuf->length)) - if (!scratch_buffer_grow (tmpbuf)) - return false; - - if ((c = strchr (tmpbuf->data, '.')) != NULL) - { - domain = __strdup (++c); - return domain != NULL; - } - - /* We need to preserve the hostname. */ - size_t hstnamelen = strlen (tmpbuf->data) + 1; - while (__gethostbyname_r (tmpbuf->data, &th, tmpbuf->data + hstnamelen, - tmpbuf->length - hstnamelen, &h, &herror)) - { - if (herror == NETDB_INTERNAL && errno == ERANGE) - { - if (!scratch_buffer_grow_preserve (tmpbuf)) - return false; - } - else - break; - } - - if (h != NULL && (c = strchr(h->h_name, '.')) != NULL) - { - domain = __strdup (++c); - return domain != NULL; - } - - struct in_addr in_addr = { .s_addr = htonl (INADDR_LOOPBACK) }; - - while (__gethostbyaddr_r ((const char *) &in_addr, sizeof (struct in_addr), - AF_INET, &th, tmpbuf->data, tmpbuf->length, &h, - &herror)) - { - if (herror == NETDB_INTERNAL && errno == ERANGE) - { - if (!scratch_buffer_grow (tmpbuf)) - return false; - } - else - break; - } - - if (h != NULL && (c = strchr (h->h_name, '.')) != NULL) - { - domain = __strdup (++c); - return domain != NULL; - } - return true; -} - -static bool -nrl_domainname (void) -{ - static int not_first; - - if (__glibc_likely (atomic_load_acquire (¬_first) != 0)) - return true; - - int r = true; - - __libc_lock_define_initialized (static, lock); - __libc_lock_lock (lock); - - if (atomic_load_relaxed (¬_first) == 0) - { - struct scratch_buffer tmpbuf; - scratch_buffer_init (&tmpbuf); - - if ((r = nrl_domainname_core (&tmpbuf))) - atomic_store_release (¬_first, 1); - - scratch_buffer_free (&tmpbuf); - } - - __libc_lock_unlock (lock); - - return r; -}; - -/* Copy a string to a destination buffer with length checking. Return - EAI_OVERFLOW if the buffer is not large enough, and 0 on - success. */ -static int -checked_copy (char *dest, size_t destlen, const char *source) -{ - size_t source_length = strlen (source); - if (source_length + 1 > destlen) - return EAI_OVERFLOW; - memcpy (dest, source, source_length + 1); - return 0; -} - -/* Helper function for CHECKED_SNPRINTF below. */ -static int -check_sprintf_result (int result, size_t destlen) -{ - if (result < 0) - return EAI_SYSTEM; - if ((size_t) result >= destlen) - /* If ret == destlen, there was no room for the terminating NUL - character. */ - return EAI_OVERFLOW; - return 0; -} - -/* Format a string in the destination buffer. Return 0 on success, - EAI_OVERFLOW in case the buffer is too small, or EAI_SYSTEM on any - other error. */ -#define CHECKED_SNPRINTF(dest, destlen, format, ...) \ - check_sprintf_result \ - (__snprintf (dest, destlen, format, __VA_ARGS__), destlen) - -/* Convert host name, AF_INET/AF_INET6 case, name only. */ -static int -gni_host_inet_name (struct scratch_buffer *tmpbuf, - const struct sockaddr *sa, socklen_t addrlen, - char *host, socklen_t hostlen, int flags) -{ - int herrno; - struct hostent th; - struct hostent *h = NULL; - if (sa->sa_family == AF_INET6) - { - const struct sockaddr_in6 *sin6p = (const struct sockaddr_in6 *) sa; - while (__gethostbyaddr_r (&sin6p->sin6_addr, sizeof(struct in6_addr), - AF_INET6, &th, tmpbuf->data, tmpbuf->length, - &h, &herrno)) - if (herrno == NETDB_INTERNAL && errno == ERANGE) - { - if (!scratch_buffer_grow (tmpbuf)) - { - __set_h_errno (herrno); - return EAI_MEMORY; - } - } - else - break; - } - else - { - const struct sockaddr_in *sinp = (const struct sockaddr_in *) sa; - while (__gethostbyaddr_r (&sinp->sin_addr, sizeof(struct in_addr), - AF_INET, &th, tmpbuf->data, tmpbuf->length, - &h, &herrno)) - if (herrno == NETDB_INTERNAL && errno == ERANGE) - { - if (!scratch_buffer_grow (tmpbuf)) - { - __set_h_errno (herrno); - return EAI_MEMORY; - } - } - else - break; - } - - if (h == NULL) - { - if (herrno == NETDB_INTERNAL) - { - __set_h_errno (herrno); - return EAI_SYSTEM; - } - if (herrno == TRY_AGAIN) - { - __set_h_errno (herrno); - return EAI_AGAIN; - } - } - - if (h) - { - if (flags & NI_NOFQDN) - { - if (!nrl_domainname ()) - return EAI_MEMORY; - - char *c = domain; - if (c != NULL && (c = strstr (h->h_name, c)) - && (c != h->h_name) && (*(--c) == '.')) - /* Terminate the string after the prefix. */ - *c = '\0'; - } - - /* If requested, convert from the IDN format. */ - bool do_idn = flags & NI_IDN; - char *h_name; - if (do_idn) - { - int rc = __idna_from_dns_encoding (h->h_name, &h_name); - if (rc == EAI_IDN_ENCODE) - /* Use the punycode name as a fallback. */ - do_idn = false; - else if (rc != 0) - return rc; - } - if (!do_idn) - h_name = h->h_name; - - size_t len = strlen (h_name) + 1; - if (len > hostlen) - return EAI_OVERFLOW; - memcpy (host, h_name, len); - - if (do_idn) - free (h_name); - - return 0; - } - - return EAI_NONAME; -} - -/* Convert host name, AF_INET/AF_INET6 case, numeric conversion. */ -static int -gni_host_inet_numeric (struct scratch_buffer *tmpbuf, - const struct sockaddr *sa, socklen_t addrlen, - char *host, socklen_t hostlen, int flags) -{ - if (sa->sa_family == AF_INET6) - { - const struct sockaddr_in6 *sin6p = (const struct sockaddr_in6 *) sa; - if (inet_ntop (AF_INET6, &sin6p->sin6_addr, host, hostlen) == NULL) - return EAI_OVERFLOW; - - uint32_t scopeid = sin6p->sin6_scope_id; - if (scopeid != 0) - { - size_t used_hostlen = __strnlen (host, hostlen); - /* Location of the scope string in the host buffer. */ - char *scope_start = host + used_hostlen; - size_t scope_length = hostlen - used_hostlen; - - if (IN6_IS_ADDR_LINKLOCAL (&sin6p->sin6_addr) - || IN6_IS_ADDR_MC_LINKLOCAL (&sin6p->sin6_addr)) - { - char scopebuf[IFNAMSIZ]; - if (if_indextoname (scopeid, scopebuf) != NULL) - return CHECKED_SNPRINTF - (scope_start, scope_length, - "%c%s", SCOPE_DELIMITER, scopebuf); - } - return CHECKED_SNPRINTF - (scope_start, scope_length, "%c%u", SCOPE_DELIMITER, scopeid); - } - } - else - { - const struct sockaddr_in *sinp = (const struct sockaddr_in *) sa; - if (inet_ntop (AF_INET, &sinp->sin_addr, host, hostlen) == NULL) - return EAI_OVERFLOW; - } - return 0; -} - -/* Convert AF_INET or AF_INET6 socket address, host part. */ -static int -gni_host_inet (struct scratch_buffer *tmpbuf, - const struct sockaddr *sa, socklen_t addrlen, - char *host, socklen_t hostlen, int flags) -{ - if (!(flags & NI_NUMERICHOST)) - { - int result = gni_host_inet_name - (tmpbuf, sa, addrlen, host, hostlen, flags); - if (result != EAI_NONAME) - return result; - } - - if (flags & NI_NAMEREQD) - return EAI_NONAME; - else - return gni_host_inet_numeric - (tmpbuf, sa, addrlen, host, hostlen, flags); -} - -/* Convert AF_LOCAL socket address, host part. */ -static int -gni_host_local (struct scratch_buffer *tmpbuf, - const struct sockaddr *sa, socklen_t addrlen, - char *host, socklen_t hostlen, int flags) -{ - if (!(flags & NI_NUMERICHOST)) - { - struct utsname utsname; - if (uname (&utsname) == 0) - return checked_copy (host, hostlen, utsname.nodename); - } - - if (flags & NI_NAMEREQD) - return EAI_NONAME; - - return checked_copy (host, hostlen, "localhost"); -} - -/* Convert the host part of an AF_LOCAK socket address. */ -static int -gni_host (struct scratch_buffer *tmpbuf, - const struct sockaddr *sa, socklen_t addrlen, - char *host, socklen_t hostlen, int flags) -{ - switch (sa->sa_family) - { - case AF_INET: - case AF_INET6: - return gni_host_inet (tmpbuf, sa, addrlen, host, hostlen, flags); - - case AF_LOCAL: - return gni_host_local (tmpbuf, sa, addrlen, host, hostlen, flags); - - default: - return EAI_FAMILY; - } -} - -/* Convert service to string, AF_INET and AF_INET6 variant. */ -static int -gni_serv_inet (struct scratch_buffer *tmpbuf, - const struct sockaddr *sa, socklen_t addrlen, - char *serv, socklen_t servlen, int flags) -{ - _Static_assert - (offsetof (struct sockaddr_in, sin_port) - == offsetof (struct sockaddr_in6, sin6_port) - && sizeof (((struct sockaddr_in) {}).sin_port) == sizeof (in_port_t) - && sizeof (((struct sockaddr_in6) {}).sin6_port) == sizeof (in_port_t), - "AF_INET and AF_INET6 port consistency"); - const struct sockaddr_in *sinp = (const struct sockaddr_in *) sa; - if (!(flags & NI_NUMERICSERV)) - { - struct servent *s, ts; - int e; - while ((e = __getservbyport_r (sinp->sin_port, - ((flags & NI_DGRAM) - ? "udp" : "tcp"), &ts, - tmpbuf->data, tmpbuf->length, &s))) - { - if (e == ERANGE) - { - if (!scratch_buffer_grow (tmpbuf)) - return EAI_MEMORY; - } - else - break; - } - if (s) - return checked_copy (serv, servlen, s->s_name); - /* Fall through to numeric conversion. */ - } - return CHECKED_SNPRINTF (serv, servlen, "%d", ntohs (sinp->sin_port)); -} - -/* Convert service to string, AF_LOCAL variant. */ -static int -gni_serv_local (struct scratch_buffer *tmpbuf, - const struct sockaddr *sa, socklen_t addrlen, - char *serv, socklen_t servlen, int flags) -{ - return checked_copy - (serv, servlen, ((const struct sockaddr_un *) sa)->sun_path); -} - -/* Convert service to string, dispatching to the implementations - above. */ -static int -gni_serv (struct scratch_buffer *tmpbuf, - const struct sockaddr *sa, socklen_t addrlen, - char *serv, socklen_t servlen, int flags) -{ - switch (sa->sa_family) - { - case AF_INET: - case AF_INET6: - return gni_serv_inet (tmpbuf, sa, addrlen, serv, servlen, flags); - case AF_LOCAL: - return gni_serv_local (tmpbuf, sa, addrlen, serv, servlen, flags); - default: - return EAI_FAMILY; - } -} - -int -getnameinfo (const struct sockaddr *sa, socklen_t addrlen, char *host, - socklen_t hostlen, char *serv, socklen_t servlen, - int flags) -{ - if (flags & ~(NI_NUMERICHOST|NI_NUMERICSERV|NI_NOFQDN|NI_NAMEREQD|NI_DGRAM - |NI_IDN|DEPRECATED_NI_IDN)) - return EAI_BADFLAGS; - - if (sa == NULL || addrlen < sizeof (sa_family_t)) - return EAI_FAMILY; - - if ((flags & NI_NAMEREQD) && host == NULL && serv == NULL) - return EAI_NONAME; - - switch (sa->sa_family) - { - case AF_LOCAL: - if (addrlen < (socklen_t) offsetof (struct sockaddr_un, sun_path)) - return EAI_FAMILY; - break; - case AF_INET: - if (addrlen < sizeof (struct sockaddr_in)) - return EAI_FAMILY; - break; - case AF_INET6: - if (addrlen < sizeof (struct sockaddr_in6)) - return EAI_FAMILY; - break; - default: - return EAI_FAMILY; - } - - struct scratch_buffer tmpbuf; - scratch_buffer_init (&tmpbuf); - - if (host != NULL && hostlen > 0) - { - int result = gni_host (&tmpbuf, sa, addrlen, host, hostlen, flags); - if (result != 0) - { - scratch_buffer_free (&tmpbuf); - return result; - } - } - - if (serv && (servlen > 0)) - { - int result = gni_serv (&tmpbuf, sa, addrlen, serv, servlen, flags); - if (result != 0) - { - scratch_buffer_free (&tmpbuf); - return result; - } - } - - scratch_buffer_free (&tmpbuf); - return 0; -} -libc_hidden_def (getnameinfo) - -weak_alias (domain, __libc_getnameinfo_freemem_ptr) |