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