From owner-svn-src-all@freebsd.org Sat Jun 27 00:55:04 2020 Return-Path: Delivered-To: svn-src-all@mailman.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.nyi.freebsd.org (Postfix) with ESMTP id 1871D3634D3; Sat, 27 Jun 2020 00:55:04 +0000 (UTC) (envelope-from mmacy@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 49twJl5vQHz44Mn; Sat, 27 Jun 2020 00:55:03 +0000 (UTC) (envelope-from mmacy@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id AB67B1CD33; Sat, 27 Jun 2020 00:55:03 +0000 (UTC) (envelope-from mmacy@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id 05R0t3Q2070755; Sat, 27 Jun 2020 00:55:03 GMT (envelope-from mmacy@FreeBSD.org) Received: (from mmacy@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id 05R0t3oY070754; Sat, 27 Jun 2020 00:55:03 GMT (envelope-from mmacy@FreeBSD.org) Message-Id: <202006270055.05R0t3oY070754@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: mmacy set sender to mmacy@FreeBSD.org using -f From: Matt Macy Date: Sat, 27 Jun 2020 00:55:03 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r362666 - in head/sys: conf contrib/libnv X-SVN-Group: head X-SVN-Commit-Author: mmacy X-SVN-Commit-Paths: in head/sys: conf contrib/libnv X-SVN-Commit-Revision: 362666 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.33 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 27 Jun 2020 00:55:04 -0000 Author: mmacy Date: Sat Jun 27 00:55:03 2020 New Revision: 362666 URL: https://svnweb.freebsd.org/changeset/base/362666 Log: Rename nvpair.c to bsd_nvpair.c to not conflict with openzfs' version. Added: head/sys/contrib/libnv/bsd_nvpair.c - copied unchanged from r362665, head/sys/contrib/libnv/nvpair.c Deleted: head/sys/contrib/libnv/nvpair.c Modified: head/sys/conf/files Modified: head/sys/conf/files ============================================================================== --- head/sys/conf/files Fri Jun 26 22:23:15 2020 (r362665) +++ head/sys/conf/files Sat Jun 27 00:55:03 2020 (r362666) @@ -593,7 +593,7 @@ contrib/libfdt/fdt_wip.c optional fdt contrib/libnv/cnvlist.c standard contrib/libnv/dnvlist.c standard contrib/libnv/nvlist.c standard -contrib/libnv/nvpair.c standard +contrib/libnv/bsd_nvpair.c standard contrib/ngatm/netnatm/api/cc_conn.c optional ngatm_ccatm \ compile-with "${NORMAL_C_NOWERROR} -I$S/contrib/ngatm" contrib/ngatm/netnatm/api/cc_data.c optional ngatm_ccatm \ Copied: head/sys/contrib/libnv/bsd_nvpair.c (from r362665, head/sys/contrib/libnv/nvpair.c) ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/sys/contrib/libnv/bsd_nvpair.c Sat Jun 27 00:55:03 2020 (r362666, copy of r362665, head/sys/contrib/libnv/nvpair.c) @@ -0,0 +1,2135 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2009-2013 The FreeBSD Foundation + * Copyright (c) 2013-2015 Mariusz Zaborski + * All rights reserved. + * + * This software was developed by Pawel Jakub Dawidek under sponsorship from + * the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include + +#ifdef _KERNEL + +#include +#include +#include +#include + +#include + +#else +#include +#include +#include +#include +#include +#include +#include +#include + +#include "common_impl.h" +#endif + +#ifdef HAVE_PJDLOG +#include +#endif + +#include + +#include "nv_impl.h" +#include "nvlist_impl.h" +#include "nvpair_impl.h" + +#ifndef HAVE_PJDLOG +#ifdef _KERNEL +#define PJDLOG_ASSERT(...) MPASS(__VA_ARGS__) +#define PJDLOG_RASSERT(expr, ...) KASSERT(expr, (__VA_ARGS__)) +#define PJDLOG_ABORT(...) panic(__VA_ARGS__) +#else +#include +#define PJDLOG_ASSERT(...) assert(__VA_ARGS__) +#define PJDLOG_RASSERT(expr, ...) assert(expr) +#define PJDLOG_ABORT(...) abort() +#endif +#endif + +#define NVPAIR_MAGIC 0x6e7670 /* "nvp" */ +struct nvpair { + int nvp_magic; + char *nvp_name; + int nvp_type; + uint64_t nvp_data; + size_t nvp_datasize; + size_t nvp_nitems; /* Used only for array types. */ + nvlist_t *nvp_list; + TAILQ_ENTRY(nvpair) nvp_next; +}; + +#define NVPAIR_ASSERT(nvp) do { \ + PJDLOG_ASSERT((nvp) != NULL); \ + PJDLOG_ASSERT((nvp)->nvp_magic == NVPAIR_MAGIC); \ +} while (0) + +struct nvpair_header { + uint8_t nvph_type; + uint16_t nvph_namesize; + uint64_t nvph_datasize; + uint64_t nvph_nitems; +} __packed; + + +void +nvpair_assert(const nvpair_t *nvp __unused) +{ + + NVPAIR_ASSERT(nvp); +} + +static nvpair_t * +nvpair_allocv(const char *name, int type, uint64_t data, size_t datasize, + size_t nitems) +{ + nvpair_t *nvp; + size_t namelen; + + PJDLOG_ASSERT(type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST); + + namelen = strlen(name); + if (namelen >= NV_NAME_MAX) { + ERRNO_SET(ENAMETOOLONG); + return (NULL); + } + + nvp = nv_calloc(1, sizeof(*nvp) + namelen + 1); + if (nvp != NULL) { + nvp->nvp_name = (char *)(nvp + 1); + memcpy(nvp->nvp_name, name, namelen); + nvp->nvp_name[namelen] = '\0'; + nvp->nvp_type = type; + nvp->nvp_data = data; + nvp->nvp_datasize = datasize; + nvp->nvp_nitems = nitems; + nvp->nvp_magic = NVPAIR_MAGIC; + } + + return (nvp); +} + +static int +nvpair_append(nvpair_t *nvp, const void *value, size_t valsize, size_t datasize) +{ + void *olddata, *data, *valp; + size_t oldlen; + + oldlen = nvp->nvp_nitems * valsize; + olddata = (void *)(uintptr_t)nvp->nvp_data; + data = nv_realloc(olddata, oldlen + valsize); + if (data == NULL) { + ERRNO_SET(ENOMEM); + return (-1); + } + valp = (unsigned char *)data + oldlen; + memcpy(valp, value, valsize); + + nvp->nvp_data = (uint64_t)(uintptr_t)data; + nvp->nvp_datasize += datasize; + nvp->nvp_nitems++; + return (0); +} + +nvlist_t * +nvpair_nvlist(const nvpair_t *nvp) +{ + + NVPAIR_ASSERT(nvp); + + return (nvp->nvp_list); +} + +nvpair_t * +nvpair_next(const nvpair_t *nvp) +{ + + NVPAIR_ASSERT(nvp); + PJDLOG_ASSERT(nvp->nvp_list != NULL); + + return (TAILQ_NEXT(nvp, nvp_next)); +} + +nvpair_t * +nvpair_prev(const nvpair_t *nvp) +{ + + NVPAIR_ASSERT(nvp); + PJDLOG_ASSERT(nvp->nvp_list != NULL); + + return (TAILQ_PREV(nvp, nvl_head, nvp_next)); +} + +void +nvpair_insert(struct nvl_head *head, nvpair_t *nvp, nvlist_t *nvl) +{ + + NVPAIR_ASSERT(nvp); + PJDLOG_ASSERT(nvp->nvp_list == NULL); + PJDLOG_ASSERT((nvlist_flags(nvl) & NV_FLAG_NO_UNIQUE) != 0 || + !nvlist_exists(nvl, nvpair_name(nvp))); + + TAILQ_INSERT_TAIL(head, nvp, nvp_next); + nvp->nvp_list = nvl; +} + +static void +nvpair_remove_nvlist(nvpair_t *nvp) +{ + nvlist_t *nvl; + + /* XXX: DECONST is bad, mkay? */ + nvl = __DECONST(nvlist_t *, nvpair_get_nvlist(nvp)); + PJDLOG_ASSERT(nvl != NULL); + nvlist_set_parent(nvl, NULL); +} + +static void +nvpair_remove_nvlist_array(nvpair_t *nvp) +{ + nvlist_t **nvlarray; + size_t count, i; + + /* XXX: DECONST is bad, mkay? */ + nvlarray = __DECONST(nvlist_t **, + nvpair_get_nvlist_array(nvp, &count)); + for (i = 0; i < count; i++) { + nvlist_set_array_next(nvlarray[i], NULL); + nvlist_set_parent(nvlarray[i], NULL); + } +} + +void +nvpair_remove(struct nvl_head *head, nvpair_t *nvp, + const nvlist_t *nvl __unused) +{ + + NVPAIR_ASSERT(nvp); + PJDLOG_ASSERT(nvp->nvp_list == nvl); + + if (nvpair_type(nvp) == NV_TYPE_NVLIST) + nvpair_remove_nvlist(nvp); + else if (nvpair_type(nvp) == NV_TYPE_NVLIST_ARRAY) + nvpair_remove_nvlist_array(nvp); + + TAILQ_REMOVE(head, nvp, nvp_next); + nvp->nvp_list = NULL; +} + +nvpair_t * +nvpair_clone(const nvpair_t *nvp) +{ + nvpair_t *newnvp; + const char *name; + const void *data; + size_t datasize; + + NVPAIR_ASSERT(nvp); + + name = nvpair_name(nvp); + + switch (nvpair_type(nvp)) { + case NV_TYPE_NULL: + newnvp = nvpair_create_null(name); + break; + case NV_TYPE_BOOL: + newnvp = nvpair_create_bool(name, nvpair_get_bool(nvp)); + break; + case NV_TYPE_NUMBER: + newnvp = nvpair_create_number(name, nvpair_get_number(nvp)); + break; + case NV_TYPE_STRING: + newnvp = nvpair_create_string(name, nvpair_get_string(nvp)); + break; + case NV_TYPE_NVLIST: + newnvp = nvpair_create_nvlist(name, nvpair_get_nvlist(nvp)); + break; + case NV_TYPE_BINARY: + data = nvpair_get_binary(nvp, &datasize); + newnvp = nvpair_create_binary(name, data, datasize); + break; + case NV_TYPE_BOOL_ARRAY: + data = nvpair_get_bool_array(nvp, &datasize); + newnvp = nvpair_create_bool_array(name, data, datasize); + break; + case NV_TYPE_NUMBER_ARRAY: + data = nvpair_get_number_array(nvp, &datasize); + newnvp = nvpair_create_number_array(name, data, datasize); + break; + case NV_TYPE_STRING_ARRAY: + data = nvpair_get_string_array(nvp, &datasize); + newnvp = nvpair_create_string_array(name, data, datasize); + break; + case NV_TYPE_NVLIST_ARRAY: + data = nvpair_get_nvlist_array(nvp, &datasize); + newnvp = nvpair_create_nvlist_array(name, data, datasize); + break; +#ifndef _KERNEL + case NV_TYPE_DESCRIPTOR: + newnvp = nvpair_create_descriptor(name, + nvpair_get_descriptor(nvp)); + break; + case NV_TYPE_DESCRIPTOR_ARRAY: + data = nvpair_get_descriptor_array(nvp, &datasize); + newnvp = nvpair_create_descriptor_array(name, data, datasize); + break; +#endif + default: + PJDLOG_ABORT("Unknown type: %d.", nvpair_type(nvp)); + } + + return (newnvp); +} + +size_t +nvpair_header_size(void) +{ + + return (sizeof(struct nvpair_header)); +} + +size_t +nvpair_size(const nvpair_t *nvp) +{ + + NVPAIR_ASSERT(nvp); + + return (nvp->nvp_datasize); +} + +unsigned char * +nvpair_pack_header(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp) +{ + struct nvpair_header nvphdr; + size_t namesize; + + NVPAIR_ASSERT(nvp); + + nvphdr.nvph_type = nvp->nvp_type; + namesize = strlen(nvp->nvp_name) + 1; + PJDLOG_ASSERT(namesize > 0 && namesize <= UINT16_MAX); + nvphdr.nvph_namesize = namesize; + nvphdr.nvph_datasize = nvp->nvp_datasize; + nvphdr.nvph_nitems = nvp->nvp_nitems; + PJDLOG_ASSERT(*leftp >= sizeof(nvphdr)); + memcpy(ptr, &nvphdr, sizeof(nvphdr)); + ptr += sizeof(nvphdr); + *leftp -= sizeof(nvphdr); + + PJDLOG_ASSERT(*leftp >= namesize); + memcpy(ptr, nvp->nvp_name, namesize); + ptr += namesize; + *leftp -= namesize; + + return (ptr); +} + +unsigned char * +nvpair_pack_null(const nvpair_t *nvp __unused, unsigned char *ptr, + size_t *leftp __unused) +{ + + NVPAIR_ASSERT(nvp); + PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NULL); + + return (ptr); +} + +unsigned char * +nvpair_pack_bool(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp) +{ + uint8_t value; + + NVPAIR_ASSERT(nvp); + PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BOOL); + + value = (uint8_t)nvp->nvp_data; + + PJDLOG_ASSERT(*leftp >= sizeof(value)); + memcpy(ptr, &value, sizeof(value)); + ptr += sizeof(value); + *leftp -= sizeof(value); + + return (ptr); +} + +unsigned char * +nvpair_pack_number(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp) +{ + uint64_t value; + + NVPAIR_ASSERT(nvp); + PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NUMBER); + + value = (uint64_t)nvp->nvp_data; + + PJDLOG_ASSERT(*leftp >= sizeof(value)); + memcpy(ptr, &value, sizeof(value)); + ptr += sizeof(value); + *leftp -= sizeof(value); + + return (ptr); +} + +unsigned char * +nvpair_pack_string(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp) +{ + + NVPAIR_ASSERT(nvp); + PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING); + + PJDLOG_ASSERT(*leftp >= nvp->nvp_datasize); + memcpy(ptr, (const void *)(intptr_t)nvp->nvp_data, nvp->nvp_datasize); + ptr += nvp->nvp_datasize; + *leftp -= nvp->nvp_datasize; + + return (ptr); +} + +unsigned char * +nvpair_pack_nvlist_up(unsigned char *ptr, size_t *leftp) +{ + struct nvpair_header nvphdr; + size_t namesize; + const char *name = ""; + + namesize = 1; + nvphdr.nvph_type = NV_TYPE_NVLIST_UP; + nvphdr.nvph_namesize = namesize; + nvphdr.nvph_datasize = 0; + nvphdr.nvph_nitems = 0; + PJDLOG_ASSERT(*leftp >= sizeof(nvphdr)); + memcpy(ptr, &nvphdr, sizeof(nvphdr)); + ptr += sizeof(nvphdr); + *leftp -= sizeof(nvphdr); + + PJDLOG_ASSERT(*leftp >= namesize); + memcpy(ptr, name, namesize); + ptr += namesize; + *leftp -= namesize; + + return (ptr); +} + +unsigned char * +nvpair_pack_nvlist_array_next(unsigned char *ptr, size_t *leftp) +{ + struct nvpair_header nvphdr; + size_t namesize; + const char *name = ""; + + namesize = 1; + nvphdr.nvph_type = NV_TYPE_NVLIST_ARRAY_NEXT; + nvphdr.nvph_namesize = namesize; + nvphdr.nvph_datasize = 0; + nvphdr.nvph_nitems = 0; + PJDLOG_ASSERT(*leftp >= sizeof(nvphdr)); + memcpy(ptr, &nvphdr, sizeof(nvphdr)); + ptr += sizeof(nvphdr); + *leftp -= sizeof(nvphdr); + + PJDLOG_ASSERT(*leftp >= namesize); + memcpy(ptr, name, namesize); + ptr += namesize; + *leftp -= namesize; + + return (ptr); +} + +#ifndef _KERNEL +unsigned char * +nvpair_pack_descriptor(const nvpair_t *nvp, unsigned char *ptr, int64_t *fdidxp, + size_t *leftp) +{ + int64_t value; + + NVPAIR_ASSERT(nvp); + PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR); + + value = (int64_t)nvp->nvp_data; + if (value != -1) { + /* + * If there is a real descriptor here, we change its number + * to position in the array of descriptors send via control + * message. + */ + PJDLOG_ASSERT(fdidxp != NULL); + + value = *fdidxp; + (*fdidxp)++; + } + + PJDLOG_ASSERT(*leftp >= sizeof(value)); + memcpy(ptr, &value, sizeof(value)); + ptr += sizeof(value); + *leftp -= sizeof(value); + + return (ptr); +} +#endif + +unsigned char * +nvpair_pack_binary(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp) +{ + + NVPAIR_ASSERT(nvp); + PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BINARY); + + PJDLOG_ASSERT(*leftp >= nvp->nvp_datasize); + memcpy(ptr, (const void *)(intptr_t)nvp->nvp_data, nvp->nvp_datasize); + ptr += nvp->nvp_datasize; + *leftp -= nvp->nvp_datasize; + + return (ptr); +} + +unsigned char * +nvpair_pack_bool_array(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp) +{ + + NVPAIR_ASSERT(nvp); + PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BOOL_ARRAY); + PJDLOG_ASSERT(*leftp >= nvp->nvp_datasize); + + memcpy(ptr, (const void *)(intptr_t)nvp->nvp_data, nvp->nvp_datasize); + ptr += nvp->nvp_datasize; + *leftp -= nvp->nvp_datasize; + + return (ptr); +} + +unsigned char * +nvpair_pack_number_array(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp) +{ + + NVPAIR_ASSERT(nvp); + PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NUMBER_ARRAY); + PJDLOG_ASSERT(*leftp >= nvp->nvp_datasize); + + memcpy(ptr, (const void *)(intptr_t)nvp->nvp_data, nvp->nvp_datasize); + ptr += nvp->nvp_datasize; + *leftp -= nvp->nvp_datasize; + + return (ptr); +} + +unsigned char * +nvpair_pack_string_array(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp) +{ + unsigned int ii; + size_t size, len; + const char * const *array; + + NVPAIR_ASSERT(nvp); + PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING_ARRAY); + PJDLOG_ASSERT(*leftp >= nvp->nvp_datasize); + + size = 0; + array = nvpair_get_string_array(nvp, NULL); + PJDLOG_ASSERT(array != NULL); + + for (ii = 0; ii < nvp->nvp_nitems; ii++) { + len = strlen(array[ii]) + 1; + PJDLOG_ASSERT(*leftp >= len); + + memcpy(ptr, (const void *)array[ii], len); + size += len; + ptr += len; + *leftp -= len; + } + + PJDLOG_ASSERT(size == nvp->nvp_datasize); + + return (ptr); +} + +#ifndef _KERNEL +unsigned char * +nvpair_pack_descriptor_array(const nvpair_t *nvp, unsigned char *ptr, + int64_t *fdidxp, size_t *leftp) +{ + int64_t value; + const int *array; + unsigned int ii; + + NVPAIR_ASSERT(nvp); + PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR_ARRAY); + PJDLOG_ASSERT(*leftp >= nvp->nvp_datasize); + + array = nvpair_get_descriptor_array(nvp, NULL); + PJDLOG_ASSERT(array != NULL); + + for (ii = 0; ii < nvp->nvp_nitems; ii++) { + PJDLOG_ASSERT(*leftp >= sizeof(value)); + + value = array[ii]; + if (value != -1) { + /* + * If there is a real descriptor here, we change its + * number to position in the array of descriptors send + * via control message. + */ + PJDLOG_ASSERT(fdidxp != NULL); + + value = *fdidxp; + (*fdidxp)++; + } + memcpy(ptr, &value, sizeof(value)); + ptr += sizeof(value); + *leftp -= sizeof(value); + } + + return (ptr); +} +#endif + +void +nvpair_init_datasize(nvpair_t *nvp) +{ + + NVPAIR_ASSERT(nvp); + + if (nvp->nvp_type == NV_TYPE_NVLIST) { + if (nvp->nvp_data == 0) { + nvp->nvp_datasize = 0; + } else { + nvp->nvp_datasize = + nvlist_size((const nvlist_t *)(intptr_t)nvp->nvp_data); + } + } +} + +const unsigned char * +nvpair_unpack_header(bool isbe, nvpair_t *nvp, const unsigned char *ptr, + size_t *leftp) +{ + struct nvpair_header nvphdr; + + if (*leftp < sizeof(nvphdr)) + goto fail; + + memcpy(&nvphdr, ptr, sizeof(nvphdr)); + ptr += sizeof(nvphdr); + *leftp -= sizeof(nvphdr); + +#if NV_TYPE_FIRST > 0 + if (nvphdr.nvph_type < NV_TYPE_FIRST) + goto fail; +#endif + if (nvphdr.nvph_type > NV_TYPE_LAST && + nvphdr.nvph_type != NV_TYPE_NVLIST_UP && + nvphdr.nvph_type != NV_TYPE_NVLIST_ARRAY_NEXT) { + goto fail; + } + +#if BYTE_ORDER == BIG_ENDIAN + if (!isbe) { + nvphdr.nvph_namesize = le16toh(nvphdr.nvph_namesize); + nvphdr.nvph_datasize = le64toh(nvphdr.nvph_datasize); + } +#else + if (isbe) { + nvphdr.nvph_namesize = be16toh(nvphdr.nvph_namesize); + nvphdr.nvph_datasize = be64toh(nvphdr.nvph_datasize); + } +#endif + + if (nvphdr.nvph_namesize > NV_NAME_MAX) + goto fail; + if (*leftp < nvphdr.nvph_namesize) + goto fail; + if (nvphdr.nvph_namesize < 1) + goto fail; + if (strnlen((const char *)ptr, nvphdr.nvph_namesize) != + (size_t)(nvphdr.nvph_namesize - 1)) { + goto fail; + } + + memcpy(nvp->nvp_name, ptr, nvphdr.nvph_namesize); + ptr += nvphdr.nvph_namesize; + *leftp -= nvphdr.nvph_namesize; + + if (*leftp < nvphdr.nvph_datasize) + goto fail; + + nvp->nvp_type = nvphdr.nvph_type; + nvp->nvp_data = 0; + nvp->nvp_datasize = nvphdr.nvph_datasize; + nvp->nvp_nitems = nvphdr.nvph_nitems; + + return (ptr); +fail: + ERRNO_SET(EINVAL); + return (NULL); +} + +const unsigned char * +nvpair_unpack_null(bool isbe __unused, nvpair_t *nvp, const unsigned char *ptr, + size_t *leftp __unused) +{ + + PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NULL); + + if (nvp->nvp_datasize != 0) { + ERRNO_SET(EINVAL); + return (NULL); + } + + return (ptr); +} + +const unsigned char * +nvpair_unpack_bool(bool isbe __unused, nvpair_t *nvp, const unsigned char *ptr, + size_t *leftp) +{ + uint8_t value; + + PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BOOL); + + if (nvp->nvp_datasize != sizeof(value)) { + ERRNO_SET(EINVAL); + return (NULL); + } + if (*leftp < sizeof(value)) { + ERRNO_SET(EINVAL); + return (NULL); + } + + memcpy(&value, ptr, sizeof(value)); + ptr += sizeof(value); + *leftp -= sizeof(value); + + if (value != 0 && value != 1) { + ERRNO_SET(EINVAL); + return (NULL); + } + + nvp->nvp_data = (uint64_t)value; + + return (ptr); +} + +const unsigned char * +nvpair_unpack_number(bool isbe, nvpair_t *nvp, const unsigned char *ptr, + size_t *leftp) +{ + + PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NUMBER); + + if (nvp->nvp_datasize != sizeof(uint64_t)) { + ERRNO_SET(EINVAL); + return (NULL); + } + if (*leftp < sizeof(uint64_t)) { + ERRNO_SET(EINVAL); + return (NULL); + } + + if (isbe) + nvp->nvp_data = be64dec(ptr); + else + nvp->nvp_data = le64dec(ptr); + + ptr += sizeof(uint64_t); + *leftp -= sizeof(uint64_t); + + return (ptr); +} + +const unsigned char * +nvpair_unpack_string(bool isbe __unused, nvpair_t *nvp, + const unsigned char *ptr, size_t *leftp) +{ + + PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING); + + if (*leftp < nvp->nvp_datasize || nvp->nvp_datasize == 0) { + ERRNO_SET(EINVAL); + return (NULL); + } + + if (strnlen((const char *)ptr, nvp->nvp_datasize) != + nvp->nvp_datasize - 1) { + ERRNO_SET(EINVAL); + return (NULL); + } + + nvp->nvp_data = (uint64_t)(uintptr_t)nv_strdup((const char *)ptr); + if (nvp->nvp_data == 0) + return (NULL); + + ptr += nvp->nvp_datasize; + *leftp -= nvp->nvp_datasize; + + return (ptr); +} + +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) +{ + nvlist_t *value; + + PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST); + + if (*leftp < nvp->nvp_datasize || nvp->nvp_datasize == 0) { + ERRNO_SET(EINVAL); + return (NULL); + } + + value = nvlist_create(0); + if (value == NULL) + return (NULL); + + ptr = nvlist_unpack_header(value, ptr, nfds, NULL, leftp); + if (ptr == NULL) + return (NULL); + + nvp->nvp_data = (uint64_t)(uintptr_t)value; + *child = value; + + return (ptr); +} + +#ifndef _KERNEL +const unsigned char * +nvpair_unpack_descriptor(bool isbe, nvpair_t *nvp, const unsigned char *ptr, + size_t *leftp, const int *fds, size_t nfds) +{ + int64_t idx; + + PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR); + + if (nvp->nvp_datasize != sizeof(idx)) { + ERRNO_SET(EINVAL); + return (NULL); + } + if (*leftp < sizeof(idx)) { + ERRNO_SET(EINVAL); + return (NULL); + } + + if (isbe) + idx = be64dec(ptr); + else + idx = le64dec(ptr); + + if (idx < 0) { + ERRNO_SET(EINVAL); + return (NULL); + } + + if ((size_t)idx >= nfds) { + ERRNO_SET(EINVAL); + return (NULL); + } + + nvp->nvp_data = (uint64_t)fds[idx]; + + ptr += sizeof(idx); + *leftp -= sizeof(idx); + + return (ptr); +} +#endif + +const unsigned char * +nvpair_unpack_binary(bool isbe __unused, nvpair_t *nvp, + const unsigned char *ptr, size_t *leftp) +{ + void *value; + + PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BINARY); + + if (*leftp < nvp->nvp_datasize || nvp->nvp_datasize == 0) { + ERRNO_SET(EINVAL); + return (NULL); + } + + value = nv_malloc(nvp->nvp_datasize); + if (value == NULL) + return (NULL); + + memcpy(value, ptr, nvp->nvp_datasize); + ptr += nvp->nvp_datasize; + *leftp -= nvp->nvp_datasize; + + nvp->nvp_data = (uint64_t)(uintptr_t)value; + + return (ptr); +} + +const unsigned char * +nvpair_unpack_bool_array(bool isbe __unused, nvpair_t *nvp, + const unsigned char *ptr, size_t *leftp) +{ + uint8_t *value; + size_t size; + unsigned int i; + + PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BOOL_ARRAY); + + size = sizeof(*value) * nvp->nvp_nitems; + if (nvp->nvp_datasize != size || *leftp < size || + nvp->nvp_nitems == 0 || size < nvp->nvp_nitems) { + ERRNO_SET(EINVAL); + return (NULL); + } + + value = nv_malloc(size); + if (value == NULL) + return (NULL); + + for (i = 0; i < nvp->nvp_nitems; i++) { + value[i] = *(const uint8_t *)ptr; + + ptr += sizeof(*value); + *leftp -= sizeof(*value); + } + + nvp->nvp_data = (uint64_t)(uintptr_t)value; + + return (ptr); +} + +const unsigned char * +nvpair_unpack_number_array(bool isbe, nvpair_t *nvp, const unsigned char *ptr, + size_t *leftp) +{ + uint64_t *value; + size_t size; + unsigned int i; + + PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NUMBER_ARRAY); + + size = sizeof(*value) * nvp->nvp_nitems; + if (nvp->nvp_datasize != size || *leftp < size || + nvp->nvp_nitems == 0 || size < nvp->nvp_nitems) { + ERRNO_SET(EINVAL); + return (NULL); + } + + value = nv_malloc(size); + if (value == NULL) + return (NULL); + + for (i = 0; i < nvp->nvp_nitems; i++) { + if (isbe) + value[i] = be64dec(ptr); + else + value[i] = le64dec(ptr); + + ptr += sizeof(*value); + *leftp -= sizeof(*value); + } + + nvp->nvp_data = (uint64_t)(uintptr_t)value; + + return (ptr); +} + +const unsigned char * +nvpair_unpack_string_array(bool isbe __unused, nvpair_t *nvp, + const unsigned char *ptr, size_t *leftp) +{ + ssize_t size; + size_t len; + const char *tmp; + char **value; + unsigned int ii, j; + + PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING_ARRAY); + + if (*leftp < nvp->nvp_datasize || nvp->nvp_datasize == 0 || + nvp->nvp_nitems == 0) { + ERRNO_SET(EINVAL); + return (NULL); + } + + size = nvp->nvp_datasize; + tmp = (const char *)ptr; + for (ii = 0; ii < nvp->nvp_nitems; ii++) { *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***