xref: /titanic_50/usr/src/lib/smbsrv/libsmb/common/smb_scfutil.c (revision a90cf9f29973990687fa61de9f1f6ea22e924e40)
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.
24b819cea2SGordon Ross  *
25*a90cf9f2SGordon Ross  * Copyright 2015 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 {
52b819cea2SGordon Ross 	if (msg == NULL)
53b819cea2SGordon Ross 		msg = "SMBD SMF problem";
54b819cea2SGordon Ross 
55b819cea2SGordon 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;
158*a90cf9f2SGordon Ross 	int rc;
159da6c28aaSamw 
160da6c28aaSamw 	if (handle == NULL)
161da6c28aaSamw 		return (SMBD_SMF_SYSTEM_ERR);
162da6c28aaSamw 
163da6c28aaSamw 	if (handle->scf_trans == NULL) {
164da6c28aaSamw 		ret = SMBD_SMF_SYSTEM_ERR;
165da6c28aaSamw 	} else {
166*a90cf9f2SGordon Ross 		rc = scf_transaction_commit(handle->scf_trans);
167*a90cf9f2SGordon Ross 		if (rc == 1) {
168*a90cf9f2SGordon Ross 			ret = SMBD_SMF_OK;
169*a90cf9f2SGordon Ross 		} else if (rc == 0) {
170*a90cf9f2SGordon Ross 			ret = SMBD_SMF_INVALID_ARG;
171*a90cf9f2SGordon Ross 			smb_smf_scf_log_error("Failed to commit, old pg: "
172*a90cf9f2SGordon Ross 			    "transaction: %s");
173*a90cf9f2SGordon Ross 		} else {
174da6c28aaSamw 			ret = SMBD_SMF_SYSTEM_ERR;
175*a90cf9f2SGordon Ross 			smb_smf_scf_log_error("Failed to commit, error: "
176da6c28aaSamw 			    "transaction: %s");
177da6c28aaSamw 		}
178da6c28aaSamw 		scf_transaction_destroy_children(handle->scf_trans);
179da6c28aaSamw 		scf_transaction_destroy(handle->scf_trans);
180da6c28aaSamw 		handle->scf_trans = NULL;
181da6c28aaSamw 	}
182da6c28aaSamw 	return (ret);
183da6c28aaSamw }
184da6c28aaSamw 
185da6c28aaSamw /*
186da6c28aaSamw  * Sets string property in current pg
187da6c28aaSamw  */
188da6c28aaSamw int
smb_smf_set_string_property(smb_scfhandle_t * handle,char * propname,char * valstr)189da6c28aaSamw smb_smf_set_string_property(smb_scfhandle_t *handle,
190da6c28aaSamw     char *propname, char *valstr)
191da6c28aaSamw {
192da6c28aaSamw 	int ret = SMBD_SMF_OK;
193da6c28aaSamw 	scf_value_t *value = NULL;
194da6c28aaSamw 	scf_transaction_entry_t *entry = NULL;
195da6c28aaSamw 
196da6c28aaSamw 	if (handle == NULL)
197da6c28aaSamw 		return (SMBD_SMF_SYSTEM_ERR);
198da6c28aaSamw 
199da6c28aaSamw 	/*
200da6c28aaSamw 	 * properties must be set in transactions and don't take
201da6c28aaSamw 	 * effect until the transaction has been ended/committed.
202da6c28aaSamw 	 */
203da6c28aaSamw 	value = scf_value_create(handle->scf_handle);
204da6c28aaSamw 	entry = scf_entry_create(handle->scf_handle);
205da6c28aaSamw 	if (value != NULL && entry != NULL) {
206da6c28aaSamw 		if (scf_transaction_property_change(handle->scf_trans, entry,
207da6c28aaSamw 		    propname, SCF_TYPE_ASTRING) == 0 ||
208da6c28aaSamw 		    scf_transaction_property_new(handle->scf_trans, entry,
209da6c28aaSamw 		    propname, SCF_TYPE_ASTRING) == 0) {
210da6c28aaSamw 			if (scf_value_set_astring(value, valstr) == 0) {
211da6c28aaSamw 				if (scf_entry_add_value(entry, value) != 0) {
212da6c28aaSamw 					ret = SMBD_SMF_SYSTEM_ERR;
213da6c28aaSamw 					scf_value_destroy(value);
214da6c28aaSamw 				}
215da6c28aaSamw 				/* the value is in the transaction */
216da6c28aaSamw 				value = NULL;
217da6c28aaSamw 			} else {
218da6c28aaSamw 				/* value couldn't be constructed */
219da6c28aaSamw 				ret = SMBD_SMF_SYSTEM_ERR;
220da6c28aaSamw 			}
221da6c28aaSamw 			/* the entry is in the transaction */
222da6c28aaSamw 			entry = NULL;
223da6c28aaSamw 		} else {
224da6c28aaSamw 			ret = SMBD_SMF_SYSTEM_ERR;
225da6c28aaSamw 		}
226da6c28aaSamw 	} else {
227da6c28aaSamw 		ret = SMBD_SMF_SYSTEM_ERR;
228da6c28aaSamw 	}
229da6c28aaSamw 	if (ret == SMBD_SMF_SYSTEM_ERR) {
230da6c28aaSamw 		switch (scf_error()) {
231da6c28aaSamw 		case SCF_ERROR_PERMISSION_DENIED:
232da6c28aaSamw 			ret = SMBD_SMF_NO_PERMISSION;
233da6c28aaSamw 			break;
234da6c28aaSamw 		}
235da6c28aaSamw 	}
236da6c28aaSamw 
237da6c28aaSamw 	/*
238da6c28aaSamw 	 * cleanup if there were any errors that didn't leave these
239da6c28aaSamw 	 * values where they would be cleaned up later.
240da6c28aaSamw 	 */
241da6c28aaSamw 	if (value != NULL)
242da6c28aaSamw 		scf_value_destroy(value);
243da6c28aaSamw 	if (entry != NULL)
244da6c28aaSamw 		scf_entry_destroy(entry);
245da6c28aaSamw 	return (ret);
246da6c28aaSamw }
247da6c28aaSamw 
248da6c28aaSamw /*
249da6c28aaSamw  * Gets string property value.upto sz size.
250da6c28aaSamw  * Caller is responsible to have enough memory allocated.
251da6c28aaSamw  */
252da6c28aaSamw int
smb_smf_get_string_property(smb_scfhandle_t * handle,char * propname,char * valstr,size_t sz)253da6c28aaSamw smb_smf_get_string_property(smb_scfhandle_t *handle, char *propname,
254da6c28aaSamw     char *valstr, size_t sz)
255da6c28aaSamw {
256da6c28aaSamw 	int ret = SMBD_SMF_OK;
257da6c28aaSamw 	scf_value_t *value;
258da6c28aaSamw 	scf_property_t *prop;
259da6c28aaSamw 
260da6c28aaSamw 	if (handle == NULL)
261da6c28aaSamw 		return (SMBD_SMF_SYSTEM_ERR);
262da6c28aaSamw 
263da6c28aaSamw 	value = scf_value_create(handle->scf_handle);
264da6c28aaSamw 	prop = scf_property_create(handle->scf_handle);
265da6c28aaSamw 	if (value && prop &&
266da6c28aaSamw 	    (scf_pg_get_property(handle->scf_pg, propname, prop) == 0)) {
267da6c28aaSamw 		if (scf_property_get_value(prop, value) == 0) {
268da6c28aaSamw 			if (scf_value_get_astring(value, valstr, sz) < 0) {
269da6c28aaSamw 				ret = SMBD_SMF_SYSTEM_ERR;
270da6c28aaSamw 			}
271da6c28aaSamw 		} else {
272da6c28aaSamw 			ret = SMBD_SMF_SYSTEM_ERR;
273da6c28aaSamw 		}
274da6c28aaSamw 	} else {
275da6c28aaSamw 		ret = SMBD_SMF_SYSTEM_ERR;
276da6c28aaSamw 	}
277da6c28aaSamw 	if (value != NULL)
278da6c28aaSamw 		scf_value_destroy(value);
279da6c28aaSamw 	if (prop != NULL)
280da6c28aaSamw 		scf_property_destroy(prop);
281da6c28aaSamw 	return (ret);
282da6c28aaSamw }
283da6c28aaSamw 
284da6c28aaSamw /*
285da6c28aaSamw  * Set integer value of property.
286da6c28aaSamw  * The value is returned as int64_t value
287da6c28aaSamw  * Caller ensures appropriate translation.
288da6c28aaSamw  */
289da6c28aaSamw int
smb_smf_set_integer_property(smb_scfhandle_t * handle,char * propname,int64_t valint)290da6c28aaSamw smb_smf_set_integer_property(smb_scfhandle_t *handle, char *propname,
291da6c28aaSamw     int64_t valint)
292da6c28aaSamw {
293da6c28aaSamw 	int ret = SMBD_SMF_OK;
294da6c28aaSamw 	scf_value_t *value = NULL;
295da6c28aaSamw 	scf_transaction_entry_t *entry = NULL;
296da6c28aaSamw 
297da6c28aaSamw 	if (handle == NULL)
298da6c28aaSamw 		return (SMBD_SMF_SYSTEM_ERR);
299da6c28aaSamw 
300da6c28aaSamw 	/*
301da6c28aaSamw 	 * properties must be set in transactions and don't take
302da6c28aaSamw 	 * effect until the transaction has been ended/committed.
303da6c28aaSamw 	 */
304da6c28aaSamw 	value = scf_value_create(handle->scf_handle);
305da6c28aaSamw 	entry = scf_entry_create(handle->scf_handle);
306da6c28aaSamw 	if (value != NULL && entry != NULL) {
307da6c28aaSamw 		if (scf_transaction_property_change(handle->scf_trans, entry,
308da6c28aaSamw 		    propname, SCF_TYPE_INTEGER) == 0 ||
309da6c28aaSamw 		    scf_transaction_property_new(handle->scf_trans, entry,
310da6c28aaSamw 		    propname, SCF_TYPE_INTEGER) == 0) {
311da6c28aaSamw 			scf_value_set_integer(value, valint);
312da6c28aaSamw 			if (scf_entry_add_value(entry, value) != 0) {
313da6c28aaSamw 				ret = SMBD_SMF_SYSTEM_ERR;
314da6c28aaSamw 				scf_value_destroy(value);
315da6c28aaSamw 			}
316da6c28aaSamw 			/* the value is in the transaction */
317da6c28aaSamw 			value = NULL;
318da6c28aaSamw 		}
319da6c28aaSamw 		/* the entry is in the transaction */
320da6c28aaSamw 		entry = NULL;
321da6c28aaSamw 	} else {
322da6c28aaSamw 		ret = SMBD_SMF_SYSTEM_ERR;
323da6c28aaSamw 	}
324da6c28aaSamw 	if (ret == SMBD_SMF_SYSTEM_ERR) {
325da6c28aaSamw 		switch (scf_error()) {
326da6c28aaSamw 		case SCF_ERROR_PERMISSION_DENIED:
327da6c28aaSamw 			ret = SMBD_SMF_NO_PERMISSION;
328da6c28aaSamw 			break;
329da6c28aaSamw 		}
330da6c28aaSamw 	}
331da6c28aaSamw 	/*
332da6c28aaSamw 	 * cleanup if there were any errors that didn't leave these
333da6c28aaSamw 	 * values where they would be cleaned up later.
334da6c28aaSamw 	 */
335da6c28aaSamw 	if (value != NULL)
336da6c28aaSamw 		scf_value_destroy(value);
337da6c28aaSamw 	if (entry != NULL)
338da6c28aaSamw 		scf_entry_destroy(entry);
339da6c28aaSamw 	return (ret);
340da6c28aaSamw }
341da6c28aaSamw 
342da6c28aaSamw /*
343da6c28aaSamw  * Gets integer property value.
344da6c28aaSamw  * Caller is responsible to have enough memory allocated.
345da6c28aaSamw  */
346da6c28aaSamw int
smb_smf_get_integer_property(smb_scfhandle_t * handle,char * propname,int64_t * valint)347da6c28aaSamw smb_smf_get_integer_property(smb_scfhandle_t *handle, char *propname,
348da6c28aaSamw     int64_t *valint)
349da6c28aaSamw {
350da6c28aaSamw 	int ret = SMBD_SMF_OK;
351da6c28aaSamw 	scf_value_t *value = NULL;
352da6c28aaSamw 	scf_property_t *prop = NULL;
353da6c28aaSamw 
354da6c28aaSamw 	if (handle == NULL)
355da6c28aaSamw 		return (SMBD_SMF_SYSTEM_ERR);
356da6c28aaSamw 
357da6c28aaSamw 	value = scf_value_create(handle->scf_handle);
358da6c28aaSamw 	prop = scf_property_create(handle->scf_handle);
359da6c28aaSamw 	if ((prop) && (value) &&
360da6c28aaSamw 	    (scf_pg_get_property(handle->scf_pg, propname, prop) == 0)) {
361da6c28aaSamw 		if (scf_property_get_value(prop, value) == 0) {
362da6c28aaSamw 			if (scf_value_get_integer(value,
363da6c28aaSamw 			    valint) != 0) {
364da6c28aaSamw 				ret = SMBD_SMF_SYSTEM_ERR;
365da6c28aaSamw 			}
366da6c28aaSamw 		} else {
367da6c28aaSamw 			ret = SMBD_SMF_SYSTEM_ERR;
368da6c28aaSamw 		}
369da6c28aaSamw 	} else {
370da6c28aaSamw 		ret = SMBD_SMF_SYSTEM_ERR;
371da6c28aaSamw 	}
372da6c28aaSamw 	if (value != NULL)
373da6c28aaSamw 		scf_value_destroy(value);
374da6c28aaSamw 	if (prop != NULL)
375da6c28aaSamw 		scf_property_destroy(prop);
376da6c28aaSamw 	return (ret);
377da6c28aaSamw }
378da6c28aaSamw 
379da6c28aaSamw /*
380da6c28aaSamw  * Set boolean value of property.
381da6c28aaSamw  * The value is returned as int64_t value
382da6c28aaSamw  * Caller ensures appropriate translation.
383da6c28aaSamw  */
384da6c28aaSamw int
smb_smf_set_boolean_property(smb_scfhandle_t * handle,char * propname,uint8_t valbool)385da6c28aaSamw smb_smf_set_boolean_property(smb_scfhandle_t *handle, char *propname,
386da6c28aaSamw     uint8_t valbool)
387da6c28aaSamw {
388da6c28aaSamw 	int ret = SMBD_SMF_OK;
389da6c28aaSamw 	scf_value_t *value = NULL;
390da6c28aaSamw 	scf_transaction_entry_t *entry = NULL;
391da6c28aaSamw 
392da6c28aaSamw 	if (handle == NULL)
393da6c28aaSamw 		return (SMBD_SMF_SYSTEM_ERR);
394da6c28aaSamw 
395da6c28aaSamw 	/*
396da6c28aaSamw 	 * properties must be set in transactions and don't take
397da6c28aaSamw 	 * effect until the transaction has been ended/committed.
398da6c28aaSamw 	 */
399da6c28aaSamw 	value = scf_value_create(handle->scf_handle);
400da6c28aaSamw 	entry = scf_entry_create(handle->scf_handle);
401da6c28aaSamw 	if (value != NULL && entry != NULL) {
402da6c28aaSamw 		if (scf_transaction_property_change(handle->scf_trans, entry,
403da6c28aaSamw 		    propname, SCF_TYPE_BOOLEAN) == 0 ||
404da6c28aaSamw 		    scf_transaction_property_new(handle->scf_trans, entry,
405da6c28aaSamw 		    propname, SCF_TYPE_BOOLEAN) == 0) {
406da6c28aaSamw 			scf_value_set_boolean(value, valbool);
407da6c28aaSamw 			if (scf_entry_add_value(entry, value) != 0) {
408da6c28aaSamw 				ret = SMBD_SMF_SYSTEM_ERR;
409da6c28aaSamw 				scf_value_destroy(value);
410da6c28aaSamw 			}
411da6c28aaSamw 			/* the value is in the transaction */
412da6c28aaSamw 			value = NULL;
413da6c28aaSamw 		}
414da6c28aaSamw 		/* the entry is in the transaction */
415da6c28aaSamw 		entry = NULL;
416da6c28aaSamw 	} else {
417da6c28aaSamw 		ret = SMBD_SMF_SYSTEM_ERR;
418da6c28aaSamw 	}
419da6c28aaSamw 	if (ret == SMBD_SMF_SYSTEM_ERR) {
420da6c28aaSamw 		switch (scf_error()) {
421da6c28aaSamw 		case SCF_ERROR_PERMISSION_DENIED:
422da6c28aaSamw 			ret = SMBD_SMF_NO_PERMISSION;
423da6c28aaSamw 			break;
424da6c28aaSamw 		}
425da6c28aaSamw 	}
426da6c28aaSamw 	/*
427da6c28aaSamw 	 * cleanup if there were any errors that didn't leave these
428da6c28aaSamw 	 * values where they would be cleaned up later.
429da6c28aaSamw 	 */
430da6c28aaSamw 	if (value != NULL)
431da6c28aaSamw 		scf_value_destroy(value);
432da6c28aaSamw 	if (entry != NULL)
433da6c28aaSamw 		scf_entry_destroy(entry);
434da6c28aaSamw 	return (ret);
435da6c28aaSamw }
436da6c28aaSamw 
437da6c28aaSamw /*
438da6c28aaSamw  * Gets boolean property value.
439da6c28aaSamw  * Caller is responsible to have enough memory allocated.
440da6c28aaSamw  */
441da6c28aaSamw int
smb_smf_get_boolean_property(smb_scfhandle_t * handle,char * propname,uint8_t * valbool)442da6c28aaSamw smb_smf_get_boolean_property(smb_scfhandle_t *handle, char *propname,
443da6c28aaSamw     uint8_t *valbool)
444da6c28aaSamw {
445da6c28aaSamw 	int ret = SMBD_SMF_OK;
446da6c28aaSamw 	scf_value_t *value = NULL;
447da6c28aaSamw 	scf_property_t *prop = NULL;
448da6c28aaSamw 
449da6c28aaSamw 	if (handle == NULL)
450da6c28aaSamw 		return (SMBD_SMF_SYSTEM_ERR);
451da6c28aaSamw 
452da6c28aaSamw 	value = scf_value_create(handle->scf_handle);
453da6c28aaSamw 	prop = scf_property_create(handle->scf_handle);
454da6c28aaSamw 	if ((prop) && (value) &&
455da6c28aaSamw 	    (scf_pg_get_property(handle->scf_pg, propname, prop) == 0)) {
456da6c28aaSamw 		if (scf_property_get_value(prop, value) == 0) {
457da6c28aaSamw 			if (scf_value_get_boolean(value,
458da6c28aaSamw 			    valbool) != 0) {
459da6c28aaSamw 				ret = SMBD_SMF_SYSTEM_ERR;
460da6c28aaSamw 			}
461da6c28aaSamw 		} else {
462da6c28aaSamw 			ret = SMBD_SMF_SYSTEM_ERR;
463da6c28aaSamw 		}
464da6c28aaSamw 	} else {
465da6c28aaSamw 		ret = SMBD_SMF_SYSTEM_ERR;
466da6c28aaSamw 	}
467da6c28aaSamw 	if (value != NULL)
468da6c28aaSamw 		scf_value_destroy(value);
469da6c28aaSamw 	if (prop != NULL)
470da6c28aaSamw 		scf_property_destroy(prop);
471da6c28aaSamw 	return (ret);
472da6c28aaSamw }
473da6c28aaSamw 
474da6c28aaSamw /*
475da6c28aaSamw  * Sets a blob property value.
476da6c28aaSamw  */
477da6c28aaSamw int
smb_smf_set_opaque_property(smb_scfhandle_t * handle,char * propname,void * voidval,size_t sz)478da6c28aaSamw smb_smf_set_opaque_property(smb_scfhandle_t *handle, char *propname,
479da6c28aaSamw     void *voidval, size_t sz)
480da6c28aaSamw {
481da6c28aaSamw 	int ret = SMBD_SMF_OK;
482da6c28aaSamw 	scf_value_t *value;
483da6c28aaSamw 	scf_transaction_entry_t *entry;
484da6c28aaSamw 
485da6c28aaSamw 	if (handle == NULL)
486da6c28aaSamw 		return (SMBD_SMF_SYSTEM_ERR);
487da6c28aaSamw 
488da6c28aaSamw 	/*
489da6c28aaSamw 	 * properties must be set in transactions and don't take
490da6c28aaSamw 	 * effect until the transaction has been ended/committed.
491da6c28aaSamw 	 */
492da6c28aaSamw 	value = scf_value_create(handle->scf_handle);
493da6c28aaSamw 	entry = scf_entry_create(handle->scf_handle);
494da6c28aaSamw 	if (value != NULL && entry != NULL) {
495da6c28aaSamw 		if (scf_transaction_property_change(handle->scf_trans, entry,
496da6c28aaSamw 		    propname, SCF_TYPE_OPAQUE) == 0 ||
497da6c28aaSamw 		    scf_transaction_property_new(handle->scf_trans, entry,
498da6c28aaSamw 		    propname, SCF_TYPE_OPAQUE) == 0) {
499da6c28aaSamw 			if (scf_value_set_opaque(value, voidval, sz) == 0) {
500da6c28aaSamw 				if (scf_entry_add_value(entry, value) != 0) {
501da6c28aaSamw 					ret = SMBD_SMF_SYSTEM_ERR;
502da6c28aaSamw 					scf_value_destroy(value);
503da6c28aaSamw 				}
504da6c28aaSamw 				/* the value is in the transaction */
505da6c28aaSamw 				value = NULL;
506da6c28aaSamw 			} else {
507da6c28aaSamw 				/* value couldn't be constructed */
508da6c28aaSamw 				ret = SMBD_SMF_SYSTEM_ERR;
509da6c28aaSamw 			}
510da6c28aaSamw 			/* the entry is in the transaction */
511da6c28aaSamw 			entry = NULL;
512da6c28aaSamw 		} else {
513da6c28aaSamw 			ret = SMBD_SMF_SYSTEM_ERR;
514da6c28aaSamw 		}
515da6c28aaSamw 	} else {
516da6c28aaSamw 		ret = SMBD_SMF_SYSTEM_ERR;
517da6c28aaSamw 	}
518da6c28aaSamw 	if (ret == SMBD_SMF_SYSTEM_ERR) {
519da6c28aaSamw 		switch (scf_error()) {
520da6c28aaSamw 		case SCF_ERROR_PERMISSION_DENIED:
521da6c28aaSamw 			ret = SMBD_SMF_NO_PERMISSION;
522da6c28aaSamw 			break;
523da6c28aaSamw 		}
524da6c28aaSamw 	}
525da6c28aaSamw 	/*
526da6c28aaSamw 	 * cleanup if there were any errors that didn't leave these
527da6c28aaSamw 	 * values where they would be cleaned up later.
528da6c28aaSamw 	 */
529da6c28aaSamw 	if (value != NULL)
530da6c28aaSamw 		scf_value_destroy(value);
531da6c28aaSamw 	if (entry != NULL)
532da6c28aaSamw 		scf_entry_destroy(entry);
533da6c28aaSamw 	return (ret);
534da6c28aaSamw }
535da6c28aaSamw 
536da6c28aaSamw /*
537da6c28aaSamw  * Gets a blob property value.
538da6c28aaSamw  * Caller is responsible to have enough memory allocated.
539da6c28aaSamw  */
540da6c28aaSamw int
smb_smf_get_opaque_property(smb_scfhandle_t * handle,char * propname,void * v,size_t sz)541da6c28aaSamw smb_smf_get_opaque_property(smb_scfhandle_t *handle, char *propname,
542da6c28aaSamw     void *v, size_t sz)
543da6c28aaSamw {
544da6c28aaSamw 	int ret = SMBD_SMF_OK;
545da6c28aaSamw 	scf_value_t *value = NULL;
546da6c28aaSamw 	scf_property_t *prop = NULL;
547da6c28aaSamw 
548da6c28aaSamw 	if (handle == NULL)
549da6c28aaSamw 		return (SMBD_SMF_SYSTEM_ERR);
550da6c28aaSamw 
551da6c28aaSamw 	value = scf_value_create(handle->scf_handle);
552da6c28aaSamw 	prop = scf_property_create(handle->scf_handle);
553da6c28aaSamw 	if ((prop) && (value) &&
554da6c28aaSamw 	    (scf_pg_get_property(handle->scf_pg, propname, prop) == 0)) {
555da6c28aaSamw 		if (scf_property_get_value(prop, value) == 0) {
556da6c28aaSamw 			if (scf_value_get_opaque(value, (char *)v, sz) != sz) {
557da6c28aaSamw 				ret = SMBD_SMF_SYSTEM_ERR;
558da6c28aaSamw 			}
559da6c28aaSamw 		} else {
560da6c28aaSamw 			ret = SMBD_SMF_SYSTEM_ERR;
561da6c28aaSamw 		}
562da6c28aaSamw 	} else {
563da6c28aaSamw 		ret = SMBD_SMF_SYSTEM_ERR;
564da6c28aaSamw 	}
565da6c28aaSamw 	if (value != NULL)
566da6c28aaSamw 		scf_value_destroy(value);
567da6c28aaSamw 	if (prop != NULL)
568da6c28aaSamw 		scf_property_destroy(prop);
569da6c28aaSamw 	return (ret);
570da6c28aaSamw }
571da6c28aaSamw 
572da6c28aaSamw /*
573*a90cf9f2SGordon Ross  * Delete a property (for properties obsoleted during an upgrade).
574*a90cf9f2SGordon Ross  */
575*a90cf9f2SGordon Ross int
smb_smf_delete_property(smb_scfhandle_t * handle,char * propname)576*a90cf9f2SGordon Ross smb_smf_delete_property(smb_scfhandle_t *handle, char *propname)
577*a90cf9f2SGordon Ross {
578*a90cf9f2SGordon Ross 	scf_transaction_entry_t *entry;
579*a90cf9f2SGordon Ross 	int ret = SMBD_SMF_OK;
580*a90cf9f2SGordon Ross 
581*a90cf9f2SGordon Ross 	if (handle == NULL)
582*a90cf9f2SGordon Ross 		return (SMBD_SMF_SYSTEM_ERR);
583*a90cf9f2SGordon Ross 	if (handle->scf_trans == NULL)
584*a90cf9f2SGordon Ross 		return (SMBD_SMF_SYSTEM_ERR);
585*a90cf9f2SGordon Ross 
586*a90cf9f2SGordon Ross 	/*
587*a90cf9f2SGordon Ross 	 * properties must be set in transactions and don't take
588*a90cf9f2SGordon Ross 	 * effect until the transaction has been ended/committed.
589*a90cf9f2SGordon Ross 	 */
590*a90cf9f2SGordon Ross 	entry = scf_entry_create(handle->scf_handle);
591*a90cf9f2SGordon Ross 	if (entry == NULL) {
592*a90cf9f2SGordon Ross 		ret = SMBD_SMF_SYSTEM_ERR;
593*a90cf9f2SGordon Ross 		goto out;
594*a90cf9f2SGordon Ross 	}
595*a90cf9f2SGordon Ross 
596*a90cf9f2SGordon Ross 	if (scf_transaction_property_delete(handle->scf_trans,
597*a90cf9f2SGordon Ross 	    entry, propname) == 0) {
598*a90cf9f2SGordon Ross 		/* the entry is in the transaction */
599*a90cf9f2SGordon Ross 		entry = NULL;
600*a90cf9f2SGordon Ross 	} else {
601*a90cf9f2SGordon Ross 		switch (scf_error()) {
602*a90cf9f2SGordon Ross 		case SCF_ERROR_NOT_FOUND:
603*a90cf9f2SGordon Ross 			/* Did not exist.  We're done. */
604*a90cf9f2SGordon Ross 			ret = SMBD_SMF_OK;
605*a90cf9f2SGordon Ross 			goto out;
606*a90cf9f2SGordon Ross 		case SCF_ERROR_PERMISSION_DENIED:
607*a90cf9f2SGordon Ross 			ret = SMBD_SMF_NO_PERMISSION;
608*a90cf9f2SGordon Ross 			goto out;
609*a90cf9f2SGordon Ross 		default:
610*a90cf9f2SGordon Ross 			ret = SMBD_SMF_SYSTEM_ERR;
611*a90cf9f2SGordon Ross 			goto out;
612*a90cf9f2SGordon Ross 		}
613*a90cf9f2SGordon Ross 	}
614*a90cf9f2SGordon Ross 
615*a90cf9f2SGordon Ross out:
616*a90cf9f2SGordon Ross 	scf_entry_destroy(entry);
617*a90cf9f2SGordon Ross 	return (ret);
618*a90cf9f2SGordon Ross }
619*a90cf9f2SGordon Ross 
620*a90cf9f2SGordon Ross /*
6218d7e4166Sjose borrego  * Put the smb service into maintenance mode.
6228d7e4166Sjose borrego  */
6238d7e4166Sjose borrego int
smb_smf_maintenance_mode(void)6248d7e4166Sjose borrego smb_smf_maintenance_mode(void)
6258d7e4166Sjose borrego {
6268d7e4166Sjose borrego 	return (smf_maintain_instance(SMBD_DEFAULT_INSTANCE_FMRI, 0));
6278d7e4166Sjose borrego }
6288d7e4166Sjose borrego 
6298d7e4166Sjose borrego /*
6308d7e4166Sjose borrego  * Restart the smb service.
631c8ec8eeaSjose borrego  */
632c8ec8eeaSjose borrego int
smb_smf_restart_service(void)633c8ec8eeaSjose borrego smb_smf_restart_service(void)
634c8ec8eeaSjose borrego {
635c8ec8eeaSjose borrego 	return (smf_restart_instance(SMBD_DEFAULT_INSTANCE_FMRI));
636c8ec8eeaSjose borrego }
637c8ec8eeaSjose borrego 
638c8ec8eeaSjose borrego /*
639da6c28aaSamw  * smb_smf_scf_init()
640da6c28aaSamw  *
641da6c28aaSamw  * must be called before using any of the SCF functions.
642da6c28aaSamw  * Returns smb_scfhandle_t pointer if success.
643da6c28aaSamw  */
644da6c28aaSamw smb_scfhandle_t *
smb_smf_scf_init(char * svc_name)645da6c28aaSamw smb_smf_scf_init(char *svc_name)
646da6c28aaSamw {
647da6c28aaSamw 	smb_scfhandle_t *handle;
648da6c28aaSamw 
649da6c28aaSamw 	handle = malloc(sizeof (smb_scfhandle_t));
650da6c28aaSamw 	if (handle != NULL) {
651da6c28aaSamw 		bzero((char *)handle, sizeof (smb_scfhandle_t));
652da6c28aaSamw 		handle->scf_state = SCH_STATE_INITIALIZING;
653da6c28aaSamw 		handle->scf_handle = scf_handle_create(SCF_VERSION);
654da6c28aaSamw 		if (handle->scf_handle != NULL) {
655da6c28aaSamw 			if (scf_handle_bind(handle->scf_handle) == 0) {
656da6c28aaSamw 				handle->scf_scope =
657da6c28aaSamw 				    scf_scope_create(handle->scf_handle);
6587b59d02dSjb150015 
6597b59d02dSjb150015 				if (handle->scf_scope == NULL)
6607b59d02dSjb150015 					goto err;
6617b59d02dSjb150015 
662da6c28aaSamw 				if (scf_handle_get_local_scope(
663da6c28aaSamw 				    handle->scf_handle, handle->scf_scope) != 0)
664da6c28aaSamw 					goto err;
665da6c28aaSamw 
666da6c28aaSamw 				handle->scf_service =
667da6c28aaSamw 				    scf_service_create(handle->scf_handle);
668da6c28aaSamw 
6697b59d02dSjb150015 				if (handle->scf_service == NULL)
6707b59d02dSjb150015 					goto err;
6717b59d02dSjb150015 
672da6c28aaSamw 				if (scf_scope_get_service(handle->scf_scope,
673da6c28aaSamw 				    svc_name, handle->scf_service)
674da6c28aaSamw 				    != SCF_SUCCESS) {
675da6c28aaSamw 					goto err;
676da6c28aaSamw 				}
677da6c28aaSamw 				handle->scf_pg =
678da6c28aaSamw 				    scf_pg_create(handle->scf_handle);
6797b59d02dSjb150015 
6807b59d02dSjb150015 				if (handle->scf_pg == NULL)
6817b59d02dSjb150015 					goto err;
6827b59d02dSjb150015 
683da6c28aaSamw 				handle->scf_state = SCH_STATE_INIT;
684da6c28aaSamw 			} else {
685da6c28aaSamw 				goto err;
686da6c28aaSamw 			}
687da6c28aaSamw 		} else {
688da6c28aaSamw 			free(handle);
689da6c28aaSamw 			handle = NULL;
690da6c28aaSamw 			smb_smf_scf_log_error("Could not access SMF "
691da6c28aaSamw 			    "repository: %s\n");
692da6c28aaSamw 		}
693da6c28aaSamw 	}
694da6c28aaSamw 	return (handle);
695da6c28aaSamw 
696da6c28aaSamw 	/* error handling/unwinding */
697da6c28aaSamw err:
698da6c28aaSamw 	(void) smb_smf_scf_fini(handle);
699da6c28aaSamw 	(void) smb_smf_scf_log_error("SMF initialization problem: %s\n");
700da6c28aaSamw 	return (NULL);
701da6c28aaSamw }
702da6c28aaSamw 
703da6c28aaSamw /*
704da6c28aaSamw  * smb_smf_scf_fini(handle)
705da6c28aaSamw  *
706da6c28aaSamw  * must be called when done. Called with the handle allocated in
707da6c28aaSamw  * smb_smf_scf_init(), it cleans up the state and frees any SCF resources
708da6c28aaSamw  * still in use.
709da6c28aaSamw  */
710da6c28aaSamw void
smb_smf_scf_fini(smb_scfhandle_t * handle)711da6c28aaSamw smb_smf_scf_fini(smb_scfhandle_t *handle)
712da6c28aaSamw {
713da6c28aaSamw 	if (handle != NULL) {
714da6c28aaSamw 		int unbind = 0;
715da6c28aaSamw 		scf_iter_destroy(handle->scf_pg_iter);
716da6c28aaSamw 		handle->scf_pg_iter = NULL;
717da6c28aaSamw 
718da6c28aaSamw 		scf_iter_destroy(handle->scf_inst_iter);
719da6c28aaSamw 		handle->scf_inst_iter = NULL;
720da6c28aaSamw 
721da6c28aaSamw 		unbind = 1;
722da6c28aaSamw 		scf_scope_destroy(handle->scf_scope);
723da6c28aaSamw 		handle->scf_scope = NULL;
724da6c28aaSamw 
725da6c28aaSamw 		scf_instance_destroy(handle->scf_instance);
726da6c28aaSamw 		handle->scf_instance = NULL;
727da6c28aaSamw 
728da6c28aaSamw 		scf_service_destroy(handle->scf_service);
729da6c28aaSamw 		handle->scf_service = NULL;
730da6c28aaSamw 
731da6c28aaSamw 		scf_pg_destroy(handle->scf_pg);
732da6c28aaSamw 		handle->scf_pg = NULL;
733da6c28aaSamw 
734da6c28aaSamw 		handle->scf_state = SCH_STATE_UNINIT;
735da6c28aaSamw 		if (unbind)
736da6c28aaSamw 			(void) scf_handle_unbind(handle->scf_handle);
737da6c28aaSamw 		scf_handle_destroy(handle->scf_handle);
738da6c28aaSamw 		handle->scf_handle = NULL;
739da6c28aaSamw 
740da6c28aaSamw 		free(handle);
741da6c28aaSamw 	}
742da6c28aaSamw }
743