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