xref: /trueos/sys/kern/subr_nvpair.c (revision 40782981b22ef4e5389f32da5c91672c6e5e7429)
1 /*-
2  * Copyright (c) 2009-2013 The FreeBSD Foundation
3  * All rights reserved.
4  *
5  * This software was developed by Pawel Jakub Dawidek under sponsorship from
6  * the FreeBSD Foundation.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  */
29 
30 #include <sys/cdefs.h>
31 __FBSDID("$FreeBSD$");
32 
33 #include <sys/param.h>
34 #include <sys/endian.h>
35 #include <sys/queue.h>
36 
37 #ifdef _KERNEL
38 
39 #include <sys/errno.h>
40 #include <sys/lock.h>
41 #include <sys/malloc.h>
42 #include <sys/systm.h>
43 
44 #include <machine/stdarg.h>
45 
46 #else
47 #include <errno.h>
48 #include <fcntl.h>
49 #include <stdarg.h>
50 #include <stdbool.h>
51 #include <stdint.h>
52 #include <stdlib.h>
53 #include <string.h>
54 #include <unistd.h>
55 
56 #include "common_impl.h"
57 #endif
58 
59 #ifdef HAVE_PJDLOG
60 #include <pjdlog.h>
61 #endif
62 
63 #include <sys/nv.h>
64 #include <sys/nv_impl.h>
65 #include <sys/nvlist_impl.h>
66 #include <sys/nvpair_impl.h>
67 
68 #ifndef	HAVE_PJDLOG
69 #ifdef _KERNEL
70 #define	PJDLOG_ASSERT(...)		MPASS(__VA_ARGS__)
71 #define	PJDLOG_RASSERT(expr, ...)	KASSERT(expr, (__VA_ARGS__))
72 #define	PJDLOG_ABORT(...)		panic(__VA_ARGS__)
73 #else
74 #include <assert.h>
75 #define	PJDLOG_ASSERT(...)		assert(__VA_ARGS__)
76 #define	PJDLOG_RASSERT(expr, ...)	assert(expr)
77 #define	PJDLOG_ABORT(...)		abort()
78 #endif
79 #endif
80 
81 #define	NVPAIR_MAGIC	0x6e7670	/* "nvp" */
82 struct nvpair {
83 	int		 nvp_magic;
84 	char		*nvp_name;
85 	int		 nvp_type;
86 	uint64_t	 nvp_data;
87 	size_t		 nvp_datasize;
88 	nvlist_t	*nvp_list;
89 	TAILQ_ENTRY(nvpair) nvp_next;
90 };
91 
92 #define	NVPAIR_ASSERT(nvp)	do {					\
93 	PJDLOG_ASSERT((nvp) != NULL);					\
94 	PJDLOG_ASSERT((nvp)->nvp_magic == NVPAIR_MAGIC);		\
95 } while (0)
96 
97 struct nvpair_header {
98 	uint8_t		nvph_type;
99 	uint16_t	nvph_namesize;
100 	uint64_t	nvph_datasize;
101 } __packed;
102 
103 
104 void
nvpair_assert(const nvpair_t * nvp)105 nvpair_assert(const nvpair_t *nvp)
106 {
107 
108 	NVPAIR_ASSERT(nvp);
109 }
110 
111 nvlist_t *
nvpair_nvlist(const nvpair_t * nvp)112 nvpair_nvlist(const nvpair_t *nvp)
113 {
114 
115 	NVPAIR_ASSERT(nvp);
116 
117 	return (nvp->nvp_list);
118 }
119 
120 nvpair_t *
nvpair_next(const nvpair_t * nvp)121 nvpair_next(const nvpair_t *nvp)
122 {
123 
124 	NVPAIR_ASSERT(nvp);
125 	PJDLOG_ASSERT(nvp->nvp_list != NULL);
126 
127 	return (TAILQ_NEXT(nvp, nvp_next));
128 }
129 
130 nvpair_t *
nvpair_prev(const nvpair_t * nvp)131 nvpair_prev(const nvpair_t *nvp)
132 {
133 
134 	NVPAIR_ASSERT(nvp);
135 	PJDLOG_ASSERT(nvp->nvp_list != NULL);
136 
137 	return (TAILQ_PREV(nvp, nvl_head, nvp_next));
138 }
139 
140 void
nvpair_insert(struct nvl_head * head,nvpair_t * nvp,nvlist_t * nvl)141 nvpair_insert(struct nvl_head *head, nvpair_t *nvp, nvlist_t *nvl)
142 {
143 
144 	NVPAIR_ASSERT(nvp);
145 	PJDLOG_ASSERT(nvp->nvp_list == NULL);
146 	PJDLOG_ASSERT(!nvlist_exists(nvl, nvpair_name(nvp)));
147 
148 	TAILQ_INSERT_TAIL(head, nvp, nvp_next);
149 	nvp->nvp_list = nvl;
150 }
151 
152 static void
nvpair_remove_nvlist(nvpair_t * nvp)153 nvpair_remove_nvlist(nvpair_t *nvp)
154 {
155 	nvlist_t *nvl;
156 
157 	/* XXX: DECONST is bad, mkay? */
158 	nvl = __DECONST(nvlist_t *, nvpair_get_nvlist(nvp));
159 	PJDLOG_ASSERT(nvl != NULL);
160 	nvlist_set_parent(nvl, NULL);
161 }
162 
163 void
nvpair_remove(struct nvl_head * head,nvpair_t * nvp,const nvlist_t * nvl)164 nvpair_remove(struct nvl_head *head, nvpair_t *nvp, const nvlist_t *nvl)
165 {
166 
167 	NVPAIR_ASSERT(nvp);
168 	PJDLOG_ASSERT(nvp->nvp_list == nvl);
169 
170 	if (nvpair_type(nvp) == NV_TYPE_NVLIST ||
171 		nvpair_type(nvp) == NV_TYPE_NVLIST_ARRAY ||
172 		nvpair_type(nvp) == NV_TYPE_NVLIST_DICTIONARY)
173 		nvpair_remove_nvlist(nvp);
174 
175 	TAILQ_REMOVE(head, nvp, nvp_next);
176 	nvp->nvp_list = NULL;
177 }
178 
179 nvpair_t *
nvpair_clone(const nvpair_t * nvp)180 nvpair_clone(const nvpair_t *nvp)
181 {
182 	nvpair_t *newnvp;
183 	const char *name;
184 	const void *data;
185 	size_t datasize;
186 
187 	NVPAIR_ASSERT(nvp);
188 
189 	name = nvpair_name(nvp);
190 
191 	switch (nvpair_type(nvp)) {
192 	case NV_TYPE_NULL:
193 		newnvp = nvpair_create_null(name);
194 		break;
195 	case NV_TYPE_BOOL:
196 		newnvp = nvpair_create_bool(name, nvpair_get_bool(nvp));
197 		break;
198 	case NV_TYPE_NUMBER:
199 	case NV_TYPE_PTR:
200 	case NV_TYPE_UINT64:
201 	case NV_TYPE_INT64:
202 	case NV_TYPE_ENDPOINT:
203 		newnvp = nvpair_create_number_type(name, nvpair_get_number(nvp), nvpair_type(nvp));
204 		break;
205 	case NV_TYPE_STRING:
206 		newnvp = nvpair_create_string(name, nvpair_get_string(nvp));
207 		break;
208 	case NV_TYPE_NVLIST:
209 	case NV_TYPE_NVLIST_ARRAY:
210 	case NV_TYPE_NVLIST_DICTIONARY:
211 		newnvp = nvpair_create_nvlist_type(name, nvpair_get_nvlist(nvp), nvpair_type(nvp));
212 		break;
213 #ifndef _KERNEL
214 	case NV_TYPE_DESCRIPTOR:
215 		newnvp = nvpair_create_descriptor(name,
216 		    nvpair_get_descriptor(nvp));
217 		break;
218 #endif
219 	case NV_TYPE_BINARY:
220 		data = nvpair_get_binary(nvp, &datasize);
221 		newnvp = nvpair_create_binary(name, data, datasize);
222 		break;
223 	case NV_TYPE_UUID:
224 		data = nvpair_get_uuid(nvp);
225 		newnvp = nvpair_create_uuid(name, data);
226 		break;
227 	default:
228 		PJDLOG_ABORT("Unknown type: %d.", nvpair_type(nvp));
229 	}
230 
231 	return (newnvp);
232 }
233 
234 size_t
nvpair_header_size(void)235 nvpair_header_size(void)
236 {
237 
238 	return (sizeof(struct nvpair_header));
239 }
240 
241 size_t
nvpair_size(const nvpair_t * nvp)242 nvpair_size(const nvpair_t *nvp)
243 {
244 
245 	NVPAIR_ASSERT(nvp);
246 
247 	return (nvp->nvp_datasize);
248 }
249 
250 unsigned char *
nvpair_pack_header(const nvpair_t * nvp,unsigned char * ptr,size_t * leftp)251 nvpair_pack_header(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp)
252 {
253 	struct nvpair_header nvphdr;
254 	size_t namesize;
255 
256 	NVPAIR_ASSERT(nvp);
257 
258 	nvphdr.nvph_type = nvp->nvp_type;
259 	namesize = strlen(nvp->nvp_name) + 1;
260 	PJDLOG_ASSERT(namesize > 0 && namesize <= UINT16_MAX);
261 	nvphdr.nvph_namesize = namesize;
262 	nvphdr.nvph_datasize = nvp->nvp_datasize;
263 	PJDLOG_ASSERT(*leftp >= sizeof(nvphdr));
264 	memcpy(ptr, &nvphdr, sizeof(nvphdr));
265 	ptr += sizeof(nvphdr);
266 	*leftp -= sizeof(nvphdr);
267 
268 	PJDLOG_ASSERT(*leftp >= namesize);
269 	memcpy(ptr, nvp->nvp_name, namesize);
270 	ptr += namesize;
271 	*leftp -= namesize;
272 
273 	return (ptr);
274 }
275 
276 unsigned char *
nvpair_pack_null(const nvpair_t * nvp,unsigned char * ptr,size_t * leftp __unused)277 nvpair_pack_null(const nvpair_t *nvp, unsigned char *ptr,
278     size_t *leftp __unused)
279 {
280 
281 	NVPAIR_ASSERT(nvp);
282 	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NULL);
283 
284 	return (ptr);
285 }
286 
287 unsigned char *
nvpair_pack_bool(const nvpair_t * nvp,unsigned char * ptr,size_t * leftp)288 nvpair_pack_bool(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp)
289 {
290 	uint8_t value;
291 
292 	NVPAIR_ASSERT(nvp);
293 	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BOOL);
294 
295 	value = (uint8_t)nvp->nvp_data;
296 
297 	PJDLOG_ASSERT(*leftp >= sizeof(value));
298 	memcpy(ptr, &value, sizeof(value));
299 	ptr += sizeof(value);
300 	*leftp -= sizeof(value);
301 
302 	return (ptr);
303 }
304 
305 unsigned char *
nvpair_pack_number(const nvpair_t * nvp,unsigned char * ptr,size_t * leftp)306 nvpair_pack_number(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp)
307 {
308 	uint64_t value;
309 
310 	NVPAIR_ASSERT(nvp);
311 	PJDLOG_ASSERT(
312 	    nvp->nvp_type == NV_TYPE_NUMBER ||
313 	    nvp->nvp_type == NV_TYPE_PTR ||
314 	    nvp->nvp_type == NV_TYPE_UINT64 ||
315 	    nvp->nvp_type == NV_TYPE_INT64 ||
316 	    nvp->nvp_type == NV_TYPE_ENDPOINT ||
317 	    nvp->nvp_type == NV_TYPE_DATE
318 	);
319 
320 	value = (uint64_t)nvp->nvp_data;
321 
322 	PJDLOG_ASSERT(*leftp >= sizeof(value));
323 	memcpy(ptr, &value, sizeof(value));
324 	ptr += sizeof(value);
325 	*leftp -= sizeof(value);
326 
327 	return (ptr);
328 }
329 
330 unsigned char *
nvpair_pack_string(const nvpair_t * nvp,unsigned char * ptr,size_t * leftp)331 nvpair_pack_string(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp)
332 {
333 
334 	NVPAIR_ASSERT(nvp);
335 	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING);
336 
337 	PJDLOG_ASSERT(*leftp >= nvp->nvp_datasize);
338 	memcpy(ptr, (const void *)(intptr_t)nvp->nvp_data, nvp->nvp_datasize);
339 	ptr += nvp->nvp_datasize;
340 	*leftp -= nvp->nvp_datasize;
341 
342 	return (ptr);
343 }
344 
345 unsigned char *
nvpair_pack_nvlist_up(unsigned char * ptr,size_t * leftp)346 nvpair_pack_nvlist_up(unsigned char *ptr, size_t *leftp)
347 {
348 	struct nvpair_header nvphdr;
349 	size_t namesize;
350 	const char *name = "";
351 
352 	namesize = 1;
353 	nvphdr.nvph_type = NV_TYPE_NVLIST_UP;
354 	nvphdr.nvph_namesize = namesize;
355 	nvphdr.nvph_datasize = 0;
356 	PJDLOG_ASSERT(*leftp >= sizeof(nvphdr));
357 	memcpy(ptr, &nvphdr, sizeof(nvphdr));
358 	ptr += sizeof(nvphdr);
359 	*leftp -= sizeof(nvphdr);
360 
361 	PJDLOG_ASSERT(*leftp >= namesize);
362 	memcpy(ptr, name, namesize);
363 	ptr += namesize;
364 	*leftp -= namesize;
365 
366 	return (ptr);
367 }
368 
369 #ifndef _KERNEL
370 unsigned char *
nvpair_pack_descriptor(const nvpair_t * nvp,unsigned char * ptr,int64_t * fdidxp,size_t * leftp)371 nvpair_pack_descriptor(const nvpair_t *nvp, unsigned char *ptr, int64_t *fdidxp,
372     size_t *leftp)
373 {
374 	int64_t value;
375 
376 	NVPAIR_ASSERT(nvp);
377 	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR);
378 
379 	value = (int64_t)nvp->nvp_data;
380 	if (value != -1) {
381 		/*
382 		 * If there is a real descriptor here, we change its number
383 		 * to position in the array of descriptors send via control
384 		 * message.
385 		 */
386 		PJDLOG_ASSERT(fdidxp != NULL);
387 
388 		value = *fdidxp;
389 		(*fdidxp)++;
390 	}
391 
392 	PJDLOG_ASSERT(*leftp >= sizeof(value));
393 	memcpy(ptr, &value, sizeof(value));
394 	ptr += sizeof(value);
395 	*leftp -= sizeof(value);
396 
397 	return (ptr);
398 }
399 #endif
400 
401 unsigned char *
nvpair_pack_binary(const nvpair_t * nvp,unsigned char * ptr,size_t * leftp)402 nvpair_pack_binary(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp)
403 {
404 
405 	NVPAIR_ASSERT(nvp);
406 	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BINARY);
407 
408 	PJDLOG_ASSERT(*leftp >= nvp->nvp_datasize);
409 	memcpy(ptr, (const void *)(intptr_t)nvp->nvp_data, nvp->nvp_datasize);
410 	ptr += nvp->nvp_datasize;
411 	*leftp -= nvp->nvp_datasize;
412 
413 	return (ptr);
414 }
415 
416 void
nvpair_init_datasize(nvpair_t * nvp)417 nvpair_init_datasize(nvpair_t *nvp)
418 {
419 
420 	NVPAIR_ASSERT(nvp);
421 
422 	if (nvp->nvp_type == NV_TYPE_NVLIST_ARRAY ||
423 		nvp->nvp_type == NV_TYPE_NVLIST_DICTIONARY ||
424 		nvp->nvp_type == NV_TYPE_NVLIST) {
425 		if (nvp->nvp_data == 0) {
426 			nvp->nvp_datasize = 0;
427 		} else {
428 			nvp->nvp_datasize =
429 			    nvlist_size((const nvlist_t *)(intptr_t)nvp->nvp_data);
430 		}
431 	}
432 }
433 
434 const unsigned char *
nvpair_unpack_header(bool isbe,nvpair_t * nvp,const unsigned char * ptr,size_t * leftp)435 nvpair_unpack_header(bool isbe, nvpair_t *nvp, const unsigned char *ptr,
436     size_t *leftp)
437 {
438 	struct nvpair_header nvphdr;
439 
440 	if (*leftp < sizeof(nvphdr))
441 		goto failed;
442 
443 	memcpy(&nvphdr, ptr, sizeof(nvphdr));
444 	ptr += sizeof(nvphdr);
445 	*leftp -= sizeof(nvphdr);
446 
447 #if NV_TYPE_FIRST > 0
448 	if (nvphdr.nvph_type < NV_TYPE_FIRST)
449 		goto failed;
450 #endif
451 	if (nvphdr.nvph_type > NV_TYPE_LAST &&
452 	    nvphdr.nvph_type != NV_TYPE_NVLIST_UP) {
453 		goto failed;
454 	}
455 
456 #if BYTE_ORDER == BIG_ENDIAN
457 	if (!isbe) {
458 		nvphdr.nvph_namesize = le16toh(nvphdr.nvph_namesize);
459 		nvphdr.nvph_datasize = le64toh(nvphdr.nvph_datasize);
460 	}
461 #else
462 	if (isbe) {
463 		nvphdr.nvph_namesize = be16toh(nvphdr.nvph_namesize);
464 		nvphdr.nvph_datasize = be64toh(nvphdr.nvph_datasize);
465 	}
466 #endif
467 
468 	if (nvphdr.nvph_namesize > NV_NAME_MAX)
469 		goto failed;
470 	if (*leftp < nvphdr.nvph_namesize)
471 		goto failed;
472 	if (nvphdr.nvph_namesize < 1)
473 		goto failed;
474 	if (strnlen((const char *)ptr, nvphdr.nvph_namesize) !=
475 	    (size_t)(nvphdr.nvph_namesize - 1)) {
476 		goto failed;
477 	}
478 
479 	memcpy(nvp->nvp_name, ptr, nvphdr.nvph_namesize);
480 	ptr += nvphdr.nvph_namesize;
481 	*leftp -= nvphdr.nvph_namesize;
482 
483 	if (*leftp < nvphdr.nvph_datasize)
484 		goto failed;
485 
486 	nvp->nvp_type = nvphdr.nvph_type;
487 	nvp->nvp_data = 0;
488 	nvp->nvp_datasize = nvphdr.nvph_datasize;
489 
490 	return (ptr);
491 failed:
492 	RESTORE_ERRNO(EINVAL);
493 	return (NULL);
494 }
495 
496 const unsigned char *
nvpair_unpack_null(bool isbe __unused,nvpair_t * nvp,const unsigned char * ptr,size_t * leftp __unused)497 nvpair_unpack_null(bool isbe __unused, nvpair_t *nvp, const unsigned char *ptr,
498     size_t *leftp __unused)
499 {
500 
501 	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NULL);
502 
503 	if (nvp->nvp_datasize != 0) {
504 		RESTORE_ERRNO(EINVAL);
505 		return (NULL);
506 	}
507 
508 	return (ptr);
509 }
510 
511 const unsigned char *
nvpair_unpack_bool(bool isbe __unused,nvpair_t * nvp,const unsigned char * ptr,size_t * leftp)512 nvpair_unpack_bool(bool isbe __unused, nvpair_t *nvp, const unsigned char *ptr,
513     size_t *leftp)
514 {
515 	uint8_t value;
516 
517 	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BOOL);
518 
519 	if (nvp->nvp_datasize != sizeof(value)) {
520 		RESTORE_ERRNO(EINVAL);
521 		return (NULL);
522 	}
523 	if (*leftp < sizeof(value)) {
524 		RESTORE_ERRNO(EINVAL);
525 		return (NULL);
526 	}
527 
528 	memcpy(&value, ptr, sizeof(value));
529 	ptr += sizeof(value);
530 	*leftp -= sizeof(value);
531 
532 	if (value != 0 && value != 1) {
533 		RESTORE_ERRNO(EINVAL);
534 		return (NULL);
535 	}
536 
537 	nvp->nvp_data = (uint64_t)value;
538 
539 	return (ptr);
540 }
541 
542 const unsigned char *
nvpair_unpack_number(bool isbe,nvpair_t * nvp,const unsigned char * ptr,size_t * leftp)543 nvpair_unpack_number(bool isbe, nvpair_t *nvp, const unsigned char *ptr,
544      size_t *leftp)
545 {
546 
547 	PJDLOG_ASSERT(
548 	    nvp->nvp_type == NV_TYPE_NUMBER ||
549 	    nvp->nvp_type == NV_TYPE_PTR ||
550 	    nvp->nvp_type == NV_TYPE_UINT64 ||
551 	    nvp->nvp_type == NV_TYPE_INT64 ||
552 	    nvp->nvp_type == NV_TYPE_ENDPOINT ||
553 	    nvp->nvp_type == NV_TYPE_DATE
554 	);
555 
556 	if (nvp->nvp_datasize != sizeof(uint64_t)) {
557 		RESTORE_ERRNO(EINVAL);
558 		return (NULL);
559 	}
560 	if (*leftp < sizeof(uint64_t)) {
561 		RESTORE_ERRNO(EINVAL);
562 		return (NULL);
563 	}
564 
565 	if (isbe)
566 		nvp->nvp_data = be64dec(ptr);
567 	else
568 		nvp->nvp_data = le64dec(ptr);
569 	ptr += sizeof(uint64_t);
570 	*leftp -= sizeof(uint64_t);
571 
572 	return (ptr);
573 }
574 
575 const unsigned char *
nvpair_unpack_string(bool isbe __unused,nvpair_t * nvp,const unsigned char * ptr,size_t * leftp)576 nvpair_unpack_string(bool isbe __unused, nvpair_t *nvp,
577     const unsigned char *ptr, size_t *leftp)
578 {
579 
580 	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING);
581 
582 	if (*leftp < nvp->nvp_datasize || nvp->nvp_datasize == 0) {
583 		RESTORE_ERRNO(EINVAL);
584 		return (NULL);
585 	}
586 
587 	if (strnlen((const char *)ptr, nvp->nvp_datasize) !=
588 	    nvp->nvp_datasize - 1) {
589 		RESTORE_ERRNO(EINVAL);
590 		return (NULL);
591 	}
592 
593 	nvp->nvp_data = (uint64_t)(uintptr_t)nv_strdup((const char *)ptr);
594 	if (nvp->nvp_data == 0)
595 		return (NULL);
596 
597 	ptr += nvp->nvp_datasize;
598 	*leftp -= nvp->nvp_datasize;
599 
600 	return (ptr);
601 }
602 
603 const unsigned char *
nvpair_unpack_nvlist(bool isbe __unused,nvpair_t * nvp,const unsigned char * ptr,size_t * leftp,size_t nfds,nvlist_t ** child)604 nvpair_unpack_nvlist(bool isbe __unused, nvpair_t *nvp,
605     const unsigned char *ptr, size_t *leftp, size_t nfds, nvlist_t **child)
606 {
607 	nvlist_t *value;
608 
609 	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST ||
610 	    nvp->nvp_type == NV_TYPE_NVLIST_ARRAY ||
611 	    nvp->nvp_type == NV_TYPE_NVLIST_DICTIONARY);
612 
613 	if (*leftp < nvp->nvp_datasize || nvp->nvp_datasize == 0) {
614 		RESTORE_ERRNO(EINVAL);
615 		return (NULL);
616 	}
617 
618 	switch (nvp->nvp_type) {
619 	case NV_TYPE_NVLIST:
620 		value = nvlist_create(0);
621 		break;
622 	case NV_TYPE_NVLIST_ARRAY:
623 		value = nvlist_create_array(0);
624 		break;
625 	case NV_TYPE_NVLIST_DICTIONARY:
626 		value = nvlist_create_dictionary(0);
627 	}
628 
629 	if (value == NULL)
630 		return (NULL);
631 
632 	ptr = nvlist_unpack_header(value, ptr, nfds, NULL, leftp);
633 	if (ptr == NULL)
634 		return (NULL);
635 
636 	nvp->nvp_data = (uint64_t)(uintptr_t)value;
637 	*child = value;
638 
639 	return (ptr);
640 }
641 
642 #ifndef _KERNEL
643 const unsigned char *
nvpair_unpack_descriptor(bool isbe,nvpair_t * nvp,const unsigned char * ptr,size_t * leftp,const int * fds,size_t nfds)644 nvpair_unpack_descriptor(bool isbe, nvpair_t *nvp, const unsigned char *ptr,
645     size_t *leftp, const int *fds, size_t nfds)
646 {
647 	int64_t idx;
648 
649 	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR);
650 
651 	if (nvp->nvp_datasize != sizeof(idx)) {
652 		errno = EINVAL;
653 		return (NULL);
654 	}
655 	if (*leftp < sizeof(idx)) {
656 		errno = EINVAL;
657 		return (NULL);
658 	}
659 
660 	if (isbe)
661 		idx = be64dec(ptr);
662 	else
663 		idx = le64dec(ptr);
664 
665 	if (idx < 0) {
666 		errno = EINVAL;
667 		return (NULL);
668 	}
669 
670 	if ((size_t)idx >= nfds) {
671 		errno = EINVAL;
672 		return (NULL);
673 	}
674 
675 	nvp->nvp_data = (uint64_t)fds[idx];
676 
677 	ptr += sizeof(idx);
678 	*leftp -= sizeof(idx);
679 
680 	return (ptr);
681 }
682 #endif
683 
684 const unsigned char *
nvpair_unpack_binary(bool isbe __unused,nvpair_t * nvp,const unsigned char * ptr,size_t * leftp)685 nvpair_unpack_binary(bool isbe __unused, nvpair_t *nvp,
686     const unsigned char *ptr, size_t *leftp)
687 {
688 	void *value;
689 
690 	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BINARY);
691 
692 	if (*leftp < nvp->nvp_datasize || nvp->nvp_datasize == 0) {
693 		RESTORE_ERRNO(EINVAL);
694 		return (NULL);
695 	}
696 
697 	value = nv_malloc(nvp->nvp_datasize);
698 	if (value == NULL)
699 		return (NULL);
700 
701 	memcpy(value, ptr, nvp->nvp_datasize);
702 	ptr += nvp->nvp_datasize;
703 	*leftp -= nvp->nvp_datasize;
704 
705 	nvp->nvp_data = (uint64_t)(uintptr_t)value;
706 
707 	return (ptr);
708 }
709 
710 const unsigned char *
nvpair_unpack(bool isbe,const unsigned char * ptr,size_t * leftp,nvpair_t ** nvpp)711 nvpair_unpack(bool isbe, const unsigned char *ptr, size_t *leftp,
712     nvpair_t **nvpp)
713 {
714 	nvpair_t *nvp, *tmp;
715 
716 	nvp = nv_calloc(1, sizeof(*nvp) + NV_NAME_MAX);
717 	if (nvp == NULL)
718 		return (NULL);
719 	nvp->nvp_name = (char *)(nvp + 1);
720 
721 	ptr = nvpair_unpack_header(isbe, nvp, ptr, leftp);
722 	if (ptr == NULL)
723 		goto failed;
724 	tmp = nv_realloc(nvp, sizeof(*nvp) + strlen(nvp->nvp_name) + 1);
725 	if (tmp == NULL)
726 		goto failed;
727 	nvp = tmp;
728 
729 	/* Update nvp_name after realloc(). */
730 	nvp->nvp_name = (char *)(nvp + 1);
731 	nvp->nvp_data = 0x00;
732 	nvp->nvp_magic = NVPAIR_MAGIC;
733 	*nvpp = nvp;
734 	return (ptr);
735 failed:
736 	nv_free(nvp);
737 	return (NULL);
738 }
739 
740 int
nvpair_type(const nvpair_t * nvp)741 nvpair_type(const nvpair_t *nvp)
742 {
743 
744 	NVPAIR_ASSERT(nvp);
745 
746 	return (nvp->nvp_type);
747 }
748 
749 const char *
nvpair_name(const nvpair_t * nvp)750 nvpair_name(const nvpair_t *nvp)
751 {
752 
753 	NVPAIR_ASSERT(nvp);
754 
755 	return (nvp->nvp_name);
756 }
757 
758 static nvpair_t *
nvpair_allocv(int type,uint64_t data,size_t datasize,const char * namefmt,va_list nameap)759 nvpair_allocv(int type, uint64_t data, size_t datasize, const char *namefmt,
760     va_list nameap)
761 {
762 	nvpair_t *nvp;
763 	char *name;
764 	int namelen;
765 
766 	PJDLOG_ASSERT(type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST);
767 
768 	namelen = nv_vasprintf(&name, namefmt, nameap);
769 	if (namelen < 0)
770 		return (NULL);
771 
772 	PJDLOG_ASSERT(namelen > 0);
773 	if (namelen >= NV_NAME_MAX) {
774 		nv_free(name);
775 		RESTORE_ERRNO(ENAMETOOLONG);
776 		return (NULL);
777 	}
778 
779 	nvp = nv_calloc(1, sizeof(*nvp) + namelen + 1);
780 	if (nvp != NULL) {
781 		nvp->nvp_name = (char *)(nvp + 1);
782 		memcpy(nvp->nvp_name, name, namelen + 1);
783 		nvp->nvp_type = type;
784 		nvp->nvp_data = data;
785 		nvp->nvp_datasize = datasize;
786 		nvp->nvp_magic = NVPAIR_MAGIC;
787 	}
788 	nv_free(name);
789 
790 	return (nvp);
791 };
792 
793 nvpair_t *
nvpair_create_null(const char * name)794 nvpair_create_null(const char *name)
795 {
796 
797 	return (nvpair_createf_null("%s", name));
798 }
799 
800 nvpair_t *
nvpair_create_bool(const char * name,bool value)801 nvpair_create_bool(const char *name, bool value)
802 {
803 
804 	return (nvpair_createf_bool(value, "%s", name));
805 }
806 
807 nvpair_t *
nvpair_create_number_type(const char * name,uint64_t value,int type)808 nvpair_create_number_type(const char *name, uint64_t value, int type)
809 {
810 
811 	return (nvpair_createf_number_type(value, type, "%s", name));
812 }
813 
814 nvpair_t *
nvpair_create_string(const char * name,const char * value)815 nvpair_create_string(const char *name, const char *value)
816 {
817 
818 	return (nvpair_createf_string(value, "%s", name));
819 }
820 
821 nvpair_t *
nvpair_create_stringf(const char * name,const char * valuefmt,...)822 nvpair_create_stringf(const char *name, const char *valuefmt, ...)
823 {
824 	va_list valueap;
825 	nvpair_t *nvp;
826 
827 	va_start(valueap, valuefmt);
828 	nvp = nvpair_create_stringv(name, valuefmt, valueap);
829 	va_end(valueap);
830 
831 	return (nvp);
832 }
833 
834 nvpair_t *
nvpair_create_stringv(const char * name,const char * valuefmt,va_list valueap)835 nvpair_create_stringv(const char *name, const char *valuefmt, va_list valueap)
836 {
837 	nvpair_t *nvp;
838 	char *str;
839 	int len;
840 
841 	len = nv_vasprintf(&str, valuefmt, valueap);
842 	if (len < 0)
843 		return (NULL);
844 	nvp = nvpair_create_string(name, str);
845 	if (nvp == NULL)
846 		nv_free(str);
847 	return (nvp);
848 }
849 
850 nvpair_t *
nvpair_create_nvlist_type(const char * name,const nvlist_t * value,int type)851 nvpair_create_nvlist_type(const char *name, const nvlist_t *value, int type)
852 {
853 
854 	return (nvpair_createf_nvlist_type(value, type, "%s", name));
855 }
856 
857 #ifndef _KERNEL
858 nvpair_t *
nvpair_create_descriptor(const char * name,int value)859 nvpair_create_descriptor(const char *name, int value)
860 {
861 
862 	return (nvpair_createf_descriptor(value, "%s", name));
863 }
864 #endif
865 
866 nvpair_t *
nvpair_create_binary(const char * name,const void * value,size_t size)867 nvpair_create_binary(const char *name, const void *value, size_t size)
868 {
869 
870 	return (nvpair_createf_binary(value, size, "%s", name));
871 }
872 
873 nvpair_t *
nvpair_create_uuid(const char * name,const uuid_t * value)874 nvpair_create_uuid(const char *name, const uuid_t *value)
875 {
876 
877 	return (nvpair_createf_uuid(value, "%s", name));
878 }
879 
880 nvpair_t *
nvpair_createf_null(const char * namefmt,...)881 nvpair_createf_null(const char *namefmt, ...)
882 {
883 	va_list nameap;
884 	nvpair_t *nvp;
885 
886 	va_start(nameap, namefmt);
887 	nvp = nvpair_createv_null(namefmt, nameap);
888 	va_end(nameap);
889 
890 	return (nvp);
891 }
892 
893 nvpair_t *
nvpair_createf_bool(bool value,const char * namefmt,...)894 nvpair_createf_bool(bool value, const char *namefmt, ...)
895 {
896 	va_list nameap;
897 	nvpair_t *nvp;
898 
899 	va_start(nameap, namefmt);
900 	nvp = nvpair_createv_bool(value, namefmt, nameap);
901 	va_end(nameap);
902 
903 	return (nvp);
904 }
905 
906 nvpair_t *
nvpair_createf_number_type(uint64_t value,int type,const char * namefmt,...)907 nvpair_createf_number_type(uint64_t value, int type, const char *namefmt, ...)
908 {
909 	va_list nameap;
910 	nvpair_t *nvp;
911 
912 	va_start(nameap, namefmt);
913 	nvp = nvpair_createv_number_type(value, type, namefmt, nameap);
914 	va_end(nameap);
915 
916 	return (nvp);
917 }
918 
919 nvpair_t *
nvpair_createf_string(const char * value,const char * namefmt,...)920 nvpair_createf_string(const char *value, const char *namefmt, ...)
921 {
922 	va_list nameap;
923 	nvpair_t *nvp;
924 
925 	va_start(nameap, namefmt);
926 	nvp = nvpair_createv_string(value, namefmt, nameap);
927 	va_end(nameap);
928 
929 	return (nvp);
930 }
931 
932 nvpair_t *
nvpair_createf_nvlist_type(const nvlist_t * value,int type,const char * namefmt,...)933 nvpair_createf_nvlist_type(const nvlist_t *value, int type, const char *namefmt, ...)
934 {
935 	va_list nameap;
936 	nvpair_t *nvp;
937 
938 	va_start(nameap, namefmt);
939 	nvp = nvpair_createv_nvlist_type(value, type, namefmt, nameap);
940 	va_end(nameap);
941 
942 	return (nvp);
943 }
944 
945 #ifndef _KERNEL
946 nvpair_t *
nvpair_createf_descriptor(int value,const char * namefmt,...)947 nvpair_createf_descriptor(int value, const char *namefmt, ...)
948 {
949 	va_list nameap;
950 	nvpair_t *nvp;
951 
952 	va_start(nameap, namefmt);
953 	nvp = nvpair_createv_descriptor(value, namefmt, nameap);
954 	va_end(nameap);
955 
956 	return (nvp);
957 }
958 #endif
959 
960 nvpair_t *
nvpair_createf_binary(const void * value,size_t size,const char * namefmt,...)961 nvpair_createf_binary(const void *value, size_t size, const char *namefmt, ...)
962 {
963 	va_list nameap;
964 	nvpair_t *nvp;
965 
966 	va_start(nameap, namefmt);
967 	nvp = nvpair_createv_binary(value, size, namefmt, nameap);
968 	va_end(nameap);
969 
970 	return (nvp);
971 }
972 
973 nvpair_t *
nvpair_createf_uuid(const uuid_t * value,const char * namefmt,...)974 nvpair_createf_uuid(const uuid_t *value, const char *namefmt, ...)
975 {
976 	va_list nameap;
977 	nvpair_t *nvp;
978 
979 	va_start(nameap, namefmt);
980 	nvp = nvpair_createv_uuid(value, namefmt, nameap);
981 	va_end(nameap);
982 
983 	return (nvp);
984 }
985 
986 nvpair_t *
nvpair_createv_null(const char * namefmt,va_list nameap)987 nvpair_createv_null(const char *namefmt, va_list nameap)
988 {
989 
990 	return (nvpair_allocv(NV_TYPE_NULL, 0, 0, namefmt, nameap));
991 }
992 
993 nvpair_t *
nvpair_createv_bool(bool value,const char * namefmt,va_list nameap)994 nvpair_createv_bool(bool value, const char *namefmt, va_list nameap)
995 {
996 
997 	return (nvpair_allocv(NV_TYPE_BOOL, value ? 1 : 0, sizeof(uint8_t),
998 	    namefmt, nameap));
999 }
1000 
1001 nvpair_t *
nvpair_createv_number_type(uint64_t value,int type,const char * namefmt,va_list nameap)1002 nvpair_createv_number_type(uint64_t value, int type, const char *namefmt, va_list nameap)
1003 {
1004 	if (type > NV_TYPE_NUMBER_MAX || type < NV_TYPE_NUMBER_MIN)
1005 		return (NULL);
1006 
1007 	return (nvpair_allocv(type, value, sizeof(value), namefmt,
1008 	    nameap));
1009 }
1010 
1011 nvpair_t *
nvpair_createv_string(const char * value,const char * namefmt,va_list nameap)1012 nvpair_createv_string(const char *value, const char *namefmt, va_list nameap)
1013 {
1014 	nvpair_t *nvp;
1015 	size_t size;
1016 	char *data;
1017 
1018 	if (value == NULL) {
1019 		RESTORE_ERRNO(EINVAL);
1020 		return (NULL);
1021 	}
1022 
1023 	data = nv_strdup(value);
1024 	if (data == NULL)
1025 		return (NULL);
1026 	size = strlen(value) + 1;
1027 
1028 	nvp = nvpair_allocv(NV_TYPE_STRING, (uint64_t)(uintptr_t)data, size,
1029 	    namefmt, nameap);
1030 	if (nvp == NULL)
1031 		nv_free(data);
1032 
1033 	return (nvp);
1034 }
1035 
1036 nvpair_t *
nvpair_createv_nvlist_type(const nvlist_t * value,int type,const char * namefmt,va_list nameap)1037 nvpair_createv_nvlist_type(const nvlist_t *value, int type, const char *namefmt,
1038     va_list nameap)
1039 {
1040 	nvlist_t *nvl;
1041 	nvpair_t *nvp;
1042 
1043 	if (value == NULL) {
1044 		RESTORE_ERRNO(EINVAL);
1045 		return (NULL);
1046 	}
1047 
1048 	nvl = nvlist_clone(value);
1049 	if (nvl == NULL)
1050 		return (NULL);
1051 
1052 	nvp = nvpair_allocv(type, (uint64_t)(uintptr_t)nvl, 0,
1053 	    namefmt, nameap);
1054 	if (nvp == NULL)
1055 		nvlist_destroy(nvl);
1056 	else
1057 		nvlist_set_parent(nvl, nvp);
1058 
1059 	return (nvp);
1060 }
1061 
1062 #ifndef _KERNEL
1063 nvpair_t *
nvpair_createv_descriptor(int value,const char * namefmt,va_list nameap)1064 nvpair_createv_descriptor(int value, const char *namefmt, va_list nameap)
1065 {
1066 	nvpair_t *nvp;
1067 
1068 	if (value < 0 || !fd_is_valid(value)) {
1069 		errno = EBADF;
1070 		return (NULL);
1071 	}
1072 
1073 	value = fcntl(value, F_DUPFD_CLOEXEC, 0);
1074 	if (value < 0)
1075 		return (NULL);
1076 
1077 	nvp = nvpair_allocv(NV_TYPE_DESCRIPTOR, (uint64_t)value,
1078 	    sizeof(int64_t), namefmt, nameap);
1079 	if (nvp == NULL)
1080 		close(value);
1081 
1082 	return (nvp);
1083 }
1084 #endif
1085 
1086 nvpair_t *
nvpair_createv_binary(const void * value,size_t size,const char * namefmt,va_list nameap)1087 nvpair_createv_binary(const void *value, size_t size, const char *namefmt,
1088     va_list nameap)
1089 {
1090 	nvpair_t *nvp;
1091 	void *data;
1092 
1093 	if (value == NULL || size == 0) {
1094 		RESTORE_ERRNO(EINVAL);
1095 		return (NULL);
1096 	}
1097 
1098 	data = nv_malloc(size);
1099 	if (data == NULL)
1100 		return (NULL);
1101 	memcpy(data, value, size);
1102 
1103 	nvp = nvpair_allocv(NV_TYPE_BINARY, (uint64_t)(uintptr_t)data, size,
1104 	    namefmt, nameap);
1105 	if (nvp == NULL)
1106 		nv_free(data);
1107 
1108 	return (nvp);
1109 }
1110 
1111 nvpair_t *
nvpair_createv_uuid(const uuid_t * value,const char * namefmt,va_list nameap)1112 nvpair_createv_uuid(const uuid_t *value,  const char *namefmt,
1113     va_list nameap)
1114 {
1115 	nvpair_t *nvp;
1116 	void *data;
1117 	size_t size;
1118 
1119 	size = sizeof(uuid_t);
1120 
1121 	if (value == NULL) {
1122 		RESTORE_ERRNO(EINVAL);
1123 		return (NULL);
1124 	}
1125 
1126 	data = nv_malloc(size);
1127 	if (data == NULL)
1128 		return (NULL);
1129 	memcpy(data, value, size);
1130 
1131 	nvp = nvpair_allocv(NV_TYPE_UUID, (uint64_t)(uintptr_t)data, size,
1132 	    namefmt, nameap);
1133 	if (nvp == NULL)
1134 		nv_free(data);
1135 
1136 	return (nvp);
1137 }
1138 
1139 nvpair_t *
nvpair_move_string(const char * name,char * value)1140 nvpair_move_string(const char *name, char *value)
1141 {
1142 
1143 	return (nvpair_movef_string(value, "%s", name));
1144 }
1145 
1146 nvpair_t *
nvpair_move_nvlist(const char * name,nvlist_t * value)1147 nvpair_move_nvlist(const char *name, nvlist_t *value)
1148 {
1149 
1150 	return (nvpair_movef_nvlist_type(value, NV_TYPE_NVLIST, "%s", name));
1151 }
1152 
1153 nvpair_t *
nvpair_move_nvlist_type(const char * name,nvlist_t * value,int type)1154 nvpair_move_nvlist_type(const char *name, nvlist_t *value, int type)
1155 {
1156 
1157 	return (nvpair_movef_nvlist_type(value, type, "%s", name));
1158 }
1159 
1160 #ifndef _KERNEL
1161 nvpair_t *
nvpair_move_descriptor(const char * name,int value)1162 nvpair_move_descriptor(const char *name, int value)
1163 {
1164 
1165 	return (nvpair_movef_descriptor(value, "%s", name));
1166 }
1167 #endif
1168 
1169 nvpair_t *
nvpair_move_binary(const char * name,void * value,size_t size)1170 nvpair_move_binary(const char *name, void *value, size_t size)
1171 {
1172 
1173 	return (nvpair_movef_binary(value, size, "%s", name));
1174 }
1175 
1176 nvpair_t *
nvpair_movef_string(char * value,const char * namefmt,...)1177 nvpair_movef_string(char *value, const char *namefmt, ...)
1178 {
1179 	va_list nameap;
1180 	nvpair_t *nvp;
1181 
1182 	va_start(nameap, namefmt);
1183 	nvp = nvpair_movev_string(value, namefmt, nameap);
1184 	va_end(nameap);
1185 
1186 	return (nvp);
1187 }
1188 
1189 nvpair_t *
nvpair_movef_nvlist_type(nvlist_t * value,int type,const char * namefmt,...)1190 nvpair_movef_nvlist_type(nvlist_t *value, int type, const char *namefmt, ...)
1191 {
1192 	va_list nameap;
1193 	nvpair_t *nvp;
1194 
1195 	va_start(nameap, namefmt);
1196 	nvp = nvpair_movev_nvlist_type(value, type, namefmt, nameap);
1197 	va_end(nameap);
1198 
1199 	return (nvp);
1200 }
1201 
1202 #ifndef _KERNEL
1203 nvpair_t *
nvpair_movef_descriptor(int value,const char * namefmt,...)1204 nvpair_movef_descriptor(int value, const char *namefmt, ...)
1205 {
1206 	va_list nameap;
1207 	nvpair_t *nvp;
1208 
1209 	va_start(nameap, namefmt);
1210 	nvp = nvpair_movev_descriptor(value, namefmt, nameap);
1211 	va_end(nameap);
1212 
1213 	return (nvp);
1214 }
1215 #endif
1216 
1217 nvpair_t *
nvpair_movef_binary(void * value,size_t size,const char * namefmt,...)1218 nvpair_movef_binary(void *value, size_t size, const char *namefmt, ...)
1219 {
1220 	va_list nameap;
1221 	nvpair_t *nvp;
1222 
1223 	va_start(nameap, namefmt);
1224 	nvp = nvpair_movev_binary(value, size, namefmt, nameap);
1225 	va_end(nameap);
1226 
1227 	return (nvp);
1228 }
1229 
1230 nvpair_t *
nvpair_movef_uuid(uuid_t * value,const char * namefmt,...)1231 nvpair_movef_uuid(uuid_t *value, const char *namefmt, ...)
1232 {
1233 	va_list nameap;
1234 	nvpair_t *nvp;
1235 
1236 	va_start(nameap, namefmt);
1237 	nvp = nvpair_movev_uuid(value, namefmt, nameap);
1238 	va_end(nameap);
1239 
1240 	return (nvp);
1241 }
1242 
1243 nvpair_t *
nvpair_movev_string(char * value,const char * namefmt,va_list nameap)1244 nvpair_movev_string(char *value, const char *namefmt, va_list nameap)
1245 {
1246 	nvpair_t *nvp;
1247 	int serrno;
1248 
1249 	if (value == NULL) {
1250 		RESTORE_ERRNO(EINVAL);
1251 		return (NULL);
1252 	}
1253 
1254 	nvp = nvpair_allocv(NV_TYPE_STRING, (uint64_t)(uintptr_t)value,
1255 	    strlen(value) + 1, namefmt, nameap);
1256 	if (nvp == NULL) {
1257 		SAVE_ERRNO(serrno);
1258 		nv_free(value);
1259 		RESTORE_ERRNO(serrno);
1260 	}
1261 
1262 	return (nvp);
1263 }
1264 
1265 nvpair_t *
nvpair_movev_nvlist_type(nvlist_t * value,int type,const char * namefmt,va_list nameap)1266 nvpair_movev_nvlist_type(nvlist_t *value, int type, const char *namefmt, va_list nameap)
1267 {
1268 	nvpair_t *nvp;
1269 
1270 	if (value == NULL || nvlist_get_nvpair_parent(value) != NULL) {
1271 		RESTORE_ERRNO(EINVAL);
1272 		return (NULL);
1273 	}
1274 
1275 	if (nvlist_error(value) != 0) {
1276 		RESTORE_ERRNO(nvlist_error(value));
1277 		nvlist_destroy(value);
1278 		return (NULL);
1279 	}
1280 
1281 	nvp = nvpair_allocv(type, (uint64_t)(uintptr_t)value, 0,
1282 	    namefmt, nameap);
1283 	if (nvp == NULL)
1284 		nvlist_destroy(value);
1285 	else
1286 		nvlist_set_parent(value, nvp);
1287 
1288 	return (nvp);
1289 }
1290 
1291 #ifndef _KERNEL
1292 nvpair_t *
nvpair_movev_descriptor(int value,const char * namefmt,va_list nameap)1293 nvpair_movev_descriptor(int value, const char *namefmt, va_list nameap)
1294 {
1295 	nvpair_t *nvp;
1296 	int serrno;
1297 
1298 	if (value < 0 || !fd_is_valid(value)) {
1299 		errno = EBADF;
1300 		return (NULL);
1301 	}
1302 
1303 	nvp = nvpair_allocv(NV_TYPE_DESCRIPTOR, (uint64_t)value,
1304 	    sizeof(int64_t), namefmt, nameap);
1305 	if (nvp == NULL) {
1306 		serrno = errno;
1307 		close(value);
1308 		errno = serrno;
1309 	}
1310 
1311 	return (nvp);
1312 }
1313 #endif
1314 
1315 nvpair_t *
nvpair_movev_binary(void * value,size_t size,const char * namefmt,va_list nameap)1316 nvpair_movev_binary(void *value, size_t size, const char *namefmt,
1317     va_list nameap)
1318 {
1319 	nvpair_t *nvp;
1320 	int serrno;
1321 
1322 	if (value == NULL || size == 0) {
1323 		RESTORE_ERRNO(EINVAL);
1324 		return (NULL);
1325 	}
1326 
1327 	nvp = nvpair_allocv(NV_TYPE_BINARY, (uint64_t)(uintptr_t)value, size,
1328 	    namefmt, nameap);
1329 	if (nvp == NULL) {
1330 		SAVE_ERRNO(serrno);
1331 		nv_free(value);
1332 		RESTORE_ERRNO(serrno);
1333 	}
1334 
1335 	return (nvp);
1336 }
1337 
1338 nvpair_t *
nvpair_movev_uuid(uuid_t * value,const char * namefmt,va_list nameap)1339 nvpair_movev_uuid(uuid_t *value, const char *namefmt,
1340     va_list nameap)
1341 {
1342 
1343 	if (value == NULL) {
1344 		RESTORE_ERRNO(EINVAL);
1345 		return (NULL);
1346 	}
1347 
1348 	return (nvpair_allocv(NV_TYPE_UUID, (uint64_t)(uintptr_t)value,
1349 	    sizeof(uuid_t), namefmt, nameap));
1350 }
1351 
1352 bool
nvpair_get_bool(const nvpair_t * nvp)1353 nvpair_get_bool(const nvpair_t *nvp)
1354 {
1355 
1356 	NVPAIR_ASSERT(nvp);
1357 
1358 	return (nvp->nvp_data == 1);
1359 }
1360 
1361 uint64_t
nvpair_get_number(const nvpair_t * nvp)1362 nvpair_get_number(const nvpair_t *nvp)
1363 {
1364 
1365 	NVPAIR_ASSERT(nvp);
1366 
1367 	return (nvp->nvp_data);
1368 }
1369 
1370 const char *
nvpair_get_string(const nvpair_t * nvp)1371 nvpair_get_string(const nvpair_t *nvp)
1372 {
1373 
1374 	NVPAIR_ASSERT(nvp);
1375 	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING);
1376 
1377 	return ((const char *)(intptr_t)nvp->nvp_data);
1378 }
1379 
1380 const nvlist_t *
nvpair_get_nvlist(const nvpair_t * nvp)1381 nvpair_get_nvlist(const nvpair_t *nvp)
1382 {
1383 
1384 	NVPAIR_ASSERT(nvp);
1385 	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST_ARRAY ||
1386 	    nvp->nvp_type == NV_TYPE_NVLIST_DICTIONARY ||
1387 	    nvp->nvp_type == NV_TYPE_NVLIST);
1388 
1389 	return ((const nvlist_t *)(intptr_t)nvp->nvp_data);
1390 }
1391 
1392 #ifndef _KERNEL
1393 int
nvpair_get_descriptor(const nvpair_t * nvp)1394 nvpair_get_descriptor(const nvpair_t *nvp)
1395 {
1396 
1397 	NVPAIR_ASSERT(nvp);
1398 	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR);
1399 
1400 	return ((int)nvp->nvp_data);
1401 }
1402 #endif
1403 
1404 const void *
nvpair_get_binary(const nvpair_t * nvp,size_t * sizep)1405 nvpair_get_binary(const nvpair_t *nvp, size_t *sizep)
1406 {
1407 
1408 	NVPAIR_ASSERT(nvp);
1409 	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BINARY);
1410 
1411 	if (sizep != NULL)
1412 		*sizep = nvp->nvp_datasize;
1413 	return ((const void *)(intptr_t)nvp->nvp_data);
1414 }
1415 
1416 const uuid_t *
nvpair_get_uuid(const nvpair_t * nvp)1417 nvpair_get_uuid(const nvpair_t *nvp)
1418 {
1419 
1420 	NVPAIR_ASSERT(nvp);
1421 	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_UUID);
1422 
1423 	return ((const uuid_t *)(intptr_t)nvp->nvp_data);
1424 }
1425 
1426 void
nvpair_free(nvpair_t * nvp)1427 nvpair_free(nvpair_t *nvp)
1428 {
1429 
1430 	NVPAIR_ASSERT(nvp);
1431 	PJDLOG_ASSERT(nvp->nvp_list == NULL);
1432 
1433 	nvp->nvp_magic = 0;
1434 	switch (nvp->nvp_type) {
1435 #ifndef _KERNEL
1436 	case NV_TYPE_DESCRIPTOR:
1437 		close((int)nvp->nvp_data);
1438 		break;
1439 #endif
1440 	case NV_TYPE_NVLIST:
1441 	case NV_TYPE_NVLIST_ARRAY:
1442 	case NV_TYPE_NVLIST_DICTIONARY:
1443 		nvlist_destroy((nvlist_t *)(intptr_t)nvp->nvp_data);
1444 		break;
1445 	case NV_TYPE_STRING:
1446 		nv_free((char *)(intptr_t)nvp->nvp_data);
1447 		break;
1448 	case NV_TYPE_BINARY:
1449 		nv_free((void *)(intptr_t)nvp->nvp_data);
1450 		break;
1451 	case NV_TYPE_UUID:
1452 		nv_free((void *)(intptr_t)nvp->nvp_data);
1453 		break;
1454 	}
1455 	nv_free(nvp);
1456 }
1457 
1458 void
nvpair_free_structure(nvpair_t * nvp)1459 nvpair_free_structure(nvpair_t *nvp)
1460 {
1461 
1462 	NVPAIR_ASSERT(nvp);
1463 	PJDLOG_ASSERT(nvp->nvp_list == NULL);
1464 
1465 	nvp->nvp_magic = 0;
1466 	nv_free(nvp);
1467 }
1468 
1469 const char *
nvpair_type_string(int type)1470 nvpair_type_string(int type)
1471 {
1472 
1473 	switch (type) {
1474 	case NV_TYPE_NULL:
1475 		return ("NULL");
1476 	case NV_TYPE_BOOL:
1477 		return ("BOOL");
1478 	case NV_TYPE_NUMBER:
1479 		return ("NUMBER");
1480 	case NV_TYPE_STRING:
1481 		return ("STRING");
1482 	case NV_TYPE_NVLIST:
1483 		return ("NVLIST");
1484 	case NV_TYPE_NVLIST_ARRAY:
1485 		return ("NVLIST_ARRAY");
1486 	case NV_TYPE_NVLIST_DICTIONARY:
1487 		return ("NVLIST_DICTIONARY");
1488 	case NV_TYPE_DESCRIPTOR:
1489 		return ("DESCRIPTOR");
1490 	case NV_TYPE_BINARY:
1491 		return ("BINARY");
1492 	case NV_TYPE_PTR:
1493 		return ("PTR");
1494 	case NV_TYPE_UINT64:
1495 		return ("UINT64");
1496 	case NV_TYPE_INT64:
1497 		return ("INT64");
1498 	case NV_TYPE_ENDPOINT:
1499 		return ("ENDPOINT");
1500 	case NV_TYPE_UUID:
1501 		return ("UUID");
1502 	default:
1503 		return ("<UNKNOWN>");
1504 	}
1505 }
1506