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 * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
23 * Use is subject to license terms.
24 */
25
26#include <unistd.h>
27#include <strings.h>
28#include <libintl.h>
29#include <sys/types.h>
30#include <sys/inttypes.h>
31#include "libnvpair.h"
32
33/*
34 * libnvpair - A tools library for manipulating <name, value> pairs.
35 *
36 *	This library provides routines packing an unpacking nv pairs
37 *	for transporting data across process boundaries, transporting
38 *	between kernel and userland, and possibly saving onto disk files.
39 */
40
41static void
42indent(FILE *fp, int depth)
43{
44	while (depth-- > 0)
45		(void) fprintf(fp, "\t");
46}
47
48/*
49 * nvlist_print - Prints elements in an event buffer
50 */
51static
52void
53nvlist_print_with_indent(FILE *fp, nvlist_t *nvl, int depth)
54{
55	int i;
56	char *name;
57	uint_t nelem;
58	nvpair_t *nvp;
59
60	if (nvl == NULL)
61		return;
62
63	indent(fp, depth);
64	(void) fprintf(fp, "nvlist version: %d\n", NVL_VERSION(nvl));
65
66	nvp = nvlist_next_nvpair(nvl, NULL);
67
68	while (nvp) {
69		data_type_t type = nvpair_type(nvp);
70
71		indent(fp, depth);
72		name = nvpair_name(nvp);
73		(void) fprintf(fp, "\t%s =", name);
74		nelem = 0;
75		switch (type) {
76		case DATA_TYPE_BOOLEAN: {
77			(void) fprintf(fp, " 1");
78			break;
79		}
80		case DATA_TYPE_BOOLEAN_VALUE: {
81			boolean_t val;
82			(void) nvpair_value_boolean_value(nvp, &val);
83			(void) fprintf(fp, " %d", val);
84			break;
85		}
86		case DATA_TYPE_BYTE: {
87			uchar_t val;
88			(void) nvpair_value_byte(nvp, &val);
89			(void) fprintf(fp, " 0x%2.2x", val);
90			break;
91		}
92		case DATA_TYPE_INT8: {
93			int8_t val;
94			(void) nvpair_value_int8(nvp, &val);
95			(void) fprintf(fp, " %d", val);
96			break;
97		}
98		case DATA_TYPE_UINT8: {
99			uint8_t val;
100			(void) nvpair_value_uint8(nvp, &val);
101			(void) fprintf(fp, " 0x%x", val);
102			break;
103		}
104		case DATA_TYPE_INT16: {
105			int16_t val;
106			(void) nvpair_value_int16(nvp, &val);
107			(void) fprintf(fp, " %d", val);
108			break;
109		}
110		case DATA_TYPE_UINT16: {
111			uint16_t val;
112			(void) nvpair_value_uint16(nvp, &val);
113			(void) fprintf(fp, " 0x%x", val);
114			break;
115		}
116		case DATA_TYPE_INT32: {
117			int32_t val;
118			(void) nvpair_value_int32(nvp, &val);
119			(void) fprintf(fp, " %d", val);
120			break;
121		}
122		case DATA_TYPE_UINT32: {
123			uint32_t val;
124			(void) nvpair_value_uint32(nvp, &val);
125			(void) fprintf(fp, " 0x%x", val);
126			break;
127		}
128		case DATA_TYPE_INT64: {
129			int64_t val;
130			(void) nvpair_value_int64(nvp, &val);
131			(void) fprintf(fp, " %lld", (longlong_t)val);
132			break;
133		}
134		case DATA_TYPE_UINT64: {
135			uint64_t val;
136			(void) nvpair_value_uint64(nvp, &val);
137			(void) fprintf(fp, " 0x%llx", (u_longlong_t)val);
138			break;
139		}
140		case DATA_TYPE_DOUBLE: {
141			double val;
142			(void) nvpair_value_double(nvp, &val);
143			(void) fprintf(fp, " 0x%llf", val);
144			break;
145		}
146		case DATA_TYPE_STRING: {
147			char *val;
148			(void) nvpair_value_string(nvp, &val);
149			(void) fprintf(fp, " %s", val);
150			break;
151		}
152		case DATA_TYPE_BOOLEAN_ARRAY: {
153			boolean_t *val;
154			(void) nvpair_value_boolean_array(nvp, &val, &nelem);
155			for (i = 0; i < nelem; i++)
156				(void) fprintf(fp, " %d", val[i]);
157			break;
158		}
159		case DATA_TYPE_BYTE_ARRAY: {
160			uchar_t *val;
161			(void) nvpair_value_byte_array(nvp, &val, &nelem);
162			for (i = 0; i < nelem; i++)
163				(void) fprintf(fp, " 0x%2.2x", val[i]);
164			break;
165		}
166		case DATA_TYPE_INT8_ARRAY: {
167			int8_t *val;
168			(void) nvpair_value_int8_array(nvp, &val, &nelem);
169			for (i = 0; i < nelem; i++)
170				(void) fprintf(fp, " %d", val[i]);
171			break;
172		}
173		case DATA_TYPE_UINT8_ARRAY: {
174			uint8_t *val;
175			(void) nvpair_value_uint8_array(nvp, &val, &nelem);
176			for (i = 0; i < nelem; i++)
177				(void) fprintf(fp, " 0x%x", val[i]);
178			break;
179		}
180		case DATA_TYPE_INT16_ARRAY: {
181			int16_t *val;
182			(void) nvpair_value_int16_array(nvp, &val, &nelem);
183			for (i = 0; i < nelem; i++)
184				(void) fprintf(fp, " %d", val[i]);
185			break;
186		}
187		case DATA_TYPE_UINT16_ARRAY: {
188			uint16_t *val;
189			(void) nvpair_value_uint16_array(nvp, &val, &nelem);
190			for (i = 0; i < nelem; i++)
191				(void) fprintf(fp, " 0x%x", val[i]);
192			break;
193		}
194		case DATA_TYPE_INT32_ARRAY: {
195			int32_t *val;
196			(void) nvpair_value_int32_array(nvp, &val, &nelem);
197			for (i = 0; i < nelem; i++)
198				(void) fprintf(fp, " %d", val[i]);
199			break;
200		}
201		case DATA_TYPE_UINT32_ARRAY: {
202			uint32_t *val;
203			(void) nvpair_value_uint32_array(nvp, &val, &nelem);
204			for (i = 0; i < nelem; i++)
205				(void) fprintf(fp, " 0x%x", val[i]);
206			break;
207		}
208		case DATA_TYPE_INT64_ARRAY: {
209			int64_t *val;
210			(void) nvpair_value_int64_array(nvp, &val, &nelem);
211			for (i = 0; i < nelem; i++)
212				(void) fprintf(fp, " %lld", (longlong_t)val[i]);
213			break;
214		}
215		case DATA_TYPE_UINT64_ARRAY: {
216			uint64_t *val;
217			(void) nvpair_value_uint64_array(nvp, &val, &nelem);
218			for (i = 0; i < nelem; i++)
219				(void) fprintf(fp, " 0x%llx",
220				    (u_longlong_t)val[i]);
221			break;
222		}
223		case DATA_TYPE_STRING_ARRAY: {
224			char **val;
225			(void) nvpair_value_string_array(nvp, &val, &nelem);
226			for (i = 0; i < nelem; i++)
227				(void) fprintf(fp, " %s", val[i]);
228			break;
229		}
230		case DATA_TYPE_HRTIME: {
231			hrtime_t val;
232			(void) nvpair_value_hrtime(nvp, &val);
233			(void) fprintf(fp, " 0x%llx", val);
234			break;
235		}
236		case DATA_TYPE_NVLIST: {
237			nvlist_t *val;
238			(void) nvpair_value_nvlist(nvp, &val);
239			(void) fprintf(fp, " (embedded nvlist)\n");
240			nvlist_print_with_indent(fp, val, depth + 1);
241			indent(fp, depth + 1);
242			(void) fprintf(fp, "(end %s)\n", name);
243			break;
244		}
245		case DATA_TYPE_NVLIST_ARRAY: {
246			nvlist_t **val;
247			(void) nvpair_value_nvlist_array(nvp, &val, &nelem);
248			(void) fprintf(fp, " (array of embedded nvlists)\n");
249			for (i = 0; i < nelem; i++) {
250				indent(fp, depth + 1);
251				(void) fprintf(fp,
252				    "(start %s[%d])\n", name, i);
253				nvlist_print_with_indent(fp, val[i], depth + 1);
254				indent(fp, depth + 1);
255				(void) fprintf(fp, "(end %s[%d])\n", name, i);
256			}
257			break;
258		}
259		default:
260			(void) fprintf(fp, " unknown data type (%d)", type);
261			break;
262		}
263		(void) fprintf(fp, "\n");
264		nvp = nvlist_next_nvpair(nvl, nvp);
265	}
266}
267
268void
269nvlist_print(FILE *fp, nvlist_t *nvl)
270{
271	nvlist_print_with_indent(fp, nvl, 0);
272}
273
274
275#define	NVP(elem, type, vtype, ptype, format) { \
276	vtype	value; \
277\
278	(void) nvpair_value_##type(elem, &value); \
279	(void) printf("%*s%s: " format "\n", indent, "", \
280	    nvpair_name(elem), (ptype)value); \
281}
282
283#define	NVPA(elem, type, vtype, ptype, format) { \
284	uint_t	i, count; \
285	vtype	*value;  \
286\
287	(void) nvpair_value_##type(elem, &value, &count); \
288	for (i = 0; i < count; i++) { \
289		(void) printf("%*s%s[%d]: " format "\n", indent, "", \
290		    nvpair_name(elem), i, (ptype)value[i]); \
291	} \
292}
293
294/*
295 * Similar to nvlist_print() but handles arrays slightly differently.
296 */
297void
298dump_nvlist(nvlist_t *list, int indent)
299{
300	nvpair_t	*elem = NULL;
301	boolean_t	bool_value;
302	nvlist_t	*nvlist_value;
303	nvlist_t	**nvlist_array_value;
304	uint_t		i, count;
305
306	if (list == NULL) {
307		return;
308	}
309
310	while ((elem = nvlist_next_nvpair(list, elem)) != NULL) {
311		switch (nvpair_type(elem)) {
312		case DATA_TYPE_BOOLEAN_VALUE:
313			(void) nvpair_value_boolean_value(elem, &bool_value);
314			(void) printf("%*s%s: %s\n", indent, "",
315			    nvpair_name(elem), bool_value ? "true" : "false");
316			break;
317
318		case DATA_TYPE_BYTE:
319			NVP(elem, byte, uchar_t, int, "%u");
320			break;
321
322		case DATA_TYPE_INT8:
323			NVP(elem, int8, int8_t, int, "%d");
324			break;
325
326		case DATA_TYPE_UINT8:
327			NVP(elem, uint8, uint8_t, int, "%u");
328			break;
329
330		case DATA_TYPE_INT16:
331			NVP(elem, int16, int16_t, int, "%d");
332			break;
333
334		case DATA_TYPE_UINT16:
335			NVP(elem, uint16, uint16_t, int, "%u");
336			break;
337
338		case DATA_TYPE_INT32:
339			NVP(elem, int32, int32_t, long, "%ld");
340			break;
341
342		case DATA_TYPE_UINT32:
343			NVP(elem, uint32, uint32_t, ulong_t, "%lu");
344			break;
345
346		case DATA_TYPE_INT64:
347			NVP(elem, int64, int64_t, longlong_t, "%lld");
348			break;
349
350		case DATA_TYPE_UINT64:
351			NVP(elem, uint64, uint64_t, u_longlong_t, "%llu");
352			break;
353
354		case DATA_TYPE_STRING:
355			NVP(elem, string, char *, char *, "'%s'");
356			break;
357
358		case DATA_TYPE_BYTE_ARRAY:
359			NVPA(elem, byte_array, uchar_t, int, "%u");
360			break;
361
362		case DATA_TYPE_INT8_ARRAY:
363			NVPA(elem, int8_array, int8_t, int, "%d");
364			break;
365
366		case DATA_TYPE_UINT8_ARRAY:
367			NVPA(elem, uint8_array, uint8_t, int, "%u");
368			break;
369
370		case DATA_TYPE_INT16_ARRAY:
371			NVPA(elem, int16_array, int16_t, int, "%d");
372			break;
373
374		case DATA_TYPE_UINT16_ARRAY:
375			NVPA(elem, uint16_array, uint16_t, int, "%u");
376			break;
377
378		case DATA_TYPE_INT32_ARRAY:
379			NVPA(elem, int32_array, int32_t, long, "%ld");
380			break;
381
382		case DATA_TYPE_UINT32_ARRAY:
383			NVPA(elem, uint32_array, uint32_t, ulong_t, "%lu");
384			break;
385
386		case DATA_TYPE_INT64_ARRAY:
387			NVPA(elem, int64_array, int64_t, longlong_t, "%lld");
388			break;
389
390		case DATA_TYPE_UINT64_ARRAY:
391			NVPA(elem, uint64_array, uint64_t, u_longlong_t,
392			    "%llu");
393			break;
394
395		case DATA_TYPE_STRING_ARRAY:
396			NVPA(elem, string_array, char *, char *, "'%s'");
397			break;
398
399		case DATA_TYPE_NVLIST:
400			(void) nvpair_value_nvlist(elem, &nvlist_value);
401			(void) printf("%*s%s:\n", indent, "",
402			    nvpair_name(elem));
403			dump_nvlist(nvlist_value, indent + 4);
404			break;
405
406		case DATA_TYPE_NVLIST_ARRAY:
407			(void) nvpair_value_nvlist_array(elem,
408			    &nvlist_array_value, &count);
409			for (i = 0; i < count; i++) {
410				(void) printf("%*s%s[%u]:\n", indent, "",
411				    nvpair_name(elem), i);
412				dump_nvlist(nvlist_array_value[i], indent + 4);
413			}
414			break;
415
416		default:
417			(void) printf(dgettext(TEXT_DOMAIN, "bad config type "
418			    "%d for %s\n"), nvpair_type(elem),
419			    nvpair_name(elem));
420		}
421	}
422}
423
424/*
425 * Determine if string 'value' matches 'nvp' value.  The 'value' string is
426 * converted, depending on the type of 'nvp', prior to match.  For numeric
427 * types, a radix independent sscanf conversion of 'value' is used. If 'nvp'
428 * is an array type, 'ai' is the index into the array against which we are
429 * checking for match. If nvp is of DATA_TYPE_STRING*, the caller can pass
430 * in a regex_t compilation of value in 'value_regex' to trigger regular
431 * expression string match instead of simple strcmp().
432 *
433 * Return 1 on match, 0 on no-match, and -1 on error.  If the error is
434 * related to value syntax error and 'ep' is non-NULL, *ep will point into
435 * the 'value' string at the location where the error exists.
436 *
437 * NOTE: It may be possible to move the non-regex_t version of this into
438 * common code used by library/kernel/boot.
439 */
440int
441nvpair_value_match_regex(nvpair_t *nvp, int ai,
442    char *value, regex_t *value_regex, char **ep)
443{
444	char	*evalue;
445	uint_t	a_len;
446	int	sr;
447
448	if (ep)
449		*ep = NULL;
450
451	if ((nvp == NULL) || (value == NULL))
452		return (-1);		/* error fail match - invalid args */
453
454	/* make sure array and index combination make sense */
455	if ((nvpair_type_is_array(nvp) && (ai < 0)) ||
456	    (!nvpair_type_is_array(nvp) && (ai >= 0)))
457		return (-1);		/* error fail match - bad index */
458
459	/* non-string values should be single 'chunk' */
460	if ((nvpair_type(nvp) != DATA_TYPE_STRING) &&
461	    (nvpair_type(nvp) != DATA_TYPE_STRING_ARRAY)) {
462		value += strspn(value, " \t");
463		evalue = value + strcspn(value, " \t");
464		if (*evalue) {
465			if (ep)
466				*ep = evalue;
467			return (-1);	/* error fail match - syntax */
468		}
469	}
470
471	sr = EOF;
472	switch (nvpair_type(nvp)) {
473	case DATA_TYPE_STRING: {
474		char	*val;
475
476		/* check string value for match */
477		if (nvpair_value_string(nvp, &val) == 0) {
478			if (value_regex) {
479				if (regexec(value_regex, val,
480				    (size_t)0, NULL, 0) == 0)
481					return (1);	/* match */
482			} else {
483				if (strcmp(value, val) == 0)
484					return (1);	/* match */
485			}
486		}
487		break;
488	}
489	case DATA_TYPE_STRING_ARRAY: {
490		char **val_array;
491
492		/* check indexed string value of array for match */
493		if ((nvpair_value_string_array(nvp, &val_array, &a_len) == 0) &&
494		    (ai < a_len)) {
495			if (value_regex) {
496				if (regexec(value_regex, val_array[ai],
497				    (size_t)0, NULL, 0) == 0)
498					return (1);
499			} else {
500				if (strcmp(value, val_array[ai]) == 0)
501					return (1);
502			}
503		}
504		break;
505	}
506	case DATA_TYPE_BYTE: {
507		uchar_t val, val_arg;
508
509		/* scanf uchar_t from value and check for match */
510		sr = sscanf(value, "%c", &val_arg);
511		if ((sr == 1) && (nvpair_value_byte(nvp, &val) == 0) &&
512		    (val == val_arg))
513			return (1);
514		break;
515	}
516	case DATA_TYPE_BYTE_ARRAY: {
517		uchar_t *val_array, val_arg;
518
519
520		/* check indexed value of array for match */
521		sr = sscanf(value, "%c", &val_arg);
522		if ((sr == 1) &&
523		    (nvpair_value_byte_array(nvp, &val_array, &a_len) == 0) &&
524		    (ai < a_len) &&
525		    (val_array[ai] == val_arg))
526			return (1);
527		break;
528	}
529	case DATA_TYPE_INT8: {
530		int8_t val, val_arg;
531
532		/* scanf int8_t from value and check for match */
533		sr = sscanf(value, "%"SCNi8, &val_arg);
534		if ((sr == 1) &&
535		    (nvpair_value_int8(nvp, &val) == 0) &&
536		    (val == val_arg))
537			return (1);
538		break;
539	}
540	case DATA_TYPE_INT8_ARRAY: {
541		int8_t *val_array, val_arg;
542
543		/* check indexed value of array for match */
544		sr = sscanf(value, "%"SCNi8, &val_arg);
545		if ((sr == 1) &&
546		    (nvpair_value_int8_array(nvp, &val_array, &a_len) == 0) &&
547		    (ai < a_len) &&
548		    (val_array[ai] == val_arg))
549			return (1);
550		break;
551	}
552	case DATA_TYPE_UINT8: {
553		uint8_t val, val_arg;
554
555		/* scanf uint8_t from value and check for match */
556		sr = sscanf(value, "%"SCNi8, (int8_t *)&val_arg);
557		if ((sr == 1) &&
558		    (nvpair_value_uint8(nvp, &val) == 0) &&
559		    (val == val_arg))
560			return (1);
561		break;
562	}
563	case DATA_TYPE_UINT8_ARRAY: {
564		uint8_t *val_array, val_arg;
565
566		/* check indexed value of array for match */
567		sr = sscanf(value, "%"SCNi8, (int8_t *)&val_arg);
568		if ((sr == 1) &&
569		    (nvpair_value_uint8_array(nvp, &val_array, &a_len) == 0) &&
570		    (ai < a_len) &&
571		    (val_array[ai] == val_arg))
572			return (1);
573		break;
574	}
575	case DATA_TYPE_INT16: {
576		int16_t val, val_arg;
577
578		/* scanf int16_t from value and check for match */
579		sr = sscanf(value, "%"SCNi16, &val_arg);
580		if ((sr == 1) &&
581		    (nvpair_value_int16(nvp, &val) == 0) &&
582		    (val == val_arg))
583			return (1);
584		break;
585	}
586	case DATA_TYPE_INT16_ARRAY: {
587		int16_t *val_array, val_arg;
588
589		/* check indexed value of array for match */
590		sr = sscanf(value, "%"SCNi16, &val_arg);
591		if ((sr == 1) &&
592		    (nvpair_value_int16_array(nvp, &val_array, &a_len) == 0) &&
593		    (ai < a_len) &&
594		    (val_array[ai] == val_arg))
595			return (1);
596		break;
597	}
598	case DATA_TYPE_UINT16: {
599		uint16_t val, val_arg;
600
601		/* scanf uint16_t from value and check for match */
602		sr = sscanf(value, "%"SCNi16, (int16_t *)&val_arg);
603		if ((sr == 1) &&
604		    (nvpair_value_uint16(nvp, &val) == 0) &&
605		    (val == val_arg))
606			return (1);
607		break;
608	}
609	case DATA_TYPE_UINT16_ARRAY: {
610		uint16_t *val_array, val_arg;
611
612		/* check indexed value of array for match */
613		sr = sscanf(value, "%"SCNi16, (int16_t *)&val_arg);
614		if ((sr == 1) &&
615		    (nvpair_value_uint16_array(nvp, &val_array, &a_len) == 0) &&
616		    (ai < a_len) &&
617		    (val_array[ai] == val_arg))
618			return (1);
619		break;
620	}
621	case DATA_TYPE_INT32: {
622		int32_t val, val_arg;
623
624		/* scanf int32_t from value and check for match */
625		sr = sscanf(value, "%"SCNi32, &val_arg);
626		if ((sr == 1) &&
627		    (nvpair_value_int32(nvp, &val) == 0) &&
628		    (val == val_arg))
629			return (1);
630		break;
631	}
632	case DATA_TYPE_INT32_ARRAY: {
633		int32_t *val_array, val_arg;
634
635		/* check indexed value of array for match */
636		sr = sscanf(value, "%"SCNi32, &val_arg);
637		if ((sr == 1) &&
638		    (nvpair_value_int32_array(nvp, &val_array, &a_len) == 0) &&
639		    (ai < a_len) &&
640		    (val_array[ai] == val_arg))
641			return (1);
642		break;
643	}
644	case DATA_TYPE_UINT32: {
645		uint32_t val, val_arg;
646
647		/* scanf uint32_t from value and check for match */
648		sr = sscanf(value, "%"SCNi32, (int32_t *)&val_arg);
649		if ((sr == 1) &&
650		    (nvpair_value_uint32(nvp, &val) == 0) &&
651		    (val == val_arg))
652			return (1);
653		break;
654	}
655	case DATA_TYPE_UINT32_ARRAY: {
656		uint32_t *val_array, val_arg;
657
658		/* check indexed value of array for match */
659		sr = sscanf(value, "%"SCNi32, (int32_t *)&val_arg);
660		if ((sr == 1) &&
661		    (nvpair_value_uint32_array(nvp, &val_array, &a_len) == 0) &&
662		    (ai < a_len) &&
663		    (val_array[ai] == val_arg))
664			return (1);
665		break;
666	}
667	case DATA_TYPE_INT64: {
668		int64_t val, val_arg;
669
670		/* scanf int64_t from value and check for match */
671		sr = sscanf(value, "%"SCNi64, &val_arg);
672		if ((sr == 1) &&
673		    (nvpair_value_int64(nvp, &val) == 0) &&
674		    (val == val_arg))
675			return (1);
676		break;
677	}
678	case DATA_TYPE_INT64_ARRAY: {
679		int64_t *val_array, val_arg;
680
681		/* check indexed value of array for match */
682		sr = sscanf(value, "%"SCNi64, &val_arg);
683		if ((sr == 1) &&
684		    (nvpair_value_int64_array(nvp, &val_array, &a_len) == 0) &&
685		    (ai < a_len) &&
686		    (val_array[ai] == val_arg))
687				return (1);
688		break;
689	}
690	case DATA_TYPE_UINT64: {
691		uint64_t val_arg, val;
692
693		/* scanf uint64_t from value and check for match */
694		sr = sscanf(value, "%"SCNi64, (int64_t *)&val_arg);
695		if ((sr == 1) &&
696		    (nvpair_value_uint64(nvp, &val) == 0) &&
697		    (val == val_arg))
698			return (1);
699		break;
700	}
701	case DATA_TYPE_UINT64_ARRAY: {
702		uint64_t *val_array, val_arg;
703
704		/* check indexed value of array for match */
705		sr = sscanf(value, "%"SCNi64, (int64_t *)&val_arg);
706		if ((sr == 1) &&
707		    (nvpair_value_uint64_array(nvp, &val_array, &a_len) == 0) &&
708		    (ai < a_len) &&
709		    (val_array[ai] == val_arg))
710			return (1);
711		break;
712	}
713	case DATA_TYPE_BOOLEAN_VALUE: {
714		boolean_t val, val_arg;
715
716		/* scanf boolean_t from value and check for match */
717		sr = sscanf(value, "%"SCNi32, &val_arg);
718		if ((sr == 1) &&
719		    (nvpair_value_boolean_value(nvp, &val) == 0) &&
720		    (val == val_arg))
721			return (1);
722		break;
723	}
724	case DATA_TYPE_BOOLEAN_ARRAY: {
725		boolean_t *val_array, val_arg;
726
727		/* check indexed value of array for match */
728		sr = sscanf(value, "%"SCNi32, &val_arg);
729		if ((sr == 1) &&
730		    (nvpair_value_boolean_array(nvp,
731		    &val_array, &a_len) == 0) &&
732		    (ai < a_len) &&
733		    (val_array[ai] == val_arg))
734			return (1);
735		break;
736	}
737	case DATA_TYPE_HRTIME:
738	case DATA_TYPE_NVLIST:
739	case DATA_TYPE_NVLIST_ARRAY:
740	case DATA_TYPE_BOOLEAN:
741	case DATA_TYPE_DOUBLE:
742	case DATA_TYPE_UNKNOWN:
743	default:
744		/*
745		 * unknown/unsupported data type
746		 */
747		return (-1);		/* error fail match */
748	}
749
750	/*
751	 * check to see if sscanf failed conversion, return approximate
752	 * pointer to problem
753	 */
754	if (sr != 1) {
755		if (ep)
756			*ep = value;
757		return (-1);		/* error fail match  - syntax */
758	}
759
760	return (0);			/* fail match */
761}
762
763int
764nvpair_value_match(nvpair_t *nvp, int ai, char *value, char **ep)
765{
766	return (nvpair_value_match_regex(nvp, ai, value, NULL, ep));
767}
768