nvpair.c revision 324830
1/*-
2 * Copyright (c) 2009-2013 The FreeBSD Foundation
3 * Copyright (c) 2013-2015 Mariusz Zaborski <oshogbo@FreeBSD.org>
4 * All rights reserved.
5 *
6 * This software was developed by Pawel Jakub Dawidek under sponsorship from
7 * the FreeBSD Foundation.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 *    notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 *    notice, this list of conditions and the following disclaimer in the
16 *    documentation and/or other materials provided with the distribution.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 */
30
31#include <sys/cdefs.h>
32__FBSDID("$FreeBSD: stable/11/sys/contrib/libnv/nvpair.c 324830 2017-10-21 19:33:31Z oshogbo $");
33
34#include <sys/param.h>
35#include <sys/endian.h>
36#include <sys/queue.h>
37
38#ifdef _KERNEL
39
40#include <sys/errno.h>
41#include <sys/lock.h>
42#include <sys/malloc.h>
43#include <sys/systm.h>
44
45#include <machine/stdarg.h>
46
47#else
48#include <errno.h>
49#include <fcntl.h>
50#include <stdarg.h>
51#include <stdbool.h>
52#include <stdint.h>
53#include <stdlib.h>
54#include <string.h>
55#include <unistd.h>
56
57#include "common_impl.h"
58#endif
59
60#ifdef HAVE_PJDLOG
61#include <pjdlog.h>
62#endif
63
64#include <sys/nv.h>
65
66#include "nv_impl.h"
67#include "nvlist_impl.h"
68#include "nvpair_impl.h"
69
70#ifndef	HAVE_PJDLOG
71#ifdef _KERNEL
72#define	PJDLOG_ASSERT(...)		MPASS(__VA_ARGS__)
73#define	PJDLOG_RASSERT(expr, ...)	KASSERT(expr, (__VA_ARGS__))
74#define	PJDLOG_ABORT(...)		panic(__VA_ARGS__)
75#else
76#include <assert.h>
77#define	PJDLOG_ASSERT(...)		assert(__VA_ARGS__)
78#define	PJDLOG_RASSERT(expr, ...)	assert(expr)
79#define	PJDLOG_ABORT(...)		abort()
80#endif
81#endif
82
83#define	NVPAIR_MAGIC	0x6e7670	/* "nvp" */
84struct nvpair {
85	int		 nvp_magic;
86	char		*nvp_name;
87	int		 nvp_type;
88	uint64_t	 nvp_data;
89	size_t		 nvp_datasize;
90	size_t		 nvp_nitems;	/* Used only for array types. */
91	nvlist_t	*nvp_list;
92	TAILQ_ENTRY(nvpair) nvp_next;
93};
94
95#define	NVPAIR_ASSERT(nvp)	do {					\
96	PJDLOG_ASSERT((nvp) != NULL);					\
97	PJDLOG_ASSERT((nvp)->nvp_magic == NVPAIR_MAGIC);		\
98} while (0)
99
100struct nvpair_header {
101	uint8_t		nvph_type;
102	uint16_t	nvph_namesize;
103	uint64_t	nvph_datasize;
104	uint64_t	nvph_nitems;
105} __packed;
106
107
108void
109nvpair_assert(const nvpair_t *nvp)
110{
111
112	NVPAIR_ASSERT(nvp);
113}
114
115static nvpair_t *
116nvpair_allocv(const char *name, int type, uint64_t data, size_t datasize,
117    size_t nitems)
118{
119	nvpair_t *nvp;
120	size_t namelen;
121
122	PJDLOG_ASSERT(type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST);
123
124	namelen = strlen(name);
125	if (namelen >= NV_NAME_MAX) {
126		ERRNO_SET(ENAMETOOLONG);
127		return (NULL);
128	}
129
130	nvp = nv_calloc(1, sizeof(*nvp) + namelen + 1);
131	if (nvp != NULL) {
132		nvp->nvp_name = (char *)(nvp + 1);
133		memcpy(nvp->nvp_name, name, namelen);
134		nvp->nvp_name[namelen] = '\0';
135		nvp->nvp_type = type;
136		nvp->nvp_data = data;
137		nvp->nvp_datasize = datasize;
138		nvp->nvp_nitems = nitems;
139		nvp->nvp_magic = NVPAIR_MAGIC;
140	}
141
142	return (nvp);
143}
144
145nvlist_t *
146nvpair_nvlist(const nvpair_t *nvp)
147{
148
149	NVPAIR_ASSERT(nvp);
150
151	return (nvp->nvp_list);
152}
153
154nvpair_t *
155nvpair_next(const nvpair_t *nvp)
156{
157
158	NVPAIR_ASSERT(nvp);
159	PJDLOG_ASSERT(nvp->nvp_list != NULL);
160
161	return (TAILQ_NEXT(nvp, nvp_next));
162}
163
164nvpair_t *
165nvpair_prev(const nvpair_t *nvp)
166{
167
168	NVPAIR_ASSERT(nvp);
169	PJDLOG_ASSERT(nvp->nvp_list != NULL);
170
171	return (TAILQ_PREV(nvp, nvl_head, nvp_next));
172}
173
174void
175nvpair_insert(struct nvl_head *head, nvpair_t *nvp, nvlist_t *nvl)
176{
177
178	NVPAIR_ASSERT(nvp);
179	PJDLOG_ASSERT(nvp->nvp_list == NULL);
180	PJDLOG_ASSERT((nvlist_flags(nvl) & NV_FLAG_NO_UNIQUE) != 0 ||
181	    !nvlist_exists(nvl, nvpair_name(nvp)));
182
183	TAILQ_INSERT_TAIL(head, nvp, nvp_next);
184	nvp->nvp_list = nvl;
185}
186
187static void
188nvpair_remove_nvlist(nvpair_t *nvp)
189{
190	nvlist_t *nvl;
191
192	/* XXX: DECONST is bad, mkay? */
193	nvl = __DECONST(nvlist_t *, nvpair_get_nvlist(nvp));
194	PJDLOG_ASSERT(nvl != NULL);
195	nvlist_set_parent(nvl, NULL);
196}
197
198static void
199nvpair_remove_nvlist_array(nvpair_t *nvp)
200{
201	nvlist_t **nvlarray;
202	size_t count, i;
203
204	/* XXX: DECONST is bad, mkay? */
205	nvlarray = __DECONST(nvlist_t **,
206	    nvpair_get_nvlist_array(nvp, &count));
207	for (i = 0; i < count; i++)
208		nvlist_set_array_next(nvlarray[i], NULL);
209}
210
211void
212nvpair_remove(struct nvl_head *head, nvpair_t *nvp, const nvlist_t *nvl)
213{
214
215	NVPAIR_ASSERT(nvp);
216	PJDLOG_ASSERT(nvp->nvp_list == nvl);
217
218	if (nvpair_type(nvp) == NV_TYPE_NVLIST)
219		nvpair_remove_nvlist(nvp);
220	else if (nvpair_type(nvp) == NV_TYPE_NVLIST_ARRAY)
221		nvpair_remove_nvlist_array(nvp);
222
223	TAILQ_REMOVE(head, nvp, nvp_next);
224	nvp->nvp_list = NULL;
225}
226
227nvpair_t *
228nvpair_clone(const nvpair_t *nvp)
229{
230	nvpair_t *newnvp;
231	const char *name;
232	const void *data;
233	size_t datasize;
234
235	NVPAIR_ASSERT(nvp);
236
237	name = nvpair_name(nvp);
238
239	switch (nvpair_type(nvp)) {
240	case NV_TYPE_NULL:
241		newnvp = nvpair_create_null(name);
242		break;
243	case NV_TYPE_BOOL:
244		newnvp = nvpair_create_bool(name, nvpair_get_bool(nvp));
245		break;
246	case NV_TYPE_NUMBER:
247		newnvp = nvpair_create_number(name, nvpair_get_number(nvp));
248		break;
249	case NV_TYPE_STRING:
250		newnvp = nvpair_create_string(name, nvpair_get_string(nvp));
251		break;
252	case NV_TYPE_NVLIST:
253		newnvp = nvpair_create_nvlist(name, nvpair_get_nvlist(nvp));
254		break;
255	case NV_TYPE_BINARY:
256		data = nvpair_get_binary(nvp, &datasize);
257		newnvp = nvpair_create_binary(name, data, datasize);
258		break;
259	case NV_TYPE_BOOL_ARRAY:
260		data = nvpair_get_bool_array(nvp, &datasize);
261		newnvp = nvpair_create_bool_array(name, data, datasize);
262		break;
263	case NV_TYPE_NUMBER_ARRAY:
264		data = nvpair_get_number_array(nvp, &datasize);
265		newnvp = nvpair_create_number_array(name, data, datasize);
266		break;
267	case NV_TYPE_STRING_ARRAY:
268		data = nvpair_get_string_array(nvp, &datasize);
269		newnvp = nvpair_create_string_array(name, data, datasize);
270		break;
271	case NV_TYPE_NVLIST_ARRAY:
272		data = nvpair_get_nvlist_array(nvp, &datasize);
273		newnvp = nvpair_create_nvlist_array(name, data, datasize);
274		break;
275#ifndef _KERNEL
276	case NV_TYPE_DESCRIPTOR:
277		newnvp = nvpair_create_descriptor(name,
278		    nvpair_get_descriptor(nvp));
279		break;
280	case NV_TYPE_DESCRIPTOR_ARRAY:
281		data = nvpair_get_descriptor_array(nvp, &datasize);
282		newnvp = nvpair_create_descriptor_array(name, data, datasize);
283		break;
284#endif
285	default:
286		PJDLOG_ABORT("Unknown type: %d.", nvpair_type(nvp));
287	}
288
289	return (newnvp);
290}
291
292size_t
293nvpair_header_size(void)
294{
295
296	return (sizeof(struct nvpair_header));
297}
298
299size_t
300nvpair_size(const nvpair_t *nvp)
301{
302
303	NVPAIR_ASSERT(nvp);
304
305	return (nvp->nvp_datasize);
306}
307
308unsigned char *
309nvpair_pack_header(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp)
310{
311	struct nvpair_header nvphdr;
312	size_t namesize;
313
314	NVPAIR_ASSERT(nvp);
315
316	nvphdr.nvph_type = nvp->nvp_type;
317	namesize = strlen(nvp->nvp_name) + 1;
318	PJDLOG_ASSERT(namesize > 0 && namesize <= UINT16_MAX);
319	nvphdr.nvph_namesize = namesize;
320	nvphdr.nvph_datasize = nvp->nvp_datasize;
321	nvphdr.nvph_nitems = nvp->nvp_nitems;
322	PJDLOG_ASSERT(*leftp >= sizeof(nvphdr));
323	memcpy(ptr, &nvphdr, sizeof(nvphdr));
324	ptr += sizeof(nvphdr);
325	*leftp -= sizeof(nvphdr);
326
327	PJDLOG_ASSERT(*leftp >= namesize);
328	memcpy(ptr, nvp->nvp_name, namesize);
329	ptr += namesize;
330	*leftp -= namesize;
331
332	return (ptr);
333}
334
335unsigned char *
336nvpair_pack_null(const nvpair_t *nvp, unsigned char *ptr,
337    size_t *leftp __unused)
338{
339
340	NVPAIR_ASSERT(nvp);
341	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NULL);
342
343	return (ptr);
344}
345
346unsigned char *
347nvpair_pack_bool(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp)
348{
349	uint8_t value;
350
351	NVPAIR_ASSERT(nvp);
352	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BOOL);
353
354	value = (uint8_t)nvp->nvp_data;
355
356	PJDLOG_ASSERT(*leftp >= sizeof(value));
357	memcpy(ptr, &value, sizeof(value));
358	ptr += sizeof(value);
359	*leftp -= sizeof(value);
360
361	return (ptr);
362}
363
364unsigned char *
365nvpair_pack_number(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp)
366{
367	uint64_t value;
368
369	NVPAIR_ASSERT(nvp);
370	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NUMBER);
371
372	value = (uint64_t)nvp->nvp_data;
373
374	PJDLOG_ASSERT(*leftp >= sizeof(value));
375	memcpy(ptr, &value, sizeof(value));
376	ptr += sizeof(value);
377	*leftp -= sizeof(value);
378
379	return (ptr);
380}
381
382unsigned char *
383nvpair_pack_string(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp)
384{
385
386	NVPAIR_ASSERT(nvp);
387	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING);
388
389	PJDLOG_ASSERT(*leftp >= nvp->nvp_datasize);
390	memcpy(ptr, (const void *)(intptr_t)nvp->nvp_data, nvp->nvp_datasize);
391	ptr += nvp->nvp_datasize;
392	*leftp -= nvp->nvp_datasize;
393
394	return (ptr);
395}
396
397unsigned char *
398nvpair_pack_nvlist_up(unsigned char *ptr, size_t *leftp)
399{
400	struct nvpair_header nvphdr;
401	size_t namesize;
402	const char *name = "";
403
404	namesize = 1;
405	nvphdr.nvph_type = NV_TYPE_NVLIST_UP;
406	nvphdr.nvph_namesize = namesize;
407	nvphdr.nvph_datasize = 0;
408	nvphdr.nvph_nitems = 0;
409	PJDLOG_ASSERT(*leftp >= sizeof(nvphdr));
410	memcpy(ptr, &nvphdr, sizeof(nvphdr));
411	ptr += sizeof(nvphdr);
412	*leftp -= sizeof(nvphdr);
413
414	PJDLOG_ASSERT(*leftp >= namesize);
415	memcpy(ptr, name, namesize);
416	ptr += namesize;
417	*leftp -= namesize;
418
419	return (ptr);
420}
421
422unsigned char *
423nvpair_pack_nvlist_array_next(unsigned char *ptr, size_t *leftp)
424{
425	struct nvpair_header nvphdr;
426	size_t namesize;
427	const char *name = "";
428
429	namesize = 1;
430	nvphdr.nvph_type = NV_TYPE_NVLIST_ARRAY_NEXT;
431	nvphdr.nvph_namesize = namesize;
432	nvphdr.nvph_datasize = 0;
433	nvphdr.nvph_nitems = 0;
434	PJDLOG_ASSERT(*leftp >= sizeof(nvphdr));
435	memcpy(ptr, &nvphdr, sizeof(nvphdr));
436	ptr += sizeof(nvphdr);
437	*leftp -= sizeof(nvphdr);
438
439	PJDLOG_ASSERT(*leftp >= namesize);
440	memcpy(ptr, name, namesize);
441	ptr += namesize;
442	*leftp -= namesize;
443
444	return (ptr);
445}
446
447#ifndef _KERNEL
448unsigned char *
449nvpair_pack_descriptor(const nvpair_t *nvp, unsigned char *ptr, int64_t *fdidxp,
450    size_t *leftp)
451{
452	int64_t value;
453
454	NVPAIR_ASSERT(nvp);
455	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR);
456
457	value = (int64_t)nvp->nvp_data;
458	if (value != -1) {
459		/*
460		 * If there is a real descriptor here, we change its number
461		 * to position in the array of descriptors send via control
462		 * message.
463		 */
464		PJDLOG_ASSERT(fdidxp != NULL);
465
466		value = *fdidxp;
467		(*fdidxp)++;
468	}
469
470	PJDLOG_ASSERT(*leftp >= sizeof(value));
471	memcpy(ptr, &value, sizeof(value));
472	ptr += sizeof(value);
473	*leftp -= sizeof(value);
474
475	return (ptr);
476}
477#endif
478
479unsigned char *
480nvpair_pack_binary(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp)
481{
482
483	NVPAIR_ASSERT(nvp);
484	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BINARY);
485
486	PJDLOG_ASSERT(*leftp >= nvp->nvp_datasize);
487	memcpy(ptr, (const void *)(intptr_t)nvp->nvp_data, nvp->nvp_datasize);
488	ptr += nvp->nvp_datasize;
489	*leftp -= nvp->nvp_datasize;
490
491	return (ptr);
492}
493
494unsigned char *
495nvpair_pack_bool_array(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp)
496{
497
498	NVPAIR_ASSERT(nvp);
499	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BOOL_ARRAY);
500	PJDLOG_ASSERT(*leftp >= nvp->nvp_datasize);
501
502	memcpy(ptr, (const void *)(intptr_t)nvp->nvp_data, nvp->nvp_datasize);
503	ptr += nvp->nvp_datasize;
504	*leftp -= nvp->nvp_datasize;
505
506	return (ptr);
507}
508
509unsigned char *
510nvpair_pack_number_array(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp)
511{
512
513	NVPAIR_ASSERT(nvp);
514	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NUMBER_ARRAY);
515	PJDLOG_ASSERT(*leftp >= nvp->nvp_datasize);
516
517	memcpy(ptr, (const void *)(intptr_t)nvp->nvp_data, nvp->nvp_datasize);
518	ptr += nvp->nvp_datasize;
519	*leftp -= nvp->nvp_datasize;
520
521	return (ptr);
522}
523
524unsigned char *
525nvpair_pack_string_array(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp)
526{
527	unsigned int ii;
528	size_t size, len;
529	const char * const *array;
530
531	NVPAIR_ASSERT(nvp);
532	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING_ARRAY);
533	PJDLOG_ASSERT(*leftp >= nvp->nvp_datasize);
534
535	size = 0;
536	array = nvpair_get_string_array(nvp, NULL);
537	PJDLOG_ASSERT(array != NULL);
538
539	for (ii = 0; ii < nvp->nvp_nitems; ii++) {
540		len = strlen(array[ii]) + 1;
541		PJDLOG_ASSERT(*leftp >= len);
542
543		memcpy(ptr, (const void *)array[ii], len);
544		size += len;
545		ptr += len;
546		*leftp -= len;
547	}
548
549	PJDLOG_ASSERT(size == nvp->nvp_datasize);
550
551	return (ptr);
552}
553
554#ifndef _KERNEL
555unsigned char *
556nvpair_pack_descriptor_array(const nvpair_t *nvp, unsigned char *ptr,
557    int64_t *fdidxp, size_t *leftp)
558{
559	int64_t value;
560	const int *array;
561	unsigned int ii;
562
563	NVPAIR_ASSERT(nvp);
564	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR_ARRAY);
565	PJDLOG_ASSERT(*leftp >= nvp->nvp_datasize);
566
567	array = nvpair_get_descriptor_array(nvp, NULL);
568	PJDLOG_ASSERT(array != NULL);
569
570	for (ii = 0; ii < nvp->nvp_nitems; ii++) {
571		PJDLOG_ASSERT(*leftp >= sizeof(value));
572
573		value = array[ii];
574		if (value != -1) {
575			/*
576			 * If there is a real descriptor here, we change its
577			 * number to position in the array of descriptors send
578			 * via control message.
579			 */
580			PJDLOG_ASSERT(fdidxp != NULL);
581
582			value = *fdidxp;
583			(*fdidxp)++;
584		}
585		memcpy(ptr, &value, sizeof(value));
586		ptr += sizeof(value);
587		*leftp -= sizeof(value);
588	}
589
590	return (ptr);
591}
592#endif
593
594void
595nvpair_init_datasize(nvpair_t *nvp)
596{
597
598	NVPAIR_ASSERT(nvp);
599
600	if (nvp->nvp_type == NV_TYPE_NVLIST) {
601		if (nvp->nvp_data == 0) {
602			nvp->nvp_datasize = 0;
603		} else {
604			nvp->nvp_datasize =
605			    nvlist_size((const nvlist_t *)(intptr_t)nvp->nvp_data);
606		}
607	}
608}
609
610const unsigned char *
611nvpair_unpack_header(bool isbe, nvpair_t *nvp, const unsigned char *ptr,
612    size_t *leftp)
613{
614	struct nvpair_header nvphdr;
615
616	if (*leftp < sizeof(nvphdr))
617		goto fail;
618
619	memcpy(&nvphdr, ptr, sizeof(nvphdr));
620	ptr += sizeof(nvphdr);
621	*leftp -= sizeof(nvphdr);
622
623#if NV_TYPE_FIRST > 0
624	if (nvphdr.nvph_type < NV_TYPE_FIRST)
625		goto fail;
626#endif
627	if (nvphdr.nvph_type > NV_TYPE_LAST &&
628	    nvphdr.nvph_type != NV_TYPE_NVLIST_UP &&
629	    nvphdr.nvph_type != NV_TYPE_NVLIST_ARRAY_NEXT) {
630		goto fail;
631	}
632
633#if BYTE_ORDER == BIG_ENDIAN
634	if (!isbe) {
635		nvphdr.nvph_namesize = le16toh(nvphdr.nvph_namesize);
636		nvphdr.nvph_datasize = le64toh(nvphdr.nvph_datasize);
637	}
638#else
639	if (isbe) {
640		nvphdr.nvph_namesize = be16toh(nvphdr.nvph_namesize);
641		nvphdr.nvph_datasize = be64toh(nvphdr.nvph_datasize);
642	}
643#endif
644
645	if (nvphdr.nvph_namesize > NV_NAME_MAX)
646		goto fail;
647	if (*leftp < nvphdr.nvph_namesize)
648		goto fail;
649	if (nvphdr.nvph_namesize < 1)
650		goto fail;
651	if (strnlen((const char *)ptr, nvphdr.nvph_namesize) !=
652	    (size_t)(nvphdr.nvph_namesize - 1)) {
653		goto fail;
654	}
655
656	memcpy(nvp->nvp_name, ptr, nvphdr.nvph_namesize);
657	ptr += nvphdr.nvph_namesize;
658	*leftp -= nvphdr.nvph_namesize;
659
660	if (*leftp < nvphdr.nvph_datasize)
661		goto fail;
662
663	nvp->nvp_type = nvphdr.nvph_type;
664	nvp->nvp_data = 0;
665	nvp->nvp_datasize = nvphdr.nvph_datasize;
666	nvp->nvp_nitems = nvphdr.nvph_nitems;
667
668	return (ptr);
669fail:
670	ERRNO_SET(EINVAL);
671	return (NULL);
672}
673
674const unsigned char *
675nvpair_unpack_null(bool isbe __unused, nvpair_t *nvp, const unsigned char *ptr,
676    size_t *leftp __unused)
677{
678
679	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NULL);
680
681	if (nvp->nvp_datasize != 0) {
682		ERRNO_SET(EINVAL);
683		return (NULL);
684	}
685
686	return (ptr);
687}
688
689const unsigned char *
690nvpair_unpack_bool(bool isbe __unused, nvpair_t *nvp, const unsigned char *ptr,
691    size_t *leftp)
692{
693	uint8_t value;
694
695	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BOOL);
696
697	if (nvp->nvp_datasize != sizeof(value)) {
698		ERRNO_SET(EINVAL);
699		return (NULL);
700	}
701	if (*leftp < sizeof(value)) {
702		ERRNO_SET(EINVAL);
703		return (NULL);
704	}
705
706	memcpy(&value, ptr, sizeof(value));
707	ptr += sizeof(value);
708	*leftp -= sizeof(value);
709
710	if (value != 0 && value != 1) {
711		ERRNO_SET(EINVAL);
712		return (NULL);
713	}
714
715	nvp->nvp_data = (uint64_t)value;
716
717	return (ptr);
718}
719
720const unsigned char *
721nvpair_unpack_number(bool isbe, nvpair_t *nvp, const unsigned char *ptr,
722     size_t *leftp)
723{
724
725	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NUMBER);
726
727	if (nvp->nvp_datasize != sizeof(uint64_t)) {
728		ERRNO_SET(EINVAL);
729		return (NULL);
730	}
731	if (*leftp < sizeof(uint64_t)) {
732		ERRNO_SET(EINVAL);
733		return (NULL);
734	}
735
736	if (isbe)
737		nvp->nvp_data = be64dec(ptr);
738	else
739		nvp->nvp_data = le64dec(ptr);
740
741	ptr += sizeof(uint64_t);
742	*leftp -= sizeof(uint64_t);
743
744	return (ptr);
745}
746
747const unsigned char *
748nvpair_unpack_string(bool isbe __unused, nvpair_t *nvp,
749    const unsigned char *ptr, size_t *leftp)
750{
751
752	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING);
753
754	if (*leftp < nvp->nvp_datasize || nvp->nvp_datasize == 0) {
755		ERRNO_SET(EINVAL);
756		return (NULL);
757	}
758
759	if (strnlen((const char *)ptr, nvp->nvp_datasize) !=
760	    nvp->nvp_datasize - 1) {
761		ERRNO_SET(EINVAL);
762		return (NULL);
763	}
764
765	nvp->nvp_data = (uint64_t)(uintptr_t)nv_strdup((const char *)ptr);
766	if (nvp->nvp_data == 0)
767		return (NULL);
768
769	ptr += nvp->nvp_datasize;
770	*leftp -= nvp->nvp_datasize;
771
772	return (ptr);
773}
774
775const unsigned char *
776nvpair_unpack_nvlist(bool isbe __unused, nvpair_t *nvp,
777    const unsigned char *ptr, size_t *leftp, size_t nfds, nvlist_t **child)
778{
779	nvlist_t *value;
780
781	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST);
782
783	if (*leftp < nvp->nvp_datasize || nvp->nvp_datasize == 0) {
784		ERRNO_SET(EINVAL);
785		return (NULL);
786	}
787
788	value = nvlist_create(0);
789	if (value == NULL)
790		return (NULL);
791
792	ptr = nvlist_unpack_header(value, ptr, nfds, NULL, leftp);
793	if (ptr == NULL)
794		return (NULL);
795
796	nvp->nvp_data = (uint64_t)(uintptr_t)value;
797	*child = value;
798
799	return (ptr);
800}
801
802#ifndef _KERNEL
803const unsigned char *
804nvpair_unpack_descriptor(bool isbe, nvpair_t *nvp, const unsigned char *ptr,
805    size_t *leftp, const int *fds, size_t nfds)
806{
807	int64_t idx;
808
809	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR);
810
811	if (nvp->nvp_datasize != sizeof(idx)) {
812		ERRNO_SET(EINVAL);
813		return (NULL);
814	}
815	if (*leftp < sizeof(idx)) {
816		ERRNO_SET(EINVAL);
817		return (NULL);
818	}
819
820	if (isbe)
821		idx = be64dec(ptr);
822	else
823		idx = le64dec(ptr);
824
825	if (idx < 0) {
826		ERRNO_SET(EINVAL);
827		return (NULL);
828	}
829
830	if ((size_t)idx >= nfds) {
831		ERRNO_SET(EINVAL);
832		return (NULL);
833	}
834
835	nvp->nvp_data = (uint64_t)fds[idx];
836
837	ptr += sizeof(idx);
838	*leftp -= sizeof(idx);
839
840	return (ptr);
841}
842#endif
843
844const unsigned char *
845nvpair_unpack_binary(bool isbe __unused, nvpair_t *nvp,
846    const unsigned char *ptr, size_t *leftp)
847{
848	void *value;
849
850	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BINARY);
851
852	if (*leftp < nvp->nvp_datasize || nvp->nvp_datasize == 0) {
853		ERRNO_SET(EINVAL);
854		return (NULL);
855	}
856
857	value = nv_malloc(nvp->nvp_datasize);
858	if (value == NULL)
859		return (NULL);
860
861	memcpy(value, ptr, nvp->nvp_datasize);
862	ptr += nvp->nvp_datasize;
863	*leftp -= nvp->nvp_datasize;
864
865	nvp->nvp_data = (uint64_t)(uintptr_t)value;
866
867	return (ptr);
868}
869
870const unsigned char *
871nvpair_unpack_bool_array(bool isbe __unused, nvpair_t *nvp,
872    const unsigned char *ptr, size_t *leftp)
873{
874	uint8_t *value;
875	size_t size;
876	unsigned int i;
877
878	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BOOL_ARRAY);
879
880	size = sizeof(*value) * nvp->nvp_nitems;
881	if (nvp->nvp_datasize != size || *leftp < size ||
882	    nvp->nvp_nitems == 0 || size < nvp->nvp_nitems) {
883		ERRNO_SET(EINVAL);
884		return (NULL);
885	}
886
887	value = nv_malloc(size);
888	if (value == NULL)
889		return (NULL);
890
891	for (i = 0; i < nvp->nvp_nitems; i++) {
892		value[i] = *(const uint8_t *)ptr;
893
894		ptr += sizeof(*value);
895		*leftp -= sizeof(*value);
896	}
897
898	nvp->nvp_data = (uint64_t)(uintptr_t)value;
899
900	return (ptr);
901}
902
903const unsigned char *
904nvpair_unpack_number_array(bool isbe, nvpair_t *nvp, const unsigned char *ptr,
905     size_t *leftp)
906{
907	uint64_t *value;
908	size_t size;
909	unsigned int i;
910
911	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NUMBER_ARRAY);
912
913	size = sizeof(*value) * nvp->nvp_nitems;
914	if (nvp->nvp_datasize != size || *leftp < size ||
915	    nvp->nvp_nitems == 0 || size < nvp->nvp_nitems) {
916		ERRNO_SET(EINVAL);
917		return (NULL);
918	}
919
920	value = nv_malloc(size);
921	if (value == NULL)
922		return (NULL);
923
924	for (i = 0; i < nvp->nvp_nitems; i++) {
925		if (isbe)
926			value[i] = be64dec(ptr);
927		else
928			value[i] = le64dec(ptr);
929
930		ptr += sizeof(*value);
931		*leftp -= sizeof(*value);
932	}
933
934	nvp->nvp_data = (uint64_t)(uintptr_t)value;
935
936	return (ptr);
937}
938
939const unsigned char *
940nvpair_unpack_string_array(bool isbe __unused, nvpair_t *nvp,
941    const unsigned char *ptr, size_t *leftp)
942{
943	ssize_t size;
944	size_t len;
945	const char *tmp;
946	char **value;
947	unsigned int ii, j;
948
949	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING_ARRAY);
950
951	if (*leftp < nvp->nvp_datasize || nvp->nvp_datasize == 0 ||
952	    nvp->nvp_nitems == 0) {
953		ERRNO_SET(EINVAL);
954		return (NULL);
955	}
956
957	size = nvp->nvp_datasize;
958	tmp = (const char *)ptr;
959	for (ii = 0; ii < nvp->nvp_nitems; ii++) {
960		len = strnlen(tmp, size - 1) + 1;
961		size -= len;
962		if (size < 0) {
963			ERRNO_SET(EINVAL);
964			return (NULL);
965		}
966		tmp += len;
967	}
968	if (size != 0) {
969		ERRNO_SET(EINVAL);
970		return (NULL);
971	}
972
973	value = nv_malloc(sizeof(*value) * nvp->nvp_nitems);
974	if (value == NULL)
975		return (NULL);
976
977	for (ii = 0; ii < nvp->nvp_nitems; ii++) {
978		value[ii] = nv_strdup((const char *)ptr);
979		if (value[ii] == NULL)
980			goto out;
981		len = strlen(value[ii]) + 1;
982		ptr += len;
983		*leftp -= len;
984	}
985	nvp->nvp_data = (uint64_t)(uintptr_t)value;
986
987	return (ptr);
988out:
989	for (j = 0; j < ii; j++)
990		nv_free(value[j]);
991	nv_free(value);
992	return (NULL);
993}
994
995#ifndef _KERNEL
996const unsigned char *
997nvpair_unpack_descriptor_array(bool isbe, nvpair_t *nvp,
998    const unsigned char *ptr, size_t *leftp, const int *fds, size_t nfds)
999{
1000	int64_t idx;
1001	size_t size;
1002	unsigned int ii;
1003	int *array;
1004
1005	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR_ARRAY);
1006
1007	size = sizeof(idx) * nvp->nvp_nitems;
1008	if (nvp->nvp_datasize != size || *leftp < size ||
1009	    nvp->nvp_nitems == 0 || size < nvp->nvp_nitems) {
1010		ERRNO_SET(EINVAL);
1011		return (NULL);
1012	}
1013
1014	array = (int *)nv_malloc(size);
1015	if (array == NULL)
1016		return (NULL);
1017
1018	for (ii = 0; ii < nvp->nvp_nitems; ii++) {
1019		if (isbe)
1020			idx = be64dec(ptr);
1021		else
1022			idx = le64dec(ptr);
1023
1024		if (idx < 0) {
1025			ERRNO_SET(EINVAL);
1026			nv_free(array);
1027			return (NULL);
1028		}
1029
1030		if ((size_t)idx >= nfds) {
1031			ERRNO_SET(EINVAL);
1032			nv_free(array);
1033			return (NULL);
1034		}
1035
1036		array[ii] = (uint64_t)fds[idx];
1037
1038		ptr += sizeof(idx);
1039		*leftp -= sizeof(idx);
1040	}
1041
1042	nvp->nvp_data = (uint64_t)(uintptr_t)array;
1043
1044	return (ptr);
1045}
1046#endif
1047
1048const unsigned char *
1049nvpair_unpack_nvlist_array(bool isbe __unused, nvpair_t *nvp,
1050    const unsigned char *ptr, size_t *leftp, nvlist_t **firstel)
1051{
1052	nvlist_t **value;
1053	nvpair_t *tmpnvp;
1054	unsigned int ii, j;
1055	size_t sizeup;
1056
1057	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST_ARRAY);
1058
1059	sizeup = sizeof(struct nvpair_header) * nvp->nvp_nitems;
1060	if (nvp->nvp_nitems == 0 || sizeup < nvp->nvp_nitems ||
1061	    sizeup > *leftp) {
1062		ERRNO_SET(EINVAL);
1063		return (NULL);
1064	}
1065
1066	value = nv_malloc(nvp->nvp_nitems * sizeof(*value));
1067	if (value == NULL)
1068		return (NULL);
1069
1070	for (ii = 0; ii < nvp->nvp_nitems; ii++) {
1071		value[ii] = nvlist_create(0);
1072		if (value[ii] == NULL)
1073			goto fail;
1074		if (ii > 0) {
1075			tmpnvp = nvpair_allocv(" ", NV_TYPE_NVLIST,
1076			    (uint64_t)(uintptr_t)value[ii], 0, 0);
1077			if (tmpnvp == NULL)
1078				goto fail;
1079			nvlist_set_array_next(value[ii - 1], tmpnvp);
1080		}
1081	}
1082	nvlist_set_flags(value[nvp->nvp_nitems - 1], NV_FLAG_IN_ARRAY);
1083
1084	nvp->nvp_data = (uint64_t)(uintptr_t)value;
1085	*firstel = value[0];
1086
1087	return (ptr);
1088fail:
1089	ERRNO_SAVE();
1090	for (j = 0; j < ii; j++)
1091		nvlist_destroy(value[j]);
1092	nv_free(value);
1093	ERRNO_RESTORE();
1094
1095	return (NULL);
1096}
1097
1098const unsigned char *
1099nvpair_unpack(bool isbe, const unsigned char *ptr, size_t *leftp,
1100    nvpair_t **nvpp)
1101{
1102	nvpair_t *nvp, *tmp;
1103
1104	nvp = nv_calloc(1, sizeof(*nvp) + NV_NAME_MAX);
1105	if (nvp == NULL)
1106		return (NULL);
1107	nvp->nvp_name = (char *)(nvp + 1);
1108
1109	ptr = nvpair_unpack_header(isbe, nvp, ptr, leftp);
1110	if (ptr == NULL)
1111		goto fail;
1112	tmp = nv_realloc(nvp, sizeof(*nvp) + strlen(nvp->nvp_name) + 1);
1113	if (tmp == NULL)
1114		goto fail;
1115	nvp = tmp;
1116
1117	/* Update nvp_name after realloc(). */
1118	nvp->nvp_name = (char *)(nvp + 1);
1119	nvp->nvp_data = 0x00;
1120	nvp->nvp_magic = NVPAIR_MAGIC;
1121	*nvpp = nvp;
1122	return (ptr);
1123fail:
1124	nv_free(nvp);
1125	return (NULL);
1126}
1127
1128int
1129nvpair_type(const nvpair_t *nvp)
1130{
1131
1132	NVPAIR_ASSERT(nvp);
1133
1134	return (nvp->nvp_type);
1135}
1136
1137const char *
1138nvpair_name(const nvpair_t *nvp)
1139{
1140
1141	NVPAIR_ASSERT(nvp);
1142
1143	return (nvp->nvp_name);
1144}
1145
1146nvpair_t *
1147nvpair_create_stringf(const char *name, const char *valuefmt, ...)
1148{
1149	va_list valueap;
1150	nvpair_t *nvp;
1151
1152	va_start(valueap, valuefmt);
1153	nvp = nvpair_create_stringv(name, valuefmt, valueap);
1154	va_end(valueap);
1155
1156	return (nvp);
1157}
1158
1159nvpair_t *
1160nvpair_create_stringv(const char *name, const char *valuefmt, va_list valueap)
1161{
1162	nvpair_t *nvp;
1163	char *str;
1164	int len;
1165
1166	len = nv_vasprintf(&str, valuefmt, valueap);
1167	if (len < 0)
1168		return (NULL);
1169	nvp = nvpair_create_string(name, str);
1170	if (nvp == NULL)
1171		nv_free(str);
1172	return (nvp);
1173}
1174
1175nvpair_t *
1176nvpair_create_null(const char *name)
1177{
1178
1179	return (nvpair_allocv(name, NV_TYPE_NULL, 0, 0, 0));
1180}
1181
1182nvpair_t *
1183nvpair_create_bool(const char *name, bool value)
1184{
1185
1186	return (nvpair_allocv(name, NV_TYPE_BOOL, value ? 1 : 0,
1187	    sizeof(uint8_t), 0));
1188}
1189
1190nvpair_t *
1191nvpair_create_number(const char *name, uint64_t value)
1192{
1193
1194	return (nvpair_allocv(name, NV_TYPE_NUMBER, value, sizeof(value), 0));
1195}
1196
1197nvpair_t *
1198nvpair_create_string(const char *name, const char *value)
1199{
1200	nvpair_t *nvp;
1201	size_t size;
1202	char *data;
1203
1204	if (value == NULL) {
1205		ERRNO_SET(EINVAL);
1206		return (NULL);
1207	}
1208
1209	data = nv_strdup(value);
1210	if (data == NULL)
1211		return (NULL);
1212	size = strlen(value) + 1;
1213
1214	nvp = nvpair_allocv(name, NV_TYPE_STRING, (uint64_t)(uintptr_t)data,
1215	    size, 0);
1216	if (nvp == NULL)
1217		nv_free(data);
1218
1219	return (nvp);
1220}
1221
1222nvpair_t *
1223nvpair_create_nvlist(const char *name, const nvlist_t *value)
1224{
1225	nvlist_t *nvl;
1226	nvpair_t *nvp;
1227
1228	if (value == NULL) {
1229		ERRNO_SET(EINVAL);
1230		return (NULL);
1231	}
1232
1233	nvl = nvlist_clone(value);
1234	if (nvl == NULL)
1235		return (NULL);
1236
1237	nvp = nvpair_allocv(name, NV_TYPE_NVLIST, (uint64_t)(uintptr_t)nvl, 0,
1238	    0);
1239	if (nvp == NULL)
1240		nvlist_destroy(nvl);
1241	else
1242		nvlist_set_parent(nvl, nvp);
1243
1244	return (nvp);
1245}
1246
1247#ifndef _KERNEL
1248nvpair_t *
1249nvpair_create_descriptor(const char *name, int value)
1250{
1251	nvpair_t *nvp;
1252
1253	if (value < 0 || !fd_is_valid(value)) {
1254		ERRNO_SET(EBADF);
1255		return (NULL);
1256	}
1257
1258	value = fcntl(value, F_DUPFD_CLOEXEC, 0);
1259	if (value < 0)
1260		return (NULL);
1261
1262	nvp = nvpair_allocv(name, NV_TYPE_DESCRIPTOR, (uint64_t)value,
1263	    sizeof(int64_t), 0);
1264	if (nvp == NULL) {
1265		ERRNO_SAVE();
1266		close(value);
1267		ERRNO_RESTORE();
1268	}
1269
1270	return (nvp);
1271}
1272#endif
1273
1274nvpair_t *
1275nvpair_create_binary(const char *name, const void *value, size_t size)
1276{
1277	nvpair_t *nvp;
1278	void *data;
1279
1280	if (value == NULL || size == 0) {
1281		ERRNO_SET(EINVAL);
1282		return (NULL);
1283	}
1284
1285	data = nv_malloc(size);
1286	if (data == NULL)
1287		return (NULL);
1288	memcpy(data, value, size);
1289
1290	nvp = nvpair_allocv(name, NV_TYPE_BINARY, (uint64_t)(uintptr_t)data,
1291	    size, 0);
1292	if (nvp == NULL)
1293		nv_free(data);
1294
1295	return (nvp);
1296}
1297
1298nvpair_t *
1299nvpair_create_bool_array(const char *name, const bool *value, size_t nitems)
1300{
1301	nvpair_t *nvp;
1302	size_t size;
1303	void *data;
1304
1305	if (value == NULL || nitems == 0) {
1306		ERRNO_SET(EINVAL);
1307		return (NULL);
1308	}
1309
1310	size = sizeof(value[0]) * nitems;
1311	data = nv_malloc(size);
1312	if (data == NULL)
1313		return (NULL);
1314
1315	memcpy(data, value, size);
1316	nvp = nvpair_allocv(name, NV_TYPE_BOOL_ARRAY, (uint64_t)(uintptr_t)data,
1317	    size, nitems);
1318	if (nvp == NULL) {
1319		ERRNO_SAVE();
1320		nv_free(data);
1321		ERRNO_RESTORE();
1322	}
1323
1324	return (nvp);
1325}
1326
1327nvpair_t *
1328nvpair_create_number_array(const char *name, const uint64_t *value,
1329    size_t nitems)
1330{
1331	nvpair_t *nvp;
1332	size_t size;
1333	void *data;
1334
1335	if (value == NULL || nitems == 0) {
1336		ERRNO_SET(EINVAL);
1337		return (NULL);
1338	}
1339
1340	size = sizeof(value[0]) * nitems;
1341	data = nv_malloc(size);
1342	if (data == NULL)
1343		return (NULL);
1344
1345	memcpy(data, value, size);
1346	nvp = nvpair_allocv(name, NV_TYPE_NUMBER_ARRAY,
1347	    (uint64_t)(uintptr_t)data, size, nitems);
1348	if (nvp == NULL) {
1349		ERRNO_SAVE();
1350		nv_free(data);
1351		ERRNO_RESTORE();
1352	}
1353
1354	return (nvp);
1355}
1356
1357nvpair_t *
1358nvpair_create_string_array(const char *name, const char * const *value,
1359    size_t nitems)
1360{
1361	nvpair_t *nvp;
1362	unsigned int ii;
1363	size_t datasize, size;
1364	char **data;
1365
1366	if (value == NULL || nitems == 0) {
1367		ERRNO_SET(EINVAL);
1368		return (NULL);
1369	}
1370
1371	nvp = NULL;
1372	datasize = 0;
1373	data = nv_malloc(sizeof(value[0]) * nitems);
1374	if (data == NULL)
1375		return (NULL);
1376
1377	for (ii = 0; ii < nitems; ii++) {
1378		if (value[ii] == NULL) {
1379			ERRNO_SET(EINVAL);
1380			goto fail;
1381		}
1382
1383		size = strlen(value[ii]) + 1;
1384		datasize += size;
1385		data[ii] = nv_strdup(value[ii]);
1386		if (data[ii] == NULL)
1387			goto fail;
1388	}
1389	nvp = nvpair_allocv(name, NV_TYPE_STRING_ARRAY,
1390	    (uint64_t)(uintptr_t)data, datasize, nitems);
1391
1392fail:
1393	if (nvp == NULL) {
1394		ERRNO_SAVE();
1395		for (; ii > 0; ii--)
1396			nv_free(data[ii - 1]);
1397		nv_free(data);
1398		ERRNO_RESTORE();
1399	}
1400
1401	return (nvp);
1402}
1403
1404nvpair_t *
1405nvpair_create_nvlist_array(const char *name, const nvlist_t * const *value,
1406    size_t nitems)
1407{
1408	unsigned int ii;
1409	nvlist_t **nvls;
1410	nvpair_t *parent;
1411	int flags;
1412
1413	nvls = NULL;
1414	ii = 0;
1415
1416	if (value == NULL || nitems == 0) {
1417		ERRNO_SET(EINVAL);
1418		return (NULL);
1419	}
1420
1421	nvls = nv_malloc(sizeof(value[0]) * nitems);
1422	if (nvls == NULL)
1423		return (NULL);
1424
1425	for (ii = 0; ii < nitems; ii++) {
1426		if (value[ii] == NULL) {
1427			ERRNO_SET(EINVAL);
1428			goto fail;
1429		}
1430
1431		nvls[ii] = nvlist_clone(value[ii]);
1432		if (nvls[ii] == NULL)
1433			goto fail;
1434
1435		if (ii > 0) {
1436			nvpair_t *nvp;
1437
1438			nvp = nvpair_allocv(" ", NV_TYPE_NVLIST,
1439			    (uint64_t)(uintptr_t)nvls[ii], 0, 0);
1440			if (nvp == NULL) {
1441				ERRNO_SAVE();
1442				nvlist_destroy(nvls[ii]);
1443				ERRNO_RESTORE();
1444				goto fail;
1445			}
1446			nvlist_set_array_next(nvls[ii - 1], nvp);
1447		}
1448	}
1449	flags = nvlist_flags(nvls[nitems - 1]) | NV_FLAG_IN_ARRAY;
1450	nvlist_set_flags(nvls[nitems - 1], flags);
1451
1452	parent = nvpair_allocv(name, NV_TYPE_NVLIST_ARRAY,
1453	    (uint64_t)(uintptr_t)nvls, 0, nitems);
1454	if (parent == NULL)
1455		goto fail;
1456
1457	for (ii = 0; ii < nitems; ii++)
1458		nvlist_set_parent(nvls[ii], parent);
1459
1460	return (parent);
1461
1462fail:
1463	ERRNO_SAVE();
1464	for (; ii > 0; ii--)
1465		nvlist_destroy(nvls[ii - 1]);
1466	nv_free(nvls);
1467	ERRNO_RESTORE();
1468
1469	return (NULL);
1470}
1471
1472#ifndef _KERNEL
1473nvpair_t *
1474nvpair_create_descriptor_array(const char *name, const int *value,
1475    size_t nitems)
1476{
1477	unsigned int ii;
1478	nvpair_t *nvp;
1479	int *fds;
1480
1481	if (value == NULL) {
1482		ERRNO_SET(EINVAL);
1483		return (NULL);
1484	}
1485
1486	nvp = NULL;
1487
1488	fds = nv_malloc(sizeof(value[0]) * nitems);
1489	if (fds == NULL)
1490		return (NULL);
1491	for (ii = 0; ii < nitems; ii++) {
1492		if (value[ii] == -1) {
1493			fds[ii] = -1;
1494		} else {
1495			if (!fd_is_valid(value[ii])) {
1496				ERRNO_SET(EBADF);
1497				goto fail;
1498			}
1499
1500			fds[ii] = fcntl(value[ii], F_DUPFD_CLOEXEC, 0);
1501			if (fds[ii] == -1)
1502				goto fail;
1503		}
1504	}
1505
1506	nvp = nvpair_allocv(name, NV_TYPE_DESCRIPTOR_ARRAY,
1507	    (uint64_t)(uintptr_t)fds, sizeof(int64_t) * nitems, nitems);
1508
1509fail:
1510	if (nvp == NULL) {
1511		ERRNO_SAVE();
1512		for (; ii > 0; ii--) {
1513			if (fds[ii - 1] != -1)
1514				close(fds[ii - 1]);
1515		}
1516		nv_free(fds);
1517		ERRNO_RESTORE();
1518	}
1519
1520	return (nvp);
1521}
1522#endif
1523
1524nvpair_t *
1525nvpair_move_string(const char *name, char *value)
1526{
1527	nvpair_t *nvp;
1528
1529	if (value == NULL) {
1530		ERRNO_SET(EINVAL);
1531		return (NULL);
1532	}
1533
1534	nvp = nvpair_allocv(name, NV_TYPE_STRING, (uint64_t)(uintptr_t)value,
1535	    strlen(value) + 1, 0);
1536	if (nvp == NULL) {
1537		ERRNO_SAVE();
1538		nv_free(value);
1539		ERRNO_RESTORE();
1540	}
1541
1542	return (nvp);
1543}
1544
1545nvpair_t *
1546nvpair_move_nvlist(const char *name, nvlist_t *value)
1547{
1548	nvpair_t *nvp;
1549
1550	if (value == NULL || nvlist_get_nvpair_parent(value) != NULL) {
1551		ERRNO_SET(EINVAL);
1552		return (NULL);
1553	}
1554
1555	if (nvlist_error(value) != 0) {
1556		ERRNO_SET(nvlist_error(value));
1557		nvlist_destroy(value);
1558		return (NULL);
1559	}
1560
1561	nvp = nvpair_allocv(name, NV_TYPE_NVLIST, (uint64_t)(uintptr_t)value,
1562	    0, 0);
1563	if (nvp == NULL)
1564		nvlist_destroy(value);
1565	else
1566		nvlist_set_parent(value, nvp);
1567
1568	return (nvp);
1569}
1570
1571#ifndef _KERNEL
1572nvpair_t *
1573nvpair_move_descriptor(const char *name, int value)
1574{
1575	nvpair_t *nvp;
1576
1577	if (value < 0 || !fd_is_valid(value)) {
1578		ERRNO_SET(EBADF);
1579		return (NULL);
1580	}
1581
1582	nvp = nvpair_allocv(name, NV_TYPE_DESCRIPTOR, (uint64_t)value,
1583	    sizeof(int64_t), 0);
1584	if (nvp == NULL) {
1585		ERRNO_SAVE();
1586		close(value);
1587		ERRNO_RESTORE();
1588	}
1589
1590	return (nvp);
1591}
1592#endif
1593
1594nvpair_t *
1595nvpair_move_binary(const char *name, void *value, size_t size)
1596{
1597	nvpair_t *nvp;
1598
1599	if (value == NULL || size == 0) {
1600		ERRNO_SET(EINVAL);
1601		return (NULL);
1602	}
1603
1604	nvp = nvpair_allocv(name, NV_TYPE_BINARY, (uint64_t)(uintptr_t)value,
1605	    size, 0);
1606	if (nvp == NULL) {
1607		ERRNO_SAVE();
1608		nv_free(value);
1609		ERRNO_RESTORE();
1610	}
1611
1612	return (nvp);
1613}
1614
1615nvpair_t *
1616nvpair_move_bool_array(const char *name, bool *value, size_t nitems)
1617{
1618	nvpair_t *nvp;
1619
1620	if (value == NULL || nitems == 0) {
1621		ERRNO_SET(EINVAL);
1622		return (NULL);
1623	}
1624
1625	nvp = nvpair_allocv(name, NV_TYPE_BOOL_ARRAY,
1626	    (uint64_t)(uintptr_t)value, sizeof(value[0]) * nitems, nitems);
1627	if (nvp == NULL) {
1628		ERRNO_SAVE();
1629		nv_free(value);
1630		ERRNO_RESTORE();
1631	}
1632
1633	return (nvp);
1634}
1635
1636nvpair_t *
1637nvpair_move_string_array(const char *name, char **value, size_t nitems)
1638{
1639	nvpair_t *nvp;
1640	size_t i, size;
1641
1642	if (value == NULL || nitems == 0) {
1643		ERRNO_SET(EINVAL);
1644		return (NULL);
1645	}
1646
1647	size = 0;
1648	for (i = 0; i < nitems; i++) {
1649		if (value[i] == NULL) {
1650			ERRNO_SET(EINVAL);
1651			return (NULL);
1652		}
1653
1654		size += strlen(value[i]) + 1;
1655	}
1656
1657	nvp = nvpair_allocv(name, NV_TYPE_STRING_ARRAY,
1658	    (uint64_t)(uintptr_t)value, size, nitems);
1659	if (nvp == NULL) {
1660		ERRNO_SAVE();
1661		for (i = 0; i < nitems; i++)
1662			nv_free(value[i]);
1663		nv_free(value);
1664		ERRNO_RESTORE();
1665	}
1666
1667	return (nvp);
1668}
1669
1670nvpair_t *
1671nvpair_move_number_array(const char *name, uint64_t *value, size_t nitems)
1672{
1673	nvpair_t *nvp;
1674
1675	if (value == NULL || nitems == 0) {
1676		ERRNO_SET(EINVAL);
1677		return (NULL);
1678	}
1679
1680	nvp = nvpair_allocv(name, NV_TYPE_NUMBER_ARRAY,
1681	    (uint64_t)(uintptr_t)value, sizeof(value[0]) * nitems, nitems);
1682	if (nvp == NULL) {
1683		ERRNO_SAVE();
1684		nv_free(value);
1685		ERRNO_RESTORE();
1686	}
1687
1688	return (nvp);
1689}
1690
1691nvpair_t *
1692nvpair_move_nvlist_array(const char *name, nvlist_t **value, size_t nitems)
1693{
1694	unsigned int ii;
1695	nvpair_t *nvp;
1696	int flags;
1697
1698	nvp = NULL;
1699	if (value == NULL || nitems == 0) {
1700		ERRNO_SET(EINVAL);
1701		return (NULL);
1702	}
1703
1704	for (ii = 0; ii < nitems; ii++) {
1705		if (value == NULL || nvlist_error(value[ii]) != 0 ||
1706		    nvlist_get_pararr(value[ii], NULL) != NULL) {
1707			ERRNO_SET(EINVAL);
1708			goto fail;
1709		}
1710		if (ii > 0) {
1711			nvp = nvpair_allocv(" ", NV_TYPE_NVLIST,
1712			    (uint64_t)(uintptr_t)value[ii], 0, 0);
1713			if (nvp == NULL)
1714				goto fail;
1715			nvlist_set_array_next(value[ii - 1], nvp);
1716		}
1717	}
1718	flags = nvlist_flags(value[nitems - 1]) | NV_FLAG_IN_ARRAY;
1719	nvlist_set_flags(value[nitems - 1], flags);
1720
1721	nvp = nvpair_allocv(name, NV_TYPE_NVLIST_ARRAY,
1722	    (uint64_t)(uintptr_t)value, 0, nitems);
1723fail:
1724	if (nvp == NULL) {
1725		ERRNO_SAVE();
1726		for (ii = 0; ii < nitems; ii++) {
1727			if (value[ii] != NULL &&
1728			    nvlist_get_pararr(value[ii], NULL) != NULL) {
1729				nvlist_destroy(value[ii]);
1730			}
1731			nv_free(value);
1732		}
1733		ERRNO_RESTORE();
1734	} else {
1735		for (ii = 0; ii < nitems; ii++)
1736			nvlist_set_parent(value[ii], nvp);
1737	}
1738
1739	return (nvp);
1740}
1741
1742#ifndef _KERNEL
1743nvpair_t *
1744nvpair_move_descriptor_array(const char *name, int *value, size_t nitems)
1745{
1746	nvpair_t *nvp;
1747	size_t i;
1748
1749	if (value == NULL || nitems == 0) {
1750		ERRNO_SET(EINVAL);
1751		return (NULL);
1752	}
1753
1754	for (i = 0; i < nitems; i++) {
1755		if (value[i] != -1 && !fd_is_valid(value[i])) {
1756			ERRNO_SET(EBADF);
1757			goto fail;
1758		}
1759	}
1760
1761	nvp = nvpair_allocv(name, NV_TYPE_DESCRIPTOR_ARRAY,
1762	    (uint64_t)(uintptr_t)value, sizeof(value[0]) * nitems, nitems);
1763	if (nvp == NULL)
1764		goto fail;
1765
1766	return (nvp);
1767fail:
1768	ERRNO_SAVE();
1769	for (i = 0; i < nitems; i++) {
1770		if (fd_is_valid(value[i]))
1771			close(value[i]);
1772	}
1773	nv_free(value);
1774	ERRNO_RESTORE();
1775
1776	return (NULL);
1777}
1778#endif
1779
1780bool
1781nvpair_get_bool(const nvpair_t *nvp)
1782{
1783
1784	NVPAIR_ASSERT(nvp);
1785
1786	return (nvp->nvp_data == 1);
1787}
1788
1789uint64_t
1790nvpair_get_number(const nvpair_t *nvp)
1791{
1792
1793	NVPAIR_ASSERT(nvp);
1794
1795	return (nvp->nvp_data);
1796}
1797
1798const char *
1799nvpair_get_string(const nvpair_t *nvp)
1800{
1801
1802	NVPAIR_ASSERT(nvp);
1803	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING);
1804
1805	return ((const char *)(intptr_t)nvp->nvp_data);
1806}
1807
1808const nvlist_t *
1809nvpair_get_nvlist(const nvpair_t *nvp)
1810{
1811
1812	NVPAIR_ASSERT(nvp);
1813	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST);
1814
1815	return ((const nvlist_t *)(intptr_t)nvp->nvp_data);
1816}
1817
1818#ifndef _KERNEL
1819int
1820nvpair_get_descriptor(const nvpair_t *nvp)
1821{
1822
1823	NVPAIR_ASSERT(nvp);
1824	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR);
1825
1826	return ((int)nvp->nvp_data);
1827}
1828#endif
1829
1830const void *
1831nvpair_get_binary(const nvpair_t *nvp, size_t *sizep)
1832{
1833
1834	NVPAIR_ASSERT(nvp);
1835	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BINARY);
1836
1837	if (sizep != NULL)
1838		*sizep = nvp->nvp_datasize;
1839
1840	return ((const void *)(intptr_t)nvp->nvp_data);
1841}
1842
1843const bool *
1844nvpair_get_bool_array(const nvpair_t *nvp, size_t *nitems)
1845{
1846
1847	NVPAIR_ASSERT(nvp);
1848	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BOOL_ARRAY);
1849
1850	if (nitems != NULL)
1851		*nitems = nvp->nvp_nitems;
1852
1853	return ((const bool *)(intptr_t)nvp->nvp_data);
1854}
1855
1856const uint64_t *
1857nvpair_get_number_array(const nvpair_t *nvp, size_t *nitems)
1858{
1859
1860	NVPAIR_ASSERT(nvp);
1861	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NUMBER_ARRAY);
1862
1863	if (nitems != NULL)
1864		*nitems = nvp->nvp_nitems;
1865
1866	return ((const uint64_t *)(intptr_t)nvp->nvp_data);
1867}
1868
1869const char * const *
1870nvpair_get_string_array(const nvpair_t *nvp, size_t *nitems)
1871{
1872
1873	NVPAIR_ASSERT(nvp);
1874	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING_ARRAY);
1875
1876	if (nitems != NULL)
1877		*nitems = nvp->nvp_nitems;
1878
1879	return ((const char * const *)(intptr_t)nvp->nvp_data);
1880}
1881
1882const nvlist_t * const *
1883nvpair_get_nvlist_array(const nvpair_t *nvp, size_t *nitems)
1884{
1885
1886	NVPAIR_ASSERT(nvp);
1887	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST_ARRAY);
1888
1889	if (nitems != NULL)
1890		*nitems = nvp->nvp_nitems;
1891
1892	return ((const nvlist_t * const *)((intptr_t)nvp->nvp_data));
1893}
1894
1895#ifndef _KERNEL
1896const int *
1897nvpair_get_descriptor_array(const nvpair_t *nvp, size_t *nitems)
1898{
1899
1900	NVPAIR_ASSERT(nvp);
1901	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR_ARRAY);
1902
1903	if (nitems != NULL)
1904		*nitems = nvp->nvp_nitems;
1905
1906	return ((const int *)(intptr_t)nvp->nvp_data);
1907}
1908#endif
1909
1910void
1911nvpair_free(nvpair_t *nvp)
1912{
1913	size_t i;
1914
1915	NVPAIR_ASSERT(nvp);
1916	PJDLOG_ASSERT(nvp->nvp_list == NULL);
1917
1918	nvp->nvp_magic = 0;
1919	switch (nvp->nvp_type) {
1920#ifndef _KERNEL
1921	case NV_TYPE_DESCRIPTOR:
1922		close((int)nvp->nvp_data);
1923		break;
1924	case NV_TYPE_DESCRIPTOR_ARRAY:
1925		for (i = 0; i < nvp->nvp_nitems; i++)
1926			close(((int *)(intptr_t)nvp->nvp_data)[i]);
1927		break;
1928#endif
1929	case NV_TYPE_NVLIST:
1930		nvlist_destroy((nvlist_t *)(intptr_t)nvp->nvp_data);
1931		break;
1932	case NV_TYPE_STRING:
1933		nv_free((char *)(intptr_t)nvp->nvp_data);
1934		break;
1935	case NV_TYPE_BINARY:
1936		nv_free((void *)(intptr_t)nvp->nvp_data);
1937		break;
1938	case NV_TYPE_NVLIST_ARRAY:
1939		for (i = 0; i < nvp->nvp_nitems; i++) {
1940			nvlist_destroy(
1941			    ((nvlist_t **)(intptr_t)nvp->nvp_data)[i]);
1942		}
1943		nv_free(((nvlist_t **)(intptr_t)nvp->nvp_data));
1944		break;
1945	case NV_TYPE_NUMBER_ARRAY:
1946		nv_free((uint64_t *)(intptr_t)nvp->nvp_data);
1947		break;
1948	case NV_TYPE_BOOL_ARRAY:
1949		nv_free((bool *)(intptr_t)nvp->nvp_data);
1950		break;
1951	case NV_TYPE_STRING_ARRAY:
1952		for (i = 0; i < nvp->nvp_nitems; i++)
1953			nv_free(((char **)(intptr_t)nvp->nvp_data)[i]);
1954		nv_free((char **)(intptr_t)nvp->nvp_data);
1955		break;
1956	}
1957	nv_free(nvp);
1958}
1959
1960void
1961nvpair_free_structure(nvpair_t *nvp)
1962{
1963
1964	NVPAIR_ASSERT(nvp);
1965	PJDLOG_ASSERT(nvp->nvp_list == NULL);
1966
1967	nvp->nvp_magic = 0;
1968	nv_free(nvp);
1969}
1970
1971const char *
1972nvpair_type_string(int type)
1973{
1974
1975	switch (type) {
1976	case NV_TYPE_NULL:
1977		return ("NULL");
1978	case NV_TYPE_BOOL:
1979		return ("BOOL");
1980	case NV_TYPE_NUMBER:
1981		return ("NUMBER");
1982	case NV_TYPE_STRING:
1983		return ("STRING");
1984	case NV_TYPE_NVLIST:
1985		return ("NVLIST");
1986	case NV_TYPE_DESCRIPTOR:
1987		return ("DESCRIPTOR");
1988	case NV_TYPE_BINARY:
1989		return ("BINARY");
1990	case NV_TYPE_BOOL_ARRAY:
1991		return ("BOOL ARRAY");
1992	case NV_TYPE_NUMBER_ARRAY:
1993		return ("NUMBER ARRAY");
1994	case NV_TYPE_STRING_ARRAY:
1995		return ("STRING ARRAY");
1996	case NV_TYPE_NVLIST_ARRAY:
1997		return ("NVLIST ARRAY");
1998	case NV_TYPE_DESCRIPTOR_ARRAY:
1999		return ("DESCRIPTOR ARRAY");
2000	default:
2001		return ("<UNKNOWN>");
2002	}
2003}
2004
2005