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 "libshare_impl.h" 40 #include "nfs.h" 41 #include "smb.h" 42 43 static sa_share_impl_t alloc_share(const char *zfsname, const char *path); 44 static void free_share(sa_share_impl_t share); 45 46 static int fstypes_count; 47 static sa_fstype_t *fstypes; 48 49 sa_fstype_t * 50 register_fstype(const char *name, const sa_share_ops_t *ops) 51 { 52 sa_fstype_t *fstype; 53 54 fstype = calloc(1, sizeof (sa_fstype_t)); 55 56 if (fstype == NULL) 57 return (NULL); 58 59 fstype->name = name; 60 fstype->ops = ops; 61 fstype->fsinfo_index = fstypes_count; 62 63 fstypes_count++; 64 65 fstype->next = fstypes; 66 fstypes = fstype; 67 68 return (fstype); 69 } 70 71 __attribute__((constructor)) static void 72 libshare_init(void) 73 { 74 libshare_nfs_init(); 75 libshare_smb_init(); 76 } 77 78 int 79 sa_enable_share(const char *zfsname, const char *mountpoint, 80 const char *shareopts, char *protocol) 81 { 82 int rc, ret = SA_OK; 83 boolean_t found_protocol = B_FALSE; 84 sa_fstype_t *fstype; 85 86 sa_share_impl_t impl_share = alloc_share(zfsname, mountpoint); 87 if (impl_share == NULL) 88 return (SA_NO_MEMORY); 89 90 fstype = fstypes; 91 while (fstype != NULL) { 92 if (strcmp(fstype->name, protocol) == 0) { 93 94 rc = fstype->ops->update_shareopts(impl_share, 95 shareopts); 96 if (rc != SA_OK) 97 break; 98 99 rc = fstype->ops->enable_share(impl_share); 100 if (rc != SA_OK) 101 ret = rc; 102 103 found_protocol = B_TRUE; 104 } 105 106 fstype = fstype->next; 107 } 108 free_share(impl_share); 109 110 return (found_protocol ? ret : SA_INVALID_PROTOCOL); 111 } 112 113 int 114 sa_disable_share(const char *mountpoint, char *protocol) 115 { 116 int rc, ret = SA_OK; 117 boolean_t found_protocol = B_FALSE; 118 sa_fstype_t *fstype; 119 120 sa_share_impl_t impl_share = alloc_share(NULL, mountpoint); 121 if (impl_share == NULL) 122 return (SA_NO_MEMORY); 123 124 fstype = fstypes; 125 while (fstype != NULL) { 126 if (strcmp(fstype->name, protocol) == 0) { 127 128 rc = fstype->ops->disable_share(impl_share); 129 if (rc != SA_OK) 130 ret = rc; 131 132 found_protocol = B_TRUE; 133 } 134 135 fstype = fstype->next; 136 } 137 free_share(impl_share); 138 139 return (found_protocol ? ret : SA_INVALID_PROTOCOL); 140 } 141 142 boolean_t 143 sa_is_shared(const char *mountpoint, char *protocol) 144 { 145 sa_fstype_t *fstype; 146 boolean_t ret = B_FALSE; 147 148 /* guid value is not used */ 149 sa_share_impl_t impl_share = alloc_share(NULL, mountpoint); 150 if (impl_share == NULL) 151 return (B_FALSE); 152 153 fstype = fstypes; 154 while (fstype != NULL) { 155 if (strcmp(fstype->name, protocol) == 0) { 156 ret = fstype->ops->is_shared(impl_share); 157 } 158 fstype = fstype->next; 159 } 160 free_share(impl_share); 161 return (ret); 162 } 163 164 void 165 sa_commit_shares(const char *protocol) 166 { 167 sa_fstype_t *fstype = fstypes; 168 while (fstype != NULL) { 169 if (strcmp(fstype->name, protocol) == 0) 170 fstype->ops->commit_shares(); 171 fstype = fstype->next; 172 } 173 } 174 175 /* 176 * sa_errorstr(err) 177 * 178 * convert an error value to an error string 179 */ 180 char * 181 sa_errorstr(int err) 182 { 183 static char errstr[32]; 184 char *ret = NULL; 185 186 switch (err) { 187 case SA_OK: 188 ret = dgettext(TEXT_DOMAIN, "ok"); 189 break; 190 case SA_NO_SUCH_PATH: 191 ret = dgettext(TEXT_DOMAIN, "path doesn't exist"); 192 break; 193 case SA_NO_MEMORY: 194 ret = dgettext(TEXT_DOMAIN, "no memory"); 195 break; 196 case SA_DUPLICATE_NAME: 197 ret = dgettext(TEXT_DOMAIN, "name in use"); 198 break; 199 case SA_BAD_PATH: 200 ret = dgettext(TEXT_DOMAIN, "bad path"); 201 break; 202 case SA_NO_SUCH_GROUP: 203 ret = dgettext(TEXT_DOMAIN, "no such group"); 204 break; 205 case SA_CONFIG_ERR: 206 ret = dgettext(TEXT_DOMAIN, "configuration error"); 207 break; 208 case SA_SYSTEM_ERR: 209 ret = dgettext(TEXT_DOMAIN, "system error"); 210 break; 211 case SA_SYNTAX_ERR: 212 ret = dgettext(TEXT_DOMAIN, "syntax error"); 213 break; 214 case SA_NO_PERMISSION: 215 ret = dgettext(TEXT_DOMAIN, "no permission"); 216 break; 217 case SA_BUSY: 218 ret = dgettext(TEXT_DOMAIN, "busy"); 219 break; 220 case SA_NO_SUCH_PROP: 221 ret = dgettext(TEXT_DOMAIN, "no such property"); 222 break; 223 case SA_INVALID_NAME: 224 ret = dgettext(TEXT_DOMAIN, "invalid name"); 225 break; 226 case SA_INVALID_PROTOCOL: 227 ret = dgettext(TEXT_DOMAIN, "invalid protocol"); 228 break; 229 case SA_NOT_ALLOWED: 230 ret = dgettext(TEXT_DOMAIN, "operation not allowed"); 231 break; 232 case SA_BAD_VALUE: 233 ret = dgettext(TEXT_DOMAIN, "bad property value"); 234 break; 235 case SA_INVALID_SECURITY: 236 ret = dgettext(TEXT_DOMAIN, "invalid security type"); 237 break; 238 case SA_NO_SUCH_SECURITY: 239 ret = dgettext(TEXT_DOMAIN, "security type not found"); 240 break; 241 case SA_VALUE_CONFLICT: 242 ret = dgettext(TEXT_DOMAIN, "property value conflict"); 243 break; 244 case SA_NOT_IMPLEMENTED: 245 ret = dgettext(TEXT_DOMAIN, "not implemented"); 246 break; 247 case SA_INVALID_PATH: 248 ret = dgettext(TEXT_DOMAIN, "invalid path"); 249 break; 250 case SA_NOT_SUPPORTED: 251 ret = dgettext(TEXT_DOMAIN, "operation not supported"); 252 break; 253 case SA_PROP_SHARE_ONLY: 254 ret = dgettext(TEXT_DOMAIN, "property not valid for group"); 255 break; 256 case SA_NOT_SHARED: 257 ret = dgettext(TEXT_DOMAIN, "not shared"); 258 break; 259 case SA_NO_SUCH_RESOURCE: 260 ret = dgettext(TEXT_DOMAIN, "no such resource"); 261 break; 262 case SA_RESOURCE_REQUIRED: 263 ret = dgettext(TEXT_DOMAIN, "resource name required"); 264 break; 265 case SA_MULTIPLE_ERROR: 266 ret = dgettext(TEXT_DOMAIN, "errors from multiple protocols"); 267 break; 268 case SA_PATH_IS_SUBDIR: 269 ret = dgettext(TEXT_DOMAIN, "path is a subpath of share"); 270 break; 271 case SA_PATH_IS_PARENTDIR: 272 ret = dgettext(TEXT_DOMAIN, "path is parent of a share"); 273 break; 274 case SA_NO_SECTION: 275 ret = dgettext(TEXT_DOMAIN, "protocol requires a section"); 276 break; 277 case SA_NO_PROPERTIES: 278 ret = dgettext(TEXT_DOMAIN, "properties not found"); 279 break; 280 case SA_NO_SUCH_SECTION: 281 ret = dgettext(TEXT_DOMAIN, "section not found"); 282 break; 283 case SA_PASSWORD_ENC: 284 ret = dgettext(TEXT_DOMAIN, "passwords must be encrypted"); 285 break; 286 case SA_SHARE_EXISTS: 287 ret = dgettext(TEXT_DOMAIN, "path or file is already shared"); 288 break; 289 default: 290 (void) snprintf(errstr, sizeof (errstr), 291 dgettext(TEXT_DOMAIN, "unknown %d"), err); 292 ret = errstr; 293 } 294 return (ret); 295 } 296 297 int 298 sa_validate_shareopts(char *options, char *proto) 299 { 300 sa_fstype_t *fstype; 301 302 fstype = fstypes; 303 while (fstype != NULL) { 304 if (strcmp(fstype->name, proto) != 0) { 305 fstype = fstype->next; 306 continue; 307 } 308 309 return (fstype->ops->validate_shareopts(options)); 310 } 311 312 return (SA_INVALID_PROTOCOL); 313 } 314 315 static sa_share_impl_t 316 alloc_share(const char *zfsname, const char *mountpoint) 317 { 318 sa_share_impl_t impl_share; 319 320 impl_share = calloc(1, sizeof (struct sa_share_impl)); 321 322 if (impl_share == NULL) 323 return (NULL); 324 325 if (mountpoint != NULL && 326 ((impl_share->sa_mountpoint = strdup(mountpoint)) == NULL)) { 327 free(impl_share); 328 return (NULL); 329 } 330 331 if (zfsname != NULL && 332 ((impl_share->sa_zfsname = strdup(zfsname)) == NULL)) { 333 free(impl_share->sa_mountpoint); 334 free(impl_share); 335 return (NULL); 336 } 337 338 impl_share->sa_fsinfo = calloc(fstypes_count, 339 sizeof (sa_share_fsinfo_t)); 340 if (impl_share->sa_fsinfo == NULL) { 341 free(impl_share->sa_mountpoint); 342 free(impl_share->sa_zfsname); 343 free(impl_share); 344 return (NULL); 345 } 346 347 return (impl_share); 348 } 349 350 static void 351 free_share(sa_share_impl_t impl_share) 352 { 353 sa_fstype_t *fstype; 354 355 fstype = fstypes; 356 while (fstype != NULL) { 357 fstype->ops->clear_shareopts(impl_share); 358 fstype = fstype->next; 359 } 360 361 free(impl_share->sa_mountpoint); 362 free(impl_share->sa_zfsname); 363 free(impl_share->sa_fsinfo); 364 free(impl_share); 365 } 366