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*b56bf881SAntonello Cruz  * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
247c478bd9Sstevel@tonic-gate  */
257c478bd9Sstevel@tonic-gate 
26*b56bf881SAntonello Cruz #include <assert.h>
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>
34*b56bf881SAntonello Cruz #include <sys/types.h>
35*b56bf881SAntonello Cruz #include <sys/socket.h>
36*b56bf881SAntonello Cruz #include <arpa/inet.h>
37*b56bf881SAntonello Cruz #include <netinet/in.h>
387c478bd9Sstevel@tonic-gate 
397c478bd9Sstevel@tonic-gate #define	UTF8_TOP_N(n) \
407c478bd9Sstevel@tonic-gate 	(0xff ^ (0xff >> (n)))		/* top N bits set */
417c478bd9Sstevel@tonic-gate 
427c478bd9Sstevel@tonic-gate #define	UTF8_BOTTOM_N(n) \
437c478bd9Sstevel@tonic-gate 	((1 << (n)) - 1)		/* bottom N bits set */
447c478bd9Sstevel@tonic-gate 
457c478bd9Sstevel@tonic-gate /*
467c478bd9Sstevel@tonic-gate  * The first byte of an n-byte UTF8 encoded character looks like:
477c478bd9Sstevel@tonic-gate  *
487c478bd9Sstevel@tonic-gate  *	n	bits
497c478bd9Sstevel@tonic-gate  *
507c478bd9Sstevel@tonic-gate  *	1	0xxxxxxx
517c478bd9Sstevel@tonic-gate  *	2	110xxxxx
527c478bd9Sstevel@tonic-gate  *	3	1110xxxx
537c478bd9Sstevel@tonic-gate  *	4	11110xxx
547c478bd9Sstevel@tonic-gate  *	5	111110xx
557c478bd9Sstevel@tonic-gate  *	6	1111110x
567c478bd9Sstevel@tonic-gate  *
577c478bd9Sstevel@tonic-gate  * Continuation bytes are 01xxxxxx.
587c478bd9Sstevel@tonic-gate  */
597c478bd9Sstevel@tonic-gate 
607c478bd9Sstevel@tonic-gate #define	UTF8_MAX_BYTES	6
617c478bd9Sstevel@tonic-gate 
627c478bd9Sstevel@tonic-gate /*
637c478bd9Sstevel@tonic-gate  * number of bits in an n-byte UTF-8 encoding.  for multi-byte encodings,
647c478bd9Sstevel@tonic-gate  * You get (7 - n) bits in the first byte, and 6 bits for each additional byte.
657c478bd9Sstevel@tonic-gate  */
667c478bd9Sstevel@tonic-gate #define	UTF8_BITS(n)	/* 1 <= n <= 6 */			\
677c478bd9Sstevel@tonic-gate 	((n) == 1)? 7 :						\
687c478bd9Sstevel@tonic-gate 	(7 - (n) + 6 * ((n) - 1))
697c478bd9Sstevel@tonic-gate 
707c478bd9Sstevel@tonic-gate #define	UTF8_SINGLE_BYTE(c) \
717c478bd9Sstevel@tonic-gate 	(((c) & UTF8_TOP_N(1)) == 0)	/* 0xxxxxxx */
727c478bd9Sstevel@tonic-gate 
737c478bd9Sstevel@tonic-gate #define	UTF8_HEAD_CHECK(c, n)		/* 2 <= n <= 6 */		\
747c478bd9Sstevel@tonic-gate 	(((c) & UTF8_TOP_N((n) + 1)) == UTF8_TOP_N(n))
757c478bd9Sstevel@tonic-gate 
767c478bd9Sstevel@tonic-gate #define	UTF8_HEAD_VALUE(c, n)		/* 2 <= n <= 6 */		\
777c478bd9Sstevel@tonic-gate 	((c) & UTF8_BOTTOM_N(7 - (n)))	/* 'x' mask */
787c478bd9Sstevel@tonic-gate 
797c478bd9Sstevel@tonic-gate #define	UTF8_CONT_CHECK(c) \
807c478bd9Sstevel@tonic-gate 	(((c) & UTF8_TOP_N(2)) == UTF8_TOP_N(1))	/* 10xxxxxx */
817c478bd9Sstevel@tonic-gate 
827c478bd9Sstevel@tonic-gate /*
837c478bd9Sstevel@tonic-gate  * adds in the 6 new bits from a continuation byte
847c478bd9Sstevel@tonic-gate  */
857c478bd9Sstevel@tonic-gate #define	UTF8_VALUE_UPDATE(v, c) \
867c478bd9Sstevel@tonic-gate 	(((v) << 6) | ((c) & UTF8_BOTTOM_N(6)))
877c478bd9Sstevel@tonic-gate 
887c478bd9Sstevel@tonic-gate /*
897c478bd9Sstevel@tonic-gate  * URI components
907c478bd9Sstevel@tonic-gate  */
917c478bd9Sstevel@tonic-gate 
927c478bd9Sstevel@tonic-gate #define	URI_COMPONENT_COUNT	5
937c478bd9Sstevel@tonic-gate 
947c478bd9Sstevel@tonic-gate enum {
957c478bd9Sstevel@tonic-gate 	URI_SCHEME = 0x0,		/* URI scheme */
967c478bd9Sstevel@tonic-gate 	URI_AUTHORITY,			/* URI authority */
977c478bd9Sstevel@tonic-gate 	URI_PATH,			/* URI path */
987c478bd9Sstevel@tonic-gate 	URI_QUERY,			/* URI query */
997c478bd9Sstevel@tonic-gate 	URI_FRAGMENT			/* URI fragment  */
1007c478bd9Sstevel@tonic-gate };
1017c478bd9Sstevel@tonic-gate 
1027c478bd9Sstevel@tonic-gate static int
valid_utf8(const char * str_arg)1037c478bd9Sstevel@tonic-gate valid_utf8(const char *str_arg)
1047c478bd9Sstevel@tonic-gate {
1057c478bd9Sstevel@tonic-gate 	const char *str = str_arg;
1067c478bd9Sstevel@tonic-gate 	uint_t c;
1077c478bd9Sstevel@tonic-gate 	uint32_t v;
1087c478bd9Sstevel@tonic-gate 	int i, n;
1097c478bd9Sstevel@tonic-gate 
1107c478bd9Sstevel@tonic-gate 	while ((c = *str++) != 0) {
1117c478bd9Sstevel@tonic-gate 		if (UTF8_SINGLE_BYTE(c))
1127c478bd9Sstevel@tonic-gate 			continue;	/* ascii */
1137c478bd9Sstevel@tonic-gate 
1147c478bd9Sstevel@tonic-gate 		for (n = 2; n <= UTF8_MAX_BYTES; n++)
1157c478bd9Sstevel@tonic-gate 			if (UTF8_HEAD_CHECK(c, n))
1167c478bd9Sstevel@tonic-gate 				break;
1177c478bd9Sstevel@tonic-gate 
1187c478bd9Sstevel@tonic-gate 		if (n > UTF8_MAX_BYTES)
1197c478bd9Sstevel@tonic-gate 			return (0);		/* invalid head byte */
1207c478bd9Sstevel@tonic-gate 
1217c478bd9Sstevel@tonic-gate 		v = UTF8_HEAD_VALUE(c, n);
1227c478bd9Sstevel@tonic-gate 
1237c478bd9Sstevel@tonic-gate 		for (i = 1; i < n; i++) {
1247c478bd9Sstevel@tonic-gate 			c = *str++;
1257c478bd9Sstevel@tonic-gate 			if (!UTF8_CONT_CHECK(c))
1267c478bd9Sstevel@tonic-gate 				return (0);	/* invalid byte */
1277c478bd9Sstevel@tonic-gate 
1287c478bd9Sstevel@tonic-gate 			v = UTF8_VALUE_UPDATE(v, c);
1297c478bd9Sstevel@tonic-gate 		}
1307c478bd9Sstevel@tonic-gate 
1317c478bd9Sstevel@tonic-gate 		/*
1327c478bd9Sstevel@tonic-gate 		 * if v could have been encoded in the next smallest
1337c478bd9Sstevel@tonic-gate 		 * encoding, the string is not well-formed UTF-8.
1347c478bd9Sstevel@tonic-gate 		 */
1357c478bd9Sstevel@tonic-gate 		if ((v >> (UTF8_BITS(n - 1))) == 0)
1367c478bd9Sstevel@tonic-gate 			return (0);
1377c478bd9Sstevel@tonic-gate 	}
1387c478bd9Sstevel@tonic-gate 
1397c478bd9Sstevel@tonic-gate 	/*
1407c478bd9Sstevel@tonic-gate 	 * we've reached the end of the string -- make sure it is short enough
1417c478bd9Sstevel@tonic-gate 	 */
1427c478bd9Sstevel@tonic-gate 	return ((str - str_arg) < REP_PROTOCOL_VALUE_LEN);
1437c478bd9Sstevel@tonic-gate }
1447c478bd9Sstevel@tonic-gate 
1457c478bd9Sstevel@tonic-gate static int
valid_string(const char * str)1467c478bd9Sstevel@tonic-gate valid_string(const char *str)
1477c478bd9Sstevel@tonic-gate {
1487c478bd9Sstevel@tonic-gate 	return (strlen(str) < REP_PROTOCOL_VALUE_LEN);
1497c478bd9Sstevel@tonic-gate }
1507c478bd9Sstevel@tonic-gate 
1517c478bd9Sstevel@tonic-gate static int
valid_opaque(const char * str_arg)1527c478bd9Sstevel@tonic-gate valid_opaque(const char *str_arg)
1537c478bd9Sstevel@tonic-gate {
1547c478bd9Sstevel@tonic-gate 	const char *str = str_arg;
1557c478bd9Sstevel@tonic-gate 	uint_t c;
1567c478bd9Sstevel@tonic-gate 	ptrdiff_t len;
1577c478bd9Sstevel@tonic-gate 
1587c478bd9Sstevel@tonic-gate 	while ((c = *str++) != 0)
1597c478bd9Sstevel@tonic-gate 		if ((c < '0' || c > '9') && (c < 'a' || c > 'f') &&
1607c478bd9Sstevel@tonic-gate 		    (c < 'A' || c > 'F'))
1617c478bd9Sstevel@tonic-gate 			return (0);		/* not hex digit */
1627c478bd9Sstevel@tonic-gate 
1637c478bd9Sstevel@tonic-gate 	len = (str - str_arg) - 1;		/* not counting NIL byte */
1647c478bd9Sstevel@tonic-gate 	return ((len % 2) == 0 && len / 2 < REP_PROTOCOL_VALUE_LEN);
1657c478bd9Sstevel@tonic-gate }
1667c478bd9Sstevel@tonic-gate 
1677c478bd9Sstevel@tonic-gate /*
1687c478bd9Sstevel@tonic-gate  * Return 1 if the supplied parameter is a conformant URI (as defined
1697c478bd9Sstevel@tonic-gate  * by RFC 2396), 0 otherwise.
1707c478bd9Sstevel@tonic-gate  */
1717c478bd9Sstevel@tonic-gate static int
valid_uri(const char * str)1727c478bd9Sstevel@tonic-gate valid_uri(const char *str)
1737c478bd9Sstevel@tonic-gate {
1747c478bd9Sstevel@tonic-gate 	/*
1757c478bd9Sstevel@tonic-gate 	 * URI Regular Expression. Compiled with regcmp(1).
1767c478bd9Sstevel@tonic-gate 	 *
1777c478bd9Sstevel@tonic-gate 	 * ^(([^:/?#]+:){0,1})$0(//([^/?#]*)$1){0,1}([^?#]*)$2
1787c478bd9Sstevel@tonic-gate 	 * (?([^#]*)$3){0,1}(#(.*)$4){0,1}
1797c478bd9Sstevel@tonic-gate 	 */
1807c478bd9Sstevel@tonic-gate 	char exp[] = {
1817c478bd9Sstevel@tonic-gate 		040, 074, 00, 060, 012, 0126, 05, 072, 057, 077, 043, 024,
1827c478bd9Sstevel@tonic-gate 		072, 057, 00, 00, 01, 014, 00, 00, 060, 020, 024, 057,
1837c478bd9Sstevel@tonic-gate 		024, 057, 074, 01, 0125, 04, 057, 077, 043, 014, 01, 01,
1847c478bd9Sstevel@tonic-gate 		057, 01, 00, 01, 074, 02, 0125, 03, 077, 043, 014, 02,
1857c478bd9Sstevel@tonic-gate 		02, 060, 014, 024, 077, 074, 03, 0125, 02, 043, 014, 03,
1867c478bd9Sstevel@tonic-gate 		03, 057, 02, 00, 01, 060, 012, 024, 043, 074, 04, 021,
1877c478bd9Sstevel@tonic-gate 		014, 04, 04, 057, 03, 00, 01, 064, 00,
1887c478bd9Sstevel@tonic-gate 		0};
1897c478bd9Sstevel@tonic-gate 	char uri[URI_COMPONENT_COUNT][REP_PROTOCOL_VALUE_LEN];
1907c478bd9Sstevel@tonic-gate 
1917c478bd9Sstevel@tonic-gate 	/*
1927c478bd9Sstevel@tonic-gate 	 * If the string is too long, then the URI cannot be valid. Also,
1937c478bd9Sstevel@tonic-gate 	 * this protects against buffer overflow attacks on the uri array.
1947c478bd9Sstevel@tonic-gate 	 */
1957c478bd9Sstevel@tonic-gate 	if (strlen(str) >= REP_PROTOCOL_VALUE_LEN)
1967c478bd9Sstevel@tonic-gate 		return (0);
1977c478bd9Sstevel@tonic-gate 
1987c478bd9Sstevel@tonic-gate 	if (regex(exp, str, uri[URI_SCHEME], uri[URI_AUTHORITY], uri[URI_PATH],
199a574db85Sraf 	    uri[URI_QUERY], uri[URI_FRAGMENT]) == NULL) {
2007c478bd9Sstevel@tonic-gate 		return (0);
2017c478bd9Sstevel@tonic-gate 	}
2027c478bd9Sstevel@tonic-gate 	/*
2037c478bd9Sstevel@tonic-gate 	 * To be a valid URI, the length of the URI_PATH must not be zero
2047c478bd9Sstevel@tonic-gate 	 */
2057c478bd9Sstevel@tonic-gate 	if (strlen(uri[URI_PATH]) == 0) {
2067c478bd9Sstevel@tonic-gate 		return (0);
2077c478bd9Sstevel@tonic-gate 	}
2087c478bd9Sstevel@tonic-gate 	return (1);
2097c478bd9Sstevel@tonic-gate }
2107c478bd9Sstevel@tonic-gate 
2117c478bd9Sstevel@tonic-gate /*
2127c478bd9Sstevel@tonic-gate  * Return 1 if the supplied parameter is a conformant fmri, 0
2137c478bd9Sstevel@tonic-gate  * otherwise.
2147c478bd9Sstevel@tonic-gate  */
2157c478bd9Sstevel@tonic-gate static int
valid_fmri(const char * str)2167c478bd9Sstevel@tonic-gate valid_fmri(const char *str)
2177c478bd9Sstevel@tonic-gate {
2187c478bd9Sstevel@tonic-gate 	int ret;
2197c478bd9Sstevel@tonic-gate 	char fmri[REP_PROTOCOL_VALUE_LEN] = { 0 };
2207c478bd9Sstevel@tonic-gate 
2217c478bd9Sstevel@tonic-gate 	/*
2227c478bd9Sstevel@tonic-gate 	 * Try to parse the fmri, if we can parse it then it
2237c478bd9Sstevel@tonic-gate 	 * must be syntactically correct. Work on a copy of
2247c478bd9Sstevel@tonic-gate 	 * the fmri since the parsing process can modify the
2257c478bd9Sstevel@tonic-gate 	 * supplied string.
2267c478bd9Sstevel@tonic-gate 	 */
2277c478bd9Sstevel@tonic-gate 	if (strlcpy(fmri, str, sizeof (fmri)) >= sizeof (fmri))
2287c478bd9Sstevel@tonic-gate 		return (0);
2297c478bd9Sstevel@tonic-gate 
2307c478bd9Sstevel@tonic-gate 	ret = ! scf_parse_fmri(fmri, NULL, NULL, NULL, NULL, NULL, NULL);
2317c478bd9Sstevel@tonic-gate 
2327c478bd9Sstevel@tonic-gate 	return (ret);
2337c478bd9Sstevel@tonic-gate }
2347c478bd9Sstevel@tonic-gate 
235*b56bf881SAntonello Cruz /*
236*b56bf881SAntonello Cruz  * check_prefix()
237*b56bf881SAntonello Cruz  * Return 1 if the prefix is a valid IPv4 or IPv6 network prefix, 0 otherwise
238*b56bf881SAntonello Cruz  */
239*b56bf881SAntonello Cruz static int
check_net_prefix(const char * p,int max_len)240*b56bf881SAntonello Cruz check_net_prefix(const char *p, int max_len)
241*b56bf881SAntonello Cruz {
242*b56bf881SAntonello Cruz 	char *end;
243*b56bf881SAntonello Cruz 	int len;
244*b56bf881SAntonello Cruz 
245*b56bf881SAntonello Cruz 	len = strtol(p, &end, 10);
246*b56bf881SAntonello Cruz 	if (p == end || len < 0 || len > max_len)
247*b56bf881SAntonello Cruz 		return (0);
248*b56bf881SAntonello Cruz 
249*b56bf881SAntonello Cruz 	return (1);
250*b56bf881SAntonello Cruz }
251*b56bf881SAntonello Cruz 
252*b56bf881SAntonello Cruz /*
253*b56bf881SAntonello Cruz  * Return 1 if the supplied IP address is valid, 0 otherwise.
254*b56bf881SAntonello Cruz  */
255*b56bf881SAntonello Cruz static int
valid_ip(int af,const char * str)256*b56bf881SAntonello Cruz valid_ip(int af, const char *str)
257*b56bf881SAntonello Cruz {
258*b56bf881SAntonello Cruz 	void *unused[4];
259*b56bf881SAntonello Cruz 	const char *addr = str;
260*b56bf881SAntonello Cruz 	char buf[INET6_ADDRSTRLEN]; /* enough for both IPv4 and IPv6 */
261*b56bf881SAntonello Cruz 	char *net_prefix;
262*b56bf881SAntonello Cruz 	int buf_sz;
263*b56bf881SAntonello Cruz 	int plen;
264*b56bf881SAntonello Cruz 
265*b56bf881SAntonello Cruz 	switch (af) {
266*b56bf881SAntonello Cruz 	case AF_INET:
267*b56bf881SAntonello Cruz 		buf_sz = INET_ADDRSTRLEN;
268*b56bf881SAntonello Cruz 		plen = 32; /* bit size of an IPv4 */
269*b56bf881SAntonello Cruz 		break;
270*b56bf881SAntonello Cruz 
271*b56bf881SAntonello Cruz 	case AF_INET6:
272*b56bf881SAntonello Cruz 		buf_sz = INET6_ADDRSTRLEN;
273*b56bf881SAntonello Cruz 		plen = 128; /* bit size of an IPv6 */
274*b56bf881SAntonello Cruz 		break;
275*b56bf881SAntonello Cruz 
276*b56bf881SAntonello Cruz 	default:
277*b56bf881SAntonello Cruz 		assert(0);
278*b56bf881SAntonello Cruz 		abort();
279*b56bf881SAntonello Cruz 	}
280*b56bf881SAntonello Cruz 
281*b56bf881SAntonello Cruz 	/* check network prefix for the IP address */
282*b56bf881SAntonello Cruz 	if ((net_prefix = strchr(str, '/')) != NULL) {
283*b56bf881SAntonello Cruz 		if (check_net_prefix(++net_prefix, plen) == 0)
284*b56bf881SAntonello Cruz 			return (0);
285*b56bf881SAntonello Cruz 
286*b56bf881SAntonello Cruz 		(void) strlcpy(buf, str, buf_sz);
287*b56bf881SAntonello Cruz 		if ((net_prefix = strchr(buf, '/')) != NULL)
288*b56bf881SAntonello Cruz 			*net_prefix = '\0';
289*b56bf881SAntonello Cruz 
290*b56bf881SAntonello Cruz 		addr = buf;
291*b56bf881SAntonello Cruz 	}
292*b56bf881SAntonello Cruz 
293*b56bf881SAntonello Cruz 	return (inet_pton(af, addr, unused));
294*b56bf881SAntonello Cruz }
295*b56bf881SAntonello Cruz 
2967c478bd9Sstevel@tonic-gate rep_protocol_value_type_t
scf_proto_underlying_type(rep_protocol_value_type_t t)2977c478bd9Sstevel@tonic-gate scf_proto_underlying_type(rep_protocol_value_type_t t)
2987c478bd9Sstevel@tonic-gate {
2997c478bd9Sstevel@tonic-gate 	switch (t) {
3007c478bd9Sstevel@tonic-gate 	case REP_PROTOCOL_TYPE_BOOLEAN:
3017c478bd9Sstevel@tonic-gate 	case REP_PROTOCOL_TYPE_COUNT:
3027c478bd9Sstevel@tonic-gate 	case REP_PROTOCOL_TYPE_INTEGER:
3037c478bd9Sstevel@tonic-gate 	case REP_PROTOCOL_TYPE_TIME:
3047c478bd9Sstevel@tonic-gate 	case REP_PROTOCOL_TYPE_STRING:
3057c478bd9Sstevel@tonic-gate 	case REP_PROTOCOL_TYPE_OPAQUE:
3067c478bd9Sstevel@tonic-gate 		return (t);
3077c478bd9Sstevel@tonic-gate 
3087c478bd9Sstevel@tonic-gate 	case REP_PROTOCOL_SUBTYPE_USTRING:
3097c478bd9Sstevel@tonic-gate 		return (REP_PROTOCOL_TYPE_STRING);
3107c478bd9Sstevel@tonic-gate 
3117c478bd9Sstevel@tonic-gate 	case REP_PROTOCOL_SUBTYPE_URI:
3127c478bd9Sstevel@tonic-gate 		return (REP_PROTOCOL_SUBTYPE_USTRING);
3137c478bd9Sstevel@tonic-gate 	case REP_PROTOCOL_SUBTYPE_FMRI:
3147c478bd9Sstevel@tonic-gate 		return (REP_PROTOCOL_SUBTYPE_URI);
3157c478bd9Sstevel@tonic-gate 
3167c478bd9Sstevel@tonic-gate 	case REP_PROTOCOL_SUBTYPE_HOST:
3177c478bd9Sstevel@tonic-gate 		return (REP_PROTOCOL_SUBTYPE_USTRING);
3187c478bd9Sstevel@tonic-gate 	case REP_PROTOCOL_SUBTYPE_HOSTNAME:
3197c478bd9Sstevel@tonic-gate 		return (REP_PROTOCOL_SUBTYPE_HOST);
320*b56bf881SAntonello Cruz 	case REP_PROTOCOL_SUBTYPE_NETADDR:
3217c478bd9Sstevel@tonic-gate 		return (REP_PROTOCOL_SUBTYPE_HOST);
322*b56bf881SAntonello Cruz 	case REP_PROTOCOL_SUBTYPE_NETADDR_V4:
323*b56bf881SAntonello Cruz 		return (REP_PROTOCOL_SUBTYPE_NETADDR);
3247c478bd9Sstevel@tonic-gate 	case REP_PROTOCOL_SUBTYPE_NETADDR_V6:
325*b56bf881SAntonello Cruz 		return (REP_PROTOCOL_SUBTYPE_NETADDR);
3267c478bd9Sstevel@tonic-gate 
3277c478bd9Sstevel@tonic-gate 	case REP_PROTOCOL_TYPE_INVALID:
3287c478bd9Sstevel@tonic-gate 	default:
3297c478bd9Sstevel@tonic-gate 		return (REP_PROTOCOL_TYPE_INVALID);
3307c478bd9Sstevel@tonic-gate 	}
3317c478bd9Sstevel@tonic-gate }
3327c478bd9Sstevel@tonic-gate 
3337c478bd9Sstevel@tonic-gate int
scf_is_compatible_protocol_type(rep_protocol_value_type_t base,rep_protocol_value_type_t new)334870ad75aSSean Wilcox scf_is_compatible_protocol_type(rep_protocol_value_type_t base,
3357c478bd9Sstevel@tonic-gate     rep_protocol_value_type_t new)
3367c478bd9Sstevel@tonic-gate {
3377c478bd9Sstevel@tonic-gate 	rep_protocol_value_type_t t, cur;
3387c478bd9Sstevel@tonic-gate 
3397c478bd9Sstevel@tonic-gate 	if (base == REP_PROTOCOL_TYPE_INVALID)
3407c478bd9Sstevel@tonic-gate 		return (0);
3417c478bd9Sstevel@tonic-gate 
3427c478bd9Sstevel@tonic-gate 	if (base == new)
3437c478bd9Sstevel@tonic-gate 		return (1);
3447c478bd9Sstevel@tonic-gate 
3457c478bd9Sstevel@tonic-gate 	for (t = new; t != (cur = scf_proto_underlying_type(t)); t = cur) {
3467c478bd9Sstevel@tonic-gate 		if (cur == REP_PROTOCOL_TYPE_INVALID)
3477c478bd9Sstevel@tonic-gate 			return (0);
3487c478bd9Sstevel@tonic-gate 		if (cur == base)
3497c478bd9Sstevel@tonic-gate 			return (1);		/* base is parent of new */
3507c478bd9Sstevel@tonic-gate 	}
3517c478bd9Sstevel@tonic-gate 	return (0);
3527c478bd9Sstevel@tonic-gate }
3537c478bd9Sstevel@tonic-gate 
3547c478bd9Sstevel@tonic-gate static int
valid_encoded_value(rep_protocol_value_type_t t,const char * v)3557c478bd9Sstevel@tonic-gate valid_encoded_value(rep_protocol_value_type_t t, const char *v)
3567c478bd9Sstevel@tonic-gate {
3577c478bd9Sstevel@tonic-gate 	char *p;
3587c478bd9Sstevel@tonic-gate 	ulong_t ns;
3597c478bd9Sstevel@tonic-gate 
3607c478bd9Sstevel@tonic-gate 	switch (t) {
3617c478bd9Sstevel@tonic-gate 	case REP_PROTOCOL_TYPE_BOOLEAN:
3627c478bd9Sstevel@tonic-gate 		return ((*v == '0' || *v == '1') && v[1] == 0);
3637c478bd9Sstevel@tonic-gate 
3647c478bd9Sstevel@tonic-gate 	case REP_PROTOCOL_TYPE_COUNT:
3657c478bd9Sstevel@tonic-gate 		errno = 0;
3667c478bd9Sstevel@tonic-gate 		if (strtoull(v, &p, 10) != 0 && *v == '0')
3677c478bd9Sstevel@tonic-gate 			return (0);
3687c478bd9Sstevel@tonic-gate 		return (errno == 0 && p != v && *p == 0);
3697c478bd9Sstevel@tonic-gate 
3707c478bd9Sstevel@tonic-gate 	case REP_PROTOCOL_TYPE_INTEGER:
3717c478bd9Sstevel@tonic-gate 		errno = 0;
3727c478bd9Sstevel@tonic-gate 		if (strtoll(v, &p, 10) != 0 && *v == '0')
3737c478bd9Sstevel@tonic-gate 			return (0);
3747c478bd9Sstevel@tonic-gate 		return (errno == 0 && p != v && *p == 0);
3757c478bd9Sstevel@tonic-gate 
3767c478bd9Sstevel@tonic-gate 	case REP_PROTOCOL_TYPE_TIME:
3777c478bd9Sstevel@tonic-gate 		errno = 0;
3787c478bd9Sstevel@tonic-gate 		(void) strtoll(v, &p, 10);
3797c478bd9Sstevel@tonic-gate 		if (errno != 0 || p == v || (*p != 0 && *p != '.'))
3807c478bd9Sstevel@tonic-gate 			return (0);
3817c478bd9Sstevel@tonic-gate 		if (*p == '.') {
3827c478bd9Sstevel@tonic-gate 			v = p + 1;
3837c478bd9Sstevel@tonic-gate 			errno = 0;
3847c478bd9Sstevel@tonic-gate 			ns = strtoul(v, &p, 10);
3857c478bd9Sstevel@tonic-gate 
3867c478bd9Sstevel@tonic-gate 			/* must be exactly 9 digits */
3877c478bd9Sstevel@tonic-gate 			if ((p - v) != 9 || errno != 0 || *p != 0)
3887c478bd9Sstevel@tonic-gate 				return (0);
3897c478bd9Sstevel@tonic-gate 			if (ns >= NANOSEC)
3907c478bd9Sstevel@tonic-gate 				return (0);
3917c478bd9Sstevel@tonic-gate 		}
3927c478bd9Sstevel@tonic-gate 		return (1);
3937c478bd9Sstevel@tonic-gate 
3947c478bd9Sstevel@tonic-gate 	case REP_PROTOCOL_TYPE_STRING:
3957c478bd9Sstevel@tonic-gate 		return (valid_string(v));
3967c478bd9Sstevel@tonic-gate 
3977c478bd9Sstevel@tonic-gate 	case REP_PROTOCOL_TYPE_OPAQUE:
3987c478bd9Sstevel@tonic-gate 		return (valid_opaque(v));
3997c478bd9Sstevel@tonic-gate 
4007c478bd9Sstevel@tonic-gate 	/*
4017c478bd9Sstevel@tonic-gate 	 * The remaining types are subtypes -- because of the way
4027c478bd9Sstevel@tonic-gate 	 * scf_validate_encoded_value() works, we can rely on the fact
4037c478bd9Sstevel@tonic-gate 	 * that v is a valid example of our base type.  We only have to
4047c478bd9Sstevel@tonic-gate 	 * check our own additional restrictions.
4057c478bd9Sstevel@tonic-gate 	 */
4067c478bd9Sstevel@tonic-gate 	case REP_PROTOCOL_SUBTYPE_USTRING:
4077c478bd9Sstevel@tonic-gate 		return (valid_utf8(v));
4087c478bd9Sstevel@tonic-gate 
4097c478bd9Sstevel@tonic-gate 	case REP_PROTOCOL_SUBTYPE_URI:
4107c478bd9Sstevel@tonic-gate 		return (valid_uri(v));
4117c478bd9Sstevel@tonic-gate 
4127c478bd9Sstevel@tonic-gate 	case REP_PROTOCOL_SUBTYPE_FMRI:
4137c478bd9Sstevel@tonic-gate 		return (valid_fmri(v));
4147c478bd9Sstevel@tonic-gate 
4157c478bd9Sstevel@tonic-gate 	case REP_PROTOCOL_SUBTYPE_HOST:
4167c478bd9Sstevel@tonic-gate 		return (valid_encoded_value(REP_PROTOCOL_SUBTYPE_HOSTNAME, v) ||
417*b56bf881SAntonello Cruz 		    valid_encoded_value(REP_PROTOCOL_SUBTYPE_NETADDR, v));
4187c478bd9Sstevel@tonic-gate 
4197c478bd9Sstevel@tonic-gate 	case REP_PROTOCOL_SUBTYPE_HOSTNAME:
4207c478bd9Sstevel@tonic-gate 		/* XXX check for valid hostname */
4217c478bd9Sstevel@tonic-gate 		return (valid_utf8(v));
4227c478bd9Sstevel@tonic-gate 
423*b56bf881SAntonello Cruz 	case REP_PROTOCOL_SUBTYPE_NETADDR:
424*b56bf881SAntonello Cruz 		return (valid_ip(AF_INET, v) || valid_ip(AF_INET6, v));
425*b56bf881SAntonello Cruz 
4267c478bd9Sstevel@tonic-gate 	case REP_PROTOCOL_SUBTYPE_NETADDR_V4:
427*b56bf881SAntonello Cruz 		return (valid_ip(AF_INET, v));
428*b56bf881SAntonello Cruz 
4297c478bd9Sstevel@tonic-gate 	case REP_PROTOCOL_SUBTYPE_NETADDR_V6:
430*b56bf881SAntonello Cruz 		return (valid_ip(AF_INET6, v));
4317c478bd9Sstevel@tonic-gate 
4327c478bd9Sstevel@tonic-gate 	case REP_PROTOCOL_TYPE_INVALID:
4337c478bd9Sstevel@tonic-gate 	default:
4347c478bd9Sstevel@tonic-gate 		return (0);
4357c478bd9Sstevel@tonic-gate 	}
4367c478bd9Sstevel@tonic-gate }
4377c478bd9Sstevel@tonic-gate 
4387c478bd9Sstevel@tonic-gate int
scf_validate_encoded_value(rep_protocol_value_type_t t,const char * v)4397c478bd9Sstevel@tonic-gate scf_validate_encoded_value(rep_protocol_value_type_t t, const char *v)
4407c478bd9Sstevel@tonic-gate {
4417c478bd9Sstevel@tonic-gate 	rep_protocol_value_type_t base, cur;
4427c478bd9Sstevel@tonic-gate 
4437c478bd9Sstevel@tonic-gate 	base = scf_proto_underlying_type(t);
4447c478bd9Sstevel@tonic-gate 	while ((cur = scf_proto_underlying_type(base)) != base)
4457c478bd9Sstevel@tonic-gate 		base = cur;
4467c478bd9Sstevel@tonic-gate 
4477c478bd9Sstevel@tonic-gate 	if (base != t && !valid_encoded_value(base, v))
4487c478bd9Sstevel@tonic-gate 		return (0);
4497c478bd9Sstevel@tonic-gate 
4507c478bd9Sstevel@tonic-gate 	return (valid_encoded_value(t, v));
4517c478bd9Sstevel@tonic-gate }
452