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