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