summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authoralfred <alfred@FreeBSD.org>2002-07-11 16:23:04 +0000
committeralfred <alfred@FreeBSD.org>2002-07-11 16:23:04 +0000
commit5b169b54b872927977c851631d464c27ef5fa10a (patch)
treea98b9550416d304fe0a94ec91f6129aa1ccb928e /lib
parentd96c3f211e59bdb210800c68cf8304a6c22163dd (diff)
downloadFreeBSD-src-5b169b54b872927977c851631d464c27ef5fa10a.zip
FreeBSD-src-5b169b54b872927977c851631d464c27ef5fa10a.tar.gz
Add functions allowing for the user to specify a timeout for rpc functions.
Update copyrights to reflect where this code was lifted from. (tirpc '99) Submitted by: mbr
Diffstat (limited to 'lib')
-rw-r--r--lib/libc/rpc/LICENSE335
-rw-r--r--lib/libc/rpc/Makefile.inc3
-rw-r--r--lib/libc/rpc/clnt_generic.c234
-rw-r--r--lib/libc/rpc/rpc_clnt_create.345
-rw-r--r--lib/libc/rpc/rpcb_clnt.c149
5 files changed, 670 insertions, 96 deletions
diff --git a/lib/libc/rpc/LICENSE b/lib/libc/rpc/LICENSE
new file mode 100644
index 0000000..5f1205c
--- /dev/null
+++ b/lib/libc/rpc/LICENSE
@@ -0,0 +1,335 @@
+$FreeBSD$
+
+Sun Industry Standards Source License 1.0
+
+DEFINITIONS
+
+1.1. "Commercial Use" means distribution or otherwise
+making the Original Code available to a third party.
+
+1.2. "Contributor Version" means the combination of the
+Original Code, and the Modifications made by that particular
+Contributor.
+
+1.3. "Electronic Distribution Mechanism" means a mechanism
+generally accepted in the software development community for
+the electronic transfer of data.
+
+1.4. "Executable" means Original Code in any form other
+than Source Code.
+
+1.5. "Initial Developer" means the individual or entity
+identified as the Initial Developer in the Source Code
+notice required by 2 (Exhibit A)
+
+1.6. "Larger Work" means a work which combines Original
+Code or portions thereof with code not governed by the terms
+of this License.
+
+1.7. "License" means this document.
+
+1.8. "Licensable" means having the right to grant, to the
+maximum extent possible, whether at the time of the initial
+grant or subsequently acquired, any and all of the rights
+conveyed herein.
+
+1.9. "Modifications" means any addition to or deletion from
+the substance or structure of either the Original Code or
+any previous Modifications. A Modification is:
+
+A. Any addition to or deletion from the contents of a file
+containing Original Code or previous Modifications.
+
+B. Any new file that contains any part of the Original Code
+or previous Modifications. .
+
+1.10. "Original Code" means Source Code of computer
+software code which is described in the Source Code notice
+required by Exhibit A as Original Code.
+
+1.11. "Patent Claims" means any patent claims, now owned or
+hereafter acquired, including without limitation, method,
+process, and apparatus claims, in any patent Licensable by
+grantor.
+
+1.12. "Source Code" means the preferred form of the
+Original Code for making modifications to it, including all
+modules it contains, plus any associated interface
+definition files, or scripts used to control compilation and
+installation of an Executable.
+
+1.13. "Standards" means the standard identified in Exhibit
+B or a subsequent version of such standard.
+
+1.14. "You" or "Your" means an individual or a legal entity
+exercising rights under, and complying with all of the terms
+of, this License or a future version of this License issued
+under Section 6.1. For legal entities, "You" includes any
+entity which controls, is controlled by, or is under common
+control with You. For purposes of this definition,
+"control" means (a) the power, direct or indirect, to cause
+the direction or management of such entity, whether by
+contract or otherwise, or (b) ownership of more than fifty
+percent (50%) of the outstanding shares or beneficial
+ownership of such entity.
+
+2.0 SOURCE CODE LICENSE
+
+2.1 The Initial Developer Grant: The Initial Developer
+hereby grants You a world-wide, royalty-free, non-exclusive
+license, subject to third party intellectual property
+claims:
+
+a) under intellectual property rights (other than patent or
+trademark) Licensable by Initial Developer to use,
+reproduce, modify, display, perform, sub license and
+distribute the Original Code (or portions thereof )with or
+without Modifications, and/or as part of a Larger Work; and
+
+b) under Patents Claims infringed by the making, using or
+selling of Original Code, to make, have made, use, practice,
+sell, and offer for sale, and/or otherwise dispose of the
+Original Code (or portions thereof).
+
+c) the licenses granted in this Section 2.1(a ) and (b) are
+effective on the date Initial Developer first distributes
+Original Code under the terms of this License.
+
+d) Notwithstanding Section 2.1(b )above, no patent license
+is granted: 1) for code that You delete from the Original
+Code; 2) separate from the Original Code; or 3) for
+infringements caused by: i) the modification of the
+Original Code or
+
+ii) the combination of the Original Code with other software
+or devices, including but not limited to Modifications.
+
+3.0 DISTRIBUTION OBLIGATIONS
+
+3.1 Application of License. The Source Code version of
+Original Code may be distributed only under the terms of
+this License or a future version of this License released
+under Section 6.1, and You must include a copy of this
+License with every copy of the Source Code You distribute.
+You may not offer or impose any terms on any Source Code
+version that alters or restricts the applicable version of
+this License or the recipient's rights hereunder. Your
+license for shipment of the Contributor Version is
+conditioned upon your full compliance with this Section.
+The Modifications which you create must comply with all
+requirements set out by the Standards body in effect 120
+days before You ship the Contributor Version. In the event
+that the Modifications do not meet such requirements, You
+agree to publish (i) any deviation from the Standards
+protocol resulting from implementation of your Modifications
+and (ii) a reference implementation of Your Modifications,
+and to make any such deviation and reference implementation
+available to all third parties under the same terms as the
+license on a royalty free basis within thirty (30) days of
+Your first customer shipment of Your Modifications.
+
+3.2 Required Notices. You must duplicate the notice in
+Exhibit A in each file of the Source Code. If it is not
+possible to put such notice in a particular Source Code file
+due to its structure, then You must include such notice in a
+location (such as a relevant directory ) where a user would
+be likely to look for such a notice. If You created one or
+more Modifications ) You may add your name as a Contributor
+to the notice described in Exhibit A. You must also
+duplicate this License in any documentation for the Source
+Code where You describe recipients' rights or ownership
+rights relating to Initial Code. You may choose to offer,
+and to charge a fee for, warranty, support, indemnity or
+liability obligations to one or more recipients of Your
+version of the Code. However, You may do so only
+
+on Your own behalf, and not on behalf of the Initial
+Developer. You must make it absolutely clear than any such
+warranty, support, indemnity or liability obligation is
+offered by You alone, and You hereby agree to indemnify the
+Initial Developer for any liability incurred by the Initial
+Developer as a result of warranty, support, indemnity or
+liability terms You offer.
+
+3.3 Distribution of Executable Versions. You may distribute
+Original Code in Executable and Source form only if the
+requirements of Section 3.1 and 3.2 have been met for that
+Original Code, and if You include a notice stating that the
+Source Code version of the Original Code is available under
+the terms of this License. The notice must be conspicuously
+included in any notice in an Executable or Source versions,
+related documentation or collateral in which You describe
+recipients' rights relating to the Original Code. You may
+distribute the Executable and Source versions of Your
+version of the Code or ownership rights under a license of
+Your choice, which may contain terms different from this
+License, provided that You are in compliance with the terms
+of this License. If You distribute the Executable and
+Source versions under a different license You must make it
+absolutely clear that any terms which differ from this
+License are offered by You alone, not by the Initial
+Developer . You hereby agree to indemnify the Initial
+Developer for any liability incurred by the Initial
+Developer as a result of any such terms You offer .
+
+3.4 Larger Works. You may create a Larger Work by combining
+Original Code with other code not governed by the terms of
+this License and distribute the Larger Work as a single
+product. In such a case, You must make sure the
+requirements of this License are fulfilled for the Original
+Code.
+
+4.0 INABILITY TO COMPLY DUE TO STATUTE OR REGULATION
+
+If it is impossible for You to comply with any of the terms
+of this License with respect to some or all of the Original
+Code due to statute, judicial order, or regulation then You
+must:
+
+a) comply with the terms of this License to the maximum
+extent possible; and
+
+b) describe the limitations and the code they affect. Such
+description must be included in the LEGAL file described in
+Section 3.2 and must be included with all distributions of
+the Source Code. Except to the extent prohibited by statute
+or regulation, such description must be sufficiently
+detailed for a recipient of ordinary skill to be able to
+understand it.
+
+5.0 APPLICATION OF THIS LICENSE This License applies to code
+to which the Initial Developer has attached the notice in
+Exhibit A and to related Modifications as set out in Section
+3.1.
+
+6.0 VERSIONS OF THE LICENSE
+
+6.1 New Versions. Sun Microsystems, Inc. Sun may publish
+revised and/or new versions of the License from time to
+time. Each version will be given a distinguishing version
+number .
+
+6.2 Effect of New Versions. Once Original Code has been
+published under a particular version of the License, You may
+always continue to use it under the terms of that version.
+You may also choose to use such Original Code under the
+terms of any subsequent version of the License published by
+Sun. No one other than Sun has the right to modify the
+terms applicable to Original Code.
+
+7. DISCLAIMER OF W ARRANTY. ORIGINAL CODE IS PROVIDED
+UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY OF
+ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT
+LIMITATION, WARRANTIES THAT THE ORIGINAL CODE IS FREE OF
+DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR
+NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND
+PERFORMANCE OF THE ORIGINAL CODE IS WITH YOU. SHOULD ANY
+ORIGINAL CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT THE
+INITIAL DEVELOPER )ASSUME THE COST OF ANY NECESSARY
+SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF
+WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO
+USE OF ANY ORIGINAL CODE IS AUTHORIZED HEREUNDER EXCEPT
+UNDER THIS DISCLAIMER.
+
+8.0 TERMINATION
+
+8.1 This License and the rights granted hereunder will
+terminate automatically if You fail to comply with terms
+herein and fail to cure such breach within 30 days of
+becoming aware of the breach. All sublicenses to the
+Original Code which are properly granted shall survive any
+termination of this License. Provisions which, by their
+nature, must remain in effect beyond the termination of this
+License shall survive.
+
+8.2 .In the event of termination under Section 8.1 above,
+all end user license agreements (excluding distributors and
+resellers) which have been validly granted by You or any
+distributor hereunder prior to termination shall survive
+termination.
+
+9.0 LIMIT OF LIABILITY UNDER NO CIRCUMSTANCES AND UNDER NO
+LEGAL THEORY, WHETHER TORT (INCLUDING NEGLIGENCE) ,CONTRACT,
+OR OTHER WISE, SHALL YOU, THE INITIAL DEVELOPER, ANY OTHER
+CONTRIBUTOR, OR ANY DISTRIBUTOR OF ORIGINAL CODE, OR ANY
+SUPPLIER OF ANY OF SUCH PARTIES, BE LIABLE TO ANY PERSON FOR
+ANY INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+OF ANY CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR
+LOSS OF GOOD WILL, WORK STOPPAGE, COMPUTER FAILURE OR
+MALFUNCTION, OR ANY AND ALL OTHER COMMERCIAL DAMAGES OR
+LOSSES, EVEN IF SUCH PARTY SHALL HAVE BEEN INFORMED OF THE
+POSSIBILITY OF SUCH DAMAGES. THIS LIMITATION OF LIABILITY
+SHALL NOT APPLY TO LIABILITY FOR DEATH OR PERSONAL INJURY
+RESULTING FROM SUCH PARTYS NEGLIGENCE TO THE EXTENT
+APPLICABLE LAW PROHIBITS SUCH LIMITATION. SOME
+JURISDICTIONS DO NOT ALLOW THE EXCLUSION OR LIMITATION OF
+INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THIS EXCLUSION AND
+LIMITATION MAY NOT APPLY TO YOU.
+
+10.0 U .S. GOVERNMENT END USERS U.S. Government: If this
+Software is being acquired by or on behalf of the U.S.
+Government or by a U.S. Government prime contractor or
+subcontractor (at any tier), then the Government's rights in
+the Software and accompanying documentation shall be only as
+set forth in this license; this is in accordance with 48 C.F
+.R. 227.7201 through 227.7202-4 (for Department of Defense
+(DoD) acquisitions )and with 48 C.F.R.2.101 and 12.212( for
+non-DoD acquisitions).
+
+11.0 MISCELLANEOUS This License represents the complete
+agreement concerning subject matter hereof. If any
+provision of this License is held to be unenforceable, such
+provision shall be reformed only to the extent necessary to
+make it enforceable. This License shall be governed by
+California law provisions (except to the extent applicable
+law, if any, provides otherwise), excluding its
+conflict-of-law provisions. With respect to disputes in
+which at least one party is a citizen of, or an entity
+chartered or registered to do business in the United States
+of America, any litigation relating to this License shall be
+subject to the jurisdiction of the Federal Courts of the
+Northern District of California, with venue lying in Santa
+Clara County, California, with the losing party responsible
+for costs, including without limitation, court costs and
+reasonable attorneys fees and expenses. The application of
+the United Nations Convention on Contracts for the
+International Sale of Goods is expressly excluded. Any law
+or regulation which provides that the language of a contract
+shall be construed against the drafter shall not apply to
+this License.
+
+EXHIBIT A - Sun Standards
+
+"The contents of this file are subject to the Sun Standards
+License Version 1.0 the (the "License";) You may not use
+this file except in compliance with the License. You may
+obtain a copy of the License at
+_______________________________.
+
+ Software distributed under the License is distributed on
+an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either
+express or implied. See the License for the specific
+language governing rights and limitations under the License.
+
+The Original Code is Copyright 1998 by Sun Microsystems, Inc
+
+The Initial Developer of the Original Code is: Sun
+Microsystems, Inc.
+
+Portions created by _____________________________ are
+Copyright ______________________________.
+
+All Rights Reserved.
+
+Contributors: ______________________________________.
+
+EXHIBIT B - Sun Standards
+
+The Standard is defined as the following IETF RFCs:
+
+RFC1831: RPC: Remote Procedure Call Protocol Specification
+Version 2 RFC1832: XDR: External Data REpresentation
+Standard RFC1833: Binding Protocols for ONC RPC Version 2
+RFC2078: Generic Security Service Application Program
+Interface, Version 2 RFC2203: RPCSEC_GSS Protocol
+Specification RFC2695: Authentication Mechanisms for ONC RPC
diff --git a/lib/libc/rpc/Makefile.inc b/lib/libc/rpc/Makefile.inc
index 5234e89..3f2903f 100644
--- a/lib/libc/rpc/Makefile.inc
+++ b/lib/libc/rpc/Makefile.inc
@@ -78,7 +78,9 @@ MLINKS+= bindresvport.3 bindresvport_sa.3 \
rpc_clnt_calls.3 clnt_geterr.3 \
rpc_clnt_create.3 clnt_control.3 \
rpc_clnt_create.3 clnt_create.3 \
+ rpc_clnt_create.3 clnt_create_timed.3 \
rpc_clnt_create.3 clnt_create_vers.3 \
+ rpc_clnt_create.3 clnt_create_vers_timed.3 \
rpc_clnt_create.3 clnt_destroy.3 \
rpc_clnt_create.3 clnt_pcreateerror.3 \
rpc_clnt_create.3 clnt_spcreateerror.3 \
@@ -86,6 +88,7 @@ MLINKS+= bindresvport.3 bindresvport_sa.3 \
rpc_clnt_create.3 clnt_raw_create.3 \
rpc_clnt_create.3 clnt_tli_create.3 \
rpc_clnt_create.3 clnt_tp_create.3 \
+ rpc_clnt_create.3 clnt_tp_create_timed.3 \
rpc_clnt_create.3 clnt_vc_create.3 \
rpc_svc_calls.3 svc_dg_enablecache.3 \
rpc_svc_calls.3 svc_exit.3 \
diff --git a/lib/libc/rpc/clnt_generic.c b/lib/libc/rpc/clnt_generic.c
index 4147871..d249df6 100644
--- a/lib/libc/rpc/clnt_generic.c
+++ b/lib/libc/rpc/clnt_generic.c
@@ -1,6 +1,23 @@
/* $NetBSD: clnt_generic.c,v 1.18 2000/07/06 03:10:34 christos Exp $ */
/*
+ * The contents of this file are subject to the Sun Standards
+ * License Version 1.0 the (the "License";) You may not use
+ * this file except in compliance with the License. You may
+ * obtain a copy of the License at lib/libc/rpc/LICENSE
+ *
+ * Software distributed under the License is distributed on
+ * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either
+ * express or implied. See the License for the specific
+ * language governing rights and limitations under the License.
+ *
+ * The Original Code is Copyright 1998 by Sun Microsystems, Inc
+ *
+ * The Initial Developer of the Original Code is: Sun
+ * Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
* media and as a part of the software program in whole or part. Users
@@ -29,7 +46,7 @@
* Mountain View, California 94043
*/
-/* #ident "@(#)clnt_generic.c 1.20 94/05/03 SMI" */
+/* #ident "@(#)clnt_generic.c 1.40 99/04/21 SMI" */
#if defined(LIBC_SCCS) && !defined(lint)
/*static char *sccsid = "from: @(#)clnt_generic.c 1.4 87/08/11 (C) 1987 SMI";*/
@@ -39,17 +56,20 @@
__FBSDID("$FreeBSD$");
/*
- * Copyright (c) 1986-1991 by Sun Microsystems Inc.
+ * Copyright (c) 1986-1996,1998 by Sun Microsystems, Inc.
+ * All rights reserved.
*/
#include "namespace.h"
#include "reentrant.h"
#include <sys/types.h>
+#include <sys/fcntl.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <stdio.h>
#include <errno.h>
#include <netdb.h>
+#include <syslog.h>
#include <rpc/rpc.h>
#include <rpc/nettype.h>
#include <string.h>
@@ -58,55 +78,79 @@ __FBSDID("$FreeBSD$");
#include "un-namespace.h"
#include "rpc_com.h"
+extern bool_t __rpc_is_local_host(const char *);
+int __rpc_raise_fd(int);
+
+#ifndef NETIDLEN
+#define NETIDLEN 32
+#endif
+
+
/*
* Generic client creation with version checking the value of
* vers_out is set to the highest server supported value
* vers_low <= vers_out <= vers_high AND an error results
* if this can not be done.
+ *
+ * It calls clnt_create_vers_timed() with a NULL value for the timeout
+ * pointer, which indicates that the default timeout should be used.
*/
CLIENT *
-clnt_create_vers(hostname, prog, vers_out, vers_low, vers_high, nettype)
- const char *hostname;
- rpcprog_t prog;
- rpcvers_t *vers_out;
- rpcvers_t vers_low;
- rpcvers_t vers_high;
- const char *nettype;
+clnt_create_vers(const char *hostname, rpcprog_t prog, rpcvers_t *vers_out,
+ rpcvers_t vers_low, rpcvers_t vers_high, const char *nettype)
+{
+
+ return (clnt_create_vers_timed(hostname, prog, vers_out, vers_low,
+ vers_high, nettype, NULL));
+}
+
+/*
+ * This the routine has the same definition as clnt_create_vers(),
+ * except it takes an additional timeout parameter - a pointer to
+ * a timeval structure. A NULL value for the pointer indicates
+ * that the default timeout value should be used.
+ */
+CLIENT *
+clnt_create_vers_timed(const char *hostname, rpcprog_t prog,
+ rpcvers_t *vers_out, rpcvers_t vers_low, rpcvers_t vers_high,
+ const char *nettype, const struct timeval *tp)
{
CLIENT *clnt;
struct timeval to;
enum clnt_stat rpc_stat;
struct rpc_err rpcerr;
- clnt = clnt_create(hostname, prog, vers_high, nettype);
+ clnt = clnt_create_timed(hostname, prog, vers_high, nettype, tp);
if (clnt == NULL) {
return (NULL);
}
to.tv_sec = 10;
to.tv_usec = 0;
- rpc_stat = clnt_call(clnt, NULLPROC, (xdrproc_t) xdr_void,
- (char *) NULL, (xdrproc_t) xdr_void, (char *) NULL, to);
+ rpc_stat = clnt_call(clnt, NULLPROC, (xdrproc_t)xdr_void,
+ (char *)NULL, (xdrproc_t)xdr_void, (char *)NULL, to);
if (rpc_stat == RPC_SUCCESS) {
*vers_out = vers_high;
return (clnt);
}
- if (rpc_stat == RPC_PROGVERSMISMATCH) {
- unsigned long minvers, maxvers;
+ while (rpc_stat == RPC_PROGVERSMISMATCH && vers_high > vers_low) {
+ unsigned int minvers, maxvers;
clnt_geterr(clnt, &rpcerr);
minvers = rpcerr.re_vers.low;
maxvers = rpcerr.re_vers.high;
if (maxvers < vers_high)
- vers_high = (rpcvers_t)maxvers;
+ vers_high = maxvers;
+ else
+ vers_high--;
if (minvers > vers_low)
- vers_low = (rpcvers_t)minvers;
+ vers_low = minvers;
if (vers_low > vers_high) {
goto error;
}
- CLNT_CONTROL(clnt, CLSET_VERS, (char *)(void *)&vers_high);
- rpc_stat = clnt_call(clnt, NULLPROC, (xdrproc_t) xdr_void,
- (char *) NULL, (xdrproc_t) xdr_void,
- (char *) NULL, to);
+ CLNT_CONTROL(clnt, CLSET_VERS, (char *)&vers_high);
+ rpc_stat = clnt_call(clnt, NULLPROC, (xdrproc_t)xdr_void,
+ (char *)NULL, (xdrproc_t)xdr_void,
+ (char *)NULL, to);
if (rpc_stat == RPC_SUCCESS) {
*vers_out = vers_high;
return (clnt);
@@ -132,23 +176,48 @@ error:
* XXX The error message in the case of failure will be the one
* pertaining to the last create error.
*
- * It calls clnt_tp_create();
+ * It calls clnt_create_timed() with the default timeout.
*/
CLIENT *
-clnt_create(hostname, prog, vers, nettype)
- const char *hostname; /* server name */
- rpcprog_t prog; /* program number */
- rpcvers_t vers; /* version number */
- const char *nettype; /* net type */
+clnt_create(const char *hostname, rpcprog_t prog, rpcvers_t vers,
+ const char *nettype)
+{
+
+ return (clnt_create_timed(hostname, prog, vers, nettype, NULL));
+}
+
+/*
+ * This the routine has the same definition as clnt_create(),
+ * except it takes an additional timeout parameter - a pointer to
+ * a timeval structure. A NULL value for the pointer indicates
+ * that the default timeout value should be used.
+ *
+ * This function calls clnt_tp_create_timed().
+ */
+CLIENT *
+clnt_create_timed(const char *hostname, rpcprog_t prog, rpcvers_t vers,
+ const char *netclass, const struct timeval *tp)
{
struct netconfig *nconf;
CLIENT *clnt = NULL;
void *handle;
enum clnt_stat save_cf_stat = RPC_SUCCESS;
struct rpc_err save_cf_error;
+ char nettype_array[NETIDLEN];
+ char *nettype = &nettype_array[0];
+ if (netclass == NULL)
+ nettype = NULL;
+ else {
+ size_t len = strlen(netclass);
+ if (len >= sizeof (nettype_array)) {
+ rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
+ return (NULL);
+ }
+ strcpy(nettype, netclass);
+ }
- if ((handle = __rpc_setconf(nettype)) == NULL) {
+ if ((handle = __rpc_setconf((char *)nettype)) == NULL) {
rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
return (NULL);
}
@@ -162,7 +231,7 @@ clnt_create(hostname, prog, vers, nettype)
#ifdef CLNT_DEBUG
printf("trying netid %s\n", nconf->nc_netid);
#endif
- clnt = clnt_tp_create(hostname, prog, vers, nconf);
+ clnt = clnt_tp_create_timed(hostname, prog, vers, nconf, tp);
if (clnt)
break;
else
@@ -178,9 +247,12 @@ clnt_create(hostname, prog, vers, nettype)
* the local loopbacks are typically the
* last ones in /etc/netconfig and the most
* likely to be unable to translate a host
- * name).
+ * name). We also check for a more
+ * meaningful error than ``unknown host
+ * name'' for the same reasons.
*/
- if (rpc_createerr.cf_stat != RPC_N2AXLATEFAILURE) {
+ if (rpc_createerr.cf_stat != RPC_N2AXLATEFAILURE &&
+ rpc_createerr.cf_stat != RPC_UNKNOWNHOST) {
save_cf_stat = rpc_createerr.cf_stat;
save_cf_error = rpc_createerr.cf_error;
}
@@ -188,10 +260,11 @@ clnt_create(hostname, prog, vers, nettype)
/*
* Attempt to return an error more specific than ``Name to address
- * translation failed''
+ * translation failed'' or ``unknown host name''
*/
- if ((rpc_createerr.cf_stat == RPC_N2AXLATEFAILURE) &&
- (save_cf_stat != RPC_SUCCESS)) {
+ if ((rpc_createerr.cf_stat == RPC_N2AXLATEFAILURE ||
+ rpc_createerr.cf_stat == RPC_UNKNOWNHOST) &&
+ (save_cf_stat != RPC_SUCCESS)) {
rpc_createerr.cf_stat = save_cf_stat;
rpc_createerr.cf_error = save_cf_error;
}
@@ -203,14 +276,27 @@ clnt_create(hostname, prog, vers, nettype)
* Generic client creation: takes (servers name, program-number, netconf) and
* returns client handle. Default options are set, which the user can
* change using the rpc equivalent of _ioctl()'s : clnt_control()
- * It finds out the server address from rpcbind and calls clnt_tli_create()
+ * It finds out the server address from rpcbind and calls clnt_tli_create().
+ *
+ * It calls clnt_tp_create_timed() with the default timeout.
*/
CLIENT *
-clnt_tp_create(hostname, prog, vers, nconf)
- const char *hostname; /* server name */
- rpcprog_t prog; /* program number */
- rpcvers_t vers; /* version number */
- const struct netconfig *nconf; /* net config struct */
+clnt_tp_create(const char *hostname, rpcprog_t prog, rpcvers_t vers,
+ const struct netconfig *nconf)
+{
+
+ return (clnt_tp_create_timed(hostname, prog, vers, nconf, NULL));
+}
+
+/*
+ * This has the same definition as clnt_tp_create(), except it
+ * takes an additional parameter - a pointer to a timeval structure.
+ * A NULL value for the timeout pointer indicates that the default
+ * value for the timeout should be used.
+ */
+CLIENT *
+clnt_tp_create_timed(const char *hostname, rpcprog_t prog, rpcvers_t vers,
+ const struct netconfig *nconf, const struct timeval *tp)
{
struct netbuf *svcaddr; /* servers address */
CLIENT *cl = NULL; /* client handle */
@@ -223,8 +309,9 @@ clnt_tp_create(hostname, prog, vers, nconf)
/*
* Get the address of the server
*/
- if ((svcaddr = __rpcb_findaddr(prog, vers, nconf, hostname,
- &cl)) == NULL) {
+ if ((svcaddr = __rpcb_findaddr_timed(prog, vers,
+ (struct netconfig *)nconf, (char *)hostname,
+ &cl, (struct timeval *)tp)) == NULL) {
/* appropriate error number is set by rpcbind libraries */
return (NULL);
}
@@ -260,20 +347,16 @@ clnt_tp_create(hostname, prog, vers, nconf)
* If sizes are 0; appropriate defaults will be chosen.
*/
CLIENT *
-clnt_tli_create(fd, nconf, svcaddr, prog, vers, sendsz, recvsz)
- int fd; /* fd */
- const struct netconfig *nconf; /* netconfig structure */
- const struct netbuf *svcaddr; /* servers address */
- rpcprog_t prog; /* program number */
- rpcvers_t vers; /* version number */
- u_int sendsz; /* send size */
- u_int recvsz; /* recv size */
+clnt_tli_create(int fd, const struct netconfig *nconf,
+ struct netbuf *svcaddr, rpcprog_t prog, rpcvers_t vers,
+ uint sendsz, uint recvsz)
{
CLIENT *cl; /* client handle */
bool_t madefd = FALSE; /* whether fd opened here */
long servtype;
int one = 1;
struct __rpc_sockinfo si;
+ extern int __rpc_minfd;
if (fd == RPC_ANYFD) {
if (nconf == NULL) {
@@ -285,12 +368,12 @@ clnt_tli_create(fd, nconf, svcaddr, prog, vers, sendsz, recvsz)
if (fd == -1)
goto err;
-
+ if (fd < __rpc_minfd)
+ fd = __rpc_raise_fd(fd);
madefd = TRUE;
servtype = nconf->nc_semantics;
if (!__rpc_fd2sockinfo(fd, &si))
goto err;
-
bindresvport(fd, NULL);
} else {
if (!__rpc_fd2sockinfo(fd, &si))
@@ -298,9 +381,8 @@ clnt_tli_create(fd, nconf, svcaddr, prog, vers, sendsz, recvsz)
servtype = __rpc_socktype2seman(si.si_socktype);
if (servtype == -1) {
rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
- return NULL;
+ return (NULL);
}
-
}
if (si.si_af != ((struct sockaddr *)svcaddr->buf)->sa_family) {
@@ -309,14 +391,15 @@ clnt_tli_create(fd, nconf, svcaddr, prog, vers, sendsz, recvsz)
}
switch (servtype) {
- case NC_TPI_COTS_ORD:
+ case NC_TPI_COTS:
cl = clnt_vc_create(fd, svcaddr, prog, vers, sendsz, recvsz);
- if (!nconf || !cl)
- break;
- /* XXX fvdl - is this useful? */
- if (strncmp(nconf->nc_protofmly, "inet", 4) == 0)
+ break;
+ case NC_TPI_COTS_ORD:
+ if (nconf && ((strcmp(nconf->nc_protofmly, "inet") == 0))) {
_setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &one,
sizeof (one));
+ }
+ cl = clnt_vc_create(fd, svcaddr, prog, vers, sendsz, recvsz);
break;
case NC_TPI_CLTS:
cl = clnt_dg_create(fd, svcaddr, prog, vers, sendsz, recvsz);
@@ -336,7 +419,7 @@ clnt_tli_create(fd, nconf, svcaddr, prog, vers, sendsz, recvsz)
}
if (madefd) {
(void) CLNT_CONTROL(cl, CLSET_FD_CLOSE, NULL);
-/* (void) CLNT_CONTROL(cl, CLSET_POP_TIMOD, (char *) NULL); */
+/* (void) CLNT_CONTROL(cl, CLSET_POP_TIMOD, NULL); */
};
return (cl);
@@ -348,3 +431,36 @@ err1: if (madefd)
(void)_close(fd);
return (NULL);
}
+
+/*
+ * To avoid conflicts with the "magic" file descriptors (0, 1, and 2),
+ * we try to not use them. The __rpc_raise_fd() routine will dup
+ * a descriptor to a higher value. If we fail to do it, we continue
+ * to use the old one (and hope for the best).
+ */
+int __rpc_minfd = 3;
+
+int
+__rpc_raise_fd(int fd)
+{
+ int nfd;
+
+ if (fd >= __rpc_minfd)
+ return (fd);
+
+ if ((nfd = _fcntl(fd, F_DUPFD, __rpc_minfd)) == -1)
+ return (fd);
+
+ if (_fsync(nfd) == -1) {
+ _close(nfd);
+ return (fd);
+ }
+
+ if (_close(fd) == -1) {
+ /* this is okay, we will syslog an error, then use the new fd */
+ (void) syslog(LOG_ERR,
+ "could not close() fd %d; mem & fd leak", fd);
+ }
+
+ return (nfd);
+}
diff --git a/lib/libc/rpc/rpc_clnt_create.3 b/lib/libc/rpc/rpc_clnt_create.3
index 4f6e90c..d353168 100644
--- a/lib/libc/rpc/rpc_clnt_create.3
+++ b/lib/libc/rpc/rpc_clnt_create.3
@@ -11,7 +11,9 @@
.Nm rpc_clnt_create ,
.Nm clnt_control ,
.Nm clnt_create ,
+.Nm clnt_create_timed ,
.Nm clnt_create_vers ,
+.Nm clnt_create_vers_timed ,
.Nm clnt_destroy ,
.Nm clnt_dg_create ,
.Nm clnt_pcreateerror ,
@@ -19,6 +21,7 @@
.Nm clnt_spcreateerror ,
.Nm clnt_tli_create ,
.Nm clnt_tp_create ,
+.Nm clnt_tp_create_timed ,
.Nm clnt_vc_create ,
.Nm rpc_createerr
.Nd "library routines for dealing with creation and manipulation of"
@@ -33,7 +36,11 @@ handles
.Ft "CLIENT *"
.Fn clnt_create "const char * host" "const rpcprog_t prognum" "const rpcvers_t versnum" "const char *nettype"
.Ft "CLIENT *"
+.Fn clnt_create_timed "const char * host" "const rpcprog_t prognum" "const rpcvers_t versnum" "const char *nettype" "const struct timeval *timeout"
+.Ft "CLIENT *"
.Fn clnt_create_vers "const char * host" "const rpcprog_t prognum" "rpcvers_t *vers_outp" "const rpcvers_t vers_low" "const rpcvers_t vers_high" "const char *nettype"
+.Ft "CLIENT *"
+.Fn clnt_create_vers_timed "const char * host" "const rpcprog_t prognum" "rpcvers_t *vers_outp" "const rpcvers_t vers_low" "const rpcvers_t vers_high" "char *nettype" "const struct timeval *timeout"
.Ft void
.Fn clnt_destroy "CLIENT *clnt"
.Ft "CLIENT *"
@@ -49,6 +56,8 @@ handles
.Ft "CLIENT *"
.Fn clnt_tp_create "const char * host" "const rpcprog_t prognum" "const rpcvers_t versnum" "const struct netconfig *netconf"
.Ft "CLIENT *"
+.Fn clnt_tp_create_timed "const char * host" "const rpcprog_t prognum" "const rpcvers_t versnum" "const struct netconfig *netconf" "const struct timeval *timeout"
+.Ft "CLIENT *"
.Fn clnt_vc_create "const int fildes" "const struct netbuf *svcaddr" "const rpcprog_t prognum" "const rpcvers_t versnum" "const u_int sendsz" "const u_int recvsz"
.Sh DESCRIPTION
RPC library routines allow C language programs to make procedure
@@ -158,6 +167,17 @@ This mismatch will be discovered by a
.Fn clnt_call
later (see
.Xr rpc_clnt_calls 3 ) .
+.It Fn clnt_create_timed
+Generic client creation routine which is similar to
+.Fn clnt_create
+but which also has the additional parameter
+.Fa timeout
+that specifies the maximum amount of time allowed for
+each transport class tried. In all other respects, the
+.Fn clnt_create_timed
+call behaves exactly like the
+.Fn clnt_create
+call.
.It Fn clnt_create_vers
Generic client creation routine which is similar to
.Fn clnt_create
@@ -213,6 +233,17 @@ However,
does this for you and returns a valid handle
only if a version within
the range supplied is supported by the server.
+.It Fn clnt_create_vers_timed
+Generic client creation routine which is similar to
+.Fn clnt_create_vers
+but which also has the additional parameter
+.Fa timeout
+that specifies the maximum amount of time allowed for
+each transport class tried. In all other respects, the
+.Fn clnt_create_vers_timed
+call behaves exactly like the
+.Fn clnt_create_vers
+call.
.It Fn clnt_destroy
A function macro that destroys the client's RPC handle.
Destruction usually involves deallocation
@@ -393,6 +424,20 @@ if it fails.
The
.Fn clnt_pcreateerror
routine can be used to print the reason for failure.
+.It Fn clnt_tp_create_timed
+Like
+.Fn clnt_tp_create
+except
+.Fn clnt_tp_create_timed
+has the extra parameter
+.Fa timeout
+which specifies the maximum time allowed for
+for the creation attempt to succeed.
+In all other respects, the
+.Fn clnt_tp_create_timed
+call behaves exactly like the
+.Fn clnt_tp_create
+call.
.It Fn clnt_vc_create
This routine creates an RPC
client for the remote program
diff --git a/lib/libc/rpc/rpcb_clnt.c b/lib/libc/rpc/rpcb_clnt.c
index c4db751..b47f36b 100644
--- a/lib/libc/rpc/rpcb_clnt.c
+++ b/lib/libc/rpc/rpcb_clnt.c
@@ -1,6 +1,23 @@
/* $NetBSD: rpcb_clnt.c,v 1.6 2000/07/16 06:41:43 itojun Exp $ */
/*
+ * The contents of this file are subject to the Sun Standards
+ * License Version 1.0 the (the "License";) You may not use
+ * this file except in compliance with the License. You may
+ * obtain a copy of the License at lib/libc/rpc/LICENSE
+ *
+ * Software distributed under the License is distributed on
+ * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either
+ * express or implied. See the License for the specific
+ * language governing rights and limitations under the License.
+ *
+ * The Original Code is Copyright 1998 by Sun Microsystems, Inc
+ *
+ * The Initial Developer of the Original Code is: Sun
+ * Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
* media and as a part of the software program in whole or part. Users
@@ -75,6 +92,7 @@ __FBSDID("$FreeBSD$");
static struct timeval tottimeout = { 60, 0 };
static const struct timeval rmttimeout = { 3, 0 };
+static struct timeval rpcbrmttime = { 15, 0 };
extern bool_t xdr_wrapstring(XDR *, char **);
@@ -654,6 +672,47 @@ got_entry(relp, nconf)
}
/*
+ * Quick check to see if rpcbind is up. Tries to connect over
+ * local transport.
+ */
+bool_t
+__rpcbind_is_up()
+{
+ struct netconfig *nconf;
+ struct sockaddr_un sun;
+ void *localhandle;
+ int sock;
+
+ nconf = NULL;
+ localhandle = setnetconfig();
+ while (nconf = getnetconfig(localhandle)){
+ if (nconf->nc_protofmly != NULL &&
+ strcmp(nconf->nc_protofmly, NC_LOOPBACK) == 0)
+ break;
+ }
+ if (nconf == NULL)
+ return (FALSE);
+
+ endnetconfig(localhandle);
+
+ memset(&sun, 0, sizeof sun);
+ sock = _socket(AF_LOCAL, SOCK_STREAM, 0);
+ if (sock < 0)
+ return (FALSE);
+ sun.sun_family = AF_LOCAL;
+ strncpy(sun.sun_path, _PATH_RPCBINDSOCK, sizeof(sun.sun_path));
+ sun.sun_len = SUN_LEN(&sun);
+
+ if (_connect(sock, (struct sockaddr *)&sun, sun.sun_len) < 0) {
+ _close(sock);
+ return (FALSE);
+ }
+
+ _close(sock);
+ return (TRUE);
+}
+
+/*
* An internal function which optimizes rpcb_getaddr function. It also
* returns the client handle that it uses to contact the remote rpcbind.
*
@@ -672,13 +731,15 @@ got_entry(relp, nconf)
* starts working properly. Also look under clnt_vc.c.
*/
struct netbuf *
-__rpcb_findaddr(program, version, nconf, host, clpp)
+__rpcb_findaddr_timed(program, version, nconf, host, clpp, tp)
rpcprog_t program;
rpcvers_t version;
const struct netconfig *nconf;
const char *host;
CLIENT **clpp;
+ struct timeval *tp;
{
+ static bool_t check_rpcbind = TRUE;
CLIENT *client = NULL;
RPCB parms;
enum clnt_stat clnt_st;
@@ -696,6 +757,12 @@ __rpcb_findaddr(program, version, nconf, host, clpp)
parms.r_addr = NULL;
+ /*
+ * Use default total timeout if no timeout is specified.
+ */
+ if (tp == NULL)
+ tp = &tottimeout;
+
#ifdef PORTMAP
/* Try version 2 for TCP or UDP */
if (strcmp(nconf->nc_protofmly, NC_INET) == 0) {
@@ -710,22 +777,31 @@ __rpcb_findaddr(program, version, nconf, host, clpp)
*/
if (strcmp(nconf->nc_proto, NC_TCP) == 0) {
struct netconfig *newnconf;
+ void *handle;
- if ((newnconf = getnetconfigent("udp")) == NULL) {
+ if ((handle = getnetconfigent("udp")) == NULL) {
+ rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
+ return (NULL);
+ }
+ if ((newnconf = __rpc_getconf(handle)) == NULL) {
+ __rpc_endconf(handle);
rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
return (NULL);
}
client = getclnthandle(host, newnconf, &parms.r_addr);
- freenetconfigent(newnconf);
+ __rpc_endconf(handle);
} else {
client = getclnthandle(host, nconf, &parms.r_addr);
}
- if (client == NULL) {
+ if (client == NULL)
return (NULL);
- }
- /* Set the version */
- CLNT_CONTROL(client, CLSET_VERS, (char *)(void *)&pmapvers);
+ /*
+ * Set version and retry timeout.
+ */
+ CLNT_CONTROL(client, CLSET_RETRY_TIMEOUT, (char *)&rpcbrmttime);
+ CLNT_CONTROL(client, CLSET_VERS, (char *)&pmapvers);
+
pmapparms.pm_prog = program;
pmapparms.pm_vers = version;
pmapparms.pm_prot = strcmp(nconf->nc_proto, NC_TCP) ?
@@ -734,7 +810,7 @@ __rpcb_findaddr(program, version, nconf, host, clpp)
clnt_st = CLNT_CALL(client, (rpcproc_t)PMAPPROC_GETPORT,
(xdrproc_t) xdr_pmap, (caddr_t)(void *)&pmapparms,
(xdrproc_t) xdr_u_short, (caddr_t)(void *)&port,
- tottimeout);
+ *tp);
if (clnt_st != RPC_SUCCESS) {
if ((clnt_st == RPC_PROGVERSMISMATCH) ||
(clnt_st == RPC_PROGUNAVAIL))
@@ -748,7 +824,7 @@ __rpcb_findaddr(program, version, nconf, host, clpp)
goto error;
}
port = htons(port);
- CLNT_CONTROL(client, CLGET_SVC_ADDR, (char *)(void *)&remote);
+ CLNT_CONTROL(client, CLGET_SVC_ADDR, (char *)&remote);
if (((address = (struct netbuf *)
malloc(sizeof (struct netbuf))) == NULL) ||
((address->buf = (char *)
@@ -771,6 +847,20 @@ __rpcb_findaddr(program, version, nconf, host, clpp)
try_rpcbind:
/*
+ * Check if rpcbind is up. This prevents needless delays when
+ * accessing applications such as the keyserver while booting
+ * disklessly.
+ */
+ if (check_rpcbind && strcmp(nconf->nc_protofmly, NC_LOOPBACK) == 0) {
+ if (!__rpcbind_is_up()) {
+ rpc_createerr.cf_stat = RPC_PMAPFAILURE;
+ rpc_createerr.cf_error.re_errno = 0;
+ goto error;
+ }
+ check_rpcbind = FALSE;
+ }
+
+ /*
* Now we try version 4 and then 3.
* We also send the remote system the address we used to
* contact it in case it can help to connect back with us
@@ -785,33 +875,17 @@ try_rpcbind:
/*
* If a COTS transport is being used, try getting address via CLTS
* transport. This works only with version 4.
- * NOTE: This is being done for all transports EXCEPT LOOPBACK
- * because with loopback the cost to go to a COTS is same as
- * the cost to go through CLTS, plus you get the advantage of
- * finding out immediately if the local rpcbind process is dead.
*/
-#if 1
- if ((nconf->nc_semantics == NC_TPI_COTS_ORD ||
- nconf->nc_semantics == NC_TPI_COTS) &&
- (strcmp(nconf->nc_protofmly, NC_LOOPBACK) != 0)) {
-#else
- if (client != NULL) {
- CLNT_DESTROY(client);
- client = NULL;
- }
- if (nconf->nc_semantics == NC_TPI_CLTS) {
-#endif
+ if (nconf->nc_semantics == NC_TPI_COTS_ORD ||
+ nconf->nc_semantics == NC_TPI_COTS) {
+
void *handle;
struct netconfig *nconf_clts;
rpcb_entry_list_ptr relp = NULL;
if (client == NULL) {
/* This did not go through the above PORTMAP/TCP code */
-#if 1
if ((handle = __rpc_setconf("datagram_v")) != NULL) {
-#else
- if ((handle = __rpc_setconf("circuit_v")) != NULL) {
-#endif
while ((nconf_clts = __rpc_getconf(handle))
!= NULL) {
if (strcmp(nconf_clts->nc_protofmly,
@@ -839,10 +913,13 @@ try_rpcbind:
/*LINTED const castaway*/
parms.r_addr = (char *) &nullstring[0]; /* for XDRing */
}
+
+ CLNT_CONTROL(client, CLSET_RETRY_TIMEOUT, (char *)&rpcbrmttime);
+
clnt_st = CLNT_CALL(client, (rpcproc_t)RPCBPROC_GETADDRLIST,
(xdrproc_t) xdr_rpcb, (char *)(void *)&parms,
(xdrproc_t) xdr_rpcb_entry_list_ptr,
- (char *)(void *)&relp, tottimeout);
+ (char *)(void *)&relp, *tp);
if (clnt_st == RPC_SUCCESS) {
if ((address = got_entry(relp, nconf)) != NULL) {
xdr_free((xdrproc_t) xdr_rpcb_entry_list_ptr,
@@ -873,12 +950,8 @@ try_rpcbind:
regular_rpcbind:
/* Now the same transport is to be used to get the address */
-#if 1
if (client && ((nconf->nc_semantics == NC_TPI_COTS_ORD) ||
(nconf->nc_semantics == NC_TPI_COTS))) {
-#else
- if (client && nconf->nc_semantics == NC_TPI_CLTS) {
-#endif
/* A CLTS type of client - destroy it */
CLNT_DESTROY(client);
client = NULL;
@@ -896,13 +969,14 @@ regular_rpcbind:
}
/* First try from start_vers and then version 3 (RPCBVERS) */
+
+ CLNT_CONTROL(client, CLSET_RETRY_TIMEOUT, (char *) &rpcbrmttime);
for (vers = start_vers; vers >= RPCBVERS; vers--) {
/* Set the version */
CLNT_CONTROL(client, CLSET_VERS, (char *)(void *)&vers);
clnt_st = CLNT_CALL(client, (rpcproc_t)RPCBPROC_GETADDR,
(xdrproc_t) xdr_rpcb, (char *)(void *)&parms,
- (xdrproc_t) xdr_wrapstring, (char *)(void *) &ua,
- tottimeout);
+ (xdrproc_t) xdr_wrapstring, (char *)(void *) &ua, *tp);
if (clnt_st == RPC_SUCCESS) {
if ((ua == NULL) || (ua[0] == NULL)) {
/* address unknown */
@@ -989,8 +1063,9 @@ rpcb_getaddr(program, version, nconf, address, host)
{
struct netbuf *na;
- if ((na = __rpcb_findaddr(program, version, nconf,
- host, (CLIENT **) NULL)) == NULL)
+ if ((na = __rpcb_findaddr_timed(program, version,
+ (struct netconfig *) nconf, (char *) host,
+ (CLIENT **) NULL, (struct timeval *) NULL)) == NULL)
return (FALSE);
if (na->len > address->maxlen) {
OpenPOWER on IntegriCloud