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