17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5a574db85Sraf  * Common Development and Distribution License (the "License").
6a574db85Sraf  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
21a574db85Sraf 
227c478bd9Sstevel@tonic-gate /*
23*870ad75aSSean Wilcox  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate #include <repcache_protocol.h>
287c478bd9Sstevel@tonic-gate #include "scf_type.h"
297c478bd9Sstevel@tonic-gate #include <errno.h>
307c478bd9Sstevel@tonic-gate #include <libgen.h>
317c478bd9Sstevel@tonic-gate #include <libscf_priv.h>
327c478bd9Sstevel@tonic-gate #include <stdlib.h>
337c478bd9Sstevel@tonic-gate #include <string.h>
347c478bd9Sstevel@tonic-gate 
357c478bd9Sstevel@tonic-gate #define	UTF8_TOP_N(n) \
367c478bd9Sstevel@tonic-gate 	(0xff ^ (0xff >> (n)))		/* top N bits set */
377c478bd9Sstevel@tonic-gate 
387c478bd9Sstevel@tonic-gate #define	UTF8_BOTTOM_N(n) \
397c478bd9Sstevel@tonic-gate 	((1 << (n)) - 1)		/* bottom N bits set */
407c478bd9Sstevel@tonic-gate 
417c478bd9Sstevel@tonic-gate /*
427c478bd9Sstevel@tonic-gate  * The first byte of an n-byte UTF8 encoded character looks like:
437c478bd9Sstevel@tonic-gate  *
447c478bd9Sstevel@tonic-gate  *	n	bits
457c478bd9Sstevel@tonic-gate  *
467c478bd9Sstevel@tonic-gate  *	1	0xxxxxxx
477c478bd9Sstevel@tonic-gate  *	2	110xxxxx
487c478bd9Sstevel@tonic-gate  *	3	1110xxxx
497c478bd9Sstevel@tonic-gate  *	4	11110xxx
507c478bd9Sstevel@tonic-gate  *	5	111110xx
517c478bd9Sstevel@tonic-gate  *	6	1111110x
527c478bd9Sstevel@tonic-gate  *
537c478bd9Sstevel@tonic-gate  * Continuation bytes are 01xxxxxx.
547c478bd9Sstevel@tonic-gate  */
557c478bd9Sstevel@tonic-gate 
567c478bd9Sstevel@tonic-gate #define	UTF8_MAX_BYTES	6
577c478bd9Sstevel@tonic-gate 
587c478bd9Sstevel@tonic-gate /*
597c478bd9Sstevel@tonic-gate  * number of bits in an n-byte UTF-8 encoding.  for multi-byte encodings,
607c478bd9Sstevel@tonic-gate  * You get (7 - n) bits in the first byte, and 6 bits for each additional byte.
617c478bd9Sstevel@tonic-gate  */
627c478bd9Sstevel@tonic-gate #define	UTF8_BITS(n)	/* 1 <= n <= 6 */			\
637c478bd9Sstevel@tonic-gate 	((n) == 1)? 7 :						\
647c478bd9Sstevel@tonic-gate 	(7 - (n) + 6 * ((n) - 1))
657c478bd9Sstevel@tonic-gate 
667c478bd9Sstevel@tonic-gate #define	UTF8_SINGLE_BYTE(c) \
677c478bd9Sstevel@tonic-gate 	(((c) & UTF8_TOP_N(1)) == 0)	/* 0xxxxxxx */
687c478bd9Sstevel@tonic-gate 
697c478bd9Sstevel@tonic-gate #define	UTF8_HEAD_CHECK(c, n)		/* 2 <= n <= 6 */		\
707c478bd9Sstevel@tonic-gate 	(((c) & UTF8_TOP_N((n) + 1)) == UTF8_TOP_N(n))
717c478bd9Sstevel@tonic-gate 
727c478bd9Sstevel@tonic-gate #define	UTF8_HEAD_VALUE(c, n)		/* 2 <= n <= 6 */		\
737c478bd9Sstevel@tonic-gate 	((c) & UTF8_BOTTOM_N(7 - (n)))	/* 'x' mask */
747c478bd9Sstevel@tonic-gate 
757c478bd9Sstevel@tonic-gate #define	UTF8_CONT_CHECK(c) \
767c478bd9Sstevel@tonic-gate 	(((c) & UTF8_TOP_N(2)) == UTF8_TOP_N(1))	/* 10xxxxxx */
777c478bd9Sstevel@tonic-gate 
787c478bd9Sstevel@tonic-gate /*
797c478bd9Sstevel@tonic-gate  * adds in the 6 new bits from a continuation byte
807c478bd9Sstevel@tonic-gate  */
817c478bd9Sstevel@tonic-gate #define	UTF8_VALUE_UPDATE(v, c) \
827c478bd9Sstevel@tonic-gate 	(((v) << 6) | ((c) & UTF8_BOTTOM_N(6)))
837c478bd9Sstevel@tonic-gate 
847c478bd9Sstevel@tonic-gate /*
857c478bd9Sstevel@tonic-gate  * URI components
867c478bd9Sstevel@tonic-gate  */
877c478bd9Sstevel@tonic-gate 
887c478bd9Sstevel@tonic-gate #define	URI_COMPONENT_COUNT	5
897c478bd9Sstevel@tonic-gate 
907c478bd9Sstevel@tonic-gate enum {
917c478bd9Sstevel@tonic-gate 	URI_SCHEME = 0x0,		/* URI scheme */
927c478bd9Sstevel@tonic-gate 	URI_AUTHORITY,			/* URI authority */
937c478bd9Sstevel@tonic-gate 	URI_PATH,			/* URI path */
947c478bd9Sstevel@tonic-gate 	URI_QUERY,			/* URI query */
957c478bd9Sstevel@tonic-gate 	URI_FRAGMENT			/* URI fragment  */
967c478bd9Sstevel@tonic-gate };
977c478bd9Sstevel@tonic-gate 
987c478bd9Sstevel@tonic-gate static int
997c478bd9Sstevel@tonic-gate valid_utf8(const char *str_arg)
1007c478bd9Sstevel@tonic-gate {
1017c478bd9Sstevel@tonic-gate 	const char *str = str_arg;
1027c478bd9Sstevel@tonic-gate 	uint_t c;
1037c478bd9Sstevel@tonic-gate 	uint32_t v;
1047c478bd9Sstevel@tonic-gate 	int i, n;
1057c478bd9Sstevel@tonic-gate 
1067c478bd9Sstevel@tonic-gate 	while ((c = *str++) != 0) {
1077c478bd9Sstevel@tonic-gate 		if (UTF8_SINGLE_BYTE(c))
1087c478bd9Sstevel@tonic-gate 			continue;	/* ascii */
1097c478bd9Sstevel@tonic-gate 
1107c478bd9Sstevel@tonic-gate 		for (n = 2; n <= UTF8_MAX_BYTES; n++)
1117c478bd9Sstevel@tonic-gate 			if (UTF8_HEAD_CHECK(c, n))
1127c478bd9Sstevel@tonic-gate 				break;
1137c478bd9Sstevel@tonic-gate 
1147c478bd9Sstevel@tonic-gate 		if (n > UTF8_MAX_BYTES)
1157c478bd9Sstevel@tonic-gate 			return (0);		/* invalid head byte */
1167c478bd9Sstevel@tonic-gate 
1177c478bd9Sstevel@tonic-gate 		v = UTF8_HEAD_VALUE(c, n);
1187c478bd9Sstevel@tonic-gate 
1197c478bd9Sstevel@tonic-gate 		for (i = 1; i < n; i++) {
1207c478bd9Sstevel@tonic-gate 			c = *str++;
1217c478bd9Sstevel@tonic-gate 			if (!UTF8_CONT_CHECK(c))
1227c478bd9Sstevel@tonic-gate 				return (0);	/* invalid byte */
1237c478bd9Sstevel@tonic-gate 
1247c478bd9Sstevel@tonic-gate 			v = UTF8_VALUE_UPDATE(v, c);
1257c478bd9Sstevel@tonic-gate 		}
1267c478bd9Sstevel@tonic-gate 
1277c478bd9Sstevel@tonic-gate 		/*
1287c478bd9Sstevel@tonic-gate 		 * if v could have been encoded in the next smallest
1297c478bd9Sstevel@tonic-gate 		 * encoding, the string is not well-formed UTF-8.
1307c478bd9Sstevel@tonic-gate 		 */
1317c478bd9Sstevel@tonic-gate 		if ((v >> (UTF8_BITS(n - 1))) == 0)
1327c478bd9Sstevel@tonic-gate 			return (0);
1337c478bd9Sstevel@tonic-gate 	}
1347c478bd9Sstevel@tonic-gate 
1357c478bd9Sstevel@tonic-gate 	/*
1367c478bd9Sstevel@tonic-gate 	 * we've reached the end of the string -- make sure it is short enough
1377c478bd9Sstevel@tonic-gate 	 */
1387c478bd9Sstevel@tonic-gate 	return ((str - str_arg) < REP_PROTOCOL_VALUE_LEN);
1397c478bd9Sstevel@tonic-gate }
1407c478bd9Sstevel@tonic-gate 
1417c478bd9Sstevel@tonic-gate static int
1427c478bd9Sstevel@tonic-gate valid_string(const char *str)
1437c478bd9Sstevel@tonic-gate {
1447c478bd9Sstevel@tonic-gate 	return (strlen(str) < REP_PROTOCOL_VALUE_LEN);
1457c478bd9Sstevel@tonic-gate }
1467c478bd9Sstevel@tonic-gate 
1477c478bd9Sstevel@tonic-gate static int
1487c478bd9Sstevel@tonic-gate valid_opaque(const char *str_arg)
1497c478bd9Sstevel@tonic-gate {
1507c478bd9Sstevel@tonic-gate 	const char *str = str_arg;
1517c478bd9Sstevel@tonic-gate 	uint_t c;
1527c478bd9Sstevel@tonic-gate 	ptrdiff_t len;
1537c478bd9Sstevel@tonic-gate 
1547c478bd9Sstevel@tonic-gate 	while ((c = *str++) != 0)
1557c478bd9Sstevel@tonic-gate 		if ((c < '0' || c > '9') && (c < 'a' || c > 'f') &&
1567c478bd9Sstevel@tonic-gate 		    (c < 'A' || c > 'F'))
1577c478bd9Sstevel@tonic-gate 			return (0);		/* not hex digit */
1587c478bd9Sstevel@tonic-gate 
1597c478bd9Sstevel@tonic-gate 	len = (str - str_arg) - 1;		/* not counting NIL byte */
1607c478bd9Sstevel@tonic-gate 	return ((len % 2) == 0 && len / 2 < REP_PROTOCOL_VALUE_LEN);
1617c478bd9Sstevel@tonic-gate }
1627c478bd9Sstevel@tonic-gate 
1637c478bd9Sstevel@tonic-gate /*
1647c478bd9Sstevel@tonic-gate  * Return 1 if the supplied parameter is a conformant URI (as defined
1657c478bd9Sstevel@tonic-gate  * by RFC 2396), 0 otherwise.
1667c478bd9Sstevel@tonic-gate  */
1677c478bd9Sstevel@tonic-gate static int
1687c478bd9Sstevel@tonic-gate valid_uri(const char *str)
1697c478bd9Sstevel@tonic-gate {
1707c478bd9Sstevel@tonic-gate 	/*
1717c478bd9Sstevel@tonic-gate 	 * URI Regular Expression. Compiled with regcmp(1).
1727c478bd9Sstevel@tonic-gate 	 *
1737c478bd9Sstevel@tonic-gate 	 * ^(([^:/?#]+:){0,1})$0(//([^/?#]*)$1){0,1}([^?#]*)$2
1747c478bd9Sstevel@tonic-gate 	 * (?([^#]*)$3){0,1}(#(.*)$4){0,1}
1757c478bd9Sstevel@tonic-gate 	 */
1767c478bd9Sstevel@tonic-gate 	char exp[] = {
1777c478bd9Sstevel@tonic-gate 		040, 074, 00, 060, 012, 0126, 05, 072, 057, 077, 043, 024,
1787c478bd9Sstevel@tonic-gate 		072, 057, 00, 00, 01, 014, 00, 00, 060, 020, 024, 057,
1797c478bd9Sstevel@tonic-gate 		024, 057, 074, 01, 0125, 04, 057, 077, 043, 014, 01, 01,
1807c478bd9Sstevel@tonic-gate 		057, 01, 00, 01, 074, 02, 0125, 03, 077, 043, 014, 02,
1817c478bd9Sstevel@tonic-gate 		02, 060, 014, 024, 077, 074, 03, 0125, 02, 043, 014, 03,
1827c478bd9Sstevel@tonic-gate 		03, 057, 02, 00, 01, 060, 012, 024, 043, 074, 04, 021,
1837c478bd9Sstevel@tonic-gate 		014, 04, 04, 057, 03, 00, 01, 064, 00,
1847c478bd9Sstevel@tonic-gate 		0};
1857c478bd9Sstevel@tonic-gate 	char uri[URI_COMPONENT_COUNT][REP_PROTOCOL_VALUE_LEN];
1867c478bd9Sstevel@tonic-gate 
1877c478bd9Sstevel@tonic-gate 	/*
1887c478bd9Sstevel@tonic-gate 	 * If the string is too long, then the URI cannot be valid. Also,
1897c478bd9Sstevel@tonic-gate 	 * this protects against buffer overflow attacks on the uri array.
1907c478bd9Sstevel@tonic-gate 	 */
1917c478bd9Sstevel@tonic-gate 	if (strlen(str) >= REP_PROTOCOL_VALUE_LEN)
1927c478bd9Sstevel@tonic-gate 		return (0);
1937c478bd9Sstevel@tonic-gate 
1947c478bd9Sstevel@tonic-gate 	if (regex(exp, str, uri[URI_SCHEME], uri[URI_AUTHORITY], uri[URI_PATH],
195a574db85Sraf 	    uri[URI_QUERY], uri[URI_FRAGMENT]) == NULL) {
1967c478bd9Sstevel@tonic-gate 		return (0);
1977c478bd9Sstevel@tonic-gate 	}
1987c478bd9Sstevel@tonic-gate 	/*
1997c478bd9Sstevel@tonic-gate 	 * To be a valid URI, the length of the URI_PATH must not be zero
2007c478bd9Sstevel@tonic-gate 	 */
2017c478bd9Sstevel@tonic-gate 	if (strlen(uri[URI_PATH]) == 0) {
2027c478bd9Sstevel@tonic-gate 		return (0);
2037c478bd9Sstevel@tonic-gate 	}
2047c478bd9Sstevel@tonic-gate 	return (1);
2057c478bd9Sstevel@tonic-gate }
2067c478bd9Sstevel@tonic-gate 
2077c478bd9Sstevel@tonic-gate /*
2087c478bd9Sstevel@tonic-gate  * Return 1 if the supplied parameter is a conformant fmri, 0
2097c478bd9Sstevel@tonic-gate  * otherwise.
2107c478bd9Sstevel@tonic-gate  */
2117c478bd9Sstevel@tonic-gate static int
2127c478bd9Sstevel@tonic-gate valid_fmri(const char *str)
2137c478bd9Sstevel@tonic-gate {
2147c478bd9Sstevel@tonic-gate 	int ret;
2157c478bd9Sstevel@tonic-gate 	char fmri[REP_PROTOCOL_VALUE_LEN] = { 0 };
2167c478bd9Sstevel@tonic-gate 
2177c478bd9Sstevel@tonic-gate 	/*
2187c478bd9Sstevel@tonic-gate 	 * Try to parse the fmri, if we can parse it then it
2197c478bd9Sstevel@tonic-gate 	 * must be syntactically correct. Work on a copy of
2207c478bd9Sstevel@tonic-gate 	 * the fmri since the parsing process can modify the
2217c478bd9Sstevel@tonic-gate 	 * supplied string.
2227c478bd9Sstevel@tonic-gate 	 */
2237c478bd9Sstevel@tonic-gate 	if (strlcpy(fmri, str, sizeof (fmri)) >= sizeof (fmri))
2247c478bd9Sstevel@tonic-gate 		return (0);
2257c478bd9Sstevel@tonic-gate 
2267c478bd9Sstevel@tonic-gate 	ret = ! scf_parse_fmri(fmri, NULL, NULL, NULL, NULL, NULL, NULL);
2277c478bd9Sstevel@tonic-gate 
2287c478bd9Sstevel@tonic-gate 	return (ret);
2297c478bd9Sstevel@tonic-gate }
2307c478bd9Sstevel@tonic-gate 
2317c478bd9Sstevel@tonic-gate rep_protocol_value_type_t
2327c478bd9Sstevel@tonic-gate scf_proto_underlying_type(rep_protocol_value_type_t t)
2337c478bd9Sstevel@tonic-gate {
2347c478bd9Sstevel@tonic-gate 	switch (t) {
2357c478bd9Sstevel@tonic-gate 	case REP_PROTOCOL_TYPE_BOOLEAN:
2367c478bd9Sstevel@tonic-gate 	case REP_PROTOCOL_TYPE_COUNT:
2377c478bd9Sstevel@tonic-gate 	case REP_PROTOCOL_TYPE_INTEGER:
2387c478bd9Sstevel@tonic-gate 	case REP_PROTOCOL_TYPE_TIME:
2397c478bd9Sstevel@tonic-gate 	case REP_PROTOCOL_TYPE_STRING:
2407c478bd9Sstevel@tonic-gate 	case REP_PROTOCOL_TYPE_OPAQUE:
2417c478bd9Sstevel@tonic-gate 		return (t);
2427c478bd9Sstevel@tonic-gate 
2437c478bd9Sstevel@tonic-gate 	case REP_PROTOCOL_SUBTYPE_USTRING:
2447c478bd9Sstevel@tonic-gate 		return (REP_PROTOCOL_TYPE_STRING);
2457c478bd9Sstevel@tonic-gate 
2467c478bd9Sstevel@tonic-gate 	case REP_PROTOCOL_SUBTYPE_URI:
2477c478bd9Sstevel@tonic-gate 		return (REP_PROTOCOL_SUBTYPE_USTRING);
2487c478bd9Sstevel@tonic-gate 	case REP_PROTOCOL_SUBTYPE_FMRI:
2497c478bd9Sstevel@tonic-gate 		return (REP_PROTOCOL_SUBTYPE_URI);
2507c478bd9Sstevel@tonic-gate 
2517c478bd9Sstevel@tonic-gate 	case REP_PROTOCOL_SUBTYPE_HOST:
2527c478bd9Sstevel@tonic-gate 		return (REP_PROTOCOL_SUBTYPE_USTRING);
2537c478bd9Sstevel@tonic-gate 	case REP_PROTOCOL_SUBTYPE_HOSTNAME:
2547c478bd9Sstevel@tonic-gate 		return (REP_PROTOCOL_SUBTYPE_HOST);
2557c478bd9Sstevel@tonic-gate 	case REP_PROTOCOL_SUBTYPE_NETADDR_V4:
2567c478bd9Sstevel@tonic-gate 		return (REP_PROTOCOL_SUBTYPE_HOST);
2577c478bd9Sstevel@tonic-gate 	case REP_PROTOCOL_SUBTYPE_NETADDR_V6:
2587c478bd9Sstevel@tonic-gate 		return (REP_PROTOCOL_SUBTYPE_HOST);
2597c478bd9Sstevel@tonic-gate 
2607c478bd9Sstevel@tonic-gate 	case REP_PROTOCOL_TYPE_INVALID:
2617c478bd9Sstevel@tonic-gate 	default:
2627c478bd9Sstevel@tonic-gate 		return (REP_PROTOCOL_TYPE_INVALID);
2637c478bd9Sstevel@tonic-gate 	}
2647c478bd9Sstevel@tonic-gate }
2657c478bd9Sstevel@tonic-gate 
2667c478bd9Sstevel@tonic-gate int
267*870ad75aSSean Wilcox scf_is_compatible_protocol_type(rep_protocol_value_type_t base,
2687c478bd9Sstevel@tonic-gate     rep_protocol_value_type_t new)
2697c478bd9Sstevel@tonic-gate {
2707c478bd9Sstevel@tonic-gate 	rep_protocol_value_type_t t, cur;
2717c478bd9Sstevel@tonic-gate 
2727c478bd9Sstevel@tonic-gate 	if (base == REP_PROTOCOL_TYPE_INVALID)
2737c478bd9Sstevel@tonic-gate 		return (0);
2747c478bd9Sstevel@tonic-gate 
2757c478bd9Sstevel@tonic-gate 	if (base == new)
2767c478bd9Sstevel@tonic-gate 		return (1);
2777c478bd9Sstevel@tonic-gate 
2787c478bd9Sstevel@tonic-gate 	for (t = new; t != (cur = scf_proto_underlying_type(t)); t = cur) {
2797c478bd9Sstevel@tonic-gate 		if (cur == REP_PROTOCOL_TYPE_INVALID)
2807c478bd9Sstevel@tonic-gate 			return (0);
2817c478bd9Sstevel@tonic-gate 		if (cur == base)
2827c478bd9Sstevel@tonic-gate 			return (1);		/* base is parent of new */
2837c478bd9Sstevel@tonic-gate 	}
2847c478bd9Sstevel@tonic-gate 	return (0);
2857c478bd9Sstevel@tonic-gate }
2867c478bd9Sstevel@tonic-gate 
2877c478bd9Sstevel@tonic-gate static int
2887c478bd9Sstevel@tonic-gate valid_encoded_value(rep_protocol_value_type_t t, const char *v)
2897c478bd9Sstevel@tonic-gate {
2907c478bd9Sstevel@tonic-gate 	char *p;
2917c478bd9Sstevel@tonic-gate 	ulong_t ns;
2927c478bd9Sstevel@tonic-gate 
2937c478bd9Sstevel@tonic-gate 	switch (t) {
2947c478bd9Sstevel@tonic-gate 	case REP_PROTOCOL_TYPE_BOOLEAN:
2957c478bd9Sstevel@tonic-gate 		return ((*v == '0' || *v == '1') && v[1] == 0);
2967c478bd9Sstevel@tonic-gate 
2977c478bd9Sstevel@tonic-gate 	case REP_PROTOCOL_TYPE_COUNT:
2987c478bd9Sstevel@tonic-gate 		errno = 0;
2997c478bd9Sstevel@tonic-gate 		if (strtoull(v, &p, 10) != 0 && *v == '0')
3007c478bd9Sstevel@tonic-gate 			return (0);
3017c478bd9Sstevel@tonic-gate 		return (errno == 0 && p != v && *p == 0);
3027c478bd9Sstevel@tonic-gate 
3037c478bd9Sstevel@tonic-gate 	case REP_PROTOCOL_TYPE_INTEGER:
3047c478bd9Sstevel@tonic-gate 		errno = 0;
3057c478bd9Sstevel@tonic-gate 		if (strtoll(v, &p, 10) != 0 && *v == '0')
3067c478bd9Sstevel@tonic-gate 			return (0);
3077c478bd9Sstevel@tonic-gate 		return (errno == 0 && p != v && *p == 0);
3087c478bd9Sstevel@tonic-gate 
3097c478bd9Sstevel@tonic-gate 	case REP_PROTOCOL_TYPE_TIME:
3107c478bd9Sstevel@tonic-gate 		errno = 0;
3117c478bd9Sstevel@tonic-gate 		(void) strtoll(v, &p, 10);
3127c478bd9Sstevel@tonic-gate 		if (errno != 0 || p == v || (*p != 0 && *p != '.'))
3137c478bd9Sstevel@tonic-gate 			return (0);
3147c478bd9Sstevel@tonic-gate 		if (*p == '.') {
3157c478bd9Sstevel@tonic-gate 			v = p + 1;
3167c478bd9Sstevel@tonic-gate 			errno = 0;
3177c478bd9Sstevel@tonic-gate 			ns = strtoul(v, &p, 10);
3187c478bd9Sstevel@tonic-gate 
3197c478bd9Sstevel@tonic-gate 			/* must be exactly 9 digits */
3207c478bd9Sstevel@tonic-gate 			if ((p - v) != 9 || errno != 0 || *p != 0)
3217c478bd9Sstevel@tonic-gate 				return (0);
3227c478bd9Sstevel@tonic-gate 			if (ns >= NANOSEC)
3237c478bd9Sstevel@tonic-gate 				return (0);
3247c478bd9Sstevel@tonic-gate 		}
3257c478bd9Sstevel@tonic-gate 		return (1);
3267c478bd9Sstevel@tonic-gate 
3277c478bd9Sstevel@tonic-gate 	case REP_PROTOCOL_TYPE_STRING:
3287c478bd9Sstevel@tonic-gate 		return (valid_string(v));
3297c478bd9Sstevel@tonic-gate 
3307c478bd9Sstevel@tonic-gate 	case REP_PROTOCOL_TYPE_OPAQUE:
3317c478bd9Sstevel@tonic-gate 		return (valid_opaque(v));
3327c478bd9Sstevel@tonic-gate 
3337c478bd9Sstevel@tonic-gate 	/*
3347c478bd9Sstevel@tonic-gate 	 * The remaining types are subtypes -- because of the way
3357c478bd9Sstevel@tonic-gate 	 * scf_validate_encoded_value() works, we can rely on the fact
3367c478bd9Sstevel@tonic-gate 	 * that v is a valid example of our base type.  We only have to
3377c478bd9Sstevel@tonic-gate 	 * check our own additional restrictions.
3387c478bd9Sstevel@tonic-gate 	 */
3397c478bd9Sstevel@tonic-gate 	case REP_PROTOCOL_SUBTYPE_USTRING:
3407c478bd9Sstevel@tonic-gate 		return (valid_utf8(v));
3417c478bd9Sstevel@tonic-gate 
3427c478bd9Sstevel@tonic-gate 	case REP_PROTOCOL_SUBTYPE_URI:
3437c478bd9Sstevel@tonic-gate 		return (valid_uri(v));
3447c478bd9Sstevel@tonic-gate 
3457c478bd9Sstevel@tonic-gate 	case REP_PROTOCOL_SUBTYPE_FMRI:
3467c478bd9Sstevel@tonic-gate 		return (valid_fmri(v));
3477c478bd9Sstevel@tonic-gate 
3487c478bd9Sstevel@tonic-gate 	case REP_PROTOCOL_SUBTYPE_HOST:
3497c478bd9Sstevel@tonic-gate 		return (valid_encoded_value(REP_PROTOCOL_SUBTYPE_HOSTNAME, v) ||
3507c478bd9Sstevel@tonic-gate 		    valid_encoded_value(REP_PROTOCOL_SUBTYPE_NETADDR_V4, v) ||
3517c478bd9Sstevel@tonic-gate 		    valid_encoded_value(REP_PROTOCOL_SUBTYPE_NETADDR_V6, v));
3527c478bd9Sstevel@tonic-gate 
3537c478bd9Sstevel@tonic-gate 	case REP_PROTOCOL_SUBTYPE_HOSTNAME:
3547c478bd9Sstevel@tonic-gate 		/* XXX check for valid hostname */
3557c478bd9Sstevel@tonic-gate 		return (valid_utf8(v));
3567c478bd9Sstevel@tonic-gate 
3577c478bd9Sstevel@tonic-gate 	case REP_PROTOCOL_SUBTYPE_NETADDR_V4:
3587c478bd9Sstevel@tonic-gate 	case REP_PROTOCOL_SUBTYPE_NETADDR_V6:
3597c478bd9Sstevel@tonic-gate 		/* XXX check for valid netaddr */
3607c478bd9Sstevel@tonic-gate 		return (valid_utf8(v));
3617c478bd9Sstevel@tonic-gate 
3627c478bd9Sstevel@tonic-gate 	case REP_PROTOCOL_TYPE_INVALID:
3637c478bd9Sstevel@tonic-gate 	default:
3647c478bd9Sstevel@tonic-gate 		return (0);
3657c478bd9Sstevel@tonic-gate 	}
3667c478bd9Sstevel@tonic-gate }
3677c478bd9Sstevel@tonic-gate 
3687c478bd9Sstevel@tonic-gate int
3697c478bd9Sstevel@tonic-gate scf_validate_encoded_value(rep_protocol_value_type_t t, const char *v)
3707c478bd9Sstevel@tonic-gate {
3717c478bd9Sstevel@tonic-gate 	rep_protocol_value_type_t base, cur;
3727c478bd9Sstevel@tonic-gate 
3737c478bd9Sstevel@tonic-gate 	base = scf_proto_underlying_type(t);
3747c478bd9Sstevel@tonic-gate 	while ((cur = scf_proto_underlying_type(base)) != base)
3757c478bd9Sstevel@tonic-gate 		base = cur;
3767c478bd9Sstevel@tonic-gate 
3777c478bd9Sstevel@tonic-gate 	if (base != t && !valid_encoded_value(base, v))
3787c478bd9Sstevel@tonic-gate 		return (0);
3797c478bd9Sstevel@tonic-gate 
3807c478bd9Sstevel@tonic-gate 	return (valid_encoded_value(t, v));
3817c478bd9Sstevel@tonic-gate }
382