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