17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
53582b7c1Sgt29601 * Common Development and Distribution License (the "License").
63582b7c1Sgt29601 * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate *
87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate * and limitations under the License.
127c478bd9Sstevel@tonic-gate *
137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate *
197c478bd9Sstevel@tonic-gate * CDDL HEADER END
207c478bd9Sstevel@tonic-gate */
217c478bd9Sstevel@tonic-gate /*
2236e852a1SRaja Andra * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
237c478bd9Sstevel@tonic-gate * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate */
258f6d9daeSMarcel Telka /*
268f6d9daeSMarcel Telka * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
27*77b65ce6SAlex Wilson * Copyright 2017 Joyent Inc
288f6d9daeSMarcel Telka */
297c478bd9Sstevel@tonic-gate /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
307c478bd9Sstevel@tonic-gate /* All Rights Reserved */
317c478bd9Sstevel@tonic-gate /*
327c478bd9Sstevel@tonic-gate * University Copyright- Copyright (c) 1982, 1986, 1988
337c478bd9Sstevel@tonic-gate * The Regents of the University of California
347c478bd9Sstevel@tonic-gate * All Rights Reserved
357c478bd9Sstevel@tonic-gate *
367c478bd9Sstevel@tonic-gate * University Acknowledgment- Portions of this document are derived from
377c478bd9Sstevel@tonic-gate * software developed by the University of California, Berkeley, and its
387c478bd9Sstevel@tonic-gate * contributors.
397c478bd9Sstevel@tonic-gate */
407c478bd9Sstevel@tonic-gate
417c478bd9Sstevel@tonic-gate /*
427c478bd9Sstevel@tonic-gate * rpcb_svc_com.c
437c478bd9Sstevel@tonic-gate * The commom server procedure for the rpcbind.
447c478bd9Sstevel@tonic-gate */
457c478bd9Sstevel@tonic-gate
467c478bd9Sstevel@tonic-gate #include <stdio.h>
477c478bd9Sstevel@tonic-gate #include <sys/types.h>
487c478bd9Sstevel@tonic-gate #include <sys/stat.h>
497c478bd9Sstevel@tonic-gate #include <unistd.h>
507c478bd9Sstevel@tonic-gate #include <stdlib.h>
517c478bd9Sstevel@tonic-gate #include <string.h>
527c478bd9Sstevel@tonic-gate #include <strings.h>
537c478bd9Sstevel@tonic-gate #include <rpc/rpc.h>
547c478bd9Sstevel@tonic-gate #include <rpc/rpcb_prot.h>
55f48205beScasper #include <rpcsvc/svc_dg_priv.h>
567c478bd9Sstevel@tonic-gate #include <netconfig.h>
577c478bd9Sstevel@tonic-gate #include <sys/param.h>
587c478bd9Sstevel@tonic-gate #include <errno.h>
597c478bd9Sstevel@tonic-gate #include <zone.h>
607c478bd9Sstevel@tonic-gate #include <sys/poll.h>
617c478bd9Sstevel@tonic-gate #include <sys/stropts.h>
627c478bd9Sstevel@tonic-gate #ifdef PORTMAP
637c478bd9Sstevel@tonic-gate #include <netinet/in.h>
647c478bd9Sstevel@tonic-gate #include <rpc/pmap_prot.h>
658f6d9daeSMarcel Telka #else
668f6d9daeSMarcel Telka #define PMAPVERS 2
677c478bd9Sstevel@tonic-gate #endif /* PORTMAP */
687c478bd9Sstevel@tonic-gate #include <syslog.h>
697c478bd9Sstevel@tonic-gate #include <netdir.h>
707c478bd9Sstevel@tonic-gate #include <ucred.h>
717c478bd9Sstevel@tonic-gate #include <alloca.h>
727c478bd9Sstevel@tonic-gate #include <rpcsvc/yp_prot.h>
737c478bd9Sstevel@tonic-gate #include <nfs/nfs.h>
747c478bd9Sstevel@tonic-gate #include <nfs/nfs_acl.h>
757c478bd9Sstevel@tonic-gate #include <rpcsvc/mount.h>
767c478bd9Sstevel@tonic-gate #include <nfs/nfs_acl.h>
777c478bd9Sstevel@tonic-gate #include <rpc/key_prot.h>
787c478bd9Sstevel@tonic-gate #include <rpcsvc/yp_prot.h>
797c478bd9Sstevel@tonic-gate #include <rpcsvc/rquota.h>
807c478bd9Sstevel@tonic-gate #include <rpcsvc/yppasswd.h>
817c478bd9Sstevel@tonic-gate #include <rpcsvc/ypupd.h>
828f6d9daeSMarcel Telka #include <assert.h>
838f6d9daeSMarcel Telka #include <synch.h>
847c478bd9Sstevel@tonic-gate #include "rpcbind.h"
85*77b65ce6SAlex Wilson #include <sys/debug.h>
867c478bd9Sstevel@tonic-gate
878f6d9daeSMarcel Telka static struct finfo *forward_register(ulong_t, struct netbuf *, int, char *);
888f6d9daeSMarcel Telka static void forward_destroy(struct finfo *);
898f6d9daeSMarcel Telka static void handle_reply(svc_input_id_t, int, unsigned int, void *);
908f6d9daeSMarcel Telka static int netbufcmp(struct netbuf *, struct netbuf *);
918f6d9daeSMarcel Telka static void netbuffree(struct netbuf *);
928f6d9daeSMarcel Telka static struct netbuf *netbufdup(struct netbuf *);
938f6d9daeSMarcel Telka static void find_versions(rpcprog_t, char *, rpcvers_t *, rpcvers_t *);
948f6d9daeSMarcel Telka static rpcblist_ptr find_service(ulong_t, ulong_t, char *);
958f6d9daeSMarcel Telka #ifdef PORTMAP
967c478bd9Sstevel@tonic-gate static int add_pmaplist(RPCB *);
978f6d9daeSMarcel Telka #endif
987c478bd9Sstevel@tonic-gate
998f6d9daeSMarcel Telka zoneid_t myzone;
1007c478bd9Sstevel@tonic-gate
1017c478bd9Sstevel@tonic-gate /*
1027c478bd9Sstevel@tonic-gate * Set a mapping of program, version, netid
1037c478bd9Sstevel@tonic-gate */
1048f6d9daeSMarcel Telka bool_t
rpcbproc_set_com(RPCB * regp,bool_t * result,struct svc_req * rqstp,int rpcbversnum)1058f6d9daeSMarcel Telka rpcbproc_set_com(RPCB *regp, bool_t *result, struct svc_req *rqstp,
1068f6d9daeSMarcel Telka int rpcbversnum)
1077c478bd9Sstevel@tonic-gate {
1087c478bd9Sstevel@tonic-gate char owner[64];
1097c478bd9Sstevel@tonic-gate
1108f6d9daeSMarcel Telka *result = map_set(regp, getowner(rqstp->rq_xprt, owner));
1118f6d9daeSMarcel Telka
1128f6d9daeSMarcel Telka rpcbs_set(rpcbversnum - PMAPVERS, *result);
1138f6d9daeSMarcel Telka
1148f6d9daeSMarcel Telka return (TRUE);
1157c478bd9Sstevel@tonic-gate }
1167c478bd9Sstevel@tonic-gate
1177c478bd9Sstevel@tonic-gate bool_t
map_set(RPCB * regp,char * owner)1188f6d9daeSMarcel Telka map_set(RPCB *regp, char *owner)
1197c478bd9Sstevel@tonic-gate {
1208f6d9daeSMarcel Telka RPCB *a;
1217c478bd9Sstevel@tonic-gate rpcblist_ptr rbl, fnd;
1227c478bd9Sstevel@tonic-gate
1237c478bd9Sstevel@tonic-gate /*
1247c478bd9Sstevel@tonic-gate * check to see if already used
1257c478bd9Sstevel@tonic-gate * find_service returns a hit even if
1267c478bd9Sstevel@tonic-gate * the versions don't match, so check for it
1277c478bd9Sstevel@tonic-gate */
1288f6d9daeSMarcel Telka (void) rw_wrlock(&list_rbl_lock);
1298f6d9daeSMarcel Telka #ifdef PORTMAP
1308f6d9daeSMarcel Telka (void) rw_wrlock(&list_pml_lock);
1318f6d9daeSMarcel Telka #endif /* PORTMAP */
1328f6d9daeSMarcel Telka fnd = find_service(regp->r_prog, regp->r_vers, regp->r_netid);
1338f6d9daeSMarcel Telka if (fnd && (fnd->rpcb_map.r_vers == regp->r_vers)) {
1348f6d9daeSMarcel Telka if (strcmp(fnd->rpcb_map.r_addr, regp->r_addr) == 0) {
1357c478bd9Sstevel@tonic-gate /*
1367c478bd9Sstevel@tonic-gate * if these match then it is already
1377c478bd9Sstevel@tonic-gate * registered so just say "OK".
1387c478bd9Sstevel@tonic-gate */
1398f6d9daeSMarcel Telka #ifdef PORTMAP
1408f6d9daeSMarcel Telka (void) rw_unlock(&list_pml_lock);
1418f6d9daeSMarcel Telka #endif /* PORTMAP */
1428f6d9daeSMarcel Telka (void) rw_unlock(&list_rbl_lock);
1437c478bd9Sstevel@tonic-gate return (TRUE);
1448f6d9daeSMarcel Telka } else {
1457c478bd9Sstevel@tonic-gate /*
1467c478bd9Sstevel@tonic-gate * Check if server is up. If so, return FALSE.
1477c478bd9Sstevel@tonic-gate * If not, cleanup old registrations for the
1487c478bd9Sstevel@tonic-gate * program and register the new server.
1497c478bd9Sstevel@tonic-gate */
1507c478bd9Sstevel@tonic-gate if (is_bound(fnd->rpcb_map.r_netid,
1518f6d9daeSMarcel Telka fnd->rpcb_map.r_addr)) {
1528f6d9daeSMarcel Telka #ifdef PORTMAP
1538f6d9daeSMarcel Telka (void) rw_unlock(&list_pml_lock);
1548f6d9daeSMarcel Telka #endif /* PORTMAP */
1558f6d9daeSMarcel Telka (void) rw_unlock(&list_rbl_lock);
1567c478bd9Sstevel@tonic-gate return (FALSE);
1578f6d9daeSMarcel Telka }
1588f6d9daeSMarcel Telka
1598f6d9daeSMarcel Telka delete_prog(regp->r_prog);
1607c478bd9Sstevel@tonic-gate fnd = NULL;
1617c478bd9Sstevel@tonic-gate }
1627c478bd9Sstevel@tonic-gate }
1638f6d9daeSMarcel Telka #ifdef PORTMAP
1648f6d9daeSMarcel Telka (void) rw_unlock(&list_pml_lock);
1658f6d9daeSMarcel Telka #endif /* PORTMAP */
1668f6d9daeSMarcel Telka
1677c478bd9Sstevel@tonic-gate /*
1687c478bd9Sstevel@tonic-gate * add to the end of the list
1697c478bd9Sstevel@tonic-gate */
1708f6d9daeSMarcel Telka rbl = malloc(sizeof (RPCBLIST));
1718f6d9daeSMarcel Telka if (rbl == NULL) {
1728f6d9daeSMarcel Telka (void) rw_unlock(&list_rbl_lock);
1737c478bd9Sstevel@tonic-gate return (FALSE);
1747c478bd9Sstevel@tonic-gate }
1758f6d9daeSMarcel Telka a = &rbl->rpcb_map;
1768f6d9daeSMarcel Telka a->r_prog = regp->r_prog;
1778f6d9daeSMarcel Telka a->r_vers = regp->r_vers;
1788f6d9daeSMarcel Telka a->r_netid = strdup(regp->r_netid);
1798f6d9daeSMarcel Telka a->r_addr = strdup(regp->r_addr);
1807c478bd9Sstevel@tonic-gate a->r_owner = strdup(owner);
1817c478bd9Sstevel@tonic-gate if (a->r_addr == NULL || a->r_netid == NULL|| a->r_owner == NULL) {
1828f6d9daeSMarcel Telka (void) rw_unlock(&list_rbl_lock);
1837c478bd9Sstevel@tonic-gate delete_rbl(rbl);
1847c478bd9Sstevel@tonic-gate return (FALSE);
1857c478bd9Sstevel@tonic-gate }
1868f6d9daeSMarcel Telka rbl->rpcb_next = NULL;
1877c478bd9Sstevel@tonic-gate if (list_rbl == NULL) {
1887c478bd9Sstevel@tonic-gate list_rbl = rbl;
1897c478bd9Sstevel@tonic-gate } else {
1908f6d9daeSMarcel Telka for (fnd = list_rbl; fnd->rpcb_next; fnd = fnd->rpcb_next)
1917c478bd9Sstevel@tonic-gate ;
1927c478bd9Sstevel@tonic-gate fnd->rpcb_next = rbl;
1937c478bd9Sstevel@tonic-gate }
1948f6d9daeSMarcel Telka
1957c478bd9Sstevel@tonic-gate #ifdef PORTMAP
1967c478bd9Sstevel@tonic-gate (void) add_pmaplist(regp);
1977c478bd9Sstevel@tonic-gate #endif
1988f6d9daeSMarcel Telka (void) rw_unlock(&list_rbl_lock);
1997c478bd9Sstevel@tonic-gate return (TRUE);
2007c478bd9Sstevel@tonic-gate }
2017c478bd9Sstevel@tonic-gate
2027c478bd9Sstevel@tonic-gate /*
2037c478bd9Sstevel@tonic-gate * Unset a mapping of program, version, netid
2047c478bd9Sstevel@tonic-gate */
2058f6d9daeSMarcel Telka bool_t
rpcbproc_unset_com(RPCB * regp,bool_t * result,struct svc_req * rqstp,int rpcbversnum)2068f6d9daeSMarcel Telka rpcbproc_unset_com(RPCB *regp, bool_t *result, struct svc_req *rqstp,
2078f6d9daeSMarcel Telka int rpcbversnum)
2087c478bd9Sstevel@tonic-gate {
2097c478bd9Sstevel@tonic-gate char owner[64];
2107c478bd9Sstevel@tonic-gate
2118f6d9daeSMarcel Telka *result = map_unset(regp, getowner(rqstp->rq_xprt, owner));
2128f6d9daeSMarcel Telka
2138f6d9daeSMarcel Telka rpcbs_unset(rpcbversnum - PMAPVERS, *result);
2148f6d9daeSMarcel Telka
2158f6d9daeSMarcel Telka return (TRUE);
2167c478bd9Sstevel@tonic-gate }
2177c478bd9Sstevel@tonic-gate
2187c478bd9Sstevel@tonic-gate bool_t
map_unset(RPCB * regp,char * owner)2198f6d9daeSMarcel Telka map_unset(RPCB *regp, char *owner)
2207c478bd9Sstevel@tonic-gate {
2217c478bd9Sstevel@tonic-gate #ifdef PORTMAP
2227c478bd9Sstevel@tonic-gate int ans = 0;
2237c478bd9Sstevel@tonic-gate #endif
2247c478bd9Sstevel@tonic-gate rpcblist_ptr rbl, next, prev = NULL;
2257c478bd9Sstevel@tonic-gate
2267c478bd9Sstevel@tonic-gate if (owner == NULL)
2277c478bd9Sstevel@tonic-gate return (0);
2287c478bd9Sstevel@tonic-gate
2298f6d9daeSMarcel Telka (void) rw_wrlock(&list_rbl_lock);
2307c478bd9Sstevel@tonic-gate for (rbl = list_rbl; rbl != NULL; rbl = next) {
2317c478bd9Sstevel@tonic-gate next = rbl->rpcb_next;
2327c478bd9Sstevel@tonic-gate
2337c478bd9Sstevel@tonic-gate if ((rbl->rpcb_map.r_prog != regp->r_prog) ||
2347c478bd9Sstevel@tonic-gate (rbl->rpcb_map.r_vers != regp->r_vers) ||
2357c478bd9Sstevel@tonic-gate (regp->r_netid[0] && strcasecmp(regp->r_netid,
2367c478bd9Sstevel@tonic-gate rbl->rpcb_map.r_netid))) {
2377c478bd9Sstevel@tonic-gate /* prev moves forwards */
2387c478bd9Sstevel@tonic-gate prev = rbl;
2397c478bd9Sstevel@tonic-gate continue;
2407c478bd9Sstevel@tonic-gate }
2418f6d9daeSMarcel Telka
2427c478bd9Sstevel@tonic-gate /*
2437c478bd9Sstevel@tonic-gate * Check whether appropriate uid. Unset only
2447c478bd9Sstevel@tonic-gate * if superuser or the owner itself.
2457c478bd9Sstevel@tonic-gate */
2467c478bd9Sstevel@tonic-gate if (strcmp(owner, "superuser") &&
2478f6d9daeSMarcel Telka strcmp(rbl->rpcb_map.r_owner, owner)) {
2488f6d9daeSMarcel Telka (void) rw_unlock(&list_rbl_lock);
2497c478bd9Sstevel@tonic-gate return (0);
2508f6d9daeSMarcel Telka }
2518f6d9daeSMarcel Telka
2527c478bd9Sstevel@tonic-gate /* prev stays */
2537c478bd9Sstevel@tonic-gate #ifdef PORTMAP
2547c478bd9Sstevel@tonic-gate ans = 1;
2557c478bd9Sstevel@tonic-gate #endif
2567c478bd9Sstevel@tonic-gate delete_rbl(rbl);
2577c478bd9Sstevel@tonic-gate
2587c478bd9Sstevel@tonic-gate if (prev == NULL)
2597c478bd9Sstevel@tonic-gate list_rbl = next;
2607c478bd9Sstevel@tonic-gate else
2617c478bd9Sstevel@tonic-gate prev->rpcb_next = next;
2627c478bd9Sstevel@tonic-gate }
2637c478bd9Sstevel@tonic-gate #ifdef PORTMAP
2648f6d9daeSMarcel Telka if (ans != 0) {
2658f6d9daeSMarcel Telka (void) rw_wrlock(&list_pml_lock);
2667c478bd9Sstevel@tonic-gate (void) del_pmaplist(regp);
2678f6d9daeSMarcel Telka (void) rw_unlock(&list_pml_lock);
2688f6d9daeSMarcel Telka }
2697c478bd9Sstevel@tonic-gate #endif
2708f6d9daeSMarcel Telka (void) rw_unlock(&list_rbl_lock);
2718f6d9daeSMarcel Telka
2727c478bd9Sstevel@tonic-gate /*
2737c478bd9Sstevel@tonic-gate * We return 1 either when the entry was not there or it
2747c478bd9Sstevel@tonic-gate * was able to unset it. It can come to this point only if
2757c478bd9Sstevel@tonic-gate * at least one of the conditions is true.
2767c478bd9Sstevel@tonic-gate */
2777c478bd9Sstevel@tonic-gate return (1);
2787c478bd9Sstevel@tonic-gate }
2797c478bd9Sstevel@tonic-gate
2803582b7c1Sgt29601 void
delete_rbl(rpcblist_ptr rbl)2813582b7c1Sgt29601 delete_rbl(rpcblist_ptr rbl)
2827c478bd9Sstevel@tonic-gate {
2837c478bd9Sstevel@tonic-gate free(rbl->rpcb_map.r_addr);
2847c478bd9Sstevel@tonic-gate free(rbl->rpcb_map.r_netid);
2857c478bd9Sstevel@tonic-gate free(rbl->rpcb_map.r_owner);
2867c478bd9Sstevel@tonic-gate free(rbl);
2877c478bd9Sstevel@tonic-gate }
2887c478bd9Sstevel@tonic-gate
2897c478bd9Sstevel@tonic-gate void
delete_prog(rpcprog_t prog)2908f6d9daeSMarcel Telka delete_prog(rpcprog_t prog)
2917c478bd9Sstevel@tonic-gate {
2927c478bd9Sstevel@tonic-gate rpcblist_ptr rbl, next, prev = NULL;
2937c478bd9Sstevel@tonic-gate
2948f6d9daeSMarcel Telka assert(RW_WRITE_HELD(&list_rbl_lock));
2958f6d9daeSMarcel Telka
2967c478bd9Sstevel@tonic-gate for (rbl = list_rbl; rbl != NULL; rbl = next) {
2977c478bd9Sstevel@tonic-gate next = rbl->rpcb_next;
2987c478bd9Sstevel@tonic-gate
2997c478bd9Sstevel@tonic-gate if (rbl->rpcb_map.r_prog != prog ||
3007c478bd9Sstevel@tonic-gate is_bound(rbl->rpcb_map.r_netid, rbl->rpcb_map.r_addr)) {
3017c478bd9Sstevel@tonic-gate prev = rbl;
3027c478bd9Sstevel@tonic-gate continue;
3037c478bd9Sstevel@tonic-gate }
3047c478bd9Sstevel@tonic-gate
3057c478bd9Sstevel@tonic-gate #ifdef PORTMAP
3067c478bd9Sstevel@tonic-gate (void) del_pmaplist(&rbl->rpcb_map);
3077c478bd9Sstevel@tonic-gate #endif
3087c478bd9Sstevel@tonic-gate delete_rbl(rbl);
3097c478bd9Sstevel@tonic-gate
3107c478bd9Sstevel@tonic-gate if (prev == NULL)
3117c478bd9Sstevel@tonic-gate list_rbl = next;
3127c478bd9Sstevel@tonic-gate else
3137c478bd9Sstevel@tonic-gate prev->rpcb_next = next;
3147c478bd9Sstevel@tonic-gate }
3157c478bd9Sstevel@tonic-gate }
3167c478bd9Sstevel@tonic-gate
3178f6d9daeSMarcel Telka /*
3188f6d9daeSMarcel Telka * Lookup the mapping for a program, version and return its
3198f6d9daeSMarcel Telka * address. Assuming that the caller wants the address of the
3208f6d9daeSMarcel Telka * server running on the transport on which the request came.
3218f6d9daeSMarcel Telka *
3228f6d9daeSMarcel Telka * For RPCBPROC_GETVERSADDR it will return a service with the exact version
3238f6d9daeSMarcel Telka * number only.
3248f6d9daeSMarcel Telka *
3258f6d9daeSMarcel Telka * Otherwise, even if a service with a different version number is available,
3268f6d9daeSMarcel Telka * it will return that address. The client should check with an
3278f6d9daeSMarcel Telka * clnt_call to verify whether the service is the one that is desired.
3288f6d9daeSMarcel Telka *
3298f6d9daeSMarcel Telka * We also try to resolve the universal address in terms of
3308f6d9daeSMarcel Telka * address of the caller.
3318f6d9daeSMarcel Telka */
3328f6d9daeSMarcel Telka bool_t
rpcbproc_getaddr_com(RPCB * regp,char ** result,struct svc_req * rqstp,ulong_t rpcbversnum)3338f6d9daeSMarcel Telka rpcbproc_getaddr_com(RPCB *regp, char **result, struct svc_req *rqstp,
3348f6d9daeSMarcel Telka ulong_t rpcbversnum)
3357c478bd9Sstevel@tonic-gate {
3367c478bd9Sstevel@tonic-gate char *saddr = NULL;
3377c478bd9Sstevel@tonic-gate rpcblist_ptr fnd;
3387c478bd9Sstevel@tonic-gate struct netconfig *trans_conf; /* transport netconfig */
3398f6d9daeSMarcel Telka SVCXPRT *transp = rqstp->rq_xprt;
3408f6d9daeSMarcel Telka int verstype = rqstp->rq_proc == RPCBPROC_GETVERSADDR ? RPCB_ONEVERS :
3418f6d9daeSMarcel Telka RPCB_ALLVERS;
3428f6d9daeSMarcel Telka bool_t pml_locked = FALSE;
3437c478bd9Sstevel@tonic-gate
3447c478bd9Sstevel@tonic-gate /*
3457c478bd9Sstevel@tonic-gate * There is a potential window at startup during which rpcbind
3467c478bd9Sstevel@tonic-gate * service has been established over IPv6 but not over IPv4. If an
3477c478bd9Sstevel@tonic-gate * IPv4 request comes in during that window, the IP code will map
3487c478bd9Sstevel@tonic-gate * it into IPv6. We could patch up the request so that it looks
3497c478bd9Sstevel@tonic-gate * like IPv4 (so that rpcbind returns an IPv4 uaddr to the caller),
3507c478bd9Sstevel@tonic-gate * but that requires some non-trivial code and it's hard to test.
3517c478bd9Sstevel@tonic-gate * Instead, drop the request on the floor and force the caller to
3527c478bd9Sstevel@tonic-gate * retransmit. By the time rpcbind sees the retransmission, IPv4
3537c478bd9Sstevel@tonic-gate * service should be in place and it should see the request as
3547c478bd9Sstevel@tonic-gate * IPv4, as desired.
3557c478bd9Sstevel@tonic-gate */
3567c478bd9Sstevel@tonic-gate trans_conf = rpcbind_get_conf(transp->xp_netid);
3577c478bd9Sstevel@tonic-gate if (strcmp(trans_conf->nc_protofmly, NC_INET6) == 0) {
3587c478bd9Sstevel@tonic-gate struct sockaddr_in6 *rmtaddr;
3597c478bd9Sstevel@tonic-gate
3607c478bd9Sstevel@tonic-gate rmtaddr = (struct sockaddr_in6 *)transp->xp_rtaddr.buf;
3617c478bd9Sstevel@tonic-gate if (IN6_IS_ADDR_V4MAPPED(&rmtaddr->sin6_addr)) {
3627c478bd9Sstevel@tonic-gate syslog(LOG_DEBUG,
3637c478bd9Sstevel@tonic-gate "IPv4 GETADDR request mapped to IPv6: ignoring");
3648f6d9daeSMarcel Telka *result = NULL;
3658f6d9daeSMarcel Telka return (FALSE);
3667c478bd9Sstevel@tonic-gate }
3677c478bd9Sstevel@tonic-gate }
3687c478bd9Sstevel@tonic-gate
3698f6d9daeSMarcel Telka (void) rw_rdlock(&list_rbl_lock);
3708f6d9daeSMarcel Telka retry:
3717c478bd9Sstevel@tonic-gate fnd = find_service(regp->r_prog, regp->r_vers, transp->xp_netid);
3727c478bd9Sstevel@tonic-gate if (fnd && ((verstype == RPCB_ALLVERS) ||
3737c478bd9Sstevel@tonic-gate (regp->r_vers == fnd->rpcb_map.r_vers))) {
3747c478bd9Sstevel@tonic-gate if (*(regp->r_addr) != '\0') { /* may contain a hint about */
3757c478bd9Sstevel@tonic-gate saddr = regp->r_addr; /* the interface that we */
3767c478bd9Sstevel@tonic-gate } /* should use */
3778f6d9daeSMarcel Telka if (!(*result = mergeaddr(transp, transp->xp_netid,
3787c478bd9Sstevel@tonic-gate fnd->rpcb_map.r_addr, saddr))) {
3797c478bd9Sstevel@tonic-gate /* Try whatever we have */
3808f6d9daeSMarcel Telka *result = strdup(fnd->rpcb_map.r_addr);
3818f6d9daeSMarcel Telka } else if (!(*result)[0]) {
3828f6d9daeSMarcel Telka if (!pml_locked) {
3838f6d9daeSMarcel Telka (void) rw_unlock(&list_rbl_lock);
3848f6d9daeSMarcel Telka (void) rw_wrlock(&list_rbl_lock);
3858f6d9daeSMarcel Telka #ifdef PORTMAP
3868f6d9daeSMarcel Telka (void) rw_wrlock(&list_pml_lock);
3878f6d9daeSMarcel Telka #endif /* PORTMAP */
3888f6d9daeSMarcel Telka pml_locked = TRUE;
3898f6d9daeSMarcel Telka goto retry;
3908f6d9daeSMarcel Telka }
3917c478bd9Sstevel@tonic-gate /*
3927c478bd9Sstevel@tonic-gate * The server died. Unset all versions of this prog.
3937c478bd9Sstevel@tonic-gate */
3947c478bd9Sstevel@tonic-gate delete_prog(regp->r_prog);
3958f6d9daeSMarcel Telka *result = NULL;
3967c478bd9Sstevel@tonic-gate }
3977c478bd9Sstevel@tonic-gate } else {
3988f6d9daeSMarcel Telka *result = NULL;
3997c478bd9Sstevel@tonic-gate }
4008f6d9daeSMarcel Telka #ifdef PORTMAP
4018f6d9daeSMarcel Telka if (pml_locked)
4028f6d9daeSMarcel Telka (void) rw_unlock(&list_pml_lock);
4038f6d9daeSMarcel Telka #endif /* PORTMAP */
4048f6d9daeSMarcel Telka (void) rw_unlock(&list_rbl_lock);
4058f6d9daeSMarcel Telka
4068f6d9daeSMarcel Telka rpcbs_getaddr(rpcbversnum - PMAPVERS, regp->r_prog, regp->r_vers,
4078f6d9daeSMarcel Telka transp->xp_netid, *result);
4088f6d9daeSMarcel Telka return (TRUE);
4097c478bd9Sstevel@tonic-gate }
4107c478bd9Sstevel@tonic-gate
4118f6d9daeSMarcel Telka /* ARGSUSED */
4128f6d9daeSMarcel Telka bool_t
rpcbproc_dump_com(void * argp,rpcblist_ptr ** result)4138f6d9daeSMarcel Telka rpcbproc_dump_com(void *argp, rpcblist_ptr **result)
4147c478bd9Sstevel@tonic-gate {
4158f6d9daeSMarcel Telka /*
4168f6d9daeSMarcel Telka * list_rbl_lock is unlocked in xdr_rpcblist_ptr_ptr()
4178f6d9daeSMarcel Telka */
4188f6d9daeSMarcel Telka (void) rw_rdlock(&list_rbl_lock);
4198f6d9daeSMarcel Telka *result = &list_rbl;
4208f6d9daeSMarcel Telka return (TRUE);
4218f6d9daeSMarcel Telka }
4227c478bd9Sstevel@tonic-gate
4238f6d9daeSMarcel Telka bool_t
xdr_rpcblist_ptr_ptr(XDR * xdrs,rpcblist_ptr ** objp)4248f6d9daeSMarcel Telka xdr_rpcblist_ptr_ptr(XDR *xdrs, rpcblist_ptr **objp)
4258f6d9daeSMarcel Telka {
4268f6d9daeSMarcel Telka if (xdrs->x_op == XDR_FREE) {
4278f6d9daeSMarcel Telka /*
4288f6d9daeSMarcel Telka * list_rbl_lock is locked in rpcbproc_dump_com()
4298f6d9daeSMarcel Telka */
4308f6d9daeSMarcel Telka rw_unlock(&list_rbl_lock);
4318f6d9daeSMarcel Telka return (TRUE);
4328f6d9daeSMarcel Telka }
4338f6d9daeSMarcel Telka
4348f6d9daeSMarcel Telka return (xdr_rpcblist_ptr(xdrs, *objp));
4358f6d9daeSMarcel Telka }
4368f6d9daeSMarcel Telka
4378f6d9daeSMarcel Telka /* ARGSUSED */
4388f6d9daeSMarcel Telka bool_t
rpcbproc_gettime_com(void * argp,ulong_t * result)4398f6d9daeSMarcel Telka rpcbproc_gettime_com(void *argp, ulong_t *result)
4408f6d9daeSMarcel Telka {
4418f6d9daeSMarcel Telka (void) time((time_t *)result);
4428f6d9daeSMarcel Telka
4438f6d9daeSMarcel Telka return (TRUE);
4447c478bd9Sstevel@tonic-gate }
4457c478bd9Sstevel@tonic-gate
4467c478bd9Sstevel@tonic-gate /*
4477c478bd9Sstevel@tonic-gate * Convert uaddr to taddr. Should be used only by
4487c478bd9Sstevel@tonic-gate * local servers/clients. (kernel level stuff only)
4497c478bd9Sstevel@tonic-gate */
4508f6d9daeSMarcel Telka bool_t
rpcbproc_uaddr2taddr_com(char ** uaddrp,struct netbuf * result,struct svc_req * rqstp)4518f6d9daeSMarcel Telka rpcbproc_uaddr2taddr_com(char **uaddrp, struct netbuf *result,
4528f6d9daeSMarcel Telka struct svc_req *rqstp)
4537c478bd9Sstevel@tonic-gate {
4547c478bd9Sstevel@tonic-gate struct netconfig *nconf;
4558f6d9daeSMarcel Telka struct netbuf *taddr;
4567c478bd9Sstevel@tonic-gate
4578f6d9daeSMarcel Telka if (((nconf = rpcbind_get_conf(rqstp->rq_xprt->xp_netid)) == NULL) ||
4587c478bd9Sstevel@tonic-gate ((taddr = uaddr2taddr(nconf, *uaddrp)) == NULL)) {
4598f6d9daeSMarcel Telka (void) memset(result, 0, sizeof (*result));
4608f6d9daeSMarcel Telka return (TRUE);
4617c478bd9Sstevel@tonic-gate }
4628f6d9daeSMarcel Telka
4638f6d9daeSMarcel Telka memcpy(result, taddr, sizeof (*result));
4648f6d9daeSMarcel Telka free(taddr);
4658f6d9daeSMarcel Telka
4668f6d9daeSMarcel Telka return (TRUE);
4677c478bd9Sstevel@tonic-gate }
4687c478bd9Sstevel@tonic-gate
4697c478bd9Sstevel@tonic-gate /*
4707c478bd9Sstevel@tonic-gate * Convert taddr to uaddr. Should be used only by
4717c478bd9Sstevel@tonic-gate * local servers/clients. (kernel level stuff only)
4727c478bd9Sstevel@tonic-gate */
4738f6d9daeSMarcel Telka bool_t
rpcbproc_taddr2uaddr_com(struct netbuf * taddr,char ** result,struct svc_req * rqstp)4748f6d9daeSMarcel Telka rpcbproc_taddr2uaddr_com(struct netbuf *taddr, char **result,
4758f6d9daeSMarcel Telka struct svc_req *rqstp)
4767c478bd9Sstevel@tonic-gate {
4777c478bd9Sstevel@tonic-gate struct netconfig *nconf;
4787c478bd9Sstevel@tonic-gate
4798f6d9daeSMarcel Telka if ((nconf = rpcbind_get_conf(rqstp->rq_xprt->xp_netid)) == NULL)
4808f6d9daeSMarcel Telka *result = NULL;
4818f6d9daeSMarcel Telka else
4828f6d9daeSMarcel Telka *result = taddr2uaddr(nconf, taddr);
4837c478bd9Sstevel@tonic-gate
4848f6d9daeSMarcel Telka return (TRUE);
4857c478bd9Sstevel@tonic-gate }
4867c478bd9Sstevel@tonic-gate
4877c478bd9Sstevel@tonic-gate /*
4887c478bd9Sstevel@tonic-gate * Stuff for the rmtcall service
4897c478bd9Sstevel@tonic-gate */
4908f6d9daeSMarcel Telka bool_t
xdr_rpcb_rmtcallargs(XDR * xdrs,rpcb_rmtcallargs * objp)4918f6d9daeSMarcel Telka xdr_rpcb_rmtcallargs(XDR *xdrs, rpcb_rmtcallargs *objp)
4927c478bd9Sstevel@tonic-gate {
4938f6d9daeSMarcel Telka if (!xdr_u_long(xdrs, &objp->prog))
4947c478bd9Sstevel@tonic-gate return (FALSE);
4958f6d9daeSMarcel Telka if (!xdr_u_long(xdrs, &objp->vers))
4968f6d9daeSMarcel Telka return (FALSE);
4978f6d9daeSMarcel Telka if (!xdr_u_long(xdrs, &objp->proc))
4988f6d9daeSMarcel Telka return (FALSE);
4998f6d9daeSMarcel Telka if (!xdr_bytes(xdrs, (char **)&objp->args.args_val,
5008f6d9daeSMarcel Telka (uint_t *)&objp->args.args_len, ~0))
5018f6d9daeSMarcel Telka return (FALSE);
5028f6d9daeSMarcel Telka return (TRUE);
5037c478bd9Sstevel@tonic-gate }
5047c478bd9Sstevel@tonic-gate
5057c478bd9Sstevel@tonic-gate #ifdef PORTMAP
5068f6d9daeSMarcel Telka bool_t
xdr_rmtcallres(XDR * xdrs,rmtcallres * objp)5078f6d9daeSMarcel Telka xdr_rmtcallres(XDR *xdrs, rmtcallres *objp)
5087c478bd9Sstevel@tonic-gate {
5098f6d9daeSMarcel Telka if (!xdr_u_long(xdrs, &objp->port))
5108f6d9daeSMarcel Telka return (FALSE);
5118f6d9daeSMarcel Telka if (!xdr_bytes(xdrs, (char **)&objp->res.res_val,
5128f6d9daeSMarcel Telka (uint_t *)&objp->res.res_len, ~0))
5138f6d9daeSMarcel Telka return (FALSE);
5148f6d9daeSMarcel Telka return (TRUE);
5158f6d9daeSMarcel Telka }
5168f6d9daeSMarcel Telka #endif
5178f6d9daeSMarcel Telka
5188f6d9daeSMarcel Telka bool_t
xdr_rpcb_rmtcallres(XDR * xdrs,rpcb_rmtcallres * objp)5198f6d9daeSMarcel Telka xdr_rpcb_rmtcallres(XDR *xdrs, rpcb_rmtcallres *objp)
5208f6d9daeSMarcel Telka {
5218f6d9daeSMarcel Telka if (!xdr_string(xdrs, &objp->addr, ~0))
5228f6d9daeSMarcel Telka return (FALSE);
5238f6d9daeSMarcel Telka if (!xdr_bytes(xdrs, (char **)&objp->results.results_val,
5248f6d9daeSMarcel Telka (uint_t *)&objp->results.results_len, ~0))
5258f6d9daeSMarcel Telka return (FALSE);
5268f6d9daeSMarcel Telka return (TRUE);
5277c478bd9Sstevel@tonic-gate }
5287c478bd9Sstevel@tonic-gate
5297c478bd9Sstevel@tonic-gate struct rmtcallfd_list {
5307c478bd9Sstevel@tonic-gate int fd;
5317c478bd9Sstevel@tonic-gate char *netid;
5327c478bd9Sstevel@tonic-gate struct rmtcallfd_list *next;
5337c478bd9Sstevel@tonic-gate };
5347c478bd9Sstevel@tonic-gate
5357c478bd9Sstevel@tonic-gate static struct rmtcallfd_list *rmthead;
5367c478bd9Sstevel@tonic-gate static struct rmtcallfd_list *rmttail;
5377c478bd9Sstevel@tonic-gate
5388f6d9daeSMarcel Telka #define MASKVAL (POLLIN | POLLPRI | POLLRDNORM | POLLRDBAND)
5398f6d9daeSMarcel Telka
5407c478bd9Sstevel@tonic-gate int
create_rmtcall_fd(struct netconfig * nconf)5418f6d9daeSMarcel Telka create_rmtcall_fd(struct netconfig *nconf)
5427c478bd9Sstevel@tonic-gate {
5437c478bd9Sstevel@tonic-gate int fd;
5447c478bd9Sstevel@tonic-gate struct rmtcallfd_list *rmt;
5457c478bd9Sstevel@tonic-gate
5467c478bd9Sstevel@tonic-gate if ((fd = t_open(nconf->nc_device, O_RDWR, NULL)) == -1) {
5477c478bd9Sstevel@tonic-gate if (debugging)
5488f6d9daeSMarcel Telka fprintf(stderr, "create_rmtcall_fd: couldn't open "
5498f6d9daeSMarcel Telka "\"%s\" (errno %d, t_errno %d)\n",
5507c478bd9Sstevel@tonic-gate nconf->nc_device, errno, t_errno);
5517c478bd9Sstevel@tonic-gate return (-1);
5527c478bd9Sstevel@tonic-gate }
5538f6d9daeSMarcel Telka
5548f6d9daeSMarcel Telka if (t_bind(fd, NULL, NULL) == -1) {
5557c478bd9Sstevel@tonic-gate if (debugging)
5568f6d9daeSMarcel Telka fprintf(stderr, "create_rmtcall_fd: couldn't bind to "
5578f6d9daeSMarcel Telka "fd for \"%s\" (errno %d, t_errno %d)\n",
5587c478bd9Sstevel@tonic-gate nconf->nc_device, errno, t_errno);
5597c478bd9Sstevel@tonic-gate return (-1);
5607c478bd9Sstevel@tonic-gate }
5618f6d9daeSMarcel Telka
5628f6d9daeSMarcel Telka rmt = malloc(sizeof (struct rmtcallfd_list));
5637c478bd9Sstevel@tonic-gate if (rmt == NULL) {
5647c478bd9Sstevel@tonic-gate syslog(LOG_ERR, "create_rmtcall_fd: no memory!");
5657c478bd9Sstevel@tonic-gate return (-1);
5667c478bd9Sstevel@tonic-gate }
5678f6d9daeSMarcel Telka
5687c478bd9Sstevel@tonic-gate rmt->netid = strdup(nconf->nc_netid);
5698f6d9daeSMarcel Telka if (rmt->netid == NULL) {
5708f6d9daeSMarcel Telka free(rmt);
5718f6d9daeSMarcel Telka syslog(LOG_ERR, "create_rmtcall_fd: no memory!");
5728f6d9daeSMarcel Telka return (-1);
5738f6d9daeSMarcel Telka }
5748f6d9daeSMarcel Telka
5758f6d9daeSMarcel Telka if (svc_add_input(fd, MASKVAL, handle_reply, rmt->netid) == -1) {
5768f6d9daeSMarcel Telka free(rmt->netid);
5778f6d9daeSMarcel Telka free(rmt);
5788f6d9daeSMarcel Telka syslog(LOG_ERR, "create_rmtcall_fd: svc_add_input() failed!");
5798f6d9daeSMarcel Telka return (-1);
5808f6d9daeSMarcel Telka }
5818f6d9daeSMarcel Telka
5827c478bd9Sstevel@tonic-gate rmt->fd = fd;
5837c478bd9Sstevel@tonic-gate rmt->next = NULL;
5847c478bd9Sstevel@tonic-gate if (rmthead == NULL) {
5857c478bd9Sstevel@tonic-gate rmthead = rmt;
5867c478bd9Sstevel@tonic-gate rmttail = rmt;
5877c478bd9Sstevel@tonic-gate } else {
5887c478bd9Sstevel@tonic-gate rmttail->next = rmt;
5897c478bd9Sstevel@tonic-gate rmttail = rmt;
5907c478bd9Sstevel@tonic-gate }
5918f6d9daeSMarcel Telka
5927c478bd9Sstevel@tonic-gate return (fd);
5937c478bd9Sstevel@tonic-gate }
5947c478bd9Sstevel@tonic-gate
5957c478bd9Sstevel@tonic-gate static int
find_rmtcallfd_by_netid(char * netid)5968f6d9daeSMarcel Telka find_rmtcallfd_by_netid(char *netid)
5977c478bd9Sstevel@tonic-gate {
5987c478bd9Sstevel@tonic-gate struct rmtcallfd_list *rmt;
5997c478bd9Sstevel@tonic-gate
6007c478bd9Sstevel@tonic-gate for (rmt = rmthead; rmt != NULL; rmt = rmt->next) {
6017c478bd9Sstevel@tonic-gate if (strcmp(netid, rmt->netid) == 0) {
6027c478bd9Sstevel@tonic-gate return (rmt->fd);
6037c478bd9Sstevel@tonic-gate }
6047c478bd9Sstevel@tonic-gate }
6057c478bd9Sstevel@tonic-gate return (-1);
6067c478bd9Sstevel@tonic-gate }
6077c478bd9Sstevel@tonic-gate
6088f6d9daeSMarcel Telka #define MAXTIME_OFF 300 /* 5 minutes timeout for rmtcalls */
6098f6d9daeSMarcel Telka
6108f6d9daeSMarcel Telka struct finfo {
6118f6d9daeSMarcel Telka struct finfo *prev;
6128f6d9daeSMarcel Telka struct finfo *next;
6138f6d9daeSMarcel Telka int flag;
6148f6d9daeSMarcel Telka #define FINFO_ACTIVE 0x1
6158f6d9daeSMarcel Telka ulong_t caller_xid;
6168f6d9daeSMarcel Telka struct netbuf *caller_addr;
6178f6d9daeSMarcel Telka ulong_t forward_xid;
6188f6d9daeSMarcel Telka int forward_fd;
6198f6d9daeSMarcel Telka char *uaddr;
6208f6d9daeSMarcel Telka struct t_unitdata *reply_data;
6218f6d9daeSMarcel Telka struct rpc_err reply_error;
6228f6d9daeSMarcel Telka uint_t res_len;
6238f6d9daeSMarcel Telka void *res_val;
6248f6d9daeSMarcel Telka cond_t cv;
6258f6d9daeSMarcel Telka };
6268f6d9daeSMarcel Telka
6278f6d9daeSMarcel Telka /*
6288f6d9daeSMarcel Telka * finfo_lock protects rpcb_rmtcalls, rpcb_rmtcalls_max, lastxid,
6298f6d9daeSMarcel Telka * fihead, and fitail.
6308f6d9daeSMarcel Telka */
6318f6d9daeSMarcel Telka static mutex_t finfo_lock = DEFAULTMUTEX;
6328f6d9daeSMarcel Telka
6338f6d9daeSMarcel Telka static int rpcb_rmtcalls;
6348f6d9daeSMarcel Telka static int rpcb_rmtcalls_max;
6358f6d9daeSMarcel Telka static ulong_t lastxid;
6368f6d9daeSMarcel Telka static struct finfo *fihead;
6378f6d9daeSMarcel Telka static struct finfo *fitail;
6388f6d9daeSMarcel Telka
6398f6d9daeSMarcel Telka void
set_rpcb_rmtcalls_max(int max)6408f6d9daeSMarcel Telka set_rpcb_rmtcalls_max(int max)
6417c478bd9Sstevel@tonic-gate {
6428f6d9daeSMarcel Telka (void) mutex_lock(&finfo_lock);
6438f6d9daeSMarcel Telka rpcb_rmtcalls_max = max;
6448f6d9daeSMarcel Telka if (rpcb_rmtcalls > rpcb_rmtcalls_max) {
6458f6d9daeSMarcel Telka assert(fitail != NULL);
6468f6d9daeSMarcel Telka (void) cond_signal(&fitail->cv);
6477c478bd9Sstevel@tonic-gate }
6488f6d9daeSMarcel Telka (void) mutex_unlock(&finfo_lock);
6497c478bd9Sstevel@tonic-gate }
6507c478bd9Sstevel@tonic-gate
6517c478bd9Sstevel@tonic-gate /*
6527c478bd9Sstevel@tonic-gate * Call a remote procedure service. This procedure is very quiet when things
6537c478bd9Sstevel@tonic-gate * go wrong. The proc is written to support broadcast rpc. In the broadcast
6547c478bd9Sstevel@tonic-gate * case, a machine should shut-up instead of complain, lest the requestor be
6557c478bd9Sstevel@tonic-gate * overrun with complaints at the expense of not hearing a valid reply.
6567c478bd9Sstevel@tonic-gate * When receiving a request and verifying that the service exists, we
6577c478bd9Sstevel@tonic-gate *
6587c478bd9Sstevel@tonic-gate * receive the request
6597c478bd9Sstevel@tonic-gate *
6607c478bd9Sstevel@tonic-gate * open a new TLI endpoint on the same transport on which we received
6617c478bd9Sstevel@tonic-gate * the original request
6627c478bd9Sstevel@tonic-gate *
6637c478bd9Sstevel@tonic-gate * remember the original request's XID (which requires knowing the format
6647c478bd9Sstevel@tonic-gate * of the svc_dg_data structure)
6657c478bd9Sstevel@tonic-gate *
6667c478bd9Sstevel@tonic-gate * forward the request, with a new XID, to the requested service,
6677c478bd9Sstevel@tonic-gate * remembering the XID used to send this request (for later use in
6687c478bd9Sstevel@tonic-gate * reassociating the answer with the original request), the requestor's
6697c478bd9Sstevel@tonic-gate * address, the file descriptor on which the forwarded request is
6708f6d9daeSMarcel Telka * made and the service's address
6717c478bd9Sstevel@tonic-gate *
6728f6d9daeSMarcel Telka * wait for either the timeout or the condition variable is signalled from
6738f6d9daeSMarcel Telka * handle_reply().
6747c478bd9Sstevel@tonic-gate *
6757c478bd9Sstevel@tonic-gate * At some time in the future, a reply will be received from the service to
6768f6d9daeSMarcel Telka * which we forwarded the request. At that time, svc_run() detect that the
6778f6d9daeSMarcel Telka * socket used was for forwarding and call handle_reply() to
6787c478bd9Sstevel@tonic-gate *
6797c478bd9Sstevel@tonic-gate * receive the reply
6807c478bd9Sstevel@tonic-gate *
6817c478bd9Sstevel@tonic-gate * bundle the reply, along with the service's universal address
6827c478bd9Sstevel@tonic-gate *
6838f6d9daeSMarcel Telka * put the reply into the particular finfo
6848f6d9daeSMarcel Telka *
6858f6d9daeSMarcel Telka * signal the condition variable.
6867c478bd9Sstevel@tonic-gate */
6877c478bd9Sstevel@tonic-gate
6887c478bd9Sstevel@tonic-gate #define RPC_BUF_MAX 65536 /* can be raised if required */
6897c478bd9Sstevel@tonic-gate
6907c478bd9Sstevel@tonic-gate /*
6917c478bd9Sstevel@tonic-gate * This is from ../ypcmd/yp_b.h
6927c478bd9Sstevel@tonic-gate * It does not appear in <rpcsvc/yp_prot.h>
6937c478bd9Sstevel@tonic-gate */
6947c478bd9Sstevel@tonic-gate #define YPBINDPROG ((ulong_t)100007)
6957c478bd9Sstevel@tonic-gate #define YPBINDPROC_SETDOM ((ulong_t)2)
6967c478bd9Sstevel@tonic-gate
6978f6d9daeSMarcel Telka /*
6988f6d9daeSMarcel Telka * reply_type - which proc number
6998f6d9daeSMarcel Telka * versnum - which vers was called
7008f6d9daeSMarcel Telka */
7017c478bd9Sstevel@tonic-gate void
rpcbproc_callit_com(struct svc_req * rqstp,SVCXPRT * transp,ulong_t reply_type,int versnum)7028f6d9daeSMarcel Telka rpcbproc_callit_com(struct svc_req *rqstp, SVCXPRT *transp, ulong_t reply_type,
7038f6d9daeSMarcel Telka int versnum)
7047c478bd9Sstevel@tonic-gate {
7058f6d9daeSMarcel Telka struct t_info tinfo;
7068f6d9daeSMarcel Telka uint_t sendsz;
7078f6d9daeSMarcel Telka
7088f6d9daeSMarcel Telka rpcb_rmtcallargs arg;
7098f6d9daeSMarcel Telka rpcblist_ptr rbl;
7108f6d9daeSMarcel Telka
7117c478bd9Sstevel@tonic-gate struct netconfig *nconf;
7127c478bd9Sstevel@tonic-gate struct netbuf *caller;
7137c478bd9Sstevel@tonic-gate struct nd_mergearg ma;
7147c478bd9Sstevel@tonic-gate int stat;
7157c478bd9Sstevel@tonic-gate
7168f6d9daeSMarcel Telka int fd;
7178f6d9daeSMarcel Telka struct svc_dg_data *bd;
7188f6d9daeSMarcel Telka struct finfo *fi;
7198f6d9daeSMarcel Telka
7208f6d9daeSMarcel Telka struct rpc_msg call_msg;
7218f6d9daeSMarcel Telka char outbuf[RPC_BUF_MAX];
7228f6d9daeSMarcel Telka char *outbuf_alloc = NULL;
7238f6d9daeSMarcel Telka XDR outxdr;
7248f6d9daeSMarcel Telka bool_t outxdr_created = FALSE;
7258f6d9daeSMarcel Telka
7268f6d9daeSMarcel Telka AUTH *auth;
7278f6d9daeSMarcel Telka
7288f6d9daeSMarcel Telka struct t_unitdata tu_data;
7298f6d9daeSMarcel Telka struct netbuf *na;
7308f6d9daeSMarcel Telka
7318f6d9daeSMarcel Telka timestruc_t to;
7328f6d9daeSMarcel Telka
7338f6d9daeSMarcel Telka (void) mutex_lock(&finfo_lock);
7348f6d9daeSMarcel Telka if (!allow_indirect || rpcb_rmtcalls_max == 0) {
7358f6d9daeSMarcel Telka (void) mutex_unlock(&finfo_lock);
7368f6d9daeSMarcel Telka return;
7378f6d9daeSMarcel Telka }
7388f6d9daeSMarcel Telka (void) mutex_unlock(&finfo_lock);
7398f6d9daeSMarcel Telka
7407c478bd9Sstevel@tonic-gate if (t_getinfo(transp->xp_fd, &tinfo) == -1) {
7417c478bd9Sstevel@tonic-gate if (reply_type == RPCBPROC_INDIRECT)
7427c478bd9Sstevel@tonic-gate svcerr_systemerr(transp);
7437c478bd9Sstevel@tonic-gate return;
7447c478bd9Sstevel@tonic-gate }
7457c478bd9Sstevel@tonic-gate if (tinfo.servtype != T_CLTS)
7467c478bd9Sstevel@tonic-gate return; /* Only datagram type accepted */
7478f6d9daeSMarcel Telka
7487c478bd9Sstevel@tonic-gate sendsz = __rpc_get_t_size(0, tinfo.tsdu);
7497c478bd9Sstevel@tonic-gate if (sendsz == 0) { /* data transfer not supported */
7507c478bd9Sstevel@tonic-gate if (reply_type == RPCBPROC_INDIRECT)
7517c478bd9Sstevel@tonic-gate svcerr_systemerr(transp);
7527c478bd9Sstevel@tonic-gate return;
7537c478bd9Sstevel@tonic-gate }
7547c478bd9Sstevel@tonic-gate /*
7557c478bd9Sstevel@tonic-gate * Should be multiple of 4 for XDR.
7567c478bd9Sstevel@tonic-gate */
7577c478bd9Sstevel@tonic-gate sendsz = ((sendsz + 3) / 4) * 4;
7587c478bd9Sstevel@tonic-gate
7598f6d9daeSMarcel Telka (void) memset((char *)&arg, 0, sizeof (arg));
7608f6d9daeSMarcel Telka if (!svc_getargs(transp, xdr_rpcb_rmtcallargs, (char *)&arg)) {
7617c478bd9Sstevel@tonic-gate if (reply_type == RPCBPROC_INDIRECT)
7627c478bd9Sstevel@tonic-gate svcerr_decode(transp);
7637c478bd9Sstevel@tonic-gate if (debugging)
7647c478bd9Sstevel@tonic-gate fprintf(stderr,
7657c478bd9Sstevel@tonic-gate "rpcbproc_callit_com: svc_getargs failed\n");
7667c478bd9Sstevel@tonic-gate goto error;
7677c478bd9Sstevel@tonic-gate }
7687c478bd9Sstevel@tonic-gate
7697c478bd9Sstevel@tonic-gate /*
7707c478bd9Sstevel@tonic-gate * Disallow calling rpcbind for certain procedures.
7717c478bd9Sstevel@tonic-gate * Allow calling NULLPROC - per man page on rpcb_rmtcall().
7727c478bd9Sstevel@tonic-gate * switch is in alphabetical order.
7737c478bd9Sstevel@tonic-gate */
7748f6d9daeSMarcel Telka if (arg.proc != NULLPROC) {
7758f6d9daeSMarcel Telka switch (arg.prog) {
7767c478bd9Sstevel@tonic-gate case KEY_PROG:
7777c478bd9Sstevel@tonic-gate if (debugging)
7787c478bd9Sstevel@tonic-gate fprintf(stderr,
7797c478bd9Sstevel@tonic-gate "rpcbind: rejecting KEY_PROG(%d)\n",
7808f6d9daeSMarcel Telka arg.proc);
7817c478bd9Sstevel@tonic-gate goto error;
7827c478bd9Sstevel@tonic-gate case MOUNTPROG:
7838f6d9daeSMarcel Telka if (arg.proc != MOUNTPROC_MNT)
7847c478bd9Sstevel@tonic-gate break;
7857c478bd9Sstevel@tonic-gate /*
7867c478bd9Sstevel@tonic-gate * In Solaris 2.6, the host-based accesss control
7877c478bd9Sstevel@tonic-gate * is done by the NFS server on each request.
7887c478bd9Sstevel@tonic-gate * Prior to 2.6 we rely on mountd.
7897c478bd9Sstevel@tonic-gate */
7907c478bd9Sstevel@tonic-gate if (debugging)
7917c478bd9Sstevel@tonic-gate fprintf(stderr,
7927c478bd9Sstevel@tonic-gate "rpcbind: rejecting MOUNTPROG(%d)\n",
7938f6d9daeSMarcel Telka arg.proc);
7947c478bd9Sstevel@tonic-gate goto error;
7957c478bd9Sstevel@tonic-gate case NFS_ACL_PROGRAM:
7967c478bd9Sstevel@tonic-gate if (debugging)
7977c478bd9Sstevel@tonic-gate fprintf(stderr,
7987c478bd9Sstevel@tonic-gate "rpcbind: rejecting NFS_ACL_PROGRAM(%d)\n",
7998f6d9daeSMarcel Telka arg.proc);
8007c478bd9Sstevel@tonic-gate goto error;
8017c478bd9Sstevel@tonic-gate case NFS_PROGRAM:
8027c478bd9Sstevel@tonic-gate /* also NFS3_PROGRAM */
8037c478bd9Sstevel@tonic-gate if (debugging)
8047c478bd9Sstevel@tonic-gate fprintf(stderr,
8057c478bd9Sstevel@tonic-gate "rpcbind: rejecting NFS_PROGRAM(%d)\n",
8068f6d9daeSMarcel Telka arg.proc);
8077c478bd9Sstevel@tonic-gate goto error;
8087c478bd9Sstevel@tonic-gate case RPCBPROG:
8097c478bd9Sstevel@tonic-gate /*
8107c478bd9Sstevel@tonic-gate * Disallow calling rpcbind for certain procedures.
8117c478bd9Sstevel@tonic-gate * Luckily Portmap set/unset/callit also have same
8127c478bd9Sstevel@tonic-gate * procedure numbers. So, will not check for those.
8137c478bd9Sstevel@tonic-gate */
8148f6d9daeSMarcel Telka switch (arg.proc) {
8157c478bd9Sstevel@tonic-gate case RPCBPROC_SET:
8167c478bd9Sstevel@tonic-gate case RPCBPROC_UNSET:
8177c478bd9Sstevel@tonic-gate case RPCBPROC_CALLIT:
8187c478bd9Sstevel@tonic-gate case RPCBPROC_INDIRECT:
8197c478bd9Sstevel@tonic-gate if (reply_type == RPCBPROC_INDIRECT)
8207c478bd9Sstevel@tonic-gate svcerr_weakauth(transp); /* XXX */
8217c478bd9Sstevel@tonic-gate if (debugging)
8228f6d9daeSMarcel Telka fprintf(stderr, "rpcbproc_callit_com: "
8238f6d9daeSMarcel Telka "calling RPCBPROG procs SET, "
8248f6d9daeSMarcel Telka "UNSET, CALLIT, or INDIRECT not "
8258f6d9daeSMarcel Telka "allowed\n");
8267c478bd9Sstevel@tonic-gate goto error;
8277c478bd9Sstevel@tonic-gate default:
8287c478bd9Sstevel@tonic-gate /*
8297c478bd9Sstevel@tonic-gate * Ideally, we should have called rpcb_service()
8307c478bd9Sstevel@tonic-gate * or pmap_service() with appropriate parameters
8317c478bd9Sstevel@tonic-gate * instead of going about in a roundabout
8327c478bd9Sstevel@tonic-gate * manner. Hopefully, this case should happen
8337c478bd9Sstevel@tonic-gate * rarely.
8347c478bd9Sstevel@tonic-gate */
8357c478bd9Sstevel@tonic-gate break;
8367c478bd9Sstevel@tonic-gate }
8377c478bd9Sstevel@tonic-gate break;
8387c478bd9Sstevel@tonic-gate case RQUOTAPROG:
8397c478bd9Sstevel@tonic-gate if (debugging)
8407c478bd9Sstevel@tonic-gate fprintf(stderr,
8417c478bd9Sstevel@tonic-gate "rpcbind: rejecting RQUOTAPROG(%d)\n",
8428f6d9daeSMarcel Telka arg.proc);
8437c478bd9Sstevel@tonic-gate goto error;
8447c478bd9Sstevel@tonic-gate case YPPASSWDPROG:
8457c478bd9Sstevel@tonic-gate if (debugging)
8467c478bd9Sstevel@tonic-gate fprintf(stderr,
8477c478bd9Sstevel@tonic-gate "rpcbind: rejecting YPPASSWDPROG(%d)\n",
8488f6d9daeSMarcel Telka arg.proc);
8497c478bd9Sstevel@tonic-gate goto error;
8507c478bd9Sstevel@tonic-gate case YPU_PROG:
8517c478bd9Sstevel@tonic-gate if (debugging)
8527c478bd9Sstevel@tonic-gate fprintf(stderr,
8537c478bd9Sstevel@tonic-gate "rpcbind: rejecting YPU_PROG(%d)\n",
8548f6d9daeSMarcel Telka arg.proc);
8557c478bd9Sstevel@tonic-gate goto error;
8567c478bd9Sstevel@tonic-gate case YPBINDPROG:
8578f6d9daeSMarcel Telka if (arg.proc != YPBINDPROC_SETDOM)
8587c478bd9Sstevel@tonic-gate break;
8597c478bd9Sstevel@tonic-gate if (debugging)
8607c478bd9Sstevel@tonic-gate fprintf(stderr,
8617c478bd9Sstevel@tonic-gate "rpcbind: rejecting YPBINDPROG(%d)\n",
8628f6d9daeSMarcel Telka arg.proc);
8637c478bd9Sstevel@tonic-gate goto error;
8647c478bd9Sstevel@tonic-gate case YPPROG:
8658f6d9daeSMarcel Telka switch (arg.proc) {
8667c478bd9Sstevel@tonic-gate case YPPROC_FIRST:
8677c478bd9Sstevel@tonic-gate case YPPROC_NEXT:
8687c478bd9Sstevel@tonic-gate case YPPROC_MATCH:
8697c478bd9Sstevel@tonic-gate case YPPROC_ALL:
8707c478bd9Sstevel@tonic-gate if (debugging)
8717c478bd9Sstevel@tonic-gate fprintf(stderr,
8727c478bd9Sstevel@tonic-gate "rpcbind: rejecting YPPROG(%d)\n",
8738f6d9daeSMarcel Telka arg.proc);
8747c478bd9Sstevel@tonic-gate goto error;
8757c478bd9Sstevel@tonic-gate default:
8767c478bd9Sstevel@tonic-gate break;
8777c478bd9Sstevel@tonic-gate }
8787c478bd9Sstevel@tonic-gate break;
8797c478bd9Sstevel@tonic-gate default:
8807c478bd9Sstevel@tonic-gate break;
8817c478bd9Sstevel@tonic-gate }
8827c478bd9Sstevel@tonic-gate }
8837c478bd9Sstevel@tonic-gate
8848f6d9daeSMarcel Telka (void) rw_rdlock(&list_rbl_lock);
8858f6d9daeSMarcel Telka rbl = find_service(arg.prog, arg.vers, transp->xp_netid);
8867c478bd9Sstevel@tonic-gate
8878f6d9daeSMarcel Telka rpcbs_rmtcall(versnum - PMAPVERS, reply_type, arg.prog, arg.vers,
8888f6d9daeSMarcel Telka arg.proc, transp->xp_netid, rbl);
8897c478bd9Sstevel@tonic-gate
8908f6d9daeSMarcel Telka if (rbl == NULL) {
8918f6d9daeSMarcel Telka (void) rw_unlock(&list_rbl_lock);
8927c478bd9Sstevel@tonic-gate if (reply_type == RPCBPROC_INDIRECT)
8937c478bd9Sstevel@tonic-gate svcerr_noprog(transp);
8947c478bd9Sstevel@tonic-gate goto error;
8957c478bd9Sstevel@tonic-gate }
8968f6d9daeSMarcel Telka if (rbl->rpcb_map.r_vers != arg.vers) {
8977c478bd9Sstevel@tonic-gate if (reply_type == RPCBPROC_INDIRECT) {
8987c478bd9Sstevel@tonic-gate ulong_t vers_low, vers_high;
8997c478bd9Sstevel@tonic-gate
9008f6d9daeSMarcel Telka find_versions(arg.prog, transp->xp_netid,
9017c478bd9Sstevel@tonic-gate &vers_low, &vers_high);
9028f6d9daeSMarcel Telka (void) rw_unlock(&list_rbl_lock);
9037c478bd9Sstevel@tonic-gate svcerr_progvers(transp, vers_low, vers_high);
9048f6d9daeSMarcel Telka } else {
9058f6d9daeSMarcel Telka (void) rw_unlock(&list_rbl_lock);
9067c478bd9Sstevel@tonic-gate }
9077c478bd9Sstevel@tonic-gate goto error;
9087c478bd9Sstevel@tonic-gate }
9097c478bd9Sstevel@tonic-gate
9107c478bd9Sstevel@tonic-gate /*
9117c478bd9Sstevel@tonic-gate * Check whether this entry is valid and a server is present
9127c478bd9Sstevel@tonic-gate * Mergeaddr() returns NULL if no such entry is present, and
9137c478bd9Sstevel@tonic-gate * returns "" if the entry was present but the server is not
9147c478bd9Sstevel@tonic-gate * present (i.e., it crashed).
9157c478bd9Sstevel@tonic-gate */
9167c478bd9Sstevel@tonic-gate if (reply_type == RPCBPROC_INDIRECT) {
9178f6d9daeSMarcel Telka char *uaddr = mergeaddr(transp, transp->xp_netid,
9187c478bd9Sstevel@tonic-gate rbl->rpcb_map.r_addr, NULL);
9197c478bd9Sstevel@tonic-gate if ((uaddr == (char *)NULL) || uaddr[0] == '\0') {
9208f6d9daeSMarcel Telka (void) rw_unlock(&list_rbl_lock);
9217c478bd9Sstevel@tonic-gate svcerr_noprog(transp);
9227c478bd9Sstevel@tonic-gate goto error;
9237c478bd9Sstevel@tonic-gate } else {
9248f6d9daeSMarcel Telka free(uaddr);
9257c478bd9Sstevel@tonic-gate }
9267c478bd9Sstevel@tonic-gate }
9278f6d9daeSMarcel Telka
9287c478bd9Sstevel@tonic-gate nconf = rpcbind_get_conf(transp->xp_netid);
9298f6d9daeSMarcel Telka if (nconf == NULL) {
9308f6d9daeSMarcel Telka (void) rw_unlock(&list_rbl_lock);
9317c478bd9Sstevel@tonic-gate if (reply_type == RPCBPROC_INDIRECT)
9327c478bd9Sstevel@tonic-gate svcerr_systemerr(transp);
9337c478bd9Sstevel@tonic-gate if (debugging)
9347c478bd9Sstevel@tonic-gate fprintf(stderr,
9357c478bd9Sstevel@tonic-gate "rpcbproc_callit_com: rpcbind_get_conf failed\n");
9367c478bd9Sstevel@tonic-gate goto error;
9377c478bd9Sstevel@tonic-gate }
9388f6d9daeSMarcel Telka
9398f6d9daeSMarcel Telka caller = svc_getrpccaller(transp);
9407c478bd9Sstevel@tonic-gate ma.c_uaddr = taddr2uaddr(nconf, caller);
9417c478bd9Sstevel@tonic-gate ma.s_uaddr = rbl->rpcb_map.r_addr;
9428f6d9daeSMarcel Telka
9437c478bd9Sstevel@tonic-gate /*
9447c478bd9Sstevel@tonic-gate * A mergeaddr operation allocates a string, which it stores in
9457c478bd9Sstevel@tonic-gate * ma.m_uaddr. It's passed to forward_register() and is
9468f6d9daeSMarcel Telka * eventually freed by forward_destroy().
9477c478bd9Sstevel@tonic-gate */
9487c478bd9Sstevel@tonic-gate stat = netdir_options(nconf, ND_MERGEADDR, 0, (char *)&ma);
9498f6d9daeSMarcel Telka (void) rw_unlock(&list_rbl_lock);
9508f6d9daeSMarcel Telka free(ma.c_uaddr);
9517c478bd9Sstevel@tonic-gate if (stat)
9527c478bd9Sstevel@tonic-gate (void) syslog(LOG_ERR, "netdir_merge failed for %s: %s",
9537c478bd9Sstevel@tonic-gate nconf->nc_netid, netdir_sperror());
9548f6d9daeSMarcel Telka
9557c478bd9Sstevel@tonic-gate if ((fd = find_rmtcallfd_by_netid(nconf->nc_netid)) == -1) {
9567c478bd9Sstevel@tonic-gate if (reply_type == RPCBPROC_INDIRECT)
9577c478bd9Sstevel@tonic-gate svcerr_systemerr(transp);
9588f6d9daeSMarcel Telka free(ma.m_uaddr);
9597c478bd9Sstevel@tonic-gate goto error;
9607c478bd9Sstevel@tonic-gate }
9618f6d9daeSMarcel Telka
962f48205beScasper bd = get_svc_dg_data(transp);
9638f6d9daeSMarcel Telka
9648f6d9daeSMarcel Telka assert(!MUTEX_HELD(&finfo_lock));
9658f6d9daeSMarcel Telka fi = forward_register(bd->su_xid, caller, fd, ma.m_uaddr);
9668f6d9daeSMarcel Telka if (fi == NULL) {
9678f6d9daeSMarcel Telka /* forward_register failed. Perhaps no memory. */
9688f6d9daeSMarcel Telka free(ma.m_uaddr);
9698f6d9daeSMarcel Telka if (debugging)
9708f6d9daeSMarcel Telka fprintf(stderr,
9718f6d9daeSMarcel Telka "rpcbproc_callit_com: forward_register failed\n");
9728f6d9daeSMarcel Telka assert(!MUTEX_HELD(&finfo_lock));
9738f6d9daeSMarcel Telka goto error;
9748f6d9daeSMarcel Telka }
9758f6d9daeSMarcel Telka /* forward_register() returns with finfo_lock held when successful */
9768f6d9daeSMarcel Telka assert(MUTEX_HELD(&finfo_lock));
9778f6d9daeSMarcel Telka
9788f6d9daeSMarcel Telka if (fi->flag & FINFO_ACTIVE) {
9797c478bd9Sstevel@tonic-gate /*
9807c478bd9Sstevel@tonic-gate * A duplicate request for the slow server. Let's not
9817c478bd9Sstevel@tonic-gate * beat on it any more.
9827c478bd9Sstevel@tonic-gate */
9838f6d9daeSMarcel Telka (void) mutex_unlock(&finfo_lock);
9848f6d9daeSMarcel Telka free(ma.m_uaddr);
9857c478bd9Sstevel@tonic-gate if (debugging)
9867c478bd9Sstevel@tonic-gate fprintf(stderr,
9877c478bd9Sstevel@tonic-gate "rpcbproc_callit_com: duplicate request\n");
9887c478bd9Sstevel@tonic-gate goto error;
9897c478bd9Sstevel@tonic-gate }
9908f6d9daeSMarcel Telka fi->flag |= FINFO_ACTIVE;
9917c478bd9Sstevel@tonic-gate
9928f6d9daeSMarcel Telka call_msg.rm_xid = fi->forward_xid;
9937c478bd9Sstevel@tonic-gate call_msg.rm_direction = CALL;
9947c478bd9Sstevel@tonic-gate call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
9958f6d9daeSMarcel Telka call_msg.rm_call.cb_prog = arg.prog;
9968f6d9daeSMarcel Telka call_msg.rm_call.cb_vers = arg.vers;
9978f6d9daeSMarcel Telka
9987c478bd9Sstevel@tonic-gate if (sendsz > RPC_BUF_MAX) {
9997c478bd9Sstevel@tonic-gate outbuf_alloc = malloc(sendsz);
10007c478bd9Sstevel@tonic-gate if (outbuf_alloc == NULL) {
10018f6d9daeSMarcel Telka forward_destroy(fi);
10028f6d9daeSMarcel Telka (void) mutex_unlock(&finfo_lock);
10037c478bd9Sstevel@tonic-gate if (reply_type == RPCBPROC_INDIRECT)
10047c478bd9Sstevel@tonic-gate svcerr_systemerr(transp);
10057c478bd9Sstevel@tonic-gate if (debugging)
10067c478bd9Sstevel@tonic-gate fprintf(stderr,
10077c478bd9Sstevel@tonic-gate "rpcbproc_callit_com: No memory!\n");
10087c478bd9Sstevel@tonic-gate goto error;
10097c478bd9Sstevel@tonic-gate }
10107c478bd9Sstevel@tonic-gate xdrmem_create(&outxdr, outbuf_alloc, sendsz, XDR_ENCODE);
10117c478bd9Sstevel@tonic-gate } else {
10127c478bd9Sstevel@tonic-gate xdrmem_create(&outxdr, outbuf, sendsz, XDR_ENCODE);
10137c478bd9Sstevel@tonic-gate }
10148f6d9daeSMarcel Telka outxdr_created = TRUE;
10158f6d9daeSMarcel Telka
10167c478bd9Sstevel@tonic-gate if (!xdr_callhdr(&outxdr, &call_msg)) {
10178f6d9daeSMarcel Telka forward_destroy(fi);
10188f6d9daeSMarcel Telka (void) mutex_unlock(&finfo_lock);
10197c478bd9Sstevel@tonic-gate if (reply_type == RPCBPROC_INDIRECT)
10207c478bd9Sstevel@tonic-gate svcerr_systemerr(transp);
10217c478bd9Sstevel@tonic-gate if (debugging)
10227c478bd9Sstevel@tonic-gate fprintf(stderr,
10237c478bd9Sstevel@tonic-gate "rpcbproc_callit_com: xdr_callhdr failed\n");
10247c478bd9Sstevel@tonic-gate goto error;
10257c478bd9Sstevel@tonic-gate }
10268f6d9daeSMarcel Telka
10278f6d9daeSMarcel Telka if (!xdr_u_long(&outxdr, &arg.proc)) {
10288f6d9daeSMarcel Telka forward_destroy(fi);
10298f6d9daeSMarcel Telka (void) mutex_unlock(&finfo_lock);
10307c478bd9Sstevel@tonic-gate if (reply_type == RPCBPROC_INDIRECT)
10317c478bd9Sstevel@tonic-gate svcerr_systemerr(transp);
10327c478bd9Sstevel@tonic-gate if (debugging)
10337c478bd9Sstevel@tonic-gate fprintf(stderr,
10347c478bd9Sstevel@tonic-gate "rpcbproc_callit_com: xdr_u_long failed\n");
10357c478bd9Sstevel@tonic-gate goto error;
10367c478bd9Sstevel@tonic-gate }
10377c478bd9Sstevel@tonic-gate
10387c478bd9Sstevel@tonic-gate if (rqstp->rq_cred.oa_flavor == AUTH_NULL) {
10397c478bd9Sstevel@tonic-gate auth = authnone_create();
10407c478bd9Sstevel@tonic-gate } else if (rqstp->rq_cred.oa_flavor == AUTH_SYS) {
10417c478bd9Sstevel@tonic-gate struct authsys_parms *au;
10427c478bd9Sstevel@tonic-gate
1043*77b65ce6SAlex Wilson CTASSERT(sizeof (struct authsys_parms) <= RQCRED_SIZE);
10447c478bd9Sstevel@tonic-gate au = (struct authsys_parms *)rqstp->rq_clntcred;
10458f6d9daeSMarcel Telka auth = authsys_create(au->aup_machname, au->aup_uid,
10468f6d9daeSMarcel Telka au->aup_gid, au->aup_len, au->aup_gids);
10477c478bd9Sstevel@tonic-gate if (auth == NULL) /* fall back */
10487c478bd9Sstevel@tonic-gate auth = authnone_create();
10497c478bd9Sstevel@tonic-gate } else {
10507c478bd9Sstevel@tonic-gate /* we do not support any other authentication scheme */
10518f6d9daeSMarcel Telka forward_destroy(fi);
10528f6d9daeSMarcel Telka (void) mutex_unlock(&finfo_lock);
10537c478bd9Sstevel@tonic-gate if (reply_type == RPCBPROC_INDIRECT)
10547c478bd9Sstevel@tonic-gate svcerr_weakauth(transp); /* XXX too strong.. */
10558f6d9daeSMarcel Telka if (debugging)
10568f6d9daeSMarcel Telka fprintf(stderr, "rpcbproc_callit_com: oa_flavor != "
10578f6d9daeSMarcel Telka "AUTH_NONE and oa_flavor != AUTH_SYS\n");
10587c478bd9Sstevel@tonic-gate goto error;
10597c478bd9Sstevel@tonic-gate }
10607c478bd9Sstevel@tonic-gate if (auth == NULL) {
10618f6d9daeSMarcel Telka forward_destroy(fi);
10628f6d9daeSMarcel Telka (void) mutex_unlock(&finfo_lock);
10637c478bd9Sstevel@tonic-gate if (reply_type == RPCBPROC_INDIRECT)
10647c478bd9Sstevel@tonic-gate svcerr_systemerr(transp);
10657c478bd9Sstevel@tonic-gate if (debugging)
10668f6d9daeSMarcel Telka fprintf(stderr, "rpcbproc_callit_com: "
10678f6d9daeSMarcel Telka "authwhatever_create returned NULL\n");
10687c478bd9Sstevel@tonic-gate goto error;
10697c478bd9Sstevel@tonic-gate }
10707c478bd9Sstevel@tonic-gate if (!AUTH_MARSHALL(auth, &outxdr)) {
10718f6d9daeSMarcel Telka forward_destroy(fi);
10728f6d9daeSMarcel Telka (void) mutex_unlock(&finfo_lock);
10737c478bd9Sstevel@tonic-gate if (reply_type == RPCBPROC_INDIRECT)
10747c478bd9Sstevel@tonic-gate svcerr_systemerr(transp);
10757c478bd9Sstevel@tonic-gate AUTH_DESTROY(auth);
10767c478bd9Sstevel@tonic-gate if (debugging)
10777c478bd9Sstevel@tonic-gate fprintf(stderr,
10787c478bd9Sstevel@tonic-gate "rpcbproc_callit_com: AUTH_MARSHALL failed\n");
10797c478bd9Sstevel@tonic-gate goto error;
10807c478bd9Sstevel@tonic-gate }
10817c478bd9Sstevel@tonic-gate AUTH_DESTROY(auth);
10828f6d9daeSMarcel Telka
10838f6d9daeSMarcel Telka if (!xdr_opaque(&outxdr, arg.args.args_val, arg.args.args_len)) {
10848f6d9daeSMarcel Telka forward_destroy(fi);
10858f6d9daeSMarcel Telka (void) mutex_unlock(&finfo_lock);
10867c478bd9Sstevel@tonic-gate if (reply_type == RPCBPROC_INDIRECT)
10877c478bd9Sstevel@tonic-gate svcerr_systemerr(transp);
10887c478bd9Sstevel@tonic-gate if (debugging)
10897c478bd9Sstevel@tonic-gate fprintf(stderr,
10908f6d9daeSMarcel Telka "rpcbproc_callit_com: xdr_opaque failed\n");
10917c478bd9Sstevel@tonic-gate goto error;
10927c478bd9Sstevel@tonic-gate }
10938f6d9daeSMarcel Telka
10948f6d9daeSMarcel Telka tu_data.udata.len = XDR_GETPOS(&outxdr);
10957c478bd9Sstevel@tonic-gate if (outbuf_alloc)
10967c478bd9Sstevel@tonic-gate tu_data.udata.buf = outbuf_alloc;
10977c478bd9Sstevel@tonic-gate else
10987c478bd9Sstevel@tonic-gate tu_data.udata.buf = outbuf;
10997c478bd9Sstevel@tonic-gate tu_data.opt.len = 0;
11007c478bd9Sstevel@tonic-gate
11017c478bd9Sstevel@tonic-gate na = uaddr2taddr(nconf, ma.m_uaddr);
11027c478bd9Sstevel@tonic-gate if (!na) {
11038f6d9daeSMarcel Telka forward_destroy(fi);
11048f6d9daeSMarcel Telka (void) mutex_unlock(&finfo_lock);
11057c478bd9Sstevel@tonic-gate if (reply_type == RPCBPROC_INDIRECT)
11067c478bd9Sstevel@tonic-gate svcerr_systemerr(transp);
11077c478bd9Sstevel@tonic-gate goto error;
11087c478bd9Sstevel@tonic-gate }
11097c478bd9Sstevel@tonic-gate tu_data.addr = *na;
11107c478bd9Sstevel@tonic-gate
11117c478bd9Sstevel@tonic-gate if (t_sndudata(fd, &tu_data) == -1) {
11128f6d9daeSMarcel Telka int err = errno;
11138f6d9daeSMarcel Telka forward_destroy(fi);
11148f6d9daeSMarcel Telka (void) mutex_unlock(&finfo_lock);
11158f6d9daeSMarcel Telka
11168f6d9daeSMarcel Telka netdir_free((char *)na, ND_ADDR);
11178f6d9daeSMarcel Telka
11187c478bd9Sstevel@tonic-gate if (reply_type == RPCBPROC_INDIRECT)
11197c478bd9Sstevel@tonic-gate svcerr_systemerr(transp);
11208f6d9daeSMarcel Telka if (debugging)
11218f6d9daeSMarcel Telka fprintf(stderr,
11228f6d9daeSMarcel Telka "rpcbproc_callit_com: t_sndudata failed: "
11238f6d9daeSMarcel Telka "t_errno %d, errno %d\n", t_errno, err);
11247c478bd9Sstevel@tonic-gate goto error;
11257c478bd9Sstevel@tonic-gate }
11268f6d9daeSMarcel Telka
11278f6d9daeSMarcel Telka netdir_free((char *)na, ND_ADDR);
11288f6d9daeSMarcel Telka xdr_destroy(&outxdr);
11298f6d9daeSMarcel Telka outxdr_created = FALSE;
11308f6d9daeSMarcel Telka if (outbuf_alloc != NULL) {
11318f6d9daeSMarcel Telka free(outbuf_alloc);
11328f6d9daeSMarcel Telka outbuf_alloc = NULL;
11338f6d9daeSMarcel Telka }
11348f6d9daeSMarcel Telka svc_freeargs(transp, xdr_rpcb_rmtcallargs, (char *)&arg);
11358f6d9daeSMarcel Telka
11368f6d9daeSMarcel Telka to.tv_sec = time(NULL) + MAXTIME_OFF;
11378f6d9daeSMarcel Telka to.tv_nsec = 0;
11388f6d9daeSMarcel Telka
11398f6d9daeSMarcel Telka while (fi->reply_data == NULL &&
11408f6d9daeSMarcel Telka cond_timedwait(&fi->cv, &finfo_lock, &to) != ETIME)
11418f6d9daeSMarcel Telka ;
11428f6d9daeSMarcel Telka
11438f6d9daeSMarcel Telka if (fi->reply_data == NULL) {
11448f6d9daeSMarcel Telka forward_destroy(fi);
11458f6d9daeSMarcel Telka (void) mutex_unlock(&finfo_lock);
11468f6d9daeSMarcel Telka
11478f6d9daeSMarcel Telka if (reply_type == RPCBPROC_INDIRECT)
11488f6d9daeSMarcel Telka svcerr_systemerr(transp);
11498f6d9daeSMarcel Telka if (debugging)
11508f6d9daeSMarcel Telka (void) fprintf(stderr,
11518f6d9daeSMarcel Telka "rpcbproc_callit_com: timeout\n");
11528f6d9daeSMarcel Telka return;
11538f6d9daeSMarcel Telka }
11548f6d9daeSMarcel Telka
11558f6d9daeSMarcel Telka if (fi->reply_error.re_status != RPC_SUCCESS) {
11568f6d9daeSMarcel Telka forward_destroy(fi);
11578f6d9daeSMarcel Telka (void) mutex_unlock(&finfo_lock);
11588f6d9daeSMarcel Telka
11598f6d9daeSMarcel Telka if (reply_type == RPCBPROC_INDIRECT)
11608f6d9daeSMarcel Telka svcerr_systemerr(transp);
11618f6d9daeSMarcel Telka if (debugging)
11628f6d9daeSMarcel Telka (void) fprintf(stderr,
11638f6d9daeSMarcel Telka "rpcbproc_callit_com: error in reply: %s\n",
11648f6d9daeSMarcel Telka clnt_sperrno(fi->reply_error.re_status));
11658f6d9daeSMarcel Telka return;
11668f6d9daeSMarcel Telka }
11678f6d9daeSMarcel Telka
11688f6d9daeSMarcel Telka switch (versnum) {
11698f6d9daeSMarcel Telka #ifdef PORTMAP
11708f6d9daeSMarcel Telka case PMAPVERS:
11718f6d9daeSMarcel Telka {
11728f6d9daeSMarcel Telka rmtcallres result;
11738f6d9daeSMarcel Telka int h1, h2, h3, h4, p1, p2;
11748f6d9daeSMarcel Telka
11758f6d9daeSMarcel Telka /* interpret the universal address for TCP/IP */
11768f6d9daeSMarcel Telka if (sscanf(fi->uaddr, "%d.%d.%d.%d.%d.%d",
11778f6d9daeSMarcel Telka &h1, &h2, &h3, &h4, &p1, &p2) != 6)
11788f6d9daeSMarcel Telka break;
11798f6d9daeSMarcel Telka
11808f6d9daeSMarcel Telka result.port = ((p1 & 0xff) << 8) + (p2 & 0xff);
11818f6d9daeSMarcel Telka result.res.res_len = fi->res_len;
11828f6d9daeSMarcel Telka result.res.res_val = fi->res_val;
11838f6d9daeSMarcel Telka
11848f6d9daeSMarcel Telka svc_sendreply(transp, xdr_rmtcallres, (char *)&result);
11858f6d9daeSMarcel Telka }
11868f6d9daeSMarcel Telka break;
11878f6d9daeSMarcel Telka #endif
11888f6d9daeSMarcel Telka case RPCBVERS:
11898f6d9daeSMarcel Telka case RPCBVERS4:
11908f6d9daeSMarcel Telka {
11918f6d9daeSMarcel Telka rpcb_rmtcallres result;
11928f6d9daeSMarcel Telka
11938f6d9daeSMarcel Telka result.addr = fi->uaddr;
11948f6d9daeSMarcel Telka result.results.results_len = fi->res_len;
11958f6d9daeSMarcel Telka result.results.results_val = fi->res_val;
11968f6d9daeSMarcel Telka
11978f6d9daeSMarcel Telka svc_sendreply(transp, xdr_rpcb_rmtcallres,
11988f6d9daeSMarcel Telka (char *)&result);
11998f6d9daeSMarcel Telka }
12008f6d9daeSMarcel Telka break;
12018f6d9daeSMarcel Telka }
12028f6d9daeSMarcel Telka
12038f6d9daeSMarcel Telka forward_destroy(fi);
12048f6d9daeSMarcel Telka (void) mutex_unlock(&finfo_lock);
12058f6d9daeSMarcel Telka
12068f6d9daeSMarcel Telka return;
12077c478bd9Sstevel@tonic-gate
12087c478bd9Sstevel@tonic-gate error:
12098f6d9daeSMarcel Telka if (outxdr_created)
12108f6d9daeSMarcel Telka xdr_destroy(&outxdr);
12118f6d9daeSMarcel Telka free(outbuf_alloc);
12128f6d9daeSMarcel Telka svc_freeargs(transp, xdr_rpcb_rmtcallargs, (char *)&arg);
12137c478bd9Sstevel@tonic-gate }
12147c478bd9Sstevel@tonic-gate
12158f6d9daeSMarcel Telka static struct finfo *forward_find(ulong_t, char *);
12167c478bd9Sstevel@tonic-gate
12177c478bd9Sstevel@tonic-gate /*
12188f6d9daeSMarcel Telka * Adds an entry into the finfo list for the given request. Returns the finfo
12198f6d9daeSMarcel Telka * and finfo_lock is left held. If duplicate request, returns finfo with
12208f6d9daeSMarcel Telka * FINFO_ACTIVE, else returns finfo without FINFO_ACTIVE.
12218f6d9daeSMarcel Telka * If failed, returns NULL and finfo_lock is left unheld.
12227c478bd9Sstevel@tonic-gate */
12238f6d9daeSMarcel Telka static struct finfo *
forward_register(ulong_t caller_xid,struct netbuf * caller_addr,int forward_fd,char * uaddr)12248f6d9daeSMarcel Telka forward_register(ulong_t caller_xid, struct netbuf *caller_addr, int forward_fd,
12258f6d9daeSMarcel Telka char *uaddr)
12267c478bd9Sstevel@tonic-gate {
12278f6d9daeSMarcel Telka struct finfo *fi;
12287c478bd9Sstevel@tonic-gate
12298f6d9daeSMarcel Telka (void) mutex_lock(&finfo_lock);
12308f6d9daeSMarcel Telka if (rpcb_rmtcalls_max == 0) {
12318f6d9daeSMarcel Telka (void) mutex_unlock(&finfo_lock);
12328f6d9daeSMarcel Telka return (NULL);
12338f6d9daeSMarcel Telka }
12348f6d9daeSMarcel Telka
12353582b7c1Sgt29601 /*
12363582b7c1Sgt29601 * initialization: once this has happened, lastxid will
12378f6d9daeSMarcel Telka * never be 0 again, when entering or returning from this function.
12383582b7c1Sgt29601 */
12398f6d9daeSMarcel Telka if (lastxid == 0)
12408f6d9daeSMarcel Telka lastxid = time(NULL);
12418f6d9daeSMarcel Telka
12423582b7c1Sgt29601 /*
12438f6d9daeSMarcel Telka * Check if it is an duplicate entry
12443582b7c1Sgt29601 */
12458f6d9daeSMarcel Telka for (fi = fihead; fi != NULL; fi = fi->next) {
12468f6d9daeSMarcel Telka if (fi->caller_xid == caller_xid &&
12478f6d9daeSMarcel Telka netbufcmp(fi->caller_addr, caller_addr)) {
12488f6d9daeSMarcel Telka assert(fi->flag & FINFO_ACTIVE);
12498f6d9daeSMarcel Telka return (fi);
12508f6d9daeSMarcel Telka }
12518f6d9daeSMarcel Telka }
12528f6d9daeSMarcel Telka
12538f6d9daeSMarcel Telka fi = malloc(sizeof (*fi));
12548f6d9daeSMarcel Telka if (fi == NULL) {
12558f6d9daeSMarcel Telka (void) mutex_unlock(&finfo_lock);
12568f6d9daeSMarcel Telka return (NULL);
12578f6d9daeSMarcel Telka }
12588f6d9daeSMarcel Telka
12598f6d9daeSMarcel Telka if ((fi->caller_addr = netbufdup(caller_addr)) == NULL) {
12608f6d9daeSMarcel Telka (void) mutex_unlock(&finfo_lock);
12618f6d9daeSMarcel Telka free(fi);
12628f6d9daeSMarcel Telka return (NULL);
12633582b7c1Sgt29601 }
12647c478bd9Sstevel@tonic-gate
12657c478bd9Sstevel@tonic-gate /*
12668f6d9daeSMarcel Telka * Generate new xid and make sure it is unique.
12677c478bd9Sstevel@tonic-gate */
12688f6d9daeSMarcel Telka do {
12698f6d9daeSMarcel Telka lastxid++;
12708f6d9daeSMarcel Telka /* avoid lastxid wraparound to 0 */
12718f6d9daeSMarcel Telka if (lastxid == 0)
12728f6d9daeSMarcel Telka lastxid = 1;
12738f6d9daeSMarcel Telka } while (forward_find(lastxid, uaddr) != NULL);
12748f6d9daeSMarcel Telka
12758f6d9daeSMarcel Telka fi->prev = NULL;
12768f6d9daeSMarcel Telka fi->next = fihead;
1277e9b15d23SMarcel Telka if (fihead != NULL)
1278e9b15d23SMarcel Telka fihead->prev = fi;
12798f6d9daeSMarcel Telka fihead = fi;
12808f6d9daeSMarcel Telka if (fitail == NULL)
12818f6d9daeSMarcel Telka fitail = fi;
12828f6d9daeSMarcel Telka
12838f6d9daeSMarcel Telka fi->flag = 0;
12848f6d9daeSMarcel Telka fi->caller_xid = caller_xid;
12858f6d9daeSMarcel Telka
12868f6d9daeSMarcel Telka fi->forward_xid = lastxid;
12878f6d9daeSMarcel Telka fi->forward_fd = forward_fd;
12888f6d9daeSMarcel Telka
12897c478bd9Sstevel@tonic-gate /*
12907c478bd9Sstevel@tonic-gate * Though uaddr is not allocated here, it will still be freed
12918f6d9daeSMarcel Telka * from forward_destroy().
12927c478bd9Sstevel@tonic-gate */
12938f6d9daeSMarcel Telka fi->uaddr = uaddr;
12943582b7c1Sgt29601
12958f6d9daeSMarcel Telka fi->reply_data = NULL;
12968f6d9daeSMarcel Telka (void) cond_init(&fi->cv, USYNC_THREAD, NULL);
12978f6d9daeSMarcel Telka
12988f6d9daeSMarcel Telka rpcb_rmtcalls++;
12998f6d9daeSMarcel Telka if (rpcb_rmtcalls > rpcb_rmtcalls_max) {
13008f6d9daeSMarcel Telka assert(fitail != fi);
13018f6d9daeSMarcel Telka (void) cond_signal(&fitail->cv);
13028f6d9daeSMarcel Telka }
13038f6d9daeSMarcel Telka
13048f6d9daeSMarcel Telka return (fi);
13058f6d9daeSMarcel Telka }
13068f6d9daeSMarcel Telka
13078f6d9daeSMarcel Telka static void
forward_destroy(struct finfo * fi)13088f6d9daeSMarcel Telka forward_destroy(struct finfo *fi)
13098f6d9daeSMarcel Telka {
13108f6d9daeSMarcel Telka assert(MUTEX_HELD(&finfo_lock));
13118f6d9daeSMarcel Telka assert(fi->flag & FINFO_ACTIVE);
13128f6d9daeSMarcel Telka
13138f6d9daeSMarcel Telka if (fihead == fi) {
13148f6d9daeSMarcel Telka assert(fi->prev == NULL);
13158f6d9daeSMarcel Telka fihead = fi->next;
13168f6d9daeSMarcel Telka } else {
13178f6d9daeSMarcel Telka fi->prev->next = fi->next;
13188f6d9daeSMarcel Telka }
13198f6d9daeSMarcel Telka
13208f6d9daeSMarcel Telka if (fitail == fi) {
13218f6d9daeSMarcel Telka assert(fi->next == NULL);
13228f6d9daeSMarcel Telka fitail = fi->prev;
13238f6d9daeSMarcel Telka } else {
13248f6d9daeSMarcel Telka fi->next->prev = fi->prev;
13258f6d9daeSMarcel Telka }
13268f6d9daeSMarcel Telka
13278f6d9daeSMarcel Telka netbuffree(fi->caller_addr);
13288f6d9daeSMarcel Telka free(fi->uaddr);
13298f6d9daeSMarcel Telka if (fi->reply_data != NULL)
13308f6d9daeSMarcel Telka t_free((char *)fi->reply_data, T_UNITDATA);
13318f6d9daeSMarcel Telka (void) cond_destroy(&fi->cv);
13328f6d9daeSMarcel Telka
13338f6d9daeSMarcel Telka free(fi);
13348f6d9daeSMarcel Telka
13358f6d9daeSMarcel Telka rpcb_rmtcalls--;
13368f6d9daeSMarcel Telka if (rpcb_rmtcalls > rpcb_rmtcalls_max) {
13378f6d9daeSMarcel Telka assert(fitail != NULL);
13388f6d9daeSMarcel Telka (void) cond_signal(&fitail->cv);
13398f6d9daeSMarcel Telka }
13407c478bd9Sstevel@tonic-gate }
13417c478bd9Sstevel@tonic-gate
13427c478bd9Sstevel@tonic-gate static struct finfo *
forward_find(ulong_t reply_xid,char * uaddr)13438f6d9daeSMarcel Telka forward_find(ulong_t reply_xid, char *uaddr)
13447c478bd9Sstevel@tonic-gate {
13458f6d9daeSMarcel Telka struct finfo *fi;
13467c478bd9Sstevel@tonic-gate
13478f6d9daeSMarcel Telka assert(MUTEX_HELD(&finfo_lock));
13488f6d9daeSMarcel Telka
13498f6d9daeSMarcel Telka for (fi = fihead; fi != NULL; fi = fi->next) {
13508f6d9daeSMarcel Telka if (fi->forward_xid == reply_xid &&
13518f6d9daeSMarcel Telka strcmp(fi->uaddr, uaddr) == 0)
13528f6d9daeSMarcel Telka return (fi);
13537c478bd9Sstevel@tonic-gate }
13548f6d9daeSMarcel Telka
13557c478bd9Sstevel@tonic-gate return (NULL);
13567c478bd9Sstevel@tonic-gate }
13577c478bd9Sstevel@tonic-gate
13587c478bd9Sstevel@tonic-gate static int
netbufcmp(struct netbuf * n1,struct netbuf * n2)13598f6d9daeSMarcel Telka netbufcmp(struct netbuf *n1, struct netbuf *n2)
13607c478bd9Sstevel@tonic-gate {
13617c478bd9Sstevel@tonic-gate return ((n1->len != n2->len) || memcmp(n1->buf, n2->buf, n1->len));
13627c478bd9Sstevel@tonic-gate }
13637c478bd9Sstevel@tonic-gate
13647c478bd9Sstevel@tonic-gate static struct netbuf *
netbufdup(struct netbuf * ap)13658f6d9daeSMarcel Telka netbufdup(struct netbuf *ap)
13667c478bd9Sstevel@tonic-gate {
13678f6d9daeSMarcel Telka struct netbuf *np;
13687c478bd9Sstevel@tonic-gate
13698f6d9daeSMarcel Telka np = malloc(sizeof (struct netbuf) + ap->len);
13707c478bd9Sstevel@tonic-gate if (np) {
13717c478bd9Sstevel@tonic-gate np->maxlen = np->len = ap->len;
13727c478bd9Sstevel@tonic-gate np->buf = ((char *)np) + sizeof (struct netbuf);
13737c478bd9Sstevel@tonic-gate (void) memcpy(np->buf, ap->buf, ap->len);
13747c478bd9Sstevel@tonic-gate }
13757c478bd9Sstevel@tonic-gate return (np);
13767c478bd9Sstevel@tonic-gate }
13777c478bd9Sstevel@tonic-gate
13787c478bd9Sstevel@tonic-gate static void
netbuffree(struct netbuf * ap)13798f6d9daeSMarcel Telka netbuffree(struct netbuf *ap)
13807c478bd9Sstevel@tonic-gate {
13818f6d9daeSMarcel Telka free(ap);
13827c478bd9Sstevel@tonic-gate }
13837c478bd9Sstevel@tonic-gate
13847c478bd9Sstevel@tonic-gate static void
handle_reply(svc_input_id_t id,int fd,unsigned int events,void * cookie)13858f6d9daeSMarcel Telka handle_reply(svc_input_id_t id, int fd, unsigned int events, void *cookie)
13867c478bd9Sstevel@tonic-gate {
13878f6d9daeSMarcel Telka struct t_unitdata *tr_data;
13888f6d9daeSMarcel Telka int res;
13897c478bd9Sstevel@tonic-gate
13908f6d9daeSMarcel Telka unsigned int inlen;
13917c478bd9Sstevel@tonic-gate char *buffer;
13928f6d9daeSMarcel Telka XDR reply_xdrs;
13938f6d9daeSMarcel Telka
13948f6d9daeSMarcel Telka struct rpc_msg reply_msg;
13958f6d9daeSMarcel Telka unsigned int pos;
13968f6d9daeSMarcel Telka unsigned int len;
13978f6d9daeSMarcel Telka
13988f6d9daeSMarcel Telka struct netconfig *nconf;
13997c478bd9Sstevel@tonic-gate char *uaddr = NULL;
14007c478bd9Sstevel@tonic-gate
14018f6d9daeSMarcel Telka struct finfo *fi;
14027c478bd9Sstevel@tonic-gate
14038f6d9daeSMarcel Telka tr_data = (struct t_unitdata *)t_alloc(fd, T_UNITDATA,
14048f6d9daeSMarcel Telka T_ADDR | T_UDATA);
14058f6d9daeSMarcel Telka if (tr_data == NULL) {
14068f6d9daeSMarcel Telka syslog(LOG_ERR, "handle_reply: t_alloc failed!");
14077c478bd9Sstevel@tonic-gate return;
14087c478bd9Sstevel@tonic-gate }
14097c478bd9Sstevel@tonic-gate
14107c478bd9Sstevel@tonic-gate do {
14118f6d9daeSMarcel Telka int moreflag = 0;
14127c478bd9Sstevel@tonic-gate
14137c478bd9Sstevel@tonic-gate if (errno == EINTR)
14147c478bd9Sstevel@tonic-gate errno = 0;
14157c478bd9Sstevel@tonic-gate res = t_rcvudata(fd, tr_data, &moreflag);
14167c478bd9Sstevel@tonic-gate if (moreflag & T_MORE) {
14177c478bd9Sstevel@tonic-gate /* Drop this packet - we have no more space. */
14187c478bd9Sstevel@tonic-gate if (debugging)
14198f6d9daeSMarcel Telka fprintf(stderr, "handle_reply: recvd packet "
14208f6d9daeSMarcel Telka "with T_MORE flag set\n");
14217c478bd9Sstevel@tonic-gate goto done;
14227c478bd9Sstevel@tonic-gate }
14238f6d9daeSMarcel Telka } while (res < 0 && t_errno == TSYSERR && errno == EINTR);
14247c478bd9Sstevel@tonic-gate
14258f6d9daeSMarcel Telka if (res < 0) {
14267c478bd9Sstevel@tonic-gate if (debugging)
14278f6d9daeSMarcel Telka fprintf(stderr, "handle_reply: t_rcvudata returned "
14288f6d9daeSMarcel Telka "%d, t_errno %d, errno %d\n", res, t_errno, errno);
14298f6d9daeSMarcel Telka
14308f6d9daeSMarcel Telka if (t_errno == TLOOK)
14318f6d9daeSMarcel Telka (void) t_rcvuderr(fd, NULL);
14327c478bd9Sstevel@tonic-gate
14337c478bd9Sstevel@tonic-gate goto done;
14347c478bd9Sstevel@tonic-gate }
14357c478bd9Sstevel@tonic-gate
14367c478bd9Sstevel@tonic-gate inlen = tr_data->udata.len;
14377c478bd9Sstevel@tonic-gate buffer = tr_data->udata.buf;
14388f6d9daeSMarcel Telka assert(buffer != NULL);
14398f6d9daeSMarcel Telka xdrmem_create(&reply_xdrs, buffer, inlen, XDR_DECODE);
14408f6d9daeSMarcel Telka
14417c478bd9Sstevel@tonic-gate reply_msg.acpted_rply.ar_verf = _null_auth;
14427c478bd9Sstevel@tonic-gate reply_msg.acpted_rply.ar_results.where = 0;
14437c478bd9Sstevel@tonic-gate reply_msg.acpted_rply.ar_results.proc = (xdrproc_t)xdr_void;
14447c478bd9Sstevel@tonic-gate
14457c478bd9Sstevel@tonic-gate if (!xdr_replymsg(&reply_xdrs, &reply_msg)) {
14468f6d9daeSMarcel Telka xdr_destroy(&reply_xdrs);
14477c478bd9Sstevel@tonic-gate if (debugging)
14487c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
14497c478bd9Sstevel@tonic-gate "handle_reply: xdr_replymsg failed\n");
14507c478bd9Sstevel@tonic-gate goto done;
14517c478bd9Sstevel@tonic-gate }
14527c478bd9Sstevel@tonic-gate pos = XDR_GETPOS(&reply_xdrs);
14538f6d9daeSMarcel Telka xdr_destroy(&reply_xdrs);
14548f6d9daeSMarcel Telka
14557c478bd9Sstevel@tonic-gate len = inlen - pos;
14567c478bd9Sstevel@tonic-gate
14578f6d9daeSMarcel Telka nconf = rpcbind_get_conf((char *)cookie);
14588f6d9daeSMarcel Telka if (nconf == NULL) {
14598f6d9daeSMarcel Telka syslog(LOG_ERR, "handle_reply: rpcbind_get_conf failed!");
14608f6d9daeSMarcel Telka goto done;
14617c478bd9Sstevel@tonic-gate }
14628f6d9daeSMarcel Telka uaddr = taddr2uaddr(nconf, &tr_data->addr);
14638f6d9daeSMarcel Telka if (uaddr == NULL) {
14648f6d9daeSMarcel Telka syslog(LOG_ERR, "handle_reply: taddr2uaddr failed!");
14658f6d9daeSMarcel Telka goto done;
14668f6d9daeSMarcel Telka }
14678f6d9daeSMarcel Telka
14688f6d9daeSMarcel Telka (void) mutex_lock(&finfo_lock);
14698f6d9daeSMarcel Telka fi = forward_find(reply_msg.rm_xid, uaddr);
14708f6d9daeSMarcel Telka if (fi == NULL) {
14718f6d9daeSMarcel Telka (void) mutex_unlock(&finfo_lock);
14728f6d9daeSMarcel Telka goto done;
14738f6d9daeSMarcel Telka }
14748f6d9daeSMarcel Telka
14758f6d9daeSMarcel Telka fi->reply_data = tr_data;
14768f6d9daeSMarcel Telka tr_data = NULL;
14778f6d9daeSMarcel Telka
14788f6d9daeSMarcel Telka __seterr_reply(&reply_msg, &fi->reply_error);
14798f6d9daeSMarcel Telka
14808f6d9daeSMarcel Telka fi->res_len = len;
14818f6d9daeSMarcel Telka fi->res_val = &buffer[pos];
14828f6d9daeSMarcel Telka
14838f6d9daeSMarcel Telka (void) cond_signal(&fi->cv);
14848f6d9daeSMarcel Telka (void) mutex_unlock(&finfo_lock);
14858f6d9daeSMarcel Telka
14867c478bd9Sstevel@tonic-gate done:
14878f6d9daeSMarcel Telka free(uaddr);
14887c478bd9Sstevel@tonic-gate if (tr_data)
14897c478bd9Sstevel@tonic-gate t_free((char *)tr_data, T_UNITDATA);
14907c478bd9Sstevel@tonic-gate }
14917c478bd9Sstevel@tonic-gate
14928f6d9daeSMarcel Telka /*
14938f6d9daeSMarcel Telka * prog: Program Number
14948f6d9daeSMarcel Telka * netid: Transport Provider token
14958f6d9daeSMarcel Telka * lowvp: Low version number
14968f6d9daeSMarcel Telka * highvp: High version number
14978f6d9daeSMarcel Telka */
14987c478bd9Sstevel@tonic-gate static void
find_versions(rpcprog_t prog,char * netid,rpcvers_t * lowvp,rpcvers_t * highvp)14998f6d9daeSMarcel Telka find_versions(rpcprog_t prog, char *netid, rpcvers_t *lowvp, rpcvers_t *highvp)
15007c478bd9Sstevel@tonic-gate {
15018f6d9daeSMarcel Telka rpcblist_ptr rbl;
15028f6d9daeSMarcel Telka rpcvers_t lowv = 0;
15038f6d9daeSMarcel Telka rpcvers_t highv = 0;
15048f6d9daeSMarcel Telka
15058f6d9daeSMarcel Telka assert(RW_LOCK_HELD(&list_rbl_lock));
15067c478bd9Sstevel@tonic-gate
15077c478bd9Sstevel@tonic-gate for (rbl = list_rbl; rbl != NULL; rbl = rbl->rpcb_next) {
15087c478bd9Sstevel@tonic-gate if ((rbl->rpcb_map.r_prog != prog) ||
15098f6d9daeSMarcel Telka (strcasecmp(rbl->rpcb_map.r_netid, netid) != 0))
15107c478bd9Sstevel@tonic-gate continue;
15117c478bd9Sstevel@tonic-gate if (lowv == 0) {
15127c478bd9Sstevel@tonic-gate highv = rbl->rpcb_map.r_vers;
15137c478bd9Sstevel@tonic-gate lowv = highv;
15147c478bd9Sstevel@tonic-gate } else if (rbl->rpcb_map.r_vers < lowv) {
15157c478bd9Sstevel@tonic-gate lowv = rbl->rpcb_map.r_vers;
15167c478bd9Sstevel@tonic-gate } else if (rbl->rpcb_map.r_vers > highv) {
15177c478bd9Sstevel@tonic-gate highv = rbl->rpcb_map.r_vers;
15187c478bd9Sstevel@tonic-gate }
15197c478bd9Sstevel@tonic-gate }
15208f6d9daeSMarcel Telka
15217c478bd9Sstevel@tonic-gate *lowvp = lowv;
15227c478bd9Sstevel@tonic-gate *highvp = highv;
15237c478bd9Sstevel@tonic-gate }
15247c478bd9Sstevel@tonic-gate
15257c478bd9Sstevel@tonic-gate /*
15267c478bd9Sstevel@tonic-gate * returns the item with the given program, version number and netid.
15277c478bd9Sstevel@tonic-gate * If that version number is not found, it returns the item with that
15287c478bd9Sstevel@tonic-gate * program number, so that address is now returned to the caller. The
15297c478bd9Sstevel@tonic-gate * caller when makes a call to this program, version number, the call
15307c478bd9Sstevel@tonic-gate * will fail and it will return with PROGVERS_MISMATCH. The user can
15317c478bd9Sstevel@tonic-gate * then determine the highest and the lowest version number for this
15327c478bd9Sstevel@tonic-gate * program using clnt_geterr() and use those program version numbers.
15337c478bd9Sstevel@tonic-gate *
15347c478bd9Sstevel@tonic-gate * Returns the RPCBLIST for the given prog, vers and netid
15358f6d9daeSMarcel Telka *
15368f6d9daeSMarcel Telka * prog: Program Number
15378f6d9daeSMarcel Telka * vers: Version Number
15388f6d9daeSMarcel Telka * netid: Transport Provider token
15397c478bd9Sstevel@tonic-gate */
15407c478bd9Sstevel@tonic-gate static rpcblist_ptr
find_service(rpcprog_t prog,rpcvers_t vers,char * netid)15418f6d9daeSMarcel Telka find_service(rpcprog_t prog, rpcvers_t vers, char *netid)
15427c478bd9Sstevel@tonic-gate {
15438f6d9daeSMarcel Telka rpcblist_ptr hit = NULL;
15448f6d9daeSMarcel Telka rpcblist_ptr rbl;
15458f6d9daeSMarcel Telka
15468f6d9daeSMarcel Telka assert(RW_LOCK_HELD(&list_rbl_lock));
15477c478bd9Sstevel@tonic-gate
15487c478bd9Sstevel@tonic-gate for (rbl = list_rbl; rbl != NULL; rbl = rbl->rpcb_next) {
15497c478bd9Sstevel@tonic-gate if ((rbl->rpcb_map.r_prog != prog) ||
15508f6d9daeSMarcel Telka (strcasecmp(rbl->rpcb_map.r_netid, netid) != 0))
15517c478bd9Sstevel@tonic-gate continue;
15527c478bd9Sstevel@tonic-gate hit = rbl;
15537c478bd9Sstevel@tonic-gate if (rbl->rpcb_map.r_vers == vers)
15547c478bd9Sstevel@tonic-gate break;
15557c478bd9Sstevel@tonic-gate }
15568f6d9daeSMarcel Telka
15577c478bd9Sstevel@tonic-gate return (hit);
15587c478bd9Sstevel@tonic-gate }
15597c478bd9Sstevel@tonic-gate
15607c478bd9Sstevel@tonic-gate /*
15617c478bd9Sstevel@tonic-gate * If the caller is from our zone and we know
15627c478bd9Sstevel@tonic-gate * who it is, we return the uid.
15637c478bd9Sstevel@tonic-gate */
15647c478bd9Sstevel@tonic-gate uid_t
rpcb_caller_uid(SVCXPRT * transp)15657c478bd9Sstevel@tonic-gate rpcb_caller_uid(SVCXPRT *transp)
15667c478bd9Sstevel@tonic-gate {
15677c478bd9Sstevel@tonic-gate ucred_t *uc = alloca(ucred_size());
15687c478bd9Sstevel@tonic-gate
15697c478bd9Sstevel@tonic-gate if (svc_getcallerucred(transp, &uc) != 0 ||
15707c478bd9Sstevel@tonic-gate (ucred_getzoneid(uc)) != myzone) {
15717c478bd9Sstevel@tonic-gate return (-1);
15727c478bd9Sstevel@tonic-gate } else {
15737c478bd9Sstevel@tonic-gate return (ucred_geteuid(uc));
15747c478bd9Sstevel@tonic-gate }
15757c478bd9Sstevel@tonic-gate }
15767c478bd9Sstevel@tonic-gate
15777c478bd9Sstevel@tonic-gate /*
15787c478bd9Sstevel@tonic-gate * Copies the name associated with the uid of the caller and returns
15797c478bd9Sstevel@tonic-gate * a pointer to it. Similar to getwd().
15807c478bd9Sstevel@tonic-gate */
15817c478bd9Sstevel@tonic-gate char *
getowner(SVCXPRT * transp,char * owner)15828f6d9daeSMarcel Telka getowner(SVCXPRT *transp, char *owner)
15837c478bd9Sstevel@tonic-gate {
15847c478bd9Sstevel@tonic-gate uid_t uid = rpcb_caller_uid(transp);
15857c478bd9Sstevel@tonic-gate
15867c478bd9Sstevel@tonic-gate switch (uid) {
15877c478bd9Sstevel@tonic-gate case -1:
15887c478bd9Sstevel@tonic-gate return (strcpy(owner, "unknown"));
15897c478bd9Sstevel@tonic-gate case 0:
15907c478bd9Sstevel@tonic-gate return (strcpy(owner, "superuser"));
15917c478bd9Sstevel@tonic-gate default:
15927c478bd9Sstevel@tonic-gate (void) sprintf(owner, "%u", uid);
15937c478bd9Sstevel@tonic-gate return (owner);
15947c478bd9Sstevel@tonic-gate }
15957c478bd9Sstevel@tonic-gate }
15967c478bd9Sstevel@tonic-gate
15977c478bd9Sstevel@tonic-gate #ifdef PORTMAP
15987c478bd9Sstevel@tonic-gate /*
15997c478bd9Sstevel@tonic-gate * Add this to the pmap list only if it is UDP or TCP.
16007c478bd9Sstevel@tonic-gate */
16017c478bd9Sstevel@tonic-gate static int
add_pmaplist(RPCB * arg)16028f6d9daeSMarcel Telka add_pmaplist(RPCB *arg)
16037c478bd9Sstevel@tonic-gate {
16047c478bd9Sstevel@tonic-gate pmap pmap;
16057c478bd9Sstevel@tonic-gate pmaplist *pml;
16067c478bd9Sstevel@tonic-gate int h1, h2, h3, h4, p1, p2;
16077c478bd9Sstevel@tonic-gate
16087c478bd9Sstevel@tonic-gate if (strcmp(arg->r_netid, udptrans) == 0) {
16097c478bd9Sstevel@tonic-gate /* It is UDP! */
16107c478bd9Sstevel@tonic-gate pmap.pm_prot = IPPROTO_UDP;
16117c478bd9Sstevel@tonic-gate } else if (strcmp(arg->r_netid, tcptrans) == 0) {
16127c478bd9Sstevel@tonic-gate /* It is TCP */
16137c478bd9Sstevel@tonic-gate pmap.pm_prot = IPPROTO_TCP;
16147c478bd9Sstevel@tonic-gate } else
16157c478bd9Sstevel@tonic-gate /* Not a IP protocol */
16167c478bd9Sstevel@tonic-gate return (0);
16177c478bd9Sstevel@tonic-gate
16187c478bd9Sstevel@tonic-gate /* interpret the universal address for TCP/IP */
16197c478bd9Sstevel@tonic-gate if (sscanf(arg->r_addr, "%d.%d.%d.%d.%d.%d",
16207c478bd9Sstevel@tonic-gate &h1, &h2, &h3, &h4, &p1, &p2) != 6)
16217c478bd9Sstevel@tonic-gate return (0);
16227c478bd9Sstevel@tonic-gate pmap.pm_port = ((p1 & 0xff) << 8) + (p2 & 0xff);
16237c478bd9Sstevel@tonic-gate pmap.pm_prog = arg->r_prog;
16247c478bd9Sstevel@tonic-gate pmap.pm_vers = arg->r_vers;
16257c478bd9Sstevel@tonic-gate /*
16267c478bd9Sstevel@tonic-gate * add to END of list
16277c478bd9Sstevel@tonic-gate */
16287c478bd9Sstevel@tonic-gate pml = (pmaplist *) malloc((uint_t)sizeof (pmaplist));
16297c478bd9Sstevel@tonic-gate if (pml == NULL) {
16307c478bd9Sstevel@tonic-gate (void) syslog(LOG_ERR, "rpcbind: no memory!\n");
16317c478bd9Sstevel@tonic-gate return (1);
16327c478bd9Sstevel@tonic-gate }
16337c478bd9Sstevel@tonic-gate pml->pml_map = pmap;
16347c478bd9Sstevel@tonic-gate pml->pml_next = NULL;
16358f6d9daeSMarcel Telka
16368f6d9daeSMarcel Telka (void) rw_wrlock(&list_pml_lock);
16377c478bd9Sstevel@tonic-gate if (list_pml == NULL) {
16387c478bd9Sstevel@tonic-gate list_pml = pml;
16397c478bd9Sstevel@tonic-gate } else {
16407c478bd9Sstevel@tonic-gate pmaplist *fnd;
16417c478bd9Sstevel@tonic-gate
16427c478bd9Sstevel@tonic-gate /* Attach to the end of the list */
16437c478bd9Sstevel@tonic-gate for (fnd = list_pml; fnd->pml_next; fnd = fnd->pml_next)
16447c478bd9Sstevel@tonic-gate ;
16457c478bd9Sstevel@tonic-gate fnd->pml_next = pml;
16467c478bd9Sstevel@tonic-gate }
16478f6d9daeSMarcel Telka (void) rw_unlock(&list_pml_lock);
16488f6d9daeSMarcel Telka
16497c478bd9Sstevel@tonic-gate return (0);
16507c478bd9Sstevel@tonic-gate }
16517c478bd9Sstevel@tonic-gate
16527c478bd9Sstevel@tonic-gate /*
16537c478bd9Sstevel@tonic-gate * Delete this from the pmap list only if it is UDP or TCP.
16547c478bd9Sstevel@tonic-gate */
16553582b7c1Sgt29601 int
del_pmaplist(RPCB * arg)16563582b7c1Sgt29601 del_pmaplist(RPCB *arg)
16577c478bd9Sstevel@tonic-gate {
16588f6d9daeSMarcel Telka pmaplist *pml;
16597c478bd9Sstevel@tonic-gate pmaplist *prevpml, *fnd;
16608f6d9daeSMarcel Telka rpcport_t prot;
16617c478bd9Sstevel@tonic-gate
16627c478bd9Sstevel@tonic-gate if (strcmp(arg->r_netid, udptrans) == 0) {
16637c478bd9Sstevel@tonic-gate /* It is UDP! */
16647c478bd9Sstevel@tonic-gate prot = IPPROTO_UDP;
16657c478bd9Sstevel@tonic-gate } else if (strcmp(arg->r_netid, tcptrans) == 0) {
16667c478bd9Sstevel@tonic-gate /* It is TCP */
16677c478bd9Sstevel@tonic-gate prot = IPPROTO_TCP;
16688f6d9daeSMarcel Telka } else if (arg->r_netid[0] == '\0') {
16697c478bd9Sstevel@tonic-gate prot = 0; /* Remove all occurrences */
16707c478bd9Sstevel@tonic-gate } else {
16717c478bd9Sstevel@tonic-gate /* Not a IP protocol */
16727c478bd9Sstevel@tonic-gate return (0);
16737c478bd9Sstevel@tonic-gate }
16748f6d9daeSMarcel Telka
16758f6d9daeSMarcel Telka assert(RW_WRITE_HELD(&list_pml_lock));
16768f6d9daeSMarcel Telka
16777c478bd9Sstevel@tonic-gate for (prevpml = NULL, pml = list_pml; pml; /* cstyle */) {
16787c478bd9Sstevel@tonic-gate if ((pml->pml_map.pm_prog != arg->r_prog) ||
16797c478bd9Sstevel@tonic-gate (pml->pml_map.pm_vers != arg->r_vers) ||
16807c478bd9Sstevel@tonic-gate (prot && (pml->pml_map.pm_prot != prot))) {
16817c478bd9Sstevel@tonic-gate /* both pml & prevpml move forwards */
16827c478bd9Sstevel@tonic-gate prevpml = pml;
16837c478bd9Sstevel@tonic-gate pml = pml->pml_next;
16847c478bd9Sstevel@tonic-gate continue;
16857c478bd9Sstevel@tonic-gate }
16867c478bd9Sstevel@tonic-gate /* found it; pml moves forward, prevpml stays */
16877c478bd9Sstevel@tonic-gate fnd = pml;
16887c478bd9Sstevel@tonic-gate pml = pml->pml_next;
16897c478bd9Sstevel@tonic-gate if (prevpml == NULL)
16907c478bd9Sstevel@tonic-gate list_pml = pml;
16917c478bd9Sstevel@tonic-gate else
16927c478bd9Sstevel@tonic-gate prevpml->pml_next = pml;
16938f6d9daeSMarcel Telka free(fnd);
16947c478bd9Sstevel@tonic-gate }
16958f6d9daeSMarcel Telka
16967c478bd9Sstevel@tonic-gate return (0);
16977c478bd9Sstevel@tonic-gate }
16987c478bd9Sstevel@tonic-gate #endif /* PORTMAP */
1699