]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/kern/subr_nvlist.c
Fix memory leak.
[FreeBSD/FreeBSD.git] / sys / kern / subr_nvlist.c
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/kernel.h>
41 #include <sys/lock.h>
42 #include <sys/malloc.h>
43 #include <sys/systm.h>
44
45 #include <machine/stdarg.h>
46
47 #else
48 #include <sys/socket.h>
49
50 #include <errno.h>
51 #include <stdarg.h>
52 #include <stdbool.h>
53 #include <stdint.h>
54 #define _WITH_DPRINTF
55 #include <stdio.h>
56 #include <stdlib.h>
57 #include <string.h>
58 #include <unistd.h>
59
60 #include "msgio.h"
61 #endif
62
63 #ifdef HAVE_PJDLOG
64 #include <pjdlog.h>
65 #endif
66
67 #include <sys/nv.h>
68 #include <sys/nv_impl.h>
69 #include <sys/nvlist_impl.h>
70 #include <sys/nvpair_impl.h>
71
72 #ifndef HAVE_PJDLOG
73 #ifdef _KERNEL
74 #define PJDLOG_ASSERT(...)              MPASS(__VA_ARGS__)
75 #define PJDLOG_RASSERT(expr, ...)       KASSERT(expr, (__VA_ARGS__))
76 #define PJDLOG_ABORT(...)               panic(__VA_ARGS__)
77 #else
78 #include <assert.h>
79 #define PJDLOG_ASSERT(...)              assert(__VA_ARGS__)
80 #define PJDLOG_RASSERT(expr, ...)       assert(expr)
81 #define PJDLOG_ABORT(...)               do {                            \
82         fprintf(stderr, "%s:%u: ", __FILE__, __LINE__);                 \
83         fprintf(stderr, __VA_ARGS__);                                   \
84         fprintf(stderr, "\n");                                          \
85         abort();                                                        \
86 } while (0)
87 #endif
88 #endif
89
90 #define NV_FLAG_PRIVATE_MASK    (NV_FLAG_BIG_ENDIAN)
91 #define NV_FLAG_PUBLIC_MASK     (NV_FLAG_IGNORE_CASE | NV_FLAG_NO_UNIQUE)
92 #define NV_FLAG_ALL_MASK        (NV_FLAG_PRIVATE_MASK | NV_FLAG_PUBLIC_MASK)
93
94 #define NVLIST_MAGIC    0x6e766c        /* "nvl" */
95 struct nvlist {
96         int              nvl_magic;
97         int              nvl_error;
98         int              nvl_flags;
99         nvpair_t        *nvl_parent;
100         struct nvl_head  nvl_head;
101 };
102
103 #define NVLIST_ASSERT(nvl)      do {                                    \
104         PJDLOG_ASSERT((nvl) != NULL);                                   \
105         PJDLOG_ASSERT((nvl)->nvl_magic == NVLIST_MAGIC);                \
106 } while (0)
107
108 #ifdef _KERNEL
109 MALLOC_DEFINE(M_NVLIST, "nvlist", "kernel nvlist");
110 #endif
111
112 #define NVPAIR_ASSERT(nvp)      nvpair_assert(nvp)
113
114 #define NVLIST_HEADER_MAGIC     0x6c
115 #define NVLIST_HEADER_VERSION   0x00
116 struct nvlist_header {
117         uint8_t         nvlh_magic;
118         uint8_t         nvlh_version;
119         uint8_t         nvlh_flags;
120         uint64_t        nvlh_descriptors;
121         uint64_t        nvlh_size;
122 } __packed;
123
124 nvlist_t *
125 nvlist_create(int flags)
126 {
127         nvlist_t *nvl;
128
129         PJDLOG_ASSERT((flags & ~(NV_FLAG_PUBLIC_MASK)) == 0);
130
131         nvl = nv_malloc(sizeof(*nvl));
132         if (nvl == NULL)
133                 return (NULL);
134         nvl->nvl_error = 0;
135         nvl->nvl_flags = flags;
136         nvl->nvl_parent = NULL;
137         TAILQ_INIT(&nvl->nvl_head);
138         nvl->nvl_magic = NVLIST_MAGIC;
139
140         return (nvl);
141 }
142
143 void
144 nvlist_destroy(nvlist_t *nvl)
145 {
146         nvpair_t *nvp;
147
148         if (nvl == NULL)
149                 return;
150
151         ERRNO_SAVE();
152
153         NVLIST_ASSERT(nvl);
154
155         while ((nvp = nvlist_first_nvpair(nvl)) != NULL) {
156                 nvlist_remove_nvpair(nvl, nvp);
157                 nvpair_free(nvp);
158         }
159         nvl->nvl_magic = 0;
160         nv_free(nvl);
161
162         ERRNO_RESTORE();
163 }
164
165 void
166 nvlist_set_error(nvlist_t *nvl, int error)
167 {
168
169         PJDLOG_ASSERT(error != 0);
170
171         /*
172          * Check for error != 0 so that we don't do the wrong thing if somebody
173          * tries to abuse this API when asserts are disabled.
174          */
175         if (nvl != NULL && error != 0 && nvl->nvl_error == 0)
176                 nvl->nvl_error = error;
177 }
178
179 int
180 nvlist_error(const nvlist_t *nvl)
181 {
182
183         if (nvl == NULL)
184                 return (ENOMEM);
185
186         NVLIST_ASSERT(nvl);
187
188         return (nvl->nvl_error);
189 }
190
191 nvpair_t *
192 nvlist_get_nvpair_parent(const nvlist_t *nvl)
193 {
194
195         NVLIST_ASSERT(nvl);
196
197         return (nvl->nvl_parent);
198 }
199
200 const nvlist_t *
201 nvlist_get_parent(const nvlist_t *nvl, void **cookiep)
202 {
203         nvpair_t *nvp;
204
205         NVLIST_ASSERT(nvl);
206
207         nvp = nvl->nvl_parent;
208         if (cookiep != NULL)
209                 *cookiep = nvp;
210         if (nvp == NULL)
211                 return (NULL);
212
213         return (nvpair_nvlist(nvp));
214 }
215
216 void
217 nvlist_set_parent(nvlist_t *nvl, nvpair_t *parent)
218 {
219
220         NVLIST_ASSERT(nvl);
221
222         nvl->nvl_parent = parent;
223 }
224
225 bool
226 nvlist_empty(const nvlist_t *nvl)
227 {
228
229         NVLIST_ASSERT(nvl);
230         PJDLOG_ASSERT(nvl->nvl_error == 0);
231
232         return (nvlist_first_nvpair(nvl) == NULL);
233 }
234
235 int
236 nvlist_flags(const nvlist_t *nvl)
237 {
238
239         NVLIST_ASSERT(nvl);
240         PJDLOG_ASSERT(nvl->nvl_error == 0);
241         PJDLOG_ASSERT((nvl->nvl_flags & ~(NV_FLAG_PUBLIC_MASK)) == 0);
242
243         return (nvl->nvl_flags);
244 }
245
246 static void
247 nvlist_report_missing(int type, const char *name)
248 {
249
250         PJDLOG_ABORT("Element '%s' of type %s doesn't exist.",
251             name, nvpair_type_string(type));
252 }
253
254 static nvpair_t *
255 nvlist_find(const nvlist_t *nvl, int type, const char *name)
256 {
257         nvpair_t *nvp;
258
259         NVLIST_ASSERT(nvl);
260         PJDLOG_ASSERT(nvl->nvl_error == 0);
261         PJDLOG_ASSERT(type == NV_TYPE_NONE ||
262             (type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST));
263
264         for (nvp = nvlist_first_nvpair(nvl); nvp != NULL;
265             nvp = nvlist_next_nvpair(nvl, nvp)) {
266                 if (type != NV_TYPE_NONE && nvpair_type(nvp) != type)
267                         continue;
268                 if ((nvl->nvl_flags & NV_FLAG_IGNORE_CASE) != 0) {
269                         if (strcasecmp(nvpair_name(nvp), name) != 0)
270                                 continue;
271                 } else {
272                         if (strcmp(nvpair_name(nvp), name) != 0)
273                                 continue;
274                 }
275                 break;
276         }
277
278         if (nvp == NULL)
279                 ERRNO_SET(ENOENT);
280
281         return (nvp);
282 }
283
284 bool
285 nvlist_exists_type(const nvlist_t *nvl, const char *name, int type)
286 {
287
288         NVLIST_ASSERT(nvl);
289         PJDLOG_ASSERT(nvl->nvl_error == 0);
290         PJDLOG_ASSERT(type == NV_TYPE_NONE ||
291             (type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST));
292
293         return (nvlist_find(nvl, type, name) != NULL);
294 }
295
296 void
297 nvlist_free_type(nvlist_t *nvl, const char *name, int type)
298 {
299         nvpair_t *nvp;
300
301         NVLIST_ASSERT(nvl);
302         PJDLOG_ASSERT(nvl->nvl_error == 0);
303         PJDLOG_ASSERT(type == NV_TYPE_NONE ||
304             (type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST));
305
306         nvp = nvlist_find(nvl, type, name);
307         if (nvp != NULL)
308                 nvlist_free_nvpair(nvl, nvp);
309         else
310                 nvlist_report_missing(type, name);
311 }
312
313 nvlist_t *
314 nvlist_clone(const nvlist_t *nvl)
315 {
316         nvlist_t *newnvl;
317         nvpair_t *nvp, *newnvp;
318
319         NVLIST_ASSERT(nvl);
320
321         if (nvl->nvl_error != 0) {
322                 ERRNO_SET(nvl->nvl_error);
323                 return (NULL);
324         }
325
326         newnvl = nvlist_create(nvl->nvl_flags & NV_FLAG_PUBLIC_MASK);
327         for (nvp = nvlist_first_nvpair(nvl); nvp != NULL;
328             nvp = nvlist_next_nvpair(nvl, nvp)) {
329                 newnvp = nvpair_clone(nvp);
330                 if (newnvp == NULL)
331                         break;
332                 nvlist_move_nvpair(newnvl, newnvp);
333         }
334         if (nvp != NULL) {
335                 nvlist_destroy(newnvl);
336                 return (NULL);
337         }
338         return (newnvl);
339 }
340
341 #ifndef _KERNEL
342 static bool
343 nvlist_dump_error_check(const nvlist_t *nvl, int fd, int level)
344 {
345
346         if (nvlist_error(nvl) != 0) {
347                 dprintf(fd, "%*serror: %d\n", level * 4, "",
348                     nvlist_error(nvl));
349                 return (true);
350         }
351
352         return (false);
353 }
354
355 /*
356  * Dump content of nvlist.
357  */
358 void
359 nvlist_dump(const nvlist_t *nvl, int fd)
360 {
361         const nvlist_t *tmpnvl;
362         nvpair_t *nvp, *tmpnvp;
363         void *cookie;
364         int level;
365
366         level = 0;
367         if (nvlist_dump_error_check(nvl, fd, level))
368                 return;
369
370         nvp = nvlist_first_nvpair(nvl);
371         while (nvp != NULL) {
372                 dprintf(fd, "%*s%s (%s):", level * 4, "", nvpair_name(nvp),
373                     nvpair_type_string(nvpair_type(nvp)));
374                 switch (nvpair_type(nvp)) {
375                 case NV_TYPE_NULL:
376                         dprintf(fd, " null\n");
377                         break;
378                 case NV_TYPE_BOOL:
379                         dprintf(fd, " %s\n", nvpair_get_bool(nvp) ?
380                             "TRUE" : "FALSE");
381                         break;
382                 case NV_TYPE_NUMBER:
383                         dprintf(fd, " %ju (%jd) (0x%jx)\n",
384                             (uintmax_t)nvpair_get_number(nvp),
385                             (intmax_t)nvpair_get_number(nvp),
386                             (uintmax_t)nvpair_get_number(nvp));
387                         break;
388                 case NV_TYPE_STRING:
389                         dprintf(fd, " [%s]\n", nvpair_get_string(nvp));
390                         break;
391                 case NV_TYPE_NVLIST:
392                         dprintf(fd, "\n");
393                         tmpnvl = nvpair_get_nvlist(nvp);
394                         if (nvlist_dump_error_check(tmpnvl, fd, level + 1))
395                                 break;
396                         tmpnvp = nvlist_first_nvpair(tmpnvl);
397                         if (tmpnvp != NULL) {
398                                 nvl = tmpnvl;
399                                 nvp = tmpnvp;
400                                 level++;
401                                 continue;
402                         }
403                         break;
404                 case NV_TYPE_DESCRIPTOR:
405                         dprintf(fd, " %d\n", nvpair_get_descriptor(nvp));
406                         break;
407                 case NV_TYPE_BINARY:
408                     {
409                         const unsigned char *binary;
410                         unsigned int ii;
411                         size_t size;
412
413                         binary = nvpair_get_binary(nvp, &size);
414                         dprintf(fd, " %zu ", size);
415                         for (ii = 0; ii < size; ii++)
416                                 dprintf(fd, "%02hhx", binary[ii]);
417                         dprintf(fd, "\n");
418                         break;
419                     }
420                 default:
421                         PJDLOG_ABORT("Unknown type: %d.", nvpair_type(nvp));
422                 }
423
424                 while ((nvp = nvlist_next_nvpair(nvl, nvp)) == NULL) {
425                         cookie = NULL;
426                         nvl = nvlist_get_parent(nvl, &cookie);
427                         if (nvl == NULL)
428                                 return;
429                         nvp = cookie;
430                         level--;
431                 }
432         }
433 }
434
435 void
436 nvlist_fdump(const nvlist_t *nvl, FILE *fp)
437 {
438
439         fflush(fp);
440         nvlist_dump(nvl, fileno(fp));
441 }
442 #endif
443
444 /*
445  * The function obtains size of the nvlist after nvlist_pack().
446  */
447 size_t
448 nvlist_size(const nvlist_t *nvl)
449 {
450         const nvlist_t *tmpnvl;
451         const nvpair_t *nvp, *tmpnvp;
452         void *cookie;
453         size_t size;
454
455         NVLIST_ASSERT(nvl);
456         PJDLOG_ASSERT(nvl->nvl_error == 0);
457
458         size = sizeof(struct nvlist_header);
459         nvp = nvlist_first_nvpair(nvl);
460         while (nvp != NULL) {
461                 size += nvpair_header_size();
462                 size += strlen(nvpair_name(nvp)) + 1;
463                 if (nvpair_type(nvp) == NV_TYPE_NVLIST) {
464                         size += sizeof(struct nvlist_header);
465                         size += nvpair_header_size() + 1;
466                         tmpnvl = nvpair_get_nvlist(nvp);
467                         PJDLOG_ASSERT(tmpnvl->nvl_error == 0);
468                         tmpnvp = nvlist_first_nvpair(tmpnvl);
469                         if (tmpnvp != NULL) {
470                                 nvl = tmpnvl;
471                                 nvp = tmpnvp;
472                                 continue;
473                         }
474                 } else {
475                         size += nvpair_size(nvp);
476                 }
477
478                 while ((nvp = nvlist_next_nvpair(nvl, nvp)) == NULL) {
479                         cookie = NULL;
480                         nvl = nvlist_get_parent(nvl, &cookie);
481                         if (nvl == NULL)
482                                 goto out;
483                         nvp = cookie;
484                 }
485         }
486
487 out:
488         return (size);
489 }
490
491 #ifndef _KERNEL
492 static int *
493 nvlist_xdescriptors(const nvlist_t *nvl, int *descs)
494 {
495         nvpair_t *nvp;
496         const char *name;
497         int type;
498
499         NVLIST_ASSERT(nvl);
500         PJDLOG_ASSERT(nvl->nvl_error == 0);
501
502         nvp = NULL;
503         do {
504                 while ((name = nvlist_next(nvl, &type, (void**)&nvp)) != NULL) {
505                         switch (type) {
506                         case NV_TYPE_DESCRIPTOR:
507                                 *descs = nvpair_get_descriptor(nvp);
508                                 descs++;
509                                 break;
510                         case NV_TYPE_NVLIST:
511                                 nvl = nvpair_get_nvlist(nvp);
512                                 nvp = NULL;
513                                 break;
514                         }
515                 }
516         } while ((nvl = nvlist_get_parent(nvl, (void**)&nvp)) != NULL);
517
518         return (descs);
519 }
520 #endif
521
522 #ifndef _KERNEL
523 int *
524 nvlist_descriptors(const nvlist_t *nvl, size_t *nitemsp)
525 {
526         size_t nitems;
527         int *fds;
528
529         nitems = nvlist_ndescriptors(nvl);
530         fds = nv_malloc(sizeof(fds[0]) * (nitems + 1));
531         if (fds == NULL)
532                 return (NULL);
533         if (nitems > 0)
534                 nvlist_xdescriptors(nvl, fds);
535         fds[nitems] = -1;
536         if (nitemsp != NULL)
537                 *nitemsp = nitems;
538         return (fds);
539 }
540 #endif
541
542 size_t
543 nvlist_ndescriptors(const nvlist_t *nvl)
544 {
545 #ifndef _KERNEL
546         nvpair_t *nvp;
547         const char *name;
548         size_t ndescs;
549         int type;
550
551         NVLIST_ASSERT(nvl);
552         PJDLOG_ASSERT(nvl->nvl_error == 0);
553
554         ndescs = 0;
555         nvp = NULL;
556         do {
557                 while ((name = nvlist_next(nvl, &type, (void**)&nvp)) != NULL) {
558                         switch (type) {
559                         case NV_TYPE_DESCRIPTOR:
560                                 ndescs++;
561                                 break;
562                         case NV_TYPE_NVLIST:
563                                 nvl = nvpair_get_nvlist(nvp);
564                                 nvp = NULL;
565                                 break;
566                         }
567                 }
568         } while ((nvl = nvlist_get_parent(nvl, (void**)&nvp)) != NULL);
569
570         return (ndescs);
571 #else
572         return (0);
573 #endif
574 }
575
576 static unsigned char *
577 nvlist_pack_header(const nvlist_t *nvl, unsigned char *ptr, size_t *leftp)
578 {
579         struct nvlist_header nvlhdr;
580
581         NVLIST_ASSERT(nvl);
582
583         nvlhdr.nvlh_magic = NVLIST_HEADER_MAGIC;
584         nvlhdr.nvlh_version = NVLIST_HEADER_VERSION;
585         nvlhdr.nvlh_flags = nvl->nvl_flags;
586 #if BYTE_ORDER == BIG_ENDIAN
587         nvlhdr.nvlh_flags |= NV_FLAG_BIG_ENDIAN;
588 #endif
589         nvlhdr.nvlh_descriptors = nvlist_ndescriptors(nvl);
590         nvlhdr.nvlh_size = *leftp - sizeof(nvlhdr);
591         PJDLOG_ASSERT(*leftp >= sizeof(nvlhdr));
592         memcpy(ptr, &nvlhdr, sizeof(nvlhdr));
593         ptr += sizeof(nvlhdr);
594         *leftp -= sizeof(nvlhdr);
595
596         return (ptr);
597 }
598
599 static void *
600 nvlist_xpack(const nvlist_t *nvl, int64_t *fdidxp, size_t *sizep)
601 {
602         unsigned char *buf, *ptr;
603         size_t left, size;
604         const nvlist_t *tmpnvl;
605         nvpair_t *nvp, *tmpnvp;
606         void *cookie;
607
608         NVLIST_ASSERT(nvl);
609
610         if (nvl->nvl_error != 0) {
611                 ERRNO_SET(nvl->nvl_error);
612                 return (NULL);
613         }
614
615         size = nvlist_size(nvl);
616         buf = nv_malloc(size);
617         if (buf == NULL)
618                 return (NULL);
619
620         ptr = buf;
621         left = size;
622
623         ptr = nvlist_pack_header(nvl, ptr, &left);
624
625         nvp = nvlist_first_nvpair(nvl);
626         while (nvp != NULL) {
627                 NVPAIR_ASSERT(nvp);
628
629                 nvpair_init_datasize(nvp);
630                 ptr = nvpair_pack_header(nvp, ptr, &left);
631                 if (ptr == NULL) {
632                         nv_free(buf);
633                         return (NULL);
634                 }
635                 switch (nvpair_type(nvp)) {
636                 case NV_TYPE_NULL:
637                         ptr = nvpair_pack_null(nvp, ptr, &left);
638                         break;
639                 case NV_TYPE_BOOL:
640                         ptr = nvpair_pack_bool(nvp, ptr, &left);
641                         break;
642                 case NV_TYPE_NUMBER:
643                         ptr = nvpair_pack_number(nvp, ptr, &left);
644                         break;
645                 case NV_TYPE_STRING:
646                         ptr = nvpair_pack_string(nvp, ptr, &left);
647                         break;
648                 case NV_TYPE_NVLIST:
649                         tmpnvl = nvpair_get_nvlist(nvp);
650                         ptr = nvlist_pack_header(tmpnvl, ptr, &left);
651                         if (ptr == NULL)
652                                 goto out;
653                         tmpnvp = nvlist_first_nvpair(tmpnvl);
654                         if (tmpnvp != NULL) {
655                                 nvl = tmpnvl;
656                                 nvp = tmpnvp;
657                                 continue;
658                         }
659                         ptr = nvpair_pack_nvlist_up(ptr, &left);
660                         break;
661 #ifndef _KERNEL
662                 case NV_TYPE_DESCRIPTOR:
663                         ptr = nvpair_pack_descriptor(nvp, ptr, fdidxp, &left);
664                         break;
665 #endif
666                 case NV_TYPE_BINARY:
667                         ptr = nvpair_pack_binary(nvp, ptr, &left);
668                         break;
669                 default:
670                         PJDLOG_ABORT("Invalid type (%d).", nvpair_type(nvp));
671                 }
672                 if (ptr == NULL) {
673                         nv_free(buf);
674                         return (NULL);
675                 }
676                 while ((nvp = nvlist_next_nvpair(nvl, nvp)) == NULL) {
677                         cookie = NULL;
678                         nvl = nvlist_get_parent(nvl, &cookie);
679                         if (nvl == NULL)
680                                 goto out;
681                         nvp = cookie;
682                         ptr = nvpair_pack_nvlist_up(ptr, &left);
683                         if (ptr == NULL)
684                                 goto out;
685                 }
686         }
687
688 out:
689         if (sizep != NULL)
690                 *sizep = size;
691         return (buf);
692 }
693
694 void *
695 nvlist_pack(const nvlist_t *nvl, size_t *sizep)
696 {
697
698         NVLIST_ASSERT(nvl);
699
700         if (nvl->nvl_error != 0) {
701                 ERRNO_SET(nvl->nvl_error);
702                 return (NULL);
703         }
704
705         if (nvlist_ndescriptors(nvl) > 0) {
706                 ERRNO_SET(EOPNOTSUPP);
707                 return (NULL);
708         }
709
710         return (nvlist_xpack(nvl, NULL, sizep));
711 }
712
713 static bool
714 nvlist_check_header(struct nvlist_header *nvlhdrp)
715 {
716
717         if (nvlhdrp->nvlh_magic != NVLIST_HEADER_MAGIC) {
718                 ERRNO_SET(EINVAL);
719                 return (false);
720         }
721         if ((nvlhdrp->nvlh_flags & ~NV_FLAG_ALL_MASK) != 0) {
722                 ERRNO_SET(EINVAL);
723                 return (false);
724         }
725 #if BYTE_ORDER == BIG_ENDIAN
726         if ((nvlhdrp->nvlh_flags & NV_FLAG_BIG_ENDIAN) == 0) {
727                 nvlhdrp->nvlh_size = le64toh(nvlhdrp->nvlh_size);
728                 nvlhdrp->nvlh_descriptors = le64toh(nvlhdrp->nvlh_descriptors);
729         }
730 #else
731         if ((nvlhdrp->nvlh_flags & NV_FLAG_BIG_ENDIAN) != 0) {
732                 nvlhdrp->nvlh_size = be64toh(nvlhdrp->nvlh_size);
733                 nvlhdrp->nvlh_descriptors = be64toh(nvlhdrp->nvlh_descriptors);
734         }
735 #endif
736         return (true);
737 }
738
739 const unsigned char *
740 nvlist_unpack_header(nvlist_t *nvl, const unsigned char *ptr, size_t nfds,
741     bool *isbep, size_t *leftp)
742 {
743         struct nvlist_header nvlhdr;
744
745         if (*leftp < sizeof(nvlhdr))
746                 goto failed;
747
748         memcpy(&nvlhdr, ptr, sizeof(nvlhdr));
749
750         if (!nvlist_check_header(&nvlhdr))
751                 goto failed;
752
753         if (nvlhdr.nvlh_size != *leftp - sizeof(nvlhdr))
754                 goto failed;
755
756         /*
757          * nvlh_descriptors might be smaller than nfds in embedded nvlists.
758          */
759         if (nvlhdr.nvlh_descriptors > nfds)
760                 goto failed;
761
762         if ((nvlhdr.nvlh_flags & ~NV_FLAG_ALL_MASK) != 0)
763                 goto failed;
764
765         nvl->nvl_flags = (nvlhdr.nvlh_flags & NV_FLAG_PUBLIC_MASK);
766
767         ptr += sizeof(nvlhdr);
768         if (isbep != NULL)
769                 *isbep = (((int)nvlhdr.nvlh_flags & NV_FLAG_BIG_ENDIAN) != 0);
770         *leftp -= sizeof(nvlhdr);
771
772         return (ptr);
773 failed:
774         ERRNO_SET(EINVAL);
775         return (NULL);
776 }
777
778 static nvlist_t *
779 nvlist_xunpack(const void *buf, size_t size, const int *fds, size_t nfds,
780     int flags)
781 {
782         const unsigned char *ptr;
783         nvlist_t *nvl, *retnvl, *tmpnvl;
784         nvpair_t *nvp;
785         size_t left;
786         bool isbe;
787
788         PJDLOG_ASSERT((flags & ~(NV_FLAG_PUBLIC_MASK)) == 0);
789
790         left = size;
791         ptr = buf;
792
793         tmpnvl = NULL;
794         nvl = retnvl = nvlist_create(0);
795         if (nvl == NULL)
796                 goto failed;
797
798         ptr = nvlist_unpack_header(nvl, ptr, nfds, &isbe, &left);
799         if (ptr == NULL)
800                 goto failed;
801         if (nvl->nvl_flags != flags) {
802                 ERRNO_SET(EILSEQ);
803                 goto failed;
804         }
805
806         while (left > 0) {
807                 ptr = nvpair_unpack(isbe, ptr, &left, &nvp);
808                 if (ptr == NULL)
809                         goto failed;
810                 switch (nvpair_type(nvp)) {
811                 case NV_TYPE_NULL:
812                         ptr = nvpair_unpack_null(isbe, nvp, ptr, &left);
813                         break;
814                 case NV_TYPE_BOOL:
815                         ptr = nvpair_unpack_bool(isbe, nvp, ptr, &left);
816                         break;
817                 case NV_TYPE_NUMBER:
818                         ptr = nvpair_unpack_number(isbe, nvp, ptr, &left);
819                         break;
820                 case NV_TYPE_STRING:
821                         ptr = nvpair_unpack_string(isbe, nvp, ptr, &left);
822                         break;
823                 case NV_TYPE_NVLIST:
824                         ptr = nvpair_unpack_nvlist(isbe, nvp, ptr, &left, nfds,
825                             &tmpnvl);
826                         nvlist_set_parent(tmpnvl, nvp);
827                         break;
828 #ifndef _KERNEL
829                 case NV_TYPE_DESCRIPTOR:
830                         ptr = nvpair_unpack_descriptor(isbe, nvp, ptr, &left,
831                             fds, nfds);
832                         break;
833 #endif
834                 case NV_TYPE_BINARY:
835                         ptr = nvpair_unpack_binary(isbe, nvp, ptr, &left);
836                         break;
837                 case NV_TYPE_NVLIST_UP:
838                         if (nvl->nvl_parent == NULL)
839                                 goto failed;
840                         nvl = nvpair_nvlist(nvl->nvl_parent);
841                         nvpair_free_structure(nvp);
842                         continue;
843                 default:
844                         PJDLOG_ABORT("Invalid type (%d).", nvpair_type(nvp));
845                 }
846                 if (ptr == NULL)
847                         goto failed;
848                 nvlist_move_nvpair(nvl, nvp);
849                 if (tmpnvl != NULL) {
850                         nvl = tmpnvl;
851                         tmpnvl = NULL;
852                 }
853         }
854
855         return (retnvl);
856 failed:
857         nvlist_destroy(retnvl);
858         return (NULL);
859 }
860
861 nvlist_t *
862 nvlist_unpack(const void *buf, size_t size, int flags)
863 {
864
865         return (nvlist_xunpack(buf, size, NULL, 0, flags));
866 }
867
868 #ifndef _KERNEL
869 int
870 nvlist_send(int sock, const nvlist_t *nvl)
871 {
872         size_t datasize, nfds;
873         int *fds;
874         void *data;
875         int64_t fdidx;
876         int ret;
877
878         if (nvlist_error(nvl) != 0) {
879                 ERRNO_SET(nvlist_error(nvl));
880                 return (-1);
881         }
882
883         fds = nvlist_descriptors(nvl, &nfds);
884         if (fds == NULL)
885                 return (-1);
886
887         ret = -1;
888         data = NULL;
889         fdidx = 0;
890
891         data = nvlist_xpack(nvl, &fdidx, &datasize);
892         if (data == NULL)
893                 goto out;
894
895         if (buf_send(sock, data, datasize) == -1)
896                 goto out;
897
898         if (nfds > 0) {
899                 if (fd_send(sock, fds, nfds) == -1)
900                         goto out;
901         }
902
903         ret = 0;
904 out:
905         ERRNO_SAVE();
906         nv_free(fds);
907         nv_free(data);
908         ERRNO_RESTORE();
909         return (ret);
910 }
911
912 nvlist_t *
913 nvlist_recv(int sock, int flags)
914 {
915         struct nvlist_header nvlhdr;
916         nvlist_t *nvl, *ret;
917         unsigned char *buf;
918         size_t nfds, size, i;
919         int *fds;
920
921         if (buf_recv(sock, &nvlhdr, sizeof(nvlhdr)) == -1)
922                 return (NULL);
923
924         if (!nvlist_check_header(&nvlhdr))
925                 return (NULL);
926
927         nfds = (size_t)nvlhdr.nvlh_descriptors;
928         size = sizeof(nvlhdr) + (size_t)nvlhdr.nvlh_size;
929
930         buf = nv_malloc(size);
931         if (buf == NULL)
932                 return (NULL);
933
934         memcpy(buf, &nvlhdr, sizeof(nvlhdr));
935
936         ret = NULL;
937         fds = NULL;
938
939         if (buf_recv(sock, buf + sizeof(nvlhdr), size - sizeof(nvlhdr)) == -1)
940                 goto out;
941
942         if (nfds > 0) {
943                 fds = nv_malloc(nfds * sizeof(fds[0]));
944                 if (fds == NULL)
945                         goto out;
946                 if (fd_recv(sock, fds, nfds) == -1)
947                         goto out;
948         }
949
950         nvl = nvlist_xunpack(buf, size, fds, nfds, flags);
951         if (nvl == NULL) {
952                 ERRNO_SAVE();
953                 for (i = 0; i < nfds; i++)
954                         close(fds[i]);
955                 ERRNO_RESTORE();
956                 goto out;
957         }
958
959         ret = nvl;
960 out:
961         ERRNO_SAVE();
962         nv_free(buf);
963         nv_free(fds);
964         ERRNO_RESTORE();
965
966         return (ret);
967 }
968
969 nvlist_t *
970 nvlist_xfer(int sock, nvlist_t *nvl, int flags)
971 {
972
973         if (nvlist_send(sock, nvl) < 0) {
974                 nvlist_destroy(nvl);
975                 return (NULL);
976         }
977         nvlist_destroy(nvl);
978         return (nvlist_recv(sock, flags));
979 }
980 #endif
981
982 nvpair_t *
983 nvlist_first_nvpair(const nvlist_t *nvl)
984 {
985
986         NVLIST_ASSERT(nvl);
987
988         return (TAILQ_FIRST(&nvl->nvl_head));
989 }
990
991 nvpair_t *
992 nvlist_next_nvpair(const nvlist_t *nvl, const nvpair_t *nvp)
993 {
994         nvpair_t *retnvp;
995
996         NVLIST_ASSERT(nvl);
997         NVPAIR_ASSERT(nvp);
998         PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl);
999
1000         retnvp = nvpair_next(nvp);
1001         PJDLOG_ASSERT(retnvp == NULL || nvpair_nvlist(retnvp) == nvl);
1002
1003         return (retnvp);
1004
1005 }
1006
1007 nvpair_t *
1008 nvlist_prev_nvpair(const nvlist_t *nvl, const nvpair_t *nvp)
1009 {
1010         nvpair_t *retnvp;
1011
1012         NVLIST_ASSERT(nvl);
1013         NVPAIR_ASSERT(nvp);
1014         PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl);
1015
1016         retnvp = nvpair_prev(nvp);
1017         PJDLOG_ASSERT(nvpair_nvlist(retnvp) == nvl);
1018
1019         return (retnvp);
1020 }
1021
1022 const char *
1023 nvlist_next(const nvlist_t *nvl, int *typep, void **cookiep)
1024 {
1025         nvpair_t *nvp;
1026
1027         NVLIST_ASSERT(nvl);
1028         PJDLOG_ASSERT(cookiep != NULL);
1029
1030         if (*cookiep == NULL)
1031                 nvp = nvlist_first_nvpair(nvl);
1032         else
1033                 nvp = nvlist_next_nvpair(nvl, *cookiep);
1034         if (nvp == NULL)
1035                 return (NULL);
1036         if (typep != NULL)
1037                 *typep = nvpair_type(nvp);
1038         *cookiep = nvp;
1039         return (nvpair_name(nvp));
1040 }
1041
1042 bool
1043 nvlist_exists(const nvlist_t *nvl, const char *name)
1044 {
1045
1046         return (nvlist_find(nvl, NV_TYPE_NONE, name) != NULL);
1047 }
1048
1049 #define NVLIST_EXISTS(type, TYPE)                                       \
1050 bool                                                                    \
1051 nvlist_exists_##type(const nvlist_t *nvl, const char *name)             \
1052 {                                                                       \
1053                                                                         \
1054         return (nvlist_find(nvl, NV_TYPE_##TYPE, name) != NULL);        \
1055 }
1056
1057 NVLIST_EXISTS(null, NULL)
1058 NVLIST_EXISTS(bool, BOOL)
1059 NVLIST_EXISTS(number, NUMBER)
1060 NVLIST_EXISTS(string, STRING)
1061 NVLIST_EXISTS(nvlist, NVLIST)
1062 #ifndef _KERNEL
1063 NVLIST_EXISTS(descriptor, DESCRIPTOR)
1064 #endif
1065 NVLIST_EXISTS(binary, BINARY)
1066
1067 #undef  NVLIST_EXISTS
1068
1069 void
1070 nvlist_add_nvpair(nvlist_t *nvl, const nvpair_t *nvp)
1071 {
1072         nvpair_t *newnvp;
1073
1074         NVPAIR_ASSERT(nvp);
1075
1076         if (nvlist_error(nvl) != 0) {
1077                 ERRNO_SET(nvlist_error(nvl));
1078                 return;
1079         }
1080         if ((nvl->nvl_flags & NV_FLAG_NO_UNIQUE) == 0) {
1081                 if (nvlist_exists(nvl, nvpair_name(nvp))) {
1082                         nvl->nvl_error = EEXIST;
1083                         ERRNO_SET(nvlist_error(nvl));
1084                         return;
1085                 }
1086         }
1087
1088         newnvp = nvpair_clone(nvp);
1089         if (newnvp == NULL) {
1090                 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1091                 ERRNO_SET(nvlist_error(nvl));
1092                 return;
1093         }
1094
1095         nvpair_insert(&nvl->nvl_head, newnvp, nvl);
1096 }
1097
1098 void
1099 nvlist_add_stringf(nvlist_t *nvl, const char *name, const char *valuefmt, ...)
1100 {
1101         va_list valueap;
1102
1103         va_start(valueap, valuefmt);
1104         nvlist_add_stringv(nvl, name, valuefmt, valueap);
1105         va_end(valueap);
1106 }
1107
1108 void
1109 nvlist_add_stringv(nvlist_t *nvl, const char *name, const char *valuefmt,
1110     va_list valueap)
1111 {
1112         nvpair_t *nvp;
1113
1114         if (nvlist_error(nvl) != 0) {
1115                 ERRNO_SET(nvlist_error(nvl));
1116                 return;
1117         }
1118
1119         nvp = nvpair_create_stringv(name, valuefmt, valueap);
1120         if (nvp == NULL) {
1121                 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1122                 ERRNO_SET(nvl->nvl_error);
1123         } else {
1124                 nvlist_move_nvpair(nvl, nvp);
1125         }
1126 }
1127
1128 void
1129 nvlist_add_null(nvlist_t *nvl, const char *name)
1130 {
1131         nvpair_t *nvp;
1132
1133         if (nvlist_error(nvl) != 0) {
1134                 ERRNO_SET(nvlist_error(nvl));
1135                 return;
1136         }
1137
1138         nvp = nvpair_create_null(name);
1139         if (nvp == NULL) {
1140                 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1141                 ERRNO_SET(nvl->nvl_error);
1142         } else {
1143                 nvlist_move_nvpair(nvl, nvp);
1144         }
1145 }
1146
1147 void
1148 nvlist_add_binary(nvlist_t *nvl, const char *name, const void *value,
1149     size_t size)
1150 {
1151         nvpair_t *nvp;
1152
1153         if (nvlist_error(nvl) != 0) {
1154                 ERRNO_SET(nvlist_error(nvl));
1155                 return;
1156         }
1157
1158         nvp = nvpair_create_binary(name, value, size);
1159         if (nvp == NULL) {
1160                 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1161                 ERRNO_SET(nvl->nvl_error);
1162         } else {
1163                 nvlist_move_nvpair(nvl, nvp);
1164         }
1165 }
1166
1167
1168 #define NVLIST_ADD(vtype, type)                                         \
1169 void                                                                    \
1170 nvlist_add_##type(nvlist_t *nvl, const char *name, vtype value)         \
1171 {                                                                       \
1172         nvpair_t *nvp;                                                  \
1173                                                                         \
1174         if (nvlist_error(nvl) != 0) {                                   \
1175                 ERRNO_SET(nvlist_error(nvl));                           \
1176                 return;                                                 \
1177         }                                                               \
1178                                                                         \
1179         nvp = nvpair_create_##type(name, value);                        \
1180         if (nvp == NULL) {                                              \
1181                 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);              \
1182                 ERRNO_SET(nvl->nvl_error);                              \
1183         } else {                                                        \
1184                 nvlist_move_nvpair(nvl, nvp);                           \
1185         }                                                               \
1186 }
1187
1188 NVLIST_ADD(bool, bool)
1189 NVLIST_ADD(uint64_t, number)
1190 NVLIST_ADD(const char *, string)
1191 NVLIST_ADD(const nvlist_t *, nvlist)
1192 #ifndef _KERNEL
1193 NVLIST_ADD(int, descriptor);
1194 #endif
1195
1196 #undef  NVLIST_ADD
1197
1198 void
1199 nvlist_move_nvpair(nvlist_t *nvl, nvpair_t *nvp)
1200 {
1201
1202         NVPAIR_ASSERT(nvp);
1203         PJDLOG_ASSERT(nvpair_nvlist(nvp) == NULL);
1204
1205         if (nvlist_error(nvl) != 0) {
1206                 nvpair_free(nvp);
1207                 ERRNO_SET(nvlist_error(nvl));
1208                 return;
1209         }
1210         if ((nvl->nvl_flags & NV_FLAG_NO_UNIQUE) == 0) {
1211                 if (nvlist_exists(nvl, nvpair_name(nvp))) {
1212                         nvpair_free(nvp);
1213                         nvl->nvl_error = EEXIST;
1214                         ERRNO_SET(nvl->nvl_error);
1215                         return;
1216                 }
1217         }
1218
1219         nvpair_insert(&nvl->nvl_head, nvp, nvl);
1220 }
1221
1222 void
1223 nvlist_move_string(nvlist_t *nvl, const char *name, char *value)
1224 {
1225         nvpair_t *nvp;
1226
1227         if (nvlist_error(nvl) != 0) {
1228                 nv_free(value);
1229                 ERRNO_SET(nvlist_error(nvl));
1230                 return;
1231         }
1232
1233         nvp = nvpair_move_string(name, value);
1234         if (nvp == NULL) {
1235                 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1236                 ERRNO_SET(nvl->nvl_error);
1237         } else {
1238                 nvlist_move_nvpair(nvl, nvp);
1239         }
1240 }
1241
1242 void
1243 nvlist_move_nvlist(nvlist_t *nvl, const char *name, nvlist_t *value)
1244 {
1245         nvpair_t *nvp;
1246
1247         if (nvlist_error(nvl) != 0) {
1248                 if (value != NULL && nvlist_get_nvpair_parent(value) != NULL)
1249                         nvlist_destroy(value);
1250                 ERRNO_SET(nvlist_error(nvl));
1251                 return;
1252         }
1253
1254         nvp = nvpair_move_nvlist(name, value);
1255         if (nvp == NULL) {
1256                 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1257                 ERRNO_SET(nvl->nvl_error);
1258         } else {
1259                 nvlist_move_nvpair(nvl, nvp);
1260         }
1261 }
1262
1263 #ifndef _KERNEL
1264 void
1265 nvlist_move_descriptor(nvlist_t *nvl, const char *name, int value)
1266 {
1267         nvpair_t *nvp;
1268
1269         if (nvlist_error(nvl) != 0) {
1270                 close(value);
1271                 ERRNO_SET(nvlist_error(nvl));
1272                 return;
1273         }
1274
1275         nvp = nvpair_move_descriptor(name, value);
1276         if (nvp == NULL) {
1277                 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1278                 ERRNO_SET(nvl->nvl_error);
1279         } else {
1280                 nvlist_move_nvpair(nvl, nvp);
1281         }
1282 }
1283 #endif
1284
1285 void
1286 nvlist_move_binary(nvlist_t *nvl, const char *name, void *value, size_t size)
1287 {
1288         nvpair_t *nvp;
1289
1290         if (nvlist_error(nvl) != 0) {
1291                 nv_free(value);
1292                 ERRNO_SET(nvlist_error(nvl));
1293                 return;
1294         }
1295
1296         nvp = nvpair_move_binary(name, value, size);
1297         if (nvp == NULL) {
1298                 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1299                 ERRNO_SET(nvl->nvl_error);
1300         } else {
1301                 nvlist_move_nvpair(nvl, nvp);
1302         }
1303 }
1304
1305 const nvpair_t *
1306 nvlist_get_nvpair(const nvlist_t *nvl, const char *name)
1307 {
1308
1309         return (nvlist_find(nvl, NV_TYPE_NONE, name));
1310 }
1311
1312 #define NVLIST_GET(ftype, type, TYPE)                                   \
1313 ftype                                                                   \
1314 nvlist_get_##type(const nvlist_t *nvl, const char *name)                \
1315 {                                                                       \
1316         const nvpair_t *nvp;                                            \
1317                                                                         \
1318         nvp = nvlist_find(nvl, NV_TYPE_##TYPE, name);                   \
1319         if (nvp == NULL)                                                \
1320                 nvlist_report_missing(NV_TYPE_##TYPE, name);            \
1321         return (nvpair_get_##type(nvp));                                \
1322 }
1323
1324 NVLIST_GET(bool, bool, BOOL)
1325 NVLIST_GET(uint64_t, number, NUMBER)
1326 NVLIST_GET(const char *, string, STRING)
1327 NVLIST_GET(const nvlist_t *, nvlist, NVLIST)
1328 #ifndef _KERNEL
1329 NVLIST_GET(int, descriptor, DESCRIPTOR)
1330 #endif
1331
1332 #undef  NVLIST_GET
1333
1334 const void *
1335 nvlist_get_binary(const nvlist_t *nvl, const char *name, size_t *sizep)
1336 {
1337         nvpair_t *nvp;
1338
1339         nvp = nvlist_find(nvl, NV_TYPE_BINARY, name);
1340         if (nvp == NULL)
1341                 nvlist_report_missing(NV_TYPE_BINARY, name);
1342
1343         return (nvpair_get_binary(nvp, sizep));
1344 }
1345
1346 #define NVLIST_TAKE(ftype, type, TYPE)                                  \
1347 ftype                                                                   \
1348 nvlist_take_##type(nvlist_t *nvl, const char *name)                     \
1349 {                                                                       \
1350         nvpair_t *nvp;                                                  \
1351         ftype value;                                                    \
1352                                                                         \
1353         nvp = nvlist_find(nvl, NV_TYPE_##TYPE, name);                   \
1354         if (nvp == NULL)                                                \
1355                 nvlist_report_missing(NV_TYPE_##TYPE, name);            \
1356         value = (ftype)(intptr_t)nvpair_get_##type(nvp);                \
1357         nvlist_remove_nvpair(nvl, nvp);                                 \
1358         nvpair_free_structure(nvp);                                     \
1359         return (value);                                                 \
1360 }
1361
1362 NVLIST_TAKE(bool, bool, BOOL)
1363 NVLIST_TAKE(uint64_t, number, NUMBER)
1364 NVLIST_TAKE(char *, string, STRING)
1365 NVLIST_TAKE(nvlist_t *, nvlist, NVLIST)
1366 #ifndef _KERNEL
1367 NVLIST_TAKE(int, descriptor, DESCRIPTOR)
1368 #endif
1369
1370 #undef  NVLIST_TAKE
1371
1372 void *
1373 nvlist_take_binary(nvlist_t *nvl, const char *name, size_t *sizep)
1374 {
1375         nvpair_t *nvp;
1376         void *value;
1377
1378         nvp = nvlist_find(nvl, NV_TYPE_BINARY, name);
1379         if (nvp == NULL)
1380                 nvlist_report_missing(NV_TYPE_BINARY, name);
1381
1382         value = (void *)(intptr_t)nvpair_get_binary(nvp, sizep);
1383         nvlist_remove_nvpair(nvl, nvp);
1384         nvpair_free_structure(nvp);
1385         return (value);
1386 }
1387
1388 void
1389 nvlist_remove_nvpair(nvlist_t *nvl, nvpair_t *nvp)
1390 {
1391
1392         NVLIST_ASSERT(nvl);
1393         NVPAIR_ASSERT(nvp);
1394         PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl);
1395
1396         nvpair_remove(&nvl->nvl_head, nvp, nvl);
1397 }
1398
1399 void
1400 nvlist_free(nvlist_t *nvl, const char *name)
1401 {
1402
1403         nvlist_free_type(nvl, name, NV_TYPE_NONE);
1404 }
1405
1406 #define NVLIST_FREE(type, TYPE)                                         \
1407 void                                                                    \
1408 nvlist_free_##type(nvlist_t *nvl, const char *name)                     \
1409 {                                                                       \
1410                                                                         \
1411         nvlist_free_type(nvl, name, NV_TYPE_##TYPE);                    \
1412 }
1413
1414 NVLIST_FREE(null, NULL)
1415 NVLIST_FREE(bool, BOOL)
1416 NVLIST_FREE(number, NUMBER)
1417 NVLIST_FREE(string, STRING)
1418 NVLIST_FREE(nvlist, NVLIST)
1419 #ifndef _KERNEL
1420 NVLIST_FREE(descriptor, DESCRIPTOR)
1421 #endif
1422 NVLIST_FREE(binary, BINARY)
1423
1424 #undef  NVLIST_FREE
1425
1426 void
1427 nvlist_free_nvpair(nvlist_t *nvl, nvpair_t *nvp)
1428 {
1429
1430         NVLIST_ASSERT(nvl);
1431         NVPAIR_ASSERT(nvp);
1432         PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl);
1433
1434         nvlist_remove_nvpair(nvl, nvp);
1435         nvpair_free(nvp);
1436 }
1437