13830659eSToomas Soome /*- 23830659eSToomas Soome * Copyright 2020 Toomas Soome <tsoome@me.com> 33830659eSToomas Soome * 43830659eSToomas Soome * Redistribution and use in source and binary forms, with or without 53830659eSToomas Soome * modification, are permitted provided that the following conditions 63830659eSToomas Soome * are met: 73830659eSToomas Soome * 1. Redistributions of source code must retain the above copyright 83830659eSToomas Soome * notice, this list of conditions and the following disclaimer. 93830659eSToomas Soome * 2. Redistributions in binary form must reproduce the above copyright 103830659eSToomas Soome * notice, this list of conditions and the following disclaimer in the 113830659eSToomas Soome * documentation and/or other materials provided with the distribution. 123830659eSToomas Soome * 133830659eSToomas Soome * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 143830659eSToomas Soome * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 153830659eSToomas Soome * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 163830659eSToomas Soome * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 173830659eSToomas Soome * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 183830659eSToomas Soome * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 193830659eSToomas Soome * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 203830659eSToomas Soome * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 213830659eSToomas Soome * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 223830659eSToomas Soome * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 233830659eSToomas Soome * SUCH DAMAGE. 243830659eSToomas Soome */ 253830659eSToomas Soome 263830659eSToomas Soome #include <sys/cdefs.h> 273830659eSToomas Soome __FBSDID("$FreeBSD$"); 283830659eSToomas Soome 293830659eSToomas Soome #include <stand.h> 30e307eb94SToomas Soome #include <stdbool.h> 313830659eSToomas Soome #include <sys/endian.h> 32e307eb94SToomas Soome #include <sys/stdint.h> 33e307eb94SToomas Soome #include <sys/param.h> 343830659eSToomas Soome #include <zfsimpl.h> 353830659eSToomas Soome #include "libzfs.h" 363830659eSToomas Soome 37e307eb94SToomas Soome enum xdr_op { 38e307eb94SToomas Soome XDR_OP_ENCODE = 1, 39e307eb94SToomas Soome XDR_OP_DECODE = 2 40e307eb94SToomas Soome }; 41e307eb94SToomas Soome 423830659eSToomas Soome typedef struct xdr { 43e307eb94SToomas Soome enum xdr_op xdr_op; 44e307eb94SToomas Soome int (*xdr_getint)(struct xdr *, int *); 45e307eb94SToomas Soome int (*xdr_putint)(struct xdr *, int); 46e307eb94SToomas Soome int (*xdr_getuint)(struct xdr *, unsigned *); 47e307eb94SToomas Soome int (*xdr_putuint)(struct xdr *, unsigned); 48e307eb94SToomas Soome const uint8_t *xdr_buf; 49e307eb94SToomas Soome uint8_t *xdr_idx; 50e307eb94SToomas Soome size_t xdr_buf_size; 513830659eSToomas Soome } xdr_t; 523830659eSToomas Soome 53e307eb94SToomas Soome static int nvlist_xdr_nvlist(xdr_t *, nvlist_t *); 54e307eb94SToomas Soome static bool nvlist_size_xdr(xdr_t *, size_t *); 55e307eb94SToomas Soome static bool nvlist_size_native(xdr_t *, size_t *); 56e307eb94SToomas Soome static bool xdr_int(xdr_t *, int *); 57e307eb94SToomas Soome static bool xdr_u_int(xdr_t *, unsigned *); 583830659eSToomas Soome 59e307eb94SToomas Soome typedef int (*xdrproc_t)(xdr_t *, void *); 603830659eSToomas Soome 61e307eb94SToomas Soome /* Basic primitives for XDR translation operations, getint and putint. */ 623830659eSToomas Soome static int 63e307eb94SToomas Soome _getint(struct xdr *xdr, int *ip) 643830659eSToomas Soome { 65e307eb94SToomas Soome *ip = be32dec(xdr->xdr_idx); 663830659eSToomas Soome return (sizeof(int)); 673830659eSToomas Soome } 683830659eSToomas Soome 693830659eSToomas Soome static int 70e307eb94SToomas Soome _putint(struct xdr *xdr, int i) 713830659eSToomas Soome { 72e307eb94SToomas Soome int *ip = (int *)xdr->xdr_idx; 73e307eb94SToomas Soome 74e307eb94SToomas Soome *ip = htobe32(i); 75e307eb94SToomas Soome return (sizeof(int)); 76e307eb94SToomas Soome } 77e307eb94SToomas Soome 78e307eb94SToomas Soome static int 79e307eb94SToomas Soome _getuint(struct xdr *xdr, unsigned *ip) 80e307eb94SToomas Soome { 81e307eb94SToomas Soome *ip = be32dec(xdr->xdr_idx); 823830659eSToomas Soome return (sizeof(unsigned)); 833830659eSToomas Soome } 843830659eSToomas Soome 853830659eSToomas Soome static int 86e307eb94SToomas Soome _putuint(struct xdr *xdr, unsigned i) 873830659eSToomas Soome { 88e307eb94SToomas Soome unsigned *up = (unsigned *)xdr->xdr_idx; 893830659eSToomas Soome 90e307eb94SToomas Soome *up = htobe32(i); 91e307eb94SToomas Soome return (sizeof(int)); 923830659eSToomas Soome } 933830659eSToomas Soome 949de6a13eSToomas Soome static int 959de6a13eSToomas Soome _getint_mem(struct xdr *xdr, int *ip) 969de6a13eSToomas Soome { 979de6a13eSToomas Soome *ip = *(int *)xdr->xdr_idx; 989de6a13eSToomas Soome return (sizeof(int)); 999de6a13eSToomas Soome } 1009de6a13eSToomas Soome 1019de6a13eSToomas Soome static int 1029de6a13eSToomas Soome _putint_mem(struct xdr *xdr, int i) 1039de6a13eSToomas Soome { 1049de6a13eSToomas Soome int *ip = (int *)xdr->xdr_idx; 1059de6a13eSToomas Soome 1069de6a13eSToomas Soome *ip = i; 1079de6a13eSToomas Soome return (sizeof(int)); 1089de6a13eSToomas Soome } 1099de6a13eSToomas Soome 1109de6a13eSToomas Soome static int 1119de6a13eSToomas Soome _getuint_mem(struct xdr *xdr, unsigned *ip) 1129de6a13eSToomas Soome { 1139de6a13eSToomas Soome *ip = *(unsigned *)xdr->xdr_idx; 1149de6a13eSToomas Soome return (sizeof(unsigned)); 1159de6a13eSToomas Soome } 1169de6a13eSToomas Soome 1179de6a13eSToomas Soome static int 1189de6a13eSToomas Soome _putuint_mem(struct xdr *xdr, unsigned i) 1199de6a13eSToomas Soome { 1209de6a13eSToomas Soome unsigned *up = (unsigned *)xdr->xdr_idx; 1219de6a13eSToomas Soome 1229de6a13eSToomas Soome *up = i; 1239de6a13eSToomas Soome return (sizeof(int)); 1249de6a13eSToomas Soome } 1259de6a13eSToomas Soome 126e307eb94SToomas Soome /* 127e307eb94SToomas Soome * XDR data translations. 128e307eb94SToomas Soome */ 129e307eb94SToomas Soome static bool 130e307eb94SToomas Soome xdr_short(xdr_t *xdr, short *ip) 1313830659eSToomas Soome { 132e307eb94SToomas Soome int i; 133e307eb94SToomas Soome bool rv; 1343830659eSToomas Soome 135e307eb94SToomas Soome i = *ip; 136e307eb94SToomas Soome if ((rv = xdr_int(xdr, &i))) { 137e307eb94SToomas Soome if (xdr->xdr_op == XDR_OP_DECODE) 138e307eb94SToomas Soome *ip = i; 139e307eb94SToomas Soome } 1403830659eSToomas Soome return (rv); 1413830659eSToomas Soome } 1423830659eSToomas Soome 143e307eb94SToomas Soome static bool 144e307eb94SToomas Soome xdr_u_short(xdr_t *xdr, unsigned short *ip) 1453830659eSToomas Soome { 146e307eb94SToomas Soome unsigned u; 147e307eb94SToomas Soome bool rv; 1483830659eSToomas Soome 149e307eb94SToomas Soome u = *ip; 150e307eb94SToomas Soome if ((rv = xdr_u_int(xdr, &u))) { 151e307eb94SToomas Soome if (xdr->xdr_op == XDR_OP_DECODE) 152e307eb94SToomas Soome *ip = u; 1533830659eSToomas Soome } 1543830659eSToomas Soome return (rv); 1553830659eSToomas Soome } 1563830659eSToomas Soome 1573830659eSToomas Soome /* 158e307eb94SToomas Soome * translate xdr->xdr_idx, increment it by size of int. 1593830659eSToomas Soome */ 160e307eb94SToomas Soome static bool 161e307eb94SToomas Soome xdr_int(xdr_t *xdr, int *ip) 1623830659eSToomas Soome { 163e307eb94SToomas Soome bool rv = false; 164e307eb94SToomas Soome int *i = (int *)xdr->xdr_idx; 165e307eb94SToomas Soome 166e307eb94SToomas Soome if (xdr->xdr_idx + sizeof(int) > xdr->xdr_buf + xdr->xdr_buf_size) 167e307eb94SToomas Soome return (rv); 168e307eb94SToomas Soome 169e307eb94SToomas Soome switch (xdr->xdr_op) { 170e307eb94SToomas Soome case XDR_OP_ENCODE: 171e307eb94SToomas Soome /* Encode value *ip, store to buf */ 172e307eb94SToomas Soome xdr->xdr_idx += xdr->xdr_putint(xdr, *ip); 173e307eb94SToomas Soome rv = true; 174e307eb94SToomas Soome break; 175e307eb94SToomas Soome 176e307eb94SToomas Soome case XDR_OP_DECODE: 177e307eb94SToomas Soome /* Decode buf, return value to *ip */ 178e307eb94SToomas Soome xdr->xdr_idx += xdr->xdr_getint(xdr, i); 179e307eb94SToomas Soome *ip = *i; 180e307eb94SToomas Soome rv = true; 181e307eb94SToomas Soome break; 182e307eb94SToomas Soome } 183e307eb94SToomas Soome return (rv); 1843830659eSToomas Soome } 1853830659eSToomas Soome 186e307eb94SToomas Soome /* 187e307eb94SToomas Soome * translate xdr->xdr_idx, increment it by size of unsigned int. 188e307eb94SToomas Soome */ 189e307eb94SToomas Soome static bool 190e307eb94SToomas Soome xdr_u_int(xdr_t *xdr, unsigned *ip) 191e307eb94SToomas Soome { 192e307eb94SToomas Soome bool rv = false; 193e307eb94SToomas Soome unsigned *u = (unsigned *)xdr->xdr_idx; 194e307eb94SToomas Soome 195e307eb94SToomas Soome if (xdr->xdr_idx + sizeof(unsigned) > xdr->xdr_buf + xdr->xdr_buf_size) 196e307eb94SToomas Soome return (rv); 197e307eb94SToomas Soome 198e307eb94SToomas Soome switch (xdr->xdr_op) { 199e307eb94SToomas Soome case XDR_OP_ENCODE: 200e307eb94SToomas Soome /* Encode value *ip, store to buf */ 201e307eb94SToomas Soome xdr->xdr_idx += xdr->xdr_putuint(xdr, *ip); 202e307eb94SToomas Soome rv = true; 203e307eb94SToomas Soome break; 204e307eb94SToomas Soome 205e307eb94SToomas Soome case XDR_OP_DECODE: 206e307eb94SToomas Soome /* Decode buf, return value to *ip */ 207e307eb94SToomas Soome xdr->xdr_idx += xdr->xdr_getuint(xdr, u); 208e307eb94SToomas Soome *ip = *u; 209e307eb94SToomas Soome rv = true; 210e307eb94SToomas Soome break; 211e307eb94SToomas Soome } 212e307eb94SToomas Soome return (rv); 213e307eb94SToomas Soome } 214e307eb94SToomas Soome 215e307eb94SToomas Soome static bool 216e307eb94SToomas Soome xdr_int64(xdr_t *xdr, int64_t *lp) 217e307eb94SToomas Soome { 218e307eb94SToomas Soome bool rv = false; 219e307eb94SToomas Soome 220e307eb94SToomas Soome if (xdr->xdr_idx + sizeof(int64_t) > xdr->xdr_buf + xdr->xdr_buf_size) 221e307eb94SToomas Soome return (rv); 222e307eb94SToomas Soome 223e307eb94SToomas Soome switch (xdr->xdr_op) { 224e307eb94SToomas Soome case XDR_OP_ENCODE: 225e307eb94SToomas Soome /* Encode value *lp, store to buf */ 2269de6a13eSToomas Soome if (xdr->xdr_putint == _putint) 2279de6a13eSToomas Soome *(int64_t *)xdr->xdr_idx = htobe64(*lp); 2289de6a13eSToomas Soome else 2299de6a13eSToomas Soome *(int64_t *)xdr->xdr_idx = *lp; 2309de6a13eSToomas Soome xdr->xdr_idx += sizeof(int64_t); 231e307eb94SToomas Soome rv = true; 232e307eb94SToomas Soome break; 233e307eb94SToomas Soome 234e307eb94SToomas Soome case XDR_OP_DECODE: 235e307eb94SToomas Soome /* Decode buf, return value to *ip */ 2369de6a13eSToomas Soome if (xdr->xdr_getint == _getint) 2379de6a13eSToomas Soome *lp = be64toh(*(int64_t *)xdr->xdr_idx); 2389de6a13eSToomas Soome else 2399de6a13eSToomas Soome *lp = *(int64_t *)xdr->xdr_idx; 2409de6a13eSToomas Soome xdr->xdr_idx += sizeof(int64_t); 241e307eb94SToomas Soome rv = true; 242e307eb94SToomas Soome } 243e307eb94SToomas Soome return (rv); 244e307eb94SToomas Soome } 245e307eb94SToomas Soome 246e307eb94SToomas Soome static bool 247e307eb94SToomas Soome xdr_uint64(xdr_t *xdr, uint64_t *lp) 248e307eb94SToomas Soome { 249e307eb94SToomas Soome bool rv = false; 250e307eb94SToomas Soome 251e307eb94SToomas Soome if (xdr->xdr_idx + sizeof(uint64_t) > xdr->xdr_buf + xdr->xdr_buf_size) 252e307eb94SToomas Soome return (rv); 253e307eb94SToomas Soome 254e307eb94SToomas Soome switch (xdr->xdr_op) { 255e307eb94SToomas Soome case XDR_OP_ENCODE: 256e307eb94SToomas Soome /* Encode value *ip, store to buf */ 2579de6a13eSToomas Soome if (xdr->xdr_putint == _putint) 2589de6a13eSToomas Soome *(uint64_t *)xdr->xdr_idx = htobe64(*lp); 2599de6a13eSToomas Soome else 2609de6a13eSToomas Soome *(uint64_t *)xdr->xdr_idx = *lp; 2619de6a13eSToomas Soome xdr->xdr_idx += sizeof(uint64_t); 262e307eb94SToomas Soome rv = true; 263e307eb94SToomas Soome break; 264e307eb94SToomas Soome 265e307eb94SToomas Soome case XDR_OP_DECODE: 266e307eb94SToomas Soome /* Decode buf, return value to *ip */ 2679de6a13eSToomas Soome if (xdr->xdr_getuint == _getuint) 2689de6a13eSToomas Soome *lp = be64toh(*(uint64_t *)xdr->xdr_idx); 2699de6a13eSToomas Soome else 2709de6a13eSToomas Soome *lp = *(uint64_t *)xdr->xdr_idx; 2719de6a13eSToomas Soome xdr->xdr_idx += sizeof(uint64_t); 272e307eb94SToomas Soome rv = true; 273e307eb94SToomas Soome } 274e307eb94SToomas Soome return (rv); 275e307eb94SToomas Soome } 276e307eb94SToomas Soome 277e307eb94SToomas Soome static bool 278e307eb94SToomas Soome xdr_char(xdr_t *xdr, char *cp) 279e307eb94SToomas Soome { 280e307eb94SToomas Soome int i; 281e307eb94SToomas Soome bool rv = false; 282e307eb94SToomas Soome 283e307eb94SToomas Soome i = *cp; 284e307eb94SToomas Soome if ((rv = xdr_int(xdr, &i))) { 285e307eb94SToomas Soome if (xdr->xdr_op == XDR_OP_DECODE) 286e307eb94SToomas Soome *cp = i; 287e307eb94SToomas Soome } 288e307eb94SToomas Soome return (rv); 289e307eb94SToomas Soome } 290e307eb94SToomas Soome 291e307eb94SToomas Soome static bool 292e307eb94SToomas Soome xdr_string(xdr_t *xdr, nv_string_t *s) 293e307eb94SToomas Soome { 294e307eb94SToomas Soome int size = 0; 295e307eb94SToomas Soome bool rv = false; 296e307eb94SToomas Soome 297e307eb94SToomas Soome switch (xdr->xdr_op) { 298e307eb94SToomas Soome case XDR_OP_ENCODE: 299e307eb94SToomas Soome size = s->nv_size; 300e307eb94SToomas Soome if (xdr->xdr_idx + sizeof(unsigned) + NV_ALIGN4(size) > 301e307eb94SToomas Soome xdr->xdr_buf + xdr->xdr_buf_size) 302e307eb94SToomas Soome break; 303e307eb94SToomas Soome xdr->xdr_idx += xdr->xdr_putuint(xdr, s->nv_size); 304e307eb94SToomas Soome xdr->xdr_idx += NV_ALIGN4(size); 305e307eb94SToomas Soome rv = true; 306e307eb94SToomas Soome break; 307e307eb94SToomas Soome 308e307eb94SToomas Soome case XDR_OP_DECODE: 309e307eb94SToomas Soome if (xdr->xdr_idx + sizeof(unsigned) > 310e307eb94SToomas Soome xdr->xdr_buf + xdr->xdr_buf_size) 311e307eb94SToomas Soome break; 312e307eb94SToomas Soome size = xdr->xdr_getuint(xdr, &s->nv_size); 313e307eb94SToomas Soome size = NV_ALIGN4(size + s->nv_size); 314e307eb94SToomas Soome if (xdr->xdr_idx + size > xdr->xdr_buf + xdr->xdr_buf_size) 315e307eb94SToomas Soome break; 316e307eb94SToomas Soome xdr->xdr_idx += size; 317e307eb94SToomas Soome rv = true; 318e307eb94SToomas Soome break; 319e307eb94SToomas Soome } 320e307eb94SToomas Soome return (rv); 321e307eb94SToomas Soome } 322e307eb94SToomas Soome 323e307eb94SToomas Soome static bool 324e307eb94SToomas Soome xdr_array(xdr_t *xdr, const unsigned nelem, const xdrproc_t elproc) 325e307eb94SToomas Soome { 326e307eb94SToomas Soome bool rv = true; 3279de6a13eSToomas Soome unsigned c = nelem; 3289de6a13eSToomas Soome 3299de6a13eSToomas Soome if (!xdr_u_int(xdr, &c)) 3309de6a13eSToomas Soome return (false); 331e307eb94SToomas Soome 332e307eb94SToomas Soome for (unsigned i = 0; i < nelem; i++) { 333e307eb94SToomas Soome if (!elproc(xdr, xdr->xdr_idx)) 334e307eb94SToomas Soome return (false); 335e307eb94SToomas Soome } 336e307eb94SToomas Soome return (rv); 337e307eb94SToomas Soome } 338e307eb94SToomas Soome 339e307eb94SToomas Soome /* 340e307eb94SToomas Soome * nvlist management functions. 341e307eb94SToomas Soome */ 3423830659eSToomas Soome void 3433830659eSToomas Soome nvlist_destroy(nvlist_t *nvl) 3443830659eSToomas Soome { 3453830659eSToomas Soome if (nvl != NULL) { 3463830659eSToomas Soome /* Free data if it was allocated by us. */ 3473830659eSToomas Soome if (nvl->nv_asize > 0) 3483830659eSToomas Soome free(nvl->nv_data); 3493830659eSToomas Soome } 3503830659eSToomas Soome free(nvl); 3513830659eSToomas Soome } 3523830659eSToomas Soome 3533830659eSToomas Soome char * 3543830659eSToomas Soome nvstring_get(nv_string_t *nvs) 3553830659eSToomas Soome { 3563830659eSToomas Soome char *s; 3573830659eSToomas Soome 3583830659eSToomas Soome s = malloc(nvs->nv_size + 1); 3593830659eSToomas Soome if (s != NULL) { 3603830659eSToomas Soome bcopy(nvs->nv_data, s, nvs->nv_size); 3613830659eSToomas Soome s[nvs->nv_size] = '\0'; 3623830659eSToomas Soome } 3633830659eSToomas Soome return (s); 3643830659eSToomas Soome } 3653830659eSToomas Soome 3663830659eSToomas Soome /* 3673830659eSToomas Soome * Create empty nvlist. 3683830659eSToomas Soome * The nvlist is terminated by 2x zeros (8 bytes). 3693830659eSToomas Soome */ 3703830659eSToomas Soome nvlist_t * 3713830659eSToomas Soome nvlist_create(int flag) 3723830659eSToomas Soome { 3733830659eSToomas Soome nvlist_t *nvl; 3743830659eSToomas Soome nvs_data_t *nvs; 3753830659eSToomas Soome 3763830659eSToomas Soome nvl = calloc(1, sizeof(*nvl)); 3773830659eSToomas Soome if (nvl == NULL) 3783830659eSToomas Soome return (nvl); 3793830659eSToomas Soome 3803830659eSToomas Soome nvl->nv_header.nvh_encoding = NV_ENCODE_XDR; 3813830659eSToomas Soome nvl->nv_header.nvh_endian = _BYTE_ORDER == _LITTLE_ENDIAN; 3823830659eSToomas Soome 3833830659eSToomas Soome nvl->nv_asize = nvl->nv_size = sizeof(*nvs); 3843830659eSToomas Soome nvs = calloc(1, nvl->nv_asize); 3853830659eSToomas Soome if (nvs == NULL) { 3863830659eSToomas Soome free(nvl); 3873830659eSToomas Soome return (NULL); 3883830659eSToomas Soome } 3893830659eSToomas Soome /* data in nvlist is byte stream */ 3903830659eSToomas Soome nvl->nv_data = (uint8_t *)nvs; 3913830659eSToomas Soome 3923830659eSToomas Soome nvs->nvl_version = NV_VERSION; 3933830659eSToomas Soome nvs->nvl_nvflag = flag; 3943830659eSToomas Soome return (nvl); 3953830659eSToomas Soome } 3963830659eSToomas Soome 397e307eb94SToomas Soome static bool 398e307eb94SToomas Soome nvlist_xdr_nvp(xdr_t *xdr, nvlist_t *nvl) 3993830659eSToomas Soome { 4003830659eSToomas Soome nv_string_t *nv_string; 4013830659eSToomas Soome nv_pair_data_t *nvp_data; 4023830659eSToomas Soome nvlist_t nvlist; 403e307eb94SToomas Soome unsigned type, nelem; 404e307eb94SToomas Soome xdr_t nv_xdr; 4053830659eSToomas Soome 406e307eb94SToomas Soome nv_string = (nv_string_t *)xdr->xdr_idx; 407e307eb94SToomas Soome if (!xdr_string(xdr, nv_string)) { 408e307eb94SToomas Soome return (false); 409e307eb94SToomas Soome } 410e307eb94SToomas Soome nvp_data = (nv_pair_data_t *)xdr->xdr_idx; 4113830659eSToomas Soome 412e307eb94SToomas Soome type = nvp_data->nv_type; 413e307eb94SToomas Soome nelem = nvp_data->nv_nelem; 414e307eb94SToomas Soome if (!xdr_u_int(xdr, &type) || !xdr_u_int(xdr, &nelem)) 415e307eb94SToomas Soome return (false); 4163830659eSToomas Soome 417e307eb94SToomas Soome switch (type) { 4183830659eSToomas Soome case DATA_TYPE_NVLIST: 4193830659eSToomas Soome case DATA_TYPE_NVLIST_ARRAY: 4203830659eSToomas Soome bzero(&nvlist, sizeof(nvlist)); 421e307eb94SToomas Soome nvlist.nv_data = xdr->xdr_idx; 4223830659eSToomas Soome nvlist.nv_idx = nvlist.nv_data; 423e307eb94SToomas Soome 424e307eb94SToomas Soome /* Set up xdr for this nvlist. */ 425e307eb94SToomas Soome nv_xdr = *xdr; 426e307eb94SToomas Soome nv_xdr.xdr_buf = nvlist.nv_data; 427e307eb94SToomas Soome nv_xdr.xdr_idx = nvlist.nv_data; 428e307eb94SToomas Soome nv_xdr.xdr_buf_size = 429e307eb94SToomas Soome nvl->nv_data + nvl->nv_size - nvlist.nv_data; 430e307eb94SToomas Soome 431e307eb94SToomas Soome for (unsigned i = 0; i < nelem; i++) { 432e307eb94SToomas Soome if (xdr->xdr_op == XDR_OP_ENCODE) { 433e307eb94SToomas Soome if (!nvlist_size_native(&nv_xdr, 434e307eb94SToomas Soome &nvlist.nv_size)) 435e307eb94SToomas Soome return (false); 436e307eb94SToomas Soome } else { 437e307eb94SToomas Soome if (!nvlist_size_xdr(&nv_xdr, 438e307eb94SToomas Soome &nvlist.nv_size)) 439e307eb94SToomas Soome return (false); 440e307eb94SToomas Soome } 441e307eb94SToomas Soome if (nvlist_xdr_nvlist(xdr, &nvlist) != 0) 442e307eb94SToomas Soome return (false); 443e307eb94SToomas Soome 444e307eb94SToomas Soome nvlist.nv_data = nv_xdr.xdr_idx; 445e307eb94SToomas Soome nvlist.nv_idx = nv_xdr.xdr_idx; 446e307eb94SToomas Soome 447e307eb94SToomas Soome nv_xdr.xdr_buf = nv_xdr.xdr_idx; 448e307eb94SToomas Soome nv_xdr.xdr_buf_size = 449e307eb94SToomas Soome nvl->nv_data + nvl->nv_size - nvlist.nv_data; 4503830659eSToomas Soome } 4513830659eSToomas Soome break; 4523830659eSToomas Soome 4533830659eSToomas Soome case DATA_TYPE_BOOLEAN: 4543830659eSToomas Soome /* BOOLEAN does not take value space */ 4553830659eSToomas Soome break; 4563830659eSToomas Soome case DATA_TYPE_BYTE: 4573830659eSToomas Soome case DATA_TYPE_INT8: 4583830659eSToomas Soome case DATA_TYPE_UINT8: 459e307eb94SToomas Soome if (!xdr_char(xdr, (char *)&nvp_data->nv_data[0])) 460e307eb94SToomas Soome return (false); 4613830659eSToomas Soome break; 4623830659eSToomas Soome 4633830659eSToomas Soome case DATA_TYPE_INT16: 464e307eb94SToomas Soome if (!xdr_short(xdr, (short *)&nvp_data->nv_data[0])) 465e307eb94SToomas Soome return (false); 4663830659eSToomas Soome break; 4673830659eSToomas Soome 4683830659eSToomas Soome case DATA_TYPE_UINT16: 469e307eb94SToomas Soome if (!xdr_u_short(xdr, (unsigned short *)&nvp_data->nv_data[0])) 470e307eb94SToomas Soome return (false); 4713830659eSToomas Soome break; 4723830659eSToomas Soome 4733830659eSToomas Soome case DATA_TYPE_BOOLEAN_VALUE: 4743830659eSToomas Soome case DATA_TYPE_INT32: 475e307eb94SToomas Soome if (!xdr_int(xdr, (int *)&nvp_data->nv_data[0])) 476e307eb94SToomas Soome return (false); 4773830659eSToomas Soome break; 4783830659eSToomas Soome 4793830659eSToomas Soome case DATA_TYPE_UINT32: 480e307eb94SToomas Soome if (!xdr_u_int(xdr, (unsigned *)&nvp_data->nv_data[0])) 481e307eb94SToomas Soome return (false); 4823830659eSToomas Soome break; 4833830659eSToomas Soome 484e307eb94SToomas Soome case DATA_TYPE_HRTIME: 4853830659eSToomas Soome case DATA_TYPE_INT64: 486e307eb94SToomas Soome if (!xdr_int64(xdr, (int64_t *)&nvp_data->nv_data[0])) 487e307eb94SToomas Soome return (false); 4883830659eSToomas Soome break; 4893830659eSToomas Soome 4903830659eSToomas Soome case DATA_TYPE_UINT64: 491e307eb94SToomas Soome if (!xdr_uint64(xdr, (uint64_t *)&nvp_data->nv_data[0])) 492e307eb94SToomas Soome return (false); 4933830659eSToomas Soome break; 4943830659eSToomas Soome 495e307eb94SToomas Soome case DATA_TYPE_BYTE_ARRAY: 4963830659eSToomas Soome case DATA_TYPE_STRING: 4973830659eSToomas Soome nv_string = (nv_string_t *)&nvp_data->nv_data[0]; 498e307eb94SToomas Soome if (!xdr_string(xdr, nv_string)) 499e307eb94SToomas Soome return (false); 500e307eb94SToomas Soome break; 5013830659eSToomas Soome 502e307eb94SToomas Soome case DATA_TYPE_STRING_ARRAY: 503e307eb94SToomas Soome nv_string = (nv_string_t *)&nvp_data->nv_data[0]; 504e307eb94SToomas Soome for (unsigned i = 0; i < nelem; i++) { 505e307eb94SToomas Soome if (!xdr_string(xdr, nv_string)) 506e307eb94SToomas Soome return (false); 507e307eb94SToomas Soome nv_string = (nv_string_t *)xdr->xdr_idx; 508e307eb94SToomas Soome } 509e307eb94SToomas Soome break; 510e307eb94SToomas Soome 511e307eb94SToomas Soome case DATA_TYPE_INT8_ARRAY: 512e307eb94SToomas Soome case DATA_TYPE_UINT8_ARRAY: 513e307eb94SToomas Soome case DATA_TYPE_INT16_ARRAY: 514e307eb94SToomas Soome case DATA_TYPE_UINT16_ARRAY: 515e307eb94SToomas Soome case DATA_TYPE_BOOLEAN_ARRAY: 516e307eb94SToomas Soome case DATA_TYPE_INT32_ARRAY: 517e307eb94SToomas Soome case DATA_TYPE_UINT32_ARRAY: 518e307eb94SToomas Soome if (!xdr_array(xdr, nelem, (xdrproc_t)xdr_u_int)) 519e307eb94SToomas Soome return (false); 520e307eb94SToomas Soome break; 521e307eb94SToomas Soome 522e307eb94SToomas Soome case DATA_TYPE_INT64_ARRAY: 523e307eb94SToomas Soome case DATA_TYPE_UINT64_ARRAY: 524e307eb94SToomas Soome if (!xdr_array(xdr, nelem, (xdrproc_t)xdr_uint64)) 525e307eb94SToomas Soome return (false); 5263830659eSToomas Soome break; 5273830659eSToomas Soome } 528e307eb94SToomas Soome return (true); 5293830659eSToomas Soome } 5303830659eSToomas Soome 5313830659eSToomas Soome static int 532e307eb94SToomas Soome nvlist_xdr_nvlist(xdr_t *xdr, nvlist_t *nvl) 5333830659eSToomas Soome { 534e307eb94SToomas Soome nvp_header_t *nvph; 535e307eb94SToomas Soome nvs_data_t *nvs; 536e307eb94SToomas Soome unsigned encoded_size, decoded_size; 537e307eb94SToomas Soome int rv; 538e307eb94SToomas Soome 539e307eb94SToomas Soome nvs = (nvs_data_t *)xdr->xdr_idx; 540e307eb94SToomas Soome nvph = &nvs->nvl_pair; 541e307eb94SToomas Soome 542e307eb94SToomas Soome if (!xdr_u_int(xdr, &nvs->nvl_version)) 543e307eb94SToomas Soome return (EINVAL); 544e307eb94SToomas Soome if (!xdr_u_int(xdr, &nvs->nvl_nvflag)) 545e307eb94SToomas Soome return (EINVAL); 546e307eb94SToomas Soome 547e307eb94SToomas Soome encoded_size = nvph->encoded_size; 548e307eb94SToomas Soome decoded_size = nvph->decoded_size; 549e307eb94SToomas Soome 550e307eb94SToomas Soome if (xdr->xdr_op == XDR_OP_ENCODE) { 551e307eb94SToomas Soome if (!xdr_u_int(xdr, &nvph->encoded_size)) 552e307eb94SToomas Soome return (EINVAL); 553e307eb94SToomas Soome if (!xdr_u_int(xdr, &nvph->decoded_size)) 554e307eb94SToomas Soome return (EINVAL); 555e307eb94SToomas Soome } else { 556e307eb94SToomas Soome xdr->xdr_idx += 2 * sizeof(unsigned); 557e307eb94SToomas Soome } 558e307eb94SToomas Soome 559e307eb94SToomas Soome rv = 0; 560e307eb94SToomas Soome while (encoded_size && decoded_size) { 561e307eb94SToomas Soome if (!nvlist_xdr_nvp(xdr, nvl)) 562e307eb94SToomas Soome return (EINVAL); 563e307eb94SToomas Soome 564e307eb94SToomas Soome nvph = (nvp_header_t *)(xdr->xdr_idx); 565e307eb94SToomas Soome encoded_size = nvph->encoded_size; 566e307eb94SToomas Soome decoded_size = nvph->decoded_size; 567e307eb94SToomas Soome if (xdr->xdr_op == XDR_OP_ENCODE) { 568e307eb94SToomas Soome if (!xdr_u_int(xdr, &nvph->encoded_size)) 569e307eb94SToomas Soome return (EINVAL); 570e307eb94SToomas Soome if (!xdr_u_int(xdr, &nvph->decoded_size)) 571e307eb94SToomas Soome return (EINVAL); 572e307eb94SToomas Soome } else { 573e307eb94SToomas Soome xdr->xdr_idx += 2 * sizeof(unsigned); 574e307eb94SToomas Soome } 575e307eb94SToomas Soome } 576e307eb94SToomas Soome return (rv); 577e307eb94SToomas Soome } 578e307eb94SToomas Soome 579e307eb94SToomas Soome /* 580e307eb94SToomas Soome * Calculate nvlist size, translating encoded_size and decoded_size. 581e307eb94SToomas Soome */ 582e307eb94SToomas Soome static bool 583e307eb94SToomas Soome nvlist_size_xdr(xdr_t *xdr, size_t *size) 584e307eb94SToomas Soome { 585e307eb94SToomas Soome uint8_t *pair; 5863830659eSToomas Soome unsigned encoded_size, decoded_size; 5873830659eSToomas Soome 588e307eb94SToomas Soome xdr->xdr_idx += 2 * sizeof(unsigned); 5893830659eSToomas Soome 590e307eb94SToomas Soome pair = xdr->xdr_idx; 591e307eb94SToomas Soome if (!xdr_u_int(xdr, &encoded_size) || !xdr_u_int(xdr, &decoded_size)) 592e307eb94SToomas Soome return (false); 593e307eb94SToomas Soome 5943830659eSToomas Soome while (encoded_size && decoded_size) { 595e307eb94SToomas Soome xdr->xdr_idx = pair + encoded_size; 596e307eb94SToomas Soome pair = xdr->xdr_idx; 597e307eb94SToomas Soome if (!xdr_u_int(xdr, &encoded_size) || 598e307eb94SToomas Soome !xdr_u_int(xdr, &decoded_size)) 599e307eb94SToomas Soome return (false); 6003830659eSToomas Soome } 601e307eb94SToomas Soome *size = xdr->xdr_idx - xdr->xdr_buf; 602e307eb94SToomas Soome 603e307eb94SToomas Soome return (true); 604e307eb94SToomas Soome } 605e307eb94SToomas Soome 606e307eb94SToomas Soome nvp_header_t * 607e307eb94SToomas Soome nvlist_next_nvpair(nvlist_t *nvl, nvp_header_t *nvh) 608e307eb94SToomas Soome { 609e307eb94SToomas Soome uint8_t *pair; 610e307eb94SToomas Soome unsigned encoded_size, decoded_size; 611e307eb94SToomas Soome xdr_t xdr; 612e307eb94SToomas Soome 613e307eb94SToomas Soome if (nvl == NULL) 614e307eb94SToomas Soome return (NULL); 615e307eb94SToomas Soome 616e307eb94SToomas Soome xdr.xdr_buf = nvl->nv_data; 617e307eb94SToomas Soome xdr.xdr_idx = nvl->nv_data; 618e307eb94SToomas Soome xdr.xdr_buf_size = nvl->nv_size; 619e307eb94SToomas Soome 620e307eb94SToomas Soome xdr.xdr_idx += 2 * sizeof(unsigned); 621e307eb94SToomas Soome 622e307eb94SToomas Soome /* Skip tp current pair */ 623e307eb94SToomas Soome if (nvh != NULL) { 624e307eb94SToomas Soome xdr.xdr_idx = (uint8_t *)nvh; 625e307eb94SToomas Soome } 626e307eb94SToomas Soome 627e307eb94SToomas Soome pair = xdr.xdr_idx; 628e307eb94SToomas Soome if (xdr.xdr_idx > xdr.xdr_buf + xdr.xdr_buf_size) 629e307eb94SToomas Soome return (NULL); 630e307eb94SToomas Soome 631e307eb94SToomas Soome encoded_size = *(unsigned *)xdr.xdr_idx; 632e307eb94SToomas Soome xdr.xdr_idx += sizeof(unsigned); 633e307eb94SToomas Soome if (xdr.xdr_idx > xdr.xdr_buf + xdr.xdr_buf_size) 634e307eb94SToomas Soome return (NULL); 635e307eb94SToomas Soome 636e307eb94SToomas Soome decoded_size = *(unsigned *)xdr.xdr_idx; 637e307eb94SToomas Soome xdr.xdr_idx += sizeof(unsigned); 638e307eb94SToomas Soome if (xdr.xdr_idx > xdr.xdr_buf + xdr.xdr_buf_size) 639e307eb94SToomas Soome return (NULL); 640e307eb94SToomas Soome 641e307eb94SToomas Soome while (encoded_size && decoded_size) { 642e307eb94SToomas Soome if (nvh == NULL) 643e307eb94SToomas Soome return ((nvp_header_t *)pair); 644e307eb94SToomas Soome 645e307eb94SToomas Soome xdr.xdr_idx = pair + encoded_size; 646e307eb94SToomas Soome nvh = (nvp_header_t *)xdr.xdr_idx; 647e307eb94SToomas Soome 648e307eb94SToomas Soome if (xdr.xdr_idx > xdr.xdr_buf + xdr.xdr_buf_size) 649e307eb94SToomas Soome return (NULL); 650e307eb94SToomas Soome 651e307eb94SToomas Soome encoded_size = *(unsigned *)xdr.xdr_idx; 652e307eb94SToomas Soome xdr.xdr_idx += sizeof(unsigned); 653e307eb94SToomas Soome if (xdr.xdr_idx > xdr.xdr_buf + xdr.xdr_buf_size) 654e307eb94SToomas Soome return (NULL); 655e307eb94SToomas Soome decoded_size = *(unsigned *)xdr.xdr_idx; 656e307eb94SToomas Soome xdr.xdr_idx += sizeof(unsigned); 657e307eb94SToomas Soome if (xdr.xdr_idx > xdr.xdr_buf + xdr.xdr_buf_size) 658e307eb94SToomas Soome return (NULL); 659e307eb94SToomas Soome 660e307eb94SToomas Soome if (encoded_size != 0 && decoded_size != 0) { 661e307eb94SToomas Soome return (nvh); 662e307eb94SToomas Soome } 663e307eb94SToomas Soome } 664e307eb94SToomas Soome return (NULL); 665e307eb94SToomas Soome } 666e307eb94SToomas Soome 667e307eb94SToomas Soome /* 668e307eb94SToomas Soome * Calculate nvlist size by walking in memory data. 669e307eb94SToomas Soome */ 670e307eb94SToomas Soome static bool 671e307eb94SToomas Soome nvlist_size_native(xdr_t *xdr, size_t *size) 672e307eb94SToomas Soome { 673e307eb94SToomas Soome uint8_t *pair; 674e307eb94SToomas Soome unsigned encoded_size, decoded_size; 675e307eb94SToomas Soome 676e307eb94SToomas Soome xdr->xdr_idx += 2 * sizeof(unsigned); 677e307eb94SToomas Soome 678e307eb94SToomas Soome pair = xdr->xdr_idx; 679e307eb94SToomas Soome if (xdr->xdr_idx > xdr->xdr_buf + xdr->xdr_buf_size) 680e307eb94SToomas Soome return (false); 681e307eb94SToomas Soome 682e307eb94SToomas Soome encoded_size = *(unsigned *)xdr->xdr_idx; 683e307eb94SToomas Soome xdr->xdr_idx += sizeof(unsigned); 684e307eb94SToomas Soome if (xdr->xdr_idx > xdr->xdr_buf + xdr->xdr_buf_size) 685e307eb94SToomas Soome return (false); 686e307eb94SToomas Soome decoded_size = *(unsigned *)xdr->xdr_idx; 687e307eb94SToomas Soome xdr->xdr_idx += sizeof(unsigned); 688e307eb94SToomas Soome while (encoded_size && decoded_size) { 689e307eb94SToomas Soome xdr->xdr_idx = pair + encoded_size; 690e307eb94SToomas Soome pair = xdr->xdr_idx; 691e307eb94SToomas Soome if (xdr->xdr_idx > xdr->xdr_buf + xdr->xdr_buf_size) 692e307eb94SToomas Soome return (false); 693e307eb94SToomas Soome encoded_size = *(unsigned *)xdr->xdr_idx; 694e307eb94SToomas Soome xdr->xdr_idx += sizeof(unsigned); 695e307eb94SToomas Soome if (xdr->xdr_idx > xdr->xdr_buf + xdr->xdr_buf_size) 696e307eb94SToomas Soome return (false); 697e307eb94SToomas Soome decoded_size = *(unsigned *)xdr->xdr_idx; 698e307eb94SToomas Soome xdr->xdr_idx += sizeof(unsigned); 699e307eb94SToomas Soome } 700e307eb94SToomas Soome *size = xdr->xdr_idx - xdr->xdr_buf; 701e307eb94SToomas Soome 702e307eb94SToomas Soome return (true); 703e307eb94SToomas Soome } 704e307eb94SToomas Soome 705e307eb94SToomas Soome /* 706e307eb94SToomas Soome * Export nvlist to byte stream format. 707e307eb94SToomas Soome */ 708e307eb94SToomas Soome int 709e307eb94SToomas Soome nvlist_export(nvlist_t *nvl) 710e307eb94SToomas Soome { 711e307eb94SToomas Soome int rv; 712e307eb94SToomas Soome xdr_t xdr = { 713e307eb94SToomas Soome .xdr_op = XDR_OP_ENCODE, 714e307eb94SToomas Soome .xdr_putint = _putint, 715e307eb94SToomas Soome .xdr_putuint = _putuint, 716e307eb94SToomas Soome .xdr_buf = nvl->nv_data, 717e307eb94SToomas Soome .xdr_idx = nvl->nv_data, 718e307eb94SToomas Soome .xdr_buf_size = nvl->nv_size 719e307eb94SToomas Soome }; 720e307eb94SToomas Soome 721e307eb94SToomas Soome if (nvl->nv_header.nvh_encoding != NV_ENCODE_XDR) 722e307eb94SToomas Soome return (ENOTSUP); 723e307eb94SToomas Soome 724e307eb94SToomas Soome nvl->nv_idx = nvl->nv_data; 725e307eb94SToomas Soome rv = nvlist_xdr_nvlist(&xdr, nvl); 726e307eb94SToomas Soome 727e307eb94SToomas Soome return (rv); 7283830659eSToomas Soome } 7293830659eSToomas Soome 7303830659eSToomas Soome /* 7313830659eSToomas Soome * Import nvlist from byte stream. 7323830659eSToomas Soome * Determine the stream size and allocate private copy. 7333830659eSToomas Soome * Then translate the data. 7343830659eSToomas Soome */ 7353830659eSToomas Soome nvlist_t * 736e307eb94SToomas Soome nvlist_import(const char *stream, size_t size) 7373830659eSToomas Soome { 7383830659eSToomas Soome nvlist_t *nvl; 739e307eb94SToomas Soome xdr_t xdr = { 740e307eb94SToomas Soome .xdr_op = XDR_OP_DECODE, 741e307eb94SToomas Soome .xdr_getint = _getint, 742e307eb94SToomas Soome .xdr_getuint = _getuint 743e307eb94SToomas Soome }; 7443830659eSToomas Soome 745e307eb94SToomas Soome /* Check the nvlist head. */ 746e307eb94SToomas Soome if (stream[0] != NV_ENCODE_XDR || 747e307eb94SToomas Soome (stream[1] != '\0' && stream[1] != '\1') || 748e307eb94SToomas Soome stream[2] != '\0' || stream[3] != '\0' || 749e307eb94SToomas Soome be32toh(*(uint32_t *)(stream + 4)) != NV_VERSION || 750e307eb94SToomas Soome be32toh(*(uint32_t *)(stream + 8)) != NV_UNIQUE_NAME) 7513830659eSToomas Soome return (NULL); 7523830659eSToomas Soome 7533830659eSToomas Soome nvl = malloc(sizeof(*nvl)); 7543830659eSToomas Soome if (nvl == NULL) 7553830659eSToomas Soome return (nvl); 7563830659eSToomas Soome 757e307eb94SToomas Soome nvl->nv_header.nvh_encoding = stream[0]; 758e307eb94SToomas Soome nvl->nv_header.nvh_endian = stream[1]; 759e307eb94SToomas Soome nvl->nv_header.nvh_reserved1 = stream[2]; 760e307eb94SToomas Soome nvl->nv_header.nvh_reserved2 = stream[3]; 761e307eb94SToomas Soome 762e307eb94SToomas Soome xdr.xdr_buf = xdr.xdr_idx = (uint8_t *)stream + 4; 763e307eb94SToomas Soome xdr.xdr_buf_size = size - 4; 764e307eb94SToomas Soome 765e307eb94SToomas Soome if (!nvlist_size_xdr(&xdr, &nvl->nv_asize)) { 766e307eb94SToomas Soome free(nvl); 767e307eb94SToomas Soome return (NULL); 768e307eb94SToomas Soome } 769e307eb94SToomas Soome nvl->nv_size = nvl->nv_asize; 7703830659eSToomas Soome nvl->nv_data = malloc(nvl->nv_asize); 7713830659eSToomas Soome if (nvl->nv_data == NULL) { 7723830659eSToomas Soome free(nvl); 7733830659eSToomas Soome return (NULL); 7743830659eSToomas Soome } 7753830659eSToomas Soome nvl->nv_idx = nvl->nv_data; 776e307eb94SToomas Soome bcopy(stream + 4, nvl->nv_data, nvl->nv_asize); 7773830659eSToomas Soome 778e307eb94SToomas Soome xdr.xdr_buf = xdr.xdr_idx = nvl->nv_data; 779e307eb94SToomas Soome xdr.xdr_buf_size = nvl->nv_asize; 780e307eb94SToomas Soome 781e307eb94SToomas Soome if (nvlist_xdr_nvlist(&xdr, nvl) != 0) { 782e307eb94SToomas Soome free(nvl->nv_data); 783e307eb94SToomas Soome free(nvl); 784e307eb94SToomas Soome nvl = NULL; 785e307eb94SToomas Soome } 786e307eb94SToomas Soome 7873830659eSToomas Soome return (nvl); 7883830659eSToomas Soome } 7893830659eSToomas Soome 7903830659eSToomas Soome /* 7913830659eSToomas Soome * remove pair from this nvlist. 7923830659eSToomas Soome */ 7933830659eSToomas Soome int 7943830659eSToomas Soome nvlist_remove(nvlist_t *nvl, const char *name, data_type_t type) 7953830659eSToomas Soome { 7963830659eSToomas Soome uint8_t *head, *tail; 7973830659eSToomas Soome nvs_data_t *data; 7983830659eSToomas Soome nvp_header_t *nvp; 7993830659eSToomas Soome nv_string_t *nvp_name; 8003830659eSToomas Soome nv_pair_data_t *nvp_data; 8013830659eSToomas Soome size_t size; 802e307eb94SToomas Soome xdr_t xdr; 8033830659eSToomas Soome 8043830659eSToomas Soome if (nvl == NULL || nvl->nv_data == NULL || name == NULL) 8053830659eSToomas Soome return (EINVAL); 8063830659eSToomas Soome 807e307eb94SToomas Soome /* Make sure the nvlist size is set correct */ 808e307eb94SToomas Soome xdr.xdr_idx = nvl->nv_data; 809e307eb94SToomas Soome xdr.xdr_buf = xdr.xdr_idx; 810e307eb94SToomas Soome xdr.xdr_buf_size = nvl->nv_size; 811e307eb94SToomas Soome if (!nvlist_size_native(&xdr, &nvl->nv_size)) 812e307eb94SToomas Soome return (EINVAL); 813e307eb94SToomas Soome 814e307eb94SToomas Soome data = (nvs_data_t *)nvl->nv_data; 8153830659eSToomas Soome nvp = &data->nvl_pair; /* first pair in nvlist */ 8163830659eSToomas Soome head = (uint8_t *)nvp; 8173830659eSToomas Soome 8183830659eSToomas Soome while (nvp->encoded_size != 0 && nvp->decoded_size != 0) { 819e307eb94SToomas Soome nvp_name = (nv_string_t *)(nvp + 1); 8203830659eSToomas Soome 821e307eb94SToomas Soome nvp_data = (nv_pair_data_t *)(&nvp_name->nv_data[0] + 822e307eb94SToomas Soome NV_ALIGN4(nvp_name->nv_size)); 8233830659eSToomas Soome 824e307eb94SToomas Soome if (strlen(name) == nvp_name->nv_size && 825e307eb94SToomas Soome memcmp(nvp_name->nv_data, name, nvp_name->nv_size) == 0 && 826e307eb94SToomas Soome (nvp_data->nv_type == type || type == DATA_TYPE_UNKNOWN)) { 8273830659eSToomas Soome /* 8283830659eSToomas Soome * set tail to point to next nvpair and size 8293830659eSToomas Soome * is the length of the tail. 8303830659eSToomas Soome */ 8313830659eSToomas Soome tail = head + nvp->encoded_size; 832e307eb94SToomas Soome size = nvl->nv_size - (tail - nvl->nv_data); 8333830659eSToomas Soome 8343830659eSToomas Soome /* adjust the size of the nvlist. */ 8353830659eSToomas Soome nvl->nv_size -= nvp->encoded_size; 8363830659eSToomas Soome bcopy(tail, head, size); 8373830659eSToomas Soome return (0); 8383830659eSToomas Soome } 8393830659eSToomas Soome /* Not our pair, skip to next. */ 8403830659eSToomas Soome head = head + nvp->encoded_size; 8413830659eSToomas Soome nvp = (nvp_header_t *)head; 8423830659eSToomas Soome } 8433830659eSToomas Soome return (ENOENT); 8443830659eSToomas Soome } 8453830659eSToomas Soome 846e307eb94SToomas Soome static int 847e307eb94SToomas Soome clone_nvlist(const nvlist_t *nvl, const uint8_t *ptr, unsigned size, 848e307eb94SToomas Soome nvlist_t **nvlist) 849e307eb94SToomas Soome { 850e307eb94SToomas Soome nvlist_t *nv; 851e307eb94SToomas Soome 852e307eb94SToomas Soome nv = calloc(1, sizeof(*nv)); 853e307eb94SToomas Soome if (nv == NULL) 854e307eb94SToomas Soome return (ENOMEM); 855e307eb94SToomas Soome 856e307eb94SToomas Soome nv->nv_header = nvl->nv_header; 857e307eb94SToomas Soome nv->nv_asize = size; 858e307eb94SToomas Soome nv->nv_size = size; 859e307eb94SToomas Soome nv->nv_data = malloc(nv->nv_asize); 860e307eb94SToomas Soome if (nv->nv_data == NULL) { 861e307eb94SToomas Soome free(nv); 862e307eb94SToomas Soome return (ENOMEM); 863e307eb94SToomas Soome } 864e307eb94SToomas Soome 865e307eb94SToomas Soome bcopy(ptr, nv->nv_data, nv->nv_asize); 866e307eb94SToomas Soome *nvlist = nv; 867e307eb94SToomas Soome return (0); 868e307eb94SToomas Soome } 869e307eb94SToomas Soome 870e307eb94SToomas Soome /* 871e307eb94SToomas Soome * Return the next nvlist in an nvlist array. 872e307eb94SToomas Soome */ 873e307eb94SToomas Soome static uint8_t * 874e307eb94SToomas Soome nvlist_next(const uint8_t *ptr) 875e307eb94SToomas Soome { 876e307eb94SToomas Soome nvs_data_t *data; 877e307eb94SToomas Soome nvp_header_t *nvp; 878e307eb94SToomas Soome 879e307eb94SToomas Soome data = (nvs_data_t *)ptr; 880e307eb94SToomas Soome nvp = &data->nvl_pair; /* first pair in nvlist */ 881e307eb94SToomas Soome 882e307eb94SToomas Soome while (nvp->encoded_size != 0 && nvp->decoded_size != 0) { 883e307eb94SToomas Soome nvp = (nvp_header_t *)((uint8_t *)nvp + nvp->encoded_size); 884e307eb94SToomas Soome } 885e307eb94SToomas Soome return ((uint8_t *)nvp + sizeof(*nvp)); 886e307eb94SToomas Soome } 887e307eb94SToomas Soome 888e307eb94SToomas Soome /* 889e307eb94SToomas Soome * Note: nvlist and nvlist array must be freed by caller. 890e307eb94SToomas Soome */ 8913830659eSToomas Soome int 8923830659eSToomas Soome nvlist_find(const nvlist_t *nvl, const char *name, data_type_t type, 8933830659eSToomas Soome int *elementsp, void *valuep, int *sizep) 8943830659eSToomas Soome { 8953830659eSToomas Soome nvs_data_t *data; 8963830659eSToomas Soome nvp_header_t *nvp; 8973830659eSToomas Soome nv_string_t *nvp_name; 8983830659eSToomas Soome nv_pair_data_t *nvp_data; 899e307eb94SToomas Soome nvlist_t **nvlist, *nv; 900e307eb94SToomas Soome uint8_t *ptr; 901e307eb94SToomas Soome int rv; 9023830659eSToomas Soome 9033830659eSToomas Soome if (nvl == NULL || nvl->nv_data == NULL || name == NULL) 9043830659eSToomas Soome return (EINVAL); 9053830659eSToomas Soome 9063830659eSToomas Soome data = (nvs_data_t *)nvl->nv_data; 9073830659eSToomas Soome nvp = &data->nvl_pair; /* first pair in nvlist */ 9083830659eSToomas Soome 9093830659eSToomas Soome while (nvp->encoded_size != 0 && nvp->decoded_size != 0) { 9103830659eSToomas Soome nvp_name = (nv_string_t *)((uint8_t *)nvp + sizeof(*nvp)); 911e307eb94SToomas Soome if (nvl->nv_data + nvl->nv_size < 912e307eb94SToomas Soome nvp_name->nv_data + nvp_name->nv_size) 913e307eb94SToomas Soome return (EIO); 9143830659eSToomas Soome 9153830659eSToomas Soome nvp_data = (nv_pair_data_t *) 9163830659eSToomas Soome NV_ALIGN4((uintptr_t)&nvp_name->nv_data[0] + 9173830659eSToomas Soome nvp_name->nv_size); 9183830659eSToomas Soome 919e307eb94SToomas Soome if (strlen(name) == nvp_name->nv_size && 920e307eb94SToomas Soome memcmp(nvp_name->nv_data, name, nvp_name->nv_size) == 0 && 921e307eb94SToomas Soome (nvp_data->nv_type == type || type == DATA_TYPE_UNKNOWN)) { 9223830659eSToomas Soome if (elementsp != NULL) 9233830659eSToomas Soome *elementsp = nvp_data->nv_nelem; 9243830659eSToomas Soome switch (nvp_data->nv_type) { 9253830659eSToomas Soome case DATA_TYPE_UINT64: 926e307eb94SToomas Soome bcopy(nvp_data->nv_data, valuep, 927e307eb94SToomas Soome sizeof(uint64_t)); 9283830659eSToomas Soome return (0); 9293830659eSToomas Soome case DATA_TYPE_STRING: 9303830659eSToomas Soome nvp_name = (nv_string_t *)nvp_data->nv_data; 9313830659eSToomas Soome if (sizep != NULL) { 9323830659eSToomas Soome *sizep = nvp_name->nv_size; 9333830659eSToomas Soome } 9343830659eSToomas Soome *(const uint8_t **)valuep = 9353830659eSToomas Soome &nvp_name->nv_data[0]; 9363830659eSToomas Soome return (0); 9373830659eSToomas Soome case DATA_TYPE_NVLIST: 938e307eb94SToomas Soome ptr = &nvp_data->nv_data[0]; 939e307eb94SToomas Soome rv = clone_nvlist(nvl, ptr, 940e307eb94SToomas Soome nvlist_next(ptr) - ptr, &nv); 941e307eb94SToomas Soome if (rv == 0) { 942e307eb94SToomas Soome *(nvlist_t **)valuep = nv; 9433830659eSToomas Soome } 944e307eb94SToomas Soome return (rv); 945e307eb94SToomas Soome 946e307eb94SToomas Soome case DATA_TYPE_NVLIST_ARRAY: 947e307eb94SToomas Soome nvlist = calloc(nvp_data->nv_nelem, 948e307eb94SToomas Soome sizeof(nvlist_t *)); 949e307eb94SToomas Soome if (nvlist == NULL) 9503830659eSToomas Soome return (ENOMEM); 951e307eb94SToomas Soome ptr = &nvp_data->nv_data[0]; 952e307eb94SToomas Soome rv = 0; 953e307eb94SToomas Soome for (unsigned i = 0; i < nvp_data->nv_nelem; 954e307eb94SToomas Soome i++) { 955e307eb94SToomas Soome rv = clone_nvlist(nvl, ptr, 956e307eb94SToomas Soome nvlist_next(ptr) - ptr, &nvlist[i]); 957e307eb94SToomas Soome if (rv != 0) 958e307eb94SToomas Soome goto error; 959e307eb94SToomas Soome ptr = nvlist_next(ptr); 960e307eb94SToomas Soome } 961e307eb94SToomas Soome *(nvlist_t ***)valuep = nvlist; 962e307eb94SToomas Soome return (rv); 9633830659eSToomas Soome } 9643830659eSToomas Soome return (EIO); 9653830659eSToomas Soome } 9663830659eSToomas Soome /* Not our pair, skip to next. */ 9673830659eSToomas Soome nvp = (nvp_header_t *)((uint8_t *)nvp + nvp->encoded_size); 968e307eb94SToomas Soome if (nvl->nv_data + nvl->nv_size < (uint8_t *)nvp) 969e307eb94SToomas Soome return (EIO); 9703830659eSToomas Soome } 9713830659eSToomas Soome return (ENOENT); 972e307eb94SToomas Soome error: 973e307eb94SToomas Soome for (unsigned i = 0; i < nvp_data->nv_nelem; i++) { 974e307eb94SToomas Soome free(nvlist[i]->nv_data); 975e307eb94SToomas Soome free(nvlist[i]); 976e307eb94SToomas Soome } 977e307eb94SToomas Soome free(nvlist); 978e307eb94SToomas Soome return (rv); 9793830659eSToomas Soome } 9803830659eSToomas Soome 981e307eb94SToomas Soome static int 982e307eb94SToomas Soome get_value_size(data_type_t type, const void *data, uint32_t nelem) 9833830659eSToomas Soome { 984e307eb94SToomas Soome uint64_t value_sz = 0; 9853830659eSToomas Soome 986e307eb94SToomas Soome switch (type) { 987e307eb94SToomas Soome case DATA_TYPE_BOOLEAN: 988e307eb94SToomas Soome value_sz = 0; 989e307eb94SToomas Soome break; 990e307eb94SToomas Soome case DATA_TYPE_BOOLEAN_VALUE: 991e307eb94SToomas Soome case DATA_TYPE_BYTE: 992e307eb94SToomas Soome case DATA_TYPE_INT8: 993e307eb94SToomas Soome case DATA_TYPE_UINT8: 994e307eb94SToomas Soome case DATA_TYPE_INT16: 995e307eb94SToomas Soome case DATA_TYPE_UINT16: 996e307eb94SToomas Soome case DATA_TYPE_INT32: 997e307eb94SToomas Soome case DATA_TYPE_UINT32: 998e307eb94SToomas Soome /* Our smallest data unit is 32-bit */ 999e307eb94SToomas Soome value_sz = sizeof(uint32_t); 1000e307eb94SToomas Soome break; 1001e307eb94SToomas Soome case DATA_TYPE_HRTIME: 1002e307eb94SToomas Soome case DATA_TYPE_INT64: 1003e307eb94SToomas Soome value_sz = sizeof(int64_t); 1004e307eb94SToomas Soome break; 1005e307eb94SToomas Soome case DATA_TYPE_UINT64: 1006e307eb94SToomas Soome value_sz = sizeof(uint64_t); 1007e307eb94SToomas Soome break; 1008e307eb94SToomas Soome case DATA_TYPE_STRING: 1009e307eb94SToomas Soome if (data == NULL) 1010e307eb94SToomas Soome value_sz = 0; 1011e307eb94SToomas Soome else 1012e307eb94SToomas Soome value_sz = strlen(data) + 1; 1013e307eb94SToomas Soome break; 1014e307eb94SToomas Soome case DATA_TYPE_BYTE_ARRAY: 1015e307eb94SToomas Soome value_sz = nelem * sizeof(uint8_t); 1016e307eb94SToomas Soome break; 1017e307eb94SToomas Soome case DATA_TYPE_BOOLEAN_ARRAY: 1018e307eb94SToomas Soome case DATA_TYPE_INT8_ARRAY: 1019e307eb94SToomas Soome case DATA_TYPE_UINT8_ARRAY: 1020e307eb94SToomas Soome case DATA_TYPE_INT16_ARRAY: 1021e307eb94SToomas Soome case DATA_TYPE_UINT16_ARRAY: 1022e307eb94SToomas Soome case DATA_TYPE_INT32_ARRAY: 1023e307eb94SToomas Soome case DATA_TYPE_UINT32_ARRAY: 1024e307eb94SToomas Soome value_sz = (uint64_t)nelem * sizeof(uint32_t); 1025e307eb94SToomas Soome break; 1026e307eb94SToomas Soome case DATA_TYPE_INT64_ARRAY: 1027e307eb94SToomas Soome value_sz = (uint64_t)nelem * sizeof(int64_t); 1028e307eb94SToomas Soome break; 1029e307eb94SToomas Soome case DATA_TYPE_UINT64_ARRAY: 1030e307eb94SToomas Soome value_sz = (uint64_t)nelem * sizeof(uint64_t); 1031e307eb94SToomas Soome break; 1032e307eb94SToomas Soome case DATA_TYPE_STRING_ARRAY: 1033e307eb94SToomas Soome value_sz = (uint64_t)nelem * sizeof(uint64_t); 1034e307eb94SToomas Soome 1035e307eb94SToomas Soome if (data != NULL) { 1036e307eb94SToomas Soome char *const *strs = data; 1037e307eb94SToomas Soome uint32_t i; 1038e307eb94SToomas Soome 1039e307eb94SToomas Soome for (i = 0; i < nelem; i++) { 1040e307eb94SToomas Soome if (strs[i] == NULL) 1041e307eb94SToomas Soome return (-1); 1042e307eb94SToomas Soome value_sz += strlen(strs[i]) + 1; 1043e307eb94SToomas Soome } 1044e307eb94SToomas Soome } 1045e307eb94SToomas Soome break; 1046e307eb94SToomas Soome case DATA_TYPE_NVLIST: 1047e307eb94SToomas Soome /* 1048e307eb94SToomas Soome * The decoded size of nvlist is constant. 1049e307eb94SToomas Soome */ 1050e307eb94SToomas Soome value_sz = NV_ALIGN(6 * 4); /* sizeof nvlist_t */ 1051e307eb94SToomas Soome break; 1052e307eb94SToomas Soome case DATA_TYPE_NVLIST_ARRAY: 1053e307eb94SToomas Soome value_sz = (uint64_t)nelem * sizeof(uint64_t) + 1054e307eb94SToomas Soome (uint64_t)nelem * NV_ALIGN(6 * 4); /* sizeof nvlist_t */ 1055e307eb94SToomas Soome break; 1056e307eb94SToomas Soome default: 1057e307eb94SToomas Soome return (-1); 1058e307eb94SToomas Soome } 1059e307eb94SToomas Soome 1060e307eb94SToomas Soome return (value_sz > INT32_MAX ? -1 : (int)value_sz); 1061e307eb94SToomas Soome } 1062e307eb94SToomas Soome 1063e307eb94SToomas Soome static int 1064e307eb94SToomas Soome get_nvp_data_size(data_type_t type, const void *data, uint32_t nelem) 1065e307eb94SToomas Soome { 1066e307eb94SToomas Soome uint64_t value_sz = 0; 1067e307eb94SToomas Soome xdr_t xdr; 1068e307eb94SToomas Soome size_t size; 1069e307eb94SToomas Soome 1070e307eb94SToomas Soome switch (type) { 1071e307eb94SToomas Soome case DATA_TYPE_BOOLEAN: 1072e307eb94SToomas Soome value_sz = 0; 1073e307eb94SToomas Soome break; 1074e307eb94SToomas Soome case DATA_TYPE_BOOLEAN_VALUE: 1075e307eb94SToomas Soome case DATA_TYPE_BYTE: 1076e307eb94SToomas Soome case DATA_TYPE_INT8: 1077e307eb94SToomas Soome case DATA_TYPE_UINT8: 1078e307eb94SToomas Soome case DATA_TYPE_INT16: 1079e307eb94SToomas Soome case DATA_TYPE_UINT16: 1080e307eb94SToomas Soome case DATA_TYPE_INT32: 1081e307eb94SToomas Soome case DATA_TYPE_UINT32: 1082e307eb94SToomas Soome /* Our smallest data unit is 32-bit */ 1083e307eb94SToomas Soome value_sz = sizeof(uint32_t); 1084e307eb94SToomas Soome break; 1085e307eb94SToomas Soome case DATA_TYPE_HRTIME: 1086e307eb94SToomas Soome case DATA_TYPE_INT64: 1087e307eb94SToomas Soome case DATA_TYPE_UINT64: 1088e307eb94SToomas Soome value_sz = sizeof(uint64_t); 1089e307eb94SToomas Soome break; 1090e307eb94SToomas Soome case DATA_TYPE_STRING: 1091e307eb94SToomas Soome value_sz = 4 + NV_ALIGN4(strlen(data)); 1092e307eb94SToomas Soome break; 1093e307eb94SToomas Soome case DATA_TYPE_BYTE_ARRAY: 1094e307eb94SToomas Soome value_sz = NV_ALIGN4(nelem); 1095e307eb94SToomas Soome break; 1096e307eb94SToomas Soome case DATA_TYPE_BOOLEAN_ARRAY: 1097e307eb94SToomas Soome case DATA_TYPE_INT8_ARRAY: 1098e307eb94SToomas Soome case DATA_TYPE_UINT8_ARRAY: 1099e307eb94SToomas Soome case DATA_TYPE_INT16_ARRAY: 1100e307eb94SToomas Soome case DATA_TYPE_UINT16_ARRAY: 1101e307eb94SToomas Soome case DATA_TYPE_INT32_ARRAY: 1102e307eb94SToomas Soome case DATA_TYPE_UINT32_ARRAY: 1103e307eb94SToomas Soome value_sz = 4 + (uint64_t)nelem * sizeof(uint32_t); 1104e307eb94SToomas Soome break; 1105e307eb94SToomas Soome case DATA_TYPE_INT64_ARRAY: 1106e307eb94SToomas Soome case DATA_TYPE_UINT64_ARRAY: 1107e307eb94SToomas Soome value_sz = 4 + (uint64_t)nelem * sizeof(uint64_t); 1108e307eb94SToomas Soome break; 1109e307eb94SToomas Soome case DATA_TYPE_STRING_ARRAY: 1110e307eb94SToomas Soome if (data != NULL) { 1111e307eb94SToomas Soome char *const *strs = data; 1112e307eb94SToomas Soome uint32_t i; 1113e307eb94SToomas Soome 1114e307eb94SToomas Soome for (i = 0; i < nelem; i++) { 1115e307eb94SToomas Soome value_sz += 4 + NV_ALIGN4(strlen(strs[i])); 1116e307eb94SToomas Soome } 1117e307eb94SToomas Soome } 1118e307eb94SToomas Soome break; 1119e307eb94SToomas Soome case DATA_TYPE_NVLIST: 1120e307eb94SToomas Soome xdr.xdr_idx = ((nvlist_t *)data)->nv_data; 1121e307eb94SToomas Soome xdr.xdr_buf = xdr.xdr_idx; 1122e307eb94SToomas Soome xdr.xdr_buf_size = ((nvlist_t *)data)->nv_size; 1123e307eb94SToomas Soome 1124e307eb94SToomas Soome if (!nvlist_size_native(&xdr, &size)) 1125e307eb94SToomas Soome return (-1); 1126e307eb94SToomas Soome 1127e307eb94SToomas Soome value_sz = size; 1128e307eb94SToomas Soome break; 1129e307eb94SToomas Soome case DATA_TYPE_NVLIST_ARRAY: 1130e307eb94SToomas Soome value_sz = 0; 1131e307eb94SToomas Soome for (uint32_t i = 0; i < nelem; i++) { 1132e307eb94SToomas Soome xdr.xdr_idx = ((nvlist_t **)data)[i]->nv_data; 1133e307eb94SToomas Soome xdr.xdr_buf = xdr.xdr_idx; 1134e307eb94SToomas Soome xdr.xdr_buf_size = ((nvlist_t **)data)[i]->nv_size; 1135e307eb94SToomas Soome 1136e307eb94SToomas Soome if (!nvlist_size_native(&xdr, &size)) 1137e307eb94SToomas Soome return (-1); 1138e307eb94SToomas Soome value_sz += size; 1139e307eb94SToomas Soome } 1140e307eb94SToomas Soome break; 1141e307eb94SToomas Soome default: 1142e307eb94SToomas Soome return (-1); 1143e307eb94SToomas Soome } 1144e307eb94SToomas Soome 1145e307eb94SToomas Soome return (value_sz > INT32_MAX ? -1 : (int)value_sz); 1146e307eb94SToomas Soome } 1147e307eb94SToomas Soome 1148e307eb94SToomas Soome #define NVPE_SIZE(name_len, data_len) \ 1149e307eb94SToomas Soome (4 + 4 + 4 + NV_ALIGN4(name_len) + 4 + 4 + data_len) 1150e307eb94SToomas Soome #define NVP_SIZE(name_len, data_len) \ 1151e307eb94SToomas Soome (NV_ALIGN((4 * 4) + (name_len)) + NV_ALIGN(data_len)) 1152e307eb94SToomas Soome 1153e307eb94SToomas Soome static int 1154e307eb94SToomas Soome nvlist_add_common(nvlist_t *nvl, const char *name, data_type_t type, 1155e307eb94SToomas Soome uint32_t nelem, const void *data) 1156e307eb94SToomas Soome { 1157e307eb94SToomas Soome nvs_data_t *nvs; 1158e307eb94SToomas Soome nvp_header_t head, *hp; 1159e307eb94SToomas Soome uint8_t *ptr; 1160e307eb94SToomas Soome size_t namelen; 1161e307eb94SToomas Soome int decoded_size, encoded_size; 11629de6a13eSToomas Soome xdr_t xdr = { 11639de6a13eSToomas Soome .xdr_op = XDR_OP_ENCODE, 11649de6a13eSToomas Soome .xdr_putint = _putint_mem, 11659de6a13eSToomas Soome .xdr_putuint = _putuint_mem, 11669de6a13eSToomas Soome .xdr_buf = nvl->nv_data, 11679de6a13eSToomas Soome .xdr_idx = nvl->nv_data, 11689de6a13eSToomas Soome .xdr_buf_size = nvl->nv_size 11699de6a13eSToomas Soome }; 1170e307eb94SToomas Soome 1171e307eb94SToomas Soome nvs = (nvs_data_t *)nvl->nv_data; 1172e307eb94SToomas Soome if (nvs->nvl_nvflag & NV_UNIQUE_NAME) 1173e307eb94SToomas Soome (void) nvlist_remove(nvl, name, type); 1174e307eb94SToomas Soome 1175e307eb94SToomas Soome xdr.xdr_buf = nvl->nv_data; 1176e307eb94SToomas Soome xdr.xdr_idx = nvl->nv_data; 1177e307eb94SToomas Soome xdr.xdr_buf_size = nvl->nv_size; 1178e307eb94SToomas Soome if (!nvlist_size_native(&xdr, &nvl->nv_size)) 11793830659eSToomas Soome return (EINVAL); 11803830659eSToomas Soome 1181e307eb94SToomas Soome namelen = strlen(name); 1182e307eb94SToomas Soome if ((decoded_size = get_value_size(type, data, nelem)) < 0) 1183e307eb94SToomas Soome return (EINVAL); 1184e307eb94SToomas Soome if ((encoded_size = get_nvp_data_size(type, data, nelem)) < 0) 1185e307eb94SToomas Soome return (EINVAL); 11863830659eSToomas Soome 1187e307eb94SToomas Soome /* 1188e307eb94SToomas Soome * The encoded size is calculated as: 1189e307eb94SToomas Soome * encode_size (4) + decode_size (4) + 1190e307eb94SToomas Soome * name string size (4 + NV_ALIGN4(namelen) + 1191e307eb94SToomas Soome * data type (4) + nelem size (4) + datalen 1192e307eb94SToomas Soome * 1193e307eb94SToomas Soome * The decoded size is calculated as: 1194e307eb94SToomas Soome * Note: namelen is with terminating 0. 1195e307eb94SToomas Soome * NV_ALIGN(sizeof(nvpair_t) (4 * 4) + namelen + 1) + 1196e307eb94SToomas Soome * NV_ALIGN(data_len) 1197e307eb94SToomas Soome */ 1198e307eb94SToomas Soome 1199e307eb94SToomas Soome head.encoded_size = NVPE_SIZE(namelen, encoded_size); 1200e307eb94SToomas Soome head.decoded_size = NVP_SIZE(namelen + 1, decoded_size); 1201e307eb94SToomas Soome 1202e307eb94SToomas Soome if (nvl->nv_asize - nvl->nv_size < head.encoded_size + 8) { 1203e307eb94SToomas Soome ptr = realloc(nvl->nv_data, nvl->nv_asize + head.encoded_size); 1204e307eb94SToomas Soome if (ptr == NULL) 1205e307eb94SToomas Soome return (ENOMEM); 1206e307eb94SToomas Soome nvl->nv_data = ptr; 1207e307eb94SToomas Soome nvl->nv_asize += head.encoded_size; 12083830659eSToomas Soome } 1209e307eb94SToomas Soome nvl->nv_idx = nvl->nv_data + nvl->nv_size - sizeof(*hp); 1210e307eb94SToomas Soome bzero(nvl->nv_idx, head.encoded_size + 8); 1211e307eb94SToomas Soome hp = (nvp_header_t *)nvl->nv_idx; 1212e307eb94SToomas Soome *hp = head; 1213e307eb94SToomas Soome nvl->nv_idx += sizeof(*hp); 12149de6a13eSToomas Soome 12159de6a13eSToomas Soome xdr.xdr_buf = nvl->nv_data; 12169de6a13eSToomas Soome xdr.xdr_idx = nvl->nv_idx; 12179de6a13eSToomas Soome 12189de6a13eSToomas Soome xdr.xdr_idx += xdr.xdr_putuint(&xdr, namelen); 12199de6a13eSToomas Soome strlcpy((char *)xdr.xdr_idx, name, namelen + 1); 12209de6a13eSToomas Soome xdr.xdr_idx += NV_ALIGN4(namelen); 12219de6a13eSToomas Soome xdr.xdr_idx += xdr.xdr_putuint(&xdr, type); 12229de6a13eSToomas Soome xdr.xdr_idx += xdr.xdr_putuint(&xdr, nelem); 1223e307eb94SToomas Soome 1224e307eb94SToomas Soome switch (type) { 1225e307eb94SToomas Soome case DATA_TYPE_BOOLEAN: 1226e307eb94SToomas Soome break; 12279de6a13eSToomas Soome 1228e307eb94SToomas Soome case DATA_TYPE_BYTE_ARRAY: 12299de6a13eSToomas Soome xdr.xdr_idx += xdr.xdr_putuint(&xdr, encoded_size); 12309de6a13eSToomas Soome bcopy(data, xdr.xdr_idx, nelem); 12319de6a13eSToomas Soome xdr.xdr_idx += NV_ALIGN4(encoded_size); 1232e307eb94SToomas Soome break; 12339de6a13eSToomas Soome 1234e307eb94SToomas Soome case DATA_TYPE_STRING: 1235e307eb94SToomas Soome encoded_size = strlen(data); 12369de6a13eSToomas Soome xdr.xdr_idx += xdr.xdr_putuint(&xdr, encoded_size); 12379de6a13eSToomas Soome strlcpy((char *)xdr.xdr_idx, data, encoded_size + 1); 12389de6a13eSToomas Soome xdr.xdr_idx += NV_ALIGN4(encoded_size); 1239e307eb94SToomas Soome break; 12409de6a13eSToomas Soome 1241e307eb94SToomas Soome case DATA_TYPE_STRING_ARRAY: 1242e307eb94SToomas Soome for (uint32_t i = 0; i < nelem; i++) { 1243e307eb94SToomas Soome encoded_size = strlen(((char **)data)[i]); 12449de6a13eSToomas Soome xdr.xdr_idx += xdr.xdr_putuint(&xdr, encoded_size); 12459de6a13eSToomas Soome strlcpy((char *)xdr.xdr_idx, ((char **)data)[i], 1246e307eb94SToomas Soome encoded_size + 1); 12479de6a13eSToomas Soome xdr.xdr_idx += NV_ALIGN4(encoded_size); 1248e307eb94SToomas Soome } 1249e307eb94SToomas Soome break; 12509de6a13eSToomas Soome 1251e307eb94SToomas Soome case DATA_TYPE_BYTE: 1252e307eb94SToomas Soome case DATA_TYPE_INT8: 1253e307eb94SToomas Soome case DATA_TYPE_UINT8: 12549de6a13eSToomas Soome xdr_char(&xdr, (char *)data); 12559de6a13eSToomas Soome break; 12569de6a13eSToomas Soome 1257e307eb94SToomas Soome case DATA_TYPE_INT8_ARRAY: 1258e307eb94SToomas Soome case DATA_TYPE_UINT8_ARRAY: 12599de6a13eSToomas Soome xdr_array(&xdr, nelem, (xdrproc_t)xdr_char); 1260e307eb94SToomas Soome break; 12619de6a13eSToomas Soome 1262e307eb94SToomas Soome case DATA_TYPE_INT16: 12639de6a13eSToomas Soome xdr_short(&xdr, (short *)data); 12649de6a13eSToomas Soome break; 12659de6a13eSToomas Soome 1266e307eb94SToomas Soome case DATA_TYPE_UINT16: 12679de6a13eSToomas Soome xdr_u_short(&xdr, (unsigned short *)data); 12689de6a13eSToomas Soome break; 12699de6a13eSToomas Soome 1270e307eb94SToomas Soome case DATA_TYPE_INT16_ARRAY: 12719de6a13eSToomas Soome xdr_array(&xdr, nelem, (xdrproc_t)xdr_short); 12729de6a13eSToomas Soome break; 12739de6a13eSToomas Soome 1274e307eb94SToomas Soome case DATA_TYPE_UINT16_ARRAY: 12759de6a13eSToomas Soome xdr_array(&xdr, nelem, (xdrproc_t)xdr_u_short); 1276e307eb94SToomas Soome break; 12779de6a13eSToomas Soome 12789de6a13eSToomas Soome case DATA_TYPE_BOOLEAN_VALUE: 12799de6a13eSToomas Soome case DATA_TYPE_INT32: 12809de6a13eSToomas Soome xdr_int(&xdr, (int *)data); 12819de6a13eSToomas Soome break; 12829de6a13eSToomas Soome 12839de6a13eSToomas Soome case DATA_TYPE_UINT32: 12849de6a13eSToomas Soome xdr_u_int(&xdr, (unsigned int *)data); 12859de6a13eSToomas Soome break; 12869de6a13eSToomas Soome 12879de6a13eSToomas Soome case DATA_TYPE_BOOLEAN_ARRAY: 12889de6a13eSToomas Soome case DATA_TYPE_INT32_ARRAY: 12899de6a13eSToomas Soome xdr_array(&xdr, nelem, (xdrproc_t)xdr_int); 12909de6a13eSToomas Soome break; 12919de6a13eSToomas Soome 12929de6a13eSToomas Soome case DATA_TYPE_UINT32_ARRAY: 12939de6a13eSToomas Soome xdr_array(&xdr, nelem, (xdrproc_t)xdr_u_int); 12949de6a13eSToomas Soome break; 12959de6a13eSToomas Soome 12969de6a13eSToomas Soome case DATA_TYPE_INT64: 12979de6a13eSToomas Soome xdr_int64(&xdr, (int64_t *)data); 12989de6a13eSToomas Soome break; 12999de6a13eSToomas Soome 13009de6a13eSToomas Soome case DATA_TYPE_UINT64: 13019de6a13eSToomas Soome xdr_uint64(&xdr, (uint64_t *)data); 13029de6a13eSToomas Soome break; 13039de6a13eSToomas Soome 13049de6a13eSToomas Soome case DATA_TYPE_INT64_ARRAY: 13059de6a13eSToomas Soome xdr_array(&xdr, nelem, (xdrproc_t)xdr_int64); 13069de6a13eSToomas Soome break; 13079de6a13eSToomas Soome 13089de6a13eSToomas Soome case DATA_TYPE_UINT64_ARRAY: 13099de6a13eSToomas Soome xdr_array(&xdr, nelem, (xdrproc_t)xdr_uint64); 13109de6a13eSToomas Soome break; 13119de6a13eSToomas Soome 1312e307eb94SToomas Soome case DATA_TYPE_NVLIST: 13139de6a13eSToomas Soome bcopy(((nvlist_t *)data)->nv_data, xdr.xdr_idx, encoded_size); 1314e307eb94SToomas Soome break; 13159de6a13eSToomas Soome 1316e307eb94SToomas Soome case DATA_TYPE_NVLIST_ARRAY: { 1317e307eb94SToomas Soome size_t size; 13189de6a13eSToomas Soome xdr_t xdr_nv; 1319e307eb94SToomas Soome 1320e307eb94SToomas Soome for (uint32_t i = 0; i < nelem; i++) { 13219de6a13eSToomas Soome xdr_nv.xdr_idx = ((nvlist_t **)data)[i]->nv_data; 13229de6a13eSToomas Soome xdr_nv.xdr_buf = xdr_nv.xdr_idx; 13239de6a13eSToomas Soome xdr_nv.xdr_buf_size = ((nvlist_t **)data)[i]->nv_size; 1324e307eb94SToomas Soome 13259de6a13eSToomas Soome if (!nvlist_size_native(&xdr_nv, &size)) 1326e307eb94SToomas Soome return (EINVAL); 1327e307eb94SToomas Soome 13289de6a13eSToomas Soome bcopy(((nvlist_t **)data)[i]->nv_data, xdr.xdr_idx, 13299de6a13eSToomas Soome size); 13309de6a13eSToomas Soome xdr.xdr_idx += size; 1331e307eb94SToomas Soome } 1332e307eb94SToomas Soome break; 1333e307eb94SToomas Soome } 1334e307eb94SToomas Soome default: 13359de6a13eSToomas Soome bcopy(data, xdr.xdr_idx, encoded_size); 1336e307eb94SToomas Soome } 1337e307eb94SToomas Soome 1338e307eb94SToomas Soome nvl->nv_size += head.encoded_size; 1339e307eb94SToomas Soome 13403830659eSToomas Soome return (0); 13413830659eSToomas Soome } 13423830659eSToomas Soome 1343e307eb94SToomas Soome int 1344e307eb94SToomas Soome nvlist_add_boolean_value(nvlist_t *nvl, const char *name, boolean_t value) 13453830659eSToomas Soome { 1346e307eb94SToomas Soome return (nvlist_add_common(nvl, name, DATA_TYPE_BOOLEAN_VALUE, 1, 1347e307eb94SToomas Soome &value)); 1348e307eb94SToomas Soome } 1349e307eb94SToomas Soome 1350e307eb94SToomas Soome int 1351e307eb94SToomas Soome nvlist_add_byte(nvlist_t *nvl, const char *name, uint8_t value) 1352e307eb94SToomas Soome { 1353e307eb94SToomas Soome return (nvlist_add_common(nvl, name, DATA_TYPE_BYTE, 1, &value)); 1354e307eb94SToomas Soome } 1355e307eb94SToomas Soome 1356e307eb94SToomas Soome int 1357e307eb94SToomas Soome nvlist_add_int8(nvlist_t *nvl, const char *name, int8_t value) 1358e307eb94SToomas Soome { 1359e307eb94SToomas Soome return (nvlist_add_common(nvl, name, DATA_TYPE_INT8, 1, &value)); 1360e307eb94SToomas Soome } 1361e307eb94SToomas Soome 1362e307eb94SToomas Soome int 1363e307eb94SToomas Soome nvlist_add_uint8(nvlist_t *nvl, const char *name, uint8_t value) 1364e307eb94SToomas Soome { 1365e307eb94SToomas Soome return (nvlist_add_common(nvl, name, DATA_TYPE_UINT8, 1, &value)); 1366e307eb94SToomas Soome } 1367e307eb94SToomas Soome 1368e307eb94SToomas Soome int 1369e307eb94SToomas Soome nvlist_add_int16(nvlist_t *nvl, const char *name, int16_t value) 1370e307eb94SToomas Soome { 1371e307eb94SToomas Soome return (nvlist_add_common(nvl, name, DATA_TYPE_INT16, 1, &value)); 1372e307eb94SToomas Soome } 1373e307eb94SToomas Soome 1374e307eb94SToomas Soome int 1375e307eb94SToomas Soome nvlist_add_uint16(nvlist_t *nvl, const char *name, uint16_t value) 1376e307eb94SToomas Soome { 1377e307eb94SToomas Soome return (nvlist_add_common(nvl, name, DATA_TYPE_UINT16, 1, &value)); 1378e307eb94SToomas Soome } 1379e307eb94SToomas Soome 1380e307eb94SToomas Soome int 1381e307eb94SToomas Soome nvlist_add_int32(nvlist_t *nvl, const char *name, int32_t value) 1382e307eb94SToomas Soome { 1383e307eb94SToomas Soome return (nvlist_add_common(nvl, name, DATA_TYPE_INT32, 1, &value)); 1384e307eb94SToomas Soome } 1385e307eb94SToomas Soome 1386e307eb94SToomas Soome int 1387e307eb94SToomas Soome nvlist_add_uint32(nvlist_t *nvl, const char *name, uint32_t value) 1388e307eb94SToomas Soome { 1389e307eb94SToomas Soome return (nvlist_add_common(nvl, name, DATA_TYPE_UINT32, 1, &value)); 1390e307eb94SToomas Soome } 1391e307eb94SToomas Soome 1392e307eb94SToomas Soome int 1393e307eb94SToomas Soome nvlist_add_int64(nvlist_t *nvl, const char *name, int64_t value) 1394e307eb94SToomas Soome { 1395e307eb94SToomas Soome return (nvlist_add_common(nvl, name, DATA_TYPE_INT64, 1, &value)); 1396e307eb94SToomas Soome } 1397e307eb94SToomas Soome 1398e307eb94SToomas Soome int 1399e307eb94SToomas Soome nvlist_add_uint64(nvlist_t *nvl, const char *name, uint64_t value) 1400e307eb94SToomas Soome { 1401e307eb94SToomas Soome return (nvlist_add_common(nvl, name, DATA_TYPE_UINT64, 1, &value)); 1402e307eb94SToomas Soome } 1403e307eb94SToomas Soome 1404e307eb94SToomas Soome int 1405e307eb94SToomas Soome nvlist_add_string(nvlist_t *nvl, const char *name, const char *value) 1406e307eb94SToomas Soome { 1407e307eb94SToomas Soome return (nvlist_add_common(nvl, name, DATA_TYPE_STRING, 1, value)); 1408e307eb94SToomas Soome } 1409e307eb94SToomas Soome 1410e307eb94SToomas Soome int 1411e307eb94SToomas Soome nvlist_add_boolean_array(nvlist_t *nvl, const char *name, 1412e307eb94SToomas Soome boolean_t *a, uint32_t n) 1413e307eb94SToomas Soome { 1414e307eb94SToomas Soome return (nvlist_add_common(nvl, name, DATA_TYPE_BOOLEAN_ARRAY, n, a)); 1415e307eb94SToomas Soome } 1416e307eb94SToomas Soome 1417e307eb94SToomas Soome int 1418e307eb94SToomas Soome nvlist_add_byte_array(nvlist_t *nvl, const char *name, uint8_t *a, uint32_t n) 1419e307eb94SToomas Soome { 1420e307eb94SToomas Soome return (nvlist_add_common(nvl, name, DATA_TYPE_BYTE_ARRAY, n, a)); 1421e307eb94SToomas Soome } 1422e307eb94SToomas Soome 1423e307eb94SToomas Soome int 1424e307eb94SToomas Soome nvlist_add_int8_array(nvlist_t *nvl, const char *name, int8_t *a, uint32_t n) 1425e307eb94SToomas Soome { 1426e307eb94SToomas Soome return (nvlist_add_common(nvl, name, DATA_TYPE_INT8_ARRAY, n, a)); 1427e307eb94SToomas Soome } 1428e307eb94SToomas Soome 1429e307eb94SToomas Soome int 1430e307eb94SToomas Soome nvlist_add_uint8_array(nvlist_t *nvl, const char *name, uint8_t *a, uint32_t n) 1431e307eb94SToomas Soome { 1432e307eb94SToomas Soome return (nvlist_add_common(nvl, name, DATA_TYPE_UINT8_ARRAY, n, a)); 1433e307eb94SToomas Soome } 1434e307eb94SToomas Soome 1435e307eb94SToomas Soome int 1436e307eb94SToomas Soome nvlist_add_int16_array(nvlist_t *nvl, const char *name, int16_t *a, uint32_t n) 1437e307eb94SToomas Soome { 1438e307eb94SToomas Soome return (nvlist_add_common(nvl, name, DATA_TYPE_INT16_ARRAY, n, a)); 1439e307eb94SToomas Soome } 1440e307eb94SToomas Soome 1441e307eb94SToomas Soome int 1442e307eb94SToomas Soome nvlist_add_uint16_array(nvlist_t *nvl, const char *name, uint16_t *a, 1443e307eb94SToomas Soome uint32_t n) 1444e307eb94SToomas Soome { 1445e307eb94SToomas Soome return (nvlist_add_common(nvl, name, DATA_TYPE_UINT16_ARRAY, n, a)); 1446e307eb94SToomas Soome } 1447e307eb94SToomas Soome 1448e307eb94SToomas Soome int 1449e307eb94SToomas Soome nvlist_add_int32_array(nvlist_t *nvl, const char *name, int32_t *a, uint32_t n) 1450e307eb94SToomas Soome { 1451e307eb94SToomas Soome return (nvlist_add_common(nvl, name, DATA_TYPE_INT32_ARRAY, n, a)); 1452e307eb94SToomas Soome } 1453e307eb94SToomas Soome 1454e307eb94SToomas Soome int 1455e307eb94SToomas Soome nvlist_add_uint32_array(nvlist_t *nvl, const char *name, uint32_t *a, 1456e307eb94SToomas Soome uint32_t n) 1457e307eb94SToomas Soome { 1458e307eb94SToomas Soome return (nvlist_add_common(nvl, name, DATA_TYPE_UINT32_ARRAY, n, a)); 1459e307eb94SToomas Soome } 1460e307eb94SToomas Soome 1461e307eb94SToomas Soome int 1462e307eb94SToomas Soome nvlist_add_int64_array(nvlist_t *nvl, const char *name, int64_t *a, uint32_t n) 1463e307eb94SToomas Soome { 1464e307eb94SToomas Soome return (nvlist_add_common(nvl, name, DATA_TYPE_INT64_ARRAY, n, a)); 1465e307eb94SToomas Soome } 1466e307eb94SToomas Soome 1467e307eb94SToomas Soome int 1468e307eb94SToomas Soome nvlist_add_uint64_array(nvlist_t *nvl, const char *name, uint64_t *a, 1469e307eb94SToomas Soome uint32_t n) 1470e307eb94SToomas Soome { 1471e307eb94SToomas Soome return (nvlist_add_common(nvl, name, DATA_TYPE_UINT64_ARRAY, n, a)); 1472e307eb94SToomas Soome } 1473e307eb94SToomas Soome 1474e307eb94SToomas Soome int 1475e307eb94SToomas Soome nvlist_add_string_array(nvlist_t *nvl, const char *name, 1476e307eb94SToomas Soome char * const *a, uint32_t n) 1477e307eb94SToomas Soome { 1478e307eb94SToomas Soome return (nvlist_add_common(nvl, name, DATA_TYPE_STRING_ARRAY, n, a)); 1479e307eb94SToomas Soome } 1480e307eb94SToomas Soome 1481e307eb94SToomas Soome int 1482e307eb94SToomas Soome nvlist_add_nvlist(nvlist_t *nvl, const char *name, nvlist_t *val) 1483e307eb94SToomas Soome { 1484e307eb94SToomas Soome return (nvlist_add_common(nvl, name, DATA_TYPE_NVLIST, 1, val)); 1485e307eb94SToomas Soome } 1486e307eb94SToomas Soome 1487e307eb94SToomas Soome int 1488e307eb94SToomas Soome nvlist_add_nvlist_array(nvlist_t *nvl, const char *name, nvlist_t **a, 1489e307eb94SToomas Soome uint32_t n) 1490e307eb94SToomas Soome { 1491e307eb94SToomas Soome return (nvlist_add_common(nvl, name, DATA_TYPE_NVLIST_ARRAY, n, a)); 1492e307eb94SToomas Soome } 1493e307eb94SToomas Soome 14943830659eSToomas Soome static const char *typenames[] = { 14953830659eSToomas Soome "DATA_TYPE_UNKNOWN", 14963830659eSToomas Soome "DATA_TYPE_BOOLEAN", 14973830659eSToomas Soome "DATA_TYPE_BYTE", 14983830659eSToomas Soome "DATA_TYPE_INT16", 14993830659eSToomas Soome "DATA_TYPE_UINT16", 15003830659eSToomas Soome "DATA_TYPE_INT32", 15013830659eSToomas Soome "DATA_TYPE_UINT32", 15023830659eSToomas Soome "DATA_TYPE_INT64", 15033830659eSToomas Soome "DATA_TYPE_UINT64", 15043830659eSToomas Soome "DATA_TYPE_STRING", 15053830659eSToomas Soome "DATA_TYPE_BYTE_ARRAY", 15063830659eSToomas Soome "DATA_TYPE_INT16_ARRAY", 15073830659eSToomas Soome "DATA_TYPE_UINT16_ARRAY", 15083830659eSToomas Soome "DATA_TYPE_INT32_ARRAY", 15093830659eSToomas Soome "DATA_TYPE_UINT32_ARRAY", 15103830659eSToomas Soome "DATA_TYPE_INT64_ARRAY", 15113830659eSToomas Soome "DATA_TYPE_UINT64_ARRAY", 15123830659eSToomas Soome "DATA_TYPE_STRING_ARRAY", 15133830659eSToomas Soome "DATA_TYPE_HRTIME", 15143830659eSToomas Soome "DATA_TYPE_NVLIST", 15153830659eSToomas Soome "DATA_TYPE_NVLIST_ARRAY", 15163830659eSToomas Soome "DATA_TYPE_BOOLEAN_VALUE", 15173830659eSToomas Soome "DATA_TYPE_INT8", 15183830659eSToomas Soome "DATA_TYPE_UINT8", 15193830659eSToomas Soome "DATA_TYPE_BOOLEAN_ARRAY", 15203830659eSToomas Soome "DATA_TYPE_INT8_ARRAY", 15213830659eSToomas Soome "DATA_TYPE_UINT8_ARRAY" 15223830659eSToomas Soome }; 1523e307eb94SToomas Soome 1524e307eb94SToomas Soome int 1525e307eb94SToomas Soome nvpair_type_from_name(const char *name) 1526e307eb94SToomas Soome { 1527e307eb94SToomas Soome unsigned i; 1528e307eb94SToomas Soome 1529e307eb94SToomas Soome for (i = 0; i < nitems(typenames); i++) { 1530e307eb94SToomas Soome if (strcmp(name, typenames[i]) == 0) 1531e307eb94SToomas Soome return (i); 1532e307eb94SToomas Soome } 1533e307eb94SToomas Soome return (0); 1534e307eb94SToomas Soome } 1535e307eb94SToomas Soome 1536e307eb94SToomas Soome nvp_header_t * 1537e307eb94SToomas Soome nvpair_find(nvlist_t *nv, const char *name) 1538e307eb94SToomas Soome { 1539e307eb94SToomas Soome nvp_header_t *nvh; 1540e307eb94SToomas Soome 1541e307eb94SToomas Soome nvh = NULL; 1542e307eb94SToomas Soome while ((nvh = nvlist_next_nvpair(nv, nvh)) != NULL) { 1543e307eb94SToomas Soome nv_string_t *nvp_name; 1544e307eb94SToomas Soome 1545e307eb94SToomas Soome nvp_name = (nv_string_t *)(nvh + 1); 1546e307eb94SToomas Soome if (nvp_name->nv_size == strlen(name) && 1547e307eb94SToomas Soome memcmp(nvp_name->nv_data, name, nvp_name->nv_size) == 0) 1548e307eb94SToomas Soome break; 1549e307eb94SToomas Soome } 1550e307eb94SToomas Soome return (nvh); 1551e307eb94SToomas Soome } 1552e307eb94SToomas Soome 1553e307eb94SToomas Soome void 1554e307eb94SToomas Soome nvpair_print(nvp_header_t *nvp, unsigned int indent) 1555e307eb94SToomas Soome { 15563830659eSToomas Soome nv_string_t *nvp_name; 15573830659eSToomas Soome nv_pair_data_t *nvp_data; 15583830659eSToomas Soome nvlist_t nvlist; 15599de6a13eSToomas Soome unsigned i, j; 15609de6a13eSToomas Soome xdr_t xdr = { 15619de6a13eSToomas Soome .xdr_op = XDR_OP_DECODE, 15629de6a13eSToomas Soome .xdr_getint = _getint_mem, 15639de6a13eSToomas Soome .xdr_getuint = _getuint_mem, 15649de6a13eSToomas Soome .xdr_buf = (const uint8_t *)nvp, 15659de6a13eSToomas Soome .xdr_idx = NULL, 15669de6a13eSToomas Soome .xdr_buf_size = nvp->encoded_size 15679de6a13eSToomas Soome }; 15683830659eSToomas Soome 15693830659eSToomas Soome nvp_name = (nv_string_t *)((uintptr_t)nvp + sizeof(*nvp)); 15703830659eSToomas Soome nvp_data = (nv_pair_data_t *) 1571e307eb94SToomas Soome NV_ALIGN4((uintptr_t)&nvp_name->nv_data[0] + nvp_name->nv_size); 15723830659eSToomas Soome 1573e307eb94SToomas Soome for (i = 0; i < indent; i++) 15743830659eSToomas Soome printf(" "); 15753830659eSToomas Soome 15763830659eSToomas Soome printf("%s [%d] %.*s", typenames[nvp_data->nv_type], 15773830659eSToomas Soome nvp_data->nv_nelem, nvp_name->nv_size, nvp_name->nv_data); 15783830659eSToomas Soome 15799de6a13eSToomas Soome xdr.xdr_idx = nvp_data->nv_data; 15803830659eSToomas Soome switch (nvp_data->nv_type) { 1581e307eb94SToomas Soome case DATA_TYPE_BYTE: 1582e307eb94SToomas Soome case DATA_TYPE_INT8: 15839de6a13eSToomas Soome case DATA_TYPE_UINT8: { 15849de6a13eSToomas Soome char c; 15859de6a13eSToomas Soome 15869de6a13eSToomas Soome if (xdr_char(&xdr, &c)) 15879de6a13eSToomas Soome printf(" = 0x%x\n", c); 15883830659eSToomas Soome break; 15899de6a13eSToomas Soome } 15903830659eSToomas Soome 1591e307eb94SToomas Soome case DATA_TYPE_INT16: 15929de6a13eSToomas Soome case DATA_TYPE_UINT16: { 15939de6a13eSToomas Soome unsigned short u; 15949de6a13eSToomas Soome 15959de6a13eSToomas Soome if (xdr_u_short(&xdr, &u)) 15969de6a13eSToomas Soome printf(" = 0x%hx\n", u); 1597e307eb94SToomas Soome break; 15989de6a13eSToomas Soome } 1599e307eb94SToomas Soome 1600e307eb94SToomas Soome case DATA_TYPE_BOOLEAN_VALUE: 1601e307eb94SToomas Soome case DATA_TYPE_INT32: 16029de6a13eSToomas Soome case DATA_TYPE_UINT32: { 16039de6a13eSToomas Soome unsigned u; 16049de6a13eSToomas Soome 16059de6a13eSToomas Soome if (xdr_u_int(&xdr, &u)) 1606e307eb94SToomas Soome printf(" = 0x%x\n", u); 1607e307eb94SToomas Soome break; 16089de6a13eSToomas Soome } 1609e307eb94SToomas Soome 1610e307eb94SToomas Soome case DATA_TYPE_INT64: 16119de6a13eSToomas Soome case DATA_TYPE_UINT64: { 16129de6a13eSToomas Soome uint64_t u; 16139de6a13eSToomas Soome 16149de6a13eSToomas Soome if (xdr_uint64(&xdr, &u)) 16159de6a13eSToomas Soome printf(" = 0x%jx\n", (uintmax_t)u); 1616e307eb94SToomas Soome break; 16179de6a13eSToomas Soome } 16189de6a13eSToomas Soome 16199de6a13eSToomas Soome case DATA_TYPE_INT64_ARRAY: 16209de6a13eSToomas Soome case DATA_TYPE_UINT64_ARRAY: { 16219de6a13eSToomas Soome uint64_t *u; 16229de6a13eSToomas Soome 16239de6a13eSToomas Soome if (xdr_array(&xdr, nvp_data->nv_nelem, 16249de6a13eSToomas Soome (xdrproc_t)xdr_uint64)) { 16259de6a13eSToomas Soome u = (uint64_t *)(nvp_data->nv_data + sizeof(unsigned)); 16269de6a13eSToomas Soome for (i = 0; i < nvp_data->nv_nelem; i++) 16279de6a13eSToomas Soome printf(" [%u] = 0x%jx", i, (uintmax_t)u[i]); 16289de6a13eSToomas Soome printf("\n"); 16299de6a13eSToomas Soome } 16309de6a13eSToomas Soome 16319de6a13eSToomas Soome break; 16329de6a13eSToomas Soome } 1633e307eb94SToomas Soome 1634e307eb94SToomas Soome case DATA_TYPE_STRING: 1635e307eb94SToomas Soome case DATA_TYPE_STRING_ARRAY: 16363830659eSToomas Soome nvp_name = (nv_string_t *)&nvp_data->nv_data[0]; 1637e307eb94SToomas Soome for (i = 0; i < nvp_data->nv_nelem; i++) { 16383830659eSToomas Soome printf(" = \"%.*s\"\n", nvp_name->nv_size, 16393830659eSToomas Soome nvp_name->nv_data); 16403830659eSToomas Soome } 1641e307eb94SToomas Soome break; 16423830659eSToomas Soome 16433830659eSToomas Soome case DATA_TYPE_NVLIST: 16443830659eSToomas Soome printf("\n"); 16453830659eSToomas Soome nvlist.nv_data = &nvp_data->nv_data[0]; 16463830659eSToomas Soome nvlist_print(&nvlist, indent + 2); 16473830659eSToomas Soome break; 16483830659eSToomas Soome 16493830659eSToomas Soome case DATA_TYPE_NVLIST_ARRAY: 16503830659eSToomas Soome nvlist.nv_data = &nvp_data->nv_data[0]; 16513830659eSToomas Soome for (j = 0; j < nvp_data->nv_nelem; j++) { 1652e307eb94SToomas Soome size_t size; 1653e307eb94SToomas Soome 16543830659eSToomas Soome printf("[%d]\n", j); 16553830659eSToomas Soome nvlist_print(&nvlist, indent + 2); 16563830659eSToomas Soome if (j != nvp_data->nv_nelem - 1) { 16573830659eSToomas Soome for (i = 0; i < indent; i++) 16583830659eSToomas Soome printf(" "); 16593830659eSToomas Soome printf("%s %.*s", 16603830659eSToomas Soome typenames[nvp_data->nv_type], 16613830659eSToomas Soome nvp_name->nv_size, 16623830659eSToomas Soome nvp_name->nv_data); 16633830659eSToomas Soome } 1664e307eb94SToomas Soome xdr.xdr_idx = nvlist.nv_data; 1665e307eb94SToomas Soome xdr.xdr_buf = xdr.xdr_idx; 1666e307eb94SToomas Soome xdr.xdr_buf_size = nvp->encoded_size - 1667e307eb94SToomas Soome (xdr.xdr_idx - (uint8_t *)nvp); 1668e307eb94SToomas Soome 1669e307eb94SToomas Soome if (!nvlist_size_native(&xdr, &size)) 1670e307eb94SToomas Soome return; 1671e307eb94SToomas Soome 1672e307eb94SToomas Soome nvlist.nv_data += size; 16733830659eSToomas Soome } 16743830659eSToomas Soome break; 16753830659eSToomas Soome 16763830659eSToomas Soome default: 16773830659eSToomas Soome printf("\n"); 16783830659eSToomas Soome } 1679e307eb94SToomas Soome } 1680e307eb94SToomas Soome 1681e307eb94SToomas Soome void 1682e307eb94SToomas Soome nvlist_print(const nvlist_t *nvl, unsigned int indent) 1683e307eb94SToomas Soome { 1684e307eb94SToomas Soome nvs_data_t *data; 1685e307eb94SToomas Soome nvp_header_t *nvp; 1686e307eb94SToomas Soome 1687e307eb94SToomas Soome data = (nvs_data_t *)nvl->nv_data; 1688e307eb94SToomas Soome nvp = &data->nvl_pair; /* first pair in nvlist */ 1689e307eb94SToomas Soome while (nvp->encoded_size != 0 && nvp->decoded_size != 0) { 1690e307eb94SToomas Soome nvpair_print(nvp, indent); 16913830659eSToomas Soome nvp = (nvp_header_t *)((uint8_t *)nvp + nvp->encoded_size); 16923830659eSToomas Soome } 16933830659eSToomas Soome printf("%*s\n", indent + 13, "End of nvlist"); 16943830659eSToomas Soome } 1695