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