xref: /titanic_44/usr/src/lib/smbsrv/libsmb/common/smb_scfutil.c (revision b819cea2f73f98c5662230cc9affc8cc84f77fcf)
1da6c28aaSamw /*
2da6c28aaSamw  * CDDL HEADER START
3da6c28aaSamw  *
4da6c28aaSamw  * The contents of this file are subject to the terms of the
5da6c28aaSamw  * Common Development and Distribution License (the "License").
6da6c28aaSamw  * You may not use this file except in compliance with the License.
7da6c28aaSamw  *
8da6c28aaSamw  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9da6c28aaSamw  * or http://www.opensolaris.org/os/licensing.
10da6c28aaSamw  * See the License for the specific language governing permissions
11da6c28aaSamw  * and limitations under the License.
12da6c28aaSamw  *
13da6c28aaSamw  * When distributing Covered Code, include this CDDL HEADER in each
14da6c28aaSamw  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15da6c28aaSamw  * If applicable, add the following below this CDDL HEADER, with the
16da6c28aaSamw  * fields enclosed by brackets "[]" replaced with your own identifying
17da6c28aaSamw  * information: Portions Copyright [yyyy] [name of copyright owner]
18da6c28aaSamw  *
19da6c28aaSamw  * CDDL HEADER END
20da6c28aaSamw  */
21da6c28aaSamw /*
22dc20a302Sas200622  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23da6c28aaSamw  * Use is subject to license terms.
24*b819cea2SGordon Ross  *
25*b819cea2SGordon Ross  * Copyright 2014 Nexenta Systems, Inc.  All rights reserved.
26da6c28aaSamw  */
27da6c28aaSamw 
28da6c28aaSamw /* helper functions for using libscf with CIFS */
29da6c28aaSamw 
30da6c28aaSamw #include <libscf.h>
31da6c28aaSamw #include <string.h>
32da6c28aaSamw #include <stdio.h>
33da6c28aaSamw #include <stdlib.h>
34da6c28aaSamw #include <syslog.h>
35da6c28aaSamw #include <errno.h>
36da6c28aaSamw #include <libintl.h>
37da6c28aaSamw #include <assert.h>
38da6c28aaSamw #include <strings.h>
39da6c28aaSamw 
40da6c28aaSamw #include <uuid/uuid.h>
41da6c28aaSamw #include <sys/param.h>
42da6c28aaSamw 
43da6c28aaSamw #include <smbsrv/libsmb.h>
44da6c28aaSamw 
45da6c28aaSamw /*
46da6c28aaSamw  * smb_smf_scf_log_error(msg)
47da6c28aaSamw  * Logs error messages from scf API's
48da6c28aaSamw  */
49da6c28aaSamw static void
smb_smf_scf_log_error(char * msg)50da6c28aaSamw smb_smf_scf_log_error(char *msg)
51da6c28aaSamw {
52*b819cea2SGordon Ross 	if (msg == NULL)
53*b819cea2SGordon Ross 		msg = "SMBD SMF problem";
54*b819cea2SGordon Ross 
55*b819cea2SGordon Ross 	syslog(LOG_ERR, " %s: %s", msg, scf_strerror(scf_error()));
56da6c28aaSamw }
57da6c28aaSamw 
58da6c28aaSamw /*
59da6c28aaSamw  * smb_smf_create_service_pgroup(handle, pgroup)
60da6c28aaSamw  *
61da6c28aaSamw  * create a new property group at service level.
62da6c28aaSamw  */
63da6c28aaSamw int
smb_smf_create_service_pgroup(smb_scfhandle_t * handle,char * pgroup)64da6c28aaSamw smb_smf_create_service_pgroup(smb_scfhandle_t *handle, char *pgroup)
65da6c28aaSamw {
66da6c28aaSamw 	int ret = SMBD_SMF_OK;
67da6c28aaSamw 	int err;
68da6c28aaSamw 
697b59d02dSjb150015 	if (handle == NULL)
70da6c28aaSamw 		return (SMBD_SMF_SYSTEM_ERR);
71da6c28aaSamw 
72da6c28aaSamw 	/*
73da6c28aaSamw 	 * only create a handle if it doesn't exist. It is ok to exist
74da6c28aaSamw 	 * since the pg handle will be set as a side effect.
75da6c28aaSamw 	 */
76da6c28aaSamw 	if (handle->scf_pg == NULL)
777b59d02dSjb150015 		if ((handle->scf_pg =
787b59d02dSjb150015 		    scf_pg_create(handle->scf_handle)) == NULL)
797b59d02dSjb150015 			return (SMBD_SMF_SYSTEM_ERR);
80da6c28aaSamw 
81da6c28aaSamw 	/*
82da6c28aaSamw 	 * if the pgroup exists, we are done. If it doesn't, then we
83da6c28aaSamw 	 * need to actually add one to the service instance.
84da6c28aaSamw 	 */
85da6c28aaSamw 	if (scf_service_get_pg(handle->scf_service,
86da6c28aaSamw 	    pgroup, handle->scf_pg) != 0) {
87da6c28aaSamw 		/* doesn't exist so create one */
88da6c28aaSamw 		if (scf_service_add_pg(handle->scf_service, pgroup,
89da6c28aaSamw 		    SCF_GROUP_APPLICATION, 0, handle->scf_pg) != 0) {
90da6c28aaSamw 			err = scf_error();
91da6c28aaSamw 			if (err != SCF_ERROR_NONE)
92da6c28aaSamw 				smb_smf_scf_log_error(NULL);
93da6c28aaSamw 			switch (err) {
94da6c28aaSamw 			case SCF_ERROR_PERMISSION_DENIED:
95da6c28aaSamw 				ret = SMBD_SMF_NO_PERMISSION;
96da6c28aaSamw 				break;
97da6c28aaSamw 			default:
98da6c28aaSamw 				ret = SMBD_SMF_SYSTEM_ERR;
99da6c28aaSamw 				break;
100da6c28aaSamw 			}
101da6c28aaSamw 		}
102da6c28aaSamw 	}
103da6c28aaSamw 	return (ret);
104da6c28aaSamw }
105da6c28aaSamw 
106da6c28aaSamw /*
107da6c28aaSamw  * Start transaction on current pg in handle.
108da6c28aaSamw  * The pg could be service or instance level.
109da6c28aaSamw  * Must be called after pg handle is obtained
110da6c28aaSamw  * from create or get.
111da6c28aaSamw  */
112da6c28aaSamw int
smb_smf_start_transaction(smb_scfhandle_t * handle)113da6c28aaSamw smb_smf_start_transaction(smb_scfhandle_t *handle)
114da6c28aaSamw {
115da6c28aaSamw 	int ret = SMBD_SMF_OK;
116da6c28aaSamw 
117da6c28aaSamw 	if (!handle || (!handle->scf_pg))
118da6c28aaSamw 		return (SMBD_SMF_SYSTEM_ERR);
119da6c28aaSamw 
120da6c28aaSamw 	/*
121da6c28aaSamw 	 * lookup the property group and create it if it doesn't already
122da6c28aaSamw 	 * exist.
123da6c28aaSamw 	 */
124da6c28aaSamw 	if (handle->scf_state == SCH_STATE_INIT) {
125da6c28aaSamw 		if (ret == SMBD_SMF_OK) {
126da6c28aaSamw 			handle->scf_trans =
127da6c28aaSamw 			    scf_transaction_create(handle->scf_handle);
128da6c28aaSamw 			if (handle->scf_trans != NULL) {
129da6c28aaSamw 				if (scf_transaction_start(handle->scf_trans,
130da6c28aaSamw 				    handle->scf_pg) != 0) {
131da6c28aaSamw 					ret = SMBD_SMF_SYSTEM_ERR;
132da6c28aaSamw 					scf_transaction_destroy(
133da6c28aaSamw 					    handle->scf_trans);
134da6c28aaSamw 					handle->scf_trans = NULL;
135da6c28aaSamw 				}
136da6c28aaSamw 			} else {
137da6c28aaSamw 				ret = SMBD_SMF_SYSTEM_ERR;
138da6c28aaSamw 			}
139da6c28aaSamw 		}
140da6c28aaSamw 	}
141da6c28aaSamw 	if (ret == SMBD_SMF_SYSTEM_ERR &&
142da6c28aaSamw 	    scf_error() == SCF_ERROR_PERMISSION_DENIED)
143da6c28aaSamw 		ret = SMBD_SMF_NO_PERMISSION;
144da6c28aaSamw 
145da6c28aaSamw 	return (ret);
146da6c28aaSamw }
147da6c28aaSamw 
148da6c28aaSamw /*
149da6c28aaSamw  * smb_smf_end_transaction(handle)
150da6c28aaSamw  *
151da6c28aaSamw  * Commit the changes that were added to the transaction in the
152da6c28aaSamw  * handle. Do all necessary cleanup.
153da6c28aaSamw  */
154da6c28aaSamw int
smb_smf_end_transaction(smb_scfhandle_t * handle)155da6c28aaSamw smb_smf_end_transaction(smb_scfhandle_t *handle)
156da6c28aaSamw {
157da6c28aaSamw 	int ret = SMBD_SMF_OK;
158da6c28aaSamw 
159da6c28aaSamw 	if (handle == NULL)
160da6c28aaSamw 		return (SMBD_SMF_SYSTEM_ERR);
161da6c28aaSamw 
162da6c28aaSamw 	if (handle->scf_trans == NULL) {
163da6c28aaSamw 		ret = SMBD_SMF_SYSTEM_ERR;
164da6c28aaSamw 	} else {
165da6c28aaSamw 		if (scf_transaction_commit(handle->scf_trans) < 0) {
166da6c28aaSamw 			ret = SMBD_SMF_SYSTEM_ERR;
167da6c28aaSamw 			smb_smf_scf_log_error("Failed to commit "
168da6c28aaSamw 			    "transaction: %s");
169da6c28aaSamw 		}
170da6c28aaSamw 		scf_transaction_destroy_children(handle->scf_trans);
171da6c28aaSamw 		scf_transaction_destroy(handle->scf_trans);
172da6c28aaSamw 		handle->scf_trans = NULL;
173da6c28aaSamw 	}
174da6c28aaSamw 	return (ret);
175da6c28aaSamw }
176da6c28aaSamw 
177da6c28aaSamw /*
178da6c28aaSamw  * Sets string property in current pg
179da6c28aaSamw  */
180da6c28aaSamw int
smb_smf_set_string_property(smb_scfhandle_t * handle,char * propname,char * valstr)181da6c28aaSamw smb_smf_set_string_property(smb_scfhandle_t *handle,
182da6c28aaSamw     char *propname, char *valstr)
183da6c28aaSamw {
184da6c28aaSamw 	int ret = SMBD_SMF_OK;
185da6c28aaSamw 	scf_value_t *value = NULL;
186da6c28aaSamw 	scf_transaction_entry_t *entry = NULL;
187da6c28aaSamw 
188da6c28aaSamw 	if (handle == NULL)
189da6c28aaSamw 		return (SMBD_SMF_SYSTEM_ERR);
190da6c28aaSamw 
191da6c28aaSamw 	/*
192da6c28aaSamw 	 * properties must be set in transactions and don't take
193da6c28aaSamw 	 * effect until the transaction has been ended/committed.
194da6c28aaSamw 	 */
195da6c28aaSamw 	value = scf_value_create(handle->scf_handle);
196da6c28aaSamw 	entry = scf_entry_create(handle->scf_handle);
197da6c28aaSamw 	if (value != NULL && entry != NULL) {
198da6c28aaSamw 		if (scf_transaction_property_change(handle->scf_trans, entry,
199da6c28aaSamw 		    propname, SCF_TYPE_ASTRING) == 0 ||
200da6c28aaSamw 		    scf_transaction_property_new(handle->scf_trans, entry,
201da6c28aaSamw 		    propname, SCF_TYPE_ASTRING) == 0) {
202da6c28aaSamw 			if (scf_value_set_astring(value, valstr) == 0) {
203da6c28aaSamw 				if (scf_entry_add_value(entry, value) != 0) {
204da6c28aaSamw 					ret = SMBD_SMF_SYSTEM_ERR;
205da6c28aaSamw 					scf_value_destroy(value);
206da6c28aaSamw 				}
207da6c28aaSamw 				/* the value is in the transaction */
208da6c28aaSamw 				value = NULL;
209da6c28aaSamw 			} else {
210da6c28aaSamw 				/* value couldn't be constructed */
211da6c28aaSamw 				ret = SMBD_SMF_SYSTEM_ERR;
212da6c28aaSamw 			}
213da6c28aaSamw 			/* the entry is in the transaction */
214da6c28aaSamw 			entry = NULL;
215da6c28aaSamw 		} else {
216da6c28aaSamw 			ret = SMBD_SMF_SYSTEM_ERR;
217da6c28aaSamw 		}
218da6c28aaSamw 	} else {
219da6c28aaSamw 		ret = SMBD_SMF_SYSTEM_ERR;
220da6c28aaSamw 	}
221da6c28aaSamw 	if (ret == SMBD_SMF_SYSTEM_ERR) {
222da6c28aaSamw 		switch (scf_error()) {
223da6c28aaSamw 		case SCF_ERROR_PERMISSION_DENIED:
224da6c28aaSamw 			ret = SMBD_SMF_NO_PERMISSION;
225da6c28aaSamw 			break;
226da6c28aaSamw 		}
227da6c28aaSamw 	}
228da6c28aaSamw 
229da6c28aaSamw 	/*
230da6c28aaSamw 	 * cleanup if there were any errors that didn't leave these
231da6c28aaSamw 	 * values where they would be cleaned up later.
232da6c28aaSamw 	 */
233da6c28aaSamw 	if (value != NULL)
234da6c28aaSamw 		scf_value_destroy(value);
235da6c28aaSamw 	if (entry != NULL)
236da6c28aaSamw 		scf_entry_destroy(entry);
237da6c28aaSamw 	return (ret);
238da6c28aaSamw }
239da6c28aaSamw 
240da6c28aaSamw /*
241da6c28aaSamw  * Gets string property value.upto sz size.
242da6c28aaSamw  * Caller is responsible to have enough memory allocated.
243da6c28aaSamw  */
244da6c28aaSamw int
smb_smf_get_string_property(smb_scfhandle_t * handle,char * propname,char * valstr,size_t sz)245da6c28aaSamw smb_smf_get_string_property(smb_scfhandle_t *handle, char *propname,
246da6c28aaSamw     char *valstr, size_t sz)
247da6c28aaSamw {
248da6c28aaSamw 	int ret = SMBD_SMF_OK;
249da6c28aaSamw 	scf_value_t *value;
250da6c28aaSamw 	scf_property_t *prop;
251da6c28aaSamw 
252da6c28aaSamw 	if (handle == NULL)
253da6c28aaSamw 		return (SMBD_SMF_SYSTEM_ERR);
254da6c28aaSamw 
255da6c28aaSamw 	value = scf_value_create(handle->scf_handle);
256da6c28aaSamw 	prop = scf_property_create(handle->scf_handle);
257da6c28aaSamw 	if (value && prop &&
258da6c28aaSamw 	    (scf_pg_get_property(handle->scf_pg, propname, prop) == 0)) {
259da6c28aaSamw 		if (scf_property_get_value(prop, value) == 0) {
260da6c28aaSamw 			if (scf_value_get_astring(value, valstr, sz) < 0) {
261da6c28aaSamw 				ret = SMBD_SMF_SYSTEM_ERR;
262da6c28aaSamw 			}
263da6c28aaSamw 		} else {
264da6c28aaSamw 			ret = SMBD_SMF_SYSTEM_ERR;
265da6c28aaSamw 		}
266da6c28aaSamw 	} else {
267da6c28aaSamw 		ret = SMBD_SMF_SYSTEM_ERR;
268da6c28aaSamw 	}
269da6c28aaSamw 	if (value != NULL)
270da6c28aaSamw 		scf_value_destroy(value);
271da6c28aaSamw 	if (prop != NULL)
272da6c28aaSamw 		scf_property_destroy(prop);
273da6c28aaSamw 	return (ret);
274da6c28aaSamw }
275da6c28aaSamw 
276da6c28aaSamw /*
277da6c28aaSamw  * Set integer value of property.
278da6c28aaSamw  * The value is returned as int64_t value
279da6c28aaSamw  * Caller ensures appropriate translation.
280da6c28aaSamw  */
281da6c28aaSamw int
smb_smf_set_integer_property(smb_scfhandle_t * handle,char * propname,int64_t valint)282da6c28aaSamw smb_smf_set_integer_property(smb_scfhandle_t *handle, char *propname,
283da6c28aaSamw     int64_t valint)
284da6c28aaSamw {
285da6c28aaSamw 	int ret = SMBD_SMF_OK;
286da6c28aaSamw 	scf_value_t *value = NULL;
287da6c28aaSamw 	scf_transaction_entry_t *entry = NULL;
288da6c28aaSamw 
289da6c28aaSamw 	if (handle == NULL)
290da6c28aaSamw 		return (SMBD_SMF_SYSTEM_ERR);
291da6c28aaSamw 
292da6c28aaSamw 	/*
293da6c28aaSamw 	 * properties must be set in transactions and don't take
294da6c28aaSamw 	 * effect until the transaction has been ended/committed.
295da6c28aaSamw 	 */
296da6c28aaSamw 	value = scf_value_create(handle->scf_handle);
297da6c28aaSamw 	entry = scf_entry_create(handle->scf_handle);
298da6c28aaSamw 	if (value != NULL && entry != NULL) {
299da6c28aaSamw 		if (scf_transaction_property_change(handle->scf_trans, entry,
300da6c28aaSamw 		    propname, SCF_TYPE_INTEGER) == 0 ||
301da6c28aaSamw 		    scf_transaction_property_new(handle->scf_trans, entry,
302da6c28aaSamw 		    propname, SCF_TYPE_INTEGER) == 0) {
303da6c28aaSamw 			scf_value_set_integer(value, valint);
304da6c28aaSamw 			if (scf_entry_add_value(entry, value) != 0) {
305da6c28aaSamw 				ret = SMBD_SMF_SYSTEM_ERR;
306da6c28aaSamw 				scf_value_destroy(value);
307da6c28aaSamw 			}
308da6c28aaSamw 			/* the value is in the transaction */
309da6c28aaSamw 			value = NULL;
310da6c28aaSamw 		}
311da6c28aaSamw 		/* the entry is in the transaction */
312da6c28aaSamw 		entry = NULL;
313da6c28aaSamw 	} else {
314da6c28aaSamw 		ret = SMBD_SMF_SYSTEM_ERR;
315da6c28aaSamw 	}
316da6c28aaSamw 	if (ret == SMBD_SMF_SYSTEM_ERR) {
317da6c28aaSamw 		switch (scf_error()) {
318da6c28aaSamw 		case SCF_ERROR_PERMISSION_DENIED:
319da6c28aaSamw 			ret = SMBD_SMF_NO_PERMISSION;
320da6c28aaSamw 			break;
321da6c28aaSamw 		}
322da6c28aaSamw 	}
323da6c28aaSamw 	/*
324da6c28aaSamw 	 * cleanup if there were any errors that didn't leave these
325da6c28aaSamw 	 * values where they would be cleaned up later.
326da6c28aaSamw 	 */
327da6c28aaSamw 	if (value != NULL)
328da6c28aaSamw 		scf_value_destroy(value);
329da6c28aaSamw 	if (entry != NULL)
330da6c28aaSamw 		scf_entry_destroy(entry);
331da6c28aaSamw 	return (ret);
332da6c28aaSamw }
333da6c28aaSamw 
334da6c28aaSamw /*
335da6c28aaSamw  * Gets integer property value.
336da6c28aaSamw  * Caller is responsible to have enough memory allocated.
337da6c28aaSamw  */
338da6c28aaSamw int
smb_smf_get_integer_property(smb_scfhandle_t * handle,char * propname,int64_t * valint)339da6c28aaSamw smb_smf_get_integer_property(smb_scfhandle_t *handle, char *propname,
340da6c28aaSamw     int64_t *valint)
341da6c28aaSamw {
342da6c28aaSamw 	int ret = SMBD_SMF_OK;
343da6c28aaSamw 	scf_value_t *value = NULL;
344da6c28aaSamw 	scf_property_t *prop = NULL;
345da6c28aaSamw 
346da6c28aaSamw 	if (handle == NULL)
347da6c28aaSamw 		return (SMBD_SMF_SYSTEM_ERR);
348da6c28aaSamw 
349da6c28aaSamw 	value = scf_value_create(handle->scf_handle);
350da6c28aaSamw 	prop = scf_property_create(handle->scf_handle);
351da6c28aaSamw 	if ((prop) && (value) &&
352da6c28aaSamw 	    (scf_pg_get_property(handle->scf_pg, propname, prop) == 0)) {
353da6c28aaSamw 		if (scf_property_get_value(prop, value) == 0) {
354da6c28aaSamw 			if (scf_value_get_integer(value,
355da6c28aaSamw 			    valint) != 0) {
356da6c28aaSamw 				ret = SMBD_SMF_SYSTEM_ERR;
357da6c28aaSamw 			}
358da6c28aaSamw 		} else {
359da6c28aaSamw 			ret = SMBD_SMF_SYSTEM_ERR;
360da6c28aaSamw 		}
361da6c28aaSamw 	} else {
362da6c28aaSamw 		ret = SMBD_SMF_SYSTEM_ERR;
363da6c28aaSamw 	}
364da6c28aaSamw 	if (value != NULL)
365da6c28aaSamw 		scf_value_destroy(value);
366da6c28aaSamw 	if (prop != NULL)
367da6c28aaSamw 		scf_property_destroy(prop);
368da6c28aaSamw 	return (ret);
369da6c28aaSamw }
370da6c28aaSamw 
371da6c28aaSamw /*
372da6c28aaSamw  * Set boolean value of property.
373da6c28aaSamw  * The value is returned as int64_t value
374da6c28aaSamw  * Caller ensures appropriate translation.
375da6c28aaSamw  */
376da6c28aaSamw int
smb_smf_set_boolean_property(smb_scfhandle_t * handle,char * propname,uint8_t valbool)377da6c28aaSamw smb_smf_set_boolean_property(smb_scfhandle_t *handle, char *propname,
378da6c28aaSamw     uint8_t valbool)
379da6c28aaSamw {
380da6c28aaSamw 	int ret = SMBD_SMF_OK;
381da6c28aaSamw 	scf_value_t *value = NULL;
382da6c28aaSamw 	scf_transaction_entry_t *entry = NULL;
383da6c28aaSamw 
384da6c28aaSamw 	if (handle == NULL)
385da6c28aaSamw 		return (SMBD_SMF_SYSTEM_ERR);
386da6c28aaSamw 
387da6c28aaSamw 	/*
388da6c28aaSamw 	 * properties must be set in transactions and don't take
389da6c28aaSamw 	 * effect until the transaction has been ended/committed.
390da6c28aaSamw 	 */
391da6c28aaSamw 	value = scf_value_create(handle->scf_handle);
392da6c28aaSamw 	entry = scf_entry_create(handle->scf_handle);
393da6c28aaSamw 	if (value != NULL && entry != NULL) {
394da6c28aaSamw 		if (scf_transaction_property_change(handle->scf_trans, entry,
395da6c28aaSamw 		    propname, SCF_TYPE_BOOLEAN) == 0 ||
396da6c28aaSamw 		    scf_transaction_property_new(handle->scf_trans, entry,
397da6c28aaSamw 		    propname, SCF_TYPE_BOOLEAN) == 0) {
398da6c28aaSamw 			scf_value_set_boolean(value, valbool);
399da6c28aaSamw 			if (scf_entry_add_value(entry, value) != 0) {
400da6c28aaSamw 				ret = SMBD_SMF_SYSTEM_ERR;
401da6c28aaSamw 				scf_value_destroy(value);
402da6c28aaSamw 			}
403da6c28aaSamw 			/* the value is in the transaction */
404da6c28aaSamw 			value = NULL;
405da6c28aaSamw 		}
406da6c28aaSamw 		/* the entry is in the transaction */
407da6c28aaSamw 		entry = NULL;
408da6c28aaSamw 	} else {
409da6c28aaSamw 		ret = SMBD_SMF_SYSTEM_ERR;
410da6c28aaSamw 	}
411da6c28aaSamw 	if (ret == SMBD_SMF_SYSTEM_ERR) {
412da6c28aaSamw 		switch (scf_error()) {
413da6c28aaSamw 		case SCF_ERROR_PERMISSION_DENIED:
414da6c28aaSamw 			ret = SMBD_SMF_NO_PERMISSION;
415da6c28aaSamw 			break;
416da6c28aaSamw 		}
417da6c28aaSamw 	}
418da6c28aaSamw 	/*
419da6c28aaSamw 	 * cleanup if there were any errors that didn't leave these
420da6c28aaSamw 	 * values where they would be cleaned up later.
421da6c28aaSamw 	 */
422da6c28aaSamw 	if (value != NULL)
423da6c28aaSamw 		scf_value_destroy(value);
424da6c28aaSamw 	if (entry != NULL)
425da6c28aaSamw 		scf_entry_destroy(entry);
426da6c28aaSamw 	return (ret);
427da6c28aaSamw }
428da6c28aaSamw 
429da6c28aaSamw /*
430da6c28aaSamw  * Gets boolean property value.
431da6c28aaSamw  * Caller is responsible to have enough memory allocated.
432da6c28aaSamw  */
433da6c28aaSamw int
smb_smf_get_boolean_property(smb_scfhandle_t * handle,char * propname,uint8_t * valbool)434da6c28aaSamw smb_smf_get_boolean_property(smb_scfhandle_t *handle, char *propname,
435da6c28aaSamw     uint8_t *valbool)
436da6c28aaSamw {
437da6c28aaSamw 	int ret = SMBD_SMF_OK;
438da6c28aaSamw 	scf_value_t *value = NULL;
439da6c28aaSamw 	scf_property_t *prop = NULL;
440da6c28aaSamw 
441da6c28aaSamw 	if (handle == NULL)
442da6c28aaSamw 		return (SMBD_SMF_SYSTEM_ERR);
443da6c28aaSamw 
444da6c28aaSamw 	value = scf_value_create(handle->scf_handle);
445da6c28aaSamw 	prop = scf_property_create(handle->scf_handle);
446da6c28aaSamw 	if ((prop) && (value) &&
447da6c28aaSamw 	    (scf_pg_get_property(handle->scf_pg, propname, prop) == 0)) {
448da6c28aaSamw 		if (scf_property_get_value(prop, value) == 0) {
449da6c28aaSamw 			if (scf_value_get_boolean(value,
450da6c28aaSamw 			    valbool) != 0) {
451da6c28aaSamw 				ret = SMBD_SMF_SYSTEM_ERR;
452da6c28aaSamw 			}
453da6c28aaSamw 		} else {
454da6c28aaSamw 			ret = SMBD_SMF_SYSTEM_ERR;
455da6c28aaSamw 		}
456da6c28aaSamw 	} else {
457da6c28aaSamw 		ret = SMBD_SMF_SYSTEM_ERR;
458da6c28aaSamw 	}
459da6c28aaSamw 	if (value != NULL)
460da6c28aaSamw 		scf_value_destroy(value);
461da6c28aaSamw 	if (prop != NULL)
462da6c28aaSamw 		scf_property_destroy(prop);
463da6c28aaSamw 	return (ret);
464da6c28aaSamw }
465da6c28aaSamw 
466da6c28aaSamw /*
467da6c28aaSamw  * Sets a blob property value.
468da6c28aaSamw  */
469da6c28aaSamw int
smb_smf_set_opaque_property(smb_scfhandle_t * handle,char * propname,void * voidval,size_t sz)470da6c28aaSamw smb_smf_set_opaque_property(smb_scfhandle_t *handle, char *propname,
471da6c28aaSamw     void *voidval, size_t sz)
472da6c28aaSamw {
473da6c28aaSamw 	int ret = SMBD_SMF_OK;
474da6c28aaSamw 	scf_value_t *value;
475da6c28aaSamw 	scf_transaction_entry_t *entry;
476da6c28aaSamw 
477da6c28aaSamw 	if (handle == NULL)
478da6c28aaSamw 		return (SMBD_SMF_SYSTEM_ERR);
479da6c28aaSamw 
480da6c28aaSamw 	/*
481da6c28aaSamw 	 * properties must be set in transactions and don't take
482da6c28aaSamw 	 * effect until the transaction has been ended/committed.
483da6c28aaSamw 	 */
484da6c28aaSamw 	value = scf_value_create(handle->scf_handle);
485da6c28aaSamw 	entry = scf_entry_create(handle->scf_handle);
486da6c28aaSamw 	if (value != NULL && entry != NULL) {
487da6c28aaSamw 		if (scf_transaction_property_change(handle->scf_trans, entry,
488da6c28aaSamw 		    propname, SCF_TYPE_OPAQUE) == 0 ||
489da6c28aaSamw 		    scf_transaction_property_new(handle->scf_trans, entry,
490da6c28aaSamw 		    propname, SCF_TYPE_OPAQUE) == 0) {
491da6c28aaSamw 			if (scf_value_set_opaque(value, voidval, sz) == 0) {
492da6c28aaSamw 				if (scf_entry_add_value(entry, value) != 0) {
493da6c28aaSamw 					ret = SMBD_SMF_SYSTEM_ERR;
494da6c28aaSamw 					scf_value_destroy(value);
495da6c28aaSamw 				}
496da6c28aaSamw 				/* the value is in the transaction */
497da6c28aaSamw 				value = NULL;
498da6c28aaSamw 			} else {
499da6c28aaSamw 				/* value couldn't be constructed */
500da6c28aaSamw 				ret = SMBD_SMF_SYSTEM_ERR;
501da6c28aaSamw 			}
502da6c28aaSamw 			/* the entry is in the transaction */
503da6c28aaSamw 			entry = NULL;
504da6c28aaSamw 		} else {
505da6c28aaSamw 			ret = SMBD_SMF_SYSTEM_ERR;
506da6c28aaSamw 		}
507da6c28aaSamw 	} else {
508da6c28aaSamw 		ret = SMBD_SMF_SYSTEM_ERR;
509da6c28aaSamw 	}
510da6c28aaSamw 	if (ret == SMBD_SMF_SYSTEM_ERR) {
511da6c28aaSamw 		switch (scf_error()) {
512da6c28aaSamw 		case SCF_ERROR_PERMISSION_DENIED:
513da6c28aaSamw 			ret = SMBD_SMF_NO_PERMISSION;
514da6c28aaSamw 			break;
515da6c28aaSamw 		}
516da6c28aaSamw 	}
517da6c28aaSamw 	/*
518da6c28aaSamw 	 * cleanup if there were any errors that didn't leave these
519da6c28aaSamw 	 * values where they would be cleaned up later.
520da6c28aaSamw 	 */
521da6c28aaSamw 	if (value != NULL)
522da6c28aaSamw 		scf_value_destroy(value);
523da6c28aaSamw 	if (entry != NULL)
524da6c28aaSamw 		scf_entry_destroy(entry);
525da6c28aaSamw 	return (ret);
526da6c28aaSamw }
527da6c28aaSamw 
528da6c28aaSamw /*
529da6c28aaSamw  * Gets a blob property value.
530da6c28aaSamw  * Caller is responsible to have enough memory allocated.
531da6c28aaSamw  */
532da6c28aaSamw int
smb_smf_get_opaque_property(smb_scfhandle_t * handle,char * propname,void * v,size_t sz)533da6c28aaSamw smb_smf_get_opaque_property(smb_scfhandle_t *handle, char *propname,
534da6c28aaSamw     void *v, size_t sz)
535da6c28aaSamw {
536da6c28aaSamw 	int ret = SMBD_SMF_OK;
537da6c28aaSamw 	scf_value_t *value = NULL;
538da6c28aaSamw 	scf_property_t *prop = NULL;
539da6c28aaSamw 
540da6c28aaSamw 	if (handle == NULL)
541da6c28aaSamw 		return (SMBD_SMF_SYSTEM_ERR);
542da6c28aaSamw 
543da6c28aaSamw 	value = scf_value_create(handle->scf_handle);
544da6c28aaSamw 	prop = scf_property_create(handle->scf_handle);
545da6c28aaSamw 	if ((prop) && (value) &&
546da6c28aaSamw 	    (scf_pg_get_property(handle->scf_pg, propname, prop) == 0)) {
547da6c28aaSamw 		if (scf_property_get_value(prop, value) == 0) {
548da6c28aaSamw 			if (scf_value_get_opaque(value, (char *)v, sz) != sz) {
549da6c28aaSamw 				ret = SMBD_SMF_SYSTEM_ERR;
550da6c28aaSamw 			}
551da6c28aaSamw 		} else {
552da6c28aaSamw 			ret = SMBD_SMF_SYSTEM_ERR;
553da6c28aaSamw 		}
554da6c28aaSamw 	} else {
555da6c28aaSamw 		ret = SMBD_SMF_SYSTEM_ERR;
556da6c28aaSamw 	}
557da6c28aaSamw 	if (value != NULL)
558da6c28aaSamw 		scf_value_destroy(value);
559da6c28aaSamw 	if (prop != NULL)
560da6c28aaSamw 		scf_property_destroy(prop);
561da6c28aaSamw 	return (ret);
562da6c28aaSamw }
563da6c28aaSamw 
564da6c28aaSamw /*
5658d7e4166Sjose borrego  * Put the smb service into maintenance mode.
5668d7e4166Sjose borrego  */
5678d7e4166Sjose borrego int
smb_smf_maintenance_mode(void)5688d7e4166Sjose borrego smb_smf_maintenance_mode(void)
5698d7e4166Sjose borrego {
5708d7e4166Sjose borrego 	return (smf_maintain_instance(SMBD_DEFAULT_INSTANCE_FMRI, 0));
5718d7e4166Sjose borrego }
5728d7e4166Sjose borrego 
5738d7e4166Sjose borrego /*
5748d7e4166Sjose borrego  * Restart the smb service.
575c8ec8eeaSjose borrego  */
576c8ec8eeaSjose borrego int
smb_smf_restart_service(void)577c8ec8eeaSjose borrego smb_smf_restart_service(void)
578c8ec8eeaSjose borrego {
579c8ec8eeaSjose borrego 	return (smf_restart_instance(SMBD_DEFAULT_INSTANCE_FMRI));
580c8ec8eeaSjose borrego }
581c8ec8eeaSjose borrego 
582c8ec8eeaSjose borrego /*
583da6c28aaSamw  * smb_smf_scf_init()
584da6c28aaSamw  *
585da6c28aaSamw  * must be called before using any of the SCF functions.
586da6c28aaSamw  * Returns smb_scfhandle_t pointer if success.
587da6c28aaSamw  */
588da6c28aaSamw smb_scfhandle_t *
smb_smf_scf_init(char * svc_name)589da6c28aaSamw smb_smf_scf_init(char *svc_name)
590da6c28aaSamw {
591da6c28aaSamw 	smb_scfhandle_t *handle;
592da6c28aaSamw 
593da6c28aaSamw 	handle = malloc(sizeof (smb_scfhandle_t));
594da6c28aaSamw 	if (handle != NULL) {
595da6c28aaSamw 		bzero((char *)handle, sizeof (smb_scfhandle_t));
596da6c28aaSamw 		handle->scf_state = SCH_STATE_INITIALIZING;
597da6c28aaSamw 		handle->scf_handle = scf_handle_create(SCF_VERSION);
598da6c28aaSamw 		if (handle->scf_handle != NULL) {
599da6c28aaSamw 			if (scf_handle_bind(handle->scf_handle) == 0) {
600da6c28aaSamw 				handle->scf_scope =
601da6c28aaSamw 				    scf_scope_create(handle->scf_handle);
6027b59d02dSjb150015 
6037b59d02dSjb150015 				if (handle->scf_scope == NULL)
6047b59d02dSjb150015 					goto err;
6057b59d02dSjb150015 
606da6c28aaSamw 				if (scf_handle_get_local_scope(
607da6c28aaSamw 				    handle->scf_handle, handle->scf_scope) != 0)
608da6c28aaSamw 					goto err;
609da6c28aaSamw 
610da6c28aaSamw 				handle->scf_service =
611da6c28aaSamw 				    scf_service_create(handle->scf_handle);
612da6c28aaSamw 
6137b59d02dSjb150015 				if (handle->scf_service == NULL)
6147b59d02dSjb150015 					goto err;
6157b59d02dSjb150015 
616da6c28aaSamw 				if (scf_scope_get_service(handle->scf_scope,
617da6c28aaSamw 				    svc_name, handle->scf_service)
618da6c28aaSamw 				    != SCF_SUCCESS) {
619da6c28aaSamw 					goto err;
620da6c28aaSamw 				}
621da6c28aaSamw 				handle->scf_pg =
622da6c28aaSamw 				    scf_pg_create(handle->scf_handle);
6237b59d02dSjb150015 
6247b59d02dSjb150015 				if (handle->scf_pg == NULL)
6257b59d02dSjb150015 					goto err;
6267b59d02dSjb150015 
627da6c28aaSamw 				handle->scf_state = SCH_STATE_INIT;
628da6c28aaSamw 			} else {
629da6c28aaSamw 				goto err;
630da6c28aaSamw 			}
631da6c28aaSamw 		} else {
632da6c28aaSamw 			free(handle);
633da6c28aaSamw 			handle = NULL;
634da6c28aaSamw 			smb_smf_scf_log_error("Could not access SMF "
635da6c28aaSamw 			    "repository: %s\n");
636da6c28aaSamw 		}
637da6c28aaSamw 	}
638da6c28aaSamw 	return (handle);
639da6c28aaSamw 
640da6c28aaSamw 	/* error handling/unwinding */
641da6c28aaSamw err:
642da6c28aaSamw 	(void) smb_smf_scf_fini(handle);
643da6c28aaSamw 	(void) smb_smf_scf_log_error("SMF initialization problem: %s\n");
644da6c28aaSamw 	return (NULL);
645da6c28aaSamw }
646da6c28aaSamw 
647da6c28aaSamw /*
648da6c28aaSamw  * smb_smf_scf_fini(handle)
649da6c28aaSamw  *
650da6c28aaSamw  * must be called when done. Called with the handle allocated in
651da6c28aaSamw  * smb_smf_scf_init(), it cleans up the state and frees any SCF resources
652da6c28aaSamw  * still in use.
653da6c28aaSamw  */
654da6c28aaSamw void
smb_smf_scf_fini(smb_scfhandle_t * handle)655da6c28aaSamw smb_smf_scf_fini(smb_scfhandle_t *handle)
656da6c28aaSamw {
657da6c28aaSamw 	if (handle != NULL) {
658da6c28aaSamw 		int unbind = 0;
659da6c28aaSamw 		scf_iter_destroy(handle->scf_pg_iter);
660da6c28aaSamw 		handle->scf_pg_iter = NULL;
661da6c28aaSamw 
662da6c28aaSamw 		scf_iter_destroy(handle->scf_inst_iter);
663da6c28aaSamw 		handle->scf_inst_iter = NULL;
664da6c28aaSamw 
665da6c28aaSamw 		unbind = 1;
666da6c28aaSamw 		scf_scope_destroy(handle->scf_scope);
667da6c28aaSamw 		handle->scf_scope = NULL;
668da6c28aaSamw 
669da6c28aaSamw 		scf_instance_destroy(handle->scf_instance);
670da6c28aaSamw 		handle->scf_instance = NULL;
671da6c28aaSamw 
672da6c28aaSamw 		scf_service_destroy(handle->scf_service);
673da6c28aaSamw 		handle->scf_service = NULL;
674da6c28aaSamw 
675da6c28aaSamw 		scf_pg_destroy(handle->scf_pg);
676da6c28aaSamw 		handle->scf_pg = NULL;
677da6c28aaSamw 
678da6c28aaSamw 		handle->scf_state = SCH_STATE_UNINIT;
679da6c28aaSamw 		if (unbind)
680da6c28aaSamw 			(void) scf_handle_unbind(handle->scf_handle);
681da6c28aaSamw 		scf_handle_destroy(handle->scf_handle);
682da6c28aaSamw 		handle->scf_handle = NULL;
683da6c28aaSamw 
684da6c28aaSamw 		free(handle);
685da6c28aaSamw 	}
686da6c28aaSamw }
687