1 1.1 haad /* 2 1.1 haad * CDDL HEADER START 3 1.1 haad * 4 1.1 haad * The contents of this file are subject to the terms of the 5 1.1 haad * Common Development and Distribution License (the "License"). 6 1.1 haad * You may not use this file except in compliance with the License. 7 1.1 haad * 8 1.1 haad * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 1.1 haad * or http://www.opensolaris.org/os/licensing. 10 1.1 haad * See the License for the specific language governing permissions 11 1.1 haad * and limitations under the License. 12 1.1 haad * 13 1.1 haad * When distributing Covered Code, include this CDDL HEADER in each 14 1.1 haad * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 1.1 haad * If applicable, add the following below this CDDL HEADER, with the 16 1.1 haad * fields enclosed by brackets "[]" replaced with your own identifying 17 1.1 haad * information: Portions Copyright [yyyy] [name of copyright owner] 18 1.1 haad * 19 1.1 haad * CDDL HEADER END 20 1.1 haad */ 21 1.1 haad 22 1.1 haad /* 23 1.4 chs * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. 24 1.1 haad */ 25 1.1 haad 26 1.1 haad #include <sys/debug.h> 27 1.1 haad #include <sys/nvpair.h> 28 1.1 haad #include <sys/nvpair_impl.h> 29 1.1 haad #include <rpc/types.h> 30 1.1 haad #include <rpc/xdr.h> 31 1.1 haad 32 1.1 haad #if defined(_KERNEL) && !defined(_BOOT) 33 1.7 nia #include <sys/endian.h> 34 1.1 haad #include <sys/varargs.h> 35 1.1 haad #include <sys/sunddi.h> 36 1.1 haad #else 37 1.7 nia #include <endian.h> 38 1.1 haad #include <stdarg.h> 39 1.1 haad #include <stdlib.h> 40 1.1 haad #include <string.h> 41 1.1 haad #include <strings.h> 42 1.1 haad #endif 43 1.1 haad 44 1.1 haad #ifndef offsetof 45 1.1 haad #define offsetof(s, m) ((size_t)(&(((s *)0)->m))) 46 1.1 haad #endif 47 1.1 haad #define skip_whitespace(p) while ((*(p) == ' ') || (*(p) == '\t')) p++ 48 1.1 haad 49 1.4 chs #if !defined(illumos) && !defined(_KERNEL) 50 1.4 chs /* 51 1.4 chs * libnvpair is the lowest commen denominator for ZFS related libraries, 52 1.4 chs * defining aok here makes it usable by all ZFS related libraries 53 1.4 chs */ 54 1.4 chs int aok; 55 1.4 chs #endif 56 1.4 chs 57 1.1 haad /* 58 1.1 haad * nvpair.c - Provides kernel & userland interfaces for manipulating 59 1.1 haad * name-value pairs. 60 1.1 haad * 61 1.1 haad * Overview Diagram 62 1.1 haad * 63 1.1 haad * +--------------+ 64 1.1 haad * | nvlist_t | 65 1.1 haad * |--------------| 66 1.1 haad * | nvl_version | 67 1.1 haad * | nvl_nvflag | 68 1.1 haad * | nvl_priv -+-+ 69 1.1 haad * | nvl_flag | | 70 1.1 haad * | nvl_pad | | 71 1.1 haad * +--------------+ | 72 1.1 haad * V 73 1.1 haad * +--------------+ last i_nvp in list 74 1.1 haad * | nvpriv_t | +---------------------> 75 1.1 haad * |--------------| | 76 1.1 haad * +--+- nvp_list | | +------------+ 77 1.1 haad * | | nvp_last -+--+ + nv_alloc_t | 78 1.1 haad * | | nvp_curr | |------------| 79 1.1 haad * | | nvp_nva -+----> | nva_ops | 80 1.1 haad * | | nvp_stat | | nva_arg | 81 1.1 haad * | +--------------+ +------------+ 82 1.1 haad * | 83 1.1 haad * +-------+ 84 1.1 haad * V 85 1.1 haad * +---------------------+ +-------------------+ 86 1.1 haad * | i_nvp_t | +-->| i_nvp_t | +--> 87 1.1 haad * |---------------------| | |-------------------| | 88 1.1 haad * | nvi_next -+--+ | nvi_next -+--+ 89 1.1 haad * | nvi_prev (NULL) | <----+ nvi_prev | 90 1.1 haad * | . . . . . . . . . . | | . . . . . . . . . | 91 1.1 haad * | nvp (nvpair_t) | | nvp (nvpair_t) | 92 1.1 haad * | - nvp_size | | - nvp_size | 93 1.1 haad * | - nvp_name_sz | | - nvp_name_sz | 94 1.1 haad * | - nvp_value_elem | | - nvp_value_elem | 95 1.1 haad * | - nvp_type | | - nvp_type | 96 1.1 haad * | - data ... | | - data ... | 97 1.1 haad * +---------------------+ +-------------------+ 98 1.1 haad * 99 1.1 haad * 100 1.1 haad * 101 1.1 haad * +---------------------+ +---------------------+ 102 1.1 haad * | i_nvp_t | +--> +-->| i_nvp_t (last) | 103 1.1 haad * |---------------------| | | |---------------------| 104 1.1 haad * | nvi_next -+--+ ... --+ | nvi_next (NULL) | 105 1.1 haad * <-+- nvi_prev |<-- ... <----+ nvi_prev | 106 1.1 haad * | . . . . . . . . . | | . . . . . . . . . | 107 1.1 haad * | nvp (nvpair_t) | | nvp (nvpair_t) | 108 1.1 haad * | - nvp_size | | - nvp_size | 109 1.1 haad * | - nvp_name_sz | | - nvp_name_sz | 110 1.1 haad * | - nvp_value_elem | | - nvp_value_elem | 111 1.1 haad * | - DATA_TYPE_NVLIST | | - nvp_type | 112 1.1 haad * | - data (embedded) | | - data ... | 113 1.1 haad * | nvlist name | +---------------------+ 114 1.1 haad * | +--------------+ | 115 1.1 haad * | | nvlist_t | | 116 1.1 haad * | |--------------| | 117 1.1 haad * | | nvl_version | | 118 1.1 haad * | | nvl_nvflag | | 119 1.1 haad * | | nvl_priv --+---+----> 120 1.1 haad * | | nvl_flag | | 121 1.1 haad * | | nvl_pad | | 122 1.1 haad * | +--------------+ | 123 1.1 haad * +---------------------+ 124 1.1 haad * 125 1.1 haad * 126 1.1 haad * N.B. nvpair_t may be aligned on 4 byte boundary, so +4 will 127 1.1 haad * allow value to be aligned on 8 byte boundary 128 1.1 haad * 129 1.1 haad * name_len is the length of the name string including the null terminator 130 1.1 haad * so it must be >= 1 131 1.1 haad */ 132 1.1 haad #define NVP_SIZE_CALC(name_len, data_len) \ 133 1.1 haad (NV_ALIGN((sizeof (nvpair_t)) + name_len) + NV_ALIGN(data_len)) 134 1.1 haad 135 1.1 haad static int i_get_value_size(data_type_t type, const void *data, uint_t nelem); 136 1.1 haad static int nvlist_add_common(nvlist_t *nvl, const char *name, data_type_t type, 137 1.1 haad uint_t nelem, const void *data); 138 1.1 haad 139 1.1 haad #define NV_STAT_EMBEDDED 0x1 140 1.1 haad #define EMBEDDED_NVL(nvp) ((nvlist_t *)(void *)NVP_VALUE(nvp)) 141 1.1 haad #define EMBEDDED_NVL_ARRAY(nvp) ((nvlist_t **)(void *)NVP_VALUE(nvp)) 142 1.1 haad 143 1.1 haad #define NVP_VALOFF(nvp) (NV_ALIGN(sizeof (nvpair_t) + (nvp)->nvp_name_sz)) 144 1.1 haad #define NVPAIR2I_NVP(nvp) \ 145 1.1 haad ((i_nvp_t *)((size_t)(nvp) - offsetof(i_nvp_t, nvi_nvp))) 146 1.1 haad 147 1.1 haad 148 1.7 nia #ifndef BYTE_ORDER 149 1.7 nia #error BYTE_ORDER is undefined! 150 1.7 nia #endif 151 1.7 nia 152 1.1 haad int 153 1.1 haad nv_alloc_init(nv_alloc_t *nva, const nv_alloc_ops_t *nvo, /* args */ ...) 154 1.1 haad { 155 1.1 haad va_list valist; 156 1.1 haad int err = 0; 157 1.1 haad 158 1.1 haad nva->nva_ops = nvo; 159 1.1 haad nva->nva_arg = NULL; 160 1.1 haad 161 1.1 haad va_start(valist, nvo); 162 1.1 haad if (nva->nva_ops->nv_ao_init != NULL) 163 1.1 haad err = nva->nva_ops->nv_ao_init(nva, valist); 164 1.1 haad va_end(valist); 165 1.1 haad 166 1.1 haad return (err); 167 1.1 haad } 168 1.1 haad 169 1.1 haad void 170 1.1 haad nv_alloc_reset(nv_alloc_t *nva) 171 1.1 haad { 172 1.1 haad if (nva->nva_ops->nv_ao_reset != NULL) 173 1.1 haad nva->nva_ops->nv_ao_reset(nva); 174 1.1 haad } 175 1.1 haad 176 1.1 haad void 177 1.1 haad nv_alloc_fini(nv_alloc_t *nva) 178 1.1 haad { 179 1.1 haad if (nva->nva_ops->nv_ao_fini != NULL) 180 1.1 haad nva->nva_ops->nv_ao_fini(nva); 181 1.1 haad } 182 1.1 haad 183 1.1 haad nv_alloc_t * 184 1.1 haad nvlist_lookup_nv_alloc(nvlist_t *nvl) 185 1.1 haad { 186 1.1 haad nvpriv_t *priv; 187 1.1 haad 188 1.1 haad if (nvl == NULL || 189 1.1 haad (priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv) == NULL) 190 1.1 haad return (NULL); 191 1.1 haad 192 1.1 haad return (priv->nvp_nva); 193 1.1 haad } 194 1.1 haad 195 1.1 haad static void * 196 1.1 haad nv_mem_zalloc(nvpriv_t *nvp, size_t size) 197 1.1 haad { 198 1.1 haad nv_alloc_t *nva = nvp->nvp_nva; 199 1.1 haad void *buf; 200 1.1 haad 201 1.1 haad if ((buf = nva->nva_ops->nv_ao_alloc(nva, size)) != NULL) 202 1.1 haad bzero(buf, size); 203 1.1 haad 204 1.1 haad return (buf); 205 1.1 haad } 206 1.1 haad 207 1.1 haad static void 208 1.1 haad nv_mem_free(nvpriv_t *nvp, void *buf, size_t size) 209 1.1 haad { 210 1.1 haad nv_alloc_t *nva = nvp->nvp_nva; 211 1.1 haad 212 1.1 haad nva->nva_ops->nv_ao_free(nva, buf, size); 213 1.1 haad } 214 1.1 haad 215 1.1 haad static void 216 1.1 haad nv_priv_init(nvpriv_t *priv, nv_alloc_t *nva, uint32_t stat) 217 1.1 haad { 218 1.1 haad bzero(priv, sizeof (nvpriv_t)); 219 1.1 haad 220 1.1 haad priv->nvp_nva = nva; 221 1.1 haad priv->nvp_stat = stat; 222 1.1 haad } 223 1.1 haad 224 1.1 haad static nvpriv_t * 225 1.1 haad nv_priv_alloc(nv_alloc_t *nva) 226 1.1 haad { 227 1.1 haad nvpriv_t *priv; 228 1.1 haad 229 1.1 haad /* 230 1.1 haad * nv_mem_alloc() cannot called here because it needs the priv 231 1.1 haad * argument. 232 1.1 haad */ 233 1.1 haad if ((priv = nva->nva_ops->nv_ao_alloc(nva, sizeof (nvpriv_t))) == NULL) 234 1.1 haad return (NULL); 235 1.1 haad 236 1.1 haad nv_priv_init(priv, nva, 0); 237 1.1 haad 238 1.1 haad return (priv); 239 1.1 haad } 240 1.1 haad 241 1.1 haad /* 242 1.1 haad * Embedded lists need their own nvpriv_t's. We create a new 243 1.1 haad * nvpriv_t using the parameters and allocator from the parent 244 1.1 haad * list's nvpriv_t. 245 1.1 haad */ 246 1.1 haad static nvpriv_t * 247 1.1 haad nv_priv_alloc_embedded(nvpriv_t *priv) 248 1.1 haad { 249 1.1 haad nvpriv_t *emb_priv; 250 1.1 haad 251 1.1 haad if ((emb_priv = nv_mem_zalloc(priv, sizeof (nvpriv_t))) == NULL) 252 1.1 haad return (NULL); 253 1.1 haad 254 1.1 haad nv_priv_init(emb_priv, priv->nvp_nva, NV_STAT_EMBEDDED); 255 1.1 haad 256 1.1 haad return (emb_priv); 257 1.1 haad } 258 1.1 haad 259 1.1 haad static void 260 1.1 haad nvlist_init(nvlist_t *nvl, uint32_t nvflag, nvpriv_t *priv) 261 1.1 haad { 262 1.1 haad nvl->nvl_version = NV_VERSION; 263 1.1 haad nvl->nvl_nvflag = nvflag & (NV_UNIQUE_NAME|NV_UNIQUE_NAME_TYPE); 264 1.1 haad nvl->nvl_priv = (uint64_t)(uintptr_t)priv; 265 1.1 haad nvl->nvl_flag = 0; 266 1.1 haad nvl->nvl_pad = 0; 267 1.1 haad } 268 1.1 haad 269 1.1 haad /* 270 1.1 haad * nvlist_alloc - Allocate nvlist. 271 1.1 haad */ 272 1.1 haad /*ARGSUSED1*/ 273 1.1 haad int 274 1.1 haad nvlist_alloc(nvlist_t **nvlp, uint_t nvflag, int kmflag) 275 1.1 haad { 276 1.1 haad #if defined(_KERNEL) && !defined(_BOOT) 277 1.1 haad return (nvlist_xalloc(nvlp, nvflag, 278 1.1 haad (kmflag == KM_SLEEP ? nv_alloc_sleep : nv_alloc_nosleep))); 279 1.1 haad #else 280 1.1 haad return (nvlist_xalloc(nvlp, nvflag, nv_alloc_nosleep)); 281 1.1 haad #endif 282 1.1 haad } 283 1.1 haad 284 1.1 haad int 285 1.1 haad nvlist_xalloc(nvlist_t **nvlp, uint_t nvflag, nv_alloc_t *nva) 286 1.1 haad { 287 1.1 haad nvpriv_t *priv; 288 1.1 haad 289 1.1 haad if (nvlp == NULL || nva == NULL) 290 1.1 haad return (EINVAL); 291 1.1 haad 292 1.1 haad if ((priv = nv_priv_alloc(nva)) == NULL) 293 1.1 haad return (ENOMEM); 294 1.1 haad 295 1.1 haad if ((*nvlp = nv_mem_zalloc(priv, 296 1.1 haad NV_ALIGN(sizeof (nvlist_t)))) == NULL) { 297 1.1 haad nv_mem_free(priv, priv, sizeof (nvpriv_t)); 298 1.1 haad return (ENOMEM); 299 1.1 haad } 300 1.1 haad 301 1.1 haad nvlist_init(*nvlp, nvflag, priv); 302 1.1 haad 303 1.1 haad return (0); 304 1.1 haad } 305 1.1 haad 306 1.1 haad /* 307 1.1 haad * nvp_buf_alloc - Allocate i_nvp_t for storing a new nv pair. 308 1.1 haad */ 309 1.1 haad static nvpair_t * 310 1.1 haad nvp_buf_alloc(nvlist_t *nvl, size_t len) 311 1.1 haad { 312 1.1 haad nvpriv_t *priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv; 313 1.1 haad i_nvp_t *buf; 314 1.1 haad nvpair_t *nvp; 315 1.1 haad size_t nvsize; 316 1.1 haad 317 1.1 haad /* 318 1.1 haad * Allocate the buffer 319 1.1 haad */ 320 1.1 haad nvsize = len + offsetof(i_nvp_t, nvi_nvp); 321 1.1 haad 322 1.1 haad if ((buf = nv_mem_zalloc(priv, nvsize)) == NULL) 323 1.1 haad return (NULL); 324 1.1 haad 325 1.1 haad nvp = &buf->nvi_nvp; 326 1.1 haad nvp->nvp_size = len; 327 1.1 haad 328 1.1 haad return (nvp); 329 1.1 haad } 330 1.1 haad 331 1.1 haad /* 332 1.1 haad * nvp_buf_free - de-Allocate an i_nvp_t. 333 1.1 haad */ 334 1.1 haad static void 335 1.1 haad nvp_buf_free(nvlist_t *nvl, nvpair_t *nvp) 336 1.1 haad { 337 1.1 haad nvpriv_t *priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv; 338 1.1 haad size_t nvsize = nvp->nvp_size + offsetof(i_nvp_t, nvi_nvp); 339 1.1 haad 340 1.1 haad nv_mem_free(priv, NVPAIR2I_NVP(nvp), nvsize); 341 1.1 haad } 342 1.1 haad 343 1.1 haad /* 344 1.1 haad * nvp_buf_link - link a new nv pair into the nvlist. 345 1.1 haad */ 346 1.1 haad static void 347 1.1 haad nvp_buf_link(nvlist_t *nvl, nvpair_t *nvp) 348 1.1 haad { 349 1.1 haad nvpriv_t *priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv; 350 1.1 haad i_nvp_t *curr = NVPAIR2I_NVP(nvp); 351 1.1 haad 352 1.1 haad /* Put element at end of nvlist */ 353 1.1 haad if (priv->nvp_list == NULL) { 354 1.1 haad priv->nvp_list = priv->nvp_last = curr; 355 1.1 haad } else { 356 1.1 haad curr->nvi_prev = priv->nvp_last; 357 1.1 haad priv->nvp_last->nvi_next = curr; 358 1.1 haad priv->nvp_last = curr; 359 1.1 haad } 360 1.1 haad } 361 1.1 haad 362 1.1 haad /* 363 1.1 haad * nvp_buf_unlink - unlink an removed nvpair out of the nvlist. 364 1.1 haad */ 365 1.1 haad static void 366 1.1 haad nvp_buf_unlink(nvlist_t *nvl, nvpair_t *nvp) 367 1.1 haad { 368 1.1 haad nvpriv_t *priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv; 369 1.1 haad i_nvp_t *curr = NVPAIR2I_NVP(nvp); 370 1.1 haad 371 1.1 haad /* 372 1.1 haad * protect nvlist_next_nvpair() against walking on freed memory. 373 1.1 haad */ 374 1.1 haad if (priv->nvp_curr == curr) 375 1.1 haad priv->nvp_curr = curr->nvi_next; 376 1.1 haad 377 1.1 haad if (curr == priv->nvp_list) 378 1.1 haad priv->nvp_list = curr->nvi_next; 379 1.1 haad else 380 1.1 haad curr->nvi_prev->nvi_next = curr->nvi_next; 381 1.1 haad 382 1.1 haad if (curr == priv->nvp_last) 383 1.1 haad priv->nvp_last = curr->nvi_prev; 384 1.1 haad else 385 1.1 haad curr->nvi_next->nvi_prev = curr->nvi_prev; 386 1.1 haad } 387 1.1 haad 388 1.1 haad /* 389 1.1 haad * take a nvpair type and number of elements and make sure the are valid 390 1.1 haad */ 391 1.1 haad static int 392 1.1 haad i_validate_type_nelem(data_type_t type, uint_t nelem) 393 1.1 haad { 394 1.1 haad switch (type) { 395 1.1 haad case DATA_TYPE_BOOLEAN: 396 1.1 haad if (nelem != 0) 397 1.1 haad return (EINVAL); 398 1.1 haad break; 399 1.1 haad case DATA_TYPE_BOOLEAN_VALUE: 400 1.1 haad case DATA_TYPE_BYTE: 401 1.1 haad case DATA_TYPE_INT8: 402 1.1 haad case DATA_TYPE_UINT8: 403 1.1 haad case DATA_TYPE_INT16: 404 1.1 haad case DATA_TYPE_UINT16: 405 1.1 haad case DATA_TYPE_INT32: 406 1.1 haad case DATA_TYPE_UINT32: 407 1.1 haad case DATA_TYPE_INT64: 408 1.1 haad case DATA_TYPE_UINT64: 409 1.1 haad case DATA_TYPE_STRING: 410 1.1 haad case DATA_TYPE_HRTIME: 411 1.1 haad case DATA_TYPE_NVLIST: 412 1.1 haad #if !defined(_KERNEL) 413 1.1 haad case DATA_TYPE_DOUBLE: 414 1.1 haad #endif 415 1.1 haad if (nelem != 1) 416 1.1 haad return (EINVAL); 417 1.1 haad break; 418 1.1 haad case DATA_TYPE_BOOLEAN_ARRAY: 419 1.1 haad case DATA_TYPE_BYTE_ARRAY: 420 1.1 haad case DATA_TYPE_INT8_ARRAY: 421 1.1 haad case DATA_TYPE_UINT8_ARRAY: 422 1.1 haad case DATA_TYPE_INT16_ARRAY: 423 1.1 haad case DATA_TYPE_UINT16_ARRAY: 424 1.1 haad case DATA_TYPE_INT32_ARRAY: 425 1.1 haad case DATA_TYPE_UINT32_ARRAY: 426 1.1 haad case DATA_TYPE_INT64_ARRAY: 427 1.1 haad case DATA_TYPE_UINT64_ARRAY: 428 1.1 haad case DATA_TYPE_STRING_ARRAY: 429 1.1 haad case DATA_TYPE_NVLIST_ARRAY: 430 1.1 haad /* we allow arrays with 0 elements */ 431 1.1 haad break; 432 1.1 haad default: 433 1.1 haad return (EINVAL); 434 1.1 haad } 435 1.1 haad return (0); 436 1.1 haad } 437 1.1 haad 438 1.1 haad /* 439 1.1 haad * Verify nvp_name_sz and check the name string length. 440 1.1 haad */ 441 1.1 haad static int 442 1.1 haad i_validate_nvpair_name(nvpair_t *nvp) 443 1.1 haad { 444 1.1 haad if ((nvp->nvp_name_sz <= 0) || 445 1.1 haad (nvp->nvp_size < NVP_SIZE_CALC(nvp->nvp_name_sz, 0))) 446 1.1 haad return (EFAULT); 447 1.1 haad 448 1.1 haad /* verify the name string, make sure its terminated */ 449 1.1 haad if (NVP_NAME(nvp)[nvp->nvp_name_sz - 1] != '\0') 450 1.1 haad return (EFAULT); 451 1.1 haad 452 1.1 haad return (strlen(NVP_NAME(nvp)) == nvp->nvp_name_sz - 1 ? 0 : EFAULT); 453 1.1 haad } 454 1.1 haad 455 1.1 haad static int 456 1.1 haad i_validate_nvpair_value(data_type_t type, uint_t nelem, const void *data) 457 1.1 haad { 458 1.1 haad switch (type) { 459 1.1 haad case DATA_TYPE_BOOLEAN_VALUE: 460 1.1 haad if (*(boolean_t *)data != B_TRUE && 461 1.1 haad *(boolean_t *)data != B_FALSE) 462 1.1 haad return (EINVAL); 463 1.1 haad break; 464 1.1 haad case DATA_TYPE_BOOLEAN_ARRAY: { 465 1.1 haad int i; 466 1.1 haad 467 1.1 haad for (i = 0; i < nelem; i++) 468 1.1 haad if (((boolean_t *)data)[i] != B_TRUE && 469 1.1 haad ((boolean_t *)data)[i] != B_FALSE) 470 1.1 haad return (EINVAL); 471 1.1 haad break; 472 1.1 haad } 473 1.1 haad default: 474 1.1 haad break; 475 1.1 haad } 476 1.1 haad 477 1.1 haad return (0); 478 1.1 haad } 479 1.1 haad 480 1.1 haad /* 481 1.1 haad * This function takes a pointer to what should be a nvpair and it's size 482 1.1 haad * and then verifies that all the nvpair fields make sense and can be 483 1.1 haad * trusted. This function is used when decoding packed nvpairs. 484 1.1 haad */ 485 1.1 haad static int 486 1.1 haad i_validate_nvpair(nvpair_t *nvp) 487 1.1 haad { 488 1.1 haad data_type_t type = NVP_TYPE(nvp); 489 1.1 haad int size1, size2; 490 1.1 haad 491 1.1 haad /* verify nvp_name_sz, check the name string length */ 492 1.1 haad if (i_validate_nvpair_name(nvp) != 0) 493 1.1 haad return (EFAULT); 494 1.1 haad 495 1.1 haad if (i_validate_nvpair_value(type, NVP_NELEM(nvp), NVP_VALUE(nvp)) != 0) 496 1.1 haad return (EFAULT); 497 1.1 haad 498 1.1 haad /* 499 1.1 haad * verify nvp_type, nvp_value_elem, and also possibly 500 1.1 haad * verify string values and get the value size. 501 1.1 haad */ 502 1.1 haad size2 = i_get_value_size(type, NVP_VALUE(nvp), NVP_NELEM(nvp)); 503 1.1 haad size1 = nvp->nvp_size - NVP_VALOFF(nvp); 504 1.1 haad if (size2 < 0 || size1 != NV_ALIGN(size2)) 505 1.1 haad return (EFAULT); 506 1.1 haad 507 1.1 haad return (0); 508 1.1 haad } 509 1.1 haad 510 1.1 haad static int 511 1.1 haad nvlist_copy_pairs(nvlist_t *snvl, nvlist_t *dnvl) 512 1.1 haad { 513 1.1 haad nvpriv_t *priv; 514 1.1 haad i_nvp_t *curr; 515 1.1 haad 516 1.1 haad if ((priv = (nvpriv_t *)(uintptr_t)snvl->nvl_priv) == NULL) 517 1.1 haad return (EINVAL); 518 1.1 haad 519 1.1 haad for (curr = priv->nvp_list; curr != NULL; curr = curr->nvi_next) { 520 1.1 haad nvpair_t *nvp = &curr->nvi_nvp; 521 1.1 haad int err; 522 1.1 haad 523 1.1 haad if ((err = nvlist_add_common(dnvl, NVP_NAME(nvp), NVP_TYPE(nvp), 524 1.1 haad NVP_NELEM(nvp), NVP_VALUE(nvp))) != 0) 525 1.1 haad return (err); 526 1.1 haad } 527 1.1 haad 528 1.1 haad return (0); 529 1.1 haad } 530 1.1 haad 531 1.1 haad /* 532 1.1 haad * Frees all memory allocated for an nvpair (like embedded lists) with 533 1.1 haad * the exception of the nvpair buffer itself. 534 1.1 haad */ 535 1.1 haad static void 536 1.1 haad nvpair_free(nvpair_t *nvp) 537 1.1 haad { 538 1.1 haad switch (NVP_TYPE(nvp)) { 539 1.1 haad case DATA_TYPE_NVLIST: 540 1.1 haad nvlist_free(EMBEDDED_NVL(nvp)); 541 1.1 haad break; 542 1.1 haad case DATA_TYPE_NVLIST_ARRAY: { 543 1.1 haad nvlist_t **nvlp = EMBEDDED_NVL_ARRAY(nvp); 544 1.1 haad int i; 545 1.1 haad 546 1.1 haad for (i = 0; i < NVP_NELEM(nvp); i++) 547 1.4 chs nvlist_free(nvlp[i]); 548 1.1 haad break; 549 1.1 haad } 550 1.1 haad default: 551 1.1 haad break; 552 1.1 haad } 553 1.1 haad } 554 1.1 haad 555 1.1 haad /* 556 1.1 haad * nvlist_free - free an unpacked nvlist 557 1.1 haad */ 558 1.1 haad void 559 1.1 haad nvlist_free(nvlist_t *nvl) 560 1.1 haad { 561 1.1 haad nvpriv_t *priv; 562 1.1 haad i_nvp_t *curr; 563 1.1 haad 564 1.1 haad if (nvl == NULL || 565 1.1 haad (priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv) == NULL) 566 1.1 haad return; 567 1.1 haad 568 1.1 haad /* 569 1.1 haad * Unpacked nvlist are linked through i_nvp_t 570 1.1 haad */ 571 1.1 haad curr = priv->nvp_list; 572 1.1 haad while (curr != NULL) { 573 1.1 haad nvpair_t *nvp = &curr->nvi_nvp; 574 1.1 haad curr = curr->nvi_next; 575 1.1 haad 576 1.1 haad nvpair_free(nvp); 577 1.1 haad nvp_buf_free(nvl, nvp); 578 1.1 haad } 579 1.1 haad 580 1.1 haad if (!(priv->nvp_stat & NV_STAT_EMBEDDED)) 581 1.1 haad nv_mem_free(priv, nvl, NV_ALIGN(sizeof (nvlist_t))); 582 1.1 haad else 583 1.1 haad nvl->nvl_priv = 0; 584 1.1 haad 585 1.1 haad nv_mem_free(priv, priv, sizeof (nvpriv_t)); 586 1.1 haad } 587 1.1 haad 588 1.1 haad static int 589 1.1 haad nvlist_contains_nvp(nvlist_t *nvl, nvpair_t *nvp) 590 1.1 haad { 591 1.1 haad nvpriv_t *priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv; 592 1.1 haad i_nvp_t *curr; 593 1.1 haad 594 1.1 haad if (nvp == NULL) 595 1.1 haad return (0); 596 1.1 haad 597 1.1 haad for (curr = priv->nvp_list; curr != NULL; curr = curr->nvi_next) 598 1.1 haad if (&curr->nvi_nvp == nvp) 599 1.1 haad return (1); 600 1.1 haad 601 1.1 haad return (0); 602 1.1 haad } 603 1.1 haad 604 1.1 haad /* 605 1.1 haad * Make a copy of nvlist 606 1.1 haad */ 607 1.1 haad /*ARGSUSED1*/ 608 1.1 haad int 609 1.1 haad nvlist_dup(nvlist_t *nvl, nvlist_t **nvlp, int kmflag) 610 1.1 haad { 611 1.1 haad #if defined(_KERNEL) && !defined(_BOOT) 612 1.1 haad return (nvlist_xdup(nvl, nvlp, 613 1.1 haad (kmflag == KM_SLEEP ? nv_alloc_sleep : nv_alloc_nosleep))); 614 1.1 haad #else 615 1.1 haad return (nvlist_xdup(nvl, nvlp, nv_alloc_nosleep)); 616 1.1 haad #endif 617 1.1 haad } 618 1.1 haad 619 1.1 haad int 620 1.1 haad nvlist_xdup(nvlist_t *nvl, nvlist_t **nvlp, nv_alloc_t *nva) 621 1.1 haad { 622 1.1 haad int err; 623 1.1 haad nvlist_t *ret; 624 1.1 haad 625 1.1 haad if (nvl == NULL || nvlp == NULL) 626 1.1 haad return (EINVAL); 627 1.1 haad 628 1.1 haad if ((err = nvlist_xalloc(&ret, nvl->nvl_nvflag, nva)) != 0) 629 1.1 haad return (err); 630 1.1 haad 631 1.1 haad if ((err = nvlist_copy_pairs(nvl, ret)) != 0) 632 1.1 haad nvlist_free(ret); 633 1.1 haad else 634 1.1 haad *nvlp = ret; 635 1.1 haad 636 1.1 haad return (err); 637 1.1 haad } 638 1.1 haad 639 1.1 haad /* 640 1.1 haad * Remove all with matching name 641 1.1 haad */ 642 1.1 haad int 643 1.1 haad nvlist_remove_all(nvlist_t *nvl, const char *name) 644 1.1 haad { 645 1.1 haad nvpriv_t *priv; 646 1.1 haad i_nvp_t *curr; 647 1.1 haad int error = ENOENT; 648 1.1 haad 649 1.1 haad if (nvl == NULL || name == NULL || 650 1.1 haad (priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv) == NULL) 651 1.1 haad return (EINVAL); 652 1.1 haad 653 1.1 haad curr = priv->nvp_list; 654 1.1 haad while (curr != NULL) { 655 1.1 haad nvpair_t *nvp = &curr->nvi_nvp; 656 1.1 haad 657 1.1 haad curr = curr->nvi_next; 658 1.1 haad if (strcmp(name, NVP_NAME(nvp)) != 0) 659 1.1 haad continue; 660 1.1 haad 661 1.1 haad nvp_buf_unlink(nvl, nvp); 662 1.1 haad nvpair_free(nvp); 663 1.1 haad nvp_buf_free(nvl, nvp); 664 1.1 haad 665 1.1 haad error = 0; 666 1.1 haad } 667 1.1 haad 668 1.1 haad return (error); 669 1.1 haad } 670 1.1 haad 671 1.1 haad /* 672 1.1 haad * Remove first one with matching name and type 673 1.1 haad */ 674 1.1 haad int 675 1.1 haad nvlist_remove(nvlist_t *nvl, const char *name, data_type_t type) 676 1.1 haad { 677 1.1 haad nvpriv_t *priv; 678 1.1 haad i_nvp_t *curr; 679 1.1 haad 680 1.1 haad if (nvl == NULL || name == NULL || 681 1.1 haad (priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv) == NULL) 682 1.1 haad return (EINVAL); 683 1.1 haad 684 1.1 haad curr = priv->nvp_list; 685 1.1 haad while (curr != NULL) { 686 1.1 haad nvpair_t *nvp = &curr->nvi_nvp; 687 1.1 haad 688 1.1 haad if (strcmp(name, NVP_NAME(nvp)) == 0 && NVP_TYPE(nvp) == type) { 689 1.1 haad nvp_buf_unlink(nvl, nvp); 690 1.1 haad nvpair_free(nvp); 691 1.1 haad nvp_buf_free(nvl, nvp); 692 1.1 haad 693 1.1 haad return (0); 694 1.1 haad } 695 1.1 haad curr = curr->nvi_next; 696 1.1 haad } 697 1.1 haad 698 1.1 haad return (ENOENT); 699 1.1 haad } 700 1.1 haad 701 1.2 dsl int 702 1.2 dsl nvlist_remove_nvpair(nvlist_t *nvl, nvpair_t *nvp) 703 1.2 dsl { 704 1.2 dsl if (nvl == NULL || nvp == NULL) 705 1.2 dsl return (EINVAL); 706 1.2 dsl 707 1.2 dsl nvp_buf_unlink(nvl, nvp); 708 1.2 dsl nvpair_free(nvp); 709 1.2 dsl nvp_buf_free(nvl, nvp); 710 1.2 dsl return (0); 711 1.2 dsl } 712 1.2 dsl 713 1.1 haad /* 714 1.1 haad * This function calculates the size of an nvpair value. 715 1.1 haad * 716 1.1 haad * The data argument controls the behavior in case of the data types 717 1.1 haad * DATA_TYPE_STRING and 718 1.1 haad * DATA_TYPE_STRING_ARRAY 719 1.1 haad * Is data == NULL then the size of the string(s) is excluded. 720 1.1 haad */ 721 1.1 haad static int 722 1.1 haad i_get_value_size(data_type_t type, const void *data, uint_t nelem) 723 1.1 haad { 724 1.1 haad uint64_t value_sz; 725 1.1 haad 726 1.1 haad if (i_validate_type_nelem(type, nelem) != 0) 727 1.1 haad return (-1); 728 1.1 haad 729 1.1 haad /* Calculate required size for holding value */ 730 1.1 haad switch (type) { 731 1.1 haad case DATA_TYPE_BOOLEAN: 732 1.1 haad value_sz = 0; 733 1.1 haad break; 734 1.1 haad case DATA_TYPE_BOOLEAN_VALUE: 735 1.1 haad value_sz = sizeof (boolean_t); 736 1.1 haad break; 737 1.1 haad case DATA_TYPE_BYTE: 738 1.1 haad value_sz = sizeof (uchar_t); 739 1.1 haad break; 740 1.1 haad case DATA_TYPE_INT8: 741 1.1 haad value_sz = sizeof (int8_t); 742 1.1 haad break; 743 1.1 haad case DATA_TYPE_UINT8: 744 1.1 haad value_sz = sizeof (uint8_t); 745 1.1 haad break; 746 1.1 haad case DATA_TYPE_INT16: 747 1.1 haad value_sz = sizeof (int16_t); 748 1.1 haad break; 749 1.1 haad case DATA_TYPE_UINT16: 750 1.1 haad value_sz = sizeof (uint16_t); 751 1.1 haad break; 752 1.1 haad case DATA_TYPE_INT32: 753 1.1 haad value_sz = sizeof (int32_t); 754 1.1 haad break; 755 1.1 haad case DATA_TYPE_UINT32: 756 1.1 haad value_sz = sizeof (uint32_t); 757 1.1 haad break; 758 1.1 haad case DATA_TYPE_INT64: 759 1.1 haad value_sz = sizeof (int64_t); 760 1.1 haad break; 761 1.1 haad case DATA_TYPE_UINT64: 762 1.1 haad value_sz = sizeof (uint64_t); 763 1.1 haad break; 764 1.1 haad #if !defined(_KERNEL) 765 1.1 haad case DATA_TYPE_DOUBLE: 766 1.1 haad value_sz = sizeof (double); 767 1.1 haad break; 768 1.1 haad #endif 769 1.1 haad case DATA_TYPE_STRING: 770 1.1 haad if (data == NULL) 771 1.1 haad value_sz = 0; 772 1.1 haad else 773 1.1 haad value_sz = strlen(data) + 1; 774 1.1 haad break; 775 1.1 haad case DATA_TYPE_BOOLEAN_ARRAY: 776 1.1 haad value_sz = (uint64_t)nelem * sizeof (boolean_t); 777 1.1 haad break; 778 1.1 haad case DATA_TYPE_BYTE_ARRAY: 779 1.1 haad value_sz = (uint64_t)nelem * sizeof (uchar_t); 780 1.1 haad break; 781 1.1 haad case DATA_TYPE_INT8_ARRAY: 782 1.1 haad value_sz = (uint64_t)nelem * sizeof (int8_t); 783 1.1 haad break; 784 1.1 haad case DATA_TYPE_UINT8_ARRAY: 785 1.1 haad value_sz = (uint64_t)nelem * sizeof (uint8_t); 786 1.1 haad break; 787 1.1 haad case DATA_TYPE_INT16_ARRAY: 788 1.1 haad value_sz = (uint64_t)nelem * sizeof (int16_t); 789 1.1 haad break; 790 1.1 haad case DATA_TYPE_UINT16_ARRAY: 791 1.1 haad value_sz = (uint64_t)nelem * sizeof (uint16_t); 792 1.1 haad break; 793 1.1 haad case DATA_TYPE_INT32_ARRAY: 794 1.1 haad value_sz = (uint64_t)nelem * sizeof (int32_t); 795 1.1 haad break; 796 1.1 haad case DATA_TYPE_UINT32_ARRAY: 797 1.1 haad value_sz = (uint64_t)nelem * sizeof (uint32_t); 798 1.1 haad break; 799 1.1 haad case DATA_TYPE_INT64_ARRAY: 800 1.1 haad value_sz = (uint64_t)nelem * sizeof (int64_t); 801 1.1 haad break; 802 1.1 haad case DATA_TYPE_UINT64_ARRAY: 803 1.1 haad value_sz = (uint64_t)nelem * sizeof (uint64_t); 804 1.1 haad break; 805 1.1 haad case DATA_TYPE_STRING_ARRAY: 806 1.1 haad value_sz = (uint64_t)nelem * sizeof (uint64_t); 807 1.1 haad 808 1.1 haad if (data != NULL) { 809 1.1 haad char *const *strs = data; 810 1.1 haad uint_t i; 811 1.1 haad 812 1.1 haad /* no alignment requirement for strings */ 813 1.1 haad for (i = 0; i < nelem; i++) { 814 1.1 haad if (strs[i] == NULL) 815 1.1 haad return (-1); 816 1.1 haad value_sz += strlen(strs[i]) + 1; 817 1.1 haad } 818 1.1 haad } 819 1.1 haad break; 820 1.1 haad case DATA_TYPE_HRTIME: 821 1.1 haad value_sz = sizeof (hrtime_t); 822 1.1 haad break; 823 1.1 haad case DATA_TYPE_NVLIST: 824 1.1 haad value_sz = NV_ALIGN(sizeof (nvlist_t)); 825 1.1 haad break; 826 1.1 haad case DATA_TYPE_NVLIST_ARRAY: 827 1.1 haad value_sz = (uint64_t)nelem * sizeof (uint64_t) + 828 1.1 haad (uint64_t)nelem * NV_ALIGN(sizeof (nvlist_t)); 829 1.1 haad break; 830 1.1 haad default: 831 1.1 haad return (-1); 832 1.1 haad } 833 1.1 haad 834 1.1 haad return (value_sz > INT32_MAX ? -1 : (int)value_sz); 835 1.1 haad } 836 1.1 haad 837 1.1 haad static int 838 1.1 haad nvlist_copy_embedded(nvlist_t *nvl, nvlist_t *onvl, nvlist_t *emb_nvl) 839 1.1 haad { 840 1.1 haad nvpriv_t *priv; 841 1.1 haad int err; 842 1.1 haad 843 1.1 haad if ((priv = nv_priv_alloc_embedded((nvpriv_t *)(uintptr_t) 844 1.1 haad nvl->nvl_priv)) == NULL) 845 1.1 haad return (ENOMEM); 846 1.1 haad 847 1.1 haad nvlist_init(emb_nvl, onvl->nvl_nvflag, priv); 848 1.1 haad 849 1.1 haad if ((err = nvlist_copy_pairs(onvl, emb_nvl)) != 0) { 850 1.1 haad nvlist_free(emb_nvl); 851 1.1 haad emb_nvl->nvl_priv = 0; 852 1.1 haad } 853 1.1 haad 854 1.1 haad return (err); 855 1.1 haad } 856 1.1 haad 857 1.1 haad /* 858 1.1 haad * nvlist_add_common - Add new <name,value> pair to nvlist 859 1.1 haad */ 860 1.1 haad static int 861 1.1 haad nvlist_add_common(nvlist_t *nvl, const char *name, 862 1.1 haad data_type_t type, uint_t nelem, const void *data) 863 1.1 haad { 864 1.1 haad nvpair_t *nvp; 865 1.1 haad uint_t i; 866 1.1 haad 867 1.1 haad int nvp_sz, name_sz, value_sz; 868 1.1 haad int err = 0; 869 1.1 haad 870 1.1 haad if (name == NULL || nvl == NULL || nvl->nvl_priv == 0) 871 1.1 haad return (EINVAL); 872 1.1 haad 873 1.1 haad if (nelem != 0 && data == NULL) 874 1.1 haad return (EINVAL); 875 1.1 haad 876 1.1 haad /* 877 1.1 haad * Verify type and nelem and get the value size. 878 1.1 haad * In case of data types DATA_TYPE_STRING and DATA_TYPE_STRING_ARRAY 879 1.1 haad * is the size of the string(s) included. 880 1.1 haad */ 881 1.1 haad if ((value_sz = i_get_value_size(type, data, nelem)) < 0) 882 1.1 haad return (EINVAL); 883 1.1 haad 884 1.1 haad if (i_validate_nvpair_value(type, nelem, data) != 0) 885 1.1 haad return (EINVAL); 886 1.1 haad 887 1.1 haad /* 888 1.1 haad * If we're adding an nvlist or nvlist array, ensure that we are not 889 1.1 haad * adding the input nvlist to itself, which would cause recursion, 890 1.1 haad * and ensure that no NULL nvlist pointers are present. 891 1.1 haad */ 892 1.1 haad switch (type) { 893 1.1 haad case DATA_TYPE_NVLIST: 894 1.1 haad if (data == nvl || data == NULL) 895 1.1 haad return (EINVAL); 896 1.1 haad break; 897 1.1 haad case DATA_TYPE_NVLIST_ARRAY: { 898 1.1 haad nvlist_t **onvlp = (nvlist_t **)data; 899 1.1 haad for (i = 0; i < nelem; i++) { 900 1.1 haad if (onvlp[i] == nvl || onvlp[i] == NULL) 901 1.1 haad return (EINVAL); 902 1.1 haad } 903 1.1 haad break; 904 1.1 haad } 905 1.1 haad default: 906 1.1 haad break; 907 1.1 haad } 908 1.1 haad 909 1.1 haad /* calculate sizes of the nvpair elements and the nvpair itself */ 910 1.1 haad name_sz = strlen(name) + 1; 911 1.1 haad 912 1.1 haad nvp_sz = NVP_SIZE_CALC(name_sz, value_sz); 913 1.1 haad 914 1.1 haad if ((nvp = nvp_buf_alloc(nvl, nvp_sz)) == NULL) 915 1.1 haad return (ENOMEM); 916 1.1 haad 917 1.1 haad ASSERT(nvp->nvp_size == nvp_sz); 918 1.1 haad nvp->nvp_name_sz = name_sz; 919 1.1 haad nvp->nvp_value_elem = nelem; 920 1.1 haad nvp->nvp_type = type; 921 1.1 haad bcopy(name, NVP_NAME(nvp), name_sz); 922 1.1 haad 923 1.1 haad switch (type) { 924 1.1 haad case DATA_TYPE_BOOLEAN: 925 1.1 haad break; 926 1.1 haad case DATA_TYPE_STRING_ARRAY: { 927 1.1 haad char *const *strs = data; 928 1.1 haad char *buf = NVP_VALUE(nvp); 929 1.1 haad char **cstrs = (void *)buf; 930 1.1 haad 931 1.1 haad /* skip pre-allocated space for pointer array */ 932 1.1 haad buf += nelem * sizeof (uint64_t); 933 1.1 haad for (i = 0; i < nelem; i++) { 934 1.1 haad int slen = strlen(strs[i]) + 1; 935 1.1 haad bcopy(strs[i], buf, slen); 936 1.1 haad cstrs[i] = buf; 937 1.1 haad buf += slen; 938 1.1 haad } 939 1.1 haad break; 940 1.1 haad } 941 1.1 haad case DATA_TYPE_NVLIST: { 942 1.1 haad nvlist_t *nnvl = EMBEDDED_NVL(nvp); 943 1.1 haad nvlist_t *onvl = (nvlist_t *)data; 944 1.1 haad 945 1.1 haad if ((err = nvlist_copy_embedded(nvl, onvl, nnvl)) != 0) { 946 1.1 haad nvp_buf_free(nvl, nvp); 947 1.1 haad return (err); 948 1.1 haad } 949 1.1 haad break; 950 1.1 haad } 951 1.1 haad case DATA_TYPE_NVLIST_ARRAY: { 952 1.1 haad nvlist_t **onvlp = (nvlist_t **)data; 953 1.1 haad nvlist_t **nvlp = EMBEDDED_NVL_ARRAY(nvp); 954 1.1 haad nvlist_t *embedded = (nvlist_t *) 955 1.1 haad ((uintptr_t)nvlp + nelem * sizeof (uint64_t)); 956 1.1 haad 957 1.1 haad for (i = 0; i < nelem; i++) { 958 1.1 haad if ((err = nvlist_copy_embedded(nvl, 959 1.1 haad onvlp[i], embedded)) != 0) { 960 1.1 haad /* 961 1.1 haad * Free any successfully created lists 962 1.1 haad */ 963 1.1 haad nvpair_free(nvp); 964 1.1 haad nvp_buf_free(nvl, nvp); 965 1.1 haad return (err); 966 1.1 haad } 967 1.1 haad 968 1.1 haad nvlp[i] = embedded++; 969 1.1 haad } 970 1.1 haad break; 971 1.1 haad } 972 1.1 haad default: 973 1.1 haad bcopy(data, NVP_VALUE(nvp), value_sz); 974 1.1 haad } 975 1.1 haad 976 1.1 haad /* if unique name, remove before add */ 977 1.1 haad if (nvl->nvl_nvflag & NV_UNIQUE_NAME) 978 1.1 haad (void) nvlist_remove_all(nvl, name); 979 1.1 haad else if (nvl->nvl_nvflag & NV_UNIQUE_NAME_TYPE) 980 1.1 haad (void) nvlist_remove(nvl, name, type); 981 1.1 haad 982 1.1 haad nvp_buf_link(nvl, nvp); 983 1.1 haad 984 1.1 haad return (0); 985 1.1 haad } 986 1.1 haad 987 1.1 haad int 988 1.1 haad nvlist_add_boolean(nvlist_t *nvl, const char *name) 989 1.1 haad { 990 1.1 haad return (nvlist_add_common(nvl, name, DATA_TYPE_BOOLEAN, 0, NULL)); 991 1.1 haad } 992 1.1 haad 993 1.1 haad int 994 1.1 haad nvlist_add_boolean_value(nvlist_t *nvl, const char *name, boolean_t val) 995 1.1 haad { 996 1.1 haad return (nvlist_add_common(nvl, name, DATA_TYPE_BOOLEAN_VALUE, 1, &val)); 997 1.1 haad } 998 1.1 haad 999 1.1 haad int 1000 1.1 haad nvlist_add_byte(nvlist_t *nvl, const char *name, uchar_t val) 1001 1.1 haad { 1002 1.1 haad return (nvlist_add_common(nvl, name, DATA_TYPE_BYTE, 1, &val)); 1003 1.1 haad } 1004 1.1 haad 1005 1.1 haad int 1006 1.1 haad nvlist_add_int8(nvlist_t *nvl, const char *name, int8_t val) 1007 1.1 haad { 1008 1.1 haad return (nvlist_add_common(nvl, name, DATA_TYPE_INT8, 1, &val)); 1009 1.1 haad } 1010 1.1 haad 1011 1.1 haad int 1012 1.1 haad nvlist_add_uint8(nvlist_t *nvl, const char *name, uint8_t val) 1013 1.1 haad { 1014 1.1 haad return (nvlist_add_common(nvl, name, DATA_TYPE_UINT8, 1, &val)); 1015 1.1 haad } 1016 1.1 haad 1017 1.1 haad int 1018 1.1 haad nvlist_add_int16(nvlist_t *nvl, const char *name, int16_t val) 1019 1.1 haad { 1020 1.1 haad return (nvlist_add_common(nvl, name, DATA_TYPE_INT16, 1, &val)); 1021 1.1 haad } 1022 1.1 haad 1023 1.1 haad int 1024 1.1 haad nvlist_add_uint16(nvlist_t *nvl, const char *name, uint16_t val) 1025 1.1 haad { 1026 1.1 haad return (nvlist_add_common(nvl, name, DATA_TYPE_UINT16, 1, &val)); 1027 1.1 haad } 1028 1.1 haad 1029 1.1 haad int 1030 1.1 haad nvlist_add_int32(nvlist_t *nvl, const char *name, int32_t val) 1031 1.1 haad { 1032 1.1 haad return (nvlist_add_common(nvl, name, DATA_TYPE_INT32, 1, &val)); 1033 1.1 haad } 1034 1.1 haad 1035 1.1 haad int 1036 1.1 haad nvlist_add_uint32(nvlist_t *nvl, const char *name, uint32_t val) 1037 1.1 haad { 1038 1.1 haad return (nvlist_add_common(nvl, name, DATA_TYPE_UINT32, 1, &val)); 1039 1.1 haad } 1040 1.1 haad 1041 1.1 haad int 1042 1.1 haad nvlist_add_int64(nvlist_t *nvl, const char *name, int64_t val) 1043 1.1 haad { 1044 1.1 haad return (nvlist_add_common(nvl, name, DATA_TYPE_INT64, 1, &val)); 1045 1.1 haad } 1046 1.1 haad 1047 1.1 haad int 1048 1.1 haad nvlist_add_uint64(nvlist_t *nvl, const char *name, uint64_t val) 1049 1.1 haad { 1050 1.1 haad return (nvlist_add_common(nvl, name, DATA_TYPE_UINT64, 1, &val)); 1051 1.1 haad } 1052 1.1 haad 1053 1.1 haad #if !defined(_KERNEL) 1054 1.1 haad int 1055 1.1 haad nvlist_add_double(nvlist_t *nvl, const char *name, double val) 1056 1.1 haad { 1057 1.1 haad return (nvlist_add_common(nvl, name, DATA_TYPE_DOUBLE, 1, &val)); 1058 1.1 haad } 1059 1.1 haad #endif 1060 1.1 haad 1061 1.1 haad int 1062 1.1 haad nvlist_add_string(nvlist_t *nvl, const char *name, const char *val) 1063 1.1 haad { 1064 1.1 haad return (nvlist_add_common(nvl, name, DATA_TYPE_STRING, 1, (void *)val)); 1065 1.1 haad } 1066 1.1 haad 1067 1.1 haad int 1068 1.1 haad nvlist_add_boolean_array(nvlist_t *nvl, const char *name, 1069 1.1 haad boolean_t *a, uint_t n) 1070 1.1 haad { 1071 1.1 haad return (nvlist_add_common(nvl, name, DATA_TYPE_BOOLEAN_ARRAY, n, a)); 1072 1.1 haad } 1073 1.1 haad 1074 1.1 haad int 1075 1.1 haad nvlist_add_byte_array(nvlist_t *nvl, const char *name, uchar_t *a, uint_t n) 1076 1.1 haad { 1077 1.1 haad return (nvlist_add_common(nvl, name, DATA_TYPE_BYTE_ARRAY, n, a)); 1078 1.1 haad } 1079 1.1 haad 1080 1.1 haad int 1081 1.1 haad nvlist_add_int8_array(nvlist_t *nvl, const char *name, int8_t *a, uint_t n) 1082 1.1 haad { 1083 1.1 haad return (nvlist_add_common(nvl, name, DATA_TYPE_INT8_ARRAY, n, a)); 1084 1.1 haad } 1085 1.1 haad 1086 1.1 haad int 1087 1.1 haad nvlist_add_uint8_array(nvlist_t *nvl, const char *name, uint8_t *a, uint_t n) 1088 1.1 haad { 1089 1.1 haad return (nvlist_add_common(nvl, name, DATA_TYPE_UINT8_ARRAY, n, a)); 1090 1.1 haad } 1091 1.1 haad 1092 1.1 haad int 1093 1.1 haad nvlist_add_int16_array(nvlist_t *nvl, const char *name, int16_t *a, uint_t n) 1094 1.1 haad { 1095 1.1 haad return (nvlist_add_common(nvl, name, DATA_TYPE_INT16_ARRAY, n, a)); 1096 1.1 haad } 1097 1.1 haad 1098 1.1 haad int 1099 1.1 haad nvlist_add_uint16_array(nvlist_t *nvl, const char *name, uint16_t *a, uint_t n) 1100 1.1 haad { 1101 1.1 haad return (nvlist_add_common(nvl, name, DATA_TYPE_UINT16_ARRAY, n, a)); 1102 1.1 haad } 1103 1.1 haad 1104 1.1 haad int 1105 1.1 haad nvlist_add_int32_array(nvlist_t *nvl, const char *name, int32_t *a, uint_t n) 1106 1.1 haad { 1107 1.1 haad return (nvlist_add_common(nvl, name, DATA_TYPE_INT32_ARRAY, n, a)); 1108 1.1 haad } 1109 1.1 haad 1110 1.1 haad int 1111 1.1 haad nvlist_add_uint32_array(nvlist_t *nvl, const char *name, uint32_t *a, uint_t n) 1112 1.1 haad { 1113 1.1 haad return (nvlist_add_common(nvl, name, DATA_TYPE_UINT32_ARRAY, n, a)); 1114 1.1 haad } 1115 1.1 haad 1116 1.1 haad int 1117 1.1 haad nvlist_add_int64_array(nvlist_t *nvl, const char *name, int64_t *a, uint_t n) 1118 1.1 haad { 1119 1.1 haad return (nvlist_add_common(nvl, name, DATA_TYPE_INT64_ARRAY, n, a)); 1120 1.1 haad } 1121 1.1 haad 1122 1.1 haad int 1123 1.1 haad nvlist_add_uint64_array(nvlist_t *nvl, const char *name, uint64_t *a, uint_t n) 1124 1.1 haad { 1125 1.1 haad return (nvlist_add_common(nvl, name, DATA_TYPE_UINT64_ARRAY, n, a)); 1126 1.1 haad } 1127 1.1 haad 1128 1.1 haad int 1129 1.1 haad nvlist_add_string_array(nvlist_t *nvl, const char *name, 1130 1.1 haad char *const *a, uint_t n) 1131 1.1 haad { 1132 1.1 haad return (nvlist_add_common(nvl, name, DATA_TYPE_STRING_ARRAY, n, a)); 1133 1.1 haad } 1134 1.1 haad 1135 1.1 haad int 1136 1.1 haad nvlist_add_hrtime(nvlist_t *nvl, const char *name, hrtime_t val) 1137 1.1 haad { 1138 1.1 haad return (nvlist_add_common(nvl, name, DATA_TYPE_HRTIME, 1, &val)); 1139 1.1 haad } 1140 1.1 haad 1141 1.1 haad int 1142 1.1 haad nvlist_add_nvlist(nvlist_t *nvl, const char *name, nvlist_t *val) 1143 1.1 haad { 1144 1.1 haad return (nvlist_add_common(nvl, name, DATA_TYPE_NVLIST, 1, val)); 1145 1.1 haad } 1146 1.1 haad 1147 1.1 haad int 1148 1.1 haad nvlist_add_nvlist_array(nvlist_t *nvl, const char *name, nvlist_t **a, uint_t n) 1149 1.1 haad { 1150 1.1 haad return (nvlist_add_common(nvl, name, DATA_TYPE_NVLIST_ARRAY, n, a)); 1151 1.1 haad } 1152 1.1 haad 1153 1.1 haad /* reading name-value pairs */ 1154 1.1 haad nvpair_t * 1155 1.1 haad nvlist_next_nvpair(nvlist_t *nvl, nvpair_t *nvp) 1156 1.1 haad { 1157 1.1 haad nvpriv_t *priv; 1158 1.1 haad i_nvp_t *curr; 1159 1.1 haad 1160 1.1 haad if (nvl == NULL || 1161 1.1 haad (priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv) == NULL) 1162 1.1 haad return (NULL); 1163 1.1 haad 1164 1.1 haad curr = NVPAIR2I_NVP(nvp); 1165 1.1 haad 1166 1.1 haad /* 1167 1.1 haad * Ensure that nvp is a valid nvpair on this nvlist. 1168 1.1 haad * NB: nvp_curr is used only as a hint so that we don't always 1169 1.1 haad * have to walk the list to determine if nvp is still on the list. 1170 1.1 haad */ 1171 1.1 haad if (nvp == NULL) 1172 1.1 haad curr = priv->nvp_list; 1173 1.1 haad else if (priv->nvp_curr == curr || nvlist_contains_nvp(nvl, nvp)) 1174 1.1 haad curr = curr->nvi_next; 1175 1.1 haad else 1176 1.1 haad curr = NULL; 1177 1.1 haad 1178 1.1 haad priv->nvp_curr = curr; 1179 1.1 haad 1180 1.1 haad return (curr != NULL ? &curr->nvi_nvp : NULL); 1181 1.1 haad } 1182 1.1 haad 1183 1.2 dsl nvpair_t * 1184 1.2 dsl nvlist_prev_nvpair(nvlist_t *nvl, nvpair_t *nvp) 1185 1.2 dsl { 1186 1.2 dsl nvpriv_t *priv; 1187 1.2 dsl i_nvp_t *curr; 1188 1.2 dsl 1189 1.2 dsl if (nvl == NULL || 1190 1.2 dsl (priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv) == NULL) 1191 1.2 dsl return (NULL); 1192 1.2 dsl 1193 1.2 dsl curr = NVPAIR2I_NVP(nvp); 1194 1.2 dsl 1195 1.2 dsl if (nvp == NULL) 1196 1.2 dsl curr = priv->nvp_last; 1197 1.2 dsl else if (priv->nvp_curr == curr || nvlist_contains_nvp(nvl, nvp)) 1198 1.2 dsl curr = curr->nvi_prev; 1199 1.2 dsl else 1200 1.2 dsl curr = NULL; 1201 1.2 dsl 1202 1.2 dsl priv->nvp_curr = curr; 1203 1.2 dsl 1204 1.2 dsl return (curr != NULL ? &curr->nvi_nvp : NULL); 1205 1.2 dsl } 1206 1.2 dsl 1207 1.2 dsl boolean_t 1208 1.2 dsl nvlist_empty(nvlist_t *nvl) 1209 1.2 dsl { 1210 1.2 dsl nvpriv_t *priv; 1211 1.2 dsl 1212 1.2 dsl if (nvl == NULL || 1213 1.2 dsl (priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv) == NULL) 1214 1.2 dsl return (B_TRUE); 1215 1.2 dsl 1216 1.2 dsl return (priv->nvp_list == NULL); 1217 1.2 dsl } 1218 1.2 dsl 1219 1.1 haad char * 1220 1.1 haad nvpair_name(nvpair_t *nvp) 1221 1.1 haad { 1222 1.1 haad return (NVP_NAME(nvp)); 1223 1.1 haad } 1224 1.1 haad 1225 1.1 haad data_type_t 1226 1.1 haad nvpair_type(nvpair_t *nvp) 1227 1.1 haad { 1228 1.1 haad return (NVP_TYPE(nvp)); 1229 1.1 haad } 1230 1.1 haad 1231 1.1 haad int 1232 1.1 haad nvpair_type_is_array(nvpair_t *nvp) 1233 1.1 haad { 1234 1.1 haad data_type_t type = NVP_TYPE(nvp); 1235 1.1 haad 1236 1.1 haad if ((type == DATA_TYPE_BYTE_ARRAY) || 1237 1.4 chs (type == DATA_TYPE_INT8_ARRAY) || 1238 1.1 haad (type == DATA_TYPE_UINT8_ARRAY) || 1239 1.1 haad (type == DATA_TYPE_INT16_ARRAY) || 1240 1.1 haad (type == DATA_TYPE_UINT16_ARRAY) || 1241 1.1 haad (type == DATA_TYPE_INT32_ARRAY) || 1242 1.1 haad (type == DATA_TYPE_UINT32_ARRAY) || 1243 1.1 haad (type == DATA_TYPE_INT64_ARRAY) || 1244 1.1 haad (type == DATA_TYPE_UINT64_ARRAY) || 1245 1.1 haad (type == DATA_TYPE_BOOLEAN_ARRAY) || 1246 1.1 haad (type == DATA_TYPE_STRING_ARRAY) || 1247 1.1 haad (type == DATA_TYPE_NVLIST_ARRAY)) 1248 1.1 haad return (1); 1249 1.1 haad return (0); 1250 1.1 haad 1251 1.1 haad } 1252 1.1 haad 1253 1.1 haad static int 1254 1.1 haad nvpair_value_common(nvpair_t *nvp, data_type_t type, uint_t *nelem, void *data) 1255 1.1 haad { 1256 1.1 haad if (nvp == NULL || nvpair_type(nvp) != type) 1257 1.1 haad return (EINVAL); 1258 1.1 haad 1259 1.1 haad /* 1260 1.1 haad * For non-array types, we copy the data. 1261 1.1 haad * For array types (including string), we set a pointer. 1262 1.1 haad */ 1263 1.1 haad switch (type) { 1264 1.1 haad case DATA_TYPE_BOOLEAN: 1265 1.1 haad if (nelem != NULL) 1266 1.1 haad *nelem = 0; 1267 1.1 haad break; 1268 1.1 haad 1269 1.1 haad case DATA_TYPE_BOOLEAN_VALUE: 1270 1.1 haad case DATA_TYPE_BYTE: 1271 1.1 haad case DATA_TYPE_INT8: 1272 1.1 haad case DATA_TYPE_UINT8: 1273 1.1 haad case DATA_TYPE_INT16: 1274 1.1 haad case DATA_TYPE_UINT16: 1275 1.1 haad case DATA_TYPE_INT32: 1276 1.1 haad case DATA_TYPE_UINT32: 1277 1.1 haad case DATA_TYPE_INT64: 1278 1.1 haad case DATA_TYPE_UINT64: 1279 1.1 haad case DATA_TYPE_HRTIME: 1280 1.1 haad #if !defined(_KERNEL) 1281 1.1 haad case DATA_TYPE_DOUBLE: 1282 1.1 haad #endif 1283 1.1 haad if (data == NULL) 1284 1.1 haad return (EINVAL); 1285 1.1 haad bcopy(NVP_VALUE(nvp), data, 1286 1.1 haad (size_t)i_get_value_size(type, NULL, 1)); 1287 1.1 haad if (nelem != NULL) 1288 1.1 haad *nelem = 1; 1289 1.1 haad break; 1290 1.1 haad 1291 1.1 haad case DATA_TYPE_NVLIST: 1292 1.1 haad case DATA_TYPE_STRING: 1293 1.1 haad if (data == NULL) 1294 1.1 haad return (EINVAL); 1295 1.1 haad *(void **)data = (void *)NVP_VALUE(nvp); 1296 1.1 haad if (nelem != NULL) 1297 1.1 haad *nelem = 1; 1298 1.1 haad break; 1299 1.1 haad 1300 1.1 haad case DATA_TYPE_BOOLEAN_ARRAY: 1301 1.1 haad case DATA_TYPE_BYTE_ARRAY: 1302 1.1 haad case DATA_TYPE_INT8_ARRAY: 1303 1.1 haad case DATA_TYPE_UINT8_ARRAY: 1304 1.1 haad case DATA_TYPE_INT16_ARRAY: 1305 1.1 haad case DATA_TYPE_UINT16_ARRAY: 1306 1.1 haad case DATA_TYPE_INT32_ARRAY: 1307 1.1 haad case DATA_TYPE_UINT32_ARRAY: 1308 1.1 haad case DATA_TYPE_INT64_ARRAY: 1309 1.1 haad case DATA_TYPE_UINT64_ARRAY: 1310 1.1 haad case DATA_TYPE_STRING_ARRAY: 1311 1.1 haad case DATA_TYPE_NVLIST_ARRAY: 1312 1.1 haad if (nelem == NULL || data == NULL) 1313 1.1 haad return (EINVAL); 1314 1.1 haad if ((*nelem = NVP_NELEM(nvp)) != 0) 1315 1.1 haad *(void **)data = (void *)NVP_VALUE(nvp); 1316 1.1 haad else 1317 1.1 haad *(void **)data = NULL; 1318 1.1 haad break; 1319 1.1 haad 1320 1.1 haad default: 1321 1.1 haad return (ENOTSUP); 1322 1.1 haad } 1323 1.1 haad 1324 1.1 haad return (0); 1325 1.1 haad } 1326 1.1 haad 1327 1.1 haad static int 1328 1.1 haad nvlist_lookup_common(nvlist_t *nvl, const char *name, data_type_t type, 1329 1.1 haad uint_t *nelem, void *data) 1330 1.1 haad { 1331 1.1 haad nvpriv_t *priv; 1332 1.1 haad nvpair_t *nvp; 1333 1.1 haad i_nvp_t *curr; 1334 1.1 haad 1335 1.1 haad if (name == NULL || nvl == NULL || 1336 1.1 haad (priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv) == NULL) 1337 1.1 haad return (EINVAL); 1338 1.1 haad 1339 1.1 haad if (!(nvl->nvl_nvflag & (NV_UNIQUE_NAME | NV_UNIQUE_NAME_TYPE))) 1340 1.1 haad return (ENOTSUP); 1341 1.1 haad 1342 1.1 haad for (curr = priv->nvp_list; curr != NULL; curr = curr->nvi_next) { 1343 1.1 haad nvp = &curr->nvi_nvp; 1344 1.1 haad 1345 1.1 haad if (strcmp(name, NVP_NAME(nvp)) == 0 && NVP_TYPE(nvp) == type) 1346 1.1 haad return (nvpair_value_common(nvp, type, nelem, data)); 1347 1.1 haad } 1348 1.1 haad 1349 1.1 haad return (ENOENT); 1350 1.1 haad } 1351 1.1 haad 1352 1.1 haad int 1353 1.1 haad nvlist_lookup_boolean(nvlist_t *nvl, const char *name) 1354 1.1 haad { 1355 1.1 haad return (nvlist_lookup_common(nvl, name, DATA_TYPE_BOOLEAN, NULL, NULL)); 1356 1.1 haad } 1357 1.1 haad 1358 1.1 haad int 1359 1.1 haad nvlist_lookup_boolean_value(nvlist_t *nvl, const char *name, boolean_t *val) 1360 1.1 haad { 1361 1.1 haad return (nvlist_lookup_common(nvl, name, 1362 1.1 haad DATA_TYPE_BOOLEAN_VALUE, NULL, val)); 1363 1.1 haad } 1364 1.1 haad 1365 1.1 haad int 1366 1.1 haad nvlist_lookup_byte(nvlist_t *nvl, const char *name, uchar_t *val) 1367 1.1 haad { 1368 1.1 haad return (nvlist_lookup_common(nvl, name, DATA_TYPE_BYTE, NULL, val)); 1369 1.1 haad } 1370 1.1 haad 1371 1.1 haad int 1372 1.1 haad nvlist_lookup_int8(nvlist_t *nvl, const char *name, int8_t *val) 1373 1.1 haad { 1374 1.1 haad return (nvlist_lookup_common(nvl, name, DATA_TYPE_INT8, NULL, val)); 1375 1.1 haad } 1376 1.1 haad 1377 1.1 haad int 1378 1.1 haad nvlist_lookup_uint8(nvlist_t *nvl, const char *name, uint8_t *val) 1379 1.1 haad { 1380 1.1 haad return (nvlist_lookup_common(nvl, name, DATA_TYPE_UINT8, NULL, val)); 1381 1.1 haad } 1382 1.1 haad 1383 1.1 haad int 1384 1.1 haad nvlist_lookup_int16(nvlist_t *nvl, const char *name, int16_t *val) 1385 1.1 haad { 1386 1.1 haad return (nvlist_lookup_common(nvl, name, DATA_TYPE_INT16, NULL, val)); 1387 1.1 haad } 1388 1.1 haad 1389 1.1 haad int 1390 1.1 haad nvlist_lookup_uint16(nvlist_t *nvl, const char *name, uint16_t *val) 1391 1.1 haad { 1392 1.1 haad return (nvlist_lookup_common(nvl, name, DATA_TYPE_UINT16, NULL, val)); 1393 1.1 haad } 1394 1.1 haad 1395 1.1 haad int 1396 1.1 haad nvlist_lookup_int32(nvlist_t *nvl, const char *name, int32_t *val) 1397 1.1 haad { 1398 1.1 haad return (nvlist_lookup_common(nvl, name, DATA_TYPE_INT32, NULL, val)); 1399 1.1 haad } 1400 1.1 haad 1401 1.1 haad int 1402 1.1 haad nvlist_lookup_uint32(nvlist_t *nvl, const char *name, uint32_t *val) 1403 1.1 haad { 1404 1.1 haad return (nvlist_lookup_common(nvl, name, DATA_TYPE_UINT32, NULL, val)); 1405 1.1 haad } 1406 1.1 haad 1407 1.1 haad int 1408 1.1 haad nvlist_lookup_int64(nvlist_t *nvl, const char *name, int64_t *val) 1409 1.1 haad { 1410 1.1 haad return (nvlist_lookup_common(nvl, name, DATA_TYPE_INT64, NULL, val)); 1411 1.1 haad } 1412 1.1 haad 1413 1.1 haad int 1414 1.1 haad nvlist_lookup_uint64(nvlist_t *nvl, const char *name, uint64_t *val) 1415 1.1 haad { 1416 1.1 haad return (nvlist_lookup_common(nvl, name, DATA_TYPE_UINT64, NULL, val)); 1417 1.1 haad } 1418 1.1 haad 1419 1.1 haad #if !defined(_KERNEL) 1420 1.1 haad int 1421 1.1 haad nvlist_lookup_double(nvlist_t *nvl, const char *name, double *val) 1422 1.1 haad { 1423 1.1 haad return (nvlist_lookup_common(nvl, name, DATA_TYPE_DOUBLE, NULL, val)); 1424 1.1 haad } 1425 1.1 haad #endif 1426 1.1 haad 1427 1.1 haad int 1428 1.1 haad nvlist_lookup_string(nvlist_t *nvl, const char *name, char **val) 1429 1.1 haad { 1430 1.1 haad return (nvlist_lookup_common(nvl, name, DATA_TYPE_STRING, NULL, val)); 1431 1.1 haad } 1432 1.1 haad 1433 1.1 haad int 1434 1.1 haad nvlist_lookup_nvlist(nvlist_t *nvl, const char *name, nvlist_t **val) 1435 1.1 haad { 1436 1.1 haad return (nvlist_lookup_common(nvl, name, DATA_TYPE_NVLIST, NULL, val)); 1437 1.1 haad } 1438 1.1 haad 1439 1.1 haad int 1440 1.1 haad nvlist_lookup_boolean_array(nvlist_t *nvl, const char *name, 1441 1.1 haad boolean_t **a, uint_t *n) 1442 1.1 haad { 1443 1.1 haad return (nvlist_lookup_common(nvl, name, 1444 1.1 haad DATA_TYPE_BOOLEAN_ARRAY, n, a)); 1445 1.1 haad } 1446 1.1 haad 1447 1.1 haad int 1448 1.1 haad nvlist_lookup_byte_array(nvlist_t *nvl, const char *name, 1449 1.1 haad uchar_t **a, uint_t *n) 1450 1.1 haad { 1451 1.1 haad return (nvlist_lookup_common(nvl, name, DATA_TYPE_BYTE_ARRAY, n, a)); 1452 1.1 haad } 1453 1.1 haad 1454 1.1 haad int 1455 1.1 haad nvlist_lookup_int8_array(nvlist_t *nvl, const char *name, int8_t **a, uint_t *n) 1456 1.1 haad { 1457 1.1 haad return (nvlist_lookup_common(nvl, name, DATA_TYPE_INT8_ARRAY, n, a)); 1458 1.1 haad } 1459 1.1 haad 1460 1.1 haad int 1461 1.1 haad nvlist_lookup_uint8_array(nvlist_t *nvl, const char *name, 1462 1.1 haad uint8_t **a, uint_t *n) 1463 1.1 haad { 1464 1.1 haad return (nvlist_lookup_common(nvl, name, DATA_TYPE_UINT8_ARRAY, n, a)); 1465 1.1 haad } 1466 1.1 haad 1467 1.1 haad int 1468 1.1 haad nvlist_lookup_int16_array(nvlist_t *nvl, const char *name, 1469 1.1 haad int16_t **a, uint_t *n) 1470 1.1 haad { 1471 1.1 haad return (nvlist_lookup_common(nvl, name, DATA_TYPE_INT16_ARRAY, n, a)); 1472 1.1 haad } 1473 1.1 haad 1474 1.1 haad int 1475 1.1 haad nvlist_lookup_uint16_array(nvlist_t *nvl, const char *name, 1476 1.1 haad uint16_t **a, uint_t *n) 1477 1.1 haad { 1478 1.1 haad return (nvlist_lookup_common(nvl, name, DATA_TYPE_UINT16_ARRAY, n, a)); 1479 1.1 haad } 1480 1.1 haad 1481 1.1 haad int 1482 1.1 haad nvlist_lookup_int32_array(nvlist_t *nvl, const char *name, 1483 1.1 haad int32_t **a, uint_t *n) 1484 1.1 haad { 1485 1.1 haad return (nvlist_lookup_common(nvl, name, DATA_TYPE_INT32_ARRAY, n, a)); 1486 1.1 haad } 1487 1.1 haad 1488 1.1 haad int 1489 1.1 haad nvlist_lookup_uint32_array(nvlist_t *nvl, const char *name, 1490 1.1 haad uint32_t **a, uint_t *n) 1491 1.1 haad { 1492 1.1 haad return (nvlist_lookup_common(nvl, name, DATA_TYPE_UINT32_ARRAY, n, a)); 1493 1.1 haad } 1494 1.1 haad 1495 1.1 haad int 1496 1.1 haad nvlist_lookup_int64_array(nvlist_t *nvl, const char *name, 1497 1.1 haad int64_t **a, uint_t *n) 1498 1.1 haad { 1499 1.1 haad return (nvlist_lookup_common(nvl, name, DATA_TYPE_INT64_ARRAY, n, a)); 1500 1.1 haad } 1501 1.1 haad 1502 1.1 haad int 1503 1.1 haad nvlist_lookup_uint64_array(nvlist_t *nvl, const char *name, 1504 1.1 haad uint64_t **a, uint_t *n) 1505 1.1 haad { 1506 1.1 haad return (nvlist_lookup_common(nvl, name, DATA_TYPE_UINT64_ARRAY, n, a)); 1507 1.1 haad } 1508 1.1 haad 1509 1.1 haad int 1510 1.1 haad nvlist_lookup_string_array(nvlist_t *nvl, const char *name, 1511 1.1 haad char ***a, uint_t *n) 1512 1.1 haad { 1513 1.1 haad return (nvlist_lookup_common(nvl, name, DATA_TYPE_STRING_ARRAY, n, a)); 1514 1.1 haad } 1515 1.1 haad 1516 1.1 haad int 1517 1.1 haad nvlist_lookup_nvlist_array(nvlist_t *nvl, const char *name, 1518 1.1 haad nvlist_t ***a, uint_t *n) 1519 1.1 haad { 1520 1.1 haad return (nvlist_lookup_common(nvl, name, DATA_TYPE_NVLIST_ARRAY, n, a)); 1521 1.1 haad } 1522 1.1 haad 1523 1.1 haad int 1524 1.1 haad nvlist_lookup_hrtime(nvlist_t *nvl, const char *name, hrtime_t *val) 1525 1.1 haad { 1526 1.1 haad return (nvlist_lookup_common(nvl, name, DATA_TYPE_HRTIME, NULL, val)); 1527 1.1 haad } 1528 1.1 haad 1529 1.1 haad int 1530 1.1 haad nvlist_lookup_pairs(nvlist_t *nvl, int flag, ...) 1531 1.1 haad { 1532 1.1 haad va_list ap; 1533 1.1 haad char *name; 1534 1.1 haad int noentok = (flag & NV_FLAG_NOENTOK ? 1 : 0); 1535 1.1 haad int ret = 0; 1536 1.1 haad 1537 1.1 haad va_start(ap, flag); 1538 1.1 haad while (ret == 0 && (name = va_arg(ap, char *)) != NULL) { 1539 1.1 haad data_type_t type; 1540 1.1 haad void *val; 1541 1.1 haad uint_t *nelem; 1542 1.1 haad 1543 1.1 haad switch (type = va_arg(ap, data_type_t)) { 1544 1.1 haad case DATA_TYPE_BOOLEAN: 1545 1.1 haad ret = nvlist_lookup_common(nvl, name, type, NULL, NULL); 1546 1.1 haad break; 1547 1.1 haad 1548 1.1 haad case DATA_TYPE_BOOLEAN_VALUE: 1549 1.1 haad case DATA_TYPE_BYTE: 1550 1.1 haad case DATA_TYPE_INT8: 1551 1.1 haad case DATA_TYPE_UINT8: 1552 1.1 haad case DATA_TYPE_INT16: 1553 1.1 haad case DATA_TYPE_UINT16: 1554 1.1 haad case DATA_TYPE_INT32: 1555 1.1 haad case DATA_TYPE_UINT32: 1556 1.1 haad case DATA_TYPE_INT64: 1557 1.1 haad case DATA_TYPE_UINT64: 1558 1.1 haad case DATA_TYPE_HRTIME: 1559 1.1 haad case DATA_TYPE_STRING: 1560 1.1 haad case DATA_TYPE_NVLIST: 1561 1.1 haad #if !defined(_KERNEL) 1562 1.1 haad case DATA_TYPE_DOUBLE: 1563 1.1 haad #endif 1564 1.1 haad val = va_arg(ap, void *); 1565 1.1 haad ret = nvlist_lookup_common(nvl, name, type, NULL, val); 1566 1.1 haad break; 1567 1.1 haad 1568 1.1 haad case DATA_TYPE_BYTE_ARRAY: 1569 1.1 haad case DATA_TYPE_BOOLEAN_ARRAY: 1570 1.1 haad case DATA_TYPE_INT8_ARRAY: 1571 1.1 haad case DATA_TYPE_UINT8_ARRAY: 1572 1.1 haad case DATA_TYPE_INT16_ARRAY: 1573 1.1 haad case DATA_TYPE_UINT16_ARRAY: 1574 1.1 haad case DATA_TYPE_INT32_ARRAY: 1575 1.1 haad case DATA_TYPE_UINT32_ARRAY: 1576 1.1 haad case DATA_TYPE_INT64_ARRAY: 1577 1.1 haad case DATA_TYPE_UINT64_ARRAY: 1578 1.1 haad case DATA_TYPE_STRING_ARRAY: 1579 1.1 haad case DATA_TYPE_NVLIST_ARRAY: 1580 1.1 haad val = va_arg(ap, void *); 1581 1.1 haad nelem = va_arg(ap, uint_t *); 1582 1.1 haad ret = nvlist_lookup_common(nvl, name, type, nelem, val); 1583 1.1 haad break; 1584 1.1 haad 1585 1.1 haad default: 1586 1.1 haad ret = EINVAL; 1587 1.1 haad } 1588 1.1 haad 1589 1.1 haad if (ret == ENOENT && noentok) 1590 1.1 haad ret = 0; 1591 1.1 haad } 1592 1.1 haad va_end(ap); 1593 1.1 haad 1594 1.1 haad return (ret); 1595 1.1 haad } 1596 1.1 haad 1597 1.1 haad /* 1598 1.1 haad * Find the 'name'ed nvpair in the nvlist 'nvl'. If 'name' found, the function 1599 1.1 haad * returns zero and a pointer to the matching nvpair is returned in '*ret' 1600 1.1 haad * (given 'ret' is non-NULL). If 'sep' is specified then 'name' will penitrate 1601 1.1 haad * multiple levels of embedded nvlists, with 'sep' as the separator. As an 1602 1.1 haad * example, if sep is '.', name might look like: "a" or "a.b" or "a.c[3]" or 1603 1.1 haad * "a.d[3].e[1]". This matches the C syntax for array embed (for convience, 1604 1.1 haad * code also supports "a.d[3]e[1]" syntax). 1605 1.1 haad * 1606 1.1 haad * If 'ip' is non-NULL and the last name component is an array, return the 1607 1.1 haad * value of the "...[index]" array index in *ip. For an array reference that 1608 1.1 haad * is not indexed, *ip will be returned as -1. If there is a syntax error in 1609 1.1 haad * 'name', and 'ep' is non-NULL then *ep will be set to point to the location 1610 1.1 haad * inside the 'name' string where the syntax error was detected. 1611 1.1 haad */ 1612 1.1 haad static int 1613 1.1 haad nvlist_lookup_nvpair_ei_sep(nvlist_t *nvl, const char *name, const char sep, 1614 1.1 haad nvpair_t **ret, int *ip, char **ep) 1615 1.1 haad { 1616 1.1 haad nvpair_t *nvp; 1617 1.1 haad const char *np; 1618 1.4 chs char *sepp; 1619 1.1 haad char *idxp, *idxep; 1620 1.1 haad nvlist_t **nva; 1621 1.4 chs long idx; 1622 1.1 haad int n; 1623 1.1 haad 1624 1.1 haad if (ip) 1625 1.1 haad *ip = -1; /* not indexed */ 1626 1.1 haad if (ep) 1627 1.1 haad *ep = NULL; 1628 1.1 haad 1629 1.1 haad if ((nvl == NULL) || (name == NULL)) 1630 1.1 haad return (EINVAL); 1631 1.1 haad 1632 1.4 chs sepp = NULL; 1633 1.4 chs idx = 0; 1634 1.1 haad /* step through components of name */ 1635 1.1 haad for (np = name; np && *np; np = sepp) { 1636 1.1 haad /* ensure unique names */ 1637 1.1 haad if (!(nvl->nvl_nvflag & NV_UNIQUE_NAME)) 1638 1.1 haad return (ENOTSUP); 1639 1.1 haad 1640 1.1 haad /* skip white space */ 1641 1.1 haad skip_whitespace(np); 1642 1.1 haad if (*np == 0) 1643 1.1 haad break; 1644 1.1 haad 1645 1.1 haad /* set 'sepp' to end of current component 'np' */ 1646 1.1 haad if (sep) 1647 1.1 haad sepp = strchr(np, sep); 1648 1.1 haad else 1649 1.1 haad sepp = NULL; 1650 1.1 haad 1651 1.1 haad /* find start of next "[ index ]..." */ 1652 1.1 haad idxp = strchr(np, '['); 1653 1.1 haad 1654 1.1 haad /* if sepp comes first, set idxp to NULL */ 1655 1.1 haad if (sepp && idxp && (sepp < idxp)) 1656 1.1 haad idxp = NULL; 1657 1.1 haad 1658 1.1 haad /* 1659 1.1 haad * At this point 'idxp' is set if there is an index 1660 1.1 haad * expected for the current component. 1661 1.1 haad */ 1662 1.1 haad if (idxp) { 1663 1.1 haad /* set 'n' to length of current 'np' name component */ 1664 1.1 haad n = idxp++ - np; 1665 1.1 haad 1666 1.1 haad /* keep sepp up to date for *ep use as we advance */ 1667 1.1 haad skip_whitespace(idxp); 1668 1.1 haad sepp = idxp; 1669 1.1 haad 1670 1.1 haad /* determine the index value */ 1671 1.1 haad #if defined(_KERNEL) && !defined(_BOOT) 1672 1.1 haad if (ddi_strtol(idxp, &idxep, 0, &idx)) 1673 1.1 haad goto fail; 1674 1.1 haad #else 1675 1.1 haad idx = strtol(idxp, &idxep, 0); 1676 1.1 haad #endif 1677 1.1 haad if (idxep == idxp) 1678 1.1 haad goto fail; 1679 1.1 haad 1680 1.1 haad /* keep sepp up to date for *ep use as we advance */ 1681 1.1 haad sepp = idxep; 1682 1.1 haad 1683 1.1 haad /* skip white space index value and check for ']' */ 1684 1.1 haad skip_whitespace(sepp); 1685 1.1 haad if (*sepp++ != ']') 1686 1.1 haad goto fail; 1687 1.1 haad 1688 1.1 haad /* for embedded arrays, support C syntax: "a[1].b" */ 1689 1.1 haad skip_whitespace(sepp); 1690 1.1 haad if (sep && (*sepp == sep)) 1691 1.1 haad sepp++; 1692 1.1 haad } else if (sepp) { 1693 1.1 haad n = sepp++ - np; 1694 1.1 haad } else { 1695 1.1 haad n = strlen(np); 1696 1.1 haad } 1697 1.1 haad 1698 1.1 haad /* trim trailing whitespace by reducing length of 'np' */ 1699 1.1 haad if (n == 0) 1700 1.1 haad goto fail; 1701 1.1 haad for (n--; (np[n] == ' ') || (np[n] == '\t'); n--) 1702 1.1 haad ; 1703 1.1 haad n++; 1704 1.1 haad 1705 1.1 haad /* skip whitespace, and set sepp to NULL if complete */ 1706 1.1 haad if (sepp) { 1707 1.1 haad skip_whitespace(sepp); 1708 1.1 haad if (*sepp == 0) 1709 1.1 haad sepp = NULL; 1710 1.1 haad } 1711 1.1 haad 1712 1.1 haad /* 1713 1.1 haad * At this point: 1714 1.1 haad * o 'n' is the length of current 'np' component. 1715 1.1 haad * o 'idxp' is set if there was an index, and value 'idx'. 1716 1.1 haad * o 'sepp' is set to the beginning of the next component, 1717 1.1 haad * and set to NULL if we have no more components. 1718 1.1 haad * 1719 1.1 haad * Search for nvpair with matching component name. 1720 1.1 haad */ 1721 1.1 haad for (nvp = nvlist_next_nvpair(nvl, NULL); nvp != NULL; 1722 1.1 haad nvp = nvlist_next_nvpair(nvl, nvp)) { 1723 1.1 haad 1724 1.1 haad /* continue if no match on name */ 1725 1.1 haad if (strncmp(np, nvpair_name(nvp), n) || 1726 1.1 haad (strlen(nvpair_name(nvp)) != n)) 1727 1.1 haad continue; 1728 1.1 haad 1729 1.1 haad /* if indexed, verify type is array oriented */ 1730 1.1 haad if (idxp && !nvpair_type_is_array(nvp)) 1731 1.1 haad goto fail; 1732 1.1 haad 1733 1.1 haad /* 1734 1.1 haad * Full match found, return nvp and idx if this 1735 1.1 haad * was the last component. 1736 1.1 haad */ 1737 1.1 haad if (sepp == NULL) { 1738 1.1 haad if (ret) 1739 1.1 haad *ret = nvp; 1740 1.1 haad if (ip && idxp) 1741 1.1 haad *ip = (int)idx; /* return index */ 1742 1.1 haad return (0); /* found */ 1743 1.1 haad } 1744 1.1 haad 1745 1.1 haad /* 1746 1.1 haad * More components: current match must be 1747 1.1 haad * of DATA_TYPE_NVLIST or DATA_TYPE_NVLIST_ARRAY 1748 1.1 haad * to support going deeper. 1749 1.1 haad */ 1750 1.1 haad if (nvpair_type(nvp) == DATA_TYPE_NVLIST) { 1751 1.1 haad nvl = EMBEDDED_NVL(nvp); 1752 1.1 haad break; 1753 1.1 haad } else if (nvpair_type(nvp) == DATA_TYPE_NVLIST_ARRAY) { 1754 1.1 haad (void) nvpair_value_nvlist_array(nvp, 1755 1.1 haad &nva, (uint_t *)&n); 1756 1.1 haad if ((n < 0) || (idx >= n)) 1757 1.1 haad goto fail; 1758 1.1 haad nvl = nva[idx]; 1759 1.1 haad break; 1760 1.1 haad } 1761 1.1 haad 1762 1.1 haad /* type does not support more levels */ 1763 1.1 haad goto fail; 1764 1.1 haad } 1765 1.1 haad if (nvp == NULL) 1766 1.1 haad goto fail; /* 'name' not found */ 1767 1.1 haad 1768 1.1 haad /* search for match of next component in embedded 'nvl' list */ 1769 1.1 haad } 1770 1.1 haad 1771 1.1 haad fail: if (ep && sepp) 1772 1.1 haad *ep = sepp; 1773 1.1 haad return (EINVAL); 1774 1.1 haad } 1775 1.1 haad 1776 1.1 haad /* 1777 1.1 haad * Return pointer to nvpair with specified 'name'. 1778 1.1 haad */ 1779 1.1 haad int 1780 1.1 haad nvlist_lookup_nvpair(nvlist_t *nvl, const char *name, nvpair_t **ret) 1781 1.1 haad { 1782 1.1 haad return (nvlist_lookup_nvpair_ei_sep(nvl, name, 0, ret, NULL, NULL)); 1783 1.1 haad } 1784 1.1 haad 1785 1.1 haad /* 1786 1.1 haad * Determine if named nvpair exists in nvlist (use embedded separator of '.' 1787 1.1 haad * and return array index). See nvlist_lookup_nvpair_ei_sep for more detailed 1788 1.1 haad * description. 1789 1.1 haad */ 1790 1.1 haad int nvlist_lookup_nvpair_embedded_index(nvlist_t *nvl, 1791 1.1 haad const char *name, nvpair_t **ret, int *ip, char **ep) 1792 1.1 haad { 1793 1.1 haad return (nvlist_lookup_nvpair_ei_sep(nvl, name, '.', ret, ip, ep)); 1794 1.1 haad } 1795 1.1 haad 1796 1.1 haad boolean_t 1797 1.1 haad nvlist_exists(nvlist_t *nvl, const char *name) 1798 1.1 haad { 1799 1.1 haad nvpriv_t *priv; 1800 1.1 haad nvpair_t *nvp; 1801 1.1 haad i_nvp_t *curr; 1802 1.1 haad 1803 1.1 haad if (name == NULL || nvl == NULL || 1804 1.1 haad (priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv) == NULL) 1805 1.1 haad return (B_FALSE); 1806 1.1 haad 1807 1.1 haad for (curr = priv->nvp_list; curr != NULL; curr = curr->nvi_next) { 1808 1.1 haad nvp = &curr->nvi_nvp; 1809 1.1 haad 1810 1.1 haad if (strcmp(name, NVP_NAME(nvp)) == 0) 1811 1.1 haad return (B_TRUE); 1812 1.1 haad } 1813 1.1 haad 1814 1.1 haad return (B_FALSE); 1815 1.1 haad } 1816 1.1 haad 1817 1.1 haad int 1818 1.1 haad nvpair_value_boolean_value(nvpair_t *nvp, boolean_t *val) 1819 1.1 haad { 1820 1.1 haad return (nvpair_value_common(nvp, DATA_TYPE_BOOLEAN_VALUE, NULL, val)); 1821 1.1 haad } 1822 1.1 haad 1823 1.1 haad int 1824 1.1 haad nvpair_value_byte(nvpair_t *nvp, uchar_t *val) 1825 1.1 haad { 1826 1.1 haad return (nvpair_value_common(nvp, DATA_TYPE_BYTE, NULL, val)); 1827 1.1 haad } 1828 1.1 haad 1829 1.1 haad int 1830 1.1 haad nvpair_value_int8(nvpair_t *nvp, int8_t *val) 1831 1.1 haad { 1832 1.1 haad return (nvpair_value_common(nvp, DATA_TYPE_INT8, NULL, val)); 1833 1.1 haad } 1834 1.1 haad 1835 1.1 haad int 1836 1.1 haad nvpair_value_uint8(nvpair_t *nvp, uint8_t *val) 1837 1.1 haad { 1838 1.1 haad return (nvpair_value_common(nvp, DATA_TYPE_UINT8, NULL, val)); 1839 1.1 haad } 1840 1.1 haad 1841 1.1 haad int 1842 1.1 haad nvpair_value_int16(nvpair_t *nvp, int16_t *val) 1843 1.1 haad { 1844 1.1 haad return (nvpair_value_common(nvp, DATA_TYPE_INT16, NULL, val)); 1845 1.1 haad } 1846 1.1 haad 1847 1.1 haad int 1848 1.1 haad nvpair_value_uint16(nvpair_t *nvp, uint16_t *val) 1849 1.1 haad { 1850 1.1 haad return (nvpair_value_common(nvp, DATA_TYPE_UINT16, NULL, val)); 1851 1.1 haad } 1852 1.1 haad 1853 1.1 haad int 1854 1.1 haad nvpair_value_int32(nvpair_t *nvp, int32_t *val) 1855 1.1 haad { 1856 1.1 haad return (nvpair_value_common(nvp, DATA_TYPE_INT32, NULL, val)); 1857 1.1 haad } 1858 1.1 haad 1859 1.1 haad int 1860 1.1 haad nvpair_value_uint32(nvpair_t *nvp, uint32_t *val) 1861 1.1 haad { 1862 1.1 haad return (nvpair_value_common(nvp, DATA_TYPE_UINT32, NULL, val)); 1863 1.1 haad } 1864 1.1 haad 1865 1.1 haad int 1866 1.1 haad nvpair_value_int64(nvpair_t *nvp, int64_t *val) 1867 1.1 haad { 1868 1.1 haad return (nvpair_value_common(nvp, DATA_TYPE_INT64, NULL, val)); 1869 1.1 haad } 1870 1.1 haad 1871 1.1 haad int 1872 1.1 haad nvpair_value_uint64(nvpair_t *nvp, uint64_t *val) 1873 1.1 haad { 1874 1.1 haad return (nvpair_value_common(nvp, DATA_TYPE_UINT64, NULL, val)); 1875 1.1 haad } 1876 1.1 haad 1877 1.1 haad #if !defined(_KERNEL) 1878 1.1 haad int 1879 1.1 haad nvpair_value_double(nvpair_t *nvp, double *val) 1880 1.1 haad { 1881 1.1 haad return (nvpair_value_common(nvp, DATA_TYPE_DOUBLE, NULL, val)); 1882 1.1 haad } 1883 1.1 haad #endif 1884 1.1 haad 1885 1.1 haad int 1886 1.1 haad nvpair_value_string(nvpair_t *nvp, char **val) 1887 1.1 haad { 1888 1.1 haad return (nvpair_value_common(nvp, DATA_TYPE_STRING, NULL, val)); 1889 1.1 haad } 1890 1.1 haad 1891 1.1 haad int 1892 1.1 haad nvpair_value_nvlist(nvpair_t *nvp, nvlist_t **val) 1893 1.1 haad { 1894 1.1 haad return (nvpair_value_common(nvp, DATA_TYPE_NVLIST, NULL, val)); 1895 1.1 haad } 1896 1.1 haad 1897 1.1 haad int 1898 1.1 haad nvpair_value_boolean_array(nvpair_t *nvp, boolean_t **val, uint_t *nelem) 1899 1.1 haad { 1900 1.1 haad return (nvpair_value_common(nvp, DATA_TYPE_BOOLEAN_ARRAY, nelem, val)); 1901 1.1 haad } 1902 1.1 haad 1903 1.1 haad int 1904 1.1 haad nvpair_value_byte_array(nvpair_t *nvp, uchar_t **val, uint_t *nelem) 1905 1.1 haad { 1906 1.1 haad return (nvpair_value_common(nvp, DATA_TYPE_BYTE_ARRAY, nelem, val)); 1907 1.1 haad } 1908 1.1 haad 1909 1.1 haad int 1910 1.1 haad nvpair_value_int8_array(nvpair_t *nvp, int8_t **val, uint_t *nelem) 1911 1.1 haad { 1912 1.1 haad return (nvpair_value_common(nvp, DATA_TYPE_INT8_ARRAY, nelem, val)); 1913 1.1 haad } 1914 1.1 haad 1915 1.1 haad int 1916 1.1 haad nvpair_value_uint8_array(nvpair_t *nvp, uint8_t **val, uint_t *nelem) 1917 1.1 haad { 1918 1.1 haad return (nvpair_value_common(nvp, DATA_TYPE_UINT8_ARRAY, nelem, val)); 1919 1.1 haad } 1920 1.1 haad 1921 1.1 haad int 1922 1.1 haad nvpair_value_int16_array(nvpair_t *nvp, int16_t **val, uint_t *nelem) 1923 1.1 haad { 1924 1.1 haad return (nvpair_value_common(nvp, DATA_TYPE_INT16_ARRAY, nelem, val)); 1925 1.1 haad } 1926 1.1 haad 1927 1.1 haad int 1928 1.1 haad nvpair_value_uint16_array(nvpair_t *nvp, uint16_t **val, uint_t *nelem) 1929 1.1 haad { 1930 1.1 haad return (nvpair_value_common(nvp, DATA_TYPE_UINT16_ARRAY, nelem, val)); 1931 1.1 haad } 1932 1.1 haad 1933 1.1 haad int 1934 1.1 haad nvpair_value_int32_array(nvpair_t *nvp, int32_t **val, uint_t *nelem) 1935 1.1 haad { 1936 1.1 haad return (nvpair_value_common(nvp, DATA_TYPE_INT32_ARRAY, nelem, val)); 1937 1.1 haad } 1938 1.1 haad 1939 1.1 haad int 1940 1.1 haad nvpair_value_uint32_array(nvpair_t *nvp, uint32_t **val, uint_t *nelem) 1941 1.1 haad { 1942 1.1 haad return (nvpair_value_common(nvp, DATA_TYPE_UINT32_ARRAY, nelem, val)); 1943 1.1 haad } 1944 1.1 haad 1945 1.1 haad int 1946 1.1 haad nvpair_value_int64_array(nvpair_t *nvp, int64_t **val, uint_t *nelem) 1947 1.1 haad { 1948 1.1 haad return (nvpair_value_common(nvp, DATA_TYPE_INT64_ARRAY, nelem, val)); 1949 1.1 haad } 1950 1.1 haad 1951 1.1 haad int 1952 1.1 haad nvpair_value_uint64_array(nvpair_t *nvp, uint64_t **val, uint_t *nelem) 1953 1.1 haad { 1954 1.1 haad return (nvpair_value_common(nvp, DATA_TYPE_UINT64_ARRAY, nelem, val)); 1955 1.1 haad } 1956 1.1 haad 1957 1.1 haad int 1958 1.1 haad nvpair_value_string_array(nvpair_t *nvp, char ***val, uint_t *nelem) 1959 1.1 haad { 1960 1.1 haad return (nvpair_value_common(nvp, DATA_TYPE_STRING_ARRAY, nelem, val)); 1961 1.1 haad } 1962 1.1 haad 1963 1.1 haad int 1964 1.1 haad nvpair_value_nvlist_array(nvpair_t *nvp, nvlist_t ***val, uint_t *nelem) 1965 1.1 haad { 1966 1.1 haad return (nvpair_value_common(nvp, DATA_TYPE_NVLIST_ARRAY, nelem, val)); 1967 1.1 haad } 1968 1.1 haad 1969 1.1 haad int 1970 1.1 haad nvpair_value_hrtime(nvpair_t *nvp, hrtime_t *val) 1971 1.1 haad { 1972 1.1 haad return (nvpair_value_common(nvp, DATA_TYPE_HRTIME, NULL, val)); 1973 1.1 haad } 1974 1.1 haad 1975 1.1 haad /* 1976 1.1 haad * Add specified pair to the list. 1977 1.1 haad */ 1978 1.1 haad int 1979 1.1 haad nvlist_add_nvpair(nvlist_t *nvl, nvpair_t *nvp) 1980 1.1 haad { 1981 1.1 haad if (nvl == NULL || nvp == NULL) 1982 1.1 haad return (EINVAL); 1983 1.1 haad 1984 1.1 haad return (nvlist_add_common(nvl, NVP_NAME(nvp), NVP_TYPE(nvp), 1985 1.1 haad NVP_NELEM(nvp), NVP_VALUE(nvp))); 1986 1.1 haad } 1987 1.1 haad 1988 1.1 haad /* 1989 1.1 haad * Merge the supplied nvlists and put the result in dst. 1990 1.1 haad * The merged list will contain all names specified in both lists, 1991 1.1 haad * the values are taken from nvl in the case of duplicates. 1992 1.1 haad * Return 0 on success. 1993 1.1 haad */ 1994 1.1 haad /*ARGSUSED*/ 1995 1.1 haad int 1996 1.1 haad nvlist_merge(nvlist_t *dst, nvlist_t *nvl, int flag) 1997 1.1 haad { 1998 1.1 haad if (nvl == NULL || dst == NULL) 1999 1.1 haad return (EINVAL); 2000 1.1 haad 2001 1.1 haad if (dst != nvl) 2002 1.1 haad return (nvlist_copy_pairs(nvl, dst)); 2003 1.1 haad 2004 1.1 haad return (0); 2005 1.1 haad } 2006 1.1 haad 2007 1.1 haad /* 2008 1.1 haad * Encoding related routines 2009 1.1 haad */ 2010 1.1 haad #define NVS_OP_ENCODE 0 2011 1.1 haad #define NVS_OP_DECODE 1 2012 1.1 haad #define NVS_OP_GETSIZE 2 2013 1.1 haad 2014 1.1 haad typedef struct nvs_ops nvs_ops_t; 2015 1.1 haad 2016 1.1 haad typedef struct { 2017 1.1 haad int nvs_op; 2018 1.1 haad const nvs_ops_t *nvs_ops; 2019 1.1 haad void *nvs_private; 2020 1.1 haad nvpriv_t *nvs_priv; 2021 1.1 haad } nvstream_t; 2022 1.1 haad 2023 1.1 haad /* 2024 1.1 haad * nvs operations are: 2025 1.1 haad * - nvs_nvlist 2026 1.1 haad * encoding / decoding of a nvlist header (nvlist_t) 2027 1.1 haad * calculates the size used for header and end detection 2028 1.1 haad * 2029 1.1 haad * - nvs_nvpair 2030 1.1 haad * responsible for the first part of encoding / decoding of an nvpair 2031 1.1 haad * calculates the decoded size of an nvpair 2032 1.1 haad * 2033 1.1 haad * - nvs_nvp_op 2034 1.1 haad * second part of encoding / decoding of an nvpair 2035 1.1 haad * 2036 1.1 haad * - nvs_nvp_size 2037 1.1 haad * calculates the encoding size of an nvpair 2038 1.1 haad * 2039 1.1 haad * - nvs_nvl_fini 2040 1.1 haad * encodes the end detection mark (zeros). 2041 1.1 haad */ 2042 1.1 haad struct nvs_ops { 2043 1.1 haad int (*nvs_nvlist)(nvstream_t *, nvlist_t *, size_t *); 2044 1.1 haad int (*nvs_nvpair)(nvstream_t *, nvpair_t *, size_t *); 2045 1.1 haad int (*nvs_nvp_op)(nvstream_t *, nvpair_t *); 2046 1.1 haad int (*nvs_nvp_size)(nvstream_t *, nvpair_t *, size_t *); 2047 1.1 haad int (*nvs_nvl_fini)(nvstream_t *); 2048 1.1 haad }; 2049 1.1 haad 2050 1.1 haad typedef struct { 2051 1.1 haad char nvh_encoding; /* nvs encoding method */ 2052 1.1 haad char nvh_endian; /* nvs endian */ 2053 1.1 haad char nvh_reserved1; /* reserved for future use */ 2054 1.1 haad char nvh_reserved2; /* reserved for future use */ 2055 1.1 haad } nvs_header_t; 2056 1.1 haad 2057 1.1 haad static int 2058 1.1 haad nvs_encode_pairs(nvstream_t *nvs, nvlist_t *nvl) 2059 1.1 haad { 2060 1.1 haad nvpriv_t *priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv; 2061 1.1 haad i_nvp_t *curr; 2062 1.1 haad 2063 1.1 haad /* 2064 1.1 haad * Walk nvpair in list and encode each nvpair 2065 1.1 haad */ 2066 1.1 haad for (curr = priv->nvp_list; curr != NULL; curr = curr->nvi_next) 2067 1.1 haad if (nvs->nvs_ops->nvs_nvpair(nvs, &curr->nvi_nvp, NULL) != 0) 2068 1.1 haad return (EFAULT); 2069 1.1 haad 2070 1.1 haad return (nvs->nvs_ops->nvs_nvl_fini(nvs)); 2071 1.1 haad } 2072 1.1 haad 2073 1.1 haad static int 2074 1.1 haad nvs_decode_pairs(nvstream_t *nvs, nvlist_t *nvl) 2075 1.1 haad { 2076 1.1 haad nvpair_t *nvp; 2077 1.1 haad size_t nvsize; 2078 1.1 haad int err; 2079 1.1 haad 2080 1.1 haad /* 2081 1.1 haad * Get decoded size of next pair in stream, alloc 2082 1.1 haad * memory for nvpair_t, then decode the nvpair 2083 1.1 haad */ 2084 1.1 haad while ((err = nvs->nvs_ops->nvs_nvpair(nvs, NULL, &nvsize)) == 0) { 2085 1.1 haad if (nvsize == 0) /* end of list */ 2086 1.1 haad break; 2087 1.1 haad 2088 1.1 haad /* make sure len makes sense */ 2089 1.1 haad if (nvsize < NVP_SIZE_CALC(1, 0)) 2090 1.1 haad return (EFAULT); 2091 1.1 haad 2092 1.1 haad if ((nvp = nvp_buf_alloc(nvl, nvsize)) == NULL) 2093 1.1 haad return (ENOMEM); 2094 1.1 haad 2095 1.1 haad if ((err = nvs->nvs_ops->nvs_nvp_op(nvs, nvp)) != 0) { 2096 1.1 haad nvp_buf_free(nvl, nvp); 2097 1.1 haad return (err); 2098 1.1 haad } 2099 1.1 haad 2100 1.1 haad if (i_validate_nvpair(nvp) != 0) { 2101 1.1 haad nvpair_free(nvp); 2102 1.1 haad nvp_buf_free(nvl, nvp); 2103 1.1 haad return (EFAULT); 2104 1.1 haad } 2105 1.1 haad 2106 1.1 haad nvp_buf_link(nvl, nvp); 2107 1.1 haad } 2108 1.1 haad return (err); 2109 1.1 haad } 2110 1.1 haad 2111 1.1 haad static int 2112 1.1 haad nvs_getsize_pairs(nvstream_t *nvs, nvlist_t *nvl, size_t *buflen) 2113 1.1 haad { 2114 1.1 haad nvpriv_t *priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv; 2115 1.1 haad i_nvp_t *curr; 2116 1.1 haad uint64_t nvsize = *buflen; 2117 1.1 haad size_t size; 2118 1.1 haad 2119 1.1 haad /* 2120 1.1 haad * Get encoded size of nvpairs in nvlist 2121 1.1 haad */ 2122 1.1 haad for (curr = priv->nvp_list; curr != NULL; curr = curr->nvi_next) { 2123 1.1 haad if (nvs->nvs_ops->nvs_nvp_size(nvs, &curr->nvi_nvp, &size) != 0) 2124 1.1 haad return (EINVAL); 2125 1.1 haad 2126 1.1 haad if ((nvsize += size) > INT32_MAX) 2127 1.1 haad return (EINVAL); 2128 1.1 haad } 2129 1.1 haad 2130 1.1 haad *buflen = nvsize; 2131 1.1 haad return (0); 2132 1.1 haad } 2133 1.1 haad 2134 1.1 haad static int 2135 1.1 haad nvs_operation(nvstream_t *nvs, nvlist_t *nvl, size_t *buflen) 2136 1.1 haad { 2137 1.1 haad int err; 2138 1.1 haad 2139 1.1 haad if (nvl->nvl_priv == 0) 2140 1.1 haad return (EFAULT); 2141 1.1 haad 2142 1.1 haad /* 2143 1.1 haad * Perform the operation, starting with header, then each nvpair 2144 1.1 haad */ 2145 1.1 haad if ((err = nvs->nvs_ops->nvs_nvlist(nvs, nvl, buflen)) != 0) 2146 1.1 haad return (err); 2147 1.1 haad 2148 1.1 haad switch (nvs->nvs_op) { 2149 1.1 haad case NVS_OP_ENCODE: 2150 1.1 haad err = nvs_encode_pairs(nvs, nvl); 2151 1.1 haad break; 2152 1.1 haad 2153 1.1 haad case NVS_OP_DECODE: 2154 1.1 haad err = nvs_decode_pairs(nvs, nvl); 2155 1.1 haad break; 2156 1.1 haad 2157 1.1 haad case NVS_OP_GETSIZE: 2158 1.1 haad err = nvs_getsize_pairs(nvs, nvl, buflen); 2159 1.1 haad break; 2160 1.1 haad 2161 1.1 haad default: 2162 1.1 haad err = EINVAL; 2163 1.1 haad } 2164 1.1 haad 2165 1.1 haad return (err); 2166 1.1 haad } 2167 1.1 haad 2168 1.1 haad static int 2169 1.1 haad nvs_embedded(nvstream_t *nvs, nvlist_t *embedded) 2170 1.1 haad { 2171 1.1 haad switch (nvs->nvs_op) { 2172 1.1 haad case NVS_OP_ENCODE: 2173 1.1 haad return (nvs_operation(nvs, embedded, NULL)); 2174 1.1 haad 2175 1.1 haad case NVS_OP_DECODE: { 2176 1.1 haad nvpriv_t *priv; 2177 1.1 haad int err; 2178 1.1 haad 2179 1.1 haad if (embedded->nvl_version != NV_VERSION) 2180 1.1 haad return (ENOTSUP); 2181 1.1 haad 2182 1.1 haad if ((priv = nv_priv_alloc_embedded(nvs->nvs_priv)) == NULL) 2183 1.1 haad return (ENOMEM); 2184 1.1 haad 2185 1.1 haad nvlist_init(embedded, embedded->nvl_nvflag, priv); 2186 1.1 haad 2187 1.1 haad if ((err = nvs_operation(nvs, embedded, NULL)) != 0) 2188 1.1 haad nvlist_free(embedded); 2189 1.1 haad return (err); 2190 1.1 haad } 2191 1.1 haad default: 2192 1.1 haad break; 2193 1.1 haad } 2194 1.1 haad 2195 1.1 haad return (EINVAL); 2196 1.1 haad } 2197 1.1 haad 2198 1.1 haad static int 2199 1.1 haad nvs_embedded_nvl_array(nvstream_t *nvs, nvpair_t *nvp, size_t *size) 2200 1.1 haad { 2201 1.1 haad size_t nelem = NVP_NELEM(nvp); 2202 1.1 haad nvlist_t **nvlp = EMBEDDED_NVL_ARRAY(nvp); 2203 1.1 haad int i; 2204 1.1 haad 2205 1.1 haad switch (nvs->nvs_op) { 2206 1.1 haad case NVS_OP_ENCODE: 2207 1.1 haad for (i = 0; i < nelem; i++) 2208 1.1 haad if (nvs_embedded(nvs, nvlp[i]) != 0) 2209 1.1 haad return (EFAULT); 2210 1.1 haad break; 2211 1.1 haad 2212 1.1 haad case NVS_OP_DECODE: { 2213 1.1 haad size_t len = nelem * sizeof (uint64_t); 2214 1.1 haad nvlist_t *embedded = (nvlist_t *)((uintptr_t)nvlp + len); 2215 1.1 haad 2216 1.1 haad bzero(nvlp, len); /* don't trust packed data */ 2217 1.1 haad for (i = 0; i < nelem; i++) { 2218 1.1 haad if (nvs_embedded(nvs, embedded) != 0) { 2219 1.1 haad nvpair_free(nvp); 2220 1.1 haad return (EFAULT); 2221 1.1 haad } 2222 1.1 haad 2223 1.1 haad nvlp[i] = embedded++; 2224 1.1 haad } 2225 1.1 haad break; 2226 1.1 haad } 2227 1.1 haad case NVS_OP_GETSIZE: { 2228 1.1 haad uint64_t nvsize = 0; 2229 1.1 haad 2230 1.1 haad for (i = 0; i < nelem; i++) { 2231 1.1 haad size_t nvp_sz = 0; 2232 1.1 haad 2233 1.1 haad if (nvs_operation(nvs, nvlp[i], &nvp_sz) != 0) 2234 1.1 haad return (EINVAL); 2235 1.1 haad 2236 1.1 haad if ((nvsize += nvp_sz) > INT32_MAX) 2237 1.1 haad return (EINVAL); 2238 1.1 haad } 2239 1.1 haad 2240 1.1 haad *size = nvsize; 2241 1.1 haad break; 2242 1.1 haad } 2243 1.1 haad default: 2244 1.1 haad return (EINVAL); 2245 1.1 haad } 2246 1.1 haad 2247 1.1 haad return (0); 2248 1.1 haad } 2249 1.1 haad 2250 1.1 haad static int nvs_native(nvstream_t *, nvlist_t *, char *, size_t *); 2251 1.1 haad static int nvs_xdr(nvstream_t *, nvlist_t *, char *, size_t *); 2252 1.1 haad 2253 1.1 haad /* 2254 1.1 haad * Common routine for nvlist operations: 2255 1.1 haad * encode, decode, getsize (encoded size). 2256 1.1 haad */ 2257 1.1 haad static int 2258 1.1 haad nvlist_common(nvlist_t *nvl, char *buf, size_t *buflen, int encoding, 2259 1.1 haad int nvs_op) 2260 1.1 haad { 2261 1.1 haad int err = 0; 2262 1.1 haad nvstream_t nvs; 2263 1.1 haad int nvl_endian; 2264 1.6 hannken #if BYTE_ORDER == BIG_ENDIAN 2265 1.6 hannken int host_endian = 0; 2266 1.6 hannken #else 2267 1.1 haad int host_endian = 1; 2268 1.6 hannken #endif /* BYTE_ORDER */ 2269 1.1 haad nvs_header_t *nvh = (void *)buf; 2270 1.1 haad 2271 1.1 haad if (buflen == NULL || nvl == NULL || 2272 1.1 haad (nvs.nvs_priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv) == NULL) 2273 1.1 haad return (EINVAL); 2274 1.1 haad 2275 1.1 haad nvs.nvs_op = nvs_op; 2276 1.1 haad 2277 1.1 haad /* 2278 1.1 haad * For NVS_OP_ENCODE and NVS_OP_DECODE make sure an nvlist and 2279 1.1 haad * a buffer is allocated. The first 4 bytes in the buffer are 2280 1.1 haad * used for encoding method and host endian. 2281 1.1 haad */ 2282 1.1 haad switch (nvs_op) { 2283 1.1 haad case NVS_OP_ENCODE: 2284 1.1 haad if (buf == NULL || *buflen < sizeof (nvs_header_t)) 2285 1.1 haad return (EINVAL); 2286 1.1 haad 2287 1.1 haad nvh->nvh_encoding = encoding; 2288 1.1 haad nvh->nvh_endian = nvl_endian = host_endian; 2289 1.1 haad nvh->nvh_reserved1 = 0; 2290 1.1 haad nvh->nvh_reserved2 = 0; 2291 1.1 haad break; 2292 1.1 haad 2293 1.1 haad case NVS_OP_DECODE: 2294 1.1 haad if (buf == NULL || *buflen < sizeof (nvs_header_t)) 2295 1.1 haad return (EINVAL); 2296 1.1 haad 2297 1.1 haad /* get method of encoding from first byte */ 2298 1.1 haad encoding = nvh->nvh_encoding; 2299 1.1 haad nvl_endian = nvh->nvh_endian; 2300 1.1 haad break; 2301 1.1 haad 2302 1.1 haad case NVS_OP_GETSIZE: 2303 1.1 haad nvl_endian = host_endian; 2304 1.1 haad 2305 1.1 haad /* 2306 1.1 haad * add the size for encoding 2307 1.1 haad */ 2308 1.1 haad *buflen = sizeof (nvs_header_t); 2309 1.1 haad break; 2310 1.1 haad 2311 1.1 haad default: 2312 1.1 haad return (ENOTSUP); 2313 1.1 haad } 2314 1.1 haad 2315 1.1 haad /* 2316 1.1 haad * Create an nvstream with proper encoding method 2317 1.1 haad */ 2318 1.1 haad switch (encoding) { 2319 1.1 haad case NV_ENCODE_NATIVE: 2320 1.1 haad /* 2321 1.1 haad * check endianness, in case we are unpacking 2322 1.1 haad * from a file 2323 1.1 haad */ 2324 1.1 haad if (nvl_endian != host_endian) 2325 1.1 haad return (ENOTSUP); 2326 1.1 haad err = nvs_native(&nvs, nvl, buf, buflen); 2327 1.1 haad break; 2328 1.1 haad case NV_ENCODE_XDR: 2329 1.1 haad err = nvs_xdr(&nvs, nvl, buf, buflen); 2330 1.1 haad break; 2331 1.1 haad default: 2332 1.1 haad err = ENOTSUP; 2333 1.1 haad break; 2334 1.1 haad } 2335 1.1 haad 2336 1.1 haad return (err); 2337 1.1 haad } 2338 1.1 haad 2339 1.1 haad int 2340 1.1 haad nvlist_size(nvlist_t *nvl, size_t *size, int encoding) 2341 1.1 haad { 2342 1.1 haad return (nvlist_common(nvl, NULL, size, encoding, NVS_OP_GETSIZE)); 2343 1.1 haad } 2344 1.1 haad 2345 1.1 haad /* 2346 1.1 haad * Pack nvlist into contiguous memory 2347 1.1 haad */ 2348 1.1 haad /*ARGSUSED1*/ 2349 1.1 haad int 2350 1.1 haad nvlist_pack(nvlist_t *nvl, char **bufp, size_t *buflen, int encoding, 2351 1.1 haad int kmflag) 2352 1.1 haad { 2353 1.1 haad #if defined(_KERNEL) && !defined(_BOOT) 2354 1.1 haad return (nvlist_xpack(nvl, bufp, buflen, encoding, 2355 1.1 haad (kmflag == KM_SLEEP ? nv_alloc_sleep : nv_alloc_nosleep))); 2356 1.1 haad #else 2357 1.1 haad return (nvlist_xpack(nvl, bufp, buflen, encoding, nv_alloc_nosleep)); 2358 1.1 haad #endif 2359 1.1 haad } 2360 1.1 haad 2361 1.1 haad int 2362 1.1 haad nvlist_xpack(nvlist_t *nvl, char **bufp, size_t *buflen, int encoding, 2363 1.1 haad nv_alloc_t *nva) 2364 1.1 haad { 2365 1.1 haad nvpriv_t nvpriv; 2366 1.1 haad size_t alloc_size; 2367 1.1 haad char *buf; 2368 1.1 haad int err; 2369 1.1 haad 2370 1.1 haad if (nva == NULL || nvl == NULL || bufp == NULL || buflen == NULL) 2371 1.1 haad return (EINVAL); 2372 1.1 haad 2373 1.1 haad if (*bufp != NULL) 2374 1.1 haad return (nvlist_common(nvl, *bufp, buflen, encoding, 2375 1.1 haad NVS_OP_ENCODE)); 2376 1.1 haad 2377 1.1 haad /* 2378 1.1 haad * Here is a difficult situation: 2379 1.1 haad * 1. The nvlist has fixed allocator properties. 2380 1.1 haad * All other nvlist routines (like nvlist_add_*, ...) use 2381 1.1 haad * these properties. 2382 1.1 haad * 2. When using nvlist_pack() the user can specify his own 2383 1.1 haad * allocator properties (e.g. by using KM_NOSLEEP). 2384 1.1 haad * 2385 1.1 haad * We use the user specified properties (2). A clearer solution 2386 1.1 haad * will be to remove the kmflag from nvlist_pack(), but we will 2387 1.1 haad * not change the interface. 2388 1.1 haad */ 2389 1.1 haad nv_priv_init(&nvpriv, nva, 0); 2390 1.1 haad 2391 1.2 dsl if ((err = nvlist_size(nvl, &alloc_size, encoding))) 2392 1.1 haad return (err); 2393 1.1 haad 2394 1.1 haad if ((buf = nv_mem_zalloc(&nvpriv, alloc_size)) == NULL) 2395 1.1 haad return (ENOMEM); 2396 1.1 haad 2397 1.1 haad if ((err = nvlist_common(nvl, buf, &alloc_size, encoding, 2398 1.1 haad NVS_OP_ENCODE)) != 0) { 2399 1.1 haad nv_mem_free(&nvpriv, buf, alloc_size); 2400 1.1 haad } else { 2401 1.1 haad *buflen = alloc_size; 2402 1.1 haad *bufp = buf; 2403 1.1 haad } 2404 1.1 haad 2405 1.1 haad return (err); 2406 1.1 haad } 2407 1.1 haad 2408 1.1 haad /* 2409 1.1 haad * Unpack buf into an nvlist_t 2410 1.1 haad */ 2411 1.1 haad /*ARGSUSED1*/ 2412 1.1 haad int 2413 1.1 haad nvlist_unpack(char *buf, size_t buflen, nvlist_t **nvlp, int kmflag) 2414 1.1 haad { 2415 1.1 haad #if defined(_KERNEL) && !defined(_BOOT) 2416 1.1 haad return (nvlist_xunpack(buf, buflen, nvlp, 2417 1.1 haad (kmflag == KM_SLEEP ? nv_alloc_sleep : nv_alloc_nosleep))); 2418 1.1 haad #else 2419 1.1 haad return (nvlist_xunpack(buf, buflen, nvlp, nv_alloc_nosleep)); 2420 1.1 haad #endif 2421 1.1 haad } 2422 1.1 haad 2423 1.1 haad int 2424 1.1 haad nvlist_xunpack(char *buf, size_t buflen, nvlist_t **nvlp, nv_alloc_t *nva) 2425 1.1 haad { 2426 1.1 haad nvlist_t *nvl; 2427 1.1 haad int err; 2428 1.1 haad 2429 1.1 haad if (nvlp == NULL) 2430 1.1 haad return (EINVAL); 2431 1.1 haad 2432 1.1 haad if ((err = nvlist_xalloc(&nvl, 0, nva)) != 0) 2433 1.1 haad return (err); 2434 1.1 haad 2435 1.1 haad if ((err = nvlist_common(nvl, buf, &buflen, 0, NVS_OP_DECODE)) != 0) 2436 1.1 haad nvlist_free(nvl); 2437 1.1 haad else 2438 1.1 haad *nvlp = nvl; 2439 1.1 haad 2440 1.1 haad return (err); 2441 1.1 haad } 2442 1.1 haad 2443 1.1 haad /* 2444 1.1 haad * Native encoding functions 2445 1.1 haad */ 2446 1.1 haad typedef struct { 2447 1.1 haad /* 2448 1.1 haad * This structure is used when decoding a packed nvpair in 2449 1.1 haad * the native format. n_base points to a buffer containing the 2450 1.1 haad * packed nvpair. n_end is a pointer to the end of the buffer. 2451 1.1 haad * (n_end actually points to the first byte past the end of the 2452 1.1 haad * buffer.) n_curr is a pointer that lies between n_base and n_end. 2453 1.1 haad * It points to the current data that we are decoding. 2454 1.1 haad * The amount of data left in the buffer is equal to n_end - n_curr. 2455 1.1 haad * n_flag is used to recognize a packed embedded list. 2456 1.1 haad */ 2457 1.1 haad caddr_t n_base; 2458 1.1 haad caddr_t n_end; 2459 1.1 haad caddr_t n_curr; 2460 1.1 haad uint_t n_flag; 2461 1.1 haad } nvs_native_t; 2462 1.1 haad 2463 1.1 haad static int 2464 1.1 haad nvs_native_create(nvstream_t *nvs, nvs_native_t *native, char *buf, 2465 1.1 haad size_t buflen) 2466 1.1 haad { 2467 1.1 haad switch (nvs->nvs_op) { 2468 1.1 haad case NVS_OP_ENCODE: 2469 1.1 haad case NVS_OP_DECODE: 2470 1.1 haad nvs->nvs_private = native; 2471 1.1 haad native->n_curr = native->n_base = buf; 2472 1.1 haad native->n_end = buf + buflen; 2473 1.1 haad native->n_flag = 0; 2474 1.1 haad return (0); 2475 1.1 haad 2476 1.1 haad case NVS_OP_GETSIZE: 2477 1.1 haad nvs->nvs_private = native; 2478 1.1 haad native->n_curr = native->n_base = native->n_end = NULL; 2479 1.1 haad native->n_flag = 0; 2480 1.1 haad return (0); 2481 1.1 haad default: 2482 1.1 haad return (EINVAL); 2483 1.1 haad } 2484 1.1 haad } 2485 1.1 haad 2486 1.1 haad /*ARGSUSED*/ 2487 1.1 haad static void 2488 1.1 haad nvs_native_destroy(nvstream_t *nvs) 2489 1.1 haad { 2490 1.1 haad } 2491 1.1 haad 2492 1.1 haad static int 2493 1.1 haad native_cp(nvstream_t *nvs, void *buf, size_t size) 2494 1.1 haad { 2495 1.1 haad nvs_native_t *native = (nvs_native_t *)nvs->nvs_private; 2496 1.1 haad 2497 1.1 haad if (native->n_curr + size > native->n_end) 2498 1.1 haad return (EFAULT); 2499 1.1 haad 2500 1.1 haad /* 2501 1.1 haad * The bcopy() below eliminates alignment requirement 2502 1.1 haad * on the buffer (stream) and is preferred over direct access. 2503 1.1 haad */ 2504 1.1 haad switch (nvs->nvs_op) { 2505 1.1 haad case NVS_OP_ENCODE: 2506 1.1 haad bcopy(buf, native->n_curr, size); 2507 1.1 haad break; 2508 1.1 haad case NVS_OP_DECODE: 2509 1.1 haad bcopy(native->n_curr, buf, size); 2510 1.1 haad break; 2511 1.1 haad default: 2512 1.1 haad return (EINVAL); 2513 1.1 haad } 2514 1.1 haad 2515 1.1 haad native->n_curr += size; 2516 1.1 haad return (0); 2517 1.1 haad } 2518 1.1 haad 2519 1.1 haad /* 2520 1.1 haad * operate on nvlist_t header 2521 1.1 haad */ 2522 1.1 haad static int 2523 1.1 haad nvs_native_nvlist(nvstream_t *nvs, nvlist_t *nvl, size_t *size) 2524 1.1 haad { 2525 1.1 haad nvs_native_t *native = nvs->nvs_private; 2526 1.1 haad 2527 1.1 haad switch (nvs->nvs_op) { 2528 1.1 haad case NVS_OP_ENCODE: 2529 1.1 haad case NVS_OP_DECODE: 2530 1.1 haad if (native->n_flag) 2531 1.1 haad return (0); /* packed embedded list */ 2532 1.1 haad 2533 1.1 haad native->n_flag = 1; 2534 1.1 haad 2535 1.1 haad /* copy version and nvflag of the nvlist_t */ 2536 1.1 haad if (native_cp(nvs, &nvl->nvl_version, sizeof (int32_t)) != 0 || 2537 1.1 haad native_cp(nvs, &nvl->nvl_nvflag, sizeof (int32_t)) != 0) 2538 1.1 haad return (EFAULT); 2539 1.1 haad 2540 1.1 haad return (0); 2541 1.1 haad 2542 1.1 haad case NVS_OP_GETSIZE: 2543 1.1 haad /* 2544 1.1 haad * if calculate for packed embedded list 2545 1.1 haad * 4 for end of the embedded list 2546 1.1 haad * else 2547 1.1 haad * 2 * sizeof (int32_t) for nvl_version and nvl_nvflag 2548 1.1 haad * and 4 for end of the entire list 2549 1.1 haad */ 2550 1.1 haad if (native->n_flag) { 2551 1.1 haad *size += 4; 2552 1.1 haad } else { 2553 1.1 haad native->n_flag = 1; 2554 1.1 haad *size += 2 * sizeof (int32_t) + 4; 2555 1.1 haad } 2556 1.1 haad 2557 1.1 haad return (0); 2558 1.1 haad 2559 1.1 haad default: 2560 1.1 haad return (EINVAL); 2561 1.1 haad } 2562 1.1 haad } 2563 1.1 haad 2564 1.1 haad static int 2565 1.1 haad nvs_native_nvl_fini(nvstream_t *nvs) 2566 1.1 haad { 2567 1.1 haad if (nvs->nvs_op == NVS_OP_ENCODE) { 2568 1.1 haad nvs_native_t *native = (nvs_native_t *)nvs->nvs_private; 2569 1.1 haad /* 2570 1.1 haad * Add 4 zero bytes at end of nvlist. They are used 2571 1.1 haad * for end detection by the decode routine. 2572 1.1 haad */ 2573 1.1 haad if (native->n_curr + sizeof (int) > native->n_end) 2574 1.1 haad return (EFAULT); 2575 1.1 haad 2576 1.1 haad bzero(native->n_curr, sizeof (int)); 2577 1.1 haad native->n_curr += sizeof (int); 2578 1.1 haad } 2579 1.1 haad 2580 1.1 haad return (0); 2581 1.1 haad } 2582 1.1 haad 2583 1.1 haad static int 2584 1.1 haad nvpair_native_embedded(nvstream_t *nvs, nvpair_t *nvp) 2585 1.1 haad { 2586 1.1 haad if (nvs->nvs_op == NVS_OP_ENCODE) { 2587 1.1 haad nvs_native_t *native = (nvs_native_t *)nvs->nvs_private; 2588 1.1 haad nvlist_t *packed = (void *) 2589 1.1 haad (native->n_curr - nvp->nvp_size + NVP_VALOFF(nvp)); 2590 1.1 haad /* 2591 1.1 haad * Null out the pointer that is meaningless in the packed 2592 1.1 haad * structure. The address may not be aligned, so we have 2593 1.1 haad * to use bzero. 2594 1.1 haad */ 2595 1.5 kamil bzero((char *)packed + offsetof(nvlist_t, nvl_priv), 2596 1.5 kamil sizeof (uint64_t)); 2597 1.1 haad } 2598 1.1 haad 2599 1.1 haad return (nvs_embedded(nvs, EMBEDDED_NVL(nvp))); 2600 1.1 haad } 2601 1.1 haad 2602 1.1 haad static int 2603 1.1 haad nvpair_native_embedded_array(nvstream_t *nvs, nvpair_t *nvp) 2604 1.1 haad { 2605 1.1 haad if (nvs->nvs_op == NVS_OP_ENCODE) { 2606 1.1 haad nvs_native_t *native = (nvs_native_t *)nvs->nvs_private; 2607 1.1 haad char *value = native->n_curr - nvp->nvp_size + NVP_VALOFF(nvp); 2608 1.1 haad size_t len = NVP_NELEM(nvp) * sizeof (uint64_t); 2609 1.1 haad nvlist_t *packed = (nvlist_t *)((uintptr_t)value + len); 2610 1.1 haad int i; 2611 1.1 haad /* 2612 1.1 haad * Null out pointers that are meaningless in the packed 2613 1.1 haad * structure. The addresses may not be aligned, so we have 2614 1.1 haad * to use bzero. 2615 1.1 haad */ 2616 1.1 haad bzero(value, len); 2617 1.1 haad 2618 1.1 haad for (i = 0; i < NVP_NELEM(nvp); i++, packed++) 2619 1.1 haad /* 2620 1.1 haad * Null out the pointer that is meaningless in the 2621 1.1 haad * packed structure. The address may not be aligned, 2622 1.1 haad * so we have to use bzero. 2623 1.1 haad */ 2624 1.5 kamil bzero((char *)packed + offsetof(nvlist_t, nvl_priv), 2625 1.5 kamil sizeof (uint64_t)); 2626 1.1 haad } 2627 1.1 haad 2628 1.1 haad return (nvs_embedded_nvl_array(nvs, nvp, NULL)); 2629 1.1 haad } 2630 1.1 haad 2631 1.1 haad static void 2632 1.1 haad nvpair_native_string_array(nvstream_t *nvs, nvpair_t *nvp) 2633 1.1 haad { 2634 1.1 haad switch (nvs->nvs_op) { 2635 1.1 haad case NVS_OP_ENCODE: { 2636 1.1 haad nvs_native_t *native = (nvs_native_t *)nvs->nvs_private; 2637 1.1 haad uint64_t *strp = (void *) 2638 1.1 haad (native->n_curr - nvp->nvp_size + NVP_VALOFF(nvp)); 2639 1.1 haad /* 2640 1.1 haad * Null out pointers that are meaningless in the packed 2641 1.1 haad * structure. The addresses may not be aligned, so we have 2642 1.1 haad * to use bzero. 2643 1.1 haad */ 2644 1.1 haad bzero(strp, NVP_NELEM(nvp) * sizeof (uint64_t)); 2645 1.1 haad break; 2646 1.1 haad } 2647 1.1 haad case NVS_OP_DECODE: { 2648 1.1 haad char **strp = (void *)NVP_VALUE(nvp); 2649 1.1 haad char *buf = ((char *)strp + NVP_NELEM(nvp) * sizeof (uint64_t)); 2650 1.1 haad int i; 2651 1.1 haad 2652 1.1 haad for (i = 0; i < NVP_NELEM(nvp); i++) { 2653 1.1 haad strp[i] = buf; 2654 1.1 haad buf += strlen(buf) + 1; 2655 1.1 haad } 2656 1.1 haad break; 2657 1.1 haad } 2658 1.1 haad } 2659 1.1 haad } 2660 1.1 haad 2661 1.1 haad static int 2662 1.1 haad nvs_native_nvp_op(nvstream_t *nvs, nvpair_t *nvp) 2663 1.1 haad { 2664 1.1 haad data_type_t type; 2665 1.1 haad int value_sz; 2666 1.1 haad int ret = 0; 2667 1.1 haad 2668 1.1 haad /* 2669 1.1 haad * We do the initial bcopy of the data before we look at 2670 1.1 haad * the nvpair type, because when we're decoding, we won't 2671 1.1 haad * have the correct values for the pair until we do the bcopy. 2672 1.1 haad */ 2673 1.1 haad switch (nvs->nvs_op) { 2674 1.1 haad case NVS_OP_ENCODE: 2675 1.1 haad case NVS_OP_DECODE: 2676 1.1 haad if (native_cp(nvs, nvp, nvp->nvp_size) != 0) 2677 1.1 haad return (EFAULT); 2678 1.1 haad break; 2679 1.1 haad default: 2680 1.1 haad return (EINVAL); 2681 1.1 haad } 2682 1.1 haad 2683 1.1 haad /* verify nvp_name_sz, check the name string length */ 2684 1.1 haad if (i_validate_nvpair_name(nvp) != 0) 2685 1.1 haad return (EFAULT); 2686 1.1 haad 2687 1.1 haad type = NVP_TYPE(nvp); 2688 1.1 haad 2689 1.1 haad /* 2690 1.1 haad * Verify type and nelem and get the value size. 2691 1.1 haad * In case of data types DATA_TYPE_STRING and DATA_TYPE_STRING_ARRAY 2692 1.1 haad * is the size of the string(s) excluded. 2693 1.1 haad */ 2694 1.1 haad if ((value_sz = i_get_value_size(type, NULL, NVP_NELEM(nvp))) < 0) 2695 1.1 haad return (EFAULT); 2696 1.1 haad 2697 1.1 haad if (NVP_SIZE_CALC(nvp->nvp_name_sz, value_sz) > nvp->nvp_size) 2698 1.1 haad return (EFAULT); 2699 1.1 haad 2700 1.1 haad switch (type) { 2701 1.1 haad case DATA_TYPE_NVLIST: 2702 1.1 haad ret = nvpair_native_embedded(nvs, nvp); 2703 1.1 haad break; 2704 1.1 haad case DATA_TYPE_NVLIST_ARRAY: 2705 1.1 haad ret = nvpair_native_embedded_array(nvs, nvp); 2706 1.1 haad break; 2707 1.1 haad case DATA_TYPE_STRING_ARRAY: 2708 1.1 haad nvpair_native_string_array(nvs, nvp); 2709 1.1 haad break; 2710 1.1 haad default: 2711 1.1 haad break; 2712 1.1 haad } 2713 1.1 haad 2714 1.1 haad return (ret); 2715 1.1 haad } 2716 1.1 haad 2717 1.1 haad static int 2718 1.1 haad nvs_native_nvp_size(nvstream_t *nvs, nvpair_t *nvp, size_t *size) 2719 1.1 haad { 2720 1.1 haad uint64_t nvp_sz = nvp->nvp_size; 2721 1.1 haad 2722 1.1 haad switch (NVP_TYPE(nvp)) { 2723 1.1 haad case DATA_TYPE_NVLIST: { 2724 1.1 haad size_t nvsize = 0; 2725 1.1 haad 2726 1.1 haad if (nvs_operation(nvs, EMBEDDED_NVL(nvp), &nvsize) != 0) 2727 1.1 haad return (EINVAL); 2728 1.1 haad 2729 1.1 haad nvp_sz += nvsize; 2730 1.1 haad break; 2731 1.1 haad } 2732 1.1 haad case DATA_TYPE_NVLIST_ARRAY: { 2733 1.1 haad size_t nvsize; 2734 1.1 haad 2735 1.1 haad if (nvs_embedded_nvl_array(nvs, nvp, &nvsize) != 0) 2736 1.1 haad return (EINVAL); 2737 1.1 haad 2738 1.1 haad nvp_sz += nvsize; 2739 1.1 haad break; 2740 1.1 haad } 2741 1.1 haad default: 2742 1.1 haad break; 2743 1.1 haad } 2744 1.1 haad 2745 1.1 haad if (nvp_sz > INT32_MAX) 2746 1.1 haad return (EINVAL); 2747 1.1 haad 2748 1.1 haad *size = nvp_sz; 2749 1.1 haad 2750 1.1 haad return (0); 2751 1.1 haad } 2752 1.1 haad 2753 1.1 haad static int 2754 1.1 haad nvs_native_nvpair(nvstream_t *nvs, nvpair_t *nvp, size_t *size) 2755 1.1 haad { 2756 1.1 haad switch (nvs->nvs_op) { 2757 1.1 haad case NVS_OP_ENCODE: 2758 1.1 haad return (nvs_native_nvp_op(nvs, nvp)); 2759 1.1 haad 2760 1.1 haad case NVS_OP_DECODE: { 2761 1.1 haad nvs_native_t *native = (nvs_native_t *)nvs->nvs_private; 2762 1.1 haad int32_t decode_len; 2763 1.1 haad 2764 1.1 haad /* try to read the size value from the stream */ 2765 1.1 haad if (native->n_curr + sizeof (int32_t) > native->n_end) 2766 1.1 haad return (EFAULT); 2767 1.1 haad bcopy(native->n_curr, &decode_len, sizeof (int32_t)); 2768 1.1 haad 2769 1.1 haad /* sanity check the size value */ 2770 1.1 haad if (decode_len < 0 || 2771 1.1 haad decode_len > native->n_end - native->n_curr) 2772 1.1 haad return (EFAULT); 2773 1.1 haad 2774 1.1 haad *size = decode_len; 2775 1.1 haad 2776 1.1 haad /* 2777 1.1 haad * If at the end of the stream then move the cursor 2778 1.1 haad * forward, otherwise nvpair_native_op() will read 2779 1.1 haad * the entire nvpair at the same cursor position. 2780 1.1 haad */ 2781 1.1 haad if (*size == 0) 2782 1.1 haad native->n_curr += sizeof (int32_t); 2783 1.1 haad break; 2784 1.1 haad } 2785 1.1 haad 2786 1.1 haad default: 2787 1.1 haad return (EINVAL); 2788 1.1 haad } 2789 1.1 haad 2790 1.1 haad return (0); 2791 1.1 haad } 2792 1.1 haad 2793 1.1 haad static const nvs_ops_t nvs_native_ops = { 2794 1.1 haad nvs_native_nvlist, 2795 1.1 haad nvs_native_nvpair, 2796 1.1 haad nvs_native_nvp_op, 2797 1.1 haad nvs_native_nvp_size, 2798 1.1 haad nvs_native_nvl_fini 2799 1.1 haad }; 2800 1.1 haad 2801 1.1 haad static int 2802 1.1 haad nvs_native(nvstream_t *nvs, nvlist_t *nvl, char *buf, size_t *buflen) 2803 1.1 haad { 2804 1.1 haad nvs_native_t native; 2805 1.1 haad int err; 2806 1.1 haad 2807 1.1 haad nvs->nvs_ops = &nvs_native_ops; 2808 1.1 haad 2809 1.1 haad if ((err = nvs_native_create(nvs, &native, buf + sizeof (nvs_header_t), 2810 1.1 haad *buflen - sizeof (nvs_header_t))) != 0) 2811 1.1 haad return (err); 2812 1.1 haad 2813 1.1 haad err = nvs_operation(nvs, nvl, buflen); 2814 1.1 haad 2815 1.1 haad nvs_native_destroy(nvs); 2816 1.1 haad 2817 1.1 haad return (err); 2818 1.1 haad } 2819 1.1 haad 2820 1.1 haad /* 2821 1.1 haad * XDR encoding functions 2822 1.1 haad * 2823 1.1 haad * An xdr packed nvlist is encoded as: 2824 1.1 haad * 2825 1.1 haad * - encoding methode and host endian (4 bytes) 2826 1.1 haad * - nvl_version (4 bytes) 2827 1.1 haad * - nvl_nvflag (4 bytes) 2828 1.1 haad * 2829 1.1 haad * - encoded nvpairs, the format of one xdr encoded nvpair is: 2830 1.1 haad * - encoded size of the nvpair (4 bytes) 2831 1.1 haad * - decoded size of the nvpair (4 bytes) 2832 1.1 haad * - name string, (4 + sizeof(NV_ALIGN4(string)) 2833 1.1 haad * a string is coded as size (4 bytes) and data 2834 1.1 haad * - data type (4 bytes) 2835 1.1 haad * - number of elements in the nvpair (4 bytes) 2836 1.1 haad * - data 2837 1.1 haad * 2838 1.1 haad * - 2 zero's for end of the entire list (8 bytes) 2839 1.1 haad */ 2840 1.1 haad static int 2841 1.1 haad nvs_xdr_create(nvstream_t *nvs, XDR *xdr, char *buf, size_t buflen) 2842 1.1 haad { 2843 1.1 haad /* xdr data must be 4 byte aligned */ 2844 1.1 haad if ((ulong_t)buf % 4 != 0) 2845 1.1 haad return (EFAULT); 2846 1.1 haad 2847 1.1 haad switch (nvs->nvs_op) { 2848 1.1 haad case NVS_OP_ENCODE: 2849 1.1 haad xdrmem_create(xdr, buf, (uint_t)buflen, XDR_ENCODE); 2850 1.1 haad nvs->nvs_private = xdr; 2851 1.1 haad return (0); 2852 1.1 haad case NVS_OP_DECODE: 2853 1.1 haad xdrmem_create(xdr, buf, (uint_t)buflen, XDR_DECODE); 2854 1.1 haad nvs->nvs_private = xdr; 2855 1.1 haad return (0); 2856 1.1 haad case NVS_OP_GETSIZE: 2857 1.1 haad nvs->nvs_private = NULL; 2858 1.1 haad return (0); 2859 1.1 haad default: 2860 1.1 haad return (EINVAL); 2861 1.1 haad } 2862 1.1 haad } 2863 1.1 haad 2864 1.1 haad static void 2865 1.1 haad nvs_xdr_destroy(nvstream_t *nvs) 2866 1.1 haad { 2867 1.1 haad switch (nvs->nvs_op) { 2868 1.1 haad case NVS_OP_ENCODE: 2869 1.1 haad case NVS_OP_DECODE: 2870 1.1 haad xdr_destroy((XDR *)nvs->nvs_private); 2871 1.1 haad break; 2872 1.1 haad default: 2873 1.1 haad break; 2874 1.1 haad } 2875 1.1 haad } 2876 1.1 haad 2877 1.1 haad static int 2878 1.1 haad nvs_xdr_nvlist(nvstream_t *nvs, nvlist_t *nvl, size_t *size) 2879 1.1 haad { 2880 1.1 haad switch (nvs->nvs_op) { 2881 1.1 haad case NVS_OP_ENCODE: 2882 1.1 haad case NVS_OP_DECODE: { 2883 1.1 haad XDR *xdr = nvs->nvs_private; 2884 1.1 haad 2885 1.1 haad if (!xdr_int(xdr, &nvl->nvl_version) || 2886 1.1 haad !xdr_u_int(xdr, &nvl->nvl_nvflag)) 2887 1.1 haad return (EFAULT); 2888 1.1 haad break; 2889 1.1 haad } 2890 1.1 haad case NVS_OP_GETSIZE: { 2891 1.1 haad /* 2892 1.1 haad * 2 * 4 for nvl_version + nvl_nvflag 2893 1.1 haad * and 8 for end of the entire list 2894 1.1 haad */ 2895 1.1 haad *size += 2 * 4 + 8; 2896 1.1 haad break; 2897 1.1 haad } 2898 1.1 haad default: 2899 1.1 haad return (EINVAL); 2900 1.1 haad } 2901 1.1 haad return (0); 2902 1.1 haad } 2903 1.1 haad 2904 1.1 haad static int 2905 1.1 haad nvs_xdr_nvl_fini(nvstream_t *nvs) 2906 1.1 haad { 2907 1.1 haad if (nvs->nvs_op == NVS_OP_ENCODE) { 2908 1.1 haad XDR *xdr = nvs->nvs_private; 2909 1.1 haad int zero = 0; 2910 1.1 haad 2911 1.1 haad if (!xdr_int(xdr, &zero) || !xdr_int(xdr, &zero)) 2912 1.1 haad return (EFAULT); 2913 1.1 haad } 2914 1.1 haad 2915 1.1 haad return (0); 2916 1.1 haad } 2917 1.1 haad 2918 1.1 haad /* 2919 1.1 haad * The format of xdr encoded nvpair is: 2920 1.1 haad * encode_size, decode_size, name string, data type, nelem, data 2921 1.1 haad */ 2922 1.1 haad static int 2923 1.1 haad nvs_xdr_nvp_op(nvstream_t *nvs, nvpair_t *nvp) 2924 1.1 haad { 2925 1.1 haad data_type_t type; 2926 1.1 haad char *buf; 2927 1.1 haad char *buf_end = (char *)nvp + nvp->nvp_size; 2928 1.1 haad int value_sz; 2929 1.1 haad uint_t nelem, buflen; 2930 1.1 haad bool_t ret = FALSE; 2931 1.1 haad XDR *xdr = nvs->nvs_private; 2932 1.1 haad 2933 1.1 haad ASSERT(xdr != NULL && nvp != NULL); 2934 1.1 haad 2935 1.1 haad /* name string */ 2936 1.1 haad if ((buf = NVP_NAME(nvp)) >= buf_end) 2937 1.1 haad return (EFAULT); 2938 1.1 haad buflen = buf_end - buf; 2939 1.1 haad 2940 1.1 haad if (!xdr_string(xdr, &buf, buflen - 1)) 2941 1.1 haad return (EFAULT); 2942 1.1 haad nvp->nvp_name_sz = strlen(buf) + 1; 2943 1.1 haad 2944 1.1 haad /* type and nelem */ 2945 1.1 haad if (!xdr_int(xdr, (int *)&nvp->nvp_type) || 2946 1.1 haad !xdr_int(xdr, &nvp->nvp_value_elem)) 2947 1.1 haad return (EFAULT); 2948 1.1 haad 2949 1.1 haad type = NVP_TYPE(nvp); 2950 1.1 haad nelem = nvp->nvp_value_elem; 2951 1.1 haad 2952 1.1 haad /* 2953 1.1 haad * Verify type and nelem and get the value size. 2954 1.1 haad * In case of data types DATA_TYPE_STRING and DATA_TYPE_STRING_ARRAY 2955 1.1 haad * is the size of the string(s) excluded. 2956 1.1 haad */ 2957 1.1 haad if ((value_sz = i_get_value_size(type, NULL, nelem)) < 0) 2958 1.1 haad return (EFAULT); 2959 1.1 haad 2960 1.1 haad /* if there is no data to extract then return */ 2961 1.1 haad if (nelem == 0) 2962 1.1 haad return (0); 2963 1.1 haad 2964 1.1 haad /* value */ 2965 1.1 haad if ((buf = NVP_VALUE(nvp)) >= buf_end) 2966 1.1 haad return (EFAULT); 2967 1.1 haad buflen = buf_end - buf; 2968 1.1 haad 2969 1.1 haad if (buflen < value_sz) 2970 1.1 haad return (EFAULT); 2971 1.1 haad 2972 1.1 haad switch (type) { 2973 1.1 haad case DATA_TYPE_NVLIST: 2974 1.1 haad if (nvs_embedded(nvs, (void *)buf) == 0) 2975 1.1 haad return (0); 2976 1.1 haad break; 2977 1.1 haad 2978 1.1 haad case DATA_TYPE_NVLIST_ARRAY: 2979 1.1 haad if (nvs_embedded_nvl_array(nvs, nvp, NULL) == 0) 2980 1.1 haad return (0); 2981 1.1 haad break; 2982 1.1 haad 2983 1.1 haad case DATA_TYPE_BOOLEAN: 2984 1.1 haad ret = TRUE; 2985 1.1 haad break; 2986 1.1 haad 2987 1.1 haad case DATA_TYPE_BYTE: 2988 1.1 haad case DATA_TYPE_INT8: 2989 1.1 haad case DATA_TYPE_UINT8: 2990 1.1 haad ret = xdr_char(xdr, buf); 2991 1.1 haad break; 2992 1.1 haad 2993 1.1 haad case DATA_TYPE_INT16: 2994 1.1 haad ret = xdr_short(xdr, (void *)buf); 2995 1.1 haad break; 2996 1.1 haad 2997 1.1 haad case DATA_TYPE_UINT16: 2998 1.1 haad ret = xdr_u_short(xdr, (void *)buf); 2999 1.1 haad break; 3000 1.1 haad 3001 1.1 haad case DATA_TYPE_BOOLEAN_VALUE: 3002 1.1 haad case DATA_TYPE_INT32: 3003 1.1 haad ret = xdr_int(xdr, (void *)buf); 3004 1.1 haad break; 3005 1.1 haad 3006 1.1 haad case DATA_TYPE_UINT32: 3007 1.1 haad ret = xdr_u_int(xdr, (void *)buf); 3008 1.1 haad break; 3009 1.1 haad 3010 1.1 haad case DATA_TYPE_INT64: 3011 1.1 haad ret = xdr_longlong_t(xdr, (void *)buf); 3012 1.1 haad break; 3013 1.1 haad 3014 1.1 haad case DATA_TYPE_UINT64: 3015 1.1 haad ret = xdr_u_longlong_t(xdr, (void *)buf); 3016 1.1 haad break; 3017 1.1 haad 3018 1.1 haad case DATA_TYPE_HRTIME: 3019 1.1 haad /* 3020 1.1 haad * NOTE: must expose the definition of hrtime_t here 3021 1.1 haad */ 3022 1.1 haad ret = xdr_longlong_t(xdr, (void *)buf); 3023 1.1 haad break; 3024 1.3 riastrad #ifndef __NetBSD__ 3025 1.1 haad #if !defined(_KERNEL) 3026 1.1 haad case DATA_TYPE_DOUBLE: 3027 1.1 haad ret = xdr_double(xdr, (void *)buf); 3028 1.1 haad break; 3029 1.1 haad #endif 3030 1.3 riastrad #endif 3031 1.1 haad case DATA_TYPE_STRING: 3032 1.1 haad ret = xdr_string(xdr, &buf, buflen - 1); 3033 1.1 haad break; 3034 1.1 haad 3035 1.1 haad case DATA_TYPE_BYTE_ARRAY: 3036 1.1 haad ret = xdr_opaque(xdr, buf, nelem); 3037 1.1 haad break; 3038 1.1 haad 3039 1.1 haad case DATA_TYPE_INT8_ARRAY: 3040 1.1 haad case DATA_TYPE_UINT8_ARRAY: 3041 1.1 haad ret = xdr_array(xdr, &buf, &nelem, buflen, sizeof (int8_t), 3042 1.1 haad (xdrproc_t)xdr_char); 3043 1.1 haad break; 3044 1.1 haad 3045 1.1 haad case DATA_TYPE_INT16_ARRAY: 3046 1.1 haad ret = xdr_array(xdr, &buf, &nelem, buflen / sizeof (int16_t), 3047 1.1 haad sizeof (int16_t), (xdrproc_t)xdr_short); 3048 1.1 haad break; 3049 1.1 haad 3050 1.1 haad case DATA_TYPE_UINT16_ARRAY: 3051 1.1 haad ret = xdr_array(xdr, &buf, &nelem, buflen / sizeof (uint16_t), 3052 1.1 haad sizeof (uint16_t), (xdrproc_t)xdr_u_short); 3053 1.1 haad break; 3054 1.1 haad 3055 1.1 haad case DATA_TYPE_BOOLEAN_ARRAY: 3056 1.1 haad case DATA_TYPE_INT32_ARRAY: 3057 1.1 haad ret = xdr_array(xdr, &buf, &nelem, buflen / sizeof (int32_t), 3058 1.1 haad sizeof (int32_t), (xdrproc_t)xdr_int); 3059 1.1 haad break; 3060 1.1 haad 3061 1.1 haad case DATA_TYPE_UINT32_ARRAY: 3062 1.1 haad ret = xdr_array(xdr, &buf, &nelem, buflen / sizeof (uint32_t), 3063 1.1 haad sizeof (uint32_t), (xdrproc_t)xdr_u_int); 3064 1.1 haad break; 3065 1.1 haad 3066 1.1 haad case DATA_TYPE_INT64_ARRAY: 3067 1.1 haad ret = xdr_array(xdr, &buf, &nelem, buflen / sizeof (int64_t), 3068 1.1 haad sizeof (int64_t), (xdrproc_t)xdr_longlong_t); 3069 1.1 haad break; 3070 1.1 haad 3071 1.1 haad case DATA_TYPE_UINT64_ARRAY: 3072 1.1 haad ret = xdr_array(xdr, &buf, &nelem, buflen / sizeof (uint64_t), 3073 1.1 haad sizeof (uint64_t), (xdrproc_t)xdr_u_longlong_t); 3074 1.1 haad break; 3075 1.1 haad 3076 1.1 haad case DATA_TYPE_STRING_ARRAY: { 3077 1.1 haad size_t len = nelem * sizeof (uint64_t); 3078 1.1 haad char **strp = (void *)buf; 3079 1.1 haad int i; 3080 1.1 haad 3081 1.1 haad if (nvs->nvs_op == NVS_OP_DECODE) 3082 1.1 haad bzero(buf, len); /* don't trust packed data */ 3083 1.1 haad 3084 1.1 haad for (i = 0; i < nelem; i++) { 3085 1.1 haad if (buflen <= len) 3086 1.1 haad return (EFAULT); 3087 1.1 haad 3088 1.1 haad buf += len; 3089 1.1 haad buflen -= len; 3090 1.1 haad 3091 1.1 haad if (xdr_string(xdr, &buf, buflen - 1) != TRUE) 3092 1.1 haad return (EFAULT); 3093 1.1 haad 3094 1.1 haad if (nvs->nvs_op == NVS_OP_DECODE) 3095 1.1 haad strp[i] = buf; 3096 1.1 haad len = strlen(buf) + 1; 3097 1.1 haad } 3098 1.1 haad ret = TRUE; 3099 1.1 haad break; 3100 1.1 haad } 3101 1.1 haad default: 3102 1.1 haad break; 3103 1.1 haad } 3104 1.1 haad 3105 1.1 haad return (ret == TRUE ? 0 : EFAULT); 3106 1.1 haad } 3107 1.1 haad 3108 1.1 haad static int 3109 1.1 haad nvs_xdr_nvp_size(nvstream_t *nvs, nvpair_t *nvp, size_t *size) 3110 1.1 haad { 3111 1.1 haad data_type_t type = NVP_TYPE(nvp); 3112 1.1 haad /* 3113 1.1 haad * encode_size + decode_size + name string size + data type + nelem 3114 1.1 haad * where name string size = 4 + NV_ALIGN4(strlen(NVP_NAME(nvp))) 3115 1.1 haad */ 3116 1.1 haad uint64_t nvp_sz = 4 + 4 + 4 + NV_ALIGN4(strlen(NVP_NAME(nvp))) + 4 + 4; 3117 1.1 haad 3118 1.1 haad switch (type) { 3119 1.1 haad case DATA_TYPE_BOOLEAN: 3120 1.1 haad break; 3121 1.1 haad 3122 1.1 haad case DATA_TYPE_BOOLEAN_VALUE: 3123 1.1 haad case DATA_TYPE_BYTE: 3124 1.1 haad case DATA_TYPE_INT8: 3125 1.1 haad case DATA_TYPE_UINT8: 3126 1.1 haad case DATA_TYPE_INT16: 3127 1.1 haad case DATA_TYPE_UINT16: 3128 1.1 haad case DATA_TYPE_INT32: 3129 1.1 haad case DATA_TYPE_UINT32: 3130 1.1 haad nvp_sz += 4; /* 4 is the minimum xdr unit */ 3131 1.1 haad break; 3132 1.1 haad 3133 1.1 haad case DATA_TYPE_INT64: 3134 1.1 haad case DATA_TYPE_UINT64: 3135 1.1 haad case DATA_TYPE_HRTIME: 3136 1.1 haad #if !defined(_KERNEL) 3137 1.1 haad case DATA_TYPE_DOUBLE: 3138 1.1 haad #endif 3139 1.1 haad nvp_sz += 8; 3140 1.1 haad break; 3141 1.1 haad 3142 1.1 haad case DATA_TYPE_STRING: 3143 1.1 haad nvp_sz += 4 + NV_ALIGN4(strlen((char *)NVP_VALUE(nvp))); 3144 1.1 haad break; 3145 1.1 haad 3146 1.1 haad case DATA_TYPE_BYTE_ARRAY: 3147 1.1 haad nvp_sz += NV_ALIGN4(NVP_NELEM(nvp)); 3148 1.1 haad break; 3149 1.1 haad 3150 1.1 haad case DATA_TYPE_BOOLEAN_ARRAY: 3151 1.1 haad case DATA_TYPE_INT8_ARRAY: 3152 1.1 haad case DATA_TYPE_UINT8_ARRAY: 3153 1.1 haad case DATA_TYPE_INT16_ARRAY: 3154 1.1 haad case DATA_TYPE_UINT16_ARRAY: 3155 1.1 haad case DATA_TYPE_INT32_ARRAY: 3156 1.1 haad case DATA_TYPE_UINT32_ARRAY: 3157 1.1 haad nvp_sz += 4 + 4 * (uint64_t)NVP_NELEM(nvp); 3158 1.1 haad break; 3159 1.1 haad 3160 1.1 haad case DATA_TYPE_INT64_ARRAY: 3161 1.1 haad case DATA_TYPE_UINT64_ARRAY: 3162 1.1 haad nvp_sz += 4 + 8 * (uint64_t)NVP_NELEM(nvp); 3163 1.1 haad break; 3164 1.1 haad 3165 1.1 haad case DATA_TYPE_STRING_ARRAY: { 3166 1.1 haad int i; 3167 1.1 haad char **strs = (void *)NVP_VALUE(nvp); 3168 1.1 haad 3169 1.1 haad for (i = 0; i < NVP_NELEM(nvp); i++) 3170 1.1 haad nvp_sz += 4 + NV_ALIGN4(strlen(strs[i])); 3171 1.1 haad 3172 1.1 haad break; 3173 1.1 haad } 3174 1.1 haad 3175 1.1 haad case DATA_TYPE_NVLIST: 3176 1.1 haad case DATA_TYPE_NVLIST_ARRAY: { 3177 1.1 haad size_t nvsize = 0; 3178 1.1 haad int old_nvs_op = nvs->nvs_op; 3179 1.1 haad int err; 3180 1.1 haad 3181 1.1 haad nvs->nvs_op = NVS_OP_GETSIZE; 3182 1.1 haad if (type == DATA_TYPE_NVLIST) 3183 1.1 haad err = nvs_operation(nvs, EMBEDDED_NVL(nvp), &nvsize); 3184 1.1 haad else 3185 1.1 haad err = nvs_embedded_nvl_array(nvs, nvp, &nvsize); 3186 1.1 haad nvs->nvs_op = old_nvs_op; 3187 1.1 haad 3188 1.1 haad if (err != 0) 3189 1.1 haad return (EINVAL); 3190 1.1 haad 3191 1.1 haad nvp_sz += nvsize; 3192 1.1 haad break; 3193 1.1 haad } 3194 1.1 haad 3195 1.1 haad default: 3196 1.1 haad return (EINVAL); 3197 1.1 haad } 3198 1.1 haad 3199 1.1 haad if (nvp_sz > INT32_MAX) 3200 1.1 haad return (EINVAL); 3201 1.1 haad 3202 1.1 haad *size = nvp_sz; 3203 1.1 haad 3204 1.1 haad return (0); 3205 1.1 haad } 3206 1.1 haad 3207 1.1 haad 3208 1.1 haad /* 3209 1.1 haad * The NVS_XDR_MAX_LEN macro takes a packed xdr buffer of size x and estimates 3210 1.1 haad * the largest nvpair that could be encoded in the buffer. 3211 1.1 haad * 3212 1.1 haad * See comments above nvpair_xdr_op() for the format of xdr encoding. 3213 1.1 haad * The size of a xdr packed nvpair without any data is 5 words. 3214 1.1 haad * 3215 1.1 haad * Using the size of the data directly as an estimate would be ok 3216 1.1 haad * in all cases except one. If the data type is of DATA_TYPE_STRING_ARRAY 3217 1.1 haad * then the actual nvpair has space for an array of pointers to index 3218 1.1 haad * the strings. These pointers are not encoded into the packed xdr buffer. 3219 1.1 haad * 3220 1.1 haad * If the data is of type DATA_TYPE_STRING_ARRAY and all the strings are 3221 1.1 haad * of length 0, then each string is endcoded in xdr format as a single word. 3222 1.1 haad * Therefore when expanded to an nvpair there will be 2.25 word used for 3223 1.1 haad * each string. (a int64_t allocated for pointer usage, and a single char 3224 1.1 haad * for the null termination.) 3225 1.1 haad * 3226 1.1 haad * This is the calculation performed by the NVS_XDR_MAX_LEN macro. 3227 1.1 haad */ 3228 1.1 haad #define NVS_XDR_HDR_LEN ((size_t)(5 * 4)) 3229 1.1 haad #define NVS_XDR_DATA_LEN(y) (((size_t)(y) <= NVS_XDR_HDR_LEN) ? \ 3230 1.1 haad 0 : ((size_t)(y) - NVS_XDR_HDR_LEN)) 3231 1.1 haad #define NVS_XDR_MAX_LEN(x) (NVP_SIZE_CALC(1, 0) + \ 3232 1.1 haad (NVS_XDR_DATA_LEN(x) * 2) + \ 3233 1.1 haad NV_ALIGN4((NVS_XDR_DATA_LEN(x) / 4))) 3234 1.1 haad 3235 1.1 haad static int 3236 1.1 haad nvs_xdr_nvpair(nvstream_t *nvs, nvpair_t *nvp, size_t *size) 3237 1.1 haad { 3238 1.1 haad XDR *xdr = nvs->nvs_private; 3239 1.1 haad int32_t encode_len, decode_len; 3240 1.1 haad 3241 1.1 haad switch (nvs->nvs_op) { 3242 1.1 haad case NVS_OP_ENCODE: { 3243 1.1 haad size_t nvsize; 3244 1.1 haad 3245 1.1 haad if (nvs_xdr_nvp_size(nvs, nvp, &nvsize) != 0) 3246 1.1 haad return (EFAULT); 3247 1.1 haad 3248 1.1 haad decode_len = nvp->nvp_size; 3249 1.1 haad encode_len = nvsize; 3250 1.1 haad if (!xdr_int(xdr, &encode_len) || !xdr_int(xdr, &decode_len)) 3251 1.1 haad return (EFAULT); 3252 1.1 haad 3253 1.1 haad return (nvs_xdr_nvp_op(nvs, nvp)); 3254 1.1 haad } 3255 1.1 haad case NVS_OP_DECODE: { 3256 1.1 haad struct xdr_bytesrec bytesrec; 3257 1.1 haad 3258 1.1 haad /* get the encode and decode size */ 3259 1.1 haad if (!xdr_int(xdr, &encode_len) || !xdr_int(xdr, &decode_len)) 3260 1.1 haad return (EFAULT); 3261 1.1 haad *size = decode_len; 3262 1.1 haad 3263 1.1 haad /* are we at the end of the stream? */ 3264 1.1 haad if (*size == 0) 3265 1.1 haad return (0); 3266 1.1 haad 3267 1.1 haad /* sanity check the size parameter */ 3268 1.1 haad if (!xdr_control(xdr, XDR_GET_BYTES_AVAIL, &bytesrec)) 3269 1.1 haad return (EFAULT); 3270 1.1 haad 3271 1.1 haad if (*size > NVS_XDR_MAX_LEN(bytesrec.xc_num_avail)) 3272 1.1 haad return (EFAULT); 3273 1.1 haad break; 3274 1.1 haad } 3275 1.1 haad 3276 1.1 haad default: 3277 1.1 haad return (EINVAL); 3278 1.1 haad } 3279 1.1 haad return (0); 3280 1.1 haad } 3281 1.1 haad 3282 1.1 haad static const struct nvs_ops nvs_xdr_ops = { 3283 1.1 haad nvs_xdr_nvlist, 3284 1.1 haad nvs_xdr_nvpair, 3285 1.1 haad nvs_xdr_nvp_op, 3286 1.1 haad nvs_xdr_nvp_size, 3287 1.1 haad nvs_xdr_nvl_fini 3288 1.1 haad }; 3289 1.1 haad 3290 1.1 haad static int 3291 1.1 haad nvs_xdr(nvstream_t *nvs, nvlist_t *nvl, char *buf, size_t *buflen) 3292 1.1 haad { 3293 1.1 haad XDR xdr; 3294 1.1 haad int err; 3295 1.1 haad 3296 1.1 haad nvs->nvs_ops = &nvs_xdr_ops; 3297 1.1 haad 3298 1.1 haad if ((err = nvs_xdr_create(nvs, &xdr, buf + sizeof (nvs_header_t), 3299 1.1 haad *buflen - sizeof (nvs_header_t))) != 0) 3300 1.1 haad return (err); 3301 1.1 haad 3302 1.1 haad err = nvs_operation(nvs, nvl, buflen); 3303 1.1 haad 3304 1.1 haad nvs_xdr_destroy(nvs); 3305 1.1 haad 3306 1.1 haad return (err); 3307 1.1 haad } 3308