1911106dfSjm199354 /* 2911106dfSjm199354 * CDDL HEADER START 3911106dfSjm199354 * 4911106dfSjm199354 * The contents of this file are subject to the terms of the 5911106dfSjm199354 * Common Development and Distribution License (the "License"). 6911106dfSjm199354 * You may not use this file except in compliance with the License. 7911106dfSjm199354 * 8911106dfSjm199354 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9911106dfSjm199354 * or http://www.opensolaris.org/os/licensing. 10911106dfSjm199354 * See the License for the specific language governing permissions 11911106dfSjm199354 * and limitations under the License. 12911106dfSjm199354 * 13911106dfSjm199354 * When distributing Covered Code, include this CDDL HEADER in each 14911106dfSjm199354 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15911106dfSjm199354 * If applicable, add the following below this CDDL HEADER, with the 16911106dfSjm199354 * fields enclosed by brackets "[]" replaced with your own identifying 17911106dfSjm199354 * information: Portions Copyright [yyyy] [name of copyright owner] 18911106dfSjm199354 * 19911106dfSjm199354 * CDDL HEADER END 20911106dfSjm199354 */ 21911106dfSjm199354 /* 22*bfc848c6Sjm199354 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23911106dfSjm199354 * Use is subject to license terms. 24911106dfSjm199354 */ 25911106dfSjm199354 26911106dfSjm199354 #pragma ident "%Z%%M% %I% %E% SMI" 27911106dfSjm199354 28911106dfSjm199354 #include <string.h> 29911106dfSjm199354 #include <stdio.h> 30911106dfSjm199354 #include <stdlib.h> 31911106dfSjm199354 #include <unistd.h> 32911106dfSjm199354 #include <ctype.h> 33911106dfSjm199354 #include <math.h> 34911106dfSjm199354 #include <limits.h> 35911106dfSjm199354 #include <libscf.h> 36911106dfSjm199354 #include <errno.h> 37911106dfSjm199354 #include <fcntl.h> 38911106dfSjm199354 #include <door.h> 39911106dfSjm199354 #include <pwd.h> 40911106dfSjm199354 #include <auth_attr.h> 41911106dfSjm199354 #include <secdb.h> 42911106dfSjm199354 #include <sys/socket.h> 43911106dfSjm199354 #include <arpa/inet.h> 44911106dfSjm199354 #include <libintl.h> 45911106dfSjm199354 #include <libvscan.h> 46911106dfSjm199354 47911106dfSjm199354 #define VS_INSTANCE_FMRI "svc:/system/filesystem/vscan:icap" 48911106dfSjm199354 49911106dfSjm199354 /* SMF property group and property names */ 50911106dfSjm199354 #define VS_PGNAME_GENERAL "vs_general" 51*bfc848c6Sjm199354 #define VS_PGNAME_ENGINE_PREFIX "vs_engine_" 52*bfc848c6Sjm199354 #define VS_PGNAME_ENGINE_LEN VS_SE_NAME_LEN + 16 53911106dfSjm199354 54911106dfSjm199354 #define VS_PNAME_MAXSIZE "maxsize" 55911106dfSjm199354 #define VS_PNAME_MAXSIZE_ACTION "maxsize_action" 56911106dfSjm199354 #define VS_PNAME_TYPES "types" 57911106dfSjm199354 #define VS_PNAME_VLOG "viruslog" 58911106dfSjm199354 59911106dfSjm199354 #define VS_PNAME_SE_ENABLE "enable" 60911106dfSjm199354 #define VS_PNAME_SE_HOST "host" 61911106dfSjm199354 #define VS_PNAME_SE_PORT "port" 62911106dfSjm199354 #define VS_PNAME_SE_MAXCONN "max_connect" 63911106dfSjm199354 #define VS_PNAME_VAUTH "value_authorization" 64911106dfSjm199354 65911106dfSjm199354 66911106dfSjm199354 /* types string processing */ 67911106dfSjm199354 #define VS_TYPES_SEP ',' 68911106dfSjm199354 #define VS_TYPES_ESCAPE '\\' 69911106dfSjm199354 #define VS_TYPES_RULES "+-" 70911106dfSjm199354 71911106dfSjm199354 72911106dfSjm199354 /* 73911106dfSjm199354 * The SCF context enapsulating the SCF objects used in the 74911106dfSjm199354 * repository load and store routines vs_scf_values_get() 75911106dfSjm199354 * and vs_scf_values_set(). 76911106dfSjm199354 * 77911106dfSjm199354 * The context is always opened before a get or set, then 78911106dfSjm199354 * closed when finished (or on error); the open does an 79911106dfSjm199354 * initial setup, while inside the get and set functions, 80911106dfSjm199354 * additional objects within the context may be selectively 81911106dfSjm199354 * initialized for use, depending on the actions needed and 82911106dfSjm199354 * the properties being operated on. 83911106dfSjm199354 */ 84911106dfSjm199354 typedef struct vs_scfctx { 85911106dfSjm199354 scf_handle_t *vscf_handle; 86911106dfSjm199354 scf_instance_t *vscf_inst; 87911106dfSjm199354 scf_propertygroup_t *vscf_pgroup; 88911106dfSjm199354 scf_transaction_t *vscf_tx; 89911106dfSjm199354 scf_iter_t *vscf_iter; 90911106dfSjm199354 scf_property_t *vscf_prop[VS_NUM_PROPIDS]; 91911106dfSjm199354 scf_transaction_entry_t *vscf_ent[VS_NUM_PROPIDS]; 92911106dfSjm199354 scf_value_t *vscf_val[VS_NUM_PROPIDS]; 93911106dfSjm199354 } vs_scfctx_t; 94911106dfSjm199354 95911106dfSjm199354 /* 96911106dfSjm199354 * The vscan property definition. Maps the property id with the name 97911106dfSjm199354 * and type used to store the property in the repository. 98911106dfSjm199354 * A table of these definitions is defined with a single entry per 99911106dfSjm199354 * property. 100911106dfSjm199354 */ 101911106dfSjm199354 typedef struct { 102911106dfSjm199354 const char *vpd_name; 103911106dfSjm199354 uint64_t vpd_id; 104911106dfSjm199354 scf_type_t vpd_type; 105911106dfSjm199354 } vs_propdef_t; 106911106dfSjm199354 107911106dfSjm199354 typedef enum { 108911106dfSjm199354 VS_PTYPE_GEN, 109911106dfSjm199354 VS_PTYPE_SE 110911106dfSjm199354 } vs_prop_type_t; 111911106dfSjm199354 112911106dfSjm199354 typedef struct vs_prop_hd { 113911106dfSjm199354 vs_prop_type_t vp_type; 114911106dfSjm199354 uint64_t vp_ids; 115911106dfSjm199354 uint64_t vp_all; 116911106dfSjm199354 union { 117911106dfSjm199354 vs_props_t vp_gen; 118911106dfSjm199354 vs_props_se_t vp_se; 119911106dfSjm199354 } vp_props; 120911106dfSjm199354 } vs_prop_hd_t; 121911106dfSjm199354 122911106dfSjm199354 #define vp_gen vp_props.vp_gen 123911106dfSjm199354 #define vp_se vp_props.vp_se 124911106dfSjm199354 125911106dfSjm199354 /* 126911106dfSjm199354 * Default values - these are used to return valid data 127911106dfSjm199354 * to the caller in cases where invalid or unexpected values 128911106dfSjm199354 * are found in the repository. 129911106dfSjm199354 * 130911106dfSjm199354 * Note: These values must be kept in sync with those defined 131911106dfSjm199354 * in the service manifest. 132911106dfSjm199354 */ 133911106dfSjm199354 static const boolean_t vs_dflt_allow = B_TRUE; 134911106dfSjm199354 static const boolean_t vs_dflt_enable = B_TRUE; 135911106dfSjm199354 static const char *vs_dflt_maxsize = "1GB"; 136911106dfSjm199354 static const char *vs_dflt_host = ""; 137911106dfSjm199354 static const uint16_t vs_dflt_port = 1344; 138911106dfSjm199354 static const uint16_t vs_dflt_maxconn = 32L; 139911106dfSjm199354 static const char *vs_dflt_types = "+*"; 140911106dfSjm199354 static const char *vs_dflt_vlog = ""; 141911106dfSjm199354 142911106dfSjm199354 /* Property definition table */ 143911106dfSjm199354 static const vs_propdef_t vs_propdefs[] = { 144911106dfSjm199354 /* general properties */ 145911106dfSjm199354 { VS_PNAME_MAXSIZE, VS_PROPID_MAXSIZE, SCF_TYPE_ASTRING }, 146911106dfSjm199354 { VS_PNAME_MAXSIZE_ACTION, VS_PROPID_MAXSIZE_ACTION, SCF_TYPE_BOOLEAN }, 147911106dfSjm199354 { VS_PNAME_TYPES, VS_PROPID_TYPES, SCF_TYPE_ASTRING }, 148911106dfSjm199354 { VS_PNAME_VLOG, VS_PROPID_VLOG, SCF_TYPE_ASTRING }, 149911106dfSjm199354 /* scan engine properties */ 150911106dfSjm199354 { VS_PNAME_SE_ENABLE, VS_PROPID_SE_ENABLE, SCF_TYPE_BOOLEAN }, 151911106dfSjm199354 { VS_PNAME_SE_HOST, VS_PROPID_SE_HOST, SCF_TYPE_HOST }, 152911106dfSjm199354 { VS_PNAME_SE_PORT, VS_PROPID_SE_PORT, SCF_TYPE_INTEGER }, 153911106dfSjm199354 { VS_PNAME_SE_MAXCONN, VS_PROPID_SE_MAXCONN, SCF_TYPE_INTEGER }, 154911106dfSjm199354 { VS_PNAME_VAUTH, VS_PROPID_VALUE_AUTH, SCF_TYPE_ASTRING } 155911106dfSjm199354 }; 156911106dfSjm199354 157911106dfSjm199354 static const int vs_npropdefs = sizeof (vs_propdefs)/sizeof (vs_propdef_t); 158911106dfSjm199354 159911106dfSjm199354 /* Local functions */ 160911106dfSjm199354 static const vs_propdef_t *vs_get_propdef(uint64_t); 161911106dfSjm199354 static void vs_default_value(vs_prop_hd_t *, const uint64_t); 162911106dfSjm199354 163911106dfSjm199354 static int vs_scf_values_get(const char *, vs_prop_hd_t *); 164911106dfSjm199354 static int vs_scf_get(const vs_propdef_t *, vs_prop_hd_t *, vs_scfctx_t *, int); 165911106dfSjm199354 166911106dfSjm199354 static int vs_scf_values_set(const char *, vs_prop_hd_t *); 167911106dfSjm199354 static int vs_scf_set(const vs_propdef_t *, vs_prop_hd_t *, vs_scfctx_t *, int); 168911106dfSjm199354 static int vs_scf_pg_create(const char *, vs_prop_hd_t *); 169*bfc848c6Sjm199354 static int vs_scf_pg_delete(const char *); 170911106dfSjm199354 171911106dfSjm199354 static int vs_scf_ctx_open(vs_scfctx_t *); 172911106dfSjm199354 static void vs_scf_ctx_close(vs_scfctx_t *); 173911106dfSjm199354 174911106dfSjm199354 static int vs_validate(const vs_prop_hd_t *, uint64_t); 175911106dfSjm199354 static int vs_is_valid_types(const char *); 176911106dfSjm199354 static int vs_is_valid_host(const char *); 177911106dfSjm199354 static int vs_checkauth(char *); 178911106dfSjm199354 179*bfc848c6Sjm199354 static int vs_props_get_engines(char *[], int *); 180*bfc848c6Sjm199354 static void vs_engid_to_pgname(const char *, char [VS_PGNAME_ENGINE_LEN]); 181911106dfSjm199354 static int vs_scf_pg_count(void); 182911106dfSjm199354 static int vs_strtoshift(const char *); 183911106dfSjm199354 184911106dfSjm199354 185911106dfSjm199354 /* 186911106dfSjm199354 * vs_props_get_all 187911106dfSjm199354 * 188911106dfSjm199354 * Retrieves the general service properties and all properties 189911106dfSjm199354 * for all scan engines from the repository. 190911106dfSjm199354 * 191911106dfSjm199354 * If invalid property values are found, the values are corrected to 192911106dfSjm199354 * the default value. 193911106dfSjm199354 * 194911106dfSjm199354 * Return codes: 195911106dfSjm199354 * VS_ERR_VS_ERR_NONE 196911106dfSjm199354 * VS_ERR_SCF 197911106dfSjm199354 * VS_ERR_SYS 198911106dfSjm199354 */ 199911106dfSjm199354 int 200911106dfSjm199354 vs_props_get_all(vs_props_all_t *va) 201911106dfSjm199354 { 202911106dfSjm199354 int i, rc, n; 203*bfc848c6Sjm199354 char *engids[VS_SE_MAX]; 204911106dfSjm199354 205911106dfSjm199354 (void) memset(va, 0, sizeof (vs_props_all_t)); 206911106dfSjm199354 if ((rc = vs_props_get(&va->va_props, VS_PROPID_GEN_ALL)) 207911106dfSjm199354 != VS_ERR_NONE) 208911106dfSjm199354 return (rc); 209911106dfSjm199354 210911106dfSjm199354 n = VS_SE_MAX; 211911106dfSjm199354 if ((rc = vs_props_get_engines(engids, &n)) != VS_ERR_NONE) 212911106dfSjm199354 return (rc); 213911106dfSjm199354 214911106dfSjm199354 for (i = 0; i < n; i++) { 215*bfc848c6Sjm199354 if ((rc = vs_props_se_get(engids[i], 216*bfc848c6Sjm199354 &va->va_se[i], VS_PROPID_SE_ALL)) != VS_ERR_NONE) 217*bfc848c6Sjm199354 break; 218911106dfSjm199354 } 219911106dfSjm199354 220*bfc848c6Sjm199354 /* free engids allocated in vs_props_get_engines */ 221*bfc848c6Sjm199354 for (i = 0; i < VS_SE_MAX; i++) { 222*bfc848c6Sjm199354 if (engids[i] != NULL) 223*bfc848c6Sjm199354 free(engids[i]); 224*bfc848c6Sjm199354 } 225*bfc848c6Sjm199354 226*bfc848c6Sjm199354 return (rc); 227911106dfSjm199354 } 228911106dfSjm199354 229911106dfSjm199354 230911106dfSjm199354 /* 231911106dfSjm199354 * vs_props_get 232911106dfSjm199354 * 233911106dfSjm199354 * Retrieves values for the specified general service properties from 234911106dfSjm199354 * the repository. 235911106dfSjm199354 * 236911106dfSjm199354 * If invalid property values are found, the values are corrected to 237911106dfSjm199354 * the default value. 238911106dfSjm199354 * 239911106dfSjm199354 * Return codes: 240911106dfSjm199354 * VS_ERR_VS_ERR_NONE 241911106dfSjm199354 * VS_ERR_INVALID_PROPERTY 242911106dfSjm199354 * VS_ERR_SCF 243911106dfSjm199354 * VS_ERR_SYS 244911106dfSjm199354 */ 245911106dfSjm199354 int 246911106dfSjm199354 vs_props_get(vs_props_t *vp, uint64_t propids) 247911106dfSjm199354 { 248911106dfSjm199354 int rc; 249911106dfSjm199354 vs_prop_hd_t prop_hd; 250911106dfSjm199354 251911106dfSjm199354 if ((propids & VS_PROPID_GEN_ALL) != propids) 252911106dfSjm199354 return (VS_ERR_INVALID_PROPERTY); 253911106dfSjm199354 254911106dfSjm199354 (void) memset(&prop_hd, 0, sizeof (vs_prop_hd_t)); 255911106dfSjm199354 prop_hd.vp_type = VS_PTYPE_GEN; 256911106dfSjm199354 prop_hd.vp_ids = propids; 257911106dfSjm199354 prop_hd.vp_all = VS_PROPID_GEN_ALL; 258911106dfSjm199354 259911106dfSjm199354 rc = vs_scf_values_get(VS_PGNAME_GENERAL, &prop_hd); 260911106dfSjm199354 261911106dfSjm199354 *vp = prop_hd.vp_gen; 262911106dfSjm199354 return (rc); 263911106dfSjm199354 } 264911106dfSjm199354 265911106dfSjm199354 266911106dfSjm199354 /* 267911106dfSjm199354 * vs_props_set 268911106dfSjm199354 * 269911106dfSjm199354 * Changes values for the specified general service properties 270911106dfSjm199354 * in the repository. 271911106dfSjm199354 * 272911106dfSjm199354 * Return codes: 273911106dfSjm199354 * VS_ERR_VS_ERR_NONE 274911106dfSjm199354 * VS_ERR_INVALID_PROPERTY 275911106dfSjm199354 * VS_ERR_INVALID_VALUE 276911106dfSjm199354 * VS_ERR_SCF 277911106dfSjm199354 * VS_ERR_SYS 278911106dfSjm199354 */ 279911106dfSjm199354 int 280911106dfSjm199354 vs_props_set(const vs_props_t *vp, uint64_t propids) 281911106dfSjm199354 { 282911106dfSjm199354 vs_prop_hd_t prop_hd; 283911106dfSjm199354 284911106dfSjm199354 if ((propids & VS_PROPID_GEN_ALL) != propids) 285911106dfSjm199354 return (VS_ERR_INVALID_PROPERTY); 286911106dfSjm199354 287911106dfSjm199354 (void) memset(&prop_hd, 0, sizeof (vs_prop_hd_t)); 288911106dfSjm199354 prop_hd.vp_type = VS_PTYPE_GEN; 289911106dfSjm199354 prop_hd.vp_ids = propids; 290911106dfSjm199354 prop_hd.vp_all = VS_PROPID_GEN_ALL; 291911106dfSjm199354 prop_hd.vp_gen = *vp; 292911106dfSjm199354 return (vs_scf_values_set(VS_PGNAME_GENERAL, &prop_hd)); 293911106dfSjm199354 } 294911106dfSjm199354 295911106dfSjm199354 296911106dfSjm199354 /* 297911106dfSjm199354 * vs_props_se_get 298911106dfSjm199354 * 299911106dfSjm199354 * Retrieves values for the specified scan engine properties from the 300911106dfSjm199354 * repository. 301911106dfSjm199354 * 302911106dfSjm199354 * If the enable property is set (true), the host property is 303911106dfSjm199354 * checked for validity. If it is not valid, the requested values 304911106dfSjm199354 * are returned with the enable propery set to off (false) 305911106dfSjm199354 * 306911106dfSjm199354 * Return codes: 307911106dfSjm199354 * VS_ERR_VS_ERR_NONE 308911106dfSjm199354 * VS_ERR_INVALID_PROPERTY 309911106dfSjm199354 * VS_ERR_SCF 310911106dfSjm199354 * VS_ERR_SYS 311911106dfSjm199354 */ 312911106dfSjm199354 int 313911106dfSjm199354 vs_props_se_get(char *engid, vs_props_se_t *sep, uint64_t propids) 314911106dfSjm199354 { 315911106dfSjm199354 int rc; 316*bfc848c6Sjm199354 char pgname[VS_PGNAME_ENGINE_LEN]; 317911106dfSjm199354 vs_prop_hd_t prop_hd; 318911106dfSjm199354 319911106dfSjm199354 /* VS_PGNAME_GENERAL is a reserved for GENERAL property group */ 320911106dfSjm199354 if (strcmp(engid, VS_PGNAME_GENERAL) == 0) 321911106dfSjm199354 return (VS_ERR_INVALID_SE); 322911106dfSjm199354 323911106dfSjm199354 if ((propids & VS_PROPID_SE_ALL) != propids) 324911106dfSjm199354 return (VS_ERR_INVALID_PROPERTY); 325911106dfSjm199354 326911106dfSjm199354 (void) memset(&prop_hd, 0, sizeof (vs_prop_hd_t)); 327911106dfSjm199354 prop_hd.vp_type = VS_PTYPE_SE; 328911106dfSjm199354 prop_hd.vp_ids = propids; 329911106dfSjm199354 prop_hd.vp_all = VS_PROPID_SE_ALL; 330911106dfSjm199354 (void) strlcpy(prop_hd.vp_se.vep_engid, engid, VS_SE_NAME_LEN); 331911106dfSjm199354 332911106dfSjm199354 /* If getting enable, get the host property too */ 333911106dfSjm199354 if ((propids & VS_PROPID_SE_ENABLE)) 334911106dfSjm199354 prop_hd.vp_ids |= VS_PROPID_SE_HOST; 335911106dfSjm199354 336911106dfSjm199354 /* Load values from the repository */ 337*bfc848c6Sjm199354 vs_engid_to_pgname(engid, pgname); 338*bfc848c6Sjm199354 rc = vs_scf_values_get(pgname, &prop_hd); 339911106dfSjm199354 if (rc != VS_ERR_NONE) 340911106dfSjm199354 return (rc); 341911106dfSjm199354 342911106dfSjm199354 /* 343911106dfSjm199354 * If the host is invalid and the enable property is on, 344911106dfSjm199354 * return enable property as off 345911106dfSjm199354 */ 346911106dfSjm199354 if ((prop_hd.vp_ids & VS_PROPID_SE_HOST) && 347911106dfSjm199354 (vs_validate(&prop_hd, VS_PROPID_SE_HOST) != VS_ERR_NONE)) { 348911106dfSjm199354 prop_hd.vp_se.vep_enable = B_FALSE; 349911106dfSjm199354 } 350911106dfSjm199354 351911106dfSjm199354 *sep = prop_hd.vp_se; 352911106dfSjm199354 return (rc); 353911106dfSjm199354 } 354911106dfSjm199354 355911106dfSjm199354 356911106dfSjm199354 357911106dfSjm199354 /* 358911106dfSjm199354 * vs_props_se_set 359911106dfSjm199354 * 360911106dfSjm199354 * Changes the values for the specified scan engine properties in the 361911106dfSjm199354 * repository. 362911106dfSjm199354 * 363911106dfSjm199354 * If the enable property is being changed to true in this operation, 364911106dfSjm199354 * a host property must also be specified, or already exist in the 365911106dfSjm199354 * repository. 366911106dfSjm199354 * 367911106dfSjm199354 * Return codes: 368911106dfSjm199354 * VS_ERR_NONE 369911106dfSjm199354 * VS_ERR_INVALID_PROPERTY 370911106dfSjm199354 * VS_ERR_INVALID_VALUE 371911106dfSjm199354 * VS_ERR_SCF 372911106dfSjm199354 * VS_ERR_SYS 373911106dfSjm199354 */ 374911106dfSjm199354 int 375911106dfSjm199354 vs_props_se_set(char *engid, const vs_props_se_t *sep, uint64_t propids) 376911106dfSjm199354 { 377911106dfSjm199354 int rc; 378*bfc848c6Sjm199354 char pgname[VS_PGNAME_ENGINE_LEN]; 379911106dfSjm199354 vs_prop_hd_t prop_hd; 380911106dfSjm199354 381911106dfSjm199354 /* VS_PGNAME_GENERAL is a reserved for GENERAL property group */ 382911106dfSjm199354 if (strcmp(engid, VS_PGNAME_GENERAL) == 0) 383911106dfSjm199354 return (VS_ERR_INVALID_SE); 384911106dfSjm199354 385911106dfSjm199354 if ((propids & VS_PROPID_SE_ALL) != propids) 386911106dfSjm199354 return (VS_ERR_INVALID_PROPERTY); 387911106dfSjm199354 388911106dfSjm199354 (void) memset(&prop_hd, 0, sizeof (vs_prop_hd_t)); 389911106dfSjm199354 prop_hd.vp_type = VS_PTYPE_SE; 390911106dfSjm199354 prop_hd.vp_all = VS_PROPID_SE_ALL; 391911106dfSjm199354 392*bfc848c6Sjm199354 vs_engid_to_pgname(engid, pgname); 393*bfc848c6Sjm199354 394911106dfSjm199354 /* 395911106dfSjm199354 * if enabling a scan engine, ensure that a valid host 396911106dfSjm199354 * is also being set, or already exists in the repository 397911106dfSjm199354 */ 398911106dfSjm199354 if ((propids & VS_PROPID_SE_ENABLE) && (sep->vep_enable == B_TRUE) && 399911106dfSjm199354 !(propids & VS_PROPID_SE_HOST)) { 400911106dfSjm199354 401911106dfSjm199354 prop_hd.vp_ids = VS_PROPID_SE_HOST; 402*bfc848c6Sjm199354 if ((rc = vs_scf_values_get(pgname, &prop_hd)) != VS_ERR_NONE) 403911106dfSjm199354 return (rc); 404911106dfSjm199354 405911106dfSjm199354 if (vs_validate(&prop_hd, VS_PROPID_SE_HOST) != VS_ERR_NONE) 406911106dfSjm199354 return (VS_ERR_INVALID_HOST); 407911106dfSjm199354 } 408911106dfSjm199354 409911106dfSjm199354 prop_hd.vp_ids = propids; 410911106dfSjm199354 prop_hd.vp_se = *sep; 411911106dfSjm199354 412*bfc848c6Sjm199354 return (vs_scf_values_set(pgname, &prop_hd)); 413911106dfSjm199354 } 414911106dfSjm199354 415911106dfSjm199354 416911106dfSjm199354 /* 417911106dfSjm199354 * vs_props_se_create 418911106dfSjm199354 */ 419911106dfSjm199354 int 420911106dfSjm199354 vs_props_se_create(char *engid, const vs_props_se_t *sep, uint64_t propids) 421911106dfSjm199354 { 422911106dfSjm199354 int n; 423*bfc848c6Sjm199354 char pgname[VS_PGNAME_ENGINE_LEN]; 424911106dfSjm199354 vs_prop_hd_t prop_hd; 425911106dfSjm199354 426911106dfSjm199354 if ((propids & VS_PROPID_SE_ALL) != propids) 427911106dfSjm199354 return (VS_ERR_INVALID_PROPERTY); 428911106dfSjm199354 429911106dfSjm199354 /* VS_PGNAME_GENERAL is a reserved for GENERAL property group */ 430911106dfSjm199354 if (strcmp(engid, VS_PGNAME_GENERAL) == 0) 431911106dfSjm199354 return (VS_ERR_INVALID_SE); 432911106dfSjm199354 433911106dfSjm199354 if ((n = vs_scf_pg_count()) == -1) 434911106dfSjm199354 return (VS_ERR_SCF); 435911106dfSjm199354 436911106dfSjm199354 if (n == VS_SE_MAX) 437911106dfSjm199354 return (VS_ERR_MAX_SE); 438911106dfSjm199354 439*bfc848c6Sjm199354 vs_engid_to_pgname(engid, pgname); 440*bfc848c6Sjm199354 441911106dfSjm199354 (void) memset(&prop_hd, 0, sizeof (vs_prop_hd_t)); 442911106dfSjm199354 prop_hd.vp_type = VS_PTYPE_SE; 443911106dfSjm199354 prop_hd.vp_all = VS_PROPID_SE_ALL; 444911106dfSjm199354 prop_hd.vp_ids = propids | VS_PROPID_VALUE_AUTH; 445911106dfSjm199354 prop_hd.vp_se = *sep; 446911106dfSjm199354 447*bfc848c6Sjm199354 /* if hostname not specified, default it to engid */ 448*bfc848c6Sjm199354 if ((propids & VS_PROPID_SE_HOST) == 0) { 449*bfc848c6Sjm199354 (void) strlcpy(prop_hd.vp_se.vep_host, engid, MAXHOSTNAMELEN); 450*bfc848c6Sjm199354 prop_hd.vp_ids |= VS_PROPID_SE_HOST; 451*bfc848c6Sjm199354 } 452911106dfSjm199354 453*bfc848c6Sjm199354 return (vs_scf_pg_create(pgname, &prop_hd)); 454911106dfSjm199354 } 455911106dfSjm199354 456911106dfSjm199354 457911106dfSjm199354 /* 458911106dfSjm199354 * vs_props_se_delete 459911106dfSjm199354 */ 460911106dfSjm199354 int 461911106dfSjm199354 vs_props_se_delete(const char *engid) 462911106dfSjm199354 { 463*bfc848c6Sjm199354 char pgname[VS_PGNAME_ENGINE_LEN]; 464911106dfSjm199354 465911106dfSjm199354 /* VS_PGNAME_GENERAL is a reserved for GENERAL property group */ 466911106dfSjm199354 if (strcmp(engid, VS_PGNAME_GENERAL) == 0) 467911106dfSjm199354 return (VS_ERR_INVALID_SE); 468911106dfSjm199354 469*bfc848c6Sjm199354 vs_engid_to_pgname(engid, pgname); 470911106dfSjm199354 471*bfc848c6Sjm199354 return (vs_scf_pg_delete(pgname)); 472911106dfSjm199354 } 473911106dfSjm199354 474911106dfSjm199354 475911106dfSjm199354 /* 476911106dfSjm199354 * vs_strerror 477911106dfSjm199354 */ 478911106dfSjm199354 const char * 479911106dfSjm199354 vs_strerror(int error) 480911106dfSjm199354 { 481911106dfSjm199354 switch (error) { 482911106dfSjm199354 case VS_ERR_NONE: 483911106dfSjm199354 return (gettext("no error")); 484911106dfSjm199354 case VS_ERR_INVALID_PROPERTY: 485911106dfSjm199354 return (gettext("invalid property id")); 486911106dfSjm199354 case VS_ERR_INVALID_VALUE: 487911106dfSjm199354 return (gettext("invalid property value")); 488911106dfSjm199354 case VS_ERR_INVALID_HOST: 489911106dfSjm199354 return (gettext("invalid host")); 490911106dfSjm199354 case VS_ERR_INVALID_SE: 491911106dfSjm199354 return (gettext("invalid scan engine")); 492911106dfSjm199354 case VS_ERR_MAX_SE: 493911106dfSjm199354 return (gettext("max scan engines exceeded")); 494911106dfSjm199354 case VS_ERR_AUTH: 495911106dfSjm199354 return (gettext("insufficient privileges for action")); 496911106dfSjm199354 case VS_ERR_DAEMON_COMM: 497911106dfSjm199354 return (gettext("unable to contact vscand")); 498911106dfSjm199354 case VS_ERR_SCF: 499911106dfSjm199354 return (scf_strerror(scf_error())); 500911106dfSjm199354 case VS_ERR_SYS: 501911106dfSjm199354 return (strerror(errno)); 502911106dfSjm199354 default: 503911106dfSjm199354 return (gettext("unknown error")); 504911106dfSjm199354 } 505911106dfSjm199354 } 506911106dfSjm199354 507911106dfSjm199354 508911106dfSjm199354 /* 509911106dfSjm199354 * vs_get_propdef 510911106dfSjm199354 * 511911106dfSjm199354 * Finds and returns a property definition by property id. 512911106dfSjm199354 */ 513911106dfSjm199354 static const vs_propdef_t * 514911106dfSjm199354 vs_get_propdef(uint64_t propid) 515911106dfSjm199354 { 516911106dfSjm199354 int i; 517911106dfSjm199354 518911106dfSjm199354 for (i = 0; i < vs_npropdefs; i++) { 519911106dfSjm199354 if (propid == vs_propdefs[i].vpd_id) 520911106dfSjm199354 return (&vs_propdefs[i]); 521911106dfSjm199354 } 522911106dfSjm199354 523911106dfSjm199354 return (NULL); 524911106dfSjm199354 } 525911106dfSjm199354 526911106dfSjm199354 527911106dfSjm199354 /* 528911106dfSjm199354 * vs_default_value 529911106dfSjm199354 * 530911106dfSjm199354 * Sets a property value that contains invalid data to its default value. 531911106dfSjm199354 * 532911106dfSjm199354 * Note that this function does not alter any values in the repository 533911106dfSjm199354 * This is only to enable the caller to get valid data. 534911106dfSjm199354 */ 535911106dfSjm199354 static void 536911106dfSjm199354 vs_default_value(vs_prop_hd_t *prop_hd, const uint64_t propid) 537911106dfSjm199354 { 538911106dfSjm199354 vs_props_t *vp = &prop_hd->vp_gen; 539911106dfSjm199354 vs_props_se_t *vep = &prop_hd->vp_se; 540911106dfSjm199354 541911106dfSjm199354 switch (propid) { 542911106dfSjm199354 case VS_PROPID_MAXSIZE: 543911106dfSjm199354 (void) strlcpy(vp->vp_maxsize, vs_dflt_maxsize, 544911106dfSjm199354 sizeof (vp->vp_maxsize)); 545911106dfSjm199354 break; 546911106dfSjm199354 case VS_PROPID_MAXSIZE_ACTION: 547911106dfSjm199354 vp->vp_maxsize_action = vs_dflt_allow; 548911106dfSjm199354 break; 549911106dfSjm199354 case VS_PROPID_TYPES: 550911106dfSjm199354 (void) strlcpy(vp->vp_types, vs_dflt_types, 551911106dfSjm199354 sizeof (vp->vp_types)); 552911106dfSjm199354 break; 553911106dfSjm199354 case VS_PROPID_VLOG: 554911106dfSjm199354 (void) strlcpy(vp->vp_vlog, vs_dflt_vlog, 555911106dfSjm199354 sizeof (vp->vp_vlog)); 556911106dfSjm199354 break; 557911106dfSjm199354 case VS_PROPID_SE_ENABLE: 558911106dfSjm199354 vep->vep_enable = vs_dflt_enable; 559911106dfSjm199354 break; 560911106dfSjm199354 case VS_PROPID_SE_HOST: 561911106dfSjm199354 (void) strlcpy(vep->vep_host, vs_dflt_host, 562911106dfSjm199354 sizeof (vep->vep_host)); 563911106dfSjm199354 break; 564911106dfSjm199354 case VS_PROPID_SE_PORT: 565911106dfSjm199354 vep->vep_port = vs_dflt_port; 566911106dfSjm199354 break; 567911106dfSjm199354 case VS_PROPID_SE_MAXCONN: 568911106dfSjm199354 vep->vep_maxconn = vs_dflt_maxconn; 569911106dfSjm199354 break; 570911106dfSjm199354 default: 571911106dfSjm199354 break; 572911106dfSjm199354 } 573911106dfSjm199354 } 574911106dfSjm199354 575911106dfSjm199354 576911106dfSjm199354 /* 577911106dfSjm199354 * vs_scf_values_get 578911106dfSjm199354 * 579911106dfSjm199354 * Gets property values for one or more properties from the repository. 580911106dfSjm199354 * This is the single entry point for loading SMF values. 581911106dfSjm199354 * 582911106dfSjm199354 * While a transaction is not used for loading property values, 583911106dfSjm199354 * the operation is parameterized by a property group. All properties 584911106dfSjm199354 * retrieved in this function, then, must belong to the same property 585911106dfSjm199354 * group. 586911106dfSjm199354 */ 587911106dfSjm199354 int 588911106dfSjm199354 vs_scf_values_get(const char *pgname, vs_prop_hd_t *prop_hd) 589911106dfSjm199354 { 590911106dfSjm199354 vs_scfctx_t vsc; 591911106dfSjm199354 int rc, np; 592911106dfSjm199354 const vs_propdef_t *vpd; 593911106dfSjm199354 uint64_t propid; 594911106dfSjm199354 595911106dfSjm199354 if ((vs_scf_ctx_open(&vsc)) != 0) { 596911106dfSjm199354 vs_scf_ctx_close(&vsc); 597911106dfSjm199354 return (VS_ERR_SCF); 598911106dfSjm199354 } 599911106dfSjm199354 600911106dfSjm199354 if (scf_instance_get_pg(vsc.vscf_inst, pgname, vsc.vscf_pgroup) == -1) { 601911106dfSjm199354 vs_scf_ctx_close(&vsc); 602911106dfSjm199354 if (strcmp(pgname, "VS_PGNAME_GENERAL") != 0) { 603911106dfSjm199354 rc = scf_error(); 604911106dfSjm199354 if ((rc == SCF_ERROR_NOT_FOUND) || 605911106dfSjm199354 (rc == SCF_ERROR_INVALID_ARGUMENT)) 606911106dfSjm199354 return (VS_ERR_INVALID_SE); 607911106dfSjm199354 } 608911106dfSjm199354 return (VS_ERR_SCF); 609911106dfSjm199354 } 610911106dfSjm199354 611911106dfSjm199354 rc = VS_ERR_NONE; 612911106dfSjm199354 np = 0; 613911106dfSjm199354 for (propid = 1LL; propid <= VS_PROPID_MAX; propid <<= 1) { 614911106dfSjm199354 if ((prop_hd->vp_ids & propid) == 0) 615911106dfSjm199354 continue; 616911106dfSjm199354 617911106dfSjm199354 if ((vpd = vs_get_propdef(propid)) == NULL) { 618911106dfSjm199354 rc = VS_ERR_INVALID_PROPERTY; 619911106dfSjm199354 break; 620911106dfSjm199354 } 621911106dfSjm199354 622911106dfSjm199354 vsc.vscf_prop[np] = scf_property_create(vsc.vscf_handle); 623911106dfSjm199354 vsc.vscf_val[np] = scf_value_create(vsc.vscf_handle); 624911106dfSjm199354 625911106dfSjm199354 if (vsc.vscf_prop[np] == NULL || vsc.vscf_val[np] == NULL) { 626911106dfSjm199354 rc = VS_ERR_SCF; 627911106dfSjm199354 break; 628911106dfSjm199354 } 629911106dfSjm199354 630911106dfSjm199354 if (scf_pg_get_property(vsc.vscf_pgroup, vpd->vpd_name, 631911106dfSjm199354 vsc.vscf_prop[np]) == -1) { 632911106dfSjm199354 if (scf_error() == SCF_ERROR_NOT_FOUND) { 633911106dfSjm199354 vs_default_value(prop_hd, vpd->vpd_id); 634911106dfSjm199354 continue; 635911106dfSjm199354 } 636911106dfSjm199354 rc = VS_ERR_SCF; 637911106dfSjm199354 break; 638911106dfSjm199354 } 639911106dfSjm199354 640911106dfSjm199354 if ((rc = vs_scf_get(vpd, prop_hd, &vsc, np)) != VS_ERR_NONE) 641911106dfSjm199354 break; 642911106dfSjm199354 643911106dfSjm199354 ++np; 644911106dfSjm199354 } 645911106dfSjm199354 646911106dfSjm199354 647911106dfSjm199354 vs_scf_ctx_close(&vsc); 648911106dfSjm199354 649911106dfSjm199354 return (rc); 650911106dfSjm199354 } 651911106dfSjm199354 652911106dfSjm199354 653911106dfSjm199354 /* 654911106dfSjm199354 * vs_scf_get 655911106dfSjm199354 * 656911106dfSjm199354 * Loads a single values from the repository into the appropriate vscan 657911106dfSjm199354 * property structure member. 658911106dfSjm199354 */ 659911106dfSjm199354 static int 660911106dfSjm199354 vs_scf_get(const vs_propdef_t *vpd, vs_prop_hd_t *prop_hd, 661911106dfSjm199354 vs_scfctx_t *vsc, int idx) 662911106dfSjm199354 { 663911106dfSjm199354 int rc; 664911106dfSjm199354 int64_t port; 665911106dfSjm199354 uint8_t valbool; 666911106dfSjm199354 vs_props_t *vp = &prop_hd->vp_gen; 667911106dfSjm199354 vs_props_se_t *vep = &prop_hd->vp_se; 668911106dfSjm199354 669911106dfSjm199354 if ((rc = scf_property_get_value(vsc->vscf_prop[idx], 670911106dfSjm199354 vsc->vscf_val[idx])) == -1) { 671911106dfSjm199354 if (rc == SCF_ERROR_CONSTRAINT_VIOLATED || 672911106dfSjm199354 rc == SCF_ERROR_NOT_FOUND) { 673911106dfSjm199354 vs_default_value(prop_hd, vpd->vpd_id); 674911106dfSjm199354 return (VS_ERR_NONE); 675911106dfSjm199354 } 676911106dfSjm199354 return (VS_ERR_SCF); 677911106dfSjm199354 } 678911106dfSjm199354 679911106dfSjm199354 rc = VS_ERR_NONE; 680911106dfSjm199354 switch (vpd->vpd_id) { 681911106dfSjm199354 case VS_PROPID_MAXSIZE: 682911106dfSjm199354 if ((scf_value_get_astring(vsc->vscf_val[idx], 683911106dfSjm199354 vp->vp_maxsize, sizeof (vp->vp_maxsize))) == -1) { 684911106dfSjm199354 return (VS_ERR_SCF); 685911106dfSjm199354 } 686911106dfSjm199354 break; 687911106dfSjm199354 case VS_PROPID_MAXSIZE_ACTION: 688911106dfSjm199354 if ((scf_value_get_boolean(vsc->vscf_val[idx], 689911106dfSjm199354 &valbool)) == -1) { 690911106dfSjm199354 return (VS_ERR_SCF); 691911106dfSjm199354 } 692911106dfSjm199354 vp->vp_maxsize_action = (valbool == 0) ? B_FALSE : B_TRUE; 693911106dfSjm199354 break; 694911106dfSjm199354 case VS_PROPID_TYPES: 695911106dfSjm199354 if ((scf_value_get_astring(vsc->vscf_val[idx], 696911106dfSjm199354 vp->vp_types, sizeof (vp->vp_types))) == -1) { 697911106dfSjm199354 return (VS_ERR_SCF); 698911106dfSjm199354 } 699911106dfSjm199354 break; 700911106dfSjm199354 case VS_PROPID_VLOG: 701911106dfSjm199354 if ((scf_value_get_astring(vsc->vscf_val[idx], 702911106dfSjm199354 vp->vp_vlog, sizeof (vp->vp_vlog))) == -1) { 703911106dfSjm199354 return (VS_ERR_SCF); 704911106dfSjm199354 } 705911106dfSjm199354 break; 706911106dfSjm199354 case VS_PROPID_SE_ENABLE: 707911106dfSjm199354 if ((scf_value_get_boolean(vsc->vscf_val[idx], 708911106dfSjm199354 &valbool)) == -1) { 709911106dfSjm199354 return (VS_ERR_SCF); 710911106dfSjm199354 } 711911106dfSjm199354 vep->vep_enable = (valbool == 0) ? B_FALSE : B_TRUE; 712911106dfSjm199354 break; 713911106dfSjm199354 case VS_PROPID_SE_HOST: 714911106dfSjm199354 (void) scf_value_get_as_string_typed(vsc->vscf_val[idx], 715911106dfSjm199354 vpd->vpd_type, vep->vep_host, sizeof (vep->vep_host)); 716911106dfSjm199354 break; 717911106dfSjm199354 case VS_PROPID_SE_PORT: 718911106dfSjm199354 if ((scf_value_get_integer(vsc->vscf_val[idx], &port)) == -1) 719911106dfSjm199354 return (VS_ERR_SCF); 720911106dfSjm199354 if (port <= 0 || port >= UINT16_MAX) 721911106dfSjm199354 rc = VS_ERR_INVALID_VALUE; 722911106dfSjm199354 else 723911106dfSjm199354 vep->vep_port = (uint16_t)port; 724911106dfSjm199354 break; 725911106dfSjm199354 case VS_PROPID_SE_MAXCONN: 726911106dfSjm199354 if ((scf_value_get_integer(vsc->vscf_val[idx], 727911106dfSjm199354 (int64_t *)&vep->vep_maxconn)) == -1) { 728911106dfSjm199354 return (VS_ERR_SCF); 729911106dfSjm199354 } 730911106dfSjm199354 break; 731911106dfSjm199354 default: 732911106dfSjm199354 break; 733911106dfSjm199354 } 734911106dfSjm199354 735911106dfSjm199354 if ((rc != VS_ERR_NONE) || 736911106dfSjm199354 (vs_validate(prop_hd, vpd->vpd_id) != VS_ERR_NONE)) { 737911106dfSjm199354 vs_default_value(prop_hd, vpd->vpd_id); 738911106dfSjm199354 } 739911106dfSjm199354 740911106dfSjm199354 return (VS_ERR_NONE); 741911106dfSjm199354 } 742911106dfSjm199354 743911106dfSjm199354 744911106dfSjm199354 /* 745911106dfSjm199354 * vs_scf_pg_create 746911106dfSjm199354 */ 747911106dfSjm199354 static int 748911106dfSjm199354 vs_scf_pg_create(const char *pgname, vs_prop_hd_t *prop_hd) 749911106dfSjm199354 { 750911106dfSjm199354 int rc; 751911106dfSjm199354 uint64_t propid; 752911106dfSjm199354 vs_scfctx_t vsc; 753911106dfSjm199354 754911106dfSjm199354 /* ensure that caller has authorization to refresh service */ 755911106dfSjm199354 if ((rc = vs_checkauth(VS_ACTION_AUTH)) != VS_ERR_NONE) 756911106dfSjm199354 return (rc); 757911106dfSjm199354 758911106dfSjm199354 if (vs_scf_ctx_open(&vsc) != 0) { 759911106dfSjm199354 vs_scf_ctx_close(&vsc); 760911106dfSjm199354 return (VS_ERR_SCF); 761911106dfSjm199354 } 762911106dfSjm199354 763911106dfSjm199354 if (scf_instance_add_pg(vsc.vscf_inst, pgname, 764911106dfSjm199354 SCF_GROUP_APPLICATION, 0, vsc.vscf_pgroup) == -1) { 765911106dfSjm199354 vs_scf_ctx_close(&vsc); 766911106dfSjm199354 if (scf_error() == SCF_ERROR_INVALID_ARGUMENT) 767911106dfSjm199354 return (VS_ERR_INVALID_SE); 768911106dfSjm199354 return (VS_ERR_SCF); 769911106dfSjm199354 } 770911106dfSjm199354 vs_scf_ctx_close(&vsc); 771911106dfSjm199354 772911106dfSjm199354 /* set default values for those not specified */ 773911106dfSjm199354 for (propid = 1LL; propid <= VS_PROPID_MAX; propid <<= 1) { 774911106dfSjm199354 if ((propid & prop_hd->vp_all) && !(propid & prop_hd->vp_ids)) 775911106dfSjm199354 vs_default_value(prop_hd, propid); 776911106dfSjm199354 } 777*bfc848c6Sjm199354 778911106dfSjm199354 prop_hd->vp_ids = prop_hd->vp_all; 779911106dfSjm199354 prop_hd->vp_ids |= VS_PROPID_VALUE_AUTH; 780911106dfSjm199354 781911106dfSjm199354 rc = vs_scf_values_set(pgname, prop_hd); 782911106dfSjm199354 if (rc != VS_ERR_NONE) 783*bfc848c6Sjm199354 (void) vs_scf_pg_delete(pgname); 784911106dfSjm199354 785911106dfSjm199354 return (rc); 786911106dfSjm199354 } 787911106dfSjm199354 788911106dfSjm199354 789911106dfSjm199354 /* 790*bfc848c6Sjm199354 * vs_scf_pg_delete 791*bfc848c6Sjm199354 */ 792*bfc848c6Sjm199354 static int 793*bfc848c6Sjm199354 vs_scf_pg_delete(const char *pgname) 794*bfc848c6Sjm199354 { 795*bfc848c6Sjm199354 int rc; 796*bfc848c6Sjm199354 vs_scfctx_t vsc; 797*bfc848c6Sjm199354 798*bfc848c6Sjm199354 /* ensure that caller has authorization to refresh service */ 799*bfc848c6Sjm199354 if ((rc = vs_checkauth(VS_ACTION_AUTH)) != VS_ERR_NONE) 800*bfc848c6Sjm199354 return (rc); 801*bfc848c6Sjm199354 802*bfc848c6Sjm199354 if (vs_scf_ctx_open(&vsc) != 0) { 803*bfc848c6Sjm199354 vs_scf_ctx_close(&vsc); 804*bfc848c6Sjm199354 return (VS_ERR_SCF); 805*bfc848c6Sjm199354 } 806*bfc848c6Sjm199354 807*bfc848c6Sjm199354 if (scf_instance_get_pg(vsc.vscf_inst, pgname, vsc.vscf_pgroup) == -1) { 808*bfc848c6Sjm199354 vs_scf_ctx_close(&vsc); 809*bfc848c6Sjm199354 rc = scf_error(); 810*bfc848c6Sjm199354 if ((rc == SCF_ERROR_NOT_FOUND) || 811*bfc848c6Sjm199354 (rc == SCF_ERROR_INVALID_ARGUMENT)) 812*bfc848c6Sjm199354 return (VS_ERR_INVALID_SE); 813*bfc848c6Sjm199354 else 814*bfc848c6Sjm199354 return (VS_ERR_SCF); 815*bfc848c6Sjm199354 } 816*bfc848c6Sjm199354 817*bfc848c6Sjm199354 if (scf_pg_delete(vsc.vscf_pgroup) == -1) { 818*bfc848c6Sjm199354 vs_scf_ctx_close(&vsc); 819*bfc848c6Sjm199354 rc = scf_error(); 820*bfc848c6Sjm199354 if ((rc == SCF_ERROR_NOT_FOUND) || 821*bfc848c6Sjm199354 (rc == SCF_ERROR_INVALID_ARGUMENT)) 822*bfc848c6Sjm199354 return (VS_ERR_INVALID_SE); 823*bfc848c6Sjm199354 824*bfc848c6Sjm199354 return (VS_ERR_SCF); 825*bfc848c6Sjm199354 } 826*bfc848c6Sjm199354 827*bfc848c6Sjm199354 vs_scf_ctx_close(&vsc); 828*bfc848c6Sjm199354 829*bfc848c6Sjm199354 /* Notify the daemon that things have changed */ 830*bfc848c6Sjm199354 if ((smf_refresh_instance(VS_INSTANCE_FMRI)) == -1) { 831*bfc848c6Sjm199354 return (VS_ERR_SCF); 832*bfc848c6Sjm199354 } 833*bfc848c6Sjm199354 834*bfc848c6Sjm199354 return (VS_ERR_NONE); 835*bfc848c6Sjm199354 } 836*bfc848c6Sjm199354 837*bfc848c6Sjm199354 838*bfc848c6Sjm199354 /* 839911106dfSjm199354 * vs_scf_values_set 840911106dfSjm199354 * 841911106dfSjm199354 * Sets property values in the repository. This is the single 842911106dfSjm199354 * entry point for storing SMF values. 843911106dfSjm199354 * 844911106dfSjm199354 * Like loading values, this is an operation based on a single property 845911106dfSjm199354 * group, so all property values changed in this function must belong 846911106dfSjm199354 * to the same property group. Additionally, this operation is done in 847911106dfSjm199354 * the context of a repository transaction; on any fatal error, the 848911106dfSjm199354 * SCF context will be closed, destroying all SCF objects and aborting 849911106dfSjm199354 * the transaction. 850911106dfSjm199354 */ 851911106dfSjm199354 static int 852911106dfSjm199354 vs_scf_values_set(const char *pgname, vs_prop_hd_t *prop_hd) 853911106dfSjm199354 { 854911106dfSjm199354 int rc, np; 855911106dfSjm199354 const vs_propdef_t *vpd; 856911106dfSjm199354 uint64_t propid; 857911106dfSjm199354 vs_scfctx_t vsc; 858911106dfSjm199354 859911106dfSjm199354 /* ensure that caller has authorization to refresh service */ 860911106dfSjm199354 if ((rc = vs_checkauth(VS_ACTION_AUTH)) != VS_ERR_NONE) 861911106dfSjm199354 return (rc); 862911106dfSjm199354 863911106dfSjm199354 if (vs_scf_ctx_open(&vsc) != 0) { 864911106dfSjm199354 vs_scf_ctx_close(&vsc); 865911106dfSjm199354 return (VS_ERR_SCF); 866911106dfSjm199354 } 867911106dfSjm199354 868911106dfSjm199354 if (scf_instance_get_pg(vsc.vscf_inst, pgname, vsc.vscf_pgroup) == -1) { 869911106dfSjm199354 vs_scf_ctx_close(&vsc); 870911106dfSjm199354 rc = scf_error(); 871911106dfSjm199354 if (strcmp(pgname, "VS_PGNAME_GENERAL") != 0) { 872911106dfSjm199354 if ((rc == SCF_ERROR_NOT_FOUND) || 873911106dfSjm199354 (rc == SCF_ERROR_INVALID_ARGUMENT)) 874911106dfSjm199354 return (VS_ERR_INVALID_SE); 875911106dfSjm199354 } 876911106dfSjm199354 return (VS_ERR_SCF); 877911106dfSjm199354 } 878911106dfSjm199354 879911106dfSjm199354 if (((vsc.vscf_tx = scf_transaction_create(vsc.vscf_handle)) == NULL) || 880911106dfSjm199354 (scf_transaction_start(vsc.vscf_tx, vsc.vscf_pgroup) == -1)) { 881911106dfSjm199354 vs_scf_ctx_close(&vsc); 882911106dfSjm199354 return (VS_ERR_SCF); 883911106dfSjm199354 } 884911106dfSjm199354 885911106dfSjm199354 /* Process the value change for each specified property */ 886911106dfSjm199354 rc = 0; 887911106dfSjm199354 np = 0; 888911106dfSjm199354 for (propid = 1LL; propid <= VS_PROPID_MAX; propid <<= 1) { 889911106dfSjm199354 if ((prop_hd->vp_ids & propid) == 0) 890911106dfSjm199354 continue; 891911106dfSjm199354 892911106dfSjm199354 if ((vpd = vs_get_propdef(propid)) == NULL) { 893911106dfSjm199354 rc = VS_ERR_INVALID_PROPERTY; 894911106dfSjm199354 break; 895911106dfSjm199354 } 896911106dfSjm199354 897911106dfSjm199354 vsc.vscf_val[np] = scf_value_create(vsc.vscf_handle); 898911106dfSjm199354 vsc.vscf_ent[np] = scf_entry_create(vsc.vscf_handle); 899911106dfSjm199354 900911106dfSjm199354 if (vsc.vscf_val[np] == NULL || vsc.vscf_ent[np] == NULL) { 901911106dfSjm199354 rc = VS_ERR_SCF; 902911106dfSjm199354 break; 903911106dfSjm199354 } 904911106dfSjm199354 905911106dfSjm199354 if ((rc = scf_transaction_property_change(vsc.vscf_tx, 906911106dfSjm199354 vsc.vscf_ent[np], vpd->vpd_name, vpd->vpd_type)) == -1) { 907911106dfSjm199354 rc = scf_transaction_property_new(vsc.vscf_tx, 908911106dfSjm199354 vsc.vscf_ent[np], vpd->vpd_name, vpd->vpd_type); 909911106dfSjm199354 } 910911106dfSjm199354 if (rc == -1) { 911911106dfSjm199354 rc = VS_ERR_SCF; 912911106dfSjm199354 break; 913911106dfSjm199354 } 914911106dfSjm199354 915911106dfSjm199354 if ((rc = vs_scf_set(vpd, prop_hd, &vsc, np)) != VS_ERR_NONE) 916911106dfSjm199354 break; 917911106dfSjm199354 918911106dfSjm199354 ++np; 919911106dfSjm199354 } 920911106dfSjm199354 921911106dfSjm199354 if (rc != VS_ERR_NONE) { 922911106dfSjm199354 vs_scf_ctx_close(&vsc); 923911106dfSjm199354 return (rc); 924911106dfSjm199354 } 925911106dfSjm199354 926911106dfSjm199354 /* Commit the transaction */ 927911106dfSjm199354 if (scf_transaction_commit(vsc.vscf_tx) == -1) { 928911106dfSjm199354 vs_scf_ctx_close(&vsc); 929911106dfSjm199354 return (VS_ERR_SCF); 930911106dfSjm199354 } 931911106dfSjm199354 vs_scf_ctx_close(&vsc); 932911106dfSjm199354 933911106dfSjm199354 /* Notify the daemon that things have changed */ 934911106dfSjm199354 if ((smf_refresh_instance(VS_INSTANCE_FMRI)) == -1) 935911106dfSjm199354 return (VS_ERR_SCF); 936911106dfSjm199354 937911106dfSjm199354 return (VS_ERR_NONE); 938911106dfSjm199354 } 939911106dfSjm199354 940911106dfSjm199354 941911106dfSjm199354 /* 942911106dfSjm199354 * vs_scf_set 943911106dfSjm199354 * 944911106dfSjm199354 * Stores a single value from the appropriate vscan property structure 945911106dfSjm199354 * member into the repository. 946911106dfSjm199354 * 947911106dfSjm199354 * Values are set in the SCF value object, then the value object 948911106dfSjm199354 * is added to the SCF property object. 949911106dfSjm199354 */ 950911106dfSjm199354 static int 951911106dfSjm199354 vs_scf_set(const vs_propdef_t *vpd, vs_prop_hd_t *prop_hd, 952911106dfSjm199354 vs_scfctx_t *vsc, int idx) 953911106dfSjm199354 { 954911106dfSjm199354 int rc; 955911106dfSjm199354 vs_props_t *vp = &prop_hd->vp_gen; 956911106dfSjm199354 vs_props_se_t *vep = &prop_hd->vp_se; 957911106dfSjm199354 958911106dfSjm199354 if ((rc = vs_validate(prop_hd, vpd->vpd_id)) != VS_ERR_NONE) 959911106dfSjm199354 return (rc); 960911106dfSjm199354 961911106dfSjm199354 rc = VS_ERR_NONE; 962911106dfSjm199354 switch (vpd->vpd_id) { 963911106dfSjm199354 case VS_PROPID_MAXSIZE: 964911106dfSjm199354 if ((scf_value_set_astring(vsc->vscf_val[idx], 965911106dfSjm199354 vp->vp_maxsize)) == -1) { 966911106dfSjm199354 rc = VS_ERR_SCF; 967911106dfSjm199354 } 968911106dfSjm199354 break; 969911106dfSjm199354 case VS_PROPID_MAXSIZE_ACTION: 970911106dfSjm199354 scf_value_set_boolean(vsc->vscf_val[idx], 971911106dfSjm199354 (uint8_t)vp->vp_maxsize_action); 972911106dfSjm199354 break; 973911106dfSjm199354 case VS_PROPID_TYPES: 974911106dfSjm199354 if ((scf_value_set_astring(vsc->vscf_val[idx], 975911106dfSjm199354 vp->vp_types)) == -1) { 976911106dfSjm199354 return (VS_ERR_SCF); 977911106dfSjm199354 } 978911106dfSjm199354 break; 979911106dfSjm199354 case VS_PROPID_SE_ENABLE: 980911106dfSjm199354 scf_value_set_boolean(vsc->vscf_val[idx], 981911106dfSjm199354 (uint8_t)vep->vep_enable); 982911106dfSjm199354 break; 983911106dfSjm199354 case VS_PROPID_SE_HOST: 984911106dfSjm199354 if ((scf_value_set_from_string(vsc->vscf_val[idx], 985911106dfSjm199354 vpd->vpd_type, vep->vep_host)) == -1) { 986911106dfSjm199354 rc = VS_ERR_SCF; 987911106dfSjm199354 } 988911106dfSjm199354 break; 989911106dfSjm199354 case VS_PROPID_SE_PORT: 990911106dfSjm199354 scf_value_set_integer(vsc->vscf_val[idx], vep->vep_port); 991911106dfSjm199354 break; 992911106dfSjm199354 case VS_PROPID_SE_MAXCONN: 993911106dfSjm199354 scf_value_set_integer(vsc->vscf_val[idx], 994911106dfSjm199354 vep->vep_maxconn); 995911106dfSjm199354 break; 996911106dfSjm199354 case VS_PROPID_VALUE_AUTH: 997911106dfSjm199354 if ((scf_value_set_astring(vsc->vscf_val[idx], 998911106dfSjm199354 VS_VALUE_AUTH)) == -1) { 999911106dfSjm199354 return (VS_ERR_SCF); 1000911106dfSjm199354 } 1001911106dfSjm199354 break; 1002911106dfSjm199354 default: 1003911106dfSjm199354 break; 1004911106dfSjm199354 } 1005911106dfSjm199354 1006911106dfSjm199354 if ((scf_entry_add_value(vsc->vscf_ent[idx], 1007911106dfSjm199354 vsc->vscf_val[idx])) == -1) { 1008911106dfSjm199354 return (VS_ERR_SCF); 1009911106dfSjm199354 } 1010911106dfSjm199354 1011911106dfSjm199354 return (rc); 1012911106dfSjm199354 } 1013911106dfSjm199354 1014911106dfSjm199354 1015911106dfSjm199354 /* 1016911106dfSjm199354 * vs_scf_ctx_open 1017911106dfSjm199354 * 1018911106dfSjm199354 * Opens an SCF context; creates the minumum SCF objects 1019911106dfSjm199354 * for use in loading/storing from the SMF repository (meaning 1020911106dfSjm199354 * vscf_property group data). 1021911106dfSjm199354 * 1022911106dfSjm199354 * Other SCF objects in the context may be initialized elsewher 1023911106dfSjm199354 * subsequent to open, but all initialized structures are destroyed 1024911106dfSjm199354 * in vs_scf_ctx_close(). 1025911106dfSjm199354 */ 1026911106dfSjm199354 static int 1027911106dfSjm199354 vs_scf_ctx_open(vs_scfctx_t *vsc) 1028911106dfSjm199354 { 1029911106dfSjm199354 (void) memset(vsc, 0, sizeof (vs_scfctx_t)); 1030911106dfSjm199354 1031911106dfSjm199354 if ((vsc->vscf_handle = scf_handle_create(SCF_VERSION)) == NULL) 1032911106dfSjm199354 return (VS_ERR_SCF); 1033911106dfSjm199354 1034911106dfSjm199354 if (scf_handle_bind(vsc->vscf_handle) == -1) 1035911106dfSjm199354 return (VS_ERR_SCF); 1036911106dfSjm199354 1037911106dfSjm199354 if ((vsc->vscf_inst = scf_instance_create(vsc->vscf_handle)) == NULL) 1038911106dfSjm199354 return (VS_ERR_SCF); 1039911106dfSjm199354 1040911106dfSjm199354 if (scf_handle_decode_fmri(vsc->vscf_handle, VS_INSTANCE_FMRI, 1041911106dfSjm199354 NULL, NULL, vsc->vscf_inst, NULL, NULL, 1042911106dfSjm199354 SCF_DECODE_FMRI_EXACT) == -1) { 1043911106dfSjm199354 return (VS_ERR_SCF); 1044911106dfSjm199354 } 1045911106dfSjm199354 1046911106dfSjm199354 if ((vsc->vscf_pgroup = scf_pg_create(vsc->vscf_handle)) == NULL) 1047911106dfSjm199354 return (VS_ERR_SCF); 1048911106dfSjm199354 1049911106dfSjm199354 return (VS_ERR_NONE); 1050911106dfSjm199354 } 1051911106dfSjm199354 1052911106dfSjm199354 1053911106dfSjm199354 /* 1054911106dfSjm199354 * vs_scf_ctx_close 1055911106dfSjm199354 * 1056911106dfSjm199354 * Closes an SCF context; destroys all initialized SCF objects. 1057911106dfSjm199354 */ 1058911106dfSjm199354 static void 1059911106dfSjm199354 vs_scf_ctx_close(vs_scfctx_t *vsc) 1060911106dfSjm199354 { 1061911106dfSjm199354 int i; 1062911106dfSjm199354 1063911106dfSjm199354 for (i = 0; i < VS_NUM_PROPIDS; i++) { 1064911106dfSjm199354 if (vsc->vscf_val[i]) 1065911106dfSjm199354 scf_value_destroy(vsc->vscf_val[i]); 1066911106dfSjm199354 if (vsc->vscf_ent[i]) 1067911106dfSjm199354 scf_entry_destroy(vsc->vscf_ent[i]); 1068911106dfSjm199354 if (vsc->vscf_prop[i]) 1069911106dfSjm199354 scf_property_destroy(vsc->vscf_prop[i]); 1070911106dfSjm199354 } 1071911106dfSjm199354 1072911106dfSjm199354 if (vsc->vscf_iter) 1073911106dfSjm199354 scf_iter_destroy(vsc->vscf_iter); 1074911106dfSjm199354 if (vsc->vscf_tx) 1075911106dfSjm199354 scf_transaction_destroy(vsc->vscf_tx); 1076911106dfSjm199354 if (vsc->vscf_pgroup) 1077911106dfSjm199354 scf_pg_destroy(vsc->vscf_pgroup); 1078911106dfSjm199354 if (vsc->vscf_inst) 1079911106dfSjm199354 scf_instance_destroy(vsc->vscf_inst); 1080911106dfSjm199354 if (vsc->vscf_handle) 1081911106dfSjm199354 scf_handle_destroy(vsc->vscf_handle); 1082911106dfSjm199354 } 1083911106dfSjm199354 1084911106dfSjm199354 1085911106dfSjm199354 /* 1086911106dfSjm199354 * vs_validate 1087911106dfSjm199354 * 1088911106dfSjm199354 * Validate property identified in propid. 1089911106dfSjm199354 * 1090911106dfSjm199354 * Returns: VS_ERR_NONE 1091911106dfSjm199354 * VS_ERR_INVALID_VALUE 1092911106dfSjm199354 * VS_ERR_INVALID_PROPERTY 1093911106dfSjm199354 */ 1094911106dfSjm199354 static int 1095911106dfSjm199354 vs_validate(const vs_prop_hd_t *prop_hd, uint64_t propid) 1096911106dfSjm199354 { 1097911106dfSjm199354 uint64_t num; 1098911106dfSjm199354 const vs_props_t *vp = &prop_hd->vp_gen; 1099911106dfSjm199354 const vs_props_se_t *vep = &prop_hd->vp_se; 1100911106dfSjm199354 1101911106dfSjm199354 switch (propid) { 1102911106dfSjm199354 case VS_PROPID_MAXSIZE: 1103911106dfSjm199354 if ((vs_strtonum(vp->vp_maxsize, &num) != 0) || (num == 0)) 1104911106dfSjm199354 return (VS_ERR_INVALID_VALUE); 1105911106dfSjm199354 break; 1106911106dfSjm199354 case VS_PROPID_MAXSIZE_ACTION: 1107911106dfSjm199354 break; 1108911106dfSjm199354 case VS_PROPID_TYPES: 1109911106dfSjm199354 if (!vs_is_valid_types(vp->vp_types)) 1110911106dfSjm199354 return (VS_ERR_INVALID_VALUE); 1111911106dfSjm199354 break; 1112911106dfSjm199354 case VS_PROPID_SE_ENABLE: 1113911106dfSjm199354 break; 1114911106dfSjm199354 case VS_PROPID_SE_PORT: 1115911106dfSjm199354 if (vep->vep_port == 0) 1116911106dfSjm199354 return (VS_ERR_INVALID_VALUE); 1117911106dfSjm199354 break; 1118911106dfSjm199354 case VS_PROPID_SE_HOST: 1119911106dfSjm199354 if (!vs_is_valid_host(vep->vep_host)) 1120911106dfSjm199354 return (VS_ERR_INVALID_VALUE); 1121911106dfSjm199354 break; 1122911106dfSjm199354 case VS_PROPID_SE_MAXCONN: 1123911106dfSjm199354 if (vep->vep_maxconn < VS_VAL_SE_MAXCONN_MIN || 1124911106dfSjm199354 vep->vep_maxconn > VS_VAL_SE_MAXCONN_MAX) 1125911106dfSjm199354 return (VS_ERR_INVALID_VALUE); 1126911106dfSjm199354 break; 1127911106dfSjm199354 case VS_PROPID_VALUE_AUTH: 1128911106dfSjm199354 case VS_PROPID_VLOG: 1129911106dfSjm199354 break; 1130911106dfSjm199354 default: 1131911106dfSjm199354 return (VS_ERR_INVALID_PROPERTY); 1132911106dfSjm199354 } 1133911106dfSjm199354 1134911106dfSjm199354 return (VS_ERR_NONE); 1135911106dfSjm199354 } 1136911106dfSjm199354 1137911106dfSjm199354 1138911106dfSjm199354 /* 1139911106dfSjm199354 * vs_props_validate 1140911106dfSjm199354 * 1141911106dfSjm199354 * Validate properties identified in propids. 1142911106dfSjm199354 * 1143911106dfSjm199354 * Returns: VS_ERR_NONE 1144911106dfSjm199354 * VS_ERR_INVALID_VALUE 1145911106dfSjm199354 * VS_ERR_INVALID_PROPERTY 1146911106dfSjm199354 */ 1147911106dfSjm199354 int 1148911106dfSjm199354 vs_props_validate(const vs_props_t *props, uint64_t propids) 1149911106dfSjm199354 { 1150911106dfSjm199354 uint64_t propid; 1151911106dfSjm199354 vs_prop_hd_t prop_hd; 1152911106dfSjm199354 1153911106dfSjm199354 if ((propids & VS_PROPID_GEN_ALL) != propids) 1154911106dfSjm199354 return (VS_ERR_INVALID_PROPERTY); 1155911106dfSjm199354 1156911106dfSjm199354 (void) memset(&prop_hd, 0, sizeof (vs_prop_hd_t)); 1157911106dfSjm199354 prop_hd.vp_gen = *props; 1158911106dfSjm199354 prop_hd.vp_type = VS_PTYPE_GEN; 1159911106dfSjm199354 prop_hd.vp_ids = propids; 1160911106dfSjm199354 prop_hd.vp_all = VS_PROPID_GEN_ALL; 1161911106dfSjm199354 1162911106dfSjm199354 for (propid = 1LL; propid <= VS_PROPID_MAX; propid <<= 1) { 1163911106dfSjm199354 if ((propids & propid) == 0) 1164911106dfSjm199354 continue; 1165911106dfSjm199354 1166911106dfSjm199354 if (vs_validate(&prop_hd, propid) != VS_ERR_NONE) 1167911106dfSjm199354 return (VS_ERR_INVALID_VALUE); 1168911106dfSjm199354 } 1169911106dfSjm199354 1170911106dfSjm199354 return (VS_ERR_NONE); 1171911106dfSjm199354 } 1172911106dfSjm199354 1173911106dfSjm199354 1174911106dfSjm199354 /* 1175911106dfSjm199354 * vs_props_se_validate 1176911106dfSjm199354 * 1177911106dfSjm199354 * Validate properties identified in propids. 1178911106dfSjm199354 * 1179911106dfSjm199354 * Returns: VS_ERR_NONE 1180911106dfSjm199354 * VS_ERR_INVALID_VALUE 1181911106dfSjm199354 * VS_ERR_INVALID_PROPERTY 1182911106dfSjm199354 */ 1183911106dfSjm199354 int 1184911106dfSjm199354 vs_props_se_validate(const vs_props_se_t *se_props, uint64_t propids) 1185911106dfSjm199354 { 1186911106dfSjm199354 uint64_t propid; 1187911106dfSjm199354 vs_prop_hd_t prop_hd; 1188911106dfSjm199354 1189911106dfSjm199354 if ((propids & VS_PROPID_SE_ALL) != propids) 1190911106dfSjm199354 return (VS_ERR_INVALID_PROPERTY); 1191911106dfSjm199354 1192911106dfSjm199354 (void) memset(&prop_hd, 0, sizeof (vs_prop_hd_t)); 1193911106dfSjm199354 prop_hd.vp_se = *se_props; 1194911106dfSjm199354 prop_hd.vp_type = VS_PTYPE_SE; 1195911106dfSjm199354 prop_hd.vp_ids = propids; 1196911106dfSjm199354 prop_hd.vp_all = VS_PROPID_SE_ALL; 1197911106dfSjm199354 1198911106dfSjm199354 for (propid = 1LL; propid <= VS_PROPID_MAX; propid <<= 1) { 1199911106dfSjm199354 if ((propids & propid) == 0) 1200911106dfSjm199354 continue; 1201911106dfSjm199354 1202911106dfSjm199354 if (vs_validate(&prop_hd, propid) != VS_ERR_NONE) 1203911106dfSjm199354 return (VS_ERR_INVALID_VALUE); 1204911106dfSjm199354 } 1205911106dfSjm199354 1206911106dfSjm199354 return (VS_ERR_NONE); 1207911106dfSjm199354 } 1208911106dfSjm199354 1209911106dfSjm199354 1210911106dfSjm199354 /* 1211911106dfSjm199354 * vs_is_valid_types 1212911106dfSjm199354 * 1213911106dfSjm199354 * Checks that types property is a valid format: 1214911106dfSjm199354 * - doesn't exceed VS_VAL_TYPES_MAX 1215911106dfSjm199354 * - doesn't contain VS_VAL_TYPES_INVALID_CHARS 1216911106dfSjm199354 * - is correctly formatted - passes the parsing tests 1217911106dfSjm199354 * 1218911106dfSjm199354 * Returns 1 on success, 0 on failure 1219911106dfSjm199354 */ 1220911106dfSjm199354 static int 1221911106dfSjm199354 vs_is_valid_types(const char *types) 1222911106dfSjm199354 { 1223911106dfSjm199354 char buf[VS_VAL_TYPES_LEN]; 1224911106dfSjm199354 uint32_t len = VS_VAL_TYPES_LEN; 1225911106dfSjm199354 1226911106dfSjm199354 if (strlen(types) > VS_VAL_TYPES_LEN) 1227911106dfSjm199354 return (0); 1228911106dfSjm199354 1229911106dfSjm199354 if (strpbrk(types, VS_VAL_TYPES_INVALID_CHARS) != NULL) 1230911106dfSjm199354 return (0); 1231911106dfSjm199354 1232911106dfSjm199354 if (vs_parse_types(types, buf, &len) != 0) 1233911106dfSjm199354 return (0); 1234911106dfSjm199354 1235911106dfSjm199354 return (1); 1236911106dfSjm199354 } 1237911106dfSjm199354 1238911106dfSjm199354 1239911106dfSjm199354 /* 1240911106dfSjm199354 * vs_is_valid_host 1241911106dfSjm199354 * 1242911106dfSjm199354 * Returns 1 on success, 0 on failure 1243911106dfSjm199354 */ 1244911106dfSjm199354 static int 1245911106dfSjm199354 vs_is_valid_host(const char *host) 1246911106dfSjm199354 { 1247911106dfSjm199354 long naddr; 1248911106dfSjm199354 const char *p; 1249911106dfSjm199354 1250911106dfSjm199354 if (!host || *host == '\0') 1251911106dfSjm199354 return (0); 1252911106dfSjm199354 1253911106dfSjm199354 if ('0' <= host[0] && host[0] <= '9') { 1254911106dfSjm199354 /* ip address */ 1255911106dfSjm199354 if ((inet_pton(AF_INET, host, &naddr)) == 0) 1256911106dfSjm199354 return (0); 1257911106dfSjm199354 if ((naddr & IN_CLASSA_NET) == 0) 1258911106dfSjm199354 return (0); 1259911106dfSjm199354 if ((naddr & IN_CLASSC_HOST) == 0) 1260911106dfSjm199354 return (0); 1261911106dfSjm199354 } else { 1262911106dfSjm199354 /* hostname */ 1263911106dfSjm199354 p = host; 1264911106dfSjm199354 while (*p != '\0') { 1265911106dfSjm199354 if (!isascii(*p)) 1266911106dfSjm199354 return (0); 1267911106dfSjm199354 1268911106dfSjm199354 if (isalnum(*p) || 1269911106dfSjm199354 (*p == '.') || (*p == '-') || (*p == '_')) { 1270911106dfSjm199354 ++p; 1271911106dfSjm199354 } else { 1272911106dfSjm199354 return (0); 1273911106dfSjm199354 } 1274911106dfSjm199354 } 1275911106dfSjm199354 } 1276911106dfSjm199354 1277911106dfSjm199354 return (1); 1278911106dfSjm199354 } 1279911106dfSjm199354 1280911106dfSjm199354 1281911106dfSjm199354 /* 1282911106dfSjm199354 * vs_parse_types 1283911106dfSjm199354 * 1284911106dfSjm199354 * Replace comma separators with '\0'. 1285911106dfSjm199354 * 1286911106dfSjm199354 * Types contains comma separated rules each beginning with +|- 1287911106dfSjm199354 * - embedded commas are escaped by backslash 1288911106dfSjm199354 * - backslash is escaped by backslash 1289911106dfSjm199354 * - a single backslash not followed by comma is illegal 1290911106dfSjm199354 * 1291911106dfSjm199354 * On entry to the function len must contain the length of 1292911106dfSjm199354 * the buffer. On sucecssful exit len will contain the length 1293911106dfSjm199354 * of the parsed data within the buffer. 1294911106dfSjm199354 * 1295911106dfSjm199354 * Returns 0 on success, -1 on failure 1296911106dfSjm199354 */ 1297911106dfSjm199354 int 1298911106dfSjm199354 vs_parse_types(const char *types, char *buf, uint32_t *len) 1299911106dfSjm199354 { 1300911106dfSjm199354 char *p = (char *)types; 1301911106dfSjm199354 char *b = buf; 1302911106dfSjm199354 1303911106dfSjm199354 if (strlen(types) > *len) 1304911106dfSjm199354 return (-1); 1305911106dfSjm199354 1306911106dfSjm199354 if (strchr(VS_TYPES_RULES, *p) == NULL) 1307911106dfSjm199354 return (-1); 1308911106dfSjm199354 1309911106dfSjm199354 (void) memset(buf, 0, *len); 1310911106dfSjm199354 1311911106dfSjm199354 while (*p) { 1312911106dfSjm199354 switch (*p) { 1313911106dfSjm199354 case VS_TYPES_SEP: 1314911106dfSjm199354 if (*(p + 1) && 1315911106dfSjm199354 (strchr(VS_TYPES_RULES, *(p + 1))) == NULL) 1316911106dfSjm199354 return (-1); 1317911106dfSjm199354 *b = '\0'; 1318911106dfSjm199354 break; 1319911106dfSjm199354 case VS_TYPES_ESCAPE: 1320911106dfSjm199354 ++p; 1321911106dfSjm199354 if (*p == VS_TYPES_ESCAPE || *p == VS_TYPES_SEP) 1322911106dfSjm199354 *b = *p; 1323911106dfSjm199354 else 1324911106dfSjm199354 return (-1); 1325911106dfSjm199354 break; 1326911106dfSjm199354 default: 1327911106dfSjm199354 *b = *p; 1328911106dfSjm199354 } 1329911106dfSjm199354 ++p; 1330911106dfSjm199354 ++b; 1331911106dfSjm199354 } 1332911106dfSjm199354 1333911106dfSjm199354 *len = (b - buf) + 1; 1334911106dfSjm199354 1335911106dfSjm199354 return (0); 1336911106dfSjm199354 } 1337911106dfSjm199354 1338911106dfSjm199354 1339911106dfSjm199354 /* 1340911106dfSjm199354 * vs_statistics 1341911106dfSjm199354 */ 1342911106dfSjm199354 int 1343911106dfSjm199354 vs_statistics(vs_stats_t *stats) 1344911106dfSjm199354 { 1345911106dfSjm199354 int door_fd, rc = VS_ERR_NONE; 1346911106dfSjm199354 vs_stats_req_t *req; 1347*bfc848c6Sjm199354 vs_stats_rsp_t *rsp; 1348911106dfSjm199354 door_arg_t arg; 1349911106dfSjm199354 1350911106dfSjm199354 if ((req = calloc(1, sizeof (vs_stats_req_t))) == NULL) 1351911106dfSjm199354 return (VS_ERR_SYS); 1352911106dfSjm199354 1353*bfc848c6Sjm199354 if ((rsp = calloc(1, sizeof (vs_stats_rsp_t))) == NULL) { 1354911106dfSjm199354 free(req); 1355911106dfSjm199354 return (VS_ERR_SYS); 1356911106dfSjm199354 } 1357911106dfSjm199354 1358911106dfSjm199354 if ((door_fd = open(VS_STATS_DOOR_NAME, O_RDONLY)) < 0) { 1359911106dfSjm199354 free(req); 1360*bfc848c6Sjm199354 free(rsp); 1361911106dfSjm199354 return (VS_ERR_DAEMON_COMM); 1362911106dfSjm199354 } 1363911106dfSjm199354 1364*bfc848c6Sjm199354 req->vsr_magic = VS_STATS_DOOR_MAGIC; 1365*bfc848c6Sjm199354 req->vsr_id = VS_STATS_GET; 1366911106dfSjm199354 1367911106dfSjm199354 arg.data_ptr = (char *)req; 1368911106dfSjm199354 arg.data_size = sizeof (vs_stats_req_t); 1369911106dfSjm199354 arg.desc_ptr = NULL; 1370911106dfSjm199354 arg.desc_num = 0; 1371*bfc848c6Sjm199354 arg.rbuf = (char *)rsp; 1372*bfc848c6Sjm199354 arg.rsize = sizeof (vs_stats_rsp_t); 1373911106dfSjm199354 1374*bfc848c6Sjm199354 if ((door_call(door_fd, &arg) < 0) || 1375*bfc848c6Sjm199354 (rsp->vsr_magic != VS_STATS_DOOR_MAGIC)) { 1376911106dfSjm199354 rc = VS_ERR_DAEMON_COMM; 1377*bfc848c6Sjm199354 } else { 1378*bfc848c6Sjm199354 *stats = rsp->vsr_stats; 1379*bfc848c6Sjm199354 } 1380911106dfSjm199354 1381911106dfSjm199354 (void) close(door_fd); 1382911106dfSjm199354 1383911106dfSjm199354 free(req); 1384*bfc848c6Sjm199354 free(rsp); 1385911106dfSjm199354 return (rc); 1386911106dfSjm199354 } 1387911106dfSjm199354 1388911106dfSjm199354 1389911106dfSjm199354 /* 1390911106dfSjm199354 * vs_statistics_reset 1391911106dfSjm199354 */ 1392911106dfSjm199354 int 1393911106dfSjm199354 vs_statistics_reset() 1394911106dfSjm199354 { 1395911106dfSjm199354 int door_fd, rc; 1396911106dfSjm199354 vs_stats_req_t *req; 1397911106dfSjm199354 door_arg_t arg; 1398911106dfSjm199354 1399911106dfSjm199354 /* ensure that caller has authorization to reset stats */ 1400911106dfSjm199354 if ((rc = vs_checkauth(VS_VALUE_AUTH)) != VS_ERR_NONE) 1401911106dfSjm199354 return (rc); 1402911106dfSjm199354 1403911106dfSjm199354 if ((req = calloc(1, sizeof (vs_stats_req_t))) == NULL) 1404911106dfSjm199354 return (VS_ERR_SYS); 1405911106dfSjm199354 1406911106dfSjm199354 if ((door_fd = open(VS_STATS_DOOR_NAME, O_RDONLY)) < 0) { 1407911106dfSjm199354 free(req); 1408911106dfSjm199354 return (VS_ERR_DAEMON_COMM); 1409911106dfSjm199354 } 1410911106dfSjm199354 1411*bfc848c6Sjm199354 req->vsr_magic = VS_STATS_DOOR_MAGIC; 1412*bfc848c6Sjm199354 req->vsr_id = VS_STATS_RESET; 1413911106dfSjm199354 1414911106dfSjm199354 arg.data_ptr = (char *)req; 1415911106dfSjm199354 arg.data_size = sizeof (vs_stats_req_t); 1416911106dfSjm199354 arg.desc_ptr = NULL; 1417911106dfSjm199354 arg.desc_num = 0; 1418911106dfSjm199354 arg.rbuf = NULL; 1419911106dfSjm199354 arg.rsize = 0; 1420911106dfSjm199354 1421911106dfSjm199354 if (door_call(door_fd, &arg) < 0) 1422911106dfSjm199354 rc = VS_ERR_DAEMON_COMM; 1423911106dfSjm199354 else 1424911106dfSjm199354 rc = VS_ERR_NONE; 1425911106dfSjm199354 1426911106dfSjm199354 (void) close(door_fd); 1427911106dfSjm199354 free(req); 1428911106dfSjm199354 return (rc); 1429911106dfSjm199354 } 1430911106dfSjm199354 1431911106dfSjm199354 1432911106dfSjm199354 /* 1433911106dfSjm199354 * vs_checkauth 1434911106dfSjm199354 */ 1435911106dfSjm199354 static int 1436911106dfSjm199354 vs_checkauth(char *auth) 1437911106dfSjm199354 { 1438911106dfSjm199354 struct passwd *pw; 1439911106dfSjm199354 uid_t uid; 1440911106dfSjm199354 1441911106dfSjm199354 uid = getuid(); 1442911106dfSjm199354 1443911106dfSjm199354 if ((pw = getpwuid(uid)) == NULL) 1444911106dfSjm199354 return (VS_ERR_SYS); 1445911106dfSjm199354 1446911106dfSjm199354 if (chkauthattr(auth, pw->pw_name) != 1) { 1447911106dfSjm199354 return (VS_ERR_AUTH); 1448911106dfSjm199354 } 1449911106dfSjm199354 1450911106dfSjm199354 return (VS_ERR_NONE); 1451911106dfSjm199354 } 1452911106dfSjm199354 1453911106dfSjm199354 1454911106dfSjm199354 /* 1455911106dfSjm199354 * vs_props_get_engines 1456*bfc848c6Sjm199354 * 1457911106dfSjm199354 * On input, count specifies the maximum number of engine ids to 1458911106dfSjm199354 * return. engids must be an array with count entries. 1459911106dfSjm199354 * On return, count specifies the number of engine ids being 1460911106dfSjm199354 * returned in engids. 1461*bfc848c6Sjm199354 * 1462*bfc848c6Sjm199354 * Caller is responsible for free'ing the engids allocated herein. 1463911106dfSjm199354 */ 1464911106dfSjm199354 static int 1465*bfc848c6Sjm199354 vs_props_get_engines(char *engids[], int *count) 1466911106dfSjm199354 { 1467*bfc848c6Sjm199354 int i, prefix_len; 1468*bfc848c6Sjm199354 char pgname[VS_PGNAME_ENGINE_LEN]; 1469911106dfSjm199354 vs_scfctx_t vsc; 1470911106dfSjm199354 1471911106dfSjm199354 1472911106dfSjm199354 if (((vs_scf_ctx_open(&vsc)) != 0) || 1473911106dfSjm199354 ((vsc.vscf_iter = scf_iter_create(vsc.vscf_handle)) == NULL) || 1474911106dfSjm199354 (scf_iter_instance_pgs_typed(vsc.vscf_iter, vsc.vscf_inst, 1475911106dfSjm199354 SCF_GROUP_APPLICATION) != 0)) { 1476911106dfSjm199354 vs_scf_ctx_close(&vsc); 1477911106dfSjm199354 return (VS_ERR_SCF); 1478911106dfSjm199354 } 1479911106dfSjm199354 1480*bfc848c6Sjm199354 for (i = 0; i < *count; i++) 1481*bfc848c6Sjm199354 engids[i] = NULL; 1482*bfc848c6Sjm199354 1483*bfc848c6Sjm199354 i = 0; 1484*bfc848c6Sjm199354 prefix_len = sizeof (VS_PGNAME_ENGINE_PREFIX) - 1; 1485*bfc848c6Sjm199354 1486911106dfSjm199354 while ((i < VS_SE_MAX) && 1487911106dfSjm199354 (scf_iter_next_pg(vsc.vscf_iter, vsc.vscf_pgroup) == 1)) { 1488*bfc848c6Sjm199354 if (scf_pg_get_name(vsc.vscf_pgroup, pgname, 1489*bfc848c6Sjm199354 VS_PGNAME_ENGINE_LEN) < 0) { 1490911106dfSjm199354 vs_scf_ctx_close(&vsc); 1491911106dfSjm199354 return (VS_ERR_SCF); 1492911106dfSjm199354 } 1493911106dfSjm199354 1494*bfc848c6Sjm199354 if (strncmp(pgname, VS_PGNAME_ENGINE_PREFIX, prefix_len) == 0) { 1495*bfc848c6Sjm199354 if ((engids[i] = strdup(pgname + prefix_len)) != NULL) { 1496911106dfSjm199354 if (++i == *count) 1497911106dfSjm199354 break; 1498911106dfSjm199354 } 1499*bfc848c6Sjm199354 } 1500*bfc848c6Sjm199354 } 1501911106dfSjm199354 vs_scf_ctx_close(&vsc); 1502911106dfSjm199354 1503911106dfSjm199354 *count = i; 1504911106dfSjm199354 return (VS_ERR_NONE); 1505911106dfSjm199354 } 1506911106dfSjm199354 1507911106dfSjm199354 1508911106dfSjm199354 /* 1509911106dfSjm199354 * vs_scf_pg_count 1510911106dfSjm199354 */ 1511911106dfSjm199354 static int 1512911106dfSjm199354 vs_scf_pg_count(void) 1513911106dfSjm199354 { 1514911106dfSjm199354 int count = 0; 1515911106dfSjm199354 vs_scfctx_t vsc; 1516911106dfSjm199354 1517911106dfSjm199354 if ((vs_scf_ctx_open(&vsc) != 0) || 1518911106dfSjm199354 ((vsc.vscf_iter = scf_iter_create(vsc.vscf_handle)) == NULL) || 1519911106dfSjm199354 (scf_iter_instance_pgs_typed(vsc.vscf_iter, vsc.vscf_inst, 1520911106dfSjm199354 SCF_GROUP_APPLICATION) != 0)) { 1521911106dfSjm199354 vs_scf_ctx_close(&vsc); 1522911106dfSjm199354 return (-1); 1523911106dfSjm199354 } 1524911106dfSjm199354 1525911106dfSjm199354 while (scf_iter_next_pg(vsc.vscf_iter, vsc.vscf_pgroup) == 1) 1526911106dfSjm199354 ++count; 1527911106dfSjm199354 1528911106dfSjm199354 vs_scf_ctx_close(&vsc); 1529911106dfSjm199354 1530911106dfSjm199354 return (count); 1531911106dfSjm199354 } 1532911106dfSjm199354 1533911106dfSjm199354 1534911106dfSjm199354 /* 1535*bfc848c6Sjm199354 * vs_engid_to_pgname 1536*bfc848c6Sjm199354 * 1537*bfc848c6Sjm199354 * To convert an engine id (engid) to a property group name (pgname), 1538*bfc848c6Sjm199354 * the engine id is prefixed with VS_PGNAME_ENGINE_PREFIX. 1539*bfc848c6Sjm199354 */ 1540*bfc848c6Sjm199354 static void 1541*bfc848c6Sjm199354 vs_engid_to_pgname(const char *engid, char pgname[VS_PGNAME_ENGINE_LEN]) 1542*bfc848c6Sjm199354 { 1543*bfc848c6Sjm199354 (void) snprintf(pgname, VS_PGNAME_ENGINE_LEN, "%s%s", 1544*bfc848c6Sjm199354 VS_PGNAME_ENGINE_PREFIX, engid); 1545*bfc848c6Sjm199354 } 1546*bfc848c6Sjm199354 1547*bfc848c6Sjm199354 1548*bfc848c6Sjm199354 /* 1549911106dfSjm199354 * vs_strtonum 1550911106dfSjm199354 * 1551911106dfSjm199354 * Converts a size string in the format into an integer. 1552911106dfSjm199354 * 1553911106dfSjm199354 * A size string is a numeric value followed by an optional unit 1554911106dfSjm199354 * specifier which is used as a multiplier to calculate a raw 1555911106dfSjm199354 * number. 1556911106dfSjm199354 * The size string format is: N[.N][KMGTP][B] 1557911106dfSjm199354 * 1558911106dfSjm199354 * The numeric value can contain a decimal portion. Unit specifiers 1559911106dfSjm199354 * are either a one-character or two-character string; i.e. "K" or 1560911106dfSjm199354 * "KB" for kilobytes. Unit specifiers must follow the numeric portion 1561911106dfSjm199354 * immediately, and are not case-sensitive. 1562911106dfSjm199354 * 1563911106dfSjm199354 * If either "B" is specified, or there is no unit specifier portion 1564911106dfSjm199354 * in the string, the numeric value is calculated with no multiplier 1565911106dfSjm199354 * (assumes a basic unit of "bytes"). 1566911106dfSjm199354 * 1567911106dfSjm199354 * Returns: 1568911106dfSjm199354 * -1: Failure; errno set to specify the error. 1569911106dfSjm199354 * 0: Success. 1570911106dfSjm199354 */ 1571911106dfSjm199354 int 1572911106dfSjm199354 vs_strtonum(const char *value, uint64_t *num) 1573911106dfSjm199354 { 1574911106dfSjm199354 char *end; 1575911106dfSjm199354 int shift; 1576911106dfSjm199354 double fval; 1577911106dfSjm199354 1578911106dfSjm199354 *num = 0; 1579911106dfSjm199354 1580911106dfSjm199354 /* Check to see if this looks like a number. */ 1581911106dfSjm199354 if ((value[0] < '0' || value[0] > '9') && value[0] != '.') { 1582911106dfSjm199354 errno = EINVAL; 1583911106dfSjm199354 return (-1); 1584911106dfSjm199354 } 1585911106dfSjm199354 1586911106dfSjm199354 /* Rely on stroll() to process the numeric portion. */ 1587911106dfSjm199354 errno = 0; 1588911106dfSjm199354 *num = strtoll(value, &end, 10); 1589911106dfSjm199354 1590911106dfSjm199354 /* 1591911106dfSjm199354 * Check for ERANGE, which indicates that the value is too large to 1592911106dfSjm199354 * fit in a 64-bit value. 1593911106dfSjm199354 */ 1594911106dfSjm199354 if (errno != 0) 1595911106dfSjm199354 return (-1); 1596911106dfSjm199354 1597911106dfSjm199354 /* 1598911106dfSjm199354 * If we have a decimal value, then do the computation with floating 1599911106dfSjm199354 * point arithmetic. Otherwise, use standard arithmetic. 1600911106dfSjm199354 */ 1601911106dfSjm199354 if (*end == '.') { 1602911106dfSjm199354 fval = strtod(value, &end); 1603911106dfSjm199354 1604911106dfSjm199354 if ((shift = vs_strtoshift(end)) == -1) 1605911106dfSjm199354 return (-1); /* errno set */ 1606911106dfSjm199354 1607911106dfSjm199354 fval *= pow(2, shift); 1608911106dfSjm199354 if (fval > UINT64_MAX) { 1609911106dfSjm199354 errno = ERANGE; 1610911106dfSjm199354 return (-1); 1611911106dfSjm199354 } 1612911106dfSjm199354 1613911106dfSjm199354 *num = (uint64_t)fval; 1614911106dfSjm199354 } else { 1615911106dfSjm199354 if ((shift = vs_strtoshift(end)) == -1) 1616911106dfSjm199354 return (-1); /* errno set */ 1617911106dfSjm199354 1618911106dfSjm199354 /* Check for overflow */ 1619911106dfSjm199354 if (shift >= 64 || (*num << shift) >> shift != *num) { 1620911106dfSjm199354 errno = ERANGE; 1621911106dfSjm199354 return (-1); 1622911106dfSjm199354 } 1623911106dfSjm199354 1624911106dfSjm199354 *num <<= shift; 1625911106dfSjm199354 } 1626911106dfSjm199354 1627911106dfSjm199354 return (0); 1628911106dfSjm199354 } 1629911106dfSjm199354 1630911106dfSjm199354 1631911106dfSjm199354 /* 1632911106dfSjm199354 * vs_strtoshift 1633911106dfSjm199354 * 1634911106dfSjm199354 * Converts a unit specifier string into a number of bits that 1635911106dfSjm199354 * a numeric value must be shifted. 1636911106dfSjm199354 * 1637911106dfSjm199354 * Returns: 1638911106dfSjm199354 * -1: Failure; errno set to specify the error. 1639911106dfSjm199354 * >-1: Success; the shift count. 1640911106dfSjm199354 * 1641911106dfSjm199354 */ 1642911106dfSjm199354 static int 1643911106dfSjm199354 vs_strtoshift(const char *buf) 1644911106dfSjm199354 { 1645911106dfSjm199354 const char *ends = "BKMGTPEZ"; 1646911106dfSjm199354 int i; 1647911106dfSjm199354 1648911106dfSjm199354 if (buf[0] == '\0') 1649911106dfSjm199354 return (0); 1650911106dfSjm199354 for (i = 0; i < strlen(ends); i++) { 1651911106dfSjm199354 if (toupper(buf[0]) == ends[i]) 1652911106dfSjm199354 break; 1653911106dfSjm199354 } 1654911106dfSjm199354 if (i == strlen(ends)) { 1655911106dfSjm199354 errno = EINVAL; 1656911106dfSjm199354 return (-1); 1657911106dfSjm199354 } 1658911106dfSjm199354 1659911106dfSjm199354 /* Allow trailing 'b' characters except in the case of 'BB'. */ 1660911106dfSjm199354 if (buf[1] == '\0' || (toupper(buf[1]) == 'B' && buf[2] == '\0' && 1661911106dfSjm199354 toupper(buf[0]) != 'B')) { 1662911106dfSjm199354 return (10 * i); 1663911106dfSjm199354 } 1664911106dfSjm199354 1665911106dfSjm199354 errno = EINVAL; 1666911106dfSjm199354 return (-1); 1667911106dfSjm199354 } 1668