1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate 
27*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*7c478bd9Sstevel@tonic-gate 
29*7c478bd9Sstevel@tonic-gate #include <repcache_protocol.h>
30*7c478bd9Sstevel@tonic-gate #include "scf_type.h"
31*7c478bd9Sstevel@tonic-gate 
32*7c478bd9Sstevel@tonic-gate #include <errno.h>
33*7c478bd9Sstevel@tonic-gate #include <libgen.h>
34*7c478bd9Sstevel@tonic-gate #include <libscf_priv.h>
35*7c478bd9Sstevel@tonic-gate #include <stdlib.h>
36*7c478bd9Sstevel@tonic-gate #include <string.h>
37*7c478bd9Sstevel@tonic-gate 
38*7c478bd9Sstevel@tonic-gate #define	UTF8_TOP_N(n) \
39*7c478bd9Sstevel@tonic-gate 	(0xff ^ (0xff >> (n)))		/* top N bits set */
40*7c478bd9Sstevel@tonic-gate 
41*7c478bd9Sstevel@tonic-gate #define	UTF8_BOTTOM_N(n) \
42*7c478bd9Sstevel@tonic-gate 	((1 << (n)) - 1)		/* bottom N bits set */
43*7c478bd9Sstevel@tonic-gate 
44*7c478bd9Sstevel@tonic-gate /*
45*7c478bd9Sstevel@tonic-gate  * The first byte of an n-byte UTF8 encoded character looks like:
46*7c478bd9Sstevel@tonic-gate  *
47*7c478bd9Sstevel@tonic-gate  *	n	bits
48*7c478bd9Sstevel@tonic-gate  *
49*7c478bd9Sstevel@tonic-gate  *	1	0xxxxxxx
50*7c478bd9Sstevel@tonic-gate  *	2	110xxxxx
51*7c478bd9Sstevel@tonic-gate  *	3	1110xxxx
52*7c478bd9Sstevel@tonic-gate  *	4	11110xxx
53*7c478bd9Sstevel@tonic-gate  *	5	111110xx
54*7c478bd9Sstevel@tonic-gate  *	6	1111110x
55*7c478bd9Sstevel@tonic-gate  *
56*7c478bd9Sstevel@tonic-gate  * Continuation bytes are 01xxxxxx.
57*7c478bd9Sstevel@tonic-gate  */
58*7c478bd9Sstevel@tonic-gate 
59*7c478bd9Sstevel@tonic-gate #define	UTF8_MAX_BYTES	6
60*7c478bd9Sstevel@tonic-gate 
61*7c478bd9Sstevel@tonic-gate /*
62*7c478bd9Sstevel@tonic-gate  * number of bits in an n-byte UTF-8 encoding.  for multi-byte encodings,
63*7c478bd9Sstevel@tonic-gate  * You get (7 - n) bits in the first byte, and 6 bits for each additional byte.
64*7c478bd9Sstevel@tonic-gate  */
65*7c478bd9Sstevel@tonic-gate #define	UTF8_BITS(n)	/* 1 <= n <= 6 */			\
66*7c478bd9Sstevel@tonic-gate 	((n) == 1)? 7 :						\
67*7c478bd9Sstevel@tonic-gate 	(7 - (n) + 6 * ((n) - 1))
68*7c478bd9Sstevel@tonic-gate 
69*7c478bd9Sstevel@tonic-gate #define	UTF8_SINGLE_BYTE(c) \
70*7c478bd9Sstevel@tonic-gate 	(((c) & UTF8_TOP_N(1)) == 0)	/* 0xxxxxxx */
71*7c478bd9Sstevel@tonic-gate 
72*7c478bd9Sstevel@tonic-gate #define	UTF8_HEAD_CHECK(c, n)		/* 2 <= n <= 6 */		\
73*7c478bd9Sstevel@tonic-gate 	(((c) & UTF8_TOP_N((n) + 1)) == UTF8_TOP_N(n))
74*7c478bd9Sstevel@tonic-gate 
75*7c478bd9Sstevel@tonic-gate #define	UTF8_HEAD_VALUE(c, n)		/* 2 <= n <= 6 */		\
76*7c478bd9Sstevel@tonic-gate 	((c) & UTF8_BOTTOM_N(7 - (n)))	/* 'x' mask */
77*7c478bd9Sstevel@tonic-gate 
78*7c478bd9Sstevel@tonic-gate #define	UTF8_CONT_CHECK(c) \
79*7c478bd9Sstevel@tonic-gate 	(((c) & UTF8_TOP_N(2)) == UTF8_TOP_N(1))	/* 10xxxxxx */
80*7c478bd9Sstevel@tonic-gate 
81*7c478bd9Sstevel@tonic-gate /*
82*7c478bd9Sstevel@tonic-gate  * adds in the 6 new bits from a continuation byte
83*7c478bd9Sstevel@tonic-gate  */
84*7c478bd9Sstevel@tonic-gate #define	UTF8_VALUE_UPDATE(v, c) \
85*7c478bd9Sstevel@tonic-gate 	(((v) << 6) | ((c) & UTF8_BOTTOM_N(6)))
86*7c478bd9Sstevel@tonic-gate 
87*7c478bd9Sstevel@tonic-gate /*
88*7c478bd9Sstevel@tonic-gate  * URI components
89*7c478bd9Sstevel@tonic-gate  */
90*7c478bd9Sstevel@tonic-gate 
91*7c478bd9Sstevel@tonic-gate #define	URI_COMPONENT_COUNT	5
92*7c478bd9Sstevel@tonic-gate 
93*7c478bd9Sstevel@tonic-gate enum {
94*7c478bd9Sstevel@tonic-gate 	URI_SCHEME = 0x0,		/* URI scheme */
95*7c478bd9Sstevel@tonic-gate 	URI_AUTHORITY,			/* URI authority */
96*7c478bd9Sstevel@tonic-gate 	URI_PATH,			/* URI path */
97*7c478bd9Sstevel@tonic-gate 	URI_QUERY,			/* URI query */
98*7c478bd9Sstevel@tonic-gate 	URI_FRAGMENT			/* URI fragment  */
99*7c478bd9Sstevel@tonic-gate };
100*7c478bd9Sstevel@tonic-gate 
101*7c478bd9Sstevel@tonic-gate static int
102*7c478bd9Sstevel@tonic-gate valid_utf8(const char *str_arg)
103*7c478bd9Sstevel@tonic-gate {
104*7c478bd9Sstevel@tonic-gate 	const char *str = str_arg;
105*7c478bd9Sstevel@tonic-gate 	uint_t c;
106*7c478bd9Sstevel@tonic-gate 	uint32_t v;
107*7c478bd9Sstevel@tonic-gate 	int i, n;
108*7c478bd9Sstevel@tonic-gate 
109*7c478bd9Sstevel@tonic-gate 	while ((c = *str++) != 0) {
110*7c478bd9Sstevel@tonic-gate 		if (UTF8_SINGLE_BYTE(c))
111*7c478bd9Sstevel@tonic-gate 			continue;	/* ascii */
112*7c478bd9Sstevel@tonic-gate 
113*7c478bd9Sstevel@tonic-gate 		for (n = 2; n <= UTF8_MAX_BYTES; n++)
114*7c478bd9Sstevel@tonic-gate 			if (UTF8_HEAD_CHECK(c, n))
115*7c478bd9Sstevel@tonic-gate 				break;
116*7c478bd9Sstevel@tonic-gate 
117*7c478bd9Sstevel@tonic-gate 		if (n > UTF8_MAX_BYTES)
118*7c478bd9Sstevel@tonic-gate 			return (0);		/* invalid head byte */
119*7c478bd9Sstevel@tonic-gate 
120*7c478bd9Sstevel@tonic-gate 		v = UTF8_HEAD_VALUE(c, n);
121*7c478bd9Sstevel@tonic-gate 
122*7c478bd9Sstevel@tonic-gate 		for (i = 1; i < n; i++) {
123*7c478bd9Sstevel@tonic-gate 			c = *str++;
124*7c478bd9Sstevel@tonic-gate 			if (!UTF8_CONT_CHECK(c))
125*7c478bd9Sstevel@tonic-gate 				return (0);	/* invalid byte */
126*7c478bd9Sstevel@tonic-gate 
127*7c478bd9Sstevel@tonic-gate 			v = UTF8_VALUE_UPDATE(v, c);
128*7c478bd9Sstevel@tonic-gate 		}
129*7c478bd9Sstevel@tonic-gate 
130*7c478bd9Sstevel@tonic-gate 		/*
131*7c478bd9Sstevel@tonic-gate 		 * if v could have been encoded in the next smallest
132*7c478bd9Sstevel@tonic-gate 		 * encoding, the string is not well-formed UTF-8.
133*7c478bd9Sstevel@tonic-gate 		 */
134*7c478bd9Sstevel@tonic-gate 		if ((v >> (UTF8_BITS(n - 1))) == 0)
135*7c478bd9Sstevel@tonic-gate 			return (0);
136*7c478bd9Sstevel@tonic-gate 	}
137*7c478bd9Sstevel@tonic-gate 
138*7c478bd9Sstevel@tonic-gate 	/*
139*7c478bd9Sstevel@tonic-gate 	 * we've reached the end of the string -- make sure it is short enough
140*7c478bd9Sstevel@tonic-gate 	 */
141*7c478bd9Sstevel@tonic-gate 	return ((str - str_arg) < REP_PROTOCOL_VALUE_LEN);
142*7c478bd9Sstevel@tonic-gate }
143*7c478bd9Sstevel@tonic-gate 
144*7c478bd9Sstevel@tonic-gate static int
145*7c478bd9Sstevel@tonic-gate valid_string(const char *str)
146*7c478bd9Sstevel@tonic-gate {
147*7c478bd9Sstevel@tonic-gate 	return (strlen(str) < REP_PROTOCOL_VALUE_LEN);
148*7c478bd9Sstevel@tonic-gate }
149*7c478bd9Sstevel@tonic-gate 
150*7c478bd9Sstevel@tonic-gate static int
151*7c478bd9Sstevel@tonic-gate valid_opaque(const char *str_arg)
152*7c478bd9Sstevel@tonic-gate {
153*7c478bd9Sstevel@tonic-gate 	const char *str = str_arg;
154*7c478bd9Sstevel@tonic-gate 	uint_t c;
155*7c478bd9Sstevel@tonic-gate 	ptrdiff_t len;
156*7c478bd9Sstevel@tonic-gate 
157*7c478bd9Sstevel@tonic-gate 	while ((c = *str++) != 0)
158*7c478bd9Sstevel@tonic-gate 		if ((c < '0' || c > '9') && (c < 'a' || c > 'f') &&
159*7c478bd9Sstevel@tonic-gate 		    (c < 'A' || c > 'F'))
160*7c478bd9Sstevel@tonic-gate 			return (0);		/* not hex digit */
161*7c478bd9Sstevel@tonic-gate 
162*7c478bd9Sstevel@tonic-gate 	len = (str - str_arg) - 1;		/* not counting NIL byte */
163*7c478bd9Sstevel@tonic-gate 	return ((len % 2) == 0 && len / 2 < REP_PROTOCOL_VALUE_LEN);
164*7c478bd9Sstevel@tonic-gate }
165*7c478bd9Sstevel@tonic-gate 
166*7c478bd9Sstevel@tonic-gate /*
167*7c478bd9Sstevel@tonic-gate  * Return 1 if the supplied parameter is a conformant URI (as defined
168*7c478bd9Sstevel@tonic-gate  * by RFC 2396), 0 otherwise.
169*7c478bd9Sstevel@tonic-gate  */
170*7c478bd9Sstevel@tonic-gate static int
171*7c478bd9Sstevel@tonic-gate valid_uri(const char *str)
172*7c478bd9Sstevel@tonic-gate {
173*7c478bd9Sstevel@tonic-gate 	/*
174*7c478bd9Sstevel@tonic-gate 	 * URI Regular Expression. Compiled with regcmp(1).
175*7c478bd9Sstevel@tonic-gate 	 *
176*7c478bd9Sstevel@tonic-gate 	 * ^(([^:/?#]+:){0,1})$0(//([^/?#]*)$1){0,1}([^?#]*)$2
177*7c478bd9Sstevel@tonic-gate 	 * (?([^#]*)$3){0,1}(#(.*)$4){0,1}
178*7c478bd9Sstevel@tonic-gate 	 */
179*7c478bd9Sstevel@tonic-gate 	char exp[] = {
180*7c478bd9Sstevel@tonic-gate 		040, 074, 00, 060, 012, 0126, 05, 072, 057, 077, 043, 024,
181*7c478bd9Sstevel@tonic-gate 		072, 057, 00, 00, 01, 014, 00, 00, 060, 020, 024, 057,
182*7c478bd9Sstevel@tonic-gate 		024, 057, 074, 01, 0125, 04, 057, 077, 043, 014, 01, 01,
183*7c478bd9Sstevel@tonic-gate 		057, 01, 00, 01, 074, 02, 0125, 03, 077, 043, 014, 02,
184*7c478bd9Sstevel@tonic-gate 		02, 060, 014, 024, 077, 074, 03, 0125, 02, 043, 014, 03,
185*7c478bd9Sstevel@tonic-gate 		03, 057, 02, 00, 01, 060, 012, 024, 043, 074, 04, 021,
186*7c478bd9Sstevel@tonic-gate 		014, 04, 04, 057, 03, 00, 01, 064, 00,
187*7c478bd9Sstevel@tonic-gate 		0};
188*7c478bd9Sstevel@tonic-gate 	char uri[URI_COMPONENT_COUNT][REP_PROTOCOL_VALUE_LEN];
189*7c478bd9Sstevel@tonic-gate 
190*7c478bd9Sstevel@tonic-gate 	/*
191*7c478bd9Sstevel@tonic-gate 	 * If the string is too long, then the URI cannot be valid. Also,
192*7c478bd9Sstevel@tonic-gate 	 * this protects against buffer overflow attacks on the uri array.
193*7c478bd9Sstevel@tonic-gate 	 */
194*7c478bd9Sstevel@tonic-gate 	if (strlen(str) >= REP_PROTOCOL_VALUE_LEN)
195*7c478bd9Sstevel@tonic-gate 		return (0);
196*7c478bd9Sstevel@tonic-gate 
197*7c478bd9Sstevel@tonic-gate 	if (regex(exp, str, uri[URI_SCHEME], uri[URI_AUTHORITY], uri[URI_PATH],
198*7c478bd9Sstevel@tonic-gate 		uri[URI_QUERY], uri[URI_FRAGMENT]) == NULL) {
199*7c478bd9Sstevel@tonic-gate 		return (0);
200*7c478bd9Sstevel@tonic-gate 	}
201*7c478bd9Sstevel@tonic-gate 	/*
202*7c478bd9Sstevel@tonic-gate 	 * To be a valid URI, the length of the URI_PATH must not be zero
203*7c478bd9Sstevel@tonic-gate 	 */
204*7c478bd9Sstevel@tonic-gate 	if (strlen(uri[URI_PATH]) == 0) {
205*7c478bd9Sstevel@tonic-gate 		return (0);
206*7c478bd9Sstevel@tonic-gate 	}
207*7c478bd9Sstevel@tonic-gate 	return (1);
208*7c478bd9Sstevel@tonic-gate }
209*7c478bd9Sstevel@tonic-gate 
210*7c478bd9Sstevel@tonic-gate /*
211*7c478bd9Sstevel@tonic-gate  * Return 1 if the supplied parameter is a conformant fmri, 0
212*7c478bd9Sstevel@tonic-gate  * otherwise.
213*7c478bd9Sstevel@tonic-gate  */
214*7c478bd9Sstevel@tonic-gate static int
215*7c478bd9Sstevel@tonic-gate valid_fmri(const char *str)
216*7c478bd9Sstevel@tonic-gate {
217*7c478bd9Sstevel@tonic-gate 	int ret;
218*7c478bd9Sstevel@tonic-gate 	char fmri[REP_PROTOCOL_VALUE_LEN] = { 0 };
219*7c478bd9Sstevel@tonic-gate 
220*7c478bd9Sstevel@tonic-gate 	/*
221*7c478bd9Sstevel@tonic-gate 	 * Try to parse the fmri, if we can parse it then it
222*7c478bd9Sstevel@tonic-gate 	 * must be syntactically correct. Work on a copy of
223*7c478bd9Sstevel@tonic-gate 	 * the fmri since the parsing process can modify the
224*7c478bd9Sstevel@tonic-gate 	 * supplied string.
225*7c478bd9Sstevel@tonic-gate 	 */
226*7c478bd9Sstevel@tonic-gate 	if (strlcpy(fmri, str, sizeof (fmri)) >= sizeof (fmri))
227*7c478bd9Sstevel@tonic-gate 		return (0);
228*7c478bd9Sstevel@tonic-gate 
229*7c478bd9Sstevel@tonic-gate 	ret = ! scf_parse_fmri(fmri, NULL, NULL, NULL, NULL, NULL, NULL);
230*7c478bd9Sstevel@tonic-gate 
231*7c478bd9Sstevel@tonic-gate 	return (ret);
232*7c478bd9Sstevel@tonic-gate }
233*7c478bd9Sstevel@tonic-gate 
234*7c478bd9Sstevel@tonic-gate rep_protocol_value_type_t
235*7c478bd9Sstevel@tonic-gate scf_proto_underlying_type(rep_protocol_value_type_t t)
236*7c478bd9Sstevel@tonic-gate {
237*7c478bd9Sstevel@tonic-gate 	switch (t) {
238*7c478bd9Sstevel@tonic-gate 	case REP_PROTOCOL_TYPE_BOOLEAN:
239*7c478bd9Sstevel@tonic-gate 	case REP_PROTOCOL_TYPE_COUNT:
240*7c478bd9Sstevel@tonic-gate 	case REP_PROTOCOL_TYPE_INTEGER:
241*7c478bd9Sstevel@tonic-gate 	case REP_PROTOCOL_TYPE_TIME:
242*7c478bd9Sstevel@tonic-gate 	case REP_PROTOCOL_TYPE_STRING:
243*7c478bd9Sstevel@tonic-gate 	case REP_PROTOCOL_TYPE_OPAQUE:
244*7c478bd9Sstevel@tonic-gate 		return (t);
245*7c478bd9Sstevel@tonic-gate 
246*7c478bd9Sstevel@tonic-gate 	case REP_PROTOCOL_SUBTYPE_USTRING:
247*7c478bd9Sstevel@tonic-gate 		return (REP_PROTOCOL_TYPE_STRING);
248*7c478bd9Sstevel@tonic-gate 
249*7c478bd9Sstevel@tonic-gate 	case REP_PROTOCOL_SUBTYPE_URI:
250*7c478bd9Sstevel@tonic-gate 		return (REP_PROTOCOL_SUBTYPE_USTRING);
251*7c478bd9Sstevel@tonic-gate 	case REP_PROTOCOL_SUBTYPE_FMRI:
252*7c478bd9Sstevel@tonic-gate 		return (REP_PROTOCOL_SUBTYPE_URI);
253*7c478bd9Sstevel@tonic-gate 
254*7c478bd9Sstevel@tonic-gate 	case REP_PROTOCOL_SUBTYPE_HOST:
255*7c478bd9Sstevel@tonic-gate 		return (REP_PROTOCOL_SUBTYPE_USTRING);
256*7c478bd9Sstevel@tonic-gate 	case REP_PROTOCOL_SUBTYPE_HOSTNAME:
257*7c478bd9Sstevel@tonic-gate 		return (REP_PROTOCOL_SUBTYPE_HOST);
258*7c478bd9Sstevel@tonic-gate 	case REP_PROTOCOL_SUBTYPE_NETADDR_V4:
259*7c478bd9Sstevel@tonic-gate 		return (REP_PROTOCOL_SUBTYPE_HOST);
260*7c478bd9Sstevel@tonic-gate 	case REP_PROTOCOL_SUBTYPE_NETADDR_V6:
261*7c478bd9Sstevel@tonic-gate 		return (REP_PROTOCOL_SUBTYPE_HOST);
262*7c478bd9Sstevel@tonic-gate 
263*7c478bd9Sstevel@tonic-gate 	case REP_PROTOCOL_TYPE_INVALID:
264*7c478bd9Sstevel@tonic-gate 	default:
265*7c478bd9Sstevel@tonic-gate 		return (REP_PROTOCOL_TYPE_INVALID);
266*7c478bd9Sstevel@tonic-gate 	}
267*7c478bd9Sstevel@tonic-gate }
268*7c478bd9Sstevel@tonic-gate 
269*7c478bd9Sstevel@tonic-gate int
270*7c478bd9Sstevel@tonic-gate scf_is_compatible_type(rep_protocol_value_type_t base,
271*7c478bd9Sstevel@tonic-gate     rep_protocol_value_type_t new)
272*7c478bd9Sstevel@tonic-gate {
273*7c478bd9Sstevel@tonic-gate 	rep_protocol_value_type_t t, cur;
274*7c478bd9Sstevel@tonic-gate 
275*7c478bd9Sstevel@tonic-gate 	if (base == REP_PROTOCOL_TYPE_INVALID)
276*7c478bd9Sstevel@tonic-gate 		return (0);
277*7c478bd9Sstevel@tonic-gate 
278*7c478bd9Sstevel@tonic-gate 	if (base == new)
279*7c478bd9Sstevel@tonic-gate 		return (1);
280*7c478bd9Sstevel@tonic-gate 
281*7c478bd9Sstevel@tonic-gate 	for (t = new; t != (cur = scf_proto_underlying_type(t)); t = cur) {
282*7c478bd9Sstevel@tonic-gate 		if (cur == REP_PROTOCOL_TYPE_INVALID)
283*7c478bd9Sstevel@tonic-gate 			return (0);
284*7c478bd9Sstevel@tonic-gate 		if (cur == base)
285*7c478bd9Sstevel@tonic-gate 			return (1);		/* base is parent of new */
286*7c478bd9Sstevel@tonic-gate 	}
287*7c478bd9Sstevel@tonic-gate 	return (0);
288*7c478bd9Sstevel@tonic-gate }
289*7c478bd9Sstevel@tonic-gate 
290*7c478bd9Sstevel@tonic-gate static int
291*7c478bd9Sstevel@tonic-gate valid_encoded_value(rep_protocol_value_type_t t, const char *v)
292*7c478bd9Sstevel@tonic-gate {
293*7c478bd9Sstevel@tonic-gate 	char *p;
294*7c478bd9Sstevel@tonic-gate 	ulong_t ns;
295*7c478bd9Sstevel@tonic-gate 
296*7c478bd9Sstevel@tonic-gate 	switch (t) {
297*7c478bd9Sstevel@tonic-gate 	case REP_PROTOCOL_TYPE_BOOLEAN:
298*7c478bd9Sstevel@tonic-gate 		return ((*v == '0' || *v == '1') && v[1] == 0);
299*7c478bd9Sstevel@tonic-gate 
300*7c478bd9Sstevel@tonic-gate 	case REP_PROTOCOL_TYPE_COUNT:
301*7c478bd9Sstevel@tonic-gate 		errno = 0;
302*7c478bd9Sstevel@tonic-gate 		if (strtoull(v, &p, 10) != 0 && *v == '0')
303*7c478bd9Sstevel@tonic-gate 			return (0);
304*7c478bd9Sstevel@tonic-gate 		return (errno == 0 && p != v && *p == 0);
305*7c478bd9Sstevel@tonic-gate 
306*7c478bd9Sstevel@tonic-gate 	case REP_PROTOCOL_TYPE_INTEGER:
307*7c478bd9Sstevel@tonic-gate 		errno = 0;
308*7c478bd9Sstevel@tonic-gate 		if (strtoll(v, &p, 10) != 0 && *v == '0')
309*7c478bd9Sstevel@tonic-gate 			return (0);
310*7c478bd9Sstevel@tonic-gate 		return (errno == 0 && p != v && *p == 0);
311*7c478bd9Sstevel@tonic-gate 
312*7c478bd9Sstevel@tonic-gate 	case REP_PROTOCOL_TYPE_TIME:
313*7c478bd9Sstevel@tonic-gate 		errno = 0;
314*7c478bd9Sstevel@tonic-gate 		(void) strtoll(v, &p, 10);
315*7c478bd9Sstevel@tonic-gate 		if (errno != 0 || p == v || (*p != 0 && *p != '.'))
316*7c478bd9Sstevel@tonic-gate 			return (0);
317*7c478bd9Sstevel@tonic-gate 		if (*p == '.') {
318*7c478bd9Sstevel@tonic-gate 			v = p + 1;
319*7c478bd9Sstevel@tonic-gate 			errno = 0;
320*7c478bd9Sstevel@tonic-gate 			ns = strtoul(v, &p, 10);
321*7c478bd9Sstevel@tonic-gate 
322*7c478bd9Sstevel@tonic-gate 			/* must be exactly 9 digits */
323*7c478bd9Sstevel@tonic-gate 			if ((p - v) != 9 || errno != 0 || *p != 0)
324*7c478bd9Sstevel@tonic-gate 				return (0);
325*7c478bd9Sstevel@tonic-gate 			if (ns >= NANOSEC)
326*7c478bd9Sstevel@tonic-gate 				return (0);
327*7c478bd9Sstevel@tonic-gate 		}
328*7c478bd9Sstevel@tonic-gate 		return (1);
329*7c478bd9Sstevel@tonic-gate 
330*7c478bd9Sstevel@tonic-gate 	case REP_PROTOCOL_TYPE_STRING:
331*7c478bd9Sstevel@tonic-gate 		return (valid_string(v));
332*7c478bd9Sstevel@tonic-gate 
333*7c478bd9Sstevel@tonic-gate 	case REP_PROTOCOL_TYPE_OPAQUE:
334*7c478bd9Sstevel@tonic-gate 		return (valid_opaque(v));
335*7c478bd9Sstevel@tonic-gate 
336*7c478bd9Sstevel@tonic-gate 	/*
337*7c478bd9Sstevel@tonic-gate 	 * The remaining types are subtypes -- because of the way
338*7c478bd9Sstevel@tonic-gate 	 * scf_validate_encoded_value() works, we can rely on the fact
339*7c478bd9Sstevel@tonic-gate 	 * that v is a valid example of our base type.  We only have to
340*7c478bd9Sstevel@tonic-gate 	 * check our own additional restrictions.
341*7c478bd9Sstevel@tonic-gate 	 */
342*7c478bd9Sstevel@tonic-gate 	case REP_PROTOCOL_SUBTYPE_USTRING:
343*7c478bd9Sstevel@tonic-gate 		return (valid_utf8(v));
344*7c478bd9Sstevel@tonic-gate 
345*7c478bd9Sstevel@tonic-gate 	case REP_PROTOCOL_SUBTYPE_URI:
346*7c478bd9Sstevel@tonic-gate 		return (valid_uri(v));
347*7c478bd9Sstevel@tonic-gate 
348*7c478bd9Sstevel@tonic-gate 	case REP_PROTOCOL_SUBTYPE_FMRI:
349*7c478bd9Sstevel@tonic-gate 		return (valid_fmri(v));
350*7c478bd9Sstevel@tonic-gate 
351*7c478bd9Sstevel@tonic-gate 	case REP_PROTOCOL_SUBTYPE_HOST:
352*7c478bd9Sstevel@tonic-gate 		return (valid_encoded_value(REP_PROTOCOL_SUBTYPE_HOSTNAME, v) ||
353*7c478bd9Sstevel@tonic-gate 		    valid_encoded_value(REP_PROTOCOL_SUBTYPE_NETADDR_V4, v) ||
354*7c478bd9Sstevel@tonic-gate 		    valid_encoded_value(REP_PROTOCOL_SUBTYPE_NETADDR_V6, v));
355*7c478bd9Sstevel@tonic-gate 
356*7c478bd9Sstevel@tonic-gate 	case REP_PROTOCOL_SUBTYPE_HOSTNAME:
357*7c478bd9Sstevel@tonic-gate 		/* XXX check for valid hostname */
358*7c478bd9Sstevel@tonic-gate 		return (valid_utf8(v));
359*7c478bd9Sstevel@tonic-gate 
360*7c478bd9Sstevel@tonic-gate 	case REP_PROTOCOL_SUBTYPE_NETADDR_V4:
361*7c478bd9Sstevel@tonic-gate 	case REP_PROTOCOL_SUBTYPE_NETADDR_V6:
362*7c478bd9Sstevel@tonic-gate 		/* XXX check for valid netaddr */
363*7c478bd9Sstevel@tonic-gate 		return (valid_utf8(v));
364*7c478bd9Sstevel@tonic-gate 
365*7c478bd9Sstevel@tonic-gate 	case REP_PROTOCOL_TYPE_INVALID:
366*7c478bd9Sstevel@tonic-gate 	default:
367*7c478bd9Sstevel@tonic-gate 		return (0);
368*7c478bd9Sstevel@tonic-gate 	}
369*7c478bd9Sstevel@tonic-gate }
370*7c478bd9Sstevel@tonic-gate 
371*7c478bd9Sstevel@tonic-gate int
372*7c478bd9Sstevel@tonic-gate scf_validate_encoded_value(rep_protocol_value_type_t t, const char *v)
373*7c478bd9Sstevel@tonic-gate {
374*7c478bd9Sstevel@tonic-gate 	rep_protocol_value_type_t base, cur;
375*7c478bd9Sstevel@tonic-gate 
376*7c478bd9Sstevel@tonic-gate 	base = scf_proto_underlying_type(t);
377*7c478bd9Sstevel@tonic-gate 	while ((cur = scf_proto_underlying_type(base)) != base)
378*7c478bd9Sstevel@tonic-gate 		base = cur;
379*7c478bd9Sstevel@tonic-gate 
380*7c478bd9Sstevel@tonic-gate 	if (base != t && !valid_encoded_value(base, v))
381*7c478bd9Sstevel@tonic-gate 		return (0);
382*7c478bd9Sstevel@tonic-gate 
383*7c478bd9Sstevel@tonic-gate 	return (valid_encoded_value(t, v));
384*7c478bd9Sstevel@tonic-gate }
385