libshare_smb.c revision 5f1ef25c7a11451cbd3080dc3ce8e8db4ca996c4
a237e38e9161f0acd6451439d4a7dd597e66291dth * CDDL HEADER START
a237e38e9161f0acd6451439d4a7dd597e66291dth * The contents of this file are subject to the terms of the
a237e38e9161f0acd6451439d4a7dd597e66291dth * Common Development and Distribution License (the "License").
a237e38e9161f0acd6451439d4a7dd597e66291dth * You may not use this file except in compliance with the License.
a237e38e9161f0acd6451439d4a7dd597e66291dth * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
a237e38e9161f0acd6451439d4a7dd597e66291dth * See the License for the specific language governing permissions
a237e38e9161f0acd6451439d4a7dd597e66291dth * and limitations under the License.
a237e38e9161f0acd6451439d4a7dd597e66291dth * When distributing Covered Code, include this CDDL HEADER in each
a237e38e9161f0acd6451439d4a7dd597e66291dth * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
a237e38e9161f0acd6451439d4a7dd597e66291dth * If applicable, add the following below this CDDL HEADER, with the
a237e38e9161f0acd6451439d4a7dd597e66291dth * fields enclosed by brackets "[]" replaced with your own identifying
a237e38e9161f0acd6451439d4a7dd597e66291dth * information: Portions Copyright [yyyy] [name of copyright owner]
a237e38e9161f0acd6451439d4a7dd597e66291dth * CDDL HEADER END
a237e38e9161f0acd6451439d4a7dd597e66291dth * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
a237e38e9161f0acd6451439d4a7dd597e66291dth * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
a237e38e9161f0acd6451439d4a7dd597e66291dth * SMB specific functions
a237e38e9161f0acd6451439d4a7dd597e66291dth#define SMB_VALID_SUB_CHRS "UDhMLmIiSPu" /* substitution characters */
a237e38e9161f0acd6451439d4a7dd597e66291dth/* internal functions */
a237e38e9161f0acd6451439d4a7dd597e66291dthstatic int smb_share_init(void);
a237e38e9161f0acd6451439d4a7dd597e66291dthstatic void smb_share_fini(void);
a237e38e9161f0acd6451439d4a7dd597e66291dthstatic int smb_rename_resource(sa_handle_t, sa_resource_t, char *);
a237e38e9161f0acd6451439d4a7dd597e66291dthstatic int smb_validate_property(sa_handle_t, sa_property_t, sa_optionset_t);
a237e38e9161f0acd6451439d4a7dd597e66291dthstatic char *smb_get_status(void);
a237e38e9161f0acd6451439d4a7dd597e66291dthstatic int smb_enable_service(void);
a237e38e9161f0acd6451439d4a7dd597e66291dthstatic int range_check_validator(int, char *);
a237e38e9161f0acd6451439d4a7dd597e66291dthstatic int range_check_validator_zero_ok(int, char *);
a237e38e9161f0acd6451439d4a7dd597e66291dthstatic int string_length_check_validator(int, char *);
a237e38e9161f0acd6451439d4a7dd597e66291dthstatic int print_enable_validator(int, char *);
a237e38e9161f0acd6451439d4a7dd597e66291dthstatic int true_false_validator(int, char *);
a237e38e9161f0acd6451439d4a7dd597e66291dthstatic int ipv4_validator(int, char *);
a237e38e9161f0acd6451439d4a7dd597e66291dthstatic int hostname_validator(int, char *);
a237e38e9161f0acd6451439d4a7dd597e66291dthstatic int path_validator(int, char *);
a237e38e9161f0acd6451439d4a7dd597e66291dthstatic int cmd_validator(int, char *);
a237e38e9161f0acd6451439d4a7dd597e66291dthstatic int disposition_validator(int, char *);
a237e38e9161f0acd6451439d4a7dd597e66291dthstatic int smb_build_shareinfo(sa_share_t, sa_resource_t, smb_share_t *);
a237e38e9161f0acd6451439d4a7dd597e66291dthstatic int interface_validator(int, char *);
a237e38e9161f0acd6451439d4a7dd597e66291dthstatic int smb_update_optionset_props(sa_handle_t, sa_resource_t, nvlist_t *);
a237e38e9161f0acd6451439d4a7dd597e66291dthstatic boolean_t smb_saprop_getbool(sa_optionset_t, char *);
a237e38e9161f0acd6451439d4a7dd597e66291dthstatic boolean_t smb_saprop_getstr(sa_optionset_t, char *, char *, size_t);
a237e38e9161f0acd6451439d4a7dd597e66291dthstatic struct {
a237e38e9161f0acd6451439d4a7dd597e66291dth/* size of basic format allocation */
a237e38e9161f0acd6451439d4a7dd597e66291dth/* size of string for types - big enough to hold "dependency" */
a237e38e9161f0acd6451439d4a7dd597e66291dth * Indexes of entries in smb_proto_options table.
a237e38e9161f0acd6451439d4a7dd597e66291dth * Changes to smb_proto_options table may require
a237e38e9161f0acd6451439d4a7dd597e66291dth * an update to these values.
a237e38e9161f0acd6451439d4a7dd597e66291dthtypedef struct smb_hostifs_walker {
a237e38e9161f0acd6451439d4a7dd597e66291dth const char *hiw_ifname;
a237e38e9161f0acd6451439d4a7dd597e66291dth * ops vector that provides the protocol specific info and operations
a237e38e9161f0acd6451439d4a7dd597e66291dth * for share management.
a237e38e9161f0acd6451439d4a7dd597e66291dth * findopt(name)
a237e38e9161f0acd6451439d4a7dd597e66291dth * Lookup option "name" in the option table and return the table
a237e38e9161f0acd6451439d4a7dd597e66291dth return (i);
a237e38e9161f0acd6451439d4a7dd597e66291dth return (-1);
a237e38e9161f0acd6451439d4a7dd597e66291dth * is_a_number(number)
a237e38e9161f0acd6451439d4a7dd597e66291dth * is the string a number in one of the forms we want to use?
a237e38e9161f0acd6451439d4a7dd597e66291dth * check ro vs rw values. Over time this may get beefed up.
a237e38e9161f0acd6451439d4a7dd597e66291dth * for now it just does simple checks.
a237e38e9161f0acd6451439d4a7dd597e66291dth * validresource(name)
a237e38e9161f0acd6451439d4a7dd597e66291dth * Check that name only has valid characters in it. The current valid
a237e38e9161f0acd6451439d4a7dd597e66291dth * set are the printable characters but not including:
a237e38e9161f0acd6451439d4a7dd597e66291dth * " / \ [ ] : | < > + ; , ? * = \t
a237e38e9161f0acd6451439d4a7dd597e66291dth * Note that space is included and there is a maximum length.
a237e38e9161f0acd6451439d4a7dd597e66291dth const char *cp;
a237e38e9161f0acd6451439d4a7dd597e66291dth * Check that the client-side caching (CSC) option value is valid.
a237e38e9161f0acd6451439d4a7dd597e66291dth for (i = 0; i < (sizeof (cscopt) / sizeof (cscopt[0])); ++i) {
a237e38e9161f0acd6451439d4a7dd597e66291dth * smb_isonline()
a237e38e9161f0acd6451439d4a7dd597e66291dth * Determine if the SMF service instance is in the online state or
a237e38e9161f0acd6451439d4a7dd597e66291dth * not. A number of operations depend on this state.
a237e38e9161f0acd6451439d4a7dd597e66291dth if ((str = smf_get_state(SMBD_DEFAULT_INSTANCE_FMRI)) != NULL) {
a237e38e9161f0acd6451439d4a7dd597e66291dth * smb_isdisabled()
a237e38e9161f0acd6451439d4a7dd597e66291dth * Determine if the SMF service instance is in the disabled state or
a237e38e9161f0acd6451439d4a7dd597e66291dth * not. A number of operations depend on this state.
a237e38e9161f0acd6451439d4a7dd597e66291dth if ((str = smf_get_state(SMBD_DEFAULT_INSTANCE_FMRI)) != NULL) {
a237e38e9161f0acd6451439d4a7dd597e66291dth * smb_isautoenable()
a237e38e9161f0acd6451439d4a7dd597e66291dth * Determine if the SMF service instance auto_enabled set or not. A
a237e38e9161f0acd6451439d4a7dd597e66291dth * number of operations depend on this state. The property not being
a237e38e9161f0acd6451439d4a7dd597e66291dth * set or being set to true means autoenable. Only being set to false
a237e38e9161f0acd6451439d4a7dd597e66291dth * is not autoenabled.
a237e38e9161f0acd6451439d4a7dd597e66291dth prop = scf_simple_prop_get(NULL, SMBD_DEFAULT_INSTANCE_FMRI,
a237e38e9161f0acd6451439d4a7dd597e66291dth * smb_ismaint()
a237e38e9161f0acd6451439d4a7dd597e66291dth * Determine if the SMF service instance is in the disabled state or
a237e38e9161f0acd6451439d4a7dd597e66291dth * not. A number of operations depend on this state.
a237e38e9161f0acd6451439d4a7dd597e66291dth if ((str = smf_get_state(SMBD_DEFAULT_INSTANCE_FMRI)) != NULL) {
a237e38e9161f0acd6451439d4a7dd597e66291dth * smb_enable_share tells the implementation that it is to enable the share.
a237e38e9161f0acd6451439d4a7dd597e66291dth * This entails converting the path and options into the appropriate ioctl
a237e38e9161f0acd6451439d4a7dd597e66291dth * calls. It is assumed that all error checking of paths, etc. were
a237e38e9161f0acd6451439d4a7dd597e66291dth * done earlier.
a237e38e9161f0acd6451439d4a7dd597e66291dth * We only start in the global zone and only run if we aren't
a237e38e9161f0acd6451439d4a7dd597e66291dth * running Trusted Extensions.
a237e38e9161f0acd6451439d4a7dd597e66291dth "SMB: service not supported in local zone\n"));
a237e38e9161f0acd6451439d4a7dd597e66291dth "SMB: service not supported with Trusted Extensions\n"));
a237e38e9161f0acd6451439d4a7dd597e66291dth /* get the path since it is important in several places */
a237e38e9161f0acd6451439d4a7dd597e66291dth * If administratively disabled, don't try to start anything.
a237e38e9161f0acd6451439d4a7dd597e66291dth "SMB: Cannot share remove "
a237e38e9161f0acd6451439d4a7dd597e66291dth "SMB: Service needs to be enabled "
a237e38e9161f0acd6451439d4a7dd597e66291dth "by a privileged user\n"));
a237e38e9161f0acd6451439d4a7dd597e66291dth "SMB: Unable to enable service\n"));
a237e38e9161f0acd6451439d4a7dd597e66291dth * For now, it is OK to not be able to enable
a237e38e9161f0acd6451439d4a7dd597e66291dth * the service.
a237e38e9161f0acd6451439d4a7dd597e66291dth * Don't bother trying to start shares if the service isn't
a237e38e9161f0acd6451439d4a7dd597e66291dth * running.
return (err);
if (!iszfs) {
if (!iszfs)
done:
int err;
return (SA_NO_SUCH_PATH);
return (SA_OK);
if (!isonline) {
(void) smb_enable_service();
if (!smb_isonline())
return (SA_OK);
return (ret);
return (SA_NOT_SHARED);
return (SA_OK);
char *rname;
return (SA_NO_SUCH_RESOURCE);
if (smb_isonline()) {
return (SA_CONFIG_ERR);
return (SA_OK);
char *path;
if (!smb_isonline())
return (SA_OK);
return (SA_NO_SUCH_PATH);
return (SA_OK);
if (!smb_isonline())
return (SA_OK);
return (SA_CONFIG_ERR);
return (res);
return (SA_CONFIG_ERR);
return (smb_enable_service());
char *rname;
return (ret);
if (!smb_isonline())
goto done;
if (!iszfs) {
switch (err) {
case NERR_NetNameNotFound:
case NERR_Success:
switch (err) {
case EINVAL:
case ENOENT:
if (!first)
done:
if (!iszfs) {
return (ret);
char *propname;
int optindex;
char *value;
char *other;
return (ret);
case OPT_TYPE_NUMBER:
case OPT_TYPE_BOOLEAN:
case OPT_TYPE_NAME:
case OPT_TYPE_STRING:
case OPT_TYPE_CSC:
case OPT_TYPE_ACCLIST: {
char *ovalue;
return (ret);
struct smb_proto_option_defs {
int smb_index;
int (*validator)(int, char *);
} smb_proto_options[] = {
#define SMB_OPT_NUM \
int val;
return (ret);
int val;
if (val == 0)
return (ret);
return (SA_BAD_VALUE);
return (ret);
return (SA_BAD_VALUE);
return (SA_OK);
return (SA_BAD_VALUE);
return (SA_BAD_VALUE);
#ifdef HAVE_CUPS
return (SA_OK);
return (SA_OK);
return (SA_BAD_VALUE);
return (SA_OK);
return (SA_OK);
return (SA_BAD_VALUE);
return (SA_OK);
char label_terminator;
int len;
return (SA_OK);
return (SA_OK);
return (SA_OK);
return (SA_OK);
return (SA_BAD_VALUE);
return (SA_BAD_VALUE);
if (new_label) {
if (!isalnum(*p))
return (SA_BAD_VALUE);
label_terminator = *p;
return (SA_BAD_VALUE);
label_terminator = *p;
label_terminator = *p;
return (SA_BAD_VALUE);
return (SA_BAD_VALUE);
return (SA_OK);
static boolean_t
static boolean_t
return (B_FALSE);
return (ret);
return (SA_BAD_VALUE);
return (SA_NO_MEMORY);
tmp = p;
free(p);
return (ret);
return (SA_BAD_VALUE);
if (fd < 0)
return (SA_BAD_VALUE);
if (status < 0)
return (SA_BAD_VALUE);
return (SA_OK);
return (SA_BAD_VALUE);
char *sc_name;
for (i = 0; i < SMB_OPT_NUM; i++) {
char *name;
int index;
int rc;
return (SA_NO_MEMORY);
return (ret);
smb_share_init(void)
return (SA_SYSTEM_ERR);
return (smb_load_proto_properties());
smb_share_fini(void)
static sa_protocol_properties_t
smb_get_proto_set(void)
return (protoset);
char *dependency;
char *servname;
int maxlen;
goto done;
goto done;
goto done;
goto done;
goto done;
done:
smb_enable_service(void)
if (!smb_isonline()) {
for (i = 0; i < WAIT_FOR_SERVICE; i++) {
if (smb_isonline()) {
} else if (smb_ismaint()) {
} else if (smb_isdisabled()) {
return (ret);
return (SA_BAD_VALUE);
return (SA_OK);
return (SA_OK);
return (SA_BAD_VALUE);
char *name;
char *value;
if (index >= 0) {
(void) smf_refresh_instance(
(void) smf_restart_instance(
return (ret);
smb_get_status(void)
static uint64_t
smb_share_features(void)
int err;
char *opt;
return (SA_INVALID_NAME);
return (SA_NO_SUCH_GROUP);
return (SA_NO_SUCH_PATH);
return (SA_NO_SUCH_RESOURCE);
return (SA_NO_MEMORY);
if (err) {
return (SA_CONFIG_ERR);
return (err);
int i, offset;
int res;
if (smb_share_count() <= 0)
return (SA_OK);
offset = 0;
return (res);
return (SA_OK);
char *dataset;
char *dup;
char *base;
char *lasts;
char *token;
int iszfs = 0;
int persist = 0;
int need_optionset = 0;
char *zfs;
if (iszfs ||
return (SA_PROP_SHARE_ONLY);
return (SA_NO_MEMORY);
return (ret);
return (SA_NO_MEMORY);
char *value;
char *prefix;
if (!iszfs) {
(void) sa_set_share_description(
(void) sa_set_resource_description(
if (need_optionset) {
need_optionset = 0;
if (!iszfs)
return (ret);
char *name;
char *value;
int curlen;
curlen = 0;
int len;
goto err;
goto err;
err:
int sep = 0;
char *buff;
return (NULL);
options);
return (buff);
return (buff);
int err;
char *oldname;
if (!smb_isonline())
return (SA_OK);
return (SA_NO_SUCH_RESOURCE);
switch (err) {
case NERR_Success:
case NERR_InternalError:
case NERR_DuplicateShare:
return (ret);
char *path;
char *rname;
return (SA_NO_SUCH_PATH);
return (SA_NO_SUCH_RESOURCE);
return (SA_OK);
return (SA_OK);
case SMB_SHRF_CSC_DISABLED:
case SMB_SHRF_CSC_MANUAL:
case SMB_SHRF_CSC_AUTO:
case SMB_SHRF_CSC_VDO:
return (NULL);
static sa_group_t
int err;
return (group);
return (NULL);
return (group);
char *ptr, *v;
return (SA_BAD_VALUE);
return (SA_OK);
if (skip_cmdname) {
return (SA_BAD_VALUE);
return (SA_BAD_VALUE);
} while (v != NULL);
if (skip_cmdname)
return (SA_BAD_VALUE);
return (SA_OK);
return (SA_BAD_VALUE);
return (SA_OK);
return (SA_OK);
return (SA_BAD_VALUE);
return (SA_CONFIG_ERR);
return (err);
static boolean_t
char *val;
return (propval);
static boolean_t
char *val;
return (B_TRUE);
return (B_FALSE);