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
check_scf_error(scf_error_t e,const scf_error_t * errs)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
is_svc_stn(const char * class)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
base_class_len(const char * c)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 *
class_to_pgname(const char * class)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
get_pg(scf_service_t * s,scf_instance_t * i,const char * n,scf_propertygroup_t * pg,int composed)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
get_or_add_pg(scf_service_t * s,scf_instance_t * i,const char * n,const char * t,uint32_t flags,scf_propertygroup_t * pg)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
del_pg(scf_service_t * s,scf_instance_t * i,const char * n,scf_propertygroup_t * pg)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
get_scf_type(nvpair_t * p)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
add_entry(scf_transaction_entry_t * te,scf_value_t * val)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
add_boolean_entry(scf_handle_t * h,scf_transaction_entry_t * te,uint8_t v)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
add_count_entry(scf_handle_t * h,scf_transaction_entry_t * te,uint64_t v)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
add_integer_entry(scf_handle_t * h,scf_transaction_entry_t * te,int64_t v)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
add_astring_entry(scf_handle_t * h,scf_transaction_entry_t * te,char * s)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
get_nvpair_vals(scf_handle_t * h,scf_transaction_entry_t * te,nvpair_t * p)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
prep_transaction(scf_transaction_t * tx,scf_transaction_entry_t * te,const char * prop,scf_type_t type)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
notify_set_params(scf_propertygroup_t * pg,nvlist_t * params)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
decode_fmri(const char * fmri,scf_handle_t * h,scf_service_t ** s,scf_instance_t ** i)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
get_type_size(scf_type_t t)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 **
get_v_pointer(scf_values_t * v)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
get_value(scf_value_t * val,scf_values_t * v,int c,char * buf,int sz)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
values_get(scf_property_t * prop,scf_values_t * v)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
add_prop_to_nvlist(scf_property_t * p,const char * pname,nvlist_t * nvl,int array)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
get_mech_name(const char * name,char ** mech,char ** val)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
num_of_transitions(int32_t 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
class_to_transition(const char * c)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
smf_notify_set_params(const char * class,nvlist_t * attr)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
_scf_notify_get_params(scf_propertygroup_t * pg,nvlist_t * params)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
get_stn_pg(scf_service_t * s,scf_instance_t * i,scf_instance_t * g,const char * pgname,scf_propertygroup_t * pg)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
get_pg_source(scf_propertygroup_t * pg,nvlist_t * params)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
_scf_get_svc_notify_params(const char * fmri,nvlist_t * nvl,int32_t tset,int getsource,int getglobal)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
_scf_get_fma_notify_params(const char * class,nvlist_t * nvl,int getsource)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
smf_notify_get_params(nvlist_t ** params,nvlist_t * nvl)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
smf_notify_del_params(const char * class,const char * fmri,int32_t tset)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