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*4b3b7fc6SAlex 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*4b3b7fc6SAlex 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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*4b3b7fc6SAlex 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 * 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 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 * 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 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 * 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 13798f6d9daeSMarcel Telka netbuffree(struct netbuf *ap) 13807c478bd9Sstevel@tonic-gate { 13818f6d9daeSMarcel Telka free(ap); 13827c478bd9Sstevel@tonic-gate } 13837c478bd9Sstevel@tonic-gate 13847c478bd9Sstevel@tonic-gate static void 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 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 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 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 * 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 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 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