diff --git a/ChangeLog b/ChangeLog index dcb50083fe..7b502559ae 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,16 @@ 1999-07-18 Ulrich Drepper + * inet/Makefile (routines): Add getipnodebyad and freehostent. + * inet/Versions [GLIBC_2.2] (libc): Add getipnodebyad and freehostent. + * inet/freehostent.c: New file. + * inet/getipnodebyad.c: New file. + * nss/digits_dots.c: Fail if IPv6 is found and IPv4 is requested. + Add support for getipnode* functions. + + * nss/digits_dots.c: Don't use __set_h_errno, assign to *h_errnop. + Set h_aliases to NULL and not to a pointer to an array with a NULL + pointer following XNS 5.2. + * posix/sched.h: Remove internal interfaces. * include/sched.h: Add internal interfaces. diff --git a/inet/Makefile b/inet/Makefile index 12da863f80..14bc027a0b 100644 --- a/inet/Makefile +++ b/inet/Makefile @@ -45,7 +45,7 @@ routines := htonl htons \ rcmd rexec ruserpass \ getnetgrent_r getnetgrent \ getaliasent_r getaliasent getaliasname getaliasname_r \ - in6_addr getnameinfo if_index + in6_addr getnameinfo if_index getipnodebyad freehostent tests := htontest test_ifindex tst-ntoa tst-ether_aton diff --git a/inet/Versions b/inet/Versions index 711d490aa5..df97f6188a 100644 --- a/inet/Versions +++ b/inet/Versions @@ -62,4 +62,10 @@ libc { getprotoent_r; getrpcbyname_r; getrpcbynumber_r; getrpcent_r; getservbyname_r; } + GLIBC_2.2 { + # f* + freehostent; + # g* + getipnodebyaddr; + } } diff --git a/inet/freehostent.c b/inet/freehostent.c new file mode 100644 index 0000000000..c2c1b25d6d --- /dev/null +++ b/inet/freehostent.c @@ -0,0 +1,27 @@ +/* Copyright (C) 1999 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + + +void +freehostent (struct hostent *ptr) +{ + free (ptr); +} diff --git a/inet/getipnodebyad.c b/inet/getipnodebyad.c new file mode 100644 index 0000000000..d9d5ba8887 --- /dev/null +++ b/inet/getipnodebyad.c @@ -0,0 +1,59 @@ +/* Copyright (C) 1999 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include +#include + +#include "nsswitch.h" + +/* We avoid using a too large buffer in case the user is accumulating the + results and there is lots of unused space in the allocated buffer. */ +#define BUFLEN 512 + + +struct hostent * +getipnodebyaddr (const char *addr, size_t len, int type, int *error_num) +{ + size_t buffer_size; + char *buffer; + struct hostent *result; + + buffer_size = BUFLEN; + buffer = malloc (buffer_size); + + while (buffer != NULL + && __gethostbyaddr_r (addr, len, type, (struct hostent *) buffer, + (char *) ((struct hostent *) buffer + 1), + buffer_size - sizeof (struct hostent), + &result, error_num) == ERANGE + && *error_num == NETDB_INTERNAL) + { + buffer_size += BUFLEN; + buffer = realloc (buffer, buffer_size); + if (buffer == NULL) + { + *error_num = TRY_AGAIN; + assert (result == NULL); + return NULL; + } + } + + return buffer == NULL ? NULL : result; +} diff --git a/nss/digits_dots.c b/nss/digits_dots.c index 306249a347..03ae2ec7a5 100644 --- a/nss/digits_dots.c +++ b/nss/digits_dots.c @@ -28,13 +28,15 @@ typedef unsigned char host_addr_t [16]; host_addr_t *host_addr; typedef char *host_addr_list_t [2]; - host_addr_list_t *host_aliases; host_addr_list_t *h_addr_ptrs; size_t size_needed; int addr_size; #ifndef HAVE_AF int af = -1; #endif +#ifdef HAVE_TYPE + int af = type; +#endif switch (af) { @@ -47,18 +49,26 @@ break; default: +#ifdef HAVE_TYPE + /* This must not happen. */ + *h_errnop = HOST_NOT_FOUND; + goto done; +#else af = (_res.options & RES_USE_INET6) ? AF_INET6 : AF_INET; addr_size = af == AF_INET6 ? IN6ADDRSZ : INADDRSZ; break; +#endif } size_needed = (sizeof (*host_addr) - + sizeof (*host_aliases) + sizeof (*h_addr_ptrs) - + strlen (name) + 1); + + sizeof (*h_addr_ptrs) + strlen (name) + 1); #ifdef HAVE_LOOKUP_BUFFER if (buflen < size_needed) { +# ifdef NEED_H_ERRNO + *h_errnop = TRY_AGAIN; +# endif __set_errno (ERANGE); goto done; } @@ -89,10 +99,8 @@ memset (buffer, 0, size_needed); host_addr = (host_addr_t *) buffer; - host_aliases = (host_addr_list_t *) - ((char *) host_addr + sizeof (*host_addr)); h_addr_ptrs = (host_addr_list_t *) - ((char *) host_aliases + sizeof (*host_aliases)); + ((char *) host_addr + sizeof (*host_addr)); hostname = (char *) h_addr_ptrs + sizeof (*h_addr_ptrs); if (isdigit (name[0])) @@ -119,7 +127,7 @@ } if (! ok) { - __set_h_errno (HOST_NOT_FOUND); + *h_errnop = HOST_NOT_FOUND; #ifndef HAVE_LOOKUP_BUFFER result = (struct hostent *) NULL; #endif @@ -127,36 +135,54 @@ } resbuf.h_name = strcpy (hostname, name); - resbuf.h_aliases = *host_aliases; - (*host_aliases)[0] = NULL; + resbuf.h_aliases = NULL; (*h_addr_ptrs)[0] = (char *)host_addr; (*h_addr_ptrs)[1] = (char *)0; resbuf.h_addr_list = *h_addr_ptrs; - if (_res.options & RES_USE_INET6 && af == AF_INET) + if ( +#ifdef HAVE_TYPE + type == AF_INET6 +#else + af == AF_INET && (_res.options & RES_USE_INET6) +#endif + ) { - /* We need to change the IP v4 address into the - IP v6 address. */ - char tmp[INADDRSZ], *p = (char *) host_addr; - int i; +#ifdef HAVE_TYPE + if ((flags & AI_V4MAPPED) == 0) + { + /* That's bad. The user hasn't specified that she + allows IPv4 numeric addresses. */ + result = NULL; + *herrno_p = HOST_NOT_FOUND; + goto done; + } + else +#endif + { + /* We need to change the IP v4 address into the + IP v6 address. */ + char tmp[INADDRSZ], *p = (char *) host_addr; + int i; - /* Save a copy of the IP v4 address. */ - memcpy (tmp, host_addr, INADDRSZ); - /* Mark this ipv6 addr as a mapped ipv4. */ - for (i = 0; i < 10; i++) - *p++ = 0x00; - *p++ = 0xff; - *p++ = 0xff; - /* Copy the IP v4 address. */ - memcpy (p, tmp, INADDRSZ); - resbuf.h_addrtype = AF_INET6; - resbuf.h_length = IN6ADDRSZ; + /* Save a copy of the IP v4 address. */ + memcpy (tmp, host_addr, INADDRSZ); + /* Mark this ipv6 addr as a mapped ipv4. */ + for (i = 0; i < 10; i++) + *p++ = 0x00; + *p++ = 0xff; + *p++ = 0xff; + /* Copy the IP v4 address. */ + memcpy (p, tmp, INADDRSZ); + resbuf.h_addrtype = AF_INET6; + resbuf.h_length = IN6ADDRSZ; + } } else { resbuf.h_addrtype = af; resbuf.h_length = addr_size; } - __set_h_errno (NETDB_SUCCESS); + *h_errnop = NETDB_SUCCESS; #ifdef HAVE_LOOKUP_BUFFER status = NSS_STATUS_SUCCESS; #else @@ -177,37 +203,48 @@ typedef unsigned char host_addr_t [16]; host_addr_t *host_addr; typedef char *host_addr_list_t [2]; - host_addr_list_t *host_aliases; host_addr_list_t *h_addr_ptrs; size_t size_needed; int addr_size; #ifndef HAVE_AF int af = -1; #endif +#ifdef HAVE_TYPE + int af = type; +#endif switch (af) { + default: + af = (_res.options & RES_USE_INET6) ? AF_INET6 : AF_INET; + if (af == AF_INET6) + { + addr_size = IN6ADDRSZ; + break; + } + /* FALLTHROUGH */ + case AF_INET: - addr_size = INADDRSZ; - break; + /* This is not possible. We cannot represent an IPv6 address + in an `struct in_addr' variable. */ + *h_errnop = HOST_NOT_FOUND; + result = NULL; + goto done; case AF_INET6: addr_size = IN6ADDRSZ; break; - - default: - af = (_res.options & RES_USE_INET6) ? AF_INET6 : AF_INET; - addr_size = (af == AF_INET6 ) ? IN6ADDRSZ : INADDRSZ; - break; } size_needed = (sizeof (*host_addr) - + sizeof (*host_aliases) + sizeof (*h_addr_ptrs) - + strlen (name) + 1); + + sizeof (*h_addr_ptrs) + strlen (name) + 1); #ifdef HAVE_LOOKUP_BUFFER if (buflen < size_needed) { +# ifdef NEED_H_ERRNO + *h_errnop = TRY_AGAIN; +# endif __set_errno (ERANGE); goto done; } @@ -235,10 +272,8 @@ memset (buffer, 0, size_needed); host_addr = (host_addr_t *) buffer; - host_aliases = (host_addr_list_t *) - ((char *) host_addr + sizeof (*host_addr)); h_addr_ptrs = (host_addr_list_t *) - ((char *) host_aliases + sizeof (*host_aliases)); + ((char *) host_addr + sizeof (*host_addr)); hostname = (char *) h_addr_ptrs + sizeof (*h_addr_ptrs); for (cp = name;; ++cp) @@ -250,9 +285,9 @@ /* All-IPv6-legal, no dot at the end. Fake up a hostent as if we'd actually done a lookup. */ - if (inet_pton (af, name, host_addr) <= 0) + if (inet_pton (AF_INET6, name, host_addr) <= 0) { - __set_h_errno (HOST_NOT_FOUND); + *h_errnop = HOST_NOT_FOUND; #ifndef HAVE_LOOKUP_BUFFER result = (struct hostent *) NULL; #endif @@ -260,14 +295,13 @@ } resbuf.h_name = strcpy (hostname, name); - resbuf.h_aliases = *host_aliases; - (*host_aliases)[0] = NULL; + resbuf.h_aliases = NULL; (*h_addr_ptrs)[0] = (char *) host_addr; (*h_addr_ptrs)[1] = (char *) 0; resbuf.h_addr_list = *h_addr_ptrs; - resbuf.h_addrtype = af; + resbuf.h_addrtype = AF_INET6; resbuf.h_length = addr_size; - __set_h_errno (NETDB_SUCCESS); + *h_errnop = NETDB_SUCCESS; #ifdef HAVE_LOOKUP_BUFFER status = NSS_STATUS_SUCCESS; #else