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 *
cf_get_client_uuid(void)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
rc_scf_get_sharectl(FILE * fp)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
main(int argc,char ** arv)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