xref: /titanic_51/usr/src/cmd/svc/svccfg/svccfg_tmpl.c (revision 53a7b6b6763f5865522a76e5e887390a8f4777d7)
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 2008 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 == ENOMEM)
1917 			uu_die(emesg_nomem);
1918 		else
1919 			svc->sc_u.sc_service.sc_restarter = NULL;
1920 	}
1921 	if (is_global == 0) {
1922 		if ((r = load_instance(SCF_INSTANCE_GLOBAL, "global",
1923 		    &svc->sc_u.sc_service.sc_global)) != 0) {
1924 			/*
1925 			 * During initial manifest import, global may not be in
1926 			 * the repository yet.
1927 			 */
1928 			if (r == ENOMEM)
1929 				uu_die(emesg_nomem);
1930 			else
1931 				svc->sc_u.sc_service.sc_global = NULL;
1932 		}
1933 	}
1934 }
1935 
1936 /*
1937  * Load the instance specific restarter if one is declared.
1938  *
1939  * There is no corresponding unload_instance_restarter() function because
1940  * it is not needed.  The memory will be freed in internal_instance_free()
1941  * when internal_bundle_free() is called.
1942  */
1943 static void
1944 load_instance_restarter(entity_t *i)
1945 {
1946 	const char *restarter;
1947 	int r;
1948 
1949 	assert(i->sc_etype == SVCCFG_INSTANCE_OBJECT);
1950 
1951 	restarter = find_restarter(i);
1952 	if (restarter == NULL) {
1953 		/* No instance specific restarter */
1954 		return;
1955 	}
1956 	r = load_instance(restarter, "instance_restarter",
1957 	    &i->sc_u.sc_instance.sc_instance_restarter);
1958 	if (r != 0) {
1959 		/*
1960 		 * During initial manifest import, the restarter may not be
1961 		 * in the repository yet.  In this case we continue on
1962 		 * without it.
1963 		 */
1964 		if (r == ENOMEM)
1965 			uu_die(emesg_nomem);
1966 	}
1967 }
1968 
1969 /*
1970  * Find the next property after current in the property group at pg.  If
1971  * the property group contains a tree of composed properties, that tree is
1972  * walked.  Otherwise, we walk through the uu_list at sc_pgroup_props.
1973  */
1974 static property_t *
1975 next_property(pgroup_t *pg, property_t *current)
1976 {
1977 	composed_pg_t *cpg;
1978 	property_t *prop;
1979 
1980 	cpg = pg->sc_pgroup_composed;
1981 	if ((cpg != NULL) && (cpg->cpg_composed_props != NULL)) {
1982 		/* Walk through composed property list. */
1983 		if (current) {
1984 			prop = uu_avl_next(cpg->cpg_composed_props, current);
1985 		} else {
1986 			prop = uu_avl_first(cpg->cpg_composed_props);
1987 		}
1988 	} else {
1989 		/* No composition available, so walk the list of properties */
1990 		if (current) {
1991 			prop = uu_list_next(pg->sc_pgroup_props, current);
1992 		} else {
1993 			prop = uu_list_first(pg->sc_pgroup_props);
1994 		}
1995 	}
1996 
1997 	return (prop);
1998 }
1999 
2000 static ptrn_info_t *
2001 ptrn_info_create(pgroup_t *pat)
2002 {
2003 	entity_t *e;
2004 	ptrn_info_t *info;
2005 	composed_pg_t *match;
2006 	composed_pg_t cpg;
2007 
2008 	info = safe_malloc(sizeof (*info));
2009 
2010 	switch (pgroup_type(pat)) {
2011 	case PG_PATTERN_PG:
2012 		info->pi_ptrn_type = PG_PATTERN;
2013 		break;
2014 	case PROP_PATTERN_PG:
2015 		info->pi_ptrn_type = PROP_PATTERN;
2016 		break;
2017 	default:
2018 		assert(0);
2019 		abort();
2020 	}
2021 	info->pi_ptrnpg = pat;
2022 	info->pi_name = find_name_specification(pat);
2023 	info->pi_name = EMPTY_TO_NULL(info->pi_name);
2024 	info->pi_type = find_type_specification(pat);
2025 	info->pi_type = EMPTY_TO_NULL(info->pi_type);
2026 	if (info->pi_ptrn_type == PG_PATTERN) {
2027 		info->pi_target = find_astring_value_in_pg(pat,
2028 		    SCF_PROPERTY_TM_TARGET);
2029 		if (info->pi_target == NULL)
2030 			info->pi_target = SCF_TM_TARGET_THIS;
2031 	}
2032 	if (info->pi_ptrn_type == PROP_PATTERN) {
2033 		info->pi_pgp_name = find_astring_value_in_pg(pat,
2034 		    SCF_PROPERTY_TM_PG_PATTERN);
2035 		assert((info->pi_pgp_name != NULL) &&
2036 		    (*(info->pi_pgp_name) != 0));
2037 
2038 		/*
2039 		 * Find the property group that defines the pg_pattern that
2040 		 * holds this prop_pattern.
2041 		 */
2042 		e = pat->sc_parent;
2043 		if (e->sc_etype == SVCCFG_INSTANCE_OBJECT) {
2044 			(void) memset(&cpg, 0, sizeof (cpg));
2045 			cpg.cpg_name = info->pi_pgp_name;
2046 			cpg.cpg_type = SCF_GROUP_TEMPLATE_PG_PATTERN;
2047 			match = uu_avl_find(e->sc_u.sc_instance.sc_composed,
2048 			    &cpg, NULL, NULL);
2049 			assert(match != NULL);
2050 			info->pi_enc_pgp = CPG2PG(match);
2051 		} else {
2052 			info->pi_enc_pgp = internal_pgroup_find(e,
2053 			    info->pi_pgp_name, SCF_GROUP_TEMPLATE_PG_PATTERN);
2054 		}
2055 		assert(info->pi_enc_pgp != NULL);
2056 	}
2057 	uu_avl_node_init(info, &info->pi_link, ptrn_info_pool);
2058 	return (info);
2059 }
2060 
2061 static void
2062 ptrn_info_destroy(ptrn_info_t *info)
2063 {
2064 	if (info == NULL)
2065 		return;
2066 	uu_avl_node_fini(info, &info->pi_link, ptrn_info_pool);
2067 	free(info);
2068 }
2069 
2070 /*
2071  * Walk through the property groups of the instance or service at e looking
2072  * for definitions of pg_patterns or prop_patterns as specified by type.
2073  * For each property group that matches type create a ptrn_info_t and add
2074  * it to the avl tree at tree.  If duplicates are found add an error entry
2075  * to errs.
2076  */
2077 static tmpl_validate_status_t
2078 gather_pattern(entity_t *e, ptrn_type_t type, uu_avl_t *tree,
2079     tmpl_errors_t *errs)
2080 {
2081 	error_info_t einfo;
2082 	ptrn_info_t *info = NULL;
2083 	uu_avl_index_t marker;
2084 	ptrn_info_t *match;
2085 	pgroup_t *pg;
2086 	tmpl_validate_status_t rc = TVS_SUCCESS;
2087 	const char *selector;
2088 
2089 	switch (type) {
2090 	case PG_PATTERN:
2091 		selector = SCF_GROUP_TEMPLATE_PG_PATTERN;
2092 		break;
2093 	case PROP_PATTERN:
2094 		selector = SCF_GROUP_TEMPLATE_PROP_PATTERN;
2095 		break;
2096 	default:
2097 		assert(0);
2098 		abort();
2099 	}
2100 
2101 	for (pg = uu_list_first(e->sc_pgroups);
2102 	    pg != NULL;
2103 	    pg = uu_list_next(e->sc_pgroups, pg)) {
2104 		if (strcmp(pg->sc_pgroup_type, selector) != 0) {
2105 			continue;
2106 		}
2107 		if (info != NULL) {
2108 			/* Get rid of old structure. */
2109 			ptrn_info_destroy(info);
2110 		}
2111 		info = ptrn_info_create(pg);
2112 		match = uu_avl_find(tree, info, NULL, &marker);
2113 		if (match == NULL) {
2114 			/* No match.  Insert the info. */
2115 			uu_avl_insert(tree, info, marker);
2116 			info = NULL;
2117 			continue;
2118 		}
2119 
2120 		/* Got a match.  Determine if it is a conflict. */
2121 		if ((info->pi_name == NULL) ||
2122 		    (info->pi_type == NULL) ||
2123 		    (match->pi_name == NULL) ||
2124 		    (match->pi_type == NULL)) {
2125 			/* No conflicts if any wild cards. */
2126 			continue;
2127 		}
2128 
2129 		/*
2130 		 * Name already matches, or we wouldn't have gotten
2131 		 * here.  Make sure that the type also matches.
2132 		 */
2133 		if (strcmp(info->pi_type, match->pi_type) == 0) {
2134 			continue;
2135 		}
2136 
2137 		/*
2138 		 * If we get to this point we have a conflict, and
2139 		 * we need to generate the correct type of error.
2140 		 */
2141 		CLEAR_ERROR_INFO(&einfo);
2142 		einfo.ei_type = EIT_PATTERN_CONFLICT;
2143 		einfo.ei_u.ei_pattern_conflict.ei_pattern =
2144 		    match->pi_ptrnpg;
2145 		if (type == PG_PATTERN) {
2146 			rc = TVS_VALIDATION;
2147 			if (add_scf_error(errs, SCF_TERR_PG_PATTERN_CONFLICT,
2148 			    info->pi_ptrnpg, NULL, NULL, NULL, NULL,
2149 			    &einfo) != 0) {
2150 				/*
2151 				 * If we can no longer accumulate
2152 				 * errors, break out of the loop.
2153 				 */
2154 				break;
2155 			}
2156 		} else {
2157 			/*
2158 			 * Possible conflicting prop_pattern.  See if the
2159 			 * prop_patterns are declared in the same
2160 			 * pg_pattern.
2161 			 */
2162 			if ((info->pi_pgp_name == NULL) ||
2163 			    (match->pi_pgp_name == NULL)) {
2164 				continue;
2165 			}
2166 			if (strcmp(info->pi_pgp_name, match->pi_pgp_name) != 0)
2167 				continue;
2168 
2169 			/* It is a real conflict. */
2170 			rc = TVS_VALIDATION;
2171 			if (add_scf_error(errs, SCF_TERR_PROP_PATTERN_CONFLICT,
2172 			    info->pi_enc_pgp, NULL, info->pi_ptrnpg, NULL, NULL,
2173 			    &einfo) != 0) {
2174 				/*
2175 				 * If we can no longer accumulate
2176 				 * errors, break out of the loop.
2177 				 */
2178 				break;
2179 			}
2180 		}
2181 	}
2182 
2183 	ptrn_info_destroy(info);
2184 	return (rc);
2185 }
2186 
2187 /*
2188  * Free the pg_iter structure.
2189  */
2190 static void
2191 pg_iter_destroy(pg_iter_t *i)
2192 {
2193 	if (i == NULL)
2194 		return;
2195 
2196 	uu_free(i);
2197 }
2198 
2199 /*
2200  * Create a property group iterator for the instance at e.  This iterator
2201  * will walk through the composed property groups of the instance.  It will
2202  * then step through the property groups of the instance's restarter and
2203  * finally the global service.  If you wish to iterate over a specific type
2204  * of property group, set restriction to point the the desired type.
2205  * Otherwise set restriction to NULL.
2206  *
2207  * The returned interator must be freed by calling pg_iter_destroy().  NULL
2208  * is returned if we are unable to allocate the necessary memory.
2209  */
2210 static pg_iter_t *
2211 pg_iter_create(entity_t *e, const char *restriction)
2212 {
2213 	pg_iter_t *i;
2214 
2215 	assert(e->sc_etype == SVCCFG_INSTANCE_OBJECT);
2216 
2217 	i = uu_zalloc(sizeof (*i));
2218 	if (i == NULL)
2219 		return (NULL);
2220 
2221 	i->pgi_entity = e;
2222 	i->pgi_restrict = restriction;
2223 	i->pgi_level = TL_COMPOSED;
2224 	i->pgi_service = e->sc_parent;
2225 
2226 	return (i);
2227 }
2228 
2229 /*
2230  * Return the next property group in the iteration.  NULL is returned if we
2231  * reach the end of the list.  The iterator will automatically proceed from
2232  * most specific to most general levels.
2233  */
2234 static pgroup_t *
2235 next_pattern_pg(pg_iter_t *i)
2236 {
2237 	composed_pg_t *cpg;
2238 	entity_t *e;
2239 	pgroup_t *pg;
2240 	uu_avl_t *composed_tree;
2241 
2242 	assert(i->pgi_level != TL_NOLEVEL);
2243 
2244 	while (i->pgi_entity != NULL) {
2245 		if (i->pgi_level == TL_COMPOSED) {
2246 			composed_tree =
2247 			    i->pgi_entity->sc_u.sc_instance.sc_composed;
2248 			cpg = i->pgi_current.pgi_cpg;
2249 			if (cpg == NULL) {
2250 				cpg = uu_avl_first(composed_tree);
2251 			} else {
2252 				cpg = uu_avl_next(composed_tree, cpg);
2253 			}
2254 			if (cpg == NULL) {
2255 				pg = NULL;
2256 			} else {
2257 				pg = CPG2PG(cpg);
2258 				i->pgi_current.pgi_cpg = cpg;
2259 			}
2260 		} else {
2261 			pg = i->pgi_current.pgi_pg;
2262 			if (pg == NULL) {
2263 				pg = uu_list_first(i->pgi_entity->sc_pgroups);
2264 			} else {
2265 				pg = uu_list_next(i->pgi_entity->sc_pgroups,
2266 				    pg);
2267 			}
2268 			i->pgi_current.pgi_pg = pg;
2269 		}
2270 
2271 		if (pg == NULL) {
2272 			/*
2273 			 * End of the list.  Reset current and break out of
2274 			 * the loop.
2275 			 */
2276 			(void) memset(&i->pgi_current, 0,
2277 			    sizeof (i->pgi_current));
2278 			break;
2279 		}
2280 
2281 		/*
2282 		 * If this iteration is for a specific type, verify that
2283 		 * this pg is of that type.
2284 		 */
2285 		if (i->pgi_restrict) {
2286 			if (strcmp(pg->sc_pgroup_type, i->pgi_restrict) != 0) {
2287 				continue;
2288 			}
2289 		}
2290 
2291 		return (pg);
2292 	}
2293 
2294 	/*
2295 	 * End of the list in the current level.  Move up to the next
2296 	 * level.
2297 	 */
2298 	switch (i->pgi_level) {
2299 	case TL_COMPOSED:
2300 		/* Skip service if we've finished a composed instance. */
2301 		e = i->pgi_entity;
2302 		if (e->sc_u.sc_instance.sc_instance_restarter == NULL) {
2303 			/* Use service restarter */
2304 			i->pgi_entity =
2305 			    i->pgi_service->sc_u.sc_service.sc_restarter;
2306 		} else {
2307 			/* Use instance restarter */
2308 			i->pgi_entity =
2309 			    e->sc_u.sc_instance.sc_instance_restarter;
2310 		}
2311 		i->pgi_level = TL_RESTARTER;
2312 		break;
2313 	case TL_RESTARTER:
2314 		i->pgi_entity = i->pgi_service->sc_u.sc_service.sc_global;
2315 		i->pgi_level = TL_GLOBAL;
2316 		break;
2317 	case TL_GLOBAL:
2318 		i->pgi_level = TL_NOLEVEL;
2319 		return (NULL);
2320 	default:
2321 		assert(0);
2322 		abort();
2323 	}
2324 
2325 	/* Go process the next level. */
2326 	return (next_pattern_pg(i));
2327 }
2328 
2329 /*
2330  * Compare two pattern info structures (ptrn_info_t).  If both structures
2331  * have names, the comparison is based on the name.  If only one has a
2332  * name, the structure with no name will be first.  If neither structure
2333  * has a name, the comparison is based on their types using similar wild
2334  * card logic.
2335  */
2336 /* ARGSUSED2 */
2337 static int
2338 ptrn_info_compare(const  void *left, const void *right, void *unused)
2339 {
2340 	ptrn_info_t *l = (ptrn_info_t *)left;
2341 	ptrn_info_t *r = (ptrn_info_t *)right;
2342 
2343 	if ((l->pi_name != NULL) && (r->pi_name != NULL))
2344 		return (strcmp(l->pi_name, r->pi_name));
2345 	if ((l->pi_name == NULL) && (r->pi_name == NULL)) {
2346 		/* No names, so we need to compare types. */
2347 		if ((l->pi_type != NULL) && (r->pi_type != NULL))
2348 			return (strcmp(l->pi_type, r->pi_type));
2349 		if ((l->pi_type == NULL) && (r->pi_type == NULL))
2350 			return (0);
2351 
2352 		/* If we get here, exactly one of the types is NULL */
2353 		if (l->pi_type == NULL)
2354 			return (-1);
2355 		return (1);
2356 	}
2357 
2358 	/* If we get here, exactly one of the names is NULL */
2359 	if (l->pi_name == NULL)
2360 		return (-1);
2361 	return (1);
2362 }
2363 
2364 /*
2365  * The target of a pg_pattern in combination with the level at which the
2366  * pg_pattern was defined determines whether or not it should be applied.
2367  * The following combinations should be ignored, and all others should be
2368  * applied.
2369  *
2370  *	Target		Level
2371  *	------		-----
2372  *	this		TL_RESTARTER, TL_GLOBAL
2373  *			"this" only applies if the pg_pattern was defined
2374  *			at the instance or service level
2375  *	delegate	TL_INSTANCE, TL_SERVICE
2376  *			Only restarters and the global service can
2377  *			delegate.
2378  *	instance	TL_INSTANCE, TL_RESTARTER, TL_GLOBAL
2379  *			Only the service level can specify the "instance"
2380  *			target.
2381  *	all		TL_INSTANCE, TL_SERVICE, TL_RESTARTER
2382  *			Only the global service can specify the "all"
2383  *			target.
2384  *
2385  * Return Values:
2386  *	1	apply the pg_pattern
2387  *	0	ignore the pg_pattern
2388  */
2389 static int
2390 target_check(const char *target, tmpl_level_t level)
2391 {
2392 	if ((target == NULL) || (*target == 0)) {
2393 		/* Default is this */
2394 		target = SCF_TM_TARGET_THIS;
2395 	}
2396 	if (strcmp(target, SCF_TM_TARGET_THIS) == 0) {
2397 		if ((level == TL_RESTARTER) ||
2398 		    (level == TL_GLOBAL)) {
2399 			return (0);
2400 		} else {
2401 			return (1);
2402 		}
2403 	}
2404 	if (strcmp(target, SCF_TM_TARGET_DELEGATE) == 0) {
2405 		if ((level == TL_INSTANCE) ||
2406 		    (level == TL_SERVICE)) {
2407 			return (0);
2408 		} else {
2409 			return (1);
2410 		}
2411 	}
2412 	if (strcmp(target, SCF_TM_TARGET_INSTANCE) == 0) {
2413 		/*
2414 		 * Note that the test is inverted from the other cases.
2415 		 * This is because there is only one instance where apply
2416 		 * is the correct thing to do.
2417 		 */
2418 		if (level == TL_SERVICE) {
2419 			return (1);
2420 		} else {
2421 			return (0);
2422 		}
2423 	}
2424 	if (strcmp(target, SCF_TM_TARGET_ALL) == 0) {
2425 		if ((level == TL_INSTANCE) ||
2426 		    (level == TL_SERVICE) ||
2427 		    (level == TL_RESTARTER)) {
2428 			return (0);
2429 		}
2430 	}
2431 	return (1);
2432 }
2433 
2434 static int
2435 pg_target_check(pgroup_t *pg_pattern, tmpl_level_t level)
2436 {
2437 	const char *target;
2438 
2439 	target = find_astring_value_in_pg(pg_pattern, SCF_PROPERTY_TM_TARGET);
2440 	if (level == TL_COMPOSED) {
2441 		switch (pg_pattern->sc_parent->sc_etype) {
2442 		case SVCCFG_INSTANCE_OBJECT:
2443 			level = TL_INSTANCE;
2444 			break;
2445 		case SVCCFG_SERVICE_OBJECT:
2446 			level = TL_SERVICE;
2447 			break;
2448 		default:
2449 			assert(0);
2450 			abort();
2451 		}
2452 	}
2453 	return (target_check(target, level));
2454 }
2455 
2456 /*
2457  * Find the prop_pattern's type sepcification and convert it to the
2458  * appropriate scf_type.
2459  */
2460 static tmpl_validate_status_t
2461 prop_pattern_type(pgroup_t *pattern, scf_type_t *type)
2462 {
2463 	const char *type_spec;
2464 
2465 	assert(strcmp(pattern->sc_pgroup_type,
2466 	    SCF_GROUP_TEMPLATE_PROP_PATTERN) == 0);
2467 
2468 	type_spec = find_type_specification(pattern);
2469 	if ((type_spec == NULL) || (*type_spec == 0))
2470 		return (TVS_MISSING_TYPE_SPECIFICATION);
2471 	*type = scf_string_to_type(type_spec);
2472 	return (TVS_SUCCESS);
2473 }
2474 
2475 /*
2476  * This function is analagous to scf_property_is_type(3SCF), but it works
2477  * on the in memory representation of the property.
2478  *
2479  * RETURNS:
2480  *	0		The property at prop does not have the specified
2481  *			type.
2482  *	non-zero	The property at prop does have the specified type.
2483  */
2484 static int
2485 property_is_type(property_t *prop, scf_type_t type)
2486 {
2487 	return (prop->sc_value_type == type);
2488 }
2489 
2490 /*
2491  * This function generates a property group name for a template's
2492  * pg_pattern.  The name and type of the pg_pattern are used to construct
2493  * the name, but either or both may be null.  A pointer to the constructed
2494  * name is returned, and the referenced memory must be freed using
2495  * free(3c).  NULL is returned if we are unable to allocate enough memory.
2496  */
2497 static char *
2498 gen_pg_pattern_pg_name(const char *name, const char *type)
2499 {
2500 	char *pg_name;
2501 	char *rv = NULL;
2502 	ssize_t	name_size;
2503 
2504 	name_size = scf_limit(SCF_LIMIT_MAX_NAME_LENGTH);
2505 	pg_name = safe_malloc(name_size);
2506 	rv = pg_name;
2507 
2508 	/*
2509 	 * There are four cases -- name and type are both null, name and
2510 	 * type are both non-null, only name is present or only type is
2511 	 * present.
2512 	 */
2513 	if ((name == NULL) || (*name == 0)) {
2514 		if ((type == NULL) || (*type == 0)) {
2515 			/*
2516 			 * Name and type are both null, so the PG name
2517 			 * contains only the prefix.
2518 			 */
2519 			if (strlcpy(pg_name, SCF_PG_TM_PG_PATTERN_PREFIX,
2520 			    name_size) >= name_size) {
2521 				rv = NULL;
2522 			}
2523 		} else {
2524 			/*
2525 			 * If we have a type and no name, the type becomes
2526 			 * part of the pg_pattern property group name.
2527 			 */
2528 			if (snprintf(pg_name, name_size, "%s%s",
2529 			    SCF_PG_TM_PG_PATTERN_T_PREFIX, type) >=
2530 			    name_size) {
2531 				rv = NULL;
2532 			}
2533 		}
2534 	} else {
2535 		/*
2536 		 * As long as the pg_pattern has a name, it becomes part of
2537 		 * the name of the pg_pattern property group name.  We
2538 		 * merely need to pick the appropriate prefix.
2539 		 */
2540 		const char *prefix;
2541 		if ((type == NULL) || (*type == 0)) {
2542 			prefix = SCF_PG_TM_PG_PATTERN_N_PREFIX;
2543 		} else {
2544 			prefix = SCF_PG_TM_PG_PATTERN_NT_PREFIX;
2545 		}
2546 		if (snprintf(pg_name, name_size, "%s%s", prefix, name) >=
2547 		    name_size) {
2548 			rv = NULL;
2549 		}
2550 	}
2551 
2552 	if (rv == NULL) {
2553 		/* Name was too big. */
2554 		free(pg_name);
2555 	}
2556 	return (rv);
2557 }
2558 
2559 /*
2560  * pinfo contains information about a prop_pattern.  An include_values
2561  * element with a type of type has been included in the prop_pattern
2562  * specification.  We need to determine if the prop_pattern also contains
2563  * constraints or values specifications as determined by type.  Thus, we
2564  * search the prop_pattern for properties whose names start with the
2565  * correct prefix.
2566  */
2567 static tmpl_validate_status_t
2568 include_values_support(ptrn_info_t *pinfo, const char *type,
2569     tmpl_errors_t *errs)
2570 {
2571 	error_info_t einfo;
2572 	int i;
2573 	const char **prefixes;
2574 	const char *pfx;
2575 	property_t *prop;
2576 	pgroup_t *ptrn;
2577 
2578 	if (strcmp(type, "constraints") == 0) {
2579 		prefixes = constraint_prefixes;
2580 	} else if (strcmp(type, "values") == 0) {
2581 		prefixes = value_prefixes;
2582 	} else {
2583 		CLEAR_ERROR_INFO(&einfo);
2584 		einfo.ei_type = EIT_BAD_TEMPLATE;
2585 		einfo.ei_u.ei_bad_template.ei_reason = gettext("include_values "
2586 		    "type must be \"constraints\" or \"values\"");
2587 		(void) tmpl_errors_add_im(errs, TVS_BAD_TEMPLATE,
2588 		    pinfo->pi_ptrnpg->sc_parent, pinfo->pi_enc_pgp,
2589 		    NULL, pinfo->pi_ptrnpg, NULL, NULL, &einfo);
2590 		return (TVS_BAD_TEMPLATE);
2591 	}
2592 
2593 	/*
2594 	 * Now see if the prop_pattern has a property whose name starts
2595 	 * with one of these prefixes.
2596 	 */
2597 	ptrn = pinfo->pi_ptrnpg;
2598 	for (prop = uu_list_first(ptrn->sc_pgroup_props);
2599 	    prop != NULL;
2600 	    prop = uu_list_next(ptrn->sc_pgroup_props, prop)) {
2601 		for (pfx = prefixes[0], i = 0;
2602 		    pfx != NULL;
2603 		    ++i, pfx = prefixes[i]) {
2604 			if (strncmp(prop->sc_property_name, pfx,
2605 			    strlen(pfx)) == 0) {
2606 				return (TVS_SUCCESS);
2607 			}
2608 		}
2609 	}
2610 
2611 	/* No match found.  Generate error */
2612 	CLEAR_ERROR_INFO(&einfo);
2613 	einfo.ei_type = EIT_INCLUDE_VALUES;
2614 	einfo.ei_u.ei_inc_values.ei_type = type;
2615 	(void) add_scf_error(errs, SCF_TERR_INCLUDE_VALUES, pinfo->pi_enc_pgp,
2616 	    NULL, ptrn, NULL, NULL, &einfo);
2617 
2618 	return (TVS_VALIDATION);
2619 }
2620 
2621 /*
2622  * Walk through the prop_patterns in tree, looking for any that have an
2623  * include_values, SCF_PROPERTY_TM_CHOICES_INCLUDE_VALUES, property.  For
2624  * the prop_patterns with the include values property, verify that the
2625  * prop_pattern has constraint or values declarations as specified by the
2626  * include_values property.
2627  */
2628 static tmpl_validate_status_t
2629 tmpl_include_values_check(uu_avl_t *tree, tmpl_errors_t *errs)
2630 {
2631 	ptrn_info_t *info;
2632 	property_t *iv;
2633 	tmpl_validate_status_t r;
2634 	tmpl_validate_status_t rc = TVS_SUCCESS;
2635 	value_t *v;
2636 
2637 	for (info = uu_avl_first(tree);
2638 	    info != NULL;
2639 	    info = uu_avl_next(tree, info)) {
2640 		iv = internal_property_find(info->pi_ptrnpg,
2641 		    SCF_PROPERTY_TM_CHOICES_INCLUDE_VALUES);
2642 		if (iv == NULL)
2643 			continue;
2644 		for (v = uu_list_first(iv->sc_property_values);
2645 		    v != NULL;
2646 		    v = uu_list_next(iv->sc_property_values, v)) {
2647 			assert(is_numeric_type(v->sc_type) == 0);
2648 			r = include_values_support(info, v->sc_u.sc_string,
2649 			    errs);
2650 			if (r != TVS_SUCCESS)
2651 				rc = r;
2652 		}
2653 	}
2654 	return (rc);
2655 }
2656 
2657 /*
2658  * Verify that there are no conflicting definitions of pg_pattern or
2659  * prop_pattern.  Two patterns are said to be in conflict if they have the
2660  * same name and differing types.  There is a caveat, however.  Empty
2661  * pattern names or types are considered to be wild cards.  There is no
2662  * conflict if a pattern has a wild card.
2663  */
2664 static tmpl_validate_status_t
2665 tmpl_pattern_conflict(entity_t *inst, uu_avl_t *tree, ptrn_type_t type,
2666     tmpl_errors_t *errs)
2667 {
2668 	tmpl_validate_status_t r;
2669 	tmpl_validate_status_t rc;
2670 
2671 	/* First walk the instance. */
2672 	rc = gather_pattern(inst, type, tree, errs);
2673 
2674 	/* Now walk the service */
2675 	r = gather_pattern(inst->sc_parent, type, tree, errs);
2676 	if (r != TVS_SUCCESS)
2677 		rc = r;
2678 
2679 	return (rc);
2680 }
2681 
2682 static tmpl_validate_status_t
2683 tmpl_required_attr_present(uu_avl_t *tree, tmpl_errors_t *errs)
2684 {
2685 	ptrn_info_t *pinfo;
2686 	tmpl_validate_status_t rc = TVS_SUCCESS;
2687 	int reported_name;
2688 	int rv;
2689 
2690 	for (pinfo = uu_avl_first(tree);
2691 	    pinfo != NULL;
2692 	    pinfo = uu_avl_next(tree, pinfo)) {
2693 		if (is_required(pinfo->pi_ptrnpg) == 0) {
2694 			/* Nothing to check if pattern is not required. */
2695 			continue;
2696 		}
2697 
2698 		/*
2699 		 * For pg_pattern both name and type are optional unless
2700 		 * the required attribute has a value of true.  For
2701 		 * prop_patterns only the type is optional, but it must be
2702 		 * provided if the required attribute has a value of true.
2703 		 */
2704 		reported_name = 0;
2705 		if ((pinfo->pi_ptrn_type == PG_PATTERN) &&
2706 		    (pinfo->pi_name == NULL)) {
2707 			rc = TVS_VALIDATION;
2708 			if (add_scf_error(errs, SCF_TERR_PG_PATTERN_INCOMPLETE,
2709 			    pinfo->pi_ptrnpg,
2710 			    NULL, NULL, NULL, NULL, NULL) != 0) {
2711 				/*
2712 				 * If we're unable to report errors, break
2713 				 * out of the loop.
2714 				 */
2715 				break;
2716 			}
2717 			/*
2718 			 * Don't report the error twice if both name and
2719 			 * type are missing.  One error message is
2720 			 * adequate.
2721 			 */
2722 			reported_name = 1;
2723 		}
2724 		if ((pinfo->pi_type == NULL) && (reported_name == 0)) {
2725 			rc = TVS_VALIDATION;
2726 			if (pinfo->pi_ptrn_type == PG_PATTERN) {
2727 				rv = add_scf_error(errs,
2728 				    SCF_TERR_PG_PATTERN_INCOMPLETE,
2729 				    pinfo->pi_ptrnpg,
2730 				    NULL, NULL, NULL, NULL, NULL);
2731 			} else {
2732 				rv = add_scf_error(errs,
2733 				    SCF_TERR_PROP_PATTERN_INCOMPLETE,
2734 				    pinfo->pi_enc_pgp, NULL, pinfo->pi_ptrnpg,
2735 				    NULL, NULL, NULL);
2736 			}
2737 			/* If we're unable to log errors, break out of loop. */
2738 			if (rv != 0)
2739 				break;
2740 		}
2741 	}
2742 	return (rc);
2743 }
2744 
2745 /*
2746  * Look for pg_pattern definitions in general.  general is either the
2747  * restarter serivce for inst or it is the global service.  tree contains
2748  * the ptrn_info_t structures describing the pg_patterns for an instance.
2749  * For each general pg_pattern, see if the instance contains an overriding
2750  * definition in tree.  If it does generate an error entry.
2751  *
2752  * If a redefinition is found, TVS_WARN is returned.  This is because a
2753  * redefinition is not sufficient reason to inhibit the import operation.
2754  */
2755 static tmpl_validate_status_t
2756 tmpl_scan_general(entity_t *general, uu_avl_t *tree,
2757     tmpl_level_t level, tmpl_errors_t *errs)
2758 {
2759 	tmpl_level_t cur_level;
2760 	error_info_t einfo;
2761 	pgroup_t *pg;
2762 	ptrn_info_t *ginfo = NULL;
2763 	ptrn_info_t *match;
2764 	tmpl_validate_status_t rc = TVS_SUCCESS;
2765 
2766 	/*
2767 	 * General services may not be in repository yet.  It depends on
2768 	 * the order that manifests are imported.
2769 	 */
2770 	if (general == NULL)
2771 		return (TVS_SUCCESS);
2772 
2773 	for (pg = uu_list_first(general->sc_pgroups);
2774 	    pg != NULL;
2775 	    pg = uu_list_next(general->sc_pgroups, pg)) {
2776 		if (strcmp(pg->sc_pgroup_type,
2777 		    SCF_GROUP_TEMPLATE_PG_PATTERN) != 0) {
2778 			/* Not a pg_pattern */
2779 			continue;
2780 		}
2781 		if (ginfo != NULL)
2782 			ptrn_info_destroy(ginfo);
2783 		ginfo = ptrn_info_create(pg);
2784 		match = uu_avl_find(tree, ginfo, NULL, NULL);
2785 		if (match != NULL) {
2786 			/* See if global pg_pattern is targeted at us. */
2787 			if (target_check(ginfo->pi_target, level) == 0)
2788 				continue;
2789 
2790 			/*
2791 			 * See if the match applies to us.  If we happen to
2792 			 * be a restarter, the pg_pattern could have a
2793 			 * target of delegate.  That wouldn't apply to this
2794 			 * instance, it would only apply to our delegates.
2795 			 * Cases such as this are not a redefinition.
2796 			 */
2797 			if (match->pi_ptrnpg->sc_parent->sc_etype ==
2798 			    SVCCFG_INSTANCE_OBJECT) {
2799 				cur_level = TL_INSTANCE;
2800 			} else {
2801 				cur_level = TL_SERVICE;
2802 			}
2803 			if (target_check(match->pi_target, cur_level) == 0)
2804 				continue;
2805 
2806 			/*
2807 			 * Instance or service overrides a general
2808 			 * definition.  We need to issue a warning message.
2809 			 */
2810 			rc = TVS_WARN;
2811 			CLEAR_ERROR_INFO(&einfo);
2812 			einfo.ei_type = EIT_PATTERN_CONFLICT;
2813 			einfo.ei_u.ei_pattern_conflict.ei_pattern = pg;
2814 			if (add_scf_error(errs, SCF_TERR_GENERAL_REDEFINE,
2815 			    match->pi_ptrnpg, NULL, NULL, NULL, NULL,
2816 			    &einfo) != 0) {
2817 				/*
2818 				 * No need to continue the search if we
2819 				 * cannot record errors.
2820 				 */
2821 				break;
2822 			}
2823 		}
2824 	}
2825 
2826 	if (ginfo != NULL)
2827 		ptrn_info_destroy(ginfo);
2828 	return (rc);
2829 }
2830 
2831 /*
2832  * tree contains the pg_pattern definitions for the instance at inst.  See
2833  * if these pg_patterns redefine any pg_patterns in the instance's
2834  * restarter or in the global service.  TVS_WARN is returned if a
2835  * redefinition is encountered.
2836  */
2837 static tmpl_validate_status_t
2838 tmpl_level_redefine(entity_t *inst, uu_avl_t *tree, tmpl_errors_t *errs)
2839 {
2840 	entity_t *restarter;
2841 	entity_t *svc = inst->sc_parent;
2842 	tmpl_validate_status_t r;
2843 	tmpl_validate_status_t rc;
2844 
2845 	restarter = inst->sc_u.sc_instance.sc_instance_restarter;
2846 	if (restarter == NULL) {
2847 		/* No instance restarter.  Use the service restarter */
2848 		restarter = svc->sc_u.sc_service.sc_restarter;
2849 	}
2850 	rc = tmpl_scan_general(restarter, tree, TL_RESTARTER, errs);
2851 	r = tmpl_scan_general(svc->sc_u.sc_service.sc_global, tree,
2852 	    TL_GLOBAL, errs);
2853 	if (r != TVS_SUCCESS)
2854 		rc = r;
2855 	return (rc);
2856 }
2857 
2858 /*
2859  * Perform the following consistency checks on the template specifications
2860  * themselves:
2861  *
2862  *	- No conflicting definitions of `pg_pattern` are allowed within a
2863  *	  single instance.
2864  *
2865  *	- Templates at a narrow target (e.g. instance) which define
2866  *	  property groups already templated at a broad target
2867  *	  (e.g. restarter or all) are strongly discouraged.
2868  *
2869  *	- Developers may not define a template which specifies a single
2870  *	  prop_pattern name with differing types on the same target
2871  *	  entity.
2872  *
2873  *	- If a pg_pattern has a required attribute with a value of true,
2874  *	  then its name and type attributes must be specified.
2875  *
2876  *	- If a prop_pattern has a required attribute with a value of true,
2877  *	  then its type attribute must be specified.
2878  *
2879  *	- If a prop_pattern has an include values make sure that the
2880  *	  appropriate constraints or values element has also been
2881  *	  declared.
2882  */
2883 static tmpl_validate_status_t
2884 tmpl_consistency(entity_t *inst, tmpl_errors_t *errs)
2885 {
2886 	void *marker = NULL;
2887 	ptrn_info_t *info;
2888 	uu_avl_t *tree;
2889 	tmpl_validate_status_t rc;
2890 	tmpl_validate_status_t r;
2891 
2892 	/* Allocate the tree. */
2893 	tree = uu_avl_create(ptrn_info_pool, NULL, TMPL_DEBUG_TREE);
2894 	if (tree == NULL) {
2895 		uu_die(gettext("pg_info tree creation failed: %s\n"),
2896 		    uu_strerror(uu_error()));
2897 	}
2898 
2899 	rc = tmpl_pattern_conflict(inst, tree, PG_PATTERN, errs);
2900 
2901 	/*
2902 	 * The tree now contains the instance and service pg_patterns.
2903 	 * Check to see if they override any pg_pattern definitions in the
2904 	 * restarter and global services.
2905 	 */
2906 	r = tmpl_level_redefine(inst, tree, errs);
2907 	if (r != TVS_SUCCESS) {
2908 		/*
2909 		 * tmpl_level_redefine() can return a warning.  Don't
2910 		 * override a serious error with a warning.
2911 		 */
2912 		if (r == TVS_WARN) {
2913 			if (rc == TVS_SUCCESS)
2914 				rc = r;
2915 		} else {
2916 			rc = r;
2917 		}
2918 	}
2919 
2920 	/*
2921 	 * If the pg_pattern has a required attribute with a value of true,
2922 	 * then it must also have name and type attributes.
2923 	 */
2924 	r = tmpl_required_attr_present(tree, errs);
2925 	if (r != TVS_SUCCESS)
2926 		rc = r;
2927 
2928 	/* Empty the tree, so that we can reuse it for prop_patterns. */
2929 	while ((info = uu_avl_teardown(tree, &marker)) != NULL) {
2930 		ptrn_info_destroy(info);
2931 	}
2932 
2933 	r = tmpl_pattern_conflict(inst, tree, PROP_PATTERN, errs);
2934 	if (r != TVS_SUCCESS)
2935 		rc = r;
2936 
2937 	/*
2938 	 * If a prop_pattern has required attribute with a value of true,
2939 	 * then it must also have a type attribute.
2940 	 */
2941 	r = tmpl_required_attr_present(tree, errs);
2942 	if (r != TVS_SUCCESS)
2943 		rc = r;
2944 
2945 	/*
2946 	 * Insure that include_values have the constraint for values
2947 	 * elements that are needed.
2948 	 */
2949 	r = tmpl_include_values_check(tree, errs);
2950 	if (r != TVS_SUCCESS)
2951 		rc = r;
2952 
2953 	/* Tear down the tree. */
2954 	marker = NULL;
2955 	while ((info = uu_avl_teardown(tree, &marker)) != NULL) {
2956 		ptrn_info_destroy(info);
2957 	}
2958 	uu_avl_destroy(tree);
2959 
2960 	return (rc);
2961 }
2962 
2963 /*
2964  * Release memory associated with the tmpl_errors structure and then free
2965  * the structure itself.
2966  */
2967 void
2968 tmpl_errors_destroy(tmpl_errors_t *te)
2969 {
2970 	im_tmpl_error_t *ite;
2971 	tv_errors_t *ste;
2972 	void *marker = NULL;
2973 
2974 	if (te == NULL)
2975 		return;
2976 	if (te->te_list) {
2977 		while ((ite = uu_list_teardown(te->te_list, &marker)) != NULL) {
2978 			uu_list_node_fini(ite, &ite->ite_node,
2979 			    inmem_errors_pool);
2980 			uu_free(ite);
2981 		}
2982 		uu_list_destroy(te->te_list);
2983 	}
2984 	if (te->te_scf) {
2985 		marker = NULL;
2986 		while ((ste = uu_list_teardown(te->te_scf, &marker)) != NULL) {
2987 			destroy_scf_errors(ste);
2988 		}
2989 		uu_list_destroy(te->te_scf);
2990 	}
2991 	uu_free(te);
2992 }
2993 
2994 /*
2995  * Allocate and initialize a tmpl_errors structure.  The address of the
2996  * structure is returned, unless we are unable to allocate enough memory.
2997  * In the case of memory allocation failures, NULL is returned.
2998  *
2999  * The allocated structure should be freed by calling
3000  * tmpl_errors_destroy().
3001  */
3002 static tmpl_errors_t *
3003 tmpl_errors_create()
3004 {
3005 	tmpl_errors_t *te;
3006 
3007 	te = uu_zalloc(sizeof (*te));
3008 	if (te == NULL)
3009 		return (NULL);
3010 	te->te_list = uu_list_create(inmem_errors_pool, NULL, TMPL_DEBUG_LIST);
3011 	if (te->te_list == NULL) {
3012 		uu_free(te);
3013 		return (NULL);
3014 	}
3015 	te->te_scf = uu_list_create(tv_errors_pool, NULL, TMPL_DEBUG_LIST);
3016 	if (te->te_scf == NULL) {
3017 		tmpl_errors_destroy(te);
3018 		return (NULL);
3019 	}
3020 
3021 	return (te);
3022 }
3023 
3024 void
3025 tmpl_errors_print(FILE *out, tmpl_errors_t *errs, const char *prefix)
3026 {
3027 	scf_tmpl_error_t *cur;
3028 	size_t buf_size = 4096;
3029 	im_tmpl_error_t *ite;
3030 	char *s = NULL;
3031 	scf_tmpl_errors_t *scferrs;
3032 	tv_errors_t *scft;
3033 	int interactive = (est->sc_cmd_flags & SC_CMD_IACTIVE) ?
3034 	    SCF_TMPL_STRERROR_HUMAN : 0;
3035 
3036 	for (ite = uu_list_first(errs->te_list);
3037 	    ite != NULL;
3038 	    ite = uu_list_next(errs->te_list, ite)) {
3039 		im_tmpl_error_print(out, ite, prefix);
3040 	}
3041 
3042 	/* Now handle the errors that can be printed via libscf. */
3043 	s = safe_malloc(buf_size);
3044 	for (scft = uu_list_first(errs->te_scf);
3045 	    scft != NULL;
3046 	    scft = uu_list_next(errs->te_scf, scft)) {
3047 		scferrs = scft->tve_errors;
3048 		if (_scf_tmpl_error_set_prefix(scferrs, prefix) != 0)
3049 			uu_die(emesg_nomem);
3050 		while ((cur = scf_tmpl_next_error(scferrs)) != NULL) {
3051 			(void) scf_tmpl_strerror(cur, s, buf_size, interactive);
3052 			(void) fputs(s, out);
3053 			(void) fputc('\n', out);
3054 		}
3055 	}
3056 
3057 	free(s);
3058 }
3059 
3060 /*
3061  * This function finds the prop_pattern for the property, prop.  e is the
3062  * instance where the search for the prop_pattern will start.  pg_pattern
3063  * is the address of the pg_pattern that holds the prop_pattern.
3064  */
3065 static tmpl_validate_status_t
3066 tmpl_find_prop_pattern(entity_t *inst, pgroup_t *pg_pattern,
3067     property_t *prop, pgroup_t **prop_pattern)
3068 {
3069 	pgroup_t *candidate;
3070 	pg_iter_t *iter = NULL;
3071 	char *prop_pattern_name = NULL;
3072 	tmpl_validate_status_t rc;
3073 
3074 	/*
3075 	 * Get the name of the property group that holds the prop_pattern
3076 	 * definition.
3077 	 */
3078 	rc = gen_prop_pattern_pg_name(pg_pattern,
3079 	    prop->sc_property_name, &prop_pattern_name);
3080 	if (rc != TVS_SUCCESS)
3081 		goto out;
3082 
3083 	/* Find the property group. */
3084 	iter = pg_iter_create(inst, SCF_GROUP_TEMPLATE_PROP_PATTERN);
3085 	if (iter == NULL)
3086 		goto out;
3087 	while ((candidate = next_pattern_pg(iter)) != NULL) {
3088 		const char *c;
3089 
3090 		if (strcmp(prop_pattern_name, candidate->sc_pgroup_name) != 0)
3091 			continue;
3092 		c = find_astring_value_in_pg(candidate,
3093 		    SCF_PROPERTY_TM_PG_PATTERN);
3094 		if (c == NULL)
3095 			continue;
3096 		if (strcmp(pg_pattern->sc_pgroup_name, c) == 0)
3097 			break;
3098 	}
3099 	*prop_pattern = candidate;
3100 	if (candidate == NULL)
3101 		rc = TVS_NOMATCH;
3102 
3103 out:
3104 	pg_iter_destroy(iter);
3105 	uu_free((void *)prop_pattern_name);
3106 	return (rc);
3107 }
3108 
3109 /*
3110  * Indexes for pg_pattern property group names.  Indexes are arranged
3111  * from most specific to least specific.
3112  */
3113 #define	PGN_BOTH	0	/* both name and type */
3114 #define	PGN_NAME	1	/* name only */
3115 #define	PGN_TYPE	2	/* type only */
3116 #define	PGN_NEITHER	3	/* neither name nor type */
3117 #define	PGN_MAX		4	/* Size of array */
3118 
3119 /*
3120  * Given an instance entity, e, and a propety group, pg, within the
3121  * instance; return the address of the pg_pattern for the property group.
3122  * The address of the pg_pattern is placed at pgp.  NULL indicates that no
3123  * pg_pattern was specified.
3124  */
3125 static tmpl_validate_status_t
3126 tmpl_find_pg_pattern(entity_t *e, pgroup_t *pg, pgroup_t **pgp)
3127 {
3128 	pgroup_t *cpg;		/* candidate property group */
3129 	int i;
3130 	pg_iter_t *iter = NULL;
3131 	char *pg_names[PGN_MAX];
3132 	pgroup_t *pg_patterns[PGN_MAX];
3133 	tmpl_validate_status_t rv = TVS_SUCCESS;
3134 
3135 	(void) memset(pg_patterns, 0, sizeof (pg_patterns));
3136 	*pgp = NULL;
3137 
3138 	/* Generate candidate names for pg_pattern property groups. */
3139 	pg_names[PGN_BOTH] = gen_pg_pattern_pg_name(pg->sc_pgroup_name,
3140 	    pg->sc_pgroup_type);
3141 	pg_names[PGN_NAME] = gen_pg_pattern_pg_name(pg->sc_pgroup_name,
3142 	    NULL);
3143 	pg_names[PGN_TYPE] = gen_pg_pattern_pg_name(NULL,
3144 	    pg->sc_pgroup_type);
3145 	pg_names[PGN_NEITHER] = gen_pg_pattern_pg_name(NULL, NULL);
3146 	for (i = 0; i < PGN_MAX; i++) {
3147 		if (pg_names[i] == NULL) {
3148 			rv = TVS_BAD_TEMPLATE;
3149 			goto errout;
3150 		}
3151 	}
3152 
3153 	/* Search for property groups that match these names */
3154 	iter = pg_iter_create(e, SCF_GROUP_TEMPLATE_PG_PATTERN);
3155 	if (iter == NULL) {
3156 		uu_die(emesg_nomem);
3157 	}
3158 	while ((cpg = next_pattern_pg(iter)) != NULL) {
3159 		if (pg_target_check(cpg, iter->pgi_level) == 0)
3160 			continue;
3161 
3162 		/* See if we have a name match. */
3163 		for (i = 0; i < PGN_MAX; i++) {
3164 			if (strcmp(cpg->sc_pgroup_name, pg_names[i]) == 0) {
3165 				/*
3166 				 * If we already have a lower level
3167 				 * pg_pattern, keep it.
3168 				 */
3169 				if (pg_patterns[i] == NULL)
3170 					pg_patterns[i] = cpg;
3171 				break;
3172 			}
3173 		}
3174 	}
3175 
3176 	/* Find the most specific pg_pattern. */
3177 	for (i = 0; i < PGN_MAX; i++) {
3178 		if (pg_patterns[i] != NULL) {
3179 			*pgp = pg_patterns[i];
3180 			break;
3181 		}
3182 	}
3183 errout:
3184 	for (i = 0; i < PGN_MAX; i++) {
3185 		free(pg_names[i]);
3186 	}
3187 	pg_iter_destroy(iter);
3188 	return (rv);
3189 }
3190 
3191 /*
3192  * Initialize structures that are required for validation using
3193  * templates specifications.
3194  */
3195 void
3196 tmpl_init(void)
3197 {
3198 	emesg_nomem = gettext("Out of memory.\n");
3199 
3200 	composed_pg_pool = uu_avl_pool_create("composed_pg",
3201 	    sizeof (composed_pg_t), offsetof(composed_pg_t, cpg_node),
3202 	    composed_pg_compare, TMPL_DEBUG_AVL_POOL);
3203 	if (composed_pg_pool == NULL) {
3204 		uu_die(gettext("composed_pg pool creation failed: %s\n"),
3205 		    uu_strerror(uu_error()));
3206 	}
3207 	composed_prop_pool = uu_avl_pool_create("composed_prop",
3208 	    sizeof (property_t), offsetof(property_t, sc_composed_node),
3209 	    composed_prop_compare, TMPL_DEBUG_AVL_POOL);
3210 	if (composed_prop_pool == NULL) {
3211 		uu_die(gettext("composed_prop pool creation failed. %s\n"),
3212 		    uu_strerror(uu_error()));
3213 	}
3214 	ptrn_info_pool = uu_avl_pool_create("ptrn_info", sizeof (ptrn_info_t),
3215 	    offsetof(ptrn_info_t, pi_link), ptrn_info_compare,
3216 	    TMPL_DEBUG_AVL_POOL);
3217 	if (ptrn_info_pool == NULL) {
3218 		uu_die(gettext("pg_pattern info pool creation failed: %s\n"),
3219 		    uu_strerror(uu_error()));
3220 	}
3221 	inmem_errors_pool = uu_list_pool_create("errors-internal",
3222 	    sizeof (im_tmpl_error_t), offsetof(im_tmpl_error_t,
3223 	    ite_node), NULL, TMPL_DEBUG_LIST_POOL);
3224 	if (inmem_errors_pool == NULL) {
3225 		uu_die(gettext("inmem_errors_pool pool creation failed: "
3226 		    "%s\n"), uu_strerror(uu_error()));
3227 	}
3228 	tv_errors_pool = uu_list_pool_create("scf-terrors",
3229 	    sizeof (tv_errors_t), offsetof(tv_errors_t, tve_node),
3230 	    NULL,  TMPL_DEBUG_LIST_POOL);
3231 	if (tv_errors_pool == NULL) {
3232 		uu_die(gettext("tv_errors_pool pool creation failed: %s\n"),
3233 		    uu_strerror(uu_error()));
3234 	}
3235 }
3236 
3237 /*
3238  * Clean up the composed property node in the property.
3239  */
3240 void
3241 tmpl_property_fini(property_t *p)
3242 {
3243 	uu_avl_node_fini(p, &p->sc_composed_node, composed_prop_pool);
3244 }
3245 
3246 /*
3247  * Initialize the composed property node in the property.
3248  */
3249 void
3250 tmpl_property_init(property_t *p)
3251 {
3252 	uu_avl_node_init(p, &p->sc_composed_node, composed_prop_pool);
3253 }
3254 
3255 /*
3256  * Use the cardinality specification in the prop_pattern to verify the
3257  * cardinality of the property at prop.  The cardinality of the property is
3258  * the number of values that it has.
3259  *
3260  * pg is the property group that holds prop, and pg_pattern is the
3261  * pg_pattern for the property group.  pg and pg_pattern are only used for
3262  * error reporting.
3263  */
3264 static tmpl_validate_status_t
3265 tmpl_validate_cardinality(pgroup_t *prop_pattern, property_t *prop,
3266     pgroup_t *pg, pgroup_t *pg_pattern, tmpl_errors_t *errs)
3267 {
3268 	size_t count;
3269 	uint64_t max;
3270 	uint64_t min;
3271 	tmpl_validate_status_t rc;
3272 	error_info_t einfo;
3273 
3274 	assert(strcmp(prop_pattern->sc_pgroup_type,
3275 	    SCF_GROUP_TEMPLATE_PROP_PATTERN) == 0);
3276 
3277 	rc = get_cardinality(prop_pattern, &min, &max);
3278 	switch (rc) {
3279 	case TVS_NOMATCH:
3280 		/* Nothing to check. */
3281 		return (TVS_SUCCESS);
3282 	case TVS_SUCCESS:
3283 		/* Process the limits. */
3284 		break;
3285 	default:
3286 		return (rc);
3287 	}
3288 
3289 	if ((min == 0) && (max == ULLONG_MAX)) {
3290 		/* Any number of values is permitted.  No need to count. */
3291 		return (TVS_SUCCESS);
3292 	}
3293 
3294 	count = count_prop_values(prop);
3295 	if ((count < min) || (count > max)) {
3296 		CLEAR_ERROR_INFO(&einfo);
3297 		einfo.ei_type = EIT_CARDINALITY;
3298 		einfo.ei_u.ei_cardinality.ei_min = min;
3299 		einfo.ei_u.ei_cardinality.ei_max = max;
3300 		einfo.ei_u.ei_cardinality.ei_count = count;
3301 		(void) add_scf_error(errs, SCF_TERR_CARDINALITY_VIOLATION,
3302 		    pg_pattern, pg, prop_pattern, prop, NULL, &einfo);
3303 		return (TVS_VALIDATION);
3304 	}
3305 
3306 	return (TVS_SUCCESS);
3307 }
3308 
3309 /*
3310  * Iterate over pg_patterns in the entity, e.  If the pg_pattern's required
3311  * attribute is true, verify that the entity contains the corresponding
3312  * property group.
3313  */
3314 static tmpl_validate_status_t
3315 tmpl_required_pg_present(entity_t *e, tmpl_errors_t *errs)
3316 {
3317 	composed_pg_t cpg;
3318 	composed_pg_t *match;
3319 	error_info_t einfo;
3320 	pg_iter_t *iter;
3321 	pgroup_t *pg;
3322 	const char *pg_name;
3323 	const char *pg_type;
3324 	tmpl_validate_status_t rc = TVS_SUCCESS;
3325 	uu_avl_t *tree;
3326 
3327 	assert(e->sc_etype == SVCCFG_INSTANCE_OBJECT);
3328 
3329 	iter = pg_iter_create(e, SCF_GROUP_TEMPLATE_PG_PATTERN);
3330 	if (iter == NULL)
3331 		uu_die(emesg_nomem);
3332 
3333 	CLEAR_ERROR_INFO(&einfo);
3334 	einfo.ei_type = EIT_MISSING_PG;
3335 
3336 	while ((pg = next_pattern_pg(iter)) != NULL) {
3337 		if (is_required(pg) == 0) {
3338 			/* If pg is not required, there is nothing to check. */
3339 			continue;
3340 		}
3341 		pg_name = find_astring_value_in_pg(pg, SCF_PROPERTY_TM_NAME);
3342 		pg_type = find_astring_value_in_pg(pg, SCF_PROPERTY_TM_TYPE);
3343 		if (pg_target_check(pg, iter->pgi_level) == 0)
3344 			continue;
3345 		einfo.ei_u.ei_missing_pg.ei_pg_name = pg_name;
3346 		einfo.ei_u.ei_missing_pg.ei_pg_type = pg_type;
3347 		tree = e->sc_u.sc_instance.sc_composed;
3348 		(void) memset(&cpg, 0, sizeof (cpg));
3349 		cpg.cpg_name = pg_name;
3350 		cpg.cpg_type = pg_type;
3351 		match = uu_avl_find(tree, &cpg, NULL, NULL);
3352 		if (match == NULL) {
3353 			rc = TVS_VALIDATION;
3354 			if (add_scf_error(errs, SCF_TERR_MISSING_PG, pg,
3355 			    NULL, NULL, NULL, NULL, &einfo) != 0) {
3356 				break;
3357 			}
3358 		}
3359 	}
3360 
3361 	pg_iter_destroy(iter);
3362 	return (rc);
3363 }
3364 
3365 /*
3366  * Verify that the property group, pg, contains property declarations for
3367  * all required properties.  Unfortunately, there is no direct way to find
3368  * the prop_patterns for a given property group.  Therefore, we need to
3369  * scan the entity at e looking for property groups with a type of
3370  * SCF_GROUP_TEMPLATE_PROP_PATTERN.  That is, we scan the entity looking
3371  * for all prop_patterns.  When we find a prop_pattern, we look at the
3372  * value of its pg_pattern property to see if it matches the name of the
3373  * pg_pattern.  If they match, this is a prop_pattern that is of interest
3374  * to us.
3375  *
3376  * When we find an interesting prop_pattern, we see if it's required
3377  * property is true.  If it is, we verify that the property group at pg
3378  * contains the specified property.
3379  */
3380 static tmpl_validate_status_t
3381 tmpl_required_props_present(entity_t *e, pgroup_t *pg, pgroup_t *pg_pattern,
3382     tmpl_errors_t *errs)
3383 {
3384 	error_info_t einfo;
3385 	pg_iter_t *iter;
3386 	const char *prop_name;
3387 	const char *prop_pg_pattern_name;
3388 	pgroup_t *prop_pattern;
3389 	scf_tmpl_error_type_t ec;
3390 	tmpl_validate_status_t rc = TVS_SUCCESS;
3391 
3392 	/*
3393 	 * Scan the entity's property groups looking for ones with a type
3394 	 * of SCF_GROUP_TEMPLATE_PROP_PATTERN.
3395 	 */
3396 	iter = pg_iter_create(e, SCF_GROUP_TEMPLATE_PROP_PATTERN);
3397 	if (iter == NULL)
3398 		uu_die(emesg_nomem);
3399 	CLEAR_ERROR_INFO(&einfo);
3400 	for (prop_pattern = next_pattern_pg(iter);
3401 	    prop_pattern != NULL;
3402 	    prop_pattern = next_pattern_pg(iter)) {
3403 		/*
3404 		 * Find the pg_pattern property in this prop_pattern.
3405 		 * Verify that its value matches the name of the
3406 		 * pg_pattern.
3407 		 */
3408 		prop_pg_pattern_name = find_astring_value_in_pg(prop_pattern,
3409 		    SCF_PROPERTY_TM_PG_PATTERN);
3410 		assert(prop_pg_pattern_name != NULL);
3411 		if (strcmp(pg_pattern->sc_pgroup_name,
3412 		    prop_pg_pattern_name) != 0) {
3413 			continue;
3414 		}
3415 
3416 		/* If the property is required, see if it is in the pg. */
3417 		if (is_required(prop_pattern) == 0)
3418 			continue;
3419 		prop_name = find_astring_value_in_pg(prop_pattern,
3420 		    SCF_PROPERTY_TM_NAME);
3421 		assert(prop_name != NULL);
3422 		if (property_find(pg, prop_name) == NULL) {
3423 			ec = SCF_TERR_MISSING_PROP;
3424 			rc = TVS_VALIDATION;
3425 			einfo.ei_type = EIT_MISSING_PROP;
3426 			einfo.ei_u.ei_missing_prop.ei_prop_name = prop_name;
3427 			if (add_scf_error(errs, ec, pg_pattern, pg,
3428 			    prop_pattern, NULL, NULL, &einfo) != 0) {
3429 				/*
3430 				 * If we can no longer accumulate errors,
3431 				 * break out of the loop.
3432 				 */
3433 				break;
3434 			}
3435 		}
3436 	}
3437 
3438 	pg_iter_destroy(iter);
3439 	return (rc);
3440 }
3441 
3442 /*
3443  * Check the value at v to see if it falls within any of the ranges at r.
3444  * count is the number of ranges at r, and type tells whether to treat the
3445  * value as signed or unsigned.
3446  *
3447  * Return 1 if the value falls within one of the ranges.  Otherwise return
3448  * 0.
3449  */
3450 static int
3451 value_in_range(value_t *v, scf_type_t type, range_t *r, size_t count)
3452 {
3453 	for (; count > 0; --count, r++) {
3454 		if (type == SCF_TYPE_COUNT) {
3455 			if ((v->sc_u.sc_count >=
3456 			    r->rng_u.rng_unsigned.rng_min) &&
3457 			    (v->sc_u.sc_count <=
3458 			    r->rng_u.rng_unsigned.rng_max))
3459 				return (1);
3460 		} else {
3461 			if ((v->sc_u.sc_integer >=
3462 			    r->rng_u.rng_signed.rng_min) &&
3463 			    (v->sc_u.sc_integer <=
3464 			    r->rng_u.rng_signed.rng_max))
3465 				return (1);
3466 		}
3467 	}
3468 	return (0);
3469 }
3470 
3471 /*
3472  * If the template prop_pattern at pattern contains a constraint_range
3473  * property, use the specified range to validate all the numeric property
3474  * values of the property at prop.
3475  *
3476  * pg is the property group that holds prop, and pg_pattern is the
3477  * pg_pattern for the property group.  pg and pg_pattern are only used for
3478  * error reporting.
3479  */
3480 static tmpl_validate_status_t
3481 tmpl_validate_value_range(pgroup_t *pattern, property_t *prop, pgroup_t *pg,
3482     pgroup_t *pg_pattern, tmpl_errors_t *errs)
3483 {
3484 	uint_t count;
3485 	error_info_t einfo;
3486 	property_t *range_prop;
3487 	range_t *ranges;
3488 	tmpl_validate_status_t rc;
3489 	scf_type_t type;
3490 	value_t *v;
3491 
3492 	/* Get the range constraints if they exist. */
3493 	if ((range_prop = property_find(pattern,
3494 	    SCF_PROPERTY_TM_CONSTRAINT_RANGE)) == NULL) {
3495 		/* No range to check. */
3496 		return (TVS_SUCCESS);
3497 	}
3498 	type = prop->sc_value_type;
3499 	if ((type != SCF_TYPE_COUNT) && (type != SCF_TYPE_INTEGER)) {
3500 		rc = TVS_BAD_TEMPLATE;
3501 		CLEAR_ERROR_INFO(&einfo);
3502 		einfo.ei_type = EIT_BAD_TEMPLATE;
3503 		einfo.ei_u.ei_bad_template.ei_reason =
3504 		    gettext("Property does not have correct type for "
3505 		    "a range specification");
3506 		(void) tmpl_errors_add_im(errs, rc, pg_pattern->sc_parent,
3507 		    pg_pattern, pg, pattern, prop, NULL, &einfo);
3508 		return (rc);
3509 	}
3510 	if ((rc = get_ranges(range_prop, prop->sc_value_type, &ranges,
3511 	    &count)) != TVS_SUCCESS) {
3512 		rc = TVS_BAD_TEMPLATE;
3513 		CLEAR_ERROR_INFO(&einfo);
3514 		einfo.ei_type = EIT_BAD_TEMPLATE;
3515 		einfo.ei_u.ei_bad_template.ei_reason = gettext("Illegal range "
3516 		    "value");
3517 		(void) tmpl_errors_add_im(errs, rc, pg_pattern->sc_parent,
3518 		    pg_pattern, pg, pattern, prop, NULL, &einfo);
3519 		return (rc);
3520 	}
3521 
3522 	/* Set up error info before entering loop. */
3523 	CLEAR_ERROR_INFO(&einfo);
3524 	einfo.ei_type = EIT_RANGE;
3525 	einfo.ei_u.ei_range.ei_rtype = type;
3526 
3527 	/* Compare numeric values of the property to the range. */
3528 	for (v = uu_list_first(prop->sc_property_values);
3529 	    v != NULL;
3530 	    v = uu_list_next(prop->sc_property_values, v)) {
3531 		if (value_in_range(v, type, ranges, count) == 1)
3532 			continue;
3533 		if (type == SCF_TYPE_COUNT) {
3534 			einfo.ei_u.ei_range.ei_uvalue = v->sc_u.sc_count;
3535 		} else {
3536 			einfo.ei_u.ei_range.ei_ivalue = v->sc_u.sc_integer;
3537 		}
3538 		rc = TVS_VALIDATION;
3539 		if (add_scf_error(errs, SCF_TERR_RANGE_VIOLATION, pg_pattern,
3540 		    pg, pattern, prop, v, &einfo) != 0) {
3541 			return (rc);
3542 		}
3543 	}
3544 
3545 	return (rc);
3546 }
3547 
3548 /*
3549  * If the prop_pattern has value constraints, verify that all the values
3550  * for the property at prop are legal values.
3551  *
3552  * pg is the property group that holds prop, and pg_pattern is the
3553  * pg_pattern for the property group.  pg and pg_pattern are only used for
3554  * error reporting.
3555  */
3556 static tmpl_validate_status_t
3557 tmpl_validate_values(pgroup_t *prop_pattern, property_t *prop, pgroup_t *pg,
3558     pgroup_t *pg_pattern, tmpl_errors_t *errs)
3559 {
3560 	int found;
3561 	uint_t i;
3562 	avalues_t *legal;
3563 	tmpl_validate_status_t r;
3564 	tmpl_validate_status_t rc = TVS_SUCCESS;
3565 	value_t *v;
3566 
3567 	/* Get list of legal values. */
3568 	r = av_get_values(prop_pattern, SCF_PROPERTY_TM_CONSTRAINT_NAME,
3569 	    prop->sc_value_type, &legal);
3570 	switch (r) {
3571 	case TVS_BAD_CONVERSION:
3572 		(void) tmpl_errors_add_im(errs, r, pg->sc_parent, pg_pattern,
3573 		    pg, prop_pattern, prop, NULL, NULL);
3574 		return (r);
3575 	case TVS_NOMATCH:
3576 		/* No constraints in template. */
3577 		return (TVS_SUCCESS);
3578 	case TVS_SUCCESS:
3579 		/* process the constraints. */
3580 		break;
3581 	default:
3582 		assert(0);
3583 		abort();
3584 	}
3585 
3586 	/* Check the property values against the legal values. */
3587 	for (v = uu_list_first(prop->sc_property_values);
3588 	    v != NULL;
3589 	    v = uu_list_next(prop->sc_property_values, v)) {
3590 		/* Check this property value against the legal values. */
3591 		found = 0;
3592 		for (i = 0; (i < legal->av_count) && (found == 0); i++) {
3593 			switch (v->sc_type) {
3594 			case SCF_TYPE_BOOLEAN:
3595 			case SCF_TYPE_COUNT:
3596 				if (av_get_unsigned(legal, i) ==
3597 				    v->sc_u.sc_count) {
3598 					found = 1;
3599 				}
3600 				break;
3601 			case SCF_TYPE_INTEGER:
3602 				if (av_get_integer(legal, i) ==
3603 				    v->sc_u.sc_integer) {
3604 					found = 1;
3605 				}
3606 				break;
3607 			default:
3608 				if (strcmp(av_get_string(legal, i),
3609 				    v->sc_u.sc_string) == 0) {
3610 					found = 1;
3611 				}
3612 				break;
3613 			}
3614 		}
3615 		if (found == 0) {
3616 			rc = TVS_VALIDATION;
3617 			if (add_scf_error(errs,
3618 			    SCF_TERR_VALUE_CONSTRAINT_VIOLATED, pg_pattern, pg,
3619 			    prop_pattern, prop, v, NULL) != 0) {
3620 				/*
3621 				 * Exit loop if no longer able to report
3622 				 * errors.
3623 				 */
3624 				break;
3625 			}
3626 		}
3627 	}
3628 
3629 out:
3630 	av_destroy(legal);
3631 	return (rc);
3632 }
3633 
3634 /*
3635  * Verify the following items about the values of property, prop.
3636  *
3637  *	- The values all have the type specified by the prop_pattern at
3638  *	  pattern.
3639  *	- Check numeric values against range constraints.
3640  *	- If the prop_pattern has one or more value constraints, validate
3641  *	  the property's values against the constraints.
3642  *
3643  * pg is the property group that holds prop, and pg_pattern is the
3644  * pg_pattern for the property group.  pg and pg_pattern are only used for
3645  * error reporting.
3646  */
3647 static tmpl_validate_status_t
3648 tmpl_validate_value_constraints(pgroup_t *pattern, property_t *prop,
3649     pgroup_t *pg, pgroup_t *pg_pattern, tmpl_errors_t *errs)
3650 {
3651 	tmpl_validate_status_t r;
3652 	tmpl_validate_status_t rc;
3653 
3654 	rc = tmpl_validate_value_range(pattern, prop, pg, pg_pattern, errs);
3655 	r = tmpl_validate_values(pattern, prop, pg, pg_pattern, errs);
3656 	if (r != TVS_SUCCESS)
3657 		rc = r;
3658 
3659 	return (rc);
3660 }
3661 
3662 /*
3663  * Perform the following validations on the property, prop.
3664  *
3665  *	- Verify that the property's type agrees with the type specified in
3666  *	  the prop_pattern template, tmpl.
3667  *	- Verify the cardinality.
3668  *	- Verify that the property values satisfy the constraints specified
3669  *	  by the template.
3670  *
3671  * pg is the property group that holds prop, and pg_pattern is the
3672  * pg_pattern for the property group.  pg and pg_pattern are only used for
3673  * error reporting.
3674  */
3675 static tmpl_validate_status_t
3676 tmpl_validate_prop(property_t *prop, pgroup_t *tmpl, pgroup_t *pg,
3677     pgroup_t *pg_pattern, tmpl_errors_t *errs)
3678 {
3679 	scf_tmpl_error_type_t ec;
3680 	error_info_t einfo;
3681 	tmpl_validate_status_t r;
3682 	tmpl_validate_status_t rc = TVS_SUCCESS;
3683 	int status;
3684 	scf_type_t type;
3685 
3686 	r = prop_pattern_type(tmpl, &type);
3687 	switch (r) {
3688 	case TVS_SUCCESS:
3689 		if (type == SCF_TYPE_INVALID) {
3690 			rc = TVS_INVALID_TYPE_SPECIFICATION;
3691 			r = tmpl_errors_add_im(errs, rc, pg->sc_parent, NULL,
3692 			    pg, tmpl, NULL, NULL, NULL);
3693 			if (r != TVS_SUCCESS) {
3694 				/*
3695 				 * Give up if we can no longer accumulate
3696 				 * errors.
3697 				 */
3698 				return (rc);
3699 			}
3700 		} else {
3701 			if (property_is_type(prop, type) == 0) {
3702 				CLEAR_ERROR_INFO(&einfo);
3703 				rc = TVS_VALIDATION;
3704 				ec = SCF_TERR_WRONG_PROP_TYPE;
3705 				einfo.ei_type  = EIT_PROP_TYPE;
3706 				einfo.ei_u.ei_prop_type.ei_specified = type;
3707 				einfo.ei_u.ei_prop_type.ei_actual =
3708 				    prop->sc_value_type;
3709 				status = add_scf_error(errs, ec,
3710 				    pg_pattern, pg, tmpl, prop, NULL, &einfo);
3711 				if (status != 0) {
3712 					/*
3713 					 * Give up if we can no longer
3714 					 * accumulate errors.
3715 					 */
3716 					return (rc);
3717 				}
3718 			}
3719 		}
3720 		break;
3721 	case TVS_MISSING_TYPE_SPECIFICATION:
3722 		/*
3723 		 * A null type specification means that we do not need to
3724 		 * check the property's type.
3725 		 */
3726 		break;
3727 	default:
3728 		rc = r;
3729 	}
3730 
3731 	/* Validate the cardinality */
3732 	r = tmpl_validate_cardinality(tmpl, prop, pg, pg_pattern, errs);
3733 	if (r != TVS_SUCCESS)
3734 		rc = r;
3735 
3736 	/* Validate that property values satisfy constraints. */
3737 	r = tmpl_validate_value_constraints(tmpl, prop, pg, pg_pattern, errs);
3738 	if (r != TVS_SUCCESS)
3739 		rc = r;
3740 
3741 	return (rc);
3742 }
3743 
3744 /*
3745  * Validate the property group at pg by performing the following checks:
3746  *
3747  *	- Verify that the types of the pg and the pg_pattern are
3748  *	  compatible.
3749  *	- Verify the properties in the pg.
3750  *	- Verify that required properties are present.
3751  */
3752 static tmpl_validate_status_t
3753 tmpl_validate_pg(entity_t *e, pgroup_t *pg, tmpl_errors_t *errs)
3754 {
3755 	error_info_t einfo;
3756 	const char *pg_pattern_type;	/* Type declared by pg_pattern. */
3757 	pgroup_t *pg_pattern;	/* Prop. group for pg_pattern */
3758 	property_t *prop;
3759 	pgroup_t *prop_pattern;
3760 	tmpl_validate_status_t r;
3761 	tmpl_validate_status_t rc = TVS_SUCCESS;
3762 	int stat;
3763 
3764 	/*
3765 	 * See if there is a pg_pattern for this property group.  If it
3766 	 * exists, use it to validate the property group.  If there is no
3767 	 * pg_pattern, then there is no validation to do.
3768 	 */
3769 	rc = tmpl_find_pg_pattern(e, pg, &pg_pattern);
3770 	switch (rc) {
3771 	case TVS_SUCCESS:
3772 		break;
3773 	case TVS_BAD_TEMPLATE:
3774 		CLEAR_ERROR_INFO(&einfo);
3775 		einfo.ei_type = EIT_BAD_TEMPLATE;
3776 		einfo.ei_u.ei_bad_template.ei_reason = gettext("Property "
3777 		    "group name too long");
3778 		(void) tmpl_errors_add_im(errs, rc, e, NULL, pg, NULL, NULL,
3779 		    NULL, &einfo);
3780 		return (rc);
3781 	default:
3782 		assert(0);
3783 		abort();
3784 	}
3785 	if (pg_pattern == NULL)
3786 		return (TVS_SUCCESS);
3787 
3788 	/*
3789 	 * If the pg_pattern declares a type, verify that the PG has the
3790 	 * correct type.
3791 	 */
3792 	pg_pattern_type = find_type_specification(pg_pattern);
3793 	if ((pg_pattern_type != NULL) &&
3794 	    (*pg_pattern_type != 0)) {
3795 		if ((pg->sc_pgroup_type != NULL) &&
3796 		    (*(pg->sc_pgroup_type) != 0)) {
3797 			if (strcmp(pg_pattern_type,
3798 			    pg->sc_pgroup_type) != 0) {
3799 				rc = TVS_VALIDATION;
3800 				stat = add_scf_error(errs,
3801 				    SCF_TERR_WRONG_PG_TYPE, pg_pattern, pg,
3802 				    NULL, NULL, NULL, NULL);
3803 				if (stat != 0) {
3804 					/*
3805 					 * If we can no longer accumulate
3806 					 * errors, return without trying to
3807 					 * do further validation.
3808 					 */
3809 					return (rc);
3810 				}
3811 			}
3812 		} else {
3813 			rc = TVS_MISSING_PG_TYPE;
3814 			r = tmpl_errors_add_im(errs, rc, e, pg_pattern, pg,
3815 			    NULL, NULL, NULL, NULL);
3816 			if (r != TVS_SUCCESS) {
3817 				/*
3818 				 * If we can no longer accumulate errors,
3819 				 * return without trying to do further
3820 				 * validation.
3821 				 */
3822 				return (rc);
3823 			}
3824 		}
3825 	}
3826 
3827 	/* Verify the properties in the property group. */
3828 	prop = NULL;
3829 	while ((prop = next_property(pg, prop)) != NULL) {
3830 		r = tmpl_find_prop_pattern(e, pg_pattern, prop, &prop_pattern);
3831 		switch (r) {
3832 		case TVS_SUCCESS:
3833 			/* Found match.  Validate property. */
3834 			break;
3835 		case TVS_NOMATCH:
3836 			/* No prop_patern.  Go on to next property. */
3837 			continue;
3838 		case TVS_BAD_TEMPLATE:
3839 			CLEAR_ERROR_INFO(&einfo);
3840 			einfo.ei_type = EIT_BAD_TEMPLATE;
3841 			einfo.ei_u.ei_bad_template.ei_reason =
3842 			    gettext("prop_pattern name too long");
3843 			(void) tmpl_errors_add_im(errs, r, e, NULL, pg, NULL,
3844 			    NULL, NULL, &einfo);
3845 			continue;
3846 		default:
3847 			assert(0);
3848 			abort();
3849 		}
3850 		r = tmpl_validate_prop(prop, prop_pattern, pg, pg_pattern,
3851 		    errs);
3852 		if (r != TVS_SUCCESS)
3853 			rc = r;
3854 	}
3855 
3856 	/*
3857 	 * Confirm required properties are present.
3858 	 */
3859 	r = tmpl_required_props_present(e, pg, pg_pattern, errs);
3860 	if (r != TVS_SUCCESS)
3861 		rc = r;
3862 
3863 	return (rc);
3864 }
3865 
3866 /*
3867  * Validate that the property groups in the entity conform to the template
3868  * specifications.  Specifically, this means do the following:
3869  *
3870  *	- Loop through the property groups in the entity skipping the ones
3871  *	  that are of type "template".
3872  *
3873  *	- For the PG search for the corresponding template_pg_pattern
3874  *	  property group.  It is possible that one may not exist.
3875  *
3876  *	- Verify that the PG is in conformance with the pg_pattern
3877  *	  specification if it exists.
3878  */
3879 static tmpl_validate_status_t
3880 tmpl_validate_entity_pgs(entity_t *e, tmpl_errors_t *errs)
3881 {
3882 	composed_pg_t *cpg;
3883 	uu_avl_t *pgroups;
3884 	pgroup_t *pg;
3885 	tmpl_validate_status_t r;
3886 	tmpl_validate_status_t rc = TVS_SUCCESS;
3887 
3888 	assert(e->sc_etype == SVCCFG_INSTANCE_OBJECT);
3889 
3890 	pgroups = e->sc_u.sc_instance.sc_composed;
3891 	for (cpg = uu_avl_first(pgroups);
3892 	    cpg != NULL;
3893 	    cpg = uu_avl_next(pgroups, cpg)) {
3894 		if (strcmp(cpg->cpg_type, SCF_GROUP_TEMPLATE) == 0)
3895 			continue;
3896 		pg = CPG2PG(cpg);
3897 		if ((r = tmpl_validate_pg(e, pg, errs)) != TVS_SUCCESS)
3898 			rc = r;
3899 	}
3900 
3901 	return (rc);
3902 }
3903 
3904 /*
3905  * Validate the instance, e, by performing the following checks:
3906  *
3907  *	- Verify template consistency.
3908  *
3909  *	- Validate each property group in the entity is in conformance
3910  *	  with the template specifications.
3911  *
3912  *	- Verify that all required property groups are present in the
3913  *	  entity.
3914  */
3915 static tmpl_validate_status_t
3916 tmpl_validate_instance(entity_t *e, tmpl_errors_t *errs)
3917 {
3918 	tmpl_validate_status_t r;
3919 	tmpl_validate_status_t rc = TVS_SUCCESS;
3920 	int status;
3921 	tv_errors_t *ste;
3922 
3923 	/* Prepare to collect errors for this instance. */
3924 	ste = tv_errors_create(e->sc_fmri);
3925 	status = uu_list_insert_after(errs->te_scf, errs->te_cur_scf, ste);
3926 	assert(status == 0);
3927 	errs->te_cur_scf = ste;
3928 
3929 	/* Verify template consistency */
3930 	rc = tmpl_consistency(e, errs);
3931 
3932 	/* Validate the property groups in the entity. */
3933 	r = tmpl_validate_entity_pgs(e, errs);
3934 	if (r != TVS_SUCCESS)
3935 		rc = r;
3936 
3937 	/* Verify that all required property groups are present. */
3938 	r = tmpl_required_pg_present(e, errs);
3939 	if (r != TVS_SUCCESS)
3940 		rc = r;
3941 
3942 	return (rc);
3943 }
3944 
3945 /*
3946  * First validate the instances of the service.
3947  */
3948 static tmpl_validate_status_t
3949 tmpl_validate_service(entity_t *svc, tmpl_errors_t *errs)
3950 {
3951 	entity_t *inst;
3952 	tmpl_validate_status_t r;
3953 	tmpl_validate_status_t rc = TVS_SUCCESS;
3954 
3955 	assert(svc->sc_etype == SVCCFG_SERVICE_OBJECT);
3956 
3957 	load_general_templates(svc);
3958 
3959 	/* Validate the service's instances. */
3960 	for (inst = uu_list_first(svc->sc_u.sc_service.sc_service_instances);
3961 	    inst != NULL;
3962 	    inst = uu_list_next(svc->sc_u.sc_service.sc_service_instances,
3963 	    inst)) {
3964 		load_instance_restarter(inst);
3965 		build_composed_instance(inst);
3966 		r = tmpl_validate_instance(inst, errs);
3967 		if (r != TVS_SUCCESS)
3968 			rc = r;
3969 		demolish_composed_instance(inst);
3970 	}
3971 
3972 	return (rc);
3973 }
3974 
3975 /*
3976  * Validate all services and instances in the bundle against their
3977  * templates.  If err_list is not NULL, a tmpl_errors structure will be
3978  * allocated and its address will be returned to err_list.  This structure
3979  * can be used to generate error messages.
3980  */
3981 tmpl_validate_status_t
3982 tmpl_validate_bundle(bundle_t *bndl, tmpl_errors_t **err_list)
3983 {
3984 	tmpl_errors_t *errs = NULL;
3985 	entity_t *svc;
3986 	tmpl_validate_status_t r;
3987 	tmpl_validate_status_t rc = TVS_SUCCESS;
3988 
3989 	if (err_list != NULL)
3990 		*err_list = NULL;
3991 	if (bndl->sc_bundle_type != SVCCFG_MANIFEST) {
3992 		semerr(gettext("Bundle is not a manifest.  Unable to validate "
3993 		    "against templates.\n"));
3994 		return (TVS_FATAL);
3995 	}
3996 
3997 	errs = tmpl_errors_create();
3998 	if (errs == NULL)
3999 		uu_die(emesg_nomem);
4000 
4001 	lscf_prep_hndl();		/* Initialize g_hndl */
4002 	if (load_init() != 0)
4003 		uu_die(emesg_nomem);
4004 
4005 	/*
4006 	 * We will process all services in the bundle, unless we get a
4007 	 * fatal error.  That way we can report all errors on all services
4008 	 * on a single run of svccfg.
4009 	 */
4010 	for (svc = uu_list_first(bndl->sc_bundle_services);
4011 	    svc != NULL;
4012 	    svc = uu_list_next(bndl->sc_bundle_services, svc)) {
4013 		if (svc->sc_etype != SVCCFG_SERVICE_OBJECT) {
4014 			semerr(gettext("Manifest for %s contains an object "
4015 			    "named \"%s\" that is not a service.\n"),
4016 			    bndl->sc_bundle_name, svc->sc_name);
4017 			tmpl_errors_destroy(errs);
4018 			load_fini();
4019 			return (TVS_FATAL);
4020 		}
4021 		if ((r = tmpl_validate_service(svc, errs)) != TVS_SUCCESS)
4022 			rc = r;
4023 		if (r == TVS_FATAL)
4024 			break;
4025 	}
4026 
4027 	if (err_list == NULL) {
4028 		tmpl_errors_destroy(errs);
4029 	} else {
4030 		*err_list = errs;
4031 	}
4032 
4033 	load_fini();
4034 
4035 	return (rc);
4036 }
4037