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