1*5440Sjm199354 /* 2*5440Sjm199354 * CDDL HEADER START 3*5440Sjm199354 * 4*5440Sjm199354 * The contents of this file are subject to the terms of the 5*5440Sjm199354 * Common Development and Distribution License (the "License"). 6*5440Sjm199354 * You may not use this file except in compliance with the License. 7*5440Sjm199354 * 8*5440Sjm199354 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*5440Sjm199354 * or http://www.opensolaris.org/os/licensing. 10*5440Sjm199354 * See the License for the specific language governing permissions 11*5440Sjm199354 * and limitations under the License. 12*5440Sjm199354 * 13*5440Sjm199354 * When distributing Covered Code, include this CDDL HEADER in each 14*5440Sjm199354 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*5440Sjm199354 * If applicable, add the following below this CDDL HEADER, with the 16*5440Sjm199354 * fields enclosed by brackets "[]" replaced with your own identifying 17*5440Sjm199354 * information: Portions Copyright [yyyy] [name of copyright owner] 18*5440Sjm199354 * 19*5440Sjm199354 * CDDL HEADER END 20*5440Sjm199354 */ 21*5440Sjm199354 /* 22*5440Sjm199354 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 23*5440Sjm199354 * Use is subject to license terms. 24*5440Sjm199354 */ 25*5440Sjm199354 26*5440Sjm199354 #pragma ident "%Z%%M% %I% %E% SMI" 27*5440Sjm199354 28*5440Sjm199354 #include <string.h> 29*5440Sjm199354 #include <stdio.h> 30*5440Sjm199354 #include <stdlib.h> 31*5440Sjm199354 #include <unistd.h> 32*5440Sjm199354 #include <ctype.h> 33*5440Sjm199354 #include <math.h> 34*5440Sjm199354 #include <limits.h> 35*5440Sjm199354 #include <libscf.h> 36*5440Sjm199354 #include <errno.h> 37*5440Sjm199354 #include <fcntl.h> 38*5440Sjm199354 #include <door.h> 39*5440Sjm199354 #include <pwd.h> 40*5440Sjm199354 #include <auth_attr.h> 41*5440Sjm199354 #include <secdb.h> 42*5440Sjm199354 #include <sys/socket.h> 43*5440Sjm199354 #include <arpa/inet.h> 44*5440Sjm199354 #include <libintl.h> 45*5440Sjm199354 #include <libvscan.h> 46*5440Sjm199354 47*5440Sjm199354 #define VS_INSTANCE_FMRI "svc:/system/filesystem/vscan:icap" 48*5440Sjm199354 49*5440Sjm199354 /* SMF property group and property names */ 50*5440Sjm199354 #define VS_PGNAME_GENERAL "vs_general" 51*5440Sjm199354 #define VS_PGNAME_ENGINE "vs_engine_%d" 52*5440Sjm199354 #define VS_PGNAME_ENGINE_LEN 16 53*5440Sjm199354 54*5440Sjm199354 #define VS_PNAME_MAXSIZE "maxsize" 55*5440Sjm199354 #define VS_PNAME_MAXSIZE_ACTION "maxsize_action" 56*5440Sjm199354 #define VS_PNAME_TYPES "types" 57*5440Sjm199354 #define VS_PNAME_VLOG "viruslog" 58*5440Sjm199354 59*5440Sjm199354 #define VS_PNAME_SE_ENABLE "enable" 60*5440Sjm199354 #define VS_PNAME_SE_HOST "host" 61*5440Sjm199354 #define VS_PNAME_SE_PORT "port" 62*5440Sjm199354 #define VS_PNAME_SE_MAXCONN "max_connect" 63*5440Sjm199354 #define VS_PNAME_VAUTH "value_authorization" 64*5440Sjm199354 65*5440Sjm199354 66*5440Sjm199354 /* types string processing */ 67*5440Sjm199354 #define VS_TYPES_SEP ',' 68*5440Sjm199354 #define VS_TYPES_ESCAPE '\\' 69*5440Sjm199354 #define VS_TYPES_RULES "+-" 70*5440Sjm199354 71*5440Sjm199354 72*5440Sjm199354 /* 73*5440Sjm199354 * The SCF context enapsulating the SCF objects used in the 74*5440Sjm199354 * repository load and store routines vs_scf_values_get() 75*5440Sjm199354 * and vs_scf_values_set(). 76*5440Sjm199354 * 77*5440Sjm199354 * The context is always opened before a get or set, then 78*5440Sjm199354 * closed when finished (or on error); the open does an 79*5440Sjm199354 * initial setup, while inside the get and set functions, 80*5440Sjm199354 * additional objects within the context may be selectively 81*5440Sjm199354 * initialized for use, depending on the actions needed and 82*5440Sjm199354 * the properties being operated on. 83*5440Sjm199354 */ 84*5440Sjm199354 typedef struct vs_scfctx { 85*5440Sjm199354 scf_handle_t *vscf_handle; 86*5440Sjm199354 scf_instance_t *vscf_inst; 87*5440Sjm199354 scf_propertygroup_t *vscf_pgroup; 88*5440Sjm199354 scf_transaction_t *vscf_tx; 89*5440Sjm199354 scf_iter_t *vscf_iter; 90*5440Sjm199354 scf_property_t *vscf_prop[VS_NUM_PROPIDS]; 91*5440Sjm199354 scf_transaction_entry_t *vscf_ent[VS_NUM_PROPIDS]; 92*5440Sjm199354 scf_value_t *vscf_val[VS_NUM_PROPIDS]; 93*5440Sjm199354 } vs_scfctx_t; 94*5440Sjm199354 95*5440Sjm199354 /* 96*5440Sjm199354 * The vscan property definition. Maps the property id with the name 97*5440Sjm199354 * and type used to store the property in the repository. 98*5440Sjm199354 * A table of these definitions is defined with a single entry per 99*5440Sjm199354 * property. 100*5440Sjm199354 */ 101*5440Sjm199354 typedef struct { 102*5440Sjm199354 const char *vpd_name; 103*5440Sjm199354 uint64_t vpd_id; 104*5440Sjm199354 scf_type_t vpd_type; 105*5440Sjm199354 } vs_propdef_t; 106*5440Sjm199354 107*5440Sjm199354 typedef enum { 108*5440Sjm199354 VS_PTYPE_GEN, 109*5440Sjm199354 VS_PTYPE_SE 110*5440Sjm199354 } vs_prop_type_t; 111*5440Sjm199354 112*5440Sjm199354 typedef struct vs_prop_hd { 113*5440Sjm199354 vs_prop_type_t vp_type; 114*5440Sjm199354 uint64_t vp_ids; 115*5440Sjm199354 uint64_t vp_all; 116*5440Sjm199354 union { 117*5440Sjm199354 vs_props_t vp_gen; 118*5440Sjm199354 vs_props_se_t vp_se; 119*5440Sjm199354 } vp_props; 120*5440Sjm199354 } vs_prop_hd_t; 121*5440Sjm199354 122*5440Sjm199354 #define vp_gen vp_props.vp_gen 123*5440Sjm199354 #define vp_se vp_props.vp_se 124*5440Sjm199354 125*5440Sjm199354 /* 126*5440Sjm199354 * Default values - these are used to return valid data 127*5440Sjm199354 * to the caller in cases where invalid or unexpected values 128*5440Sjm199354 * are found in the repository. 129*5440Sjm199354 * 130*5440Sjm199354 * Note: These values must be kept in sync with those defined 131*5440Sjm199354 * in the service manifest. 132*5440Sjm199354 */ 133*5440Sjm199354 static const boolean_t vs_dflt_allow = B_TRUE; 134*5440Sjm199354 static const boolean_t vs_dflt_enable = B_TRUE; 135*5440Sjm199354 static const char *vs_dflt_maxsize = "1GB"; 136*5440Sjm199354 static const char *vs_dflt_host = ""; 137*5440Sjm199354 static const uint16_t vs_dflt_port = 1344; 138*5440Sjm199354 static const uint16_t vs_dflt_maxconn = 32L; 139*5440Sjm199354 static const char *vs_dflt_types = "+*"; 140*5440Sjm199354 static const char *vs_dflt_vlog = ""; 141*5440Sjm199354 142*5440Sjm199354 /* Property definition table */ 143*5440Sjm199354 static const vs_propdef_t vs_propdefs[] = { 144*5440Sjm199354 /* general properties */ 145*5440Sjm199354 { VS_PNAME_MAXSIZE, VS_PROPID_MAXSIZE, SCF_TYPE_ASTRING }, 146*5440Sjm199354 { VS_PNAME_MAXSIZE_ACTION, VS_PROPID_MAXSIZE_ACTION, SCF_TYPE_BOOLEAN }, 147*5440Sjm199354 { VS_PNAME_TYPES, VS_PROPID_TYPES, SCF_TYPE_ASTRING }, 148*5440Sjm199354 { VS_PNAME_VLOG, VS_PROPID_VLOG, SCF_TYPE_ASTRING }, 149*5440Sjm199354 /* scan engine properties */ 150*5440Sjm199354 { VS_PNAME_SE_ENABLE, VS_PROPID_SE_ENABLE, SCF_TYPE_BOOLEAN }, 151*5440Sjm199354 { VS_PNAME_SE_HOST, VS_PROPID_SE_HOST, SCF_TYPE_HOST }, 152*5440Sjm199354 { VS_PNAME_SE_PORT, VS_PROPID_SE_PORT, SCF_TYPE_INTEGER }, 153*5440Sjm199354 { VS_PNAME_SE_MAXCONN, VS_PROPID_SE_MAXCONN, SCF_TYPE_INTEGER }, 154*5440Sjm199354 { VS_PNAME_VAUTH, VS_PROPID_VALUE_AUTH, SCF_TYPE_ASTRING } 155*5440Sjm199354 }; 156*5440Sjm199354 157*5440Sjm199354 static const int vs_npropdefs = sizeof (vs_propdefs)/sizeof (vs_propdef_t); 158*5440Sjm199354 159*5440Sjm199354 /* Local functions */ 160*5440Sjm199354 static const vs_propdef_t *vs_get_propdef(uint64_t); 161*5440Sjm199354 static void vs_default_value(vs_prop_hd_t *, const uint64_t); 162*5440Sjm199354 163*5440Sjm199354 static int vs_scf_values_get(const char *, vs_prop_hd_t *); 164*5440Sjm199354 static int vs_scf_get(const vs_propdef_t *, vs_prop_hd_t *, vs_scfctx_t *, int); 165*5440Sjm199354 166*5440Sjm199354 static int vs_scf_values_set(const char *, vs_prop_hd_t *); 167*5440Sjm199354 static int vs_scf_set(const vs_propdef_t *, vs_prop_hd_t *, vs_scfctx_t *, int); 168*5440Sjm199354 static int vs_scf_pg_create(const char *, vs_prop_hd_t *); 169*5440Sjm199354 170*5440Sjm199354 static int vs_scf_ctx_open(vs_scfctx_t *); 171*5440Sjm199354 static void vs_scf_ctx_close(vs_scfctx_t *); 172*5440Sjm199354 173*5440Sjm199354 static int vs_validate(const vs_prop_hd_t *, uint64_t); 174*5440Sjm199354 static int vs_is_valid_types(const char *); 175*5440Sjm199354 static int vs_is_valid_host(const char *); 176*5440Sjm199354 static int vs_checkauth(char *); 177*5440Sjm199354 178*5440Sjm199354 typedef char vs_engid_t[VS_SE_NAME_LEN]; 179*5440Sjm199354 static int vs_props_get_engines(vs_engid_t *engids, int *count); 180*5440Sjm199354 static int vs_scf_pg_count(void); 181*5440Sjm199354 static int vs_strtoshift(const char *); 182*5440Sjm199354 183*5440Sjm199354 184*5440Sjm199354 /* 185*5440Sjm199354 * vs_props_get_all 186*5440Sjm199354 * 187*5440Sjm199354 * Retrieves the general service properties and all properties 188*5440Sjm199354 * for all scan engines from the repository. 189*5440Sjm199354 * 190*5440Sjm199354 * If invalid property values are found, the values are corrected to 191*5440Sjm199354 * the default value. 192*5440Sjm199354 * 193*5440Sjm199354 * Return codes: 194*5440Sjm199354 * VS_ERR_VS_ERR_NONE 195*5440Sjm199354 * VS_ERR_SCF 196*5440Sjm199354 * VS_ERR_SYS 197*5440Sjm199354 */ 198*5440Sjm199354 int 199*5440Sjm199354 vs_props_get_all(vs_props_all_t *va) 200*5440Sjm199354 { 201*5440Sjm199354 int i, rc, n; 202*5440Sjm199354 char *engid; 203*5440Sjm199354 vs_engid_t engids[VS_SE_MAX]; 204*5440Sjm199354 205*5440Sjm199354 (void) memset(va, 0, sizeof (vs_props_all_t)); 206*5440Sjm199354 if ((rc = vs_props_get(&va->va_props, VS_PROPID_GEN_ALL)) 207*5440Sjm199354 != VS_ERR_NONE) 208*5440Sjm199354 return (rc); 209*5440Sjm199354 210*5440Sjm199354 n = VS_SE_MAX; 211*5440Sjm199354 if ((rc = vs_props_get_engines(engids, &n)) != VS_ERR_NONE) 212*5440Sjm199354 return (rc); 213*5440Sjm199354 214*5440Sjm199354 if (n > VS_SE_MAX) 215*5440Sjm199354 n = VS_SE_MAX; 216*5440Sjm199354 217*5440Sjm199354 for (i = 0; i < n; i++) { 218*5440Sjm199354 engid = engids[i]; 219*5440Sjm199354 rc = vs_props_se_get(engid, &va->va_se[i], VS_PROPID_SE_ALL); 220*5440Sjm199354 if (rc != VS_ERR_NONE) 221*5440Sjm199354 return (rc); 222*5440Sjm199354 } 223*5440Sjm199354 224*5440Sjm199354 return (VS_ERR_NONE); 225*5440Sjm199354 } 226*5440Sjm199354 227*5440Sjm199354 228*5440Sjm199354 /* 229*5440Sjm199354 * vs_props_get 230*5440Sjm199354 * 231*5440Sjm199354 * Retrieves values for the specified general service properties from 232*5440Sjm199354 * the repository. 233*5440Sjm199354 * 234*5440Sjm199354 * If invalid property values are found, the values are corrected to 235*5440Sjm199354 * the default value. 236*5440Sjm199354 * 237*5440Sjm199354 * Return codes: 238*5440Sjm199354 * VS_ERR_VS_ERR_NONE 239*5440Sjm199354 * VS_ERR_INVALID_PROPERTY 240*5440Sjm199354 * VS_ERR_SCF 241*5440Sjm199354 * VS_ERR_SYS 242*5440Sjm199354 */ 243*5440Sjm199354 int 244*5440Sjm199354 vs_props_get(vs_props_t *vp, uint64_t propids) 245*5440Sjm199354 { 246*5440Sjm199354 int rc; 247*5440Sjm199354 vs_prop_hd_t prop_hd; 248*5440Sjm199354 249*5440Sjm199354 if ((propids & VS_PROPID_GEN_ALL) != propids) 250*5440Sjm199354 return (VS_ERR_INVALID_PROPERTY); 251*5440Sjm199354 252*5440Sjm199354 (void) memset(&prop_hd, 0, sizeof (vs_prop_hd_t)); 253*5440Sjm199354 prop_hd.vp_type = VS_PTYPE_GEN; 254*5440Sjm199354 prop_hd.vp_ids = propids; 255*5440Sjm199354 prop_hd.vp_all = VS_PROPID_GEN_ALL; 256*5440Sjm199354 257*5440Sjm199354 rc = vs_scf_values_get(VS_PGNAME_GENERAL, &prop_hd); 258*5440Sjm199354 259*5440Sjm199354 *vp = prop_hd.vp_gen; 260*5440Sjm199354 return (rc); 261*5440Sjm199354 } 262*5440Sjm199354 263*5440Sjm199354 264*5440Sjm199354 /* 265*5440Sjm199354 * vs_props_set 266*5440Sjm199354 * 267*5440Sjm199354 * Changes values for the specified general service properties 268*5440Sjm199354 * in the repository. 269*5440Sjm199354 * 270*5440Sjm199354 * Return codes: 271*5440Sjm199354 * VS_ERR_VS_ERR_NONE 272*5440Sjm199354 * VS_ERR_INVALID_PROPERTY 273*5440Sjm199354 * VS_ERR_INVALID_VALUE 274*5440Sjm199354 * VS_ERR_SCF 275*5440Sjm199354 * VS_ERR_SYS 276*5440Sjm199354 */ 277*5440Sjm199354 int 278*5440Sjm199354 vs_props_set(const vs_props_t *vp, uint64_t propids) 279*5440Sjm199354 { 280*5440Sjm199354 vs_prop_hd_t prop_hd; 281*5440Sjm199354 282*5440Sjm199354 if ((propids & VS_PROPID_GEN_ALL) != propids) 283*5440Sjm199354 return (VS_ERR_INVALID_PROPERTY); 284*5440Sjm199354 285*5440Sjm199354 (void) memset(&prop_hd, 0, sizeof (vs_prop_hd_t)); 286*5440Sjm199354 prop_hd.vp_type = VS_PTYPE_GEN; 287*5440Sjm199354 prop_hd.vp_ids = propids; 288*5440Sjm199354 prop_hd.vp_all = VS_PROPID_GEN_ALL; 289*5440Sjm199354 prop_hd.vp_gen = *vp; 290*5440Sjm199354 return (vs_scf_values_set(VS_PGNAME_GENERAL, &prop_hd)); 291*5440Sjm199354 } 292*5440Sjm199354 293*5440Sjm199354 294*5440Sjm199354 /* 295*5440Sjm199354 * vs_props_se_get 296*5440Sjm199354 * 297*5440Sjm199354 * Retrieves values for the specified scan engine properties from the 298*5440Sjm199354 * repository. 299*5440Sjm199354 * 300*5440Sjm199354 * If the enable property is set (true), the host property is 301*5440Sjm199354 * checked for validity. If it is not valid, the requested values 302*5440Sjm199354 * are returned with the enable propery set to off (false) 303*5440Sjm199354 * 304*5440Sjm199354 * Return codes: 305*5440Sjm199354 * VS_ERR_VS_ERR_NONE 306*5440Sjm199354 * VS_ERR_INVALID_PROPERTY 307*5440Sjm199354 * VS_ERR_SCF 308*5440Sjm199354 * VS_ERR_SYS 309*5440Sjm199354 */ 310*5440Sjm199354 int 311*5440Sjm199354 vs_props_se_get(char *engid, vs_props_se_t *sep, uint64_t propids) 312*5440Sjm199354 { 313*5440Sjm199354 int rc; 314*5440Sjm199354 vs_prop_hd_t prop_hd; 315*5440Sjm199354 316*5440Sjm199354 /* VS_PGNAME_GENERAL is a reserved for GENERAL property group */ 317*5440Sjm199354 if (strcmp(engid, VS_PGNAME_GENERAL) == 0) 318*5440Sjm199354 return (VS_ERR_INVALID_SE); 319*5440Sjm199354 320*5440Sjm199354 if ((propids & VS_PROPID_SE_ALL) != propids) 321*5440Sjm199354 return (VS_ERR_INVALID_PROPERTY); 322*5440Sjm199354 323*5440Sjm199354 (void) memset(&prop_hd, 0, sizeof (vs_prop_hd_t)); 324*5440Sjm199354 prop_hd.vp_type = VS_PTYPE_SE; 325*5440Sjm199354 prop_hd.vp_ids = propids; 326*5440Sjm199354 prop_hd.vp_all = VS_PROPID_SE_ALL; 327*5440Sjm199354 (void) strlcpy(prop_hd.vp_se.vep_engid, engid, VS_SE_NAME_LEN); 328*5440Sjm199354 329*5440Sjm199354 /* If getting enable, get the host property too */ 330*5440Sjm199354 if ((propids & VS_PROPID_SE_ENABLE)) 331*5440Sjm199354 prop_hd.vp_ids |= VS_PROPID_SE_HOST; 332*5440Sjm199354 333*5440Sjm199354 /* Load values from the repository */ 334*5440Sjm199354 rc = vs_scf_values_get(engid, &prop_hd); 335*5440Sjm199354 if (rc != VS_ERR_NONE) 336*5440Sjm199354 return (rc); 337*5440Sjm199354 338*5440Sjm199354 /* 339*5440Sjm199354 * If the host is invalid and the enable property is on, 340*5440Sjm199354 * return enable property as off 341*5440Sjm199354 */ 342*5440Sjm199354 if ((prop_hd.vp_ids & VS_PROPID_SE_HOST) && 343*5440Sjm199354 (vs_validate(&prop_hd, VS_PROPID_SE_HOST) != VS_ERR_NONE)) { 344*5440Sjm199354 prop_hd.vp_se.vep_enable = B_FALSE; 345*5440Sjm199354 } 346*5440Sjm199354 347*5440Sjm199354 *sep = prop_hd.vp_se; 348*5440Sjm199354 return (rc); 349*5440Sjm199354 } 350*5440Sjm199354 351*5440Sjm199354 352*5440Sjm199354 353*5440Sjm199354 /* 354*5440Sjm199354 * vs_props_se_set 355*5440Sjm199354 * 356*5440Sjm199354 * Changes the values for the specified scan engine properties in the 357*5440Sjm199354 * repository. 358*5440Sjm199354 * 359*5440Sjm199354 * If the enable property is being changed to true in this operation, 360*5440Sjm199354 * a host property must also be specified, or already exist in the 361*5440Sjm199354 * repository. 362*5440Sjm199354 * 363*5440Sjm199354 * Return codes: 364*5440Sjm199354 * VS_ERR_NONE 365*5440Sjm199354 * VS_ERR_INVALID_PROPERTY 366*5440Sjm199354 * VS_ERR_INVALID_VALUE 367*5440Sjm199354 * VS_ERR_SCF 368*5440Sjm199354 * VS_ERR_SYS 369*5440Sjm199354 */ 370*5440Sjm199354 int 371*5440Sjm199354 vs_props_se_set(char *engid, const vs_props_se_t *sep, uint64_t propids) 372*5440Sjm199354 { 373*5440Sjm199354 int rc; 374*5440Sjm199354 vs_prop_hd_t prop_hd; 375*5440Sjm199354 376*5440Sjm199354 /* VS_PGNAME_GENERAL is a reserved for GENERAL property group */ 377*5440Sjm199354 if (strcmp(engid, VS_PGNAME_GENERAL) == 0) 378*5440Sjm199354 return (VS_ERR_INVALID_SE); 379*5440Sjm199354 380*5440Sjm199354 if ((propids & VS_PROPID_SE_ALL) != propids) 381*5440Sjm199354 return (VS_ERR_INVALID_PROPERTY); 382*5440Sjm199354 383*5440Sjm199354 (void) memset(&prop_hd, 0, sizeof (vs_prop_hd_t)); 384*5440Sjm199354 prop_hd.vp_type = VS_PTYPE_SE; 385*5440Sjm199354 prop_hd.vp_all = VS_PROPID_SE_ALL; 386*5440Sjm199354 387*5440Sjm199354 /* 388*5440Sjm199354 * if enabling a scan engine, ensure that a valid host 389*5440Sjm199354 * is also being set, or already exists in the repository 390*5440Sjm199354 */ 391*5440Sjm199354 if ((propids & VS_PROPID_SE_ENABLE) && (sep->vep_enable == B_TRUE) && 392*5440Sjm199354 !(propids & VS_PROPID_SE_HOST)) { 393*5440Sjm199354 394*5440Sjm199354 prop_hd.vp_ids = VS_PROPID_SE_HOST; 395*5440Sjm199354 if ((rc = vs_scf_values_get(engid, &prop_hd)) != VS_ERR_NONE) 396*5440Sjm199354 return (rc); 397*5440Sjm199354 398*5440Sjm199354 if (vs_validate(&prop_hd, VS_PROPID_SE_HOST) != VS_ERR_NONE) 399*5440Sjm199354 return (VS_ERR_INVALID_HOST); 400*5440Sjm199354 } 401*5440Sjm199354 402*5440Sjm199354 prop_hd.vp_ids = propids; 403*5440Sjm199354 prop_hd.vp_se = *sep; 404*5440Sjm199354 405*5440Sjm199354 return (vs_scf_values_set(engid, &prop_hd)); 406*5440Sjm199354 } 407*5440Sjm199354 408*5440Sjm199354 409*5440Sjm199354 /* 410*5440Sjm199354 * vs_props_se_create 411*5440Sjm199354 */ 412*5440Sjm199354 int 413*5440Sjm199354 vs_props_se_create(char *engid, const vs_props_se_t *sep, uint64_t propids) 414*5440Sjm199354 { 415*5440Sjm199354 int n; 416*5440Sjm199354 vs_prop_hd_t prop_hd; 417*5440Sjm199354 418*5440Sjm199354 if ((propids & VS_PROPID_SE_ALL) != propids) 419*5440Sjm199354 return (VS_ERR_INVALID_PROPERTY); 420*5440Sjm199354 421*5440Sjm199354 /* VS_PGNAME_GENERAL is a reserved for GENERAL property group */ 422*5440Sjm199354 if (strcmp(engid, VS_PGNAME_GENERAL) == 0) 423*5440Sjm199354 return (VS_ERR_INVALID_SE); 424*5440Sjm199354 425*5440Sjm199354 if ((n = vs_scf_pg_count()) == -1) 426*5440Sjm199354 return (VS_ERR_SCF); 427*5440Sjm199354 428*5440Sjm199354 if (n == VS_SE_MAX) 429*5440Sjm199354 return (VS_ERR_MAX_SE); 430*5440Sjm199354 431*5440Sjm199354 (void) memset(&prop_hd, 0, sizeof (vs_prop_hd_t)); 432*5440Sjm199354 prop_hd.vp_type = VS_PTYPE_SE; 433*5440Sjm199354 prop_hd.vp_all = VS_PROPID_SE_ALL; 434*5440Sjm199354 prop_hd.vp_ids = propids | VS_PROPID_VALUE_AUTH; 435*5440Sjm199354 prop_hd.vp_se = *sep; 436*5440Sjm199354 437*5440Sjm199354 return (vs_scf_pg_create(engid, &prop_hd)); 438*5440Sjm199354 439*5440Sjm199354 } 440*5440Sjm199354 441*5440Sjm199354 442*5440Sjm199354 /* 443*5440Sjm199354 * vs_props_se_delete 444*5440Sjm199354 */ 445*5440Sjm199354 int 446*5440Sjm199354 vs_props_se_delete(const char *engid) 447*5440Sjm199354 { 448*5440Sjm199354 int rc; 449*5440Sjm199354 vs_scfctx_t vsc; 450*5440Sjm199354 451*5440Sjm199354 /* VS_PGNAME_GENERAL is a reserved for GENERAL property group */ 452*5440Sjm199354 if (strcmp(engid, VS_PGNAME_GENERAL) == 0) 453*5440Sjm199354 return (VS_ERR_INVALID_SE); 454*5440Sjm199354 455*5440Sjm199354 /* ensure that caller has authorization to refresh service */ 456*5440Sjm199354 if ((rc = vs_checkauth(VS_ACTION_AUTH)) != VS_ERR_NONE) 457*5440Sjm199354 return (rc); 458*5440Sjm199354 459*5440Sjm199354 if (vs_scf_ctx_open(&vsc) != 0) { 460*5440Sjm199354 vs_scf_ctx_close(&vsc); 461*5440Sjm199354 return (VS_ERR_SCF); 462*5440Sjm199354 } 463*5440Sjm199354 464*5440Sjm199354 if (scf_instance_get_pg(vsc.vscf_inst, engid, vsc.vscf_pgroup) == -1) { 465*5440Sjm199354 vs_scf_ctx_close(&vsc); 466*5440Sjm199354 rc = scf_error(); 467*5440Sjm199354 if ((rc == SCF_ERROR_NOT_FOUND) || 468*5440Sjm199354 (rc == SCF_ERROR_INVALID_ARGUMENT)) 469*5440Sjm199354 return (VS_ERR_INVALID_SE); 470*5440Sjm199354 else 471*5440Sjm199354 return (VS_ERR_SCF); 472*5440Sjm199354 } 473*5440Sjm199354 474*5440Sjm199354 if (scf_pg_delete(vsc.vscf_pgroup) == -1) { 475*5440Sjm199354 vs_scf_ctx_close(&vsc); 476*5440Sjm199354 rc = scf_error(); 477*5440Sjm199354 if ((rc == SCF_ERROR_NOT_FOUND) || 478*5440Sjm199354 (rc == SCF_ERROR_INVALID_ARGUMENT)) 479*5440Sjm199354 return (VS_ERR_INVALID_SE); 480*5440Sjm199354 481*5440Sjm199354 return (VS_ERR_SCF); 482*5440Sjm199354 } 483*5440Sjm199354 484*5440Sjm199354 vs_scf_ctx_close(&vsc); 485*5440Sjm199354 486*5440Sjm199354 /* Notify the daemon that things have changed */ 487*5440Sjm199354 if ((smf_refresh_instance(VS_INSTANCE_FMRI)) == -1) { 488*5440Sjm199354 return (VS_ERR_SCF); 489*5440Sjm199354 } 490*5440Sjm199354 491*5440Sjm199354 return (VS_ERR_NONE); 492*5440Sjm199354 } 493*5440Sjm199354 494*5440Sjm199354 495*5440Sjm199354 /* 496*5440Sjm199354 * vs_strerror 497*5440Sjm199354 */ 498*5440Sjm199354 const char * 499*5440Sjm199354 vs_strerror(int error) 500*5440Sjm199354 { 501*5440Sjm199354 switch (error) { 502*5440Sjm199354 case VS_ERR_NONE: 503*5440Sjm199354 return (gettext("no error")); 504*5440Sjm199354 case VS_ERR_INVALID_PROPERTY: 505*5440Sjm199354 return (gettext("invalid property id")); 506*5440Sjm199354 case VS_ERR_INVALID_VALUE: 507*5440Sjm199354 return (gettext("invalid property value")); 508*5440Sjm199354 case VS_ERR_INVALID_HOST: 509*5440Sjm199354 return (gettext("invalid host")); 510*5440Sjm199354 case VS_ERR_INVALID_SE: 511*5440Sjm199354 return (gettext("invalid scan engine")); 512*5440Sjm199354 case VS_ERR_MAX_SE: 513*5440Sjm199354 return (gettext("max scan engines exceeded")); 514*5440Sjm199354 case VS_ERR_AUTH: 515*5440Sjm199354 return (gettext("insufficient privileges for action")); 516*5440Sjm199354 case VS_ERR_DAEMON_COMM: 517*5440Sjm199354 return (gettext("unable to contact vscand")); 518*5440Sjm199354 case VS_ERR_SCF: 519*5440Sjm199354 return (scf_strerror(scf_error())); 520*5440Sjm199354 case VS_ERR_SYS: 521*5440Sjm199354 return (strerror(errno)); 522*5440Sjm199354 default: 523*5440Sjm199354 return (gettext("unknown error")); 524*5440Sjm199354 } 525*5440Sjm199354 } 526*5440Sjm199354 527*5440Sjm199354 528*5440Sjm199354 /* 529*5440Sjm199354 * vs_get_propdef 530*5440Sjm199354 * 531*5440Sjm199354 * Finds and returns a property definition by property id. 532*5440Sjm199354 */ 533*5440Sjm199354 static const vs_propdef_t * 534*5440Sjm199354 vs_get_propdef(uint64_t propid) 535*5440Sjm199354 { 536*5440Sjm199354 int i; 537*5440Sjm199354 538*5440Sjm199354 for (i = 0; i < vs_npropdefs; i++) { 539*5440Sjm199354 if (propid == vs_propdefs[i].vpd_id) 540*5440Sjm199354 return (&vs_propdefs[i]); 541*5440Sjm199354 } 542*5440Sjm199354 543*5440Sjm199354 return (NULL); 544*5440Sjm199354 } 545*5440Sjm199354 546*5440Sjm199354 547*5440Sjm199354 /* 548*5440Sjm199354 * vs_default_value 549*5440Sjm199354 * 550*5440Sjm199354 * Sets a property value that contains invalid data to its default value. 551*5440Sjm199354 * 552*5440Sjm199354 * Note that this function does not alter any values in the repository 553*5440Sjm199354 * This is only to enable the caller to get valid data. 554*5440Sjm199354 */ 555*5440Sjm199354 static void 556*5440Sjm199354 vs_default_value(vs_prop_hd_t *prop_hd, const uint64_t propid) 557*5440Sjm199354 { 558*5440Sjm199354 vs_props_t *vp = &prop_hd->vp_gen; 559*5440Sjm199354 vs_props_se_t *vep = &prop_hd->vp_se; 560*5440Sjm199354 561*5440Sjm199354 switch (propid) { 562*5440Sjm199354 case VS_PROPID_MAXSIZE: 563*5440Sjm199354 (void) strlcpy(vp->vp_maxsize, vs_dflt_maxsize, 564*5440Sjm199354 sizeof (vp->vp_maxsize)); 565*5440Sjm199354 break; 566*5440Sjm199354 case VS_PROPID_MAXSIZE_ACTION: 567*5440Sjm199354 vp->vp_maxsize_action = vs_dflt_allow; 568*5440Sjm199354 break; 569*5440Sjm199354 case VS_PROPID_TYPES: 570*5440Sjm199354 (void) strlcpy(vp->vp_types, vs_dflt_types, 571*5440Sjm199354 sizeof (vp->vp_types)); 572*5440Sjm199354 break; 573*5440Sjm199354 case VS_PROPID_VLOG: 574*5440Sjm199354 (void) strlcpy(vp->vp_vlog, vs_dflt_vlog, 575*5440Sjm199354 sizeof (vp->vp_vlog)); 576*5440Sjm199354 break; 577*5440Sjm199354 case VS_PROPID_SE_ENABLE: 578*5440Sjm199354 vep->vep_enable = vs_dflt_enable; 579*5440Sjm199354 break; 580*5440Sjm199354 case VS_PROPID_SE_HOST: 581*5440Sjm199354 (void) strlcpy(vep->vep_host, vs_dflt_host, 582*5440Sjm199354 sizeof (vep->vep_host)); 583*5440Sjm199354 break; 584*5440Sjm199354 case VS_PROPID_SE_PORT: 585*5440Sjm199354 vep->vep_port = vs_dflt_port; 586*5440Sjm199354 break; 587*5440Sjm199354 case VS_PROPID_SE_MAXCONN: 588*5440Sjm199354 vep->vep_maxconn = vs_dflt_maxconn; 589*5440Sjm199354 break; 590*5440Sjm199354 default: 591*5440Sjm199354 break; 592*5440Sjm199354 } 593*5440Sjm199354 } 594*5440Sjm199354 595*5440Sjm199354 596*5440Sjm199354 /* 597*5440Sjm199354 * vs_scf_values_get 598*5440Sjm199354 * 599*5440Sjm199354 * Gets property values for one or more properties from the repository. 600*5440Sjm199354 * This is the single entry point for loading SMF values. 601*5440Sjm199354 * 602*5440Sjm199354 * While a transaction is not used for loading property values, 603*5440Sjm199354 * the operation is parameterized by a property group. All properties 604*5440Sjm199354 * retrieved in this function, then, must belong to the same property 605*5440Sjm199354 * group. 606*5440Sjm199354 */ 607*5440Sjm199354 int 608*5440Sjm199354 vs_scf_values_get(const char *pgname, vs_prop_hd_t *prop_hd) 609*5440Sjm199354 { 610*5440Sjm199354 vs_scfctx_t vsc; 611*5440Sjm199354 int rc, np; 612*5440Sjm199354 const vs_propdef_t *vpd; 613*5440Sjm199354 uint64_t propid; 614*5440Sjm199354 615*5440Sjm199354 if ((vs_scf_ctx_open(&vsc)) != 0) { 616*5440Sjm199354 vs_scf_ctx_close(&vsc); 617*5440Sjm199354 return (VS_ERR_SCF); 618*5440Sjm199354 } 619*5440Sjm199354 620*5440Sjm199354 if (scf_instance_get_pg(vsc.vscf_inst, pgname, vsc.vscf_pgroup) == -1) { 621*5440Sjm199354 vs_scf_ctx_close(&vsc); 622*5440Sjm199354 if (strcmp(pgname, "VS_PGNAME_GENERAL") != 0) { 623*5440Sjm199354 rc = scf_error(); 624*5440Sjm199354 if ((rc == SCF_ERROR_NOT_FOUND) || 625*5440Sjm199354 (rc == SCF_ERROR_INVALID_ARGUMENT)) 626*5440Sjm199354 return (VS_ERR_INVALID_SE); 627*5440Sjm199354 } 628*5440Sjm199354 return (VS_ERR_SCF); 629*5440Sjm199354 } 630*5440Sjm199354 631*5440Sjm199354 rc = VS_ERR_NONE; 632*5440Sjm199354 np = 0; 633*5440Sjm199354 for (propid = 1LL; propid <= VS_PROPID_MAX; propid <<= 1) { 634*5440Sjm199354 if ((prop_hd->vp_ids & propid) == 0) 635*5440Sjm199354 continue; 636*5440Sjm199354 637*5440Sjm199354 if ((vpd = vs_get_propdef(propid)) == NULL) { 638*5440Sjm199354 rc = VS_ERR_INVALID_PROPERTY; 639*5440Sjm199354 break; 640*5440Sjm199354 } 641*5440Sjm199354 642*5440Sjm199354 vsc.vscf_prop[np] = scf_property_create(vsc.vscf_handle); 643*5440Sjm199354 vsc.vscf_val[np] = scf_value_create(vsc.vscf_handle); 644*5440Sjm199354 645*5440Sjm199354 if (vsc.vscf_prop[np] == NULL || vsc.vscf_val[np] == NULL) { 646*5440Sjm199354 rc = VS_ERR_SCF; 647*5440Sjm199354 break; 648*5440Sjm199354 } 649*5440Sjm199354 650*5440Sjm199354 if (scf_pg_get_property(vsc.vscf_pgroup, vpd->vpd_name, 651*5440Sjm199354 vsc.vscf_prop[np]) == -1) { 652*5440Sjm199354 if (scf_error() == SCF_ERROR_NOT_FOUND) { 653*5440Sjm199354 vs_default_value(prop_hd, vpd->vpd_id); 654*5440Sjm199354 continue; 655*5440Sjm199354 } 656*5440Sjm199354 rc = VS_ERR_SCF; 657*5440Sjm199354 break; 658*5440Sjm199354 } 659*5440Sjm199354 660*5440Sjm199354 if ((rc = vs_scf_get(vpd, prop_hd, &vsc, np)) != VS_ERR_NONE) 661*5440Sjm199354 break; 662*5440Sjm199354 663*5440Sjm199354 ++np; 664*5440Sjm199354 } 665*5440Sjm199354 666*5440Sjm199354 667*5440Sjm199354 vs_scf_ctx_close(&vsc); 668*5440Sjm199354 669*5440Sjm199354 return (rc); 670*5440Sjm199354 } 671*5440Sjm199354 672*5440Sjm199354 673*5440Sjm199354 /* 674*5440Sjm199354 * vs_scf_get 675*5440Sjm199354 * 676*5440Sjm199354 * Loads a single values from the repository into the appropriate vscan 677*5440Sjm199354 * property structure member. 678*5440Sjm199354 */ 679*5440Sjm199354 static int 680*5440Sjm199354 vs_scf_get(const vs_propdef_t *vpd, vs_prop_hd_t *prop_hd, 681*5440Sjm199354 vs_scfctx_t *vsc, int idx) 682*5440Sjm199354 { 683*5440Sjm199354 int rc; 684*5440Sjm199354 int64_t port; 685*5440Sjm199354 uint8_t valbool; 686*5440Sjm199354 vs_props_t *vp = &prop_hd->vp_gen; 687*5440Sjm199354 vs_props_se_t *vep = &prop_hd->vp_se; 688*5440Sjm199354 689*5440Sjm199354 if ((rc = scf_property_get_value(vsc->vscf_prop[idx], 690*5440Sjm199354 vsc->vscf_val[idx])) == -1) { 691*5440Sjm199354 if (rc == SCF_ERROR_CONSTRAINT_VIOLATED || 692*5440Sjm199354 rc == SCF_ERROR_NOT_FOUND) { 693*5440Sjm199354 vs_default_value(prop_hd, vpd->vpd_id); 694*5440Sjm199354 return (VS_ERR_NONE); 695*5440Sjm199354 } 696*5440Sjm199354 return (VS_ERR_SCF); 697*5440Sjm199354 } 698*5440Sjm199354 699*5440Sjm199354 rc = VS_ERR_NONE; 700*5440Sjm199354 switch (vpd->vpd_id) { 701*5440Sjm199354 case VS_PROPID_MAXSIZE: 702*5440Sjm199354 if ((scf_value_get_astring(vsc->vscf_val[idx], 703*5440Sjm199354 vp->vp_maxsize, sizeof (vp->vp_maxsize))) == -1) { 704*5440Sjm199354 return (VS_ERR_SCF); 705*5440Sjm199354 } 706*5440Sjm199354 break; 707*5440Sjm199354 case VS_PROPID_MAXSIZE_ACTION: 708*5440Sjm199354 if ((scf_value_get_boolean(vsc->vscf_val[idx], 709*5440Sjm199354 &valbool)) == -1) { 710*5440Sjm199354 return (VS_ERR_SCF); 711*5440Sjm199354 } 712*5440Sjm199354 vp->vp_maxsize_action = (valbool == 0) ? B_FALSE : B_TRUE; 713*5440Sjm199354 break; 714*5440Sjm199354 case VS_PROPID_TYPES: 715*5440Sjm199354 if ((scf_value_get_astring(vsc->vscf_val[idx], 716*5440Sjm199354 vp->vp_types, sizeof (vp->vp_types))) == -1) { 717*5440Sjm199354 return (VS_ERR_SCF); 718*5440Sjm199354 } 719*5440Sjm199354 break; 720*5440Sjm199354 case VS_PROPID_VLOG: 721*5440Sjm199354 if ((scf_value_get_astring(vsc->vscf_val[idx], 722*5440Sjm199354 vp->vp_vlog, sizeof (vp->vp_vlog))) == -1) { 723*5440Sjm199354 return (VS_ERR_SCF); 724*5440Sjm199354 } 725*5440Sjm199354 break; 726*5440Sjm199354 case VS_PROPID_SE_ENABLE: 727*5440Sjm199354 if ((scf_value_get_boolean(vsc->vscf_val[idx], 728*5440Sjm199354 &valbool)) == -1) { 729*5440Sjm199354 return (VS_ERR_SCF); 730*5440Sjm199354 } 731*5440Sjm199354 vep->vep_enable = (valbool == 0) ? B_FALSE : B_TRUE; 732*5440Sjm199354 break; 733*5440Sjm199354 case VS_PROPID_SE_HOST: 734*5440Sjm199354 (void) scf_value_get_as_string_typed(vsc->vscf_val[idx], 735*5440Sjm199354 vpd->vpd_type, vep->vep_host, sizeof (vep->vep_host)); 736*5440Sjm199354 break; 737*5440Sjm199354 case VS_PROPID_SE_PORT: 738*5440Sjm199354 if ((scf_value_get_integer(vsc->vscf_val[idx], &port)) == -1) 739*5440Sjm199354 return (VS_ERR_SCF); 740*5440Sjm199354 if (port <= 0 || port >= UINT16_MAX) 741*5440Sjm199354 rc = VS_ERR_INVALID_VALUE; 742*5440Sjm199354 else 743*5440Sjm199354 vep->vep_port = (uint16_t)port; 744*5440Sjm199354 break; 745*5440Sjm199354 case VS_PROPID_SE_MAXCONN: 746*5440Sjm199354 if ((scf_value_get_integer(vsc->vscf_val[idx], 747*5440Sjm199354 (int64_t *)&vep->vep_maxconn)) == -1) { 748*5440Sjm199354 return (VS_ERR_SCF); 749*5440Sjm199354 } 750*5440Sjm199354 break; 751*5440Sjm199354 default: 752*5440Sjm199354 break; 753*5440Sjm199354 } 754*5440Sjm199354 755*5440Sjm199354 if ((rc != VS_ERR_NONE) || 756*5440Sjm199354 (vs_validate(prop_hd, vpd->vpd_id) != VS_ERR_NONE)) { 757*5440Sjm199354 vs_default_value(prop_hd, vpd->vpd_id); 758*5440Sjm199354 } 759*5440Sjm199354 760*5440Sjm199354 return (VS_ERR_NONE); 761*5440Sjm199354 } 762*5440Sjm199354 763*5440Sjm199354 764*5440Sjm199354 /* 765*5440Sjm199354 * vs_scf_pg_create 766*5440Sjm199354 */ 767*5440Sjm199354 static int 768*5440Sjm199354 vs_scf_pg_create(const char *pgname, vs_prop_hd_t *prop_hd) 769*5440Sjm199354 { 770*5440Sjm199354 int rc; 771*5440Sjm199354 uint64_t propid; 772*5440Sjm199354 uint64_t propids = prop_hd->vp_ids; 773*5440Sjm199354 vs_scfctx_t vsc; 774*5440Sjm199354 775*5440Sjm199354 /* ensure that caller has authorization to refresh service */ 776*5440Sjm199354 if ((rc = vs_checkauth(VS_ACTION_AUTH)) != VS_ERR_NONE) 777*5440Sjm199354 return (rc); 778*5440Sjm199354 779*5440Sjm199354 if (vs_scf_ctx_open(&vsc) != 0) { 780*5440Sjm199354 vs_scf_ctx_close(&vsc); 781*5440Sjm199354 return (VS_ERR_SCF); 782*5440Sjm199354 } 783*5440Sjm199354 784*5440Sjm199354 if (scf_instance_add_pg(vsc.vscf_inst, pgname, 785*5440Sjm199354 SCF_GROUP_APPLICATION, 0, vsc.vscf_pgroup) == -1) { 786*5440Sjm199354 vs_scf_ctx_close(&vsc); 787*5440Sjm199354 if (scf_error() == SCF_ERROR_INVALID_ARGUMENT) 788*5440Sjm199354 return (VS_ERR_INVALID_SE); 789*5440Sjm199354 return (VS_ERR_SCF); 790*5440Sjm199354 } 791*5440Sjm199354 vs_scf_ctx_close(&vsc); 792*5440Sjm199354 793*5440Sjm199354 /* set default values for those not specified */ 794*5440Sjm199354 for (propid = 1LL; propid <= VS_PROPID_MAX; propid <<= 1) { 795*5440Sjm199354 if ((propid & prop_hd->vp_all) && !(propid & prop_hd->vp_ids)) 796*5440Sjm199354 vs_default_value(prop_hd, propid); 797*5440Sjm199354 } 798*5440Sjm199354 prop_hd->vp_ids = prop_hd->vp_all; 799*5440Sjm199354 800*5440Sjm199354 801*5440Sjm199354 if ((propids & VS_PROPID_SE_HOST) == 0) 802*5440Sjm199354 (void) strlcpy(prop_hd->vp_se.vep_host, pgname, MAXHOSTNAMELEN); 803*5440Sjm199354 804*5440Sjm199354 prop_hd->vp_ids |= VS_PROPID_VALUE_AUTH; 805*5440Sjm199354 806*5440Sjm199354 rc = vs_scf_values_set(pgname, prop_hd); 807*5440Sjm199354 if (rc != VS_ERR_NONE) 808*5440Sjm199354 (void) vs_props_se_delete(pgname); 809*5440Sjm199354 810*5440Sjm199354 return (rc); 811*5440Sjm199354 } 812*5440Sjm199354 813*5440Sjm199354 814*5440Sjm199354 /* 815*5440Sjm199354 * vs_scf_values_set 816*5440Sjm199354 * 817*5440Sjm199354 * Sets property values in the repository. This is the single 818*5440Sjm199354 * entry point for storing SMF values. 819*5440Sjm199354 * 820*5440Sjm199354 * Like loading values, this is an operation based on a single property 821*5440Sjm199354 * group, so all property values changed in this function must belong 822*5440Sjm199354 * to the same property group. Additionally, this operation is done in 823*5440Sjm199354 * the context of a repository transaction; on any fatal error, the 824*5440Sjm199354 * SCF context will be closed, destroying all SCF objects and aborting 825*5440Sjm199354 * the transaction. 826*5440Sjm199354 */ 827*5440Sjm199354 static int 828*5440Sjm199354 vs_scf_values_set(const char *pgname, vs_prop_hd_t *prop_hd) 829*5440Sjm199354 { 830*5440Sjm199354 int rc, np; 831*5440Sjm199354 const vs_propdef_t *vpd; 832*5440Sjm199354 uint64_t propid; 833*5440Sjm199354 vs_scfctx_t vsc; 834*5440Sjm199354 835*5440Sjm199354 836*5440Sjm199354 /* ensure that caller has authorization to refresh service */ 837*5440Sjm199354 if ((rc = vs_checkauth(VS_ACTION_AUTH)) != VS_ERR_NONE) 838*5440Sjm199354 return (rc); 839*5440Sjm199354 840*5440Sjm199354 if (vs_scf_ctx_open(&vsc) != 0) { 841*5440Sjm199354 vs_scf_ctx_close(&vsc); 842*5440Sjm199354 return (VS_ERR_SCF); 843*5440Sjm199354 } 844*5440Sjm199354 845*5440Sjm199354 if (scf_instance_get_pg(vsc.vscf_inst, pgname, vsc.vscf_pgroup) == -1) { 846*5440Sjm199354 vs_scf_ctx_close(&vsc); 847*5440Sjm199354 rc = scf_error(); 848*5440Sjm199354 if (strcmp(pgname, "VS_PGNAME_GENERAL") != 0) { 849*5440Sjm199354 if ((rc == SCF_ERROR_NOT_FOUND) || 850*5440Sjm199354 (rc == SCF_ERROR_INVALID_ARGUMENT)) 851*5440Sjm199354 return (VS_ERR_INVALID_SE); 852*5440Sjm199354 } 853*5440Sjm199354 return (VS_ERR_SCF); 854*5440Sjm199354 } 855*5440Sjm199354 856*5440Sjm199354 if (((vsc.vscf_tx = scf_transaction_create(vsc.vscf_handle)) == NULL) || 857*5440Sjm199354 (scf_transaction_start(vsc.vscf_tx, vsc.vscf_pgroup) == -1)) { 858*5440Sjm199354 vs_scf_ctx_close(&vsc); 859*5440Sjm199354 return (VS_ERR_SCF); 860*5440Sjm199354 } 861*5440Sjm199354 862*5440Sjm199354 /* Process the value change for each specified property */ 863*5440Sjm199354 rc = 0; 864*5440Sjm199354 np = 0; 865*5440Sjm199354 for (propid = 1LL; propid <= VS_PROPID_MAX; propid <<= 1) { 866*5440Sjm199354 if ((prop_hd->vp_ids & propid) == 0) 867*5440Sjm199354 continue; 868*5440Sjm199354 869*5440Sjm199354 if ((vpd = vs_get_propdef(propid)) == NULL) { 870*5440Sjm199354 rc = VS_ERR_INVALID_PROPERTY; 871*5440Sjm199354 break; 872*5440Sjm199354 } 873*5440Sjm199354 874*5440Sjm199354 vsc.vscf_val[np] = scf_value_create(vsc.vscf_handle); 875*5440Sjm199354 vsc.vscf_ent[np] = scf_entry_create(vsc.vscf_handle); 876*5440Sjm199354 877*5440Sjm199354 if (vsc.vscf_val[np] == NULL || vsc.vscf_ent[np] == NULL) { 878*5440Sjm199354 rc = VS_ERR_SCF; 879*5440Sjm199354 break; 880*5440Sjm199354 } 881*5440Sjm199354 882*5440Sjm199354 if ((rc = scf_transaction_property_change(vsc.vscf_tx, 883*5440Sjm199354 vsc.vscf_ent[np], vpd->vpd_name, vpd->vpd_type)) == -1) { 884*5440Sjm199354 rc = scf_transaction_property_new(vsc.vscf_tx, 885*5440Sjm199354 vsc.vscf_ent[np], vpd->vpd_name, vpd->vpd_type); 886*5440Sjm199354 } 887*5440Sjm199354 if (rc == -1) { 888*5440Sjm199354 rc = VS_ERR_SCF; 889*5440Sjm199354 break; 890*5440Sjm199354 } 891*5440Sjm199354 892*5440Sjm199354 if ((rc = vs_scf_set(vpd, prop_hd, &vsc, np)) != VS_ERR_NONE) 893*5440Sjm199354 break; 894*5440Sjm199354 895*5440Sjm199354 ++np; 896*5440Sjm199354 } 897*5440Sjm199354 898*5440Sjm199354 if (rc != VS_ERR_NONE) { 899*5440Sjm199354 vs_scf_ctx_close(&vsc); 900*5440Sjm199354 return (rc); 901*5440Sjm199354 } 902*5440Sjm199354 903*5440Sjm199354 /* Commit the transaction */ 904*5440Sjm199354 if (scf_transaction_commit(vsc.vscf_tx) == -1) { 905*5440Sjm199354 vs_scf_ctx_close(&vsc); 906*5440Sjm199354 return (VS_ERR_SCF); 907*5440Sjm199354 } 908*5440Sjm199354 vs_scf_ctx_close(&vsc); 909*5440Sjm199354 910*5440Sjm199354 /* Notify the daemon that things have changed */ 911*5440Sjm199354 if ((smf_refresh_instance(VS_INSTANCE_FMRI)) == -1) 912*5440Sjm199354 return (VS_ERR_SCF); 913*5440Sjm199354 914*5440Sjm199354 return (VS_ERR_NONE); 915*5440Sjm199354 } 916*5440Sjm199354 917*5440Sjm199354 918*5440Sjm199354 /* 919*5440Sjm199354 * vs_scf_set 920*5440Sjm199354 * 921*5440Sjm199354 * Stores a single value from the appropriate vscan property structure 922*5440Sjm199354 * member into the repository. 923*5440Sjm199354 * 924*5440Sjm199354 * Values are set in the SCF value object, then the value object 925*5440Sjm199354 * is added to the SCF property object. 926*5440Sjm199354 */ 927*5440Sjm199354 static int 928*5440Sjm199354 vs_scf_set(const vs_propdef_t *vpd, vs_prop_hd_t *prop_hd, 929*5440Sjm199354 vs_scfctx_t *vsc, int idx) 930*5440Sjm199354 { 931*5440Sjm199354 int rc; 932*5440Sjm199354 vs_props_t *vp = &prop_hd->vp_gen; 933*5440Sjm199354 vs_props_se_t *vep = &prop_hd->vp_se; 934*5440Sjm199354 935*5440Sjm199354 if ((rc = vs_validate(prop_hd, vpd->vpd_id)) != VS_ERR_NONE) 936*5440Sjm199354 return (rc); 937*5440Sjm199354 938*5440Sjm199354 rc = VS_ERR_NONE; 939*5440Sjm199354 switch (vpd->vpd_id) { 940*5440Sjm199354 case VS_PROPID_MAXSIZE: 941*5440Sjm199354 if ((scf_value_set_astring(vsc->vscf_val[idx], 942*5440Sjm199354 vp->vp_maxsize)) == -1) { 943*5440Sjm199354 rc = VS_ERR_SCF; 944*5440Sjm199354 } 945*5440Sjm199354 break; 946*5440Sjm199354 case VS_PROPID_MAXSIZE_ACTION: 947*5440Sjm199354 scf_value_set_boolean(vsc->vscf_val[idx], 948*5440Sjm199354 (uint8_t)vp->vp_maxsize_action); 949*5440Sjm199354 break; 950*5440Sjm199354 case VS_PROPID_TYPES: 951*5440Sjm199354 if ((scf_value_set_astring(vsc->vscf_val[idx], 952*5440Sjm199354 vp->vp_types)) == -1) { 953*5440Sjm199354 return (VS_ERR_SCF); 954*5440Sjm199354 } 955*5440Sjm199354 break; 956*5440Sjm199354 case VS_PROPID_SE_ENABLE: 957*5440Sjm199354 scf_value_set_boolean(vsc->vscf_val[idx], 958*5440Sjm199354 (uint8_t)vep->vep_enable); 959*5440Sjm199354 break; 960*5440Sjm199354 case VS_PROPID_SE_HOST: 961*5440Sjm199354 if ((scf_value_set_from_string(vsc->vscf_val[idx], 962*5440Sjm199354 vpd->vpd_type, vep->vep_host)) == -1) { 963*5440Sjm199354 rc = VS_ERR_SCF; 964*5440Sjm199354 } 965*5440Sjm199354 break; 966*5440Sjm199354 case VS_PROPID_SE_PORT: 967*5440Sjm199354 scf_value_set_integer(vsc->vscf_val[idx], vep->vep_port); 968*5440Sjm199354 break; 969*5440Sjm199354 case VS_PROPID_SE_MAXCONN: 970*5440Sjm199354 scf_value_set_integer(vsc->vscf_val[idx], 971*5440Sjm199354 vep->vep_maxconn); 972*5440Sjm199354 break; 973*5440Sjm199354 case VS_PROPID_VALUE_AUTH: 974*5440Sjm199354 if ((scf_value_set_astring(vsc->vscf_val[idx], 975*5440Sjm199354 VS_VALUE_AUTH)) == -1) { 976*5440Sjm199354 return (VS_ERR_SCF); 977*5440Sjm199354 } 978*5440Sjm199354 break; 979*5440Sjm199354 default: 980*5440Sjm199354 break; 981*5440Sjm199354 } 982*5440Sjm199354 983*5440Sjm199354 if ((scf_entry_add_value(vsc->vscf_ent[idx], 984*5440Sjm199354 vsc->vscf_val[idx])) == -1) { 985*5440Sjm199354 return (VS_ERR_SCF); 986*5440Sjm199354 } 987*5440Sjm199354 988*5440Sjm199354 return (rc); 989*5440Sjm199354 } 990*5440Sjm199354 991*5440Sjm199354 992*5440Sjm199354 /* 993*5440Sjm199354 * vs_scf_ctx_open 994*5440Sjm199354 * 995*5440Sjm199354 * Opens an SCF context; creates the minumum SCF objects 996*5440Sjm199354 * for use in loading/storing from the SMF repository (meaning 997*5440Sjm199354 * vscf_property group data). 998*5440Sjm199354 * 999*5440Sjm199354 * Other SCF objects in the context may be initialized elsewher 1000*5440Sjm199354 * subsequent to open, but all initialized structures are destroyed 1001*5440Sjm199354 * in vs_scf_ctx_close(). 1002*5440Sjm199354 */ 1003*5440Sjm199354 static int 1004*5440Sjm199354 vs_scf_ctx_open(vs_scfctx_t *vsc) 1005*5440Sjm199354 { 1006*5440Sjm199354 (void) memset(vsc, 0, sizeof (vs_scfctx_t)); 1007*5440Sjm199354 1008*5440Sjm199354 if ((vsc->vscf_handle = scf_handle_create(SCF_VERSION)) == NULL) 1009*5440Sjm199354 return (VS_ERR_SCF); 1010*5440Sjm199354 1011*5440Sjm199354 if (scf_handle_bind(vsc->vscf_handle) == -1) 1012*5440Sjm199354 return (VS_ERR_SCF); 1013*5440Sjm199354 1014*5440Sjm199354 if ((vsc->vscf_inst = scf_instance_create(vsc->vscf_handle)) == NULL) 1015*5440Sjm199354 return (VS_ERR_SCF); 1016*5440Sjm199354 1017*5440Sjm199354 if (scf_handle_decode_fmri(vsc->vscf_handle, VS_INSTANCE_FMRI, 1018*5440Sjm199354 NULL, NULL, vsc->vscf_inst, NULL, NULL, 1019*5440Sjm199354 SCF_DECODE_FMRI_EXACT) == -1) { 1020*5440Sjm199354 return (VS_ERR_SCF); 1021*5440Sjm199354 } 1022*5440Sjm199354 1023*5440Sjm199354 if ((vsc->vscf_pgroup = scf_pg_create(vsc->vscf_handle)) == NULL) 1024*5440Sjm199354 return (VS_ERR_SCF); 1025*5440Sjm199354 1026*5440Sjm199354 return (VS_ERR_NONE); 1027*5440Sjm199354 } 1028*5440Sjm199354 1029*5440Sjm199354 1030*5440Sjm199354 /* 1031*5440Sjm199354 * vs_scf_ctx_close 1032*5440Sjm199354 * 1033*5440Sjm199354 * Closes an SCF context; destroys all initialized SCF objects. 1034*5440Sjm199354 */ 1035*5440Sjm199354 static void 1036*5440Sjm199354 vs_scf_ctx_close(vs_scfctx_t *vsc) 1037*5440Sjm199354 { 1038*5440Sjm199354 int i; 1039*5440Sjm199354 1040*5440Sjm199354 for (i = 0; i < VS_NUM_PROPIDS; i++) { 1041*5440Sjm199354 if (vsc->vscf_val[i]) 1042*5440Sjm199354 scf_value_destroy(vsc->vscf_val[i]); 1043*5440Sjm199354 if (vsc->vscf_ent[i]) 1044*5440Sjm199354 scf_entry_destroy(vsc->vscf_ent[i]); 1045*5440Sjm199354 if (vsc->vscf_prop[i]) 1046*5440Sjm199354 scf_property_destroy(vsc->vscf_prop[i]); 1047*5440Sjm199354 } 1048*5440Sjm199354 1049*5440Sjm199354 if (vsc->vscf_iter) 1050*5440Sjm199354 scf_iter_destroy(vsc->vscf_iter); 1051*5440Sjm199354 if (vsc->vscf_tx) 1052*5440Sjm199354 scf_transaction_destroy(vsc->vscf_tx); 1053*5440Sjm199354 if (vsc->vscf_pgroup) 1054*5440Sjm199354 scf_pg_destroy(vsc->vscf_pgroup); 1055*5440Sjm199354 if (vsc->vscf_inst) 1056*5440Sjm199354 scf_instance_destroy(vsc->vscf_inst); 1057*5440Sjm199354 if (vsc->vscf_handle) 1058*5440Sjm199354 scf_handle_destroy(vsc->vscf_handle); 1059*5440Sjm199354 } 1060*5440Sjm199354 1061*5440Sjm199354 1062*5440Sjm199354 /* 1063*5440Sjm199354 * vs_validate 1064*5440Sjm199354 * 1065*5440Sjm199354 * Validate property identified in propid. 1066*5440Sjm199354 * 1067*5440Sjm199354 * Returns: VS_ERR_NONE 1068*5440Sjm199354 * VS_ERR_INVALID_VALUE 1069*5440Sjm199354 * VS_ERR_INVALID_PROPERTY 1070*5440Sjm199354 */ 1071*5440Sjm199354 static int 1072*5440Sjm199354 vs_validate(const vs_prop_hd_t *prop_hd, uint64_t propid) 1073*5440Sjm199354 { 1074*5440Sjm199354 uint64_t num; 1075*5440Sjm199354 const vs_props_t *vp = &prop_hd->vp_gen; 1076*5440Sjm199354 const vs_props_se_t *vep = &prop_hd->vp_se; 1077*5440Sjm199354 1078*5440Sjm199354 switch (propid) { 1079*5440Sjm199354 case VS_PROPID_MAXSIZE: 1080*5440Sjm199354 if ((vs_strtonum(vp->vp_maxsize, &num) != 0) || (num == 0)) 1081*5440Sjm199354 return (VS_ERR_INVALID_VALUE); 1082*5440Sjm199354 break; 1083*5440Sjm199354 case VS_PROPID_MAXSIZE_ACTION: 1084*5440Sjm199354 break; 1085*5440Sjm199354 case VS_PROPID_TYPES: 1086*5440Sjm199354 if (!vs_is_valid_types(vp->vp_types)) 1087*5440Sjm199354 return (VS_ERR_INVALID_VALUE); 1088*5440Sjm199354 break; 1089*5440Sjm199354 case VS_PROPID_SE_ENABLE: 1090*5440Sjm199354 break; 1091*5440Sjm199354 case VS_PROPID_SE_PORT: 1092*5440Sjm199354 if (vep->vep_port == 0) 1093*5440Sjm199354 return (VS_ERR_INVALID_VALUE); 1094*5440Sjm199354 break; 1095*5440Sjm199354 case VS_PROPID_SE_HOST: 1096*5440Sjm199354 if (!vs_is_valid_host(vep->vep_host)) 1097*5440Sjm199354 return (VS_ERR_INVALID_VALUE); 1098*5440Sjm199354 break; 1099*5440Sjm199354 case VS_PROPID_SE_MAXCONN: 1100*5440Sjm199354 if (vep->vep_maxconn < VS_VAL_SE_MAXCONN_MIN || 1101*5440Sjm199354 vep->vep_maxconn > VS_VAL_SE_MAXCONN_MAX) 1102*5440Sjm199354 return (VS_ERR_INVALID_VALUE); 1103*5440Sjm199354 break; 1104*5440Sjm199354 case VS_PROPID_VALUE_AUTH: 1105*5440Sjm199354 case VS_PROPID_VLOG: 1106*5440Sjm199354 break; 1107*5440Sjm199354 default: 1108*5440Sjm199354 return (VS_ERR_INVALID_PROPERTY); 1109*5440Sjm199354 } 1110*5440Sjm199354 1111*5440Sjm199354 return (VS_ERR_NONE); 1112*5440Sjm199354 } 1113*5440Sjm199354 1114*5440Sjm199354 1115*5440Sjm199354 /* 1116*5440Sjm199354 * vs_props_validate 1117*5440Sjm199354 * 1118*5440Sjm199354 * Validate properties identified in propids. 1119*5440Sjm199354 * 1120*5440Sjm199354 * Returns: VS_ERR_NONE 1121*5440Sjm199354 * VS_ERR_INVALID_VALUE 1122*5440Sjm199354 * VS_ERR_INVALID_PROPERTY 1123*5440Sjm199354 */ 1124*5440Sjm199354 int 1125*5440Sjm199354 vs_props_validate(const vs_props_t *props, uint64_t propids) 1126*5440Sjm199354 { 1127*5440Sjm199354 uint64_t propid; 1128*5440Sjm199354 vs_prop_hd_t prop_hd; 1129*5440Sjm199354 1130*5440Sjm199354 if ((propids & VS_PROPID_GEN_ALL) != propids) 1131*5440Sjm199354 return (VS_ERR_INVALID_PROPERTY); 1132*5440Sjm199354 1133*5440Sjm199354 (void) memset(&prop_hd, 0, sizeof (vs_prop_hd_t)); 1134*5440Sjm199354 prop_hd.vp_gen = *props; 1135*5440Sjm199354 prop_hd.vp_type = VS_PTYPE_GEN; 1136*5440Sjm199354 prop_hd.vp_ids = propids; 1137*5440Sjm199354 prop_hd.vp_all = VS_PROPID_GEN_ALL; 1138*5440Sjm199354 1139*5440Sjm199354 for (propid = 1LL; propid <= VS_PROPID_MAX; propid <<= 1) { 1140*5440Sjm199354 if ((propids & propid) == 0) 1141*5440Sjm199354 continue; 1142*5440Sjm199354 1143*5440Sjm199354 if (vs_validate(&prop_hd, propid) != VS_ERR_NONE) 1144*5440Sjm199354 return (VS_ERR_INVALID_VALUE); 1145*5440Sjm199354 } 1146*5440Sjm199354 1147*5440Sjm199354 return (VS_ERR_NONE); 1148*5440Sjm199354 } 1149*5440Sjm199354 1150*5440Sjm199354 1151*5440Sjm199354 /* 1152*5440Sjm199354 * vs_props_se_validate 1153*5440Sjm199354 * 1154*5440Sjm199354 * Validate properties identified in propids. 1155*5440Sjm199354 * 1156*5440Sjm199354 * Returns: VS_ERR_NONE 1157*5440Sjm199354 * VS_ERR_INVALID_VALUE 1158*5440Sjm199354 * VS_ERR_INVALID_PROPERTY 1159*5440Sjm199354 */ 1160*5440Sjm199354 int 1161*5440Sjm199354 vs_props_se_validate(const vs_props_se_t *se_props, uint64_t propids) 1162*5440Sjm199354 { 1163*5440Sjm199354 uint64_t propid; 1164*5440Sjm199354 vs_prop_hd_t prop_hd; 1165*5440Sjm199354 1166*5440Sjm199354 if ((propids & VS_PROPID_SE_ALL) != propids) 1167*5440Sjm199354 return (VS_ERR_INVALID_PROPERTY); 1168*5440Sjm199354 1169*5440Sjm199354 (void) memset(&prop_hd, 0, sizeof (vs_prop_hd_t)); 1170*5440Sjm199354 prop_hd.vp_se = *se_props; 1171*5440Sjm199354 prop_hd.vp_type = VS_PTYPE_SE; 1172*5440Sjm199354 prop_hd.vp_ids = propids; 1173*5440Sjm199354 prop_hd.vp_all = VS_PROPID_SE_ALL; 1174*5440Sjm199354 1175*5440Sjm199354 for (propid = 1LL; propid <= VS_PROPID_MAX; propid <<= 1) { 1176*5440Sjm199354 if ((propids & propid) == 0) 1177*5440Sjm199354 continue; 1178*5440Sjm199354 1179*5440Sjm199354 if (vs_validate(&prop_hd, propid) != VS_ERR_NONE) 1180*5440Sjm199354 return (VS_ERR_INVALID_VALUE); 1181*5440Sjm199354 } 1182*5440Sjm199354 1183*5440Sjm199354 return (VS_ERR_NONE); 1184*5440Sjm199354 } 1185*5440Sjm199354 1186*5440Sjm199354 1187*5440Sjm199354 /* 1188*5440Sjm199354 * vs_is_valid_types 1189*5440Sjm199354 * 1190*5440Sjm199354 * Checks that types property is a valid format: 1191*5440Sjm199354 * - doesn't exceed VS_VAL_TYPES_MAX 1192*5440Sjm199354 * - doesn't contain VS_VAL_TYPES_INVALID_CHARS 1193*5440Sjm199354 * - is correctly formatted - passes the parsing tests 1194*5440Sjm199354 * 1195*5440Sjm199354 * Returns 1 on success, 0 on failure 1196*5440Sjm199354 */ 1197*5440Sjm199354 static int 1198*5440Sjm199354 vs_is_valid_types(const char *types) 1199*5440Sjm199354 { 1200*5440Sjm199354 char buf[VS_VAL_TYPES_LEN]; 1201*5440Sjm199354 uint32_t len = VS_VAL_TYPES_LEN; 1202*5440Sjm199354 1203*5440Sjm199354 if (strlen(types) > VS_VAL_TYPES_LEN) 1204*5440Sjm199354 return (0); 1205*5440Sjm199354 1206*5440Sjm199354 if (strpbrk(types, VS_VAL_TYPES_INVALID_CHARS) != NULL) 1207*5440Sjm199354 return (0); 1208*5440Sjm199354 1209*5440Sjm199354 if (vs_parse_types(types, buf, &len) != 0) 1210*5440Sjm199354 return (0); 1211*5440Sjm199354 1212*5440Sjm199354 return (1); 1213*5440Sjm199354 } 1214*5440Sjm199354 1215*5440Sjm199354 1216*5440Sjm199354 /* 1217*5440Sjm199354 * vs_is_valid_host 1218*5440Sjm199354 * 1219*5440Sjm199354 * Returns 1 on success, 0 on failure 1220*5440Sjm199354 */ 1221*5440Sjm199354 static int 1222*5440Sjm199354 vs_is_valid_host(const char *host) 1223*5440Sjm199354 { 1224*5440Sjm199354 long naddr; 1225*5440Sjm199354 const char *p; 1226*5440Sjm199354 1227*5440Sjm199354 if (!host || *host == '\0') 1228*5440Sjm199354 return (0); 1229*5440Sjm199354 1230*5440Sjm199354 if ('0' <= host[0] && host[0] <= '9') { 1231*5440Sjm199354 /* ip address */ 1232*5440Sjm199354 if ((inet_pton(AF_INET, host, &naddr)) == 0) 1233*5440Sjm199354 return (0); 1234*5440Sjm199354 if ((naddr & IN_CLASSA_NET) == 0) 1235*5440Sjm199354 return (0); 1236*5440Sjm199354 if ((naddr & IN_CLASSC_HOST) == 0) 1237*5440Sjm199354 return (0); 1238*5440Sjm199354 } else { 1239*5440Sjm199354 /* hostname */ 1240*5440Sjm199354 p = host; 1241*5440Sjm199354 while (*p != '\0') { 1242*5440Sjm199354 if (!isascii(*p)) 1243*5440Sjm199354 return (0); 1244*5440Sjm199354 1245*5440Sjm199354 if (isalnum(*p) || 1246*5440Sjm199354 (*p == '.') || (*p == '-') || (*p == '_')) { 1247*5440Sjm199354 ++p; 1248*5440Sjm199354 } else { 1249*5440Sjm199354 return (0); 1250*5440Sjm199354 } 1251*5440Sjm199354 } 1252*5440Sjm199354 } 1253*5440Sjm199354 1254*5440Sjm199354 return (1); 1255*5440Sjm199354 } 1256*5440Sjm199354 1257*5440Sjm199354 1258*5440Sjm199354 /* 1259*5440Sjm199354 * vs_parse_types 1260*5440Sjm199354 * 1261*5440Sjm199354 * Replace comma separators with '\0'. 1262*5440Sjm199354 * 1263*5440Sjm199354 * Types contains comma separated rules each beginning with +|- 1264*5440Sjm199354 * - embedded commas are escaped by backslash 1265*5440Sjm199354 * - backslash is escaped by backslash 1266*5440Sjm199354 * - a single backslash not followed by comma is illegal 1267*5440Sjm199354 * 1268*5440Sjm199354 * On entry to the function len must contain the length of 1269*5440Sjm199354 * the buffer. On sucecssful exit len will contain the length 1270*5440Sjm199354 * of the parsed data within the buffer. 1271*5440Sjm199354 * 1272*5440Sjm199354 * Returns 0 on success, -1 on failure 1273*5440Sjm199354 */ 1274*5440Sjm199354 int 1275*5440Sjm199354 vs_parse_types(const char *types, char *buf, uint32_t *len) 1276*5440Sjm199354 { 1277*5440Sjm199354 char *p = (char *)types; 1278*5440Sjm199354 char *b = buf; 1279*5440Sjm199354 1280*5440Sjm199354 if (strlen(types) > *len) 1281*5440Sjm199354 return (-1); 1282*5440Sjm199354 1283*5440Sjm199354 if (strchr(VS_TYPES_RULES, *p) == NULL) 1284*5440Sjm199354 return (-1); 1285*5440Sjm199354 1286*5440Sjm199354 (void) memset(buf, 0, *len); 1287*5440Sjm199354 1288*5440Sjm199354 while (*p) { 1289*5440Sjm199354 switch (*p) { 1290*5440Sjm199354 case VS_TYPES_SEP: 1291*5440Sjm199354 if (*(p + 1) && 1292*5440Sjm199354 (strchr(VS_TYPES_RULES, *(p + 1))) == NULL) 1293*5440Sjm199354 return (-1); 1294*5440Sjm199354 *b = '\0'; 1295*5440Sjm199354 break; 1296*5440Sjm199354 case VS_TYPES_ESCAPE: 1297*5440Sjm199354 ++p; 1298*5440Sjm199354 if (*p == VS_TYPES_ESCAPE || *p == VS_TYPES_SEP) 1299*5440Sjm199354 *b = *p; 1300*5440Sjm199354 else 1301*5440Sjm199354 return (-1); 1302*5440Sjm199354 break; 1303*5440Sjm199354 default: 1304*5440Sjm199354 *b = *p; 1305*5440Sjm199354 } 1306*5440Sjm199354 ++p; 1307*5440Sjm199354 ++b; 1308*5440Sjm199354 } 1309*5440Sjm199354 1310*5440Sjm199354 *len = (b - buf) + 1; 1311*5440Sjm199354 1312*5440Sjm199354 return (0); 1313*5440Sjm199354 } 1314*5440Sjm199354 1315*5440Sjm199354 1316*5440Sjm199354 /* 1317*5440Sjm199354 * vs_statistics 1318*5440Sjm199354 */ 1319*5440Sjm199354 int 1320*5440Sjm199354 vs_statistics(vs_stats_t *stats) 1321*5440Sjm199354 { 1322*5440Sjm199354 int door_fd, rc = VS_ERR_NONE; 1323*5440Sjm199354 vs_stats_req_t *req; 1324*5440Sjm199354 vs_stats_t *buf; 1325*5440Sjm199354 door_arg_t arg; 1326*5440Sjm199354 1327*5440Sjm199354 if ((req = calloc(1, sizeof (vs_stats_req_t))) == NULL) 1328*5440Sjm199354 return (VS_ERR_SYS); 1329*5440Sjm199354 1330*5440Sjm199354 if ((buf = calloc(1, sizeof (vs_stats_t))) == NULL) { 1331*5440Sjm199354 free(req); 1332*5440Sjm199354 return (VS_ERR_SYS); 1333*5440Sjm199354 } 1334*5440Sjm199354 1335*5440Sjm199354 if ((door_fd = open(VS_STATS_DOOR_NAME, O_RDONLY)) < 0) { 1336*5440Sjm199354 free(req); 1337*5440Sjm199354 free(buf); 1338*5440Sjm199354 return (VS_ERR_DAEMON_COMM); 1339*5440Sjm199354 } 1340*5440Sjm199354 1341*5440Sjm199354 *req = VS_STATS_GET; 1342*5440Sjm199354 1343*5440Sjm199354 arg.data_ptr = (char *)req; 1344*5440Sjm199354 arg.data_size = sizeof (vs_stats_req_t); 1345*5440Sjm199354 arg.desc_ptr = NULL; 1346*5440Sjm199354 arg.desc_num = 0; 1347*5440Sjm199354 arg.rbuf = (char *)buf; 1348*5440Sjm199354 arg.rsize = sizeof (vs_stats_t); 1349*5440Sjm199354 1350*5440Sjm199354 if (door_call(door_fd, &arg) < 0) 1351*5440Sjm199354 rc = VS_ERR_DAEMON_COMM; 1352*5440Sjm199354 else 1353*5440Sjm199354 *stats = *buf; 1354*5440Sjm199354 1355*5440Sjm199354 (void) close(door_fd); 1356*5440Sjm199354 1357*5440Sjm199354 free(req); 1358*5440Sjm199354 free(buf); 1359*5440Sjm199354 return (rc); 1360*5440Sjm199354 } 1361*5440Sjm199354 1362*5440Sjm199354 1363*5440Sjm199354 /* 1364*5440Sjm199354 * vs_statistics_reset 1365*5440Sjm199354 */ 1366*5440Sjm199354 int 1367*5440Sjm199354 vs_statistics_reset() 1368*5440Sjm199354 { 1369*5440Sjm199354 int door_fd, rc; 1370*5440Sjm199354 vs_stats_req_t *req; 1371*5440Sjm199354 door_arg_t arg; 1372*5440Sjm199354 1373*5440Sjm199354 /* ensure that caller has authorization to reset stats */ 1374*5440Sjm199354 if ((rc = vs_checkauth(VS_VALUE_AUTH)) != VS_ERR_NONE) 1375*5440Sjm199354 return (rc); 1376*5440Sjm199354 1377*5440Sjm199354 if ((req = calloc(1, sizeof (vs_stats_req_t))) == NULL) 1378*5440Sjm199354 return (VS_ERR_SYS); 1379*5440Sjm199354 1380*5440Sjm199354 if ((door_fd = open(VS_STATS_DOOR_NAME, O_RDONLY)) < 0) { 1381*5440Sjm199354 free(req); 1382*5440Sjm199354 return (VS_ERR_DAEMON_COMM); 1383*5440Sjm199354 } 1384*5440Sjm199354 1385*5440Sjm199354 *req = VS_STATS_RESET; 1386*5440Sjm199354 1387*5440Sjm199354 arg.data_ptr = (char *)req; 1388*5440Sjm199354 arg.data_size = sizeof (vs_stats_req_t); 1389*5440Sjm199354 arg.desc_ptr = NULL; 1390*5440Sjm199354 arg.desc_num = 0; 1391*5440Sjm199354 arg.rbuf = NULL; 1392*5440Sjm199354 arg.rsize = 0; 1393*5440Sjm199354 1394*5440Sjm199354 if (door_call(door_fd, &arg) < 0) 1395*5440Sjm199354 rc = VS_ERR_DAEMON_COMM; 1396*5440Sjm199354 else 1397*5440Sjm199354 rc = VS_ERR_NONE; 1398*5440Sjm199354 1399*5440Sjm199354 (void) close(door_fd); 1400*5440Sjm199354 free(req); 1401*5440Sjm199354 return (rc); 1402*5440Sjm199354 } 1403*5440Sjm199354 1404*5440Sjm199354 1405*5440Sjm199354 /* 1406*5440Sjm199354 * vs_checkauth 1407*5440Sjm199354 */ 1408*5440Sjm199354 static int 1409*5440Sjm199354 vs_checkauth(char *auth) 1410*5440Sjm199354 { 1411*5440Sjm199354 struct passwd *pw; 1412*5440Sjm199354 uid_t uid; 1413*5440Sjm199354 1414*5440Sjm199354 uid = getuid(); 1415*5440Sjm199354 1416*5440Sjm199354 if ((pw = getpwuid(uid)) == NULL) 1417*5440Sjm199354 return (VS_ERR_SYS); 1418*5440Sjm199354 1419*5440Sjm199354 if (chkauthattr(auth, pw->pw_name) != 1) { 1420*5440Sjm199354 return (VS_ERR_AUTH); 1421*5440Sjm199354 } 1422*5440Sjm199354 1423*5440Sjm199354 return (VS_ERR_NONE); 1424*5440Sjm199354 } 1425*5440Sjm199354 1426*5440Sjm199354 1427*5440Sjm199354 /* 1428*5440Sjm199354 * vs_props_get_engines 1429*5440Sjm199354 * On input, count specifies the maximum number of engine ids to 1430*5440Sjm199354 * return. engids must be an array with count entries. 1431*5440Sjm199354 * On return, count specifies the number of engine ids being 1432*5440Sjm199354 * returned in engids. 1433*5440Sjm199354 */ 1434*5440Sjm199354 static int 1435*5440Sjm199354 vs_props_get_engines(vs_engid_t *engids, int *count) 1436*5440Sjm199354 { 1437*5440Sjm199354 int i = 0; 1438*5440Sjm199354 vs_scfctx_t vsc; 1439*5440Sjm199354 1440*5440Sjm199354 1441*5440Sjm199354 if (((vs_scf_ctx_open(&vsc)) != 0) || 1442*5440Sjm199354 ((vsc.vscf_iter = scf_iter_create(vsc.vscf_handle)) == NULL) || 1443*5440Sjm199354 (scf_iter_instance_pgs_typed(vsc.vscf_iter, vsc.vscf_inst, 1444*5440Sjm199354 SCF_GROUP_APPLICATION) != 0)) { 1445*5440Sjm199354 vs_scf_ctx_close(&vsc); 1446*5440Sjm199354 return (VS_ERR_SCF); 1447*5440Sjm199354 } 1448*5440Sjm199354 1449*5440Sjm199354 while ((i < VS_SE_MAX) && 1450*5440Sjm199354 (scf_iter_next_pg(vsc.vscf_iter, vsc.vscf_pgroup) == 1)) { 1451*5440Sjm199354 if (scf_pg_get_name(vsc.vscf_pgroup, engids[i], 1452*5440Sjm199354 VS_SE_NAME_LEN) < 0) { 1453*5440Sjm199354 vs_scf_ctx_close(&vsc); 1454*5440Sjm199354 return (VS_ERR_SCF); 1455*5440Sjm199354 } 1456*5440Sjm199354 1457*5440Sjm199354 if (strcmp(engids[i], VS_PGNAME_GENERAL) == 0) 1458*5440Sjm199354 *engids[i] = 0; 1459*5440Sjm199354 else 1460*5440Sjm199354 if (++i == *count) 1461*5440Sjm199354 break; 1462*5440Sjm199354 } 1463*5440Sjm199354 vs_scf_ctx_close(&vsc); 1464*5440Sjm199354 1465*5440Sjm199354 *count = i; 1466*5440Sjm199354 return (VS_ERR_NONE); 1467*5440Sjm199354 } 1468*5440Sjm199354 1469*5440Sjm199354 1470*5440Sjm199354 /* 1471*5440Sjm199354 * vs_scf_pg_count 1472*5440Sjm199354 */ 1473*5440Sjm199354 static int 1474*5440Sjm199354 vs_scf_pg_count(void) 1475*5440Sjm199354 { 1476*5440Sjm199354 int count = 0; 1477*5440Sjm199354 vs_scfctx_t vsc; 1478*5440Sjm199354 1479*5440Sjm199354 if ((vs_scf_ctx_open(&vsc) != 0) || 1480*5440Sjm199354 ((vsc.vscf_iter = scf_iter_create(vsc.vscf_handle)) == NULL) || 1481*5440Sjm199354 (scf_iter_instance_pgs_typed(vsc.vscf_iter, vsc.vscf_inst, 1482*5440Sjm199354 SCF_GROUP_APPLICATION) != 0)) { 1483*5440Sjm199354 vs_scf_ctx_close(&vsc); 1484*5440Sjm199354 return (-1); 1485*5440Sjm199354 } 1486*5440Sjm199354 1487*5440Sjm199354 while (scf_iter_next_pg(vsc.vscf_iter, vsc.vscf_pgroup) == 1) 1488*5440Sjm199354 ++count; 1489*5440Sjm199354 1490*5440Sjm199354 vs_scf_ctx_close(&vsc); 1491*5440Sjm199354 1492*5440Sjm199354 return (count); 1493*5440Sjm199354 } 1494*5440Sjm199354 1495*5440Sjm199354 1496*5440Sjm199354 /* 1497*5440Sjm199354 * vs_strtonum 1498*5440Sjm199354 * 1499*5440Sjm199354 * Converts a size string in the format into an integer. 1500*5440Sjm199354 * 1501*5440Sjm199354 * A size string is a numeric value followed by an optional unit 1502*5440Sjm199354 * specifier which is used as a multiplier to calculate a raw 1503*5440Sjm199354 * number. 1504*5440Sjm199354 * The size string format is: N[.N][KMGTP][B] 1505*5440Sjm199354 * 1506*5440Sjm199354 * The numeric value can contain a decimal portion. Unit specifiers 1507*5440Sjm199354 * are either a one-character or two-character string; i.e. "K" or 1508*5440Sjm199354 * "KB" for kilobytes. Unit specifiers must follow the numeric portion 1509*5440Sjm199354 * immediately, and are not case-sensitive. 1510*5440Sjm199354 * 1511*5440Sjm199354 * If either "B" is specified, or there is no unit specifier portion 1512*5440Sjm199354 * in the string, the numeric value is calculated with no multiplier 1513*5440Sjm199354 * (assumes a basic unit of "bytes"). 1514*5440Sjm199354 * 1515*5440Sjm199354 * Returns: 1516*5440Sjm199354 * -1: Failure; errno set to specify the error. 1517*5440Sjm199354 * 0: Success. 1518*5440Sjm199354 */ 1519*5440Sjm199354 int 1520*5440Sjm199354 vs_strtonum(const char *value, uint64_t *num) 1521*5440Sjm199354 { 1522*5440Sjm199354 char *end; 1523*5440Sjm199354 int shift; 1524*5440Sjm199354 double fval; 1525*5440Sjm199354 1526*5440Sjm199354 *num = 0; 1527*5440Sjm199354 1528*5440Sjm199354 /* Check to see if this looks like a number. */ 1529*5440Sjm199354 if ((value[0] < '0' || value[0] > '9') && value[0] != '.') { 1530*5440Sjm199354 errno = EINVAL; 1531*5440Sjm199354 return (-1); 1532*5440Sjm199354 } 1533*5440Sjm199354 1534*5440Sjm199354 /* Rely on stroll() to process the numeric portion. */ 1535*5440Sjm199354 errno = 0; 1536*5440Sjm199354 *num = strtoll(value, &end, 10); 1537*5440Sjm199354 1538*5440Sjm199354 /* 1539*5440Sjm199354 * Check for ERANGE, which indicates that the value is too large to 1540*5440Sjm199354 * fit in a 64-bit value. 1541*5440Sjm199354 */ 1542*5440Sjm199354 if (errno != 0) 1543*5440Sjm199354 return (-1); 1544*5440Sjm199354 1545*5440Sjm199354 /* 1546*5440Sjm199354 * If we have a decimal value, then do the computation with floating 1547*5440Sjm199354 * point arithmetic. Otherwise, use standard arithmetic. 1548*5440Sjm199354 */ 1549*5440Sjm199354 if (*end == '.') { 1550*5440Sjm199354 fval = strtod(value, &end); 1551*5440Sjm199354 1552*5440Sjm199354 if ((shift = vs_strtoshift(end)) == -1) 1553*5440Sjm199354 return (-1); /* errno set */ 1554*5440Sjm199354 1555*5440Sjm199354 fval *= pow(2, shift); 1556*5440Sjm199354 if (fval > UINT64_MAX) { 1557*5440Sjm199354 errno = ERANGE; 1558*5440Sjm199354 return (-1); 1559*5440Sjm199354 } 1560*5440Sjm199354 1561*5440Sjm199354 *num = (uint64_t)fval; 1562*5440Sjm199354 } else { 1563*5440Sjm199354 if ((shift = vs_strtoshift(end)) == -1) 1564*5440Sjm199354 return (-1); /* errno set */ 1565*5440Sjm199354 1566*5440Sjm199354 /* Check for overflow */ 1567*5440Sjm199354 if (shift >= 64 || (*num << shift) >> shift != *num) { 1568*5440Sjm199354 errno = ERANGE; 1569*5440Sjm199354 return (-1); 1570*5440Sjm199354 } 1571*5440Sjm199354 1572*5440Sjm199354 *num <<= shift; 1573*5440Sjm199354 } 1574*5440Sjm199354 1575*5440Sjm199354 return (0); 1576*5440Sjm199354 } 1577*5440Sjm199354 1578*5440Sjm199354 1579*5440Sjm199354 /* 1580*5440Sjm199354 * vs_strtoshift 1581*5440Sjm199354 * 1582*5440Sjm199354 * Converts a unit specifier string into a number of bits that 1583*5440Sjm199354 * a numeric value must be shifted. 1584*5440Sjm199354 * 1585*5440Sjm199354 * Returns: 1586*5440Sjm199354 * -1: Failure; errno set to specify the error. 1587*5440Sjm199354 * >-1: Success; the shift count. 1588*5440Sjm199354 * 1589*5440Sjm199354 */ 1590*5440Sjm199354 static int 1591*5440Sjm199354 vs_strtoshift(const char *buf) 1592*5440Sjm199354 { 1593*5440Sjm199354 const char *ends = "BKMGTPEZ"; 1594*5440Sjm199354 int i; 1595*5440Sjm199354 1596*5440Sjm199354 if (buf[0] == '\0') 1597*5440Sjm199354 return (0); 1598*5440Sjm199354 for (i = 0; i < strlen(ends); i++) { 1599*5440Sjm199354 if (toupper(buf[0]) == ends[i]) 1600*5440Sjm199354 break; 1601*5440Sjm199354 } 1602*5440Sjm199354 if (i == strlen(ends)) { 1603*5440Sjm199354 errno = EINVAL; 1604*5440Sjm199354 return (-1); 1605*5440Sjm199354 } 1606*5440Sjm199354 1607*5440Sjm199354 /* Allow trailing 'b' characters except in the case of 'BB'. */ 1608*5440Sjm199354 if (buf[1] == '\0' || (toupper(buf[1]) == 'B' && buf[2] == '\0' && 1609*5440Sjm199354 toupper(buf[0]) != 'B')) { 1610*5440Sjm199354 return (10 * i); 1611*5440Sjm199354 } 1612*5440Sjm199354 1613*5440Sjm199354 errno = EINVAL; 1614*5440Sjm199354 return (-1); 1615*5440Sjm199354 } 1616