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.
2541bec5e3SMarcel Telka * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
2677b65ce6SAlex 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>
7077b65ce6SAlex 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
_init(void)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
_fini()1597c478bd9Sstevel@tonic-gate _fini()
1607c478bd9Sstevel@tonic-gate {
1617c478bd9Sstevel@tonic-gate return (EBUSY);
1627c478bd9Sstevel@tonic-gate }
1637c478bd9Sstevel@tonic-gate
1647c478bd9Sstevel@tonic-gate int
_info(struct modinfo * modinfop)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
276d9ad96c1Srg137905 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
nfs_srv_offline(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
nfs_srv_stop_all(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
nfs_srv_quiesce_all(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
nfs_srv_shutdown_all(int quiesce)327*e413b7aaSMarcel Telka nfs_srv_shutdown_all(int quiesce)
328*e413b7aaSMarcel 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
nfs_srv_set_sc_versions(struct file * fp,SVC_CALLOUT_TABLE ** sctpp,rpcvers_t versmin,rpcvers_t versmax)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
nfs_svc(struct nfs_svc_args * arg,model_t model)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
rfs4_server_start(int nfs4_srv_delegation)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
rdma_start(struct rdma_svc_args * rsa)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
rpc_null(caddr_t * argp,caddr_t * resp,struct exportinfo * exi,struct svc_req * req,cred_t * cr,bool_t ro)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
rpc_null_v3(caddr_t * argp,caddr_t * resp,struct exportinfo * exi,struct svc_req * req,cred_t * cr,bool_t ro)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
rfs_error(caddr_t * argp,caddr_t * resp,struct exportinfo * exi,struct svc_req * req,cred_t * cr,bool_t ro)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
nullfree(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,
13467c478bd9Sstevel@tonic-gate &rfsproccnt_v2_ptr, rfsdisptab_v2},
13477c478bd9Sstevel@tonic-gate {sizeof (rfsdisptab_v3) / sizeof (rfsdisptab_v3[0]),
13487c478bd9Sstevel@tonic-gate rfscallnames_v3,
13497c478bd9Sstevel@tonic-gate &rfsproccnt_v3_ptr, rfsdisptab_v3},
13507c478bd9Sstevel@tonic-gate {sizeof (rfsdisptab_v4) / sizeof (rfsdisptab_v4[0]),
13517c478bd9Sstevel@tonic-gate rfscallnames_v4,
13527c478bd9Sstevel@tonic-gate &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
auth_tooweak(struct svc_req * req,char * res)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
common_dispatch(struct svc_req * req,SVCXPRT * xprt,rpcvers_t min_vers,rpcvers_t max_vers,char * pgmname,struct rpc_disptable * disptable)14777c478bd9Sstevel@tonic-gate common_dispatch(struct svc_req *req, SVCXPRT *xprt, rpcvers_t min_vers,
1478*e413b7aaSMarcel 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) {
1574d9ad96c1Srg137905 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
16503ed73216SArne 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
rfs_dispatch(struct svc_req * req,SVCXPRT * xprt)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,
19747c478bd9Sstevel@tonic-gate &aclproccnt_v2_ptr, acldisptab_v2},
19757c478bd9Sstevel@tonic-gate {sizeof (acldisptab_v3) / sizeof (acldisptab_v3[0]),
19767c478bd9Sstevel@tonic-gate aclcallnames_v3,
19777c478bd9Sstevel@tonic-gate &aclproccnt_v3_ptr, acldisptab_v3},
19787c478bd9Sstevel@tonic-gate };
19797c478bd9Sstevel@tonic-gate
19807c478bd9Sstevel@tonic-gate static void
acl_dispatch(struct svc_req * req,SVCXPRT * xprt)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
checkwin(int flavor,int window,struct svc_req * req)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;
199577b65ce6SAlex 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
checkauth(struct exportinfo * exi,struct svc_req * req,cred_t * cr,int anon_ok,bool_t publicfh_ok,bool_t * ro)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
checkauth4(struct compound_state * cs,struct svc_req * req)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*e413b7aaSMarcel 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*e413b7aaSMarcel 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*e413b7aaSMarcel 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*e413b7aaSMarcel 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*e413b7aaSMarcel Telka if (secp == NULL) {
2428*e413b7aaSMarcel 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*e413b7aaSMarcel 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*e413b7aaSMarcel Telka if (crgetuid(cr) == 0 && secp->s_rootid == 0) {
2453*e413b7aaSMarcel Telka rw_exit(&exported_lock);
24547c478bd9Sstevel@tonic-gate return (1);
2455*e413b7aaSMarcel Telka }
24567c478bd9Sstevel@tonic-gate
2457b89a8333Snatalie li - Sun Microsystems - Irvine United States (void) crsetugid(cr, secp->s_rootid, secp->s_rootid);
24587c478bd9Sstevel@tonic-gate
2459*e413b7aaSMarcel Telka rw_exit(&exported_lock);
2460*e413b7aaSMarcel 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*e413b7aaSMarcel Telka rw_exit(&exported_lock);
2475*e413b7aaSMarcel 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 *
client_name(struct svc_req * req)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 *
client_addr(struct svc_req * req,char * buf)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
nfs_srvinit(void)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
nfs_srvfini(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
mblk_to_iov(mblk_t * m,int cnt,struct iovec * iovp)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
rfs_publicfh_mclookup(char * p,vnode_t * dvp,cred_t * cr,vnode_t ** vpp,struct exportinfo ** exi,struct sec_ol * sec)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
rfs_pathname(char * path,vnode_t ** dirvpp,vnode_t ** compvpp,vnode_t * startdvp,cred_t * cr,int pathflag)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
MCLpath(char ** path)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
URLparse(char * str)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
nfs_check_vpexi(vnode_t * mc_dvp,vnode_t * vp,cred_t * cr,struct exportinfo ** exi)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
hanfsv4_failover(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 *
nfs_getflabel(vnode_t * vp,struct exportinfo * exi)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
do_rfs_label_check(bslabel_t * clabel,vnode_t * vp,int flag,struct exportinfo * exi)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
rfs_free_xuio(void * free_arg)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 *
rfs_setup_xuio(vnode_t * vp)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 *
uio_to_mblk(uio_t * uiop)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 *
rfs_read_alloc(uint_t len,struct iovec ** iov,int * iovcnt)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
rfs_rndup_mblks(mblk_t * mp,uint_t len,int buf_loaned)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