15440Sjm199354 /* 25440Sjm199354 * CDDL HEADER START 35440Sjm199354 * 45440Sjm199354 * The contents of this file are subject to the terms of the 55440Sjm199354 * Common Development and Distribution License (the "License"). 65440Sjm199354 * You may not use this file except in compliance with the License. 75440Sjm199354 * 85440Sjm199354 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 95440Sjm199354 * or http://www.opensolaris.org/os/licensing. 105440Sjm199354 * See the License for the specific language governing permissions 115440Sjm199354 * and limitations under the License. 125440Sjm199354 * 135440Sjm199354 * When distributing Covered Code, include this CDDL HEADER in each 145440Sjm199354 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 155440Sjm199354 * If applicable, add the following below this CDDL HEADER, with the 165440Sjm199354 * fields enclosed by brackets "[]" replaced with your own identifying 175440Sjm199354 * information: Portions Copyright [yyyy] [name of copyright owner] 185440Sjm199354 * 195440Sjm199354 * CDDL HEADER END 205440Sjm199354 */ 215440Sjm199354 /* 22*6407Sjm199354 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 235440Sjm199354 * Use is subject to license terms. 245440Sjm199354 */ 255440Sjm199354 265440Sjm199354 #pragma ident "%Z%%M% %I% %E% SMI" 275440Sjm199354 285440Sjm199354 #include <string.h> 295440Sjm199354 #include <stdio.h> 305440Sjm199354 #include <stdlib.h> 315440Sjm199354 #include <unistd.h> 325440Sjm199354 #include <ctype.h> 335440Sjm199354 #include <math.h> 345440Sjm199354 #include <limits.h> 355440Sjm199354 #include <libscf.h> 365440Sjm199354 #include <errno.h> 375440Sjm199354 #include <fcntl.h> 385440Sjm199354 #include <door.h> 395440Sjm199354 #include <pwd.h> 405440Sjm199354 #include <auth_attr.h> 415440Sjm199354 #include <secdb.h> 425440Sjm199354 #include <sys/socket.h> 435440Sjm199354 #include <arpa/inet.h> 445440Sjm199354 #include <libintl.h> 455440Sjm199354 #include <libvscan.h> 465440Sjm199354 475440Sjm199354 #define VS_INSTANCE_FMRI "svc:/system/filesystem/vscan:icap" 485440Sjm199354 495440Sjm199354 /* SMF property group and property names */ 505440Sjm199354 #define VS_PGNAME_GENERAL "vs_general" 51*6407Sjm199354 #define VS_PGNAME_ENGINE_PREFIX "vs_engine_" 52*6407Sjm199354 #define VS_PGNAME_ENGINE_LEN VS_SE_NAME_LEN + 16 535440Sjm199354 545440Sjm199354 #define VS_PNAME_MAXSIZE "maxsize" 555440Sjm199354 #define VS_PNAME_MAXSIZE_ACTION "maxsize_action" 565440Sjm199354 #define VS_PNAME_TYPES "types" 575440Sjm199354 #define VS_PNAME_VLOG "viruslog" 585440Sjm199354 595440Sjm199354 #define VS_PNAME_SE_ENABLE "enable" 605440Sjm199354 #define VS_PNAME_SE_HOST "host" 615440Sjm199354 #define VS_PNAME_SE_PORT "port" 625440Sjm199354 #define VS_PNAME_SE_MAXCONN "max_connect" 635440Sjm199354 #define VS_PNAME_VAUTH "value_authorization" 645440Sjm199354 655440Sjm199354 665440Sjm199354 /* types string processing */ 675440Sjm199354 #define VS_TYPES_SEP ',' 685440Sjm199354 #define VS_TYPES_ESCAPE '\\' 695440Sjm199354 #define VS_TYPES_RULES "+-" 705440Sjm199354 715440Sjm199354 725440Sjm199354 /* 735440Sjm199354 * The SCF context enapsulating the SCF objects used in the 745440Sjm199354 * repository load and store routines vs_scf_values_get() 755440Sjm199354 * and vs_scf_values_set(). 765440Sjm199354 * 775440Sjm199354 * The context is always opened before a get or set, then 785440Sjm199354 * closed when finished (or on error); the open does an 795440Sjm199354 * initial setup, while inside the get and set functions, 805440Sjm199354 * additional objects within the context may be selectively 815440Sjm199354 * initialized for use, depending on the actions needed and 825440Sjm199354 * the properties being operated on. 835440Sjm199354 */ 845440Sjm199354 typedef struct vs_scfctx { 855440Sjm199354 scf_handle_t *vscf_handle; 865440Sjm199354 scf_instance_t *vscf_inst; 875440Sjm199354 scf_propertygroup_t *vscf_pgroup; 885440Sjm199354 scf_transaction_t *vscf_tx; 895440Sjm199354 scf_iter_t *vscf_iter; 905440Sjm199354 scf_property_t *vscf_prop[VS_NUM_PROPIDS]; 915440Sjm199354 scf_transaction_entry_t *vscf_ent[VS_NUM_PROPIDS]; 925440Sjm199354 scf_value_t *vscf_val[VS_NUM_PROPIDS]; 935440Sjm199354 } vs_scfctx_t; 945440Sjm199354 955440Sjm199354 /* 965440Sjm199354 * The vscan property definition. Maps the property id with the name 975440Sjm199354 * and type used to store the property in the repository. 985440Sjm199354 * A table of these definitions is defined with a single entry per 995440Sjm199354 * property. 1005440Sjm199354 */ 1015440Sjm199354 typedef struct { 1025440Sjm199354 const char *vpd_name; 1035440Sjm199354 uint64_t vpd_id; 1045440Sjm199354 scf_type_t vpd_type; 1055440Sjm199354 } vs_propdef_t; 1065440Sjm199354 1075440Sjm199354 typedef enum { 1085440Sjm199354 VS_PTYPE_GEN, 1095440Sjm199354 VS_PTYPE_SE 1105440Sjm199354 } vs_prop_type_t; 1115440Sjm199354 1125440Sjm199354 typedef struct vs_prop_hd { 1135440Sjm199354 vs_prop_type_t vp_type; 1145440Sjm199354 uint64_t vp_ids; 1155440Sjm199354 uint64_t vp_all; 1165440Sjm199354 union { 1175440Sjm199354 vs_props_t vp_gen; 1185440Sjm199354 vs_props_se_t vp_se; 1195440Sjm199354 } vp_props; 1205440Sjm199354 } vs_prop_hd_t; 1215440Sjm199354 1225440Sjm199354 #define vp_gen vp_props.vp_gen 1235440Sjm199354 #define vp_se vp_props.vp_se 1245440Sjm199354 1255440Sjm199354 /* 1265440Sjm199354 * Default values - these are used to return valid data 1275440Sjm199354 * to the caller in cases where invalid or unexpected values 1285440Sjm199354 * are found in the repository. 1295440Sjm199354 * 1305440Sjm199354 * Note: These values must be kept in sync with those defined 1315440Sjm199354 * in the service manifest. 1325440Sjm199354 */ 1335440Sjm199354 static const boolean_t vs_dflt_allow = B_TRUE; 1345440Sjm199354 static const boolean_t vs_dflt_enable = B_TRUE; 1355440Sjm199354 static const char *vs_dflt_maxsize = "1GB"; 1365440Sjm199354 static const char *vs_dflt_host = ""; 1375440Sjm199354 static const uint16_t vs_dflt_port = 1344; 1385440Sjm199354 static const uint16_t vs_dflt_maxconn = 32L; 1395440Sjm199354 static const char *vs_dflt_types = "+*"; 1405440Sjm199354 static const char *vs_dflt_vlog = ""; 1415440Sjm199354 1425440Sjm199354 /* Property definition table */ 1435440Sjm199354 static const vs_propdef_t vs_propdefs[] = { 1445440Sjm199354 /* general properties */ 1455440Sjm199354 { VS_PNAME_MAXSIZE, VS_PROPID_MAXSIZE, SCF_TYPE_ASTRING }, 1465440Sjm199354 { VS_PNAME_MAXSIZE_ACTION, VS_PROPID_MAXSIZE_ACTION, SCF_TYPE_BOOLEAN }, 1475440Sjm199354 { VS_PNAME_TYPES, VS_PROPID_TYPES, SCF_TYPE_ASTRING }, 1485440Sjm199354 { VS_PNAME_VLOG, VS_PROPID_VLOG, SCF_TYPE_ASTRING }, 1495440Sjm199354 /* scan engine properties */ 1505440Sjm199354 { VS_PNAME_SE_ENABLE, VS_PROPID_SE_ENABLE, SCF_TYPE_BOOLEAN }, 1515440Sjm199354 { VS_PNAME_SE_HOST, VS_PROPID_SE_HOST, SCF_TYPE_HOST }, 1525440Sjm199354 { VS_PNAME_SE_PORT, VS_PROPID_SE_PORT, SCF_TYPE_INTEGER }, 1535440Sjm199354 { VS_PNAME_SE_MAXCONN, VS_PROPID_SE_MAXCONN, SCF_TYPE_INTEGER }, 1545440Sjm199354 { VS_PNAME_VAUTH, VS_PROPID_VALUE_AUTH, SCF_TYPE_ASTRING } 1555440Sjm199354 }; 1565440Sjm199354 1575440Sjm199354 static const int vs_npropdefs = sizeof (vs_propdefs)/sizeof (vs_propdef_t); 1585440Sjm199354 1595440Sjm199354 /* Local functions */ 1605440Sjm199354 static const vs_propdef_t *vs_get_propdef(uint64_t); 1615440Sjm199354 static void vs_default_value(vs_prop_hd_t *, const uint64_t); 1625440Sjm199354 1635440Sjm199354 static int vs_scf_values_get(const char *, vs_prop_hd_t *); 1645440Sjm199354 static int vs_scf_get(const vs_propdef_t *, vs_prop_hd_t *, vs_scfctx_t *, int); 1655440Sjm199354 1665440Sjm199354 static int vs_scf_values_set(const char *, vs_prop_hd_t *); 1675440Sjm199354 static int vs_scf_set(const vs_propdef_t *, vs_prop_hd_t *, vs_scfctx_t *, int); 1685440Sjm199354 static int vs_scf_pg_create(const char *, vs_prop_hd_t *); 169*6407Sjm199354 static int vs_scf_pg_delete(const char *); 1705440Sjm199354 1715440Sjm199354 static int vs_scf_ctx_open(vs_scfctx_t *); 1725440Sjm199354 static void vs_scf_ctx_close(vs_scfctx_t *); 1735440Sjm199354 1745440Sjm199354 static int vs_validate(const vs_prop_hd_t *, uint64_t); 1755440Sjm199354 static int vs_is_valid_types(const char *); 1765440Sjm199354 static int vs_is_valid_host(const char *); 1775440Sjm199354 static int vs_checkauth(char *); 1785440Sjm199354 179*6407Sjm199354 static int vs_props_get_engines(char *[], int *); 180*6407Sjm199354 static void vs_engid_to_pgname(const char *, char [VS_PGNAME_ENGINE_LEN]); 1815440Sjm199354 static int vs_scf_pg_count(void); 1825440Sjm199354 static int vs_strtoshift(const char *); 1835440Sjm199354 1845440Sjm199354 1855440Sjm199354 /* 1865440Sjm199354 * vs_props_get_all 1875440Sjm199354 * 1885440Sjm199354 * Retrieves the general service properties and all properties 1895440Sjm199354 * for all scan engines from the repository. 1905440Sjm199354 * 1915440Sjm199354 * If invalid property values are found, the values are corrected to 1925440Sjm199354 * the default value. 1935440Sjm199354 * 1945440Sjm199354 * Return codes: 1955440Sjm199354 * VS_ERR_VS_ERR_NONE 1965440Sjm199354 * VS_ERR_SCF 1975440Sjm199354 * VS_ERR_SYS 1985440Sjm199354 */ 1995440Sjm199354 int 2005440Sjm199354 vs_props_get_all(vs_props_all_t *va) 2015440Sjm199354 { 2025440Sjm199354 int i, rc, n; 203*6407Sjm199354 char *engids[VS_SE_MAX]; 2045440Sjm199354 2055440Sjm199354 (void) memset(va, 0, sizeof (vs_props_all_t)); 2065440Sjm199354 if ((rc = vs_props_get(&va->va_props, VS_PROPID_GEN_ALL)) 2075440Sjm199354 != VS_ERR_NONE) 2085440Sjm199354 return (rc); 2095440Sjm199354 2105440Sjm199354 n = VS_SE_MAX; 2115440Sjm199354 if ((rc = vs_props_get_engines(engids, &n)) != VS_ERR_NONE) 2125440Sjm199354 return (rc); 2135440Sjm199354 2145440Sjm199354 for (i = 0; i < n; i++) { 215*6407Sjm199354 if ((rc = vs_props_se_get(engids[i], 216*6407Sjm199354 &va->va_se[i], VS_PROPID_SE_ALL)) != VS_ERR_NONE) 217*6407Sjm199354 break; 2185440Sjm199354 } 2195440Sjm199354 220*6407Sjm199354 /* free engids allocated in vs_props_get_engines */ 221*6407Sjm199354 for (i = 0; i < VS_SE_MAX; i++) { 222*6407Sjm199354 if (engids[i] != NULL) 223*6407Sjm199354 free(engids[i]); 224*6407Sjm199354 } 225*6407Sjm199354 226*6407Sjm199354 return (rc); 2275440Sjm199354 } 2285440Sjm199354 2295440Sjm199354 2305440Sjm199354 /* 2315440Sjm199354 * vs_props_get 2325440Sjm199354 * 2335440Sjm199354 * Retrieves values for the specified general service properties from 2345440Sjm199354 * the repository. 2355440Sjm199354 * 2365440Sjm199354 * If invalid property values are found, the values are corrected to 2375440Sjm199354 * the default value. 2385440Sjm199354 * 2395440Sjm199354 * Return codes: 2405440Sjm199354 * VS_ERR_VS_ERR_NONE 2415440Sjm199354 * VS_ERR_INVALID_PROPERTY 2425440Sjm199354 * VS_ERR_SCF 2435440Sjm199354 * VS_ERR_SYS 2445440Sjm199354 */ 2455440Sjm199354 int 2465440Sjm199354 vs_props_get(vs_props_t *vp, uint64_t propids) 2475440Sjm199354 { 2485440Sjm199354 int rc; 2495440Sjm199354 vs_prop_hd_t prop_hd; 2505440Sjm199354 2515440Sjm199354 if ((propids & VS_PROPID_GEN_ALL) != propids) 2525440Sjm199354 return (VS_ERR_INVALID_PROPERTY); 2535440Sjm199354 2545440Sjm199354 (void) memset(&prop_hd, 0, sizeof (vs_prop_hd_t)); 2555440Sjm199354 prop_hd.vp_type = VS_PTYPE_GEN; 2565440Sjm199354 prop_hd.vp_ids = propids; 2575440Sjm199354 prop_hd.vp_all = VS_PROPID_GEN_ALL; 2585440Sjm199354 2595440Sjm199354 rc = vs_scf_values_get(VS_PGNAME_GENERAL, &prop_hd); 2605440Sjm199354 2615440Sjm199354 *vp = prop_hd.vp_gen; 2625440Sjm199354 return (rc); 2635440Sjm199354 } 2645440Sjm199354 2655440Sjm199354 2665440Sjm199354 /* 2675440Sjm199354 * vs_props_set 2685440Sjm199354 * 2695440Sjm199354 * Changes values for the specified general service properties 2705440Sjm199354 * in the repository. 2715440Sjm199354 * 2725440Sjm199354 * Return codes: 2735440Sjm199354 * VS_ERR_VS_ERR_NONE 2745440Sjm199354 * VS_ERR_INVALID_PROPERTY 2755440Sjm199354 * VS_ERR_INVALID_VALUE 2765440Sjm199354 * VS_ERR_SCF 2775440Sjm199354 * VS_ERR_SYS 2785440Sjm199354 */ 2795440Sjm199354 int 2805440Sjm199354 vs_props_set(const vs_props_t *vp, uint64_t propids) 2815440Sjm199354 { 2825440Sjm199354 vs_prop_hd_t prop_hd; 2835440Sjm199354 2845440Sjm199354 if ((propids & VS_PROPID_GEN_ALL) != propids) 2855440Sjm199354 return (VS_ERR_INVALID_PROPERTY); 2865440Sjm199354 2875440Sjm199354 (void) memset(&prop_hd, 0, sizeof (vs_prop_hd_t)); 2885440Sjm199354 prop_hd.vp_type = VS_PTYPE_GEN; 2895440Sjm199354 prop_hd.vp_ids = propids; 2905440Sjm199354 prop_hd.vp_all = VS_PROPID_GEN_ALL; 2915440Sjm199354 prop_hd.vp_gen = *vp; 2925440Sjm199354 return (vs_scf_values_set(VS_PGNAME_GENERAL, &prop_hd)); 2935440Sjm199354 } 2945440Sjm199354 2955440Sjm199354 2965440Sjm199354 /* 2975440Sjm199354 * vs_props_se_get 2985440Sjm199354 * 2995440Sjm199354 * Retrieves values for the specified scan engine properties from the 3005440Sjm199354 * repository. 3015440Sjm199354 * 3025440Sjm199354 * If the enable property is set (true), the host property is 3035440Sjm199354 * checked for validity. If it is not valid, the requested values 3045440Sjm199354 * are returned with the enable propery set to off (false) 3055440Sjm199354 * 3065440Sjm199354 * Return codes: 3075440Sjm199354 * VS_ERR_VS_ERR_NONE 3085440Sjm199354 * VS_ERR_INVALID_PROPERTY 3095440Sjm199354 * VS_ERR_SCF 3105440Sjm199354 * VS_ERR_SYS 3115440Sjm199354 */ 3125440Sjm199354 int 3135440Sjm199354 vs_props_se_get(char *engid, vs_props_se_t *sep, uint64_t propids) 3145440Sjm199354 { 3155440Sjm199354 int rc; 316*6407Sjm199354 char pgname[VS_PGNAME_ENGINE_LEN]; 3175440Sjm199354 vs_prop_hd_t prop_hd; 3185440Sjm199354 3195440Sjm199354 /* VS_PGNAME_GENERAL is a reserved for GENERAL property group */ 3205440Sjm199354 if (strcmp(engid, VS_PGNAME_GENERAL) == 0) 3215440Sjm199354 return (VS_ERR_INVALID_SE); 3225440Sjm199354 3235440Sjm199354 if ((propids & VS_PROPID_SE_ALL) != propids) 3245440Sjm199354 return (VS_ERR_INVALID_PROPERTY); 3255440Sjm199354 3265440Sjm199354 (void) memset(&prop_hd, 0, sizeof (vs_prop_hd_t)); 3275440Sjm199354 prop_hd.vp_type = VS_PTYPE_SE; 3285440Sjm199354 prop_hd.vp_ids = propids; 3295440Sjm199354 prop_hd.vp_all = VS_PROPID_SE_ALL; 3305440Sjm199354 (void) strlcpy(prop_hd.vp_se.vep_engid, engid, VS_SE_NAME_LEN); 3315440Sjm199354 3325440Sjm199354 /* If getting enable, get the host property too */ 3335440Sjm199354 if ((propids & VS_PROPID_SE_ENABLE)) 3345440Sjm199354 prop_hd.vp_ids |= VS_PROPID_SE_HOST; 3355440Sjm199354 3365440Sjm199354 /* Load values from the repository */ 337*6407Sjm199354 vs_engid_to_pgname(engid, pgname); 338*6407Sjm199354 rc = vs_scf_values_get(pgname, &prop_hd); 3395440Sjm199354 if (rc != VS_ERR_NONE) 3405440Sjm199354 return (rc); 3415440Sjm199354 3425440Sjm199354 /* 3435440Sjm199354 * If the host is invalid and the enable property is on, 3445440Sjm199354 * return enable property as off 3455440Sjm199354 */ 3465440Sjm199354 if ((prop_hd.vp_ids & VS_PROPID_SE_HOST) && 3475440Sjm199354 (vs_validate(&prop_hd, VS_PROPID_SE_HOST) != VS_ERR_NONE)) { 3485440Sjm199354 prop_hd.vp_se.vep_enable = B_FALSE; 3495440Sjm199354 } 3505440Sjm199354 3515440Sjm199354 *sep = prop_hd.vp_se; 3525440Sjm199354 return (rc); 3535440Sjm199354 } 3545440Sjm199354 3555440Sjm199354 3565440Sjm199354 3575440Sjm199354 /* 3585440Sjm199354 * vs_props_se_set 3595440Sjm199354 * 3605440Sjm199354 * Changes the values for the specified scan engine properties in the 3615440Sjm199354 * repository. 3625440Sjm199354 * 3635440Sjm199354 * If the enable property is being changed to true in this operation, 3645440Sjm199354 * a host property must also be specified, or already exist in the 3655440Sjm199354 * repository. 3665440Sjm199354 * 3675440Sjm199354 * Return codes: 3685440Sjm199354 * VS_ERR_NONE 3695440Sjm199354 * VS_ERR_INVALID_PROPERTY 3705440Sjm199354 * VS_ERR_INVALID_VALUE 3715440Sjm199354 * VS_ERR_SCF 3725440Sjm199354 * VS_ERR_SYS 3735440Sjm199354 */ 3745440Sjm199354 int 3755440Sjm199354 vs_props_se_set(char *engid, const vs_props_se_t *sep, uint64_t propids) 3765440Sjm199354 { 3775440Sjm199354 int rc; 378*6407Sjm199354 char pgname[VS_PGNAME_ENGINE_LEN]; 3795440Sjm199354 vs_prop_hd_t prop_hd; 3805440Sjm199354 3815440Sjm199354 /* VS_PGNAME_GENERAL is a reserved for GENERAL property group */ 3825440Sjm199354 if (strcmp(engid, VS_PGNAME_GENERAL) == 0) 3835440Sjm199354 return (VS_ERR_INVALID_SE); 3845440Sjm199354 3855440Sjm199354 if ((propids & VS_PROPID_SE_ALL) != propids) 3865440Sjm199354 return (VS_ERR_INVALID_PROPERTY); 3875440Sjm199354 3885440Sjm199354 (void) memset(&prop_hd, 0, sizeof (vs_prop_hd_t)); 3895440Sjm199354 prop_hd.vp_type = VS_PTYPE_SE; 3905440Sjm199354 prop_hd.vp_all = VS_PROPID_SE_ALL; 3915440Sjm199354 392*6407Sjm199354 vs_engid_to_pgname(engid, pgname); 393*6407Sjm199354 3945440Sjm199354 /* 3955440Sjm199354 * if enabling a scan engine, ensure that a valid host 3965440Sjm199354 * is also being set, or already exists in the repository 3975440Sjm199354 */ 3985440Sjm199354 if ((propids & VS_PROPID_SE_ENABLE) && (sep->vep_enable == B_TRUE) && 3995440Sjm199354 !(propids & VS_PROPID_SE_HOST)) { 4005440Sjm199354 4015440Sjm199354 prop_hd.vp_ids = VS_PROPID_SE_HOST; 402*6407Sjm199354 if ((rc = vs_scf_values_get(pgname, &prop_hd)) != VS_ERR_NONE) 4035440Sjm199354 return (rc); 4045440Sjm199354 4055440Sjm199354 if (vs_validate(&prop_hd, VS_PROPID_SE_HOST) != VS_ERR_NONE) 4065440Sjm199354 return (VS_ERR_INVALID_HOST); 4075440Sjm199354 } 4085440Sjm199354 4095440Sjm199354 prop_hd.vp_ids = propids; 4105440Sjm199354 prop_hd.vp_se = *sep; 4115440Sjm199354 412*6407Sjm199354 return (vs_scf_values_set(pgname, &prop_hd)); 4135440Sjm199354 } 4145440Sjm199354 4155440Sjm199354 4165440Sjm199354 /* 4175440Sjm199354 * vs_props_se_create 4185440Sjm199354 */ 4195440Sjm199354 int 4205440Sjm199354 vs_props_se_create(char *engid, const vs_props_se_t *sep, uint64_t propids) 4215440Sjm199354 { 4225440Sjm199354 int n; 423*6407Sjm199354 char pgname[VS_PGNAME_ENGINE_LEN]; 4245440Sjm199354 vs_prop_hd_t prop_hd; 4255440Sjm199354 4265440Sjm199354 if ((propids & VS_PROPID_SE_ALL) != propids) 4275440Sjm199354 return (VS_ERR_INVALID_PROPERTY); 4285440Sjm199354 4295440Sjm199354 /* VS_PGNAME_GENERAL is a reserved for GENERAL property group */ 4305440Sjm199354 if (strcmp(engid, VS_PGNAME_GENERAL) == 0) 4315440Sjm199354 return (VS_ERR_INVALID_SE); 4325440Sjm199354 4335440Sjm199354 if ((n = vs_scf_pg_count()) == -1) 4345440Sjm199354 return (VS_ERR_SCF); 4355440Sjm199354 4365440Sjm199354 if (n == VS_SE_MAX) 4375440Sjm199354 return (VS_ERR_MAX_SE); 4385440Sjm199354 439*6407Sjm199354 vs_engid_to_pgname(engid, pgname); 440*6407Sjm199354 4415440Sjm199354 (void) memset(&prop_hd, 0, sizeof (vs_prop_hd_t)); 4425440Sjm199354 prop_hd.vp_type = VS_PTYPE_SE; 4435440Sjm199354 prop_hd.vp_all = VS_PROPID_SE_ALL; 4445440Sjm199354 prop_hd.vp_ids = propids | VS_PROPID_VALUE_AUTH; 4455440Sjm199354 prop_hd.vp_se = *sep; 4465440Sjm199354 447*6407Sjm199354 /* if hostname not specified, default it to engid */ 448*6407Sjm199354 if ((propids & VS_PROPID_SE_HOST) == 0) { 449*6407Sjm199354 (void) strlcpy(prop_hd.vp_se.vep_host, engid, MAXHOSTNAMELEN); 450*6407Sjm199354 prop_hd.vp_ids |= VS_PROPID_SE_HOST; 451*6407Sjm199354 } 4525440Sjm199354 453*6407Sjm199354 return (vs_scf_pg_create(pgname, &prop_hd)); 4545440Sjm199354 } 4555440Sjm199354 4565440Sjm199354 4575440Sjm199354 /* 4585440Sjm199354 * vs_props_se_delete 4595440Sjm199354 */ 4605440Sjm199354 int 4615440Sjm199354 vs_props_se_delete(const char *engid) 4625440Sjm199354 { 463*6407Sjm199354 char pgname[VS_PGNAME_ENGINE_LEN]; 4645440Sjm199354 4655440Sjm199354 /* VS_PGNAME_GENERAL is a reserved for GENERAL property group */ 4665440Sjm199354 if (strcmp(engid, VS_PGNAME_GENERAL) == 0) 4675440Sjm199354 return (VS_ERR_INVALID_SE); 4685440Sjm199354 469*6407Sjm199354 vs_engid_to_pgname(engid, pgname); 4705440Sjm199354 471*6407Sjm199354 return (vs_scf_pg_delete(pgname)); 4725440Sjm199354 } 4735440Sjm199354 4745440Sjm199354 4755440Sjm199354 /* 4765440Sjm199354 * vs_strerror 4775440Sjm199354 */ 4785440Sjm199354 const char * 4795440Sjm199354 vs_strerror(int error) 4805440Sjm199354 { 4815440Sjm199354 switch (error) { 4825440Sjm199354 case VS_ERR_NONE: 4835440Sjm199354 return (gettext("no error")); 4845440Sjm199354 case VS_ERR_INVALID_PROPERTY: 4855440Sjm199354 return (gettext("invalid property id")); 4865440Sjm199354 case VS_ERR_INVALID_VALUE: 4875440Sjm199354 return (gettext("invalid property value")); 4885440Sjm199354 case VS_ERR_INVALID_HOST: 4895440Sjm199354 return (gettext("invalid host")); 4905440Sjm199354 case VS_ERR_INVALID_SE: 4915440Sjm199354 return (gettext("invalid scan engine")); 4925440Sjm199354 case VS_ERR_MAX_SE: 4935440Sjm199354 return (gettext("max scan engines exceeded")); 4945440Sjm199354 case VS_ERR_AUTH: 4955440Sjm199354 return (gettext("insufficient privileges for action")); 4965440Sjm199354 case VS_ERR_DAEMON_COMM: 4975440Sjm199354 return (gettext("unable to contact vscand")); 4985440Sjm199354 case VS_ERR_SCF: 4995440Sjm199354 return (scf_strerror(scf_error())); 5005440Sjm199354 case VS_ERR_SYS: 5015440Sjm199354 return (strerror(errno)); 5025440Sjm199354 default: 5035440Sjm199354 return (gettext("unknown error")); 5045440Sjm199354 } 5055440Sjm199354 } 5065440Sjm199354 5075440Sjm199354 5085440Sjm199354 /* 5095440Sjm199354 * vs_get_propdef 5105440Sjm199354 * 5115440Sjm199354 * Finds and returns a property definition by property id. 5125440Sjm199354 */ 5135440Sjm199354 static const vs_propdef_t * 5145440Sjm199354 vs_get_propdef(uint64_t propid) 5155440Sjm199354 { 5165440Sjm199354 int i; 5175440Sjm199354 5185440Sjm199354 for (i = 0; i < vs_npropdefs; i++) { 5195440Sjm199354 if (propid == vs_propdefs[i].vpd_id) 5205440Sjm199354 return (&vs_propdefs[i]); 5215440Sjm199354 } 5225440Sjm199354 5235440Sjm199354 return (NULL); 5245440Sjm199354 } 5255440Sjm199354 5265440Sjm199354 5275440Sjm199354 /* 5285440Sjm199354 * vs_default_value 5295440Sjm199354 * 5305440Sjm199354 * Sets a property value that contains invalid data to its default value. 5315440Sjm199354 * 5325440Sjm199354 * Note that this function does not alter any values in the repository 5335440Sjm199354 * This is only to enable the caller to get valid data. 5345440Sjm199354 */ 5355440Sjm199354 static void 5365440Sjm199354 vs_default_value(vs_prop_hd_t *prop_hd, const uint64_t propid) 5375440Sjm199354 { 5385440Sjm199354 vs_props_t *vp = &prop_hd->vp_gen; 5395440Sjm199354 vs_props_se_t *vep = &prop_hd->vp_se; 5405440Sjm199354 5415440Sjm199354 switch (propid) { 5425440Sjm199354 case VS_PROPID_MAXSIZE: 5435440Sjm199354 (void) strlcpy(vp->vp_maxsize, vs_dflt_maxsize, 5445440Sjm199354 sizeof (vp->vp_maxsize)); 5455440Sjm199354 break; 5465440Sjm199354 case VS_PROPID_MAXSIZE_ACTION: 5475440Sjm199354 vp->vp_maxsize_action = vs_dflt_allow; 5485440Sjm199354 break; 5495440Sjm199354 case VS_PROPID_TYPES: 5505440Sjm199354 (void) strlcpy(vp->vp_types, vs_dflt_types, 5515440Sjm199354 sizeof (vp->vp_types)); 5525440Sjm199354 break; 5535440Sjm199354 case VS_PROPID_VLOG: 5545440Sjm199354 (void) strlcpy(vp->vp_vlog, vs_dflt_vlog, 5555440Sjm199354 sizeof (vp->vp_vlog)); 5565440Sjm199354 break; 5575440Sjm199354 case VS_PROPID_SE_ENABLE: 5585440Sjm199354 vep->vep_enable = vs_dflt_enable; 5595440Sjm199354 break; 5605440Sjm199354 case VS_PROPID_SE_HOST: 5615440Sjm199354 (void) strlcpy(vep->vep_host, vs_dflt_host, 5625440Sjm199354 sizeof (vep->vep_host)); 5635440Sjm199354 break; 5645440Sjm199354 case VS_PROPID_SE_PORT: 5655440Sjm199354 vep->vep_port = vs_dflt_port; 5665440Sjm199354 break; 5675440Sjm199354 case VS_PROPID_SE_MAXCONN: 5685440Sjm199354 vep->vep_maxconn = vs_dflt_maxconn; 5695440Sjm199354 break; 5705440Sjm199354 default: 5715440Sjm199354 break; 5725440Sjm199354 } 5735440Sjm199354 } 5745440Sjm199354 5755440Sjm199354 5765440Sjm199354 /* 5775440Sjm199354 * vs_scf_values_get 5785440Sjm199354 * 5795440Sjm199354 * Gets property values for one or more properties from the repository. 5805440Sjm199354 * This is the single entry point for loading SMF values. 5815440Sjm199354 * 5825440Sjm199354 * While a transaction is not used for loading property values, 5835440Sjm199354 * the operation is parameterized by a property group. All properties 5845440Sjm199354 * retrieved in this function, then, must belong to the same property 5855440Sjm199354 * group. 5865440Sjm199354 */ 5875440Sjm199354 int 5885440Sjm199354 vs_scf_values_get(const char *pgname, vs_prop_hd_t *prop_hd) 5895440Sjm199354 { 5905440Sjm199354 vs_scfctx_t vsc; 5915440Sjm199354 int rc, np; 5925440Sjm199354 const vs_propdef_t *vpd; 5935440Sjm199354 uint64_t propid; 5945440Sjm199354 5955440Sjm199354 if ((vs_scf_ctx_open(&vsc)) != 0) { 5965440Sjm199354 vs_scf_ctx_close(&vsc); 5975440Sjm199354 return (VS_ERR_SCF); 5985440Sjm199354 } 5995440Sjm199354 6005440Sjm199354 if (scf_instance_get_pg(vsc.vscf_inst, pgname, vsc.vscf_pgroup) == -1) { 6015440Sjm199354 vs_scf_ctx_close(&vsc); 6025440Sjm199354 if (strcmp(pgname, "VS_PGNAME_GENERAL") != 0) { 6035440Sjm199354 rc = scf_error(); 6045440Sjm199354 if ((rc == SCF_ERROR_NOT_FOUND) || 6055440Sjm199354 (rc == SCF_ERROR_INVALID_ARGUMENT)) 6065440Sjm199354 return (VS_ERR_INVALID_SE); 6075440Sjm199354 } 6085440Sjm199354 return (VS_ERR_SCF); 6095440Sjm199354 } 6105440Sjm199354 6115440Sjm199354 rc = VS_ERR_NONE; 6125440Sjm199354 np = 0; 6135440Sjm199354 for (propid = 1LL; propid <= VS_PROPID_MAX; propid <<= 1) { 6145440Sjm199354 if ((prop_hd->vp_ids & propid) == 0) 6155440Sjm199354 continue; 6165440Sjm199354 6175440Sjm199354 if ((vpd = vs_get_propdef(propid)) == NULL) { 6185440Sjm199354 rc = VS_ERR_INVALID_PROPERTY; 6195440Sjm199354 break; 6205440Sjm199354 } 6215440Sjm199354 6225440Sjm199354 vsc.vscf_prop[np] = scf_property_create(vsc.vscf_handle); 6235440Sjm199354 vsc.vscf_val[np] = scf_value_create(vsc.vscf_handle); 6245440Sjm199354 6255440Sjm199354 if (vsc.vscf_prop[np] == NULL || vsc.vscf_val[np] == NULL) { 6265440Sjm199354 rc = VS_ERR_SCF; 6275440Sjm199354 break; 6285440Sjm199354 } 6295440Sjm199354 6305440Sjm199354 if (scf_pg_get_property(vsc.vscf_pgroup, vpd->vpd_name, 6315440Sjm199354 vsc.vscf_prop[np]) == -1) { 6325440Sjm199354 if (scf_error() == SCF_ERROR_NOT_FOUND) { 6335440Sjm199354 vs_default_value(prop_hd, vpd->vpd_id); 6345440Sjm199354 continue; 6355440Sjm199354 } 6365440Sjm199354 rc = VS_ERR_SCF; 6375440Sjm199354 break; 6385440Sjm199354 } 6395440Sjm199354 6405440Sjm199354 if ((rc = vs_scf_get(vpd, prop_hd, &vsc, np)) != VS_ERR_NONE) 6415440Sjm199354 break; 6425440Sjm199354 6435440Sjm199354 ++np; 6445440Sjm199354 } 6455440Sjm199354 6465440Sjm199354 6475440Sjm199354 vs_scf_ctx_close(&vsc); 6485440Sjm199354 6495440Sjm199354 return (rc); 6505440Sjm199354 } 6515440Sjm199354 6525440Sjm199354 6535440Sjm199354 /* 6545440Sjm199354 * vs_scf_get 6555440Sjm199354 * 6565440Sjm199354 * Loads a single values from the repository into the appropriate vscan 6575440Sjm199354 * property structure member. 6585440Sjm199354 */ 6595440Sjm199354 static int 6605440Sjm199354 vs_scf_get(const vs_propdef_t *vpd, vs_prop_hd_t *prop_hd, 6615440Sjm199354 vs_scfctx_t *vsc, int idx) 6625440Sjm199354 { 6635440Sjm199354 int rc; 6645440Sjm199354 int64_t port; 6655440Sjm199354 uint8_t valbool; 6665440Sjm199354 vs_props_t *vp = &prop_hd->vp_gen; 6675440Sjm199354 vs_props_se_t *vep = &prop_hd->vp_se; 6685440Sjm199354 6695440Sjm199354 if ((rc = scf_property_get_value(vsc->vscf_prop[idx], 6705440Sjm199354 vsc->vscf_val[idx])) == -1) { 6715440Sjm199354 if (rc == SCF_ERROR_CONSTRAINT_VIOLATED || 6725440Sjm199354 rc == SCF_ERROR_NOT_FOUND) { 6735440Sjm199354 vs_default_value(prop_hd, vpd->vpd_id); 6745440Sjm199354 return (VS_ERR_NONE); 6755440Sjm199354 } 6765440Sjm199354 return (VS_ERR_SCF); 6775440Sjm199354 } 6785440Sjm199354 6795440Sjm199354 rc = VS_ERR_NONE; 6805440Sjm199354 switch (vpd->vpd_id) { 6815440Sjm199354 case VS_PROPID_MAXSIZE: 6825440Sjm199354 if ((scf_value_get_astring(vsc->vscf_val[idx], 6835440Sjm199354 vp->vp_maxsize, sizeof (vp->vp_maxsize))) == -1) { 6845440Sjm199354 return (VS_ERR_SCF); 6855440Sjm199354 } 6865440Sjm199354 break; 6875440Sjm199354 case VS_PROPID_MAXSIZE_ACTION: 6885440Sjm199354 if ((scf_value_get_boolean(vsc->vscf_val[idx], 6895440Sjm199354 &valbool)) == -1) { 6905440Sjm199354 return (VS_ERR_SCF); 6915440Sjm199354 } 6925440Sjm199354 vp->vp_maxsize_action = (valbool == 0) ? B_FALSE : B_TRUE; 6935440Sjm199354 break; 6945440Sjm199354 case VS_PROPID_TYPES: 6955440Sjm199354 if ((scf_value_get_astring(vsc->vscf_val[idx], 6965440Sjm199354 vp->vp_types, sizeof (vp->vp_types))) == -1) { 6975440Sjm199354 return (VS_ERR_SCF); 6985440Sjm199354 } 6995440Sjm199354 break; 7005440Sjm199354 case VS_PROPID_VLOG: 7015440Sjm199354 if ((scf_value_get_astring(vsc->vscf_val[idx], 7025440Sjm199354 vp->vp_vlog, sizeof (vp->vp_vlog))) == -1) { 7035440Sjm199354 return (VS_ERR_SCF); 7045440Sjm199354 } 7055440Sjm199354 break; 7065440Sjm199354 case VS_PROPID_SE_ENABLE: 7075440Sjm199354 if ((scf_value_get_boolean(vsc->vscf_val[idx], 7085440Sjm199354 &valbool)) == -1) { 7095440Sjm199354 return (VS_ERR_SCF); 7105440Sjm199354 } 7115440Sjm199354 vep->vep_enable = (valbool == 0) ? B_FALSE : B_TRUE; 7125440Sjm199354 break; 7135440Sjm199354 case VS_PROPID_SE_HOST: 7145440Sjm199354 (void) scf_value_get_as_string_typed(vsc->vscf_val[idx], 7155440Sjm199354 vpd->vpd_type, vep->vep_host, sizeof (vep->vep_host)); 7165440Sjm199354 break; 7175440Sjm199354 case VS_PROPID_SE_PORT: 7185440Sjm199354 if ((scf_value_get_integer(vsc->vscf_val[idx], &port)) == -1) 7195440Sjm199354 return (VS_ERR_SCF); 7205440Sjm199354 if (port <= 0 || port >= UINT16_MAX) 7215440Sjm199354 rc = VS_ERR_INVALID_VALUE; 7225440Sjm199354 else 7235440Sjm199354 vep->vep_port = (uint16_t)port; 7245440Sjm199354 break; 7255440Sjm199354 case VS_PROPID_SE_MAXCONN: 7265440Sjm199354 if ((scf_value_get_integer(vsc->vscf_val[idx], 7275440Sjm199354 (int64_t *)&vep->vep_maxconn)) == -1) { 7285440Sjm199354 return (VS_ERR_SCF); 7295440Sjm199354 } 7305440Sjm199354 break; 7315440Sjm199354 default: 7325440Sjm199354 break; 7335440Sjm199354 } 7345440Sjm199354 7355440Sjm199354 if ((rc != VS_ERR_NONE) || 7365440Sjm199354 (vs_validate(prop_hd, vpd->vpd_id) != VS_ERR_NONE)) { 7375440Sjm199354 vs_default_value(prop_hd, vpd->vpd_id); 7385440Sjm199354 } 7395440Sjm199354 7405440Sjm199354 return (VS_ERR_NONE); 7415440Sjm199354 } 7425440Sjm199354 7435440Sjm199354 7445440Sjm199354 /* 7455440Sjm199354 * vs_scf_pg_create 7465440Sjm199354 */ 7475440Sjm199354 static int 7485440Sjm199354 vs_scf_pg_create(const char *pgname, vs_prop_hd_t *prop_hd) 7495440Sjm199354 { 7505440Sjm199354 int rc; 7515440Sjm199354 uint64_t propid; 7525440Sjm199354 vs_scfctx_t vsc; 7535440Sjm199354 7545440Sjm199354 /* ensure that caller has authorization to refresh service */ 7555440Sjm199354 if ((rc = vs_checkauth(VS_ACTION_AUTH)) != VS_ERR_NONE) 7565440Sjm199354 return (rc); 7575440Sjm199354 7585440Sjm199354 if (vs_scf_ctx_open(&vsc) != 0) { 7595440Sjm199354 vs_scf_ctx_close(&vsc); 7605440Sjm199354 return (VS_ERR_SCF); 7615440Sjm199354 } 7625440Sjm199354 7635440Sjm199354 if (scf_instance_add_pg(vsc.vscf_inst, pgname, 7645440Sjm199354 SCF_GROUP_APPLICATION, 0, vsc.vscf_pgroup) == -1) { 7655440Sjm199354 vs_scf_ctx_close(&vsc); 7665440Sjm199354 if (scf_error() == SCF_ERROR_INVALID_ARGUMENT) 7675440Sjm199354 return (VS_ERR_INVALID_SE); 7685440Sjm199354 return (VS_ERR_SCF); 7695440Sjm199354 } 7705440Sjm199354 vs_scf_ctx_close(&vsc); 7715440Sjm199354 7725440Sjm199354 /* set default values for those not specified */ 7735440Sjm199354 for (propid = 1LL; propid <= VS_PROPID_MAX; propid <<= 1) { 7745440Sjm199354 if ((propid & prop_hd->vp_all) && !(propid & prop_hd->vp_ids)) 7755440Sjm199354 vs_default_value(prop_hd, propid); 7765440Sjm199354 } 777*6407Sjm199354 7785440Sjm199354 prop_hd->vp_ids = prop_hd->vp_all; 7795440Sjm199354 prop_hd->vp_ids |= VS_PROPID_VALUE_AUTH; 7805440Sjm199354 7815440Sjm199354 rc = vs_scf_values_set(pgname, prop_hd); 7825440Sjm199354 if (rc != VS_ERR_NONE) 783*6407Sjm199354 (void) vs_scf_pg_delete(pgname); 7845440Sjm199354 7855440Sjm199354 return (rc); 7865440Sjm199354 } 7875440Sjm199354 7885440Sjm199354 7895440Sjm199354 /* 790*6407Sjm199354 * vs_scf_pg_delete 791*6407Sjm199354 */ 792*6407Sjm199354 static int 793*6407Sjm199354 vs_scf_pg_delete(const char *pgname) 794*6407Sjm199354 { 795*6407Sjm199354 int rc; 796*6407Sjm199354 vs_scfctx_t vsc; 797*6407Sjm199354 798*6407Sjm199354 /* ensure that caller has authorization to refresh service */ 799*6407Sjm199354 if ((rc = vs_checkauth(VS_ACTION_AUTH)) != VS_ERR_NONE) 800*6407Sjm199354 return (rc); 801*6407Sjm199354 802*6407Sjm199354 if (vs_scf_ctx_open(&vsc) != 0) { 803*6407Sjm199354 vs_scf_ctx_close(&vsc); 804*6407Sjm199354 return (VS_ERR_SCF); 805*6407Sjm199354 } 806*6407Sjm199354 807*6407Sjm199354 if (scf_instance_get_pg(vsc.vscf_inst, pgname, vsc.vscf_pgroup) == -1) { 808*6407Sjm199354 vs_scf_ctx_close(&vsc); 809*6407Sjm199354 rc = scf_error(); 810*6407Sjm199354 if ((rc == SCF_ERROR_NOT_FOUND) || 811*6407Sjm199354 (rc == SCF_ERROR_INVALID_ARGUMENT)) 812*6407Sjm199354 return (VS_ERR_INVALID_SE); 813*6407Sjm199354 else 814*6407Sjm199354 return (VS_ERR_SCF); 815*6407Sjm199354 } 816*6407Sjm199354 817*6407Sjm199354 if (scf_pg_delete(vsc.vscf_pgroup) == -1) { 818*6407Sjm199354 vs_scf_ctx_close(&vsc); 819*6407Sjm199354 rc = scf_error(); 820*6407Sjm199354 if ((rc == SCF_ERROR_NOT_FOUND) || 821*6407Sjm199354 (rc == SCF_ERROR_INVALID_ARGUMENT)) 822*6407Sjm199354 return (VS_ERR_INVALID_SE); 823*6407Sjm199354 824*6407Sjm199354 return (VS_ERR_SCF); 825*6407Sjm199354 } 826*6407Sjm199354 827*6407Sjm199354 vs_scf_ctx_close(&vsc); 828*6407Sjm199354 829*6407Sjm199354 /* Notify the daemon that things have changed */ 830*6407Sjm199354 if ((smf_refresh_instance(VS_INSTANCE_FMRI)) == -1) { 831*6407Sjm199354 return (VS_ERR_SCF); 832*6407Sjm199354 } 833*6407Sjm199354 834*6407Sjm199354 return (VS_ERR_NONE); 835*6407Sjm199354 } 836*6407Sjm199354 837*6407Sjm199354 838*6407Sjm199354 /* 8395440Sjm199354 * vs_scf_values_set 8405440Sjm199354 * 8415440Sjm199354 * Sets property values in the repository. This is the single 8425440Sjm199354 * entry point for storing SMF values. 8435440Sjm199354 * 8445440Sjm199354 * Like loading values, this is an operation based on a single property 8455440Sjm199354 * group, so all property values changed in this function must belong 8465440Sjm199354 * to the same property group. Additionally, this operation is done in 8475440Sjm199354 * the context of a repository transaction; on any fatal error, the 8485440Sjm199354 * SCF context will be closed, destroying all SCF objects and aborting 8495440Sjm199354 * the transaction. 8505440Sjm199354 */ 8515440Sjm199354 static int 8525440Sjm199354 vs_scf_values_set(const char *pgname, vs_prop_hd_t *prop_hd) 8535440Sjm199354 { 8545440Sjm199354 int rc, np; 8555440Sjm199354 const vs_propdef_t *vpd; 8565440Sjm199354 uint64_t propid; 8575440Sjm199354 vs_scfctx_t vsc; 8585440Sjm199354 8595440Sjm199354 /* ensure that caller has authorization to refresh service */ 8605440Sjm199354 if ((rc = vs_checkauth(VS_ACTION_AUTH)) != VS_ERR_NONE) 8615440Sjm199354 return (rc); 8625440Sjm199354 8635440Sjm199354 if (vs_scf_ctx_open(&vsc) != 0) { 8645440Sjm199354 vs_scf_ctx_close(&vsc); 8655440Sjm199354 return (VS_ERR_SCF); 8665440Sjm199354 } 8675440Sjm199354 8685440Sjm199354 if (scf_instance_get_pg(vsc.vscf_inst, pgname, vsc.vscf_pgroup) == -1) { 8695440Sjm199354 vs_scf_ctx_close(&vsc); 8705440Sjm199354 rc = scf_error(); 8715440Sjm199354 if (strcmp(pgname, "VS_PGNAME_GENERAL") != 0) { 8725440Sjm199354 if ((rc == SCF_ERROR_NOT_FOUND) || 8735440Sjm199354 (rc == SCF_ERROR_INVALID_ARGUMENT)) 8745440Sjm199354 return (VS_ERR_INVALID_SE); 8755440Sjm199354 } 8765440Sjm199354 return (VS_ERR_SCF); 8775440Sjm199354 } 8785440Sjm199354 8795440Sjm199354 if (((vsc.vscf_tx = scf_transaction_create(vsc.vscf_handle)) == NULL) || 8805440Sjm199354 (scf_transaction_start(vsc.vscf_tx, vsc.vscf_pgroup) == -1)) { 8815440Sjm199354 vs_scf_ctx_close(&vsc); 8825440Sjm199354 return (VS_ERR_SCF); 8835440Sjm199354 } 8845440Sjm199354 8855440Sjm199354 /* Process the value change for each specified property */ 8865440Sjm199354 rc = 0; 8875440Sjm199354 np = 0; 8885440Sjm199354 for (propid = 1LL; propid <= VS_PROPID_MAX; propid <<= 1) { 8895440Sjm199354 if ((prop_hd->vp_ids & propid) == 0) 8905440Sjm199354 continue; 8915440Sjm199354 8925440Sjm199354 if ((vpd = vs_get_propdef(propid)) == NULL) { 8935440Sjm199354 rc = VS_ERR_INVALID_PROPERTY; 8945440Sjm199354 break; 8955440Sjm199354 } 8965440Sjm199354 8975440Sjm199354 vsc.vscf_val[np] = scf_value_create(vsc.vscf_handle); 8985440Sjm199354 vsc.vscf_ent[np] = scf_entry_create(vsc.vscf_handle); 8995440Sjm199354 9005440Sjm199354 if (vsc.vscf_val[np] == NULL || vsc.vscf_ent[np] == NULL) { 9015440Sjm199354 rc = VS_ERR_SCF; 9025440Sjm199354 break; 9035440Sjm199354 } 9045440Sjm199354 9055440Sjm199354 if ((rc = scf_transaction_property_change(vsc.vscf_tx, 9065440Sjm199354 vsc.vscf_ent[np], vpd->vpd_name, vpd->vpd_type)) == -1) { 9075440Sjm199354 rc = scf_transaction_property_new(vsc.vscf_tx, 9085440Sjm199354 vsc.vscf_ent[np], vpd->vpd_name, vpd->vpd_type); 9095440Sjm199354 } 9105440Sjm199354 if (rc == -1) { 9115440Sjm199354 rc = VS_ERR_SCF; 9125440Sjm199354 break; 9135440Sjm199354 } 9145440Sjm199354 9155440Sjm199354 if ((rc = vs_scf_set(vpd, prop_hd, &vsc, np)) != VS_ERR_NONE) 9165440Sjm199354 break; 9175440Sjm199354 9185440Sjm199354 ++np; 9195440Sjm199354 } 9205440Sjm199354 9215440Sjm199354 if (rc != VS_ERR_NONE) { 9225440Sjm199354 vs_scf_ctx_close(&vsc); 9235440Sjm199354 return (rc); 9245440Sjm199354 } 9255440Sjm199354 9265440Sjm199354 /* Commit the transaction */ 9275440Sjm199354 if (scf_transaction_commit(vsc.vscf_tx) == -1) { 9285440Sjm199354 vs_scf_ctx_close(&vsc); 9295440Sjm199354 return (VS_ERR_SCF); 9305440Sjm199354 } 9315440Sjm199354 vs_scf_ctx_close(&vsc); 9325440Sjm199354 9335440Sjm199354 /* Notify the daemon that things have changed */ 9345440Sjm199354 if ((smf_refresh_instance(VS_INSTANCE_FMRI)) == -1) 9355440Sjm199354 return (VS_ERR_SCF); 9365440Sjm199354 9375440Sjm199354 return (VS_ERR_NONE); 9385440Sjm199354 } 9395440Sjm199354 9405440Sjm199354 9415440Sjm199354 /* 9425440Sjm199354 * vs_scf_set 9435440Sjm199354 * 9445440Sjm199354 * Stores a single value from the appropriate vscan property structure 9455440Sjm199354 * member into the repository. 9465440Sjm199354 * 9475440Sjm199354 * Values are set in the SCF value object, then the value object 9485440Sjm199354 * is added to the SCF property object. 9495440Sjm199354 */ 9505440Sjm199354 static int 9515440Sjm199354 vs_scf_set(const vs_propdef_t *vpd, vs_prop_hd_t *prop_hd, 9525440Sjm199354 vs_scfctx_t *vsc, int idx) 9535440Sjm199354 { 9545440Sjm199354 int rc; 9555440Sjm199354 vs_props_t *vp = &prop_hd->vp_gen; 9565440Sjm199354 vs_props_se_t *vep = &prop_hd->vp_se; 9575440Sjm199354 9585440Sjm199354 if ((rc = vs_validate(prop_hd, vpd->vpd_id)) != VS_ERR_NONE) 9595440Sjm199354 return (rc); 9605440Sjm199354 9615440Sjm199354 rc = VS_ERR_NONE; 9625440Sjm199354 switch (vpd->vpd_id) { 9635440Sjm199354 case VS_PROPID_MAXSIZE: 9645440Sjm199354 if ((scf_value_set_astring(vsc->vscf_val[idx], 9655440Sjm199354 vp->vp_maxsize)) == -1) { 9665440Sjm199354 rc = VS_ERR_SCF; 9675440Sjm199354 } 9685440Sjm199354 break; 9695440Sjm199354 case VS_PROPID_MAXSIZE_ACTION: 9705440Sjm199354 scf_value_set_boolean(vsc->vscf_val[idx], 9715440Sjm199354 (uint8_t)vp->vp_maxsize_action); 9725440Sjm199354 break; 9735440Sjm199354 case VS_PROPID_TYPES: 9745440Sjm199354 if ((scf_value_set_astring(vsc->vscf_val[idx], 9755440Sjm199354 vp->vp_types)) == -1) { 9765440Sjm199354 return (VS_ERR_SCF); 9775440Sjm199354 } 9785440Sjm199354 break; 9795440Sjm199354 case VS_PROPID_SE_ENABLE: 9805440Sjm199354 scf_value_set_boolean(vsc->vscf_val[idx], 9815440Sjm199354 (uint8_t)vep->vep_enable); 9825440Sjm199354 break; 9835440Sjm199354 case VS_PROPID_SE_HOST: 9845440Sjm199354 if ((scf_value_set_from_string(vsc->vscf_val[idx], 9855440Sjm199354 vpd->vpd_type, vep->vep_host)) == -1) { 9865440Sjm199354 rc = VS_ERR_SCF; 9875440Sjm199354 } 9885440Sjm199354 break; 9895440Sjm199354 case VS_PROPID_SE_PORT: 9905440Sjm199354 scf_value_set_integer(vsc->vscf_val[idx], vep->vep_port); 9915440Sjm199354 break; 9925440Sjm199354 case VS_PROPID_SE_MAXCONN: 9935440Sjm199354 scf_value_set_integer(vsc->vscf_val[idx], 9945440Sjm199354 vep->vep_maxconn); 9955440Sjm199354 break; 9965440Sjm199354 case VS_PROPID_VALUE_AUTH: 9975440Sjm199354 if ((scf_value_set_astring(vsc->vscf_val[idx], 9985440Sjm199354 VS_VALUE_AUTH)) == -1) { 9995440Sjm199354 return (VS_ERR_SCF); 10005440Sjm199354 } 10015440Sjm199354 break; 10025440Sjm199354 default: 10035440Sjm199354 break; 10045440Sjm199354 } 10055440Sjm199354 10065440Sjm199354 if ((scf_entry_add_value(vsc->vscf_ent[idx], 10075440Sjm199354 vsc->vscf_val[idx])) == -1) { 10085440Sjm199354 return (VS_ERR_SCF); 10095440Sjm199354 } 10105440Sjm199354 10115440Sjm199354 return (rc); 10125440Sjm199354 } 10135440Sjm199354 10145440Sjm199354 10155440Sjm199354 /* 10165440Sjm199354 * vs_scf_ctx_open 10175440Sjm199354 * 10185440Sjm199354 * Opens an SCF context; creates the minumum SCF objects 10195440Sjm199354 * for use in loading/storing from the SMF repository (meaning 10205440Sjm199354 * vscf_property group data). 10215440Sjm199354 * 10225440Sjm199354 * Other SCF objects in the context may be initialized elsewher 10235440Sjm199354 * subsequent to open, but all initialized structures are destroyed 10245440Sjm199354 * in vs_scf_ctx_close(). 10255440Sjm199354 */ 10265440Sjm199354 static int 10275440Sjm199354 vs_scf_ctx_open(vs_scfctx_t *vsc) 10285440Sjm199354 { 10295440Sjm199354 (void) memset(vsc, 0, sizeof (vs_scfctx_t)); 10305440Sjm199354 10315440Sjm199354 if ((vsc->vscf_handle = scf_handle_create(SCF_VERSION)) == NULL) 10325440Sjm199354 return (VS_ERR_SCF); 10335440Sjm199354 10345440Sjm199354 if (scf_handle_bind(vsc->vscf_handle) == -1) 10355440Sjm199354 return (VS_ERR_SCF); 10365440Sjm199354 10375440Sjm199354 if ((vsc->vscf_inst = scf_instance_create(vsc->vscf_handle)) == NULL) 10385440Sjm199354 return (VS_ERR_SCF); 10395440Sjm199354 10405440Sjm199354 if (scf_handle_decode_fmri(vsc->vscf_handle, VS_INSTANCE_FMRI, 10415440Sjm199354 NULL, NULL, vsc->vscf_inst, NULL, NULL, 10425440Sjm199354 SCF_DECODE_FMRI_EXACT) == -1) { 10435440Sjm199354 return (VS_ERR_SCF); 10445440Sjm199354 } 10455440Sjm199354 10465440Sjm199354 if ((vsc->vscf_pgroup = scf_pg_create(vsc->vscf_handle)) == NULL) 10475440Sjm199354 return (VS_ERR_SCF); 10485440Sjm199354 10495440Sjm199354 return (VS_ERR_NONE); 10505440Sjm199354 } 10515440Sjm199354 10525440Sjm199354 10535440Sjm199354 /* 10545440Sjm199354 * vs_scf_ctx_close 10555440Sjm199354 * 10565440Sjm199354 * Closes an SCF context; destroys all initialized SCF objects. 10575440Sjm199354 */ 10585440Sjm199354 static void 10595440Sjm199354 vs_scf_ctx_close(vs_scfctx_t *vsc) 10605440Sjm199354 { 10615440Sjm199354 int i; 10625440Sjm199354 10635440Sjm199354 for (i = 0; i < VS_NUM_PROPIDS; i++) { 10645440Sjm199354 if (vsc->vscf_val[i]) 10655440Sjm199354 scf_value_destroy(vsc->vscf_val[i]); 10665440Sjm199354 if (vsc->vscf_ent[i]) 10675440Sjm199354 scf_entry_destroy(vsc->vscf_ent[i]); 10685440Sjm199354 if (vsc->vscf_prop[i]) 10695440Sjm199354 scf_property_destroy(vsc->vscf_prop[i]); 10705440Sjm199354 } 10715440Sjm199354 10725440Sjm199354 if (vsc->vscf_iter) 10735440Sjm199354 scf_iter_destroy(vsc->vscf_iter); 10745440Sjm199354 if (vsc->vscf_tx) 10755440Sjm199354 scf_transaction_destroy(vsc->vscf_tx); 10765440Sjm199354 if (vsc->vscf_pgroup) 10775440Sjm199354 scf_pg_destroy(vsc->vscf_pgroup); 10785440Sjm199354 if (vsc->vscf_inst) 10795440Sjm199354 scf_instance_destroy(vsc->vscf_inst); 10805440Sjm199354 if (vsc->vscf_handle) 10815440Sjm199354 scf_handle_destroy(vsc->vscf_handle); 10825440Sjm199354 } 10835440Sjm199354 10845440Sjm199354 10855440Sjm199354 /* 10865440Sjm199354 * vs_validate 10875440Sjm199354 * 10885440Sjm199354 * Validate property identified in propid. 10895440Sjm199354 * 10905440Sjm199354 * Returns: VS_ERR_NONE 10915440Sjm199354 * VS_ERR_INVALID_VALUE 10925440Sjm199354 * VS_ERR_INVALID_PROPERTY 10935440Sjm199354 */ 10945440Sjm199354 static int 10955440Sjm199354 vs_validate(const vs_prop_hd_t *prop_hd, uint64_t propid) 10965440Sjm199354 { 10975440Sjm199354 uint64_t num; 10985440Sjm199354 const vs_props_t *vp = &prop_hd->vp_gen; 10995440Sjm199354 const vs_props_se_t *vep = &prop_hd->vp_se; 11005440Sjm199354 11015440Sjm199354 switch (propid) { 11025440Sjm199354 case VS_PROPID_MAXSIZE: 11035440Sjm199354 if ((vs_strtonum(vp->vp_maxsize, &num) != 0) || (num == 0)) 11045440Sjm199354 return (VS_ERR_INVALID_VALUE); 11055440Sjm199354 break; 11065440Sjm199354 case VS_PROPID_MAXSIZE_ACTION: 11075440Sjm199354 break; 11085440Sjm199354 case VS_PROPID_TYPES: 11095440Sjm199354 if (!vs_is_valid_types(vp->vp_types)) 11105440Sjm199354 return (VS_ERR_INVALID_VALUE); 11115440Sjm199354 break; 11125440Sjm199354 case VS_PROPID_SE_ENABLE: 11135440Sjm199354 break; 11145440Sjm199354 case VS_PROPID_SE_PORT: 11155440Sjm199354 if (vep->vep_port == 0) 11165440Sjm199354 return (VS_ERR_INVALID_VALUE); 11175440Sjm199354 break; 11185440Sjm199354 case VS_PROPID_SE_HOST: 11195440Sjm199354 if (!vs_is_valid_host(vep->vep_host)) 11205440Sjm199354 return (VS_ERR_INVALID_VALUE); 11215440Sjm199354 break; 11225440Sjm199354 case VS_PROPID_SE_MAXCONN: 11235440Sjm199354 if (vep->vep_maxconn < VS_VAL_SE_MAXCONN_MIN || 11245440Sjm199354 vep->vep_maxconn > VS_VAL_SE_MAXCONN_MAX) 11255440Sjm199354 return (VS_ERR_INVALID_VALUE); 11265440Sjm199354 break; 11275440Sjm199354 case VS_PROPID_VALUE_AUTH: 11285440Sjm199354 case VS_PROPID_VLOG: 11295440Sjm199354 break; 11305440Sjm199354 default: 11315440Sjm199354 return (VS_ERR_INVALID_PROPERTY); 11325440Sjm199354 } 11335440Sjm199354 11345440Sjm199354 return (VS_ERR_NONE); 11355440Sjm199354 } 11365440Sjm199354 11375440Sjm199354 11385440Sjm199354 /* 11395440Sjm199354 * vs_props_validate 11405440Sjm199354 * 11415440Sjm199354 * Validate properties identified in propids. 11425440Sjm199354 * 11435440Sjm199354 * Returns: VS_ERR_NONE 11445440Sjm199354 * VS_ERR_INVALID_VALUE 11455440Sjm199354 * VS_ERR_INVALID_PROPERTY 11465440Sjm199354 */ 11475440Sjm199354 int 11485440Sjm199354 vs_props_validate(const vs_props_t *props, uint64_t propids) 11495440Sjm199354 { 11505440Sjm199354 uint64_t propid; 11515440Sjm199354 vs_prop_hd_t prop_hd; 11525440Sjm199354 11535440Sjm199354 if ((propids & VS_PROPID_GEN_ALL) != propids) 11545440Sjm199354 return (VS_ERR_INVALID_PROPERTY); 11555440Sjm199354 11565440Sjm199354 (void) memset(&prop_hd, 0, sizeof (vs_prop_hd_t)); 11575440Sjm199354 prop_hd.vp_gen = *props; 11585440Sjm199354 prop_hd.vp_type = VS_PTYPE_GEN; 11595440Sjm199354 prop_hd.vp_ids = propids; 11605440Sjm199354 prop_hd.vp_all = VS_PROPID_GEN_ALL; 11615440Sjm199354 11625440Sjm199354 for (propid = 1LL; propid <= VS_PROPID_MAX; propid <<= 1) { 11635440Sjm199354 if ((propids & propid) == 0) 11645440Sjm199354 continue; 11655440Sjm199354 11665440Sjm199354 if (vs_validate(&prop_hd, propid) != VS_ERR_NONE) 11675440Sjm199354 return (VS_ERR_INVALID_VALUE); 11685440Sjm199354 } 11695440Sjm199354 11705440Sjm199354 return (VS_ERR_NONE); 11715440Sjm199354 } 11725440Sjm199354 11735440Sjm199354 11745440Sjm199354 /* 11755440Sjm199354 * vs_props_se_validate 11765440Sjm199354 * 11775440Sjm199354 * Validate properties identified in propids. 11785440Sjm199354 * 11795440Sjm199354 * Returns: VS_ERR_NONE 11805440Sjm199354 * VS_ERR_INVALID_VALUE 11815440Sjm199354 * VS_ERR_INVALID_PROPERTY 11825440Sjm199354 */ 11835440Sjm199354 int 11845440Sjm199354 vs_props_se_validate(const vs_props_se_t *se_props, uint64_t propids) 11855440Sjm199354 { 11865440Sjm199354 uint64_t propid; 11875440Sjm199354 vs_prop_hd_t prop_hd; 11885440Sjm199354 11895440Sjm199354 if ((propids & VS_PROPID_SE_ALL) != propids) 11905440Sjm199354 return (VS_ERR_INVALID_PROPERTY); 11915440Sjm199354 11925440Sjm199354 (void) memset(&prop_hd, 0, sizeof (vs_prop_hd_t)); 11935440Sjm199354 prop_hd.vp_se = *se_props; 11945440Sjm199354 prop_hd.vp_type = VS_PTYPE_SE; 11955440Sjm199354 prop_hd.vp_ids = propids; 11965440Sjm199354 prop_hd.vp_all = VS_PROPID_SE_ALL; 11975440Sjm199354 11985440Sjm199354 for (propid = 1LL; propid <= VS_PROPID_MAX; propid <<= 1) { 11995440Sjm199354 if ((propids & propid) == 0) 12005440Sjm199354 continue; 12015440Sjm199354 12025440Sjm199354 if (vs_validate(&prop_hd, propid) != VS_ERR_NONE) 12035440Sjm199354 return (VS_ERR_INVALID_VALUE); 12045440Sjm199354 } 12055440Sjm199354 12065440Sjm199354 return (VS_ERR_NONE); 12075440Sjm199354 } 12085440Sjm199354 12095440Sjm199354 12105440Sjm199354 /* 12115440Sjm199354 * vs_is_valid_types 12125440Sjm199354 * 12135440Sjm199354 * Checks that types property is a valid format: 12145440Sjm199354 * - doesn't exceed VS_VAL_TYPES_MAX 12155440Sjm199354 * - doesn't contain VS_VAL_TYPES_INVALID_CHARS 12165440Sjm199354 * - is correctly formatted - passes the parsing tests 12175440Sjm199354 * 12185440Sjm199354 * Returns 1 on success, 0 on failure 12195440Sjm199354 */ 12205440Sjm199354 static int 12215440Sjm199354 vs_is_valid_types(const char *types) 12225440Sjm199354 { 12235440Sjm199354 char buf[VS_VAL_TYPES_LEN]; 12245440Sjm199354 uint32_t len = VS_VAL_TYPES_LEN; 12255440Sjm199354 12265440Sjm199354 if (strlen(types) > VS_VAL_TYPES_LEN) 12275440Sjm199354 return (0); 12285440Sjm199354 12295440Sjm199354 if (strpbrk(types, VS_VAL_TYPES_INVALID_CHARS) != NULL) 12305440Sjm199354 return (0); 12315440Sjm199354 12325440Sjm199354 if (vs_parse_types(types, buf, &len) != 0) 12335440Sjm199354 return (0); 12345440Sjm199354 12355440Sjm199354 return (1); 12365440Sjm199354 } 12375440Sjm199354 12385440Sjm199354 12395440Sjm199354 /* 12405440Sjm199354 * vs_is_valid_host 12415440Sjm199354 * 12425440Sjm199354 * Returns 1 on success, 0 on failure 12435440Sjm199354 */ 12445440Sjm199354 static int 12455440Sjm199354 vs_is_valid_host(const char *host) 12465440Sjm199354 { 12475440Sjm199354 long naddr; 12485440Sjm199354 const char *p; 12495440Sjm199354 12505440Sjm199354 if (!host || *host == '\0') 12515440Sjm199354 return (0); 12525440Sjm199354 12535440Sjm199354 if ('0' <= host[0] && host[0] <= '9') { 12545440Sjm199354 /* ip address */ 12555440Sjm199354 if ((inet_pton(AF_INET, host, &naddr)) == 0) 12565440Sjm199354 return (0); 12575440Sjm199354 if ((naddr & IN_CLASSA_NET) == 0) 12585440Sjm199354 return (0); 12595440Sjm199354 if ((naddr & IN_CLASSC_HOST) == 0) 12605440Sjm199354 return (0); 12615440Sjm199354 } else { 12625440Sjm199354 /* hostname */ 12635440Sjm199354 p = host; 12645440Sjm199354 while (*p != '\0') { 12655440Sjm199354 if (!isascii(*p)) 12665440Sjm199354 return (0); 12675440Sjm199354 12685440Sjm199354 if (isalnum(*p) || 12695440Sjm199354 (*p == '.') || (*p == '-') || (*p == '_')) { 12705440Sjm199354 ++p; 12715440Sjm199354 } else { 12725440Sjm199354 return (0); 12735440Sjm199354 } 12745440Sjm199354 } 12755440Sjm199354 } 12765440Sjm199354 12775440Sjm199354 return (1); 12785440Sjm199354 } 12795440Sjm199354 12805440Sjm199354 12815440Sjm199354 /* 12825440Sjm199354 * vs_parse_types 12835440Sjm199354 * 12845440Sjm199354 * Replace comma separators with '\0'. 12855440Sjm199354 * 12865440Sjm199354 * Types contains comma separated rules each beginning with +|- 12875440Sjm199354 * - embedded commas are escaped by backslash 12885440Sjm199354 * - backslash is escaped by backslash 12895440Sjm199354 * - a single backslash not followed by comma is illegal 12905440Sjm199354 * 12915440Sjm199354 * On entry to the function len must contain the length of 12925440Sjm199354 * the buffer. On sucecssful exit len will contain the length 12935440Sjm199354 * of the parsed data within the buffer. 12945440Sjm199354 * 12955440Sjm199354 * Returns 0 on success, -1 on failure 12965440Sjm199354 */ 12975440Sjm199354 int 12985440Sjm199354 vs_parse_types(const char *types, char *buf, uint32_t *len) 12995440Sjm199354 { 13005440Sjm199354 char *p = (char *)types; 13015440Sjm199354 char *b = buf; 13025440Sjm199354 13035440Sjm199354 if (strlen(types) > *len) 13045440Sjm199354 return (-1); 13055440Sjm199354 13065440Sjm199354 if (strchr(VS_TYPES_RULES, *p) == NULL) 13075440Sjm199354 return (-1); 13085440Sjm199354 13095440Sjm199354 (void) memset(buf, 0, *len); 13105440Sjm199354 13115440Sjm199354 while (*p) { 13125440Sjm199354 switch (*p) { 13135440Sjm199354 case VS_TYPES_SEP: 13145440Sjm199354 if (*(p + 1) && 13155440Sjm199354 (strchr(VS_TYPES_RULES, *(p + 1))) == NULL) 13165440Sjm199354 return (-1); 13175440Sjm199354 *b = '\0'; 13185440Sjm199354 break; 13195440Sjm199354 case VS_TYPES_ESCAPE: 13205440Sjm199354 ++p; 13215440Sjm199354 if (*p == VS_TYPES_ESCAPE || *p == VS_TYPES_SEP) 13225440Sjm199354 *b = *p; 13235440Sjm199354 else 13245440Sjm199354 return (-1); 13255440Sjm199354 break; 13265440Sjm199354 default: 13275440Sjm199354 *b = *p; 13285440Sjm199354 } 13295440Sjm199354 ++p; 13305440Sjm199354 ++b; 13315440Sjm199354 } 13325440Sjm199354 13335440Sjm199354 *len = (b - buf) + 1; 13345440Sjm199354 13355440Sjm199354 return (0); 13365440Sjm199354 } 13375440Sjm199354 13385440Sjm199354 13395440Sjm199354 /* 13405440Sjm199354 * vs_statistics 13415440Sjm199354 */ 13425440Sjm199354 int 13435440Sjm199354 vs_statistics(vs_stats_t *stats) 13445440Sjm199354 { 13455440Sjm199354 int door_fd, rc = VS_ERR_NONE; 13465440Sjm199354 vs_stats_req_t *req; 1347*6407Sjm199354 vs_stats_rsp_t *rsp; 13485440Sjm199354 door_arg_t arg; 13495440Sjm199354 13505440Sjm199354 if ((req = calloc(1, sizeof (vs_stats_req_t))) == NULL) 13515440Sjm199354 return (VS_ERR_SYS); 13525440Sjm199354 1353*6407Sjm199354 if ((rsp = calloc(1, sizeof (vs_stats_rsp_t))) == NULL) { 13545440Sjm199354 free(req); 13555440Sjm199354 return (VS_ERR_SYS); 13565440Sjm199354 } 13575440Sjm199354 13585440Sjm199354 if ((door_fd = open(VS_STATS_DOOR_NAME, O_RDONLY)) < 0) { 13595440Sjm199354 free(req); 1360*6407Sjm199354 free(rsp); 13615440Sjm199354 return (VS_ERR_DAEMON_COMM); 13625440Sjm199354 } 13635440Sjm199354 1364*6407Sjm199354 req->vsr_magic = VS_STATS_DOOR_MAGIC; 1365*6407Sjm199354 req->vsr_id = VS_STATS_GET; 13665440Sjm199354 13675440Sjm199354 arg.data_ptr = (char *)req; 13685440Sjm199354 arg.data_size = sizeof (vs_stats_req_t); 13695440Sjm199354 arg.desc_ptr = NULL; 13705440Sjm199354 arg.desc_num = 0; 1371*6407Sjm199354 arg.rbuf = (char *)rsp; 1372*6407Sjm199354 arg.rsize = sizeof (vs_stats_rsp_t); 13735440Sjm199354 1374*6407Sjm199354 if ((door_call(door_fd, &arg) < 0) || 1375*6407Sjm199354 (rsp->vsr_magic != VS_STATS_DOOR_MAGIC)) { 13765440Sjm199354 rc = VS_ERR_DAEMON_COMM; 1377*6407Sjm199354 } else { 1378*6407Sjm199354 *stats = rsp->vsr_stats; 1379*6407Sjm199354 } 13805440Sjm199354 13815440Sjm199354 (void) close(door_fd); 13825440Sjm199354 13835440Sjm199354 free(req); 1384*6407Sjm199354 free(rsp); 13855440Sjm199354 return (rc); 13865440Sjm199354 } 13875440Sjm199354 13885440Sjm199354 13895440Sjm199354 /* 13905440Sjm199354 * vs_statistics_reset 13915440Sjm199354 */ 13925440Sjm199354 int 13935440Sjm199354 vs_statistics_reset() 13945440Sjm199354 { 13955440Sjm199354 int door_fd, rc; 13965440Sjm199354 vs_stats_req_t *req; 13975440Sjm199354 door_arg_t arg; 13985440Sjm199354 13995440Sjm199354 /* ensure that caller has authorization to reset stats */ 14005440Sjm199354 if ((rc = vs_checkauth(VS_VALUE_AUTH)) != VS_ERR_NONE) 14015440Sjm199354 return (rc); 14025440Sjm199354 14035440Sjm199354 if ((req = calloc(1, sizeof (vs_stats_req_t))) == NULL) 14045440Sjm199354 return (VS_ERR_SYS); 14055440Sjm199354 14065440Sjm199354 if ((door_fd = open(VS_STATS_DOOR_NAME, O_RDONLY)) < 0) { 14075440Sjm199354 free(req); 14085440Sjm199354 return (VS_ERR_DAEMON_COMM); 14095440Sjm199354 } 14105440Sjm199354 1411*6407Sjm199354 req->vsr_magic = VS_STATS_DOOR_MAGIC; 1412*6407Sjm199354 req->vsr_id = VS_STATS_RESET; 14135440Sjm199354 14145440Sjm199354 arg.data_ptr = (char *)req; 14155440Sjm199354 arg.data_size = sizeof (vs_stats_req_t); 14165440Sjm199354 arg.desc_ptr = NULL; 14175440Sjm199354 arg.desc_num = 0; 14185440Sjm199354 arg.rbuf = NULL; 14195440Sjm199354 arg.rsize = 0; 14205440Sjm199354 14215440Sjm199354 if (door_call(door_fd, &arg) < 0) 14225440Sjm199354 rc = VS_ERR_DAEMON_COMM; 14235440Sjm199354 else 14245440Sjm199354 rc = VS_ERR_NONE; 14255440Sjm199354 14265440Sjm199354 (void) close(door_fd); 14275440Sjm199354 free(req); 14285440Sjm199354 return (rc); 14295440Sjm199354 } 14305440Sjm199354 14315440Sjm199354 14325440Sjm199354 /* 14335440Sjm199354 * vs_checkauth 14345440Sjm199354 */ 14355440Sjm199354 static int 14365440Sjm199354 vs_checkauth(char *auth) 14375440Sjm199354 { 14385440Sjm199354 struct passwd *pw; 14395440Sjm199354 uid_t uid; 14405440Sjm199354 14415440Sjm199354 uid = getuid(); 14425440Sjm199354 14435440Sjm199354 if ((pw = getpwuid(uid)) == NULL) 14445440Sjm199354 return (VS_ERR_SYS); 14455440Sjm199354 14465440Sjm199354 if (chkauthattr(auth, pw->pw_name) != 1) { 14475440Sjm199354 return (VS_ERR_AUTH); 14485440Sjm199354 } 14495440Sjm199354 14505440Sjm199354 return (VS_ERR_NONE); 14515440Sjm199354 } 14525440Sjm199354 14535440Sjm199354 14545440Sjm199354 /* 14555440Sjm199354 * vs_props_get_engines 1456*6407Sjm199354 * 14575440Sjm199354 * On input, count specifies the maximum number of engine ids to 14585440Sjm199354 * return. engids must be an array with count entries. 14595440Sjm199354 * On return, count specifies the number of engine ids being 14605440Sjm199354 * returned in engids. 1461*6407Sjm199354 * 1462*6407Sjm199354 * Caller is responsible for free'ing the engids allocated herein. 14635440Sjm199354 */ 14645440Sjm199354 static int 1465*6407Sjm199354 vs_props_get_engines(char *engids[], int *count) 14665440Sjm199354 { 1467*6407Sjm199354 int i, prefix_len; 1468*6407Sjm199354 char pgname[VS_PGNAME_ENGINE_LEN]; 14695440Sjm199354 vs_scfctx_t vsc; 14705440Sjm199354 14715440Sjm199354 14725440Sjm199354 if (((vs_scf_ctx_open(&vsc)) != 0) || 14735440Sjm199354 ((vsc.vscf_iter = scf_iter_create(vsc.vscf_handle)) == NULL) || 14745440Sjm199354 (scf_iter_instance_pgs_typed(vsc.vscf_iter, vsc.vscf_inst, 14755440Sjm199354 SCF_GROUP_APPLICATION) != 0)) { 14765440Sjm199354 vs_scf_ctx_close(&vsc); 14775440Sjm199354 return (VS_ERR_SCF); 14785440Sjm199354 } 14795440Sjm199354 1480*6407Sjm199354 for (i = 0; i < *count; i++) 1481*6407Sjm199354 engids[i] = NULL; 1482*6407Sjm199354 1483*6407Sjm199354 i = 0; 1484*6407Sjm199354 prefix_len = sizeof (VS_PGNAME_ENGINE_PREFIX) - 1; 1485*6407Sjm199354 14865440Sjm199354 while ((i < VS_SE_MAX) && 14875440Sjm199354 (scf_iter_next_pg(vsc.vscf_iter, vsc.vscf_pgroup) == 1)) { 1488*6407Sjm199354 if (scf_pg_get_name(vsc.vscf_pgroup, pgname, 1489*6407Sjm199354 VS_PGNAME_ENGINE_LEN) < 0) { 14905440Sjm199354 vs_scf_ctx_close(&vsc); 14915440Sjm199354 return (VS_ERR_SCF); 14925440Sjm199354 } 14935440Sjm199354 1494*6407Sjm199354 if (strncmp(pgname, VS_PGNAME_ENGINE_PREFIX, prefix_len) == 0) { 1495*6407Sjm199354 if ((engids[i] = strdup(pgname + prefix_len)) != NULL) { 1496*6407Sjm199354 if (++i == *count) 1497*6407Sjm199354 break; 1498*6407Sjm199354 } 1499*6407Sjm199354 } 15005440Sjm199354 } 15015440Sjm199354 vs_scf_ctx_close(&vsc); 15025440Sjm199354 15035440Sjm199354 *count = i; 15045440Sjm199354 return (VS_ERR_NONE); 15055440Sjm199354 } 15065440Sjm199354 15075440Sjm199354 15085440Sjm199354 /* 15095440Sjm199354 * vs_scf_pg_count 15105440Sjm199354 */ 15115440Sjm199354 static int 15125440Sjm199354 vs_scf_pg_count(void) 15135440Sjm199354 { 15145440Sjm199354 int count = 0; 15155440Sjm199354 vs_scfctx_t vsc; 15165440Sjm199354 15175440Sjm199354 if ((vs_scf_ctx_open(&vsc) != 0) || 15185440Sjm199354 ((vsc.vscf_iter = scf_iter_create(vsc.vscf_handle)) == NULL) || 15195440Sjm199354 (scf_iter_instance_pgs_typed(vsc.vscf_iter, vsc.vscf_inst, 15205440Sjm199354 SCF_GROUP_APPLICATION) != 0)) { 15215440Sjm199354 vs_scf_ctx_close(&vsc); 15225440Sjm199354 return (-1); 15235440Sjm199354 } 15245440Sjm199354 15255440Sjm199354 while (scf_iter_next_pg(vsc.vscf_iter, vsc.vscf_pgroup) == 1) 15265440Sjm199354 ++count; 15275440Sjm199354 15285440Sjm199354 vs_scf_ctx_close(&vsc); 15295440Sjm199354 15305440Sjm199354 return (count); 15315440Sjm199354 } 15325440Sjm199354 15335440Sjm199354 15345440Sjm199354 /* 1535*6407Sjm199354 * vs_engid_to_pgname 1536*6407Sjm199354 * 1537*6407Sjm199354 * To convert an engine id (engid) to a property group name (pgname), 1538*6407Sjm199354 * the engine id is prefixed with VS_PGNAME_ENGINE_PREFIX. 1539*6407Sjm199354 */ 1540*6407Sjm199354 static void 1541*6407Sjm199354 vs_engid_to_pgname(const char *engid, char pgname[VS_PGNAME_ENGINE_LEN]) 1542*6407Sjm199354 { 1543*6407Sjm199354 (void) snprintf(pgname, VS_PGNAME_ENGINE_LEN, "%s%s", 1544*6407Sjm199354 VS_PGNAME_ENGINE_PREFIX, engid); 1545*6407Sjm199354 } 1546*6407Sjm199354 1547*6407Sjm199354 1548*6407Sjm199354 /* 15495440Sjm199354 * vs_strtonum 15505440Sjm199354 * 15515440Sjm199354 * Converts a size string in the format into an integer. 15525440Sjm199354 * 15535440Sjm199354 * A size string is a numeric value followed by an optional unit 15545440Sjm199354 * specifier which is used as a multiplier to calculate a raw 15555440Sjm199354 * number. 15565440Sjm199354 * The size string format is: N[.N][KMGTP][B] 15575440Sjm199354 * 15585440Sjm199354 * The numeric value can contain a decimal portion. Unit specifiers 15595440Sjm199354 * are either a one-character or two-character string; i.e. "K" or 15605440Sjm199354 * "KB" for kilobytes. Unit specifiers must follow the numeric portion 15615440Sjm199354 * immediately, and are not case-sensitive. 15625440Sjm199354 * 15635440Sjm199354 * If either "B" is specified, or there is no unit specifier portion 15645440Sjm199354 * in the string, the numeric value is calculated with no multiplier 15655440Sjm199354 * (assumes a basic unit of "bytes"). 15665440Sjm199354 * 15675440Sjm199354 * Returns: 15685440Sjm199354 * -1: Failure; errno set to specify the error. 15695440Sjm199354 * 0: Success. 15705440Sjm199354 */ 15715440Sjm199354 int 15725440Sjm199354 vs_strtonum(const char *value, uint64_t *num) 15735440Sjm199354 { 15745440Sjm199354 char *end; 15755440Sjm199354 int shift; 15765440Sjm199354 double fval; 15775440Sjm199354 15785440Sjm199354 *num = 0; 15795440Sjm199354 15805440Sjm199354 /* Check to see if this looks like a number. */ 15815440Sjm199354 if ((value[0] < '0' || value[0] > '9') && value[0] != '.') { 15825440Sjm199354 errno = EINVAL; 15835440Sjm199354 return (-1); 15845440Sjm199354 } 15855440Sjm199354 15865440Sjm199354 /* Rely on stroll() to process the numeric portion. */ 15875440Sjm199354 errno = 0; 15885440Sjm199354 *num = strtoll(value, &end, 10); 15895440Sjm199354 15905440Sjm199354 /* 15915440Sjm199354 * Check for ERANGE, which indicates that the value is too large to 15925440Sjm199354 * fit in a 64-bit value. 15935440Sjm199354 */ 15945440Sjm199354 if (errno != 0) 15955440Sjm199354 return (-1); 15965440Sjm199354 15975440Sjm199354 /* 15985440Sjm199354 * If we have a decimal value, then do the computation with floating 15995440Sjm199354 * point arithmetic. Otherwise, use standard arithmetic. 16005440Sjm199354 */ 16015440Sjm199354 if (*end == '.') { 16025440Sjm199354 fval = strtod(value, &end); 16035440Sjm199354 16045440Sjm199354 if ((shift = vs_strtoshift(end)) == -1) 16055440Sjm199354 return (-1); /* errno set */ 16065440Sjm199354 16075440Sjm199354 fval *= pow(2, shift); 16085440Sjm199354 if (fval > UINT64_MAX) { 16095440Sjm199354 errno = ERANGE; 16105440Sjm199354 return (-1); 16115440Sjm199354 } 16125440Sjm199354 16135440Sjm199354 *num = (uint64_t)fval; 16145440Sjm199354 } else { 16155440Sjm199354 if ((shift = vs_strtoshift(end)) == -1) 16165440Sjm199354 return (-1); /* errno set */ 16175440Sjm199354 16185440Sjm199354 /* Check for overflow */ 16195440Sjm199354 if (shift >= 64 || (*num << shift) >> shift != *num) { 16205440Sjm199354 errno = ERANGE; 16215440Sjm199354 return (-1); 16225440Sjm199354 } 16235440Sjm199354 16245440Sjm199354 *num <<= shift; 16255440Sjm199354 } 16265440Sjm199354 16275440Sjm199354 return (0); 16285440Sjm199354 } 16295440Sjm199354 16305440Sjm199354 16315440Sjm199354 /* 16325440Sjm199354 * vs_strtoshift 16335440Sjm199354 * 16345440Sjm199354 * Converts a unit specifier string into a number of bits that 16355440Sjm199354 * a numeric value must be shifted. 16365440Sjm199354 * 16375440Sjm199354 * Returns: 16385440Sjm199354 * -1: Failure; errno set to specify the error. 16395440Sjm199354 * >-1: Success; the shift count. 16405440Sjm199354 * 16415440Sjm199354 */ 16425440Sjm199354 static int 16435440Sjm199354 vs_strtoshift(const char *buf) 16445440Sjm199354 { 16455440Sjm199354 const char *ends = "BKMGTPEZ"; 16465440Sjm199354 int i; 16475440Sjm199354 16485440Sjm199354 if (buf[0] == '\0') 16495440Sjm199354 return (0); 16505440Sjm199354 for (i = 0; i < strlen(ends); i++) { 16515440Sjm199354 if (toupper(buf[0]) == ends[i]) 16525440Sjm199354 break; 16535440Sjm199354 } 16545440Sjm199354 if (i == strlen(ends)) { 16555440Sjm199354 errno = EINVAL; 16565440Sjm199354 return (-1); 16575440Sjm199354 } 16585440Sjm199354 16595440Sjm199354 /* Allow trailing 'b' characters except in the case of 'BB'. */ 16605440Sjm199354 if (buf[1] == '\0' || (toupper(buf[1]) == 'B' && buf[2] == '\0' && 16615440Sjm199354 toupper(buf[0]) != 'B')) { 16625440Sjm199354 return (10 * i); 16635440Sjm199354 } 16645440Sjm199354 16655440Sjm199354 errno = EINVAL; 16665440Sjm199354 return (-1); 16675440Sjm199354 } 1668