xref: /illumos-gate/usr/src/lib/libsmbfs/smb/rc_scf.c (revision 069e6b7e31ba5dcbc5441b98af272714d9a5455c)
1 /*
2  * This file and its contents are supplied under the terms of the
3  * Common Development and Distribution License ("CDDL"), version 1.0.
4  * You may only use this file in accordance with the terms of version
5  * 1.0 of the CDDL.
6  *
7  * A full copy of the text of the CDDL should have accompanied this
8  * source.  A copy of the CDDL is also available via the Internet at
9  * http://www.illumos.org/license/CDDL.
10  */
11 
12 /*
13  * Copyright 2018 Nexenta Systems, Inc.  All rights reserved.
14  */
15 
16 /*
17  * Support functions for getting things libsmbfs needs
18  * from the SMF configuration (using libscf).
19  */
20 
21 #include <sys/types.h>
22 #include <sys/queue.h>
23 
24 #include <ctype.h>
25 #include <errno.h>
26 #include <stdio.h>
27 #include <string.h>
28 #include <strings.h>
29 #include <stdlib.h>
30 #include <unistd.h>
31 #include <libscf.h>
32 
33 #include <cflib.h>
34 #include "rcfile_priv.h"
35 
36 #define	IDMAP_SERVICE_FMRI		"svc:/system/idmap"
37 #define	IDMAP_PG_NAME			"config"
38 #define	MACHINE_UUID			"machine_uuid"
39 
40 #define	SMBC_DEFAULT_INSTANCE_FMRI	"svc:/network/smb/client:default"
41 
42 scf_handle_t *_scf_handle_create_and_bind(scf_version_t ver);
43 
44 /*
45  * Get the "machine_uuid" from idmap, as a string (allocated)
46  */
47 char *
48 cf_get_client_uuid(void)
49 {
50 	char val_buf[64];
51 	char *ret = NULL;
52 
53 	scf_handle_t		*h = NULL;
54 	scf_service_t		*svc = NULL;
55 	scf_propertygroup_t	*pg = NULL;
56 	scf_property_t		*prop = NULL;
57 	scf_value_t		*val = NULL;
58 
59 	if ((h = _scf_handle_create_and_bind(SCF_VERSION)) == NULL)
60 		goto out;
61 
62 	if ((svc = scf_service_create(h)) == NULL ||
63 	    (pg = scf_pg_create(h)) == NULL ||
64 	    (prop = scf_property_create(h)) == NULL ||
65 	    (val = scf_value_create(h)) == NULL)
66 		goto out;
67 
68 	if (scf_handle_decode_fmri(h, IDMAP_SERVICE_FMRI,
69 	    NULL, svc, NULL, NULL, NULL, 0) == -1)
70 		goto out;
71 
72 
73 	if (scf_service_get_pg(svc, IDMAP_PG_NAME, pg) != 0)
74 		goto out;
75 	if (scf_pg_get_property(pg, MACHINE_UUID, prop) != 0)
76 		goto out;
77 	if (scf_property_get_value(prop, val) != 0)
78 		goto out;
79 	if (scf_value_get_as_string(val, val_buf, sizeof (val_buf)) < 0)
80 		goto out;
81 
82 	ret = strdup(val_buf);
83 
84 out:
85 	scf_value_destroy(val);
86 	scf_property_destroy(prop);
87 	scf_pg_destroy(pg);
88 	scf_service_destroy(svc);
89 
90 	if (h != NULL)
91 		scf_handle_destroy(h);
92 
93 	return (ret);
94 }
95 
96 /*
97  * Get the output of "sharectl get smbfs" into a file, without an
98  * actual fork/exec of sharectl.
99  *
100  * Each section of the smbfs settings are represented as an SMF
101  * property group with an "S-" prefix and a UUID, and the section
102  * name itself a property which can have a more flexible name than
103  * a property group name can have.
104  */
105 int
106 rc_scf_get_sharectl(FILE *fp)
107 {
108 	char sect_name[256];
109 	char prop_name[256];
110 	char val_buf[1024];
111 
112 	scf_handle_t		*h = NULL;
113 	scf_service_t		*svc = NULL;
114 	scf_instance_t		*inst = NULL;
115 	scf_propertygroup_t	*pg = NULL;
116 	scf_property_t		*prop = NULL;
117 	scf_value_t		*val = NULL;
118 	scf_iter_t		*pgiter = NULL;
119 	scf_iter_t		*propiter = NULL;
120 	scf_iter_t		*valiter = NULL;
121 	int ret = -1;
122 
123 	if ((h = _scf_handle_create_and_bind(SCF_VERSION)) == NULL)
124 		goto out;
125 
126 	if ((svc = scf_service_create(h)) == NULL ||
127 	    (inst = scf_instance_create(h)) == NULL ||
128 	    (pgiter = scf_iter_create(h)) == NULL ||
129 	    (propiter = scf_iter_create(h)) == NULL ||
130 	    (valiter = scf_iter_create(h)) == NULL ||
131 	    (pg = scf_pg_create(h)) == NULL ||
132 	    (prop = scf_property_create(h)) == NULL ||
133 	    (val = scf_value_create(h)) == NULL)
134 		goto out;
135 
136 	if (scf_handle_decode_fmri(h, SMBC_DEFAULT_INSTANCE_FMRI,
137 	    NULL, svc, inst, NULL, NULL, 0) == -1)
138 		goto out;
139 
140 	if (scf_iter_instance_pgs_composed(pgiter, inst, NULL) == -1)
141 		goto out;
142 	while ((ret = scf_iter_next_pg(pgiter, pg)) == 1) {
143 		/*
144 		 * Using prop_name array for pg name temporarily.
145 		 * Skip any property groups names other than "S-*".
146 		 */
147 		if (scf_pg_get_name(pg, prop_name, sizeof (prop_name)) < 0)
148 			continue;
149 		if (strncmp(prop_name, "S-", 2) != 0)
150 			continue;
151 
152 		/*
153 		 * Get the "section" name, which is a property of
154 		 * this property group.
155 		 */
156 		if (scf_pg_get_property(pg, "section", prop) != 0)
157 			continue;
158 		if (scf_property_get_value(prop, val) != 0)
159 			continue;
160 		if (scf_value_get_as_string(val, sect_name,
161 		    sizeof (sect_name)) < 0)
162 			continue;
163 
164 		/*
165 		 * Have an S-* property group with a "section" name.
166 		 * Print the section start.
167 		 */
168 		fprintf(fp, "[%s]\n", sect_name);
169 
170 		/*
171 		 * Now print the remaining properties in this PG,
172 		 * but skip the special "section" (name) prop.
173 		 */
174 		if (scf_iter_pg_properties(propiter, pg) == -1)
175 			goto out;
176 		while ((ret = scf_iter_next_property(propiter, prop)) == 1) {
177 
178 			if (scf_property_get_name(prop, prop_name,
179 			    sizeof (prop_name)) < 0)
180 				continue;
181 
182 			/* Skip the "section" prop. now */
183 			if (strcmp(prop_name, "section") == 0)
184 				continue;
185 
186 			if (scf_property_get_value(prop, val) != 0)
187 				continue;
188 
189 			if (scf_value_get_as_string(val, val_buf,
190 			    sizeof (val_buf)) < 0)
191 				continue;
192 
193 			fprintf(fp, "%s=%s\n", prop_name, val_buf);
194 		}
195 	}
196 	ret = 0;
197 
198 out:
199 	fflush(fp);
200 
201 	scf_value_destroy(val);
202 	scf_property_destroy(prop);
203 	scf_pg_destroy(pg);
204 	scf_iter_destroy(valiter);
205 	scf_iter_destroy(propiter);
206 	scf_iter_destroy(pgiter);
207 	scf_instance_destroy(inst);
208 	scf_service_destroy(svc);
209 
210 	if (h != NULL)
211 		scf_handle_destroy(h);
212 
213 	return (ret);
214 }
215 
216 /*
217  * Simple test wrapper.  Compile with:
218  * cc -o rc_scf_test -I.. -DTEST_MAIN rc_scf.c -lscf
219  */
220 #ifdef	TEST_MAIN
221 int
222 main(int argc, char **arv)
223 {
224 	char *s;
225 	int rc;
226 
227 	rc = rc_scf_get_sharectl(stdout);
228 	printf("# rc=%d\n", rc);
229 	return (0);
230 }
231 #endif	/* TEST_MAIN */
232