summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
authorMarcel Telka <marcel.telka@nexenta.com>2014-07-02 20:44:32 +0200
committerGordon Ross <gwr@nexenta.com>2014-07-08 09:32:37 -0400
commit5cb0d67909d9970a3e7adbea9422ca3fc88000bf (patch)
treedf34b8a1eeb9c9f1398e0acf0b9fea6332a204aa /usr/src
parent33cde0d0c27645bc9ec94c4d2955193c3dd4027c (diff)
downloadillumos-gate-5cb0d67909d9970a3e7adbea9422ca3fc88000bf.tar.gz
4943 NFS server: Generic uid and gid remapping for AUTH_SYS
Reviewed by: Jan Kryl <jan.kryl@nexenta.com> Reviewed by: Dan McDonald <danmcd@omniti.com> Approved by: Garrett D'Amore <garrett@damore.org>
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/cmd/fs.d/nfs/lib/sharetab.h5
-rw-r--r--usr/src/cmd/fs.d/nfs/mountd/mountd.c438
-rw-r--r--usr/src/cmd/fs.d/nfs/mountd/mountd.h7
-rw-r--r--usr/src/cmd/fs.d/nfs/mountd/nfsauth.c11
-rw-r--r--usr/src/cmd/fs.d/nfs/mountd/nfsauth_xdr.c12
-rw-r--r--usr/src/lib/libshare/common/libshare.c3
-rw-r--r--usr/src/lib/libshare/common/libsharecore.c5
-rw-r--r--usr/src/lib/libshare/nfs/libshare_nfs.c237
-rw-r--r--usr/src/lib/libshare/nfs/libshare_nfs.h4
-rw-r--r--usr/src/man/man1m/share_nfs.1m84
-rw-r--r--usr/src/uts/common/fs/nfs/nfs3_srv.c67
-rw-r--r--usr/src/uts/common/fs/nfs/nfs4_srv.c26
-rw-r--r--usr/src/uts/common/fs/nfs/nfs_acl_srv.c22
-rw-r--r--usr/src/uts/common/fs/nfs/nfs_auth.c90
-rw-r--r--usr/src/uts/common/fs/nfs/nfs_auth_xdr.c12
-rw-r--r--usr/src/uts/common/fs/nfs/nfs_server.c58
-rw-r--r--usr/src/uts/common/fs/nfs/nfs_srv.c63
-rw-r--r--usr/src/uts/common/nfs/auth.h20
-rw-r--r--usr/src/uts/common/nfs/export.h32
-rw-r--r--usr/src/uts/common/nfs/nfs.h665
-rw-r--r--usr/src/uts/common/nfs/nfs_acl.h21
-rw-r--r--usr/src/uts/common/nfs/nfs_dispatch.h10
22 files changed, 1336 insertions, 556 deletions
diff --git a/usr/src/cmd/fs.d/nfs/lib/sharetab.h b/usr/src/cmd/fs.d/nfs/lib/sharetab.h
index 167ac79305..b51c5e7d85 100644
--- a/usr/src/cmd/fs.d/nfs/lib/sharetab.h
+++ b/usr/src/cmd/fs.d/nfs/lib/sharetab.h
@@ -23,6 +23,9 @@
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
+/*
+ * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
+ */
/* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
/* All Rights Reserved */
@@ -60,6 +63,8 @@ extern "C" {
#define SHOPT_INDEX "index"
#define SHOPT_LOG "log"
#define SHOPT_NOACLFAB "noaclfab"
+#define SHOPT_UIDMAP "uidmap"
+#define SHOPT_GIDMAP "gidmap"
/* XXX The following are added for testing volatile fh's purposes only */
#ifdef VOLATILE_FH_TEST
diff --git a/usr/src/cmd/fs.d/nfs/mountd/mountd.c b/usr/src/cmd/fs.d/nfs/mountd/mountd.c
index 0bfa94b225..852d6f484d 100644
--- a/usr/src/cmd/fs.d/nfs/mountd/mountd.c
+++ b/usr/src/cmd/fs.d/nfs/mountd/mountd.c
@@ -82,6 +82,8 @@
#include <sys/nvpair.h>
#include <attr.h>
#include "smfcfg.h"
+#include <pwd.h>
+#include <grp.h>
extern int daemonize_init(void);
extern void daemonize_fini(int fd);
@@ -104,9 +106,9 @@ static int getclientsflavors_old(share_t *, SVCXPRT *, struct netbuf **,
static int getclientsflavors_new(share_t *, SVCXPRT *, struct netbuf **,
struct nd_hostservlist **, int *);
static int check_client_old(share_t *, SVCXPRT *, struct netbuf **,
- struct nd_hostservlist **, int);
+ struct nd_hostservlist **, int, uid_t, gid_t, uid_t *, gid_t *);
static int check_client_new(share_t *, SVCXPRT *, struct netbuf **,
- struct nd_hostservlist **, int);
+ struct nd_hostservlist **, int, uid_t, gid_t, uid_t *, gid_t *);
static void mnt(struct svc_req *, SVCXPRT *);
static void mnt_pathconf(struct svc_req *);
static int mount(struct svc_req *r);
@@ -1948,6 +1950,10 @@ static char *optlist[] = {
SHOPT_SEC,
#define OPT_NONE 9
SHOPT_NONE,
+#define OPT_UIDMAP 10
+ SHOPT_UIDMAP,
+#define OPT_GIDMAP 11
+ SHOPT_GIDMAP,
NULL
};
@@ -2154,17 +2160,99 @@ getclientsflavors_new(share_t *sh, SVCXPRT *transp, struct netbuf **nb,
*/
int
check_client(share_t *sh, struct netbuf *nb,
- struct nd_hostservlist *clnames, int flavor)
+ struct nd_hostservlist *clnames, int flavor, uid_t clnt_uid, gid_t clnt_gid,
+ uid_t *srv_uid, gid_t *srv_gid)
{
if (newopts(sh->sh_opts))
- return (check_client_new(sh, NULL, &nb, &clnames, flavor));
+ return (check_client_new(sh, NULL, &nb, &clnames, flavor,
+ clnt_uid, clnt_gid, srv_uid, srv_gid));
else
- return (check_client_old(sh, NULL, &nb, &clnames, flavor));
+ return (check_client_old(sh, NULL, &nb, &clnames, flavor,
+ clnt_uid, clnt_gid, srv_uid, srv_gid));
+}
+
+/*
+ * is_a_number(number)
+ *
+ * is the string a number in one of the forms we want to use?
+ */
+
+static int
+is_a_number(char *number)
+{
+ int ret = 1;
+ int hex = 0;
+
+ if (strncmp(number, "0x", 2) == 0) {
+ number += 2;
+ hex = 1;
+ } else if (*number == '-') {
+ number++; /* skip the minus */
+ }
+ while (ret == 1 && *number != '\0') {
+ if (hex) {
+ ret = isxdigit(*number++);
+ } else {
+ ret = isdigit(*number++);
+ }
+ }
+ return (ret);
+}
+
+static boolean_t
+get_uid(char *value, uid_t *uid)
+{
+ if (!is_a_number(value)) {
+ struct passwd *pw;
+ /*
+ * in this case it would have to be a
+ * user name
+ */
+ pw = getpwnam(value);
+ if (pw == NULL)
+ return (B_FALSE);
+ *uid = pw->pw_uid;
+ endpwent();
+ } else {
+ uint64_t intval;
+ intval = strtoull(value, NULL, 0);
+ if (intval > UID_MAX && intval != -1)
+ return (B_FALSE);
+ *uid = (uid_t)intval;
+ }
+
+ return (B_TRUE);
+}
+
+static boolean_t
+get_gid(char *value, gid_t *gid)
+{
+ if (!is_a_number(value)) {
+ struct group *gr;
+ /*
+ * in this case it would have to be a
+ * group name
+ */
+ gr = getgrnam(value);
+ if (gr == NULL)
+ return (B_FALSE);
+ *gid = gr->gr_gid;
+ endgrent();
+ } else {
+ uint64_t intval;
+ intval = strtoull(value, NULL, 0);
+ if (intval > UID_MAX && intval != -1)
+ return (B_FALSE);
+ *gid = (gid_t)intval;
+ }
+
+ return (B_TRUE);
}
static int
check_client_old(share_t *sh, SVCXPRT *transp, struct netbuf **nb,
- struct nd_hostservlist **clnames, int flavor)
+ struct nd_hostservlist **clnames, int flavor, uid_t clnt_uid,
+ gid_t clnt_gid, uid_t *srv_uid, gid_t *srv_gid)
{
char *opts, *p, *val;
int match; /* Set when a flavor is matched */
@@ -2172,7 +2260,8 @@ check_client_old(share_t *sh, SVCXPRT *transp, struct netbuf **nb,
int list = 0; /* Set when "ro", "rw" is found */
int ro_val = 0; /* Set if ro option is 'ro=' */
int rw_val = 0; /* Set if rw option is 'rw=' */
- boolean_t reject = B_FALSE; /* if none= contains the host */
+
+ boolean_t map_deny = B_FALSE;
opts = strdup(sh->sh_opts);
if (opts == NULL) {
@@ -2192,14 +2281,16 @@ check_client_old(share_t *sh, SVCXPRT *transp, struct netbuf **nb,
case OPT_RO:
list++;
- if (val) ro_val++;
+ if (val != NULL)
+ ro_val++;
if (in_access_list(transp, nb, clnames, val))
perm |= NFSAUTH_RO;
break;
case OPT_RW:
list++;
- if (val) rw_val++;
+ if (val != NULL)
+ rw_val++;
if (in_access_list(transp, nb, clnames, val))
perm |= NFSAUTH_RW;
break;
@@ -2216,8 +2307,14 @@ check_client_old(share_t *sh, SVCXPRT *transp, struct netbuf **nb,
if (val == NULL || *val == '\0')
break;
- if (in_access_list(transp, nb, clnames, val))
+ if (clnt_uid != 0)
+ break;
+
+ if (in_access_list(transp, nb, clnames, val)) {
perm |= NFSAUTH_ROOT;
+ perm |= NFSAUTH_UIDMAP | NFSAUTH_GIDMAP;
+ map_deny = B_FALSE;
+ }
break;
case OPT_NONE:
@@ -2227,14 +2324,160 @@ check_client_old(share_t *sh, SVCXPRT *transp, struct netbuf **nb,
* more like "root" than either "rw" or "ro".
*/
if (in_access_list(transp, nb, clnames, val))
- reject = B_TRUE;
+ perm |= NFSAUTH_DENIED;
+ break;
+
+ case OPT_UIDMAP: {
+ char *c;
+ char *n;
+
+ /*
+ * The uidmap is supported for AUTH_SYS only.
+ */
+ if (flavor != AUTH_SYS)
+ break;
+
+ if (perm & NFSAUTH_UIDMAP || map_deny)
+ break;
+
+ for (c = val; c != NULL; c = n) {
+ char *s;
+ char *al;
+ uid_t srv;
+
+ n = strchr(c, '~');
+ if (n != NULL)
+ *n++ = '\0';
+
+ s = strchr(c, ':');
+ if (s != NULL) {
+ *s++ = '\0';
+ al = strchr(s, ':');
+ if (al != NULL)
+ *al++ = '\0';
+ }
+
+ if (s == NULL || al == NULL)
+ continue;
+
+ if (*c == '\0') {
+ if (clnt_uid != (uid_t)-1)
+ continue;
+ } else if (strcmp(c, "*") != 0) {
+ uid_t clnt;
+
+ if (!get_uid(c, &clnt))
+ continue;
+
+ if (clnt_uid != clnt)
+ continue;
+ }
+
+ if (*s == '\0')
+ srv = UID_NOBODY;
+ else if (!get_uid(s, &srv))
+ continue;
+ else if (srv == (uid_t)-1) {
+ map_deny = B_TRUE;
+ break;
+ }
+
+ if (in_access_list(transp, nb, clnames, al)) {
+ *srv_uid = srv;
+ perm |= NFSAUTH_UIDMAP;
+ break;
+ }
+ }
+
+ break;
+ }
+
+ case OPT_GIDMAP: {
+ char *c;
+ char *n;
+
+ /*
+ * The gidmap is supported for AUTH_SYS only.
+ */
+ if (flavor != AUTH_SYS)
+ break;
+
+ if (perm & NFSAUTH_GIDMAP || map_deny)
+ break;
+
+ for (c = val; c != NULL; c = n) {
+ char *s;
+ char *al;
+ gid_t srv;
+
+ n = strchr(c, '~');
+ if (n != NULL)
+ *n++ = '\0';
+
+ s = strchr(c, ':');
+ if (s != NULL) {
+ *s++ = '\0';
+ al = strchr(s, ':');
+ if (al != NULL)
+ *al++ = '\0';
+ }
+
+ if (s == NULL || al == NULL)
+ break;
+
+ if (*c == '\0') {
+ if (clnt_gid != (gid_t)-1)
+ continue;
+ } else if (strcmp(c, "*") != 0) {
+ gid_t clnt;
+
+ if (!get_gid(c, &clnt))
+ continue;
+
+ if (clnt_gid != clnt)
+ continue;
+ }
+
+ if (*s == '\0')
+ srv = UID_NOBODY;
+ else if (!get_gid(s, &srv))
+ continue;
+ else if (srv == (gid_t)-1) {
+ map_deny = B_TRUE;
+ break;
+ }
+
+ if (in_access_list(transp, nb, clnames, al)) {
+ *srv_gid = srv;
+ perm |= NFSAUTH_GIDMAP;
+ break;
+ }
+ }
+
+ break;
+ }
+
+ default:
break;
}
}
free(opts);
- if (flavor != match || reject)
+ if (perm & NFSAUTH_ROOT) {
+ *srv_uid = 0;
+ *srv_gid = 0;
+ }
+
+ if (map_deny)
+ perm |= NFSAUTH_DENIED;
+
+ if (!(perm & NFSAUTH_UIDMAP))
+ *srv_uid = clnt_uid;
+ if (!(perm & NFSAUTH_GIDMAP))
+ *srv_gid = clnt_gid;
+
+ if (flavor != match || perm & NFSAUTH_DENIED)
return (NFSAUTH_DENIED);
if (list) {
@@ -2253,7 +2496,6 @@ check_client_old(share_t *sh, SVCXPRT *transp, struct netbuf **nb,
perm |= NFSAUTH_RW;
}
-
/*
* The client may show up in both ro= and rw=
* lists. If so, then turn off the RO access
@@ -2329,7 +2571,8 @@ is_wrongsec(share_t *sh, SVCXPRT *transp, struct netbuf **nb,
static int
check_client_new(share_t *sh, SVCXPRT *transp, struct netbuf **nb,
- struct nd_hostservlist **clnames, int flavor)
+ struct nd_hostservlist **clnames, int flavor, uid_t clnt_uid,
+ gid_t clnt_gid, uid_t *srv_uid, gid_t *srv_gid)
{
char *opts, *p, *val;
char *lasts;
@@ -2339,7 +2582,8 @@ check_client_new(share_t *sh, SVCXPRT *transp, struct netbuf **nb,
int list = 0; /* Set when "ro", "rw" is found */
int ro_val = 0; /* Set if ro option is 'ro=' */
int rw_val = 0; /* Set if rw option is 'rw=' */
- boolean_t reject;
+
+ boolean_t map_deny = B_FALSE;
opts = strdup(sh->sh_opts);
if (opts == NULL) {
@@ -2371,7 +2615,8 @@ check_client_new(share_t *sh, SVCXPRT *transp, struct netbuf **nb,
break;
list++;
- if (val) ro_val++;
+ if (val != NULL)
+ ro_val++;
if (in_access_list(transp, nb, clnames, val))
perm |= NFSAUTH_RO;
break;
@@ -2381,7 +2626,8 @@ check_client_new(share_t *sh, SVCXPRT *transp, struct netbuf **nb,
break;
list++;
- if (val) rw_val++;
+ if (val != NULL)
+ rw_val++;
if (in_access_list(transp, nb, clnames, val))
perm |= NFSAUTH_RW;
break;
@@ -2401,8 +2647,14 @@ check_client_new(share_t *sh, SVCXPRT *transp, struct netbuf **nb,
if (val == NULL || *val == '\0')
break;
- if (in_access_list(transp, nb, clnames, val))
+ if (clnt_uid != 0)
+ break;
+
+ if (in_access_list(transp, nb, clnames, val)) {
perm |= NFSAUTH_ROOT;
+ perm |= NFSAUTH_UIDMAP | NFSAUTH_GIDMAP;
+ map_deny = B_FALSE;
+ }
break;
case OPT_NONE:
@@ -2414,15 +2666,163 @@ check_client_new(share_t *sh, SVCXPRT *transp, struct netbuf **nb,
if (in_access_list(transp, nb, clnames, val))
perm |= NFSAUTH_DENIED;
break;
+
+ case OPT_UIDMAP: {
+ char *c;
+ char *n;
+
+ /*
+ * The uidmap is supported for AUTH_SYS only.
+ */
+ if (flavor != AUTH_SYS)
+ break;
+
+ if (!match || perm & NFSAUTH_UIDMAP || map_deny)
+ break;
+
+ for (c = val; c != NULL; c = n) {
+ char *s;
+ char *al;
+ uid_t srv;
+
+ n = strchr(c, '~');
+ if (n != NULL)
+ *n++ = '\0';
+
+ s = strchr(c, ':');
+ if (s != NULL) {
+ *s++ = '\0';
+ al = strchr(s, ':');
+ if (al != NULL)
+ *al++ = '\0';
+ }
+
+ if (s == NULL || al == NULL)
+ continue;
+
+ if (*c == '\0') {
+ if (clnt_uid != (uid_t)-1)
+ continue;
+ } else if (strcmp(c, "*") != 0) {
+ uid_t clnt;
+
+ if (!get_uid(c, &clnt))
+ continue;
+
+ if (clnt_uid != clnt)
+ continue;
+ }
+
+ if (*s == '\0')
+ srv = UID_NOBODY;
+ else if (!get_uid(s, &srv))
+ continue;
+ else if (srv == (uid_t)-1) {
+ map_deny = B_TRUE;
+ break;
+ }
+
+ if (in_access_list(transp, nb, clnames, al)) {
+ *srv_uid = srv;
+ perm |= NFSAUTH_UIDMAP;
+ break;
+ }
+ }
+
+ break;
+ }
+
+ case OPT_GIDMAP: {
+ char *c;
+ char *n;
+
+ /*
+ * The gidmap is supported for AUTH_SYS only.
+ */
+ if (flavor != AUTH_SYS)
+ break;
+
+ if (!match || perm & NFSAUTH_GIDMAP || map_deny)
+ break;
+
+ for (c = val; c != NULL; c = n) {
+ char *s;
+ char *al;
+ gid_t srv;
+
+ n = strchr(c, '~');
+ if (n != NULL)
+ *n++ = '\0';
+
+ s = strchr(c, ':');
+ if (s != NULL) {
+ *s++ = '\0';
+ al = strchr(s, ':');
+ if (al != NULL)
+ *al++ = '\0';
+ }
+
+ if (s == NULL || al == NULL)
+ break;
+
+ if (*c == '\0') {
+ if (clnt_gid != (gid_t)-1)
+ continue;
+ } else if (strcmp(c, "*") != 0) {
+ gid_t clnt;
+
+ if (!get_gid(c, &clnt))
+ continue;
+
+ if (clnt_gid != clnt)
+ continue;
+ }
+
+ if (*s == '\0')
+ srv = UID_NOBODY;
+ else if (!get_gid(s, &srv))
+ continue;
+ else if (srv == (gid_t)-1) {
+ map_deny = B_TRUE;
+ break;
+ }
+
+ if (in_access_list(transp, nb, clnames, al)) {
+ *srv_gid = srv;
+ perm |= NFSAUTH_GIDMAP;
+ break;
+ }
+ }
+
+ break;
+ }
+
+ default:
+ break;
}
}
done:
+ if (perm & NFSAUTH_ROOT) {
+ *srv_uid = 0;
+ *srv_gid = 0;
+ }
+
+ if (map_deny)
+ perm |= NFSAUTH_DENIED;
+
+ if (!(perm & NFSAUTH_UIDMAP))
+ *srv_uid = clnt_uid;
+ if (!(perm & NFSAUTH_GIDMAP))
+ *srv_gid = clnt_gid;
+
/*
* If no match then set the perm accordingly
*/
- if (!match || perm & NFSAUTH_DENIED)
+ if (!match || perm & NFSAUTH_DENIED) {
+ free(opts);
return (NFSAUTH_DENIED);
+ }
if (list) {
/*
diff --git a/usr/src/cmd/fs.d/nfs/mountd/mountd.h b/usr/src/cmd/fs.d/nfs/mountd/mountd.h
index 0953154559..80b0f86bcc 100644
--- a/usr/src/cmd/fs.d/nfs/mountd/mountd.h
+++ b/usr/src/cmd/fs.d/nfs/mountd/mountd.h
@@ -23,12 +23,13 @@
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
+/*
+ * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
+ */
#ifndef _MOUNTD_H
#define _MOUNTD_H
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <door.h>
#include <nfs/nfs.h>
@@ -63,7 +64,7 @@ extern void *exmalloc(size_t);
extern struct share *findentry(char *);
extern int check_client(struct share *, struct netbuf *,
- struct nd_hostservlist *, int);
+ struct nd_hostservlist *, int, uid_t, gid_t, uid_t *, gid_t *);
extern struct nd_hostservlist *anon_client(char *host);
/*
diff --git a/usr/src/cmd/fs.d/nfs/mountd/nfsauth.c b/usr/src/cmd/fs.d/nfs/mountd/nfsauth.c
index 6b29434d03..0f681fa59e 100644
--- a/usr/src/cmd/fs.d/nfs/mountd/nfsauth.c
+++ b/usr/src/cmd/fs.d/nfs/mountd/nfsauth.c
@@ -23,6 +23,9 @@
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
+/*
+ * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
+ */
#include <stdio.h>
#include <stdlib.h>
@@ -114,7 +117,9 @@ nfsauth_access(auth_req *argp, auth_res *result)
goto done;
}
- result->auth_perm = check_client(sh, &nbuf, clnames, argp->req_flavor);
+ result->auth_perm = check_client(sh, &nbuf, clnames, argp->req_flavor,
+ argp->req_clnt_uid, argp->req_clnt_gid, &result->auth_srv_uid,
+ &result->auth_srv_gid);
sharefree(sh);
@@ -141,8 +146,8 @@ nfsauth_func(void *cookie, char *dataptr, size_t arg_size,
XDR xdrs_r;
caddr_t abuf = dataptr;
size_t absz = arg_size;
- size_t rbsz = (size_t)(BYTES_PER_XDR_UNIT * 2);
- char result[BYTES_PER_XDR_UNIT * 2];
+ size_t rbsz = (size_t)(BYTES_PER_XDR_UNIT * 4);
+ char result[BYTES_PER_XDR_UNIT * 4];
caddr_t rbuf = (caddr_t)&result;
varg_t varg = {0};
diff --git a/usr/src/cmd/fs.d/nfs/mountd/nfsauth_xdr.c b/usr/src/cmd/fs.d/nfs/mountd/nfsauth_xdr.c
index 9e7efa4939..8c526eeb31 100644
--- a/usr/src/cmd/fs.d/nfs/mountd/nfsauth_xdr.c
+++ b/usr/src/cmd/fs.d/nfs/mountd/nfsauth_xdr.c
@@ -22,7 +22,9 @@
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
+/*
+ * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
+ */
#include <stdlib.h>
#include <nfs/auth.h>
@@ -62,6 +64,10 @@ xdr_nfsauth_arg(XDR *xdrs, nfsauth_arg_t *argp)
return (FALSE);
if (!xdr_int(xdrs, &argp->areq.req_flavor))
return (FALSE);
+ if (!xdr_u_int(xdrs, &argp->areq.req_clnt_uid))
+ return (FALSE);
+ if (!xdr_u_int(xdrs, &argp->areq.req_clnt_gid))
+ return (FALSE);
return (TRUE);
}
@@ -72,5 +78,9 @@ xdr_nfsauth_res(XDR *xdrs, nfsauth_res_t *argp)
return (FALSE);
if (!xdr_int(xdrs, &argp->ares.auth_perm))
return (FALSE);
+ if (!xdr_u_int(xdrs, &argp->ares.auth_srv_uid))
+ return (FALSE);
+ if (!xdr_u_int(xdrs, &argp->ares.auth_srv_gid))
+ return (FALSE);
return (TRUE);
}
diff --git a/usr/src/lib/libshare/common/libshare.c b/usr/src/lib/libshare/common/libshare.c
index 1d17d5fea7..320ff911d7 100644
--- a/usr/src/lib/libshare/common/libshare.c
+++ b/usr/src/lib/libshare/common/libshare.c
@@ -21,6 +21,7 @@
/*
* Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
*/
/*
@@ -597,7 +598,7 @@ validpath(sa_handle_t handle, char *path, int strictness)
* check to see if group/share is persistent.
*
* "group" can be either an sa_group_t or an sa_share_t. (void *)
- * works since both thse types are also void *.
+ * works since both these types are also void *.
* If the share is a ZFS share, mark it as persistent.
*/
int
diff --git a/usr/src/lib/libshare/common/libsharecore.c b/usr/src/lib/libshare/common/libsharecore.c
index 02b44052ca..ba2aa89fb6 100644
--- a/usr/src/lib/libshare/common/libsharecore.c
+++ b/usr/src/lib/libshare/common/libsharecore.c
@@ -21,6 +21,7 @@
/*
* Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
*/
/*
@@ -772,7 +773,7 @@ add_syntax_comment(xmlNodePtr root, char *line, char *err, int todfstab)
/*
* sa_is_share(object)
*
- * returns true of the object is of type "share".
+ * returns true if the object is of type "share".
*/
int
@@ -787,7 +788,7 @@ sa_is_share(void *object)
/*
* sa_is_resource(object)
*
- * returns true of the object is of type "share".
+ * returns true if the object is of type "resource".
*/
int
diff --git a/usr/src/lib/libshare/nfs/libshare_nfs.c b/usr/src/lib/libshare/nfs/libshare_nfs.c
index a3b7305ac2..9e6124286d 100644
--- a/usr/src/lib/libshare/nfs/libshare_nfs.c
+++ b/usr/src/lib/libshare/nfs/libshare_nfs.c
@@ -41,6 +41,7 @@
#include "libshare_impl.h"
#include <nfs/export.h>
#include <pwd.h>
+#include <grp.h>
#include <limits.h>
#include <libscf.h>
#include <syslog.h>
@@ -167,8 +168,12 @@ struct option_defs optdefs[] = {
{"", OPT_CHARSET_MAP, OPT_TYPE_ACCLIST},
#define OPT_NOACLFAB 17
{SHOPT_NOACLFAB, OPT_NOACLFAB, OPT_TYPE_BOOLEAN},
+#define OPT_UIDMAP 18
+ {SHOPT_UIDMAP, OPT_UIDMAP, OPT_TYPE_MAPPING},
+#define OPT_GIDMAP 19
+ {SHOPT_GIDMAP, OPT_GIDMAP, OPT_TYPE_MAPPING},
#ifdef VOLATILE_FH_TEST /* XXX added for testing volatile fh's only */
-#define OPT_VOLFH 18
+#define OPT_VOLFH 20
{SHOPT_VOLFH, OPT_VOLFH},
#endif /* VOLATILE_FH_TEST */
NULL
@@ -211,6 +216,8 @@ static char *seclist[] = {
SHOPT_WINDOW,
SHOPT_NONE,
SHOPT_ROOT_MAPPING,
+ SHOPT_UIDMAP,
+ SHOPT_GIDMAP,
NULL
};
@@ -434,7 +441,7 @@ nfs_alistcat(char *str1, char *str2, char sep)
}
/*
- * add_security_prop(sec, name, value, persist)
+ * add_security_prop(sec, name, value, persist, iszfs)
*
* Add the property to the securities structure. This accumulates
* properties for as part of parsing legacy options.
@@ -472,21 +479,28 @@ add_security_prop(struct securities *sec, char *name, char *value,
char *newvalue;
/*
- * The security options of ro/rw/root might appear
- * multiple times. If they do, the values need to be
- * merged into an access list. If it was previously
- * empty, the new value alone is added.
+ * The security options of ro/rw/root/uidmap/gidmap
+ * might appear multiple times. If they do, the values
+ * need to be merged. If it was previously empty, the
+ * new value alone is added.
*/
oldvalue = sa_get_property_attr(prop, "value");
if (oldvalue != NULL) {
+ char sep = ':';
+
+ if (strcmp(name, SHOPT_UIDMAP) == 0 ||
+ strcmp(name, SHOPT_GIDMAP) == 0)
+ sep = '~';
+
/*
* The general case is to concatenate the new
* value onto the old value for multiple
- * rw(ro/root) properties. A special case
- * exists when either the old or new is the
- * "all" case. In the special case, if both
- * are "all", then it is "all", else if one is
- * an access-list, that replaces the "all".
+ * rw(ro/root/uidmap/gidmap) properties. For
+ * rw/ro/root a special case exists when either
+ * the old or new is the "all" case. In the
+ * special case, if both are "all", then it is
+ * "all", else if one is an access-list, that
+ * replaces the "all".
*/
if (strcmp(oldvalue, "*") == 0) {
/* Replace old value with new value. */
@@ -504,7 +518,7 @@ add_security_prop(struct securities *sec, char *name, char *value,
* access-list.
*/
newvalue = nfs_alistcat(oldvalue,
- value, ':');
+ value, sep);
}
if (newvalue != NULL) {
@@ -515,8 +529,8 @@ add_security_prop(struct securities *sec, char *name, char *value,
prop);
free(newvalue);
}
- if (oldvalue != NULL)
- sa_free_attr_string(oldvalue);
+
+ sa_free_attr_string(oldvalue);
}
} else {
prop = sa_create_property(name, value);
@@ -567,7 +581,7 @@ invalid_security(char *options)
value = strchr(token, '=');
if (value != NULL)
*value++ = '\0';
- if (strcmp(token, "sec") == 0) {
+ if (strcmp(token, SHOPT_SEC) == 0) {
/* HAVE security flavors so check them */
char *tok, *next;
for (next = NULL, tok = value; tok != NULL;
@@ -681,7 +695,6 @@ nfs_parse_legacy_options(sa_group_t group, char *options)
token = dup;
lasts = NULL;
while (token != NULL && ret == SA_OK) {
- ret = SA_OK;
token = strtok_r(base, ",", &lasts);
base = NULL;
if (token != NULL) {
@@ -696,8 +709,8 @@ nfs_parse_legacy_options(sa_group_t group, char *options)
if (value != NULL) {
*value++ = '\0';
}
- if (strcmp(token, "sec") == 0 ||
- strcmp(token, "secure") == 0) {
+ if (strcmp(token, SHOPT_SEC) == 0 ||
+ strcmp(token, SHOPT_SECURE) == 0) {
/*
* Once in security parsing, we only
* do security. We do need to move
@@ -713,7 +726,7 @@ nfs_parse_legacy_options(sa_group_t group, char *options)
*/
free_security_list(security_list);
}
- if (strcmp(token, "secure") == 0) {
+ if (strcmp(token, SHOPT_SECURE) == 0) {
value = "dh";
} else {
if (value == NULL) {
@@ -726,7 +739,7 @@ nfs_parse_legacy_options(sa_group_t group, char *options)
} else {
/*
* Note that the "old" syntax allowed a
- * default security model This must be
+ * default security model. This must be
* accounted for and internally converted to
* "standard" security structure.
*/
@@ -1194,6 +1207,10 @@ fill_security_from_secopts(struct secinfo *sp, sa_security_t secopts)
}
sp->s_rootid = val;
break;
+ case OPT_UIDMAP:
+ case OPT_GIDMAP:
+ sp->s_flags |= M_MAP;
+ break;
default:
break;
}
@@ -1263,6 +1280,7 @@ printarg(char *path, struct exportdata *ep)
if (sp->s_flags & M_RW) (void) printf("M_RW ");
if (sp->s_flags & M_RWL) (void) printf("M_RWL ");
if (sp->s_flags & M_NONE) (void) printf("M_NONE ");
+ if (sp->s_flags & M_MAP) (void) printf("M_MAP ");
if (sp->s_flags == 0) (void) printf("(none)");
(void) printf("\n");
(void) printf("\t\ts_window = %d\n", sp->s_window);
@@ -1390,8 +1408,7 @@ nfs_sprint_option(char **rbuff, size_t *rbuffsize, size_t incr,
if (value == NULL) {
(void) snprintf(buff + curlen, buffsize - curlen,
- "%s%s", sep ? "," : "",
- name, value != NULL ? value : "");
+ "%s%s", sep ? "," : "", name);
} else {
(void) snprintf(buff + curlen, buffsize - curlen,
"%s%s=%s", sep ? "," : "",
@@ -1697,7 +1714,7 @@ check_public(sa_group_t group, sa_share_t skipshare)
}
/*
- * public_exists(handle, share)
+ * public_exists(handle, skipshare)
*
* check to see if public option is set on any other share than the
* one specified. Need to check zfs sub-groups as well as the top
@@ -1871,7 +1888,7 @@ nfs_enable_share(sa_share_t share)
sp[i].s_window = DEF_WIN;
sp[i].s_rootcnt = 0;
sp[i].s_rootnames = NULL;
- (void) fill_security_from_secopts(&sp[i], sec);
+ (void) fill_security_from_secopts(&sp[i], sec);
if (sec != NULL)
sa_free_derived_security(sec);
if (sectype != NULL)
@@ -1880,7 +1897,7 @@ nfs_enable_share(sa_share_t share)
}
/*
* when we get here, we can do the exportfs system call and
- * initiate thinsg. We probably want to enable the nfs.server
+ * initiate things. We probably want to enable the nfs.server
* service first if it isn't running within SMF.
*/
/* check nfs.server status and start if needed */
@@ -2094,6 +2111,56 @@ nfs_disable_share(sa_share_t share, char *path)
return (ret);
}
+static int
+check_user(char *value)
+{
+ int ret = SA_OK;
+
+ if (!is_a_number(value)) {
+ struct passwd *pw;
+ /*
+ * in this case it would have to be a
+ * user name
+ */
+ pw = getpwnam(value);
+ if (pw == NULL)
+ ret = SA_BAD_VALUE;
+ endpwent();
+ } else {
+ uint64_t intval;
+ intval = strtoull(value, NULL, 0);
+ if (intval > UID_MAX && intval != -1)
+ ret = SA_BAD_VALUE;
+ }
+
+ return (ret);
+}
+
+static int
+check_group(char *value)
+{
+ int ret = SA_OK;
+
+ if (!is_a_number(value)) {
+ struct group *gr;
+ /*
+ * in this case it would have to be a
+ * group name
+ */
+ gr = getgrnam(value);
+ if (gr == NULL)
+ ret = SA_BAD_VALUE;
+ endgrent();
+ } else {
+ uint64_t intval;
+ intval = strtoull(value, NULL, 0);
+ if (intval > UID_MAX && intval != -1)
+ ret = SA_BAD_VALUE;
+ }
+
+ return (ret);
+}
+
/*
* check_rorwnone(v1, v2, v3)
*
@@ -2161,11 +2228,13 @@ nfs_validate_property(sa_handle_t handle, sa_property_t property,
if (value != NULL) {
/* first basic type checking */
switch (optdefs[optindex].type) {
+
case OPT_TYPE_NUMBER:
/* check that the value is all digits */
if (!is_a_number(value))
ret = SA_BAD_VALUE;
break;
+
case OPT_TYPE_BOOLEAN:
if (strlen(value) == 0 ||
strcasecmp(value, "true") == 0 ||
@@ -2177,30 +2246,18 @@ nfs_validate_property(sa_handle_t handle, sa_property_t property,
ret = SA_BAD_VALUE;
}
break;
+
case OPT_TYPE_USER:
- if (!is_a_number(value)) {
- struct passwd *pw;
- /*
- * in this case it would have to be a
- * user name
- */
- pw = getpwnam(value);
- if (pw == NULL)
- ret = SA_BAD_VALUE;
- endpwent();
- } else {
- uint64_t intval;
- intval = strtoull(value, NULL, 0);
- if (intval > UID_MAX && intval != ~0)
- ret = SA_BAD_VALUE;
- }
+ ret = check_user(value);
break;
+
case OPT_TYPE_FILE:
if (strcmp(value, "..") == 0 ||
strchr(value, '/') != NULL) {
ret = SA_BAD_VALUE;
}
break;
+
case OPT_TYPE_ACCLIST: {
sa_property_t oprop1;
sa_property_t oprop2;
@@ -2256,6 +2313,7 @@ nfs_validate_property(sa_handle_t handle, sa_property_t property,
sa_free_attr_string(ovalue2);
break;
}
+
case OPT_TYPE_LOGTAG:
if (nfsl_getconfig_list(&configlist) == 0) {
int error;
@@ -2277,9 +2335,11 @@ nfs_validate_property(sa_handle_t handle, sa_property_t property,
ret = SA_CONFIG_ERR;
}
break;
+
case OPT_TYPE_STRING:
/* whatever is here should be ok */
break;
+
case OPT_TYPE_SECURITY:
/*
* The "sec" property isn't used in the
@@ -2289,6 +2349,99 @@ nfs_validate_property(sa_handle_t handle, sa_property_t property,
*/
ret = SA_NO_SUCH_PROP;
break;
+
+ case OPT_TYPE_MAPPING: {
+ char *p;
+ char *n;
+ char *c;
+ int (*f)(char *);
+
+ sa_security_t security;
+
+ /*
+ * mapping is only supported for sec=sys
+ */
+ ret = SA_CONFIG_ERR;
+ if (parent_group == NULL)
+ break;
+
+ for (security = sa_get_security(parent_group,
+ NULL, NULL); security != NULL;
+ security = sa_get_next_security(security)) {
+ char *type;
+ char *sectype;
+
+ type = sa_get_security_attr(security,
+ "type");
+ if (type == NULL)
+ continue;
+
+ if (strcmp(type, "nfs") != 0) {
+ sa_free_attr_string(type);
+ continue;
+ }
+ sa_free_attr_string(type);
+
+ sectype = sa_get_security_attr(security,
+ "sectype");
+ if (sectype == NULL)
+ continue;
+
+ if (strcmp(sectype, "sys") != 0) {
+ sa_free_attr_string(sectype);
+ ret = SA_CONFIG_ERR;
+ break;
+ }
+ sa_free_attr_string(sectype);
+ ret = SA_OK;
+ }
+
+ if (ret != SA_OK)
+ break;
+
+ assert(optindex == OPT_UIDMAP ||
+ optindex == OPT_GIDMAP);
+ f = optindex == OPT_UIDMAP ? check_user :
+ check_group;
+
+
+ p = strdup(value);
+ if (p == NULL)
+ ret = SA_BAD_VALUE;
+
+ for (c = p; ret == SA_OK && c != NULL; c = n) {
+ char *s;
+ char *t;
+
+ n = strchr(c, '~');
+ if (n != NULL)
+ *n++ = '\0';
+
+ s = strchr(c, ':');
+ if (s != NULL) {
+ *s++ = '\0';
+ t = strchr(s, ':');
+ if (t != NULL)
+ *t = '\0';
+ }
+
+ if (s == NULL || t == NULL)
+ ret = SA_BAD_VALUE;
+
+ if (ret == SA_OK && *c != '\0' &&
+ strcmp(c, "*") != 0)
+ ret = f(c);
+
+ if (ret == SA_OK && *s != '\0' &&
+ strcmp(s, "-1") != 0)
+ ret = f(s);
+ }
+
+ free(p);
+
+ break;
+ }
+
default:
break;
}
@@ -3040,7 +3193,7 @@ nfs_space_alias(char *space)
* Only the space named "default" is special. If it is used,
* the default needs to be looked up and the real name used.
* This is normally "sys" but could be changed. We always
- * change defautl to the real name.
+ * change default to the real name.
*/
if (strcmp(space, "default") == 0 &&
nfs_getseconfig_default(&secconf) == 0) {
diff --git a/usr/src/lib/libshare/nfs/libshare_nfs.h b/usr/src/lib/libshare/nfs/libshare_nfs.h
index 5a079db653..ac608f2b52 100644
--- a/usr/src/lib/libshare/nfs/libshare_nfs.h
+++ b/usr/src/lib/libshare/nfs/libshare_nfs.h
@@ -21,6 +21,7 @@
/*
* Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
*/
/*
@@ -53,6 +54,8 @@ extern "C" {
#define SHOPT_LOG "log"
#define SHOPT_CKSUM "cksum"
#define SHOPT_NOACLFAB "noaclfab"
+#define SHOPT_UIDMAP "uidmap"
+#define SHOPT_GIDMAP "gidmap"
/*
* defined options types. These should be in a file rather than
@@ -75,6 +78,7 @@ extern "C" {
#define OPT_TYPE_DOMAIN 13
#define OPT_TYPE_ONOFF 14
#define OPT_TYPE_PROTOCOL 15
+#define OPT_TYPE_MAPPING 16
#define OPT_SHARE_ONLY 1
diff --git a/usr/src/man/man1m/share_nfs.1m b/usr/src/man/man1m/share_nfs.1m
index a772e7e83b..8d6a1a6013 100644
--- a/usr/src/man/man1m/share_nfs.1m
+++ b/usr/src/man/man1m/share_nfs.1m
@@ -1,9 +1,10 @@
'\" te
+.\" Copyright 2014 Nexenta Systems, Inc. All rights reserved.
.\" Copyright (C) 2008, Sun Microsystems, Inc. All Rights Reserved
.\" The contents of this file are subject to the terms of the Common Development and Distribution License (the "License"). You may not use this file except in compliance with the License.
.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE or http://www.opensolaris.org/os/licensing. See the License for the specific language governing permissions and limitations under the License.
.\" When distributing Covered Code, include this CDDL HEADER in each file and include the License file at usr/src/OPENSOLARIS.LICENSE. If applicable, add the following below this CDDL HEADER, with the fields enclosed by brackets "[]" replaced with your own identifying information: Portions Copyright [yyyy] [name of copyright owner]
-.TH SHARE_NFS 1M "May 6, 2009"
+.TH SHARE_NFS 1M "Jun 30, 2014"
.SH NAME
share_nfs \- make local NFS file systems available for mounting by remote
systems
@@ -106,6 +107,39 @@ converted to UTF-8 for the server.
.sp
.ne 2
.na
+\fB\fBgidmap=\fR\fImapping\fR[\fB~\fR\fImapping\fR]...\fR
+.ad
+.sp .6
+.RS 4n
+Where \fImapping\fR is:
+.sp
+[\fIclnt\fR]\fB:\fR[\fIsrv\fR]\fB:\fR\fIaccess_list\fR
+.sp
+Allows remapping the group ID (gid) in the incoming request to some other gid.
+This effectively changes the identity of the user in the request to that of
+some other local user.
+.sp
+For clients where the gid in the incoming request is \fIclnt\fR and the client
+matches the \fIaccess_list\fR, change the group ID to \fIsrv\fR. If \fIclnt\fR
+is asterisk (*), all groups are mapped by this rule. If \fIclnt\fR is omitted,
+all unknown groups are mapped by this rule. If \fIsrv\fR is set to \(mi1,
+access is denied. If \fIsrv\fR is omitted, the gid is mapped to
+\fBUID_NOBODY\fR.
+.sp
+The particular \fImapping\fRs are separated in the \fBgidmap=\fR option
+by tilde (~) and are evaluated in the specified order until a match is
+found. Both \fBroot=\fR and \fBroot_mapping=\fR options (if specified) are
+evaluated before the \fBgidmap=\fR option. The \fBgidmap=\fR option is
+skipped in the case where the client matches the \fBroot=\fR option.
+.sp
+The \fBgidmap=\fR option is evaluated before the \fBanon=\fR option.
+.sp
+This option is supported only for \fBAUTH_SYS\fR.
+.RE
+
+.sp
+.ne 2
+.na
\fB\fBindex=\fR\fBfile\fR\fR
.ad
.sp .6
@@ -306,6 +340,39 @@ This option has been deprecated in favor of the \fBsec=\fR\fIdh\fR option.
.sp
.ne 2
.na
+\fB\fBuidmap=\fR\fImapping\fR[\fB~\fR\fImapping\fR]...\fR
+.ad
+.sp .6
+.RS 4n
+Where \fImapping\fR is:
+.sp
+[\fIclnt\fR]\fB:\fR[\fIsrv\fR]\fB:\fR\fIaccess_list\fR
+.sp
+Allows remapping the user ID (uid) in the incoming request to some other uid.
+This effectively changes the identity of the user in the request to that of
+some other local user.
+.sp
+For clients where the uid in the incoming request is \fIclnt\fR and the client
+matches the \fIaccess_list\fR, change the user ID to \fIsrv\fR. If \fIclnt\fR
+is asterisk (*), all users are mapped by this rule. If \fIclnt\fR is omitted,
+all unknown users are mapped by this rule. If \fIsrv\fR is set to \(mi1,
+access is denied. If \fIsrv\fR is omitted, the uid is mapped to
+\fBUID_NOBODY\fR.
+.sp
+The particular \fImapping\fRs are separated in the \fBuidmap=\fR option
+by tilde (~) and are evaluated in the specified order until a match is
+found. Both \fBroot=\fR and \fBroot_mapping=\fR options (if specified) are
+evaluated before the \fBuidmap=\fR option. The \fBuidmap=\fR option is
+skipped in the case where the client matches the \fBroot=\fR option.
+.sp
+The \fBuidmap=\fR option is evaluated before the \fBanon=\fR option.
+.sp
+This option is supported only for \fBAUTH_SYS\fR.
+.RE
+
+.sp
+.ne 2
+.na
\fB\fBwindow=\fR\fIvalue\fR\fR
.ad
.sp .6
@@ -512,6 +579,21 @@ files, is specified by the global entry in \fB/etc/nfs/nfslog.conf\fR. The
the system. Simply sharing a file system with logging enabled from the command
line does not start the \fBnfslogd\fR(1M).
+.LP
+\fBExample 2 \fRRemap A User Coming From The Particular NFS Client
+.sp
+.LP
+The following example remaps the user with uid \fB100\fR at client
+\fB10.0.0.1\fR to user \fBjoe\fR:
+
+.sp
+.in +2
+.nf
+example% \fBshare -o uidmap=100:joe:@10.0.0.1 /export\fR
+.fi
+.in -2
+.sp
+
.SH EXIT STATUS
.sp
.LP
diff --git a/usr/src/uts/common/fs/nfs/nfs3_srv.c b/usr/src/uts/common/fs/nfs/nfs3_srv.c
index 0bb8d4912f..0f3d54ec4c 100644
--- a/usr/src/uts/common/fs/nfs/nfs3_srv.c
+++ b/usr/src/uts/common/fs/nfs/nfs3_srv.c
@@ -88,7 +88,7 @@ u_longlong_t nfs3_srv_caller_id;
/* ARGSUSED */
void
rfs3_getattr(GETATTR3args *args, GETATTR3res *resp, struct exportinfo *exi,
- struct svc_req *req, cred_t *cr)
+ struct svc_req *req, cred_t *cr, bool_t ro)
{
int error;
vnode_t *vp;
@@ -149,7 +149,7 @@ rfs3_getattr_getfh(GETATTR3args *args)
void
rfs3_setattr(SETATTR3args *args, SETATTR3res *resp, struct exportinfo *exi,
- struct svc_req *req, cred_t *cr)
+ struct svc_req *req, cred_t *cr, bool_t ro)
{
int error;
vnode_t *vp;
@@ -224,7 +224,7 @@ rfs3_setattr(SETATTR3args *args, SETATTR3res *resp, struct exportinfo *exi,
bvap = &bva;
- if (rdonly(exi, vp, req)) {
+ if (rdonly(ro, vp)) {
resp->status = NFS3ERR_ROFS;
goto out1;
}
@@ -364,7 +364,7 @@ rfs3_setattr_getfh(SETATTR3args *args)
/* ARGSUSED */
void
rfs3_lookup(LOOKUP3args *args, LOOKUP3res *resp, struct exportinfo *exi,
- struct svc_req *req, cred_t *cr)
+ struct svc_req *req, cred_t *cr, bool_t ro)
{
int error;
vnode_t *vp;
@@ -576,7 +576,7 @@ rfs3_lookup_getfh(LOOKUP3args *args)
/* ARGSUSED */
void
rfs3_access(ACCESS3args *args, ACCESS3res *resp, struct exportinfo *exi,
- struct svc_req *req, cred_t *cr)
+ struct svc_req *req, cred_t *cr, bool_t ro)
{
int error;
vnode_t *vp;
@@ -605,7 +605,7 @@ rfs3_access(ACCESS3args *args, ACCESS3res *resp, struct exportinfo *exi,
* Special files are interpreted by the client, so the underlying
* permissions are sent back to the client for interpretation.
*/
- if (rdonly(exi, vp, req) && (vp->v_type == VREG || vp->v_type == VDIR))
+ if (rdonly(ro, vp) && (vp->v_type == VREG || vp->v_type == VDIR))
checkwriteperm = 0;
else
checkwriteperm = 1;
@@ -732,7 +732,7 @@ rfs3_access_getfh(ACCESS3args *args)
/* ARGSUSED */
void
rfs3_readlink(READLINK3args *args, READLINK3res *resp, struct exportinfo *exi,
- struct svc_req *req, cred_t *cr)
+ struct svc_req *req, cred_t *cr, bool_t ro)
{
int error;
vnode_t *vp;
@@ -915,7 +915,7 @@ rfs3_readlink_free(READLINK3res *resp)
/* ARGSUSED */
void
rfs3_read(READ3args *args, READ3res *resp, struct exportinfo *exi,
- struct svc_req *req, cred_t *cr)
+ struct svc_req *req, cred_t *cr, bool_t ro)
{
int error;
vnode_t *vp;
@@ -1254,7 +1254,7 @@ static int rfs3_write_misses = 0;
void
rfs3_write(WRITE3args *args, WRITE3res *resp, struct exportinfo *exi,
- struct svc_req *req, cred_t *cr)
+ struct svc_req *req, cred_t *cr, bool_t ro)
{
int error;
vnode_t *vp;
@@ -1347,7 +1347,7 @@ rfs3_write(WRITE3args *args, WRITE3res *resp, struct exportinfo *exi,
goto err1;
}
- if (rdonly(exi, vp, req)) {
+ if (rdonly(ro, vp)) {
resp->status = NFS3ERR_ROFS;
goto err1;
}
@@ -1506,7 +1506,7 @@ rfs3_write_getfh(WRITE3args *args)
void
rfs3_create(CREATE3args *args, CREATE3res *resp, struct exportinfo *exi,
- struct svc_req *req, cred_t *cr)
+ struct svc_req *req, cred_t *cr, bool_t ro)
{
int error;
int in_crit = 0;
@@ -1553,7 +1553,7 @@ rfs3_create(CREATE3args *args, CREATE3res *resp, struct exportinfo *exi,
goto out1;
}
- if (rdonly(exi, dvp, req)) {
+ if (rdonly(ro, dvp)) {
resp->status = NFS3ERR_ROFS;
goto out1;
}
@@ -1869,7 +1869,7 @@ rfs3_create_getfh(CREATE3args *args)
void
rfs3_mkdir(MKDIR3args *args, MKDIR3res *resp, struct exportinfo *exi,
- struct svc_req *req, cred_t *cr)
+ struct svc_req *req, cred_t *cr, bool_t ro)
{
int error;
vnode_t *vp = NULL;
@@ -1910,7 +1910,7 @@ rfs3_mkdir(MKDIR3args *args, MKDIR3res *resp, struct exportinfo *exi,
goto out1;
}
- if (rdonly(exi, dvp, req)) {
+ if (rdonly(ro, dvp)) {
resp->status = NFS3ERR_ROFS;
goto out1;
}
@@ -2017,7 +2017,7 @@ rfs3_mkdir_getfh(MKDIR3args *args)
void
rfs3_symlink(SYMLINK3args *args, SYMLINK3res *resp, struct exportinfo *exi,
- struct svc_req *req, cred_t *cr)
+ struct svc_req *req, cred_t *cr, bool_t ro)
{
int error;
vnode_t *vp;
@@ -2059,7 +2059,7 @@ rfs3_symlink(SYMLINK3args *args, SYMLINK3res *resp, struct exportinfo *exi,
goto err1;
}
- if (rdonly(exi, dvp, req)) {
+ if (rdonly(ro, dvp)) {
resp->status = NFS3ERR_ROFS;
goto err1;
}
@@ -2191,7 +2191,7 @@ rfs3_symlink_getfh(SYMLINK3args *args)
void
rfs3_mknod(MKNOD3args *args, MKNOD3res *resp, struct exportinfo *exi,
- struct svc_req *req, cred_t *cr)
+ struct svc_req *req, cred_t *cr, bool_t ro)
{
int error;
vnode_t *vp;
@@ -2235,7 +2235,7 @@ rfs3_mknod(MKNOD3args *args, MKNOD3res *resp, struct exportinfo *exi,
goto out1;
}
- if (rdonly(exi, dvp, req)) {
+ if (rdonly(ro, dvp)) {
resp->status = NFS3ERR_ROFS;
goto out1;
}
@@ -2388,7 +2388,7 @@ rfs3_mknod_getfh(MKNOD3args *args)
void
rfs3_remove(REMOVE3args *args, REMOVE3res *resp, struct exportinfo *exi,
- struct svc_req *req, cred_t *cr)
+ struct svc_req *req, cred_t *cr, bool_t ro)
{
int error = 0;
vnode_t *vp;
@@ -2432,7 +2432,7 @@ rfs3_remove(REMOVE3args *args, REMOVE3res *resp, struct exportinfo *exi,
goto err1;
}
- if (rdonly(exi, vp, req)) {
+ if (rdonly(ro, vp)) {
resp->status = NFS3ERR_ROFS;
goto err1;
}
@@ -2533,7 +2533,7 @@ rfs3_remove_getfh(REMOVE3args *args)
void
rfs3_rmdir(RMDIR3args *args, RMDIR3res *resp, struct exportinfo *exi,
- struct svc_req *req, cred_t *cr)
+ struct svc_req *req, cred_t *cr, bool_t ro)
{
int error;
vnode_t *vp;
@@ -2576,7 +2576,7 @@ rfs3_rmdir(RMDIR3args *args, RMDIR3res *resp, struct exportinfo *exi,
goto err1;
}
- if (rdonly(exi, vp, req)) {
+ if (rdonly(ro, vp)) {
resp->status = NFS3ERR_ROFS;
goto err1;
}
@@ -2660,7 +2660,7 @@ rfs3_rmdir_getfh(RMDIR3args *args)
void
rfs3_rename(RENAME3args *args, RENAME3res *resp, struct exportinfo *exi,
- struct svc_req *req, cred_t *cr)
+ struct svc_req *req, cred_t *cr, bool_t ro)
{
int error = 0;
vnode_t *fvp;
@@ -2756,7 +2756,7 @@ rfs3_rename(RENAME3args *args, RENAME3res *resp, struct exportinfo *exi,
goto err1;
}
- if (rdonly(exi, tvp, req)) {
+ if (rdonly(ro, tvp)) {
resp->status = NFS3ERR_ROFS;
goto err1;
}
@@ -2892,7 +2892,7 @@ rfs3_rename_getfh(RENAME3args *args)
void
rfs3_link(LINK3args *args, LINK3res *resp, struct exportinfo *exi,
- struct svc_req *req, cred_t *cr)
+ struct svc_req *req, cred_t *cr, bool_t ro)
{
int error;
vnode_t *vp;
@@ -2980,7 +2980,7 @@ rfs3_link(LINK3args *args, LINK3res *resp, struct exportinfo *exi,
goto out1;
}
- if (rdonly(exi, dvp, req)) {
+ if (rdonly(ro, dvp)) {
resp->status = NFS3ERR_ROFS;
goto out1;
}
@@ -3096,7 +3096,7 @@ rfs3_link_getfh(LINK3args *args)
/* ARGSUSED */
void
rfs3_readdir(READDIR3args *args, READDIR3res *resp, struct exportinfo *exi,
- struct svc_req *req, cred_t *cr)
+ struct svc_req *req, cred_t *cr, bool_t ro)
{
int error;
vnode_t *vp;
@@ -3353,7 +3353,7 @@ static int rfs3_readdir_unit = MAXBSIZE;
/* ARGSUSED */
void
rfs3_readdirplus(READDIRPLUS3args *args, READDIRPLUS3res *resp,
- struct exportinfo *exi, struct svc_req *req, cred_t *cr)
+ struct exportinfo *exi, struct svc_req *req, cred_t *cr, bool_t ro)
{
int error;
vnode_t *vp;
@@ -3717,7 +3717,7 @@ rfs3_readdirplus_free(READDIRPLUS3res *resp)
/* ARGSUSED */
void
rfs3_fsstat(FSSTAT3args *args, FSSTAT3res *resp, struct exportinfo *exi,
- struct svc_req *req, cred_t *cr)
+ struct svc_req *req, cred_t *cr, bool_t ro)
{
int error;
vnode_t *vp;
@@ -3808,9 +3808,10 @@ rfs3_fsstat_getfh(FSSTAT3args *args)
return (&args->fsroot);
}
+/* ARGSUSED */
void
rfs3_fsinfo(FSINFO3args *args, FSINFO3res *resp, struct exportinfo *exi,
- struct svc_req *req, cred_t *cr)
+ struct svc_req *req, cred_t *cr, bool_t ro)
{
vnode_t *vp;
struct vattr *vap;
@@ -3919,7 +3920,7 @@ rfs3_fsinfo_getfh(FSINFO3args *args)
/* ARGSUSED */
void
rfs3_pathconf(PATHCONF3args *args, PATHCONF3res *resp, struct exportinfo *exi,
- struct svc_req *req, cred_t *cr)
+ struct svc_req *req, cred_t *cr, bool_t ro)
{
int error;
vnode_t *vp;
@@ -4016,7 +4017,7 @@ rfs3_pathconf_getfh(PATHCONF3args *args)
void
rfs3_commit(COMMIT3args *args, COMMIT3res *resp, struct exportinfo *exi,
- struct svc_req *req, cred_t *cr)
+ struct svc_req *req, cred_t *cr, bool_t ro)
{
int error;
vnode_t *vp;
@@ -4050,7 +4051,7 @@ rfs3_commit(COMMIT3args *args, COMMIT3res *resp, struct exportinfo *exi,
bvap = &bva;
- if (rdonly(exi, vp, req)) {
+ if (rdonly(ro, vp)) {
resp->status = NFS3ERR_ROFS;
goto out1;
}
diff --git a/usr/src/uts/common/fs/nfs/nfs4_srv.c b/usr/src/uts/common/fs/nfs/nfs4_srv.c
index 7cc71954b1..127d9e3f29 100644
--- a/usr/src/uts/common/fs/nfs/nfs4_srv.c
+++ b/usr/src/uts/common/fs/nfs/nfs4_srv.c
@@ -21,7 +21,7 @@
/*
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012 by Delphix. All rights reserved.
- * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
+ * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
*/
/*
@@ -1063,7 +1063,7 @@ do_rfs4_op_secinfo(struct compound_state *cs, char *nm, SECINFO4res *resp)
perm = secp[i].s_flags;
access = nfsauth4_secinfo_access(exi, cs->req,
- flavor, perm);
+ flavor, perm, cs->basecr);
if (! (access & NFSAUTH_DENIED) &&
! (access & NFSAUTH_WRONGSEC)) {
@@ -1274,7 +1274,7 @@ rfs4_op_access(nfs_argop4 *argop, nfs_resop4 *resop, struct svc_req *req,
* Special files are interpreted by the client, so the underlying
* permissions are sent back to the client for interpretation.
*/
- if (rdonly4(cs->exi, cs->vp, req) &&
+ if (rdonly4(req, cs) &&
(vp->v_type == VREG || vp->v_type == VDIR))
checkwriteperm = 0;
else
@@ -1410,7 +1410,7 @@ rfs4_op_commit(nfs_argop4 *argop, nfs_resop4 *resop, struct svc_req *req,
*cs->statusp = resp->status = puterrno4(error);
goto out;
}
- if (rdonly4(cs->exi, cs->vp, req)) {
+ if (rdonly4(req, cs)) {
*cs->statusp = resp->status = NFS4ERR_ROFS;
goto out;
}
@@ -1581,7 +1581,7 @@ rfs4_op_create(nfs_argop4 *argop, nfs_resop4 *resop, struct svc_req *req,
goto out;
}
- if (rdonly4(cs->exi, cs->vp, req)) {
+ if (rdonly4(req, cs)) {
*cs->statusp = resp->status = NFS4ERR_ROFS;
goto out;
}
@@ -2520,7 +2520,7 @@ rfs4_op_link(nfs_argop4 *argop, nfs_resop4 *resop, struct svc_req *req,
goto out;
}
- if (rdonly4(cs->exi, cs->vp, req)) {
+ if (rdonly4(req, cs)) {
*cs->statusp = resp->status = NFS4ERR_ROFS;
kmem_free(nm, len);
goto out;
@@ -3045,7 +3045,7 @@ rfs4_op_openattr(nfs_argop4 *argop, nfs_resop4 *resop, struct svc_req *req,
* Returning NOTSUPP is more appropriate in this case
* because the object will never be able to have an attrdir.
*/
- if (args->createdir && ! (exp_ro = rdonly4(cs->exi, cs->vp, req)))
+ if (args->createdir && ! (exp_ro = rdonly4(req, cs)))
lookup_flags |= CREATE_XATTR_DIR;
error = VOP_LOOKUP(cs->vp, "", &avp, NULL, lookup_flags, NULL, cs->cr,
@@ -4131,7 +4131,7 @@ rfs4_op_remove(nfs_argop4 *argop, nfs_resop4 *resop, struct svc_req *req,
goto out;
}
- if (rdonly4(cs->exi, cs->vp, req)) {
+ if (rdonly4(req, cs)) {
*cs->statusp = resp->status = NFS4ERR_ROFS;
kmem_free(nm, len);
goto out;
@@ -4493,7 +4493,7 @@ rfs4_op_rename(nfs_argop4 *argop, nfs_resop4 *resop, struct svc_req *req,
}
- if (rdonly4(cs->exi, cs->vp, req)) {
+ if (rdonly4(req, cs)) {
*cs->statusp = resp->status = NFS4ERR_ROFS;
if (onm != converted_onm)
kmem_free(converted_onm, MAXPATHLEN + 1);
@@ -5388,7 +5388,7 @@ rfs4_op_setattr(nfs_argop4 *argop, nfs_resop4 *resop, struct svc_req *req,
resp->attrsset = 0;
- if (rdonly4(cs->exi, cs->vp, req)) {
+ if (rdonly4(req, cs)) {
*cs->statusp = resp->status = NFS4ERR_ROFS;
goto out;
}
@@ -5615,7 +5615,7 @@ rfs4_op_write(nfs_argop4 *argop, nfs_resop4 *resop, struct svc_req *req,
goto out;
}
- if (rdonly4(cs->exi, cs->vp, req)) {
+ if (rdonly4(req, cs)) {
*cs->statusp = resp->status = NFS4ERR_ROFS;
goto out;
}
@@ -6284,7 +6284,7 @@ check_open_access(uint32_t access, struct compound_state *cs,
* to open for write, then return NFS4ERR_ROFS
*/
- readonly = rdonly4(cs->exi, cs->vp, req);
+ readonly = rdonly4(req, cs);
if ((access & OPEN4_SHARE_ACCESS_WRITE) && readonly)
return (NFS4ERR_ROFS);
@@ -6338,7 +6338,7 @@ rfs4_createfile(OPEN4args *args, struct svc_req *req, struct compound_state *cs,
dvp = cs->vp;
/* Check if the file system is read only */
- if (rdonly4(cs->exi, dvp, req))
+ if (rdonly4(req, cs))
return (NFS4ERR_ROFS);
/* check the label of including directory */
diff --git a/usr/src/uts/common/fs/nfs/nfs_acl_srv.c b/usr/src/uts/common/fs/nfs/nfs_acl_srv.c
index f6d872ac3d..8a3077c80f 100644
--- a/usr/src/uts/common/fs/nfs/nfs_acl_srv.c
+++ b/usr/src/uts/common/fs/nfs/nfs_acl_srv.c
@@ -77,7 +77,7 @@
/* ARGSUSED */
void
acl2_getacl(GETACL2args *args, GETACL2res *resp, struct exportinfo *exi,
- struct svc_req *req, cred_t *cr)
+ struct svc_req *req, cred_t *cr, bool_t ro)
{
int error;
vnode_t *vp;
@@ -191,7 +191,7 @@ acl2_getacl_free(GETACL2res *resp)
/* ARGSUSED */
void
acl2_setacl(SETACL2args *args, SETACL2res *resp, struct exportinfo *exi,
- struct svc_req *req, cred_t *cr)
+ struct svc_req *req, cred_t *cr, bool_t ro)
{
int error;
vnode_t *vp;
@@ -203,7 +203,7 @@ acl2_setacl(SETACL2args *args, SETACL2res *resp, struct exportinfo *exi,
return;
}
- if (rdonly(exi, vp, req)) {
+ if (rdonly(ro, vp)) {
VN_RELE(vp);
resp->status = NFSERR_ROFS;
return;
@@ -246,7 +246,7 @@ acl2_setacl_getfh(SETACL2args *args)
/* ARGSUSED */
void
acl2_getattr(GETATTR2args *args, GETATTR2res *resp, struct exportinfo *exi,
- struct svc_req *req, cred_t *cr)
+ struct svc_req *req, cred_t *cr, bool_t ro)
{
int error;
vnode_t *vp;
@@ -285,7 +285,7 @@ acl2_getattr_getfh(GETATTR2args *args)
/* ARGSUSED */
void
acl2_access(ACCESS2args *args, ACCESS2res *resp, struct exportinfo *exi,
- struct svc_req *req, cred_t *cr)
+ struct svc_req *req, cred_t *cr, bool_t ro)
{
int error;
vnode_t *vp;
@@ -304,7 +304,7 @@ acl2_access(ACCESS2args *args, ACCESS2res *resp, struct exportinfo *exi,
* Special files are interpreted by the client, so the underlying
* permissions are sent back to the client for interpretation.
*/
- if (rdonly(exi, vp, req) && (vp->v_type == VREG || vp->v_type == VDIR))
+ if (rdonly(ro, vp) && (vp->v_type == VREG || vp->v_type == VDIR))
checkwriteperm = 0;
else
checkwriteperm = 1;
@@ -381,7 +381,7 @@ acl2_access_getfh(ACCESS2args *args)
/* ARGSUSED */
void
acl2_getxattrdir(GETXATTRDIR2args *args, GETXATTRDIR2res *resp,
- struct exportinfo *exi, struct svc_req *req, cred_t *cr)
+ struct exportinfo *exi, struct svc_req *req, cred_t *cr, bool_t ro)
{
int error;
int flags;
@@ -446,7 +446,7 @@ acl2_getxattrdir_getfh(GETXATTRDIR2args *args)
/* ARGSUSED */
void
acl3_getacl(GETACL3args *args, GETACL3res *resp, struct exportinfo *exi,
- struct svc_req *req, cred_t *cr)
+ struct svc_req *req, cred_t *cr, bool_t ro)
{
int error;
vnode_t *vp;
@@ -557,7 +557,7 @@ acl3_getacl_free(GETACL3res *resp)
/* ARGSUSED */
void
acl3_setacl(SETACL3args *args, SETACL3res *resp, struct exportinfo *exi,
- struct svc_req *req, cred_t *cr)
+ struct svc_req *req, cred_t *cr, bool_t ro)
{
int error;
vnode_t *vp;
@@ -577,7 +577,7 @@ acl3_setacl(SETACL3args *args, SETACL3res *resp, struct exportinfo *exi,
va.va_mask = AT_ALL;
vap = rfs4_delegated_getattr(vp, &va, 0, cr) ? NULL : &va;
- if (rdonly(exi, vp, req)) {
+ if (rdonly(ro, vp)) {
resp->status = NFS3ERR_ROFS;
goto out1;
}
@@ -621,7 +621,7 @@ acl3_setacl_getfh(SETACL3args *args)
/* ARGSUSED */
void
acl3_getxattrdir(GETXATTRDIR3args *args, GETXATTRDIR3res *resp,
- struct exportinfo *exi, struct svc_req *req, cred_t *cr)
+ struct exportinfo *exi, struct svc_req *req, cred_t *cr, bool_t ro)
{
int error;
int flags;
diff --git a/usr/src/uts/common/fs/nfs/nfs_auth.c b/usr/src/uts/common/fs/nfs/nfs_auth.c
index 1a32259722..d20780ebba 100644
--- a/usr/src/uts/common/fs/nfs/nfs_auth.c
+++ b/usr/src/uts/common/fs/nfs/nfs_auth.c
@@ -316,11 +316,12 @@ addrmask(struct netbuf *addr, struct netbuf *mask)
* used does not meet the policy.
*/
int
-nfsauth4_access(struct exportinfo *exi, vnode_t *vp, struct svc_req *req)
+nfsauth4_access(struct exportinfo *exi, vnode_t *vp, struct svc_req *req,
+ cred_t *cr, uid_t *uid, gid_t *gid)
{
int access;
- access = nfsauth_access(exi, req);
+ access = nfsauth_access(exi, req, cr, uid, gid);
/*
* There are cases that the server needs to allow the client
@@ -368,7 +369,8 @@ sys_log(const char *msg)
*/
static bool_t
nfsauth_retrieve(struct exportinfo *exi, char *req_netid, int flavor,
- struct netbuf *addr, int *access)
+ struct netbuf *addr, int *access, uid_t clnt_uid, gid_t clnt_gid,
+ uid_t *srv_uid, gid_t *srv_gid)
{
varg_t varg = {0};
nfsauth_res_t res = {0};
@@ -376,8 +378,8 @@ nfsauth_retrieve(struct exportinfo *exi, char *req_netid, int flavor,
XDR xdrs_r;
size_t absz;
caddr_t abuf;
- size_t rbsz = (size_t)(BYTES_PER_XDR_UNIT * 2);
- char result[BYTES_PER_XDR_UNIT * 2] = {0};
+ size_t rbsz = (size_t)(BYTES_PER_XDR_UNIT * 4);
+ char result[BYTES_PER_XDR_UNIT * 4] = {0};
caddr_t rbuf = (caddr_t)&result;
int last = 0;
door_arg_t da;
@@ -426,6 +428,8 @@ retry:
varg.arg_u.arg.areq.req_netid = req_netid;
varg.arg_u.arg.areq.req_path = exi->exi_export.ex_path;
varg.arg_u.arg.areq.req_flavor = flavor;
+ varg.arg_u.arg.areq.req_clnt_uid = clnt_uid;
+ varg.arg_u.arg.areq.req_clnt_gid = clnt_gid;
/*
* Setup the XDR stream for encoding the arguments. Notice that
@@ -452,7 +456,7 @@ retry:
XDR_DESTROY(&xdrs_a);
/*
- * The result (nfsauth_res_t) is always two int's, so we don't
+ * The result (nfsauth_res_t) is always four int's, so we don't
* have to dynamically size (or allocate) the results buffer.
* Now that we've got what we need, we prep the door arguments
* and place the call.
@@ -485,7 +489,7 @@ retry:
* is iff userland wanted to hand us
* a bigger response than what we
* expect; that should not happen
- * (nfsauth_res_t is only 2 int's),
+ * (nfsauth_res_t is only 4 int's),
* but we check nevertheless.
*/
rbuf = da.rbuf;
@@ -493,7 +497,7 @@ retry:
} else if (rbsz > da.data_size) {
/*
- * We were expecting two int's; but if
+ * We were expecting four int's; but if
* userland fails in encoding the XDR
* stream, we detect that here, since
* the mountd forces down only one byte
@@ -588,6 +592,8 @@ retry:
switch (res.stat) {
case NFSAUTH_DR_OKAY:
*access = res.ares.auth_perm;
+ *srv_uid = res.ares.auth_srv_uid;
+ *srv_gid = res.ares.auth_srv_gid;
kmem_free(abuf, absz);
break;
@@ -707,7 +713,9 @@ nfsauth_refresh_thread(void)
ASSERT(p->auth_netid != NULL);
retrieval = nfsauth_retrieve(exi, p->auth_netid,
- p->auth_flavor, &p->auth_addr, &access);
+ p->auth_flavor, &p->auth_addr, &access,
+ p->auth_clnt_uid, p->auth_clnt_gid,
+ &p->auth_srv_uid, &p->auth_srv_gid);
/*
* This can only be set in one other place
@@ -751,8 +759,9 @@ nfsauth_refresh_thread(void)
* Get the access information from the cache or callup to the mountd
* to get and cache the access information in the kernel.
*/
-int
-nfsauth_cache_get(struct exportinfo *exi, struct svc_req *req, int flavor)
+static int
+nfsauth_cache_get(struct exportinfo *exi, struct svc_req *req, int flavor,
+ cred_t *cr, uid_t *uid, gid_t *gid)
{
struct netbuf *taddrmask;
struct netbuf addr;
@@ -765,6 +774,11 @@ nfsauth_cache_get(struct exportinfo *exi, struct svc_req *req, int flavor)
refreshq_exi_node_t *ren;
refreshq_auth_node_t *ran;
+ uid_t tmpuid;
+ gid_t tmpgid;
+
+ ASSERT(cr != NULL);
+
/*
* Now check whether this client already
* has an entry for this flavor in the cache
@@ -787,7 +801,9 @@ nfsauth_cache_get(struct exportinfo *exi, struct svc_req *req, int flavor)
rw_enter(&exi->exi_cache_lock, RW_READER);
head = &exi->exi_cache[hash(&addr)];
for (p = *head; p; p = p->auth_next) {
- if (EQADDR(&addr, &p->auth_addr) && flavor == p->auth_flavor)
+ if (EQADDR(&addr, &p->auth_addr) && flavor == p->auth_flavor &&
+ crgetuid(cr) == p->auth_clnt_uid &&
+ crgetgid(cr) == p->auth_clnt_gid)
break;
}
@@ -869,6 +885,11 @@ nfsauth_cache_get(struct exportinfo *exi, struct svc_req *req, int flavor)
}
access = p->auth_access;
+ if (uid != NULL)
+ *uid = p->auth_srv_uid;
+ if (gid != NULL)
+ *gid = p->auth_srv_gid;
+
p->auth_time = gethrestime_sec();
rw_exit(&exi->exi_cache_lock);
@@ -882,11 +903,16 @@ nfsauth_cache_get(struct exportinfo *exi, struct svc_req *req, int flavor)
nfsauth_cache_miss++;
if (!nfsauth_retrieve(exi, svc_getnetid(req->rq_xprt), flavor,
- &addr, &access)) {
+ &addr, &access, crgetuid(cr), crgetgid(cr), &tmpuid, &tmpgid)) {
kmem_free(addr.buf, addr.len);
return (access);
}
+ if (uid != NULL)
+ *uid = tmpuid;
+ if (gid != NULL)
+ *gid = tmpgid;
+
/*
* Now cache the result on the cache chain
* for this export (if there's enough memory)
@@ -895,6 +921,10 @@ nfsauth_cache_get(struct exportinfo *exi, struct svc_req *req, int flavor)
if (p != NULL) {
p->auth_addr = addr;
p->auth_flavor = flavor;
+ p->auth_clnt_uid = crgetuid(cr);
+ p->auth_clnt_gid = crgetgid(cr);
+ p->auth_srv_uid = tmpuid;
+ p->auth_srv_gid = tmpgid;
p->auth_access = access;
p->auth_time = p->auth_freshness = gethrestime_sec();
p->auth_state = NFS_AUTH_FRESH;
@@ -918,7 +948,7 @@ nfsauth_cache_get(struct exportinfo *exi, struct svc_req *req, int flavor)
*/
int
nfsauth4_secinfo_access(struct exportinfo *exi, struct svc_req *req,
- int flavor, int perm)
+ int flavor, int perm, cred_t *cr)
{
int access;
@@ -929,7 +959,7 @@ nfsauth4_secinfo_access(struct exportinfo *exi, struct svc_req *req,
/*
* Optimize if there are no lists
*/
- if ((perm & (M_ROOT|M_NONE)) == 0) {
+ if ((perm & (M_ROOT | M_NONE | M_MAP)) == 0) {
perm &= ~M_4SEC_EXPORTED;
if (perm == M_RO)
return (NFSAUTH_RO);
@@ -937,13 +967,14 @@ nfsauth4_secinfo_access(struct exportinfo *exi, struct svc_req *req,
return (NFSAUTH_RW);
}
- access = nfsauth_cache_get(exi, req, flavor);
+ access = nfsauth_cache_get(exi, req, flavor, cr, NULL, NULL);
return (access);
}
int
-nfsauth_access(struct exportinfo *exi, struct svc_req *req)
+nfsauth_access(struct exportinfo *exi, struct svc_req *req, cred_t *cr,
+ uid_t *uid, gid_t *gid)
{
int access, mapaccess;
struct secinfo *sp;
@@ -986,6 +1017,22 @@ nfsauth_access(struct exportinfo *exi, struct svc_req *req)
}
/*
+ * By default root is mapped to anonymous user.
+ * This might get overriden later in nfsauth_cache_get().
+ */
+ if (crgetuid(cr) == 0) {
+ if (uid)
+ *uid = exi->exi_export.ex_anon;
+ if (gid)
+ *gid = exi->exi_export.ex_anon;
+ } else {
+ if (uid)
+ *uid = crgetuid(cr);
+ if (gid)
+ *gid = crgetgid(cr);
+ }
+
+ /*
* If the flavor is in the ex_secinfo list, but not an explicitly
* shared flavor by the user, it is a result of the nfsv4 server
* namespace setup. We will grant an RO permission similar for
@@ -1010,7 +1057,7 @@ nfsauth_access(struct exportinfo *exi, struct svc_req *req)
* Optimize if there are no lists
*/
perm = sp[i].s_flags;
- if ((perm & (M_ROOT|M_NONE)) == 0) {
+ if ((perm & (M_ROOT | M_NONE | M_MAP)) == 0) {
perm &= ~M_4SEC_EXPORTED;
if (perm == M_RO)
return (mapaccess | NFSAUTH_RO);
@@ -1018,7 +1065,7 @@ nfsauth_access(struct exportinfo *exi, struct svc_req *req)
return (mapaccess | NFSAUTH_RW);
}
- access = nfsauth_cache_get(exi, req, flavor);
+ access = nfsauth_cache_get(exi, req, flavor, cr, uid, gid);
/*
* Client's security flavor doesn't match with "ro" or
@@ -1030,7 +1077,8 @@ nfsauth_access(struct exportinfo *exi, struct svc_req *req)
*/
if (authnone_entry != -1) {
mapaccess = NFSAUTH_MAPNONE;
- access = nfsauth_cache_get(exi, req, AUTH_NONE);
+ access = nfsauth_cache_get(exi, req, AUTH_NONE, cr,
+ NULL, NULL);
} else {
/*
* Check for AUTH_NONE presence.
@@ -1039,7 +1087,7 @@ nfsauth_access(struct exportinfo *exi, struct svc_req *req)
if (sp[i].s_secinfo.sc_nfsnum == AUTH_NONE) {
mapaccess = NFSAUTH_MAPNONE;
access = nfsauth_cache_get(exi, req,
- AUTH_NONE);
+ AUTH_NONE, cr, NULL, NULL);
break;
}
}
diff --git a/usr/src/uts/common/fs/nfs/nfs_auth_xdr.c b/usr/src/uts/common/fs/nfs/nfs_auth_xdr.c
index 8add0c2efa..d9981bafd7 100644
--- a/usr/src/uts/common/fs/nfs/nfs_auth_xdr.c
+++ b/usr/src/uts/common/fs/nfs/nfs_auth_xdr.c
@@ -22,7 +22,9 @@
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
+/*
+ * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
+ */
#include <nfs/auth.h>
@@ -61,6 +63,10 @@ xdr_nfsauth_arg(XDR *xdrs, nfsauth_arg_t *argp)
return (FALSE);
if (!xdr_int(xdrs, &argp->areq.req_flavor))
return (FALSE);
+ if (!xdr_u_int(xdrs, &argp->areq.req_clnt_uid))
+ return (FALSE);
+ if (!xdr_u_int(xdrs, &argp->areq.req_clnt_gid))
+ return (FALSE);
return (TRUE);
}
@@ -71,5 +77,9 @@ xdr_nfsauth_res(XDR *xdrs, nfsauth_res_t *argp)
return (FALSE);
if (!xdr_int(xdrs, &argp->ares.auth_perm))
return (FALSE);
+ if (!xdr_u_int(xdrs, &argp->ares.auth_srv_uid))
+ return (FALSE);
+ if (!xdr_u_int(xdrs, &argp->ares.auth_srv_gid))
+ return (FALSE);
return (TRUE);
}
diff --git a/usr/src/uts/common/fs/nfs/nfs_server.c b/usr/src/uts/common/fs/nfs/nfs_server.c
index c777d8acff..ca3d7d8bb9 100644
--- a/usr/src/uts/common/fs/nfs/nfs_server.c
+++ b/usr/src/uts/common/fs/nfs/nfs_server.c
@@ -191,7 +191,7 @@ static void common_dispatch(struct svc_req *, SVCXPRT *,
struct rpc_disptable *);
static void hanfsv4_failover(void);
static int checkauth(struct exportinfo *, struct svc_req *, cred_t *, int,
- bool_t);
+ bool_t, bool_t *);
static char *client_name(struct svc_req *req);
static char *client_addr(struct svc_req *req, char *buf);
extern int sec_svc_getcred(struct svc_req *, cred_t *cr, char **, int *);
@@ -649,14 +649,15 @@ restart:
/* ARGSUSED */
void
-rpc_null(caddr_t *argp, caddr_t *resp)
+rpc_null(caddr_t *argp, caddr_t *resp, struct exportinfo *exi,
+ struct svc_req *req, cred_t *cr, bool_t ro)
{
}
/* ARGSUSED */
void
rpc_null_v3(caddr_t *argp, caddr_t *resp, struct exportinfo *exi,
- struct svc_req *req, cred_t *cr)
+ struct svc_req *req, cred_t *cr, bool_t ro)
{
DTRACE_NFSV3_3(op__null__start, struct svc_req *, req,
cred_t *, cr, vnode_t *, NULL);
@@ -666,7 +667,8 @@ rpc_null_v3(caddr_t *argp, caddr_t *resp, struct exportinfo *exi,
/* ARGSUSED */
static void
-rfs_error(caddr_t *argp, caddr_t *resp)
+rfs_error(caddr_t *argp, caddr_t *resp, struct exportinfo *exi,
+ struct svc_req *req, cred_t *cr, bool_t ro)
{
/* return (EOPNOTSUPP); */
}
@@ -1503,6 +1505,7 @@ common_dispatch(struct svc_req *req, SVCXPRT *xprt, rpcvers_t min_vers,
struct exportinfo *nfslog_exi = NULL;
char **procnames;
char cbuf[INET6_ADDRSTRLEN]; /* to hold both IPv4 and IPv6 addr */
+ bool_t ro = FALSE;
vers = req->rq_vers;
@@ -1657,7 +1660,8 @@ common_dispatch(struct svc_req *req, SVCXPRT *xprt, rpcvers_t min_vers,
goto done;
}
- authres = checkauth(exi, req, cr, anon_ok, publicfh_ok);
+ authres = checkauth(exi, req, cr, anon_ok, publicfh_ok,
+ &ro);
/*
* authres > 0: authentication OK - proceed
* authres == 0: authentication weak - return error
@@ -1701,7 +1705,7 @@ common_dispatch(struct svc_req *req, SVCXPRT *xprt, rpcvers_t min_vers,
case DUP_DROP:
curthread->t_flag |= T_DONTPEND;
- (*disp->dis_proc)(args, res, exi, req, cr);
+ (*disp->dis_proc)(args, res, exi, req, cr, ro);
curthread->t_flag &= ~T_DONTPEND;
if (curthread->t_flag & T_WOULDBLOCK) {
@@ -1731,7 +1735,7 @@ common_dispatch(struct svc_req *req, SVCXPRT *xprt, rpcvers_t min_vers,
} else {
curthread->t_flag |= T_DONTPEND;
- (*disp->dis_proc)(args, res, exi, req, cr);
+ (*disp->dis_proc)(args, res, exi, req, cr, ro);
curthread->t_flag &= ~T_DONTPEND;
if (curthread->t_flag & T_WOULDBLOCK) {
@@ -2005,7 +2009,7 @@ checkwin(int flavor, int window, struct svc_req *req)
*/
static int
checkauth(struct exportinfo *exi, struct svc_req *req, cred_t *cr, int anon_ok,
- bool_t publicfh_ok)
+ bool_t publicfh_ok, bool_t *ro)
{
int i, nfsflavor, rpcflavor, stat, access;
struct secinfo *secp;
@@ -2013,6 +2017,9 @@ checkauth(struct exportinfo *exi, struct svc_req *req, cred_t *cr, int anon_ok,
char buf[INET6_ADDRSTRLEN]; /* to hold both IPv4 and IPv6 addr */
int anon_res = 0;
+ uid_t uid;
+ gid_t gid;
+
/*
* Check for privileged port number
* N.B.: this assumes that we know the format of a netbuf.
@@ -2044,7 +2051,7 @@ checkauth(struct exportinfo *exi, struct svc_req *req, cred_t *cr, int anon_ok,
stat = sec_svc_getcred(req, cr, &principal, &nfsflavor);
/*
- * A failed AUTH_UNIX svc_get_cred() implies we couldn't set
+ * A failed AUTH_UNIX sec_svc_getcred() implies we couldn't set
* the credentials; below we map that to anonymous.
*/
if (!stat && nfsflavor != AUTH_UNIX) {
@@ -2070,14 +2077,17 @@ checkauth(struct exportinfo *exi, struct svc_req *req, cred_t *cr, int anon_ok,
/*
* Check if the auth flavor is valid for this export
*/
- access = nfsauth_access(exi, req);
+ access = nfsauth_access(exi, req, cr, &uid, &gid);
if (access & NFSAUTH_DROP)
return (-1); /* drop the request */
+ if (access & NFSAUTH_RO)
+ *ro = TRUE;
+
if (access & NFSAUTH_DENIED) {
/*
* If anon_ok == 1 and we got NFSAUTH_DENIED, it was
- * probably due to the flavor not matching during the
+ * probably due to the flavor not matching during
* the mount attempt. So map the flavor to AUTH_NONE
* so that the credentials get mapped to the anonymous
* user.
@@ -2111,12 +2121,11 @@ checkauth(struct exportinfo *exi, struct svc_req *req, cred_t *cr, int anon_ok,
break;
case AUTH_UNIX:
- if (!stat || crgetuid(cr) == 0 && !(access & NFSAUTH_ROOT)) {
+ if (!stat || crgetuid(cr) == 0 && !(access & NFSAUTH_UIDMAP)) {
anon_res = crsetugid(cr, exi->exi_export.ex_anon,
exi->exi_export.ex_anon);
(void) crsetgroups(cr, 0, NULL);
- } else if (!stat || crgetuid(cr) == 0 &&
- access & NFSAUTH_ROOT) {
+ } else if (crgetuid(cr) == 0 && access & NFSAUTH_ROOT) {
/*
* It is root, so apply rootid to get real UID
* Find the secinfo structure. We should be able
@@ -2137,7 +2146,14 @@ checkauth(struct exportinfo *exi, struct svc_req *req, cred_t *cr, int anon_ok,
secp->s_rootid);
(void) crsetgroups(cr, 0, NULL);
}
+ } else if (crgetuid(cr) != uid || crgetgid(cr) != gid) {
+ if (crsetugid(cr, uid, gid) != 0)
+ anon_res = crsetugid(cr,
+ exi->exi_export.ex_anon,
+ exi->exi_export.ex_anon);
+ (void) crsetgroups(cr, 0, NULL);
}
+
break;
case AUTH_DES:
@@ -2253,6 +2269,9 @@ checkauth4(struct compound_state *cs, struct svc_req *req)
cred_t *cr;
caddr_t principal;
+ uid_t uid;
+ gid_t gid;
+
exi = cs->exi;
cr = cs->cr;
principal = cs->principal;
@@ -2292,7 +2311,7 @@ checkauth4(struct compound_state *cs, struct svc_req *req)
* Check the access right per auth flavor on the vnode of
* this export for the given request.
*/
- access = nfsauth4_access(cs->exi, cs->vp, req);
+ access = nfsauth4_access(cs->exi, cs->vp, req, cr, &uid, &gid);
if (access & NFSAUTH_WRONGSEC)
return (-2); /* no access for this security flavor */
@@ -2330,7 +2349,7 @@ checkauth4(struct compound_state *cs, struct svc_req *req)
break;
case AUTH_UNIX:
- if (crgetuid(cr) == 0 && !(access & NFSAUTH_ROOT)) {
+ if (crgetuid(cr) == 0 && !(access & NFSAUTH_UIDMAP)) {
anon_res = crsetugid(cr, exi->exi_export.ex_anon,
exi->exi_export.ex_anon);
(void) crsetgroups(cr, 0, NULL);
@@ -2355,7 +2374,14 @@ checkauth4(struct compound_state *cs, struct svc_req *req)
secp->s_rootid);
(void) crsetgroups(cr, 0, NULL);
}
+ } else if (crgetuid(cr) != uid || crgetgid(cr) != gid) {
+ if (crsetugid(cr, uid, gid) != 0)
+ anon_res = crsetugid(cr,
+ exi->exi_export.ex_anon,
+ exi->exi_export.ex_anon);
+ (void) crsetgroups(cr, 0, NULL);
}
+
break;
default:
diff --git a/usr/src/uts/common/fs/nfs/nfs_srv.c b/usr/src/uts/common/fs/nfs/nfs_srv.c
index b7f96d5cec..054a6d1233 100644
--- a/usr/src/uts/common/fs/nfs/nfs_srv.c
+++ b/usr/src/uts/common/fs/nfs/nfs_srv.c
@@ -96,7 +96,7 @@ u_longlong_t nfs2_srv_caller_id;
/* ARGSUSED */
void
rfs_getattr(fhandle_t *fhp, struct nfsattrstat *ns, struct exportinfo *exi,
- struct svc_req *req, cred_t *cr)
+ struct svc_req *req, cred_t *cr, bool_t ro)
{
int error;
vnode_t *vp;
@@ -140,9 +140,10 @@ rfs_getattr_getfh(fhandle_t *fhp)
* Sets the attributes of the file with the given fhandle. Returns
* the new attributes.
*/
+/* ARGSUSED */
void
rfs_setattr(struct nfssaargs *args, struct nfsattrstat *ns,
- struct exportinfo *exi, struct svc_req *req, cred_t *cr)
+ struct exportinfo *exi, struct svc_req *req, cred_t *cr, bool_t ro)
{
int error;
int flag;
@@ -160,7 +161,7 @@ rfs_setattr(struct nfssaargs *args, struct nfsattrstat *ns,
return;
}
- if (rdonly(exi, vp, req)) {
+ if (rdonly(ro, vp)) {
VN_RELE(vp);
ns->ns_status = NFSERR_ROFS;
return;
@@ -334,7 +335,7 @@ rfs_setattr_getfh(struct nfssaargs *args)
/* ARGSUSED */
void
rfs_lookup(struct nfsdiropargs *da, struct nfsdiropres *dr,
- struct exportinfo *exi, struct svc_req *req, cred_t *cr)
+ struct exportinfo *exi, struct svc_req *req, cred_t *cr, bool_t ro)
{
int error;
vnode_t *dvp;
@@ -484,7 +485,7 @@ rfs_lookup_getfh(struct nfsdiropargs *da)
/* ARGSUSED */
void
rfs_readlink(fhandle_t *fhp, struct nfsrdlnres *rl, struct exportinfo *exi,
- struct svc_req *req, cred_t *cr)
+ struct svc_req *req, cred_t *cr, bool_t ro)
{
int error;
struct iovec iov;
@@ -631,7 +632,7 @@ static int rdma_setup_read_data2(struct nfsreadargs *, struct nfsrdresult *);
/* ARGSUSED */
void
rfs_read(struct nfsreadargs *ra, struct nfsrdresult *rr,
- struct exportinfo *exi, struct svc_req *req, cred_t *cr)
+ struct exportinfo *exi, struct svc_req *req, cred_t *cr, bool_t ro)
{
vnode_t *vp;
int error;
@@ -912,9 +913,10 @@ static int rfs_write_sync_misses = 0;
* Any changes made here, especially in error handling might have
* to also be done in rfs_write (which clusters write requests).
*/
+/* ARGSUSED */
void
rfs_write_sync(struct nfswriteargs *wa, struct nfsattrstat *ns,
- struct exportinfo *exi, struct svc_req *req, cred_t *cr)
+ struct exportinfo *exi, struct svc_req *req, cred_t *cr, bool_t ro)
{
int error;
vnode_t *vp;
@@ -935,7 +937,7 @@ rfs_write_sync(struct nfswriteargs *wa, struct nfsattrstat *ns,
return;
}
- if (rdonly(exi, vp, req)) {
+ if (rdonly(ro, vp)) {
VN_RELE(vp);
ns->ns_status = NFSERR_ROFS;
return;
@@ -1134,6 +1136,7 @@ struct rfs_async_write {
struct nfsattrstat *ns;
struct svc_req *req;
cred_t *cr;
+ bool_t ro;
kthread_t *thread;
struct rfs_async_write *list;
};
@@ -1163,7 +1166,7 @@ static int rfs_write_misses = 0;
*/
void
rfs_write(struct nfswriteargs *wa, struct nfsattrstat *ns,
- struct exportinfo *exi, struct svc_req *req, cred_t *cr)
+ struct exportinfo *exi, struct svc_req *req, cred_t *cr, bool_t ro)
{
int error;
vnode_t *vp;
@@ -1194,7 +1197,7 @@ rfs_write(struct nfswriteargs *wa, struct nfsattrstat *ns,
caller_context_t ct;
if (!rfs_write_async) {
- rfs_write_sync(wa, ns, exi, req, cr);
+ rfs_write_sync(wa, ns, exi, req, cr, ro);
return;
}
@@ -1209,6 +1212,7 @@ rfs_write(struct nfswriteargs *wa, struct nfsattrstat *ns,
nrp->ns = ns;
nrp->req = req;
nrp->cr = cr;
+ nrp->ro = ro;
nrp->thread = curthread;
ASSERT(curthread->t_schedflag & TS_DONT_SWAP);
@@ -1415,7 +1419,7 @@ rfs_write(struct nfswriteargs *wa, struct nfsattrstat *ns,
off = rp->wa->wa_offset;
len = (uint_t)0;
do {
- if (rdonly(exi, vp, rp->req)) {
+ if (rdonly(rp->ro, vp)) {
rp->ns->ns_status = NFSERR_ROFS;
t_flag = curthread->t_flag & T_WOULDBLOCK;
rp->thread->t_flag |= t_flag;
@@ -1668,7 +1672,7 @@ rfs_write_getfh(struct nfswriteargs *wa)
*/
void
rfs_create(struct nfscreatargs *args, struct nfsdiropres *dr,
- struct exportinfo *exi, struct svc_req *req, cred_t *cr)
+ struct exportinfo *exi, struct svc_req *req, cred_t *cr, bool_t ro)
{
int error;
int lookuperr;
@@ -1787,7 +1791,7 @@ rfs_create(struct nfscreatargs *args, struct nfsdiropres *dr,
}
if (!lookup_ok) {
- if (rdonly(exi, dvp, req)) {
+ if (rdonly(ro, dvp)) {
error = EROFS;
} else if (va.va_type != VREG && va.va_type != VFIFO &&
va.va_type != VSOCK && secpolicy_sys_devices(cr) != 0) {
@@ -1933,9 +1937,10 @@ rfs_create_getfh(struct nfscreatargs *args)
* Remove a file.
* Remove named file from parent directory.
*/
+/* ARGSUSED */
void
rfs_remove(struct nfsdiropargs *da, enum nfsstat *status,
- struct exportinfo *exi, struct svc_req *req, cred_t *cr)
+ struct exportinfo *exi, struct svc_req *req, cred_t *cr, bool_t ro)
{
int error = 0;
vnode_t *vp;
@@ -1956,7 +1961,7 @@ rfs_remove(struct nfsdiropargs *da, enum nfsstat *status,
return;
}
- if (rdonly(exi, vp, req)) {
+ if (rdonly(ro, vp)) {
VN_RELE(vp);
*status = NFSERR_ROFS;
return;
@@ -2024,9 +2029,10 @@ rfs_remove_getfh(struct nfsdiropargs *da)
* rename a file
* Give a file (from) a new name (to).
*/
+/* ARGSUSED */
void
rfs_rename(struct nfsrnmargs *args, enum nfsstat *status,
- struct exportinfo *exi, struct svc_req *req, cred_t *cr)
+ struct exportinfo *exi, struct svc_req *req, cred_t *cr, bool_t ro)
{
int error = 0;
vnode_t *fromvp;
@@ -2083,7 +2089,7 @@ rfs_rename(struct nfsrnmargs *args, enum nfsstat *status,
return;
}
- if (rdonly(exi, tovp, req)) {
+ if (rdonly(ro, tovp)) {
VN_RELE(tovp);
VN_RELE(fromvp);
*status = NFSERR_ROFS;
@@ -2172,9 +2178,10 @@ rfs_rename_getfh(struct nfsrnmargs *args)
* Link to a file.
* Create a file (to) which is a hard link to the given file (from).
*/
+/* ARGSUSED */
void
rfs_link(struct nfslinkargs *args, enum nfsstat *status,
- struct exportinfo *exi, struct svc_req *req, cred_t *cr)
+ struct exportinfo *exi, struct svc_req *req, cred_t *cr, bool_t ro)
{
int error;
vnode_t *fromvp;
@@ -2226,7 +2233,7 @@ rfs_link(struct nfslinkargs *args, enum nfsstat *status,
return;
}
- if (rdonly(exi, tovp, req)) {
+ if (rdonly(ro, tovp)) {
VN_RELE(tovp);
VN_RELE(fromvp);
*status = NFSERR_ROFS;
@@ -2260,7 +2267,7 @@ rfs_link_getfh(struct nfslinkargs *args)
*/
void
rfs_symlink(struct nfsslargs *args, enum nfsstat *status,
- struct exportinfo *exi, struct svc_req *req, cred_t *cr)
+ struct exportinfo *exi, struct svc_req *req, cred_t *cr, bool_t ro)
{
int error;
struct vattr va;
@@ -2284,7 +2291,7 @@ rfs_symlink(struct nfsslargs *args, enum nfsstat *status,
return;
}
- if (rdonly(exi, vp, req)) {
+ if (rdonly(ro, vp)) {
VN_RELE(vp);
*status = NFSERR_ROFS;
return;
@@ -2351,9 +2358,10 @@ rfs_symlink_getfh(struct nfsslargs *args)
* Create a directory with the given name, parent directory, and attributes.
* Returns a file handle and attributes for the new directory.
*/
+/* ARGSUSED */
void
rfs_mkdir(struct nfscreatargs *args, struct nfsdiropres *dr,
- struct exportinfo *exi, struct svc_req *req, cred_t *cr)
+ struct exportinfo *exi, struct svc_req *req, cred_t *cr, bool_t ro)
{
int error;
struct vattr va;
@@ -2375,7 +2383,7 @@ rfs_mkdir(struct nfscreatargs *args, struct nfsdiropres *dr,
return;
}
- if (rdonly(exi, vp, req)) {
+ if (rdonly(ro, vp)) {
VN_RELE(vp);
dr->dr_status = NFSERR_ROFS;
return;
@@ -2442,9 +2450,10 @@ rfs_mkdir_getfh(struct nfscreatargs *args)
* Remove a directory.
* Remove the given directory name from the given parent directory.
*/
+/* ARGSUSED */
void
rfs_rmdir(struct nfsdiropargs *da, enum nfsstat *status,
- struct exportinfo *exi, struct svc_req *req, cred_t *cr)
+ struct exportinfo *exi, struct svc_req *req, cred_t *cr, bool_t ro)
{
int error;
vnode_t *vp;
@@ -2463,7 +2472,7 @@ rfs_rmdir(struct nfsdiropargs *da, enum nfsstat *status,
return;
}
- if (rdonly(exi, vp, req)) {
+ if (rdonly(ro, vp)) {
VN_RELE(vp);
*status = NFSERR_ROFS;
return;
@@ -2508,7 +2517,7 @@ rfs_rmdir_getfh(struct nfsdiropargs *da)
/* ARGSUSED */
void
rfs_readdir(struct nfsrddirargs *rda, struct nfsrddirres *rd,
- struct exportinfo *exi, struct svc_req *req, cred_t *cr)
+ struct exportinfo *exi, struct svc_req *req, cred_t *cr, bool_t ro)
{
int error;
int iseof;
@@ -2653,7 +2662,7 @@ rfs_rddirfree(struct nfsrddirres *rd)
/* ARGSUSED */
void
rfs_statfs(fhandle_t *fh, struct nfsstatfs *fs, struct exportinfo *exi,
- struct svc_req *req, cred_t *cr)
+ struct svc_req *req, cred_t *cr, bool_t ro)
{
int error;
struct statvfs64 sb;
diff --git a/usr/src/uts/common/nfs/auth.h b/usr/src/uts/common/nfs/auth.h
index a30567935c..365b1ff6d7 100644
--- a/usr/src/uts/common/nfs/auth.h
+++ b/usr/src/uts/common/nfs/auth.h
@@ -22,13 +22,13 @@
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
+/*
+ * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
+ */
#ifndef _AUTH_H
#define _AUTH_H
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-
/*
* nfsauth_prot.x (The NFSAUTH Protocol)
*
@@ -39,7 +39,7 @@
* The status result determines what kind of access the client is permitted.
*
* The result is cached in the kernel, so the authorization call will be
- * made * only the first time the client mounts the filesystem.
+ * made only the first time the client mounts the filesystem.
*
* const A_MAXPATH = 1024;
*
@@ -48,6 +48,8 @@
* string req_netid<>; # Netid of address
* string req_path<A_MAXPATH>; # export path
* int req_flavor; # auth flavor
+ * uid_t req_clnt_uid; # client's uid
+ * gid_t req_clnt_gid; # client's gid
* };
*
* const NFSAUTH_DENIED = 0x01; # Access denied
@@ -56,6 +58,8 @@
* const NFSAUTH_ROOT = 0x08; # Root access
* const NFSAUTH_WRONGSEC = 0x10; # Advise NFS v4 clients to
* # try a different flavor
+ * const NFSAUTH_UIDMAP = 0x100; # uid mapped
+ * const NFSAUTH_GIDMAP = 0x200; # gid mapped
* #
* # The following are not part of the protocol.
* #
@@ -65,6 +69,8 @@
*
* struct auth_res {
* int auth_perm;
+ * uid_t auth_srv_uid;
+ * gid_t auth_srv_gid;
* };
*
* program NFSAUTH_PROG {
@@ -105,17 +111,23 @@ extern "C" {
#define NFSAUTH_DROP 0x20
#define NFSAUTH_MAPNONE 0x40
#define NFSAUTH_LIMITED 0x80
+#define NFSAUTH_UIDMAP 0x100
+#define NFSAUTH_GIDMAP 0x200
struct auth_req {
netobj req_client;
char *req_netid;
char *req_path;
int req_flavor;
+ uid_t req_clnt_uid;
+ gid_t req_clnt_gid;
};
typedef struct auth_req auth_req;
struct auth_res {
int auth_perm;
+ uid_t auth_srv_uid;
+ gid_t auth_srv_gid;
};
typedef struct auth_res auth_res;
diff --git a/usr/src/uts/common/nfs/export.h b/usr/src/uts/common/nfs/export.h
index 89c046545e..821ff44fdd 100644
--- a/usr/src/uts/common/nfs/export.h
+++ b/usr/src/uts/common/nfs/export.h
@@ -110,6 +110,7 @@ struct sec_ol {
#define M_ROOT 0x10 /* root list is defined */
#define M_4SEC_EXPORTED 0x20 /* this is an explicitly shared flavor */
#define M_NONE 0x40 /* none list is defined */
+#define M_MAP 0x80 /* uidmap and/or gidmap is defined */
/* invalid secinfo reference count */
#define SEC_REF_INVALID(p) ((p)->s_refcnt < 1)
@@ -190,7 +191,7 @@ struct exportdata32 {
#define RPC_IDEMPOTENT 0x1 /* idempotent or not */
/*
* Be very careful about which NFS procedures get the RPC_ALLOWANON bit.
- * Right now, it this bit is on, we ignore the results of per NFS request
+ * Right now, if this bit is on, we ignore the results of per NFS request
* access control.
*/
#define RPC_ALLOWANON 0x2 /* allow anonymous access */
@@ -253,6 +254,10 @@ typedef enum auth_state {
struct auth_cache {
struct netbuf auth_addr;
int auth_flavor;
+ uid_t auth_clnt_uid;
+ gid_t auth_clnt_gid;
+ uid_t auth_srv_uid;
+ gid_t auth_srv_gid;
int auth_access;
time_t auth_time;
time_t auth_freshness;
@@ -533,31 +538,30 @@ typedef struct exp_visible exp_visible_t;
* Note: this macro should be as fast as possible since it's called
* on each NFS modification request.
*/
-#define rdonly(exi, vp, req) \
- (vn_is_readonly(vp) || \
- (nfsauth_access(exi, req) & NFSAUTH_RO))
-#define rdonly4(exi, vp, req) \
- (vn_is_readonly(vp) || \
- (nfsauth4_access(exi, vp, req) & (NFSAUTH_RO | NFSAUTH_LIMITED)))
+#define rdonly(ro, vp) ((ro) || vn_is_readonly(vp))
+#define rdonly4(req, cs) \
+ (vn_is_readonly((cs)->vp) || \
+ (nfsauth4_access((cs)->exi, (cs)->vp, (req), (cs)->basecr, NULL, \
+ NULL) & (NFSAUTH_RO | NFSAUTH_LIMITED)))
extern int nfsauth4_access(struct exportinfo *, vnode_t *,
- struct svc_req *);
+ struct svc_req *, cred_t *, uid_t *, gid_t *);
extern int nfsauth4_secinfo_access(struct exportinfo *,
- struct svc_req *, int, int);
+ struct svc_req *, int, int, cred_t *);
extern int nfs_fhbcmp(char *, char *, int);
extern int nfs_exportinit(void);
extern void nfs_exportfini(void);
-extern int chk_clnt_sec(struct exportinfo *, struct svc_req *req);
+extern int chk_clnt_sec(struct exportinfo *, struct svc_req *);
extern int makefh(fhandle_t *, struct vnode *, struct exportinfo *);
extern int makefh_ol(fhandle_t *, struct exportinfo *, uint_t);
extern int makefh3(nfs_fh3 *, struct vnode *, struct exportinfo *);
extern int makefh3_ol(nfs_fh3 *, struct exportinfo *, uint_t);
extern vnode_t *nfs_fhtovp(fhandle_t *, struct exportinfo *);
extern vnode_t *nfs3_fhtovp(nfs_fh3 *, struct exportinfo *);
-extern vnode_t *lm_fhtovp(fhandle_t *fh);
-extern vnode_t *lm_nfs3_fhtovp(nfs_fh3 *fh);
+extern vnode_t *lm_fhtovp(fhandle_t *);
+extern vnode_t *lm_nfs3_fhtovp(nfs_fh3 *);
extern struct exportinfo *checkexport(fsid_t *, struct fid *);
-extern struct exportinfo *checkexport4(fsid_t *, struct fid *, vnode_t *vp);
+extern struct exportinfo *checkexport4(fsid_t *, struct fid *, vnode_t *);
extern void exi_hold(struct exportinfo *);
extern void exi_rele(struct exportinfo *);
extern struct exportinfo *nfs_vptoexi(vnode_t *, vnode_t *, cred_t *, int *,
@@ -584,7 +588,7 @@ extern void free_visible(struct exp_visible *);
extern int nfs_exported(struct exportinfo *, vnode_t *);
extern struct exportinfo *pseudo_exportfs(vnode_t *, fid_t *,
struct exp_visible *, struct exportdata *);
-extern int vop_fid_pseudo(vnode_t *, fid_t *fidp);
+extern int vop_fid_pseudo(vnode_t *, fid_t *);
extern int nfs4_vget_pseudo(struct exportinfo *, vnode_t **, fid_t *);
/*
* Functions that handle the NFSv4 server namespace security flavors
diff --git a/usr/src/uts/common/nfs/nfs.h b/usr/src/uts/common/nfs/nfs.h
index ede19e2430..b85fe98b11 100644
--- a/usr/src/uts/common/nfs/nfs.h
+++ b/usr/src/uts/common/nfs/nfs.h
@@ -20,9 +20,8 @@
*/
/*
* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
- *
- * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2013 by Delphix. All rights reserved.
+ * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
*/
/* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
@@ -750,43 +749,43 @@ struct nfsstatfs {
/*
* XDR routines for handling structures defined above
*/
-bool_t xdr_attrstat(XDR *, struct nfsattrstat *);
-bool_t xdr_fastattrstat(XDR *, struct nfsattrstat *);
-bool_t xdr_creatargs(XDR *, struct nfscreatargs *);
-bool_t xdr_diropargs(XDR *, struct nfsdiropargs *);
-bool_t xdr_diropres(XDR *, struct nfsdiropres *);
-bool_t xdr_fastdiropres(XDR *, struct nfsdiropres *);
-bool_t xdr_drok(XDR *, struct nfsdrok *);
+extern bool_t xdr_attrstat(XDR *, struct nfsattrstat *);
+extern bool_t xdr_fastattrstat(XDR *, struct nfsattrstat *);
+extern bool_t xdr_creatargs(XDR *, struct nfscreatargs *);
+extern bool_t xdr_diropargs(XDR *, struct nfsdiropargs *);
+extern bool_t xdr_diropres(XDR *, struct nfsdiropres *);
+extern bool_t xdr_fastdiropres(XDR *, struct nfsdiropres *);
+extern bool_t xdr_drok(XDR *, struct nfsdrok *);
#ifdef _LITTLE_ENDIAN
-bool_t xdr_fastdrok(XDR *, struct nfsdrok *);
-bool_t xdr_fastfattr(XDR *, struct nfsfattr *);
+extern bool_t xdr_fastdrok(XDR *, struct nfsdrok *);
+extern bool_t xdr_fastfattr(XDR *, struct nfsfattr *);
#endif
-bool_t xdr_fattr(XDR *, struct nfsfattr *);
-bool_t xdr_fhandle(XDR *, fhandle_t *);
-bool_t xdr_fastfhandle(XDR *, fhandle_t **);
-bool_t xdr_linkargs(XDR *, struct nfslinkargs *);
-bool_t xdr_rddirargs(XDR *, struct nfsrddirargs *);
-bool_t xdr_putrddirres(XDR *, struct nfsrddirres *);
-bool_t xdr_getrddirres(XDR *, struct nfsrddirres *);
-bool_t xdr_rdlnres(XDR *, struct nfsrdlnres *);
-bool_t xdr_rdresult(XDR *, struct nfsrdresult *);
-bool_t xdr_readargs(XDR *, struct nfsreadargs *);
-bool_t xdr_readlink(XDR *, fhandle_t *);
-bool_t xdr_rnmargs(XDR *, struct nfsrnmargs *);
-bool_t xdr_rrok(XDR *, struct nfsrrok *);
-bool_t xdr_saargs(XDR *, struct nfssaargs *);
-bool_t xdr_sattr(XDR *, struct nfssattr *);
-bool_t xdr_slargs(XDR *, struct nfsslargs *);
-bool_t xdr_srok(XDR *, struct nfssrok *);
-bool_t xdr_nfs2_timeval(XDR *, struct nfs2_timeval *);
-bool_t xdr_writeargs(XDR *, struct nfswriteargs *);
-bool_t xdr_fsok(XDR *, struct nfsstatfsok *);
+extern bool_t xdr_fattr(XDR *, struct nfsfattr *);
+extern bool_t xdr_fhandle(XDR *, fhandle_t *);
+extern bool_t xdr_fastfhandle(XDR *, fhandle_t **);
+extern bool_t xdr_linkargs(XDR *, struct nfslinkargs *);
+extern bool_t xdr_rddirargs(XDR *, struct nfsrddirargs *);
+extern bool_t xdr_putrddirres(XDR *, struct nfsrddirres *);
+extern bool_t xdr_getrddirres(XDR *, struct nfsrddirres *);
+extern bool_t xdr_rdlnres(XDR *, struct nfsrdlnres *);
+extern bool_t xdr_rdresult(XDR *, struct nfsrdresult *);
+extern bool_t xdr_readargs(XDR *, struct nfsreadargs *);
+extern bool_t xdr_readlink(XDR *, fhandle_t *);
+extern bool_t xdr_rnmargs(XDR *, struct nfsrnmargs *);
+extern bool_t xdr_rrok(XDR *, struct nfsrrok *);
+extern bool_t xdr_saargs(XDR *, struct nfssaargs *);
+extern bool_t xdr_sattr(XDR *, struct nfssattr *);
+extern bool_t xdr_slargs(XDR *, struct nfsslargs *);
+extern bool_t xdr_srok(XDR *, struct nfssrok *);
+extern bool_t xdr_nfs2_timeval(XDR *, struct nfs2_timeval *);
+extern bool_t xdr_writeargs(XDR *, struct nfswriteargs *);
+extern bool_t xdr_fsok(XDR *, struct nfsstatfsok *);
#ifdef _LITTLE_ENDIAN
-bool_t xdr_fastfsok(XDR *, struct nfsstatfsok *);
-bool_t xdr_fastenum(XDR *, enum_t *);
+extern bool_t xdr_fastfsok(XDR *, struct nfsstatfsok *);
+extern bool_t xdr_fastenum(XDR *, enum_t *);
#endif
-bool_t xdr_statfs(XDR *, struct nfsstatfs *);
-bool_t xdr_faststatfs(XDR *, struct nfsstatfs *);
+extern bool_t xdr_statfs(XDR *, struct nfsstatfs *);
+extern bool_t xdr_faststatfs(XDR *, struct nfsstatfs *);
#endif
/*
@@ -820,58 +819,58 @@ struct exportinfo; /* defined in nfs/export.h */
struct servinfo; /* defined in nfs/nfs_clnt.h */
struct mntinfo; /* defined in nfs/nfs_clnt.h */
-void rfs_getattr(fhandle_t *, struct nfsattrstat *, struct exportinfo *,
- struct svc_req *, cred_t *);
-void *rfs_getattr_getfh(fhandle_t *);
-void rfs_setattr(struct nfssaargs *, struct nfsattrstat *,
- struct exportinfo *, struct svc_req *, cred_t *);
-void *rfs_setattr_getfh(struct nfssaargs *);
-void rfs_lookup(struct nfsdiropargs *, struct nfsdiropres *,
- struct exportinfo *, struct svc_req *, cred_t *);
-void *rfs_lookup_getfh(struct nfsdiropargs *);
-void rfs_readlink(fhandle_t *, struct nfsrdlnres *, struct exportinfo *,
- struct svc_req *, cred_t *);
-void *rfs_readlink_getfh(fhandle_t *);
-void rfs_rlfree(struct nfsrdlnres *);
-void rfs_read(struct nfsreadargs *, struct nfsrdresult *,
- struct exportinfo *, struct svc_req *, cred_t *);
-void *rfs_read_getfh(struct nfsreadargs *);
-void rfs_rdfree(struct nfsrdresult *);
-void rfs_write_sync(struct nfswriteargs *, struct nfsattrstat *,
- struct exportinfo *, struct svc_req *, cred_t *);
-void rfs_write(struct nfswriteargs *, struct nfsattrstat *,
- struct exportinfo *, struct svc_req *, cred_t *);
-void *rfs_write_getfh(struct nfswriteargs *);
-void rfs_create(struct nfscreatargs *, struct nfsdiropres *,
- struct exportinfo *, struct svc_req *, cred_t *);
-void *rfs_create_getfh(struct nfscreatargs *);
-void rfs_remove(struct nfsdiropargs *, enum nfsstat *, struct exportinfo *,
- struct svc_req *, cred_t *);
-void *rfs_remove_getfh(struct nfsdiropargs *);
-void rfs_rename(struct nfsrnmargs *, enum nfsstat *, struct exportinfo *,
- struct svc_req *, cred_t *);
-void *rfs_rename_getfh(struct nfsrnmargs *);
-void rfs_link(struct nfslinkargs *, enum nfsstat *, struct exportinfo *,
- struct svc_req *, cred_t *);
-void *rfs_link_getfh(struct nfslinkargs *);
-void rfs_symlink(struct nfsslargs *, enum nfsstat *, struct exportinfo *,
- struct svc_req *, cred_t *);
-void *rfs_symlink_getfh(struct nfsslargs *);
-void rfs_mkdir(struct nfscreatargs *, struct nfsdiropres *,
- struct exportinfo *, struct svc_req *, cred_t *);
-void *rfs_mkdir_getfh(struct nfscreatargs *);
-void rfs_rmdir(struct nfsdiropargs *, enum nfsstat *, struct exportinfo *,
- struct svc_req *, cred_t *);
-void *rfs_rmdir_getfh(struct nfsdiropargs *);
-void rfs_readdir(struct nfsrddirargs *, struct nfsrddirres *,
- struct exportinfo *, struct svc_req *, cred_t *);
-void *rfs_readdir_getfh(struct nfsrddirargs *);
-void rfs_rddirfree(struct nfsrddirres *);
-void rfs_statfs(fhandle_t *, struct nfsstatfs *, struct exportinfo *,
- struct svc_req *, cred_t *);
-void *rfs_statfs_getfh(fhandle_t *);
-void rfs_srvrinit(void);
-void rfs_srvrfini(void);
+extern void rfs_getattr(fhandle_t *, struct nfsattrstat *,
+ struct exportinfo *, struct svc_req *, cred_t *, bool_t);
+extern void *rfs_getattr_getfh(fhandle_t *);
+extern void rfs_setattr(struct nfssaargs *, struct nfsattrstat *,
+ struct exportinfo *, struct svc_req *, cred_t *, bool_t);
+extern void *rfs_setattr_getfh(struct nfssaargs *);
+extern void rfs_lookup(struct nfsdiropargs *, struct nfsdiropres *,
+ struct exportinfo *, struct svc_req *, cred_t *, bool_t);
+extern void *rfs_lookup_getfh(struct nfsdiropargs *);
+extern void rfs_readlink(fhandle_t *, struct nfsrdlnres *,
+ struct exportinfo *, struct svc_req *, cred_t *, bool_t);
+extern void *rfs_readlink_getfh(fhandle_t *);
+extern void rfs_rlfree(struct nfsrdlnres *);
+extern void rfs_read(struct nfsreadargs *, struct nfsrdresult *,
+ struct exportinfo *, struct svc_req *, cred_t *, bool_t);
+extern void *rfs_read_getfh(struct nfsreadargs *);
+extern void rfs_rdfree(struct nfsrdresult *);
+extern void rfs_write_sync(struct nfswriteargs *, struct nfsattrstat *,
+ struct exportinfo *, struct svc_req *, cred_t *, bool_t);
+extern void rfs_write(struct nfswriteargs *, struct nfsattrstat *,
+ struct exportinfo *, struct svc_req *, cred_t *, bool_t);
+extern void *rfs_write_getfh(struct nfswriteargs *);
+extern void rfs_create(struct nfscreatargs *, struct nfsdiropres *,
+ struct exportinfo *, struct svc_req *, cred_t *, bool_t);
+extern void *rfs_create_getfh(struct nfscreatargs *);
+extern void rfs_remove(struct nfsdiropargs *, enum nfsstat *,
+ struct exportinfo *, struct svc_req *, cred_t *, bool_t);
+extern void *rfs_remove_getfh(struct nfsdiropargs *);
+extern void rfs_rename(struct nfsrnmargs *, enum nfsstat *,
+ struct exportinfo *, struct svc_req *, cred_t *, bool_t);
+extern void *rfs_rename_getfh(struct nfsrnmargs *);
+extern void rfs_link(struct nfslinkargs *, enum nfsstat *,
+ struct exportinfo *, struct svc_req *, cred_t *, bool_t);
+extern void *rfs_link_getfh(struct nfslinkargs *);
+extern void rfs_symlink(struct nfsslargs *, enum nfsstat *,
+ struct exportinfo *, struct svc_req *, cred_t *, bool_t);
+extern void *rfs_symlink_getfh(struct nfsslargs *);
+extern void rfs_mkdir(struct nfscreatargs *, struct nfsdiropres *,
+ struct exportinfo *, struct svc_req *, cred_t *, bool_t);
+extern void *rfs_mkdir_getfh(struct nfscreatargs *);
+extern void rfs_rmdir(struct nfsdiropargs *, enum nfsstat *,
+ struct exportinfo *, struct svc_req *, cred_t *, bool_t);
+extern void *rfs_rmdir_getfh(struct nfsdiropargs *);
+extern void rfs_readdir(struct nfsrddirargs *, struct nfsrddirres *,
+ struct exportinfo *, struct svc_req *, cred_t *, bool_t);
+extern void *rfs_readdir_getfh(struct nfsrddirargs *);
+extern void rfs_rddirfree(struct nfsrddirres *);
+extern void rfs_statfs(fhandle_t *, struct nfsstatfs *, struct exportinfo *,
+ struct svc_req *, cred_t *, bool_t);
+extern void *rfs_statfs_getfh(fhandle_t *);
+extern void rfs_srvrinit(void);
+extern void rfs_srvrfini(void);
/*
* flags to define path types during Multi Component Lookups
@@ -885,69 +884,71 @@ void rfs_srvrfini(void);
enum nfs_svccounts {NFS_CALLS, NFS_BADCALLS, NFS_REFERRALS, NFS_REFERLINKS};
/* function defs for NFS kernel */
-int nfs_waitfor_purge_complete(vnode_t *);
-int nfs_validate_caches(vnode_t *, cred_t *);
-void nfs_purge_caches(vnode_t *, int, cred_t *);
-void nfs_purge_rddir_cache(vnode_t *);
-void nfs_attrcache(vnode_t *, struct nfsfattr *, hrtime_t);
-int nfs_cache_fattr(vnode_t *, struct nfsfattr *, vattr_t *, hrtime_t,
- cred_t *);
-void nfs_attr_cache(vnode_t *, vattr_t *, hrtime_t, cred_t *);
-void nfs_attrcache_va(vnode_t *, struct vattr *);
-int nfs_getattr_otw(vnode_t *, struct vattr *, cred_t *);
-int nfsgetattr(vnode_t *, struct vattr *, cred_t *);
-int nattr_to_vattr(vnode_t *, struct nfsfattr *, struct vattr *);
-void nfs_async_manager(struct vfs *);
-void nfs_async_manager_stop(struct vfs *);
-void nfs_async_stop(struct vfs *);
-int nfs_async_stop_sig(struct vfs *);
-int nfs_clntinit(void);
-void nfs_clntfini(void);
-int nfstsize(void);
-int nfs_srvinit(void);
-void nfs_srvfini(void);
-int vattr_to_sattr(struct vattr *, struct nfssattr *);
-void setdiropargs(struct nfsdiropargs *, char *, vnode_t *);
-int setdirgid(vnode_t *, gid_t *, cred_t *);
-int setdirmode(vnode_t *, mode_t *, cred_t *);
-int newnum(void);
-char *newname(void);
-int nfs_subrinit(void);
-void nfs_subrfini(void);
-enum nfsstat puterrno(int);
-int geterrno(enum nfsstat);
-int nfsinit(int, char *);
-void nfsfini(void);
-int nfs_vfsinit(void);
-void nfs_vfsfini(void);
-int nfs_dump(vnode_t *, caddr_t, offset_t, offset_t, caller_context_t *);
-void nfs_perror(int error, char *fmt, ...);
-void nfs_cmn_err(int error, int level, char *fmt, ...);
-int nfs_addcllock(vnode_t *vp, struct flock64 *bfp);
-void nfs_rmcllock(vnode_t *vp, struct flock64 *bfp);
-void nfs_lockrelease(vnode_t *vp, int flag, offset_t offset, cred_t *credp);
-int vattr_to_nattr(struct vattr *, struct nfsfattr *);
-int mount_root(char *, char *, int, struct nfs_args *, int *);
-void nfs_lockcompletion(vnode_t *vp, int cmd);
-void nfs_add_locking_id(vnode_t *, pid_t, int, char *, int);
-void nfs3copyfh(caddr_t, vnode_t *);
-void nfscopyfh(caddr_t, vnode_t *);
-int nfs3lookup(vnode_t *, char *, vnode_t **, struct pathname *, int,
- vnode_t *, cred_t *, int);
-int nfslookup(vnode_t *, char *, vnode_t **, struct pathname *, int,
+extern int nfs_waitfor_purge_complete(vnode_t *);
+extern int nfs_validate_caches(vnode_t *, cred_t *);
+extern void nfs_purge_caches(vnode_t *, int, cred_t *);
+extern void nfs_purge_rddir_cache(vnode_t *);
+extern void nfs_attrcache(vnode_t *, struct nfsfattr *, hrtime_t);
+extern int nfs_cache_fattr(vnode_t *, struct nfsfattr *, vattr_t *,
+ hrtime_t, cred_t *);
+extern void nfs_attr_cache(vnode_t *, vattr_t *, hrtime_t, cred_t *);
+extern void nfs_attrcache_va(vnode_t *, struct vattr *);
+extern int nfs_getattr_otw(vnode_t *, struct vattr *, cred_t *);
+extern int nfsgetattr(vnode_t *, struct vattr *, cred_t *);
+extern int nattr_to_vattr(vnode_t *, struct nfsfattr *, struct vattr *);
+extern void nfs_async_manager(struct vfs *);
+extern void nfs_async_manager_stop(struct vfs *);
+extern void nfs_async_stop(struct vfs *);
+extern int nfs_async_stop_sig(struct vfs *);
+extern int nfs_clntinit(void);
+extern void nfs_clntfini(void);
+extern int nfstsize(void);
+extern int nfs_srvinit(void);
+extern void nfs_srvfini(void);
+extern int vattr_to_sattr(struct vattr *, struct nfssattr *);
+extern void setdiropargs(struct nfsdiropargs *, char *, vnode_t *);
+extern int setdirgid(vnode_t *, gid_t *, cred_t *);
+extern int setdirmode(vnode_t *, mode_t *, cred_t *);
+extern int newnum(void);
+extern char *newname(void);
+extern int nfs_subrinit(void);
+extern void nfs_subrfini(void);
+extern enum nfsstat puterrno(int);
+extern int geterrno(enum nfsstat);
+extern int nfsinit(int, char *);
+extern void nfsfini(void);
+extern int nfs_vfsinit(void);
+extern void nfs_vfsfini(void);
+extern int nfs_dump(vnode_t *, caddr_t, offset_t, offset_t,
+ caller_context_t *);
+extern void nfs_perror(int, char *, ...);
+extern void nfs_cmn_err(int, int, char *, ...);
+extern int nfs_addcllock(vnode_t *, struct flock64 *);
+extern void nfs_rmcllock(vnode_t *, struct flock64 *);
+extern void nfs_lockrelease(vnode_t *, int, offset_t, cred_t *);
+extern int vattr_to_nattr(struct vattr *, struct nfsfattr *);
+extern int mount_root(char *, char *, int, struct nfs_args *, int *);
+extern void nfs_lockcompletion(vnode_t *, int);
+extern void nfs_add_locking_id(vnode_t *, pid_t, int, char *, int);
+extern void nfs3copyfh(caddr_t, vnode_t *);
+extern void nfscopyfh(caddr_t, vnode_t *);
+extern int nfs3lookup(vnode_t *, char *, vnode_t **, struct pathname *,
+ int, vnode_t *, cred_t *, int);
+extern int nfslookup(vnode_t *, char *, vnode_t **, struct pathname *, int,
vnode_t *, cred_t *, int);
-void sv_free(struct servinfo *);
-int nfsauth_access(struct exportinfo *exi, struct svc_req *req);
-void nfsauth_init();
-void nfsauth_fini();
-int nfs_setopts(vnode_t *vp, model_t model, struct nfs_args *args);
-int nfs_mount_label_policy(vfs_t *vfsp, struct netbuf *addr,
- struct knetconfig *knconf, cred_t *cr);
-boolean_t nfs_has_ctty(void);
-void nfs_srv_stop_all(void);
-void nfs_srv_quiesce_all(void);
-int rfs4_dss_setpaths(char *, size_t);
-int nfs_setmod_check(page_t *pp);
+extern void sv_free(struct servinfo *);
+extern int nfsauth_access(struct exportinfo *, struct svc_req *, cred_t *,
+ uid_t *, gid_t *);
+extern void nfsauth_init(void);
+extern void nfsauth_fini(void);
+extern int nfs_setopts(vnode_t *, model_t, struct nfs_args *);
+extern int nfs_mount_label_policy(vfs_t *, struct netbuf *,
+ struct knetconfig *, cred_t *);
+extern boolean_t nfs_has_ctty(void);
+extern void nfs_srv_stop_all(void);
+extern void nfs_srv_quiesce_all(void);
+extern int rfs4_dss_setpaths(char *, size_t);
+extern int nfs_setmod_check(page_t *);
extern time_t rfs4_lease_time;
extern time_t rfs4_grace_period;
@@ -996,8 +997,8 @@ extern zone_key_t nfsstat_zone_key;
/*
* Zone callback functions.
*/
-void *nfsstat_zone_init(zoneid_t);
-void nfsstat_zone_fini(zoneid_t, void *);
+extern void *nfsstat_zone_init(zoneid_t);
+extern void nfsstat_zone_fini(zoneid_t, void *);
#endif /* _KERNEL */
@@ -2092,82 +2093,82 @@ typedef struct COMMIT3res COMMIT3res;
#define NFSPROC3_COMMIT ((rpcproc_t)21)
#ifndef _KERNEL
-void *nfsproc3_null_3();
-GETATTR3res *nfsproc3_getattr_3();
-SETATTR3res *nfsproc3_setattr_3();
-LOOKUP3res *nfsproc3_lookup_3();
-ACCESS3res *nfsproc3_access_3();
-READLINK3res *nfsproc3_readlink_3();
-READ3res *nfsproc3_read_3();
-WRITE3res *nfsproc3_write_3();
-CREATE3res *nfsproc3_create_3();
-MKDIR3res *nfsproc3_mkdir_3();
-SYMLINK3res *nfsproc3_symlink_3();
-MKNOD3res *nfsproc3_mknod_3();
-REMOVE3res *nfsproc3_remove_3();
-RMDIR3res *nfsproc3_rmdir_3();
-RENAME3res *nfsproc3_rename_3();
-LINK3res *nfsproc3_link_3();
-READDIR3res *nfsproc3_readdir_3();
-READDIRPLUS3res *nfsproc3_readdirplus_3();
-FSSTAT3res *nfsproc3_fsstat_3();
-FSINFO3res *nfsproc3_fsinfo_3();
-PATHCONF3res *nfsproc3_pathconf_3();
-COMMIT3res *nfsproc3_commit_3();
+extern void *nfsproc3_null_3();
+extern GETATTR3res *nfsproc3_getattr_3();
+extern SETATTR3res *nfsproc3_setattr_3();
+extern LOOKUP3res *nfsproc3_lookup_3();
+extern ACCESS3res *nfsproc3_access_3();
+extern READLINK3res *nfsproc3_readlink_3();
+extern READ3res *nfsproc3_read_3();
+extern WRITE3res *nfsproc3_write_3();
+extern CREATE3res *nfsproc3_create_3();
+extern MKDIR3res *nfsproc3_mkdir_3();
+extern SYMLINK3res *nfsproc3_symlink_3();
+extern MKNOD3res *nfsproc3_mknod_3();
+extern REMOVE3res *nfsproc3_remove_3();
+extern RMDIR3res *nfsproc3_rmdir_3();
+extern RENAME3res *nfsproc3_rename_3();
+extern LINK3res *nfsproc3_link_3();
+extern READDIR3res *nfsproc3_readdir_3();
+extern READDIRPLUS3res *nfsproc3_readdirplus_3();
+extern FSSTAT3res *nfsproc3_fsstat_3();
+extern FSINFO3res *nfsproc3_fsinfo_3();
+extern PATHCONF3res *nfsproc3_pathconf_3();
+extern COMMIT3res *nfsproc3_commit_3();
#endif /* !_KERNEL */
#ifdef _KERNEL
/* the NFS Version 3 XDR functions */
-bool_t xdr_nfs_fh3(XDR *, nfs_fh3 *);
-bool_t xdr_nfslog_nfs_fh3(XDR *, nfs_fh3 *);
-bool_t xdr_nfs_fh3_server(XDR *, nfs_fh3 *);
-bool_t xdr_diropargs3(XDR *, diropargs3 *);
-bool_t xdr_post_op_attr(XDR *, post_op_attr *);
-bool_t xdr_post_op_fh3(XDR *, post_op_fh3 *);
-bool_t xdr_GETATTR3res(XDR *, GETATTR3res *);
-bool_t xdr_GETATTR3vres(XDR *, GETATTR3vres *);
-bool_t xdr_SETATTR3args(XDR *, SETATTR3args *);
-bool_t xdr_SETATTR3res(XDR *, SETATTR3res *);
-bool_t xdr_LOOKUP3res(XDR *, LOOKUP3res *);
-bool_t xdr_LOOKUP3vres(XDR *, LOOKUP3vres *);
-bool_t xdr_ACCESS3args(XDR *, ACCESS3args *);
-bool_t xdr_ACCESS3res(XDR *, ACCESS3res *);
-bool_t xdr_READLINK3args(XDR *, READLINK3args *);
-bool_t xdr_READLINK3res(XDR *, READLINK3res *);
-bool_t xdr_READ3args(XDR *, READ3args *);
-bool_t xdr_READ3res(XDR *, READ3res *);
-bool_t xdr_READ3vres(XDR *, READ3vres *);
-bool_t xdr_READ3uiores(XDR *, READ3uiores *);
-bool_t xdr_WRITE3args(XDR *, WRITE3args *);
-bool_t xdr_WRITE3res(XDR *, WRITE3res *);
-bool_t xdr_CREATE3args(XDR *, CREATE3args *);
-bool_t xdr_CREATE3res(XDR *, CREATE3res *);
-bool_t xdr_MKDIR3args(XDR *, MKDIR3args *);
-bool_t xdr_MKDIR3res(XDR *, MKDIR3res *);
-bool_t xdr_SYMLINK3args(XDR *, SYMLINK3args *);
-bool_t xdr_SYMLINK3res(XDR *, SYMLINK3res *);
-bool_t xdr_MKNOD3args(XDR *, MKNOD3args *);
-bool_t xdr_MKNOD3res(XDR *, MKNOD3res *);
-bool_t xdr_REMOVE3res(XDR *, REMOVE3res *);
-bool_t xdr_RMDIR3resfail(XDR *, RMDIR3resfail *);
-bool_t xdr_RMDIR3res(XDR *, RMDIR3res *);
-bool_t xdr_RENAME3args(XDR *, RENAME3args *);
-bool_t xdr_RENAME3res(XDR *, RENAME3res *);
-bool_t xdr_LINK3args(XDR *, LINK3args *);
-bool_t xdr_LINK3res(XDR *, LINK3res *);
-bool_t xdr_READDIR3args(XDR *, READDIR3args *);
-bool_t xdr_READDIR3res(XDR *, READDIR3res *);
-bool_t xdr_READDIR3vres(XDR *, READDIR3vres *);
-bool_t xdr_READDIRPLUS3args(XDR *, READDIRPLUS3args *);
-bool_t xdr_READDIRPLUS3res(XDR *, READDIRPLUS3res *);
-bool_t xdr_READDIRPLUS3vres(XDR *, READDIRPLUS3vres *);
-bool_t xdr_FSSTAT3res(XDR *, FSSTAT3res *);
-bool_t xdr_FSINFO3res(XDR *, FSINFO3res *);
-bool_t xdr_PATHCONF3res(XDR *, PATHCONF3res *);
-bool_t xdr_COMMIT3args(XDR *, COMMIT3args *);
-bool_t xdr_COMMIT3res(XDR *, COMMIT3res *);
-bool_t xdr_fastnfs_fh3(XDR *, nfs_fh3 **);
+extern bool_t xdr_nfs_fh3(XDR *, nfs_fh3 *);
+extern bool_t xdr_nfslog_nfs_fh3(XDR *, nfs_fh3 *);
+extern bool_t xdr_nfs_fh3_server(XDR *, nfs_fh3 *);
+extern bool_t xdr_diropargs3(XDR *, diropargs3 *);
+extern bool_t xdr_post_op_attr(XDR *, post_op_attr *);
+extern bool_t xdr_post_op_fh3(XDR *, post_op_fh3 *);
+extern bool_t xdr_GETATTR3res(XDR *, GETATTR3res *);
+extern bool_t xdr_GETATTR3vres(XDR *, GETATTR3vres *);
+extern bool_t xdr_SETATTR3args(XDR *, SETATTR3args *);
+extern bool_t xdr_SETATTR3res(XDR *, SETATTR3res *);
+extern bool_t xdr_LOOKUP3res(XDR *, LOOKUP3res *);
+extern bool_t xdr_LOOKUP3vres(XDR *, LOOKUP3vres *);
+extern bool_t xdr_ACCESS3args(XDR *, ACCESS3args *);
+extern bool_t xdr_ACCESS3res(XDR *, ACCESS3res *);
+extern bool_t xdr_READLINK3args(XDR *, READLINK3args *);
+extern bool_t xdr_READLINK3res(XDR *, READLINK3res *);
+extern bool_t xdr_READ3args(XDR *, READ3args *);
+extern bool_t xdr_READ3res(XDR *, READ3res *);
+extern bool_t xdr_READ3vres(XDR *, READ3vres *);
+extern bool_t xdr_READ3uiores(XDR *, READ3uiores *);
+extern bool_t xdr_WRITE3args(XDR *, WRITE3args *);
+extern bool_t xdr_WRITE3res(XDR *, WRITE3res *);
+extern bool_t xdr_CREATE3args(XDR *, CREATE3args *);
+extern bool_t xdr_CREATE3res(XDR *, CREATE3res *);
+extern bool_t xdr_MKDIR3args(XDR *, MKDIR3args *);
+extern bool_t xdr_MKDIR3res(XDR *, MKDIR3res *);
+extern bool_t xdr_SYMLINK3args(XDR *, SYMLINK3args *);
+extern bool_t xdr_SYMLINK3res(XDR *, SYMLINK3res *);
+extern bool_t xdr_MKNOD3args(XDR *, MKNOD3args *);
+extern bool_t xdr_MKNOD3res(XDR *, MKNOD3res *);
+extern bool_t xdr_REMOVE3res(XDR *, REMOVE3res *);
+extern bool_t xdr_RMDIR3resfail(XDR *, RMDIR3resfail *);
+extern bool_t xdr_RMDIR3res(XDR *, RMDIR3res *);
+extern bool_t xdr_RENAME3args(XDR *, RENAME3args *);
+extern bool_t xdr_RENAME3res(XDR *, RENAME3res *);
+extern bool_t xdr_LINK3args(XDR *, LINK3args *);
+extern bool_t xdr_LINK3res(XDR *, LINK3res *);
+extern bool_t xdr_READDIR3args(XDR *, READDIR3args *);
+extern bool_t xdr_READDIR3res(XDR *, READDIR3res *);
+extern bool_t xdr_READDIR3vres(XDR *, READDIR3vres *);
+extern bool_t xdr_READDIRPLUS3args(XDR *, READDIRPLUS3args *);
+extern bool_t xdr_READDIRPLUS3res(XDR *, READDIRPLUS3res *);
+extern bool_t xdr_READDIRPLUS3vres(XDR *, READDIRPLUS3vres *);
+extern bool_t xdr_FSSTAT3res(XDR *, FSSTAT3res *);
+extern bool_t xdr_FSINFO3res(XDR *, FSINFO3res *);
+extern bool_t xdr_PATHCONF3res(XDR *, PATHCONF3res *);
+extern bool_t xdr_COMMIT3args(XDR *, COMMIT3args *);
+extern bool_t xdr_COMMIT3res(XDR *, COMMIT3res *);
+extern bool_t xdr_fastnfs_fh3(XDR *, nfs_fh3 **);
/*
* The NFS Version 3 service procedures.
@@ -2177,102 +2178,105 @@ struct servinfo; /* defined in nfs/nfs_clnt.h */
struct mntinfo; /* defined in nfs/nfs_clnt.h */
struct sec_ol; /* defined in nfs/export.h */
-void rfs3_getattr(GETATTR3args *, GETATTR3res *, struct exportinfo *,
- struct svc_req *, cred_t *);
-void *rfs3_getattr_getfh(GETATTR3args *);
-void rfs3_setattr(SETATTR3args *, SETATTR3res *, struct exportinfo *,
- struct svc_req *, cred_t *);
-void *rfs3_setattr_getfh(SETATTR3args *);
-void rfs3_lookup(LOOKUP3args *, LOOKUP3res *, struct exportinfo *,
- struct svc_req *, cred_t *);
-void *rfs3_lookup_getfh(LOOKUP3args *);
-void rfs3_access(ACCESS3args *, ACCESS3res *, struct exportinfo *,
- struct svc_req *, cred_t *);
-void *rfs3_access_getfh(ACCESS3args *);
-void rfs3_readlink(READLINK3args *, READLINK3res *, struct exportinfo *,
- struct svc_req *, cred_t *);
-void *rfs3_readlink_getfh(READLINK3args *);
-void rfs3_readlink_free(READLINK3res *);
-void rfs3_read(READ3args *, READ3res *, struct exportinfo *,
- struct svc_req *, cred_t *);
-void *rfs3_read_getfh(READ3args *);
-void rfs3_read_free(READ3res *);
-void rfs3_write(WRITE3args *, WRITE3res *, struct exportinfo *,
- struct svc_req *, cred_t *);
-void *rfs3_write_getfh(WRITE3args *);
-void rfs3_create(CREATE3args *, CREATE3res *, struct exportinfo *,
- struct svc_req *, cred_t *);
-void *rfs3_create_getfh(CREATE3args *);
-void rfs3_mkdir(MKDIR3args *, MKDIR3res *, struct exportinfo *,
- struct svc_req *, cred_t *);
-void *rfs3_mkdir_getfh(MKDIR3args *);
-void rfs3_symlink(SYMLINK3args *, SYMLINK3res *, struct exportinfo *,
- struct svc_req *, cred_t *);
-void *rfs3_symlink_getfh(SYMLINK3args *);
-void rfs3_mknod(MKNOD3args *, MKNOD3res *, struct exportinfo *,
- struct svc_req *, cred_t *);
-void *rfs3_mknod_getfh(MKNOD3args *);
-void rfs3_remove(REMOVE3args *, REMOVE3res *, struct exportinfo *,
- struct svc_req *, cred_t *);
-void *rfs3_remove_getfh(REMOVE3args *);
-void rfs3_rmdir(RMDIR3args *, RMDIR3res *, struct exportinfo *,
- struct svc_req *, cred_t *);
-void *rfs3_rmdir_getfh(RMDIR3args *);
-void rfs3_rename(RENAME3args *, RENAME3res *, struct exportinfo *,
- struct svc_req *, cred_t *);
-void *rfs3_rename_getfh(RENAME3args *);
-void rfs3_link(LINK3args *, LINK3res *, struct exportinfo *,
- struct svc_req *, cred_t *);
-void *rfs3_link_getfh(LINK3args *);
-void rfs3_readdir(READDIR3args *, READDIR3res *, struct exportinfo *,
- struct svc_req *, cred_t *);
-void *rfs3_readdir_getfh(READDIR3args *);
-void rfs3_readdir_free(READDIR3res *);
-void rfs3_readdirplus(READDIRPLUS3args *, READDIRPLUS3res *,
- struct exportinfo *, struct svc_req *, cred_t *);
-void *rfs3_readdirplus_getfh(READDIRPLUS3args *);
-void rfs3_readdirplus_free(READDIRPLUS3res *);
-void rfs3_fsstat(FSSTAT3args *, FSSTAT3res *, struct exportinfo *,
- struct svc_req *, cred_t *);
-void *rfs3_fsstat_getfh(FSSTAT3args *);
-void rfs3_fsinfo(FSINFO3args *, FSINFO3res *, struct exportinfo *,
- struct svc_req *, cred_t *);
-void *rfs3_fsinfo_getfh(FSINFO3args *);
-void rfs3_pathconf(PATHCONF3args *, PATHCONF3res *, struct exportinfo *,
- struct svc_req *, cred_t *);
-void *rfs3_pathconf_getfh(PATHCONF3args *);
-void rfs3_commit(COMMIT3args *, COMMIT3res *, struct exportinfo *,
- struct svc_req *, cred_t *);
-void *rfs3_commit_getfh(COMMIT3args *);
-void rfs3_srvrinit(void);
-void rfs3_srvrfini(void);
-
-int nfs3_validate_caches(vnode_t *, cred_t *);
-void nfs3_cache_post_op_attr(vnode_t *, post_op_attr *, hrtime_t, cred_t *);
-void nfs3_cache_post_op_vattr(vnode_t *, post_op_vattr *, hrtime_t,
+extern void rfs3_getattr(GETATTR3args *, GETATTR3res *, struct exportinfo *,
+ struct svc_req *, cred_t *, bool_t);
+extern void *rfs3_getattr_getfh(GETATTR3args *);
+extern void rfs3_setattr(SETATTR3args *, SETATTR3res *, struct exportinfo *,
+ struct svc_req *, cred_t *, bool_t);
+extern void *rfs3_setattr_getfh(SETATTR3args *);
+extern void rfs3_lookup(LOOKUP3args *, LOOKUP3res *, struct exportinfo *,
+ struct svc_req *, cred_t *, bool_t);
+extern void *rfs3_lookup_getfh(LOOKUP3args *);
+extern void rfs3_access(ACCESS3args *, ACCESS3res *, struct exportinfo *,
+ struct svc_req *, cred_t *, bool_t);
+extern void *rfs3_access_getfh(ACCESS3args *);
+extern void rfs3_readlink(READLINK3args *, READLINK3res *,
+ struct exportinfo *, struct svc_req *, cred_t *, bool_t);
+extern void *rfs3_readlink_getfh(READLINK3args *);
+extern void rfs3_readlink_free(READLINK3res *);
+extern void rfs3_read(READ3args *, READ3res *, struct exportinfo *,
+ struct svc_req *, cred_t *, bool_t);
+extern void *rfs3_read_getfh(READ3args *);
+extern void rfs3_read_free(READ3res *);
+extern void rfs3_write(WRITE3args *, WRITE3res *, struct exportinfo *,
+ struct svc_req *, cred_t *, bool_t);
+extern void *rfs3_write_getfh(WRITE3args *);
+extern void rfs3_create(CREATE3args *, CREATE3res *, struct exportinfo *,
+ struct svc_req *, cred_t *, bool_t);
+extern void *rfs3_create_getfh(CREATE3args *);
+extern void rfs3_mkdir(MKDIR3args *, MKDIR3res *, struct exportinfo *,
+ struct svc_req *, cred_t *, bool_t);
+extern void *rfs3_mkdir_getfh(MKDIR3args *);
+extern void rfs3_symlink(SYMLINK3args *, SYMLINK3res *, struct exportinfo *,
+ struct svc_req *, cred_t *, bool_t);
+extern void *rfs3_symlink_getfh(SYMLINK3args *);
+extern void rfs3_mknod(MKNOD3args *, MKNOD3res *, struct exportinfo *,
+ struct svc_req *, cred_t *, bool_t);
+extern void *rfs3_mknod_getfh(MKNOD3args *);
+extern void rfs3_remove(REMOVE3args *, REMOVE3res *, struct exportinfo *,
+ struct svc_req *, cred_t *, bool_t);
+extern void *rfs3_remove_getfh(REMOVE3args *);
+extern void rfs3_rmdir(RMDIR3args *, RMDIR3res *, struct exportinfo *,
+ struct svc_req *, cred_t *, bool_t);
+extern void *rfs3_rmdir_getfh(RMDIR3args *);
+extern void rfs3_rename(RENAME3args *, RENAME3res *, struct exportinfo *,
+ struct svc_req *, cred_t *, bool_t);
+extern void *rfs3_rename_getfh(RENAME3args *);
+extern void rfs3_link(LINK3args *, LINK3res *, struct exportinfo *,
+ struct svc_req *, cred_t *, bool_t);
+extern void *rfs3_link_getfh(LINK3args *);
+extern void rfs3_readdir(READDIR3args *, READDIR3res *, struct exportinfo *,
+ struct svc_req *, cred_t *, bool_t);
+extern void *rfs3_readdir_getfh(READDIR3args *);
+extern void rfs3_readdir_free(READDIR3res *);
+extern void rfs3_readdirplus(READDIRPLUS3args *, READDIRPLUS3res *,
+ struct exportinfo *, struct svc_req *, cred_t *, bool_t);
+extern void *rfs3_readdirplus_getfh(READDIRPLUS3args *);
+extern void rfs3_readdirplus_free(READDIRPLUS3res *);
+extern void rfs3_fsstat(FSSTAT3args *, FSSTAT3res *, struct exportinfo *,
+ struct svc_req *, cred_t *, bool_t);
+extern void *rfs3_fsstat_getfh(FSSTAT3args *);
+extern void rfs3_fsinfo(FSINFO3args *, FSINFO3res *, struct exportinfo *,
+ struct svc_req *, cred_t *, bool_t);
+extern void *rfs3_fsinfo_getfh(FSINFO3args *);
+extern void rfs3_pathconf(PATHCONF3args *, PATHCONF3res *,
+ struct exportinfo *, struct svc_req *, cred_t *, bool_t);
+extern void *rfs3_pathconf_getfh(PATHCONF3args *);
+extern void rfs3_commit(COMMIT3args *, COMMIT3res *, struct exportinfo *,
+ struct svc_req *, cred_t *, bool_t);
+extern void *rfs3_commit_getfh(COMMIT3args *);
+extern void rfs3_srvrinit(void);
+extern void rfs3_srvrfini(void);
+
+extern int nfs3_validate_caches(vnode_t *, cred_t *);
+extern void nfs3_cache_post_op_attr(vnode_t *, post_op_attr *, hrtime_t,
+ cred_t *);
+extern void nfs3_cache_post_op_vattr(vnode_t *, post_op_vattr *, hrtime_t,
+ cred_t *);
+extern void nfs3_cache_wcc_data(vnode_t *, wcc_data *, hrtime_t, cred_t *);
+extern void nfs3_attrcache(vnode_t *, fattr3 *, hrtime_t);
+extern int nfs3_cache_fattr3(vnode_t *, fattr3 *, vattr_t *, hrtime_t,
cred_t *);
-void nfs3_cache_wcc_data(vnode_t *, wcc_data *, hrtime_t, cred_t *);
-void nfs3_attrcache(vnode_t *, fattr3 *, hrtime_t);
-int nfs3_cache_fattr3(vnode_t *, fattr3 *, vattr_t *, hrtime_t, cred_t *);
-int nfs3_getattr_otw(vnode_t *, struct vattr *, cred_t *);
-int nfs3getattr(vnode_t *, struct vattr *, cred_t *);
-int fattr3_to_vattr(vnode_t *, fattr3 *, struct vattr *);
-int nfs3tsize(void);
-uint_t nfs3_tsize(struct knetconfig *);
-uint_t rfs3_tsize(struct svc_req *);
-int vattr_to_sattr3(struct vattr *, sattr3 *);
-void setdiropargs3(diropargs3 *, char *, vnode_t *);
-enum nfsstat3 puterrno3(int);
-int geterrno3(enum nfsstat3);
-int nfs3init(int, char *);
-void nfs3fini(void);
-int nfs3_vfsinit(void);
-void nfs3_vfsfini(void);
-void vattr_to_post_op_attr(struct vattr *, post_op_attr *);
-void mblk_to_iov(mblk_t *, int, struct iovec *);
-int rfs_publicfh_mclookup(char *, vnode_t *, cred_t *, vnode_t **,
+extern int nfs3_getattr_otw(vnode_t *, struct vattr *, cred_t *);
+extern int nfs3getattr(vnode_t *, struct vattr *, cred_t *);
+extern int fattr3_to_vattr(vnode_t *, fattr3 *, struct vattr *);
+extern int nfs3tsize(void);
+extern uint_t nfs3_tsize(struct knetconfig *);
+extern uint_t rfs3_tsize(struct svc_req *);
+extern int vattr_to_sattr3(struct vattr *, sattr3 *);
+extern void setdiropargs3(diropargs3 *, char *, vnode_t *);
+extern enum nfsstat3 puterrno3(int);
+extern int geterrno3(enum nfsstat3);
+extern int nfs3init(int, char *);
+extern void nfs3fini(void);
+extern int nfs3_vfsinit(void);
+extern void nfs3_vfsfini(void);
+extern void vattr_to_post_op_attr(struct vattr *, post_op_attr *);
+extern void mblk_to_iov(mblk_t *, int, struct iovec *);
+extern int rfs_publicfh_mclookup(char *, vnode_t *, cred_t *, vnode_t **,
struct exportinfo **, struct sec_ol *);
-int rfs_pathname(char *, vnode_t **, vnode_t **, vnode_t *, cred_t *, int);
+extern int rfs_pathname(char *, vnode_t **, vnode_t **, vnode_t *,
+ cred_t *, int);
extern vtype_t nf3_to_vt[];
extern kstat_named_t *rfsproccnt_v3_ptr;
@@ -2291,27 +2295,28 @@ extern int nfs_disable_rddir_cache;
/*
* External functions called by the v2/v3 code into the v4 code
*/
-void nfs4_clnt_init(void);
-void nfs4_clnt_fini(void);
+extern void nfs4_clnt_init(void);
+extern void nfs4_clnt_fini(void);
/*
* Does NFS4 server have a vnode delegated? TRUE if so, FALSE if not.
*/
-bool_t rfs4_check_delegated(int mode, vnode_t *, bool_t trunc);
+extern bool_t rfs4_check_delegated(int mode, vnode_t *, bool_t trunc);
/*
* VOP_GETATTR call. If a NFS4 delegation is present on the supplied vnode
* call back to the delegated client to get attributes for AT_MTIME and
* AT_SIZE. Invoke VOP_GETATTR to get all other attributes or all attributes
* if no delegation is present.
*/
-int rfs4_delegated_getattr(vnode_t *, vattr_t *, int, cred_t *);
-void rfs4_hold_deleg_policy(void);
-void rfs4_rele_deleg_policy(void);
+extern int rfs4_delegated_getattr(vnode_t *, vattr_t *, int, cred_t *);
+extern void rfs4_hold_deleg_policy(void);
+extern void rfs4_rele_deleg_policy(void);
-int do_xattr_exists_check(vnode_t *, ulong_t *, cred_t *);
+extern int do_xattr_exists_check(vnode_t *, ulong_t *, cred_t *);
-ts_label_t *nfs_getflabel(vnode_t *, struct exportinfo *);
-boolean_t do_rfs_label_check(bslabel_t *, vnode_t *, int, struct exportinfo *);
+extern ts_label_t *nfs_getflabel(vnode_t *, struct exportinfo *);
+extern boolean_t do_rfs_label_check(bslabel_t *, vnode_t *, int,
+ struct exportinfo *);
/*
* Copy Reduction support.
@@ -2325,11 +2330,11 @@ typedef struct nfs_xuio {
frtn_t nu_frtn;
} nfs_xuio_t;
-xuio_t *rfs_setup_xuio(vnode_t *);
-mblk_t *uio_to_mblk(uio_t *);
-mblk_t *rfs_read_alloc(uint_t, struct iovec **, int *);
-void rfs_rndup_mblks(mblk_t *, uint_t, int);
-void rfs_free_xuio(void *);
+extern xuio_t *rfs_setup_xuio(vnode_t *);
+extern mblk_t *uio_to_mblk(uio_t *);
+extern mblk_t *rfs_read_alloc(uint_t, struct iovec **, int *);
+extern void rfs_rndup_mblks(mblk_t *, uint_t, int);
+extern void rfs_free_xuio(void *);
#endif /* _KERNEL */
diff --git a/usr/src/uts/common/nfs/nfs_acl.h b/usr/src/uts/common/nfs/nfs_acl.h
index 8f0be8d15b..a9dd2e3635 100644
--- a/usr/src/uts/common/nfs/nfs_acl.h
+++ b/usr/src/uts/common/nfs/nfs_acl.h
@@ -23,12 +23,13 @@
* All rights reserved.
* Use is subject to license terms.
*/
+/*
+ * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
+ */
#ifndef _NFS_NFS_ACL_H
#define _NFS_NFS_ACL_H
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#ifdef __cplusplus
extern "C" {
#endif
@@ -328,31 +329,31 @@ extern bool_t xdr_GETXATTRDIR3res(XDR *, GETXATTRDIR3res *);
#ifdef _KERNEL
/* the service procedures */
extern void acl2_getacl(GETACL2args *, GETACL2res *,
- struct exportinfo *, struct svc_req *, cred_t *);
+ struct exportinfo *, struct svc_req *, cred_t *, bool_t);
extern void *acl2_getacl_getfh(GETACL2args *);
extern void acl2_getacl_free(GETACL2res *);
extern void acl2_setacl(SETACL2args *, SETACL2res *,
- struct exportinfo *, struct svc_req *, cred_t *);
+ struct exportinfo *, struct svc_req *, cred_t *, bool_t);
extern void *acl2_setacl_getfh(SETACL2args *);
extern void acl2_getattr(GETATTR2args *, GETATTR2res *,
- struct exportinfo *, struct svc_req *, cred_t *);
+ struct exportinfo *, struct svc_req *, cred_t *, bool_t);
extern void *acl2_getattr_getfh(GETATTR2args *);
extern void acl2_access(ACCESS2args *, ACCESS2res *,
- struct exportinfo *, struct svc_req *, cred_t *);
+ struct exportinfo *, struct svc_req *, cred_t *, bool_t);
extern void *acl2_access_getfh(ACCESS2args *);
extern void acl2_getxattrdir(GETXATTRDIR2args *, GETXATTRDIR2res *,
- struct exportinfo *, struct svc_req *, cred_t *);
+ struct exportinfo *, struct svc_req *, cred_t *, bool_t);
extern void *acl2_getxattrdir_getfh(GETXATTRDIR2args *);
extern void acl3_getacl(GETACL3args *, GETACL3res *,
- struct exportinfo *, struct svc_req *, cred_t *);
+ struct exportinfo *, struct svc_req *, cred_t *, bool_t);
extern void *acl3_getacl_getfh(GETACL3args *);
extern void acl3_getacl_free(GETACL3res *);
extern void acl3_setacl(SETACL3args *, SETACL3res *,
- struct exportinfo *, struct svc_req *, cred_t *);
+ struct exportinfo *, struct svc_req *, cred_t *, bool_t);
extern void *acl3_setacl_getfh(SETACL3args *);
extern void acl3_getxattrdir(GETXATTRDIR3args *, GETXATTRDIR3res *,
- struct exportinfo *, struct svc_req *, cred_t *);
+ struct exportinfo *, struct svc_req *, cred_t *, bool_t);
extern void *acl3_getxattrdir_getfh(GETXATTRDIR3args *);
#endif
diff --git a/usr/src/uts/common/nfs/nfs_dispatch.h b/usr/src/uts/common/nfs/nfs_dispatch.h
index 00db2d1059..16475fea47 100644
--- a/usr/src/uts/common/nfs/nfs_dispatch.h
+++ b/usr/src/uts/common/nfs/nfs_dispatch.h
@@ -23,6 +23,9 @@
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
+/*
+ * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
+ */
/*
* Copyright (c) 1983,1984,1985,1986,1987,1988,1989 AT&T.
@@ -34,8 +37,6 @@
#ifndef _NFS_DISPATCH_H
#define _NFS_DISPATCH_H
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#ifdef __cplusplus
extern "C" {
#endif
@@ -61,7 +62,7 @@ typedef struct rpcdisp {
#define RPC_IDEMPOTENT 0x1 /* idempotent or not */
/*
* Be very careful about which NFS procedures get the RPC_ALLOWANON bit.
- * Right now, it this bit is on, we ignore the results of per NFS request
+ * Right now, if this bit is on, we ignore the results of per NFS request
* access control.
*/
#define RPC_ALLOWANON 0x2 /* allow anonymous access */
@@ -76,7 +77,8 @@ typedef struct rpc_disptable {
struct rpcdisp *dis_table;
} rpc_disptable_t;
-void rpc_null(caddr_t *, caddr_t *);
+void rpc_null(caddr_t *, caddr_t *, struct exportinfo *, struct svc_req *,
+ cred_t *, bool_t);
#ifdef __cplusplus
}