1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
  24  * Copyright 2012 Milan Jurik. All rights reserved.
  25  */
  26 
  27 #include <assert.h>
  28 #include <stdio.h>
  29 #include <stdlib.h>
  30 #include <string.h>
  31 #include <sys/types.h>
  32 #include <libdlwlan.h>
  33 #include <libnvpair.h>
  34 
  35 #include "libnwam_impl.h"
  36 #include <libnwam_priv.h>
  37 #include <libnwam.h>
  38 
  39 /*
  40  * Internal implementation of libnwam in-memory objects and values.  Objects
  41  * are nvlists.
  42  */
  43 
  44 void
  45 nwam_value_free(nwam_value_t value)
  46 {
  47         uint_t i;
  48 
  49         if (value == NULL)
  50                 return;
  51 
  52         switch (value->nwv_value_type) {
  53         case NWAM_VALUE_TYPE_BOOLEAN:
  54                 free(value->nwv_values.nwv_boolean);
  55                 break;
  56         case NWAM_VALUE_TYPE_INT64:
  57                 free(value->nwv_values.nwv_int64);
  58                 break;
  59         case NWAM_VALUE_TYPE_UINT64:
  60                 free(value->nwv_values.nwv_uint64);
  61                 break;
  62         case NWAM_VALUE_TYPE_STRING:
  63                 for (i = 0; i < value->nwv_value_numvalues; i++)
  64                         free(value->nwv_values.nwv_string[i]);
  65                 free(value->nwv_values.nwv_string);
  66                 break;
  67         }
  68         free(value);
  69 }
  70 
  71 nwam_error_t
  72 nwam_value_create(nwam_value_type_t value_type, void *values, uint_t numvalues,
  73     nwam_value_t *valuep)
  74 {
  75         nwam_value_t newvalue;
  76         boolean_t *values_boolean;
  77         int64_t *values_int64;
  78         uint64_t *values_uint64;
  79         char **values_string;
  80         int i, j;
  81         nwam_error_t err = NWAM_SUCCESS;
  82 
  83         *valuep = NULL;
  84 
  85         if ((newvalue = calloc(1, sizeof (struct nwam_value))) == NULL)
  86                 return (NWAM_NO_MEMORY);
  87 
  88         newvalue->nwv_value_type = value_type;
  89         newvalue->nwv_value_numvalues = numvalues;
  90 
  91         switch (value_type) {
  92         case NWAM_VALUE_TYPE_BOOLEAN:
  93                 values_boolean = values;
  94                 if ((newvalue->nwv_values.nwv_boolean =
  95                     calloc(numvalues, sizeof (boolean_t))) == NULL) {
  96                         free(newvalue);
  97                         return (NWAM_NO_MEMORY);
  98                 }
  99                 for (i = 0; i < numvalues; i++)
 100                         newvalue->nwv_values.nwv_boolean[i] = values_boolean[i];
 101                 break;
 102         case NWAM_VALUE_TYPE_INT64:
 103                 values_int64 = values;
 104                 if ((newvalue->nwv_values.nwv_int64 =
 105                     calloc(numvalues, sizeof (int64_t))) == NULL) {
 106                         free(newvalue);
 107                         return (NWAM_NO_MEMORY);
 108                 }
 109                 for (i = 0; i < numvalues; i++)
 110                         newvalue->nwv_values.nwv_int64[i] = values_int64[i];
 111                 break;
 112         case NWAM_VALUE_TYPE_UINT64:
 113                 values_uint64 = values;
 114                 if ((newvalue->nwv_values.nwv_uint64 =
 115                     calloc(numvalues, sizeof (uint64_t))) == NULL) {
 116                         free(newvalue);
 117                         return (NWAM_NO_MEMORY);
 118                 }
 119                 for (i = 0; i < numvalues; i++)
 120                         newvalue->nwv_values.nwv_uint64[i] = values_uint64[i];
 121                 break;
 122         case NWAM_VALUE_TYPE_STRING:
 123                 values_string = values;
 124                 if ((newvalue->nwv_values.nwv_string =
 125                     calloc(numvalues, sizeof (char *))) == NULL) {
 126                         free(newvalue);
 127                         return (NWAM_NO_MEMORY);
 128                 }
 129                 for (i = 0; i < numvalues; i++) {
 130                         if (strnlen(values_string[i], NWAM_MAX_VALUE_LEN) ==
 131                             NWAM_MAX_VALUE_LEN) {
 132                                 err = NWAM_ENTITY_INVALID_VALUE;
 133                         } else if ((newvalue->nwv_values.nwv_string[i] =
 134                             strdup(values_string[i])) == NULL) {
 135                                 err = NWAM_NO_MEMORY;
 136                         }
 137                         if (err != NWAM_SUCCESS) {
 138                                 for (j = 0; j < i; j++)
 139                                         free(
 140                                             newvalue->nwv_values.nwv_string[i]);
 141                                 free(newvalue->nwv_values.nwv_string);
 142                                 free(newvalue);
 143                                 return (err);
 144                         }
 145                 }
 146                 break;
 147         default:
 148                 break;
 149         }
 150 
 151         *valuep = newvalue;
 152         return (NWAM_SUCCESS);
 153 }
 154 
 155 nwam_error_t
 156 nwam_value_copy(nwam_value_t old, nwam_value_t *newp)
 157 {
 158         void *values;
 159 
 160         assert(old != NULL && newp != NULL);
 161 
 162         switch (old->nwv_value_type) {
 163         case NWAM_VALUE_TYPE_BOOLEAN:
 164                 values = old->nwv_values.nwv_boolean;
 165                 break;
 166         case NWAM_VALUE_TYPE_INT64:
 167                 values = old->nwv_values.nwv_int64;
 168                 break;
 169         case NWAM_VALUE_TYPE_UINT64:
 170                 values = old->nwv_values.nwv_uint64;
 171                 break;
 172         case NWAM_VALUE_TYPE_STRING:
 173                 values = old->nwv_values.nwv_string;
 174                 break;
 175         default:
 176                 return (NWAM_INVALID_ARG);
 177         }
 178         return (nwam_value_create(old->nwv_value_type, values,
 179             old->nwv_value_numvalues, newp));
 180 }
 181 nwam_error_t
 182 nwam_value_create_boolean_array(boolean_t *values, uint_t numvalues,
 183     nwam_value_t *valuep)
 184 {
 185         return (nwam_value_create(NWAM_VALUE_TYPE_BOOLEAN, values, numvalues,
 186             valuep));
 187 }
 188 
 189 nwam_error_t
 190 nwam_value_create_boolean(boolean_t value, nwam_value_t *valuep)
 191 {
 192         return (nwam_value_create_boolean_array(&value, 1, valuep));
 193 }
 194 
 195 nwam_error_t
 196 nwam_value_create_int64_array(int64_t *values, uint_t numvalues,
 197     nwam_value_t *valuep)
 198 {
 199         return (nwam_value_create(NWAM_VALUE_TYPE_INT64, values, numvalues,
 200             valuep));
 201 }
 202 
 203 nwam_error_t
 204 nwam_value_create_int64(int64_t value, nwam_value_t *valuep)
 205 {
 206         return (nwam_value_create_int64_array(&value, 1, valuep));
 207 }
 208 
 209 nwam_error_t
 210 nwam_value_create_uint64_array(uint64_t *values, uint_t numvalues,
 211     nwam_value_t *valuep)
 212 {
 213         return (nwam_value_create(NWAM_VALUE_TYPE_UINT64, values, numvalues,
 214             valuep));
 215 }
 216 
 217 nwam_error_t
 218 nwam_value_create_uint64(uint64_t value, nwam_value_t *valuep)
 219 {
 220         return (nwam_value_create_uint64_array(&value, 1, valuep));
 221 }
 222 
 223 nwam_error_t
 224 nwam_value_create_string_array(char **values, uint_t numvalues,
 225     nwam_value_t *valuep)
 226 {
 227         return (nwam_value_create(NWAM_VALUE_TYPE_STRING, values, numvalues,
 228             valuep));
 229 }
 230 
 231 nwam_error_t
 232 nwam_value_create_string(char *value, nwam_value_t *valuep)
 233 {
 234         return (nwam_value_create_string_array(&value, 1, valuep));
 235 }
 236 
 237 nwam_error_t
 238 nwam_value_get_boolean_array(nwam_value_t value, boolean_t **valuesp,
 239     uint_t *numvaluesp)
 240 {
 241         assert(value != NULL && numvaluesp != NULL && valuesp != NULL);
 242 
 243         *numvaluesp = value->nwv_value_numvalues;
 244         *valuesp = value->nwv_values.nwv_boolean;
 245         return (NWAM_SUCCESS);
 246 }
 247 
 248 nwam_error_t
 249 nwam_value_get_boolean(nwam_value_t value, boolean_t *valuep)
 250 {
 251         uint_t numvalues;
 252         boolean_t *myvaluesp;
 253         nwam_error_t err;
 254 
 255         err = nwam_value_get_boolean_array(value, &myvaluesp, &numvalues);
 256         if (err != NWAM_SUCCESS)
 257                 return (err);
 258         if (numvalues != 1)
 259                 return (NWAM_ENTITY_MULTIPLE_VALUES);
 260 
 261         *valuep = myvaluesp[0];
 262         return (NWAM_SUCCESS);
 263 }
 264 
 265 nwam_error_t
 266 nwam_value_get_int64_array(nwam_value_t value, int64_t **valuesp,
 267     uint_t *numvaluesp)
 268 {
 269         assert(value != NULL && numvaluesp != NULL && valuesp != NULL);
 270 
 271         *numvaluesp = value->nwv_value_numvalues;
 272         *valuesp = value->nwv_values.nwv_int64;
 273         return (NWAM_SUCCESS);
 274 }
 275 
 276 nwam_error_t
 277 nwam_value_get_int64(nwam_value_t value, int64_t *valuep)
 278 {
 279         uint_t numvalues;
 280         int64_t *myvaluesp;
 281         nwam_error_t err;
 282 
 283         err = nwam_value_get_int64_array(value, &myvaluesp, &numvalues);
 284         if (err != NWAM_SUCCESS)
 285                 return (err);
 286         if (numvalues != 1)
 287                 return (NWAM_ENTITY_MULTIPLE_VALUES);
 288 
 289         *valuep = myvaluesp[0];
 290         return (NWAM_SUCCESS);
 291 }
 292 
 293 nwam_error_t
 294 nwam_value_get_uint64_array(nwam_value_t value, uint64_t **valuesp,
 295     uint_t *numvaluesp)
 296 {
 297         assert(value != NULL && numvaluesp != NULL && valuesp != NULL);
 298 
 299         *numvaluesp = value->nwv_value_numvalues;
 300         *valuesp = value->nwv_values.nwv_uint64;
 301         return (NWAM_SUCCESS);
 302 }
 303 
 304 nwam_error_t
 305 nwam_value_get_uint64(nwam_value_t value, uint64_t *valuep)
 306 {
 307         uint_t numvalues;
 308         uint64_t *myvaluesp;
 309         nwam_error_t err;
 310 
 311         err = nwam_value_get_uint64_array(value, &myvaluesp, &numvalues);
 312         if (err != NWAM_SUCCESS)
 313                 return (err);
 314         if (numvalues != 1)
 315                 return (NWAM_ENTITY_MULTIPLE_VALUES);
 316 
 317         *valuep = myvaluesp[0];
 318         return (NWAM_SUCCESS);
 319 }
 320 
 321 nwam_error_t
 322 nwam_value_get_string_array(nwam_value_t value, char ***valuesp,
 323     uint_t *numvaluesp)
 324 {
 325         assert(value != NULL && numvaluesp != NULL && valuesp != NULL);
 326 
 327         *numvaluesp = value->nwv_value_numvalues;
 328         *valuesp = value->nwv_values.nwv_string;
 329         return (NWAM_SUCCESS);
 330 }
 331 
 332 nwam_error_t
 333 nwam_value_get_string(nwam_value_t value, char **valuep)
 334 {
 335         uint_t numvalues;
 336         char **myvaluesp;
 337         nwam_error_t err;
 338 
 339         err = nwam_value_get_string_array(value, &myvaluesp, &numvalues);
 340         if (err != NWAM_SUCCESS)
 341                 return (err);
 342         if (numvalues != 1)
 343                 return (NWAM_ENTITY_MULTIPLE_VALUES);
 344 
 345         *valuep = myvaluesp[0];
 346         return (NWAM_SUCCESS);
 347 }
 348 
 349 nwam_error_t
 350 nwam_value_get_type(nwam_value_t value, nwam_value_type_t *typep)
 351 {
 352         *typep = value->nwv_value_type;
 353         return (NWAM_SUCCESS);
 354 }
 355 
 356 nwam_error_t
 357 nwam_value_get_numvalues(nwam_value_t value, uint_t *numvaluesp)
 358 {
 359         *numvaluesp = value->nwv_value_numvalues;
 360         return (NWAM_SUCCESS);
 361 }
 362 
 363 /*
 364  * Generic object data functions. We hide nvlist implementation
 365  * from NCP, ENM and location implementations.
 366  */
 367 nwam_error_t
 368 nwam_alloc_object_list(void *list)
 369 {
 370         int nverr;
 371 
 372         assert(list != NULL);
 373 
 374         if ((nverr = nvlist_alloc((nvlist_t **)list, NV_UNIQUE_NAME, 0)) != 0)
 375                 return (nwam_errno_to_nwam_error(nverr));
 376 
 377         return (NWAM_SUCCESS);
 378 }
 379 
 380 void
 381 nwam_free_object_list(void *list)
 382 {
 383         nvlist_free(list);
 384 }
 385 
 386 nwam_error_t
 387 nwam_dup_object_list(void *oldlist, void *newlist)
 388 {
 389         int nverr;
 390 
 391         assert(oldlist != NULL && newlist != NULL);
 392 
 393         if ((nverr = nvlist_dup(oldlist, newlist, 0)) != 0)
 394                 return (nwam_errno_to_nwam_error(nverr));
 395 
 396         return (NWAM_SUCCESS);
 397 }
 398 
 399 /* Add child object list to parent object list using property name childname */
 400 nwam_error_t
 401 nwam_object_list_add_object_list(void *parentlist, char *childname,
 402     void *childlist)
 403 {
 404         return (nwam_errno_to_nwam_error(nvlist_add_nvlist(parentlist,
 405             childname, childlist)));
 406 }
 407 
 408 /* Remove object list from parent object list */
 409 nwam_error_t
 410 nwam_object_list_remove_object_list(void *parentlist, char *childname)
 411 {
 412         return (nwam_errno_to_nwam_error(nvlist_remove_all(parentlist,
 413             childname)));
 414 }
 415 
 416 /*
 417  * Get next object list (nvlist) after lastname.  Used to walk NCUs, ENMs and
 418  * locations, each of which is internally represented as an nvlist.
 419  */
 420 nwam_error_t
 421 nwam_next_object_list(void *parentlist, char *lastname, char **childnamep,
 422     void *childlistp)
 423 {
 424         nvpair_t *last = NULL, *next;
 425         int nverr;
 426 
 427         if (lastname != NULL) {
 428                 if ((nverr = nvlist_lookup_nvpair(parentlist, lastname, &last))
 429                     != 0)
 430                         return (nwam_errno_to_nwam_error(nverr));
 431         }
 432         if ((next = nvlist_next_nvpair(parentlist, last)) == NULL)
 433                 return (NWAM_LIST_END);
 434 
 435         *childnamep = nvpair_name(next);
 436 
 437         if (nvpair_type(next) != DATA_TYPE_NVLIST)
 438                 return (NWAM_ERROR_INTERNAL);
 439 
 440         if ((nverr = nvpair_value_nvlist(next, childlistp)) != NWAM_SUCCESS)
 441                 return (nwam_errno_to_nwam_error(nverr));
 442 
 443         return (NWAM_SUCCESS);
 444 }
 445 
 446 /*
 447  * Pack nvlist into contiguous memory. If packed_listp is NULL, we just
 448  * return the size of the memory needed to do so.
 449  */
 450 nwam_error_t
 451 nwam_pack_object_list(void *list, char **packed_listp, size_t *packed_sizep)
 452 {
 453         int nverr;
 454 
 455         assert(list != NULL && packed_sizep != NULL);
 456 
 457         if (packed_listp == NULL) {
 458                 nverr = nvlist_size(list, packed_sizep, NV_ENCODE_XDR);
 459         } else {
 460                 nverr = nvlist_pack(list, packed_listp, packed_sizep,
 461                     NV_ENCODE_XDR, 0);
 462         }
 463 
 464         if (nverr != 0)
 465                 return (nwam_errno_to_nwam_error(nverr));
 466 
 467         return (NWAM_SUCCESS);
 468 }
 469 
 470 nwam_error_t
 471 nwam_unpack_object_list(char *packed_list, size_t packed_size,
 472     void *list)
 473 {
 474         int nverr;
 475 
 476         assert(packed_list != NULL && list != NULL);
 477 
 478         *((nvlist_t **)list) = NULL;
 479 
 480         nverr = nvlist_unpack(packed_list, packed_size, (nvlist_t **)list, 0);
 481 
 482         if (nverr != 0)
 483                 return (nwam_errno_to_nwam_error(nverr));
 484 
 485         return (NWAM_SUCCESS);
 486 }
 487 
 488 /*
 489  * Functions to walk, set and get properties in nvlist, translating
 490  * between nwam_value_t and nvlist/nvpair representations.
 491  */
 492 nwam_error_t
 493 nwam_next_object_prop(void *list, char *lastname, char **namep,
 494     nwam_value_t *valuep)
 495 {
 496         nvpair_t *last = NULL, *next;
 497         int nverr;
 498 
 499         if (lastname != NULL) {
 500                 if ((nverr = nvlist_lookup_nvpair(list, lastname, &last)) != 0)
 501                         return (nwam_errno_to_nwam_error(nverr));
 502         }
 503         if ((next = nvlist_next_nvpair(list, last)) == NULL)
 504                 return (NWAM_LIST_END);
 505 
 506         *namep = nvpair_name(next);
 507 
 508         return (nwam_get_prop_value(list, (const char *)*namep, valuep));
 509 }
 510 
 511 nwam_error_t
 512 nwam_get_prop_value(void *list, const char *name, nwam_value_t *valuep)
 513 {
 514         nvpair_t *prop;
 515         nwam_error_t err;
 516         int nverr;
 517         boolean_t *valbool;
 518         int64_t *valint64;
 519         uint64_t *valuint64;
 520         char **valstr;
 521         uint_t numvalues;
 522 
 523         assert(valuep != NULL);
 524 
 525         *valuep = NULL;
 526 
 527         if ((nverr = nvlist_lookup_nvpair(list, name, &prop)) != 0) {
 528                 /* convert EINVAL to NOT_FOUND */
 529                 if (nverr == EINVAL)
 530                         return (NWAM_ENTITY_NOT_FOUND);
 531                 return (nwam_errno_to_nwam_error(nverr));
 532         }
 533 
 534         switch (nvpair_type(prop)) {
 535         case DATA_TYPE_BOOLEAN_ARRAY:
 536                 if ((nverr = nvpair_value_boolean_array(prop,
 537                     &valbool, &numvalues)) != 0)
 538                         return (nwam_errno_to_nwam_error(nverr));
 539                 if ((err = nwam_value_create_boolean_array(valbool, numvalues,
 540                     valuep)) != NWAM_SUCCESS)
 541                         return (err);
 542                 break;
 543         case DATA_TYPE_INT64_ARRAY:
 544                 if ((nverr = nvpair_value_int64_array(prop,
 545                     &valint64, &numvalues)) != 0)
 546                         return (nwam_errno_to_nwam_error(nverr));
 547                 if ((err = nwam_value_create_int64_array(valint64, numvalues,
 548                     valuep)) != NWAM_SUCCESS)
 549                         return (err);
 550                 break;
 551         case DATA_TYPE_UINT64_ARRAY:
 552                 if ((nverr = nvpair_value_uint64_array(prop,
 553                     &valuint64, &numvalues)) != 0)
 554                         return (nwam_errno_to_nwam_error(nverr));
 555                 if ((err = nwam_value_create_uint64_array(valuint64, numvalues,
 556                     valuep)) != NWAM_SUCCESS)
 557                         return (err);
 558                 break;
 559         case DATA_TYPE_STRING_ARRAY:
 560                 if ((nverr = nvpair_value_string_array(prop,
 561                     &valstr, &numvalues)) != 0)
 562                         return (nwam_errno_to_nwam_error(nverr));
 563                 if ((err = nwam_value_create_string_array(valstr, numvalues,
 564                     valuep)) != NWAM_SUCCESS)
 565                         return (err);
 566                 break;
 567         default:
 568                 /* Should not happen */
 569                 return (NWAM_ERROR_INTERNAL);
 570         }
 571         return (NWAM_SUCCESS);
 572 }
 573 
 574 nwam_error_t
 575 nwam_delete_prop(void *list, const char *name)
 576 {
 577         int nverr;
 578 
 579         if ((nverr = nvlist_remove_all(list, name)) != 0)
 580                 return (nwam_errno_to_nwam_error(nverr));
 581         return (NWAM_SUCCESS);
 582 }
 583 
 584 nwam_error_t
 585 nwam_set_prop_value(void *list, const char *propname, nwam_value_t value)
 586 {
 587         int nverr;
 588         nwam_error_t err;
 589         nwam_value_type_t type;
 590         uint_t numvalues;
 591         boolean_t *valbool;
 592         int64_t *valint64;
 593         uint64_t *valuint64;
 594         char **valstr;
 595 
 596         assert(list != NULL && value != NULL);
 597 
 598         if ((err = nwam_value_get_type(value, &type)) != NWAM_SUCCESS)
 599                 return (err);
 600 
 601         switch (type) {
 602         case NWAM_VALUE_TYPE_BOOLEAN:
 603                 if ((err = nwam_value_get_boolean_array(value, &valbool,
 604                     &numvalues)) != NWAM_SUCCESS)
 605                         return (err);
 606                 if ((nverr = nvlist_add_boolean_array(list, propname,
 607                     valbool, numvalues)) != 0)
 608                         return (nwam_errno_to_nwam_error(nverr));
 609                 break;
 610         case NWAM_VALUE_TYPE_INT64:
 611                 if ((err = nwam_value_get_int64_array(value, &valint64,
 612                     &numvalues)) != NWAM_SUCCESS)
 613                         return (err);
 614                 if ((nverr = nvlist_add_int64_array(list, propname,
 615                     valint64, numvalues)) != 0)
 616                         return (nwam_errno_to_nwam_error(nverr));
 617                 break;
 618         case NWAM_VALUE_TYPE_UINT64:
 619                 if ((err = nwam_value_get_uint64_array(value, &valuint64,
 620                     &numvalues)) != NWAM_SUCCESS)
 621                         return (err);
 622                 if ((nverr = nvlist_add_uint64_array(list, propname,
 623                     valuint64, numvalues)) != 0)
 624                         return (nwam_errno_to_nwam_error(nverr));
 625                 break;
 626         case NWAM_VALUE_TYPE_STRING:
 627                 if ((err = nwam_value_get_string_array(value, &valstr,
 628                     &numvalues)) != NWAM_SUCCESS)
 629                         return (err);
 630                 if ((nverr = nvlist_add_string_array(list, propname,
 631                     valstr, numvalues)) != 0)
 632                         return (nwam_errno_to_nwam_error(nverr));
 633                 break;
 634         default:
 635                 return (NWAM_INVALID_ARG);
 636         }
 637 
 638         return (NWAM_SUCCESS);
 639 }
 640 
 641 /* Map uint64 values to their string counterparts */
 642 
 643 struct nwam_value_entry {
 644         const char      *value_string;
 645         uint64_t                value;
 646 };
 647 
 648 struct nwam_value_entry prop_activation_mode_value_entries[] =
 649 {
 650         { NWAM_ACTIVATION_MODE_MANUAL_STRING, NWAM_ACTIVATION_MODE_MANUAL },
 651         { NWAM_ACTIVATION_MODE_SYSTEM_STRING, NWAM_ACTIVATION_MODE_SYSTEM },
 652         { NWAM_ACTIVATION_MODE_CONDITIONAL_ANY_STRING,
 653         NWAM_ACTIVATION_MODE_CONDITIONAL_ANY },
 654         { NWAM_ACTIVATION_MODE_CONDITIONAL_ALL_STRING,
 655         NWAM_ACTIVATION_MODE_CONDITIONAL_ALL },
 656         { NWAM_ACTIVATION_MODE_PRIORITIZED_STRING,
 657         NWAM_ACTIVATION_MODE_PRIORITIZED },
 658         { NULL, 0 }
 659 };
 660 
 661 struct nwam_value_entry ncu_prop_type_entries[] =
 662 {
 663         { NWAM_NCU_TYPE_LINK_STRING, NWAM_NCU_TYPE_LINK },
 664         { NWAM_NCU_TYPE_INTERFACE_STRING, NWAM_NCU_TYPE_INTERFACE },
 665         { NULL, 0 }
 666 };
 667 
 668 struct nwam_value_entry ncu_prop_class_entries[] =
 669 {
 670         { NWAM_NCU_CLASS_PHYS_STRING, NWAM_NCU_CLASS_PHYS },
 671         { NWAM_NCU_CLASS_IP_STRING, NWAM_NCU_CLASS_IP },
 672         { NULL, 0 }
 673 };
 674 
 675 struct nwam_value_entry ncu_prop_ip_version_entries[] =
 676 {
 677         { NWAM_IP_VERSION_IPV4_STRING, IPV4_VERSION },
 678         { NWAM_IP_VERSION_IPV6_STRING, IPV6_VERSION },
 679         { NULL, 0 }
 680 };
 681 
 682 struct nwam_value_entry ncu_prop_ipv4_addrsrc_entries[] =
 683 {
 684         { NWAM_ADDRSRC_DHCP_STRING, NWAM_ADDRSRC_DHCP },
 685         { NWAM_ADDRSRC_STATIC_STRING, NWAM_ADDRSRC_STATIC },
 686         { NULL, 0 }
 687 };
 688 
 689 struct nwam_value_entry ncu_prop_ipv6_addrsrc_entries[] =
 690 {
 691         { NWAM_ADDRSRC_DHCP_STRING, NWAM_ADDRSRC_DHCP },
 692         { NWAM_ADDRSRC_STATIC_STRING, NWAM_ADDRSRC_STATIC },
 693         { NWAM_ADDRSRC_AUTOCONF_STRING, NWAM_ADDRSRC_AUTOCONF },
 694         { NULL, 0 }
 695 };
 696 
 697 struct nwam_value_entry ncu_prop_priority_mode_entries[] =
 698 {
 699         { NWAM_PRIORITY_MODE_EXCLUSIVE_STRING, NWAM_PRIORITY_MODE_EXCLUSIVE },
 700         { NWAM_PRIORITY_MODE_SHARED_STRING, NWAM_PRIORITY_MODE_SHARED },
 701         { NWAM_PRIORITY_MODE_ALL_STRING, NWAM_PRIORITY_MODE_ALL },
 702         { NULL, 0 }
 703 };
 704 
 705 struct nwam_value_entry loc_prop_nameservices_entries[] =
 706 {
 707         { NWAM_NAMESERVICES_DNS_STRING, NWAM_NAMESERVICES_DNS },
 708         { NWAM_NAMESERVICES_FILES_STRING, NWAM_NAMESERVICES_FILES },
 709         { NWAM_NAMESERVICES_NIS_STRING, NWAM_NAMESERVICES_NIS },
 710         { NWAM_NAMESERVICES_LDAP_STRING, NWAM_NAMESERVICES_LDAP },
 711         { NULL, 0 }
 712 };
 713 
 714 struct nwam_value_entry loc_prop_nameservice_configsrc_entries[] =
 715 {
 716         { NWAM_CONFIGSRC_MANUAL_STRING, NWAM_CONFIGSRC_MANUAL },
 717         { NWAM_CONFIGSRC_DHCP_STRING, NWAM_CONFIGSRC_DHCP },
 718         { NULL, 0 }
 719 };
 720 
 721 struct nwam_value_entry known_wlan_prop_security_mode_entries[] =
 722 {
 723         { "none", DLADM_WLAN_SECMODE_NONE },
 724         { "wep", DLADM_WLAN_SECMODE_WEP },
 725         { "wpa", DLADM_WLAN_SECMODE_WPA },
 726         { NULL, 0 }
 727 };
 728 
 729 struct nwam_prop_value_entry {
 730         const char              *prop_name;
 731         struct nwam_value_entry *value_entries;
 732 } prop_value_entry_table[] =
 733 {
 734         { NWAM_NCU_PROP_ACTIVATION_MODE, prop_activation_mode_value_entries },
 735         { NWAM_NCU_PROP_TYPE, ncu_prop_type_entries },
 736         { NWAM_NCU_PROP_CLASS, ncu_prop_class_entries },
 737         { NWAM_NCU_PROP_IP_VERSION, ncu_prop_ip_version_entries },
 738         { NWAM_NCU_PROP_IPV4_ADDRSRC, ncu_prop_ipv4_addrsrc_entries },
 739         { NWAM_NCU_PROP_IPV6_ADDRSRC, ncu_prop_ipv6_addrsrc_entries },
 740         { NWAM_NCU_PROP_PRIORITY_MODE, ncu_prop_priority_mode_entries },
 741         { NWAM_ENM_PROP_ACTIVATION_MODE, prop_activation_mode_value_entries },
 742         { NWAM_LOC_PROP_ACTIVATION_MODE, prop_activation_mode_value_entries },
 743         { NWAM_LOC_PROP_NAMESERVICES, loc_prop_nameservices_entries },
 744         { NWAM_LOC_PROP_DNS_NAMESERVICE_CONFIGSRC,
 745             loc_prop_nameservice_configsrc_entries },
 746         { NWAM_LOC_PROP_NIS_NAMESERVICE_CONFIGSRC,
 747             loc_prop_nameservice_configsrc_entries },
 748         { NWAM_LOC_PROP_LDAP_NAMESERVICE_CONFIGSRC,
 749             loc_prop_nameservice_configsrc_entries },
 750         { NWAM_KNOWN_WLAN_PROP_SECURITY_MODE,
 751             known_wlan_prop_security_mode_entries },
 752         { NULL, NULL }
 753 };
 754 
 755 /*
 756  * Convert uint64 values for property propname into a string representing
 757  * that value. Used by enum values.
 758  */
 759 nwam_error_t
 760 nwam_uint64_get_value_string(const char *propname, uint64_t val,
 761     const char **valstrp)
 762 {
 763         int i, j;
 764         int max = 0; /* largest enum value seen so far */
 765         struct nwam_value_entry *value_entries;
 766 
 767         assert(propname != NULL && valstrp != NULL);
 768 
 769         for (i = 0; prop_value_entry_table[i].prop_name != NULL; i++) {
 770                 if (strcmp(prop_value_entry_table[i].prop_name, propname) != 0)
 771                         continue;
 772 
 773                 value_entries = prop_value_entry_table[i].value_entries;
 774 
 775                 for (j = 0; value_entries[j].value_string != NULL; j++) {
 776                         if (value_entries[j].value == val) {
 777                                 *valstrp = value_entries[j].value_string;
 778                                 return (NWAM_SUCCESS);
 779                         }
 780                         max = value_entries[j].value > max ?
 781                             value_entries[j].value : max;
 782                 }
 783                 /*
 784                  * If trying to get the string for an enum value that doesn't
 785                  * exist, return NWAM_LIST_END.  Otherwise, the input enum
 786                  * value doesn't exist for the given property.
 787                  */
 788                 if (val > max)
 789                         return (NWAM_LIST_END);
 790                 else
 791                         return (NWAM_ENTITY_INVALID_VALUE);
 792         }
 793         return (NWAM_INVALID_ARG);
 794 }
 795 
 796 /*
 797  * Convert string to appropriate uint64 value.
 798  */
 799 nwam_error_t
 800 nwam_value_string_get_uint64(const char *propname, const char *valstr,
 801     uint64_t *valp)
 802 {
 803         int i, j;
 804         struct nwam_value_entry *value_entries;
 805 
 806         assert(propname != NULL && valstr != NULL && valp != NULL);
 807 
 808         for (i = 0; prop_value_entry_table[i].prop_name != NULL; i++) {
 809                 if (strcmp(prop_value_entry_table[i].prop_name, propname) != 0)
 810                         continue;
 811 
 812                 value_entries = prop_value_entry_table[i].value_entries;
 813 
 814                 for (j = 0; value_entries[j].value_string != NULL; j++) {
 815                         if (strcasecmp(value_entries[j].value_string, valstr)
 816                             == 0) {
 817                                 *valp = value_entries[j].value;
 818                                 return (NWAM_SUCCESS);
 819                         }
 820                 }
 821                 return (NWAM_ENTITY_INVALID_VALUE);
 822         }
 823         return (NWAM_INVALID_ARG);
 824 }
 825 
 826 /* Conditional activation functions */
 827 
 828 nwam_error_t
 829 nwam_condition_to_condition_string(nwam_condition_object_type_t object_type,
 830     nwam_condition_t condition, const char *object_name, char **stringp)
 831 {
 832         char *object_type_string, *condition_string;
 833         char *string;
 834 
 835         assert(stringp != NULL);
 836 
 837         *stringp = NULL;
 838 
 839         switch (object_type) {
 840         case NWAM_CONDITION_OBJECT_TYPE_NCP:
 841                 object_type_string = NWAM_CONDITION_OBJECT_TYPE_NCP_STRING;
 842                 break;
 843         case NWAM_CONDITION_OBJECT_TYPE_NCU:
 844                 object_type_string = NWAM_CONDITION_OBJECT_TYPE_NCU_STRING;
 845                 break;
 846         case NWAM_CONDITION_OBJECT_TYPE_ENM:
 847                 object_type_string = NWAM_CONDITION_OBJECT_TYPE_ENM_STRING;
 848                 break;
 849         case NWAM_CONDITION_OBJECT_TYPE_LOC:
 850                 object_type_string = NWAM_CONDITION_OBJECT_TYPE_LOC_STRING;
 851                 break;
 852         case NWAM_CONDITION_OBJECT_TYPE_IP_ADDRESS:
 853                 object_type_string =
 854                     NWAM_CONDITION_OBJECT_TYPE_IP_ADDRESS_STRING;
 855                 break;
 856         case NWAM_CONDITION_OBJECT_TYPE_ADV_DOMAIN:
 857                 object_type_string =
 858                     NWAM_CONDITION_OBJECT_TYPE_ADV_DOMAIN_STRING;
 859                 break;
 860         case NWAM_CONDITION_OBJECT_TYPE_SYS_DOMAIN:
 861                 object_type_string =
 862                     NWAM_CONDITION_OBJECT_TYPE_SYS_DOMAIN_STRING;
 863                 break;
 864         case NWAM_CONDITION_OBJECT_TYPE_ESSID:
 865                 object_type_string = NWAM_CONDITION_OBJECT_TYPE_ESSID_STRING;
 866                 break;
 867         case NWAM_CONDITION_OBJECT_TYPE_BSSID:
 868                 object_type_string = NWAM_CONDITION_OBJECT_TYPE_BSSID_STRING;
 869                 break;
 870         default:
 871                 return (NWAM_INVALID_ARG);
 872 
 873         }
 874         switch (condition) {
 875         case NWAM_CONDITION_IS:
 876                 condition_string = NWAM_CONDITION_IS_STRING;
 877                 break;
 878         case NWAM_CONDITION_IS_NOT:
 879                 condition_string = NWAM_CONDITION_IS_NOT_STRING;
 880                 break;
 881         case NWAM_CONDITION_CONTAINS:
 882                 if (object_type != NWAM_CONDITION_OBJECT_TYPE_SYS_DOMAIN &&
 883                     object_type != NWAM_CONDITION_OBJECT_TYPE_ADV_DOMAIN &&
 884                     object_type != NWAM_CONDITION_OBJECT_TYPE_ESSID)
 885                         return (NWAM_INVALID_ARG);
 886                 condition_string = NWAM_CONDITION_CONTAINS_STRING;
 887                 break;
 888         case NWAM_CONDITION_DOES_NOT_CONTAIN:
 889                 if (object_type != NWAM_CONDITION_OBJECT_TYPE_SYS_DOMAIN &&
 890                     object_type != NWAM_CONDITION_OBJECT_TYPE_ADV_DOMAIN &&
 891                     object_type != NWAM_CONDITION_OBJECT_TYPE_ESSID)
 892                         return (NWAM_INVALID_ARG);
 893 
 894                 condition_string = NWAM_CONDITION_DOES_NOT_CONTAIN_STRING;
 895                 break;
 896         case NWAM_CONDITION_IS_IN_RANGE:
 897                 if (object_type != NWAM_CONDITION_OBJECT_TYPE_IP_ADDRESS)
 898                         return (NWAM_INVALID_ARG);
 899                 condition_string = NWAM_CONDITION_IS_IN_RANGE_STRING;
 900                 break;
 901         case NWAM_CONDITION_IS_NOT_IN_RANGE:
 902                 if (object_type != NWAM_CONDITION_OBJECT_TYPE_IP_ADDRESS)
 903                         return (NWAM_INVALID_ARG);
 904                 condition_string = NWAM_CONDITION_IS_NOT_IN_RANGE_STRING;
 905                 break;
 906         default:
 907                 return (NWAM_INVALID_ARG);
 908         }
 909         if ((string = malloc(NWAM_MAX_VALUE_LEN)) == NULL)
 910                 return (NWAM_NO_MEMORY);
 911         switch (object_type) {
 912         case NWAM_CONDITION_OBJECT_TYPE_NCP:
 913         case NWAM_CONDITION_OBJECT_TYPE_NCU:
 914         case NWAM_CONDITION_OBJECT_TYPE_ENM:
 915         case NWAM_CONDITION_OBJECT_TYPE_LOC:
 916                 (void) snprintf(string, NWAM_MAX_VALUE_LEN,
 917                     "%s %s %s active", object_type_string,
 918                     object_name, condition_string);
 919                 *stringp = string;
 920                 break;
 921 
 922         case NWAM_CONDITION_OBJECT_TYPE_IP_ADDRESS:
 923         case NWAM_CONDITION_OBJECT_TYPE_ADV_DOMAIN:
 924         case NWAM_CONDITION_OBJECT_TYPE_SYS_DOMAIN:
 925         case NWAM_CONDITION_OBJECT_TYPE_ESSID:
 926         case NWAM_CONDITION_OBJECT_TYPE_BSSID:
 927                 (void) snprintf(string, NWAM_MAX_VALUE_LEN,
 928                     "%s %s %s", object_type_string,
 929                     condition_string, object_name);
 930                 *stringp = string;
 931                 break;
 932 
 933         default:
 934                 free(string);
 935                 return (NWAM_INVALID_ARG);
 936 
 937         }
 938         return (NWAM_SUCCESS);
 939 }
 940 
 941 nwam_error_t
 942 nwam_condition_string_to_condition(const char *string,
 943     nwam_condition_object_type_t *object_typep,
 944     nwam_condition_t *conditionp, char **object_namep)
 945 {
 946         char *copy, *lasts;
 947         char *object_type_string, *object_name;
 948         char *condition_string, *active_string;
 949 
 950         assert(string != NULL && object_typep != NULL && conditionp != NULL &&
 951             object_namep != NULL);
 952 
 953         if ((copy = strdup(string)) == NULL)
 954                 return (NWAM_NO_MEMORY);
 955 
 956         if ((object_type_string = strtok_r(copy, " \t", &lasts)) == NULL) {
 957                 free(copy);
 958                 return (NWAM_INVALID_ARG);
 959         }
 960 
 961         if (strcmp(object_type_string, NWAM_CONDITION_OBJECT_TYPE_NCP_STRING)
 962             == 0)
 963                 *object_typep = NWAM_CONDITION_OBJECT_TYPE_NCP;
 964         else if (strcmp(object_type_string,
 965             NWAM_CONDITION_OBJECT_TYPE_NCU_STRING) == 0)
 966                 *object_typep = NWAM_CONDITION_OBJECT_TYPE_NCU;
 967         else if (strcmp(object_type_string,
 968             NWAM_CONDITION_OBJECT_TYPE_ENM_STRING) == 0)
 969                 *object_typep = NWAM_CONDITION_OBJECT_TYPE_ENM;
 970         else if (strcmp(object_type_string,
 971             NWAM_CONDITION_OBJECT_TYPE_LOC_STRING) == 0)
 972                 *object_typep = NWAM_CONDITION_OBJECT_TYPE_LOC;
 973         else if (strcmp(object_type_string,
 974             NWAM_CONDITION_OBJECT_TYPE_IP_ADDRESS_STRING) == 0)
 975                 *object_typep = NWAM_CONDITION_OBJECT_TYPE_IP_ADDRESS;
 976         else if (strcmp(object_type_string,
 977             NWAM_CONDITION_OBJECT_TYPE_ADV_DOMAIN_STRING) == 0)
 978                 *object_typep = NWAM_CONDITION_OBJECT_TYPE_ADV_DOMAIN;
 979         else if (strcmp(object_type_string,
 980             NWAM_CONDITION_OBJECT_TYPE_SYS_DOMAIN_STRING) == 0)
 981                 *object_typep = NWAM_CONDITION_OBJECT_TYPE_SYS_DOMAIN;
 982         else if (strcmp(object_type_string,
 983             NWAM_CONDITION_OBJECT_TYPE_ESSID_STRING) == 0)
 984                 *object_typep = NWAM_CONDITION_OBJECT_TYPE_ESSID;
 985         else if (strcmp(object_type_string,
 986             NWAM_CONDITION_OBJECT_TYPE_BSSID_STRING) == 0)
 987                 *object_typep = NWAM_CONDITION_OBJECT_TYPE_BSSID;
 988         else {
 989                 free(copy);
 990                 return (NWAM_INVALID_ARG);
 991         }
 992 
 993         if (*object_typep == NWAM_CONDITION_OBJECT_TYPE_NCP ||
 994             *object_typep == NWAM_CONDITION_OBJECT_TYPE_NCU ||
 995             *object_typep == NWAM_CONDITION_OBJECT_TYPE_ENM ||
 996             *object_typep == NWAM_CONDITION_OBJECT_TYPE_LOC) {
 997                 if ((object_name = strtok_r(NULL, " \t", &lasts)) == NULL) {
 998                         free(copy);
 999                         return (NWAM_INVALID_ARG);
1000                 }
1001                 if ((*object_namep = strdup(object_name)) == NULL) {
1002                         free(copy);
1003                         return (NWAM_NO_MEMORY);
1004                 }
1005 
1006         }
1007 
1008         if ((condition_string = strtok_r(NULL, " \t", &lasts)) == NULL) {
1009                 free(copy);
1010                 if (*object_namep != NULL)
1011                         free(*object_namep);
1012                 return (NWAM_INVALID_ARG);
1013         }
1014         if (strcmp(condition_string, NWAM_CONDITION_IS_STRING) == 0)
1015                 *conditionp = NWAM_CONDITION_IS;
1016         else if (strcmp(condition_string, NWAM_CONDITION_IS_NOT_STRING) == 0)
1017                 *conditionp = NWAM_CONDITION_IS_NOT;
1018         else if (strcmp(condition_string, NWAM_CONDITION_CONTAINS_STRING) == 0)
1019                 *conditionp = NWAM_CONDITION_CONTAINS;
1020         else if (strcmp(condition_string,
1021             NWAM_CONDITION_DOES_NOT_CONTAIN_STRING) == 0)
1022                 *conditionp = NWAM_CONDITION_DOES_NOT_CONTAIN;
1023         else if (strcmp(condition_string,
1024             NWAM_CONDITION_IS_IN_RANGE_STRING) == 0)
1025                 *conditionp = NWAM_CONDITION_IS_IN_RANGE;
1026         else if (strcmp(condition_string,
1027             NWAM_CONDITION_IS_NOT_IN_RANGE_STRING) == 0)
1028                 *conditionp = NWAM_CONDITION_IS_NOT_IN_RANGE;
1029         else {
1030                 free(copy);
1031                 if (*object_namep != NULL)
1032                         free(*object_namep);
1033                 return (NWAM_INVALID_ARG);
1034         }
1035 
1036         if (*object_typep == NWAM_CONDITION_OBJECT_TYPE_NCP ||
1037             *object_typep == NWAM_CONDITION_OBJECT_TYPE_NCU ||
1038             *object_typep == NWAM_CONDITION_OBJECT_TYPE_ENM ||
1039             *object_typep == NWAM_CONDITION_OBJECT_TYPE_LOC) {
1040                 if ((*conditionp != NWAM_CONDITION_IS &&
1041                     *conditionp != NWAM_CONDITION_IS_NOT) ||
1042                     (active_string = strtok_r(NULL, " \t", &lasts)) == NULL ||
1043                     strcmp(active_string, NWAM_CONDITION_ACTIVE_STRING) != 0) {
1044                         free(copy);
1045                         free(*object_namep);
1046                         return (NWAM_INVALID_ARG);
1047                 }
1048         } else {
1049                 switch (*conditionp) {
1050                 case NWAM_CONDITION_CONTAINS:
1051                 case NWAM_CONDITION_DOES_NOT_CONTAIN:
1052                         if (*object_typep !=
1053                             NWAM_CONDITION_OBJECT_TYPE_ADV_DOMAIN &&
1054                             *object_typep !=
1055                             NWAM_CONDITION_OBJECT_TYPE_SYS_DOMAIN &&
1056                             *object_typep != NWAM_CONDITION_OBJECT_TYPE_ESSID) {
1057                                 free(copy);
1058                                 free(*object_namep);
1059                                 return (NWAM_INVALID_ARG);
1060                         }
1061                         break;
1062                 case NWAM_CONDITION_IS_IN_RANGE:
1063                 case NWAM_CONDITION_IS_NOT_IN_RANGE:
1064                         if (*object_typep !=
1065                             NWAM_CONDITION_OBJECT_TYPE_IP_ADDRESS) {
1066                                 free(copy);
1067                                 free(*object_namep);
1068                                 return (NWAM_INVALID_ARG);
1069                         }
1070                         break;
1071                 }
1072 
1073                 if ((object_name = strtok_r(NULL, " \t", &lasts)) == NULL) {
1074                         free(copy);
1075                         free(*object_namep);
1076                         return (NWAM_INVALID_ARG);
1077                 }
1078                 if ((*object_namep = strdup(object_name)) == NULL) {
1079                         free(copy);
1080                         free(*object_namep);
1081                         return (NWAM_NO_MEMORY);
1082                 }
1083         }
1084 
1085         free(copy);
1086         return (NWAM_SUCCESS);
1087 }
1088 
1089 nwam_error_t
1090 nwam_condition_rate(nwam_condition_object_type_t object_type,
1091     nwam_condition_t condition, uint64_t *ratep)
1092 {
1093         assert(ratep != NULL);
1094 
1095         *ratep = 0;
1096 
1097         switch (object_type) {
1098         case NWAM_CONDITION_OBJECT_TYPE_NCP:
1099         case NWAM_CONDITION_OBJECT_TYPE_NCU:
1100         case NWAM_CONDITION_OBJECT_TYPE_ENM:
1101         case NWAM_CONDITION_OBJECT_TYPE_LOC:
1102                 (*ratep)++;
1103                 /* FALLTHRU */
1104         case NWAM_CONDITION_OBJECT_TYPE_SYS_DOMAIN:
1105                 (*ratep)++;
1106                 /* FALLTHRU */
1107         case NWAM_CONDITION_OBJECT_TYPE_ADV_DOMAIN:
1108                 (*ratep)++;
1109                 /* FALLTHRU */
1110         case NWAM_CONDITION_OBJECT_TYPE_IP_ADDRESS:
1111                 (*ratep)++;
1112                 /* FALLTHRU */
1113         case NWAM_CONDITION_OBJECT_TYPE_BSSID:
1114                 (*ratep)++;
1115                 /* FALLTHRU */
1116         case NWAM_CONDITION_OBJECT_TYPE_ESSID:
1117                 (*ratep)++;
1118                 break;
1119         default:
1120                 return (NWAM_INVALID_ARG);
1121         }
1122 
1123         switch (condition) {
1124         case NWAM_CONDITION_IS:
1125                 (*ratep)++;
1126                 /* FALLTHRU */
1127         case NWAM_CONDITION_CONTAINS:
1128         case NWAM_CONDITION_IS_IN_RANGE:
1129                 (*ratep)++;
1130                 /* FALLTHRU */
1131         case NWAM_CONDITION_DOES_NOT_CONTAIN:
1132         case NWAM_CONDITION_IS_NOT_IN_RANGE:
1133                 (*ratep)++;
1134                 /* FALLTHRU */
1135         case NWAM_CONDITION_IS_NOT:
1136                 (*ratep)++;
1137                 break;
1138         default:
1139                 return (NWAM_INVALID_ARG);
1140         }
1141         return (NWAM_SUCCESS);
1142 }