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