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 = NULL;
 108         scf_handle_t *handle;
 109         scf_propertygroup_t *pg;
 110         scf_property_t *prop;
 111         scf_transaction_t *tran = NULL;
 112         scf_transaction_entry_t *entry = NULL;
 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 = NULL;
 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 }