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
This commit is contained in:
Alfred Perlstein 2002-07-11 16:23:04 +00:00
parent 9fb9141723
commit 4e37855e01
6 changed files with 737 additions and 105 deletions

View File

@ -1,6 +1,23 @@
/* $NetBSD: clnt.h,v 1.14 2000/06/02 22:57:55 fvdl 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
@ -36,7 +53,8 @@
/*
* clnt.h - Client side remote procedure call interface.
*
* Copyright (C) 1984, Sun Microsystems, Inc.
* Copyright (c) 1986-1991,1994-1999 by Sun Microsystems, Inc.
* All rights reserved.
*/
#ifndef _RPC_CLNT_H_
@ -257,6 +275,7 @@ struct rpc_timers {
#define NULLPROC ((rpcproc_t)0)
__BEGIN_DECLS
/*
* Below are the client handle creation routines for the various
* implementations of client side rpc. They can return NULL if a
@ -266,12 +285,6 @@ struct rpc_timers {
/*
* Generic client creation routine. Supported protocols are those that
* belong to the nettype namespace (/etc/netconfig).
* CLIENT *
* clnt_create(host, prog, vers, prot);
* const char *host; -- hostname
* const rpcprog_t prog; -- program number
* const rpcvers_t vers; -- version number
* const char *prot; -- protocol
*/
__BEGIN_DECLS
extern CLIENT *clnt_create(const char *, const rpcprog_t, const rpcvers_t,
@ -284,6 +297,21 @@ extern CLIENT *clnt_create(const char *, const rpcprog_t, const rpcvers_t,
* const char *nettype; -- network type
*/
/*
* Generic client creation routine. Just like clnt_create(), except
* it takes an additional timeout parameter.
*/
extern CLIENT * clnt_create_timed(const char *, const rpcprog_t,
const rpcvers_t, const char *, const struct timeval *);
/*
*
* const char *hostname; -- hostname
* const rpcprog_t prog; -- program number
* const rpcvers_t vers; -- version number
* const char *nettype; -- network type
* const struct timeval *tp; -- timeout
*/
/*
* Generic client creation routine. Supported protocols are which belong
* to the nettype name space.
@ -300,6 +328,22 @@ extern CLIENT *clnt_create_vers(const char *, const rpcprog_t, rpcvers_t *,
* const char *nettype; -- network type
*/
/*
* Generic client creation routine. Supported protocols are which belong
* to the nettype name space.
*/
extern CLIENT * clnt_create_vers_timed(const char *, const rpcprog_t,
rpcvers_t *, const rpcvers_t, const rpcvers_t, const char *,
const struct timeval *);
/*
* const char *host; -- hostname
* const rpcprog_t prog; -- program number
* rpcvers_t *vers_out; -- servers highest available version
* const rpcvers_t vers_low; -- low version number
* const rpcvers_t vers_high; -- high version number
* const char *nettype; -- network type
* const struct timeval *tp -- timeout
*/
/*
* Generic client creation routine. It takes a netconfig structure
@ -314,17 +358,31 @@ extern CLIENT *clnt_tp_create(const char *, const rpcprog_t,
* const struct netconfig *netconf; -- network config structure
*/
/*
* Generic client creation routine. Just like clnt_tp_create(), except
* it takes an additional timeout parameter.
*/
extern CLIENT * clnt_tp_create_timed(const char *, const rpcprog_t,
const rpcvers_t, const struct netconfig *, const struct timeval *);
/*
* const char *hostname; -- hostname
* const rpcprog_t prog; -- program number
* const rpcvers_t vers; -- version number
* const struct netconfig *netconf; -- network config structure
* const struct timeval *tp -- timeout
*/
/*
* Generic TLI create routine. Only provided for compatibility.
*/
extern CLIENT *clnt_tli_create(const int, const struct netconfig *,
const struct netbuf *, const rpcprog_t,
struct netbuf *, const rpcprog_t,
const rpcvers_t, const u_int, const u_int);
/*
* const register int fd; -- fd
* const struct netconfig *nconf; -- netconfig structure
* const struct netbuf *svcaddr; -- servers address
* struct netbuf *svcaddr; -- servers address
* const u_long prog; -- program number
* const u_long vers; -- version number
* const u_int sendsz; -- send size

335
lib/libc/rpc/LICENSE Normal file
View File

@ -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

View File

@ -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 \

View File

@ -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 @@ clnt_create_vers(hostname, prog, vers_out, vers_low, vers_high, nettype)
* 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);
}

View File

@ -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

View File

@ -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 **);
@ -653,6 +671,47 @@ got_entry(relp, nconf)
return (na);
}
/*
* 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 *)
@ -770,6 +846,20 @@ __rpcb_findaddr(program, version, nconf, host, clpp)
#endif /* PORTMAP */
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
@ -785,33 +875,17 @@ __rpcb_findaddr(program, version, nconf, host, clpp)
/*
* 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 @@ __rpcb_findaddr(program, version, nconf, host, clpp)
/*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 @@ __rpcb_findaddr(program, version, nconf, host, clpp)
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 @@ __rpcb_findaddr(program, version, nconf, host, clpp)
}
/* 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) {