Home | History | Annotate | Download | only in svccfg
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 
     22 /*
     23  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     24  * Use is subject to license terms.
     25  */
     26 
     27 /*
     28  * This file provides the code that allows svccfg(1M) to validate a
     29  * manifest against the template specifications.  svccfg uses the
     30  * validation facilities for the import and validate subcommands.
     31  *
     32  * There are three entry points -- tmpl_validate_bundle(),
     33  * tmpl_errors_print() and tmpl_errors_destroy().  svccfg calls
     34  * tmpl_validate_bundle() to validate a bundle.  tmpl_validate_bundle()
     35  * returns a pointer to a tmpl_errors_t.  This is a pointer to information
     36  * about any validation errors that were found.  If an error was detected,
     37  * svccfg calls tmpl_errors_print() to print the error information.  Once
     38  * the error information is printed, svccfg calls tmpl_errors_destroy() to
     39  * free the memory associated with the tmpl_errors_t.
     40  *
     41  * libscf's scf_tmpl.c performs similar checks to the ones described in
     42  * this paragraph.  Any changes to the algorithms in this file should also
     43  * be infcorporated into scf_tmpl.c.  The reason that there are two bodies
     44  * of code is that they work on different data structures.
     45  * tmpl_validate_bundle() validates each instance of each service in the
     46  * bundle.  The following checks are performed on each instance:
     47  *
     48  *	1.  Verify template consistency.
     49  *	    A.  No conflicting definitions of "pg_pattern" are allowed
     50  *		within a single instance.
     51  *	    B.  Templates at a narrow target (e.g. instance) which define
     52  *		property groups already templated at a broad target
     53  *		(e.g. delegate or all) are strongly discouraged.
     54  *	    C.  Developers may not define a template which specifies a
     55  *		single prop_pattern name with differing types on the same
     56  *		target entity.
     57  *	    D.  If a pg_pattern has a required attribute with a value of
     58  *		true, then its name and type attributes must be
     59  *		specified.
     60  *	    E.  If a prop_pattern has a required attribute with a value
     61  *		of true, then its type attribute must be specified.
     62  *	    F.  If a prop_pattern has an include_values element make sure
     63  *		that the appropriate constraints or values element has
     64  *		also been declared.
     65  *	2.  Validate that each property group in the instance is in
     66  *	    conformance with the template specifications.
     67  *	    A.  Verify that the types of the PG and the pg_pattern are
     68  *		compatible.
     69  *	    B.  Verify properties of the PG against the prop_patterns in
     70  *		the template.
     71  *		o Verify property's type.
     72  *		o Verify cardinality.
     73  *		o Vefiy that property values satisfy the constraints
     74  *		  imposed by the prop_pattern.
     75  *	    C.  Verify that required properties are present.
     76  *	3.  Verify that all required property groups are present in the
     77  *	    insance.
     78  *
     79  * tmpl_validate_bundle() is called after svccfg has processed the manifest
     80  * file.  The manifest is represented in memory by a set of entity_t,
     81  * pgroup_t, property_t and value_t structures.  These structures are
     82  * defined in svccfg.h.
     83  *
     84  * tmpl_validate_bundle() calls tmpl_validate_service() for each service in
     85  * the bundle, and tmpl_validate_service() then calls
     86  * tmpl_validate_instance() for each instance in the service.
     87  * tmpl_validate_instance() is the function that does the real work of
     88  * validation against the template specification.
     89  *
     90  * Subsystems:
     91  * ==========
     92  *
     93  * General Templates:
     94  * -----------------
     95  * In order to perform the validation specified by 1.B above, we need to
     96  * load the templates specifications for the global service and the
     97  * instance's restarter.  This information is loaded from the repository
     98  * and it is held in memory using the entity_t, pgroup_t, property_t and
     99  * value_t hierarchy of structures.  When a service is processed,
    100  * load_general_templates() is called to load the information for the
    101  * global service and restarter that is declared at the service level.  The
    102  * sc_service.sc_global and sc_service.sc_restarter members of the
    103  * service's entity_t point to the information for the global and restarter
    104  * services.
    105  *
    106  * The instance portion of a manifest can declare an instance specific
    107  * restarter.  If this is the case, load_instance_restarter() will load the
    108  * information for that restarter, and it is saved in the
    109  * sc_instance.sc_instance_restarter member of the entity_t that represents
    110  * the instance.
    111  *
    112  * Composed Properties:
    113  * -------------------
    114  * We need the ability to process the composed properties of an instance.
    115  * That is to say if an instance defines a property, it overrides any
    116  * definition in the service.  Otherwise, the service's definition is
    117  * inherited in the instance.
    118  *
    119  * In an entity_t, the sc_instance.sc_composed member points to a
    120  * uu_avl tree of composed property groups (composed_pg_t) for the
    121  * instance.  The composed_pg_t has two members, cpg_instance_pg and
    122  * cpg_service_pg, that point to the instance and service property group
    123  * definitions respectively.  Either of these may be NULL indicating that
    124  * only an instance or service definition exists in the manifest.
    125  *
    126  * In the case where both the instance and the service define a property
    127  * group, the properties must be composed.  This is done by
    128  * compose_props().  The compose_pg_t holds the composed properties in a
    129  * uu_avl_tree at cpf_compose_props.  This is a tree of property_t
    130  * structures.  If a property is defined in both the instance and service
    131  * property group, the tree will hold the instance definition.  If the
    132  * property is defined at only one level, the tree will hold the property_t
    133  * for that level.  Thus, the tree is truly a set of composed properties of
    134  * the property group.
    135  *
    136  * Property Group Iteration:
    137  * ------------------------
    138  * A number of functions must iterate through an instance's property groups
    139  * looking for the ones that define a pg_pattern or a prop_pattern.  To be
    140  * specific, the iteration starts with the composed view of the instance.
    141  * It then proceeds through the restarter information and finally moves on
    142  * to the global service.  The pg_iter_t structure holds the information
    143  * that is needed to implement this type of iteration.  pg_iter_create()
    144  * creates one of these iterators, and pg_iter_destroy() frees the memory
    145  * associated with the pg_iter_t.  next_pattern_pg(), is used to step
    146  * through the iteration.
    147  *
    148  * Error Reporting:
    149  * ---------------
    150  * While performing the templates validation checks, svccfg collects
    151  * information for all the errors that it finds.  Because of this you will
    152  * see many places in the code where a loop is not exited when an error is
    153  * encountered.  We note that fact that an error has occurred, but continue
    154  * in the loop to see if there are more validation errors.  The error code
    155  * of the last error that is encountered is returned.  This works, because
    156  * the callers of tmpl_validate_bundle() only look to see whether or not
    157  * the return code is TVS_SUCCESS.
    158  *
    159  * The information for reporting the errors is collected in a tmpl_errors_t
    160  * structure, and tmpl_validate_bundle() returns the address of this
    161  * structure.  The caller of tmpl_validate_bundle() can then call
    162  * tmpl_errors_print() to display the error information to the user.
    163  *
    164  * There are two categories of errors.  Some errors are seen when
    165  * processing the information in the manifest.  This type of error is only
    166  * seen by svccfg when it is importing or validating a manifest.  The other
    167  * type of error consists of template validation errors.  These errors can
    168  * be seen when processing a manifest or when performing a templates
    169  * validation of the information associated with an FMRI in the the
    170  * repository.  tmpl_errors_add_im() is used to capture error information
    171  * about the first type of error, and add_scf_error() is used to capture
    172  * error information about the second type of error.
    173  *
    174  * The distinction is important when printing the error information.  The
    175  * fuctions for printing the first type of error reside in this file, since
    176  * these errors will only be seen by the functions in this file.  The
    177  * functions for printing the template validation errors reside in libscf,
    178  * because these errors are of a more general nature.
    179  *
    180  * Thus, tmpl_errors_t has two lists -- one for each type of error.
    181  * te_list is a list of im_tmpl_error_t structures that represent the first
    182  * type of error.  te_scf is a list of tv_errors_t structures that hold
    183  * information about general template validation errors.
    184  * tmpl_errors_print() processes both lists to print information about all
    185  * errors.  In tmpl_errors_print() im_tmpl_error_print() is used to print
    186  * the errors that are specific to this file.  scf_tmpl_strerror() provides
    187  * the errors messages for general templates errors.
    188  *
    189  * As was mentioned in the previous paragraph, im_tmpl_error_print() is
    190  * responsible for printing the errors that are specific to this file.
    191  * Based on the error code, it dispatches to one of
    192  * im_perror_bad_conversion(), im_perror_bad_template(),
    193  * im_perror_invalid_type(), im_perror_missing_pg_type() or
    194  * im_perror_missing_type().  The rest of the im_perror_* functions provide
    195  * services to these error specific functions by printing common
    196  * information.
    197  *
    198  * im_perror_item() is the heart of this message printing subsystem.  It is
    199  * called directly or indirectly by all of the other im_perror_* functions.
    200  * im_perror_item() prints a single item of error information.  If svccfg
    201  * is running in interactive mode, im_perror_item() prints each item on a
    202  * single line, so that they are readable by a human.  In non-interactive
    203  * mode, all items are printed on a single line separated by semi-colons.
    204  */
    205 
    206 #include <assert.h>
    207 #include <errno.h>
    208 #include <inttypes.h>
    209 #include <libintl.h>
    210 #include <limits.h>
    211 #include <libscf.h>
    212 #include <libscf_priv.h>
    213 #include <stdio.h>
    214 #include <stdlib.h>
    215 #include <strings.h>
    216 #include "svccfg.h"
    217 
    218 /*
    219  * Clear error_info_t structure.
    220  */
    221 #define	CLEAR_ERROR_INFO(ei)	((void) memset((ei), 0, sizeof (error_info_t)))
    222 
    223 /*
    224  * Retrieve the property group pointer from the composed_pg structure.
    225  */
    226 #define	CPG2PG(cpg)	(cpg->cpg_instance_pg ? cpg->cpg_instance_pg : \
    227 			    cpg->cpg_service_pg)
    228 
    229 /*
    230  * Convert a pointer to an empty string into a NULL pointer.
    231  */
    232 #define	EMPTY_TO_NULL(p) (((p) && (*(p) == 0)) ? NULL : (p))
    233 
    234 /* uu_avl and uu_list debugging bits. */
    235 #ifdef	NDEBUG
    236 #define	TMPL_DEBUG_AVL_POOL	UU_DEFAULT
    237 #define	TMPL_DEBUG_LIST		UU_DEFAULT
    238 #define	TMPL_DEBUG_LIST_POOL	UU_DEFAULT
    239 #define	TMPL_DEBUG_TREE		UU_DEFAULT
    240 #else
    241 #define	TMPL_DEBUG_AVL_POOL	UU_AVL_POOL_DEBUG
    242 #define	TMPL_DEBUG_LIST		UU_LIST_DEBUG
    243 #define	TMPL_DEBUG_LIST_POOL	UU_LIST_POOL_DEBUG
    244 #define	TMPL_DEBUG_TREE		UU_AVL_DEBUG
    245 #endif	/* NDEBUG */
    246 
    247 /*
    248  * Structures and enums that are used in producing error messages:
    249  *
    250  * error_info_t is used to pass information about an error to
    251  * tmpl_errors_add_im() and add_scf_error().  tmpl_errors_add_im() collects
    252  * the error information and stores it in an im_tmpl_error_t.  The
    253  * im_tmpl_error_t is linked into the tmpl_errors_t, so that the captured
    254  * information can be used later when error messages are printed.
    255  *
    256  * tv_errors_t is used to keep track of error information for general
    257  * template errors that are known by libscf.  add_scf_error() captures the
    258  * error information for use in this structure.
    259  */
    260 /*
    261  * enum to designate the type of data that is held in a err_info structure.
    262  */
    263 typedef enum err_info_type {
    264 	EIT_NONE,		/* No values in the structure */
    265 	EIT_BAD_TEMPLATE,	/* Reason that template is bad */
    266 	EIT_CARDINALITY,	/* Ranges for property cardinality */
    267 	EIT_INCLUDE_VALUES,	/* include_values type attribute */
    268 	EIT_MISSING_PG,		/* Name of missing pg */
    269 	EIT_MISSING_PROP,	/* Name of missing property */
    270 	EIT_PATTERN_CONFLICT, 	/* Conflicting pattern definition */
    271 	EIT_PROP_TYPE,		/* Value with invalid type */
    272 	EIT_RANGE		/* Value that is out of range */
    273 } err_info_type_t;
    274 
    275 /*
    276  * Structure to hold information that will be used in generating error
    277  * messages.
    278  */
    279 typedef struct error_info {
    280 	err_info_type_t	ei_type;	/* Type of information stored here */
    281 	union {
    282 		/* EIT_BAD_TEMPLATE */
    283 		struct {
    284 			const char	*ei_reason;
    285 		} ei_bad_template;
    286 		/* EIT_CARDINALITY */
    287 		struct {
    288 			uint64_t	ei_min;
    289 			uint64_t	ei_max;
    290 			uint64_t	ei_count; /* Number of prop values */
    291 		} ei_cardinality;
    292 		/* EIT_INCLUDE_VALUES */
    293 		struct {
    294 			const char	*ei_type;
    295 		} ei_inc_values;
    296 		/* EIT_MISSING_PG */
    297 		struct {
    298 			const char	*ei_pg_name;	/* Name of missing pg */
    299 			const char	*ei_pg_type;	/* Type of missing pg */
    300 		} ei_missing_pg;
    301 		/* EIT_MISSING_PROP */
    302 		struct {
    303 			const char	*ei_prop_name; /* Name of prop */
    304 		} ei_missing_prop;
    305 		/* EIT_PATTERN_CONFLICT */
    306 		struct {
    307 			pgroup_t	*ei_pattern; /* Conficting pattern */
    308 		} ei_pattern_conflict;
    309 		/* EIT_PROP_TYPE */
    310 		struct {
    311 			scf_type_t	ei_actual;
    312 			scf_type_t	ei_specified;
    313 		} ei_prop_type;
    314 		/* EIT_RANGE */
    315 		struct {
    316 			scf_type_t	ei_rtype;
    317 			int64_t		ei_ivalue;
    318 			uint64_t	ei_uvalue;
    319 		} ei_range;
    320 	} ei_u;
    321 } error_info_t;
    322 
    323 /*
    324  * Structure with information about a template violation.  This structure
    325  * is for use with in memory representations of the manifest and template.
    326  * See scf_tmpl_error_t for use with repository representations.  Some of
    327  * the pointers may be NULL for some types of errors.
    328  */
    329 typedef struct im_tmpl_error {
    330 	tmpl_validate_status_t ite_type; /* Type of error */
    331 	entity_t	*ite_entity;	/* Instance or service */
    332 	pgroup_t	*ite_pg;	/* Non-conforming prop. group */
    333 	pgroup_t	*ite_pg_pattern; /* Violated pg_pattern */
    334 	property_t	*ite_prop;	/* Non-conforming property */
    335 	pgroup_t	*ite_prop_pattern; /* Violated prop_pattern */
    336 	value_t		*ite_value;	/* Non-conforming value */
    337 	error_info_t	ite_einfo;	/* Extra error information */
    338 	uu_list_node_t	ite_node;	/* Node to link us in a list. */
    339 } im_tmpl_error_t;
    340 
    341 /*
    342  * This structure holds the data that will be used by scf_tmpl_strerror()
    343  * for printing template validation errors.
    344  */
    345 typedef struct tv_errors {
    346 	scf_tmpl_errors_t *tve_errors;	/* Errors for scf_tmpl_strerror() */
    347 	uu_list_node_t	tve_node;	/* Linkage in a list. */
    348 } tv_errors_t;
    349 
    350 /*
    351  * Structure to collect template validation errors.
    352  */
    353 struct tmpl_errors {
    354 	uu_list_t	*te_list;	/* List of im_tmpl_error_t */
    355 	im_tmpl_error_t *te_next;	/* Next error to present */
    356 	uu_list_t	*te_scf;	/* Errors for scf_tmpl_strerror() */
    357 	tv_errors_t	*te_cur_scf;	/* Current member of te_scf */
    358 };
    359 
    360 /* End of structures used in error processing. */
    361 
    362 /*
    363  * Property group types that are of interest to us.  See pgroup_type().
    364  */
    365 typedef enum pg_type {
    366 	NORMAL_PG,
    367 	PG_PATTERN_PG,
    368 	PROP_PATTERN_PG
    369 } pg_type_t;
    370 
    371 /*
    372  * Structure to keep track of a set of ASTRING property values for a
    373  * property.  The consumer may wish to have the ASTRING property values
    374  * converted to a numeric form which is the reason for the av_v union.
    375  * This structure is returned by av_get_values() and is accessed by
    376  * av_get_integer(), av_get_string() and av_get_unsigned().
    377  */
    378 typedef struct avalues {
    379 	uint_t		av_count;	/* Number of values */
    380 	scf_type_t	av_type;	/* Type of value representation */
    381 	union {
    382 		uint64_t	*av_unsigned;	/* Count & boolean values */
    383 		int64_t		*av_integer;	/* Integer values */
    384 		const char 	**av_string;	/* String values */
    385 	} av_v;				/* Container for the values */
    386 } avalues_t;
    387 
    388 /*
    389  * composed_pg_t contains the information that is needed to compose a
    390  * property group.  See the section on Composed Properties in the block
    391  * comment at the beginning of this file.  The composed_pg structures are
    392  * linked into a uu_avl tree.  The tree is at sc_instance.sc_composed in
    393  * the entity_t.
    394  */
    395 struct composed_pg {
    396 	/*
    397 	 * Property group is uniquely identified by its name and type.
    398 	 * These two elements point to the name and type in a pgroup_t
    399 	 * (either service or instance), so they do not need to be
    400 	 * allocated or freed.
    401 	 */
    402 	const char	*cpg_name;
    403 	const char	*cpg_type;
    404 
    405 	/* References to the actual property group definitions. */
    406 	pgroup_t	*cpg_instance_pg;
    407 	pgroup_t	*cpg_service_pg;
    408 
    409 	/* Composed properties of the property group. */
    410 	uu_avl_t	*cpg_composed_props;
    411 
    412 	uu_avl_node_t	cpg_node;	/* Linkage for AVL tree */
    413 };
    414 
    415 /*
    416  * Prefixes for standard property names.  Used in
    417  * include_values_support().
    418  */
    419 typedef struct prop_prefix {
    420 	const char	*pp_prefix;
    421 	size_t		pp_size;
    422 } prop_prefix_t;
    423 
    424 /*
    425  * Store a legal range for a property allowing for either signed or
    426  * unsigned ranges.  It is used to store a range from a template
    427  * constraint element of a prop_pattern.  The structure is returned by
    428  * get_ranges() and is used by value_in_range() to validate the values of a
    429  * property.
    430  */
    431 typedef struct range {
    432 	union {
    433 		struct {
    434 			uint64_t	rng_min;
    435 			uint64_t	rng_max;
    436 		} rng_unsigned;
    437 		struct {
    438 			int64_t		rng_min;
    439 			int64_t		rng_max;
    440 		} rng_signed;
    441 	} rng_u;
    442 } range_t;
    443 
    444 /*
    445  * This enum defines the levels where templates can be defined.  See the
    446  * pg_iter structure below.
    447  */
    448 typedef enum tmpl_level {
    449 	TL_NOLEVEL = 0,		/* No level yet specified. */
    450 	TL_INSTANCE,		/* Instance templates. */
    451 	TL_COMPOSED,		/* Composed instance. */
    452 	TL_SERVICE,		/* Service wide templates. */
    453 	TL_RESTARTER,		/* Templates from restarter manifest. */
    454 	TL_GLOBAL		/* SMF wide templates. */
    455 } tmpl_level_t;
    456 
    457 /*
    458  * pg_iter is a structure that allows us to iterate through property groups
    459  * in an instance followed by the property groups of the instance's
    460  * service, the instance's restarter and finally the global service.  See
    461  * the Property Group Iteration section of the block comment at the
    462  * beginning of this file.
    463  */
    464 typedef struct pg_iter {
    465 	entity_t	*pgi_entity;	/* Entity being searched */
    466 	const char	*pgi_restrict;	/* Only return PGs of this type */
    467 	tmpl_level_t	pgi_level;	/* Current level */
    468 	entity_t	*pgi_service;	/* Service being processed. */
    469 	union {
    470 		pgroup_t	*pgi_pg;
    471 		composed_pg_t	*pgi_cpg;
    472 	} pgi_current;			/* Current property group. */
    473 } pg_iter_t;
    474 
    475 /*
    476  * enum to distinguish between pg_patterns and prop_patterns.  It is used
    477  * in the ptrn_info_t structure.  See below.
    478  */
    479 typedef enum ptrn_type {
    480 	PG_PATTERN,
    481 	PROP_PATTERN
    482 } ptrn_type_t;
    483 
    484 /*
    485  * Structure of information about a pg_pattern or a prop_pattern.  It is
    486  * used for template consistency checks.  gather_pattern() is used to
    487  * gather information for all the pg_patterns or prop_patterns in an
    488  * instance.  It allocates a ptrn_info_t for each of these and adds them to
    489  * an avl tree that is held by tmpl_consistency().
    490  */
    491 typedef struct ptrn_info {
    492 	ptrn_type_t	pi_ptrn_type;
    493 	pgroup_t	*pi_ptrnpg;	/* pgroup_t defining the pattern. */
    494 	const char	*pi_name;	/* Name attribute. */
    495 	const char	*pi_type;	/* Type attribute. */
    496 	const char	*pi_target;	/* Target attribute - only PG_PATTERN */
    497 	const char	*pi_pgp_name;	/* Name of the pg pattern.  Only */
    498 					/* used for PROP_PATTERN. */
    499 	pgroup_t	*pi_enc_pgp;	/* PG of the pg_pattern that holds */
    500 					/* the prop_pattern defined by this */
    501 					/* structure.  Only used for */
    502 					/* PROP_PATTERN. */
    503 	uu_avl_node_t	pi_link;	/* Linkage into AVL tree */
    504 } ptrn_info_t;
    505 
    506 static const char *emesg_nomem;
    507 
    508 /*
    509  * Pool for trees of composed property groups.
    510  */
    511 static uu_avl_pool_t *composed_pg_pool;
    512 
    513 /*
    514  * Pool for trees of composed properties.
    515  */
    516 static uu_avl_pool_t *composed_prop_pool;
    517 
    518 /*
    519  * Pool for lists of errors in the internal representation.
    520  */
    521 static uu_list_pool_t *inmem_errors_pool;
    522 
    523 /*
    524  * Pool for trees of pg_pattern info structures (ptrn_info_t).
    525  */
    526 static uu_avl_pool_t *ptrn_info_pool;
    527 
    528 /*
    529  * Pool for lists of template errors in the libscf representation.
    530  */
    531 static uu_list_pool_t *tv_errors_pool;
    532 
    533 /*
    534  * Property name prefixes for constraints and values.
    535  */
    536 static const char *constraint_prefixes[] = {
    537 	SCF_PROPERTY_TM_CONSTRAINT_NAME,
    538 	SCF_PROPERTY_TM_CONSTRAINT_RANGE,
    539 	NULL
    540 };
    541 static const char *value_prefixes[] = {
    542 	SCF_PROPERTY_TM_VALUE_PREFIX,
    543 	NULL
    544 };
    545 
    546 /*
    547  * Function to compare two composed_pg structures.
    548  */
    549 /* ARGSUSED2 */
    550 static int
    551 composed_pg_compare(const void *left, const void *right, void *unused)
    552 {
    553 	composed_pg_t *l = (composed_pg_t *)left;
    554 	composed_pg_t *r = (composed_pg_t *)right;
    555 	int rc;
    556 
    557 	if ((rc = strcmp(l->cpg_name, r->cpg_name)) == 0) {
    558 		rc = strcmp(l->cpg_type, r->cpg_type);
    559 	}
    560 	return (rc);
    561 }
    562 
    563 /* ARGSUSED2 */
    564 static int
    565 composed_prop_compare(const void *left, const void *right, void *unused)
    566 {
    567 	property_t *l = (property_t *)left;
    568 	property_t *r = (property_t *)right;
    569 
    570 	return (strcmp(l->sc_property_name, r->sc_property_name));
    571 }
    572 
    573 static composed_pg_t *
    574 composed_pg_create()
    575 {
    576 	composed_pg_t *cpg;
    577 
    578 	cpg = safe_malloc(sizeof (*cpg));
    579 	uu_avl_node_init(cpg, &cpg->cpg_node, composed_pg_pool);
    580 	return (cpg);
    581 }
    582 
    583 static void
    584 composed_pg_destroy(composed_pg_t *cpg)
    585 {
    586 	void *marker = NULL;
    587 	pgroup_t *pg;
    588 
    589 	if (cpg == NULL)
    590 		return;
    591 	/* Tear down composed property tree if we have one. */
    592 	if ((cpg->cpg_composed_props != NULL)) {
    593 		while (uu_avl_teardown(cpg->cpg_composed_props, &marker) !=
    594 		    NULL) {
    595 			/*
    596 			 * Nothing to do other than getting the property
    597 			 * out of the list.  This cleans up the property's
    598 			 * uu_avl_node.
    599 			 */
    600 		}
    601 		uu_avl_destroy(cpg->cpg_composed_props);
    602 	}
    603 
    604 	/* Clean up any pgroup_t references to us. */
    605 	if ((pg = cpg->cpg_instance_pg) != NULL) {
    606 		assert((pg->sc_pgroup_composed == NULL) ||
    607 		    (pg->sc_pgroup_composed == cpg));
    608 		pg->sc_pgroup_composed = NULL;
    609 	}
    610 
    611 	uu_avl_node_fini(cpg, &cpg->cpg_node, composed_pg_pool);
    612 	free(cpg);
    613 }
    614 
    615 /*
    616  * Walk the property group at pg, and add its properties to the AVL tree at
    617  * tree.
    618  */
    619 static void
    620 grow_props_tree(pgroup_t *pg, uu_avl_t *tree)
    621 {
    622 	uu_avl_index_t marker;
    623 	property_t *prop;
    624 
    625 	for (prop = uu_list_first(pg->sc_pgroup_props);
    626 	    prop != NULL;
    627 	    prop = uu_list_next(pg->sc_pgroup_props, prop)) {
    628 		if (uu_avl_find(tree, prop, NULL, &marker) == NULL) {
    629 			/*
    630 			 * If there was no match, insert the property into
    631 			 * the tree.  If we do get a match, there is
    632 			 * nothing to do.  That is because we rely on our
    633 			 * caller to process the instance properties first,
    634 			 * and the instance properties override the service
    635 			 * properties.
    636 			 */
    637 			uu_avl_insert(tree, prop, marker);
    638 		}
    639 	}
    640 }
    641 
    642 /*
    643  * The composed properties are stored in a uu_avl_tree.  First we populate
    644  * the tree with properties from the instance level property group.  Then,
    645  * we'll add the properties from the service level property group.
    646  */
    647 static void
    648 compose_props(composed_pg_t *cpg)
    649 {
    650 	uu_avl_t *tree;
    651 
    652 	tree = uu_avl_create(composed_prop_pool, cpg, TMPL_DEBUG_TREE);
    653 	if (tree == NULL) {
    654 		uu_die(gettext("composed_pool tree creation failed: %s\n"),
    655 		    uu_strerror(uu_error()));
    656 	}
    657 	cpg->cpg_composed_props = tree;
    658 
    659 	/*
    660 	 * compose_props() is only called when there is both an instance
    661 	 * and a service definition of the property group.  This implies
    662 	 * that neither cpg->cpg_instance_pg nor cpg->cpg_service_pg can be
    663 	 * NULL.
    664 	 */
    665 	/*
    666 	 * First add instance properties to the tree.
    667 	 */
    668 	assert(cpg->cpg_instance_pg != NULL);
    669 	grow_props_tree(cpg->cpg_instance_pg, tree);
    670 
    671 	/*
    672 	 * Add service properties to the tree.
    673 	 */
    674 	assert(cpg->cpg_service_pg != NULL);
    675 	grow_props_tree(cpg->cpg_service_pg, tree);
    676 }
    677 
    678 /*
    679  * This function is a utility for build_composed_instance().
    680  */
    681 static void
    682 build_composed_property_groups(entity_t *inst, uu_avl_t *tree)
    683 {
    684 	composed_pg_t *cpg;
    685 	uu_avl_index_t marker;
    686 	composed_pg_t *match;
    687 	pgroup_t *pg;
    688 	entity_t *svc;
    689 
    690 	/* First capture the instance property groups. */
    691 	for (pg = uu_list_first(inst->sc_pgroups);
    692 	    pg != NULL;
    693 	    pg = uu_list_next(inst->sc_pgroups, pg)) {
    694 		cpg = composed_pg_create();
    695 		cpg->cpg_name = pg->sc_pgroup_name;
    696 		cpg->cpg_type = pg->sc_pgroup_type;
    697 		cpg->cpg_instance_pg = pg;
    698 		match = uu_avl_find(tree, cpg, NULL, &marker);
    699 		/* Since we do the instance first, there should be no match. */
    700 		assert(match == NULL);
    701 		uu_avl_insert(tree, cpg, marker);
    702 		pg->sc_pgroup_composed = cpg;
    703 	}
    704 
    705 	/* Now capture the service property groups. */
    706 	svc = inst->sc_parent;
    707 	cpg = NULL;
    708 	for (pg = uu_list_first(svc->sc_pgroups);
    709 	    pg != NULL;
    710 	    pg = uu_list_next(svc->sc_pgroups, pg)) {
    711 		if (cpg == NULL)
    712 			cpg = composed_pg_create();
    713 		cpg->cpg_name = pg->sc_pgroup_name;
    714 		cpg->cpg_type = pg->sc_pgroup_type;
    715 		cpg->cpg_service_pg = pg;
    716 		match = uu_avl_find(tree, cpg, NULL, &marker);
    717 		if (match == NULL) {
    718 			uu_avl_insert(tree, cpg, marker);
    719 			/* Get new composed_pg_t next at top of loop. */
    720 			cpg = NULL;
    721 		} else {
    722 			/*
    723 			 * Already have a composed_pg from instance
    724 			 * processing.  Just add the pointer to the service
    725 			 * pg and compose the properties.
    726 			 */
    727 			match->cpg_service_pg = pg;
    728 			compose_props(match);
    729 		}
    730 	}
    731 	if (cpg != NULL)
    732 		composed_pg_destroy(cpg);
    733 }
    734 
    735 static void
    736 build_composed_instance(entity_t *inst)
    737 {
    738 	uu_avl_t *tree;
    739 
    740 	assert(inst->sc_etype == SVCCFG_INSTANCE_OBJECT);
    741 
    742 	if (inst->sc_u.sc_instance.sc_composed == NULL) {
    743 		tree = uu_avl_create(composed_pg_pool, inst, TMPL_DEBUG_TREE);
    744 		if (tree == NULL) {
    745 			uu_die(gettext("composed_instance tree creation "
    746 			    "failed: %s\n"), uu_strerror(uu_error()));
    747 		}
    748 		inst->sc_u.sc_instance.sc_composed = tree;
    749 	}
    750 	build_composed_property_groups(inst,
    751 	    inst->sc_u.sc_instance.sc_composed);
    752 }
    753 
    754 static void
    755 demolish_composed_instance(entity_t *inst)
    756 {
    757 	composed_pg_t *cpg;
    758 	void *marker = NULL;
    759 	uu_avl_t *tree;
    760 
    761 	tree = inst->sc_u.sc_instance.sc_composed;
    762 	if (tree == NULL)
    763 		return;
    764 
    765 	marker = NULL;
    766 	while ((cpg = uu_avl_teardown(tree, &marker)) != NULL) {
    767 		composed_pg_destroy(cpg);
    768 	}
    769 	uu_avl_destroy(tree);
    770 
    771 	inst->sc_u.sc_instance.sc_composed = NULL;
    772 }
    773 /*
    774  * Return the number of values in prop.
    775  */
    776 static size_t
    777 count_prop_values(property_t *prop)
    778 {
    779 	return (uu_list_numnodes(prop->sc_property_values));
    780 }
    781 
    782 static int
    783 is_numeric_type(scf_type_t type)
    784 {
    785 	if (type == SCF_TYPE_BOOLEAN)
    786 		return (1);
    787 	if (type == SCF_TYPE_COUNT)
    788 		return (1);
    789 	if (type == SCF_TYPE_INTEGER)
    790 		return (1);
    791 	return (0);
    792 }
    793 
    794 static pg_type_t
    795 pgroup_type(pgroup_t *pg)
    796 {
    797 	if (strcmp(pg->sc_pgroup_type, SCF_GROUP_TEMPLATE_PG_PATTERN) == 0)
    798 		return (PG_PATTERN_PG);
    799 	if (strcmp(pg->sc_pgroup_type, SCF_GROUP_TEMPLATE_PROP_PATTERN) == 0)
    800 		return (PROP_PATTERN_PG);
    801 	return (NORMAL_PG);
    802 }
    803 
    804 /*
    805  * Search the property group at pg for a property named name.  If the
    806  * property group has a tree of composed properties, the tree will be
    807  * searched for the property.  Otherwise, the property group's linked list
    808  * will be searched.
    809  */
    810 static property_t *
    811 property_find(pgroup_t *pg, const char *name)
    812 {
    813 	composed_pg_t *cpg;
    814 	property_t look;
    815 
    816 	cpg = pg->sc_pgroup_composed;
    817 
    818 	if ((cpg == NULL) || (cpg->cpg_composed_props == NULL)) {
    819 		/* This is not a composed property group. */
    820 		return (internal_property_find(pg, name));
    821 	}
    822 
    823 	/*
    824 	 * This is a composed property group, so look for the property in
    825 	 * the AVL tree.
    826 	 */
    827 	look.sc_property_name = (char *)name;
    828 	return (uu_avl_find(cpg->cpg_composed_props, &look, NULL, NULL));
    829 }
    830 
    831 /*
    832  * Functions for manipulating the avalues structure.
    833  */
    834 
    835 /*
    836  * Free allocated memory referenced by the avalues structure.  Then, free
    837  * the structure itself.
    838  */
    839 static void
    840 av_destroy(avalues_t *av)
    841 {
    842 	if (av == NULL)
    843 		return;
    844 	switch (av->av_type) {
    845 	case SCF_TYPE_BOOLEAN:
    846 	case SCF_TYPE_COUNT:
    847 		uu_free(av->av_v.av_unsigned);
    848 		break;
    849 	case SCF_TYPE_INTEGER:
    850 		uu_free(av->av_v.av_integer);
    851 		break;
    852 	default:
    853 		/*
    854 		 * We don't need to free the strings that are referenced by
    855 		 * av_string.  The strings are held in propery_t structures
    856 		 * that will be freed at a later time.
    857 		 */
    858 		uu_free(av->av_v.av_string);
    859 		break;
    860 	}
    861 	uu_free(av);
    862 }
    863 /*
    864  * Allocate and inialize an avalues structure.  count represents the
    865  * number of values the structure is expected to hold.  type specifies how
    866  * the consumer of the property values would like to see them represented.
    867  * See comments for the av_get_values() more details on how type is used.
    868  *
    869  * The returned structure must be freed by calling av_destroy().
    870  *
    871  * NULL is returned if memory allocation fails.
    872  */
    873 static avalues_t *
    874 av_create(size_t count, scf_type_t type)
    875 {
    876 	uint_t alloc_failed = 0;
    877 	avalues_t *av;
    878 
    879 	av = uu_zalloc(sizeof (*av));
    880 	if (av == NULL)
    881 		return (NULL);
    882 	av->av_count = count;
    883 	av->av_type = type;
    884 	switch (type) {
    885 	case SCF_TYPE_BOOLEAN:
    886 	case SCF_TYPE_COUNT:
    887 		av->av_v.av_unsigned = uu_zalloc(count * sizeof (uint64_t));
    888 		if (av->av_v.av_unsigned == NULL)
    889 			alloc_failed = 1;
    890 		break;
    891 	case SCF_TYPE_INTEGER:
    892 		av->av_v.av_integer = uu_zalloc(count * sizeof (int64_t));
    893 		if (av->av_v.av_integer == NULL)
    894 			alloc_failed = 1;
    895 		break;
    896 	default:
    897 		av->av_v.av_string = uu_zalloc(count * sizeof (char *));
    898 		if (av->av_v.av_string == NULL)
    899 			alloc_failed = 1;
    900 	}
    901 	if (alloc_failed) {
    902 		av_destroy(av);
    903 		return (NULL);
    904 	}
    905 	return (av);
    906 }
    907 
    908 /*
    909  * Return the ith integer value in av.
    910  */
    911 static int64_t
    912 av_get_integer(avalues_t *av, uint_t i)
    913 {
    914 	assert(av->av_type == SCF_TYPE_INTEGER);
    915 	assert(i < av->av_count);
    916 	return (*(av->av_v.av_integer + i));
    917 }
    918 
    919 /*
    920  * Return the ith string value in av.
    921  */
    922 static const char *
    923 av_get_string(avalues_t *av, uint_t i)
    924 {
    925 	assert(is_numeric_type(av->av_type) == 0);
    926 	assert(i < av->av_count);
    927 	return (*(av->av_v.av_string + i));
    928 }
    929 
    930 /*
    931  * Return the ith unsigned value in av.
    932  */
    933 static uint64_t
    934 av_get_unsigned(avalues_t *av, uint_t i)
    935 {
    936 	assert((av->av_type == SCF_TYPE_BOOLEAN) ||
    937 	    (av->av_type == SCF_TYPE_COUNT));
    938 	assert(i < av->av_count);
    939 	return (*(av->av_v.av_unsigned + i));
    940 }
    941 
    942 /*
    943  * Store the value in the ith slot of the av structure.  If av is being
    944  * used to store numeric values, the string at value will be converted to
    945  * the appropriate numeric form.
    946  */
    947 static tmpl_validate_status_t
    948 av_set_value(avalues_t *av, uint_t i, const char *value)
    949 {
    950 	char *endptr;
    951 	int64_t n;
    952 	uint64_t un;
    953 
    954 	if (is_numeric_type(av->av_type)) {
    955 		switch (av->av_type) {
    956 		case SCF_TYPE_BOOLEAN:
    957 		case SCF_TYPE_COUNT:
    958 			un = strtoull(value, &endptr, 0);
    959 			if ((endptr == value) || (*endptr != 0)) {
    960 				return (TVS_BAD_CONVERSION);
    961 			}
    962 			*(av->av_v.av_unsigned + i) = un;
    963 			break;
    964 		case SCF_TYPE_INTEGER:
    965 			n = strtoll(value, &endptr, 0);
    966 			if ((endptr == value) || (*endptr != 0)) {
    967 				return (TVS_BAD_CONVERSION);
    968 			}
    969 			*(av->av_v.av_integer + i) = n;
    970 		}
    971 	} else {
    972 		*(av->av_v.av_string + i) = value;
    973 	}
    974 
    975 	return (TVS_SUCCESS);
    976 }
    977 
    978 /*
    979  * Find the property whose name is prop_name in the property group at pg.
    980  * Read all the values of this property and return them in an avalues
    981  * structure placing the address of the structure in *values.  The caller
    982  * must free the structure by calling av_destroy().
    983  *
    984  * The type parameter is used to indicate the type of information that the
    985  * caller would like to consume.  If it is one of the numeric types, the
    986  * property value will be converted to the appropriate numeric type before
    987  * placing it in the avalues struct.  Decoding will be done before the
    988  * conversion if necessary.
    989  */
    990 static tmpl_validate_status_t
    991 av_get_values(pgroup_t *pg, const char *prop_name, scf_type_t type,
    992     avalues_t **values)
    993 {
    994 	avalues_t *av;
    995 	uint_t i;
    996 	property_t *prop;
    997 	tmpl_validate_status_t rc;
    998 	value_t *v;
    999 
   1000 	prop = property_find(pg, prop_name);
   1001 	if (prop == NULL) {
   1002 		return (TVS_NOMATCH);
   1003 	}
   1004 	assert(prop->sc_value_type == SCF_TYPE_ASTRING);
   1005 	av = av_create(count_prop_values(prop), type);
   1006 	if (av == NULL)
   1007 		uu_die(emesg_nomem);
   1008 
   1009 	/* Collect the values. */
   1010 	for ((v = uu_list_first(prop->sc_property_values)), i = 0;
   1011 	    v != NULL;
   1012 	    (v = uu_list_next(prop->sc_property_values, v)), i++) {
   1013 		assert(i < av->av_count);
   1014 		assert(v->sc_type == SCF_TYPE_ASTRING);
   1015 		rc = av_set_value(av, i, v->sc_u.sc_string);
   1016 		if (rc != TVS_SUCCESS) {
   1017 			av_destroy(av);
   1018 			return (rc);
   1019 		}
   1020 	}
   1021 	*values = av;
   1022 	return (TVS_SUCCESS);
   1023 }
   1024 
   1025 /*
   1026  * Find the property in pg whose name is prop_name.  Return a pointer to
   1027  * the first astring value in that property.
   1028  *
   1029  * NULL is returned if there is no property named prop_name or if it does
   1030  * not have an astring value.
   1031  */
   1032 static const char *
   1033 find_astring_value_in_pg(pgroup_t *pg, const char *prop_name)
   1034 {
   1035 	property_t *prop;
   1036 	value_t *v;
   1037 
   1038 	prop = property_find(pg, prop_name);
   1039 	if (prop == NULL)
   1040 		return (NULL);
   1041 	if (prop->sc_value_type != SCF_TYPE_ASTRING)
   1042 		return (NULL);
   1043 	v = uu_list_first(prop->sc_property_values);
   1044 	if (v == NULL)
   1045 		return (NULL);
   1046 	assert(v->sc_type == SCF_TYPE_ASTRING);
   1047 	return (v->sc_u.sc_string);
   1048 }
   1049 /*
   1050  * Find the first property value of type SCF_TYPE_COUNT in the property at
   1051  * prop.  Return the value to count.
   1052  */
   1053 static tmpl_validate_status_t
   1054 find_count_value(property_t *prop, uint64_t *count)
   1055 {
   1056 	value_t *value;
   1057 
   1058 	assert(prop->sc_value_type == SCF_TYPE_COUNT);
   1059 	value = uu_list_first(prop->sc_property_values);
   1060 	if (value == NULL)
   1061 		return (TVS_NOMATCH);
   1062 	*count = value->sc_u.sc_count;
   1063 	return (TVS_SUCCESS);
   1064 }
   1065 
   1066 /*
   1067  * pattern is a property group representing a pg_pattern or a
   1068  * prop_pattern.  This function returns the name specification from the
   1069  * pg_pattern or prop_pattern.
   1070  */
   1071 static const char *
   1072 find_name_specification(pgroup_t *pattern)
   1073 {
   1074 	return (find_astring_value_in_pg(pattern, SCF_PROPERTY_TM_NAME));
   1075 }
   1076 
   1077 /*
   1078  * pattern is a property group representing a pg_pattern or a prop_pattern.
   1079  * This function returns the type specification from the pg_pattern or
   1080  * prop_pattern.
   1081  */
   1082 static const char *
   1083 find_type_specification(pgroup_t *pattern)
   1084 {
   1085 	return (find_astring_value_in_pg(pattern, SCF_PROPERTY_TM_TYPE));
   1086 }
   1087 
   1088 /*
   1089  * Find the FMRI of the restarter for the entity, e.  The restarter is the
   1090  * value of the "restarter" property in the "general" property group.
   1091  */
   1092 static const char *
   1093 find_restarter(entity_t *e)
   1094 {
   1095 	pgroup_t *pg;
   1096 	property_t *prop;
   1097 	value_t *v;
   1098 
   1099 	pg = internal_pgroup_find(e, scf_pg_general, scf_group_framework);
   1100 	if (pg != NULL) {
   1101 		prop = property_find(pg, SCF_PROPERTY_RESTARTER);
   1102 		if ((prop != NULL) && (prop->sc_value_type == SCF_TYPE_FMRI)) {
   1103 			v = uu_list_first(prop->sc_property_values);
   1104 			if (v != NULL)
   1105 				return (v->sc_u.sc_string);
   1106 		}
   1107 	}
   1108 
   1109 	/*
   1110 	 * Didn't find the restarter.
   1111 	 */
   1112 	return (NULL);
   1113 }
   1114 
   1115 /*
   1116  * prop_pattern points to a prop_pattern.  This function finds the
   1117  * cardinality specification in the prop_pattern and returns the minimum
   1118  * and maximum values of the cardinality.
   1119  *
   1120  * Returns TVS_NOMATCH if either the cardinality minimum or maximum are
   1121  * missing.
   1122  */
   1123 static tmpl_validate_status_t
   1124 get_cardinality(pgroup_t *prop_pattern, uint64_t *min, uint64_t *max)
   1125 {
   1126 	property_t *prop;
   1127 	tmpl_validate_status_t rc;
   1128 
   1129 	assert(strcmp(prop_pattern->sc_pgroup_type,
   1130 	    SCF_GROUP_TEMPLATE_PROP_PATTERN) == 0);
   1131 
   1132 	prop = property_find(prop_pattern,
   1133 	    SCF_PROPERTY_TM_CARDINALITY_MIN);
   1134 	if (prop == NULL)
   1135 		return (TVS_NOMATCH);
   1136 	rc = find_count_value(prop, min);
   1137 	if (rc != TVS_SUCCESS)
   1138 		return (rc);
   1139 
   1140 	prop = property_find(prop_pattern,
   1141 	    SCF_PROPERTY_TM_CARDINALITY_MAX);
   1142 	if (prop == NULL)
   1143 		return (TVS_NOMATCH);
   1144 	rc = find_count_value(prop, max);
   1145 
   1146 	return (rc);
   1147 }
   1148 
   1149 /*
   1150  * Ranges are represented as ASTRING values in the property at range_prop.
   1151  * The minimum and maximum of the range are separated by a comma.
   1152  *
   1153  * range_prop can contain multiple range values, so we return a pointer to
   1154  * an allocated array of range_t in ranges.  This array must be freed by
   1155  * the caller using free().  count receives the number of range_t
   1156  * structures that are allocated.
   1157  *
   1158  * type tells us whether the range values should be treated as signed or
   1159  * unsigned.  It must be SCF_TYPE_COUNT or SCF_TYPE_INTEGER.
   1160  */
   1161 static tmpl_validate_status_t
   1162 get_ranges(property_t *range_prop, scf_type_t type, range_t **ranges,
   1163     uint_t *count)
   1164 {
   1165 	char *endptr;
   1166 	char *endptr2;
   1167 	range_t *r;
   1168 	value_t *value;
   1169 
   1170 	*count = uu_list_numnodes(range_prop->sc_property_values);
   1171 	assert(*count != 0);
   1172 	r = safe_malloc(*count * sizeof (*r));
   1173 	*ranges = r;
   1174 	for (value = uu_list_first(range_prop->sc_property_values);
   1175 	    value != NULL;
   1176 	    value = uu_list_next(range_prop->sc_property_values, value)) {
   1177 		assert(value->sc_type == SCF_TYPE_ASTRING);
   1178 
   1179 		/* First get the minimum */
   1180 		errno = 0;
   1181 		if (type == SCF_TYPE_INTEGER) {
   1182 			r->rng_u.rng_signed.rng_min =
   1183 			    strtoll(value->sc_u.sc_string, &endptr, 0);
   1184 		} else {
   1185 			r->rng_u.rng_unsigned.rng_min =
   1186 			    strtoull(value->sc_u.sc_string, &endptr, 0);
   1187 		}
   1188 		if ((errno != 0) || (endptr == value->sc_u.sc_string))
   1189 			goto badtemplate;
   1190 		if (*endptr != ',')
   1191 			goto badtemplate;
   1192 
   1193 		/* Now get the maximum */
   1194 		endptr++;
   1195 		if (type == SCF_TYPE_INTEGER) {
   1196 			r->rng_u.rng_signed.rng_max =
   1197 			    strtoll(endptr, &endptr2, 0);
   1198 		} else {
   1199 			r->rng_u.rng_unsigned.rng_max =
   1200 			    strtoull(endptr, &endptr2, 0);
   1201 		}
   1202 		if ((errno != 0) || (endptr2 == endptr) ||
   1203 		    (*endptr2 != 0))
   1204 			goto badtemplate;
   1205 		r++;
   1206 	}
   1207 
   1208 	return (TVS_SUCCESS);
   1209 
   1210 badtemplate:
   1211 	free(*ranges);
   1212 	*ranges = NULL;
   1213 	return (TVS_BAD_TEMPLATE);
   1214 }
   1215 
   1216 static tv_errors_t *
   1217 tv_errors_create(const char *fmri)
   1218 {
   1219 	tv_errors_t *ste;
   1220 
   1221 	ste = safe_malloc(sizeof (*ste));
   1222 	uu_list_node_init(ste, &ste->tve_node, tv_errors_pool);
   1223 	ste->tve_errors = _scf_create_errors(fmri, 1);
   1224 	if (ste->tve_errors == NULL)
   1225 		uu_die(emesg_nomem);
   1226 
   1227 	return (ste);
   1228 }
   1229 
   1230 static void
   1231 destroy_scf_errors(tv_errors_t *ste)
   1232 {
   1233 	scf_tmpl_errors_destroy(ste->tve_errors);
   1234 	uu_list_node_fini(ste, &ste->tve_node, tv_errors_pool);
   1235 	free(ste);
   1236 }
   1237 
   1238 /*
   1239  * Given a property group and the name of a property within that property
   1240  * group, generate the name of the property group that holds the
   1241  * prop_pattern information for the property.  The address of the generated
   1242  * name is returned to prop_pattern_pg_name.  The memory holding the
   1243  * generated name must be freed using uu_free().
   1244  */
   1245 static tmpl_validate_status_t
   1246 gen_prop_pattern_pg_name(pgroup_t *pg_pattern, const char *prop_name,
   1247     char **prop_pattern_pg_name)
   1248 {
   1249 	ssize_t limit;
   1250 	char *name;
   1251 	size_t prefix_size;
   1252 	const char *unique;
   1253 
   1254 	limit = scf_limit(SCF_LIMIT_MAX_NAME_LENGTH) + 1;
   1255 	assert(limit > 0);
   1256 
   1257 	/* Get the unique part of the pg_pattern's property group name. */
   1258 	prefix_size = strlen(SCF_PG_TM_PG_PAT_BASE);
   1259 	assert(strncmp(pg_pattern->sc_pgroup_name, SCF_PG_TM_PG_PAT_BASE,
   1260 	    prefix_size) == 0);
   1261 	unique = pg_pattern->sc_pgroup_name + prefix_size;
   1262 
   1263 	/* Construct the prop pattern property group name. */
   1264 	*prop_pattern_pg_name = NULL;
   1265 	name = uu_zalloc(limit);
   1266 	if (name == NULL)
   1267 		uu_die(emesg_nomem);
   1268 	if (snprintf(name, limit, "%s%s_%s", SCF_PG_TM_PROP_PATTERN_PREFIX,
   1269 	    unique, prop_name) >= limit) {
   1270 		uu_free(name);
   1271 		return (TVS_BAD_TEMPLATE);
   1272 	}
   1273 	*prop_pattern_pg_name = name;
   1274 	return (TVS_SUCCESS);
   1275 }
   1276 
   1277 /*
   1278  * Error message printing functions:
   1279  */
   1280 
   1281 /*
   1282  * Flags for use by im_perror_item.
   1283  */
   1284 #define	IPI_NOT_FIRST	0x1	/* Not first item to be displayed. */
   1285 
   1286 /*
   1287  * Print a single item of information about a validation failure.  This
   1288  * function takes care of printing the appropriate decoration before the
   1289  * first item and between subsequent items.
   1290  *
   1291  * Parameters:
   1292  *	out		Stream to receive the output.
   1293  *	desc		Text describing the items
   1294  *	item		Address of the item to be displayed
   1295  *	type		Type of the item
   1296  *	flags		Used by im_perror_item to keep track of where it
   1297  *			is.  Caller should set flags to 0 before calling
   1298  *			this function with the first item.
   1299  */
   1300 static void
   1301 im_perror_item(FILE *out, const char *desc, void *item, scf_type_t type,
   1302     int *flags)
   1303 {
   1304 	const char *cp;
   1305 	const char *first_sep;
   1306 	int64_t ival;
   1307 	const char *subsequent_sep;
   1308 	uint64_t uval;
   1309 
   1310 	/* Nothing to print if item is NULL. */
   1311 	if (item == NULL)
   1312 		return;
   1313 
   1314 	assert(type != SCF_TYPE_INVALID);
   1315 
   1316 	/* Establish separators for environment. */
   1317 	if (est->sc_cmd_flags & SC_CMD_IACTIVE) {
   1318 		/* Interactive mode - make messages readable */
   1319 		first_sep = ":\n\t";
   1320 		subsequent_sep = "\n\t";
   1321 	} else {
   1322 		/* Non-interactive - one line messages. */
   1323 		first_sep = ": ";
   1324 		subsequent_sep = "; ";
   1325 	}
   1326 
   1327 	/* Print separator and description */
   1328 	if (*flags & IPI_NOT_FIRST) {
   1329 		(void) fprintf(out, subsequent_sep);
   1330 	} else {
   1331 		(void) fprintf(out, first_sep);
   1332 		*flags |= IPI_NOT_FIRST;
   1333 	}
   1334 	(void) fprintf(out, "%s=", desc);
   1335 
   1336 	switch (type) {
   1337 	case SCF_TYPE_BOOLEAN:
   1338 		uval = *((uint64_t *)item);
   1339 		if (uval) {
   1340 			(void) fprintf(out, "\"%s\"", gettext("true"));
   1341 		} else {
   1342 			(void) fprintf(out, "\"%s\"", gettext("false"));
   1343 		}
   1344 		break;
   1345 	case SCF_TYPE_COUNT:
   1346 		uval = *((uint64_t *)item);
   1347 		(void) fprintf(out, "%" PRIu64, uval);
   1348 		break;
   1349 	case SCF_TYPE_INTEGER:
   1350 		ival = *((int64_t *)item);
   1351 		(void) fprintf(out, "%" PRIi64, ival);
   1352 		break;
   1353 	default:
   1354 		/*
   1355 		 * Treat everything else as a string, but escape any
   1356 		 * internal quotes.
   1357 		 */
   1358 		(void) fputc('\"', out);
   1359 		cp = (const char *)item;
   1360 		while (*cp != 0) {
   1361 			if (*cp == '\"') {
   1362 				(void) fprintf(out, "\\\"");
   1363 			} else {
   1364 				(void) fputc(*cp, out);
   1365 			}
   1366 			cp++;
   1367 		}
   1368 		(void) fputc('\"', out);
   1369 		break;
   1370 	}
   1371 }
   1372 
   1373 /*
   1374  * Print erroneous FMRI.
   1375  */
   1376 static void
   1377 im_perror_fmri(FILE *out, im_tmpl_error_t *i, int *flags)
   1378 {
   1379 	if (i->ite_entity != NULL) {
   1380 		im_perror_item(out, "FMRI", (void *)i->ite_entity->sc_fmri,
   1381 		    SCF_TYPE_FMRI, flags);
   1382 	}
   1383 }
   1384 
   1385 /*
   1386  * Print erroneous property group name.
   1387  */
   1388 static void
   1389 im_perror_pg_name(FILE *out, im_tmpl_error_t *i, int *flags)
   1390 {
   1391 	if (i->ite_pg != NULL) {
   1392 		im_perror_item(out, gettext("Property group"),
   1393 		    (void *)i->ite_pg->sc_pgroup_name, SCF_TYPE_ASTRING,
   1394 		    flags);
   1395 	}
   1396 }
   1397 
   1398 /*
   1399  * If srcflag is 1, print the template source of the pg_pattern or
   1400  * prop_pattern at pattern.  Always print the name and type of the pattern.
   1401  */
   1402 static void
   1403 im_perror_pattern_info(FILE *out, pgroup_t *pattern, int *flags, int srcflag)
   1404 {
   1405 	void *c;
   1406 	const char *name_string;
   1407 	const char *type_string;
   1408 
   1409 	if (pattern == NULL)
   1410 		return;
   1411 	switch (pgroup_type(pattern)) {
   1412 	case PG_PATTERN_PG:
   1413 		name_string = gettext("pg_pattern name");
   1414 		type_string = gettext("pg_pattern type");
   1415 		break;
   1416 	case PROP_PATTERN_PG:
   1417 		name_string = gettext("prop_pattern name");
   1418 		type_string = gettext("prop_pattern type");
   1419 		break;
   1420 	default:
   1421 		assert(0);
   1422 		abort();
   1423 	}
   1424 	if (srcflag) {
   1425 		im_perror_item(out, gettext("Template source"),
   1426 		    (void *)pattern->sc_parent->sc_fmri, SCF_TYPE_FMRI, flags);
   1427 	}
   1428 	c = (void *)find_name_specification(pattern);
   1429 	im_perror_item(out, name_string,
   1430 	    (c == NULL) ? "" : c, SCF_TYPE_ASTRING, flags);
   1431 	c = (void *)find_type_specification(pattern);
   1432 	im_perror_item(out, type_string,
   1433 	    (c == NULL) ? "" : c, SCF_TYPE_ASTRING, flags);
   1434 }
   1435 
   1436 /*
   1437  * Print information about the template specifications that were violated,
   1438  * so that the user can find the specification.
   1439  */
   1440 static void
   1441 im_perror_template_info(FILE *out, im_tmpl_error_t *i, int *flags)
   1442 {
   1443 	pgroup_t *pg_pattern = i->ite_pg_pattern;
   1444 	pgroup_t *prop_pattern = i->ite_prop_pattern;
   1445 	int srcflag = 1;
   1446 
   1447 	if (pg_pattern != NULL) {
   1448 		im_perror_pattern_info(out, pg_pattern, flags, srcflag);
   1449 		srcflag = 0;
   1450 	}
   1451 	if (prop_pattern != NULL) {
   1452 		im_perror_pattern_info(out, prop_pattern, flags, srcflag);
   1453 	}
   1454 }
   1455 
   1456 /* Print error message for TVS_BAD_CONVERSION errors. */
   1457 static void
   1458 im_perror_bad_conversion(FILE *out, im_tmpl_error_t *i, const char *prefix)
   1459 {
   1460 	int flags = 0;
   1461 
   1462 	(void) fprintf(out, gettext("%sUnable to convert property value"),
   1463 	    prefix);
   1464 	im_perror_fmri(out, i, &flags);
   1465 	im_perror_pg_name(out, i, &flags);
   1466 	im_perror_item(out, gettext("Property"),
   1467 	    (void *)i->ite_prop->sc_property_name, SCF_TYPE_ASTRING, &flags);
   1468 	im_perror_template_info(out, i, &flags);
   1469 	(void) fputc('\n', out);
   1470 }
   1471 
   1472 /* Print error message for TVS_BAD_TEMPLATE errors. */
   1473 static void
   1474 im_perror_bad_template(FILE *out, im_tmpl_error_t *i, const char *prefix)
   1475 {
   1476 	int flags = 0;
   1477 
   1478 	assert(i->ite_einfo.ei_type == EIT_BAD_TEMPLATE);
   1479 	(void) fprintf(out, gettext("%sInvalid template - %s"), prefix,
   1480 	    i->ite_einfo.ei_u.ei_bad_template.ei_reason);
   1481 	im_perror_fmri(out, i, &flags);
   1482 	im_perror_template_info(out, i, &flags);
   1483 	(void) fputc('\n', out);
   1484 }
   1485 
   1486 /*
   1487  * Print error message for TVS_INVALID_TYPE_SPECIFICATION errors.  This
   1488  * error occurs if a prop_pattern has an invalid type specification.  Thus,
   1489  * it is an indication of an invalid template rather than a violation of a
   1490  * template.
   1491  */
   1492 static void
   1493 im_perror_invalid_type(FILE *out, im_tmpl_error_t *i, const char *prefix)
   1494 {
   1495 	int flags = 0;
   1496 	const char *prop_pattern_name;
   1497 
   1498 	(void) fprintf(out, gettext("%sInvalid type in prop_pattern"), prefix);
   1499 	im_perror_pg_name(out, i, &flags);
   1500 	if (i->ite_prop_pattern != NULL) {
   1501 		prop_pattern_name =
   1502 		    find_name_specification(i->ite_prop_pattern);
   1503 		im_perror_item(out, gettext("prop_pattern name"),
   1504 		    (void *)prop_pattern_name, SCF_TYPE_ASTRING, &flags);
   1505 	}
   1506 	im_perror_template_info(out, i, &flags);
   1507 	(void) fputc('\n', out);
   1508 }
   1509 
   1510 /*
   1511  * Print error message for TVS_MISSING_PG_TYPE errors.  In this case the
   1512  * template specifies a type, but the property group itself has no type.
   1513  */
   1514 static void
   1515 im_perror_missing_pg_type(FILE *out, im_tmpl_error_t *i, const char *prefix)
   1516 {
   1517 	int flags = 0;
   1518 	const char *type_spec;
   1519 
   1520 	(void) fprintf(out, gettext("%sProperty group has no type"), prefix);
   1521 	im_perror_fmri(out, i, &flags);
   1522 	im_perror_pg_name(out, i, &flags);
   1523 	if (i->ite_pg_pattern != NULL) {
   1524 		type_spec = find_type_specification(i->ite_pg_pattern);
   1525 		im_perror_item(out, gettext("Type specified in pg_pattern"),
   1526 		    (void *)type_spec, SCF_TYPE_ASTRING, &flags);
   1527 	}
   1528 	(void) fputc('\n', out);
   1529 }
   1530 
   1531 /*
   1532  * Print error message for TVS_MISSING_TYPE_SPECIFICATION errors.  A
   1533  * property group has a "required" attribute of true, but it does not have
   1534  * a type specification.
   1535  */
   1536 static void
   1537 im_perror_missing_type(FILE *out, im_tmpl_error_t *i, const char *prefix)
   1538 {
   1539 	int flags = 0;
   1540 	const char *pg_pattern_name;
   1541 
   1542 	(void) fprintf(out, gettext("%sPg_pattern with true required attribute "
   1543 	    "is missing the type attribute"), prefix);
   1544 	im_perror_fmri(out, i, &flags);
   1545 	if (i->ite_pg_pattern != NULL) {
   1546 		pg_pattern_name = find_name_specification(i->ite_pg_pattern);
   1547 		im_perror_item(out, gettext("Pg_pattern name"),
   1548 		    (void *)pg_pattern_name, SCF_TYPE_ASTRING, &flags);
   1549 	}
   1550 	im_perror_template_info(out, i, &flags);
   1551 	(void) fputc('\n', out);
   1552 }
   1553 
   1554 static void
   1555 im_tmpl_error_print(FILE *out, im_tmpl_error_t *ite, const char *prefix)
   1556 {
   1557 	switch (ite->ite_type) {
   1558 	case TVS_BAD_CONVERSION:
   1559 		im_perror_bad_conversion(out, ite, prefix);
   1560 		break;
   1561 	case TVS_BAD_TEMPLATE:
   1562 		im_perror_bad_template(out, ite, prefix);
   1563 		break;
   1564 	case TVS_INVALID_TYPE_SPECIFICATION:
   1565 		im_perror_invalid_type(out, ite, prefix);
   1566 		break;
   1567 	case TVS_MISSING_PG_TYPE:
   1568 		im_perror_missing_pg_type(out, ite, prefix);
   1569 		break;
   1570 	case TVS_MISSING_TYPE_SPECIFICATION:
   1571 		im_perror_missing_type(out, ite, prefix);
   1572 		break;
   1573 	case TVS_NOMATCH:
   1574 		/*
   1575 		 * TVS_NOMATCH should be handled where it occurs.  Thus,
   1576 		 * there are no error messages associated with it.
   1577 		 */
   1578 		assert(0);
   1579 		abort();
   1580 		break;
   1581 	case TVS_SUCCESS:
   1582 		break;
   1583 	default:
   1584 		assert(0);
   1585 		abort();
   1586 	}
   1587 }
   1588 
   1589 static char *
   1590 int64_to_str(int64_t i)
   1591 {
   1592 	char *c;
   1593 	const char *fmt;
   1594 	int size;
   1595 
   1596 	fmt = "%" PRIi64;
   1597 	size = snprintf(NULL, 0, fmt, i) + 1;
   1598 	c = safe_malloc(size);
   1599 	(void) snprintf(c, size, fmt, i);
   1600 	return (c);
   1601 }
   1602 
   1603 static char *
   1604 uint64_to_str(uint64_t u)
   1605 {
   1606 	char *c;
   1607 	const char *fmt;
   1608 	int size;
   1609 
   1610 	fmt = "%" PRIu64;
   1611 	size = snprintf(NULL, 0, fmt, u) + 1;
   1612 	c = safe_malloc(size);
   1613 	(void) snprintf(c, size, fmt, u);
   1614 	return (c);
   1615 }
   1616 
   1617 /*
   1618  * Convert the value to a string.  The returned value must be freed using
   1619  * free(3C).
   1620  */
   1621 static const char *
   1622 value_to_string(value_t *v)
   1623 {
   1624 	char *c;
   1625 
   1626 	if (is_numeric_type(v->sc_type)) {
   1627 		switch (v->sc_type) {
   1628 		case SCF_TYPE_BOOLEAN:
   1629 			if (v->sc_u.sc_count == 0) {
   1630 				c = gettext("false");
   1631 			} else {
   1632 				c = gettext("true");
   1633 			}
   1634 			break;
   1635 		case SCF_TYPE_COUNT:
   1636 			c = uint64_to_str(v->sc_u.sc_count);
   1637 			return (c);
   1638 		case SCF_TYPE_INTEGER:
   1639 			c = int64_to_str(v->sc_u.sc_integer);
   1640 			return (c);
   1641 		}
   1642 	} else {
   1643 		c = v->sc_u.sc_string;
   1644 	}
   1645 
   1646 	return (safe_strdup(c));
   1647 }
   1648 
   1649 /*
   1650  * Subscripts for common error data.
   1651  */
   1652 #define	ED_PG_NAME	0
   1653 #define	ED_PROP_NAME	1
   1654 #define	ED_TMPL_FMRI	2
   1655 #define	ED_TMPL_PG_NAME	3
   1656 #define	ED_TMPL_PG_TYPE	4
   1657 #define	ED_TMPL_PROP_NAME	5
   1658 #define	ED_TMPL_PROP_TYPE	6
   1659 #define	ED_COUNT	7
   1660 
   1661 /*
   1662  * This function converts the error information specified by the function
   1663  * parameters.  It converts it to form needed by _scf_tmpl_add_error().
   1664  * _scf_tmpl_add_error() requires that the error information be in the form
   1665  * of allocated strings that can be freed when it is done with them.  Thus,
   1666  * the bulk of this function is devoted to producing those allocated
   1667  * strings.
   1668  *
   1669  * Once the strings are ready, we call _scf_tmpl_add_error() to add an
   1670  * new error structure to errs.
   1671  */
   1672 static int
   1673 add_scf_error(tmpl_errors_t *errs, scf_tmpl_error_type_t ec,
   1674     pgroup_t *pg_pattern, pgroup_t *pg, pgroup_t *prop_pattern,
   1675     property_t *prop, value_t *val, error_info_t *einfo)
   1676 {
   1677 	const char *actual = NULL;
   1678 	char *c;
   1679 	pgroup_t *conflict;
   1680 	const char *ed[ED_COUNT];
   1681 	const char *ev1 = NULL;
   1682 	const char *ev2 = NULL;
   1683 	int i;
   1684 	scf_type_t prop_type;
   1685 	int rc;
   1686 
   1687 	(void) memset(ed, 0, sizeof (ed));
   1688 
   1689 	/* Set values that are common to most error types. */
   1690 	if (pg != NULL) {
   1691 		ed[ED_PG_NAME] = pg->sc_pgroup_name;
   1692 	}
   1693 	if (prop != NULL) {
   1694 		ed[ED_PROP_NAME] = prop->sc_property_name;
   1695 	}
   1696 	if (pg_pattern == NULL) {
   1697 		if (prop_pattern != NULL) {
   1698 			ed[ED_TMPL_FMRI] = prop_pattern->sc_parent->sc_fmri;
   1699 		}
   1700 	} else {
   1701 		ed[ED_TMPL_FMRI] = pg_pattern->sc_parent->sc_fmri;
   1702 		ed[ED_TMPL_PG_NAME] = find_name_specification(pg_pattern);
   1703 		ed[ED_TMPL_PG_TYPE] = find_type_specification(pg_pattern);
   1704 	}
   1705 	if (prop_pattern != NULL) {
   1706 		ed[ED_TMPL_PROP_NAME] = find_name_specification(prop_pattern);
   1707 		ed[ED_TMPL_PROP_TYPE] = find_type_specification(prop_pattern);
   1708 	}
   1709 
   1710 	/*
   1711 	 * All of the strings that we've found must be strduped.  This is
   1712 	 * so that scf_tmpl_errors_destroy() can free them.  We cannot use
   1713 	 * the flag argument of _scf_create_errors() to indicate that the
   1714 	 * strings should not be freed.  The flag argument is an all or
   1715 	 * nothing thing.  In the code below we need to convert integers to
   1716 	 * strings, and this requires memory allocation.  Since we have to
   1717 	 * allocate memory for that data, we need to allocate it for every
   1718 	 * thing.
   1719 	 */
   1720 	for (i = 0; i < ED_COUNT; i++) {
   1721 		if (ed[i] == NULL)
   1722 			continue;
   1723 		ed[i] = safe_strdup(ed[i]);
   1724 	}
   1725 
   1726 	/* actual, ev1 and ev2 are error code specific. */
   1727 	switch (ec) {
   1728 	case SCF_TERR_CARDINALITY_VIOLATION:
   1729 		assert(einfo != NULL);
   1730 		assert(einfo->ei_type == EIT_CARDINALITY);
   1731 		ev1 = uint64_to_str(einfo->ei_u.ei_cardinality.ei_min);
   1732 		ev2 = uint64_to_str(einfo->ei_u.ei_cardinality.ei_max);
   1733 		actual = uint64_to_str(einfo->ei_u.ei_cardinality.ei_count);
   1734 		break;
   1735 	case SCF_TERR_WRONG_PG_TYPE:
   1736 		/* Specified type. */
   1737 		if (pg_pattern != NULL) {
   1738 			ev1 = find_type_specification(pg_pattern);
   1739 			if (ev1 != NULL) {
   1740 				ev1 = safe_strdup(ev1);
   1741 			}
   1742 		}
   1743 		/* Actual type. */
   1744 		if (pg != NULL) {
   1745 			actual = pg->sc_pgroup_type;
   1746 			if (actual != NULL) {
   1747 				actual = safe_strdup(actual);
   1748 			}
   1749 		}
   1750 		break;
   1751 	case SCF_TERR_WRONG_PROP_TYPE:
   1752 		assert(einfo->ei_type == EIT_PROP_TYPE);
   1753 		prop_type = einfo->ei_u.ei_prop_type.ei_specified;
   1754 		ev1 = safe_strdup(scf_type_to_string(prop_type));
   1755 		prop_type = einfo->ei_u.ei_prop_type.ei_actual;
   1756 		actual = safe_strdup(scf_type_to_string(prop_type));
   1757 		break;
   1758 	case SCF_TERR_VALUE_CONSTRAINT_VIOLATED:
   1759 		actual = value_to_string(val);
   1760 		break;
   1761 	case SCF_TERR_MISSING_PG:
   1762 		assert(einfo->ei_type == EIT_MISSING_PG);
   1763 		ev1 = safe_strdup(einfo->ei_u.ei_missing_pg.ei_pg_name);
   1764 		ev2 = safe_strdup(einfo->ei_u.ei_missing_pg.ei_pg_type);
   1765 		break;
   1766 	case SCF_TERR_MISSING_PROP:
   1767 		assert(einfo->ei_type == EIT_MISSING_PROP);
   1768 		ev1 = safe_strdup(einfo->ei_u.ei_missing_prop.ei_prop_name);
   1769 		break;
   1770 	case SCF_TERR_RANGE_VIOLATION:
   1771 		assert(einfo->ei_type == EIT_RANGE);
   1772 		if (einfo->ei_u.ei_range.ei_rtype == SCF_TYPE_COUNT) {
   1773 			c = uint64_to_str(einfo->ei_u.ei_range.ei_uvalue);
   1774 		} else {
   1775 			c = int64_to_str(einfo->ei_u.ei_range.ei_ivalue);
   1776 		}
   1777 		actual = c;
   1778 		break;
   1779 	case SCF_TERR_PG_PATTERN_CONFLICT:
   1780 	case SCF_TERR_PROP_PATTERN_CONFLICT:
   1781 	case SCF_TERR_GENERAL_REDEFINE:
   1782 		assert(einfo->ei_type == EIT_PATTERN_CONFLICT);
   1783 		conflict = einfo->ei_u.ei_pattern_conflict.ei_pattern;
   1784 		ev1 = safe_strdup(conflict->sc_parent->sc_fmri);
   1785 		ev2 = find_name_specification(conflict);
   1786 		if (ev2 != NULL)
   1787 			ev2 = safe_strdup(ev2);
   1788 		actual = find_type_specification(conflict);
   1789 		if (actual != NULL)
   1790 			actual = safe_strdup(actual);
   1791 		break;
   1792 	case SCF_TERR_INCLUDE_VALUES:
   1793 		assert(einfo->ei_type == EIT_INCLUDE_VALUES);
   1794 		ev1 = safe_strdup(einfo->ei_u.ei_inc_values.ei_type);
   1795 		break;
   1796 	case SCF_TERR_PG_PATTERN_INCOMPLETE:
   1797 	case SCF_TERR_PROP_PATTERN_INCOMPLETE:
   1798 		break;
   1799 	default:
   1800 		assert(0);
   1801 		abort();
   1802 	};
   1803 
   1804 	rc = _scf_tmpl_add_error(errs->te_cur_scf->tve_errors, ec,
   1805 	    ed[ED_PG_NAME], ed[ED_PROP_NAME], ev1, ev2, actual,
   1806 	    ed[ED_TMPL_FMRI], ed[ED_TMPL_PG_NAME], ed[ED_TMPL_PG_TYPE],
   1807 	    ed[ED_TMPL_PROP_NAME], ed[ED_TMPL_PROP_TYPE]);
   1808 
   1809 	return (rc);
   1810 }
   1811 
   1812 /*
   1813  * Create and initialize a new im_tmpl_error structure and add it to the
   1814  * list of errors in errs.  The rest of the parameters are used to
   1815  * initialize the im_tmpl_error structure.
   1816  */
   1817 static tmpl_validate_status_t
   1818 tmpl_errors_add_im(tmpl_errors_t *errs, tmpl_validate_status_t ec, entity_t *e,
   1819     pgroup_t *pg_pattern, pgroup_t *pg, pgroup_t *prop_pattern,
   1820     property_t *prop, value_t *val, error_info_t *einfo)
   1821 {
   1822 	im_tmpl_error_t *ite;
   1823 	int result;
   1824 
   1825 	ite = uu_zalloc(sizeof (*ite));
   1826 	if (ite == NULL)
   1827 		uu_die(emesg_nomem);
   1828 	uu_list_node_init(ite, &ite->ite_node, inmem_errors_pool);
   1829 	ite->ite_type = ec;
   1830 	ite->ite_entity = e;
   1831 	ite->ite_pg = pg;
   1832 	ite->ite_pg_pattern = pg_pattern;
   1833 	ite->ite_prop = prop;
   1834 	ite->ite_prop_pattern = prop_pattern;
   1835 	ite->ite_value = val;
   1836 	if (einfo != NULL)
   1837 		ite->ite_einfo = *einfo;
   1838 
   1839 	result = uu_list_insert_after(errs->te_list, NULL, ite);
   1840 	assert(result == 0);
   1841 	return (TVS_SUCCESS);
   1842 }
   1843 
   1844 /*
   1845  * pattern must point to a pg_pattern or a prop_pattern.  This function
   1846  * finds the property named required and returns the property's value.  If
   1847  * the property does not exist, false is return since it is the default.
   1848  */
   1849 static int
   1850 is_required(pgroup_t *pattern)
   1851 {
   1852 	property_t *required;
   1853 	value_t *value;
   1854 
   1855 	assert((strcmp(pattern->sc_pgroup_type,
   1856 	    SCF_GROUP_TEMPLATE_PG_PATTERN) == 0) ||
   1857 	    (strcmp(pattern->sc_pgroup_type,
   1858 	    SCF_GROUP_TEMPLATE_PROP_PATTERN) == 0));
   1859 
   1860 	required = property_find(pattern, SCF_PROPERTY_TM_REQUIRED);
   1861 
   1862 	/* Default if there is no required property is false. */
   1863 	if (required == NULL)
   1864 		return (0);
   1865 
   1866 	/* Retrieve the value of the required property. */
   1867 	value = uu_list_first(required->sc_property_values);
   1868 	if (value == NULL)
   1869 		return (0);
   1870 	if (value->sc_type == SCF_TYPE_BOOLEAN)
   1871 		return (value->sc_u.sc_count == 0 ? 0 : 1);
   1872 
   1873 	/* No boolean property values, so return false. */
   1874 	return (0);
   1875 }
   1876 
   1877 /*
   1878  * Load the service's restarter instance and the global instance from the
   1879  * repository.  This will allow us to use their templates in validating the
   1880  * service.
   1881  *
   1882  * There is no function to unload the general templates.  The memory that
   1883  * is allocated by load_general_templates() will be freed automatically in
   1884  * internal_service_free() which is called by internal_bundle_free().
   1885  */
   1886 static void
   1887 load_general_templates(entity_t *svc)
   1888 {
   1889 	const char *restarter;
   1890 	int is_global = 0;
   1891 	int r;
   1892 
   1893 	assert(svc->sc_etype == SVCCFG_SERVICE_OBJECT);
   1894 
   1895 	/*
   1896 	 * If e is the global service, we only need to load the restarter.
   1897 	 */
   1898 	if ((strcmp(svc->sc_fmri, SCF_INSTANCE_GLOBAL) == 0) ||
   1899 	    (strcmp(svc->sc_fmri, SCF_SERVICE_GLOBAL) == 0)) {
   1900 		is_global = 1;
   1901 	}
   1902 
   1903 	/*
   1904 	 * Load the templates for the service's restarter.
   1905 	 */
   1906 	restarter = find_restarter(svc);
   1907 	if (restarter == NULL)
   1908 		restarter = SCF_SERVICE_STARTD;
   1909 	if ((r = load_instance(restarter, "restarter",
   1910 	    &svc->sc_u.sc_service.sc_restarter)) != 0) {
   1911 		/*
   1912 		 * During initial manifest import, restarter may
   1913 		 * not be in the repository yet.  In this case we
   1914 		 * continue on without it.
   1915 		 */
   1916 		if (r == EINVAL)
   1917 			warn(gettext("WARNING: restarter FMRI %s is invalid\n"),
   1918 			    restarter);
   1919 
   1920 		if (r == ENOTSUP)
   1921 			warn(gettext("WARNING: restarter FMRI %s is not valid; "
   1922 			    "instance fmri required.\n"), restarter);
   1923 
   1924 		if (r == ENOMEM)
   1925 			uu_die(emesg_nomem);
   1926 
   1927 		svc->sc_u.sc_service.sc_restarter = NULL;
   1928 	}
   1929 	if (is_global == 0) {
   1930 		if ((r = load_instance(SCF_INSTANCE_GLOBAL, "global",
   1931 		    &svc->sc_u.sc_service.sc_global)) != 0) {
   1932 			/*
   1933 			 * During initial manifest import, global may not be in
   1934 			 * the repository yet.
   1935 			 */
   1936 			if (r == ENOMEM)
   1937 				uu_die(emesg_nomem);
   1938 			else
   1939 				svc->sc_u.sc_service.sc_global = NULL;
   1940 		}
   1941 	}
   1942 }
   1943 
   1944 /*
   1945  * Load the instance specific restarter if one is declared.
   1946  *
   1947  * There is no corresponding unload_instance_restarter() function because
   1948  * it is not needed.  The memory will be freed in internal_instance_free()
   1949  * when internal_bundle_free() is called.
   1950  */
   1951 static void
   1952 load_instance_restarter(entity_t *i)
   1953 {
   1954 	const char *restarter;
   1955 	int r;
   1956 
   1957 	assert(i->sc_etype == SVCCFG_INSTANCE_OBJECT);
   1958 
   1959 	restarter = find_restarter(i);
   1960 	if (restarter == NULL) {
   1961 		/* No instance specific restarter */
   1962 		return;
   1963 	}
   1964 	r = load_instance(restarter, "instance_restarter",
   1965 	    &i->sc_u.sc_instance.sc_instance_restarter);
   1966 	if (r != 0) {
   1967 		/*
   1968 		 * During initial manifest import, the restarter may not be
   1969 		 * in the repository yet.  In this case we continue on
   1970 		 * without it.
   1971 		 */
   1972 		if (r == EINVAL)
   1973 			warn(gettext("WARNING: restarter FMRI %s is invalid\n"),
   1974 			    restarter);
   1975 
   1976 		if (r == ENOTSUP)
   1977 			warn(gettext("WARNING: restarter FMRI %s is not valid; "
   1978 			    "instance fmri required.\n"), restarter);
   1979 
   1980 		if (r == ENOMEM)
   1981 			uu_die(emesg_nomem);
   1982 	}
   1983 }
   1984 
   1985 /*
   1986  * Find the next property after current in the property group at pg.  If
   1987  * the property group contains a tree of composed properties, that tree is
   1988  * walked.  Otherwise, we walk through the uu_list at sc_pgroup_props.
   1989  */
   1990 static property_t *
   1991 next_property(pgroup_t *pg, property_t *current)
   1992 {
   1993 	composed_pg_t *cpg;
   1994 	property_t *prop;
   1995 
   1996 	cpg = pg->sc_pgroup_composed;
   1997 	if ((cpg != NULL) && (cpg->cpg_composed_props != NULL)) {
   1998 		/* Walk through composed property list. */
   1999 		if (current) {
   2000 			prop = uu_avl_next(cpg->cpg_composed_props, current);
   2001 		} else {
   2002 			prop = uu_avl_first(cpg->cpg_composed_props);
   2003 		}
   2004 	} else {
   2005 		/* No composition available, so walk the list of properties */
   2006 		if (current) {
   2007 			prop = uu_list_next(pg->sc_pgroup_props, current);
   2008 		} else {
   2009 			prop = uu_list_first(pg->sc_pgroup_props);
   2010 		}
   2011 	}
   2012 
   2013 	return (prop);
   2014 }
   2015 
   2016 static ptrn_info_t *
   2017 ptrn_info_create(pgroup_t *pat)
   2018 {
   2019 	entity_t *e;
   2020 	ptrn_info_t *info;
   2021 	composed_pg_t *match;
   2022 	composed_pg_t cpg;
   2023 
   2024 	info = safe_malloc(sizeof (*info));
   2025 
   2026 	switch (pgroup_type(pat)) {
   2027 	case PG_PATTERN_PG:
   2028 		info->pi_ptrn_type = PG_PATTERN;
   2029 		break;
   2030 	case PROP_PATTERN_PG:
   2031 		info->pi_ptrn_type = PROP_PATTERN;
   2032 		break;
   2033 	default:
   2034 		assert(0);
   2035 		abort();
   2036 	}
   2037 	info->pi_ptrnpg = pat;
   2038 	info->pi_name = find_name_specification(pat);
   2039 	info->pi_name = EMPTY_TO_NULL(info->pi_name);
   2040 	info->pi_type = find_type_specification(pat);
   2041 	info->pi_type = EMPTY_TO_NULL(info->pi_type);
   2042 	if (info->pi_ptrn_type == PG_PATTERN) {
   2043 		info->pi_target = find_astring_value_in_pg(pat,
   2044 		    SCF_PROPERTY_TM_TARGET);
   2045 		if (info->pi_target == NULL)
   2046 			info->pi_target = SCF_TM_TARGET_THIS;
   2047 	}
   2048 	if (info->pi_ptrn_type == PROP_PATTERN) {
   2049 		info->pi_pgp_name = find_astring_value_in_pg(pat,
   2050 		    SCF_PROPERTY_TM_PG_PATTERN);
   2051 		assert((info->pi_pgp_name != NULL) &&
   2052 		    (*(info->pi_pgp_name) != 0));
   2053 
   2054 		/*
   2055 		 * Find the property group that defines the pg_pattern that
   2056 		 * holds this prop_pattern.
   2057 		 */
   2058 		e = pat->sc_parent;
   2059 		if (e->sc_etype == SVCCFG_INSTANCE_OBJECT) {
   2060 			(void) memset(&cpg, 0, sizeof (cpg));
   2061 			cpg.cpg_name = info->pi_pgp_name;
   2062 			cpg.cpg_type = SCF_GROUP_TEMPLATE_PG_PATTERN;
   2063 			match = uu_avl_find(e->sc_u.sc_instance.sc_composed,
   2064 			    &cpg, NULL, NULL);
   2065 			assert(match != NULL);
   2066 			info->pi_enc_pgp = CPG2PG(match);
   2067 		} else {
   2068 			info->pi_enc_pgp = internal_pgroup_find(e,
   2069 			    info->pi_pgp_name, SCF_GROUP_TEMPLATE_PG_PATTERN);
   2070 		}
   2071 		assert(info->pi_enc_pgp != NULL);
   2072 	}
   2073 	uu_avl_node_init(info, &info->pi_link, ptrn_info_pool);
   2074 	return (info);
   2075 }
   2076 
   2077 static void
   2078 ptrn_info_destroy(ptrn_info_t *info)
   2079 {
   2080 	if (info == NULL)
   2081 		return;
   2082 	uu_avl_node_fini(info, &info->pi_link, ptrn_info_pool);
   2083 	free(info);
   2084 }
   2085 
   2086 /*
   2087  * Walk through the property groups of the instance or service at e looking
   2088  * for definitions of pg_patterns or prop_patterns as specified by type.
   2089  * For each property group that matches type create a ptrn_info_t and add
   2090  * it to the avl tree at tree.  If duplicates are found add an error entry
   2091  * to errs.
   2092  */
   2093 static tmpl_validate_status_t
   2094 gather_pattern(entity_t *e, ptrn_type_t type, uu_avl_t *tree,
   2095     tmpl_errors_t *errs)
   2096 {
   2097 	error_info_t einfo;
   2098 	ptrn_info_t *info = NULL;
   2099 	uu_avl_index_t marker;
   2100 	ptrn_info_t *match;
   2101 	pgroup_t *pg;
   2102 	tmpl_validate_status_t rc = TVS_SUCCESS;
   2103 	const char *selector;
   2104 
   2105 	switch (type) {
   2106 	case PG_PATTERN:
   2107 		selector = SCF_GROUP_TEMPLATE_PG_PATTERN;
   2108 		break;
   2109 	case PROP_PATTERN:
   2110 		selector = SCF_GROUP_TEMPLATE_PROP_PATTERN;
   2111 		break;
   2112 	default:
   2113 		assert(0);
   2114 		abort();
   2115 	}
   2116 
   2117 	for (pg = uu_list_first(e->sc_pgroups);
   2118 	    pg != NULL;
   2119 	    pg = uu_list_next(e->sc_pgroups, pg)) {
   2120 		if (strcmp(pg->sc_pgroup_type, selector) != 0) {
   2121 			continue;
   2122 		}
   2123 		if (info != NULL) {
   2124 			/* Get rid of old structure. */
   2125 			ptrn_info_destroy(info);
   2126 		}
   2127 		info = ptrn_info_create(pg);
   2128 		match = uu_avl_find(tree, info, NULL, &marker);
   2129 		if (match == NULL) {
   2130 			/* No match.  Insert the info. */
   2131 			uu_avl_insert(tree, info, marker);
   2132 			info = NULL;
   2133 			continue;
   2134 		}
   2135 
   2136 		/* Got a match.  Determine if it is a conflict. */
   2137 		if ((info->pi_name == NULL) ||
   2138 		    (info->pi_type == NULL) ||
   2139 		    (match->pi_name == NULL) ||
   2140 		    (match->pi_type == NULL)) {
   2141 			/* No conflicts if any wild cards. */
   2142 			continue;
   2143 		}
   2144 
   2145 		/*
   2146 		 * Name already matches, or we wouldn't have gotten
   2147 		 * here.  Make sure that the type also matches.
   2148 		 */
   2149 		if (strcmp(info->pi_type, match->pi_type) == 0) {
   2150 			continue;
   2151 		}
   2152 
   2153 		/*
   2154 		 * If we get to this point we have a conflict, and
   2155 		 * we need to generate the correct type of error.
   2156 		 */
   2157 		CLEAR_ERROR_INFO(&einfo);
   2158 		einfo.ei_type = EIT_PATTERN_CONFLICT;
   2159 		einfo.ei_u.ei_pattern_conflict.ei_pattern =
   2160 		    match->pi_ptrnpg;
   2161 		if (type == PG_PATTERN) {
   2162 			rc = TVS_VALIDATION;
   2163 			if (add_scf_error(errs, SCF_TERR_PG_PATTERN_CONFLICT,
   2164 			    info->pi_ptrnpg, NULL, NULL, NULL, NULL,
   2165 			    &einfo) != 0) {
   2166 				/*
   2167 				 * If we can no longer accumulate
   2168 				 * errors, break out of the loop.
   2169 				 */
   2170 				break;
   2171 			}
   2172 		} else {
   2173 			/*
   2174 			 * Possible conflicting prop_pattern.  See if the
   2175 			 * prop_patterns are declared in the same
   2176 			 * pg_pattern.
   2177 			 */
   2178 			if ((info->pi_pgp_name == NULL) ||
   2179 			    (match->pi_pgp_name == NULL)) {
   2180 				continue;
   2181 			}
   2182 			if (strcmp(info->pi_pgp_name, match->pi_pgp_name) != 0)
   2183 				continue;
   2184 
   2185 			/* It is a real conflict. */
   2186 			rc = TVS_VALIDATION;
   2187 			if (add_scf_error(errs, SCF_TERR_PROP_PATTERN_CONFLICT,
   2188 			    info->pi_enc_pgp, NULL, info->pi_ptrnpg, NULL, NULL,
   2189 			    &einfo) != 0) {
   2190 				/*
   2191 				 * If we can no longer accumulate
   2192 				 * errors, break out of the loop.
   2193 				 */
   2194 				break;
   2195 			}
   2196 		}
   2197 	}
   2198 
   2199 	ptrn_info_destroy(info);
   2200 	return (rc);
   2201 }
   2202 
   2203 /*
   2204  * Free the pg_iter structure.
   2205  */
   2206 static void
   2207 pg_iter_destroy(pg_iter_t *i)
   2208 {
   2209 	if (i == NULL)
   2210 		return;
   2211 
   2212 	uu_free(i);
   2213 }
   2214 
   2215 /*
   2216  * Create a property group iterator for the instance at e.  This iterator
   2217  * will walk through the composed property groups of the instance.  It will
   2218  * then step through the property groups of the instance's restarter and
   2219  * finally the global service.  If you wish to iterate over a specific type
   2220  * of property group, set restriction to point the the desired type.
   2221  * Otherwise set restriction to NULL.
   2222  *
   2223  * The returned interator must be freed by calling pg_iter_destroy().  NULL
   2224  * is returned if we are unable to allocate the necessary memory.
   2225  */
   2226 static pg_iter_t *
   2227 pg_iter_create(entity_t *e, const char *restriction)
   2228 {
   2229 	pg_iter_t *i;
   2230 
   2231 	assert(e->sc_etype == SVCCFG_INSTANCE_OBJECT);
   2232 
   2233 	i = uu_zalloc(sizeof (*i));
   2234 	if (i == NULL)
   2235 		return (NULL);
   2236 
   2237 	i->pgi_entity = e;
   2238 	i->pgi_restrict = restriction;
   2239 	i->pgi_level = TL_COMPOSED;
   2240 	i->pgi_service = e->sc_parent;
   2241 
   2242 	return (i);
   2243 }
   2244 
   2245 /*
   2246  * Return the next property group in the iteration.  NULL is returned if we
   2247  * reach the end of the list.  The iterator will automatically proceed from
   2248  * most specific to most general levels.
   2249  */
   2250 static pgroup_t *
   2251 next_pattern_pg(pg_iter_t *i)
   2252 {
   2253 	composed_pg_t *cpg;
   2254 	entity_t *e;
   2255 	pgroup_t *pg;
   2256 	uu_avl_t *composed_tree;
   2257 
   2258 	assert(i->pgi_level != TL_NOLEVEL);
   2259 
   2260 	while (i->pgi_entity != NULL) {
   2261 		if (i->pgi_level == TL_COMPOSED) {
   2262 			composed_tree =
   2263 			    i->pgi_entity->sc_u.sc_instance.sc_composed;
   2264 			cpg = i->pgi_current.pgi_cpg;
   2265 			if (cpg == NULL) {
   2266 				cpg = uu_avl_first(composed_tree);
   2267 			} else {
   2268 				cpg = uu_avl_next(composed_tree, cpg);
   2269 			}
   2270 			if (cpg == NULL) {
   2271 				pg = NULL;
   2272 			} else {
   2273 				pg = CPG2PG(cpg);
   2274 				i->pgi_current.pgi_cpg = cpg;
   2275 			}
   2276 		} else {
   2277 			pg = i->pgi_current.pgi_pg;
   2278 			if (pg == NULL) {
   2279 				pg = uu_list_first(i->pgi_entity->sc_pgroups);
   2280 			} else {
   2281 				pg = uu_list_next(i->pgi_entity->sc_pgroups,
   2282 				    pg);
   2283 			}
   2284 			i->pgi_current.pgi_pg = pg;
   2285 		}
   2286 
   2287 		if (pg == NULL) {
   2288 			/*
   2289 			 * End of the list.  Reset current and break out of
   2290 			 * the loop.
   2291 			 */
   2292 			(void) memset(&i->pgi_current, 0,
   2293 			    sizeof (i->pgi_current));
   2294 			break;
   2295 		}
   2296 
   2297 		/*
   2298 		 * If this iteration is for a specific type, verify that
   2299 		 * this pg is of that type.
   2300 		 */
   2301 		if (i->pgi_restrict) {
   2302 			if (strcmp(pg->sc_pgroup_type, i->pgi_restrict) != 0) {
   2303 				continue;
   2304 			}
   2305 		}
   2306 
   2307 		return (pg);
   2308 	}
   2309 
   2310 	/*
   2311 	 * End of the list in the current level.  Move up to the next
   2312 	 * level.
   2313 	 */
   2314 	switch (i->pgi_level) {
   2315 	case TL_COMPOSED:
   2316 		/* Skip service if we've finished a composed instance. */
   2317 		e = i->pgi_entity;
   2318 		if (e->sc_u.sc_instance.sc_instance_restarter == NULL) {
   2319 			/* Use service restarter */
   2320 			i->pgi_entity =
   2321 			    i->pgi_service->sc_u.sc_service.sc_restarter;
   2322 		} else {
   2323 			/* Use instance restarter */
   2324 			i->pgi_entity =
   2325 			    e->sc_u.sc_instance.sc_instance_restarter;
   2326 		}
   2327 		i->pgi_level = TL_RESTARTER;
   2328 		break;
   2329 	case TL_RESTARTER:
   2330 		i->pgi_entity = i->pgi_service->sc_u.sc_service.sc_global;
   2331 		i->pgi_level = TL_GLOBAL;
   2332 		break;
   2333 	case TL_GLOBAL:
   2334 		i->pgi_level = TL_NOLEVEL;
   2335 		return (NULL);
   2336 	default:
   2337 		assert(0);
   2338 		abort();
   2339 	}
   2340 
   2341 	/* Go process the next level. */
   2342 	return (next_pattern_pg(i));
   2343 }
   2344 
   2345 /*
   2346  * Compare two pattern info structures (ptrn_info_t).  If both structures
   2347  * have names, the comparison is based on the name.  If only one has a
   2348  * name, the structure with no name will be first.  If neither structure
   2349  * has a name, the comparison is based on their types using similar wild
   2350  * card logic.
   2351  */
   2352 /* ARGSUSED2 */
   2353 static int
   2354 ptrn_info_compare(const  void *left, const void *right, void *unused)
   2355 {
   2356 	ptrn_info_t *l = (ptrn_info_t *)left;
   2357 	ptrn_info_t *r = (ptrn_info_t *)right;
   2358 
   2359 	if ((l->pi_name != NULL) && (r->pi_name != NULL))
   2360 		return (strcmp(l->pi_name, r->pi_name));
   2361 	if ((l->pi_name == NULL) && (r->pi_name == NULL)) {
   2362 		/* No names, so we need to compare types. */
   2363 		if ((l->pi_type != NULL) && (r->pi_type != NULL))
   2364 			return (strcmp(l->pi_type, r->pi_type));
   2365 		if ((l->pi_type == NULL) && (r->pi_type == NULL))
   2366 			return (0);
   2367 
   2368 		/* If we get here, exactly one of the types is NULL */
   2369 		if (l->pi_type == NULL)
   2370 			return (-1);
   2371 		return (1);
   2372 	}
   2373 
   2374 	/* If we get here, exactly one of the names is NULL */
   2375 	if (l->pi_name == NULL)
   2376 		return (-1);
   2377 	return (1);
   2378 }
   2379 
   2380 /*
   2381  * The target of a pg_pattern in combination with the level at which the
   2382  * pg_pattern was defined determines whether or not it should be applied.
   2383  * The following combinations should be ignored, and all others should be
   2384  * applied.
   2385  *
   2386  *	Target		Level
   2387  *	------		-----
   2388  *	this		TL_RESTARTER, TL_GLOBAL
   2389  *			"this" only applies if the pg_pattern was defined
   2390  *			at the instance or service level
   2391  *	delegate	TL_INSTANCE, TL_SERVICE
   2392  *			Only restarters and the global service can
   2393  *			delegate.
   2394  *	instance	TL_INSTANCE, TL_RESTARTER, TL_GLOBAL
   2395  *			Only the service level can specify the "instance"
   2396  *			target.
   2397  *	all		TL_INSTANCE, TL_SERVICE, TL_RESTARTER
   2398  *			Only the global service can specify the "all"
   2399  *			target.
   2400  *
   2401  * Return Values:
   2402  *	1	apply the pg_pattern
   2403  *	0	ignore the pg_pattern
   2404  */
   2405 static int
   2406 target_check(const char *target, tmpl_level_t level)
   2407 {
   2408 	if ((target == NULL) || (*target == 0)) {
   2409 		/* Default is this */
   2410 		target = SCF_TM_TARGET_THIS;
   2411 	}
   2412 	if (strcmp(target, SCF_TM_TARGET_THIS) == 0) {
   2413 		if ((level == TL_RESTARTER) ||
   2414 		    (level == TL_GLOBAL)) {
   2415 			return (0);
   2416 		} else {
   2417 			return (1);
   2418 		}
   2419 	}
   2420 	if (strcmp(target, SCF_TM_TARGET_DELEGATE) == 0) {
   2421 		if ((level == TL_INSTANCE) ||
   2422 		    (level == TL_SERVICE)) {
   2423 			return (0);
   2424 		} else {
   2425 			return (1);
   2426 		}
   2427 	}
   2428 	if (strcmp(target, SCF_TM_TARGET_INSTANCE) == 0) {
   2429 		/*
   2430 		 * Note that the test is inverted from the other cases.
   2431 		 * This is because there is only one instance where apply
   2432 		 * is the correct thing to do.
   2433 		 */
   2434 		if (level == TL_SERVICE) {
   2435 			return (1);
   2436 		} else {
   2437 			return (0);
   2438 		}
   2439 	}
   2440 	if (strcmp(target, SCF_TM_TARGET_ALL) == 0) {
   2441 		if ((level == TL_INSTANCE) ||
   2442 		    (level == TL_SERVICE) ||
   2443 		    (level == TL_RESTARTER)) {
   2444 			return (0);
   2445 		}
   2446 	}
   2447 	return (1);
   2448 }
   2449 
   2450 static int
   2451 pg_target_check(pgroup_t *pg_pattern, tmpl_level_t level)
   2452 {
   2453 	const char *target;
   2454 
   2455 	target = find_astring_value_in_pg(pg_pattern, SCF_PROPERTY_TM_TARGET);
   2456 	if (level == TL_COMPOSED) {
   2457 		switch (pg_pattern->sc_parent->sc_etype) {
   2458 		case SVCCFG_INSTANCE_OBJECT:
   2459 			level = TL_INSTANCE;
   2460 			break;
   2461 		case SVCCFG_SERVICE_OBJECT:
   2462 			level = TL_SERVICE;
   2463 			break;
   2464 		default:
   2465 			assert(0);
   2466 			abort();
   2467 		}
   2468 	}
   2469 	return (target_check(target, level));
   2470 }
   2471 
   2472 /*
   2473  * Find the prop_pattern's type sepcification and convert it to the
   2474  * appropriate scf_type.
   2475  */
   2476 static tmpl_validate_status_t
   2477 prop_pattern_type(pgroup_t *pattern, scf_type_t *type)
   2478 {
   2479 	const char *type_spec;
   2480 
   2481 	assert(strcmp(pattern->sc_pgroup_type,
   2482 	    SCF_GROUP_TEMPLATE_PROP_PATTERN) == 0);
   2483 
   2484 	type_spec = find_type_specification(pattern);
   2485 	if ((type_spec == NULL) || (*type_spec == 0))
   2486 		return (TVS_MISSING_TYPE_SPECIFICATION);
   2487 	*type = scf_string_to_type(type_spec);
   2488 	return (TVS_SUCCESS);
   2489 }
   2490 
   2491 /*
   2492  * This function is analagous to scf_property_is_type(3SCF), but it works
   2493  * on the in memory representation of the property.
   2494  *
   2495  * RETURNS:
   2496  *	0		The property at prop does not have the specified
   2497  *			type.
   2498  *	non-zero	The property at prop does have the specified type.
   2499  */
   2500 static int
   2501 property_is_type(property_t *prop, scf_type_t type)
   2502 {
   2503 	return (scf_is_compatible_type(type, prop->sc_value_type) ==
   2504 	    SCF_SUCCESS);
   2505 }
   2506 
   2507 /*
   2508  * This function generates a property group name for a template's
   2509  * pg_pattern.  The name and type of the pg_pattern are used to construct
   2510  * the name, but either or both may be null.  A pointer to the constructed
   2511  * name is returned, and the referenced memory must be freed using
   2512  * free(3c).  NULL is returned if we are unable to allocate enough memory.
   2513  */
   2514 static char *
   2515 gen_pg_pattern_pg_name(const char *name, const char *type)
   2516 {
   2517 	char *pg_name;
   2518 	char *rv = NULL;
   2519 	ssize_t	name_size;
   2520 
   2521 	name_size = scf_limit(SCF_LIMIT_MAX_NAME_LENGTH);
   2522 	pg_name = safe_malloc(name_size);
   2523 	rv = pg_name;
   2524 
   2525 	/*
   2526 	 * There are four cases -- name and type are both null, name and
   2527 	 * type are both non-null, only name is present or only type is
   2528 	 * present.
   2529 	 */
   2530 	if ((name == NULL) || (*name == 0)) {
   2531 		if ((type == NULL) || (*type == 0)) {
   2532 			/*
   2533 			 * Name and type are both null, so the PG name
   2534 			 * contains only the prefix.
   2535 			 */
   2536 			if (strlcpy(pg_name, SCF_PG_TM_PG_PATTERN_PREFIX,
   2537 			    name_size) >= name_size) {
   2538 				rv = NULL;
   2539 			}
   2540 		} else {
   2541 			/*
   2542 			 * If we have a type and no name, the type becomes
   2543 			 * part of the pg_pattern property group name.
   2544 			 */
   2545 			if (snprintf(pg_name, name_size, "%s%s",
   2546 			    SCF_PG_TM_PG_PATTERN_T_PREFIX, type) >=
   2547 			    name_size) {
   2548 				rv = NULL;
   2549 			}
   2550 		}
   2551 	} else {
   2552 		/*
   2553 		 * As long as the pg_pattern has a name, it becomes part of
   2554 		 * the name of the pg_pattern property group name.  We
   2555 		 * merely need to pick the appropriate prefix.
   2556 		 */
   2557 		const char *prefix;
   2558 		if ((type == NULL) || (*type == 0)) {
   2559 			prefix = SCF_PG_TM_PG_PATTERN_N_PREFIX;
   2560 		} else {
   2561 			prefix = SCF_PG_TM_PG_PATTERN_NT_PREFIX;
   2562 		}
   2563 		if (snprintf(pg_name, name_size, "%s%s", prefix, name) >=
   2564 		    name_size) {
   2565 			rv = NULL;
   2566 		}
   2567 	}
   2568 
   2569 	if (rv == NULL) {
   2570 		/* Name was too big. */
   2571 		free(pg_name);
   2572 	}
   2573 	return (rv);
   2574 }
   2575 
   2576 /*
   2577  * pinfo contains information about a prop_pattern.  An include_values
   2578  * element with a type of type has been included in the prop_pattern
   2579  * specification.  We need to determine if the prop_pattern also contains
   2580  * constraints or values specifications as determined by type.  Thus, we
   2581  * search the prop_pattern for properties whose names start with the
   2582  * correct prefix.
   2583  */
   2584 static tmpl_validate_status_t
   2585 include_values_support(ptrn_info_t *pinfo, const char *type,
   2586     tmpl_errors_t *errs)
   2587 {
   2588 	error_info_t einfo;
   2589 	int i;
   2590 	const char **prefixes;
   2591 	const char *pfx;
   2592 	property_t *prop;
   2593 	pgroup_t *ptrn;
   2594 
   2595 	if (strcmp(type, "constraints") == 0) {
   2596 		prefixes = constraint_prefixes;
   2597 	} else if (strcmp(type, "values") == 0) {
   2598 		prefixes = value_prefixes;
   2599 	} else {
   2600 		CLEAR_ERROR_INFO(&einfo);
   2601 		einfo.ei_type = EIT_BAD_TEMPLATE;
   2602 		einfo.ei_u.ei_bad_template.ei_reason = gettext("include_values "
   2603 		    "type must be \"constraints\" or \"values\"");
   2604 		(void) tmpl_errors_add_im(errs, TVS_BAD_TEMPLATE,
   2605 		    pinfo->pi_ptrnpg->sc_parent, pinfo->pi_enc_pgp,
   2606 		    NULL, pinfo->pi_ptrnpg, NULL, NULL, &einfo);
   2607 		return (TVS_BAD_TEMPLATE);
   2608 	}
   2609 
   2610 	/*
   2611 	 * Now see if the prop_pattern has a property whose name starts
   2612 	 * with one of these prefixes.
   2613 	 */
   2614 	ptrn = pinfo->pi_ptrnpg;
   2615 	for (prop = uu_list_first(ptrn->sc_pgroup_props);
   2616 	    prop != NULL;
   2617 	    prop = uu_list_next(ptrn->sc_pgroup_props, prop)) {
   2618 		for (pfx = prefixes[0], i = 0;
   2619 		    pfx != NULL;
   2620 		    ++i, pfx = prefixes[i]) {
   2621 			if (strncmp(prop->sc_property_name, pfx,
   2622 			    strlen(pfx)) == 0) {
   2623 				return (TVS_SUCCESS);
   2624 			}
   2625 		}
   2626 	}
   2627 
   2628 	/* No match found.  Generate error */
   2629 	CLEAR_ERROR_INFO(&einfo);
   2630 	einfo.ei_type = EIT_INCLUDE_VALUES;
   2631 	einfo.ei_u.ei_inc_values.ei_type = type;
   2632 	(void) add_scf_error(errs, SCF_TERR_INCLUDE_VALUES, pinfo->pi_enc_pgp,
   2633 	    NULL, ptrn, NULL, NULL, &einfo);
   2634 
   2635 	return (TVS_VALIDATION);
   2636 }
   2637 
   2638 /*
   2639  * Walk through the prop_patterns in tree, looking for any that have an
   2640  * include_values, SCF_PROPERTY_TM_CHOICES_INCLUDE_VALUES, property.  For
   2641  * the prop_patterns with the include values property, verify that the
   2642  * prop_pattern has constraint or values declarations as specified by the
   2643  * include_values property.
   2644  */
   2645 static tmpl_validate_status_t
   2646 tmpl_include_values_check(uu_avl_t *tree, tmpl_errors_t *errs)
   2647 {
   2648 	ptrn_info_t *info;
   2649 	property_t *iv;
   2650 	tmpl_validate_status_t r;
   2651 	tmpl_validate_status_t rc = TVS_SUCCESS;
   2652 	value_t *v;
   2653 
   2654 	for (info = uu_avl_first(tree);
   2655 	    info != NULL;
   2656 	    info = uu_avl_next(tree, info)) {
   2657 		iv = internal_property_find(info->pi_ptrnpg,
   2658 		    SCF_PROPERTY_TM_CHOICES_INCLUDE_VALUES);
   2659 		if (iv == NULL)
   2660 			continue;
   2661 		for (v = uu_list_first(iv->sc_property_values);
   2662 		    v != NULL;
   2663 		    v = uu_list_next(iv->sc_property_values, v)) {
   2664 			assert(is_numeric_type(v->sc_type) == 0);
   2665 			r = include_values_support(info, v->sc_u.sc_string,
   2666 			    errs);
   2667 			if (r != TVS_SUCCESS)
   2668 				rc = r;
   2669 		}
   2670 	}
   2671 	return (rc);
   2672 }
   2673 
   2674 /*
   2675  * Verify that there are no conflicting definitions of pg_pattern or
   2676  * prop_pattern.  Two patterns are said to be in conflict if they have the
   2677  * same name and differing types.  There is a caveat, however.  Empty
   2678  * pattern names or types are considered to be wild cards.  There is no
   2679  * conflict if a pattern has a wild card.
   2680  */
   2681 static tmpl_validate_status_t
   2682 tmpl_pattern_conflict(entity_t *inst, uu_avl_t *tree, ptrn_type_t type,
   2683     tmpl_errors_t *errs)
   2684 {
   2685 	tmpl_validate_status_t r;
   2686 	tmpl_validate_status_t rc;
   2687 
   2688 	/* First walk the instance. */
   2689 	rc = gather_pattern(inst, type, tree, errs);
   2690 
   2691 	/* Now walk the service */
   2692 	r = gather_pattern(inst->sc_parent, type, tree, errs);
   2693 	if (r != TVS_SUCCESS)
   2694 		rc = r;
   2695 
   2696 	return (rc);
   2697 }
   2698 
   2699 static tmpl_validate_status_t
   2700 tmpl_required_attr_present(uu_avl_t *tree, tmpl_errors_t *errs)
   2701 {
   2702 	ptrn_info_t *pinfo;
   2703 	tmpl_validate_status_t rc = TVS_SUCCESS;
   2704 	int reported_name;
   2705 	int rv;
   2706 
   2707 	for (pinfo = uu_avl_first(tree);
   2708 	    pinfo != NULL;
   2709 	    pinfo = uu_avl_next(tree, pinfo)) {
   2710 		if (is_required(pinfo->pi_ptrnpg) == 0) {
   2711 			/* Nothing to check if pattern is not required. */
   2712 			continue;
   2713 		}
   2714 
   2715 		/*
   2716 		 * For pg_pattern both name and type are optional unless
   2717 		 * the required attribute has a value of true.  For
   2718 		 * prop_patterns only the type is optional, but it must be
   2719 		 * provided if the required attribute has a value of true.
   2720 		 */
   2721 		reported_name = 0;
   2722 		if ((pinfo->pi_ptrn_type == PG_PATTERN) &&
   2723 		    (pinfo->pi_name == NULL)) {
   2724 			rc = TVS_VALIDATION;
   2725 			if (add_scf_error(errs, SCF_TERR_PG_PATTERN_INCOMPLETE,
   2726 			    pinfo->pi_ptrnpg,
   2727 			    NULL, NULL, NULL, NULL, NULL) != 0) {
   2728 				/*
   2729 				 * If we're unable to report errors, break
   2730 				 * out of the loop.
   2731 				 */
   2732 				break;
   2733 			}
   2734 			/*
   2735 			 * Don't report the error twice if both name and
   2736 			 * type are missing.  One error message is
   2737 			 * adequate.
   2738 			 */
   2739 			reported_name = 1;
   2740 		}
   2741 		if ((pinfo->pi_type == NULL) && (reported_name == 0)) {
   2742 			rc = TVS_VALIDATION;
   2743 			if (pinfo->pi_ptrn_type == PG_PATTERN) {
   2744 				rv = add_scf_error(errs,
   2745 				    SCF_TERR_PG_PATTERN_INCOMPLETE,
   2746 				    pinfo->pi_ptrnpg,
   2747 				    NULL, NULL, NULL, NULL, NULL);
   2748 			} else {
   2749 				rv = add_scf_error(errs,
   2750 				    SCF_TERR_PROP_PATTERN_INCOMPLETE,
   2751 				    pinfo->pi_enc_pgp, NULL, pinfo->pi_ptrnpg,
   2752 				    NULL, NULL, NULL);
   2753 			}
   2754 			/* If we're unable to log errors, break out of loop. */
   2755 			if (rv != 0)
   2756 				break;
   2757 		}
   2758 	}
   2759 	return (rc);
   2760 }
   2761 
   2762 /*
   2763  * Look for pg_pattern definitions in general.  general is either the
   2764  * restarter serivce for inst or it is the global service.  tree contains
   2765  * the ptrn_info_t structures describing the pg_patterns for an instance.
   2766  * For each general pg_pattern, see if the instance contains an overriding
   2767  * definition in tree.  If it does generate an error entry.
   2768  *
   2769  * If a redefinition is found, TVS_WARN is returned.  This is because a
   2770  * redefinition is not sufficient reason to inhibit the import operation.
   2771  */
   2772 static tmpl_validate_status_t
   2773 tmpl_scan_general(entity_t *general, uu_avl_t *tree,
   2774     tmpl_level_t level, tmpl_errors_t *errs)
   2775 {
   2776 	tmpl_level_t cur_level;
   2777 	error_info_t einfo;
   2778 	pgroup_t *pg;
   2779 	ptrn_info_t *ginfo = NULL;
   2780 	ptrn_info_t *match;
   2781 	tmpl_validate_status_t rc = TVS_SUCCESS;
   2782 
   2783 	/*
   2784 	 * General services may not be in repository yet.  It depends on
   2785 	 * the order that manifests are imported.
   2786 	 */
   2787 	if (general == NULL)
   2788 		return (TVS_SUCCESS);
   2789 
   2790 	for (pg = uu_list_first(general->sc_pgroups);
   2791 	    pg != NULL;
   2792 	    pg = uu_list_next(general->sc_pgroups, pg)) {
   2793 		if (strcmp(pg->sc_pgroup_type,
   2794 		    SCF_GROUP_TEMPLATE_PG_PATTERN) != 0) {
   2795 			/* Not a pg_pattern */
   2796 			continue;
   2797 		}
   2798 		if (ginfo != NULL)
   2799 			ptrn_info_destroy(ginfo);
   2800 		ginfo = ptrn_info_create(pg);
   2801 		match = uu_avl_find(tree, ginfo, NULL, NULL);
   2802 		if (match != NULL) {
   2803 			/* See if global pg_pattern is targeted at us. */
   2804 			if (target_check(ginfo->pi_target, level) == 0)
   2805 				continue;
   2806 
   2807 			/*
   2808 			 * See if the match applies to us.  If we happen to
   2809 			 * be a restarter, the pg_pattern could have a
   2810 			 * target of delegate.  That wouldn't apply to this
   2811 			 * instance, it would only apply to our delegates.
   2812 			 * Cases such as this are not a redefinition.
   2813 			 */
   2814 			if (match->pi_ptrnpg->sc_parent->sc_etype ==
   2815 			    SVCCFG_INSTANCE_OBJECT) {
   2816 				cur_level = TL_INSTANCE;
   2817 			} else {
   2818 				cur_level = TL_SERVICE;
   2819 			}
   2820 			if (target_check(match->pi_target, cur_level) == 0)
   2821 				continue;
   2822 
   2823 			/*
   2824 			 * Instance or service overrides a general
   2825 			 * definition.  We need to issue a warning message.
   2826 			 */
   2827 			rc = TVS_WARN;
   2828 			CLEAR_ERROR_INFO(&einfo);
   2829 			einfo.ei_type = EIT_PATTERN_CONFLICT;
   2830 			einfo.ei_u.ei_pattern_conflict.ei_pattern = pg;
   2831 			if (add_scf_error(errs, SCF_TERR_GENERAL_REDEFINE,
   2832 			    match->pi_ptrnpg, NULL, NULL, NULL, NULL,
   2833 			    &einfo) != 0) {
   2834 				/*
   2835 				 * No need to continue the search if we
   2836 				 * cannot record errors.
   2837 				 */
   2838 				break;
   2839 			}
   2840 		}
   2841 	}
   2842 
   2843 	if (ginfo != NULL)
   2844 		ptrn_info_destroy(ginfo);
   2845 	return (rc);
   2846 }
   2847 
   2848 /*
   2849  * tree contains the pg_pattern definitions for the instance at inst.  See
   2850  * if these pg_patterns redefine any pg_patterns in the instance's
   2851  * restarter or in the global service.  TVS_WARN is returned if a
   2852  * redefinition is encountered.
   2853  */
   2854 static tmpl_validate_status_t
   2855 tmpl_level_redefine(entity_t *inst, uu_avl_t *tree, tmpl_errors_t *errs)
   2856 {
   2857 	entity_t *restarter;
   2858 	entity_t *svc = inst->sc_parent;
   2859 	tmpl_validate_status_t r;
   2860 	tmpl_validate_status_t rc;
   2861 
   2862 	restarter = inst->sc_u.sc_instance.sc_instance_restarter;
   2863 	if (restarter == NULL) {
   2864 		/* No instance restarter.  Use the service restarter */
   2865 		restarter = svc->sc_u.sc_service.sc_restarter;
   2866 	}
   2867 	rc = tmpl_scan_general(restarter, tree, TL_RESTARTER, errs);
   2868 	r = tmpl_scan_general(svc->sc_u.sc_service.sc_global, tree,
   2869 	    TL_GLOBAL, errs);
   2870 	if (r != TVS_SUCCESS)
   2871 		rc = r;
   2872 	return (rc);
   2873 }
   2874 
   2875 /*
   2876  * Perform the following consistency checks on the template specifications
   2877  * themselves:
   2878  *
   2879  *	- No conflicting definitions of `pg_pattern` are allowed within a
   2880  *	  single instance.
   2881  *
   2882  *	- Templates at a narrow target (e.g. instance) which define
   2883  *	  property groups already templated at a broad target
   2884  *	  (e.g. restarter or all) are strongly discouraged.
   2885  *
   2886  *	- Developers may not define a template which specifies a single
   2887  *	  prop_pattern name with differing types on the same target
   2888  *	  entity.
   2889  *
   2890  *	- If a pg_pattern has a required attribute with a value of true,
   2891  *	  then its name and type attributes must be specified.
   2892  *
   2893  *	- If a prop_pattern has a required attribute with a value of true,
   2894  *	  then its type attribute must be specified.
   2895  *
   2896  *	- If a prop_pattern has an include values make sure that the
   2897  *	  appropriate constraints or values element has also been
   2898  *	  declared.
   2899  */
   2900 static tmpl_validate_status_t
   2901 tmpl_consistency(entity_t *inst, tmpl_errors_t *errs)
   2902 {
   2903 	void *marker = NULL;
   2904 	ptrn_info_t *info;
   2905 	uu_avl_t *tree;
   2906 	tmpl_validate_status_t rc;
   2907 	tmpl_validate_status_t r;
   2908 
   2909 	/* Allocate the tree. */
   2910 	tree = uu_avl_create(ptrn_info_pool, NULL, TMPL_DEBUG_TREE);
   2911 	if (tree == NULL) {
   2912 		uu_die(gettext("pg_info tree creation failed: %s\n"),
   2913 		    uu_strerror(uu_error()));
   2914 	}
   2915 
   2916 	rc = tmpl_pattern_conflict(inst, tree, PG_PATTERN, errs);
   2917 
   2918 	/*
   2919 	 * The tree now contains the instance and service pg_patterns.
   2920 	 * Check to see if they override any pg_pattern definitions in the
   2921 	 * restarter and global services.
   2922 	 */
   2923 	r = tmpl_level_redefine(inst, tree, errs);
   2924 	if (r != TVS_SUCCESS) {
   2925 		/*
   2926 		 * tmpl_level_redefine() can return a warning.  Don't
   2927 		 * override a serious error with a warning.
   2928 		 */
   2929 		if (r == TVS_WARN) {
   2930 			if (rc == TVS_SUCCESS)
   2931 				rc = r;
   2932 		} else {
   2933 			rc = r;
   2934 		}
   2935 	}
   2936 
   2937 	/*
   2938 	 * If the pg_pattern has a required attribute with a value of true,
   2939 	 * then it must also have name and type attributes.
   2940 	 */
   2941 	r = tmpl_required_attr_present(tree, errs);
   2942 	if (r != TVS_SUCCESS)
   2943 		rc = r;
   2944 
   2945 	/* Empty the tree, so that we can reuse it for prop_patterns. */
   2946 	while ((info = uu_avl_teardown(tree, &marker)) != NULL) {
   2947 		ptrn_info_destroy(info);
   2948 	}
   2949 
   2950 	r = tmpl_pattern_conflict(inst, tree, PROP_PATTERN, errs);
   2951 	if (r != TVS_SUCCESS)
   2952 		rc = r;
   2953 
   2954 	/*
   2955 	 * If a prop_pattern has required attribute with a value of true,
   2956 	 * then it must also have a type attribute.
   2957 	 */
   2958 	r = tmpl_required_attr_present(tree, errs);
   2959 	if (r != TVS_SUCCESS)
   2960 		rc = r;
   2961 
   2962 	/*
   2963 	 * Insure that include_values have the constraint for values
   2964 	 * elements that are needed.
   2965 	 */
   2966 	r = tmpl_include_values_check(tree, errs);
   2967 	if (r != TVS_SUCCESS)
   2968 		rc = r;
   2969 
   2970 	/* Tear down the tree. */
   2971 	marker = NULL;
   2972 	while ((info = uu_avl_teardown(tree, &marker)) != NULL) {
   2973 		ptrn_info_destroy(info);
   2974 	}
   2975 	uu_avl_destroy(tree);
   2976 
   2977 	return (rc);
   2978 }
   2979 
   2980 /*
   2981  * Release memory associated with the tmpl_errors structure and then free
   2982  * the structure itself.
   2983  */
   2984 void
   2985 tmpl_errors_destroy(tmpl_errors_t *te)
   2986 {
   2987 	im_tmpl_error_t *ite;
   2988 	tv_errors_t *ste;
   2989 	void *marker = NULL;
   2990 
   2991 	if (te == NULL)
   2992 		return;
   2993 	if (te->te_list) {
   2994 		while ((ite = uu_list_teardown(te->te_list, &marker)) != NULL) {
   2995 			uu_list_node_fini(ite, &ite->ite_node,
   2996 			    inmem_errors_pool);
   2997 			uu_free(ite);
   2998 		}
   2999 		uu_list_destroy(te->te_list);
   3000 	}
   3001 	if (te->te_scf) {
   3002 		marker = NULL;
   3003 		while ((ste = uu_list_teardown(te->te_scf, &marker)) != NULL) {
   3004 			destroy_scf_errors(ste);
   3005 		}
   3006 		uu_list_destroy(te->te_scf);
   3007 	}
   3008 	uu_free(te);
   3009 }
   3010 
   3011 /*
   3012  * Allocate and initialize a tmpl_errors structure.  The address of the
   3013  * structure is returned, unless we are unable to allocate enough memory.
   3014  * In the case of memory allocation failures, NULL is returned.
   3015  *
   3016  * The allocated structure should be freed by calling
   3017  * tmpl_errors_destroy().
   3018  */
   3019 static tmpl_errors_t *
   3020 tmpl_errors_create()
   3021 {
   3022 	tmpl_errors_t *te;
   3023 
   3024 	te = uu_zalloc(sizeof (*te));
   3025 	if (te == NULL)
   3026 		return (NULL);
   3027 	te->te_list = uu_list_create(inmem_errors_pool, NULL, TMPL_DEBUG_LIST);
   3028 	if (te->te_list == NULL) {
   3029 		uu_free(te);
   3030 		return (NULL);
   3031 	}
   3032 	te->te_scf = uu_list_create(tv_errors_pool, NULL, TMPL_DEBUG_LIST);
   3033 	if (te->te_scf == NULL) {
   3034 		tmpl_errors_destroy(te);
   3035 		return (NULL);
   3036 	}
   3037 
   3038 	return (te);
   3039 }
   3040 
   3041 void
   3042 tmpl_errors_print(FILE *out, tmpl_errors_t *errs, const char *prefix)
   3043 {
   3044 	scf_tmpl_error_t *cur;
   3045 	size_t buf_size = 4096;
   3046 	im_tmpl_error_t *ite;
   3047 	char *s = NULL;
   3048 	scf_tmpl_errors_t *scferrs;
   3049 	tv_errors_t *scft;
   3050 	int interactive = (est->sc_cmd_flags & SC_CMD_IACTIVE) ?
   3051 	    SCF_TMPL_STRERROR_HUMAN : 0;
   3052 
   3053 	for (ite = uu_list_first(errs->te_list);
   3054 	    ite != NULL;
   3055 	    ite = uu_list_next(errs->te_list, ite)) {
   3056 		im_tmpl_error_print(out, ite, prefix);
   3057 	}
   3058 
   3059 	/* Now handle the errors that can be printed via libscf. */
   3060 	s = safe_malloc(buf_size);
   3061 	for (scft = uu_list_first(errs->te_scf);
   3062 	    scft != NULL;
   3063 	    scft = uu_list_next(errs->te_scf, scft)) {
   3064 		scferrs = scft->tve_errors;
   3065 		if (_scf_tmpl_error_set_prefix(scferrs, prefix) != 0)
   3066 			uu_die(emesg_nomem);
   3067 		while ((cur = scf_tmpl_next_error(scferrs)) != NULL) {
   3068 			(void) scf_tmpl_strerror(cur, s, buf_size, interactive);
   3069 			(void) fputs(s, out);
   3070 			(void) fputc('\n', out);
   3071 		}
   3072 	}
   3073 
   3074 	free(s);
   3075 }
   3076 
   3077 /*
   3078  * This function finds the prop_pattern for the property, prop.  e is the
   3079  * instance where the search for the prop_pattern will start.  pg_pattern
   3080  * is the address of the pg_pattern that holds the prop_pattern.
   3081  */
   3082 static tmpl_validate_status_t
   3083 tmpl_find_prop_pattern(entity_t *inst, pgroup_t *pg_pattern,
   3084     property_t *prop, pgroup_t **prop_pattern)
   3085 {
   3086 	pgroup_t *candidate;
   3087 	pg_iter_t *iter = NULL;
   3088 	char *prop_pattern_name = NULL;
   3089 	tmpl_validate_status_t rc;
   3090 
   3091 	/*
   3092 	 * Get the name of the property group that holds the prop_pattern
   3093 	 * definition.
   3094 	 */
   3095 	rc = gen_prop_pattern_pg_name(pg_pattern,
   3096 	    prop->sc_property_name, &prop_pattern_name);
   3097 	if (rc != TVS_SUCCESS)
   3098 		goto out;
   3099 
   3100 	/* Find the property group. */
   3101 	iter = pg_iter_create(inst, SCF_GROUP_TEMPLATE_PROP_PATTERN);
   3102 	if (iter == NULL)
   3103 		goto out;
   3104 	while ((candidate = next_pattern_pg(iter)) != NULL) {
   3105 		const char *c;
   3106 
   3107 		if (strcmp(prop_pattern_name, candidate->sc_pgroup_name) != 0)
   3108 			continue;
   3109 		c = find_astring_value_in_pg(candidate,
   3110 		    SCF_PROPERTY_TM_PG_PATTERN);
   3111 		if (c == NULL)
   3112 			continue;
   3113 		if (strcmp(pg_pattern->sc_pgroup_name, c) == 0)
   3114 			break;
   3115 	}
   3116 	*prop_pattern = candidate;
   3117 	if (candidate == NULL)
   3118 		rc = TVS_NOMATCH;
   3119 
   3120 out:
   3121 	pg_iter_destroy(iter);
   3122 	uu_free((void *)prop_pattern_name);
   3123 	return (rc);
   3124 }
   3125 
   3126 /*
   3127  * Indexes for pg_pattern property group names.  Indexes are arranged
   3128  * from most specific to least specific.
   3129  */
   3130 #define	PGN_BOTH	0	/* both name and type */
   3131 #define	PGN_NAME	1	/* name only */
   3132 #define	PGN_TYPE	2	/* type only */
   3133 #define	PGN_NEITHER	3	/* neither name nor type */
   3134 #define	PGN_MAX		4	/* Size of array */
   3135 
   3136 /*
   3137  * Given an instance entity, e, and a propety group, pg, within the
   3138  * instance; return the address of the pg_pattern for the property group.
   3139  * The address of the pg_pattern is placed at pgp.  NULL indicates that no
   3140  * pg_pattern was specified.
   3141  */
   3142 static tmpl_validate_status_t
   3143 tmpl_find_pg_pattern(entity_t *e, pgroup_t *pg, pgroup_t **pgp)
   3144 {
   3145 	pgroup_t *cpg;		/* candidate property group */
   3146 	int i;
   3147 	pg_iter_t *iter = NULL;
   3148 	char *pg_names[PGN_MAX];
   3149 	pgroup_t *pg_patterns[PGN_MAX];
   3150 	tmpl_validate_status_t rv = TVS_SUCCESS;
   3151 
   3152 	(void) memset(pg_patterns, 0, sizeof (pg_patterns));
   3153 	*pgp = NULL;
   3154 
   3155 	/* Generate candidate names for pg_pattern property groups. */
   3156 	pg_names[PGN_BOTH] = gen_pg_pattern_pg_name(pg->sc_pgroup_name,
   3157 	    pg->sc_pgroup_type);
   3158 	pg_names[PGN_NAME] = gen_pg_pattern_pg_name(pg->sc_pgroup_name,
   3159 	    NULL);
   3160 	pg_names[PGN_TYPE] = gen_pg_pattern_pg_name(NULL,
   3161 	    pg->sc_pgroup_type);
   3162 	pg_names[PGN_NEITHER] = gen_pg_pattern_pg_name(NULL, NULL);
   3163 	for (i = 0; i < PGN_MAX; i++) {
   3164 		if (pg_names[i] == NULL) {
   3165 			rv = TVS_BAD_TEMPLATE;
   3166 			goto errout;
   3167 		}
   3168 	}
   3169 
   3170 	/* Search for property groups that match these names */
   3171 	iter = pg_iter_create(e, SCF_GROUP_TEMPLATE_PG_PATTERN);
   3172 	if (iter == NULL) {
   3173 		uu_die(emesg_nomem);
   3174 	}
   3175 	while ((cpg = next_pattern_pg(iter)) != NULL) {
   3176 		if (pg_target_check(cpg, iter->pgi_level) == 0)
   3177 			continue;
   3178 
   3179 		/* See if we have a name match. */
   3180 		for (i = 0; i < PGN_MAX; i++) {
   3181 			if (strcmp(cpg->sc_pgroup_name, pg_names[i]) == 0) {
   3182 				/*
   3183 				 * If we already have a lower level
   3184 				 * pg_pattern, keep it.
   3185 				 */
   3186 				if (pg_patterns[i] == NULL)
   3187 					pg_patterns[i] = cpg;
   3188 				break;
   3189 			}
   3190 		}
   3191 	}
   3192 
   3193 	/* Find the most specific pg_pattern. */
   3194 	for (i = 0; i < PGN_MAX; i++) {
   3195 		if (pg_patterns[i] != NULL) {
   3196 			*pgp = pg_patterns[i];
   3197 			break;
   3198 		}
   3199 	}
   3200 errout:
   3201 	for (i = 0; i < PGN_MAX; i++) {
   3202 		free(pg_names[i]);
   3203 	}
   3204 	pg_iter_destroy(iter);
   3205 	return (rv);
   3206 }
   3207 
   3208 /*
   3209  * Initialize structures that are required for validation using
   3210  * templates specifications.
   3211  */
   3212 void
   3213 tmpl_init(void)
   3214 {
   3215 	emesg_nomem = gettext("Out of memory.\n");
   3216 
   3217 	composed_pg_pool = uu_avl_pool_create("composed_pg",
   3218 	    sizeof (composed_pg_t), offsetof(composed_pg_t, cpg_node),
   3219 	    composed_pg_compare, TMPL_DEBUG_AVL_POOL);
   3220 	if (composed_pg_pool == NULL) {
   3221 		uu_die(gettext("composed_pg pool creation failed: %s\n"),
   3222 		    uu_strerror(uu_error()));
   3223 	}
   3224 	composed_prop_pool = uu_avl_pool_create("composed_prop",
   3225 	    sizeof (property_t), offsetof(property_t, sc_composed_node),
   3226 	    composed_prop_compare, TMPL_DEBUG_AVL_POOL);
   3227 	if (composed_prop_pool == NULL) {
   3228 		uu_die(gettext("composed_prop pool creation failed. %s\n"),
   3229 		    uu_strerror(uu_error()));
   3230 	}
   3231 	ptrn_info_pool = uu_avl_pool_create("ptrn_info", sizeof (ptrn_info_t),
   3232 	    offsetof(ptrn_info_t, pi_link), ptrn_info_compare,
   3233 	    TMPL_DEBUG_AVL_POOL);
   3234 	if (ptrn_info_pool == NULL) {
   3235 		uu_die(gettext("pg_pattern info pool creation failed: %s\n"),
   3236 		    uu_strerror(uu_error()));
   3237 	}
   3238 	inmem_errors_pool = uu_list_pool_create("errors-internal",
   3239 	    sizeof (im_tmpl_error_t), offsetof(im_tmpl_error_t,
   3240 	    ite_node), NULL, TMPL_DEBUG_LIST_POOL);
   3241 	if (inmem_errors_pool == NULL) {
   3242 		uu_die(gettext("inmem_errors_pool pool creation failed: "
   3243 		    "%s\n"), uu_strerror(uu_error()));
   3244 	}
   3245 	tv_errors_pool = uu_list_pool_create("scf-terrors",
   3246 	    sizeof (tv_errors_t), offsetof(tv_errors_t, tve_node),
   3247 	    NULL,  TMPL_DEBUG_LIST_POOL);
   3248 	if (tv_errors_pool == NULL) {
   3249 		uu_die(gettext("tv_errors_pool pool creation failed: %s\n"),
   3250 		    uu_strerror(uu_error()));
   3251 	}
   3252 }
   3253 
   3254 /*
   3255  * Clean up the composed property node in the property.
   3256  */
   3257 void
   3258 tmpl_property_fini(property_t *p)
   3259 {
   3260 	uu_avl_node_fini(p, &p->sc_composed_node, composed_prop_pool);
   3261 }
   3262 
   3263 /*
   3264  * Initialize the composed property node in the property.
   3265  */
   3266 void
   3267 tmpl_property_init(property_t *p)
   3268 {
   3269 	uu_avl_node_init(p, &p->sc_composed_node, composed_prop_pool);
   3270 }
   3271 
   3272 /*
   3273  * Use the cardinality specification in the prop_pattern to verify the
   3274  * cardinality of the property at prop.  The cardinality of the property is
   3275  * the number of values that it has.
   3276  *
   3277  * pg is the property group that holds prop, and pg_pattern is the
   3278  * pg_pattern for the property group.  pg and pg_pattern are only used for
   3279  * error reporting.
   3280  */
   3281 static tmpl_validate_status_t
   3282 tmpl_validate_cardinality(pgroup_t *prop_pattern, property_t *prop,
   3283     pgroup_t *pg, pgroup_t *pg_pattern, tmpl_errors_t *errs)
   3284 {
   3285 	size_t count;
   3286 	uint64_t max;
   3287 	uint64_t min;
   3288 	tmpl_validate_status_t rc;
   3289 	error_info_t einfo;
   3290 
   3291 	assert(strcmp(prop_pattern->sc_pgroup_type,
   3292 	    SCF_GROUP_TEMPLATE_PROP_PATTERN) == 0);
   3293 
   3294 	rc = get_cardinality(prop_pattern, &min, &max);
   3295 	switch (rc) {
   3296 	case TVS_NOMATCH:
   3297 		/* Nothing to check. */
   3298 		return (TVS_SUCCESS);
   3299 	case TVS_SUCCESS:
   3300 		/* Process the limits. */
   3301 		break;
   3302 	default:
   3303 		return (rc);
   3304 	}
   3305 
   3306 	if ((min == 0) && (max == ULLONG_MAX)) {
   3307 		/* Any number of values is permitted.  No need to count. */
   3308 		return (TVS_SUCCESS);
   3309 	}
   3310 
   3311 	count = count_prop_values(prop);
   3312 	if ((count < min) || (count > max)) {
   3313 		CLEAR_ERROR_INFO(&einfo);
   3314 		einfo.ei_type = EIT_CARDINALITY;
   3315 		einfo.ei_u.ei_cardinality.ei_min = min;
   3316 		einfo.ei_u.ei_cardinality.ei_max = max;
   3317 		einfo.ei_u.ei_cardinality.ei_count = count;
   3318 		(void) add_scf_error(errs, SCF_TERR_CARDINALITY_VIOLATION,
   3319 		    pg_pattern, pg, prop_pattern, prop, NULL, &einfo);
   3320 		return (TVS_VALIDATION);
   3321 	}
   3322 
   3323 	return (TVS_SUCCESS);
   3324 }
   3325 
   3326 /*
   3327  * Iterate over pg_patterns in the entity, e.  If the pg_pattern's required
   3328  * attribute is true, verify that the entity contains the corresponding
   3329  * property group.
   3330  */
   3331 static tmpl_validate_status_t
   3332 tmpl_required_pg_present(entity_t *e, tmpl_errors_t *errs)
   3333 {
   3334 	composed_pg_t cpg;
   3335 	composed_pg_t *match;
   3336 	error_info_t einfo;
   3337 	pg_iter_t *iter;
   3338 	pgroup_t *pg;
   3339 	const char *pg_name;
   3340 	const char *pg_type;
   3341 	tmpl_validate_status_t rc = TVS_SUCCESS;
   3342 	uu_avl_t *tree;
   3343 
   3344 	assert(e->sc_etype == SVCCFG_INSTANCE_OBJECT);
   3345 
   3346 	iter = pg_iter_create(e, SCF_GROUP_TEMPLATE_PG_PATTERN);
   3347 	if (iter == NULL)
   3348 		uu_die(emesg_nomem);
   3349 
   3350 	CLEAR_ERROR_INFO(&einfo);
   3351 	einfo.ei_type = EIT_MISSING_PG;
   3352 
   3353 	while ((pg = next_pattern_pg(iter)) != NULL) {
   3354 		if (is_required(pg) == 0) {
   3355 			/* If pg is not required, there is nothing to check. */
   3356 			continue;
   3357 		}
   3358 		pg_name = find_astring_value_in_pg(pg, SCF_PROPERTY_TM_NAME);
   3359 		pg_type = find_astring_value_in_pg(pg, SCF_PROPERTY_TM_TYPE);
   3360 		if (pg_target_check(pg, iter->pgi_level) == 0)
   3361 			continue;
   3362 		einfo.ei_u.ei_missing_pg.ei_pg_name = pg_name;
   3363 		einfo.ei_u.ei_missing_pg.ei_pg_type = pg_type;
   3364 		tree = e->sc_u.sc_instance.sc_composed;
   3365 		(void) memset(&cpg, 0, sizeof (cpg));
   3366 		cpg.cpg_name = pg_name;
   3367 		cpg.cpg_type = pg_type;
   3368 		match = uu_avl_find(tree, &cpg, NULL, NULL);
   3369 		if (match == NULL) {
   3370 			rc = TVS_VALIDATION;
   3371 			if (add_scf_error(errs, SCF_TERR_MISSING_PG, pg,
   3372 			    NULL, NULL, NULL, NULL, &einfo) != 0) {
   3373 				break;
   3374 			}
   3375 		}
   3376 	}
   3377 
   3378 	pg_iter_destroy(iter);
   3379 	return (rc);
   3380 }
   3381 
   3382 /*
   3383  * Verify that the property group, pg, contains property declarations for
   3384  * all required properties.  Unfortunately, there is no direct way to find
   3385  * the prop_patterns for a given property group.  Therefore, we need to
   3386  * scan the entity at e looking for property groups with a type of
   3387  * SCF_GROUP_TEMPLATE_PROP_PATTERN.  That is, we scan the entity looking
   3388  * for all prop_patterns.  When we find a prop_pattern, we look at the
   3389  * value of its pg_pattern property to see if it matches the name of the
   3390  * pg_pattern.  If they match, this is a prop_pattern that is of interest
   3391  * to us.
   3392  *
   3393  * When we find an interesting prop_pattern, we see if it's required
   3394  * property is true.  If it is, we verify that the property group at pg
   3395  * contains the specified property.
   3396  */
   3397 static tmpl_validate_status_t
   3398 tmpl_required_props_present(entity_t *e, pgroup_t *pg, pgroup_t *pg_pattern,
   3399     tmpl_errors_t *errs)
   3400 {
   3401 	error_info_t einfo;
   3402 	pg_iter_t *iter;
   3403 	const char *prop_name;
   3404 	const char *prop_pg_pattern_name;
   3405 	pgroup_t *prop_pattern;
   3406 	scf_tmpl_error_type_t ec;
   3407 	tmpl_validate_status_t rc = TVS_SUCCESS;
   3408 
   3409 	/*
   3410 	 * Scan the entity's property groups looking for ones with a type
   3411 	 * of SCF_GROUP_TEMPLATE_PROP_PATTERN.
   3412 	 */
   3413 	iter = pg_iter_create(e, SCF_GROUP_TEMPLATE_PROP_PATTERN);
   3414 	if (iter == NULL)
   3415 		uu_die(emesg_nomem);
   3416 	CLEAR_ERROR_INFO(&einfo);
   3417 	for (prop_pattern = next_pattern_pg(iter);
   3418 	    prop_pattern != NULL;
   3419 	    prop_pattern = next_pattern_pg(iter)) {
   3420 		/*
   3421 		 * Find the pg_pattern property in this prop_pattern.
   3422 		 * Verify that its value matches the name of the
   3423 		 * pg_pattern.
   3424 		 */
   3425 		prop_pg_pattern_name = find_astring_value_in_pg(prop_pattern,
   3426 		    SCF_PROPERTY_TM_PG_PATTERN);
   3427 		assert(prop_pg_pattern_name != NULL);
   3428 		if (strcmp(pg_pattern->sc_pgroup_name,
   3429 		    prop_pg_pattern_name) != 0) {
   3430 			continue;
   3431 		}
   3432 
   3433 		/* If the property is required, see if it is in the pg. */
   3434 		if (is_required(prop_pattern) == 0)
   3435 			continue;
   3436 		prop_name = find_astring_value_in_pg(prop_pattern,
   3437 		    SCF_PROPERTY_TM_NAME);
   3438 		assert(prop_name != NULL);
   3439 		if (property_find(pg, prop_name) == NULL) {
   3440 			ec = SCF_TERR_MISSING_PROP;
   3441 			rc = TVS_VALIDATION;
   3442 			einfo.ei_type = EIT_MISSING_PROP;
   3443 			einfo.ei_u.ei_missing_prop.ei_prop_name = prop_name;
   3444 			if (add_scf_error(errs, ec, pg_pattern, pg,
   3445 			    prop_pattern, NULL, NULL, &einfo) != 0) {
   3446 				/*
   3447 				 * If we can no longer accumulate errors,
   3448 				 * break out of the loop.
   3449 				 */
   3450 				break;
   3451 			}
   3452 		}
   3453 	}
   3454 
   3455 	pg_iter_destroy(iter);
   3456 	return (rc);
   3457 }
   3458 
   3459 /*
   3460  * Check the value at v to see if it falls within any of the ranges at r.
   3461  * count is the number of ranges at r, and type tells whether to treat the
   3462  * value as signed or unsigned.
   3463  *
   3464  * Return 1 if the value falls within one of the ranges.  Otherwise return
   3465  * 0.
   3466  */
   3467 static int
   3468 value_in_range(value_t *v, scf_type_t type, range_t *r, size_t count)
   3469 {
   3470 	for (; count > 0; --count, r++) {
   3471 		if (type == SCF_TYPE_COUNT) {
   3472 			if ((v->sc_u.sc_count >=
   3473 			    r->rng_u.rng_unsigned.rng_min) &&
   3474 			    (v->sc_u.sc_count <=
   3475 			    r->rng_u.rng_unsigned.rng_max))
   3476 				return (1);
   3477 		} else {
   3478 			if ((v->sc_u.sc_integer >=
   3479 			    r->rng_u.rng_signed.rng_min) &&
   3480 			    (v->sc_u.sc_integer <=
   3481 			    r->rng_u.rng_signed.rng_max))
   3482 				return (1);
   3483 		}
   3484 	}
   3485 	return (0);
   3486 }
   3487 
   3488 /*
   3489  * If the template prop_pattern at pattern contains a constraint_range
   3490  * property, use the specified range to validate all the numeric property
   3491  * values of the property at prop.
   3492  *
   3493  * pg is the property group that holds prop, and pg_pattern is the
   3494  * pg_pattern for the property group.  pg and pg_pattern are only used for
   3495  * error reporting.
   3496  */
   3497 static tmpl_validate_status_t
   3498 tmpl_validate_value_range(pgroup_t *pattern, property_t *prop, pgroup_t *pg,
   3499     pgroup_t *pg_pattern, tmpl_errors_t *errs)
   3500 {
   3501 	uint_t count;
   3502 	error_info_t einfo;
   3503 	property_t *range_prop;
   3504 	range_t *ranges;
   3505 	tmpl_validate_status_t rc;
   3506 	scf_type_t type;
   3507 	value_t *v;
   3508 
   3509 	/* Get the range constraints if they exist. */
   3510 	if ((range_prop = property_find(pattern,
   3511 	    SCF_PROPERTY_TM_CONSTRAINT_RANGE)) == NULL) {
   3512 		/* No range to check. */
   3513 		return (TVS_SUCCESS);
   3514 	}
   3515 	type = prop->sc_value_type;
   3516 	if ((type != SCF_TYPE_COUNT) && (type != SCF_TYPE_INTEGER)) {
   3517 		rc = TVS_BAD_TEMPLATE;
   3518 		CLEAR_ERROR_INFO(&einfo);
   3519 		einfo.ei_type = EIT_BAD_TEMPLATE;
   3520 		einfo.ei_u.ei_bad_template.ei_reason =
   3521 		    gettext("Property does not have correct type for "
   3522 		    "a range specification");
   3523 		(void) tmpl_errors_add_im(errs, rc, pg_pattern->sc_parent,
   3524 		    pg_pattern, pg, pattern, prop, NULL, &einfo);
   3525 		return (rc);
   3526 	}
   3527 	if ((rc = get_ranges(range_prop, prop->sc_value_type, &ranges,
   3528 	    &count)) != TVS_SUCCESS) {
   3529 		rc = TVS_BAD_TEMPLATE;
   3530 		CLEAR_ERROR_INFO(&einfo);
   3531 		einfo.ei_type = EIT_BAD_TEMPLATE;
   3532 		einfo.ei_u.ei_bad_template.ei_reason = gettext("Illegal range "
   3533 		    "value");
   3534 		(void) tmpl_errors_add_im(errs, rc, pg_pattern->sc_parent,
   3535 		    pg_pattern, pg, pattern, prop, NULL, &einfo);
   3536 		return (rc);
   3537 	}
   3538 
   3539 	/* Set up error info before entering loop. */
   3540 	CLEAR_ERROR_INFO(&einfo);
   3541 	einfo.ei_type = EIT_RANGE;
   3542 	einfo.ei_u.ei_range.ei_rtype = type;
   3543 
   3544 	/* Compare numeric values of the property to the range. */
   3545 	for (v = uu_list_first(prop->sc_property_values);
   3546 	    v != NULL;
   3547 	    v = uu_list_next(prop->sc_property_values, v)) {
   3548 		if (value_in_range(v, type, ranges, count) == 1)
   3549 			continue;
   3550 		if (type == SCF_TYPE_COUNT) {
   3551 			einfo.ei_u.ei_range.ei_uvalue = v->sc_u.sc_count;
   3552 		} else {
   3553 			einfo.ei_u.ei_range.ei_ivalue = v->sc_u.sc_integer;
   3554 		}
   3555 		rc = TVS_VALIDATION;
   3556 		if (add_scf_error(errs, SCF_TERR_RANGE_VIOLATION, pg_pattern,
   3557 		    pg, pattern, prop, v, &einfo) != 0) {
   3558 			return (rc);
   3559 		}
   3560 	}
   3561 
   3562 	return (rc);
   3563 }
   3564 
   3565 /*
   3566  * If the prop_pattern has value constraints, verify that all the values
   3567  * for the property at prop are legal values.
   3568  *
   3569  * pg is the property group that holds prop, and pg_pattern is the
   3570  * pg_pattern for the property group.  pg and pg_pattern are only used for
   3571  * error reporting.
   3572  */
   3573 static tmpl_validate_status_t
   3574 tmpl_validate_values(pgroup_t *prop_pattern, property_t *prop, pgroup_t *pg,
   3575     pgroup_t *pg_pattern, tmpl_errors_t *errs)
   3576 {
   3577 	int found;
   3578 	uint_t i;
   3579 	avalues_t *legal;
   3580 	tmpl_validate_status_t r;
   3581 	tmpl_validate_status_t rc = TVS_SUCCESS;
   3582 	value_t *v;
   3583 
   3584 	/* Get list of legal values. */
   3585 	r = av_get_values(prop_pattern, SCF_PROPERTY_TM_CONSTRAINT_NAME,
   3586 	    prop->sc_value_type, &legal);
   3587 	switch (r) {
   3588 	case TVS_BAD_CONVERSION:
   3589 		(void) tmpl_errors_add_im(errs, r, pg->sc_parent, pg_pattern,
   3590 		    pg, prop_pattern, prop, NULL, NULL);
   3591 		return (r);
   3592 	case TVS_NOMATCH:
   3593 		/* No constraints in template. */
   3594 		return (TVS_SUCCESS);
   3595 	case TVS_SUCCESS:
   3596 		/* process the constraints. */
   3597 		break;
   3598 	default:
   3599 		assert(0);
   3600 		abort();
   3601 	}
   3602 
   3603 	/* Check the property values against the legal values. */
   3604 	for (v = uu_list_first(prop->sc_property_values);
   3605 	    v != NULL;
   3606 	    v = uu_list_next(prop->sc_property_values, v)) {
   3607 		/* Check this property value against the legal values. */
   3608 		found = 0;
   3609 		for (i = 0; (i < legal->av_count) && (found == 0); i++) {
   3610 			switch (v->sc_type) {
   3611 			case SCF_TYPE_BOOLEAN:
   3612 			case SCF_TYPE_COUNT:
   3613 				if (av_get_unsigned(legal, i) ==
   3614 				    v->sc_u.sc_count) {
   3615 					found = 1;
   3616 				}
   3617 				break;
   3618 			case SCF_TYPE_INTEGER:
   3619 				if (av_get_integer(legal, i) ==
   3620 				    v->sc_u.sc_integer) {
   3621 					found = 1;
   3622 				}
   3623 				break;
   3624 			default:
   3625 				if (strcmp(av_get_string(legal, i),
   3626 				    v->sc_u.sc_string) == 0) {
   3627 					found = 1;
   3628 				}
   3629 				break;
   3630 			}
   3631 		}
   3632 		if (found == 0) {
   3633 			rc = TVS_VALIDATION;
   3634 			if (add_scf_error(errs,
   3635 			    SCF_TERR_VALUE_CONSTRAINT_VIOLATED, pg_pattern, pg,
   3636 			    prop_pattern, prop, v, NULL) != 0) {
   3637 				/*
   3638 				 * Exit loop if no longer able to report
   3639 				 * errors.
   3640 				 */
   3641 				break;
   3642 			}
   3643 		}
   3644 	}
   3645 
   3646 out:
   3647 	av_destroy(legal);
   3648 	return (rc);
   3649 }
   3650 
   3651 /*
   3652  * Verify the following items about the values of property, prop.
   3653  *
   3654  *	- The values all have the type specified by the prop_pattern at
   3655  *	  pattern.
   3656  *	- Check numeric values against range constraints.
   3657  *	- If the prop_pattern has one or more value constraints, validate
   3658  *	  the property's values against the constraints.
   3659  *
   3660  * pg is the property group that holds prop, and pg_pattern is the
   3661  * pg_pattern for the property group.  pg and pg_pattern are only used for
   3662  * error reporting.
   3663  */
   3664 static tmpl_validate_status_t
   3665 tmpl_validate_value_constraints(pgroup_t *pattern, property_t *prop,
   3666     pgroup_t *pg, pgroup_t *pg_pattern, tmpl_errors_t *errs)
   3667 {
   3668 	tmpl_validate_status_t r;
   3669 	tmpl_validate_status_t rc;
   3670 
   3671 	rc = tmpl_validate_value_range(pattern, prop, pg, pg_pattern, errs);
   3672 	r = tmpl_validate_values(pattern, prop, pg, pg_pattern, errs);
   3673 	if (r != TVS_SUCCESS)
   3674 		rc = r;
   3675 
   3676 	return (rc);
   3677 }
   3678 
   3679 /*
   3680  * Perform the following validations on the property, prop.
   3681  *
   3682  *	- Verify that the property's type agrees with the type specified in
   3683  *	  the prop_pattern template, tmpl.
   3684  *	- Verify the cardinality.
   3685  *	- Verify that the property values satisfy the constraints specified
   3686  *	  by the template.
   3687  *
   3688  * pg is the property group that holds prop, and pg_pattern is the
   3689  * pg_pattern for the property group.  pg and pg_pattern are only used for
   3690  * error reporting.
   3691  */
   3692 static tmpl_validate_status_t
   3693 tmpl_validate_prop(property_t *prop, pgroup_t *tmpl, pgroup_t *pg,
   3694     pgroup_t *pg_pattern, tmpl_errors_t *errs)
   3695 {
   3696 	scf_tmpl_error_type_t ec;
   3697 	error_info_t einfo;
   3698 	tmpl_validate_status_t r;
   3699 	tmpl_validate_status_t rc = TVS_SUCCESS;
   3700 	int status;
   3701 	scf_type_t type;
   3702 
   3703 	r = prop_pattern_type(tmpl, &type);
   3704 	switch (r) {
   3705 	case TVS_SUCCESS:
   3706 		if (type == SCF_TYPE_INVALID) {
   3707 			rc = TVS_INVALID_TYPE_SPECIFICATION;
   3708 			r = tmpl_errors_add_im(errs, rc, pg->sc_parent, NULL,
   3709 			    pg, tmpl, NULL, NULL, NULL);
   3710 			if (r != TVS_SUCCESS) {
   3711 				/*
   3712 				 * Give up if we can no longer accumulate
   3713 				 * errors.
   3714 				 */
   3715 				return (rc);
   3716 			}
   3717 		} else {
   3718 			if (property_is_type(prop, type) == 0) {
   3719 				CLEAR_ERROR_INFO(&einfo);
   3720 				rc = TVS_VALIDATION;
   3721 				ec = SCF_TERR_WRONG_PROP_TYPE;
   3722 				einfo.ei_type  = EIT_PROP_TYPE;
   3723 				einfo.ei_u.ei_prop_type.ei_specified = type;
   3724 				einfo.ei_u.ei_prop_type.ei_actual =
   3725 				    prop->sc_value_type;
   3726 				status = add_scf_error(errs, ec,
   3727 				    pg_pattern, pg, tmpl, prop, NULL, &einfo);
   3728 				if (status != 0) {
   3729 					/*
   3730 					 * Give up if we can no longer
   3731 					 * accumulate errors.
   3732 					 */
   3733 					return (rc);
   3734 				}
   3735 			}
   3736 		}
   3737 		break;
   3738 	case TVS_MISSING_TYPE_SPECIFICATION:
   3739 		/*
   3740 		 * A null type specification means that we do not need to
   3741 		 * check the property's type.
   3742 		 */
   3743 		break;
   3744 	default:
   3745 		rc = r;
   3746 	}
   3747 
   3748 	/* Validate the cardinality */
   3749 	r = tmpl_validate_cardinality(tmpl, prop, pg, pg_pattern, errs);
   3750 	if (r != TVS_SUCCESS)
   3751 		rc = r;
   3752 
   3753 	/* Validate that property values satisfy constraints. */
   3754 	r = tmpl_validate_value_constraints(tmpl, prop, pg, pg_pattern, errs);
   3755 	if (r != TVS_SUCCESS)
   3756 		rc = r;
   3757 
   3758 	return (rc);
   3759 }
   3760 
   3761 /*
   3762  * Validate the property group at pg by performing the following checks:
   3763  *
   3764  *	- Verify that the types of the pg and the pg_pattern are
   3765  *	  compatible.
   3766  *	- Verify the properties in the pg.
   3767  *	- Verify that required properties are present.
   3768  */
   3769 static tmpl_validate_status_t
   3770 tmpl_validate_pg(entity_t *e, pgroup_t *pg, tmpl_errors_t *errs)
   3771 {
   3772 	error_info_t einfo;
   3773 	const char *pg_pattern_type;	/* Type declared by pg_pattern. */
   3774 	pgroup_t *pg_pattern;	/* Prop. group for pg_pattern */
   3775 	property_t *prop;
   3776 	pgroup_t *prop_pattern;
   3777 	tmpl_validate_status_t r;
   3778 	tmpl_validate_status_t rc = TVS_SUCCESS;
   3779 	int stat;
   3780 
   3781 	/*
   3782 	 * See if there is a pg_pattern for this property group.  If it
   3783 	 * exists, use it to validate the property group.  If there is no
   3784 	 * pg_pattern, then there is no validation to do.
   3785 	 */
   3786 	rc = tmpl_find_pg_pattern(e, pg, &pg_pattern);
   3787 	switch (rc) {
   3788 	case TVS_SUCCESS:
   3789 		break;
   3790 	case TVS_BAD_TEMPLATE:
   3791 		CLEAR_ERROR_INFO(&einfo);
   3792 		einfo.ei_type = EIT_BAD_TEMPLATE;
   3793 		einfo.ei_u.ei_bad_template.ei_reason = gettext("Property "
   3794 		    "group name too long");
   3795 		(void) tmpl_errors_add_im(errs, rc, e, NULL, pg, NULL, NULL,
   3796 		    NULL, &einfo);
   3797 		return (rc);
   3798 	default:
   3799 		assert(0);
   3800 		abort();
   3801 	}
   3802 	if (pg_pattern == NULL)
   3803 		return (TVS_SUCCESS);
   3804 
   3805 	/*
   3806 	 * If the pg_pattern declares a type, verify that the PG has the
   3807 	 * correct type.
   3808 	 */
   3809 	pg_pattern_type = find_type_specification(pg_pattern);
   3810 	if ((pg_pattern_type != NULL) &&
   3811 	    (*pg_pattern_type != 0)) {
   3812 		if ((pg->sc_pgroup_type != NULL) &&
   3813 		    (*(pg->sc_pgroup_type) != 0)) {
   3814 			if (strcmp(pg_pattern_type,
   3815 			    pg->sc_pgroup_type) != 0) {
   3816 				rc = TVS_VALIDATION;
   3817 				stat = add_scf_error(errs,
   3818 				    SCF_TERR_WRONG_PG_TYPE, pg_pattern, pg,
   3819 				    NULL, NULL, NULL, NULL);
   3820 				if (stat != 0) {
   3821 					/*
   3822 					 * If we can no longer accumulate
   3823 					 * errors, return without trying to
   3824 					 * do further validation.
   3825 					 */
   3826 					return (rc);
   3827 				}
   3828 			}
   3829 		} else {
   3830 			rc = TVS_MISSING_PG_TYPE;
   3831 			r = tmpl_errors_add_im(errs, rc, e, pg_pattern, pg,
   3832 			    NULL, NULL, NULL, NULL);
   3833 			if (r != TVS_SUCCESS) {
   3834 				/*
   3835 				 * If we can no longer accumulate errors,
   3836 				 * return without trying to do further
   3837 				 * validation.
   3838 				 */
   3839 				return (rc);
   3840 			}
   3841 		}
   3842 	}
   3843 
   3844 	/* Verify the properties in the property group. */
   3845 	prop = NULL;
   3846 	while ((prop = next_property(pg, prop)) != NULL) {
   3847 		r = tmpl_find_prop_pattern(e, pg_pattern, prop, &prop_pattern);
   3848 		switch (r) {
   3849 		case TVS_SUCCESS:
   3850 			/* Found match.  Validate property. */
   3851 			break;
   3852 		case TVS_NOMATCH:
   3853 			/* No prop_patern.  Go on to next property. */
   3854 			continue;
   3855 		case TVS_BAD_TEMPLATE:
   3856 			CLEAR_ERROR_INFO(&einfo);
   3857 			einfo.ei_type = EIT_BAD_TEMPLATE;
   3858 			einfo.ei_u.ei_bad_template.ei_reason =
   3859 			    gettext("prop_pattern name too long");
   3860 			(void) tmpl_errors_add_im(errs, r, e, NULL, pg, NULL,
   3861 			    NULL, NULL, &einfo);
   3862 			continue;
   3863 		default:
   3864 			assert(0);
   3865 			abort();
   3866 		}
   3867 		r = tmpl_validate_prop(prop, prop_pattern, pg, pg_pattern,
   3868 		    errs);
   3869 		if (r != TVS_SUCCESS)
   3870 			rc = r;
   3871 	}
   3872 
   3873 	/*
   3874 	 * Confirm required properties are present.
   3875 	 */
   3876 	r = tmpl_required_props_present(e, pg, pg_pattern, errs);
   3877 	if (r != TVS_SUCCESS)
   3878 		rc = r;
   3879 
   3880 	return (rc);
   3881 }
   3882 
   3883 /*
   3884  * Validate that the property groups in the entity conform to the template
   3885  * specifications.  Specifically, this means do the following:
   3886  *
   3887  *	- Loop through the property groups in the entity skipping the ones
   3888  *	  that are of type "template".
   3889  *
   3890  *	- For the PG search for the corresponding template_pg_pattern
   3891  *	  property group.  It is possible that one may not exist.
   3892  *
   3893  *	- Verify that the PG is in conformance with the pg_pattern
   3894  *	  specification if it exists.
   3895  */
   3896 static tmpl_validate_status_t
   3897 tmpl_validate_entity_pgs(entity_t *e, tmpl_errors_t *errs)
   3898 {
   3899 	composed_pg_t *cpg;
   3900 	uu_avl_t *pgroups;
   3901 	pgroup_t *pg;
   3902 	tmpl_validate_status_t r;
   3903 	tmpl_validate_status_t rc = TVS_SUCCESS;
   3904 
   3905 	assert(e->sc_etype == SVCCFG_INSTANCE_OBJECT);
   3906 
   3907 	pgroups = e->sc_u.sc_instance.sc_composed;
   3908 	for (cpg = uu_avl_first(pgroups);
   3909 	    cpg != NULL;
   3910 	    cpg = uu_avl_next(pgroups, cpg)) {
   3911 		if (strcmp(cpg->cpg_type, SCF_GROUP_TEMPLATE) == 0)
   3912 			continue;
   3913 		pg = CPG2PG(cpg);
   3914 		if ((r = tmpl_validate_pg(e, pg, errs)) != TVS_SUCCESS)
   3915 			rc = r;
   3916 	}
   3917 
   3918 	return (rc);
   3919 }
   3920 
   3921 /*
   3922  * Validate the instance, e, by performing the following checks:
   3923  *
   3924  *	- Verify template consistency.
   3925  *
   3926  *	- Validate each property group in the entity is in conformance
   3927  *	  with the template specifications.
   3928  *
   3929  *	- Verify that all required property groups are present in the
   3930  *	  entity.
   3931  */
   3932 static tmpl_validate_status_t
   3933 tmpl_validate_instance(entity_t *e, tmpl_errors_t *errs)
   3934 {
   3935 	tmpl_validate_status_t r;
   3936 	tmpl_validate_status_t rc = TVS_SUCCESS;
   3937 	int status;
   3938 	tv_errors_t *ste;
   3939 
   3940 	/* Prepare to collect errors for this instance. */
   3941 	ste = tv_errors_create(e->sc_fmri);
   3942 	status = uu_list_insert_after(errs->te_scf, errs->te_cur_scf, ste);
   3943 	assert(status == 0);
   3944 	errs->te_cur_scf = ste;
   3945 
   3946 	/* Verify template consistency */
   3947 	rc = tmpl_consistency(e, errs);
   3948 
   3949 	/* Validate the property groups in the entity. */
   3950 	r = tmpl_validate_entity_pgs(e, errs);
   3951 	if (r != TVS_SUCCESS)
   3952 		rc = r;
   3953 
   3954 	/* Verify that all required property groups are present. */
   3955 	r = tmpl_required_pg_present(e, errs);
   3956 	if (r != TVS_SUCCESS)
   3957 		rc = r;
   3958 
   3959 	return (rc);
   3960 }
   3961 
   3962 /*
   3963  * First validate the instances of the service.
   3964  */
   3965 static tmpl_validate_status_t
   3966 tmpl_validate_service(entity_t *svc, tmpl_errors_t *errs)
   3967 {
   3968 	entity_t *inst;
   3969 	tmpl_validate_status_t r;
   3970 	tmpl_validate_status_t rc = TVS_SUCCESS;
   3971 
   3972 	assert(svc->sc_etype == SVCCFG_SERVICE_OBJECT);
   3973 
   3974 	load_general_templates(svc);
   3975 
   3976 	/* Validate the service's instances. */
   3977 	for (inst = uu_list_first(svc->sc_u.sc_service.sc_service_instances);
   3978 	    inst != NULL;
   3979 	    inst = uu_list_next(svc->sc_u.sc_service.sc_service_instances,
   3980 	    inst)) {
   3981 		load_instance_restarter(inst);
   3982 		build_composed_instance(inst);
   3983 		r = tmpl_validate_instance(inst, errs);
   3984 		if (r != TVS_SUCCESS)
   3985 			rc = r;
   3986 		demolish_composed_instance(inst);
   3987 	}
   3988 
   3989 	return (rc);
   3990 }
   3991 
   3992 /*
   3993  * Validate all services and instances in the bundle against their
   3994  * templates.  If err_list is not NULL, a tmpl_errors structure will be
   3995  * allocated and its address will be returned to err_list.  This structure
   3996  * can be used to generate error messages.
   3997  */
   3998 tmpl_validate_status_t
   3999 tmpl_validate_bundle(bundle_t *bndl, tmpl_errors_t **err_list)
   4000 {
   4001 	tmpl_errors_t *errs = NULL;
   4002 	entity_t *svc;
   4003 	tmpl_validate_status_t r;
   4004 	tmpl_validate_status_t rc = TVS_SUCCESS;
   4005 
   4006 	if (err_list != NULL)
   4007 		*err_list = NULL;
   4008 	if (bndl->sc_bundle_type != SVCCFG_MANIFEST) {
   4009 		semerr(gettext("Bundle is not a manifest.  Unable to validate "
   4010 		    "against templates.\n"));
   4011 		return (TVS_FATAL);
   4012 	}
   4013 
   4014 	errs = tmpl_errors_create();
   4015 	if (errs == NULL)
   4016 		uu_die(emesg_nomem);
   4017 
   4018 	lscf_prep_hndl();		/* Initialize g_hndl */
   4019 	if (load_init() != 0)
   4020 		uu_die(emesg_nomem);
   4021 
   4022 	/*
   4023 	 * We will process all services in the bundle, unless we get a
   4024 	 * fatal error.  That way we can report all errors on all services
   4025 	 * on a single run of svccfg.
   4026 	 */
   4027 	for (svc = uu_list_first(bndl->sc_bundle_services);
   4028 	    svc != NULL;
   4029 	    svc = uu_list_next(bndl->sc_bundle_services, svc)) {
   4030 		if (svc->sc_etype != SVCCFG_SERVICE_OBJECT) {
   4031 			semerr(gettext("Manifest for %s contains an object "
   4032 			    "named \"%s\" that is not a service.\n"),
   4033 			    bndl->sc_bundle_name, svc->sc_name);
   4034 			tmpl_errors_destroy(errs);
   4035 			load_fini();
   4036 			return (TVS_FATAL);
   4037 		}
   4038 		if ((r = tmpl_validate_service(svc, errs)) != TVS_SUCCESS)
   4039 			rc = r;
   4040 		if (r == TVS_FATAL)
   4041 			break;
   4042 	}
   4043 
   4044 	if (err_list == NULL) {
   4045 		tmpl_errors_destroy(errs);
   4046 	} else {
   4047 		*err_list = errs;
   4048 	}
   4049 
   4050 	load_fini();
   4051 
   4052 	return (rc);
   4053 }
   4054