1*6185db85Sdougm /* 2*6185db85Sdougm * CDDL HEADER START 3*6185db85Sdougm * 4*6185db85Sdougm * The contents of this file are subject to the terms of the 5*6185db85Sdougm * Common Development and Distribution License (the "License"). 6*6185db85Sdougm * You may not use this file except in compliance with the License. 7*6185db85Sdougm * 8*6185db85Sdougm * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*6185db85Sdougm * or http://www.opensolaris.org/os/licensing. 10*6185db85Sdougm * See the License for the specific language governing permissions 11*6185db85Sdougm * and limitations under the License. 12*6185db85Sdougm * 13*6185db85Sdougm * When distributing Covered Code, include this CDDL HEADER in each 14*6185db85Sdougm * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*6185db85Sdougm * If applicable, add the following below this CDDL HEADER, with the 16*6185db85Sdougm * fields enclosed by brackets "[]" replaced with your own identifying 17*6185db85Sdougm * information: Portions Copyright [yyyy] [name of copyright owner] 18*6185db85Sdougm * 19*6185db85Sdougm * CDDL HEADER END 20*6185db85Sdougm */ 21*6185db85Sdougm 22*6185db85Sdougm /* 23*6185db85Sdougm * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 24*6185db85Sdougm * Use is subject to license terms. 25*6185db85Sdougm */ 26*6185db85Sdougm 27*6185db85Sdougm #pragma ident "%Z%%M% %I% %E% SMI" 28*6185db85Sdougm 29*6185db85Sdougm /* helper functions for using libscf with sharemgr */ 30*6185db85Sdougm 31*6185db85Sdougm #include <libscf.h> 32*6185db85Sdougm #include <libxml/parser.h> 33*6185db85Sdougm #include <libxml/tree.h> 34*6185db85Sdougm #include "libshare.h" 35*6185db85Sdougm #include "libshare_impl.h" 36*6185db85Sdougm #include "scfutil.h" 37*6185db85Sdougm #include <string.h> 38*6185db85Sdougm #include <errno.h> 39*6185db85Sdougm #include <uuid/uuid.h> 40*6185db85Sdougm #include <sys/param.h> 41*6185db85Sdougm 42*6185db85Sdougm ssize_t scf_max_name_len; 43*6185db85Sdougm extern struct sa_proto_plugin *sap_proto_list; 44*6185db85Sdougm 45*6185db85Sdougm /* 46*6185db85Sdougm * The SMF facility uses some properties that must exist. We want to 47*6185db85Sdougm * skip over these when processing protocol options. 48*6185db85Sdougm */ 49*6185db85Sdougm static char *skip_props[] = { 50*6185db85Sdougm "modify_authorization", 51*6185db85Sdougm "action_authorization", 52*6185db85Sdougm "value_authorization", 53*6185db85Sdougm NULL 54*6185db85Sdougm }; 55*6185db85Sdougm 56*6185db85Sdougm /* 57*6185db85Sdougm * sa_scf_fini(handle) 58*6185db85Sdougm * 59*6185db85Sdougm * must be called when done. Called with the handle allocated in 60*6185db85Sdougm * sa_scf_init(), it cleans up the state and frees any SCF resources 61*6185db85Sdougm * still in use. Called by sa_fini(). 62*6185db85Sdougm */ 63*6185db85Sdougm 64*6185db85Sdougm void 65*6185db85Sdougm sa_scf_fini(scfutilhandle_t *handle) 66*6185db85Sdougm { 67*6185db85Sdougm if (handle != NULL) { 68*6185db85Sdougm int unbind = 0; 69*6185db85Sdougm if (handle->scope != NULL) { 70*6185db85Sdougm unbind = 1; 71*6185db85Sdougm scf_scope_destroy(handle->scope); 72*6185db85Sdougm } 73*6185db85Sdougm if (handle->service != NULL) 74*6185db85Sdougm scf_service_destroy(handle->service); 75*6185db85Sdougm if (handle->pg != NULL) 76*6185db85Sdougm scf_pg_destroy(handle->pg); 77*6185db85Sdougm if (handle->handle != NULL) { 78*6185db85Sdougm handle->scf_state = SCH_STATE_UNINIT; 79*6185db85Sdougm if (unbind) 80*6185db85Sdougm (void) scf_handle_unbind(handle->handle); 81*6185db85Sdougm scf_handle_destroy(handle->handle); 82*6185db85Sdougm } 83*6185db85Sdougm free(handle); 84*6185db85Sdougm } 85*6185db85Sdougm } 86*6185db85Sdougm 87*6185db85Sdougm /* 88*6185db85Sdougm * sa_scf_init() 89*6185db85Sdougm * 90*6185db85Sdougm * must be called before using any of the SCF functions. Called by 91*6185db85Sdougm * sa_init() during the API setup. 92*6185db85Sdougm */ 93*6185db85Sdougm 94*6185db85Sdougm scfutilhandle_t * 95*6185db85Sdougm sa_scf_init() 96*6185db85Sdougm { 97*6185db85Sdougm scfutilhandle_t *handle; 98*6185db85Sdougm 99*6185db85Sdougm scf_max_name_len = scf_limit(SCF_LIMIT_MAX_NAME_LENGTH); 100*6185db85Sdougm if (scf_max_name_len <= 0) 101*6185db85Sdougm scf_max_name_len = SA_MAX_NAME_LEN + 1; 102*6185db85Sdougm 103*6185db85Sdougm handle = calloc(1, sizeof (scfutilhandle_t)); 104*6185db85Sdougm if (handle != NULL) { 105*6185db85Sdougm handle->scf_state = SCH_STATE_INITIALIZING; 106*6185db85Sdougm handle->handle = scf_handle_create(SCF_VERSION); 107*6185db85Sdougm if (handle->handle != NULL) { 108*6185db85Sdougm if (scf_handle_bind(handle->handle) == 0) { 109*6185db85Sdougm handle->scope = scf_scope_create(handle->handle); 110*6185db85Sdougm handle->service = scf_service_create(handle->handle); 111*6185db85Sdougm handle->pg = scf_pg_create(handle->handle); 112*6185db85Sdougm handle->instance = scf_instance_create(handle->handle); 113*6185db85Sdougm if (scf_handle_get_scope(handle->handle, 114*6185db85Sdougm SCF_SCOPE_LOCAL, handle->scope) == 0) { 115*6185db85Sdougm if (scf_scope_get_service(handle->scope, 116*6185db85Sdougm SA_GROUP_SVC_NAME, 117*6185db85Sdougm handle->service) != 0) { 118*6185db85Sdougm goto err; 119*6185db85Sdougm } 120*6185db85Sdougm handle->scf_state = SCH_STATE_INIT; 121*6185db85Sdougm if (sa_get_instance(handle, "default") != SA_OK) { 122*6185db85Sdougm char **protolist; 123*6185db85Sdougm int numprotos, i; 124*6185db85Sdougm sa_group_t defgrp; 125*6185db85Sdougm defgrp = sa_create_group("default", NULL); 126*6185db85Sdougm if (defgrp != NULL) { 127*6185db85Sdougm numprotos = sa_get_protocols(&protolist); 128*6185db85Sdougm for (i = 0; i < numprotos; i++) { 129*6185db85Sdougm (void) sa_create_optionset(defgrp, 130*6185db85Sdougm protolist[i]); 131*6185db85Sdougm } 132*6185db85Sdougm if (protolist != NULL) 133*6185db85Sdougm free(protolist); 134*6185db85Sdougm } 135*6185db85Sdougm } 136*6185db85Sdougm } else { 137*6185db85Sdougm goto err; 138*6185db85Sdougm } 139*6185db85Sdougm } else { 140*6185db85Sdougm goto err; 141*6185db85Sdougm } 142*6185db85Sdougm } else { 143*6185db85Sdougm free(handle); 144*6185db85Sdougm handle = NULL; 145*6185db85Sdougm (void) printf("libshare could not access SMF repository: %s\n", 146*6185db85Sdougm scf_strerror(scf_error())); 147*6185db85Sdougm } 148*6185db85Sdougm } 149*6185db85Sdougm return (handle); 150*6185db85Sdougm 151*6185db85Sdougm /* error handling/unwinding */ 152*6185db85Sdougm err: 153*6185db85Sdougm (void) sa_scf_fini(handle); 154*6185db85Sdougm (void) printf("libshare SMF initialization problem: %s\n", 155*6185db85Sdougm scf_strerror(scf_error())); 156*6185db85Sdougm return (NULL); 157*6185db85Sdougm } 158*6185db85Sdougm 159*6185db85Sdougm /* 160*6185db85Sdougm * get_scf_limit(name) 161*6185db85Sdougm * 162*6185db85Sdougm * Since we use scf_limit a lot and do the same check and return the 163*6185db85Sdougm * same value if it fails, implement as a function for code 164*6185db85Sdougm * simplification. Basically, if name isn't found, return MAXPATHLEN 165*6185db85Sdougm * (1024) so we have a reasonable default buffer size. 166*6185db85Sdougm */ 167*6185db85Sdougm static ssize_t 168*6185db85Sdougm get_scf_limit(uint32_t name) 169*6185db85Sdougm { 170*6185db85Sdougm ssize_t vallen; 171*6185db85Sdougm 172*6185db85Sdougm vallen = scf_limit(name); 173*6185db85Sdougm if (vallen == (ssize_t)-1) 174*6185db85Sdougm vallen = MAXPATHLEN; 175*6185db85Sdougm return (vallen); 176*6185db85Sdougm } 177*6185db85Sdougm 178*6185db85Sdougm /* 179*6185db85Sdougm * skip_property(name) 180*6185db85Sdougm * 181*6185db85Sdougm * internal function to check to see if a property is an SMF magic 182*6185db85Sdougm * property that needs to be skipped. 183*6185db85Sdougm */ 184*6185db85Sdougm static int 185*6185db85Sdougm skip_property(char *name) 186*6185db85Sdougm { 187*6185db85Sdougm int i; 188*6185db85Sdougm 189*6185db85Sdougm for (i = 0; skip_props[i] != NULL; i++) 190*6185db85Sdougm if (strcmp(name, skip_props[i]) == 0) 191*6185db85Sdougm return (1); 192*6185db85Sdougm return (0); 193*6185db85Sdougm } 194*6185db85Sdougm 195*6185db85Sdougm /* 196*6185db85Sdougm * generate_unique_sharename(sharename) 197*6185db85Sdougm * 198*6185db85Sdougm * Shares are represented in SMF as property groups. Due to share 199*6185db85Sdougm * paths containing characters that are not allowed in SMF names and 200*6185db85Sdougm * the need to be unique, we use UUIDs to construct a unique name. 201*6185db85Sdougm */ 202*6185db85Sdougm 203*6185db85Sdougm static void 204*6185db85Sdougm generate_unique_sharename(char *sharename) 205*6185db85Sdougm { 206*6185db85Sdougm uuid_t uuid; 207*6185db85Sdougm 208*6185db85Sdougm uuid_generate(uuid); 209*6185db85Sdougm (void) strcpy(sharename, "S-"); 210*6185db85Sdougm uuid_unparse(uuid, sharename + 2); 211*6185db85Sdougm } 212*6185db85Sdougm 213*6185db85Sdougm /* 214*6185db85Sdougm * valid_protocol(proto) 215*6185db85Sdougm * 216*6185db85Sdougm * check to see if the specified protocol is a valid one for the 217*6185db85Sdougm * general sharemgr facility. We determine this by checking which 218*6185db85Sdougm * plugin protocols were found. 219*6185db85Sdougm */ 220*6185db85Sdougm 221*6185db85Sdougm static int 222*6185db85Sdougm valid_protocol(char *proto) 223*6185db85Sdougm { 224*6185db85Sdougm struct sa_proto_plugin *plugin; 225*6185db85Sdougm for (plugin = sap_proto_list; plugin != NULL; 226*6185db85Sdougm plugin = plugin->plugin_next) 227*6185db85Sdougm if (strcmp(proto, plugin->plugin_ops->sa_protocol) == 0) 228*6185db85Sdougm return (1); 229*6185db85Sdougm return (0); 230*6185db85Sdougm } 231*6185db85Sdougm 232*6185db85Sdougm /* 233*6185db85Sdougm * sa_extract_pgroup(root, handle, pg, nodetype, proto, sectype) 234*6185db85Sdougm * 235*6185db85Sdougm * extract the name property group and create the specified type of 236*6185db85Sdougm * node on the provided group. type will be optionset or security. 237*6185db85Sdougm */ 238*6185db85Sdougm 239*6185db85Sdougm static int 240*6185db85Sdougm sa_extract_pgroup(xmlNodePtr root, scfutilhandle_t *handle, 241*6185db85Sdougm scf_propertygroup_t *pg, 242*6185db85Sdougm char *nodetype, char *proto, char *sectype) 243*6185db85Sdougm { 244*6185db85Sdougm xmlNodePtr node; 245*6185db85Sdougm scf_iter_t *iter; 246*6185db85Sdougm scf_property_t *prop; 247*6185db85Sdougm scf_value_t *value; 248*6185db85Sdougm char *name; 249*6185db85Sdougm char *valuestr; 250*6185db85Sdougm ssize_t vallen; 251*6185db85Sdougm int ret = SA_OK; 252*6185db85Sdougm 253*6185db85Sdougm vallen = get_scf_limit(SCF_LIMIT_MAX_VALUE_LENGTH); 254*6185db85Sdougm 255*6185db85Sdougm node = xmlNewChild(root, NULL, (xmlChar *)nodetype, NULL); 256*6185db85Sdougm if (node != NULL) { 257*6185db85Sdougm if (proto != NULL) 258*6185db85Sdougm xmlSetProp(node, (xmlChar *)"type", (xmlChar *)proto); 259*6185db85Sdougm if (sectype != NULL) 260*6185db85Sdougm xmlSetProp(node, (xmlChar *)"sectype", (xmlChar *)sectype); 261*6185db85Sdougm /* 262*6185db85Sdougm * have node to work with so iterate over the properties 263*6185db85Sdougm * in the pg and create option sub nodes. 264*6185db85Sdougm */ 265*6185db85Sdougm iter = scf_iter_create(handle->handle); 266*6185db85Sdougm value = scf_value_create(handle->handle); 267*6185db85Sdougm prop = scf_property_create(handle->handle); 268*6185db85Sdougm name = malloc(scf_max_name_len); 269*6185db85Sdougm valuestr = malloc(vallen); 270*6185db85Sdougm /* 271*6185db85Sdougm * want to iterate through the properties and add them 272*6185db85Sdougm * to the base optionset. 273*6185db85Sdougm */ 274*6185db85Sdougm if (iter != NULL && value != NULL && prop != NULL && 275*6185db85Sdougm valuestr != NULL && name != NULL) { 276*6185db85Sdougm if (scf_iter_pg_properties(iter, pg) == 0) { 277*6185db85Sdougm /* now iterate the properties in the group */ 278*6185db85Sdougm while (scf_iter_next_property(iter, prop) > 0) { 279*6185db85Sdougm /* have a property */ 280*6185db85Sdougm if (scf_property_get_name(prop, name, 281*6185db85Sdougm scf_max_name_len) > 0) { 282*6185db85Sdougm /* some properties are part of the framework */ 283*6185db85Sdougm if (skip_property(name)) 284*6185db85Sdougm continue; 285*6185db85Sdougm if (scf_property_get_value(prop, value) == 0) { 286*6185db85Sdougm if (scf_value_get_astring(value, valuestr, 287*6185db85Sdougm vallen) >= 0) { 288*6185db85Sdougm sa_property_t saprop; 289*6185db85Sdougm saprop = sa_create_property(name, 290*6185db85Sdougm valuestr); 291*6185db85Sdougm if (saprop != NULL) { 292*6185db85Sdougm /* 293*6185db85Sdougm * since in SMF, don't 294*6185db85Sdougm * recurse. Use xmlAddChild 295*6185db85Sdougm * directly, instead. 296*6185db85Sdougm */ 297*6185db85Sdougm xmlAddChild(node, 298*6185db85Sdougm (xmlNodePtr) saprop); 299*6185db85Sdougm } 300*6185db85Sdougm } 301*6185db85Sdougm } 302*6185db85Sdougm } 303*6185db85Sdougm } 304*6185db85Sdougm } 305*6185db85Sdougm } else { 306*6185db85Sdougm ret = SA_NO_MEMORY; 307*6185db85Sdougm } 308*6185db85Sdougm /* cleanup to avoid memory leaks */ 309*6185db85Sdougm if (value != NULL) 310*6185db85Sdougm scf_value_destroy(value); 311*6185db85Sdougm if (iter != NULL) 312*6185db85Sdougm scf_iter_destroy(iter); 313*6185db85Sdougm if (prop != NULL) 314*6185db85Sdougm scf_property_destroy(prop); 315*6185db85Sdougm if (name != NULL) 316*6185db85Sdougm free(name); 317*6185db85Sdougm if (valuestr != NULL) 318*6185db85Sdougm free(valuestr); 319*6185db85Sdougm } 320*6185db85Sdougm return (ret); 321*6185db85Sdougm } 322*6185db85Sdougm 323*6185db85Sdougm /* 324*6185db85Sdougm * sa_extract_attrs(root, handle, instance) 325*6185db85Sdougm * 326*6185db85Sdougm * local function to extract the actual attributes/properties from the 327*6185db85Sdougm * property group of the service instance. These are the well known 328*6185db85Sdougm * attributes of "state" and "zfs". If additional attributes are 329*6185db85Sdougm * added, they should be added here. 330*6185db85Sdougm */ 331*6185db85Sdougm 332*6185db85Sdougm static void 333*6185db85Sdougm sa_extract_attrs(xmlNodePtr root, scfutilhandle_t *handle, 334*6185db85Sdougm scf_instance_t *instance) 335*6185db85Sdougm { 336*6185db85Sdougm scf_property_t *prop; 337*6185db85Sdougm scf_value_t *value; 338*6185db85Sdougm char *valuestr; 339*6185db85Sdougm ssize_t vallen; 340*6185db85Sdougm 341*6185db85Sdougm vallen = get_scf_limit(SCF_LIMIT_MAX_VALUE_LENGTH); 342*6185db85Sdougm prop = scf_property_create(handle->handle); 343*6185db85Sdougm value = scf_value_create(handle->handle); 344*6185db85Sdougm valuestr = malloc(vallen); 345*6185db85Sdougm if (prop != NULL && value != NULL && valuestr != NULL && 346*6185db85Sdougm scf_instance_get_pg(instance, "operation", 347*6185db85Sdougm handle->pg) == 0) { 348*6185db85Sdougm /* 349*6185db85Sdougm * have a property group with desired name so now get 350*6185db85Sdougm * the known attributes. 351*6185db85Sdougm */ 352*6185db85Sdougm if (scf_pg_get_property(handle->pg, "state", prop) == 0) { 353*6185db85Sdougm /* found the property so get the value */ 354*6185db85Sdougm if (scf_property_get_value(prop, value) == 0) { 355*6185db85Sdougm if (scf_value_get_astring(value, valuestr, vallen) >= 0) { 356*6185db85Sdougm xmlSetProp(root, (xmlChar *)"state", 357*6185db85Sdougm (xmlChar *)valuestr); 358*6185db85Sdougm } 359*6185db85Sdougm } 360*6185db85Sdougm } 361*6185db85Sdougm if (scf_pg_get_property(handle->pg, "zfs", prop) == 0) { 362*6185db85Sdougm /* found the property so get the value */ 363*6185db85Sdougm if (scf_property_get_value(prop, value) == 0) { 364*6185db85Sdougm if (scf_value_get_astring(value, valuestr, vallen) > 0) { 365*6185db85Sdougm xmlSetProp(root, (xmlChar *)"zfs", 366*6185db85Sdougm (xmlChar *)valuestr); 367*6185db85Sdougm } 368*6185db85Sdougm } 369*6185db85Sdougm } 370*6185db85Sdougm } 371*6185db85Sdougm if (valuestr != NULL) 372*6185db85Sdougm free(valuestr); 373*6185db85Sdougm if (value != NULL) 374*6185db85Sdougm scf_value_destroy(value); 375*6185db85Sdougm if (prop != NULL) 376*6185db85Sdougm scf_property_destroy(prop); 377*6185db85Sdougm } 378*6185db85Sdougm 379*6185db85Sdougm /* 380*6185db85Sdougm * list of known share attributes. 381*6185db85Sdougm */ 382*6185db85Sdougm 383*6185db85Sdougm static char *share_attr[] = { 384*6185db85Sdougm "path", 385*6185db85Sdougm "id", 386*6185db85Sdougm "resource", 387*6185db85Sdougm NULL, 388*6185db85Sdougm }; 389*6185db85Sdougm 390*6185db85Sdougm static int 391*6185db85Sdougm is_share_attr(char *name) 392*6185db85Sdougm { 393*6185db85Sdougm int i; 394*6185db85Sdougm for (i = 0; share_attr[i] != NULL; i++) 395*6185db85Sdougm if (strcmp(name, share_attr[i]) == 0) 396*6185db85Sdougm return (1); 397*6185db85Sdougm return (0); 398*6185db85Sdougm } 399*6185db85Sdougm 400*6185db85Sdougm /* 401*6185db85Sdougm * sa_share_from_pgroup 402*6185db85Sdougm * 403*6185db85Sdougm * extract the share definition from the share property group. We do 404*6185db85Sdougm * some sanity checking to avoid bad data. 405*6185db85Sdougm * 406*6185db85Sdougm * Since this is only constructing the internal data structures, we 407*6185db85Sdougm * don't use the sa_* functions most of the time. 408*6185db85Sdougm */ 409*6185db85Sdougm void 410*6185db85Sdougm sa_share_from_pgroup(xmlNodePtr root, scfutilhandle_t *handle, 411*6185db85Sdougm scf_propertygroup_t *pg, char *id) 412*6185db85Sdougm { 413*6185db85Sdougm xmlNodePtr node; 414*6185db85Sdougm char *name; 415*6185db85Sdougm scf_iter_t *iter; 416*6185db85Sdougm scf_property_t *prop; 417*6185db85Sdougm scf_value_t *value; 418*6185db85Sdougm ssize_t vallen; 419*6185db85Sdougm char *valuestr; 420*6185db85Sdougm int ret = SA_OK; 421*6185db85Sdougm 422*6185db85Sdougm /* 423*6185db85Sdougm * While preliminary check (starts with 'S') passed before 424*6185db85Sdougm * getting here. Need to make sure it is in ID syntax 425*6185db85Sdougm * (Snnnnnn). Note that shares with properties have similar 426*6185db85Sdougm * pgroups. 427*6185db85Sdougm */ 428*6185db85Sdougm vallen = strlen(id); 429*6185db85Sdougm if (*id == SA_SHARE_PG_PREFIX[0] && vallen == SA_SHARE_PG_LEN) { 430*6185db85Sdougm uuid_t uuid; 431*6185db85Sdougm if (strncmp(id, SA_SHARE_PG_PREFIX, SA_SHARE_PG_PREFIXLEN) != 0 || 432*6185db85Sdougm uuid_parse(id + 2, uuid) < 0) 433*6185db85Sdougm return; 434*6185db85Sdougm } else { 435*6185db85Sdougm return; 436*6185db85Sdougm } 437*6185db85Sdougm 438*6185db85Sdougm vallen = get_scf_limit(SCF_LIMIT_MAX_VALUE_LENGTH); 439*6185db85Sdougm 440*6185db85Sdougm iter = scf_iter_create(handle->handle); 441*6185db85Sdougm value = scf_value_create(handle->handle); 442*6185db85Sdougm prop = scf_property_create(handle->handle); 443*6185db85Sdougm name = malloc(scf_max_name_len); 444*6185db85Sdougm valuestr = malloc(vallen); 445*6185db85Sdougm 446*6185db85Sdougm /* 447*6185db85Sdougm * construct the share XML node. It is similar to sa_add_share 448*6185db85Sdougm * but never changes the repository. Also, there won't be any 449*6185db85Sdougm * ZFS or transient shares. Root will be the group it is 450*6185db85Sdougm * associated with. 451*6185db85Sdougm */ 452*6185db85Sdougm node = xmlNewChild(root, NULL, (xmlChar *)"share", NULL); 453*6185db85Sdougm if (node != NULL) { 454*6185db85Sdougm /* 455*6185db85Sdougm * make sure the UUID part of the property group is 456*6185db85Sdougm * stored in the share "id" property. We use this 457*6185db85Sdougm * later. 458*6185db85Sdougm */ 459*6185db85Sdougm xmlSetProp(node, (xmlChar *)"id", (xmlChar *)id); 460*6185db85Sdougm xmlSetProp(node, (xmlChar *)"type", (xmlChar *)"persist"); 461*6185db85Sdougm } 462*6185db85Sdougm 463*6185db85Sdougm if (iter != NULL && value != NULL && prop != NULL && name != NULL) { 464*6185db85Sdougm /* iterate over the share pg properties */ 465*6185db85Sdougm if (scf_iter_pg_properties(iter, pg) == 0) { 466*6185db85Sdougm while (scf_iter_next_property(iter, prop) > 0) { 467*6185db85Sdougm ret = SA_SYSTEM_ERR; /* assume the worst */ 468*6185db85Sdougm if (scf_property_get_name(prop, name, 469*6185db85Sdougm scf_max_name_len) > 0) { 470*6185db85Sdougm if (scf_property_get_value(prop, value) == 0) { 471*6185db85Sdougm if (scf_value_get_astring(value, valuestr, 472*6185db85Sdougm vallen) >= 0) { 473*6185db85Sdougm ret = SA_OK; 474*6185db85Sdougm } 475*6185db85Sdougm } 476*6185db85Sdougm } 477*6185db85Sdougm if (ret == SA_OK) { 478*6185db85Sdougm if (is_share_attr(name)) { 479*6185db85Sdougm /* 480*6185db85Sdougm * if a share attr, then simple - 481*6185db85Sdougm * usually path and resource name 482*6185db85Sdougm */ 483*6185db85Sdougm xmlSetProp(node, (xmlChar *)name, 484*6185db85Sdougm (xmlChar *)valuestr); 485*6185db85Sdougm } else { 486*6185db85Sdougm if (strcmp(name, "description") == 0) { 487*6185db85Sdougm /* we have a description node */ 488*6185db85Sdougm xmlNodePtr desc; 489*6185db85Sdougm desc = xmlNewChild(node, NULL, 490*6185db85Sdougm (xmlChar *)"description", 491*6185db85Sdougm NULL); 492*6185db85Sdougm if (desc != NULL) 493*6185db85Sdougm xmlNodeSetContent(desc, 494*6185db85Sdougm (xmlChar *)valuestr); 495*6185db85Sdougm } 496*6185db85Sdougm } 497*6185db85Sdougm } 498*6185db85Sdougm } 499*6185db85Sdougm } 500*6185db85Sdougm } 501*6185db85Sdougm if (name != NULL) 502*6185db85Sdougm free(name); 503*6185db85Sdougm if (valuestr != NULL) 504*6185db85Sdougm free(valuestr); 505*6185db85Sdougm if (value != NULL) 506*6185db85Sdougm scf_value_destroy(value); 507*6185db85Sdougm if (iter != NULL) 508*6185db85Sdougm scf_iter_destroy(iter); 509*6185db85Sdougm if (prop != NULL) 510*6185db85Sdougm scf_property_destroy(prop); 511*6185db85Sdougm } 512*6185db85Sdougm 513*6185db85Sdougm /* 514*6185db85Sdougm * find_share_by_id(shareid) 515*6185db85Sdougm * 516*6185db85Sdougm * Search all shares in all groups until we find the share represented 517*6185db85Sdougm * by "id". 518*6185db85Sdougm */ 519*6185db85Sdougm 520*6185db85Sdougm static sa_share_t 521*6185db85Sdougm find_share_by_id(char *shareid) 522*6185db85Sdougm { 523*6185db85Sdougm sa_group_t group; 524*6185db85Sdougm sa_share_t share = NULL; 525*6185db85Sdougm char *id = NULL; 526*6185db85Sdougm int done = 0; 527*6185db85Sdougm 528*6185db85Sdougm for (group = sa_get_group(NULL); group != NULL && !done; 529*6185db85Sdougm group = sa_get_next_group(group)) { 530*6185db85Sdougm for (share = sa_get_share(group, NULL); share != NULL; 531*6185db85Sdougm share = sa_get_next_share(share)) { 532*6185db85Sdougm id = sa_get_share_attr(share, "id"); 533*6185db85Sdougm if (id != NULL && strcmp(id, shareid) == 0) { 534*6185db85Sdougm sa_free_attr_string(id); 535*6185db85Sdougm id = NULL; 536*6185db85Sdougm done++; 537*6185db85Sdougm break; 538*6185db85Sdougm } 539*6185db85Sdougm if (id != NULL) { 540*6185db85Sdougm sa_free_attr_string(id); 541*6185db85Sdougm id = NULL; 542*6185db85Sdougm } 543*6185db85Sdougm } 544*6185db85Sdougm } 545*6185db85Sdougm return (share); 546*6185db85Sdougm } 547*6185db85Sdougm 548*6185db85Sdougm /* 549*6185db85Sdougm * sa_share_props_from_pgroup(root, handle, pg, id) 550*6185db85Sdougm * 551*6185db85Sdougm * extract share properties from the SMF property group. More sanity 552*6185db85Sdougm * checks are done and the share object is created. We ignore some 553*6185db85Sdougm * errors that could exist in the repository and only worry about 554*6185db85Sdougm * property groups that validate in naming. 555*6185db85Sdougm */ 556*6185db85Sdougm 557*6185db85Sdougm static int 558*6185db85Sdougm sa_share_props_from_pgroup(xmlNodePtr root, scfutilhandle_t *handle, 559*6185db85Sdougm scf_propertygroup_t *pg, char *id) 560*6185db85Sdougm { 561*6185db85Sdougm xmlNodePtr node; 562*6185db85Sdougm char *name; 563*6185db85Sdougm scf_iter_t *iter; 564*6185db85Sdougm scf_property_t *prop; 565*6185db85Sdougm scf_value_t *value; 566*6185db85Sdougm ssize_t vallen; 567*6185db85Sdougm char *valuestr; 568*6185db85Sdougm int ret = SA_OK; 569*6185db85Sdougm char *sectype = NULL; 570*6185db85Sdougm char *proto; 571*6185db85Sdougm sa_share_t share; 572*6185db85Sdougm 573*6185db85Sdougm /* 574*6185db85Sdougm * While preliminary check (starts with 'S') passed before 575*6185db85Sdougm * getting here. Need to make sure it is in ID syntax 576*6185db85Sdougm * (Snnnnnn). Note that shares with properties have similar 577*6185db85Sdougm * pgroups. If the pg name is more than SA_SHARE_PG_LEN 578*6185db85Sdougm * characters, it is likely one of the protocol/security 579*6185db85Sdougm * versions. 580*6185db85Sdougm */ 581*6185db85Sdougm vallen = strlen(id); 582*6185db85Sdougm if (*id == SA_SHARE_PG_PREFIX[0] && vallen > SA_SHARE_PG_LEN) { 583*6185db85Sdougm uuid_t uuid; 584*6185db85Sdougm if (strncmp(id, SA_SHARE_PG_PREFIX, SA_SHARE_PG_PREFIXLEN) == 0) { 585*6185db85Sdougm proto = strchr(id, '_'); 586*6185db85Sdougm if (proto == NULL) 587*6185db85Sdougm return (ret); 588*6185db85Sdougm *proto++ = '\0'; 589*6185db85Sdougm if (uuid_parse(id + SA_SHARE_PG_PREFIXLEN, uuid) < 0) 590*6185db85Sdougm return (ret); 591*6185db85Sdougm /* 592*6185db85Sdougm * probably a legal optionset so check a few more 593*6185db85Sdougm * syntax points below. 594*6185db85Sdougm */ 595*6185db85Sdougm if (*proto == '\0') { 596*6185db85Sdougm /* not a valid proto (null) */ 597*6185db85Sdougm return (ret); 598*6185db85Sdougm } 599*6185db85Sdougm sectype = strchr(proto, '_'); 600*6185db85Sdougm if (sectype != NULL) 601*6185db85Sdougm *sectype++ = '\0'; 602*6185db85Sdougm if (!valid_protocol(proto)) 603*6185db85Sdougm return (ret); 604*6185db85Sdougm } 605*6185db85Sdougm } else { 606*6185db85Sdougm /* 607*6185db85Sdougm * it is ok to not have what we thought since someone might 608*6185db85Sdougm * have added a name via SMF. 609*6185db85Sdougm */ 610*6185db85Sdougm return (ret); 611*6185db85Sdougm } 612*6185db85Sdougm 613*6185db85Sdougm /* 614*6185db85Sdougm * to get here, we have a valid protocol and possibly a 615*6185db85Sdougm * security. We now have to find the share that it is really 616*6185db85Sdougm * associated with. The "id" portion of the pgroup name will 617*6185db85Sdougm * match. 618*6185db85Sdougm */ 619*6185db85Sdougm 620*6185db85Sdougm share = find_share_by_id(id); 621*6185db85Sdougm if (share == NULL) 622*6185db85Sdougm return (SA_BAD_PATH); 623*6185db85Sdougm 624*6185db85Sdougm root = (xmlNodePtr)share; 625*6185db85Sdougm 626*6185db85Sdougm vallen = get_scf_limit(SCF_LIMIT_MAX_VALUE_LENGTH); 627*6185db85Sdougm 628*6185db85Sdougm iter = scf_iter_create(handle->handle); 629*6185db85Sdougm value = scf_value_create(handle->handle); 630*6185db85Sdougm prop = scf_property_create(handle->handle); 631*6185db85Sdougm name = malloc(scf_max_name_len); 632*6185db85Sdougm valuestr = malloc(vallen); 633*6185db85Sdougm 634*6185db85Sdougm if (sectype == NULL) 635*6185db85Sdougm node = xmlNewChild(root, NULL, (xmlChar *)"optionset", NULL); 636*6185db85Sdougm else { 637*6185db85Sdougm node = xmlNewChild(root, NULL, (xmlChar *)"security", NULL); 638*6185db85Sdougm if (node != NULL) 639*6185db85Sdougm xmlSetProp(node, (xmlChar *)"sectype", (xmlChar *)sectype); 640*6185db85Sdougm } 641*6185db85Sdougm if (node != NULL) { 642*6185db85Sdougm xmlSetProp(node, (xmlChar *)"type", (xmlChar *)proto); 643*6185db85Sdougm /* now find the properties */ 644*6185db85Sdougm if (iter != NULL && value != NULL && prop != NULL && name != NULL) { 645*6185db85Sdougm /* iterate over the share pg properties */ 646*6185db85Sdougm if (scf_iter_pg_properties(iter, pg) == 0) { 647*6185db85Sdougm while (scf_iter_next_property(iter, prop) > 0) { 648*6185db85Sdougm ret = SA_SYSTEM_ERR; /* assume the worst */ 649*6185db85Sdougm if (scf_property_get_name(prop, name, 650*6185db85Sdougm scf_max_name_len) > 0) { 651*6185db85Sdougm if (scf_property_get_value(prop, value) == 0) { 652*6185db85Sdougm if (scf_value_get_astring(value, valuestr, 653*6185db85Sdougm vallen) >= 0) { 654*6185db85Sdougm ret = SA_OK; 655*6185db85Sdougm } 656*6185db85Sdougm } 657*6185db85Sdougm } else { 658*6185db85Sdougm ret = SA_SYSTEM_ERR; 659*6185db85Sdougm } 660*6185db85Sdougm if (ret == SA_OK) { 661*6185db85Sdougm sa_property_t prop; 662*6185db85Sdougm prop = sa_create_property(name, valuestr); 663*6185db85Sdougm if (prop != NULL) 664*6185db85Sdougm prop = (sa_property_t)xmlAddChild(node, 665*6185db85Sdougm (xmlNodePtr)prop); 666*6185db85Sdougm else 667*6185db85Sdougm ret = SA_NO_MEMORY; 668*6185db85Sdougm } 669*6185db85Sdougm } 670*6185db85Sdougm } else { 671*6185db85Sdougm ret = SA_SYSTEM_ERR; 672*6185db85Sdougm } 673*6185db85Sdougm } 674*6185db85Sdougm } else { 675*6185db85Sdougm ret = SA_NO_MEMORY; 676*6185db85Sdougm } 677*6185db85Sdougm if (iter != NULL) 678*6185db85Sdougm scf_iter_destroy(iter); 679*6185db85Sdougm if (value != NULL) 680*6185db85Sdougm scf_value_destroy(value); 681*6185db85Sdougm if (prop != NULL) 682*6185db85Sdougm scf_property_destroy(prop); 683*6185db85Sdougm if (name != NULL) 684*6185db85Sdougm free(name); 685*6185db85Sdougm if (valuestr != NULL) 686*6185db85Sdougm free(valuestr); 687*6185db85Sdougm return (ret); 688*6185db85Sdougm } 689*6185db85Sdougm 690*6185db85Sdougm /* 691*6185db85Sdougm * sa_extract_group(root, handle, instance) 692*6185db85Sdougm * 693*6185db85Sdougm * get the config info for this instance of a group and create the XML 694*6185db85Sdougm * subtree from it. 695*6185db85Sdougm */ 696*6185db85Sdougm 697*6185db85Sdougm static int 698*6185db85Sdougm sa_extract_group(xmlNodePtr root, scfutilhandle_t *handle, 699*6185db85Sdougm scf_instance_t *instance) 700*6185db85Sdougm { 701*6185db85Sdougm char *buff; 702*6185db85Sdougm xmlNodePtr node; 703*6185db85Sdougm scf_iter_t *iter; 704*6185db85Sdougm char *proto; 705*6185db85Sdougm char *sectype; 706*6185db85Sdougm int have_shares = 0; 707*6185db85Sdougm int has_proto = 0; 708*6185db85Sdougm int is_default = 0; 709*6185db85Sdougm int ret = SA_OK; 710*6185db85Sdougm int err; 711*6185db85Sdougm 712*6185db85Sdougm buff = malloc(scf_max_name_len); 713*6185db85Sdougm iter = scf_iter_create(handle->handle); 714*6185db85Sdougm if (buff != NULL) { 715*6185db85Sdougm if (scf_instance_get_name(instance, buff, 716*6185db85Sdougm scf_max_name_len) > 0) { 717*6185db85Sdougm node = xmlNewChild(root, NULL, (xmlChar *)"group", NULL); 718*6185db85Sdougm if (node != NULL) { 719*6185db85Sdougm xmlSetProp(node, (xmlChar *)"name", (xmlChar *)buff); 720*6185db85Sdougm if (strcmp(buff, "default") == 0) 721*6185db85Sdougm is_default++; 722*6185db85Sdougm sa_extract_attrs(node, handle, instance); 723*6185db85Sdougm /* 724*6185db85Sdougm * Iterate through all the property groups 725*6185db85Sdougm * looking for those with security or 726*6185db85Sdougm * optionset prefixes. The names of the 727*6185db85Sdougm * matching pgroups are parsed to get the 728*6185db85Sdougm * protocol, and for security, the sectype. 729*6185db85Sdougm * Syntax is as follows: 730*6185db85Sdougm * optionset | optionset_<proto> 731*6185db85Sdougm * security_default | security_<proto>_<sectype> 732*6185db85Sdougm * "operation" is handled by 733*6185db85Sdougm * sa_extract_attrs(). 734*6185db85Sdougm */ 735*6185db85Sdougm if (iter != NULL) { 736*6185db85Sdougm if (scf_iter_instance_pgs(iter, instance) == 0) { 737*6185db85Sdougm while (scf_iter_next_pg(iter, handle->pg) > 0) { 738*6185db85Sdougm /* have a pgroup so sort it out */ 739*6185db85Sdougm ret = scf_pg_get_name(handle->pg, buff, 740*6185db85Sdougm scf_max_name_len); 741*6185db85Sdougm if (ret > 0) { 742*6185db85Sdougm if (buff[0] == SA_SHARE_PG_PREFIX[0]) { 743*6185db85Sdougm sa_share_from_pgroup(node, handle, 744*6185db85Sdougm handle->pg, 745*6185db85Sdougm buff); 746*6185db85Sdougm have_shares++; 747*6185db85Sdougm } else if (strncmp(buff, "optionset", 9) == 748*6185db85Sdougm 0) { 749*6185db85Sdougm char *nodetype = "optionset"; 750*6185db85Sdougm /* have an optionset */ 751*6185db85Sdougm sectype = NULL; 752*6185db85Sdougm proto = strchr(buff, '_'); 753*6185db85Sdougm if (proto != NULL) { 754*6185db85Sdougm *proto++ = '\0'; 755*6185db85Sdougm sectype = strchr(proto, '_'); 756*6185db85Sdougm if (sectype != NULL) { 757*6185db85Sdougm *sectype++ = '\0'; 758*6185db85Sdougm nodetype = "security"; 759*6185db85Sdougm } 760*6185db85Sdougm } 761*6185db85Sdougm ret = sa_extract_pgroup(node, handle, 762*6185db85Sdougm handle->pg, 763*6185db85Sdougm nodetype, 764*6185db85Sdougm proto, sectype); 765*6185db85Sdougm has_proto++; 766*6185db85Sdougm } else if (strncmp(buff, 767*6185db85Sdougm "security", 8) == 0) { 768*6185db85Sdougm /* 769*6185db85Sdougm * have a security (note that 770*6185db85Sdougm * this should change in the 771*6185db85Sdougm * future) 772*6185db85Sdougm */ 773*6185db85Sdougm proto = strchr(buff, '_'); 774*6185db85Sdougm sectype = NULL; 775*6185db85Sdougm if (proto != NULL) { 776*6185db85Sdougm *proto++ = '\0'; 777*6185db85Sdougm sectype = strchr(proto, '_'); 778*6185db85Sdougm if (sectype != NULL) 779*6185db85Sdougm *sectype++ = '\0'; 780*6185db85Sdougm if (strcmp(proto, "default") == 0) 781*6185db85Sdougm proto = NULL; 782*6185db85Sdougm } 783*6185db85Sdougm ret = sa_extract_pgroup(node, handle, 784*6185db85Sdougm handle->pg, 785*6185db85Sdougm "security", proto, 786*6185db85Sdougm sectype); 787*6185db85Sdougm has_proto++; 788*6185db85Sdougm } 789*6185db85Sdougm /* ignore everything else */ 790*6185db85Sdougm } 791*6185db85Sdougm } 792*6185db85Sdougm } else { 793*6185db85Sdougm ret = SA_NO_MEMORY; 794*6185db85Sdougm } 795*6185db85Sdougm /* 796*6185db85Sdougm * Make sure we have a valid default group. 797*6185db85Sdougm * On first boot, default won't have any 798*6185db85Sdougm * protocols defined and won't be enabled (but 799*6185db85Sdougm * should be). 800*6185db85Sdougm */ 801*6185db85Sdougm if (is_default) { 802*6185db85Sdougm char *state = sa_get_group_attr((sa_group_t)node, 803*6185db85Sdougm "state"); 804*6185db85Sdougm char **protos; 805*6185db85Sdougm int numprotos; 806*6185db85Sdougm int i; 807*6185db85Sdougm 808*6185db85Sdougm if (state == NULL) { 809*6185db85Sdougm /* set attribute to enabled */ 810*6185db85Sdougm (void) sa_set_group_attr((sa_group_t)node, 811*6185db85Sdougm "state", 812*6185db85Sdougm "enabled"); 813*6185db85Sdougm /* we can assume no protocols */ 814*6185db85Sdougm numprotos = sa_get_protocols(&protos); 815*6185db85Sdougm for (i = 0; i < numprotos; i++) 816*6185db85Sdougm (void) sa_create_optionset((sa_group_t)node, 817*6185db85Sdougm protos[i]); 818*6185db85Sdougm if (numprotos > 0) 819*6185db85Sdougm free(protos); 820*6185db85Sdougm } else { 821*6185db85Sdougm sa_free_attr_string(state); 822*6185db85Sdougm } 823*6185db85Sdougm } 824*6185db85Sdougm /* do a second pass if shares were found */ 825*6185db85Sdougm if (have_shares && 826*6185db85Sdougm scf_iter_instance_pgs(iter, instance) == 0) { 827*6185db85Sdougm while (scf_iter_next_pg(iter, handle->pg) > 0) { 828*6185db85Sdougm /* 829*6185db85Sdougm * have a pgroup so see if it is a 830*6185db85Sdougm * share optionset 831*6185db85Sdougm */ 832*6185db85Sdougm err = scf_pg_get_name(handle->pg, buff, 833*6185db85Sdougm scf_max_name_len); 834*6185db85Sdougm if (err > 0) { 835*6185db85Sdougm if (buff[0] == SA_SHARE_PG_PREFIX[0]) { 836*6185db85Sdougm ret = sa_share_props_from_pgroup(node, 837*6185db85Sdougm handle, 838*6185db85Sdougm handle->pg, 839*6185db85Sdougm buff); 840*6185db85Sdougm } 841*6185db85Sdougm } 842*6185db85Sdougm } 843*6185db85Sdougm } 844*6185db85Sdougm } 845*6185db85Sdougm } 846*6185db85Sdougm } 847*6185db85Sdougm } 848*6185db85Sdougm if (iter != NULL) 849*6185db85Sdougm scf_iter_destroy(iter); 850*6185db85Sdougm if (buff != NULL) 851*6185db85Sdougm free(buff); 852*6185db85Sdougm return (ret); 853*6185db85Sdougm } 854*6185db85Sdougm 855*6185db85Sdougm /* 856*6185db85Sdougm * sa_extract_defaults(root, handle, instance) 857*6185db85Sdougm * 858*6185db85Sdougm * local function to find the default properties that live in the 859*6185db85Sdougm * default instance's "operation" proprerty group. 860*6185db85Sdougm */ 861*6185db85Sdougm 862*6185db85Sdougm static void 863*6185db85Sdougm sa_extract_defaults(xmlNodePtr root, scfutilhandle_t *handle, 864*6185db85Sdougm scf_instance_t *instance) 865*6185db85Sdougm { 866*6185db85Sdougm xmlNodePtr node; 867*6185db85Sdougm scf_property_t *prop; 868*6185db85Sdougm scf_value_t *value; 869*6185db85Sdougm char *valuestr; 870*6185db85Sdougm ssize_t vallen; 871*6185db85Sdougm 872*6185db85Sdougm vallen = get_scf_limit(SCF_LIMIT_MAX_VALUE_LENGTH); 873*6185db85Sdougm prop = scf_property_create(handle->handle); 874*6185db85Sdougm value = scf_value_create(handle->handle); 875*6185db85Sdougm valuestr = malloc(vallen); 876*6185db85Sdougm if (prop != NULL && value != NULL && vallen != NULL && 877*6185db85Sdougm scf_instance_get_pg(instance, "operation", 878*6185db85Sdougm handle->pg) == 0) { 879*6185db85Sdougm if (scf_pg_get_property(handle->pg, 880*6185db85Sdougm "legacy-timestamp", prop) == 0) { 881*6185db85Sdougm /* found the property so get the value */ 882*6185db85Sdougm if (scf_property_get_value(prop, value) == 0) { 883*6185db85Sdougm if (scf_value_get_astring(value, valuestr, vallen) > 0) { 884*6185db85Sdougm node = xmlNewChild(root, NULL, (xmlChar *)"legacy", 885*6185db85Sdougm NULL); 886*6185db85Sdougm if (node != NULL) { 887*6185db85Sdougm xmlSetProp(node, (xmlChar *)"timestamp", 888*6185db85Sdougm (xmlChar *)valuestr); 889*6185db85Sdougm xmlSetProp(node, (xmlChar *)"path", 890*6185db85Sdougm (xmlChar *)SA_LEGACY_DFSTAB); 891*6185db85Sdougm } 892*6185db85Sdougm } 893*6185db85Sdougm } 894*6185db85Sdougm } 895*6185db85Sdougm } 896*6185db85Sdougm if (valuestr != NULL) 897*6185db85Sdougm free(valuestr); 898*6185db85Sdougm if (value != NULL) 899*6185db85Sdougm scf_value_destroy(value); 900*6185db85Sdougm if (prop != NULL) 901*6185db85Sdougm scf_property_destroy(prop); 902*6185db85Sdougm } 903*6185db85Sdougm 904*6185db85Sdougm 905*6185db85Sdougm /* 906*6185db85Sdougm * sa_get_config(handle, root, doc) 907*6185db85Sdougm * 908*6185db85Sdougm * walk the SMF repository for /network/shares/group and find all the 909*6185db85Sdougm * instances. These become group names. Then add the XML structure 910*6185db85Sdougm * below the groups based on property groups and properties. 911*6185db85Sdougm */ 912*6185db85Sdougm int 913*6185db85Sdougm sa_get_config(scfutilhandle_t *handle, xmlNodePtr *root, xmlDocPtr *doc) 914*6185db85Sdougm { 915*6185db85Sdougm int ret = SA_OK; 916*6185db85Sdougm scf_instance_t *instance; 917*6185db85Sdougm scf_iter_t *iter; 918*6185db85Sdougm char buff[BUFSIZ * 2]; 919*6185db85Sdougm 920*6185db85Sdougm *doc = xmlNewDoc((xmlChar *)"1.0"); 921*6185db85Sdougm *root = xmlNewNode(NULL, (xmlChar *)"sharecfg"); 922*6185db85Sdougm instance = scf_instance_create(handle->handle); 923*6185db85Sdougm iter = scf_iter_create(handle->handle); 924*6185db85Sdougm if (*doc != NULL && *root != NULL && instance != NULL && iter != NULL) { 925*6185db85Sdougm xmlDocSetRootElement(*doc, *root); 926*6185db85Sdougm if ((ret = scf_iter_service_instances(iter, 927*6185db85Sdougm handle->service)) == 0) { 928*6185db85Sdougm while ((ret = scf_iter_next_instance(iter, 929*6185db85Sdougm instance)) > 0) { 930*6185db85Sdougm if (scf_instance_get_name(instance, buff, 931*6185db85Sdougm sizeof (buff)) > 0) { 932*6185db85Sdougm if (strcmp(buff, "default") == 0) 933*6185db85Sdougm sa_extract_defaults(*root, handle, instance); 934*6185db85Sdougm ret = sa_extract_group(*root, handle, instance); 935*6185db85Sdougm } 936*6185db85Sdougm } 937*6185db85Sdougm } 938*6185db85Sdougm } else { 939*6185db85Sdougm /* if we can't create the document, cleanup */ 940*6185db85Sdougm if (*doc != NULL) 941*6185db85Sdougm xmlFreeDoc(*doc); 942*6185db85Sdougm if (*root != NULL) 943*6185db85Sdougm xmlFreeNode(*root); 944*6185db85Sdougm *doc = NULL; 945*6185db85Sdougm *root = NULL; 946*6185db85Sdougm } 947*6185db85Sdougm /* always cleanup these */ 948*6185db85Sdougm if (instance != NULL) 949*6185db85Sdougm scf_instance_destroy(instance); 950*6185db85Sdougm if (iter != NULL) 951*6185db85Sdougm scf_iter_destroy(iter); 952*6185db85Sdougm return (ret); 953*6185db85Sdougm } 954*6185db85Sdougm 955*6185db85Sdougm /* 956*6185db85Sdougm * sa_get_instance(handle, instance) 957*6185db85Sdougm * 958*6185db85Sdougm * get the instance of the group service. This is actually the 959*6185db85Sdougm * specific group name. The instance is needed for all property and 960*6185db85Sdougm * control operations. 961*6185db85Sdougm */ 962*6185db85Sdougm 963*6185db85Sdougm int 964*6185db85Sdougm sa_get_instance(scfutilhandle_t *handle, char *instname) 965*6185db85Sdougm { 966*6185db85Sdougm if (scf_service_get_instance(handle->service, instname, 967*6185db85Sdougm handle->instance) != 0) { 968*6185db85Sdougm return (SA_NO_SUCH_GROUP); 969*6185db85Sdougm } 970*6185db85Sdougm return (SA_OK); 971*6185db85Sdougm } 972*6185db85Sdougm 973*6185db85Sdougm /* 974*6185db85Sdougm * sa_create_instance(handle, instname) 975*6185db85Sdougm * 976*6185db85Sdougm * Create a new SMF service instance. There can only be one with a 977*6185db85Sdougm * given name. 978*6185db85Sdougm */ 979*6185db85Sdougm 980*6185db85Sdougm int 981*6185db85Sdougm sa_create_instance(scfutilhandle_t *handle, char *instname) 982*6185db85Sdougm { 983*6185db85Sdougm int ret = SA_OK; 984*6185db85Sdougm char instance[SA_GROUP_INST_LEN]; 985*6185db85Sdougm if (scf_service_add_instance(handle->service, instname, 986*6185db85Sdougm handle->instance) != 0) { 987*6185db85Sdougm /* better error returns need to be added based on real error */ 988*6185db85Sdougm if (scf_error() == SCF_ERROR_PERMISSION_DENIED) 989*6185db85Sdougm ret = SA_NO_PERMISSION; 990*6185db85Sdougm else 991*6185db85Sdougm ret = SA_DUPLICATE_NAME; 992*6185db85Sdougm } else { 993*6185db85Sdougm /* have the service created, so enable it */ 994*6185db85Sdougm (void) snprintf(instance, sizeof (instance), "%s:%s", 995*6185db85Sdougm SA_SVC_FMRI_BASE, instname); 996*6185db85Sdougm (void) smf_enable_instance(instance, 0); 997*6185db85Sdougm } 998*6185db85Sdougm return (ret); 999*6185db85Sdougm } 1000*6185db85Sdougm 1001*6185db85Sdougm /* 1002*6185db85Sdougm * sa_delete_instance(handle, instname) 1003*6185db85Sdougm * 1004*6185db85Sdougm * When a group goes away, we also remove the service instance. 1005*6185db85Sdougm */ 1006*6185db85Sdougm 1007*6185db85Sdougm int 1008*6185db85Sdougm sa_delete_instance(scfutilhandle_t *handle, char *instname) 1009*6185db85Sdougm { 1010*6185db85Sdougm int ret; 1011*6185db85Sdougm 1012*6185db85Sdougm if (strcmp(instname, "default") == 0) { 1013*6185db85Sdougm ret = SA_NO_PERMISSION; 1014*6185db85Sdougm } else { 1015*6185db85Sdougm if ((ret = sa_get_instance(handle, instname)) == SA_OK) { 1016*6185db85Sdougm if (scf_instance_delete(handle->instance) != 0) 1017*6185db85Sdougm /* need better analysis */ 1018*6185db85Sdougm ret = SA_NO_PERMISSION; 1019*6185db85Sdougm } 1020*6185db85Sdougm } 1021*6185db85Sdougm return (ret); 1022*6185db85Sdougm } 1023*6185db85Sdougm 1024*6185db85Sdougm /* 1025*6185db85Sdougm * sa_create_pgroup(handle, pgroup) 1026*6185db85Sdougm * 1027*6185db85Sdougm * create a new property group 1028*6185db85Sdougm */ 1029*6185db85Sdougm 1030*6185db85Sdougm int 1031*6185db85Sdougm sa_create_pgroup(scfutilhandle_t *handle, char *pgroup) 1032*6185db85Sdougm { 1033*6185db85Sdougm int ret = SA_OK; 1034*6185db85Sdougm /* 1035*6185db85Sdougm * only create a handle if it doesn't exist. It is ok to exist 1036*6185db85Sdougm * since the pg handle will be set as a side effect. 1037*6185db85Sdougm */ 1038*6185db85Sdougm if (handle->pg == NULL) { 1039*6185db85Sdougm handle->pg = scf_pg_create(handle->handle); 1040*6185db85Sdougm } 1041*6185db85Sdougm /* 1042*6185db85Sdougm * if the pgroup exists, we are done. If it doesn't, then we 1043*6185db85Sdougm * need to actually add one to the service instance. 1044*6185db85Sdougm */ 1045*6185db85Sdougm if (scf_instance_get_pg(handle->instance, 1046*6185db85Sdougm pgroup, handle->pg) != 0) { 1047*6185db85Sdougm /* doesn't exist so create one */ 1048*6185db85Sdougm if (scf_instance_add_pg(handle->instance, pgroup, 1049*6185db85Sdougm SCF_GROUP_APPLICATION, 0, 1050*6185db85Sdougm handle->pg) != 0) { 1051*6185db85Sdougm switch (scf_error()) { 1052*6185db85Sdougm case SCF_ERROR_PERMISSION_DENIED: 1053*6185db85Sdougm ret = SA_NO_PERMISSION; 1054*6185db85Sdougm break; 1055*6185db85Sdougm default: 1056*6185db85Sdougm ret = SA_SYSTEM_ERR; 1057*6185db85Sdougm break; 1058*6185db85Sdougm } 1059*6185db85Sdougm } 1060*6185db85Sdougm } 1061*6185db85Sdougm return (ret); 1062*6185db85Sdougm } 1063*6185db85Sdougm 1064*6185db85Sdougm /* 1065*6185db85Sdougm * sa_delete_pgroup(handle, pgroup) 1066*6185db85Sdougm * 1067*6185db85Sdougm * remove the property group from the current instance of the service, 1068*6185db85Sdougm * but only if it actually exists. 1069*6185db85Sdougm */ 1070*6185db85Sdougm 1071*6185db85Sdougm int 1072*6185db85Sdougm sa_delete_pgroup(scfutilhandle_t *handle, char *pgroup) 1073*6185db85Sdougm { 1074*6185db85Sdougm int ret = SA_OK; 1075*6185db85Sdougm /* 1076*6185db85Sdougm * only delete if it does exist. 1077*6185db85Sdougm */ 1078*6185db85Sdougm if (scf_instance_get_pg(handle->instance, 1079*6185db85Sdougm pgroup, handle->pg) == 0) { 1080*6185db85Sdougm /* does exist so delete it */ 1081*6185db85Sdougm if (scf_pg_delete(handle->pg) != 0) { 1082*6185db85Sdougm ret = SA_SYSTEM_ERR; 1083*6185db85Sdougm } 1084*6185db85Sdougm } else { 1085*6185db85Sdougm ret = SA_SYSTEM_ERR; 1086*6185db85Sdougm } 1087*6185db85Sdougm if (ret == SA_SYSTEM_ERR && 1088*6185db85Sdougm scf_error() == SCF_ERROR_PERMISSION_DENIED) { 1089*6185db85Sdougm ret = SA_NO_PERMISSION; 1090*6185db85Sdougm } 1091*6185db85Sdougm return (ret); 1092*6185db85Sdougm } 1093*6185db85Sdougm 1094*6185db85Sdougm /* 1095*6185db85Sdougm * sa_start_transaction(handle, pgroup) 1096*6185db85Sdougm * 1097*6185db85Sdougm * Start an SMF transaction so we can deal with properties. it would 1098*6185db85Sdougm * be nice to not have to expose this, but we have to in order to 1099*6185db85Sdougm * optimize. 1100*6185db85Sdougm * 1101*6185db85Sdougm * Basic model is to hold the transaction in the handle and allow 1102*6185db85Sdougm * property adds/deletes/updates to be added then close the 1103*6185db85Sdougm * transaction (or abort). There may eventually be a need to handle 1104*6185db85Sdougm * other types of transaction mechanisms but we don't do that now. 1105*6185db85Sdougm * 1106*6185db85Sdougm * An sa_start_transaction must be followed by either an 1107*6185db85Sdougm * sa_end_transaction or sa_abort_transaction before another 1108*6185db85Sdougm * sa_start_transaction can be done. 1109*6185db85Sdougm */ 1110*6185db85Sdougm 1111*6185db85Sdougm int 1112*6185db85Sdougm sa_start_transaction(scfutilhandle_t *handle, char *propgroup) 1113*6185db85Sdougm { 1114*6185db85Sdougm int ret = SA_OK; 1115*6185db85Sdougm /* 1116*6185db85Sdougm * lookup the property group and create it if it doesn't already 1117*6185db85Sdougm * exist. 1118*6185db85Sdougm */ 1119*6185db85Sdougm if (handle->scf_state == SCH_STATE_INIT) { 1120*6185db85Sdougm ret = sa_create_pgroup(handle, propgroup); 1121*6185db85Sdougm if (ret == SA_OK) { 1122*6185db85Sdougm handle->trans = scf_transaction_create(handle->handle); 1123*6185db85Sdougm if (handle->trans != NULL) { 1124*6185db85Sdougm if (scf_transaction_start(handle->trans, handle->pg) != 0) { 1125*6185db85Sdougm ret = SA_SYSTEM_ERR; 1126*6185db85Sdougm } 1127*6185db85Sdougm if (ret != SA_OK) { 1128*6185db85Sdougm scf_transaction_destroy(handle->trans); 1129*6185db85Sdougm handle->trans = NULL; 1130*6185db85Sdougm } 1131*6185db85Sdougm } else { 1132*6185db85Sdougm ret = SA_SYSTEM_ERR; 1133*6185db85Sdougm } 1134*6185db85Sdougm } 1135*6185db85Sdougm } 1136*6185db85Sdougm if (ret == SA_SYSTEM_ERR && 1137*6185db85Sdougm scf_error() == SCF_ERROR_PERMISSION_DENIED) { 1138*6185db85Sdougm ret = SA_NO_PERMISSION; 1139*6185db85Sdougm } 1140*6185db85Sdougm return (ret); 1141*6185db85Sdougm } 1142*6185db85Sdougm 1143*6185db85Sdougm /* 1144*6185db85Sdougm * sa_end_transaction(handle) 1145*6185db85Sdougm * 1146*6185db85Sdougm * Commit the changes that were added to the transaction in the 1147*6185db85Sdougm * handle. Do all necessary cleanup. 1148*6185db85Sdougm */ 1149*6185db85Sdougm 1150*6185db85Sdougm int 1151*6185db85Sdougm sa_end_transaction(scfutilhandle_t *handle) 1152*6185db85Sdougm { 1153*6185db85Sdougm int ret = SA_OK; 1154*6185db85Sdougm 1155*6185db85Sdougm if (handle->trans == NULL) { 1156*6185db85Sdougm ret = SA_SYSTEM_ERR; 1157*6185db85Sdougm } else { 1158*6185db85Sdougm if (scf_transaction_commit(handle->trans) < 0) 1159*6185db85Sdougm ret = SA_SYSTEM_ERR; 1160*6185db85Sdougm scf_transaction_destroy_children(handle->trans); 1161*6185db85Sdougm scf_transaction_destroy(handle->trans); 1162*6185db85Sdougm handle->trans = NULL; 1163*6185db85Sdougm } 1164*6185db85Sdougm return (ret); 1165*6185db85Sdougm } 1166*6185db85Sdougm 1167*6185db85Sdougm /* 1168*6185db85Sdougm * sa_abort_transaction(handle) 1169*6185db85Sdougm * 1170*6185db85Sdougm * Abort the changes that were added to the transaction in the 1171*6185db85Sdougm * handle. Do all necessary cleanup. 1172*6185db85Sdougm */ 1173*6185db85Sdougm 1174*6185db85Sdougm void 1175*6185db85Sdougm sa_abort_transaction(scfutilhandle_t *handle) 1176*6185db85Sdougm { 1177*6185db85Sdougm if (handle->trans != NULL) { 1178*6185db85Sdougm scf_transaction_reset_all(handle->trans); 1179*6185db85Sdougm scf_transaction_destroy_children(handle->trans); 1180*6185db85Sdougm scf_transaction_destroy(handle->trans); 1181*6185db85Sdougm handle->trans = NULL; 1182*6185db85Sdougm } 1183*6185db85Sdougm } 1184*6185db85Sdougm 1185*6185db85Sdougm /* 1186*6185db85Sdougm * sa_set_property(handle, prop, value) 1187*6185db85Sdougm * 1188*6185db85Sdougm * set a property transaction entry into the pending SMF transaction. 1189*6185db85Sdougm */ 1190*6185db85Sdougm 1191*6185db85Sdougm int 1192*6185db85Sdougm sa_set_property(scfutilhandle_t *handle, char *propname, char *valstr) 1193*6185db85Sdougm { 1194*6185db85Sdougm int ret = SA_OK; 1195*6185db85Sdougm scf_value_t *value; 1196*6185db85Sdougm scf_transaction_entry_t *entry; 1197*6185db85Sdougm /* 1198*6185db85Sdougm * properties must be set in transactions and don't take 1199*6185db85Sdougm * effect until the transaction has been ended/committed. 1200*6185db85Sdougm */ 1201*6185db85Sdougm value = scf_value_create(handle->handle); 1202*6185db85Sdougm entry = scf_entry_create(handle->handle); 1203*6185db85Sdougm if (value != NULL && entry != NULL) { 1204*6185db85Sdougm if (scf_transaction_property_change(handle->trans, entry, 1205*6185db85Sdougm propname, 1206*6185db85Sdougm SCF_TYPE_ASTRING) == 0 || 1207*6185db85Sdougm scf_transaction_property_new(handle->trans, entry, 1208*6185db85Sdougm propname, 1209*6185db85Sdougm SCF_TYPE_ASTRING) == 0) { 1210*6185db85Sdougm if (scf_value_set_astring(value, valstr) == 0) { 1211*6185db85Sdougm if (scf_entry_add_value(entry, value) != 0) { 1212*6185db85Sdougm ret = SA_SYSTEM_ERR; 1213*6185db85Sdougm scf_value_destroy(value); 1214*6185db85Sdougm } 1215*6185db85Sdougm /* the value is in the transaction */ 1216*6185db85Sdougm value = NULL; 1217*6185db85Sdougm } else { 1218*6185db85Sdougm /* value couldn't be constructed */ 1219*6185db85Sdougm ret = SA_SYSTEM_ERR; 1220*6185db85Sdougm } 1221*6185db85Sdougm /* the entry is in the transaction */ 1222*6185db85Sdougm entry = NULL; 1223*6185db85Sdougm } else { 1224*6185db85Sdougm ret = SA_SYSTEM_ERR; 1225*6185db85Sdougm } 1226*6185db85Sdougm } else { 1227*6185db85Sdougm ret = SA_SYSTEM_ERR; 1228*6185db85Sdougm } 1229*6185db85Sdougm if (ret == SA_SYSTEM_ERR) { 1230*6185db85Sdougm switch (scf_error()) { 1231*6185db85Sdougm case SCF_ERROR_PERMISSION_DENIED: 1232*6185db85Sdougm ret = SA_NO_PERMISSION; 1233*6185db85Sdougm break; 1234*6185db85Sdougm } 1235*6185db85Sdougm } 1236*6185db85Sdougm /* 1237*6185db85Sdougm * cleanup if there were any errors that didn't leave these 1238*6185db85Sdougm * values where they would be cleaned up later. 1239*6185db85Sdougm */ 1240*6185db85Sdougm if (value != NULL) 1241*6185db85Sdougm scf_value_destroy(value); 1242*6185db85Sdougm if (entry != NULL) 1243*6185db85Sdougm scf_entry_destroy(entry); 1244*6185db85Sdougm return (ret); 1245*6185db85Sdougm } 1246*6185db85Sdougm 1247*6185db85Sdougm /* 1248*6185db85Sdougm * sa_commit_share(handle, group, share) 1249*6185db85Sdougm * 1250*6185db85Sdougm * commit this share to the repository. 1251*6185db85Sdougm * properties are added if they exist but can be added later. 1252*6185db85Sdougm * Need to add to dfstab and sharetab, if appropriate. 1253*6185db85Sdougm */ 1254*6185db85Sdougm int 1255*6185db85Sdougm sa_commit_share(scfutilhandle_t *handle, sa_group_t group, sa_share_t share) 1256*6185db85Sdougm { 1257*6185db85Sdougm int ret = SA_OK; 1258*6185db85Sdougm char *groupname; 1259*6185db85Sdougm char *name; 1260*6185db85Sdougm char *resource; 1261*6185db85Sdougm char *description; 1262*6185db85Sdougm char *sharename; 1263*6185db85Sdougm ssize_t proplen; 1264*6185db85Sdougm char *propstring; 1265*6185db85Sdougm 1266*6185db85Sdougm /* 1267*6185db85Sdougm * don't commit in the zfs group. We do commit legacy 1268*6185db85Sdougm * (default) and all other groups/shares. ZFS is handled 1269*6185db85Sdougm * through the ZFS configuration rather than SMF. 1270*6185db85Sdougm */ 1271*6185db85Sdougm 1272*6185db85Sdougm groupname = sa_get_group_attr(group, "name"); 1273*6185db85Sdougm if (groupname != NULL) { 1274*6185db85Sdougm if (strcmp(groupname, "zfs") == 0) { 1275*6185db85Sdougm /* 1276*6185db85Sdougm * adding to the ZFS group will result in the sharenfs 1277*6185db85Sdougm * property being set but we don't want to do anything 1278*6185db85Sdougm * SMF related at this point. 1279*6185db85Sdougm */ 1280*6185db85Sdougm sa_free_attr_string(groupname); 1281*6185db85Sdougm return (ret); 1282*6185db85Sdougm } 1283*6185db85Sdougm } 1284*6185db85Sdougm 1285*6185db85Sdougm proplen = get_scf_limit(SCF_LIMIT_MAX_VALUE_LENGTH); 1286*6185db85Sdougm propstring = malloc(proplen); 1287*6185db85Sdougm if (propstring == NULL) 1288*6185db85Sdougm ret = SA_NO_MEMORY; 1289*6185db85Sdougm 1290*6185db85Sdougm if (groupname != NULL && ret == SA_OK) { 1291*6185db85Sdougm ret = sa_get_instance(handle, groupname); 1292*6185db85Sdougm sa_free_attr_string(groupname); 1293*6185db85Sdougm groupname = NULL; 1294*6185db85Sdougm sharename = sa_get_share_attr(share, "id"); 1295*6185db85Sdougm if (sharename == NULL) { 1296*6185db85Sdougm /* slipped by */ 1297*6185db85Sdougm char shname[SA_SHARE_UUID_BUFLEN]; 1298*6185db85Sdougm generate_unique_sharename(shname); 1299*6185db85Sdougm xmlSetProp((xmlNodePtr)share, (xmlChar *)"id", 1300*6185db85Sdougm (xmlChar *)shname); 1301*6185db85Sdougm sharename = strdup(shname); 1302*6185db85Sdougm } 1303*6185db85Sdougm if (sharename != NULL) { 1304*6185db85Sdougm /* 1305*6185db85Sdougm * have a share name allocated so create a pgroup 1306*6185db85Sdougm * for it. It may already exist, but that is OK. 1307*6185db85Sdougm */ 1308*6185db85Sdougm ret = sa_create_pgroup(handle, sharename); 1309*6185db85Sdougm if (ret == SA_OK) { 1310*6185db85Sdougm /* 1311*6185db85Sdougm * now start the transaction for the 1312*6185db85Sdougm * properties that define this share. They may 1313*6185db85Sdougm * exist so attempt to update before create. 1314*6185db85Sdougm */ 1315*6185db85Sdougm ret = sa_start_transaction(handle, sharename); 1316*6185db85Sdougm } 1317*6185db85Sdougm if (ret == SA_OK) { 1318*6185db85Sdougm name = sa_get_share_attr(share, "path"); 1319*6185db85Sdougm if (name != NULL) { 1320*6185db85Sdougm /* there needs to be a path for a share to exist */ 1321*6185db85Sdougm ret = sa_set_property(handle, "path", name); 1322*6185db85Sdougm sa_free_attr_string(name); 1323*6185db85Sdougm } else { 1324*6185db85Sdougm ret = SA_NO_MEMORY; 1325*6185db85Sdougm } 1326*6185db85Sdougm } 1327*6185db85Sdougm if (ret == SA_OK) { 1328*6185db85Sdougm resource = sa_get_share_attr(share, "resource"); 1329*6185db85Sdougm if (resource != NULL) { 1330*6185db85Sdougm ret = sa_set_property(handle, "resource", resource); 1331*6185db85Sdougm sa_free_attr_string(resource); 1332*6185db85Sdougm } 1333*6185db85Sdougm } 1334*6185db85Sdougm if (ret == SA_OK) { 1335*6185db85Sdougm description = sa_get_share_description(share); 1336*6185db85Sdougm if (description != NULL) { 1337*6185db85Sdougm ret = sa_set_property(handle, "description", 1338*6185db85Sdougm description); 1339*6185db85Sdougm sa_free_share_description(description); 1340*6185db85Sdougm } 1341*6185db85Sdougm } 1342*6185db85Sdougm /* make sure we cleanup the transaction */ 1343*6185db85Sdougm if (ret == SA_OK) { 1344*6185db85Sdougm ret = sa_end_transaction(handle); 1345*6185db85Sdougm } else { 1346*6185db85Sdougm sa_abort_transaction(handle); 1347*6185db85Sdougm } 1348*6185db85Sdougm free(sharename); 1349*6185db85Sdougm } 1350*6185db85Sdougm } 1351*6185db85Sdougm if (ret == SA_SYSTEM_ERR) { 1352*6185db85Sdougm int err = scf_error(); 1353*6185db85Sdougm if (err == SCF_ERROR_PERMISSION_DENIED) 1354*6185db85Sdougm ret = SA_NO_PERMISSION; 1355*6185db85Sdougm } 1356*6185db85Sdougm if (propstring != NULL) 1357*6185db85Sdougm free(propstring); 1358*6185db85Sdougm if (groupname != NULL) 1359*6185db85Sdougm sa_free_attr_string(groupname); 1360*6185db85Sdougm 1361*6185db85Sdougm return (ret); 1362*6185db85Sdougm } 1363*6185db85Sdougm 1364*6185db85Sdougm /* 1365*6185db85Sdougm * sa_delete_share(handle, group, share) 1366*6185db85Sdougm * 1367*6185db85Sdougm * remove the specified share from the group (and service instance). 1368*6185db85Sdougm */ 1369*6185db85Sdougm 1370*6185db85Sdougm int 1371*6185db85Sdougm sa_delete_share(scfutilhandle_t *handle, sa_group_t group, sa_share_t share) 1372*6185db85Sdougm { 1373*6185db85Sdougm int ret = SA_OK; 1374*6185db85Sdougm char *groupname = NULL; 1375*6185db85Sdougm char *shareid = NULL; 1376*6185db85Sdougm sa_optionset_t opt; 1377*6185db85Sdougm sa_security_t sec; 1378*6185db85Sdougm ssize_t proplen; 1379*6185db85Sdougm char *propstring; 1380*6185db85Sdougm 1381*6185db85Sdougm proplen = get_scf_limit(SCF_LIMIT_MAX_VALUE_LENGTH); 1382*6185db85Sdougm propstring = malloc(proplen); 1383*6185db85Sdougm if (propstring == NULL) 1384*6185db85Sdougm ret = SA_NO_MEMORY; 1385*6185db85Sdougm 1386*6185db85Sdougm if (ret == SA_OK) { 1387*6185db85Sdougm groupname = sa_get_group_attr(group, "name"); 1388*6185db85Sdougm shareid = sa_get_share_attr(share, "id"); 1389*6185db85Sdougm if (groupname != NULL && shareid != NULL) { 1390*6185db85Sdougm ret = sa_get_instance(handle, groupname); 1391*6185db85Sdougm if (ret == SA_OK) { 1392*6185db85Sdougm /* if a share has properties, remove them */ 1393*6185db85Sdougm ret = sa_delete_pgroup(handle, shareid); 1394*6185db85Sdougm for (opt = sa_get_optionset(share, NULL); opt != NULL; 1395*6185db85Sdougm opt = sa_get_next_optionset(opt)) { 1396*6185db85Sdougm char *proto; 1397*6185db85Sdougm proto = sa_get_optionset_attr(opt, "type"); 1398*6185db85Sdougm if (proto != NULL) { 1399*6185db85Sdougm (void) snprintf(propstring, proplen, "%s_%s", 1400*6185db85Sdougm shareid, proto); 1401*6185db85Sdougm ret = sa_delete_pgroup(handle, propstring); 1402*6185db85Sdougm sa_free_attr_string(proto); 1403*6185db85Sdougm } else { 1404*6185db85Sdougm ret = SA_NO_MEMORY; 1405*6185db85Sdougm } 1406*6185db85Sdougm } 1407*6185db85Sdougm /* 1408*6185db85Sdougm * if a share has security/negotiable 1409*6185db85Sdougm * properties, remove them. 1410*6185db85Sdougm */ 1411*6185db85Sdougm for (sec = sa_get_security(share, NULL, NULL); sec != NULL; 1412*6185db85Sdougm sec = sa_get_next_security(sec)) { 1413*6185db85Sdougm char *proto; 1414*6185db85Sdougm char *sectype; 1415*6185db85Sdougm proto = sa_get_security_attr(sec, "type"); 1416*6185db85Sdougm sectype = sa_get_security_attr(sec, "sectype"); 1417*6185db85Sdougm if (proto != NULL && sectype != NULL) { 1418*6185db85Sdougm (void) snprintf(propstring, proplen, "%s_%s_%s", 1419*6185db85Sdougm shareid, 1420*6185db85Sdougm proto, sectype); 1421*6185db85Sdougm ret = sa_delete_pgroup(handle, propstring); 1422*6185db85Sdougm } else { 1423*6185db85Sdougm ret = SA_NO_MEMORY; 1424*6185db85Sdougm } 1425*6185db85Sdougm if (proto != NULL) 1426*6185db85Sdougm sa_free_attr_string(proto); 1427*6185db85Sdougm if (sectype != NULL) 1428*6185db85Sdougm sa_free_attr_string(sectype); 1429*6185db85Sdougm } 1430*6185db85Sdougm } 1431*6185db85Sdougm } else { 1432*6185db85Sdougm ret = SA_CONFIG_ERR; 1433*6185db85Sdougm } 1434*6185db85Sdougm } 1435*6185db85Sdougm if (groupname != NULL) 1436*6185db85Sdougm sa_free_attr_string(groupname); 1437*6185db85Sdougm if (shareid != NULL) 1438*6185db85Sdougm sa_free_attr_string(shareid); 1439*6185db85Sdougm if (propstring != NULL) 1440*6185db85Sdougm free(propstring); 1441*6185db85Sdougm 1442*6185db85Sdougm return (ret); 1443*6185db85Sdougm } 1444