1eda14cbcSMatt Macy /* 2eda14cbcSMatt Macy * CDDL HEADER START 3eda14cbcSMatt Macy * 4eda14cbcSMatt Macy * The contents of this file are subject to the terms of the 5eda14cbcSMatt Macy * Common Development and Distribution License (the "License"). 6eda14cbcSMatt Macy * You may not use this file except in compliance with the License. 7eda14cbcSMatt Macy * 8eda14cbcSMatt Macy * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9eda14cbcSMatt Macy * or http://www.opensolaris.org/os/licensing. 10eda14cbcSMatt Macy * See the License for the specific language governing permissions 11eda14cbcSMatt Macy * and limitations under the License. 12eda14cbcSMatt Macy * 13eda14cbcSMatt Macy * When distributing Covered Code, include this CDDL HEADER in each 14eda14cbcSMatt Macy * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15eda14cbcSMatt Macy * If applicable, add the following below this CDDL HEADER, with the 16eda14cbcSMatt Macy * fields enclosed by brackets "[]" replaced with your own identifying 17eda14cbcSMatt Macy * information: Portions Copyright [yyyy] [name of copyright owner] 18eda14cbcSMatt Macy * 19eda14cbcSMatt Macy * CDDL HEADER END 20eda14cbcSMatt Macy */ 21eda14cbcSMatt Macy 22eda14cbcSMatt Macy /* 23eda14cbcSMatt Macy * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. 24eda14cbcSMatt Macy * Copyright (c) 2011 Gunnar Beutner 25eda14cbcSMatt Macy * Copyright (c) 2018, 2020 by Delphix. All rights reserved. 26eda14cbcSMatt Macy */ 27eda14cbcSMatt Macy 28eda14cbcSMatt Macy #include <stdio.h> 29eda14cbcSMatt Macy #include <stdlib.h> 30*da5137abSMartin Matuska #include <string.h> 31eda14cbcSMatt Macy #include <errno.h> 32eda14cbcSMatt Macy #include <libintl.h> 33eda14cbcSMatt Macy #include <sys/file.h> 34eda14cbcSMatt Macy #include <sys/types.h> 35eda14cbcSMatt Macy #include <sys/stat.h> 36eda14cbcSMatt Macy #include <unistd.h> 37eda14cbcSMatt Macy #include <libzfs.h> 38eda14cbcSMatt Macy #include <libshare.h> 39eda14cbcSMatt Macy #include "libshare_impl.h" 40eda14cbcSMatt Macy #include "nfs.h" 41eda14cbcSMatt Macy #include "smb.h" 42eda14cbcSMatt Macy 43eda14cbcSMatt Macy static sa_share_impl_t alloc_share(const char *zfsname, const char *path); 44eda14cbcSMatt Macy static void free_share(sa_share_impl_t share); 45eda14cbcSMatt Macy 46eda14cbcSMatt Macy static int fstypes_count; 47eda14cbcSMatt Macy static sa_fstype_t *fstypes; 48eda14cbcSMatt Macy 49eda14cbcSMatt Macy sa_fstype_t * 50eda14cbcSMatt Macy register_fstype(const char *name, const sa_share_ops_t *ops) 51eda14cbcSMatt Macy { 52eda14cbcSMatt Macy sa_fstype_t *fstype; 53eda14cbcSMatt Macy 54eda14cbcSMatt Macy fstype = calloc(1, sizeof (sa_fstype_t)); 55eda14cbcSMatt Macy 56eda14cbcSMatt Macy if (fstype == NULL) 57eda14cbcSMatt Macy return (NULL); 58eda14cbcSMatt Macy 59eda14cbcSMatt Macy fstype->name = name; 60eda14cbcSMatt Macy fstype->ops = ops; 61eda14cbcSMatt Macy fstype->fsinfo_index = fstypes_count; 62eda14cbcSMatt Macy 63eda14cbcSMatt Macy fstypes_count++; 64eda14cbcSMatt Macy 65eda14cbcSMatt Macy fstype->next = fstypes; 66eda14cbcSMatt Macy fstypes = fstype; 67eda14cbcSMatt Macy 68eda14cbcSMatt Macy return (fstype); 69eda14cbcSMatt Macy } 70eda14cbcSMatt Macy 71eda14cbcSMatt Macy __attribute__((constructor)) static void 72eda14cbcSMatt Macy libshare_init(void) 73eda14cbcSMatt Macy { 74eda14cbcSMatt Macy libshare_nfs_init(); 75eda14cbcSMatt Macy libshare_smb_init(); 76eda14cbcSMatt Macy } 77eda14cbcSMatt Macy 78eda14cbcSMatt Macy int 79eda14cbcSMatt Macy sa_enable_share(const char *zfsname, const char *mountpoint, 80eda14cbcSMatt Macy const char *shareopts, char *protocol) 81eda14cbcSMatt Macy { 82eda14cbcSMatt Macy int rc, ret = SA_OK; 83eda14cbcSMatt Macy boolean_t found_protocol = B_FALSE; 84eda14cbcSMatt Macy sa_fstype_t *fstype; 85eda14cbcSMatt Macy 86eda14cbcSMatt Macy sa_share_impl_t impl_share = alloc_share(zfsname, mountpoint); 87eda14cbcSMatt Macy if (impl_share == NULL) 88eda14cbcSMatt Macy return (SA_NO_MEMORY); 89eda14cbcSMatt Macy 90eda14cbcSMatt Macy fstype = fstypes; 91eda14cbcSMatt Macy while (fstype != NULL) { 92eda14cbcSMatt Macy if (strcmp(fstype->name, protocol) == 0) { 93eda14cbcSMatt Macy 94eda14cbcSMatt Macy rc = fstype->ops->update_shareopts(impl_share, 95eda14cbcSMatt Macy shareopts); 96eda14cbcSMatt Macy if (rc != SA_OK) 97eda14cbcSMatt Macy break; 98eda14cbcSMatt Macy 99eda14cbcSMatt Macy rc = fstype->ops->enable_share(impl_share); 100eda14cbcSMatt Macy if (rc != SA_OK) 101eda14cbcSMatt Macy ret = rc; 102eda14cbcSMatt Macy 103eda14cbcSMatt Macy found_protocol = B_TRUE; 104eda14cbcSMatt Macy } 105eda14cbcSMatt Macy 106eda14cbcSMatt Macy fstype = fstype->next; 107eda14cbcSMatt Macy } 108eda14cbcSMatt Macy free_share(impl_share); 109eda14cbcSMatt Macy 110eda14cbcSMatt Macy return (found_protocol ? ret : SA_INVALID_PROTOCOL); 111eda14cbcSMatt Macy } 112eda14cbcSMatt Macy 113eda14cbcSMatt Macy int 114eda14cbcSMatt Macy sa_disable_share(const char *mountpoint, char *protocol) 115eda14cbcSMatt Macy { 116eda14cbcSMatt Macy int rc, ret = SA_OK; 117eda14cbcSMatt Macy boolean_t found_protocol = B_FALSE; 118eda14cbcSMatt Macy sa_fstype_t *fstype; 119eda14cbcSMatt Macy 120eda14cbcSMatt Macy sa_share_impl_t impl_share = alloc_share(NULL, mountpoint); 121eda14cbcSMatt Macy if (impl_share == NULL) 122eda14cbcSMatt Macy return (SA_NO_MEMORY); 123eda14cbcSMatt Macy 124eda14cbcSMatt Macy fstype = fstypes; 125eda14cbcSMatt Macy while (fstype != NULL) { 126eda14cbcSMatt Macy if (strcmp(fstype->name, protocol) == 0) { 127eda14cbcSMatt Macy 128eda14cbcSMatt Macy rc = fstype->ops->disable_share(impl_share); 129eda14cbcSMatt Macy if (rc != SA_OK) 130eda14cbcSMatt Macy ret = rc; 131eda14cbcSMatt Macy 132eda14cbcSMatt Macy found_protocol = B_TRUE; 133eda14cbcSMatt Macy } 134eda14cbcSMatt Macy 135eda14cbcSMatt Macy fstype = fstype->next; 136eda14cbcSMatt Macy } 137eda14cbcSMatt Macy free_share(impl_share); 138eda14cbcSMatt Macy 139eda14cbcSMatt Macy return (found_protocol ? ret : SA_INVALID_PROTOCOL); 140eda14cbcSMatt Macy } 141eda14cbcSMatt Macy 142eda14cbcSMatt Macy boolean_t 143eda14cbcSMatt Macy sa_is_shared(const char *mountpoint, char *protocol) 144eda14cbcSMatt Macy { 145eda14cbcSMatt Macy sa_fstype_t *fstype; 146eda14cbcSMatt Macy boolean_t ret = B_FALSE; 147eda14cbcSMatt Macy 148eda14cbcSMatt Macy /* guid value is not used */ 149eda14cbcSMatt Macy sa_share_impl_t impl_share = alloc_share(NULL, mountpoint); 150eda14cbcSMatt Macy if (impl_share == NULL) 151eda14cbcSMatt Macy return (B_FALSE); 152eda14cbcSMatt Macy 153eda14cbcSMatt Macy fstype = fstypes; 154eda14cbcSMatt Macy while (fstype != NULL) { 155eda14cbcSMatt Macy if (strcmp(fstype->name, protocol) == 0) { 156eda14cbcSMatt Macy ret = fstype->ops->is_shared(impl_share); 157eda14cbcSMatt Macy } 158eda14cbcSMatt Macy fstype = fstype->next; 159eda14cbcSMatt Macy } 160eda14cbcSMatt Macy free_share(impl_share); 161eda14cbcSMatt Macy return (ret); 162eda14cbcSMatt Macy } 163eda14cbcSMatt Macy 164eda14cbcSMatt Macy void 165eda14cbcSMatt Macy sa_commit_shares(const char *protocol) 166eda14cbcSMatt Macy { 167eda14cbcSMatt Macy sa_fstype_t *fstype = fstypes; 168eda14cbcSMatt Macy while (fstype != NULL) { 169eda14cbcSMatt Macy if (strcmp(fstype->name, protocol) == 0) 170eda14cbcSMatt Macy fstype->ops->commit_shares(); 171eda14cbcSMatt Macy fstype = fstype->next; 172eda14cbcSMatt Macy } 173eda14cbcSMatt Macy } 174eda14cbcSMatt Macy 175eda14cbcSMatt Macy /* 176eda14cbcSMatt Macy * sa_errorstr(err) 177eda14cbcSMatt Macy * 178eda14cbcSMatt Macy * convert an error value to an error string 179eda14cbcSMatt Macy */ 180eda14cbcSMatt Macy char * 181eda14cbcSMatt Macy sa_errorstr(int err) 182eda14cbcSMatt Macy { 183eda14cbcSMatt Macy static char errstr[32]; 184eda14cbcSMatt Macy char *ret = NULL; 185eda14cbcSMatt Macy 186eda14cbcSMatt Macy switch (err) { 187eda14cbcSMatt Macy case SA_OK: 188eda14cbcSMatt Macy ret = dgettext(TEXT_DOMAIN, "ok"); 189eda14cbcSMatt Macy break; 190eda14cbcSMatt Macy case SA_NO_SUCH_PATH: 191eda14cbcSMatt Macy ret = dgettext(TEXT_DOMAIN, "path doesn't exist"); 192eda14cbcSMatt Macy break; 193eda14cbcSMatt Macy case SA_NO_MEMORY: 194eda14cbcSMatt Macy ret = dgettext(TEXT_DOMAIN, "no memory"); 195eda14cbcSMatt Macy break; 196eda14cbcSMatt Macy case SA_DUPLICATE_NAME: 197eda14cbcSMatt Macy ret = dgettext(TEXT_DOMAIN, "name in use"); 198eda14cbcSMatt Macy break; 199eda14cbcSMatt Macy case SA_BAD_PATH: 200eda14cbcSMatt Macy ret = dgettext(TEXT_DOMAIN, "bad path"); 201eda14cbcSMatt Macy break; 202eda14cbcSMatt Macy case SA_NO_SUCH_GROUP: 203eda14cbcSMatt Macy ret = dgettext(TEXT_DOMAIN, "no such group"); 204eda14cbcSMatt Macy break; 205eda14cbcSMatt Macy case SA_CONFIG_ERR: 206eda14cbcSMatt Macy ret = dgettext(TEXT_DOMAIN, "configuration error"); 207eda14cbcSMatt Macy break; 208eda14cbcSMatt Macy case SA_SYSTEM_ERR: 209eda14cbcSMatt Macy ret = dgettext(TEXT_DOMAIN, "system error"); 210eda14cbcSMatt Macy break; 211eda14cbcSMatt Macy case SA_SYNTAX_ERR: 212eda14cbcSMatt Macy ret = dgettext(TEXT_DOMAIN, "syntax error"); 213eda14cbcSMatt Macy break; 214eda14cbcSMatt Macy case SA_NO_PERMISSION: 215eda14cbcSMatt Macy ret = dgettext(TEXT_DOMAIN, "no permission"); 216eda14cbcSMatt Macy break; 217eda14cbcSMatt Macy case SA_BUSY: 218eda14cbcSMatt Macy ret = dgettext(TEXT_DOMAIN, "busy"); 219eda14cbcSMatt Macy break; 220eda14cbcSMatt Macy case SA_NO_SUCH_PROP: 221eda14cbcSMatt Macy ret = dgettext(TEXT_DOMAIN, "no such property"); 222eda14cbcSMatt Macy break; 223eda14cbcSMatt Macy case SA_INVALID_NAME: 224eda14cbcSMatt Macy ret = dgettext(TEXT_DOMAIN, "invalid name"); 225eda14cbcSMatt Macy break; 226eda14cbcSMatt Macy case SA_INVALID_PROTOCOL: 227eda14cbcSMatt Macy ret = dgettext(TEXT_DOMAIN, "invalid protocol"); 228eda14cbcSMatt Macy break; 229eda14cbcSMatt Macy case SA_NOT_ALLOWED: 230eda14cbcSMatt Macy ret = dgettext(TEXT_DOMAIN, "operation not allowed"); 231eda14cbcSMatt Macy break; 232eda14cbcSMatt Macy case SA_BAD_VALUE: 233eda14cbcSMatt Macy ret = dgettext(TEXT_DOMAIN, "bad property value"); 234eda14cbcSMatt Macy break; 235eda14cbcSMatt Macy case SA_INVALID_SECURITY: 236eda14cbcSMatt Macy ret = dgettext(TEXT_DOMAIN, "invalid security type"); 237eda14cbcSMatt Macy break; 238eda14cbcSMatt Macy case SA_NO_SUCH_SECURITY: 239eda14cbcSMatt Macy ret = dgettext(TEXT_DOMAIN, "security type not found"); 240eda14cbcSMatt Macy break; 241eda14cbcSMatt Macy case SA_VALUE_CONFLICT: 242eda14cbcSMatt Macy ret = dgettext(TEXT_DOMAIN, "property value conflict"); 243eda14cbcSMatt Macy break; 244eda14cbcSMatt Macy case SA_NOT_IMPLEMENTED: 245eda14cbcSMatt Macy ret = dgettext(TEXT_DOMAIN, "not implemented"); 246eda14cbcSMatt Macy break; 247eda14cbcSMatt Macy case SA_INVALID_PATH: 248eda14cbcSMatt Macy ret = dgettext(TEXT_DOMAIN, "invalid path"); 249eda14cbcSMatt Macy break; 250eda14cbcSMatt Macy case SA_NOT_SUPPORTED: 251eda14cbcSMatt Macy ret = dgettext(TEXT_DOMAIN, "operation not supported"); 252eda14cbcSMatt Macy break; 253eda14cbcSMatt Macy case SA_PROP_SHARE_ONLY: 254eda14cbcSMatt Macy ret = dgettext(TEXT_DOMAIN, "property not valid for group"); 255eda14cbcSMatt Macy break; 256eda14cbcSMatt Macy case SA_NOT_SHARED: 257eda14cbcSMatt Macy ret = dgettext(TEXT_DOMAIN, "not shared"); 258eda14cbcSMatt Macy break; 259eda14cbcSMatt Macy case SA_NO_SUCH_RESOURCE: 260eda14cbcSMatt Macy ret = dgettext(TEXT_DOMAIN, "no such resource"); 261eda14cbcSMatt Macy break; 262eda14cbcSMatt Macy case SA_RESOURCE_REQUIRED: 263eda14cbcSMatt Macy ret = dgettext(TEXT_DOMAIN, "resource name required"); 264eda14cbcSMatt Macy break; 265eda14cbcSMatt Macy case SA_MULTIPLE_ERROR: 266eda14cbcSMatt Macy ret = dgettext(TEXT_DOMAIN, "errors from multiple protocols"); 267eda14cbcSMatt Macy break; 268eda14cbcSMatt Macy case SA_PATH_IS_SUBDIR: 269eda14cbcSMatt Macy ret = dgettext(TEXT_DOMAIN, "path is a subpath of share"); 270eda14cbcSMatt Macy break; 271eda14cbcSMatt Macy case SA_PATH_IS_PARENTDIR: 272eda14cbcSMatt Macy ret = dgettext(TEXT_DOMAIN, "path is parent of a share"); 273eda14cbcSMatt Macy break; 274eda14cbcSMatt Macy case SA_NO_SECTION: 275eda14cbcSMatt Macy ret = dgettext(TEXT_DOMAIN, "protocol requires a section"); 276eda14cbcSMatt Macy break; 277eda14cbcSMatt Macy case SA_NO_PROPERTIES: 278eda14cbcSMatt Macy ret = dgettext(TEXT_DOMAIN, "properties not found"); 279eda14cbcSMatt Macy break; 280eda14cbcSMatt Macy case SA_NO_SUCH_SECTION: 281eda14cbcSMatt Macy ret = dgettext(TEXT_DOMAIN, "section not found"); 282eda14cbcSMatt Macy break; 283eda14cbcSMatt Macy case SA_PASSWORD_ENC: 284eda14cbcSMatt Macy ret = dgettext(TEXT_DOMAIN, "passwords must be encrypted"); 285eda14cbcSMatt Macy break; 286eda14cbcSMatt Macy case SA_SHARE_EXISTS: 287eda14cbcSMatt Macy ret = dgettext(TEXT_DOMAIN, "path or file is already shared"); 288eda14cbcSMatt Macy break; 289eda14cbcSMatt Macy default: 290eda14cbcSMatt Macy (void) snprintf(errstr, sizeof (errstr), 291eda14cbcSMatt Macy dgettext(TEXT_DOMAIN, "unknown %d"), err); 292eda14cbcSMatt Macy ret = errstr; 293eda14cbcSMatt Macy } 294eda14cbcSMatt Macy return (ret); 295eda14cbcSMatt Macy } 296eda14cbcSMatt Macy 297eda14cbcSMatt Macy int 298eda14cbcSMatt Macy sa_validate_shareopts(char *options, char *proto) 299eda14cbcSMatt Macy { 300eda14cbcSMatt Macy sa_fstype_t *fstype; 301eda14cbcSMatt Macy 302eda14cbcSMatt Macy fstype = fstypes; 303eda14cbcSMatt Macy while (fstype != NULL) { 304eda14cbcSMatt Macy if (strcmp(fstype->name, proto) != 0) { 305eda14cbcSMatt Macy fstype = fstype->next; 306eda14cbcSMatt Macy continue; 307eda14cbcSMatt Macy } 308eda14cbcSMatt Macy 309eda14cbcSMatt Macy return (fstype->ops->validate_shareopts(options)); 310eda14cbcSMatt Macy } 311eda14cbcSMatt Macy 312eda14cbcSMatt Macy return (SA_INVALID_PROTOCOL); 313eda14cbcSMatt Macy } 314eda14cbcSMatt Macy 315eda14cbcSMatt Macy static sa_share_impl_t 316eda14cbcSMatt Macy alloc_share(const char *zfsname, const char *mountpoint) 317eda14cbcSMatt Macy { 318eda14cbcSMatt Macy sa_share_impl_t impl_share; 319eda14cbcSMatt Macy 320eda14cbcSMatt Macy impl_share = calloc(1, sizeof (struct sa_share_impl)); 321eda14cbcSMatt Macy 322eda14cbcSMatt Macy if (impl_share == NULL) 323eda14cbcSMatt Macy return (NULL); 324eda14cbcSMatt Macy 325eda14cbcSMatt Macy if (mountpoint != NULL && 326eda14cbcSMatt Macy ((impl_share->sa_mountpoint = strdup(mountpoint)) == NULL)) { 327eda14cbcSMatt Macy free(impl_share); 328eda14cbcSMatt Macy return (NULL); 329eda14cbcSMatt Macy } 330eda14cbcSMatt Macy 331eda14cbcSMatt Macy if (zfsname != NULL && 332eda14cbcSMatt Macy ((impl_share->sa_zfsname = strdup(zfsname)) == NULL)) { 333eda14cbcSMatt Macy free(impl_share->sa_mountpoint); 334eda14cbcSMatt Macy free(impl_share); 335eda14cbcSMatt Macy return (NULL); 336eda14cbcSMatt Macy } 337eda14cbcSMatt Macy 338eda14cbcSMatt Macy impl_share->sa_fsinfo = calloc(fstypes_count, 339eda14cbcSMatt Macy sizeof (sa_share_fsinfo_t)); 340eda14cbcSMatt Macy if (impl_share->sa_fsinfo == NULL) { 341eda14cbcSMatt Macy free(impl_share->sa_mountpoint); 342eda14cbcSMatt Macy free(impl_share->sa_zfsname); 343eda14cbcSMatt Macy free(impl_share); 344eda14cbcSMatt Macy return (NULL); 345eda14cbcSMatt Macy } 346eda14cbcSMatt Macy 347eda14cbcSMatt Macy return (impl_share); 348eda14cbcSMatt Macy } 349eda14cbcSMatt Macy 350eda14cbcSMatt Macy static void 351eda14cbcSMatt Macy free_share(sa_share_impl_t impl_share) 352eda14cbcSMatt Macy { 353eda14cbcSMatt Macy sa_fstype_t *fstype; 354eda14cbcSMatt Macy 355eda14cbcSMatt Macy fstype = fstypes; 356eda14cbcSMatt Macy while (fstype != NULL) { 357eda14cbcSMatt Macy fstype->ops->clear_shareopts(impl_share); 358eda14cbcSMatt Macy fstype = fstype->next; 359eda14cbcSMatt Macy } 360eda14cbcSMatt Macy 361eda14cbcSMatt Macy free(impl_share->sa_mountpoint); 362eda14cbcSMatt Macy free(impl_share->sa_zfsname); 363eda14cbcSMatt Macy free(impl_share->sa_fsinfo); 364eda14cbcSMatt Macy free(impl_share); 365eda14cbcSMatt Macy } 366