16185db85Sdougm /* 26185db85Sdougm * CDDL HEADER START 36185db85Sdougm * 46185db85Sdougm * The contents of this file are subject to the terms of the 56185db85Sdougm * Common Development and Distribution License (the "License"). 66185db85Sdougm * You may not use this file except in compliance with the License. 76185db85Sdougm * 86185db85Sdougm * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 96185db85Sdougm * or http://www.opensolaris.org/os/licensing. 106185db85Sdougm * See the License for the specific language governing permissions 116185db85Sdougm * and limitations under the License. 126185db85Sdougm * 136185db85Sdougm * When distributing Covered Code, include this CDDL HEADER in each 146185db85Sdougm * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 156185db85Sdougm * If applicable, add the following below this CDDL HEADER, with the 166185db85Sdougm * fields enclosed by brackets "[]" replaced with your own identifying 176185db85Sdougm * information: Portions Copyright [yyyy] [name of copyright owner] 186185db85Sdougm * 196185db85Sdougm * CDDL HEADER END 206185db85Sdougm */ 216185db85Sdougm 226185db85Sdougm /* 23822e6387SMarcel Telka * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. 24*f091aea1SYuri Pankov * Copyright 2016 Nexenta Systems, Inc. 2587da98afSVitaliy Gusev */ 266185db85Sdougm 276185db85Sdougm /* 286185db85Sdougm * NFS specific functions 296185db85Sdougm */ 306185db85Sdougm #include <stdio.h> 316185db85Sdougm #include <string.h> 326185db85Sdougm #include <ctype.h> 336185db85Sdougm #include <stdlib.h> 346185db85Sdougm #include <unistd.h> 356185db85Sdougm #include <zone.h> 366185db85Sdougm #include <errno.h> 376185db85Sdougm #include <locale.h> 386185db85Sdougm #include <signal.h> 39dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States #include <strings.h> 406185db85Sdougm #include "libshare.h" 416185db85Sdougm #include "libshare_impl.h" 426185db85Sdougm #include <nfs/export.h> 436185db85Sdougm #include <pwd.h> 445cb0d679SMarcel Telka #include <grp.h> 456185db85Sdougm #include <limits.h> 466185db85Sdougm #include <libscf.h> 47dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States #include <syslog.h> 48dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States #include <rpcsvc/daemon_utils.h> 496185db85Sdougm #include "nfslog_config.h" 506185db85Sdougm #include "nfslogtab.h" 516185db85Sdougm #include "libshare_nfs.h" 526185db85Sdougm #include <nfs/nfs.h> 53ecd6cf80Smarks #include <nfs/nfssys.h> 54*f091aea1SYuri Pankov #include <netconfig.h> 55dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States #include "smfcfg.h" 566185db85Sdougm 576185db85Sdougm /* should really be in some global place */ 586185db85Sdougm #define DEF_WIN 30000 596185db85Sdougm #define OPT_CHUNK 1024 606185db85Sdougm 616185db85Sdougm int debug = 0; 626185db85Sdougm 63ecd6cf80Smarks #define NFS_SERVER_SVC "svc:/network/nfs/server:default" 64dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States #define NFS_CLIENT_SVC (char *)"svc:/network/nfs/client:default" 656185db85Sdougm 666185db85Sdougm /* internal functions */ 676185db85Sdougm static int nfs_init(); 686185db85Sdougm static void nfs_fini(); 696185db85Sdougm static int nfs_enable_share(sa_share_t); 70ecd6cf80Smarks static int nfs_disable_share(sa_share_t, char *); 71687915e9Sdougm static int nfs_validate_property(sa_handle_t, sa_property_t, sa_optionset_t); 726185db85Sdougm static int nfs_validate_security_mode(char *); 736185db85Sdougm static int nfs_is_security_opt(char *); 746185db85Sdougm static int nfs_parse_legacy_options(sa_group_t, char *); 756185db85Sdougm static char *nfs_format_options(sa_group_t, int); 766185db85Sdougm static int nfs_set_proto_prop(sa_property_t); 776185db85Sdougm static sa_protocol_properties_t nfs_get_proto_set(); 786185db85Sdougm static char *nfs_get_status(); 796185db85Sdougm static char *nfs_space_alias(char *); 80da6c28aaSamw static uint64_t nfs_features(); 816185db85Sdougm 826185db85Sdougm /* 836185db85Sdougm * ops vector that provides the protocol specific info and operations 846185db85Sdougm * for share management. 856185db85Sdougm */ 866185db85Sdougm 876185db85Sdougm struct sa_plugin_ops sa_plugin_ops = { 886185db85Sdougm SA_PLUGIN_VERSION, 896185db85Sdougm "nfs", 906185db85Sdougm nfs_init, 916185db85Sdougm nfs_fini, 926185db85Sdougm nfs_enable_share, 936185db85Sdougm nfs_disable_share, 946185db85Sdougm nfs_validate_property, 956185db85Sdougm nfs_validate_security_mode, 966185db85Sdougm nfs_is_security_opt, 976185db85Sdougm nfs_parse_legacy_options, 986185db85Sdougm nfs_format_options, 996185db85Sdougm nfs_set_proto_prop, 1006185db85Sdougm nfs_get_proto_set, 1016185db85Sdougm nfs_get_status, 1026185db85Sdougm nfs_space_alias, 103da6c28aaSamw NULL, /* update_legacy */ 104da6c28aaSamw NULL, /* delete_legacy */ 105da6c28aaSamw NULL, /* change_notify */ 106da6c28aaSamw NULL, /* enable_resource */ 107da6c28aaSamw NULL, /* disable_resource */ 108da6c28aaSamw nfs_features, 109da6c28aaSamw NULL, /* transient shares */ 110da6c28aaSamw NULL, /* notify resource */ 1114bff34e3Sthurlow NULL, /* rename_resource */ 1124bff34e3Sthurlow NULL, /* run_command */ 1134bff34e3Sthurlow NULL, /* command_help */ 1144bff34e3Sthurlow NULL /* delete_proto_section */ 1156185db85Sdougm }; 1166185db85Sdougm 1176185db85Sdougm /* 1186185db85Sdougm * list of support services needed 1196185db85Sdougm * defines should come from head/rpcsvc/daemon_utils.h 1206185db85Sdougm */ 1216185db85Sdougm 1226185db85Sdougm static char *service_list_default[] = 1232f172c55SRobert Thurlow { STATD, LOCKD, MOUNTD, NFSD, NFSMAPID, RQUOTAD, REPARSED, NULL }; 1246185db85Sdougm static char *service_list_logging[] = 1252f172c55SRobert Thurlow { STATD, LOCKD, MOUNTD, NFSD, NFSMAPID, RQUOTAD, NFSLOGD, REPARSED, 1262f172c55SRobert Thurlow NULL }; 1276185db85Sdougm 1286185db85Sdougm /* 1296185db85Sdougm * option definitions. Make sure to keep the #define for the option 1306185db85Sdougm * index just before the entry it is the index for. Changing the order 1316185db85Sdougm * can cause breakage. E.g OPT_RW is index 1 and must precede the 1326185db85Sdougm * line that includes the SHOPT_RW and OPT_RW entries. 1336185db85Sdougm */ 1346185db85Sdougm 1356185db85Sdougm struct option_defs optdefs[] = { 1366185db85Sdougm #define OPT_RO 0 1376185db85Sdougm {SHOPT_RO, OPT_RO, OPT_TYPE_ACCLIST}, 1386185db85Sdougm #define OPT_RW 1 1396185db85Sdougm {SHOPT_RW, OPT_RW, OPT_TYPE_ACCLIST}, 1406185db85Sdougm #define OPT_ROOT 2 1416185db85Sdougm {SHOPT_ROOT, OPT_ROOT, OPT_TYPE_ACCLIST}, 1426185db85Sdougm #define OPT_SECURE 3 1436185db85Sdougm {SHOPT_SECURE, OPT_SECURE, OPT_TYPE_DEPRECATED}, 1446185db85Sdougm #define OPT_ANON 4 1456185db85Sdougm {SHOPT_ANON, OPT_ANON, OPT_TYPE_USER}, 1466185db85Sdougm #define OPT_WINDOW 5 1476185db85Sdougm {SHOPT_WINDOW, OPT_WINDOW, OPT_TYPE_NUMBER}, 1486185db85Sdougm #define OPT_NOSUID 6 1496185db85Sdougm {SHOPT_NOSUID, OPT_NOSUID, OPT_TYPE_BOOLEAN}, 1506185db85Sdougm #define OPT_ACLOK 7 1516185db85Sdougm {SHOPT_ACLOK, OPT_ACLOK, OPT_TYPE_BOOLEAN}, 1526185db85Sdougm #define OPT_NOSUB 8 1536185db85Sdougm {SHOPT_NOSUB, OPT_NOSUB, OPT_TYPE_BOOLEAN}, 1546185db85Sdougm #define OPT_SEC 9 1556185db85Sdougm {SHOPT_SEC, OPT_SEC, OPT_TYPE_SECURITY}, 1566185db85Sdougm #define OPT_PUBLIC 10 1576185db85Sdougm {SHOPT_PUBLIC, OPT_PUBLIC, OPT_TYPE_BOOLEAN, OPT_SHARE_ONLY}, 1586185db85Sdougm #define OPT_INDEX 11 1596185db85Sdougm {SHOPT_INDEX, OPT_INDEX, OPT_TYPE_FILE}, 1606185db85Sdougm #define OPT_LOG 12 1616185db85Sdougm {SHOPT_LOG, OPT_LOG, OPT_TYPE_LOGTAG}, 1626185db85Sdougm #define OPT_CKSUM 13 1636185db85Sdougm {SHOPT_CKSUM, OPT_CKSUM, OPT_TYPE_STRINGSET}, 164b89a8333Snatalie li - Sun Microsystems - Irvine United States #define OPT_NONE 14 165b89a8333Snatalie li - Sun Microsystems - Irvine United States {SHOPT_NONE, OPT_NONE, OPT_TYPE_ACCLIST}, 166b89a8333Snatalie li - Sun Microsystems - Irvine United States #define OPT_ROOT_MAPPING 15 167b89a8333Snatalie li - Sun Microsystems - Irvine United States {SHOPT_ROOT_MAPPING, OPT_ROOT_MAPPING, OPT_TYPE_USER}, 168b89a8333Snatalie li - Sun Microsystems - Irvine United States #define OPT_CHARSET_MAP 16 169b89a8333Snatalie li - Sun Microsystems - Irvine United States {"", OPT_CHARSET_MAP, OPT_TYPE_ACCLIST}, 1706764e83bSVallish Vaidyeshwara #define OPT_NOACLFAB 17 1716764e83bSVallish Vaidyeshwara {SHOPT_NOACLFAB, OPT_NOACLFAB, OPT_TYPE_BOOLEAN}, 1725cb0d679SMarcel Telka #define OPT_UIDMAP 18 1735cb0d679SMarcel Telka {SHOPT_UIDMAP, OPT_UIDMAP, OPT_TYPE_MAPPING}, 1745cb0d679SMarcel Telka #define OPT_GIDMAP 19 1755cb0d679SMarcel Telka {SHOPT_GIDMAP, OPT_GIDMAP, OPT_TYPE_MAPPING}, 1766185db85Sdougm #ifdef VOLATILE_FH_TEST /* XXX added for testing volatile fh's only */ 1775cb0d679SMarcel Telka #define OPT_VOLFH 20 1786185db85Sdougm {SHOPT_VOLFH, OPT_VOLFH}, 1796185db85Sdougm #endif /* VOLATILE_FH_TEST */ 1806185db85Sdougm NULL 1816185db85Sdougm }; 1826185db85Sdougm 183b89a8333Snatalie li - Sun Microsystems - Irvine United States /* 184b89a8333Snatalie li - Sun Microsystems - Irvine United States * Codesets that may need to be converted to UTF-8 for file paths. 185b89a8333Snatalie li - Sun Microsystems - Irvine United States * Add new names here to add new property support. If we ever get a 186b89a8333Snatalie li - Sun Microsystems - Irvine United States * way to query the kernel for character sets, this should become 187b89a8333Snatalie li - Sun Microsystems - Irvine United States * dynamically loaded. Make sure changes here are reflected in 188b89a8333Snatalie li - Sun Microsystems - Irvine United States * cmd/fs.d/nfs/mountd/nfscmd.c 189b89a8333Snatalie li - Sun Microsystems - Irvine United States */ 190b89a8333Snatalie li - Sun Microsystems - Irvine United States 191b89a8333Snatalie li - Sun Microsystems - Irvine United States static char *legal_conv[] = { 192b89a8333Snatalie li - Sun Microsystems - Irvine United States "euc-cn", 193b89a8333Snatalie li - Sun Microsystems - Irvine United States "euc-jp", 194b89a8333Snatalie li - Sun Microsystems - Irvine United States "euc-jpms", 195b89a8333Snatalie li - Sun Microsystems - Irvine United States "euc-kr", 196b89a8333Snatalie li - Sun Microsystems - Irvine United States "euc-tw", 197b89a8333Snatalie li - Sun Microsystems - Irvine United States "iso8859-1", 198b89a8333Snatalie li - Sun Microsystems - Irvine United States "iso8859-2", 199b89a8333Snatalie li - Sun Microsystems - Irvine United States "iso8859-5", 200b89a8333Snatalie li - Sun Microsystems - Irvine United States "iso8859-6", 201b89a8333Snatalie li - Sun Microsystems - Irvine United States "iso8859-7", 202b89a8333Snatalie li - Sun Microsystems - Irvine United States "iso8859-8", 203b89a8333Snatalie li - Sun Microsystems - Irvine United States "iso8859-9", 204b89a8333Snatalie li - Sun Microsystems - Irvine United States "iso8859-13", 205b89a8333Snatalie li - Sun Microsystems - Irvine United States "iso8859-15", 206b89a8333Snatalie li - Sun Microsystems - Irvine United States "koi8-r", 207b89a8333Snatalie li - Sun Microsystems - Irvine United States NULL 208b89a8333Snatalie li - Sun Microsystems - Irvine United States }; 209b89a8333Snatalie li - Sun Microsystems - Irvine United States 2106185db85Sdougm /* 211a99982a7Sdougm * list of properties that are related to security flavors. 2126185db85Sdougm */ 2136185db85Sdougm static char *seclist[] = { 2146185db85Sdougm SHOPT_RO, 2156185db85Sdougm SHOPT_RW, 2166185db85Sdougm SHOPT_ROOT, 2176185db85Sdougm SHOPT_WINDOW, 218b89a8333Snatalie li - Sun Microsystems - Irvine United States SHOPT_NONE, 219b89a8333Snatalie li - Sun Microsystems - Irvine United States SHOPT_ROOT_MAPPING, 2205cb0d679SMarcel Telka SHOPT_UIDMAP, 2215cb0d679SMarcel Telka SHOPT_GIDMAP, 2226185db85Sdougm NULL 2236185db85Sdougm }; 2246185db85Sdougm 2256185db85Sdougm /* structure for list of securities */ 2266185db85Sdougm struct securities { 227a99982a7Sdougm sa_security_t security; 228a99982a7Sdougm struct securities *next; 2296185db85Sdougm }; 2306185db85Sdougm 231b89a8333Snatalie li - Sun Microsystems - Irvine United States /* 232b89a8333Snatalie li - Sun Microsystems - Irvine United States * findcharset(charset) 233b89a8333Snatalie li - Sun Microsystems - Irvine United States * 234b89a8333Snatalie li - Sun Microsystems - Irvine United States * Returns B_TRUE if the charset is a legal conversion otherwise 235b89a8333Snatalie li - Sun Microsystems - Irvine United States * B_FALSE. This will need to be rewritten to be more efficient when 236b89a8333Snatalie li - Sun Microsystems - Irvine United States * we have a dynamic list of legal conversions. 237b89a8333Snatalie li - Sun Microsystems - Irvine United States */ 238b89a8333Snatalie li - Sun Microsystems - Irvine United States 239b89a8333Snatalie li - Sun Microsystems - Irvine United States static boolean_t 240b89a8333Snatalie li - Sun Microsystems - Irvine United States findcharset(char *charset) 241b89a8333Snatalie li - Sun Microsystems - Irvine United States { 242b89a8333Snatalie li - Sun Microsystems - Irvine United States int i; 243b89a8333Snatalie li - Sun Microsystems - Irvine United States 244b89a8333Snatalie li - Sun Microsystems - Irvine United States for (i = 0; legal_conv[i] != NULL; i++) 245b89a8333Snatalie li - Sun Microsystems - Irvine United States if (strcmp(charset, legal_conv[i]) == 0) 246b89a8333Snatalie li - Sun Microsystems - Irvine United States return (B_TRUE); 247b89a8333Snatalie li - Sun Microsystems - Irvine United States return (B_FALSE); 248b89a8333Snatalie li - Sun Microsystems - Irvine United States } 249b89a8333Snatalie li - Sun Microsystems - Irvine United States 2506185db85Sdougm /* 2516185db85Sdougm * findopt(name) 2526185db85Sdougm * 2536185db85Sdougm * Lookup option "name" in the option table and return the table 2546185db85Sdougm * index. 2556185db85Sdougm */ 2566185db85Sdougm 2576185db85Sdougm static int 2586185db85Sdougm findopt(char *name) 2596185db85Sdougm { 2606185db85Sdougm int i; 2616185db85Sdougm if (name != NULL) { 262a3351425Sdougm for (i = 0; optdefs[i].tag != NULL; i++) { 263a3351425Sdougm if (strcmp(optdefs[i].tag, name) == 0) 26487da98afSVitaliy Gusev return (optdefs[i].index); 265a3351425Sdougm } 266b89a8333Snatalie li - Sun Microsystems - Irvine United States if (findcharset(name)) 267b89a8333Snatalie li - Sun Microsystems - Irvine United States return (OPT_CHARSET_MAP); 2686185db85Sdougm } 2696185db85Sdougm return (-1); 2706185db85Sdougm } 2716185db85Sdougm 2726185db85Sdougm /* 2736185db85Sdougm * gettype(name) 2746185db85Sdougm * 2756185db85Sdougm * Return the type of option "name". 2766185db85Sdougm */ 2776185db85Sdougm 2786185db85Sdougm static int 2796185db85Sdougm gettype(char *name) 2806185db85Sdougm { 2816185db85Sdougm int optdef; 2826185db85Sdougm 2836185db85Sdougm optdef = findopt(name); 2846185db85Sdougm if (optdef != -1) 285a3351425Sdougm return (optdefs[optdef].type); 2866185db85Sdougm return (OPT_TYPE_ANY); 2876185db85Sdougm } 2886185db85Sdougm 2896185db85Sdougm /* 2906185db85Sdougm * nfs_validate_security_mode(mode) 2916185db85Sdougm * 2926185db85Sdougm * is the specified mode string a valid one for use with NFS? 2936185db85Sdougm */ 2946185db85Sdougm 2956185db85Sdougm static int 2966185db85Sdougm nfs_validate_security_mode(char *mode) 2976185db85Sdougm { 2986185db85Sdougm seconfig_t secinfo; 2996185db85Sdougm int err; 3006185db85Sdougm 3016185db85Sdougm (void) memset(&secinfo, '\0', sizeof (secinfo)); 3026185db85Sdougm err = nfs_getseconfig_byname(mode, &secinfo); 3036185db85Sdougm if (err == SC_NOERROR) 304a3351425Sdougm return (1); 3056185db85Sdougm return (0); 3066185db85Sdougm } 3076185db85Sdougm 3086185db85Sdougm /* 3096185db85Sdougm * nfs_is_security_opt(tok) 3106185db85Sdougm * 3116185db85Sdougm * check to see if tok represents an option that is only valid in some 3126185db85Sdougm * security flavor. 3136185db85Sdougm */ 3146185db85Sdougm 3156185db85Sdougm static int 3166185db85Sdougm nfs_is_security_opt(char *tok) 3176185db85Sdougm { 3186185db85Sdougm int i; 3196185db85Sdougm 3206185db85Sdougm for (i = 0; seclist[i] != NULL; i++) { 321a3351425Sdougm if (strcmp(tok, seclist[i]) == 0) 322a3351425Sdougm return (1); 3236185db85Sdougm } 3246185db85Sdougm return (0); 3256185db85Sdougm } 3266185db85Sdougm 3276185db85Sdougm /* 3286185db85Sdougm * find_security(seclist, sec) 3296185db85Sdougm * 3306185db85Sdougm * Walk the current list of security flavors and return true if it is 3316185db85Sdougm * present, else return false. 3326185db85Sdougm */ 3336185db85Sdougm 3346185db85Sdougm static int 3356185db85Sdougm find_security(struct securities *seclist, sa_security_t sec) 3366185db85Sdougm { 3376185db85Sdougm while (seclist != NULL) { 338a3351425Sdougm if (seclist->security == sec) 339a3351425Sdougm return (1); 340a3351425Sdougm seclist = seclist->next; 3416185db85Sdougm } 3426185db85Sdougm return (0); 3436185db85Sdougm } 3446185db85Sdougm 3456185db85Sdougm /* 3466185db85Sdougm * make_security_list(group, securitymodes, proto) 3476185db85Sdougm * go through the list of securitymodes and add them to the 3486185db85Sdougm * group's list of security optionsets. We also keep a list of 3496185db85Sdougm * those optionsets so we don't have to find them later. All of 3506185db85Sdougm * these will get copies of the same properties. 3516185db85Sdougm */ 3526185db85Sdougm 3536185db85Sdougm static struct securities * 3546185db85Sdougm make_security_list(sa_group_t group, char *securitymodes, char *proto) 3556185db85Sdougm { 3566185db85Sdougm char *tok, *next = NULL; 3576185db85Sdougm struct securities *curp, *headp = NULL, *prev; 3586185db85Sdougm sa_security_t check; 3596185db85Sdougm int freetok = 0; 3606185db85Sdougm 3616185db85Sdougm for (tok = securitymodes; tok != NULL; tok = next) { 362a3351425Sdougm next = strchr(tok, ':'); 363a3351425Sdougm if (next != NULL) 364a3351425Sdougm *next++ = '\0'; 365a3351425Sdougm if (strcmp(tok, "default") == 0) { 366a3351425Sdougm /* resolve default into the real type */ 367a3351425Sdougm tok = nfs_space_alias(tok); 368a3351425Sdougm freetok = 1; 369a3351425Sdougm } 370a3351425Sdougm check = sa_get_security(group, tok, proto); 371a3351425Sdougm 372a3351425Sdougm /* add to the security list if it isn't there already */ 373a3351425Sdougm if (check == NULL || !find_security(headp, check)) { 374a3351425Sdougm curp = (struct securities *)calloc(1, 375a3351425Sdougm sizeof (struct securities)); 376a3351425Sdougm if (curp != NULL) { 377a3351425Sdougm if (check == NULL) { 378a3351425Sdougm curp->security = sa_create_security( 379a3351425Sdougm group, tok, proto); 380a3351425Sdougm } else { 381a3351425Sdougm curp->security = check; 382a3351425Sdougm } 383a3351425Sdougm /* 384a3351425Sdougm * note that the first time through the loop, 385a3351425Sdougm * headp will be NULL and prev will be 386a3351425Sdougm * undefined. Since headp is NULL, we set 387a3351425Sdougm * both it and prev to the curp (first 388a3351425Sdougm * structure to be allocated). 389a3351425Sdougm * 390a3351425Sdougm * later passes through the loop will have 391a3351425Sdougm * headp not being NULL and prev will be used 392a3351425Sdougm * to allocate at the end of the list. 393a3351425Sdougm */ 394a3351425Sdougm if (headp == NULL) { 395a3351425Sdougm headp = curp; 396a3351425Sdougm prev = curp; 397a3351425Sdougm } else { 398a3351425Sdougm prev->next = curp; 399a3351425Sdougm prev = curp; 400a3351425Sdougm } 401a3351425Sdougm } 4026185db85Sdougm } 403a99982a7Sdougm 404a3351425Sdougm if (freetok) { 405a3351425Sdougm freetok = 0; 406a3351425Sdougm sa_free_attr_string(tok); 407a3351425Sdougm } 4086185db85Sdougm } 4096185db85Sdougm return (headp); 4106185db85Sdougm } 4116185db85Sdougm 4126185db85Sdougm static void 4136185db85Sdougm free_security_list(struct securities *sec) 4146185db85Sdougm { 4156185db85Sdougm struct securities *next; 4166185db85Sdougm if (sec != NULL) { 417a3351425Sdougm for (next = sec->next; sec != NULL; sec = next) { 418a3351425Sdougm next = sec->next; 419a3351425Sdougm free(sec); 420a3351425Sdougm } 4216185db85Sdougm } 4226185db85Sdougm } 4236185db85Sdougm 4246185db85Sdougm /* 4256185db85Sdougm * nfs_alistcat(str1, str2, sep) 4266185db85Sdougm * 4276185db85Sdougm * concatenate str1 and str2 into a new string using sep as a separate 4286185db85Sdougm * character. If memory allocation fails, return NULL; 4296185db85Sdougm */ 4306185db85Sdougm 4316185db85Sdougm static char * 4326185db85Sdougm nfs_alistcat(char *str1, char *str2, char sep) 4336185db85Sdougm { 4346185db85Sdougm char *newstr; 4356185db85Sdougm size_t len; 4366185db85Sdougm 4376185db85Sdougm len = strlen(str1) + strlen(str2) + 2; 4386185db85Sdougm newstr = (char *)malloc(len); 4396185db85Sdougm if (newstr != NULL) 440a3351425Sdougm (void) snprintf(newstr, len, "%s%c%s", str1, sep, str2); 4416185db85Sdougm return (newstr); 4426185db85Sdougm } 4436185db85Sdougm 4446185db85Sdougm /* 4455cb0d679SMarcel Telka * add_security_prop(sec, name, value, persist, iszfs) 4466185db85Sdougm * 4476185db85Sdougm * Add the property to the securities structure. This accumulates 4486185db85Sdougm * properties for as part of parsing legacy options. 4496185db85Sdougm */ 4506185db85Sdougm 4516185db85Sdougm static int 4526185db85Sdougm add_security_prop(struct securities *sec, char *name, char *value, 453*f091aea1SYuri Pankov int persist, int iszfs) 4546185db85Sdougm { 4556185db85Sdougm sa_property_t prop; 4566185db85Sdougm int ret = SA_OK; 4576185db85Sdougm 4586185db85Sdougm for (; sec != NULL; sec = sec->next) { 459a3351425Sdougm if (value == NULL) { 460a3351425Sdougm if (strcmp(name, SHOPT_RW) == 0 || 461a3351425Sdougm strcmp(name, SHOPT_RO) == 0) 462a3351425Sdougm value = "*"; 463a3351425Sdougm else 464a3351425Sdougm value = "true"; 465a3351425Sdougm } 466a99982a7Sdougm 467a99982a7Sdougm /* 468a99982a7Sdougm * Get the existing property, if it exists, so we can 469a99982a7Sdougm * determine what to do with it. The ro/rw/root 470a99982a7Sdougm * properties can be merged if multiple instances of 471a99982a7Sdougm * these properies are given. For example, if "rw" 472a99982a7Sdougm * exists with a value "host1" and a later token of 473a99982a7Sdougm * rw="host2" is seen, the values are merged into a 474a99982a7Sdougm * single rw="host1:host2". 475a99982a7Sdougm */ 476a3351425Sdougm prop = sa_get_property(sec->security, name); 477a99982a7Sdougm 478a3351425Sdougm if (prop != NULL) { 479a3351425Sdougm char *oldvalue; 480a3351425Sdougm char *newvalue; 481a99982a7Sdougm 482a99982a7Sdougm /* 4835cb0d679SMarcel Telka * The security options of ro/rw/root/uidmap/gidmap 4845cb0d679SMarcel Telka * might appear multiple times. If they do, the values 4855cb0d679SMarcel Telka * need to be merged. If it was previously empty, the 4865cb0d679SMarcel Telka * new value alone is added. 487a99982a7Sdougm */ 488a3351425Sdougm oldvalue = sa_get_property_attr(prop, "value"); 489a3351425Sdougm if (oldvalue != NULL) { 4905cb0d679SMarcel Telka char sep = ':'; 4915cb0d679SMarcel Telka 4925cb0d679SMarcel Telka if (strcmp(name, SHOPT_UIDMAP) == 0 || 4935cb0d679SMarcel Telka strcmp(name, SHOPT_GIDMAP) == 0) 4945cb0d679SMarcel Telka sep = '~'; 4955cb0d679SMarcel Telka 496a3351425Sdougm /* 497a3351425Sdougm * The general case is to concatenate the new 498a3351425Sdougm * value onto the old value for multiple 4995cb0d679SMarcel Telka * rw(ro/root/uidmap/gidmap) properties. For 5005cb0d679SMarcel Telka * rw/ro/root a special case exists when either 5015cb0d679SMarcel Telka * the old or new is the "all" case. In the 5025cb0d679SMarcel Telka * special case, if both are "all", then it is 5035cb0d679SMarcel Telka * "all", else if one is an access-list, that 5045cb0d679SMarcel Telka * replaces the "all". 505a3351425Sdougm */ 506a3351425Sdougm if (strcmp(oldvalue, "*") == 0) { 507a3351425Sdougm /* Replace old value with new value. */ 508a3351425Sdougm newvalue = strdup(value); 50997df5ac9Sdougm } else if (strcmp(value, "*") == 0 || 51097df5ac9Sdougm strcmp(oldvalue, value) == 0) { 511a3351425Sdougm /* 512a3351425Sdougm * Keep old value and ignore 513a3351425Sdougm * the new value. 514a3351425Sdougm */ 515a3351425Sdougm newvalue = NULL; 516a3351425Sdougm } else { 517a3351425Sdougm /* 518a3351425Sdougm * Make a new list of old plus new 519a3351425Sdougm * access-list. 520a3351425Sdougm */ 521a3351425Sdougm newvalue = nfs_alistcat(oldvalue, 5225cb0d679SMarcel Telka value, sep); 523a3351425Sdougm } 524a3351425Sdougm 525a3351425Sdougm if (newvalue != NULL) { 526a3351425Sdougm (void) sa_remove_property(prop); 527a3351425Sdougm prop = sa_create_property(name, 528a3351425Sdougm newvalue); 529a3351425Sdougm ret = sa_add_property(sec->security, 530a3351425Sdougm prop); 531a3351425Sdougm free(newvalue); 532a3351425Sdougm } 5335cb0d679SMarcel Telka 5345cb0d679SMarcel Telka sa_free_attr_string(oldvalue); 535a3351425Sdougm } 536a3351425Sdougm } else { 537a3351425Sdougm prop = sa_create_property(name, value); 538a99982a7Sdougm ret = sa_add_property(sec->security, prop); 5396185db85Sdougm } 540a3351425Sdougm if (ret == SA_OK && !iszfs) { 541a3351425Sdougm ret = sa_commit_properties(sec->security, !persist); 542a3351425Sdougm } 5436185db85Sdougm } 5446185db85Sdougm return (ret); 5456185db85Sdougm } 5466185db85Sdougm 5476185db85Sdougm /* 5486185db85Sdougm * check to see if group/share is persistent. 5496185db85Sdougm */ 5506185db85Sdougm static int 5516185db85Sdougm is_persistent(sa_group_t group) 5526185db85Sdougm { 5536185db85Sdougm char *type; 5546185db85Sdougm int persist = 1; 5556185db85Sdougm 5566185db85Sdougm type = sa_get_group_attr(group, "type"); 5576185db85Sdougm if (type != NULL && strcmp(type, "persist") != 0) 558a3351425Sdougm persist = 0; 5596185db85Sdougm if (type != NULL) 560a3351425Sdougm sa_free_attr_string(type); 5616185db85Sdougm return (persist); 5626185db85Sdougm } 5636185db85Sdougm 5646185db85Sdougm /* 5656185db85Sdougm * invalid_security(options) 5666185db85Sdougm * 5676185db85Sdougm * search option string for any invalid sec= type. 5686185db85Sdougm * return true (1) if any are not valid else false (0) 5696185db85Sdougm */ 5706185db85Sdougm static int 5716185db85Sdougm invalid_security(char *options) 5726185db85Sdougm { 5736185db85Sdougm char *copy, *base, *token, *value; 5746185db85Sdougm int ret = 0; 5756185db85Sdougm 5766185db85Sdougm copy = strdup(options); 5776185db85Sdougm token = base = copy; 5786185db85Sdougm while (token != NULL && ret == 0) { 579a3351425Sdougm token = strtok(base, ","); 580a3351425Sdougm base = NULL; 581a3351425Sdougm if (token != NULL) { 582a3351425Sdougm value = strchr(token, '='); 583a3351425Sdougm if (value != NULL) 584a3351425Sdougm *value++ = '\0'; 5855cb0d679SMarcel Telka if (strcmp(token, SHOPT_SEC) == 0) { 586a3351425Sdougm /* HAVE security flavors so check them */ 587a3351425Sdougm char *tok, *next; 588a3351425Sdougm for (next = NULL, tok = value; tok != NULL; 589a3351425Sdougm tok = next) { 590a3351425Sdougm next = strchr(tok, ':'); 591a3351425Sdougm if (next != NULL) 592a3351425Sdougm *next++ = '\0'; 593a3351425Sdougm ret = !nfs_validate_security_mode(tok); 594a3351425Sdougm if (ret) 595a3351425Sdougm break; 596a3351425Sdougm } 597a3351425Sdougm } 5986185db85Sdougm } 5996185db85Sdougm } 6006185db85Sdougm if (copy != NULL) 601a3351425Sdougm free(copy); 6026185db85Sdougm return (ret); 6036185db85Sdougm } 6046185db85Sdougm 6056185db85Sdougm /* 6066185db85Sdougm * nfs_parse_legacy_options(group, options) 6076185db85Sdougm * 6086185db85Sdougm * Parse the old style options into internal format and store on the 6096185db85Sdougm * specified group. Group could be a share for full legacy support. 6106185db85Sdougm */ 6116185db85Sdougm 6126185db85Sdougm static int 6136185db85Sdougm nfs_parse_legacy_options(sa_group_t group, char *options) 6146185db85Sdougm { 615aba7a40bSdougm char *dup; 6166185db85Sdougm char *base; 6176185db85Sdougm char *token; 6186185db85Sdougm sa_optionset_t optionset; 6196185db85Sdougm struct securities *security_list = NULL; 6206185db85Sdougm sa_property_t prop; 6216185db85Sdougm int ret = SA_OK; 6226185db85Sdougm int iszfs = 0; 6236185db85Sdougm sa_group_t parent; 6246185db85Sdougm int persist = 0; 6256185db85Sdougm char *lasts; 6266185db85Sdougm 6276185db85Sdougm /* do we have an existing optionset? */ 6286185db85Sdougm optionset = sa_get_optionset(group, "nfs"); 6296185db85Sdougm if (optionset == NULL) { 630a3351425Sdougm /* didn't find existing optionset so create one */ 631a3351425Sdougm optionset = sa_create_optionset(group, "nfs"); 6326185db85Sdougm } else { 6336185db85Sdougm /* 634da6c28aaSamw * Have an existing optionset . Ideally, we would need 635da6c28aaSamw * to compare options in order to detect errors. For 636da6c28aaSamw * now, we assume that the first optionset is the 637da6c28aaSamw * correct one and the others will be the same. An 638da6c28aaSamw * empty optionset is the same as no optionset so we 639da6c28aaSamw * don't want to exit in that case. Getting an empty 640da6c28aaSamw * optionset can occur with ZFS property checking. 6416185db85Sdougm */ 642da6c28aaSamw if (sa_get_property(optionset, NULL) != NULL) 643da6c28aaSamw return (ret); 6446185db85Sdougm } 6456185db85Sdougm 6466185db85Sdougm if (strcmp(options, SHOPT_RW) == 0) { 6476185db85Sdougm /* 6486185db85Sdougm * there is a special case of only the option "rw" 6496185db85Sdougm * being the default option. We don't have to do 6506185db85Sdougm * anything. 6516185db85Sdougm */ 652a3351425Sdougm return (ret); 6536185db85Sdougm } 6546185db85Sdougm 6556185db85Sdougm /* 6566185db85Sdougm * check if security types are present and validate them. If 6576185db85Sdougm * any are not legal, fail. 6586185db85Sdougm */ 6596185db85Sdougm 6606185db85Sdougm if (invalid_security(options)) { 661a3351425Sdougm return (SA_INVALID_SECURITY); 6626185db85Sdougm } 6636185db85Sdougm 6646185db85Sdougm /* 6656185db85Sdougm * in order to not attempt to change ZFS properties unless 6666185db85Sdougm * absolutely necessary, we never do it in the legacy parsing. 6676185db85Sdougm */ 6686185db85Sdougm if (sa_is_share(group)) { 669a3351425Sdougm char *zfs; 670a3351425Sdougm parent = sa_get_parent_group(group); 671a3351425Sdougm if (parent != NULL) { 672a3351425Sdougm zfs = sa_get_group_attr(parent, "zfs"); 673a3351425Sdougm if (zfs != NULL) { 674a3351425Sdougm sa_free_attr_string(zfs); 675a3351425Sdougm iszfs++; 676a3351425Sdougm } 6776185db85Sdougm } 6786185db85Sdougm } else { 679a3351425Sdougm iszfs = sa_group_is_zfs(group); 6806185db85Sdougm } 6816185db85Sdougm 682aba7a40bSdougm /* We need a copy of options for the next part. */ 683aba7a40bSdougm dup = strdup(options); 684aba7a40bSdougm if (dup == NULL) 685aba7a40bSdougm return (SA_NO_MEMORY); 686aba7a40bSdougm 6876185db85Sdougm /* 6886185db85Sdougm * we need to step through each option in the string and then 6896185db85Sdougm * add either the option or the security option as needed. If 6906185db85Sdougm * this is not a persistent share, don't commit to the 691a99982a7Sdougm * repository. If there is an error, we also want to abort the 692a99982a7Sdougm * processing and report it. 6936185db85Sdougm */ 6946185db85Sdougm persist = is_persistent(group); 6956185db85Sdougm base = dup; 6966185db85Sdougm token = dup; 6976185db85Sdougm lasts = NULL; 698a99982a7Sdougm while (token != NULL && ret == SA_OK) { 699a3351425Sdougm token = strtok_r(base, ",", &lasts); 700a3351425Sdougm base = NULL; 701a3351425Sdougm if (token != NULL) { 702a3351425Sdougm char *value; 7036185db85Sdougm /* 704a3351425Sdougm * if the option has a value, it will have an '=' to 705a3351425Sdougm * separate the name from the value. The following 706a3351425Sdougm * code will result in value != NULL and token 707a3351425Sdougm * pointing to just the name if there is a value. 7086185db85Sdougm */ 709a3351425Sdougm value = strchr(token, '='); 710a3351425Sdougm if (value != NULL) { 711a3351425Sdougm *value++ = '\0'; 7126185db85Sdougm } 7135cb0d679SMarcel Telka if (strcmp(token, SHOPT_SEC) == 0 || 7145cb0d679SMarcel Telka strcmp(token, SHOPT_SECURE) == 0) { 7156185db85Sdougm /* 716a3351425Sdougm * Once in security parsing, we only 717a3351425Sdougm * do security. We do need to move 718a3351425Sdougm * between the security node and the 719a3351425Sdougm * toplevel. The security tag goes on 720a3351425Sdougm * the root while the following ones 721a3351425Sdougm * go on the security. 7226185db85Sdougm */ 723a3351425Sdougm if (security_list != NULL) { 724a3351425Sdougm /* 725a3351425Sdougm * have an old list so close it and 726a3351425Sdougm * start the new 727a3351425Sdougm */ 728a3351425Sdougm free_security_list(security_list); 729a3351425Sdougm } 7305cb0d679SMarcel Telka if (strcmp(token, SHOPT_SECURE) == 0) { 731a3351425Sdougm value = "dh"; 732a3351425Sdougm } else { 733a3351425Sdougm if (value == NULL) { 734a3351425Sdougm ret = SA_SYNTAX_ERR; 735a3351425Sdougm break; 736a3351425Sdougm } 737a3351425Sdougm } 738a3351425Sdougm security_list = make_security_list(group, 739a3351425Sdougm value, "nfs"); 7406185db85Sdougm } else { 741a3351425Sdougm /* 742a3351425Sdougm * Note that the "old" syntax allowed a 7435cb0d679SMarcel Telka * default security model. This must be 744a3351425Sdougm * accounted for and internally converted to 745a3351425Sdougm * "standard" security structure. 746a3351425Sdougm */ 747a3351425Sdougm if (nfs_is_security_opt(token)) { 748a3351425Sdougm if (security_list == NULL) { 749a3351425Sdougm /* 750a3351425Sdougm * need to have a 751a3351425Sdougm * security 752a3351425Sdougm * option. This will 753a3351425Sdougm * be "closed" when a 754a3351425Sdougm * defined "sec=" 755a3351425Sdougm * option is 756a3351425Sdougm * seen. This is 757a3351425Sdougm * technically an 758a3351425Sdougm * error but will be 759a3351425Sdougm * allowed with 760a3351425Sdougm * warning. 761a3351425Sdougm */ 762a3351425Sdougm security_list = 763a3351425Sdougm make_security_list(group, 764a3351425Sdougm "default", 765a3351425Sdougm "nfs"); 766a3351425Sdougm } 767a3351425Sdougm if (security_list != NULL) { 768a3351425Sdougm ret = add_security_prop( 769a3351425Sdougm security_list, token, 770a3351425Sdougm value, persist, iszfs); 771a3351425Sdougm } else { 772a3351425Sdougm ret = SA_NO_MEMORY; 773a3351425Sdougm } 774a3351425Sdougm } else { 775a3351425Sdougm /* regular options */ 776a3351425Sdougm if (value == NULL) { 777a3351425Sdougm if (strcmp(token, SHOPT_RW) == 778a3351425Sdougm 0 || strcmp(token, 779a3351425Sdougm SHOPT_RO) == 0) { 780a3351425Sdougm value = "*"; 781a3351425Sdougm } else { 782a3351425Sdougm value = "global"; 783a3351425Sdougm if (strcmp(token, 784a3351425Sdougm SHOPT_LOG) != 0) { 785a3351425Sdougm value = "true"; 786a3351425Sdougm } 787a3351425Sdougm } 788a3351425Sdougm } 789d6405362Sdougm /* 790d6405362Sdougm * In all cases, create the 791d6405362Sdougm * property specified. If the 792d6405362Sdougm * value was NULL, the default 793d6405362Sdougm * value will have been 794d6405362Sdougm * substituted. 795d6405362Sdougm */ 796d6405362Sdougm prop = sa_create_property(token, value); 797d6405362Sdougm ret = sa_add_property(optionset, prop); 798d6405362Sdougm if (ret != SA_OK) 799d6405362Sdougm break; 800d6405362Sdougm 801a3351425Sdougm if (!iszfs) { 802a3351425Sdougm ret = sa_commit_properties( 803a3351425Sdougm optionset, !persist); 804a3351425Sdougm } 805a3351425Sdougm } 8066185db85Sdougm } 8076185db85Sdougm } 8086185db85Sdougm } 8096185db85Sdougm if (security_list != NULL) 810a3351425Sdougm free_security_list(security_list); 811aba7a40bSdougm 812aba7a40bSdougm free(dup); 8136185db85Sdougm return (ret); 8146185db85Sdougm } 8156185db85Sdougm 8166185db85Sdougm /* 8176185db85Sdougm * is_a_number(number) 8186185db85Sdougm * 8196185db85Sdougm * is the string a number in one of the forms we want to use? 8206185db85Sdougm */ 8216185db85Sdougm 8226185db85Sdougm static int 8236185db85Sdougm is_a_number(char *number) 8246185db85Sdougm { 8256185db85Sdougm int ret = 1; 8266185db85Sdougm int hex = 0; 8276185db85Sdougm 8286185db85Sdougm if (strncmp(number, "0x", 2) == 0) { 829a3351425Sdougm number += 2; 830a3351425Sdougm hex = 1; 831a3351425Sdougm } else if (*number == '-') { 832a3351425Sdougm number++; /* skip the minus */ 833a3351425Sdougm } 8346185db85Sdougm while (ret == 1 && *number != '\0') { 835a3351425Sdougm if (hex) { 836a3351425Sdougm ret = isxdigit(*number++); 837a3351425Sdougm } else { 838a3351425Sdougm ret = isdigit(*number++); 839a3351425Sdougm } 8406185db85Sdougm } 8416185db85Sdougm return (ret); 8426185db85Sdougm } 8436185db85Sdougm 8446185db85Sdougm /* 8456185db85Sdougm * Look for the specified tag in the configuration file. If it is found, 8466185db85Sdougm * enable logging and set the logging configuration information for exp. 8476185db85Sdougm */ 8486185db85Sdougm static void 8496185db85Sdougm configlog(struct exportdata *exp, char *tag) 8506185db85Sdougm { 8516185db85Sdougm nfsl_config_t *configlist = NULL, *configp; 8526185db85Sdougm int error = 0; 8536185db85Sdougm char globaltag[] = DEFAULTTAG; 8546185db85Sdougm 8556185db85Sdougm /* 8566185db85Sdougm * Sends config errors to stderr 8576185db85Sdougm */ 8586185db85Sdougm nfsl_errs_to_syslog = B_FALSE; 8596185db85Sdougm 8606185db85Sdougm /* 8616185db85Sdougm * get the list of configuration settings 8626185db85Sdougm */ 8636185db85Sdougm error = nfsl_getconfig_list(&configlist); 8646185db85Sdougm if (error) { 8656185db85Sdougm (void) fprintf(stderr, 866a3351425Sdougm dgettext(TEXT_DOMAIN, "Cannot get log configuration: %s\n"), 867a3351425Sdougm strerror(error)); 8686185db85Sdougm } 8696185db85Sdougm 8706185db85Sdougm if (tag == NULL) 8716185db85Sdougm tag = globaltag; 8726185db85Sdougm if ((configp = nfsl_findconfig(configlist, tag, &error)) == NULL) { 8736185db85Sdougm nfsl_freeconfig_list(&configlist); 8746185db85Sdougm (void) fprintf(stderr, 875a3351425Sdougm dgettext(TEXT_DOMAIN, "No tags matching \"%s\"\n"), tag); 8766185db85Sdougm /* bad configuration */ 8776185db85Sdougm error = ENOENT; 8786185db85Sdougm goto err; 8796185db85Sdougm } 8806185db85Sdougm 8816185db85Sdougm if ((exp->ex_tag = strdup(tag)) == NULL) { 8826185db85Sdougm error = ENOMEM; 8836185db85Sdougm goto out; 8846185db85Sdougm } 8856185db85Sdougm if ((exp->ex_log_buffer = strdup(configp->nc_bufferpath)) == NULL) { 8866185db85Sdougm error = ENOMEM; 8876185db85Sdougm goto out; 8886185db85Sdougm } 8896185db85Sdougm exp->ex_flags |= EX_LOG; 8906185db85Sdougm if (configp->nc_rpclogpath != NULL) 8916185db85Sdougm exp->ex_flags |= EX_LOG_ALLOPS; 8926185db85Sdougm out: 8936185db85Sdougm if (configlist != NULL) 894a3351425Sdougm nfsl_freeconfig_list(&configlist); 8956185db85Sdougm 8966185db85Sdougm err: 8976185db85Sdougm if (error != 0) { 898822e6387SMarcel Telka free(exp->ex_tag); 899822e6387SMarcel Telka free(exp->ex_log_buffer); 9006185db85Sdougm (void) fprintf(stderr, 901a3351425Sdougm dgettext(TEXT_DOMAIN, "Cannot set log configuration: %s\n"), 902a3351425Sdougm strerror(error)); 9036185db85Sdougm } 9046185db85Sdougm } 9056185db85Sdougm 9066185db85Sdougm /* 9076185db85Sdougm * fill_export_from_optionset(export, optionset) 9086185db85Sdougm * 9096185db85Sdougm * In order to share, we need to set all the possible general options 9106185db85Sdougm * into the export structure. Share info will be filled in by the 9116185db85Sdougm * caller. Various property values get turned into structure specific 9126185db85Sdougm * values. 9136185db85Sdougm */ 9146185db85Sdougm 9156185db85Sdougm static int 9166185db85Sdougm fill_export_from_optionset(struct exportdata *export, sa_optionset_t optionset) 9176185db85Sdougm { 9186185db85Sdougm sa_property_t option; 9196185db85Sdougm int ret = SA_OK; 9206185db85Sdougm 9216185db85Sdougm for (option = sa_get_property(optionset, NULL); 922a3351425Sdougm option != NULL; option = sa_get_next_property(option)) { 923a3351425Sdougm char *name; 924a3351425Sdougm char *value; 925a3351425Sdougm uint32_t val; 9266185db85Sdougm 927a3351425Sdougm /* 928a3351425Sdougm * since options may be set/reset multiple times, always do an 929a3351425Sdougm * explicit set or clear of the option. This allows defaults 930da6c28aaSamw * to be set and then the protocol specific to override. 931a3351425Sdougm */ 9326185db85Sdougm 933a3351425Sdougm name = sa_get_property_attr(option, "type"); 934a3351425Sdougm value = sa_get_property_attr(option, "value"); 935a3351425Sdougm switch (findopt(name)) { 936a3351425Sdougm case OPT_ANON: 937a3351425Sdougm if (value != NULL && is_a_number(value)) { 938a3351425Sdougm val = strtoul(value, NULL, 0); 939a3351425Sdougm } else { 940a3351425Sdougm struct passwd *pw; 941a3351425Sdougm pw = getpwnam(value != NULL ? value : "nobody"); 942a3351425Sdougm if (pw != NULL) { 943a3351425Sdougm val = pw->pw_uid; 944a3351425Sdougm } else { 945a3351425Sdougm val = UID_NOBODY; 946a3351425Sdougm } 947a3351425Sdougm endpwent(); 948a3351425Sdougm } 949a3351425Sdougm export->ex_anon = val; 950a3351425Sdougm break; 951a3351425Sdougm case OPT_NOSUID: 952a3351425Sdougm if (value != NULL && (strcasecmp(value, "true") == 0 || 953a3351425Sdougm strcmp(value, "1") == 0)) 954a3351425Sdougm export->ex_flags |= EX_NOSUID; 955a3351425Sdougm else 956a3351425Sdougm export->ex_flags &= ~EX_NOSUID; 957a3351425Sdougm break; 958a3351425Sdougm case OPT_ACLOK: 959a3351425Sdougm if (value != NULL && (strcasecmp(value, "true") == 0 || 960a3351425Sdougm strcmp(value, "1") == 0)) 961a3351425Sdougm export->ex_flags |= EX_ACLOK; 962a3351425Sdougm else 963a3351425Sdougm export->ex_flags &= ~EX_ACLOK; 964a3351425Sdougm break; 965a3351425Sdougm case OPT_NOSUB: 966a3351425Sdougm if (value != NULL && (strcasecmp(value, "true") == 0 || 967a3351425Sdougm strcmp(value, "1") == 0)) 968a3351425Sdougm export->ex_flags |= EX_NOSUB; 969a3351425Sdougm else 970a3351425Sdougm export->ex_flags &= ~EX_NOSUB; 971a3351425Sdougm break; 972a3351425Sdougm case OPT_PUBLIC: 973a3351425Sdougm if (value != NULL && (strcasecmp(value, "true") == 0 || 974a3351425Sdougm strcmp(value, "1") == 0)) 975a3351425Sdougm export->ex_flags |= EX_PUBLIC; 976a3351425Sdougm else 977a3351425Sdougm export->ex_flags &= ~EX_PUBLIC; 978a3351425Sdougm break; 979a3351425Sdougm case OPT_INDEX: 980a3351425Sdougm if (value != NULL && (strcmp(value, "..") == 0 || 981a3351425Sdougm strchr(value, '/') != NULL)) { 982a3351425Sdougm /* this is an error */ 983a3351425Sdougm (void) printf(dgettext(TEXT_DOMAIN, 984a3351425Sdougm "NFS: index=\"%s\" not valid;" 985a3351425Sdougm "must be a filename.\n"), 986a3351425Sdougm value); 987a3351425Sdougm break; 988a3351425Sdougm } 989a3351425Sdougm if (value != NULL && *value != '\0' && 990a3351425Sdougm strcmp(value, ".") != 0) { 991a3351425Sdougm /* valid index file string */ 992a3351425Sdougm if (export->ex_index != NULL) { 993a3351425Sdougm /* left over from "default" */ 994a3351425Sdougm free(export->ex_index); 995a3351425Sdougm } 996a3351425Sdougm /* remember to free */ 997a3351425Sdougm export->ex_index = strdup(value); 998a3351425Sdougm if (export->ex_index == NULL) { 999a3351425Sdougm (void) printf(dgettext(TEXT_DOMAIN, 1000a3351425Sdougm "NFS: out of memory setting " 1001a3351425Sdougm "index property\n")); 1002a3351425Sdougm break; 1003a3351425Sdougm } 1004a3351425Sdougm export->ex_flags |= EX_INDEX; 1005a3351425Sdougm } 1006a3351425Sdougm break; 1007a3351425Sdougm case OPT_LOG: 1008a3351425Sdougm if (value == NULL) 1009a3351425Sdougm value = strdup("global"); 1010a3351425Sdougm if (value != NULL) 1011a3351425Sdougm configlog(export, 1012a3351425Sdougm strlen(value) ? value : "global"); 1013a3351425Sdougm break; 1014b89a8333Snatalie li - Sun Microsystems - Irvine United States case OPT_CHARSET_MAP: 1015b89a8333Snatalie li - Sun Microsystems - Irvine United States /* 1016b89a8333Snatalie li - Sun Microsystems - Irvine United States * Set EX_CHARMAP when there is at least one 1017b89a8333Snatalie li - Sun Microsystems - Irvine United States * charmap conversion property. This will get 1018b89a8333Snatalie li - Sun Microsystems - Irvine United States * checked by the nfs server when it needs to. 1019b89a8333Snatalie li - Sun Microsystems - Irvine United States */ 1020b89a8333Snatalie li - Sun Microsystems - Irvine United States export->ex_flags |= EX_CHARMAP; 1021b89a8333Snatalie li - Sun Microsystems - Irvine United States break; 10226764e83bSVallish Vaidyeshwara case OPT_NOACLFAB: 10236764e83bSVallish Vaidyeshwara if (value != NULL && (strcasecmp(value, "true") == 0 || 10246764e83bSVallish Vaidyeshwara strcmp(value, "1") == 0)) 10256764e83bSVallish Vaidyeshwara export->ex_flags |= EX_NOACLFAB; 10266764e83bSVallish Vaidyeshwara else 10276764e83bSVallish Vaidyeshwara export->ex_flags &= ~EX_NOACLFAB; 10286764e83bSVallish Vaidyeshwara break; 1029a3351425Sdougm default: 1030a3351425Sdougm /* have a syntactic error */ 1031549ec3ffSdougm (void) printf(dgettext(TEXT_DOMAIN, 1032a3351425Sdougm "NFS: unrecognized option %s=%s\n"), 1033fe1c642dSBill Krier name != NULL ? name : "", 1034fe1c642dSBill Krier value != NULL ? value : ""); 10356185db85Sdougm break; 10366185db85Sdougm } 1037a3351425Sdougm if (name != NULL) 1038a3351425Sdougm sa_free_attr_string(name); 10396185db85Sdougm if (value != NULL) 1040a3351425Sdougm sa_free_attr_string(value); 10416185db85Sdougm } 10426185db85Sdougm return (ret); 10436185db85Sdougm } 10446185db85Sdougm 10456185db85Sdougm /* 10466185db85Sdougm * cleanup_export(export) 10476185db85Sdougm * 10486185db85Sdougm * Cleanup the allocated areas so we don't leak memory 10496185db85Sdougm */ 10506185db85Sdougm 10516185db85Sdougm static void 10526185db85Sdougm cleanup_export(struct exportdata *export) 10536185db85Sdougm { 10546185db85Sdougm int i; 10556185db85Sdougm 10563253d86fSMarcel Telka free(export->ex_index); 10573253d86fSMarcel Telka 10583253d86fSMarcel Telka for (i = 0; i < export->ex_seccnt; i++) { 10593253d86fSMarcel Telka struct secinfo *s = &export->ex_secinfo[i]; 10603253d86fSMarcel Telka 10613253d86fSMarcel Telka while (s->s_rootcnt > 0) 10623253d86fSMarcel Telka free(s->s_rootnames[--s->s_rootcnt]); 10633253d86fSMarcel Telka 10643253d86fSMarcel Telka free(s->s_rootnames); 10656185db85Sdougm } 10663253d86fSMarcel Telka free(export->ex_secinfo); 10676185db85Sdougm } 10686185db85Sdougm 10696185db85Sdougm /* 10706185db85Sdougm * Given a seconfig entry and a colon-separated 10716185db85Sdougm * list of names, allocate an array big enough 10726185db85Sdougm * to hold the root list, then convert each name to 10736185db85Sdougm * a principal name according to the security 10746185db85Sdougm * info and assign it to an array element. 10756185db85Sdougm * Return the array and its size. 10766185db85Sdougm */ 10776185db85Sdougm static caddr_t * 10786185db85Sdougm get_rootnames(seconfig_t *sec, char *list, int *count) 10796185db85Sdougm { 10806185db85Sdougm caddr_t *a; 10816185db85Sdougm int c, i; 10826185db85Sdougm char *host, *p; 10836185db85Sdougm 10846185db85Sdougm /* 10856185db85Sdougm * Count the number of strings in the list. 10866185db85Sdougm * This is the number of colon separators + 1. 10876185db85Sdougm */ 10886185db85Sdougm c = 1; 10896185db85Sdougm for (p = list; *p; p++) 10906185db85Sdougm if (*p == ':') 10916185db85Sdougm c++; 10926185db85Sdougm *count = c; 10936185db85Sdougm 10946185db85Sdougm a = (caddr_t *)malloc(c * sizeof (char *)); 10956185db85Sdougm if (a == NULL) { 1096549ec3ffSdougm (void) printf(dgettext(TEXT_DOMAIN, 1097a3351425Sdougm "get_rootnames: no memory\n")); 109807b64d17SMarcel Telka *count = 0; 10996185db85Sdougm } else { 1100a3351425Sdougm for (i = 0; i < c; i++) { 1101a3351425Sdougm host = strtok(list, ":"); 1102a3351425Sdougm if (!nfs_get_root_principal(sec, host, &a[i])) { 11033253d86fSMarcel Telka while (i > 0) 11043253d86fSMarcel Telka free(a[--i]); 1105a3351425Sdougm free(a); 1106a3351425Sdougm a = NULL; 110707b64d17SMarcel Telka *count = 0; 1108a3351425Sdougm break; 1109a3351425Sdougm } 1110a3351425Sdougm list = NULL; 11116185db85Sdougm } 11126185db85Sdougm } 11136185db85Sdougm 11146185db85Sdougm return (a); 11156185db85Sdougm } 11166185db85Sdougm 11176185db85Sdougm /* 11186185db85Sdougm * fill_security_from_secopts(sp, secopts) 11196185db85Sdougm * 11206185db85Sdougm * Fill the secinfo structure from the secopts optionset. 11216185db85Sdougm */ 11226185db85Sdougm 11236185db85Sdougm static int 11246185db85Sdougm fill_security_from_secopts(struct secinfo *sp, sa_security_t secopts) 11256185db85Sdougm { 11266185db85Sdougm sa_property_t prop; 11276185db85Sdougm char *type; 11286185db85Sdougm int longform; 1129a99982a7Sdougm int err = SC_NOERROR; 1130b89a8333Snatalie li - Sun Microsystems - Irvine United States uint32_t val; 11316185db85Sdougm 11326185db85Sdougm type = sa_get_security_attr(secopts, "sectype"); 11336185db85Sdougm if (type != NULL) { 1134a3351425Sdougm /* named security type needs secinfo to be filled in */ 1135a3351425Sdougm err = nfs_getseconfig_byname(type, &sp->s_secinfo); 1136a3351425Sdougm sa_free_attr_string(type); 1137a3351425Sdougm if (err != SC_NOERROR) 1138a3351425Sdougm return (err); 11396185db85Sdougm } else { 1140a3351425Sdougm /* default case */ 1141a3351425Sdougm err = nfs_getseconfig_default(&sp->s_secinfo); 1142a3351425Sdougm if (err != SC_NOERROR) 1143a3351425Sdougm return (err); 11446185db85Sdougm } 11456185db85Sdougm 1146a99982a7Sdougm err = SA_OK; 11476185db85Sdougm for (prop = sa_get_property(secopts, NULL); 1148a3351425Sdougm prop != NULL && err == SA_OK; 1149a3351425Sdougm prop = sa_get_next_property(prop)) { 1150a3351425Sdougm char *name; 1151a3351425Sdougm char *value; 11526185db85Sdougm 1153a3351425Sdougm name = sa_get_property_attr(prop, "type"); 1154a3351425Sdougm value = sa_get_property_attr(prop, "value"); 11556185db85Sdougm 1156a3351425Sdougm longform = value != NULL && strcmp(value, "*") != 0; 11576185db85Sdougm 1158a3351425Sdougm switch (findopt(name)) { 1159a3351425Sdougm case OPT_RO: 1160a3351425Sdougm sp->s_flags |= longform ? M_ROL : M_RO; 1161a3351425Sdougm break; 1162a3351425Sdougm case OPT_RW: 1163a3351425Sdougm sp->s_flags |= longform ? M_RWL : M_RW; 1164a3351425Sdougm break; 1165a3351425Sdougm case OPT_ROOT: 1166a3351425Sdougm sp->s_flags |= M_ROOT; 1167a3351425Sdougm /* 1168a3351425Sdougm * if we are using AUTH_UNIX, handle like other things 1169a3351425Sdougm * such as RO/RW 1170a3351425Sdougm */ 1171a3351425Sdougm if (sp->s_secinfo.sc_rpcnum == AUTH_UNIX) 11726020a1b7SMarcel Telka break; 1173a3351425Sdougm /* not AUTH_UNIX */ 1174a3351425Sdougm if (value != NULL) { 1175a3351425Sdougm sp->s_rootnames = get_rootnames(&sp->s_secinfo, 1176a3351425Sdougm value, &sp->s_rootcnt); 1177a3351425Sdougm if (sp->s_rootnames == NULL) { 1178a3351425Sdougm err = SA_BAD_VALUE; 1179a3351425Sdougm (void) fprintf(stderr, 1180a3351425Sdougm dgettext(TEXT_DOMAIN, 1181a3351425Sdougm "Bad root list\n")); 1182a3351425Sdougm } 1183a3351425Sdougm } 1184a3351425Sdougm break; 1185b89a8333Snatalie li - Sun Microsystems - Irvine United States case OPT_NONE: 1186b89a8333Snatalie li - Sun Microsystems - Irvine United States sp->s_flags |= M_NONE; 1187b89a8333Snatalie li - Sun Microsystems - Irvine United States break; 1188a3351425Sdougm case OPT_WINDOW: 1189a3351425Sdougm if (value != NULL) { 1190a3351425Sdougm sp->s_window = atoi(value); 1191a3351425Sdougm /* just in case */ 1192a3351425Sdougm if (sp->s_window < 0) 1193a3351425Sdougm sp->s_window = DEF_WIN; 1194a3351425Sdougm } 1195a3351425Sdougm break; 1196b89a8333Snatalie li - Sun Microsystems - Irvine United States case OPT_ROOT_MAPPING: 1197b89a8333Snatalie li - Sun Microsystems - Irvine United States if (value != NULL && is_a_number(value)) { 1198b89a8333Snatalie li - Sun Microsystems - Irvine United States val = strtoul(value, NULL, 0); 1199b89a8333Snatalie li - Sun Microsystems - Irvine United States } else { 1200b89a8333Snatalie li - Sun Microsystems - Irvine United States struct passwd *pw; 1201b89a8333Snatalie li - Sun Microsystems - Irvine United States pw = getpwnam(value != NULL ? value : "nobody"); 1202b89a8333Snatalie li - Sun Microsystems - Irvine United States if (pw != NULL) { 1203b89a8333Snatalie li - Sun Microsystems - Irvine United States val = pw->pw_uid; 1204b89a8333Snatalie li - Sun Microsystems - Irvine United States } else { 1205b89a8333Snatalie li - Sun Microsystems - Irvine United States val = UID_NOBODY; 1206b89a8333Snatalie li - Sun Microsystems - Irvine United States } 1207b89a8333Snatalie li - Sun Microsystems - Irvine United States endpwent(); 1208b89a8333Snatalie li - Sun Microsystems - Irvine United States } 1209b89a8333Snatalie li - Sun Microsystems - Irvine United States sp->s_rootid = val; 1210b89a8333Snatalie li - Sun Microsystems - Irvine United States break; 12115cb0d679SMarcel Telka case OPT_UIDMAP: 12125cb0d679SMarcel Telka case OPT_GIDMAP: 12135cb0d679SMarcel Telka sp->s_flags |= M_MAP; 12145cb0d679SMarcel Telka break; 1215a3351425Sdougm default: 1216a3351425Sdougm break; 12176185db85Sdougm } 1218a3351425Sdougm if (name != NULL) 1219a3351425Sdougm sa_free_attr_string(name); 1220a3351425Sdougm if (value != NULL) 1221a3351425Sdougm sa_free_attr_string(value); 12226185db85Sdougm } 12236185db85Sdougm /* if rw/ro options not set, use default of RW */ 12246185db85Sdougm if ((sp->s_flags & NFS_RWMODES) == 0) 1225a3351425Sdougm sp->s_flags |= M_RW; 12266185db85Sdougm return (err); 12276185db85Sdougm } 12286185db85Sdougm 12296185db85Sdougm /* 12306185db85Sdougm * This is for testing only 12316185db85Sdougm * It displays the export structure that 12326185db85Sdougm * goes into the kernel. 12336185db85Sdougm */ 12346185db85Sdougm static void 12356185db85Sdougm printarg(char *path, struct exportdata *ep) 12366185db85Sdougm { 12376185db85Sdougm int i, j; 12386185db85Sdougm struct secinfo *sp; 12396185db85Sdougm 12406185db85Sdougm if (debug == 0) 1241a3351425Sdougm return; 12426185db85Sdougm 12436185db85Sdougm (void) printf("%s:\n", path); 12446185db85Sdougm (void) printf("\tex_version = %d\n", ep->ex_version); 12456185db85Sdougm (void) printf("\tex_path = %s\n", ep->ex_path); 1246549ec3ffSdougm (void) printf("\tex_pathlen = %ld\n", (ulong_t)ep->ex_pathlen); 12476185db85Sdougm (void) printf("\tex_flags: (0x%02x) ", ep->ex_flags); 12486185db85Sdougm if (ep->ex_flags & EX_NOSUID) 12496185db85Sdougm (void) printf("NOSUID "); 12506185db85Sdougm if (ep->ex_flags & EX_ACLOK) 12516185db85Sdougm (void) printf("ACLOK "); 12526185db85Sdougm if (ep->ex_flags & EX_PUBLIC) 12536185db85Sdougm (void) printf("PUBLIC "); 12546185db85Sdougm if (ep->ex_flags & EX_NOSUB) 12556185db85Sdougm (void) printf("NOSUB "); 12566185db85Sdougm if (ep->ex_flags & EX_LOG) 12576185db85Sdougm (void) printf("LOG "); 1258b89a8333Snatalie li - Sun Microsystems - Irvine United States if (ep->ex_flags & EX_CHARMAP) 1259b89a8333Snatalie li - Sun Microsystems - Irvine United States (void) printf("CHARMAP "); 12606185db85Sdougm if (ep->ex_flags & EX_LOG_ALLOPS) 12616185db85Sdougm (void) printf("LOG_ALLOPS "); 12626185db85Sdougm if (ep->ex_flags == 0) 12636185db85Sdougm (void) printf("(none)"); 12646185db85Sdougm (void) printf("\n"); 12656185db85Sdougm if (ep->ex_flags & EX_LOG) { 12666185db85Sdougm (void) printf("\tex_log_buffer = %s\n", 1267a3351425Sdougm (ep->ex_log_buffer ? ep->ex_log_buffer : "(NULL)")); 12686185db85Sdougm (void) printf("\tex_tag = %s\n", 1269a3351425Sdougm (ep->ex_tag ? ep->ex_tag : "(NULL)")); 12706185db85Sdougm } 12716185db85Sdougm (void) printf("\tex_anon = %d\n", ep->ex_anon); 12726185db85Sdougm (void) printf("\tex_seccnt = %d\n", ep->ex_seccnt); 12736185db85Sdougm (void) printf("\n"); 12746185db85Sdougm for (i = 0; i < ep->ex_seccnt; i++) { 12756185db85Sdougm sp = &ep->ex_secinfo[i]; 12766185db85Sdougm (void) printf("\t\ts_secinfo = %s\n", sp->s_secinfo.sc_name); 12776185db85Sdougm (void) printf("\t\ts_flags: (0x%02x) ", sp->s_flags); 12786185db85Sdougm if (sp->s_flags & M_ROOT) (void) printf("M_ROOT "); 12796185db85Sdougm if (sp->s_flags & M_RO) (void) printf("M_RO "); 12806185db85Sdougm if (sp->s_flags & M_ROL) (void) printf("M_ROL "); 12816185db85Sdougm if (sp->s_flags & M_RW) (void) printf("M_RW "); 12826185db85Sdougm if (sp->s_flags & M_RWL) (void) printf("M_RWL "); 1283b89a8333Snatalie li - Sun Microsystems - Irvine United States if (sp->s_flags & M_NONE) (void) printf("M_NONE "); 12845cb0d679SMarcel Telka if (sp->s_flags & M_MAP) (void) printf("M_MAP "); 12856185db85Sdougm if (sp->s_flags == 0) (void) printf("(none)"); 12866185db85Sdougm (void) printf("\n"); 12876185db85Sdougm (void) printf("\t\ts_window = %d\n", sp->s_window); 1288b89a8333Snatalie li - Sun Microsystems - Irvine United States (void) printf("\t\ts_rootid = %d\n", sp->s_rootid); 12896185db85Sdougm (void) printf("\t\ts_rootcnt = %d ", sp->s_rootcnt); 12906185db85Sdougm (void) fflush(stdout); 12916185db85Sdougm for (j = 0; j < sp->s_rootcnt; j++) 12926185db85Sdougm (void) printf("%s ", sp->s_rootnames[j] ? 1293a3351425Sdougm sp->s_rootnames[j] : "<null>"); 12946185db85Sdougm (void) printf("\n\n"); 12956185db85Sdougm } 12966185db85Sdougm } 12976185db85Sdougm 12986185db85Sdougm /* 12996185db85Sdougm * count_security(opts) 13006185db85Sdougm * 13016185db85Sdougm * Count the number of security types (flavors). The optionset has 13026185db85Sdougm * been populated with the security flavors as a holding mechanism. 13036185db85Sdougm * We later use this number to allocate data structures. 13046185db85Sdougm */ 13056185db85Sdougm 13066185db85Sdougm static int 13076185db85Sdougm count_security(sa_optionset_t opts) 13086185db85Sdougm { 13096185db85Sdougm int count = 0; 13106185db85Sdougm sa_property_t prop; 13116185db85Sdougm if (opts != NULL) { 1312a3351425Sdougm for (prop = sa_get_property(opts, NULL); prop != NULL; 1313a3351425Sdougm prop = sa_get_next_property(prop)) { 1314a3351425Sdougm count++; 1315a3351425Sdougm } 13166185db85Sdougm } 13176185db85Sdougm return (count); 13186185db85Sdougm } 13196185db85Sdougm 13206185db85Sdougm /* 13216185db85Sdougm * nfs_sprint_option(rbuff, rbuffsize, incr, prop, sep) 13226185db85Sdougm * 13236185db85Sdougm * provides a mechanism to format NFS properties into legacy output 13246185db85Sdougm * format. If the buffer would overflow, it is reallocated and grown 13256185db85Sdougm * as appropriate. Special cases of converting internal form of values 13266185db85Sdougm * to those used by "share" are done. this function does one property 13276185db85Sdougm * at a time. 13286185db85Sdougm */ 13296185db85Sdougm 1330aed5d200Sdougm static int 13316185db85Sdougm nfs_sprint_option(char **rbuff, size_t *rbuffsize, size_t incr, 1332*f091aea1SYuri Pankov sa_property_t prop, int sep) 13336185db85Sdougm { 13346185db85Sdougm char *name; 13356185db85Sdougm char *value; 13366185db85Sdougm int curlen; 13376185db85Sdougm char *buff = *rbuff; 13386185db85Sdougm size_t buffsize = *rbuffsize; 1339aed5d200Sdougm int printed = B_FALSE; 13406185db85Sdougm 13416185db85Sdougm name = sa_get_property_attr(prop, "type"); 13426185db85Sdougm value = sa_get_property_attr(prop, "value"); 13436185db85Sdougm if (buff != NULL) 1344a3351425Sdougm curlen = strlen(buff); 13456185db85Sdougm else 1346a3351425Sdougm curlen = 0; 13476185db85Sdougm if (name != NULL) { 1348a3351425Sdougm int len; 1349a3351425Sdougm len = strlen(name) + sep; 13506185db85Sdougm 13516185db85Sdougm /* 13526185db85Sdougm * A future RFE would be to replace this with more 13536185db85Sdougm * generic code and to possibly handle more types. 13546185db85Sdougm */ 1355a3351425Sdougm switch (gettype(name)) { 1356a3351425Sdougm case OPT_TYPE_BOOLEAN: 1357aed5d200Sdougm /* 1358aed5d200Sdougm * For NFS, boolean value of FALSE means it 1359aed5d200Sdougm * doesn't show up in the option list at all. 1360aed5d200Sdougm */ 1361a3351425Sdougm if (value != NULL && strcasecmp(value, "false") == 0) 1362aed5d200Sdougm goto skip; 1363aed5d200Sdougm if (value != NULL) { 1364a3351425Sdougm sa_free_attr_string(value); 1365aed5d200Sdougm value = NULL; 1366aed5d200Sdougm } 1367a3351425Sdougm break; 1368a3351425Sdougm case OPT_TYPE_ACCLIST: 1369a3351425Sdougm if (value != NULL && strcmp(value, "*") == 0) { 1370a3351425Sdougm sa_free_attr_string(value); 1371a3351425Sdougm value = NULL; 1372a3351425Sdougm } else { 1373a3351425Sdougm if (value != NULL) 1374a3351425Sdougm len += 1 + strlen(value); 1375a3351425Sdougm } 1376a3351425Sdougm break; 1377a3351425Sdougm case OPT_TYPE_LOGTAG: 1378a3351425Sdougm if (value != NULL && strlen(value) == 0) { 1379a3351425Sdougm sa_free_attr_string(value); 1380a3351425Sdougm value = NULL; 1381a3351425Sdougm } else { 1382a3351425Sdougm if (value != NULL) 1383a3351425Sdougm len += 1 + strlen(value); 1384a3351425Sdougm } 1385a3351425Sdougm break; 1386a3351425Sdougm default: 1387a3351425Sdougm if (value != NULL) 1388a3351425Sdougm len += 1 + strlen(value); 1389a3351425Sdougm break; 13906185db85Sdougm } 1391a3351425Sdougm while (buffsize <= (curlen + len)) { 1392a3351425Sdougm /* need more room */ 1393a3351425Sdougm buffsize += incr; 1394a3351425Sdougm buff = realloc(buff, buffsize); 1395a3351425Sdougm if (buff == NULL) { 1396a3351425Sdougm /* realloc failed so free everything */ 1397a3351425Sdougm if (*rbuff != NULL) 1398a3351425Sdougm free(*rbuff); 1399a3351425Sdougm } 1400a3351425Sdougm *rbuff = buff; 1401a3351425Sdougm *rbuffsize = buffsize; 1402aed5d200Sdougm if (buff == NULL) 1403aed5d200Sdougm goto skip; 1404aed5d200Sdougm 14056185db85Sdougm } 1406aed5d200Sdougm 1407a3351425Sdougm if (buff == NULL) 1408aed5d200Sdougm goto skip; 1409aed5d200Sdougm 1410a3351425Sdougm if (value == NULL) { 1411a3351425Sdougm (void) snprintf(buff + curlen, buffsize - curlen, 14125cb0d679SMarcel Telka "%s%s", sep ? "," : "", name); 14136185db85Sdougm } else { 1414a3351425Sdougm (void) snprintf(buff + curlen, buffsize - curlen, 1415a3351425Sdougm "%s%s=%s", sep ? "," : "", 1416a3351425Sdougm name, value != NULL ? value : ""); 14176185db85Sdougm } 1418aed5d200Sdougm printed = B_TRUE; 14196185db85Sdougm } 1420aed5d200Sdougm skip: 14216185db85Sdougm if (name != NULL) 1422a3351425Sdougm sa_free_attr_string(name); 14236185db85Sdougm if (value != NULL) 1424a3351425Sdougm sa_free_attr_string(value); 1425aed5d200Sdougm return (printed); 14266185db85Sdougm } 14276185db85Sdougm 14286185db85Sdougm /* 14296185db85Sdougm * nfs_format_options(group, hier) 14306185db85Sdougm * 14316185db85Sdougm * format all the options on the group into an old-style option 14326185db85Sdougm * string. If hier is non-zero, walk up the tree to get inherited 14336185db85Sdougm * options. 14346185db85Sdougm */ 14356185db85Sdougm 14366185db85Sdougm static char * 14376185db85Sdougm nfs_format_options(sa_group_t group, int hier) 14386185db85Sdougm { 14396185db85Sdougm sa_optionset_t options = NULL; 1440a3351425Sdougm sa_optionset_t secoptions = NULL; 14416185db85Sdougm sa_property_t prop, secprop; 1442a3351425Sdougm sa_security_t security = NULL; 14436185db85Sdougm char *buff; 14446185db85Sdougm size_t buffsize; 1445a3351425Sdougm char *sectype = NULL; 1446a3351425Sdougm int sep = 0; 1447a3351425Sdougm 1448a3351425Sdougm 1449a3351425Sdougm buff = malloc(OPT_CHUNK); 1450a3351425Sdougm if (buff == NULL) { 1451a3351425Sdougm return (NULL); 1452a3351425Sdougm } 1453a3351425Sdougm 1454a3351425Sdougm buff[0] = '\0'; 1455a3351425Sdougm buffsize = OPT_CHUNK; 1456a3351425Sdougm 1457a3351425Sdougm /* 1458a3351425Sdougm * We may have a an optionset relative to this item. format 1459a3351425Sdougm * these if we find them and then add any security definitions. 1460a3351425Sdougm */ 14616185db85Sdougm 14626185db85Sdougm options = sa_get_derived_optionset(group, "nfs", hier); 14636185db85Sdougm 14646185db85Sdougm /* 1465a3351425Sdougm * do the default set first but skip any option that is also 1466a3351425Sdougm * in the protocol specific optionset. 14676185db85Sdougm */ 1468a3351425Sdougm if (options != NULL) { 1469a3351425Sdougm for (prop = sa_get_property(options, NULL); 1470a3351425Sdougm prop != NULL; prop = sa_get_next_property(prop)) { 14716185db85Sdougm /* 1472a3351425Sdougm * use this one since we skipped any 1473a3351425Sdougm * of these that were also in 1474a3351425Sdougm * optdefault 14756185db85Sdougm */ 1476aed5d200Sdougm if (nfs_sprint_option(&buff, &buffsize, OPT_CHUNK, 1477aed5d200Sdougm prop, sep)) 1478aed5d200Sdougm sep = 1; 1479a3351425Sdougm if (buff == NULL) { 1480a3351425Sdougm /* 1481a3351425Sdougm * buff could become NULL if there 1482a3351425Sdougm * isn't enough memory for 1483a3351425Sdougm * nfs_sprint_option to realloc() 1484a3351425Sdougm * as necessary. We can't really 1485a3351425Sdougm * do anything about it at this 1486a3351425Sdougm * point so we return NULL. The 1487a3351425Sdougm * caller should handle the 1488a3351425Sdougm * failure. 1489a3351425Sdougm */ 14906185db85Sdougm if (options != NULL) 1491a3351425Sdougm sa_free_derived_optionset( 1492a3351425Sdougm options); 14936185db85Sdougm return (buff); 14946185db85Sdougm } 1495a3351425Sdougm } 1496a3351425Sdougm } 1497a3351425Sdougm secoptions = (sa_optionset_t)sa_get_all_security_types(group, 1498a3351425Sdougm "nfs", hier); 1499a3351425Sdougm if (secoptions != NULL) { 1500a3351425Sdougm for (secprop = sa_get_property(secoptions, NULL); 1501a3351425Sdougm secprop != NULL; 1502a3351425Sdougm secprop = sa_get_next_property(secprop)) { 1503a3351425Sdougm sectype = sa_get_property_attr(secprop, "type"); 1504a3351425Sdougm security = 1505a3351425Sdougm (sa_security_t)sa_get_derived_security( 1506a3351425Sdougm group, sectype, "nfs", hier); 1507a3351425Sdougm if (security != NULL) { 1508a3351425Sdougm if (sectype != NULL) { 1509a3351425Sdougm prop = sa_create_property( 1510a3351425Sdougm "sec", sectype); 1511aed5d200Sdougm if (prop == NULL) 1512aed5d200Sdougm goto err; 1513aed5d200Sdougm if (nfs_sprint_option(&buff, 1514aed5d200Sdougm &buffsize, OPT_CHUNK, prop, sep)) 1515aed5d200Sdougm sep = 1; 1516a3351425Sdougm (void) sa_remove_property(prop); 1517aed5d200Sdougm if (buff == NULL) 1518aed5d200Sdougm goto err; 1519a3351425Sdougm } 1520a3351425Sdougm for (prop = sa_get_property(security, 1521a3351425Sdougm NULL); prop != NULL; 1522a3351425Sdougm prop = sa_get_next_property(prop)) { 1523aed5d200Sdougm if (nfs_sprint_option(&buff, 1524aed5d200Sdougm &buffsize, OPT_CHUNK, prop, sep)) 1525aed5d200Sdougm sep = 1; 1526a3351425Sdougm if (buff == NULL) 1527a3351425Sdougm goto err; 1528a3351425Sdougm } 1529a3351425Sdougm sa_free_derived_optionset(security); 1530a3351425Sdougm } 1531a3351425Sdougm if (sectype != NULL) 1532a3351425Sdougm sa_free_attr_string(sectype); 15336185db85Sdougm } 15346185db85Sdougm sa_free_derived_optionset(secoptions); 15356185db85Sdougm } 1536a3351425Sdougm 15376185db85Sdougm if (options != NULL) 1538a3351425Sdougm sa_free_derived_optionset(options); 1539a3351425Sdougm return (buff); 1540a3351425Sdougm 1541a3351425Sdougm err: 1542a3351425Sdougm /* 1543a3351425Sdougm * If we couldn't allocate memory for option printing, we need 1544a3351425Sdougm * to break out of the nested loops, cleanup and return NULL. 1545a3351425Sdougm */ 1546a3351425Sdougm if (secoptions != NULL) 1547a3351425Sdougm sa_free_derived_optionset(secoptions); 1548a3351425Sdougm if (security != NULL) 1549a3351425Sdougm sa_free_derived_optionset(security); 1550a3351425Sdougm if (sectype != NULL) 1551a3351425Sdougm sa_free_attr_string(sectype); 1552a3351425Sdougm if (options != NULL) 1553a3351425Sdougm sa_free_derived_optionset(options); 1554dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States return (buff); 15556185db85Sdougm } 1556a3351425Sdougm 15576185db85Sdougm /* 15586185db85Sdougm * Append an entry to the nfslogtab file 15596185db85Sdougm */ 15606185db85Sdougm static int 1561*f091aea1SYuri Pankov nfslogtab_add(char *dir, char *buffer, char *tag) 15626185db85Sdougm { 15636185db85Sdougm FILE *f; 15646185db85Sdougm struct logtab_ent lep; 15656185db85Sdougm int error = 0; 15666185db85Sdougm 15676185db85Sdougm /* 15686185db85Sdougm * Open the file for update and create it if necessary. 15696185db85Sdougm * This may leave the I/O offset at the end of the file, 15706185db85Sdougm * so rewind back to the beginning of the file. 15716185db85Sdougm */ 15726185db85Sdougm f = fopen(NFSLOGTAB, "a+"); 15736185db85Sdougm if (f == NULL) { 15746185db85Sdougm error = errno; 15756185db85Sdougm goto out; 15766185db85Sdougm } 15776185db85Sdougm rewind(f); 15786185db85Sdougm 15796185db85Sdougm if (lockf(fileno(f), F_LOCK, 0L) < 0) { 1580549ec3ffSdougm (void) fprintf(stderr, dgettext(TEXT_DOMAIN, 1581a3351425Sdougm "share complete, however failed to lock %s " 1582a3351425Sdougm "for update: %s\n"), NFSLOGTAB, strerror(errno)); 15836185db85Sdougm error = -1; 15846185db85Sdougm goto out; 15856185db85Sdougm } 15866185db85Sdougm 15876185db85Sdougm if (logtab_deactivate_after_boot(f) == -1) { 1588549ec3ffSdougm (void) fprintf(stderr, dgettext(TEXT_DOMAIN, 1589a3351425Sdougm "share complete, however could not deactivate " 1590a3351425Sdougm "entries in %s\n"), NFSLOGTAB); 15916185db85Sdougm error = -1; 15926185db85Sdougm goto out; 15936185db85Sdougm } 15946185db85Sdougm 15956185db85Sdougm /* 15966185db85Sdougm * Remove entries matching buffer and sharepoint since we're 15976185db85Sdougm * going to replace it with perhaps an entry with a new tag. 15986185db85Sdougm */ 15996185db85Sdougm if (logtab_rement(f, buffer, dir, NULL, -1)) { 1600549ec3ffSdougm (void) fprintf(stderr, dgettext(TEXT_DOMAIN, 1601a3351425Sdougm "share complete, however could not remove matching " 1602a3351425Sdougm "entries in %s\n"), NFSLOGTAB); 16036185db85Sdougm error = -1; 16046185db85Sdougm goto out; 16056185db85Sdougm } 16066185db85Sdougm 16076185db85Sdougm /* 16086185db85Sdougm * Deactivate all active entries matching this sharepoint 16096185db85Sdougm */ 16106185db85Sdougm if (logtab_deactivate(f, NULL, dir, NULL)) { 1611549ec3ffSdougm (void) fprintf(stderr, dgettext(TEXT_DOMAIN, 1612a3351425Sdougm "share complete, however could not deactivate matching " 1613a3351425Sdougm "entries in %s\n"), NFSLOGTAB); 16146185db85Sdougm error = -1; 16156185db85Sdougm goto out; 16166185db85Sdougm } 16176185db85Sdougm 16186185db85Sdougm lep.le_buffer = buffer; 16196185db85Sdougm lep.le_path = dir; 16206185db85Sdougm lep.le_tag = tag; 16216185db85Sdougm lep.le_state = LES_ACTIVE; 16226185db85Sdougm 16236185db85Sdougm /* 16246185db85Sdougm * Add new sharepoint / buffer location to nfslogtab 16256185db85Sdougm */ 16266185db85Sdougm if (logtab_putent(f, &lep) < 0) { 1627549ec3ffSdougm (void) fprintf(stderr, dgettext(TEXT_DOMAIN, 1628a3351425Sdougm "share complete, however could not add %s to %s\n"), 1629a3351425Sdougm dir, NFSLOGTAB); 16306185db85Sdougm error = -1; 16316185db85Sdougm } 16326185db85Sdougm 16336185db85Sdougm out: 16346185db85Sdougm if (f != NULL) 16356185db85Sdougm (void) fclose(f); 16366185db85Sdougm return (error); 16376185db85Sdougm } 16386185db85Sdougm 16396185db85Sdougm /* 16406185db85Sdougm * Deactivate an entry from the nfslogtab file 16416185db85Sdougm */ 16426185db85Sdougm static int 1643*f091aea1SYuri Pankov nfslogtab_deactivate(char *path) 16446185db85Sdougm { 16456185db85Sdougm FILE *f; 16466185db85Sdougm int error = 0; 16476185db85Sdougm 16486185db85Sdougm f = fopen(NFSLOGTAB, "r+"); 16496185db85Sdougm if (f == NULL) { 16506185db85Sdougm error = errno; 16516185db85Sdougm goto out; 16526185db85Sdougm } 16536185db85Sdougm if (lockf(fileno(f), F_LOCK, 0L) < 0) { 16546185db85Sdougm error = errno; 1655549ec3ffSdougm (void) fprintf(stderr, dgettext(TEXT_DOMAIN, 1656a3351425Sdougm "share complete, however could not lock %s for " 1657a3351425Sdougm "update: %s\n"), NFSLOGTAB, strerror(error)); 16586185db85Sdougm goto out; 16596185db85Sdougm } 16606185db85Sdougm if (logtab_deactivate(f, NULL, path, NULL) == -1) { 16616185db85Sdougm error = -1; 16626185db85Sdougm (void) fprintf(stderr, 1663a3351425Sdougm dgettext(TEXT_DOMAIN, 1664a3351425Sdougm "share complete, however could not " 1665a3351425Sdougm "deactivate %s in %s\n"), path, NFSLOGTAB); 16666185db85Sdougm goto out; 16676185db85Sdougm } 16686185db85Sdougm 16696185db85Sdougm out: if (f != NULL) 16706185db85Sdougm (void) fclose(f); 16716185db85Sdougm 16726185db85Sdougm return (error); 16736185db85Sdougm } 16746185db85Sdougm 1675546405c3Sdougm /* 1676546405c3Sdougm * check_public(group, skipshare) 1677546405c3Sdougm * 1678546405c3Sdougm * Check the group for any shares that have the public property 1679546405c3Sdougm * enabled. We skip "skipshare" since that is the one we are 1680546405c3Sdougm * working with. This is a separate function to make handling 1681546405c3Sdougm * subgroups simpler. Returns true if there is a share with public. 1682546405c3Sdougm */ 1683546405c3Sdougm static int 1684546405c3Sdougm check_public(sa_group_t group, sa_share_t skipshare) 1685546405c3Sdougm { 1686546405c3Sdougm int exists = B_FALSE; 1687546405c3Sdougm sa_share_t share; 1688546405c3Sdougm sa_optionset_t opt; 1689546405c3Sdougm sa_property_t prop; 1690546405c3Sdougm char *shared; 1691546405c3Sdougm 1692546405c3Sdougm for (share = sa_get_share(group, NULL); share != NULL; 1693546405c3Sdougm share = sa_get_next_share(share)) { 1694546405c3Sdougm if (share == skipshare) 1695546405c3Sdougm continue; 1696546405c3Sdougm 1697546405c3Sdougm opt = sa_get_optionset(share, "nfs"); 1698546405c3Sdougm if (opt == NULL) 1699546405c3Sdougm continue; 1700546405c3Sdougm prop = sa_get_property(opt, "public"); 1701546405c3Sdougm if (prop == NULL) 1702546405c3Sdougm continue; 1703546405c3Sdougm shared = sa_get_share_attr(share, "shared"); 1704546405c3Sdougm if (shared != NULL) { 1705546405c3Sdougm exists = strcmp(shared, "true") == 0; 1706546405c3Sdougm sa_free_attr_string(shared); 1707546405c3Sdougm if (exists == B_TRUE) 1708546405c3Sdougm break; 1709546405c3Sdougm } 1710546405c3Sdougm } 1711546405c3Sdougm 1712546405c3Sdougm return (exists); 1713546405c3Sdougm } 1714546405c3Sdougm 17156185db85Sdougm /* 17165cb0d679SMarcel Telka * public_exists(handle, skipshare) 17176185db85Sdougm * 17186185db85Sdougm * check to see if public option is set on any other share than the 1719546405c3Sdougm * one specified. Need to check zfs sub-groups as well as the top 1720546405c3Sdougm * level groups. 17216185db85Sdougm */ 17226185db85Sdougm static int 1723687915e9Sdougm public_exists(sa_handle_t handle, sa_share_t skipshare) 17246185db85Sdougm { 1725687915e9Sdougm sa_group_t group = NULL; 1726549ec3ffSdougm 17273b61b335Sdougm /* 17283b61b335Sdougm * If we don't have a handle, we can only do syntax check. We 17293b61b335Sdougm * can't check against other shares so we assume OK and will 17303b61b335Sdougm * catch the problem only when we actually try to apply it. 17313b61b335Sdougm */ 1732549ec3ffSdougm if (handle == NULL) 17333b61b335Sdougm return (SA_OK); 1734549ec3ffSdougm 1735687915e9Sdougm if (skipshare != NULL) { 1736687915e9Sdougm group = sa_get_parent_group(skipshare); 1737687915e9Sdougm if (group == NULL) 1738687915e9Sdougm return (SA_NO_SUCH_GROUP); 1739687915e9Sdougm } 1740687915e9Sdougm 1741549ec3ffSdougm for (group = sa_get_group(handle, NULL); group != NULL; 17426185db85Sdougm group = sa_get_next_group(group)) { 1743546405c3Sdougm /* Walk any ZFS subgroups as well as all standard groups */ 1744546405c3Sdougm if (sa_group_is_zfs(group)) { 1745546405c3Sdougm sa_group_t subgroup; 1746546405c3Sdougm for (subgroup = sa_get_sub_group(group); 1747546405c3Sdougm subgroup != NULL; 1748546405c3Sdougm subgroup = sa_get_next_group(subgroup)) { 1749546405c3Sdougm if (check_public(subgroup, skipshare)) 1750546405c3Sdougm return (B_TRUE); 17516185db85Sdougm } 1752546405c3Sdougm } else { 1753546405c3Sdougm if (check_public(group, skipshare)) 1754546405c3Sdougm return (B_TRUE); 17556185db85Sdougm } 17566185db85Sdougm } 1757546405c3Sdougm return (B_FALSE); 17586185db85Sdougm } 17596185db85Sdougm 17606185db85Sdougm /* 17616185db85Sdougm * sa_enable_share at the protocol level, enable_share must tell the 17626185db85Sdougm * implementation that it is to enable the share. This entails 17636185db85Sdougm * converting the path and options into the appropriate ioctl 17646185db85Sdougm * calls. It is assumed that all error checking of paths, etc. were 17656185db85Sdougm * done earlier. 17666185db85Sdougm */ 17676185db85Sdougm static int 17686185db85Sdougm nfs_enable_share(sa_share_t share) 17696185db85Sdougm { 17706185db85Sdougm struct exportdata export; 17716185db85Sdougm sa_optionset_t secoptlist; 17726185db85Sdougm struct secinfo *sp; 17736185db85Sdougm int num_secinfo; 17746185db85Sdougm sa_optionset_t opt; 17756185db85Sdougm sa_security_t sec; 17766185db85Sdougm sa_property_t prop; 17776185db85Sdougm char *path; 17786185db85Sdougm int err = SA_OK; 1779546405c3Sdougm int i; 1780ecd6cf80Smarks int iszfs; 1781687915e9Sdougm sa_handle_t handle; 17826185db85Sdougm 17836185db85Sdougm /* Don't drop core if the NFS module isn't loaded. */ 17846185db85Sdougm (void) signal(SIGSYS, SIG_IGN); 17856185db85Sdougm 17866185db85Sdougm /* get the path since it is important in several places */ 17876185db85Sdougm path = sa_get_share_attr(share, "path"); 17886185db85Sdougm if (path == NULL) 1789a3351425Sdougm return (SA_NO_SUCH_PATH); 17906185db85Sdougm 1791ecd6cf80Smarks iszfs = sa_path_is_zfs(path); 17926185db85Sdougm /* 17936185db85Sdougm * find the optionsets and security sets. There may not be 17946185db85Sdougm * any or there could be one or two for each of optionset and 17956185db85Sdougm * security may have multiple, one per security type per 17966185db85Sdougm * protocol type. 17976185db85Sdougm */ 17986185db85Sdougm opt = sa_get_derived_optionset(share, "nfs", 1); 17996185db85Sdougm secoptlist = (sa_optionset_t)sa_get_all_security_types(share, "nfs", 1); 18006185db85Sdougm if (secoptlist != NULL) 1801a3351425Sdougm num_secinfo = MAX(1, count_security(secoptlist)); 18026185db85Sdougm else 1803a3351425Sdougm num_secinfo = 1; 18046185db85Sdougm 18056185db85Sdougm /* 18066185db85Sdougm * walk through the options and fill in the structure 18076185db85Sdougm * appropriately. 18086185db85Sdougm */ 18096185db85Sdougm 18106185db85Sdougm (void) memset(&export, '\0', sizeof (export)); 18116185db85Sdougm 18126185db85Sdougm /* 18136185db85Sdougm * do non-security options first since there is only one after 18146185db85Sdougm * the derived group is constructed. 18156185db85Sdougm */ 18166185db85Sdougm export.ex_version = EX_CURRENT_VERSION; 18176185db85Sdougm export.ex_anon = UID_NOBODY; /* this is our default value */ 18186185db85Sdougm export.ex_index = NULL; 18196185db85Sdougm export.ex_path = path; 18206185db85Sdougm export.ex_pathlen = strlen(path) + 1; 18216185db85Sdougm 18226185db85Sdougm if (opt != NULL) 1823a3351425Sdougm err = fill_export_from_optionset(&export, opt); 18246185db85Sdougm 18256185db85Sdougm /* 18266185db85Sdougm * check to see if "public" is set. If it is, then make sure 18276185db85Sdougm * no other share has it set. If it is already used, fail. 18286185db85Sdougm */ 18296185db85Sdougm 1830687915e9Sdougm handle = sa_find_group_handle((sa_group_t)share); 1831687915e9Sdougm if (export.ex_flags & EX_PUBLIC && public_exists(handle, share)) { 1832a3351425Sdougm (void) printf(dgettext(TEXT_DOMAIN, 1833a3351425Sdougm "NFS: Cannot share more than one file " 1834a3351425Sdougm "system with 'public' property\n")); 1835a3351425Sdougm err = SA_NOT_ALLOWED; 1836a3351425Sdougm goto out; 18376185db85Sdougm } 18386185db85Sdougm 1839546405c3Sdougm sp = calloc(num_secinfo, sizeof (struct secinfo)); 18406185db85Sdougm if (sp == NULL) { 1841a3351425Sdougm err = SA_NO_MEMORY; 1842546405c3Sdougm (void) printf(dgettext(TEXT_DOMAIN, 1843546405c3Sdougm "NFS: NFS: no memory for security\n")); 1844546405c3Sdougm goto out; 1845546405c3Sdougm } 1846546405c3Sdougm export.ex_secinfo = sp; 1847546405c3Sdougm /* get default secinfo */ 1848546405c3Sdougm export.ex_seccnt = num_secinfo; 1849546405c3Sdougm /* 1850546405c3Sdougm * since we must have one security option defined, we 1851546405c3Sdougm * init to the default and then override as we find 1852546405c3Sdougm * defined security options. This handles the case 1853546405c3Sdougm * where we have no defined options but we need to set 1854546405c3Sdougm * up one. 1855546405c3Sdougm */ 1856546405c3Sdougm sp[0].s_window = DEF_WIN; 1857546405c3Sdougm sp[0].s_rootnames = NULL; 1858546405c3Sdougm /* setup a default in case no properties defined */ 1859546405c3Sdougm if (nfs_getseconfig_default(&sp[0].s_secinfo)) { 1860546405c3Sdougm (void) printf(dgettext(TEXT_DOMAIN, 1861546405c3Sdougm "NFS: nfs_getseconfig_default: failed to " 1862546405c3Sdougm "get default security mode\n")); 1863546405c3Sdougm err = SA_CONFIG_ERR; 1864546405c3Sdougm } 1865546405c3Sdougm if (secoptlist != NULL) { 1866546405c3Sdougm for (i = 0, prop = sa_get_property(secoptlist, NULL); 1867546405c3Sdougm prop != NULL && i < num_secinfo; 1868546405c3Sdougm prop = sa_get_next_property(prop), i++) { 1869546405c3Sdougm char *sectype; 1870fe1c642dSBill Krier sectype = sa_get_property_attr(prop, "type"); 1871546405c3Sdougm /* 1872546405c3Sdougm * if sectype is NULL, we probably 1873546405c3Sdougm * have a memory problem and can't get 1874546405c3Sdougm * the correct values. Rather than 1875546405c3Sdougm * exporting with incorrect security, 1876546405c3Sdougm * don't share it. 1877546405c3Sdougm */ 1878546405c3Sdougm if (sectype == NULL) { 1879546405c3Sdougm err = SA_NO_MEMORY; 1880546405c3Sdougm (void) printf(dgettext(TEXT_DOMAIN, 1881546405c3Sdougm "NFS: Cannot share %s: " 1882546405c3Sdougm "no memory\n"), path); 1883546405c3Sdougm goto out; 1884a3351425Sdougm } 1885546405c3Sdougm sec = (sa_security_t)sa_get_derived_security( 1886546405c3Sdougm share, sectype, "nfs", 1); 1887546405c3Sdougm sp[i].s_window = DEF_WIN; 1888546405c3Sdougm sp[i].s_rootcnt = 0; 1889546405c3Sdougm sp[i].s_rootnames = NULL; 18905cb0d679SMarcel Telka (void) fill_security_from_secopts(&sp[i], sec); 1891546405c3Sdougm if (sec != NULL) 1892546405c3Sdougm sa_free_derived_security(sec); 1893546405c3Sdougm if (sectype != NULL) 1894546405c3Sdougm sa_free_attr_string(sectype); 18956185db85Sdougm } 1896546405c3Sdougm } 1897546405c3Sdougm /* 1898546405c3Sdougm * when we get here, we can do the exportfs system call and 18994b92079bSAlexander Eremin * initiate things. We probably want to enable the 19004b92079bSAlexander Eremin * svc:/network/nfs/server service first if it isn't running. 1901546405c3Sdougm */ 19024b92079bSAlexander Eremin /* check svc:/network/nfs/server status and start if needed */ 1903546405c3Sdougm /* now add the share to the internal tables */ 1904546405c3Sdougm printarg(path, &export); 1905546405c3Sdougm /* 1906546405c3Sdougm * call the exportfs system call which is implemented 1907546405c3Sdougm * via the nfssys() call as the EXPORTFS subfunction. 1908546405c3Sdougm */ 1909ecd6cf80Smarks if (iszfs) { 1910ecd6cf80Smarks struct exportfs_args ea; 1911ecd6cf80Smarks share_t sh; 1912ecd6cf80Smarks char *str; 1913ecd6cf80Smarks priv_set_t *priv_effective; 1914ecd6cf80Smarks int privileged; 1915ecd6cf80Smarks 1916ecd6cf80Smarks /* 1917ecd6cf80Smarks * If we aren't a privileged user 1918ecd6cf80Smarks * and NFS server service isn't running 1919ecd6cf80Smarks * then print out an error message 1920ecd6cf80Smarks * and return EPERM 1921ecd6cf80Smarks */ 1922ecd6cf80Smarks 1923ecd6cf80Smarks priv_effective = priv_allocset(); 1924ecd6cf80Smarks (void) getppriv(PRIV_EFFECTIVE, priv_effective); 1925ecd6cf80Smarks 1926ecd6cf80Smarks privileged = (priv_isfullset(priv_effective) == B_TRUE); 1927ecd6cf80Smarks priv_freeset(priv_effective); 1928ecd6cf80Smarks 1929ecd6cf80Smarks if (!privileged && 1930ecd6cf80Smarks (str = smf_get_state(NFS_SERVER_SVC)) != NULL) { 1931ecd6cf80Smarks err = 0; 1932ecd6cf80Smarks if (strcmp(str, SCF_STATE_STRING_ONLINE) != 0) { 1933ecd6cf80Smarks (void) printf(dgettext(TEXT_DOMAIN, 1934ecd6cf80Smarks "NFS: Cannot share remote " 1935ecd6cf80Smarks "filesystem: %s\n"), path); 1936ecd6cf80Smarks (void) printf(dgettext(TEXT_DOMAIN, 1937ecd6cf80Smarks "NFS: Service needs to be enabled " 1938ecd6cf80Smarks "by a privileged user\n")); 1939ecd6cf80Smarks err = SA_SYSTEM_ERR; 1940ecd6cf80Smarks errno = EPERM; 1941ecd6cf80Smarks } 1942ecd6cf80Smarks free(str); 1943ecd6cf80Smarks } 1944ecd6cf80Smarks 1945ecd6cf80Smarks if (err == 0) { 1946ecd6cf80Smarks ea.dname = path; 1947ecd6cf80Smarks ea.uex = &export; 1948ecd6cf80Smarks 19495ad42b1bSSurya Prakki (void) sa_sharetab_fill_zfs(share, &sh, "nfs"); 1950743a77edSAlan Wright err = sa_share_zfs(share, NULL, path, &sh, 1951da6c28aaSamw &ea, ZFS_SHARE_NFS); 1952a63214d6SBill Krier if (err != SA_OK) { 1953a63214d6SBill Krier errno = err; 1954a63214d6SBill Krier err = -1; 1955a63214d6SBill Krier } 1956ecd6cf80Smarks sa_emptyshare(&sh); 1957ecd6cf80Smarks } 1958ecd6cf80Smarks } else { 1959ecd6cf80Smarks err = exportfs(path, &export); 1960ecd6cf80Smarks } 1961ecd6cf80Smarks 1962ecd6cf80Smarks if (err < 0) { 1963546405c3Sdougm err = SA_SYSTEM_ERR; 1964546405c3Sdougm switch (errno) { 1965546405c3Sdougm case EREMOTE: 1966546405c3Sdougm (void) printf(dgettext(TEXT_DOMAIN, 1967ecd6cf80Smarks "NFS: Cannot share filesystems " 1968ecd6cf80Smarks "in non-global zones: %s\n"), path); 1969ecd6cf80Smarks err = SA_NOT_SUPPORTED; 1970546405c3Sdougm break; 1971546405c3Sdougm case EPERM: 1972546405c3Sdougm if (getzoneid() != GLOBAL_ZONEID) { 1973a3351425Sdougm (void) printf(dgettext(TEXT_DOMAIN, 1974ecd6cf80Smarks "NFS: Cannot share file systems " 1975546405c3Sdougm "in non-global zones: %s\n"), path); 1976546405c3Sdougm err = SA_NOT_SUPPORTED; 1977a3351425Sdougm break; 1978a3351425Sdougm } 1979546405c3Sdougm err = SA_NO_PERMISSION; 19800616fd7fSPavel Filipensky break; 19810616fd7fSPavel Filipensky case EEXIST: 19820616fd7fSPavel Filipensky err = SA_SHARE_EXISTS; 19830616fd7fSPavel Filipensky break; 1984546405c3Sdougm default: 1985546405c3Sdougm break; 19866185db85Sdougm } 1987546405c3Sdougm } else { 1988546405c3Sdougm /* update sharetab with an add/modify */ 1989ecd6cf80Smarks if (!iszfs) { 1990ecd6cf80Smarks (void) sa_update_sharetab(share, "nfs"); 1991ecd6cf80Smarks } 19926185db85Sdougm } 19936185db85Sdougm 19946185db85Sdougm if (err == SA_OK) { 19956185db85Sdougm /* 19966185db85Sdougm * enable services as needed. This should probably be 19976185db85Sdougm * done elsewhere in order to minimize the calls to 19986185db85Sdougm * check services. 19996185db85Sdougm */ 20006185db85Sdougm /* 20016185db85Sdougm * check to see if logging and other services need to 20026185db85Sdougm * be triggered, but only if there wasn't an 20036185db85Sdougm * error. This is probably where sharetab should be 20046185db85Sdougm * updated with the NFS specific entry. 20056185db85Sdougm */ 2006a3351425Sdougm if (export.ex_flags & EX_LOG) { 2007a3351425Sdougm /* enable logging */ 2008a3351425Sdougm if (nfslogtab_add(path, export.ex_log_buffer, 2009a3351425Sdougm export.ex_tag) != 0) { 2010a3351425Sdougm (void) fprintf(stderr, dgettext(TEXT_DOMAIN, 2011a3351425Sdougm "Could not enable logging for %s\n"), 2012a3351425Sdougm path); 2013a3351425Sdougm } 2014a3351425Sdougm _check_services(service_list_logging); 2015a3351425Sdougm } else { 2016a3351425Sdougm /* 2017a3351425Sdougm * don't have logging so remove it from file. It might 2018a3351425Sdougm * not be thre, but that doesn't matter. 2019a3351425Sdougm */ 2020a3351425Sdougm (void) nfslogtab_deactivate(path); 2021a3351425Sdougm _check_services(service_list_default); 20226185db85Sdougm } 20236185db85Sdougm } 20246185db85Sdougm 20256185db85Sdougm out: 20266185db85Sdougm if (path != NULL) 2027a3351425Sdougm free(path); 20286185db85Sdougm 20296185db85Sdougm cleanup_export(&export); 20306185db85Sdougm if (opt != NULL) 2031a3351425Sdougm sa_free_derived_optionset(opt); 20326185db85Sdougm if (secoptlist != NULL) 2033a3351425Sdougm (void) sa_destroy_optionset(secoptlist); 20346185db85Sdougm return (err); 20356185db85Sdougm } 20366185db85Sdougm 20376185db85Sdougm /* 20388e314a44Sdougm * nfs_disable_share(share, path) 20396185db85Sdougm * 20408e314a44Sdougm * Unshare the specified share. Note that "path" is the same path as 20418e314a44Sdougm * what is in the "share" object. It is passed in to avoid an 20428e314a44Sdougm * additional lookup. A missing "path" value makes this a no-op 20438e314a44Sdougm * function. 20446185db85Sdougm */ 20456185db85Sdougm static int 2046ecd6cf80Smarks nfs_disable_share(sa_share_t share, char *path) 20476185db85Sdougm { 20486185db85Sdougm int err; 20496185db85Sdougm int ret = SA_OK; 2050ecd6cf80Smarks int iszfs; 20518e314a44Sdougm sa_group_t parent; 20525b6e0c46Sdougm sa_handle_t handle; 2053ecd6cf80Smarks 20548e314a44Sdougm if (path == NULL) 20558e314a44Sdougm return (ret); 2056ecd6cf80Smarks 20578e314a44Sdougm /* 20588e314a44Sdougm * If the share is in a ZFS group we need to handle it 20598e314a44Sdougm * differently. Just being on a ZFS file system isn't 20608e314a44Sdougm * enough since we may be in a legacy share case. 20618e314a44Sdougm */ 20628e314a44Sdougm parent = sa_get_parent_group(share); 20638e314a44Sdougm iszfs = sa_group_is_zfs(parent); 20648e314a44Sdougm if (iszfs) { 20658e314a44Sdougm struct exportfs_args ea; 20668e314a44Sdougm share_t sh = { 0 }; 20678e314a44Sdougm ea.dname = path; 20688e314a44Sdougm ea.uex = NULL; 20698e314a44Sdougm sh.sh_path = path; 20708e314a44Sdougm sh.sh_fstype = "nfs"; 20718e314a44Sdougm 2072743a77edSAlan Wright err = sa_share_zfs(share, NULL, path, &sh, 20738e314a44Sdougm &ea, ZFS_UNSHARE_NFS); 2074a63214d6SBill Krier if (err != SA_OK) { 2075a63214d6SBill Krier errno = err; 2076a63214d6SBill Krier err = -1; 2077a63214d6SBill Krier } 20788e314a44Sdougm } else { 20798e314a44Sdougm err = exportfs(path, NULL); 20808e314a44Sdougm } 20818e314a44Sdougm if (err < 0) { 20828e314a44Sdougm /* 20838e314a44Sdougm * TBD: only an error in some 20848e314a44Sdougm * cases - need better analysis 20858e314a44Sdougm */ 20868e314a44Sdougm switch (errno) { 20878e314a44Sdougm case EPERM: 20888e314a44Sdougm case EACCES: 20898e314a44Sdougm ret = SA_NO_PERMISSION; 20908e314a44Sdougm if (getzoneid() != GLOBAL_ZONEID) { 20918e314a44Sdougm ret = SA_NOT_SUPPORTED; 20928e314a44Sdougm } 20938e314a44Sdougm break; 20948e314a44Sdougm case EINVAL: 20958e314a44Sdougm case ENOENT: 20968e314a44Sdougm ret = SA_NO_SUCH_PATH; 2097ecd6cf80Smarks break; 2098a63214d6SBill Krier default: 2099a63214d6SBill Krier ret = SA_SYSTEM_ERR; 2100ecd6cf80Smarks break; 21016185db85Sdougm } 21026185db85Sdougm } 21038e314a44Sdougm if (ret == SA_OK || ret == SA_NO_SUCH_PATH) { 21045b6e0c46Sdougm handle = sa_find_group_handle((sa_group_t)share); 21058e314a44Sdougm if (!iszfs) 21065b6e0c46Sdougm (void) sa_delete_sharetab(handle, path, "nfs"); 21078e314a44Sdougm /* just in case it was logged */ 21088e314a44Sdougm (void) nfslogtab_deactivate(path); 21098e314a44Sdougm } 21106185db85Sdougm return (ret); 21116185db85Sdougm } 21126185db85Sdougm 21135cb0d679SMarcel Telka static int 21145cb0d679SMarcel Telka check_user(char *value) 21155cb0d679SMarcel Telka { 21165cb0d679SMarcel Telka int ret = SA_OK; 21175cb0d679SMarcel Telka 21185cb0d679SMarcel Telka if (!is_a_number(value)) { 21195cb0d679SMarcel Telka struct passwd *pw; 21205cb0d679SMarcel Telka /* 21215cb0d679SMarcel Telka * in this case it would have to be a 21225cb0d679SMarcel Telka * user name 21235cb0d679SMarcel Telka */ 21245cb0d679SMarcel Telka pw = getpwnam(value); 21255cb0d679SMarcel Telka if (pw == NULL) 21265cb0d679SMarcel Telka ret = SA_BAD_VALUE; 21275cb0d679SMarcel Telka endpwent(); 21285cb0d679SMarcel Telka } else { 21295cb0d679SMarcel Telka uint64_t intval; 21305cb0d679SMarcel Telka intval = strtoull(value, NULL, 0); 21315cb0d679SMarcel Telka if (intval > UID_MAX && intval != -1) 21325cb0d679SMarcel Telka ret = SA_BAD_VALUE; 21335cb0d679SMarcel Telka } 21345cb0d679SMarcel Telka 21355cb0d679SMarcel Telka return (ret); 21365cb0d679SMarcel Telka } 21375cb0d679SMarcel Telka 21385cb0d679SMarcel Telka static int 21395cb0d679SMarcel Telka check_group(char *value) 21405cb0d679SMarcel Telka { 21415cb0d679SMarcel Telka int ret = SA_OK; 21425cb0d679SMarcel Telka 21435cb0d679SMarcel Telka if (!is_a_number(value)) { 21445cb0d679SMarcel Telka struct group *gr; 21455cb0d679SMarcel Telka /* 21465cb0d679SMarcel Telka * in this case it would have to be a 21475cb0d679SMarcel Telka * group name 21485cb0d679SMarcel Telka */ 21495cb0d679SMarcel Telka gr = getgrnam(value); 21505cb0d679SMarcel Telka if (gr == NULL) 21515cb0d679SMarcel Telka ret = SA_BAD_VALUE; 21525cb0d679SMarcel Telka endgrent(); 21535cb0d679SMarcel Telka } else { 21545cb0d679SMarcel Telka uint64_t intval; 21555cb0d679SMarcel Telka intval = strtoull(value, NULL, 0); 21565cb0d679SMarcel Telka if (intval > UID_MAX && intval != -1) 21575cb0d679SMarcel Telka ret = SA_BAD_VALUE; 21585cb0d679SMarcel Telka } 21595cb0d679SMarcel Telka 21605cb0d679SMarcel Telka return (ret); 21615cb0d679SMarcel Telka } 21625cb0d679SMarcel Telka 21636185db85Sdougm /* 2164b89a8333Snatalie li - Sun Microsystems - Irvine United States * check_rorwnone(v1, v2, v3) 2165b89a8333Snatalie li - Sun Microsystems - Irvine United States * 2166b89a8333Snatalie li - Sun Microsystems - Irvine United States * check ro vs rw vs none values. Over time this may get beefed up. 2167b89a8333Snatalie li - Sun Microsystems - Irvine United States * for now it just does simple checks. v1 is never NULL but v2 or v3 2168b89a8333Snatalie li - Sun Microsystems - Irvine United States * could be. 21696185db85Sdougm */ 21706185db85Sdougm 21716185db85Sdougm static int 2172b89a8333Snatalie li - Sun Microsystems - Irvine United States check_rorwnone(char *v1, char *v2, char *v3) 21736185db85Sdougm { 21746185db85Sdougm int ret = SA_OK; 2175b89a8333Snatalie li - Sun Microsystems - Irvine United States if (v2 != NULL && strcmp(v1, v2) == 0) 2176b89a8333Snatalie li - Sun Microsystems - Irvine United States ret = SA_VALUE_CONFLICT; 2177b89a8333Snatalie li - Sun Microsystems - Irvine United States else if (v3 != NULL && strcmp(v1, v3) == 0) 2178a3351425Sdougm ret = SA_VALUE_CONFLICT; 2179b89a8333Snatalie li - Sun Microsystems - Irvine United States 21806185db85Sdougm return (ret); 21816185db85Sdougm } 21826185db85Sdougm 21836185db85Sdougm /* 2184687915e9Sdougm * nfs_validate_property(handle, property, parent) 21856185db85Sdougm * 21866185db85Sdougm * Check that the property has a legitimate value for its type. 21876185db85Sdougm */ 21886185db85Sdougm 21896185db85Sdougm static int 2190687915e9Sdougm nfs_validate_property(sa_handle_t handle, sa_property_t property, 2191687915e9Sdougm sa_optionset_t parent) 21926185db85Sdougm { 21936185db85Sdougm int ret = SA_OK; 21946185db85Sdougm char *propname; 2195b89a8333Snatalie li - Sun Microsystems - Irvine United States char *other1; 2196b89a8333Snatalie li - Sun Microsystems - Irvine United States char *other2; 21976185db85Sdougm int optindex; 21986185db85Sdougm nfsl_config_t *configlist; 21996185db85Sdougm sa_group_t parent_group; 22006185db85Sdougm char *value; 22016185db85Sdougm 22026185db85Sdougm propname = sa_get_property_attr(property, "type"); 22036185db85Sdougm 22046185db85Sdougm if ((optindex = findopt(propname)) < 0) 2205a3351425Sdougm ret = SA_NO_SUCH_PROP; 22066185db85Sdougm 22076185db85Sdougm /* need to validate value range here as well */ 22086185db85Sdougm 22096185db85Sdougm if (ret == SA_OK) { 2210a3351425Sdougm parent_group = sa_get_parent_group((sa_share_t)parent); 2211687915e9Sdougm if (optdefs[optindex].share && parent_group != NULL && 2212687915e9Sdougm !sa_is_share(parent_group)) 2213a3351425Sdougm ret = SA_PROP_SHARE_ONLY; 22146185db85Sdougm } 22156185db85Sdougm if (ret == SA_OK) { 2216687915e9Sdougm if (optdefs[optindex].index == OPT_PUBLIC) { 2217687915e9Sdougm /* 2218687915e9Sdougm * Public is special in that only one instance can 2219687915e9Sdougm * be in the repository at the same time. 2220687915e9Sdougm */ 2221687915e9Sdougm if (public_exists(handle, parent_group)) { 2222b89a8333Snatalie li - Sun Microsystems - Irvine United States sa_free_attr_string(propname); 2223687915e9Sdougm return (SA_VALUE_CONFLICT); 2224687915e9Sdougm } 2225687915e9Sdougm } 2226a3351425Sdougm value = sa_get_property_attr(property, "value"); 2227a3351425Sdougm if (value != NULL) { 2228a3351425Sdougm /* first basic type checking */ 2229a3351425Sdougm switch (optdefs[optindex].type) { 22305cb0d679SMarcel Telka 2231a3351425Sdougm case OPT_TYPE_NUMBER: 2232a3351425Sdougm /* check that the value is all digits */ 2233a3351425Sdougm if (!is_a_number(value)) 2234a3351425Sdougm ret = SA_BAD_VALUE; 2235a3351425Sdougm break; 22365cb0d679SMarcel Telka 2237a3351425Sdougm case OPT_TYPE_BOOLEAN: 2238a3351425Sdougm if (strlen(value) == 0 || 2239a3351425Sdougm strcasecmp(value, "true") == 0 || 2240a3351425Sdougm strcmp(value, "1") == 0 || 2241a3351425Sdougm strcasecmp(value, "false") == 0 || 2242a3351425Sdougm strcmp(value, "0") == 0) { 2243a3351425Sdougm ret = SA_OK; 2244a3351425Sdougm } else { 2245a3351425Sdougm ret = SA_BAD_VALUE; 2246a3351425Sdougm } 2247a3351425Sdougm break; 22485cb0d679SMarcel Telka 2249a3351425Sdougm case OPT_TYPE_USER: 22505cb0d679SMarcel Telka ret = check_user(value); 2251a3351425Sdougm break; 22525cb0d679SMarcel Telka 2253a3351425Sdougm case OPT_TYPE_FILE: 2254a3351425Sdougm if (strcmp(value, "..") == 0 || 2255a3351425Sdougm strchr(value, '/') != NULL) { 2256a3351425Sdougm ret = SA_BAD_VALUE; 2257a3351425Sdougm } 2258a3351425Sdougm break; 22595cb0d679SMarcel Telka 2260b89a8333Snatalie li - Sun Microsystems - Irvine United States case OPT_TYPE_ACCLIST: { 2261b89a8333Snatalie li - Sun Microsystems - Irvine United States sa_property_t oprop1; 2262b89a8333Snatalie li - Sun Microsystems - Irvine United States sa_property_t oprop2; 2263b89a8333Snatalie li - Sun Microsystems - Irvine United States char *ovalue1 = NULL; 2264b89a8333Snatalie li - Sun Microsystems - Irvine United States char *ovalue2 = NULL; 2265b89a8333Snatalie li - Sun Microsystems - Irvine United States 2266b89a8333Snatalie li - Sun Microsystems - Irvine United States if (parent == NULL) 2267b89a8333Snatalie li - Sun Microsystems - Irvine United States break; 2268a3351425Sdougm /* 2269a3351425Sdougm * access list handling. Should eventually 2270a3351425Sdougm * validate that all the values make sense. 2271a3351425Sdougm * Also, ro and rw may have cross value 2272a3351425Sdougm * conflicts. 2273a3351425Sdougm */ 2274b89a8333Snatalie li - Sun Microsystems - Irvine United States if (strcmp(propname, SHOPT_RO) == 0) { 2275b89a8333Snatalie li - Sun Microsystems - Irvine United States other1 = SHOPT_RW; 2276b89a8333Snatalie li - Sun Microsystems - Irvine United States other2 = SHOPT_NONE; 2277b89a8333Snatalie li - Sun Microsystems - Irvine United States } else if (strcmp(propname, SHOPT_RW) == 0) { 2278b89a8333Snatalie li - Sun Microsystems - Irvine United States other1 = SHOPT_RO; 2279b89a8333Snatalie li - Sun Microsystems - Irvine United States other2 = SHOPT_NONE; 2280b89a8333Snatalie li - Sun Microsystems - Irvine United States } else if (strcmp(propname, SHOPT_NONE) == 0) { 2281b89a8333Snatalie li - Sun Microsystems - Irvine United States other1 = SHOPT_RO; 2282b89a8333Snatalie li - Sun Microsystems - Irvine United States other2 = SHOPT_RW; 2283b89a8333Snatalie li - Sun Microsystems - Irvine United States } else { 2284b89a8333Snatalie li - Sun Microsystems - Irvine United States other1 = NULL; 2285b89a8333Snatalie li - Sun Microsystems - Irvine United States other2 = NULL; 2286a3351425Sdougm } 2287b89a8333Snatalie li - Sun Microsystems - Irvine United States if (other1 == NULL && other2 == NULL) 2288b89a8333Snatalie li - Sun Microsystems - Irvine United States break; 2289b89a8333Snatalie li - Sun Microsystems - Irvine United States 2290b89a8333Snatalie li - Sun Microsystems - Irvine United States /* compare rw(ro) with ro(rw) */ 2291b89a8333Snatalie li - Sun Microsystems - Irvine United States 2292b89a8333Snatalie li - Sun Microsystems - Irvine United States oprop1 = sa_get_property(parent, other1); 2293b89a8333Snatalie li - Sun Microsystems - Irvine United States oprop2 = sa_get_property(parent, other2); 2294b89a8333Snatalie li - Sun Microsystems - Irvine United States if (oprop1 == NULL && oprop2 == NULL) 2295b89a8333Snatalie li - Sun Microsystems - Irvine United States break; 2296b89a8333Snatalie li - Sun Microsystems - Irvine United States /* 2297b89a8333Snatalie li - Sun Microsystems - Irvine United States * Only potential confusion if other1 2298b89a8333Snatalie li - Sun Microsystems - Irvine United States * or other2 exists. Check the values 2299b89a8333Snatalie li - Sun Microsystems - Irvine United States * and run the check if there is a 2300b89a8333Snatalie li - Sun Microsystems - Irvine United States * value other than the one we are 2301b89a8333Snatalie li - Sun Microsystems - Irvine United States * explicitly looking at. 2302b89a8333Snatalie li - Sun Microsystems - Irvine United States */ 2303b89a8333Snatalie li - Sun Microsystems - Irvine United States ovalue1 = sa_get_property_attr(oprop1, "value"); 2304b89a8333Snatalie li - Sun Microsystems - Irvine United States ovalue2 = sa_get_property_attr(oprop2, "value"); 2305b89a8333Snatalie li - Sun Microsystems - Irvine United States if (ovalue1 != NULL || ovalue2 != NULL) 2306b89a8333Snatalie li - Sun Microsystems - Irvine United States ret = check_rorwnone(value, ovalue1, 2307b89a8333Snatalie li - Sun Microsystems - Irvine United States ovalue2); 2308b89a8333Snatalie li - Sun Microsystems - Irvine United States 2309b89a8333Snatalie li - Sun Microsystems - Irvine United States if (ovalue1 != NULL) 2310b89a8333Snatalie li - Sun Microsystems - Irvine United States sa_free_attr_string(ovalue1); 2311b89a8333Snatalie li - Sun Microsystems - Irvine United States if (ovalue2 != NULL) 2312b89a8333Snatalie li - Sun Microsystems - Irvine United States sa_free_attr_string(ovalue2); 2313a3351425Sdougm break; 2314b89a8333Snatalie li - Sun Microsystems - Irvine United States } 23155cb0d679SMarcel Telka 2316a3351425Sdougm case OPT_TYPE_LOGTAG: 2317a3351425Sdougm if (nfsl_getconfig_list(&configlist) == 0) { 2318a3351425Sdougm int error; 2319a3351425Sdougm if (value == NULL || 2320a3351425Sdougm strlen(value) == 0) { 2321a3351425Sdougm if (value != NULL) 2322a3351425Sdougm sa_free_attr_string( 2323a3351425Sdougm value); 2324a3351425Sdougm value = strdup("global"); 2325a3351425Sdougm } 2326a3351425Sdougm if (value != NULL && 2327a3351425Sdougm nfsl_findconfig(configlist, value, 2328a3351425Sdougm &error) == NULL) { 2329a3351425Sdougm ret = SA_BAD_VALUE; 2330a3351425Sdougm } 2331aed5d200Sdougm /* Must always free when done */ 2332aed5d200Sdougm nfsl_freeconfig_list(&configlist); 2333a3351425Sdougm } else { 2334a3351425Sdougm ret = SA_CONFIG_ERR; 2335a3351425Sdougm } 2336a3351425Sdougm break; 23375cb0d679SMarcel Telka 2338a3351425Sdougm case OPT_TYPE_STRING: 2339a3351425Sdougm /* whatever is here should be ok */ 2340a3351425Sdougm break; 23415cb0d679SMarcel Telka 2342a3351425Sdougm case OPT_TYPE_SECURITY: 2343a3351425Sdougm /* 2344a3351425Sdougm * The "sec" property isn't used in the 2345a3351425Sdougm * non-legacy parts of sharemgr. We need to 2346a3351425Sdougm * reject it here. For legacy, it is pulled 2347a3351425Sdougm * out well before we get here. 2348a3351425Sdougm */ 2349a3351425Sdougm ret = SA_NO_SUCH_PROP; 2350a3351425Sdougm break; 23515cb0d679SMarcel Telka 23525cb0d679SMarcel Telka case OPT_TYPE_MAPPING: { 23535cb0d679SMarcel Telka char *p; 23545cb0d679SMarcel Telka char *n; 23555cb0d679SMarcel Telka char *c; 23565cb0d679SMarcel Telka int (*f)(char *); 23575cb0d679SMarcel Telka 23585cb0d679SMarcel Telka sa_security_t security; 23595cb0d679SMarcel Telka 23605cb0d679SMarcel Telka /* 23615cb0d679SMarcel Telka * mapping is only supported for sec=sys 23625cb0d679SMarcel Telka */ 23635cb0d679SMarcel Telka ret = SA_CONFIG_ERR; 23645cb0d679SMarcel Telka if (parent_group == NULL) 23655cb0d679SMarcel Telka break; 23665cb0d679SMarcel Telka 23675cb0d679SMarcel Telka for (security = sa_get_security(parent_group, 23685cb0d679SMarcel Telka NULL, NULL); security != NULL; 23695cb0d679SMarcel Telka security = sa_get_next_security(security)) { 23705cb0d679SMarcel Telka char *type; 23715cb0d679SMarcel Telka char *sectype; 23725cb0d679SMarcel Telka 23735cb0d679SMarcel Telka type = sa_get_security_attr(security, 23745cb0d679SMarcel Telka "type"); 23755cb0d679SMarcel Telka if (type == NULL) 23765cb0d679SMarcel Telka continue; 23775cb0d679SMarcel Telka 23785cb0d679SMarcel Telka if (strcmp(type, "nfs") != 0) { 23795cb0d679SMarcel Telka sa_free_attr_string(type); 23805cb0d679SMarcel Telka continue; 23815cb0d679SMarcel Telka } 23825cb0d679SMarcel Telka sa_free_attr_string(type); 23835cb0d679SMarcel Telka 23845cb0d679SMarcel Telka sectype = sa_get_security_attr(security, 23855cb0d679SMarcel Telka "sectype"); 23865cb0d679SMarcel Telka if (sectype == NULL) 23875cb0d679SMarcel Telka continue; 23885cb0d679SMarcel Telka 23895cb0d679SMarcel Telka if (strcmp(sectype, "sys") != 0) { 23905cb0d679SMarcel Telka sa_free_attr_string(sectype); 23915cb0d679SMarcel Telka ret = SA_CONFIG_ERR; 23925cb0d679SMarcel Telka break; 23935cb0d679SMarcel Telka } 23945cb0d679SMarcel Telka sa_free_attr_string(sectype); 23955cb0d679SMarcel Telka ret = SA_OK; 23965cb0d679SMarcel Telka } 23975cb0d679SMarcel Telka 23985cb0d679SMarcel Telka if (ret != SA_OK) 23995cb0d679SMarcel Telka break; 24005cb0d679SMarcel Telka 24015cb0d679SMarcel Telka assert(optindex == OPT_UIDMAP || 24025cb0d679SMarcel Telka optindex == OPT_GIDMAP); 24035cb0d679SMarcel Telka f = optindex == OPT_UIDMAP ? check_user : 24045cb0d679SMarcel Telka check_group; 24055cb0d679SMarcel Telka 24065cb0d679SMarcel Telka 24075cb0d679SMarcel Telka p = strdup(value); 24085cb0d679SMarcel Telka if (p == NULL) 24095cb0d679SMarcel Telka ret = SA_BAD_VALUE; 24105cb0d679SMarcel Telka 24115cb0d679SMarcel Telka for (c = p; ret == SA_OK && c != NULL; c = n) { 24125cb0d679SMarcel Telka char *s; 24135cb0d679SMarcel Telka char *t; 24145cb0d679SMarcel Telka 24155cb0d679SMarcel Telka n = strchr(c, '~'); 24165cb0d679SMarcel Telka if (n != NULL) 24175cb0d679SMarcel Telka *n++ = '\0'; 24185cb0d679SMarcel Telka 24195cb0d679SMarcel Telka s = strchr(c, ':'); 24205cb0d679SMarcel Telka if (s != NULL) { 24215cb0d679SMarcel Telka *s++ = '\0'; 24225cb0d679SMarcel Telka t = strchr(s, ':'); 24235cb0d679SMarcel Telka if (t != NULL) 24245cb0d679SMarcel Telka *t = '\0'; 24255cb0d679SMarcel Telka } 24265cb0d679SMarcel Telka 24275cb0d679SMarcel Telka if (s == NULL || t == NULL) 24285cb0d679SMarcel Telka ret = SA_BAD_VALUE; 24295cb0d679SMarcel Telka 24305cb0d679SMarcel Telka if (ret == SA_OK && *c != '\0' && 24315cb0d679SMarcel Telka strcmp(c, "*") != 0) 24325cb0d679SMarcel Telka ret = f(c); 24335cb0d679SMarcel Telka 24345cb0d679SMarcel Telka if (ret == SA_OK && *s != '\0' && 24355cb0d679SMarcel Telka strcmp(s, "-1") != 0) 24365cb0d679SMarcel Telka ret = f(s); 24375cb0d679SMarcel Telka } 24385cb0d679SMarcel Telka 24395cb0d679SMarcel Telka free(p); 24405cb0d679SMarcel Telka 24415cb0d679SMarcel Telka break; 24425cb0d679SMarcel Telka } 24435cb0d679SMarcel Telka 2444a3351425Sdougm default: 2445a3351425Sdougm break; 24466185db85Sdougm } 2447aed5d200Sdougm 2448aed5d200Sdougm if (value != NULL) 2449aed5d200Sdougm sa_free_attr_string(value); 2450aed5d200Sdougm 2451a3351425Sdougm if (ret == SA_OK && optdefs[optindex].check != NULL) { 2452a3351425Sdougm /* do the property specific check */ 2453687915e9Sdougm ret = optdefs[optindex].check(handle, property); 24546185db85Sdougm } 24556185db85Sdougm } 24566185db85Sdougm } 24576185db85Sdougm 24586185db85Sdougm if (propname != NULL) 2459a3351425Sdougm sa_free_attr_string(propname); 24606185db85Sdougm return (ret); 24616185db85Sdougm } 24626185db85Sdougm 24636185db85Sdougm /* 24646185db85Sdougm * Protocol management functions 24656185db85Sdougm * 24663472f5dcSdougm * Properties defined in the default files are defined in 24673472f5dcSdougm * proto_option_defs for parsing and validation. If "other" and 24683472f5dcSdougm * "compare" are set, then the value for this property should be 24693472f5dcSdougm * compared against the property specified in "other" using the 24703472f5dcSdougm * "compare" check (either <= or >=) in order to ensure that the 24713472f5dcSdougm * values are in the correct range. E.g. setting server_versmin 24723472f5dcSdougm * higher than server_versmax should not be allowed. 24736185db85Sdougm */ 24746185db85Sdougm 24756185db85Sdougm struct proto_option_defs { 24766185db85Sdougm char *tag; 24776185db85Sdougm char *name; /* display name -- remove protocol identifier */ 24786185db85Sdougm int index; 24796185db85Sdougm int type; 24806185db85Sdougm union { 24816185db85Sdougm int intval; 24826185db85Sdougm char *string; 24836185db85Sdougm } defvalue; 24846185db85Sdougm uint32_t svcs; 24856185db85Sdougm int32_t minval; 24866185db85Sdougm int32_t maxval; 24873472f5dcSdougm char *other; 24883472f5dcSdougm int compare; 24893472f5dcSdougm #define OPT_CMP_GE 0 24903472f5dcSdougm #define OPT_CMP_LE 1 24916185db85Sdougm int (*check)(char *); 24926185db85Sdougm } proto_options[] = { 24936185db85Sdougm #define PROTO_OPT_NFSD_SERVERS 0 24946185db85Sdougm {"nfsd_servers", 24956185db85Sdougm "servers", PROTO_OPT_NFSD_SERVERS, OPT_TYPE_NUMBER, 16, SVC_NFSD, 2496dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States 1, INT32_MAX}, 24976185db85Sdougm #define PROTO_OPT_LOCKD_LISTEN_BACKLOG 1 24986185db85Sdougm {"lockd_listen_backlog", 24996185db85Sdougm "lockd_listen_backlog", PROTO_OPT_LOCKD_LISTEN_BACKLOG, 2500dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States OPT_TYPE_NUMBER, 32, SVC_LOCKD, 32, INT32_MAX}, 25016185db85Sdougm #define PROTO_OPT_LOCKD_SERVERS 2 25026185db85Sdougm {"lockd_servers", 25036185db85Sdougm "lockd_servers", PROTO_OPT_LOCKD_SERVERS, OPT_TYPE_NUMBER, 20, 2504dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States SVC_LOCKD, 1, INT32_MAX}, 25056185db85Sdougm #define PROTO_OPT_LOCKD_RETRANSMIT_TIMEOUT 3 25066185db85Sdougm {"lockd_retransmit_timeout", 25076185db85Sdougm "lockd_retransmit_timeout", PROTO_OPT_LOCKD_RETRANSMIT_TIMEOUT, 2508dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States OPT_TYPE_NUMBER, 5, SVC_LOCKD, 0, INT32_MAX}, 25096185db85Sdougm #define PROTO_OPT_GRACE_PERIOD 4 25106185db85Sdougm {"grace_period", 25116185db85Sdougm "grace_period", PROTO_OPT_GRACE_PERIOD, OPT_TYPE_NUMBER, 90, 2512dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States SVC_LOCKD, 0, INT32_MAX}, 25136185db85Sdougm #define PROTO_OPT_NFS_SERVER_VERSMIN 5 25146185db85Sdougm {"nfs_server_versmin", 25156185db85Sdougm "server_versmin", PROTO_OPT_NFS_SERVER_VERSMIN, OPT_TYPE_NUMBER, 25166185db85Sdougm (int)NFS_VERSMIN_DEFAULT, SVC_NFSD|SVC_MOUNTD, NFS_VERSMIN, 2517dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States NFS_VERSMAX, "server_versmax", OPT_CMP_LE}, 25186185db85Sdougm #define PROTO_OPT_NFS_SERVER_VERSMAX 6 25196185db85Sdougm {"nfs_server_versmax", 25206185db85Sdougm "server_versmax", PROTO_OPT_NFS_SERVER_VERSMAX, OPT_TYPE_NUMBER, 25216185db85Sdougm (int)NFS_VERSMAX_DEFAULT, SVC_NFSD|SVC_MOUNTD, NFS_VERSMIN, 2522dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States NFS_VERSMAX, "server_versmin", OPT_CMP_GE}, 25236185db85Sdougm #define PROTO_OPT_NFS_CLIENT_VERSMIN 7 25246185db85Sdougm {"nfs_client_versmin", 25256185db85Sdougm "client_versmin", PROTO_OPT_NFS_CLIENT_VERSMIN, OPT_TYPE_NUMBER, 2526dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States (int)NFS_VERSMIN_DEFAULT, SVC_CLIENT, NFS_VERSMIN, NFS_VERSMAX, 2527dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States "client_versmax", OPT_CMP_LE}, 25286185db85Sdougm #define PROTO_OPT_NFS_CLIENT_VERSMAX 8 25296185db85Sdougm {"nfs_client_versmax", 25306185db85Sdougm "client_versmax", PROTO_OPT_NFS_CLIENT_VERSMAX, OPT_TYPE_NUMBER, 2531dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States (int)NFS_VERSMAX_DEFAULT, SVC_CLIENT, NFS_VERSMIN, NFS_VERSMAX, 2532dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States "client_versmin", OPT_CMP_GE}, 25336185db85Sdougm #define PROTO_OPT_NFS_SERVER_DELEGATION 9 25346185db85Sdougm {"nfs_server_delegation", 25356185db85Sdougm "server_delegation", PROTO_OPT_NFS_SERVER_DELEGATION, 2536dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States OPT_TYPE_ONOFF, NFS_SERVER_DELEGATION_DEFAULT, SVC_NFSD, 0, 0}, 25376185db85Sdougm #define PROTO_OPT_NFSMAPID_DOMAIN 10 25386185db85Sdougm {"nfsmapid_domain", 25396185db85Sdougm "nfsmapid_domain", PROTO_OPT_NFSMAPID_DOMAIN, OPT_TYPE_DOMAIN, 2540dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States NULL, SVC_NFSMAPID, 0, 0}, 25416185db85Sdougm #define PROTO_OPT_NFSD_MAX_CONNECTIONS 11 25426185db85Sdougm {"nfsd_max_connections", 25436185db85Sdougm "max_connections", PROTO_OPT_NFSD_MAX_CONNECTIONS, 2544dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States OPT_TYPE_NUMBER, -1, SVC_NFSD, -1, INT32_MAX}, 25456185db85Sdougm #define PROTO_OPT_NFSD_PROTOCOL 12 25466185db85Sdougm {"nfsd_protocol", 25476185db85Sdougm "protocol", PROTO_OPT_NFSD_PROTOCOL, OPT_TYPE_PROTOCOL, 0, 2548dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States SVC_NFSD, 0, 0}, 25496185db85Sdougm #define PROTO_OPT_NFSD_LISTEN_BACKLOG 13 25506185db85Sdougm {"nfsd_listen_backlog", 25516185db85Sdougm "listen_backlog", PROTO_OPT_NFSD_LISTEN_BACKLOG, 2552dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States OPT_TYPE_NUMBER, 0, SVC_NFSD, 0, INT32_MAX}, 2553dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States #define PROTO_OPT_NFSD_DEVICE 14 2554dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States {"nfsd_device", 2555dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States "device", PROTO_OPT_NFSD_DEVICE, 2556dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States OPT_TYPE_STRING, NULL, SVC_NFSD, 0, 0}, 2557361f55a5SMarcel Telka #define PROTO_OPT_MOUNTD_LISTEN_BACKLOG 15 2558361f55a5SMarcel Telka {"mountd_listen_backlog", 2559361f55a5SMarcel Telka "mountd_listen_backlog", PROTO_OPT_MOUNTD_LISTEN_BACKLOG, 2560361f55a5SMarcel Telka OPT_TYPE_NUMBER, 64, SVC_NFSD|SVC_MOUNTD, 1, INT32_MAX}, 2561361f55a5SMarcel Telka #define PROTO_OPT_MOUNTD_MAX_THREADS 16 2562361f55a5SMarcel Telka {"mountd_max_threads", 2563361f55a5SMarcel Telka "mountd_max_threads", PROTO_OPT_MOUNTD_MAX_THREADS, 2564361f55a5SMarcel Telka OPT_TYPE_NUMBER, 16, SVC_NFSD|SVC_MOUNTD, 1, INT32_MAX}, 25656185db85Sdougm {NULL} 25666185db85Sdougm }; 25676185db85Sdougm 25686185db85Sdougm /* 25696185db85Sdougm * the protoset holds the defined options so we don't have to read 25706185db85Sdougm * them multiple times 25716185db85Sdougm */ 2572aed5d200Sdougm static sa_protocol_properties_t protoset; 25736185db85Sdougm 25746185db85Sdougm static int 25756185db85Sdougm findprotoopt(char *name, int whichname) 25766185db85Sdougm { 25776185db85Sdougm int i; 25786185db85Sdougm for (i = 0; proto_options[i].tag != NULL; i++) { 2579a3351425Sdougm if (whichname == 1) { 2580a3351425Sdougm if (strcasecmp(proto_options[i].name, name) == 0) 25816185db85Sdougm return (i); 2582a3351425Sdougm } else { 2583a3351425Sdougm if (strcasecmp(proto_options[i].tag, name) == 0) 2584a3351425Sdougm return (i); 2585a3351425Sdougm } 25866185db85Sdougm } 25876185db85Sdougm return (-1); 25886185db85Sdougm } 25896185db85Sdougm 25906185db85Sdougm /* 25916185db85Sdougm * fixcaselower(str) 25926185db85Sdougm * 25936185db85Sdougm * convert a string to lower case (inplace). 25946185db85Sdougm */ 25956185db85Sdougm 25966185db85Sdougm static void 25976185db85Sdougm fixcaselower(char *str) 25986185db85Sdougm { 25996185db85Sdougm while (*str) { 2600a3351425Sdougm *str = tolower(*str); 2601a3351425Sdougm str++; 26026185db85Sdougm } 26036185db85Sdougm } 26046185db85Sdougm 2605330ef417Sdougm /* 2606330ef417Sdougm * skipwhitespace(str) 2607330ef417Sdougm * 2608330ef417Sdougm * Skip leading white space. It is assumed that it is called with a 2609330ef417Sdougm * valid pointer. 2610330ef417Sdougm */ 2611330ef417Sdougm 2612330ef417Sdougm static char * 2613330ef417Sdougm skipwhitespace(char *str) 2614330ef417Sdougm { 2615330ef417Sdougm while (*str && isspace(*str)) 2616330ef417Sdougm str++; 2617330ef417Sdougm 2618330ef417Sdougm return (str); 2619330ef417Sdougm } 2620330ef417Sdougm 2621a3351425Sdougm /* 2622a3351425Sdougm * extractprop() 2623a3351425Sdougm * 2624a3351425Sdougm * Extract the property and value out of the line and create the 2625a3351425Sdougm * property in the optionset. 2626a3351425Sdougm */ 2627e7bab347Sdougm static int 2628a3351425Sdougm extractprop(char *name, char *value) 2629a3351425Sdougm { 2630a3351425Sdougm sa_property_t prop; 2631a3351425Sdougm int index; 2632e7bab347Sdougm int ret = SA_OK; 2633a3351425Sdougm /* 2634a3351425Sdougm * Remove any leading 2635a3351425Sdougm * white space. 2636a3351425Sdougm */ 2637a3351425Sdougm name = skipwhitespace(name); 2638a3351425Sdougm 2639dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States index = findprotoopt(name, 1); 2640a3351425Sdougm if (index >= 0) { 2641a3351425Sdougm fixcaselower(name); 2642a3351425Sdougm prop = sa_create_property(proto_options[index].name, value); 2643a3351425Sdougm if (prop != NULL) 2644e7bab347Sdougm ret = sa_add_protocol_property(protoset, prop); 2645e7bab347Sdougm else 2646e7bab347Sdougm ret = SA_NO_MEMORY; 2647a3351425Sdougm } 2648e7bab347Sdougm return (ret); 2649a3351425Sdougm } 2650a3351425Sdougm 2651dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States scf_type_t 2652dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States getscftype(int type) 2653dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States { 2654dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States scf_type_t ret; 2655dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States 2656dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States switch (type) { 2657dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States case OPT_TYPE_NUMBER: 2658dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States ret = SCF_TYPE_INTEGER; 2659dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States break; 2660dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States case OPT_TYPE_BOOLEAN: 2661dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States ret = SCF_TYPE_BOOLEAN; 2662dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States break; 2663dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States default: 2664dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States ret = SCF_TYPE_ASTRING; 2665dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States } 2666dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States return (ret); 2667dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States } 2668dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States 2669dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States char * 2670dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States getsvcname(uint32_t svcs) 2671dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States { 2672dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States char *service; 2673dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States switch (svcs) { 2674dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States case SVC_LOCKD: 2675dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States service = LOCKD; 2676dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States break; 2677dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States case SVC_STATD: 2678dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States service = STATD; 2679dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States break; 2680dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States case SVC_NFSD: 2681dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States service = NFSD; 2682dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States break; 2683dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States case SVC_CLIENT: 2684dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States service = NFS_CLIENT_SVC; 2685dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States break; 2686dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States case SVC_NFS4CBD: 2687dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States service = NFS4CBD; 2688dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States break; 2689dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States case SVC_NFSMAPID: 2690dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States service = NFSMAPID; 2691dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States break; 2692dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States case SVC_RQUOTAD: 2693dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States service = RQUOTAD; 2694dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States break; 2695dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States case SVC_NFSLOGD: 2696dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States service = NFSLOGD; 2697dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States break; 2698dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States case SVC_REPARSED: 2699dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States service = REPARSED; 2700dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States break; 2701dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States default: 2702dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States service = NFSD; 2703dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States } 2704dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States return (service); 2705dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States } 2706dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States 27076185db85Sdougm /* 2708dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States * initprotofromsmf() 27096185db85Sdougm * 2710dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States * Read NFS SMF properties and add the defined values to the 27116185db85Sdougm * protoset. Note that default values are known from the built in 2712dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States * table in case SMF doesn't have a definition. Not having 2713dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States * SMF properties is OK since we have builtin default 2714dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States * values. 27156185db85Sdougm */ 27166185db85Sdougm static int 2717dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States initprotofromsmf() 27186185db85Sdougm { 2719dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States char name[PATH_MAX]; 2720dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States char value[PATH_MAX]; 2721dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States int ret = SA_OK, bufsz = 0, i; 27226185db85Sdougm 27236185db85Sdougm protoset = sa_create_protocol_properties("nfs"); 27246185db85Sdougm if (protoset != NULL) { 2725dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States for (i = 0; proto_options[i].tag != NULL; i++) { 2726dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States scf_type_t ptype; 2727dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States char *svc_name; 2728dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States 2729dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States bzero(value, PATH_MAX); 2730dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States (void) strncpy(name, proto_options[i].name, PATH_MAX); 2731dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States /* Replace NULL with the correct instance */ 2732dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States ptype = getscftype(proto_options[i].type); 2733dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States svc_name = getsvcname(proto_options[i].svcs); 2734dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States bufsz = PATH_MAX; 2735dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States ret = nfs_smf_get_prop(name, value, 2736dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States (char *)DEFAULT_INSTANCE, ptype, 2737dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States svc_name, &bufsz); 2738dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States if (ret == SA_OK) { 2739dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States ret = extractprop(name, value); 2740917c27c8Sdougm } 27416185db85Sdougm } 2742e7bab347Sdougm } else { 2743e7bab347Sdougm ret = SA_NO_MEMORY; 27446185db85Sdougm } 2745dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States 2746e7bab347Sdougm return (ret); 27476185db85Sdougm } 27486185db85Sdougm 27496185db85Sdougm /* 2750a3351425Sdougm * add_defaults() 27516185db85Sdougm * 2752dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States * Add the default values for any property not defined 2753dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States * in NFS SMF repository. 2754dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States * Values are set according to their defined types. 27556185db85Sdougm */ 27566185db85Sdougm 27576185db85Sdougm static void 27586185db85Sdougm add_defaults() 27596185db85Sdougm { 27606185db85Sdougm int i; 27616185db85Sdougm char number[MAXDIGITS]; 27626185db85Sdougm 27636185db85Sdougm for (i = 0; proto_options[i].tag != NULL; i++) { 2764a3351425Sdougm sa_property_t prop; 2765a3351425Sdougm prop = sa_get_protocol_property(protoset, 2766a3351425Sdougm proto_options[i].name); 2767a3351425Sdougm if (prop == NULL) { 2768a3351425Sdougm /* add the default value */ 2769a3351425Sdougm switch (proto_options[i].type) { 2770a3351425Sdougm case OPT_TYPE_NUMBER: 2771a3351425Sdougm (void) snprintf(number, sizeof (number), "%d", 2772a3351425Sdougm proto_options[i].defvalue.intval); 2773a3351425Sdougm prop = sa_create_property(proto_options[i].name, 2774a3351425Sdougm number); 2775a3351425Sdougm break; 2776a3351425Sdougm 2777a3351425Sdougm case OPT_TYPE_BOOLEAN: 2778a3351425Sdougm prop = sa_create_property(proto_options[i].name, 2779a3351425Sdougm proto_options[i].defvalue.intval ? 2780a3351425Sdougm "true" : "false"); 2781a3351425Sdougm break; 2782a3351425Sdougm 2783a3351425Sdougm case OPT_TYPE_ONOFF: 2784a3351425Sdougm prop = sa_create_property(proto_options[i].name, 2785a3351425Sdougm proto_options[i].defvalue.intval ? 2786a3351425Sdougm "on" : "off"); 2787a3351425Sdougm break; 2788a3351425Sdougm 2789a3351425Sdougm default: 2790a3351425Sdougm /* treat as strings of zero length */ 2791a3351425Sdougm prop = sa_create_property(proto_options[i].name, 2792a3351425Sdougm ""); 2793a3351425Sdougm break; 2794a3351425Sdougm } 2795a3351425Sdougm if (prop != NULL) 2796a3351425Sdougm (void) sa_add_protocol_property(protoset, prop); 27976185db85Sdougm } 27986185db85Sdougm } 27996185db85Sdougm } 28006185db85Sdougm 28016185db85Sdougm static void 28026185db85Sdougm free_protoprops() 28036185db85Sdougm { 2804aed5d200Sdougm if (protoset != NULL) { 2805aed5d200Sdougm xmlFreeNode(protoset); 2806aed5d200Sdougm protoset = NULL; 2807aed5d200Sdougm } 28086185db85Sdougm } 28096185db85Sdougm 28106185db85Sdougm /* 28116185db85Sdougm * nfs_init() 28126185db85Sdougm * 28136185db85Sdougm * Initialize the NFS plugin. 28146185db85Sdougm */ 28156185db85Sdougm 28166185db85Sdougm static int 28176185db85Sdougm nfs_init() 28186185db85Sdougm { 28196185db85Sdougm int ret = SA_OK; 28206185db85Sdougm 2821917c27c8Sdougm if (sa_plugin_ops.sa_init != nfs_init) { 2822a3351425Sdougm (void) printf(dgettext(TEXT_DOMAIN, 2823a3351425Sdougm "NFS plugin not properly initialized\n")); 2824917c27c8Sdougm return (SA_CONFIG_ERR); 2825917c27c8Sdougm } 28266185db85Sdougm 2827dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States ret = initprotofromsmf(); 2828917c27c8Sdougm if (ret != SA_OK) { 2829917c27c8Sdougm (void) printf(dgettext(TEXT_DOMAIN, 2830dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States "NFS plugin problem with SMF repository: %s\n"), 2831917c27c8Sdougm sa_errorstr(ret)); 2832917c27c8Sdougm ret = SA_OK; 2833917c27c8Sdougm } 2834917c27c8Sdougm add_defaults(); 28356185db85Sdougm 28366185db85Sdougm return (ret); 28376185db85Sdougm } 28386185db85Sdougm 28396185db85Sdougm /* 28406185db85Sdougm * nfs_fini() 28416185db85Sdougm * 28426185db85Sdougm * uninitialize the NFS plugin. Want to avoid memory leaks. 28436185db85Sdougm */ 28446185db85Sdougm 28456185db85Sdougm static void 28466185db85Sdougm nfs_fini() 28476185db85Sdougm { 28486185db85Sdougm free_protoprops(); 28496185db85Sdougm } 28506185db85Sdougm 28516185db85Sdougm /* 28526185db85Sdougm * nfs_get_proto_set() 28536185db85Sdougm * 28546185db85Sdougm * Return an optionset with all the protocol specific properties in 28556185db85Sdougm * it. 28566185db85Sdougm */ 28576185db85Sdougm 28586185db85Sdougm static sa_protocol_properties_t 28596185db85Sdougm nfs_get_proto_set() 28606185db85Sdougm { 28616185db85Sdougm return (protoset); 28626185db85Sdougm } 28636185db85Sdougm 28643472f5dcSdougm /* 28653472f5dcSdougm * service_in_state(service, chkstate) 28663472f5dcSdougm * 28673472f5dcSdougm * Want to know if the specified service is in the desired state 28683472f5dcSdougm * (chkstate) or not. Return true (1) if it is and false (0) if it 28693472f5dcSdougm * isn't. 28703472f5dcSdougm */ 28713472f5dcSdougm static int 28723472f5dcSdougm service_in_state(char *service, const char *chkstate) 28733472f5dcSdougm { 28743472f5dcSdougm char *state; 28753472f5dcSdougm int ret = B_FALSE; 28763472f5dcSdougm 28773472f5dcSdougm state = smf_get_state(service); 28783472f5dcSdougm if (state != NULL) { 2879a3351425Sdougm /* got the state so get the equality for the return value */ 2880a3351425Sdougm ret = strcmp(state, chkstate) == 0 ? B_TRUE : B_FALSE; 2881a3351425Sdougm free(state); 28823472f5dcSdougm } 28833472f5dcSdougm return (ret); 28843472f5dcSdougm } 28853472f5dcSdougm 28866185db85Sdougm /* 28876185db85Sdougm * restart_service(svcs) 28886185db85Sdougm * 28896185db85Sdougm * Walk through the bit mask of services that need to be restarted in 28906185db85Sdougm * order to use the new property values. Some properties affect 28913472f5dcSdougm * multiple daemons. Should only restart a service if it is currently 28923472f5dcSdougm * enabled (online). 28936185db85Sdougm */ 28946185db85Sdougm 28956185db85Sdougm static void 28966185db85Sdougm restart_service(uint32_t svcs) 28976185db85Sdougm { 28986185db85Sdougm uint32_t mask; 28993472f5dcSdougm int ret; 29003472f5dcSdougm char *service; 29013472f5dcSdougm 29026185db85Sdougm for (mask = 1; svcs != 0; mask <<= 1) { 2903a3351425Sdougm switch (svcs & mask) { 2904a3351425Sdougm case SVC_LOCKD: 2905a3351425Sdougm service = LOCKD; 2906a3351425Sdougm break; 2907a3351425Sdougm case SVC_STATD: 2908a3351425Sdougm service = STATD; 2909a3351425Sdougm break; 2910a3351425Sdougm case SVC_NFSD: 2911a3351425Sdougm service = NFSD; 2912a3351425Sdougm break; 2913a3351425Sdougm case SVC_MOUNTD: 2914a3351425Sdougm service = MOUNTD; 2915a3351425Sdougm break; 2916a3351425Sdougm case SVC_NFS4CBD: 2917a3351425Sdougm service = NFS4CBD; 2918a3351425Sdougm break; 2919a3351425Sdougm case SVC_NFSMAPID: 2920a3351425Sdougm service = NFSMAPID; 2921a3351425Sdougm break; 2922a3351425Sdougm case SVC_RQUOTAD: 2923a3351425Sdougm service = RQUOTAD; 2924a3351425Sdougm break; 2925a3351425Sdougm case SVC_NFSLOGD: 2926a3351425Sdougm service = NFSLOGD; 2927a3351425Sdougm break; 29282f172c55SRobert Thurlow case SVC_REPARSED: 29292f172c55SRobert Thurlow service = REPARSED; 29302f172c55SRobert Thurlow break; 2931dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States case SVC_CLIENT: 2932dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States service = NFS_CLIENT_SVC; 2933dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States break; 2934a3351425Sdougm default: 2935a3351425Sdougm continue; 2936a3351425Sdougm } 29373472f5dcSdougm 29383472f5dcSdougm /* 29393472f5dcSdougm * Only attempt to restart the service if it is 29403472f5dcSdougm * currently running. In the future, it may be 29413472f5dcSdougm * desirable to use smf_refresh_instance if the NFS 29423472f5dcSdougm * services ever implement the refresh method. 29433472f5dcSdougm */ 2944a3351425Sdougm if (service_in_state(service, SCF_STATE_STRING_ONLINE)) { 2945a3351425Sdougm ret = smf_restart_instance(service); 29463472f5dcSdougm /* 2947a3351425Sdougm * There are only a few SMF errors at this point, but 2948a3351425Sdougm * it is also possible that a bad value may have put 2949a3351425Sdougm * the service into maintenance if there wasn't an 2950a3351425Sdougm * SMF level error. 29513472f5dcSdougm */ 2952a3351425Sdougm if (ret != 0) { 2953a3351425Sdougm (void) fprintf(stderr, 2954a3351425Sdougm dgettext(TEXT_DOMAIN, 2955a3351425Sdougm "%s failed to restart: %s\n"), 295603205638SMarcel Telka service, scf_strerror(scf_error())); 2957a3351425Sdougm } else { 2958a3351425Sdougm /* 2959a3351425Sdougm * Check whether it has gone to "maintenance" 2960a3351425Sdougm * mode or not. Maintenance implies something 2961a3351425Sdougm * went wrong. 2962a3351425Sdougm */ 2963a3351425Sdougm if (service_in_state(service, 2964a3351425Sdougm SCF_STATE_STRING_MAINT)) { 2965a3351425Sdougm (void) fprintf(stderr, 2966a3351425Sdougm dgettext(TEXT_DOMAIN, 2967a3351425Sdougm "%s failed to restart\n"), 2968a3351425Sdougm service); 2969a3351425Sdougm } 2970a3351425Sdougm } 29713472f5dcSdougm } 2972a3351425Sdougm svcs &= ~mask; 29736185db85Sdougm } 29746185db85Sdougm } 29756185db85Sdougm 29763472f5dcSdougm /* 29773472f5dcSdougm * nfs_minmax_check(name, value) 29783472f5dcSdougm * 29793472f5dcSdougm * Verify that the value for the property specified by index is valid 29803472f5dcSdougm * relative to the opposite value in the case of a min/max variable. 29813472f5dcSdougm * Currently, server_minvers/server_maxvers and 29823472f5dcSdougm * client_minvers/client_maxvers are the only ones to check. 29833472f5dcSdougm */ 29843472f5dcSdougm 29853472f5dcSdougm static int 29863472f5dcSdougm nfs_minmax_check(int index, int value) 29873472f5dcSdougm { 29883472f5dcSdougm int val; 29893472f5dcSdougm char *pval; 29903472f5dcSdougm sa_property_t prop; 29913472f5dcSdougm sa_optionset_t opts; 29923472f5dcSdougm int ret = B_TRUE; 29933472f5dcSdougm 29943472f5dcSdougm if (proto_options[index].other != NULL) { 2995a3351425Sdougm /* have a property to compare against */ 2996a3351425Sdougm opts = nfs_get_proto_set(); 2997a3351425Sdougm prop = sa_get_property(opts, proto_options[index].other); 29983472f5dcSdougm /* 29993472f5dcSdougm * If we don't find the property, assume default 30003472f5dcSdougm * values which will work since the max will be at the 30013472f5dcSdougm * max and the min at the min. 30023472f5dcSdougm */ 3003a3351425Sdougm if (prop != NULL) { 3004a3351425Sdougm pval = sa_get_property_attr(prop, "value"); 3005a3351425Sdougm if (pval != NULL) { 3006a3351425Sdougm val = strtoul(pval, NULL, 0); 3007a3351425Sdougm if (proto_options[index].compare == 3008a3351425Sdougm OPT_CMP_LE) { 3009a3351425Sdougm ret = value <= val ? B_TRUE : B_FALSE; 3010a3351425Sdougm } else if (proto_options[index].compare == 3011a3351425Sdougm OPT_CMP_GE) { 3012a3351425Sdougm ret = value >= val ? B_TRUE : B_FALSE; 3013a3351425Sdougm } 3014fe1c642dSBill Krier sa_free_attr_string(pval); 3015a3351425Sdougm } 30163472f5dcSdougm } 30173472f5dcSdougm } 30183472f5dcSdougm return (ret); 30193472f5dcSdougm } 30203472f5dcSdougm 30216185db85Sdougm /* 30226185db85Sdougm * nfs_validate_proto_prop(index, name, value) 30236185db85Sdougm * 3024da6c28aaSamw * Verify that the property specified by name can take the new 30256185db85Sdougm * value. This is a sanity check to prevent bad values getting into 30263472f5dcSdougm * the default files. All values need to be checked against what is 30273472f5dcSdougm * allowed by their defined type. If a type isn't explicitly defined 30283472f5dcSdougm * here, it is treated as a string. 30293472f5dcSdougm * 30303472f5dcSdougm * Note that OPT_TYPE_NUMBER will additionally check that the value is 30313472f5dcSdougm * within the range specified and potentially against another property 30323472f5dcSdougm * value as well as specified in the proto_options members other and 30333472f5dcSdougm * compare. 30346185db85Sdougm */ 30356185db85Sdougm 30366185db85Sdougm static int 30376185db85Sdougm nfs_validate_proto_prop(int index, char *name, char *value) 30386185db85Sdougm { 30396185db85Sdougm int ret = SA_OK; 30406185db85Sdougm char *cp; 30416185db85Sdougm #ifdef lint 30426185db85Sdougm name = name; 30436185db85Sdougm #endif 30446185db85Sdougm switch (proto_options[index].type) { 30456185db85Sdougm case OPT_TYPE_NUMBER: 3046a3351425Sdougm if (!is_a_number(value)) 3047a3351425Sdougm ret = SA_BAD_VALUE; 3048a3351425Sdougm else { 3049a3351425Sdougm int val; 3050a3351425Sdougm val = strtoul(value, NULL, 0); 3051a3351425Sdougm if (val < proto_options[index].minval || 3052a3351425Sdougm val > proto_options[index].maxval) 3053a3351425Sdougm ret = SA_BAD_VALUE; 3054a3351425Sdougm /* 3055a3351425Sdougm * For server_versmin/server_versmax and 3056a3351425Sdougm * client_versmin/client_versmax, the value of the 3057a3351425Sdougm * min(max) should be checked to be correct relative 3058a3351425Sdougm * to the current max(min). 3059a3351425Sdougm */ 3060a3351425Sdougm if (!nfs_minmax_check(index, val)) { 3061a3351425Sdougm ret = SA_BAD_VALUE; 3062a3351425Sdougm } 30633472f5dcSdougm } 3064a3351425Sdougm break; 30653472f5dcSdougm 30666185db85Sdougm case OPT_TYPE_DOMAIN: 30676185db85Sdougm /* 30683472f5dcSdougm * needs to be a qualified domain so will have at 30693472f5dcSdougm * least one period and other characters on either 30703472f5dcSdougm * side of it. A zero length string is also allowed 30713472f5dcSdougm * and is the way to turn off the override. 30726185db85Sdougm */ 3073a3351425Sdougm if (strlen(value) == 0) 3074a3351425Sdougm break; 3075a3351425Sdougm cp = strchr(value, '.'); 3076a3351425Sdougm if (cp == NULL || cp == value || strchr(value, '@') != NULL) 3077a3351425Sdougm ret = SA_BAD_VALUE; 30783472f5dcSdougm break; 30793472f5dcSdougm 30806185db85Sdougm case OPT_TYPE_BOOLEAN: 3081a3351425Sdougm if (strlen(value) == 0 || 3082a3351425Sdougm strcasecmp(value, "true") == 0 || 3083a3351425Sdougm strcmp(value, "1") == 0 || 3084a3351425Sdougm strcasecmp(value, "false") == 0 || 3085a3351425Sdougm strcmp(value, "0") == 0) { 3086a3351425Sdougm ret = SA_OK; 3087a3351425Sdougm } else { 3088a3351425Sdougm ret = SA_BAD_VALUE; 3089a3351425Sdougm } 3090a3351425Sdougm break; 30913472f5dcSdougm 30926185db85Sdougm case OPT_TYPE_ONOFF: 3093a3351425Sdougm if (strcasecmp(value, "on") != 0 && 3094a3351425Sdougm strcasecmp(value, "off") != 0) { 3095a3351425Sdougm ret = SA_BAD_VALUE; 3096a3351425Sdougm } 3097a3351425Sdougm break; 30983472f5dcSdougm 3099*f091aea1SYuri Pankov case OPT_TYPE_PROTOCOL: { 3100*f091aea1SYuri Pankov struct netconfig *nconf; 3101*f091aea1SYuri Pankov void *nc; 3102*f091aea1SYuri Pankov boolean_t pfound = B_FALSE; 3103*f091aea1SYuri Pankov 3104*f091aea1SYuri Pankov if (strcasecmp(value, "all") == 0) 3105*f091aea1SYuri Pankov break; 3106*f091aea1SYuri Pankov 3107*f091aea1SYuri Pankov if ((nc = setnetconfig()) == NULL) { 3108*f091aea1SYuri Pankov (void) fprintf(stderr, dgettext(TEXT_DOMAIN, 3109*f091aea1SYuri Pankov "setnetconfig failed: %s\n"), strerror(errno)); 3110*f091aea1SYuri Pankov } else { 3111*f091aea1SYuri Pankov while ((nconf = getnetconfig(nc)) != NULL) { 3112*f091aea1SYuri Pankov if (strcmp(nconf->nc_proto, value) == 0) { 3113*f091aea1SYuri Pankov pfound = B_TRUE; 3114*f091aea1SYuri Pankov break; 3115*f091aea1SYuri Pankov } 3116*f091aea1SYuri Pankov } 3117*f091aea1SYuri Pankov (void) endnetconfig(nc); 3118*f091aea1SYuri Pankov } 3119*f091aea1SYuri Pankov 3120*f091aea1SYuri Pankov if (!pfound) 3121a3351425Sdougm ret = SA_BAD_VALUE; 3122a3351425Sdougm break; 3123*f091aea1SYuri Pankov } 31243472f5dcSdougm 31253472f5dcSdougm default: 3126a3351425Sdougm /* treat as a string */ 3127a3351425Sdougm break; 31286185db85Sdougm } 31296185db85Sdougm return (ret); 31306185db85Sdougm } 31316185db85Sdougm 31326185db85Sdougm /* 31336185db85Sdougm * nfs_set_proto_prop(prop) 31346185db85Sdougm * 31356185db85Sdougm * check that prop is valid. 31366185db85Sdougm */ 31376185db85Sdougm 31386185db85Sdougm static int 31396185db85Sdougm nfs_set_proto_prop(sa_property_t prop) 31406185db85Sdougm { 31416185db85Sdougm int ret = SA_OK; 31426185db85Sdougm char *name; 31436185db85Sdougm char *value; 31446185db85Sdougm 31456185db85Sdougm name = sa_get_property_attr(prop, "type"); 31466185db85Sdougm value = sa_get_property_attr(prop, "value"); 31476185db85Sdougm if (name != NULL && value != NULL) { 3148dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States scf_type_t sctype; 3149dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States char *svc_name; 3150dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States char *instance = NULL; 3151a3351425Sdougm int index = findprotoopt(name, 1); 3152dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States 3153dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States ret = nfs_validate_proto_prop(index, name, value); 3154dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States if (ret == SA_OK) { 3155dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States sctype = getscftype(proto_options[index].type); 3156dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States svc_name = getsvcname(proto_options[index].svcs); 3157dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States if (sctype == SCF_TYPE_BOOLEAN) { 3158dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States if (value != NULL) 3159dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States sa_free_attr_string(value); 3160dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States if (string_to_boolean(value) == 0) 3161dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States value = strdup("0"); 3162dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States else 3163dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States value = strdup("1"); 3164dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States } 3165dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States ret = nfs_smf_set_prop(name, value, instance, sctype, 3166dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States svc_name); 3167dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States if (ret == SA_OK) { 3168a3351425Sdougm restart_service(proto_options[index].svcs); 3169dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States } else { 3170dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States (void) printf(dgettext(TEXT_DOMAIN, 3171dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States "Cannot restart NFS services : %s\n"), 3172dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States sa_errorstr(ret)); 3173dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States } 3174a3351425Sdougm } 31756185db85Sdougm } 31766185db85Sdougm if (name != NULL) 3177a3351425Sdougm sa_free_attr_string(name); 31786185db85Sdougm if (value != NULL) 3179a3351425Sdougm sa_free_attr_string(value); 31806185db85Sdougm return (ret); 31816185db85Sdougm } 31826185db85Sdougm 31836185db85Sdougm /* 31846185db85Sdougm * nfs_get_status() 31856185db85Sdougm * 31866185db85Sdougm * What is the current status of the nfsd? We use the SMF state here. 31876185db85Sdougm * Caller must free the returned value. 31886185db85Sdougm */ 31896185db85Sdougm 31906185db85Sdougm static char * 31916185db85Sdougm nfs_get_status() 31926185db85Sdougm { 3193652601fbSRobert Mustacchi return (smf_get_state(NFSD)); 31946185db85Sdougm } 31956185db85Sdougm 31966185db85Sdougm /* 31976185db85Sdougm * nfs_space_alias(alias) 31986185db85Sdougm * 31996185db85Sdougm * Lookup the space (security) name. If it is default, convert to the 32006185db85Sdougm * real name. 32016185db85Sdougm */ 32026185db85Sdougm 32036185db85Sdougm static char * 32046185db85Sdougm nfs_space_alias(char *space) 32056185db85Sdougm { 32066185db85Sdougm char *name = space; 32076185db85Sdougm seconfig_t secconf; 3208a99982a7Sdougm 3209a99982a7Sdougm /* 3210a99982a7Sdougm * Only the space named "default" is special. If it is used, 3211a99982a7Sdougm * the default needs to be looked up and the real name used. 3212a99982a7Sdougm * This is normally "sys" but could be changed. We always 32135cb0d679SMarcel Telka * change default to the real name. 3214a99982a7Sdougm */ 3215a99982a7Sdougm if (strcmp(space, "default") == 0 && 3216a99982a7Sdougm nfs_getseconfig_default(&secconf) == 0) { 3217a3351425Sdougm if (nfs_getseconfig_bynumber(secconf.sc_nfsnum, &secconf) == 0) 3218a3351425Sdougm name = secconf.sc_name; 32196185db85Sdougm } 32206185db85Sdougm return (strdup(name)); 32216185db85Sdougm } 3222da6c28aaSamw 3223da6c28aaSamw /* 3224da6c28aaSamw * nfs_features() 3225da6c28aaSamw * 3226da6c28aaSamw * Return a mask of the features required. 3227da6c28aaSamw */ 3228da6c28aaSamw 3229da6c28aaSamw static uint64_t 3230da6c28aaSamw nfs_features() 3231da6c28aaSamw { 32329e5da854Sdougm return ((uint64_t)SA_FEATURE_DFSTAB | SA_FEATURE_SERVER); 3233da6c28aaSamw } 3234