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