1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. 23 */ 24 #include <stdio.h> 25 #include <stdlib.h> 26 #include <syslog.h> 27 #include <stdarg.h> 28 #include "smfcfg.h" 29 30 fs_smfhandle_t * 31 fs_smf_init(char *fmri, char *instance) 32 { 33 fs_smfhandle_t *handle = NULL; 34 char *svcname, srv[MAXPATHLEN]; 35 36 /* 37 * svc name is of the form svc://network/fs/server:instance1 38 * FMRI portion is /network/fs/server 39 */ 40 snprintf(srv, MAXPATHLEN, "%s", fmri + strlen("svc:/")); 41 svcname = strrchr(srv, ':'); 42 if (svcname != NULL) 43 *svcname = '\0'; 44 svcname = srv; 45 46 handle = calloc(1, sizeof (fs_smfhandle_t)); 47 if (handle != NULL) { 48 handle->fs_handle = scf_handle_create(SCF_VERSION); 49 if (handle->fs_handle == NULL) 50 goto out; 51 if (scf_handle_bind(handle->fs_handle) != 0) 52 goto out; 53 handle->fs_service = 54 scf_service_create(handle->fs_handle); 55 handle->fs_scope = 56 scf_scope_create(handle->fs_handle); 57 if (scf_handle_get_local_scope(handle->fs_handle, 58 handle->fs_scope) != 0) 59 goto out; 60 if (scf_scope_get_service(handle->fs_scope, 61 svcname, handle->fs_service) != SCF_SUCCESS) { 62 goto out; 63 } 64 handle->fs_pg = 65 scf_pg_create(handle->fs_handle); 66 handle->fs_instance = 67 scf_instance_create(handle->fs_handle); 68 handle->fs_property = 69 scf_property_create(handle->fs_handle); 70 handle->fs_value = 71 scf_value_create(handle->fs_handle); 72 } else { 73 fprintf(stderr, 74 gettext("Cannot access SMF repository: %s\n"), fmri); 75 } 76 return (handle); 77 78 out: 79 fs_smf_fini(handle); 80 fprintf(stderr, gettext("SMF Initialization problems..%s\n"), fmri); 81 return (NULL); 82 } 83 84 85 void 86 fs_smf_fini(fs_smfhandle_t *handle) 87 { 88 if (handle != NULL) { 89 scf_scope_destroy(handle->fs_scope); 90 scf_instance_destroy(handle->fs_instance); 91 scf_service_destroy(handle->fs_service); 92 scf_pg_destroy(handle->fs_pg); 93 scf_property_destroy(handle->fs_property); 94 scf_value_destroy(handle->fs_value); 95 if (handle->fs_handle != NULL) { 96 scf_handle_unbind(handle->fs_handle); 97 scf_handle_destroy(handle->fs_handle); 98 } 99 free(handle); 100 } 101 } 102 103 int 104 fs_smf_set_prop(smf_fstype_t fstype, char *prop_name, char *valbuf, 105 char *instance, scf_type_t sctype, char *fmri) 106 { 107 fs_smfhandle_t *phandle; 108 scf_handle_t *handle; 109 scf_propertygroup_t *pg; 110 scf_property_t *prop; 111 scf_transaction_t *tran; 112 scf_transaction_entry_t *entry; 113 scf_instance_t *inst; 114 scf_value_t *val; 115 int valint; 116 int index = 0; 117 int ret = 0; 118 char *p = NULL; 119 char *svcname, srv[MAXPATHLEN]; 120 const char *pgname; 121 122 /* 123 * The SVC names we are using currently are already 124 * appended by default. Fix this for instances project. 125 */ 126 snprintf(srv, MAXPATHLEN, "%s", fmri); 127 p = strstr(fmri, ":default"); 128 if (p == NULL) { 129 strcat(srv, ":"); 130 if (instance == NULL) 131 instance = "default"; 132 if (strlen(srv) + strlen(instance) > MAXPATHLEN) 133 goto out; 134 strncat(srv, instance, strlen(instance)); 135 } 136 svcname = srv; 137 phandle = fs_smf_init(fmri, instance); 138 if (phandle == NULL) { 139 return (SMF_SYSTEM_ERR); 140 } 141 handle = phandle->fs_handle; 142 pg = phandle->fs_pg; 143 prop = phandle->fs_property; 144 inst = phandle->fs_instance; 145 val = phandle->fs_value; 146 tran = scf_transaction_create(handle); 147 entry = scf_entry_create(handle); 148 149 if (handle == NULL || pg == NULL || prop == NULL || 150 val == NULL|| tran == NULL || entry == NULL || inst == NULL) { 151 ret = SMF_SYSTEM_ERR; 152 goto out; 153 } 154 155 if (scf_handle_decode_fmri(handle, svcname, phandle->fs_scope, 156 phandle->fs_service, inst, NULL, NULL, 0) != 0) { 157 ret = scf_error(); 158 goto out; 159 } 160 if (fstype == AUTOFS_SMF) 161 pgname = AUTOFS_PROPS_PGNAME; 162 else 163 pgname = NFS_PROPS_PGNAME; 164 165 if (scf_instance_get_pg(inst, pgname, 166 pg) != -1) { 167 uint8_t vint; 168 if (scf_transaction_start(tran, pg) == -1) { 169 ret = scf_error(); 170 goto out; 171 } 172 switch (sctype) { 173 case SCF_TYPE_INTEGER: 174 errno = 0; 175 valint = strtoul(valbuf, NULL, 0); 176 if (errno != 0) { 177 ret = SMF_SYSTEM_ERR; 178 goto out; 179 } 180 if (scf_transaction_property_change(tran, 181 entry, prop_name, SCF_TYPE_INTEGER) == 0) { 182 scf_value_set_integer(val, valint); 183 if (scf_entry_add_value(entry, val) < 0) { 184 ret = scf_error(); 185 goto out; 186 } 187 } 188 break; 189 case SCF_TYPE_ASTRING: 190 if (scf_transaction_property_change(tran, entry, 191 prop_name, SCF_TYPE_ASTRING) == 0) { 192 if (scf_value_set_astring(val, 193 valbuf) == 0) { 194 if (scf_entry_add_value(entry, 195 val) != 0) { 196 ret = scf_error(); 197 goto out; 198 } 199 } else 200 ret = SMF_SYSTEM_ERR; 201 } else 202 ret = SMF_SYSTEM_ERR; 203 break; 204 case SCF_TYPE_BOOLEAN: 205 if (strcmp(valbuf, "1") == 0) { 206 vint = 1; 207 } else if (strcmp(valbuf, "0") == 0) { 208 vint = 0; 209 } else { 210 ret = SMF_SYSTEM_ERR; 211 break; 212 } 213 if (scf_transaction_property_change(tran, entry, 214 prop_name, SCF_TYPE_BOOLEAN) == 0) { 215 scf_value_set_boolean(val, (uint8_t)vint); 216 if (scf_entry_add_value(entry, val) != 0) { 217 ret = scf_error(); 218 goto out; 219 } 220 } else { 221 ret = SMF_SYSTEM_ERR; 222 } 223 break; 224 } 225 if (ret != SMF_SYSTEM_ERR) 226 scf_transaction_commit(tran); 227 } 228 out: 229 if (tran != NULL) 230 scf_transaction_destroy(tran); 231 if (entry != NULL) 232 scf_entry_destroy(entry); 233 fs_smf_fini(phandle); 234 return (ret); 235 } 236 237 int 238 fs_smf_get_prop(smf_fstype_t fstype, char *prop_name, char *cbuf, 239 char *instance, scf_type_t sctype, char *fmri, int *bufsz) 240 { 241 fs_smfhandle_t *phandle; 242 scf_handle_t *handle; 243 scf_propertygroup_t *pg; 244 scf_property_t *prop; 245 scf_value_t *val; 246 scf_instance_t *inst; 247 int ret = 0, len = 0, length; 248 int64_t valint = 0; 249 char srv[MAXPATHLEN], *p, *svcname; 250 const char *pgname; 251 uint8_t bval; 252 253 /* 254 * The SVC names we are using currently are already 255 * appended by default. Fix this for instances project. 256 */ 257 snprintf(srv, MAXPATHLEN, "%s", fmri); 258 p = strstr(fmri, ":default"); 259 if (p == NULL) { 260 strcat(srv, ":"); 261 if (instance == NULL) 262 instance = "default"; 263 if (strlen(srv) + strlen(instance) > MAXPATHLEN) 264 goto out; 265 strncat(srv, instance, strlen(instance)); 266 } 267 svcname = srv; 268 phandle = fs_smf_init(fmri, instance); 269 if (phandle == NULL) 270 return (SMF_SYSTEM_ERR); 271 handle = phandle->fs_handle; 272 pg = phandle->fs_pg; 273 inst = phandle->fs_instance; 274 prop = phandle->fs_property; 275 val = phandle->fs_value; 276 277 if (handle == NULL || pg == NULL || prop == NULL || val == NULL || 278 inst == NULL) { 279 return (SMF_SYSTEM_ERR); 280 } 281 282 283 if (scf_handle_decode_fmri(handle, svcname, phandle->fs_scope, 284 phandle->fs_service, inst, NULL, NULL, 0) != 0) { 285 ret = scf_error(); 286 goto out; 287 } 288 289 if (fstype == AUTOFS_SMF) 290 pgname = AUTOFS_PROPS_PGNAME; 291 else 292 pgname = NFS_PROPS_PGNAME; 293 294 if (scf_instance_get_pg(inst, pgname, pg) != -1) { 295 if (scf_pg_get_property(pg, prop_name, 296 prop) != SCF_SUCCESS) { 297 ret = scf_error(); 298 goto out; 299 } 300 if (scf_property_get_value(prop, val) != SCF_SUCCESS) { 301 ret = scf_error(); 302 goto out; 303 } 304 switch (sctype) { 305 case SCF_TYPE_ASTRING: 306 len = scf_value_get_astring(val, cbuf, *bufsz); 307 if (len < 0 || len > *bufsz) { 308 ret = scf_error(); 309 goto out; 310 } 311 ret = 0; 312 *bufsz = len; 313 break; 314 case SCF_TYPE_INTEGER: 315 if (scf_value_get_integer(val, &valint) != 0) { 316 ret = scf_error(); 317 goto out; 318 } 319 length = snprintf(cbuf, *bufsz, "%lld", valint); 320 if (length < 0 || length > *bufsz) { 321 ret = SA_BAD_VALUE; 322 goto out; 323 } 324 ret = 0; 325 break; 326 case SCF_TYPE_BOOLEAN: 327 if (scf_value_get_boolean(val, &bval) != 0) { 328 ret = scf_error(); 329 goto out; 330 } 331 if (bval == 1) { 332 length = snprintf(cbuf, *bufsz, "%s", "true"); 333 } else { 334 length = snprintf(cbuf, *bufsz, "%s", "false"); 335 } 336 if (length < 0 || length > *bufsz) { 337 ret = SA_BAD_VALUE; 338 goto out; 339 } 340 break; 341 } 342 } else { 343 ret = scf_error(); 344 } 345 if ((ret != 0) && scf_error() != SCF_ERROR_NONE) 346 fprintf(stdout, gettext("%s\n"), scf_strerror(ret)); 347 out: 348 fs_smf_fini(phandle); 349 return (ret); 350 } 351 352 353 int 354 nfs_smf_get_prop(char *prop_name, char *propbuf, char *instance, 355 scf_type_t sctype, char *svc_name, int *bufsz) 356 { 357 return (fs_smf_get_prop(NFS_SMF, prop_name, propbuf, 358 instance, sctype, svc_name, bufsz)); 359 } 360 361 int 362 nfs_smf_set_prop(char *prop_name, char *value, char *instance, 363 scf_type_t type, char *svc_name) 364 { 365 return (fs_smf_set_prop(NFS_SMF, prop_name, value, instance, 366 type, svc_name)); 367 } 368 369 int 370 autofs_smf_set_prop(char *prop_name, char *value, char *instance, 371 scf_type_t type, char *svc_name) 372 { 373 return (fs_smf_set_prop(AUTOFS_SMF, prop_name, value, instance, 374 type, svc_name)); 375 } 376 377 int 378 autofs_smf_get_prop(char *prop_name, char *propbuf, char *instance, 379 scf_type_t sctype, char *svc_name, int *bufsz) 380 { 381 return (fs_smf_get_prop(AUTOFS_SMF, prop_name, propbuf, 382 instance, sctype, svc_name, bufsz)); 383 } 384 385 boolean_t 386 string_to_boolean(const char *str) 387 { 388 if (strcasecmp(str, "true") == 0 || atoi(str) == 1 || 389 strcasecmp(str, "on") == 0 || strcasecmp(str, "yes") == 0) { 390 return (B_TRUE); 391 } else 392 return (B_FALSE); 393 } 394