1*f6e214c7SGavin Maltby /* 2*f6e214c7SGavin Maltby * CDDL HEADER START 3*f6e214c7SGavin Maltby * 4*f6e214c7SGavin Maltby * The contents of this file are subject to the terms of the 5*f6e214c7SGavin Maltby * Common Development and Distribution License (the "License"). 6*f6e214c7SGavin Maltby * You may not use this file except in compliance with the License. 7*f6e214c7SGavin Maltby * 8*f6e214c7SGavin Maltby * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*f6e214c7SGavin Maltby * or http://www.opensolaris.org/os/licensing. 10*f6e214c7SGavin Maltby * See the License for the specific language governing permissions 11*f6e214c7SGavin Maltby * and limitations under the License. 12*f6e214c7SGavin Maltby * 13*f6e214c7SGavin Maltby * When distributing Covered Code, include this CDDL HEADER in each 14*f6e214c7SGavin Maltby * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*f6e214c7SGavin Maltby * If applicable, add the following below this CDDL HEADER, with the 16*f6e214c7SGavin Maltby * fields enclosed by brackets "[]" replaced with your own identifying 17*f6e214c7SGavin Maltby * information: Portions Copyright [yyyy] [name of copyright owner] 18*f6e214c7SGavin Maltby * 19*f6e214c7SGavin Maltby * CDDL HEADER END 20*f6e214c7SGavin Maltby */ 21*f6e214c7SGavin Maltby 22*f6e214c7SGavin Maltby /* 23*f6e214c7SGavin Maltby * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. 24*f6e214c7SGavin Maltby */ 25*f6e214c7SGavin Maltby 26*f6e214c7SGavin Maltby #include "libscf_impl.h" 27*f6e214c7SGavin Maltby 28*f6e214c7SGavin Maltby #include <assert.h> 29*f6e214c7SGavin Maltby #include <strings.h> 30*f6e214c7SGavin Maltby 31*f6e214c7SGavin Maltby /* 32*f6e214c7SGavin Maltby * Errors returned by smf_notify_{del|get|set}_params() 33*f6e214c7SGavin Maltby */ 34*f6e214c7SGavin Maltby static const scf_error_t errs_1[] = { 35*f6e214c7SGavin Maltby SCF_ERROR_BACKEND_ACCESS, 36*f6e214c7SGavin Maltby SCF_ERROR_BACKEND_READONLY, 37*f6e214c7SGavin Maltby SCF_ERROR_CONNECTION_BROKEN, 38*f6e214c7SGavin Maltby SCF_ERROR_DELETED, 39*f6e214c7SGavin Maltby SCF_ERROR_INTERNAL, 40*f6e214c7SGavin Maltby SCF_ERROR_INVALID_ARGUMENT, 41*f6e214c7SGavin Maltby SCF_ERROR_NO_MEMORY, 42*f6e214c7SGavin Maltby SCF_ERROR_NO_RESOURCES, 43*f6e214c7SGavin Maltby SCF_ERROR_NOT_FOUND, 44*f6e214c7SGavin Maltby SCF_ERROR_PERMISSION_DENIED, 45*f6e214c7SGavin Maltby 0 46*f6e214c7SGavin Maltby }; 47*f6e214c7SGavin Maltby 48*f6e214c7SGavin Maltby /* 49*f6e214c7SGavin Maltby * Errors returned by smf_notify_{del|get|set}_params() 50*f6e214c7SGavin Maltby * Except SCF_ERROR_INVALID_ARGUMENT 51*f6e214c7SGavin Maltby */ 52*f6e214c7SGavin Maltby static const scf_error_t errs_2[] = { 53*f6e214c7SGavin Maltby SCF_ERROR_BACKEND_ACCESS, 54*f6e214c7SGavin Maltby SCF_ERROR_BACKEND_READONLY, 55*f6e214c7SGavin Maltby SCF_ERROR_CONNECTION_BROKEN, 56*f6e214c7SGavin Maltby SCF_ERROR_DELETED, 57*f6e214c7SGavin Maltby SCF_ERROR_INTERNAL, 58*f6e214c7SGavin Maltby SCF_ERROR_NO_MEMORY, 59*f6e214c7SGavin Maltby SCF_ERROR_NO_RESOURCES, 60*f6e214c7SGavin Maltby SCF_ERROR_NOT_FOUND, 61*f6e214c7SGavin Maltby SCF_ERROR_PERMISSION_DENIED, 62*f6e214c7SGavin Maltby 0 63*f6e214c7SGavin Maltby }; 64*f6e214c7SGavin Maltby 65*f6e214c7SGavin Maltby /* 66*f6e214c7SGavin Maltby * Helper function that abort() on unexpected errors. 67*f6e214c7SGavin Maltby * The expected error set is a zero-terminated array of scf_error_t 68*f6e214c7SGavin Maltby */ 69*f6e214c7SGavin Maltby static int 70*f6e214c7SGavin Maltby check_scf_error(scf_error_t e, const scf_error_t *errs) 71*f6e214c7SGavin Maltby { 72*f6e214c7SGavin Maltby if (ismember(e, errs)) 73*f6e214c7SGavin Maltby return (1); 74*f6e214c7SGavin Maltby 75*f6e214c7SGavin Maltby assert(0); 76*f6e214c7SGavin Maltby abort(); 77*f6e214c7SGavin Maltby 78*f6e214c7SGavin Maltby /*NOTREACHED*/ 79*f6e214c7SGavin Maltby } 80*f6e214c7SGavin Maltby 81*f6e214c7SGavin Maltby /* 82*f6e214c7SGavin Maltby * Mapping of state transition to pgname. 83*f6e214c7SGavin Maltby */ 84*f6e214c7SGavin Maltby static struct st_pgname { 85*f6e214c7SGavin Maltby const char *st_pgname; 86*f6e214c7SGavin Maltby int32_t st_state; 87*f6e214c7SGavin Maltby } st_pgnames[] = { 88*f6e214c7SGavin Maltby { "to-uninitialized", SCF_TRANS(0, SCF_STATE_UNINIT) }, 89*f6e214c7SGavin Maltby { "from-uninitialized", SCF_TRANS(SCF_STATE_UNINIT, 0) }, 90*f6e214c7SGavin Maltby { "to-maintenance", SCF_TRANS(0, SCF_STATE_MAINT) }, 91*f6e214c7SGavin Maltby { "from-maintenance", SCF_TRANS(SCF_STATE_MAINT, 0) }, 92*f6e214c7SGavin Maltby { "to-offline", SCF_TRANS(0, SCF_STATE_OFFLINE) }, 93*f6e214c7SGavin Maltby { "from-offline", SCF_TRANS(SCF_STATE_OFFLINE, 0) }, 94*f6e214c7SGavin Maltby { "to-disabled", SCF_TRANS(0, SCF_STATE_DISABLED) }, 95*f6e214c7SGavin Maltby { "from-disabled", SCF_TRANS(SCF_STATE_DISABLED, 0) }, 96*f6e214c7SGavin Maltby { "to-online", SCF_TRANS(0, SCF_STATE_ONLINE) }, 97*f6e214c7SGavin Maltby { "from-online", SCF_TRANS(SCF_STATE_ONLINE, 0) }, 98*f6e214c7SGavin Maltby { "to-degraded", SCF_TRANS(0, SCF_STATE_DEGRADED) }, 99*f6e214c7SGavin Maltby { "from-degraded", SCF_TRANS(SCF_STATE_DEGRADED, 0) }, 100*f6e214c7SGavin Maltby { NULL, 0 } 101*f6e214c7SGavin Maltby }; 102*f6e214c7SGavin Maltby 103*f6e214c7SGavin Maltby /* 104*f6e214c7SGavin Maltby * Check if class matches or is a subclass of SCF_SVC_TRANSITION_CLASS 105*f6e214c7SGavin Maltby * 106*f6e214c7SGavin Maltby * returns 1, otherwise return 0 107*f6e214c7SGavin Maltby */ 108*f6e214c7SGavin Maltby static boolean_t 109*f6e214c7SGavin Maltby is_svc_stn(const char *class) 110*f6e214c7SGavin Maltby { 111*f6e214c7SGavin Maltby int n = strlen(SCF_SVC_TRANSITION_CLASS); 112*f6e214c7SGavin Maltby 113*f6e214c7SGavin Maltby if (class && strncmp(class, SCF_SVC_TRANSITION_CLASS, n) == 0) 114*f6e214c7SGavin Maltby if (class[n] == '\0' || class[n] == '.') 115*f6e214c7SGavin Maltby return (1); 116*f6e214c7SGavin Maltby return (0); 117*f6e214c7SGavin Maltby } 118*f6e214c7SGavin Maltby 119*f6e214c7SGavin Maltby /* 120*f6e214c7SGavin Maltby * Return the len of the base class. For instance, "class.class1.class2.*" 121*f6e214c7SGavin Maltby * will return the length of "class.class1.class2" 122*f6e214c7SGavin Maltby * This function does not check if the class or base class is valid. 123*f6e214c7SGavin Maltby * A class such as "class.class1....****" is not valid but will return the 124*f6e214c7SGavin Maltby * length of "class.class1....***" 125*f6e214c7SGavin Maltby */ 126*f6e214c7SGavin Maltby static size_t 127*f6e214c7SGavin Maltby base_class_len(const char *c) 128*f6e214c7SGavin Maltby { 129*f6e214c7SGavin Maltby const char *p; 130*f6e214c7SGavin Maltby size_t n; 131*f6e214c7SGavin Maltby 132*f6e214c7SGavin Maltby if ((n = strlen(c)) == 0) 133*f6e214c7SGavin Maltby return (0); 134*f6e214c7SGavin Maltby 135*f6e214c7SGavin Maltby p = c + n; 136*f6e214c7SGavin Maltby 137*f6e214c7SGavin Maltby /* get rid of any trailing asterisk */ 138*f6e214c7SGavin Maltby if (*--p == '*') 139*f6e214c7SGavin Maltby n--; 140*f6e214c7SGavin Maltby 141*f6e214c7SGavin Maltby /* make sure the class doesn't end in '.' */ 142*f6e214c7SGavin Maltby while (p >= c && *--p == '.') 143*f6e214c7SGavin Maltby n--; 144*f6e214c7SGavin Maltby 145*f6e214c7SGavin Maltby return (n); 146*f6e214c7SGavin Maltby } 147*f6e214c7SGavin Maltby 148*f6e214c7SGavin Maltby /* 149*f6e214c7SGavin Maltby * Allocates and builds the pgname for an FMA dotted class. 150*f6e214c7SGavin Maltby * The pgname will be of the form "class.class1.class2,SCF_NOTIFY_PG_POSTFIX" 151*f6e214c7SGavin Maltby * 152*f6e214c7SGavin Maltby * NULL on error 153*f6e214c7SGavin Maltby */ 154*f6e214c7SGavin Maltby static char * 155*f6e214c7SGavin Maltby class_to_pgname(const char *class) 156*f6e214c7SGavin Maltby { 157*f6e214c7SGavin Maltby size_t n; 158*f6e214c7SGavin Maltby ssize_t sz = scf_limit(SCF_LIMIT_MAX_NAME_LENGTH) + 1; 159*f6e214c7SGavin Maltby char *pgname = NULL; 160*f6e214c7SGavin Maltby 161*f6e214c7SGavin Maltby n = base_class_len(class); 162*f6e214c7SGavin Maltby 163*f6e214c7SGavin Maltby if (n == 0) { 164*f6e214c7SGavin Maltby (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT); 165*f6e214c7SGavin Maltby return (NULL); 166*f6e214c7SGavin Maltby } 167*f6e214c7SGavin Maltby 168*f6e214c7SGavin Maltby if ((pgname = malloc(sz)) == NULL) { 169*f6e214c7SGavin Maltby (void) scf_set_error(SCF_ERROR_NO_MEMORY); 170*f6e214c7SGavin Maltby goto error; 171*f6e214c7SGavin Maltby } 172*f6e214c7SGavin Maltby 173*f6e214c7SGavin Maltby if (snprintf(pgname, sz, "%.*s,%s", (int)n, class, 174*f6e214c7SGavin Maltby SCF_NOTIFY_PG_POSTFIX) >= sz) { 175*f6e214c7SGavin Maltby (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT); 176*f6e214c7SGavin Maltby goto error; 177*f6e214c7SGavin Maltby } 178*f6e214c7SGavin Maltby return (pgname); 179*f6e214c7SGavin Maltby 180*f6e214c7SGavin Maltby error: 181*f6e214c7SGavin Maltby free(pgname); 182*f6e214c7SGavin Maltby pgname = NULL; 183*f6e214c7SGavin Maltby 184*f6e214c7SGavin Maltby return (pgname); 185*f6e214c7SGavin Maltby } 186*f6e214c7SGavin Maltby 187*f6e214c7SGavin Maltby /* 188*f6e214c7SGavin Maltby * Get the pg from the running snapshot of the instance (composed or not) 189*f6e214c7SGavin Maltby */ 190*f6e214c7SGavin Maltby static int 191*f6e214c7SGavin Maltby get_pg(scf_service_t *s, scf_instance_t *i, const char *n, 192*f6e214c7SGavin Maltby scf_propertygroup_t *pg, int composed) 193*f6e214c7SGavin Maltby { 194*f6e214c7SGavin Maltby scf_handle_t *h = scf_instance_handle(i); 195*f6e214c7SGavin Maltby scf_error_t scf_e = scf_error(); 196*f6e214c7SGavin Maltby scf_snapshot_t *snap = scf_snapshot_create(h); 197*f6e214c7SGavin Maltby scf_snaplevel_t *slvl = scf_snaplevel_create(h); 198*f6e214c7SGavin Maltby int r = -1; 199*f6e214c7SGavin Maltby 200*f6e214c7SGavin Maltby if (h == NULL) { 201*f6e214c7SGavin Maltby /* 202*f6e214c7SGavin Maltby * Use the error stored in scf_e 203*f6e214c7SGavin Maltby */ 204*f6e214c7SGavin Maltby (void) scf_set_error(scf_e); 205*f6e214c7SGavin Maltby goto out; 206*f6e214c7SGavin Maltby } 207*f6e214c7SGavin Maltby if (s == NULL) { 208*f6e214c7SGavin Maltby if (snap == NULL || slvl == NULL) 209*f6e214c7SGavin Maltby goto out; 210*f6e214c7SGavin Maltby if (scf_instance_get_snapshot(i, "running", snap) != 0) 211*f6e214c7SGavin Maltby goto out; 212*f6e214c7SGavin Maltby 213*f6e214c7SGavin Maltby if (composed) { 214*f6e214c7SGavin Maltby if (scf_instance_get_pg_composed(i, snap, n, pg) != 0) 215*f6e214c7SGavin Maltby goto out; 216*f6e214c7SGavin Maltby } else { 217*f6e214c7SGavin Maltby if (scf_snapshot_get_base_snaplevel(snap, slvl) != 0 || 218*f6e214c7SGavin Maltby scf_snaplevel_get_pg(slvl, n, pg) != 0) 219*f6e214c7SGavin Maltby goto out; 220*f6e214c7SGavin Maltby } 221*f6e214c7SGavin Maltby } else { 222*f6e214c7SGavin Maltby if (scf_service_get_pg(s, n, pg) != 0) 223*f6e214c7SGavin Maltby goto out; 224*f6e214c7SGavin Maltby } 225*f6e214c7SGavin Maltby 226*f6e214c7SGavin Maltby r = 0; 227*f6e214c7SGavin Maltby out: 228*f6e214c7SGavin Maltby scf_snaplevel_destroy(slvl); 229*f6e214c7SGavin Maltby scf_snapshot_destroy(snap); 230*f6e214c7SGavin Maltby 231*f6e214c7SGavin Maltby return (r); 232*f6e214c7SGavin Maltby } 233*f6e214c7SGavin Maltby 234*f6e214c7SGavin Maltby /* 235*f6e214c7SGavin Maltby * Add a pg if it does not exist, or get it if it exists. 236*f6e214c7SGavin Maltby * It operates on the instance if the service parameter is NULL. 237*f6e214c7SGavin Maltby * 238*f6e214c7SGavin Maltby * returns 0 on success or -1 on failure 239*f6e214c7SGavin Maltby */ 240*f6e214c7SGavin Maltby static int 241*f6e214c7SGavin Maltby get_or_add_pg(scf_service_t *s, scf_instance_t *i, const char *n, const char *t, 242*f6e214c7SGavin Maltby uint32_t flags, scf_propertygroup_t *pg) 243*f6e214c7SGavin Maltby { 244*f6e214c7SGavin Maltby int r; 245*f6e214c7SGavin Maltby 246*f6e214c7SGavin Maltby if (s == NULL) 247*f6e214c7SGavin Maltby r = scf_instance_add_pg(i, n, t, flags, pg); 248*f6e214c7SGavin Maltby else 249*f6e214c7SGavin Maltby r = scf_service_add_pg(s, n, t, flags, pg); 250*f6e214c7SGavin Maltby 251*f6e214c7SGavin Maltby if (r == 0) 252*f6e214c7SGavin Maltby return (0); 253*f6e214c7SGavin Maltby else if (scf_error() != SCF_ERROR_EXISTS) 254*f6e214c7SGavin Maltby return (-1); 255*f6e214c7SGavin Maltby 256*f6e214c7SGavin Maltby if (s == NULL) 257*f6e214c7SGavin Maltby r = scf_instance_get_pg(i, n, pg); 258*f6e214c7SGavin Maltby else 259*f6e214c7SGavin Maltby r = scf_service_get_pg(s, n, pg); 260*f6e214c7SGavin Maltby 261*f6e214c7SGavin Maltby return (r); 262*f6e214c7SGavin Maltby } 263*f6e214c7SGavin Maltby 264*f6e214c7SGavin Maltby /* 265*f6e214c7SGavin Maltby * Delete the property group form the instance or service. 266*f6e214c7SGavin Maltby * If service is NULL, use instance, otherwise use only the service. 267*f6e214c7SGavin Maltby * 268*f6e214c7SGavin Maltby * Return SCF_SUCCESS or SCF_FAILED on 269*f6e214c7SGavin Maltby * SCF_ERROR_BACKEND_ACCESS 270*f6e214c7SGavin Maltby * SCF_ERROR_BACKEND_READONLY 271*f6e214c7SGavin Maltby * SCF_ERROR_CONNECTION_BROKEN 272*f6e214c7SGavin Maltby * SCF_ERROR_DELETED 273*f6e214c7SGavin Maltby * SCF_ERROR_HANDLE_MISMATCH 274*f6e214c7SGavin Maltby * SCF_ERROR_INTERNAL 275*f6e214c7SGavin Maltby * SCF_ERROR_INVALID_ARGUMENT 276*f6e214c7SGavin Maltby * SCF_ERROR_NO_RESOURCES 277*f6e214c7SGavin Maltby * SCF_ERROR_NOT_BOUND 278*f6e214c7SGavin Maltby * SCF_ERROR_NOT_FOUND 279*f6e214c7SGavin Maltby * SCF_ERROR_NOT_SET 280*f6e214c7SGavin Maltby * SCF_ERROR_PERMISSION_DENIED 281*f6e214c7SGavin Maltby */ 282*f6e214c7SGavin Maltby static int 283*f6e214c7SGavin Maltby del_pg(scf_service_t *s, scf_instance_t *i, const char *n, 284*f6e214c7SGavin Maltby scf_propertygroup_t *pg) 285*f6e214c7SGavin Maltby { 286*f6e214c7SGavin Maltby if ((s == NULL ? scf_instance_get_pg(i, n, pg) : 287*f6e214c7SGavin Maltby scf_service_get_pg(s, n, pg)) != SCF_SUCCESS) 288*f6e214c7SGavin Maltby if (scf_error() == SCF_ERROR_NOT_FOUND) 289*f6e214c7SGavin Maltby return (SCF_SUCCESS); 290*f6e214c7SGavin Maltby else 291*f6e214c7SGavin Maltby return (SCF_FAILED); 292*f6e214c7SGavin Maltby 293*f6e214c7SGavin Maltby if (scf_pg_delete(pg) != SCF_SUCCESS) 294*f6e214c7SGavin Maltby if (scf_error() == SCF_ERROR_DELETED) 295*f6e214c7SGavin Maltby return (SCF_SUCCESS); 296*f6e214c7SGavin Maltby else 297*f6e214c7SGavin Maltby return (SCF_FAILED); 298*f6e214c7SGavin Maltby 299*f6e214c7SGavin Maltby return (SCF_SUCCESS); 300*f6e214c7SGavin Maltby } 301*f6e214c7SGavin Maltby 302*f6e214c7SGavin Maltby static scf_type_t 303*f6e214c7SGavin Maltby get_scf_type(nvpair_t *p) 304*f6e214c7SGavin Maltby { 305*f6e214c7SGavin Maltby switch (nvpair_type(p)) { 306*f6e214c7SGavin Maltby case DATA_TYPE_BOOLEAN: 307*f6e214c7SGavin Maltby case DATA_TYPE_BOOLEAN_VALUE: 308*f6e214c7SGavin Maltby case DATA_TYPE_BOOLEAN_ARRAY: 309*f6e214c7SGavin Maltby return (SCF_TYPE_BOOLEAN); 310*f6e214c7SGavin Maltby 311*f6e214c7SGavin Maltby case DATA_TYPE_BYTE: 312*f6e214c7SGavin Maltby case DATA_TYPE_UINT8: 313*f6e214c7SGavin Maltby case DATA_TYPE_UINT16: 314*f6e214c7SGavin Maltby case DATA_TYPE_UINT32: 315*f6e214c7SGavin Maltby case DATA_TYPE_UINT64: 316*f6e214c7SGavin Maltby case DATA_TYPE_BYTE_ARRAY: 317*f6e214c7SGavin Maltby case DATA_TYPE_UINT8_ARRAY: 318*f6e214c7SGavin Maltby case DATA_TYPE_UINT16_ARRAY: 319*f6e214c7SGavin Maltby case DATA_TYPE_UINT32_ARRAY: 320*f6e214c7SGavin Maltby case DATA_TYPE_UINT64_ARRAY: 321*f6e214c7SGavin Maltby return (SCF_TYPE_COUNT); 322*f6e214c7SGavin Maltby 323*f6e214c7SGavin Maltby case DATA_TYPE_INT8: 324*f6e214c7SGavin Maltby case DATA_TYPE_INT16: 325*f6e214c7SGavin Maltby case DATA_TYPE_INT32: 326*f6e214c7SGavin Maltby case DATA_TYPE_INT64: 327*f6e214c7SGavin Maltby case DATA_TYPE_INT8_ARRAY: 328*f6e214c7SGavin Maltby case DATA_TYPE_INT16_ARRAY: 329*f6e214c7SGavin Maltby case DATA_TYPE_INT32_ARRAY: 330*f6e214c7SGavin Maltby case DATA_TYPE_INT64_ARRAY: 331*f6e214c7SGavin Maltby return (SCF_TYPE_INTEGER); 332*f6e214c7SGavin Maltby 333*f6e214c7SGavin Maltby case DATA_TYPE_STRING: 334*f6e214c7SGavin Maltby case DATA_TYPE_STRING_ARRAY: 335*f6e214c7SGavin Maltby return (SCF_TYPE_ASTRING); 336*f6e214c7SGavin Maltby 337*f6e214c7SGavin Maltby default: 338*f6e214c7SGavin Maltby return (SCF_TYPE_INVALID); 339*f6e214c7SGavin Maltby } 340*f6e214c7SGavin Maltby } 341*f6e214c7SGavin Maltby 342*f6e214c7SGavin Maltby static int 343*f6e214c7SGavin Maltby add_entry(scf_transaction_entry_t *te, scf_value_t *val) 344*f6e214c7SGavin Maltby { 345*f6e214c7SGavin Maltby if (scf_entry_add_value(te, val) != 0) { 346*f6e214c7SGavin Maltby scf_value_destroy(val); 347*f6e214c7SGavin Maltby return (SCF_FAILED); 348*f6e214c7SGavin Maltby } 349*f6e214c7SGavin Maltby 350*f6e214c7SGavin Maltby return (SCF_SUCCESS); 351*f6e214c7SGavin Maltby } 352*f6e214c7SGavin Maltby 353*f6e214c7SGavin Maltby static int 354*f6e214c7SGavin Maltby add_boolean_entry(scf_handle_t *h, scf_transaction_entry_t *te, uint8_t v) 355*f6e214c7SGavin Maltby { 356*f6e214c7SGavin Maltby scf_value_t *val = scf_value_create(h); 357*f6e214c7SGavin Maltby 358*f6e214c7SGavin Maltby if (val == NULL) 359*f6e214c7SGavin Maltby return (SCF_FAILED); 360*f6e214c7SGavin Maltby 361*f6e214c7SGavin Maltby scf_value_set_boolean(val, v); 362*f6e214c7SGavin Maltby 363*f6e214c7SGavin Maltby return (add_entry(te, val)); 364*f6e214c7SGavin Maltby } 365*f6e214c7SGavin Maltby 366*f6e214c7SGavin Maltby static int 367*f6e214c7SGavin Maltby add_count_entry(scf_handle_t *h, scf_transaction_entry_t *te, uint64_t v) 368*f6e214c7SGavin Maltby { 369*f6e214c7SGavin Maltby scf_value_t *val = scf_value_create(h); 370*f6e214c7SGavin Maltby 371*f6e214c7SGavin Maltby if (val == NULL) 372*f6e214c7SGavin Maltby return (SCF_FAILED); 373*f6e214c7SGavin Maltby 374*f6e214c7SGavin Maltby scf_value_set_count(val, v); 375*f6e214c7SGavin Maltby 376*f6e214c7SGavin Maltby return (add_entry(te, val)); 377*f6e214c7SGavin Maltby } 378*f6e214c7SGavin Maltby 379*f6e214c7SGavin Maltby static int 380*f6e214c7SGavin Maltby add_integer_entry(scf_handle_t *h, scf_transaction_entry_t *te, int64_t v) 381*f6e214c7SGavin Maltby { 382*f6e214c7SGavin Maltby scf_value_t *val = scf_value_create(h); 383*f6e214c7SGavin Maltby 384*f6e214c7SGavin Maltby if (val == NULL) 385*f6e214c7SGavin Maltby return (SCF_FAILED); 386*f6e214c7SGavin Maltby 387*f6e214c7SGavin Maltby scf_value_set_integer(val, v); 388*f6e214c7SGavin Maltby 389*f6e214c7SGavin Maltby return (add_entry(te, val)); 390*f6e214c7SGavin Maltby } 391*f6e214c7SGavin Maltby 392*f6e214c7SGavin Maltby static int 393*f6e214c7SGavin Maltby add_astring_entry(scf_handle_t *h, scf_transaction_entry_t *te, char *s) 394*f6e214c7SGavin Maltby { 395*f6e214c7SGavin Maltby scf_value_t *val = scf_value_create(h); 396*f6e214c7SGavin Maltby 397*f6e214c7SGavin Maltby if (val == NULL) 398*f6e214c7SGavin Maltby return (SCF_FAILED); 399*f6e214c7SGavin Maltby 400*f6e214c7SGavin Maltby if (scf_value_set_astring(val, s) != 0) { 401*f6e214c7SGavin Maltby scf_value_destroy(val); 402*f6e214c7SGavin Maltby return (SCF_FAILED); 403*f6e214c7SGavin Maltby } 404*f6e214c7SGavin Maltby 405*f6e214c7SGavin Maltby return (add_entry(te, val)); 406*f6e214c7SGavin Maltby } 407*f6e214c7SGavin Maltby 408*f6e214c7SGavin Maltby static int 409*f6e214c7SGavin Maltby get_nvpair_vals(scf_handle_t *h, scf_transaction_entry_t *te, nvpair_t *p) 410*f6e214c7SGavin Maltby { 411*f6e214c7SGavin Maltby scf_value_t *val = scf_value_create(h); 412*f6e214c7SGavin Maltby uint_t n = 1; 413*f6e214c7SGavin Maltby int i; 414*f6e214c7SGavin Maltby 415*f6e214c7SGavin Maltby if (val == NULL) 416*f6e214c7SGavin Maltby return (SCF_FAILED); 417*f6e214c7SGavin Maltby 418*f6e214c7SGavin Maltby switch (nvpair_type(p)) { 419*f6e214c7SGavin Maltby case DATA_TYPE_BOOLEAN: 420*f6e214c7SGavin Maltby return (add_boolean_entry(h, te, 1)); 421*f6e214c7SGavin Maltby case DATA_TYPE_BOOLEAN_VALUE: 422*f6e214c7SGavin Maltby { 423*f6e214c7SGavin Maltby boolean_t v; 424*f6e214c7SGavin Maltby 425*f6e214c7SGavin Maltby (void) nvpair_value_boolean_value(p, &v); 426*f6e214c7SGavin Maltby return (add_boolean_entry(h, te, (uint8_t)v)); 427*f6e214c7SGavin Maltby } 428*f6e214c7SGavin Maltby case DATA_TYPE_BOOLEAN_ARRAY: 429*f6e214c7SGavin Maltby { 430*f6e214c7SGavin Maltby boolean_t *v; 431*f6e214c7SGavin Maltby 432*f6e214c7SGavin Maltby (void) nvpair_value_boolean_array(p, &v, &n); 433*f6e214c7SGavin Maltby for (i = 0; i < n; ++i) { 434*f6e214c7SGavin Maltby if (add_boolean_entry(h, te, (uint8_t)v[i]) != 435*f6e214c7SGavin Maltby SCF_SUCCESS) 436*f6e214c7SGavin Maltby return (SCF_FAILED); 437*f6e214c7SGavin Maltby } 438*f6e214c7SGavin Maltby return (SCF_SUCCESS); 439*f6e214c7SGavin Maltby } 440*f6e214c7SGavin Maltby case DATA_TYPE_BYTE: 441*f6e214c7SGavin Maltby { 442*f6e214c7SGavin Maltby uchar_t v; 443*f6e214c7SGavin Maltby 444*f6e214c7SGavin Maltby (void) nvpair_value_byte(p, &v); 445*f6e214c7SGavin Maltby return (add_count_entry(h, te, v)); 446*f6e214c7SGavin Maltby } 447*f6e214c7SGavin Maltby case DATA_TYPE_UINT8: 448*f6e214c7SGavin Maltby { 449*f6e214c7SGavin Maltby uint8_t v; 450*f6e214c7SGavin Maltby 451*f6e214c7SGavin Maltby (void) nvpair_value_uint8(p, &v); 452*f6e214c7SGavin Maltby return (add_count_entry(h, te, v)); 453*f6e214c7SGavin Maltby } 454*f6e214c7SGavin Maltby case DATA_TYPE_UINT16: 455*f6e214c7SGavin Maltby { 456*f6e214c7SGavin Maltby uint16_t v; 457*f6e214c7SGavin Maltby 458*f6e214c7SGavin Maltby (void) nvpair_value_uint16(p, &v); 459*f6e214c7SGavin Maltby return (add_count_entry(h, te, v)); 460*f6e214c7SGavin Maltby } 461*f6e214c7SGavin Maltby case DATA_TYPE_UINT32: 462*f6e214c7SGavin Maltby { 463*f6e214c7SGavin Maltby uint32_t v; 464*f6e214c7SGavin Maltby 465*f6e214c7SGavin Maltby (void) nvpair_value_uint32(p, &v); 466*f6e214c7SGavin Maltby return (add_count_entry(h, te, v)); 467*f6e214c7SGavin Maltby } 468*f6e214c7SGavin Maltby case DATA_TYPE_UINT64: 469*f6e214c7SGavin Maltby { 470*f6e214c7SGavin Maltby uint64_t v; 471*f6e214c7SGavin Maltby 472*f6e214c7SGavin Maltby (void) nvpair_value_uint64(p, &v); 473*f6e214c7SGavin Maltby return (add_count_entry(h, te, v)); 474*f6e214c7SGavin Maltby } 475*f6e214c7SGavin Maltby case DATA_TYPE_BYTE_ARRAY: 476*f6e214c7SGavin Maltby { 477*f6e214c7SGavin Maltby uchar_t *v; 478*f6e214c7SGavin Maltby 479*f6e214c7SGavin Maltby (void) nvpair_value_byte_array(p, &v, &n); 480*f6e214c7SGavin Maltby for (i = 0; i < n; ++i) { 481*f6e214c7SGavin Maltby if (add_count_entry(h, te, v[i]) != SCF_SUCCESS) 482*f6e214c7SGavin Maltby return (SCF_FAILED); 483*f6e214c7SGavin Maltby } 484*f6e214c7SGavin Maltby return (SCF_SUCCESS); 485*f6e214c7SGavin Maltby } 486*f6e214c7SGavin Maltby case DATA_TYPE_UINT8_ARRAY: 487*f6e214c7SGavin Maltby { 488*f6e214c7SGavin Maltby uint8_t *v; 489*f6e214c7SGavin Maltby 490*f6e214c7SGavin Maltby (void) nvpair_value_uint8_array(p, &v, &n); 491*f6e214c7SGavin Maltby for (i = 0; i < n; ++i) { 492*f6e214c7SGavin Maltby if (add_count_entry(h, te, v[i]) != SCF_SUCCESS) 493*f6e214c7SGavin Maltby return (SCF_FAILED); 494*f6e214c7SGavin Maltby } 495*f6e214c7SGavin Maltby return (SCF_SUCCESS); 496*f6e214c7SGavin Maltby } 497*f6e214c7SGavin Maltby case DATA_TYPE_UINT16_ARRAY: 498*f6e214c7SGavin Maltby { 499*f6e214c7SGavin Maltby uint16_t *v; 500*f6e214c7SGavin Maltby 501*f6e214c7SGavin Maltby (void) nvpair_value_uint16_array(p, &v, &n); 502*f6e214c7SGavin Maltby for (i = 0; i < n; ++i) { 503*f6e214c7SGavin Maltby if (add_count_entry(h, te, v[i]) != SCF_SUCCESS) 504*f6e214c7SGavin Maltby return (SCF_FAILED); 505*f6e214c7SGavin Maltby } 506*f6e214c7SGavin Maltby return (SCF_SUCCESS); 507*f6e214c7SGavin Maltby } 508*f6e214c7SGavin Maltby case DATA_TYPE_UINT32_ARRAY: 509*f6e214c7SGavin Maltby { 510*f6e214c7SGavin Maltby uint32_t *v; 511*f6e214c7SGavin Maltby 512*f6e214c7SGavin Maltby (void) nvpair_value_uint32_array(p, &v, &n); 513*f6e214c7SGavin Maltby for (i = 0; i < n; ++i) { 514*f6e214c7SGavin Maltby if (add_count_entry(h, te, v[i]) != SCF_SUCCESS) 515*f6e214c7SGavin Maltby return (SCF_FAILED); 516*f6e214c7SGavin Maltby } 517*f6e214c7SGavin Maltby return (SCF_SUCCESS); 518*f6e214c7SGavin Maltby } 519*f6e214c7SGavin Maltby case DATA_TYPE_UINT64_ARRAY: 520*f6e214c7SGavin Maltby { 521*f6e214c7SGavin Maltby uint64_t *v; 522*f6e214c7SGavin Maltby 523*f6e214c7SGavin Maltby (void) nvpair_value_uint64_array(p, &v, &n); 524*f6e214c7SGavin Maltby for (i = 0; i < n; ++i) { 525*f6e214c7SGavin Maltby if (add_count_entry(h, te, v[i]) != SCF_SUCCESS) 526*f6e214c7SGavin Maltby return (SCF_FAILED); 527*f6e214c7SGavin Maltby } 528*f6e214c7SGavin Maltby return (SCF_SUCCESS); 529*f6e214c7SGavin Maltby } 530*f6e214c7SGavin Maltby case DATA_TYPE_INT8: 531*f6e214c7SGavin Maltby { 532*f6e214c7SGavin Maltby int8_t v; 533*f6e214c7SGavin Maltby 534*f6e214c7SGavin Maltby (void) nvpair_value_int8(p, &v); 535*f6e214c7SGavin Maltby return (add_integer_entry(h, te, v)); 536*f6e214c7SGavin Maltby } 537*f6e214c7SGavin Maltby case DATA_TYPE_INT16: 538*f6e214c7SGavin Maltby { 539*f6e214c7SGavin Maltby int16_t v; 540*f6e214c7SGavin Maltby 541*f6e214c7SGavin Maltby (void) nvpair_value_int16(p, &v); 542*f6e214c7SGavin Maltby return (add_integer_entry(h, te, v)); 543*f6e214c7SGavin Maltby } 544*f6e214c7SGavin Maltby case DATA_TYPE_INT32: 545*f6e214c7SGavin Maltby { 546*f6e214c7SGavin Maltby int32_t v; 547*f6e214c7SGavin Maltby 548*f6e214c7SGavin Maltby (void) nvpair_value_int32(p, &v); 549*f6e214c7SGavin Maltby return (add_integer_entry(h, te, v)); 550*f6e214c7SGavin Maltby } 551*f6e214c7SGavin Maltby case DATA_TYPE_INT64: 552*f6e214c7SGavin Maltby { 553*f6e214c7SGavin Maltby int64_t v; 554*f6e214c7SGavin Maltby 555*f6e214c7SGavin Maltby (void) nvpair_value_int64(p, &v); 556*f6e214c7SGavin Maltby return (add_integer_entry(h, te, v)); 557*f6e214c7SGavin Maltby } 558*f6e214c7SGavin Maltby case DATA_TYPE_INT8_ARRAY: 559*f6e214c7SGavin Maltby { 560*f6e214c7SGavin Maltby int8_t *v; 561*f6e214c7SGavin Maltby 562*f6e214c7SGavin Maltby (void) nvpair_value_int8_array(p, &v, &n); 563*f6e214c7SGavin Maltby for (i = 0; i < n; ++i) { 564*f6e214c7SGavin Maltby if (add_integer_entry(h, te, v[i]) != 565*f6e214c7SGavin Maltby SCF_SUCCESS) 566*f6e214c7SGavin Maltby return (SCF_FAILED); 567*f6e214c7SGavin Maltby } 568*f6e214c7SGavin Maltby return (SCF_SUCCESS); 569*f6e214c7SGavin Maltby } 570*f6e214c7SGavin Maltby case DATA_TYPE_INT16_ARRAY: 571*f6e214c7SGavin Maltby { 572*f6e214c7SGavin Maltby int16_t *v; 573*f6e214c7SGavin Maltby 574*f6e214c7SGavin Maltby (void) nvpair_value_int16_array(p, &v, &n); 575*f6e214c7SGavin Maltby for (i = 0; i < n; ++i) { 576*f6e214c7SGavin Maltby if (add_integer_entry(h, te, v[i]) != 577*f6e214c7SGavin Maltby SCF_SUCCESS) 578*f6e214c7SGavin Maltby return (SCF_FAILED); 579*f6e214c7SGavin Maltby } 580*f6e214c7SGavin Maltby return (SCF_SUCCESS); 581*f6e214c7SGavin Maltby } 582*f6e214c7SGavin Maltby case DATA_TYPE_INT32_ARRAY: 583*f6e214c7SGavin Maltby { 584*f6e214c7SGavin Maltby int32_t *v; 585*f6e214c7SGavin Maltby 586*f6e214c7SGavin Maltby (void) nvpair_value_int32_array(p, &v, &n); 587*f6e214c7SGavin Maltby for (i = 0; i < n; ++i) { 588*f6e214c7SGavin Maltby if (add_integer_entry(h, te, v[i]) != 589*f6e214c7SGavin Maltby SCF_SUCCESS) 590*f6e214c7SGavin Maltby return (SCF_FAILED); 591*f6e214c7SGavin Maltby } 592*f6e214c7SGavin Maltby return (SCF_SUCCESS); 593*f6e214c7SGavin Maltby } 594*f6e214c7SGavin Maltby case DATA_TYPE_INT64_ARRAY: 595*f6e214c7SGavin Maltby { 596*f6e214c7SGavin Maltby int64_t *v; 597*f6e214c7SGavin Maltby 598*f6e214c7SGavin Maltby (void) nvpair_value_int64_array(p, &v, &n); 599*f6e214c7SGavin Maltby for (i = 0; i < n; ++i) { 600*f6e214c7SGavin Maltby if (add_integer_entry(h, te, v[i]) != 601*f6e214c7SGavin Maltby SCF_SUCCESS) 602*f6e214c7SGavin Maltby return (SCF_FAILED); 603*f6e214c7SGavin Maltby } 604*f6e214c7SGavin Maltby return (SCF_SUCCESS); 605*f6e214c7SGavin Maltby } 606*f6e214c7SGavin Maltby case DATA_TYPE_STRING: 607*f6e214c7SGavin Maltby { 608*f6e214c7SGavin Maltby char *str; 609*f6e214c7SGavin Maltby 610*f6e214c7SGavin Maltby (void) nvpair_value_string(p, &str); 611*f6e214c7SGavin Maltby return (add_astring_entry(h, te, str)); 612*f6e214c7SGavin Maltby } 613*f6e214c7SGavin Maltby case DATA_TYPE_STRING_ARRAY: 614*f6e214c7SGavin Maltby { 615*f6e214c7SGavin Maltby char **v; 616*f6e214c7SGavin Maltby 617*f6e214c7SGavin Maltby (void) nvpair_value_string_array(p, &v, &n); 618*f6e214c7SGavin Maltby for (i = 0; i < n; ++i) { 619*f6e214c7SGavin Maltby if (add_astring_entry(h, te, v[i]) != 620*f6e214c7SGavin Maltby SCF_SUCCESS) 621*f6e214c7SGavin Maltby return (SCF_FAILED); 622*f6e214c7SGavin Maltby } 623*f6e214c7SGavin Maltby return (SCF_SUCCESS); 624*f6e214c7SGavin Maltby } 625*f6e214c7SGavin Maltby default: 626*f6e214c7SGavin Maltby (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT); 627*f6e214c7SGavin Maltby return (SCF_FAILED); 628*f6e214c7SGavin Maltby } 629*f6e214c7SGavin Maltby 630*f6e214c7SGavin Maltby /*NOTREACHED*/ 631*f6e214c7SGavin Maltby } 632*f6e214c7SGavin Maltby 633*f6e214c7SGavin Maltby /* 634*f6e214c7SGavin Maltby * Add new transaction entry to scf_transaction_t 635*f6e214c7SGavin Maltby * 636*f6e214c7SGavin Maltby * Can fail with 637*f6e214c7SGavin Maltby * SCF_ERROR_BACKEND_ACCESS 638*f6e214c7SGavin Maltby * SCF_ERROR_CONNECTION_BROKEN 639*f6e214c7SGavin Maltby * SCF_ERROR_DELETED 640*f6e214c7SGavin Maltby * SCF_ERROR_INTERNAL 641*f6e214c7SGavin Maltby * SCF_ERROR_NO_RESOURCES 642*f6e214c7SGavin Maltby * SCF_ERROR_NOT_FOUND 643*f6e214c7SGavin Maltby */ 644*f6e214c7SGavin Maltby static int 645*f6e214c7SGavin Maltby prep_transaction(scf_transaction_t *tx, scf_transaction_entry_t *te, 646*f6e214c7SGavin Maltby const char *prop, scf_type_t type) 647*f6e214c7SGavin Maltby { 648*f6e214c7SGavin Maltby if (scf_transaction_property_new(tx, te, prop, type) != SCF_SUCCESS && 649*f6e214c7SGavin Maltby (scf_error() != SCF_ERROR_EXISTS || 650*f6e214c7SGavin Maltby scf_transaction_property_change(tx, te, prop, type) != 651*f6e214c7SGavin Maltby SCF_SUCCESS)) { 652*f6e214c7SGavin Maltby if (check_scf_error(scf_error(), errs_2)) { 653*f6e214c7SGavin Maltby return (SCF_FAILED); 654*f6e214c7SGavin Maltby } 655*f6e214c7SGavin Maltby } 656*f6e214c7SGavin Maltby 657*f6e214c7SGavin Maltby return (SCF_SUCCESS); 658*f6e214c7SGavin Maltby } 659*f6e214c7SGavin Maltby 660*f6e214c7SGavin Maltby /* 661*f6e214c7SGavin Maltby * notify_set_params() 662*f6e214c7SGavin Maltby * returns 0 on success or -1 on failure 663*f6e214c7SGavin Maltby * SCF_ERROR_BACKEND_ACCESS 664*f6e214c7SGavin Maltby * SCF_ERROR_BACKEND_READONLY 665*f6e214c7SGavin Maltby * SCF_ERROR_CONNECTION_BROKEN 666*f6e214c7SGavin Maltby * SCF_ERROR_DELETED 667*f6e214c7SGavin Maltby * SCF_ERROR_INTERNAL 668*f6e214c7SGavin Maltby * SCF_ERROR_INVALID_ARGUMENT 669*f6e214c7SGavin Maltby * SCF_ERROR_NO_MEMORY 670*f6e214c7SGavin Maltby * SCF_ERROR_NO_RESOURCES 671*f6e214c7SGavin Maltby * SCF_ERROR_NOT_FOUND 672*f6e214c7SGavin Maltby * SCF_ERROR_PERMISSION_DENIED 673*f6e214c7SGavin Maltby */ 674*f6e214c7SGavin Maltby static int 675*f6e214c7SGavin Maltby notify_set_params(scf_propertygroup_t *pg, nvlist_t *params) 676*f6e214c7SGavin Maltby { 677*f6e214c7SGavin Maltby scf_handle_t *h = scf_pg_handle(pg); 678*f6e214c7SGavin Maltby scf_error_t scf_e = scf_error(); 679*f6e214c7SGavin Maltby scf_transaction_t *tx = scf_transaction_create(h); 680*f6e214c7SGavin Maltby int bufsz = scf_limit(SCF_LIMIT_MAX_NAME_LENGTH) + 1; 681*f6e214c7SGavin Maltby char *propname = malloc(bufsz); 682*f6e214c7SGavin Maltby int r = -1; 683*f6e214c7SGavin Maltby int err; 684*f6e214c7SGavin Maltby 685*f6e214c7SGavin Maltby if (h == NULL) { 686*f6e214c7SGavin Maltby /* 687*f6e214c7SGavin Maltby * Use the error stored in scf_e 688*f6e214c7SGavin Maltby */ 689*f6e214c7SGavin Maltby (void) scf_set_error(scf_e); 690*f6e214c7SGavin Maltby goto cleanup; 691*f6e214c7SGavin Maltby } 692*f6e214c7SGavin Maltby if (tx == NULL) 693*f6e214c7SGavin Maltby goto cleanup; 694*f6e214c7SGavin Maltby 695*f6e214c7SGavin Maltby if (propname == NULL) { 696*f6e214c7SGavin Maltby (void) scf_set_error(SCF_ERROR_NO_MEMORY); 697*f6e214c7SGavin Maltby goto cleanup; 698*f6e214c7SGavin Maltby } 699*f6e214c7SGavin Maltby 700*f6e214c7SGavin Maltby do { 701*f6e214c7SGavin Maltby nvpair_t *nvp; 702*f6e214c7SGavin Maltby 703*f6e214c7SGavin Maltby /* 704*f6e214c7SGavin Maltby * make sure we have the most recent version of the pg 705*f6e214c7SGavin Maltby * start the transaction 706*f6e214c7SGavin Maltby */ 707*f6e214c7SGavin Maltby if (scf_pg_update(pg) == SCF_FAILED || 708*f6e214c7SGavin Maltby scf_transaction_start(tx, pg) != SCF_SUCCESS) { 709*f6e214c7SGavin Maltby if (check_scf_error(scf_error(), errs_2)) { 710*f6e214c7SGavin Maltby goto cleanup; 711*f6e214c7SGavin Maltby } 712*f6e214c7SGavin Maltby } 713*f6e214c7SGavin Maltby 714*f6e214c7SGavin Maltby for (nvp = nvlist_next_nvpair(params, NULL); nvp != NULL; 715*f6e214c7SGavin Maltby nvp = nvlist_next_nvpair(params, nvp)) { 716*f6e214c7SGavin Maltby nvlist_t *m; 717*f6e214c7SGavin Maltby nvpair_t *p; 718*f6e214c7SGavin Maltby 719*f6e214c7SGavin Maltby /* we ONLY take nvlists here */ 720*f6e214c7SGavin Maltby if (nvpair_type(nvp) != DATA_TYPE_NVLIST) { 721*f6e214c7SGavin Maltby char *name = nvpair_name(nvp); 722*f6e214c7SGavin Maltby 723*f6e214c7SGavin Maltby /* 724*f6e214c7SGavin Maltby * if this is output from 725*f6e214c7SGavin Maltby * smf_notify_get_params() we want to skip 726*f6e214c7SGavin Maltby * the tset value of the nvlist 727*f6e214c7SGavin Maltby */ 728*f6e214c7SGavin Maltby if (strcmp(name, SCF_NOTIFY_NAME_TSET) == 0) 729*f6e214c7SGavin Maltby continue; 730*f6e214c7SGavin Maltby 731*f6e214c7SGavin Maltby (void) scf_set_error( 732*f6e214c7SGavin Maltby SCF_ERROR_INVALID_ARGUMENT); 733*f6e214c7SGavin Maltby goto cleanup; 734*f6e214c7SGavin Maltby } 735*f6e214c7SGavin Maltby 736*f6e214c7SGavin Maltby if (nvpair_value_nvlist(nvp, &m) != 0) { 737*f6e214c7SGavin Maltby (void) scf_set_error( 738*f6e214c7SGavin Maltby SCF_ERROR_INVALID_ARGUMENT); 739*f6e214c7SGavin Maltby goto cleanup; 740*f6e214c7SGavin Maltby } 741*f6e214c7SGavin Maltby 742*f6e214c7SGavin Maltby /* 743*f6e214c7SGavin Maltby * Traverse each mechanism list 744*f6e214c7SGavin Maltby */ 745*f6e214c7SGavin Maltby for (p = nvlist_next_nvpair(m, NULL); p != NULL; 746*f6e214c7SGavin Maltby p = nvlist_next_nvpair(m, p)) { 747*f6e214c7SGavin Maltby scf_transaction_entry_t *te = 748*f6e214c7SGavin Maltby scf_entry_create(h); 749*f6e214c7SGavin Maltby /* map the nvpair type to scf type */ 750*f6e214c7SGavin Maltby scf_type_t type = get_scf_type(p); 751*f6e214c7SGavin Maltby 752*f6e214c7SGavin Maltby if (te == NULL) { 753*f6e214c7SGavin Maltby if (scf_error() != 754*f6e214c7SGavin Maltby SCF_ERROR_INVALID_ARGUMENT) { 755*f6e214c7SGavin Maltby scf_entry_destroy(te); 756*f6e214c7SGavin Maltby goto cleanup; 757*f6e214c7SGavin Maltby } else { 758*f6e214c7SGavin Maltby assert(0); 759*f6e214c7SGavin Maltby abort(); 760*f6e214c7SGavin Maltby } 761*f6e214c7SGavin Maltby } 762*f6e214c7SGavin Maltby 763*f6e214c7SGavin Maltby if (type == SCF_TYPE_INVALID) { 764*f6e214c7SGavin Maltby (void) scf_set_error( 765*f6e214c7SGavin Maltby SCF_ERROR_INVALID_ARGUMENT); 766*f6e214c7SGavin Maltby scf_entry_destroy(te); 767*f6e214c7SGavin Maltby goto cleanup; 768*f6e214c7SGavin Maltby } 769*f6e214c7SGavin Maltby 770*f6e214c7SGavin Maltby if (snprintf(propname, bufsz, "%s,%s", 771*f6e214c7SGavin Maltby nvpair_name(nvp), nvpair_name(p)) >= 772*f6e214c7SGavin Maltby bufsz) { 773*f6e214c7SGavin Maltby (void) scf_set_error( 774*f6e214c7SGavin Maltby SCF_ERROR_INVALID_ARGUMENT); 775*f6e214c7SGavin Maltby scf_entry_destroy(te); 776*f6e214c7SGavin Maltby goto cleanup; 777*f6e214c7SGavin Maltby } 778*f6e214c7SGavin Maltby 779*f6e214c7SGavin Maltby if (prep_transaction(tx, te, propname, type) != 780*f6e214c7SGavin Maltby SCF_SUCCESS) { 781*f6e214c7SGavin Maltby scf_entry_destroy(te); 782*f6e214c7SGavin Maltby goto cleanup; 783*f6e214c7SGavin Maltby } 784*f6e214c7SGavin Maltby 785*f6e214c7SGavin Maltby if (get_nvpair_vals(h, te, p) != SCF_SUCCESS) { 786*f6e214c7SGavin Maltby if (check_scf_error(scf_error(), 787*f6e214c7SGavin Maltby errs_2)) { 788*f6e214c7SGavin Maltby goto cleanup; 789*f6e214c7SGavin Maltby } 790*f6e214c7SGavin Maltby } 791*f6e214c7SGavin Maltby } 792*f6e214c7SGavin Maltby } 793*f6e214c7SGavin Maltby err = scf_transaction_commit(tx); 794*f6e214c7SGavin Maltby scf_transaction_destroy_children(tx); 795*f6e214c7SGavin Maltby } while (err == 0); 796*f6e214c7SGavin Maltby 797*f6e214c7SGavin Maltby if (err == -1) { 798*f6e214c7SGavin Maltby if (check_scf_error(scf_error(), errs_2)) { 799*f6e214c7SGavin Maltby goto cleanup; 800*f6e214c7SGavin Maltby } 801*f6e214c7SGavin Maltby } 802*f6e214c7SGavin Maltby 803*f6e214c7SGavin Maltby r = 0; 804*f6e214c7SGavin Maltby 805*f6e214c7SGavin Maltby cleanup: 806*f6e214c7SGavin Maltby scf_transaction_destroy_children(tx); 807*f6e214c7SGavin Maltby scf_transaction_destroy(tx); 808*f6e214c7SGavin Maltby free(propname); 809*f6e214c7SGavin Maltby 810*f6e214c7SGavin Maltby return (r); 811*f6e214c7SGavin Maltby } 812*f6e214c7SGavin Maltby 813*f6e214c7SGavin Maltby /* 814*f6e214c7SGavin Maltby * Decode fmri. Populates service OR instance depending on which one is an 815*f6e214c7SGavin Maltby * exact match to the fmri parameter. 816*f6e214c7SGavin Maltby * 817*f6e214c7SGavin Maltby * The function destroys and sets the unused entity (service or instance) to 818*f6e214c7SGavin Maltby * NULL. 819*f6e214c7SGavin Maltby * 820*f6e214c7SGavin Maltby * return SCF_SUCCESS or SCF_FAILED on 821*f6e214c7SGavin Maltby * SCF_ERROR_BACKEND_ACCESS 822*f6e214c7SGavin Maltby * SCF_ERROR_CONNECTION_BROKEN 823*f6e214c7SGavin Maltby * SCF_ERROR_CONSTRAINT_VIOLATED 824*f6e214c7SGavin Maltby * SCF_ERROR_DELETED 825*f6e214c7SGavin Maltby * SCF_ERROR_HANDLE_MISMATCH 826*f6e214c7SGavin Maltby * SCF_ERROR_INTERNAL 827*f6e214c7SGavin Maltby * SCF_ERROR_INVALID_ARGUMENT 828*f6e214c7SGavin Maltby * SCF_ERROR_NO_RESOURCES 829*f6e214c7SGavin Maltby * SCF_ERROR_NOT_BOUND 830*f6e214c7SGavin Maltby * SCF_ERROR_NOT_FOUND 831*f6e214c7SGavin Maltby * SCF_ERROR_NOT_SET 832*f6e214c7SGavin Maltby */ 833*f6e214c7SGavin Maltby static int 834*f6e214c7SGavin Maltby decode_fmri(const char *fmri, scf_handle_t *h, scf_service_t **s, 835*f6e214c7SGavin Maltby scf_instance_t **i) 836*f6e214c7SGavin Maltby { 837*f6e214c7SGavin Maltby if (scf_handle_decode_fmri(h, fmri, NULL, *s, NULL, NULL, NULL, 838*f6e214c7SGavin Maltby SCF_DECODE_FMRI_EXACT) != SCF_SUCCESS) { 839*f6e214c7SGavin Maltby if (scf_error() == SCF_ERROR_CONSTRAINT_VIOLATED) { 840*f6e214c7SGavin Maltby scf_service_destroy(*s); 841*f6e214c7SGavin Maltby *s = NULL; 842*f6e214c7SGavin Maltby } else { 843*f6e214c7SGavin Maltby return (SCF_FAILED); 844*f6e214c7SGavin Maltby } 845*f6e214c7SGavin Maltby } 846*f6e214c7SGavin Maltby if (*s == NULL) 847*f6e214c7SGavin Maltby if (scf_handle_decode_fmri(h, fmri, NULL, NULL, *i, 848*f6e214c7SGavin Maltby NULL, NULL, SCF_DECODE_FMRI_EXACT) != SCF_SUCCESS) { 849*f6e214c7SGavin Maltby return (SCF_FAILED); 850*f6e214c7SGavin Maltby } 851*f6e214c7SGavin Maltby 852*f6e214c7SGavin Maltby return (SCF_SUCCESS); 853*f6e214c7SGavin Maltby } 854*f6e214c7SGavin Maltby 855*f6e214c7SGavin Maltby /* 856*f6e214c7SGavin Maltby * Return size in bytes for an SCF_TYPE_*. Not all libscf types are supported 857*f6e214c7SGavin Maltby */ 858*f6e214c7SGavin Maltby static int 859*f6e214c7SGavin Maltby get_type_size(scf_type_t t) 860*f6e214c7SGavin Maltby { 861*f6e214c7SGavin Maltby switch (t) { 862*f6e214c7SGavin Maltby case SCF_TYPE_BOOLEAN: 863*f6e214c7SGavin Maltby return (sizeof (uint8_t)); 864*f6e214c7SGavin Maltby case SCF_TYPE_COUNT: 865*f6e214c7SGavin Maltby return (sizeof (uint64_t)); 866*f6e214c7SGavin Maltby case SCF_TYPE_INTEGER: 867*f6e214c7SGavin Maltby return (sizeof (int64_t)); 868*f6e214c7SGavin Maltby case SCF_TYPE_ASTRING: 869*f6e214c7SGavin Maltby case SCF_TYPE_USTRING: 870*f6e214c7SGavin Maltby return (sizeof (void *)); 871*f6e214c7SGavin Maltby default: 872*f6e214c7SGavin Maltby return (-1); 873*f6e214c7SGavin Maltby } 874*f6e214c7SGavin Maltby 875*f6e214c7SGavin Maltby /*NOTREACHED*/ 876*f6e214c7SGavin Maltby } 877*f6e214c7SGavin Maltby 878*f6e214c7SGavin Maltby /* 879*f6e214c7SGavin Maltby * Return a pointer to the array of values according to its type 880*f6e214c7SGavin Maltby */ 881*f6e214c7SGavin Maltby static void ** 882*f6e214c7SGavin Maltby get_v_pointer(scf_values_t *v) 883*f6e214c7SGavin Maltby { 884*f6e214c7SGavin Maltby switch (v->value_type) { 885*f6e214c7SGavin Maltby case SCF_TYPE_BOOLEAN: 886*f6e214c7SGavin Maltby return ((void **)&v->values.v_boolean); 887*f6e214c7SGavin Maltby case SCF_TYPE_COUNT: 888*f6e214c7SGavin Maltby return ((void **)&v->values.v_count); 889*f6e214c7SGavin Maltby case SCF_TYPE_INTEGER: 890*f6e214c7SGavin Maltby return ((void **)&v->values.v_integer); 891*f6e214c7SGavin Maltby case SCF_TYPE_ASTRING: 892*f6e214c7SGavin Maltby return ((void **)&v->values.v_astring); 893*f6e214c7SGavin Maltby case SCF_TYPE_USTRING: 894*f6e214c7SGavin Maltby return ((void **)&v->values.v_ustring); 895*f6e214c7SGavin Maltby default: 896*f6e214c7SGavin Maltby return (NULL); 897*f6e214c7SGavin Maltby } 898*f6e214c7SGavin Maltby 899*f6e214c7SGavin Maltby /*NOTREACHED*/ 900*f6e214c7SGavin Maltby } 901*f6e214c7SGavin Maltby 902*f6e214c7SGavin Maltby /* 903*f6e214c7SGavin Maltby * Populate scf_values_t value array at position c. 904*f6e214c7SGavin Maltby */ 905*f6e214c7SGavin Maltby static int 906*f6e214c7SGavin Maltby get_value(scf_value_t *val, scf_values_t *v, int c, char *buf, int sz) 907*f6e214c7SGavin Maltby { 908*f6e214c7SGavin Maltby switch (v->value_type) { 909*f6e214c7SGavin Maltby case SCF_TYPE_BOOLEAN: 910*f6e214c7SGavin Maltby return (scf_value_get_boolean(val, v->values.v_boolean + c)); 911*f6e214c7SGavin Maltby case SCF_TYPE_COUNT: 912*f6e214c7SGavin Maltby return (scf_value_get_count(val, v->values.v_count + c)); 913*f6e214c7SGavin Maltby case SCF_TYPE_INTEGER: 914*f6e214c7SGavin Maltby return (scf_value_get_integer(val, v->values.v_integer + c)); 915*f6e214c7SGavin Maltby case SCF_TYPE_ASTRING: 916*f6e214c7SGavin Maltby if (scf_value_get_astring(val, buf, sz) < 0 || 917*f6e214c7SGavin Maltby (v->values.v_astring[c] = strdup(buf)) == NULL) { 918*f6e214c7SGavin Maltby (void) scf_set_error(SCF_ERROR_NO_MEMORY); 919*f6e214c7SGavin Maltby return (-1); 920*f6e214c7SGavin Maltby } 921*f6e214c7SGavin Maltby return (0); 922*f6e214c7SGavin Maltby case SCF_TYPE_USTRING: 923*f6e214c7SGavin Maltby if (scf_value_get_ustring(val, buf, sz) < 0 || 924*f6e214c7SGavin Maltby (v->values.v_ustring[c] = strdup(buf)) == NULL) { 925*f6e214c7SGavin Maltby (void) scf_set_error(SCF_ERROR_NO_MEMORY); 926*f6e214c7SGavin Maltby return (-1); 927*f6e214c7SGavin Maltby } 928*f6e214c7SGavin Maltby return (0); 929*f6e214c7SGavin Maltby default: 930*f6e214c7SGavin Maltby return (-1); 931*f6e214c7SGavin Maltby } 932*f6e214c7SGavin Maltby 933*f6e214c7SGavin Maltby /*NOTREACHED*/ 934*f6e214c7SGavin Maltby } 935*f6e214c7SGavin Maltby 936*f6e214c7SGavin Maltby /* 937*f6e214c7SGavin Maltby * Populate scf_values_t structure with values from prop 938*f6e214c7SGavin Maltby */ 939*f6e214c7SGavin Maltby static int 940*f6e214c7SGavin Maltby values_get(scf_property_t *prop, scf_values_t *v) 941*f6e214c7SGavin Maltby { 942*f6e214c7SGavin Maltby scf_handle_t *h = scf_property_handle(prop); 943*f6e214c7SGavin Maltby scf_error_t scf_e = scf_error(); 944*f6e214c7SGavin Maltby scf_value_t *val = scf_value_create(h); 945*f6e214c7SGavin Maltby scf_iter_t *it = scf_iter_create(h); 946*f6e214c7SGavin Maltby scf_type_t type = SCF_TYPE_INVALID; 947*f6e214c7SGavin Maltby ssize_t sz = scf_limit(SCF_LIMIT_MAX_VALUE_LENGTH) + 1; 948*f6e214c7SGavin Maltby char *buf = malloc(sz); 949*f6e214c7SGavin Maltby void **p; 950*f6e214c7SGavin Maltby int err, elem_sz, count, cursz; 951*f6e214c7SGavin Maltby int r = SCF_FAILED; 952*f6e214c7SGavin Maltby 953*f6e214c7SGavin Maltby assert(v != NULL); 954*f6e214c7SGavin Maltby assert(v->reserved == NULL); 955*f6e214c7SGavin Maltby if (buf == NULL) { 956*f6e214c7SGavin Maltby (void) scf_set_error(SCF_ERROR_NO_MEMORY); 957*f6e214c7SGavin Maltby goto cleanup; 958*f6e214c7SGavin Maltby } 959*f6e214c7SGavin Maltby if (h == NULL) { 960*f6e214c7SGavin Maltby /* 961*f6e214c7SGavin Maltby * Use the error stored in scf_e 962*f6e214c7SGavin Maltby */ 963*f6e214c7SGavin Maltby (void) scf_set_error(scf_e); 964*f6e214c7SGavin Maltby goto cleanup; 965*f6e214c7SGavin Maltby } 966*f6e214c7SGavin Maltby if (val == NULL || it == NULL) 967*f6e214c7SGavin Maltby goto cleanup; 968*f6e214c7SGavin Maltby 969*f6e214c7SGavin Maltby if (scf_property_type(prop, &type) != SCF_SUCCESS) 970*f6e214c7SGavin Maltby goto cleanup; 971*f6e214c7SGavin Maltby if (scf_property_is_type(prop, v->value_type) != SCF_SUCCESS) 972*f6e214c7SGavin Maltby goto error; 973*f6e214c7SGavin Maltby 974*f6e214c7SGavin Maltby elem_sz = get_type_size(type); 975*f6e214c7SGavin Maltby assert(elem_sz > 0); 976*f6e214c7SGavin Maltby 977*f6e214c7SGavin Maltby p = get_v_pointer(v); 978*f6e214c7SGavin Maltby assert(p != NULL); 979*f6e214c7SGavin Maltby 980*f6e214c7SGavin Maltby cursz = count = v->value_count; 981*f6e214c7SGavin Maltby if (scf_iter_property_values(it, prop) != 0) { 982*f6e214c7SGavin Maltby goto error; 983*f6e214c7SGavin Maltby } 984*f6e214c7SGavin Maltby 985*f6e214c7SGavin Maltby while ((err = scf_iter_next_value(it, val)) == 1) { 986*f6e214c7SGavin Maltby if (count + 1 >= cursz) { 987*f6e214c7SGavin Maltby void *tmp; 988*f6e214c7SGavin Maltby 989*f6e214c7SGavin Maltby /* set initial size or double it */ 990*f6e214c7SGavin Maltby cursz = cursz ? 2 * cursz : 8; 991*f6e214c7SGavin Maltby if ((tmp = realloc(*p, cursz * elem_sz)) == NULL) { 992*f6e214c7SGavin Maltby (void) scf_set_error(SCF_ERROR_NO_MEMORY); 993*f6e214c7SGavin Maltby goto error; 994*f6e214c7SGavin Maltby } 995*f6e214c7SGavin Maltby *p = tmp; 996*f6e214c7SGavin Maltby } 997*f6e214c7SGavin Maltby 998*f6e214c7SGavin Maltby if (get_value(val, v, count, buf, sz) != 0) 999*f6e214c7SGavin Maltby goto error; 1000*f6e214c7SGavin Maltby 1001*f6e214c7SGavin Maltby count++; 1002*f6e214c7SGavin Maltby } 1003*f6e214c7SGavin Maltby 1004*f6e214c7SGavin Maltby v->value_count = count; 1005*f6e214c7SGavin Maltby 1006*f6e214c7SGavin Maltby if (err != 0) 1007*f6e214c7SGavin Maltby goto error; 1008*f6e214c7SGavin Maltby 1009*f6e214c7SGavin Maltby r = SCF_SUCCESS; 1010*f6e214c7SGavin Maltby goto cleanup; 1011*f6e214c7SGavin Maltby 1012*f6e214c7SGavin Maltby error: 1013*f6e214c7SGavin Maltby v->value_count = count; 1014*f6e214c7SGavin Maltby scf_values_destroy(v); 1015*f6e214c7SGavin Maltby 1016*f6e214c7SGavin Maltby cleanup: 1017*f6e214c7SGavin Maltby free(buf); 1018*f6e214c7SGavin Maltby scf_iter_destroy(it); 1019*f6e214c7SGavin Maltby scf_value_destroy(val); 1020*f6e214c7SGavin Maltby return (r); 1021*f6e214c7SGavin Maltby } 1022*f6e214c7SGavin Maltby 1023*f6e214c7SGavin Maltby /* 1024*f6e214c7SGavin Maltby * Add values from property p to existing nvlist_t nvl. The data type in the 1025*f6e214c7SGavin Maltby * nvlist is inferred from the scf_type_t of the property. 1026*f6e214c7SGavin Maltby * 1027*f6e214c7SGavin Maltby * Returns SCF_SUCCESS or SCF_FAILED on 1028*f6e214c7SGavin Maltby * SCF_ERROR_CONNECTION_BROKEN 1029*f6e214c7SGavin Maltby * SCF_ERROR_DELETED 1030*f6e214c7SGavin Maltby * SCF_ERROR_HANDLE_DESTROYED 1031*f6e214c7SGavin Maltby * SCF_ERROR_HANDLE_MISMATCH 1032*f6e214c7SGavin Maltby * SCF_ERROR_INVALID_ARGUMENT 1033*f6e214c7SGavin Maltby * SCF_ERROR_NO_MEMORY 1034*f6e214c7SGavin Maltby * SCF_ERROR_NO_RESOURCES 1035*f6e214c7SGavin Maltby * SCF_ERROR_NOT_BOUND 1036*f6e214c7SGavin Maltby * SCF_ERROR_NOT_SET 1037*f6e214c7SGavin Maltby * SCF_ERROR_PERMISSION_DENIED 1038*f6e214c7SGavin Maltby * SCF_ERROR_TYPE_MISMATCH 1039*f6e214c7SGavin Maltby */ 1040*f6e214c7SGavin Maltby static int 1041*f6e214c7SGavin Maltby add_prop_to_nvlist(scf_property_t *p, const char *pname, nvlist_t *nvl, 1042*f6e214c7SGavin Maltby int array) 1043*f6e214c7SGavin Maltby { 1044*f6e214c7SGavin Maltby scf_values_t vals = { 0 }; 1045*f6e214c7SGavin Maltby scf_type_t type, base_type; 1046*f6e214c7SGavin Maltby int r = SCF_FAILED; 1047*f6e214c7SGavin Maltby int err = 0; 1048*f6e214c7SGavin Maltby 1049*f6e214c7SGavin Maltby if (p == NULL || pname == NULL || *pname == '\0' || nvl == NULL) { 1050*f6e214c7SGavin Maltby (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT); 1051*f6e214c7SGavin Maltby return (r); 1052*f6e214c7SGavin Maltby } 1053*f6e214c7SGavin Maltby 1054*f6e214c7SGavin Maltby if (scf_property_type(p, &type) != 0) 1055*f6e214c7SGavin Maltby goto cleanup; 1056*f6e214c7SGavin Maltby 1057*f6e214c7SGavin Maltby /* 1058*f6e214c7SGavin Maltby * scf_values_t does not support subtypes of SCF_TYPE_USTRING, 1059*f6e214c7SGavin Maltby * mapping them all to SCF_TYPE_USTRING 1060*f6e214c7SGavin Maltby */ 1061*f6e214c7SGavin Maltby base_type = scf_true_base_type(type); 1062*f6e214c7SGavin Maltby if (base_type == SCF_TYPE_ASTRING && type != SCF_TYPE_ASTRING) 1063*f6e214c7SGavin Maltby type = SCF_TYPE_USTRING; 1064*f6e214c7SGavin Maltby 1065*f6e214c7SGavin Maltby vals.value_type = type; 1066*f6e214c7SGavin Maltby if (values_get(p, &vals) != SCF_SUCCESS) { 1067*f6e214c7SGavin Maltby if (scf_error() == SCF_ERROR_INVALID_ARGUMENT) { 1068*f6e214c7SGavin Maltby assert(0); 1069*f6e214c7SGavin Maltby abort(); 1070*f6e214c7SGavin Maltby } 1071*f6e214c7SGavin Maltby goto cleanup; 1072*f6e214c7SGavin Maltby } 1073*f6e214c7SGavin Maltby 1074*f6e214c7SGavin Maltby switch (vals.value_type) { 1075*f6e214c7SGavin Maltby case SCF_TYPE_BOOLEAN: 1076*f6e214c7SGavin Maltby { 1077*f6e214c7SGavin Maltby boolean_t *v; 1078*f6e214c7SGavin Maltby int i; 1079*f6e214c7SGavin Maltby int n = vals.value_count; 1080*f6e214c7SGavin Maltby 1081*f6e214c7SGavin Maltby v = calloc(n, sizeof (boolean_t)); 1082*f6e214c7SGavin Maltby if (v == NULL) { 1083*f6e214c7SGavin Maltby (void) scf_set_error(SCF_ERROR_NO_MEMORY); 1084*f6e214c7SGavin Maltby goto cleanup; 1085*f6e214c7SGavin Maltby } 1086*f6e214c7SGavin Maltby for (i = 0; i < n; ++i) 1087*f6e214c7SGavin Maltby v[i] = (boolean_t)vals.values.v_boolean[i]; 1088*f6e214c7SGavin Maltby 1089*f6e214c7SGavin Maltby if (n == 1 && !array) 1090*f6e214c7SGavin Maltby err = nvlist_add_boolean_value(nvl, pname, *v); 1091*f6e214c7SGavin Maltby else 1092*f6e214c7SGavin Maltby err = nvlist_add_boolean_array(nvl, pname, 1093*f6e214c7SGavin Maltby v, n); 1094*f6e214c7SGavin Maltby if (err != 0) { 1095*f6e214c7SGavin Maltby free(v); 1096*f6e214c7SGavin Maltby goto cleanup; 1097*f6e214c7SGavin Maltby } 1098*f6e214c7SGavin Maltby free(v); 1099*f6e214c7SGavin Maltby } 1100*f6e214c7SGavin Maltby break; 1101*f6e214c7SGavin Maltby 1102*f6e214c7SGavin Maltby case SCF_TYPE_COUNT: 1103*f6e214c7SGavin Maltby if (vals.value_count == 1 && !array) 1104*f6e214c7SGavin Maltby err = nvlist_add_uint64(nvl, pname, 1105*f6e214c7SGavin Maltby *vals.values.v_count); 1106*f6e214c7SGavin Maltby else 1107*f6e214c7SGavin Maltby err = nvlist_add_uint64_array(nvl, pname, 1108*f6e214c7SGavin Maltby vals.values.v_count, vals.value_count); 1109*f6e214c7SGavin Maltby if (err != 0) 1110*f6e214c7SGavin Maltby goto cleanup; 1111*f6e214c7SGavin Maltby 1112*f6e214c7SGavin Maltby break; 1113*f6e214c7SGavin Maltby 1114*f6e214c7SGavin Maltby case SCF_TYPE_INTEGER: 1115*f6e214c7SGavin Maltby if (vals.value_count == 1 && !array) 1116*f6e214c7SGavin Maltby err = nvlist_add_int64(nvl, pname, 1117*f6e214c7SGavin Maltby *vals.values.v_integer); 1118*f6e214c7SGavin Maltby else 1119*f6e214c7SGavin Maltby err = nvlist_add_int64_array(nvl, pname, 1120*f6e214c7SGavin Maltby vals.values.v_integer, vals.value_count); 1121*f6e214c7SGavin Maltby if (err != 0) 1122*f6e214c7SGavin Maltby goto cleanup; 1123*f6e214c7SGavin Maltby 1124*f6e214c7SGavin Maltby break; 1125*f6e214c7SGavin Maltby 1126*f6e214c7SGavin Maltby case SCF_TYPE_ASTRING: 1127*f6e214c7SGavin Maltby if (vals.value_count == 1 && !array) 1128*f6e214c7SGavin Maltby err = nvlist_add_string(nvl, pname, 1129*f6e214c7SGavin Maltby *vals.values.v_astring); 1130*f6e214c7SGavin Maltby else 1131*f6e214c7SGavin Maltby err = nvlist_add_string_array(nvl, pname, 1132*f6e214c7SGavin Maltby vals.values.v_astring, vals.value_count); 1133*f6e214c7SGavin Maltby if (err != 0) 1134*f6e214c7SGavin Maltby goto cleanup; 1135*f6e214c7SGavin Maltby break; 1136*f6e214c7SGavin Maltby 1137*f6e214c7SGavin Maltby default: 1138*f6e214c7SGavin Maltby (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT); 1139*f6e214c7SGavin Maltby goto cleanup; 1140*f6e214c7SGavin Maltby } 1141*f6e214c7SGavin Maltby 1142*f6e214c7SGavin Maltby r = SCF_SUCCESS; 1143*f6e214c7SGavin Maltby cleanup: 1144*f6e214c7SGavin Maltby scf_values_destroy(&vals); 1145*f6e214c7SGavin Maltby switch (err) { 1146*f6e214c7SGavin Maltby case 0: 1147*f6e214c7SGavin Maltby break; 1148*f6e214c7SGavin Maltby case EINVAL: 1149*f6e214c7SGavin Maltby (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT); 1150*f6e214c7SGavin Maltby break; 1151*f6e214c7SGavin Maltby case ENOMEM: 1152*f6e214c7SGavin Maltby (void) scf_set_error(SCF_ERROR_NO_MEMORY); 1153*f6e214c7SGavin Maltby break; 1154*f6e214c7SGavin Maltby default: 1155*f6e214c7SGavin Maltby /* we should *never* get here */ 1156*f6e214c7SGavin Maltby abort(); 1157*f6e214c7SGavin Maltby } 1158*f6e214c7SGavin Maltby 1159*f6e214c7SGavin Maltby return (r); 1160*f6e214c7SGavin Maltby } 1161*f6e214c7SGavin Maltby 1162*f6e214c7SGavin Maltby /* 1163*f6e214c7SGavin Maltby * Parse property name "mechanism,parameter" into separate mechanism 1164*f6e214c7SGavin Maltby * and parameter. *mech must be freed by caller. *val points into 1165*f6e214c7SGavin Maltby * *mech and must not be freed. 1166*f6e214c7SGavin Maltby * 1167*f6e214c7SGavin Maltby * Returns SCF_SUCCESS or SCF_FAILED on 1168*f6e214c7SGavin Maltby * SCF_ERROR_NO_MEMORY 1169*f6e214c7SGavin Maltby * SCF_ERROR_NOT_FOUND 1170*f6e214c7SGavin Maltby */ 1171*f6e214c7SGavin Maltby static int 1172*f6e214c7SGavin Maltby get_mech_name(const char *name, char **mech, char **val) 1173*f6e214c7SGavin Maltby { 1174*f6e214c7SGavin Maltby char *p; 1175*f6e214c7SGavin Maltby char *m; 1176*f6e214c7SGavin Maltby 1177*f6e214c7SGavin Maltby if ((m = strdup(name)) == NULL) { 1178*f6e214c7SGavin Maltby (void) scf_set_error(SCF_ERROR_NO_MEMORY); 1179*f6e214c7SGavin Maltby return (SCF_FAILED); 1180*f6e214c7SGavin Maltby } 1181*f6e214c7SGavin Maltby if ((p = strchr(m, ',')) == NULL) { 1182*f6e214c7SGavin Maltby free(m); 1183*f6e214c7SGavin Maltby (void) scf_set_error(SCF_ERROR_NOT_FOUND); 1184*f6e214c7SGavin Maltby return (SCF_FAILED); 1185*f6e214c7SGavin Maltby } 1186*f6e214c7SGavin Maltby *p = '\0'; 1187*f6e214c7SGavin Maltby *val = p + 1; 1188*f6e214c7SGavin Maltby *mech = m; 1189*f6e214c7SGavin Maltby 1190*f6e214c7SGavin Maltby return (SCF_SUCCESS); 1191*f6e214c7SGavin Maltby } 1192*f6e214c7SGavin Maltby 1193*f6e214c7SGavin Maltby /* 1194*f6e214c7SGavin Maltby * Return the number of transitions in a transition set. 1195*f6e214c7SGavin Maltby * If the transition set is invalid, it returns zero. 1196*f6e214c7SGavin Maltby */ 1197*f6e214c7SGavin Maltby static uint_t 1198*f6e214c7SGavin Maltby num_of_transitions(int32_t t) 1199*f6e214c7SGavin Maltby { 1200*f6e214c7SGavin Maltby int i; 1201*f6e214c7SGavin Maltby int n = 0; 1202*f6e214c7SGavin Maltby 1203*f6e214c7SGavin Maltby if (SCF_TRANS_VALID(t)) { 1204*f6e214c7SGavin Maltby for (i = 0x1; i < SCF_STATE_ALL; i <<= 1) { 1205*f6e214c7SGavin Maltby if (i & t) 1206*f6e214c7SGavin Maltby ++n; 1207*f6e214c7SGavin Maltby if (SCF_TRANS_INITIAL_STATE(t) & i) 1208*f6e214c7SGavin Maltby ++n; 1209*f6e214c7SGavin Maltby } 1210*f6e214c7SGavin Maltby } 1211*f6e214c7SGavin Maltby 1212*f6e214c7SGavin Maltby return (n); 1213*f6e214c7SGavin Maltby } 1214*f6e214c7SGavin Maltby 1215*f6e214c7SGavin Maltby /* 1216*f6e214c7SGavin Maltby * Return the SCF_STATE_* macro value for the state in the FMA classes for 1217*f6e214c7SGavin Maltby * SMF state transitions. They are of type: 1218*f6e214c7SGavin Maltby * SCF_SVC_TRANSITION_CLASS.<state> 1219*f6e214c7SGavin Maltby * ireport.os.smf.state-transition.<state> 1220*f6e214c7SGavin Maltby */ 1221*f6e214c7SGavin Maltby static int32_t 1222*f6e214c7SGavin Maltby class_to_transition(const char *c) 1223*f6e214c7SGavin Maltby { 1224*f6e214c7SGavin Maltby const char *p; 1225*f6e214c7SGavin Maltby int r = 0; 1226*f6e214c7SGavin Maltby size_t n; 1227*f6e214c7SGavin Maltby 1228*f6e214c7SGavin Maltby if (!is_svc_stn(c)) { 1229*f6e214c7SGavin Maltby return (0); 1230*f6e214c7SGavin Maltby } 1231*f6e214c7SGavin Maltby 1232*f6e214c7SGavin Maltby /* 1233*f6e214c7SGavin Maltby * if we get here, c is SCF_SVC_TRANSITION_CLASS or longer 1234*f6e214c7SGavin Maltby */ 1235*f6e214c7SGavin Maltby p = c + strlen(SCF_SVC_TRANSITION_CLASS); 1236*f6e214c7SGavin Maltby if (*p == '.') 1237*f6e214c7SGavin Maltby ++p; 1238*f6e214c7SGavin Maltby else 1239*f6e214c7SGavin Maltby return (0); 1240*f6e214c7SGavin Maltby 1241*f6e214c7SGavin Maltby if ((n = base_class_len(p)) == 0) 1242*f6e214c7SGavin Maltby return (0); 1243*f6e214c7SGavin Maltby 1244*f6e214c7SGavin Maltby if ((r = state_from_string(p, n)) == -1) 1245*f6e214c7SGavin Maltby r = 0; 1246*f6e214c7SGavin Maltby 1247*f6e214c7SGavin Maltby return (r); 1248*f6e214c7SGavin Maltby } 1249*f6e214c7SGavin Maltby 1250*f6e214c7SGavin Maltby /* 1251*f6e214c7SGavin Maltby * return SCF_SUCCESS or SCF_FAILED on 1252*f6e214c7SGavin Maltby * SCF_ERROR_BACKEND_ACCESS 1253*f6e214c7SGavin Maltby * SCF_ERROR_BACKEND_READONLY 1254*f6e214c7SGavin Maltby * SCF_ERROR_CONNECTION_BROKEN 1255*f6e214c7SGavin Maltby * SCF_ERROR_DELETED 1256*f6e214c7SGavin Maltby * SCF_ERROR_INTERNAL 1257*f6e214c7SGavin Maltby * SCF_ERROR_INVALID_ARGUMENT 1258*f6e214c7SGavin Maltby * SCF_ERROR_NO_MEMORY 1259*f6e214c7SGavin Maltby * SCF_ERROR_NO_RESOURCES 1260*f6e214c7SGavin Maltby * SCF_ERROR_NOT_FOUND 1261*f6e214c7SGavin Maltby * SCF_ERROR_PERMISSION_DENIED 1262*f6e214c7SGavin Maltby */ 1263*f6e214c7SGavin Maltby int 1264*f6e214c7SGavin Maltby smf_notify_set_params(const char *class, nvlist_t *attr) 1265*f6e214c7SGavin Maltby { 1266*f6e214c7SGavin Maltby uint32_t ver; 1267*f6e214c7SGavin Maltby int32_t tset; 1268*f6e214c7SGavin Maltby scf_handle_t *h = _scf_handle_create_and_bind(SCF_VERSION); 1269*f6e214c7SGavin Maltby scf_error_t scf_e = scf_error(); 1270*f6e214c7SGavin Maltby scf_service_t *s = scf_service_create(h); 1271*f6e214c7SGavin Maltby scf_instance_t *i = scf_instance_create(h); 1272*f6e214c7SGavin Maltby scf_propertygroup_t *pg = scf_pg_create(h); 1273*f6e214c7SGavin Maltby nvlist_t *params = NULL; 1274*f6e214c7SGavin Maltby char *fmri = (char *)SCF_NOTIFY_PARAMS_INST; 1275*f6e214c7SGavin Maltby char *pgname = NULL; 1276*f6e214c7SGavin Maltby int r = SCF_FAILED; 1277*f6e214c7SGavin Maltby boolean_t is_stn; 1278*f6e214c7SGavin Maltby int j; 1279*f6e214c7SGavin Maltby 1280*f6e214c7SGavin Maltby assert(class != NULL); 1281*f6e214c7SGavin Maltby if (h == NULL) { 1282*f6e214c7SGavin Maltby /* 1283*f6e214c7SGavin Maltby * use saved error if _scf_handle_create_and_bind() fails 1284*f6e214c7SGavin Maltby */ 1285*f6e214c7SGavin Maltby (void) scf_set_error(scf_e); 1286*f6e214c7SGavin Maltby goto cleanup; 1287*f6e214c7SGavin Maltby } 1288*f6e214c7SGavin Maltby if (i == NULL || s == NULL || pg == NULL) 1289*f6e214c7SGavin Maltby goto cleanup; 1290*f6e214c7SGavin Maltby 1291*f6e214c7SGavin Maltby /* check version */ 1292*f6e214c7SGavin Maltby if (nvlist_lookup_uint32(attr, SCF_NOTIFY_NAME_VERSION, &ver) != 0 || 1293*f6e214c7SGavin Maltby ver != SCF_NOTIFY_PARAMS_VERSION) { 1294*f6e214c7SGavin Maltby (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT); 1295*f6e214c7SGavin Maltby goto cleanup; 1296*f6e214c7SGavin Maltby } 1297*f6e214c7SGavin Maltby 1298*f6e214c7SGavin Maltby if (nvlist_lookup_nvlist(attr, SCF_NOTIFY_PARAMS, ¶ms) != 0) { 1299*f6e214c7SGavin Maltby (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT); 1300*f6e214c7SGavin Maltby goto cleanup; 1301*f6e214c7SGavin Maltby } 1302*f6e214c7SGavin Maltby 1303*f6e214c7SGavin Maltby is_stn = is_svc_stn(class); 1304*f6e214c7SGavin Maltby /* special case SMF state transition notification */ 1305*f6e214c7SGavin Maltby if (is_stn && 1306*f6e214c7SGavin Maltby (nvlist_lookup_string(attr, SCF_NOTIFY_NAME_FMRI, &fmri) != 0 || 1307*f6e214c7SGavin Maltby nvlist_lookup_int32(attr, SCF_NOTIFY_NAME_TSET, &tset) != 0 || 1308*f6e214c7SGavin Maltby !SCF_TRANS_VALID(tset))) { 1309*f6e214c7SGavin Maltby (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT); 1310*f6e214c7SGavin Maltby goto cleanup; 1311*f6e214c7SGavin Maltby } 1312*f6e214c7SGavin Maltby if (decode_fmri(fmri, h, &s, &i) != SCF_SUCCESS) 1313*f6e214c7SGavin Maltby if (scf_error() == SCF_ERROR_CONSTRAINT_VIOLATED) { 1314*f6e214c7SGavin Maltby (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT); 1315*f6e214c7SGavin Maltby } else if (check_scf_error(scf_error(), errs_1)) { 1316*f6e214c7SGavin Maltby goto cleanup; 1317*f6e214c7SGavin Maltby } 1318*f6e214c7SGavin Maltby 1319*f6e214c7SGavin Maltby if (is_stn) { 1320*f6e214c7SGavin Maltby tset |= class_to_transition(class); 1321*f6e214c7SGavin Maltby 1322*f6e214c7SGavin Maltby if (!SCF_TRANS_VALID(tset)) { 1323*f6e214c7SGavin Maltby (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT); 1324*f6e214c7SGavin Maltby goto cleanup; 1325*f6e214c7SGavin Maltby } 1326*f6e214c7SGavin Maltby 1327*f6e214c7SGavin Maltby for (j = 0; st_pgnames[j].st_pgname != NULL; ++j) { 1328*f6e214c7SGavin Maltby /* if this transition is not in the tset, continue */ 1329*f6e214c7SGavin Maltby if (!(tset & st_pgnames[j].st_state)) 1330*f6e214c7SGavin Maltby continue; 1331*f6e214c7SGavin Maltby 1332*f6e214c7SGavin Maltby if (get_or_add_pg(s, i, st_pgnames[j].st_pgname, 1333*f6e214c7SGavin Maltby SCF_NOTIFY_PARAMS_PG_TYPE, 0, pg) != 0 && 1334*f6e214c7SGavin Maltby check_scf_error(scf_error(), errs_2)) 1335*f6e214c7SGavin Maltby goto cleanup; 1336*f6e214c7SGavin Maltby 1337*f6e214c7SGavin Maltby if (notify_set_params(pg, params) != 0) 1338*f6e214c7SGavin Maltby goto cleanup; 1339*f6e214c7SGavin Maltby } 1340*f6e214c7SGavin Maltby if (s == NULL) { 1341*f6e214c7SGavin Maltby /* We only need to refresh the instance */ 1342*f6e214c7SGavin Maltby if (_smf_refresh_instance_i(i) != 0 && 1343*f6e214c7SGavin Maltby check_scf_error(scf_error(), errs_1)) 1344*f6e214c7SGavin Maltby goto cleanup; 1345*f6e214c7SGavin Maltby } else { 1346*f6e214c7SGavin Maltby /* We have to refresh all instances in the service */ 1347*f6e214c7SGavin Maltby if (_smf_refresh_all_instances(s) != 0 && 1348*f6e214c7SGavin Maltby check_scf_error(scf_error(), errs_1)) 1349*f6e214c7SGavin Maltby goto cleanup; 1350*f6e214c7SGavin Maltby } 1351*f6e214c7SGavin Maltby } else { 1352*f6e214c7SGavin Maltby if ((pgname = class_to_pgname(class)) == NULL) 1353*f6e214c7SGavin Maltby goto cleanup; 1354*f6e214c7SGavin Maltby if (get_or_add_pg(s, i, pgname, SCF_GROUP_APPLICATION, 0, pg) != 1355*f6e214c7SGavin Maltby 0) { 1356*f6e214c7SGavin Maltby if (check_scf_error(scf_error(), errs_2)) { 1357*f6e214c7SGavin Maltby goto cleanup; 1358*f6e214c7SGavin Maltby } 1359*f6e214c7SGavin Maltby } 1360*f6e214c7SGavin Maltby if (notify_set_params(pg, params) != 0) { 1361*f6e214c7SGavin Maltby goto cleanup; 1362*f6e214c7SGavin Maltby } 1363*f6e214c7SGavin Maltby if (_smf_refresh_instance_i(i) != 0 && 1364*f6e214c7SGavin Maltby check_scf_error(scf_error(), errs_1)) 1365*f6e214c7SGavin Maltby goto cleanup; 1366*f6e214c7SGavin Maltby } 1367*f6e214c7SGavin Maltby 1368*f6e214c7SGavin Maltby r = SCF_SUCCESS; 1369*f6e214c7SGavin Maltby cleanup: 1370*f6e214c7SGavin Maltby scf_instance_destroy(i); 1371*f6e214c7SGavin Maltby scf_service_destroy(s); 1372*f6e214c7SGavin Maltby scf_pg_destroy(pg); 1373*f6e214c7SGavin Maltby scf_handle_destroy(h); 1374*f6e214c7SGavin Maltby free(pgname); 1375*f6e214c7SGavin Maltby 1376*f6e214c7SGavin Maltby return (r); 1377*f6e214c7SGavin Maltby } 1378*f6e214c7SGavin Maltby 1379*f6e214c7SGavin Maltby /* 1380*f6e214c7SGavin Maltby * returns SCF_SUCCESS or SCF_FAILED on 1381*f6e214c7SGavin Maltby * SCF_ERROR_CONNECTION_BROKEN 1382*f6e214c7SGavin Maltby * SCF_ERROR_DELETED 1383*f6e214c7SGavin Maltby * SCF_ERROR_HANDLE_DESTROYED 1384*f6e214c7SGavin Maltby * SCF_ERROR_HANDLE_MISMATCH 1385*f6e214c7SGavin Maltby * SCF_ERROR_INVALID_ARGUMENT 1386*f6e214c7SGavin Maltby * SCF_ERROR_NO_MEMORY 1387*f6e214c7SGavin Maltby * SCF_ERROR_NO_RESOURCES 1388*f6e214c7SGavin Maltby * SCF_ERROR_NOT_BOUND 1389*f6e214c7SGavin Maltby * SCF_ERROR_NOT_FOUND 1390*f6e214c7SGavin Maltby * SCF_ERROR_NOT_SET 1391*f6e214c7SGavin Maltby * SCF_ERROR_PERMISSION_DENIED 1392*f6e214c7SGavin Maltby */ 1393*f6e214c7SGavin Maltby int 1394*f6e214c7SGavin Maltby _scf_notify_get_params(scf_propertygroup_t *pg, nvlist_t *params) 1395*f6e214c7SGavin Maltby { 1396*f6e214c7SGavin Maltby scf_handle_t *h = scf_pg_handle(pg); 1397*f6e214c7SGavin Maltby scf_error_t scf_e = scf_error(); 1398*f6e214c7SGavin Maltby scf_property_t *p = scf_property_create(h); 1399*f6e214c7SGavin Maltby scf_iter_t *it = scf_iter_create(h); 1400*f6e214c7SGavin Maltby int sz = scf_limit(SCF_LIMIT_MAX_NAME_LENGTH) + 1; 1401*f6e214c7SGavin Maltby char *name = malloc(sz); 1402*f6e214c7SGavin Maltby int r = SCF_FAILED; 1403*f6e214c7SGavin Maltby int err; 1404*f6e214c7SGavin Maltby 1405*f6e214c7SGavin Maltby if (h == NULL) { 1406*f6e214c7SGavin Maltby /* 1407*f6e214c7SGavin Maltby * Use the error stored in scf_e 1408*f6e214c7SGavin Maltby */ 1409*f6e214c7SGavin Maltby (void) scf_set_error(scf_e); 1410*f6e214c7SGavin Maltby goto cleanup; 1411*f6e214c7SGavin Maltby } 1412*f6e214c7SGavin Maltby if (it == NULL || p == NULL) 1413*f6e214c7SGavin Maltby goto cleanup; 1414*f6e214c7SGavin Maltby 1415*f6e214c7SGavin Maltby if (name == NULL) { 1416*f6e214c7SGavin Maltby (void) scf_set_error(SCF_ERROR_NO_MEMORY); 1417*f6e214c7SGavin Maltby goto cleanup; 1418*f6e214c7SGavin Maltby } 1419*f6e214c7SGavin Maltby 1420*f6e214c7SGavin Maltby if (scf_iter_pg_properties(it, pg) != SCF_SUCCESS) { 1421*f6e214c7SGavin Maltby if (check_scf_error(scf_error(), errs_1)) { 1422*f6e214c7SGavin Maltby goto cleanup; 1423*f6e214c7SGavin Maltby } 1424*f6e214c7SGavin Maltby } 1425*f6e214c7SGavin Maltby 1426*f6e214c7SGavin Maltby while ((err = scf_iter_next_property(it, p)) == 1) { 1427*f6e214c7SGavin Maltby nvlist_t *nvl; 1428*f6e214c7SGavin Maltby int nvl_new = 0; 1429*f6e214c7SGavin Maltby char *mech; 1430*f6e214c7SGavin Maltby char *val; 1431*f6e214c7SGavin Maltby 1432*f6e214c7SGavin Maltby if (scf_property_get_name(p, name, sz) == SCF_FAILED) { 1433*f6e214c7SGavin Maltby if (check_scf_error(scf_error(), errs_1)) { 1434*f6e214c7SGavin Maltby goto cleanup; 1435*f6e214c7SGavin Maltby } 1436*f6e214c7SGavin Maltby } 1437*f6e214c7SGavin Maltby 1438*f6e214c7SGavin Maltby if (get_mech_name(name, &mech, &val) != SCF_SUCCESS) { 1439*f6e214c7SGavin Maltby if (scf_error() == SCF_ERROR_NOT_FOUND) 1440*f6e214c7SGavin Maltby continue; 1441*f6e214c7SGavin Maltby goto cleanup; 1442*f6e214c7SGavin Maltby } 1443*f6e214c7SGavin Maltby 1444*f6e214c7SGavin Maltby if (nvlist_lookup_nvlist(params, mech, &nvl) != 0) { 1445*f6e214c7SGavin Maltby if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0) { 1446*f6e214c7SGavin Maltby (void) scf_set_error(SCF_ERROR_NO_MEMORY); 1447*f6e214c7SGavin Maltby free(mech); 1448*f6e214c7SGavin Maltby goto cleanup; 1449*f6e214c7SGavin Maltby } 1450*f6e214c7SGavin Maltby nvl_new = 1; 1451*f6e214c7SGavin Maltby } 1452*f6e214c7SGavin Maltby 1453*f6e214c7SGavin Maltby if (add_prop_to_nvlist(p, val, nvl, 1) != SCF_SUCCESS) { 1454*f6e214c7SGavin Maltby if (check_scf_error(scf_error(), errs_2)) { 1455*f6e214c7SGavin Maltby free(mech); 1456*f6e214c7SGavin Maltby nvlist_free(nvl); 1457*f6e214c7SGavin Maltby goto cleanup; 1458*f6e214c7SGavin Maltby } 1459*f6e214c7SGavin Maltby } 1460*f6e214c7SGavin Maltby if (nvl_new) { 1461*f6e214c7SGavin Maltby if (nvlist_add_nvlist(params, mech, nvl) != 0) { 1462*f6e214c7SGavin Maltby (void) scf_set_error(SCF_ERROR_NO_MEMORY); 1463*f6e214c7SGavin Maltby free(mech); 1464*f6e214c7SGavin Maltby nvlist_free(nvl); 1465*f6e214c7SGavin Maltby goto cleanup; 1466*f6e214c7SGavin Maltby } 1467*f6e214c7SGavin Maltby nvlist_free(nvl); 1468*f6e214c7SGavin Maltby } 1469*f6e214c7SGavin Maltby 1470*f6e214c7SGavin Maltby free(mech); 1471*f6e214c7SGavin Maltby } 1472*f6e214c7SGavin Maltby 1473*f6e214c7SGavin Maltby if (err == 0) { 1474*f6e214c7SGavin Maltby r = SCF_SUCCESS; 1475*f6e214c7SGavin Maltby } else if (check_scf_error(scf_error(), errs_2)) { 1476*f6e214c7SGavin Maltby goto cleanup; 1477*f6e214c7SGavin Maltby } 1478*f6e214c7SGavin Maltby 1479*f6e214c7SGavin Maltby cleanup: 1480*f6e214c7SGavin Maltby scf_iter_destroy(it); 1481*f6e214c7SGavin Maltby scf_property_destroy(p); 1482*f6e214c7SGavin Maltby free(name); 1483*f6e214c7SGavin Maltby 1484*f6e214c7SGavin Maltby return (r); 1485*f6e214c7SGavin Maltby } 1486*f6e214c7SGavin Maltby 1487*f6e214c7SGavin Maltby /* 1488*f6e214c7SGavin Maltby * Look up pg containing an SMF state transition parameters. If it cannot find 1489*f6e214c7SGavin Maltby * the pg in the composed view of the instance, it will look in the global 1490*f6e214c7SGavin Maltby * instance for the system wide parameters. 1491*f6e214c7SGavin Maltby * Instance, service and global instance have to be passed by caller. 1492*f6e214c7SGavin Maltby * 1493*f6e214c7SGavin Maltby * returns SCF_SUCCESS or SCF_FAILED on 1494*f6e214c7SGavin Maltby * SCF_ERROR_BACKEND_ACCESS 1495*f6e214c7SGavin Maltby * SCF_ERROR_CONNECTION_BROKEN 1496*f6e214c7SGavin Maltby * SCF_ERROR_DELETED 1497*f6e214c7SGavin Maltby * SCF_ERROR_HANDLE_DESTROYED 1498*f6e214c7SGavin Maltby * SCF_ERROR_HANDLE_MISMATCH 1499*f6e214c7SGavin Maltby * SCF_ERROR_INTERNAL 1500*f6e214c7SGavin Maltby * SCF_ERROR_INVALID_ARGUMENT 1501*f6e214c7SGavin Maltby * SCF_ERROR_NO_MEMORY 1502*f6e214c7SGavin Maltby * SCF_ERROR_NO_RESOURCES 1503*f6e214c7SGavin Maltby * SCF_ERROR_NOT_BOUND 1504*f6e214c7SGavin Maltby * SCF_ERROR_NOT_FOUND 1505*f6e214c7SGavin Maltby * SCF_ERROR_NOT_SET 1506*f6e214c7SGavin Maltby */ 1507*f6e214c7SGavin Maltby static int 1508*f6e214c7SGavin Maltby get_stn_pg(scf_service_t *s, scf_instance_t *i, scf_instance_t *g, 1509*f6e214c7SGavin Maltby const char *pgname, scf_propertygroup_t *pg) 1510*f6e214c7SGavin Maltby { 1511*f6e214c7SGavin Maltby if (get_pg(s, i, pgname, pg, 1) == 0 || 1512*f6e214c7SGavin Maltby scf_error() == SCF_ERROR_NOT_FOUND && 1513*f6e214c7SGavin Maltby get_pg(NULL, g, pgname, pg, 0) == 0) 1514*f6e214c7SGavin Maltby return (SCF_SUCCESS); 1515*f6e214c7SGavin Maltby 1516*f6e214c7SGavin Maltby return (SCF_FAILED); 1517*f6e214c7SGavin Maltby } 1518*f6e214c7SGavin Maltby 1519*f6e214c7SGavin Maltby /* 1520*f6e214c7SGavin Maltby * Populates nvlist_t params with the source fmri for the pg 1521*f6e214c7SGavin Maltby * 1522*f6e214c7SGavin Maltby * return SCF_SUCCESS or SCF_FAILED on 1523*f6e214c7SGavin Maltby * SCF_ERROR_DELETED 1524*f6e214c7SGavin Maltby * SCF_ERROR_CONNECTION_BROKEN 1525*f6e214c7SGavin Maltby * SCF_ERROR_NO_MEMORY 1526*f6e214c7SGavin Maltby */ 1527*f6e214c7SGavin Maltby static int 1528*f6e214c7SGavin Maltby get_pg_source(scf_propertygroup_t *pg, nvlist_t *params) 1529*f6e214c7SGavin Maltby { 1530*f6e214c7SGavin Maltby size_t sz = scf_limit(SCF_LIMIT_MAX_FMRI_LENGTH) + 1; 1531*f6e214c7SGavin Maltby char *fmri = malloc(sz); 1532*f6e214c7SGavin Maltby char *p; 1533*f6e214c7SGavin Maltby int r = SCF_FAILED; 1534*f6e214c7SGavin Maltby 1535*f6e214c7SGavin Maltby if (fmri == NULL) { 1536*f6e214c7SGavin Maltby (void) scf_set_error(SCF_ERROR_NO_MEMORY); 1537*f6e214c7SGavin Maltby goto out; 1538*f6e214c7SGavin Maltby } 1539*f6e214c7SGavin Maltby 1540*f6e214c7SGavin Maltby if (scf_pg_to_fmri(pg, fmri, sz) == -1) { 1541*f6e214c7SGavin Maltby if (check_scf_error(scf_error(), errs_1)) { 1542*f6e214c7SGavin Maltby goto out; 1543*f6e214c7SGavin Maltby } 1544*f6e214c7SGavin Maltby } 1545*f6e214c7SGavin Maltby 1546*f6e214c7SGavin Maltby /* get rid of the properties part of the pg source */ 1547*f6e214c7SGavin Maltby if ((p = strrchr(fmri, ':')) != NULL && p > fmri) 1548*f6e214c7SGavin Maltby *(p - 1) = '\0'; 1549*f6e214c7SGavin Maltby if (nvlist_add_string(params, SCF_NOTIFY_PARAMS_SOURCE_NAME, fmri) != 1550*f6e214c7SGavin Maltby 0) { 1551*f6e214c7SGavin Maltby (void) scf_set_error(SCF_ERROR_NO_MEMORY); 1552*f6e214c7SGavin Maltby goto out; 1553*f6e214c7SGavin Maltby } 1554*f6e214c7SGavin Maltby 1555*f6e214c7SGavin Maltby r = SCF_SUCCESS; 1556*f6e214c7SGavin Maltby out: 1557*f6e214c7SGavin Maltby free(fmri); 1558*f6e214c7SGavin Maltby return (r); 1559*f6e214c7SGavin Maltby } 1560*f6e214c7SGavin Maltby 1561*f6e214c7SGavin Maltby /* 1562*f6e214c7SGavin Maltby * Specialized function to get SMF state transition notification parameters 1563*f6e214c7SGavin Maltby * 1564*f6e214c7SGavin Maltby * return SCF_SUCCESS or SCF_FAILED on 1565*f6e214c7SGavin Maltby * SCF_ERROR_BACKEND_ACCESS 1566*f6e214c7SGavin Maltby * SCF_ERROR_CONNECTION_BROKEN 1567*f6e214c7SGavin Maltby * SCF_ERROR_DELETED 1568*f6e214c7SGavin Maltby * SCF_ERROR_INTERNAL 1569*f6e214c7SGavin Maltby * SCF_ERROR_INVALID_ARGUMENT 1570*f6e214c7SGavin Maltby * SCF_ERROR_NO_MEMORY 1571*f6e214c7SGavin Maltby * SCF_ERROR_NO_RESOURCES 1572*f6e214c7SGavin Maltby * SCF_ERROR_NOT_FOUND 1573*f6e214c7SGavin Maltby * SCF_ERROR_PERMISSION_DENIED 1574*f6e214c7SGavin Maltby */ 1575*f6e214c7SGavin Maltby int 1576*f6e214c7SGavin Maltby _scf_get_svc_notify_params(const char *fmri, nvlist_t *nvl, int32_t tset, 1577*f6e214c7SGavin Maltby int getsource, int getglobal) 1578*f6e214c7SGavin Maltby { 1579*f6e214c7SGavin Maltby scf_handle_t *h = _scf_handle_create_and_bind(SCF_VERSION); 1580*f6e214c7SGavin Maltby scf_error_t scf_e = scf_error(); 1581*f6e214c7SGavin Maltby scf_service_t *s = scf_service_create(h); 1582*f6e214c7SGavin Maltby scf_instance_t *i = scf_instance_create(h); 1583*f6e214c7SGavin Maltby scf_instance_t *g = scf_instance_create(h); 1584*f6e214c7SGavin Maltby scf_propertygroup_t *pg = scf_pg_create(h); 1585*f6e214c7SGavin Maltby int r = SCF_FAILED; 1586*f6e214c7SGavin Maltby nvlist_t **params = NULL; 1587*f6e214c7SGavin Maltby uint_t c, nvl_num = 0; 1588*f6e214c7SGavin Maltby int not_found = 1; 1589*f6e214c7SGavin Maltby int j; 1590*f6e214c7SGavin Maltby const char *pgname; 1591*f6e214c7SGavin Maltby 1592*f6e214c7SGavin Maltby assert(fmri != NULL && nvl != NULL); 1593*f6e214c7SGavin Maltby if (h == NULL) { 1594*f6e214c7SGavin Maltby /* 1595*f6e214c7SGavin Maltby * use saved error if _scf_handle_create_and_bind() fails 1596*f6e214c7SGavin Maltby */ 1597*f6e214c7SGavin Maltby (void) scf_set_error(scf_e); 1598*f6e214c7SGavin Maltby goto cleanup; 1599*f6e214c7SGavin Maltby } 1600*f6e214c7SGavin Maltby if (s == NULL || i == NULL || g == NULL || pg == NULL) 1601*f6e214c7SGavin Maltby goto cleanup; 1602*f6e214c7SGavin Maltby 1603*f6e214c7SGavin Maltby if (decode_fmri(fmri, h, &s, &i) != SCF_SUCCESS || 1604*f6e214c7SGavin Maltby scf_handle_decode_fmri(h, SCF_INSTANCE_GLOBAL, NULL, NULL, g, NULL, 1605*f6e214c7SGavin Maltby NULL, SCF_DECODE_FMRI_EXACT) != 0) { 1606*f6e214c7SGavin Maltby if (scf_error() == SCF_ERROR_CONSTRAINT_VIOLATED) { 1607*f6e214c7SGavin Maltby (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT); 1608*f6e214c7SGavin Maltby } else if (check_scf_error(scf_error(), errs_1)) { 1609*f6e214c7SGavin Maltby goto cleanup; 1610*f6e214c7SGavin Maltby } 1611*f6e214c7SGavin Maltby } 1612*f6e214c7SGavin Maltby 1613*f6e214c7SGavin Maltby nvl_num = num_of_transitions(tset); 1614*f6e214c7SGavin Maltby if ((params = calloc(nvl_num, sizeof (nvlist_t *))) == NULL) { 1615*f6e214c7SGavin Maltby (void) scf_set_error(SCF_ERROR_NO_MEMORY); 1616*f6e214c7SGavin Maltby goto cleanup; 1617*f6e214c7SGavin Maltby } 1618*f6e214c7SGavin Maltby 1619*f6e214c7SGavin Maltby for (c = 0; c < nvl_num; ++c) 1620*f6e214c7SGavin Maltby if (nvlist_alloc(params + c, NV_UNIQUE_NAME, 0) != 0) { 1621*f6e214c7SGavin Maltby (void) scf_set_error(SCF_ERROR_NO_MEMORY); 1622*f6e214c7SGavin Maltby goto cleanup; 1623*f6e214c7SGavin Maltby } 1624*f6e214c7SGavin Maltby 1625*f6e214c7SGavin Maltby for (c = 0, j = 0; st_pgnames[j].st_pgname != NULL; ++j) { 1626*f6e214c7SGavin Maltby /* if this transition is not in the tset, continue */ 1627*f6e214c7SGavin Maltby if (!(tset & st_pgnames[j].st_state)) 1628*f6e214c7SGavin Maltby continue; 1629*f6e214c7SGavin Maltby 1630*f6e214c7SGavin Maltby assert(c < nvl_num); 1631*f6e214c7SGavin Maltby pgname = st_pgnames[j].st_pgname; 1632*f6e214c7SGavin Maltby 1633*f6e214c7SGavin Maltby if (nvlist_add_int32(params[c], SCF_NOTIFY_NAME_TSET, 1634*f6e214c7SGavin Maltby st_pgnames[j].st_state) != 0) { 1635*f6e214c7SGavin Maltby (void) scf_set_error(SCF_ERROR_NO_MEMORY); 1636*f6e214c7SGavin Maltby goto cleanup; 1637*f6e214c7SGavin Maltby } 1638*f6e214c7SGavin Maltby if ((getglobal ? get_stn_pg(s, i, g, pgname, pg) : 1639*f6e214c7SGavin Maltby get_pg(s, i, pgname, pg, 1)) == SCF_SUCCESS) { 1640*f6e214c7SGavin Maltby not_found = 0; 1641*f6e214c7SGavin Maltby if (_scf_notify_get_params(pg, params[c]) != 1642*f6e214c7SGavin Maltby SCF_SUCCESS) 1643*f6e214c7SGavin Maltby goto cleanup; 1644*f6e214c7SGavin Maltby if (getsource && get_pg_source(pg, params[c]) != 1645*f6e214c7SGavin Maltby SCF_SUCCESS) 1646*f6e214c7SGavin Maltby goto cleanup; 1647*f6e214c7SGavin Maltby } else if (scf_error() == SCF_ERROR_NOT_FOUND || 1648*f6e214c7SGavin Maltby scf_error() == SCF_ERROR_DELETED) { 1649*f6e214c7SGavin Maltby /* keep driving */ 1650*f6e214c7SGavin Maltby /*EMPTY*/ 1651*f6e214c7SGavin Maltby } else if (check_scf_error(scf_error(), errs_1)) { 1652*f6e214c7SGavin Maltby goto cleanup; 1653*f6e214c7SGavin Maltby } 1654*f6e214c7SGavin Maltby ++c; 1655*f6e214c7SGavin Maltby } 1656*f6e214c7SGavin Maltby 1657*f6e214c7SGavin Maltby if (not_found) { 1658*f6e214c7SGavin Maltby (void) scf_set_error(SCF_ERROR_NOT_FOUND); 1659*f6e214c7SGavin Maltby goto cleanup; 1660*f6e214c7SGavin Maltby } 1661*f6e214c7SGavin Maltby 1662*f6e214c7SGavin Maltby assert(c == nvl_num); 1663*f6e214c7SGavin Maltby 1664*f6e214c7SGavin Maltby if (nvlist_add_nvlist_array(nvl, SCF_NOTIFY_PARAMS, params, nvl_num) != 1665*f6e214c7SGavin Maltby 0 || nvlist_add_uint32(nvl, SCF_NOTIFY_NAME_VERSION, 1666*f6e214c7SGavin Maltby SCF_NOTIFY_PARAMS_VERSION) != 0) { 1667*f6e214c7SGavin Maltby (void) scf_set_error(SCF_ERROR_NO_MEMORY); 1668*f6e214c7SGavin Maltby goto cleanup; 1669*f6e214c7SGavin Maltby } 1670*f6e214c7SGavin Maltby 1671*f6e214c7SGavin Maltby r = SCF_SUCCESS; 1672*f6e214c7SGavin Maltby 1673*f6e214c7SGavin Maltby cleanup: 1674*f6e214c7SGavin Maltby scf_pg_destroy(pg); 1675*f6e214c7SGavin Maltby scf_instance_destroy(i); 1676*f6e214c7SGavin Maltby scf_instance_destroy(g); 1677*f6e214c7SGavin Maltby scf_service_destroy(s); 1678*f6e214c7SGavin Maltby scf_handle_destroy(h); 1679*f6e214c7SGavin Maltby if (params != NULL) 1680*f6e214c7SGavin Maltby for (c = 0; c < nvl_num; ++c) 1681*f6e214c7SGavin Maltby nvlist_free(params[c]); 1682*f6e214c7SGavin Maltby free(params); 1683*f6e214c7SGavin Maltby 1684*f6e214c7SGavin Maltby return (r); 1685*f6e214c7SGavin Maltby } 1686*f6e214c7SGavin Maltby 1687*f6e214c7SGavin Maltby /* 1688*f6e214c7SGavin Maltby * Specialized function to get fma notification parameters 1689*f6e214c7SGavin Maltby * 1690*f6e214c7SGavin Maltby * return SCF_SUCCESS or SCF_FAILED on 1691*f6e214c7SGavin Maltby * SCF_ERROR_BACKEND_ACCESS 1692*f6e214c7SGavin Maltby * SCF_ERROR_CONNECTION_BROKEN 1693*f6e214c7SGavin Maltby * SCF_ERROR_DELETED 1694*f6e214c7SGavin Maltby * SCF_ERROR_INTERNAL 1695*f6e214c7SGavin Maltby * SCF_ERROR_INVALID_ARGUMENT 1696*f6e214c7SGavin Maltby * SCF_ERROR_NO_MEMORY 1697*f6e214c7SGavin Maltby * SCF_ERROR_NO_RESOURCES 1698*f6e214c7SGavin Maltby * SCF_ERROR_NOT_FOUND 1699*f6e214c7SGavin Maltby * SCF_ERROR_PERMISSION_DENIED 1700*f6e214c7SGavin Maltby */ 1701*f6e214c7SGavin Maltby int 1702*f6e214c7SGavin Maltby _scf_get_fma_notify_params(const char *class, nvlist_t *nvl, int getsource) 1703*f6e214c7SGavin Maltby { 1704*f6e214c7SGavin Maltby scf_handle_t *h = _scf_handle_create_and_bind(SCF_VERSION); 1705*f6e214c7SGavin Maltby scf_error_t scf_e = scf_error(); 1706*f6e214c7SGavin Maltby scf_instance_t *i = scf_instance_create(h); 1707*f6e214c7SGavin Maltby scf_propertygroup_t *pg = scf_pg_create(h); 1708*f6e214c7SGavin Maltby int r = SCF_FAILED; 1709*f6e214c7SGavin Maltby nvlist_t *params = NULL; 1710*f6e214c7SGavin Maltby char *pgname = NULL; 1711*f6e214c7SGavin Maltby 1712*f6e214c7SGavin Maltby if (h == NULL) { 1713*f6e214c7SGavin Maltby /* 1714*f6e214c7SGavin Maltby * use saved error if _scf_handle_create_and_bind() fails 1715*f6e214c7SGavin Maltby */ 1716*f6e214c7SGavin Maltby (void) scf_set_error(scf_e); 1717*f6e214c7SGavin Maltby goto cleanup; 1718*f6e214c7SGavin Maltby } 1719*f6e214c7SGavin Maltby if (i == NULL || pg == NULL) 1720*f6e214c7SGavin Maltby goto cleanup; 1721*f6e214c7SGavin Maltby 1722*f6e214c7SGavin Maltby if (scf_handle_decode_fmri(h, SCF_NOTIFY_PARAMS_INST, NULL, NULL, i, 1723*f6e214c7SGavin Maltby NULL, NULL, SCF_DECODE_FMRI_EXACT) != SCF_SUCCESS) { 1724*f6e214c7SGavin Maltby if (check_scf_error(scf_error(), errs_1)) { 1725*f6e214c7SGavin Maltby goto cleanup; 1726*f6e214c7SGavin Maltby } 1727*f6e214c7SGavin Maltby } 1728*f6e214c7SGavin Maltby 1729*f6e214c7SGavin Maltby if ((pgname = class_to_pgname(class)) == NULL) 1730*f6e214c7SGavin Maltby goto cleanup; 1731*f6e214c7SGavin Maltby 1732*f6e214c7SGavin Maltby while (get_pg(NULL, i, pgname, pg, 0) != 0) { 1733*f6e214c7SGavin Maltby if (scf_error() == SCF_ERROR_NOT_FOUND) { 1734*f6e214c7SGavin Maltby char *p = strrchr(pgname, '.'); 1735*f6e214c7SGavin Maltby 1736*f6e214c7SGavin Maltby if (p != NULL) { 1737*f6e214c7SGavin Maltby *p = ','; 1738*f6e214c7SGavin Maltby /* 1739*f6e214c7SGavin Maltby * since the resulting string is shorter, 1740*f6e214c7SGavin Maltby * there is no risk of buffer overflow 1741*f6e214c7SGavin Maltby */ 1742*f6e214c7SGavin Maltby (void) strcpy(p + 1, SCF_NOTIFY_PG_POSTFIX); 1743*f6e214c7SGavin Maltby continue; 1744*f6e214c7SGavin Maltby } 1745*f6e214c7SGavin Maltby } 1746*f6e214c7SGavin Maltby 1747*f6e214c7SGavin Maltby if (check_scf_error(scf_error(), errs_1)) { 1748*f6e214c7SGavin Maltby goto cleanup; 1749*f6e214c7SGavin Maltby } 1750*f6e214c7SGavin Maltby } 1751*f6e214c7SGavin Maltby 1752*f6e214c7SGavin Maltby if (nvlist_alloc(¶ms, NV_UNIQUE_NAME, 0) != 0) { 1753*f6e214c7SGavin Maltby (void) scf_set_error(SCF_ERROR_NO_MEMORY); 1754*f6e214c7SGavin Maltby goto cleanup; 1755*f6e214c7SGavin Maltby } 1756*f6e214c7SGavin Maltby 1757*f6e214c7SGavin Maltby if (_scf_notify_get_params(pg, params) != SCF_SUCCESS) 1758*f6e214c7SGavin Maltby goto cleanup; 1759*f6e214c7SGavin Maltby 1760*f6e214c7SGavin Maltby if (getsource && get_pg_source(pg, params) != SCF_SUCCESS) 1761*f6e214c7SGavin Maltby goto cleanup; 1762*f6e214c7SGavin Maltby 1763*f6e214c7SGavin Maltby if (nvlist_add_nvlist_array(nvl, SCF_NOTIFY_PARAMS, ¶ms, 1) != 0 || 1764*f6e214c7SGavin Maltby nvlist_add_uint32(nvl, SCF_NOTIFY_NAME_VERSION, 1765*f6e214c7SGavin Maltby SCF_NOTIFY_PARAMS_VERSION) != 0) { 1766*f6e214c7SGavin Maltby (void) scf_set_error(SCF_ERROR_NO_MEMORY); 1767*f6e214c7SGavin Maltby goto cleanup; 1768*f6e214c7SGavin Maltby } 1769*f6e214c7SGavin Maltby 1770*f6e214c7SGavin Maltby r = SCF_SUCCESS; 1771*f6e214c7SGavin Maltby 1772*f6e214c7SGavin Maltby cleanup: 1773*f6e214c7SGavin Maltby nvlist_free(params); 1774*f6e214c7SGavin Maltby scf_pg_destroy(pg); 1775*f6e214c7SGavin Maltby scf_instance_destroy(i); 1776*f6e214c7SGavin Maltby scf_handle_destroy(h); 1777*f6e214c7SGavin Maltby free(pgname); 1778*f6e214c7SGavin Maltby 1779*f6e214c7SGavin Maltby return (r); 1780*f6e214c7SGavin Maltby } 1781*f6e214c7SGavin Maltby 1782*f6e214c7SGavin Maltby /* 1783*f6e214c7SGavin Maltby * Retrieve the notification parameters for the Event described in the 1784*f6e214c7SGavin Maltby * input nvlist_t nvl. 1785*f6e214c7SGavin Maltby * The function will allocate an nvlist_t to store the notification 1786*f6e214c7SGavin Maltby * parameters. The notification parameters in the output nvlist will have 1787*f6e214c7SGavin Maltby * the following format: 1788*f6e214c7SGavin Maltby * 1789*f6e214c7SGavin Maltby * version (uint32_t) 1790*f6e214c7SGavin Maltby * SCF_NOTIFY_PARAMS (array of embedded nvlists) 1791*f6e214c7SGavin Maltby * (start of notify-params[0]) 1792*f6e214c7SGavin Maltby * tset (int32_t) 1793*f6e214c7SGavin Maltby * <mechanism-name> (embedded nvlist) 1794*f6e214c7SGavin Maltby * <parameter-name> <parameter-type> 1795*f6e214c7SGavin Maltby * ... 1796*f6e214c7SGavin Maltby * (end <mechanism-name>) 1797*f6e214c7SGavin Maltby * ... 1798*f6e214c7SGavin Maltby * (end of notify-params[0]) 1799*f6e214c7SGavin Maltby * ... 1800*f6e214c7SGavin Maltby * 1801*f6e214c7SGavin Maltby * return SCF_SUCCESS or SCF_FAILED on 1802*f6e214c7SGavin Maltby * SCF_ERROR_BACKEND_ACCESS 1803*f6e214c7SGavin Maltby * SCF_ERROR_CONNECTION_BROKEN 1804*f6e214c7SGavin Maltby * SCF_ERROR_DELETED 1805*f6e214c7SGavin Maltby * SCF_ERROR_INTERNAL 1806*f6e214c7SGavin Maltby * SCF_ERROR_INVALID_ARGUMENT 1807*f6e214c7SGavin Maltby * SCF_ERROR_NO_MEMORY 1808*f6e214c7SGavin Maltby * SCF_ERROR_NO_RESOURCES 1809*f6e214c7SGavin Maltby * SCF_ERROR_NOT_FOUND 1810*f6e214c7SGavin Maltby * SCF_ERROR_PERMISSION_DENIED 1811*f6e214c7SGavin Maltby */ 1812*f6e214c7SGavin Maltby int 1813*f6e214c7SGavin Maltby smf_notify_get_params(nvlist_t **params, nvlist_t *nvl) 1814*f6e214c7SGavin Maltby { 1815*f6e214c7SGavin Maltby char *class; 1816*f6e214c7SGavin Maltby char *from; /* from state */ 1817*f6e214c7SGavin Maltby char *to; /* to state */ 1818*f6e214c7SGavin Maltby nvlist_t *attr; 1819*f6e214c7SGavin Maltby char *fmri; 1820*f6e214c7SGavin Maltby int32_t tset = 0; 1821*f6e214c7SGavin Maltby int r = SCF_FAILED; 1822*f6e214c7SGavin Maltby 1823*f6e214c7SGavin Maltby if (params == NULL || nvlist_lookup_string(nvl, "class", &class) != 0) { 1824*f6e214c7SGavin Maltby (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT); 1825*f6e214c7SGavin Maltby return (r); 1826*f6e214c7SGavin Maltby } 1827*f6e214c7SGavin Maltby if (nvlist_alloc(params, NV_UNIQUE_NAME, 0) != 0) { 1828*f6e214c7SGavin Maltby (void) scf_set_error(SCF_ERROR_NO_MEMORY); 1829*f6e214c7SGavin Maltby return (r); 1830*f6e214c7SGavin Maltby } 1831*f6e214c7SGavin Maltby 1832*f6e214c7SGavin Maltby if (is_svc_stn(class)) { 1833*f6e214c7SGavin Maltby if (nvlist_lookup_nvlist(nvl, "attr", &attr) != 0 || 1834*f6e214c7SGavin Maltby nvlist_lookup_string(attr, "svc-string", &fmri) != 0 || 1835*f6e214c7SGavin Maltby nvlist_lookup_string(attr, "from-state", &from) != 0 || 1836*f6e214c7SGavin Maltby nvlist_lookup_string(attr, "to-state", &to) != 0) { 1837*f6e214c7SGavin Maltby (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT); 1838*f6e214c7SGavin Maltby goto cleanup; 1839*f6e214c7SGavin Maltby } 1840*f6e214c7SGavin Maltby 1841*f6e214c7SGavin Maltby tset = SCF_TRANS(smf_state_from_string(from), 1842*f6e214c7SGavin Maltby smf_state_from_string(to)); 1843*f6e214c7SGavin Maltby if (!SCF_TRANS_VALID(tset)) { 1844*f6e214c7SGavin Maltby (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT); 1845*f6e214c7SGavin Maltby goto cleanup; 1846*f6e214c7SGavin Maltby } 1847*f6e214c7SGavin Maltby tset |= class_to_transition(class); 1848*f6e214c7SGavin Maltby 1849*f6e214c7SGavin Maltby r = _scf_get_svc_notify_params(fmri, *params, tset, 0, 1); 1850*f6e214c7SGavin Maltby } else { 1851*f6e214c7SGavin Maltby r = _scf_get_fma_notify_params(class, *params, 0); 1852*f6e214c7SGavin Maltby } 1853*f6e214c7SGavin Maltby 1854*f6e214c7SGavin Maltby cleanup: 1855*f6e214c7SGavin Maltby if (r == SCF_FAILED) { 1856*f6e214c7SGavin Maltby nvlist_free(*params); 1857*f6e214c7SGavin Maltby *params = NULL; 1858*f6e214c7SGavin Maltby } 1859*f6e214c7SGavin Maltby 1860*f6e214c7SGavin Maltby return (r); 1861*f6e214c7SGavin Maltby } 1862*f6e214c7SGavin Maltby 1863*f6e214c7SGavin Maltby /* 1864*f6e214c7SGavin Maltby * return SCF_SUCCESS or SCF_FAILED on 1865*f6e214c7SGavin Maltby * SCF_ERROR_BACKEND_ACCESS 1866*f6e214c7SGavin Maltby * SCF_ERROR_BACKEND_READONLY 1867*f6e214c7SGavin Maltby * SCF_ERROR_CONNECTION_BROKEN 1868*f6e214c7SGavin Maltby * SCF_ERROR_DELETED 1869*f6e214c7SGavin Maltby * SCF_ERROR_INTERNAL 1870*f6e214c7SGavin Maltby * SCF_ERROR_INVALID_ARGUMENT 1871*f6e214c7SGavin Maltby * SCF_ERROR_NO_MEMORY 1872*f6e214c7SGavin Maltby * SCF_ERROR_NO_RESOURCES 1873*f6e214c7SGavin Maltby * SCF_ERROR_NOT_FOUND 1874*f6e214c7SGavin Maltby * SCF_ERROR_PERMISSION_DENIED 1875*f6e214c7SGavin Maltby */ 1876*f6e214c7SGavin Maltby int 1877*f6e214c7SGavin Maltby smf_notify_del_params(const char *class, const char *fmri, int32_t tset) 1878*f6e214c7SGavin Maltby { 1879*f6e214c7SGavin Maltby scf_handle_t *h = _scf_handle_create_and_bind(SCF_VERSION); 1880*f6e214c7SGavin Maltby scf_error_t scf_e = scf_error(); 1881*f6e214c7SGavin Maltby scf_service_t *s = scf_service_create(h); 1882*f6e214c7SGavin Maltby scf_instance_t *i = scf_instance_create(h); 1883*f6e214c7SGavin Maltby scf_propertygroup_t *pg = scf_pg_create(h); 1884*f6e214c7SGavin Maltby int r = SCF_FAILED; 1885*f6e214c7SGavin Maltby char *pgname = NULL; 1886*f6e214c7SGavin Maltby int j; 1887*f6e214c7SGavin Maltby 1888*f6e214c7SGavin Maltby if (class == NULL) { 1889*f6e214c7SGavin Maltby (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT); 1890*f6e214c7SGavin Maltby goto cleanup; 1891*f6e214c7SGavin Maltby } 1892*f6e214c7SGavin Maltby 1893*f6e214c7SGavin Maltby if (h == NULL) { 1894*f6e214c7SGavin Maltby /* 1895*f6e214c7SGavin Maltby * use saved error if _scf_handle_create_and_bind() fails 1896*f6e214c7SGavin Maltby */ 1897*f6e214c7SGavin Maltby (void) scf_set_error(scf_e); 1898*f6e214c7SGavin Maltby goto cleanup; 1899*f6e214c7SGavin Maltby } 1900*f6e214c7SGavin Maltby if (s == NULL || i == NULL || pg == NULL) 1901*f6e214c7SGavin Maltby goto cleanup; 1902*f6e214c7SGavin Maltby 1903*f6e214c7SGavin Maltby if (is_svc_stn(class)) { 1904*f6e214c7SGavin Maltby tset |= class_to_transition(class); 1905*f6e214c7SGavin Maltby 1906*f6e214c7SGavin Maltby if (!SCF_TRANS_VALID(tset) || fmri == NULL) { 1907*f6e214c7SGavin Maltby (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT); 1908*f6e214c7SGavin Maltby goto cleanup; 1909*f6e214c7SGavin Maltby } 1910*f6e214c7SGavin Maltby 1911*f6e214c7SGavin Maltby if (decode_fmri(fmri, h, &s, &i) != SCF_SUCCESS) { 1912*f6e214c7SGavin Maltby if (scf_error() == SCF_ERROR_CONSTRAINT_VIOLATED) 1913*f6e214c7SGavin Maltby (void) scf_set_error( 1914*f6e214c7SGavin Maltby SCF_ERROR_INVALID_ARGUMENT); 1915*f6e214c7SGavin Maltby if (check_scf_error(scf_error(), errs_1)) { 1916*f6e214c7SGavin Maltby goto cleanup; 1917*f6e214c7SGavin Maltby } 1918*f6e214c7SGavin Maltby } 1919*f6e214c7SGavin Maltby 1920*f6e214c7SGavin Maltby for (j = 0; st_pgnames[j].st_pgname != NULL; ++j) { 1921*f6e214c7SGavin Maltby /* if this transition is not in the tset, continue */ 1922*f6e214c7SGavin Maltby if (!(tset & st_pgnames[j].st_state)) 1923*f6e214c7SGavin Maltby continue; 1924*f6e214c7SGavin Maltby 1925*f6e214c7SGavin Maltby if (del_pg(s, i, st_pgnames[j].st_pgname, pg) != 1926*f6e214c7SGavin Maltby SCF_SUCCESS && 1927*f6e214c7SGavin Maltby scf_error() != SCF_ERROR_DELETED && 1928*f6e214c7SGavin Maltby scf_error() != SCF_ERROR_NOT_FOUND) { 1929*f6e214c7SGavin Maltby if (check_scf_error(scf_error(), 1930*f6e214c7SGavin Maltby errs_1)) { 1931*f6e214c7SGavin Maltby goto cleanup; 1932*f6e214c7SGavin Maltby } 1933*f6e214c7SGavin Maltby } 1934*f6e214c7SGavin Maltby } 1935*f6e214c7SGavin Maltby if (s == NULL) { 1936*f6e214c7SGavin Maltby /* We only need to refresh the instance */ 1937*f6e214c7SGavin Maltby if (_smf_refresh_instance_i(i) != 0 && 1938*f6e214c7SGavin Maltby check_scf_error(scf_error(), errs_1)) 1939*f6e214c7SGavin Maltby goto cleanup; 1940*f6e214c7SGavin Maltby } else { 1941*f6e214c7SGavin Maltby /* We have to refresh all instances in the service */ 1942*f6e214c7SGavin Maltby if (_smf_refresh_all_instances(s) != 0 && 1943*f6e214c7SGavin Maltby check_scf_error(scf_error(), errs_1)) 1944*f6e214c7SGavin Maltby goto cleanup; 1945*f6e214c7SGavin Maltby } 1946*f6e214c7SGavin Maltby } else { 1947*f6e214c7SGavin Maltby if ((pgname = class_to_pgname(class)) == NULL) 1948*f6e214c7SGavin Maltby goto cleanup; 1949*f6e214c7SGavin Maltby 1950*f6e214c7SGavin Maltby if (scf_handle_decode_fmri(h, SCF_NOTIFY_PARAMS_INST, NULL, 1951*f6e214c7SGavin Maltby NULL, i, NULL, NULL, SCF_DECODE_FMRI_EXACT) != SCF_SUCCESS) 1952*f6e214c7SGavin Maltby goto cleanup; 1953*f6e214c7SGavin Maltby 1954*f6e214c7SGavin Maltby if (del_pg(NULL, i, pgname, pg) != SCF_SUCCESS && 1955*f6e214c7SGavin Maltby scf_error() != SCF_ERROR_DELETED && 1956*f6e214c7SGavin Maltby scf_error() != SCF_ERROR_NOT_FOUND) { 1957*f6e214c7SGavin Maltby if (check_scf_error(scf_error(), errs_1)) { 1958*f6e214c7SGavin Maltby goto cleanup; 1959*f6e214c7SGavin Maltby } 1960*f6e214c7SGavin Maltby } 1961*f6e214c7SGavin Maltby 1962*f6e214c7SGavin Maltby if (_smf_refresh_instance_i(i) != 0 && 1963*f6e214c7SGavin Maltby check_scf_error(scf_error(), errs_1)) 1964*f6e214c7SGavin Maltby goto cleanup; 1965*f6e214c7SGavin Maltby } 1966*f6e214c7SGavin Maltby 1967*f6e214c7SGavin Maltby 1968*f6e214c7SGavin Maltby r = SCF_SUCCESS; 1969*f6e214c7SGavin Maltby 1970*f6e214c7SGavin Maltby cleanup: 1971*f6e214c7SGavin Maltby scf_pg_destroy(pg); 1972*f6e214c7SGavin Maltby scf_instance_destroy(i); 1973*f6e214c7SGavin Maltby scf_service_destroy(s); 1974*f6e214c7SGavin Maltby scf_handle_destroy(h); 1975*f6e214c7SGavin Maltby free(pgname); 1976*f6e214c7SGavin Maltby 1977*f6e214c7SGavin Maltby return (r); 1978*f6e214c7SGavin Maltby } 1979