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 527242a7cSthurlow * Common Development and Distribution License (the "License"). 627242a7cSthurlow * 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 /* 220a4b0810SKaren Rochford * Copyright (c) 1990, 2010, Oracle and/or its affiliates. All rights reserved. 2389b43686SBayard Bell * Copyright (c) 2011 Bayard G. Bell. All rights reserved. 24e36d7b11SSebastien Roy * Copyright (c) 2013 by Delphix. All rights reserved. 25c93d332cSDan McDonald * Copyright 2014 Nexenta Systems, Inc. All rights reserved. 264b3b7fc6SAlex Wilson * Copyright (c) 2017 Joyent Inc 277c478bd9Sstevel@tonic-gate */ 287c478bd9Sstevel@tonic-gate 297c478bd9Sstevel@tonic-gate /* 307c478bd9Sstevel@tonic-gate * Copyright (c) 1983,1984,1985,1986,1987,1988,1989 AT&T. 317c478bd9Sstevel@tonic-gate * All rights reserved. 327c478bd9Sstevel@tonic-gate * Use is subject to license terms. 337c478bd9Sstevel@tonic-gate */ 347c478bd9Sstevel@tonic-gate 357c478bd9Sstevel@tonic-gate #include <sys/param.h> 367c478bd9Sstevel@tonic-gate #include <sys/types.h> 377c478bd9Sstevel@tonic-gate #include <sys/systm.h> 387c478bd9Sstevel@tonic-gate #include <sys/cred.h> 397c478bd9Sstevel@tonic-gate #include <sys/proc.h> 407c478bd9Sstevel@tonic-gate #include <sys/user.h> 417c478bd9Sstevel@tonic-gate #include <sys/buf.h> 427c478bd9Sstevel@tonic-gate #include <sys/vfs.h> 437c478bd9Sstevel@tonic-gate #include <sys/vnode.h> 447c478bd9Sstevel@tonic-gate #include <sys/pathname.h> 457c478bd9Sstevel@tonic-gate #include <sys/uio.h> 467c478bd9Sstevel@tonic-gate #include <sys/file.h> 477c478bd9Sstevel@tonic-gate #include <sys/stat.h> 487c478bd9Sstevel@tonic-gate #include <sys/errno.h> 497c478bd9Sstevel@tonic-gate #include <sys/socket.h> 507c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h> 517c478bd9Sstevel@tonic-gate #include <sys/siginfo.h> 527c478bd9Sstevel@tonic-gate #include <sys/tiuser.h> 537c478bd9Sstevel@tonic-gate #include <sys/statvfs.h> 547c478bd9Sstevel@tonic-gate #include <sys/stream.h> 55e36d7b11SSebastien Roy #include <sys/strsun.h> 567c478bd9Sstevel@tonic-gate #include <sys/strsubr.h> 577c478bd9Sstevel@tonic-gate #include <sys/stropts.h> 587c478bd9Sstevel@tonic-gate #include <sys/timod.h> 597c478bd9Sstevel@tonic-gate #include <sys/t_kuser.h> 607c478bd9Sstevel@tonic-gate #include <sys/kmem.h> 617c478bd9Sstevel@tonic-gate #include <sys/kstat.h> 627c478bd9Sstevel@tonic-gate #include <sys/dirent.h> 637c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h> 647c478bd9Sstevel@tonic-gate #include <sys/debug.h> 657c478bd9Sstevel@tonic-gate #include <sys/unistd.h> 667c478bd9Sstevel@tonic-gate #include <sys/vtrace.h> 677c478bd9Sstevel@tonic-gate #include <sys/mode.h> 687c478bd9Sstevel@tonic-gate #include <sys/acl.h> 697c478bd9Sstevel@tonic-gate #include <sys/sdt.h> 704b3b7fc6SAlex Wilson #include <sys/debug.h> 717c478bd9Sstevel@tonic-gate 727c478bd9Sstevel@tonic-gate #include <rpc/types.h> 737c478bd9Sstevel@tonic-gate #include <rpc/auth.h> 747c478bd9Sstevel@tonic-gate #include <rpc/auth_unix.h> 757c478bd9Sstevel@tonic-gate #include <rpc/auth_des.h> 767c478bd9Sstevel@tonic-gate #include <rpc/svc.h> 777c478bd9Sstevel@tonic-gate #include <rpc/xdr.h> 7851f34d4bSRajkumar Sivaprakasam #include <rpc/rpc_rdma.h> 797c478bd9Sstevel@tonic-gate 807c478bd9Sstevel@tonic-gate #include <nfs/nfs.h> 817c478bd9Sstevel@tonic-gate #include <nfs/export.h> 827c478bd9Sstevel@tonic-gate #include <nfs/nfssys.h> 837c478bd9Sstevel@tonic-gate #include <nfs/nfs_clnt.h> 847c478bd9Sstevel@tonic-gate #include <nfs/nfs_acl.h> 857c478bd9Sstevel@tonic-gate #include <nfs/nfs_log.h> 86b89a8333Snatalie li - Sun Microsystems - Irvine United States #include <nfs/nfs_cmd.h> 877c478bd9Sstevel@tonic-gate #include <nfs/lm.h> 88d9ad96c1Srg137905 #include <nfs/nfs_dispatch.h> 89d9ad96c1Srg137905 #include <nfs/nfs4_drc.h> 907c478bd9Sstevel@tonic-gate 917c478bd9Sstevel@tonic-gate #include <sys/modctl.h> 927c478bd9Sstevel@tonic-gate #include <sys/cladm.h> 937c478bd9Sstevel@tonic-gate #include <sys/clconf.h> 947c478bd9Sstevel@tonic-gate 95bd6f1640SJarrett Lu #include <sys/tsol/label.h> 96bd6f1640SJarrett Lu 977c478bd9Sstevel@tonic-gate #define MAXHOST 32 987c478bd9Sstevel@tonic-gate const char *kinet_ntop6(uchar_t *, char *, size_t); 997c478bd9Sstevel@tonic-gate 1007c478bd9Sstevel@tonic-gate /* 1017c478bd9Sstevel@tonic-gate * Module linkage information. 1027c478bd9Sstevel@tonic-gate */ 1037c478bd9Sstevel@tonic-gate 1047c478bd9Sstevel@tonic-gate static struct modlmisc modlmisc = { 1057c478bd9Sstevel@tonic-gate &mod_miscops, "NFS server module" 1067c478bd9Sstevel@tonic-gate }; 1077c478bd9Sstevel@tonic-gate 1087c478bd9Sstevel@tonic-gate static struct modlinkage modlinkage = { 1097c478bd9Sstevel@tonic-gate MODREV_1, (void *)&modlmisc, NULL 1107c478bd9Sstevel@tonic-gate }; 1117c478bd9Sstevel@tonic-gate 112c242f9a0Schunli zhang - Sun Microsystems - Irvine United States kmem_cache_t *nfs_xuio_cache; 113c242f9a0Schunli zhang - Sun Microsystems - Irvine United States int nfs_loaned_buffers = 0; 114c242f9a0Schunli zhang - Sun Microsystems - Irvine United States 1157c478bd9Sstevel@tonic-gate int 1167c478bd9Sstevel@tonic-gate _init(void) 1177c478bd9Sstevel@tonic-gate { 1187c478bd9Sstevel@tonic-gate int status; 1197c478bd9Sstevel@tonic-gate 1207c478bd9Sstevel@tonic-gate if ((status = nfs_srvinit()) != 0) { 1217c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "_init: nfs_srvinit failed"); 1227c478bd9Sstevel@tonic-gate return (status); 1237c478bd9Sstevel@tonic-gate } 1247c478bd9Sstevel@tonic-gate 1257c478bd9Sstevel@tonic-gate status = mod_install((struct modlinkage *)&modlinkage); 1267c478bd9Sstevel@tonic-gate if (status != 0) { 1277c478bd9Sstevel@tonic-gate /* 1287c478bd9Sstevel@tonic-gate * Could not load module, cleanup previous 1297c478bd9Sstevel@tonic-gate * initialization work. 1307c478bd9Sstevel@tonic-gate */ 1317c478bd9Sstevel@tonic-gate nfs_srvfini(); 13241bec5e3SMarcel Telka 13341bec5e3SMarcel Telka return (status); 1347c478bd9Sstevel@tonic-gate } 1357c478bd9Sstevel@tonic-gate 136cee86682Scalum /* 137cee86682Scalum * Initialise some placeholders for nfssys() calls. These have 138cee86682Scalum * to be declared by the nfs module, since that handles nfssys() 139cee86682Scalum * calls - also used by NFS clients - but are provided by this 140cee86682Scalum * nfssrv module. These also then serve as confirmation to the 141cee86682Scalum * relevant code in nfs that nfssrv has been loaded, as they're 142cee86682Scalum * initially NULL. 143cee86682Scalum */ 1447c478bd9Sstevel@tonic-gate nfs_srv_quiesce_func = nfs_srv_quiesce_all; 145cee86682Scalum nfs_srv_dss_func = rfs4_dss_setpaths; 146cee86682Scalum 147cee86682Scalum /* setup DSS paths here; must be done before initial server startup */ 148cee86682Scalum rfs4_dss_paths = rfs4_dss_oldpaths = NULL; 1497c478bd9Sstevel@tonic-gate 150c242f9a0Schunli zhang - Sun Microsystems - Irvine United States /* initialize the copy reduction caches */ 151c242f9a0Schunli zhang - Sun Microsystems - Irvine United States 152c242f9a0Schunli zhang - Sun Microsystems - Irvine United States nfs_xuio_cache = kmem_cache_create("nfs_xuio_cache", 153c242f9a0Schunli zhang - Sun Microsystems - Irvine United States sizeof (nfs_xuio_t), 0, NULL, NULL, NULL, NULL, NULL, 0); 154c242f9a0Schunli zhang - Sun Microsystems - Irvine United States 1557c478bd9Sstevel@tonic-gate return (status); 1567c478bd9Sstevel@tonic-gate } 1577c478bd9Sstevel@tonic-gate 1587c478bd9Sstevel@tonic-gate int 1597c478bd9Sstevel@tonic-gate _fini() 1607c478bd9Sstevel@tonic-gate { 1617c478bd9Sstevel@tonic-gate return (EBUSY); 1627c478bd9Sstevel@tonic-gate } 1637c478bd9Sstevel@tonic-gate 1647c478bd9Sstevel@tonic-gate int 1657c478bd9Sstevel@tonic-gate _info(struct modinfo *modinfop) 1667c478bd9Sstevel@tonic-gate { 1677c478bd9Sstevel@tonic-gate return (mod_info(&modlinkage, modinfop)); 1687c478bd9Sstevel@tonic-gate } 1697c478bd9Sstevel@tonic-gate 1707c478bd9Sstevel@tonic-gate /* 1717c478bd9Sstevel@tonic-gate * PUBLICFH_CHECK() checks if the dispatch routine supports 1727c478bd9Sstevel@tonic-gate * RPC_PUBLICFH_OK, if the filesystem is exported public, and if the 1737c478bd9Sstevel@tonic-gate * incoming request is using the public filehandle. The check duplicates 1747c478bd9Sstevel@tonic-gate * the exportmatch() call done in checkexport(), and we should consider 1757c478bd9Sstevel@tonic-gate * modifying those routines to avoid the duplication. For now, we optimize 1767c478bd9Sstevel@tonic-gate * by calling exportmatch() only after checking that the dispatch routine 1777c478bd9Sstevel@tonic-gate * supports RPC_PUBLICFH_OK, and if the filesystem is explicitly exported 1787c478bd9Sstevel@tonic-gate * public (i.e., not the placeholder). 1797c478bd9Sstevel@tonic-gate */ 18027242a7cSthurlow #define PUBLICFH_CHECK(disp, exi, fsid, xfid) \ 1817c478bd9Sstevel@tonic-gate ((disp->dis_flags & RPC_PUBLICFH_OK) && \ 1827c478bd9Sstevel@tonic-gate ((exi->exi_export.ex_flags & EX_PUBLIC) || \ 1837c478bd9Sstevel@tonic-gate (exi == exi_public && exportmatch(exi_root, \ 18427242a7cSthurlow fsid, xfid)))) 1857c478bd9Sstevel@tonic-gate 1867c478bd9Sstevel@tonic-gate static void nfs_srv_shutdown_all(int); 1877c478bd9Sstevel@tonic-gate static void rfs4_server_start(int); 1887c478bd9Sstevel@tonic-gate static void nullfree(void); 1897c478bd9Sstevel@tonic-gate static void rfs_dispatch(struct svc_req *, SVCXPRT *); 1907c478bd9Sstevel@tonic-gate static void acl_dispatch(struct svc_req *, SVCXPRT *); 1917c478bd9Sstevel@tonic-gate static void common_dispatch(struct svc_req *, SVCXPRT *, 1927c478bd9Sstevel@tonic-gate rpcvers_t, rpcvers_t, char *, 1937c478bd9Sstevel@tonic-gate struct rpc_disptable *); 194cee86682Scalum static void hanfsv4_failover(void); 1957c478bd9Sstevel@tonic-gate static int checkauth(struct exportinfo *, struct svc_req *, cred_t *, int, 1965cb0d679SMarcel Telka bool_t, bool_t *); 1977c478bd9Sstevel@tonic-gate static char *client_name(struct svc_req *req); 1987c478bd9Sstevel@tonic-gate static char *client_addr(struct svc_req *req, char *buf); 1997c478bd9Sstevel@tonic-gate extern int sec_svc_getcred(struct svc_req *, cred_t *cr, char **, int *); 2007c478bd9Sstevel@tonic-gate extern bool_t sec_svc_inrootlist(int, caddr_t, int, caddr_t *); 2017c478bd9Sstevel@tonic-gate 2027c478bd9Sstevel@tonic-gate #define NFSLOG_COPY_NETBUF(exi, xprt, nb) { \ 2037c478bd9Sstevel@tonic-gate (nb)->maxlen = (xprt)->xp_rtaddr.maxlen; \ 2047c478bd9Sstevel@tonic-gate (nb)->len = (xprt)->xp_rtaddr.len; \ 2057c478bd9Sstevel@tonic-gate (nb)->buf = kmem_alloc((nb)->len, KM_SLEEP); \ 2067c478bd9Sstevel@tonic-gate bcopy((xprt)->xp_rtaddr.buf, (nb)->buf, (nb)->len); \ 2077c478bd9Sstevel@tonic-gate } 2087c478bd9Sstevel@tonic-gate 2097c478bd9Sstevel@tonic-gate /* 2107c478bd9Sstevel@tonic-gate * Public Filehandle common nfs routines 2117c478bd9Sstevel@tonic-gate */ 2127c478bd9Sstevel@tonic-gate static int MCLpath(char **); 2137c478bd9Sstevel@tonic-gate static void URLparse(char *); 2147c478bd9Sstevel@tonic-gate 2157c478bd9Sstevel@tonic-gate /* 2167c478bd9Sstevel@tonic-gate * NFS callout table. 2177c478bd9Sstevel@tonic-gate * This table is used by svc_getreq() to dispatch a request with 2187c478bd9Sstevel@tonic-gate * a given prog/vers pair to an appropriate service provider 2197c478bd9Sstevel@tonic-gate * dispatch routine. 2207c478bd9Sstevel@tonic-gate * 2217c478bd9Sstevel@tonic-gate * NOTE: ordering is relied upon below when resetting the version min/max 2227c478bd9Sstevel@tonic-gate * for NFS_PROGRAM. Careful, if this is ever changed. 2237c478bd9Sstevel@tonic-gate */ 2247c478bd9Sstevel@tonic-gate static SVC_CALLOUT __nfs_sc_clts[] = { 2257c478bd9Sstevel@tonic-gate { NFS_PROGRAM, NFS_VERSMIN, NFS_VERSMAX, rfs_dispatch }, 2267c478bd9Sstevel@tonic-gate { NFS_ACL_PROGRAM, NFS_ACL_VERSMIN, NFS_ACL_VERSMAX, acl_dispatch } 2277c478bd9Sstevel@tonic-gate }; 2287c478bd9Sstevel@tonic-gate 2297c478bd9Sstevel@tonic-gate static SVC_CALLOUT_TABLE nfs_sct_clts = { 2307c478bd9Sstevel@tonic-gate sizeof (__nfs_sc_clts) / sizeof (__nfs_sc_clts[0]), FALSE, 2317c478bd9Sstevel@tonic-gate __nfs_sc_clts 2327c478bd9Sstevel@tonic-gate }; 2337c478bd9Sstevel@tonic-gate 2347c478bd9Sstevel@tonic-gate static SVC_CALLOUT __nfs_sc_cots[] = { 2357c478bd9Sstevel@tonic-gate { NFS_PROGRAM, NFS_VERSMIN, NFS_VERSMAX, rfs_dispatch }, 2367c478bd9Sstevel@tonic-gate { NFS_ACL_PROGRAM, NFS_ACL_VERSMIN, NFS_ACL_VERSMAX, acl_dispatch } 2377c478bd9Sstevel@tonic-gate }; 2387c478bd9Sstevel@tonic-gate 2397c478bd9Sstevel@tonic-gate static SVC_CALLOUT_TABLE nfs_sct_cots = { 2407c478bd9Sstevel@tonic-gate sizeof (__nfs_sc_cots) / sizeof (__nfs_sc_cots[0]), FALSE, __nfs_sc_cots 2417c478bd9Sstevel@tonic-gate }; 2427c478bd9Sstevel@tonic-gate 2437c478bd9Sstevel@tonic-gate static SVC_CALLOUT __nfs_sc_rdma[] = { 2447c478bd9Sstevel@tonic-gate { NFS_PROGRAM, NFS_VERSMIN, NFS_VERSMAX, rfs_dispatch }, 2457c478bd9Sstevel@tonic-gate { NFS_ACL_PROGRAM, NFS_ACL_VERSMIN, NFS_ACL_VERSMAX, acl_dispatch } 2467c478bd9Sstevel@tonic-gate }; 2477c478bd9Sstevel@tonic-gate 2487c478bd9Sstevel@tonic-gate static SVC_CALLOUT_TABLE nfs_sct_rdma = { 2497c478bd9Sstevel@tonic-gate sizeof (__nfs_sc_rdma) / sizeof (__nfs_sc_rdma[0]), FALSE, __nfs_sc_rdma 2507c478bd9Sstevel@tonic-gate }; 2517c478bd9Sstevel@tonic-gate rpcvers_t nfs_versmin = NFS_VERSMIN_DEFAULT; 2527c478bd9Sstevel@tonic-gate rpcvers_t nfs_versmax = NFS_VERSMAX_DEFAULT; 2537c478bd9Sstevel@tonic-gate 2547c478bd9Sstevel@tonic-gate /* 2557c478bd9Sstevel@tonic-gate * Used to track the state of the server so that initialization 2567c478bd9Sstevel@tonic-gate * can be done properly. 2577c478bd9Sstevel@tonic-gate */ 2587c478bd9Sstevel@tonic-gate typedef enum { 2597c478bd9Sstevel@tonic-gate NFS_SERVER_STOPPED, /* server state destroyed */ 2607c478bd9Sstevel@tonic-gate NFS_SERVER_STOPPING, /* server state being destroyed */ 2617c478bd9Sstevel@tonic-gate NFS_SERVER_RUNNING, 2627c478bd9Sstevel@tonic-gate NFS_SERVER_QUIESCED, /* server state preserved */ 2637c478bd9Sstevel@tonic-gate NFS_SERVER_OFFLINE /* server pool offline */ 2647c478bd9Sstevel@tonic-gate } nfs_server_running_t; 2657c478bd9Sstevel@tonic-gate 2667c478bd9Sstevel@tonic-gate static nfs_server_running_t nfs_server_upordown; 2677c478bd9Sstevel@tonic-gate static kmutex_t nfs_server_upordown_lock; 2687c478bd9Sstevel@tonic-gate static kcondvar_t nfs_server_upordown_cv; 2697c478bd9Sstevel@tonic-gate 270cee86682Scalum /* 271cee86682Scalum * DSS: distributed stable storage 272cee86682Scalum * lists of all DSS paths: current, and before last warmstart 273cee86682Scalum */ 274cee86682Scalum nvlist_t *rfs4_dss_paths, *rfs4_dss_oldpaths; 275cee86682Scalum 276c93d332cSDan McDonald int rfs4_dispatch(struct rpcdisp *, struct svc_req *, SVCXPRT *, char *); 2777d12f3bcSmaheshvs bool_t rfs4_minorvers_mismatch(struct svc_req *, SVCXPRT *, void *); 278d9ad96c1Srg137905 2797c478bd9Sstevel@tonic-gate /* 2807c478bd9Sstevel@tonic-gate * RDMA wait variables. 2817c478bd9Sstevel@tonic-gate */ 2827c478bd9Sstevel@tonic-gate static kcondvar_t rdma_wait_cv; 2837c478bd9Sstevel@tonic-gate static kmutex_t rdma_wait_mutex; 2847c478bd9Sstevel@tonic-gate 2857c478bd9Sstevel@tonic-gate /* 2867c478bd9Sstevel@tonic-gate * Will be called at the point the server pool is being unregistered 2877c478bd9Sstevel@tonic-gate * from the pool list. From that point onwards, the pool is waiting 2887c478bd9Sstevel@tonic-gate * to be drained and as such the server state is stale and pertains 2897c478bd9Sstevel@tonic-gate * to the old instantiation of the NFS server pool. 2907c478bd9Sstevel@tonic-gate */ 2917c478bd9Sstevel@tonic-gate void 2927c478bd9Sstevel@tonic-gate nfs_srv_offline(void) 2937c478bd9Sstevel@tonic-gate { 2947c478bd9Sstevel@tonic-gate mutex_enter(&nfs_server_upordown_lock); 2957c478bd9Sstevel@tonic-gate if (nfs_server_upordown == NFS_SERVER_RUNNING) { 2967c478bd9Sstevel@tonic-gate nfs_server_upordown = NFS_SERVER_OFFLINE; 2977c478bd9Sstevel@tonic-gate } 2987c478bd9Sstevel@tonic-gate mutex_exit(&nfs_server_upordown_lock); 2997c478bd9Sstevel@tonic-gate } 3007c478bd9Sstevel@tonic-gate 3017c478bd9Sstevel@tonic-gate /* 3027c478bd9Sstevel@tonic-gate * Will be called at the point the server pool is being destroyed so 3037c478bd9Sstevel@tonic-gate * all transports have been closed and no service threads are in 3047c478bd9Sstevel@tonic-gate * existence. 3057c478bd9Sstevel@tonic-gate * 3067c478bd9Sstevel@tonic-gate * If we quiesce the server, we're shutting it down without destroying the 3077c478bd9Sstevel@tonic-gate * server state. This allows it to warm start subsequently. 3087c478bd9Sstevel@tonic-gate */ 3097c478bd9Sstevel@tonic-gate void 3107c478bd9Sstevel@tonic-gate nfs_srv_stop_all(void) 3117c478bd9Sstevel@tonic-gate { 3127c478bd9Sstevel@tonic-gate int quiesce = 0; 3137c478bd9Sstevel@tonic-gate nfs_srv_shutdown_all(quiesce); 3147c478bd9Sstevel@tonic-gate } 3157c478bd9Sstevel@tonic-gate 3167c478bd9Sstevel@tonic-gate /* 3177c478bd9Sstevel@tonic-gate * This alternative shutdown routine can be requested via nfssys() 3187c478bd9Sstevel@tonic-gate */ 3197c478bd9Sstevel@tonic-gate void 3207c478bd9Sstevel@tonic-gate nfs_srv_quiesce_all(void) 3217c478bd9Sstevel@tonic-gate { 3227c478bd9Sstevel@tonic-gate int quiesce = 1; 3237c478bd9Sstevel@tonic-gate nfs_srv_shutdown_all(quiesce); 3247c478bd9Sstevel@tonic-gate } 3257c478bd9Sstevel@tonic-gate 3267c478bd9Sstevel@tonic-gate static void 327*aafcd32bSMarcel Telka nfs_srv_shutdown_all(int quiesce) 328*aafcd32bSMarcel Telka { 3297c478bd9Sstevel@tonic-gate mutex_enter(&nfs_server_upordown_lock); 3307c478bd9Sstevel@tonic-gate if (quiesce) { 3317c478bd9Sstevel@tonic-gate if (nfs_server_upordown == NFS_SERVER_RUNNING || 3327c478bd9Sstevel@tonic-gate nfs_server_upordown == NFS_SERVER_OFFLINE) { 3337c478bd9Sstevel@tonic-gate nfs_server_upordown = NFS_SERVER_QUIESCED; 3347c478bd9Sstevel@tonic-gate cv_signal(&nfs_server_upordown_cv); 335cee86682Scalum 336cee86682Scalum /* reset DSS state, for subsequent warm restart */ 337cee86682Scalum rfs4_dss_numnewpaths = 0; 338cee86682Scalum rfs4_dss_newpaths = NULL; 339cee86682Scalum 3407c478bd9Sstevel@tonic-gate cmn_err(CE_NOTE, "nfs_server: server is now quiesced; " 3417c478bd9Sstevel@tonic-gate "NFSv4 state has been preserved"); 3427c478bd9Sstevel@tonic-gate } 3437c478bd9Sstevel@tonic-gate } else { 3447c478bd9Sstevel@tonic-gate if (nfs_server_upordown == NFS_SERVER_OFFLINE) { 3457c478bd9Sstevel@tonic-gate nfs_server_upordown = NFS_SERVER_STOPPING; 3467c478bd9Sstevel@tonic-gate mutex_exit(&nfs_server_upordown_lock); 3477c478bd9Sstevel@tonic-gate rfs4_state_fini(); 348d9ad96c1Srg137905 rfs4_fini_drc(nfs4_drc); 3497c478bd9Sstevel@tonic-gate mutex_enter(&nfs_server_upordown_lock); 3507c478bd9Sstevel@tonic-gate nfs_server_upordown = NFS_SERVER_STOPPED; 3517c478bd9Sstevel@tonic-gate cv_signal(&nfs_server_upordown_cv); 3527c478bd9Sstevel@tonic-gate } 3537c478bd9Sstevel@tonic-gate } 3547c478bd9Sstevel@tonic-gate mutex_exit(&nfs_server_upordown_lock); 3557c478bd9Sstevel@tonic-gate } 3567c478bd9Sstevel@tonic-gate 3577c478bd9Sstevel@tonic-gate static int 3587c478bd9Sstevel@tonic-gate nfs_srv_set_sc_versions(struct file *fp, SVC_CALLOUT_TABLE **sctpp, 3597c478bd9Sstevel@tonic-gate rpcvers_t versmin, rpcvers_t versmax) 3607c478bd9Sstevel@tonic-gate { 3617c478bd9Sstevel@tonic-gate struct strioctl strioc; 3627c478bd9Sstevel@tonic-gate struct T_info_ack tinfo; 3637c478bd9Sstevel@tonic-gate int error, retval; 3647c478bd9Sstevel@tonic-gate 3657c478bd9Sstevel@tonic-gate /* 3667c478bd9Sstevel@tonic-gate * Find out what type of transport this is. 3677c478bd9Sstevel@tonic-gate */ 3687c478bd9Sstevel@tonic-gate strioc.ic_cmd = TI_GETINFO; 3697c478bd9Sstevel@tonic-gate strioc.ic_timout = -1; 3707c478bd9Sstevel@tonic-gate strioc.ic_len = sizeof (tinfo); 3717c478bd9Sstevel@tonic-gate strioc.ic_dp = (char *)&tinfo; 3727c478bd9Sstevel@tonic-gate tinfo.PRIM_type = T_INFO_REQ; 3737c478bd9Sstevel@tonic-gate 3747c478bd9Sstevel@tonic-gate error = strioctl(fp->f_vnode, I_STR, (intptr_t)&strioc, 0, K_TO_K, 3757c478bd9Sstevel@tonic-gate CRED(), &retval); 3767c478bd9Sstevel@tonic-gate if (error || retval) 3777c478bd9Sstevel@tonic-gate return (error); 3787c478bd9Sstevel@tonic-gate 3797c478bd9Sstevel@tonic-gate /* 3807c478bd9Sstevel@tonic-gate * Based on our query of the transport type... 3817c478bd9Sstevel@tonic-gate * 3827c478bd9Sstevel@tonic-gate * Reset the min/max versions based on the caller's request 3837c478bd9Sstevel@tonic-gate * NOTE: This assumes that NFS_PROGRAM is first in the array!! 3847c478bd9Sstevel@tonic-gate * And the second entry is the NFS_ACL_PROGRAM. 3857c478bd9Sstevel@tonic-gate */ 3867c478bd9Sstevel@tonic-gate switch (tinfo.SERV_type) { 3877c478bd9Sstevel@tonic-gate case T_CLTS: 3887c478bd9Sstevel@tonic-gate if (versmax == NFS_V4) 3897c478bd9Sstevel@tonic-gate return (EINVAL); 3907c478bd9Sstevel@tonic-gate __nfs_sc_clts[0].sc_versmin = versmin; 3917c478bd9Sstevel@tonic-gate __nfs_sc_clts[0].sc_versmax = versmax; 3927c478bd9Sstevel@tonic-gate __nfs_sc_clts[1].sc_versmin = versmin; 3937c478bd9Sstevel@tonic-gate __nfs_sc_clts[1].sc_versmax = versmax; 3947c478bd9Sstevel@tonic-gate *sctpp = &nfs_sct_clts; 3957c478bd9Sstevel@tonic-gate break; 3967c478bd9Sstevel@tonic-gate case T_COTS: 3977c478bd9Sstevel@tonic-gate case T_COTS_ORD: 3987c478bd9Sstevel@tonic-gate __nfs_sc_cots[0].sc_versmin = versmin; 3997c478bd9Sstevel@tonic-gate __nfs_sc_cots[0].sc_versmax = versmax; 4007c478bd9Sstevel@tonic-gate /* For the NFS_ACL program, check the max version */ 4017c478bd9Sstevel@tonic-gate if (versmax > NFS_ACL_VERSMAX) 4027c478bd9Sstevel@tonic-gate versmax = NFS_ACL_VERSMAX; 4037c478bd9Sstevel@tonic-gate __nfs_sc_cots[1].sc_versmin = versmin; 4047c478bd9Sstevel@tonic-gate __nfs_sc_cots[1].sc_versmax = versmax; 4057c478bd9Sstevel@tonic-gate *sctpp = &nfs_sct_cots; 4067c478bd9Sstevel@tonic-gate break; 4077c478bd9Sstevel@tonic-gate default: 4087c478bd9Sstevel@tonic-gate error = EINVAL; 4097c478bd9Sstevel@tonic-gate } 4107c478bd9Sstevel@tonic-gate 4117c478bd9Sstevel@tonic-gate return (error); 4127c478bd9Sstevel@tonic-gate } 4137c478bd9Sstevel@tonic-gate 4147c478bd9Sstevel@tonic-gate /* 4157c478bd9Sstevel@tonic-gate * NFS Server system call. 4167c478bd9Sstevel@tonic-gate * Does all of the work of running a NFS server. 4177c478bd9Sstevel@tonic-gate * uap->fd is the fd of an open transport provider 4187c478bd9Sstevel@tonic-gate */ 4197c478bd9Sstevel@tonic-gate int 4207c478bd9Sstevel@tonic-gate nfs_svc(struct nfs_svc_args *arg, model_t model) 4217c478bd9Sstevel@tonic-gate { 4227c478bd9Sstevel@tonic-gate file_t *fp; 4237c478bd9Sstevel@tonic-gate SVCMASTERXPRT *xprt; 4247c478bd9Sstevel@tonic-gate int error; 4257c478bd9Sstevel@tonic-gate int readsize; 4267c478bd9Sstevel@tonic-gate char buf[KNC_STRSIZE]; 4277c478bd9Sstevel@tonic-gate size_t len; 4287c478bd9Sstevel@tonic-gate STRUCT_HANDLE(nfs_svc_args, uap); 4297c478bd9Sstevel@tonic-gate struct netbuf addrmask; 4307c478bd9Sstevel@tonic-gate SVC_CALLOUT_TABLE *sctp = NULL; 4317c478bd9Sstevel@tonic-gate 4327c478bd9Sstevel@tonic-gate #ifdef lint 4337c478bd9Sstevel@tonic-gate model = model; /* STRUCT macros don't always refer to it */ 4347c478bd9Sstevel@tonic-gate #endif 4357c478bd9Sstevel@tonic-gate 4367c478bd9Sstevel@tonic-gate STRUCT_SET_HANDLE(uap, model, arg); 4377c478bd9Sstevel@tonic-gate 4387c478bd9Sstevel@tonic-gate /* Check privileges in nfssys() */ 4397c478bd9Sstevel@tonic-gate 4407c478bd9Sstevel@tonic-gate if ((fp = getf(STRUCT_FGET(uap, fd))) == NULL) 4417c478bd9Sstevel@tonic-gate return (EBADF); 4427c478bd9Sstevel@tonic-gate 4437c478bd9Sstevel@tonic-gate /* 4447c478bd9Sstevel@tonic-gate * Set read buffer size to rsize 4457c478bd9Sstevel@tonic-gate * and add room for RPC headers. 4467c478bd9Sstevel@tonic-gate */ 4477c478bd9Sstevel@tonic-gate readsize = nfs3tsize() + (RPC_MAXDATASIZE - NFS_MAXDATA); 4487c478bd9Sstevel@tonic-gate if (readsize < RPC_MAXDATASIZE) 4497c478bd9Sstevel@tonic-gate readsize = RPC_MAXDATASIZE; 4507c478bd9Sstevel@tonic-gate 4517c478bd9Sstevel@tonic-gate error = copyinstr((const char *)STRUCT_FGETP(uap, netid), buf, 4527c478bd9Sstevel@tonic-gate KNC_STRSIZE, &len); 4537c478bd9Sstevel@tonic-gate if (error) { 4547c478bd9Sstevel@tonic-gate releasef(STRUCT_FGET(uap, fd)); 4557c478bd9Sstevel@tonic-gate return (error); 4567c478bd9Sstevel@tonic-gate } 4577c478bd9Sstevel@tonic-gate 4587c478bd9Sstevel@tonic-gate addrmask.len = STRUCT_FGET(uap, addrmask.len); 4597c478bd9Sstevel@tonic-gate addrmask.maxlen = STRUCT_FGET(uap, addrmask.maxlen); 4607c478bd9Sstevel@tonic-gate addrmask.buf = kmem_alloc(addrmask.maxlen, KM_SLEEP); 4617c478bd9Sstevel@tonic-gate error = copyin(STRUCT_FGETP(uap, addrmask.buf), addrmask.buf, 4627c478bd9Sstevel@tonic-gate addrmask.len); 4637c478bd9Sstevel@tonic-gate if (error) { 4647c478bd9Sstevel@tonic-gate releasef(STRUCT_FGET(uap, fd)); 4657c478bd9Sstevel@tonic-gate kmem_free(addrmask.buf, addrmask.maxlen); 4667c478bd9Sstevel@tonic-gate return (error); 4677c478bd9Sstevel@tonic-gate } 4687c478bd9Sstevel@tonic-gate 4697c478bd9Sstevel@tonic-gate nfs_versmin = STRUCT_FGET(uap, versmin); 4707c478bd9Sstevel@tonic-gate nfs_versmax = STRUCT_FGET(uap, versmax); 4717c478bd9Sstevel@tonic-gate 4727c478bd9Sstevel@tonic-gate /* Double check the vers min/max ranges */ 4737c478bd9Sstevel@tonic-gate if ((nfs_versmin > nfs_versmax) || 4747c478bd9Sstevel@tonic-gate (nfs_versmin < NFS_VERSMIN) || 4757c478bd9Sstevel@tonic-gate (nfs_versmax > NFS_VERSMAX)) { 4767c478bd9Sstevel@tonic-gate nfs_versmin = NFS_VERSMIN_DEFAULT; 4777c478bd9Sstevel@tonic-gate nfs_versmax = NFS_VERSMAX_DEFAULT; 4787c478bd9Sstevel@tonic-gate } 4797c478bd9Sstevel@tonic-gate 4807c478bd9Sstevel@tonic-gate if (error = 4817c478bd9Sstevel@tonic-gate nfs_srv_set_sc_versions(fp, &sctp, nfs_versmin, nfs_versmax)) { 4827c478bd9Sstevel@tonic-gate releasef(STRUCT_FGET(uap, fd)); 4837c478bd9Sstevel@tonic-gate kmem_free(addrmask.buf, addrmask.maxlen); 4847c478bd9Sstevel@tonic-gate return (error); 4857c478bd9Sstevel@tonic-gate } 4867c478bd9Sstevel@tonic-gate 4877c478bd9Sstevel@tonic-gate /* Initialize nfsv4 server */ 4887c478bd9Sstevel@tonic-gate if (nfs_versmax == (rpcvers_t)NFS_V4) 4897c478bd9Sstevel@tonic-gate rfs4_server_start(STRUCT_FGET(uap, delegation)); 4907c478bd9Sstevel@tonic-gate 4917c478bd9Sstevel@tonic-gate /* Create a transport handle. */ 4927c478bd9Sstevel@tonic-gate error = svc_tli_kcreate(fp, readsize, buf, &addrmask, &xprt, 4937c478bd9Sstevel@tonic-gate sctp, NULL, NFS_SVCPOOL_ID, TRUE); 4947c478bd9Sstevel@tonic-gate 4957c478bd9Sstevel@tonic-gate if (error) 4967c478bd9Sstevel@tonic-gate kmem_free(addrmask.buf, addrmask.maxlen); 4977c478bd9Sstevel@tonic-gate 4987c478bd9Sstevel@tonic-gate releasef(STRUCT_FGET(uap, fd)); 4997c478bd9Sstevel@tonic-gate 500cee86682Scalum /* HA-NFSv4: save the cluster nodeid */ 5017c478bd9Sstevel@tonic-gate if (cluster_bootflags & CLUSTER_BOOTED) 5027c478bd9Sstevel@tonic-gate lm_global_nlmid = clconf_get_nodeid(); 5037c478bd9Sstevel@tonic-gate 5047c478bd9Sstevel@tonic-gate return (error); 5057c478bd9Sstevel@tonic-gate } 5067c478bd9Sstevel@tonic-gate 5077c478bd9Sstevel@tonic-gate static void 5087c478bd9Sstevel@tonic-gate rfs4_server_start(int nfs4_srv_delegation) 5097c478bd9Sstevel@tonic-gate { 5107c478bd9Sstevel@tonic-gate /* 5117c478bd9Sstevel@tonic-gate * Determine if the server has previously been "started" and 5127c478bd9Sstevel@tonic-gate * if not, do the per instance initialization 5137c478bd9Sstevel@tonic-gate */ 5147c478bd9Sstevel@tonic-gate mutex_enter(&nfs_server_upordown_lock); 5157c478bd9Sstevel@tonic-gate 5167c478bd9Sstevel@tonic-gate if (nfs_server_upordown != NFS_SERVER_RUNNING) { 5177c478bd9Sstevel@tonic-gate /* Do we need to stop and wait on the previous server? */ 5187c478bd9Sstevel@tonic-gate while (nfs_server_upordown == NFS_SERVER_STOPPING || 5197c478bd9Sstevel@tonic-gate nfs_server_upordown == NFS_SERVER_OFFLINE) 5207c478bd9Sstevel@tonic-gate cv_wait(&nfs_server_upordown_cv, 5217c478bd9Sstevel@tonic-gate &nfs_server_upordown_lock); 5227c478bd9Sstevel@tonic-gate 5237c478bd9Sstevel@tonic-gate if (nfs_server_upordown != NFS_SERVER_RUNNING) { 5247c478bd9Sstevel@tonic-gate (void) svc_pool_control(NFS_SVCPOOL_ID, 5257c478bd9Sstevel@tonic-gate SVCPSET_UNREGISTER_PROC, (void *)&nfs_srv_offline); 5267c478bd9Sstevel@tonic-gate (void) svc_pool_control(NFS_SVCPOOL_ID, 5277c478bd9Sstevel@tonic-gate SVCPSET_SHUTDOWN_PROC, (void *)&nfs_srv_stop_all); 5287c478bd9Sstevel@tonic-gate 5297c478bd9Sstevel@tonic-gate /* is this an nfsd warm start? */ 5307c478bd9Sstevel@tonic-gate if (nfs_server_upordown == NFS_SERVER_QUIESCED) { 5317c478bd9Sstevel@tonic-gate cmn_err(CE_NOTE, "nfs_server: " 5327c478bd9Sstevel@tonic-gate "server was previously quiesced; " 5337c478bd9Sstevel@tonic-gate "existing NFSv4 state will be re-used"); 5347c478bd9Sstevel@tonic-gate 5357c478bd9Sstevel@tonic-gate /* 536cee86682Scalum * HA-NFSv4: this is also the signal 537cee86682Scalum * that a Resource Group failover has 538cee86682Scalum * occurred. 5397c478bd9Sstevel@tonic-gate */ 54097669b90Scalum if (cluster_bootflags & CLUSTER_BOOTED) 541cee86682Scalum hanfsv4_failover(); 5427c478bd9Sstevel@tonic-gate } else { 543cee86682Scalum /* cold start */ 5447c478bd9Sstevel@tonic-gate rfs4_state_init(); 545d9ad96c1Srg137905 nfs4_drc = rfs4_init_drc(nfs4_drc_max, 54648a34407Srmesta nfs4_drc_hash); 5477c478bd9Sstevel@tonic-gate } 5487c478bd9Sstevel@tonic-gate 5497c478bd9Sstevel@tonic-gate /* 5507c478bd9Sstevel@tonic-gate * Check to see if delegation is to be 5517c478bd9Sstevel@tonic-gate * enabled at the server 5527c478bd9Sstevel@tonic-gate */ 5537c478bd9Sstevel@tonic-gate if (nfs4_srv_delegation != FALSE) 5547c478bd9Sstevel@tonic-gate rfs4_set_deleg_policy(SRV_NORMAL_DELEGATE); 5557c478bd9Sstevel@tonic-gate 5567c478bd9Sstevel@tonic-gate nfs_server_upordown = NFS_SERVER_RUNNING; 5577c478bd9Sstevel@tonic-gate } 5587c478bd9Sstevel@tonic-gate cv_signal(&nfs_server_upordown_cv); 5597c478bd9Sstevel@tonic-gate } 5607c478bd9Sstevel@tonic-gate mutex_exit(&nfs_server_upordown_lock); 5617c478bd9Sstevel@tonic-gate } 5627c478bd9Sstevel@tonic-gate 5637c478bd9Sstevel@tonic-gate /* 5647c478bd9Sstevel@tonic-gate * If RDMA device available, 5657c478bd9Sstevel@tonic-gate * start RDMA listener. 5667c478bd9Sstevel@tonic-gate */ 5677c478bd9Sstevel@tonic-gate int 5687c478bd9Sstevel@tonic-gate rdma_start(struct rdma_svc_args *rsa) 5697c478bd9Sstevel@tonic-gate { 5707c478bd9Sstevel@tonic-gate int error; 5717c478bd9Sstevel@tonic-gate rdma_xprt_group_t started_rdma_xprts; 57251f34d4bSRajkumar Sivaprakasam rdma_stat stat; 57351f34d4bSRajkumar Sivaprakasam int svc_state = 0; 5747c478bd9Sstevel@tonic-gate 5757c478bd9Sstevel@tonic-gate /* Double check the vers min/max ranges */ 5767c478bd9Sstevel@tonic-gate if ((rsa->nfs_versmin > rsa->nfs_versmax) || 5777c478bd9Sstevel@tonic-gate (rsa->nfs_versmin < NFS_VERSMIN) || 5787c478bd9Sstevel@tonic-gate (rsa->nfs_versmax > NFS_VERSMAX)) { 5797c478bd9Sstevel@tonic-gate rsa->nfs_versmin = NFS_VERSMIN_DEFAULT; 5807c478bd9Sstevel@tonic-gate rsa->nfs_versmax = NFS_VERSMAX_DEFAULT; 5817c478bd9Sstevel@tonic-gate } 5827c478bd9Sstevel@tonic-gate nfs_versmin = rsa->nfs_versmin; 5837c478bd9Sstevel@tonic-gate nfs_versmax = rsa->nfs_versmax; 5847c478bd9Sstevel@tonic-gate 5857c478bd9Sstevel@tonic-gate /* Set the versions in the callout table */ 5867c478bd9Sstevel@tonic-gate __nfs_sc_rdma[0].sc_versmin = rsa->nfs_versmin; 5877c478bd9Sstevel@tonic-gate __nfs_sc_rdma[0].sc_versmax = rsa->nfs_versmax; 5887c478bd9Sstevel@tonic-gate /* For the NFS_ACL program, check the max version */ 5897c478bd9Sstevel@tonic-gate __nfs_sc_rdma[1].sc_versmin = rsa->nfs_versmin; 5907c478bd9Sstevel@tonic-gate if (rsa->nfs_versmax > NFS_ACL_VERSMAX) 5917c478bd9Sstevel@tonic-gate __nfs_sc_rdma[1].sc_versmax = NFS_ACL_VERSMAX; 5927c478bd9Sstevel@tonic-gate else 5937c478bd9Sstevel@tonic-gate __nfs_sc_rdma[1].sc_versmax = rsa->nfs_versmax; 5947c478bd9Sstevel@tonic-gate 5957c478bd9Sstevel@tonic-gate /* Initialize nfsv4 server */ 5967c478bd9Sstevel@tonic-gate if (rsa->nfs_versmax == (rpcvers_t)NFS_V4) 5977c478bd9Sstevel@tonic-gate rfs4_server_start(rsa->delegation); 5987c478bd9Sstevel@tonic-gate 5997c478bd9Sstevel@tonic-gate started_rdma_xprts.rtg_count = 0; 6007c478bd9Sstevel@tonic-gate started_rdma_xprts.rtg_listhead = NULL; 6017c478bd9Sstevel@tonic-gate started_rdma_xprts.rtg_poolid = rsa->poolid; 60251f34d4bSRajkumar Sivaprakasam 60351f34d4bSRajkumar Sivaprakasam restart: 6047c478bd9Sstevel@tonic-gate error = svc_rdma_kcreate(rsa->netid, &nfs_sct_rdma, rsa->poolid, 6057c478bd9Sstevel@tonic-gate &started_rdma_xprts); 6067c478bd9Sstevel@tonic-gate 60751f34d4bSRajkumar Sivaprakasam svc_state = !error; 60851f34d4bSRajkumar Sivaprakasam 60951f34d4bSRajkumar Sivaprakasam while (!error) { 61051f34d4bSRajkumar Sivaprakasam 61151f34d4bSRajkumar Sivaprakasam /* 61251f34d4bSRajkumar Sivaprakasam * wait till either interrupted by a signal on 61351f34d4bSRajkumar Sivaprakasam * nfs service stop/restart or signalled by a 61451f34d4bSRajkumar Sivaprakasam * rdma plugin attach/detatch. 61551f34d4bSRajkumar Sivaprakasam */ 61651f34d4bSRajkumar Sivaprakasam 61751f34d4bSRajkumar Sivaprakasam stat = rdma_kwait(); 61851f34d4bSRajkumar Sivaprakasam 61951f34d4bSRajkumar Sivaprakasam /* 62051f34d4bSRajkumar Sivaprakasam * stop services if running -- either on a HCA detach event 62151f34d4bSRajkumar Sivaprakasam * or if the nfs service is stopped/restarted. 62251f34d4bSRajkumar Sivaprakasam */ 62351f34d4bSRajkumar Sivaprakasam 62451f34d4bSRajkumar Sivaprakasam if ((stat == RDMA_HCA_DETACH || stat == RDMA_INTR) && 62551f34d4bSRajkumar Sivaprakasam svc_state) { 62651f34d4bSRajkumar Sivaprakasam rdma_stop(&started_rdma_xprts); 62751f34d4bSRajkumar Sivaprakasam svc_state = 0; 6287c478bd9Sstevel@tonic-gate } 62951f34d4bSRajkumar Sivaprakasam 63051f34d4bSRajkumar Sivaprakasam /* 63151f34d4bSRajkumar Sivaprakasam * nfs service stop/restart, break out of the 63251f34d4bSRajkumar Sivaprakasam * wait loop and return; 63351f34d4bSRajkumar Sivaprakasam */ 63451f34d4bSRajkumar Sivaprakasam if (stat == RDMA_INTR) 63551f34d4bSRajkumar Sivaprakasam return (0); 63651f34d4bSRajkumar Sivaprakasam 63751f34d4bSRajkumar Sivaprakasam /* 63851f34d4bSRajkumar Sivaprakasam * restart stopped services on a HCA attach event 63951f34d4bSRajkumar Sivaprakasam * (if not already running) 64051f34d4bSRajkumar Sivaprakasam */ 64151f34d4bSRajkumar Sivaprakasam 64251f34d4bSRajkumar Sivaprakasam if ((stat == RDMA_HCA_ATTACH) && (svc_state == 0)) 64351f34d4bSRajkumar Sivaprakasam goto restart; 64451f34d4bSRajkumar Sivaprakasam 64551f34d4bSRajkumar Sivaprakasam /* 64651f34d4bSRajkumar Sivaprakasam * loop until a nfs service stop/restart 64751f34d4bSRajkumar Sivaprakasam */ 6487c478bd9Sstevel@tonic-gate } 6497c478bd9Sstevel@tonic-gate 6507c478bd9Sstevel@tonic-gate return (error); 6517c478bd9Sstevel@tonic-gate } 6527c478bd9Sstevel@tonic-gate 6537c478bd9Sstevel@tonic-gate /* ARGSUSED */ 654d9ad96c1Srg137905 void 6555cb0d679SMarcel Telka rpc_null(caddr_t *argp, caddr_t *resp, struct exportinfo *exi, 6565cb0d679SMarcel Telka struct svc_req *req, cred_t *cr, bool_t ro) 6577c478bd9Sstevel@tonic-gate { 6587c478bd9Sstevel@tonic-gate } 6597c478bd9Sstevel@tonic-gate 6607c478bd9Sstevel@tonic-gate /* ARGSUSED */ 661e1adf50cSahl void 662e1adf50cSahl rpc_null_v3(caddr_t *argp, caddr_t *resp, struct exportinfo *exi, 6635cb0d679SMarcel Telka struct svc_req *req, cred_t *cr, bool_t ro) 664e1adf50cSahl { 665e1adf50cSahl DTRACE_NFSV3_3(op__null__start, struct svc_req *, req, 666e1adf50cSahl cred_t *, cr, vnode_t *, NULL); 667e1adf50cSahl DTRACE_NFSV3_3(op__null__done, struct svc_req *, req, 668e1adf50cSahl cred_t *, cr, vnode_t *, NULL); 669e1adf50cSahl } 670e1adf50cSahl 671e1adf50cSahl /* ARGSUSED */ 6727c478bd9Sstevel@tonic-gate static void 6735cb0d679SMarcel Telka rfs_error(caddr_t *argp, caddr_t *resp, struct exportinfo *exi, 6745cb0d679SMarcel Telka struct svc_req *req, cred_t *cr, bool_t ro) 6757c478bd9Sstevel@tonic-gate { 6767c478bd9Sstevel@tonic-gate /* return (EOPNOTSUPP); */ 6777c478bd9Sstevel@tonic-gate } 6787c478bd9Sstevel@tonic-gate 6797c478bd9Sstevel@tonic-gate static void 6807c478bd9Sstevel@tonic-gate nullfree(void) 6817c478bd9Sstevel@tonic-gate { 6827c478bd9Sstevel@tonic-gate } 6837c478bd9Sstevel@tonic-gate 6847c478bd9Sstevel@tonic-gate static char *rfscallnames_v2[] = { 6857c478bd9Sstevel@tonic-gate "RFS2_NULL", 6867c478bd9Sstevel@tonic-gate "RFS2_GETATTR", 6877c478bd9Sstevel@tonic-gate "RFS2_SETATTR", 6887c478bd9Sstevel@tonic-gate "RFS2_ROOT", 6897c478bd9Sstevel@tonic-gate "RFS2_LOOKUP", 6907c478bd9Sstevel@tonic-gate "RFS2_READLINK", 6917c478bd9Sstevel@tonic-gate "RFS2_READ", 6927c478bd9Sstevel@tonic-gate "RFS2_WRITECACHE", 6937c478bd9Sstevel@tonic-gate "RFS2_WRITE", 6947c478bd9Sstevel@tonic-gate "RFS2_CREATE", 6957c478bd9Sstevel@tonic-gate "RFS2_REMOVE", 6967c478bd9Sstevel@tonic-gate "RFS2_RENAME", 6977c478bd9Sstevel@tonic-gate "RFS2_LINK", 6987c478bd9Sstevel@tonic-gate "RFS2_SYMLINK", 6997c478bd9Sstevel@tonic-gate "RFS2_MKDIR", 7007c478bd9Sstevel@tonic-gate "RFS2_RMDIR", 7017c478bd9Sstevel@tonic-gate "RFS2_READDIR", 7027c478bd9Sstevel@tonic-gate "RFS2_STATFS" 7037c478bd9Sstevel@tonic-gate }; 7047c478bd9Sstevel@tonic-gate 7057c478bd9Sstevel@tonic-gate static struct rpcdisp rfsdisptab_v2[] = { 7067c478bd9Sstevel@tonic-gate /* 7077c478bd9Sstevel@tonic-gate * NFS VERSION 2 7087c478bd9Sstevel@tonic-gate */ 7097c478bd9Sstevel@tonic-gate 7107c478bd9Sstevel@tonic-gate /* RFS_NULL = 0 */ 7117c478bd9Sstevel@tonic-gate {rpc_null, 7127c478bd9Sstevel@tonic-gate xdr_void, NULL_xdrproc_t, 0, 7137c478bd9Sstevel@tonic-gate xdr_void, NULL_xdrproc_t, 0, 7147c478bd9Sstevel@tonic-gate nullfree, RPC_IDEMPOTENT, 715d9ad96c1Srg137905 0}, 7167c478bd9Sstevel@tonic-gate 7177c478bd9Sstevel@tonic-gate /* RFS_GETATTR = 1 */ 7187c478bd9Sstevel@tonic-gate {rfs_getattr, 7197c478bd9Sstevel@tonic-gate xdr_fhandle, xdr_fastfhandle, sizeof (fhandle_t), 7207c478bd9Sstevel@tonic-gate xdr_attrstat, xdr_fastattrstat, sizeof (struct nfsattrstat), 7217c478bd9Sstevel@tonic-gate nullfree, RPC_IDEMPOTENT|RPC_ALLOWANON|RPC_MAPRESP, 722d9ad96c1Srg137905 rfs_getattr_getfh}, 7237c478bd9Sstevel@tonic-gate 7247c478bd9Sstevel@tonic-gate /* RFS_SETATTR = 2 */ 7257c478bd9Sstevel@tonic-gate {rfs_setattr, 7267c478bd9Sstevel@tonic-gate xdr_saargs, NULL_xdrproc_t, sizeof (struct nfssaargs), 7277c478bd9Sstevel@tonic-gate xdr_attrstat, xdr_fastattrstat, sizeof (struct nfsattrstat), 7287c478bd9Sstevel@tonic-gate nullfree, RPC_MAPRESP, 729d9ad96c1Srg137905 rfs_setattr_getfh}, 7307c478bd9Sstevel@tonic-gate 7317c478bd9Sstevel@tonic-gate /* RFS_ROOT = 3 *** NO LONGER SUPPORTED *** */ 7327c478bd9Sstevel@tonic-gate {rfs_error, 7337c478bd9Sstevel@tonic-gate xdr_void, NULL_xdrproc_t, 0, 7347c478bd9Sstevel@tonic-gate xdr_void, NULL_xdrproc_t, 0, 7357c478bd9Sstevel@tonic-gate nullfree, RPC_IDEMPOTENT, 736d9ad96c1Srg137905 0}, 7377c478bd9Sstevel@tonic-gate 7387c478bd9Sstevel@tonic-gate /* RFS_LOOKUP = 4 */ 7397c478bd9Sstevel@tonic-gate {rfs_lookup, 7407c478bd9Sstevel@tonic-gate xdr_diropargs, NULL_xdrproc_t, sizeof (struct nfsdiropargs), 7417c478bd9Sstevel@tonic-gate xdr_diropres, xdr_fastdiropres, sizeof (struct nfsdiropres), 7427c478bd9Sstevel@tonic-gate nullfree, RPC_IDEMPOTENT|RPC_MAPRESP|RPC_PUBLICFH_OK, 743d9ad96c1Srg137905 rfs_lookup_getfh}, 7447c478bd9Sstevel@tonic-gate 7457c478bd9Sstevel@tonic-gate /* RFS_READLINK = 5 */ 7467c478bd9Sstevel@tonic-gate {rfs_readlink, 7477c478bd9Sstevel@tonic-gate xdr_fhandle, xdr_fastfhandle, sizeof (fhandle_t), 7487c478bd9Sstevel@tonic-gate xdr_rdlnres, NULL_xdrproc_t, sizeof (struct nfsrdlnres), 7497c478bd9Sstevel@tonic-gate rfs_rlfree, RPC_IDEMPOTENT, 750d9ad96c1Srg137905 rfs_readlink_getfh}, 7517c478bd9Sstevel@tonic-gate 7527c478bd9Sstevel@tonic-gate /* RFS_READ = 6 */ 7537c478bd9Sstevel@tonic-gate {rfs_read, 7547c478bd9Sstevel@tonic-gate xdr_readargs, NULL_xdrproc_t, sizeof (struct nfsreadargs), 7557c478bd9Sstevel@tonic-gate xdr_rdresult, NULL_xdrproc_t, sizeof (struct nfsrdresult), 7567c478bd9Sstevel@tonic-gate rfs_rdfree, RPC_IDEMPOTENT, 757d9ad96c1Srg137905 rfs_read_getfh}, 7587c478bd9Sstevel@tonic-gate 7597c478bd9Sstevel@tonic-gate /* RFS_WRITECACHE = 7 *** NO LONGER SUPPORTED *** */ 7607c478bd9Sstevel@tonic-gate {rfs_error, 7617c478bd9Sstevel@tonic-gate xdr_void, NULL_xdrproc_t, 0, 7627c478bd9Sstevel@tonic-gate xdr_void, NULL_xdrproc_t, 0, 7637c478bd9Sstevel@tonic-gate nullfree, RPC_IDEMPOTENT, 764d9ad96c1Srg137905 0}, 7657c478bd9Sstevel@tonic-gate 7667c478bd9Sstevel@tonic-gate /* RFS_WRITE = 8 */ 7677c478bd9Sstevel@tonic-gate {rfs_write, 7687c478bd9Sstevel@tonic-gate xdr_writeargs, NULL_xdrproc_t, sizeof (struct nfswriteargs), 7697c478bd9Sstevel@tonic-gate xdr_attrstat, xdr_fastattrstat, sizeof (struct nfsattrstat), 7707c478bd9Sstevel@tonic-gate nullfree, RPC_MAPRESP, 771d9ad96c1Srg137905 rfs_write_getfh}, 7727c478bd9Sstevel@tonic-gate 7737c478bd9Sstevel@tonic-gate /* RFS_CREATE = 9 */ 7747c478bd9Sstevel@tonic-gate {rfs_create, 7757c478bd9Sstevel@tonic-gate xdr_creatargs, NULL_xdrproc_t, sizeof (struct nfscreatargs), 7767c478bd9Sstevel@tonic-gate xdr_diropres, xdr_fastdiropres, sizeof (struct nfsdiropres), 7777c478bd9Sstevel@tonic-gate nullfree, RPC_MAPRESP, 778d9ad96c1Srg137905 rfs_create_getfh}, 7797c478bd9Sstevel@tonic-gate 7807c478bd9Sstevel@tonic-gate /* RFS_REMOVE = 10 */ 7817c478bd9Sstevel@tonic-gate {rfs_remove, 7827c478bd9Sstevel@tonic-gate xdr_diropargs, NULL_xdrproc_t, sizeof (struct nfsdiropargs), 7837c478bd9Sstevel@tonic-gate #ifdef _LITTLE_ENDIAN 7847c478bd9Sstevel@tonic-gate xdr_enum, xdr_fastenum, sizeof (enum nfsstat), 7857c478bd9Sstevel@tonic-gate #else 7867c478bd9Sstevel@tonic-gate xdr_enum, NULL_xdrproc_t, sizeof (enum nfsstat), 7877c478bd9Sstevel@tonic-gate #endif 7887c478bd9Sstevel@tonic-gate nullfree, RPC_MAPRESP, 789d9ad96c1Srg137905 rfs_remove_getfh}, 7907c478bd9Sstevel@tonic-gate 7917c478bd9Sstevel@tonic-gate /* RFS_RENAME = 11 */ 7927c478bd9Sstevel@tonic-gate {rfs_rename, 7937c478bd9Sstevel@tonic-gate xdr_rnmargs, NULL_xdrproc_t, sizeof (struct nfsrnmargs), 7947c478bd9Sstevel@tonic-gate #ifdef _LITTLE_ENDIAN 7957c478bd9Sstevel@tonic-gate xdr_enum, xdr_fastenum, sizeof (enum nfsstat), 7967c478bd9Sstevel@tonic-gate #else 7977c478bd9Sstevel@tonic-gate xdr_enum, NULL_xdrproc_t, sizeof (enum nfsstat), 7987c478bd9Sstevel@tonic-gate #endif 7997c478bd9Sstevel@tonic-gate nullfree, RPC_MAPRESP, 800d9ad96c1Srg137905 rfs_rename_getfh}, 8017c478bd9Sstevel@tonic-gate 8027c478bd9Sstevel@tonic-gate /* RFS_LINK = 12 */ 8037c478bd9Sstevel@tonic-gate {rfs_link, 8047c478bd9Sstevel@tonic-gate xdr_linkargs, NULL_xdrproc_t, sizeof (struct nfslinkargs), 8057c478bd9Sstevel@tonic-gate #ifdef _LITTLE_ENDIAN 8067c478bd9Sstevel@tonic-gate xdr_enum, xdr_fastenum, sizeof (enum nfsstat), 8077c478bd9Sstevel@tonic-gate #else 8087c478bd9Sstevel@tonic-gate xdr_enum, NULL_xdrproc_t, sizeof (enum nfsstat), 8097c478bd9Sstevel@tonic-gate #endif 8107c478bd9Sstevel@tonic-gate nullfree, RPC_MAPRESP, 811d9ad96c1Srg137905 rfs_link_getfh}, 8127c478bd9Sstevel@tonic-gate 8137c478bd9Sstevel@tonic-gate /* RFS_SYMLINK = 13 */ 8147c478bd9Sstevel@tonic-gate {rfs_symlink, 8157c478bd9Sstevel@tonic-gate xdr_slargs, NULL_xdrproc_t, sizeof (struct nfsslargs), 8167c478bd9Sstevel@tonic-gate #ifdef _LITTLE_ENDIAN 8177c478bd9Sstevel@tonic-gate xdr_enum, xdr_fastenum, sizeof (enum nfsstat), 8187c478bd9Sstevel@tonic-gate #else 8197c478bd9Sstevel@tonic-gate xdr_enum, NULL_xdrproc_t, sizeof (enum nfsstat), 8207c478bd9Sstevel@tonic-gate #endif 8217c478bd9Sstevel@tonic-gate nullfree, RPC_MAPRESP, 822d9ad96c1Srg137905 rfs_symlink_getfh}, 8237c478bd9Sstevel@tonic-gate 8247c478bd9Sstevel@tonic-gate /* RFS_MKDIR = 14 */ 8257c478bd9Sstevel@tonic-gate {rfs_mkdir, 8267c478bd9Sstevel@tonic-gate xdr_creatargs, NULL_xdrproc_t, sizeof (struct nfscreatargs), 8277c478bd9Sstevel@tonic-gate xdr_diropres, xdr_fastdiropres, sizeof (struct nfsdiropres), 8287c478bd9Sstevel@tonic-gate nullfree, RPC_MAPRESP, 829d9ad96c1Srg137905 rfs_mkdir_getfh}, 8307c478bd9Sstevel@tonic-gate 8317c478bd9Sstevel@tonic-gate /* RFS_RMDIR = 15 */ 8327c478bd9Sstevel@tonic-gate {rfs_rmdir, 8337c478bd9Sstevel@tonic-gate xdr_diropargs, NULL_xdrproc_t, sizeof (struct nfsdiropargs), 8347c478bd9Sstevel@tonic-gate #ifdef _LITTLE_ENDIAN 8357c478bd9Sstevel@tonic-gate xdr_enum, xdr_fastenum, sizeof (enum nfsstat), 8367c478bd9Sstevel@tonic-gate #else 8377c478bd9Sstevel@tonic-gate xdr_enum, NULL_xdrproc_t, sizeof (enum nfsstat), 8387c478bd9Sstevel@tonic-gate #endif 8397c478bd9Sstevel@tonic-gate nullfree, RPC_MAPRESP, 840d9ad96c1Srg137905 rfs_rmdir_getfh}, 8417c478bd9Sstevel@tonic-gate 8427c478bd9Sstevel@tonic-gate /* RFS_READDIR = 16 */ 8437c478bd9Sstevel@tonic-gate {rfs_readdir, 8447c478bd9Sstevel@tonic-gate xdr_rddirargs, NULL_xdrproc_t, sizeof (struct nfsrddirargs), 8457c478bd9Sstevel@tonic-gate xdr_putrddirres, NULL_xdrproc_t, sizeof (struct nfsrddirres), 8467c478bd9Sstevel@tonic-gate rfs_rddirfree, RPC_IDEMPOTENT, 847d9ad96c1Srg137905 rfs_readdir_getfh}, 8487c478bd9Sstevel@tonic-gate 8497c478bd9Sstevel@tonic-gate /* RFS_STATFS = 17 */ 8507c478bd9Sstevel@tonic-gate {rfs_statfs, 8517c478bd9Sstevel@tonic-gate xdr_fhandle, xdr_fastfhandle, sizeof (fhandle_t), 8527c478bd9Sstevel@tonic-gate xdr_statfs, xdr_faststatfs, sizeof (struct nfsstatfs), 8537c478bd9Sstevel@tonic-gate nullfree, RPC_IDEMPOTENT|RPC_ALLOWANON|RPC_MAPRESP, 854d9ad96c1Srg137905 rfs_statfs_getfh}, 8557c478bd9Sstevel@tonic-gate }; 8567c478bd9Sstevel@tonic-gate 8577c478bd9Sstevel@tonic-gate static char *rfscallnames_v3[] = { 8587c478bd9Sstevel@tonic-gate "RFS3_NULL", 8597c478bd9Sstevel@tonic-gate "RFS3_GETATTR", 8607c478bd9Sstevel@tonic-gate "RFS3_SETATTR", 8617c478bd9Sstevel@tonic-gate "RFS3_LOOKUP", 8627c478bd9Sstevel@tonic-gate "RFS3_ACCESS", 8637c478bd9Sstevel@tonic-gate "RFS3_READLINK", 8647c478bd9Sstevel@tonic-gate "RFS3_READ", 8657c478bd9Sstevel@tonic-gate "RFS3_WRITE", 8667c478bd9Sstevel@tonic-gate "RFS3_CREATE", 8677c478bd9Sstevel@tonic-gate "RFS3_MKDIR", 8687c478bd9Sstevel@tonic-gate "RFS3_SYMLINK", 8697c478bd9Sstevel@tonic-gate "RFS3_MKNOD", 8707c478bd9Sstevel@tonic-gate "RFS3_REMOVE", 8717c478bd9Sstevel@tonic-gate "RFS3_RMDIR", 8727c478bd9Sstevel@tonic-gate "RFS3_RENAME", 8737c478bd9Sstevel@tonic-gate "RFS3_LINK", 8747c478bd9Sstevel@tonic-gate "RFS3_READDIR", 8757c478bd9Sstevel@tonic-gate "RFS3_READDIRPLUS", 8767c478bd9Sstevel@tonic-gate "RFS3_FSSTAT", 8777c478bd9Sstevel@tonic-gate "RFS3_FSINFO", 8787c478bd9Sstevel@tonic-gate "RFS3_PATHCONF", 8797c478bd9Sstevel@tonic-gate "RFS3_COMMIT" 8807c478bd9Sstevel@tonic-gate }; 8817c478bd9Sstevel@tonic-gate 8827c478bd9Sstevel@tonic-gate static struct rpcdisp rfsdisptab_v3[] = { 8837c478bd9Sstevel@tonic-gate /* 8847c478bd9Sstevel@tonic-gate * NFS VERSION 3 8857c478bd9Sstevel@tonic-gate */ 8867c478bd9Sstevel@tonic-gate 8877c478bd9Sstevel@tonic-gate /* RFS_NULL = 0 */ 888e1adf50cSahl {rpc_null_v3, 8897c478bd9Sstevel@tonic-gate xdr_void, NULL_xdrproc_t, 0, 8907c478bd9Sstevel@tonic-gate xdr_void, NULL_xdrproc_t, 0, 8917c478bd9Sstevel@tonic-gate nullfree, RPC_IDEMPOTENT, 892d9ad96c1Srg137905 0}, 8937c478bd9Sstevel@tonic-gate 8947c478bd9Sstevel@tonic-gate /* RFS3_GETATTR = 1 */ 8957c478bd9Sstevel@tonic-gate {rfs3_getattr, 89627242a7cSthurlow xdr_nfs_fh3_server, NULL_xdrproc_t, sizeof (GETATTR3args), 8977c478bd9Sstevel@tonic-gate xdr_GETATTR3res, NULL_xdrproc_t, sizeof (GETATTR3res), 8987c478bd9Sstevel@tonic-gate nullfree, (RPC_IDEMPOTENT | RPC_ALLOWANON), 899d9ad96c1Srg137905 rfs3_getattr_getfh}, 9007c478bd9Sstevel@tonic-gate 9017c478bd9Sstevel@tonic-gate /* RFS3_SETATTR = 2 */ 9027c478bd9Sstevel@tonic-gate {rfs3_setattr, 9037c478bd9Sstevel@tonic-gate xdr_SETATTR3args, NULL_xdrproc_t, sizeof (SETATTR3args), 9047c478bd9Sstevel@tonic-gate xdr_SETATTR3res, NULL_xdrproc_t, sizeof (SETATTR3res), 9057c478bd9Sstevel@tonic-gate nullfree, 0, 906d9ad96c1Srg137905 rfs3_setattr_getfh}, 9077c478bd9Sstevel@tonic-gate 9087c478bd9Sstevel@tonic-gate /* RFS3_LOOKUP = 3 */ 9097c478bd9Sstevel@tonic-gate {rfs3_lookup, 9107c478bd9Sstevel@tonic-gate xdr_diropargs3, NULL_xdrproc_t, sizeof (LOOKUP3args), 9117c478bd9Sstevel@tonic-gate xdr_LOOKUP3res, NULL_xdrproc_t, sizeof (LOOKUP3res), 9127c478bd9Sstevel@tonic-gate nullfree, (RPC_IDEMPOTENT | RPC_PUBLICFH_OK), 913d9ad96c1Srg137905 rfs3_lookup_getfh}, 9147c478bd9Sstevel@tonic-gate 9157c478bd9Sstevel@tonic-gate /* RFS3_ACCESS = 4 */ 9167c478bd9Sstevel@tonic-gate {rfs3_access, 9177c478bd9Sstevel@tonic-gate xdr_ACCESS3args, NULL_xdrproc_t, sizeof (ACCESS3args), 9187c478bd9Sstevel@tonic-gate xdr_ACCESS3res, NULL_xdrproc_t, sizeof (ACCESS3res), 9197c478bd9Sstevel@tonic-gate nullfree, RPC_IDEMPOTENT, 920d9ad96c1Srg137905 rfs3_access_getfh}, 9217c478bd9Sstevel@tonic-gate 9227c478bd9Sstevel@tonic-gate /* RFS3_READLINK = 5 */ 9237c478bd9Sstevel@tonic-gate {rfs3_readlink, 92427242a7cSthurlow xdr_nfs_fh3_server, NULL_xdrproc_t, sizeof (READLINK3args), 9257c478bd9Sstevel@tonic-gate xdr_READLINK3res, NULL_xdrproc_t, sizeof (READLINK3res), 9267c478bd9Sstevel@tonic-gate rfs3_readlink_free, RPC_IDEMPOTENT, 927d9ad96c1Srg137905 rfs3_readlink_getfh}, 9287c478bd9Sstevel@tonic-gate 9297c478bd9Sstevel@tonic-gate /* RFS3_READ = 6 */ 9307c478bd9Sstevel@tonic-gate {rfs3_read, 9317c478bd9Sstevel@tonic-gate xdr_READ3args, NULL_xdrproc_t, sizeof (READ3args), 9327c478bd9Sstevel@tonic-gate xdr_READ3res, NULL_xdrproc_t, sizeof (READ3res), 9337c478bd9Sstevel@tonic-gate rfs3_read_free, RPC_IDEMPOTENT, 934d9ad96c1Srg137905 rfs3_read_getfh}, 9357c478bd9Sstevel@tonic-gate 9367c478bd9Sstevel@tonic-gate /* RFS3_WRITE = 7 */ 9377c478bd9Sstevel@tonic-gate {rfs3_write, 9387c478bd9Sstevel@tonic-gate xdr_WRITE3args, NULL_xdrproc_t, sizeof (WRITE3args), 9397c478bd9Sstevel@tonic-gate xdr_WRITE3res, NULL_xdrproc_t, sizeof (WRITE3res), 9407c478bd9Sstevel@tonic-gate nullfree, 0, 941d9ad96c1Srg137905 rfs3_write_getfh}, 9427c478bd9Sstevel@tonic-gate 9437c478bd9Sstevel@tonic-gate /* RFS3_CREATE = 8 */ 9447c478bd9Sstevel@tonic-gate {rfs3_create, 9457c478bd9Sstevel@tonic-gate xdr_CREATE3args, NULL_xdrproc_t, sizeof (CREATE3args), 9467c478bd9Sstevel@tonic-gate xdr_CREATE3res, NULL_xdrproc_t, sizeof (CREATE3res), 9477c478bd9Sstevel@tonic-gate nullfree, 0, 948d9ad96c1Srg137905 rfs3_create_getfh}, 9497c478bd9Sstevel@tonic-gate 9507c478bd9Sstevel@tonic-gate /* RFS3_MKDIR = 9 */ 9517c478bd9Sstevel@tonic-gate {rfs3_mkdir, 9527c478bd9Sstevel@tonic-gate xdr_MKDIR3args, NULL_xdrproc_t, sizeof (MKDIR3args), 9537c478bd9Sstevel@tonic-gate xdr_MKDIR3res, NULL_xdrproc_t, sizeof (MKDIR3res), 9547c478bd9Sstevel@tonic-gate nullfree, 0, 955d9ad96c1Srg137905 rfs3_mkdir_getfh}, 9567c478bd9Sstevel@tonic-gate 9577c478bd9Sstevel@tonic-gate /* RFS3_SYMLINK = 10 */ 9587c478bd9Sstevel@tonic-gate {rfs3_symlink, 9597c478bd9Sstevel@tonic-gate xdr_SYMLINK3args, NULL_xdrproc_t, sizeof (SYMLINK3args), 9607c478bd9Sstevel@tonic-gate xdr_SYMLINK3res, NULL_xdrproc_t, sizeof (SYMLINK3res), 9617c478bd9Sstevel@tonic-gate nullfree, 0, 962d9ad96c1Srg137905 rfs3_symlink_getfh}, 9637c478bd9Sstevel@tonic-gate 9647c478bd9Sstevel@tonic-gate /* RFS3_MKNOD = 11 */ 9657c478bd9Sstevel@tonic-gate {rfs3_mknod, 9667c478bd9Sstevel@tonic-gate xdr_MKNOD3args, NULL_xdrproc_t, sizeof (MKNOD3args), 9677c478bd9Sstevel@tonic-gate xdr_MKNOD3res, NULL_xdrproc_t, sizeof (MKNOD3res), 9687c478bd9Sstevel@tonic-gate nullfree, 0, 969d9ad96c1Srg137905 rfs3_mknod_getfh}, 9707c478bd9Sstevel@tonic-gate 9717c478bd9Sstevel@tonic-gate /* RFS3_REMOVE = 12 */ 9727c478bd9Sstevel@tonic-gate {rfs3_remove, 9737c478bd9Sstevel@tonic-gate xdr_diropargs3, NULL_xdrproc_t, sizeof (REMOVE3args), 9747c478bd9Sstevel@tonic-gate xdr_REMOVE3res, NULL_xdrproc_t, sizeof (REMOVE3res), 9757c478bd9Sstevel@tonic-gate nullfree, 0, 976d9ad96c1Srg137905 rfs3_remove_getfh}, 9777c478bd9Sstevel@tonic-gate 9787c478bd9Sstevel@tonic-gate /* RFS3_RMDIR = 13 */ 9797c478bd9Sstevel@tonic-gate {rfs3_rmdir, 9807c478bd9Sstevel@tonic-gate xdr_diropargs3, NULL_xdrproc_t, sizeof (RMDIR3args), 9817c478bd9Sstevel@tonic-gate xdr_RMDIR3res, NULL_xdrproc_t, sizeof (RMDIR3res), 9827c478bd9Sstevel@tonic-gate nullfree, 0, 983d9ad96c1Srg137905 rfs3_rmdir_getfh}, 9847c478bd9Sstevel@tonic-gate 9857c478bd9Sstevel@tonic-gate /* RFS3_RENAME = 14 */ 9867c478bd9Sstevel@tonic-gate {rfs3_rename, 9877c478bd9Sstevel@tonic-gate xdr_RENAME3args, NULL_xdrproc_t, sizeof (RENAME3args), 9887c478bd9Sstevel@tonic-gate xdr_RENAME3res, NULL_xdrproc_t, sizeof (RENAME3res), 9897c478bd9Sstevel@tonic-gate nullfree, 0, 990d9ad96c1Srg137905 rfs3_rename_getfh}, 9917c478bd9Sstevel@tonic-gate 9927c478bd9Sstevel@tonic-gate /* RFS3_LINK = 15 */ 9937c478bd9Sstevel@tonic-gate {rfs3_link, 9947c478bd9Sstevel@tonic-gate xdr_LINK3args, NULL_xdrproc_t, sizeof (LINK3args), 9957c478bd9Sstevel@tonic-gate xdr_LINK3res, NULL_xdrproc_t, sizeof (LINK3res), 9967c478bd9Sstevel@tonic-gate nullfree, 0, 997d9ad96c1Srg137905 rfs3_link_getfh}, 9987c478bd9Sstevel@tonic-gate 9997c478bd9Sstevel@tonic-gate /* RFS3_READDIR = 16 */ 10007c478bd9Sstevel@tonic-gate {rfs3_readdir, 10017c478bd9Sstevel@tonic-gate xdr_READDIR3args, NULL_xdrproc_t, sizeof (READDIR3args), 10027c478bd9Sstevel@tonic-gate xdr_READDIR3res, NULL_xdrproc_t, sizeof (READDIR3res), 10037c478bd9Sstevel@tonic-gate rfs3_readdir_free, RPC_IDEMPOTENT, 1004d9ad96c1Srg137905 rfs3_readdir_getfh}, 10057c478bd9Sstevel@tonic-gate 10067c478bd9Sstevel@tonic-gate /* RFS3_READDIRPLUS = 17 */ 10077c478bd9Sstevel@tonic-gate {rfs3_readdirplus, 10087c478bd9Sstevel@tonic-gate xdr_READDIRPLUS3args, NULL_xdrproc_t, sizeof (READDIRPLUS3args), 10097c478bd9Sstevel@tonic-gate xdr_READDIRPLUS3res, NULL_xdrproc_t, sizeof (READDIRPLUS3res), 10107c478bd9Sstevel@tonic-gate rfs3_readdirplus_free, RPC_AVOIDWORK, 1011d9ad96c1Srg137905 rfs3_readdirplus_getfh}, 10127c478bd9Sstevel@tonic-gate 10137c478bd9Sstevel@tonic-gate /* RFS3_FSSTAT = 18 */ 10147c478bd9Sstevel@tonic-gate {rfs3_fsstat, 101527242a7cSthurlow xdr_nfs_fh3_server, NULL_xdrproc_t, sizeof (FSSTAT3args), 10167c478bd9Sstevel@tonic-gate xdr_FSSTAT3res, NULL_xdrproc_t, sizeof (FSSTAT3res), 10177c478bd9Sstevel@tonic-gate nullfree, RPC_IDEMPOTENT, 1018d9ad96c1Srg137905 rfs3_fsstat_getfh}, 10197c478bd9Sstevel@tonic-gate 10207c478bd9Sstevel@tonic-gate /* RFS3_FSINFO = 19 */ 10217c478bd9Sstevel@tonic-gate {rfs3_fsinfo, 102227242a7cSthurlow xdr_nfs_fh3_server, NULL_xdrproc_t, sizeof (FSINFO3args), 10237c478bd9Sstevel@tonic-gate xdr_FSINFO3res, NULL_xdrproc_t, sizeof (FSINFO3res), 10247c478bd9Sstevel@tonic-gate nullfree, RPC_IDEMPOTENT|RPC_ALLOWANON, 1025d9ad96c1Srg137905 rfs3_fsinfo_getfh}, 10267c478bd9Sstevel@tonic-gate 10277c478bd9Sstevel@tonic-gate /* RFS3_PATHCONF = 20 */ 10287c478bd9Sstevel@tonic-gate {rfs3_pathconf, 102927242a7cSthurlow xdr_nfs_fh3_server, NULL_xdrproc_t, sizeof (PATHCONF3args), 10307c478bd9Sstevel@tonic-gate xdr_PATHCONF3res, NULL_xdrproc_t, sizeof (PATHCONF3res), 10317c478bd9Sstevel@tonic-gate nullfree, RPC_IDEMPOTENT, 1032d9ad96c1Srg137905 rfs3_pathconf_getfh}, 10337c478bd9Sstevel@tonic-gate 10347c478bd9Sstevel@tonic-gate /* RFS3_COMMIT = 21 */ 10357c478bd9Sstevel@tonic-gate {rfs3_commit, 10367c478bd9Sstevel@tonic-gate xdr_COMMIT3args, NULL_xdrproc_t, sizeof (COMMIT3args), 10377c478bd9Sstevel@tonic-gate xdr_COMMIT3res, NULL_xdrproc_t, sizeof (COMMIT3res), 10387c478bd9Sstevel@tonic-gate nullfree, RPC_IDEMPOTENT, 1039d9ad96c1Srg137905 rfs3_commit_getfh}, 10407c478bd9Sstevel@tonic-gate }; 10417c478bd9Sstevel@tonic-gate 10427c478bd9Sstevel@tonic-gate static char *rfscallnames_v4[] = { 10437c478bd9Sstevel@tonic-gate "RFS4_NULL", 10447c478bd9Sstevel@tonic-gate "RFS4_COMPOUND", 10457c478bd9Sstevel@tonic-gate "RFS4_NULL", 10467c478bd9Sstevel@tonic-gate "RFS4_NULL", 10477c478bd9Sstevel@tonic-gate "RFS4_NULL", 10487c478bd9Sstevel@tonic-gate "RFS4_NULL", 10497c478bd9Sstevel@tonic-gate "RFS4_NULL", 10507c478bd9Sstevel@tonic-gate "RFS4_NULL", 10517c478bd9Sstevel@tonic-gate "RFS4_CREATE" 10527c478bd9Sstevel@tonic-gate }; 10537c478bd9Sstevel@tonic-gate 10547c478bd9Sstevel@tonic-gate static struct rpcdisp rfsdisptab_v4[] = { 10557c478bd9Sstevel@tonic-gate /* 10567c478bd9Sstevel@tonic-gate * NFS VERSION 4 10577c478bd9Sstevel@tonic-gate */ 10587c478bd9Sstevel@tonic-gate 10597c478bd9Sstevel@tonic-gate /* RFS_NULL = 0 */ 10607c478bd9Sstevel@tonic-gate {rpc_null, 10617c478bd9Sstevel@tonic-gate xdr_void, NULL_xdrproc_t, 0, 10627c478bd9Sstevel@tonic-gate xdr_void, NULL_xdrproc_t, 0, 1063d9ad96c1Srg137905 nullfree, RPC_IDEMPOTENT, 0}, 10647c478bd9Sstevel@tonic-gate 10657c478bd9Sstevel@tonic-gate /* RFS4_compound = 1 */ 10667c478bd9Sstevel@tonic-gate {rfs4_compound, 10677c46fb7fSek110237 xdr_COMPOUND4args_srv, NULL_xdrproc_t, sizeof (COMPOUND4args), 10687c46fb7fSek110237 xdr_COMPOUND4res_srv, NULL_xdrproc_t, sizeof (COMPOUND4res), 1069d9ad96c1Srg137905 rfs4_compound_free, 0, 0}, 10707c478bd9Sstevel@tonic-gate }; 10717c478bd9Sstevel@tonic-gate 10727c478bd9Sstevel@tonic-gate union rfs_args { 10737c478bd9Sstevel@tonic-gate /* 10747c478bd9Sstevel@tonic-gate * NFS VERSION 2 10757c478bd9Sstevel@tonic-gate */ 10767c478bd9Sstevel@tonic-gate 10777c478bd9Sstevel@tonic-gate /* RFS_NULL = 0 */ 10787c478bd9Sstevel@tonic-gate 10797c478bd9Sstevel@tonic-gate /* RFS_GETATTR = 1 */ 10807c478bd9Sstevel@tonic-gate fhandle_t nfs2_getattr_args; 10817c478bd9Sstevel@tonic-gate 10827c478bd9Sstevel@tonic-gate /* RFS_SETATTR = 2 */ 10837c478bd9Sstevel@tonic-gate struct nfssaargs nfs2_setattr_args; 10847c478bd9Sstevel@tonic-gate 10857c478bd9Sstevel@tonic-gate /* RFS_ROOT = 3 *** NO LONGER SUPPORTED *** */ 10867c478bd9Sstevel@tonic-gate 10877c478bd9Sstevel@tonic-gate /* RFS_LOOKUP = 4 */ 10887c478bd9Sstevel@tonic-gate struct nfsdiropargs nfs2_lookup_args; 10897c478bd9Sstevel@tonic-gate 10907c478bd9Sstevel@tonic-gate /* RFS_READLINK = 5 */ 10917c478bd9Sstevel@tonic-gate fhandle_t nfs2_readlink_args; 10927c478bd9Sstevel@tonic-gate 10937c478bd9Sstevel@tonic-gate /* RFS_READ = 6 */ 10947c478bd9Sstevel@tonic-gate struct nfsreadargs nfs2_read_args; 10957c478bd9Sstevel@tonic-gate 10967c478bd9Sstevel@tonic-gate /* RFS_WRITECACHE = 7 *** NO LONGER SUPPORTED *** */ 10977c478bd9Sstevel@tonic-gate 10987c478bd9Sstevel@tonic-gate /* RFS_WRITE = 8 */ 10997c478bd9Sstevel@tonic-gate struct nfswriteargs nfs2_write_args; 11007c478bd9Sstevel@tonic-gate 11017c478bd9Sstevel@tonic-gate /* RFS_CREATE = 9 */ 11027c478bd9Sstevel@tonic-gate struct nfscreatargs nfs2_create_args; 11037c478bd9Sstevel@tonic-gate 11047c478bd9Sstevel@tonic-gate /* RFS_REMOVE = 10 */ 11057c478bd9Sstevel@tonic-gate struct nfsdiropargs nfs2_remove_args; 11067c478bd9Sstevel@tonic-gate 11077c478bd9Sstevel@tonic-gate /* RFS_RENAME = 11 */ 11087c478bd9Sstevel@tonic-gate struct nfsrnmargs nfs2_rename_args; 11097c478bd9Sstevel@tonic-gate 11107c478bd9Sstevel@tonic-gate /* RFS_LINK = 12 */ 11117c478bd9Sstevel@tonic-gate struct nfslinkargs nfs2_link_args; 11127c478bd9Sstevel@tonic-gate 11137c478bd9Sstevel@tonic-gate /* RFS_SYMLINK = 13 */ 11147c478bd9Sstevel@tonic-gate struct nfsslargs nfs2_symlink_args; 11157c478bd9Sstevel@tonic-gate 11167c478bd9Sstevel@tonic-gate /* RFS_MKDIR = 14 */ 11177c478bd9Sstevel@tonic-gate struct nfscreatargs nfs2_mkdir_args; 11187c478bd9Sstevel@tonic-gate 11197c478bd9Sstevel@tonic-gate /* RFS_RMDIR = 15 */ 11207c478bd9Sstevel@tonic-gate struct nfsdiropargs nfs2_rmdir_args; 11217c478bd9Sstevel@tonic-gate 11227c478bd9Sstevel@tonic-gate /* RFS_READDIR = 16 */ 11237c478bd9Sstevel@tonic-gate struct nfsrddirargs nfs2_readdir_args; 11247c478bd9Sstevel@tonic-gate 11257c478bd9Sstevel@tonic-gate /* RFS_STATFS = 17 */ 11267c478bd9Sstevel@tonic-gate fhandle_t nfs2_statfs_args; 11277c478bd9Sstevel@tonic-gate 11287c478bd9Sstevel@tonic-gate /* 11297c478bd9Sstevel@tonic-gate * NFS VERSION 3 11307c478bd9Sstevel@tonic-gate */ 11317c478bd9Sstevel@tonic-gate 11327c478bd9Sstevel@tonic-gate /* RFS_NULL = 0 */ 11337c478bd9Sstevel@tonic-gate 11347c478bd9Sstevel@tonic-gate /* RFS3_GETATTR = 1 */ 11357c478bd9Sstevel@tonic-gate GETATTR3args nfs3_getattr_args; 11367c478bd9Sstevel@tonic-gate 11377c478bd9Sstevel@tonic-gate /* RFS3_SETATTR = 2 */ 11387c478bd9Sstevel@tonic-gate SETATTR3args nfs3_setattr_args; 11397c478bd9Sstevel@tonic-gate 11407c478bd9Sstevel@tonic-gate /* RFS3_LOOKUP = 3 */ 11417c478bd9Sstevel@tonic-gate LOOKUP3args nfs3_lookup_args; 11427c478bd9Sstevel@tonic-gate 11437c478bd9Sstevel@tonic-gate /* RFS3_ACCESS = 4 */ 11447c478bd9Sstevel@tonic-gate ACCESS3args nfs3_access_args; 11457c478bd9Sstevel@tonic-gate 11467c478bd9Sstevel@tonic-gate /* RFS3_READLINK = 5 */ 11477c478bd9Sstevel@tonic-gate READLINK3args nfs3_readlink_args; 11487c478bd9Sstevel@tonic-gate 11497c478bd9Sstevel@tonic-gate /* RFS3_READ = 6 */ 11507c478bd9Sstevel@tonic-gate READ3args nfs3_read_args; 11517c478bd9Sstevel@tonic-gate 11527c478bd9Sstevel@tonic-gate /* RFS3_WRITE = 7 */ 11537c478bd9Sstevel@tonic-gate WRITE3args nfs3_write_args; 11547c478bd9Sstevel@tonic-gate 11557c478bd9Sstevel@tonic-gate /* RFS3_CREATE = 8 */ 11567c478bd9Sstevel@tonic-gate CREATE3args nfs3_create_args; 11577c478bd9Sstevel@tonic-gate 11587c478bd9Sstevel@tonic-gate /* RFS3_MKDIR = 9 */ 11597c478bd9Sstevel@tonic-gate MKDIR3args nfs3_mkdir_args; 11607c478bd9Sstevel@tonic-gate 11617c478bd9Sstevel@tonic-gate /* RFS3_SYMLINK = 10 */ 11627c478bd9Sstevel@tonic-gate SYMLINK3args nfs3_symlink_args; 11637c478bd9Sstevel@tonic-gate 11647c478bd9Sstevel@tonic-gate /* RFS3_MKNOD = 11 */ 11657c478bd9Sstevel@tonic-gate MKNOD3args nfs3_mknod_args; 11667c478bd9Sstevel@tonic-gate 11677c478bd9Sstevel@tonic-gate /* RFS3_REMOVE = 12 */ 11687c478bd9Sstevel@tonic-gate REMOVE3args nfs3_remove_args; 11697c478bd9Sstevel@tonic-gate 11707c478bd9Sstevel@tonic-gate /* RFS3_RMDIR = 13 */ 11717c478bd9Sstevel@tonic-gate RMDIR3args nfs3_rmdir_args; 11727c478bd9Sstevel@tonic-gate 11737c478bd9Sstevel@tonic-gate /* RFS3_RENAME = 14 */ 11747c478bd9Sstevel@tonic-gate RENAME3args nfs3_rename_args; 11757c478bd9Sstevel@tonic-gate 11767c478bd9Sstevel@tonic-gate /* RFS3_LINK = 15 */ 11777c478bd9Sstevel@tonic-gate LINK3args nfs3_link_args; 11787c478bd9Sstevel@tonic-gate 11797c478bd9Sstevel@tonic-gate /* RFS3_READDIR = 16 */ 11807c478bd9Sstevel@tonic-gate READDIR3args nfs3_readdir_args; 11817c478bd9Sstevel@tonic-gate 11827c478bd9Sstevel@tonic-gate /* RFS3_READDIRPLUS = 17 */ 11837c478bd9Sstevel@tonic-gate READDIRPLUS3args nfs3_readdirplus_args; 11847c478bd9Sstevel@tonic-gate 11857c478bd9Sstevel@tonic-gate /* RFS3_FSSTAT = 18 */ 11867c478bd9Sstevel@tonic-gate FSSTAT3args nfs3_fsstat_args; 11877c478bd9Sstevel@tonic-gate 11887c478bd9Sstevel@tonic-gate /* RFS3_FSINFO = 19 */ 11897c478bd9Sstevel@tonic-gate FSINFO3args nfs3_fsinfo_args; 11907c478bd9Sstevel@tonic-gate 11917c478bd9Sstevel@tonic-gate /* RFS3_PATHCONF = 20 */ 11927c478bd9Sstevel@tonic-gate PATHCONF3args nfs3_pathconf_args; 11937c478bd9Sstevel@tonic-gate 11947c478bd9Sstevel@tonic-gate /* RFS3_COMMIT = 21 */ 11957c478bd9Sstevel@tonic-gate COMMIT3args nfs3_commit_args; 11967c478bd9Sstevel@tonic-gate 11977c478bd9Sstevel@tonic-gate /* 11987c478bd9Sstevel@tonic-gate * NFS VERSION 4 11997c478bd9Sstevel@tonic-gate */ 12007c478bd9Sstevel@tonic-gate 12017c478bd9Sstevel@tonic-gate /* RFS_NULL = 0 */ 12027c478bd9Sstevel@tonic-gate 12037c478bd9Sstevel@tonic-gate /* COMPUND = 1 */ 12047c478bd9Sstevel@tonic-gate COMPOUND4args nfs4_compound_args; 12057c478bd9Sstevel@tonic-gate }; 12067c478bd9Sstevel@tonic-gate 12077c478bd9Sstevel@tonic-gate union rfs_res { 12087c478bd9Sstevel@tonic-gate /* 12097c478bd9Sstevel@tonic-gate * NFS VERSION 2 12107c478bd9Sstevel@tonic-gate */ 12117c478bd9Sstevel@tonic-gate 12127c478bd9Sstevel@tonic-gate /* RFS_NULL = 0 */ 12137c478bd9Sstevel@tonic-gate 12147c478bd9Sstevel@tonic-gate /* RFS_GETATTR = 1 */ 12157c478bd9Sstevel@tonic-gate struct nfsattrstat nfs2_getattr_res; 12167c478bd9Sstevel@tonic-gate 12177c478bd9Sstevel@tonic-gate /* RFS_SETATTR = 2 */ 12187c478bd9Sstevel@tonic-gate struct nfsattrstat nfs2_setattr_res; 12197c478bd9Sstevel@tonic-gate 12207c478bd9Sstevel@tonic-gate /* RFS_ROOT = 3 *** NO LONGER SUPPORTED *** */ 12217c478bd9Sstevel@tonic-gate 12227c478bd9Sstevel@tonic-gate /* RFS_LOOKUP = 4 */ 12237c478bd9Sstevel@tonic-gate struct nfsdiropres nfs2_lookup_res; 12247c478bd9Sstevel@tonic-gate 12257c478bd9Sstevel@tonic-gate /* RFS_READLINK = 5 */ 12267c478bd9Sstevel@tonic-gate struct nfsrdlnres nfs2_readlink_res; 12277c478bd9Sstevel@tonic-gate 12287c478bd9Sstevel@tonic-gate /* RFS_READ = 6 */ 12297c478bd9Sstevel@tonic-gate struct nfsrdresult nfs2_read_res; 12307c478bd9Sstevel@tonic-gate 12317c478bd9Sstevel@tonic-gate /* RFS_WRITECACHE = 7 *** NO LONGER SUPPORTED *** */ 12327c478bd9Sstevel@tonic-gate 12337c478bd9Sstevel@tonic-gate /* RFS_WRITE = 8 */ 12347c478bd9Sstevel@tonic-gate struct nfsattrstat nfs2_write_res; 12357c478bd9Sstevel@tonic-gate 12367c478bd9Sstevel@tonic-gate /* RFS_CREATE = 9 */ 12377c478bd9Sstevel@tonic-gate struct nfsdiropres nfs2_create_res; 12387c478bd9Sstevel@tonic-gate 12397c478bd9Sstevel@tonic-gate /* RFS_REMOVE = 10 */ 12407c478bd9Sstevel@tonic-gate enum nfsstat nfs2_remove_res; 12417c478bd9Sstevel@tonic-gate 12427c478bd9Sstevel@tonic-gate /* RFS_RENAME = 11 */ 12437c478bd9Sstevel@tonic-gate enum nfsstat nfs2_rename_res; 12447c478bd9Sstevel@tonic-gate 12457c478bd9Sstevel@tonic-gate /* RFS_LINK = 12 */ 12467c478bd9Sstevel@tonic-gate enum nfsstat nfs2_link_res; 12477c478bd9Sstevel@tonic-gate 12487c478bd9Sstevel@tonic-gate /* RFS_SYMLINK = 13 */ 12497c478bd9Sstevel@tonic-gate enum nfsstat nfs2_symlink_res; 12507c478bd9Sstevel@tonic-gate 12517c478bd9Sstevel@tonic-gate /* RFS_MKDIR = 14 */ 12527c478bd9Sstevel@tonic-gate struct nfsdiropres nfs2_mkdir_res; 12537c478bd9Sstevel@tonic-gate 12547c478bd9Sstevel@tonic-gate /* RFS_RMDIR = 15 */ 12557c478bd9Sstevel@tonic-gate enum nfsstat nfs2_rmdir_res; 12567c478bd9Sstevel@tonic-gate 12577c478bd9Sstevel@tonic-gate /* RFS_READDIR = 16 */ 12587c478bd9Sstevel@tonic-gate struct nfsrddirres nfs2_readdir_res; 12597c478bd9Sstevel@tonic-gate 12607c478bd9Sstevel@tonic-gate /* RFS_STATFS = 17 */ 12617c478bd9Sstevel@tonic-gate struct nfsstatfs nfs2_statfs_res; 12627c478bd9Sstevel@tonic-gate 12637c478bd9Sstevel@tonic-gate /* 12647c478bd9Sstevel@tonic-gate * NFS VERSION 3 12657c478bd9Sstevel@tonic-gate */ 12667c478bd9Sstevel@tonic-gate 12677c478bd9Sstevel@tonic-gate /* RFS_NULL = 0 */ 12687c478bd9Sstevel@tonic-gate 12697c478bd9Sstevel@tonic-gate /* RFS3_GETATTR = 1 */ 12707c478bd9Sstevel@tonic-gate GETATTR3res nfs3_getattr_res; 12717c478bd9Sstevel@tonic-gate 12727c478bd9Sstevel@tonic-gate /* RFS3_SETATTR = 2 */ 12737c478bd9Sstevel@tonic-gate SETATTR3res nfs3_setattr_res; 12747c478bd9Sstevel@tonic-gate 12757c478bd9Sstevel@tonic-gate /* RFS3_LOOKUP = 3 */ 12767c478bd9Sstevel@tonic-gate LOOKUP3res nfs3_lookup_res; 12777c478bd9Sstevel@tonic-gate 12787c478bd9Sstevel@tonic-gate /* RFS3_ACCESS = 4 */ 12797c478bd9Sstevel@tonic-gate ACCESS3res nfs3_access_res; 12807c478bd9Sstevel@tonic-gate 12817c478bd9Sstevel@tonic-gate /* RFS3_READLINK = 5 */ 12827c478bd9Sstevel@tonic-gate READLINK3res nfs3_readlink_res; 12837c478bd9Sstevel@tonic-gate 12847c478bd9Sstevel@tonic-gate /* RFS3_READ = 6 */ 12857c478bd9Sstevel@tonic-gate READ3res nfs3_read_res; 12867c478bd9Sstevel@tonic-gate 12877c478bd9Sstevel@tonic-gate /* RFS3_WRITE = 7 */ 12887c478bd9Sstevel@tonic-gate WRITE3res nfs3_write_res; 12897c478bd9Sstevel@tonic-gate 12907c478bd9Sstevel@tonic-gate /* RFS3_CREATE = 8 */ 12917c478bd9Sstevel@tonic-gate CREATE3res nfs3_create_res; 12927c478bd9Sstevel@tonic-gate 12937c478bd9Sstevel@tonic-gate /* RFS3_MKDIR = 9 */ 12947c478bd9Sstevel@tonic-gate MKDIR3res nfs3_mkdir_res; 12957c478bd9Sstevel@tonic-gate 12967c478bd9Sstevel@tonic-gate /* RFS3_SYMLINK = 10 */ 12977c478bd9Sstevel@tonic-gate SYMLINK3res nfs3_symlink_res; 12987c478bd9Sstevel@tonic-gate 12997c478bd9Sstevel@tonic-gate /* RFS3_MKNOD = 11 */ 13007c478bd9Sstevel@tonic-gate MKNOD3res nfs3_mknod_res; 13017c478bd9Sstevel@tonic-gate 13027c478bd9Sstevel@tonic-gate /* RFS3_REMOVE = 12 */ 13037c478bd9Sstevel@tonic-gate REMOVE3res nfs3_remove_res; 13047c478bd9Sstevel@tonic-gate 13057c478bd9Sstevel@tonic-gate /* RFS3_RMDIR = 13 */ 13067c478bd9Sstevel@tonic-gate RMDIR3res nfs3_rmdir_res; 13077c478bd9Sstevel@tonic-gate 13087c478bd9Sstevel@tonic-gate /* RFS3_RENAME = 14 */ 13097c478bd9Sstevel@tonic-gate RENAME3res nfs3_rename_res; 13107c478bd9Sstevel@tonic-gate 13117c478bd9Sstevel@tonic-gate /* RFS3_LINK = 15 */ 13127c478bd9Sstevel@tonic-gate LINK3res nfs3_link_res; 13137c478bd9Sstevel@tonic-gate 13147c478bd9Sstevel@tonic-gate /* RFS3_READDIR = 16 */ 13157c478bd9Sstevel@tonic-gate READDIR3res nfs3_readdir_res; 13167c478bd9Sstevel@tonic-gate 13177c478bd9Sstevel@tonic-gate /* RFS3_READDIRPLUS = 17 */ 13187c478bd9Sstevel@tonic-gate READDIRPLUS3res nfs3_readdirplus_res; 13197c478bd9Sstevel@tonic-gate 13207c478bd9Sstevel@tonic-gate /* RFS3_FSSTAT = 18 */ 13217c478bd9Sstevel@tonic-gate FSSTAT3res nfs3_fsstat_res; 13227c478bd9Sstevel@tonic-gate 13237c478bd9Sstevel@tonic-gate /* RFS3_FSINFO = 19 */ 13247c478bd9Sstevel@tonic-gate FSINFO3res nfs3_fsinfo_res; 13257c478bd9Sstevel@tonic-gate 13267c478bd9Sstevel@tonic-gate /* RFS3_PATHCONF = 20 */ 13277c478bd9Sstevel@tonic-gate PATHCONF3res nfs3_pathconf_res; 13287c478bd9Sstevel@tonic-gate 13297c478bd9Sstevel@tonic-gate /* RFS3_COMMIT = 21 */ 13307c478bd9Sstevel@tonic-gate COMMIT3res nfs3_commit_res; 13317c478bd9Sstevel@tonic-gate 13327c478bd9Sstevel@tonic-gate /* 13337c478bd9Sstevel@tonic-gate * NFS VERSION 4 13347c478bd9Sstevel@tonic-gate */ 13357c478bd9Sstevel@tonic-gate 13367c478bd9Sstevel@tonic-gate /* RFS_NULL = 0 */ 13377c478bd9Sstevel@tonic-gate 13387c478bd9Sstevel@tonic-gate /* RFS4_COMPOUND = 1 */ 13397c478bd9Sstevel@tonic-gate COMPOUND4res nfs4_compound_res; 13407c478bd9Sstevel@tonic-gate 13417c478bd9Sstevel@tonic-gate }; 13427c478bd9Sstevel@tonic-gate 13437c478bd9Sstevel@tonic-gate static struct rpc_disptable rfs_disptable[] = { 13447c478bd9Sstevel@tonic-gate {sizeof (rfsdisptab_v2) / sizeof (rfsdisptab_v2[0]), 13457c478bd9Sstevel@tonic-gate rfscallnames_v2, 1346c93d332cSDan McDonald &rfsproccnt_v2_ptr, rfsdisptab_v2}, 13477c478bd9Sstevel@tonic-gate {sizeof (rfsdisptab_v3) / sizeof (rfsdisptab_v3[0]), 13487c478bd9Sstevel@tonic-gate rfscallnames_v3, 1349c93d332cSDan McDonald &rfsproccnt_v3_ptr, rfsdisptab_v3}, 13507c478bd9Sstevel@tonic-gate {sizeof (rfsdisptab_v4) / sizeof (rfsdisptab_v4[0]), 13517c478bd9Sstevel@tonic-gate rfscallnames_v4, 1352c93d332cSDan McDonald &rfsproccnt_v4_ptr, rfsdisptab_v4}, 13537c478bd9Sstevel@tonic-gate }; 13547c478bd9Sstevel@tonic-gate 13557c478bd9Sstevel@tonic-gate /* 13567c478bd9Sstevel@tonic-gate * If nfs_portmon is set, then clients are required to use privileged 13577c478bd9Sstevel@tonic-gate * ports (ports < IPPORT_RESERVED) in order to get NFS services. 13587c478bd9Sstevel@tonic-gate * 13597c478bd9Sstevel@tonic-gate * N.B.: this attempt to carry forward the already ill-conceived notion 13607c478bd9Sstevel@tonic-gate * of privileged ports for TCP/UDP is really quite ineffectual. Not only 13617c478bd9Sstevel@tonic-gate * is it transport-dependent, it's laughably easy to spoof. If you're 13627c478bd9Sstevel@tonic-gate * really interested in security, you must start with secure RPC instead. 13637c478bd9Sstevel@tonic-gate */ 13647c478bd9Sstevel@tonic-gate static int nfs_portmon = 0; 13657c478bd9Sstevel@tonic-gate 13667c478bd9Sstevel@tonic-gate #ifdef DEBUG 13677c478bd9Sstevel@tonic-gate static int cred_hits = 0; 13687c478bd9Sstevel@tonic-gate static int cred_misses = 0; 13697c478bd9Sstevel@tonic-gate #endif 13707c478bd9Sstevel@tonic-gate 13717c478bd9Sstevel@tonic-gate 13727c478bd9Sstevel@tonic-gate #ifdef DEBUG 13737c478bd9Sstevel@tonic-gate /* 13747c478bd9Sstevel@tonic-gate * Debug code to allow disabling of rfs_dispatch() use of 13757c478bd9Sstevel@tonic-gate * fastxdrargs() and fastxdrres() calls for testing purposes. 13767c478bd9Sstevel@tonic-gate */ 13777c478bd9Sstevel@tonic-gate static int rfs_no_fast_xdrargs = 0; 13787c478bd9Sstevel@tonic-gate static int rfs_no_fast_xdrres = 0; 13797c478bd9Sstevel@tonic-gate #endif 13807c478bd9Sstevel@tonic-gate 13817c478bd9Sstevel@tonic-gate union acl_args { 13827c478bd9Sstevel@tonic-gate /* 13837c478bd9Sstevel@tonic-gate * ACL VERSION 2 13847c478bd9Sstevel@tonic-gate */ 13857c478bd9Sstevel@tonic-gate 13867c478bd9Sstevel@tonic-gate /* ACL2_NULL = 0 */ 13877c478bd9Sstevel@tonic-gate 13887c478bd9Sstevel@tonic-gate /* ACL2_GETACL = 1 */ 13897c478bd9Sstevel@tonic-gate GETACL2args acl2_getacl_args; 13907c478bd9Sstevel@tonic-gate 13917c478bd9Sstevel@tonic-gate /* ACL2_SETACL = 2 */ 13927c478bd9Sstevel@tonic-gate SETACL2args acl2_setacl_args; 13937c478bd9Sstevel@tonic-gate 13947c478bd9Sstevel@tonic-gate /* ACL2_GETATTR = 3 */ 13957c478bd9Sstevel@tonic-gate GETATTR2args acl2_getattr_args; 13967c478bd9Sstevel@tonic-gate 13977c478bd9Sstevel@tonic-gate /* ACL2_ACCESS = 4 */ 13987c478bd9Sstevel@tonic-gate ACCESS2args acl2_access_args; 13997c478bd9Sstevel@tonic-gate 14007c478bd9Sstevel@tonic-gate /* ACL2_GETXATTRDIR = 5 */ 14017c478bd9Sstevel@tonic-gate GETXATTRDIR2args acl2_getxattrdir_args; 14027c478bd9Sstevel@tonic-gate 14037c478bd9Sstevel@tonic-gate /* 14047c478bd9Sstevel@tonic-gate * ACL VERSION 3 14057c478bd9Sstevel@tonic-gate */ 14067c478bd9Sstevel@tonic-gate 14077c478bd9Sstevel@tonic-gate /* ACL3_NULL = 0 */ 14087c478bd9Sstevel@tonic-gate 14097c478bd9Sstevel@tonic-gate /* ACL3_GETACL = 1 */ 14107c478bd9Sstevel@tonic-gate GETACL3args acl3_getacl_args; 14117c478bd9Sstevel@tonic-gate 14127c478bd9Sstevel@tonic-gate /* ACL3_SETACL = 2 */ 14137c478bd9Sstevel@tonic-gate SETACL3args acl3_setacl; 14147c478bd9Sstevel@tonic-gate 14157c478bd9Sstevel@tonic-gate /* ACL3_GETXATTRDIR = 3 */ 14167c478bd9Sstevel@tonic-gate GETXATTRDIR3args acl3_getxattrdir_args; 14177c478bd9Sstevel@tonic-gate 14187c478bd9Sstevel@tonic-gate }; 14197c478bd9Sstevel@tonic-gate 14207c478bd9Sstevel@tonic-gate union acl_res { 14217c478bd9Sstevel@tonic-gate /* 14227c478bd9Sstevel@tonic-gate * ACL VERSION 2 14237c478bd9Sstevel@tonic-gate */ 14247c478bd9Sstevel@tonic-gate 14257c478bd9Sstevel@tonic-gate /* ACL2_NULL = 0 */ 14267c478bd9Sstevel@tonic-gate 14277c478bd9Sstevel@tonic-gate /* ACL2_GETACL = 1 */ 14287c478bd9Sstevel@tonic-gate GETACL2res acl2_getacl_res; 14297c478bd9Sstevel@tonic-gate 14307c478bd9Sstevel@tonic-gate /* ACL2_SETACL = 2 */ 14317c478bd9Sstevel@tonic-gate SETACL2res acl2_setacl_res; 14327c478bd9Sstevel@tonic-gate 14337c478bd9Sstevel@tonic-gate /* ACL2_GETATTR = 3 */ 14347c478bd9Sstevel@tonic-gate GETATTR2res acl2_getattr_res; 14357c478bd9Sstevel@tonic-gate 14367c478bd9Sstevel@tonic-gate /* ACL2_ACCESS = 4 */ 14377c478bd9Sstevel@tonic-gate ACCESS2res acl2_access_res; 14387c478bd9Sstevel@tonic-gate 14397c478bd9Sstevel@tonic-gate /* ACL2_GETXATTRDIR = 5 */ 14407c478bd9Sstevel@tonic-gate GETXATTRDIR2args acl2_getxattrdir_res; 14417c478bd9Sstevel@tonic-gate 14427c478bd9Sstevel@tonic-gate /* 14437c478bd9Sstevel@tonic-gate * ACL VERSION 3 14447c478bd9Sstevel@tonic-gate */ 14457c478bd9Sstevel@tonic-gate 14467c478bd9Sstevel@tonic-gate /* ACL3_NULL = 0 */ 14477c478bd9Sstevel@tonic-gate 14487c478bd9Sstevel@tonic-gate /* ACL3_GETACL = 1 */ 14497c478bd9Sstevel@tonic-gate GETACL3res acl3_getacl_res; 14507c478bd9Sstevel@tonic-gate 14517c478bd9Sstevel@tonic-gate /* ACL3_SETACL = 2 */ 14527c478bd9Sstevel@tonic-gate SETACL3res acl3_setacl_res; 14537c478bd9Sstevel@tonic-gate 14547c478bd9Sstevel@tonic-gate /* ACL3_GETXATTRDIR = 3 */ 14557c478bd9Sstevel@tonic-gate GETXATTRDIR3res acl3_getxattrdir_res; 14567c478bd9Sstevel@tonic-gate 14577c478bd9Sstevel@tonic-gate }; 14587c478bd9Sstevel@tonic-gate 14597c478bd9Sstevel@tonic-gate static bool_t 14607c478bd9Sstevel@tonic-gate auth_tooweak(struct svc_req *req, char *res) 14617c478bd9Sstevel@tonic-gate { 14627c478bd9Sstevel@tonic-gate 14637c478bd9Sstevel@tonic-gate if (req->rq_vers == NFS_VERSION && req->rq_proc == RFS_LOOKUP) { 14647c478bd9Sstevel@tonic-gate struct nfsdiropres *dr = (struct nfsdiropres *)res; 14652c2d21e9SRichard Lowe if ((enum wnfsstat)dr->dr_status == WNFSERR_CLNT_FLAVOR) 14667c478bd9Sstevel@tonic-gate return (TRUE); 14677c478bd9Sstevel@tonic-gate } else if (req->rq_vers == NFS_V3 && req->rq_proc == NFSPROC3_LOOKUP) { 14687c478bd9Sstevel@tonic-gate LOOKUP3res *resp = (LOOKUP3res *)res; 14692c2d21e9SRichard Lowe if ((enum wnfsstat)resp->status == WNFSERR_CLNT_FLAVOR) 14707c478bd9Sstevel@tonic-gate return (TRUE); 14717c478bd9Sstevel@tonic-gate } 14727c478bd9Sstevel@tonic-gate return (FALSE); 14737c478bd9Sstevel@tonic-gate } 14747c478bd9Sstevel@tonic-gate 1475d9ad96c1Srg137905 14767c478bd9Sstevel@tonic-gate static void 14777c478bd9Sstevel@tonic-gate common_dispatch(struct svc_req *req, SVCXPRT *xprt, rpcvers_t min_vers, 1478*aafcd32bSMarcel Telka rpcvers_t max_vers, char *pgmname, struct rpc_disptable *disptable) 14797c478bd9Sstevel@tonic-gate { 14807c478bd9Sstevel@tonic-gate int which; 14817c478bd9Sstevel@tonic-gate rpcvers_t vers; 14827c478bd9Sstevel@tonic-gate char *args; 14837c478bd9Sstevel@tonic-gate union { 14847c478bd9Sstevel@tonic-gate union rfs_args ra; 14857c478bd9Sstevel@tonic-gate union acl_args aa; 14867c478bd9Sstevel@tonic-gate } args_buf; 14877c478bd9Sstevel@tonic-gate char *res; 14887c478bd9Sstevel@tonic-gate union { 14897c478bd9Sstevel@tonic-gate union rfs_res rr; 14907c478bd9Sstevel@tonic-gate union acl_res ar; 14917c478bd9Sstevel@tonic-gate } res_buf; 14927c478bd9Sstevel@tonic-gate struct rpcdisp *disp = NULL; 14937c478bd9Sstevel@tonic-gate int dis_flags = 0; 14947c478bd9Sstevel@tonic-gate cred_t *cr; 14957c478bd9Sstevel@tonic-gate int error = 0; 14967c478bd9Sstevel@tonic-gate int anon_ok; 14977c478bd9Sstevel@tonic-gate struct exportinfo *exi = NULL; 14987c478bd9Sstevel@tonic-gate unsigned int nfslog_rec_id; 14997c478bd9Sstevel@tonic-gate int dupstat; 15007c478bd9Sstevel@tonic-gate struct dupreq *dr; 15017c478bd9Sstevel@tonic-gate int authres; 15027c478bd9Sstevel@tonic-gate bool_t publicfh_ok = FALSE; 15037c478bd9Sstevel@tonic-gate enum_t auth_flavor; 15047c478bd9Sstevel@tonic-gate bool_t dupcached = FALSE; 15057c478bd9Sstevel@tonic-gate struct netbuf nb; 15067c478bd9Sstevel@tonic-gate bool_t logging_enabled = FALSE; 15077c478bd9Sstevel@tonic-gate struct exportinfo *nfslog_exi = NULL; 1508eac3aab7Srobinson char **procnames; 1509eac3aab7Srobinson char cbuf[INET6_ADDRSTRLEN]; /* to hold both IPv4 and IPv6 addr */ 15105cb0d679SMarcel Telka bool_t ro = FALSE; 15117c478bd9Sstevel@tonic-gate 15127c478bd9Sstevel@tonic-gate vers = req->rq_vers; 15137c478bd9Sstevel@tonic-gate 15147c478bd9Sstevel@tonic-gate if (vers < min_vers || vers > max_vers) { 15157c478bd9Sstevel@tonic-gate svcerr_progvers(req->rq_xprt, min_vers, max_vers); 15167c478bd9Sstevel@tonic-gate error++; 15177c478bd9Sstevel@tonic-gate cmn_err(CE_NOTE, "%s: bad version number %u", pgmname, vers); 15187c478bd9Sstevel@tonic-gate goto done; 15197c478bd9Sstevel@tonic-gate } 15207c478bd9Sstevel@tonic-gate vers -= min_vers; 15217c478bd9Sstevel@tonic-gate 15227c478bd9Sstevel@tonic-gate which = req->rq_proc; 15237c478bd9Sstevel@tonic-gate if (which < 0 || which >= disptable[(int)vers].dis_nprocs) { 15247c478bd9Sstevel@tonic-gate svcerr_noproc(req->rq_xprt); 15257c478bd9Sstevel@tonic-gate error++; 15267c478bd9Sstevel@tonic-gate goto done; 15277c478bd9Sstevel@tonic-gate } 15287c478bd9Sstevel@tonic-gate 15297c478bd9Sstevel@tonic-gate (*(disptable[(int)vers].dis_proccntp))[which].value.ui64++; 15307c478bd9Sstevel@tonic-gate 15317c478bd9Sstevel@tonic-gate disp = &disptable[(int)vers].dis_table[which]; 1532eac3aab7Srobinson procnames = disptable[(int)vers].dis_procnames; 15337c478bd9Sstevel@tonic-gate 15347c478bd9Sstevel@tonic-gate auth_flavor = req->rq_cred.oa_flavor; 1535eac3aab7Srobinson 15367c478bd9Sstevel@tonic-gate /* 15377c478bd9Sstevel@tonic-gate * Deserialize into the args struct. 15387c478bd9Sstevel@tonic-gate */ 15397c478bd9Sstevel@tonic-gate args = (char *)&args_buf; 1540d9ad96c1Srg137905 15417c478bd9Sstevel@tonic-gate #ifdef DEBUG 15427c478bd9Sstevel@tonic-gate if (rfs_no_fast_xdrargs || (auth_flavor == RPCSEC_GSS) || 15437c478bd9Sstevel@tonic-gate disp->dis_fastxdrargs == NULL_xdrproc_t || 154427242a7cSthurlow !SVC_GETARGS(xprt, disp->dis_fastxdrargs, (char *)&args)) 15457c478bd9Sstevel@tonic-gate #else 15467c478bd9Sstevel@tonic-gate if ((auth_flavor == RPCSEC_GSS) || 15477c478bd9Sstevel@tonic-gate disp->dis_fastxdrargs == NULL_xdrproc_t || 154827242a7cSthurlow !SVC_GETARGS(xprt, disp->dis_fastxdrargs, (char *)&args)) 15497c478bd9Sstevel@tonic-gate #endif 155027242a7cSthurlow { 15517c478bd9Sstevel@tonic-gate bzero(args, disp->dis_argsz); 15527c478bd9Sstevel@tonic-gate if (!SVC_GETARGS(xprt, disp->dis_xdrargs, args)) { 15537c478bd9Sstevel@tonic-gate error++; 15547d12f3bcSmaheshvs /* 15557d12f3bcSmaheshvs * Check if we are outside our capabilities. 15567d12f3bcSmaheshvs */ 15577d12f3bcSmaheshvs if (rfs4_minorvers_mismatch(req, xprt, (void *)args)) 15587d12f3bcSmaheshvs goto done; 15597d12f3bcSmaheshvs 15607d12f3bcSmaheshvs svcerr_decode(xprt); 1561eac3aab7Srobinson cmn_err(CE_NOTE, 1562eac3aab7Srobinson "Failed to decode arguments for %s version %u " 1563eac3aab7Srobinson "procedure %s client %s%s", 1564eac3aab7Srobinson pgmname, vers + min_vers, procnames[which], 1565eac3aab7Srobinson client_name(req), client_addr(req, cbuf)); 15667c478bd9Sstevel@tonic-gate goto done; 15677c478bd9Sstevel@tonic-gate } 15687c478bd9Sstevel@tonic-gate } 15697c478bd9Sstevel@tonic-gate 15707c478bd9Sstevel@tonic-gate /* 1571d9ad96c1Srg137905 * If Version 4 use that specific dispatch function. 15727c478bd9Sstevel@tonic-gate */ 1573d9ad96c1Srg137905 if (req->rq_vers == 4) { 1574c93d332cSDan McDonald error += rfs4_dispatch(disp, req, xprt, args); 1575d9ad96c1Srg137905 goto done; 1576d9ad96c1Srg137905 } 15777c478bd9Sstevel@tonic-gate 15787c478bd9Sstevel@tonic-gate dis_flags = disp->dis_flags; 15797c478bd9Sstevel@tonic-gate 15807c478bd9Sstevel@tonic-gate /* 15817c478bd9Sstevel@tonic-gate * Find export information and check authentication, 15827c478bd9Sstevel@tonic-gate * setting the credential if everything is ok. 15837c478bd9Sstevel@tonic-gate */ 15847c478bd9Sstevel@tonic-gate if (disp->dis_getfh != NULL) { 158527242a7cSthurlow void *fh; 158627242a7cSthurlow fsid_t *fsid; 158727242a7cSthurlow fid_t *fid, *xfid; 158827242a7cSthurlow fhandle_t *fh2; 158927242a7cSthurlow nfs_fh3 *fh3; 15907c478bd9Sstevel@tonic-gate 15917c478bd9Sstevel@tonic-gate fh = (*disp->dis_getfh)(args); 159227242a7cSthurlow switch (req->rq_vers) { 159327242a7cSthurlow case NFS_VERSION: 159427242a7cSthurlow fh2 = (fhandle_t *)fh; 159527242a7cSthurlow fsid = &fh2->fh_fsid; 159627242a7cSthurlow fid = (fid_t *)&fh2->fh_len; 159727242a7cSthurlow xfid = (fid_t *)&fh2->fh_xlen; 159827242a7cSthurlow break; 159927242a7cSthurlow case NFS_V3: 160027242a7cSthurlow fh3 = (nfs_fh3 *)fh; 160127242a7cSthurlow fsid = &fh3->fh3_fsid; 160227242a7cSthurlow fid = FH3TOFIDP(fh3); 160327242a7cSthurlow xfid = FH3TOXFIDP(fh3); 160427242a7cSthurlow break; 160527242a7cSthurlow } 16067c478bd9Sstevel@tonic-gate 16077c478bd9Sstevel@tonic-gate /* 16087c478bd9Sstevel@tonic-gate * Fix for bug 1038302 - corbin 16097c478bd9Sstevel@tonic-gate * There is a problem here if anonymous access is 16107c478bd9Sstevel@tonic-gate * disallowed. If the current request is part of the 16117c478bd9Sstevel@tonic-gate * client's mount process for the requested filesystem, 16127c478bd9Sstevel@tonic-gate * then it will carry root (uid 0) credentials on it, and 16137c478bd9Sstevel@tonic-gate * will be denied by checkauth if that client does not 16147c478bd9Sstevel@tonic-gate * have explicit root=0 permission. This will cause the 16157c478bd9Sstevel@tonic-gate * client's mount operation to fail. As a work-around, 16167c478bd9Sstevel@tonic-gate * we check here to see if the request is a getattr or 16177c478bd9Sstevel@tonic-gate * statfs operation on the exported vnode itself, and 16187c478bd9Sstevel@tonic-gate * pass a flag to checkauth with the result of this test. 16197c478bd9Sstevel@tonic-gate * 16207c478bd9Sstevel@tonic-gate * The filehandle refers to the mountpoint itself if 16217c478bd9Sstevel@tonic-gate * the fh_data and fh_xdata portions of the filehandle 16227c478bd9Sstevel@tonic-gate * are equal. 16237c478bd9Sstevel@tonic-gate * 16247c478bd9Sstevel@tonic-gate * Added anon_ok argument to checkauth(). 16257c478bd9Sstevel@tonic-gate */ 16267c478bd9Sstevel@tonic-gate 162727242a7cSthurlow if ((dis_flags & RPC_ALLOWANON) && EQFID(fid, xfid)) 16287c478bd9Sstevel@tonic-gate anon_ok = 1; 16297c478bd9Sstevel@tonic-gate else 16307c478bd9Sstevel@tonic-gate anon_ok = 0; 16317c478bd9Sstevel@tonic-gate 16327c478bd9Sstevel@tonic-gate cr = xprt->xp_cred; 16337c478bd9Sstevel@tonic-gate ASSERT(cr != NULL); 16347c478bd9Sstevel@tonic-gate #ifdef DEBUG 16357c478bd9Sstevel@tonic-gate if (crgetref(cr) != 1) { 16367c478bd9Sstevel@tonic-gate crfree(cr); 16377c478bd9Sstevel@tonic-gate cr = crget(); 16387c478bd9Sstevel@tonic-gate xprt->xp_cred = cr; 16397c478bd9Sstevel@tonic-gate cred_misses++; 16407c478bd9Sstevel@tonic-gate } else 16417c478bd9Sstevel@tonic-gate cred_hits++; 16427c478bd9Sstevel@tonic-gate #else 16437c478bd9Sstevel@tonic-gate if (crgetref(cr) != 1) { 16447c478bd9Sstevel@tonic-gate crfree(cr); 16457c478bd9Sstevel@tonic-gate cr = crget(); 16467c478bd9Sstevel@tonic-gate xprt->xp_cred = cr; 16477c478bd9Sstevel@tonic-gate } 16487c478bd9Sstevel@tonic-gate #endif 16497c478bd9Sstevel@tonic-gate 1650fbd2e8e1SArne Jansen exi = checkexport(fsid, xfid, NULL); 1651d9ad96c1Srg137905 16527c478bd9Sstevel@tonic-gate if (exi != NULL) { 165327242a7cSthurlow publicfh_ok = PUBLICFH_CHECK(disp, exi, fsid, xfid); 16547c478bd9Sstevel@tonic-gate 16557c478bd9Sstevel@tonic-gate /* 16567c478bd9Sstevel@tonic-gate * Don't allow non-V4 clients access 16577c478bd9Sstevel@tonic-gate * to pseudo exports 16587c478bd9Sstevel@tonic-gate */ 16597c478bd9Sstevel@tonic-gate if (PSEUDO(exi)) { 16607c478bd9Sstevel@tonic-gate svcerr_weakauth(xprt); 16617c478bd9Sstevel@tonic-gate error++; 16627c478bd9Sstevel@tonic-gate goto done; 16637c478bd9Sstevel@tonic-gate } 16647c478bd9Sstevel@tonic-gate 16655cb0d679SMarcel Telka authres = checkauth(exi, req, cr, anon_ok, publicfh_ok, 16665cb0d679SMarcel Telka &ro); 16677c478bd9Sstevel@tonic-gate /* 16687c478bd9Sstevel@tonic-gate * authres > 0: authentication OK - proceed 16697c478bd9Sstevel@tonic-gate * authres == 0: authentication weak - return error 16707c478bd9Sstevel@tonic-gate * authres < 0: authentication timeout - drop 16717c478bd9Sstevel@tonic-gate */ 16727c478bd9Sstevel@tonic-gate if (authres <= 0) { 16737c478bd9Sstevel@tonic-gate if (authres == 0) { 16747c478bd9Sstevel@tonic-gate svcerr_weakauth(xprt); 16757c478bd9Sstevel@tonic-gate error++; 16767c478bd9Sstevel@tonic-gate } 16777c478bd9Sstevel@tonic-gate goto done; 16787c478bd9Sstevel@tonic-gate } 16797c478bd9Sstevel@tonic-gate } 16807c478bd9Sstevel@tonic-gate } else 16817c478bd9Sstevel@tonic-gate cr = NULL; 16827c478bd9Sstevel@tonic-gate 16837c478bd9Sstevel@tonic-gate if ((dis_flags & RPC_MAPRESP) && (auth_flavor != RPCSEC_GSS)) { 16847c478bd9Sstevel@tonic-gate res = (char *)SVC_GETRES(xprt, disp->dis_ressz); 16857c478bd9Sstevel@tonic-gate if (res == NULL) 16867c478bd9Sstevel@tonic-gate res = (char *)&res_buf; 16877c478bd9Sstevel@tonic-gate } else 16887c478bd9Sstevel@tonic-gate res = (char *)&res_buf; 16897c478bd9Sstevel@tonic-gate 16907c478bd9Sstevel@tonic-gate if (!(dis_flags & RPC_IDEMPOTENT)) { 16917c478bd9Sstevel@tonic-gate dupstat = SVC_DUP_EXT(xprt, req, res, disp->dis_ressz, &dr, 16927c478bd9Sstevel@tonic-gate &dupcached); 16937c478bd9Sstevel@tonic-gate 16947c478bd9Sstevel@tonic-gate switch (dupstat) { 16957c478bd9Sstevel@tonic-gate case DUP_ERROR: 16967c478bd9Sstevel@tonic-gate svcerr_systemerr(xprt); 16977c478bd9Sstevel@tonic-gate error++; 16987c478bd9Sstevel@tonic-gate goto done; 16997c478bd9Sstevel@tonic-gate /* NOTREACHED */ 17007c478bd9Sstevel@tonic-gate case DUP_INPROGRESS: 17017c478bd9Sstevel@tonic-gate if (res != (char *)&res_buf) 17027c478bd9Sstevel@tonic-gate SVC_FREERES(xprt); 17037c478bd9Sstevel@tonic-gate error++; 17047c478bd9Sstevel@tonic-gate goto done; 17057c478bd9Sstevel@tonic-gate /* NOTREACHED */ 17067c478bd9Sstevel@tonic-gate case DUP_NEW: 17077c478bd9Sstevel@tonic-gate case DUP_DROP: 17087c478bd9Sstevel@tonic-gate curthread->t_flag |= T_DONTPEND; 1709d9ad96c1Srg137905 17105cb0d679SMarcel Telka (*disp->dis_proc)(args, res, exi, req, cr, ro); 1711d9ad96c1Srg137905 17127c478bd9Sstevel@tonic-gate curthread->t_flag &= ~T_DONTPEND; 17137c478bd9Sstevel@tonic-gate if (curthread->t_flag & T_WOULDBLOCK) { 17147c478bd9Sstevel@tonic-gate curthread->t_flag &= ~T_WOULDBLOCK; 17157c478bd9Sstevel@tonic-gate SVC_DUPDONE_EXT(xprt, dr, res, NULL, 17167c478bd9Sstevel@tonic-gate disp->dis_ressz, DUP_DROP); 17177c478bd9Sstevel@tonic-gate if (res != (char *)&res_buf) 17187c478bd9Sstevel@tonic-gate SVC_FREERES(xprt); 17197c478bd9Sstevel@tonic-gate error++; 17207c478bd9Sstevel@tonic-gate goto done; 17217c478bd9Sstevel@tonic-gate } 17227c478bd9Sstevel@tonic-gate if (dis_flags & RPC_AVOIDWORK) { 17237c478bd9Sstevel@tonic-gate SVC_DUPDONE_EXT(xprt, dr, res, NULL, 17247c478bd9Sstevel@tonic-gate disp->dis_ressz, DUP_DROP); 17257c478bd9Sstevel@tonic-gate } else { 17267c478bd9Sstevel@tonic-gate SVC_DUPDONE_EXT(xprt, dr, res, 17277c478bd9Sstevel@tonic-gate disp->dis_resfree == nullfree ? NULL : 17287c478bd9Sstevel@tonic-gate disp->dis_resfree, 17297c478bd9Sstevel@tonic-gate disp->dis_ressz, DUP_DONE); 17307c478bd9Sstevel@tonic-gate dupcached = TRUE; 17317c478bd9Sstevel@tonic-gate } 17327c478bd9Sstevel@tonic-gate break; 17337c478bd9Sstevel@tonic-gate case DUP_DONE: 17347c478bd9Sstevel@tonic-gate break; 17357c478bd9Sstevel@tonic-gate } 17367c478bd9Sstevel@tonic-gate 17377c478bd9Sstevel@tonic-gate } else { 17387c478bd9Sstevel@tonic-gate curthread->t_flag |= T_DONTPEND; 1739d9ad96c1Srg137905 17405cb0d679SMarcel Telka (*disp->dis_proc)(args, res, exi, req, cr, ro); 1741d9ad96c1Srg137905 17427c478bd9Sstevel@tonic-gate curthread->t_flag &= ~T_DONTPEND; 17437c478bd9Sstevel@tonic-gate if (curthread->t_flag & T_WOULDBLOCK) { 17447c478bd9Sstevel@tonic-gate curthread->t_flag &= ~T_WOULDBLOCK; 17457c478bd9Sstevel@tonic-gate if (res != (char *)&res_buf) 17467c478bd9Sstevel@tonic-gate SVC_FREERES(xprt); 17477c478bd9Sstevel@tonic-gate error++; 17487c478bd9Sstevel@tonic-gate goto done; 17497c478bd9Sstevel@tonic-gate } 17507c478bd9Sstevel@tonic-gate } 17517c478bd9Sstevel@tonic-gate 17527c478bd9Sstevel@tonic-gate if (auth_tooweak(req, res)) { 17537c478bd9Sstevel@tonic-gate svcerr_weakauth(xprt); 17547c478bd9Sstevel@tonic-gate error++; 17557c478bd9Sstevel@tonic-gate goto done; 17567c478bd9Sstevel@tonic-gate } 17577c478bd9Sstevel@tonic-gate 17587c478bd9Sstevel@tonic-gate /* 17597c478bd9Sstevel@tonic-gate * Check to see if logging has been enabled on the server. 17607c478bd9Sstevel@tonic-gate * If so, then obtain the export info struct to be used for 17617c478bd9Sstevel@tonic-gate * the later writing of the log record. This is done for 17627c478bd9Sstevel@tonic-gate * the case that a lookup is done across a non-logged public 17637c478bd9Sstevel@tonic-gate * file system. 17647c478bd9Sstevel@tonic-gate */ 17657c478bd9Sstevel@tonic-gate if (nfslog_buffer_list != NULL) { 17667c478bd9Sstevel@tonic-gate nfslog_exi = nfslog_get_exi(exi, req, res, &nfslog_rec_id); 17677c478bd9Sstevel@tonic-gate /* 17687c478bd9Sstevel@tonic-gate * Is logging enabled? 17697c478bd9Sstevel@tonic-gate */ 17707c478bd9Sstevel@tonic-gate logging_enabled = (nfslog_exi != NULL); 17717c478bd9Sstevel@tonic-gate 17727c478bd9Sstevel@tonic-gate /* 17737c478bd9Sstevel@tonic-gate * Copy the netbuf for logging purposes, before it is 17747c478bd9Sstevel@tonic-gate * freed by svc_sendreply(). 17757c478bd9Sstevel@tonic-gate */ 17767c478bd9Sstevel@tonic-gate if (logging_enabled) { 17777c478bd9Sstevel@tonic-gate NFSLOG_COPY_NETBUF(nfslog_exi, xprt, &nb); 17787c478bd9Sstevel@tonic-gate /* 17797c478bd9Sstevel@tonic-gate * If RPC_MAPRESP flag set (i.e. in V2 ops) the 17807c478bd9Sstevel@tonic-gate * res gets copied directly into the mbuf and 17817c478bd9Sstevel@tonic-gate * may be freed soon after the sendreply. So we 17827c478bd9Sstevel@tonic-gate * must copy it here to a safe place... 17837c478bd9Sstevel@tonic-gate */ 17847c478bd9Sstevel@tonic-gate if (res != (char *)&res_buf) { 17857c478bd9Sstevel@tonic-gate bcopy(res, (char *)&res_buf, disp->dis_ressz); 17867c478bd9Sstevel@tonic-gate } 17877c478bd9Sstevel@tonic-gate } 17887c478bd9Sstevel@tonic-gate } 17897c478bd9Sstevel@tonic-gate 17907c478bd9Sstevel@tonic-gate /* 17917c478bd9Sstevel@tonic-gate * Serialize and send results struct 17927c478bd9Sstevel@tonic-gate */ 17937c478bd9Sstevel@tonic-gate #ifdef DEBUG 179427242a7cSthurlow if (rfs_no_fast_xdrres == 0 && res != (char *)&res_buf) 17957c478bd9Sstevel@tonic-gate #else 179627242a7cSthurlow if (res != (char *)&res_buf) 17977c478bd9Sstevel@tonic-gate #endif 179827242a7cSthurlow { 17997c478bd9Sstevel@tonic-gate if (!svc_sendreply(xprt, disp->dis_fastxdrres, res)) { 18007c478bd9Sstevel@tonic-gate cmn_err(CE_NOTE, "%s: bad sendreply", pgmname); 18010a4b0810SKaren Rochford svcerr_systemerr(xprt); 18027c478bd9Sstevel@tonic-gate error++; 18037c478bd9Sstevel@tonic-gate } 18047c478bd9Sstevel@tonic-gate } else { 18057c478bd9Sstevel@tonic-gate if (!svc_sendreply(xprt, disp->dis_xdrres, res)) { 18067c478bd9Sstevel@tonic-gate cmn_err(CE_NOTE, "%s: bad sendreply", pgmname); 18070a4b0810SKaren Rochford svcerr_systemerr(xprt); 18087c478bd9Sstevel@tonic-gate error++; 18097c478bd9Sstevel@tonic-gate } 18107c478bd9Sstevel@tonic-gate } 18117c478bd9Sstevel@tonic-gate 18127c478bd9Sstevel@tonic-gate /* 18137c478bd9Sstevel@tonic-gate * Log if needed 18147c478bd9Sstevel@tonic-gate */ 18157c478bd9Sstevel@tonic-gate if (logging_enabled) { 18167c478bd9Sstevel@tonic-gate nfslog_write_record(nfslog_exi, req, args, (char *)&res_buf, 18177c478bd9Sstevel@tonic-gate cr, &nb, nfslog_rec_id, NFSLOG_ONE_BUFFER); 18187c478bd9Sstevel@tonic-gate exi_rele(nfslog_exi); 18197c478bd9Sstevel@tonic-gate kmem_free((&nb)->buf, (&nb)->len); 18207c478bd9Sstevel@tonic-gate } 18217c478bd9Sstevel@tonic-gate 18227c478bd9Sstevel@tonic-gate /* 18237c478bd9Sstevel@tonic-gate * Free results struct. With the addition of NFS V4 we can 18247c478bd9Sstevel@tonic-gate * have non-idempotent procedures with functions. 18257c478bd9Sstevel@tonic-gate */ 18267c478bd9Sstevel@tonic-gate if (disp->dis_resfree != nullfree && dupcached == FALSE) { 18277c478bd9Sstevel@tonic-gate (*disp->dis_resfree)(res); 18287c478bd9Sstevel@tonic-gate } 18297c478bd9Sstevel@tonic-gate 18307c478bd9Sstevel@tonic-gate done: 18317c478bd9Sstevel@tonic-gate /* 18327c478bd9Sstevel@tonic-gate * Free arguments struct 18337c478bd9Sstevel@tonic-gate */ 18347c478bd9Sstevel@tonic-gate if (disp) { 18357c478bd9Sstevel@tonic-gate if (!SVC_FREEARGS(xprt, disp->dis_xdrargs, args)) { 18367c478bd9Sstevel@tonic-gate cmn_err(CE_NOTE, "%s: bad freeargs", pgmname); 18377c478bd9Sstevel@tonic-gate error++; 18387c478bd9Sstevel@tonic-gate } 18397c478bd9Sstevel@tonic-gate } else { 18407c478bd9Sstevel@tonic-gate if (!SVC_FREEARGS(xprt, (xdrproc_t)0, (caddr_t)0)) { 18417c478bd9Sstevel@tonic-gate cmn_err(CE_NOTE, "%s: bad freeargs", pgmname); 18427c478bd9Sstevel@tonic-gate error++; 18437c478bd9Sstevel@tonic-gate } 18447c478bd9Sstevel@tonic-gate } 18457c478bd9Sstevel@tonic-gate 18467c478bd9Sstevel@tonic-gate if (exi != NULL) 18477c478bd9Sstevel@tonic-gate exi_rele(exi); 18487c478bd9Sstevel@tonic-gate 18497c478bd9Sstevel@tonic-gate global_svstat_ptr[req->rq_vers][NFS_BADCALLS].value.ui64 += error; 18507c478bd9Sstevel@tonic-gate 18517c478bd9Sstevel@tonic-gate global_svstat_ptr[req->rq_vers][NFS_CALLS].value.ui64++; 18527c478bd9Sstevel@tonic-gate } 18537c478bd9Sstevel@tonic-gate 18547c478bd9Sstevel@tonic-gate static void 18557c478bd9Sstevel@tonic-gate rfs_dispatch(struct svc_req *req, SVCXPRT *xprt) 18567c478bd9Sstevel@tonic-gate { 18577c478bd9Sstevel@tonic-gate common_dispatch(req, xprt, NFS_VERSMIN, NFS_VERSMAX, 1858eac3aab7Srobinson "NFS", rfs_disptable); 18597c478bd9Sstevel@tonic-gate } 18607c478bd9Sstevel@tonic-gate 18617c478bd9Sstevel@tonic-gate static char *aclcallnames_v2[] = { 18627c478bd9Sstevel@tonic-gate "ACL2_NULL", 18637c478bd9Sstevel@tonic-gate "ACL2_GETACL", 18647c478bd9Sstevel@tonic-gate "ACL2_SETACL", 18657c478bd9Sstevel@tonic-gate "ACL2_GETATTR", 18667c478bd9Sstevel@tonic-gate "ACL2_ACCESS", 18677c478bd9Sstevel@tonic-gate "ACL2_GETXATTRDIR" 18687c478bd9Sstevel@tonic-gate }; 18697c478bd9Sstevel@tonic-gate 18707c478bd9Sstevel@tonic-gate static struct rpcdisp acldisptab_v2[] = { 18717c478bd9Sstevel@tonic-gate /* 18727c478bd9Sstevel@tonic-gate * ACL VERSION 2 18737c478bd9Sstevel@tonic-gate */ 18747c478bd9Sstevel@tonic-gate 18757c478bd9Sstevel@tonic-gate /* ACL2_NULL = 0 */ 18767c478bd9Sstevel@tonic-gate {rpc_null, 18777c478bd9Sstevel@tonic-gate xdr_void, NULL_xdrproc_t, 0, 18787c478bd9Sstevel@tonic-gate xdr_void, NULL_xdrproc_t, 0, 18797c478bd9Sstevel@tonic-gate nullfree, RPC_IDEMPOTENT, 18807c478bd9Sstevel@tonic-gate 0}, 18817c478bd9Sstevel@tonic-gate 18827c478bd9Sstevel@tonic-gate /* ACL2_GETACL = 1 */ 18837c478bd9Sstevel@tonic-gate {acl2_getacl, 18847c478bd9Sstevel@tonic-gate xdr_GETACL2args, xdr_fastGETACL2args, sizeof (GETACL2args), 18857c478bd9Sstevel@tonic-gate xdr_GETACL2res, NULL_xdrproc_t, sizeof (GETACL2res), 18867c478bd9Sstevel@tonic-gate acl2_getacl_free, RPC_IDEMPOTENT, 18877c478bd9Sstevel@tonic-gate acl2_getacl_getfh}, 18887c478bd9Sstevel@tonic-gate 18897c478bd9Sstevel@tonic-gate /* ACL2_SETACL = 2 */ 18907c478bd9Sstevel@tonic-gate {acl2_setacl, 18917c478bd9Sstevel@tonic-gate xdr_SETACL2args, NULL_xdrproc_t, sizeof (SETACL2args), 18927c478bd9Sstevel@tonic-gate #ifdef _LITTLE_ENDIAN 18937c478bd9Sstevel@tonic-gate xdr_SETACL2res, xdr_fastSETACL2res, sizeof (SETACL2res), 18947c478bd9Sstevel@tonic-gate #else 18957c478bd9Sstevel@tonic-gate xdr_SETACL2res, NULL_xdrproc_t, sizeof (SETACL2res), 18967c478bd9Sstevel@tonic-gate #endif 18977c478bd9Sstevel@tonic-gate nullfree, RPC_MAPRESP, 18987c478bd9Sstevel@tonic-gate acl2_setacl_getfh}, 18997c478bd9Sstevel@tonic-gate 19007c478bd9Sstevel@tonic-gate /* ACL2_GETATTR = 3 */ 19017c478bd9Sstevel@tonic-gate {acl2_getattr, 19027c478bd9Sstevel@tonic-gate xdr_GETATTR2args, xdr_fastGETATTR2args, sizeof (GETATTR2args), 19037c478bd9Sstevel@tonic-gate #ifdef _LITTLE_ENDIAN 19047c478bd9Sstevel@tonic-gate xdr_GETATTR2res, xdr_fastGETATTR2res, sizeof (GETATTR2res), 19057c478bd9Sstevel@tonic-gate #else 19067c478bd9Sstevel@tonic-gate xdr_GETATTR2res, NULL_xdrproc_t, sizeof (GETATTR2res), 19077c478bd9Sstevel@tonic-gate #endif 19087c478bd9Sstevel@tonic-gate nullfree, RPC_IDEMPOTENT|RPC_ALLOWANON|RPC_MAPRESP, 19097c478bd9Sstevel@tonic-gate acl2_getattr_getfh}, 19107c478bd9Sstevel@tonic-gate 19117c478bd9Sstevel@tonic-gate /* ACL2_ACCESS = 4 */ 19127c478bd9Sstevel@tonic-gate {acl2_access, 19137c478bd9Sstevel@tonic-gate xdr_ACCESS2args, xdr_fastACCESS2args, sizeof (ACCESS2args), 19147c478bd9Sstevel@tonic-gate #ifdef _LITTLE_ENDIAN 19157c478bd9Sstevel@tonic-gate xdr_ACCESS2res, xdr_fastACCESS2res, sizeof (ACCESS2res), 19167c478bd9Sstevel@tonic-gate #else 19177c478bd9Sstevel@tonic-gate xdr_ACCESS2res, NULL_xdrproc_t, sizeof (ACCESS2res), 19187c478bd9Sstevel@tonic-gate #endif 19197c478bd9Sstevel@tonic-gate nullfree, RPC_IDEMPOTENT|RPC_MAPRESP, 19207c478bd9Sstevel@tonic-gate acl2_access_getfh}, 19217c478bd9Sstevel@tonic-gate 19227c478bd9Sstevel@tonic-gate /* ACL2_GETXATTRDIR = 5 */ 19237c478bd9Sstevel@tonic-gate {acl2_getxattrdir, 19247c478bd9Sstevel@tonic-gate xdr_GETXATTRDIR2args, NULL_xdrproc_t, sizeof (GETXATTRDIR2args), 19257c478bd9Sstevel@tonic-gate xdr_GETXATTRDIR2res, NULL_xdrproc_t, sizeof (GETXATTRDIR2res), 19267c478bd9Sstevel@tonic-gate nullfree, RPC_IDEMPOTENT, 19277c478bd9Sstevel@tonic-gate acl2_getxattrdir_getfh}, 19287c478bd9Sstevel@tonic-gate }; 19297c478bd9Sstevel@tonic-gate 19307c478bd9Sstevel@tonic-gate static char *aclcallnames_v3[] = { 19317c478bd9Sstevel@tonic-gate "ACL3_NULL", 19327c478bd9Sstevel@tonic-gate "ACL3_GETACL", 19337c478bd9Sstevel@tonic-gate "ACL3_SETACL", 19347c478bd9Sstevel@tonic-gate "ACL3_GETXATTRDIR" 19357c478bd9Sstevel@tonic-gate }; 19367c478bd9Sstevel@tonic-gate 19377c478bd9Sstevel@tonic-gate static struct rpcdisp acldisptab_v3[] = { 19387c478bd9Sstevel@tonic-gate /* 19397c478bd9Sstevel@tonic-gate * ACL VERSION 3 19407c478bd9Sstevel@tonic-gate */ 19417c478bd9Sstevel@tonic-gate 19427c478bd9Sstevel@tonic-gate /* ACL3_NULL = 0 */ 19437c478bd9Sstevel@tonic-gate {rpc_null, 19447c478bd9Sstevel@tonic-gate xdr_void, NULL_xdrproc_t, 0, 19457c478bd9Sstevel@tonic-gate xdr_void, NULL_xdrproc_t, 0, 19467c478bd9Sstevel@tonic-gate nullfree, RPC_IDEMPOTENT, 19477c478bd9Sstevel@tonic-gate 0}, 19487c478bd9Sstevel@tonic-gate 19497c478bd9Sstevel@tonic-gate /* ACL3_GETACL = 1 */ 19507c478bd9Sstevel@tonic-gate {acl3_getacl, 19517c478bd9Sstevel@tonic-gate xdr_GETACL3args, NULL_xdrproc_t, sizeof (GETACL3args), 19527c478bd9Sstevel@tonic-gate xdr_GETACL3res, NULL_xdrproc_t, sizeof (GETACL3res), 19537c478bd9Sstevel@tonic-gate acl3_getacl_free, RPC_IDEMPOTENT, 19547c478bd9Sstevel@tonic-gate acl3_getacl_getfh}, 19557c478bd9Sstevel@tonic-gate 19567c478bd9Sstevel@tonic-gate /* ACL3_SETACL = 2 */ 19577c478bd9Sstevel@tonic-gate {acl3_setacl, 19587c478bd9Sstevel@tonic-gate xdr_SETACL3args, NULL_xdrproc_t, sizeof (SETACL3args), 19597c478bd9Sstevel@tonic-gate xdr_SETACL3res, NULL_xdrproc_t, sizeof (SETACL3res), 19607c478bd9Sstevel@tonic-gate nullfree, 0, 19617c478bd9Sstevel@tonic-gate acl3_setacl_getfh}, 19627c478bd9Sstevel@tonic-gate 19637c478bd9Sstevel@tonic-gate /* ACL3_GETXATTRDIR = 3 */ 19647c478bd9Sstevel@tonic-gate {acl3_getxattrdir, 19657c478bd9Sstevel@tonic-gate xdr_GETXATTRDIR3args, NULL_xdrproc_t, sizeof (GETXATTRDIR3args), 19667c478bd9Sstevel@tonic-gate xdr_GETXATTRDIR3res, NULL_xdrproc_t, sizeof (GETXATTRDIR3res), 19677c478bd9Sstevel@tonic-gate nullfree, RPC_IDEMPOTENT, 19687c478bd9Sstevel@tonic-gate acl3_getxattrdir_getfh}, 19697c478bd9Sstevel@tonic-gate }; 19707c478bd9Sstevel@tonic-gate 19717c478bd9Sstevel@tonic-gate static struct rpc_disptable acl_disptable[] = { 19727c478bd9Sstevel@tonic-gate {sizeof (acldisptab_v2) / sizeof (acldisptab_v2[0]), 19737c478bd9Sstevel@tonic-gate aclcallnames_v2, 1974c93d332cSDan McDonald &aclproccnt_v2_ptr, acldisptab_v2}, 19757c478bd9Sstevel@tonic-gate {sizeof (acldisptab_v3) / sizeof (acldisptab_v3[0]), 19767c478bd9Sstevel@tonic-gate aclcallnames_v3, 1977c93d332cSDan McDonald &aclproccnt_v3_ptr, acldisptab_v3}, 19787c478bd9Sstevel@tonic-gate }; 19797c478bd9Sstevel@tonic-gate 19807c478bd9Sstevel@tonic-gate static void 19817c478bd9Sstevel@tonic-gate acl_dispatch(struct svc_req *req, SVCXPRT *xprt) 19827c478bd9Sstevel@tonic-gate { 19837c478bd9Sstevel@tonic-gate common_dispatch(req, xprt, NFS_ACL_VERSMIN, NFS_ACL_VERSMAX, 1984eac3aab7Srobinson "ACL", acl_disptable); 19857c478bd9Sstevel@tonic-gate } 19867c478bd9Sstevel@tonic-gate 19877c478bd9Sstevel@tonic-gate int 19887c478bd9Sstevel@tonic-gate checkwin(int flavor, int window, struct svc_req *req) 19897c478bd9Sstevel@tonic-gate { 19907c478bd9Sstevel@tonic-gate struct authdes_cred *adc; 19917c478bd9Sstevel@tonic-gate 19927c478bd9Sstevel@tonic-gate switch (flavor) { 19937c478bd9Sstevel@tonic-gate case AUTH_DES: 19947c478bd9Sstevel@tonic-gate adc = (struct authdes_cred *)req->rq_clntcred; 19954b3b7fc6SAlex Wilson CTASSERT(sizeof (struct authdes_cred) <= RQCRED_SIZE); 19967c478bd9Sstevel@tonic-gate if (adc->adc_fullname.window > window) 19977c478bd9Sstevel@tonic-gate return (0); 19987c478bd9Sstevel@tonic-gate break; 19997c478bd9Sstevel@tonic-gate 20007c478bd9Sstevel@tonic-gate default: 20017c478bd9Sstevel@tonic-gate break; 20027c478bd9Sstevel@tonic-gate } 20037c478bd9Sstevel@tonic-gate return (1); 20047c478bd9Sstevel@tonic-gate } 20057c478bd9Sstevel@tonic-gate 20067c478bd9Sstevel@tonic-gate 20077c478bd9Sstevel@tonic-gate /* 20087c478bd9Sstevel@tonic-gate * checkauth() will check the access permission against the export 20097c478bd9Sstevel@tonic-gate * information. Then map root uid/gid to appropriate uid/gid. 20107c478bd9Sstevel@tonic-gate * 20117c478bd9Sstevel@tonic-gate * This routine is used by NFS V3 and V2 code. 20127c478bd9Sstevel@tonic-gate */ 20137c478bd9Sstevel@tonic-gate static int 20147c478bd9Sstevel@tonic-gate checkauth(struct exportinfo *exi, struct svc_req *req, cred_t *cr, int anon_ok, 20155cb0d679SMarcel Telka bool_t publicfh_ok, bool_t *ro) 20167c478bd9Sstevel@tonic-gate { 20177c478bd9Sstevel@tonic-gate int i, nfsflavor, rpcflavor, stat, access; 20187c478bd9Sstevel@tonic-gate struct secinfo *secp; 20197c478bd9Sstevel@tonic-gate caddr_t principal; 20207c478bd9Sstevel@tonic-gate char buf[INET6_ADDRSTRLEN]; /* to hold both IPv4 and IPv6 addr */ 20217c478bd9Sstevel@tonic-gate int anon_res = 0; 20227c478bd9Sstevel@tonic-gate 20235cb0d679SMarcel Telka uid_t uid; 20245cb0d679SMarcel Telka gid_t gid; 202589621fe1SMarcel Telka uint_t ngids; 202689621fe1SMarcel Telka gid_t *gids; 20275cb0d679SMarcel Telka 20287c478bd9Sstevel@tonic-gate /* 20297c478bd9Sstevel@tonic-gate * Check for privileged port number 20307c478bd9Sstevel@tonic-gate * N.B.: this assumes that we know the format of a netbuf. 20317c478bd9Sstevel@tonic-gate */ 20327c478bd9Sstevel@tonic-gate if (nfs_portmon) { 20337c478bd9Sstevel@tonic-gate struct sockaddr *ca; 20347c478bd9Sstevel@tonic-gate ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf; 20357c478bd9Sstevel@tonic-gate 20367c478bd9Sstevel@tonic-gate if (ca == NULL) 20377c478bd9Sstevel@tonic-gate return (0); 20387c478bd9Sstevel@tonic-gate 20397c478bd9Sstevel@tonic-gate if ((ca->sa_family == AF_INET && 20407c478bd9Sstevel@tonic-gate ntohs(((struct sockaddr_in *)ca)->sin_port) >= 20417c478bd9Sstevel@tonic-gate IPPORT_RESERVED) || 20427c478bd9Sstevel@tonic-gate (ca->sa_family == AF_INET6 && 20437c478bd9Sstevel@tonic-gate ntohs(((struct sockaddr_in6 *)ca)->sin6_port) >= 20447c478bd9Sstevel@tonic-gate IPPORT_RESERVED)) { 20457c478bd9Sstevel@tonic-gate cmn_err(CE_NOTE, 20467c478bd9Sstevel@tonic-gate "nfs_server: client %s%ssent NFS request from " 20477c478bd9Sstevel@tonic-gate "unprivileged port", 20487c478bd9Sstevel@tonic-gate client_name(req), client_addr(req, buf)); 20497c478bd9Sstevel@tonic-gate return (0); 20507c478bd9Sstevel@tonic-gate } 20517c478bd9Sstevel@tonic-gate } 20527c478bd9Sstevel@tonic-gate 20537c478bd9Sstevel@tonic-gate /* 20547c478bd9Sstevel@tonic-gate * return 1 on success or 0 on failure 20557c478bd9Sstevel@tonic-gate */ 20567c478bd9Sstevel@tonic-gate stat = sec_svc_getcred(req, cr, &principal, &nfsflavor); 20577c478bd9Sstevel@tonic-gate 20587c478bd9Sstevel@tonic-gate /* 20595cb0d679SMarcel Telka * A failed AUTH_UNIX sec_svc_getcred() implies we couldn't set 20607c478bd9Sstevel@tonic-gate * the credentials; below we map that to anonymous. 20617c478bd9Sstevel@tonic-gate */ 20627c478bd9Sstevel@tonic-gate if (!stat && nfsflavor != AUTH_UNIX) { 20637c478bd9Sstevel@tonic-gate cmn_err(CE_NOTE, 20647c478bd9Sstevel@tonic-gate "nfs_server: couldn't get unix cred for %s", 20657c478bd9Sstevel@tonic-gate client_name(req)); 20667c478bd9Sstevel@tonic-gate return (0); 20677c478bd9Sstevel@tonic-gate } 20687c478bd9Sstevel@tonic-gate 20697c478bd9Sstevel@tonic-gate /* 20707c478bd9Sstevel@tonic-gate * Short circuit checkauth() on operations that support the 20717c478bd9Sstevel@tonic-gate * public filehandle, and if the request for that operation 20727c478bd9Sstevel@tonic-gate * is using the public filehandle. Note that we must call 20737c478bd9Sstevel@tonic-gate * sec_svc_getcred() first so that xp_cookie is set to the 20747c478bd9Sstevel@tonic-gate * right value. Normally xp_cookie is just the RPC flavor 20757c478bd9Sstevel@tonic-gate * of the the request, but in the case of RPCSEC_GSS it 20767c478bd9Sstevel@tonic-gate * could be a pseudo flavor. 20777c478bd9Sstevel@tonic-gate */ 20787c478bd9Sstevel@tonic-gate if (publicfh_ok) 20797c478bd9Sstevel@tonic-gate return (1); 20807c478bd9Sstevel@tonic-gate 20817c478bd9Sstevel@tonic-gate rpcflavor = req->rq_cred.oa_flavor; 20827c478bd9Sstevel@tonic-gate /* 20837c478bd9Sstevel@tonic-gate * Check if the auth flavor is valid for this export 20847c478bd9Sstevel@tonic-gate */ 208589621fe1SMarcel Telka access = nfsauth_access(exi, req, cr, &uid, &gid, &ngids, &gids); 20867c478bd9Sstevel@tonic-gate if (access & NFSAUTH_DROP) 20877c478bd9Sstevel@tonic-gate return (-1); /* drop the request */ 20887c478bd9Sstevel@tonic-gate 20895cb0d679SMarcel Telka if (access & NFSAUTH_RO) 20905cb0d679SMarcel Telka *ro = TRUE; 20915cb0d679SMarcel Telka 20927c478bd9Sstevel@tonic-gate if (access & NFSAUTH_DENIED) { 20937c478bd9Sstevel@tonic-gate /* 20947c478bd9Sstevel@tonic-gate * If anon_ok == 1 and we got NFSAUTH_DENIED, it was 20955cb0d679SMarcel Telka * probably due to the flavor not matching during 20967c478bd9Sstevel@tonic-gate * the mount attempt. So map the flavor to AUTH_NONE 20977c478bd9Sstevel@tonic-gate * so that the credentials get mapped to the anonymous 20987c478bd9Sstevel@tonic-gate * user. 20997c478bd9Sstevel@tonic-gate */ 21007c478bd9Sstevel@tonic-gate if (anon_ok == 1) 21017c478bd9Sstevel@tonic-gate rpcflavor = AUTH_NONE; 21027c478bd9Sstevel@tonic-gate else 21037c478bd9Sstevel@tonic-gate return (0); /* deny access */ 21047c478bd9Sstevel@tonic-gate 21057c478bd9Sstevel@tonic-gate } else if (access & NFSAUTH_MAPNONE) { 21067c478bd9Sstevel@tonic-gate /* 21077c478bd9Sstevel@tonic-gate * Access was granted even though the flavor mismatched 21087c478bd9Sstevel@tonic-gate * because AUTH_NONE was one of the exported flavors. 21097c478bd9Sstevel@tonic-gate */ 21107c478bd9Sstevel@tonic-gate rpcflavor = AUTH_NONE; 21117c478bd9Sstevel@tonic-gate 21127c478bd9Sstevel@tonic-gate } else if (access & NFSAUTH_WRONGSEC) { 21137c478bd9Sstevel@tonic-gate /* 2114829eb6b7SThomas Haynes * NFSAUTH_WRONGSEC is used for NFSv4. If we get here, 2115829eb6b7SThomas Haynes * it means a client ignored the list of allowed flavors 2116829eb6b7SThomas Haynes * returned via the MOUNT protocol. So we just disallow it! 21177c478bd9Sstevel@tonic-gate */ 2118829eb6b7SThomas Haynes return (0); 21197c478bd9Sstevel@tonic-gate } 21207c478bd9Sstevel@tonic-gate 212189621fe1SMarcel Telka if (rpcflavor != AUTH_SYS) 212289621fe1SMarcel Telka kmem_free(gids, ngids * sizeof (gid_t)); 212389621fe1SMarcel Telka 21247c478bd9Sstevel@tonic-gate switch (rpcflavor) { 21257c478bd9Sstevel@tonic-gate case AUTH_NONE: 21267c478bd9Sstevel@tonic-gate anon_res = crsetugid(cr, exi->exi_export.ex_anon, 21277c478bd9Sstevel@tonic-gate exi->exi_export.ex_anon); 21287c478bd9Sstevel@tonic-gate (void) crsetgroups(cr, 0, NULL); 21297c478bd9Sstevel@tonic-gate break; 21307c478bd9Sstevel@tonic-gate 21317c478bd9Sstevel@tonic-gate case AUTH_UNIX: 21325cb0d679SMarcel Telka if (!stat || crgetuid(cr) == 0 && !(access & NFSAUTH_UIDMAP)) { 21337c478bd9Sstevel@tonic-gate anon_res = crsetugid(cr, exi->exi_export.ex_anon, 21347c478bd9Sstevel@tonic-gate exi->exi_export.ex_anon); 21357c478bd9Sstevel@tonic-gate (void) crsetgroups(cr, 0, NULL); 21365cb0d679SMarcel Telka } else if (crgetuid(cr) == 0 && access & NFSAUTH_ROOT) { 2137b89a8333Snatalie li - Sun Microsystems - Irvine United States /* 2138b89a8333Snatalie li - Sun Microsystems - Irvine United States * It is root, so apply rootid to get real UID 2139b89a8333Snatalie li - Sun Microsystems - Irvine United States * Find the secinfo structure. We should be able 2140b89a8333Snatalie li - Sun Microsystems - Irvine United States * to find it by the time we reach here. 2141b89a8333Snatalie li - Sun Microsystems - Irvine United States * nfsauth_access() has done the checking. 2142b89a8333Snatalie li - Sun Microsystems - Irvine United States */ 2143b89a8333Snatalie li - Sun Microsystems - Irvine United States secp = NULL; 2144b89a8333Snatalie li - Sun Microsystems - Irvine United States for (i = 0; i < exi->exi_export.ex_seccnt; i++) { 2145b89a8333Snatalie li - Sun Microsystems - Irvine United States struct secinfo *sptr; 2146b89a8333Snatalie li - Sun Microsystems - Irvine United States sptr = &exi->exi_export.ex_secinfo[i]; 2147b89a8333Snatalie li - Sun Microsystems - Irvine United States if (sptr->s_secinfo.sc_nfsnum == nfsflavor) { 2148b89a8333Snatalie li - Sun Microsystems - Irvine United States secp = sptr; 2149b89a8333Snatalie li - Sun Microsystems - Irvine United States break; 2150b89a8333Snatalie li - Sun Microsystems - Irvine United States } 2151b89a8333Snatalie li - Sun Microsystems - Irvine United States } 2152b89a8333Snatalie li - Sun Microsystems - Irvine United States if (secp != NULL) { 2153b89a8333Snatalie li - Sun Microsystems - Irvine United States (void) crsetugid(cr, secp->s_rootid, 2154b89a8333Snatalie li - Sun Microsystems - Irvine United States secp->s_rootid); 2155b89a8333Snatalie li - Sun Microsystems - Irvine United States (void) crsetgroups(cr, 0, NULL); 2156b89a8333Snatalie li - Sun Microsystems - Irvine United States } 21575cb0d679SMarcel Telka } else if (crgetuid(cr) != uid || crgetgid(cr) != gid) { 21585cb0d679SMarcel Telka if (crsetugid(cr, uid, gid) != 0) 21595cb0d679SMarcel Telka anon_res = crsetugid(cr, 21605cb0d679SMarcel Telka exi->exi_export.ex_anon, 21615cb0d679SMarcel Telka exi->exi_export.ex_anon); 21625cb0d679SMarcel Telka (void) crsetgroups(cr, 0, NULL); 216389621fe1SMarcel Telka } else if (access & NFSAUTH_GROUPS) { 216489621fe1SMarcel Telka (void) crsetgroups(cr, ngids, gids); 21657c478bd9Sstevel@tonic-gate } 21665cb0d679SMarcel Telka 216789621fe1SMarcel Telka kmem_free(gids, ngids * sizeof (gid_t)); 216889621fe1SMarcel Telka 21697c478bd9Sstevel@tonic-gate break; 21707c478bd9Sstevel@tonic-gate 21717c478bd9Sstevel@tonic-gate case AUTH_DES: 21727c478bd9Sstevel@tonic-gate case RPCSEC_GSS: 21737c478bd9Sstevel@tonic-gate /* 21747c478bd9Sstevel@tonic-gate * Find the secinfo structure. We should be able 21757c478bd9Sstevel@tonic-gate * to find it by the time we reach here. 21767c478bd9Sstevel@tonic-gate * nfsauth_access() has done the checking. 21777c478bd9Sstevel@tonic-gate */ 21787c478bd9Sstevel@tonic-gate secp = NULL; 21797c478bd9Sstevel@tonic-gate for (i = 0; i < exi->exi_export.ex_seccnt; i++) { 21807c478bd9Sstevel@tonic-gate if (exi->exi_export.ex_secinfo[i].s_secinfo.sc_nfsnum == 21817c478bd9Sstevel@tonic-gate nfsflavor) { 21827c478bd9Sstevel@tonic-gate secp = &exi->exi_export.ex_secinfo[i]; 21837c478bd9Sstevel@tonic-gate break; 21847c478bd9Sstevel@tonic-gate } 21857c478bd9Sstevel@tonic-gate } 21867c478bd9Sstevel@tonic-gate 21877c478bd9Sstevel@tonic-gate if (!secp) { 21887c478bd9Sstevel@tonic-gate cmn_err(CE_NOTE, "nfs_server: client %s%shad " 21897c478bd9Sstevel@tonic-gate "no secinfo data for flavor %d", 21907c478bd9Sstevel@tonic-gate client_name(req), client_addr(req, buf), 21917c478bd9Sstevel@tonic-gate nfsflavor); 21927c478bd9Sstevel@tonic-gate return (0); 21937c478bd9Sstevel@tonic-gate } 21947c478bd9Sstevel@tonic-gate 21957c478bd9Sstevel@tonic-gate if (!checkwin(rpcflavor, secp->s_window, req)) { 21967c478bd9Sstevel@tonic-gate cmn_err(CE_NOTE, 21977c478bd9Sstevel@tonic-gate "nfs_server: client %s%sused invalid " 21987c478bd9Sstevel@tonic-gate "auth window value", 21997c478bd9Sstevel@tonic-gate client_name(req), client_addr(req, buf)); 22007c478bd9Sstevel@tonic-gate return (0); 22017c478bd9Sstevel@tonic-gate } 22027c478bd9Sstevel@tonic-gate 22037c478bd9Sstevel@tonic-gate /* 22047c478bd9Sstevel@tonic-gate * Map root principals listed in the share's root= list to root, 22057c478bd9Sstevel@tonic-gate * and map any others principals that were mapped to root by RPC 22067c478bd9Sstevel@tonic-gate * to anon. 22077c478bd9Sstevel@tonic-gate */ 22087c478bd9Sstevel@tonic-gate if (principal && sec_svc_inrootlist(rpcflavor, principal, 22097c478bd9Sstevel@tonic-gate secp->s_rootcnt, secp->s_rootnames)) { 2210b89a8333Snatalie li - Sun Microsystems - Irvine United States if (crgetuid(cr) == 0 && secp->s_rootid == 0) 22117c478bd9Sstevel@tonic-gate return (1); 22127c478bd9Sstevel@tonic-gate 2213b89a8333Snatalie li - Sun Microsystems - Irvine United States 2214b89a8333Snatalie li - Sun Microsystems - Irvine United States (void) crsetugid(cr, secp->s_rootid, secp->s_rootid); 22157c478bd9Sstevel@tonic-gate 22167c478bd9Sstevel@tonic-gate /* 22177c478bd9Sstevel@tonic-gate * NOTE: If and when kernel-land privilege tracing is 22187c478bd9Sstevel@tonic-gate * added this may have to be replaced with code that 22197c478bd9Sstevel@tonic-gate * retrieves root's supplementary groups (e.g., using 22207c478bd9Sstevel@tonic-gate * kgss_get_group_info(). In the meantime principals 22217c478bd9Sstevel@tonic-gate * mapped to uid 0 get all privileges, so setting cr's 22227c478bd9Sstevel@tonic-gate * supplementary groups for them does nothing. 22237c478bd9Sstevel@tonic-gate */ 22247c478bd9Sstevel@tonic-gate (void) crsetgroups(cr, 0, NULL); 22257c478bd9Sstevel@tonic-gate 22267c478bd9Sstevel@tonic-gate return (1); 22277c478bd9Sstevel@tonic-gate } 22287c478bd9Sstevel@tonic-gate 22297c478bd9Sstevel@tonic-gate /* 22307c478bd9Sstevel@tonic-gate * Not a root princ, or not in root list, map UID 0/nobody to 22317c478bd9Sstevel@tonic-gate * the anon ID for the share. (RPC sets cr's UIDs and GIDs to 22327c478bd9Sstevel@tonic-gate * UID_NOBODY and GID_NOBODY, respectively.) 22337c478bd9Sstevel@tonic-gate */ 22347c478bd9Sstevel@tonic-gate if (crgetuid(cr) != 0 && 22357c478bd9Sstevel@tonic-gate (crgetuid(cr) != UID_NOBODY || crgetgid(cr) != GID_NOBODY)) 22367c478bd9Sstevel@tonic-gate return (1); 22377c478bd9Sstevel@tonic-gate 22387c478bd9Sstevel@tonic-gate anon_res = crsetugid(cr, exi->exi_export.ex_anon, 22397c478bd9Sstevel@tonic-gate exi->exi_export.ex_anon); 22407c478bd9Sstevel@tonic-gate (void) crsetgroups(cr, 0, NULL); 22417c478bd9Sstevel@tonic-gate break; 22427c478bd9Sstevel@tonic-gate default: 22437c478bd9Sstevel@tonic-gate return (0); 22447c478bd9Sstevel@tonic-gate } /* switch on rpcflavor */ 22457c478bd9Sstevel@tonic-gate 22467c478bd9Sstevel@tonic-gate /* 22477c478bd9Sstevel@tonic-gate * Even if anon access is disallowed via ex_anon == -1, we allow 22487c478bd9Sstevel@tonic-gate * this access if anon_ok is set. So set creds to the default 22497c478bd9Sstevel@tonic-gate * "nobody" id. 22507c478bd9Sstevel@tonic-gate */ 22517c478bd9Sstevel@tonic-gate if (anon_res != 0) { 22527c478bd9Sstevel@tonic-gate if (anon_ok == 0) { 22537c478bd9Sstevel@tonic-gate cmn_err(CE_NOTE, 22547c478bd9Sstevel@tonic-gate "nfs_server: client %s%ssent wrong " 22557c478bd9Sstevel@tonic-gate "authentication for %s", 22567c478bd9Sstevel@tonic-gate client_name(req), client_addr(req, buf), 22577c478bd9Sstevel@tonic-gate exi->exi_export.ex_path ? 22587c478bd9Sstevel@tonic-gate exi->exi_export.ex_path : "?"); 22597c478bd9Sstevel@tonic-gate return (0); 22607c478bd9Sstevel@tonic-gate } 22617c478bd9Sstevel@tonic-gate 22627c478bd9Sstevel@tonic-gate if (crsetugid(cr, UID_NOBODY, GID_NOBODY) != 0) 22637c478bd9Sstevel@tonic-gate return (0); 22647c478bd9Sstevel@tonic-gate } 22657c478bd9Sstevel@tonic-gate 22667c478bd9Sstevel@tonic-gate return (1); 22677c478bd9Sstevel@tonic-gate } 22687c478bd9Sstevel@tonic-gate 22697c478bd9Sstevel@tonic-gate /* 22707c478bd9Sstevel@tonic-gate * returns 0 on failure, -1 on a drop, -2 on wrong security flavor, 22717c478bd9Sstevel@tonic-gate * and 1 on success 22727c478bd9Sstevel@tonic-gate */ 22737c478bd9Sstevel@tonic-gate int 22747c478bd9Sstevel@tonic-gate checkauth4(struct compound_state *cs, struct svc_req *req) 22757c478bd9Sstevel@tonic-gate { 22767c478bd9Sstevel@tonic-gate int i, rpcflavor, access; 22777c478bd9Sstevel@tonic-gate struct secinfo *secp; 22787c478bd9Sstevel@tonic-gate char buf[MAXHOST + 1]; 22797c478bd9Sstevel@tonic-gate int anon_res = 0, nfsflavor; 22807c478bd9Sstevel@tonic-gate struct exportinfo *exi; 22817c478bd9Sstevel@tonic-gate cred_t *cr; 22827c478bd9Sstevel@tonic-gate caddr_t principal; 22837c478bd9Sstevel@tonic-gate 22845cb0d679SMarcel Telka uid_t uid; 22855cb0d679SMarcel Telka gid_t gid; 228689621fe1SMarcel Telka uint_t ngids; 228789621fe1SMarcel Telka gid_t *gids; 22885cb0d679SMarcel Telka 22897c478bd9Sstevel@tonic-gate exi = cs->exi; 22907c478bd9Sstevel@tonic-gate cr = cs->cr; 22917c478bd9Sstevel@tonic-gate principal = cs->principal; 22927c478bd9Sstevel@tonic-gate nfsflavor = cs->nfsflavor; 22937c478bd9Sstevel@tonic-gate 22947c478bd9Sstevel@tonic-gate ASSERT(cr != NULL); 22957c478bd9Sstevel@tonic-gate 22967c478bd9Sstevel@tonic-gate rpcflavor = req->rq_cred.oa_flavor; 22977c478bd9Sstevel@tonic-gate cs->access &= ~CS_ACCESS_LIMITED; 2298b4ff7163SThomas Haynes 2299b4ff7163SThomas Haynes /* 2300b4ff7163SThomas Haynes * Check for privileged port number 2301b4ff7163SThomas Haynes * N.B.: this assumes that we know the format of a netbuf. 2302b4ff7163SThomas Haynes */ 2303b4ff7163SThomas Haynes if (nfs_portmon) { 2304b4ff7163SThomas Haynes struct sockaddr *ca; 2305b4ff7163SThomas Haynes ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf; 2306b4ff7163SThomas Haynes 2307b4ff7163SThomas Haynes if (ca == NULL) 2308b4ff7163SThomas Haynes return (0); 2309b4ff7163SThomas Haynes 2310b4ff7163SThomas Haynes if ((ca->sa_family == AF_INET && 2311b4ff7163SThomas Haynes ntohs(((struct sockaddr_in *)ca)->sin_port) >= 2312b4ff7163SThomas Haynes IPPORT_RESERVED) || 2313b4ff7163SThomas Haynes (ca->sa_family == AF_INET6 && 2314b4ff7163SThomas Haynes ntohs(((struct sockaddr_in6 *)ca)->sin6_port) >= 2315b4ff7163SThomas Haynes IPPORT_RESERVED)) { 2316b4ff7163SThomas Haynes cmn_err(CE_NOTE, 2317b4ff7163SThomas Haynes "nfs_server: client %s%ssent NFSv4 request from " 2318b4ff7163SThomas Haynes "unprivileged port", 2319b4ff7163SThomas Haynes client_name(req), client_addr(req, buf)); 2320b4ff7163SThomas Haynes return (0); 2321b4ff7163SThomas Haynes } 2322b4ff7163SThomas Haynes } 23237c478bd9Sstevel@tonic-gate 23247c478bd9Sstevel@tonic-gate /* 23257c478bd9Sstevel@tonic-gate * Check the access right per auth flavor on the vnode of 23267c478bd9Sstevel@tonic-gate * this export for the given request. 23277c478bd9Sstevel@tonic-gate */ 232889621fe1SMarcel Telka access = nfsauth4_access(cs->exi, cs->vp, req, cr, &uid, &gid, &ngids, 232989621fe1SMarcel Telka &gids); 23307c478bd9Sstevel@tonic-gate 23317c478bd9Sstevel@tonic-gate if (access & NFSAUTH_WRONGSEC) 23327c478bd9Sstevel@tonic-gate return (-2); /* no access for this security flavor */ 23337c478bd9Sstevel@tonic-gate 23347c478bd9Sstevel@tonic-gate if (access & NFSAUTH_DROP) 23357c478bd9Sstevel@tonic-gate return (-1); /* drop the request */ 23367c478bd9Sstevel@tonic-gate 23377c478bd9Sstevel@tonic-gate if (access & NFSAUTH_DENIED) { 23387c478bd9Sstevel@tonic-gate 23397c478bd9Sstevel@tonic-gate if (exi->exi_export.ex_seccnt > 0) 23407c478bd9Sstevel@tonic-gate return (0); /* deny access */ 23417c478bd9Sstevel@tonic-gate 23427c478bd9Sstevel@tonic-gate } else if (access & NFSAUTH_LIMITED) { 23437c478bd9Sstevel@tonic-gate 23447c478bd9Sstevel@tonic-gate cs->access |= CS_ACCESS_LIMITED; 23457c478bd9Sstevel@tonic-gate 23467c478bd9Sstevel@tonic-gate } else if (access & NFSAUTH_MAPNONE) { 23477c478bd9Sstevel@tonic-gate /* 23487c478bd9Sstevel@tonic-gate * Access was granted even though the flavor mismatched 23497c478bd9Sstevel@tonic-gate * because AUTH_NONE was one of the exported flavors. 23507c478bd9Sstevel@tonic-gate */ 23517c478bd9Sstevel@tonic-gate rpcflavor = AUTH_NONE; 23527c478bd9Sstevel@tonic-gate } 23537c478bd9Sstevel@tonic-gate 23547c478bd9Sstevel@tonic-gate /* 23557c478bd9Sstevel@tonic-gate * XXX probably need to redo some of it for nfsv4? 23567c478bd9Sstevel@tonic-gate * return 1 on success or 0 on failure 23577c478bd9Sstevel@tonic-gate */ 23587c478bd9Sstevel@tonic-gate 235989621fe1SMarcel Telka if (rpcflavor != AUTH_SYS) 236089621fe1SMarcel Telka kmem_free(gids, ngids * sizeof (gid_t)); 236189621fe1SMarcel Telka 23627c478bd9Sstevel@tonic-gate switch (rpcflavor) { 23637c478bd9Sstevel@tonic-gate case AUTH_NONE: 23647c478bd9Sstevel@tonic-gate anon_res = crsetugid(cr, exi->exi_export.ex_anon, 23657c478bd9Sstevel@tonic-gate exi->exi_export.ex_anon); 23667c478bd9Sstevel@tonic-gate (void) crsetgroups(cr, 0, NULL); 23677c478bd9Sstevel@tonic-gate break; 23687c478bd9Sstevel@tonic-gate 23697c478bd9Sstevel@tonic-gate case AUTH_UNIX: 23705cb0d679SMarcel Telka if (crgetuid(cr) == 0 && !(access & NFSAUTH_UIDMAP)) { 23717c478bd9Sstevel@tonic-gate anon_res = crsetugid(cr, exi->exi_export.ex_anon, 23727c478bd9Sstevel@tonic-gate exi->exi_export.ex_anon); 23737c478bd9Sstevel@tonic-gate (void) crsetgroups(cr, 0, NULL); 2374b89a8333Snatalie li - Sun Microsystems - Irvine United States } else if (crgetuid(cr) == 0 && access & NFSAUTH_ROOT) { 2375b89a8333Snatalie li - Sun Microsystems - Irvine United States /* 2376*aafcd32bSMarcel Telka * It is root, so apply rootid to get real UID. 2377b89a8333Snatalie li - Sun Microsystems - Irvine United States * Find the secinfo structure. We should be able 2378b89a8333Snatalie li - Sun Microsystems - Irvine United States * to find it by the time we reach here. 2379b89a8333Snatalie li - Sun Microsystems - Irvine United States * nfsauth_access() has done the checking. 2380b89a8333Snatalie li - Sun Microsystems - Irvine United States */ 2381b89a8333Snatalie li - Sun Microsystems - Irvine United States secp = NULL; 2382*aafcd32bSMarcel Telka rw_enter(&exported_lock, RW_READER); 2383b89a8333Snatalie li - Sun Microsystems - Irvine United States for (i = 0; i < exi->exi_export.ex_seccnt; i++) { 2384b89a8333Snatalie li - Sun Microsystems - Irvine United States struct secinfo *sptr; 2385b89a8333Snatalie li - Sun Microsystems - Irvine United States sptr = &exi->exi_export.ex_secinfo[i]; 2386b89a8333Snatalie li - Sun Microsystems - Irvine United States if (sptr->s_secinfo.sc_nfsnum == nfsflavor) { 2387b89a8333Snatalie li - Sun Microsystems - Irvine United States secp = &exi->exi_export.ex_secinfo[i]; 2388b89a8333Snatalie li - Sun Microsystems - Irvine United States break; 2389b89a8333Snatalie li - Sun Microsystems - Irvine United States } 2390b89a8333Snatalie li - Sun Microsystems - Irvine United States } 2391b89a8333Snatalie li - Sun Microsystems - Irvine United States if (secp != NULL) { 2392b89a8333Snatalie li - Sun Microsystems - Irvine United States (void) crsetugid(cr, secp->s_rootid, 2393b89a8333Snatalie li - Sun Microsystems - Irvine United States secp->s_rootid); 2394b89a8333Snatalie li - Sun Microsystems - Irvine United States (void) crsetgroups(cr, 0, NULL); 2395b89a8333Snatalie li - Sun Microsystems - Irvine United States } 2396*aafcd32bSMarcel Telka rw_exit(&exported_lock); 23975cb0d679SMarcel Telka } else if (crgetuid(cr) != uid || crgetgid(cr) != gid) { 23985cb0d679SMarcel Telka if (crsetugid(cr, uid, gid) != 0) 23995cb0d679SMarcel Telka anon_res = crsetugid(cr, 24005cb0d679SMarcel Telka exi->exi_export.ex_anon, 24015cb0d679SMarcel Telka exi->exi_export.ex_anon); 24025cb0d679SMarcel Telka (void) crsetgroups(cr, 0, NULL); 240389621fe1SMarcel Telka } if (access & NFSAUTH_GROUPS) { 240489621fe1SMarcel Telka (void) crsetgroups(cr, ngids, gids); 24057c478bd9Sstevel@tonic-gate } 24065cb0d679SMarcel Telka 240789621fe1SMarcel Telka kmem_free(gids, ngids * sizeof (gid_t)); 240889621fe1SMarcel Telka 24097c478bd9Sstevel@tonic-gate break; 24107c478bd9Sstevel@tonic-gate 24117c478bd9Sstevel@tonic-gate default: 24127c478bd9Sstevel@tonic-gate /* 24137c478bd9Sstevel@tonic-gate * Find the secinfo structure. We should be able 24147c478bd9Sstevel@tonic-gate * to find it by the time we reach here. 24157c478bd9Sstevel@tonic-gate * nfsauth_access() has done the checking. 24167c478bd9Sstevel@tonic-gate */ 24177c478bd9Sstevel@tonic-gate secp = NULL; 2418*aafcd32bSMarcel Telka rw_enter(&exported_lock, RW_READER); 24197c478bd9Sstevel@tonic-gate for (i = 0; i < exi->exi_export.ex_seccnt; i++) { 24207c478bd9Sstevel@tonic-gate if (exi->exi_export.ex_secinfo[i].s_secinfo.sc_nfsnum == 24217c478bd9Sstevel@tonic-gate nfsflavor) { 24227c478bd9Sstevel@tonic-gate secp = &exi->exi_export.ex_secinfo[i]; 24237c478bd9Sstevel@tonic-gate break; 24247c478bd9Sstevel@tonic-gate } 24257c478bd9Sstevel@tonic-gate } 24267c478bd9Sstevel@tonic-gate 2427*aafcd32bSMarcel Telka if (secp == NULL) { 2428*aafcd32bSMarcel Telka rw_exit(&exported_lock); 24297c478bd9Sstevel@tonic-gate cmn_err(CE_NOTE, "nfs_server: client %s%shad " 24307c478bd9Sstevel@tonic-gate "no secinfo data for flavor %d", 24317c478bd9Sstevel@tonic-gate client_name(req), client_addr(req, buf), 24327c478bd9Sstevel@tonic-gate nfsflavor); 24337c478bd9Sstevel@tonic-gate return (0); 24347c478bd9Sstevel@tonic-gate } 24357c478bd9Sstevel@tonic-gate 24367c478bd9Sstevel@tonic-gate if (!checkwin(rpcflavor, secp->s_window, req)) { 2437*aafcd32bSMarcel Telka rw_exit(&exported_lock); 24387c478bd9Sstevel@tonic-gate cmn_err(CE_NOTE, 24397c478bd9Sstevel@tonic-gate "nfs_server: client %s%sused invalid " 24407c478bd9Sstevel@tonic-gate "auth window value", 24417c478bd9Sstevel@tonic-gate client_name(req), client_addr(req, buf)); 24427c478bd9Sstevel@tonic-gate return (0); 24437c478bd9Sstevel@tonic-gate } 24447c478bd9Sstevel@tonic-gate 24457c478bd9Sstevel@tonic-gate /* 24467c478bd9Sstevel@tonic-gate * Map root principals listed in the share's root= list to root, 24477c478bd9Sstevel@tonic-gate * and map any others principals that were mapped to root by RPC 2448b89a8333Snatalie li - Sun Microsystems - Irvine United States * to anon. If not going to anon, set to rootid (root_mapping). 24497c478bd9Sstevel@tonic-gate */ 24507c478bd9Sstevel@tonic-gate if (principal && sec_svc_inrootlist(rpcflavor, principal, 24517c478bd9Sstevel@tonic-gate secp->s_rootcnt, secp->s_rootnames)) { 2452*aafcd32bSMarcel Telka if (crgetuid(cr) == 0 && secp->s_rootid == 0) { 2453*aafcd32bSMarcel Telka rw_exit(&exported_lock); 24547c478bd9Sstevel@tonic-gate return (1); 2455*aafcd32bSMarcel Telka } 24567c478bd9Sstevel@tonic-gate 2457b89a8333Snatalie li - Sun Microsystems - Irvine United States (void) crsetugid(cr, secp->s_rootid, secp->s_rootid); 24587c478bd9Sstevel@tonic-gate 2459*aafcd32bSMarcel Telka rw_exit(&exported_lock); 2460*aafcd32bSMarcel Telka 24617c478bd9Sstevel@tonic-gate /* 24627c478bd9Sstevel@tonic-gate * NOTE: If and when kernel-land privilege tracing is 24637c478bd9Sstevel@tonic-gate * added this may have to be replaced with code that 24647c478bd9Sstevel@tonic-gate * retrieves root's supplementary groups (e.g., using 24657c478bd9Sstevel@tonic-gate * kgss_get_group_info(). In the meantime principals 24667c478bd9Sstevel@tonic-gate * mapped to uid 0 get all privileges, so setting cr's 24677c478bd9Sstevel@tonic-gate * supplementary groups for them does nothing. 24687c478bd9Sstevel@tonic-gate */ 24697c478bd9Sstevel@tonic-gate (void) crsetgroups(cr, 0, NULL); 24707c478bd9Sstevel@tonic-gate 24717c478bd9Sstevel@tonic-gate return (1); 24727c478bd9Sstevel@tonic-gate } 24737c478bd9Sstevel@tonic-gate 2474*aafcd32bSMarcel Telka rw_exit(&exported_lock); 2475*aafcd32bSMarcel Telka 24767c478bd9Sstevel@tonic-gate /* 24777c478bd9Sstevel@tonic-gate * Not a root princ, or not in root list, map UID 0/nobody to 24787c478bd9Sstevel@tonic-gate * the anon ID for the share. (RPC sets cr's UIDs and GIDs to 24797c478bd9Sstevel@tonic-gate * UID_NOBODY and GID_NOBODY, respectively.) 24807c478bd9Sstevel@tonic-gate */ 24817c478bd9Sstevel@tonic-gate if (crgetuid(cr) != 0 && 24827c478bd9Sstevel@tonic-gate (crgetuid(cr) != UID_NOBODY || crgetgid(cr) != GID_NOBODY)) 24837c478bd9Sstevel@tonic-gate return (1); 24847c478bd9Sstevel@tonic-gate 24857c478bd9Sstevel@tonic-gate anon_res = crsetugid(cr, exi->exi_export.ex_anon, 24867c478bd9Sstevel@tonic-gate exi->exi_export.ex_anon); 24877c478bd9Sstevel@tonic-gate (void) crsetgroups(cr, 0, NULL); 24887c478bd9Sstevel@tonic-gate break; 24897c478bd9Sstevel@tonic-gate } /* switch on rpcflavor */ 24907c478bd9Sstevel@tonic-gate 24917c478bd9Sstevel@tonic-gate /* 24927c478bd9Sstevel@tonic-gate * Even if anon access is disallowed via ex_anon == -1, we allow 24937c478bd9Sstevel@tonic-gate * this access if anon_ok is set. So set creds to the default 24947c478bd9Sstevel@tonic-gate * "nobody" id. 24957c478bd9Sstevel@tonic-gate */ 24967c478bd9Sstevel@tonic-gate 24977c478bd9Sstevel@tonic-gate if (anon_res != 0) { 24987c478bd9Sstevel@tonic-gate cmn_err(CE_NOTE, 24997c478bd9Sstevel@tonic-gate "nfs_server: client %s%ssent wrong " 25007c478bd9Sstevel@tonic-gate "authentication for %s", 25017c478bd9Sstevel@tonic-gate client_name(req), client_addr(req, buf), 25027c478bd9Sstevel@tonic-gate exi->exi_export.ex_path ? 25037c478bd9Sstevel@tonic-gate exi->exi_export.ex_path : "?"); 25047c478bd9Sstevel@tonic-gate return (0); 25057c478bd9Sstevel@tonic-gate } 25067c478bd9Sstevel@tonic-gate 25077c478bd9Sstevel@tonic-gate return (1); 25087c478bd9Sstevel@tonic-gate } 25097c478bd9Sstevel@tonic-gate 25107c478bd9Sstevel@tonic-gate 25117c478bd9Sstevel@tonic-gate static char * 25127c478bd9Sstevel@tonic-gate client_name(struct svc_req *req) 25137c478bd9Sstevel@tonic-gate { 25147c478bd9Sstevel@tonic-gate char *hostname = NULL; 25157c478bd9Sstevel@tonic-gate 25167c478bd9Sstevel@tonic-gate /* 25177c478bd9Sstevel@tonic-gate * If it's a Unix cred then use the 25187c478bd9Sstevel@tonic-gate * hostname from the credential. 25197c478bd9Sstevel@tonic-gate */ 25207c478bd9Sstevel@tonic-gate if (req->rq_cred.oa_flavor == AUTH_UNIX) { 25217c478bd9Sstevel@tonic-gate hostname = ((struct authunix_parms *) 25227c478bd9Sstevel@tonic-gate req->rq_clntcred)->aup_machname; 25237c478bd9Sstevel@tonic-gate } 25247c478bd9Sstevel@tonic-gate if (hostname == NULL) 25257c478bd9Sstevel@tonic-gate hostname = ""; 25267c478bd9Sstevel@tonic-gate 25277c478bd9Sstevel@tonic-gate return (hostname); 25287c478bd9Sstevel@tonic-gate } 25297c478bd9Sstevel@tonic-gate 25307c478bd9Sstevel@tonic-gate static char * 25317c478bd9Sstevel@tonic-gate client_addr(struct svc_req *req, char *buf) 25327c478bd9Sstevel@tonic-gate { 25337c478bd9Sstevel@tonic-gate struct sockaddr *ca; 25347c478bd9Sstevel@tonic-gate uchar_t *b; 25357c478bd9Sstevel@tonic-gate char *frontspace = ""; 25367c478bd9Sstevel@tonic-gate 25377c478bd9Sstevel@tonic-gate /* 25387c478bd9Sstevel@tonic-gate * We assume we are called in tandem with client_name and the 25397c478bd9Sstevel@tonic-gate * format string looks like "...client %s%sblah blah..." 25407c478bd9Sstevel@tonic-gate * 25417c478bd9Sstevel@tonic-gate * If it's a Unix cred then client_name returned 25427c478bd9Sstevel@tonic-gate * a host name, so we need insert a space between host name 25437c478bd9Sstevel@tonic-gate * and IP address. 25447c478bd9Sstevel@tonic-gate */ 25457c478bd9Sstevel@tonic-gate if (req->rq_cred.oa_flavor == AUTH_UNIX) 25467c478bd9Sstevel@tonic-gate frontspace = " "; 25477c478bd9Sstevel@tonic-gate 25487c478bd9Sstevel@tonic-gate /* 25497c478bd9Sstevel@tonic-gate * Convert the caller's IP address to a dotted string 25507c478bd9Sstevel@tonic-gate */ 25517c478bd9Sstevel@tonic-gate ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf; 25527c478bd9Sstevel@tonic-gate 25537c478bd9Sstevel@tonic-gate if (ca->sa_family == AF_INET) { 25547c478bd9Sstevel@tonic-gate b = (uchar_t *)&((struct sockaddr_in *)ca)->sin_addr; 25557c478bd9Sstevel@tonic-gate (void) sprintf(buf, "%s(%d.%d.%d.%d) ", frontspace, 25567c478bd9Sstevel@tonic-gate b[0] & 0xFF, b[1] & 0xFF, b[2] & 0xFF, b[3] & 0xFF); 25577c478bd9Sstevel@tonic-gate } else if (ca->sa_family == AF_INET6) { 25587c478bd9Sstevel@tonic-gate struct sockaddr_in6 *sin6; 25597c478bd9Sstevel@tonic-gate sin6 = (struct sockaddr_in6 *)ca; 25607c478bd9Sstevel@tonic-gate (void) kinet_ntop6((uchar_t *)&sin6->sin6_addr, 25617c478bd9Sstevel@tonic-gate buf, INET6_ADDRSTRLEN); 25627c478bd9Sstevel@tonic-gate 25637c478bd9Sstevel@tonic-gate } else { 25647c478bd9Sstevel@tonic-gate 25657c478bd9Sstevel@tonic-gate /* 25667c478bd9Sstevel@tonic-gate * No IP address to print. If there was a host name 25677c478bd9Sstevel@tonic-gate * printed, then we print a space. 25687c478bd9Sstevel@tonic-gate */ 25697c478bd9Sstevel@tonic-gate (void) sprintf(buf, frontspace); 25707c478bd9Sstevel@tonic-gate } 25717c478bd9Sstevel@tonic-gate 25727c478bd9Sstevel@tonic-gate return (buf); 25737c478bd9Sstevel@tonic-gate } 25747c478bd9Sstevel@tonic-gate 25757c478bd9Sstevel@tonic-gate /* 25767c478bd9Sstevel@tonic-gate * NFS Server initialization routine. This routine should only be called 25777c478bd9Sstevel@tonic-gate * once. It performs the following tasks: 25787c478bd9Sstevel@tonic-gate * - Call sub-initialization routines (localize access to variables) 25797c478bd9Sstevel@tonic-gate * - Initialize all locks 25807c478bd9Sstevel@tonic-gate * - initialize the version 3 write verifier 25817c478bd9Sstevel@tonic-gate */ 25827c478bd9Sstevel@tonic-gate int 25837c478bd9Sstevel@tonic-gate nfs_srvinit(void) 25847c478bd9Sstevel@tonic-gate { 25857c478bd9Sstevel@tonic-gate int error; 25867c478bd9Sstevel@tonic-gate 25877c478bd9Sstevel@tonic-gate error = nfs_exportinit(); 25887c478bd9Sstevel@tonic-gate if (error != 0) 25897c478bd9Sstevel@tonic-gate return (error); 25907c478bd9Sstevel@tonic-gate error = rfs4_srvrinit(); 25917c478bd9Sstevel@tonic-gate if (error != 0) { 25927c478bd9Sstevel@tonic-gate nfs_exportfini(); 25937c478bd9Sstevel@tonic-gate return (error); 25947c478bd9Sstevel@tonic-gate } 25957c478bd9Sstevel@tonic-gate rfs_srvrinit(); 25967c478bd9Sstevel@tonic-gate rfs3_srvrinit(); 25977c478bd9Sstevel@tonic-gate nfsauth_init(); 25987c478bd9Sstevel@tonic-gate 25997c478bd9Sstevel@tonic-gate /* Init the stuff to control start/stop */ 26007c478bd9Sstevel@tonic-gate nfs_server_upordown = NFS_SERVER_STOPPED; 26017c478bd9Sstevel@tonic-gate mutex_init(&nfs_server_upordown_lock, NULL, MUTEX_DEFAULT, NULL); 26027c478bd9Sstevel@tonic-gate cv_init(&nfs_server_upordown_cv, NULL, CV_DEFAULT, NULL); 26037c478bd9Sstevel@tonic-gate mutex_init(&rdma_wait_mutex, NULL, MUTEX_DEFAULT, NULL); 26047c478bd9Sstevel@tonic-gate cv_init(&rdma_wait_cv, NULL, CV_DEFAULT, NULL); 26057c478bd9Sstevel@tonic-gate 26067c478bd9Sstevel@tonic-gate return (0); 26077c478bd9Sstevel@tonic-gate } 26087c478bd9Sstevel@tonic-gate 26097c478bd9Sstevel@tonic-gate /* 26107c478bd9Sstevel@tonic-gate * NFS Server finalization routine. This routine is called to cleanup the 26117c478bd9Sstevel@tonic-gate * initialization work previously performed if the NFS server module could 26127c478bd9Sstevel@tonic-gate * not be loaded correctly. 26137c478bd9Sstevel@tonic-gate */ 26147c478bd9Sstevel@tonic-gate void 26157c478bd9Sstevel@tonic-gate nfs_srvfini(void) 26167c478bd9Sstevel@tonic-gate { 26177c478bd9Sstevel@tonic-gate nfsauth_fini(); 26187c478bd9Sstevel@tonic-gate rfs3_srvrfini(); 26197c478bd9Sstevel@tonic-gate rfs_srvrfini(); 26207c478bd9Sstevel@tonic-gate nfs_exportfini(); 26217c478bd9Sstevel@tonic-gate 26227c478bd9Sstevel@tonic-gate mutex_destroy(&nfs_server_upordown_lock); 26237c478bd9Sstevel@tonic-gate cv_destroy(&nfs_server_upordown_cv); 26247c478bd9Sstevel@tonic-gate mutex_destroy(&rdma_wait_mutex); 26257c478bd9Sstevel@tonic-gate cv_destroy(&rdma_wait_cv); 26267c478bd9Sstevel@tonic-gate } 26277c478bd9Sstevel@tonic-gate 26287c478bd9Sstevel@tonic-gate /* 26297c478bd9Sstevel@tonic-gate * Set up an iovec array of up to cnt pointers. 26307c478bd9Sstevel@tonic-gate */ 26317c478bd9Sstevel@tonic-gate 26327c478bd9Sstevel@tonic-gate void 26337c478bd9Sstevel@tonic-gate mblk_to_iov(mblk_t *m, int cnt, struct iovec *iovp) 26347c478bd9Sstevel@tonic-gate { 26357c478bd9Sstevel@tonic-gate while (m != NULL && cnt-- > 0) { 26367c478bd9Sstevel@tonic-gate iovp->iov_base = (caddr_t)m->b_rptr; 26377c478bd9Sstevel@tonic-gate iovp->iov_len = (m->b_wptr - m->b_rptr); 26387c478bd9Sstevel@tonic-gate iovp++; 26397c478bd9Sstevel@tonic-gate m = m->b_cont; 26407c478bd9Sstevel@tonic-gate } 26417c478bd9Sstevel@tonic-gate } 26427c478bd9Sstevel@tonic-gate 26437c478bd9Sstevel@tonic-gate /* 26447c478bd9Sstevel@tonic-gate * Common code between NFS Version 2 and NFS Version 3 for the public 26457c478bd9Sstevel@tonic-gate * filehandle multicomponent lookups. 26467c478bd9Sstevel@tonic-gate */ 26477c478bd9Sstevel@tonic-gate 26487c478bd9Sstevel@tonic-gate /* 26497c478bd9Sstevel@tonic-gate * Public filehandle evaluation of a multi-component lookup, following 26507c478bd9Sstevel@tonic-gate * symbolic links, if necessary. This may result in a vnode in another 26517c478bd9Sstevel@tonic-gate * filesystem, which is OK as long as the other filesystem is exported. 26527c478bd9Sstevel@tonic-gate * 26537c478bd9Sstevel@tonic-gate * Note that the exi will be set either to NULL or a new reference to the 26547c478bd9Sstevel@tonic-gate * exportinfo struct that corresponds to the vnode of the multi-component path. 26557c478bd9Sstevel@tonic-gate * It is the callers responsibility to release this reference. 26567c478bd9Sstevel@tonic-gate */ 26577c478bd9Sstevel@tonic-gate int 26587c478bd9Sstevel@tonic-gate rfs_publicfh_mclookup(char *p, vnode_t *dvp, cred_t *cr, vnode_t **vpp, 26597c478bd9Sstevel@tonic-gate struct exportinfo **exi, struct sec_ol *sec) 26607c478bd9Sstevel@tonic-gate { 26617c478bd9Sstevel@tonic-gate int pathflag; 26627c478bd9Sstevel@tonic-gate vnode_t *mc_dvp = NULL; 26637c478bd9Sstevel@tonic-gate vnode_t *realvp; 26647c478bd9Sstevel@tonic-gate int error; 26657c478bd9Sstevel@tonic-gate 26667c478bd9Sstevel@tonic-gate *exi = NULL; 26677c478bd9Sstevel@tonic-gate 26687c478bd9Sstevel@tonic-gate /* 26697c478bd9Sstevel@tonic-gate * check if the given path is a url or native path. Since p is 26707c478bd9Sstevel@tonic-gate * modified by MCLpath(), it may be empty after returning from 26717c478bd9Sstevel@tonic-gate * there, and should be checked. 26727c478bd9Sstevel@tonic-gate */ 26737c478bd9Sstevel@tonic-gate if ((pathflag = MCLpath(&p)) == -1) 26747c478bd9Sstevel@tonic-gate return (EIO); 26757c478bd9Sstevel@tonic-gate 26767c478bd9Sstevel@tonic-gate /* 26777c478bd9Sstevel@tonic-gate * If pathflag is SECURITY_QUERY, turn the SEC_QUERY bit 26787c478bd9Sstevel@tonic-gate * on in sec->sec_flags. This bit will later serve as an 26797c478bd9Sstevel@tonic-gate * indication in makefh_ol() or makefh3_ol() to overload the 26807c478bd9Sstevel@tonic-gate * filehandle to contain the sec modes used by the server for 26817c478bd9Sstevel@tonic-gate * the path. 26827c478bd9Sstevel@tonic-gate */ 26837c478bd9Sstevel@tonic-gate if (pathflag == SECURITY_QUERY) { 26847c478bd9Sstevel@tonic-gate if ((sec->sec_index = (uint_t)(*p)) > 0) { 26857c478bd9Sstevel@tonic-gate sec->sec_flags |= SEC_QUERY; 26867c478bd9Sstevel@tonic-gate p++; 26877c478bd9Sstevel@tonic-gate if ((pathflag = MCLpath(&p)) == -1) 26887c478bd9Sstevel@tonic-gate return (EIO); 26897c478bd9Sstevel@tonic-gate } else { 26907c478bd9Sstevel@tonic-gate cmn_err(CE_NOTE, 26917c478bd9Sstevel@tonic-gate "nfs_server: invalid security index %d, " 26927c478bd9Sstevel@tonic-gate "violating WebNFS SNEGO protocol.", sec->sec_index); 26937c478bd9Sstevel@tonic-gate return (EIO); 26947c478bd9Sstevel@tonic-gate } 26957c478bd9Sstevel@tonic-gate } 26967c478bd9Sstevel@tonic-gate 26977c478bd9Sstevel@tonic-gate if (p[0] == '\0') { 26987c478bd9Sstevel@tonic-gate error = ENOENT; 26997c478bd9Sstevel@tonic-gate goto publicfh_done; 27007c478bd9Sstevel@tonic-gate } 27017c478bd9Sstevel@tonic-gate 27027c478bd9Sstevel@tonic-gate error = rfs_pathname(p, &mc_dvp, vpp, dvp, cr, pathflag); 27037c478bd9Sstevel@tonic-gate 27047c478bd9Sstevel@tonic-gate /* 27057c478bd9Sstevel@tonic-gate * If name resolves to "/" we get EINVAL since we asked for 27067c478bd9Sstevel@tonic-gate * the vnode of the directory that the file is in. Try again 27077c478bd9Sstevel@tonic-gate * with NULL directory vnode. 27087c478bd9Sstevel@tonic-gate */ 27097c478bd9Sstevel@tonic-gate if (error == EINVAL) { 27107c478bd9Sstevel@tonic-gate error = rfs_pathname(p, NULL, vpp, dvp, cr, pathflag); 27117c478bd9Sstevel@tonic-gate if (!error) { 27127c478bd9Sstevel@tonic-gate ASSERT(*vpp != NULL); 27137c478bd9Sstevel@tonic-gate if ((*vpp)->v_type == VDIR) { 27147c478bd9Sstevel@tonic-gate VN_HOLD(*vpp); 27157c478bd9Sstevel@tonic-gate mc_dvp = *vpp; 27167c478bd9Sstevel@tonic-gate } else { 27177c478bd9Sstevel@tonic-gate /* 27187c478bd9Sstevel@tonic-gate * This should not happen, the filesystem is 27197c478bd9Sstevel@tonic-gate * in an inconsistent state. Fail the lookup 27207c478bd9Sstevel@tonic-gate * at this point. 27217c478bd9Sstevel@tonic-gate */ 27227c478bd9Sstevel@tonic-gate VN_RELE(*vpp); 27237c478bd9Sstevel@tonic-gate error = EINVAL; 27247c478bd9Sstevel@tonic-gate } 27257c478bd9Sstevel@tonic-gate } 27267c478bd9Sstevel@tonic-gate } 27277c478bd9Sstevel@tonic-gate 27287c478bd9Sstevel@tonic-gate if (error) 27297c478bd9Sstevel@tonic-gate goto publicfh_done; 27307c478bd9Sstevel@tonic-gate 27317c478bd9Sstevel@tonic-gate if (*vpp == NULL) { 27327c478bd9Sstevel@tonic-gate error = ENOENT; 27337c478bd9Sstevel@tonic-gate goto publicfh_done; 27347c478bd9Sstevel@tonic-gate } 27357c478bd9Sstevel@tonic-gate 27367c478bd9Sstevel@tonic-gate ASSERT(mc_dvp != NULL); 27377c478bd9Sstevel@tonic-gate ASSERT(*vpp != NULL); 27387c478bd9Sstevel@tonic-gate 27397c478bd9Sstevel@tonic-gate if ((*vpp)->v_type == VDIR) { 27407c478bd9Sstevel@tonic-gate do { 27417c478bd9Sstevel@tonic-gate /* 27427c478bd9Sstevel@tonic-gate * *vpp may be an AutoFS node, so we perform 27437c478bd9Sstevel@tonic-gate * a VOP_ACCESS() to trigger the mount of the intended 27447c478bd9Sstevel@tonic-gate * filesystem, so we can perform the lookup in the 27457c478bd9Sstevel@tonic-gate * intended filesystem. 27467c478bd9Sstevel@tonic-gate */ 2747da6c28aaSamw (void) VOP_ACCESS(*vpp, 0, 0, cr, NULL); 27487c478bd9Sstevel@tonic-gate 27497c478bd9Sstevel@tonic-gate /* 27507c478bd9Sstevel@tonic-gate * If vnode is covered, get the 27517c478bd9Sstevel@tonic-gate * the topmost vnode. 27527c478bd9Sstevel@tonic-gate */ 27537c478bd9Sstevel@tonic-gate if (vn_mountedvfs(*vpp) != NULL) { 27547c478bd9Sstevel@tonic-gate error = traverse(vpp); 27557c478bd9Sstevel@tonic-gate if (error) { 27567c478bd9Sstevel@tonic-gate VN_RELE(*vpp); 27577c478bd9Sstevel@tonic-gate goto publicfh_done; 27587c478bd9Sstevel@tonic-gate } 27597c478bd9Sstevel@tonic-gate } 27607c478bd9Sstevel@tonic-gate 2761da6c28aaSamw if (VOP_REALVP(*vpp, &realvp, NULL) == 0 && 2762da6c28aaSamw realvp != *vpp) { 27637c478bd9Sstevel@tonic-gate /* 27647c478bd9Sstevel@tonic-gate * If realvp is different from *vpp 27657c478bd9Sstevel@tonic-gate * then release our reference on *vpp, so that 27667c478bd9Sstevel@tonic-gate * the export access check be performed on the 27677c478bd9Sstevel@tonic-gate * real filesystem instead. 27687c478bd9Sstevel@tonic-gate */ 27697c478bd9Sstevel@tonic-gate VN_HOLD(realvp); 27707c478bd9Sstevel@tonic-gate VN_RELE(*vpp); 27717c478bd9Sstevel@tonic-gate *vpp = realvp; 2772b89a8333Snatalie li - Sun Microsystems - Irvine United States } else { 27737c478bd9Sstevel@tonic-gate break; 2774b89a8333Snatalie li - Sun Microsystems - Irvine United States } 27757c478bd9Sstevel@tonic-gate /* LINTED */ 27767c478bd9Sstevel@tonic-gate } while (TRUE); 27777c478bd9Sstevel@tonic-gate 27787c478bd9Sstevel@tonic-gate /* 27797c478bd9Sstevel@tonic-gate * Let nfs_vptexi() figure what the real parent is. 27807c478bd9Sstevel@tonic-gate */ 27817c478bd9Sstevel@tonic-gate VN_RELE(mc_dvp); 27827c478bd9Sstevel@tonic-gate mc_dvp = NULL; 27837c478bd9Sstevel@tonic-gate 27847c478bd9Sstevel@tonic-gate } else { 27857c478bd9Sstevel@tonic-gate /* 27867c478bd9Sstevel@tonic-gate * If vnode is covered, get the 27877c478bd9Sstevel@tonic-gate * the topmost vnode. 27887c478bd9Sstevel@tonic-gate */ 27897c478bd9Sstevel@tonic-gate if (vn_mountedvfs(mc_dvp) != NULL) { 27907c478bd9Sstevel@tonic-gate error = traverse(&mc_dvp); 27917c478bd9Sstevel@tonic-gate if (error) { 27927c478bd9Sstevel@tonic-gate VN_RELE(*vpp); 27937c478bd9Sstevel@tonic-gate goto publicfh_done; 27947c478bd9Sstevel@tonic-gate } 27957c478bd9Sstevel@tonic-gate } 27967c478bd9Sstevel@tonic-gate 2797da6c28aaSamw if (VOP_REALVP(mc_dvp, &realvp, NULL) == 0 && 2798da6c28aaSamw realvp != mc_dvp) { 27997c478bd9Sstevel@tonic-gate /* 28007c478bd9Sstevel@tonic-gate * *vpp is a file, obtain realvp of the parent 28017c478bd9Sstevel@tonic-gate * directory vnode. 28027c478bd9Sstevel@tonic-gate */ 28037c478bd9Sstevel@tonic-gate VN_HOLD(realvp); 28047c478bd9Sstevel@tonic-gate VN_RELE(mc_dvp); 28057c478bd9Sstevel@tonic-gate mc_dvp = realvp; 28067c478bd9Sstevel@tonic-gate } 28077c478bd9Sstevel@tonic-gate } 28087c478bd9Sstevel@tonic-gate 28097c478bd9Sstevel@tonic-gate /* 28107c478bd9Sstevel@tonic-gate * The pathname may take us from the public filesystem to another. 28117c478bd9Sstevel@tonic-gate * If that's the case then just set the exportinfo to the new export 28127c478bd9Sstevel@tonic-gate * and build filehandle for it. Thanks to per-access checking there's 28137c478bd9Sstevel@tonic-gate * no security issues with doing this. If the client is not allowed 28147c478bd9Sstevel@tonic-gate * access to this new export then it will get an access error when it 28157c478bd9Sstevel@tonic-gate * tries to use the filehandle 28167c478bd9Sstevel@tonic-gate */ 28177c478bd9Sstevel@tonic-gate if (error = nfs_check_vpexi(mc_dvp, *vpp, kcred, exi)) { 28187c478bd9Sstevel@tonic-gate VN_RELE(*vpp); 28197c478bd9Sstevel@tonic-gate goto publicfh_done; 28207c478bd9Sstevel@tonic-gate } 28217c478bd9Sstevel@tonic-gate 28227c478bd9Sstevel@tonic-gate /* 28237c478bd9Sstevel@tonic-gate * Not allowed access to pseudo exports. 28247c478bd9Sstevel@tonic-gate */ 28257c478bd9Sstevel@tonic-gate if (PSEUDO(*exi)) { 28267c478bd9Sstevel@tonic-gate error = ENOENT; 28277c478bd9Sstevel@tonic-gate VN_RELE(*vpp); 28287c478bd9Sstevel@tonic-gate goto publicfh_done; 28297c478bd9Sstevel@tonic-gate } 28307c478bd9Sstevel@tonic-gate 28317c478bd9Sstevel@tonic-gate /* 28327c478bd9Sstevel@tonic-gate * Do a lookup for the index file. We know the index option doesn't 28337c478bd9Sstevel@tonic-gate * allow paths through handling in the share command, so mc_dvp will 28347c478bd9Sstevel@tonic-gate * be the parent for the index file vnode, if its present. Use 28357c478bd9Sstevel@tonic-gate * temporary pointers to preserve and reuse the vnode pointers of the 28367c478bd9Sstevel@tonic-gate * original directory in case there's no index file. Note that the 28377c478bd9Sstevel@tonic-gate * index file is a native path, and should not be interpreted by 28387c478bd9Sstevel@tonic-gate * the URL parser in rfs_pathname() 28397c478bd9Sstevel@tonic-gate */ 28407c478bd9Sstevel@tonic-gate if (((*exi)->exi_export.ex_flags & EX_INDEX) && 28417c478bd9Sstevel@tonic-gate ((*vpp)->v_type == VDIR) && (pathflag == URLPATH)) { 28427c478bd9Sstevel@tonic-gate vnode_t *tvp, *tmc_dvp; /* temporary vnode pointers */ 28437c478bd9Sstevel@tonic-gate 28447c478bd9Sstevel@tonic-gate tmc_dvp = mc_dvp; 28457c478bd9Sstevel@tonic-gate mc_dvp = tvp = *vpp; 28467c478bd9Sstevel@tonic-gate 28477c478bd9Sstevel@tonic-gate error = rfs_pathname((*exi)->exi_export.ex_index, NULL, vpp, 28487c478bd9Sstevel@tonic-gate mc_dvp, cr, NATIVEPATH); 28497c478bd9Sstevel@tonic-gate 28507c478bd9Sstevel@tonic-gate if (error == ENOENT) { 28517c478bd9Sstevel@tonic-gate *vpp = tvp; 28527c478bd9Sstevel@tonic-gate mc_dvp = tmc_dvp; 28537c478bd9Sstevel@tonic-gate error = 0; 28547c478bd9Sstevel@tonic-gate } else { /* ok or error other than ENOENT */ 28557c478bd9Sstevel@tonic-gate if (tmc_dvp) 28567c478bd9Sstevel@tonic-gate VN_RELE(tmc_dvp); 28577c478bd9Sstevel@tonic-gate if (error) 28587c478bd9Sstevel@tonic-gate goto publicfh_done; 28597c478bd9Sstevel@tonic-gate 28607c478bd9Sstevel@tonic-gate /* 28617c478bd9Sstevel@tonic-gate * Found a valid vp for index "filename". Sanity check 28627c478bd9Sstevel@tonic-gate * for odd case where a directory is provided as index 28637c478bd9Sstevel@tonic-gate * option argument and leads us to another filesystem 28647c478bd9Sstevel@tonic-gate */ 28657c478bd9Sstevel@tonic-gate 28667c478bd9Sstevel@tonic-gate /* Release the reference on the old exi value */ 2867596bc239SMarcel Telka ASSERT(*exi != NULL); 28687c478bd9Sstevel@tonic-gate exi_rele(*exi); 28697c478bd9Sstevel@tonic-gate 28707c478bd9Sstevel@tonic-gate if (error = nfs_check_vpexi(mc_dvp, *vpp, kcred, exi)) { 28717c478bd9Sstevel@tonic-gate VN_RELE(*vpp); 28727c478bd9Sstevel@tonic-gate goto publicfh_done; 28737c478bd9Sstevel@tonic-gate } 28747c478bd9Sstevel@tonic-gate } 28757c478bd9Sstevel@tonic-gate } 28767c478bd9Sstevel@tonic-gate 28777c478bd9Sstevel@tonic-gate publicfh_done: 28787c478bd9Sstevel@tonic-gate if (mc_dvp) 28797c478bd9Sstevel@tonic-gate VN_RELE(mc_dvp); 28807c478bd9Sstevel@tonic-gate 28817c478bd9Sstevel@tonic-gate return (error); 28827c478bd9Sstevel@tonic-gate } 28837c478bd9Sstevel@tonic-gate 28847c478bd9Sstevel@tonic-gate /* 28857c478bd9Sstevel@tonic-gate * Evaluate a multi-component path 28867c478bd9Sstevel@tonic-gate */ 28877c478bd9Sstevel@tonic-gate int 28887c478bd9Sstevel@tonic-gate rfs_pathname( 28897c478bd9Sstevel@tonic-gate char *path, /* pathname to evaluate */ 28907c478bd9Sstevel@tonic-gate vnode_t **dirvpp, /* ret for ptr to parent dir vnode */ 28917c478bd9Sstevel@tonic-gate vnode_t **compvpp, /* ret for ptr to component vnode */ 28927c478bd9Sstevel@tonic-gate vnode_t *startdvp, /* starting vnode */ 28937c478bd9Sstevel@tonic-gate cred_t *cr, /* user's credential */ 28947c478bd9Sstevel@tonic-gate int pathflag) /* flag to identify path, e.g. URL */ 28957c478bd9Sstevel@tonic-gate { 28967c478bd9Sstevel@tonic-gate char namebuf[TYPICALMAXPATHLEN]; 28977c478bd9Sstevel@tonic-gate struct pathname pn; 28987c478bd9Sstevel@tonic-gate int error; 28997c478bd9Sstevel@tonic-gate 29007c478bd9Sstevel@tonic-gate /* 29017c478bd9Sstevel@tonic-gate * If pathname starts with '/', then set startdvp to root. 29027c478bd9Sstevel@tonic-gate */ 29037c478bd9Sstevel@tonic-gate if (*path == '/') { 29047c478bd9Sstevel@tonic-gate while (*path == '/') 29057c478bd9Sstevel@tonic-gate path++; 29067c478bd9Sstevel@tonic-gate 29077c478bd9Sstevel@tonic-gate startdvp = rootdir; 29087c478bd9Sstevel@tonic-gate } 29097c478bd9Sstevel@tonic-gate 29107c478bd9Sstevel@tonic-gate error = pn_get_buf(path, UIO_SYSSPACE, &pn, namebuf, sizeof (namebuf)); 29117c478bd9Sstevel@tonic-gate if (error == 0) { 29127c478bd9Sstevel@tonic-gate /* 29137c478bd9Sstevel@tonic-gate * Call the URL parser for URL paths to modify the original 29147c478bd9Sstevel@tonic-gate * string to handle any '%' encoded characters that exist. 29157c478bd9Sstevel@tonic-gate * Done here to avoid an extra bcopy in the lookup. 29167c478bd9Sstevel@tonic-gate * We need to be careful about pathlen's. We know that 29177c478bd9Sstevel@tonic-gate * rfs_pathname() is called with a non-empty path. However, 29187c478bd9Sstevel@tonic-gate * it could be emptied due to the path simply being all /'s, 29197c478bd9Sstevel@tonic-gate * which is valid to proceed with the lookup, or due to the 29207c478bd9Sstevel@tonic-gate * URL parser finding an encoded null character at the 29217c478bd9Sstevel@tonic-gate * beginning of path which should not proceed with the lookup. 29227c478bd9Sstevel@tonic-gate */ 29237c478bd9Sstevel@tonic-gate if (pn.pn_pathlen != 0 && pathflag == URLPATH) { 29247c478bd9Sstevel@tonic-gate URLparse(pn.pn_path); 29257c478bd9Sstevel@tonic-gate if ((pn.pn_pathlen = strlen(pn.pn_path)) == 0) 29267c478bd9Sstevel@tonic-gate return (ENOENT); 29277c478bd9Sstevel@tonic-gate } 29287c478bd9Sstevel@tonic-gate VN_HOLD(startdvp); 29297c478bd9Sstevel@tonic-gate error = lookuppnvp(&pn, NULL, NO_FOLLOW, dirvpp, compvpp, 29307c478bd9Sstevel@tonic-gate rootdir, startdvp, cr); 29317c478bd9Sstevel@tonic-gate } 29327c478bd9Sstevel@tonic-gate if (error == ENAMETOOLONG) { 29337c478bd9Sstevel@tonic-gate /* 29347c478bd9Sstevel@tonic-gate * This thread used a pathname > TYPICALMAXPATHLEN bytes long. 29357c478bd9Sstevel@tonic-gate */ 29367c478bd9Sstevel@tonic-gate if (error = pn_get(path, UIO_SYSSPACE, &pn)) 29377c478bd9Sstevel@tonic-gate return (error); 29387c478bd9Sstevel@tonic-gate if (pn.pn_pathlen != 0 && pathflag == URLPATH) { 29397c478bd9Sstevel@tonic-gate URLparse(pn.pn_path); 29407c478bd9Sstevel@tonic-gate if ((pn.pn_pathlen = strlen(pn.pn_path)) == 0) { 29417c478bd9Sstevel@tonic-gate pn_free(&pn); 29427c478bd9Sstevel@tonic-gate return (ENOENT); 29437c478bd9Sstevel@tonic-gate } 29447c478bd9Sstevel@tonic-gate } 29457c478bd9Sstevel@tonic-gate VN_HOLD(startdvp); 29467c478bd9Sstevel@tonic-gate error = lookuppnvp(&pn, NULL, NO_FOLLOW, dirvpp, compvpp, 29477c478bd9Sstevel@tonic-gate rootdir, startdvp, cr); 29487c478bd9Sstevel@tonic-gate pn_free(&pn); 29497c478bd9Sstevel@tonic-gate } 29507c478bd9Sstevel@tonic-gate 29517c478bd9Sstevel@tonic-gate return (error); 29527c478bd9Sstevel@tonic-gate } 29537c478bd9Sstevel@tonic-gate 29547c478bd9Sstevel@tonic-gate /* 29557c478bd9Sstevel@tonic-gate * Adapt the multicomponent lookup path depending on the pathtype 29567c478bd9Sstevel@tonic-gate */ 29577c478bd9Sstevel@tonic-gate static int 29587c478bd9Sstevel@tonic-gate MCLpath(char **path) 29597c478bd9Sstevel@tonic-gate { 29607c478bd9Sstevel@tonic-gate unsigned char c = (unsigned char)**path; 29617c478bd9Sstevel@tonic-gate 29627c478bd9Sstevel@tonic-gate /* 29637c478bd9Sstevel@tonic-gate * If the MCL path is between 0x20 and 0x7E (graphic printable 29647c478bd9Sstevel@tonic-gate * character of the US-ASCII coded character set), its a URL path, 29657c478bd9Sstevel@tonic-gate * per RFC 1738. 29667c478bd9Sstevel@tonic-gate */ 29677c478bd9Sstevel@tonic-gate if (c >= 0x20 && c <= 0x7E) 29687c478bd9Sstevel@tonic-gate return (URLPATH); 29697c478bd9Sstevel@tonic-gate 29707c478bd9Sstevel@tonic-gate /* 29717c478bd9Sstevel@tonic-gate * If the first octet of the MCL path is not an ASCII character 29727c478bd9Sstevel@tonic-gate * then it must be interpreted as a tag value that describes the 29737c478bd9Sstevel@tonic-gate * format of the remaining octets of the MCL path. 29747c478bd9Sstevel@tonic-gate * 29757c478bd9Sstevel@tonic-gate * If the first octet of the MCL path is 0x81 it is a query 29767c478bd9Sstevel@tonic-gate * for the security info. 29777c478bd9Sstevel@tonic-gate */ 29787c478bd9Sstevel@tonic-gate switch (c) { 29797c478bd9Sstevel@tonic-gate case 0x80: /* native path, i.e. MCL via mount protocol */ 29807c478bd9Sstevel@tonic-gate (*path)++; 29817c478bd9Sstevel@tonic-gate return (NATIVEPATH); 29827c478bd9Sstevel@tonic-gate case 0x81: /* security query */ 29837c478bd9Sstevel@tonic-gate (*path)++; 29847c478bd9Sstevel@tonic-gate return (SECURITY_QUERY); 29857c478bd9Sstevel@tonic-gate default: 29867c478bd9Sstevel@tonic-gate return (-1); 29877c478bd9Sstevel@tonic-gate } 29887c478bd9Sstevel@tonic-gate } 29897c478bd9Sstevel@tonic-gate 29907c478bd9Sstevel@tonic-gate #define fromhex(c) ((c >= '0' && c <= '9') ? (c - '0') : \ 29917c478bd9Sstevel@tonic-gate ((c >= 'A' && c <= 'F') ? (c - 'A' + 10) :\ 29927c478bd9Sstevel@tonic-gate ((c >= 'a' && c <= 'f') ? (c - 'a' + 10) : 0))) 29937c478bd9Sstevel@tonic-gate 29947c478bd9Sstevel@tonic-gate /* 2995da6c28aaSamw * The implementation of URLparse guarantees that the final string will 29967c478bd9Sstevel@tonic-gate * fit in the original one. Replaces '%' occurrences followed by 2 characters 29977c478bd9Sstevel@tonic-gate * with its corresponding hexadecimal character. 29987c478bd9Sstevel@tonic-gate */ 29997c478bd9Sstevel@tonic-gate static void 30007c478bd9Sstevel@tonic-gate URLparse(char *str) 30017c478bd9Sstevel@tonic-gate { 30027c478bd9Sstevel@tonic-gate char *p, *q; 30037c478bd9Sstevel@tonic-gate 30047c478bd9Sstevel@tonic-gate p = q = str; 30057c478bd9Sstevel@tonic-gate while (*p) { 30067c478bd9Sstevel@tonic-gate *q = *p; 30077c478bd9Sstevel@tonic-gate if (*p++ == '%') { 30087c478bd9Sstevel@tonic-gate if (*p) { 30097c478bd9Sstevel@tonic-gate *q = fromhex(*p) * 16; 30107c478bd9Sstevel@tonic-gate p++; 30117c478bd9Sstevel@tonic-gate if (*p) { 30127c478bd9Sstevel@tonic-gate *q += fromhex(*p); 30137c478bd9Sstevel@tonic-gate p++; 30147c478bd9Sstevel@tonic-gate } 30157c478bd9Sstevel@tonic-gate } 30167c478bd9Sstevel@tonic-gate } 30177c478bd9Sstevel@tonic-gate q++; 30187c478bd9Sstevel@tonic-gate } 30197c478bd9Sstevel@tonic-gate *q = '\0'; 30207c478bd9Sstevel@tonic-gate } 30217c478bd9Sstevel@tonic-gate 30227c478bd9Sstevel@tonic-gate 30237c478bd9Sstevel@tonic-gate /* 30247c478bd9Sstevel@tonic-gate * Get the export information for the lookup vnode, and verify its 30257c478bd9Sstevel@tonic-gate * useable. 30267c478bd9Sstevel@tonic-gate */ 30277c478bd9Sstevel@tonic-gate int 30287c478bd9Sstevel@tonic-gate nfs_check_vpexi(vnode_t *mc_dvp, vnode_t *vp, cred_t *cr, 3029596bc239SMarcel Telka struct exportinfo **exi) 30307c478bd9Sstevel@tonic-gate { 30317c478bd9Sstevel@tonic-gate int walk; 30327c478bd9Sstevel@tonic-gate int error = 0; 30337c478bd9Sstevel@tonic-gate 3034596bc239SMarcel Telka *exi = nfs_vptoexi(mc_dvp, vp, cr, &walk, NULL, FALSE); 3035596bc239SMarcel Telka if (*exi == NULL) 30367c478bd9Sstevel@tonic-gate error = EACCES; 30377c478bd9Sstevel@tonic-gate else { 30387c478bd9Sstevel@tonic-gate /* 30397c478bd9Sstevel@tonic-gate * If nosub is set for this export then 30407c478bd9Sstevel@tonic-gate * a lookup relative to the public fh 30417c478bd9Sstevel@tonic-gate * must not terminate below the 30427c478bd9Sstevel@tonic-gate * exported directory. 30437c478bd9Sstevel@tonic-gate */ 3044596bc239SMarcel Telka if ((*exi)->exi_export.ex_flags & EX_NOSUB && walk > 0) 30457c478bd9Sstevel@tonic-gate error = EACCES; 30467c478bd9Sstevel@tonic-gate } 3047596bc239SMarcel Telka 30487c478bd9Sstevel@tonic-gate return (error); 30497c478bd9Sstevel@tonic-gate } 3050cee86682Scalum 3051cee86682Scalum /* 3052cee86682Scalum * Do the main work of handling HA-NFSv4 Resource Group failover on 3053cee86682Scalum * Sun Cluster. 3054cee86682Scalum * We need to detect whether any RG admin paths have been added or removed, 3055cee86682Scalum * and adjust resources accordingly. 3056cee86682Scalum * Currently we're using a very inefficient algorithm, ~ 2 * O(n**2). In 3057cee86682Scalum * order to scale, the list and array of paths need to be held in more 3058cee86682Scalum * suitable data structures. 3059cee86682Scalum */ 3060cee86682Scalum static void 3061cee86682Scalum hanfsv4_failover(void) 3062cee86682Scalum { 3063cee86682Scalum int i, start_grace, numadded_paths = 0; 3064cee86682Scalum char **added_paths = NULL; 3065cee86682Scalum rfs4_dss_path_t *dss_path; 3066cee86682Scalum 3067cee86682Scalum /* 306897669b90Scalum * Note: currently, rfs4_dss_pathlist cannot be NULL, since 306997669b90Scalum * it will always include an entry for NFS4_DSS_VAR_DIR. If we 307097669b90Scalum * make the latter dynamically specified too, the following will 307197669b90Scalum * need to be adjusted. 307297669b90Scalum */ 307397669b90Scalum 307497669b90Scalum /* 3075cee86682Scalum * First, look for removed paths: RGs that have been failed-over 3076cee86682Scalum * away from this node. 3077cee86682Scalum * Walk the "currently-serving" rfs4_dss_pathlist and, for each 3078cee86682Scalum * path, check if it is on the "passed-in" rfs4_dss_newpaths array 3079cee86682Scalum * from nfsd. If not, that RG path has been removed. 3080cee86682Scalum * 3081cee86682Scalum * Note that nfsd has sorted rfs4_dss_newpaths for us, and removed 3082cee86682Scalum * any duplicates. 3083cee86682Scalum */ 3084cee86682Scalum dss_path = rfs4_dss_pathlist; 3085cee86682Scalum do { 3086cee86682Scalum int found = 0; 3087cee86682Scalum char *path = dss_path->path; 3088cee86682Scalum 3089cee86682Scalum /* used only for non-HA so may not be removed */ 3090cee86682Scalum if (strcmp(path, NFS4_DSS_VAR_DIR) == 0) { 3091cee86682Scalum dss_path = dss_path->next; 3092cee86682Scalum continue; 3093cee86682Scalum } 3094cee86682Scalum 3095cee86682Scalum for (i = 0; i < rfs4_dss_numnewpaths; i++) { 3096cee86682Scalum int cmpret; 3097cee86682Scalum char *newpath = rfs4_dss_newpaths[i]; 3098cee86682Scalum 3099cee86682Scalum /* 3100cee86682Scalum * Since nfsd has sorted rfs4_dss_newpaths for us, 310197669b90Scalum * once the return from strcmp is negative we know 3102cee86682Scalum * we've passed the point where "path" should be, 3103cee86682Scalum * and can stop searching: "path" has been removed. 3104cee86682Scalum */ 310597669b90Scalum cmpret = strcmp(path, newpath); 3106cee86682Scalum if (cmpret < 0) 3107cee86682Scalum break; 3108cee86682Scalum if (cmpret == 0) { 3109cee86682Scalum found = 1; 3110cee86682Scalum break; 3111cee86682Scalum } 3112cee86682Scalum } 3113cee86682Scalum 3114cee86682Scalum if (found == 0) { 3115cee86682Scalum unsigned index = dss_path->index; 3116cee86682Scalum rfs4_servinst_t *sip = dss_path->sip; 3117cee86682Scalum rfs4_dss_path_t *path_next = dss_path->next; 3118cee86682Scalum 3119cee86682Scalum /* 3120cee86682Scalum * This path has been removed. 3121cee86682Scalum * We must clear out the servinst reference to 3122cee86682Scalum * it, since it's now owned by another 3123cee86682Scalum * node: we should not attempt to touch it. 3124cee86682Scalum */ 3125cee86682Scalum ASSERT(dss_path == sip->dss_paths[index]); 3126cee86682Scalum sip->dss_paths[index] = NULL; 3127cee86682Scalum 3128cee86682Scalum /* remove from "currently-serving" list, and destroy */ 3129cee86682Scalum remque(dss_path); 313097669b90Scalum /* allow for NUL */ 313197669b90Scalum kmem_free(dss_path->path, strlen(dss_path->path) + 1); 3132cee86682Scalum kmem_free(dss_path, sizeof (rfs4_dss_path_t)); 3133cee86682Scalum 3134cee86682Scalum dss_path = path_next; 3135cee86682Scalum } else { 3136cee86682Scalum /* path was found; not removed */ 3137cee86682Scalum dss_path = dss_path->next; 3138cee86682Scalum } 3139cee86682Scalum } while (dss_path != rfs4_dss_pathlist); 3140cee86682Scalum 3141cee86682Scalum /* 3142cee86682Scalum * Now, look for added paths: RGs that have been failed-over 3143cee86682Scalum * to this node. 3144cee86682Scalum * Walk the "passed-in" rfs4_dss_newpaths array from nfsd and, 3145cee86682Scalum * for each path, check if it is on the "currently-serving" 3146cee86682Scalum * rfs4_dss_pathlist. If not, that RG path has been added. 3147cee86682Scalum * 3148cee86682Scalum * Note: we don't do duplicate detection here; nfsd does that for us. 3149cee86682Scalum * 3150cee86682Scalum * Note: numadded_paths <= rfs4_dss_numnewpaths, which gives us 3151cee86682Scalum * an upper bound for the size needed for added_paths[numadded_paths]. 3152cee86682Scalum */ 3153cee86682Scalum 3154cee86682Scalum /* probably more space than we need, but guaranteed to be enough */ 3155cee86682Scalum if (rfs4_dss_numnewpaths > 0) { 3156cee86682Scalum size_t sz = rfs4_dss_numnewpaths * sizeof (char *); 3157cee86682Scalum added_paths = kmem_zalloc(sz, KM_SLEEP); 3158cee86682Scalum } 3159cee86682Scalum 3160cee86682Scalum /* walk the "passed-in" rfs4_dss_newpaths array from nfsd */ 3161cee86682Scalum for (i = 0; i < rfs4_dss_numnewpaths; i++) { 3162cee86682Scalum int found = 0; 3163cee86682Scalum char *newpath = rfs4_dss_newpaths[i]; 3164cee86682Scalum 3165cee86682Scalum dss_path = rfs4_dss_pathlist; 3166cee86682Scalum do { 3167cee86682Scalum char *path = dss_path->path; 3168cee86682Scalum 3169cee86682Scalum /* used only for non-HA */ 3170cee86682Scalum if (strcmp(path, NFS4_DSS_VAR_DIR) == 0) { 3171cee86682Scalum dss_path = dss_path->next; 3172cee86682Scalum continue; 3173cee86682Scalum } 3174cee86682Scalum 3175cee86682Scalum if (strncmp(path, newpath, strlen(path)) == 0) { 3176cee86682Scalum found = 1; 3177cee86682Scalum break; 3178cee86682Scalum } 3179cee86682Scalum 3180cee86682Scalum dss_path = dss_path->next; 3181cee86682Scalum } while (dss_path != rfs4_dss_pathlist); 3182cee86682Scalum 3183cee86682Scalum if (found == 0) { 3184cee86682Scalum added_paths[numadded_paths] = newpath; 3185cee86682Scalum numadded_paths++; 3186cee86682Scalum } 3187cee86682Scalum } 3188cee86682Scalum 3189cee86682Scalum /* did we find any added paths? */ 3190cee86682Scalum if (numadded_paths > 0) { 3191cee86682Scalum /* create a new server instance, and start its grace period */ 3192cee86682Scalum start_grace = 1; 3193cee86682Scalum rfs4_servinst_create(start_grace, numadded_paths, added_paths); 3194cee86682Scalum 3195cee86682Scalum /* read in the stable storage state from these paths */ 3196cee86682Scalum rfs4_dss_readstate(numadded_paths, added_paths); 3197cee86682Scalum 3198cee86682Scalum /* 3199cee86682Scalum * Multiple failovers during a grace period will cause 3200cee86682Scalum * clients of the same resource group to be partitioned 3201cee86682Scalum * into different server instances, with different 3202cee86682Scalum * grace periods. Since clients of the same resource 3203cee86682Scalum * group must be subject to the same grace period, 3204cee86682Scalum * we need to reset all currently active grace periods. 3205cee86682Scalum */ 3206cee86682Scalum rfs4_grace_reset_all(); 3207cee86682Scalum } 3208cee86682Scalum 3209cee86682Scalum if (rfs4_dss_numnewpaths > 0) 3210cee86682Scalum kmem_free(added_paths, rfs4_dss_numnewpaths * sizeof (char *)); 3211cee86682Scalum } 3212bd6f1640SJarrett Lu 3213bd6f1640SJarrett Lu /* 3214bd6f1640SJarrett Lu * Used by NFSv3 and NFSv4 server to query label of 3215bd6f1640SJarrett Lu * a pathname component during lookup/access ops. 3216bd6f1640SJarrett Lu */ 3217bd6f1640SJarrett Lu ts_label_t * 3218bd6f1640SJarrett Lu nfs_getflabel(vnode_t *vp, struct exportinfo *exi) 3219bd6f1640SJarrett Lu { 3220bd6f1640SJarrett Lu zone_t *zone; 3221bd6f1640SJarrett Lu ts_label_t *zone_label; 3222bd6f1640SJarrett Lu char *path; 3223bd6f1640SJarrett Lu 3224bd6f1640SJarrett Lu mutex_enter(&vp->v_lock); 3225bd6f1640SJarrett Lu if (vp->v_path != NULL) { 3226bd6f1640SJarrett Lu zone = zone_find_by_any_path(vp->v_path, B_FALSE); 3227bd6f1640SJarrett Lu mutex_exit(&vp->v_lock); 3228bd6f1640SJarrett Lu } else { 3229bd6f1640SJarrett Lu /* 3230bd6f1640SJarrett Lu * v_path not cached. Fall back on pathname of exported 3231bd6f1640SJarrett Lu * file system as we rely on pathname from which we can 3232bd6f1640SJarrett Lu * derive a label. The exported file system portion of 3233bd6f1640SJarrett Lu * path is sufficient to obtain a label. 3234bd6f1640SJarrett Lu */ 3235bd6f1640SJarrett Lu path = exi->exi_export.ex_path; 3236bd6f1640SJarrett Lu if (path == NULL) { 3237bd6f1640SJarrett Lu mutex_exit(&vp->v_lock); 3238bd6f1640SJarrett Lu return (NULL); 3239bd6f1640SJarrett Lu } 3240bd6f1640SJarrett Lu zone = zone_find_by_any_path(path, B_FALSE); 3241bd6f1640SJarrett Lu mutex_exit(&vp->v_lock); 3242bd6f1640SJarrett Lu } 3243bd6f1640SJarrett Lu /* 3244bd6f1640SJarrett Lu * Caller has verified that the file is either 3245bd6f1640SJarrett Lu * exported or visible. So if the path falls in 3246bd6f1640SJarrett Lu * global zone, admin_low is returned; otherwise 3247bd6f1640SJarrett Lu * the zone's label is returned. 3248bd6f1640SJarrett Lu */ 3249bd6f1640SJarrett Lu zone_label = zone->zone_slabel; 3250bd6f1640SJarrett Lu label_hold(zone_label); 3251bd6f1640SJarrett Lu zone_rele(zone); 3252bd6f1640SJarrett Lu return (zone_label); 3253bd6f1640SJarrett Lu } 3254bd6f1640SJarrett Lu 3255bd6f1640SJarrett Lu /* 3256bd6f1640SJarrett Lu * TX NFS routine used by NFSv3 and NFSv4 to do label check 3257bd6f1640SJarrett Lu * on client label and server's file object lable. 3258bd6f1640SJarrett Lu */ 3259bd6f1640SJarrett Lu boolean_t 3260bd6f1640SJarrett Lu do_rfs_label_check(bslabel_t *clabel, vnode_t *vp, int flag, 3261bd6f1640SJarrett Lu struct exportinfo *exi) 3262bd6f1640SJarrett Lu { 3263bd6f1640SJarrett Lu bslabel_t *slabel; 3264bd6f1640SJarrett Lu ts_label_t *tslabel; 3265bd6f1640SJarrett Lu boolean_t result; 3266bd6f1640SJarrett Lu 3267bd6f1640SJarrett Lu if ((tslabel = nfs_getflabel(vp, exi)) == NULL) { 3268bd6f1640SJarrett Lu return (B_FALSE); 3269bd6f1640SJarrett Lu } 3270bd6f1640SJarrett Lu slabel = label2bslabel(tslabel); 3271bd6f1640SJarrett Lu DTRACE_PROBE4(tx__rfs__log__info__labelcheck, char *, 3272bd6f1640SJarrett Lu "comparing server's file label(1) with client label(2) (vp(3))", 3273bd6f1640SJarrett Lu bslabel_t *, slabel, bslabel_t *, clabel, vnode_t *, vp); 3274bd6f1640SJarrett Lu 3275bd6f1640SJarrett Lu if (flag == EQUALITY_CHECK) 3276bd6f1640SJarrett Lu result = blequal(clabel, slabel); 3277bd6f1640SJarrett Lu else 3278bd6f1640SJarrett Lu result = bldominates(clabel, slabel); 3279bd6f1640SJarrett Lu label_rele(tslabel); 3280bd6f1640SJarrett Lu return (result); 3281bd6f1640SJarrett Lu } 3282c242f9a0Schunli zhang - Sun Microsystems - Irvine United States 3283c242f9a0Schunli zhang - Sun Microsystems - Irvine United States /* 3284c242f9a0Schunli zhang - Sun Microsystems - Irvine United States * Callback function to return the loaned buffers. 3285c242f9a0Schunli zhang - Sun Microsystems - Irvine United States * Calls VOP_RETZCBUF() only after all uio_iov[] 3286c242f9a0Schunli zhang - Sun Microsystems - Irvine United States * buffers are returned. nu_ref maintains the count. 3287c242f9a0Schunli zhang - Sun Microsystems - Irvine United States */ 3288c242f9a0Schunli zhang - Sun Microsystems - Irvine United States void 3289c242f9a0Schunli zhang - Sun Microsystems - Irvine United States rfs_free_xuio(void *free_arg) 3290c242f9a0Schunli zhang - Sun Microsystems - Irvine United States { 3291c242f9a0Schunli zhang - Sun Microsystems - Irvine United States uint_t ref; 3292c242f9a0Schunli zhang - Sun Microsystems - Irvine United States nfs_xuio_t *nfsuiop = (nfs_xuio_t *)free_arg; 3293c242f9a0Schunli zhang - Sun Microsystems - Irvine United States 3294c242f9a0Schunli zhang - Sun Microsystems - Irvine United States ref = atomic_dec_uint_nv(&nfsuiop->nu_ref); 3295c242f9a0Schunli zhang - Sun Microsystems - Irvine United States 3296c242f9a0Schunli zhang - Sun Microsystems - Irvine United States /* 3297c242f9a0Schunli zhang - Sun Microsystems - Irvine United States * Call VOP_RETZCBUF() only when all the iov buffers 3298c242f9a0Schunli zhang - Sun Microsystems - Irvine United States * are sent OTW. 3299c242f9a0Schunli zhang - Sun Microsystems - Irvine United States */ 3300c242f9a0Schunli zhang - Sun Microsystems - Irvine United States if (ref != 0) 3301c242f9a0Schunli zhang - Sun Microsystems - Irvine United States return; 3302c242f9a0Schunli zhang - Sun Microsystems - Irvine United States 3303c242f9a0Schunli zhang - Sun Microsystems - Irvine United States if (((uio_t *)nfsuiop)->uio_extflg & UIO_XUIO) { 3304c242f9a0Schunli zhang - Sun Microsystems - Irvine United States (void) VOP_RETZCBUF(nfsuiop->nu_vp, (xuio_t *)free_arg, NULL, 3305c242f9a0Schunli zhang - Sun Microsystems - Irvine United States NULL); 3306c242f9a0Schunli zhang - Sun Microsystems - Irvine United States VN_RELE(nfsuiop->nu_vp); 3307c242f9a0Schunli zhang - Sun Microsystems - Irvine United States } 3308c242f9a0Schunli zhang - Sun Microsystems - Irvine United States 3309c242f9a0Schunli zhang - Sun Microsystems - Irvine United States kmem_cache_free(nfs_xuio_cache, free_arg); 3310c242f9a0Schunli zhang - Sun Microsystems - Irvine United States } 3311c242f9a0Schunli zhang - Sun Microsystems - Irvine United States 3312c242f9a0Schunli zhang - Sun Microsystems - Irvine United States xuio_t * 3313c242f9a0Schunli zhang - Sun Microsystems - Irvine United States rfs_setup_xuio(vnode_t *vp) 3314c242f9a0Schunli zhang - Sun Microsystems - Irvine United States { 3315c242f9a0Schunli zhang - Sun Microsystems - Irvine United States nfs_xuio_t *nfsuiop; 3316c242f9a0Schunli zhang - Sun Microsystems - Irvine United States 3317c242f9a0Schunli zhang - Sun Microsystems - Irvine United States nfsuiop = kmem_cache_alloc(nfs_xuio_cache, KM_SLEEP); 3318c242f9a0Schunli zhang - Sun Microsystems - Irvine United States 3319c242f9a0Schunli zhang - Sun Microsystems - Irvine United States bzero(nfsuiop, sizeof (nfs_xuio_t)); 3320c242f9a0Schunli zhang - Sun Microsystems - Irvine United States nfsuiop->nu_vp = vp; 3321c242f9a0Schunli zhang - Sun Microsystems - Irvine United States 3322c242f9a0Schunli zhang - Sun Microsystems - Irvine United States /* 3323c242f9a0Schunli zhang - Sun Microsystems - Irvine United States * ref count set to 1. more may be added 3324c242f9a0Schunli zhang - Sun Microsystems - Irvine United States * if multiple mblks refer to multiple iov's. 3325c242f9a0Schunli zhang - Sun Microsystems - Irvine United States * This is done in uio_to_mblk(). 3326c242f9a0Schunli zhang - Sun Microsystems - Irvine United States */ 3327c242f9a0Schunli zhang - Sun Microsystems - Irvine United States 3328c242f9a0Schunli zhang - Sun Microsystems - Irvine United States nfsuiop->nu_ref = 1; 3329c242f9a0Schunli zhang - Sun Microsystems - Irvine United States 3330c242f9a0Schunli zhang - Sun Microsystems - Irvine United States nfsuiop->nu_frtn.free_func = rfs_free_xuio; 3331c242f9a0Schunli zhang - Sun Microsystems - Irvine United States nfsuiop->nu_frtn.free_arg = (char *)nfsuiop; 3332c242f9a0Schunli zhang - Sun Microsystems - Irvine United States 3333c242f9a0Schunli zhang - Sun Microsystems - Irvine United States nfsuiop->nu_uio.xu_type = UIOTYPE_ZEROCOPY; 3334c242f9a0Schunli zhang - Sun Microsystems - Irvine United States 3335c242f9a0Schunli zhang - Sun Microsystems - Irvine United States return (&nfsuiop->nu_uio); 3336c242f9a0Schunli zhang - Sun Microsystems - Irvine United States } 3337c242f9a0Schunli zhang - Sun Microsystems - Irvine United States 3338c242f9a0Schunli zhang - Sun Microsystems - Irvine United States mblk_t * 3339c242f9a0Schunli zhang - Sun Microsystems - Irvine United States uio_to_mblk(uio_t *uiop) 3340c242f9a0Schunli zhang - Sun Microsystems - Irvine United States { 3341c242f9a0Schunli zhang - Sun Microsystems - Irvine United States struct iovec *iovp; 3342c242f9a0Schunli zhang - Sun Microsystems - Irvine United States int i; 3343c242f9a0Schunli zhang - Sun Microsystems - Irvine United States mblk_t *mp, *mp1; 3344c242f9a0Schunli zhang - Sun Microsystems - Irvine United States nfs_xuio_t *nfsuiop = (nfs_xuio_t *)uiop; 3345c242f9a0Schunli zhang - Sun Microsystems - Irvine United States 3346c242f9a0Schunli zhang - Sun Microsystems - Irvine United States if (uiop->uio_iovcnt == 0) 3347c242f9a0Schunli zhang - Sun Microsystems - Irvine United States return (NULL); 3348c242f9a0Schunli zhang - Sun Microsystems - Irvine United States 3349c242f9a0Schunli zhang - Sun Microsystems - Irvine United States iovp = uiop->uio_iov; 3350c242f9a0Schunli zhang - Sun Microsystems - Irvine United States mp = mp1 = esballoca((uchar_t *)iovp->iov_base, iovp->iov_len, 3351c242f9a0Schunli zhang - Sun Microsystems - Irvine United States BPRI_MED, &nfsuiop->nu_frtn); 3352c242f9a0Schunli zhang - Sun Microsystems - Irvine United States ASSERT(mp != NULL); 3353c242f9a0Schunli zhang - Sun Microsystems - Irvine United States 3354c242f9a0Schunli zhang - Sun Microsystems - Irvine United States mp->b_wptr += iovp->iov_len; 3355c242f9a0Schunli zhang - Sun Microsystems - Irvine United States mp->b_datap->db_type = M_DATA; 3356c242f9a0Schunli zhang - Sun Microsystems - Irvine United States 3357c242f9a0Schunli zhang - Sun Microsystems - Irvine United States for (i = 1; i < uiop->uio_iovcnt; i++) { 3358c242f9a0Schunli zhang - Sun Microsystems - Irvine United States iovp = (uiop->uio_iov + i); 3359c242f9a0Schunli zhang - Sun Microsystems - Irvine United States 3360c242f9a0Schunli zhang - Sun Microsystems - Irvine United States mp1->b_cont = esballoca( 3361c242f9a0Schunli zhang - Sun Microsystems - Irvine United States (uchar_t *)iovp->iov_base, iovp->iov_len, BPRI_MED, 3362c242f9a0Schunli zhang - Sun Microsystems - Irvine United States &nfsuiop->nu_frtn); 3363c242f9a0Schunli zhang - Sun Microsystems - Irvine United States 3364c242f9a0Schunli zhang - Sun Microsystems - Irvine United States mp1 = mp1->b_cont; 3365c242f9a0Schunli zhang - Sun Microsystems - Irvine United States ASSERT(mp1 != NULL); 3366c242f9a0Schunli zhang - Sun Microsystems - Irvine United States mp1->b_wptr += iovp->iov_len; 3367c242f9a0Schunli zhang - Sun Microsystems - Irvine United States mp1->b_datap->db_type = M_DATA; 3368c242f9a0Schunli zhang - Sun Microsystems - Irvine United States } 3369c242f9a0Schunli zhang - Sun Microsystems - Irvine United States 3370c242f9a0Schunli zhang - Sun Microsystems - Irvine United States nfsuiop->nu_ref = uiop->uio_iovcnt; 3371c242f9a0Schunli zhang - Sun Microsystems - Irvine United States 3372c242f9a0Schunli zhang - Sun Microsystems - Irvine United States return (mp); 3373c242f9a0Schunli zhang - Sun Microsystems - Irvine United States } 3374c242f9a0Schunli zhang - Sun Microsystems - Irvine United States 3375e36d7b11SSebastien Roy /* 3376e36d7b11SSebastien Roy * Allocate memory to hold data for a read request of len bytes. 3377e36d7b11SSebastien Roy * 3378e36d7b11SSebastien Roy * We don't allocate buffers greater than kmem_max_cached in size to avoid 3379e36d7b11SSebastien Roy * allocating memory from the kmem_oversized arena. If we allocate oversized 3380e36d7b11SSebastien Roy * buffers, we incur heavy cross-call activity when freeing these large buffers 3381e36d7b11SSebastien Roy * in the TCP receive path. Note that we can't set b_wptr here since the 3382e36d7b11SSebastien Roy * length of the data returned may differ from the length requested when 3383e36d7b11SSebastien Roy * reading the end of a file; we set b_wptr in rfs_rndup_mblks() once the 3384e36d7b11SSebastien Roy * length of the read is known. 3385e36d7b11SSebastien Roy */ 3386e36d7b11SSebastien Roy mblk_t * 3387e36d7b11SSebastien Roy rfs_read_alloc(uint_t len, struct iovec **iov, int *iovcnt) 3388e36d7b11SSebastien Roy { 3389e36d7b11SSebastien Roy struct iovec *iovarr; 3390e36d7b11SSebastien Roy mblk_t *mp, **mpp = ∓ 3391e36d7b11SSebastien Roy size_t mpsize; 3392e36d7b11SSebastien Roy uint_t remain = len; 3393e36d7b11SSebastien Roy int i, err = 0; 3394e36d7b11SSebastien Roy 3395e36d7b11SSebastien Roy *iovcnt = howmany(len, kmem_max_cached); 3396e36d7b11SSebastien Roy 3397e36d7b11SSebastien Roy iovarr = kmem_alloc(*iovcnt * sizeof (struct iovec), KM_SLEEP); 3398e36d7b11SSebastien Roy *iov = iovarr; 3399e36d7b11SSebastien Roy 3400e36d7b11SSebastien Roy for (i = 0; i < *iovcnt; remain -= mpsize, i++) { 3401e36d7b11SSebastien Roy ASSERT(remain <= len); 3402e36d7b11SSebastien Roy /* 3403e36d7b11SSebastien Roy * We roundup the size we allocate to a multiple of 3404e36d7b11SSebastien Roy * BYTES_PER_XDR_UNIT (4 bytes) so that the call to 3405e36d7b11SSebastien Roy * xdrmblk_putmblk() never fails. 3406e36d7b11SSebastien Roy */ 3407e36d7b11SSebastien Roy ASSERT(kmem_max_cached % BYTES_PER_XDR_UNIT == 0); 3408e36d7b11SSebastien Roy mpsize = MIN(kmem_max_cached, remain); 3409e36d7b11SSebastien Roy *mpp = allocb_wait(RNDUP(mpsize), BPRI_MED, STR_NOSIG, &err); 3410e36d7b11SSebastien Roy ASSERT(*mpp != NULL); 3411e36d7b11SSebastien Roy ASSERT(err == 0); 3412e36d7b11SSebastien Roy 3413e36d7b11SSebastien Roy iovarr[i].iov_base = (caddr_t)(*mpp)->b_rptr; 3414e36d7b11SSebastien Roy iovarr[i].iov_len = mpsize; 3415e36d7b11SSebastien Roy mpp = &(*mpp)->b_cont; 3416e36d7b11SSebastien Roy } 3417e36d7b11SSebastien Roy return (mp); 3418e36d7b11SSebastien Roy } 3419e36d7b11SSebastien Roy 3420c242f9a0Schunli zhang - Sun Microsystems - Irvine United States void 3421c242f9a0Schunli zhang - Sun Microsystems - Irvine United States rfs_rndup_mblks(mblk_t *mp, uint_t len, int buf_loaned) 3422c242f9a0Schunli zhang - Sun Microsystems - Irvine United States { 3423e36d7b11SSebastien Roy int i; 3424c242f9a0Schunli zhang - Sun Microsystems - Irvine United States int alloc_err = 0; 3425c242f9a0Schunli zhang - Sun Microsystems - Irvine United States mblk_t *rmp; 3426e36d7b11SSebastien Roy uint_t mpsize, remainder; 3427c242f9a0Schunli zhang - Sun Microsystems - Irvine United States 3428e36d7b11SSebastien Roy remainder = P2NPHASE(len, BYTES_PER_XDR_UNIT); 3429c242f9a0Schunli zhang - Sun Microsystems - Irvine United States 3430e36d7b11SSebastien Roy /* 3431e36d7b11SSebastien Roy * Non copy-reduction case. This function assumes that blocks were 3432e36d7b11SSebastien Roy * allocated in multiples of BYTES_PER_XDR_UNIT bytes, which makes this 3433e36d7b11SSebastien Roy * padding safe without bounds checking. 3434e36d7b11SSebastien Roy */ 3435c242f9a0Schunli zhang - Sun Microsystems - Irvine United States if (!buf_loaned) { 3436e36d7b11SSebastien Roy /* 3437e36d7b11SSebastien Roy * Set the size of each mblk in the chain until we've consumed 3438e36d7b11SSebastien Roy * the specified length for all but the last one. 3439e36d7b11SSebastien Roy */ 3440e36d7b11SSebastien Roy while ((mpsize = MBLKSIZE(mp)) < len) { 3441e36d7b11SSebastien Roy ASSERT(mpsize % BYTES_PER_XDR_UNIT == 0); 3442e36d7b11SSebastien Roy mp->b_wptr += mpsize; 3443e36d7b11SSebastien Roy len -= mpsize; 3444e36d7b11SSebastien Roy mp = mp->b_cont; 3445e36d7b11SSebastien Roy ASSERT(mp != NULL); 3446e36d7b11SSebastien Roy } 3447e36d7b11SSebastien Roy 3448e36d7b11SSebastien Roy ASSERT(len + remainder <= mpsize); 3449c242f9a0Schunli zhang - Sun Microsystems - Irvine United States mp->b_wptr += len; 3450e36d7b11SSebastien Roy for (i = 0; i < remainder; i++) 3451c242f9a0Schunli zhang - Sun Microsystems - Irvine United States *mp->b_wptr++ = '\0'; 3452c242f9a0Schunli zhang - Sun Microsystems - Irvine United States return; 3453c242f9a0Schunli zhang - Sun Microsystems - Irvine United States } 3454c242f9a0Schunli zhang - Sun Microsystems - Irvine United States 3455e36d7b11SSebastien Roy /* 3456e36d7b11SSebastien Roy * No remainder mblk required. 3457e36d7b11SSebastien Roy */ 3458e36d7b11SSebastien Roy if (remainder == 0) 3459c242f9a0Schunli zhang - Sun Microsystems - Irvine United States return; 3460c242f9a0Schunli zhang - Sun Microsystems - Irvine United States 3461e36d7b11SSebastien Roy /* 3462e36d7b11SSebastien Roy * Get to the last mblk in the chain. 3463e36d7b11SSebastien Roy */ 3464e36d7b11SSebastien Roy while (mp->b_cont != NULL) 3465c242f9a0Schunli zhang - Sun Microsystems - Irvine United States mp = mp->b_cont; 3466c242f9a0Schunli zhang - Sun Microsystems - Irvine United States 3467c242f9a0Schunli zhang - Sun Microsystems - Irvine United States /* 3468e36d7b11SSebastien Roy * In case of copy-reduction mblks, the size of the mblks are fixed 3469e36d7b11SSebastien Roy * and are of the size of the loaned buffers. Allocate a remainder 3470e36d7b11SSebastien Roy * mblk and chain it to the data buffers. This is sub-optimal, but not 3471e36d7b11SSebastien Roy * expected to happen commonly. 3472c242f9a0Schunli zhang - Sun Microsystems - Irvine United States */ 3473e36d7b11SSebastien Roy rmp = allocb_wait(remainder, BPRI_MED, STR_NOSIG, &alloc_err); 3474c242f9a0Schunli zhang - Sun Microsystems - Irvine United States ASSERT(rmp != NULL); 3475c242f9a0Schunli zhang - Sun Microsystems - Irvine United States ASSERT(alloc_err == 0); 3476c242f9a0Schunli zhang - Sun Microsystems - Irvine United States 3477e36d7b11SSebastien Roy for (i = 0; i < remainder; i++) 3478c242f9a0Schunli zhang - Sun Microsystems - Irvine United States *rmp->b_wptr++ = '\0'; 3479c242f9a0Schunli zhang - Sun Microsystems - Irvine United States 3480c242f9a0Schunli zhang - Sun Microsystems - Irvine United States rmp->b_datap->db_type = M_DATA; 3481c242f9a0Schunli zhang - Sun Microsystems - Irvine United States mp->b_cont = rmp; 3482c242f9a0Schunli zhang - Sun Microsystems - Irvine United States } 3483