Index: freebsd/lib/libc/rpc/auth_des.c
===================================================================
--- freebsd/lib/libc/rpc/auth_des.c	(revision 60b1d40751c8b3235b7ccbf3bb6ad0c562562f01)
+++ freebsd/lib/libc/rpc/auth_des.c	(revision 60b1d40751c8b3235b7ccbf3bb6ad0c562562f01)
@@ -0,0 +1,499 @@
+#include <machine/rtems-bsd-user-space.h>
+
+/*-
+ * Copyright (c) 2009, Sun Microsystems, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions are met:
+ * - Redistributions of source code must retain the above copyright notice, 
+ *   this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice, 
+ *   this list of conditions and the following disclaimer in the documentation 
+ *   and/or other materials provided with the distribution.
+ * - Neither the name of Sun Microsystems, Inc. nor the names of its 
+ *   contributors may be used to endorse or promote products derived 
+ *   from this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * Copyright (c) 1988 by Sun Microsystems, Inc.
+ */
+/*
+ * auth_des.c, client-side implementation of DES authentication
+ */
+
+#include "namespace.h"
+#include "reentrant.h"
+#include <err.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/cdefs.h>
+#include <rpc/des_crypt.h>
+#include <syslog.h>
+#include <rpc/types.h>
+#include <rpc/auth.h>
+#include <rpc/auth_des.h>
+#include <rpc/clnt.h>
+#include <rpc/xdr.h>
+#include <sys/socket.h>
+#undef NIS
+#include <rpcsvc/nis.h>
+#include "un-namespace.h"
+#include "mt_misc.h"
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = 	"@(#)auth_des.c	2.2 88/07/29 4.0 RPCSRC; from 1.9 88/02/08 SMI";
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#define USEC_PER_SEC		1000000
+#define RTIME_TIMEOUT		5	/* seconds to wait for sync */
+
+#define AUTH_PRIVATE(auth)	(struct ad_private *) auth->ah_private
+#define ALLOC(object_type)	(object_type *) mem_alloc(sizeof(object_type))
+#define FREE(ptr, size)		mem_free((char *)(ptr), (int) size)
+#define ATTEMPT(xdr_op)		if (!(xdr_op)) return (FALSE)
+
+extern bool_t xdr_authdes_cred( XDR *, struct authdes_cred *);
+extern bool_t xdr_authdes_verf( XDR *, struct authdes_verf *);
+extern int key_encryptsession_pk();
+
+extern bool_t __rpc_get_time_offset(struct timeval *, nis_server *, char *,
+	char **, char **);
+
+/* 
+ * DES authenticator operations vector
+ */
+static void	authdes_nextverf(AUTH *);
+static bool_t	authdes_marshal(AUTH *, XDR *);
+static bool_t	authdes_validate(AUTH *, struct opaque_auth *);
+static bool_t	authdes_refresh(AUTH *, void *);
+static void	authdes_destroy(AUTH *);
+
+static struct auth_ops *authdes_ops(void);
+
+/*
+ * This struct is pointed to by the ah_private field of an "AUTH *"
+ */
+struct ad_private {
+	char *ad_fullname; 		/* client's full name */
+	u_int ad_fullnamelen;		/* length of name, rounded up */
+	char *ad_servername; 		/* server's full name */
+	u_int ad_servernamelen;		/* length of name, rounded up */
+	u_int ad_window;	  	/* client specified window */
+	bool_t ad_dosync;		/* synchronize? */		
+	struct netbuf ad_syncaddr;	/* remote host to synch with */
+	char *ad_timehost;		/* remote host to synch with */
+	struct timeval ad_timediff;	/* server's time - client's time */
+	u_int ad_nickname;		/* server's nickname for client */
+	struct authdes_cred ad_cred;	/* storage for credential */
+	struct authdes_verf ad_verf;	/* storage for verifier */
+	struct timeval ad_timestamp;	/* timestamp sent */
+	des_block ad_xkey;		/* encrypted conversation key */
+	u_char ad_pkey[1024];		/* Server's actual public key */
+	char *ad_netid;			/* Timehost netid */
+	char *ad_uaddr;			/* Timehost uaddr */
+	nis_server *ad_nis_srvr;	/* NIS+ server struct */
+};
+
+AUTH *authdes_pk_seccreate(const char *, netobj *, u_int, const char *,
+	const des_block *, nis_server *);
+	
+/*
+ * documented version of authdes_seccreate
+ */
+/*
+	servername:	network name of server
+	win:		time to live
+	timehost:	optional hostname to sync with
+	ckey:		optional conversation key to use
+*/
+
+AUTH *
+authdes_seccreate(const char *servername, const u_int win,
+	const char *timehost, const des_block *ckey)
+{
+	u_char  pkey_data[1024];
+	netobj  pkey;
+	AUTH    *dummy;
+
+	if (! getpublickey(servername, (char *) pkey_data)) {
+		syslog(LOG_ERR,
+		    "authdes_seccreate: no public key found for %s",
+		    servername);
+		return (NULL);
+	}
+
+	pkey.n_bytes = (char *) pkey_data;
+	pkey.n_len = (u_int)strlen((char *)pkey_data) + 1;
+	dummy = authdes_pk_seccreate(servername, &pkey, win, timehost,
+	    ckey, NULL);
+	return (dummy);
+}
+
+/*
+ * Slightly modified version of authdessec_create which takes the public key
+ * of the server principal as an argument. This spares us a call to
+ * getpublickey() which in the nameserver context can cause a deadlock.
+ */
+AUTH *
+authdes_pk_seccreate(const char *servername, netobj *pkey, u_int window,
+	const char *timehost, const des_block *ckey, nis_server *srvr)
+{
+	AUTH *auth;
+	struct ad_private *ad;
+	char namebuf[MAXNETNAMELEN+1];
+
+	/*
+	 * Allocate everything now
+	 */
+	auth = ALLOC(AUTH);
+	if (auth == NULL) {
+		syslog(LOG_ERR, "authdes_pk_seccreate: out of memory");
+		return (NULL);
+	}
+	ad = ALLOC(struct ad_private);
+	if (ad == NULL) {
+		syslog(LOG_ERR, "authdes_pk_seccreate: out of memory");
+		goto failed;
+	}
+	ad->ad_fullname = ad->ad_servername = NULL; /* Sanity reasons */
+	ad->ad_timehost = NULL;
+	ad->ad_netid = NULL;
+	ad->ad_uaddr = NULL;
+	ad->ad_nis_srvr = NULL;
+	ad->ad_timediff.tv_sec = 0;
+	ad->ad_timediff.tv_usec = 0;
+	memcpy(ad->ad_pkey, pkey->n_bytes, pkey->n_len);
+	if (!getnetname(namebuf))
+		goto failed;
+	ad->ad_fullnamelen = RNDUP((u_int) strlen(namebuf));
+	ad->ad_fullname = (char *)mem_alloc(ad->ad_fullnamelen + 1);
+	ad->ad_servernamelen = strlen(servername);
+	ad->ad_servername = (char *)mem_alloc(ad->ad_servernamelen + 1);
+
+	if (ad->ad_fullname == NULL || ad->ad_servername == NULL) {
+		syslog(LOG_ERR, "authdes_seccreate: out of memory");
+		goto failed;
+	}
+	if (timehost != NULL) {
+		ad->ad_timehost = (char *)mem_alloc(strlen(timehost) + 1);
+		if (ad->ad_timehost == NULL) {
+			syslog(LOG_ERR, "authdes_seccreate: out of memory");
+			goto failed;
+		}
+		memcpy(ad->ad_timehost, timehost, strlen(timehost) + 1);
+		ad->ad_dosync = TRUE;
+	} else if (srvr != NULL) {
+		ad->ad_nis_srvr = srvr;	/* transient */
+		ad->ad_dosync = TRUE;
+	} else {
+		ad->ad_dosync = FALSE;
+	}
+	memcpy(ad->ad_fullname, namebuf, ad->ad_fullnamelen + 1);
+	memcpy(ad->ad_servername, servername, ad->ad_servernamelen + 1);
+	ad->ad_window = window;
+	if (ckey == NULL) {
+		if (key_gendes(&auth->ah_key) < 0) {
+			syslog(LOG_ERR,
+	    "authdes_seccreate: keyserv(1m) is unable to generate session key");
+			goto failed;
+		}
+	} else {
+		auth->ah_key = *ckey;
+	}
+
+	/*
+	 * Set up auth handle
+	 */
+	auth->ah_cred.oa_flavor = AUTH_DES;
+	auth->ah_verf.oa_flavor = AUTH_DES;
+	auth->ah_ops = authdes_ops();
+	auth->ah_private = (caddr_t)ad;
+
+	if (!authdes_refresh(auth, NULL)) {
+		goto failed;
+	}
+	ad->ad_nis_srvr = NULL; /* not needed any longer */
+	return (auth);
+
+failed:
+	if (auth)
+		FREE(auth, sizeof (AUTH));
+	if (ad) {
+		if (ad->ad_fullname)
+			FREE(ad->ad_fullname, ad->ad_fullnamelen + 1);
+		if (ad->ad_servername)
+			FREE(ad->ad_servername, ad->ad_servernamelen + 1);
+		if (ad->ad_timehost)
+			FREE(ad->ad_timehost, strlen(ad->ad_timehost) + 1);
+		if (ad->ad_netid)
+			FREE(ad->ad_netid, strlen(ad->ad_netid) + 1);
+		if (ad->ad_uaddr)
+			FREE(ad->ad_uaddr, strlen(ad->ad_uaddr) + 1);
+		FREE(ad, sizeof (struct ad_private));
+	}
+	return (NULL);
+}
+
+/*
+ * Implement the five authentication operations
+ */
+
+
+/*
+ * 1. Next Verifier
+ */	
+/*ARGSUSED*/
+static void
+authdes_nextverf(AUTH *auth)
+{
+	/* what the heck am I supposed to do??? */
+}
+
+
+/*
+ * 2. Marshal
+ */
+static bool_t
+authdes_marshal(AUTH *auth, XDR *xdrs)
+{
+/* LINTED pointer alignment */
+	struct ad_private *ad = AUTH_PRIVATE(auth);
+	struct authdes_cred *cred = &ad->ad_cred;
+	struct authdes_verf *verf = &ad->ad_verf;
+	des_block cryptbuf[2];	
+	des_block ivec;
+	int status;
+	int len;
+	rpc_inline_t *ixdr;
+
+	/*
+	 * Figure out the "time", accounting for any time difference
+	 * with the server if necessary.
+	 */
+	(void) gettimeofday(&ad->ad_timestamp, (struct timezone *)NULL);
+	ad->ad_timestamp.tv_sec += ad->ad_timediff.tv_sec;
+	ad->ad_timestamp.tv_usec += ad->ad_timediff.tv_usec;
+	while (ad->ad_timestamp.tv_usec >= USEC_PER_SEC) {
+		ad->ad_timestamp.tv_usec -= USEC_PER_SEC;
+		ad->ad_timestamp.tv_sec++;
+	}
+
+	/*
+	 * XDR the timestamp and possibly some other things, then
+	 * encrypt them.
+	 */
+	ixdr = (rpc_inline_t *)cryptbuf;
+	IXDR_PUT_INT32(ixdr, ad->ad_timestamp.tv_sec);
+	IXDR_PUT_INT32(ixdr, ad->ad_timestamp.tv_usec);
+	if (ad->ad_cred.adc_namekind == ADN_FULLNAME) {
+		IXDR_PUT_U_INT32(ixdr, ad->ad_window);
+		IXDR_PUT_U_INT32(ixdr, ad->ad_window - 1);
+		ivec.key.high = ivec.key.low = 0;	
+		status = cbc_crypt((char *)&auth->ah_key, (char *)cryptbuf, 
+			(u_int) 2 * sizeof (des_block),
+			DES_ENCRYPT | DES_HW, (char *)&ivec);
+	} else {
+		status = ecb_crypt((char *)&auth->ah_key, (char *)cryptbuf, 
+			(u_int) sizeof (des_block),
+			DES_ENCRYPT | DES_HW);
+	}
+	if (DES_FAILED(status)) {
+		syslog(LOG_ERR, "authdes_marshal: DES encryption failure");
+		return (FALSE);
+	}
+	ad->ad_verf.adv_xtimestamp = cryptbuf[0];
+	if (ad->ad_cred.adc_namekind == ADN_FULLNAME) {
+		ad->ad_cred.adc_fullname.window = cryptbuf[1].key.high;
+		ad->ad_verf.adv_winverf = cryptbuf[1].key.low;
+	} else {
+		ad->ad_cred.adc_nickname = ad->ad_nickname;
+		ad->ad_verf.adv_winverf = 0;
+	}
+
+	/*
+	 * Serialize the credential and verifier into opaque
+	 * authentication data.
+	 */
+	if (ad->ad_cred.adc_namekind == ADN_FULLNAME) {
+		len = ((1 + 1 + 2 + 1)*BYTES_PER_XDR_UNIT + ad->ad_fullnamelen);
+	} else {
+		len = (1 + 1)*BYTES_PER_XDR_UNIT;
+	}
+
+	if ((ixdr = xdr_inline(xdrs, 2*BYTES_PER_XDR_UNIT))) {
+		IXDR_PUT_INT32(ixdr, AUTH_DES);
+		IXDR_PUT_INT32(ixdr, len);
+	} else {
+		ATTEMPT(xdr_putint32(xdrs, (int *)&auth->ah_cred.oa_flavor));
+		ATTEMPT(xdr_putint32(xdrs, &len));
+	}
+	ATTEMPT(xdr_authdes_cred(xdrs, cred));
+
+	len = (2 + 1)*BYTES_PER_XDR_UNIT; 
+	if ((ixdr = xdr_inline(xdrs, 2*BYTES_PER_XDR_UNIT))) {
+		IXDR_PUT_INT32(ixdr, AUTH_DES);
+		IXDR_PUT_INT32(ixdr, len);
+	} else {
+		ATTEMPT(xdr_putint32(xdrs, (int *)&auth->ah_verf.oa_flavor));
+		ATTEMPT(xdr_putint32(xdrs, &len));
+	}
+	ATTEMPT(xdr_authdes_verf(xdrs, verf));
+	return (TRUE);
+}
+
+
+/*
+ * 3. Validate
+ */
+static bool_t
+authdes_validate(AUTH *auth, struct opaque_auth *rverf)
+{
+/* LINTED pointer alignment */
+	struct ad_private *ad = AUTH_PRIVATE(auth);
+	struct authdes_verf verf;
+	int status;
+	uint32_t *ixdr;
+	des_block buf;
+
+	if (rverf->oa_length != (2 + 1) * BYTES_PER_XDR_UNIT) {
+		return (FALSE);
+	}
+/* LINTED pointer alignment */
+	ixdr = (uint32_t *)rverf->oa_base;
+	buf.key.high = (uint32_t)*ixdr++;
+	buf.key.low = (uint32_t)*ixdr++;
+	verf.adv_int_u = (uint32_t)*ixdr++;
+
+	/*
+	 * Decrypt the timestamp
+	 */
+	status = ecb_crypt((char *)&auth->ah_key, (char *)&buf,
+		(u_int)sizeof (des_block), DES_DECRYPT | DES_HW);
+
+	if (DES_FAILED(status)) {
+		syslog(LOG_ERR, "authdes_validate: DES decryption failure");
+		return (FALSE);
+	}
+
+	/*
+	 * xdr the decrypted timestamp
+	 */
+/* LINTED pointer alignment */
+	ixdr = (uint32_t *)buf.c;
+	verf.adv_timestamp.tv_sec = IXDR_GET_INT32(ixdr) + 1;
+	verf.adv_timestamp.tv_usec = IXDR_GET_INT32(ixdr);
+
+	/*
+	 * validate
+	 */
+	if (bcmp((char *)&ad->ad_timestamp, (char *)&verf.adv_timestamp,
+		 sizeof(struct timeval)) != 0) {
+		syslog(LOG_DEBUG, "authdes_validate: verifier mismatch");
+		return (FALSE);
+	}
+
+	/*
+	 * We have a nickname now, let's use it
+	 */
+	ad->ad_nickname = verf.adv_nickname;
+	ad->ad_cred.adc_namekind = ADN_NICKNAME;
+	return (TRUE);
+}
+
+/*
+ * 4. Refresh
+ */
+/*ARGSUSED*/
+static bool_t
+authdes_refresh(AUTH *auth, void *dummy)
+{
+/* LINTED pointer alignment */
+	struct ad_private *ad = AUTH_PRIVATE(auth);
+	struct authdes_cred *cred = &ad->ad_cred;
+	int		ok;
+	netobj		pkey;
+
+	if (ad->ad_dosync) {
+                ok = __rpc_get_time_offset(&ad->ad_timediff, ad->ad_nis_srvr,
+		    ad->ad_timehost, &(ad->ad_uaddr),
+		    &(ad->ad_netid));
+		if (! ok) {
+			/*
+			 * Hope the clocks are synced!
+			 */
+			ad->ad_dosync = 0;
+			syslog(LOG_DEBUG,
+			    "authdes_refresh: unable to synchronize clock");
+		 }
+	}
+	ad->ad_xkey = auth->ah_key;
+	pkey.n_bytes = (char *)(ad->ad_pkey);
+	pkey.n_len = (u_int)strlen((char *)ad->ad_pkey) + 1;
+	if (key_encryptsession_pk(ad->ad_servername, &pkey, &ad->ad_xkey) < 0) {
+		syslog(LOG_INFO,
+		    "authdes_refresh: keyserv(1m) is unable to encrypt session key");
+		return (FALSE);
+	}
+	cred->adc_fullname.key = ad->ad_xkey;
+	cred->adc_namekind = ADN_FULLNAME;
+	cred->adc_fullname.name = ad->ad_fullname;
+	return (TRUE);
+}
+
+
+/*
+ * 5. Destroy
+ */
+static void
+authdes_destroy(AUTH *auth)
+{
+/* LINTED pointer alignment */
+	struct ad_private *ad = AUTH_PRIVATE(auth);
+
+	FREE(ad->ad_fullname, ad->ad_fullnamelen + 1);
+	FREE(ad->ad_servername, ad->ad_servernamelen + 1);
+	if (ad->ad_timehost)
+		FREE(ad->ad_timehost, strlen(ad->ad_timehost) + 1);
+	if (ad->ad_netid)
+		FREE(ad->ad_netid, strlen(ad->ad_netid) + 1);
+	if (ad->ad_uaddr)
+		FREE(ad->ad_uaddr, strlen(ad->ad_uaddr) + 1);
+	FREE(ad, sizeof (struct ad_private));
+	FREE(auth, sizeof(AUTH));
+}
+
+static struct auth_ops *
+authdes_ops(void)
+{
+	static struct auth_ops ops;
+
+	/* VARIABLES PROTECTED BY ops_lock: ops */
+ 
+	mutex_lock(&authdes_ops_lock);
+	if (ops.ah_nextverf == NULL) {
+		ops.ah_nextverf = authdes_nextverf;
+		ops.ah_marshal = authdes_marshal;
+		ops.ah_validate = authdes_validate;
+		ops.ah_refresh = authdes_refresh;
+		ops.ah_destroy = authdes_destroy;
+        }
+	mutex_unlock(&authdes_ops_lock);
+	return (&ops);
+}
Index: freebsd/lib/libc/rpc/auth_none.c
===================================================================
--- freebsd/lib/libc/rpc/auth_none.c	(revision 60b1d40751c8b3235b7ccbf3bb6ad0c562562f01)
+++ freebsd/lib/libc/rpc/auth_none.c	(revision 60b1d40751c8b3235b7ccbf3bb6ad0c562562f01)
@@ -0,0 +1,177 @@
+#include <machine/rtems-bsd-user-space.h>
+
+/*	$NetBSD: auth_none.c,v 1.13 2000/01/22 22:19:17 mycroft Exp $	*/
+
+/*-
+ * Copyright (c) 2009, Sun Microsystems, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions are met:
+ * - Redistributions of source code must retain the above copyright notice, 
+ *   this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice, 
+ *   this list of conditions and the following disclaimer in the documentation 
+ *   and/or other materials provided with the distribution.
+ * - Neither the name of Sun Microsystems, Inc. nor the names of its 
+ *   contributors may be used to endorse or promote products derived 
+ *   from this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char *sccsid2 = "@(#)auth_none.c 1.19 87/08/11 Copyr 1984 Sun Micro";
+static char *sccsid = "@(#)auth_none.c	2.1 88/07/29 4.0 RPCSRC";
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * auth_none.c
+ * Creates a client authentication handle for passing "null"
+ * credentials and verifiers to remote systems.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#include "namespace.h"
+#include "reentrant.h"
+#include <assert.h>
+#include <stdlib.h>
+#include <rpc/types.h>
+#include <rpc/xdr.h>
+#include <rpc/auth.h>
+#include "un-namespace.h"
+#include "mt_misc.h"
+
+#define MAX_MARSHAL_SIZE 20
+
+/*
+ * Authenticator operations routines
+ */
+
+static bool_t authnone_marshal (AUTH *, XDR *);
+static void authnone_verf (AUTH *);
+static bool_t authnone_validate (AUTH *, struct opaque_auth *);
+static bool_t authnone_refresh (AUTH *, void *);
+static void authnone_destroy (AUTH *);
+
+extern bool_t xdr_opaque_auth();
+
+static struct auth_ops *authnone_ops();
+
+static struct authnone_private {
+	AUTH	no_client;
+	char	marshalled_client[MAX_MARSHAL_SIZE];
+	u_int	mcnt;
+} *authnone_private;
+
+AUTH *
+authnone_create()
+{
+	struct authnone_private *ap = authnone_private;
+	XDR xdr_stream;
+	XDR *xdrs;
+
+	mutex_lock(&authnone_lock);
+	if (ap == 0) {
+		ap = (struct authnone_private *)calloc(1, sizeof (*ap));
+		if (ap == 0) {
+			mutex_unlock(&authnone_lock);
+			return (0);
+		}
+		authnone_private = ap;
+	}
+	if (!ap->mcnt) {
+		ap->no_client.ah_cred = ap->no_client.ah_verf = _null_auth;
+		ap->no_client.ah_ops = authnone_ops();
+		xdrs = &xdr_stream;
+		xdrmem_create(xdrs, ap->marshalled_client,
+		    (u_int)MAX_MARSHAL_SIZE, XDR_ENCODE);
+		(void)xdr_opaque_auth(xdrs, &ap->no_client.ah_cred);
+		(void)xdr_opaque_auth(xdrs, &ap->no_client.ah_verf);
+		ap->mcnt = XDR_GETPOS(xdrs);
+		XDR_DESTROY(xdrs);
+	}
+	mutex_unlock(&authnone_lock);
+	return (&ap->no_client);
+}
+
+/*ARGSUSED*/
+static bool_t
+authnone_marshal(AUTH *client, XDR *xdrs)
+{
+	struct authnone_private *ap;
+	bool_t dummy;
+
+	assert(xdrs != NULL);
+
+	ap = authnone_private;
+	if (ap == NULL) {
+		mutex_unlock(&authnone_lock);
+		return (FALSE);
+	}
+	dummy = (*xdrs->x_ops->x_putbytes)(xdrs,
+	    ap->marshalled_client, ap->mcnt);
+	mutex_unlock(&authnone_lock);
+	return (dummy);
+}
+
+/* All these unused parameters are required to keep ANSI-C from grumbling */
+/*ARGSUSED*/
+static void
+authnone_verf(AUTH *client)
+{
+}
+
+/*ARGSUSED*/
+static bool_t
+authnone_validate(AUTH *client, struct opaque_auth *opaque)
+{
+
+	return (TRUE);
+}
+
+/*ARGSUSED*/
+static bool_t
+authnone_refresh(AUTH *client, void *dummy)
+{
+
+	return (FALSE);
+}
+
+/*ARGSUSED*/
+static void
+authnone_destroy(AUTH *client)
+{
+}
+
+static struct auth_ops *
+authnone_ops()
+{
+	static struct auth_ops ops;
+ 
+/* VARIABLES PROTECTED BY ops_lock: ops */
+ 
+	mutex_lock(&ops_lock);
+	if (ops.ah_nextverf == NULL) {
+		ops.ah_nextverf = authnone_verf;
+		ops.ah_marshal = authnone_marshal;
+		ops.ah_validate = authnone_validate;
+		ops.ah_refresh = authnone_refresh;
+		ops.ah_destroy = authnone_destroy;
+	}
+	mutex_unlock(&ops_lock);
+	return (&ops);
+}
Index: freebsd/lib/libc/rpc/auth_time.c
===================================================================
--- freebsd/lib/libc/rpc/auth_time.c	(revision 60b1d40751c8b3235b7ccbf3bb6ad0c562562f01)
+++ freebsd/lib/libc/rpc/auth_time.c	(revision 60b1d40751c8b3235b7ccbf3bb6ad0c562562f01)
@@ -0,0 +1,509 @@
+#include <machine/rtems-bsd-user-space.h>
+
+/* #pragma ident	"@(#)auth_time.c	1.4	92/11/10 SMI" */
+
+/*
+ *	auth_time.c
+ *
+ * This module contains the private function __rpc_get_time_offset()
+ * which will return the difference in seconds between the local system's
+ * notion of time and a remote server's notion of time. This must be
+ * possible without calling any functions that may invoke the name
+ * service. (netdir_getbyxxx, getXbyY, etc). The function is used in the
+ * synchronize call of the authdes code to synchronize clocks between
+ * NIS+ clients and their servers.
+ *
+ * Note to minimize the amount of duplicate code, portions of the
+ * synchronize() function were folded into this code, and the synchronize
+ * call becomes simply a wrapper around this function. Further, if this
+ * function is called with a timehost it *DOES* recurse to the name
+ * server so don't use it in that mode if you are doing name service code.
+ *
+ *	Copyright (c) 1992 Sun Microsystems Inc.
+ *	All rights reserved.
+ *
+ * Side effects :
+ *	When called a client handle to a RPCBIND process is created
+ *	and destroyed. Two strings "netid" and "uaddr" are malloc'd
+ *	and returned. The SIGALRM processing is modified only if
+ *	needed to deal with TCP connections.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <stdio.h>
+#include <syslog.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <netdb.h>
+#include <sys/signal.h>
+#include <rtems/bsd/sys/errno.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <rpc/rpc.h>
+#include <rpc/rpc_com.h>
+#include <rpc/rpcb_prot.h>
+#undef NIS
+#include <rpcsvc/nis.h>
+#include "un-namespace.h"
+
+extern int _rpc_dtablesize( void );
+
+#ifdef TESTING
+#define	msg(x)	printf("ERROR: %s\n", x)
+/* #define msg(x) syslog(LOG_ERR, "%s", x) */
+#else
+#define	msg(x)
+#endif
+
+static int saw_alarm = 0;
+
+static void
+alarm_hndler(s)
+	int	s;
+{
+	saw_alarm = 1;
+	return;
+}
+
+/*
+ * The internet time server defines the epoch to be Jan 1, 1900
+ * whereas UNIX defines it to be Jan 1, 1970. To adjust the result
+ * from internet time-service time, into UNIX time we subtract the
+ * following offset :
+ */
+#define	NYEARS	(1970 - 1900)
+#define	TOFFSET ((u_long)60*60*24*(365*NYEARS + (NYEARS/4)))
+
+
+/*
+ * Stolen from rpc.nisd:
+ * Turn a 'universal address' into a struct sockaddr_in.
+ * Bletch.
+ */
+static int uaddr_to_sockaddr(uaddr, sin)
+#ifdef foo
+	endpoint		*endpt;
+#endif
+	char			*uaddr;
+	struct sockaddr_in	*sin;
+{
+	unsigned char		p_bytes[2];
+	int			i;
+	unsigned long		a[6];
+
+	i = sscanf(uaddr, "%lu.%lu.%lu.%lu.%lu.%lu", &a[0], &a[1], &a[2],
+						&a[3], &a[4], &a[5]);
+
+	if (i < 6)
+		return(1);
+
+	for (i = 0; i < 4; i++)
+		sin->sin_addr.s_addr |= (a[i] & 0x000000FF) << (8 * i);
+
+	p_bytes[0] = (unsigned char)a[4] & 0x000000FF;
+	p_bytes[1] = (unsigned char)a[5] & 0x000000FF;
+
+	sin->sin_family = AF_INET; /* always */
+	bcopy((char *)&p_bytes, (char *)&sin->sin_port, 2);
+
+	return (0);
+}
+
+/*
+ * free_eps()
+ *
+ * Free the strings that were strduped into the eps structure.
+ */
+static void
+free_eps(eps, num)
+	endpoint	eps[];
+	int		num;
+{
+	int		i;
+
+	for (i = 0; i < num; i++) {
+		free(eps[i].uaddr);
+		free(eps[i].proto);
+		free(eps[i].family);
+	}
+	return;
+}
+
+/*
+ * get_server()
+ *
+ * This function constructs a nis_server structure description for the
+ * indicated hostname.
+ *
+ * NOTE: There is a chance we may end up recursing here due to the
+ * fact that gethostbyname() could do an NIS search. Ideally, the
+ * NIS+ server will call __rpc_get_time_offset() with the nis_server
+ * structure already populated.
+ */
+static nis_server *
+get_server(sin, host, srv, eps, maxep)
+	struct sockaddr_in *sin;
+	char		*host;	/* name of the time host	*/
+	nis_server	*srv;	/* nis_server struct to use.	*/
+	endpoint	eps[];	/* array of endpoints		*/
+	int		maxep;	/* max array size		*/
+{
+	char			hname[256];
+	int			num_ep = 0, i;
+	struct hostent		*he;
+	struct hostent		dummy;
+	char			*ptr[2];
+	endpoint		*ep;
+
+	if (host == NULL && sin == NULL)
+		return (NULL);
+
+	if (sin == NULL) {
+		he = gethostbyname(host);
+		if (he == NULL)
+			return(NULL);
+	} else {
+		he = &dummy;
+		ptr[0] = (char *)&sin->sin_addr.s_addr;
+		ptr[1] = NULL;
+		dummy.h_addr_list = ptr;
+	}
+
+	/*
+	 * This is lame. We go around once for TCP, then again
+	 * for UDP.
+	 */
+	for (i = 0, ep = eps; (he->h_addr_list[i] != NULL) && (num_ep < maxep);
+	    i++, ep++, num_ep++) {
+		struct in_addr *a;
+
+		a = (struct in_addr *)he->h_addr_list[i];
+		snprintf(hname, sizeof(hname), "%s.0.111", inet_ntoa(*a));
+		ep->uaddr = strdup(hname);
+		ep->family = strdup("inet");
+		ep->proto =  strdup("tcp");
+		if (ep->uaddr == NULL || ep->family == NULL || ep->proto == NULL) {
+			free_eps(eps, num_ep + 1);
+			return (NULL);
+		}
+	}
+
+	for (i = 0; (he->h_addr_list[i] != NULL) && (num_ep < maxep);
+	    i++, ep++, num_ep++) {
+		struct in_addr *a;
+
+		a = (struct in_addr *)he->h_addr_list[i];
+		snprintf(hname, sizeof(hname), "%s.0.111", inet_ntoa(*a));
+		ep->uaddr = strdup(hname);
+		ep->family = strdup("inet");
+		ep->proto =  strdup("udp");
+		if (ep->uaddr == NULL || ep->family == NULL || ep->proto == NULL) {
+			free_eps(eps, num_ep + 1);
+			return (NULL);
+		}
+	}
+
+	srv->name = (nis_name) host;
+	srv->ep.ep_len = num_ep;
+	srv->ep.ep_val = eps;
+	srv->key_type = NIS_PK_NONE;
+	srv->pkey.n_bytes = NULL;
+	srv->pkey.n_len = 0;
+	return (srv);
+}
+
+/*
+ * __rpc_get_time_offset()
+ *
+ * This function uses a nis_server structure to contact the a remote
+ * machine (as named in that structure) and returns the offset in time
+ * between that machine and this one. This offset is returned in seconds
+ * and may be positive or negative.
+ *
+ * The first time through, a lot of fiddling is done with the netconfig
+ * stuff to find a suitable transport. The function is very aggressive
+ * about choosing UDP or at worst TCP if it can. This is because
+ * those transports support both the RCPBIND call and the internet
+ * time service.
+ *
+ * Once through, *uaddr is set to the universal address of
+ * the machine and *netid is set to the local netid for the transport
+ * that uaddr goes with. On the second call, the netconfig stuff
+ * is skipped and the uaddr/netid pair are used to fetch the netconfig
+ * structure and to then contact the machine for the time.
+ *
+ * td = "server" - "client"
+ */
+int
+__rpc_get_time_offset(td, srv, thost, uaddr, netid)
+	struct timeval	*td;	 /* Time difference			*/
+	nis_server	*srv;	 /* NIS Server description 		*/
+	char		*thost;	 /* if no server, this is the timehost	*/
+	char		**uaddr; /* known universal address		*/
+	struct sockaddr_in *netid; /* known network identifier		*/
+{
+	CLIENT			*clnt; 		/* Client handle 	*/
+	endpoint		*ep,		/* useful endpoints	*/
+				*useep = NULL;	/* endpoint of xp	*/
+	char			*useua = NULL;	/* uaddr of selected xp	*/
+	int			epl, i;		/* counters		*/
+	enum clnt_stat		status;		/* result of clnt_call	*/
+	u_long			thetime, delta;
+	int			needfree = 0;
+	struct timeval		tv;
+	int			time_valid;
+	int			udp_ep = -1, tcp_ep = -1;
+	int			a1, a2, a3, a4;
+	char			ut[64], ipuaddr[64];
+	endpoint		teps[32];
+	nis_server		tsrv;
+	void			(*oldsig)() = NULL; /* old alarm handler */
+	struct sockaddr_in	sin;
+	socklen_t		len;
+	int			s = RPC_ANYSOCK;
+	int			type = 0;
+
+	td->tv_sec = 0;
+	td->tv_usec = 0;
+
+	/*
+	 * First check to see if we need to find and address for this
+	 * server.
+	 */
+	if (*uaddr == NULL) {
+		if ((srv != NULL) && (thost != NULL)) {
+			msg("both timehost and srv pointer used!");
+			return (0);
+		}
+		if (! srv) {
+			srv = get_server(netid, thost, &tsrv, teps, 32);
+			if (srv == NULL) {
+				msg("unable to contruct server data.");
+				return (0);
+			}
+			needfree = 1;	/* need to free data in endpoints */
+		}
+
+		ep = srv->ep.ep_val;
+		epl = srv->ep.ep_len;
+
+		/* Identify the TCP and UDP endpoints */
+		for (i = 0;
+			(i < epl) && ((udp_ep == -1) || (tcp_ep == -1)); i++) {
+			if (strcasecmp(ep[i].proto, "udp") == 0)
+				udp_ep = i;
+			if (strcasecmp(ep[i].proto, "tcp") == 0)
+				tcp_ep = i;
+		}
+
+		/* Check to see if it is UDP or TCP */
+		if (tcp_ep > -1) {
+			useep = &ep[tcp_ep];
+			useua = ep[tcp_ep].uaddr;
+			type = SOCK_STREAM;
+		} else if (udp_ep > -1) {
+			useep = &ep[udp_ep];
+			useua = ep[udp_ep].uaddr;
+			type = SOCK_DGRAM;
+		}
+
+		if (useep == NULL) {
+			msg("no acceptable transport endpoints.");
+			if (needfree)
+				free_eps(teps, tsrv.ep.ep_len);
+			return (0);
+		}
+	}
+
+	/*
+	 * Create a sockaddr from the uaddr.
+	 */
+	if (*uaddr != NULL)
+		useua = *uaddr;
+
+	/* Fixup test for NIS+ */
+	sscanf(useua, "%d.%d.%d.%d.", &a1, &a2, &a3, &a4);
+	sprintf(ipuaddr, "%d.%d.%d.%d.0.111", a1, a2, a3, a4);
+	useua = &ipuaddr[0];
+
+	bzero((char *)&sin, sizeof(sin));
+	if (uaddr_to_sockaddr(useua, &sin)) {
+		msg("unable to translate uaddr to sockaddr.");
+		if (needfree)
+			free_eps(teps, tsrv.ep.ep_len);
+		return (0);
+	}
+
+	/*
+	 * Create the client handle to rpcbind. Note we always try
+	 * version 3 since that is the earliest version that supports
+	 * the RPCB_GETTIME call. Also it is the version that comes
+	 * standard with SVR4. Since most everyone supports TCP/IP
+	 * we could consider trying the rtime call first.
+	 */
+	clnt = clnttcp_create(&sin, RPCBPROG, RPCBVERS, &s, 0, 0);
+	if (clnt == NULL) {
+		msg("unable to create client handle to rpcbind.");
+		if (needfree)
+			free_eps(teps, tsrv.ep.ep_len);
+		return (0);
+	}
+
+	tv.tv_sec = 5;
+	tv.tv_usec = 0;
+	time_valid = 0;
+	status = clnt_call(clnt, RPCBPROC_GETTIME, (xdrproc_t)xdr_void, NULL,
+					(xdrproc_t)xdr_u_long, &thetime, tv);
+	/*
+	 * The only error we check for is anything but success. In
+	 * fact we could have seen PROGMISMATCH if talking to a 4.1
+	 * machine (pmap v2) or TIMEDOUT if the net was busy.
+	 */
+	if (status == RPC_SUCCESS)
+		time_valid = 1;
+	else {
+		int save;
+
+		/* Blow away possible stale CLNT handle. */
+		if (clnt != NULL) {
+			clnt_destroy(clnt);
+			clnt = NULL;
+		}
+
+		/*
+		 * Convert PMAP address into timeservice address
+		 * We take advantage of the fact that we "know" what
+		 * the universal address looks like for inet transports.
+		 *
+		 * We also know that the internet timeservice is always
+		 * listening on port 37.
+		 */
+		sscanf(useua, "%d.%d.%d.%d.", &a1, &a2, &a3, &a4);
+		sprintf(ut, "%d.%d.%d.%d.0.37", a1, a2, a3, a4);
+
+		if (uaddr_to_sockaddr(ut, &sin)) {
+			msg("cannot convert timeservice uaddr to sockaddr.");
+			goto error;
+		}
+
+		s = _socket(AF_INET, type, 0);
+		if (s == -1) {
+			msg("unable to open fd to network.");
+			goto error;
+		}
+
+		/*
+		 * Now depending on whether or not we're talking to
+		 * UDP we set a timeout or not.
+		 */
+		if (type == SOCK_DGRAM) {
+			struct timeval timeout = { 20, 0 };
+			struct sockaddr_in from;
+			fd_set readfds;
+			int res;
+
+			if (_sendto(s, &thetime, sizeof(thetime), 0,
+				(struct sockaddr *)&sin, sizeof(sin)) == -1) {
+				msg("udp : sendto failed.");
+				goto error;
+			}
+			do {
+				FD_ZERO(&readfds);
+				FD_SET(s, &readfds);
+				res = _select(_rpc_dtablesize(), &readfds,
+				     (fd_set *)NULL, (fd_set *)NULL, &timeout);
+			} while (res < 0 && errno == EINTR);
+			if (res <= 0)
+				goto error;
+			len = sizeof(from);
+			res = _recvfrom(s, (char *)&thetime, sizeof(thetime), 0,
+				       (struct sockaddr *)&from, &len);
+			if (res == -1) {
+				msg("recvfrom failed on udp transport.");
+				goto error;
+			}
+			time_valid = 1;
+		} else {
+			int res;
+
+			oldsig = (void (*)())signal(SIGALRM, alarm_hndler);
+			saw_alarm = 0; /* global tracking the alarm */
+			alarm(20); /* only wait 20 seconds */
+			res = _connect(s, (struct sockaddr *)&sin, sizeof(sin));
+			if (res == -1) {
+				msg("failed to connect to tcp endpoint.");
+				goto error;
+			}
+			if (saw_alarm) {
+				msg("alarm caught it, must be unreachable.");
+				goto error;
+			}
+			res = _read(s, (char *)&thetime, sizeof(thetime));
+			if (res != sizeof(thetime)) {
+				if (saw_alarm)
+					msg("timed out TCP call.");
+				else
+					msg("wrong size of results returned");
+
+				goto error;
+			}
+			time_valid = 1;
+		}
+		save = errno;
+		(void)_close(s);
+		errno = save;
+		s = RPC_ANYSOCK;
+
+		if (time_valid) {
+			thetime = ntohl(thetime);
+			thetime = thetime - TOFFSET; /* adjust to UNIX time */
+		} else
+			thetime = 0;
+	}
+
+	gettimeofday(&tv, 0);
+
+error:
+	/*
+	 * clean up our allocated data structures.
+	 */
+
+	if (s != RPC_ANYSOCK)
+		(void)_close(s);
+
+	if (clnt != NULL)
+		clnt_destroy(clnt);
+
+	alarm(0);	/* reset that alarm if its outstanding */
+	if (oldsig) {
+		signal(SIGALRM, oldsig);
+	}
+
+	/*
+	 * note, don't free uaddr strings until after we've made a
+	 * copy of them.
+	 */
+	if (time_valid) {
+		if (*uaddr == NULL)
+			*uaddr = strdup(useua);
+
+		/* Round to the nearest second */
+		tv.tv_sec += (tv.tv_sec > 500000) ? 1 : 0;
+		delta = (thetime > tv.tv_sec) ? thetime - tv.tv_sec :
+						tv.tv_sec - thetime;
+		td->tv_sec = (thetime < tv.tv_sec) ? - delta : delta;
+		td->tv_usec = 0;
+	} else {
+		msg("unable to get the server's time.");
+	}
+
+	if (needfree)
+		free_eps(teps, tsrv.ep.ep_len);
+
+	return (time_valid);
+}
Index: freebsd/lib/libc/rpc/auth_unix.c
===================================================================
--- freebsd/lib/libc/rpc/auth_unix.c	(revision 60b1d40751c8b3235b7ccbf3bb6ad0c562562f01)
+++ freebsd/lib/libc/rpc/auth_unix.c	(revision 60b1d40751c8b3235b7ccbf3bb6ad0c562562f01)
@@ -0,0 +1,384 @@
+#include <machine/rtems-bsd-user-space.h>
+
+/*	$NetBSD: auth_unix.c,v 1.18 2000/07/06 03:03:30 christos Exp $	*/
+
+/*-
+ * Copyright (c) 2009, Sun Microsystems, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions are met:
+ * - Redistributions of source code must retain the above copyright notice, 
+ *   this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice, 
+ *   this list of conditions and the following disclaimer in the documentation 
+ *   and/or other materials provided with the distribution.
+ * - Neither the name of Sun Microsystems, Inc. nor the names of its 
+ *   contributors may be used to endorse or promote products derived 
+ *   from this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char *sccsid2 = "@(#)auth_unix.c 1.19 87/08/11 Copyr 1984 Sun Micro";
+static char *sccsid = "@(#)auth_unix.c	2.2 88/08/01 4.0 RPCSRC";
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * auth_unix.c, Implements UNIX style authentication parameters.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ *
+ * The system is very weak.  The client uses no encryption for it's
+ * credentials and only sends null verifiers.  The server sends backs
+ * null verifiers or optionally a verifier that suggests a new short hand
+ * for the credentials.
+ *
+ */
+
+#include "namespace.h"
+#include "reentrant.h"
+#include <rtems/bsd/sys/param.h>
+
+#include <assert.h>
+#include <err.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+
+#include <rpc/types.h>
+#include <rpc/xdr.h>
+#include <rpc/auth.h>
+#include <rpc/auth_unix.h>
+#include "un-namespace.h"
+#include "mt_misc.h"
+
+/* auth_unix.c */
+static void authunix_nextverf (AUTH *);
+static bool_t authunix_marshal (AUTH *, XDR *);
+static bool_t authunix_validate (AUTH *, struct opaque_auth *);
+static bool_t authunix_refresh (AUTH *, void *);
+static void authunix_destroy (AUTH *);
+static void marshal_new_auth (AUTH *);
+static struct auth_ops *authunix_ops (void);
+
+/*
+ * This struct is pointed to by the ah_private field of an auth_handle.
+ */
+struct audata {
+	struct opaque_auth	au_origcred;	/* original credentials */
+	struct opaque_auth	au_shcred;	/* short hand cred */
+	u_long			au_shfaults;	/* short hand cache faults */
+	char			au_marshed[MAX_AUTH_BYTES];
+	u_int			au_mpos;	/* xdr pos at end of marshed */
+};
+#define	AUTH_PRIVATE(auth)	((struct audata *)auth->ah_private)
+
+/*
+ * Create a unix style authenticator.
+ * Returns an auth handle with the given stuff in it.
+ */
+AUTH *
+authunix_create(machname, uid, gid, len, aup_gids)
+	char *machname;
+	u_int uid;
+	u_int gid;
+	int len;
+	u_int *aup_gids;
+{
+	struct authunix_parms aup;
+	char mymem[MAX_AUTH_BYTES];
+	struct timeval now;
+	XDR xdrs;
+	AUTH *auth;
+	struct audata *au;
+
+	/*
+	 * Allocate and set up auth handle
+	 */
+	au = NULL;
+	auth = mem_alloc(sizeof(*auth));
+#ifndef _KERNEL
+	if (auth == NULL) {
+		warnx("authunix_create: out of memory");
+		goto cleanup_authunix_create;
+	}
+#endif
+	au = mem_alloc(sizeof(*au));
+#ifndef _KERNEL
+	if (au == NULL) {
+		warnx("authunix_create: out of memory");
+		goto cleanup_authunix_create;
+	}
+#endif
+	auth->ah_ops = authunix_ops();
+	auth->ah_private = (caddr_t)au;
+	auth->ah_verf = au->au_shcred = _null_auth;
+	au->au_shfaults = 0;
+	au->au_origcred.oa_base = NULL;
+
+	/*
+	 * fill in param struct from the given params
+	 */
+	(void)gettimeofday(&now, NULL);
+	aup.aup_time = now.tv_sec;
+	aup.aup_machname = machname;
+	aup.aup_uid = uid;
+	aup.aup_gid = gid;
+	aup.aup_len = (u_int)len;
+	aup.aup_gids = aup_gids;
+
+	/*
+	 * Serialize the parameters into origcred
+	 */
+	xdrmem_create(&xdrs, mymem, MAX_AUTH_BYTES, XDR_ENCODE);
+	if (! xdr_authunix_parms(&xdrs, &aup)) 
+		abort();
+	au->au_origcred.oa_length = len = XDR_GETPOS(&xdrs);
+	au->au_origcred.oa_flavor = AUTH_UNIX;
+#ifdef _KERNEL
+	au->au_origcred.oa_base = mem_alloc((u_int) len);
+#else
+	if ((au->au_origcred.oa_base = mem_alloc((u_int) len)) == NULL) {
+		warnx("authunix_create: out of memory");
+		goto cleanup_authunix_create;
+	}
+#endif
+	memmove(au->au_origcred.oa_base, mymem, (size_t)len);
+
+	/*
+	 * set auth handle to reflect new cred.
+	 */
+	auth->ah_cred = au->au_origcred;
+	marshal_new_auth(auth);
+	return (auth);
+#ifndef _KERNEL
+ cleanup_authunix_create:
+	if (auth)
+		mem_free(auth, sizeof(*auth));
+	if (au) {
+		if (au->au_origcred.oa_base)
+			mem_free(au->au_origcred.oa_base, (u_int)len);
+		mem_free(au, sizeof(*au));
+	}
+	return (NULL);
+#endif
+}
+
+/*
+ * Returns an auth handle with parameters determined by doing lots of
+ * syscalls.
+ */
+AUTH *
+authunix_create_default()
+{
+	AUTH *auth;
+	int ngids;
+	long ngids_max;
+	char machname[MAXHOSTNAMELEN + 1];
+	u_int uid;
+	u_int gid;
+	u_int *gids;
+
+	ngids_max = sysconf(_SC_NGROUPS_MAX) + 1;
+	gids = malloc(sizeof(gid_t) * ngids_max);
+	if (gids == NULL)
+		return (NULL);
+
+	if (gethostname(machname, sizeof machname) == -1)
+		abort();
+	machname[sizeof(machname) - 1] = 0;
+	uid = geteuid();
+	gid = getegid();
+	if ((ngids = getgroups(ngids_max, gids)) < 0)
+		abort();
+	if (ngids > NGRPS)
+		ngids = NGRPS;
+	/* XXX: interface problem; we should translate from uid_t and gid_t */
+	auth = authunix_create(machname, uid, gid, ngids, gids);
+	free(gids);
+	return (auth);
+}
+
+/*
+ * authunix operations
+ */
+
+/* ARGSUSED */
+static void
+authunix_nextverf(auth)
+	AUTH *auth;
+{
+	/* no action necessary */
+}
+
+static bool_t
+authunix_marshal(auth, xdrs)
+	AUTH *auth;
+	XDR *xdrs;
+{
+	struct audata *au;
+
+	assert(auth != NULL);
+	assert(xdrs != NULL);
+
+	au = AUTH_PRIVATE(auth);
+	return (XDR_PUTBYTES(xdrs, au->au_marshed, au->au_mpos));
+}
+
+static bool_t
+authunix_validate(auth, verf)
+	AUTH *auth;
+	struct opaque_auth *verf;
+{
+	struct audata *au;
+	XDR xdrs;
+
+	assert(auth != NULL);
+	assert(verf != NULL);
+
+	if (verf->oa_flavor == AUTH_SHORT) {
+		au = AUTH_PRIVATE(auth);
+		xdrmem_create(&xdrs, verf->oa_base, verf->oa_length,
+		    XDR_DECODE);
+
+		if (au->au_shcred.oa_base != NULL) {
+			mem_free(au->au_shcred.oa_base,
+			    au->au_shcred.oa_length);
+			au->au_shcred.oa_base = NULL;
+		}
+		if (xdr_opaque_auth(&xdrs, &au->au_shcred)) {
+			auth->ah_cred = au->au_shcred;
+		} else {
+			xdrs.x_op = XDR_FREE;
+			(void)xdr_opaque_auth(&xdrs, &au->au_shcred);
+			au->au_shcred.oa_base = NULL;
+			auth->ah_cred = au->au_origcred;
+		}
+		marshal_new_auth(auth);
+	}
+	return (TRUE);
+}
+
+static bool_t
+authunix_refresh(AUTH *auth, void *dummy)
+{
+	struct audata *au = AUTH_PRIVATE(auth);
+	struct authunix_parms aup;
+	struct timeval now;
+	XDR xdrs;
+	int stat;
+
+	assert(auth != NULL);
+
+	if (auth->ah_cred.oa_base == au->au_origcred.oa_base) {
+		/* there is no hope.  Punt */
+		return (FALSE);
+	}
+	au->au_shfaults ++;
+
+	/* first deserialize the creds back into a struct authunix_parms */
+	aup.aup_machname = NULL;
+	aup.aup_gids = NULL;
+	xdrmem_create(&xdrs, au->au_origcred.oa_base,
+	    au->au_origcred.oa_length, XDR_DECODE);
+	stat = xdr_authunix_parms(&xdrs, &aup);
+	if (! stat)
+		goto done;
+
+	/* update the time and serialize in place */
+	(void)gettimeofday(&now, NULL);
+	aup.aup_time = now.tv_sec;
+	xdrs.x_op = XDR_ENCODE;
+	XDR_SETPOS(&xdrs, 0);
+	stat = xdr_authunix_parms(&xdrs, &aup);
+	if (! stat)
+		goto done;
+	auth->ah_cred = au->au_origcred;
+	marshal_new_auth(auth);
+done:
+	/* free the struct authunix_parms created by deserializing */
+	xdrs.x_op = XDR_FREE;
+	(void)xdr_authunix_parms(&xdrs, &aup);
+	XDR_DESTROY(&xdrs);
+	return (stat);
+}
+
+static void
+authunix_destroy(auth)
+	AUTH *auth;
+{
+	struct audata *au;
+
+	assert(auth != NULL);
+
+	au = AUTH_PRIVATE(auth);
+	mem_free(au->au_origcred.oa_base, au->au_origcred.oa_length);
+
+	if (au->au_shcred.oa_base != NULL)
+		mem_free(au->au_shcred.oa_base, au->au_shcred.oa_length);
+
+	mem_free(auth->ah_private, sizeof(struct audata));
+
+	if (auth->ah_verf.oa_base != NULL)
+		mem_free(auth->ah_verf.oa_base, auth->ah_verf.oa_length);
+
+	mem_free(auth, sizeof(*auth));
+}
+
+/*
+ * Marshals (pre-serializes) an auth struct.
+ * sets private data, au_marshed and au_mpos
+ */
+static void
+marshal_new_auth(auth)
+	AUTH *auth;
+{
+	XDR	xdr_stream;
+	XDR	*xdrs = &xdr_stream;
+	struct audata *au;
+
+	assert(auth != NULL);
+
+	au = AUTH_PRIVATE(auth);
+	xdrmem_create(xdrs, au->au_marshed, MAX_AUTH_BYTES, XDR_ENCODE);
+	if ((! xdr_opaque_auth(xdrs, &(auth->ah_cred))) ||
+	    (! xdr_opaque_auth(xdrs, &(auth->ah_verf))))
+		warnx("auth_none.c - Fatal marshalling problem");
+	else
+		au->au_mpos = XDR_GETPOS(xdrs);
+	XDR_DESTROY(xdrs);
+}
+
+static struct auth_ops *
+authunix_ops()
+{
+	static struct auth_ops ops;
+
+	/* VARIABLES PROTECTED BY ops_lock: ops */
+
+	mutex_lock(&ops_lock);
+	if (ops.ah_nextverf == NULL) {
+		ops.ah_nextverf = authunix_nextverf;
+		ops.ah_marshal = authunix_marshal;
+		ops.ah_validate = authunix_validate;
+		ops.ah_refresh = authunix_refresh;
+		ops.ah_destroy = authunix_destroy;
+	}
+	mutex_unlock(&ops_lock);
+	return (&ops);
+}
Index: freebsd/lib/libc/rpc/authdes_prot.c
===================================================================
--- freebsd/lib/libc/rpc/authdes_prot.c	(revision 60b1d40751c8b3235b7ccbf3bb6ad0c562562f01)
+++ freebsd/lib/libc/rpc/authdes_prot.c	(revision 60b1d40751c8b3235b7ccbf3bb6ad0c562562f01)
@@ -0,0 +1,95 @@
+#include <machine/rtems-bsd-user-space.h>
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = 	"@(#)authdes_prot.c	2.1 88/07/29 4.0 RPCSRC; from 1.6 88/02/08 SMI";
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*-
+ * Copyright (c) 2009, Sun Microsystems, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions are met:
+ * - Redistributions of source code must retain the above copyright notice, 
+ *   this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice, 
+ *   this list of conditions and the following disclaimer in the documentation 
+ *   and/or other materials provided with the distribution.
+ * - Neither the name of Sun Microsystems, Inc. nor the names of its 
+ *   contributors may be used to endorse or promote products derived 
+ *   from this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * Copyright (c) 1986-1991 by Sun Microsystems Inc.
+ */
+
+/*
+ * authdes_prot.c, XDR routines for DES authentication
+ */
+
+#include "namespace.h"
+#include <rpc/types.h>
+#include <rpc/xdr.h>
+#include <rpc/auth.h>
+#include <rpc/auth_des.h>
+#include "un-namespace.h"
+
+#define ATTEMPT(xdr_op) if (!(xdr_op)) return (FALSE)
+
+bool_t
+xdr_authdes_cred(xdrs, cred)
+	XDR *xdrs;
+	struct authdes_cred *cred;
+{
+	enum authdes_namekind *padc_namekind = &cred->adc_namekind;
+	/*
+	 * Unrolled xdr
+	 */
+	ATTEMPT(xdr_enum(xdrs, (enum_t *) padc_namekind));
+	switch (cred->adc_namekind) {
+	case ADN_FULLNAME:
+		ATTEMPT(xdr_string(xdrs, &cred->adc_fullname.name,
+		    MAXNETNAMELEN));
+		ATTEMPT(xdr_opaque(xdrs, (caddr_t)&cred->adc_fullname.key,
+		    sizeof(des_block)));
+		ATTEMPT(xdr_opaque(xdrs, (caddr_t)&cred->adc_fullname.window,
+		    sizeof(cred->adc_fullname.window)));
+		return (TRUE);
+	case ADN_NICKNAME:
+		ATTEMPT(xdr_opaque(xdrs, (caddr_t)&cred->adc_nickname,
+		    sizeof(cred->adc_nickname)));
+		return (TRUE);
+	default:
+		return (FALSE);
+	}
+}
+
+
+bool_t
+xdr_authdes_verf(xdrs, verf)
+	XDR *xdrs;
+	struct authdes_verf *verf;	
+{
+	/*
+ 	 * Unrolled xdr
+ 	 */
+	ATTEMPT(xdr_opaque(xdrs, (caddr_t)&verf->adv_xtimestamp,
+	    sizeof(des_block)));
+	ATTEMPT(xdr_opaque(xdrs, (caddr_t)&verf->adv_int_u,
+	    sizeof(verf->adv_int_u)));
+	return (TRUE);
+}
Index: freebsd/lib/libc/rpc/authunix_prot.c
===================================================================
--- freebsd/lib/libc/rpc/authunix_prot.c	(revision 60b1d40751c8b3235b7ccbf3bb6ad0c562562f01)
+++ freebsd/lib/libc/rpc/authunix_prot.c	(revision 60b1d40751c8b3235b7ccbf3bb6ad0c562562f01)
@@ -0,0 +1,80 @@
+#include <machine/rtems-bsd-user-space.h>
+
+/*	$NetBSD: authunix_prot.c,v 1.12 2000/01/22 22:19:17 mycroft Exp $	*/
+
+/*-
+ * Copyright (c) 2009, Sun Microsystems, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions are met:
+ * - Redistributions of source code must retain the above copyright notice, 
+ *   this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice, 
+ *   this list of conditions and the following disclaimer in the documentation 
+ *   and/or other materials provided with the distribution.
+ * - Neither the name of Sun Microsystems, Inc. nor the names of its 
+ *   contributors may be used to endorse or promote products derived 
+ *   from this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char *sccsid2 = "@(#)authunix_prot.c 1.15 87/08/11 Copyr 1984 Sun Micro";
+static char *sccsid = "@(#)authunix_prot.c	2.1 88/07/29 4.0 RPCSRC";
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * authunix_prot.c
+ * XDR for UNIX style authentication parameters for RPC
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#include "namespace.h"
+#include <assert.h>
+
+#include <rpc/types.h>
+#include <rpc/xdr.h>
+#include <rpc/auth.h>
+#include <rpc/auth_unix.h>
+#include "un-namespace.h"
+
+/*
+ * XDR for unix authentication parameters.
+ */
+bool_t
+xdr_authunix_parms(xdrs, p)
+	XDR *xdrs;
+	struct authunix_parms *p;
+{
+	u_int **paup_gids;
+
+	assert(xdrs != NULL);
+	assert(p != NULL);
+
+	paup_gids = &p->aup_gids;
+
+	if (xdr_u_long(xdrs, &(p->aup_time)) &&
+	    xdr_string(xdrs, &(p->aup_machname), MAX_MACHINE_NAME) &&
+	    xdr_u_int(xdrs, &(p->aup_uid)) &&
+	    xdr_u_int(xdrs, &(p->aup_gid)) &&
+	    xdr_array(xdrs, (char **) paup_gids,
+	    &(p->aup_len), NGRPS, sizeof(u_int), (xdrproc_t)xdr_u_int) ) {
+		return (TRUE);
+	}
+	return (FALSE);
+}
Index: freebsd/lib/libc/rpc/bindresvport.c
===================================================================
--- freebsd/lib/libc/rpc/bindresvport.c	(revision 60b1d40751c8b3235b7ccbf3bb6ad0c562562f01)
+++ freebsd/lib/libc/rpc/bindresvport.c	(revision 60b1d40751c8b3235b7ccbf3bb6ad0c562562f01)
@@ -0,0 +1,162 @@
+#include <machine/rtems-bsd-user-space.h>
+
+/*	$NetBSD: bindresvport.c,v 1.19 2000/07/06 03:03:59 christos Exp $	*/
+
+/*-
+ * Copyright (c) 2009, Sun Microsystems, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions are met:
+ * - Redistributions of source code must retain the above copyright notice, 
+ *   this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice, 
+ *   this list of conditions and the following disclaimer in the documentation 
+ *   and/or other materials provided with the distribution.
+ * - Neither the name of Sun Microsystems, Inc. nor the names of its 
+ *   contributors may be used to endorse or promote products derived 
+ *   from this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char *sccsid2 = "from: @(#)bindresvport.c 1.8 88/02/08 SMI";
+static char *sccsid = "from: @(#)bindresvport.c	2.2 88/07/29 4.0 RPCSRC";
+#endif
+/* from: $OpenBSD: bindresvport.c,v 1.7 1996/07/30 16:25:47 downsj Exp $ */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * Copyright (c) 1987 by Sun Microsystems, Inc.
+ *
+ * Portions Copyright(C) 1996, Jason Downs.  All rights reserved.
+ */
+
+#include "namespace.h"
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <rpc/rpc.h>
+
+#include <string.h>
+#include "un-namespace.h"
+
+/*
+ * Bind a socket to a privileged IP port
+ */
+int
+bindresvport(sd, sin)
+	int sd;
+	struct sockaddr_in *sin;
+{
+	return bindresvport_sa(sd, (struct sockaddr *)sin);
+}
+
+/*
+ * Bind a socket to a privileged IP port
+ */
+int
+bindresvport_sa(sd, sa)
+	int sd;
+	struct sockaddr *sa;
+{
+	int old, error, af;
+	struct sockaddr_storage myaddr;
+	struct sockaddr_in *sin;
+#ifdef INET6
+	struct sockaddr_in6 *sin6;
+#endif
+	int proto, portrange, portlow;
+	u_int16_t *portp;
+	socklen_t salen;
+
+	if (sa == NULL) {
+		salen = sizeof(myaddr);
+		sa = (struct sockaddr *)&myaddr;
+
+		if (_getsockname(sd, sa, &salen) == -1)
+			return -1;	/* errno is correctly set */
+
+		af = sa->sa_family;
+		memset(sa, 0, salen);
+	} else
+		af = sa->sa_family;
+
+	switch (af) {
+	case AF_INET:
+		proto = IPPROTO_IP;
+		portrange = IP_PORTRANGE;
+		portlow = IP_PORTRANGE_LOW;
+		sin = (struct sockaddr_in *)sa;
+		salen = sizeof(struct sockaddr_in);
+		portp = &sin->sin_port;
+		break;
+#ifdef INET6
+	case AF_INET6:
+		proto = IPPROTO_IPV6;
+		portrange = IPV6_PORTRANGE;
+		portlow = IPV6_PORTRANGE_LOW;
+		sin6 = (struct sockaddr_in6 *)sa;
+		salen = sizeof(struct sockaddr_in6);
+		portp = &sin6->sin6_port;
+		break;
+#endif
+	default:
+		errno = EPFNOSUPPORT;
+		return (-1);
+	}
+	sa->sa_family = af;
+	sa->sa_len = salen;
+
+	if (*portp == 0) {
+		socklen_t oldlen = sizeof(old);
+
+		error = _getsockopt(sd, proto, portrange, &old, &oldlen);
+		if (error < 0)
+			return (error);
+
+		error = _setsockopt(sd, proto, portrange, &portlow,
+		    sizeof(portlow));
+		if (error < 0)
+			return (error);
+	}
+
+	error = _bind(sd, sa, salen);
+
+	if (*portp == 0) {
+		int saved_errno = errno;
+
+		if (error < 0) {
+			if (_setsockopt(sd, proto, portrange, &old,
+			    sizeof(old)) < 0)
+				errno = saved_errno;
+			return (error);
+		}
+
+		if (sa != (struct sockaddr *)&myaddr) {
+			/* Hmm, what did the kernel assign? */
+			if (_getsockname(sd, sa, &salen) < 0)
+				errno = saved_errno;
+			return (error);
+		}
+	}
+	return (error);
+}
Index: freebsd/lib/libc/rpc/clnt_bcast.c
===================================================================
--- freebsd/lib/libc/rpc/clnt_bcast.c	(revision 60b1d40751c8b3235b7ccbf3bb6ad0c562562f01)
+++ freebsd/lib/libc/rpc/clnt_bcast.c	(revision 60b1d40751c8b3235b7ccbf3bb6ad0c562562f01)
@@ -0,0 +1,674 @@
+#include <machine/rtems-bsd-user-space.h>
+
+/*	$NetBSD: clnt_bcast.c,v 1.3 2000/07/06 03:05:20 christos Exp $	*/
+
+/*-
+ * Copyright (c) 2009, Sun Microsystems, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions are met:
+ * - Redistributions of source code must retain the above copyright notice, 
+ *   this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice, 
+ *   this list of conditions and the following disclaimer in the documentation 
+ *   and/or other materials provided with the distribution.
+ * - Neither the name of Sun Microsystems, Inc. nor the names of its 
+ *   contributors may be used to endorse or promote products derived 
+ *   from this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * Copyright (c) 1986-1991 by Sun Microsystems Inc. 
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+#ident	"@(#)clnt_bcast.c	1.18	94/05/03 SMI"
+static char sccsid[] = "@(#)clnt_bcast.c 1.15 89/04/21 Copyr 1988 Sun Micro";
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+
+/*
+ * clnt_bcast.c
+ * Client interface to broadcast service.
+ *
+ * Copyright (C) 1988, Sun Microsystems, Inc.
+ *
+ * The following is kludged-up support for simple rpc broadcasts.
+ * Someday a large, complicated system will replace these routines.
+ */
+
+#include "namespace.h"
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/queue.h>
+#include <net/if.h>
+#include <netinet/in.h>
+#include <ifaddrs.h>
+#include <sys/poll.h>
+#include <rpc/rpc.h>
+#ifdef PORTMAP
+#include <rpc/pmap_prot.h>
+#include <rpc/pmap_clnt.h>
+#include <rpc/pmap_rmt.h>
+#endif				/* PORTMAP */
+#include <rpc/nettype.h>
+#include <arpa/inet.h>
+#ifdef RPC_DEBUG
+#include <stdio.h>
+#endif
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <netdb.h>
+#include <err.h>
+#include <string.h>
+#include "un-namespace.h"
+
+#include "rpc_com.h"
+
+#define	MAXBCAST 20	/* Max no of broadcasting transports */
+#define	INITTIME 4000	/* Time to wait initially */
+#define	WAITTIME 8000	/* Maximum time to wait */
+
+/*
+ * If nettype is NULL, it broadcasts on all the available
+ * datagram_n transports. May potentially lead to broadacst storms
+ * and hence should be used with caution, care and courage.
+ *
+ * The current parameter xdr packet size is limited by the max tsdu
+ * size of the transport. If the max tsdu size of any transport is
+ * smaller than the parameter xdr packet, then broadcast is not
+ * sent on that transport.
+ *
+ * Also, the packet size should be less the packet size of
+ * the data link layer (for ethernet it is 1400 bytes).  There is
+ * no easy way to find out the max size of the data link layer and
+ * we are assuming that the args would be smaller than that.
+ *
+ * The result size has to be smaller than the transport tsdu size.
+ *
+ * If PORTMAP has been defined, we send two packets for UDP, one for
+ * rpcbind and one for portmap. For those machines which support
+ * both rpcbind and portmap, it will cause them to reply twice, and
+ * also here it will get two responses ... inefficient and clumsy.
+ */
+
+struct broadif {
+	int index;
+	struct sockaddr_storage broadaddr;
+	TAILQ_ENTRY(broadif) link;
+};
+
+typedef TAILQ_HEAD(, broadif) broadlist_t;
+
+int __rpc_getbroadifs(int, int, int, broadlist_t *);
+void __rpc_freebroadifs(broadlist_t *);
+int __rpc_broadenable(int, int, struct broadif *);
+
+int __rpc_lowvers = 0;
+
+int
+__rpc_getbroadifs(int af, int proto, int socktype, broadlist_t *list)
+{
+	int count = 0;
+	struct broadif *bip;
+	struct ifaddrs *ifap, *ifp;
+#ifdef INET6
+	struct sockaddr_in6 *sin6;
+#endif
+	struct sockaddr_in *sin;
+	struct addrinfo hints, *res;
+
+	if (getifaddrs(&ifp) < 0)
+		return 0;
+
+	memset(&hints, 0, sizeof hints);
+
+	hints.ai_family = af;
+	hints.ai_protocol = proto;
+	hints.ai_socktype = socktype;
+
+	if (getaddrinfo(NULL, "sunrpc", &hints, &res) != 0) {
+		freeifaddrs(ifp);
+		return 0;
+	}
+
+	for (ifap = ifp; ifap != NULL; ifap = ifap->ifa_next) {
+		if (ifap->ifa_addr->sa_family != af ||
+		    !(ifap->ifa_flags & IFF_UP))
+			continue;
+		bip = (struct broadif *)malloc(sizeof *bip);
+		if (bip == NULL)
+			break;
+		bip->index = if_nametoindex(ifap->ifa_name);
+		if (
+#ifdef INET6
+		af != AF_INET6 &&
+#endif
+		(ifap->ifa_flags & IFF_BROADCAST) &&
+		 ifap->ifa_broadaddr) {
+			memcpy(&bip->broadaddr, ifap->ifa_broadaddr,
+			    (size_t)ifap->ifa_broadaddr->sa_len);
+			sin = (struct sockaddr_in *)(void *)&bip->broadaddr;
+			sin->sin_port =
+			    ((struct sockaddr_in *)
+			    (void *)res->ai_addr)->sin_port;
+		} else
+#ifdef INET6
+		if (af == AF_INET6 && (ifap->ifa_flags & IFF_MULTICAST)) {
+			sin6 = (struct sockaddr_in6 *)(void *)&bip->broadaddr;
+			inet_pton(af, RPCB_MULTICAST_ADDR, &sin6->sin6_addr);
+			sin6->sin6_family = af;
+			sin6->sin6_len = sizeof *sin6;
+			sin6->sin6_port =
+			    ((struct sockaddr_in6 *)
+			    (void *)res->ai_addr)->sin6_port;
+			sin6->sin6_scope_id = bip->index;
+		} else
+#endif
+		{
+			free(bip);
+			continue;
+		}
+		TAILQ_INSERT_TAIL(list, bip, link);
+		count++;
+	}
+	freeifaddrs(ifp);
+	freeaddrinfo(res);
+
+	return count;
+}
+
+void
+__rpc_freebroadifs(broadlist_t *list)
+{
+	struct broadif *bip, *next;
+
+	bip = TAILQ_FIRST(list);
+
+	while (bip != NULL) {
+		next = TAILQ_NEXT(bip, link);
+		free(bip);
+		bip = next;
+	}
+}
+
+int
+/*ARGSUSED*/
+__rpc_broadenable(int af, int s, struct broadif *bip)
+{
+	int o = 1;
+
+#if 0
+	if (af == AF_INET6) {
+		fprintf(stderr, "set v6 multicast if to %d\n", bip->index);
+		if (_setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_IF, &bip->index,
+		    sizeof bip->index) < 0)
+			return -1;
+	} else
+#endif
+		if (_setsockopt(s, SOL_SOCKET, SO_BROADCAST, &o, sizeof o) < 0)
+			return -1;
+
+	return 0;
+}
+
+
+enum clnt_stat
+rpc_broadcast_exp(prog, vers, proc, xargs, argsp, xresults, resultsp,
+	eachresult, inittime, waittime, nettype)
+	rpcprog_t	prog;		/* program number */
+	rpcvers_t	vers;		/* version number */
+	rpcproc_t	proc;		/* procedure number */
+	xdrproc_t	xargs;		/* xdr routine for args */
+	caddr_t		argsp;		/* pointer to args */
+	xdrproc_t	xresults;	/* xdr routine for results */
+	caddr_t		resultsp;	/* pointer to results */
+	resultproc_t	eachresult;	/* call with each result obtained */
+	int 		inittime;	/* how long to wait initially */
+	int 		waittime;	/* maximum time to wait */
+	const char		*nettype;	/* transport type */
+{
+	enum clnt_stat	stat = RPC_SUCCESS; /* Return status */
+	XDR 		xdr_stream; /* XDR stream */
+	XDR 		*xdrs = &xdr_stream;
+	struct rpc_msg	msg;	/* RPC message */
+	struct timeval	t;
+	char 		*outbuf = NULL;	/* Broadcast msg buffer */
+	char		*inbuf = NULL; /* Reply buf */
+	int		inlen;
+	u_int 		maxbufsize = 0;
+	AUTH 		*sys_auth = authunix_create_default();
+	int		i;
+	void		*handle;
+	char		uaddress[1024];	/* A self imposed limit */
+	char		*uaddrp = uaddress;
+	int 		pmap_reply_flag; /* reply recvd from PORTMAP */
+	/* An array of all the suitable broadcast transports */
+	struct {
+		int fd;		/* File descriptor */
+		int af;
+		int proto;
+		struct netconfig *nconf; /* Netconfig structure */
+		u_int asize;	/* Size of the addr buf */
+		u_int dsize;	/* Size of the data buf */
+		struct sockaddr_storage raddr; /* Remote address */
+		broadlist_t nal;
+	} fdlist[MAXBCAST];
+	struct pollfd pfd[MAXBCAST];
+	size_t fdlistno = 0;
+	struct r_rpcb_rmtcallargs barg;	/* Remote arguments */
+	struct r_rpcb_rmtcallres bres; /* Remote results */
+	size_t outlen;
+	struct netconfig *nconf;
+	int msec;
+	int pollretval;
+	int fds_found;
+
+#ifdef PORTMAP
+	size_t outlen_pmap = 0;
+	u_long port;		/* Remote port number */
+	int pmap_flag = 0;	/* UDP exists ? */
+	char *outbuf_pmap = NULL;
+	struct rmtcallargs barg_pmap;	/* Remote arguments */
+	struct rmtcallres bres_pmap; /* Remote results */
+	u_int udpbufsz = 0;
+#endif				/* PORTMAP */
+
+	if (sys_auth == NULL) {
+		return (RPC_SYSTEMERROR);
+	}
+	/*
+	 * initialization: create a fd, a broadcast address, and send the
+	 * request on the broadcast transport.
+	 * Listen on all of them and on replies, call the user supplied
+	 * function.
+	 */
+
+	if (nettype == NULL)
+		nettype = "datagram_n";
+	if ((handle = __rpc_setconf(nettype)) == NULL) {
+		AUTH_DESTROY(sys_auth);
+		return (RPC_UNKNOWNPROTO);
+	}
+	while ((nconf = __rpc_getconf(handle)) != NULL) {
+		int fd;
+		struct __rpc_sockinfo si;
+
+		if (nconf->nc_semantics != NC_TPI_CLTS)
+			continue;
+		if (fdlistno >= MAXBCAST)
+			break;	/* No more slots available */
+		if (!__rpc_nconf2sockinfo(nconf, &si))
+			continue;
+
+		TAILQ_INIT(&fdlist[fdlistno].nal);
+		if (__rpc_getbroadifs(si.si_af, si.si_proto, si.si_socktype, 
+		    &fdlist[fdlistno].nal) == 0)
+			continue;
+
+		fd = _socket(si.si_af, si.si_socktype, si.si_proto);
+		if (fd < 0) {
+			stat = RPC_CANTSEND;
+			continue;
+		}
+		fdlist[fdlistno].af = si.si_af;
+		fdlist[fdlistno].proto = si.si_proto;
+		fdlist[fdlistno].fd = fd;
+		fdlist[fdlistno].nconf = nconf;
+		fdlist[fdlistno].asize = __rpc_get_a_size(si.si_af);
+		pfd[fdlistno].events = POLLIN | POLLPRI |
+			POLLRDNORM | POLLRDBAND;
+		pfd[fdlistno].fd = fdlist[fdlistno].fd = fd;
+		fdlist[fdlistno].dsize = __rpc_get_t_size(si.si_af, si.si_proto,
+							  0);
+
+		if (maxbufsize <= fdlist[fdlistno].dsize)
+			maxbufsize = fdlist[fdlistno].dsize;
+
+#ifdef PORTMAP
+		if (si.si_af == AF_INET && si.si_proto == IPPROTO_UDP) {
+			udpbufsz = fdlist[fdlistno].dsize;
+			if ((outbuf_pmap = malloc(udpbufsz)) == NULL) {
+				_close(fd);
+				stat = RPC_SYSTEMERROR;
+				goto done_broad;
+			}
+			pmap_flag = 1;
+		}
+#endif				/* PORTMAP */
+		fdlistno++;
+	}
+
+	if (fdlistno == 0) {
+		if (stat == RPC_SUCCESS)
+			stat = RPC_UNKNOWNPROTO;
+		goto done_broad;
+	}
+	if (maxbufsize == 0) {
+		if (stat == RPC_SUCCESS)
+			stat = RPC_CANTSEND;
+		goto done_broad;
+	}
+	inbuf = malloc(maxbufsize);
+	outbuf = malloc(maxbufsize);
+	if ((inbuf == NULL) || (outbuf == NULL)) {
+		stat = RPC_SYSTEMERROR;
+		goto done_broad;
+	}
+
+	/* Serialize all the arguments which have to be sent */
+	(void) gettimeofday(&t, NULL);
+	msg.rm_xid = __RPC_GETXID(&t);
+	msg.rm_direction = CALL;
+	msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
+	msg.rm_call.cb_prog = RPCBPROG;
+	msg.rm_call.cb_vers = RPCBVERS;
+	msg.rm_call.cb_proc = RPCBPROC_CALLIT;
+	barg.prog = prog;
+	barg.vers = vers;
+	barg.proc = proc;
+	barg.args.args_val = argsp;
+	barg.xdr_args = xargs;
+	bres.addr = uaddrp;
+	bres.results.results_val = resultsp;
+	bres.xdr_res = xresults;
+	msg.rm_call.cb_cred = sys_auth->ah_cred;
+	msg.rm_call.cb_verf = sys_auth->ah_verf;
+	xdrmem_create(xdrs, outbuf, maxbufsize, XDR_ENCODE);
+	if ((!xdr_callmsg(xdrs, &msg)) ||
+	    (!xdr_rpcb_rmtcallargs(xdrs,
+	    (struct rpcb_rmtcallargs *)(void *)&barg))) {
+		stat = RPC_CANTENCODEARGS;
+		goto done_broad;
+	}
+	outlen = xdr_getpos(xdrs);
+	xdr_destroy(xdrs);
+
+#ifdef PORTMAP
+	/* Prepare the packet for version 2 PORTMAP */
+	if (pmap_flag) {
+		msg.rm_xid++;	/* One way to distinguish */
+		msg.rm_call.cb_prog = PMAPPROG;
+		msg.rm_call.cb_vers = PMAPVERS;
+		msg.rm_call.cb_proc = PMAPPROC_CALLIT;
+		barg_pmap.prog = prog;
+		barg_pmap.vers = vers;
+		barg_pmap.proc = proc;
+		barg_pmap.args_ptr = argsp;
+		barg_pmap.xdr_args = xargs;
+		bres_pmap.port_ptr = &port;
+		bres_pmap.xdr_results = xresults;
+		bres_pmap.results_ptr = resultsp;
+		xdrmem_create(xdrs, outbuf_pmap, udpbufsz, XDR_ENCODE);
+		if ((! xdr_callmsg(xdrs, &msg)) ||
+		    (! xdr_rmtcall_args(xdrs, &barg_pmap))) {
+			stat = RPC_CANTENCODEARGS;
+			goto done_broad;
+		}
+		outlen_pmap = xdr_getpos(xdrs);
+		xdr_destroy(xdrs);
+	}
+#endif				/* PORTMAP */
+
+	/*
+	 * Basic loop: broadcast the packets to transports which
+	 * support data packets of size such that one can encode
+	 * all the arguments.
+	 * Wait a while for response(s).
+	 * The response timeout grows larger per iteration.
+	 */
+	for (msec = inittime; msec <= waittime; msec += msec) {
+		struct broadif *bip;
+
+		/* Broadcast all the packets now */
+		for (i = 0; i < fdlistno; i++) {
+			if (fdlist[i].dsize < outlen) {
+				stat = RPC_CANTSEND;
+				continue;
+			}
+			for (bip = TAILQ_FIRST(&fdlist[i].nal); bip != NULL;
+			     bip = TAILQ_NEXT(bip, link)) {
+				void *addr;
+
+				addr = &bip->broadaddr;
+
+				__rpc_broadenable(fdlist[i].af, fdlist[i].fd,
+				    bip);
+
+				/*
+				 * Only use version 3 if lowvers is not set
+				 */
+
+				if (!__rpc_lowvers)
+					if (_sendto(fdlist[i].fd, outbuf,
+					    outlen, 0, (struct sockaddr*)addr,
+					    (size_t)fdlist[i].asize) !=
+					    outlen) {
+#ifdef RPC_DEBUG
+						perror("sendto");
+#endif
+						warnx("clnt_bcast: cannot send "
+						      "broadcast packet");
+						stat = RPC_CANTSEND;
+						continue;
+					};
+#ifdef RPC_DEBUG
+				if (!__rpc_lowvers)
+					fprintf(stderr, "Broadcast packet sent "
+						"for %s\n",
+						 fdlist[i].nconf->nc_netid);
+#endif
+#ifdef PORTMAP
+				/*
+				 * Send the version 2 packet also
+				 * for UDP/IP
+				 */
+				if (pmap_flag &&
+				    fdlist[i].proto == IPPROTO_UDP) {
+					if (_sendto(fdlist[i].fd, outbuf_pmap,
+					    outlen_pmap, 0, addr,
+					    (size_t)fdlist[i].asize) !=
+						outlen_pmap) {
+						warnx("clnt_bcast: "
+						    "Cannot send broadcast packet");
+						stat = RPC_CANTSEND;
+						continue;
+					}
+				}
+#ifdef RPC_DEBUG
+				fprintf(stderr, "PMAP Broadcast packet "
+					"sent for %s\n",
+					fdlist[i].nconf->nc_netid);
+#endif
+#endif				/* PORTMAP */
+			}
+			/* End for sending all packets on this transport */
+		}	/* End for sending on all transports */
+
+		if (eachresult == NULL) {
+			stat = RPC_SUCCESS;
+			goto done_broad;
+		}
+
+		/*
+		 * Get all the replies from these broadcast requests
+		 */
+	recv_again:
+
+		switch (pollretval = _poll(pfd, fdlistno, msec)) {
+		case 0:		/* timed out */
+			stat = RPC_TIMEDOUT;
+			continue;
+		case -1:	/* some kind of error - we ignore it */
+			goto recv_again;
+		}		/* end of poll results switch */
+
+		for (i = fds_found = 0;
+		     i < fdlistno && fds_found < pollretval; i++) {
+			bool_t done = FALSE;
+
+			if (pfd[i].revents == 0)
+				continue;
+			else if (pfd[i].revents & POLLNVAL) {
+				/*
+				 * Something bad has happened to this descri-
+				 * ptor. We can cause _poll() to ignore
+				 * it simply by using a negative fd.  We do that
+				 * rather than compacting the pfd[] and fdlist[]
+				 * arrays.
+				 */
+				pfd[i].fd = -1;
+				fds_found++;
+				continue;
+			} else
+				fds_found++;
+#ifdef RPC_DEBUG
+			fprintf(stderr, "response for %s\n",
+				fdlist[i].nconf->nc_netid);
+#endif
+		try_again:
+			inlen = _recvfrom(fdlist[i].fd, inbuf, fdlist[i].dsize,
+			    0, (struct sockaddr *)(void *)&fdlist[i].raddr,
+			    &fdlist[i].asize);
+			if (inlen < 0) {
+				if (errno == EINTR)
+					goto try_again;
+				warnx("clnt_bcast: Cannot receive reply to "
+					"broadcast");
+				stat = RPC_CANTRECV;
+				continue;
+			}
+			if (inlen < sizeof (u_int32_t))
+				continue; /* Drop that and go ahead */
+			/*
+			 * see if reply transaction id matches sent id.
+			 * If so, decode the results. If return id is xid + 1
+			 * it was a PORTMAP reply
+			 */
+			if (*((u_int32_t *)(void *)(inbuf)) ==
+			    *((u_int32_t *)(void *)(outbuf))) {
+				pmap_reply_flag = 0;
+				msg.acpted_rply.ar_verf = _null_auth;
+				msg.acpted_rply.ar_results.where =
+					(caddr_t)(void *)&bres;
+				msg.acpted_rply.ar_results.proc =
+					(xdrproc_t)xdr_rpcb_rmtcallres;
+#ifdef PORTMAP
+			} else if (pmap_flag &&
+				*((u_int32_t *)(void *)(inbuf)) ==
+				*((u_int32_t *)(void *)(outbuf_pmap))) {
+				pmap_reply_flag = 1;
+				msg.acpted_rply.ar_verf = _null_auth;
+				msg.acpted_rply.ar_results.where =
+					(caddr_t)(void *)&bres_pmap;
+				msg.acpted_rply.ar_results.proc =
+					(xdrproc_t)xdr_rmtcallres;
+#endif				/* PORTMAP */
+			} else
+				continue;
+			xdrmem_create(xdrs, inbuf, (u_int)inlen, XDR_DECODE);
+			if (xdr_replymsg(xdrs, &msg)) {
+				if ((msg.rm_reply.rp_stat == MSG_ACCEPTED) &&
+				    (msg.acpted_rply.ar_stat == SUCCESS)) {
+					struct netbuf taddr, *np;
+					struct sockaddr_in *sin;
+
+#ifdef PORTMAP
+					if (pmap_flag && pmap_reply_flag) {
+						sin = (struct sockaddr_in *)
+						    (void *)&fdlist[i].raddr;
+						sin->sin_port =
+						    htons((u_short)port);
+						taddr.len = taddr.maxlen = 
+						    fdlist[i].raddr.ss_len;
+						taddr.buf = &fdlist[i].raddr;
+						done = (*eachresult)(resultsp,
+						    &taddr, fdlist[i].nconf);
+					} else {
+#endif				/* PORTMAP */
+#ifdef RPC_DEBUG
+						fprintf(stderr, "uaddr %s\n",
+						    uaddrp);
+#endif
+						np = uaddr2taddr(
+						    fdlist[i].nconf, uaddrp);
+						done = (*eachresult)(resultsp,
+						    np, fdlist[i].nconf);
+						free(np);
+#ifdef PORTMAP
+					}
+#endif				/* PORTMAP */
+				}
+				/* otherwise, we just ignore the errors ... */
+			}
+			/* else some kind of deserialization problem ... */
+
+			xdrs->x_op = XDR_FREE;
+			msg.acpted_rply.ar_results.proc = (xdrproc_t) xdr_void;
+			(void) xdr_replymsg(xdrs, &msg);
+			(void) (*xresults)(xdrs, resultsp);
+			XDR_DESTROY(xdrs);
+			if (done) {
+				stat = RPC_SUCCESS;
+				goto done_broad;
+			} else {
+				goto recv_again;
+			}
+		}		/* The recv for loop */
+	}			/* The giant for loop */
+
+done_broad:
+	if (inbuf)
+		(void) free(inbuf);
+	if (outbuf)
+		(void) free(outbuf);
+#ifdef PORTMAP
+	if (outbuf_pmap)
+		(void) free(outbuf_pmap);
+#endif				/* PORTMAP */
+	for (i = 0; i < fdlistno; i++) {
+		(void)_close(fdlist[i].fd);
+		__rpc_freebroadifs(&fdlist[i].nal);
+	}
+	AUTH_DESTROY(sys_auth);
+	(void) __rpc_endconf(handle);
+
+	return (stat);
+}
+
+
+enum clnt_stat
+rpc_broadcast(prog, vers, proc, xargs, argsp, xresults, resultsp,
+			eachresult, nettype)
+	rpcprog_t	prog;		/* program number */
+	rpcvers_t	vers;		/* version number */
+	rpcproc_t	proc;		/* procedure number */
+	xdrproc_t	xargs;		/* xdr routine for args */
+	caddr_t		argsp;		/* pointer to args */
+	xdrproc_t	xresults;	/* xdr routine for results */
+	caddr_t		resultsp;	/* pointer to results */
+	resultproc_t	eachresult;	/* call with each result obtained */
+	const char		*nettype;	/* transport type */
+{
+	enum clnt_stat	dummy;
+
+	dummy = rpc_broadcast_exp(prog, vers, proc, xargs, argsp,
+		xresults, resultsp, eachresult,
+		INITTIME, WAITTIME, nettype);
+	return (dummy);
+}
Index: freebsd/lib/libc/rpc/clnt_dg.c
===================================================================
--- freebsd/lib/libc/rpc/clnt_dg.c	(revision 60b1d40751c8b3235b7ccbf3bb6ad0c562562f01)
+++ freebsd/lib/libc/rpc/clnt_dg.c	(revision 60b1d40751c8b3235b7ccbf3bb6ad0c562562f01)
@@ -0,0 +1,860 @@
+#include <machine/rtems-bsd-user-space.h>
+
+/*	$NetBSD: clnt_dg.c,v 1.4 2000/07/14 08:40:41 fvdl Exp $	*/
+
+/*-
+ * Copyright (c) 2009, Sun Microsystems, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions are met:
+ * - Redistributions of source code must retain the above copyright notice, 
+ *   this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice, 
+ *   this list of conditions and the following disclaimer in the documentation 
+ *   and/or other materials provided with the distribution.
+ * - Neither the name of Sun Microsystems, Inc. nor the names of its 
+ *   contributors may be used to endorse or promote products derived 
+ *   from this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * Copyright (c) 1986-1991 by Sun Microsystems Inc. 
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+#ident	"@(#)clnt_dg.c	1.23	94/04/22 SMI"
+static char sccsid[] = "@(#)clnt_dg.c 1.19 89/03/16 Copyr 1988 Sun Micro";
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * Implements a connectionless client side RPC.
+ */
+
+#include "namespace.h"
+#include "reentrant.h"
+#include <sys/types.h>
+#include <sys/event.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <arpa/inet.h>
+#include <rpc/rpc.h>
+#include <rpc/rpcsec_gss.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#include <unistd.h>
+#include <err.h>
+#include "un-namespace.h"
+#include "rpc_com.h"
+#include "mt_misc.h"
+
+
+#ifdef _FREEFALL_CONFIG
+/*
+ * Disable RPC exponential back-off for FreeBSD.org systems.
+ */
+#define	RPC_MAX_BACKOFF		1 /* second */
+#else
+#define	RPC_MAX_BACKOFF		30 /* seconds */
+#endif
+
+
+static struct clnt_ops *clnt_dg_ops(void);
+static bool_t time_not_ok(struct timeval *);
+static enum clnt_stat clnt_dg_call(CLIENT *, rpcproc_t, xdrproc_t, void *,
+	    xdrproc_t, void *, struct timeval);
+static void clnt_dg_geterr(CLIENT *, struct rpc_err *);
+static bool_t clnt_dg_freeres(CLIENT *, xdrproc_t, void *);
+static void clnt_dg_abort(CLIENT *);
+static bool_t clnt_dg_control(CLIENT *, u_int, void *);
+static void clnt_dg_destroy(CLIENT *);
+
+
+
+
+/*
+ *	This machinery implements per-fd locks for MT-safety.  It is not
+ *	sufficient to do per-CLIENT handle locks for MT-safety because a
+ *	user may create more than one CLIENT handle with the same fd behind
+ *	it.  Therfore, we allocate an array of flags (dg_fd_locks), protected
+ *	by the clnt_fd_lock mutex, and an array (dg_cv) of condition variables
+ *	similarly protected.  Dg_fd_lock[fd] == 1 => a call is activte on some
+ *	CLIENT handle created for that fd.
+ *	The current implementation holds locks across the entire RPC and reply,
+ *	including retransmissions.  Yes, this is silly, and as soon as this
+ *	code is proven to work, this should be the first thing fixed.  One step
+ *	at a time.
+ */
+static int	*dg_fd_locks;
+static cond_t	*dg_cv;
+#define	release_fd_lock(fd, mask) {		\
+	mutex_lock(&clnt_fd_lock);	\
+	dg_fd_locks[fd] = 0;		\
+	mutex_unlock(&clnt_fd_lock);	\
+	thr_sigsetmask(SIG_SETMASK, &(mask), NULL); \
+	cond_signal(&dg_cv[fd]);	\
+}
+
+static const char mem_err_clnt_dg[] = "clnt_dg_create: out of memory";
+
+/* VARIABLES PROTECTED BY clnt_fd_lock: dg_fd_locks, dg_cv */
+
+#define	MCALL_MSG_SIZE 24
+
+/*
+ * Private data kept per client handle
+ */
+struct cu_data {
+	int			cu_fd;		/* connections fd */
+	bool_t			cu_closeit;	/* opened by library */
+	struct sockaddr_storage	cu_raddr;	/* remote address */
+	int			cu_rlen;
+	struct timeval		cu_wait;	/* retransmit interval */
+	struct timeval		cu_total;	/* total time for the call */
+	struct rpc_err		cu_error;
+	XDR			cu_outxdrs;
+	u_int			cu_xdrpos;
+	u_int			cu_sendsz;	/* send size */
+	char			cu_outhdr[MCALL_MSG_SIZE];
+	char			*cu_outbuf;
+	u_int			cu_recvsz;	/* recv size */
+	int			cu_async;
+	int			cu_connect;	/* Use connect(). */
+	int			cu_connected;	/* Have done connect(). */
+	struct kevent		cu_kin;
+	int			cu_kq;
+	char			cu_inbuf[1];
+};
+
+/*
+ * Connection less client creation returns with client handle parameters.
+ * Default options are set, which the user can change using clnt_control().
+ * fd should be open and bound.
+ * NB: The rpch->cl_auth is initialized to null authentication.
+ * 	Caller may wish to set this something more useful.
+ *
+ * sendsz and recvsz are the maximum allowable packet sizes that can be
+ * sent and received. Normally they are the same, but they can be
+ * changed to improve the program efficiency and buffer allocation.
+ * If they are 0, use the transport default.
+ *
+ * If svcaddr is NULL, returns NULL.
+ */
+CLIENT *
+clnt_dg_create(fd, svcaddr, program, version, sendsz, recvsz)
+	int fd;				/* open file descriptor */
+	const struct netbuf *svcaddr;	/* servers address */
+	rpcprog_t program;		/* program number */
+	rpcvers_t version;		/* version number */
+	u_int sendsz;			/* buffer recv size */
+	u_int recvsz;			/* buffer send size */
+{
+	CLIENT *cl = NULL;		/* client handle */
+	struct cu_data *cu = NULL;	/* private data */
+	struct timeval now;
+	struct rpc_msg call_msg;
+	sigset_t mask;
+	sigset_t newmask;
+	struct __rpc_sockinfo si;
+	int one = 1;
+
+	sigfillset(&newmask);
+	thr_sigsetmask(SIG_SETMASK, &newmask, &mask);
+	mutex_lock(&clnt_fd_lock);
+	if (dg_fd_locks == (int *) NULL) {
+		int cv_allocsz;
+		size_t fd_allocsz;
+		int dtbsize = __rpc_dtbsize();
+
+		fd_allocsz = dtbsize * sizeof (int);
+		dg_fd_locks = (int *) mem_alloc(fd_allocsz);
+		if (dg_fd_locks == (int *) NULL) {
+			mutex_unlock(&clnt_fd_lock);
+			thr_sigsetmask(SIG_SETMASK, &(mask), NULL);
+			goto err1;
+		} else
+			memset(dg_fd_locks, '\0', fd_allocsz);
+
+		cv_allocsz = dtbsize * sizeof (cond_t);
+		dg_cv = (cond_t *) mem_alloc(cv_allocsz);
+		if (dg_cv == (cond_t *) NULL) {
+			mem_free(dg_fd_locks, fd_allocsz);
+			dg_fd_locks = (int *) NULL;
+			mutex_unlock(&clnt_fd_lock);
+			thr_sigsetmask(SIG_SETMASK, &(mask), NULL);
+			goto err1;
+		} else {
+			int i;
+
+			for (i = 0; i < dtbsize; i++)
+				cond_init(&dg_cv[i], 0, (void *) 0);
+		}
+	}
+
+	mutex_unlock(&clnt_fd_lock);
+	thr_sigsetmask(SIG_SETMASK, &(mask), NULL);
+
+	if (svcaddr == NULL) {
+		rpc_createerr.cf_stat = RPC_UNKNOWNADDR;
+		return (NULL);
+	}
+
+	if (!__rpc_fd2sockinfo(fd, &si)) {
+		rpc_createerr.cf_stat = RPC_TLIERROR;
+		rpc_createerr.cf_error.re_errno = 0;
+		return (NULL);
+	}
+	/*
+	 * Find the receive and the send size
+	 */
+	sendsz = __rpc_get_t_size(si.si_af, si.si_proto, (int)sendsz);
+	recvsz = __rpc_get_t_size(si.si_af, si.si_proto, (int)recvsz);
+	if ((sendsz == 0) || (recvsz == 0)) {
+		rpc_createerr.cf_stat = RPC_TLIERROR; /* XXX */
+		rpc_createerr.cf_error.re_errno = 0;
+		return (NULL);
+	}
+
+	if ((cl = mem_alloc(sizeof (CLIENT))) == NULL)
+		goto err1;
+	/*
+	 * Should be multiple of 4 for XDR.
+	 */
+	sendsz = ((sendsz + 3) / 4) * 4;
+	recvsz = ((recvsz + 3) / 4) * 4;
+	cu = mem_alloc(sizeof (*cu) + sendsz + recvsz);
+	if (cu == NULL)
+		goto err1;
+	(void) memcpy(&cu->cu_raddr, svcaddr->buf, (size_t)svcaddr->len);
+	cu->cu_rlen = svcaddr->len;
+	cu->cu_outbuf = &cu->cu_inbuf[recvsz];
+	/* Other values can also be set through clnt_control() */
+	cu->cu_wait.tv_sec = 15;	/* heuristically chosen */
+	cu->cu_wait.tv_usec = 0;
+	cu->cu_total.tv_sec = -1;
+	cu->cu_total.tv_usec = -1;
+	cu->cu_sendsz = sendsz;
+	cu->cu_recvsz = recvsz;
+	cu->cu_async = FALSE;
+	cu->cu_connect = FALSE;
+	cu->cu_connected = FALSE;
+	(void) gettimeofday(&now, NULL);
+	call_msg.rm_xid = __RPC_GETXID(&now);
+	call_msg.rm_call.cb_prog = program;
+	call_msg.rm_call.cb_vers = version;
+	xdrmem_create(&(cu->cu_outxdrs), cu->cu_outhdr, MCALL_MSG_SIZE,
+	    XDR_ENCODE);
+	if (! xdr_callhdr(&cu->cu_outxdrs, &call_msg)) {
+		rpc_createerr.cf_stat = RPC_CANTENCODEARGS;  /* XXX */
+		rpc_createerr.cf_error.re_errno = 0;
+		goto err2;
+	}
+	cu->cu_xdrpos = XDR_GETPOS(&(cu->cu_outxdrs));
+	XDR_DESTROY(&cu->cu_outxdrs);
+	xdrmem_create(&cu->cu_outxdrs, cu->cu_outbuf, sendsz, XDR_ENCODE);
+
+	/* XXX fvdl - do we still want this? */
+#if 0
+	(void)bindresvport_sa(fd, (struct sockaddr *)svcaddr->buf);
+#endif
+	_ioctl(fd, FIONBIO, (char *)(void *)&one);
+
+	/*
+	 * By default, closeit is always FALSE. It is users responsibility
+	 * to do a close on it, else the user may use clnt_control
+	 * to let clnt_destroy do it for him/her.
+	 */
+	cu->cu_closeit = FALSE;
+	cu->cu_fd = fd;
+	cl->cl_ops = clnt_dg_ops();
+	cl->cl_private = (caddr_t)(void *)cu;
+	cl->cl_auth = authnone_create();
+	cl->cl_tp = NULL;
+	cl->cl_netid = NULL;
+	cu->cu_kq = -1;
+	EV_SET(&cu->cu_kin, cu->cu_fd, EVFILT_READ, EV_ADD, 0, 0, 0);
+	return (cl);
+err1:
+	warnx(mem_err_clnt_dg);
+	rpc_createerr.cf_stat = RPC_SYSTEMERROR;
+	rpc_createerr.cf_error.re_errno = errno;
+err2:
+	if (cl) {
+		mem_free(cl, sizeof (CLIENT));
+		if (cu)
+			mem_free(cu, sizeof (*cu) + sendsz + recvsz);
+	}
+	return (NULL);
+}
+
+static enum clnt_stat
+clnt_dg_call(cl, proc, xargs, argsp, xresults, resultsp, utimeout)
+	CLIENT	*cl;			/* client handle */
+	rpcproc_t	proc;		/* procedure number */
+	xdrproc_t	xargs;		/* xdr routine for args */
+	void		*argsp;		/* pointer to args */
+	xdrproc_t	xresults;	/* xdr routine for results */
+	void		*resultsp;	/* pointer to results */
+	struct timeval	utimeout;	/* seconds to wait before giving up */
+{
+	struct cu_data *cu = (struct cu_data *)cl->cl_private;
+	XDR *xdrs;
+	size_t outlen = 0;
+	struct rpc_msg reply_msg;
+	XDR reply_xdrs;
+	bool_t ok;
+	int nrefreshes = 2;		/* number of times to refresh cred */
+	int nretries = 0;		/* number of times we retransmitted */
+	struct timeval timeout;
+	struct timeval retransmit_time;
+	struct timeval next_sendtime, starttime, time_waited, tv;
+	struct timespec ts;
+	struct kevent kv;
+	struct sockaddr *sa;
+	sigset_t mask;
+	sigset_t newmask;
+	socklen_t inlen, salen;
+	ssize_t recvlen = 0;
+	int kin_len, n, rpc_lock_value;
+	u_int32_t xid;
+
+	outlen = 0;
+	sigfillset(&newmask);
+	thr_sigsetmask(SIG_SETMASK, &newmask, &mask);
+	mutex_lock(&clnt_fd_lock);
+	while (dg_fd_locks[cu->cu_fd])
+		cond_wait(&dg_cv[cu->cu_fd], &clnt_fd_lock);
+	if (__isthreaded)
+		rpc_lock_value = 1;
+	else
+		rpc_lock_value = 0;
+	dg_fd_locks[cu->cu_fd] = rpc_lock_value;
+	mutex_unlock(&clnt_fd_lock);
+	if (cu->cu_total.tv_usec == -1) {
+		timeout = utimeout;	/* use supplied timeout */
+	} else {
+		timeout = cu->cu_total;	/* use default timeout */
+	}
+
+	if (cu->cu_connect && !cu->cu_connected) {
+		if (_connect(cu->cu_fd, (struct sockaddr *)&cu->cu_raddr,
+		    cu->cu_rlen) < 0) {
+			cu->cu_error.re_errno = errno;
+			cu->cu_error.re_status = RPC_CANTSEND;
+			goto out;
+		}
+		cu->cu_connected = 1;
+	}
+	if (cu->cu_connected) {
+		sa = NULL;
+		salen = 0;
+	} else {
+		sa = (struct sockaddr *)&cu->cu_raddr;
+		salen = cu->cu_rlen;
+	}
+	time_waited.tv_sec = 0;
+	time_waited.tv_usec = 0;
+	retransmit_time = next_sendtime = cu->cu_wait;
+	gettimeofday(&starttime, NULL);
+
+	/* Clean up in case the last call ended in a longjmp(3) call. */
+	if (cu->cu_kq >= 0)
+		_close(cu->cu_kq);
+	if ((cu->cu_kq = kqueue()) < 0) {
+		cu->cu_error.re_errno = errno;
+		cu->cu_error.re_status = RPC_CANTSEND;
+		goto out;
+	}
+	kin_len = 1;
+
+call_again:
+	if (cu->cu_async == TRUE && xargs == NULL)
+		goto get_reply;
+	/*
+	 * the transaction is the first thing in the out buffer
+	 * XXX Yes, and it's in network byte order, so we should to
+	 * be careful when we increment it, shouldn't we.
+	 */
+	xid = ntohl(*(u_int32_t *)(void *)(cu->cu_outhdr));
+	xid++;
+	*(u_int32_t *)(void *)(cu->cu_outhdr) = htonl(xid);
+call_again_same_xid:
+	xdrs = &(cu->cu_outxdrs);
+	xdrs->x_op = XDR_ENCODE;
+	XDR_SETPOS(xdrs, 0);
+
+	if (cl->cl_auth->ah_cred.oa_flavor != RPCSEC_GSS) {
+		if ((! XDR_PUTBYTES(xdrs, cu->cu_outhdr, cu->cu_xdrpos)) ||
+		    (! XDR_PUTINT32(xdrs, &proc)) ||
+		    (! AUTH_MARSHALL(cl->cl_auth, xdrs)) ||
+		    (! (*xargs)(xdrs, argsp))) {
+			cu->cu_error.re_status = RPC_CANTENCODEARGS;
+			goto out;
+		}
+	} else {
+		*(uint32_t *) &cu->cu_outhdr[cu->cu_xdrpos] = htonl(proc);
+		if (!__rpc_gss_wrap(cl->cl_auth, cu->cu_outhdr,
+			cu->cu_xdrpos + sizeof(uint32_t),
+			xdrs, xargs, argsp)) {
+			cu->cu_error.re_status = RPC_CANTENCODEARGS;
+			goto out;
+		}
+	}
+	outlen = (size_t)XDR_GETPOS(xdrs);
+
+send_again:
+	if (_sendto(cu->cu_fd, cu->cu_outbuf, outlen, 0, sa, salen) != outlen) {
+		cu->cu_error.re_errno = errno;
+		cu->cu_error.re_status = RPC_CANTSEND;
+		goto out;
+	}
+
+	/*
+	 * Hack to provide rpc-based message passing
+	 */
+	if (timeout.tv_sec == 0 && timeout.tv_usec == 0) {
+		cu->cu_error.re_status = RPC_TIMEDOUT;
+		goto out;
+	}
+
+get_reply:
+
+	/*
+	 * sub-optimal code appears here because we have
+	 * some clock time to spare while the packets are in flight.
+	 * (We assume that this is actually only executed once.)
+	 */
+	reply_msg.acpted_rply.ar_verf = _null_auth;
+	if (cl->cl_auth->ah_cred.oa_flavor != RPCSEC_GSS) {
+		reply_msg.acpted_rply.ar_results.where = resultsp;
+		reply_msg.acpted_rply.ar_results.proc = xresults;
+	} else {
+		reply_msg.acpted_rply.ar_results.where = NULL;
+		reply_msg.acpted_rply.ar_results.proc = (xdrproc_t)xdr_void;
+	}
+
+	for (;;) {
+		/* Decide how long to wait. */
+		if (timercmp(&next_sendtime, &timeout, <))
+			timersub(&next_sendtime, &time_waited, &tv);
+		else
+			timersub(&timeout, &time_waited, &tv);
+		if (tv.tv_sec < 0 || tv.tv_usec < 0)
+			tv.tv_sec = tv.tv_usec = 0;
+		TIMEVAL_TO_TIMESPEC(&tv, &ts);
+
+		n = _kevent(cu->cu_kq, &cu->cu_kin, kin_len, &kv, 1, &ts);
+		/* We don't need to register the event again. */
+		kin_len = 0;
+
+		if (n == 1) {
+			if (kv.flags & EV_ERROR) {
+				cu->cu_error.re_errno = kv.data;
+				cu->cu_error.re_status = RPC_CANTRECV;
+				goto out;
+			}
+			/* We have some data now */
+			do {
+				recvlen = _recvfrom(cu->cu_fd, cu->cu_inbuf,
+				    cu->cu_recvsz, 0, NULL, NULL);
+			} while (recvlen < 0 && errno == EINTR);
+			if (recvlen < 0 && errno != EWOULDBLOCK) {
+				cu->cu_error.re_errno = errno;
+				cu->cu_error.re_status = RPC_CANTRECV;
+				goto out;
+			}
+			if (recvlen >= sizeof(u_int32_t) &&
+			    (cu->cu_async == TRUE ||
+			    *((u_int32_t *)(void *)(cu->cu_inbuf)) ==
+			    *((u_int32_t *)(void *)(cu->cu_outbuf)))) {
+				/* We now assume we have the proper reply. */
+				break;
+			}
+		}
+		if (n == -1 && errno != EINTR) {
+			cu->cu_error.re_errno = errno;
+			cu->cu_error.re_status = RPC_CANTRECV;
+			goto out;
+		}
+		gettimeofday(&tv, NULL);
+		timersub(&tv, &starttime, &time_waited);
+
+		/* Check for timeout. */
+		if (timercmp(&time_waited, &timeout, >)) {
+			cu->cu_error.re_status = RPC_TIMEDOUT;
+			goto out;
+		}
+
+		/* Retransmit if necessary. */		
+		if (timercmp(&time_waited, &next_sendtime, >)) {
+			/* update retransmit_time */
+			if (retransmit_time.tv_sec < RPC_MAX_BACKOFF)
+				timeradd(&retransmit_time, &retransmit_time,
+				    &retransmit_time);
+			timeradd(&next_sendtime, &retransmit_time,
+			    &next_sendtime);
+			nretries++;
+
+			/*
+			 * When retransmitting a RPCSEC_GSS message,
+			 * we must use a new sequence number (handled
+			 * by __rpc_gss_wrap above).
+			 */
+			if (cl->cl_auth->ah_cred.oa_flavor != RPCSEC_GSS)
+				goto send_again;
+			else
+				goto call_again_same_xid;
+		}
+	}
+	inlen = (socklen_t)recvlen;
+
+	/*
+	 * now decode and validate the response
+	 */
+
+	xdrmem_create(&reply_xdrs, cu->cu_inbuf, (u_int)recvlen, XDR_DECODE);
+	ok = xdr_replymsg(&reply_xdrs, &reply_msg);
+	/* XDR_DESTROY(&reply_xdrs);	save a few cycles on noop destroy */
+	if (ok) {
+		if ((reply_msg.rm_reply.rp_stat == MSG_ACCEPTED) &&
+			(reply_msg.acpted_rply.ar_stat == SUCCESS))
+			cu->cu_error.re_status = RPC_SUCCESS;
+		else
+			_seterr_reply(&reply_msg, &(cu->cu_error));
+
+		if (cu->cu_error.re_status == RPC_SUCCESS) {
+			if (! AUTH_VALIDATE(cl->cl_auth,
+					    &reply_msg.acpted_rply.ar_verf)) {
+				if (nretries &&
+				    cl->cl_auth->ah_cred.oa_flavor
+				    == RPCSEC_GSS)
+					/*
+					 * If we retransmitted, its
+					 * possible that we will
+					 * receive a reply for one of
+					 * the earlier transmissions
+					 * (which will use an older
+					 * RPCSEC_GSS sequence
+					 * number). In this case, just
+					 * go back and listen for a
+					 * new reply. We could keep a
+					 * record of all the seq
+					 * numbers we have transmitted
+					 * so far so that we could
+					 * accept a reply for any of
+					 * them here.
+					 */
+					goto get_reply;
+				cu->cu_error.re_status = RPC_AUTHERROR;
+				cu->cu_error.re_why = AUTH_INVALIDRESP;
+			} else {
+				if (cl->cl_auth->ah_cred.oa_flavor
+				    == RPCSEC_GSS) {
+					if (!__rpc_gss_unwrap(cl->cl_auth,
+						&reply_xdrs, xresults,
+						resultsp))
+						cu->cu_error.re_status =
+							RPC_CANTDECODERES;
+				}
+			}
+			if (reply_msg.acpted_rply.ar_verf.oa_base != NULL) {
+				xdrs->x_op = XDR_FREE;
+				(void) xdr_opaque_auth(xdrs,
+					&(reply_msg.acpted_rply.ar_verf));
+			}
+		}		/* end successful completion */
+		/*
+		 * If unsuccesful AND error is an authentication error
+		 * then refresh credentials and try again, else break
+		 */
+		else if (cu->cu_error.re_status == RPC_AUTHERROR)
+			/* maybe our credentials need to be refreshed ... */
+			if (nrefreshes > 0 &&
+			    AUTH_REFRESH(cl->cl_auth, &reply_msg)) {
+				nrefreshes--;
+				goto call_again;
+			}
+		/* end of unsuccessful completion */
+	}	/* end of valid reply message */
+	else {
+		cu->cu_error.re_status = RPC_CANTDECODERES;
+
+	}
+out:
+	if (cu->cu_kq >= 0)
+		_close(cu->cu_kq);
+	cu->cu_kq = -1;
+	release_fd_lock(cu->cu_fd, mask);
+	return (cu->cu_error.re_status);
+}
+
+static void
+clnt_dg_geterr(cl, errp)
+	CLIENT *cl;
+	struct rpc_err *errp;
+{
+	struct cu_data *cu = (struct cu_data *)cl->cl_private;
+
+	*errp = cu->cu_error;
+}
+
+static bool_t
+clnt_dg_freeres(cl, xdr_res, res_ptr)
+	CLIENT *cl;
+	xdrproc_t xdr_res;
+	void *res_ptr;
+{
+	struct cu_data *cu = (struct cu_data *)cl->cl_private;
+	XDR *xdrs = &(cu->cu_outxdrs);
+	bool_t dummy;
+	sigset_t mask;
+	sigset_t newmask;
+
+	sigfillset(&newmask);
+	thr_sigsetmask(SIG_SETMASK, &newmask, &mask);
+	mutex_lock(&clnt_fd_lock);
+	while (dg_fd_locks[cu->cu_fd])
+		cond_wait(&dg_cv[cu->cu_fd], &clnt_fd_lock);
+	xdrs->x_op = XDR_FREE;
+	dummy = (*xdr_res)(xdrs, res_ptr);
+	mutex_unlock(&clnt_fd_lock);
+	thr_sigsetmask(SIG_SETMASK, &mask, NULL);
+	cond_signal(&dg_cv[cu->cu_fd]);
+	return (dummy);
+}
+
+/*ARGSUSED*/
+static void
+clnt_dg_abort(h)
+	CLIENT *h;
+{
+}
+
+static bool_t
+clnt_dg_control(cl, request, info)
+	CLIENT *cl;
+	u_int request;
+	void *info;
+{
+	struct cu_data *cu = (struct cu_data *)cl->cl_private;
+	struct netbuf *addr;
+	sigset_t mask;
+	sigset_t newmask;
+	int rpc_lock_value;
+
+	sigfillset(&newmask);
+	thr_sigsetmask(SIG_SETMASK, &newmask, &mask);
+	mutex_lock(&clnt_fd_lock);
+	while (dg_fd_locks[cu->cu_fd])
+		cond_wait(&dg_cv[cu->cu_fd], &clnt_fd_lock);
+	if (__isthreaded)
+                rpc_lock_value = 1;
+        else
+                rpc_lock_value = 0;
+	dg_fd_locks[cu->cu_fd] = rpc_lock_value;
+	mutex_unlock(&clnt_fd_lock);
+	switch (request) {
+	case CLSET_FD_CLOSE:
+		cu->cu_closeit = TRUE;
+		release_fd_lock(cu->cu_fd, mask);
+		return (TRUE);
+	case CLSET_FD_NCLOSE:
+		cu->cu_closeit = FALSE;
+		release_fd_lock(cu->cu_fd, mask);
+		return (TRUE);
+	}
+
+	/* for other requests which use info */
+	if (info == NULL) {
+		release_fd_lock(cu->cu_fd, mask);
+		return (FALSE);
+	}
+	switch (request) {
+	case CLSET_TIMEOUT:
+		if (time_not_ok((struct timeval *)info)) {
+			release_fd_lock(cu->cu_fd, mask);
+			return (FALSE);
+		}
+		cu->cu_total = *(struct timeval *)info;
+		break;
+	case CLGET_TIMEOUT:
+		*(struct timeval *)info = cu->cu_total;
+		break;
+	case CLGET_SERVER_ADDR:		/* Give him the fd address */
+		/* Now obsolete. Only for backward compatibility */
+		(void) memcpy(info, &cu->cu_raddr, (size_t)cu->cu_rlen);
+		break;
+	case CLSET_RETRY_TIMEOUT:
+		if (time_not_ok((struct timeval *)info)) {
+			release_fd_lock(cu->cu_fd, mask);
+			return (FALSE);
+		}
+		cu->cu_wait = *(struct timeval *)info;
+		break;
+	case CLGET_RETRY_TIMEOUT:
+		*(struct timeval *)info = cu->cu_wait;
+		break;
+	case CLGET_FD:
+		*(int *)info = cu->cu_fd;
+		break;
+	case CLGET_SVC_ADDR:
+		addr = (struct netbuf *)info;
+		addr->buf = &cu->cu_raddr;
+		addr->len = cu->cu_rlen;
+		addr->maxlen = sizeof cu->cu_raddr;
+		break;
+	case CLSET_SVC_ADDR:		/* set to new address */
+		addr = (struct netbuf *)info;
+		if (addr->len < sizeof cu->cu_raddr) {
+			release_fd_lock(cu->cu_fd, mask);
+			return (FALSE);
+		}
+		(void) memcpy(&cu->cu_raddr, addr->buf, addr->len);
+		cu->cu_rlen = addr->len;
+		break;
+	case CLGET_XID:
+		/*
+		 * use the knowledge that xid is the
+		 * first element in the call structure *.
+		 * This will get the xid of the PREVIOUS call
+		 */
+		*(u_int32_t *)info =
+		    ntohl(*(u_int32_t *)(void *)cu->cu_outhdr);
+		break;
+
+	case CLSET_XID:
+		/* This will set the xid of the NEXT call */
+		*(u_int32_t *)(void *)cu->cu_outhdr =
+		    htonl(*(u_int32_t *)info - 1);
+		/* decrement by 1 as clnt_dg_call() increments once */
+		break;
+
+	case CLGET_VERS:
+		/*
+		 * This RELIES on the information that, in the call body,
+		 * the version number field is the fifth field from the
+		 * begining of the RPC header. MUST be changed if the
+		 * call_struct is changed
+		 */
+		*(u_int32_t *)info =
+		    ntohl(*(u_int32_t *)(void *)(cu->cu_outhdr +
+		    4 * BYTES_PER_XDR_UNIT));
+		break;
+
+	case CLSET_VERS:
+		*(u_int32_t *)(void *)(cu->cu_outhdr + 4 * BYTES_PER_XDR_UNIT)
+			= htonl(*(u_int32_t *)info);
+		break;
+
+	case CLGET_PROG:
+		/*
+		 * This RELIES on the information that, in the call body,
+		 * the program number field is the fourth field from the
+		 * begining of the RPC header. MUST be changed if the
+		 * call_struct is changed
+		 */
+		*(u_int32_t *)info =
+		    ntohl(*(u_int32_t *)(void *)(cu->cu_outhdr +
+		    3 * BYTES_PER_XDR_UNIT));
+		break;
+
+	case CLSET_PROG:
+		*(u_int32_t *)(void *)(cu->cu_outhdr + 3 * BYTES_PER_XDR_UNIT)
+			= htonl(*(u_int32_t *)info);
+		break;
+	case CLSET_ASYNC:
+		cu->cu_async = *(int *)info;
+		break;
+	case CLSET_CONNECT:
+		cu->cu_connect = *(int *)info;
+		break;
+	default:
+		release_fd_lock(cu->cu_fd, mask);
+		return (FALSE);
+	}
+	release_fd_lock(cu->cu_fd, mask);
+	return (TRUE);
+}
+
+static void
+clnt_dg_destroy(cl)
+	CLIENT *cl;
+{
+	struct cu_data *cu = (struct cu_data *)cl->cl_private;
+	int cu_fd = cu->cu_fd;
+	sigset_t mask;
+	sigset_t newmask;
+
+	sigfillset(&newmask);
+	thr_sigsetmask(SIG_SETMASK, &newmask, &mask);
+	mutex_lock(&clnt_fd_lock);
+	while (dg_fd_locks[cu_fd])
+		cond_wait(&dg_cv[cu_fd], &clnt_fd_lock);
+	if (cu->cu_closeit)
+		(void)_close(cu_fd);
+	if (cu->cu_kq >= 0)
+		_close(cu->cu_kq);
+	XDR_DESTROY(&(cu->cu_outxdrs));
+	mem_free(cu, (sizeof (*cu) + cu->cu_sendsz + cu->cu_recvsz));
+	if (cl->cl_netid && cl->cl_netid[0])
+		mem_free(cl->cl_netid, strlen(cl->cl_netid) +1);
+	if (cl->cl_tp && cl->cl_tp[0])
+		mem_free(cl->cl_tp, strlen(cl->cl_tp) +1);
+	mem_free(cl, sizeof (CLIENT));
+	mutex_unlock(&clnt_fd_lock);
+	thr_sigsetmask(SIG_SETMASK, &mask, NULL);
+	cond_signal(&dg_cv[cu_fd]);
+}
+
+static struct clnt_ops *
+clnt_dg_ops()
+{
+	static struct clnt_ops ops;
+	sigset_t mask;
+	sigset_t newmask;
+
+/* VARIABLES PROTECTED BY ops_lock: ops */
+
+	sigfillset(&newmask);
+	thr_sigsetmask(SIG_SETMASK, &newmask, &mask);
+	mutex_lock(&ops_lock);
+	if (ops.cl_call == NULL) {
+		ops.cl_call = clnt_dg_call;
+		ops.cl_abort = clnt_dg_abort;
+		ops.cl_geterr = clnt_dg_geterr;
+		ops.cl_freeres = clnt_dg_freeres;
+		ops.cl_destroy = clnt_dg_destroy;
+		ops.cl_control = clnt_dg_control;
+	}
+	mutex_unlock(&ops_lock);
+	thr_sigsetmask(SIG_SETMASK, &mask, NULL);
+	return (&ops);
+}
+
+/*
+ * Make sure that the time is not garbage.  -1 value is allowed.
+ */
+static bool_t
+time_not_ok(t)
+	struct timeval *t;
+{
+	return (t->tv_sec < -1 || t->tv_sec > 100000000 ||
+		t->tv_usec < -1 || t->tv_usec > 1000000);
+}
+
Index: freebsd/lib/libc/rpc/clnt_generic.c
===================================================================
--- freebsd/lib/libc/rpc/clnt_generic.c	(revision 60b1d40751c8b3235b7ccbf3bb6ad0c562562f01)
+++ freebsd/lib/libc/rpc/clnt_generic.c	(revision 60b1d40751c8b3235b7ccbf3bb6ad0c562562f01)
@@ -0,0 +1,450 @@
+#include <machine/rtems-bsd-user-space.h>
+
+/*	$NetBSD: clnt_generic.c,v 1.18 2000/07/06 03:10:34 christos Exp $	*/
+
+/*-
+ * Copyright (c) 2010, Oracle America, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice,
+ *   this list of conditions and the following disclaimer in the documentation
+ *   and/or other materials provided with the distribution.
+ * - Neither the name of the "Oracle America, Inc." nor the names of its
+ *   contributors may be used to endorse or promote products derived
+ *   from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* #ident	"@(#)clnt_generic.c	1.40	99/04/21 SMI" */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char *sccsid2 = "from: @(#)clnt_generic.c 1.4 87/08/11 (C) 1987 SMI";
+static char *sccsid = "from: @(#)clnt_generic.c	2.2 88/08/01 4.0 RPCSRC";
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * 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>
+#include <stdlib.h>
+#include <unistd.h>
+#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(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_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);
+	if (rpc_stat == RPC_SUCCESS) {
+		*vers_out = vers_high;
+		return (clnt);
+	}
+	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 = maxvers;
+		else
+			vers_high--;
+		if (minvers > vers_low)
+			vers_low = minvers;
+		if (vers_low > vers_high) {
+			goto error;
+		}
+		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);
+		}
+	}
+	clnt_geterr(clnt, &rpcerr);
+
+error:
+	rpc_createerr.cf_stat = rpc_stat;
+	rpc_createerr.cf_error = rpcerr;
+	clnt_destroy(clnt);
+	return (NULL);
+}
+
+/*
+ * Top level client creation routine.
+ * Generic client creation: takes (servers name, program-number, nettype) and
+ * returns client handle. Default options are set, which the user can
+ * change using the rpc equivalent of _ioctl()'s.
+ *
+ * It tries for all the netids in that particular class of netid until
+ * it succeeds.
+ * XXX The error message in the case of failure will be the one
+ * pertaining to the last create error.
+ *
+ * It calls clnt_create_timed() with the default timeout.
+ */
+CLIENT *
+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((char *)nettype)) == NULL) {
+		rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
+		return (NULL);
+	}
+	rpc_createerr.cf_stat = RPC_SUCCESS;
+	while (clnt == NULL) {
+		if ((nconf = __rpc_getconf(handle)) == NULL) {
+			if (rpc_createerr.cf_stat == RPC_SUCCESS)
+				rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
+			break;
+		}
+#ifdef CLNT_DEBUG
+		printf("trying netid %s\n", nconf->nc_netid);
+#endif
+		clnt = clnt_tp_create_timed(hostname, prog, vers, nconf, tp);
+		if (clnt)
+			break;
+		else
+			/*
+			 *	Since we didn't get a name-to-address
+			 *	translation failure here, we remember
+			 *	this particular error.  The object of
+			 *	this is to enable us to return to the
+			 *	caller a more-specific error than the
+			 *	unhelpful ``Name to address translation
+			 *	failed'' which might well occur if we
+			 *	merely returned the last error (because
+			 *	the local loopbacks are typically the
+			 *	last ones in /etc/netconfig and the most
+			 *	likely to be unable to translate a host
+			 *	name).  We also check for a more
+			 *	meaningful error than ``unknown host
+			 *	name'' for the same reasons.
+			 */
+			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;
+			}
+	}
+
+	/*
+	 *	Attempt to return an error more specific than ``Name to address
+	 *	translation failed'' or ``unknown host name''
+	 */
+	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;
+	}
+	__rpc_endconf(handle);
+	return (clnt);
+}
+
+/*
+ * 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 calls clnt_tp_create_timed() with the default timeout.
+ */
+CLIENT *
+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 */
+
+	if (nconf == NULL) {
+		rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
+		return (NULL);
+	}
+
+	/*
+	 * Get the address of the server
+	 */
+	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);
+	}
+	if (cl == NULL) {
+		cl = clnt_tli_create(RPC_ANYFD, nconf, svcaddr,
+					prog, vers, 0, 0);
+	} else {
+		/* Reuse the CLIENT handle and change the appropriate fields */
+		if (CLNT_CONTROL(cl, CLSET_SVC_ADDR, (void *)svcaddr) == TRUE) {
+			if (cl->cl_netid == NULL)
+				cl->cl_netid = strdup(nconf->nc_netid);
+			if (cl->cl_tp == NULL)
+				cl->cl_tp = strdup(nconf->nc_device);
+			(void) CLNT_CONTROL(cl, CLSET_PROG, (void *)&prog);
+			(void) CLNT_CONTROL(cl, CLSET_VERS, (void *)&vers);
+		} else {
+			CLNT_DESTROY(cl);
+			cl = clnt_tli_create(RPC_ANYFD, nconf, svcaddr,
+					prog, vers, 0, 0);
+		}
+	}
+	free(svcaddr->buf);
+	free(svcaddr);
+	return (cl);
+}
+
+/*
+ * Generic client creation:  returns client handle.
+ * Default options are set, which the user can
+ * change using the rpc equivalent of _ioctl()'s : clnt_control().
+ * If fd is RPC_ANYFD, it will be opened using nconf.
+ * It will be bound if not so.
+ * If sizes are 0; appropriate defaults will be chosen.
+ */
+CLIENT *
+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) {
+			rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
+			return (NULL);
+		}
+
+		fd = __rpc_nconf2fd(nconf);
+
+		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))
+			goto err;
+		servtype = __rpc_socktype2seman(si.si_socktype);
+		if (servtype == -1) {
+			rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
+			return (NULL);
+		}
+	}
+
+	if (si.si_af != ((struct sockaddr *)svcaddr->buf)->sa_family) {
+		rpc_createerr.cf_stat = RPC_UNKNOWNHOST;	/* XXX */
+		goto err1;
+	}
+
+	switch (servtype) {
+	case NC_TPI_COTS:
+		cl = clnt_vc_create(fd, svcaddr, prog, vers, sendsz, recvsz);
+		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);
+		break;
+	default:
+		goto err;
+	}
+
+	if (cl == NULL)
+		goto err1; /* borrow errors from clnt_dg/vc creates */
+	if (nconf) {
+		cl->cl_netid = strdup(nconf->nc_netid);
+		cl->cl_tp = strdup(nconf->nc_device);
+	} else {
+		cl->cl_netid = "";
+		cl->cl_tp = "";
+	}
+	if (madefd) {
+		(void) CLNT_CONTROL(cl, CLSET_FD_CLOSE, NULL);
+/*		(void) CLNT_CONTROL(cl, CLSET_POP_TIMOD, NULL);  */
+	};
+
+	return (cl);
+
+err:
+	rpc_createerr.cf_stat = RPC_SYSTEMERROR;
+	rpc_createerr.cf_error.re_errno = errno;
+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);
+}
Index: freebsd/lib/libc/rpc/clnt_perror.c
===================================================================
--- freebsd/lib/libc/rpc/clnt_perror.c	(revision 60b1d40751c8b3235b7ccbf3bb6ad0c562562f01)
+++ freebsd/lib/libc/rpc/clnt_perror.c	(revision 60b1d40751c8b3235b7ccbf3bb6ad0c562562f01)
@@ -0,0 +1,334 @@
+#include <machine/rtems-bsd-user-space.h>
+
+/*	$NetBSD: clnt_perror.c,v 1.24 2000/06/02 23:11:07 fvdl Exp $	*/
+
+
+/*-
+ * Copyright (c) 2009, Sun Microsystems, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions are met:
+ * - Redistributions of source code must retain the above copyright notice, 
+ *   this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice, 
+ *   this list of conditions and the following disclaimer in the documentation 
+ *   and/or other materials provided with the distribution.
+ * - Neither the name of Sun Microsystems, Inc. nor the names of its 
+ *   contributors may be used to endorse or promote products derived 
+ *   from this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char *sccsid2 = "@(#)clnt_perror.c 1.15 87/10/07 Copyr 1984 Sun Micro";
+static char *sccsid = "@(#)clnt_perror.c	2.1 88/07/29 4.0 RPCSRC";
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * clnt_perror.c
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ *
+ */
+#include "namespace.h"
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <rpc/rpc.h>
+#include <rpc/types.h>
+#include <rpc/auth.h>
+#include <rpc/clnt.h>
+#include "un-namespace.h"
+
+static char *buf;
+
+static char *_buf(void);
+static char *auth_errmsg(enum auth_stat);
+#define CLNT_PERROR_BUFLEN 256
+
+static char *
+_buf()
+{
+
+	if (buf == 0)
+		buf = (char *)malloc(CLNT_PERROR_BUFLEN);
+	return (buf);
+}
+
+/*
+ * Print reply error info
+ */
+char *
+clnt_sperror(rpch, s)
+	CLIENT *rpch;
+	const char *s;
+{
+	struct rpc_err e;
+	char *err;
+	char *str;
+	char *strstart;
+	size_t len, i;
+
+	assert(rpch != NULL);
+	assert(s != NULL);
+
+	str = _buf(); /* side effect: sets CLNT_PERROR_BUFLEN */
+	if (str == 0)
+		return (0);
+	len = CLNT_PERROR_BUFLEN;
+	strstart = str;
+	CLNT_GETERR(rpch, &e);
+
+	if ((i = snprintf(str, len, "%s: ", s)) > 0) {
+		str += i;
+		len -= i;
+	}
+
+	(void)strncpy(str, clnt_sperrno(e.re_status), len - 1);
+	i = strlen(str);
+	str += i;
+	len -= i;
+
+	switch (e.re_status) {
+	case RPC_SUCCESS:
+	case RPC_CANTENCODEARGS:
+	case RPC_CANTDECODERES:
+	case RPC_TIMEDOUT:
+	case RPC_PROGUNAVAIL:
+	case RPC_PROCUNAVAIL:
+	case RPC_CANTDECODEARGS:
+	case RPC_SYSTEMERROR:
+	case RPC_UNKNOWNHOST:
+	case RPC_UNKNOWNPROTO:
+	case RPC_PMAPFAILURE:
+	case RPC_PROGNOTREGISTERED:
+	case RPC_FAILED:
+		break;
+
+	case RPC_CANTSEND:
+	case RPC_CANTRECV:
+		i = snprintf(str, len, "; errno = %s", strerror(e.re_errno)); 
+		if (i > 0) {
+			str += i;
+			len -= i;
+		}
+		break;
+
+	case RPC_VERSMISMATCH:
+		i = snprintf(str, len, "; low version = %u, high version = %u", 
+			e.re_vers.low, e.re_vers.high);
+		if (i > 0) {
+			str += i;
+			len -= i;
+		}
+		break;
+
+	case RPC_AUTHERROR:
+		err = auth_errmsg(e.re_why);
+		i = snprintf(str, len, "; why = ");
+		if (i > 0) {
+			str += i;
+			len -= i;
+		}
+		if (err != NULL) {
+			i = snprintf(str, len, "%s",err);
+		} else {
+			i = snprintf(str, len,
+				"(unknown authentication error - %d)",
+				(int) e.re_why);
+		}
+		if (i > 0) {
+			str += i;
+			len -= i;
+		}
+		break;
+
+	case RPC_PROGVERSMISMATCH:
+		i = snprintf(str, len, "; low version = %u, high version = %u", 
+			e.re_vers.low, e.re_vers.high);
+		if (i > 0) {
+			str += i;
+			len -= i;
+		}
+		break;
+
+	default:	/* unknown */
+		i = snprintf(str, len, "; s1 = %u, s2 = %u", 
+			e.re_lb.s1, e.re_lb.s2);
+		if (i > 0) {
+			str += i;
+			len -= i;
+		}
+		break;
+	}
+	strstart[CLNT_PERROR_BUFLEN-1] = '\0';
+	return(strstart) ;
+}
+
+void
+clnt_perror(rpch, s)
+	CLIENT *rpch;
+	const char *s;
+{
+
+	assert(rpch != NULL);
+	assert(s != NULL);
+
+	(void) fprintf(stderr, "%s\n", clnt_sperror(rpch,s));
+}
+
+static const char *const rpc_errlist[] = {
+	"RPC: Success",				/*  0 - RPC_SUCCESS */
+	"RPC: Can't encode arguments",		/*  1 - RPC_CANTENCODEARGS */
+	"RPC: Can't decode result",		/*  2 - RPC_CANTDECODERES */
+	"RPC: Unable to send",			/*  3 - RPC_CANTSEND */
+	"RPC: Unable to receive",		/*  4 - RPC_CANTRECV */
+	"RPC: Timed out",			/*  5 - RPC_TIMEDOUT */
+	"RPC: Incompatible versions of RPC",	/*  6 - RPC_VERSMISMATCH */
+	"RPC: Authentication error",		/*  7 - RPC_AUTHERROR */
+	"RPC: Program unavailable",		/*  8 - RPC_PROGUNAVAIL */
+	"RPC: Program/version mismatch",	/*  9 - RPC_PROGVERSMISMATCH */
+	"RPC: Procedure unavailable",		/* 10 - RPC_PROCUNAVAIL */
+	"RPC: Server can't decode arguments",	/* 11 - RPC_CANTDECODEARGS */
+	"RPC: Remote system error",		/* 12 - RPC_SYSTEMERROR */
+	"RPC: Unknown host",			/* 13 - RPC_UNKNOWNHOST */
+	"RPC: Port mapper failure",		/* 14 - RPC_PMAPFAILURE */
+	"RPC: Program not registered",		/* 15 - RPC_PROGNOTREGISTERED */
+	"RPC: Failed (unspecified error)",	/* 16 - RPC_FAILED */
+	"RPC: Unknown protocol"			/* 17 - RPC_UNKNOWNPROTO */
+};
+
+
+/*
+ * This interface for use by clntrpc
+ */
+char *
+clnt_sperrno(stat)
+	enum clnt_stat stat;
+{
+	unsigned int errnum = stat;
+
+	if (errnum < (sizeof(rpc_errlist)/sizeof(rpc_errlist[0])))
+		/* LINTED interface problem */
+		return (char *)rpc_errlist[errnum];
+
+	return ("RPC: (unknown error code)");
+}
+
+void
+clnt_perrno(num)
+	enum clnt_stat num;
+{
+	(void) fprintf(stderr, "%s\n", clnt_sperrno(num));
+}
+
+
+char *
+clnt_spcreateerror(s)
+	const char *s;
+{
+	char *str;
+	size_t len, i;
+
+	assert(s != NULL);
+
+	str = _buf(); /* side effect: sets CLNT_PERROR_BUFLEN */
+	if (str == 0)
+		return(0);
+	len = CLNT_PERROR_BUFLEN;
+	i = snprintf(str, len, "%s: ", s);
+	if (i > 0)
+		len -= i;
+	(void)strncat(str, clnt_sperrno(rpc_createerr.cf_stat), len - 1);
+	switch (rpc_createerr.cf_stat) {
+	case RPC_PMAPFAILURE:
+		(void) strncat(str, " - ", len - 1);
+		(void) strncat(str,
+		    clnt_sperrno(rpc_createerr.cf_error.re_status), len - 4);
+		break;
+
+	case RPC_SYSTEMERROR:
+		(void)strncat(str, " - ", len - 1);
+		(void)strncat(str, strerror(rpc_createerr.cf_error.re_errno),
+		    len - 4);
+		break;
+
+	case RPC_CANTSEND:
+	case RPC_CANTDECODERES:
+	case RPC_CANTENCODEARGS:
+	case RPC_SUCCESS:
+	case RPC_UNKNOWNPROTO:
+	case RPC_PROGNOTREGISTERED:
+	case RPC_FAILED:
+	case RPC_UNKNOWNHOST:
+	case RPC_CANTDECODEARGS:
+	case RPC_PROCUNAVAIL:
+	case RPC_PROGVERSMISMATCH:
+	case RPC_PROGUNAVAIL:
+	case RPC_AUTHERROR:
+	case RPC_VERSMISMATCH:
+	case RPC_TIMEDOUT:
+	case RPC_CANTRECV:
+	default:
+		break;
+	}
+	str[CLNT_PERROR_BUFLEN-1] = '\0';
+	return (str);
+}
+
+void
+clnt_pcreateerror(s)
+	const char *s;
+{
+
+	assert(s != NULL);
+
+	(void) fprintf(stderr, "%s\n", clnt_spcreateerror(s));
+}
+
+static const char *const auth_errlist[] = {
+	"Authentication OK",			/* 0 - AUTH_OK */
+	"Invalid client credential",		/* 1 - AUTH_BADCRED */
+	"Server rejected credential",		/* 2 - AUTH_REJECTEDCRED */
+	"Invalid client verifier", 		/* 3 - AUTH_BADVERF */
+	"Server rejected verifier", 		/* 4 - AUTH_REJECTEDVERF */
+	"Client credential too weak",		/* 5 - AUTH_TOOWEAK */
+	"Invalid server verifier",		/* 6 - AUTH_INVALIDRESP */
+	"Failed (unspecified error)",		/* 7 - AUTH_FAILED */
+	"Kerberos generic error",		/* 8 - AUTH_KERB_GENERIC*/
+	"Kerberos credential expired",		/* 9 - AUTH_TIMEEXPIRE */
+	"Bad kerberos ticket file",		/* 10 - AUTH_TKT_FILE */
+	"Can't decode kerberos authenticator",	/* 11 - AUTH_DECODE */
+	"Address wrong in kerberos ticket",	/* 12 - AUTH_NET_ADDR */
+	"GSS-API crediential problem",		/* 13 - RPCSEC_GSS_CREDPROBLEM */
+	"GSS-API context problem"		/* 14 - RPCSEC_GSS_CTXPROBLEM */
+};
+
+static char *
+auth_errmsg(stat)
+	enum auth_stat stat;
+{
+	unsigned int errnum = stat;
+
+	if (errnum < (sizeof(auth_errlist)/sizeof(auth_errlist[0])))
+		/* LINTED interface problem */
+		return (char *)auth_errlist[errnum];
+
+	return(NULL);
+}
Index: freebsd/lib/libc/rpc/clnt_raw.c
===================================================================
--- freebsd/lib/libc/rpc/clnt_raw.c	(revision 60b1d40751c8b3235b7ccbf3bb6ad0c562562f01)
+++ freebsd/lib/libc/rpc/clnt_raw.c	(revision 60b1d40751c8b3235b7ccbf3bb6ad0c562562f01)
@@ -0,0 +1,316 @@
+#include <machine/rtems-bsd-user-space.h>
+
+/*	$NetBSD: clnt_raw.c,v 1.20 2000/12/10 04:12:03 christos Exp $	*/
+
+/*-
+ * Copyright (c) 2009, Sun Microsystems, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions are met:
+ * - Redistributions of source code must retain the above copyright notice, 
+ *   this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice, 
+ *   this list of conditions and the following disclaimer in the documentation 
+ *   and/or other materials provided with the distribution.
+ * - Neither the name of Sun Microsystems, Inc. nor the names of its 
+ *   contributors may be used to endorse or promote products derived 
+ *   from this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char *sccsid2 = "@(#)clnt_raw.c 1.22 87/08/11 Copyr 1984 Sun Micro";
+static char *sccsid = "@(#)clnt_raw.c	2.2 88/08/01 4.0 RPCSRC";
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * clnt_raw.c
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ *
+ * Memory based rpc for simple testing and timing.
+ * Interface to create an rpc client and server in the same process.
+ * This lets us similate rpc and get round trip overhead, without
+ * any interference from the kernel.
+ */
+
+#include "namespace.h"
+#include "reentrant.h"
+#include <assert.h>
+#include <err.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <rpc/rpc.h>
+#include <rpc/raw.h>
+#include "un-namespace.h"
+#include "mt_misc.h"
+
+#define MCALL_MSG_SIZE 24
+
+/*
+ * This is the "network" we will be moving stuff over.
+ */
+static struct clntraw_private {
+	CLIENT	client_object;
+	XDR	xdr_stream;
+	char	*_raw_buf;
+	union {
+	    struct rpc_msg	mashl_rpcmsg;
+	    char 		mashl_callmsg[MCALL_MSG_SIZE];
+	} u;
+	u_int	mcnt;
+} *clntraw_private;
+
+static enum clnt_stat clnt_raw_call(CLIENT *, rpcproc_t, xdrproc_t, void *,
+	xdrproc_t, void *, struct timeval);
+static void clnt_raw_geterr(CLIENT *, struct rpc_err *);
+static bool_t clnt_raw_freeres(CLIENT *, xdrproc_t, void *);
+static void clnt_raw_abort(CLIENT *);
+static bool_t clnt_raw_control(CLIENT *, u_int, void *);
+static void clnt_raw_destroy(CLIENT *);
+static struct clnt_ops *clnt_raw_ops(void);
+
+/*
+ * Create a client handle for memory based rpc.
+ */
+CLIENT *
+clnt_raw_create(prog, vers)
+	rpcprog_t prog;
+	rpcvers_t vers;
+{
+	struct clntraw_private *clp;
+	struct rpc_msg call_msg;
+	XDR *xdrs;
+	CLIENT	*client;
+
+	mutex_lock(&clntraw_lock);
+	if ((clp = clntraw_private) == NULL) {
+		clp = (struct clntraw_private *)calloc(1, sizeof (*clp));
+		if (clp == NULL) {
+			mutex_unlock(&clntraw_lock);
+			return NULL;
+		}
+		if (__rpc_rawcombuf == NULL)
+			__rpc_rawcombuf =
+			    (char *)calloc(UDPMSGSIZE, sizeof (char));
+		clp->_raw_buf = __rpc_rawcombuf;
+		clntraw_private = clp;
+	}
+	xdrs = &clp->xdr_stream;
+	client = &clp->client_object;
+
+	/*
+	 * pre-serialize the static part of the call msg and stash it away
+	 */
+	call_msg.rm_direction = CALL;
+	call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
+	/* XXX: prog and vers have been long historically :-( */
+	call_msg.rm_call.cb_prog = (u_int32_t)prog;
+	call_msg.rm_call.cb_vers = (u_int32_t)vers;
+	xdrmem_create(xdrs, clp->u.mashl_callmsg, MCALL_MSG_SIZE, XDR_ENCODE); 
+	if (! xdr_callhdr(xdrs, &call_msg))
+		warnx("clntraw_create - Fatal header serialization error.");
+	clp->mcnt = XDR_GETPOS(xdrs);
+	XDR_DESTROY(xdrs);
+
+	/*
+	 * Set xdrmem for client/server shared buffer
+	 */
+	xdrmem_create(xdrs, clp->_raw_buf, UDPMSGSIZE, XDR_FREE);
+
+	/*
+	 * create client handle
+	 */
+	client->cl_ops = clnt_raw_ops();
+	client->cl_auth = authnone_create();
+	mutex_unlock(&clntraw_lock);
+	return (client);
+}
+
+/* ARGSUSED */
+static enum clnt_stat 
+clnt_raw_call(h, proc, xargs, argsp, xresults, resultsp, timeout)
+	CLIENT *h;
+	rpcproc_t proc;
+	xdrproc_t xargs;
+	void *argsp;
+	xdrproc_t xresults;
+	void *resultsp;
+	struct timeval timeout;
+{
+	struct clntraw_private *clp = clntraw_private;
+	XDR *xdrs = &clp->xdr_stream;
+	struct rpc_msg msg;
+	enum clnt_stat status;
+	struct rpc_err error;
+
+	assert(h != NULL);
+
+	mutex_lock(&clntraw_lock);
+	if (clp == NULL) {
+		mutex_unlock(&clntraw_lock);
+		return (RPC_FAILED);
+	}
+	mutex_unlock(&clntraw_lock);
+
+call_again:
+	/*
+	 * send request
+	 */
+	xdrs->x_op = XDR_ENCODE;
+	XDR_SETPOS(xdrs, 0);
+	clp->u.mashl_rpcmsg.rm_xid ++ ;
+	if ((! XDR_PUTBYTES(xdrs, clp->u.mashl_callmsg, clp->mcnt)) ||
+	    (! XDR_PUTINT32(xdrs, &proc)) ||
+	    (! AUTH_MARSHALL(h->cl_auth, xdrs)) ||
+	    (! (*xargs)(xdrs, argsp))) {
+		return (RPC_CANTENCODEARGS);
+	}
+	(void)XDR_GETPOS(xdrs);  /* called just to cause overhead */
+
+	/*
+	 * We have to call server input routine here because this is
+	 * all going on in one process. Yuk.
+	 */
+	svc_getreq_common(FD_SETSIZE);
+
+	/*
+	 * get results
+	 */
+	xdrs->x_op = XDR_DECODE;
+	XDR_SETPOS(xdrs, 0);
+	msg.acpted_rply.ar_verf = _null_auth;
+	msg.acpted_rply.ar_results.where = resultsp;
+	msg.acpted_rply.ar_results.proc = xresults;
+	if (! xdr_replymsg(xdrs, &msg)) {
+		/*
+		 * It's possible for xdr_replymsg() to fail partway
+		 * through its attempt to decode the result from the
+		 * server. If this happens, it will leave the reply
+		 * structure partially populated with dynamically
+		 * allocated memory. (This can happen if someone uses
+		 * clntudp_bufcreate() to create a CLIENT handle and
+		 * specifies a receive buffer size that is too small.)
+		 * This memory must be free()ed to avoid a leak.
+		 */
+		int op = xdrs->x_op;
+		xdrs->x_op = XDR_FREE;
+		xdr_replymsg(xdrs, &msg);
+		xdrs->x_op = op;
+		return (RPC_CANTDECODERES);
+	}
+	_seterr_reply(&msg, &error);
+	status = error.re_status;
+
+	if (status == RPC_SUCCESS) {
+		if (! AUTH_VALIDATE(h->cl_auth, &msg.acpted_rply.ar_verf)) {
+			status = RPC_AUTHERROR;
+		}
+	}  /* end successful completion */
+	else {
+		if (AUTH_REFRESH(h->cl_auth, &msg))
+			goto call_again;
+	}  /* end of unsuccessful completion */
+
+	if (status == RPC_SUCCESS) {
+		if (! AUTH_VALIDATE(h->cl_auth, &msg.acpted_rply.ar_verf)) {
+			status = RPC_AUTHERROR;
+		}
+		if (msg.acpted_rply.ar_verf.oa_base != NULL) {
+			xdrs->x_op = XDR_FREE;
+			(void)xdr_opaque_auth(xdrs, &(msg.acpted_rply.ar_verf));
+		}
+	}
+
+	return (status);
+}
+
+/*ARGSUSED*/
+static void
+clnt_raw_geterr(cl, err)
+	CLIENT *cl;
+	struct rpc_err *err;
+{
+}
+
+
+/* ARGSUSED */
+static bool_t
+clnt_raw_freeres(cl, xdr_res, res_ptr)
+	CLIENT *cl;
+	xdrproc_t xdr_res;
+	void *res_ptr;
+{
+	struct clntraw_private *clp = clntraw_private;
+	XDR *xdrs = &clp->xdr_stream;
+	bool_t rval;
+
+	mutex_lock(&clntraw_lock);
+	if (clp == NULL) {
+		rval = (bool_t) RPC_FAILED;
+		mutex_unlock(&clntraw_lock);
+		return (rval);
+	}
+	mutex_unlock(&clntraw_lock);
+	xdrs->x_op = XDR_FREE;
+	return ((*xdr_res)(xdrs, res_ptr));
+}
+
+/*ARGSUSED*/
+static void
+clnt_raw_abort(cl)
+	CLIENT *cl;
+{
+}
+
+/*ARGSUSED*/
+static bool_t
+clnt_raw_control(cl, ui, str)
+	CLIENT *cl;
+	u_int ui;
+	void *str;
+{
+	return (FALSE);
+}
+
+/*ARGSUSED*/
+static void
+clnt_raw_destroy(cl)
+	CLIENT *cl;
+{
+}
+
+static struct clnt_ops *
+clnt_raw_ops()
+{
+	static struct clnt_ops ops;
+
+	/* VARIABLES PROTECTED BY ops_lock: ops */
+
+	mutex_lock(&ops_lock);
+	if (ops.cl_call == NULL) {
+		ops.cl_call = clnt_raw_call;
+		ops.cl_abort = clnt_raw_abort;
+		ops.cl_geterr = clnt_raw_geterr;
+		ops.cl_freeres = clnt_raw_freeres;
+		ops.cl_destroy = clnt_raw_destroy;
+		ops.cl_control = clnt_raw_control;
+	}
+	mutex_unlock(&ops_lock);
+	return (&ops);
+}
Index: freebsd/lib/libc/rpc/clnt_simple.c
===================================================================
--- freebsd/lib/libc/rpc/clnt_simple.c	(revision 60b1d40751c8b3235b7ccbf3bb6ad0c562562f01)
+++ freebsd/lib/libc/rpc/clnt_simple.c	(revision 60b1d40751c8b3235b7ccbf3bb6ad0c562562f01)
@@ -0,0 +1,207 @@
+#include <machine/rtems-bsd-user-space.h>
+
+/*	$NetBSD: clnt_simple.c,v 1.21 2000/07/06 03:10:34 christos Exp $	*/
+
+/*-
+ * Copyright (c) 2009, Sun Microsystems, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions are met:
+ * - Redistributions of source code must retain the above copyright notice, 
+ *   this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice, 
+ *   this list of conditions and the following disclaimer in the documentation 
+ *   and/or other materials provided with the distribution.
+ * - Neither the name of Sun Microsystems, Inc. nor the names of its 
+ *   contributors may be used to endorse or promote products derived 
+ *   from this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * Copyright (c) 1986-1991 by Sun Microsystems Inc. 
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char *sccsid2 = "from: @(#)clnt_simple.c 1.35 87/08/11 Copyr 1984 Sun Micro";
+static char *sccsid = "from: @(#)clnt_simple.c	2.2 88/08/01 4.0 RPCSRC";
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * clnt_simple.c
+ * Simplified front end to client rpc.
+ *
+ */
+
+#include "namespace.h"
+#include "reentrant.h"
+#include <rtems/bsd/sys/param.h>
+#include <stdio.h>
+#include <errno.h>
+#include <rpc/rpc.h>
+#include <string.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include "un-namespace.h"
+#include "mt_misc.h"
+
+#ifndef MAXHOSTNAMELEN
+#define	MAXHOSTNAMELEN 64
+#endif
+
+#ifndef NETIDLEN
+#define	NETIDLEN 32
+#endif
+
+struct rpc_call_private {
+	int	valid;			/* Is this entry valid ? */
+	CLIENT	*client;		/* Client handle */
+	pid_t	pid;			/* process-id at moment of creation */
+	rpcprog_t prognum;		/* Program */
+	rpcvers_t versnum;		/* Version */
+	char	host[MAXHOSTNAMELEN];	/* Servers host */
+	char	nettype[NETIDLEN];	/* Network type */
+};
+static struct rpc_call_private *rpc_call_private_main;
+static thread_key_t rpc_call_key;
+static once_t rpc_call_once = ONCE_INITIALIZER;
+static int rpc_call_key_error;
+
+static void rpc_call_key_init(void);
+static void rpc_call_destroy(void *);
+
+static void
+rpc_call_destroy(void *vp)
+{
+	struct rpc_call_private *rcp = (struct rpc_call_private *)vp;
+
+	if (rcp) {
+		if (rcp->client)
+			CLNT_DESTROY(rcp->client);
+		free(rcp);
+	}
+}
+
+static void
+rpc_call_key_init(void)
+{
+
+	rpc_call_key_error = thr_keycreate(&rpc_call_key, rpc_call_destroy);
+}
+
+/*
+ * This is the simplified interface to the client rpc layer.
+ * The client handle is not destroyed here and is reused for
+ * the future calls to same prog, vers, host and nettype combination.
+ *
+ * The total time available is 25 seconds.
+ */
+enum clnt_stat
+rpc_call(host, prognum, versnum, procnum, inproc, in, outproc, out, nettype)
+	const char *host;			/* host name */
+	rpcprog_t prognum;			/* program number */
+	rpcvers_t versnum;			/* version number */
+	rpcproc_t procnum;			/* procedure number */
+	xdrproc_t inproc, outproc;	/* in/out XDR procedures */
+	const char *in;
+	char  *out;			/* recv/send data */
+	const char *nettype;			/* nettype */
+{
+	struct rpc_call_private *rcp = (struct rpc_call_private *) 0;
+	enum clnt_stat clnt_stat;
+	struct timeval timeout, tottimeout;
+	int main_thread = 1;
+
+	if ((main_thread = thr_main())) {
+		rcp = rpc_call_private_main;
+	} else {
+		if (thr_once(&rpc_call_once, rpc_call_key_init) != 0 ||
+		    rpc_call_key_error != 0) {
+			rpc_createerr.cf_stat = RPC_SYSTEMERROR;
+			rpc_createerr.cf_error.re_errno = rpc_call_key_error;
+			return (rpc_createerr.cf_stat);
+		}
+		rcp = (struct rpc_call_private *)thr_getspecific(rpc_call_key);
+	}
+	if (rcp == NULL) {
+		rcp = malloc(sizeof (*rcp));
+		if (rcp == NULL) {
+			rpc_createerr.cf_stat = RPC_SYSTEMERROR;
+			rpc_createerr.cf_error.re_errno = errno;
+			return (rpc_createerr.cf_stat);
+		}
+		if (main_thread)
+			rpc_call_private_main = rcp;
+		else
+			thr_setspecific(rpc_call_key, (void *) rcp);
+		rcp->valid = 0;
+		rcp->client = NULL;
+	}
+	if ((nettype == NULL) || (nettype[0] == 0))
+		nettype = "netpath";
+	if (!(rcp->valid && rcp->pid == getpid() &&
+		(rcp->prognum == prognum) &&
+		(rcp->versnum == versnum) &&
+		(!strcmp(rcp->host, host)) &&
+		(!strcmp(rcp->nettype, nettype)))) {
+		int fd;
+
+		rcp->valid = 0;
+		if (rcp->client)
+			CLNT_DESTROY(rcp->client);
+		/*
+		 * Using the first successful transport for that type
+		 */
+		rcp->client = clnt_create(host, prognum, versnum, nettype);
+		rcp->pid = getpid();
+		if (rcp->client == NULL) {
+			return (rpc_createerr.cf_stat);
+		}
+		/*
+		 * Set time outs for connectionless case.  Do it
+		 * unconditionally.  Faster than doing a t_getinfo()
+		 * and then doing the right thing.
+		 */
+		timeout.tv_usec = 0;
+		timeout.tv_sec = 5;
+		(void) CLNT_CONTROL(rcp->client,
+				CLSET_RETRY_TIMEOUT, (char *)(void *)&timeout);
+		if (CLNT_CONTROL(rcp->client, CLGET_FD, (char *)(void *)&fd))
+			_fcntl(fd, F_SETFD, 1);	/* make it "close on exec" */
+		rcp->prognum = prognum;
+		rcp->versnum = versnum;
+		if ((strlen(host) < (size_t)MAXHOSTNAMELEN) &&
+		    (strlen(nettype) < (size_t)NETIDLEN)) {
+			(void) strcpy(rcp->host, host);
+			(void) strcpy(rcp->nettype, nettype);
+			rcp->valid = 1;
+		} else {
+			rcp->valid = 0;
+		}
+	} /* else reuse old client */
+	tottimeout.tv_sec = 25;
+	tottimeout.tv_usec = 0;
+	/*LINTED const castaway*/
+	clnt_stat = CLNT_CALL(rcp->client, procnum, inproc, (char *) in,
+	    outproc, out, tottimeout);
+	/*
+	 * if call failed, empty cache
+	 */
+	if (clnt_stat != RPC_SUCCESS)
+		rcp->valid = 0;
+	return (clnt_stat);
+}
Index: freebsd/lib/libc/rpc/clnt_vc.c
===================================================================
--- freebsd/lib/libc/rpc/clnt_vc.c	(revision 60b1d40751c8b3235b7ccbf3bb6ad0c562562f01)
+++ freebsd/lib/libc/rpc/clnt_vc.c	(revision 60b1d40751c8b3235b7ccbf3bb6ad0c562562f01)
@@ -0,0 +1,874 @@
+#include <machine/rtems-bsd-user-space.h>
+
+/*	$NetBSD: clnt_vc.c,v 1.4 2000/07/14 08:40:42 fvdl Exp $	*/
+
+/*-
+ * Copyright (c) 2009, Sun Microsystems, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions are met:
+ * - Redistributions of source code must retain the above copyright notice, 
+ *   this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice, 
+ *   this list of conditions and the following disclaimer in the documentation 
+ *   and/or other materials provided with the distribution.
+ * - Neither the name of Sun Microsystems, Inc. nor the names of its 
+ *   contributors may be used to endorse or promote products derived 
+ *   from this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char *sccsid2 = "@(#)clnt_tcp.c 1.37 87/10/05 Copyr 1984 Sun Micro";
+static char *sccsid = "@(#)clnt_tcp.c	2.2 88/08/01 4.0 RPCSRC";
+static char sccsid3[] = "@(#)clnt_vc.c 1.19 89/03/16 Copyr 1988 Sun Micro";
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+ 
+/*
+ * clnt_tcp.c, Implements a TCP/IP based, client side RPC.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ *
+ * TCP based RPC supports 'batched calls'.
+ * A sequence of calls may be batched-up in a send buffer.  The rpc call
+ * return immediately to the client even though the call was not necessarily
+ * sent.  The batching occurs if the results' xdr routine is NULL (0) AND
+ * the rpc timeout value is zero (see clnt.h, rpc).
+ *
+ * Clients should NOT casually batch calls that in fact return results; that is,
+ * the server side should be aware that a call is batched and not produce any
+ * return message.  Batched calls that produce many result messages can
+ * deadlock (netlock) the client and the server....
+ *
+ * Now go hang yourself.
+ */
+
+#include "namespace.h"
+#include "reentrant.h"
+#include <sys/types.h>
+#include <sys/poll.h>
+#include <sys/syslog.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/uio.h>
+
+#include <arpa/inet.h>
+#include <assert.h>
+#include <err.h>
+#include <errno.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <signal.h>
+
+#include <rpc/rpc.h>
+#include <rpc/rpcsec_gss.h>
+#include "un-namespace.h"
+#include "rpc_com.h"
+#include "mt_misc.h"
+
+#define MCALL_MSG_SIZE 24
+
+struct cmessage {
+        struct cmsghdr cmsg;
+        struct cmsgcred cmcred;
+};
+
+static enum clnt_stat clnt_vc_call(CLIENT *, rpcproc_t, xdrproc_t, void *,
+    xdrproc_t, void *, struct timeval);
+static void clnt_vc_geterr(CLIENT *, struct rpc_err *);
+static bool_t clnt_vc_freeres(CLIENT *, xdrproc_t, void *);
+static void clnt_vc_abort(CLIENT *);
+static bool_t clnt_vc_control(CLIENT *, u_int, void *);
+static void clnt_vc_destroy(CLIENT *);
+static struct clnt_ops *clnt_vc_ops(void);
+static bool_t time_not_ok(struct timeval *);
+static int read_vc(void *, void *, int);
+static int write_vc(void *, void *, int);
+static int __msgwrite(int, void *, size_t);
+static int __msgread(int, void *, size_t);
+
+struct ct_data {
+	int		ct_fd;		/* connection's fd */
+	bool_t		ct_closeit;	/* close it on destroy */
+	struct timeval	ct_wait;	/* wait interval in milliseconds */
+	bool_t          ct_waitset;	/* wait set by clnt_control? */
+	struct netbuf	ct_addr;	/* remote addr */
+	struct rpc_err	ct_error;
+	union {
+		char	ct_mcallc[MCALL_MSG_SIZE];	/* marshalled callmsg */
+		u_int32_t ct_mcalli;
+	} ct_u;
+	u_int		ct_mpos;	/* pos after marshal */
+	XDR		ct_xdrs;	/* XDR stream */
+};
+
+/*
+ *      This machinery implements per-fd locks for MT-safety.  It is not
+ *      sufficient to do per-CLIENT handle locks for MT-safety because a
+ *      user may create more than one CLIENT handle with the same fd behind
+ *      it.  Therfore, we allocate an array of flags (vc_fd_locks), protected
+ *      by the clnt_fd_lock mutex, and an array (vc_cv) of condition variables
+ *      similarly protected.  Vc_fd_lock[fd] == 1 => a call is activte on some
+ *      CLIENT handle created for that fd.
+ *      The current implementation holds locks across the entire RPC and reply.
+ *      Yes, this is silly, and as soon as this code is proven to work, this
+ *      should be the first thing fixed.  One step at a time.
+ */
+static int      *vc_fd_locks;
+static cond_t   *vc_cv;
+#define release_fd_lock(fd, mask) {	\
+	mutex_lock(&clnt_fd_lock);	\
+	vc_fd_locks[fd] = 0;		\
+	mutex_unlock(&clnt_fd_lock);	\
+	thr_sigsetmask(SIG_SETMASK, &(mask), (sigset_t *) NULL);	\
+	cond_signal(&vc_cv[fd]);	\
+}
+
+static const char clnt_vc_errstr[] = "%s : %s";
+static const char clnt_vc_str[] = "clnt_vc_create";
+static const char clnt_read_vc_str[] = "read_vc";
+static const char __no_mem_str[] = "out of memory";
+
+/*
+ * Create a client handle for a connection.
+ * Default options are set, which the user can change using clnt_control()'s.
+ * The rpc/vc package does buffering similar to stdio, so the client
+ * must pick send and receive buffer sizes, 0 => use the default.
+ * NB: fd is copied into a private area.
+ * NB: The rpch->cl_auth is set null authentication. Caller may wish to
+ * set this something more useful.
+ *
+ * fd should be an open socket
+ */
+CLIENT *
+clnt_vc_create(fd, raddr, prog, vers, sendsz, recvsz)
+	int fd;				/* open file descriptor */
+	const struct netbuf *raddr;	/* servers address */
+	const rpcprog_t prog;			/* program number */
+	const rpcvers_t vers;			/* version number */
+	u_int sendsz;			/* buffer recv size */
+	u_int recvsz;			/* buffer send size */
+{
+	CLIENT *cl;			/* client handle */
+	struct ct_data *ct = NULL;	/* client handle */
+	struct timeval now;
+	struct rpc_msg call_msg;
+	static u_int32_t disrupt;
+	sigset_t mask;
+	sigset_t newmask;
+	struct sockaddr_storage ss;
+	socklen_t slen;
+	struct __rpc_sockinfo si;
+
+	if (disrupt == 0)
+		disrupt = (u_int32_t)(long)raddr;
+
+	cl = (CLIENT *)mem_alloc(sizeof (*cl));
+	ct = (struct ct_data *)mem_alloc(sizeof (*ct));
+	if ((cl == (CLIENT *)NULL) || (ct == (struct ct_data *)NULL)) {
+		(void) syslog(LOG_ERR, clnt_vc_errstr,
+		    clnt_vc_str, __no_mem_str);
+		rpc_createerr.cf_stat = RPC_SYSTEMERROR;
+		rpc_createerr.cf_error.re_errno = errno;
+		goto err;
+	}
+	ct->ct_addr.buf = NULL;
+	sigfillset(&newmask);
+	thr_sigsetmask(SIG_SETMASK, &newmask, &mask);
+	mutex_lock(&clnt_fd_lock);
+	if (vc_fd_locks == (int *) NULL) {
+		int cv_allocsz, fd_allocsz;
+		int dtbsize = __rpc_dtbsize();
+
+		fd_allocsz = dtbsize * sizeof (int);
+		vc_fd_locks = (int *) mem_alloc(fd_allocsz);
+		if (vc_fd_locks == (int *) NULL) {
+			mutex_unlock(&clnt_fd_lock);
+			thr_sigsetmask(SIG_SETMASK, &(mask), NULL);
+			goto err;
+		} else
+			memset(vc_fd_locks, '\0', fd_allocsz);
+
+		assert(vc_cv == (cond_t *) NULL);
+		cv_allocsz = dtbsize * sizeof (cond_t);
+		vc_cv = (cond_t *) mem_alloc(cv_allocsz);
+		if (vc_cv == (cond_t *) NULL) {
+			mem_free(vc_fd_locks, fd_allocsz);
+			vc_fd_locks = (int *) NULL;
+			mutex_unlock(&clnt_fd_lock);
+			thr_sigsetmask(SIG_SETMASK, &(mask), NULL);
+			goto err;
+		} else {
+			int i;
+
+			for (i = 0; i < dtbsize; i++)
+				cond_init(&vc_cv[i], 0, (void *) 0);
+		}
+	} else
+		assert(vc_cv != (cond_t *) NULL);
+
+	/*
+	 * XXX - fvdl connecting while holding a mutex?
+	 */
+	slen = sizeof ss;
+	if (_getpeername(fd, (struct sockaddr *)(void *)&ss, &slen) < 0) {
+		if (errno != ENOTCONN) {
+			rpc_createerr.cf_stat = RPC_SYSTEMERROR;
+			rpc_createerr.cf_error.re_errno = errno;
+			mutex_unlock(&clnt_fd_lock);
+			thr_sigsetmask(SIG_SETMASK, &(mask), NULL);
+			goto err;
+		}
+		if (_connect(fd, (struct sockaddr *)raddr->buf, raddr->len) < 0){
+			rpc_createerr.cf_stat = RPC_SYSTEMERROR;
+			rpc_createerr.cf_error.re_errno = errno;
+			mutex_unlock(&clnt_fd_lock);
+			thr_sigsetmask(SIG_SETMASK, &(mask), NULL);
+			goto err;
+		}
+	}
+	mutex_unlock(&clnt_fd_lock);
+	thr_sigsetmask(SIG_SETMASK, &(mask), NULL);
+	if (!__rpc_fd2sockinfo(fd, &si))
+		goto err;
+
+	ct->ct_closeit = FALSE;
+
+	/*
+	 * Set up private data struct
+	 */
+	ct->ct_fd = fd;
+	ct->ct_wait.tv_usec = 0;
+	ct->ct_waitset = FALSE;
+	ct->ct_addr.buf = malloc(raddr->maxlen);
+	if (ct->ct_addr.buf == NULL)
+		goto err;
+	memcpy(ct->ct_addr.buf, raddr->buf, raddr->len);
+	ct->ct_addr.len = raddr->maxlen;
+	ct->ct_addr.maxlen = raddr->maxlen;
+
+	/*
+	 * Initialize call message
+	 */
+	(void)gettimeofday(&now, NULL);
+	call_msg.rm_xid = ((u_int32_t)++disrupt) ^ __RPC_GETXID(&now);
+	call_msg.rm_direction = CALL;
+	call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
+	call_msg.rm_call.cb_prog = (u_int32_t)prog;
+	call_msg.rm_call.cb_vers = (u_int32_t)vers;
+
+	/*
+	 * pre-serialize the static part of the call msg and stash it away
+	 */
+	xdrmem_create(&(ct->ct_xdrs), ct->ct_u.ct_mcallc, MCALL_MSG_SIZE,
+	    XDR_ENCODE);
+	if (! xdr_callhdr(&(ct->ct_xdrs), &call_msg)) {
+		if (ct->ct_closeit) {
+			(void)_close(fd);
+		}
+		goto err;
+	}
+	ct->ct_mpos = XDR_GETPOS(&(ct->ct_xdrs));
+	XDR_DESTROY(&(ct->ct_xdrs));
+	assert(ct->ct_mpos + sizeof(uint32_t) <= MCALL_MSG_SIZE);
+
+	/*
+	 * Create a client handle which uses xdrrec for serialization
+	 * and authnone for authentication.
+	 */
+	cl->cl_ops = clnt_vc_ops();
+	cl->cl_private = ct;
+	cl->cl_auth = authnone_create();
+	sendsz = __rpc_get_t_size(si.si_af, si.si_proto, (int)sendsz);
+	recvsz = __rpc_get_t_size(si.si_af, si.si_proto, (int)recvsz);
+	xdrrec_create(&(ct->ct_xdrs), sendsz, recvsz,
+	    cl->cl_private, read_vc, write_vc);
+	return (cl);
+
+err:
+	if (ct) {
+		if (ct->ct_addr.len)
+			mem_free(ct->ct_addr.buf, ct->ct_addr.len);
+		mem_free(ct, sizeof (struct ct_data));
+	}
+	if (cl)
+		mem_free(cl, sizeof (CLIENT));
+	return ((CLIENT *)NULL);
+}
+
+static enum clnt_stat
+clnt_vc_call(cl, proc, xdr_args, args_ptr, xdr_results, results_ptr, timeout)
+	CLIENT *cl;
+	rpcproc_t proc;
+	xdrproc_t xdr_args;
+	void *args_ptr;
+	xdrproc_t xdr_results;
+	void *results_ptr;
+	struct timeval timeout;
+{
+	struct ct_data *ct = (struct ct_data *) cl->cl_private;
+	XDR *xdrs = &(ct->ct_xdrs);
+	struct rpc_msg reply_msg;
+	u_int32_t x_id;
+	u_int32_t *msg_x_id = &ct->ct_u.ct_mcalli;    /* yuk */
+	bool_t shipnow;
+	int refreshes = 2;
+	sigset_t mask, newmask;
+	int rpc_lock_value;
+	bool_t reply_stat;
+
+	assert(cl != NULL);
+
+	sigfillset(&newmask);
+	thr_sigsetmask(SIG_SETMASK, &newmask, &mask);
+	mutex_lock(&clnt_fd_lock);
+	while (vc_fd_locks[ct->ct_fd])
+		cond_wait(&vc_cv[ct->ct_fd], &clnt_fd_lock);
+	if (__isthreaded)
+                rpc_lock_value = 1;
+        else
+                rpc_lock_value = 0;
+	vc_fd_locks[ct->ct_fd] = rpc_lock_value;
+	mutex_unlock(&clnt_fd_lock);
+	if (!ct->ct_waitset) {
+		/* If time is not within limits, we ignore it. */
+		if (time_not_ok(&timeout) == FALSE)
+			ct->ct_wait = timeout;
+	}
+
+	shipnow =
+	    (xdr_results == NULL && timeout.tv_sec == 0
+	    && timeout.tv_usec == 0) ? FALSE : TRUE;
+
+call_again:
+	xdrs->x_op = XDR_ENCODE;
+	ct->ct_error.re_status = RPC_SUCCESS;
+	x_id = ntohl(--(*msg_x_id));
+
+	if (cl->cl_auth->ah_cred.oa_flavor != RPCSEC_GSS) {
+		if ((! XDR_PUTBYTES(xdrs, ct->ct_u.ct_mcallc, ct->ct_mpos)) ||
+		    (! XDR_PUTINT32(xdrs, &proc)) ||
+		    (! AUTH_MARSHALL(cl->cl_auth, xdrs)) ||
+		    (! (*xdr_args)(xdrs, args_ptr))) {
+			if (ct->ct_error.re_status == RPC_SUCCESS)
+				ct->ct_error.re_status = RPC_CANTENCODEARGS;
+			(void)xdrrec_endofrecord(xdrs, TRUE);
+			release_fd_lock(ct->ct_fd, mask);
+			return (ct->ct_error.re_status);
+		}
+	} else {
+		*(uint32_t *) &ct->ct_u.ct_mcallc[ct->ct_mpos] = htonl(proc);
+		if (! __rpc_gss_wrap(cl->cl_auth, ct->ct_u.ct_mcallc,
+			ct->ct_mpos + sizeof(uint32_t),
+			xdrs, xdr_args, args_ptr)) {
+			if (ct->ct_error.re_status == RPC_SUCCESS)
+				ct->ct_error.re_status = RPC_CANTENCODEARGS;
+			(void)xdrrec_endofrecord(xdrs, TRUE);
+			release_fd_lock(ct->ct_fd, mask);
+			return (ct->ct_error.re_status);
+		}
+	}
+	if (! xdrrec_endofrecord(xdrs, shipnow)) {
+		release_fd_lock(ct->ct_fd, mask);
+		return (ct->ct_error.re_status = RPC_CANTSEND);
+	}
+	if (! shipnow) {
+		release_fd_lock(ct->ct_fd, mask);
+		return (RPC_SUCCESS);
+	}
+	/*
+	 * Hack to provide rpc-based message passing
+	 */
+	if (timeout.tv_sec == 0 && timeout.tv_usec == 0) {
+		release_fd_lock(ct->ct_fd, mask);
+		return(ct->ct_error.re_status = RPC_TIMEDOUT);
+	}
+
+
+	/*
+	 * Keep receiving until we get a valid transaction id
+	 */
+	xdrs->x_op = XDR_DECODE;
+	while (TRUE) {
+		reply_msg.acpted_rply.ar_verf = _null_auth;
+		reply_msg.acpted_rply.ar_results.where = NULL;
+		reply_msg.acpted_rply.ar_results.proc = (xdrproc_t)xdr_void;
+		if (! xdrrec_skiprecord(xdrs)) {
+			release_fd_lock(ct->ct_fd, mask);
+			return (ct->ct_error.re_status);
+		}
+		/* now decode and validate the response header */
+		if (! xdr_replymsg(xdrs, &reply_msg)) {
+			if (ct->ct_error.re_status == RPC_SUCCESS)
+				continue;
+			release_fd_lock(ct->ct_fd, mask);
+			return (ct->ct_error.re_status);
+		}
+		if (reply_msg.rm_xid == x_id)
+			break;
+	}
+
+	/*
+	 * process header
+	 */
+	_seterr_reply(&reply_msg, &(ct->ct_error));
+	if (ct->ct_error.re_status == RPC_SUCCESS) {
+		if (! AUTH_VALIDATE(cl->cl_auth,
+		    &reply_msg.acpted_rply.ar_verf)) {
+			ct->ct_error.re_status = RPC_AUTHERROR;
+			ct->ct_error.re_why = AUTH_INVALIDRESP;
+		} else {
+			if (cl->cl_auth->ah_cred.oa_flavor != RPCSEC_GSS) {
+				reply_stat = (*xdr_results)(xdrs, results_ptr);
+			} else {
+				reply_stat = __rpc_gss_unwrap(cl->cl_auth,
+				    xdrs, xdr_results, results_ptr);
+			}
+			if (! reply_stat) {
+				if (ct->ct_error.re_status == RPC_SUCCESS)
+					ct->ct_error.re_status =
+						RPC_CANTDECODERES;
+			}
+		}
+		/* free verifier ... */
+		if (reply_msg.acpted_rply.ar_verf.oa_base != NULL) {
+			xdrs->x_op = XDR_FREE;
+			(void)xdr_opaque_auth(xdrs,
+			    &(reply_msg.acpted_rply.ar_verf));
+		}
+	}  /* end successful completion */
+	else {
+		/* maybe our credentials need to be refreshed ... */
+		if (refreshes-- && AUTH_REFRESH(cl->cl_auth, &reply_msg))
+			goto call_again;
+	}  /* end of unsuccessful completion */
+	release_fd_lock(ct->ct_fd, mask);
+	return (ct->ct_error.re_status);
+}
+
+static void
+clnt_vc_geterr(cl, errp)
+	CLIENT *cl;
+	struct rpc_err *errp;
+{
+	struct ct_data *ct;
+
+	assert(cl != NULL);
+	assert(errp != NULL);
+
+	ct = (struct ct_data *) cl->cl_private;
+	*errp = ct->ct_error;
+}
+
+static bool_t
+clnt_vc_freeres(cl, xdr_res, res_ptr)
+	CLIENT *cl;
+	xdrproc_t xdr_res;
+	void *res_ptr;
+{
+	struct ct_data *ct;
+	XDR *xdrs;
+	bool_t dummy;
+	sigset_t mask;
+	sigset_t newmask;
+
+	assert(cl != NULL);
+
+	ct = (struct ct_data *)cl->cl_private;
+	xdrs = &(ct->ct_xdrs);
+
+	sigfillset(&newmask);
+	thr_sigsetmask(SIG_SETMASK, &newmask, &mask);
+	mutex_lock(&clnt_fd_lock);
+	while (vc_fd_locks[ct->ct_fd])
+		cond_wait(&vc_cv[ct->ct_fd], &clnt_fd_lock);
+	xdrs->x_op = XDR_FREE;
+	dummy = (*xdr_res)(xdrs, res_ptr);
+	mutex_unlock(&clnt_fd_lock);
+	thr_sigsetmask(SIG_SETMASK, &(mask), NULL);
+	cond_signal(&vc_cv[ct->ct_fd]);
+
+	return dummy;
+}
+
+/*ARGSUSED*/
+static void
+clnt_vc_abort(cl)
+	CLIENT *cl;
+{
+}
+
+static bool_t
+clnt_vc_control(cl, request, info)
+	CLIENT *cl;
+	u_int request;
+	void *info;
+{
+	struct ct_data *ct;
+	void *infop = info;
+	sigset_t mask;
+	sigset_t newmask;
+	int rpc_lock_value;
+
+	assert(cl != NULL);
+
+	ct = (struct ct_data *)cl->cl_private;
+
+	sigfillset(&newmask);
+	thr_sigsetmask(SIG_SETMASK, &newmask, &mask);
+	mutex_lock(&clnt_fd_lock);
+	while (vc_fd_locks[ct->ct_fd])
+		cond_wait(&vc_cv[ct->ct_fd], &clnt_fd_lock);
+	if (__isthreaded)
+                rpc_lock_value = 1;
+        else
+                rpc_lock_value = 0;
+	vc_fd_locks[ct->ct_fd] = rpc_lock_value;
+	mutex_unlock(&clnt_fd_lock);
+
+	switch (request) {
+	case CLSET_FD_CLOSE:
+		ct->ct_closeit = TRUE;
+		release_fd_lock(ct->ct_fd, mask);
+		return (TRUE);
+	case CLSET_FD_NCLOSE:
+		ct->ct_closeit = FALSE;
+		release_fd_lock(ct->ct_fd, mask);
+		return (TRUE);
+	default:
+		break;
+	}
+
+	/* for other requests which use info */
+	if (info == NULL) {
+		release_fd_lock(ct->ct_fd, mask);
+		return (FALSE);
+	}
+	switch (request) {
+	case CLSET_TIMEOUT:
+		if (time_not_ok((struct timeval *)info)) {
+			release_fd_lock(ct->ct_fd, mask);
+			return (FALSE);
+		}
+		ct->ct_wait = *(struct timeval *)infop;
+		ct->ct_waitset = TRUE;
+		break;
+	case CLGET_TIMEOUT:
+		*(struct timeval *)infop = ct->ct_wait;
+		break;
+	case CLGET_SERVER_ADDR:
+		(void) memcpy(info, ct->ct_addr.buf, (size_t)ct->ct_addr.len);
+		break;
+	case CLGET_FD:
+		*(int *)info = ct->ct_fd;
+		break;
+	case CLGET_SVC_ADDR:
+		/* The caller should not free this memory area */
+		*(struct netbuf *)info = ct->ct_addr;
+		break;
+	case CLSET_SVC_ADDR:		/* set to new address */
+		release_fd_lock(ct->ct_fd, mask);
+		return (FALSE);
+	case CLGET_XID:
+		/*
+		 * use the knowledge that xid is the
+		 * first element in the call structure
+		 * This will get the xid of the PREVIOUS call
+		 */
+		*(u_int32_t *)info =
+		    ntohl(*(u_int32_t *)(void *)&ct->ct_u.ct_mcalli);
+		break;
+	case CLSET_XID:
+		/* This will set the xid of the NEXT call */
+		*(u_int32_t *)(void *)&ct->ct_u.ct_mcalli =
+		    htonl(*((u_int32_t *)info) + 1);
+		/* increment by 1 as clnt_vc_call() decrements once */
+		break;
+	case CLGET_VERS:
+		/*
+		 * This RELIES on the information that, in the call body,
+		 * the version number field is the fifth field from the
+		 * begining of the RPC header. MUST be changed if the
+		 * call_struct is changed
+		 */
+		*(u_int32_t *)info =
+		    ntohl(*(u_int32_t *)(void *)(ct->ct_u.ct_mcallc +
+		    4 * BYTES_PER_XDR_UNIT));
+		break;
+
+	case CLSET_VERS:
+		*(u_int32_t *)(void *)(ct->ct_u.ct_mcallc +
+		    4 * BYTES_PER_XDR_UNIT) =
+		    htonl(*(u_int32_t *)info);
+		break;
+
+	case CLGET_PROG:
+		/*
+		 * This RELIES on the information that, in the call body,
+		 * the program number field is the fourth field from the
+		 * begining of the RPC header. MUST be changed if the
+		 * call_struct is changed
+		 */
+		*(u_int32_t *)info =
+		    ntohl(*(u_int32_t *)(void *)(ct->ct_u.ct_mcallc +
+		    3 * BYTES_PER_XDR_UNIT));
+		break;
+
+	case CLSET_PROG:
+		*(u_int32_t *)(void *)(ct->ct_u.ct_mcallc +
+		    3 * BYTES_PER_XDR_UNIT) =
+		    htonl(*(u_int32_t *)info);
+		break;
+
+	default:
+		release_fd_lock(ct->ct_fd, mask);
+		return (FALSE);
+	}
+	release_fd_lock(ct->ct_fd, mask);
+	return (TRUE);
+}
+
+
+static void
+clnt_vc_destroy(cl)
+	CLIENT *cl;
+{
+	struct ct_data *ct = (struct ct_data *) cl->cl_private;
+	int ct_fd = ct->ct_fd;
+	sigset_t mask;
+	sigset_t newmask;
+
+	assert(cl != NULL);
+
+	ct = (struct ct_data *) cl->cl_private;
+
+	sigfillset(&newmask);
+	thr_sigsetmask(SIG_SETMASK, &newmask, &mask);
+	mutex_lock(&clnt_fd_lock);
+	while (vc_fd_locks[ct_fd])
+		cond_wait(&vc_cv[ct_fd], &clnt_fd_lock);
+	if (ct->ct_closeit && ct->ct_fd != -1) {
+		(void)_close(ct->ct_fd);
+	}
+	XDR_DESTROY(&(ct->ct_xdrs));
+	if (ct->ct_addr.buf)
+		free(ct->ct_addr.buf);
+	mem_free(ct, sizeof(struct ct_data));
+	if (cl->cl_netid && cl->cl_netid[0])
+		mem_free(cl->cl_netid, strlen(cl->cl_netid) +1);
+	if (cl->cl_tp && cl->cl_tp[0])
+		mem_free(cl->cl_tp, strlen(cl->cl_tp) +1);
+	mem_free(cl, sizeof(CLIENT));
+	mutex_unlock(&clnt_fd_lock);
+	thr_sigsetmask(SIG_SETMASK, &(mask), NULL);
+	cond_signal(&vc_cv[ct_fd]);
+}
+
+/*
+ * Interface between xdr serializer and tcp connection.
+ * Behaves like the system calls, read & write, but keeps some error state
+ * around for the rpc level.
+ */
+static int
+read_vc(ctp, buf, len)
+	void *ctp;
+	void *buf;
+	int len;
+{
+	struct sockaddr sa;
+	socklen_t sal;
+	struct ct_data *ct = (struct ct_data *)ctp;
+	struct pollfd fd;
+	int milliseconds = (int)((ct->ct_wait.tv_sec * 1000) +
+	    (ct->ct_wait.tv_usec / 1000));
+
+	if (len == 0)
+		return (0);
+	fd.fd = ct->ct_fd;
+	fd.events = POLLIN;
+	for (;;) {
+		switch (_poll(&fd, 1, milliseconds)) {
+		case 0:
+			ct->ct_error.re_status = RPC_TIMEDOUT;
+			return (-1);
+
+		case -1:
+			if (errno == EINTR)
+				continue;
+			ct->ct_error.re_status = RPC_CANTRECV;
+			ct->ct_error.re_errno = errno;
+			return (-1);
+		}
+		break;
+	}
+
+	sal = sizeof(sa);
+	if ((_getpeername(ct->ct_fd, &sa, &sal) == 0) &&
+	    (sa.sa_family == AF_LOCAL)) {
+		len = __msgread(ct->ct_fd, buf, (size_t)len);
+	} else {
+		len = _read(ct->ct_fd, buf, (size_t)len);
+	}
+
+	switch (len) {
+	case 0:
+		/* premature eof */
+		ct->ct_error.re_errno = ECONNRESET;
+		ct->ct_error.re_status = RPC_CANTRECV;
+		len = -1;  /* it's really an error */
+		break;
+
+	case -1:
+		ct->ct_error.re_errno = errno;
+		ct->ct_error.re_status = RPC_CANTRECV;
+		break;
+	}
+	return (len);
+}
+
+static int
+write_vc(ctp, buf, len)
+	void *ctp;
+	void *buf;
+	int len;
+{
+	struct sockaddr sa;
+	socklen_t sal;
+	struct ct_data *ct = (struct ct_data *)ctp;
+	int i, cnt;
+
+	sal = sizeof(sa);
+	if ((_getpeername(ct->ct_fd, &sa, &sal) == 0) &&
+	    (sa.sa_family == AF_LOCAL)) {
+		for (cnt = len; cnt > 0; cnt -= i, buf = (char *)buf + i) {
+			if ((i = __msgwrite(ct->ct_fd, buf,
+			     (size_t)cnt)) == -1) {
+				ct->ct_error.re_errno = errno;
+				ct->ct_error.re_status = RPC_CANTSEND;
+				return (-1);
+			}
+		}
+	} else {
+		for (cnt = len; cnt > 0; cnt -= i, buf = (char *)buf + i) {
+			if ((i = _write(ct->ct_fd, buf, (size_t)cnt)) == -1) {
+				ct->ct_error.re_errno = errno;
+				ct->ct_error.re_status = RPC_CANTSEND;
+				return (-1);
+			}
+		}
+	}
+	return (len);
+}
+
+static struct clnt_ops *
+clnt_vc_ops()
+{
+	static struct clnt_ops ops;
+	sigset_t mask, newmask;
+
+	/* VARIABLES PROTECTED BY ops_lock: ops */
+
+	sigfillset(&newmask);
+	thr_sigsetmask(SIG_SETMASK, &newmask, &mask);
+	mutex_lock(&ops_lock);
+	if (ops.cl_call == NULL) {
+		ops.cl_call = clnt_vc_call;
+		ops.cl_abort = clnt_vc_abort;
+		ops.cl_geterr = clnt_vc_geterr;
+		ops.cl_freeres = clnt_vc_freeres;
+		ops.cl_destroy = clnt_vc_destroy;
+		ops.cl_control = clnt_vc_control;
+	}
+	mutex_unlock(&ops_lock);
+	thr_sigsetmask(SIG_SETMASK, &(mask), NULL);
+	return (&ops);
+}
+
+/*
+ * Make sure that the time is not garbage.   -1 value is disallowed.
+ * Note this is different from time_not_ok in clnt_dg.c
+ */
+static bool_t
+time_not_ok(t)
+	struct timeval *t;
+{
+	return (t->tv_sec <= -1 || t->tv_sec > 100000000 ||
+		t->tv_usec <= -1 || t->tv_usec > 1000000);
+}
+
+static int
+__msgread(sock, buf, cnt)
+	int sock;
+	void *buf;
+	size_t cnt;
+{
+	struct iovec iov[1];
+	struct msghdr msg;
+	union {
+		struct cmsghdr cmsg;
+		char control[CMSG_SPACE(sizeof(struct cmsgcred))];
+	} cm;
+ 
+	bzero((char *)&cm, sizeof(cm));
+	iov[0].iov_base = buf;
+	iov[0].iov_len = cnt;
+ 
+	msg.msg_iov = iov;
+	msg.msg_iovlen = 1;
+	msg.msg_name = NULL;
+	msg.msg_namelen = 0;
+	msg.msg_control = (caddr_t)&cm;
+	msg.msg_controllen = CMSG_SPACE(sizeof(struct cmsgcred));
+	msg.msg_flags = 0;
+ 
+	return(_recvmsg(sock, &msg, 0));
+}
+
+static int
+__msgwrite(sock, buf, cnt)
+	int sock;
+	void *buf;
+	size_t cnt;
+{
+	struct iovec iov[1];
+	struct msghdr msg;
+	union {
+		struct cmsghdr cmsg;
+		char control[CMSG_SPACE(sizeof(struct cmsgcred))];
+	} cm;
+ 
+	bzero((char *)&cm, sizeof(cm));
+	iov[0].iov_base = buf;
+	iov[0].iov_len = cnt;
+ 
+	cm.cmsg.cmsg_type = SCM_CREDS;
+	cm.cmsg.cmsg_level = SOL_SOCKET;
+	cm.cmsg.cmsg_len = CMSG_LEN(sizeof(struct cmsgcred));
+ 
+	msg.msg_iov = iov;
+	msg.msg_iovlen = 1;
+	msg.msg_name = NULL;
+	msg.msg_namelen = 0;
+	msg.msg_control = (caddr_t)&cm;
+	msg.msg_controllen = CMSG_SPACE(sizeof(struct cmsgcred));
+	msg.msg_flags = 0;
+
+	return(_sendmsg(sock, &msg, 0));
+}
Index: freebsd/lib/libc/rpc/crypt_client.c
===================================================================
--- freebsd/lib/libc/rpc/crypt_client.c	(revision 60b1d40751c8b3235b7ccbf3bb6ad0c562562f01)
+++ freebsd/lib/libc/rpc/crypt_client.c	(revision 60b1d40751c8b3235b7ccbf3bb6ad0c562562f01)
@@ -0,0 +1,103 @@
+#include <machine/rtems-bsd-user-space.h>
+
+/*
+ * Copyright (c) 1996
+ *	Bill Paul <wpaul@ctr.columbia.edu>.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by Bill Paul.
+ * 4. Neither the name of the author nor the names of any co-contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL Bill Paul OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <err.h>
+#include <sys/types.h>
+#include <rpc/des_crypt.h>
+#include <rpc/des.h>
+#include <string.h>
+#include <rpcsvc/crypt.h>
+#include "un-namespace.h"
+
+int
+_des_crypt_call(buf, len, dparms)
+	char *buf;
+	int len;
+	struct desparams *dparms;
+{
+	CLIENT *clnt;
+	desresp  *result_1;
+	desargs  des_crypt_1_arg;
+	struct netconfig *nconf;
+	void *localhandle;
+	int stat;
+
+	nconf = NULL;
+	localhandle = setnetconfig();
+	while ((nconf = getnetconfig(localhandle)) != NULL) {
+		if (nconf->nc_protofmly != NULL &&
+		     strcmp(nconf->nc_protofmly, NC_LOOPBACK) == 0)
+			break;
+	}
+	if (nconf == NULL) {
+		warnx("getnetconfig: %s", nc_sperror());
+		return(DESERR_HWERROR);
+	}
+	clnt = clnt_tp_create(NULL, CRYPT_PROG, CRYPT_VERS, nconf);
+	if (clnt == (CLIENT *) NULL) {
+		endnetconfig(localhandle);
+		return(DESERR_HWERROR);
+	}
+	endnetconfig(localhandle);
+
+	des_crypt_1_arg.desbuf.desbuf_len = len;
+	des_crypt_1_arg.desbuf.desbuf_val = buf;
+	des_crypt_1_arg.des_dir = (dparms->des_dir == ENCRYPT) ? ENCRYPT_DES : DECRYPT_DES;
+	des_crypt_1_arg.des_mode = (dparms->des_mode == CBC) ? CBC_DES : ECB_DES;
+	bcopy(dparms->des_ivec, des_crypt_1_arg.des_ivec, 8);
+	bcopy(dparms->des_key, des_crypt_1_arg.des_key, 8);
+
+	result_1 = des_crypt_1(&des_crypt_1_arg, clnt);
+	if (result_1 == (desresp *) NULL) {
+		clnt_destroy(clnt);
+		return(DESERR_HWERROR);
+	}
+
+	stat = result_1->stat;
+
+	if (result_1->stat == DESERR_NONE ||
+	    result_1->stat == DESERR_NOHWDEVICE) {
+		bcopy(result_1->desbuf.desbuf_val, buf, len);
+		bcopy(result_1->des_ivec, dparms->des_ivec, 8);
+	}
+
+	clnt_freeres(clnt, (xdrproc_t)xdr_desresp, result_1);
+	clnt_destroy(clnt);
+
+	return(stat);
+}
Index: freebsd/lib/libc/rpc/des_crypt.c
===================================================================
--- freebsd/lib/libc/rpc/des_crypt.c	(revision 60b1d40751c8b3235b7ccbf3bb6ad0c562562f01)
+++ freebsd/lib/libc/rpc/des_crypt.c	(revision 60b1d40751c8b3235b7ccbf3bb6ad0c562562f01)
@@ -0,0 +1,155 @@
+#include <machine/rtems-bsd-user-space.h>
+
+/*-
+ * Copyright (c) 2009, Sun Microsystems, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions are met:
+ * - Redistributions of source code must retain the above copyright notice, 
+ *   this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice, 
+ *   this list of conditions and the following disclaimer in the documentation 
+ *   and/or other materials provided with the distribution.
+ * - Neither the name of Sun Microsystems, Inc. nor the names of its 
+ *   contributors may be used to endorse or promote products derived 
+ *   from this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * des_crypt.c, DES encryption library routines
+ * Copyright (C) 1986, Sun Microsystems, Inc.
+ */
+
+#include <sys/types.h>
+#include <rpc/des_crypt.h>
+#include <rpc/des.h>
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)des_crypt.c	2.2 88/08/10 4.0 RPCSRC; from 1.13 88/02/08 SMI";
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+static int common_crypt( char *, char *, unsigned, unsigned, struct desparams * );
+int (*__des_crypt_LOCAL)() = 0;
+extern int _des_crypt_call(char *, int, struct desparams *);
+/*
+ * Copy 8 bytes
+ */
+#define COPY8(src, dst) { \
+	char *a = (char *) dst; \
+	char *b = (char *) src; \
+	*a++ = *b++; *a++ = *b++; *a++ = *b++; *a++ = *b++; \
+	*a++ = *b++; *a++ = *b++; *a++ = *b++; *a++ = *b++; \
+}
+ 
+/*
+ * Copy multiple of 8 bytes
+ */
+#define DESCOPY(src, dst, len) { \
+	char *a = (char *) dst; \
+	char *b = (char *) src; \
+	int i; \
+	for (i = (int) len; i > 0; i -= 8) { \
+		*a++ = *b++; *a++ = *b++; *a++ = *b++; *a++ = *b++; \
+		*a++ = *b++; *a++ = *b++; *a++ = *b++; *a++ = *b++; \
+	} \
+}
+
+/*
+ * CBC mode encryption
+ */
+int
+cbc_crypt(key, buf, len, mode, ivec)
+	char *key;
+	char *buf;
+	unsigned len;
+	unsigned mode;
+	char *ivec;	
+{
+	int err;
+	struct desparams dp;
+
+#ifdef BROKEN_DES
+	dp.UDES.UDES_buf = buf;
+	dp.des_mode = ECB;
+#else
+	dp.des_mode = CBC;
+#endif
+	COPY8(ivec, dp.des_ivec);
+	err = common_crypt(key, buf, len, mode, &dp);
+	COPY8(dp.des_ivec, ivec);
+	return(err);
+}
+
+
+/*
+ * ECB mode encryption
+ */
+int
+ecb_crypt(key, buf, len, mode)
+	char *key;
+	char *buf;
+	unsigned len;
+	unsigned mode;
+{
+	struct desparams dp;
+
+#ifdef BROKEN_DES
+	dp.UDES.UDES_buf = buf;
+	dp.des_mode = CBC;
+#else
+	dp.des_mode = ECB;
+#endif
+	return(common_crypt(key, buf, len, mode, &dp));
+}
+
+
+
+/*
+ * Common code to cbc_crypt() & ecb_crypt()
+ */
+static int
+common_crypt(key, buf, len, mode, desp)	
+	char *key;	
+	char *buf;
+	unsigned len;
+	unsigned mode;
+	struct desparams *desp;
+{
+	int desdev;
+
+	if ((len % 8) != 0 || len > DES_MAXDATA) {
+		return(DESERR_BADPARAM);
+	}
+	desp->des_dir =
+		((mode & DES_DIRMASK) == DES_ENCRYPT) ? ENCRYPT : DECRYPT;
+
+	desdev = mode & DES_DEVMASK;
+	COPY8(key, desp->des_key);
+	/* 
+	 * software
+	 */
+	if (__des_crypt_LOCAL != NULL) {
+		if (!__des_crypt_LOCAL(buf, len, desp)) {
+			return (DESERR_HWERROR);
+		}
+	} else {
+		if (!_des_crypt_call(buf, len, desp)) {
+			return (DESERR_HWERROR);
+		}
+	}
+	return(desdev == DES_SW ? DESERR_NONE : DESERR_NOHWDEVICE);
+}
Index: freebsd/lib/libc/rpc/des_soft.c
===================================================================
--- freebsd/lib/libc/rpc/des_soft.c	(revision 60b1d40751c8b3235b7ccbf3bb6ad0c562562f01)
+++ freebsd/lib/libc/rpc/des_soft.c	(revision 60b1d40751c8b3235b7ccbf3bb6ad0c562562f01)
@@ -0,0 +1,72 @@
+#include <machine/rtems-bsd-user-space.h>
+
+/*-
+ * Copyright (c) 2009, Sun Microsystems, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions are met:
+ * - Redistributions of source code must retain the above copyright notice, 
+ *   this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice, 
+ *   this list of conditions and the following disclaimer in the documentation 
+ *   and/or other materials provided with the distribution.
+ * - Neither the name of Sun Microsystems, Inc. nor the names of its 
+ *   contributors may be used to endorse or promote products derived 
+ *   from this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)des_soft.c	2.2 88/08/10 4.0 RPCSRC; from 1.13 88/02/08 SMI";
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * Table giving odd parity in the low bit for ASCII characters
+ */
+static char partab[128] = {
+	0x01, 0x01, 0x02, 0x02, 0x04, 0x04, 0x07, 0x07,
+	0x08, 0x08, 0x0b, 0x0b, 0x0d, 0x0d, 0x0e, 0x0e,
+	0x10, 0x10, 0x13, 0x13, 0x15, 0x15, 0x16, 0x16,
+	0x19, 0x19, 0x1a, 0x1a, 0x1c, 0x1c, 0x1f, 0x1f,
+	0x20, 0x20, 0x23, 0x23, 0x25, 0x25, 0x26, 0x26,
+	0x29, 0x29, 0x2a, 0x2a, 0x2c, 0x2c, 0x2f, 0x2f,
+	0x31, 0x31, 0x32, 0x32, 0x34, 0x34, 0x37, 0x37,
+	0x38, 0x38, 0x3b, 0x3b, 0x3d, 0x3d, 0x3e, 0x3e,
+	0x40, 0x40, 0x43, 0x43, 0x45, 0x45, 0x46, 0x46,
+	0x49, 0x49, 0x4a, 0x4a, 0x4c, 0x4c, 0x4f, 0x4f,
+	0x51, 0x51, 0x52, 0x52, 0x54, 0x54, 0x57, 0x57,
+	0x58, 0x58, 0x5b, 0x5b, 0x5d, 0x5d, 0x5e, 0x5e,
+	0x61, 0x61, 0x62, 0x62, 0x64, 0x64, 0x67, 0x67,
+	0x68, 0x68, 0x6b, 0x6b, 0x6d, 0x6d, 0x6e, 0x6e,
+	0x70, 0x70, 0x73, 0x73, 0x75, 0x75, 0x76, 0x76,
+	0x79, 0x79, 0x7a, 0x7a, 0x7c, 0x7c, 0x7f, 0x7f,
+};
+
+/*
+ * Add odd parity to low bit of 8 byte key
+ */
+void
+des_setparity(p)
+	char *p;
+{
+	int i;
+
+	for (i = 0; i < 8; i++) {
+		*p = partab[*p & 0x7f];
+		p++;
+	}
+}
Index: freebsd/lib/libc/rpc/getnetconfig.c
===================================================================
--- freebsd/lib/libc/rpc/getnetconfig.c	(revision 60b1d40751c8b3235b7ccbf3bb6ad0c562562f01)
+++ freebsd/lib/libc/rpc/getnetconfig.c	(revision 60b1d40751c8b3235b7ccbf3bb6ad0c562562f01)
@@ -0,0 +1,742 @@
+#include <machine/rtems-bsd-user-space.h>
+
+/*	$NetBSD: getnetconfig.c,v 1.3 2000/07/06 03:10:34 christos Exp $	*/
+
+/*-
+ * Copyright (c) 2009, Sun Microsystems, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions are met:
+ * - Redistributions of source code must retain the above copyright notice, 
+ *   this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice, 
+ *   this list of conditions and the following disclaimer in the documentation 
+ *   and/or other materials provided with the distribution.
+ * - Neither the name of Sun Microsystems, Inc. nor the names of its 
+ *   contributors may be used to endorse or promote products derived 
+ *   from this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)getnetconfig.c	1.12 91/12/19 SMI";
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * Copyright (c) 1989 by Sun Microsystems, Inc.
+ */
+
+#include "namespace.h"
+#include "reentrant.h"
+#include <stdio.h>
+#include <errno.h>
+#include <netconfig.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <rpc/rpc.h>
+#include <unistd.h>
+#include "un-namespace.h"
+#include "rpc_com.h"
+
+/*
+ * The five library routines in this file provide application access to the
+ * system network configuration database, /etc/netconfig.  In addition to the
+ * netconfig database and the routines for accessing it, the environment
+ * variable NETPATH and its corresponding routines in getnetpath.c may also be
+ * used to specify the network transport to be used.
+ */
+
+
+/*
+ * netconfig errors
+ */
+
+#define NC_NONETCONFIG	ENOENT
+#define NC_NOMEM	ENOMEM
+#define NC_NOTINIT	EINVAL	    /* setnetconfig was not called first */
+#define NC_BADFILE	EBADF	    /* format for netconfig file is bad */
+#define NC_NOTFOUND	ENOPROTOOPT /* specified netid was not found */
+
+/*
+ * semantics as strings (should be in netconfig.h)
+ */
+#define NC_TPI_CLTS_S	    "tpi_clts"
+#define	NC_TPI_COTS_S	    "tpi_cots"
+#define	NC_TPI_COTS_ORD_S   "tpi_cots_ord"
+#define	NC_TPI_RAW_S        "tpi_raw"
+
+/*
+ * flags as characters (also should be in netconfig.h)
+ */
+#define	NC_NOFLAG_C	'-'
+#define	NC_VISIBLE_C	'v'
+#define	NC_BROADCAST_C	'b'
+
+/*
+ * Character used to indicate there is no name-to-address lookup library
+ */
+#define NC_NOLOOKUP	"-"
+
+static const char * const _nc_errors[] = {
+    "Netconfig database not found",
+    "Not enough memory",
+    "Not initialized",
+    "Netconfig database has invalid format",
+    "Netid not found in netconfig database"
+};
+
+struct netconfig_info {
+    int		eof;	/* all entries has been read */
+    int		ref;	/* # of times setnetconfig() has been called */
+    struct netconfig_list	*head;	/* head of the list */
+    struct netconfig_list	*tail;	/* last of the list */
+};
+
+struct netconfig_list {
+    char			*linep;	/* hold line read from netconfig */
+    struct netconfig		*ncp;
+    struct netconfig_list	*next;
+};
+
+struct netconfig_vars {
+    int   valid;	/* token that indicates a valid netconfig_vars */
+    int   flag;		/* first time flag */
+    struct netconfig_list *nc_configs;  /* pointer to the current netconfig entry */
+};
+
+#define NC_VALID	0xfeed
+#define NC_STORAGE	0xf00d
+#define NC_INVALID	0
+
+
+static int *__nc_error(void);
+static int parse_ncp(char *, struct netconfig *);
+static struct netconfig *dup_ncp(struct netconfig *);
+
+
+static FILE *nc_file;		/* for netconfig db */
+static mutex_t nc_file_lock = MUTEX_INITIALIZER;
+
+static struct netconfig_info	ni = { 0, 0, NULL, NULL};
+static mutex_t ni_lock = MUTEX_INITIALIZER;
+
+static thread_key_t nc_key;
+static once_t nc_once = ONCE_INITIALIZER;
+static int nc_key_error;
+
+static void
+nc_key_init(void)
+{
+
+	nc_key_error = thr_keycreate(&nc_key, free);
+}
+
+#define MAXNETCONFIGLINE    1000
+
+static int *
+__nc_error()
+{
+	static int nc_error = 0;
+	int *nc_addr;
+
+	/*
+	 * Use the static `nc_error' if we are the main thread
+	 * (including non-threaded programs), or if an allocation
+	 * fails.
+	 */
+	if (thr_main())
+		return (&nc_error);
+	if (thr_once(&nc_once, nc_key_init) != 0 || nc_key_error != 0)
+		return (&nc_error);
+	if ((nc_addr = (int *)thr_getspecific(nc_key)) == NULL) {
+		nc_addr = (int *)malloc(sizeof (int));
+		if (thr_setspecific(nc_key, (void *) nc_addr) != 0) {
+			if (nc_addr)
+				free(nc_addr);
+			return (&nc_error);
+		}
+		*nc_addr = 0;
+	}
+	return (nc_addr);
+}
+
+#define nc_error        (*(__nc_error()))
+/*
+ * A call to setnetconfig() establishes a /etc/netconfig "session".  A session
+ * "handle" is returned on a successful call.  At the start of a session (after
+ * a call to setnetconfig()) searches through the /etc/netconfig database will
+ * proceed from the start of the file.  The session handle must be passed to
+ * getnetconfig() to parse the file.  Each call to getnetconfig() using the
+ * current handle will process one subsequent entry in /etc/netconfig.
+ * setnetconfig() must be called before the first call to getnetconfig().
+ * (Handles are used to allow for nested calls to setnetpath()).
+ *
+ * A new session is established with each call to setnetconfig(), with a new
+ * handle being returned on each call.  Previously established sessions remain
+ * active until endnetconfig() is called with that session's handle as an
+ * argument.
+ *
+ * setnetconfig() need *not* be called before a call to getnetconfigent().
+ * setnetconfig() returns a NULL pointer on failure (for example, if
+ * the netconfig database is not present).
+ */
+void *
+setnetconfig()
+{
+    struct netconfig_vars *nc_vars;
+
+    if ((nc_vars = (struct netconfig_vars *)malloc(sizeof
+		(struct netconfig_vars))) == NULL) {
+	return(NULL);
+    }
+
+    /*
+     * For multiple calls, i.e. nc_file is not NULL, we just return the
+     * handle without reopening the netconfig db.
+     */
+    mutex_lock(&ni_lock);
+    ni.ref++;
+    mutex_unlock(&ni_lock);
+
+    mutex_lock(&nc_file_lock);
+    if ((nc_file != NULL) || (nc_file = fopen(NETCONFIG, "r")) != NULL) {
+	nc_vars->valid = NC_VALID;
+	nc_vars->flag = 0;
+	nc_vars->nc_configs = ni.head;
+	mutex_unlock(&nc_file_lock);
+	return ((void *)nc_vars);
+    }
+    mutex_unlock(&nc_file_lock);
+
+    mutex_lock(&ni_lock);
+    ni.ref--;
+    mutex_unlock(&ni_lock);
+
+    nc_error = NC_NONETCONFIG;
+    free(nc_vars);
+    return (NULL);
+}
+
+
+/*
+ * When first called, getnetconfig() returns a pointer to the first entry in
+ * the netconfig database, formatted as a struct netconfig.  On each subsequent
+ * call, getnetconfig() returns a pointer to the next entry in the database.
+ * getnetconfig() can thus be used to search the entire netconfig file.
+ * getnetconfig() returns NULL at end of file.
+ */
+
+struct netconfig *
+getnetconfig(handlep)
+void *handlep;
+{
+    struct netconfig_vars *ncp = (struct netconfig_vars *)handlep;
+    char *stringp;		/* tmp string pointer */
+    struct netconfig_list	*list;
+    struct netconfig *np;
+    struct netconfig *result;
+
+    /*
+     * Verify that handle is valid
+     */
+    mutex_lock(&nc_file_lock);
+    if (ncp == NULL || nc_file == NULL) {
+	nc_error = NC_NOTINIT;
+	mutex_unlock(&nc_file_lock);
+	return (NULL);
+    }
+    mutex_unlock(&nc_file_lock);
+
+    switch (ncp->valid) {
+    case NC_VALID:
+	/*
+	 * If entry has already been read into the list,
+	 * we return the entry in the linked list.
+	 * If this is the first time call, check if there are any entries in
+	 * linked list.  If no entries, we need to read the netconfig db.
+	 * If we have been here and the next entry is there, we just return
+	 * it.
+	 */
+	if (ncp->flag == 0) {	/* first time */
+	    ncp->flag = 1;
+	    mutex_lock(&ni_lock);
+	    ncp->nc_configs = ni.head;
+	    mutex_unlock(&ni_lock);
+	    if (ncp->nc_configs != NULL)	/* entry already exist */
+		return(ncp->nc_configs->ncp);
+	}
+	else if (ncp->nc_configs != NULL && ncp->nc_configs->next != NULL) {
+	    ncp->nc_configs = ncp->nc_configs->next;
+	    return(ncp->nc_configs->ncp);
+	}
+
+	/*
+	 * If we cannot find the entry in the list and is end of file,
+	 * we give up.
+	 */
+	mutex_lock(&ni_lock);
+	if (ni.eof == 1) {
+		mutex_unlock(&ni_lock);
+		return(NULL);
+	}
+	mutex_unlock(&ni_lock);
+
+	break;
+    default:
+	nc_error = NC_NOTINIT;
+	return (NULL);
+    }
+
+    stringp = (char *) malloc(MAXNETCONFIGLINE);
+    if (stringp == NULL)
+    	return (NULL);
+
+#ifdef MEM_CHK
+    if (malloc_verify() == 0) {
+	fprintf(stderr, "memory heap corrupted in getnetconfig\n");
+	exit(1);
+    }
+#endif
+
+    /*
+     * Read a line from netconfig file.
+     */
+    mutex_lock(&nc_file_lock);
+    do {
+	if (fgets(stringp, MAXNETCONFIGLINE, nc_file) == NULL) {
+	    free(stringp);
+	    mutex_lock(&ni_lock);
+	    ni.eof = 1;
+	    mutex_unlock(&ni_lock);
+	    mutex_unlock(&nc_file_lock);
+	    return (NULL);
+        }
+    } while (*stringp == '#');
+    mutex_unlock(&nc_file_lock);
+
+    list = (struct netconfig_list *) malloc(sizeof (struct netconfig_list));
+    if (list == NULL) {
+    	free(stringp);
+    	return(NULL);
+    }
+    np = (struct netconfig *) malloc(sizeof (struct netconfig));
+    if (np == NULL) {
+    	free(stringp);
+	free(list);
+    	return(NULL);
+    }
+    list->ncp = np;
+    list->next = NULL;
+    list->ncp->nc_lookups = NULL;
+    list->linep = stringp;
+    if (parse_ncp(stringp, list->ncp) == -1) {
+	free(stringp);
+	free(np);
+	free(list);
+	return (NULL);
+    }
+    else {
+	/*
+	 * If this is the first entry that's been read, it is the head of
+	 * the list.  If not, put the entry at the end of the list.
+	 * Reposition the current pointer of the handle to the last entry
+	 * in the list.
+	 */
+	mutex_lock(&ni_lock);
+	if (ni.head == NULL) {	/* first entry */
+	    ni.head = ni.tail = list;
+	}
+    	else {
+    	    ni.tail->next = list;
+    	    ni.tail = ni.tail->next;
+    	}
+	ncp->nc_configs = ni.tail;
+	result = ni.tail->ncp;
+	mutex_unlock(&ni_lock);
+	return(result);
+    }
+}
+
+/*
+ * endnetconfig() may be called to "unbind" or "close" the netconfig database
+ * when processing is complete, releasing resources for reuse.  endnetconfig()
+ * may not be called before setnetconfig().  endnetconfig() returns 0 on
+ * success and -1 on failure (for example, if setnetconfig() was not called
+ * previously).
+ */
+int
+endnetconfig(handlep)
+void *handlep;
+{
+    struct netconfig_vars *nc_handlep = (struct netconfig_vars *)handlep;
+
+    struct netconfig_list *q, *p;
+
+    /*
+     * Verify that handle is valid
+     */
+    if (nc_handlep == NULL || (nc_handlep->valid != NC_VALID &&
+	    nc_handlep->valid != NC_STORAGE)) {
+	nc_error = NC_NOTINIT;
+	return (-1);
+    }
+
+    /*
+     * Return 0 if anyone still needs it.
+     */
+    nc_handlep->valid = NC_INVALID;
+    nc_handlep->flag = 0;
+    nc_handlep->nc_configs = NULL;
+    mutex_lock(&ni_lock);
+    if (--ni.ref > 0) {
+	mutex_unlock(&ni_lock);
+    	free(nc_handlep);
+	return(0);
+    }
+
+    /*
+     * Noone needs these entries anymore, then frees them.
+     * Make sure all info in netconfig_info structure has been reinitialized.
+     */
+    q = ni.head;
+    ni.eof = ni.ref = 0;
+    ni.head = NULL;
+    ni.tail = NULL;
+    mutex_unlock(&ni_lock);
+
+    while (q != NULL) {
+	p = q->next;
+	if (q->ncp->nc_lookups != NULL) free(q->ncp->nc_lookups);
+	free(q->ncp);
+	free(q->linep);
+	free(q);
+	q = p;
+    }
+    free(nc_handlep);
+
+    mutex_lock(&nc_file_lock);
+    fclose(nc_file);
+    nc_file = NULL;
+    mutex_unlock(&nc_file_lock);
+
+    return (0);
+}
+
+/*
+ * getnetconfigent(netid) returns a pointer to the struct netconfig structure
+ * corresponding to netid.  It returns NULL if netid is invalid (that is, does
+ * not name an entry in the netconfig database).  It returns NULL and sets
+ * errno in case of failure (for example, if the netconfig database cannot be
+ * opened).
+ */
+
+struct netconfig *
+getnetconfigent(netid)
+	const char *netid;
+{
+    FILE *file;		/* NETCONFIG db's file pointer */
+    char *linep;	/* holds current netconfig line */
+    char *stringp;	/* temporary string pointer */
+    struct netconfig *ncp = NULL;   /* returned value */
+    struct netconfig_list *list;	/* pointer to cache list */
+
+    nc_error = NC_NOTFOUND;	/* default error. */
+    if (netid == NULL || strlen(netid) == 0) {
+	return (NULL);
+    }
+
+    /*
+     * Look up table if the entries have already been read and parsed in
+     * getnetconfig(), then copy this entry into a buffer and return it.
+     * If we cannot find the entry in the current list and there are more
+     * entries in the netconfig db that has not been read, we then read the
+     * db and try find the match netid.
+     * If all the netconfig db has been read and placed into the list and
+     * there is no match for the netid, return NULL.
+     */
+    mutex_lock(&ni_lock);
+    if (ni.head != NULL) {
+	for (list = ni.head; list; list = list->next) {
+	    if (strcmp(list->ncp->nc_netid, netid) == 0) {
+		mutex_unlock(&ni_lock);
+	        return(dup_ncp(list->ncp));
+	    }
+	}
+	if (ni.eof == 1) {	/* that's all the entries */
+		mutex_unlock(&ni_lock);
+		return(NULL);
+	}
+    }
+    mutex_unlock(&ni_lock);
+
+
+    if ((file = fopen(NETCONFIG, "r")) == NULL) {
+	nc_error = NC_NONETCONFIG;
+	return (NULL);
+    }
+
+    if ((linep = malloc(MAXNETCONFIGLINE)) == NULL) {
+	fclose(file);
+	nc_error = NC_NOMEM;
+	return (NULL);
+    }
+    do {
+	ptrdiff_t len;
+	char *tmpp;	/* tmp string pointer */
+
+	do {
+	    if ((stringp = fgets(linep, MAXNETCONFIGLINE, file)) == NULL) {
+		break;
+	    }
+	} while (*stringp == '#');
+	if (stringp == NULL) {	    /* eof */
+	    break;
+	}
+	if ((tmpp = strpbrk(stringp, "\t ")) == NULL) {	/* can't parse file */
+	    nc_error = NC_BADFILE;
+	    break;
+	}
+	if (strlen(netid) == (size_t) (len = tmpp - stringp) &&	/* a match */
+		strncmp(stringp, netid, (size_t)len) == 0) {
+	    if ((ncp = (struct netconfig *)
+		    malloc(sizeof (struct netconfig))) == NULL) {
+		break;
+	    }
+	    ncp->nc_lookups = NULL;
+	    if (parse_ncp(linep, ncp) == -1) {
+		free(ncp);
+		ncp = NULL;
+	    }
+	    break;
+	}
+    } while (stringp != NULL);
+    if (ncp == NULL) {
+	free(linep);
+    }
+    fclose(file);
+    return(ncp);
+}
+
+/*
+ * freenetconfigent(netconfigp) frees the netconfig structure pointed to by
+ * netconfigp (previously returned by getnetconfigent()).
+ */
+
+void
+freenetconfigent(netconfigp)
+	struct netconfig *netconfigp;
+{
+    if (netconfigp != NULL) {
+	free(netconfigp->nc_netid);	/* holds all netconfigp's strings */
+	if (netconfigp->nc_lookups != NULL)
+	    free(netconfigp->nc_lookups);
+	free(netconfigp);
+    }
+    return;
+}
+
+/*
+ * Parse line and stuff it in a struct netconfig
+ * Typical line might look like:
+ *	udp tpi_cots vb inet udp /dev/udp /usr/lib/ip.so,/usr/local/ip.so
+ *
+ * We return -1 if any of the tokens don't parse, or malloc fails.
+ *
+ * Note that we modify stringp (putting NULLs after tokens) and
+ * we set the ncp's string field pointers to point to these tokens within
+ * stringp.
+ */
+
+static int
+parse_ncp(stringp, ncp)
+char *stringp;		/* string to parse */
+struct netconfig *ncp;	/* where to put results */
+{
+    char    *tokenp;	/* for processing tokens */
+    char    *lasts;
+    char    **nc_lookups;
+
+    nc_error = NC_BADFILE;	/* nearly anything that breaks is for this reason */
+    stringp[strlen(stringp)-1] = '\0';	/* get rid of newline */
+    /* netid */
+    if ((ncp->nc_netid = strtok_r(stringp, "\t ", &lasts)) == NULL) {
+	return (-1);
+    }
+
+    /* semantics */
+    if ((tokenp = strtok_r(NULL, "\t ", &lasts)) == NULL) {
+	return (-1);
+    }
+    if (strcmp(tokenp, NC_TPI_COTS_ORD_S) == 0)
+	ncp->nc_semantics = NC_TPI_COTS_ORD;
+    else if (strcmp(tokenp, NC_TPI_COTS_S) == 0)
+	ncp->nc_semantics = NC_TPI_COTS;
+    else if (strcmp(tokenp, NC_TPI_CLTS_S) == 0)
+	ncp->nc_semantics = NC_TPI_CLTS;
+    else if (strcmp(tokenp, NC_TPI_RAW_S) == 0)
+	ncp->nc_semantics = NC_TPI_RAW;
+    else
+	return (-1);
+
+    /* flags */
+    if ((tokenp = strtok_r(NULL, "\t ", &lasts)) == NULL) {
+	return (-1);
+    }
+    for (ncp->nc_flag = NC_NOFLAG; *tokenp != '\0';
+	    tokenp++) {
+	switch (*tokenp) {
+	case NC_NOFLAG_C:
+	    break;
+	case NC_VISIBLE_C:
+	    ncp->nc_flag |= NC_VISIBLE;
+	    break;
+	case NC_BROADCAST_C:
+	    ncp->nc_flag |= NC_BROADCAST;
+	    break;
+	default:
+	    return (-1);
+	}
+    }
+    /* protocol family */
+    if ((ncp->nc_protofmly = strtok_r(NULL, "\t ", &lasts)) == NULL) {
+	return (-1);
+    }
+    /* protocol name */
+    if ((ncp->nc_proto = strtok_r(NULL, "\t ", &lasts)) == NULL) {
+	return (-1);
+    }
+    /* network device */
+    if ((ncp->nc_device = strtok_r(NULL, "\t ", &lasts)) == NULL) {
+	return (-1);
+    }
+    if ((tokenp = strtok_r(NULL, "\t ", &lasts)) == NULL) {
+	return (-1);
+    }
+    if (strcmp(tokenp, NC_NOLOOKUP) == 0) {
+	ncp->nc_nlookups = 0;
+	ncp->nc_lookups = NULL;
+    } else {
+	char *cp;	    /* tmp string */
+
+	if (ncp->nc_lookups != NULL)	/* from last visit */
+	    free(ncp->nc_lookups);
+	ncp->nc_lookups = NULL;
+	ncp->nc_nlookups = 0;
+	while ((cp = tokenp) != NULL) {
+	    if ((nc_lookups = realloc(ncp->nc_lookups,
+		(ncp->nc_nlookups + 1) * sizeof *ncp->nc_lookups)) == NULL) {
+		    free(ncp->nc_lookups);
+		    ncp->nc_lookups = NULL;
+		    return (-1);
+	    }
+	    tokenp = _get_next_token(cp, ',');
+	    ncp->nc_lookups = nc_lookups;
+	    ncp->nc_lookups[ncp->nc_nlookups++] = cp;
+	}
+    }
+    return (0);
+}
+
+
+/*
+ * Returns a string describing the reason for failure.
+ */
+char *
+nc_sperror()
+{
+    const char *message;
+
+    switch(nc_error) {
+    case NC_NONETCONFIG:
+	message = _nc_errors[0];
+	break;
+    case NC_NOMEM:
+	message = _nc_errors[1];
+	break;
+    case NC_NOTINIT:
+	message = _nc_errors[2];
+	break;
+    case NC_BADFILE:
+	message = _nc_errors[3];
+	break;
+    case NC_NOTFOUND:
+	message = _nc_errors[4];
+	break;
+    default:
+	message = "Unknown network selection error";
+    }
+    /* LINTED const castaway */
+    return ((char *)message);
+}
+
+/*
+ * Prints a message onto standard error describing the reason for failure.
+ */
+void
+nc_perror(s)
+	const char *s;
+{
+    fprintf(stderr, "%s: %s\n", s, nc_sperror());
+}
+
+/*
+ * Duplicates the matched netconfig buffer.
+ */
+static struct netconfig *
+dup_ncp(ncp)
+struct netconfig	*ncp;
+{
+    struct netconfig	*p;
+    char	*tmp;
+    u_int	i;
+
+    if ((tmp=malloc(MAXNETCONFIGLINE)) == NULL)
+	return(NULL);
+    if ((p=(struct netconfig *)malloc(sizeof(struct netconfig))) == NULL) {
+	free(tmp);
+	return(NULL);
+    }
+    /*
+     * First we dup all the data from matched netconfig buffer.  Then we
+     * adjust some of the member pointer to a pre-allocated buffer where
+     * contains part of the data.
+     * To follow the convention used in parse_ncp(), we store all the
+     * necessary information in the pre-allocated buffer and let each
+     * of the netconfig char pointer member point to the right address
+     * in the buffer.
+     */
+    *p = *ncp;
+    p->nc_netid = (char *)strcpy(tmp,ncp->nc_netid);
+    tmp = strchr(tmp, '\0') + 1;
+    p->nc_protofmly = (char *)strcpy(tmp,ncp->nc_protofmly);
+    tmp = strchr(tmp, '\0') + 1;
+    p->nc_proto = (char *)strcpy(tmp,ncp->nc_proto);
+    tmp = strchr(tmp, '\0') + 1;
+    p->nc_device = (char *)strcpy(tmp,ncp->nc_device);
+    p->nc_lookups = (char **)malloc((size_t)(p->nc_nlookups+1) * sizeof(char *));
+    if (p->nc_lookups == NULL) {
+	free(p->nc_netid);
+	free(p);
+	return(NULL);
+    }
+    for (i=0; i < p->nc_nlookups; i++) {
+    	tmp = strchr(tmp, '\0') + 1;
+    	p->nc_lookups[i] = (char *)strcpy(tmp,ncp->nc_lookups[i]);
+    }
+    return(p);
+}
Index: freebsd/lib/libc/rpc/getnetpath.c
===================================================================
--- freebsd/lib/libc/rpc/getnetpath.c	(revision 60b1d40751c8b3235b7ccbf3bb6ad0c562562f01)
+++ freebsd/lib/libc/rpc/getnetpath.c	(revision 60b1d40751c8b3235b7ccbf3bb6ad0c562562f01)
@@ -0,0 +1,276 @@
+#include <machine/rtems-bsd-user-space.h>
+
+/*	$NetBSD: getnetpath.c,v 1.3 2000/07/06 03:10:34 christos Exp $	*/
+
+/*-
+ * Copyright (c) 2009, Sun Microsystems, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions are met:
+ * - Redistributions of source code must retain the above copyright notice, 
+ *   this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice, 
+ *   this list of conditions and the following disclaimer in the documentation 
+ *   and/or other materials provided with the distribution.
+ * - Neither the name of Sun Microsystems, Inc. nor the names of its 
+ *   contributors may be used to endorse or promote products derived 
+ *   from this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)getnetpath.c	1.11 91/12/19 SMI";
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * Copyright (c) 1989 by Sun Microsystems, Inc.
+ */
+
+#include "namespace.h"
+#include <stdio.h>
+#include <errno.h>
+#include <netconfig.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+#include "un-namespace.h"
+
+/*
+ * internal structure to keep track of a netpath "session"
+ */
+struct netpath_chain {
+    struct netconfig *ncp;  /* an nconf entry */
+    struct netpath_chain *nchain_next;	/* next nconf entry allocated */
+};
+
+
+struct netpath_vars {
+    int   valid;	    /* token that indicates a valid netpath_vars */
+    void *nc_handlep;	    /* handle for current netconfig "session" */
+    char *netpath;	    /* pointer to current view-point in NETPATH */
+    char *netpath_start;    /* pointer to start of our copy of NETPATH */
+    struct netpath_chain *ncp_list;  /* list of nconfs allocated this session*/
+};
+
+#define NP_VALID	0xf00d
+#define NP_INVALID	0
+
+char *_get_next_token(char *, int);
+
+
+/*
+ * A call to setnetpath() establishes a NETPATH "session".  setnetpath()
+ * must be called before the first call to getnetpath().  A "handle" is
+ * returned to distinguish the session; this handle should be passed
+ * subsequently to getnetpath().  (Handles are used to allow for nested calls
+ * to setnetpath()).
+ * If setnetpath() is unable to establish a session (due to lack of memory
+ * resources, or the absence of the /etc/netconfig file), a NULL pointer is
+ * returned.
+ */
+
+void *
+setnetpath()
+{
+
+    struct netpath_vars *np_sessionp;   /* this session's variables */
+    char *npp;				/* NETPATH env variable */
+
+#ifdef MEM_CHK
+    malloc_debug(1);
+#endif
+
+    if ((np_sessionp =
+	(struct netpath_vars *)malloc(sizeof (struct netpath_vars))) == NULL) {
+	return (NULL);
+    }
+    if ((np_sessionp->nc_handlep = setnetconfig()) == NULL) {
+	free(np_sessionp);
+	syslog (LOG_ERR, "rpc: failed to open " NETCONFIG);
+    	return (NULL);
+    }
+    np_sessionp->valid = NP_VALID;
+    np_sessionp->ncp_list = NULL;
+    if ((npp = getenv(NETPATH)) == NULL) {
+	np_sessionp->netpath = NULL;
+    } else {
+	(void) endnetconfig(np_sessionp->nc_handlep);/* won't need nc session*/
+	np_sessionp->nc_handlep = NULL;
+	if ((np_sessionp->netpath = malloc(strlen(npp)+1)) == NULL)
+		goto failed;
+	else {
+	    (void) strcpy(np_sessionp->netpath, npp);
+	}
+    }
+    np_sessionp->netpath_start = np_sessionp->netpath;
+    return ((void *)np_sessionp);
+
+failed:
+    free(np_sessionp);
+    return (NULL);
+}
+
+/*
+ * When first called, getnetpath() returns a pointer to the netconfig
+ * database entry corresponding to the first valid NETPATH component.  The
+ * netconfig entry is formatted as a struct netconfig.
+ * On each subsequent call, getnetpath returns a pointer to the netconfig
+ * entry that corresponds to the next valid NETPATH component.  getnetpath
+ * can thus be used to search the netconfig database for all networks
+ * included in the NETPATH variable.
+ * When NETPATH has been exhausted, getnetpath() returns NULL.  It returns
+ * NULL and sets errno in case of an error (e.g., setnetpath was not called
+ * previously).
+ * getnetpath() silently ignores invalid NETPATH components.  A NETPATH
+ * compnent is invalid if there is no corresponding entry in the netconfig
+ * database.
+ * If the NETPATH variable is unset, getnetpath() behaves as if NETPATH
+ * were set to the sequence of default or visible networks in the netconfig
+ * database, in the order in which they are listed.
+ */
+
+struct netconfig *
+getnetpath(handlep)
+    void *handlep;
+{
+    struct netpath_vars *np_sessionp = (struct netpath_vars *)handlep;
+    struct netconfig *ncp = NULL;   /* temp. holds a netconfig session */
+    struct netpath_chain *chainp;   /* holds chain of ncp's we alloc */
+    char  *npp;		/* holds current NETPATH */
+
+    if (np_sessionp == NULL || np_sessionp->valid != NP_VALID) {
+	errno = EINVAL;
+	return (NULL);
+    }
+    if (np_sessionp->netpath_start == NULL) {	/* NETPATH was not set */
+	do {                /* select next visible network */
+	    if (np_sessionp->nc_handlep == NULL) {
+		np_sessionp->nc_handlep = setnetconfig();
+		if (np_sessionp->nc_handlep == NULL)
+		    syslog (LOG_ERR, "rpc: failed to open " NETCONFIG);
+	    }
+	    if ((ncp = getnetconfig(np_sessionp->nc_handlep)) == NULL) {
+		return(NULL);
+	    }
+	} while ((ncp->nc_flag & NC_VISIBLE) == 0);
+	return (ncp);
+    }
+    /*
+     * Find first valid network ID in netpath.
+     */
+    while ((npp = np_sessionp->netpath) != NULL && strlen(npp) != 0) {
+	np_sessionp->netpath = _get_next_token(npp, ':');
+    	/*
+    	 * npp is a network identifier.
+	 */
+	if ((ncp = getnetconfigent(npp)) != NULL) {
+	    chainp = (struct netpath_chain *)	/* cobble alloc chain entry */
+		    malloc(sizeof (struct netpath_chain));
+	    chainp->ncp = ncp;
+	    chainp->nchain_next = NULL;
+	    if (np_sessionp->ncp_list == NULL) {
+		np_sessionp->ncp_list = chainp;
+	    } else {
+		np_sessionp->ncp_list->nchain_next = chainp;
+	    }
+	    return (ncp);
+	}
+	/* couldn't find this token in the database; go to next one. */
+    }
+    return (NULL);
+}
+
+/*
+ * endnetpath() may be called to unbind NETPATH when processing is complete,
+ * releasing resources for reuse.  It returns 0 on success and -1 on failure
+ * (e.g. if setnetpath() was not called previously.
+ */
+int
+endnetpath(handlep)
+    void *handlep;
+{
+    struct netpath_vars *np_sessionp = (struct netpath_vars *)handlep;
+    struct netpath_chain *chainp, *lastp;
+
+    if (np_sessionp == NULL || np_sessionp->valid != NP_VALID) {
+	errno = EINVAL;
+	return (-1);
+    }
+    if (np_sessionp->nc_handlep != NULL)
+	endnetconfig(np_sessionp->nc_handlep);
+    if (np_sessionp->netpath_start != NULL)
+	free(np_sessionp->netpath_start);
+    for (chainp = np_sessionp->ncp_list; chainp != NULL;
+	    lastp=chainp, chainp=chainp->nchain_next, free(lastp)) {
+	freenetconfigent(chainp->ncp);
+    }
+    free(np_sessionp);
+#ifdef MEM_CHK
+    if (malloc_verify() == 0) {
+	fprintf(stderr, "memory heap corrupted in endnetpath\n");
+	exit(1);
+    }
+#endif
+    return (0);
+}
+
+
+
+/*
+ * Returns pointer to the rest-of-the-string after the current token.
+ * The token itself starts at arg, and we null terminate it.  We return NULL
+ * if either the arg is empty, or if this is the last token.
+ */
+
+char *
+_get_next_token(npp, token)
+char *npp;		/* string */
+int token;		/* char to parse string for */
+{
+    char  *cp;		/* char pointer */
+    char  *np;		/* netpath pointer */
+    char  *ep;		/* escape pointer */
+
+    if ((cp = strchr(npp, token)) == NULL) {
+	return (NULL);
+    }
+    /*
+     * did find a token, but it might be escaped.
+     */
+    if ((cp > npp) && (cp[-1] == '\\')) {
+        /* if slash was also escaped, carry on, otherwise find next token */
+	if ((cp > npp + 1) && (cp[-2] != '\\')) {
+	    /* shift r-o-s  onto the escaped token */
+	    strcpy(&cp[-1], cp);    /* XXX: overlapping string copy */
+	    /*
+	     * Do a recursive call.
+	     * We don't know how many escaped tokens there might be.
+	     */
+	    return (_get_next_token(cp, token));
+	}
+    }
+
+    *cp++ = '\0';		/* null-terminate token */
+    /* get rid of any backslash escapes */
+    ep = npp;
+    while ((np = strchr(ep, '\\')) != 0) {
+	if (np[1] == '\\')
+	    np++;
+	strcpy(np, (ep = &np[1]));  /* XXX: overlapping string copy */
+    }
+    return (cp);		/* return ptr to r-o-s */
+}
Index: freebsd/lib/libc/rpc/getpublickey.c
===================================================================
--- freebsd/lib/libc/rpc/getpublickey.c	(revision 60b1d40751c8b3235b7ccbf3bb6ad0c562562f01)
+++ freebsd/lib/libc/rpc/getpublickey.c	(revision 60b1d40751c8b3235b7ccbf3bb6ad0c562562f01)
@@ -0,0 +1,179 @@
+#include <machine/rtems-bsd-user-space.h>
+
+/*-
+ * Copyright (c) 2009, Sun Microsystems, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions are met:
+ * - Redistributions of source code must retain the above copyright notice, 
+ *   this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice, 
+ *   this list of conditions and the following disclaimer in the documentation 
+ *   and/or other materials provided with the distribution.
+ * - Neither the name of Sun Microsystems, Inc. nor the names of its 
+ *   contributors may be used to endorse or promote products derived 
+ *   from this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)publickey.c 1.10 91/03/11 Copyr 1986 Sun Micro";
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * publickey.c
+ * Copyright (C) 1986, Sun Microsystems, Inc.
+ */
+
+/*
+ * Public key lookup routines
+ */
+#include "namespace.h"
+#include <stdio.h>
+#include <pwd.h>
+#include <rpc/rpc.h>
+#include <rpc/key_prot.h>
+#include <rpcsvc/yp_prot.h>
+#include <rpcsvc/ypclnt.h>
+#include <string.h>
+#include <stdlib.h>
+#include "un-namespace.h"
+
+#define PKFILE "/etc/publickey"
+
+/*
+ * Hack to let ypserv/rpc.nisd use AUTH_DES.
+ */
+int (*__getpublickey_LOCAL)() = 0;
+
+/*
+ * Get somebody's public key
+ */
+static int
+__getpublickey_real(netname, publickey)
+	const char *netname;
+	char *publickey;
+{
+	char lookup[3 * HEXKEYBYTES];
+	char *p;
+
+	if (publickey == NULL)
+		return (0);
+	if (!getpublicandprivatekey(netname, lookup))
+		return (0);
+	p = strchr(lookup, ':');
+	if (p == NULL) {
+		return (0);
+	}
+	*p = '\0';
+	(void) strncpy(publickey, lookup, HEXKEYBYTES);
+	publickey[HEXKEYBYTES] = '\0';
+	return (1);
+}
+
+/*
+ * reads the file /etc/publickey looking for a + to optionally go to the
+ * yellow pages
+ */
+
+int
+getpublicandprivatekey(key, ret)
+	const char *key;
+	char *ret;
+{
+	char buf[1024];	/* big enough */
+	char *res;
+	FILE *fd;
+	char *mkey;
+	char *mval;
+
+	fd = fopen(PKFILE, "r");
+	if (fd == NULL)
+		return (0);
+	for (;;) {
+		res = fgets(buf, sizeof(buf), fd);
+		if (res == NULL) {
+			fclose(fd);
+			return (0);
+		}
+		if (res[0] == '#')
+			continue;
+		else if (res[0] == '+') {
+#ifdef YP
+			char *PKMAP = "publickey.byname";
+			char *lookup;
+			char *domain;
+			int err;
+			int len;
+
+			err = yp_get_default_domain(&domain);
+			if (err) {
+				continue;
+			}
+			lookup = NULL;
+			err = yp_match(domain, PKMAP, key, strlen(key), &lookup, &len);
+			if (err) {
+#ifdef DEBUG
+				fprintf(stderr, "match failed error %d\n", err);
+#endif
+				continue;
+			}
+			lookup[len] = 0;
+			strcpy(ret, lookup);
+			fclose(fd);
+			free(lookup);
+			return (2);
+#else /* YP */
+#ifdef DEBUG
+			fprintf(stderr,
+"Bad record in %s '+' -- NIS not supported in this library copy\n", PKFILE);
+#endif /* DEBUG */
+			continue;
+#endif /* YP */
+		} else {
+			mkey = strsep(&res, "\t ");
+			if (mkey == NULL) {
+				fprintf(stderr,
+				"Bad record in %s -- %s", PKFILE, buf);
+				continue;
+			}
+			do {
+				mval = strsep(&res, " \t#\n");
+			} while (mval != NULL && !*mval);
+			if (mval == NULL) {
+				fprintf(stderr,
+			"Bad record in %s val problem - %s", PKFILE, buf);
+				continue;
+			}
+			if (strcmp(mkey, key) == 0) {
+				strcpy(ret, mval);
+				fclose(fd);
+				return (1);
+			}
+		}
+	}
+}
+
+int getpublickey(netname, publickey)
+	const char *netname;
+	char *publickey;
+{
+	if (__getpublickey_LOCAL != NULL)
+		return(__getpublickey_LOCAL(netname, publickey));
+	else
+		return(__getpublickey_real(netname, publickey));
+}
Index: freebsd/lib/libc/rpc/getrpcent.c
===================================================================
--- freebsd/lib/libc/rpc/getrpcent.c	(revision 60b1d40751c8b3235b7ccbf3bb6ad0c562562f01)
+++ freebsd/lib/libc/rpc/getrpcent.c	(revision 60b1d40751c8b3235b7ccbf3bb6ad0c562562f01)
@@ -0,0 +1,1048 @@
+#include <machine/rtems-bsd-user-space.h>
+
+/*	$NetBSD: getrpcent.c,v 1.17 2000/01/22 22:19:17 mycroft Exp $	*/
+
+/*-
+ * Copyright (c) 2009, Sun Microsystems, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions are met:
+ * - Redistributions of source code must retain the above copyright notice, 
+ *   this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice, 
+ *   this list of conditions and the following disclaimer in the documentation 
+ *   and/or other materials provided with the distribution.
+ * - Neither the name of Sun Microsystems, Inc. nor the names of its 
+ *   contributors may be used to endorse or promote products derived 
+ *   from this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char *sccsid = "@(#)getrpcent.c 1.14 91/03/11 Copyr 1984 Sun Micro";
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * Copyright (c) 1984 by Sun Microsystems, Inc.
+ */
+
+#include <rtems/bsd/sys/param.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <assert.h>
+#include <errno.h>
+#include <nsswitch.h>
+#include <netinet/in.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <rpc/rpc.h>
+#ifdef YP
+#include <rpcsvc/yp_prot.h>
+#include <rpcsvc/ypclnt.h>
+#endif
+#include <unistd.h>
+#include "namespace.h"
+#include "reentrant.h"
+#include "un-namespace.h"
+#include "libc_private.h"
+#include "nss_tls.h"
+#ifdef NS_CACHING
+#include "nscache.h"
+#endif
+
+#define	RPCDB	"/etc/rpc"
+
+/* nsswitch declarations */
+enum constants
+{
+	SETRPCENT = 1,
+	ENDRPCENT = 2,
+	RPCENT_STORAGE_INITIAL	= 1 << 10, /* 1 KByte */
+	RPCENT_STORAGE_MAX	= 1 << 20, /* 1 MByte */
+};
+
+static const ns_src defaultsrc[] = {
+	{ NSSRC_FILES, NS_SUCCESS },
+#ifdef YP
+	{ NSSRC_NIS, NS_SUCCESS },
+#endif
+	{ NULL, 0 }
+};
+
+/* files backend declarations */
+struct files_state {
+	FILE	*fp;
+	int	stayopen;
+};
+
+static	int	files_rpcent(void *, void *, va_list);
+static	int	files_setrpcent(void *, void *, va_list);
+
+static	void	files_endstate(void *);
+NSS_TLS_HANDLING(files);
+
+/* nis backend declarations */
+#ifdef YP
+struct nis_state {
+	char	domain[MAXHOSTNAMELEN];
+	char	*current;
+	int	currentlen;
+	int	stepping;
+	int	no_name_map;
+};
+
+static	int	nis_rpcent(void *, void *, va_list);
+static	int	nis_setrpcent(void *, void *, va_list);
+
+static	void	nis_endstate(void *);
+NSS_TLS_HANDLING(nis);
+#endif
+
+/* get** wrappers for get**_r functions declarations */
+struct rpcent_state {
+	struct rpcent	rpc;
+	char		*buffer;
+	size_t	bufsize;
+};
+static	void	rpcent_endstate(void *);
+NSS_TLS_HANDLING(rpcent);
+
+union key {
+	const char	*name;
+	int		number;
+};
+
+static int wrap_getrpcbyname_r(union key, struct rpcent *, char *,
+			size_t, struct rpcent **);
+static int wrap_getrpcbynumber_r(union key, struct rpcent *, char *,
+			size_t, struct rpcent **);
+static int wrap_getrpcent_r(union key, struct rpcent *, char *,
+			size_t, struct rpcent **);
+static struct rpcent *getrpc(int (*fn)(union key, struct rpcent *, char *,
+			size_t, struct rpcent **), union key);
+
+#ifdef NS_CACHING
+static int rpc_id_func(char *, size_t *, va_list, void *);
+static int rpc_marshal_func(char *, size_t *, void *, va_list, void *);
+static int rpc_unmarshal_func(char *, size_t, void *, va_list, void *);
+#endif
+
+static int
+rpcent_unpack(char *p, struct rpcent *rpc, char **r_aliases,
+	size_t aliases_size, int *errnop)
+{
+	char *cp, **q;
+
+	assert(p != NULL);
+
+	if (*p == '#')
+		return (-1);
+	cp = strpbrk(p, "#\n");
+	if (cp == NULL)
+		return (-1);
+	*cp = '\0';
+	cp = strpbrk(p, " \t");
+	if (cp == NULL)
+		return (-1);
+	*cp++ = '\0';
+	/* THIS STUFF IS INTERNET SPECIFIC */
+	rpc->r_name = p;
+	while (*cp == ' ' || *cp == '\t')
+		cp++;
+	rpc->r_number = atoi(cp);
+	q = rpc->r_aliases = r_aliases;
+	cp = strpbrk(cp, " \t");
+	if (cp != NULL)
+		*cp++ = '\0';
+	while (cp && *cp) {
+		if (*cp == ' ' || *cp == '\t') {
+			cp++;
+			continue;
+		}
+		if (q < &(r_aliases[aliases_size - 1]))
+			*q++ = cp;
+		else {
+			*errnop = ERANGE;
+			return -1;
+		}
+
+		cp = strpbrk(cp, " \t");
+		if (cp != NULL)
+			*cp++ = '\0';
+	}
+	*q = NULL;
+	return 0;
+}
+
+/* files backend implementation */
+static	void
+files_endstate(void *p)
+{
+	FILE * f;
+
+	if (p == NULL)
+		return;
+
+	f = ((struct files_state *)p)->fp;
+	if (f != NULL)
+		fclose(f);
+
+	free(p);
+}
+
+static int
+files_rpcent(void *retval, void *mdata, va_list ap)
+{
+	char *name;
+	int number;
+	struct rpcent *rpc;
+	char *buffer;
+	size_t bufsize;
+	int *errnop;
+
+	char *line;
+	size_t linesize;
+	char **aliases;
+	int aliases_size;
+	char **rp;
+
+	struct files_state	*st;
+	int rv;
+	int stayopen;
+	enum nss_lookup_type how;
+
+	how = (enum nss_lookup_type)mdata;
+	switch (how)
+	{
+	case nss_lt_name:
+		name = va_arg(ap, char *);
+		break;
+	case nss_lt_id:
+		number = va_arg(ap, int);
+		break;
+	case nss_lt_all:
+		break;
+	default:
+		return (NS_NOTFOUND);
+	}
+
+	rpc = va_arg(ap, struct rpcent *);
+	buffer = va_arg(ap, char *);
+	bufsize = va_arg(ap, size_t);
+	errnop = va_arg(ap, int *);
+
+	*errnop = files_getstate(&st);
+	if (*errnop != 0)
+		return (NS_UNAVAIL);
+
+	if (st->fp == NULL && (st->fp = fopen(RPCDB, "r")) == NULL) {
+		*errnop = errno;
+		return (NS_UNAVAIL);
+	}
+
+	if (how == nss_lt_all)
+		stayopen = 1;
+	else {
+		rewind(st->fp);
+		stayopen = st->stayopen;
+	}
+
+	do {
+		if ((line = fgetln(st->fp, &linesize)) == NULL) {
+			*errnop = errno;
+			rv = NS_RETURN;
+			break;
+		}
+
+		if (bufsize <= linesize + _ALIGNBYTES + sizeof(char *)) {
+			*errnop = ERANGE;
+			rv = NS_RETURN;
+			break;
+		}
+
+		aliases = (char **)_ALIGN(&buffer[linesize+1]);
+		aliases_size = (buffer + bufsize -
+			(char *)aliases)/sizeof(char *);
+		if (aliases_size < 1) {
+			*errnop = ERANGE;
+			rv = NS_RETURN;
+			break;
+		}
+
+		memcpy(buffer, line, linesize);
+		buffer[linesize] = '\0';
+
+		rv = rpcent_unpack(buffer, rpc, aliases, aliases_size, errnop);
+		if (rv != 0) {
+			if (*errnop == 0) {
+				rv = NS_NOTFOUND;
+				continue;
+			}
+			else {
+				rv = NS_RETURN;
+				break;
+			}
+		}
+
+		switch (how)
+		{
+		case nss_lt_name:
+			if (strcmp(rpc->r_name, name) == 0)
+				goto done;
+			for (rp = rpc->r_aliases; *rp != NULL; rp++) {
+				if (strcmp(*rp, name) == 0)
+					goto done;
+			}
+			rv = NS_NOTFOUND;
+			continue;
+done:
+			rv = NS_SUCCESS;
+			break;
+		case nss_lt_id:
+			rv = (rpc->r_number == number) ? NS_SUCCESS :
+				NS_NOTFOUND;
+			break;
+		case nss_lt_all:
+			rv = NS_SUCCESS;
+			break;
+		}
+
+	} while (!(rv & NS_TERMINATE));
+
+	if (!stayopen && st->fp!=NULL) {
+		fclose(st->fp);
+		st->fp = NULL;
+	}
+
+	if ((rv == NS_SUCCESS) && (retval != NULL))
+		*((struct rpcent **)retval) = rpc;
+
+	return (rv);
+}
+
+static int
+files_setrpcent(void *retval, void *mdata, va_list ap)
+{
+	struct files_state	*st;
+	int	rv;
+	int	f;
+
+	rv = files_getstate(&st);
+	if (rv != 0)
+		return (NS_UNAVAIL);
+
+	switch ((enum constants)mdata)
+	{
+	case SETRPCENT:
+		f = va_arg(ap,int);
+		if (st->fp == NULL)
+			st->fp = fopen(RPCDB, "r");
+		else
+			rewind(st->fp);
+		st->stayopen |= f;
+		break;
+	case ENDRPCENT:
+		if (st->fp != NULL) {
+			fclose(st->fp);
+			st->fp = NULL;
+		}
+		st->stayopen = 0;
+		break;
+	default:
+		break;
+	}
+
+	return (NS_UNAVAIL);
+}
+
+/* nis backend implementation */
+#ifdef YP
+static 	void
+nis_endstate(void *p)
+{
+	if (p == NULL)
+		return;
+
+	free(((struct nis_state *)p)->current);
+	free(p);
+}
+
+static int
+nis_rpcent(void *retval, void *mdata, va_list ap)
+{
+	char		*name;
+	int		number;
+	struct rpcent	*rpc;
+	char		*buffer;
+	size_t	bufsize;
+	int		*errnop;
+
+	char		**rp;
+	char		**aliases;
+	int		aliases_size;
+
+	char	*lastkey;
+	char	*resultbuf;
+	int	resultbuflen;
+	char	buf[YPMAXRECORD + 2];
+
+	struct nis_state	*st;
+	int		rv;
+	enum nss_lookup_type	how;
+	int	no_name_active;
+
+	how = (enum nss_lookup_type)mdata;
+	switch (how)
+	{
+	case nss_lt_name:
+		name = va_arg(ap, char *);
+		break;
+	case nss_lt_id:
+		number = va_arg(ap, int);
+		break;
+	case nss_lt_all:
+		break;
+	default:
+		return (NS_NOTFOUND);
+	}
+
+	rpc = va_arg(ap, struct rpcent *);
+	buffer = va_arg(ap, char *);
+	bufsize = va_arg(ap, size_t);
+	errnop = va_arg(ap, int *);
+
+	*errnop = nis_getstate(&st);
+	if (*errnop != 0)
+		return (NS_UNAVAIL);
+
+	if (st->domain[0] == '\0') {
+		if (getdomainname(st->domain, sizeof(st->domain)) != 0) {
+			*errnop = errno;
+			return (NS_UNAVAIL);
+		}
+	}
+
+	no_name_active = 0;
+	do {
+		switch (how)
+		{
+		case nss_lt_name:
+			if (!st->no_name_map)
+			{
+				snprintf(buf, sizeof buf, "%s", name);
+				rv = yp_match(st->domain, "rpc.byname", buf,
+			    		strlen(buf), &resultbuf, &resultbuflen);
+
+				switch (rv) {
+				case 0:
+					break;
+				case YPERR_MAP:
+					st->stepping = 0;
+					no_name_active = 1;
+					how = nss_lt_all;
+
+					rv = NS_NOTFOUND;
+					continue;
+				default:
+					rv = NS_NOTFOUND;
+					goto fin;
+				}
+			} else {
+				st->stepping = 0;
+				no_name_active = 1;
+				how = nss_lt_all;
+
+				rv = NS_NOTFOUND;
+				continue;
+			}
+		break;
+		case nss_lt_id:
+			snprintf(buf, sizeof buf, "%d", number);
+			if (yp_match(st->domain, "rpc.bynumber", buf,
+			    	strlen(buf), &resultbuf, &resultbuflen)) {
+				rv = NS_NOTFOUND;
+				goto fin;
+			}
+			break;
+		case nss_lt_all:
+				if (!st->stepping) {
+					rv = yp_first(st->domain, "rpc.bynumber",
+				    		&st->current,
+						&st->currentlen, &resultbuf,
+				    		&resultbuflen);
+					if (rv) {
+						rv = NS_NOTFOUND;
+						goto fin;
+					}
+					st->stepping = 1;
+				} else {
+					lastkey = st->current;
+					rv = yp_next(st->domain, "rpc.bynumber",
+				    		st->current,
+						st->currentlen, &st->current,
+				    		&st->currentlen,
+						&resultbuf,	&resultbuflen);
+					free(lastkey);
+					if (rv) {
+						st->stepping = 0;
+						rv = NS_NOTFOUND;
+						goto fin;
+					}
+				}
+			break;
+		}
+
+		/* we need a room for additional \n symbol */
+		if (bufsize <= resultbuflen + 1 + _ALIGNBYTES +
+		    sizeof(char *)) {
+			*errnop = ERANGE;
+			rv = NS_RETURN;
+			break;
+		}
+
+		aliases=(char **)_ALIGN(&buffer[resultbuflen+2]);
+		aliases_size = (buffer + bufsize - (char *)aliases) /
+			sizeof(char *);
+		if (aliases_size < 1) {
+			*errnop = ERANGE;
+			rv = NS_RETURN;
+			break;
+		}
+
+		/*
+		 * rpcent_unpack expects lines terminated with \n -- make it happy
+		 */
+		memcpy(buffer, resultbuf, resultbuflen);
+		buffer[resultbuflen] = '\n';
+		buffer[resultbuflen+1] = '\0';
+		free(resultbuf);
+
+		if (rpcent_unpack(buffer, rpc, aliases, aliases_size,
+		    errnop) != 0) {
+			if (*errnop == 0)
+				rv = NS_NOTFOUND;
+			else
+				rv = NS_RETURN;
+		} else {
+			if ((how == nss_lt_all) && (no_name_active != 0)) {
+				if (strcmp(rpc->r_name, name) == 0)
+					goto done;
+				for (rp = rpc->r_aliases; *rp != NULL; rp++) {
+					if (strcmp(*rp, name) == 0)
+						goto done;
+				}
+				rv = NS_NOTFOUND;
+				continue;
+done:
+				rv = NS_SUCCESS;
+			} else
+				rv = NS_SUCCESS;
+		}
+
+	} while (!(rv & NS_TERMINATE) && (how == nss_lt_all));
+
+fin:
+	if ((rv == NS_SUCCESS) && (retval != NULL))
+		*((struct rpcent **)retval) = rpc;
+
+	return (rv);
+}
+
+static int
+nis_setrpcent(void *retval, void *mdata, va_list ap)
+{
+	struct nis_state	*st;
+	int	rv;
+
+	rv = nis_getstate(&st);
+	if (rv != 0)
+		return (NS_UNAVAIL);
+
+	switch ((enum constants)mdata)
+	{
+	case SETRPCENT:
+	case ENDRPCENT:
+		free(st->current);
+		st->current = NULL;
+		st->stepping = 0;
+		break;
+	default:
+		break;
+	}
+
+	return (NS_UNAVAIL);
+}
+#endif
+
+#ifdef NS_CACHING
+static int
+rpc_id_func(char *buffer, size_t *buffer_size, va_list ap, void *cache_mdata)
+{
+	char *name;
+	int rpc;
+
+	size_t desired_size, size;
+	enum nss_lookup_type lookup_type;
+	int res = NS_UNAVAIL;
+
+	lookup_type = (enum nss_lookup_type)cache_mdata;
+	switch (lookup_type) {
+	case nss_lt_name:
+		name = va_arg(ap, char *);
+
+		size = strlen(name);
+		desired_size = sizeof(enum nss_lookup_type) + size + 1;
+		if (desired_size > *buffer_size) {
+			res = NS_RETURN;
+			goto fin;
+		}
+
+		memcpy(buffer, &lookup_type, sizeof(enum nss_lookup_type));
+		memcpy(buffer + sizeof(enum nss_lookup_type), name, size + 1);
+
+		res = NS_SUCCESS;
+		break;
+	case nss_lt_id:
+		rpc = va_arg(ap, int);
+
+		desired_size = sizeof(enum nss_lookup_type) + sizeof(int);
+		if (desired_size > *buffer_size) {
+			res = NS_RETURN;
+			goto fin;
+		}
+
+		memcpy(buffer, &lookup_type, sizeof(enum nss_lookup_type));
+		memcpy(buffer + sizeof(enum nss_lookup_type), &rpc,
+		    sizeof(int));
+
+		res = NS_SUCCESS;
+		break;
+	default:
+		/* should be unreachable */
+		return (NS_UNAVAIL);
+	}
+
+fin:
+	*buffer_size = desired_size;
+	return (res);
+}
+
+static int
+rpc_marshal_func(char *buffer, size_t *buffer_size, void *retval, va_list ap,
+    void *cache_mdata)
+{
+	char *name;
+	int num;
+	struct rpcent *rpc;
+	char *orig_buf;
+	size_t orig_buf_size;
+
+	struct rpcent new_rpc;
+	size_t desired_size, size, aliases_size;
+	char *p;
+	char **alias;
+
+	switch ((enum nss_lookup_type)cache_mdata) {
+	case nss_lt_name:
+		name = va_arg(ap, char *);
+		break;
+	case nss_lt_id:
+		num = va_arg(ap, int);
+		break;
+	case nss_lt_all:
+		break;
+	default:
+		/* should be unreachable */
+		return (NS_UNAVAIL);
+	}
+
+	rpc = va_arg(ap, struct rpcent *);
+	orig_buf = va_arg(ap, char *);
+	orig_buf_size = va_arg(ap, size_t);
+
+	desired_size = _ALIGNBYTES + sizeof(struct rpcent) + sizeof(char *);
+	if (rpc->r_name != NULL)
+		desired_size += strlen(rpc->r_name) + 1;
+
+	if (rpc->r_aliases != NULL) {
+		aliases_size = 0;
+		for (alias = rpc->r_aliases; *alias; ++alias) {
+			desired_size += strlen(*alias) + 1;
+			++aliases_size;
+		}
+
+		desired_size += _ALIGNBYTES + (aliases_size + 1) *
+		    sizeof(char *);
+	}
+
+	if (*buffer_size < desired_size) {
+		/* this assignment is here for future use */
+		*buffer_size = desired_size;
+		return (NS_RETURN);
+	}
+
+	new_rpc = *rpc;
+
+	*buffer_size = desired_size;
+	memset(buffer, 0, desired_size);
+	p = buffer + sizeof(struct rpcent) + sizeof(char *);
+	memcpy(buffer + sizeof(struct rpcent), &p, sizeof(char *));
+	p = (char *)_ALIGN(p);
+
+	if (new_rpc.r_name != NULL) {
+		size = strlen(new_rpc.r_name);
+		memcpy(p, new_rpc.r_name, size);
+		new_rpc.r_name = p;
+		p += size + 1;
+	}
+
+	if (new_rpc.r_aliases != NULL) {
+		p = (char *)_ALIGN(p);
+		memcpy(p, new_rpc.r_aliases, sizeof(char *) * aliases_size);
+		new_rpc.r_aliases = (char **)p;
+		p += sizeof(char *) * (aliases_size + 1);
+
+		for (alias = new_rpc.r_aliases; *alias; ++alias) {
+			size = strlen(*alias);
+			memcpy(p, *alias, size);
+			*alias = p;
+			p += size + 1;
+		}
+	}
+
+	memcpy(buffer, &new_rpc, sizeof(struct rpcent));
+	return (NS_SUCCESS);
+}
+
+static int
+rpc_unmarshal_func(char *buffer, size_t buffer_size, void *retval, va_list ap,
+    void *cache_mdata)
+{
+	char *name;
+	int num;
+	struct rpcent *rpc;
+	char *orig_buf;
+	size_t orig_buf_size;
+	int *ret_errno;
+
+	char *p;
+	char **alias;
+
+	switch ((enum nss_lookup_type)cache_mdata) {
+	case nss_lt_name:
+		name = va_arg(ap, char *);
+		break;
+	case nss_lt_id:
+		num = va_arg(ap, int);
+		break;
+	case nss_lt_all:
+		break;
+	default:
+		/* should be unreachable */
+		return (NS_UNAVAIL);
+	}
+
+	rpc = va_arg(ap, struct rpcent *);
+	orig_buf = va_arg(ap, char *);
+	orig_buf_size = va_arg(ap, size_t);
+	ret_errno = va_arg(ap, int *);
+
+	if (orig_buf_size <
+	    buffer_size - sizeof(struct rpcent) - sizeof(char *)) {
+		*ret_errno = ERANGE;
+		return (NS_RETURN);
+	}
+
+	memcpy(rpc, buffer, sizeof(struct rpcent));
+	memcpy(&p, buffer + sizeof(struct rpcent), sizeof(char *));
+
+	orig_buf = (char *)_ALIGN(orig_buf);
+	memcpy(orig_buf, buffer + sizeof(struct rpcent) + sizeof(char *) +
+	    _ALIGN(p) - (size_t)p,
+	    buffer_size - sizeof(struct rpcent) - sizeof(char *) -
+	    _ALIGN(p) + (size_t)p);
+	p = (char *)_ALIGN(p);
+
+	NS_APPLY_OFFSET(rpc->r_name, orig_buf, p, char *);
+	if (rpc->r_aliases != NULL) {
+		NS_APPLY_OFFSET(rpc->r_aliases, orig_buf, p, char **);
+
+		for (alias = rpc->r_aliases	; *alias; ++alias)
+			NS_APPLY_OFFSET(*alias, orig_buf, p, char *);
+	}
+
+	if (retval != NULL)
+		*((struct rpcent **)retval) = rpc;
+
+	return (NS_SUCCESS);
+}
+
+NSS_MP_CACHE_HANDLING(rpc);
+#endif /* NS_CACHING */
+
+
+/* get**_r functions implementation */
+static int
+getrpcbyname_r(const char *name, struct rpcent *rpc, char *buffer,
+	size_t bufsize, struct rpcent **result)
+{
+#ifdef NS_CACHING
+	static const nss_cache_info cache_info =
+    		NS_COMMON_CACHE_INFO_INITIALIZER(
+		rpc, (void *)nss_lt_name,
+		rpc_id_func, rpc_marshal_func, rpc_unmarshal_func);
+#endif
+	static const ns_dtab dtab[] = {
+		{ NSSRC_FILES, files_rpcent, (void *)nss_lt_name },
+#ifdef YP
+		{ NSSRC_NIS, nis_rpcent, (void *)nss_lt_name },
+#endif
+#ifdef NS_CACHING
+		NS_CACHE_CB(&cache_info)
+#endif
+		{ NULL, NULL, NULL }
+	};
+	int rv, ret_errno;
+
+	ret_errno = 0;
+	*result = NULL;
+	rv = nsdispatch(result, dtab, NSDB_RPC, "getrpcbyname_r", defaultsrc,
+	    name, rpc, buffer, bufsize, &ret_errno);
+
+	if (rv == NS_SUCCESS)
+		return (0);
+	else
+		return (ret_errno);
+}
+
+static int
+getrpcbynumber_r(int number, struct rpcent *rpc, char *buffer,
+	size_t bufsize, struct rpcent **result)
+{
+#ifdef NS_CACHING
+	static const nss_cache_info cache_info =
+    		NS_COMMON_CACHE_INFO_INITIALIZER(
+		rpc, (void *)nss_lt_id,
+		rpc_id_func, rpc_marshal_func, rpc_unmarshal_func);
+#endif
+	static const ns_dtab dtab[] = {
+		{ NSSRC_FILES, files_rpcent, (void *)nss_lt_id },
+#ifdef YP
+		{ NSSRC_NIS, nis_rpcent, (void *)nss_lt_id },
+#endif
+#ifdef NS_CACHING
+		NS_CACHE_CB(&cache_info)
+#endif
+		{ NULL, NULL, NULL }
+	};
+	int rv, ret_errno;
+
+	ret_errno = 0;
+	*result = NULL;
+	rv = nsdispatch(result, dtab, NSDB_RPC, "getrpcbynumber_r", defaultsrc,
+	    number, rpc, buffer, bufsize, &ret_errno);
+
+	if (rv == NS_SUCCESS)
+		return (0);
+	else
+		return (ret_errno);
+}
+
+static int
+getrpcent_r(struct rpcent *rpc, char *buffer, size_t bufsize,
+	struct rpcent **result)
+{
+#ifdef NS_CACHING
+	static const nss_cache_info cache_info = NS_MP_CACHE_INFO_INITIALIZER(
+		rpc, (void *)nss_lt_all,
+		rpc_marshal_func, rpc_unmarshal_func);
+#endif
+	static const ns_dtab dtab[] = {
+		{ NSSRC_FILES, files_rpcent, (void *)nss_lt_all },
+#ifdef YP
+		{ NSSRC_NIS, nis_rpcent, (void *)nss_lt_all },
+#endif
+#ifdef NS_CACHING
+		NS_CACHE_CB(&cache_info)
+#endif
+		{ NULL, NULL, NULL }
+	};
+	int rv, ret_errno;
+
+	ret_errno = 0;
+	*result = NULL;
+	rv = nsdispatch(result, dtab, NSDB_RPC, "getrpcent_r", defaultsrc,
+	    rpc, buffer, bufsize, &ret_errno);
+
+	if (rv == NS_SUCCESS)
+		return (0);
+	else
+		return (ret_errno);
+}
+
+/* get** wrappers for get**_r functions implementation */
+static 	void
+rpcent_endstate(void *p)
+{
+	if (p == NULL)
+		return;
+
+	free(((struct rpcent_state *)p)->buffer);
+	free(p);
+}
+
+static	int
+wrap_getrpcbyname_r(union key key, struct rpcent *rpc, char *buffer,
+    size_t bufsize, struct rpcent **res)
+{
+	return (getrpcbyname_r(key.name, rpc, buffer, bufsize, res));
+}
+
+static	int
+wrap_getrpcbynumber_r(union key key, struct rpcent *rpc, char *buffer,
+    size_t bufsize, struct rpcent **res)
+{
+	return (getrpcbynumber_r(key.number, rpc, buffer, bufsize, res));
+}
+
+static	int
+wrap_getrpcent_r(union key key __unused, struct rpcent *rpc, char *buffer,
+    size_t bufsize, struct rpcent **res)
+{
+	return (getrpcent_r(rpc, buffer, bufsize, res));
+}
+
+static struct rpcent *
+getrpc(int (*fn)(union key, struct rpcent *, char *, size_t, struct rpcent **),
+    union key key)
+{
+	int		 rv;
+	struct rpcent	*res;
+	struct rpcent_state * st;
+
+	rv=rpcent_getstate(&st);
+	if (rv != 0) {
+		errno = rv;
+		return NULL;
+	}
+
+	if (st->buffer == NULL) {
+		st->buffer = malloc(RPCENT_STORAGE_INITIAL);
+		if (st->buffer == NULL)
+			return (NULL);
+		st->bufsize = RPCENT_STORAGE_INITIAL;
+	}
+	do {
+		rv = fn(key, &st->rpc, st->buffer, st->bufsize, &res);
+		if (res == NULL && rv == ERANGE) {
+			free(st->buffer);
+			if ((st->bufsize << 1) > RPCENT_STORAGE_MAX) {
+				st->buffer = NULL;
+				errno = ERANGE;
+				return (NULL);
+			}
+			st->bufsize <<= 1;
+			st->buffer = malloc(st->bufsize);
+			if (st->buffer == NULL)
+				return (NULL);
+		}
+	} while (res == NULL && rv == ERANGE);
+	if (rv != 0)
+		errno = rv;
+
+	return (res);
+}
+
+struct rpcent *
+getrpcbyname(char *name)
+{
+	union key key;
+
+	key.name = name;
+
+	return (getrpc(wrap_getrpcbyname_r, key));
+}
+
+struct rpcent *
+getrpcbynumber(int number)
+{
+	union key key;
+
+	key.number = number;
+
+	return (getrpc(wrap_getrpcbynumber_r, key));
+}
+
+struct rpcent *
+getrpcent()
+{
+	union key key;
+
+	key.number = 0;	/* not used */
+
+	return (getrpc(wrap_getrpcent_r, key));
+}
+
+void
+setrpcent(int stayopen)
+{
+#ifdef NS_CACHING
+	static const nss_cache_info cache_info = NS_MP_CACHE_INFO_INITIALIZER(
+		rpc, (void *)nss_lt_all,
+		NULL, NULL);
+#endif
+
+	static const ns_dtab dtab[] = {
+		{ NSSRC_FILES, files_setrpcent, (void *)SETRPCENT },
+#ifdef YP
+		{ NSSRC_NIS, nis_setrpcent, (void *)SETRPCENT },
+#endif
+#ifdef NS_CACHING
+		NS_CACHE_CB(&cache_info)
+#endif
+		{ NULL, NULL, NULL }
+	};
+
+	(void)nsdispatch(NULL, dtab, NSDB_RPC, "setrpcent", defaultsrc,
+		stayopen);
+}
+
+void
+endrpcent()
+{
+#ifdef NS_CACHING
+	static const nss_cache_info cache_info = NS_MP_CACHE_INFO_INITIALIZER(
+		rpc, (void *)nss_lt_all,
+		NULL, NULL);
+#endif
+
+	static const ns_dtab dtab[] = {
+		{ NSSRC_FILES, files_setrpcent, (void *)ENDRPCENT },
+#ifdef YP
+		{ NSSRC_NIS, nis_setrpcent, (void *)ENDRPCENT },
+#endif
+#ifdef NS_CACHING
+		NS_CACHE_CB(&cache_info)
+#endif
+		{ NULL, NULL, NULL }
+	};
+
+	(void)nsdispatch(NULL, dtab, NSDB_RPC, "endrpcent", defaultsrc);
+}
Index: freebsd/lib/libc/rpc/getrpcport.c
===================================================================
--- freebsd/lib/libc/rpc/getrpcport.c	(revision 60b1d40751c8b3235b7ccbf3bb6ad0c562562f01)
+++ freebsd/lib/libc/rpc/getrpcport.c	(revision 60b1d40751c8b3235b7ccbf3bb6ad0c562562f01)
@@ -0,0 +1,79 @@
+#include <machine/rtems-bsd-user-space.h>
+
+/*	$NetBSD: getrpcport.c,v 1.16 2000/01/22 22:19:18 mycroft Exp $	*/
+
+/*-
+ * Copyright (c) 2009, Sun Microsystems, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions are met:
+ * - Redistributions of source code must retain the above copyright notice, 
+ *   this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice, 
+ *   this list of conditions and the following disclaimer in the documentation 
+ *   and/or other materials provided with the distribution.
+ * - Neither the name of Sun Microsystems, Inc. nor the names of its 
+ *   contributors may be used to endorse or promote products derived 
+ *   from this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char *sccsid2 = "@(#)getrpcport.c 1.3 87/08/11 SMI";
+static char *sccsid = "@(#)getrpcport.c	2.1 88/07/29 4.0 RPCSRC";
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * Copyright (c) 1985 by Sun Microsystems, Inc.
+ */
+
+#include "namespace.h"
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <assert.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <rpc/rpc.h>
+#include <rpc/pmap_clnt.h>
+#include "un-namespace.h"
+
+int
+getrpcport(host, prognum, versnum, proto)
+	char *host;
+	int prognum, versnum, proto;
+{
+	struct sockaddr_in addr;
+	struct hostent *hp;
+
+	assert(host != NULL);
+
+	if ((hp = gethostbyname(host)) == NULL)
+		return (0);
+	memset(&addr, 0, sizeof(addr));
+	addr.sin_len = sizeof(struct sockaddr_in);
+	addr.sin_family = AF_INET;
+	addr.sin_port =  0;
+	if (hp->h_length > addr.sin_len)
+		hp->h_length = addr.sin_len;
+	memcpy(&addr.sin_addr.s_addr, hp->h_addr, (size_t)hp->h_length);
+	/* Inconsistent interfaces need casts! :-( */
+	return (pmap_getport(&addr, (u_long)prognum, (u_long)versnum, 
+	    (u_int)proto));
+}
Index: freebsd/lib/libc/rpc/key_call.c
===================================================================
--- freebsd/lib/libc/rpc/key_call.c	(revision 60b1d40751c8b3235b7ccbf3bb6ad0c562562f01)
+++ freebsd/lib/libc/rpc/key_call.c	(revision 60b1d40751c8b3235b7ccbf3bb6ad0c562562f01)
@@ -0,0 +1,481 @@
+#include <machine/rtems-bsd-user-space.h>
+
+/*-
+ * Copyright (c) 2009, Sun Microsystems, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions are met:
+ * - Redistributions of source code must retain the above copyright notice, 
+ *   this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice, 
+ *   this list of conditions and the following disclaimer in the documentation 
+ *   and/or other materials provided with the distribution.
+ * - Neither the name of Sun Microsystems, Inc. nor the names of its 
+ *   contributors may be used to endorse or promote products derived 
+ *   from this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * Copyright (c) 1986-1991 by Sun Microsystems Inc. 
+ */
+
+#ident	"@(#)key_call.c	1.25	94/04/24 SMI"
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * key_call.c, Interface to keyserver
+ *
+ * setsecretkey(key) - set your secret key
+ * encryptsessionkey(agent, deskey) - encrypt a session key to talk to agent
+ * decryptsessionkey(agent, deskey) - decrypt ditto
+ * gendeskey(deskey) - generate a secure des key
+ */
+
+#include "namespace.h"
+#include "reentrant.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <rpc/rpc.h>
+#include <rpc/auth.h>
+#include <rpc/auth_unix.h>
+#include <rpc/key_prot.h>
+#include <string.h>
+#include <netconfig.h>
+#include <sys/utsname.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <sys/wait.h>
+#include <sys/fcntl.h>
+#include "un-namespace.h"
+#include "mt_misc.h"
+
+
+#define	KEY_TIMEOUT	5	/* per-try timeout in seconds */
+#define	KEY_NRETRY	12	/* number of retries */
+
+#ifdef DEBUG
+#define	debug(msg)	(void) fprintf(stderr, "%s\n", msg);
+#else
+#define	debug(msg)
+#endif /* DEBUG */
+
+/*
+ * Hack to allow the keyserver to use AUTH_DES (for authenticated
+ * NIS+ calls, for example).  The only functions that get called
+ * are key_encryptsession_pk, key_decryptsession_pk, and key_gendes.
+ *
+ * The approach is to have the keyserver fill in pointers to local
+ * implementations of these functions, and to call those in key_call().
+ */
+
+cryptkeyres *(*__key_encryptsession_pk_LOCAL)() = 0;
+cryptkeyres *(*__key_decryptsession_pk_LOCAL)() = 0;
+des_block *(*__key_gendes_LOCAL)() = 0;
+
+static int key_call( u_long, xdrproc_t, void *, xdrproc_t, void *);
+
+int
+key_setsecret(secretkey)
+	const char *secretkey;
+{
+	keystatus status;
+
+	if (!key_call((u_long) KEY_SET, (xdrproc_t)xdr_keybuf,
+			(void *)secretkey,
+			(xdrproc_t)xdr_keystatus, &status)) {
+		return (-1);
+	}
+	if (status != KEY_SUCCESS) {
+		debug("set status is nonzero");
+		return (-1);
+	}
+	return (0);
+}
+
+
+/* key_secretkey_is_set() returns 1 if the keyserver has a secret key
+ * stored for the caller's effective uid; it returns 0 otherwise
+ *
+ * N.B.:  The KEY_NET_GET key call is undocumented.  Applications shouldn't
+ * be using it, because it allows them to get the user's secret key.
+ */
+
+int
+key_secretkey_is_set(void)
+{
+	struct key_netstres 	kres;
+
+	memset((void*)&kres, 0, sizeof (kres));
+	if (key_call((u_long) KEY_NET_GET, (xdrproc_t)xdr_void, NULL,
+			(xdrproc_t)xdr_key_netstres, &kres) &&
+	    (kres.status == KEY_SUCCESS) &&
+	    (kres.key_netstres_u.knet.st_priv_key[0] != 0)) {
+		/* avoid leaving secret key in memory */
+		memset(kres.key_netstres_u.knet.st_priv_key, 0, HEXKEYBYTES);
+		return (1);
+	}
+	return (0);
+}
+
+int
+key_encryptsession_pk(remotename, remotekey, deskey)
+	char *remotename;
+	netobj *remotekey;
+	des_block *deskey;
+{
+	cryptkeyarg2 arg;
+	cryptkeyres res;
+
+	arg.remotename = remotename;
+	arg.remotekey = *remotekey;
+	arg.deskey = *deskey;
+	if (!key_call((u_long)KEY_ENCRYPT_PK, (xdrproc_t)xdr_cryptkeyarg2, &arg,
+			(xdrproc_t)xdr_cryptkeyres, &res)) {
+		return (-1);
+	}
+	if (res.status != KEY_SUCCESS) {
+		debug("encrypt status is nonzero");
+		return (-1);
+	}
+	*deskey = res.cryptkeyres_u.deskey;
+	return (0);
+}
+
+int
+key_decryptsession_pk(remotename, remotekey, deskey)
+	char *remotename;
+	netobj *remotekey;
+	des_block *deskey;
+{
+	cryptkeyarg2 arg;
+	cryptkeyres res;
+
+	arg.remotename = remotename;
+	arg.remotekey = *remotekey;
+	arg.deskey = *deskey;
+	if (!key_call((u_long)KEY_DECRYPT_PK, (xdrproc_t)xdr_cryptkeyarg2, &arg,
+			(xdrproc_t)xdr_cryptkeyres, &res)) {
+		return (-1);
+	}
+	if (res.status != KEY_SUCCESS) {
+		debug("decrypt status is nonzero");
+		return (-1);
+	}
+	*deskey = res.cryptkeyres_u.deskey;
+	return (0);
+}
+
+int
+key_encryptsession(remotename, deskey)
+	const char *remotename;
+	des_block *deskey;
+{
+	cryptkeyarg arg;
+	cryptkeyres res;
+
+	arg.remotename = (char *) remotename;
+	arg.deskey = *deskey;
+	if (!key_call((u_long)KEY_ENCRYPT, (xdrproc_t)xdr_cryptkeyarg, &arg,
+			(xdrproc_t)xdr_cryptkeyres, &res)) {
+		return (-1);
+	}
+	if (res.status != KEY_SUCCESS) {
+		debug("encrypt status is nonzero");
+		return (-1);
+	}
+	*deskey = res.cryptkeyres_u.deskey;
+	return (0);
+}
+
+int
+key_decryptsession(remotename, deskey)
+	const char *remotename;
+	des_block *deskey;
+{
+	cryptkeyarg arg;
+	cryptkeyres res;
+
+	arg.remotename = (char *) remotename;
+	arg.deskey = *deskey;
+	if (!key_call((u_long)KEY_DECRYPT, (xdrproc_t)xdr_cryptkeyarg, &arg,
+			(xdrproc_t)xdr_cryptkeyres, &res)) {
+		return (-1);
+	}
+	if (res.status != KEY_SUCCESS) {
+		debug("decrypt status is nonzero");
+		return (-1);
+	}
+	*deskey = res.cryptkeyres_u.deskey;
+	return (0);
+}
+
+int
+key_gendes(key)
+	des_block *key;
+{
+	if (!key_call((u_long)KEY_GEN, (xdrproc_t)xdr_void, NULL,
+			(xdrproc_t)xdr_des_block, key)) {
+		return (-1);
+	}
+	return (0);
+}
+
+int
+key_setnet(arg)
+struct key_netstarg *arg;
+{
+	keystatus status;
+
+
+	if (!key_call((u_long) KEY_NET_PUT, (xdrproc_t)xdr_key_netstarg, arg,
+			(xdrproc_t)xdr_keystatus, &status)){
+		return (-1);
+	}
+
+	if (status != KEY_SUCCESS) {
+		debug("key_setnet status is nonzero");
+		return (-1);
+	}
+	return (1);
+}
+
+
+int
+key_get_conv(pkey, deskey)
+	char *pkey;
+	des_block *deskey;
+{
+	cryptkeyres res;
+
+	if (!key_call((u_long) KEY_GET_CONV, (xdrproc_t)xdr_keybuf, pkey,
+			(xdrproc_t)xdr_cryptkeyres, &res)) {
+		return (-1);
+	}
+	if (res.status != KEY_SUCCESS) {
+		debug("get_conv status is nonzero");
+		return (-1);
+	}
+	*deskey = res.cryptkeyres_u.deskey;
+	return (0);
+}
+
+struct  key_call_private {
+	CLIENT	*client;	/* Client handle */
+	pid_t	pid;		/* process-id at moment of creation */
+	uid_t	uid;		/* user-id at last authorization */
+};
+static struct key_call_private *key_call_private_main = NULL;
+static thread_key_t key_call_key;
+static once_t key_call_once = ONCE_INITIALIZER;
+static int key_call_key_error;
+
+static void
+key_call_destroy(void *vp)
+{
+	struct key_call_private *kcp = (struct key_call_private *)vp;
+
+	if (kcp) {
+		if (kcp->client)
+			clnt_destroy(kcp->client);
+		free(kcp);
+	}
+}
+
+static void
+key_call_init(void)
+{
+
+	key_call_key_error = thr_keycreate(&key_call_key, key_call_destroy);
+}
+
+/*
+ * Keep the handle cached.  This call may be made quite often.
+ */
+static CLIENT *
+getkeyserv_handle(vers)
+int	vers;
+{
+	void *localhandle;
+	struct netconfig *nconf;
+	struct netconfig *tpconf;
+	struct key_call_private *kcp;
+	struct timeval wait_time;
+	struct utsname u;
+	int main_thread;
+	int fd;
+
+#define	TOTAL_TIMEOUT	30	/* total timeout talking to keyserver */
+#define	TOTAL_TRIES	5	/* Number of tries */
+
+	if ((main_thread = thr_main())) {
+		kcp = key_call_private_main;
+	} else {
+		if (thr_once(&key_call_once, key_call_init) != 0 ||
+		    key_call_key_error != 0)
+			return ((CLIENT *) NULL);
+		kcp = (struct key_call_private *)thr_getspecific(key_call_key);
+	}	
+	if (kcp == (struct key_call_private *)NULL) {
+		kcp = (struct key_call_private *)malloc(sizeof (*kcp));
+		if (kcp == (struct key_call_private *)NULL) {
+			return ((CLIENT *) NULL);
+		}
+                if (main_thread)
+                        key_call_private_main = kcp;
+                else
+                        thr_setspecific(key_call_key, (void *) kcp);
+		kcp->client = NULL;
+	}
+
+	/* if pid has changed, destroy client and rebuild */
+	if (kcp->client != NULL && kcp->pid != getpid()) {
+		clnt_destroy(kcp->client);
+		kcp->client = NULL;
+	}
+
+	if (kcp->client != NULL) {
+		/* if uid has changed, build client handle again */
+		if (kcp->uid != geteuid()) {
+			kcp->uid = geteuid();
+			auth_destroy(kcp->client->cl_auth);
+			kcp->client->cl_auth =
+				authsys_create("", kcp->uid, 0, 0, NULL);
+			if (kcp->client->cl_auth == NULL) {
+				clnt_destroy(kcp->client);
+				kcp->client = NULL;
+				return ((CLIENT *) NULL);
+			}
+		}
+		/* Change the version number to the new one */
+		clnt_control(kcp->client, CLSET_VERS, (void *)&vers);
+		return (kcp->client);
+	}
+	if (!(localhandle = setnetconfig())) {
+		return ((CLIENT *) NULL);
+	}
+        tpconf = NULL;
+#if defined(__FreeBSD__)
+	if (uname(&u) == -1)
+#else
+#if defined(i386)
+	if (_nuname(&u) == -1)
+#elif defined(sparc)
+	if (_uname(&u) == -1)
+#else
+#error Unknown architecture!
+#endif
+#endif
+	{
+		endnetconfig(localhandle);
+		return ((CLIENT *) NULL);
+        }
+	while ((nconf = getnetconfig(localhandle)) != NULL) {
+		if (strcmp(nconf->nc_protofmly, NC_LOOPBACK) == 0) {
+			/*
+			 * We use COTS_ORD here so that the caller can
+			 * find out immediately if the server is dead.
+			 */
+			if (nconf->nc_semantics == NC_TPI_COTS_ORD) {
+				kcp->client = clnt_tp_create(u.nodename,
+					KEY_PROG, vers, nconf);
+				if (kcp->client)
+					break;
+			} else {
+				tpconf = nconf;
+			}
+		}
+	}
+	if ((kcp->client == (CLIENT *) NULL) && (tpconf))
+		/* Now, try the CLTS or COTS loopback transport */
+		kcp->client = clnt_tp_create(u.nodename,
+			KEY_PROG, vers, tpconf);
+	endnetconfig(localhandle);
+
+	if (kcp->client == (CLIENT *) NULL) {
+		return ((CLIENT *) NULL);
+        }
+	kcp->uid = geteuid();
+	kcp->pid = getpid();
+	kcp->client->cl_auth = authsys_create("", kcp->uid, 0, 0, NULL);
+	if (kcp->client->cl_auth == NULL) {
+		clnt_destroy(kcp->client);
+		kcp->client = NULL;
+		return ((CLIENT *) NULL);
+	}
+
+	wait_time.tv_sec = TOTAL_TIMEOUT/TOTAL_TRIES;
+	wait_time.tv_usec = 0;
+	(void) clnt_control(kcp->client, CLSET_RETRY_TIMEOUT,
+		(char *)&wait_time);
+	if (clnt_control(kcp->client, CLGET_FD, (char *)&fd))
+		_fcntl(fd, F_SETFD, 1);	/* make it "close on exec" */
+
+	return (kcp->client);
+}
+
+/* returns  0 on failure, 1 on success */
+
+static int
+key_call(proc, xdr_arg, arg, xdr_rslt, rslt)
+	u_long proc;
+	xdrproc_t xdr_arg;
+	void *arg;
+	xdrproc_t xdr_rslt;
+	void *rslt;
+{
+	CLIENT *clnt;
+	struct timeval wait_time;
+
+	if (proc == KEY_ENCRYPT_PK && __key_encryptsession_pk_LOCAL) {
+		cryptkeyres *res;
+		res = (*__key_encryptsession_pk_LOCAL)(geteuid(), arg);
+		*(cryptkeyres*)rslt = *res;
+		return (1);
+	} else if (proc == KEY_DECRYPT_PK && __key_decryptsession_pk_LOCAL) {
+		cryptkeyres *res;
+		res = (*__key_decryptsession_pk_LOCAL)(geteuid(), arg);
+		*(cryptkeyres*)rslt = *res;
+		return (1);
+	} else if (proc == KEY_GEN && __key_gendes_LOCAL) {
+		des_block *res;
+		res = (*__key_gendes_LOCAL)(geteuid(), 0);
+		*(des_block*)rslt = *res;
+		return (1);
+	}
+
+	if ((proc == KEY_ENCRYPT_PK) || (proc == KEY_DECRYPT_PK) ||
+	    (proc == KEY_NET_GET) || (proc == KEY_NET_PUT) ||
+	    (proc == KEY_GET_CONV))
+		clnt = getkeyserv_handle(2); /* talk to version 2 */
+	else
+		clnt = getkeyserv_handle(1); /* talk to version 1 */
+
+	if (clnt == NULL) {
+		return (0);
+	}
+
+	wait_time.tv_sec = TOTAL_TIMEOUT;
+	wait_time.tv_usec = 0;
+
+	if (clnt_call(clnt, proc, xdr_arg, arg, xdr_rslt, rslt,
+		wait_time) == RPC_SUCCESS) {
+		return (1);
+	} else {
+		return (0);
+	}
+}
Index: freebsd/lib/libc/rpc/key_prot_xdr.c
===================================================================
--- freebsd/lib/libc/rpc/key_prot_xdr.c	(revision 60b1d40751c8b3235b7ccbf3bb6ad0c562562f01)
+++ freebsd/lib/libc/rpc/key_prot_xdr.c	(revision 60b1d40751c8b3235b7ccbf3bb6ad0c562562f01)
@@ -0,0 +1,179 @@
+#include <machine/rtems-bsd-user-space.h>
+
+/*
+ * Please do not edit this file.
+ * It was generated using rpcgen.
+ */
+
+#include "namespace.h"
+#include <rpc/key_prot.h>
+#include "un-namespace.h"
+/*-
+ * Copyright (c) 2009, Sun Microsystems, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions are met:
+ * - Redistributions of source code must retain the above copyright notice, 
+ *   this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice, 
+ *   this list of conditions and the following disclaimer in the documentation 
+ *   and/or other materials provided with the distribution.
+ * - Neither the name of Sun Microsystems, Inc. nor the names of its 
+ *   contributors may be used to endorse or promote products derived 
+ *   from this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+/* Copyright (c)  1990, 1991 Sun Microsystems, Inc. */
+
+/* #pragma ident	"@(#)key_prot.x	1.7	94/04/29 SMI" */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/* 
+ * Compiled from key_prot.x using rpcgen.
+ * DO NOT EDIT THIS FILE!
+ * This is NOT source code!
+ */
+
+bool_t
+xdr_keystatus(register XDR *xdrs, keystatus *objp)
+{
+
+	if (!xdr_enum(xdrs, (enum_t *)objp))
+		return (FALSE);
+	return (TRUE);
+}
+
+bool_t
+xdr_keybuf(register XDR *xdrs, keybuf objp)
+{
+
+	if (!xdr_opaque(xdrs, objp, HEXKEYBYTES))
+		return (FALSE);
+	return (TRUE);
+}
+
+bool_t
+xdr_netnamestr(register XDR *xdrs, netnamestr *objp)
+{
+
+	if (!xdr_string(xdrs, objp, MAXNETNAMELEN))
+		return (FALSE);
+	return (TRUE);
+}
+
+bool_t
+xdr_cryptkeyarg(register XDR *xdrs, cryptkeyarg *objp)
+{
+
+	if (!xdr_netnamestr(xdrs, &objp->remotename))
+		return (FALSE);
+	if (!xdr_des_block(xdrs, &objp->deskey))
+		return (FALSE);
+	return (TRUE);
+}
+
+bool_t
+xdr_cryptkeyarg2(register XDR *xdrs, cryptkeyarg2 *objp)
+{
+
+	if (!xdr_netnamestr(xdrs, &objp->remotename))
+		return (FALSE);
+	if (!xdr_netobj(xdrs, &objp->remotekey))
+		return (FALSE);
+	if (!xdr_des_block(xdrs, &objp->deskey))
+		return (FALSE);
+	return (TRUE);
+}
+
+bool_t
+xdr_cryptkeyres(register XDR *xdrs, cryptkeyres *objp)
+{
+
+	if (!xdr_keystatus(xdrs, &objp->status))
+		return (FALSE);
+	switch (objp->status) {
+	case KEY_SUCCESS:
+		if (!xdr_des_block(xdrs, &objp->cryptkeyres_u.deskey))
+			return (FALSE);
+		break;
+	default:
+		break;
+	}
+	return (TRUE);
+}
+
+bool_t
+xdr_unixcred(register XDR *xdrs, unixcred *objp)
+{
+	u_int **pgids_val;
+
+	if (!xdr_u_int(xdrs, &objp->uid))
+		return (FALSE);
+	if (!xdr_u_int(xdrs, &objp->gid))
+		return (FALSE);
+	pgids_val = &objp->gids.gids_val;
+	if (!xdr_array(xdrs, (char **) pgids_val, (u_int *) &objp->gids.gids_len, MAXGIDS,
+		sizeof (u_int), (xdrproc_t) xdr_u_int))
+		return (FALSE);
+	return (TRUE);
+}
+
+bool_t
+xdr_getcredres(register XDR *xdrs, getcredres *objp)
+{
+
+	if (!xdr_keystatus(xdrs, &objp->status))
+		return (FALSE);
+	switch (objp->status) {
+	case KEY_SUCCESS:
+		if (!xdr_unixcred(xdrs, &objp->getcredres_u.cred))
+			return (FALSE);
+		break;
+	default:
+		break;
+	}
+	return (TRUE);
+}
+
+bool_t
+xdr_key_netstarg(register XDR *xdrs, key_netstarg *objp)
+{
+
+	if (!xdr_keybuf(xdrs, objp->st_priv_key))
+		return (FALSE);
+	if (!xdr_keybuf(xdrs, objp->st_pub_key))
+		return (FALSE);
+	if (!xdr_netnamestr(xdrs, &objp->st_netname))
+		return (FALSE);
+	return (TRUE);
+}
+
+bool_t
+xdr_key_netstres(register XDR *xdrs, key_netstres *objp)
+{
+
+	if (!xdr_keystatus(xdrs, &objp->status))
+		return (FALSE);
+	switch (objp->status) {
+	case KEY_SUCCESS:
+		if (!xdr_key_netstarg(xdrs, &objp->key_netstres_u.knet))
+			return (FALSE);
+		break;
+	default:
+		break;
+	}
+	return (TRUE);
+}
Index: freebsd/lib/libc/rpc/mt_misc.c
===================================================================
--- freebsd/lib/libc/rpc/mt_misc.c	(revision 60b1d40751c8b3235b7ccbf3bb6ad0c562562f01)
+++ freebsd/lib/libc/rpc/mt_misc.c	(revision 60b1d40751c8b3235b7ccbf3bb6ad0c562562f01)
@@ -0,0 +1,119 @@
+#include <machine/rtems-bsd-user-space.h>
+
+/*	$NetBSD: mt_misc.c,v 1.1 2000/06/02 23:11:11 fvdl Exp $	*/
+
+/* #pragma ident	"@(#)mt_misc.c	1.24	93/04/29 SMI" */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include "reentrant.h"
+#include <rpc/rpc.h>
+#include <sys/time.h>
+#include <stdlib.h>
+#include <string.h>
+#include "un-namespace.h"
+#include "mt_misc.h"
+
+/* Take these objects out of the application namespace. */
+#define	svc_lock		__svc_lock
+#define	svc_fd_lock		__svc_fd_lock
+#define	rpcbaddr_cache_lock	__rpcbaddr_cache_lock
+#define	authdes_ops_lock	__authdes_ops_lock
+#define	authnone_lock		__authnone_lock
+#define	authsvc_lock		__authsvc_lock
+#define	clnt_fd_lock		__clnt_fd_lock
+#define	clntraw_lock		__clntraw_lock
+#define	dupreq_lock		__dupreq_lock
+#define	loopnconf_lock		__loopnconf_lock
+#define	ops_lock		__ops_lock
+#define	proglst_lock		__proglst_lock
+#define	rpcsoc_lock		__rpcsoc_lock
+#define	svcraw_lock		__svcraw_lock
+#define	xprtlist_lock		__xprtlist_lock
+
+/* protects the services list (svc.c) */
+pthread_rwlock_t	svc_lock = PTHREAD_RWLOCK_INITIALIZER;
+
+/* protects svc_fdset and the xports[] array */
+pthread_rwlock_t	svc_fd_lock = PTHREAD_RWLOCK_INITIALIZER;
+
+/* protects the RPCBIND address cache */
+pthread_rwlock_t	rpcbaddr_cache_lock = PTHREAD_RWLOCK_INITIALIZER;
+
+/* serializes authdes ops initializations */
+pthread_mutex_t authdes_ops_lock = PTHREAD_MUTEX_INITIALIZER;
+
+/* protects des stats list */
+pthread_mutex_t svcauthdesstats_lock = PTHREAD_MUTEX_INITIALIZER;
+
+/* auth_none.c serialization */
+pthread_mutex_t	authnone_lock = PTHREAD_MUTEX_INITIALIZER;
+
+/* protects the Auths list (svc_auth.c) */
+pthread_mutex_t	authsvc_lock = PTHREAD_MUTEX_INITIALIZER;
+
+/* protects client-side fd lock array */
+pthread_mutex_t	clnt_fd_lock = PTHREAD_MUTEX_INITIALIZER;
+
+/* clnt_raw.c serialization */
+pthread_mutex_t	clntraw_lock = PTHREAD_MUTEX_INITIALIZER;
+
+/* dupreq variables (svc_dg.c) */
+pthread_mutex_t	dupreq_lock = PTHREAD_MUTEX_INITIALIZER;
+
+/* loopnconf (rpcb_clnt.c) */
+pthread_mutex_t	loopnconf_lock = PTHREAD_MUTEX_INITIALIZER;
+
+/* serializes ops initializations */
+pthread_mutex_t	ops_lock = PTHREAD_MUTEX_INITIALIZER;
+
+/* protects proglst list (svc_simple.c) */
+pthread_mutex_t	proglst_lock = PTHREAD_MUTEX_INITIALIZER;
+
+/* serializes clnt_com_create() (rpc_soc.c) */
+pthread_mutex_t	rpcsoc_lock = PTHREAD_MUTEX_INITIALIZER;
+
+/* svc_raw.c serialization */
+pthread_mutex_t	svcraw_lock = PTHREAD_MUTEX_INITIALIZER;
+
+/* xprtlist (svc_generic.c) */
+pthread_mutex_t	xprtlist_lock = PTHREAD_MUTEX_INITIALIZER;
+
+#undef	rpc_createerr
+
+struct rpc_createerr rpc_createerr;
+static thread_key_t rce_key;
+static once_t rce_once = ONCE_INITIALIZER;
+static int rce_key_error;
+
+static void
+rce_key_init(void)
+{
+
+	rce_key_error = thr_keycreate(&rce_key, free);
+}
+
+struct rpc_createerr *
+__rpc_createerr()
+{
+	struct rpc_createerr *rce_addr = 0;
+
+	if (thr_main())
+		return (&rpc_createerr);
+	if (thr_once(&rce_once, rce_key_init) != 0 || rce_key_error != 0)
+		return (&rpc_createerr);
+	rce_addr = (struct rpc_createerr *)thr_getspecific(rce_key);
+	if (!rce_addr) {
+		rce_addr = (struct rpc_createerr *)
+			malloc(sizeof (struct rpc_createerr));
+		if (thr_setspecific(rce_key, (void *) rce_addr) != 0) {
+			if (rce_addr)
+				free(rce_addr);
+			return (&rpc_createerr);
+		}
+		memset(rce_addr, 0, sizeof (struct rpc_createerr));
+		return (rce_addr);
+	}
+	return (rce_addr);
+}
Index: freebsd/lib/libc/rpc/mt_misc.h
===================================================================
--- freebsd/lib/libc/rpc/mt_misc.h	(revision 60b1d40751c8b3235b7ccbf3bb6ad0c562562f01)
+++ freebsd/lib/libc/rpc/mt_misc.h	(revision 60b1d40751c8b3235b7ccbf3bb6ad0c562562f01)
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2006 The FreeBSD Project. All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+#ifndef _MT_MISC_H
+#define	_MT_MISC_H
+
+/* Take these locks out of the application namespace. */
+#define	svc_lock		__svc_lock
+#define	svc_fd_lock		__svc_fd_lock
+#define	rpcbaddr_cache_lock	__rpcbaddr_cache_lock
+#define	authdes_ops_lock	__authdes_ops_lock
+#define	authnone_lock		__authnone_lock
+#define	authsvc_lock		__authsvc_lock
+#define	clnt_fd_lock		__clnt_fd_lock
+#define	clntraw_lock		__clntraw_lock
+#define	dupreq_lock		__dupreq_lock
+#define	loopnconf_lock		__loopnconf_lock
+#define	ops_lock		__ops_lock
+#define	proglst_lock		__proglst_lock
+#define	rpcsoc_lock		__rpcsoc_lock
+#define	svcraw_lock		__svcraw_lock
+#define	xprtlist_lock		__xprtlist_lock
+
+extern pthread_rwlock_t	svc_lock;
+extern pthread_rwlock_t	svc_fd_lock;
+extern pthread_rwlock_t	rpcbaddr_cache_lock;
+extern pthread_mutex_t	authdes_ops_lock;
+extern pthread_mutex_t	svcauthdesstats_lock;
+extern pthread_mutex_t	authnone_lock;
+extern pthread_mutex_t	authsvc_lock;
+extern pthread_mutex_t	clnt_fd_lock;
+extern pthread_mutex_t	clntraw_lock;
+extern pthread_mutex_t	dupreq_lock;
+extern pthread_mutex_t	loopnconf_lock;
+extern pthread_mutex_t	ops_lock;
+extern pthread_mutex_t	proglst_lock;
+extern pthread_mutex_t	rpcsoc_lock;
+extern pthread_mutex_t	svcraw_lock;
+extern pthread_mutex_t	tsd_lock;
+extern pthread_mutex_t	xprtlist_lock;
+
+#endif
Index: freebsd/lib/libc/rpc/netname.c
===================================================================
--- freebsd/lib/libc/rpc/netname.c	(revision 60b1d40751c8b3235b7ccbf3bb6ad0c562562f01)
+++ freebsd/lib/libc/rpc/netname.c	(revision 60b1d40751c8b3235b7ccbf3bb6ad0c562562f01)
@@ -0,0 +1,150 @@
+#include <machine/rtems-bsd-user-space.h>
+
+/*-
+ * Copyright (c) 2009, Sun Microsystems, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions are met:
+ * - Redistributions of source code must retain the above copyright notice, 
+ *   this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice, 
+ *   this list of conditions and the following disclaimer in the documentation 
+ *   and/or other materials provided with the distribution.
+ * - Neither the name of Sun Microsystems, Inc. nor the names of its 
+ *   contributors may be used to endorse or promote products derived 
+ *   from this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)netname.c 1.8 91/03/11 Copyr 1986 Sun Micro";
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * netname utility routines
+ * convert from unix names to network names and vice-versa
+ * This module is operating system dependent!
+ * What we define here will work with any unix system that has adopted
+ * the sun NIS domain architecture.
+ */
+
+#include "namespace.h"
+#include <rtems/bsd/sys/param.h>
+#include <rpc/rpc.h>
+#include <rpc/rpc_com.h>
+#ifdef YP
+#include <rpcsvc/yp_prot.h>
+#include <rpcsvc/ypclnt.h>
+#endif
+#include <ctype.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "un-namespace.h"
+
+#ifndef MAXHOSTNAMELEN
+#define MAXHOSTNAMELEN 256
+#endif
+
+#define TYPE_BIT(type)  (sizeof (type) * CHAR_BIT)
+
+#define TYPE_SIGNED(type) (((type) -1) < 0)
+
+/*
+** 302 / 1000 is log10(2.0) rounded up.
+** Subtract one for the sign bit if the type is signed;
+** add one for integer division truncation;
+** add one more for a minus sign if the type is signed.
+*/
+#define INT_STRLEN_MAXIMUM(type) \
+    ((TYPE_BIT(type) - TYPE_SIGNED(type)) * 302 / 1000 + 1 + TYPE_SIGNED(type))
+
+static char *OPSYS = "unix";
+
+/*
+ * Figure out my fully qualified network name
+ */
+int
+getnetname(name)
+	char name[MAXNETNAMELEN+1];
+{
+	uid_t uid;
+
+	uid = geteuid();
+	if (uid == 0) {
+		return (host2netname(name, (char *) NULL, (char *) NULL));
+	} else {
+		return (user2netname(name, uid, (char *) NULL));
+	}
+}
+
+
+/*
+ * Convert unix cred to network-name
+ */
+int
+user2netname(netname, uid, domain)
+	char netname[MAXNETNAMELEN + 1];
+	const uid_t uid;
+	const char *domain;
+{
+	char *dfltdom;
+
+	if (domain == NULL) {
+		if (__rpc_get_default_domain(&dfltdom) != 0) {
+			return (0);
+		}
+		domain = dfltdom;
+	}
+	if (strlen(domain) + 1 + INT_STRLEN_MAXIMUM(u_long) + 1 + strlen(OPSYS) > MAXNETNAMELEN) {
+		return (0);
+	}
+	(void) sprintf(netname, "%s.%ld@%s", OPSYS, (u_long)uid, domain);	
+	return (1);
+}
+
+
+/*
+ * Convert host to network-name
+ */
+int
+host2netname(netname, host, domain)
+	char netname[MAXNETNAMELEN + 1];
+	const char *host;
+	const char *domain;
+{
+	char *dfltdom;
+	char hostname[MAXHOSTNAMELEN+1];
+
+	if (domain == NULL) {
+		if (__rpc_get_default_domain(&dfltdom) != 0) {
+			return (0);
+		}
+		domain = dfltdom;
+	}
+	if (host == NULL) {
+		(void) gethostname(hostname, sizeof(hostname));
+		host = hostname;
+	}
+	if (strlen(domain) + 1 + strlen(host) + 1 + strlen(OPSYS) > MAXNETNAMELEN) {
+		return (0);
+	} 
+	(void) sprintf(netname, "%s.%s@%s", OPSYS, host, domain);
+	return (1);
+}
Index: freebsd/lib/libc/rpc/netnamer.c
===================================================================
--- freebsd/lib/libc/rpc/netnamer.c	(revision 60b1d40751c8b3235b7ccbf3bb6ad0c562562f01)
+++ freebsd/lib/libc/rpc/netnamer.c	(revision 60b1d40751c8b3235b7ccbf3bb6ad0c562562f01)
@@ -0,0 +1,331 @@
+#include <machine/rtems-bsd-user-space.h>
+
+/*-
+ * Copyright (c) 2009, Sun Microsystems, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions are met:
+ * - Redistributions of source code must retain the above copyright notice, 
+ *   this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice, 
+ *   this list of conditions and the following disclaimer in the documentation 
+ *   and/or other materials provided with the distribution.
+ * - Neither the name of Sun Microsystems, Inc. nor the names of its 
+ *   contributors may be used to endorse or promote products derived 
+ *   from this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)netnamer.c 1.13 91/03/11 Copyr 1986 Sun Micro";
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * netname utility routines convert from unix names to network names and
+ * vice-versa This module is operating system dependent! What we define here
+ * will work with any unix system that has adopted the sun NIS domain
+ * architecture.
+ */
+#include "namespace.h"
+#include <rtems/bsd/sys/param.h>
+#include <rpc/rpc.h>
+#include <rpc/rpc_com.h>
+#ifdef YP
+#include <rpcsvc/yp_prot.h>
+#include <rpcsvc/ypclnt.h>
+#endif
+#include <ctype.h>
+#include <stdio.h>
+#include <grp.h>
+#include <pwd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include "un-namespace.h"
+
+static char    *OPSYS = "unix";
+#ifdef YP
+static char    *NETID = "netid.byname";
+#endif
+static char    *NETIDFILE = "/etc/netid";
+
+static int getnetid( char *, char * );
+static int _getgroups( char *, gid_t * );
+
+/*
+ * Convert network-name into unix credential
+ */
+int
+netname2user(netname, uidp, gidp, gidlenp, gidlist)
+	char            netname[MAXNETNAMELEN + 1];
+	uid_t            *uidp;
+	gid_t            *gidp;
+	int            *gidlenp;
+	gid_t	       *gidlist;
+{
+	char           *p;
+	int             gidlen;
+	uid_t           uid;
+	long		luid;
+	struct passwd  *pwd;
+	char            val[1024];
+	char           *val1, *val2;
+	char           *domain;
+	int             vallen;
+	int             err;
+
+	if (getnetid(netname, val)) {
+		char *res = val;
+
+		p = strsep(&res, ":");
+		if (p == NULL)
+			return (0);
+		*uidp = (uid_t) atol(p);
+		p = strsep(&res, "\n,");
+		if (p == NULL) {
+			return (0);
+		}
+		*gidp = (gid_t) atol(p);
+		for (gidlen = 0; gidlen < NGRPS; gidlen++) {
+			p = strsep(&res, "\n,");
+			if (p == NULL)
+				break;
+			gidlist[gidlen] = (gid_t) atol(p);
+		}
+		*gidlenp = gidlen;
+
+		return (1);
+	}
+	val1 = strchr(netname, '.');
+	if (val1 == NULL)
+		return (0);
+	if (strncmp(netname, OPSYS, (val1-netname)))
+		return (0);
+	val1++;
+	val2 = strchr(val1, '@');
+	if (val2 == NULL)
+		return (0);
+	vallen = val2 - val1;
+	if (vallen > (1024 - 1))
+		vallen = 1024 - 1;
+	(void) strncpy(val, val1, 1024);
+	val[vallen] = 0;
+
+	err = __rpc_get_default_domain(&domain);	/* change to rpc */
+	if (err)
+		return (0);
+
+	if (strcmp(val2 + 1, domain))
+		return (0);	/* wrong domain */
+
+	if (sscanf(val, "%ld", &luid) != 1)
+		return (0);
+	uid = luid;
+
+	/* use initgroups method */
+	pwd = getpwuid(uid);
+	if (pwd == NULL)
+		return (0);
+	*uidp = pwd->pw_uid;
+	*gidp = pwd->pw_gid;
+	*gidlenp = _getgroups(pwd->pw_name, gidlist);
+	return (1);
+}
+
+/*
+ * initgroups
+ */
+
+static int
+_getgroups(uname, groups)
+	char           *uname;
+	gid_t          groups[NGRPS];
+{
+	gid_t           ngroups = 0;
+	struct group *grp;
+	int    i;
+	int    j;
+	int             filter;
+
+	setgrent();
+	while ((grp = getgrent())) {
+		for (i = 0; grp->gr_mem[i]; i++)
+			if (!strcmp(grp->gr_mem[i], uname)) {
+				if (ngroups == NGRPS) {
+#ifdef DEBUG
+					fprintf(stderr,
+				"initgroups: %s is in too many groups\n", uname);
+#endif
+					goto toomany;
+				}
+				/* filter out duplicate group entries */
+				filter = 0;
+				for (j = 0; j < ngroups; j++)
+					if (groups[j] == grp->gr_gid) {
+						filter++;
+						break;
+					}
+				if (!filter)
+					groups[ngroups++] = grp->gr_gid;
+			}
+	}
+toomany:
+	endgrent();
+	return (ngroups);
+}
+
+/*
+ * Convert network-name to hostname
+ */
+int
+netname2host(netname, hostname, hostlen)
+	char            netname[MAXNETNAMELEN + 1];
+	char           *hostname;
+	int             hostlen;
+{
+	int             err;
+	char            valbuf[1024];
+	char           *val;
+	char           *val2;
+	int             vallen;
+	char           *domain;
+
+	if (getnetid(netname, valbuf)) {
+		val = valbuf;
+		if ((*val == '0') && (val[1] == ':')) {
+			(void) strncpy(hostname, val + 2, hostlen);
+			return (1);
+		}
+	}
+	val = strchr(netname, '.');
+	if (val == NULL)
+		return (0);
+	if (strncmp(netname, OPSYS, (val - netname)))
+		return (0);
+	val++;
+	val2 = strchr(val, '@');
+	if (val2 == NULL)
+		return (0);
+	vallen = val2 - val;
+	if (vallen > (hostlen - 1))
+		vallen = hostlen - 1;
+	(void) strncpy(hostname, val, vallen);
+	hostname[vallen] = 0;
+
+	err = __rpc_get_default_domain(&domain);	/* change to rpc */
+	if (err)
+		return (0);
+
+	if (strcmp(val2 + 1, domain))
+		return (0);	/* wrong domain */
+	else
+		return (1);
+}
+
+/*
+ * reads the file /etc/netid looking for a + to optionally go to the
+ * network information service.
+ */
+int
+getnetid(key, ret)
+	char           *key, *ret;
+{
+	char            buf[1024];	/* big enough */
+	char           *res;
+	char           *mkey;
+	char           *mval;
+	FILE           *fd;
+#ifdef YP
+	char           *domain;
+	int             err;
+	char           *lookup;
+	int             len;
+#endif
+
+	fd = fopen(NETIDFILE, "r");
+	if (fd == NULL) {
+#ifdef YP
+		res = "+";
+		goto getnetidyp;
+#else
+		return (0);
+#endif
+	}
+	for (;;) {
+		if (fd == NULL)
+			return (0);	/* getnetidyp brings us here */
+		res = fgets(buf, sizeof(buf), fd);
+		if (res == NULL) {
+			fclose(fd);
+			return (0);
+		}
+		if (res[0] == '#')
+			continue;
+		else if (res[0] == '+') {
+#ifdef YP
+	getnetidyp:
+			err = yp_get_default_domain(&domain);
+			if (err) {
+				continue;
+			}
+			lookup = NULL;
+			err = yp_match(domain, NETID, key,
+				strlen(key), &lookup, &len);
+			if (err) {
+#ifdef DEBUG
+				fprintf(stderr, "match failed error %d\n", err);
+#endif
+				continue;
+			}
+			lookup[len] = 0;
+			strcpy(ret, lookup);
+			free(lookup);
+			if (fd != NULL)
+				fclose(fd);
+			return (2);
+#else	/* YP */
+#ifdef DEBUG
+			fprintf(stderr,
+"Bad record in %s '+' -- NIS not supported in this library copy\n",
+				NETIDFILE);
+#endif
+			continue;
+#endif	/* YP */
+		} else {
+			mkey = strsep(&res, "\t ");
+			if (mkey == NULL) {
+				fprintf(stderr,
+		"Bad record in %s -- %s", NETIDFILE, buf);
+				continue;
+			}
+			do {
+				mval = strsep(&res, " \t#\n");
+			} while (mval != NULL && !*mval);
+			if (mval == NULL) {
+				fprintf(stderr,
+		"Bad record in %s val problem - %s", NETIDFILE, buf);
+				continue;
+			}
+			if (strcmp(mkey, key) == 0) {
+				strcpy(ret, mval);
+				fclose(fd);
+				return (1);
+
+			}
+		}
+	}
+}
Index: freebsd/lib/libc/rpc/pmap_clnt.c
===================================================================
--- freebsd/lib/libc/rpc/pmap_clnt.c	(revision 60b1d40751c8b3235b7ccbf3bb6ad0c562562f01)
+++ freebsd/lib/libc/rpc/pmap_clnt.c	(revision 60b1d40751c8b3235b7ccbf3bb6ad0c562562f01)
@@ -0,0 +1,121 @@
+#include <machine/rtems-bsd-user-space.h>
+
+/*	$NetBSD: pmap_clnt.c,v 1.16 2000/07/06 03:10:34 christos Exp $	*/
+
+/*-
+ * Copyright (c) 2009, Sun Microsystems, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions are met:
+ * - Redistributions of source code must retain the above copyright notice, 
+ *   this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice, 
+ *   this list of conditions and the following disclaimer in the documentation 
+ *   and/or other materials provided with the distribution.
+ * - Neither the name of Sun Microsystems, Inc. nor the names of its 
+ *   contributors may be used to endorse or promote products derived 
+ *   from this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char *sccsid2 = "@(#)pmap_clnt.c 1.37 87/08/11 Copyr 1984 Sun Micro";
+static char *sccsid = "@(#)pmap_clnt.c	2.2 88/08/01 4.0 RPCSRC";
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * pmap_clnt.c
+ * Client interface to pmap rpc service.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#include "namespace.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include <rpc/rpc.h>
+#include <rpc/pmap_prot.h>
+#include <rpc/pmap_clnt.h>
+#include <rpc/nettype.h>
+#include <netinet/in.h>
+#include "un-namespace.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "rpc_com.h"
+
+bool_t
+pmap_set(u_long program, u_long version, int protocol, int port)
+{
+	bool_t rslt;
+	struct netbuf *na;
+	struct netconfig *nconf;
+	char buf[32];
+
+	if ((protocol != IPPROTO_UDP) && (protocol != IPPROTO_TCP)) {
+		return (FALSE);
+	}
+	nconf = __rpc_getconfip(protocol == IPPROTO_UDP ? "udp" : "tcp");
+	if (nconf == NULL) {
+		return (FALSE);
+	}
+	snprintf(buf, sizeof buf, "0.0.0.0.%d.%d", 
+	    (((u_int32_t)port) >> 8) & 0xff, port & 0xff);
+	na = uaddr2taddr(nconf, buf);
+	if (na == NULL) {
+		freenetconfigent(nconf);
+		return (FALSE);
+	}
+	rslt = rpcb_set((rpcprog_t)program, (rpcvers_t)version, nconf, na);
+	free(na);
+	freenetconfigent(nconf);
+	return (rslt);
+}
+
+/*
+ * Remove the mapping between program, version and port.
+ * Calls the pmap service remotely to do the un-mapping.
+ */
+bool_t
+pmap_unset(u_long program, u_long version)
+{
+	struct netconfig *nconf;
+	bool_t udp_rslt = FALSE;
+	bool_t tcp_rslt = FALSE;
+
+	nconf = __rpc_getconfip("udp");
+	if (nconf != NULL) {
+		udp_rslt = rpcb_unset((rpcprog_t)program, (rpcvers_t)version,
+		    nconf);
+		freenetconfigent(nconf);
+	}
+	nconf = __rpc_getconfip("tcp");
+	if (nconf != NULL) {
+		tcp_rslt = rpcb_unset((rpcprog_t)program, (rpcvers_t)version,
+		    nconf);
+		freenetconfigent(nconf);
+	}
+	/*
+	 * XXX: The call may still succeed even if only one of the
+	 * calls succeeded.  This was the best that could be
+	 * done for backward compatibility.
+	 */
+	return (tcp_rslt || udp_rslt);
+}
Index: freebsd/lib/libc/rpc/pmap_getmaps.c
===================================================================
--- freebsd/lib/libc/rpc/pmap_getmaps.c	(revision 60b1d40751c8b3235b7ccbf3bb6ad0c562562f01)
+++ freebsd/lib/libc/rpc/pmap_getmaps.c	(revision 60b1d40751c8b3235b7ccbf3bb6ad0c562562f01)
@@ -0,0 +1,101 @@
+#include <machine/rtems-bsd-user-space.h>
+
+/*	$NetBSD: pmap_getmaps.c,v 1.16 2000/07/06 03:10:34 christos Exp $	*/
+
+/*-
+ * Copyright (c) 2009, Sun Microsystems, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions are met:
+ * - Redistributions of source code must retain the above copyright notice, 
+ *   this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice, 
+ *   this list of conditions and the following disclaimer in the documentation 
+ *   and/or other materials provided with the distribution.
+ * - Neither the name of Sun Microsystems, Inc. nor the names of its 
+ *   contributors may be used to endorse or promote products derived 
+ *   from this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char *sccsid2 = "@(#)pmap_getmaps.c 1.10 87/08/11 Copyr 1984 Sun Micro";
+static char *sccsid = "@(#)pmap_getmaps.c	2.2 88/08/01 4.0 RPCSRC";
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * pmap_getmap.c
+ * Client interface to pmap rpc service.
+ * contains pmap_getmaps, which is only tcp service involved
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#include "namespace.h"
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+
+#include <arpa/inet.h>
+#include <net/if.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include <rpc/rpc.h>
+#include <rpc/pmap_prot.h>
+#include <rpc/pmap_clnt.h>
+#include "un-namespace.h"
+
+#define NAMELEN 255
+#define MAX_BROADCAST_SIZE 1400
+
+/*
+ * Get a copy of the current port maps.
+ * Calls the pmap service remotely to do get the maps.
+ */
+struct pmaplist *
+pmap_getmaps(address)
+	 struct sockaddr_in *address;
+{
+	struct pmaplist *head = NULL;
+	int sock = -1;
+	struct timeval minutetimeout;
+	CLIENT *client;
+
+	assert(address != NULL);
+
+	minutetimeout.tv_sec = 60;
+	minutetimeout.tv_usec = 0;
+	address->sin_port = htons(PMAPPORT);
+	client = clnttcp_create(address, PMAPPROG,
+	    PMAPVERS, &sock, 50, 500);
+	if (client != NULL) {
+		if (CLNT_CALL(client, (rpcproc_t)PMAPPROC_DUMP,
+		    (xdrproc_t)xdr_void, NULL,
+		    (xdrproc_t)xdr_pmaplist, &head, minutetimeout) !=
+		    RPC_SUCCESS) {
+			clnt_perror(client, "pmap_getmaps rpc problem");
+		}
+		CLNT_DESTROY(client);
+	}
+	address->sin_port = 0;
+	return (head);
+}
Index: freebsd/lib/libc/rpc/pmap_getport.c
===================================================================
--- freebsd/lib/libc/rpc/pmap_getport.c	(revision 60b1d40751c8b3235b7ccbf3bb6ad0c562562f01)
+++ freebsd/lib/libc/rpc/pmap_getport.c	(revision 60b1d40751c8b3235b7ccbf3bb6ad0c562562f01)
@@ -0,0 +1,105 @@
+#include <machine/rtems-bsd-user-space.h>
+
+/*	$NetBSD: pmap_getport.c,v 1.16 2000/07/06 03:10:34 christos Exp $	*/
+
+/*-
+ * Copyright (c) 2009, Sun Microsystems, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions are met:
+ * - Redistributions of source code must retain the above copyright notice, 
+ *   this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice, 
+ *   this list of conditions and the following disclaimer in the documentation 
+ *   and/or other materials provided with the distribution.
+ * - Neither the name of Sun Microsystems, Inc. nor the names of its 
+ *   contributors may be used to endorse or promote products derived 
+ *   from this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char *sccsid2 = "from: @(#)pmap_getport.c 1.9 87/08/11 Copyr 1984 Sun Micro";
+static char *sccsid = "from: @(#)pmap_getport.c	2.2 88/08/01 4.0 RPCSRC";
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * pmap_getport.c
+ * Client interface to pmap rpc service.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#include "namespace.h"
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <arpa/inet.h>
+#include <net/if.h>
+
+#include <assert.h>
+#include <unistd.h>
+
+#include <rpc/rpc.h>
+#include <rpc/pmap_prot.h>
+#include <rpc/pmap_clnt.h>
+#include "un-namespace.h"
+
+static const struct timeval timeout = { 5, 0 };
+static const struct timeval tottimeout = { 60, 0 };
+
+/*
+ * Find the mapped port for program,version.
+ * Calls the pmap service remotely to do the lookup.
+ * Returns 0 if no map exists.
+ */
+u_short
+pmap_getport(address, program, version, protocol)
+	struct sockaddr_in *address;
+	u_long program;
+	u_long version;
+	u_int protocol;
+{
+	u_short port = 0;
+	int sock = -1;
+	CLIENT *client;
+	struct pmap parms;
+
+	assert(address != NULL);
+
+	address->sin_port = htons(PMAPPORT);
+	client = clntudp_bufcreate(address, PMAPPROG,
+	    PMAPVERS, timeout, &sock, RPCSMALLMSGSIZE, RPCSMALLMSGSIZE);
+	if (client != NULL) {
+		parms.pm_prog = program;
+		parms.pm_vers = version;
+		parms.pm_prot = protocol;
+		parms.pm_port = 0;  /* not needed or used */
+		if (CLNT_CALL(client, (rpcproc_t)PMAPPROC_GETPORT,
+		    (xdrproc_t)xdr_pmap,
+		    &parms, (xdrproc_t)xdr_u_short, &port, tottimeout) !=
+		    RPC_SUCCESS){
+			rpc_createerr.cf_stat = RPC_PMAPFAILURE;
+			clnt_geterr(client, &rpc_createerr.cf_error);
+		} else if (port == 0) {
+			rpc_createerr.cf_stat = RPC_PROGNOTREGISTERED;
+		}
+		CLNT_DESTROY(client);
+	}
+	address->sin_port = 0;
+	return (port);
+}
Index: freebsd/lib/libc/rpc/pmap_prot.c
===================================================================
--- freebsd/lib/libc/rpc/pmap_prot.c	(revision 60b1d40751c8b3235b7ccbf3bb6ad0c562562f01)
+++ freebsd/lib/libc/rpc/pmap_prot.c	(revision 60b1d40751c8b3235b7ccbf3bb6ad0c562562f01)
@@ -0,0 +1,70 @@
+#include <machine/rtems-bsd-user-space.h>
+
+/*	$NetBSD: pmap_prot.c,v 1.10 2000/01/22 22:19:18 mycroft Exp $	*/
+
+/*-
+ * Copyright (c) 2009, Sun Microsystems, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions are met:
+ * - Redistributions of source code must retain the above copyright notice, 
+ *   this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice, 
+ *   this list of conditions and the following disclaimer in the documentation 
+ *   and/or other materials provided with the distribution.
+ * - Neither the name of Sun Microsystems, Inc. nor the names of its 
+ *   contributors may be used to endorse or promote products derived 
+ *   from this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char *sccsid2 = "@(#)pmap_prot.c 1.17 87/08/11 Copyr 1984 Sun Micro";
+static char *sccsid = "@(#)pmap_prot.c	2.1 88/07/29 4.0 RPCSRC";
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * pmap_prot.c
+ * Protocol for the local binder service, or pmap.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#include "namespace.h"
+#include <assert.h>
+
+#include <rpc/types.h>
+#include <rpc/xdr.h>
+#include <rpc/pmap_prot.h>
+#include "un-namespace.h"
+
+
+bool_t
+xdr_pmap(xdrs, regs)
+	XDR *xdrs;
+	struct pmap *regs;
+{
+
+	assert(xdrs != NULL);
+	assert(regs != NULL);
+
+	if (xdr_u_long(xdrs, &regs->pm_prog) &&
+		xdr_u_long(xdrs, &regs->pm_vers) &&
+		xdr_u_long(xdrs, &regs->pm_prot))
+		return (xdr_u_long(xdrs, &regs->pm_port));
+	return (FALSE);
+}
Index: freebsd/lib/libc/rpc/pmap_prot2.c
===================================================================
--- freebsd/lib/libc/rpc/pmap_prot2.c	(revision 60b1d40751c8b3235b7ccbf3bb6ad0c562562f01)
+++ freebsd/lib/libc/rpc/pmap_prot2.c	(revision 60b1d40751c8b3235b7ccbf3bb6ad0c562562f01)
@@ -0,0 +1,144 @@
+#include <machine/rtems-bsd-user-space.h>
+
+/*	$NetBSD: pmap_prot2.c,v 1.14 2000/07/06 03:10:34 christos Exp $	*/
+
+/*-
+ * Copyright (c) 2009, Sun Microsystems, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions are met:
+ * - Redistributions of source code must retain the above copyright notice, 
+ *   this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice, 
+ *   this list of conditions and the following disclaimer in the documentation 
+ *   and/or other materials provided with the distribution.
+ * - Neither the name of Sun Microsystems, Inc. nor the names of its 
+ *   contributors may be used to endorse or promote products derived 
+ *   from this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char *sccsid2 = "@(#)pmap_prot2.c 1.3 87/08/11 Copyr 1984 Sun Micro";
+static char *sccsid = "@(#)pmap_prot2.c	2.1 88/07/29 4.0 RPCSRC";
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * pmap_prot2.c
+ * Protocol for the local binder service, or pmap.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#include "namespace.h"
+#include <assert.h>
+
+#include <rpc/types.h>
+#include <rpc/xdr.h>
+#include <rpc/pmap_prot.h>
+#include "un-namespace.h"
+
+
+/*
+ * What is going on with linked lists? (!)
+ * First recall the link list declaration from pmap_prot.h:
+ *
+ * struct pmaplist {
+ *	struct pmap pml_map;
+ *	struct pmaplist *pml_map;
+ * };
+ *
+ * Compare that declaration with a corresponding xdr declaration that
+ * is (a) pointer-less, and (b) recursive:
+ *
+ * typedef union switch (bool_t) {
+ *
+ *	case TRUE: struct {
+ *		struct pmap;
+ * 		pmaplist_t foo;
+ *	};
+ *
+ *	case FALSE: struct {};
+ * } pmaplist_t;
+ *
+ * Notice that the xdr declaration has no nxt pointer while
+ * the C declaration has no bool_t variable.  The bool_t can be
+ * interpreted as ``more data follows me''; if FALSE then nothing
+ * follows this bool_t; if TRUE then the bool_t is followed by
+ * an actual struct pmap, and then (recursively) by the
+ * xdr union, pamplist_t.
+ *
+ * This could be implemented via the xdr_union primitive, though this
+ * would cause a one recursive call per element in the list.  Rather than do
+ * that we can ``unwind'' the recursion
+ * into a while loop and do the union arms in-place.
+ *
+ * The head of the list is what the C programmer wishes to past around
+ * the net, yet is the data that the pointer points to which is interesting;
+ * this sounds like a job for xdr_reference!
+ */
+bool_t
+xdr_pmaplist(xdrs, rp)
+	XDR *xdrs;
+	struct pmaplist **rp;
+{
+	/*
+	 * more_elements is pre-computed in case the direction is
+	 * XDR_ENCODE or XDR_FREE.  more_elements is overwritten by
+	 * xdr_bool when the direction is XDR_DECODE.
+	 */
+	bool_t more_elements;
+	int freeing;
+	struct pmaplist **next	= NULL; /* pacify gcc */
+
+	assert(xdrs != NULL);
+	assert(rp != NULL);
+
+	freeing = (xdrs->x_op == XDR_FREE);
+
+	for (;;) {
+		more_elements = (bool_t)(*rp != NULL);
+		if (! xdr_bool(xdrs, &more_elements))
+			return (FALSE);
+		if (! more_elements)
+			return (TRUE);  /* we are done */
+		/*
+		 * the unfortunate side effect of non-recursion is that in
+		 * the case of freeing we must remember the next object
+		 * before we free the current object ...
+		 */
+		if (freeing)
+			next = &((*rp)->pml_next); 
+		if (! xdr_reference(xdrs, (caddr_t *)rp,
+		    (u_int)sizeof(struct pmaplist), (xdrproc_t)xdr_pmap))
+			return (FALSE);
+		rp = (freeing) ? next : &((*rp)->pml_next);
+	}
+}
+
+
+/*
+ * xdr_pmaplist_ptr() is specified to take a PMAPLIST *, but is identical in
+ * functionality to xdr_pmaplist().
+ */
+bool_t
+xdr_pmaplist_ptr(xdrs, rp)
+	XDR *xdrs;
+	struct pmaplist *rp;
+{
+	return xdr_pmaplist(xdrs, (struct pmaplist **)(void *)rp);
+}
Index: freebsd/lib/libc/rpc/pmap_rmt.c
===================================================================
--- freebsd/lib/libc/rpc/pmap_rmt.c	(revision 60b1d40751c8b3235b7ccbf3bb6ad0c562562f01)
+++ freebsd/lib/libc/rpc/pmap_rmt.c	(revision 60b1d40751c8b3235b7ccbf3bb6ad0c562562f01)
@@ -0,0 +1,177 @@
+#include <machine/rtems-bsd-user-space.h>
+
+/*	$NetBSD: pmap_rmt.c,v 1.29 2000/07/06 03:10:34 christos Exp $	*/
+
+/*-
+ * Copyright (c) 2009, Sun Microsystems, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions are met:
+ * - Redistributions of source code must retain the above copyright notice, 
+ *   this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice, 
+ *   this list of conditions and the following disclaimer in the documentation 
+ *   and/or other materials provided with the distribution.
+ * - Neither the name of Sun Microsystems, Inc. nor the names of its 
+ *   contributors may be used to endorse or promote products derived 
+ *   from this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char *sccsid2 = "@(#)pmap_rmt.c 1.21 87/08/27 Copyr 1984 Sun Micro";
+static char *sccsid = "@(#)pmap_rmt.c	2.2 88/08/01 4.0 RPCSRC";
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * pmap_rmt.c
+ * Client interface to pmap rpc service.
+ * remote call and broadcast service
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#include "namespace.h"
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/poll.h>
+#include <sys/socket.h>
+
+#include <net/if.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <assert.h>
+#include <err.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <rpc/rpc.h>
+#include <rpc/pmap_prot.h>
+#include <rpc/pmap_clnt.h>
+#include <rpc/pmap_rmt.h>
+#include "un-namespace.h"
+
+static const struct timeval timeout = { 3, 0 };
+
+/*
+ * pmapper remote-call-service interface.
+ * This routine is used to call the pmapper remote call service
+ * which will look up a service program in the port maps, and then
+ * remotely call that routine with the given parameters.  This allows
+ * programs to do a lookup and call in one step.
+*/
+enum clnt_stat
+pmap_rmtcall(addr, prog, vers, proc, xdrargs, argsp, xdrres, resp, tout,
+    port_ptr)
+	struct sockaddr_in *addr;
+	u_long prog, vers, proc;
+	xdrproc_t xdrargs, xdrres;
+	caddr_t argsp, resp;
+	struct timeval tout;
+	u_long *port_ptr;
+{
+	int sock = -1;
+	CLIENT *client;
+	struct rmtcallargs a;
+	struct rmtcallres r;
+	enum clnt_stat stat;
+
+	assert(addr != NULL);
+	assert(port_ptr != NULL);
+
+	addr->sin_port = htons(PMAPPORT);
+	client = clntudp_create(addr, PMAPPROG, PMAPVERS, timeout, &sock);
+	if (client != NULL) {
+		a.prog = prog;
+		a.vers = vers;
+		a.proc = proc;
+		a.args_ptr = argsp;
+		a.xdr_args = xdrargs;
+		r.port_ptr = port_ptr;
+		r.results_ptr = resp;
+		r.xdr_results = xdrres;
+		stat = CLNT_CALL(client, (rpcproc_t)PMAPPROC_CALLIT,
+		    (xdrproc_t)xdr_rmtcall_args, &a, (xdrproc_t)xdr_rmtcallres,
+		    &r, tout);
+		CLNT_DESTROY(client);
+	} else {
+		stat = RPC_FAILED;
+	}
+	addr->sin_port = 0;
+	return (stat);
+}
+
+
+/*
+ * XDR remote call arguments
+ * written for XDR_ENCODE direction only
+ */
+bool_t
+xdr_rmtcall_args(xdrs, cap)
+	XDR *xdrs;
+	struct rmtcallargs *cap;
+{
+	u_int lenposition, argposition, position;
+
+	assert(xdrs != NULL);
+	assert(cap != NULL);
+
+	if (xdr_u_long(xdrs, &(cap->prog)) &&
+	    xdr_u_long(xdrs, &(cap->vers)) &&
+	    xdr_u_long(xdrs, &(cap->proc))) {
+		lenposition = XDR_GETPOS(xdrs);
+		if (! xdr_u_long(xdrs, &(cap->arglen)))
+		    return (FALSE);
+		argposition = XDR_GETPOS(xdrs);
+		if (! (*(cap->xdr_args))(xdrs, cap->args_ptr))
+		    return (FALSE);
+		position = XDR_GETPOS(xdrs);
+		cap->arglen = (u_long)position - (u_long)argposition;
+		XDR_SETPOS(xdrs, lenposition);
+		if (! xdr_u_long(xdrs, &(cap->arglen)))
+		    return (FALSE);
+		XDR_SETPOS(xdrs, position);
+		return (TRUE);
+	}
+	return (FALSE);
+}
+
+/*
+ * XDR remote call results
+ * written for XDR_DECODE direction only
+ */
+bool_t
+xdr_rmtcallres(xdrs, crp)
+	XDR *xdrs;
+	struct rmtcallres *crp;
+{
+	caddr_t port_ptr;
+
+	assert(xdrs != NULL);
+	assert(crp != NULL);
+
+	port_ptr = (caddr_t)(void *)crp->port_ptr;
+	if (xdr_reference(xdrs, &port_ptr, sizeof (u_long),
+	    (xdrproc_t)xdr_u_long) && xdr_u_long(xdrs, &crp->resultslen)) {
+		crp->port_ptr = (u_long *)(void *)port_ptr;
+		return ((*(crp->xdr_results))(xdrs, crp->results_ptr));
+	}
+	return (FALSE);
+}
Index: freebsd/lib/libc/rpc/rpc_callmsg.c
===================================================================
--- freebsd/lib/libc/rpc/rpc_callmsg.c	(revision 60b1d40751c8b3235b7ccbf3bb6ad0c562562f01)
+++ freebsd/lib/libc/rpc/rpc_callmsg.c	(revision 60b1d40751c8b3235b7ccbf3bb6ad0c562562f01)
@@ -0,0 +1,208 @@
+#include <machine/rtems-bsd-user-space.h>
+
+/*	$NetBSD: rpc_callmsg.c,v 1.16 2000/07/14 08:40:42 fvdl Exp $	*/
+
+/*-
+ * Copyright (c) 2009, Sun Microsystems, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions are met:
+ * - Redistributions of source code must retain the above copyright notice, 
+ *   this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice, 
+ *   this list of conditions and the following disclaimer in the documentation 
+ *   and/or other materials provided with the distribution.
+ * - Neither the name of Sun Microsystems, Inc. nor the names of its 
+ *   contributors may be used to endorse or promote products derived 
+ *   from this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char *sccsid2 = "@(#)rpc_callmsg.c 1.4 87/08/11 Copyr 1984 Sun Micro";
+static char *sccsid = "@(#)rpc_callmsg.c	2.1 88/07/29 4.0 RPCSRC";
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * rpc_callmsg.c
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ *
+ */
+
+#include "namespace.h"
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <rpc/rpc.h>
+#include "un-namespace.h"
+
+/*
+ * XDR a call message
+ */
+bool_t
+xdr_callmsg(xdrs, cmsg)
+	XDR *xdrs;
+	struct rpc_msg *cmsg;
+{
+	enum msg_type *prm_direction;
+	int32_t *buf;
+	struct opaque_auth *oa;
+
+	assert(xdrs != NULL);
+	assert(cmsg != NULL);
+
+	if (xdrs->x_op == XDR_ENCODE) {
+		if (cmsg->rm_call.cb_cred.oa_length > MAX_AUTH_BYTES) {
+			return (FALSE);
+		}
+		if (cmsg->rm_call.cb_verf.oa_length > MAX_AUTH_BYTES) {
+			return (FALSE);
+		}
+		buf = XDR_INLINE(xdrs, 8 * BYTES_PER_XDR_UNIT
+			+ RNDUP(cmsg->rm_call.cb_cred.oa_length)
+			+ 2 * BYTES_PER_XDR_UNIT
+			+ RNDUP(cmsg->rm_call.cb_verf.oa_length));
+		if (buf != NULL) {
+			IXDR_PUT_INT32(buf, cmsg->rm_xid);
+			IXDR_PUT_ENUM(buf, cmsg->rm_direction);
+			if (cmsg->rm_direction != CALL) {
+				return (FALSE);
+			}
+			IXDR_PUT_INT32(buf, cmsg->rm_call.cb_rpcvers);
+			if (cmsg->rm_call.cb_rpcvers != RPC_MSG_VERSION) {
+				return (FALSE);
+			}
+			IXDR_PUT_INT32(buf, cmsg->rm_call.cb_prog);
+			IXDR_PUT_INT32(buf, cmsg->rm_call.cb_vers);
+			IXDR_PUT_INT32(buf, cmsg->rm_call.cb_proc);
+			oa = &cmsg->rm_call.cb_cred;
+			IXDR_PUT_ENUM(buf, oa->oa_flavor);
+			IXDR_PUT_INT32(buf, oa->oa_length);
+			if (oa->oa_length) {
+				memmove(buf, oa->oa_base, oa->oa_length);
+				buf += RNDUP(oa->oa_length) / sizeof (int32_t);
+			}
+			oa = &cmsg->rm_call.cb_verf;
+			IXDR_PUT_ENUM(buf, oa->oa_flavor);
+			IXDR_PUT_INT32(buf, oa->oa_length);
+			if (oa->oa_length) {
+				memmove(buf, oa->oa_base, oa->oa_length);
+				/* no real need....
+				buf += RNDUP(oa->oa_length) / sizeof (int32_t);
+				*/
+			}
+			return (TRUE);
+		}
+	}
+	if (xdrs->x_op == XDR_DECODE) {
+		buf = XDR_INLINE(xdrs, 8 * BYTES_PER_XDR_UNIT);
+		if (buf != NULL) {
+			cmsg->rm_xid = IXDR_GET_U_INT32(buf);
+			cmsg->rm_direction = IXDR_GET_ENUM(buf, enum msg_type);
+			if (cmsg->rm_direction != CALL) {
+				return (FALSE);
+			}
+			cmsg->rm_call.cb_rpcvers = IXDR_GET_U_INT32(buf);
+			if (cmsg->rm_call.cb_rpcvers != RPC_MSG_VERSION) {
+				return (FALSE);
+			}
+			cmsg->rm_call.cb_prog = IXDR_GET_U_INT32(buf);
+			cmsg->rm_call.cb_vers = IXDR_GET_U_INT32(buf);
+			cmsg->rm_call.cb_proc = IXDR_GET_U_INT32(buf);
+			oa = &cmsg->rm_call.cb_cred;
+			oa->oa_flavor = IXDR_GET_ENUM(buf, enum_t);
+			oa->oa_length = (u_int)IXDR_GET_U_INT32(buf);
+			if (oa->oa_length) {
+				if (oa->oa_length > MAX_AUTH_BYTES) {
+					return (FALSE);
+				}
+				if (oa->oa_base == NULL) {
+					oa->oa_base = (caddr_t)
+					    mem_alloc(oa->oa_length);
+					if (oa->oa_base == NULL)
+						return (FALSE);
+				}
+				buf = XDR_INLINE(xdrs, RNDUP(oa->oa_length));
+				if (buf == NULL) {
+					if (xdr_opaque(xdrs, oa->oa_base,
+					    oa->oa_length) == FALSE) {
+						return (FALSE);
+					}
+				} else {
+					memmove(oa->oa_base, buf,
+					    oa->oa_length);
+					/* no real need....
+					buf += RNDUP(oa->oa_length) /
+						sizeof (int32_t);
+					*/
+				}
+			}
+			oa = &cmsg->rm_call.cb_verf;
+			buf = XDR_INLINE(xdrs, 2 * BYTES_PER_XDR_UNIT);
+			if (buf == NULL) {
+				if (xdr_enum(xdrs, &oa->oa_flavor) == FALSE ||
+				    xdr_u_int(xdrs, &oa->oa_length) == FALSE) {
+					return (FALSE);
+				}
+			} else {
+				oa->oa_flavor = IXDR_GET_ENUM(buf, enum_t);
+				oa->oa_length = (u_int)IXDR_GET_U_INT32(buf);
+			}
+			if (oa->oa_length) {
+				if (oa->oa_length > MAX_AUTH_BYTES) {
+					return (FALSE);
+				}
+				if (oa->oa_base == NULL) {
+					oa->oa_base = (caddr_t)
+					    mem_alloc(oa->oa_length);
+					if (oa->oa_base == NULL)
+						return (FALSE);
+				}
+				buf = XDR_INLINE(xdrs, RNDUP(oa->oa_length));
+				if (buf == NULL) {
+					if (xdr_opaque(xdrs, oa->oa_base,
+					    oa->oa_length) == FALSE) {
+						return (FALSE);
+					}
+				} else {
+					memmove(oa->oa_base, buf,
+					    oa->oa_length);
+					/* no real need...
+					buf += RNDUP(oa->oa_length) /
+						sizeof (int32_t);
+					*/
+				}
+			}
+			return (TRUE);
+		}
+	}
+	prm_direction = &cmsg->rm_direction;
+	if (
+	    xdr_u_int32_t(xdrs, &(cmsg->rm_xid)) &&
+	    xdr_enum(xdrs, (enum_t *) prm_direction) &&
+	    (cmsg->rm_direction == CALL) &&
+	    xdr_u_int32_t(xdrs, &(cmsg->rm_call.cb_rpcvers)) &&
+	    (cmsg->rm_call.cb_rpcvers == RPC_MSG_VERSION) &&
+	    xdr_u_int32_t(xdrs, &(cmsg->rm_call.cb_prog)) &&
+	    xdr_u_int32_t(xdrs, &(cmsg->rm_call.cb_vers)) &&
+	    xdr_u_int32_t(xdrs, &(cmsg->rm_call.cb_proc)) &&
+	    xdr_opaque_auth(xdrs, &(cmsg->rm_call.cb_cred)) )
+		return (xdr_opaque_auth(xdrs, &(cmsg->rm_call.cb_verf)));
+	return (FALSE);
+}
Index: freebsd/lib/libc/rpc/rpc_com.h
===================================================================
--- freebsd/lib/libc/rpc/rpc_com.h	(revision 60b1d40751c8b3235b7ccbf3bb6ad0c562562f01)
+++ freebsd/lib/libc/rpc/rpc_com.h	(revision 60b1d40751c8b3235b7ccbf3bb6ad0c562562f01)
@@ -0,0 +1,94 @@
+/*	$NetBSD: rpc_com.h,v 1.3 2000/12/10 04:10:08 christos Exp $	*/
+
+/*-
+ * Copyright (c) 2009, Sun Microsystems, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions are met:
+ * - Redistributions of source code must retain the above copyright notice, 
+ *   this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice, 
+ *   this list of conditions and the following disclaimer in the documentation 
+ *   and/or other materials provided with the distribution.
+ * - Neither the name of Sun Microsystems, Inc. nor the names of its 
+ *   contributors may be used to endorse or promote products derived 
+ *   from this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+/*
+ * Copyright (c) 1986 - 1991 by Sun Microsystems, Inc.
+ */
+
+/*
+ * rpc_com.h, Common definitions for both the server and client side.
+ * All for the topmost layer of rpc
+ *
+ * In Sun's tirpc distribution, this was installed as <rpc/rpc_com.h>,
+ * but as it contains only non-exported interfaces, it was moved here.
+ */
+
+#ifndef _RPC_RPCCOM_H
+#define	_RPC_RPCCOM_H
+
+#include <sys/cdefs.h>
+
+/* #pragma ident	"@(#)rpc_com.h	1.11	93/07/05 SMI" */
+
+/*
+ * The max size of the transport, if the size cannot be determined
+ * by other means.
+ */
+#define	RPC_MAXDATASIZE 9000
+#define	RPC_MAXADDRSIZE 1024
+
+#define __RPC_GETXID(now) ((u_int32_t)getpid() ^ (u_int32_t)(now)->tv_sec ^ \
+    (u_int32_t)(now)->tv_usec)
+
+__BEGIN_DECLS
+extern u_int __rpc_get_a_size(int);
+extern int __rpc_dtbsize(void);
+extern struct netconfig * __rpcgettp(int);
+extern  int  __rpc_get_default_domain(char **);
+
+char *__rpc_taddr2uaddr_af(int, const struct netbuf *);
+struct netbuf *__rpc_uaddr2taddr_af(int, const char *);
+int __rpc_fixup_addr(struct netbuf *, const struct netbuf *);
+int __rpc_sockinfo2netid(struct __rpc_sockinfo *, const char **);
+int __rpc_seman2socktype(int);
+int __rpc_socktype2seman(int);
+void *rpc_nullproc(CLIENT *);
+int __rpc_sockisbound(int);
+
+struct netbuf *__rpcb_findaddr_timed(rpcprog_t, rpcvers_t,
+    const struct netconfig *, const char *host, CLIENT **clpp,
+    struct timeval *tp);
+
+bool_t __rpc_control(int,void *);
+
+char *_get_next_token(char *, int);
+
+bool_t __svc_clean_idle(fd_set *, int, bool_t);
+bool_t __xdrrec_setnonblock(XDR *, int);
+bool_t __xdrrec_getrec(XDR *, enum xprt_stat *, bool_t);
+void __xprt_unregister_unlocked(SVCXPRT *);
+
+SVCXPRT **__svc_xports;
+int __svc_maxrec;
+
+__END_DECLS
+
+#endif /* _RPC_RPCCOM_H */
Index: freebsd/lib/libc/rpc/rpc_commondata.c
===================================================================
--- freebsd/lib/libc/rpc/rpc_commondata.c	(revision 60b1d40751c8b3235b7ccbf3bb6ad0c562562f01)
+++ freebsd/lib/libc/rpc/rpc_commondata.c	(revision 60b1d40751c8b3235b7ccbf3bb6ad0c562562f01)
@@ -0,0 +1,49 @@
+#include <machine/rtems-bsd-user-space.h>
+
+/*	$NetBSD: rpc_commondata.c,v 1.7 2000/06/02 23:11:13 fvdl Exp $	*/
+
+/*-
+ * Copyright (c) 2009, Sun Microsystems, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions are met:
+ * - Redistributions of source code must retain the above copyright notice, 
+ *   this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice, 
+ *   this list of conditions and the following disclaimer in the documentation 
+ *   and/or other materials provided with the distribution.
+ * - Neither the name of Sun Microsystems, Inc. nor the names of its 
+ *   contributors may be used to endorse or promote products derived 
+ *   from this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char *sccsid = "@(#)rpc_commondata.c	2.1 88/07/29 4.0 RPCSRC";
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <rpc/rpc.h>
+#include "un-namespace.h"
+
+/*
+ * This file should only contain common data (global data) that is exported
+ * by public interfaces 
+ */
+struct opaque_auth _null_auth;
+fd_set svc_fdset;
+int svc_maxfd = -1;
Index: freebsd/lib/libc/rpc/rpc_dtablesize.c
===================================================================
--- freebsd/lib/libc/rpc/rpc_dtablesize.c	(revision 60b1d40751c8b3235b7ccbf3bb6ad0c562562f01)
+++ freebsd/lib/libc/rpc/rpc_dtablesize.c	(revision 60b1d40751c8b3235b7ccbf3bb6ad0c562562f01)
@@ -0,0 +1,68 @@
+#include <machine/rtems-bsd-user-space.h>
+
+/*	$NetBSD: rpc_dtablesize.c,v 1.14 1998/11/15 17:32:43 christos Exp $	*/
+
+/*-
+ * Copyright (c) 2009, Sun Microsystems, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions are met:
+ * - Redistributions of source code must retain the above copyright notice, 
+ *   this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice, 
+ *   this list of conditions and the following disclaimer in the documentation 
+ *   and/or other materials provided with the distribution.
+ * - Neither the name of Sun Microsystems, Inc. nor the names of its 
+ *   contributors may be used to endorse or promote products derived 
+ *   from this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char *sccsid2 = "@(#)rpc_dtablesize.c 1.2 87/08/11 Copyr 1987 Sun Micro";
+static char *sccsid = "@(#)rpc_dtablesize.c	2.1 88/07/29 4.0 RPCSRC";
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <unistd.h>
+#include "un-namespace.h"
+
+int _rpc_dtablesize(void);	/* XXX */
+
+/*
+ * Cache the result of getdtablesize(), so we don't have to do an
+ * expensive system call every time.
+ */
+/*
+ * XXX In FreeBSD 2.x, you can have the maximum number of open file
+ * descriptors be greater than FD_SETSIZE (which us 256 by default).
+ *
+ * Since old programs tend to use this call to determine the first arg
+ * for _select(), having this return > FD_SETSIZE is a Bad Idea(TM)!
+ */
+int
+_rpc_dtablesize(void)
+{
+	static int size;
+
+	if (size == 0) {
+		size = getdtablesize();
+		if (size > FD_SETSIZE)
+			size = FD_SETSIZE;
+	}
+	return (size);
+}
Index: freebsd/lib/libc/rpc/rpc_generic.c
===================================================================
--- freebsd/lib/libc/rpc/rpc_generic.c	(revision 60b1d40751c8b3235b7ccbf3bb6ad0c562562f01)
+++ freebsd/lib/libc/rpc/rpc_generic.c	(revision 60b1d40751c8b3235b7ccbf3bb6ad0c562562f01)
@@ -0,0 +1,848 @@
+#include <machine/rtems-bsd-user-space.h>
+
+/*	$NetBSD: rpc_generic.c,v 1.4 2000/09/28 09:07:04 kleink Exp $	*/
+
+/*-
+ * Copyright (c) 2009, Sun Microsystems, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions are met:
+ * - Redistributions of source code must retain the above copyright notice, 
+ *   this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice, 
+ *   this list of conditions and the following disclaimer in the documentation 
+ *   and/or other materials provided with the distribution.
+ * - Neither the name of Sun Microsystems, Inc. nor the names of its 
+ *   contributors may be used to endorse or promote products derived 
+ *   from this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * Copyright (c) 1986-1991 by Sun Microsystems Inc. 
+ */
+
+/* #pragma ident	"@(#)rpc_generic.c	1.17	94/04/24 SMI" */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * rpc_generic.c, Miscl routines for RPC.
+ *
+ */
+
+#include "namespace.h"
+#include "reentrant.h"
+#include <sys/types.h>
+#include <rtems/bsd/sys/param.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <sys/un.h>
+#include <rtems/bsd/sys/resource.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <rpc/rpc.h>
+#include <ctype.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <netdb.h>
+#include <netconfig.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+#include <rpc/nettype.h>
+#include "un-namespace.h"
+#include "rpc_com.h"
+#include "mt_misc.h"
+
+struct handle {
+	NCONF_HANDLE *nhandle;
+	int nflag;		/* Whether NETPATH or NETCONFIG */
+	int nettype;
+};
+
+static const struct _rpcnettype {
+	const char *name;
+	const int type;
+} _rpctypelist[] = {
+	{ "netpath", _RPC_NETPATH },
+	{ "visible", _RPC_VISIBLE },
+	{ "circuit_v", _RPC_CIRCUIT_V },
+	{ "datagram_v", _RPC_DATAGRAM_V },
+	{ "circuit_n", _RPC_CIRCUIT_N },
+	{ "datagram_n", _RPC_DATAGRAM_N },
+	{ "tcp", _RPC_TCP },
+	{ "udp", _RPC_UDP },
+	{ 0, _RPC_NONE }
+};
+
+struct netid_af {
+	const char	*netid;
+	int		af;
+	int		protocol;
+};
+
+static const struct netid_af na_cvt[] = {
+	{ "udp",  AF_INET,  IPPROTO_UDP },
+	{ "tcp",  AF_INET,  IPPROTO_TCP },
+#ifdef INET6
+	{ "udp6", AF_INET6, IPPROTO_UDP },
+	{ "tcp6", AF_INET6, IPPROTO_TCP },
+#endif
+	{ "local", AF_LOCAL, 0 }
+};
+
+#if 0
+static char *strlocase(char *);
+#endif
+static int getnettype(const char *);
+
+/*
+ * Cache the result of getrlimit(), so we don't have to do an
+ * expensive call every time.
+ */
+int
+__rpc_dtbsize()
+{
+	static int tbsize;
+	struct rlimit rl;
+
+	if (tbsize) {
+		return (tbsize);
+	}
+	if (getrlimit(RLIMIT_NOFILE, &rl) == 0) {
+		return (tbsize = (int)rl.rlim_max);
+	}
+	/*
+	 * Something wrong.  I'll try to save face by returning a
+	 * pessimistic number.
+	 */
+	return (32);
+}
+
+
+/*
+ * Find the appropriate buffer size
+ */
+u_int
+/*ARGSUSED*/
+__rpc_get_t_size(af, proto, size)
+	int af, proto;
+	int size;	/* Size requested */
+{
+	int maxsize, defsize;
+
+	maxsize = 256 * 1024;	/* XXX */
+	switch (proto) {
+	case IPPROTO_TCP:
+		defsize = 64 * 1024;	/* XXX */
+		break;
+	case IPPROTO_UDP:
+		defsize = UDPMSGSIZE;
+		break;
+	default:
+		defsize = RPC_MAXDATASIZE;
+		break;
+	}
+	if (size == 0)
+		return defsize;
+
+	/* Check whether the value is within the upper max limit */
+	return (size > maxsize ? (u_int)maxsize : (u_int)size);
+}
+
+/*
+ * Find the appropriate address buffer size
+ */
+u_int
+__rpc_get_a_size(af)
+	int af;
+{
+	switch (af) {
+	case AF_INET:
+		return sizeof (struct sockaddr_in);
+#ifdef INET6
+	case AF_INET6:
+		return sizeof (struct sockaddr_in6);
+#endif
+	case AF_LOCAL:
+		return sizeof (struct sockaddr_un);
+	default:
+		break;
+	}
+	return ((u_int)RPC_MAXADDRSIZE);
+}
+
+#if 0
+static char *
+strlocase(p)
+	char *p;
+{
+	char *t = p;
+
+	for (; *p; p++)
+		if (isupper(*p))
+			*p = tolower(*p);
+	return (t);
+}
+#endif
+
+/*
+ * Returns the type of the network as defined in <rpc/nettype.h>
+ * If nettype is NULL, it defaults to NETPATH.
+ */
+static int
+getnettype(nettype)
+	const char *nettype;
+{
+	int i;
+
+	if ((nettype == NULL) || (nettype[0] == 0)) {
+		return (_RPC_NETPATH);	/* Default */
+	}
+
+#if 0
+	nettype = strlocase(nettype);
+#endif
+	for (i = 0; _rpctypelist[i].name; i++)
+		if (strcasecmp(nettype, _rpctypelist[i].name) == 0) {
+			return (_rpctypelist[i].type);
+		}
+	return (_rpctypelist[i].type);
+}
+
+static thread_key_t tcp_key, udp_key;
+static once_t keys_once = ONCE_INITIALIZER;
+static int tcp_key_error, udp_key_error;
+
+static void
+keys_init(void)
+{
+
+	tcp_key_error = thr_keycreate(&tcp_key, free);
+	udp_key_error = thr_keycreate(&udp_key, free);
+}
+
+/*
+ * For the given nettype (tcp or udp only), return the first structure found.
+ * This should be freed by calling freenetconfigent()
+ */
+struct netconfig *
+__rpc_getconfip(nettype)
+	const char *nettype;
+{
+	char *netid;
+	char *netid_tcp = (char *) NULL;
+	char *netid_udp = (char *) NULL;
+	static char *netid_tcp_main;
+	static char *netid_udp_main;
+	struct netconfig *dummy;
+	int main_thread;
+
+	if ((main_thread = thr_main())) {
+		netid_udp = netid_udp_main;
+		netid_tcp = netid_tcp_main;
+	} else {
+		if (thr_once(&keys_once, keys_init) != 0 ||
+		    tcp_key_error != 0 || udp_key_error != 0)
+			return (NULL);
+		netid_tcp = (char *)thr_getspecific(tcp_key);
+		netid_udp = (char *)thr_getspecific(udp_key);
+	}
+	if (!netid_udp && !netid_tcp) {
+		struct netconfig *nconf;
+		void *confighandle;
+
+		if (!(confighandle = setnetconfig())) {
+			syslog (LOG_ERR, "rpc: failed to open " NETCONFIG);
+			return (NULL);
+		}
+		while ((nconf = getnetconfig(confighandle)) != NULL) {
+			if (strcmp(nconf->nc_protofmly, NC_INET) == 0) {
+				if (strcmp(nconf->nc_proto, NC_TCP) == 0 &&
+				    netid_tcp == NULL) {
+					netid_tcp = strdup(nconf->nc_netid);
+					if (main_thread)
+						netid_tcp_main = netid_tcp;
+					else
+						thr_setspecific(tcp_key,
+							(void *) netid_tcp);
+				} else
+				if (strcmp(nconf->nc_proto, NC_UDP) == 0 &&
+				    netid_udp == NULL) {
+					netid_udp = strdup(nconf->nc_netid);
+					if (main_thread)
+						netid_udp_main = netid_udp;
+					else
+						thr_setspecific(udp_key,
+						(void *) netid_udp);
+				}
+			}
+		}
+		endnetconfig(confighandle);
+	}
+	if (strcmp(nettype, "udp") == 0)
+		netid = netid_udp;
+	else if (strcmp(nettype, "tcp") == 0)
+		netid = netid_tcp;
+	else {
+		return (NULL);
+	}
+	if ((netid == NULL) || (netid[0] == 0)) {
+		return (NULL);
+	}
+	dummy = getnetconfigent(netid);
+	return (dummy);
+}
+
+/*
+ * Returns the type of the nettype, which should then be used with
+ * __rpc_getconf().
+ */
+void *
+__rpc_setconf(nettype)
+	const char *nettype;
+{
+	struct handle *handle;
+
+	handle = (struct handle *) malloc(sizeof (struct handle));
+	if (handle == NULL) {
+		return (NULL);
+	}
+	switch (handle->nettype = getnettype(nettype)) {
+	case _RPC_NETPATH:
+	case _RPC_CIRCUIT_N:
+	case _RPC_DATAGRAM_N:
+		if (!(handle->nhandle = setnetpath()))
+			goto failed;
+		handle->nflag = TRUE;
+		break;
+	case _RPC_VISIBLE:
+	case _RPC_CIRCUIT_V:
+	case _RPC_DATAGRAM_V:
+	case _RPC_TCP:
+	case _RPC_UDP:
+		if (!(handle->nhandle = setnetconfig())) {
+		        syslog (LOG_ERR, "rpc: failed to open " NETCONFIG);
+			goto failed;
+		}
+		handle->nflag = FALSE;
+		break;
+	default:
+		goto failed;
+	}
+
+	return (handle);
+
+failed:
+	free(handle);
+	return (NULL);
+}
+
+/*
+ * Returns the next netconfig struct for the given "net" type.
+ * __rpc_setconf() should have been called previously.
+ */
+struct netconfig *
+__rpc_getconf(vhandle)
+	void *vhandle;
+{
+	struct handle *handle;
+	struct netconfig *nconf;
+
+	handle = (struct handle *)vhandle;
+	if (handle == NULL) {
+		return (NULL);
+	}
+	for (;;) {
+		if (handle->nflag)
+			nconf = getnetpath(handle->nhandle);
+		else
+			nconf = getnetconfig(handle->nhandle);
+		if (nconf == NULL)
+			break;
+		if ((nconf->nc_semantics != NC_TPI_CLTS) &&
+			(nconf->nc_semantics != NC_TPI_COTS) &&
+			(nconf->nc_semantics != NC_TPI_COTS_ORD))
+			continue;
+		switch (handle->nettype) {
+		case _RPC_VISIBLE:
+			if (!(nconf->nc_flag & NC_VISIBLE))
+				continue;
+			/* FALLTHROUGH */
+		case _RPC_NETPATH:	/* Be happy */
+			break;
+		case _RPC_CIRCUIT_V:
+			if (!(nconf->nc_flag & NC_VISIBLE))
+				continue;
+			/* FALLTHROUGH */
+		case _RPC_CIRCUIT_N:
+			if ((nconf->nc_semantics != NC_TPI_COTS) &&
+				(nconf->nc_semantics != NC_TPI_COTS_ORD))
+				continue;
+			break;
+		case _RPC_DATAGRAM_V:
+			if (!(nconf->nc_flag & NC_VISIBLE))
+				continue;
+			/* FALLTHROUGH */
+		case _RPC_DATAGRAM_N:
+			if (nconf->nc_semantics != NC_TPI_CLTS)
+				continue;
+			break;
+		case _RPC_TCP:
+			if (((nconf->nc_semantics != NC_TPI_COTS) &&
+				(nconf->nc_semantics != NC_TPI_COTS_ORD)) ||
+				(strcmp(nconf->nc_protofmly, NC_INET)
+#ifdef INET6
+				 && strcmp(nconf->nc_protofmly, NC_INET6))
+#else
+				)
+#endif
+				||
+				strcmp(nconf->nc_proto, NC_TCP))
+				continue;
+			break;
+		case _RPC_UDP:
+			if ((nconf->nc_semantics != NC_TPI_CLTS) ||
+				(strcmp(nconf->nc_protofmly, NC_INET)
+#ifdef INET6
+				&& strcmp(nconf->nc_protofmly, NC_INET6))
+#else
+				)
+#endif
+				||
+				strcmp(nconf->nc_proto, NC_UDP))
+				continue;
+			break;
+		}
+		break;
+	}
+	return (nconf);
+}
+
+void
+__rpc_endconf(vhandle)
+	void * vhandle;
+{
+	struct handle *handle;
+
+	handle = (struct handle *) vhandle;
+	if (handle == NULL) {
+		return;
+	}
+	if (handle->nflag) {
+		endnetpath(handle->nhandle);
+	} else {
+		endnetconfig(handle->nhandle);
+	}
+	free(handle);
+}
+
+/*
+ * Used to ping the NULL procedure for clnt handle.
+ * Returns NULL if fails, else a non-NULL pointer.
+ */
+void *
+rpc_nullproc(clnt)
+	CLIENT *clnt;
+{
+	struct timeval TIMEOUT = {25, 0};
+
+	if (clnt_call(clnt, NULLPROC, (xdrproc_t) xdr_void, NULL,
+		(xdrproc_t) xdr_void, NULL, TIMEOUT) != RPC_SUCCESS) {
+		return (NULL);
+	}
+	return ((void *) clnt);
+}
+
+/*
+ * Try all possible transports until
+ * one succeeds in finding the netconf for the given fd.
+ */
+struct netconfig *
+__rpcgettp(fd)
+	int fd;
+{
+	const char *netid;
+	struct __rpc_sockinfo si;
+
+	if (!__rpc_fd2sockinfo(fd, &si))
+		return NULL;
+
+	if (!__rpc_sockinfo2netid(&si, &netid))
+		return NULL;
+
+	/*LINTED const castaway*/
+	return getnetconfigent((char *)netid);
+}
+
+int
+__rpc_fd2sockinfo(int fd, struct __rpc_sockinfo *sip)
+{
+	socklen_t len;
+	int type, proto;
+	struct sockaddr_storage ss;
+
+	len = sizeof ss;
+	if (_getsockname(fd, (struct sockaddr *)(void *)&ss, &len) < 0)
+		return 0;
+	sip->si_alen = len;
+
+	len = sizeof type;
+	if (_getsockopt(fd, SOL_SOCKET, SO_TYPE, &type, &len) < 0)
+		return 0;
+
+	/* XXX */
+	if (ss.ss_family != AF_LOCAL) {
+		if (type == SOCK_STREAM)
+			proto = IPPROTO_TCP;
+		else if (type == SOCK_DGRAM)
+			proto = IPPROTO_UDP;
+		else
+			return 0;
+	} else
+		proto = 0;
+
+	sip->si_af = ss.ss_family;
+	sip->si_proto = proto;
+	sip->si_socktype = type;
+
+	return 1;
+}
+
+/*
+ * Linear search, but the number of entries is small.
+ */
+int
+__rpc_nconf2sockinfo(const struct netconfig *nconf, struct __rpc_sockinfo *sip)
+{
+	int i;
+
+	for (i = 0; i < (sizeof na_cvt) / (sizeof (struct netid_af)); i++)
+		if (strcmp(na_cvt[i].netid, nconf->nc_netid) == 0 || (
+		    strcmp(nconf->nc_netid, "unix") == 0 &&
+		    strcmp(na_cvt[i].netid, "local") == 0)) {
+			sip->si_af = na_cvt[i].af;
+			sip->si_proto = na_cvt[i].protocol;
+			sip->si_socktype =
+			    __rpc_seman2socktype((int)nconf->nc_semantics);
+			if (sip->si_socktype == -1)
+				return 0;
+			sip->si_alen = __rpc_get_a_size(sip->si_af);
+			return 1;
+		}
+
+	return 0;
+}
+
+int
+__rpc_nconf2fd(const struct netconfig *nconf)
+{
+	struct __rpc_sockinfo si;
+
+	if (!__rpc_nconf2sockinfo(nconf, &si))
+		return 0;
+
+	return _socket(si.si_af, si.si_socktype, si.si_proto);
+}
+
+int
+__rpc_sockinfo2netid(struct __rpc_sockinfo *sip, const char **netid)
+{
+	int i;
+	struct netconfig *nconf;
+
+	nconf = getnetconfigent("local");
+
+	for (i = 0; i < (sizeof na_cvt) / (sizeof (struct netid_af)); i++) {
+		if (na_cvt[i].af == sip->si_af &&
+		    na_cvt[i].protocol == sip->si_proto) {
+			if (strcmp(na_cvt[i].netid, "local") == 0 && nconf == NULL) {
+				if (netid)
+					*netid = "unix";
+			} else {
+				if (netid)
+					*netid = na_cvt[i].netid;
+			}
+			if (nconf != NULL)
+				freenetconfigent(nconf);
+			return 1;
+		}
+	}
+	if (nconf != NULL)
+		freenetconfigent(nconf);
+
+	return 0;
+}
+
+char *
+taddr2uaddr(const struct netconfig *nconf, const struct netbuf *nbuf)
+{
+	struct __rpc_sockinfo si;
+
+	if (!__rpc_nconf2sockinfo(nconf, &si))
+		return NULL;
+	return __rpc_taddr2uaddr_af(si.si_af, nbuf);
+}
+
+struct netbuf *
+uaddr2taddr(const struct netconfig *nconf, const char *uaddr)
+{
+	struct __rpc_sockinfo si;
+	
+	if (!__rpc_nconf2sockinfo(nconf, &si))
+		return NULL;
+	return __rpc_uaddr2taddr_af(si.si_af, uaddr);
+}
+
+char *
+__rpc_taddr2uaddr_af(int af, const struct netbuf *nbuf)
+{
+	char *ret;
+	struct sockaddr_in *sin;
+	struct sockaddr_un *sun;
+	char namebuf[INET_ADDRSTRLEN];
+#ifdef INET6
+	struct sockaddr_in6 *sin6;
+	char namebuf6[INET6_ADDRSTRLEN];
+#endif
+	u_int16_t port;
+
+	switch (af) {
+	case AF_INET:
+		sin = nbuf->buf;
+		if (inet_ntop(af, &sin->sin_addr, namebuf, sizeof namebuf)
+		    == NULL)
+			return NULL;
+		port = ntohs(sin->sin_port);
+		if (asprintf(&ret, "%s.%u.%u", namebuf, ((u_int32_t)port) >> 8,
+		    port & 0xff) < 0)
+			return NULL;
+		break;
+#ifdef INET6
+	case AF_INET6:
+		sin6 = nbuf->buf;
+		if (inet_ntop(af, &sin6->sin6_addr, namebuf6, sizeof namebuf6)
+		    == NULL)
+			return NULL;
+		port = ntohs(sin6->sin6_port);
+		if (asprintf(&ret, "%s.%u.%u", namebuf6, ((u_int32_t)port) >> 8,
+		    port & 0xff) < 0)
+			return NULL;
+		break;
+#endif
+	case AF_LOCAL:
+		sun = nbuf->buf;
+		if (asprintf(&ret, "%.*s", (int)(sun->sun_len -
+		    offsetof(struct sockaddr_un, sun_path)),
+		    sun->sun_path) < 0)
+			return (NULL);
+		break;
+	default:
+		return NULL;
+	}
+
+	return ret;
+}
+
+struct netbuf *
+__rpc_uaddr2taddr_af(int af, const char *uaddr)
+{
+	struct netbuf *ret = NULL;
+	char *addrstr, *p;
+	unsigned port, portlo, porthi;
+	struct sockaddr_in *sin;
+#ifdef INET6
+	struct sockaddr_in6 *sin6;
+#endif
+	struct sockaddr_un *sun;
+
+	port = 0;
+	sin = NULL;
+	addrstr = strdup(uaddr);
+	if (addrstr == NULL)
+		return NULL;
+
+	/*
+	 * AF_LOCAL addresses are expected to be absolute
+	 * pathnames, anything else will be AF_INET or AF_INET6.
+	 */
+	if (*addrstr != '/') {
+		p = strrchr(addrstr, '.');
+		if (p == NULL)
+			goto out;
+		portlo = (unsigned)atoi(p + 1);
+		*p = '\0';
+
+		p = strrchr(addrstr, '.');
+		if (p == NULL)
+			goto out;
+		porthi = (unsigned)atoi(p + 1);
+		*p = '\0';
+		port = (porthi << 8) | portlo;
+	}
+
+	ret = (struct netbuf *)malloc(sizeof *ret);
+	if (ret == NULL)
+		goto out;
+	
+	switch (af) {
+	case AF_INET:
+		sin = (struct sockaddr_in *)malloc(sizeof *sin);
+		if (sin == NULL)
+			goto out;
+		memset(sin, 0, sizeof *sin);
+		sin->sin_family = AF_INET;
+		sin->sin_port = htons(port);
+		if (inet_pton(AF_INET, addrstr, &sin->sin_addr) <= 0) {
+			free(sin);
+			free(ret);
+			ret = NULL;
+			goto out;
+		}
+		sin->sin_len = ret->maxlen = ret->len = sizeof *sin;
+		ret->buf = sin;
+		break;
+#ifdef INET6
+	case AF_INET6:
+		sin6 = (struct sockaddr_in6 *)malloc(sizeof *sin6);
+		if (sin6 == NULL)
+			goto out;
+		memset(sin6, 0, sizeof *sin6);
+		sin6->sin6_family = AF_INET6;
+		sin6->sin6_port = htons(port);
+		if (inet_pton(AF_INET6, addrstr, &sin6->sin6_addr) <= 0) {
+			free(sin6);
+			free(ret);
+			ret = NULL;
+			goto out;
+		}
+		sin6->sin6_len = ret->maxlen = ret->len = sizeof *sin6;
+		ret->buf = sin6;
+		break;
+#endif
+	case AF_LOCAL:
+		sun = (struct sockaddr_un *)malloc(sizeof *sun);
+		if (sun == NULL)
+			goto out;
+		memset(sun, 0, sizeof *sun);
+		sun->sun_family = AF_LOCAL;
+		strncpy(sun->sun_path, addrstr, sizeof(sun->sun_path) - 1);
+		ret->len = ret->maxlen = sun->sun_len = SUN_LEN(sun);
+		ret->buf = sun;
+		break;
+	default:
+		break;
+	}
+out:
+	free(addrstr);
+	return ret;
+}
+
+int
+__rpc_seman2socktype(int semantics)
+{
+	switch (semantics) {
+	case NC_TPI_CLTS:
+		return SOCK_DGRAM;
+	case NC_TPI_COTS_ORD:
+		return SOCK_STREAM;
+	case NC_TPI_RAW:
+		return SOCK_RAW;
+	default:
+		break;
+	}
+
+	return -1;
+}
+
+int
+__rpc_socktype2seman(int socktype)
+{
+	switch (socktype) {
+	case SOCK_DGRAM:
+		return NC_TPI_CLTS;
+	case SOCK_STREAM:
+		return NC_TPI_COTS_ORD;
+	case SOCK_RAW:
+		return NC_TPI_RAW;
+	default:
+		break;
+	}
+
+	return -1;
+}
+
+/*
+ * XXXX - IPv6 scope IDs can't be handled in universal addresses.
+ * Here, we compare the original server address to that of the RPC
+ * service we just received back from a call to rpcbind on the remote
+ * machine. If they are both "link local" or "site local", copy
+ * the scope id of the server address over to the service address.
+ */
+int
+__rpc_fixup_addr(struct netbuf *new, const struct netbuf *svc)
+{
+#ifdef INET6
+	struct sockaddr *sa_new, *sa_svc;
+	struct sockaddr_in6 *sin6_new, *sin6_svc;
+
+	sa_svc = (struct sockaddr *)svc->buf;
+	sa_new = (struct sockaddr *)new->buf;
+
+	if (sa_new->sa_family == sa_svc->sa_family &&
+	    sa_new->sa_family == AF_INET6) {
+		sin6_new = (struct sockaddr_in6 *)new->buf;
+		sin6_svc = (struct sockaddr_in6 *)svc->buf;
+
+		if ((IN6_IS_ADDR_LINKLOCAL(&sin6_new->sin6_addr) &&
+		     IN6_IS_ADDR_LINKLOCAL(&sin6_svc->sin6_addr)) ||
+		    (IN6_IS_ADDR_SITELOCAL(&sin6_new->sin6_addr) &&
+		     IN6_IS_ADDR_SITELOCAL(&sin6_svc->sin6_addr))) {
+			sin6_new->sin6_scope_id = sin6_svc->sin6_scope_id;
+		}
+	}
+#endif
+	return 1;
+}
+
+int
+__rpc_sockisbound(int fd)
+{
+	struct sockaddr_storage ss;
+	socklen_t slen;
+
+	slen = sizeof (struct sockaddr_storage);
+	if (_getsockname(fd, (struct sockaddr *)(void *)&ss, &slen) < 0)
+		return 0;
+
+	switch (ss.ss_family) {
+		case AF_INET:
+			return (((struct sockaddr_in *)
+			    (void *)&ss)->sin_port != 0);
+#ifdef INET6
+		case AF_INET6:
+			return (((struct sockaddr_in6 *)
+			    (void *)&ss)->sin6_port != 0);
+#endif
+		case AF_LOCAL:
+			/* XXX check this */
+			return (((struct sockaddr_un *)
+			    (void *)&ss)->sun_path[0] != '\0');
+		default:
+			break;
+	}
+
+	return 0;
+}
Index: freebsd/lib/libc/rpc/rpc_prot.c
===================================================================
--- freebsd/lib/libc/rpc/rpc_prot.c	(revision 60b1d40751c8b3235b7ccbf3bb6ad0c562562f01)
+++ freebsd/lib/libc/rpc/rpc_prot.c	(revision 60b1d40751c8b3235b7ccbf3bb6ad0c562562f01)
@@ -0,0 +1,373 @@
+#include <machine/rtems-bsd-user-space.h>
+
+/*	$NetBSD: rpc_prot.c,v 1.16 2000/06/02 23:11:13 fvdl Exp $	*/
+
+/*-
+ * Copyright (c) 2009, Sun Microsystems, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions are met:
+ * - Redistributions of source code must retain the above copyright notice, 
+ *   this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice, 
+ *   this list of conditions and the following disclaimer in the documentation 
+ *   and/or other materials provided with the distribution.
+ * - Neither the name of Sun Microsystems, Inc. nor the names of its 
+ *   contributors may be used to endorse or promote products derived 
+ *   from this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char *sccsid2 = "@(#)rpc_prot.c 1.36 87/08/11 Copyr 1984 Sun Micro";
+static char *sccsid = "@(#)rpc_prot.c	2.3 88/08/07 4.0 RPCSRC";
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * rpc_prot.c
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ *
+ * This set of routines implements the rpc message definition,
+ * its serializer and some common rpc utility routines.
+ * The routines are meant for various implementations of rpc -
+ * they are NOT for the rpc client or rpc service implementations!
+ * Because authentication stuff is easy and is part of rpc, the opaque
+ * routines are also in this program.
+ */
+
+#include "namespace.h"
+#include <rtems/bsd/sys/param.h>
+
+#include <assert.h>
+
+#include <rpc/rpc.h>
+#include "un-namespace.h"
+
+static void accepted(enum accept_stat, struct rpc_err *);
+static void rejected(enum reject_stat, struct rpc_err *);
+
+/* * * * * * * * * * * * * * XDR Authentication * * * * * * * * * * * */
+
+extern struct opaque_auth _null_auth;
+
+/*
+ * XDR an opaque authentication struct
+ * (see auth.h)
+ */
+bool_t
+xdr_opaque_auth(xdrs, ap)
+	XDR *xdrs;
+	struct opaque_auth *ap;
+{
+
+	assert(xdrs != NULL);
+	assert(ap != NULL);
+
+	if (xdr_enum(xdrs, &(ap->oa_flavor)))
+		return (xdr_bytes(xdrs, &ap->oa_base,
+			&ap->oa_length, MAX_AUTH_BYTES));
+	return (FALSE);
+}
+
+/*
+ * XDR a DES block
+ */
+bool_t
+xdr_des_block(xdrs, blkp)
+	XDR *xdrs;
+	des_block *blkp;
+{
+
+	assert(xdrs != NULL);
+	assert(blkp != NULL);
+
+	return (xdr_opaque(xdrs, (caddr_t)(void *)blkp, sizeof(des_block)));
+}
+
+/* * * * * * * * * * * * * * XDR RPC MESSAGE * * * * * * * * * * * * * * * */
+
+/*
+ * XDR the MSG_ACCEPTED part of a reply message union
+ */
+bool_t
+xdr_accepted_reply(xdrs, ar)
+	XDR *xdrs;   
+	struct accepted_reply *ar;
+{
+	enum accept_stat *par_stat;
+
+	assert(xdrs != NULL);
+	assert(ar != NULL);
+
+	par_stat = &ar->ar_stat;
+
+	/* personalized union, rather than calling xdr_union */
+	if (! xdr_opaque_auth(xdrs, &(ar->ar_verf)))
+		return (FALSE);
+	if (! xdr_enum(xdrs, (enum_t *) par_stat))
+		return (FALSE);
+	switch (ar->ar_stat) {
+
+	case SUCCESS:
+		return ((*(ar->ar_results.proc))(xdrs, ar->ar_results.where));
+
+	case PROG_MISMATCH:
+		if (! xdr_u_int32_t(xdrs, &(ar->ar_vers.low)))
+			return (FALSE);
+		return (xdr_u_int32_t(xdrs, &(ar->ar_vers.high)));
+
+	case GARBAGE_ARGS:
+	case SYSTEM_ERR:
+	case PROC_UNAVAIL:
+	case PROG_UNAVAIL:
+		break;
+	}
+	return (TRUE);  /* TRUE => open ended set of problems */
+}
+
+/*
+ * XDR the MSG_DENIED part of a reply message union
+ */
+bool_t 
+xdr_rejected_reply(xdrs, rr)
+	XDR *xdrs;
+	struct rejected_reply *rr;
+{
+	enum reject_stat *prj_stat;
+	enum auth_stat *prj_why;
+
+	assert(xdrs != NULL);
+	assert(rr != NULL);
+
+	prj_stat = &rr->rj_stat;
+
+	/* personalized union, rather than calling xdr_union */
+	if (! xdr_enum(xdrs, (enum_t *) prj_stat))
+		return (FALSE);
+	switch (rr->rj_stat) {
+
+	case RPC_MISMATCH:
+		if (! xdr_u_int32_t(xdrs, &(rr->rj_vers.low)))
+			return (FALSE);
+		return (xdr_u_int32_t(xdrs, &(rr->rj_vers.high)));
+
+	case AUTH_ERROR:
+		prj_why = &rr->rj_why;
+		return (xdr_enum(xdrs, (enum_t *) prj_why));
+	}
+	/* NOTREACHED */
+	assert(0);
+	return (FALSE);
+}
+
+static const struct xdr_discrim reply_dscrm[3] = {
+	{ (int)MSG_ACCEPTED, (xdrproc_t)xdr_accepted_reply },
+	{ (int)MSG_DENIED, (xdrproc_t)xdr_rejected_reply },
+	{ __dontcare__, NULL_xdrproc_t } };
+
+/*
+ * XDR a reply message
+ */
+bool_t
+xdr_replymsg(xdrs, rmsg)
+	XDR *xdrs;
+	struct rpc_msg *rmsg;
+{
+	enum msg_type *prm_direction;
+	enum reply_stat *prp_stat;
+
+	assert(xdrs != NULL);
+	assert(rmsg != NULL);
+
+	prm_direction = &rmsg->rm_direction;
+	prp_stat = &rmsg->rm_reply.rp_stat;
+
+	if (
+	    xdr_u_int32_t(xdrs, &(rmsg->rm_xid)) && 
+	    xdr_enum(xdrs, (enum_t *) prm_direction) &&
+	    (rmsg->rm_direction == REPLY) )
+		return (xdr_union(xdrs, (enum_t *) prp_stat,
+		   (caddr_t)(void *)&(rmsg->rm_reply.ru), reply_dscrm,
+		   NULL_xdrproc_t));
+	return (FALSE);
+}
+
+
+/*
+ * Serializes the "static part" of a call message header.
+ * The fields include: rm_xid, rm_direction, rpcvers, prog, and vers.
+ * The rm_xid is not really static, but the user can easily munge on the fly.
+ */
+bool_t
+xdr_callhdr(xdrs, cmsg)
+	XDR *xdrs;
+	struct rpc_msg *cmsg;
+{
+	enum msg_type *prm_direction;
+
+	assert(xdrs != NULL);
+	assert(cmsg != NULL);
+
+	prm_direction = &cmsg->rm_direction;
+
+	cmsg->rm_direction = CALL;
+	cmsg->rm_call.cb_rpcvers = RPC_MSG_VERSION;
+	if (
+	    (xdrs->x_op == XDR_ENCODE) &&
+	    xdr_u_int32_t(xdrs, &(cmsg->rm_xid)) &&
+	    xdr_enum(xdrs, (enum_t *) prm_direction) &&
+	    xdr_u_int32_t(xdrs, &(cmsg->rm_call.cb_rpcvers)) &&
+	    xdr_u_int32_t(xdrs, &(cmsg->rm_call.cb_prog)) )
+		return (xdr_u_int32_t(xdrs, &(cmsg->rm_call.cb_vers)));
+	return (FALSE);
+}
+
+/* ************************** Client utility routine ************* */
+
+static void
+accepted(acpt_stat, error)
+	enum accept_stat acpt_stat;
+	struct rpc_err *error;
+{
+
+	assert(error != NULL);
+
+	switch (acpt_stat) {
+
+	case PROG_UNAVAIL:
+		error->re_status = RPC_PROGUNAVAIL;
+		return;
+
+	case PROG_MISMATCH:
+		error->re_status = RPC_PROGVERSMISMATCH;
+		return;
+
+	case PROC_UNAVAIL:
+		error->re_status = RPC_PROCUNAVAIL;
+		return;
+
+	case GARBAGE_ARGS:
+		error->re_status = RPC_CANTDECODEARGS;
+		return;
+
+	case SYSTEM_ERR:
+		error->re_status = RPC_SYSTEMERROR;
+		return;
+
+	case SUCCESS:
+		error->re_status = RPC_SUCCESS;
+		return;
+	}
+	/* NOTREACHED */
+	/* something's wrong, but we don't know what ... */
+	error->re_status = RPC_FAILED;
+	error->re_lb.s1 = (int32_t)MSG_ACCEPTED;
+	error->re_lb.s2 = (int32_t)acpt_stat;
+}
+
+static void 
+rejected(rjct_stat, error)
+	enum reject_stat rjct_stat;
+	struct rpc_err *error;
+{
+
+	assert(error != NULL);
+
+	switch (rjct_stat) {
+	case RPC_MISMATCH:
+		error->re_status = RPC_VERSMISMATCH;
+		return;
+
+	case AUTH_ERROR:
+		error->re_status = RPC_AUTHERROR;
+		return;
+	}
+	/* something's wrong, but we don't know what ... */
+	/* NOTREACHED */
+	error->re_status = RPC_FAILED;
+	error->re_lb.s1 = (int32_t)MSG_DENIED;
+	error->re_lb.s2 = (int32_t)rjct_stat;
+}
+
+/*
+ * given a reply message, fills in the error
+ */
+void
+_seterr_reply(msg, error)
+	struct rpc_msg *msg;
+	struct rpc_err *error;
+{
+
+	assert(msg != NULL);
+	assert(error != NULL);
+
+	/* optimized for normal, SUCCESSful case */
+	switch (msg->rm_reply.rp_stat) {
+
+	case MSG_ACCEPTED:
+		if (msg->acpted_rply.ar_stat == SUCCESS) {
+			error->re_status = RPC_SUCCESS;
+			return;
+		}
+		accepted(msg->acpted_rply.ar_stat, error);
+		break;
+
+	case MSG_DENIED:
+		rejected(msg->rjcted_rply.rj_stat, error);
+		break;
+
+	default:
+		error->re_status = RPC_FAILED;
+		error->re_lb.s1 = (int32_t)(msg->rm_reply.rp_stat);
+		break;
+	}
+	switch (error->re_status) {
+
+	case RPC_VERSMISMATCH:
+		error->re_vers.low = msg->rjcted_rply.rj_vers.low;
+		error->re_vers.high = msg->rjcted_rply.rj_vers.high;
+		break;
+
+	case RPC_AUTHERROR:
+		error->re_why = msg->rjcted_rply.rj_why;
+		break;
+
+	case RPC_PROGVERSMISMATCH:
+		error->re_vers.low = msg->acpted_rply.ar_vers.low;
+		error->re_vers.high = msg->acpted_rply.ar_vers.high;
+		break;
+
+	case RPC_FAILED:
+	case RPC_SUCCESS:
+	case RPC_PROGNOTREGISTERED:
+	case RPC_PMAPFAILURE:
+	case RPC_UNKNOWNPROTO:
+	case RPC_UNKNOWNHOST:
+	case RPC_SYSTEMERROR:
+	case RPC_CANTDECODEARGS:
+	case RPC_PROCUNAVAIL:
+	case RPC_PROGUNAVAIL:
+	case RPC_TIMEDOUT:
+	case RPC_CANTRECV:
+	case RPC_CANTSEND:
+	case RPC_CANTDECODERES:
+	case RPC_CANTENCODEARGS:
+	default:
+		break;
+	}
+}
Index: freebsd/lib/libc/rpc/rpc_soc.c
===================================================================
--- freebsd/lib/libc/rpc/rpc_soc.c	(revision 60b1d40751c8b3235b7ccbf3bb6ad0c562562f01)
+++ freebsd/lib/libc/rpc/rpc_soc.c	(revision 60b1d40751c8b3235b7ccbf3bb6ad0c562562f01)
@@ -0,0 +1,583 @@
+#include <machine/rtems-bsd-user-space.h>
+
+/*	$NetBSD: rpc_soc.c,v 1.6 2000/07/06 03:10:35 christos Exp $	*/
+
+/*-
+ * Copyright (c) 2009, Sun Microsystems, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions are met:
+ * - Redistributions of source code must retain the above copyright notice, 
+ *   this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice, 
+ *   this list of conditions and the following disclaimer in the documentation 
+ *   and/or other materials provided with the distribution.
+ * - Neither the name of Sun Microsystems, Inc. nor the names of its 
+ *   contributors may be used to endorse or promote products derived 
+ *   from this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* #ident	"@(#)rpc_soc.c	1.17	94/04/24 SMI" */
+
+/*
+ * Copyright (c) 1986-1991 by Sun Microsystems Inc.
+ * In addition, portions of such source code were derived from Berkeley
+ * 4.3 BSD under license from the Regents of the University of
+ * California.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)rpc_soc.c 1.41 89/05/02 Copyr 1988 Sun Micro";
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#ifdef PORTMAP
+/*
+ * rpc_soc.c
+ *
+ * The backward compatibility routines for the earlier implementation
+ * of RPC, where the only transports supported were tcp/ip and udp/ip.
+ * Based on berkeley socket abstraction, now implemented on the top
+ * of TLI/Streams
+ */
+
+#include "namespace.h"
+#include "reentrant.h"
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <stdio.h>
+#include <rpc/rpc.h>
+#include <rpc/pmap_clnt.h>
+#include <rpc/pmap_prot.h>
+#include <rpc/nettype.h>
+#include <syslog.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <errno.h>
+#include <syslog.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "un-namespace.h"
+
+#include "rpc_com.h"
+#include "mt_misc.h"
+
+static CLIENT *clnt_com_create(struct sockaddr_in *, rpcprog_t, rpcvers_t,
+    int *, u_int, u_int, char *);
+static SVCXPRT *svc_com_create(int, u_int, u_int, char *);
+static bool_t rpc_wrap_bcast(char *, struct netbuf *, struct netconfig *);
+
+/* XXX */
+#define IN4_LOCALHOST_STRING    "127.0.0.1"
+#define IN6_LOCALHOST_STRING    "::1"
+
+/*
+ * A common clnt create routine
+ */
+static CLIENT *
+clnt_com_create(raddr, prog, vers, sockp, sendsz, recvsz, tp)
+	struct sockaddr_in *raddr;
+	rpcprog_t prog;
+	rpcvers_t vers;
+	int *sockp;
+	u_int sendsz;
+	u_int recvsz;
+	char *tp;
+{
+	CLIENT *cl;
+	int madefd = FALSE;
+	int fd = *sockp;
+	struct netconfig *nconf;
+	struct netbuf bindaddr;
+
+	mutex_lock(&rpcsoc_lock);
+	if ((nconf = __rpc_getconfip(tp)) == NULL) {
+		rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
+		mutex_unlock(&rpcsoc_lock);
+		return (NULL);
+	}
+	if (fd == RPC_ANYSOCK) {
+		fd = __rpc_nconf2fd(nconf);
+		if (fd == -1)
+			goto syserror;
+		madefd = TRUE;
+	}
+
+	if (raddr->sin_port == 0) {
+		u_int proto;
+		u_short sport;
+
+		mutex_unlock(&rpcsoc_lock);	/* pmap_getport is recursive */
+		proto = strcmp(tp, "udp") == 0 ? IPPROTO_UDP : IPPROTO_TCP;
+		sport = pmap_getport(raddr, (u_long)prog, (u_long)vers,
+		    proto);
+		if (sport == 0) {
+			goto err;
+		}
+		raddr->sin_port = htons(sport);
+		mutex_lock(&rpcsoc_lock);	/* pmap_getport is recursive */
+	}
+
+	/* Transform sockaddr_in to netbuf */
+	bindaddr.maxlen = bindaddr.len =  sizeof (struct sockaddr_in);
+	bindaddr.buf = raddr;
+
+	bindresvport(fd, NULL);
+	cl = clnt_tli_create(fd, nconf, &bindaddr, prog, vers,
+				sendsz, recvsz);
+	if (cl) {
+		if (madefd == TRUE) {
+			/*
+			 * The fd should be closed while destroying the handle.
+			 */
+			(void) CLNT_CONTROL(cl, CLSET_FD_CLOSE, NULL);
+			*sockp = fd;
+		}
+		(void) freenetconfigent(nconf);
+		mutex_unlock(&rpcsoc_lock);
+		return (cl);
+	}
+	goto err;
+
+syserror:
+	rpc_createerr.cf_stat = RPC_SYSTEMERROR;
+	rpc_createerr.cf_error.re_errno = errno;
+
+err:	if (madefd == TRUE)
+		(void)_close(fd);
+	(void) freenetconfigent(nconf);
+	mutex_unlock(&rpcsoc_lock);
+	return (NULL);
+}
+
+CLIENT *
+clntudp_bufcreate(raddr, prog, vers, wait, sockp, sendsz, recvsz)
+	struct sockaddr_in *raddr;
+	u_long prog;
+	u_long vers;
+	struct timeval wait;
+	int *sockp;
+	u_int sendsz;
+	u_int recvsz;
+{
+	CLIENT *cl;
+
+	cl = clnt_com_create(raddr, (rpcprog_t)prog, (rpcvers_t)vers, sockp,
+	    sendsz, recvsz, "udp");
+	if (cl == NULL) {
+		return (NULL);
+	}
+	(void) CLNT_CONTROL(cl, CLSET_RETRY_TIMEOUT, &wait);
+	return (cl);
+}
+
+CLIENT *
+clntudp_create(raddr, program, version, wait, sockp)
+	struct sockaddr_in *raddr;
+	u_long program;
+	u_long version;
+	struct timeval wait;
+	int *sockp;
+{
+
+	return clntudp_bufcreate(raddr, program, version, wait, sockp,
+					UDPMSGSIZE, UDPMSGSIZE);
+}
+
+CLIENT *
+clnttcp_create(raddr, prog, vers, sockp, sendsz, recvsz)
+	struct sockaddr_in *raddr;
+	u_long prog;
+	u_long vers;
+	int *sockp;
+	u_int sendsz;
+	u_int recvsz;
+{
+
+	return clnt_com_create(raddr, (rpcprog_t)prog, (rpcvers_t)vers, sockp,
+	    sendsz, recvsz, "tcp");
+}
+
+CLIENT *
+clntraw_create(prog, vers)
+	u_long prog;
+	u_long vers;
+{
+
+	return clnt_raw_create((rpcprog_t)prog, (rpcvers_t)vers);
+}
+
+/*
+ * A common server create routine
+ */
+static SVCXPRT *
+svc_com_create(fd, sendsize, recvsize, netid)
+	int fd;
+	u_int sendsize;
+	u_int recvsize;
+	char *netid;
+{
+	struct netconfig *nconf;
+	SVCXPRT *svc;
+	int madefd = FALSE;
+	int port;
+	struct sockaddr_in sin;
+
+	if ((nconf = __rpc_getconfip(netid)) == NULL) {
+		(void) syslog(LOG_ERR, "Could not get %s transport", netid);
+		return (NULL);
+	}
+	if (fd == RPC_ANYSOCK) {
+		fd = __rpc_nconf2fd(nconf);
+		if (fd == -1) {
+			(void) freenetconfigent(nconf);
+			(void) syslog(LOG_ERR,
+			"svc%s_create: could not open connection", netid);
+			return (NULL);
+		}
+		madefd = TRUE;
+	}
+
+	memset(&sin, 0, sizeof sin);
+	sin.sin_family = AF_INET;
+	bindresvport(fd, &sin);
+	_listen(fd, SOMAXCONN);
+	svc = svc_tli_create(fd, nconf, NULL, sendsize, recvsize);
+	(void) freenetconfigent(nconf);
+	if (svc == NULL) {
+		if (madefd)
+			(void)_close(fd);
+		return (NULL);
+	}
+	port = (((struct sockaddr_in *)svc->xp_ltaddr.buf)->sin_port);
+	svc->xp_port = ntohs(port);
+	return (svc);
+}
+
+SVCXPRT *
+svctcp_create(fd, sendsize, recvsize)
+	int fd;
+	u_int sendsize;
+	u_int recvsize;
+{
+
+	return svc_com_create(fd, sendsize, recvsize, "tcp");
+}
+
+SVCXPRT *
+svcudp_bufcreate(fd, sendsz, recvsz)
+	int fd;
+	u_int sendsz, recvsz;
+{
+
+	return svc_com_create(fd, sendsz, recvsz, "udp");
+}
+
+SVCXPRT *
+svcfd_create(fd, sendsize, recvsize)
+	int fd;
+	u_int sendsize;
+	u_int recvsize;
+{
+
+	return svc_fd_create(fd, sendsize, recvsize);
+}
+
+
+SVCXPRT *
+svcudp_create(fd)
+	int fd;
+{
+
+	return svc_com_create(fd, UDPMSGSIZE, UDPMSGSIZE, "udp");
+}
+
+SVCXPRT *
+svcraw_create()
+{
+
+	return svc_raw_create();
+}
+
+int
+get_myaddress(addr)
+	struct sockaddr_in *addr;
+{
+
+	memset((void *) addr, 0, sizeof(*addr));
+	addr->sin_family = AF_INET;
+	addr->sin_port = htons(PMAPPORT);
+	addr->sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+	return (0);
+}
+
+/*
+ * For connectionless "udp" transport. Obsoleted by rpc_call().
+ */
+int
+callrpc(host, prognum, versnum, procnum, inproc, in, outproc, out)
+	const char *host;
+	int prognum, versnum, procnum;
+	xdrproc_t inproc, outproc;
+	void *in, *out;
+{
+
+	return (int)rpc_call(host, (rpcprog_t)prognum, (rpcvers_t)versnum,
+	    (rpcproc_t)procnum, inproc, in, outproc, out, "udp");
+}
+
+/*
+ * For connectionless kind of transport. Obsoleted by rpc_reg()
+ */
+int
+registerrpc(prognum, versnum, procnum, progname, inproc, outproc)
+	int prognum, versnum, procnum;
+	char *(*progname)(char [UDPMSGSIZE]);
+	xdrproc_t inproc, outproc;
+{
+
+	return rpc_reg((rpcprog_t)prognum, (rpcvers_t)versnum,
+	    (rpcproc_t)procnum, progname, inproc, outproc, "udp");
+}
+
+/*
+ * All the following clnt_broadcast stuff is convulated; it supports
+ * the earlier calling style of the callback function
+ */
+static thread_key_t	clnt_broadcast_key;
+static resultproc_t	clnt_broadcast_result_main;
+static once_t		clnt_broadcast_once = ONCE_INITIALIZER;
+
+static void
+clnt_broadcast_key_init(void)
+{
+
+	thr_keycreate(&clnt_broadcast_key, free);
+}
+
+/*
+ * Need to translate the netbuf address into sockaddr_in address.
+ * Dont care about netid here.
+ */
+/* ARGSUSED */
+static bool_t
+rpc_wrap_bcast(resultp, addr, nconf)
+	char *resultp;		/* results of the call */
+	struct netbuf *addr;	/* address of the guy who responded */
+	struct netconfig *nconf; /* Netconf of the transport */
+{
+	resultproc_t clnt_broadcast_result;
+
+	if (strcmp(nconf->nc_netid, "udp"))
+		return (FALSE);
+	if (thr_main())
+		clnt_broadcast_result = clnt_broadcast_result_main;
+	else
+		clnt_broadcast_result = (resultproc_t)thr_getspecific(clnt_broadcast_key);
+	return (*clnt_broadcast_result)(resultp,
+				(struct sockaddr_in *)addr->buf);
+}
+
+/*
+ * Broadcasts on UDP transport. Obsoleted by rpc_broadcast().
+ */
+enum clnt_stat
+clnt_broadcast(prog, vers, proc, xargs, argsp, xresults, resultsp, eachresult)
+	u_long		prog;		/* program number */
+	u_long		vers;		/* version number */
+	u_long		proc;		/* procedure number */
+	xdrproc_t	xargs;		/* xdr routine for args */
+	void	       *argsp;		/* pointer to args */
+	xdrproc_t	xresults;	/* xdr routine for results */
+	void	       *resultsp;	/* pointer to results */
+	resultproc_t	eachresult;	/* call with each result obtained */
+{
+
+	if (thr_main())
+		clnt_broadcast_result_main = eachresult;
+	else {
+		thr_once(&clnt_broadcast_once, clnt_broadcast_key_init);
+		thr_setspecific(clnt_broadcast_key, (void *) eachresult);
+	}
+	return rpc_broadcast((rpcprog_t)prog, (rpcvers_t)vers,
+	    (rpcproc_t)proc, xargs, argsp, xresults, resultsp,
+	    (resultproc_t) rpc_wrap_bcast, "udp");
+}
+
+/*
+ * Create the client des authentication object. Obsoleted by
+ * authdes_seccreate().
+ */
+AUTH *
+authdes_create(servername, window, syncaddr, ckey)
+	char *servername;		/* network name of server */
+	u_int window;			/* time to live */
+	struct sockaddr *syncaddr;	/* optional hostaddr to sync with */
+	des_block *ckey;		/* optional conversation key to use */
+{
+	AUTH *dummy;
+	AUTH *nauth;
+	char hostname[NI_MAXHOST];
+
+	if (syncaddr) {
+		/*
+		 * Change addr to hostname, because that is the way
+		 * new interface takes it.
+		 */
+		if (getnameinfo(syncaddr, syncaddr->sa_len, hostname,
+		    sizeof hostname, NULL, 0, 0) != 0)
+			goto fallback;
+
+		nauth = authdes_seccreate(servername, window, hostname, ckey);
+		return (nauth);
+	}
+fallback:
+	dummy = authdes_seccreate(servername, window, NULL, ckey);
+	return (dummy);
+}
+
+/*
+ * Create a client handle for a unix connection. Obsoleted by clnt_vc_create()
+ */
+CLIENT *
+clntunix_create(raddr, prog, vers, sockp, sendsz, recvsz)
+	struct sockaddr_un *raddr;
+	u_long prog;
+	u_long vers;
+	int *sockp;
+	u_int sendsz;
+	u_int recvsz;
+{
+	struct netbuf *svcaddr;
+	struct netconfig *nconf;
+	CLIENT *cl;
+	int len;
+
+	cl = NULL;
+	nconf = NULL;
+	svcaddr = NULL;
+	if ((raddr->sun_len == 0) ||
+	   ((svcaddr = malloc(sizeof(struct netbuf))) == NULL ) ||
+	   ((svcaddr->buf = malloc(sizeof(struct sockaddr_un))) == NULL)) {
+		if (svcaddr != NULL)
+			free(svcaddr);
+		rpc_createerr.cf_stat = RPC_SYSTEMERROR;
+		rpc_createerr.cf_error.re_errno = errno;
+		return(cl);
+	}
+	if (*sockp < 0) {
+		*sockp = _socket(AF_LOCAL, SOCK_STREAM, 0);
+		len = raddr->sun_len = SUN_LEN(raddr);
+		if ((*sockp < 0) || (_connect(*sockp,
+		    (struct sockaddr *)raddr, len) < 0)) {
+			rpc_createerr.cf_stat = RPC_SYSTEMERROR;
+			rpc_createerr.cf_error.re_errno = errno;
+			if (*sockp != -1)
+				(void)_close(*sockp);
+			goto done;
+		}
+	}
+	svcaddr->buf = raddr;
+	svcaddr->len = raddr->sun_len;
+	svcaddr->maxlen = sizeof (struct sockaddr_un);
+	cl = clnt_vc_create(*sockp, svcaddr, prog,
+	    vers, sendsz, recvsz);
+done:
+	free(svcaddr->buf);
+	free(svcaddr);
+	return(cl);
+}
+
+/*
+ * Creates, registers, and returns a (rpc) unix based transporter.
+ * Obsoleted by svc_vc_create().
+ */
+SVCXPRT *
+svcunix_create(sock, sendsize, recvsize, path)
+	int sock;
+	u_int sendsize;
+	u_int recvsize;
+	char *path;
+{
+	struct netconfig *nconf;
+	void *localhandle;
+	struct sockaddr_un sun;
+	struct sockaddr *sa;
+	struct t_bind taddr;
+	SVCXPRT *xprt;
+	int addrlen;
+
+	xprt = (SVCXPRT *)NULL;
+	localhandle = setnetconfig();
+	while ((nconf = getnetconfig(localhandle)) != NULL) {
+		if (nconf->nc_protofmly != NULL &&
+		    strcmp(nconf->nc_protofmly, NC_LOOPBACK) == 0)
+			break;
+	}
+	if (nconf == NULL)
+		return(xprt);
+
+	if ((sock = __rpc_nconf2fd(nconf)) < 0)
+		goto done;
+
+	memset(&sun, 0, sizeof sun);
+	sun.sun_family = AF_LOCAL;
+	if (strlcpy(sun.sun_path, path, sizeof(sun.sun_path)) >=
+	    sizeof(sun.sun_path))
+		goto done;
+	sun.sun_len = SUN_LEN(&sun);
+	addrlen = sizeof (struct sockaddr_un);
+	sa = (struct sockaddr *)&sun;
+
+	if (_bind(sock, sa, addrlen) < 0)
+		goto done;
+
+	taddr.addr.len = taddr.addr.maxlen = addrlen;
+	taddr.addr.buf = malloc(addrlen);
+	if (taddr.addr.buf == NULL)
+		goto done;
+	memcpy(taddr.addr.buf, sa, addrlen);
+
+	if (nconf->nc_semantics != NC_TPI_CLTS) {
+		if (_listen(sock, SOMAXCONN) < 0) {
+			free(taddr.addr.buf);
+			goto done;
+		}
+	}
+
+	xprt = (SVCXPRT *)svc_tli_create(sock, nconf, &taddr, sendsize, recvsize);
+
+done:
+	endnetconfig(localhandle);
+	return(xprt);
+}
+
+/*
+ * Like svunix_create(), except the routine takes any *open* UNIX file
+ * descriptor as its first input. Obsoleted by svc_fd_create();
+ */
+SVCXPRT *
+svcunixfd_create(fd, sendsize, recvsize)
+	int fd;
+	u_int sendsize;
+	u_int recvsize;
+{
+ 	return (svc_fd_create(fd, sendsize, recvsize));
+}
+
+#endif /* PORTMAP */
Index: freebsd/lib/libc/rpc/rpcb_clnt.c
===================================================================
--- freebsd/lib/libc/rpc/rpcb_clnt.c	(revision 60b1d40751c8b3235b7ccbf3bb6ad0c562562f01)
+++ freebsd/lib/libc/rpc/rpcb_clnt.c	(revision 60b1d40751c8b3235b7ccbf3bb6ad0c562562f01)
@@ -0,0 +1,1342 @@
+#include <machine/rtems-bsd-user-space.h>
+
+/*	$NetBSD: rpcb_clnt.c,v 1.6 2000/07/16 06:41:43 itojun Exp $	*/
+
+/*-
+ * Copyright (c) 2010, Oracle America, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice,
+ *   this list of conditions and the following disclaimer in the documentation
+ *   and/or other materials provided with the distribution.
+ * - Neither the name of the "Oracle America, Inc." nor the names of its
+ *   contributors may be used to endorse or promote products derived
+ *   from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* #ident	"@(#)rpcb_clnt.c	1.27	94/04/24 SMI" */
+
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)rpcb_clnt.c 1.30 89/06/21 Copyr 1988 Sun Micro";
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * rpcb_clnt.c
+ * interface to rpcbind rpc service.
+ */
+
+#include "namespace.h"
+#include "reentrant.h"
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/utsname.h>
+#include <rpc/rpc.h>
+#include <rpc/rpcb_prot.h>
+#include <rpc/nettype.h>
+#include <netconfig.h>
+#ifdef PORTMAP
+#include <netinet/in.h>		/* FOR IPPROTO_TCP/UDP definitions */
+#include <rpc/pmap_prot.h>
+#endif				/* PORTMAP */
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <netdb.h>
+#include <syslog.h>
+#include "un-namespace.h"
+
+#include "rpc_com.h"
+#include "mt_misc.h"
+
+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 **);
+
+static const char nullstring[] = "\000";
+
+#define	CACHESIZE 6
+
+struct address_cache {
+	char *ac_host;
+	char *ac_netid;
+	char *ac_uaddr;
+	struct netbuf *ac_taddr;
+	struct address_cache *ac_next;
+};
+
+static struct address_cache *front;
+static int cachesize;
+
+#define	CLCR_GET_RPCB_TIMEOUT	1
+#define	CLCR_SET_RPCB_TIMEOUT	2
+
+
+extern int __rpc_lowvers;
+
+static struct address_cache *check_cache(const char *, const char *);
+static void delete_cache(struct netbuf *);
+static void add_cache(const char *, const char *, struct netbuf *, char *);
+static CLIENT *getclnthandle(const char *, const struct netconfig *, char **);
+static CLIENT *local_rpcb(void);
+static struct netbuf *got_entry(rpcb_entry_list_ptr, const struct netconfig *);
+
+/*
+ * This routine adjusts the timeout used for calls to the remote rpcbind.
+ * Also, this routine can be used to set the use of portmapper version 2
+ * only when doing rpc_broadcasts
+ * These are private routines that may not be provided in future releases.
+ */
+bool_t
+__rpc_control(request, info)
+	int	request;
+	void	*info;
+{
+	switch (request) {
+	case CLCR_GET_RPCB_TIMEOUT:
+		*(struct timeval *)info = tottimeout;
+		break;
+	case CLCR_SET_RPCB_TIMEOUT:
+		tottimeout = *(struct timeval *)info;
+		break;
+	case CLCR_SET_LOWVERS:
+		__rpc_lowvers = *(int *)info;
+		break;
+	case CLCR_GET_LOWVERS:
+		*(int *)info = __rpc_lowvers;
+		break;
+	default:
+		return (FALSE);
+	}
+	return (TRUE);
+}
+
+/*
+ *	It might seem that a reader/writer lock would be more reasonable here.
+ *	However because getclnthandle(), the only user of the cache functions,
+ *	may do a delete_cache() operation if a check_cache() fails to return an
+ *	address useful to clnt_tli_create(), we may as well use a mutex.
+ */
+/*
+ * As it turns out, if the cache lock is *not* a reader/writer lock, we will
+ * block all clnt_create's if we are trying to connect to a host that's down,
+ * since the lock will be held all during that time.
+ */
+
+/*
+ * The routines check_cache(), add_cache(), delete_cache() manage the
+ * cache of rpcbind addresses for (host, netid).
+ */
+
+static struct address_cache *
+check_cache(host, netid)
+	const char *host, *netid;
+{
+	struct address_cache *cptr;
+
+	/* READ LOCK HELD ON ENTRY: rpcbaddr_cache_lock */
+
+	for (cptr = front; cptr != NULL; cptr = cptr->ac_next) {
+		if (!strcmp(cptr->ac_host, host) &&
+		    !strcmp(cptr->ac_netid, netid)) {
+#ifdef ND_DEBUG
+			fprintf(stderr, "Found cache entry for %s: %s\n",
+				host, netid);
+#endif
+			return (cptr);
+		}
+	}
+	return ((struct address_cache *) NULL);
+}
+
+static void
+delete_cache(addr)
+	struct netbuf *addr;
+{
+	struct address_cache *cptr, *prevptr = NULL;
+
+	/* WRITE LOCK HELD ON ENTRY: rpcbaddr_cache_lock */
+	for (cptr = front; cptr != NULL; cptr = cptr->ac_next) {
+		if (!memcmp(cptr->ac_taddr->buf, addr->buf, addr->len)) {
+			free(cptr->ac_host);
+			free(cptr->ac_netid);
+			free(cptr->ac_taddr->buf);
+			free(cptr->ac_taddr);
+			if (cptr->ac_uaddr)
+				free(cptr->ac_uaddr);
+			if (prevptr)
+				prevptr->ac_next = cptr->ac_next;
+			else
+				front = cptr->ac_next;
+			free(cptr);
+			cachesize--;
+			break;
+		}
+		prevptr = cptr;
+	}
+}
+
+static void
+add_cache(host, netid, taddr, uaddr)
+	const char *host, *netid;
+	char *uaddr;
+	struct netbuf *taddr;
+{
+	struct address_cache  *ad_cache, *cptr, *prevptr;
+
+	ad_cache = (struct address_cache *)
+			malloc(sizeof (struct address_cache));
+	if (!ad_cache) {
+		return;
+	}
+	ad_cache->ac_host = strdup(host);
+	ad_cache->ac_netid = strdup(netid);
+	ad_cache->ac_uaddr = uaddr ? strdup(uaddr) : NULL;
+	ad_cache->ac_taddr = (struct netbuf *)malloc(sizeof (struct netbuf));
+	if (!ad_cache->ac_host || !ad_cache->ac_netid || !ad_cache->ac_taddr ||
+		(uaddr && !ad_cache->ac_uaddr)) {
+		goto out;
+	}
+	ad_cache->ac_taddr->len = ad_cache->ac_taddr->maxlen = taddr->len;
+	ad_cache->ac_taddr->buf = (char *) malloc(taddr->len);
+	if (ad_cache->ac_taddr->buf == NULL) {
+out:
+		if (ad_cache->ac_host)
+			free(ad_cache->ac_host);
+		if (ad_cache->ac_netid)
+			free(ad_cache->ac_netid);
+		if (ad_cache->ac_uaddr)
+			free(ad_cache->ac_uaddr);
+		if (ad_cache->ac_taddr)
+			free(ad_cache->ac_taddr);
+		free(ad_cache);
+		return;
+	}
+	memcpy(ad_cache->ac_taddr->buf, taddr->buf, taddr->len);
+#ifdef ND_DEBUG
+	fprintf(stderr, "Added to cache: %s : %s\n", host, netid);
+#endif
+
+/* VARIABLES PROTECTED BY rpcbaddr_cache_lock:  cptr */
+
+	rwlock_wrlock(&rpcbaddr_cache_lock);
+	if (cachesize < CACHESIZE) {
+		ad_cache->ac_next = front;
+		front = ad_cache;
+		cachesize++;
+	} else {
+		/* Free the last entry */
+		cptr = front;
+		prevptr = NULL;
+		while (cptr->ac_next) {
+			prevptr = cptr;
+			cptr = cptr->ac_next;
+		}
+
+#ifdef ND_DEBUG
+		fprintf(stderr, "Deleted from cache: %s : %s\n",
+			cptr->ac_host, cptr->ac_netid);
+#endif
+		free(cptr->ac_host);
+		free(cptr->ac_netid);
+		free(cptr->ac_taddr->buf);
+		free(cptr->ac_taddr);
+		if (cptr->ac_uaddr)
+			free(cptr->ac_uaddr);
+
+		if (prevptr) {
+			prevptr->ac_next = NULL;
+			ad_cache->ac_next = front;
+			front = ad_cache;
+		} else {
+			front = ad_cache;
+			ad_cache->ac_next = NULL;
+		}
+		free(cptr);
+	}
+	rwlock_unlock(&rpcbaddr_cache_lock);
+}
+
+/*
+ * This routine will return a client handle that is connected to the
+ * rpcbind. If targaddr is non-NULL, the "universal address" of the
+ * host will be stored in *targaddr; the caller is responsible for
+ * freeing this string.
+ * On error, returns NULL and free's everything.
+ */
+static CLIENT *
+getclnthandle(host, nconf, targaddr)
+	const char *host;
+	const struct netconfig *nconf;
+	char **targaddr;
+{
+	CLIENT *client;
+	struct netbuf *addr, taddr;
+	struct netbuf addr_to_delete;
+	struct __rpc_sockinfo si;
+	struct addrinfo hints, *res, *tres;
+	struct address_cache *ad_cache;
+	char *tmpaddr;
+
+/* VARIABLES PROTECTED BY rpcbaddr_cache_lock:  ad_cache */
+
+	/* Get the address of the rpcbind.  Check cache first */
+	client = NULL;
+	addr_to_delete.len = 0;
+	rwlock_rdlock(&rpcbaddr_cache_lock);
+	ad_cache = NULL;
+	if (host != NULL)
+		ad_cache = check_cache(host, nconf->nc_netid);
+	if (ad_cache != NULL) {
+		addr = ad_cache->ac_taddr;
+		client = clnt_tli_create(RPC_ANYFD, nconf, addr,
+		    (rpcprog_t)RPCBPROG, (rpcvers_t)RPCBVERS4, 0, 0);
+		if (client != NULL) {
+			if (targaddr)
+				*targaddr = strdup(ad_cache->ac_uaddr);
+			rwlock_unlock(&rpcbaddr_cache_lock);
+			return (client);
+		}
+		addr_to_delete.len = addr->len;
+		addr_to_delete.buf = (char *)malloc(addr->len);
+		if (addr_to_delete.buf == NULL) {
+			addr_to_delete.len = 0;
+		} else {
+			memcpy(addr_to_delete.buf, addr->buf, addr->len);
+		}
+	}
+	rwlock_unlock(&rpcbaddr_cache_lock);
+	if (addr_to_delete.len != 0) {
+		/*
+		 * Assume this may be due to cache data being
+		 *  outdated
+		 */
+		rwlock_wrlock(&rpcbaddr_cache_lock);
+		delete_cache(&addr_to_delete);
+		rwlock_unlock(&rpcbaddr_cache_lock);
+		free(addr_to_delete.buf);
+	}
+	if (!__rpc_nconf2sockinfo(nconf, &si)) {
+		rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
+		return NULL;
+	}
+
+	memset(&hints, 0, sizeof hints);
+	hints.ai_family = si.si_af;
+	hints.ai_socktype = si.si_socktype;
+	hints.ai_protocol = si.si_proto;
+
+#ifdef CLNT_DEBUG
+	printf("trying netid %s family %d proto %d socktype %d\n",
+	    nconf->nc_netid, si.si_af, si.si_proto, si.si_socktype);
+#endif
+
+	if (nconf->nc_protofmly != NULL && strcmp(nconf->nc_protofmly, NC_LOOPBACK) == 0) {
+		client = local_rpcb();
+		if (! client) {
+#ifdef ND_DEBUG
+			clnt_pcreateerror("rpcbind clnt interface");
+#endif
+			return (NULL);
+		} else {
+			struct sockaddr_un sun;
+			if (targaddr) {
+			    *targaddr = malloc(sizeof(sun.sun_path));
+			    if (*targaddr == NULL) {
+				CLNT_DESTROY(client);
+				return (NULL);
+			    }
+			    strncpy(*targaddr, _PATH_RPCBINDSOCK,
+				sizeof(sun.sun_path));
+			}
+			return (client);
+		}
+	} else {
+		if (getaddrinfo(host, "sunrpc", &hints, &res) != 0) {
+			rpc_createerr.cf_stat = RPC_UNKNOWNHOST;
+			return NULL;
+		}
+	}
+
+	for (tres = res; tres != NULL; tres = tres->ai_next) {
+		taddr.buf = tres->ai_addr;
+		taddr.len = taddr.maxlen = tres->ai_addrlen;
+
+#ifdef ND_DEBUG
+		{
+			char *ua;
+
+			ua = taddr2uaddr(nconf, &taddr);
+			fprintf(stderr, "Got it [%s]\n", ua);
+			free(ua);
+		}
+#endif
+
+#ifdef ND_DEBUG
+		{
+			int i;
+
+			fprintf(stderr, "\tnetbuf len = %d, maxlen = %d\n",
+				taddr.len, taddr.maxlen);
+			fprintf(stderr, "\tAddress is ");
+			for (i = 0; i < taddr.len; i++)
+				fprintf(stderr, "%u.", ((char *)(taddr.buf))[i]);
+			fprintf(stderr, "\n");
+		}
+#endif
+		client = clnt_tli_create(RPC_ANYFD, nconf, &taddr,
+		    (rpcprog_t)RPCBPROG, (rpcvers_t)RPCBVERS4, 0, 0);
+#ifdef ND_DEBUG
+		if (! client) {
+			clnt_pcreateerror("rpcbind clnt interface");
+		}
+#endif
+
+		if (client) {
+			tmpaddr = targaddr ? taddr2uaddr(nconf, &taddr) : NULL;
+			add_cache(host, nconf->nc_netid, &taddr, tmpaddr);
+			if (targaddr)
+				*targaddr = tmpaddr;
+			break;
+		}
+	}
+	if (res)
+		freeaddrinfo(res);
+	return (client);
+}
+
+/* XXX */
+#define IN4_LOCALHOST_STRING	"127.0.0.1"
+#define IN6_LOCALHOST_STRING	"::1"
+
+/*
+ * This routine will return a client handle that is connected to the local
+ * rpcbind. Returns NULL on error and free's everything.
+ */
+static CLIENT *
+local_rpcb()
+{
+	CLIENT *client;
+	static struct netconfig *loopnconf;
+	static char *hostname;
+	int sock;
+	size_t tsize;
+	struct netbuf nbuf;
+	struct sockaddr_un sun;
+
+	/*
+	 * Try connecting to the local rpcbind through a local socket
+	 * first. If this doesn't work, try all transports defined in
+	 * the netconfig file.
+	 */
+	memset(&sun, 0, sizeof sun);
+	sock = _socket(AF_LOCAL, SOCK_STREAM, 0);
+	if (sock < 0)
+		goto try_nconf;
+	sun.sun_family = AF_LOCAL;
+	strcpy(sun.sun_path, _PATH_RPCBINDSOCK);
+	nbuf.len = sun.sun_len = SUN_LEN(&sun);
+	nbuf.maxlen = sizeof (struct sockaddr_un);
+	nbuf.buf = &sun;
+
+	tsize = __rpc_get_t_size(AF_LOCAL, 0, 0);
+	client = clnt_vc_create(sock, &nbuf, (rpcprog_t)RPCBPROG,
+	    (rpcvers_t)RPCBVERS, tsize, tsize);
+
+	if (client != NULL) {
+		/* Mark the socket to be closed in destructor */
+		(void) CLNT_CONTROL(client, CLSET_FD_CLOSE, NULL);
+		return client;
+	}
+
+	/* Nobody needs this socket anymore; free the descriptor. */
+	_close(sock);
+
+try_nconf:
+
+/* VARIABLES PROTECTED BY loopnconf_lock: loopnconf */
+	mutex_lock(&loopnconf_lock);
+	if (loopnconf == NULL) {
+		struct netconfig *nconf, *tmpnconf = NULL;
+		void *nc_handle;
+		int fd;
+
+		nc_handle = setnetconfig();
+		if (nc_handle == NULL) {
+			/* fails to open netconfig file */
+			syslog (LOG_ERR, "rpc: failed to open " NETCONFIG);
+			rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
+			mutex_unlock(&loopnconf_lock);
+			return (NULL);
+		}
+		while ((nconf = getnetconfig(nc_handle)) != NULL) {
+#ifdef INET6
+			if ((strcmp(nconf->nc_protofmly, NC_INET6) == 0 ||
+#else
+			if ((
+#endif
+			     strcmp(nconf->nc_protofmly, NC_INET) == 0) &&
+			    (nconf->nc_semantics == NC_TPI_COTS ||
+			     nconf->nc_semantics == NC_TPI_COTS_ORD)) {
+				fd = __rpc_nconf2fd(nconf);
+				/*
+				 * Can't create a socket, assume that
+				 * this family isn't configured in the kernel.
+				 */
+				if (fd < 0)
+					continue;
+				_close(fd);
+				tmpnconf = nconf;
+				if (!strcmp(nconf->nc_protofmly, NC_INET))
+					hostname = IN4_LOCALHOST_STRING;
+				else
+					hostname = IN6_LOCALHOST_STRING;
+			}
+		}
+		if (tmpnconf == NULL) {
+			rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
+			mutex_unlock(&loopnconf_lock);
+			return (NULL);
+		}
+		loopnconf = getnetconfigent(tmpnconf->nc_netid);
+		/* loopnconf is never freed */
+		endnetconfig(nc_handle);
+	}
+	mutex_unlock(&loopnconf_lock);
+	client = getclnthandle(hostname, loopnconf, NULL);
+	return (client);
+}
+
+/*
+ * Set a mapping between program, version and address.
+ * Calls the rpcbind service to do the mapping.
+ */
+bool_t
+rpcb_set(program, version, nconf, address)
+	rpcprog_t program;
+	rpcvers_t version;
+	const struct netconfig *nconf;	/* Network structure of transport */
+	const struct netbuf *address;		/* Services netconfig address */
+{
+	CLIENT *client;
+	bool_t rslt = FALSE;
+	RPCB parms;
+	char uidbuf[32];
+
+	/* parameter checking */
+	if (nconf == NULL) {
+		rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
+		return (FALSE);
+	}
+	if (address == NULL) {
+		rpc_createerr.cf_stat = RPC_UNKNOWNADDR;
+		return (FALSE);
+	}
+	client = local_rpcb();
+	if (! client) {
+		return (FALSE);
+	}
+
+	/* convert to universal */
+	/*LINTED const castaway*/
+	parms.r_addr = taddr2uaddr((struct netconfig *) nconf,
+				   (struct netbuf *)address);
+	if (!parms.r_addr) {
+		CLNT_DESTROY(client);
+		rpc_createerr.cf_stat = RPC_N2AXLATEFAILURE;
+		return (FALSE); /* no universal address */
+	}
+	parms.r_prog = program;
+	parms.r_vers = version;
+	parms.r_netid = nconf->nc_netid;
+	/*
+	 * Though uid is not being used directly, we still send it for
+	 * completeness.  For non-unix platforms, perhaps some other
+	 * string or an empty string can be sent.
+	 */
+	(void) snprintf(uidbuf, sizeof uidbuf, "%d", geteuid());
+	parms.r_owner = uidbuf;
+
+	CLNT_CALL(client, (rpcproc_t)RPCBPROC_SET, (xdrproc_t) xdr_rpcb,
+	    (char *)(void *)&parms, (xdrproc_t) xdr_bool,
+	    (char *)(void *)&rslt, tottimeout);
+
+	CLNT_DESTROY(client);
+	free(parms.r_addr);
+	return (rslt);
+}
+
+/*
+ * Remove the mapping between program, version and netbuf address.
+ * Calls the rpcbind service to do the un-mapping.
+ * If netbuf is NULL, unset for all the transports, otherwise unset
+ * only for the given transport.
+ */
+bool_t
+rpcb_unset(program, version, nconf)
+	rpcprog_t program;
+	rpcvers_t version;
+	const struct netconfig *nconf;
+{
+	CLIENT *client;
+	bool_t rslt = FALSE;
+	RPCB parms;
+	char uidbuf[32];
+
+	client = local_rpcb();
+	if (! client) {
+		return (FALSE);
+	}
+
+	parms.r_prog = program;
+	parms.r_vers = version;
+	if (nconf)
+		parms.r_netid = nconf->nc_netid;
+	else {
+		/*LINTED const castaway*/
+		parms.r_netid = (char *) &nullstring[0]; /* unsets  all */
+	}
+	/*LINTED const castaway*/
+	parms.r_addr = (char *) &nullstring[0];
+	(void) snprintf(uidbuf, sizeof uidbuf, "%d", geteuid());
+	parms.r_owner = uidbuf;
+
+	CLNT_CALL(client, (rpcproc_t)RPCBPROC_UNSET, (xdrproc_t) xdr_rpcb,
+	    (char *)(void *)&parms, (xdrproc_t) xdr_bool,
+	    (char *)(void *)&rslt, tottimeout);
+
+	CLNT_DESTROY(client);
+	return (rslt);
+}
+
+/*
+ * From the merged list, find the appropriate entry
+ */
+static struct netbuf *
+got_entry(relp, nconf)
+	rpcb_entry_list_ptr relp;
+	const struct netconfig *nconf;
+{
+	struct netbuf *na = NULL;
+	rpcb_entry_list_ptr sp;
+	rpcb_entry *rmap;
+
+	for (sp = relp; sp != NULL; sp = sp->rpcb_entry_next) {
+		rmap = &sp->rpcb_entry_map;
+		if ((strcmp(nconf->nc_proto, rmap->r_nc_proto) == 0) &&
+		    (strcmp(nconf->nc_protofmly, rmap->r_nc_protofmly) == 0) &&
+		    (nconf->nc_semantics == rmap->r_nc_semantics) &&
+		    (rmap->r_maddr != NULL) && (rmap->r_maddr[0] != 0)) {
+			na = uaddr2taddr(nconf, rmap->r_maddr);
+#ifdef ND_DEBUG
+			fprintf(stderr, "\tRemote address is [%s].\n",
+				rmap->r_maddr);
+			if (!na)
+				fprintf(stderr,
+				    "\tCouldn't resolve remote address!\n");
+#endif
+			break;
+		}
+	}
+	return (na);
+}
+
+/*
+ * Quick check to see if rpcbind is up.  Tries to connect over
+ * local transport.
+ */
+static bool_t
+__rpcbind_is_up()
+{
+	struct netconfig *nconf;
+	struct sockaddr_un sun;
+	void *localhandle;
+	int sock;
+
+	nconf = NULL;
+	localhandle = setnetconfig();
+	while ((nconf = getnetconfig(localhandle)) != NULL) {
+		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.
+ *
+ * The algorithm used: If the transports is TCP or UDP, it first tries
+ * version 2 (portmap), 4 and then 3 (svr4).  This order should be
+ * changed in the next OS release to 4, 2 and 3.  We are assuming that by
+ * that time, version 4 would be available on many machines on the network.
+ * With this algorithm, we get performance as well as a plan for
+ * obsoleting version 2.
+ *
+ * For all other transports, the algorithm remains as 4 and then 3.
+ *
+ * XXX: Due to some problems with t_connect(), we do not reuse the same client
+ * handle for COTS cases and hence in these cases we do not return the
+ * client handle.  This code will change if t_connect() ever
+ * starts working properly.  Also look under clnt_vc.c.
+ */
+struct netbuf *
+__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;
+	char *ua = NULL;
+	rpcvers_t vers;
+	struct netbuf *address = NULL;
+	rpcvers_t start_vers = RPCBVERS4;
+	struct netbuf servaddr;
+
+	/* parameter checking */
+	if (nconf == NULL) {
+		rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
+		return (NULL);
+	}
+
+	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) {
+		u_short port = 0;
+		struct netbuf remote;
+		rpcvers_t pmapvers = 2;
+		struct pmap pmapparms;
+
+		/*
+		 * Try UDP only - there are some portmappers out
+		 * there that use UDP only.
+		 */
+		if (strcmp(nconf->nc_proto, NC_TCP) == 0) {
+			struct netconfig *newnconf;
+
+			if ((newnconf = getnetconfigent("udp")) == NULL) {
+				rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
+				return (NULL);
+			}
+			client = getclnthandle(host, newnconf, &parms.r_addr);
+			freenetconfigent(newnconf);
+		} else {
+			client = getclnthandle(host, nconf, &parms.r_addr);
+		}
+		if (client == NULL)
+			return (NULL);
+
+		/*
+		 * 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) ?
+					IPPROTO_UDP : IPPROTO_TCP;
+		pmapparms.pm_port = 0;	/* not needed */
+		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,
+		    *tp);
+		if (clnt_st != RPC_SUCCESS) {
+			if ((clnt_st == RPC_PROGVERSMISMATCH) ||
+				(clnt_st == RPC_PROGUNAVAIL))
+				goto try_rpcbind; /* Try different versions */
+			rpc_createerr.cf_stat = RPC_PMAPFAILURE;
+			clnt_geterr(client, &rpc_createerr.cf_error);
+			goto error;
+		} else if (port == 0) {
+			address = NULL;
+			rpc_createerr.cf_stat = RPC_PROGNOTREGISTERED;
+			goto error;
+		}
+		port = htons(port);
+		CLNT_CONTROL(client, CLGET_SVC_ADDR, (char *)&remote);
+		if (((address = (struct netbuf *)
+			malloc(sizeof (struct netbuf))) == NULL) ||
+		    ((address->buf = (char *)
+			malloc(remote.len)) == NULL)) {
+			rpc_createerr.cf_stat = RPC_SYSTEMERROR;
+			clnt_geterr(client, &rpc_createerr.cf_error);
+			if (address) {
+				free(address);
+				address = NULL;
+			}
+			goto error;
+		}
+		memcpy(address->buf, remote.buf, remote.len);
+		memcpy(&((char *)address->buf)[sizeof (short)],
+				(char *)(void *)&port, sizeof (short));
+		address->len = address->maxlen = remote.len;
+		goto done;
+	}
+#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
+	 * contact it in case it can help to connect back with us
+	 */
+	parms.r_prog = program;
+	parms.r_vers = version;
+	/*LINTED const castaway*/
+	parms.r_owner = (char *) &nullstring[0];	/* not needed; */
+							/* just for xdring */
+	parms.r_netid = nconf->nc_netid; /* not really needed */
+
+	/*
+	 * If a COTS transport is being used, try getting address via CLTS
+	 * transport.  This works only with version 4.
+	 */
+	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 ((handle = __rpc_setconf("datagram_v")) != NULL) {
+				while ((nconf_clts = __rpc_getconf(handle))
+					!= NULL) {
+					if (strcmp(nconf_clts->nc_protofmly,
+						nconf->nc_protofmly) != 0) {
+						continue;
+					}
+					client = getclnthandle(host, nconf_clts,
+							&parms.r_addr);
+					break;
+				}
+				__rpc_endconf(handle);
+			}
+			if (client == NULL)
+				goto regular_rpcbind;	/* Go the regular way */
+		} else {
+			/* This is a UDP PORTMAP handle.  Change to version 4 */
+			vers = RPCBVERS4;
+			CLNT_CONTROL(client, CLSET_VERS, (char *)(void *)&vers);
+		}
+		/*
+		 * We also send the remote system the address we used to
+		 * contact it in case it can help it connect back with us
+		 */
+		if (parms.r_addr == NULL) {
+			/*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, *tp);
+		if (clnt_st == RPC_SUCCESS) {
+			if ((address = got_entry(relp, nconf)) != NULL) {
+				xdr_free((xdrproc_t) xdr_rpcb_entry_list_ptr,
+				    (char *)(void *)&relp);
+				CLNT_CONTROL(client, CLGET_SVC_ADDR,
+					(char *)(void *)&servaddr);
+				__rpc_fixup_addr(address, &servaddr);
+				goto done;
+			}
+			/* Entry not found for this transport */
+			xdr_free((xdrproc_t) xdr_rpcb_entry_list_ptr,
+			    (char *)(void *)&relp);
+			/*
+			 * XXX: should have perhaps returned with error but
+			 * since the remote machine might not always be able
+			 * to send the address on all transports, we try the
+			 * regular way with regular_rpcbind
+			 */
+			goto regular_rpcbind;
+		} else if ((clnt_st == RPC_PROGVERSMISMATCH) ||
+			(clnt_st == RPC_PROGUNAVAIL)) {
+			start_vers = RPCBVERS;	/* Try version 3 now */
+			goto regular_rpcbind; /* Try different versions */
+		} else {
+			rpc_createerr.cf_stat = RPC_PMAPFAILURE;
+			clnt_geterr(client, &rpc_createerr.cf_error);
+			goto error;
+		}
+	}
+
+regular_rpcbind:
+
+	/* Now the same transport is to be used to get the address */
+	if (client && ((nconf->nc_semantics == NC_TPI_COTS_ORD) ||
+			(nconf->nc_semantics == NC_TPI_COTS))) {
+		/* A CLTS type of client - destroy it */
+		CLNT_DESTROY(client);
+		client = NULL;
+	}
+
+	if (client == NULL) {
+		client = getclnthandle(host, nconf, &parms.r_addr);
+		if (client == NULL) {
+			goto error;
+		}
+	}
+	if (parms.r_addr == NULL) {
+		/*LINTED const castaway*/
+		parms.r_addr = (char *) &nullstring[0];
+	}
+
+	/* 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, *tp);
+		if (clnt_st == RPC_SUCCESS) {
+			if ((ua == NULL) || (ua[0] == 0)) {
+				/* address unknown */
+				rpc_createerr.cf_stat = RPC_PROGNOTREGISTERED;
+				goto error;
+			}
+			address = uaddr2taddr(nconf, ua);
+#ifdef ND_DEBUG
+			fprintf(stderr, "\tRemote address is [%s]\n", ua);
+			if (!address)
+				fprintf(stderr,
+					"\tCouldn't resolve remote address!\n");
+#endif
+			xdr_free((xdrproc_t)xdr_wrapstring,
+			    (char *)(void *)&ua);
+
+			if (! address) {
+				/* We don't know about your universal address */
+				rpc_createerr.cf_stat = RPC_N2AXLATEFAILURE;
+				goto error;
+			}
+			CLNT_CONTROL(client, CLGET_SVC_ADDR,
+			    (char *)(void *)&servaddr);
+			__rpc_fixup_addr(address, &servaddr);
+			goto done;
+		} else if (clnt_st == RPC_PROGVERSMISMATCH) {
+			struct rpc_err rpcerr;
+
+			clnt_geterr(client, &rpcerr);
+			if (rpcerr.re_vers.low > RPCBVERS4)
+				goto error;  /* a new version, can't handle */
+		} else if (clnt_st != RPC_PROGUNAVAIL) {
+			/* Cant handle this error */
+			rpc_createerr.cf_stat = clnt_st;
+			clnt_geterr(client, &rpc_createerr.cf_error);
+			goto error;
+		}
+	}
+
+error:
+	if (client) {
+		CLNT_DESTROY(client);
+		client = NULL;
+	}
+done:
+	if (nconf->nc_semantics != NC_TPI_CLTS) {
+		/* This client is the connectionless one */
+		if (client) {
+			CLNT_DESTROY(client);
+			client = NULL;
+		}
+	}
+	if (clpp) {
+		*clpp = client;
+	} else if (client) {
+		CLNT_DESTROY(client);
+	}
+	if (parms.r_addr != NULL && parms.r_addr != nullstring)
+		free(parms.r_addr);
+	return (address);
+}
+
+
+/*
+ * Find the mapped address for program, version.
+ * Calls the rpcbind service remotely to do the lookup.
+ * Uses the transport specified in nconf.
+ * Returns FALSE (0) if no map exists, else returns 1.
+ *
+ * Assuming that the address is all properly allocated
+ */
+int
+rpcb_getaddr(program, version, nconf, address, host)
+	rpcprog_t program;
+	rpcvers_t version;
+	const struct netconfig *nconf;
+	struct netbuf *address;
+	const char *host;
+{
+	struct netbuf *na;
+
+	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) {
+		/* Too long address */
+		free(na->buf);
+		free(na);
+		rpc_createerr.cf_stat = RPC_FAILED;
+		return (FALSE);
+	}
+	memcpy(address->buf, na->buf, (size_t)na->len);
+	address->len = na->len;
+	free(na->buf);
+	free(na);
+	return (TRUE);
+}
+
+/*
+ * Get a copy of the current maps.
+ * Calls the rpcbind service remotely to get the maps.
+ *
+ * It returns only a list of the services
+ * It returns NULL on failure.
+ */
+rpcblist *
+rpcb_getmaps(nconf, host)
+	const struct netconfig *nconf;
+	const char *host;
+{
+	rpcblist_ptr head = NULL;
+	CLIENT *client;
+	enum clnt_stat clnt_st;
+	rpcvers_t vers = 0;
+
+	client = getclnthandle(host, nconf, NULL);
+	if (client == NULL) {
+		return (head);
+	}
+	clnt_st = CLNT_CALL(client, (rpcproc_t)RPCBPROC_DUMP,
+	    (xdrproc_t) xdr_void, NULL, (xdrproc_t) xdr_rpcblist_ptr,
+	    (char *)(void *)&head, tottimeout);
+	if (clnt_st == RPC_SUCCESS)
+		goto done;
+
+	if ((clnt_st != RPC_PROGVERSMISMATCH) &&
+	    (clnt_st != RPC_PROGUNAVAIL)) {
+		rpc_createerr.cf_stat = RPC_RPCBFAILURE;
+		clnt_geterr(client, &rpc_createerr.cf_error);
+		goto done;
+	}
+
+	/* fall back to earlier version */
+	CLNT_CONTROL(client, CLGET_VERS, (char *)(void *)&vers);
+	if (vers == RPCBVERS4) {
+		vers = RPCBVERS;
+		CLNT_CONTROL(client, CLSET_VERS, (char *)(void *)&vers);
+		if (CLNT_CALL(client, (rpcproc_t)RPCBPROC_DUMP,
+		    (xdrproc_t) xdr_void, NULL, (xdrproc_t) xdr_rpcblist_ptr,
+		    (char *)(void *)&head, tottimeout) == RPC_SUCCESS)
+			goto done;
+	}
+	rpc_createerr.cf_stat = RPC_RPCBFAILURE;
+	clnt_geterr(client, &rpc_createerr.cf_error);
+
+done:
+	CLNT_DESTROY(client);
+	return (head);
+}
+
+/*
+ * rpcbinder remote-call-service interface.
+ * This routine is used to call the rpcbind remote call service
+ * which will look up a service program in the address maps, and then
+ * remotely call that routine with the given parameters. This allows
+ * programs to do a lookup and call in one step.
+*/
+enum clnt_stat
+rpcb_rmtcall(nconf, host, prog, vers, proc, xdrargs, argsp,
+		xdrres, resp, tout, addr_ptr)
+	const struct netconfig *nconf;	/* Netconfig structure */
+	const char *host;			/* Remote host name */
+	rpcprog_t prog;
+	rpcvers_t vers;
+	rpcproc_t proc;			/* Remote proc identifiers */
+	xdrproc_t xdrargs, xdrres;	/* XDR routines */
+	caddr_t argsp, resp;		/* Argument and Result */
+	struct timeval tout;		/* Timeout value for this call */
+	const struct netbuf *addr_ptr;	/* Preallocated netbuf address */
+{
+	CLIENT *client;
+	enum clnt_stat stat;
+	struct r_rpcb_rmtcallargs a;
+	struct r_rpcb_rmtcallres r;
+	rpcvers_t rpcb_vers;
+
+	stat = 0;
+	client = getclnthandle(host, nconf, NULL);
+	if (client == NULL) {
+		return (RPC_FAILED);
+	}
+	/*LINTED const castaway*/
+	CLNT_CONTROL(client, CLSET_RETRY_TIMEOUT, (char *)(void *)&rmttimeout);
+	a.prog = prog;
+	a.vers = vers;
+	a.proc = proc;
+	a.args.args_val = argsp;
+	a.xdr_args = xdrargs;
+	r.addr = NULL;
+	r.results.results_val = resp;
+	r.xdr_res = xdrres;
+
+	for (rpcb_vers = RPCBVERS4; rpcb_vers >= RPCBVERS; rpcb_vers--) {
+		CLNT_CONTROL(client, CLSET_VERS, (char *)(void *)&rpcb_vers);
+		stat = CLNT_CALL(client, (rpcproc_t)RPCBPROC_CALLIT,
+		    (xdrproc_t) xdr_rpcb_rmtcallargs, (char *)(void *)&a,
+		    (xdrproc_t) xdr_rpcb_rmtcallres, (char *)(void *)&r, tout);
+		if ((stat == RPC_SUCCESS) && (addr_ptr != NULL)) {
+			struct netbuf *na;
+			/*LINTED const castaway*/
+			na = uaddr2taddr((struct netconfig *) nconf, r.addr);
+			if (!na) {
+				stat = RPC_N2AXLATEFAILURE;
+				/*LINTED const castaway*/
+				((struct netbuf *) addr_ptr)->len = 0;
+				goto error;
+			}
+			if (na->len > addr_ptr->maxlen) {
+				/* Too long address */
+				stat = RPC_FAILED; /* XXX A better error no */
+				free(na->buf);
+				free(na);
+				/*LINTED const castaway*/
+				((struct netbuf *) addr_ptr)->len = 0;
+				goto error;
+			}
+			memcpy(addr_ptr->buf, na->buf, (size_t)na->len);
+			/*LINTED const castaway*/
+			((struct netbuf *)addr_ptr)->len = na->len;
+			free(na->buf);
+			free(na);
+			break;
+		} else if ((stat != RPC_PROGVERSMISMATCH) &&
+			    (stat != RPC_PROGUNAVAIL)) {
+			goto error;
+		}
+	}
+error:
+	CLNT_DESTROY(client);
+	if (r.addr)
+		xdr_free((xdrproc_t) xdr_wrapstring, (char *)(void *)&r.addr);
+	return (stat);
+}
+
+/*
+ * Gets the time on the remote host.
+ * Returns 1 if succeeds else 0.
+ */
+bool_t
+rpcb_gettime(host, timep)
+	const char *host;
+	time_t *timep;
+{
+	CLIENT *client = NULL;
+	void *handle;
+	struct netconfig *nconf;
+	rpcvers_t vers;
+	enum clnt_stat st;
+
+
+	if ((host == NULL) || (host[0] == 0)) {
+		time(timep);
+		return (TRUE);
+	}
+
+	if ((handle = __rpc_setconf("netpath")) == NULL) {
+		rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
+		return (FALSE);
+	}
+	rpc_createerr.cf_stat = RPC_SUCCESS;
+	while (client == NULL) {
+		if ((nconf = __rpc_getconf(handle)) == NULL) {
+			if (rpc_createerr.cf_stat == RPC_SUCCESS)
+				rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
+			break;
+		}
+		client = getclnthandle(host, nconf, NULL);
+		if (client)
+			break;
+	}
+	__rpc_endconf(handle);
+	if (client == (CLIENT *) NULL) {
+		return (FALSE);
+	}
+
+	st = CLNT_CALL(client, (rpcproc_t)RPCBPROC_GETTIME,
+		(xdrproc_t) xdr_void, NULL,
+		(xdrproc_t) xdr_int, (char *)(void *)timep, tottimeout);
+
+	if ((st == RPC_PROGVERSMISMATCH) || (st == RPC_PROGUNAVAIL)) {
+		CLNT_CONTROL(client, CLGET_VERS, (char *)(void *)&vers);
+		if (vers == RPCBVERS4) {
+			/* fall back to earlier version */
+			vers = RPCBVERS;
+			CLNT_CONTROL(client, CLSET_VERS, (char *)(void *)&vers);
+			st = CLNT_CALL(client, (rpcproc_t)RPCBPROC_GETTIME,
+				(xdrproc_t) xdr_void, NULL,
+				(xdrproc_t) xdr_int, (char *)(void *)timep,
+				tottimeout);
+		}
+	}
+	CLNT_DESTROY(client);
+	return (st == RPC_SUCCESS? TRUE: FALSE);
+}
+
+/*
+ * Converts taddr to universal address.  This routine should never
+ * really be called because local n2a libraries are always provided.
+ */
+char *
+rpcb_taddr2uaddr(nconf, taddr)
+	struct netconfig *nconf;
+	struct netbuf *taddr;
+{
+	CLIENT *client;
+	char *uaddr = NULL;
+
+
+	/* parameter checking */
+	if (nconf == NULL) {
+		rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
+		return (NULL);
+	}
+	if (taddr == NULL) {
+		rpc_createerr.cf_stat = RPC_UNKNOWNADDR;
+		return (NULL);
+	}
+	client = local_rpcb();
+	if (! client) {
+		return (NULL);
+	}
+
+	CLNT_CALL(client, (rpcproc_t)RPCBPROC_TADDR2UADDR,
+	    (xdrproc_t) xdr_netbuf, (char *)(void *)taddr,
+	    (xdrproc_t) xdr_wrapstring, (char *)(void *)&uaddr, tottimeout);
+	CLNT_DESTROY(client);
+	return (uaddr);
+}
+
+/*
+ * Converts universal address to netbuf.  This routine should never
+ * really be called because local n2a libraries are always provided.
+ */
+struct netbuf *
+rpcb_uaddr2taddr(nconf, uaddr)
+	struct netconfig *nconf;
+	char *uaddr;
+{
+	CLIENT *client;
+	struct netbuf *taddr;
+
+
+	/* parameter checking */
+	if (nconf == NULL) {
+		rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
+		return (NULL);
+	}
+	if (uaddr == NULL) {
+		rpc_createerr.cf_stat = RPC_UNKNOWNADDR;
+		return (NULL);
+	}
+	client = local_rpcb();
+	if (! client) {
+		return (NULL);
+	}
+
+	taddr = (struct netbuf *)calloc(1, sizeof (struct netbuf));
+	if (taddr == NULL) {
+		CLNT_DESTROY(client);
+		return (NULL);
+	}
+	if (CLNT_CALL(client, (rpcproc_t)RPCBPROC_UADDR2TADDR,
+	    (xdrproc_t) xdr_wrapstring, (char *)(void *)&uaddr,
+	    (xdrproc_t) xdr_netbuf, (char *)(void *)taddr,
+	    tottimeout) != RPC_SUCCESS) {
+		free(taddr);
+		taddr = NULL;
+	}
+	CLNT_DESTROY(client);
+	return (taddr);
+}
Index: freebsd/lib/libc/rpc/rpcb_prot.c
===================================================================
--- freebsd/lib/libc/rpc/rpcb_prot.c	(revision 60b1d40751c8b3235b7ccbf3bb6ad0c562562f01)
+++ freebsd/lib/libc/rpc/rpcb_prot.c	(revision 60b1d40751c8b3235b7ccbf3bb6ad0c562562f01)
@@ -0,0 +1,333 @@
+#include <machine/rtems-bsd-user-space.h>
+
+/*	$NetBSD: rpcb_prot.c,v 1.3 2000/07/14 08:40:42 fvdl Exp $	*/
+
+/*-
+ * Copyright (c) 2009, Sun Microsystems, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions are met:
+ * - Redistributions of source code must retain the above copyright notice, 
+ *   this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice, 
+ *   this list of conditions and the following disclaimer in the documentation 
+ *   and/or other materials provided with the distribution.
+ * - Neither the name of Sun Microsystems, Inc. nor the names of its 
+ *   contributors may be used to endorse or promote products derived 
+ *   from this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * Copyright (c) 1986-1991 by Sun Microsystems Inc. 
+ */
+
+/* #ident	"@(#)rpcb_prot.c	1.13	94/04/24 SMI" */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)rpcb_prot.c 1.9 89/04/21 Copyr 1984 Sun Micro";
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * rpcb_prot.c
+ * XDR routines for the rpcbinder version 3.
+ *
+ * Copyright (C) 1984, 1988, Sun Microsystems, Inc.
+ */
+
+#include "namespace.h"
+#include <rpc/rpc.h>
+#include <rpc/types.h>
+#include <rpc/xdr.h>
+#include <rpc/rpcb_prot.h>
+#include "un-namespace.h"
+
+bool_t
+xdr_rpcb(xdrs, objp)
+	XDR *xdrs;
+	RPCB *objp;
+{
+	if (!xdr_u_int32_t(xdrs, &objp->r_prog)) {
+		return (FALSE);
+	}
+	if (!xdr_u_int32_t(xdrs, &objp->r_vers)) {
+		return (FALSE);
+	}
+	if (!xdr_string(xdrs, &objp->r_netid, (u_int)~0)) {
+		return (FALSE);
+	}
+	if (!xdr_string(xdrs, &objp->r_addr, (u_int)~0)) {
+		return (FALSE);
+	}
+	if (!xdr_string(xdrs, &objp->r_owner, (u_int)~0)) {
+		return (FALSE);
+	}
+	return (TRUE);
+}
+
+/*
+ * rpcblist_ptr implements a linked list.  The RPCL definition from
+ * rpcb_prot.x is:
+ *
+ * struct rpcblist {
+ * 	rpcb		rpcb_map;
+ *	struct rpcblist *rpcb_next;
+ * };
+ * typedef rpcblist *rpcblist_ptr;
+ *
+ * Recall that "pointers" in XDR are encoded as a boolean, indicating whether
+ * there's any data behind the pointer, followed by the data (if any exists).
+ * The boolean can be interpreted as ``more data follows me''; if FALSE then
+ * nothing follows the boolean; if TRUE then the boolean is followed by an
+ * actual struct rpcb, and another rpcblist_ptr (declared in RPCL as "struct
+ * rpcblist *").
+ *
+ * This could be implemented via the xdr_pointer type, though this would
+ * result in one recursive call per element in the list.  Rather than do that
+ * we can ``unwind'' the recursion into a while loop and use xdr_reference to
+ * serialize the rpcb elements.
+ */
+
+bool_t
+xdr_rpcblist_ptr(xdrs, rp)
+	XDR *xdrs;
+	rpcblist_ptr *rp;
+{
+	/*
+	 * more_elements is pre-computed in case the direction is
+	 * XDR_ENCODE or XDR_FREE.  more_elements is overwritten by
+	 * xdr_bool when the direction is XDR_DECODE.
+	 */
+	bool_t more_elements;
+	int freeing = (xdrs->x_op == XDR_FREE);
+	rpcblist_ptr next;
+	rpcblist_ptr next_copy;
+
+	next = NULL;
+	for (;;) {
+		more_elements = (bool_t)(*rp != NULL);
+		if (! xdr_bool(xdrs, &more_elements)) {
+			return (FALSE);
+		}
+		if (! more_elements) {
+			return (TRUE);  /* we are done */
+		}
+		/*
+		 * the unfortunate side effect of non-recursion is that in
+		 * the case of freeing we must remember the next object
+		 * before we free the current object ...
+		 */
+		if (freeing && *rp)
+			next = (*rp)->rpcb_next;
+		if (! xdr_reference(xdrs, (caddr_t *)rp,
+		    (u_int)sizeof (rpcblist), (xdrproc_t)xdr_rpcb)) {
+			return (FALSE);
+		}
+		if (freeing) {
+			next_copy = next;
+			rp = &next_copy;
+			/*
+			 * Note that in the subsequent iteration, next_copy
+			 * gets nulled out by the xdr_reference
+			 * but next itself survives.
+			 */
+		} else if (*rp) {
+			rp = &((*rp)->rpcb_next);
+		}
+	}
+	/*NOTREACHED*/
+}
+
+/*
+ * xdr_rpcblist() is specified to take a RPCBLIST **, but is identical in
+ * functionality to xdr_rpcblist_ptr().
+ */
+bool_t
+xdr_rpcblist(xdrs, rp)
+	XDR *xdrs;
+	RPCBLIST **rp;
+{
+	bool_t	dummy;
+
+	dummy = xdr_rpcblist_ptr(xdrs, (rpcblist_ptr *)rp);
+	return (dummy);
+}
+
+
+bool_t
+xdr_rpcb_entry(xdrs, objp)
+	XDR *xdrs;
+	rpcb_entry *objp;
+{
+	if (!xdr_string(xdrs, &objp->r_maddr, (u_int)~0)) {
+		return (FALSE);
+	}
+	if (!xdr_string(xdrs, &objp->r_nc_netid, (u_int)~0)) {
+		return (FALSE);
+	}
+	if (!xdr_u_int32_t(xdrs, &objp->r_nc_semantics)) {
+		return (FALSE);
+	}
+	if (!xdr_string(xdrs, &objp->r_nc_protofmly, (u_int)~0)) {
+		return (FALSE);
+	}
+	if (!xdr_string(xdrs, &objp->r_nc_proto, (u_int)~0)) {
+		return (FALSE);
+	}
+	return (TRUE);
+}
+
+bool_t
+xdr_rpcb_entry_list_ptr(xdrs, rp)
+	XDR *xdrs;
+	rpcb_entry_list_ptr *rp;
+{
+	/*
+	 * more_elements is pre-computed in case the direction is
+	 * XDR_ENCODE or XDR_FREE.  more_elements is overwritten by
+	 * xdr_bool when the direction is XDR_DECODE.
+	 */
+	bool_t more_elements;
+	int freeing = (xdrs->x_op == XDR_FREE);
+	rpcb_entry_list_ptr next;
+	rpcb_entry_list_ptr next_copy;
+
+	next = NULL;
+	for (;;) {
+		more_elements = (bool_t)(*rp != NULL);
+		if (! xdr_bool(xdrs, &more_elements)) {
+			return (FALSE);
+		}
+		if (! more_elements) {
+			return (TRUE);  /* we are done */
+		}
+		/*
+		 * the unfortunate side effect of non-recursion is that in
+		 * the case of freeing we must remember the next object
+		 * before we free the current object ...
+		 */
+		if (freeing)
+			next = (*rp)->rpcb_entry_next;
+		if (! xdr_reference(xdrs, (caddr_t *)rp,
+		    (u_int)sizeof (rpcb_entry_list),
+				    (xdrproc_t)xdr_rpcb_entry)) {
+			return (FALSE);
+		}
+		if (freeing && *rp) {
+			next_copy = next;
+			rp = &next_copy;
+			/*
+			 * Note that in the subsequent iteration, next_copy
+			 * gets nulled out by the xdr_reference
+			 * but next itself survives.
+			 */
+		} else if (*rp) {
+			rp = &((*rp)->rpcb_entry_next);
+		}
+	}
+	/*NOTREACHED*/
+}
+
+/*
+ * XDR remote call arguments
+ * written for XDR_ENCODE direction only
+ */
+bool_t
+xdr_rpcb_rmtcallargs(xdrs, p)
+	XDR *xdrs;
+	struct rpcb_rmtcallargs *p;
+{
+	struct r_rpcb_rmtcallargs *objp =
+	    (struct r_rpcb_rmtcallargs *)(void *)p;
+	u_int lenposition, argposition, position;
+	int32_t *buf;
+
+	buf = XDR_INLINE(xdrs, 3 * BYTES_PER_XDR_UNIT);
+	if (buf == NULL) {
+		if (!xdr_u_int32_t(xdrs, &objp->prog)) {
+			return (FALSE);
+		}
+		if (!xdr_u_int32_t(xdrs, &objp->vers)) {
+			return (FALSE);
+		}
+		if (!xdr_u_int32_t(xdrs, &objp->proc)) {
+			return (FALSE);
+		}
+	} else {
+		IXDR_PUT_U_INT32(buf, objp->prog);
+		IXDR_PUT_U_INT32(buf, objp->vers);
+		IXDR_PUT_U_INT32(buf, objp->proc);
+	}
+
+	/*
+	 * All the jugglery for just getting the size of the arguments
+	 */
+	lenposition = XDR_GETPOS(xdrs);
+	if (! xdr_u_int(xdrs, &(objp->args.args_len))) {
+		return (FALSE);
+	}
+	argposition = XDR_GETPOS(xdrs);
+	if (! (*objp->xdr_args)(xdrs, objp->args.args_val)) {
+		return (FALSE);
+	}
+	position = XDR_GETPOS(xdrs);
+	objp->args.args_len = (u_int)((u_long)position - (u_long)argposition);
+	XDR_SETPOS(xdrs, lenposition);
+	if (! xdr_u_int(xdrs, &(objp->args.args_len))) {
+		return (FALSE);
+	}
+	XDR_SETPOS(xdrs, position);
+	return (TRUE);
+}
+
+/*
+ * XDR remote call results
+ * written for XDR_DECODE direction only
+ */
+bool_t
+xdr_rpcb_rmtcallres(xdrs, p)
+	XDR *xdrs;
+	struct rpcb_rmtcallres *p;
+{
+	bool_t dummy;
+	struct r_rpcb_rmtcallres *objp = (struct r_rpcb_rmtcallres *)(void *)p;
+
+	if (!xdr_string(xdrs, &objp->addr, (u_int)~0)) {
+		return (FALSE);
+	}
+	if (!xdr_u_int(xdrs, &objp->results.results_len)) {
+		return (FALSE);
+	}
+	dummy = (*(objp->xdr_res))(xdrs, objp->results.results_val);
+	return (dummy);
+}
+
+bool_t
+xdr_netbuf(xdrs, objp)
+	XDR *xdrs;
+	struct netbuf *objp;
+{
+	bool_t dummy;
+	void **pp;
+
+	if (!xdr_u_int32_t(xdrs, (u_int32_t *) &objp->maxlen)) {
+		return (FALSE);
+	}
+	pp = &objp->buf;
+	dummy = xdr_bytes(xdrs, (char **) pp,
+			(u_int *)&(objp->len), objp->maxlen);
+	return (dummy);
+}
Index: freebsd/lib/libc/rpc/rpcb_st_xdr.c
===================================================================
--- freebsd/lib/libc/rpc/rpcb_st_xdr.c	(revision 60b1d40751c8b3235b7ccbf3bb6ad0c562562f01)
+++ freebsd/lib/libc/rpc/rpcb_st_xdr.c	(revision 60b1d40751c8b3235b7ccbf3bb6ad0c562562f01)
@@ -0,0 +1,276 @@
+#include <machine/rtems-bsd-user-space.h>
+
+/*	$NetBSD: rpcb_st_xdr.c,v 1.3 2000/07/14 08:40:42 fvdl Exp $	*/
+
+/*-
+ * Copyright (c) 2009, Sun Microsystems, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions are met:
+ * - Redistributions of source code must retain the above copyright notice, 
+ *   this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice, 
+ *   this list of conditions and the following disclaimer in the documentation 
+ *   and/or other materials provided with the distribution.
+ * - Neither the name of Sun Microsystems, Inc. nor the names of its 
+ *   contributors may be used to endorse or promote products derived 
+ *   from this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * Copyright 1991 Sun Microsystems, Inc.
+ * rpcb_stat_xdr.c
+ */
+
+/*
+ * This file was generated from rpcb_prot.x, but includes only those
+ * routines used with the rpcbind stats facility.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <rpc/rpc.h>
+#include "un-namespace.h"
+
+/* Link list of all the stats about getport and getaddr */
+
+bool_t
+xdr_rpcbs_addrlist(xdrs, objp)
+	XDR *xdrs;
+	rpcbs_addrlist *objp;
+{
+	struct rpcbs_addrlist **pnext;
+
+	    if (!xdr_u_int32_t(xdrs, &objp->prog)) {
+		return (FALSE);
+	    }
+	    if (!xdr_u_int32_t(xdrs, &objp->vers)) {
+		return (FALSE);
+	    }
+	    if (!xdr_int(xdrs, &objp->success)) {
+		return (FALSE);
+	    }
+	    if (!xdr_int(xdrs, &objp->failure)) {
+		return (FALSE);
+	    }
+	    if (!xdr_string(xdrs, &objp->netid, (u_int)~0)) {
+		return (FALSE);
+	    }
+
+	    pnext = &objp->next;
+
+	    if (!xdr_pointer(xdrs, (char **) pnext,
+			sizeof (rpcbs_addrlist),
+			(xdrproc_t)xdr_rpcbs_addrlist)) {
+		return (FALSE);
+	    }
+
+	return (TRUE);
+}
+
+/* Link list of all the stats about rmtcall */
+
+bool_t
+xdr_rpcbs_rmtcalllist(xdrs, objp)
+	XDR *xdrs;
+	rpcbs_rmtcalllist *objp;
+{
+	int32_t *buf;
+	struct rpcbs_rmtcalllist **pnext;
+
+	if (xdrs->x_op == XDR_ENCODE) {
+	buf = XDR_INLINE(xdrs, 6 * BYTES_PER_XDR_UNIT);
+	if (buf == NULL) {
+		if (!xdr_u_int32_t(xdrs, &objp->prog)) {
+			return (FALSE);
+		}
+		if (!xdr_u_int32_t(xdrs, &objp->vers)) {
+			return (FALSE);
+		}
+		if (!xdr_u_int32_t(xdrs, &objp->proc)) {
+			return (FALSE);
+		}
+		if (!xdr_int(xdrs, &objp->success)) {
+			return (FALSE);
+		}
+		if (!xdr_int(xdrs, &objp->failure)) {
+			return (FALSE);
+		}
+		if (!xdr_int(xdrs, &objp->indirect)) {
+			return (FALSE);
+		}
+	} else {
+		IXDR_PUT_U_INT32(buf, objp->prog);
+		IXDR_PUT_U_INT32(buf, objp->vers);
+		IXDR_PUT_U_INT32(buf, objp->proc);
+		IXDR_PUT_INT32(buf, objp->success);
+		IXDR_PUT_INT32(buf, objp->failure);
+		IXDR_PUT_INT32(buf, objp->indirect);
+	}
+	if (!xdr_string(xdrs, &objp->netid, (u_int)~0)) {
+		return (FALSE);
+	}
+	pnext = &objp->next;
+	if (!xdr_pointer(xdrs, (char **) pnext,
+			sizeof (rpcbs_rmtcalllist),
+			(xdrproc_t)xdr_rpcbs_rmtcalllist)) {
+		return (FALSE);
+	}
+	return (TRUE);
+	} else if (xdrs->x_op == XDR_DECODE) {
+	buf = XDR_INLINE(xdrs, 6 * BYTES_PER_XDR_UNIT);
+	if (buf == NULL) {
+		if (!xdr_u_int32_t(xdrs, &objp->prog)) {
+			return (FALSE);
+		}
+		if (!xdr_u_int32_t(xdrs, &objp->vers)) {
+			return (FALSE);
+		}
+		if (!xdr_u_int32_t(xdrs, &objp->proc)) {
+			return (FALSE);
+		}
+		if (!xdr_int(xdrs, &objp->success)) {
+			return (FALSE);
+		}
+		if (!xdr_int(xdrs, &objp->failure)) {
+			return (FALSE);
+		}
+		if (!xdr_int(xdrs, &objp->indirect)) {
+			return (FALSE);
+		}
+	} else {
+		objp->prog = (rpcprog_t)IXDR_GET_U_INT32(buf);
+		objp->vers = (rpcvers_t)IXDR_GET_U_INT32(buf);
+		objp->proc = (rpcproc_t)IXDR_GET_U_INT32(buf);
+		objp->success = (int)IXDR_GET_INT32(buf);
+		objp->failure = (int)IXDR_GET_INT32(buf);
+		objp->indirect = (int)IXDR_GET_INT32(buf);
+	}
+	if (!xdr_string(xdrs, &objp->netid, (u_int)~0)) {
+		return (FALSE);
+	}
+	if (!xdr_pointer(xdrs, (char **) pnext,
+			sizeof (rpcbs_rmtcalllist),
+			(xdrproc_t)xdr_rpcbs_rmtcalllist)) {
+		return (FALSE);
+	}
+	return (TRUE);
+	}
+	if (!xdr_u_int32_t(xdrs, &objp->prog)) {
+		return (FALSE);
+	}
+	if (!xdr_u_int32_t(xdrs, &objp->vers)) {
+		return (FALSE);
+	}
+	if (!xdr_u_int32_t(xdrs, &objp->proc)) {
+		return (FALSE);
+	}
+	if (!xdr_int(xdrs, &objp->success)) {
+		return (FALSE);
+	}
+	if (!xdr_int(xdrs, &objp->failure)) {
+		return (FALSE);
+	}
+	if (!xdr_int(xdrs, &objp->indirect)) {
+		return (FALSE);
+	}
+	if (!xdr_string(xdrs, &objp->netid, (u_int)~0)) {
+		return (FALSE);
+	}
+	if (!xdr_pointer(xdrs, (char **) pnext,
+			sizeof (rpcbs_rmtcalllist),
+			(xdrproc_t)xdr_rpcbs_rmtcalllist)) {
+		return (FALSE);
+	}
+	return (TRUE);
+}
+
+bool_t
+xdr_rpcbs_proc(xdrs, objp)
+	XDR *xdrs;
+	rpcbs_proc objp;
+{
+	if (!xdr_vector(xdrs, (char *)(void *)objp, RPCBSTAT_HIGHPROC,
+	    sizeof (int), (xdrproc_t)xdr_int)) {
+		return (FALSE);
+	}
+	return (TRUE);
+}
+
+bool_t
+xdr_rpcbs_addrlist_ptr(xdrs, objp)
+	XDR *xdrs;
+	rpcbs_addrlist_ptr *objp;
+{
+	if (!xdr_pointer(xdrs, (char **)objp, sizeof (rpcbs_addrlist),
+			(xdrproc_t)xdr_rpcbs_addrlist)) {
+		return (FALSE);
+	}
+	return (TRUE);
+}
+
+bool_t
+xdr_rpcbs_rmtcalllist_ptr(xdrs, objp)
+	XDR *xdrs;
+	rpcbs_rmtcalllist_ptr *objp;
+{
+	if (!xdr_pointer(xdrs, (char **)objp, sizeof (rpcbs_rmtcalllist),
+			(xdrproc_t)xdr_rpcbs_rmtcalllist)) {
+		return (FALSE);
+	}
+	return (TRUE);
+}
+
+bool_t
+xdr_rpcb_stat(xdrs, objp)
+	XDR *xdrs;
+	rpcb_stat *objp;
+{
+
+	if (!xdr_rpcbs_proc(xdrs, objp->info)) {
+		return (FALSE);
+	}
+	if (!xdr_int(xdrs, &objp->setinfo)) {
+		return (FALSE);
+	}
+	if (!xdr_int(xdrs, &objp->unsetinfo)) {
+		return (FALSE);
+	}
+	if (!xdr_rpcbs_addrlist_ptr(xdrs, &objp->addrinfo)) {
+		return (FALSE);
+	}
+	if (!xdr_rpcbs_rmtcalllist_ptr(xdrs, &objp->rmtinfo)) {
+		return (FALSE);
+	}
+	return (TRUE);
+}
+
+/*
+ * One rpcb_stat structure is returned for each version of rpcbind
+ * being monitored.
+ */
+bool_t
+xdr_rpcb_stat_byvers(xdrs, objp)
+    XDR *xdrs;
+    rpcb_stat_byvers objp;
+{
+	if (!xdr_vector(xdrs, (char *)(void *)objp, RPCBVERS_STAT,
+	    sizeof (rpcb_stat), (xdrproc_t)xdr_rpcb_stat)) {
+		return (FALSE);
+	}
+	return (TRUE);
+}
Index: freebsd/lib/libc/rpc/rpcdname.c
===================================================================
--- freebsd/lib/libc/rpc/rpcdname.c	(revision 60b1d40751c8b3235b7ccbf3bb6ad0c562562f01)
+++ freebsd/lib/libc/rpc/rpcdname.c	(revision 60b1d40751c8b3235b7ccbf3bb6ad0c562562f01)
@@ -0,0 +1,82 @@
+#include <machine/rtems-bsd-user-space.h>
+
+/*-
+ * Copyright (c) 2009, Sun Microsystems, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions are met:
+ * - Redistributions of source code must retain the above copyright notice, 
+ *   this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice, 
+ *   this list of conditions and the following disclaimer in the documentation 
+ *   and/or other materials provided with the distribution.
+ * - Neither the name of Sun Microsystems, Inc. nor the names of its 
+ *   contributors may be used to endorse or promote products derived 
+ *   from this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)rpcdname.c 1.7 91/03/11 Copyr 1989 Sun Micro";
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * rpcdname.c
+ * Gets the default domain name
+ */
+
+#include "namespace.h"
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include "un-namespace.h"
+
+static char *default_domain = 0;
+
+static char *
+get_default_domain()
+{
+	char temp[256];
+
+	if (default_domain)
+		return (default_domain);
+	if (getdomainname(temp, sizeof(temp)) < 0)
+		return (0);
+	if ((int) strlen(temp) > 0) {
+		default_domain = (char *)malloc((strlen(temp)+(unsigned)1));
+		if (default_domain == 0)
+			return (0);
+		(void) strcpy(default_domain, temp);
+		return (default_domain);
+	}
+	return (0);
+}
+
+/*
+ * This is a wrapper for the system call getdomainname which returns a
+ * ypclnt.h error code in the failure case.  It also checks to see that
+ * the domain name is non-null, knowing that the null string is going to
+ * get rejected elsewhere in the NIS client package.
+ */
+int
+__rpc_get_default_domain(domain)
+	char **domain;
+{
+	if ((*domain = get_default_domain()) != 0)
+		return (0);
+	return (-1);
+}
Index: freebsd/lib/libc/rpc/rpcsec_gss_stub.c
===================================================================
--- freebsd/lib/libc/rpc/rpcsec_gss_stub.c	(revision 60b1d40751c8b3235b7ccbf3bb6ad0c562562f01)
+++ freebsd/lib/libc/rpc/rpcsec_gss_stub.c	(revision 60b1d40751c8b3235b7ccbf3bb6ad0c562562f01)
@@ -0,0 +1,50 @@
+#include <machine/rtems-bsd-user-space.h>
+
+/*-
+ * Copyright (c) 2006 Doug Rabson
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	$FreeBSD$
+ */
+
+#include <rpc/rpc.h>
+#include <rpc/rpcsec_gss.h>
+
+bool_t
+__rpc_gss_wrap_stub(AUTH *auth, void *header, size_t headerlen, XDR* xdrs,
+    xdrproc_t xdr_args, void *args_ptr)
+{
+
+	return (FALSE);
+}
+
+bool_t
+__rpc_gss_unwrap_stub(AUTH *auth, XDR* xdrs, xdrproc_t xdr_args, void *args_ptr)
+{
+
+	return (FALSE);
+}
+
+__weak_reference(__rpc_gss_wrap_stub,	__rpc_gss_wrap);
+__weak_reference(__rpc_gss_unwrap_stub,	__rpc_gss_unwrap);
Index: freebsd/lib/libc/rpc/rtime.c
===================================================================
--- freebsd/lib/libc/rpc/rtime.c	(revision 60b1d40751c8b3235b7ccbf3bb6ad0c562562f01)
+++ freebsd/lib/libc/rpc/rtime.c	(revision 60b1d40751c8b3235b7ccbf3bb6ad0c562562f01)
@@ -0,0 +1,161 @@
+#include <machine/rtems-bsd-user-space.h>
+
+/*-
+ * Copyright (c) 2009, Sun Microsystems, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions are met:
+ * - Redistributions of source code must retain the above copyright notice, 
+ *   this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice, 
+ *   this list of conditions and the following disclaimer in the documentation 
+ *   and/or other materials provided with the distribution.
+ * - Neither the name of Sun Microsystems, Inc. nor the names of its 
+ *   contributors may be used to endorse or promote products derived 
+ *   from this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Copyright (c) 1988 by Sun Microsystems, Inc.
+
+ */
+
+/*
+ * rtime - get time from remote machine
+ *
+ * gets time, obtaining value from host
+ * on the udp/time socket.  Since timeserver returns
+ * with time of day in seconds since Jan 1, 1900,  must
+ * subtract seconds before Jan 1, 1970 to get
+ * what unix uses.
+ */
+#include "namespace.h"
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <netinet/in.h>
+#include <stdio.h>
+#include <netdb.h>
+#include "un-namespace.h"
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = 	"@(#)rtime.c	2.2 88/08/10 4.0 RPCSRC; from 1.8 88/02/08 SMI";
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+extern int _rpc_dtablesize( void );
+
+#define NYEARS	(unsigned long)(1970 - 1900)
+#define TOFFSET (unsigned long)(60*60*24*(365*NYEARS + (NYEARS/4)))
+
+static void do_close( int );
+
+int
+rtime(addrp, timep, timeout)
+	struct sockaddr_in *addrp;
+	struct timeval *timep;
+	struct timeval *timeout;
+{
+	int s;
+	fd_set readfds;
+	int res;
+	unsigned long thetime;
+	struct sockaddr_in from;
+	socklen_t fromlen;
+	int type;
+	struct servent *serv;
+
+	if (timeout == NULL) {
+		type = SOCK_STREAM;
+	} else {
+		type = SOCK_DGRAM;
+	}
+	s = _socket(AF_INET, type, 0);
+	if (s < 0) {
+		return(-1);
+	}
+	addrp->sin_family = AF_INET;
+
+	/* TCP and UDP port are the same in this case */
+	if ((serv = getservbyname("time", "tcp")) == NULL) {
+		return(-1);
+	}
+
+	addrp->sin_port = serv->s_port;
+
+	if (type == SOCK_DGRAM) {
+		res = _sendto(s, (char *)&thetime, sizeof(thetime), 0, 
+			     (struct sockaddr *)addrp, sizeof(*addrp));
+		if (res < 0) {
+			do_close(s);
+			return(-1);	
+		}
+		do {
+			FD_ZERO(&readfds);
+			FD_SET(s, &readfds);
+			res = _select(_rpc_dtablesize(), &readfds,
+				     (fd_set *)NULL, (fd_set *)NULL, timeout);
+		} while (res < 0 && errno == EINTR);
+		if (res <= 0) {
+			if (res == 0) {
+				errno = ETIMEDOUT;
+			}
+			do_close(s);
+			return(-1);	
+		}
+		fromlen = sizeof(from);
+		res = _recvfrom(s, (char *)&thetime, sizeof(thetime), 0, 
+			       (struct sockaddr *)&from, &fromlen);
+		do_close(s);
+		if (res < 0) {
+			return(-1);	
+		}
+	} else {
+		if (_connect(s, (struct sockaddr *)addrp, sizeof(*addrp)) < 0) {
+			do_close(s);
+			return(-1);
+		}
+		res = _read(s, (char *)&thetime, sizeof(thetime));
+		do_close(s);
+		if (res < 0) {
+			return(-1);
+		}
+	}
+	if (res != sizeof(thetime)) {
+		errno = EIO;
+		return(-1);	
+	}
+	thetime = ntohl(thetime);
+	timep->tv_sec = thetime - TOFFSET;
+	timep->tv_usec = 0;
+	return(0);
+}
+
+static void
+do_close(s)
+	int s;
+{
+	int save;
+
+	save = errno;
+	(void)_close(s);
+	errno = save;
+}
Index: freebsd/lib/libc/rpc/svc.c
===================================================================
--- freebsd/lib/libc/rpc/svc.c	(revision 60b1d40751c8b3235b7ccbf3bb6ad0c562562f01)
+++ freebsd/lib/libc/rpc/svc.c	(revision 60b1d40751c8b3235b7ccbf3bb6ad0c562562f01)
@@ -0,0 +1,798 @@
+#include <machine/rtems-bsd-user-space.h>
+
+/*	$NetBSD: svc.c,v 1.21 2000/07/06 03:10:35 christos Exp $	*/
+
+/*-
+ * Copyright (c) 2009, Sun Microsystems, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions are met:
+ * - Redistributions of source code must retain the above copyright notice, 
+ *   this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice, 
+ *   this list of conditions and the following disclaimer in the documentation 
+ *   and/or other materials provided with the distribution.
+ * - Neither the name of Sun Microsystems, Inc. nor the names of its 
+ *   contributors may be used to endorse or promote products derived 
+ *   from this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char *sccsid2 = "@(#)svc.c 1.44 88/02/08 Copyr 1984 Sun Micro";
+static char *sccsid = "@(#)svc.c	2.4 88/08/11 4.0 RPCSRC";
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * svc.c, Server-side remote procedure call interface.
+ *
+ * There are two sets of procedures here.  The xprt routines are
+ * for handling transport handles.  The svc routines handle the
+ * list of service routines.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#include "namespace.h"
+#include "reentrant.h"
+#include <sys/types.h>
+#include <sys/poll.h>
+#include <assert.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <rpc/rpc.h>
+#ifdef PORTMAP
+#include <rpc/pmap_clnt.h>
+#endif				/* PORTMAP */
+#include "un-namespace.h"
+
+#include "rpc_com.h"
+#include "mt_misc.h"
+
+#define	RQCRED_SIZE	400		/* this size is excessive */
+
+#define SVC_VERSQUIET 0x0001		/* keep quiet about vers mismatch */
+#define version_keepquiet(xp) (SVC_EXT(xp)->xp_flags & SVC_VERSQUIET)
+
+#define max(a, b) (a > b ? a : b)
+
+/*
+ * The services list
+ * Each entry represents a set of procedures (an rpc program).
+ * The dispatch routine takes request structs and runs the
+ * apropriate procedure.
+ */
+static struct svc_callout {
+	struct svc_callout *sc_next;
+	rpcprog_t	    sc_prog;
+	rpcvers_t	    sc_vers;
+	char		   *sc_netid;
+	void		    (*sc_dispatch)(struct svc_req *, SVCXPRT *);
+} *svc_head;
+
+static struct svc_callout *svc_find(rpcprog_t, rpcvers_t,
+    struct svc_callout **, char *);
+static void __xprt_do_unregister (SVCXPRT *xprt, bool_t dolock);
+
+/* ***************  SVCXPRT related stuff **************** */
+
+/*
+ * Activate a transport handle.
+ */
+void
+xprt_register(xprt)
+	SVCXPRT *xprt;
+{
+	int sock;
+
+	assert(xprt != NULL);
+
+	sock = xprt->xp_fd;
+
+	rwlock_wrlock(&svc_fd_lock);
+	if (__svc_xports == NULL) {
+		__svc_xports = (SVCXPRT **)
+			mem_alloc(FD_SETSIZE * sizeof(SVCXPRT *));
+		if (__svc_xports == NULL) {
+			rwlock_unlock(&svc_fd_lock);
+			return;
+		}
+		memset(__svc_xports, '\0', FD_SETSIZE * sizeof(SVCXPRT *));
+	}
+	if (sock < FD_SETSIZE) {
+		__svc_xports[sock] = xprt;
+		FD_SET(sock, &svc_fdset);
+		svc_maxfd = max(svc_maxfd, sock);
+	}
+	rwlock_unlock(&svc_fd_lock);
+}
+
+void
+xprt_unregister(SVCXPRT *xprt)
+{
+	__xprt_do_unregister(xprt, TRUE);
+}
+
+void
+__xprt_unregister_unlocked(SVCXPRT *xprt)
+{
+	__xprt_do_unregister(xprt, FALSE);
+}
+
+/*
+ * De-activate a transport handle.
+ */
+static void
+__xprt_do_unregister(xprt, dolock)
+	SVCXPRT *xprt;
+	bool_t dolock;
+{
+	int sock;
+
+	assert(xprt != NULL);
+
+	sock = xprt->xp_fd;
+
+	if (dolock)
+		rwlock_wrlock(&svc_fd_lock);
+	if ((sock < FD_SETSIZE) && (__svc_xports[sock] == xprt)) {
+		__svc_xports[sock] = NULL;
+		FD_CLR(sock, &svc_fdset);
+		if (sock >= svc_maxfd) {
+			for (svc_maxfd--; svc_maxfd>=0; svc_maxfd--)
+				if (__svc_xports[svc_maxfd])
+					break;
+		}
+	}
+	if (dolock)
+		rwlock_unlock(&svc_fd_lock);
+}
+
+/*
+ * Add a service program to the callout list.
+ * The dispatch routine will be called when a rpc request for this
+ * program number comes in.
+ */
+bool_t
+svc_reg(xprt, prog, vers, dispatch, nconf)
+	SVCXPRT *xprt;
+	const rpcprog_t prog;
+	const rpcvers_t vers;
+	void (*dispatch)(struct svc_req *, SVCXPRT *);
+	const struct netconfig *nconf;
+{
+	bool_t dummy;
+	struct svc_callout *prev;
+	struct svc_callout *s;
+	struct netconfig *tnconf;
+	char *netid = NULL;
+	int flag = 0;
+
+/* VARIABLES PROTECTED BY svc_lock: s, prev, svc_head */
+
+	if (xprt->xp_netid) {
+		netid = strdup(xprt->xp_netid);
+		flag = 1;
+	} else if (nconf && nconf->nc_netid) {
+		netid = strdup(nconf->nc_netid);
+		flag = 1;
+	} else if ((tnconf = __rpcgettp(xprt->xp_fd)) != NULL) {
+		netid = strdup(tnconf->nc_netid);
+		flag = 1;
+		freenetconfigent(tnconf);
+	} /* must have been created with svc_raw_create */
+	if ((netid == NULL) && (flag == 1)) {
+		return (FALSE);
+	}
+
+	rwlock_wrlock(&svc_lock);
+	if ((s = svc_find(prog, vers, &prev, netid)) != NULL) {
+		if (netid)
+			free(netid);
+		if (s->sc_dispatch == dispatch)
+			goto rpcb_it; /* he is registering another xptr */
+		rwlock_unlock(&svc_lock);
+		return (FALSE);
+	}
+	s = mem_alloc(sizeof (struct svc_callout));
+	if (s == NULL) {
+		if (netid)
+			free(netid);
+		rwlock_unlock(&svc_lock);
+		return (FALSE);
+	}
+
+	s->sc_prog = prog;
+	s->sc_vers = vers;
+	s->sc_dispatch = dispatch;
+	s->sc_netid = netid;
+	s->sc_next = svc_head;
+	svc_head = s;
+
+	if ((xprt->xp_netid == NULL) && (flag == 1) && netid)
+		((SVCXPRT *) xprt)->xp_netid = strdup(netid);
+
+rpcb_it:
+	rwlock_unlock(&svc_lock);
+	/* now register the information with the local binder service */
+	if (nconf) {
+		/*LINTED const castaway*/
+		dummy = rpcb_set(prog, vers, (struct netconfig *) nconf,
+		&((SVCXPRT *) xprt)->xp_ltaddr);
+		return (dummy);
+	}
+	return (TRUE);
+}
+
+/*
+ * Remove a service program from the callout list.
+ */
+void
+svc_unreg(prog, vers)
+	const rpcprog_t prog;
+	const rpcvers_t vers;
+{
+	struct svc_callout *prev;
+	struct svc_callout *s;
+
+	/* unregister the information anyway */
+	(void) rpcb_unset(prog, vers, NULL);
+	rwlock_wrlock(&svc_lock);
+	while ((s = svc_find(prog, vers, &prev, NULL)) != NULL) {
+		if (prev == NULL) {
+			svc_head = s->sc_next;
+		} else {
+			prev->sc_next = s->sc_next;
+		}
+		s->sc_next = NULL;
+		if (s->sc_netid)
+			mem_free(s->sc_netid, sizeof (s->sc_netid) + 1);
+		mem_free(s, sizeof (struct svc_callout));
+	}
+	rwlock_unlock(&svc_lock);
+}
+
+/* ********************** CALLOUT list related stuff ************* */
+
+#ifdef PORTMAP
+/*
+ * Add a service program to the callout list.
+ * The dispatch routine will be called when a rpc request for this
+ * program number comes in.
+ */
+bool_t
+svc_register(xprt, prog, vers, dispatch, protocol)
+	SVCXPRT *xprt;
+	u_long prog;
+	u_long vers;
+	void (*dispatch)(struct svc_req *, SVCXPRT *);
+	int protocol;
+{
+	struct svc_callout *prev;
+	struct svc_callout *s;
+
+	assert(xprt != NULL);
+	assert(dispatch != NULL);
+
+	if ((s = svc_find((rpcprog_t)prog, (rpcvers_t)vers, &prev, NULL)) !=
+	    NULL) {
+		if (s->sc_dispatch == dispatch)
+			goto pmap_it;  /* he is registering another xptr */
+		return (FALSE);
+	}
+	s = mem_alloc(sizeof(struct svc_callout));
+	if (s == NULL) {
+		return (FALSE);
+	}
+	s->sc_prog = (rpcprog_t)prog;
+	s->sc_vers = (rpcvers_t)vers;
+	s->sc_dispatch = dispatch;
+	s->sc_next = svc_head;
+	svc_head = s;
+pmap_it:
+	/* now register the information with the local binder service */
+	if (protocol) {
+		return (pmap_set(prog, vers, protocol, xprt->xp_port));
+	}
+	return (TRUE);
+}
+
+/*
+ * Remove a service program from the callout list.
+ */
+void
+svc_unregister(prog, vers)
+	u_long prog;
+	u_long vers;
+{
+	struct svc_callout *prev;
+	struct svc_callout *s;
+
+	if ((s = svc_find((rpcprog_t)prog, (rpcvers_t)vers, &prev, NULL)) ==
+	    NULL)
+		return;
+	if (prev == NULL) {
+		svc_head = s->sc_next;
+	} else {
+		prev->sc_next = s->sc_next;
+	}
+	s->sc_next = NULL;
+	mem_free(s, sizeof(struct svc_callout));
+	/* now unregister the information with the local binder service */
+	(void)pmap_unset(prog, vers);
+}
+#endif				/* PORTMAP */
+
+/*
+ * Search the callout list for a program number, return the callout
+ * struct.
+ */
+static struct svc_callout *
+svc_find(prog, vers, prev, netid)
+	rpcprog_t prog;
+	rpcvers_t vers;
+	struct svc_callout **prev;
+	char *netid;
+{
+	struct svc_callout *s, *p;
+
+	assert(prev != NULL);
+
+	p = NULL;
+	for (s = svc_head; s != NULL; s = s->sc_next) {
+		if (((s->sc_prog == prog) && (s->sc_vers == vers)) &&
+		    ((netid == NULL) || (s->sc_netid == NULL) ||
+		    (strcmp(netid, s->sc_netid) == 0)))
+			break;
+		p = s;
+	}
+	*prev = p;
+	return (s);
+}
+
+/* ******************* REPLY GENERATION ROUTINES  ************ */
+
+/*
+ * Send a reply to an rpc request
+ */
+bool_t
+svc_sendreply(xprt, xdr_results, xdr_location)
+	SVCXPRT *xprt;
+	xdrproc_t xdr_results;
+	void * xdr_location;
+{
+	struct rpc_msg rply; 
+
+	assert(xprt != NULL);
+
+	rply.rm_direction = REPLY;  
+	rply.rm_reply.rp_stat = MSG_ACCEPTED; 
+	rply.acpted_rply.ar_verf = xprt->xp_verf; 
+	rply.acpted_rply.ar_stat = SUCCESS;
+	rply.acpted_rply.ar_results.where = xdr_location;
+	rply.acpted_rply.ar_results.proc = xdr_results;
+	return (SVC_REPLY(xprt, &rply)); 
+}
+
+/*
+ * No procedure error reply
+ */
+void
+svcerr_noproc(xprt)
+	SVCXPRT *xprt;
+{
+	struct rpc_msg rply;
+
+	assert(xprt != NULL);
+
+	rply.rm_direction = REPLY;
+	rply.rm_reply.rp_stat = MSG_ACCEPTED;
+	rply.acpted_rply.ar_verf = xprt->xp_verf;
+	rply.acpted_rply.ar_stat = PROC_UNAVAIL;
+	SVC_REPLY(xprt, &rply);
+}
+
+/*
+ * Can't decode args error reply
+ */
+void
+svcerr_decode(xprt)
+	SVCXPRT *xprt;
+{
+	struct rpc_msg rply; 
+
+	assert(xprt != NULL);
+
+	rply.rm_direction = REPLY; 
+	rply.rm_reply.rp_stat = MSG_ACCEPTED; 
+	rply.acpted_rply.ar_verf = xprt->xp_verf;
+	rply.acpted_rply.ar_stat = GARBAGE_ARGS;
+	SVC_REPLY(xprt, &rply); 
+}
+
+/*
+ * Some system error
+ */
+void
+svcerr_systemerr(xprt)
+	SVCXPRT *xprt;
+{
+	struct rpc_msg rply; 
+
+	assert(xprt != NULL);
+
+	rply.rm_direction = REPLY; 
+	rply.rm_reply.rp_stat = MSG_ACCEPTED; 
+	rply.acpted_rply.ar_verf = xprt->xp_verf;
+	rply.acpted_rply.ar_stat = SYSTEM_ERR;
+	SVC_REPLY(xprt, &rply); 
+}
+
+#if 0
+/*
+ * Tell RPC package to not complain about version errors to the client.	 This
+ * is useful when revving broadcast protocols that sit on a fixed address.
+ * There is really one (or should be only one) example of this kind of
+ * protocol: the portmapper (or rpc binder).
+ */
+void
+__svc_versquiet_on(xprt)
+	SVCXPRT *xprt;
+{
+
+	SVC_EXT(xprt)->xp_flags |= SVC_VERSQUIET;
+}
+
+void
+__svc_versquiet_off(xprt)
+	SVCXPRT *xprt;
+{
+
+	SVC_EXT(xprt)->xp_flags &= ~SVC_VERSQUIET;
+}
+
+void
+svc_versquiet(xprt)
+	SVCXPRT *xprt;
+{
+	__svc_versquiet_on(xprt);
+}
+
+int
+__svc_versquiet_get(xprt)
+	SVCXPRT *xprt;
+{
+
+	return (SVC_EXT(xprt)->xp_flags & SVC_VERSQUIET);
+}
+#endif
+
+/*
+ * Authentication error reply
+ */
+void
+svcerr_auth(xprt, why)
+	SVCXPRT *xprt;
+	enum auth_stat why;
+{
+	struct rpc_msg rply;
+
+	assert(xprt != NULL);
+
+	rply.rm_direction = REPLY;
+	rply.rm_reply.rp_stat = MSG_DENIED;
+	rply.rjcted_rply.rj_stat = AUTH_ERROR;
+	rply.rjcted_rply.rj_why = why;
+	SVC_REPLY(xprt, &rply);
+}
+
+/*
+ * Auth too weak error reply
+ */
+void
+svcerr_weakauth(xprt)
+	SVCXPRT *xprt;
+{
+
+	assert(xprt != NULL);
+
+	svcerr_auth(xprt, AUTH_TOOWEAK);
+}
+
+/*
+ * Program unavailable error reply
+ */
+void 
+svcerr_noprog(xprt)
+	SVCXPRT *xprt;
+{
+	struct rpc_msg rply;  
+
+	assert(xprt != NULL);
+
+	rply.rm_direction = REPLY;   
+	rply.rm_reply.rp_stat = MSG_ACCEPTED;  
+	rply.acpted_rply.ar_verf = xprt->xp_verf;  
+	rply.acpted_rply.ar_stat = PROG_UNAVAIL;
+	SVC_REPLY(xprt, &rply);
+}
+
+/*
+ * Program version mismatch error reply
+ */
+void  
+svcerr_progvers(xprt, low_vers, high_vers)
+	SVCXPRT *xprt; 
+	rpcvers_t low_vers;
+	rpcvers_t high_vers;
+{
+	struct rpc_msg rply;
+
+	assert(xprt != NULL);
+
+	rply.rm_direction = REPLY;
+	rply.rm_reply.rp_stat = MSG_ACCEPTED;
+	rply.acpted_rply.ar_verf = xprt->xp_verf;
+	rply.acpted_rply.ar_stat = PROG_MISMATCH;
+	rply.acpted_rply.ar_vers.low = (u_int32_t)low_vers;
+	rply.acpted_rply.ar_vers.high = (u_int32_t)high_vers;
+	SVC_REPLY(xprt, &rply);
+}
+
+/*
+ * Allocate a new server transport structure. All fields are
+ * initialized to zero and xp_p3 is initialized to point at an
+ * extension structure to hold various flags and authentication
+ * parameters.
+ */
+SVCXPRT *
+svc_xprt_alloc()
+{
+	SVCXPRT *xprt;
+	SVCXPRT_EXT *ext;
+
+	xprt = mem_alloc(sizeof(SVCXPRT));
+	if (xprt == NULL)
+		return (NULL);
+	memset(xprt, 0, sizeof(SVCXPRT));
+	ext = mem_alloc(sizeof(SVCXPRT_EXT));
+	if (ext == NULL) {
+		mem_free(xprt, sizeof(SVCXPRT));
+		return (NULL);
+	}
+	memset(ext, 0, sizeof(SVCXPRT_EXT));
+	xprt->xp_p3 = ext;
+	ext->xp_auth.svc_ah_ops = &svc_auth_null_ops;
+
+	return (xprt);
+}
+
+/*
+ * Free a server transport structure.
+ */
+void
+svc_xprt_free(xprt)
+	SVCXPRT *xprt;
+{
+
+	mem_free(xprt->xp_p3, sizeof(SVCXPRT_EXT));
+	mem_free(xprt, sizeof(SVCXPRT));
+}
+
+/* ******************* SERVER INPUT STUFF ******************* */
+
+/*
+ * Get server side input from some transport.
+ *
+ * Statement of authentication parameters management:
+ * This function owns and manages all authentication parameters, specifically
+ * the "raw" parameters (msg.rm_call.cb_cred and msg.rm_call.cb_verf) and
+ * the "cooked" credentials (rqst->rq_clntcred).
+ * However, this function does not know the structure of the cooked
+ * credentials, so it make the following assumptions:
+ *   a) the structure is contiguous (no pointers), and
+ *   b) the cred structure size does not exceed RQCRED_SIZE bytes.
+ * In all events, all three parameters are freed upon exit from this routine.
+ * The storage is trivially management on the call stack in user land, but
+ * is mallocated in kernel land.
+ */
+
+void
+svc_getreq(rdfds)
+	int rdfds;
+{
+	fd_set readfds;
+
+	FD_ZERO(&readfds);
+	readfds.fds_bits[0] = rdfds;
+	svc_getreqset(&readfds);
+}
+
+void
+svc_getreqset(readfds)
+	fd_set *readfds;
+{
+	int bit, fd;
+	fd_mask mask, *maskp;
+	int sock;
+
+	assert(readfds != NULL);
+
+	maskp = readfds->fds_bits;
+	for (sock = 0; sock < FD_SETSIZE; sock += NFDBITS) {
+	    for (mask = *maskp++; (bit = ffsl(mask)) != 0;
+		mask ^= (1ul << (bit - 1))) {
+		/* sock has input waiting */
+		fd = sock + bit - 1;
+		svc_getreq_common(fd);
+	    }
+	}
+}
+
+void
+svc_getreq_common(fd)
+	int fd;
+{
+	SVCXPRT *xprt;
+	struct svc_req r;
+	struct rpc_msg msg;
+	int prog_found;
+	rpcvers_t low_vers;
+	rpcvers_t high_vers;
+	enum xprt_stat stat;
+	char cred_area[2*MAX_AUTH_BYTES + RQCRED_SIZE];
+
+	msg.rm_call.cb_cred.oa_base = cred_area;
+	msg.rm_call.cb_verf.oa_base = &(cred_area[MAX_AUTH_BYTES]);
+	r.rq_clntcred = &(cred_area[2*MAX_AUTH_BYTES]);
+
+	rwlock_rdlock(&svc_fd_lock);
+	xprt = __svc_xports[fd];
+	rwlock_unlock(&svc_fd_lock);
+	if (xprt == NULL)
+		/* But do we control sock? */
+		return;
+	/* now receive msgs from xprtprt (support batch calls) */
+	do {
+		if (SVC_RECV(xprt, &msg)) {
+
+			/* now find the exported program and call it */
+			struct svc_callout *s;
+			enum auth_stat why;
+
+			r.rq_xprt = xprt;
+			r.rq_prog = msg.rm_call.cb_prog;
+			r.rq_vers = msg.rm_call.cb_vers;
+			r.rq_proc = msg.rm_call.cb_proc;
+			r.rq_cred = msg.rm_call.cb_cred;
+			/* first authenticate the message */
+			if ((why = _authenticate(&r, &msg)) != AUTH_OK) {
+				/*
+				 * RPCSEC_GSS uses this return code
+				 * for requests that form part of its
+				 * context establishment protocol and
+				 * should not be dispatched to the
+				 * application.
+				 */
+				if (why != RPCSEC_GSS_NODISPATCH)
+					svcerr_auth(xprt, why);
+				goto call_done;
+			}
+			/* now match message with a registered service*/
+			prog_found = FALSE;
+			low_vers = (rpcvers_t) -1L;
+			high_vers = (rpcvers_t) 0L;
+			for (s = svc_head; s != NULL; s = s->sc_next) {
+				if (s->sc_prog == r.rq_prog) {
+					if (s->sc_vers == r.rq_vers) {
+						(*s->sc_dispatch)(&r, xprt);
+						goto call_done;
+					}  /* found correct version */
+					prog_found = TRUE;
+					if (s->sc_vers < low_vers)
+						low_vers = s->sc_vers;
+					if (s->sc_vers > high_vers)
+						high_vers = s->sc_vers;
+				}   /* found correct program */
+			}
+			/*
+			 * if we got here, the program or version
+			 * is not served ...
+			 */
+			if (prog_found)
+				svcerr_progvers(xprt, low_vers, high_vers);
+			else
+				svcerr_noprog(xprt);
+			/* Fall through to ... */
+		}
+		/*
+		 * Check if the xprt has been disconnected in a
+		 * recursive call in the service dispatch routine.
+		 * If so, then break.
+		 */
+		rwlock_rdlock(&svc_fd_lock);
+		if (xprt != __svc_xports[fd]) {
+			rwlock_unlock(&svc_fd_lock);
+			break;
+		}
+		rwlock_unlock(&svc_fd_lock);
+call_done:
+		if ((stat = SVC_STAT(xprt)) == XPRT_DIED){
+			SVC_DESTROY(xprt);
+			break;
+		}
+	} while (stat == XPRT_MOREREQS);
+}
+
+
+void
+svc_getreq_poll(pfdp, pollretval)
+	struct pollfd	*pfdp;
+	int	pollretval;
+{
+	int i;
+	int fds_found;
+
+	for (i = fds_found = 0; fds_found < pollretval; i++) {
+		struct pollfd *p = &pfdp[i];
+
+		if (p->revents) {
+			/* fd has input waiting */
+			fds_found++;
+			/*
+			 *	We assume that this function is only called
+			 *	via someone _select()ing from svc_fdset or
+			 *	_poll()ing from svc_pollset[].  Thus it's safe
+			 *	to handle the POLLNVAL event by simply turning
+			 *	the corresponding bit off in svc_fdset.  The
+			 *	svc_pollset[] array is derived from svc_fdset
+			 *	and so will also be updated eventually.
+			 *
+			 *	XXX Should we do an xprt_unregister() instead?
+			 */
+			if (p->revents & POLLNVAL) {
+				rwlock_wrlock(&svc_fd_lock);
+				FD_CLR(p->fd, &svc_fdset);
+				rwlock_unlock(&svc_fd_lock);
+			} else
+				svc_getreq_common(p->fd);
+		}
+	}
+}
+
+bool_t
+rpc_control(int what, void *arg)
+{
+	int val;
+
+	switch (what) {
+	case RPC_SVC_CONNMAXREC_SET:
+		val = *(int *)arg;
+		if (val <= 0)
+			return FALSE;
+		__svc_maxrec = val;
+		return TRUE;
+	case RPC_SVC_CONNMAXREC_GET:
+		*(int *)arg = __svc_maxrec;
+		return TRUE;
+	default:
+		break;
+	}
+	return FALSE;
+}
Index: freebsd/lib/libc/rpc/svc_auth.c
===================================================================
--- freebsd/lib/libc/rpc/svc_auth.c	(revision 60b1d40751c8b3235b7ccbf3bb6ad0c562562f01)
+++ freebsd/lib/libc/rpc/svc_auth.c	(revision 60b1d40751c8b3235b7ccbf3bb6ad0c562562f01)
@@ -0,0 +1,235 @@
+#include <machine/rtems-bsd-user-space.h>
+
+/*	$NetBSD: svc_auth.c,v 1.12 2000/07/06 03:10:35 christos Exp $	*/
+
+/*-
+ * Copyright (c) 2009, Sun Microsystems, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions are met:
+ * - Redistributions of source code must retain the above copyright notice, 
+ *   this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice, 
+ *   this list of conditions and the following disclaimer in the documentation 
+ *   and/or other materials provided with the distribution.
+ * - Neither the name of Sun Microsystems, Inc. nor the names of its 
+ *   contributors may be used to endorse or promote products derived 
+ *   from this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * Copyright (c) 1986-1991 by Sun Microsystems Inc. 
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+#ident	"@(#)svc_auth.c	1.16	94/04/24 SMI"
+static char sccsid[] = "@(#)svc_auth.c 1.26 89/02/07 Copyr 1984 Sun Micro";
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * svc_auth.c, Server-side rpc authenticator interface.
+ *
+ */
+
+#include "namespace.h"
+#include "reentrant.h"
+#include <sys/types.h>
+#include <rpc/rpc.h>
+#include <stdlib.h>
+#include "un-namespace.h"
+#include "mt_misc.h"
+
+/*
+ * svcauthsw is the bdevsw of server side authentication.
+ *
+ * Server side authenticators are called from authenticate by
+ * using the client auth struct flavor field to index into svcauthsw.
+ * The server auth flavors must implement a routine that looks
+ * like:
+ *
+ *	enum auth_stat
+ *	flavorx_auth(rqst, msg)
+ *		struct svc_req *rqst;
+ *		struct rpc_msg *msg;
+ *
+ */
+
+/* declarations to allow servers to specify new authentication flavors */
+struct authsvc {
+	int	flavor;
+	enum	auth_stat (*handler)(struct svc_req *, struct rpc_msg *);
+	struct	authsvc	  *next;
+};
+static struct authsvc *Auths = NULL;
+
+struct svc_auth_ops svc_auth_null_ops;
+
+/*
+ * The call rpc message, msg has been obtained from the wire.  The msg contains
+ * the raw form of credentials and verifiers.  authenticate returns AUTH_OK
+ * if the msg is successfully authenticated.  If AUTH_OK then the routine also
+ * does the following things:
+ * set rqst->rq_xprt->verf to the appropriate response verifier;
+ * sets rqst->rq_client_cred to the "cooked" form of the credentials.
+ *
+ * NB: rqst->rq_cxprt->verf must be pre-alloctaed;
+ * its length is set appropriately.
+ *
+ * The caller still owns and is responsible for msg->u.cmb.cred and
+ * msg->u.cmb.verf.  The authentication system retains ownership of
+ * rqst->rq_client_cred, the cooked credentials.
+ *
+ * There is an assumption that any flavour less than AUTH_NULL is
+ * invalid.
+ */
+enum auth_stat
+_authenticate(rqst, msg)
+	struct svc_req *rqst;
+	struct rpc_msg *msg;
+{
+	int cred_flavor;
+	struct authsvc *asp;
+	enum auth_stat dummy;
+
+/* VARIABLES PROTECTED BY authsvc_lock: asp, Auths */
+
+	rqst->rq_cred = msg->rm_call.cb_cred;
+	SVC_AUTH(rqst->rq_xprt).svc_ah_ops = &svc_auth_null_ops;
+	SVC_AUTH(rqst->rq_xprt).svc_ah_private = NULL;
+	rqst->rq_xprt->xp_verf.oa_flavor = _null_auth.oa_flavor;
+	rqst->rq_xprt->xp_verf.oa_length = 0;
+	cred_flavor = rqst->rq_cred.oa_flavor;
+	switch (cred_flavor) {
+	case AUTH_NULL:
+		dummy = _svcauth_null(rqst, msg);
+		return (dummy);
+	case AUTH_SYS:
+		dummy = _svcauth_unix(rqst, msg);
+		return (dummy);
+	case AUTH_SHORT:
+		dummy = _svcauth_short(rqst, msg);
+		return (dummy);
+#ifdef DES_BUILTIN
+	case AUTH_DES:
+		dummy = _svcauth_des(rqst, msg);
+		return (dummy);
+#endif
+	default:
+		break;
+	}
+
+	/* flavor doesn't match any of the builtin types, so try new ones */
+	mutex_lock(&authsvc_lock);
+	for (asp = Auths; asp; asp = asp->next) {
+		if (asp->flavor == cred_flavor) {
+			enum auth_stat as;
+
+			as = (*asp->handler)(rqst, msg);
+			mutex_unlock(&authsvc_lock);
+			return (as);
+		}
+	}
+	mutex_unlock(&authsvc_lock);
+
+	return (AUTH_REJECTEDCRED);
+}
+
+/*
+ * A set of null auth methods used by any authentication protocols
+ * that don't need to inspect or modify the message body.
+ */
+static bool_t
+svcauth_null_wrap(auth, xdrs, xdr_func, xdr_ptr)
+	SVCAUTH *auth;
+	XDR *xdrs;
+	xdrproc_t xdr_func;
+	caddr_t xdr_ptr;
+{
+
+	return (xdr_func(xdrs, xdr_ptr));
+}
+
+struct svc_auth_ops svc_auth_null_ops = {
+	svcauth_null_wrap,
+	svcauth_null_wrap,
+};
+
+/*ARGSUSED*/
+enum auth_stat
+_svcauth_null(rqst, msg)
+	struct svc_req *rqst;
+	struct rpc_msg *msg;
+{
+	return (AUTH_OK);
+}
+
+/*
+ *  Allow the rpc service to register new authentication types that it is
+ *  prepared to handle.  When an authentication flavor is registered,
+ *  the flavor is checked against already registered values.  If not
+ *  registered, then a new Auths entry is added on the list.
+ *
+ *  There is no provision to delete a registration once registered.
+ *
+ *  This routine returns:
+ *	 0 if registration successful
+ *	 1 if flavor already registered
+ *	-1 if can't register (errno set)
+ */
+
+int
+svc_auth_reg(cred_flavor, handler)
+	int cred_flavor;
+	enum auth_stat (*handler)(struct svc_req *, struct rpc_msg *);
+{
+	struct authsvc *asp;
+
+	switch (cred_flavor) {
+	    case AUTH_NULL:
+	    case AUTH_SYS:
+	    case AUTH_SHORT:
+#ifdef DES_BUILTIN
+	    case AUTH_DES:
+#endif
+		/* already registered */
+		return (1);
+
+	    default:
+		mutex_lock(&authsvc_lock);
+		for (asp = Auths; asp; asp = asp->next) {
+			if (asp->flavor == cred_flavor) {
+				/* already registered */
+				mutex_unlock(&authsvc_lock);
+				return (1);
+			}
+		}
+
+		/* this is a new one, so go ahead and register it */
+		asp = mem_alloc(sizeof (*asp));
+		if (asp == NULL) {
+			mutex_unlock(&authsvc_lock);
+			return (-1);
+		}
+		asp->flavor = cred_flavor;
+		asp->handler = handler;
+		asp->next = Auths;
+		Auths = asp;
+		mutex_unlock(&authsvc_lock);
+		break;
+	}
+	return (0);
+}
Index: freebsd/lib/libc/rpc/svc_auth_des.c
===================================================================
--- freebsd/lib/libc/rpc/svc_auth_des.c	(revision 60b1d40751c8b3235b7ccbf3bb6ad0c562562f01)
+++ freebsd/lib/libc/rpc/svc_auth_des.c	(revision 60b1d40751c8b3235b7ccbf3bb6ad0c562562f01)
@@ -0,0 +1,539 @@
+#include <machine/rtems-bsd-user-space.h>
+
+
+/*
+ * Copyright (c) 1988 by Sun Microsystems, Inc.
+ */
+
+/*-
+ * Copyright (c) 2009, Sun Microsystems, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions are met:
+ * - Redistributions of source code must retain the above copyright notice, 
+ *   this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice, 
+ *   this list of conditions and the following disclaimer in the documentation 
+ *   and/or other materials provided with the distribution.
+ * - Neither the name of Sun Microsystems, Inc. nor the names of its 
+ *   contributors may be used to endorse or promote products derived 
+ *   from this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * svcauth_des.c, server-side des authentication
+ *
+ * We insure for the service the following:
+ * (1) The timestamp microseconds do not exceed 1 million.
+ * (2) The timestamp plus the window is less than the current time.
+ * (3) The timestamp is not less than the one previously
+ *     seen in the current session.
+ *
+ * It is up to the server to determine if the window size is
+ * too small .
+ *
+ */
+
+#include "namespace.h"
+#include "reentrant.h"
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <rpc/des_crypt.h>
+#include <rtems/bsd/sys/param.h>
+#include <netinet/in.h>
+#include <rpc/types.h>
+#include <rpc/xdr.h>
+#include <rpc/auth.h>
+#include <rpc/auth_des.h>
+#include <rpc/svc.h>
+#include <rpc/rpc_msg.h>
+#include <rpc/svc_auth.h>
+#include "libc_private.h"
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = 	"@(#)svcauth_des.c	2.3 89/07/11 4.0 RPCSRC; from 1.15 88/02/08 SMI";
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+extern int key_decryptsession_pk(const char *, netobj *, des_block *);
+
+#define debug(msg)	 printf("svcauth_des: %s\n", msg) 
+
+#define USEC_PER_SEC ((u_long) 1000000L)
+#define BEFORE(t1, t2) timercmp(t1, t2, <)
+
+/*
+ * LRU cache of conversation keys and some other useful items.
+ */
+#define AUTHDES_CACHESZ 64
+struct cache_entry {
+	des_block key;		/* conversation key */
+	char *rname;		/* client's name */
+	u_int window;		/* credential lifetime window */
+	struct timeval laststamp;	/* detect replays of creds */
+	char *localcred;	/* generic local credential */
+};
+static struct cache_entry *authdes_cache/* [AUTHDES_CACHESZ] */;
+static short *authdes_lru/* [AUTHDES_CACHESZ] */;
+
+static void cache_init();	/* initialize the cache */
+static short cache_spot();	/* find an entry in the cache */
+static void cache_ref(/*short sid*/);	/* note that sid was ref'd */
+
+static void invalidate();	/* invalidate entry in cache */
+
+/*
+ * cache statistics 
+ */
+static struct {
+	u_long ncachehits;	/* times cache hit, and is not replay */
+	u_long ncachereplays;	/* times cache hit, and is replay */
+	u_long ncachemisses;	/* times cache missed */
+} svcauthdes_stats;
+
+/*
+ * Service side authenticator for AUTH_DES
+ */
+enum auth_stat
+_svcauth_des(rqst, msg)
+	struct svc_req *rqst;
+	struct rpc_msg *msg;
+{
+
+	long *ixdr;
+	des_block cryptbuf[2];
+	struct authdes_cred *cred;
+	struct authdes_verf verf;
+	int status;
+	struct cache_entry *entry;
+	short sid = 0;
+	des_block *sessionkey;
+	des_block ivec;
+	u_int window;
+	struct timeval timestamp;
+	u_long namelen;
+	struct area {
+		struct authdes_cred area_cred;
+		char area_netname[MAXNETNAMELEN+1];
+	} *area;
+
+	if (authdes_cache == NULL) {
+		cache_init();
+	}
+
+	area = (struct area *)rqst->rq_clntcred;
+	cred = (struct authdes_cred *)&area->area_cred;
+
+	/*
+	 * Get the credential
+	 */
+	ixdr = (long *)msg->rm_call.cb_cred.oa_base;
+	cred->adc_namekind = IXDR_GET_ENUM(ixdr, enum authdes_namekind);
+	switch (cred->adc_namekind) {
+	case ADN_FULLNAME:
+		namelen = IXDR_GET_U_LONG(ixdr);
+		if (namelen > MAXNETNAMELEN) {
+			return (AUTH_BADCRED);
+		}
+		cred->adc_fullname.name = area->area_netname;
+		bcopy((char *)ixdr, cred->adc_fullname.name, 
+			(u_int)namelen);
+		cred->adc_fullname.name[namelen] = 0;
+		ixdr += (RNDUP(namelen) / BYTES_PER_XDR_UNIT);
+		cred->adc_fullname.key.key.high = (u_long)*ixdr++;
+		cred->adc_fullname.key.key.low = (u_long)*ixdr++;
+		cred->adc_fullname.window = (u_long)*ixdr++;
+		break;
+	case ADN_NICKNAME:
+		cred->adc_nickname = (u_long)*ixdr++;
+		break;
+	default:
+		return (AUTH_BADCRED);	
+	}
+
+	/*
+	 * Get the verifier
+	 */
+	ixdr = (long *)msg->rm_call.cb_verf.oa_base;
+	verf.adv_xtimestamp.key.high = (u_long)*ixdr++;
+	verf.adv_xtimestamp.key.low =  (u_long)*ixdr++;
+	verf.adv_int_u = (u_long)*ixdr++;
+
+
+	/*
+	 * Get the conversation key
+ 	 */
+	if (cred->adc_namekind == ADN_FULLNAME) {
+		netobj pkey;
+		char pkey_data[1024];
+
+		sessionkey = &cred->adc_fullname.key;
+		if (! getpublickey(cred->adc_fullname.name, pkey_data)) {
+			debug("getpublickey");
+			return(AUTH_BADCRED);
+		}
+		pkey.n_bytes = pkey_data;
+		pkey.n_len = strlen(pkey_data) + 1;
+		if (key_decryptsession_pk(cred->adc_fullname.name, &pkey,
+				       sessionkey) < 0) {
+			debug("decryptsessionkey");
+			return (AUTH_BADCRED); /* key not found */
+		}
+	} else { /* ADN_NICKNAME */	
+		sid = (short)cred->adc_nickname;
+		if (sid < 0 || sid >= AUTHDES_CACHESZ) {
+			debug("bad nickname");
+			return (AUTH_BADCRED);	/* garbled credential */
+		}
+		sessionkey = &authdes_cache[sid].key;
+	}
+
+
+	/*
+	 * Decrypt the timestamp
+	 */
+	cryptbuf[0] = verf.adv_xtimestamp; 
+	if (cred->adc_namekind == ADN_FULLNAME) {
+		cryptbuf[1].key.high = cred->adc_fullname.window;
+		cryptbuf[1].key.low = verf.adv_winverf;
+		ivec.key.high = ivec.key.low = 0;	
+		status = cbc_crypt((char *)sessionkey, (char *)cryptbuf,
+			2*sizeof(des_block), DES_DECRYPT | DES_HW, 
+			(char *)&ivec);
+	} else {
+		status = ecb_crypt((char *)sessionkey, (char *)cryptbuf,
+			sizeof(des_block), DES_DECRYPT | DES_HW);
+	}
+	if (DES_FAILED(status)) {
+		debug("decryption failure");
+		return (AUTH_FAILED);	/* system error */
+	}
+
+	/*
+	 * XDR the decrypted timestamp
+	 */
+	ixdr = (long *)cryptbuf;
+	timestamp.tv_sec = IXDR_GET_LONG(ixdr);
+	timestamp.tv_usec = IXDR_GET_LONG(ixdr);
+
+	/*
+ 	 * Check for valid credentials and verifiers.
+	 * They could be invalid because the key was flushed
+	 * out of the cache, and so a new session should begin.
+	 * Be sure and send AUTH_REJECTED{CRED, VERF} if this is the case.
+	 */
+	{
+		struct timeval current;
+		int nick;
+		int winverf;
+
+		if (cred->adc_namekind == ADN_FULLNAME) {
+			window = IXDR_GET_U_LONG(ixdr);
+			winverf = IXDR_GET_U_LONG(ixdr);
+			if (winverf != window - 1) {
+				debug("window verifier mismatch");
+				return (AUTH_BADCRED);	/* garbled credential */
+			}
+			sid = cache_spot(sessionkey, cred->adc_fullname.name, 
+			    &timestamp);
+			if (sid < 0) {
+				debug("replayed credential");
+				return (AUTH_REJECTEDCRED);	/* replay */
+			}
+			nick = 0;
+		} else {	/* ADN_NICKNAME */
+			window = authdes_cache[sid].window;
+			nick = 1;
+		}
+
+		if ((u_long)timestamp.tv_usec >= USEC_PER_SEC) {
+			debug("invalid usecs");
+			/* cached out (bad key), or garbled verifier */
+			return (nick ? AUTH_REJECTEDVERF : AUTH_BADVERF);
+		}
+		if (nick && BEFORE(&timestamp, 
+				   &authdes_cache[sid].laststamp)) {
+			debug("timestamp before last seen");
+			return (AUTH_REJECTEDVERF);	/* replay */
+		}
+		(void) gettimeofday(&current, (struct timezone *)NULL);
+		current.tv_sec -= window;	/* allow for expiration */
+		if (!BEFORE(&current, &timestamp)) {
+			debug("timestamp expired");
+			/* replay, or garbled credential */
+			return (nick ? AUTH_REJECTEDVERF : AUTH_BADCRED);
+		}
+	}
+
+	/*
+	 * Set up the reply verifier
+	 */
+	verf.adv_nickname = (u_long)sid;
+
+	/*
+	 * xdr the timestamp before encrypting
+	 */
+	ixdr = (long *)cryptbuf;
+	IXDR_PUT_LONG(ixdr, timestamp.tv_sec - 1);
+	IXDR_PUT_LONG(ixdr, timestamp.tv_usec);
+
+	/*	 
+	 * encrypt the timestamp
+	 */
+	status = ecb_crypt((char *)sessionkey, (char *)cryptbuf,
+	    sizeof(des_block), DES_ENCRYPT | DES_HW);
+	if (DES_FAILED(status)) {
+		debug("encryption failure");
+		return (AUTH_FAILED);	/* system error */
+	}
+	verf.adv_xtimestamp = cryptbuf[0];
+
+	/*
+	 * Serialize the reply verifier, and update rqst
+	 */
+	ixdr = (long *)msg->rm_call.cb_verf.oa_base;
+	*ixdr++ = (long)verf.adv_xtimestamp.key.high;
+	*ixdr++ = (long)verf.adv_xtimestamp.key.low;
+	*ixdr++ = (long)verf.adv_int_u;
+
+	rqst->rq_xprt->xp_verf.oa_flavor = AUTH_DES;
+	rqst->rq_xprt->xp_verf.oa_base = msg->rm_call.cb_verf.oa_base;
+	rqst->rq_xprt->xp_verf.oa_length = 
+		(char *)ixdr - msg->rm_call.cb_verf.oa_base;
+
+	/*
+	 * We succeeded, commit the data to the cache now and
+	 * finish cooking the credential.
+	 */
+	entry = &authdes_cache[sid];
+	entry->laststamp = timestamp;
+	cache_ref(sid);
+	if (cred->adc_namekind == ADN_FULLNAME) {
+		cred->adc_fullname.window = window;
+		cred->adc_nickname = (u_long)sid;	/* save nickname */
+		if (entry->rname != NULL) {
+			mem_free(entry->rname, strlen(entry->rname) + 1);
+		}
+		entry->rname = (char *)mem_alloc((u_int)strlen(cred->adc_fullname.name)
+					 + 1);
+		if (entry->rname != NULL) {
+			(void) strcpy(entry->rname, cred->adc_fullname.name);
+		} else {
+			debug("out of memory");
+		}
+		entry->key = *sessionkey;
+		entry->window = window;
+		invalidate(entry->localcred); /* mark any cached cred invalid */
+	} else { /* ADN_NICKNAME */
+		/*
+		 * nicknames are cooked into fullnames
+		 */	
+		cred->adc_namekind = ADN_FULLNAME;
+		cred->adc_fullname.name = entry->rname;
+		cred->adc_fullname.key = entry->key;
+		cred->adc_fullname.window = entry->window;
+	}
+	return (AUTH_OK);	/* we made it!*/
+}
+
+
+/*
+ * Initialize the cache
+ */
+static void
+cache_init()
+{
+	int i;
+
+	authdes_cache = (struct cache_entry *)
+		mem_alloc(sizeof(struct cache_entry) * AUTHDES_CACHESZ);	
+	bzero((char *)authdes_cache, 
+		sizeof(struct cache_entry) * AUTHDES_CACHESZ);
+
+	authdes_lru = (short *)mem_alloc(sizeof(short) * AUTHDES_CACHESZ);
+	/*
+	 * Initialize the lru list
+	 */
+	for (i = 0; i < AUTHDES_CACHESZ; i++) {
+		authdes_lru[i] = i;
+	}
+}
+
+
+/*
+ * Find the lru victim
+ */
+static short
+cache_victim()
+{
+	return (authdes_lru[AUTHDES_CACHESZ-1]);
+}
+
+/*
+ * Note that sid was referenced
+ */
+static void
+cache_ref(sid)
+	short sid;
+{
+	int i;
+	short curr;
+	short prev;
+
+	prev = authdes_lru[0];
+	authdes_lru[0] = sid;
+	for (i = 1; prev != sid; i++) {
+		curr = authdes_lru[i];
+		authdes_lru[i] = prev;
+		prev = curr;
+	}
+}
+
+
+/*
+ * Find a spot in the cache for a credential containing
+ * the items given.  Return -1 if a replay is detected, otherwise
+ * return the spot in the cache.
+ */
+static short
+cache_spot(key, name, timestamp)
+	des_block *key;
+	char *name;
+	struct timeval *timestamp;
+{
+	struct cache_entry *cp;
+	int i;
+	u_long hi;
+
+	hi = key->key.high;
+	for (cp = authdes_cache, i = 0; i < AUTHDES_CACHESZ; i++, cp++) {
+		if (cp->key.key.high == hi && 
+		    cp->key.key.low == key->key.low &&
+		    cp->rname != NULL &&
+		    bcmp(cp->rname, name, strlen(name) + 1) == 0) {
+			if (BEFORE(timestamp, &cp->laststamp)) {
+				svcauthdes_stats.ncachereplays++;
+				return (-1); /* replay */
+			}
+			svcauthdes_stats.ncachehits++;
+			return (i);	/* refresh */
+		}
+	}
+	svcauthdes_stats.ncachemisses++;
+	return (cache_victim());	/* new credential */
+}
+
+
+#if (defined(sun) || defined(vax) || defined(__FreeBSD__))
+/*
+ * Local credential handling stuff.
+ * NOTE: bsd unix dependent.
+ * Other operating systems should put something else here.
+ */
+#define UNKNOWN 	-2	/* grouplen, if cached cred is unknown user */
+#define INVALID		-1 	/* grouplen, if cache entry is invalid */
+
+struct bsdcred {
+	uid_t uid;		/* cached uid */
+	gid_t gid;		/* cached gid */
+	int grouplen;	/* length of cached groups */
+	gid_t groups[NGRPS];	/* cached groups */
+};
+
+/*
+ * Map a des credential into a unix cred.
+ * We cache the credential here so the application does
+ * not have to make an rpc call every time to interpret
+ * the credential.
+ */
+int
+authdes_getucred(adc, uid, gid, grouplen, groups)
+	struct authdes_cred *adc;
+	uid_t *uid;
+	gid_t *gid;
+	int *grouplen;
+	gid_t *groups;
+{
+	unsigned sid;
+	int i;
+	uid_t i_uid;	
+	gid_t i_gid;
+	int i_grouplen;
+	struct bsdcred *cred;
+
+	sid = adc->adc_nickname;
+	if (sid >= AUTHDES_CACHESZ) {
+		debug("invalid nickname");
+		return (0);
+	}
+	cred = (struct bsdcred *)authdes_cache[sid].localcred;
+	if (cred == NULL) {
+		cred = (struct bsdcred *)mem_alloc(sizeof(struct bsdcred));
+		authdes_cache[sid].localcred = (char *)cred;
+		cred->grouplen = INVALID;
+	}
+	if (cred->grouplen == INVALID) {
+		/*
+		 * not in cache: lookup
+		 */
+		if (!netname2user(adc->adc_fullname.name, &i_uid, &i_gid, 
+			&i_grouplen, groups))
+		{
+			debug("unknown netname");
+			cred->grouplen = UNKNOWN;	/* mark as lookup up, but not found */
+			return (0);
+		}
+		debug("missed ucred cache");
+		*uid = cred->uid = i_uid;
+		*gid = cred->gid = i_gid;
+		*grouplen = cred->grouplen = i_grouplen;
+		for (i = i_grouplen - 1; i >= 0; i--) {
+			cred->groups[i] = groups[i]; /* int to short */
+		}
+		return (1);
+	} else if (cred->grouplen == UNKNOWN) {
+		/*
+		 * Already lookup up, but no match found
+		 */	
+		return (0);
+	}
+
+	/*
+	 * cached credentials
+	 */
+	*uid = cred->uid;
+	*gid = cred->gid;
+	*grouplen = cred->grouplen;
+	for (i = cred->grouplen - 1; i >= 0; i--) {
+		groups[i] = cred->groups[i];	/* short to int */
+	}
+	return (1);
+}
+
+static void
+invalidate(cred)
+	char *cred;
+{
+	if (cred == NULL) {
+		return;
+	}
+	((struct bsdcred *)cred)->grouplen = INVALID;
+}
+#endif
+
Index: freebsd/lib/libc/rpc/svc_auth_unix.c
===================================================================
--- freebsd/lib/libc/rpc/svc_auth_unix.c	(revision 60b1d40751c8b3235b7ccbf3bb6ad0c562562f01)
+++ freebsd/lib/libc/rpc/svc_auth_unix.c	(revision 60b1d40751c8b3235b7ccbf3bb6ad0c562562f01)
@@ -0,0 +1,157 @@
+#include <machine/rtems-bsd-user-space.h>
+
+/*-
+ * Copyright (c) 2009, Sun Microsystems, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions are met:
+ * - Redistributions of source code must retain the above copyright notice, 
+ *   this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice, 
+ *   this list of conditions and the following disclaimer in the documentation 
+ *   and/or other materials provided with the distribution.
+ * - Neither the name of Sun Microsystems, Inc. nor the names of its 
+ *   contributors may be used to endorse or promote products derived 
+ *   from this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char *sccsid2 = "@(#)svc_auth_unix.c 1.28 88/02/08 Copyr 1984 Sun Micro";
+static char *sccsid = "@(#)svc_auth_unix.c	2.3 88/08/01 4.0 RPCSRC";
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * svc_auth_unix.c
+ * Handles UNIX flavor authentication parameters on the service side of rpc.
+ * There are two svc auth implementations here: AUTH_UNIX and AUTH_SHORT.
+ * _svcauth_unix does full blown unix style uid,gid+gids auth,
+ * _svcauth_short uses a shorthand auth to index into a cache of longhand auths.
+ * Note: the shorthand has been gutted for efficiency.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#include "namespace.h"
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <rpc/rpc.h>
+#include "un-namespace.h"
+
+/*
+ * Unix longhand authenticator
+ */
+enum auth_stat
+_svcauth_unix(rqst, msg)
+	struct svc_req *rqst;
+	struct rpc_msg *msg;
+{
+	enum auth_stat stat;
+	XDR xdrs;
+	struct authunix_parms *aup;
+	int32_t *buf;
+	struct area {
+		struct authunix_parms area_aup;
+		char area_machname[MAX_MACHINE_NAME+1];
+		u_int area_gids[NGRPS];
+	} *area;
+	u_int auth_len;
+	size_t str_len, gid_len;
+	u_int i;
+
+	assert(rqst != NULL);
+	assert(msg != NULL);
+
+	area = (struct area *) rqst->rq_clntcred;
+	aup = &area->area_aup;
+	aup->aup_machname = area->area_machname;
+	aup->aup_gids = area->area_gids;
+	auth_len = (u_int)msg->rm_call.cb_cred.oa_length;
+	xdrmem_create(&xdrs, msg->rm_call.cb_cred.oa_base, auth_len,XDR_DECODE);
+	buf = XDR_INLINE(&xdrs, auth_len);
+	if (buf != NULL) {
+		aup->aup_time = IXDR_GET_INT32(buf);
+		str_len = (size_t)IXDR_GET_U_INT32(buf);
+		if (str_len > MAX_MACHINE_NAME) {
+			stat = AUTH_BADCRED;
+			goto done;
+		}
+		memmove(aup->aup_machname, buf, str_len);
+		aup->aup_machname[str_len] = 0;
+		str_len = RNDUP(str_len);
+		buf += str_len / sizeof (int32_t);
+		aup->aup_uid = (int)IXDR_GET_INT32(buf);
+		aup->aup_gid = (int)IXDR_GET_INT32(buf);
+		gid_len = (size_t)IXDR_GET_U_INT32(buf);
+		if (gid_len > NGRPS) {
+			stat = AUTH_BADCRED;
+			goto done;
+		}
+		aup->aup_len = gid_len;
+		for (i = 0; i < gid_len; i++) {
+			aup->aup_gids[i] = (int)IXDR_GET_INT32(buf);
+		}
+		/*
+		 * five is the smallest unix credentials structure -
+		 * timestamp, hostname len (0), uid, gid, and gids len (0).
+		 */
+		if ((5 + gid_len) * BYTES_PER_XDR_UNIT + str_len > auth_len) {
+			(void) printf("bad auth_len gid %ld str %ld auth %u\n",
+			    (long)gid_len, (long)str_len, auth_len);
+			stat = AUTH_BADCRED;
+			goto done;
+		}
+	} else if (! xdr_authunix_parms(&xdrs, aup)) {
+		xdrs.x_op = XDR_FREE;
+		(void)xdr_authunix_parms(&xdrs, aup);
+		stat = AUTH_BADCRED;
+		goto done;
+	}
+
+       /* get the verifier */
+	if ((u_int)msg->rm_call.cb_verf.oa_length) {
+		rqst->rq_xprt->xp_verf.oa_flavor =
+			msg->rm_call.cb_verf.oa_flavor;
+		rqst->rq_xprt->xp_verf.oa_base =
+			msg->rm_call.cb_verf.oa_base;
+		rqst->rq_xprt->xp_verf.oa_length =
+			msg->rm_call.cb_verf.oa_length;
+	} else {
+		rqst->rq_xprt->xp_verf.oa_flavor = AUTH_NULL;
+		rqst->rq_xprt->xp_verf.oa_length = 0;
+	}
+	stat = AUTH_OK;
+done:
+	XDR_DESTROY(&xdrs);
+	return (stat);
+}
+
+
+/*
+ * Shorthand unix authenticator
+ * Looks up longhand in a cache.
+ */
+/*ARGSUSED*/
+enum auth_stat 
+_svcauth_short(rqst, msg)
+	struct svc_req *rqst;
+	struct rpc_msg *msg;
+{
+	return (AUTH_REJECTEDCRED);
+}
Index: freebsd/lib/libc/rpc/svc_dg.c
===================================================================
--- freebsd/lib/libc/rpc/svc_dg.c	(revision 60b1d40751c8b3235b7ccbf3bb6ad0c562562f01)
+++ freebsd/lib/libc/rpc/svc_dg.c	(revision 60b1d40751c8b3235b7ccbf3bb6ad0c562562f01)
@@ -0,0 +1,740 @@
+#include <machine/rtems-bsd-user-space.h>
+
+/*	$NetBSD: svc_dg.c,v 1.4 2000/07/06 03:10:35 christos Exp $	*/
+
+/*-
+ * Copyright (c) 2009, Sun Microsystems, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions are met:
+ * - Redistributions of source code must retain the above copyright notice, 
+ *   this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice, 
+ *   this list of conditions and the following disclaimer in the documentation 
+ *   and/or other materials provided with the distribution.
+ * - Neither the name of Sun Microsystems, Inc. nor the names of its 
+ *   contributors may be used to endorse or promote products derived 
+ *   from this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Copyright (c) 1986-1991 by Sun Microsystems Inc.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+#ident	"@(#)svc_dg.c	1.17	94/04/24 SMI"
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * svc_dg.c, Server side for connectionless RPC.
+ *
+ * Does some caching in the hopes of achieving execute-at-most-once semantics.
+ */
+
+#include "namespace.h"
+#include "reentrant.h"
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <rpc/rpc.h>
+#include <rpc/svc_dg.h>
+#include <assert.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef RPC_CACHE_DEBUG
+#include <netconfig.h>
+#include <netdir.h>
+#endif
+#include <err.h>
+#include "un-namespace.h"
+
+#include "rpc_com.h"
+#include "mt_misc.h"
+
+#define	su_data(xprt)	((struct svc_dg_data *)(xprt->xp_p2))
+#define	rpc_buffer(xprt) ((xprt)->xp_p1)
+
+#ifndef MAX
+#define	MAX(a, b)	(((a) > (b)) ? (a) : (b))
+#endif
+
+static void svc_dg_ops(SVCXPRT *);
+static enum xprt_stat svc_dg_stat(SVCXPRT *);
+static bool_t svc_dg_recv(SVCXPRT *, struct rpc_msg *);
+static bool_t svc_dg_reply(SVCXPRT *, struct rpc_msg *);
+static bool_t svc_dg_getargs(SVCXPRT *, xdrproc_t, void *);
+static bool_t svc_dg_freeargs(SVCXPRT *, xdrproc_t, void *);
+static void svc_dg_destroy(SVCXPRT *);
+static bool_t svc_dg_control(SVCXPRT *, const u_int, void *);
+static int cache_get(SVCXPRT *, struct rpc_msg *, char **, size_t *);
+static void cache_set(SVCXPRT *, size_t);
+int svc_dg_enablecache(SVCXPRT *, u_int);
+
+/*
+ * Usage:
+ *	xprt = svc_dg_create(sock, sendsize, recvsize);
+ * Does other connectionless specific initializations.
+ * Once *xprt is initialized, it is registered.
+ * see (svc.h, xprt_register). If recvsize or sendsize are 0 suitable
+ * system defaults are chosen.
+ * The routines returns NULL if a problem occurred.
+ */
+static const char svc_dg_str[] = "svc_dg_create: %s";
+static const char svc_dg_err1[] = "could not get transport information";
+static const char svc_dg_err2[] = "transport does not support data transfer";
+static const char svc_dg_err3[] = "getsockname failed";
+static const char svc_dg_err4[] = "cannot set IP_RECVDSTADDR";
+static const char __no_mem_str[] = "out of memory";
+
+SVCXPRT *
+svc_dg_create(fd, sendsize, recvsize)
+	int fd;
+	u_int sendsize;
+	u_int recvsize;
+{
+	SVCXPRT *xprt;
+	struct svc_dg_data *su = NULL;
+	struct __rpc_sockinfo si;
+	struct sockaddr_storage ss;
+	socklen_t slen;
+
+	if (!__rpc_fd2sockinfo(fd, &si)) {
+		warnx(svc_dg_str, svc_dg_err1);
+		return (NULL);
+	}
+	/*
+	 * Find the receive and the send size
+	 */
+	sendsize = __rpc_get_t_size(si.si_af, si.si_proto, (int)sendsize);
+	recvsize = __rpc_get_t_size(si.si_af, si.si_proto, (int)recvsize);
+	if ((sendsize == 0) || (recvsize == 0)) {
+		warnx(svc_dg_str, svc_dg_err2);
+		return (NULL);
+	}
+
+	xprt = svc_xprt_alloc();
+	if (xprt == NULL)
+		goto freedata;
+
+	su = mem_alloc(sizeof (*su));
+	if (su == NULL)
+		goto freedata;
+	su->su_iosz = ((MAX(sendsize, recvsize) + 3) / 4) * 4;
+	if ((rpc_buffer(xprt) = mem_alloc(su->su_iosz)) == NULL)
+		goto freedata;
+	xdrmem_create(&(su->su_xdrs), rpc_buffer(xprt), su->su_iosz,
+		XDR_DECODE);
+	su->su_cache = NULL;
+	xprt->xp_fd = fd;
+	xprt->xp_p2 = su;
+	xprt->xp_verf.oa_base = su->su_verfbody;
+	svc_dg_ops(xprt);
+	xprt->xp_rtaddr.maxlen = sizeof (struct sockaddr_storage);
+
+	slen = sizeof ss;
+	if (_getsockname(fd, (struct sockaddr *)(void *)&ss, &slen) < 0) {
+		warnx(svc_dg_str, svc_dg_err3);
+		goto freedata_nowarn;
+	}
+	xprt->xp_ltaddr.buf = mem_alloc(sizeof (struct sockaddr_storage));
+	xprt->xp_ltaddr.maxlen = sizeof (struct sockaddr_storage);
+	xprt->xp_ltaddr.len = slen;
+	memcpy(xprt->xp_ltaddr.buf, &ss, slen);
+
+	if (ss.ss_family == AF_INET) {
+		struct sockaddr_in *sin;
+		static const int true_value = 1;
+
+		sin = (struct sockaddr_in *)(void *)&ss;
+		if (sin->sin_addr.s_addr == INADDR_ANY) {
+		    su->su_srcaddr.buf = mem_alloc(sizeof (ss));
+		    su->su_srcaddr.maxlen = sizeof (ss);
+
+		    if (_setsockopt(fd, IPPROTO_IP, IP_RECVDSTADDR,
+				    &true_value, sizeof(true_value))) {
+			    warnx(svc_dg_str,  svc_dg_err4);
+			    goto freedata_nowarn;
+		    }
+		}
+	}
+
+	xprt_register(xprt);
+	return (xprt);
+freedata:
+	(void) warnx(svc_dg_str, __no_mem_str);
+freedata_nowarn:
+	if (xprt) {
+		if (su)
+			(void) mem_free(su, sizeof (*su));
+		svc_xprt_free(xprt);
+	}
+	return (NULL);
+}
+
+/*ARGSUSED*/
+static enum xprt_stat
+svc_dg_stat(xprt)
+	SVCXPRT *xprt;
+{
+	return (XPRT_IDLE);
+}
+
+static int
+svc_dg_recvfrom(int fd, char *buf, int buflen,
+    struct sockaddr *raddr, socklen_t *raddrlen,
+    struct sockaddr *laddr, socklen_t *laddrlen)
+{
+	struct msghdr msg;
+	struct iovec msg_iov[1];
+	struct sockaddr_in *lin = (struct sockaddr_in *)laddr;
+	int rlen;
+	bool_t have_lin = FALSE;
+	char tmp[CMSG_LEN(sizeof(*lin))];
+	struct cmsghdr *cmsg;
+
+	memset((char *)&msg, 0, sizeof(msg));
+	msg_iov[0].iov_base = buf;
+	msg_iov[0].iov_len = buflen;
+	msg.msg_iov = msg_iov;
+	msg.msg_iovlen = 1;
+	msg.msg_namelen = *raddrlen;
+	msg.msg_name = (char *)raddr;
+	if (laddr != NULL) {
+	    msg.msg_control = (caddr_t)tmp;
+	    msg.msg_controllen = CMSG_LEN(sizeof(*lin));
+	}
+	rlen = _recvmsg(fd, &msg, 0);
+	if (rlen >= 0)
+		*raddrlen = msg.msg_namelen;
+
+	if (rlen == -1 || laddr == NULL ||
+	    msg.msg_controllen < sizeof(struct cmsghdr) ||
+	    msg.msg_flags & MSG_CTRUNC)
+		return rlen;
+
+	for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL;
+	     cmsg = CMSG_NXTHDR(&msg, cmsg)) {
+		if (cmsg->cmsg_level == IPPROTO_IP &&
+		    cmsg->cmsg_type == IP_RECVDSTADDR) {
+			have_lin = TRUE;
+			memcpy(&lin->sin_addr,
+			    (struct in_addr *)CMSG_DATA(cmsg),
+			    sizeof(struct in_addr));
+			break;
+		}
+	}
+
+	lin->sin_family = AF_INET;
+	lin->sin_port = 0;
+	*laddrlen = sizeof(struct sockaddr_in);
+
+	if (!have_lin)
+		lin->sin_addr.s_addr = INADDR_ANY;
+
+	return rlen;
+}
+
+static bool_t
+svc_dg_recv(xprt, msg)
+	SVCXPRT *xprt;
+	struct rpc_msg *msg;
+{
+	struct svc_dg_data *su = su_data(xprt);
+	XDR *xdrs = &(su->su_xdrs);
+	char *reply;
+	struct sockaddr_storage ss;
+	socklen_t alen;
+	size_t replylen;
+	ssize_t rlen;
+
+again:
+	alen = sizeof (struct sockaddr_storage);
+	rlen = svc_dg_recvfrom(xprt->xp_fd, rpc_buffer(xprt), su->su_iosz,
+	    (struct sockaddr *)(void *)&ss, &alen,
+	    (struct sockaddr *)su->su_srcaddr.buf, &su->su_srcaddr.len);
+	if (rlen == -1 && errno == EINTR)
+		goto again;
+	if (rlen == -1 || (rlen < (ssize_t)(4 * sizeof (u_int32_t))))
+		return (FALSE);
+	if (xprt->xp_rtaddr.len < alen) {
+		if (xprt->xp_rtaddr.len != 0)
+			mem_free(xprt->xp_rtaddr.buf, xprt->xp_rtaddr.len);
+		xprt->xp_rtaddr.buf = mem_alloc(alen);
+		xprt->xp_rtaddr.len = alen;
+	}
+	memcpy(xprt->xp_rtaddr.buf, &ss, alen);
+#ifdef PORTMAP
+	if (ss.ss_family == AF_INET) {
+		xprt->xp_raddr = *(struct sockaddr_in *)xprt->xp_rtaddr.buf;
+		xprt->xp_addrlen = sizeof (struct sockaddr_in);
+	}
+#endif				/* PORTMAP */
+	xdrs->x_op = XDR_DECODE;
+	XDR_SETPOS(xdrs, 0);
+	if (! xdr_callmsg(xdrs, msg)) {
+		return (FALSE);
+	}
+	su->su_xid = msg->rm_xid;
+	if (su->su_cache != NULL) {
+		if (cache_get(xprt, msg, &reply, &replylen)) {
+			(void)_sendto(xprt->xp_fd, reply, replylen, 0,
+			    (struct sockaddr *)(void *)&ss, alen);
+			return (FALSE);
+		}
+	}
+	return (TRUE);
+}
+
+static int
+svc_dg_sendto(int fd, char *buf, int buflen,
+    const struct sockaddr *raddr, socklen_t raddrlen,
+    const struct sockaddr *laddr, socklen_t laddrlen)
+{
+	struct msghdr msg;
+	struct iovec msg_iov[1];
+	struct sockaddr_in *laddr_in = (struct sockaddr_in *)laddr;
+	struct in_addr *lin = &laddr_in->sin_addr;
+	char tmp[CMSG_SPACE(sizeof(*lin))];
+	struct cmsghdr *cmsg;
+
+	memset((char *)&msg, 0, sizeof(msg));
+	msg_iov[0].iov_base = buf;
+	msg_iov[0].iov_len = buflen;
+	msg.msg_iov = msg_iov;
+	msg.msg_iovlen = 1;
+	msg.msg_namelen = raddrlen;
+	msg.msg_name = (char *)raddr;
+
+	if (laddr != NULL && laddr->sa_family == AF_INET &&
+	    lin->s_addr != INADDR_ANY) {
+		msg.msg_control = (caddr_t)tmp;
+		msg.msg_controllen = CMSG_LEN(sizeof(*lin));
+		cmsg = CMSG_FIRSTHDR(&msg);
+		cmsg->cmsg_len = CMSG_LEN(sizeof(*lin));
+		cmsg->cmsg_level = IPPROTO_IP;
+		cmsg->cmsg_type = IP_SENDSRCADDR;
+		memcpy(CMSG_DATA(cmsg), lin, sizeof(*lin));
+	}
+
+	return _sendmsg(fd, &msg, 0);
+}
+
+static bool_t
+svc_dg_reply(xprt, msg)
+	SVCXPRT *xprt;
+	struct rpc_msg *msg;
+{
+	struct svc_dg_data *su = su_data(xprt);
+	XDR *xdrs = &(su->su_xdrs);
+	bool_t stat = TRUE;
+	size_t slen;
+	xdrproc_t xdr_proc;
+	caddr_t xdr_where;
+
+	xdrs->x_op = XDR_ENCODE;
+	XDR_SETPOS(xdrs, 0);
+	msg->rm_xid = su->su_xid;
+	if (msg->rm_reply.rp_stat == MSG_ACCEPTED &&
+	    msg->rm_reply.rp_acpt.ar_stat == SUCCESS) {
+		xdr_proc = msg->acpted_rply.ar_results.proc;
+		xdr_where = msg->acpted_rply.ar_results.where;
+		msg->acpted_rply.ar_results.proc = (xdrproc_t) xdr_void;
+		msg->acpted_rply.ar_results.where = NULL;
+
+		if (!xdr_replymsg(xdrs, msg) ||
+		    !SVCAUTH_WRAP(&SVC_AUTH(xprt), xdrs, xdr_proc, xdr_where))
+			stat = FALSE;
+	} else {
+		stat = xdr_replymsg(xdrs, msg);
+	}
+	if (stat) {
+		slen = XDR_GETPOS(xdrs);
+		if (svc_dg_sendto(xprt->xp_fd, rpc_buffer(xprt), slen,
+		    (struct sockaddr *)xprt->xp_rtaddr.buf,
+		    (socklen_t)xprt->xp_rtaddr.len,
+		    (struct sockaddr *)su->su_srcaddr.buf,
+		    (socklen_t)su->su_srcaddr.len) == (ssize_t) slen) {
+			stat = TRUE;
+			if (su->su_cache)
+				cache_set(xprt, slen);
+		}
+	}
+	return (stat);
+}
+
+static bool_t
+svc_dg_getargs(xprt, xdr_args, args_ptr)
+	SVCXPRT *xprt;
+	xdrproc_t xdr_args;
+	void *args_ptr;
+{
+	struct svc_dg_data *su;
+
+	assert(xprt != NULL);
+	su = su_data(xprt);
+	return (SVCAUTH_UNWRAP(&SVC_AUTH(xprt),
+		&su->su_xdrs, xdr_args, args_ptr));
+}
+
+static bool_t
+svc_dg_freeargs(xprt, xdr_args, args_ptr)
+	SVCXPRT *xprt;
+	xdrproc_t xdr_args;
+	void *args_ptr;
+{
+	XDR *xdrs = &(su_data(xprt)->su_xdrs);
+
+	xdrs->x_op = XDR_FREE;
+	return (*xdr_args)(xdrs, args_ptr);
+}
+
+static void
+svc_dg_destroy(xprt)
+	SVCXPRT *xprt;
+{
+	struct svc_dg_data *su = su_data(xprt);
+
+	xprt_unregister(xprt);
+	if (xprt->xp_fd != -1)
+		(void)_close(xprt->xp_fd);
+	XDR_DESTROY(&(su->su_xdrs));
+	(void) mem_free(rpc_buffer(xprt), su->su_iosz);
+	if (su->su_srcaddr.buf)
+		(void) mem_free(su->su_srcaddr.buf, su->su_srcaddr.maxlen);
+	(void) mem_free(su, sizeof (*su));
+	if (xprt->xp_rtaddr.buf)
+		(void) mem_free(xprt->xp_rtaddr.buf, xprt->xp_rtaddr.maxlen);
+	if (xprt->xp_ltaddr.buf)
+		(void) mem_free(xprt->xp_ltaddr.buf, xprt->xp_ltaddr.maxlen);
+	if (xprt->xp_tp)
+		(void) free(xprt->xp_tp);
+	svc_xprt_free(xprt);
+}
+
+static bool_t
+/*ARGSUSED*/
+svc_dg_control(xprt, rq, in)
+	SVCXPRT *xprt;
+	const u_int	rq;
+	void		*in;
+{
+	return (FALSE);
+}
+
+static void
+svc_dg_ops(xprt)
+	SVCXPRT *xprt;
+{
+	static struct xp_ops ops;
+	static struct xp_ops2 ops2;
+
+/* VARIABLES PROTECTED BY ops_lock: ops */
+
+	mutex_lock(&ops_lock);
+	if (ops.xp_recv == NULL) {
+		ops.xp_recv = svc_dg_recv;
+		ops.xp_stat = svc_dg_stat;
+		ops.xp_getargs = svc_dg_getargs;
+		ops.xp_reply = svc_dg_reply;
+		ops.xp_freeargs = svc_dg_freeargs;
+		ops.xp_destroy = svc_dg_destroy;
+		ops2.xp_control = svc_dg_control;
+	}
+	xprt->xp_ops = &ops;
+	xprt->xp_ops2 = &ops2;
+	mutex_unlock(&ops_lock);
+}
+
+/*  The CACHING COMPONENT */
+
+/*
+ * Could have been a separate file, but some part of it depends upon the
+ * private structure of the client handle.
+ *
+ * Fifo cache for cl server
+ * Copies pointers to reply buffers into fifo cache
+ * Buffers are sent again if retransmissions are detected.
+ */
+
+#define	SPARSENESS 4	/* 75% sparse */
+
+#define	ALLOC(type, size)	\
+	(type *) mem_alloc((sizeof (type) * (size)))
+
+#define	MEMZERO(addr, type, size)	 \
+	(void) memset((void *) (addr), 0, sizeof (type) * (int) (size))
+
+#define	FREE(addr, type, size)	\
+	mem_free((addr), (sizeof (type) * (size)))
+
+/*
+ * An entry in the cache
+ */
+typedef struct cache_node *cache_ptr;
+struct cache_node {
+	/*
+	 * Index into cache is xid, proc, vers, prog and address
+	 */
+	u_int32_t cache_xid;
+	rpcproc_t cache_proc;
+	rpcvers_t cache_vers;
+	rpcprog_t cache_prog;
+	struct netbuf cache_addr;
+	/*
+	 * The cached reply and length
+	 */
+	char *cache_reply;
+	size_t cache_replylen;
+	/*
+	 * Next node on the list, if there is a collision
+	 */
+	cache_ptr cache_next;
+};
+
+/*
+ * The entire cache
+ */
+struct cl_cache {
+	u_int uc_size;		/* size of cache */
+	cache_ptr *uc_entries;	/* hash table of entries in cache */
+	cache_ptr *uc_fifo;	/* fifo list of entries in cache */
+	u_int uc_nextvictim;	/* points to next victim in fifo list */
+	rpcprog_t uc_prog;	/* saved program number */
+	rpcvers_t uc_vers;	/* saved version number */
+	rpcproc_t uc_proc;	/* saved procedure number */
+};
+
+
+/*
+ * the hashing function
+ */
+#define	CACHE_LOC(transp, xid)	\
+	(xid % (SPARSENESS * ((struct cl_cache *) \
+		su_data(transp)->su_cache)->uc_size))
+
+/*
+ * Enable use of the cache. Returns 1 on success, 0 on failure.
+ * Note: there is no disable.
+ */
+static const char cache_enable_str[] = "svc_enablecache: %s %s";
+static const char alloc_err[] = "could not allocate cache ";
+static const char enable_err[] = "cache already enabled";
+
+int
+svc_dg_enablecache(transp, size)
+	SVCXPRT *transp;
+	u_int size;
+{
+	struct svc_dg_data *su = su_data(transp);
+	struct cl_cache *uc;
+
+	mutex_lock(&dupreq_lock);
+	if (su->su_cache != NULL) {
+		(void) warnx(cache_enable_str, enable_err, " ");
+		mutex_unlock(&dupreq_lock);
+		return (0);
+	}
+	uc = ALLOC(struct cl_cache, 1);
+	if (uc == NULL) {
+		warnx(cache_enable_str, alloc_err, " ");
+		mutex_unlock(&dupreq_lock);
+		return (0);
+	}
+	uc->uc_size = size;
+	uc->uc_nextvictim = 0;
+	uc->uc_entries = ALLOC(cache_ptr, size * SPARSENESS);
+	if (uc->uc_entries == NULL) {
+		warnx(cache_enable_str, alloc_err, "data");
+		FREE(uc, struct cl_cache, 1);
+		mutex_unlock(&dupreq_lock);
+		return (0);
+	}
+	MEMZERO(uc->uc_entries, cache_ptr, size * SPARSENESS);
+	uc->uc_fifo = ALLOC(cache_ptr, size);
+	if (uc->uc_fifo == NULL) {
+		warnx(cache_enable_str, alloc_err, "fifo");
+		FREE(uc->uc_entries, cache_ptr, size * SPARSENESS);
+		FREE(uc, struct cl_cache, 1);
+		mutex_unlock(&dupreq_lock);
+		return (0);
+	}
+	MEMZERO(uc->uc_fifo, cache_ptr, size);
+	su->su_cache = (char *)(void *)uc;
+	mutex_unlock(&dupreq_lock);
+	return (1);
+}
+
+/*
+ * Set an entry in the cache.  It assumes that the uc entry is set from
+ * the earlier call to cache_get() for the same procedure.  This will always
+ * happen because cache_get() is calle by svc_dg_recv and cache_set() is called
+ * by svc_dg_reply().  All this hoopla because the right RPC parameters are
+ * not available at svc_dg_reply time.
+ */
+
+static const char cache_set_str[] = "cache_set: %s";
+static const char cache_set_err1[] = "victim not found";
+static const char cache_set_err2[] = "victim alloc failed";
+static const char cache_set_err3[] = "could not allocate new rpc buffer";
+
+static void
+cache_set(xprt, replylen)
+	SVCXPRT *xprt;
+	size_t replylen;
+{
+	cache_ptr victim;
+	cache_ptr *vicp;
+	struct svc_dg_data *su = su_data(xprt);
+	struct cl_cache *uc = (struct cl_cache *) su->su_cache;
+	u_int loc;
+	char *newbuf;
+#ifdef RPC_CACHE_DEBUG
+	struct netconfig *nconf;
+	char *uaddr;
+#endif
+
+	mutex_lock(&dupreq_lock);
+	/*
+	 * Find space for the new entry, either by
+	 * reusing an old entry, or by mallocing a new one
+	 */
+	victim = uc->uc_fifo[uc->uc_nextvictim];
+	if (victim != NULL) {
+		loc = CACHE_LOC(xprt, victim->cache_xid);
+		for (vicp = &uc->uc_entries[loc];
+			*vicp != NULL && *vicp != victim;
+			vicp = &(*vicp)->cache_next)
+			;
+		if (*vicp == NULL) {
+			warnx(cache_set_str, cache_set_err1);
+			mutex_unlock(&dupreq_lock);
+			return;
+		}
+		*vicp = victim->cache_next;	/* remove from cache */
+		newbuf = victim->cache_reply;
+	} else {
+		victim = ALLOC(struct cache_node, 1);
+		if (victim == NULL) {
+			warnx(cache_set_str, cache_set_err2);
+			mutex_unlock(&dupreq_lock);
+			return;
+		}
+		newbuf = mem_alloc(su->su_iosz);
+		if (newbuf == NULL) {
+			warnx(cache_set_str, cache_set_err3);
+			FREE(victim, struct cache_node, 1);
+			mutex_unlock(&dupreq_lock);
+			return;
+		}
+	}
+
+	/*
+	 * Store it away
+	 */
+#ifdef RPC_CACHE_DEBUG
+	if (nconf = getnetconfigent(xprt->xp_netid)) {
+		uaddr = taddr2uaddr(nconf, &xprt->xp_rtaddr);
+		freenetconfigent(nconf);
+		printf(
+	"cache set for xid= %x prog=%d vers=%d proc=%d for rmtaddr=%s\n",
+			su->su_xid, uc->uc_prog, uc->uc_vers,
+			uc->uc_proc, uaddr);
+		free(uaddr);
+	}
+#endif
+	victim->cache_replylen = replylen;
+	victim->cache_reply = rpc_buffer(xprt);
+	rpc_buffer(xprt) = newbuf;
+	xdrmem_create(&(su->su_xdrs), rpc_buffer(xprt),
+			su->su_iosz, XDR_ENCODE);
+	victim->cache_xid = su->su_xid;
+	victim->cache_proc = uc->uc_proc;
+	victim->cache_vers = uc->uc_vers;
+	victim->cache_prog = uc->uc_prog;
+	victim->cache_addr = xprt->xp_rtaddr;
+	victim->cache_addr.buf = ALLOC(char, xprt->xp_rtaddr.len);
+	(void) memcpy(victim->cache_addr.buf, xprt->xp_rtaddr.buf,
+	    (size_t)xprt->xp_rtaddr.len);
+	loc = CACHE_LOC(xprt, victim->cache_xid);
+	victim->cache_next = uc->uc_entries[loc];
+	uc->uc_entries[loc] = victim;
+	uc->uc_fifo[uc->uc_nextvictim++] = victim;
+	uc->uc_nextvictim %= uc->uc_size;
+	mutex_unlock(&dupreq_lock);
+}
+
+/*
+ * Try to get an entry from the cache
+ * return 1 if found, 0 if not found and set the stage for cache_set()
+ */
+static int
+cache_get(xprt, msg, replyp, replylenp)
+	SVCXPRT *xprt;
+	struct rpc_msg *msg;
+	char **replyp;
+	size_t *replylenp;
+{
+	u_int loc;
+	cache_ptr ent;
+	struct svc_dg_data *su = su_data(xprt);
+	struct cl_cache *uc = (struct cl_cache *) su->su_cache;
+#ifdef RPC_CACHE_DEBUG
+	struct netconfig *nconf;
+	char *uaddr;
+#endif
+
+	mutex_lock(&dupreq_lock);
+	loc = CACHE_LOC(xprt, su->su_xid);
+	for (ent = uc->uc_entries[loc]; ent != NULL; ent = ent->cache_next) {
+		if (ent->cache_xid == su->su_xid &&
+			ent->cache_proc == msg->rm_call.cb_proc &&
+			ent->cache_vers == msg->rm_call.cb_vers &&
+			ent->cache_prog == msg->rm_call.cb_prog &&
+			ent->cache_addr.len == xprt->xp_rtaddr.len &&
+			(memcmp(ent->cache_addr.buf, xprt->xp_rtaddr.buf,
+				xprt->xp_rtaddr.len) == 0)) {
+#ifdef RPC_CACHE_DEBUG
+			if (nconf = getnetconfigent(xprt->xp_netid)) {
+				uaddr = taddr2uaddr(nconf, &xprt->xp_rtaddr);
+				freenetconfigent(nconf);
+				printf(
+	"cache entry found for xid=%x prog=%d vers=%d proc=%d for rmtaddr=%s\n",
+					su->su_xid, msg->rm_call.cb_prog,
+					msg->rm_call.cb_vers,
+					msg->rm_call.cb_proc, uaddr);
+				free(uaddr);
+			}
+#endif
+			*replyp = ent->cache_reply;
+			*replylenp = ent->cache_replylen;
+			mutex_unlock(&dupreq_lock);
+			return (1);
+		}
+	}
+	/*
+	 * Failed to find entry
+	 * Remember a few things so we can do a set later
+	 */
+	uc->uc_proc = msg->rm_call.cb_proc;
+	uc->uc_vers = msg->rm_call.cb_vers;
+	uc->uc_prog = msg->rm_call.cb_prog;
+	mutex_unlock(&dupreq_lock);
+	return (0);
+}
Index: freebsd/lib/libc/rpc/svc_generic.c
===================================================================
--- freebsd/lib/libc/rpc/svc_generic.c	(revision 60b1d40751c8b3235b7ccbf3bb6ad0c562562f01)
+++ freebsd/lib/libc/rpc/svc_generic.c	(revision 60b1d40751c8b3235b7ccbf3bb6ad0c562562f01)
@@ -0,0 +1,312 @@
+#include <machine/rtems-bsd-user-space.h>
+
+/*	$NetBSD: svc_generic.c,v 1.3 2000/07/06 03:10:35 christos Exp $	*/
+
+/*-
+ * Copyright (c) 2009, Sun Microsystems, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions are met:
+ * - Redistributions of source code must retain the above copyright notice, 
+ *   this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice, 
+ *   this list of conditions and the following disclaimer in the documentation 
+ *   and/or other materials provided with the distribution.
+ * - Neither the name of Sun Microsystems, Inc. nor the names of its 
+ *   contributors may be used to endorse or promote products derived 
+ *   from this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Copyright (c) 1986-1991 by Sun Microsystems Inc.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+#ident	"@(#)svc_generic.c	1.19	94/04/24 SMI" 
+static char sccsid[] = "@(#)svc_generic.c 1.21 89/02/28 Copyr 1988 Sun Micro";
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * svc_generic.c, Server side for RPC.
+ *
+ */
+
+#include "namespace.h"
+#include "reentrant.h"
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <rpc/rpc.h>
+#include <rpc/nettype.h>
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <err.h>
+#include "un-namespace.h"
+
+#include "rpc_com.h"
+#include "mt_misc.h"
+
+extern int __svc_vc_setflag(SVCXPRT *, int);
+
+/*
+ * The highest level interface for server creation.
+ * It tries for all the nettokens in that particular class of token
+ * and returns the number of handles it can create and/or find.
+ *
+ * It creates a link list of all the handles it could create.
+ * If svc_create() is called multiple times, it uses the handle
+ * created earlier instead of creating a new handle every time.
+ */
+int
+svc_create(dispatch, prognum, versnum, nettype)
+	void (*dispatch)(struct svc_req *, SVCXPRT *);
+	rpcprog_t prognum;		/* Program number */
+	rpcvers_t versnum;		/* Version number */
+	const char *nettype;		/* Networktype token */
+{
+	struct xlist {
+		SVCXPRT *xprt;		/* Server handle */
+		struct xlist *next;	/* Next item */
+	} *l;
+	static struct xlist *xprtlist;	/* A link list of all the handles */
+	int num = 0;
+	SVCXPRT *xprt;
+	struct netconfig *nconf;
+	void *handle;
+
+/* VARIABLES PROTECTED BY xprtlist_lock: xprtlist */
+
+	if ((handle = __rpc_setconf(nettype)) == NULL) {
+		warnx("svc_create: unknown protocol");
+		return (0);
+	}
+	while ((nconf = __rpc_getconf(handle)) != NULL) {
+		mutex_lock(&xprtlist_lock);
+		for (l = xprtlist; l; l = l->next) {
+			if (strcmp(l->xprt->xp_netid, nconf->nc_netid) == 0) {
+				/* Found an old one, use it */
+				(void) rpcb_unset(prognum, versnum, nconf);
+				if (svc_reg(l->xprt, prognum, versnum,
+					dispatch, nconf) == FALSE)
+					warnx(
+		"svc_create: could not register prog %u vers %u on %s",
+					(unsigned)prognum, (unsigned)versnum,
+					 nconf->nc_netid);
+				else
+					num++;
+				break;
+			}
+		}
+		if (l == NULL) {
+			/* It was not found. Now create a new one */
+			xprt = svc_tp_create(dispatch, prognum, versnum, nconf);
+			if (xprt) {
+				l = (struct xlist *)malloc(sizeof (*l));
+				if (l == NULL) {
+					warnx("svc_create: no memory");
+					mutex_unlock(&xprtlist_lock);
+					return (0);
+				}
+				l->xprt = xprt;
+				l->next = xprtlist;
+				xprtlist = l;
+				num++;
+			}
+		}
+		mutex_unlock(&xprtlist_lock);
+	}
+	__rpc_endconf(handle);
+	/*
+	 * In case of num == 0; the error messages are generated by the
+	 * underlying layers; and hence not needed here.
+	 */
+	return (num);
+}
+
+/*
+ * The high level interface to svc_tli_create().
+ * It tries to create a server for "nconf" and registers the service
+ * with the rpcbind. It calls svc_tli_create();
+ */
+SVCXPRT *
+svc_tp_create(dispatch, prognum, versnum, nconf)
+	void (*dispatch)(struct svc_req *, SVCXPRT *);
+	rpcprog_t prognum;		/* Program number */
+	rpcvers_t versnum;		/* Version number */
+	const struct netconfig *nconf; /* Netconfig structure for the network */
+{
+	SVCXPRT *xprt;
+
+	if (nconf == NULL) {
+		warnx(
+	"svc_tp_create: invalid netconfig structure for prog %u vers %u",
+				(unsigned)prognum, (unsigned)versnum);
+		return (NULL);
+	}
+	xprt = svc_tli_create(RPC_ANYFD, nconf, NULL, 0, 0);
+	if (xprt == NULL) {
+		return (NULL);
+	}
+	/*LINTED const castaway*/
+	(void) rpcb_unset(prognum, versnum, (struct netconfig *) nconf);
+	if (svc_reg(xprt, prognum, versnum, dispatch, nconf) == FALSE) {
+		warnx(
+		"svc_tp_create: Could not register prog %u vers %u on %s",
+				(unsigned)prognum, (unsigned)versnum,
+				nconf->nc_netid);
+		SVC_DESTROY(xprt);
+		return (NULL);
+	}
+	return (xprt);
+}
+
+/*
+ * If fd is RPC_ANYFD, then it opens a fd for the given transport
+ * provider (nconf cannot be NULL then). If the t_state is T_UNBND and
+ * bindaddr is NON-NULL, it performs a t_bind using the bindaddr. For
+ * NULL bindadr and Connection oriented transports, the value of qlen
+ * is set to 8.
+ *
+ * If sendsz or recvsz are zero, their default values are chosen.
+ */
+SVCXPRT *
+svc_tli_create(fd, nconf, bindaddr, sendsz, recvsz)
+	int fd;				/* Connection end point */
+	const struct netconfig *nconf;	/* Netconfig struct for nettoken */
+	const struct t_bind *bindaddr;	/* Local bind address */
+	u_int sendsz;			/* Max sendsize */
+	u_int recvsz;			/* Max recvsize */
+{
+	SVCXPRT *xprt = NULL;		/* service handle */
+	bool_t madefd = FALSE;		/* whether fd opened here  */
+	struct __rpc_sockinfo si;
+	struct sockaddr_storage ss;
+	socklen_t slen;
+
+	if (fd == RPC_ANYFD) {
+		if (nconf == NULL) {
+			warnx("svc_tli_create: invalid netconfig");
+			return (NULL);
+		}
+		fd = __rpc_nconf2fd(nconf);
+		if (fd == -1) {
+			warnx(
+			    "svc_tli_create: could not open connection for %s",
+					nconf->nc_netid);
+			return (NULL);
+		}
+		__rpc_nconf2sockinfo(nconf, &si);
+		madefd = TRUE;
+	} else {
+		/*
+		 * It is an open descriptor. Get the transport info.
+		 */
+		if (!__rpc_fd2sockinfo(fd, &si)) {
+			warnx(
+		"svc_tli_create: could not get transport information");
+			return (NULL);
+		}
+	}
+
+	/*
+	 * If the fd is unbound, try to bind it.
+	 */
+	if (madefd || !__rpc_sockisbound(fd)) {
+		if (bindaddr == NULL) {
+			if (bindresvport(fd, NULL) < 0) {
+				memset(&ss, 0, sizeof ss);
+				ss.ss_family = si.si_af;
+				ss.ss_len = si.si_alen;
+				if (_bind(fd, (struct sockaddr *)(void *)&ss,
+				    (socklen_t)si.si_alen) < 0) {
+					warnx(
+			"svc_tli_create: could not bind to anonymous port");
+					goto freedata;
+				}
+			}
+			_listen(fd, SOMAXCONN);
+		} else {
+			if (_bind(fd,
+			    (struct sockaddr *)bindaddr->addr.buf,
+			    (socklen_t)si.si_alen) < 0) {
+				warnx(
+		"svc_tli_create: could not bind to requested address");
+				goto freedata;
+			}
+			_listen(fd, (int)bindaddr->qlen);
+		}
+			
+	}
+	/*
+	 * call transport specific function.
+	 */
+	switch (si.si_socktype) {
+		case SOCK_STREAM:
+			slen = sizeof ss;
+			if (_getpeername(fd, (struct sockaddr *)(void *)&ss, &slen)
+			    == 0) {
+				/* accepted socket */
+				xprt = svc_fd_create(fd, sendsz, recvsz);
+			} else
+				xprt = svc_vc_create(fd, sendsz, recvsz);
+			if (!nconf || !xprt)
+				break;
+#if 0
+			/* XXX fvdl */
+			if (strcmp(nconf->nc_protofmly, "inet") == 0 ||
+			    strcmp(nconf->nc_protofmly, "inet6") == 0)
+				(void) __svc_vc_setflag(xprt, TRUE);
+#endif
+			break;
+		case SOCK_DGRAM:
+			xprt = svc_dg_create(fd, sendsz, recvsz);
+			break;
+		default:
+			warnx("svc_tli_create: bad service type");
+			goto freedata;
+	}
+
+	if (xprt == NULL)
+		/*
+		 * The error messages here are spitted out by the lower layers:
+		 * svc_vc_create(), svc_fd_create() and svc_dg_create().
+		 */
+		goto freedata;
+
+	/* Fill in type of service */
+	xprt->xp_type = __rpc_socktype2seman(si.si_socktype);
+
+	if (nconf) {
+		xprt->xp_netid = strdup(nconf->nc_netid);
+		xprt->xp_tp = strdup(nconf->nc_device);
+	}
+	return (xprt);
+
+freedata:
+	if (madefd)
+		(void)_close(fd);
+	if (xprt) {
+		if (!madefd) /* so that svc_destroy doesnt close fd */
+			xprt->xp_fd = RPC_ANYFD;
+		SVC_DESTROY(xprt);
+	}
+	return (NULL);
+}
Index: freebsd/lib/libc/rpc/svc_raw.c
===================================================================
--- freebsd/lib/libc/rpc/svc_raw.c	(revision 60b1d40751c8b3235b7ccbf3bb6ad0c562562f01)
+++ freebsd/lib/libc/rpc/svc_raw.c	(revision 60b1d40751c8b3235b7ccbf3bb6ad0c562562f01)
@@ -0,0 +1,287 @@
+#include <machine/rtems-bsd-user-space.h>
+
+/*	$NetBSD: svc_raw.c,v 1.14 2000/07/06 03:10:35 christos Exp $	*/
+
+/*-
+ * Copyright (c) 2009, Sun Microsystems, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions are met:
+ * - Redistributions of source code must retain the above copyright notice, 
+ *   this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice, 
+ *   this list of conditions and the following disclaimer in the documentation 
+ *   and/or other materials provided with the distribution.
+ * - Neither the name of Sun Microsystems, Inc. nor the names of its 
+ *   contributors may be used to endorse or promote products derived 
+ *   from this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * Copyright (c) 1986-1991 by Sun Microsystems Inc. 
+ */
+
+/* #ident	"@(#)svc_raw.c	1.16	94/04/24 SMI" */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)svc_raw.c 1.25 89/01/31 Copyr 1984 Sun Micro";
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * svc_raw.c,   This a toy for simple testing and timing.
+ * Interface to create an rpc client and server in the same UNIX process.
+ * This lets us similate rpc and get rpc (round trip) overhead, without
+ * any interference from the kernel.
+ *
+ */
+
+#include "namespace.h"
+#include "reentrant.h"
+#include <rpc/rpc.h>
+#include <sys/types.h>
+#include <rpc/raw.h>
+#include <stdlib.h>
+#include "un-namespace.h"
+#include "mt_misc.h"
+
+#ifndef UDPMSGSIZE
+#define	UDPMSGSIZE 8800
+#endif
+
+/*
+ * This is the "network" that we will be moving data over
+ */
+static struct svc_raw_private {
+	char	*raw_buf;	/* should be shared with the cl handle */
+	SVCXPRT	*server;
+	XDR	xdr_stream;
+	char	verf_body[MAX_AUTH_BYTES];
+} *svc_raw_private;
+
+static enum xprt_stat svc_raw_stat(SVCXPRT *);
+static bool_t svc_raw_recv(SVCXPRT *, struct rpc_msg *);
+static bool_t svc_raw_reply(SVCXPRT *, struct rpc_msg *);
+static bool_t svc_raw_getargs(SVCXPRT *, xdrproc_t, void *);
+static bool_t svc_raw_freeargs(SVCXPRT *, xdrproc_t, void *);
+static void svc_raw_destroy(SVCXPRT *);
+static void svc_raw_ops(SVCXPRT *);
+static bool_t svc_raw_control(SVCXPRT *, const u_int, void *);
+
+char *__rpc_rawcombuf = NULL;
+
+SVCXPRT *
+svc_raw_create()
+{
+	struct svc_raw_private *srp;
+/* VARIABLES PROTECTED BY svcraw_lock: svc_raw_private, srp */
+
+	mutex_lock(&svcraw_lock);
+	srp = svc_raw_private;
+	if (srp == NULL) {
+		srp = (struct svc_raw_private *)calloc(1, sizeof (*srp));
+		if (srp == NULL) {
+			mutex_unlock(&svcraw_lock);
+			return (NULL);
+		}
+		if (__rpc_rawcombuf == NULL) {
+			__rpc_rawcombuf = calloc(UDPMSGSIZE, sizeof (char));
+			if (__rpc_rawcombuf == NULL) {
+				free(srp);
+				mutex_unlock(&svcraw_lock);
+				return (NULL);
+			}
+		}
+		srp->raw_buf = __rpc_rawcombuf; /* Share it with the client */
+		srp->server = svc_xprt_alloc();
+		if (srp->server == NULL) {
+			free(__rpc_rawcombuf);
+			free(srp);
+			mutex_unlock(&svcraw_lock);
+			return (NULL);
+		}
+		svc_raw_private = srp;
+	}
+	srp->server->xp_fd = FD_SETSIZE;
+	srp->server->xp_port = 0;
+	svc_raw_ops(srp->server);
+	srp->server->xp_verf.oa_base = srp->verf_body;
+	xdrmem_create(&srp->xdr_stream, srp->raw_buf, UDPMSGSIZE, XDR_DECODE);
+	xprt_register(srp->server);
+	mutex_unlock(&svcraw_lock);
+	return (srp->server);
+}
+
+/*ARGSUSED*/
+static enum xprt_stat
+svc_raw_stat(xprt)
+SVCXPRT *xprt; /* args needed to satisfy ANSI-C typechecking */
+{
+	return (XPRT_IDLE);
+}
+
+/*ARGSUSED*/
+static bool_t
+svc_raw_recv(xprt, msg)
+	SVCXPRT *xprt;
+	struct rpc_msg *msg;
+{
+	struct svc_raw_private *srp;
+	XDR *xdrs;
+
+	mutex_lock(&svcraw_lock);
+	srp = svc_raw_private;
+	if (srp == NULL) {
+		mutex_unlock(&svcraw_lock);
+		return (FALSE);
+	}
+	mutex_unlock(&svcraw_lock);
+
+	xdrs = &srp->xdr_stream;
+	xdrs->x_op = XDR_DECODE;
+	(void) XDR_SETPOS(xdrs, 0);
+	if (! xdr_callmsg(xdrs, msg)) {
+		return (FALSE);
+	}
+	return (TRUE);
+}
+
+/*ARGSUSED*/
+static bool_t
+svc_raw_reply(xprt, msg)
+	SVCXPRT *xprt;
+	struct rpc_msg *msg;
+{
+	struct svc_raw_private *srp;
+	XDR *xdrs;
+	bool_t stat;
+	xdrproc_t xdr_proc;
+	caddr_t xdr_where;
+
+	mutex_lock(&svcraw_lock);
+	srp = svc_raw_private;
+	if (srp == NULL) {
+		mutex_unlock(&svcraw_lock);
+		return (FALSE);
+	}
+	mutex_unlock(&svcraw_lock);
+
+	xdrs = &srp->xdr_stream;
+	xdrs->x_op = XDR_ENCODE;
+	(void) XDR_SETPOS(xdrs, 0);
+	if (msg->rm_reply.rp_stat == MSG_ACCEPTED &&
+	    msg->rm_reply.rp_acpt.ar_stat == SUCCESS) {
+		xdr_proc = msg->acpted_rply.ar_results.proc;
+		xdr_where = msg->acpted_rply.ar_results.where;
+		msg->acpted_rply.ar_results.proc = (xdrproc_t) xdr_void;
+		msg->acpted_rply.ar_results.where = NULL;
+
+		stat = xdr_replymsg(xdrs, msg) &&
+		    SVCAUTH_WRAP(&SVC_AUTH(xprt), xdrs, xdr_proc, xdr_where);
+	} else {
+		stat = xdr_replymsg(xdrs, msg);
+	}
+	if (!stat) {
+		return (FALSE);
+	}
+	(void) XDR_GETPOS(xdrs);  /* called just for overhead */
+	return (TRUE);
+}
+
+/*ARGSUSED*/
+static bool_t
+svc_raw_getargs(xprt, xdr_args, args_ptr)
+	SVCXPRT *xprt;
+	xdrproc_t xdr_args;
+	void *args_ptr;
+{
+	struct svc_raw_private *srp;
+
+	mutex_lock(&svcraw_lock);
+	srp = svc_raw_private;
+	if (srp == NULL) {
+		mutex_unlock(&svcraw_lock);
+		return (FALSE);
+	}
+	mutex_unlock(&svcraw_lock);
+
+	return (SVCAUTH_UNWRAP(&SVC_AUTH(xprt), &srp->xdr_stream,
+		xdr_args, args_ptr));
+}
+
+/*ARGSUSED*/
+static bool_t
+svc_raw_freeargs(xprt, xdr_args, args_ptr)
+	SVCXPRT *xprt;
+	xdrproc_t xdr_args;
+	void *args_ptr;
+{
+	struct svc_raw_private *srp;
+	XDR *xdrs;
+
+	mutex_lock(&svcraw_lock);
+	srp = svc_raw_private;
+	if (srp == NULL) {
+		mutex_unlock(&svcraw_lock);
+		return (FALSE);
+	}
+	mutex_unlock(&svcraw_lock);
+
+	xdrs = &srp->xdr_stream;
+	xdrs->x_op = XDR_FREE;
+	return (*xdr_args)(xdrs, args_ptr);
+}
+
+/*ARGSUSED*/
+static void
+svc_raw_destroy(xprt)
+SVCXPRT *xprt;
+{
+}
+
+/*ARGSUSED*/
+static bool_t
+svc_raw_control(xprt, rq, in)
+	SVCXPRT *xprt;
+	const u_int	rq;
+	void		*in;
+{
+	return (FALSE);
+}
+
+static void
+svc_raw_ops(xprt)
+	SVCXPRT *xprt;
+{
+	static struct xp_ops ops;
+	static struct xp_ops2 ops2;
+
+/* VARIABLES PROTECTED BY ops_lock: ops */
+
+	mutex_lock(&ops_lock);
+	if (ops.xp_recv == NULL) {
+		ops.xp_recv = svc_raw_recv;
+		ops.xp_stat = svc_raw_stat;
+		ops.xp_getargs = svc_raw_getargs;
+		ops.xp_reply = svc_raw_reply;
+		ops.xp_freeargs = svc_raw_freeargs;
+		ops.xp_destroy = svc_raw_destroy;
+		ops2.xp_control = svc_raw_control;
+	}
+	xprt->xp_ops = &ops;
+	xprt->xp_ops2 = &ops2;
+	mutex_unlock(&ops_lock);
+}
Index: freebsd/lib/libc/rpc/svc_run.c
===================================================================
--- freebsd/lib/libc/rpc/svc_run.c	(revision 60b1d40751c8b3235b7ccbf3bb6ad0c562562f01)
+++ freebsd/lib/libc/rpc/svc_run.c	(revision 60b1d40751c8b3235b7ccbf3bb6ad0c562562f01)
@@ -0,0 +1,99 @@
+#include <machine/rtems-bsd-user-space.h>
+
+/*	$NetBSD: svc_run.c,v 1.17 2000/07/06 03:10:35 christos Exp $	*/
+
+/*-
+ * Copyright (c) 2009, Sun Microsystems, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions are met:
+ * - Redistributions of source code must retain the above copyright notice, 
+ *   this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice, 
+ *   this list of conditions and the following disclaimer in the documentation 
+ *   and/or other materials provided with the distribution.
+ * - Neither the name of Sun Microsystems, Inc. nor the names of its 
+ *   contributors may be used to endorse or promote products derived 
+ *   from this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char *sccsid2 = "from: @(#)svc_run.c 1.1 87/10/13 Copyr 1984 Sun Micro";
+static char *sccsid = "from: @(#)svc_run.c	2.1 88/07/29 4.0 RPCSRC";
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * This is the rpc server side idle loop
+ * Wait for input, call server program.
+ */
+#include "namespace.h"
+#include "reentrant.h"
+#include <err.h>
+#include <errno.h>
+#include <rpc/rpc.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include "un-namespace.h"
+
+#include <rpc/rpc.h>
+#include "rpc_com.h"
+#include "mt_misc.h"
+
+void
+svc_run()
+{
+	fd_set readfds, cleanfds;
+	struct timeval timeout;
+
+	timeout.tv_sec = 30;
+	timeout.tv_usec = 0;
+
+	for (;;) {
+		rwlock_rdlock(&svc_fd_lock);
+		readfds = svc_fdset;
+		cleanfds = svc_fdset;
+		rwlock_unlock(&svc_fd_lock);
+		switch (_select(svc_maxfd+1, &readfds, NULL, NULL, &timeout)) {
+		case -1:
+			FD_ZERO(&readfds);
+			if (errno == EINTR) {
+				continue;
+			}
+			_warn("svc_run: - select failed");
+			return;
+		case 0:
+			__svc_clean_idle(&cleanfds, 30, FALSE);
+			continue;
+		default:
+			svc_getreqset(&readfds);
+		}
+	}
+}
+
+/*
+ *      This function causes svc_run() to exit by telling it that it has no
+ *      more work to do.
+ */
+void
+svc_exit()
+{
+	rwlock_wrlock(&svc_fd_lock);
+	FD_ZERO(&svc_fdset);
+	rwlock_unlock(&svc_fd_lock);
+}
Index: freebsd/lib/libc/rpc/svc_simple.c
===================================================================
--- freebsd/lib/libc/rpc/svc_simple.c	(revision 60b1d40751c8b3235b7ccbf3bb6ad0c562562f01)
+++ freebsd/lib/libc/rpc/svc_simple.c	(revision 60b1d40751c8b3235b7ccbf3bb6ad0c562562f01)
@@ -0,0 +1,314 @@
+#include <machine/rtems-bsd-user-space.h>
+
+/*	$NetBSD: svc_simple.c,v 1.20 2000/07/06 03:10:35 christos Exp $	*/
+
+/*-
+ * Copyright (c) 2009, Sun Microsystems, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions are met:
+ * - Redistributions of source code must retain the above copyright notice, 
+ *   this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice, 
+ *   this list of conditions and the following disclaimer in the documentation 
+ *   and/or other materials provided with the distribution.
+ * - Neither the name of Sun Microsystems, Inc. nor the names of its 
+ *   contributors may be used to endorse or promote products derived 
+ *   from this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * Copyright (c) 1986-1991 by Sun Microsystems Inc. 
+ */
+
+/* #pragma ident	"@(#)svc_simple.c	1.18	94/04/24 SMI" */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * svc_simple.c
+ * Simplified front end to rpc.
+ */
+
+/*
+ * This interface creates a virtual listener for all the services
+ * started thru rpc_reg(). It listens on the same endpoint for
+ * all the services and then executes the corresponding service
+ * for the given prognum and procnum.
+ */
+
+#include "namespace.h"
+#include "reentrant.h"
+#include <sys/types.h>
+#include <rpc/rpc.h>
+#include <rpc/nettype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <err.h>
+#include "un-namespace.h"
+
+#include "rpc_com.h"
+#include "mt_misc.h"
+
+static void universal(struct svc_req *, SVCXPRT *);
+
+static struct proglst {
+	char *(*p_progname)(char *);
+	rpcprog_t p_prognum;
+	rpcvers_t p_versnum;
+	rpcproc_t p_procnum;
+	SVCXPRT *p_transp;
+	char *p_netid;
+	char *p_xdrbuf;
+	int p_recvsz;
+	xdrproc_t p_inproc, p_outproc;
+	struct proglst *p_nxt;
+} *proglst;
+
+static const char rpc_reg_err[] = "%s: %s";
+static const char rpc_reg_msg[] = "rpc_reg: ";
+static const char __reg_err1[] = "can't find appropriate transport";
+static const char __reg_err2[] = "can't get protocol info";
+static const char __reg_err3[] = "unsupported transport size";
+static const char __no_mem_str[] = "out of memory";
+
+/*
+ * For simplified, easy to use kind of rpc interfaces.
+ * nettype indicates the type of transport on which the service will be
+ * listening. Used for conservation of the system resource. Only one
+ * handle is created for all the services (actually one of each netid)
+ * and same xdrbuf is used for same netid. The size of the arguments
+ * is also limited by the recvsize for that transport, even if it is
+ * a COTS transport. This may be wrong, but for cases like these, they
+ * should not use the simplified interfaces like this.
+ */
+
+int
+rpc_reg(prognum, versnum, procnum, progname, inproc, outproc, nettype)
+	rpcprog_t prognum;			/* program number */
+	rpcvers_t versnum;			/* version number */
+	rpcproc_t procnum;			/* procedure number */
+	char *(*progname)(char *); /* Server routine */
+	xdrproc_t inproc, outproc;	/* in/out XDR procedures */
+	char *nettype;			/* nettype */
+{
+	struct netconfig *nconf;
+	int done = FALSE;
+	void *handle;
+
+
+	if (procnum == NULLPROC) {
+		warnx("%s can't reassign procedure number %u", rpc_reg_msg,
+			NULLPROC);
+		return (-1);
+	}
+
+	if (nettype == NULL)
+		nettype = "netpath";		/* The default behavior */
+	if ((handle = __rpc_setconf(nettype)) == NULL) {
+		warnx(rpc_reg_err, rpc_reg_msg, __reg_err1);
+		return (-1);
+	}
+/* VARIABLES PROTECTED BY proglst_lock: proglst */
+	mutex_lock(&proglst_lock);
+	while ((nconf = __rpc_getconf(handle)) != NULL) {
+		struct proglst *pl;
+		SVCXPRT *svcxprt;
+		int madenow;
+		u_int recvsz;
+		char *xdrbuf;
+		char *netid;
+
+		madenow = FALSE;
+		svcxprt = NULL;
+		recvsz = 0;
+		xdrbuf = netid = NULL;
+		for (pl = proglst; pl; pl = pl->p_nxt) {
+			if (strcmp(pl->p_netid, nconf->nc_netid) == 0) {
+				svcxprt = pl->p_transp;
+				xdrbuf = pl->p_xdrbuf;
+				recvsz = pl->p_recvsz;
+				netid = pl->p_netid;
+				break;
+			}
+		}
+
+		if (svcxprt == NULL) {
+			struct __rpc_sockinfo si;
+
+			svcxprt = svc_tli_create(RPC_ANYFD, nconf, NULL, 0, 0);
+			if (svcxprt == NULL)
+				continue;
+			if (!__rpc_fd2sockinfo(svcxprt->xp_fd, &si)) {
+				warnx(rpc_reg_err, rpc_reg_msg, __reg_err2);
+				SVC_DESTROY(svcxprt);
+				continue;
+			}
+			recvsz = __rpc_get_t_size(si.si_af, si.si_proto, 0);
+			if (recvsz == 0) {
+				warnx(rpc_reg_err, rpc_reg_msg, __reg_err3);
+				SVC_DESTROY(svcxprt);
+				continue;
+			}
+			if (((xdrbuf = malloc((unsigned)recvsz)) == NULL) ||
+				((netid = strdup(nconf->nc_netid)) == NULL)) {
+				warnx(rpc_reg_err, rpc_reg_msg, __no_mem_str);
+				if (xdrbuf != NULL)
+					free(xdrbuf);
+				if (netid != NULL)
+					free(netid);
+				SVC_DESTROY(svcxprt);
+				break;
+			}
+			madenow = TRUE;
+		}
+		/*
+		 * Check if this (program, version, netid) had already been
+		 * registered.  The check may save a few RPC calls to rpcbind
+		 */
+		for (pl = proglst; pl; pl = pl->p_nxt)
+			if ((pl->p_prognum == prognum) &&
+				(pl->p_versnum == versnum) &&
+				(strcmp(pl->p_netid, netid) == 0))
+				break;
+		if (pl == NULL) { /* Not yet */
+			(void) rpcb_unset(prognum, versnum, nconf);
+		} else {
+			/* so that svc_reg does not call rpcb_set() */
+			nconf = NULL;
+		}
+
+		if (!svc_reg(svcxprt, prognum, versnum, universal, nconf)) {
+			warnx("%s couldn't register prog %u vers %u for %s",
+				rpc_reg_msg, (unsigned)prognum,
+				(unsigned)versnum, netid);
+			if (madenow) {
+				SVC_DESTROY(svcxprt);
+				free(xdrbuf);
+				free(netid);
+			}
+			continue;
+		}
+
+		pl = malloc(sizeof (struct proglst));
+		if (pl == NULL) {
+			warnx(rpc_reg_err, rpc_reg_msg, __no_mem_str);
+			if (madenow) {
+				SVC_DESTROY(svcxprt);
+				free(xdrbuf);
+				free(netid);
+			}
+			break;
+		}
+		pl->p_progname = progname;
+		pl->p_prognum = prognum;
+		pl->p_versnum = versnum;
+		pl->p_procnum = procnum;
+		pl->p_inproc = inproc;
+		pl->p_outproc = outproc;
+		pl->p_transp = svcxprt;
+		pl->p_xdrbuf = xdrbuf;
+		pl->p_recvsz = recvsz;
+		pl->p_netid = netid;
+		pl->p_nxt = proglst;
+		proglst = pl;
+		done = TRUE;
+	}
+	__rpc_endconf(handle);
+	mutex_unlock(&proglst_lock);
+
+	if (done == FALSE) {
+		warnx("%s cant find suitable transport for %s",
+			rpc_reg_msg, nettype);
+		return (-1);
+	}
+	return (0);
+}
+
+/*
+ * The universal handler for the services registered using registerrpc.
+ * It handles both the connectionless and the connection oriented cases.
+ */
+
+static void
+universal(rqstp, transp)
+	struct svc_req *rqstp;
+	SVCXPRT *transp;
+{
+	rpcprog_t prog;
+	rpcvers_t vers;
+	rpcproc_t proc;
+	char *outdata;
+	char *xdrbuf;
+	struct proglst *pl;
+
+	/*
+	 * enforce "procnum 0 is echo" convention
+	 */
+	if (rqstp->rq_proc == NULLPROC) {
+		if (svc_sendreply(transp, (xdrproc_t) xdr_void, NULL) ==
+		    FALSE) {
+			warnx("svc_sendreply failed");
+		}
+		return;
+	}
+	prog = rqstp->rq_prog;
+	vers = rqstp->rq_vers;
+	proc = rqstp->rq_proc;
+	mutex_lock(&proglst_lock);
+	for (pl = proglst; pl; pl = pl->p_nxt)
+		if (pl->p_prognum == prog && pl->p_procnum == proc &&
+			pl->p_versnum == vers &&
+			(strcmp(pl->p_netid, transp->xp_netid) == 0)) {
+			/* decode arguments into a CLEAN buffer */
+			xdrbuf = pl->p_xdrbuf;
+			/* Zero the arguments: reqd ! */
+			(void) memset(xdrbuf, 0, sizeof (pl->p_recvsz));
+			/*
+			 * Assuming that sizeof (xdrbuf) would be enough
+			 * for the arguments; if not then the program
+			 * may bomb. BEWARE!
+			 */
+			if (!svc_getargs(transp, pl->p_inproc, xdrbuf)) {
+				svcerr_decode(transp);
+				mutex_unlock(&proglst_lock);
+				return;
+			}
+			outdata = (*(pl->p_progname))(xdrbuf);
+			if (outdata == NULL &&
+				pl->p_outproc != (xdrproc_t) xdr_void){
+				/* there was an error */
+				mutex_unlock(&proglst_lock);
+				return;
+			}
+			if (!svc_sendreply(transp, pl->p_outproc, outdata)) {
+				warnx(
+			"rpc: rpc_reg trouble replying to prog %u vers %u",
+				(unsigned)prog, (unsigned)vers);
+				mutex_unlock(&proglst_lock);
+				return;
+			}
+			/* free the decoded arguments */
+			(void)svc_freeargs(transp, pl->p_inproc, xdrbuf);
+			mutex_unlock(&proglst_lock);
+			return;
+		}
+	mutex_unlock(&proglst_lock);
+	/* This should never happen */
+	warnx("rpc: rpc_reg: never registered prog %u vers %u",
+		(unsigned)prog, (unsigned)vers);
+	return;
+}
Index: freebsd/lib/libc/rpc/svc_vc.c
===================================================================
--- freebsd/lib/libc/rpc/svc_vc.c	(revision 60b1d40751c8b3235b7ccbf3bb6ad0c562562f01)
+++ freebsd/lib/libc/rpc/svc_vc.c	(revision 60b1d40751c8b3235b7ccbf3bb6ad0c562562f01)
@@ -0,0 +1,812 @@
+#include <machine/rtems-bsd-user-space.h>
+
+/*	$NetBSD: svc_vc.c,v 1.7 2000/08/03 00:01:53 fvdl Exp $	*/
+
+/*-
+ * Copyright (c) 2009, Sun Microsystems, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions are met:
+ * - Redistributions of source code must retain the above copyright notice, 
+ *   this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice, 
+ *   this list of conditions and the following disclaimer in the documentation 
+ *   and/or other materials provided with the distribution.
+ * - Neither the name of Sun Microsystems, Inc. nor the names of its 
+ *   contributors may be used to endorse or promote products derived 
+ *   from this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char *sccsid2 = "@(#)svc_tcp.c 1.21 87/08/11 Copyr 1984 Sun Micro";
+static char *sccsid = "@(#)svc_tcp.c	2.2 88/08/01 4.0 RPCSRC";
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * svc_vc.c, Server side for Connection Oriented based RPC. 
+ *
+ * Actually implements two flavors of transporter -
+ * a tcp rendezvouser (a listner and connection establisher)
+ * and a record/tcp stream.
+ */
+
+#include "namespace.h"
+#include "reentrant.h"
+#include <sys/types.h>
+#include <rtems/bsd/sys/param.h>
+#include <sys/poll.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/time.h>
+#include <sys/uio.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+
+#include <assert.h>
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <rpc/rpc.h>
+
+#include "rpc_com.h"
+#include "mt_misc.h"
+#include "un-namespace.h"
+
+static SVCXPRT *makefd_xprt(int, u_int, u_int);
+static bool_t rendezvous_request(SVCXPRT *, struct rpc_msg *);
+static enum xprt_stat rendezvous_stat(SVCXPRT *);
+static void svc_vc_destroy(SVCXPRT *);
+static void __svc_vc_dodestroy (SVCXPRT *);
+static int read_vc(void *, void *, int);
+static int write_vc(void *, void *, int);
+static enum xprt_stat svc_vc_stat(SVCXPRT *);
+static bool_t svc_vc_recv(SVCXPRT *, struct rpc_msg *);
+static bool_t svc_vc_getargs(SVCXPRT *, xdrproc_t, void *);
+static bool_t svc_vc_freeargs(SVCXPRT *, xdrproc_t, void *);
+static bool_t svc_vc_reply(SVCXPRT *, struct rpc_msg *);
+static void svc_vc_rendezvous_ops(SVCXPRT *);
+static void svc_vc_ops(SVCXPRT *);
+static bool_t svc_vc_control(SVCXPRT *xprt, const u_int rq, void *in);
+static bool_t svc_vc_rendezvous_control (SVCXPRT *xprt, const u_int rq,
+				   	     void *in);
+
+struct cf_rendezvous { /* kept in xprt->xp_p1 for rendezvouser */
+	u_int sendsize;
+	u_int recvsize;
+	int maxrec;
+};
+
+struct cf_conn {  /* kept in xprt->xp_p1 for actual connection */
+	enum xprt_stat strm_stat;
+	u_int32_t x_id;
+	XDR xdrs;
+	char verf_body[MAX_AUTH_BYTES];
+	u_int sendsize;
+	u_int recvsize;
+	int maxrec;
+	bool_t nonblock;
+	struct timeval last_recv_time;
+};
+
+/*
+ * Usage:
+ *	xprt = svc_vc_create(sock, send_buf_size, recv_buf_size);
+ *
+ * Creates, registers, and returns a (rpc) tcp based transporter.
+ * Once *xprt is initialized, it is registered as a transporter
+ * see (svc.h, xprt_register).  This routine returns
+ * a NULL if a problem occurred.
+ *
+ * The filedescriptor passed in is expected to refer to a bound, but
+ * not yet connected socket.
+ *
+ * Since streams do buffered io similar to stdio, the caller can specify
+ * how big the send and receive buffers are via the second and third parms;
+ * 0 => use the system default.
+ */
+SVCXPRT *
+svc_vc_create(fd, sendsize, recvsize)
+	int fd;
+	u_int sendsize;
+	u_int recvsize;
+{
+	SVCXPRT *xprt;
+	struct cf_rendezvous *r = NULL;
+	struct __rpc_sockinfo si;
+	struct sockaddr_storage sslocal;
+	socklen_t slen;
+
+	if (!__rpc_fd2sockinfo(fd, &si))
+		return NULL;
+
+	r = mem_alloc(sizeof(*r));
+	if (r == NULL) {
+		warnx("svc_vc_create: out of memory");
+		goto cleanup_svc_vc_create;
+	}
+	r->sendsize = __rpc_get_t_size(si.si_af, si.si_proto, (int)sendsize);
+	r->recvsize = __rpc_get_t_size(si.si_af, si.si_proto, (int)recvsize);
+	r->maxrec = __svc_maxrec;
+	xprt = svc_xprt_alloc();
+	if (xprt == NULL) {
+		warnx("svc_vc_create: out of memory");
+		goto cleanup_svc_vc_create;
+	}
+	xprt->xp_p1 = r;
+	xprt->xp_verf = _null_auth;
+	svc_vc_rendezvous_ops(xprt);
+	xprt->xp_port = (u_short)-1;	/* It is the rendezvouser */
+	xprt->xp_fd = fd;
+
+	slen = sizeof (struct sockaddr_storage);
+	if (_getsockname(fd, (struct sockaddr *)(void *)&sslocal, &slen) < 0) {
+		warnx("svc_vc_create: could not retrieve local addr");
+		goto cleanup_svc_vc_create;
+	}
+
+	xprt->xp_ltaddr.maxlen = xprt->xp_ltaddr.len = sslocal.ss_len;
+	xprt->xp_ltaddr.buf = mem_alloc((size_t)sslocal.ss_len);
+	if (xprt->xp_ltaddr.buf == NULL) {
+		warnx("svc_vc_create: no mem for local addr");
+		goto cleanup_svc_vc_create;
+	}
+	memcpy(xprt->xp_ltaddr.buf, &sslocal, (size_t)sslocal.ss_len);
+
+	xprt->xp_rtaddr.maxlen = sizeof (struct sockaddr_storage);
+	xprt_register(xprt);
+	return (xprt);
+cleanup_svc_vc_create:
+	if (xprt)
+		mem_free(xprt, sizeof(*xprt));
+	if (r != NULL)
+		mem_free(r, sizeof(*r));
+	return (NULL);
+}
+
+/*
+ * Like svtcp_create(), except the routine takes any *open* UNIX file
+ * descriptor as its first input.
+ */
+SVCXPRT *
+svc_fd_create(fd, sendsize, recvsize)
+	int fd;
+	u_int sendsize;
+	u_int recvsize;
+{
+	struct sockaddr_storage ss;
+	socklen_t slen;
+	SVCXPRT *ret;
+
+	assert(fd != -1);
+
+	ret = makefd_xprt(fd, sendsize, recvsize);
+	if (ret == NULL)
+		return NULL;
+
+	slen = sizeof (struct sockaddr_storage);
+	if (_getsockname(fd, (struct sockaddr *)(void *)&ss, &slen) < 0) {
+		warnx("svc_fd_create: could not retrieve local addr");
+		goto freedata;
+	}
+	ret->xp_ltaddr.maxlen = ret->xp_ltaddr.len = ss.ss_len;
+	ret->xp_ltaddr.buf = mem_alloc((size_t)ss.ss_len);
+	if (ret->xp_ltaddr.buf == NULL) {
+		warnx("svc_fd_create: no mem for local addr");
+		goto freedata;
+	}
+	memcpy(ret->xp_ltaddr.buf, &ss, (size_t)ss.ss_len);
+
+	slen = sizeof (struct sockaddr_storage);
+	if (_getpeername(fd, (struct sockaddr *)(void *)&ss, &slen) < 0) {
+		warnx("svc_fd_create: could not retrieve remote addr");
+		goto freedata;
+	}
+	ret->xp_rtaddr.maxlen = ret->xp_rtaddr.len = ss.ss_len;
+	ret->xp_rtaddr.buf = mem_alloc((size_t)ss.ss_len);
+	if (ret->xp_rtaddr.buf == NULL) {
+		warnx("svc_fd_create: no mem for local addr");
+		goto freedata;
+	}
+	memcpy(ret->xp_rtaddr.buf, &ss, (size_t)ss.ss_len);
+#ifdef PORTMAP
+	if (ss.ss_family == AF_INET || ss.ss_family == AF_LOCAL) {
+		ret->xp_raddr = *(struct sockaddr_in *)ret->xp_rtaddr.buf;
+		ret->xp_addrlen = sizeof (struct sockaddr_in);
+	}
+#endif				/* PORTMAP */
+
+	return ret;
+
+freedata:
+	if (ret->xp_ltaddr.buf != NULL)
+		mem_free(ret->xp_ltaddr.buf, rep->xp_ltaddr.maxlen);
+
+	return NULL;
+}
+
+static SVCXPRT *
+makefd_xprt(fd, sendsize, recvsize)
+	int fd;
+	u_int sendsize;
+	u_int recvsize;
+{
+	SVCXPRT *xprt;
+	struct cf_conn *cd;
+	const char *netid;
+	struct __rpc_sockinfo si;
+ 
+	assert(fd != -1);
+
+	xprt = svc_xprt_alloc();
+	if (xprt == NULL) {
+		warnx("svc_vc: makefd_xprt: out of memory");
+		goto done;
+	}
+	cd = mem_alloc(sizeof(struct cf_conn));
+	if (cd == NULL) {
+		warnx("svc_tcp: makefd_xprt: out of memory");
+		svc_xprt_free(xprt);
+		xprt = NULL;
+		goto done;
+	}
+	cd->strm_stat = XPRT_IDLE;
+	xdrrec_create(&(cd->xdrs), sendsize, recvsize,
+	    xprt, read_vc, write_vc);
+	xprt->xp_p1 = cd;
+	xprt->xp_verf.oa_base = cd->verf_body;
+	svc_vc_ops(xprt);  /* truely deals with calls */
+	xprt->xp_port = 0;  /* this is a connection, not a rendezvouser */
+	xprt->xp_fd = fd;
+        if (__rpc_fd2sockinfo(fd, &si) && __rpc_sockinfo2netid(&si, &netid))
+		xprt->xp_netid = strdup(netid);
+
+	xprt_register(xprt);
+done:
+	return (xprt);
+}
+
+/*ARGSUSED*/
+static bool_t
+rendezvous_request(xprt, msg)
+	SVCXPRT *xprt;
+	struct rpc_msg *msg;
+{
+	int sock, flags;
+	struct cf_rendezvous *r;
+	struct cf_conn *cd;
+	struct sockaddr_storage addr;
+	socklen_t len;
+	struct __rpc_sockinfo si;
+	SVCXPRT *newxprt;
+	fd_set cleanfds;
+
+	assert(xprt != NULL);
+	assert(msg != NULL);
+
+	r = (struct cf_rendezvous *)xprt->xp_p1;
+again:
+	len = sizeof addr;
+	if ((sock = _accept(xprt->xp_fd, (struct sockaddr *)(void *)&addr,
+	    &len)) < 0) {
+		if (errno == EINTR)
+			goto again;
+		/*
+		 * Clean out the most idle file descriptor when we're
+		 * running out.
+		 */
+		if (errno == EMFILE || errno == ENFILE) {
+			cleanfds = svc_fdset;
+			__svc_clean_idle(&cleanfds, 0, FALSE);
+			goto again;
+		}
+		return (FALSE);
+	}
+	/*
+	 * make a new transporter (re-uses xprt)
+	 */
+	newxprt = makefd_xprt(sock, r->sendsize, r->recvsize);
+	newxprt->xp_rtaddr.buf = mem_alloc(len);
+	if (newxprt->xp_rtaddr.buf == NULL)
+		return (FALSE);
+	memcpy(newxprt->xp_rtaddr.buf, &addr, len);
+	newxprt->xp_rtaddr.len = len;
+#ifdef PORTMAP
+	if (addr.ss_family == AF_INET || addr.ss_family == AF_LOCAL) {
+		newxprt->xp_raddr = *(struct sockaddr_in *)newxprt->xp_rtaddr.buf;
+		newxprt->xp_addrlen = sizeof (struct sockaddr_in);
+	}
+#endif				/* PORTMAP */
+	if (__rpc_fd2sockinfo(sock, &si) && si.si_proto == IPPROTO_TCP) {
+		len = 1;
+		/* XXX fvdl - is this useful? */
+		_setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &len, sizeof (len));
+	}
+
+	cd = (struct cf_conn *)newxprt->xp_p1;
+
+	cd->recvsize = r->recvsize;
+	cd->sendsize = r->sendsize;
+	cd->maxrec = r->maxrec;
+
+	if (cd->maxrec != 0) {
+		flags = _fcntl(sock, F_GETFL, 0);
+		if (flags  == -1)
+			return (FALSE);
+		if (_fcntl(sock, F_SETFL, flags | O_NONBLOCK) == -1)
+			return (FALSE);
+		if (cd->recvsize > cd->maxrec)
+			cd->recvsize = cd->maxrec;
+		cd->nonblock = TRUE;
+		__xdrrec_setnonblock(&cd->xdrs, cd->maxrec);
+	} else
+		cd->nonblock = FALSE;
+
+	gettimeofday(&cd->last_recv_time, NULL);
+
+	return (FALSE); /* there is never an rpc msg to be processed */
+}
+
+/*ARGSUSED*/
+static enum xprt_stat
+rendezvous_stat(xprt)
+	SVCXPRT *xprt;
+{
+
+	return (XPRT_IDLE);
+}
+
+static void
+svc_vc_destroy(xprt)
+	SVCXPRT *xprt;
+{
+	assert(xprt != NULL);
+	
+	xprt_unregister(xprt);
+	__svc_vc_dodestroy(xprt);
+}
+
+static void
+__svc_vc_dodestroy(xprt)
+	SVCXPRT *xprt;
+{
+	struct cf_conn *cd;
+	struct cf_rendezvous *r;
+
+	cd = (struct cf_conn *)xprt->xp_p1;
+
+	if (xprt->xp_fd != RPC_ANYFD)
+		(void)_close(xprt->xp_fd);
+	if (xprt->xp_port != 0) {
+		/* a rendezvouser socket */
+		r = (struct cf_rendezvous *)xprt->xp_p1;
+		mem_free(r, sizeof (struct cf_rendezvous));
+		xprt->xp_port = 0;
+	} else {
+		/* an actual connection socket */
+		XDR_DESTROY(&(cd->xdrs));
+		mem_free(cd, sizeof(struct cf_conn));
+	}
+	if (xprt->xp_rtaddr.buf)
+		mem_free(xprt->xp_rtaddr.buf, xprt->xp_rtaddr.maxlen);
+	if (xprt->xp_ltaddr.buf)
+		mem_free(xprt->xp_ltaddr.buf, xprt->xp_ltaddr.maxlen);
+	if (xprt->xp_tp)
+		free(xprt->xp_tp);
+	if (xprt->xp_netid)
+		free(xprt->xp_netid);
+	svc_xprt_free(xprt);
+}
+
+/*ARGSUSED*/
+static bool_t
+svc_vc_control(xprt, rq, in)
+	SVCXPRT *xprt;
+	const u_int rq;
+	void *in;
+{
+	return (FALSE);
+}
+
+static bool_t
+svc_vc_rendezvous_control(xprt, rq, in)
+	SVCXPRT *xprt;
+	const u_int rq;
+	void *in;
+{
+	struct cf_rendezvous *cfp;
+
+	cfp = (struct cf_rendezvous *)xprt->xp_p1;
+	if (cfp == NULL)
+		return (FALSE);
+	switch (rq) {
+		case SVCGET_CONNMAXREC:
+			*(int *)in = cfp->maxrec;
+			break;
+		case SVCSET_CONNMAXREC:
+			cfp->maxrec = *(int *)in;
+			break;
+		default:
+			return (FALSE);
+	}
+	return (TRUE);
+}
+
+/*
+ * reads data from the tcp or uip connection.
+ * any error is fatal and the connection is closed.
+ * (And a read of zero bytes is a half closed stream => error.)
+ * All read operations timeout after 35 seconds.  A timeout is
+ * fatal for the connection.
+ */
+static int
+read_vc(xprtp, buf, len)
+	void *xprtp;
+	void *buf;
+	int len;
+{
+	SVCXPRT *xprt;
+	int sock;
+	int milliseconds = 35 * 1000;
+	struct pollfd pollfd;
+	struct cf_conn *cfp;
+
+	xprt = (SVCXPRT *)xprtp;
+	assert(xprt != NULL);
+
+	sock = xprt->xp_fd;
+
+	cfp = (struct cf_conn *)xprt->xp_p1;
+
+	if (cfp->nonblock) {
+		len = _read(sock, buf, (size_t)len);
+		if (len < 0) {
+			if (errno == EAGAIN)
+				len = 0;
+			else
+				goto fatal_err;
+		}
+		if (len != 0)
+			gettimeofday(&cfp->last_recv_time, NULL);
+		return len;
+	}
+
+	do {
+		pollfd.fd = sock;
+		pollfd.events = POLLIN;
+		pollfd.revents = 0;
+		switch (_poll(&pollfd, 1, milliseconds)) {
+		case -1:
+			if (errno == EINTR)
+				continue;
+			/*FALLTHROUGH*/
+		case 0:
+			goto fatal_err;
+
+		default:
+			break;
+		}
+	} while ((pollfd.revents & POLLIN) == 0);
+
+	if ((len = _read(sock, buf, (size_t)len)) > 0) {
+		gettimeofday(&cfp->last_recv_time, NULL);
+		return (len);
+	}
+
+fatal_err:
+	((struct cf_conn *)(xprt->xp_p1))->strm_stat = XPRT_DIED;
+	return (-1);
+}
+
+/*
+ * writes data to the tcp connection.
+ * Any error is fatal and the connection is closed.
+ */
+static int
+write_vc(xprtp, buf, len)
+	void *xprtp;
+	void *buf;
+	int len;
+{
+	SVCXPRT *xprt;
+	int i, cnt;
+	struct cf_conn *cd;
+	struct timeval tv0, tv1;
+
+	xprt = (SVCXPRT *)xprtp;
+	assert(xprt != NULL);
+
+	cd = (struct cf_conn *)xprt->xp_p1;
+
+	if (cd->nonblock)
+		gettimeofday(&tv0, NULL);
+	
+	for (cnt = len; cnt > 0; cnt -= i, buf = (char *)buf + i) {
+		i = _write(xprt->xp_fd, buf, (size_t)cnt);
+		if (i  < 0) {
+			if (errno != EAGAIN || !cd->nonblock) {
+				cd->strm_stat = XPRT_DIED;
+				return (-1);
+			}
+			if (cd->nonblock) {
+				/*
+				 * For non-blocking connections, do not
+				 * take more than 2 seconds writing the
+				 * data out.
+				 *
+				 * XXX 2 is an arbitrary amount.
+				 */
+				gettimeofday(&tv1, NULL);
+				if (tv1.tv_sec - tv0.tv_sec >= 2) {
+					cd->strm_stat = XPRT_DIED;
+					return (-1);
+				}
+			}
+			i = 0;
+		}
+	}
+
+	return (len);
+}
+
+static enum xprt_stat
+svc_vc_stat(xprt)
+	SVCXPRT *xprt;
+{
+	struct cf_conn *cd;
+
+	assert(xprt != NULL);
+
+	cd = (struct cf_conn *)(xprt->xp_p1);
+
+	if (cd->strm_stat == XPRT_DIED)
+		return (XPRT_DIED);
+	if (! xdrrec_eof(&(cd->xdrs)))
+		return (XPRT_MOREREQS);
+	return (XPRT_IDLE);
+}
+
+static bool_t
+svc_vc_recv(xprt, msg)
+	SVCXPRT *xprt;
+	struct rpc_msg *msg;
+{
+	struct cf_conn *cd;
+	XDR *xdrs;
+
+	assert(xprt != NULL);
+	assert(msg != NULL);
+
+	cd = (struct cf_conn *)(xprt->xp_p1);
+	xdrs = &(cd->xdrs);
+
+	if (cd->nonblock) {
+		if (!__xdrrec_getrec(xdrs, &cd->strm_stat, TRUE))
+			return FALSE;
+	} else {
+		(void)xdrrec_skiprecord(xdrs);
+	}
+
+	xdrs->x_op = XDR_DECODE;
+	if (xdr_callmsg(xdrs, msg)) {
+		cd->x_id = msg->rm_xid;
+		return (TRUE);
+	}
+	cd->strm_stat = XPRT_DIED;
+	return (FALSE);
+}
+
+static bool_t
+svc_vc_getargs(xprt, xdr_args, args_ptr)
+	SVCXPRT *xprt;
+	xdrproc_t xdr_args;
+	void *args_ptr;
+{
+	struct cf_conn *cd;
+
+	assert(xprt != NULL);
+	cd = (struct cf_conn *)(xprt->xp_p1);
+	return (SVCAUTH_UNWRAP(&SVC_AUTH(xprt),
+		&cd->xdrs, xdr_args, args_ptr));
+}
+
+static bool_t
+svc_vc_freeargs(xprt, xdr_args, args_ptr)
+	SVCXPRT *xprt;
+	xdrproc_t xdr_args;
+	void *args_ptr;
+{
+	XDR *xdrs;
+
+	assert(xprt != NULL);
+	/* args_ptr may be NULL */
+
+	xdrs = &(((struct cf_conn *)(xprt->xp_p1))->xdrs);
+
+	xdrs->x_op = XDR_FREE;
+	return ((*xdr_args)(xdrs, args_ptr));
+}
+
+static bool_t
+svc_vc_reply(xprt, msg)
+	SVCXPRT *xprt;
+	struct rpc_msg *msg;
+{
+	struct cf_conn *cd;
+	XDR *xdrs;
+	bool_t rstat;
+	xdrproc_t xdr_proc;
+	caddr_t xdr_where;
+	u_int pos;
+
+	assert(xprt != NULL);
+	assert(msg != NULL);
+
+	cd = (struct cf_conn *)(xprt->xp_p1);
+	xdrs = &(cd->xdrs);
+
+	xdrs->x_op = XDR_ENCODE;
+	msg->rm_xid = cd->x_id;
+	rstat = TRUE;
+	if (msg->rm_reply.rp_stat == MSG_ACCEPTED &&
+	    msg->rm_reply.rp_acpt.ar_stat == SUCCESS) {
+		xdr_proc = msg->acpted_rply.ar_results.proc;
+		xdr_where = msg->acpted_rply.ar_results.where;
+		msg->acpted_rply.ar_results.proc = (xdrproc_t) xdr_void;
+		msg->acpted_rply.ar_results.where = NULL;
+
+		pos = XDR_GETPOS(xdrs);
+		if (!xdr_replymsg(xdrs, msg) ||
+		    !SVCAUTH_WRAP(&SVC_AUTH(xprt), xdrs, xdr_proc, xdr_where)) {
+			XDR_SETPOS(xdrs, pos);
+			rstat = FALSE;
+		}
+	} else {
+		rstat = xdr_replymsg(xdrs, msg);
+	}
+
+	if (rstat)
+		(void)xdrrec_endofrecord(xdrs, TRUE);
+
+	return (rstat);
+}
+
+static void
+svc_vc_ops(xprt)
+	SVCXPRT *xprt;
+{
+	static struct xp_ops ops;
+	static struct xp_ops2 ops2;
+
+/* VARIABLES PROTECTED BY ops_lock: ops, ops2 */
+
+	mutex_lock(&ops_lock);
+	if (ops.xp_recv == NULL) {
+		ops.xp_recv = svc_vc_recv;
+		ops.xp_stat = svc_vc_stat;
+		ops.xp_getargs = svc_vc_getargs;
+		ops.xp_reply = svc_vc_reply;
+		ops.xp_freeargs = svc_vc_freeargs;
+		ops.xp_destroy = svc_vc_destroy;
+		ops2.xp_control = svc_vc_control;
+	}
+	xprt->xp_ops = &ops;
+	xprt->xp_ops2 = &ops2;
+	mutex_unlock(&ops_lock);
+}
+
+static void
+svc_vc_rendezvous_ops(xprt)
+	SVCXPRT *xprt;
+{
+	static struct xp_ops ops;
+	static struct xp_ops2 ops2;
+
+	mutex_lock(&ops_lock);
+	if (ops.xp_recv == NULL) {
+		ops.xp_recv = rendezvous_request;
+		ops.xp_stat = rendezvous_stat;
+		ops.xp_getargs =
+		    (bool_t (*)(SVCXPRT *, xdrproc_t, void *))abort;
+		ops.xp_reply =
+		    (bool_t (*)(SVCXPRT *, struct rpc_msg *))abort;
+		ops.xp_freeargs =
+		    (bool_t (*)(SVCXPRT *, xdrproc_t, void *))abort,
+		ops.xp_destroy = svc_vc_destroy;
+		ops2.xp_control = svc_vc_rendezvous_control;
+	}
+	xprt->xp_ops = &ops;
+	xprt->xp_ops2 = &ops2;
+	mutex_unlock(&ops_lock);
+}
+
+/*
+ * Get the effective UID of the sending process. Used by rpcbind, keyserv
+ * and rpc.yppasswdd on AF_LOCAL.
+ */
+int
+__rpc_get_local_uid(SVCXPRT *transp, uid_t *uid) {
+	int sock, ret;
+	gid_t egid;
+	uid_t euid;
+	struct sockaddr *sa;
+
+	sock = transp->xp_fd;
+	sa = (struct sockaddr *)transp->xp_rtaddr.buf;
+	if (sa->sa_family == AF_LOCAL) {
+		ret = getpeereid(sock, &euid, &egid);
+		if (ret == 0)
+			*uid = euid;
+		return (ret);
+	} else
+		return (-1);
+}
+
+/*
+ * Destroy xprts that have not have had any activity in 'timeout' seconds.
+ * If 'cleanblock' is true, blocking connections (the default) are also
+ * cleaned. If timeout is 0, the least active connection is picked.
+ */
+bool_t
+__svc_clean_idle(fd_set *fds, int timeout, bool_t cleanblock)
+{
+	int i, ncleaned;
+	SVCXPRT *xprt, *least_active;
+	struct timeval tv, tdiff, tmax;
+	struct cf_conn *cd;
+
+	gettimeofday(&tv, NULL);
+	tmax.tv_sec = tmax.tv_usec = 0;
+	least_active = NULL;
+	rwlock_wrlock(&svc_fd_lock);
+	for (i = ncleaned = 0; i <= svc_maxfd; i++) {
+		if (FD_ISSET(i, fds)) {
+			xprt = __svc_xports[i];
+			if (xprt == NULL || xprt->xp_ops == NULL ||
+			    xprt->xp_ops->xp_recv != svc_vc_recv)
+				continue;
+			cd = (struct cf_conn *)xprt->xp_p1;
+			if (!cleanblock && !cd->nonblock)
+				continue;
+			if (timeout == 0) {
+				timersub(&tv, &cd->last_recv_time, &tdiff);
+				if (timercmp(&tdiff, &tmax, >)) {
+					tmax = tdiff;
+					least_active = xprt;
+				}
+				continue;
+			}
+			if (tv.tv_sec - cd->last_recv_time.tv_sec > timeout) {
+				__xprt_unregister_unlocked(xprt);
+				__svc_vc_dodestroy(xprt);
+				ncleaned++;
+			}
+		}
+	}
+	if (timeout == 0 && least_active != NULL) {
+		__xprt_unregister_unlocked(least_active);
+		__svc_vc_dodestroy(least_active);
+		ncleaned++;
+	}
+	rwlock_unlock(&svc_fd_lock);
+	return ncleaned > 0 ? TRUE : FALSE;
+}
