1258065Spjd/*-
2258065Spjd * Copyright (c) 2009-2013 The FreeBSD Foundation
3258065Spjd * All rights reserved.
4258065Spjd *
5258065Spjd * This software was developed by Pawel Jakub Dawidek under sponsorship from
6258065Spjd * the FreeBSD Foundation.
7258065Spjd *
8258065Spjd * Redistribution and use in source and binary forms, with or without
9258065Spjd * modification, are permitted provided that the following conditions
10258065Spjd * are met:
11258065Spjd * 1. Redistributions of source code must retain the above copyright
12258065Spjd *    notice, this list of conditions and the following disclaimer.
13258065Spjd * 2. Redistributions in binary form must reproduce the above copyright
14258065Spjd *    notice, this list of conditions and the following disclaimer in the
15258065Spjd *    documentation and/or other materials provided with the distribution.
16258065Spjd *
17258065Spjd * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
18258065Spjd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19258065Spjd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20258065Spjd * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
21258065Spjd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22258065Spjd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23258065Spjd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24258065Spjd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25258065Spjd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26258065Spjd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27258065Spjd * SUCH DAMAGE.
28258065Spjd */
29258065Spjd
30258065Spjd#include <sys/cdefs.h>
31258065Spjd__FBSDID("$FreeBSD$");
32258065Spjd
33258065Spjd#include <sys/param.h>
34258065Spjd#include <sys/endian.h>
35258065Spjd#include <sys/queue.h>
36258065Spjd
37279438Srstone#ifdef _KERNEL
38279438Srstone
39279438Srstone#include <sys/errno.h>
40279438Srstone#include <sys/lock.h>
41279438Srstone#include <sys/malloc.h>
42279438Srstone#include <sys/systm.h>
43279438Srstone
44279438Srstone#include <machine/stdarg.h>
45279438Srstone
46279438Srstone#else
47258065Spjd#include <errno.h>
48258065Spjd#include <fcntl.h>
49258065Spjd#include <stdarg.h>
50258065Spjd#include <stdbool.h>
51258065Spjd#include <stdint.h>
52258065Spjd#include <stdlib.h>
53258065Spjd#include <string.h>
54258065Spjd#include <unistd.h>
55279439Srstone
56279439Srstone#include "common_impl.h"
57279438Srstone#endif
58258065Spjd
59258065Spjd#ifdef HAVE_PJDLOG
60258065Spjd#include <pjdlog.h>
61258065Spjd#endif
62258065Spjd
63279439Srstone#include <sys/nv.h>
64279439Srstone#include <sys/nv_impl.h>
65279439Srstone#include <sys/nvlist_impl.h>
66279439Srstone#include <sys/nvpair_impl.h>
67258065Spjd
68258065Spjd#ifndef	HAVE_PJDLOG
69279438Srstone#ifdef _KERNEL
70279438Srstone#define	PJDLOG_ASSERT(...)		MPASS(__VA_ARGS__)
71279438Srstone#define	PJDLOG_RASSERT(expr, ...)	KASSERT(expr, (__VA_ARGS__))
72279438Srstone#define	PJDLOG_ABORT(...)		panic(__VA_ARGS__)
73279438Srstone#else
74258065Spjd#include <assert.h>
75258065Spjd#define	PJDLOG_ASSERT(...)		assert(__VA_ARGS__)
76258065Spjd#define	PJDLOG_RASSERT(expr, ...)	assert(expr)
77258065Spjd#define	PJDLOG_ABORT(...)		abort()
78258065Spjd#endif
79279438Srstone#endif
80258065Spjd
81258065Spjd#define	NVPAIR_MAGIC	0x6e7670	/* "nvp" */
82258065Spjdstruct nvpair {
83258065Spjd	int		 nvp_magic;
84258065Spjd	char		*nvp_name;
85258065Spjd	int		 nvp_type;
86258065Spjd	uint64_t	 nvp_data;
87258065Spjd	size_t		 nvp_datasize;
88271579Spjd	nvlist_t	*nvp_list;
89258065Spjd	TAILQ_ENTRY(nvpair) nvp_next;
90258065Spjd};
91258065Spjd
92258065Spjd#define	NVPAIR_ASSERT(nvp)	do {					\
93258065Spjd	PJDLOG_ASSERT((nvp) != NULL);					\
94258065Spjd	PJDLOG_ASSERT((nvp)->nvp_magic == NVPAIR_MAGIC);		\
95258065Spjd} while (0)
96258065Spjd
97258065Spjdstruct nvpair_header {
98258065Spjd	uint8_t		nvph_type;
99258065Spjd	uint16_t	nvph_namesize;
100258065Spjd	uint64_t	nvph_datasize;
101258065Spjd} __packed;
102258065Spjd
103258065Spjd
104258065Spjdvoid
105258065Spjdnvpair_assert(const nvpair_t *nvp)
106258065Spjd{
107258065Spjd
108258065Spjd	NVPAIR_ASSERT(nvp);
109258065Spjd}
110258065Spjd
111271579Spjdnvlist_t *
112258065Spjdnvpair_nvlist(const nvpair_t *nvp)
113258065Spjd{
114258065Spjd
115258065Spjd	NVPAIR_ASSERT(nvp);
116258065Spjd
117258065Spjd	return (nvp->nvp_list);
118258065Spjd}
119258065Spjd
120258065Spjdnvpair_t *
121258065Spjdnvpair_next(const nvpair_t *nvp)
122258065Spjd{
123258065Spjd
124258065Spjd	NVPAIR_ASSERT(nvp);
125258065Spjd	PJDLOG_ASSERT(nvp->nvp_list != NULL);
126258065Spjd
127258065Spjd	return (TAILQ_NEXT(nvp, nvp_next));
128258065Spjd}
129258065Spjd
130258065Spjdnvpair_t *
131258065Spjdnvpair_prev(const nvpair_t *nvp)
132258065Spjd{
133258065Spjd
134258065Spjd	NVPAIR_ASSERT(nvp);
135258065Spjd	PJDLOG_ASSERT(nvp->nvp_list != NULL);
136258065Spjd
137258065Spjd	return (TAILQ_PREV(nvp, nvl_head, nvp_next));
138258065Spjd}
139258065Spjd
140258065Spjdvoid
141258065Spjdnvpair_insert(struct nvl_head *head, nvpair_t *nvp, nvlist_t *nvl)
142258065Spjd{
143258065Spjd
144258065Spjd	NVPAIR_ASSERT(nvp);
145258065Spjd	PJDLOG_ASSERT(nvp->nvp_list == NULL);
146258065Spjd	PJDLOG_ASSERT(!nvlist_exists(nvl, nvpair_name(nvp)));
147258065Spjd
148258065Spjd	TAILQ_INSERT_TAIL(head, nvp, nvp_next);
149258065Spjd	nvp->nvp_list = nvl;
150258065Spjd}
151258065Spjd
152271579Spjdstatic void
153271579Spjdnvpair_remove_nvlist(nvpair_t *nvp)
154271579Spjd{
155271579Spjd	nvlist_t *nvl;
156271579Spjd
157271579Spjd	/* XXX: DECONST is bad, mkay? */
158271579Spjd	nvl = __DECONST(nvlist_t *, nvpair_get_nvlist(nvp));
159271579Spjd	PJDLOG_ASSERT(nvl != NULL);
160271579Spjd	nvlist_set_parent(nvl, NULL);
161271579Spjd}
162271579Spjd
163258065Spjdvoid
164258065Spjdnvpair_remove(struct nvl_head *head, nvpair_t *nvp, const nvlist_t *nvl)
165258065Spjd{
166258065Spjd
167258065Spjd	NVPAIR_ASSERT(nvp);
168258065Spjd	PJDLOG_ASSERT(nvp->nvp_list == nvl);
169258065Spjd
170271579Spjd	if (nvpair_type(nvp) == NV_TYPE_NVLIST)
171271579Spjd		nvpair_remove_nvlist(nvp);
172271579Spjd
173258065Spjd	TAILQ_REMOVE(head, nvp, nvp_next);
174258065Spjd	nvp->nvp_list = NULL;
175258065Spjd}
176258065Spjd
177258065Spjdnvpair_t *
178258065Spjdnvpair_clone(const nvpair_t *nvp)
179258065Spjd{
180258065Spjd	nvpair_t *newnvp;
181258065Spjd	const char *name;
182258065Spjd	const void *data;
183258065Spjd	size_t datasize;
184258065Spjd
185258065Spjd	NVPAIR_ASSERT(nvp);
186258065Spjd
187258065Spjd	name = nvpair_name(nvp);
188258065Spjd
189258065Spjd	switch (nvpair_type(nvp)) {
190258065Spjd	case NV_TYPE_NULL:
191258065Spjd		newnvp = nvpair_create_null(name);
192258065Spjd		break;
193258065Spjd	case NV_TYPE_BOOL:
194258065Spjd		newnvp = nvpair_create_bool(name, nvpair_get_bool(nvp));
195258065Spjd		break;
196258065Spjd	case NV_TYPE_NUMBER:
197258065Spjd		newnvp = nvpair_create_number(name, nvpair_get_number(nvp));
198258065Spjd		break;
199258065Spjd	case NV_TYPE_STRING:
200258065Spjd		newnvp = nvpair_create_string(name, nvpair_get_string(nvp));
201258065Spjd		break;
202258065Spjd	case NV_TYPE_NVLIST:
203258065Spjd		newnvp = nvpair_create_nvlist(name, nvpair_get_nvlist(nvp));
204258065Spjd		break;
205279438Srstone#ifndef _KERNEL
206258065Spjd	case NV_TYPE_DESCRIPTOR:
207258065Spjd		newnvp = nvpair_create_descriptor(name,
208258065Spjd		    nvpair_get_descriptor(nvp));
209258065Spjd		break;
210279438Srstone#endif
211258065Spjd	case NV_TYPE_BINARY:
212258065Spjd		data = nvpair_get_binary(nvp, &datasize);
213258065Spjd		newnvp = nvpair_create_binary(name, data, datasize);
214258065Spjd		break;
215258065Spjd	default:
216258065Spjd		PJDLOG_ABORT("Unknown type: %d.", nvpair_type(nvp));
217258065Spjd	}
218258065Spjd
219258065Spjd	return (newnvp);
220258065Spjd}
221258065Spjd
222258065Spjdsize_t
223258065Spjdnvpair_header_size(void)
224258065Spjd{
225258065Spjd
226258065Spjd	return (sizeof(struct nvpair_header));
227258065Spjd}
228258065Spjd
229258065Spjdsize_t
230258065Spjdnvpair_size(const nvpair_t *nvp)
231258065Spjd{
232258065Spjd
233258065Spjd	NVPAIR_ASSERT(nvp);
234258065Spjd
235258065Spjd	return (nvp->nvp_datasize);
236258065Spjd}
237258065Spjd
238271579Spjdunsigned char *
239258065Spjdnvpair_pack_header(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp)
240258065Spjd{
241258065Spjd	struct nvpair_header nvphdr;
242258065Spjd	size_t namesize;
243258065Spjd
244258065Spjd	NVPAIR_ASSERT(nvp);
245258065Spjd
246258065Spjd	nvphdr.nvph_type = nvp->nvp_type;
247258065Spjd	namesize = strlen(nvp->nvp_name) + 1;
248258065Spjd	PJDLOG_ASSERT(namesize > 0 && namesize <= UINT16_MAX);
249258065Spjd	nvphdr.nvph_namesize = namesize;
250258065Spjd	nvphdr.nvph_datasize = nvp->nvp_datasize;
251258065Spjd	PJDLOG_ASSERT(*leftp >= sizeof(nvphdr));
252258065Spjd	memcpy(ptr, &nvphdr, sizeof(nvphdr));
253258065Spjd	ptr += sizeof(nvphdr);
254258065Spjd	*leftp -= sizeof(nvphdr);
255258065Spjd
256258065Spjd	PJDLOG_ASSERT(*leftp >= namesize);
257258065Spjd	memcpy(ptr, nvp->nvp_name, namesize);
258258065Spjd	ptr += namesize;
259258065Spjd	*leftp -= namesize;
260258065Spjd
261258065Spjd	return (ptr);
262258065Spjd}
263258065Spjd
264271579Spjdunsigned char *
265258065Spjdnvpair_pack_null(const nvpair_t *nvp, unsigned char *ptr,
266258065Spjd    size_t *leftp __unused)
267258065Spjd{
268258065Spjd
269258065Spjd	NVPAIR_ASSERT(nvp);
270258065Spjd	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NULL);
271258065Spjd
272258065Spjd	return (ptr);
273258065Spjd}
274258065Spjd
275271579Spjdunsigned char *
276258065Spjdnvpair_pack_bool(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp)
277258065Spjd{
278258065Spjd	uint8_t value;
279258065Spjd
280258065Spjd	NVPAIR_ASSERT(nvp);
281258065Spjd	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BOOL);
282258065Spjd
283258065Spjd	value = (uint8_t)nvp->nvp_data;
284258065Spjd
285258065Spjd	PJDLOG_ASSERT(*leftp >= sizeof(value));
286258065Spjd	memcpy(ptr, &value, sizeof(value));
287258065Spjd	ptr += sizeof(value);
288258065Spjd	*leftp -= sizeof(value);
289258065Spjd
290258065Spjd	return (ptr);
291258065Spjd}
292258065Spjd
293271579Spjdunsigned char *
294258065Spjdnvpair_pack_number(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp)
295258065Spjd{
296258065Spjd	uint64_t value;
297258065Spjd
298258065Spjd	NVPAIR_ASSERT(nvp);
299258065Spjd	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NUMBER);
300258065Spjd
301258065Spjd	value = (uint64_t)nvp->nvp_data;
302258065Spjd
303258065Spjd	PJDLOG_ASSERT(*leftp >= sizeof(value));
304258065Spjd	memcpy(ptr, &value, sizeof(value));
305258065Spjd	ptr += sizeof(value);
306258065Spjd	*leftp -= sizeof(value);
307258065Spjd
308258065Spjd	return (ptr);
309258065Spjd}
310258065Spjd
311271579Spjdunsigned char *
312258065Spjdnvpair_pack_string(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp)
313258065Spjd{
314258065Spjd
315258065Spjd	NVPAIR_ASSERT(nvp);
316258065Spjd	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING);
317258065Spjd
318258065Spjd	PJDLOG_ASSERT(*leftp >= nvp->nvp_datasize);
319258065Spjd	memcpy(ptr, (const void *)(intptr_t)nvp->nvp_data, nvp->nvp_datasize);
320258065Spjd	ptr += nvp->nvp_datasize;
321258065Spjd	*leftp -= nvp->nvp_datasize;
322258065Spjd
323258065Spjd	return (ptr);
324258065Spjd}
325258065Spjd
326271579Spjdunsigned char *
327271579Spjdnvpair_pack_nvlist_up(unsigned char *ptr, size_t *leftp)
328258065Spjd{
329271579Spjd	struct nvpair_header nvphdr;
330271579Spjd	size_t namesize;
331271579Spjd	const char *name = "";
332258065Spjd
333271579Spjd	namesize = 1;
334271579Spjd	nvphdr.nvph_type = NV_TYPE_NVLIST_UP;
335271579Spjd	nvphdr.nvph_namesize = namesize;
336271579Spjd	nvphdr.nvph_datasize = 0;
337271579Spjd	PJDLOG_ASSERT(*leftp >= sizeof(nvphdr));
338271579Spjd	memcpy(ptr, &nvphdr, sizeof(nvphdr));
339271579Spjd	ptr += sizeof(nvphdr);
340271579Spjd	*leftp -= sizeof(nvphdr);
341258065Spjd
342271579Spjd	PJDLOG_ASSERT(*leftp >= namesize);
343271579Spjd	memcpy(ptr, name, namesize);
344271579Spjd	ptr += namesize;
345271579Spjd	*leftp -= namesize;
346258065Spjd
347258065Spjd	return (ptr);
348258065Spjd}
349258065Spjd
350279438Srstone#ifndef _KERNEL
351271579Spjdunsigned char *
352258065Spjdnvpair_pack_descriptor(const nvpair_t *nvp, unsigned char *ptr, int64_t *fdidxp,
353258065Spjd    size_t *leftp)
354258065Spjd{
355258065Spjd	int64_t value;
356258065Spjd
357258065Spjd	NVPAIR_ASSERT(nvp);
358258065Spjd	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR);
359258065Spjd
360258065Spjd	value = (int64_t)nvp->nvp_data;
361258065Spjd	if (value != -1) {
362258065Spjd		/*
363258065Spjd		 * If there is a real descriptor here, we change its number
364258065Spjd		 * to position in the array of descriptors send via control
365258065Spjd		 * message.
366258065Spjd		 */
367258065Spjd		PJDLOG_ASSERT(fdidxp != NULL);
368258065Spjd
369258065Spjd		value = *fdidxp;
370258065Spjd		(*fdidxp)++;
371258065Spjd	}
372258065Spjd
373258065Spjd	PJDLOG_ASSERT(*leftp >= sizeof(value));
374258065Spjd	memcpy(ptr, &value, sizeof(value));
375258065Spjd	ptr += sizeof(value);
376258065Spjd	*leftp -= sizeof(value);
377258065Spjd
378258065Spjd	return (ptr);
379258065Spjd}
380279438Srstone#endif
381258065Spjd
382271579Spjdunsigned char *
383258065Spjdnvpair_pack_binary(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp)
384258065Spjd{
385258065Spjd
386258065Spjd	NVPAIR_ASSERT(nvp);
387258065Spjd	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BINARY);
388258065Spjd
389258065Spjd	PJDLOG_ASSERT(*leftp >= nvp->nvp_datasize);
390258065Spjd	memcpy(ptr, (const void *)(intptr_t)nvp->nvp_data, nvp->nvp_datasize);
391258065Spjd	ptr += nvp->nvp_datasize;
392258065Spjd	*leftp -= nvp->nvp_datasize;
393258065Spjd
394258065Spjd	return (ptr);
395258065Spjd}
396258065Spjd
397271579Spjdvoid
398271579Spjdnvpair_init_datasize(nvpair_t *nvp)
399258065Spjd{
400258065Spjd
401258065Spjd	NVPAIR_ASSERT(nvp);
402258065Spjd
403258065Spjd	if (nvp->nvp_type == NV_TYPE_NVLIST) {
404258065Spjd		if (nvp->nvp_data == 0) {
405258065Spjd			nvp->nvp_datasize = 0;
406258065Spjd		} else {
407258065Spjd			nvp->nvp_datasize =
408258065Spjd			    nvlist_size((const nvlist_t *)(intptr_t)nvp->nvp_data);
409258065Spjd		}
410258065Spjd	}
411258065Spjd}
412258065Spjd
413271579Spjdconst unsigned char *
414272843Spjdnvpair_unpack_header(bool isbe, nvpair_t *nvp, const unsigned char *ptr,
415258065Spjd    size_t *leftp)
416258065Spjd{
417258065Spjd	struct nvpair_header nvphdr;
418258065Spjd
419258065Spjd	if (*leftp < sizeof(nvphdr))
420258065Spjd		goto failed;
421258065Spjd
422258065Spjd	memcpy(&nvphdr, ptr, sizeof(nvphdr));
423258065Spjd	ptr += sizeof(nvphdr);
424258065Spjd	*leftp -= sizeof(nvphdr);
425258065Spjd
426258065Spjd#if NV_TYPE_FIRST > 0
427258065Spjd	if (nvphdr.nvph_type < NV_TYPE_FIRST)
428258065Spjd		goto failed;
429258065Spjd#endif
430271579Spjd	if (nvphdr.nvph_type > NV_TYPE_LAST &&
431271579Spjd	    nvphdr.nvph_type != NV_TYPE_NVLIST_UP) {
432258065Spjd		goto failed;
433271579Spjd	}
434258065Spjd
435258065Spjd#if BYTE_ORDER == BIG_ENDIAN
436272843Spjd	if (!isbe) {
437258065Spjd		nvphdr.nvph_namesize = le16toh(nvphdr.nvph_namesize);
438258065Spjd		nvphdr.nvph_datasize = le64toh(nvphdr.nvph_datasize);
439258065Spjd	}
440258065Spjd#else
441272843Spjd	if (isbe) {
442258065Spjd		nvphdr.nvph_namesize = be16toh(nvphdr.nvph_namesize);
443258065Spjd		nvphdr.nvph_datasize = be64toh(nvphdr.nvph_datasize);
444258065Spjd	}
445258065Spjd#endif
446258065Spjd
447258065Spjd	if (nvphdr.nvph_namesize > NV_NAME_MAX)
448258065Spjd		goto failed;
449258065Spjd	if (*leftp < nvphdr.nvph_namesize)
450258065Spjd		goto failed;
451258065Spjd	if (nvphdr.nvph_namesize < 1)
452258065Spjd		goto failed;
453258065Spjd	if (strnlen((const char *)ptr, nvphdr.nvph_namesize) !=
454258065Spjd	    (size_t)(nvphdr.nvph_namesize - 1)) {
455258065Spjd		goto failed;
456258065Spjd	}
457258065Spjd
458258065Spjd	memcpy(nvp->nvp_name, ptr, nvphdr.nvph_namesize);
459258065Spjd	ptr += nvphdr.nvph_namesize;
460258065Spjd	*leftp -= nvphdr.nvph_namesize;
461258065Spjd
462258065Spjd	if (*leftp < nvphdr.nvph_datasize)
463258065Spjd		goto failed;
464258065Spjd
465258065Spjd	nvp->nvp_type = nvphdr.nvph_type;
466258065Spjd	nvp->nvp_data = 0;
467258065Spjd	nvp->nvp_datasize = nvphdr.nvph_datasize;
468258065Spjd
469258065Spjd	return (ptr);
470258065Spjdfailed:
471279438Srstone	RESTORE_ERRNO(EINVAL);
472258065Spjd	return (NULL);
473258065Spjd}
474258065Spjd
475271579Spjdconst unsigned char *
476272843Spjdnvpair_unpack_null(bool isbe __unused, nvpair_t *nvp, const unsigned char *ptr,
477258065Spjd    size_t *leftp __unused)
478258065Spjd{
479258065Spjd
480258065Spjd	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NULL);
481258065Spjd
482258065Spjd	if (nvp->nvp_datasize != 0) {
483279438Srstone		RESTORE_ERRNO(EINVAL);
484258065Spjd		return (NULL);
485258065Spjd	}
486258065Spjd
487258065Spjd	return (ptr);
488258065Spjd}
489258065Spjd
490271579Spjdconst unsigned char *
491272843Spjdnvpair_unpack_bool(bool isbe __unused, nvpair_t *nvp, const unsigned char *ptr,
492258065Spjd    size_t *leftp)
493258065Spjd{
494258065Spjd	uint8_t value;
495258065Spjd
496258065Spjd	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BOOL);
497258065Spjd
498258065Spjd	if (nvp->nvp_datasize != sizeof(value)) {
499279438Srstone		RESTORE_ERRNO(EINVAL);
500258065Spjd		return (NULL);
501258065Spjd	}
502258065Spjd	if (*leftp < sizeof(value)) {
503279438Srstone		RESTORE_ERRNO(EINVAL);
504258065Spjd		return (NULL);
505258065Spjd	}
506258065Spjd
507258065Spjd	memcpy(&value, ptr, sizeof(value));
508258065Spjd	ptr += sizeof(value);
509258065Spjd	*leftp -= sizeof(value);
510258065Spjd
511258065Spjd	if (value != 0 && value != 1) {
512279438Srstone		RESTORE_ERRNO(EINVAL);
513258065Spjd		return (NULL);
514258065Spjd	}
515258065Spjd
516258065Spjd	nvp->nvp_data = (uint64_t)value;
517258065Spjd
518258065Spjd	return (ptr);
519258065Spjd}
520258065Spjd
521271579Spjdconst unsigned char *
522272843Spjdnvpair_unpack_number(bool isbe, nvpair_t *nvp, const unsigned char *ptr,
523271579Spjd     size_t *leftp)
524258065Spjd{
525258065Spjd
526258065Spjd	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NUMBER);
527258065Spjd
528258065Spjd	if (nvp->nvp_datasize != sizeof(uint64_t)) {
529279438Srstone		RESTORE_ERRNO(EINVAL);
530258065Spjd		return (NULL);
531258065Spjd	}
532258065Spjd	if (*leftp < sizeof(uint64_t)) {
533279438Srstone		RESTORE_ERRNO(EINVAL);
534258065Spjd		return (NULL);
535258065Spjd	}
536258065Spjd
537272843Spjd	if (isbe)
538258065Spjd		nvp->nvp_data = be64dec(ptr);
539258065Spjd	else
540258065Spjd		nvp->nvp_data = le64dec(ptr);
541258065Spjd	ptr += sizeof(uint64_t);
542258065Spjd	*leftp -= sizeof(uint64_t);
543258065Spjd
544258065Spjd	return (ptr);
545258065Spjd}
546258065Spjd
547271579Spjdconst unsigned char *
548272843Spjdnvpair_unpack_string(bool isbe __unused, nvpair_t *nvp,
549258065Spjd    const unsigned char *ptr, size_t *leftp)
550258065Spjd{
551258065Spjd
552258065Spjd	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING);
553258065Spjd
554258065Spjd	if (*leftp < nvp->nvp_datasize || nvp->nvp_datasize == 0) {
555279438Srstone		RESTORE_ERRNO(EINVAL);
556258065Spjd		return (NULL);
557258065Spjd	}
558258065Spjd
559258065Spjd	if (strnlen((const char *)ptr, nvp->nvp_datasize) !=
560258065Spjd	    nvp->nvp_datasize - 1) {
561279438Srstone		RESTORE_ERRNO(EINVAL);
562258065Spjd		return (NULL);
563258065Spjd	}
564258065Spjd
565279438Srstone	nvp->nvp_data = (uint64_t)(uintptr_t)nv_strdup((const char *)ptr);
566258065Spjd	if (nvp->nvp_data == 0)
567258065Spjd		return (NULL);
568258065Spjd
569258065Spjd	ptr += nvp->nvp_datasize;
570258065Spjd	*leftp -= nvp->nvp_datasize;
571258065Spjd
572258065Spjd	return (ptr);
573258065Spjd}
574258065Spjd
575271579Spjdconst unsigned char *
576272843Spjdnvpair_unpack_nvlist(bool isbe __unused, nvpair_t *nvp,
577272843Spjd    const unsigned char *ptr, size_t *leftp, size_t nfds, nvlist_t **child)
578258065Spjd{
579258065Spjd	nvlist_t *value;
580258065Spjd
581258065Spjd	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST);
582258065Spjd
583258065Spjd	if (*leftp < nvp->nvp_datasize || nvp->nvp_datasize == 0) {
584279438Srstone		RESTORE_ERRNO(EINVAL);
585258065Spjd		return (NULL);
586258065Spjd	}
587258065Spjd
588271579Spjd	value = nvlist_create(0);
589258065Spjd	if (value == NULL)
590258065Spjd		return (NULL);
591258065Spjd
592272843Spjd	ptr = nvlist_unpack_header(value, ptr, nfds, NULL, leftp);
593271579Spjd	if (ptr == NULL)
594271579Spjd		return (NULL);
595271579Spjd
596258065Spjd	nvp->nvp_data = (uint64_t)(uintptr_t)value;
597271579Spjd	*child = value;
598258065Spjd
599258065Spjd	return (ptr);
600258065Spjd}
601258065Spjd
602279438Srstone#ifndef _KERNEL
603271579Spjdconst unsigned char *
604272843Spjdnvpair_unpack_descriptor(bool isbe, nvpair_t *nvp, const unsigned char *ptr,
605258065Spjd    size_t *leftp, const int *fds, size_t nfds)
606258065Spjd{
607258065Spjd	int64_t idx;
608258065Spjd
609258065Spjd	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR);
610258065Spjd
611258065Spjd	if (nvp->nvp_datasize != sizeof(idx)) {
612258065Spjd		errno = EINVAL;
613258065Spjd		return (NULL);
614258065Spjd	}
615258065Spjd	if (*leftp < sizeof(idx)) {
616258065Spjd		errno = EINVAL;
617258065Spjd		return (NULL);
618258065Spjd	}
619258065Spjd
620272843Spjd	if (isbe)
621258065Spjd		idx = be64dec(ptr);
622258065Spjd	else
623258065Spjd		idx = le64dec(ptr);
624258065Spjd
625258065Spjd	if (idx < 0) {
626258065Spjd		errno = EINVAL;
627258065Spjd		return (NULL);
628258065Spjd	}
629258065Spjd
630258065Spjd	if ((size_t)idx >= nfds) {
631258065Spjd		errno = EINVAL;
632258065Spjd		return (NULL);
633258065Spjd	}
634258065Spjd
635258065Spjd	nvp->nvp_data = (uint64_t)fds[idx];
636258065Spjd
637258065Spjd	ptr += sizeof(idx);
638258065Spjd	*leftp -= sizeof(idx);
639258065Spjd
640258065Spjd	return (ptr);
641258065Spjd}
642279438Srstone#endif
643258065Spjd
644271579Spjdconst unsigned char *
645272843Spjdnvpair_unpack_binary(bool isbe __unused, nvpair_t *nvp,
646258065Spjd    const unsigned char *ptr, size_t *leftp)
647258065Spjd{
648258065Spjd	void *value;
649258065Spjd
650258065Spjd	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BINARY);
651258065Spjd
652258065Spjd	if (*leftp < nvp->nvp_datasize || nvp->nvp_datasize == 0) {
653279438Srstone		RESTORE_ERRNO(EINVAL);
654258065Spjd		return (NULL);
655258065Spjd	}
656258065Spjd
657279438Srstone	value = nv_malloc(nvp->nvp_datasize);
658258065Spjd	if (value == NULL)
659258065Spjd		return (NULL);
660258065Spjd
661258065Spjd	memcpy(value, ptr, nvp->nvp_datasize);
662258065Spjd	ptr += nvp->nvp_datasize;
663258065Spjd	*leftp -= nvp->nvp_datasize;
664258065Spjd
665258065Spjd	nvp->nvp_data = (uint64_t)(uintptr_t)value;
666258065Spjd
667258065Spjd	return (ptr);
668258065Spjd}
669258065Spjd
670258065Spjdconst unsigned char *
671272843Spjdnvpair_unpack(bool isbe, const unsigned char *ptr, size_t *leftp,
672271579Spjd    nvpair_t **nvpp)
673258065Spjd{
674258065Spjd	nvpair_t *nvp, *tmp;
675258065Spjd
676279438Srstone	nvp = nv_calloc(1, sizeof(*nvp) + NV_NAME_MAX);
677258065Spjd	if (nvp == NULL)
678258065Spjd		return (NULL);
679258065Spjd	nvp->nvp_name = (char *)(nvp + 1);
680258065Spjd
681272843Spjd	ptr = nvpair_unpack_header(isbe, nvp, ptr, leftp);
682258065Spjd	if (ptr == NULL)
683258065Spjd		goto failed;
684279438Srstone	tmp = nv_realloc(nvp, sizeof(*nvp) + strlen(nvp->nvp_name) + 1);
685258594Spjd	if (tmp == NULL)
686258065Spjd		goto failed;
687258065Spjd	nvp = tmp;
688271579Spjd
689258065Spjd	/* Update nvp_name after realloc(). */
690258065Spjd	nvp->nvp_name = (char *)(nvp + 1);
691271579Spjd	nvp->nvp_data = 0x00;
692258065Spjd	nvp->nvp_magic = NVPAIR_MAGIC;
693258065Spjd	*nvpp = nvp;
694258065Spjd	return (ptr);
695258065Spjdfailed:
696279438Srstone	nv_free(nvp);
697258065Spjd	return (NULL);
698258065Spjd}
699258065Spjd
700258065Spjdint
701258065Spjdnvpair_type(const nvpair_t *nvp)
702258065Spjd{
703258065Spjd
704258065Spjd	NVPAIR_ASSERT(nvp);
705258065Spjd
706258065Spjd	return (nvp->nvp_type);
707258065Spjd}
708258065Spjd
709258065Spjdconst char *
710258065Spjdnvpair_name(const nvpair_t *nvp)
711258065Spjd{
712258065Spjd
713258065Spjd	NVPAIR_ASSERT(nvp);
714258065Spjd
715258065Spjd	return (nvp->nvp_name);
716258065Spjd}
717258065Spjd
718258065Spjdstatic nvpair_t *
719292637Sngienvpair_allocv(const char *name, int type, uint64_t data, size_t datasize)
720258065Spjd{
721258065Spjd	nvpair_t *nvp;
722292637Sngie	size_t namelen;
723258065Spjd
724258065Spjd	PJDLOG_ASSERT(type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST);
725258065Spjd
726292637Sngie	namelen = strlen(name);
727258065Spjd	if (namelen >= NV_NAME_MAX) {
728279438Srstone		RESTORE_ERRNO(ENAMETOOLONG);
729258065Spjd		return (NULL);
730258065Spjd	}
731258065Spjd
732279438Srstone	nvp = nv_calloc(1, sizeof(*nvp) + namelen + 1);
733258065Spjd	if (nvp != NULL) {
734258065Spjd		nvp->nvp_name = (char *)(nvp + 1);
735292637Sngie		memcpy(nvp->nvp_name, name, namelen);
736292637Sngie		nvp->nvp_name[namelen + 1] = '\0';
737258065Spjd		nvp->nvp_type = type;
738258065Spjd		nvp->nvp_data = data;
739258065Spjd		nvp->nvp_datasize = datasize;
740258065Spjd		nvp->nvp_magic = NVPAIR_MAGIC;
741258065Spjd	}
742258065Spjd
743258065Spjd	return (nvp);
744258065Spjd};
745258065Spjd
746258065Spjdnvpair_t *
747258065Spjdnvpair_create_stringf(const char *name, const char *valuefmt, ...)
748258065Spjd{
749258065Spjd	va_list valueap;
750258065Spjd	nvpair_t *nvp;
751258065Spjd
752258065Spjd	va_start(valueap, valuefmt);
753258065Spjd	nvp = nvpair_create_stringv(name, valuefmt, valueap);
754258065Spjd	va_end(valueap);
755258065Spjd
756258065Spjd	return (nvp);
757258065Spjd}
758258065Spjd
759258065Spjdnvpair_t *
760258065Spjdnvpair_create_stringv(const char *name, const char *valuefmt, va_list valueap)
761258065Spjd{
762258065Spjd	nvpair_t *nvp;
763258065Spjd	char *str;
764258065Spjd	int len;
765258065Spjd
766279438Srstone	len = nv_vasprintf(&str, valuefmt, valueap);
767258065Spjd	if (len < 0)
768258065Spjd		return (NULL);
769258065Spjd	nvp = nvpair_create_string(name, str);
770258065Spjd	if (nvp == NULL)
771279438Srstone		nv_free(str);
772258065Spjd	return (nvp);
773258065Spjd}
774258065Spjd
775258065Spjdnvpair_t *
776292637Sngienvpair_create_null(const char *name)
777258065Spjd{
778258065Spjd
779292637Sngie	return (nvpair_allocv(name, NV_TYPE_NULL, 0, 0));
780258065Spjd}
781258065Spjd
782258065Spjdnvpair_t *
783292637Sngienvpair_create_bool(const char *name, bool value)
784258065Spjd{
785258065Spjd
786292637Sngie	return (nvpair_allocv(name, NV_TYPE_BOOL, value ? 1 : 0,
787292637Sngie	    sizeof(uint8_t)));
788258065Spjd}
789258065Spjd
790258065Spjdnvpair_t *
791292637Sngienvpair_create_number(const char *name, uint64_t value)
792258065Spjd{
793258065Spjd
794292637Sngie	return (nvpair_allocv(name, NV_TYPE_NUMBER, value, sizeof(value)));
795258065Spjd}
796258065Spjd
797258065Spjdnvpair_t *
798292637Sngienvpair_create_string(const char *name, const char *value)
799258065Spjd{
800258065Spjd	nvpair_t *nvp;
801258065Spjd	size_t size;
802258065Spjd	char *data;
803258065Spjd
804258065Spjd	if (value == NULL) {
805279438Srstone		RESTORE_ERRNO(EINVAL);
806258065Spjd		return (NULL);
807258065Spjd	}
808258065Spjd
809279438Srstone	data = nv_strdup(value);
810258065Spjd	if (data == NULL)
811258065Spjd		return (NULL);
812258065Spjd	size = strlen(value) + 1;
813258065Spjd
814292637Sngie	nvp = nvpair_allocv(name, NV_TYPE_STRING, (uint64_t)(uintptr_t)data,
815292637Sngie	    size);
816258065Spjd	if (nvp == NULL)
817279438Srstone		nv_free(data);
818258065Spjd
819258065Spjd	return (nvp);
820258065Spjd}
821258065Spjd
822258065Spjdnvpair_t *
823292637Sngienvpair_create_nvlist(const char *name, const nvlist_t *value)
824258065Spjd{
825258065Spjd	nvlist_t *nvl;
826258065Spjd	nvpair_t *nvp;
827258065Spjd
828258065Spjd	if (value == NULL) {
829279438Srstone		RESTORE_ERRNO(EINVAL);
830258065Spjd		return (NULL);
831258065Spjd	}
832258065Spjd
833258065Spjd	nvl = nvlist_clone(value);
834258065Spjd	if (nvl == NULL)
835258065Spjd		return (NULL);
836258065Spjd
837292637Sngie	nvp = nvpair_allocv(name, NV_TYPE_NVLIST, (uint64_t)(uintptr_t)nvl, 0);
838258065Spjd	if (nvp == NULL)
839258065Spjd		nvlist_destroy(nvl);
840271847Spjd	else
841271847Spjd		nvlist_set_parent(nvl, nvp);
842258065Spjd
843258065Spjd	return (nvp);
844258065Spjd}
845258065Spjd
846279438Srstone#ifndef _KERNEL
847258065Spjdnvpair_t *
848292637Sngienvpair_create_descriptor(const char *name, int value)
849258065Spjd{
850258065Spjd	nvpair_t *nvp;
851258065Spjd
852258065Spjd	if (value < 0 || !fd_is_valid(value)) {
853258065Spjd		errno = EBADF;
854258065Spjd		return (NULL);
855258065Spjd	}
856258065Spjd
857258065Spjd	value = fcntl(value, F_DUPFD_CLOEXEC, 0);
858258065Spjd	if (value < 0)
859258065Spjd		return (NULL);
860258065Spjd
861292637Sngie	nvp = nvpair_allocv(name, NV_TYPE_DESCRIPTOR, (uint64_t)value,
862292637Sngie	    sizeof(int64_t));
863258065Spjd	if (nvp == NULL)
864258065Spjd		close(value);
865258065Spjd
866258065Spjd	return (nvp);
867258065Spjd}
868279438Srstone#endif
869258065Spjd
870258065Spjdnvpair_t *
871292637Sngienvpair_create_binary(const char *name, const void *value, size_t size)
872258065Spjd{
873258065Spjd	nvpair_t *nvp;
874258065Spjd	void *data;
875258065Spjd
876258065Spjd	if (value == NULL || size == 0) {
877279438Srstone		RESTORE_ERRNO(EINVAL);
878258065Spjd		return (NULL);
879258065Spjd	}
880258065Spjd
881279438Srstone	data = nv_malloc(size);
882258065Spjd	if (data == NULL)
883258065Spjd		return (NULL);
884258065Spjd	memcpy(data, value, size);
885258065Spjd
886292637Sngie	nvp = nvpair_allocv(name, NV_TYPE_BINARY, (uint64_t)(uintptr_t)data,
887292637Sngie	    size);
888258065Spjd	if (nvp == NULL)
889279438Srstone		nv_free(data);
890258065Spjd
891258065Spjd	return (nvp);
892258065Spjd}
893258065Spjd
894258065Spjdnvpair_t *
895258065Spjdnvpair_move_string(const char *name, char *value)
896258065Spjd{
897258065Spjd	nvpair_t *nvp;
898277920Spjd	int serrno;
899258065Spjd
900258065Spjd	if (value == NULL) {
901279438Srstone		RESTORE_ERRNO(EINVAL);
902258065Spjd		return (NULL);
903258065Spjd	}
904258065Spjd
905292637Sngie	nvp = nvpair_allocv(name, NV_TYPE_STRING, (uint64_t)(uintptr_t)value,
906292637Sngie	    strlen(value) + 1);
907277920Spjd	if (nvp == NULL) {
908279438Srstone		SAVE_ERRNO(serrno);
909279438Srstone		nv_free(value);
910279438Srstone		RESTORE_ERRNO(serrno);
911277920Spjd	}
912258065Spjd
913258065Spjd	return (nvp);
914258065Spjd}
915258065Spjd
916258065Spjdnvpair_t *
917292637Sngienvpair_move_nvlist(const char *name, nvlist_t *value)
918258065Spjd{
919258065Spjd	nvpair_t *nvp;
920258065Spjd
921271579Spjd	if (value == NULL || nvlist_get_nvpair_parent(value) != NULL) {
922279438Srstone		RESTORE_ERRNO(EINVAL);
923258065Spjd		return (NULL);
924258065Spjd	}
925258065Spjd
926279436Srstone	if (nvlist_error(value) != 0) {
927279438Srstone		RESTORE_ERRNO(nvlist_error(value));
928279436Srstone		nvlist_destroy(value);
929279436Srstone		return (NULL);
930279436Srstone	}
931279436Srstone
932292637Sngie	nvp = nvpair_allocv(name, NV_TYPE_NVLIST, (uint64_t)(uintptr_t)value,
933292637Sngie	    0);
934258065Spjd	if (nvp == NULL)
935258065Spjd		nvlist_destroy(value);
936271579Spjd	else
937271579Spjd		nvlist_set_parent(value, nvp);
938258065Spjd
939258065Spjd	return (nvp);
940258065Spjd}
941258065Spjd
942279438Srstone#ifndef _KERNEL
943258065Spjdnvpair_t *
944292637Sngienvpair_move_descriptor(const char *name, int value)
945258065Spjd{
946277920Spjd	nvpair_t *nvp;
947277920Spjd	int serrno;
948258065Spjd
949258065Spjd	if (value < 0 || !fd_is_valid(value)) {
950258065Spjd		errno = EBADF;
951258065Spjd		return (NULL);
952258065Spjd	}
953258065Spjd
954292637Sngie	nvp = nvpair_allocv(name, NV_TYPE_DESCRIPTOR, (uint64_t)value,
955292637Sngie	    sizeof(int64_t));
956277920Spjd	if (nvp == NULL) {
957277920Spjd		serrno = errno;
958277920Spjd		close(value);
959277920Spjd		errno = serrno;
960277920Spjd	}
961277920Spjd
962277920Spjd	return (nvp);
963258065Spjd}
964279438Srstone#endif
965258065Spjd
966258065Spjdnvpair_t *
967292637Sngienvpair_move_binary(const char *name, void *value, size_t size)
968258065Spjd{
969277920Spjd	nvpair_t *nvp;
970277920Spjd	int serrno;
971258065Spjd
972258065Spjd	if (value == NULL || size == 0) {
973279438Srstone		RESTORE_ERRNO(EINVAL);
974258065Spjd		return (NULL);
975258065Spjd	}
976258065Spjd
977292637Sngie	nvp = nvpair_allocv(name, NV_TYPE_BINARY, (uint64_t)(uintptr_t)value,
978292637Sngie	    size);
979277920Spjd	if (nvp == NULL) {
980279438Srstone		SAVE_ERRNO(serrno);
981279438Srstone		nv_free(value);
982279438Srstone		RESTORE_ERRNO(serrno);
983277920Spjd	}
984277920Spjd
985277920Spjd	return (nvp);
986258065Spjd}
987258065Spjd
988258065Spjdbool
989258065Spjdnvpair_get_bool(const nvpair_t *nvp)
990258065Spjd{
991258065Spjd
992258065Spjd	NVPAIR_ASSERT(nvp);
993258065Spjd
994258065Spjd	return (nvp->nvp_data == 1);
995258065Spjd}
996258065Spjd
997258065Spjduint64_t
998258065Spjdnvpair_get_number(const nvpair_t *nvp)
999258065Spjd{
1000258065Spjd
1001258065Spjd	NVPAIR_ASSERT(nvp);
1002258065Spjd
1003258065Spjd	return (nvp->nvp_data);
1004258065Spjd}
1005258065Spjd
1006258065Spjdconst char *
1007258065Spjdnvpair_get_string(const nvpair_t *nvp)
1008258065Spjd{
1009258065Spjd
1010258065Spjd	NVPAIR_ASSERT(nvp);
1011258065Spjd	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING);
1012258065Spjd
1013258065Spjd	return ((const char *)(intptr_t)nvp->nvp_data);
1014258065Spjd}
1015258065Spjd
1016258065Spjdconst nvlist_t *
1017258065Spjdnvpair_get_nvlist(const nvpair_t *nvp)
1018258065Spjd{
1019258065Spjd
1020258065Spjd	NVPAIR_ASSERT(nvp);
1021258065Spjd	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST);
1022258065Spjd
1023258065Spjd	return ((const nvlist_t *)(intptr_t)nvp->nvp_data);
1024258065Spjd}
1025258065Spjd
1026279438Srstone#ifndef _KERNEL
1027258065Spjdint
1028258065Spjdnvpair_get_descriptor(const nvpair_t *nvp)
1029258065Spjd{
1030258065Spjd
1031258065Spjd	NVPAIR_ASSERT(nvp);
1032258065Spjd	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR);
1033258065Spjd
1034258065Spjd	return ((int)nvp->nvp_data);
1035258065Spjd}
1036279438Srstone#endif
1037258065Spjd
1038258065Spjdconst void *
1039258065Spjdnvpair_get_binary(const nvpair_t *nvp, size_t *sizep)
1040258065Spjd{
1041258065Spjd
1042258065Spjd	NVPAIR_ASSERT(nvp);
1043258065Spjd	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BINARY);
1044258065Spjd
1045258065Spjd	if (sizep != NULL)
1046258065Spjd		*sizep = nvp->nvp_datasize;
1047258065Spjd	return ((const void *)(intptr_t)nvp->nvp_data);
1048258065Spjd}
1049258065Spjd
1050258065Spjdvoid
1051258065Spjdnvpair_free(nvpair_t *nvp)
1052258065Spjd{
1053258065Spjd
1054258065Spjd	NVPAIR_ASSERT(nvp);
1055258065Spjd	PJDLOG_ASSERT(nvp->nvp_list == NULL);
1056258065Spjd
1057258065Spjd	nvp->nvp_magic = 0;
1058258065Spjd	switch (nvp->nvp_type) {
1059279438Srstone#ifndef _KERNEL
1060258065Spjd	case NV_TYPE_DESCRIPTOR:
1061258065Spjd		close((int)nvp->nvp_data);
1062258065Spjd		break;
1063279438Srstone#endif
1064258065Spjd	case NV_TYPE_NVLIST:
1065258065Spjd		nvlist_destroy((nvlist_t *)(intptr_t)nvp->nvp_data);
1066258065Spjd		break;
1067258065Spjd	case NV_TYPE_STRING:
1068279438Srstone		nv_free((char *)(intptr_t)nvp->nvp_data);
1069258065Spjd		break;
1070258065Spjd	case NV_TYPE_BINARY:
1071279438Srstone		nv_free((void *)(intptr_t)nvp->nvp_data);
1072258065Spjd		break;
1073258065Spjd	}
1074279438Srstone	nv_free(nvp);
1075258065Spjd}
1076258065Spjd
1077258065Spjdvoid
1078258065Spjdnvpair_free_structure(nvpair_t *nvp)
1079258065Spjd{
1080258065Spjd
1081258065Spjd	NVPAIR_ASSERT(nvp);
1082258065Spjd	PJDLOG_ASSERT(nvp->nvp_list == NULL);
1083258065Spjd
1084258065Spjd	nvp->nvp_magic = 0;
1085279438Srstone	nv_free(nvp);
1086258065Spjd}
1087258065Spjd
1088258065Spjdconst char *
1089258065Spjdnvpair_type_string(int type)
1090258065Spjd{
1091258065Spjd
1092258065Spjd	switch (type) {
1093258065Spjd	case NV_TYPE_NULL:
1094258065Spjd		return ("NULL");
1095258065Spjd	case NV_TYPE_BOOL:
1096258065Spjd		return ("BOOL");
1097258065Spjd	case NV_TYPE_NUMBER:
1098258065Spjd		return ("NUMBER");
1099258065Spjd	case NV_TYPE_STRING:
1100258065Spjd		return ("STRING");
1101258065Spjd	case NV_TYPE_NVLIST:
1102258065Spjd		return ("NVLIST");
1103258065Spjd	case NV_TYPE_DESCRIPTOR:
1104258065Spjd		return ("DESCRIPTOR");
1105258065Spjd	case NV_TYPE_BINARY:
1106258065Spjd		return ("BINARY");
1107258065Spjd	default:
1108258065Spjd		return ("<UNKNOWN>");
1109258065Spjd	}
1110258065Spjd}
1111292637Sngie
1112