1/*-
2 * SPDX-License-Identifier: BSD-2-Clause
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 __unused, 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		nvphdr.nvph_nitems = le64toh(nvphdr.nvph_nitems);
665	}
666#else
667	if (isbe) {
668		nvphdr.nvph_namesize = be16toh(nvphdr.nvph_namesize);
669		nvphdr.nvph_datasize = be64toh(nvphdr.nvph_datasize);
670		nvphdr.nvph_nitems = be64toh(nvphdr.nvph_nitems);
671	}
672#endif
673
674	if (nvphdr.nvph_namesize > NV_NAME_MAX)
675		goto fail;
676	if (*leftp < nvphdr.nvph_namesize)
677		goto fail;
678	if (nvphdr.nvph_namesize < 1)
679		goto fail;
680	if (strnlen((const char *)ptr, nvphdr.nvph_namesize) !=
681	    (size_t)(nvphdr.nvph_namesize - 1)) {
682		goto fail;
683	}
684
685	memcpy(nvp->nvp_name, ptr, nvphdr.nvph_namesize);
686	ptr += nvphdr.nvph_namesize;
687	*leftp -= nvphdr.nvph_namesize;
688
689	if (*leftp < nvphdr.nvph_datasize)
690		goto fail;
691
692	nvp->nvp_type = nvphdr.nvph_type;
693	nvp->nvp_data = 0;
694	nvp->nvp_datasize = nvphdr.nvph_datasize;
695	nvp->nvp_nitems = nvphdr.nvph_nitems;
696
697	return (ptr);
698fail:
699	ERRNO_SET(EINVAL);
700	return (NULL);
701}
702
703const unsigned char *
704nvpair_unpack_null(bool isbe __unused, nvpair_t *nvp, const unsigned char *ptr,
705    size_t *leftp __unused)
706{
707
708	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NULL);
709
710	if (nvp->nvp_datasize != 0) {
711		ERRNO_SET(EINVAL);
712		return (NULL);
713	}
714
715	return (ptr);
716}
717
718const unsigned char *
719nvpair_unpack_bool(bool isbe __unused, nvpair_t *nvp, const unsigned char *ptr,
720    size_t *leftp)
721{
722	uint8_t value;
723
724	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BOOL);
725
726	if (nvp->nvp_datasize != sizeof(value)) {
727		ERRNO_SET(EINVAL);
728		return (NULL);
729	}
730	if (*leftp < sizeof(value)) {
731		ERRNO_SET(EINVAL);
732		return (NULL);
733	}
734
735	memcpy(&value, ptr, sizeof(value));
736	ptr += sizeof(value);
737	*leftp -= sizeof(value);
738
739	if (value != 0 && value != 1) {
740		ERRNO_SET(EINVAL);
741		return (NULL);
742	}
743
744	nvp->nvp_data = (uint64_t)value;
745
746	return (ptr);
747}
748
749const unsigned char *
750nvpair_unpack_number(bool isbe, nvpair_t *nvp, const unsigned char *ptr,
751     size_t *leftp)
752{
753
754	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NUMBER);
755
756	if (nvp->nvp_datasize != sizeof(uint64_t)) {
757		ERRNO_SET(EINVAL);
758		return (NULL);
759	}
760	if (*leftp < sizeof(uint64_t)) {
761		ERRNO_SET(EINVAL);
762		return (NULL);
763	}
764
765	if (isbe)
766		nvp->nvp_data = be64dec(ptr);
767	else
768		nvp->nvp_data = le64dec(ptr);
769
770	ptr += sizeof(uint64_t);
771	*leftp -= sizeof(uint64_t);
772
773	return (ptr);
774}
775
776const unsigned char *
777nvpair_unpack_string(bool isbe __unused, nvpair_t *nvp,
778    const unsigned char *ptr, size_t *leftp)
779{
780
781	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING);
782
783	if (*leftp < nvp->nvp_datasize || nvp->nvp_datasize == 0) {
784		ERRNO_SET(EINVAL);
785		return (NULL);
786	}
787
788	if (strnlen((const char *)ptr, nvp->nvp_datasize) !=
789	    nvp->nvp_datasize - 1) {
790		ERRNO_SET(EINVAL);
791		return (NULL);
792	}
793
794	nvp->nvp_data = (uint64_t)(uintptr_t)nv_strdup((const char *)ptr);
795	if (nvp->nvp_data == 0)
796		return (NULL);
797
798	ptr += nvp->nvp_datasize;
799	*leftp -= nvp->nvp_datasize;
800
801	return (ptr);
802}
803
804const unsigned char *
805nvpair_unpack_nvlist(bool isbe __unused, nvpair_t *nvp,
806    const unsigned char *ptr, size_t *leftp, size_t nfds, nvlist_t **child)
807{
808	nvlist_t *value;
809
810	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST);
811
812	if (*leftp < nvp->nvp_datasize || nvp->nvp_datasize == 0) {
813		ERRNO_SET(EINVAL);
814		return (NULL);
815	}
816
817	value = nvlist_create(0);
818	if (value == NULL)
819		return (NULL);
820
821	ptr = nvlist_unpack_header(value, ptr, nfds, NULL, leftp);
822	if (ptr == NULL)
823		return (NULL);
824
825	nvp->nvp_data = (uint64_t)(uintptr_t)value;
826	*child = value;
827
828	return (ptr);
829}
830
831#ifndef _KERNEL
832const unsigned char *
833nvpair_unpack_descriptor(bool isbe, nvpair_t *nvp, const unsigned char *ptr,
834    size_t *leftp, const int *fds, size_t nfds)
835{
836	int64_t idx;
837
838	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR);
839
840	if (nvp->nvp_datasize != sizeof(idx)) {
841		ERRNO_SET(EINVAL);
842		return (NULL);
843	}
844	if (*leftp < sizeof(idx)) {
845		ERRNO_SET(EINVAL);
846		return (NULL);
847	}
848
849	if (isbe)
850		idx = be64dec(ptr);
851	else
852		idx = le64dec(ptr);
853
854	if (idx < 0) {
855		ERRNO_SET(EINVAL);
856		return (NULL);
857	}
858
859	if ((size_t)idx >= nfds) {
860		ERRNO_SET(EINVAL);
861		return (NULL);
862	}
863
864	nvp->nvp_data = (uint64_t)fds[idx];
865
866	ptr += sizeof(idx);
867	*leftp -= sizeof(idx);
868
869	return (ptr);
870}
871#endif
872
873const unsigned char *
874nvpair_unpack_binary(bool isbe __unused, nvpair_t *nvp,
875    const unsigned char *ptr, size_t *leftp)
876{
877	void *value;
878
879	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BINARY);
880
881	if (*leftp < nvp->nvp_datasize || nvp->nvp_datasize == 0) {
882		ERRNO_SET(EINVAL);
883		return (NULL);
884	}
885
886	value = nv_malloc(nvp->nvp_datasize);
887	if (value == NULL)
888		return (NULL);
889
890	memcpy(value, ptr, nvp->nvp_datasize);
891	ptr += nvp->nvp_datasize;
892	*leftp -= nvp->nvp_datasize;
893
894	nvp->nvp_data = (uint64_t)(uintptr_t)value;
895
896	return (ptr);
897}
898
899const unsigned char *
900nvpair_unpack_bool_array(bool isbe __unused, nvpair_t *nvp,
901    const unsigned char *ptr, size_t *leftp)
902{
903	uint8_t *value;
904	size_t size;
905	unsigned int i;
906
907	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BOOL_ARRAY);
908
909	size = sizeof(*value) * nvp->nvp_nitems;
910	if (nvp->nvp_datasize != size || *leftp < size ||
911	    nvp->nvp_nitems == 0 || size < nvp->nvp_nitems) {
912		ERRNO_SET(EINVAL);
913		return (NULL);
914	}
915
916	value = nv_malloc(size);
917	if (value == NULL)
918		return (NULL);
919
920	for (i = 0; i < nvp->nvp_nitems; i++) {
921		value[i] = *(const uint8_t *)ptr;
922
923		ptr += sizeof(*value);
924		*leftp -= sizeof(*value);
925	}
926
927	nvp->nvp_data = (uint64_t)(uintptr_t)value;
928
929	return (ptr);
930}
931
932const unsigned char *
933nvpair_unpack_number_array(bool isbe, nvpair_t *nvp, const unsigned char *ptr,
934     size_t *leftp)
935{
936	uint64_t *value;
937	size_t size;
938	unsigned int i;
939
940	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NUMBER_ARRAY);
941
942	size = sizeof(*value) * nvp->nvp_nitems;
943	if (nvp->nvp_datasize != size || *leftp < size ||
944	    nvp->nvp_nitems == 0 || size < nvp->nvp_nitems) {
945		ERRNO_SET(EINVAL);
946		return (NULL);
947	}
948
949	value = nv_malloc(size);
950	if (value == NULL)
951		return (NULL);
952
953	for (i = 0; i < nvp->nvp_nitems; i++) {
954		if (isbe)
955			value[i] = be64dec(ptr);
956		else
957			value[i] = le64dec(ptr);
958
959		ptr += sizeof(*value);
960		*leftp -= sizeof(*value);
961	}
962
963	nvp->nvp_data = (uint64_t)(uintptr_t)value;
964
965	return (ptr);
966}
967
968const unsigned char *
969nvpair_unpack_string_array(bool isbe __unused, nvpair_t *nvp,
970    const unsigned char *ptr, size_t *leftp)
971{
972	ssize_t size;
973	size_t len;
974	const char *tmp;
975	char **value;
976	unsigned int ii, j;
977
978	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING_ARRAY);
979
980	if (*leftp < nvp->nvp_datasize || nvp->nvp_datasize == 0 ||
981	    nvp->nvp_nitems == 0) {
982		ERRNO_SET(EINVAL);
983		return (NULL);
984	}
985
986	size = nvp->nvp_datasize;
987	tmp = (const char *)ptr;
988	for (ii = 0; ii < nvp->nvp_nitems; ii++) {
989		len = strnlen(tmp, size - 1) + 1;
990		size -= len;
991		if (size < 0) {
992			ERRNO_SET(EINVAL);
993			return (NULL);
994		}
995		tmp += len;
996	}
997	if (size != 0) {
998		ERRNO_SET(EINVAL);
999		return (NULL);
1000	}
1001
1002	value = nv_malloc(sizeof(*value) * nvp->nvp_nitems);
1003	if (value == NULL)
1004		return (NULL);
1005
1006	for (ii = 0; ii < nvp->nvp_nitems; ii++) {
1007		value[ii] = nv_strdup((const char *)ptr);
1008		if (value[ii] == NULL)
1009			goto out;
1010		len = strlen(value[ii]) + 1;
1011		ptr += len;
1012		*leftp -= len;
1013	}
1014	nvp->nvp_data = (uint64_t)(uintptr_t)value;
1015
1016	return (ptr);
1017out:
1018	for (j = 0; j < ii; j++)
1019		nv_free(value[j]);
1020	nv_free(value);
1021	return (NULL);
1022}
1023
1024#ifndef _KERNEL
1025const unsigned char *
1026nvpair_unpack_descriptor_array(bool isbe, nvpair_t *nvp,
1027    const unsigned char *ptr, size_t *leftp, const int *fds, size_t nfds)
1028{
1029	int64_t idx;
1030	size_t size;
1031	unsigned int ii;
1032	int *array;
1033
1034	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR_ARRAY);
1035
1036	size = sizeof(idx) * nvp->nvp_nitems;
1037	if (nvp->nvp_datasize != size || *leftp < size ||
1038	    nvp->nvp_nitems == 0 || size < nvp->nvp_nitems) {
1039		ERRNO_SET(EINVAL);
1040		return (NULL);
1041	}
1042
1043	array = (int *)nv_malloc(size);
1044	if (array == NULL)
1045		return (NULL);
1046
1047	for (ii = 0; ii < nvp->nvp_nitems; ii++) {
1048		if (isbe)
1049			idx = be64dec(ptr);
1050		else
1051			idx = le64dec(ptr);
1052
1053		if (idx < 0) {
1054			ERRNO_SET(EINVAL);
1055			nv_free(array);
1056			return (NULL);
1057		}
1058
1059		if ((size_t)idx >= nfds) {
1060			ERRNO_SET(EINVAL);
1061			nv_free(array);
1062			return (NULL);
1063		}
1064
1065		array[ii] = (uint64_t)fds[idx];
1066
1067		ptr += sizeof(idx);
1068		*leftp -= sizeof(idx);
1069	}
1070
1071	nvp->nvp_data = (uint64_t)(uintptr_t)array;
1072
1073	return (ptr);
1074}
1075#endif
1076
1077const unsigned char *
1078nvpair_unpack_nvlist_array(bool isbe __unused, nvpair_t *nvp,
1079    const unsigned char *ptr, size_t *leftp, nvlist_t **firstel)
1080{
1081	nvlist_t **value;
1082	nvpair_t *tmpnvp;
1083	unsigned int ii, j;
1084	size_t sizeup;
1085
1086	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST_ARRAY);
1087
1088	sizeup = sizeof(struct nvpair_header) * nvp->nvp_nitems;
1089	if (nvp->nvp_nitems == 0 || sizeup < nvp->nvp_nitems ||
1090	    sizeup > *leftp) {
1091		ERRNO_SET(EINVAL);
1092		return (NULL);
1093	}
1094
1095	value = nv_malloc(nvp->nvp_nitems * sizeof(*value));
1096	if (value == NULL)
1097		return (NULL);
1098
1099	for (ii = 0; ii < nvp->nvp_nitems; ii++) {
1100		value[ii] = nvlist_create(0);
1101		if (value[ii] == NULL)
1102			goto fail;
1103		if (ii > 0) {
1104			tmpnvp = nvpair_allocv(" ", NV_TYPE_NVLIST,
1105			    (uint64_t)(uintptr_t)value[ii], 0, 0);
1106			if (tmpnvp == NULL)
1107				goto fail;
1108			nvlist_set_array_next(value[ii - 1], tmpnvp);
1109		}
1110	}
1111	nvlist_set_flags(value[nvp->nvp_nitems - 1], NV_FLAG_IN_ARRAY);
1112
1113	nvp->nvp_data = (uint64_t)(uintptr_t)value;
1114	*firstel = value[0];
1115
1116	return (ptr);
1117fail:
1118	ERRNO_SAVE();
1119	for (j = 0; j <= ii; j++)
1120		nvlist_destroy(value[j]);
1121	nv_free(value);
1122	ERRNO_RESTORE();
1123
1124	return (NULL);
1125}
1126
1127const unsigned char *
1128nvpair_unpack(bool isbe, const unsigned char *ptr, size_t *leftp,
1129    nvpair_t **nvpp)
1130{
1131	nvpair_t *nvp, *tmp;
1132
1133	nvp = nv_calloc(1, sizeof(*nvp) + NV_NAME_MAX);
1134	if (nvp == NULL)
1135		return (NULL);
1136	nvp->nvp_name = (char *)(nvp + 1);
1137
1138	ptr = nvpair_unpack_header(isbe, nvp, ptr, leftp);
1139	if (ptr == NULL)
1140		goto fail;
1141	tmp = nv_realloc(nvp, sizeof(*nvp) + strlen(nvp->nvp_name) + 1);
1142	if (tmp == NULL)
1143		goto fail;
1144	nvp = tmp;
1145
1146	/* Update nvp_name after realloc(). */
1147	nvp->nvp_name = (char *)(nvp + 1);
1148	nvp->nvp_data = 0x00;
1149	nvp->nvp_magic = NVPAIR_MAGIC;
1150	*nvpp = nvp;
1151	return (ptr);
1152fail:
1153	nv_free(nvp);
1154	return (NULL);
1155}
1156
1157int
1158nvpair_type(const nvpair_t *nvp)
1159{
1160
1161	NVPAIR_ASSERT(nvp);
1162
1163	return (nvp->nvp_type);
1164}
1165
1166const char *
1167nvpair_name(const nvpair_t *nvp)
1168{
1169
1170	NVPAIR_ASSERT(nvp);
1171
1172	return (nvp->nvp_name);
1173}
1174
1175nvpair_t *
1176nvpair_create_stringf(const char *name, const char *valuefmt, ...)
1177{
1178	va_list valueap;
1179	nvpair_t *nvp;
1180
1181	va_start(valueap, valuefmt);
1182	nvp = nvpair_create_stringv(name, valuefmt, valueap);
1183	va_end(valueap);
1184
1185	return (nvp);
1186}
1187
1188nvpair_t *
1189nvpair_create_stringv(const char *name, const char *valuefmt, va_list valueap)
1190{
1191	nvpair_t *nvp;
1192	char *str;
1193	int len;
1194
1195	len = nv_vasprintf(&str, valuefmt, valueap);
1196	if (len < 0)
1197		return (NULL);
1198	nvp = nvpair_create_string(name, str);
1199	nv_free(str);
1200	return (nvp);
1201}
1202
1203nvpair_t *
1204nvpair_create_null(const char *name)
1205{
1206
1207	return (nvpair_allocv(name, NV_TYPE_NULL, 0, 0, 0));
1208}
1209
1210nvpair_t *
1211nvpair_create_bool(const char *name, bool value)
1212{
1213
1214	return (nvpair_allocv(name, NV_TYPE_BOOL, value ? 1 : 0,
1215	    sizeof(uint8_t), 0));
1216}
1217
1218nvpair_t *
1219nvpair_create_number(const char *name, uint64_t value)
1220{
1221
1222	return (nvpair_allocv(name, NV_TYPE_NUMBER, value, sizeof(value), 0));
1223}
1224
1225nvpair_t *
1226nvpair_create_string(const char *name, const char *value)
1227{
1228	nvpair_t *nvp;
1229	size_t size;
1230	char *data;
1231
1232	if (value == NULL) {
1233		ERRNO_SET(EINVAL);
1234		return (NULL);
1235	}
1236
1237	data = nv_strdup(value);
1238	if (data == NULL)
1239		return (NULL);
1240	size = strlen(value) + 1;
1241
1242	nvp = nvpair_allocv(name, NV_TYPE_STRING, (uint64_t)(uintptr_t)data,
1243	    size, 0);
1244	if (nvp == NULL)
1245		nv_free(data);
1246
1247	return (nvp);
1248}
1249
1250nvpair_t *
1251nvpair_create_nvlist(const char *name, const nvlist_t *value)
1252{
1253	nvlist_t *nvl;
1254	nvpair_t *nvp;
1255
1256	if (value == NULL) {
1257		ERRNO_SET(EINVAL);
1258		return (NULL);
1259	}
1260
1261	nvl = nvlist_clone(value);
1262	if (nvl == NULL)
1263		return (NULL);
1264
1265	nvp = nvpair_allocv(name, NV_TYPE_NVLIST, (uint64_t)(uintptr_t)nvl, 0,
1266	    0);
1267	if (nvp == NULL)
1268		nvlist_destroy(nvl);
1269	else
1270		nvlist_set_parent(nvl, nvp);
1271
1272	return (nvp);
1273}
1274
1275#ifndef _KERNEL
1276nvpair_t *
1277nvpair_create_descriptor(const char *name, int value)
1278{
1279	nvpair_t *nvp;
1280
1281	value = fcntl(value, F_DUPFD_CLOEXEC, 0);
1282	if (value < 0)
1283		return (NULL);
1284
1285	nvp = nvpair_allocv(name, NV_TYPE_DESCRIPTOR, (uint64_t)value,
1286	    sizeof(int64_t), 0);
1287	if (nvp == NULL) {
1288		ERRNO_SAVE();
1289		close(value);
1290		ERRNO_RESTORE();
1291	}
1292
1293	return (nvp);
1294}
1295#endif
1296
1297nvpair_t *
1298nvpair_create_binary(const char *name, const void *value, size_t size)
1299{
1300	nvpair_t *nvp;
1301	void *data;
1302
1303	if (value == NULL || size == 0) {
1304		ERRNO_SET(EINVAL);
1305		return (NULL);
1306	}
1307
1308	data = nv_malloc(size);
1309	if (data == NULL)
1310		return (NULL);
1311	memcpy(data, value, size);
1312
1313	nvp = nvpair_allocv(name, NV_TYPE_BINARY, (uint64_t)(uintptr_t)data,
1314	    size, 0);
1315	if (nvp == NULL)
1316		nv_free(data);
1317
1318	return (nvp);
1319}
1320
1321nvpair_t *
1322nvpair_create_bool_array(const char *name, const bool *value, size_t nitems)
1323{
1324	nvpair_t *nvp;
1325	size_t size;
1326	void *data;
1327
1328	if (value == NULL || nitems == 0) {
1329		ERRNO_SET(EINVAL);
1330		return (NULL);
1331	}
1332
1333	size = sizeof(value[0]) * nitems;
1334	data = nv_malloc(size);
1335	if (data == NULL)
1336		return (NULL);
1337
1338	memcpy(data, value, size);
1339	nvp = nvpair_allocv(name, NV_TYPE_BOOL_ARRAY, (uint64_t)(uintptr_t)data,
1340	    size, nitems);
1341	if (nvp == NULL) {
1342		ERRNO_SAVE();
1343		nv_free(data);
1344		ERRNO_RESTORE();
1345	}
1346
1347	return (nvp);
1348}
1349
1350nvpair_t *
1351nvpair_create_number_array(const char *name, const uint64_t *value,
1352    size_t nitems)
1353{
1354	nvpair_t *nvp;
1355	size_t size;
1356	void *data;
1357
1358	if (value == NULL || nitems == 0) {
1359		ERRNO_SET(EINVAL);
1360		return (NULL);
1361	}
1362
1363	size = sizeof(value[0]) * nitems;
1364	data = nv_malloc(size);
1365	if (data == NULL)
1366		return (NULL);
1367
1368	memcpy(data, value, size);
1369	nvp = nvpair_allocv(name, NV_TYPE_NUMBER_ARRAY,
1370	    (uint64_t)(uintptr_t)data, size, nitems);
1371	if (nvp == NULL) {
1372		ERRNO_SAVE();
1373		nv_free(data);
1374		ERRNO_RESTORE();
1375	}
1376
1377	return (nvp);
1378}
1379
1380nvpair_t *
1381nvpair_create_string_array(const char *name, const char * const *value,
1382    size_t nitems)
1383{
1384	nvpair_t *nvp;
1385	unsigned int ii;
1386	size_t datasize, size;
1387	char **data;
1388
1389	if (value == NULL || nitems == 0) {
1390		ERRNO_SET(EINVAL);
1391		return (NULL);
1392	}
1393
1394	nvp = NULL;
1395	datasize = 0;
1396	data = nv_malloc(sizeof(value[0]) * nitems);
1397	if (data == NULL)
1398		return (NULL);
1399
1400	for (ii = 0; ii < nitems; ii++) {
1401		if (value[ii] == NULL) {
1402			ERRNO_SET(EINVAL);
1403			goto fail;
1404		}
1405
1406		size = strlen(value[ii]) + 1;
1407		datasize += size;
1408		data[ii] = nv_strdup(value[ii]);
1409		if (data[ii] == NULL)
1410			goto fail;
1411	}
1412	nvp = nvpair_allocv(name, NV_TYPE_STRING_ARRAY,
1413	    (uint64_t)(uintptr_t)data, datasize, nitems);
1414
1415fail:
1416	if (nvp == NULL) {
1417		ERRNO_SAVE();
1418		for (; ii > 0; ii--)
1419			nv_free(data[ii - 1]);
1420		nv_free(data);
1421		ERRNO_RESTORE();
1422	}
1423
1424	return (nvp);
1425}
1426
1427nvpair_t *
1428nvpair_create_nvlist_array(const char *name, const nvlist_t * const *value,
1429    size_t nitems)
1430{
1431	unsigned int ii;
1432	nvlist_t **nvls;
1433	nvpair_t *parent;
1434	int flags;
1435
1436	nvls = NULL;
1437
1438	if (value == NULL || nitems == 0) {
1439		ERRNO_SET(EINVAL);
1440		return (NULL);
1441	}
1442
1443	nvls = nv_malloc(sizeof(value[0]) * nitems);
1444	if (nvls == NULL)
1445		return (NULL);
1446
1447	for (ii = 0; ii < nitems; ii++) {
1448		if (value[ii] == NULL) {
1449			ERRNO_SET(EINVAL);
1450			goto fail;
1451		}
1452
1453		nvls[ii] = nvlist_clone(value[ii]);
1454		if (nvls[ii] == NULL)
1455			goto fail;
1456
1457		if (ii > 0) {
1458			nvpair_t *nvp;
1459
1460			nvp = nvpair_allocv(" ", NV_TYPE_NVLIST,
1461			    (uint64_t)(uintptr_t)nvls[ii], 0, 0);
1462			if (nvp == NULL) {
1463				ERRNO_SAVE();
1464				nvlist_destroy(nvls[ii]);
1465				ERRNO_RESTORE();
1466				goto fail;
1467			}
1468			nvlist_set_array_next(nvls[ii - 1], nvp);
1469		}
1470	}
1471	flags = nvlist_flags(nvls[nitems - 1]) | NV_FLAG_IN_ARRAY;
1472	nvlist_set_flags(nvls[nitems - 1], flags);
1473
1474	parent = nvpair_allocv(name, NV_TYPE_NVLIST_ARRAY,
1475	    (uint64_t)(uintptr_t)nvls, 0, nitems);
1476	if (parent == NULL)
1477		goto fail;
1478
1479	for (ii = 0; ii < nitems; ii++)
1480		nvlist_set_parent(nvls[ii], parent);
1481
1482	return (parent);
1483
1484fail:
1485	ERRNO_SAVE();
1486	for (; ii > 0; ii--)
1487		nvlist_destroy(nvls[ii - 1]);
1488	nv_free(nvls);
1489	ERRNO_RESTORE();
1490
1491	return (NULL);
1492}
1493
1494#ifndef _KERNEL
1495nvpair_t *
1496nvpair_create_descriptor_array(const char *name, const int *value,
1497    size_t nitems)
1498{
1499	unsigned int ii;
1500	nvpair_t *nvp;
1501	int *fds;
1502
1503	if (value == NULL) {
1504		ERRNO_SET(EINVAL);
1505		return (NULL);
1506	}
1507
1508	nvp = NULL;
1509
1510	fds = nv_malloc(sizeof(value[0]) * nitems);
1511	if (fds == NULL)
1512		return (NULL);
1513	for (ii = 0; ii < nitems; ii++) {
1514		if (value[ii] == -1) {
1515			fds[ii] = -1;
1516		} else {
1517			fds[ii] = fcntl(value[ii], F_DUPFD_CLOEXEC, 0);
1518			if (fds[ii] == -1)
1519				goto fail;
1520		}
1521	}
1522
1523	nvp = nvpair_allocv(name, NV_TYPE_DESCRIPTOR_ARRAY,
1524	    (uint64_t)(uintptr_t)fds, sizeof(int64_t) * nitems, nitems);
1525
1526fail:
1527	if (nvp == NULL) {
1528		ERRNO_SAVE();
1529		for (; ii > 0; ii--) {
1530			if (fds[ii - 1] != -1)
1531				close(fds[ii - 1]);
1532		}
1533		nv_free(fds);
1534		ERRNO_RESTORE();
1535	}
1536
1537	return (nvp);
1538}
1539#endif
1540
1541nvpair_t *
1542nvpair_move_string(const char *name, char *value)
1543{
1544	nvpair_t *nvp;
1545
1546	if (value == NULL) {
1547		ERRNO_SET(EINVAL);
1548		return (NULL);
1549	}
1550
1551	nvp = nvpair_allocv(name, NV_TYPE_STRING, (uint64_t)(uintptr_t)value,
1552	    strlen(value) + 1, 0);
1553	if (nvp == NULL) {
1554		ERRNO_SAVE();
1555		nv_free(value);
1556		ERRNO_RESTORE();
1557	}
1558
1559	return (nvp);
1560}
1561
1562nvpair_t *
1563nvpair_move_nvlist(const char *name, nvlist_t *value)
1564{
1565	nvpair_t *nvp;
1566
1567	if (value == NULL || nvlist_get_nvpair_parent(value) != NULL) {
1568		ERRNO_SET(EINVAL);
1569		return (NULL);
1570	}
1571
1572	if (nvlist_error(value) != 0) {
1573		ERRNO_SET(nvlist_error(value));
1574		nvlist_destroy(value);
1575		return (NULL);
1576	}
1577
1578	nvp = nvpair_allocv(name, NV_TYPE_NVLIST, (uint64_t)(uintptr_t)value,
1579	    0, 0);
1580	if (nvp == NULL)
1581		nvlist_destroy(value);
1582	else
1583		nvlist_set_parent(value, nvp);
1584
1585	return (nvp);
1586}
1587
1588#ifndef _KERNEL
1589nvpair_t *
1590nvpair_move_descriptor(const char *name, int value)
1591{
1592	nvpair_t *nvp;
1593
1594	if (value < 0 || !fd_is_valid(value)) {
1595		ERRNO_SET(EBADF);
1596		return (NULL);
1597	}
1598
1599	nvp = nvpair_allocv(name, NV_TYPE_DESCRIPTOR, (uint64_t)value,
1600	    sizeof(int64_t), 0);
1601	if (nvp == NULL) {
1602		ERRNO_SAVE();
1603		close(value);
1604		ERRNO_RESTORE();
1605	}
1606
1607	return (nvp);
1608}
1609#endif
1610
1611nvpair_t *
1612nvpair_move_binary(const char *name, void *value, size_t size)
1613{
1614	nvpair_t *nvp;
1615
1616	if (value == NULL || size == 0) {
1617		ERRNO_SET(EINVAL);
1618		return (NULL);
1619	}
1620
1621	nvp = nvpair_allocv(name, NV_TYPE_BINARY, (uint64_t)(uintptr_t)value,
1622	    size, 0);
1623	if (nvp == NULL) {
1624		ERRNO_SAVE();
1625		nv_free(value);
1626		ERRNO_RESTORE();
1627	}
1628
1629	return (nvp);
1630}
1631
1632nvpair_t *
1633nvpair_move_bool_array(const char *name, bool *value, size_t nitems)
1634{
1635	nvpair_t *nvp;
1636
1637	if (value == NULL || nitems == 0) {
1638		ERRNO_SET(EINVAL);
1639		return (NULL);
1640	}
1641
1642	nvp = nvpair_allocv(name, NV_TYPE_BOOL_ARRAY,
1643	    (uint64_t)(uintptr_t)value, sizeof(value[0]) * nitems, nitems);
1644	if (nvp == NULL) {
1645		ERRNO_SAVE();
1646		nv_free(value);
1647		ERRNO_RESTORE();
1648	}
1649
1650	return (nvp);
1651}
1652
1653nvpair_t *
1654nvpair_move_string_array(const char *name, char **value, size_t nitems)
1655{
1656	nvpair_t *nvp;
1657	size_t i, size;
1658
1659	if (value == NULL || nitems == 0) {
1660		ERRNO_SET(EINVAL);
1661		return (NULL);
1662	}
1663
1664	size = 0;
1665	for (i = 0; i < nitems; i++) {
1666		if (value[i] == NULL) {
1667			ERRNO_SET(EINVAL);
1668			return (NULL);
1669		}
1670
1671		size += strlen(value[i]) + 1;
1672	}
1673
1674	nvp = nvpair_allocv(name, NV_TYPE_STRING_ARRAY,
1675	    (uint64_t)(uintptr_t)value, size, nitems);
1676	if (nvp == NULL) {
1677		ERRNO_SAVE();
1678		for (i = 0; i < nitems; i++)
1679			nv_free(value[i]);
1680		nv_free(value);
1681		ERRNO_RESTORE();
1682	}
1683
1684	return (nvp);
1685}
1686
1687nvpair_t *
1688nvpair_move_number_array(const char *name, uint64_t *value, size_t nitems)
1689{
1690	nvpair_t *nvp;
1691
1692	if (value == NULL || nitems == 0) {
1693		ERRNO_SET(EINVAL);
1694		return (NULL);
1695	}
1696
1697	nvp = nvpair_allocv(name, NV_TYPE_NUMBER_ARRAY,
1698	    (uint64_t)(uintptr_t)value, sizeof(value[0]) * nitems, nitems);
1699	if (nvp == NULL) {
1700		ERRNO_SAVE();
1701		nv_free(value);
1702		ERRNO_RESTORE();
1703	}
1704
1705	return (nvp);
1706}
1707
1708nvpair_t *
1709nvpair_move_nvlist_array(const char *name, nvlist_t **value, size_t nitems)
1710{
1711	nvpair_t *parent;
1712	unsigned int ii;
1713	int flags;
1714
1715	if (value == NULL || nitems == 0) {
1716		ERRNO_SET(EINVAL);
1717		return (NULL);
1718	}
1719
1720	for (ii = 0; ii < nitems; ii++) {
1721		if (value == NULL || nvlist_error(value[ii]) != 0 ||
1722		    nvlist_get_pararr(value[ii], NULL) != NULL) {
1723			ERRNO_SET(EINVAL);
1724			goto fail;
1725		}
1726		if (ii > 0) {
1727			nvpair_t *nvp;
1728
1729			nvp = nvpair_allocv(" ", NV_TYPE_NVLIST,
1730			    (uint64_t)(uintptr_t)value[ii], 0, 0);
1731			if (nvp == NULL)
1732				goto fail;
1733			nvlist_set_array_next(value[ii - 1], nvp);
1734		}
1735	}
1736	flags = nvlist_flags(value[nitems - 1]) | NV_FLAG_IN_ARRAY;
1737	nvlist_set_flags(value[nitems - 1], flags);
1738
1739	parent = nvpair_allocv(name, NV_TYPE_NVLIST_ARRAY,
1740	    (uint64_t)(uintptr_t)value, 0, nitems);
1741	if (parent == NULL)
1742		goto fail;
1743
1744	for (ii = 0; ii < nitems; ii++)
1745		nvlist_set_parent(value[ii], parent);
1746
1747	return (parent);
1748fail:
1749	ERRNO_SAVE();
1750	for (ii = 0; ii < nitems; ii++) {
1751		if (value[ii] != NULL &&
1752		    nvlist_get_pararr(value[ii], NULL) != NULL) {
1753			nvlist_destroy(value[ii]);
1754		}
1755	}
1756	nv_free(value);
1757	ERRNO_RESTORE();
1758
1759	return (NULL);
1760}
1761
1762#ifndef _KERNEL
1763nvpair_t *
1764nvpair_move_descriptor_array(const char *name, int *value, size_t nitems)
1765{
1766	nvpair_t *nvp;
1767	size_t i;
1768
1769	if (value == NULL || nitems == 0) {
1770		ERRNO_SET(EINVAL);
1771		return (NULL);
1772	}
1773
1774	for (i = 0; i < nitems; i++) {
1775		if (value[i] != -1 && !fd_is_valid(value[i])) {
1776			ERRNO_SET(EBADF);
1777			goto fail;
1778		}
1779	}
1780
1781	nvp = nvpair_allocv(name, NV_TYPE_DESCRIPTOR_ARRAY,
1782	    (uint64_t)(uintptr_t)value, sizeof(value[0]) * nitems, nitems);
1783	if (nvp == NULL)
1784		goto fail;
1785
1786	return (nvp);
1787fail:
1788	ERRNO_SAVE();
1789	for (i = 0; i < nitems; i++) {
1790		if (fd_is_valid(value[i]))
1791			close(value[i]);
1792	}
1793	nv_free(value);
1794	ERRNO_RESTORE();
1795
1796	return (NULL);
1797}
1798#endif
1799
1800bool
1801nvpair_get_bool(const nvpair_t *nvp)
1802{
1803
1804	NVPAIR_ASSERT(nvp);
1805
1806	return (nvp->nvp_data == 1);
1807}
1808
1809uint64_t
1810nvpair_get_number(const nvpair_t *nvp)
1811{
1812
1813	NVPAIR_ASSERT(nvp);
1814
1815	return (nvp->nvp_data);
1816}
1817
1818const char *
1819nvpair_get_string(const nvpair_t *nvp)
1820{
1821
1822	NVPAIR_ASSERT(nvp);
1823	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING);
1824
1825	return ((const char *)(intptr_t)nvp->nvp_data);
1826}
1827
1828const nvlist_t *
1829nvpair_get_nvlist(const nvpair_t *nvp)
1830{
1831
1832	NVPAIR_ASSERT(nvp);
1833	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST);
1834
1835	return ((const nvlist_t *)(intptr_t)nvp->nvp_data);
1836}
1837
1838#ifndef _KERNEL
1839int
1840nvpair_get_descriptor(const nvpair_t *nvp)
1841{
1842
1843	NVPAIR_ASSERT(nvp);
1844	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR);
1845
1846	return ((int)nvp->nvp_data);
1847}
1848#endif
1849
1850const void *
1851nvpair_get_binary(const nvpair_t *nvp, size_t *sizep)
1852{
1853
1854	NVPAIR_ASSERT(nvp);
1855	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BINARY);
1856
1857	if (sizep != NULL)
1858		*sizep = nvp->nvp_datasize;
1859
1860	return ((const void *)(intptr_t)nvp->nvp_data);
1861}
1862
1863const bool *
1864nvpair_get_bool_array(const nvpair_t *nvp, size_t *nitems)
1865{
1866
1867	NVPAIR_ASSERT(nvp);
1868	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BOOL_ARRAY);
1869
1870	if (nitems != NULL)
1871		*nitems = nvp->nvp_nitems;
1872
1873	return ((const bool *)(intptr_t)nvp->nvp_data);
1874}
1875
1876const uint64_t *
1877nvpair_get_number_array(const nvpair_t *nvp, size_t *nitems)
1878{
1879
1880	NVPAIR_ASSERT(nvp);
1881	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NUMBER_ARRAY);
1882
1883	if (nitems != NULL)
1884		*nitems = nvp->nvp_nitems;
1885
1886	return ((const uint64_t *)(intptr_t)nvp->nvp_data);
1887}
1888
1889const char * const *
1890nvpair_get_string_array(const nvpair_t *nvp, size_t *nitems)
1891{
1892
1893	NVPAIR_ASSERT(nvp);
1894	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING_ARRAY);
1895
1896	if (nitems != NULL)
1897		*nitems = nvp->nvp_nitems;
1898
1899	return ((const char * const *)(intptr_t)nvp->nvp_data);
1900}
1901
1902const nvlist_t * const *
1903nvpair_get_nvlist_array(const nvpair_t *nvp, size_t *nitems)
1904{
1905
1906	NVPAIR_ASSERT(nvp);
1907	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST_ARRAY);
1908
1909	if (nitems != NULL)
1910		*nitems = nvp->nvp_nitems;
1911
1912	return ((const nvlist_t * const *)((intptr_t)nvp->nvp_data));
1913}
1914
1915#ifndef _KERNEL
1916const int *
1917nvpair_get_descriptor_array(const nvpair_t *nvp, size_t *nitems)
1918{
1919
1920	NVPAIR_ASSERT(nvp);
1921	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR_ARRAY);
1922
1923	if (nitems != NULL)
1924		*nitems = nvp->nvp_nitems;
1925
1926	return ((const int *)(intptr_t)nvp->nvp_data);
1927}
1928#endif
1929
1930int
1931nvpair_append_bool_array(nvpair_t *nvp, const bool value)
1932{
1933
1934	NVPAIR_ASSERT(nvp);
1935	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BOOL_ARRAY);
1936	return (nvpair_append(nvp, &value, sizeof(value), sizeof(value)));
1937}
1938
1939int
1940nvpair_append_number_array(nvpair_t *nvp, const uint64_t value)
1941{
1942
1943	NVPAIR_ASSERT(nvp);
1944	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NUMBER_ARRAY);
1945	return (nvpair_append(nvp, &value, sizeof(value), sizeof(value)));
1946}
1947
1948int
1949nvpair_append_string_array(nvpair_t *nvp, const char *value)
1950{
1951	char *str;
1952
1953	NVPAIR_ASSERT(nvp);
1954	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING_ARRAY);
1955	if (value == NULL) {
1956		ERRNO_SET(EINVAL);
1957		return (-1);
1958	}
1959	str = nv_strdup(value);
1960	if (str == NULL) {
1961		return (-1);
1962	}
1963	if (nvpair_append(nvp, &str, sizeof(str), strlen(str) + 1) == -1) {
1964		nv_free(str);
1965		return (-1);
1966	}
1967	return (0);
1968}
1969
1970int
1971nvpair_append_nvlist_array(nvpair_t *nvp, const nvlist_t *value)
1972{
1973	nvpair_t *tmpnvp;
1974	nvlist_t *nvl, *prev;
1975	int flags;
1976
1977	NVPAIR_ASSERT(nvp);
1978	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST_ARRAY);
1979	if (value == NULL || nvlist_error(value) != 0 ||
1980	    nvlist_get_pararr(value, NULL) != NULL) {
1981		ERRNO_SET(EINVAL);
1982		return (-1);
1983	}
1984	nvl = nvlist_clone(value);
1985	if (nvl == NULL) {
1986		return (-1);
1987	}
1988	flags = nvlist_flags(nvl) | NV_FLAG_IN_ARRAY;
1989	nvlist_set_flags(nvl, flags);
1990
1991	tmpnvp = NULL;
1992	prev = NULL;
1993	if (nvp->nvp_nitems > 0) {
1994		nvlist_t **nvls = (void *)(uintptr_t)nvp->nvp_data;
1995
1996		prev = nvls[nvp->nvp_nitems - 1];
1997		PJDLOG_ASSERT(prev != NULL);
1998
1999		tmpnvp = nvpair_allocv(" ", NV_TYPE_NVLIST,
2000		    (uint64_t)(uintptr_t)nvl, 0, 0);
2001		if (tmpnvp == NULL) {
2002			goto fail;
2003		}
2004	}
2005	if (nvpair_append(nvp, &nvl, sizeof(nvl), 0) == -1) {
2006		goto fail;
2007	}
2008	if (tmpnvp) {
2009		NVPAIR_ASSERT(tmpnvp);
2010		nvlist_set_array_next(prev, tmpnvp);
2011	}
2012	nvlist_set_parent(nvl, nvp);
2013	return (0);
2014fail:
2015	if (tmpnvp) {
2016		nvpair_free(tmpnvp);
2017	}
2018	nvlist_destroy(nvl);
2019	return (-1);
2020}
2021
2022#ifndef _KERNEL
2023int
2024nvpair_append_descriptor_array(nvpair_t *nvp, const int value)
2025{
2026	int fd;
2027
2028	NVPAIR_ASSERT(nvp);
2029	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR_ARRAY);
2030	fd = fcntl(value, F_DUPFD_CLOEXEC, 0);
2031	if (fd == -1) {
2032		return (-1);
2033	}
2034	if (nvpair_append(nvp, &fd, sizeof(fd), sizeof(fd)) == -1) {
2035		close(fd);
2036		return (-1);
2037	}
2038	return (0);
2039}
2040#endif
2041
2042void
2043nvpair_free(nvpair_t *nvp)
2044{
2045	size_t i;
2046
2047	NVPAIR_ASSERT(nvp);
2048	PJDLOG_ASSERT(nvp->nvp_list == NULL);
2049
2050	nvp->nvp_magic = 0;
2051	switch (nvp->nvp_type) {
2052#ifndef _KERNEL
2053	case NV_TYPE_DESCRIPTOR:
2054		close((int)nvp->nvp_data);
2055		break;
2056	case NV_TYPE_DESCRIPTOR_ARRAY:
2057		for (i = 0; i < nvp->nvp_nitems; i++)
2058			close(((int *)(intptr_t)nvp->nvp_data)[i]);
2059		nv_free((int *)(intptr_t)nvp->nvp_data);
2060		break;
2061#endif
2062	case NV_TYPE_NVLIST:
2063		nvlist_destroy((nvlist_t *)(intptr_t)nvp->nvp_data);
2064		break;
2065	case NV_TYPE_STRING:
2066		nv_free((char *)(intptr_t)nvp->nvp_data);
2067		break;
2068	case NV_TYPE_BINARY:
2069		nv_free((void *)(intptr_t)nvp->nvp_data);
2070		break;
2071	case NV_TYPE_NVLIST_ARRAY:
2072		for (i = 0; i < nvp->nvp_nitems; i++) {
2073			nvlist_destroy(
2074			    ((nvlist_t **)(intptr_t)nvp->nvp_data)[i]);
2075		}
2076		nv_free(((nvlist_t **)(intptr_t)nvp->nvp_data));
2077		break;
2078	case NV_TYPE_NUMBER_ARRAY:
2079		nv_free((uint64_t *)(intptr_t)nvp->nvp_data);
2080		break;
2081	case NV_TYPE_BOOL_ARRAY:
2082		nv_free((bool *)(intptr_t)nvp->nvp_data);
2083		break;
2084	case NV_TYPE_STRING_ARRAY:
2085		for (i = 0; i < nvp->nvp_nitems; i++)
2086			nv_free(((char **)(intptr_t)nvp->nvp_data)[i]);
2087		nv_free((char **)(intptr_t)nvp->nvp_data);
2088		break;
2089	}
2090	nv_free(nvp);
2091}
2092
2093void
2094nvpair_free_structure(nvpair_t *nvp)
2095{
2096
2097	NVPAIR_ASSERT(nvp);
2098	PJDLOG_ASSERT(nvp->nvp_list == NULL);
2099
2100	nvp->nvp_magic = 0;
2101	nv_free(nvp);
2102}
2103
2104const char *
2105nvpair_type_string(int type)
2106{
2107
2108	switch (type) {
2109	case NV_TYPE_NULL:
2110		return ("NULL");
2111	case NV_TYPE_BOOL:
2112		return ("BOOL");
2113	case NV_TYPE_NUMBER:
2114		return ("NUMBER");
2115	case NV_TYPE_STRING:
2116		return ("STRING");
2117	case NV_TYPE_NVLIST:
2118		return ("NVLIST");
2119	case NV_TYPE_DESCRIPTOR:
2120		return ("DESCRIPTOR");
2121	case NV_TYPE_BINARY:
2122		return ("BINARY");
2123	case NV_TYPE_BOOL_ARRAY:
2124		return ("BOOL ARRAY");
2125	case NV_TYPE_NUMBER_ARRAY:
2126		return ("NUMBER ARRAY");
2127	case NV_TYPE_STRING_ARRAY:
2128		return ("STRING ARRAY");
2129	case NV_TYPE_NVLIST_ARRAY:
2130		return ("NVLIST ARRAY");
2131	case NV_TYPE_DESCRIPTOR_ARRAY:
2132		return ("DESCRIPTOR ARRAY");
2133	default:
2134		return ("<UNKNOWN>");
2135	}
2136}
2137
2138