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*1bf43fcdSjoyce mcintosh * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23911106dfSjm199354 * Use is subject to license terms. 24911106dfSjm199354 */ 25911106dfSjm199354 26911106dfSjm199354 #include <string.h> 27911106dfSjm199354 #include <stdio.h> 28911106dfSjm199354 #include <stdlib.h> 29911106dfSjm199354 #include <unistd.h> 30911106dfSjm199354 #include <ctype.h> 31911106dfSjm199354 #include <math.h> 32911106dfSjm199354 #include <limits.h> 33911106dfSjm199354 #include <libscf.h> 34911106dfSjm199354 #include <errno.h> 35911106dfSjm199354 #include <fcntl.h> 36911106dfSjm199354 #include <door.h> 37911106dfSjm199354 #include <pwd.h> 38911106dfSjm199354 #include <auth_attr.h> 39911106dfSjm199354 #include <secdb.h> 40911106dfSjm199354 #include <sys/socket.h> 41911106dfSjm199354 #include <arpa/inet.h> 42911106dfSjm199354 #include <libintl.h> 43911106dfSjm199354 #include <libvscan.h> 44911106dfSjm199354 451843d056SAlan Wright #define VS_DOOR_CALL_RETRIES 3 461843d056SAlan Wright 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" 51bfc848c6Sjm199354 #define VS_PGNAME_ENGINE_PREFIX "vs_engine_" 52bfc848c6Sjm199354 #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; 138*1bf43fcdSjoyce mcintosh static const uint16_t vs_dflt_maxconn = 8; 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 *); 169bfc848c6Sjm199354 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 *); 1781843d056SAlan Wright static int vs_door_call(int, door_arg_t *); 179911106dfSjm199354 180bfc848c6Sjm199354 static int vs_props_get_engines(char *[], int *); 181bfc848c6Sjm199354 static void vs_engid_to_pgname(const char *, char [VS_PGNAME_ENGINE_LEN]); 182911106dfSjm199354 static int vs_scf_pg_count(void); 183911106dfSjm199354 static int vs_strtoshift(const char *); 184911106dfSjm199354 185911106dfSjm199354 186911106dfSjm199354 /* 187911106dfSjm199354 * vs_props_get_all 188911106dfSjm199354 * 189911106dfSjm199354 * Retrieves the general service properties and all properties 190911106dfSjm199354 * for all scan engines from the repository. 191911106dfSjm199354 * 192911106dfSjm199354 * If invalid property values are found, the values are corrected to 193911106dfSjm199354 * the default value. 194911106dfSjm199354 * 195911106dfSjm199354 * Return codes: 196911106dfSjm199354 * VS_ERR_VS_ERR_NONE 197911106dfSjm199354 * VS_ERR_SCF 198911106dfSjm199354 * VS_ERR_SYS 199911106dfSjm199354 */ 200911106dfSjm199354 int 201911106dfSjm199354 vs_props_get_all(vs_props_all_t *va) 202911106dfSjm199354 { 203911106dfSjm199354 int i, rc, n; 204bfc848c6Sjm199354 char *engids[VS_SE_MAX]; 205911106dfSjm199354 206911106dfSjm199354 (void) memset(va, 0, sizeof (vs_props_all_t)); 207911106dfSjm199354 if ((rc = vs_props_get(&va->va_props, VS_PROPID_GEN_ALL)) 208911106dfSjm199354 != VS_ERR_NONE) 209911106dfSjm199354 return (rc); 210911106dfSjm199354 211911106dfSjm199354 n = VS_SE_MAX; 212911106dfSjm199354 if ((rc = vs_props_get_engines(engids, &n)) != VS_ERR_NONE) 213911106dfSjm199354 return (rc); 214911106dfSjm199354 215911106dfSjm199354 for (i = 0; i < n; i++) { 216bfc848c6Sjm199354 if ((rc = vs_props_se_get(engids[i], 217bfc848c6Sjm199354 &va->va_se[i], VS_PROPID_SE_ALL)) != VS_ERR_NONE) 218bfc848c6Sjm199354 break; 219911106dfSjm199354 } 220911106dfSjm199354 221bfc848c6Sjm199354 /* free engids allocated in vs_props_get_engines */ 222bfc848c6Sjm199354 for (i = 0; i < VS_SE_MAX; i++) { 223bfc848c6Sjm199354 if (engids[i] != NULL) 224bfc848c6Sjm199354 free(engids[i]); 225bfc848c6Sjm199354 } 226bfc848c6Sjm199354 227bfc848c6Sjm199354 return (rc); 228911106dfSjm199354 } 229911106dfSjm199354 230911106dfSjm199354 231911106dfSjm199354 /* 232911106dfSjm199354 * vs_props_get 233911106dfSjm199354 * 234911106dfSjm199354 * Retrieves values for the specified general service properties from 235911106dfSjm199354 * the repository. 236911106dfSjm199354 * 237911106dfSjm199354 * If invalid property values are found, the values are corrected to 238911106dfSjm199354 * the default value. 239911106dfSjm199354 * 240911106dfSjm199354 * Return codes: 241911106dfSjm199354 * VS_ERR_VS_ERR_NONE 242911106dfSjm199354 * VS_ERR_INVALID_PROPERTY 243911106dfSjm199354 * VS_ERR_SCF 244911106dfSjm199354 * VS_ERR_SYS 245911106dfSjm199354 */ 246911106dfSjm199354 int 247911106dfSjm199354 vs_props_get(vs_props_t *vp, uint64_t propids) 248911106dfSjm199354 { 249911106dfSjm199354 int rc; 250911106dfSjm199354 vs_prop_hd_t prop_hd; 251911106dfSjm199354 252911106dfSjm199354 if ((propids & VS_PROPID_GEN_ALL) != propids) 253911106dfSjm199354 return (VS_ERR_INVALID_PROPERTY); 254911106dfSjm199354 255911106dfSjm199354 (void) memset(&prop_hd, 0, sizeof (vs_prop_hd_t)); 256911106dfSjm199354 prop_hd.vp_type = VS_PTYPE_GEN; 257911106dfSjm199354 prop_hd.vp_ids = propids; 258911106dfSjm199354 prop_hd.vp_all = VS_PROPID_GEN_ALL; 259911106dfSjm199354 260911106dfSjm199354 rc = vs_scf_values_get(VS_PGNAME_GENERAL, &prop_hd); 261911106dfSjm199354 262911106dfSjm199354 *vp = prop_hd.vp_gen; 263911106dfSjm199354 return (rc); 264911106dfSjm199354 } 265911106dfSjm199354 266911106dfSjm199354 267911106dfSjm199354 /* 268911106dfSjm199354 * vs_props_set 269911106dfSjm199354 * 270911106dfSjm199354 * Changes values for the specified general service properties 271911106dfSjm199354 * in the repository. 272911106dfSjm199354 * 273911106dfSjm199354 * Return codes: 274911106dfSjm199354 * VS_ERR_VS_ERR_NONE 275911106dfSjm199354 * VS_ERR_INVALID_PROPERTY 276911106dfSjm199354 * VS_ERR_INVALID_VALUE 277911106dfSjm199354 * VS_ERR_SCF 278911106dfSjm199354 * VS_ERR_SYS 279911106dfSjm199354 */ 280911106dfSjm199354 int 281911106dfSjm199354 vs_props_set(const vs_props_t *vp, uint64_t propids) 282911106dfSjm199354 { 283911106dfSjm199354 vs_prop_hd_t prop_hd; 284911106dfSjm199354 285911106dfSjm199354 if ((propids & VS_PROPID_GEN_ALL) != propids) 286911106dfSjm199354 return (VS_ERR_INVALID_PROPERTY); 287911106dfSjm199354 288911106dfSjm199354 (void) memset(&prop_hd, 0, sizeof (vs_prop_hd_t)); 289911106dfSjm199354 prop_hd.vp_type = VS_PTYPE_GEN; 290911106dfSjm199354 prop_hd.vp_ids = propids; 291911106dfSjm199354 prop_hd.vp_all = VS_PROPID_GEN_ALL; 292911106dfSjm199354 prop_hd.vp_gen = *vp; 293911106dfSjm199354 return (vs_scf_values_set(VS_PGNAME_GENERAL, &prop_hd)); 294911106dfSjm199354 } 295911106dfSjm199354 296911106dfSjm199354 297911106dfSjm199354 /* 298911106dfSjm199354 * vs_props_se_get 299911106dfSjm199354 * 300911106dfSjm199354 * Retrieves values for the specified scan engine properties from the 301911106dfSjm199354 * repository. 302911106dfSjm199354 * 303911106dfSjm199354 * If the enable property is set (true), the host property is 304911106dfSjm199354 * checked for validity. If it is not valid, the requested values 305911106dfSjm199354 * are returned with the enable propery set to off (false) 306911106dfSjm199354 * 307911106dfSjm199354 * Return codes: 308911106dfSjm199354 * VS_ERR_VS_ERR_NONE 309911106dfSjm199354 * VS_ERR_INVALID_PROPERTY 310911106dfSjm199354 * VS_ERR_SCF 311911106dfSjm199354 * VS_ERR_SYS 312911106dfSjm199354 */ 313911106dfSjm199354 int 314911106dfSjm199354 vs_props_se_get(char *engid, vs_props_se_t *sep, uint64_t propids) 315911106dfSjm199354 { 316911106dfSjm199354 int rc; 317bfc848c6Sjm199354 char pgname[VS_PGNAME_ENGINE_LEN]; 318911106dfSjm199354 vs_prop_hd_t prop_hd; 319911106dfSjm199354 320911106dfSjm199354 /* VS_PGNAME_GENERAL is a reserved for GENERAL property group */ 321911106dfSjm199354 if (strcmp(engid, VS_PGNAME_GENERAL) == 0) 322911106dfSjm199354 return (VS_ERR_INVALID_SE); 323911106dfSjm199354 324911106dfSjm199354 if ((propids & VS_PROPID_SE_ALL) != propids) 325911106dfSjm199354 return (VS_ERR_INVALID_PROPERTY); 326911106dfSjm199354 327911106dfSjm199354 (void) memset(&prop_hd, 0, sizeof (vs_prop_hd_t)); 328911106dfSjm199354 prop_hd.vp_type = VS_PTYPE_SE; 329911106dfSjm199354 prop_hd.vp_ids = propids; 330911106dfSjm199354 prop_hd.vp_all = VS_PROPID_SE_ALL; 331911106dfSjm199354 (void) strlcpy(prop_hd.vp_se.vep_engid, engid, VS_SE_NAME_LEN); 332911106dfSjm199354 333911106dfSjm199354 /* If getting enable, get the host property too */ 334911106dfSjm199354 if ((propids & VS_PROPID_SE_ENABLE)) 335911106dfSjm199354 prop_hd.vp_ids |= VS_PROPID_SE_HOST; 336911106dfSjm199354 337911106dfSjm199354 /* Load values from the repository */ 338bfc848c6Sjm199354 vs_engid_to_pgname(engid, pgname); 339bfc848c6Sjm199354 rc = vs_scf_values_get(pgname, &prop_hd); 340911106dfSjm199354 if (rc != VS_ERR_NONE) 341911106dfSjm199354 return (rc); 342911106dfSjm199354 343911106dfSjm199354 /* 344911106dfSjm199354 * If the host is invalid and the enable property is on, 345911106dfSjm199354 * return enable property as off 346911106dfSjm199354 */ 347911106dfSjm199354 if ((prop_hd.vp_ids & VS_PROPID_SE_HOST) && 348911106dfSjm199354 (vs_validate(&prop_hd, VS_PROPID_SE_HOST) != VS_ERR_NONE)) { 349911106dfSjm199354 prop_hd.vp_se.vep_enable = B_FALSE; 350911106dfSjm199354 } 351911106dfSjm199354 352911106dfSjm199354 *sep = prop_hd.vp_se; 353911106dfSjm199354 return (rc); 354911106dfSjm199354 } 355911106dfSjm199354 356911106dfSjm199354 357911106dfSjm199354 358911106dfSjm199354 /* 359911106dfSjm199354 * vs_props_se_set 360911106dfSjm199354 * 361911106dfSjm199354 * Changes the values for the specified scan engine properties in the 362911106dfSjm199354 * repository. 363911106dfSjm199354 * 364911106dfSjm199354 * If the enable property is being changed to true in this operation, 365911106dfSjm199354 * a host property must also be specified, or already exist in the 366911106dfSjm199354 * repository. 367911106dfSjm199354 * 368911106dfSjm199354 * Return codes: 369911106dfSjm199354 * VS_ERR_NONE 370911106dfSjm199354 * VS_ERR_INVALID_PROPERTY 371911106dfSjm199354 * VS_ERR_INVALID_VALUE 372911106dfSjm199354 * VS_ERR_SCF 373911106dfSjm199354 * VS_ERR_SYS 374911106dfSjm199354 */ 375911106dfSjm199354 int 376911106dfSjm199354 vs_props_se_set(char *engid, const vs_props_se_t *sep, uint64_t propids) 377911106dfSjm199354 { 378911106dfSjm199354 int rc; 379bfc848c6Sjm199354 char pgname[VS_PGNAME_ENGINE_LEN]; 380911106dfSjm199354 vs_prop_hd_t prop_hd; 381911106dfSjm199354 382911106dfSjm199354 /* VS_PGNAME_GENERAL is a reserved for GENERAL property group */ 383911106dfSjm199354 if (strcmp(engid, VS_PGNAME_GENERAL) == 0) 384911106dfSjm199354 return (VS_ERR_INVALID_SE); 385911106dfSjm199354 386911106dfSjm199354 if ((propids & VS_PROPID_SE_ALL) != propids) 387911106dfSjm199354 return (VS_ERR_INVALID_PROPERTY); 388911106dfSjm199354 389911106dfSjm199354 (void) memset(&prop_hd, 0, sizeof (vs_prop_hd_t)); 390911106dfSjm199354 prop_hd.vp_type = VS_PTYPE_SE; 391911106dfSjm199354 prop_hd.vp_all = VS_PROPID_SE_ALL; 392911106dfSjm199354 393bfc848c6Sjm199354 vs_engid_to_pgname(engid, pgname); 394bfc848c6Sjm199354 395911106dfSjm199354 /* 396911106dfSjm199354 * if enabling a scan engine, ensure that a valid host 397911106dfSjm199354 * is also being set, or already exists in the repository 398911106dfSjm199354 */ 399911106dfSjm199354 if ((propids & VS_PROPID_SE_ENABLE) && (sep->vep_enable == B_TRUE) && 400911106dfSjm199354 !(propids & VS_PROPID_SE_HOST)) { 401911106dfSjm199354 402911106dfSjm199354 prop_hd.vp_ids = VS_PROPID_SE_HOST; 403bfc848c6Sjm199354 if ((rc = vs_scf_values_get(pgname, &prop_hd)) != VS_ERR_NONE) 404911106dfSjm199354 return (rc); 405911106dfSjm199354 406911106dfSjm199354 if (vs_validate(&prop_hd, VS_PROPID_SE_HOST) != VS_ERR_NONE) 407911106dfSjm199354 return (VS_ERR_INVALID_HOST); 408911106dfSjm199354 } 409911106dfSjm199354 410911106dfSjm199354 prop_hd.vp_ids = propids; 411911106dfSjm199354 prop_hd.vp_se = *sep; 412911106dfSjm199354 413bfc848c6Sjm199354 return (vs_scf_values_set(pgname, &prop_hd)); 414911106dfSjm199354 } 415911106dfSjm199354 416911106dfSjm199354 417911106dfSjm199354 /* 418911106dfSjm199354 * vs_props_se_create 419911106dfSjm199354 */ 420911106dfSjm199354 int 421911106dfSjm199354 vs_props_se_create(char *engid, const vs_props_se_t *sep, uint64_t propids) 422911106dfSjm199354 { 423911106dfSjm199354 int n; 424bfc848c6Sjm199354 char pgname[VS_PGNAME_ENGINE_LEN]; 425911106dfSjm199354 vs_prop_hd_t prop_hd; 426911106dfSjm199354 427911106dfSjm199354 if ((propids & VS_PROPID_SE_ALL) != propids) 428911106dfSjm199354 return (VS_ERR_INVALID_PROPERTY); 429911106dfSjm199354 430911106dfSjm199354 /* VS_PGNAME_GENERAL is a reserved for GENERAL property group */ 431911106dfSjm199354 if (strcmp(engid, VS_PGNAME_GENERAL) == 0) 432911106dfSjm199354 return (VS_ERR_INVALID_SE); 433911106dfSjm199354 434911106dfSjm199354 if ((n = vs_scf_pg_count()) == -1) 435911106dfSjm199354 return (VS_ERR_SCF); 436911106dfSjm199354 437911106dfSjm199354 if (n == VS_SE_MAX) 438911106dfSjm199354 return (VS_ERR_MAX_SE); 439911106dfSjm199354 440bfc848c6Sjm199354 vs_engid_to_pgname(engid, pgname); 441bfc848c6Sjm199354 442911106dfSjm199354 (void) memset(&prop_hd, 0, sizeof (vs_prop_hd_t)); 443911106dfSjm199354 prop_hd.vp_type = VS_PTYPE_SE; 444911106dfSjm199354 prop_hd.vp_all = VS_PROPID_SE_ALL; 445911106dfSjm199354 prop_hd.vp_ids = propids | VS_PROPID_VALUE_AUTH; 446911106dfSjm199354 prop_hd.vp_se = *sep; 447911106dfSjm199354 448bfc848c6Sjm199354 /* if hostname not specified, default it to engid */ 449bfc848c6Sjm199354 if ((propids & VS_PROPID_SE_HOST) == 0) { 450bfc848c6Sjm199354 (void) strlcpy(prop_hd.vp_se.vep_host, engid, MAXHOSTNAMELEN); 451bfc848c6Sjm199354 prop_hd.vp_ids |= VS_PROPID_SE_HOST; 452bfc848c6Sjm199354 } 453911106dfSjm199354 454bfc848c6Sjm199354 return (vs_scf_pg_create(pgname, &prop_hd)); 455911106dfSjm199354 } 456911106dfSjm199354 457911106dfSjm199354 458911106dfSjm199354 /* 459911106dfSjm199354 * vs_props_se_delete 460911106dfSjm199354 */ 461911106dfSjm199354 int 462911106dfSjm199354 vs_props_se_delete(const char *engid) 463911106dfSjm199354 { 464bfc848c6Sjm199354 char pgname[VS_PGNAME_ENGINE_LEN]; 465911106dfSjm199354 466911106dfSjm199354 /* VS_PGNAME_GENERAL is a reserved for GENERAL property group */ 467911106dfSjm199354 if (strcmp(engid, VS_PGNAME_GENERAL) == 0) 468911106dfSjm199354 return (VS_ERR_INVALID_SE); 469911106dfSjm199354 470bfc848c6Sjm199354 vs_engid_to_pgname(engid, pgname); 471911106dfSjm199354 472bfc848c6Sjm199354 return (vs_scf_pg_delete(pgname)); 473911106dfSjm199354 } 474911106dfSjm199354 475911106dfSjm199354 476911106dfSjm199354 /* 477911106dfSjm199354 * vs_strerror 478911106dfSjm199354 */ 479911106dfSjm199354 const char * 480911106dfSjm199354 vs_strerror(int error) 481911106dfSjm199354 { 482911106dfSjm199354 switch (error) { 483911106dfSjm199354 case VS_ERR_NONE: 484911106dfSjm199354 return (gettext("no error")); 485911106dfSjm199354 case VS_ERR_INVALID_PROPERTY: 486911106dfSjm199354 return (gettext("invalid property id")); 487911106dfSjm199354 case VS_ERR_INVALID_VALUE: 488911106dfSjm199354 return (gettext("invalid property value")); 489911106dfSjm199354 case VS_ERR_INVALID_HOST: 490911106dfSjm199354 return (gettext("invalid host")); 491911106dfSjm199354 case VS_ERR_INVALID_SE: 492911106dfSjm199354 return (gettext("invalid scan engine")); 493911106dfSjm199354 case VS_ERR_MAX_SE: 494911106dfSjm199354 return (gettext("max scan engines exceeded")); 495911106dfSjm199354 case VS_ERR_AUTH: 496911106dfSjm199354 return (gettext("insufficient privileges for action")); 497911106dfSjm199354 case VS_ERR_DAEMON_COMM: 498911106dfSjm199354 return (gettext("unable to contact vscand")); 499911106dfSjm199354 case VS_ERR_SCF: 500911106dfSjm199354 return (scf_strerror(scf_error())); 501911106dfSjm199354 case VS_ERR_SYS: 502911106dfSjm199354 return (strerror(errno)); 503911106dfSjm199354 default: 504911106dfSjm199354 return (gettext("unknown error")); 505911106dfSjm199354 } 506911106dfSjm199354 } 507911106dfSjm199354 508911106dfSjm199354 509911106dfSjm199354 /* 510911106dfSjm199354 * vs_get_propdef 511911106dfSjm199354 * 512911106dfSjm199354 * Finds and returns a property definition by property id. 513911106dfSjm199354 */ 514911106dfSjm199354 static const vs_propdef_t * 515911106dfSjm199354 vs_get_propdef(uint64_t propid) 516911106dfSjm199354 { 517911106dfSjm199354 int i; 518911106dfSjm199354 519911106dfSjm199354 for (i = 0; i < vs_npropdefs; i++) { 520911106dfSjm199354 if (propid == vs_propdefs[i].vpd_id) 521911106dfSjm199354 return (&vs_propdefs[i]); 522911106dfSjm199354 } 523911106dfSjm199354 524911106dfSjm199354 return (NULL); 525911106dfSjm199354 } 526911106dfSjm199354 527911106dfSjm199354 528911106dfSjm199354 /* 529911106dfSjm199354 * vs_default_value 530911106dfSjm199354 * 531911106dfSjm199354 * Sets a property value that contains invalid data to its default value. 532911106dfSjm199354 * 533911106dfSjm199354 * Note that this function does not alter any values in the repository 534911106dfSjm199354 * This is only to enable the caller to get valid data. 535911106dfSjm199354 */ 536911106dfSjm199354 static void 537911106dfSjm199354 vs_default_value(vs_prop_hd_t *prop_hd, const uint64_t propid) 538911106dfSjm199354 { 539911106dfSjm199354 vs_props_t *vp = &prop_hd->vp_gen; 540911106dfSjm199354 vs_props_se_t *vep = &prop_hd->vp_se; 541911106dfSjm199354 542911106dfSjm199354 switch (propid) { 543911106dfSjm199354 case VS_PROPID_MAXSIZE: 544911106dfSjm199354 (void) strlcpy(vp->vp_maxsize, vs_dflt_maxsize, 545911106dfSjm199354 sizeof (vp->vp_maxsize)); 546911106dfSjm199354 break; 547911106dfSjm199354 case VS_PROPID_MAXSIZE_ACTION: 548911106dfSjm199354 vp->vp_maxsize_action = vs_dflt_allow; 549911106dfSjm199354 break; 550911106dfSjm199354 case VS_PROPID_TYPES: 551911106dfSjm199354 (void) strlcpy(vp->vp_types, vs_dflt_types, 552911106dfSjm199354 sizeof (vp->vp_types)); 553911106dfSjm199354 break; 554911106dfSjm199354 case VS_PROPID_VLOG: 555911106dfSjm199354 (void) strlcpy(vp->vp_vlog, vs_dflt_vlog, 556911106dfSjm199354 sizeof (vp->vp_vlog)); 557911106dfSjm199354 break; 558911106dfSjm199354 case VS_PROPID_SE_ENABLE: 559911106dfSjm199354 vep->vep_enable = vs_dflt_enable; 560911106dfSjm199354 break; 561911106dfSjm199354 case VS_PROPID_SE_HOST: 562911106dfSjm199354 (void) strlcpy(vep->vep_host, vs_dflt_host, 563911106dfSjm199354 sizeof (vep->vep_host)); 564911106dfSjm199354 break; 565911106dfSjm199354 case VS_PROPID_SE_PORT: 566911106dfSjm199354 vep->vep_port = vs_dflt_port; 567911106dfSjm199354 break; 568911106dfSjm199354 case VS_PROPID_SE_MAXCONN: 569911106dfSjm199354 vep->vep_maxconn = vs_dflt_maxconn; 570911106dfSjm199354 break; 571911106dfSjm199354 default: 572911106dfSjm199354 break; 573911106dfSjm199354 } 574911106dfSjm199354 } 575911106dfSjm199354 576911106dfSjm199354 577911106dfSjm199354 /* 578911106dfSjm199354 * vs_scf_values_get 579911106dfSjm199354 * 580911106dfSjm199354 * Gets property values for one or more properties from the repository. 581911106dfSjm199354 * This is the single entry point for loading SMF values. 582911106dfSjm199354 * 583911106dfSjm199354 * While a transaction is not used for loading property values, 584911106dfSjm199354 * the operation is parameterized by a property group. All properties 585911106dfSjm199354 * retrieved in this function, then, must belong to the same property 586911106dfSjm199354 * group. 587911106dfSjm199354 */ 588911106dfSjm199354 int 589911106dfSjm199354 vs_scf_values_get(const char *pgname, vs_prop_hd_t *prop_hd) 590911106dfSjm199354 { 591911106dfSjm199354 vs_scfctx_t vsc; 592911106dfSjm199354 int rc, np; 593911106dfSjm199354 const vs_propdef_t *vpd; 594911106dfSjm199354 uint64_t propid; 595911106dfSjm199354 596911106dfSjm199354 if ((vs_scf_ctx_open(&vsc)) != 0) { 597911106dfSjm199354 vs_scf_ctx_close(&vsc); 598911106dfSjm199354 return (VS_ERR_SCF); 599911106dfSjm199354 } 600911106dfSjm199354 601911106dfSjm199354 if (scf_instance_get_pg(vsc.vscf_inst, pgname, vsc.vscf_pgroup) == -1) { 602911106dfSjm199354 vs_scf_ctx_close(&vsc); 603911106dfSjm199354 if (strcmp(pgname, "VS_PGNAME_GENERAL") != 0) { 604911106dfSjm199354 rc = scf_error(); 605911106dfSjm199354 if ((rc == SCF_ERROR_NOT_FOUND) || 606911106dfSjm199354 (rc == SCF_ERROR_INVALID_ARGUMENT)) 607911106dfSjm199354 return (VS_ERR_INVALID_SE); 608911106dfSjm199354 } 609911106dfSjm199354 return (VS_ERR_SCF); 610911106dfSjm199354 } 611911106dfSjm199354 612911106dfSjm199354 rc = VS_ERR_NONE; 613911106dfSjm199354 np = 0; 614911106dfSjm199354 for (propid = 1LL; propid <= VS_PROPID_MAX; propid <<= 1) { 615911106dfSjm199354 if ((prop_hd->vp_ids & propid) == 0) 616911106dfSjm199354 continue; 617911106dfSjm199354 618911106dfSjm199354 if ((vpd = vs_get_propdef(propid)) == NULL) { 619911106dfSjm199354 rc = VS_ERR_INVALID_PROPERTY; 620911106dfSjm199354 break; 621911106dfSjm199354 } 622911106dfSjm199354 623911106dfSjm199354 vsc.vscf_prop[np] = scf_property_create(vsc.vscf_handle); 624911106dfSjm199354 vsc.vscf_val[np] = scf_value_create(vsc.vscf_handle); 625911106dfSjm199354 626911106dfSjm199354 if (vsc.vscf_prop[np] == NULL || vsc.vscf_val[np] == NULL) { 627911106dfSjm199354 rc = VS_ERR_SCF; 628911106dfSjm199354 break; 629911106dfSjm199354 } 630911106dfSjm199354 631911106dfSjm199354 if (scf_pg_get_property(vsc.vscf_pgroup, vpd->vpd_name, 632911106dfSjm199354 vsc.vscf_prop[np]) == -1) { 633911106dfSjm199354 if (scf_error() == SCF_ERROR_NOT_FOUND) { 634911106dfSjm199354 vs_default_value(prop_hd, vpd->vpd_id); 635911106dfSjm199354 continue; 636911106dfSjm199354 } 637911106dfSjm199354 rc = VS_ERR_SCF; 638911106dfSjm199354 break; 639911106dfSjm199354 } 640911106dfSjm199354 641911106dfSjm199354 if ((rc = vs_scf_get(vpd, prop_hd, &vsc, np)) != VS_ERR_NONE) 642911106dfSjm199354 break; 643911106dfSjm199354 644911106dfSjm199354 ++np; 645911106dfSjm199354 } 646911106dfSjm199354 647911106dfSjm199354 648911106dfSjm199354 vs_scf_ctx_close(&vsc); 649911106dfSjm199354 650911106dfSjm199354 return (rc); 651911106dfSjm199354 } 652911106dfSjm199354 653911106dfSjm199354 654911106dfSjm199354 /* 655911106dfSjm199354 * vs_scf_get 656911106dfSjm199354 * 657911106dfSjm199354 * Loads a single values from the repository into the appropriate vscan 658911106dfSjm199354 * property structure member. 659911106dfSjm199354 */ 660911106dfSjm199354 static int 661911106dfSjm199354 vs_scf_get(const vs_propdef_t *vpd, vs_prop_hd_t *prop_hd, 662911106dfSjm199354 vs_scfctx_t *vsc, int idx) 663911106dfSjm199354 { 664911106dfSjm199354 int rc; 665911106dfSjm199354 int64_t port; 666911106dfSjm199354 uint8_t valbool; 667911106dfSjm199354 vs_props_t *vp = &prop_hd->vp_gen; 668911106dfSjm199354 vs_props_se_t *vep = &prop_hd->vp_se; 669911106dfSjm199354 670911106dfSjm199354 if ((rc = scf_property_get_value(vsc->vscf_prop[idx], 671911106dfSjm199354 vsc->vscf_val[idx])) == -1) { 672911106dfSjm199354 if (rc == SCF_ERROR_CONSTRAINT_VIOLATED || 673911106dfSjm199354 rc == SCF_ERROR_NOT_FOUND) { 674911106dfSjm199354 vs_default_value(prop_hd, vpd->vpd_id); 675911106dfSjm199354 return (VS_ERR_NONE); 676911106dfSjm199354 } 677911106dfSjm199354 return (VS_ERR_SCF); 678911106dfSjm199354 } 679911106dfSjm199354 680911106dfSjm199354 rc = VS_ERR_NONE; 681911106dfSjm199354 switch (vpd->vpd_id) { 682911106dfSjm199354 case VS_PROPID_MAXSIZE: 683911106dfSjm199354 if ((scf_value_get_astring(vsc->vscf_val[idx], 684911106dfSjm199354 vp->vp_maxsize, sizeof (vp->vp_maxsize))) == -1) { 685911106dfSjm199354 return (VS_ERR_SCF); 686911106dfSjm199354 } 687911106dfSjm199354 break; 688911106dfSjm199354 case VS_PROPID_MAXSIZE_ACTION: 689911106dfSjm199354 if ((scf_value_get_boolean(vsc->vscf_val[idx], 690911106dfSjm199354 &valbool)) == -1) { 691911106dfSjm199354 return (VS_ERR_SCF); 692911106dfSjm199354 } 693911106dfSjm199354 vp->vp_maxsize_action = (valbool == 0) ? B_FALSE : B_TRUE; 694911106dfSjm199354 break; 695911106dfSjm199354 case VS_PROPID_TYPES: 696911106dfSjm199354 if ((scf_value_get_astring(vsc->vscf_val[idx], 697911106dfSjm199354 vp->vp_types, sizeof (vp->vp_types))) == -1) { 698911106dfSjm199354 return (VS_ERR_SCF); 699911106dfSjm199354 } 700911106dfSjm199354 break; 701911106dfSjm199354 case VS_PROPID_VLOG: 702911106dfSjm199354 if ((scf_value_get_astring(vsc->vscf_val[idx], 703911106dfSjm199354 vp->vp_vlog, sizeof (vp->vp_vlog))) == -1) { 704911106dfSjm199354 return (VS_ERR_SCF); 705911106dfSjm199354 } 706911106dfSjm199354 break; 707911106dfSjm199354 case VS_PROPID_SE_ENABLE: 708911106dfSjm199354 if ((scf_value_get_boolean(vsc->vscf_val[idx], 709911106dfSjm199354 &valbool)) == -1) { 710911106dfSjm199354 return (VS_ERR_SCF); 711911106dfSjm199354 } 712911106dfSjm199354 vep->vep_enable = (valbool == 0) ? B_FALSE : B_TRUE; 713911106dfSjm199354 break; 714911106dfSjm199354 case VS_PROPID_SE_HOST: 715911106dfSjm199354 (void) scf_value_get_as_string_typed(vsc->vscf_val[idx], 716911106dfSjm199354 vpd->vpd_type, vep->vep_host, sizeof (vep->vep_host)); 717911106dfSjm199354 break; 718911106dfSjm199354 case VS_PROPID_SE_PORT: 719911106dfSjm199354 if ((scf_value_get_integer(vsc->vscf_val[idx], &port)) == -1) 720911106dfSjm199354 return (VS_ERR_SCF); 721911106dfSjm199354 if (port <= 0 || port >= UINT16_MAX) 722911106dfSjm199354 rc = VS_ERR_INVALID_VALUE; 723911106dfSjm199354 else 724911106dfSjm199354 vep->vep_port = (uint16_t)port; 725911106dfSjm199354 break; 726911106dfSjm199354 case VS_PROPID_SE_MAXCONN: 727911106dfSjm199354 if ((scf_value_get_integer(vsc->vscf_val[idx], 728911106dfSjm199354 (int64_t *)&vep->vep_maxconn)) == -1) { 729911106dfSjm199354 return (VS_ERR_SCF); 730911106dfSjm199354 } 731911106dfSjm199354 break; 732911106dfSjm199354 default: 733911106dfSjm199354 break; 734911106dfSjm199354 } 735911106dfSjm199354 736911106dfSjm199354 if ((rc != VS_ERR_NONE) || 737911106dfSjm199354 (vs_validate(prop_hd, vpd->vpd_id) != VS_ERR_NONE)) { 738911106dfSjm199354 vs_default_value(prop_hd, vpd->vpd_id); 739911106dfSjm199354 } 740911106dfSjm199354 741911106dfSjm199354 return (VS_ERR_NONE); 742911106dfSjm199354 } 743911106dfSjm199354 744911106dfSjm199354 745911106dfSjm199354 /* 746911106dfSjm199354 * vs_scf_pg_create 747911106dfSjm199354 */ 748911106dfSjm199354 static int 749911106dfSjm199354 vs_scf_pg_create(const char *pgname, vs_prop_hd_t *prop_hd) 750911106dfSjm199354 { 751911106dfSjm199354 int rc; 752911106dfSjm199354 uint64_t propid; 753911106dfSjm199354 vs_scfctx_t vsc; 754911106dfSjm199354 755911106dfSjm199354 /* ensure that caller has authorization to refresh service */ 756911106dfSjm199354 if ((rc = vs_checkauth(VS_ACTION_AUTH)) != VS_ERR_NONE) 757911106dfSjm199354 return (rc); 758911106dfSjm199354 759911106dfSjm199354 if (vs_scf_ctx_open(&vsc) != 0) { 760911106dfSjm199354 vs_scf_ctx_close(&vsc); 761911106dfSjm199354 return (VS_ERR_SCF); 762911106dfSjm199354 } 763911106dfSjm199354 764911106dfSjm199354 if (scf_instance_add_pg(vsc.vscf_inst, pgname, 765911106dfSjm199354 SCF_GROUP_APPLICATION, 0, vsc.vscf_pgroup) == -1) { 766911106dfSjm199354 vs_scf_ctx_close(&vsc); 767911106dfSjm199354 if (scf_error() == SCF_ERROR_INVALID_ARGUMENT) 768911106dfSjm199354 return (VS_ERR_INVALID_SE); 769911106dfSjm199354 return (VS_ERR_SCF); 770911106dfSjm199354 } 771911106dfSjm199354 vs_scf_ctx_close(&vsc); 772911106dfSjm199354 773911106dfSjm199354 /* set default values for those not specified */ 774911106dfSjm199354 for (propid = 1LL; propid <= VS_PROPID_MAX; propid <<= 1) { 775911106dfSjm199354 if ((propid & prop_hd->vp_all) && !(propid & prop_hd->vp_ids)) 776911106dfSjm199354 vs_default_value(prop_hd, propid); 777911106dfSjm199354 } 778bfc848c6Sjm199354 779911106dfSjm199354 prop_hd->vp_ids = prop_hd->vp_all; 780911106dfSjm199354 prop_hd->vp_ids |= VS_PROPID_VALUE_AUTH; 781911106dfSjm199354 782911106dfSjm199354 rc = vs_scf_values_set(pgname, prop_hd); 783911106dfSjm199354 if (rc != VS_ERR_NONE) 784bfc848c6Sjm199354 (void) vs_scf_pg_delete(pgname); 785911106dfSjm199354 786911106dfSjm199354 return (rc); 787911106dfSjm199354 } 788911106dfSjm199354 789911106dfSjm199354 790911106dfSjm199354 /* 791bfc848c6Sjm199354 * vs_scf_pg_delete 792bfc848c6Sjm199354 */ 793bfc848c6Sjm199354 static int 794bfc848c6Sjm199354 vs_scf_pg_delete(const char *pgname) 795bfc848c6Sjm199354 { 796bfc848c6Sjm199354 int rc; 797bfc848c6Sjm199354 vs_scfctx_t vsc; 798bfc848c6Sjm199354 799bfc848c6Sjm199354 /* ensure that caller has authorization to refresh service */ 800bfc848c6Sjm199354 if ((rc = vs_checkauth(VS_ACTION_AUTH)) != VS_ERR_NONE) 801bfc848c6Sjm199354 return (rc); 802bfc848c6Sjm199354 803bfc848c6Sjm199354 if (vs_scf_ctx_open(&vsc) != 0) { 804bfc848c6Sjm199354 vs_scf_ctx_close(&vsc); 805bfc848c6Sjm199354 return (VS_ERR_SCF); 806bfc848c6Sjm199354 } 807bfc848c6Sjm199354 808bfc848c6Sjm199354 if (scf_instance_get_pg(vsc.vscf_inst, pgname, vsc.vscf_pgroup) == -1) { 809bfc848c6Sjm199354 vs_scf_ctx_close(&vsc); 810bfc848c6Sjm199354 rc = scf_error(); 811bfc848c6Sjm199354 if ((rc == SCF_ERROR_NOT_FOUND) || 812bfc848c6Sjm199354 (rc == SCF_ERROR_INVALID_ARGUMENT)) 813bfc848c6Sjm199354 return (VS_ERR_INVALID_SE); 814bfc848c6Sjm199354 else 815bfc848c6Sjm199354 return (VS_ERR_SCF); 816bfc848c6Sjm199354 } 817bfc848c6Sjm199354 818bfc848c6Sjm199354 if (scf_pg_delete(vsc.vscf_pgroup) == -1) { 819bfc848c6Sjm199354 vs_scf_ctx_close(&vsc); 820bfc848c6Sjm199354 rc = scf_error(); 821bfc848c6Sjm199354 if ((rc == SCF_ERROR_NOT_FOUND) || 822bfc848c6Sjm199354 (rc == SCF_ERROR_INVALID_ARGUMENT)) 823bfc848c6Sjm199354 return (VS_ERR_INVALID_SE); 824bfc848c6Sjm199354 825bfc848c6Sjm199354 return (VS_ERR_SCF); 826bfc848c6Sjm199354 } 827bfc848c6Sjm199354 828bfc848c6Sjm199354 vs_scf_ctx_close(&vsc); 829bfc848c6Sjm199354 830bfc848c6Sjm199354 /* Notify the daemon that things have changed */ 831bfc848c6Sjm199354 if ((smf_refresh_instance(VS_INSTANCE_FMRI)) == -1) { 832bfc848c6Sjm199354 return (VS_ERR_SCF); 833bfc848c6Sjm199354 } 834bfc848c6Sjm199354 835bfc848c6Sjm199354 return (VS_ERR_NONE); 836bfc848c6Sjm199354 } 837bfc848c6Sjm199354 838bfc848c6Sjm199354 839bfc848c6Sjm199354 /* 840911106dfSjm199354 * vs_scf_values_set 841911106dfSjm199354 * 842911106dfSjm199354 * Sets property values in the repository. This is the single 843911106dfSjm199354 * entry point for storing SMF values. 844911106dfSjm199354 * 845911106dfSjm199354 * Like loading values, this is an operation based on a single property 846911106dfSjm199354 * group, so all property values changed in this function must belong 847911106dfSjm199354 * to the same property group. Additionally, this operation is done in 848911106dfSjm199354 * the context of a repository transaction; on any fatal error, the 849911106dfSjm199354 * SCF context will be closed, destroying all SCF objects and aborting 850911106dfSjm199354 * the transaction. 851911106dfSjm199354 */ 852911106dfSjm199354 static int 853911106dfSjm199354 vs_scf_values_set(const char *pgname, vs_prop_hd_t *prop_hd) 854911106dfSjm199354 { 855911106dfSjm199354 int rc, np; 856911106dfSjm199354 const vs_propdef_t *vpd; 857911106dfSjm199354 uint64_t propid; 858911106dfSjm199354 vs_scfctx_t vsc; 859911106dfSjm199354 860911106dfSjm199354 /* ensure that caller has authorization to refresh service */ 861911106dfSjm199354 if ((rc = vs_checkauth(VS_ACTION_AUTH)) != VS_ERR_NONE) 862911106dfSjm199354 return (rc); 863911106dfSjm199354 864911106dfSjm199354 if (vs_scf_ctx_open(&vsc) != 0) { 865911106dfSjm199354 vs_scf_ctx_close(&vsc); 866911106dfSjm199354 return (VS_ERR_SCF); 867911106dfSjm199354 } 868911106dfSjm199354 869911106dfSjm199354 if (scf_instance_get_pg(vsc.vscf_inst, pgname, vsc.vscf_pgroup) == -1) { 870911106dfSjm199354 vs_scf_ctx_close(&vsc); 871911106dfSjm199354 rc = scf_error(); 872911106dfSjm199354 if (strcmp(pgname, "VS_PGNAME_GENERAL") != 0) { 873911106dfSjm199354 if ((rc == SCF_ERROR_NOT_FOUND) || 874911106dfSjm199354 (rc == SCF_ERROR_INVALID_ARGUMENT)) 875911106dfSjm199354 return (VS_ERR_INVALID_SE); 876911106dfSjm199354 } 877911106dfSjm199354 return (VS_ERR_SCF); 878911106dfSjm199354 } 879911106dfSjm199354 880911106dfSjm199354 if (((vsc.vscf_tx = scf_transaction_create(vsc.vscf_handle)) == NULL) || 881911106dfSjm199354 (scf_transaction_start(vsc.vscf_tx, vsc.vscf_pgroup) == -1)) { 882911106dfSjm199354 vs_scf_ctx_close(&vsc); 883911106dfSjm199354 return (VS_ERR_SCF); 884911106dfSjm199354 } 885911106dfSjm199354 886911106dfSjm199354 /* Process the value change for each specified property */ 887911106dfSjm199354 rc = 0; 888911106dfSjm199354 np = 0; 889911106dfSjm199354 for (propid = 1LL; propid <= VS_PROPID_MAX; propid <<= 1) { 890911106dfSjm199354 if ((prop_hd->vp_ids & propid) == 0) 891911106dfSjm199354 continue; 892911106dfSjm199354 893911106dfSjm199354 if ((vpd = vs_get_propdef(propid)) == NULL) { 894911106dfSjm199354 rc = VS_ERR_INVALID_PROPERTY; 895911106dfSjm199354 break; 896911106dfSjm199354 } 897911106dfSjm199354 898911106dfSjm199354 vsc.vscf_val[np] = scf_value_create(vsc.vscf_handle); 899911106dfSjm199354 vsc.vscf_ent[np] = scf_entry_create(vsc.vscf_handle); 900911106dfSjm199354 901911106dfSjm199354 if (vsc.vscf_val[np] == NULL || vsc.vscf_ent[np] == NULL) { 902911106dfSjm199354 rc = VS_ERR_SCF; 903911106dfSjm199354 break; 904911106dfSjm199354 } 905911106dfSjm199354 906911106dfSjm199354 if ((rc = scf_transaction_property_change(vsc.vscf_tx, 907911106dfSjm199354 vsc.vscf_ent[np], vpd->vpd_name, vpd->vpd_type)) == -1) { 908911106dfSjm199354 rc = scf_transaction_property_new(vsc.vscf_tx, 909911106dfSjm199354 vsc.vscf_ent[np], vpd->vpd_name, vpd->vpd_type); 910911106dfSjm199354 } 911911106dfSjm199354 if (rc == -1) { 912911106dfSjm199354 rc = VS_ERR_SCF; 913911106dfSjm199354 break; 914911106dfSjm199354 } 915911106dfSjm199354 916911106dfSjm199354 if ((rc = vs_scf_set(vpd, prop_hd, &vsc, np)) != VS_ERR_NONE) 917911106dfSjm199354 break; 918911106dfSjm199354 919911106dfSjm199354 ++np; 920911106dfSjm199354 } 921911106dfSjm199354 922911106dfSjm199354 if (rc != VS_ERR_NONE) { 923911106dfSjm199354 vs_scf_ctx_close(&vsc); 924911106dfSjm199354 return (rc); 925911106dfSjm199354 } 926911106dfSjm199354 927911106dfSjm199354 /* Commit the transaction */ 928911106dfSjm199354 if (scf_transaction_commit(vsc.vscf_tx) == -1) { 929911106dfSjm199354 vs_scf_ctx_close(&vsc); 930911106dfSjm199354 return (VS_ERR_SCF); 931911106dfSjm199354 } 932911106dfSjm199354 vs_scf_ctx_close(&vsc); 933911106dfSjm199354 934911106dfSjm199354 /* Notify the daemon that things have changed */ 935911106dfSjm199354 if ((smf_refresh_instance(VS_INSTANCE_FMRI)) == -1) 936911106dfSjm199354 return (VS_ERR_SCF); 937911106dfSjm199354 938911106dfSjm199354 return (VS_ERR_NONE); 939911106dfSjm199354 } 940911106dfSjm199354 941911106dfSjm199354 942911106dfSjm199354 /* 943911106dfSjm199354 * vs_scf_set 944911106dfSjm199354 * 945911106dfSjm199354 * Stores a single value from the appropriate vscan property structure 946911106dfSjm199354 * member into the repository. 947911106dfSjm199354 * 948911106dfSjm199354 * Values are set in the SCF value object, then the value object 949911106dfSjm199354 * is added to the SCF property object. 950911106dfSjm199354 */ 951911106dfSjm199354 static int 952911106dfSjm199354 vs_scf_set(const vs_propdef_t *vpd, vs_prop_hd_t *prop_hd, 953911106dfSjm199354 vs_scfctx_t *vsc, int idx) 954911106dfSjm199354 { 955911106dfSjm199354 int rc; 956911106dfSjm199354 vs_props_t *vp = &prop_hd->vp_gen; 957911106dfSjm199354 vs_props_se_t *vep = &prop_hd->vp_se; 958911106dfSjm199354 959911106dfSjm199354 if ((rc = vs_validate(prop_hd, vpd->vpd_id)) != VS_ERR_NONE) 960911106dfSjm199354 return (rc); 961911106dfSjm199354 962911106dfSjm199354 rc = VS_ERR_NONE; 963911106dfSjm199354 switch (vpd->vpd_id) { 964911106dfSjm199354 case VS_PROPID_MAXSIZE: 965911106dfSjm199354 if ((scf_value_set_astring(vsc->vscf_val[idx], 966911106dfSjm199354 vp->vp_maxsize)) == -1) { 967911106dfSjm199354 rc = VS_ERR_SCF; 968911106dfSjm199354 } 969911106dfSjm199354 break; 970911106dfSjm199354 case VS_PROPID_MAXSIZE_ACTION: 971911106dfSjm199354 scf_value_set_boolean(vsc->vscf_val[idx], 972911106dfSjm199354 (uint8_t)vp->vp_maxsize_action); 973911106dfSjm199354 break; 974911106dfSjm199354 case VS_PROPID_TYPES: 975911106dfSjm199354 if ((scf_value_set_astring(vsc->vscf_val[idx], 976911106dfSjm199354 vp->vp_types)) == -1) { 977911106dfSjm199354 return (VS_ERR_SCF); 978911106dfSjm199354 } 979911106dfSjm199354 break; 980911106dfSjm199354 case VS_PROPID_SE_ENABLE: 981911106dfSjm199354 scf_value_set_boolean(vsc->vscf_val[idx], 982911106dfSjm199354 (uint8_t)vep->vep_enable); 983911106dfSjm199354 break; 984911106dfSjm199354 case VS_PROPID_SE_HOST: 985911106dfSjm199354 if ((scf_value_set_from_string(vsc->vscf_val[idx], 986911106dfSjm199354 vpd->vpd_type, vep->vep_host)) == -1) { 987911106dfSjm199354 rc = VS_ERR_SCF; 988911106dfSjm199354 } 989911106dfSjm199354 break; 990911106dfSjm199354 case VS_PROPID_SE_PORT: 991911106dfSjm199354 scf_value_set_integer(vsc->vscf_val[idx], vep->vep_port); 992911106dfSjm199354 break; 993911106dfSjm199354 case VS_PROPID_SE_MAXCONN: 994911106dfSjm199354 scf_value_set_integer(vsc->vscf_val[idx], 995911106dfSjm199354 vep->vep_maxconn); 996911106dfSjm199354 break; 997911106dfSjm199354 case VS_PROPID_VALUE_AUTH: 998911106dfSjm199354 if ((scf_value_set_astring(vsc->vscf_val[idx], 999911106dfSjm199354 VS_VALUE_AUTH)) == -1) { 1000911106dfSjm199354 return (VS_ERR_SCF); 1001911106dfSjm199354 } 1002911106dfSjm199354 break; 1003911106dfSjm199354 default: 1004911106dfSjm199354 break; 1005911106dfSjm199354 } 1006911106dfSjm199354 1007911106dfSjm199354 if ((scf_entry_add_value(vsc->vscf_ent[idx], 1008911106dfSjm199354 vsc->vscf_val[idx])) == -1) { 1009911106dfSjm199354 return (VS_ERR_SCF); 1010911106dfSjm199354 } 1011911106dfSjm199354 1012911106dfSjm199354 return (rc); 1013911106dfSjm199354 } 1014911106dfSjm199354 1015911106dfSjm199354 1016911106dfSjm199354 /* 1017911106dfSjm199354 * vs_scf_ctx_open 1018911106dfSjm199354 * 1019911106dfSjm199354 * Opens an SCF context; creates the minumum SCF objects 1020911106dfSjm199354 * for use in loading/storing from the SMF repository (meaning 1021911106dfSjm199354 * vscf_property group data). 1022911106dfSjm199354 * 1023911106dfSjm199354 * Other SCF objects in the context may be initialized elsewher 1024911106dfSjm199354 * subsequent to open, but all initialized structures are destroyed 1025911106dfSjm199354 * in vs_scf_ctx_close(). 1026911106dfSjm199354 */ 1027911106dfSjm199354 static int 1028911106dfSjm199354 vs_scf_ctx_open(vs_scfctx_t *vsc) 1029911106dfSjm199354 { 1030911106dfSjm199354 (void) memset(vsc, 0, sizeof (vs_scfctx_t)); 1031911106dfSjm199354 1032911106dfSjm199354 if ((vsc->vscf_handle = scf_handle_create(SCF_VERSION)) == NULL) 1033911106dfSjm199354 return (VS_ERR_SCF); 1034911106dfSjm199354 1035911106dfSjm199354 if (scf_handle_bind(vsc->vscf_handle) == -1) 1036911106dfSjm199354 return (VS_ERR_SCF); 1037911106dfSjm199354 1038911106dfSjm199354 if ((vsc->vscf_inst = scf_instance_create(vsc->vscf_handle)) == NULL) 1039911106dfSjm199354 return (VS_ERR_SCF); 1040911106dfSjm199354 1041911106dfSjm199354 if (scf_handle_decode_fmri(vsc->vscf_handle, VS_INSTANCE_FMRI, 1042911106dfSjm199354 NULL, NULL, vsc->vscf_inst, NULL, NULL, 1043911106dfSjm199354 SCF_DECODE_FMRI_EXACT) == -1) { 1044911106dfSjm199354 return (VS_ERR_SCF); 1045911106dfSjm199354 } 1046911106dfSjm199354 1047911106dfSjm199354 if ((vsc->vscf_pgroup = scf_pg_create(vsc->vscf_handle)) == NULL) 1048911106dfSjm199354 return (VS_ERR_SCF); 1049911106dfSjm199354 1050911106dfSjm199354 return (VS_ERR_NONE); 1051911106dfSjm199354 } 1052911106dfSjm199354 1053911106dfSjm199354 1054911106dfSjm199354 /* 1055911106dfSjm199354 * vs_scf_ctx_close 1056911106dfSjm199354 * 1057911106dfSjm199354 * Closes an SCF context; destroys all initialized SCF objects. 1058911106dfSjm199354 */ 1059911106dfSjm199354 static void 1060911106dfSjm199354 vs_scf_ctx_close(vs_scfctx_t *vsc) 1061911106dfSjm199354 { 1062911106dfSjm199354 int i; 1063911106dfSjm199354 1064911106dfSjm199354 for (i = 0; i < VS_NUM_PROPIDS; i++) { 1065911106dfSjm199354 if (vsc->vscf_val[i]) 1066911106dfSjm199354 scf_value_destroy(vsc->vscf_val[i]); 1067911106dfSjm199354 if (vsc->vscf_ent[i]) 1068911106dfSjm199354 scf_entry_destroy(vsc->vscf_ent[i]); 1069911106dfSjm199354 if (vsc->vscf_prop[i]) 1070911106dfSjm199354 scf_property_destroy(vsc->vscf_prop[i]); 1071911106dfSjm199354 } 1072911106dfSjm199354 1073911106dfSjm199354 if (vsc->vscf_iter) 1074911106dfSjm199354 scf_iter_destroy(vsc->vscf_iter); 1075911106dfSjm199354 if (vsc->vscf_tx) 1076911106dfSjm199354 scf_transaction_destroy(vsc->vscf_tx); 1077911106dfSjm199354 if (vsc->vscf_pgroup) 1078911106dfSjm199354 scf_pg_destroy(vsc->vscf_pgroup); 1079911106dfSjm199354 if (vsc->vscf_inst) 1080911106dfSjm199354 scf_instance_destroy(vsc->vscf_inst); 1081911106dfSjm199354 if (vsc->vscf_handle) 1082911106dfSjm199354 scf_handle_destroy(vsc->vscf_handle); 1083911106dfSjm199354 } 1084911106dfSjm199354 1085911106dfSjm199354 1086911106dfSjm199354 /* 1087911106dfSjm199354 * vs_validate 1088911106dfSjm199354 * 1089911106dfSjm199354 * Validate property identified in propid. 1090911106dfSjm199354 * 1091911106dfSjm199354 * Returns: VS_ERR_NONE 1092911106dfSjm199354 * VS_ERR_INVALID_VALUE 1093911106dfSjm199354 * VS_ERR_INVALID_PROPERTY 1094911106dfSjm199354 */ 1095911106dfSjm199354 static int 1096911106dfSjm199354 vs_validate(const vs_prop_hd_t *prop_hd, uint64_t propid) 1097911106dfSjm199354 { 1098911106dfSjm199354 uint64_t num; 1099911106dfSjm199354 const vs_props_t *vp = &prop_hd->vp_gen; 1100911106dfSjm199354 const vs_props_se_t *vep = &prop_hd->vp_se; 1101911106dfSjm199354 1102911106dfSjm199354 switch (propid) { 1103911106dfSjm199354 case VS_PROPID_MAXSIZE: 1104911106dfSjm199354 if ((vs_strtonum(vp->vp_maxsize, &num) != 0) || (num == 0)) 1105911106dfSjm199354 return (VS_ERR_INVALID_VALUE); 1106911106dfSjm199354 break; 1107911106dfSjm199354 case VS_PROPID_MAXSIZE_ACTION: 1108911106dfSjm199354 break; 1109911106dfSjm199354 case VS_PROPID_TYPES: 1110911106dfSjm199354 if (!vs_is_valid_types(vp->vp_types)) 1111911106dfSjm199354 return (VS_ERR_INVALID_VALUE); 1112911106dfSjm199354 break; 1113911106dfSjm199354 case VS_PROPID_SE_ENABLE: 1114911106dfSjm199354 break; 1115911106dfSjm199354 case VS_PROPID_SE_PORT: 1116911106dfSjm199354 if (vep->vep_port == 0) 1117911106dfSjm199354 return (VS_ERR_INVALID_VALUE); 1118911106dfSjm199354 break; 1119911106dfSjm199354 case VS_PROPID_SE_HOST: 1120911106dfSjm199354 if (!vs_is_valid_host(vep->vep_host)) 1121911106dfSjm199354 return (VS_ERR_INVALID_VALUE); 1122911106dfSjm199354 break; 1123911106dfSjm199354 case VS_PROPID_SE_MAXCONN: 1124911106dfSjm199354 if (vep->vep_maxconn < VS_VAL_SE_MAXCONN_MIN || 1125911106dfSjm199354 vep->vep_maxconn > VS_VAL_SE_MAXCONN_MAX) 1126911106dfSjm199354 return (VS_ERR_INVALID_VALUE); 1127911106dfSjm199354 break; 1128911106dfSjm199354 case VS_PROPID_VALUE_AUTH: 1129911106dfSjm199354 case VS_PROPID_VLOG: 1130911106dfSjm199354 break; 1131911106dfSjm199354 default: 1132911106dfSjm199354 return (VS_ERR_INVALID_PROPERTY); 1133911106dfSjm199354 } 1134911106dfSjm199354 1135911106dfSjm199354 return (VS_ERR_NONE); 1136911106dfSjm199354 } 1137911106dfSjm199354 1138911106dfSjm199354 1139911106dfSjm199354 /* 1140911106dfSjm199354 * vs_props_validate 1141911106dfSjm199354 * 1142911106dfSjm199354 * Validate properties identified in propids. 1143911106dfSjm199354 * 1144911106dfSjm199354 * Returns: VS_ERR_NONE 1145911106dfSjm199354 * VS_ERR_INVALID_VALUE 1146911106dfSjm199354 * VS_ERR_INVALID_PROPERTY 1147911106dfSjm199354 */ 1148911106dfSjm199354 int 1149911106dfSjm199354 vs_props_validate(const vs_props_t *props, uint64_t propids) 1150911106dfSjm199354 { 1151911106dfSjm199354 uint64_t propid; 1152911106dfSjm199354 vs_prop_hd_t prop_hd; 1153911106dfSjm199354 1154911106dfSjm199354 if ((propids & VS_PROPID_GEN_ALL) != propids) 1155911106dfSjm199354 return (VS_ERR_INVALID_PROPERTY); 1156911106dfSjm199354 1157911106dfSjm199354 (void) memset(&prop_hd, 0, sizeof (vs_prop_hd_t)); 1158911106dfSjm199354 prop_hd.vp_gen = *props; 1159911106dfSjm199354 prop_hd.vp_type = VS_PTYPE_GEN; 1160911106dfSjm199354 prop_hd.vp_ids = propids; 1161911106dfSjm199354 prop_hd.vp_all = VS_PROPID_GEN_ALL; 1162911106dfSjm199354 1163911106dfSjm199354 for (propid = 1LL; propid <= VS_PROPID_MAX; propid <<= 1) { 1164911106dfSjm199354 if ((propids & propid) == 0) 1165911106dfSjm199354 continue; 1166911106dfSjm199354 1167911106dfSjm199354 if (vs_validate(&prop_hd, propid) != VS_ERR_NONE) 1168911106dfSjm199354 return (VS_ERR_INVALID_VALUE); 1169911106dfSjm199354 } 1170911106dfSjm199354 1171911106dfSjm199354 return (VS_ERR_NONE); 1172911106dfSjm199354 } 1173911106dfSjm199354 1174911106dfSjm199354 1175911106dfSjm199354 /* 1176911106dfSjm199354 * vs_props_se_validate 1177911106dfSjm199354 * 1178911106dfSjm199354 * Validate properties identified in propids. 1179911106dfSjm199354 * 1180911106dfSjm199354 * Returns: VS_ERR_NONE 1181911106dfSjm199354 * VS_ERR_INVALID_VALUE 1182911106dfSjm199354 * VS_ERR_INVALID_PROPERTY 1183911106dfSjm199354 */ 1184911106dfSjm199354 int 1185911106dfSjm199354 vs_props_se_validate(const vs_props_se_t *se_props, uint64_t propids) 1186911106dfSjm199354 { 1187911106dfSjm199354 uint64_t propid; 1188911106dfSjm199354 vs_prop_hd_t prop_hd; 1189911106dfSjm199354 1190911106dfSjm199354 if ((propids & VS_PROPID_SE_ALL) != propids) 1191911106dfSjm199354 return (VS_ERR_INVALID_PROPERTY); 1192911106dfSjm199354 1193911106dfSjm199354 (void) memset(&prop_hd, 0, sizeof (vs_prop_hd_t)); 1194911106dfSjm199354 prop_hd.vp_se = *se_props; 1195911106dfSjm199354 prop_hd.vp_type = VS_PTYPE_SE; 1196911106dfSjm199354 prop_hd.vp_ids = propids; 1197911106dfSjm199354 prop_hd.vp_all = VS_PROPID_SE_ALL; 1198911106dfSjm199354 1199911106dfSjm199354 for (propid = 1LL; propid <= VS_PROPID_MAX; propid <<= 1) { 1200911106dfSjm199354 if ((propids & propid) == 0) 1201911106dfSjm199354 continue; 1202911106dfSjm199354 1203911106dfSjm199354 if (vs_validate(&prop_hd, propid) != VS_ERR_NONE) 1204911106dfSjm199354 return (VS_ERR_INVALID_VALUE); 1205911106dfSjm199354 } 1206911106dfSjm199354 1207911106dfSjm199354 return (VS_ERR_NONE); 1208911106dfSjm199354 } 1209911106dfSjm199354 1210911106dfSjm199354 1211911106dfSjm199354 /* 1212911106dfSjm199354 * vs_is_valid_types 1213911106dfSjm199354 * 1214911106dfSjm199354 * Checks that types property is a valid format: 1215911106dfSjm199354 * - doesn't exceed VS_VAL_TYPES_MAX 1216911106dfSjm199354 * - doesn't contain VS_VAL_TYPES_INVALID_CHARS 1217911106dfSjm199354 * - is correctly formatted - passes the parsing tests 1218911106dfSjm199354 * 1219911106dfSjm199354 * Returns 1 on success, 0 on failure 1220911106dfSjm199354 */ 1221911106dfSjm199354 static int 1222911106dfSjm199354 vs_is_valid_types(const char *types) 1223911106dfSjm199354 { 1224911106dfSjm199354 char buf[VS_VAL_TYPES_LEN]; 1225911106dfSjm199354 uint32_t len = VS_VAL_TYPES_LEN; 1226911106dfSjm199354 1227911106dfSjm199354 if (strlen(types) > VS_VAL_TYPES_LEN) 1228911106dfSjm199354 return (0); 1229911106dfSjm199354 1230911106dfSjm199354 if (strpbrk(types, VS_VAL_TYPES_INVALID_CHARS) != NULL) 1231911106dfSjm199354 return (0); 1232911106dfSjm199354 1233911106dfSjm199354 if (vs_parse_types(types, buf, &len) != 0) 1234911106dfSjm199354 return (0); 1235911106dfSjm199354 1236911106dfSjm199354 return (1); 1237911106dfSjm199354 } 1238911106dfSjm199354 1239911106dfSjm199354 1240911106dfSjm199354 /* 1241911106dfSjm199354 * vs_is_valid_host 1242911106dfSjm199354 * 1243911106dfSjm199354 * Returns 1 on success, 0 on failure 1244911106dfSjm199354 */ 1245911106dfSjm199354 static int 1246911106dfSjm199354 vs_is_valid_host(const char *host) 1247911106dfSjm199354 { 1248911106dfSjm199354 long naddr; 1249911106dfSjm199354 const char *p; 1250911106dfSjm199354 1251911106dfSjm199354 if (!host || *host == '\0') 1252911106dfSjm199354 return (0); 1253911106dfSjm199354 1254911106dfSjm199354 if ('0' <= host[0] && host[0] <= '9') { 1255911106dfSjm199354 /* ip address */ 1256911106dfSjm199354 if ((inet_pton(AF_INET, host, &naddr)) == 0) 1257911106dfSjm199354 return (0); 1258911106dfSjm199354 if ((naddr & IN_CLASSA_NET) == 0) 1259911106dfSjm199354 return (0); 1260911106dfSjm199354 if ((naddr & IN_CLASSC_HOST) == 0) 1261911106dfSjm199354 return (0); 1262911106dfSjm199354 } else { 1263911106dfSjm199354 /* hostname */ 1264911106dfSjm199354 p = host; 1265911106dfSjm199354 while (*p != '\0') { 1266911106dfSjm199354 if (!isascii(*p)) 1267911106dfSjm199354 return (0); 1268911106dfSjm199354 1269911106dfSjm199354 if (isalnum(*p) || 1270911106dfSjm199354 (*p == '.') || (*p == '-') || (*p == '_')) { 1271911106dfSjm199354 ++p; 1272911106dfSjm199354 } else { 1273911106dfSjm199354 return (0); 1274911106dfSjm199354 } 1275911106dfSjm199354 } 1276911106dfSjm199354 } 1277911106dfSjm199354 1278911106dfSjm199354 return (1); 1279911106dfSjm199354 } 1280911106dfSjm199354 1281911106dfSjm199354 1282911106dfSjm199354 /* 1283911106dfSjm199354 * vs_parse_types 1284911106dfSjm199354 * 1285911106dfSjm199354 * Replace comma separators with '\0'. 1286911106dfSjm199354 * 1287911106dfSjm199354 * Types contains comma separated rules each beginning with +|- 1288911106dfSjm199354 * - embedded commas are escaped by backslash 1289911106dfSjm199354 * - backslash is escaped by backslash 1290911106dfSjm199354 * - a single backslash not followed by comma is illegal 1291911106dfSjm199354 * 1292911106dfSjm199354 * On entry to the function len must contain the length of 1293911106dfSjm199354 * the buffer. On sucecssful exit len will contain the length 1294911106dfSjm199354 * of the parsed data within the buffer. 1295911106dfSjm199354 * 1296911106dfSjm199354 * Returns 0 on success, -1 on failure 1297911106dfSjm199354 */ 1298911106dfSjm199354 int 1299911106dfSjm199354 vs_parse_types(const char *types, char *buf, uint32_t *len) 1300911106dfSjm199354 { 1301911106dfSjm199354 char *p = (char *)types; 1302911106dfSjm199354 char *b = buf; 1303911106dfSjm199354 1304911106dfSjm199354 if (strlen(types) > *len) 1305911106dfSjm199354 return (-1); 1306911106dfSjm199354 1307911106dfSjm199354 if (strchr(VS_TYPES_RULES, *p) == NULL) 1308911106dfSjm199354 return (-1); 1309911106dfSjm199354 1310911106dfSjm199354 (void) memset(buf, 0, *len); 1311911106dfSjm199354 1312911106dfSjm199354 while (*p) { 1313911106dfSjm199354 switch (*p) { 1314911106dfSjm199354 case VS_TYPES_SEP: 1315911106dfSjm199354 if (*(p + 1) && 1316911106dfSjm199354 (strchr(VS_TYPES_RULES, *(p + 1))) == NULL) 1317911106dfSjm199354 return (-1); 1318911106dfSjm199354 *b = '\0'; 1319911106dfSjm199354 break; 1320911106dfSjm199354 case VS_TYPES_ESCAPE: 1321911106dfSjm199354 ++p; 1322911106dfSjm199354 if (*p == VS_TYPES_ESCAPE || *p == VS_TYPES_SEP) 1323911106dfSjm199354 *b = *p; 1324911106dfSjm199354 else 1325911106dfSjm199354 return (-1); 1326911106dfSjm199354 break; 1327911106dfSjm199354 default: 1328911106dfSjm199354 *b = *p; 1329911106dfSjm199354 } 1330911106dfSjm199354 ++p; 1331911106dfSjm199354 ++b; 1332911106dfSjm199354 } 1333911106dfSjm199354 1334911106dfSjm199354 *len = (b - buf) + 1; 1335911106dfSjm199354 1336911106dfSjm199354 return (0); 1337911106dfSjm199354 } 1338911106dfSjm199354 1339911106dfSjm199354 1340911106dfSjm199354 /* 1341911106dfSjm199354 * vs_statistics 1342911106dfSjm199354 */ 1343911106dfSjm199354 int 1344911106dfSjm199354 vs_statistics(vs_stats_t *stats) 1345911106dfSjm199354 { 1346911106dfSjm199354 int door_fd, rc = VS_ERR_NONE; 1347911106dfSjm199354 vs_stats_req_t *req; 1348bfc848c6Sjm199354 vs_stats_rsp_t *rsp; 1349911106dfSjm199354 door_arg_t arg; 1350911106dfSjm199354 1351911106dfSjm199354 if ((req = calloc(1, sizeof (vs_stats_req_t))) == NULL) 1352911106dfSjm199354 return (VS_ERR_SYS); 1353911106dfSjm199354 1354bfc848c6Sjm199354 if ((rsp = calloc(1, sizeof (vs_stats_rsp_t))) == NULL) { 1355911106dfSjm199354 free(req); 1356911106dfSjm199354 return (VS_ERR_SYS); 1357911106dfSjm199354 } 1358911106dfSjm199354 1359911106dfSjm199354 if ((door_fd = open(VS_STATS_DOOR_NAME, O_RDONLY)) < 0) { 1360911106dfSjm199354 free(req); 1361bfc848c6Sjm199354 free(rsp); 1362911106dfSjm199354 return (VS_ERR_DAEMON_COMM); 1363911106dfSjm199354 } 1364911106dfSjm199354 1365bfc848c6Sjm199354 req->vsr_magic = VS_STATS_DOOR_MAGIC; 1366bfc848c6Sjm199354 req->vsr_id = VS_STATS_GET; 1367911106dfSjm199354 1368911106dfSjm199354 arg.data_ptr = (char *)req; 1369911106dfSjm199354 arg.data_size = sizeof (vs_stats_req_t); 1370911106dfSjm199354 arg.desc_ptr = NULL; 1371911106dfSjm199354 arg.desc_num = 0; 1372bfc848c6Sjm199354 arg.rbuf = (char *)rsp; 1373bfc848c6Sjm199354 arg.rsize = sizeof (vs_stats_rsp_t); 1374911106dfSjm199354 13751843d056SAlan Wright rc = vs_door_call(door_fd, &arg); 13761843d056SAlan Wright 13771843d056SAlan Wright if ((rc == VS_ERR_NONE) && (rsp->vsr_magic == VS_STATS_DOOR_MAGIC)) 1378bfc848c6Sjm199354 *stats = rsp->vsr_stats; 13791843d056SAlan Wright else 13801843d056SAlan Wright rc = VS_ERR_DAEMON_COMM; 1381911106dfSjm199354 1382911106dfSjm199354 (void) close(door_fd); 1383911106dfSjm199354 1384911106dfSjm199354 free(req); 1385bfc848c6Sjm199354 free(rsp); 1386911106dfSjm199354 return (rc); 1387911106dfSjm199354 } 1388911106dfSjm199354 1389911106dfSjm199354 1390911106dfSjm199354 /* 1391911106dfSjm199354 * vs_statistics_reset 1392911106dfSjm199354 */ 1393911106dfSjm199354 int 1394911106dfSjm199354 vs_statistics_reset() 1395911106dfSjm199354 { 1396911106dfSjm199354 int door_fd, rc; 1397911106dfSjm199354 vs_stats_req_t *req; 1398911106dfSjm199354 door_arg_t arg; 1399911106dfSjm199354 1400911106dfSjm199354 /* ensure that caller has authorization to reset stats */ 1401911106dfSjm199354 if ((rc = vs_checkauth(VS_VALUE_AUTH)) != VS_ERR_NONE) 1402911106dfSjm199354 return (rc); 1403911106dfSjm199354 1404911106dfSjm199354 if ((req = calloc(1, sizeof (vs_stats_req_t))) == NULL) 1405911106dfSjm199354 return (VS_ERR_SYS); 1406911106dfSjm199354 1407911106dfSjm199354 if ((door_fd = open(VS_STATS_DOOR_NAME, O_RDONLY)) < 0) { 1408911106dfSjm199354 free(req); 1409911106dfSjm199354 return (VS_ERR_DAEMON_COMM); 1410911106dfSjm199354 } 1411911106dfSjm199354 1412bfc848c6Sjm199354 req->vsr_magic = VS_STATS_DOOR_MAGIC; 1413bfc848c6Sjm199354 req->vsr_id = VS_STATS_RESET; 1414911106dfSjm199354 1415911106dfSjm199354 arg.data_ptr = (char *)req; 1416911106dfSjm199354 arg.data_size = sizeof (vs_stats_req_t); 1417911106dfSjm199354 arg.desc_ptr = NULL; 1418911106dfSjm199354 arg.desc_num = 0; 1419911106dfSjm199354 arg.rbuf = NULL; 1420911106dfSjm199354 arg.rsize = 0; 1421911106dfSjm199354 14221843d056SAlan Wright rc = vs_door_call(door_fd, &arg); 1423911106dfSjm199354 1424911106dfSjm199354 (void) close(door_fd); 1425911106dfSjm199354 free(req); 1426911106dfSjm199354 return (rc); 1427911106dfSjm199354 } 1428911106dfSjm199354 14291843d056SAlan Wright /* 14301843d056SAlan Wright * Door call with retries. 14311843d056SAlan Wright * 14321843d056SAlan Wright * Returns VS_ERR_NONE on success, otherwise VS_ERR_DAEMON_COMM. 14331843d056SAlan Wright */ 14341843d056SAlan Wright static int 14351843d056SAlan Wright vs_door_call(int fd, door_arg_t *arg) 14361843d056SAlan Wright { 14371843d056SAlan Wright int rc = -1; 14381843d056SAlan Wright int i; 14391843d056SAlan Wright 14401843d056SAlan Wright for (i = 0; i < VS_DOOR_CALL_RETRIES; ++i) { 14411843d056SAlan Wright errno = 0; 14421843d056SAlan Wright 14431843d056SAlan Wright if ((rc = door_call(fd, arg)) == 0) 14441843d056SAlan Wright break; 14451843d056SAlan Wright 14461843d056SAlan Wright if (errno != EAGAIN && errno != EINTR) 14471843d056SAlan Wright break; 14481843d056SAlan Wright } 14491843d056SAlan Wright 14501843d056SAlan Wright return ((rc == 0) ? VS_ERR_NONE : VS_ERR_DAEMON_COMM); 14511843d056SAlan Wright } 1452911106dfSjm199354 1453911106dfSjm199354 /* 1454911106dfSjm199354 * vs_checkauth 1455911106dfSjm199354 */ 1456911106dfSjm199354 static int 1457911106dfSjm199354 vs_checkauth(char *auth) 1458911106dfSjm199354 { 1459911106dfSjm199354 struct passwd *pw; 1460911106dfSjm199354 uid_t uid; 1461911106dfSjm199354 1462911106dfSjm199354 uid = getuid(); 1463911106dfSjm199354 1464911106dfSjm199354 if ((pw = getpwuid(uid)) == NULL) 1465911106dfSjm199354 return (VS_ERR_SYS); 1466911106dfSjm199354 1467911106dfSjm199354 if (chkauthattr(auth, pw->pw_name) != 1) { 1468911106dfSjm199354 return (VS_ERR_AUTH); 1469911106dfSjm199354 } 1470911106dfSjm199354 1471911106dfSjm199354 return (VS_ERR_NONE); 1472911106dfSjm199354 } 1473911106dfSjm199354 1474911106dfSjm199354 1475911106dfSjm199354 /* 1476911106dfSjm199354 * vs_props_get_engines 1477bfc848c6Sjm199354 * 1478911106dfSjm199354 * On input, count specifies the maximum number of engine ids to 1479911106dfSjm199354 * return. engids must be an array with count entries. 1480911106dfSjm199354 * On return, count specifies the number of engine ids being 1481911106dfSjm199354 * returned in engids. 1482bfc848c6Sjm199354 * 1483bfc848c6Sjm199354 * Caller is responsible for free'ing the engids allocated herein. 1484911106dfSjm199354 */ 1485911106dfSjm199354 static int 1486bfc848c6Sjm199354 vs_props_get_engines(char *engids[], int *count) 1487911106dfSjm199354 { 1488bfc848c6Sjm199354 int i, prefix_len; 1489bfc848c6Sjm199354 char pgname[VS_PGNAME_ENGINE_LEN]; 1490911106dfSjm199354 vs_scfctx_t vsc; 1491911106dfSjm199354 1492911106dfSjm199354 1493911106dfSjm199354 if (((vs_scf_ctx_open(&vsc)) != 0) || 1494911106dfSjm199354 ((vsc.vscf_iter = scf_iter_create(vsc.vscf_handle)) == NULL) || 1495911106dfSjm199354 (scf_iter_instance_pgs_typed(vsc.vscf_iter, vsc.vscf_inst, 1496911106dfSjm199354 SCF_GROUP_APPLICATION) != 0)) { 1497911106dfSjm199354 vs_scf_ctx_close(&vsc); 1498911106dfSjm199354 return (VS_ERR_SCF); 1499911106dfSjm199354 } 1500911106dfSjm199354 1501bfc848c6Sjm199354 for (i = 0; i < *count; i++) 1502bfc848c6Sjm199354 engids[i] = NULL; 1503bfc848c6Sjm199354 1504bfc848c6Sjm199354 i = 0; 1505bfc848c6Sjm199354 prefix_len = sizeof (VS_PGNAME_ENGINE_PREFIX) - 1; 1506bfc848c6Sjm199354 1507911106dfSjm199354 while ((i < VS_SE_MAX) && 1508911106dfSjm199354 (scf_iter_next_pg(vsc.vscf_iter, vsc.vscf_pgroup) == 1)) { 1509bfc848c6Sjm199354 if (scf_pg_get_name(vsc.vscf_pgroup, pgname, 1510bfc848c6Sjm199354 VS_PGNAME_ENGINE_LEN) < 0) { 1511911106dfSjm199354 vs_scf_ctx_close(&vsc); 1512911106dfSjm199354 return (VS_ERR_SCF); 1513911106dfSjm199354 } 1514911106dfSjm199354 1515bfc848c6Sjm199354 if (strncmp(pgname, VS_PGNAME_ENGINE_PREFIX, prefix_len) == 0) { 1516bfc848c6Sjm199354 if ((engids[i] = strdup(pgname + prefix_len)) != NULL) { 1517911106dfSjm199354 if (++i == *count) 1518911106dfSjm199354 break; 1519911106dfSjm199354 } 1520bfc848c6Sjm199354 } 1521bfc848c6Sjm199354 } 1522911106dfSjm199354 vs_scf_ctx_close(&vsc); 1523911106dfSjm199354 1524911106dfSjm199354 *count = i; 1525911106dfSjm199354 return (VS_ERR_NONE); 1526911106dfSjm199354 } 1527911106dfSjm199354 1528911106dfSjm199354 1529911106dfSjm199354 /* 1530911106dfSjm199354 * vs_scf_pg_count 1531911106dfSjm199354 */ 1532911106dfSjm199354 static int 1533911106dfSjm199354 vs_scf_pg_count(void) 1534911106dfSjm199354 { 1535911106dfSjm199354 int count = 0; 1536911106dfSjm199354 vs_scfctx_t vsc; 1537911106dfSjm199354 1538911106dfSjm199354 if ((vs_scf_ctx_open(&vsc) != 0) || 1539911106dfSjm199354 ((vsc.vscf_iter = scf_iter_create(vsc.vscf_handle)) == NULL) || 1540911106dfSjm199354 (scf_iter_instance_pgs_typed(vsc.vscf_iter, vsc.vscf_inst, 1541911106dfSjm199354 SCF_GROUP_APPLICATION) != 0)) { 1542911106dfSjm199354 vs_scf_ctx_close(&vsc); 1543911106dfSjm199354 return (-1); 1544911106dfSjm199354 } 1545911106dfSjm199354 1546911106dfSjm199354 while (scf_iter_next_pg(vsc.vscf_iter, vsc.vscf_pgroup) == 1) 1547911106dfSjm199354 ++count; 1548911106dfSjm199354 1549911106dfSjm199354 vs_scf_ctx_close(&vsc); 1550911106dfSjm199354 1551911106dfSjm199354 return (count); 1552911106dfSjm199354 } 1553911106dfSjm199354 1554911106dfSjm199354 1555911106dfSjm199354 /* 1556bfc848c6Sjm199354 * vs_engid_to_pgname 1557bfc848c6Sjm199354 * 1558bfc848c6Sjm199354 * To convert an engine id (engid) to a property group name (pgname), 1559bfc848c6Sjm199354 * the engine id is prefixed with VS_PGNAME_ENGINE_PREFIX. 1560bfc848c6Sjm199354 */ 1561bfc848c6Sjm199354 static void 1562bfc848c6Sjm199354 vs_engid_to_pgname(const char *engid, char pgname[VS_PGNAME_ENGINE_LEN]) 1563bfc848c6Sjm199354 { 1564bfc848c6Sjm199354 (void) snprintf(pgname, VS_PGNAME_ENGINE_LEN, "%s%s", 1565bfc848c6Sjm199354 VS_PGNAME_ENGINE_PREFIX, engid); 1566bfc848c6Sjm199354 } 1567bfc848c6Sjm199354 1568bfc848c6Sjm199354 1569bfc848c6Sjm199354 /* 1570911106dfSjm199354 * vs_strtonum 1571911106dfSjm199354 * 1572911106dfSjm199354 * Converts a size string in the format into an integer. 1573911106dfSjm199354 * 1574911106dfSjm199354 * A size string is a numeric value followed by an optional unit 1575911106dfSjm199354 * specifier which is used as a multiplier to calculate a raw 1576911106dfSjm199354 * number. 1577911106dfSjm199354 * The size string format is: N[.N][KMGTP][B] 1578911106dfSjm199354 * 1579911106dfSjm199354 * The numeric value can contain a decimal portion. Unit specifiers 1580911106dfSjm199354 * are either a one-character or two-character string; i.e. "K" or 1581911106dfSjm199354 * "KB" for kilobytes. Unit specifiers must follow the numeric portion 1582911106dfSjm199354 * immediately, and are not case-sensitive. 1583911106dfSjm199354 * 1584911106dfSjm199354 * If either "B" is specified, or there is no unit specifier portion 1585911106dfSjm199354 * in the string, the numeric value is calculated with no multiplier 1586911106dfSjm199354 * (assumes a basic unit of "bytes"). 1587911106dfSjm199354 * 1588911106dfSjm199354 * Returns: 1589911106dfSjm199354 * -1: Failure; errno set to specify the error. 1590911106dfSjm199354 * 0: Success. 1591911106dfSjm199354 */ 1592911106dfSjm199354 int 1593911106dfSjm199354 vs_strtonum(const char *value, uint64_t *num) 1594911106dfSjm199354 { 1595911106dfSjm199354 char *end; 1596911106dfSjm199354 int shift; 1597911106dfSjm199354 double fval; 1598911106dfSjm199354 1599911106dfSjm199354 *num = 0; 1600911106dfSjm199354 1601911106dfSjm199354 /* Check to see if this looks like a number. */ 1602911106dfSjm199354 if ((value[0] < '0' || value[0] > '9') && value[0] != '.') { 1603911106dfSjm199354 errno = EINVAL; 1604911106dfSjm199354 return (-1); 1605911106dfSjm199354 } 1606911106dfSjm199354 1607911106dfSjm199354 /* Rely on stroll() to process the numeric portion. */ 1608911106dfSjm199354 errno = 0; 1609911106dfSjm199354 *num = strtoll(value, &end, 10); 1610911106dfSjm199354 1611911106dfSjm199354 /* 1612911106dfSjm199354 * Check for ERANGE, which indicates that the value is too large to 1613911106dfSjm199354 * fit in a 64-bit value. 1614911106dfSjm199354 */ 1615911106dfSjm199354 if (errno != 0) 1616911106dfSjm199354 return (-1); 1617911106dfSjm199354 1618911106dfSjm199354 /* 1619911106dfSjm199354 * If we have a decimal value, then do the computation with floating 1620911106dfSjm199354 * point arithmetic. Otherwise, use standard arithmetic. 1621911106dfSjm199354 */ 1622911106dfSjm199354 if (*end == '.') { 1623911106dfSjm199354 fval = strtod(value, &end); 1624911106dfSjm199354 1625911106dfSjm199354 if ((shift = vs_strtoshift(end)) == -1) 1626911106dfSjm199354 return (-1); /* errno set */ 1627911106dfSjm199354 1628911106dfSjm199354 fval *= pow(2, shift); 1629911106dfSjm199354 if (fval > UINT64_MAX) { 1630911106dfSjm199354 errno = ERANGE; 1631911106dfSjm199354 return (-1); 1632911106dfSjm199354 } 1633911106dfSjm199354 1634911106dfSjm199354 *num = (uint64_t)fval; 1635911106dfSjm199354 } else { 1636911106dfSjm199354 if ((shift = vs_strtoshift(end)) == -1) 1637911106dfSjm199354 return (-1); /* errno set */ 1638911106dfSjm199354 1639911106dfSjm199354 /* Check for overflow */ 1640911106dfSjm199354 if (shift >= 64 || (*num << shift) >> shift != *num) { 1641911106dfSjm199354 errno = ERANGE; 1642911106dfSjm199354 return (-1); 1643911106dfSjm199354 } 1644911106dfSjm199354 1645911106dfSjm199354 *num <<= shift; 1646911106dfSjm199354 } 1647911106dfSjm199354 1648911106dfSjm199354 return (0); 1649911106dfSjm199354 } 1650911106dfSjm199354 1651911106dfSjm199354 1652911106dfSjm199354 /* 1653911106dfSjm199354 * vs_strtoshift 1654911106dfSjm199354 * 1655911106dfSjm199354 * Converts a unit specifier string into a number of bits that 1656911106dfSjm199354 * a numeric value must be shifted. 1657911106dfSjm199354 * 1658911106dfSjm199354 * Returns: 1659911106dfSjm199354 * -1: Failure; errno set to specify the error. 1660911106dfSjm199354 * >-1: Success; the shift count. 1661911106dfSjm199354 * 1662911106dfSjm199354 */ 1663911106dfSjm199354 static int 1664911106dfSjm199354 vs_strtoshift(const char *buf) 1665911106dfSjm199354 { 1666911106dfSjm199354 const char *ends = "BKMGTPEZ"; 1667911106dfSjm199354 int i; 1668911106dfSjm199354 1669911106dfSjm199354 if (buf[0] == '\0') 1670911106dfSjm199354 return (0); 1671911106dfSjm199354 for (i = 0; i < strlen(ends); i++) { 1672911106dfSjm199354 if (toupper(buf[0]) == ends[i]) 1673911106dfSjm199354 break; 1674911106dfSjm199354 } 1675911106dfSjm199354 if (i == strlen(ends)) { 1676911106dfSjm199354 errno = EINVAL; 1677911106dfSjm199354 return (-1); 1678911106dfSjm199354 } 1679911106dfSjm199354 1680911106dfSjm199354 /* Allow trailing 'b' characters except in the case of 'BB'. */ 1681911106dfSjm199354 if (buf[1] == '\0' || (toupper(buf[1]) == 'B' && buf[2] == '\0' && 1682911106dfSjm199354 toupper(buf[0]) != 'B')) { 1683911106dfSjm199354 return (10 * i); 1684911106dfSjm199354 } 1685911106dfSjm199354 1686911106dfSjm199354 errno = EINVAL; 1687911106dfSjm199354 return (-1); 1688911106dfSjm199354 } 1689