diff options
-rw-r--r-- | ChangeLog | 11 | ||||
-rw-r--r-- | include/rpc/rpc.h | 6 | ||||
-rw-r--r-- | sunrpc/Makefile | 3 | ||||
-rw-r--r-- | sunrpc/clnt_gen.c | 37 | ||||
-rw-r--r-- | sunrpc/clnt_simp.c | 23 | ||||
-rw-r--r-- | sunrpc/getrpcport.c | 40 | ||||
-rw-r--r-- | sunrpc/rpc_gethostbyname.c | 73 |
7 files changed, 116 insertions, 77 deletions
@@ -1,5 +1,16 @@ 2016-12-27 Florian Weimer <fweimer@redhat.com> + [BZ #20964] + sunrpc: Always obtain AF_INET addresses from NSS. + * include/rpc/rpc.h (__libc_rpc_gethostbyname): Declare. + * sunrpc/rpc_gethostbyname.c: New file. + * sunrpc/Makefile (routines): Add it. + * sunrpc/clnt_gen.c (clnt_create): Use __libc_rpc_gethostbyname. + * sunrpc/clnt_simp.c (callrpc): Likewise. + * sunrpc/getrpcport.c (getrpcport): Likewise. + +2016-12-27 Florian Weimer <fweimer@redhat.com> + * sunrpc/rpcinfo.c: Remove. * sunrpc/Makefile: Remove comments referring to rpcinfo. diff --git a/include/rpc/rpc.h b/include/rpc/rpc.h index 4c9ee82..60c7896 100644 --- a/include/rpc/rpc.h +++ b/include/rpc/rpc.h @@ -57,6 +57,12 @@ libc_hidden_proto (__rpc_thread_svc_pollfd) libc_hidden_proto (__rpc_thread_svc_fdset) libc_hidden_proto (__rpc_thread_createerr) +/* Perform a host name lookup for NAME and return the first IPv4 + address in *ADDR. Return 0 on success and -1 on error (and set an + RPC error). */ +int __libc_rpc_gethostbyname (const char *host, struct sockaddr_in *addr) + attribute_hidden; + #endif /* _RPC_THREAD_SAFE_ */ # endif /* !_ISOMAC */ diff --git a/sunrpc/Makefile b/sunrpc/Makefile index da6dffa..f7c593a 100644 --- a/sunrpc/Makefile +++ b/sunrpc/Makefile @@ -78,7 +78,8 @@ routines := auth_none authuxprot bindrsvprt clnt_raw clnt_simp \ des_crypt des_impl des_soft key_prot openchild rtime svcauth_des \ getrpcent getrpcbyname getrpcbynumber \ getrpcent_r getrpcbyname_r getrpcbynumber_r \ - clnt_unix svc_unix create_xid $(need-export-routines) + clnt_unix svc_unix create_xid $(need-export-routines) \ + rpc_gethostbyname ifneq ($(link-obsolete-rpc),yes) # We only add the RPC for compatibility to libc.so. shared-only-routines = $(routines) diff --git a/sunrpc/clnt_gen.c b/sunrpc/clnt_gen.c index df34672..8dffaa9 100644 --- a/sunrpc/clnt_gen.c +++ b/sunrpc/clnt_gen.c @@ -45,9 +45,6 @@ CLIENT * clnt_create (const char *hostname, u_long prog, u_long vers, const char *proto) { - struct hostent hostbuf, *h; - size_t hstbuflen; - char *hsttmpbuf; struct protoent protobuf, *p; size_t prtbuflen; char *prttmpbuf; @@ -56,7 +53,6 @@ clnt_create (const char *hostname, u_long prog, u_long vers, int sock; struct timeval tv; CLIENT *client; - int herr; if (strcmp (proto, "unix") == 0) { @@ -78,37 +74,8 @@ clnt_create (const char *hostname, u_long prog, u_long vers, return client; } - hstbuflen = 1024; - hsttmpbuf = __alloca (hstbuflen); - while (__gethostbyname_r (hostname, &hostbuf, hsttmpbuf, hstbuflen, - &h, &herr) != 0 - || h == NULL) - if (herr != NETDB_INTERNAL || errno != ERANGE) - { - get_rpc_createerr().cf_stat = RPC_UNKNOWNHOST; - return NULL; - } - else - { - /* Enlarge the buffer. */ - hstbuflen *= 2; - hsttmpbuf = __alloca (hstbuflen); - } - - if (h->h_addrtype != AF_INET) - { - /* - * Only support INET for now - */ - struct rpc_createerr *ce = &get_rpc_createerr (); - ce->cf_stat = RPC_SYSTEMERROR; - ce->cf_error.re_errno = EAFNOSUPPORT; - return NULL; - } - sin.sin_family = h->h_addrtype; - sin.sin_port = 0; - __bzero (sin.sin_zero, sizeof (sin.sin_zero)); - memcpy ((char *) &sin.sin_addr, h->h_addr, h->h_length); + if (__libc_rpc_gethostbyname (hostname, &sin) != 0) + return NULL; prtbuflen = 1024; prttmpbuf = __alloca (prtbuflen); diff --git a/sunrpc/clnt_simp.c b/sunrpc/clnt_simp.c index d612df0..0ecb64c 100644 --- a/sunrpc/clnt_simp.c +++ b/sunrpc/clnt_simp.c @@ -61,7 +61,6 @@ callrpc (const char *host, u_long prognum, u_long versnum, u_long procnum, struct callrpc_private_s *crp = callrpc_private; struct sockaddr_in server_addr; enum clnt_stat clnt_stat; - struct hostent hostbuf, *hp; struct timeval timeout, tottimeout; if (crp == 0) @@ -84,10 +83,6 @@ callrpc (const char *host, u_long prognum, u_long versnum, u_long procnum, } else { - size_t buflen; - char *buffer; - int herr; - crp->valid = 0; if (crp->socket != RPC_ANYSOCK) { @@ -100,25 +95,11 @@ callrpc (const char *host, u_long prognum, u_long versnum, u_long procnum, crp->client = NULL; } - buflen = 1024; - buffer = __alloca (buflen); - while (__gethostbyname_r (host, &hostbuf, buffer, buflen, - &hp, &herr) != 0 - || hp == NULL) - if (herr != NETDB_INTERNAL || errno != ERANGE) - return (int) RPC_UNKNOWNHOST; - else - { - /* Enlarge the buffer. */ - buflen *= 2; - buffer = __alloca (buflen); - } + if (__libc_rpc_gethostbyname (host, &server_addr) != 0) + return (int) get_rpc_createerr().cf_stat; timeout.tv_usec = 0; timeout.tv_sec = 5; - memcpy ((char *) &server_addr.sin_addr, hp->h_addr, hp->h_length); - server_addr.sin_family = AF_INET; - server_addr.sin_port = 0; if ((crp->client = clntudp_create (&server_addr, (u_long) prognum, (u_long) versnum, timeout, &crp->socket)) == NULL) return (int) get_rpc_createerr().cf_stat; diff --git a/sunrpc/getrpcport.c b/sunrpc/getrpcport.c index 07ee8c0..8fde0a9 100644 --- a/sunrpc/getrpcport.c +++ b/sunrpc/getrpcport.c @@ -1,3 +1,21 @@ +/* Obtain the RPC port number for an RPC service on a host. + Copyright (C) 2016 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; see the file COPYING.LIB. If + not, see <http://www.gnu.org/licenses/>. */ + /* * Copyright (c) 2010, Oracle America, Inc. * @@ -43,26 +61,8 @@ int getrpcport (const char *host, u_long prognum, u_long versnum, u_int proto) { struct sockaddr_in addr; - struct hostent hostbuf, *hp; - size_t buflen; - char *buffer; - int herr; - - buflen = 1024; - buffer = __alloca (buflen); - while (__gethostbyname_r (host, &hostbuf, buffer, buflen, &hp, &herr) != 0 - || hp == NULL) - if (herr != NETDB_INTERNAL || errno != ERANGE) - return 0; - else - { - /* Enlarge the buffer. */ - buflen *= 2; - buffer = __alloca (buflen); - } - memcpy ((char *) &addr.sin_addr, hp->h_addr, hp->h_length); - addr.sin_family = AF_INET; - addr.sin_port = 0; + if (__libc_rpc_gethostbyname (host, &addr) != 0) + return 0; return pmap_getport (&addr, prognum, versnum, proto); } diff --git a/sunrpc/rpc_gethostbyname.c b/sunrpc/rpc_gethostbyname.c new file mode 100644 index 0000000..a2ee960 --- /dev/null +++ b/sunrpc/rpc_gethostbyname.c @@ -0,0 +1,73 @@ +/* IPv4-only variant of gethostbyname. + Copyright (C) 2016 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; see the file COPYING.LIB. If + not, see <http://www.gnu.org/licenses/>. */ + +#include <errno.h> +#include <netdb.h> +#include <rpc/rpc.h> +#include <scratch_buffer.h> +#include <string.h> + +int +__libc_rpc_gethostbyname (const char *host, struct sockaddr_in *addr) +{ + struct hostent hostbuf; + struct hostent *hp = NULL; + int herr; + struct scratch_buffer tmpbuf; + scratch_buffer_init (&tmpbuf); + + while (__gethostbyname2_r (host, AF_INET, + &hostbuf, tmpbuf.data, tmpbuf.length, &hp, + &herr) != 0 + || hp == NULL) + if (herr != NETDB_INTERNAL || errno != ERANGE) + { + struct rpc_createerr *ce = &get_rpc_createerr (); + ce->cf_stat = RPC_UNKNOWNHOST; + scratch_buffer_free (&tmpbuf); + return -1; + } + else + { + if (!scratch_buffer_grow (&tmpbuf)) + { + /* If memory allocation failed, allocating the RPC error + structure might could as well, so this could lead to a + crash. */ + struct rpc_createerr *ce = &get_rpc_createerr (); + ce->cf_stat = RPC_SYSTEMERROR; + ce->cf_error.re_errno = ENOMEM; + return -1; + } + } + + if (hp->h_addrtype != AF_INET || hp->h_length != sizeof (addr->sin_addr)) + { + struct rpc_createerr *ce = &get_rpc_createerr (); + ce->cf_stat = RPC_SYSTEMERROR; + ce->cf_error.re_errno = EAFNOSUPPORT; + scratch_buffer_free (&tmpbuf); + return -1; + } + + addr->sin_family = AF_INET; + addr->sin_port = htons (0); + memcpy (&addr->sin_addr, hp->h_addr, sizeof (addr->sin_addr)); + scratch_buffer_free (&tmpbuf); + return 0; +} |