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 /*
22dc20a302Sas * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23da6c28aaSamw * Use is subject to license terms.
24b819cea2SGordon Ross *
25a90cf9f2SGordon Ross * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
26327e8b4bSAndy Fiddaman * Copyright 2023 Oxide Computer Company
27da6c28aaSamw */
28da6c28aaSamw
29da6c28aaSamw /* helper functions for using libscf with CIFS */
30da6c28aaSamw
31da6c28aaSamw #include <libscf.h>
32da6c28aaSamw #include <string.h>
33da6c28aaSamw #include <stdio.h>
34da6c28aaSamw #include <stdlib.h>
35da6c28aaSamw #include <syslog.h>
36da6c28aaSamw #include <errno.h>
37da6c28aaSamw #include <libintl.h>
38da6c28aaSamw #include <assert.h>
39da6c28aaSamw #include <strings.h>
40da6c28aaSamw
41da6c28aaSamw #include <uuid/uuid.h>
42da6c28aaSamw #include <sys/param.h>
43da6c28aaSamw
44da6c28aaSamw #include <smbsrv/libsmb.h>
45da6c28aaSamw
46da6c28aaSamw /*
47da6c28aaSamw * smb_smf_scf_log_error(msg)
48da6c28aaSamw * Logs error messages from scf API's
49da6c28aaSamw */
50da6c28aaSamw static void
smb_smf_scf_log_error(char * msg)51da6c28aaSamw smb_smf_scf_log_error(char *msg)
52da6c28aaSamw {
53b819cea2SGordon Ross if (msg == NULL)
54c79c9de5SAndy Fiddaman msg = "SMBD SMF problems";
55b819cea2SGordon Ross
56c79c9de5SAndy Fiddaman syslog(LOG_ERR, "%s: %s", msg, scf_strerror(scf_error()));
57da6c28aaSamw }
58da6c28aaSamw
59da6c28aaSamw /*
60da6c28aaSamw * smb_smf_create_service_pgroup(handle, pgroup)
61da6c28aaSamw *
62da6c28aaSamw * create a new property group at service level.
63da6c28aaSamw */
64da6c28aaSamw int
smb_smf_create_service_pgroup(smb_scfhandle_t * handle,char * pgroup)65da6c28aaSamw smb_smf_create_service_pgroup(smb_scfhandle_t *handle, char *pgroup)
66da6c28aaSamw {
67da6c28aaSamw int ret = SMBD_SMF_OK;
68da6c28aaSamw int err;
69da6c28aaSamw
707b59d02dSjb if (handle == NULL)
71da6c28aaSamw return (SMBD_SMF_SYSTEM_ERR);
72da6c28aaSamw
73da6c28aaSamw /*
74da6c28aaSamw * only create a handle if it doesn't exist. It is ok to exist
75da6c28aaSamw * since the pg handle will be set as a side effect.
76da6c28aaSamw */
77da6c28aaSamw if (handle->scf_pg == NULL)
787b59d02dSjb if ((handle->scf_pg =
797b59d02dSjb scf_pg_create(handle->scf_handle)) == NULL)
807b59d02dSjb return (SMBD_SMF_SYSTEM_ERR);
81da6c28aaSamw
82da6c28aaSamw /*
83da6c28aaSamw * if the pgroup exists, we are done. If it doesn't, then we
84da6c28aaSamw * need to actually add one to the service instance.
85da6c28aaSamw */
86da6c28aaSamw if (scf_service_get_pg(handle->scf_service,
87da6c28aaSamw pgroup, handle->scf_pg) != 0) {
88da6c28aaSamw /* doesn't exist so create one */
89da6c28aaSamw if (scf_service_add_pg(handle->scf_service, pgroup,
90da6c28aaSamw SCF_GROUP_APPLICATION, 0, handle->scf_pg) != 0) {
91da6c28aaSamw err = scf_error();
92da6c28aaSamw if (err != SCF_ERROR_NONE)
93da6c28aaSamw smb_smf_scf_log_error(NULL);
94da6c28aaSamw switch (err) {
95da6c28aaSamw case SCF_ERROR_PERMISSION_DENIED:
96da6c28aaSamw ret = SMBD_SMF_NO_PERMISSION;
97da6c28aaSamw break;
98da6c28aaSamw default:
99da6c28aaSamw ret = SMBD_SMF_SYSTEM_ERR;
100da6c28aaSamw break;
101da6c28aaSamw }
102da6c28aaSamw }
103da6c28aaSamw }
104da6c28aaSamw return (ret);
105da6c28aaSamw }
106da6c28aaSamw
107da6c28aaSamw /*
108da6c28aaSamw * Start transaction on current pg in handle.
109da6c28aaSamw * The pg could be service or instance level.
110da6c28aaSamw * Must be called after pg handle is obtained
111da6c28aaSamw * from create or get.
112da6c28aaSamw */
113da6c28aaSamw int
smb_smf_start_transaction(smb_scfhandle_t * handle)114da6c28aaSamw smb_smf_start_transaction(smb_scfhandle_t *handle)
115da6c28aaSamw {
116da6c28aaSamw int ret = SMBD_SMF_OK;
117da6c28aaSamw
118da6c28aaSamw if (!handle || (!handle->scf_pg))
119da6c28aaSamw return (SMBD_SMF_SYSTEM_ERR);
120da6c28aaSamw
121da6c28aaSamw /*
122da6c28aaSamw * lookup the property group and create it if it doesn't already
123da6c28aaSamw * exist.
124da6c28aaSamw */
125da6c28aaSamw if (handle->scf_state == SCH_STATE_INIT) {
126da6c28aaSamw if (ret == SMBD_SMF_OK) {
127da6c28aaSamw handle->scf_trans =
128da6c28aaSamw scf_transaction_create(handle->scf_handle);
129da6c28aaSamw if (handle->scf_trans != NULL) {
130da6c28aaSamw if (scf_transaction_start(handle->scf_trans,
131da6c28aaSamw handle->scf_pg) != 0) {
132da6c28aaSamw ret = SMBD_SMF_SYSTEM_ERR;
133da6c28aaSamw scf_transaction_destroy(
134da6c28aaSamw handle->scf_trans);
135da6c28aaSamw handle->scf_trans = NULL;
136da6c28aaSamw }
137da6c28aaSamw } else {
138da6c28aaSamw ret = SMBD_SMF_SYSTEM_ERR;
139da6c28aaSamw }
140da6c28aaSamw }
141da6c28aaSamw }
142da6c28aaSamw if (ret == SMBD_SMF_SYSTEM_ERR &&
143da6c28aaSamw scf_error() == SCF_ERROR_PERMISSION_DENIED)
144da6c28aaSamw ret = SMBD_SMF_NO_PERMISSION;
145da6c28aaSamw
146da6c28aaSamw return (ret);
147da6c28aaSamw }
148da6c28aaSamw
149da6c28aaSamw /*
150da6c28aaSamw * smb_smf_end_transaction(handle)
151da6c28aaSamw *
152da6c28aaSamw * Commit the changes that were added to the transaction in the
153da6c28aaSamw * handle. Do all necessary cleanup.
154da6c28aaSamw */
155da6c28aaSamw int
smb_smf_end_transaction(smb_scfhandle_t * handle)156da6c28aaSamw smb_smf_end_transaction(smb_scfhandle_t *handle)
157da6c28aaSamw {
158da6c28aaSamw int ret = SMBD_SMF_OK;
159a90cf9f2SGordon Ross int rc;
160da6c28aaSamw
161da6c28aaSamw if (handle == NULL)
162da6c28aaSamw return (SMBD_SMF_SYSTEM_ERR);
163da6c28aaSamw
164da6c28aaSamw if (handle->scf_trans == NULL) {
165da6c28aaSamw ret = SMBD_SMF_SYSTEM_ERR;
166da6c28aaSamw } else {
167a90cf9f2SGordon Ross rc = scf_transaction_commit(handle->scf_trans);
168a90cf9f2SGordon Ross if (rc == 1) {
169a90cf9f2SGordon Ross ret = SMBD_SMF_OK;
170a90cf9f2SGordon Ross } else if (rc == 0) {
171a90cf9f2SGordon Ross ret = SMBD_SMF_INVALID_ARG;
172c79c9de5SAndy Fiddaman smb_smf_scf_log_error(
173c79c9de5SAndy Fiddaman "Failed to commit, old pg: transaction");
174a90cf9f2SGordon Ross } else {
175da6c28aaSamw ret = SMBD_SMF_SYSTEM_ERR;
176c79c9de5SAndy Fiddaman smb_smf_scf_log_error(
177c79c9de5SAndy Fiddaman "Failed to commit, error: transaction");
178da6c28aaSamw }
179da6c28aaSamw scf_transaction_destroy_children(handle->scf_trans);
180da6c28aaSamw scf_transaction_destroy(handle->scf_trans);
181da6c28aaSamw handle->scf_trans = NULL;
182da6c28aaSamw }
183da6c28aaSamw return (ret);
184da6c28aaSamw }
185da6c28aaSamw
186da6c28aaSamw /*
187da6c28aaSamw * Sets string property in current pg
188da6c28aaSamw */
189da6c28aaSamw int
smb_smf_set_string_property(smb_scfhandle_t * handle,char * propname,char * valstr)190da6c28aaSamw smb_smf_set_string_property(smb_scfhandle_t *handle,
191da6c28aaSamw char *propname, char *valstr)
192da6c28aaSamw {
193da6c28aaSamw int ret = SMBD_SMF_OK;
194da6c28aaSamw scf_value_t *value = NULL;
195da6c28aaSamw scf_transaction_entry_t *entry = NULL;
196da6c28aaSamw
197da6c28aaSamw if (handle == NULL)
198da6c28aaSamw return (SMBD_SMF_SYSTEM_ERR);
199da6c28aaSamw
200da6c28aaSamw /*
201da6c28aaSamw * properties must be set in transactions and don't take
202da6c28aaSamw * effect until the transaction has been ended/committed.
203da6c28aaSamw */
204da6c28aaSamw value = scf_value_create(handle->scf_handle);
205da6c28aaSamw entry = scf_entry_create(handle->scf_handle);
206da6c28aaSamw if (value != NULL && entry != NULL) {
207da6c28aaSamw if (scf_transaction_property_change(handle->scf_trans, entry,
208da6c28aaSamw propname, SCF_TYPE_ASTRING) == 0 ||
209da6c28aaSamw scf_transaction_property_new(handle->scf_trans, entry,
210da6c28aaSamw propname, SCF_TYPE_ASTRING) == 0) {
211da6c28aaSamw if (scf_value_set_astring(value, valstr) == 0) {
212da6c28aaSamw if (scf_entry_add_value(entry, value) != 0) {
213da6c28aaSamw ret = SMBD_SMF_SYSTEM_ERR;
214da6c28aaSamw scf_value_destroy(value);
215da6c28aaSamw }
216da6c28aaSamw /* the value is in the transaction */
217da6c28aaSamw value = NULL;
218da6c28aaSamw } else {
219da6c28aaSamw /* value couldn't be constructed */
220da6c28aaSamw ret = SMBD_SMF_SYSTEM_ERR;
221da6c28aaSamw }
222da6c28aaSamw /* the entry is in the transaction */
223da6c28aaSamw entry = NULL;
224da6c28aaSamw } else {
225da6c28aaSamw ret = SMBD_SMF_SYSTEM_ERR;
226da6c28aaSamw }
227da6c28aaSamw } else {
228da6c28aaSamw ret = SMBD_SMF_SYSTEM_ERR;
229da6c28aaSamw }
230da6c28aaSamw if (ret == SMBD_SMF_SYSTEM_ERR) {
231*2bc647a2SToomas Soome if (scf_error() == SCF_ERROR_PERMISSION_DENIED) {
232da6c28aaSamw ret = SMBD_SMF_NO_PERMISSION;
233da6c28aaSamw }
234da6c28aaSamw }
235da6c28aaSamw
236da6c28aaSamw /*
237da6c28aaSamw * cleanup if there were any errors that didn't leave these
238da6c28aaSamw * values where they would be cleaned up later.
239da6c28aaSamw */
240da6c28aaSamw if (value != NULL)
241da6c28aaSamw scf_value_destroy(value);
242da6c28aaSamw if (entry != NULL)
243da6c28aaSamw scf_entry_destroy(entry);
244da6c28aaSamw return (ret);
245da6c28aaSamw }
246da6c28aaSamw
247da6c28aaSamw /*
248da6c28aaSamw * Gets string property value.upto sz size.
249da6c28aaSamw * Caller is responsible to have enough memory allocated.
250da6c28aaSamw */
251da6c28aaSamw int
smb_smf_get_string_property(smb_scfhandle_t * handle,char * propname,char * valstr,size_t sz)252da6c28aaSamw smb_smf_get_string_property(smb_scfhandle_t *handle, char *propname,
253da6c28aaSamw char *valstr, size_t sz)
254da6c28aaSamw {
255da6c28aaSamw int ret = SMBD_SMF_OK;
256da6c28aaSamw scf_value_t *value;
257da6c28aaSamw scf_property_t *prop;
258da6c28aaSamw
259da6c28aaSamw if (handle == NULL)
260da6c28aaSamw return (SMBD_SMF_SYSTEM_ERR);
261da6c28aaSamw
262da6c28aaSamw value = scf_value_create(handle->scf_handle);
263da6c28aaSamw prop = scf_property_create(handle->scf_handle);
264da6c28aaSamw if (value && prop &&
265da6c28aaSamw (scf_pg_get_property(handle->scf_pg, propname, prop) == 0)) {
266da6c28aaSamw if (scf_property_get_value(prop, value) == 0) {
267da6c28aaSamw if (scf_value_get_astring(value, valstr, sz) < 0) {
268da6c28aaSamw ret = SMBD_SMF_SYSTEM_ERR;
269da6c28aaSamw }
270da6c28aaSamw } else {
271da6c28aaSamw ret = SMBD_SMF_SYSTEM_ERR;
272da6c28aaSamw }
273da6c28aaSamw } else {
274da6c28aaSamw ret = SMBD_SMF_SYSTEM_ERR;
275da6c28aaSamw }
276da6c28aaSamw if (value != NULL)
277da6c28aaSamw scf_value_destroy(value);
278da6c28aaSamw if (prop != NULL)
279da6c28aaSamw scf_property_destroy(prop);
280da6c28aaSamw return (ret);
281da6c28aaSamw }
282da6c28aaSamw
283da6c28aaSamw /*
284da6c28aaSamw * Set integer value of property.
285da6c28aaSamw * The value is returned as int64_t value
286da6c28aaSamw * Caller ensures appropriate translation.
287da6c28aaSamw */
288da6c28aaSamw int
smb_smf_set_integer_property(smb_scfhandle_t * handle,char * propname,int64_t valint)289da6c28aaSamw smb_smf_set_integer_property(smb_scfhandle_t *handle, char *propname,
290da6c28aaSamw int64_t valint)
291da6c28aaSamw {
292da6c28aaSamw int ret = SMBD_SMF_OK;
293da6c28aaSamw scf_value_t *value = NULL;
294da6c28aaSamw scf_transaction_entry_t *entry = NULL;
295da6c28aaSamw
296da6c28aaSamw if (handle == NULL)
297da6c28aaSamw return (SMBD_SMF_SYSTEM_ERR);
298da6c28aaSamw
299da6c28aaSamw /*
300da6c28aaSamw * properties must be set in transactions and don't take
301da6c28aaSamw * effect until the transaction has been ended/committed.
302da6c28aaSamw */
303da6c28aaSamw value = scf_value_create(handle->scf_handle);
304da6c28aaSamw entry = scf_entry_create(handle->scf_handle);
305da6c28aaSamw if (value != NULL && entry != NULL) {
306da6c28aaSamw if (scf_transaction_property_change(handle->scf_trans, entry,
307da6c28aaSamw propname, SCF_TYPE_INTEGER) == 0 ||
308da6c28aaSamw scf_transaction_property_new(handle->scf_trans, entry,
309da6c28aaSamw propname, SCF_TYPE_INTEGER) == 0) {
310da6c28aaSamw scf_value_set_integer(value, valint);
311da6c28aaSamw if (scf_entry_add_value(entry, value) != 0) {
312da6c28aaSamw ret = SMBD_SMF_SYSTEM_ERR;
313da6c28aaSamw scf_value_destroy(value);
314da6c28aaSamw }
315da6c28aaSamw /* the value is in the transaction */
316da6c28aaSamw value = NULL;
317da6c28aaSamw }
318da6c28aaSamw /* the entry is in the transaction */
319da6c28aaSamw entry = NULL;
320da6c28aaSamw } else {
321da6c28aaSamw ret = SMBD_SMF_SYSTEM_ERR;
322da6c28aaSamw }
323da6c28aaSamw if (ret == SMBD_SMF_SYSTEM_ERR) {
324*2bc647a2SToomas Soome if (scf_error() == SCF_ERROR_PERMISSION_DENIED) {
325da6c28aaSamw ret = SMBD_SMF_NO_PERMISSION;
326da6c28aaSamw }
327da6c28aaSamw }
328da6c28aaSamw /*
329da6c28aaSamw * cleanup if there were any errors that didn't leave these
330da6c28aaSamw * values where they would be cleaned up later.
331da6c28aaSamw */
332da6c28aaSamw if (value != NULL)
333da6c28aaSamw scf_value_destroy(value);
334da6c28aaSamw if (entry != NULL)
335da6c28aaSamw scf_entry_destroy(entry);
336da6c28aaSamw return (ret);
337da6c28aaSamw }
338da6c28aaSamw
339da6c28aaSamw /*
340da6c28aaSamw * Gets integer property value.
341da6c28aaSamw * Caller is responsible to have enough memory allocated.
342da6c28aaSamw */
343da6c28aaSamw int
smb_smf_get_integer_property(smb_scfhandle_t * handle,char * propname,int64_t * valint)344da6c28aaSamw smb_smf_get_integer_property(smb_scfhandle_t *handle, char *propname,
345da6c28aaSamw int64_t *valint)
346da6c28aaSamw {
347da6c28aaSamw int ret = SMBD_SMF_OK;
348da6c28aaSamw scf_value_t *value = NULL;
349da6c28aaSamw scf_property_t *prop = NULL;
350da6c28aaSamw
351da6c28aaSamw if (handle == NULL)
352da6c28aaSamw return (SMBD_SMF_SYSTEM_ERR);
353da6c28aaSamw
354da6c28aaSamw value = scf_value_create(handle->scf_handle);
355da6c28aaSamw prop = scf_property_create(handle->scf_handle);
356da6c28aaSamw if ((prop) && (value) &&
357da6c28aaSamw (scf_pg_get_property(handle->scf_pg, propname, prop) == 0)) {
358da6c28aaSamw if (scf_property_get_value(prop, value) == 0) {
359da6c28aaSamw if (scf_value_get_integer(value,
360da6c28aaSamw valint) != 0) {
361da6c28aaSamw ret = SMBD_SMF_SYSTEM_ERR;
362da6c28aaSamw }
363da6c28aaSamw } else {
364da6c28aaSamw ret = SMBD_SMF_SYSTEM_ERR;
365da6c28aaSamw }
366da6c28aaSamw } else {
367da6c28aaSamw ret = SMBD_SMF_SYSTEM_ERR;
368da6c28aaSamw }
369da6c28aaSamw if (value != NULL)
370da6c28aaSamw scf_value_destroy(value);
371da6c28aaSamw if (prop != NULL)
372da6c28aaSamw scf_property_destroy(prop);
373da6c28aaSamw return (ret);
374da6c28aaSamw }
375da6c28aaSamw
376da6c28aaSamw /*
377da6c28aaSamw * Set boolean value of property.
378da6c28aaSamw * The value is returned as int64_t value
379da6c28aaSamw * Caller ensures appropriate translation.
380da6c28aaSamw */
381da6c28aaSamw int
smb_smf_set_boolean_property(smb_scfhandle_t * handle,char * propname,uint8_t valbool)382da6c28aaSamw smb_smf_set_boolean_property(smb_scfhandle_t *handle, char *propname,
383da6c28aaSamw uint8_t valbool)
384da6c28aaSamw {
385da6c28aaSamw int ret = SMBD_SMF_OK;
386da6c28aaSamw scf_value_t *value = NULL;
387da6c28aaSamw scf_transaction_entry_t *entry = NULL;
388da6c28aaSamw
389da6c28aaSamw if (handle == NULL)
390da6c28aaSamw return (SMBD_SMF_SYSTEM_ERR);
391da6c28aaSamw
392da6c28aaSamw /*
393da6c28aaSamw * properties must be set in transactions and don't take
394da6c28aaSamw * effect until the transaction has been ended/committed.
395da6c28aaSamw */
396da6c28aaSamw value = scf_value_create(handle->scf_handle);
397da6c28aaSamw entry = scf_entry_create(handle->scf_handle);
398da6c28aaSamw if (value != NULL && entry != NULL) {
399da6c28aaSamw if (scf_transaction_property_change(handle->scf_trans, entry,
400da6c28aaSamw propname, SCF_TYPE_BOOLEAN) == 0 ||
401da6c28aaSamw scf_transaction_property_new(handle->scf_trans, entry,
402da6c28aaSamw propname, SCF_TYPE_BOOLEAN) == 0) {
403da6c28aaSamw scf_value_set_boolean(value, valbool);
404da6c28aaSamw if (scf_entry_add_value(entry, value) != 0) {
405da6c28aaSamw ret = SMBD_SMF_SYSTEM_ERR;
406da6c28aaSamw scf_value_destroy(value);
407da6c28aaSamw }
408da6c28aaSamw /* the value is in the transaction */
409da6c28aaSamw value = NULL;
410da6c28aaSamw }
411da6c28aaSamw /* the entry is in the transaction */
412da6c28aaSamw entry = NULL;
413da6c28aaSamw } else {
414da6c28aaSamw ret = SMBD_SMF_SYSTEM_ERR;
415da6c28aaSamw }
416da6c28aaSamw if (ret == SMBD_SMF_SYSTEM_ERR) {
417*2bc647a2SToomas Soome if (scf_error() == SCF_ERROR_PERMISSION_DENIED) {
418da6c28aaSamw ret = SMBD_SMF_NO_PERMISSION;
419da6c28aaSamw }
420da6c28aaSamw }
421da6c28aaSamw /*
422da6c28aaSamw * cleanup if there were any errors that didn't leave these
423da6c28aaSamw * values where they would be cleaned up later.
424da6c28aaSamw */
425da6c28aaSamw if (value != NULL)
426da6c28aaSamw scf_value_destroy(value);
427da6c28aaSamw if (entry != NULL)
428da6c28aaSamw scf_entry_destroy(entry);
429da6c28aaSamw return (ret);
430da6c28aaSamw }
431da6c28aaSamw
432da6c28aaSamw /*
433da6c28aaSamw * Gets boolean property value.
434da6c28aaSamw * Caller is responsible to have enough memory allocated.
435da6c28aaSamw */
436da6c28aaSamw int
smb_smf_get_boolean_property(smb_scfhandle_t * handle,char * propname,uint8_t * valbool)437da6c28aaSamw smb_smf_get_boolean_property(smb_scfhandle_t *handle, char *propname,
438da6c28aaSamw uint8_t *valbool)
439da6c28aaSamw {
440da6c28aaSamw int ret = SMBD_SMF_OK;
441da6c28aaSamw scf_value_t *value = NULL;
442da6c28aaSamw scf_property_t *prop = NULL;
443da6c28aaSamw
444da6c28aaSamw if (handle == NULL)
445da6c28aaSamw return (SMBD_SMF_SYSTEM_ERR);
446da6c28aaSamw
447da6c28aaSamw value = scf_value_create(handle->scf_handle);
448da6c28aaSamw prop = scf_property_create(handle->scf_handle);
449da6c28aaSamw if ((prop) && (value) &&
450da6c28aaSamw (scf_pg_get_property(handle->scf_pg, propname, prop) == 0)) {
451da6c28aaSamw if (scf_property_get_value(prop, value) == 0) {
452da6c28aaSamw if (scf_value_get_boolean(value,
453da6c28aaSamw valbool) != 0) {
454da6c28aaSamw ret = SMBD_SMF_SYSTEM_ERR;
455da6c28aaSamw }
456da6c28aaSamw } else {
457da6c28aaSamw ret = SMBD_SMF_SYSTEM_ERR;
458da6c28aaSamw }
459da6c28aaSamw } else {
460da6c28aaSamw ret = SMBD_SMF_SYSTEM_ERR;
461da6c28aaSamw }
462da6c28aaSamw if (value != NULL)
463da6c28aaSamw scf_value_destroy(value);
464da6c28aaSamw if (prop != NULL)
465da6c28aaSamw scf_property_destroy(prop);
466da6c28aaSamw return (ret);
467da6c28aaSamw }
468da6c28aaSamw
469da6c28aaSamw /*
470da6c28aaSamw * Sets a blob property value.
471da6c28aaSamw */
472da6c28aaSamw int
smb_smf_set_opaque_property(smb_scfhandle_t * handle,char * propname,void * voidval,size_t sz)473da6c28aaSamw smb_smf_set_opaque_property(smb_scfhandle_t *handle, char *propname,
474da6c28aaSamw void *voidval, size_t sz)
475da6c28aaSamw {
476da6c28aaSamw int ret = SMBD_SMF_OK;
477da6c28aaSamw scf_value_t *value;
478da6c28aaSamw scf_transaction_entry_t *entry;
479da6c28aaSamw
480da6c28aaSamw if (handle == NULL)
481da6c28aaSamw return (SMBD_SMF_SYSTEM_ERR);
482da6c28aaSamw
483da6c28aaSamw /*
484da6c28aaSamw * properties must be set in transactions and don't take
485da6c28aaSamw * effect until the transaction has been ended/committed.
486da6c28aaSamw */
487da6c28aaSamw value = scf_value_create(handle->scf_handle);
488da6c28aaSamw entry = scf_entry_create(handle->scf_handle);
489da6c28aaSamw if (value != NULL && entry != NULL) {
490da6c28aaSamw if (scf_transaction_property_change(handle->scf_trans, entry,
491da6c28aaSamw propname, SCF_TYPE_OPAQUE) == 0 ||
492da6c28aaSamw scf_transaction_property_new(handle->scf_trans, entry,
493da6c28aaSamw propname, SCF_TYPE_OPAQUE) == 0) {
494da6c28aaSamw if (scf_value_set_opaque(value, voidval, sz) == 0) {
495da6c28aaSamw if (scf_entry_add_value(entry, value) != 0) {
496da6c28aaSamw ret = SMBD_SMF_SYSTEM_ERR;
497da6c28aaSamw scf_value_destroy(value);
498da6c28aaSamw }
499da6c28aaSamw /* the value is in the transaction */
500da6c28aaSamw value = NULL;
501da6c28aaSamw } else {
502da6c28aaSamw /* value couldn't be constructed */
503da6c28aaSamw ret = SMBD_SMF_SYSTEM_ERR;
504da6c28aaSamw }
505da6c28aaSamw /* the entry is in the transaction */
506da6c28aaSamw entry = NULL;
507da6c28aaSamw } else {
508da6c28aaSamw ret = SMBD_SMF_SYSTEM_ERR;
509da6c28aaSamw }
510da6c28aaSamw } else {
511da6c28aaSamw ret = SMBD_SMF_SYSTEM_ERR;
512da6c28aaSamw }
513da6c28aaSamw if (ret == SMBD_SMF_SYSTEM_ERR) {
514*2bc647a2SToomas Soome if (scf_error() == SCF_ERROR_PERMISSION_DENIED) {
515da6c28aaSamw ret = SMBD_SMF_NO_PERMISSION;
516da6c28aaSamw }
517da6c28aaSamw }
518da6c28aaSamw /*
519da6c28aaSamw * cleanup if there were any errors that didn't leave these
520da6c28aaSamw * values where they would be cleaned up later.
521da6c28aaSamw */
522da6c28aaSamw if (value != NULL)
523da6c28aaSamw scf_value_destroy(value);
524da6c28aaSamw if (entry != NULL)
525da6c28aaSamw scf_entry_destroy(entry);
526da6c28aaSamw return (ret);
527da6c28aaSamw }
528da6c28aaSamw
529da6c28aaSamw /*
530da6c28aaSamw * Gets a blob property value.
531da6c28aaSamw * Caller is responsible to have enough memory allocated.
532da6c28aaSamw */
533da6c28aaSamw int
smb_smf_get_opaque_property(smb_scfhandle_t * handle,char * propname,void * v,size_t sz)534da6c28aaSamw smb_smf_get_opaque_property(smb_scfhandle_t *handle, char *propname,
535da6c28aaSamw void *v, size_t sz)
536da6c28aaSamw {
537da6c28aaSamw int ret = SMBD_SMF_OK;
538da6c28aaSamw scf_value_t *value = NULL;
539da6c28aaSamw scf_property_t *prop = NULL;
540da6c28aaSamw
541da6c28aaSamw if (handle == NULL)
542da6c28aaSamw return (SMBD_SMF_SYSTEM_ERR);
543da6c28aaSamw
544da6c28aaSamw value = scf_value_create(handle->scf_handle);
545da6c28aaSamw prop = scf_property_create(handle->scf_handle);
546da6c28aaSamw if ((prop) && (value) &&
547da6c28aaSamw (scf_pg_get_property(handle->scf_pg, propname, prop) == 0)) {
548da6c28aaSamw if (scf_property_get_value(prop, value) == 0) {
549da6c28aaSamw if (scf_value_get_opaque(value, (char *)v, sz) != sz) {
550da6c28aaSamw ret = SMBD_SMF_SYSTEM_ERR;
551da6c28aaSamw }
552da6c28aaSamw } else {
553da6c28aaSamw ret = SMBD_SMF_SYSTEM_ERR;
554da6c28aaSamw }
555da6c28aaSamw } else {
556da6c28aaSamw ret = SMBD_SMF_SYSTEM_ERR;
557da6c28aaSamw }
558da6c28aaSamw if (value != NULL)
559da6c28aaSamw scf_value_destroy(value);
560da6c28aaSamw if (prop != NULL)
561da6c28aaSamw scf_property_destroy(prop);
562da6c28aaSamw return (ret);
563da6c28aaSamw }
564da6c28aaSamw
565a90cf9f2SGordon Ross /*
566a90cf9f2SGordon Ross * Delete a property (for properties obsoleted during an upgrade).
567a90cf9f2SGordon Ross */
568a90cf9f2SGordon Ross int
smb_smf_delete_property(smb_scfhandle_t * handle,char * propname)569a90cf9f2SGordon Ross smb_smf_delete_property(smb_scfhandle_t *handle, char *propname)
570a90cf9f2SGordon Ross {
571a90cf9f2SGordon Ross scf_transaction_entry_t *entry;
572a90cf9f2SGordon Ross int ret = SMBD_SMF_OK;
573a90cf9f2SGordon Ross
574a90cf9f2SGordon Ross if (handle == NULL)
575a90cf9f2SGordon Ross return (SMBD_SMF_SYSTEM_ERR);
576a90cf9f2SGordon Ross if (handle->scf_trans == NULL)
577a90cf9f2SGordon Ross return (SMBD_SMF_SYSTEM_ERR);
578a90cf9f2SGordon Ross
579a90cf9f2SGordon Ross /*
580a90cf9f2SGordon Ross * properties must be set in transactions and don't take
581a90cf9f2SGordon Ross * effect until the transaction has been ended/committed.
582a90cf9f2SGordon Ross */
583a90cf9f2SGordon Ross entry = scf_entry_create(handle->scf_handle);
584a90cf9f2SGordon Ross if (entry == NULL) {
585a90cf9f2SGordon Ross ret = SMBD_SMF_SYSTEM_ERR;
586a90cf9f2SGordon Ross goto out;
587a90cf9f2SGordon Ross }
588a90cf9f2SGordon Ross
589a90cf9f2SGordon Ross if (scf_transaction_property_delete(handle->scf_trans,
590a90cf9f2SGordon Ross entry, propname) == 0) {
591a90cf9f2SGordon Ross /* the entry is in the transaction */
592a90cf9f2SGordon Ross entry = NULL;
593a90cf9f2SGordon Ross } else {
594a90cf9f2SGordon Ross switch (scf_error()) {
595a90cf9f2SGordon Ross case SCF_ERROR_NOT_FOUND:
596a90cf9f2SGordon Ross /* Did not exist. We're done. */
597a90cf9f2SGordon Ross ret = SMBD_SMF_OK;
598a90cf9f2SGordon Ross goto out;
599a90cf9f2SGordon Ross case SCF_ERROR_PERMISSION_DENIED:
600a90cf9f2SGordon Ross ret = SMBD_SMF_NO_PERMISSION;
601a90cf9f2SGordon Ross goto out;
602a90cf9f2SGordon Ross default:
603a90cf9f2SGordon Ross ret = SMBD_SMF_SYSTEM_ERR;
604a90cf9f2SGordon Ross goto out;
605a90cf9f2SGordon Ross }
606a90cf9f2SGordon Ross }
607a90cf9f2SGordon Ross
608a90cf9f2SGordon Ross out:
609a90cf9f2SGordon Ross scf_entry_destroy(entry);
610a90cf9f2SGordon Ross return (ret);
611a90cf9f2SGordon Ross }
612a90cf9f2SGordon Ross
613c8ec8eeaSjose borrego /*
6148d7e4166Sjose borrego * Put the smb service into maintenance mode.
6158d7e4166Sjose borrego */
6168d7e4166Sjose borrego int
smb_smf_maintenance_mode(void)6178d7e4166Sjose borrego smb_smf_maintenance_mode(void)
6188d7e4166Sjose borrego {
6198d7e4166Sjose borrego return (smf_maintain_instance(SMBD_DEFAULT_INSTANCE_FMRI, 0));
6208d7e4166Sjose borrego }
6218d7e4166Sjose borrego
6228d7e4166Sjose borrego /*
6238d7e4166Sjose borrego * Restart the smb service.
624c8ec8eeaSjose borrego */
625c8ec8eeaSjose borrego int
smb_smf_restart_service(void)626c8ec8eeaSjose borrego smb_smf_restart_service(void)
627c8ec8eeaSjose borrego {
628c8ec8eeaSjose borrego return (smf_restart_instance(SMBD_DEFAULT_INSTANCE_FMRI));
629c8ec8eeaSjose borrego }
630c8ec8eeaSjose borrego
631da6c28aaSamw /*
632da6c28aaSamw * smb_smf_scf_init()
633da6c28aaSamw *
634da6c28aaSamw * must be called before using any of the SCF functions.
635da6c28aaSamw * Returns smb_scfhandle_t pointer if success.
636da6c28aaSamw */
637da6c28aaSamw smb_scfhandle_t *
smb_smf_scf_init(char * svc_name)638da6c28aaSamw smb_smf_scf_init(char *svc_name)
639da6c28aaSamw {
640da6c28aaSamw smb_scfhandle_t *handle;
641da6c28aaSamw
642da6c28aaSamw handle = malloc(sizeof (smb_scfhandle_t));
643da6c28aaSamw if (handle != NULL) {
644da6c28aaSamw bzero((char *)handle, sizeof (smb_scfhandle_t));
645da6c28aaSamw handle->scf_state = SCH_STATE_INITIALIZING;
646da6c28aaSamw handle->scf_handle = scf_handle_create(SCF_VERSION);
647da6c28aaSamw if (handle->scf_handle != NULL) {
648da6c28aaSamw if (scf_handle_bind(handle->scf_handle) == 0) {
649da6c28aaSamw handle->scf_scope =
650da6c28aaSamw scf_scope_create(handle->scf_handle);
6517b59d02dSjb
6527b59d02dSjb if (handle->scf_scope == NULL)
6537b59d02dSjb goto err;
6547b59d02dSjb
655da6c28aaSamw if (scf_handle_get_local_scope(
656da6c28aaSamw handle->scf_handle, handle->scf_scope) != 0)
657da6c28aaSamw goto err;
658da6c28aaSamw
659da6c28aaSamw handle->scf_service =
660da6c28aaSamw scf_service_create(handle->scf_handle);
661da6c28aaSamw
6627b59d02dSjb if (handle->scf_service == NULL)
6637b59d02dSjb goto err;
6647b59d02dSjb
665da6c28aaSamw if (scf_scope_get_service(handle->scf_scope,
666da6c28aaSamw svc_name, handle->scf_service)
667da6c28aaSamw != SCF_SUCCESS) {
668da6c28aaSamw goto err;
669da6c28aaSamw }
670da6c28aaSamw handle->scf_pg =
671da6c28aaSamw scf_pg_create(handle->scf_handle);
6727b59d02dSjb
6737b59d02dSjb if (handle->scf_pg == NULL)
6747b59d02dSjb goto err;
6757b59d02dSjb
676da6c28aaSamw handle->scf_state = SCH_STATE_INIT;
677da6c28aaSamw } else {
678da6c28aaSamw goto err;
679da6c28aaSamw }
680da6c28aaSamw } else {
681da6c28aaSamw free(handle);
682da6c28aaSamw handle = NULL;
683c79c9de5SAndy Fiddaman smb_smf_scf_log_error(
684c79c9de5SAndy Fiddaman "Could not access SMF repository");
685da6c28aaSamw }
686da6c28aaSamw }
687da6c28aaSamw return (handle);
688da6c28aaSamw
689da6c28aaSamw /* error handling/unwinding */
690da6c28aaSamw err:
691da6c28aaSamw (void) smb_smf_scf_fini(handle);
692327e8b4bSAndy Fiddaman if (scf_error() != SCF_ERROR_NOT_FOUND)
693327e8b4bSAndy Fiddaman (void) smb_smf_scf_log_error("SMF initialization problem");
694da6c28aaSamw return (NULL);
695da6c28aaSamw }
696da6c28aaSamw
697da6c28aaSamw /*
698da6c28aaSamw * smb_smf_scf_fini(handle)
699da6c28aaSamw *
700da6c28aaSamw * must be called when done. Called with the handle allocated in
701da6c28aaSamw * smb_smf_scf_init(), it cleans up the state and frees any SCF resources
702da6c28aaSamw * still in use.
703da6c28aaSamw */
704da6c28aaSamw void
smb_smf_scf_fini(smb_scfhandle_t * handle)705da6c28aaSamw smb_smf_scf_fini(smb_scfhandle_t *handle)
706da6c28aaSamw {
707da6c28aaSamw if (handle != NULL) {
708da6c28aaSamw int unbind = 0;
709da6c28aaSamw scf_iter_destroy(handle->scf_pg_iter);
710da6c28aaSamw handle->scf_pg_iter = NULL;
711da6c28aaSamw
712da6c28aaSamw scf_iter_destroy(handle->scf_inst_iter);
713da6c28aaSamw handle->scf_inst_iter = NULL;
714da6c28aaSamw
715da6c28aaSamw unbind = 1;
716da6c28aaSamw scf_scope_destroy(handle->scf_scope);
717da6c28aaSamw handle->scf_scope = NULL;
718da6c28aaSamw
719da6c28aaSamw scf_instance_destroy(handle->scf_instance);
720da6c28aaSamw handle->scf_instance = NULL;
721da6c28aaSamw
722da6c28aaSamw scf_service_destroy(handle->scf_service);
723da6c28aaSamw handle->scf_service = NULL;
724da6c28aaSamw
725da6c28aaSamw scf_pg_destroy(handle->scf_pg);
726da6c28aaSamw handle->scf_pg = NULL;
727da6c28aaSamw
728da6c28aaSamw handle->scf_state = SCH_STATE_UNINIT;
729da6c28aaSamw if (unbind)
730da6c28aaSamw (void) scf_handle_unbind(handle->scf_handle);
731da6c28aaSamw scf_handle_destroy(handle->scf_handle);
732da6c28aaSamw handle->scf_handle = NULL;
733da6c28aaSamw
734da6c28aaSamw free(handle);
735da6c28aaSamw }
736da6c28aaSamw }
737