Index: head/lib/libc/rpc/auth_unix.c =================================================================== --- head/lib/libc/rpc/auth_unix.c (revision 288112) +++ head/lib/libc/rpc/auth_unix.c (revision 288113) @@ -1,382 +1,370 @@ /* $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 __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 #include #include #include #include #include #include #include #include #include #include #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; +authunix_create(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() +authunix_create_default(void) { AUTH *auth; int ngids; long ngids_max; char machname[MAXHOSTNAMELEN + 1]; uid_t uid; gid_t gid; gid_t *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; +authunix_nextverf(AUTH *auth) { /* no action necessary */ } static bool_t -authunix_marshal(auth, xdrs) - AUTH *auth; - XDR *xdrs; +authunix_marshal(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; +authunix_validate(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; +authunix_destroy(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; +marshal_new_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() +authunix_ops(void) { 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: head/lib/libc/rpc/authdes_prot.c =================================================================== --- head/lib/libc/rpc/authdes_prot.c (revision 288112) +++ head/lib/libc/rpc/authdes_prot.c (revision 288113) @@ -1,93 +1,89 @@ #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 __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 #include #include #include #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; +xdr_authdes_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; +xdr_authdes_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: head/lib/libc/rpc/authunix_prot.c =================================================================== --- head/lib/libc/rpc/authunix_prot.c (revision 288112) +++ head/lib/libc/rpc/authunix_prot.c (revision 288113) @@ -1,78 +1,76 @@ /* $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 __FBSDID("$FreeBSD$"); /* * authunix_prot.c * XDR for UNIX style authentication parameters for RPC * * Copyright (C) 1984, Sun Microsystems, Inc. */ #include "namespace.h" #include #include #include #include #include #include "un-namespace.h" /* * XDR for unix authentication parameters. */ bool_t -xdr_authunix_parms(xdrs, p) - XDR *xdrs; - struct authunix_parms *p; +xdr_authunix_parms(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: head/lib/libc/rpc/bindresvport.c =================================================================== --- head/lib/libc/rpc/bindresvport.c (revision 288112) +++ head/lib/libc/rpc/bindresvport.c (revision 288113) @@ -1,160 +1,156 @@ /* $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 __FBSDID("$FreeBSD$"); /* * Copyright (c) 1987 by Sun Microsystems, Inc. * * Portions Copyright(C) 1996, Jason Downs. All rights reserved. */ #include "namespace.h" #include #include #include #include #include #include #include #include #include "un-namespace.h" /* * Bind a socket to a privileged IP port */ int -bindresvport(sd, sin) - int sd; - struct sockaddr_in *sin; +bindresvport(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; +bindresvport_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: head/lib/libc/rpc/clnt_bcast.c =================================================================== --- head/lib/libc/rpc/clnt_bcast.c (revision 288112) +++ head/lib/libc/rpc/clnt_bcast.c (revision 288113) @@ -1,672 +1,681 @@ /* $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 __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 #include #include #include #include #include #include #include #ifdef PORTMAP #include #include #include #endif /* PORTMAP */ #include #include #ifdef RPC_DEBUG #include #endif #include #include #include #include #include #include #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; } - +/* + * rpc_broadcast_exp() + * + * prog - program number + * vers - version number + * proc - procedure number + * xargs - xdr routine for args + * argsp - pointer to args + * xresults - xdr routine for results + * resultsp - pointer to results + * eachresult - call with each result obtained + * inittime - how long to wait initially + * waittime - maximum time to wait + * nettype - transport type + */ 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 */ +rpc_broadcast_exp(rpcprog_t prog, rpcvers_t vers, rpcproc_t proc, + xdrproc_t xargs, caddr_t argsp, xdrproc_t xresults, caddr_t resultsp, + resultproc_t eachresult, int inittime, int waittime, + const char *nettype) { 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(); u_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); } - +/* + * rpc_broadcast() + * + * prog - program number + * vers - version number + * proc - procedure number + * xargs - xdr routine for args + * argsp - pointer to args + * xresults - xdr routine for results + * resultsp - pointer to results + * eachresult - call with each result obtained + * nettype - transport type + */ 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 */ +rpc_broadcast(rpcprog_t prog, rpcvers_t vers, rpcproc_t proc, xdrproc_t xargs, + caddr_t argsp, xdrproc_t xresults, caddr_t resultsp, + resultproc_t eachresult, const char *nettype) { enum clnt_stat dummy; dummy = rpc_broadcast_exp(prog, vers, proc, xargs, argsp, xresults, resultsp, eachresult, INITTIME, WAITTIME, nettype); return (dummy); } Index: head/lib/libc/rpc/clnt_perror.c =================================================================== --- head/lib/libc/rpc/clnt_perror.c (revision 288112) +++ head/lib/libc/rpc/clnt_perror.c (revision 288113) @@ -1,332 +1,323 @@ /* $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 __FBSDID("$FreeBSD$"); /* * clnt_perror.c * * Copyright (C) 1984, Sun Microsystems, Inc. * */ #include "namespace.h" #include #include #include #include #include #include #include #include #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() +_buf(void) { 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; +clnt_sperror(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; +clnt_perror(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; +clnt_sperrno(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; +clnt_perrno(enum clnt_stat num) { (void) fprintf(stderr, "%s\n", clnt_sperrno(num)); } char * -clnt_spcreateerror(s) - const char *s; +clnt_spcreateerror(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; +clnt_pcreateerror(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; +auth_errmsg(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: head/lib/libc/rpc/clnt_raw.c =================================================================== --- head/lib/libc/rpc/clnt_raw.c (revision 288112) +++ head/lib/libc/rpc/clnt_raw.c (revision 288113) @@ -1,314 +1,296 @@ /* $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 __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 #include #include #include #include #include #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; +clnt_raw_create(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; +clnt_raw_call(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; +clnt_raw_geterr(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; +clnt_raw_freeres(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; +clnt_raw_abort(CLIENT *cl) { } /*ARGSUSED*/ static bool_t -clnt_raw_control(cl, ui, str) - CLIENT *cl; - u_int ui; - void *str; +clnt_raw_control(CLIENT *cl, u_int ui, void *str) { return (FALSE); } /*ARGSUSED*/ static void -clnt_raw_destroy(cl) - CLIENT *cl; +clnt_raw_destroy(CLIENT *cl) { } static struct clnt_ops * -clnt_raw_ops() +clnt_raw_ops(void) { 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: head/lib/libc/rpc/clnt_simple.c =================================================================== --- head/lib/libc/rpc/clnt_simple.c (revision 288112) +++ head/lib/libc/rpc/clnt_simple.c (revision 288113) @@ -1,205 +1,207 @@ /* $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 __FBSDID("$FreeBSD$"); /* * clnt_simple.c * Simplified front end to client rpc. * */ #include "namespace.h" #include "reentrant.h" #include #include #include #include #include #include #include #include #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. + * + * host - host name + * prognum - program number + * versnum - version number + * procnum - procedure number + * inproc, outproc - in/out XDR procedures + * in, out - recv/send data + * nettype - nettype */ 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 */ +rpc_call(const char *host, const rpcprog_t prognum, const rpcvers_t versnum, + const rpcproc_t procnum, const xdrproc_t inproc, const char *in, + const xdrproc_t outproc, char *out, const char *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: head/lib/libc/rpc/clnt_vc.c =================================================================== --- head/lib/libc/rpc/clnt_vc.c (revision 288112) +++ head/lib/libc/rpc/clnt_vc.c (revision 288113) @@ -1,871 +1,844 @@ /* $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 __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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #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 __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 + * + * fd - open file descriptor + * raddr - servers address + * prog - program number + * vers - version number + * sendsz - buffer send size + * recvsz - buffer recv size */ 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 */ +clnt_vc_create(int fd, const struct netbuf *raddr, const rpcprog_t prog, + const rpcvers_t vers, u_int sendsz, u_int recvsz) { 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->len; 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; +clnt_vc_call(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; +clnt_vc_geterr(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; +clnt_vc_freeres(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; +clnt_vc_abort(CLIENT *cl) { } static bool_t -clnt_vc_control(cl, request, info) - CLIENT *cl; - u_int request; - void *info; +clnt_vc_control(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; +clnt_vc_destroy(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; +read_vc(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; +write_vc(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() +clnt_vc_ops(void) { 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; +time_not_ok(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; +__msgread(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; +__msgwrite(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: head/lib/libc/rpc/des_crypt.c =================================================================== --- head/lib/libc/rpc/des_crypt.c (revision 288112) +++ head/lib/libc/rpc/des_crypt.c (revision 288113) @@ -1,140 +1,140 @@ /*- * 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 #include #include #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 __FBSDID("$FreeBSD$"); static int common_crypt( char *, char *, unsigned, unsigned, struct desparams * ); -int (*__des_crypt_LOCAL)() = 0; +int (*__des_crypt_LOCAL)(char *, unsigned, struct desparams *) = 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(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(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(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: head/lib/libc/rpc/getnetconfig.c =================================================================== --- head/lib/libc/rpc/getnetconfig.c (revision 288112) +++ head/lib/libc/rpc/getnetconfig.c (revision 288113) @@ -1,740 +1,735 @@ /* $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 __FBSDID("$FreeBSD$"); /* * Copyright (c) 1989 by Sun Microsystems, Inc. */ #include "namespace.h" #include "reentrant.h" #include #include #include #include #include #include #include #include #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() +__nc_error(void) { 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() +setnetconfig(void) { 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; +getnetconfig(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; +endnetconfig(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; +getnetconfigent(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; +freenetconfigent(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. + * + * stringp - string to parse + * ncp - where to put results */ static int -parse_ncp(stringp, ncp) -char *stringp; /* string to parse */ -struct netconfig *ncp; /* where to put results */ +parse_ncp(char *stringp, struct netconfig *ncp) { 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() +nc_sperror(void) { 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; +nc_perror(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; +dup_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: head/lib/libc/rpc/getnetpath.c =================================================================== --- head/lib/libc/rpc/getnetpath.c (revision 288112) +++ head/lib/libc/rpc/getnetpath.c (revision 288113) @@ -1,273 +1,271 @@ /* $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 __FBSDID("$FreeBSD$"); /* * Copyright (c) 1989 by Sun Microsystems, Inc. */ #include "namespace.h" #include #include #include #include #include #include #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() +setnetpath(void) { 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) { syslog (LOG_ERR, "rpc: failed to open " NETCONFIG); goto failed; } 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; +getnetpath(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; +endnetpath(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. + * + * npp - string + * token - char to parse string for */ - char * -_get_next_token(npp, token) -char *npp; /* string */ -int token; /* char to parse string for */ +_get_next_token(char *npp, int token) { 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: head/lib/libc/rpc/getrpcent.c =================================================================== --- head/lib/libc/rpc/getrpcent.c (revision 288112) +++ head/lib/libc/rpc/getrpcent.c (revision 288113) @@ -1,1046 +1,1046 @@ /* $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 __FBSDID("$FreeBSD$"); /* * Copyright (c) 1984 by Sun Microsystems, Inc. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef YP #include #include #endif #include #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() +getrpcent(void) { 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() +endrpcent(void) { #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: head/lib/libc/rpc/getrpcport.c =================================================================== --- head/lib/libc/rpc/getrpcport.c (revision 288112) +++ head/lib/libc/rpc/getrpcport.c (revision 288113) @@ -1,77 +1,75 @@ /* $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 __FBSDID("$FreeBSD$"); /* * Copyright (c) 1985 by Sun Microsystems, Inc. */ #include "namespace.h" #include #include #include #include #include #include #include #include #include "un-namespace.h" int -getrpcport(host, prognum, versnum, proto) - char *host; - int prognum, versnum, proto; +getrpcport(char *host, int prognum, int versnum, int 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: head/lib/libc/rpc/mt_misc.c =================================================================== --- head/lib/libc/rpc/mt_misc.c (revision 288112) +++ head/lib/libc/rpc/mt_misc.c (revision 288113) @@ -1,117 +1,117 @@ /* $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 __FBSDID("$FreeBSD$"); #include "namespace.h" #include "reentrant.h" #include #include #include #include #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() +__rpc_createerr(void) { 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: head/lib/libc/rpc/netname.c =================================================================== --- head/lib/libc/rpc/netname.c (revision 288112) +++ head/lib/libc/rpc/netname.c (revision 288113) @@ -1,148 +1,141 @@ /*- * 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 __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 #include #include #ifdef YP #include #include #endif #include #include #include #include #include #include #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]; +getnetname(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; +user2netname(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; +host2netname(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: head/lib/libc/rpc/netnamer.c =================================================================== --- head/lib/libc/rpc/netnamer.c (revision 288112) +++ head/lib/libc/rpc/netnamer.c (revision 288113) @@ -1,329 +1,319 @@ /*- * 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 __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 #include #include #ifdef YP #include #include #endif #include #include #include #include #include #include #include #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; +netname2user(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]; +_getgroups(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; +netname2host(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; +getnetid(char *key, char *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: head/lib/libc/rpc/pmap_getmaps.c =================================================================== --- head/lib/libc/rpc/pmap_getmaps.c (revision 288112) +++ head/lib/libc/rpc/pmap_getmaps.c (revision 288113) @@ -1,99 +1,98 @@ /* $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 __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 #include #include #include #include #include #include #include #include #include #include #include #include #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; +pmap_getmaps(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: head/lib/libc/rpc/pmap_getport.c =================================================================== --- head/lib/libc/rpc/pmap_getport.c (revision 288112) +++ head/lib/libc/rpc/pmap_getport.c (revision 288113) @@ -1,103 +1,100 @@ /* $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 __FBSDID("$FreeBSD$"); /* * pmap_getport.c * Client interface to pmap rpc service. * * Copyright (C) 1984, Sun Microsystems, Inc. */ #include "namespace.h" #include #include #include #include #include #include #include #include #include #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; +pmap_getport(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: head/lib/libc/rpc/pmap_prot.c =================================================================== --- head/lib/libc/rpc/pmap_prot.c (revision 288112) +++ head/lib/libc/rpc/pmap_prot.c (revision 288113) @@ -1,68 +1,66 @@ /* $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 __FBSDID("$FreeBSD$"); /* * pmap_prot.c * Protocol for the local binder service, or pmap. * * Copyright (C) 1984, Sun Microsystems, Inc. */ #include "namespace.h" #include #include #include #include #include "un-namespace.h" bool_t -xdr_pmap(xdrs, regs) - XDR *xdrs; - struct pmap *regs; +xdr_pmap(XDR *xdrs, struct pmap *regs) { assert(xdrs != NULL); assert(regs != NULL); if (xdr_u_long(xdrs, ®s->pm_prog) && xdr_u_long(xdrs, ®s->pm_vers) && xdr_u_long(xdrs, ®s->pm_prot)) return (xdr_u_long(xdrs, ®s->pm_port)); return (FALSE); } Index: head/lib/libc/rpc/pmap_prot2.c =================================================================== --- head/lib/libc/rpc/pmap_prot2.c (revision 288112) +++ head/lib/libc/rpc/pmap_prot2.c (revision 288113) @@ -1,142 +1,138 @@ /* $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 __FBSDID("$FreeBSD$"); /* * pmap_prot2.c * Protocol for the local binder service, or pmap. * * Copyright (C) 1984, Sun Microsystems, Inc. */ #include "namespace.h" #include #include #include #include #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; +xdr_pmaplist(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; +xdr_pmaplist_ptr(XDR *xdrs, struct pmaplist *rp) { return xdr_pmaplist(xdrs, (struct pmaplist **)(void *)rp); } Index: head/lib/libc/rpc/pmap_rmt.c =================================================================== --- head/lib/libc/rpc/pmap_rmt.c (revision 288112) +++ head/lib/libc/rpc/pmap_rmt.c (revision 288113) @@ -1,175 +1,166 @@ /* $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 __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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #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; +pmap_rmtcall(struct sockaddr_in *addr, u_long prog, u_long vers, u_long proc, + xdrproc_t xdrargs, caddr_t argsp, xdrproc_t xdrres, caddr_t 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; +xdr_rmtcall_args(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; +xdr_rmtcallres(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: head/lib/libc/rpc/rpc_callmsg.c =================================================================== --- head/lib/libc/rpc/rpc_callmsg.c (revision 288112) +++ head/lib/libc/rpc/rpc_callmsg.c (revision 288113) @@ -1,206 +1,204 @@ /* $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 __FBSDID("$FreeBSD$"); /* * rpc_callmsg.c * * Copyright (C) 1984, Sun Microsystems, Inc. * */ #include "namespace.h" #include #include #include #include #include "un-namespace.h" /* * XDR a call message */ bool_t -xdr_callmsg(xdrs, cmsg) - XDR *xdrs; - struct rpc_msg *cmsg; +xdr_callmsg(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: head/lib/libc/rpc/rpc_generic.c =================================================================== --- head/lib/libc/rpc/rpc_generic.c (revision 288112) +++ head/lib/libc/rpc/rpc_generic.c (revision 288113) @@ -1,846 +1,837 @@ /* $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 __FBSDID("$FreeBSD$"); /* * rpc_generic.c, Miscl routines for RPC. * */ #include "namespace.h" #include "reentrant.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #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() +__rpc_dtbsize(void) { 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 + * + * size - Size requested */ u_int /*ARGSUSED*/ -__rpc_get_t_size(af, proto, size) - int af, proto; - int size; /* Size requested */ +__rpc_get_t_size(int af, int proto, int size) { 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; +__rpc_get_a_size(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; +strlocase(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 * If nettype is NULL, it defaults to NETPATH. */ static int -getnettype(nettype) - const char *nettype; +getnettype(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; +__rpc_getconfip(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; +__rpc_setconf(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; +__rpc_getconf(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; +__rpc_endconf(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; +rpc_nullproc(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; +__rpcgettp(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: head/lib/libc/rpc/rpc_prot.c =================================================================== --- head/lib/libc/rpc/rpc_prot.c (revision 288112) +++ head/lib/libc/rpc/rpc_prot.c (revision 288113) @@ -1,357 +1,353 @@ /* $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 __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 #include #include #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(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(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(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(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(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(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(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; +rejected(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; +_seterr_reply(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: head/lib/libc/rpc/rpc_soc.c =================================================================== --- head/lib/libc/rpc/rpc_soc.c (revision 288112) +++ head/lib/libc/rpc/rpc_soc.c (revision 288113) @@ -1,534 +1,534 @@ /* $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 __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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #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(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(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(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(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(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(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(int fd, u_int sendsize, u_int recvsize) { return svc_com_create(fd, sendsize, recvsize, "tcp"); } SVCXPRT * svcudp_bufcreate(int fd, u_int sendsz, u_int recvsz) { return svc_com_create(fd, sendsz, recvsz, "udp"); } SVCXPRT * svcfd_create(int fd, u_int sendsize, u_int recvsize) { return svc_fd_create(fd, sendsize, recvsize); } SVCXPRT * svcudp_create(int fd) { return svc_com_create(fd, UDPMSGSIZE, UDPMSGSIZE, "udp"); } SVCXPRT * -svcraw_create() +svcraw_create(void) { return svc_raw_create(); } int get_myaddress(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(const char *host, int prognum, int versnum, int procnum, xdrproc_t inproc, void *in, xdrproc_t outproc, void *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(int prognum, int versnum, int procnum, char *(*progname)(char [UDPMSGSIZE]), xdrproc_t inproc, xdrproc_t 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(char *resultp, struct netbuf *addr, struct netconfig *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(u_long prog, u_long vers, u_long proc, xdrproc_t xargs, void *argsp, xdrproc_t xresults, void *resultsp, resultproc_t 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(char *servername, u_int window, struct sockaddr *syncaddr, des_block *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(struct sockaddr_un *raddr, u_long prog, u_long vers, int *sockp, u_int sendsz, u_int recvsz) { struct netbuf *svcaddr; CLIENT *cl; int len; cl = 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(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(int fd, u_int sendsize, u_int recvsize) { return (svc_fd_create(fd, sendsize, recvsize)); } #endif /* PORTMAP */ Index: head/lib/libc/rpc/rpcb_clnt.c =================================================================== --- head/lib/libc/rpc/rpcb_clnt.c (revision 288112) +++ head/lib/libc/rpc/rpcb_clnt.c (revision 288113) @@ -1,1312 +1,1311 @@ /* $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 __FBSDID("$FreeBSD$"); /* * rpcb_clnt.c * interface to rpcbind rpc service. */ #include "namespace.h" #include "reentrant.h" #include #include #include #include #include #include #include #include #ifdef PORTMAP #include /* FOR IPPROTO_TCP/UDP definitions */ #include #endif /* PORTMAP */ #include #include #include #include #include #include #include #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(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(const char *host, const char *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(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; +add_cache(const char *host, const char *netid, struct netbuf *taddr, + char *uaddr) { 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(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() +local_rpcb(void) { 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. * * nconf - Network structure of transport * address - Services netconfig address */ bool_t rpcb_set(rpcprog_t program, rpcvers_t version, const struct netconfig *nconf, const struct netbuf *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(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(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(void) { 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(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(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(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. -*/ + * + * nconf -Netconfig structure + * host - Remote host name + * proc - Remote proc identifiers + * xdrargs, xdrres; XDR routines + * argsp, resp - Argument and Result + * tout - Timeout value for this call + * addr_ptr - Preallocated netbuf address + */ 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 */ +rpcb_rmtcall(const struct netconfig *nconf, const char *host, rpcprog_t prog, + rpcvers_t vers, rpcproc_t proc, xdrproc_t xdrargs, caddr_t argsp, + xdrproc_t xdrres, caddr_t resp, struct timeval tout, + const struct netbuf *addr_ptr) { 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(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(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(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: head/lib/libc/rpc/rpcb_prot.c =================================================================== --- head/lib/libc/rpc/rpcb_prot.c (revision 288112) +++ head/lib/libc/rpc/rpcb_prot.c (revision 288113) @@ -1,331 +1,315 @@ /* $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 __FBSDID("$FreeBSD$"); /* * rpcb_prot.c * XDR routines for the rpcbinder version 3. * * Copyright (C) 1984, 1988, Sun Microsystems, Inc. */ #include "namespace.h" #include #include #include #include #include "un-namespace.h" bool_t -xdr_rpcb(xdrs, objp) - XDR *xdrs; - RPCB *objp; +xdr_rpcb(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; +xdr_rpcblist_ptr(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; +xdr_rpcblist(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; +xdr_rpcb_entry(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; +xdr_rpcb_entry_list_ptr(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; +xdr_rpcb_rmtcallargs(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; +xdr_rpcb_rmtcallres(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; +xdr_netbuf(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: head/lib/libc/rpc/rpcb_st_xdr.c =================================================================== --- head/lib/libc/rpc/rpcb_st_xdr.c (revision 288112) +++ head/lib/libc/rpc/rpcb_st_xdr.c (revision 288113) @@ -1,274 +1,260 @@ /* $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 __FBSDID("$FreeBSD$"); #include "namespace.h" #include #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; +xdr_rpcbs_addrlist(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; +xdr_rpcbs_rmtcalllist(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; +xdr_rpcbs_proc(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; +xdr_rpcbs_addrlist_ptr(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; +xdr_rpcbs_rmtcalllist_ptr(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; +xdr_rpcb_stat(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; +xdr_rpcb_stat_byvers(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: head/lib/libc/rpc/svc_auth.c =================================================================== --- head/lib/libc/rpc/svc_auth.c (revision 288112) +++ head/lib/libc/rpc/svc_auth.c (revision 288113) @@ -1,226 +1,224 @@ /* $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 __FBSDID("$FreeBSD$"); /* * svc_auth.c, Server-side rpc authenticator interface. * */ #include "namespace.h" #include "reentrant.h" #include #include #include #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; +_authenticate(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(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(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(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: head/lib/libc/rpc/svc_auth_unix.c =================================================================== --- head/lib/libc/rpc/svc_auth_unix.c (revision 288112) +++ head/lib/libc/rpc/svc_auth_unix.c (revision 288113) @@ -1,155 +1,151 @@ /*- * 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 __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 #include #include #include #include "un-namespace.h" /* * Unix longhand authenticator */ enum auth_stat -_svcauth_unix(rqst, msg) - struct svc_req *rqst; - struct rpc_msg *msg; +_svcauth_unix(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; +_svcauth_short(struct svc_req *rqst, struct rpc_msg *msg) { return (AUTH_REJECTEDCRED); } Index: head/lib/libc/rpc/svc_generic.c =================================================================== --- head/lib/libc/rpc/svc_generic.c (revision 288112) +++ head/lib/libc/rpc/svc_generic.c (revision 288113) @@ -1,310 +1,314 @@ /* $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 __FBSDID("$FreeBSD$"); /* * svc_generic.c, Server side for RPC. * */ #include "namespace.h" #include "reentrant.h" #include #include #include #include #include #include #include #include #include #include #include #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. + * + * prognum - Program number + * versnum - Version number + * nettype - Networktype token */ 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 */ +svc_create(void (*dispatch)(struct svc_req *, SVCXPRT *), + rpcprog_t prognum, rpcvers_t versnum, const char *nettype) { 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(); + * + * prognum - Program number + * versnum - Version number + * ncofn - Netconfig structure for the network */ 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 */ +svc_tp_create(void (*dispatch)(struct svc_req *, SVCXPRT *), + rpcprog_t prognum, rpcvers_t versnum, const struct netconfig *nconf) { 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. + * + * fd - Connection end point + * nconf - Netconfig struct for nettoken + * bindaddr - Local bind address + * sendsz - Max sendsize + * recvxz - Max recvsize */ 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 */ +svc_tli_create(int fd, const struct netconfig *nconf, + const struct t_bind *bindaddr, u_int sendsz, u_int recvsz) { 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: head/lib/libc/rpc/svc_raw.c =================================================================== --- head/lib/libc/rpc/svc_raw.c (revision 288112) +++ head/lib/libc/rpc/svc_raw.c (revision 288113) @@ -1,285 +1,269 @@ /* $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 __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 #include #include #include #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() +svc_raw_create(void) { 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 */ +svc_raw_stat(SVCXPRT *xprt) { return (XPRT_IDLE); } /*ARGSUSED*/ static bool_t -svc_raw_recv(xprt, msg) - SVCXPRT *xprt; - struct rpc_msg *msg; +svc_raw_recv(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; +svc_raw_reply(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; +svc_raw_getargs(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; +svc_raw_freeargs(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; +svc_raw_destroy(SVCXPRT *xprt) { } /*ARGSUSED*/ static bool_t -svc_raw_control(xprt, rq, in) - SVCXPRT *xprt; - const u_int rq; - void *in; +svc_raw_control(SVCXPRT *xprt, const u_int rq, void *in) { return (FALSE); } static void -svc_raw_ops(xprt) - SVCXPRT *xprt; +svc_raw_ops(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: head/lib/libc/rpc/svc_run.c =================================================================== --- head/lib/libc/rpc/svc_run.c (revision 288112) +++ head/lib/libc/rpc/svc_run.c (revision 288113) @@ -1,97 +1,97 @@ /* $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 __FBSDID("$FreeBSD$"); /* * This is the rpc server side idle loop * Wait for input, call server program. */ #include "namespace.h" #include "reentrant.h" #include #include #include #include #include #include #include "un-namespace.h" #include #include "rpc_com.h" #include "mt_misc.h" void -svc_run() +svc_run(void) { 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() +svc_exit(void) { rwlock_wrlock(&svc_fd_lock); FD_ZERO(&svc_fdset); rwlock_unlock(&svc_fd_lock); } Index: head/lib/libc/rpc/svc_simple.c =================================================================== --- head/lib/libc/rpc/svc_simple.c (revision 288112) +++ head/lib/libc/rpc/svc_simple.c (revision 288113) @@ -1,312 +1,312 @@ /* $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 __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 #include #include #include #include #include #include #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. + * + * prognum - program number + * versnum - version number + * procnum - procedure number + * progname - Server routine + * inproc, outproc - in/out XDR procedures + * nettype - nettype */ - 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 */ +rpc_reg(rpcprog_t prognum, rpcvers_t versnum, rpcproc_t procnum, + char *(*progname)(char *), xdrproc_t inproc, xdrproc_t outproc, + char *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; +universal(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; }