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