diff options
author | Jakub Jelinek <jakub@redhat.com> | 2005-05-23 17:53:19 +0000 |
---|---|---|
committer | Jakub Jelinek <jakub@redhat.com> | 2005-05-23 17:53:19 +0000 |
commit | 7cfcf20b10c97faaf764f5c7784c4f2fa7922c5f (patch) | |
tree | 149a19f5f50b1433df714885fd986cdaefbee919 /sunrpc | |
parent | e975f7ef2955c34c381d84b2494b47018c3461ab (diff) | |
download | glibc-7cfcf20b10c97faaf764f5c7784c4f2fa7922c5f.tar glibc-7cfcf20b10c97faaf764f5c7784c4f2fa7922c5f.tar.gz glibc-7cfcf20b10c97faaf764f5c7784c4f2fa7922c5f.tar.bz2 glibc-7cfcf20b10c97faaf764f5c7784c4f2fa7922c5f.zip |
2005-05-23 Ulrich Drepper <drepper@redhat.com>
* sunrpc/pm_getport.c (__get_socket): New function.
(pmap_getport): Use it to open a non-reserved socket to the portmapper
for TCP.
* include/rpc/pmap_clnt.h (__get_socket): Declare.
* sunrpc/pm_getmaps.c (pmap_getmaps): Use __get_socket to get an
non-reserved socket for the portmapper.
Based on a patch by Steve Dickson <steved@redhat.com>.
* sunrpc/bindrsvprt.c (bindresvport): Try harder to find a port.
If we tried looking at the usual range without success extend the
range to even lower ports.
Diffstat (limited to 'sunrpc')
-rw-r--r-- | sunrpc/bindrsvprt.c | 23 | ||||
-rw-r--r-- | sunrpc/pm_getmaps.c | 15 | ||||
-rw-r--r-- | sunrpc/pm_getport.c | 52 |
3 files changed, 80 insertions, 10 deletions
diff --git a/sunrpc/bindrsvprt.c b/sunrpc/bindrsvprt.c index 374518716e..39c1e8063d 100644 --- a/sunrpc/bindrsvprt.c +++ b/sunrpc/bindrsvprt.c @@ -43,14 +43,15 @@ int bindresvport (int sd, struct sockaddr_in *sin) { - int res; static short port; struct sockaddr_in myaddr; int i; #define STARTPORT 600 +#define LOWPORT 200 #define ENDPORT (IPPORT_RESERVED - 1) #define NPORTS (ENDPORT - STARTPORT + 1) + static short startport = STARTPORT; if (sin == (struct sockaddr_in *) 0) { @@ -68,17 +69,29 @@ bindresvport (int sd, struct sockaddr_in *sin) { port = (__getpid () % NPORTS) + STARTPORT; } - res = -1; - __set_errno (EADDRINUSE); - for (i = 0; i < NPORTS && res < 0 && errno == EADDRINUSE; ++i) + /* Initialize to make gcc happy. */ + int res = -1; + + int nports = ENDPORT - startport + 1; + again: + for (i = 0; i < nports; ++i) { sin->sin_port = htons (port++); if (port > ENDPORT) { - port = STARTPORT; + port = startport; } res = __bind (sd, sin, sizeof (struct sockaddr_in)); + if (res >= 0 || errno != EADDRINUSE) + break; + } + + if (i == nports && startport != LOWPORT) + { + startport = LOWPORT; + nports = STARTPORT - LOWPORT; + goto again; } return res; diff --git a/sunrpc/pm_getmaps.c b/sunrpc/pm_getmaps.c index d1d4ca8769..2a6876d9d8 100644 --- a/sunrpc/pm_getmaps.c +++ b/sunrpc/pm_getmaps.c @@ -44,9 +44,12 @@ static char sccsid[] = "@(#)pmap_getmaps.c 1.10 87/08/11 Copyr 1984 Sun Micro"; #include <rpc/pmap_clnt.h> #include <sys/socket.h> #include <netdb.h> +#include <stdbool.h> #include <stdio.h> #include <errno.h> #include <libintl.h> +#include <unistd.h> + /* * Get a copy of the current port maps. @@ -56,13 +59,19 @@ struct pmaplist * pmap_getmaps (struct sockaddr_in *address) { struct pmaplist *head = (struct pmaplist *) NULL; - int socket = -1; struct timeval minutetimeout; CLIENT *client; + bool closeit = false; minutetimeout.tv_sec = 60; minutetimeout.tv_usec = 0; address->sin_port = htons (PMAPPORT); + + /* Don't need a reserved port to get ports from the portmapper. */ + int socket = __get_socket (address); + if (socket != -1) + closeit = true; + client = INTUSE(clnttcp_create) (address, PMAPPROG, PMAPVERS, &socket, 50, 500); if (client != (CLIENT *) NULL) @@ -75,7 +84,9 @@ pmap_getmaps (struct sockaddr_in *address) } CLNT_DESTROY (client); } - /* (void)close(socket); CLNT_DESTROY already closed it */ + /* We only need to close the socket here if we opened it. */ + if (closeit) + (void) __close (socket); address->sin_port = 0; return head; } diff --git a/sunrpc/pm_getport.c b/sunrpc/pm_getport.c index 00e1ba95bf..2d309841f3 100644 --- a/sunrpc/pm_getport.c +++ b/sunrpc/pm_getport.c @@ -38,6 +38,8 @@ static char sccsid[] = "@(#)pmap_getport.c 1.9 87/08/11 Copyr 1984 Sun Micro"; * Copyright (C) 1984, Sun Microsystems, Inc. */ +#include <stdbool.h> +#include <unistd.h> #include <rpc/rpc.h> #include <rpc/pmap_prot.h> #include <rpc/pmap_clnt.h> @@ -49,6 +51,41 @@ static const struct timeval tottimeout = {60, 0}; /* + * Create a socket that is locally bound to a non-reserve port. For + * any failures, -1 is returned which will cause the RPC code to + * create the socket. + */ +int +internal_function +__get_socket (struct sockaddr_in *saddr) +{ + int so = __socket (AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (so < 0) + return -1; + + struct sockaddr_in laddr; + socklen_t namelen = sizeof (laddr); + laddr.sin_family = AF_INET; + laddr.sin_port = 0; + laddr.sin_addr.s_addr = htonl (INADDR_ANY); + + int cc = __bind (so, (struct sockaddr *) &laddr, namelen); + if (__builtin_expect (cc < 0, 0)) + { + fail: + __close (so); + return -1; + } + + cc = __connect (so, (struct sockaddr *) saddr, namelen); + if (__builtin_expect (cc < 0, 0)) + goto fail; + + return so; +} + + +/* * Find the mapped port for program,version. * Calls the pmap service remotely to do the lookup. * Returns 0 if no map exists. @@ -64,11 +101,18 @@ pmap_getport (address, program, version, protocol) int socket = -1; CLIENT *client; struct pmap parms; + bool closeit = false; address->sin_port = htons (PMAPPORT); if (protocol == IPPROTO_TCP) - client = INTUSE(clnttcp_create) (address, PMAPPROG, PMAPVERS, &socket, - RPCSMALLMSGSIZE, RPCSMALLMSGSIZE); + { + /* Don't need a reserved port to get ports from the portmapper. */ + socket = __get_socket(address); + if (socket != -1) + closeit = true; + client = INTUSE(clnttcp_create) (address, PMAPPROG, PMAPVERS, &socket, + RPCSMALLMSGSIZE, RPCSMALLMSGSIZE); + } else client = INTUSE(clntudp_bufcreate) (address, PMAPPROG, PMAPVERS, timeout, &socket, RPCSMALLMSGSIZE, @@ -93,7 +137,9 @@ pmap_getport (address, program, version, protocol) } CLNT_DESTROY (client); } - /* (void)close(socket); CLNT_DESTROY already closed it */ + /* We only need to close the socket here if we opened it. */ + if (closeit) + (void) __close (socket); address->sin_port = 0; return port; } |