summaryrefslogtreecommitdiff
path: root/usr/src/lib/libshare
diff options
context:
space:
mode:
authormarks <none@none>2007-06-26 07:44:24 -0700
committermarks <none@none>2007-06-26 07:44:24 -0700
commitecd6cf800b63704be73fb264c3f5b6e0dafc068d (patch)
treeec83d040bc56ee0a46e9533a645e832e58d8ba86 /usr/src/lib/libshare
parent8ac1b93fdff76ea81638299d410b2d474240ee2b (diff)
downloadillumos-joyent-ecd6cf800b63704be73fb264c3f5b6e0dafc068d.tar.gz
PSARC/2006/465 ZFS Delegated Administration
PSARC/2006/577 zpool property to disable delegation PSARC/2006/625 Enhancements to zpool history PSARC/2007/228 ZFS delegation amendments PSARC/2007/295 ZFS Delegated Administration Addendum 6280676 restore "owner" property 6349470 investigate non-root restore/backup 6572465 'zpool set bootfs=...' records history as 'zfs set bootfs=...'
Diffstat (limited to 'usr/src/lib/libshare')
-rw-r--r--usr/src/lib/libshare/common/libshare.c4
-rw-r--r--usr/src/lib/libshare/common/libshare.h2
-rw-r--r--usr/src/lib/libshare/common/libshare_impl.h11
-rw-r--r--usr/src/lib/libshare/common/libshare_zfs.c75
-rw-r--r--usr/src/lib/libshare/common/libsharecore.c16
-rw-r--r--usr/src/lib/libshare/common/mapfile-vers4
-rw-r--r--usr/src/lib/libshare/common/plugin.c4
-rw-r--r--usr/src/lib/libshare/nfs/libshare_nfs.c105
8 files changed, 189 insertions, 32 deletions
diff --git a/usr/src/lib/libshare/common/libshare.c b/usr/src/lib/libshare/common/libshare.c
index 6809ab92cf..25213e97a4 100644
--- a/usr/src/lib/libshare/common/libshare.c
+++ b/usr/src/lib/libshare/common/libshare.c
@@ -1367,10 +1367,10 @@ sa_disable_share(sa_share_t share, char *protocol)
shared = sa_get_share_attr(share, "shared");
if (protocol != NULL) {
- ret = sa_proto_unshare(protocol, path);
+ ret = sa_proto_unshare(share, protocol, path);
} else {
/* need to do all protocols */
- ret = sa_proto_unshare("nfs", path);
+ ret = sa_proto_unshare(share, "nfs", path);
}
if (ret == SA_OK)
(void) sa_set_share_attr(share, "shared", NULL);
diff --git a/usr/src/lib/libshare/common/libshare.h b/usr/src/lib/libshare/common/libshare.h
index 754ef61c69..c78b0822c6 100644
--- a/usr/src/lib/libshare/common/libshare.h
+++ b/usr/src/lib/libshare/common/libshare.h
@@ -216,7 +216,7 @@ extern int sa_delete_sharetab(char *, char *);
/* ZFS functions */
extern int sa_zfs_is_shared(sa_handle_t, char *);
extern int sa_group_is_zfs(sa_group_t);
-
+extern int sa_path_is_zfs(char *);
/* SA Handle specific functions */
extern sa_handle_t sa_find_group_handle(sa_group_t);
diff --git a/usr/src/lib/libshare/common/libshare_impl.h b/usr/src/lib/libshare/common/libshare_impl.h
index 2eef7559c9..a428110a81 100644
--- a/usr/src/lib/libshare/common/libshare_impl.h
+++ b/usr/src/lib/libshare/common/libshare_impl.h
@@ -38,6 +38,8 @@
#include <libscf.h>
#include <scfutil.h>
#include <libzfs.h>
+#include <sharefs/share.h>
+#include "sharetab.h"
#ifdef __cplusplus
extern "C" {
@@ -58,7 +60,7 @@ struct sa_plugin_ops {
int (*sa_init)();
void (*sa_fini)();
int (*sa_share)(sa_share_t); /* start sharing */
- int (*sa_unshare)(char *); /* stop sharing */
+ int (*sa_unshare)(sa_share_t, char *); /* stop sharing */
int (*sa_valid_prop)(sa_property_t, sa_optionset_t);
int (*sa_valid_space)(char *); /* is name valid optionspace? */
int (*sa_security_prop)(char *); /* property is security */
@@ -91,7 +93,7 @@ typedef struct propertylist {
} property_list_t;
extern int sa_proto_share(char *, sa_share_t);
-extern int sa_proto_unshare(char *, char *);
+extern int sa_proto_unshare(sa_share_t, char *, char *);
extern int sa_proto_valid_prop(char *, sa_property_t, sa_optionset_t);
extern int sa_proto_security_prop(char *, char *);
extern int sa_proto_legacy_opts(char *, sa_group_t, char *);
@@ -113,10 +115,15 @@ extern int sa_delete_share(scfutilhandle_t *, sa_group_t, sa_share_t);
extern int sa_delete_instance(scfutilhandle_t *, char *);
extern int sa_create_pgroup(scfutilhandle_t *, char *);
extern int sa_delete_pgroup(scfutilhandle_t *, char *);
+extern void sa_fillshare(sa_share_t share, char *proto, struct share *sh);
+extern void sa_emptyshare(struct share *sh);
/* ZFS functions */
extern int sa_get_zfs_shares(sa_handle_t, char *);
extern int sa_zfs_update(sa_share_t);
+extern int sa_share_zfs(sa_share_t, char *, share_t *, void *, boolean_t);
+extern int sa_sharetab_fill_zfs(sa_share_t share, struct share *sh,
+ char *proto);
/* plugin specific functions */
extern int proto_plugin_init();
diff --git a/usr/src/lib/libshare/common/libshare_zfs.c b/usr/src/lib/libshare/common/libshare_zfs.c
index b7ac6c0d74..8beb621524 100644
--- a/usr/src/lib/libshare/common/libshare_zfs.c
+++ b/usr/src/lib/libshare/common/libshare_zfs.c
@@ -254,7 +254,7 @@ get_zfs_dataset(sa_handle_impl_t impl_handle, char *path)
/* canmount must be set */
canmount[0] = '\0';
- if (!zfs_prop_get(zlist[i], ZFS_PROP_CANMOUNT, canmount,
+ if (zfs_prop_get(zlist[i], ZFS_PROP_CANMOUNT, canmount,
sizeof (canmount), NULL, NULL, 0, B_FALSE) != 0 ||
strcmp(canmount, "off") == 0)
continue;
@@ -914,3 +914,76 @@ sa_path_is_zfs(char *path)
sa_free_fstype(fstype);
return (ret);
}
+
+int
+sa_sharetab_fill_zfs(sa_share_t share, share_t *sh, char *proto)
+{
+ char *path;
+
+ path = sa_get_share_attr(share, "path");
+ if (path != NULL) {
+ (void) memset(sh, 0, sizeof (sh));
+ (void) sa_fillshare(share, proto, sh);
+ return (0);
+ } else
+ return (1);
+}
+
+#define SMAX(i, j) \
+ if ((j) > (i)) { \
+ (i) = (j); \
+ }
+
+int
+sa_share_zfs(sa_share_t share, char *path, share_t *sh,
+ void *exportdata, boolean_t on)
+{
+ libzfs_handle_t *libhandle;
+ sa_group_t group;
+ sa_handle_t sahandle;
+ char *dataset;
+ int err = EINVAL;
+ int i, j;
+
+ /*
+ * First find the dataset name
+ */
+ if ((group = sa_get_parent_group(share)) == NULL) {
+ return (SA_SYSTEM_ERR);
+ }
+ if ((sahandle = sa_find_group_handle(group)) == NULL) {
+ return (SA_SYSTEM_ERR);
+ }
+
+ if ((dataset = get_zfs_dataset(sahandle, path)) == NULL) {
+ return (SA_SYSTEM_ERR);
+ }
+
+ libhandle = libzfs_init();
+ if (libhandle != NULL) {
+
+ i = (sh->sh_path ? strlen(sh->sh_path) : 0);
+ sh->sh_size = i;
+
+ j = (sh->sh_res ? strlen(sh->sh_res) : 0);
+ sh->sh_size += j;
+ SMAX(i, j);
+
+ j = (sh->sh_fstype ? strlen(sh->sh_fstype) : 0);
+ sh->sh_size += j;
+ SMAX(i, j);
+
+ j = (sh->sh_opts ? strlen(sh->sh_opts) : 0);
+ sh->sh_size += j;
+ SMAX(i, j);
+
+ j = (sh->sh_descr ? strlen(sh->sh_descr) : 0);
+ sh->sh_size += j;
+ SMAX(i, j);
+ err = zfs_deleg_share_nfs(libhandle, dataset, path,
+ exportdata, sh, i, on);
+ libzfs_fini(libhandle);
+ }
+ free(dataset);
+ return (err);
+}
diff --git a/usr/src/lib/libshare/common/libsharecore.c b/usr/src/lib/libshare/common/libsharecore.c
index d3bf9f4f6d..cbef53feab 100644
--- a/usr/src/lib/libshare/common/libsharecore.c
+++ b/usr/src/lib/libshare/common/libsharecore.c
@@ -1832,12 +1832,12 @@ sa_free_derived_security(sa_security_t security)
*/
/*
- * fillshare(share, proto, sh)
+ * sa_fillshare(share, proto, sh)
*
* Fill the struct share with values obtained from the share object.
*/
-static void
-fillshare(sa_share_t share, char *proto, struct share *sh)
+void
+sa_fillshare(sa_share_t share, char *proto, struct share *sh)
{
char *groupname = NULL;
char *value;
@@ -1916,13 +1916,13 @@ fillshare(sa_share_t share, char *proto, struct share *sh)
}
/*
- * emptyshare(sh)
+ * sa_emptyshare(sh)
*
* Free the strings in the non-NULL members of sh.
*/
-static void
-emptyshare(struct share *sh)
+void
+sa_emptyshare(struct share *sh)
{
if (sh->sh_path != NULL)
free(sh->sh_path);
@@ -1962,9 +1962,9 @@ sa_update_sharetab(sa_share_t share, char *proto)
/*
* Fill in share structure and send it to the kernel.
*/
- (void) fillshare(share, proto, &sh);
+ (void) sa_fillshare(share, proto, &sh);
(void) sharefs(SHAREFS_ADD, &sh);
- emptyshare(&sh);
+ sa_emptyshare(&sh);
sa_free_attr_string(path);
}
diff --git a/usr/src/lib/libshare/common/mapfile-vers b/usr/src/lib/libshare/common/mapfile-vers
index eb71ae23fb..317623b3b4 100644
--- a/usr/src/lib/libshare/common/mapfile-vers
+++ b/usr/src/lib/libshare/common/mapfile-vers
@@ -62,10 +62,14 @@ SUNWprivate {
sa_commit_properties;
sa_parse_legacy_options;
sa_zfs_is_shared;
+ sa_share_zfs;
+ sa_path_is_zfs;
sa_get_derived_optionset;
sa_move_share;
sa_group_is_zfs;
sa_update_config;
+ sa_sharetab_fill_zfs;
+ sa_emptyshare;
sa_get_share_attr;
sa_create_optionset;
sa_valid_property;
diff --git a/usr/src/lib/libshare/common/plugin.c b/usr/src/lib/libshare/common/plugin.c
index ab682e6f10..83bc4d5d94 100644
--- a/usr/src/lib/libshare/common/plugin.c
+++ b/usr/src/lib/libshare/common/plugin.c
@@ -240,13 +240,13 @@ sa_proto_share(char *proto, sa_share_t share)
*/
int
-sa_proto_unshare(char *proto, char *path)
+sa_proto_unshare(sa_share_t share, char *proto, char *path)
{
struct sa_plugin_ops *ops = find_protocol(proto);
int ret = SA_INVALID_PROTOCOL;
if (ops != NULL && ops->sa_unshare != NULL)
- ret = ops->sa_unshare(path);
+ ret = ops->sa_unshare(share, path);
return (ret);
}
diff --git a/usr/src/lib/libshare/nfs/libshare_nfs.c b/usr/src/lib/libshare/nfs/libshare_nfs.c
index f7b8e8ecba..ec25f19efe 100644
--- a/usr/src/lib/libshare/nfs/libshare_nfs.c
+++ b/usr/src/lib/libshare/nfs/libshare_nfs.c
@@ -49,6 +49,7 @@
#include "libshare_nfs.h"
#include <rpcsvc/daemon_utils.h>
#include <nfs/nfs.h>
+#include <nfs/nfssys.h>
/* should really be in some global place */
#define DEF_WIN 30000
@@ -56,12 +57,13 @@
int debug = 0;
+#define NFS_SERVER_SVC "svc:/network/nfs/server:default"
/* internal functions */
static int nfs_init();
static void nfs_fini();
static int nfs_enable_share(sa_share_t);
-static int nfs_disable_share(char *);
+static int nfs_disable_share(sa_share_t, char *);
static int nfs_validate_property(sa_property_t, sa_optionset_t);
static int nfs_validate_security_mode(char *);
static int nfs_is_security_opt(char *);
@@ -1616,6 +1618,7 @@ nfs_enable_share(sa_share_t share)
char *path;
int err = SA_OK;
int i;
+ int iszfs;
/* Don't drop core if the NFS module isn't loaded. */
(void) signal(SIGSYS, SIG_IGN);
@@ -1625,6 +1628,7 @@ nfs_enable_share(sa_share_t share)
if (path == NULL)
return (SA_NO_SUCH_PATH);
+ iszfs = sa_path_is_zfs(path);
/*
* find the optionsets and security sets. There may not be
* any or there could be one or two for each of optionset and
@@ -1741,18 +1745,67 @@ nfs_enable_share(sa_share_t share)
* call the exportfs system call which is implemented
* via the nfssys() call as the EXPORTFS subfunction.
*/
- if ((err = exportfs(path, &export)) < 0) {
+ if (iszfs) {
+ struct exportfs_args ea;
+ share_t sh;
+ char *str;
+ priv_set_t *priv_effective;
+ int privileged;
+
+ /*
+ * If we aren't a privileged user
+ * and NFS server service isn't running
+ * then print out an error message
+ * and return EPERM
+ */
+
+ priv_effective = priv_allocset();
+ (void) getppriv(PRIV_EFFECTIVE, priv_effective);
+
+ privileged = (priv_isfullset(priv_effective) == B_TRUE);
+ priv_freeset(priv_effective);
+
+ if (!privileged &&
+ (str = smf_get_state(NFS_SERVER_SVC)) != NULL) {
+ err = 0;
+ if (strcmp(str, SCF_STATE_STRING_ONLINE) != 0) {
+ (void) printf(dgettext(TEXT_DOMAIN,
+ "NFS: Cannot share remote "
+ "filesystem: %s\n"), path);
+ (void) printf(dgettext(TEXT_DOMAIN,
+ "NFS: Service needs to be enabled "
+ "by a privileged user\n"));
+ err = SA_SYSTEM_ERR;
+ errno = EPERM;
+ }
+ free(str);
+ }
+
+ if (err == 0) {
+ ea.dname = path;
+ ea.uex = &export;
+
+ sa_sharetab_fill_zfs(share, &sh, "nfs");
+ err = sa_share_zfs(share, path, &sh, &ea, B_TRUE);
+ sa_emptyshare(&sh);
+ }
+ } else {
+ err = exportfs(path, &export);
+ }
+
+ if (err < 0) {
err = SA_SYSTEM_ERR;
switch (errno) {
case EREMOTE:
(void) printf(dgettext(TEXT_DOMAIN,
- "NFS: Cannot share remote "
- "filesystem: %s\n"), path);
+ "NFS: Cannot share filesystems "
+ "in non-global zones: %s\n"), path);
+ err = SA_NOT_SUPPORTED;
break;
case EPERM:
if (getzoneid() != GLOBAL_ZONEID) {
(void) printf(dgettext(TEXT_DOMAIN,
- "NFS: Cannot share filesystems "
+ "NFS: Cannot share file systems "
"in non-global zones: %s\n"), path);
err = SA_NOT_SUPPORTED;
break;
@@ -1764,7 +1817,9 @@ nfs_enable_share(sa_share_t share)
}
} else {
/* update sharetab with an add/modify */
- (void) sa_update_sharetab(share, "nfs");
+ if (!iszfs) {
+ (void) sa_update_sharetab(share, "nfs");
+ }
}
if (err == SA_OK) {
@@ -1817,38 +1872,56 @@ out:
* done? We only do basic errors for now.
*/
static int
-nfs_disable_share(char *share)
+nfs_disable_share(sa_share_t share, char *path)
{
int err;
int ret = SA_OK;
+ int iszfs;
+
+
+ if (path != NULL) {
+ iszfs = sa_path_is_zfs(path);
+
+ if (iszfs) {
+ struct exportfs_args ea;
+ share_t sh = { 0 };
+
+ ea.dname = path;
+ ea.uex = NULL;
+ sh.sh_path = path;
+ sh.sh_fstype = "nfs";
- if (share != NULL) {
- err = exportfs(share, NULL);
+ err = sa_share_zfs(share, path, &sh, &ea, B_FALSE);
+ } else
+ err = exportfs(path, NULL);
if (err < 0) {
/*
- * TBD: only an error in some cases - need
- * better analysis
+ * TBD: only an error in some
+ * cases - need better analysis
*/
+
switch (errno) {
case EPERM:
case EACCES:
ret = SA_NO_PERMISSION;
- if (getzoneid() != GLOBAL_ZONEID)
+ if (getzoneid() != GLOBAL_ZONEID) {
ret = SA_NOT_SUPPORTED;
+ }
break;
case EINVAL:
case ENOENT:
ret = SA_NO_SUCH_PATH;
- break;
+ break;
default:
ret = SA_SYSTEM_ERR;
- break;
+ break;
}
}
if (ret == SA_OK || ret == SA_NO_SUCH_PATH) {
- (void) sa_delete_sharetab(share, "nfs");
+ if (!iszfs)
+ (void) sa_delete_sharetab(path, "nfs");
/* just in case it was logged */
- (void) nfslogtab_deactivate(share);
+ (void) nfslogtab_deactivate(path);
}
}
return (ret);