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 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 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 snprintf(srv, MAXPATHLEN, "%s", fmri); 129 p = strstr(fmri, ":default"); 130 if (p == NULL) { 131 strcat(srv, ":"); 132 if (instance == NULL) 133 instance = "default"; 134 if (strlen(srv) + strlen(instance) > MAXPATHLEN) 135 goto out; 136 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 } 227 if (ret != SMF_SYSTEM_ERR) 228 scf_transaction_commit(tran); 229 } 230 out: 231 if (tran != NULL) 232 scf_transaction_destroy(tran); 233 if (entry != NULL) 234 scf_entry_destroy(entry); 235 fs_smf_fini(phandle); 236 return (ret); 237 } 238 239 int 240 fs_smf_get_prop(smf_fstype_t fstype, char *prop_name, char *cbuf, 241 char *instance, scf_type_t sctype, char *fmri, int *bufsz) 242 { 243 fs_smfhandle_t *phandle = NULL; 244 scf_handle_t *handle; 245 scf_propertygroup_t *pg; 246 scf_property_t *prop; 247 scf_value_t *val; 248 scf_instance_t *inst; 249 int ret = 0, len = 0, length; 250 int64_t valint = 0; 251 char srv[MAXPATHLEN], *p, *svcname; 252 const char *pgname; 253 uint8_t bval; 254 255 /* 256 * The SVC names we are using currently are already 257 * appended by default. Fix this for instances project. 258 */ 259 snprintf(srv, MAXPATHLEN, "%s", fmri); 260 p = strstr(fmri, ":default"); 261 if (p == NULL) { 262 strcat(srv, ":"); 263 if (instance == NULL) 264 instance = "default"; 265 if (strlen(srv) + strlen(instance) > MAXPATHLEN) 266 goto out; 267 strncat(srv, instance, strlen(instance)); 268 } 269 svcname = srv; 270 phandle = fs_smf_init(fmri, instance); 271 if (phandle == NULL) 272 return (SMF_SYSTEM_ERR); 273 handle = phandle->fs_handle; 274 pg = phandle->fs_pg; 275 inst = phandle->fs_instance; 276 prop = phandle->fs_property; 277 val = phandle->fs_value; 278 279 if (handle == NULL || pg == NULL || prop == NULL || val == NULL || 280 inst == NULL) { 281 return (SMF_SYSTEM_ERR); 282 } 283 284 285 if (scf_handle_decode_fmri(handle, svcname, phandle->fs_scope, 286 phandle->fs_service, inst, NULL, NULL, 0) != 0) { 287 ret = scf_error(); 288 goto out; 289 } 290 291 if (fstype == AUTOFS_SMF) 292 pgname = AUTOFS_PROPS_PGNAME; 293 else 294 pgname = NFS_PROPS_PGNAME; 295 296 if (scf_instance_get_pg(inst, pgname, pg) != -1) { 297 if (scf_pg_get_property(pg, prop_name, 298 prop) != SCF_SUCCESS) { 299 ret = scf_error(); 300 goto out; 301 } 302 if (scf_property_get_value(prop, val) != SCF_SUCCESS) { 303 ret = scf_error(); 304 goto out; 305 } 306 switch (sctype) { 307 case SCF_TYPE_ASTRING: 308 len = scf_value_get_astring(val, cbuf, *bufsz); 309 if (len < 0 || len > *bufsz) { 310 ret = scf_error(); 311 goto out; 312 } 313 ret = 0; 314 *bufsz = len; 315 break; 316 case SCF_TYPE_INTEGER: 317 if (scf_value_get_integer(val, &valint) != 0) { 318 ret = scf_error(); 319 goto out; 320 } 321 length = snprintf(cbuf, *bufsz, "%lld", valint); 322 if (length < 0 || length > *bufsz) { 323 ret = SA_BAD_VALUE; 324 goto out; 325 } 326 ret = 0; 327 break; 328 case SCF_TYPE_BOOLEAN: 329 if (scf_value_get_boolean(val, &bval) != 0) { 330 ret = scf_error(); 331 goto out; 332 } 333 if (bval == 1) { 334 length = snprintf(cbuf, *bufsz, "%s", "true"); 335 } else { 336 length = snprintf(cbuf, *bufsz, "%s", "false"); 337 } 338 if (length < 0 || length > *bufsz) { 339 ret = SA_BAD_VALUE; 340 goto out; 341 } 342 break; 343 } 344 } else { 345 ret = scf_error(); 346 } 347 if ((ret != 0) && scf_error() != SCF_ERROR_NONE) 348 fprintf(stdout, gettext("%s\n"), scf_strerror(ret)); 349 out: 350 fs_smf_fini(phandle); 351 return (ret); 352 } 353 354 355 int 356 nfs_smf_get_prop(char *prop_name, char *propbuf, char *instance, 357 scf_type_t sctype, char *svc_name, int *bufsz) 358 { 359 return (fs_smf_get_prop(NFS_SMF, prop_name, propbuf, 360 instance, sctype, svc_name, bufsz)); 361 } 362 363 /* Get an integer (base 10) property */ 364 int 365 nfs_smf_get_iprop(char *prop_name, int *rvp, char *instance, 366 scf_type_t sctype, char *svc_name) 367 { 368 char propbuf[32]; 369 int bufsz, rc, val; 370 371 bufsz = sizeof (propbuf); 372 rc = fs_smf_get_prop(NFS_SMF, prop_name, propbuf, 373 instance, sctype, svc_name, &bufsz); 374 if (rc != SA_OK) 375 return (rc); 376 errno = 0; 377 val = strtol(propbuf, NULL, 10); 378 if (errno != 0) 379 return (SA_BAD_VALUE); 380 *rvp = val; 381 return (SA_OK); 382 } 383 384 int 385 nfs_smf_set_prop(char *prop_name, char *value, char *instance, 386 scf_type_t type, char *svc_name) 387 { 388 return (fs_smf_set_prop(NFS_SMF, prop_name, value, instance, 389 type, svc_name)); 390 } 391 392 int 393 autofs_smf_set_prop(char *prop_name, char *value, char *instance, 394 scf_type_t type, char *svc_name) 395 { 396 return (fs_smf_set_prop(AUTOFS_SMF, prop_name, value, instance, 397 type, svc_name)); 398 } 399 400 int 401 autofs_smf_get_prop(char *prop_name, char *propbuf, char *instance, 402 scf_type_t sctype, char *svc_name, int *bufsz) 403 { 404 return (fs_smf_get_prop(AUTOFS_SMF, prop_name, propbuf, 405 instance, sctype, svc_name, bufsz)); 406 } 407 408 boolean_t 409 string_to_boolean(const char *str) 410 { 411 if (strcasecmp(str, "true") == 0 || atoi(str) == 1 || 412 strcasecmp(str, "on") == 0 || strcasecmp(str, "yes") == 0) { 413 return (B_TRUE); 414 } else 415 return (B_FALSE); 416 } 417