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