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*10050SJoyce.McIntosh@Sun.COM * Copyright 2009 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
457943Samw@Sun.COM #define VS_DOOR_CALL_RETRIES 3
467943Samw@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;
138*10050SJoyce.McIntosh@Sun.COM static const uint16_t vs_dflt_maxconn = 8;
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 *);
1787943Samw@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
vs_props_get_all(vs_props_all_t * va)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
vs_props_get(vs_props_t * vp,uint64_t propids)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
vs_props_set(const vs_props_t * vp,uint64_t propids)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
vs_props_se_get(char * engid,vs_props_se_t * sep,uint64_t propids)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
vs_props_se_set(char * engid,const vs_props_se_t * sep,uint64_t propids)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
vs_props_se_create(char * engid,const vs_props_se_t * sep,uint64_t propids)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
vs_props_se_delete(const char * engid)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 *
vs_strerror(int error)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 *
vs_get_propdef(uint64_t propid)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
vs_default_value(vs_prop_hd_t * prop_hd,const uint64_t propid)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
vs_scf_values_get(const char * pgname,vs_prop_hd_t * prop_hd)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
vs_scf_get(const vs_propdef_t * vpd,vs_prop_hd_t * prop_hd,vs_scfctx_t * vsc,int idx)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
vs_scf_pg_create(const char * pgname,vs_prop_hd_t * prop_hd)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
vs_scf_pg_delete(const char * pgname)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
vs_scf_values_set(const char * pgname,vs_prop_hd_t * prop_hd)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
vs_scf_set(const vs_propdef_t * vpd,vs_prop_hd_t * prop_hd,vs_scfctx_t * vsc,int idx)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
vs_scf_ctx_open(vs_scfctx_t * vsc)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
vs_scf_ctx_close(vs_scfctx_t * vsc)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
vs_validate(const vs_prop_hd_t * prop_hd,uint64_t propid)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
vs_props_validate(const vs_props_t * props,uint64_t propids)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
vs_props_se_validate(const vs_props_se_t * se_props,uint64_t propids)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
vs_is_valid_types(const char * types)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
vs_is_valid_host(const char * host)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
vs_parse_types(const char * types,char * buf,uint32_t * len)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
vs_statistics(vs_stats_t * stats)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
13757943Samw@Sun.COM rc = vs_door_call(door_fd, &arg);
13767943Samw@Sun.COM
13777943Samw@Sun.COM if ((rc == VS_ERR_NONE) && (rsp->vsr_magic == VS_STATS_DOOR_MAGIC))
13787943Samw@Sun.COM *stats = rsp->vsr_stats;
13797943Samw@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
vs_statistics_reset()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
14227943Samw@Sun.COM rc = vs_door_call(door_fd, &arg);
14235440Sjm199354
14245440Sjm199354 (void) close(door_fd);
14255440Sjm199354 free(req);
14265440Sjm199354 return (rc);
14275440Sjm199354 }
14285440Sjm199354
14297943Samw@Sun.COM /*
14307943Samw@Sun.COM * Door call with retries.
14317943Samw@Sun.COM *
14327943Samw@Sun.COM * Returns VS_ERR_NONE on success, otherwise VS_ERR_DAEMON_COMM.
14337943Samw@Sun.COM */
14347943Samw@Sun.COM static int
vs_door_call(int fd,door_arg_t * arg)14357943Samw@Sun.COM vs_door_call(int fd, door_arg_t *arg)
14367943Samw@Sun.COM {
14377943Samw@Sun.COM int rc = -1;
14387943Samw@Sun.COM int i;
14397943Samw@Sun.COM
14407943Samw@Sun.COM for (i = 0; i < VS_DOOR_CALL_RETRIES; ++i) {
14417943Samw@Sun.COM errno = 0;
14427943Samw@Sun.COM
14437943Samw@Sun.COM if ((rc = door_call(fd, arg)) == 0)
14447943Samw@Sun.COM break;
14457943Samw@Sun.COM
14467943Samw@Sun.COM if (errno != EAGAIN && errno != EINTR)
14477943Samw@Sun.COM break;
14487943Samw@Sun.COM }
14497943Samw@Sun.COM
14507943Samw@Sun.COM return ((rc == 0) ? VS_ERR_NONE : VS_ERR_DAEMON_COMM);
14517943Samw@Sun.COM }
14525440Sjm199354
14535440Sjm199354 /*
14545440Sjm199354 * vs_checkauth
14555440Sjm199354 */
14565440Sjm199354 static int
vs_checkauth(char * auth)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
vs_props_get_engines(char * engids[],int * count)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
vs_scf_pg_count(void)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
vs_engid_to_pgname(const char * engid,char pgname[VS_PGNAME_ENGINE_LEN])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
vs_strtonum(const char * value,uint64_t * num)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
vs_strtoshift(const char * buf)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