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 /* 226407Sjm199354 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 235440Sjm199354 * Use is subject to license terms. 245440Sjm199354 */ 255440Sjm199354 265440Sjm199354 #include <string.h> 275440Sjm199354 #include <stdio.h> 285440Sjm199354 #include <stdlib.h> 295440Sjm199354 #include <unistd.h> 305440Sjm199354 #include <ctype.h> 315440Sjm199354 #include <math.h> 325440Sjm199354 #include <limits.h> 335440Sjm199354 #include <libscf.h> 345440Sjm199354 #include <errno.h> 355440Sjm199354 #include <fcntl.h> 365440Sjm199354 #include <door.h> 375440Sjm199354 #include <pwd.h> 385440Sjm199354 #include <auth_attr.h> 395440Sjm199354 #include <secdb.h> 405440Sjm199354 #include <sys/socket.h> 415440Sjm199354 #include <arpa/inet.h> 425440Sjm199354 #include <libintl.h> 435440Sjm199354 #include <libvscan.h> 445440Sjm199354 45*7943Samw@Sun.COM #define VS_DOOR_CALL_RETRIES 3 46*7943Samw@Sun.COM 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" 516407Sjm199354 #define VS_PGNAME_ENGINE_PREFIX "vs_engine_" 526407Sjm199354 #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 *); 1696407Sjm199354 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 *); 178*7943Samw@Sun.COM static int vs_door_call(int, door_arg_t *); 1795440Sjm199354 1806407Sjm199354 static int vs_props_get_engines(char *[], int *); 1816407Sjm199354 static void vs_engid_to_pgname(const char *, char [VS_PGNAME_ENGINE_LEN]); 1825440Sjm199354 static int vs_scf_pg_count(void); 1835440Sjm199354 static int vs_strtoshift(const char *); 1845440Sjm199354 1855440Sjm199354 1865440Sjm199354 /* 1875440Sjm199354 * vs_props_get_all 1885440Sjm199354 * 1895440Sjm199354 * Retrieves the general service properties and all properties 1905440Sjm199354 * for all scan engines from the repository. 1915440Sjm199354 * 1925440Sjm199354 * If invalid property values are found, the values are corrected to 1935440Sjm199354 * the default value. 1945440Sjm199354 * 1955440Sjm199354 * Return codes: 1965440Sjm199354 * VS_ERR_VS_ERR_NONE 1975440Sjm199354 * VS_ERR_SCF 1985440Sjm199354 * VS_ERR_SYS 1995440Sjm199354 */ 2005440Sjm199354 int 2015440Sjm199354 vs_props_get_all(vs_props_all_t *va) 2025440Sjm199354 { 2035440Sjm199354 int i, rc, n; 2046407Sjm199354 char *engids[VS_SE_MAX]; 2055440Sjm199354 2065440Sjm199354 (void) memset(va, 0, sizeof (vs_props_all_t)); 2075440Sjm199354 if ((rc = vs_props_get(&va->va_props, VS_PROPID_GEN_ALL)) 2085440Sjm199354 != VS_ERR_NONE) 2095440Sjm199354 return (rc); 2105440Sjm199354 2115440Sjm199354 n = VS_SE_MAX; 2125440Sjm199354 if ((rc = vs_props_get_engines(engids, &n)) != VS_ERR_NONE) 2135440Sjm199354 return (rc); 2145440Sjm199354 2155440Sjm199354 for (i = 0; i < n; i++) { 2166407Sjm199354 if ((rc = vs_props_se_get(engids[i], 2176407Sjm199354 &va->va_se[i], VS_PROPID_SE_ALL)) != VS_ERR_NONE) 2186407Sjm199354 break; 2195440Sjm199354 } 2205440Sjm199354 2216407Sjm199354 /* free engids allocated in vs_props_get_engines */ 2226407Sjm199354 for (i = 0; i < VS_SE_MAX; i++) { 2236407Sjm199354 if (engids[i] != NULL) 2246407Sjm199354 free(engids[i]); 2256407Sjm199354 } 2266407Sjm199354 2276407Sjm199354 return (rc); 2285440Sjm199354 } 2295440Sjm199354 2305440Sjm199354 2315440Sjm199354 /* 2325440Sjm199354 * vs_props_get 2335440Sjm199354 * 2345440Sjm199354 * Retrieves values for the specified general service properties from 2355440Sjm199354 * the repository. 2365440Sjm199354 * 2375440Sjm199354 * If invalid property values are found, the values are corrected to 2385440Sjm199354 * the default value. 2395440Sjm199354 * 2405440Sjm199354 * Return codes: 2415440Sjm199354 * VS_ERR_VS_ERR_NONE 2425440Sjm199354 * VS_ERR_INVALID_PROPERTY 2435440Sjm199354 * VS_ERR_SCF 2445440Sjm199354 * VS_ERR_SYS 2455440Sjm199354 */ 2465440Sjm199354 int 2475440Sjm199354 vs_props_get(vs_props_t *vp, uint64_t propids) 2485440Sjm199354 { 2495440Sjm199354 int rc; 2505440Sjm199354 vs_prop_hd_t prop_hd; 2515440Sjm199354 2525440Sjm199354 if ((propids & VS_PROPID_GEN_ALL) != propids) 2535440Sjm199354 return (VS_ERR_INVALID_PROPERTY); 2545440Sjm199354 2555440Sjm199354 (void) memset(&prop_hd, 0, sizeof (vs_prop_hd_t)); 2565440Sjm199354 prop_hd.vp_type = VS_PTYPE_GEN; 2575440Sjm199354 prop_hd.vp_ids = propids; 2585440Sjm199354 prop_hd.vp_all = VS_PROPID_GEN_ALL; 2595440Sjm199354 2605440Sjm199354 rc = vs_scf_values_get(VS_PGNAME_GENERAL, &prop_hd); 2615440Sjm199354 2625440Sjm199354 *vp = prop_hd.vp_gen; 2635440Sjm199354 return (rc); 2645440Sjm199354 } 2655440Sjm199354 2665440Sjm199354 2675440Sjm199354 /* 2685440Sjm199354 * vs_props_set 2695440Sjm199354 * 2705440Sjm199354 * Changes values for the specified general service properties 2715440Sjm199354 * in the repository. 2725440Sjm199354 * 2735440Sjm199354 * Return codes: 2745440Sjm199354 * VS_ERR_VS_ERR_NONE 2755440Sjm199354 * VS_ERR_INVALID_PROPERTY 2765440Sjm199354 * VS_ERR_INVALID_VALUE 2775440Sjm199354 * VS_ERR_SCF 2785440Sjm199354 * VS_ERR_SYS 2795440Sjm199354 */ 2805440Sjm199354 int 2815440Sjm199354 vs_props_set(const vs_props_t *vp, uint64_t propids) 2825440Sjm199354 { 2835440Sjm199354 vs_prop_hd_t prop_hd; 2845440Sjm199354 2855440Sjm199354 if ((propids & VS_PROPID_GEN_ALL) != propids) 2865440Sjm199354 return (VS_ERR_INVALID_PROPERTY); 2875440Sjm199354 2885440Sjm199354 (void) memset(&prop_hd, 0, sizeof (vs_prop_hd_t)); 2895440Sjm199354 prop_hd.vp_type = VS_PTYPE_GEN; 2905440Sjm199354 prop_hd.vp_ids = propids; 2915440Sjm199354 prop_hd.vp_all = VS_PROPID_GEN_ALL; 2925440Sjm199354 prop_hd.vp_gen = *vp; 2935440Sjm199354 return (vs_scf_values_set(VS_PGNAME_GENERAL, &prop_hd)); 2945440Sjm199354 } 2955440Sjm199354 2965440Sjm199354 2975440Sjm199354 /* 2985440Sjm199354 * vs_props_se_get 2995440Sjm199354 * 3005440Sjm199354 * Retrieves values for the specified scan engine properties from the 3015440Sjm199354 * repository. 3025440Sjm199354 * 3035440Sjm199354 * If the enable property is set (true), the host property is 3045440Sjm199354 * checked for validity. If it is not valid, the requested values 3055440Sjm199354 * are returned with the enable propery set to off (false) 3065440Sjm199354 * 3075440Sjm199354 * Return codes: 3085440Sjm199354 * VS_ERR_VS_ERR_NONE 3095440Sjm199354 * VS_ERR_INVALID_PROPERTY 3105440Sjm199354 * VS_ERR_SCF 3115440Sjm199354 * VS_ERR_SYS 3125440Sjm199354 */ 3135440Sjm199354 int 3145440Sjm199354 vs_props_se_get(char *engid, vs_props_se_t *sep, uint64_t propids) 3155440Sjm199354 { 3165440Sjm199354 int rc; 3176407Sjm199354 char pgname[VS_PGNAME_ENGINE_LEN]; 3185440Sjm199354 vs_prop_hd_t prop_hd; 3195440Sjm199354 3205440Sjm199354 /* VS_PGNAME_GENERAL is a reserved for GENERAL property group */ 3215440Sjm199354 if (strcmp(engid, VS_PGNAME_GENERAL) == 0) 3225440Sjm199354 return (VS_ERR_INVALID_SE); 3235440Sjm199354 3245440Sjm199354 if ((propids & VS_PROPID_SE_ALL) != propids) 3255440Sjm199354 return (VS_ERR_INVALID_PROPERTY); 3265440Sjm199354 3275440Sjm199354 (void) memset(&prop_hd, 0, sizeof (vs_prop_hd_t)); 3285440Sjm199354 prop_hd.vp_type = VS_PTYPE_SE; 3295440Sjm199354 prop_hd.vp_ids = propids; 3305440Sjm199354 prop_hd.vp_all = VS_PROPID_SE_ALL; 3315440Sjm199354 (void) strlcpy(prop_hd.vp_se.vep_engid, engid, VS_SE_NAME_LEN); 3325440Sjm199354 3335440Sjm199354 /* If getting enable, get the host property too */ 3345440Sjm199354 if ((propids & VS_PROPID_SE_ENABLE)) 3355440Sjm199354 prop_hd.vp_ids |= VS_PROPID_SE_HOST; 3365440Sjm199354 3375440Sjm199354 /* Load values from the repository */ 3386407Sjm199354 vs_engid_to_pgname(engid, pgname); 3396407Sjm199354 rc = vs_scf_values_get(pgname, &prop_hd); 3405440Sjm199354 if (rc != VS_ERR_NONE) 3415440Sjm199354 return (rc); 3425440Sjm199354 3435440Sjm199354 /* 3445440Sjm199354 * If the host is invalid and the enable property is on, 3455440Sjm199354 * return enable property as off 3465440Sjm199354 */ 3475440Sjm199354 if ((prop_hd.vp_ids & VS_PROPID_SE_HOST) && 3485440Sjm199354 (vs_validate(&prop_hd, VS_PROPID_SE_HOST) != VS_ERR_NONE)) { 3495440Sjm199354 prop_hd.vp_se.vep_enable = B_FALSE; 3505440Sjm199354 } 3515440Sjm199354 3525440Sjm199354 *sep = prop_hd.vp_se; 3535440Sjm199354 return (rc); 3545440Sjm199354 } 3555440Sjm199354 3565440Sjm199354 3575440Sjm199354 3585440Sjm199354 /* 3595440Sjm199354 * vs_props_se_set 3605440Sjm199354 * 3615440Sjm199354 * Changes the values for the specified scan engine properties in the 3625440Sjm199354 * repository. 3635440Sjm199354 * 3645440Sjm199354 * If the enable property is being changed to true in this operation, 3655440Sjm199354 * a host property must also be specified, or already exist in the 3665440Sjm199354 * repository. 3675440Sjm199354 * 3685440Sjm199354 * Return codes: 3695440Sjm199354 * VS_ERR_NONE 3705440Sjm199354 * VS_ERR_INVALID_PROPERTY 3715440Sjm199354 * VS_ERR_INVALID_VALUE 3725440Sjm199354 * VS_ERR_SCF 3735440Sjm199354 * VS_ERR_SYS 3745440Sjm199354 */ 3755440Sjm199354 int 3765440Sjm199354 vs_props_se_set(char *engid, const vs_props_se_t *sep, uint64_t propids) 3775440Sjm199354 { 3785440Sjm199354 int rc; 3796407Sjm199354 char pgname[VS_PGNAME_ENGINE_LEN]; 3805440Sjm199354 vs_prop_hd_t prop_hd; 3815440Sjm199354 3825440Sjm199354 /* VS_PGNAME_GENERAL is a reserved for GENERAL property group */ 3835440Sjm199354 if (strcmp(engid, VS_PGNAME_GENERAL) == 0) 3845440Sjm199354 return (VS_ERR_INVALID_SE); 3855440Sjm199354 3865440Sjm199354 if ((propids & VS_PROPID_SE_ALL) != propids) 3875440Sjm199354 return (VS_ERR_INVALID_PROPERTY); 3885440Sjm199354 3895440Sjm199354 (void) memset(&prop_hd, 0, sizeof (vs_prop_hd_t)); 3905440Sjm199354 prop_hd.vp_type = VS_PTYPE_SE; 3915440Sjm199354 prop_hd.vp_all = VS_PROPID_SE_ALL; 3925440Sjm199354 3936407Sjm199354 vs_engid_to_pgname(engid, pgname); 3946407Sjm199354 3955440Sjm199354 /* 3965440Sjm199354 * if enabling a scan engine, ensure that a valid host 3975440Sjm199354 * is also being set, or already exists in the repository 3985440Sjm199354 */ 3995440Sjm199354 if ((propids & VS_PROPID_SE_ENABLE) && (sep->vep_enable == B_TRUE) && 4005440Sjm199354 !(propids & VS_PROPID_SE_HOST)) { 4015440Sjm199354 4025440Sjm199354 prop_hd.vp_ids = VS_PROPID_SE_HOST; 4036407Sjm199354 if ((rc = vs_scf_values_get(pgname, &prop_hd)) != VS_ERR_NONE) 4045440Sjm199354 return (rc); 4055440Sjm199354 4065440Sjm199354 if (vs_validate(&prop_hd, VS_PROPID_SE_HOST) != VS_ERR_NONE) 4075440Sjm199354 return (VS_ERR_INVALID_HOST); 4085440Sjm199354 } 4095440Sjm199354 4105440Sjm199354 prop_hd.vp_ids = propids; 4115440Sjm199354 prop_hd.vp_se = *sep; 4125440Sjm199354 4136407Sjm199354 return (vs_scf_values_set(pgname, &prop_hd)); 4145440Sjm199354 } 4155440Sjm199354 4165440Sjm199354 4175440Sjm199354 /* 4185440Sjm199354 * vs_props_se_create 4195440Sjm199354 */ 4205440Sjm199354 int 4215440Sjm199354 vs_props_se_create(char *engid, const vs_props_se_t *sep, uint64_t propids) 4225440Sjm199354 { 4235440Sjm199354 int n; 4246407Sjm199354 char pgname[VS_PGNAME_ENGINE_LEN]; 4255440Sjm199354 vs_prop_hd_t prop_hd; 4265440Sjm199354 4275440Sjm199354 if ((propids & VS_PROPID_SE_ALL) != propids) 4285440Sjm199354 return (VS_ERR_INVALID_PROPERTY); 4295440Sjm199354 4305440Sjm199354 /* VS_PGNAME_GENERAL is a reserved for GENERAL property group */ 4315440Sjm199354 if (strcmp(engid, VS_PGNAME_GENERAL) == 0) 4325440Sjm199354 return (VS_ERR_INVALID_SE); 4335440Sjm199354 4345440Sjm199354 if ((n = vs_scf_pg_count()) == -1) 4355440Sjm199354 return (VS_ERR_SCF); 4365440Sjm199354 4375440Sjm199354 if (n == VS_SE_MAX) 4385440Sjm199354 return (VS_ERR_MAX_SE); 4395440Sjm199354 4406407Sjm199354 vs_engid_to_pgname(engid, pgname); 4416407Sjm199354 4425440Sjm199354 (void) memset(&prop_hd, 0, sizeof (vs_prop_hd_t)); 4435440Sjm199354 prop_hd.vp_type = VS_PTYPE_SE; 4445440Sjm199354 prop_hd.vp_all = VS_PROPID_SE_ALL; 4455440Sjm199354 prop_hd.vp_ids = propids | VS_PROPID_VALUE_AUTH; 4465440Sjm199354 prop_hd.vp_se = *sep; 4475440Sjm199354 4486407Sjm199354 /* if hostname not specified, default it to engid */ 4496407Sjm199354 if ((propids & VS_PROPID_SE_HOST) == 0) { 4506407Sjm199354 (void) strlcpy(prop_hd.vp_se.vep_host, engid, MAXHOSTNAMELEN); 4516407Sjm199354 prop_hd.vp_ids |= VS_PROPID_SE_HOST; 4526407Sjm199354 } 4535440Sjm199354 4546407Sjm199354 return (vs_scf_pg_create(pgname, &prop_hd)); 4555440Sjm199354 } 4565440Sjm199354 4575440Sjm199354 4585440Sjm199354 /* 4595440Sjm199354 * vs_props_se_delete 4605440Sjm199354 */ 4615440Sjm199354 int 4625440Sjm199354 vs_props_se_delete(const char *engid) 4635440Sjm199354 { 4646407Sjm199354 char pgname[VS_PGNAME_ENGINE_LEN]; 4655440Sjm199354 4665440Sjm199354 /* VS_PGNAME_GENERAL is a reserved for GENERAL property group */ 4675440Sjm199354 if (strcmp(engid, VS_PGNAME_GENERAL) == 0) 4685440Sjm199354 return (VS_ERR_INVALID_SE); 4695440Sjm199354 4706407Sjm199354 vs_engid_to_pgname(engid, pgname); 4715440Sjm199354 4726407Sjm199354 return (vs_scf_pg_delete(pgname)); 4735440Sjm199354 } 4745440Sjm199354 4755440Sjm199354 4765440Sjm199354 /* 4775440Sjm199354 * vs_strerror 4785440Sjm199354 */ 4795440Sjm199354 const char * 4805440Sjm199354 vs_strerror(int error) 4815440Sjm199354 { 4825440Sjm199354 switch (error) { 4835440Sjm199354 case VS_ERR_NONE: 4845440Sjm199354 return (gettext("no error")); 4855440Sjm199354 case VS_ERR_INVALID_PROPERTY: 4865440Sjm199354 return (gettext("invalid property id")); 4875440Sjm199354 case VS_ERR_INVALID_VALUE: 4885440Sjm199354 return (gettext("invalid property value")); 4895440Sjm199354 case VS_ERR_INVALID_HOST: 4905440Sjm199354 return (gettext("invalid host")); 4915440Sjm199354 case VS_ERR_INVALID_SE: 4925440Sjm199354 return (gettext("invalid scan engine")); 4935440Sjm199354 case VS_ERR_MAX_SE: 4945440Sjm199354 return (gettext("max scan engines exceeded")); 4955440Sjm199354 case VS_ERR_AUTH: 4965440Sjm199354 return (gettext("insufficient privileges for action")); 4975440Sjm199354 case VS_ERR_DAEMON_COMM: 4985440Sjm199354 return (gettext("unable to contact vscand")); 4995440Sjm199354 case VS_ERR_SCF: 5005440Sjm199354 return (scf_strerror(scf_error())); 5015440Sjm199354 case VS_ERR_SYS: 5025440Sjm199354 return (strerror(errno)); 5035440Sjm199354 default: 5045440Sjm199354 return (gettext("unknown error")); 5055440Sjm199354 } 5065440Sjm199354 } 5075440Sjm199354 5085440Sjm199354 5095440Sjm199354 /* 5105440Sjm199354 * vs_get_propdef 5115440Sjm199354 * 5125440Sjm199354 * Finds and returns a property definition by property id. 5135440Sjm199354 */ 5145440Sjm199354 static const vs_propdef_t * 5155440Sjm199354 vs_get_propdef(uint64_t propid) 5165440Sjm199354 { 5175440Sjm199354 int i; 5185440Sjm199354 5195440Sjm199354 for (i = 0; i < vs_npropdefs; i++) { 5205440Sjm199354 if (propid == vs_propdefs[i].vpd_id) 5215440Sjm199354 return (&vs_propdefs[i]); 5225440Sjm199354 } 5235440Sjm199354 5245440Sjm199354 return (NULL); 5255440Sjm199354 } 5265440Sjm199354 5275440Sjm199354 5285440Sjm199354 /* 5295440Sjm199354 * vs_default_value 5305440Sjm199354 * 5315440Sjm199354 * Sets a property value that contains invalid data to its default value. 5325440Sjm199354 * 5335440Sjm199354 * Note that this function does not alter any values in the repository 5345440Sjm199354 * This is only to enable the caller to get valid data. 5355440Sjm199354 */ 5365440Sjm199354 static void 5375440Sjm199354 vs_default_value(vs_prop_hd_t *prop_hd, const uint64_t propid) 5385440Sjm199354 { 5395440Sjm199354 vs_props_t *vp = &prop_hd->vp_gen; 5405440Sjm199354 vs_props_se_t *vep = &prop_hd->vp_se; 5415440Sjm199354 5425440Sjm199354 switch (propid) { 5435440Sjm199354 case VS_PROPID_MAXSIZE: 5445440Sjm199354 (void) strlcpy(vp->vp_maxsize, vs_dflt_maxsize, 5455440Sjm199354 sizeof (vp->vp_maxsize)); 5465440Sjm199354 break; 5475440Sjm199354 case VS_PROPID_MAXSIZE_ACTION: 5485440Sjm199354 vp->vp_maxsize_action = vs_dflt_allow; 5495440Sjm199354 break; 5505440Sjm199354 case VS_PROPID_TYPES: 5515440Sjm199354 (void) strlcpy(vp->vp_types, vs_dflt_types, 5525440Sjm199354 sizeof (vp->vp_types)); 5535440Sjm199354 break; 5545440Sjm199354 case VS_PROPID_VLOG: 5555440Sjm199354 (void) strlcpy(vp->vp_vlog, vs_dflt_vlog, 5565440Sjm199354 sizeof (vp->vp_vlog)); 5575440Sjm199354 break; 5585440Sjm199354 case VS_PROPID_SE_ENABLE: 5595440Sjm199354 vep->vep_enable = vs_dflt_enable; 5605440Sjm199354 break; 5615440Sjm199354 case VS_PROPID_SE_HOST: 5625440Sjm199354 (void) strlcpy(vep->vep_host, vs_dflt_host, 5635440Sjm199354 sizeof (vep->vep_host)); 5645440Sjm199354 break; 5655440Sjm199354 case VS_PROPID_SE_PORT: 5665440Sjm199354 vep->vep_port = vs_dflt_port; 5675440Sjm199354 break; 5685440Sjm199354 case VS_PROPID_SE_MAXCONN: 5695440Sjm199354 vep->vep_maxconn = vs_dflt_maxconn; 5705440Sjm199354 break; 5715440Sjm199354 default: 5725440Sjm199354 break; 5735440Sjm199354 } 5745440Sjm199354 } 5755440Sjm199354 5765440Sjm199354 5775440Sjm199354 /* 5785440Sjm199354 * vs_scf_values_get 5795440Sjm199354 * 5805440Sjm199354 * Gets property values for one or more properties from the repository. 5815440Sjm199354 * This is the single entry point for loading SMF values. 5825440Sjm199354 * 5835440Sjm199354 * While a transaction is not used for loading property values, 5845440Sjm199354 * the operation is parameterized by a property group. All properties 5855440Sjm199354 * retrieved in this function, then, must belong to the same property 5865440Sjm199354 * group. 5875440Sjm199354 */ 5885440Sjm199354 int 5895440Sjm199354 vs_scf_values_get(const char *pgname, vs_prop_hd_t *prop_hd) 5905440Sjm199354 { 5915440Sjm199354 vs_scfctx_t vsc; 5925440Sjm199354 int rc, np; 5935440Sjm199354 const vs_propdef_t *vpd; 5945440Sjm199354 uint64_t propid; 5955440Sjm199354 5965440Sjm199354 if ((vs_scf_ctx_open(&vsc)) != 0) { 5975440Sjm199354 vs_scf_ctx_close(&vsc); 5985440Sjm199354 return (VS_ERR_SCF); 5995440Sjm199354 } 6005440Sjm199354 6015440Sjm199354 if (scf_instance_get_pg(vsc.vscf_inst, pgname, vsc.vscf_pgroup) == -1) { 6025440Sjm199354 vs_scf_ctx_close(&vsc); 6035440Sjm199354 if (strcmp(pgname, "VS_PGNAME_GENERAL") != 0) { 6045440Sjm199354 rc = scf_error(); 6055440Sjm199354 if ((rc == SCF_ERROR_NOT_FOUND) || 6065440Sjm199354 (rc == SCF_ERROR_INVALID_ARGUMENT)) 6075440Sjm199354 return (VS_ERR_INVALID_SE); 6085440Sjm199354 } 6095440Sjm199354 return (VS_ERR_SCF); 6105440Sjm199354 } 6115440Sjm199354 6125440Sjm199354 rc = VS_ERR_NONE; 6135440Sjm199354 np = 0; 6145440Sjm199354 for (propid = 1LL; propid <= VS_PROPID_MAX; propid <<= 1) { 6155440Sjm199354 if ((prop_hd->vp_ids & propid) == 0) 6165440Sjm199354 continue; 6175440Sjm199354 6185440Sjm199354 if ((vpd = vs_get_propdef(propid)) == NULL) { 6195440Sjm199354 rc = VS_ERR_INVALID_PROPERTY; 6205440Sjm199354 break; 6215440Sjm199354 } 6225440Sjm199354 6235440Sjm199354 vsc.vscf_prop[np] = scf_property_create(vsc.vscf_handle); 6245440Sjm199354 vsc.vscf_val[np] = scf_value_create(vsc.vscf_handle); 6255440Sjm199354 6265440Sjm199354 if (vsc.vscf_prop[np] == NULL || vsc.vscf_val[np] == NULL) { 6275440Sjm199354 rc = VS_ERR_SCF; 6285440Sjm199354 break; 6295440Sjm199354 } 6305440Sjm199354 6315440Sjm199354 if (scf_pg_get_property(vsc.vscf_pgroup, vpd->vpd_name, 6325440Sjm199354 vsc.vscf_prop[np]) == -1) { 6335440Sjm199354 if (scf_error() == SCF_ERROR_NOT_FOUND) { 6345440Sjm199354 vs_default_value(prop_hd, vpd->vpd_id); 6355440Sjm199354 continue; 6365440Sjm199354 } 6375440Sjm199354 rc = VS_ERR_SCF; 6385440Sjm199354 break; 6395440Sjm199354 } 6405440Sjm199354 6415440Sjm199354 if ((rc = vs_scf_get(vpd, prop_hd, &vsc, np)) != VS_ERR_NONE) 6425440Sjm199354 break; 6435440Sjm199354 6445440Sjm199354 ++np; 6455440Sjm199354 } 6465440Sjm199354 6475440Sjm199354 6485440Sjm199354 vs_scf_ctx_close(&vsc); 6495440Sjm199354 6505440Sjm199354 return (rc); 6515440Sjm199354 } 6525440Sjm199354 6535440Sjm199354 6545440Sjm199354 /* 6555440Sjm199354 * vs_scf_get 6565440Sjm199354 * 6575440Sjm199354 * Loads a single values from the repository into the appropriate vscan 6585440Sjm199354 * property structure member. 6595440Sjm199354 */ 6605440Sjm199354 static int 6615440Sjm199354 vs_scf_get(const vs_propdef_t *vpd, vs_prop_hd_t *prop_hd, 6625440Sjm199354 vs_scfctx_t *vsc, int idx) 6635440Sjm199354 { 6645440Sjm199354 int rc; 6655440Sjm199354 int64_t port; 6665440Sjm199354 uint8_t valbool; 6675440Sjm199354 vs_props_t *vp = &prop_hd->vp_gen; 6685440Sjm199354 vs_props_se_t *vep = &prop_hd->vp_se; 6695440Sjm199354 6705440Sjm199354 if ((rc = scf_property_get_value(vsc->vscf_prop[idx], 6715440Sjm199354 vsc->vscf_val[idx])) == -1) { 6725440Sjm199354 if (rc == SCF_ERROR_CONSTRAINT_VIOLATED || 6735440Sjm199354 rc == SCF_ERROR_NOT_FOUND) { 6745440Sjm199354 vs_default_value(prop_hd, vpd->vpd_id); 6755440Sjm199354 return (VS_ERR_NONE); 6765440Sjm199354 } 6775440Sjm199354 return (VS_ERR_SCF); 6785440Sjm199354 } 6795440Sjm199354 6805440Sjm199354 rc = VS_ERR_NONE; 6815440Sjm199354 switch (vpd->vpd_id) { 6825440Sjm199354 case VS_PROPID_MAXSIZE: 6835440Sjm199354 if ((scf_value_get_astring(vsc->vscf_val[idx], 6845440Sjm199354 vp->vp_maxsize, sizeof (vp->vp_maxsize))) == -1) { 6855440Sjm199354 return (VS_ERR_SCF); 6865440Sjm199354 } 6875440Sjm199354 break; 6885440Sjm199354 case VS_PROPID_MAXSIZE_ACTION: 6895440Sjm199354 if ((scf_value_get_boolean(vsc->vscf_val[idx], 6905440Sjm199354 &valbool)) == -1) { 6915440Sjm199354 return (VS_ERR_SCF); 6925440Sjm199354 } 6935440Sjm199354 vp->vp_maxsize_action = (valbool == 0) ? B_FALSE : B_TRUE; 6945440Sjm199354 break; 6955440Sjm199354 case VS_PROPID_TYPES: 6965440Sjm199354 if ((scf_value_get_astring(vsc->vscf_val[idx], 6975440Sjm199354 vp->vp_types, sizeof (vp->vp_types))) == -1) { 6985440Sjm199354 return (VS_ERR_SCF); 6995440Sjm199354 } 7005440Sjm199354 break; 7015440Sjm199354 case VS_PROPID_VLOG: 7025440Sjm199354 if ((scf_value_get_astring(vsc->vscf_val[idx], 7035440Sjm199354 vp->vp_vlog, sizeof (vp->vp_vlog))) == -1) { 7045440Sjm199354 return (VS_ERR_SCF); 7055440Sjm199354 } 7065440Sjm199354 break; 7075440Sjm199354 case VS_PROPID_SE_ENABLE: 7085440Sjm199354 if ((scf_value_get_boolean(vsc->vscf_val[idx], 7095440Sjm199354 &valbool)) == -1) { 7105440Sjm199354 return (VS_ERR_SCF); 7115440Sjm199354 } 7125440Sjm199354 vep->vep_enable = (valbool == 0) ? B_FALSE : B_TRUE; 7135440Sjm199354 break; 7145440Sjm199354 case VS_PROPID_SE_HOST: 7155440Sjm199354 (void) scf_value_get_as_string_typed(vsc->vscf_val[idx], 7165440Sjm199354 vpd->vpd_type, vep->vep_host, sizeof (vep->vep_host)); 7175440Sjm199354 break; 7185440Sjm199354 case VS_PROPID_SE_PORT: 7195440Sjm199354 if ((scf_value_get_integer(vsc->vscf_val[idx], &port)) == -1) 7205440Sjm199354 return (VS_ERR_SCF); 7215440Sjm199354 if (port <= 0 || port >= UINT16_MAX) 7225440Sjm199354 rc = VS_ERR_INVALID_VALUE; 7235440Sjm199354 else 7245440Sjm199354 vep->vep_port = (uint16_t)port; 7255440Sjm199354 break; 7265440Sjm199354 case VS_PROPID_SE_MAXCONN: 7275440Sjm199354 if ((scf_value_get_integer(vsc->vscf_val[idx], 7285440Sjm199354 (int64_t *)&vep->vep_maxconn)) == -1) { 7295440Sjm199354 return (VS_ERR_SCF); 7305440Sjm199354 } 7315440Sjm199354 break; 7325440Sjm199354 default: 7335440Sjm199354 break; 7345440Sjm199354 } 7355440Sjm199354 7365440Sjm199354 if ((rc != VS_ERR_NONE) || 7375440Sjm199354 (vs_validate(prop_hd, vpd->vpd_id) != VS_ERR_NONE)) { 7385440Sjm199354 vs_default_value(prop_hd, vpd->vpd_id); 7395440Sjm199354 } 7405440Sjm199354 7415440Sjm199354 return (VS_ERR_NONE); 7425440Sjm199354 } 7435440Sjm199354 7445440Sjm199354 7455440Sjm199354 /* 7465440Sjm199354 * vs_scf_pg_create 7475440Sjm199354 */ 7485440Sjm199354 static int 7495440Sjm199354 vs_scf_pg_create(const char *pgname, vs_prop_hd_t *prop_hd) 7505440Sjm199354 { 7515440Sjm199354 int rc; 7525440Sjm199354 uint64_t propid; 7535440Sjm199354 vs_scfctx_t vsc; 7545440Sjm199354 7555440Sjm199354 /* ensure that caller has authorization to refresh service */ 7565440Sjm199354 if ((rc = vs_checkauth(VS_ACTION_AUTH)) != VS_ERR_NONE) 7575440Sjm199354 return (rc); 7585440Sjm199354 7595440Sjm199354 if (vs_scf_ctx_open(&vsc) != 0) { 7605440Sjm199354 vs_scf_ctx_close(&vsc); 7615440Sjm199354 return (VS_ERR_SCF); 7625440Sjm199354 } 7635440Sjm199354 7645440Sjm199354 if (scf_instance_add_pg(vsc.vscf_inst, pgname, 7655440Sjm199354 SCF_GROUP_APPLICATION, 0, vsc.vscf_pgroup) == -1) { 7665440Sjm199354 vs_scf_ctx_close(&vsc); 7675440Sjm199354 if (scf_error() == SCF_ERROR_INVALID_ARGUMENT) 7685440Sjm199354 return (VS_ERR_INVALID_SE); 7695440Sjm199354 return (VS_ERR_SCF); 7705440Sjm199354 } 7715440Sjm199354 vs_scf_ctx_close(&vsc); 7725440Sjm199354 7735440Sjm199354 /* set default values for those not specified */ 7745440Sjm199354 for (propid = 1LL; propid <= VS_PROPID_MAX; propid <<= 1) { 7755440Sjm199354 if ((propid & prop_hd->vp_all) && !(propid & prop_hd->vp_ids)) 7765440Sjm199354 vs_default_value(prop_hd, propid); 7775440Sjm199354 } 7786407Sjm199354 7795440Sjm199354 prop_hd->vp_ids = prop_hd->vp_all; 7805440Sjm199354 prop_hd->vp_ids |= VS_PROPID_VALUE_AUTH; 7815440Sjm199354 7825440Sjm199354 rc = vs_scf_values_set(pgname, prop_hd); 7835440Sjm199354 if (rc != VS_ERR_NONE) 7846407Sjm199354 (void) vs_scf_pg_delete(pgname); 7855440Sjm199354 7865440Sjm199354 return (rc); 7875440Sjm199354 } 7885440Sjm199354 7895440Sjm199354 7905440Sjm199354 /* 7916407Sjm199354 * vs_scf_pg_delete 7926407Sjm199354 */ 7936407Sjm199354 static int 7946407Sjm199354 vs_scf_pg_delete(const char *pgname) 7956407Sjm199354 { 7966407Sjm199354 int rc; 7976407Sjm199354 vs_scfctx_t vsc; 7986407Sjm199354 7996407Sjm199354 /* ensure that caller has authorization to refresh service */ 8006407Sjm199354 if ((rc = vs_checkauth(VS_ACTION_AUTH)) != VS_ERR_NONE) 8016407Sjm199354 return (rc); 8026407Sjm199354 8036407Sjm199354 if (vs_scf_ctx_open(&vsc) != 0) { 8046407Sjm199354 vs_scf_ctx_close(&vsc); 8056407Sjm199354 return (VS_ERR_SCF); 8066407Sjm199354 } 8076407Sjm199354 8086407Sjm199354 if (scf_instance_get_pg(vsc.vscf_inst, pgname, vsc.vscf_pgroup) == -1) { 8096407Sjm199354 vs_scf_ctx_close(&vsc); 8106407Sjm199354 rc = scf_error(); 8116407Sjm199354 if ((rc == SCF_ERROR_NOT_FOUND) || 8126407Sjm199354 (rc == SCF_ERROR_INVALID_ARGUMENT)) 8136407Sjm199354 return (VS_ERR_INVALID_SE); 8146407Sjm199354 else 8156407Sjm199354 return (VS_ERR_SCF); 8166407Sjm199354 } 8176407Sjm199354 8186407Sjm199354 if (scf_pg_delete(vsc.vscf_pgroup) == -1) { 8196407Sjm199354 vs_scf_ctx_close(&vsc); 8206407Sjm199354 rc = scf_error(); 8216407Sjm199354 if ((rc == SCF_ERROR_NOT_FOUND) || 8226407Sjm199354 (rc == SCF_ERROR_INVALID_ARGUMENT)) 8236407Sjm199354 return (VS_ERR_INVALID_SE); 8246407Sjm199354 8256407Sjm199354 return (VS_ERR_SCF); 8266407Sjm199354 } 8276407Sjm199354 8286407Sjm199354 vs_scf_ctx_close(&vsc); 8296407Sjm199354 8306407Sjm199354 /* Notify the daemon that things have changed */ 8316407Sjm199354 if ((smf_refresh_instance(VS_INSTANCE_FMRI)) == -1) { 8326407Sjm199354 return (VS_ERR_SCF); 8336407Sjm199354 } 8346407Sjm199354 8356407Sjm199354 return (VS_ERR_NONE); 8366407Sjm199354 } 8376407Sjm199354 8386407Sjm199354 8396407Sjm199354 /* 8405440Sjm199354 * vs_scf_values_set 8415440Sjm199354 * 8425440Sjm199354 * Sets property values in the repository. This is the single 8435440Sjm199354 * entry point for storing SMF values. 8445440Sjm199354 * 8455440Sjm199354 * Like loading values, this is an operation based on a single property 8465440Sjm199354 * group, so all property values changed in this function must belong 8475440Sjm199354 * to the same property group. Additionally, this operation is done in 8485440Sjm199354 * the context of a repository transaction; on any fatal error, the 8495440Sjm199354 * SCF context will be closed, destroying all SCF objects and aborting 8505440Sjm199354 * the transaction. 8515440Sjm199354 */ 8525440Sjm199354 static int 8535440Sjm199354 vs_scf_values_set(const char *pgname, vs_prop_hd_t *prop_hd) 8545440Sjm199354 { 8555440Sjm199354 int rc, np; 8565440Sjm199354 const vs_propdef_t *vpd; 8575440Sjm199354 uint64_t propid; 8585440Sjm199354 vs_scfctx_t vsc; 8595440Sjm199354 8605440Sjm199354 /* ensure that caller has authorization to refresh service */ 8615440Sjm199354 if ((rc = vs_checkauth(VS_ACTION_AUTH)) != VS_ERR_NONE) 8625440Sjm199354 return (rc); 8635440Sjm199354 8645440Sjm199354 if (vs_scf_ctx_open(&vsc) != 0) { 8655440Sjm199354 vs_scf_ctx_close(&vsc); 8665440Sjm199354 return (VS_ERR_SCF); 8675440Sjm199354 } 8685440Sjm199354 8695440Sjm199354 if (scf_instance_get_pg(vsc.vscf_inst, pgname, vsc.vscf_pgroup) == -1) { 8705440Sjm199354 vs_scf_ctx_close(&vsc); 8715440Sjm199354 rc = scf_error(); 8725440Sjm199354 if (strcmp(pgname, "VS_PGNAME_GENERAL") != 0) { 8735440Sjm199354 if ((rc == SCF_ERROR_NOT_FOUND) || 8745440Sjm199354 (rc == SCF_ERROR_INVALID_ARGUMENT)) 8755440Sjm199354 return (VS_ERR_INVALID_SE); 8765440Sjm199354 } 8775440Sjm199354 return (VS_ERR_SCF); 8785440Sjm199354 } 8795440Sjm199354 8805440Sjm199354 if (((vsc.vscf_tx = scf_transaction_create(vsc.vscf_handle)) == NULL) || 8815440Sjm199354 (scf_transaction_start(vsc.vscf_tx, vsc.vscf_pgroup) == -1)) { 8825440Sjm199354 vs_scf_ctx_close(&vsc); 8835440Sjm199354 return (VS_ERR_SCF); 8845440Sjm199354 } 8855440Sjm199354 8865440Sjm199354 /* Process the value change for each specified property */ 8875440Sjm199354 rc = 0; 8885440Sjm199354 np = 0; 8895440Sjm199354 for (propid = 1LL; propid <= VS_PROPID_MAX; propid <<= 1) { 8905440Sjm199354 if ((prop_hd->vp_ids & propid) == 0) 8915440Sjm199354 continue; 8925440Sjm199354 8935440Sjm199354 if ((vpd = vs_get_propdef(propid)) == NULL) { 8945440Sjm199354 rc = VS_ERR_INVALID_PROPERTY; 8955440Sjm199354 break; 8965440Sjm199354 } 8975440Sjm199354 8985440Sjm199354 vsc.vscf_val[np] = scf_value_create(vsc.vscf_handle); 8995440Sjm199354 vsc.vscf_ent[np] = scf_entry_create(vsc.vscf_handle); 9005440Sjm199354 9015440Sjm199354 if (vsc.vscf_val[np] == NULL || vsc.vscf_ent[np] == NULL) { 9025440Sjm199354 rc = VS_ERR_SCF; 9035440Sjm199354 break; 9045440Sjm199354 } 9055440Sjm199354 9065440Sjm199354 if ((rc = scf_transaction_property_change(vsc.vscf_tx, 9075440Sjm199354 vsc.vscf_ent[np], vpd->vpd_name, vpd->vpd_type)) == -1) { 9085440Sjm199354 rc = scf_transaction_property_new(vsc.vscf_tx, 9095440Sjm199354 vsc.vscf_ent[np], vpd->vpd_name, vpd->vpd_type); 9105440Sjm199354 } 9115440Sjm199354 if (rc == -1) { 9125440Sjm199354 rc = VS_ERR_SCF; 9135440Sjm199354 break; 9145440Sjm199354 } 9155440Sjm199354 9165440Sjm199354 if ((rc = vs_scf_set(vpd, prop_hd, &vsc, np)) != VS_ERR_NONE) 9175440Sjm199354 break; 9185440Sjm199354 9195440Sjm199354 ++np; 9205440Sjm199354 } 9215440Sjm199354 9225440Sjm199354 if (rc != VS_ERR_NONE) { 9235440Sjm199354 vs_scf_ctx_close(&vsc); 9245440Sjm199354 return (rc); 9255440Sjm199354 } 9265440Sjm199354 9275440Sjm199354 /* Commit the transaction */ 9285440Sjm199354 if (scf_transaction_commit(vsc.vscf_tx) == -1) { 9295440Sjm199354 vs_scf_ctx_close(&vsc); 9305440Sjm199354 return (VS_ERR_SCF); 9315440Sjm199354 } 9325440Sjm199354 vs_scf_ctx_close(&vsc); 9335440Sjm199354 9345440Sjm199354 /* Notify the daemon that things have changed */ 9355440Sjm199354 if ((smf_refresh_instance(VS_INSTANCE_FMRI)) == -1) 9365440Sjm199354 return (VS_ERR_SCF); 9375440Sjm199354 9385440Sjm199354 return (VS_ERR_NONE); 9395440Sjm199354 } 9405440Sjm199354 9415440Sjm199354 9425440Sjm199354 /* 9435440Sjm199354 * vs_scf_set 9445440Sjm199354 * 9455440Sjm199354 * Stores a single value from the appropriate vscan property structure 9465440Sjm199354 * member into the repository. 9475440Sjm199354 * 9485440Sjm199354 * Values are set in the SCF value object, then the value object 9495440Sjm199354 * is added to the SCF property object. 9505440Sjm199354 */ 9515440Sjm199354 static int 9525440Sjm199354 vs_scf_set(const vs_propdef_t *vpd, vs_prop_hd_t *prop_hd, 9535440Sjm199354 vs_scfctx_t *vsc, int idx) 9545440Sjm199354 { 9555440Sjm199354 int rc; 9565440Sjm199354 vs_props_t *vp = &prop_hd->vp_gen; 9575440Sjm199354 vs_props_se_t *vep = &prop_hd->vp_se; 9585440Sjm199354 9595440Sjm199354 if ((rc = vs_validate(prop_hd, vpd->vpd_id)) != VS_ERR_NONE) 9605440Sjm199354 return (rc); 9615440Sjm199354 9625440Sjm199354 rc = VS_ERR_NONE; 9635440Sjm199354 switch (vpd->vpd_id) { 9645440Sjm199354 case VS_PROPID_MAXSIZE: 9655440Sjm199354 if ((scf_value_set_astring(vsc->vscf_val[idx], 9665440Sjm199354 vp->vp_maxsize)) == -1) { 9675440Sjm199354 rc = VS_ERR_SCF; 9685440Sjm199354 } 9695440Sjm199354 break; 9705440Sjm199354 case VS_PROPID_MAXSIZE_ACTION: 9715440Sjm199354 scf_value_set_boolean(vsc->vscf_val[idx], 9725440Sjm199354 (uint8_t)vp->vp_maxsize_action); 9735440Sjm199354 break; 9745440Sjm199354 case VS_PROPID_TYPES: 9755440Sjm199354 if ((scf_value_set_astring(vsc->vscf_val[idx], 9765440Sjm199354 vp->vp_types)) == -1) { 9775440Sjm199354 return (VS_ERR_SCF); 9785440Sjm199354 } 9795440Sjm199354 break; 9805440Sjm199354 case VS_PROPID_SE_ENABLE: 9815440Sjm199354 scf_value_set_boolean(vsc->vscf_val[idx], 9825440Sjm199354 (uint8_t)vep->vep_enable); 9835440Sjm199354 break; 9845440Sjm199354 case VS_PROPID_SE_HOST: 9855440Sjm199354 if ((scf_value_set_from_string(vsc->vscf_val[idx], 9865440Sjm199354 vpd->vpd_type, vep->vep_host)) == -1) { 9875440Sjm199354 rc = VS_ERR_SCF; 9885440Sjm199354 } 9895440Sjm199354 break; 9905440Sjm199354 case VS_PROPID_SE_PORT: 9915440Sjm199354 scf_value_set_integer(vsc->vscf_val[idx], vep->vep_port); 9925440Sjm199354 break; 9935440Sjm199354 case VS_PROPID_SE_MAXCONN: 9945440Sjm199354 scf_value_set_integer(vsc->vscf_val[idx], 9955440Sjm199354 vep->vep_maxconn); 9965440Sjm199354 break; 9975440Sjm199354 case VS_PROPID_VALUE_AUTH: 9985440Sjm199354 if ((scf_value_set_astring(vsc->vscf_val[idx], 9995440Sjm199354 VS_VALUE_AUTH)) == -1) { 10005440Sjm199354 return (VS_ERR_SCF); 10015440Sjm199354 } 10025440Sjm199354 break; 10035440Sjm199354 default: 10045440Sjm199354 break; 10055440Sjm199354 } 10065440Sjm199354 10075440Sjm199354 if ((scf_entry_add_value(vsc->vscf_ent[idx], 10085440Sjm199354 vsc->vscf_val[idx])) == -1) { 10095440Sjm199354 return (VS_ERR_SCF); 10105440Sjm199354 } 10115440Sjm199354 10125440Sjm199354 return (rc); 10135440Sjm199354 } 10145440Sjm199354 10155440Sjm199354 10165440Sjm199354 /* 10175440Sjm199354 * vs_scf_ctx_open 10185440Sjm199354 * 10195440Sjm199354 * Opens an SCF context; creates the minumum SCF objects 10205440Sjm199354 * for use in loading/storing from the SMF repository (meaning 10215440Sjm199354 * vscf_property group data). 10225440Sjm199354 * 10235440Sjm199354 * Other SCF objects in the context may be initialized elsewher 10245440Sjm199354 * subsequent to open, but all initialized structures are destroyed 10255440Sjm199354 * in vs_scf_ctx_close(). 10265440Sjm199354 */ 10275440Sjm199354 static int 10285440Sjm199354 vs_scf_ctx_open(vs_scfctx_t *vsc) 10295440Sjm199354 { 10305440Sjm199354 (void) memset(vsc, 0, sizeof (vs_scfctx_t)); 10315440Sjm199354 10325440Sjm199354 if ((vsc->vscf_handle = scf_handle_create(SCF_VERSION)) == NULL) 10335440Sjm199354 return (VS_ERR_SCF); 10345440Sjm199354 10355440Sjm199354 if (scf_handle_bind(vsc->vscf_handle) == -1) 10365440Sjm199354 return (VS_ERR_SCF); 10375440Sjm199354 10385440Sjm199354 if ((vsc->vscf_inst = scf_instance_create(vsc->vscf_handle)) == NULL) 10395440Sjm199354 return (VS_ERR_SCF); 10405440Sjm199354 10415440Sjm199354 if (scf_handle_decode_fmri(vsc->vscf_handle, VS_INSTANCE_FMRI, 10425440Sjm199354 NULL, NULL, vsc->vscf_inst, NULL, NULL, 10435440Sjm199354 SCF_DECODE_FMRI_EXACT) == -1) { 10445440Sjm199354 return (VS_ERR_SCF); 10455440Sjm199354 } 10465440Sjm199354 10475440Sjm199354 if ((vsc->vscf_pgroup = scf_pg_create(vsc->vscf_handle)) == NULL) 10485440Sjm199354 return (VS_ERR_SCF); 10495440Sjm199354 10505440Sjm199354 return (VS_ERR_NONE); 10515440Sjm199354 } 10525440Sjm199354 10535440Sjm199354 10545440Sjm199354 /* 10555440Sjm199354 * vs_scf_ctx_close 10565440Sjm199354 * 10575440Sjm199354 * Closes an SCF context; destroys all initialized SCF objects. 10585440Sjm199354 */ 10595440Sjm199354 static void 10605440Sjm199354 vs_scf_ctx_close(vs_scfctx_t *vsc) 10615440Sjm199354 { 10625440Sjm199354 int i; 10635440Sjm199354 10645440Sjm199354 for (i = 0; i < VS_NUM_PROPIDS; i++) { 10655440Sjm199354 if (vsc->vscf_val[i]) 10665440Sjm199354 scf_value_destroy(vsc->vscf_val[i]); 10675440Sjm199354 if (vsc->vscf_ent[i]) 10685440Sjm199354 scf_entry_destroy(vsc->vscf_ent[i]); 10695440Sjm199354 if (vsc->vscf_prop[i]) 10705440Sjm199354 scf_property_destroy(vsc->vscf_prop[i]); 10715440Sjm199354 } 10725440Sjm199354 10735440Sjm199354 if (vsc->vscf_iter) 10745440Sjm199354 scf_iter_destroy(vsc->vscf_iter); 10755440Sjm199354 if (vsc->vscf_tx) 10765440Sjm199354 scf_transaction_destroy(vsc->vscf_tx); 10775440Sjm199354 if (vsc->vscf_pgroup) 10785440Sjm199354 scf_pg_destroy(vsc->vscf_pgroup); 10795440Sjm199354 if (vsc->vscf_inst) 10805440Sjm199354 scf_instance_destroy(vsc->vscf_inst); 10815440Sjm199354 if (vsc->vscf_handle) 10825440Sjm199354 scf_handle_destroy(vsc->vscf_handle); 10835440Sjm199354 } 10845440Sjm199354 10855440Sjm199354 10865440Sjm199354 /* 10875440Sjm199354 * vs_validate 10885440Sjm199354 * 10895440Sjm199354 * Validate property identified in propid. 10905440Sjm199354 * 10915440Sjm199354 * Returns: VS_ERR_NONE 10925440Sjm199354 * VS_ERR_INVALID_VALUE 10935440Sjm199354 * VS_ERR_INVALID_PROPERTY 10945440Sjm199354 */ 10955440Sjm199354 static int 10965440Sjm199354 vs_validate(const vs_prop_hd_t *prop_hd, uint64_t propid) 10975440Sjm199354 { 10985440Sjm199354 uint64_t num; 10995440Sjm199354 const vs_props_t *vp = &prop_hd->vp_gen; 11005440Sjm199354 const vs_props_se_t *vep = &prop_hd->vp_se; 11015440Sjm199354 11025440Sjm199354 switch (propid) { 11035440Sjm199354 case VS_PROPID_MAXSIZE: 11045440Sjm199354 if ((vs_strtonum(vp->vp_maxsize, &num) != 0) || (num == 0)) 11055440Sjm199354 return (VS_ERR_INVALID_VALUE); 11065440Sjm199354 break; 11075440Sjm199354 case VS_PROPID_MAXSIZE_ACTION: 11085440Sjm199354 break; 11095440Sjm199354 case VS_PROPID_TYPES: 11105440Sjm199354 if (!vs_is_valid_types(vp->vp_types)) 11115440Sjm199354 return (VS_ERR_INVALID_VALUE); 11125440Sjm199354 break; 11135440Sjm199354 case VS_PROPID_SE_ENABLE: 11145440Sjm199354 break; 11155440Sjm199354 case VS_PROPID_SE_PORT: 11165440Sjm199354 if (vep->vep_port == 0) 11175440Sjm199354 return (VS_ERR_INVALID_VALUE); 11185440Sjm199354 break; 11195440Sjm199354 case VS_PROPID_SE_HOST: 11205440Sjm199354 if (!vs_is_valid_host(vep->vep_host)) 11215440Sjm199354 return (VS_ERR_INVALID_VALUE); 11225440Sjm199354 break; 11235440Sjm199354 case VS_PROPID_SE_MAXCONN: 11245440Sjm199354 if (vep->vep_maxconn < VS_VAL_SE_MAXCONN_MIN || 11255440Sjm199354 vep->vep_maxconn > VS_VAL_SE_MAXCONN_MAX) 11265440Sjm199354 return (VS_ERR_INVALID_VALUE); 11275440Sjm199354 break; 11285440Sjm199354 case VS_PROPID_VALUE_AUTH: 11295440Sjm199354 case VS_PROPID_VLOG: 11305440Sjm199354 break; 11315440Sjm199354 default: 11325440Sjm199354 return (VS_ERR_INVALID_PROPERTY); 11335440Sjm199354 } 11345440Sjm199354 11355440Sjm199354 return (VS_ERR_NONE); 11365440Sjm199354 } 11375440Sjm199354 11385440Sjm199354 11395440Sjm199354 /* 11405440Sjm199354 * vs_props_validate 11415440Sjm199354 * 11425440Sjm199354 * Validate properties identified in propids. 11435440Sjm199354 * 11445440Sjm199354 * Returns: VS_ERR_NONE 11455440Sjm199354 * VS_ERR_INVALID_VALUE 11465440Sjm199354 * VS_ERR_INVALID_PROPERTY 11475440Sjm199354 */ 11485440Sjm199354 int 11495440Sjm199354 vs_props_validate(const vs_props_t *props, uint64_t propids) 11505440Sjm199354 { 11515440Sjm199354 uint64_t propid; 11525440Sjm199354 vs_prop_hd_t prop_hd; 11535440Sjm199354 11545440Sjm199354 if ((propids & VS_PROPID_GEN_ALL) != propids) 11555440Sjm199354 return (VS_ERR_INVALID_PROPERTY); 11565440Sjm199354 11575440Sjm199354 (void) memset(&prop_hd, 0, sizeof (vs_prop_hd_t)); 11585440Sjm199354 prop_hd.vp_gen = *props; 11595440Sjm199354 prop_hd.vp_type = VS_PTYPE_GEN; 11605440Sjm199354 prop_hd.vp_ids = propids; 11615440Sjm199354 prop_hd.vp_all = VS_PROPID_GEN_ALL; 11625440Sjm199354 11635440Sjm199354 for (propid = 1LL; propid <= VS_PROPID_MAX; propid <<= 1) { 11645440Sjm199354 if ((propids & propid) == 0) 11655440Sjm199354 continue; 11665440Sjm199354 11675440Sjm199354 if (vs_validate(&prop_hd, propid) != VS_ERR_NONE) 11685440Sjm199354 return (VS_ERR_INVALID_VALUE); 11695440Sjm199354 } 11705440Sjm199354 11715440Sjm199354 return (VS_ERR_NONE); 11725440Sjm199354 } 11735440Sjm199354 11745440Sjm199354 11755440Sjm199354 /* 11765440Sjm199354 * vs_props_se_validate 11775440Sjm199354 * 11785440Sjm199354 * Validate properties identified in propids. 11795440Sjm199354 * 11805440Sjm199354 * Returns: VS_ERR_NONE 11815440Sjm199354 * VS_ERR_INVALID_VALUE 11825440Sjm199354 * VS_ERR_INVALID_PROPERTY 11835440Sjm199354 */ 11845440Sjm199354 int 11855440Sjm199354 vs_props_se_validate(const vs_props_se_t *se_props, uint64_t propids) 11865440Sjm199354 { 11875440Sjm199354 uint64_t propid; 11885440Sjm199354 vs_prop_hd_t prop_hd; 11895440Sjm199354 11905440Sjm199354 if ((propids & VS_PROPID_SE_ALL) != propids) 11915440Sjm199354 return (VS_ERR_INVALID_PROPERTY); 11925440Sjm199354 11935440Sjm199354 (void) memset(&prop_hd, 0, sizeof (vs_prop_hd_t)); 11945440Sjm199354 prop_hd.vp_se = *se_props; 11955440Sjm199354 prop_hd.vp_type = VS_PTYPE_SE; 11965440Sjm199354 prop_hd.vp_ids = propids; 11975440Sjm199354 prop_hd.vp_all = VS_PROPID_SE_ALL; 11985440Sjm199354 11995440Sjm199354 for (propid = 1LL; propid <= VS_PROPID_MAX; propid <<= 1) { 12005440Sjm199354 if ((propids & propid) == 0) 12015440Sjm199354 continue; 12025440Sjm199354 12035440Sjm199354 if (vs_validate(&prop_hd, propid) != VS_ERR_NONE) 12045440Sjm199354 return (VS_ERR_INVALID_VALUE); 12055440Sjm199354 } 12065440Sjm199354 12075440Sjm199354 return (VS_ERR_NONE); 12085440Sjm199354 } 12095440Sjm199354 12105440Sjm199354 12115440Sjm199354 /* 12125440Sjm199354 * vs_is_valid_types 12135440Sjm199354 * 12145440Sjm199354 * Checks that types property is a valid format: 12155440Sjm199354 * - doesn't exceed VS_VAL_TYPES_MAX 12165440Sjm199354 * - doesn't contain VS_VAL_TYPES_INVALID_CHARS 12175440Sjm199354 * - is correctly formatted - passes the parsing tests 12185440Sjm199354 * 12195440Sjm199354 * Returns 1 on success, 0 on failure 12205440Sjm199354 */ 12215440Sjm199354 static int 12225440Sjm199354 vs_is_valid_types(const char *types) 12235440Sjm199354 { 12245440Sjm199354 char buf[VS_VAL_TYPES_LEN]; 12255440Sjm199354 uint32_t len = VS_VAL_TYPES_LEN; 12265440Sjm199354 12275440Sjm199354 if (strlen(types) > VS_VAL_TYPES_LEN) 12285440Sjm199354 return (0); 12295440Sjm199354 12305440Sjm199354 if (strpbrk(types, VS_VAL_TYPES_INVALID_CHARS) != NULL) 12315440Sjm199354 return (0); 12325440Sjm199354 12335440Sjm199354 if (vs_parse_types(types, buf, &len) != 0) 12345440Sjm199354 return (0); 12355440Sjm199354 12365440Sjm199354 return (1); 12375440Sjm199354 } 12385440Sjm199354 12395440Sjm199354 12405440Sjm199354 /* 12415440Sjm199354 * vs_is_valid_host 12425440Sjm199354 * 12435440Sjm199354 * Returns 1 on success, 0 on failure 12445440Sjm199354 */ 12455440Sjm199354 static int 12465440Sjm199354 vs_is_valid_host(const char *host) 12475440Sjm199354 { 12485440Sjm199354 long naddr; 12495440Sjm199354 const char *p; 12505440Sjm199354 12515440Sjm199354 if (!host || *host == '\0') 12525440Sjm199354 return (0); 12535440Sjm199354 12545440Sjm199354 if ('0' <= host[0] && host[0] <= '9') { 12555440Sjm199354 /* ip address */ 12565440Sjm199354 if ((inet_pton(AF_INET, host, &naddr)) == 0) 12575440Sjm199354 return (0); 12585440Sjm199354 if ((naddr & IN_CLASSA_NET) == 0) 12595440Sjm199354 return (0); 12605440Sjm199354 if ((naddr & IN_CLASSC_HOST) == 0) 12615440Sjm199354 return (0); 12625440Sjm199354 } else { 12635440Sjm199354 /* hostname */ 12645440Sjm199354 p = host; 12655440Sjm199354 while (*p != '\0') { 12665440Sjm199354 if (!isascii(*p)) 12675440Sjm199354 return (0); 12685440Sjm199354 12695440Sjm199354 if (isalnum(*p) || 12705440Sjm199354 (*p == '.') || (*p == '-') || (*p == '_')) { 12715440Sjm199354 ++p; 12725440Sjm199354 } else { 12735440Sjm199354 return (0); 12745440Sjm199354 } 12755440Sjm199354 } 12765440Sjm199354 } 12775440Sjm199354 12785440Sjm199354 return (1); 12795440Sjm199354 } 12805440Sjm199354 12815440Sjm199354 12825440Sjm199354 /* 12835440Sjm199354 * vs_parse_types 12845440Sjm199354 * 12855440Sjm199354 * Replace comma separators with '\0'. 12865440Sjm199354 * 12875440Sjm199354 * Types contains comma separated rules each beginning with +|- 12885440Sjm199354 * - embedded commas are escaped by backslash 12895440Sjm199354 * - backslash is escaped by backslash 12905440Sjm199354 * - a single backslash not followed by comma is illegal 12915440Sjm199354 * 12925440Sjm199354 * On entry to the function len must contain the length of 12935440Sjm199354 * the buffer. On sucecssful exit len will contain the length 12945440Sjm199354 * of the parsed data within the buffer. 12955440Sjm199354 * 12965440Sjm199354 * Returns 0 on success, -1 on failure 12975440Sjm199354 */ 12985440Sjm199354 int 12995440Sjm199354 vs_parse_types(const char *types, char *buf, uint32_t *len) 13005440Sjm199354 { 13015440Sjm199354 char *p = (char *)types; 13025440Sjm199354 char *b = buf; 13035440Sjm199354 13045440Sjm199354 if (strlen(types) > *len) 13055440Sjm199354 return (-1); 13065440Sjm199354 13075440Sjm199354 if (strchr(VS_TYPES_RULES, *p) == NULL) 13085440Sjm199354 return (-1); 13095440Sjm199354 13105440Sjm199354 (void) memset(buf, 0, *len); 13115440Sjm199354 13125440Sjm199354 while (*p) { 13135440Sjm199354 switch (*p) { 13145440Sjm199354 case VS_TYPES_SEP: 13155440Sjm199354 if (*(p + 1) && 13165440Sjm199354 (strchr(VS_TYPES_RULES, *(p + 1))) == NULL) 13175440Sjm199354 return (-1); 13185440Sjm199354 *b = '\0'; 13195440Sjm199354 break; 13205440Sjm199354 case VS_TYPES_ESCAPE: 13215440Sjm199354 ++p; 13225440Sjm199354 if (*p == VS_TYPES_ESCAPE || *p == VS_TYPES_SEP) 13235440Sjm199354 *b = *p; 13245440Sjm199354 else 13255440Sjm199354 return (-1); 13265440Sjm199354 break; 13275440Sjm199354 default: 13285440Sjm199354 *b = *p; 13295440Sjm199354 } 13305440Sjm199354 ++p; 13315440Sjm199354 ++b; 13325440Sjm199354 } 13335440Sjm199354 13345440Sjm199354 *len = (b - buf) + 1; 13355440Sjm199354 13365440Sjm199354 return (0); 13375440Sjm199354 } 13385440Sjm199354 13395440Sjm199354 13405440Sjm199354 /* 13415440Sjm199354 * vs_statistics 13425440Sjm199354 */ 13435440Sjm199354 int 13445440Sjm199354 vs_statistics(vs_stats_t *stats) 13455440Sjm199354 { 13465440Sjm199354 int door_fd, rc = VS_ERR_NONE; 13475440Sjm199354 vs_stats_req_t *req; 13486407Sjm199354 vs_stats_rsp_t *rsp; 13495440Sjm199354 door_arg_t arg; 13505440Sjm199354 13515440Sjm199354 if ((req = calloc(1, sizeof (vs_stats_req_t))) == NULL) 13525440Sjm199354 return (VS_ERR_SYS); 13535440Sjm199354 13546407Sjm199354 if ((rsp = calloc(1, sizeof (vs_stats_rsp_t))) == NULL) { 13555440Sjm199354 free(req); 13565440Sjm199354 return (VS_ERR_SYS); 13575440Sjm199354 } 13585440Sjm199354 13595440Sjm199354 if ((door_fd = open(VS_STATS_DOOR_NAME, O_RDONLY)) < 0) { 13605440Sjm199354 free(req); 13616407Sjm199354 free(rsp); 13625440Sjm199354 return (VS_ERR_DAEMON_COMM); 13635440Sjm199354 } 13645440Sjm199354 13656407Sjm199354 req->vsr_magic = VS_STATS_DOOR_MAGIC; 13666407Sjm199354 req->vsr_id = VS_STATS_GET; 13675440Sjm199354 13685440Sjm199354 arg.data_ptr = (char *)req; 13695440Sjm199354 arg.data_size = sizeof (vs_stats_req_t); 13705440Sjm199354 arg.desc_ptr = NULL; 13715440Sjm199354 arg.desc_num = 0; 13726407Sjm199354 arg.rbuf = (char *)rsp; 13736407Sjm199354 arg.rsize = sizeof (vs_stats_rsp_t); 13745440Sjm199354 1375*7943Samw@Sun.COM rc = vs_door_call(door_fd, &arg); 1376*7943Samw@Sun.COM 1377*7943Samw@Sun.COM if ((rc == VS_ERR_NONE) && (rsp->vsr_magic == VS_STATS_DOOR_MAGIC)) 1378*7943Samw@Sun.COM *stats = rsp->vsr_stats; 1379*7943Samw@Sun.COM else 13805440Sjm199354 rc = VS_ERR_DAEMON_COMM; 13815440Sjm199354 13825440Sjm199354 (void) close(door_fd); 13835440Sjm199354 13845440Sjm199354 free(req); 13856407Sjm199354 free(rsp); 13865440Sjm199354 return (rc); 13875440Sjm199354 } 13885440Sjm199354 13895440Sjm199354 13905440Sjm199354 /* 13915440Sjm199354 * vs_statistics_reset 13925440Sjm199354 */ 13935440Sjm199354 int 13945440Sjm199354 vs_statistics_reset() 13955440Sjm199354 { 13965440Sjm199354 int door_fd, rc; 13975440Sjm199354 vs_stats_req_t *req; 13985440Sjm199354 door_arg_t arg; 13995440Sjm199354 14005440Sjm199354 /* ensure that caller has authorization to reset stats */ 14015440Sjm199354 if ((rc = vs_checkauth(VS_VALUE_AUTH)) != VS_ERR_NONE) 14025440Sjm199354 return (rc); 14035440Sjm199354 14045440Sjm199354 if ((req = calloc(1, sizeof (vs_stats_req_t))) == NULL) 14055440Sjm199354 return (VS_ERR_SYS); 14065440Sjm199354 14075440Sjm199354 if ((door_fd = open(VS_STATS_DOOR_NAME, O_RDONLY)) < 0) { 14085440Sjm199354 free(req); 14095440Sjm199354 return (VS_ERR_DAEMON_COMM); 14105440Sjm199354 } 14115440Sjm199354 14126407Sjm199354 req->vsr_magic = VS_STATS_DOOR_MAGIC; 14136407Sjm199354 req->vsr_id = VS_STATS_RESET; 14145440Sjm199354 14155440Sjm199354 arg.data_ptr = (char *)req; 14165440Sjm199354 arg.data_size = sizeof (vs_stats_req_t); 14175440Sjm199354 arg.desc_ptr = NULL; 14185440Sjm199354 arg.desc_num = 0; 14195440Sjm199354 arg.rbuf = NULL; 14205440Sjm199354 arg.rsize = 0; 14215440Sjm199354 1422*7943Samw@Sun.COM rc = vs_door_call(door_fd, &arg); 14235440Sjm199354 14245440Sjm199354 (void) close(door_fd); 14255440Sjm199354 free(req); 14265440Sjm199354 return (rc); 14275440Sjm199354 } 14285440Sjm199354 1429*7943Samw@Sun.COM /* 1430*7943Samw@Sun.COM * Door call with retries. 1431*7943Samw@Sun.COM * 1432*7943Samw@Sun.COM * Returns VS_ERR_NONE on success, otherwise VS_ERR_DAEMON_COMM. 1433*7943Samw@Sun.COM */ 1434*7943Samw@Sun.COM static int 1435*7943Samw@Sun.COM vs_door_call(int fd, door_arg_t *arg) 1436*7943Samw@Sun.COM { 1437*7943Samw@Sun.COM int rc = -1; 1438*7943Samw@Sun.COM int i; 1439*7943Samw@Sun.COM 1440*7943Samw@Sun.COM for (i = 0; i < VS_DOOR_CALL_RETRIES; ++i) { 1441*7943Samw@Sun.COM errno = 0; 1442*7943Samw@Sun.COM 1443*7943Samw@Sun.COM if ((rc = door_call(fd, arg)) == 0) 1444*7943Samw@Sun.COM break; 1445*7943Samw@Sun.COM 1446*7943Samw@Sun.COM if (errno != EAGAIN && errno != EINTR) 1447*7943Samw@Sun.COM break; 1448*7943Samw@Sun.COM } 1449*7943Samw@Sun.COM 1450*7943Samw@Sun.COM return ((rc == 0) ? VS_ERR_NONE : VS_ERR_DAEMON_COMM); 1451*7943Samw@Sun.COM } 14525440Sjm199354 14535440Sjm199354 /* 14545440Sjm199354 * vs_checkauth 14555440Sjm199354 */ 14565440Sjm199354 static int 14575440Sjm199354 vs_checkauth(char *auth) 14585440Sjm199354 { 14595440Sjm199354 struct passwd *pw; 14605440Sjm199354 uid_t uid; 14615440Sjm199354 14625440Sjm199354 uid = getuid(); 14635440Sjm199354 14645440Sjm199354 if ((pw = getpwuid(uid)) == NULL) 14655440Sjm199354 return (VS_ERR_SYS); 14665440Sjm199354 14675440Sjm199354 if (chkauthattr(auth, pw->pw_name) != 1) { 14685440Sjm199354 return (VS_ERR_AUTH); 14695440Sjm199354 } 14705440Sjm199354 14715440Sjm199354 return (VS_ERR_NONE); 14725440Sjm199354 } 14735440Sjm199354 14745440Sjm199354 14755440Sjm199354 /* 14765440Sjm199354 * vs_props_get_engines 14776407Sjm199354 * 14785440Sjm199354 * On input, count specifies the maximum number of engine ids to 14795440Sjm199354 * return. engids must be an array with count entries. 14805440Sjm199354 * On return, count specifies the number of engine ids being 14815440Sjm199354 * returned in engids. 14826407Sjm199354 * 14836407Sjm199354 * Caller is responsible for free'ing the engids allocated herein. 14845440Sjm199354 */ 14855440Sjm199354 static int 14866407Sjm199354 vs_props_get_engines(char *engids[], int *count) 14875440Sjm199354 { 14886407Sjm199354 int i, prefix_len; 14896407Sjm199354 char pgname[VS_PGNAME_ENGINE_LEN]; 14905440Sjm199354 vs_scfctx_t vsc; 14915440Sjm199354 14925440Sjm199354 14935440Sjm199354 if (((vs_scf_ctx_open(&vsc)) != 0) || 14945440Sjm199354 ((vsc.vscf_iter = scf_iter_create(vsc.vscf_handle)) == NULL) || 14955440Sjm199354 (scf_iter_instance_pgs_typed(vsc.vscf_iter, vsc.vscf_inst, 14965440Sjm199354 SCF_GROUP_APPLICATION) != 0)) { 14975440Sjm199354 vs_scf_ctx_close(&vsc); 14985440Sjm199354 return (VS_ERR_SCF); 14995440Sjm199354 } 15005440Sjm199354 15016407Sjm199354 for (i = 0; i < *count; i++) 15026407Sjm199354 engids[i] = NULL; 15036407Sjm199354 15046407Sjm199354 i = 0; 15056407Sjm199354 prefix_len = sizeof (VS_PGNAME_ENGINE_PREFIX) - 1; 15066407Sjm199354 15075440Sjm199354 while ((i < VS_SE_MAX) && 15085440Sjm199354 (scf_iter_next_pg(vsc.vscf_iter, vsc.vscf_pgroup) == 1)) { 15096407Sjm199354 if (scf_pg_get_name(vsc.vscf_pgroup, pgname, 15106407Sjm199354 VS_PGNAME_ENGINE_LEN) < 0) { 15115440Sjm199354 vs_scf_ctx_close(&vsc); 15125440Sjm199354 return (VS_ERR_SCF); 15135440Sjm199354 } 15145440Sjm199354 15156407Sjm199354 if (strncmp(pgname, VS_PGNAME_ENGINE_PREFIX, prefix_len) == 0) { 15166407Sjm199354 if ((engids[i] = strdup(pgname + prefix_len)) != NULL) { 15176407Sjm199354 if (++i == *count) 15186407Sjm199354 break; 15196407Sjm199354 } 15206407Sjm199354 } 15215440Sjm199354 } 15225440Sjm199354 vs_scf_ctx_close(&vsc); 15235440Sjm199354 15245440Sjm199354 *count = i; 15255440Sjm199354 return (VS_ERR_NONE); 15265440Sjm199354 } 15275440Sjm199354 15285440Sjm199354 15295440Sjm199354 /* 15305440Sjm199354 * vs_scf_pg_count 15315440Sjm199354 */ 15325440Sjm199354 static int 15335440Sjm199354 vs_scf_pg_count(void) 15345440Sjm199354 { 15355440Sjm199354 int count = 0; 15365440Sjm199354 vs_scfctx_t vsc; 15375440Sjm199354 15385440Sjm199354 if ((vs_scf_ctx_open(&vsc) != 0) || 15395440Sjm199354 ((vsc.vscf_iter = scf_iter_create(vsc.vscf_handle)) == NULL) || 15405440Sjm199354 (scf_iter_instance_pgs_typed(vsc.vscf_iter, vsc.vscf_inst, 15415440Sjm199354 SCF_GROUP_APPLICATION) != 0)) { 15425440Sjm199354 vs_scf_ctx_close(&vsc); 15435440Sjm199354 return (-1); 15445440Sjm199354 } 15455440Sjm199354 15465440Sjm199354 while (scf_iter_next_pg(vsc.vscf_iter, vsc.vscf_pgroup) == 1) 15475440Sjm199354 ++count; 15485440Sjm199354 15495440Sjm199354 vs_scf_ctx_close(&vsc); 15505440Sjm199354 15515440Sjm199354 return (count); 15525440Sjm199354 } 15535440Sjm199354 15545440Sjm199354 15555440Sjm199354 /* 15566407Sjm199354 * vs_engid_to_pgname 15576407Sjm199354 * 15586407Sjm199354 * To convert an engine id (engid) to a property group name (pgname), 15596407Sjm199354 * the engine id is prefixed with VS_PGNAME_ENGINE_PREFIX. 15606407Sjm199354 */ 15616407Sjm199354 static void 15626407Sjm199354 vs_engid_to_pgname(const char *engid, char pgname[VS_PGNAME_ENGINE_LEN]) 15636407Sjm199354 { 15646407Sjm199354 (void) snprintf(pgname, VS_PGNAME_ENGINE_LEN, "%s%s", 15656407Sjm199354 VS_PGNAME_ENGINE_PREFIX, engid); 15666407Sjm199354 } 15676407Sjm199354 15686407Sjm199354 15696407Sjm199354 /* 15705440Sjm199354 * vs_strtonum 15715440Sjm199354 * 15725440Sjm199354 * Converts a size string in the format into an integer. 15735440Sjm199354 * 15745440Sjm199354 * A size string is a numeric value followed by an optional unit 15755440Sjm199354 * specifier which is used as a multiplier to calculate a raw 15765440Sjm199354 * number. 15775440Sjm199354 * The size string format is: N[.N][KMGTP][B] 15785440Sjm199354 * 15795440Sjm199354 * The numeric value can contain a decimal portion. Unit specifiers 15805440Sjm199354 * are either a one-character or two-character string; i.e. "K" or 15815440Sjm199354 * "KB" for kilobytes. Unit specifiers must follow the numeric portion 15825440Sjm199354 * immediately, and are not case-sensitive. 15835440Sjm199354 * 15845440Sjm199354 * If either "B" is specified, or there is no unit specifier portion 15855440Sjm199354 * in the string, the numeric value is calculated with no multiplier 15865440Sjm199354 * (assumes a basic unit of "bytes"). 15875440Sjm199354 * 15885440Sjm199354 * Returns: 15895440Sjm199354 * -1: Failure; errno set to specify the error. 15905440Sjm199354 * 0: Success. 15915440Sjm199354 */ 15925440Sjm199354 int 15935440Sjm199354 vs_strtonum(const char *value, uint64_t *num) 15945440Sjm199354 { 15955440Sjm199354 char *end; 15965440Sjm199354 int shift; 15975440Sjm199354 double fval; 15985440Sjm199354 15995440Sjm199354 *num = 0; 16005440Sjm199354 16015440Sjm199354 /* Check to see if this looks like a number. */ 16025440Sjm199354 if ((value[0] < '0' || value[0] > '9') && value[0] != '.') { 16035440Sjm199354 errno = EINVAL; 16045440Sjm199354 return (-1); 16055440Sjm199354 } 16065440Sjm199354 16075440Sjm199354 /* Rely on stroll() to process the numeric portion. */ 16085440Sjm199354 errno = 0; 16095440Sjm199354 *num = strtoll(value, &end, 10); 16105440Sjm199354 16115440Sjm199354 /* 16125440Sjm199354 * Check for ERANGE, which indicates that the value is too large to 16135440Sjm199354 * fit in a 64-bit value. 16145440Sjm199354 */ 16155440Sjm199354 if (errno != 0) 16165440Sjm199354 return (-1); 16175440Sjm199354 16185440Sjm199354 /* 16195440Sjm199354 * If we have a decimal value, then do the computation with floating 16205440Sjm199354 * point arithmetic. Otherwise, use standard arithmetic. 16215440Sjm199354 */ 16225440Sjm199354 if (*end == '.') { 16235440Sjm199354 fval = strtod(value, &end); 16245440Sjm199354 16255440Sjm199354 if ((shift = vs_strtoshift(end)) == -1) 16265440Sjm199354 return (-1); /* errno set */ 16275440Sjm199354 16285440Sjm199354 fval *= pow(2, shift); 16295440Sjm199354 if (fval > UINT64_MAX) { 16305440Sjm199354 errno = ERANGE; 16315440Sjm199354 return (-1); 16325440Sjm199354 } 16335440Sjm199354 16345440Sjm199354 *num = (uint64_t)fval; 16355440Sjm199354 } else { 16365440Sjm199354 if ((shift = vs_strtoshift(end)) == -1) 16375440Sjm199354 return (-1); /* errno set */ 16385440Sjm199354 16395440Sjm199354 /* Check for overflow */ 16405440Sjm199354 if (shift >= 64 || (*num << shift) >> shift != *num) { 16415440Sjm199354 errno = ERANGE; 16425440Sjm199354 return (-1); 16435440Sjm199354 } 16445440Sjm199354 16455440Sjm199354 *num <<= shift; 16465440Sjm199354 } 16475440Sjm199354 16485440Sjm199354 return (0); 16495440Sjm199354 } 16505440Sjm199354 16515440Sjm199354 16525440Sjm199354 /* 16535440Sjm199354 * vs_strtoshift 16545440Sjm199354 * 16555440Sjm199354 * Converts a unit specifier string into a number of bits that 16565440Sjm199354 * a numeric value must be shifted. 16575440Sjm199354 * 16585440Sjm199354 * Returns: 16595440Sjm199354 * -1: Failure; errno set to specify the error. 16605440Sjm199354 * >-1: Success; the shift count. 16615440Sjm199354 * 16625440Sjm199354 */ 16635440Sjm199354 static int 16645440Sjm199354 vs_strtoshift(const char *buf) 16655440Sjm199354 { 16665440Sjm199354 const char *ends = "BKMGTPEZ"; 16675440Sjm199354 int i; 16685440Sjm199354 16695440Sjm199354 if (buf[0] == '\0') 16705440Sjm199354 return (0); 16715440Sjm199354 for (i = 0; i < strlen(ends); i++) { 16725440Sjm199354 if (toupper(buf[0]) == ends[i]) 16735440Sjm199354 break; 16745440Sjm199354 } 16755440Sjm199354 if (i == strlen(ends)) { 16765440Sjm199354 errno = EINVAL; 16775440Sjm199354 return (-1); 16785440Sjm199354 } 16795440Sjm199354 16805440Sjm199354 /* Allow trailing 'b' characters except in the case of 'BB'. */ 16815440Sjm199354 if (buf[1] == '\0' || (toupper(buf[1]) == 'B' && buf[2] == '\0' && 16825440Sjm199354 toupper(buf[0]) != 'B')) { 16835440Sjm199354 return (10 * i); 16845440Sjm199354 } 16855440Sjm199354 16865440Sjm199354 errno = EINVAL; 16875440Sjm199354 return (-1); 16885440Sjm199354 } 1689