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 */ 25 26 #include <assert.h> 27 #include <ctype.h> 28 #include <sys/param.h> 29 #include <sys/types.h> 30 #include <sys/stat.h> 31 #include <stdio.h> 32 #include <stdlib.h> 33 #include <strings.h> 34 #include <unistd.h> 35 #include <libscf.h> 36 37 #include "libnwam_impl.h" 38 #include <libnwam_priv.h> 39 #include <libnwam.h> 40 41 /* 42 * Functions to support creating, modifying, destroying, querying the 43 * state of and changing the state of location objects. Locations 44 * represent the configuration to be applied once basic network configuration 45 * has been established - name services, IPsec config, etc, and can be enabled 46 * either manually or conditionally for a combination of the set of 47 * available conditions (an IP address is present, an ENM is active etc). 48 */ 49 50 #define NSSWITCH_PREFIX "/etc/nsswitch." 51 52 typedef nwam_error_t (*nwam_loc_prop_validate_func_t)(nwam_value_t); 53 54 static nwam_error_t valid_loc_activation_mode(nwam_value_t); 55 static nwam_error_t valid_loc_condition(nwam_value_t); 56 static nwam_error_t valid_nameservices(nwam_value_t); 57 static nwam_error_t valid_configsrc(nwam_value_t); 58 59 struct nwam_prop_table_entry loc_prop_table_entries[] = { 60 {NWAM_LOC_PROP_ACTIVATION_MODE, NWAM_VALUE_TYPE_UINT64, B_FALSE, 1, 1, 61 valid_loc_activation_mode, 62 "specifies the location activation mode - valid values are:\n" 63 "\'manual\', \'conditional-any\' and \'conditional-all\'", 64 NWAM_TYPE_ANY, NWAM_CLASS_ANY}, 65 {NWAM_LOC_PROP_CONDITIONS, NWAM_VALUE_TYPE_STRING, B_FALSE, 0, 66 NWAM_MAX_NUM_VALUES, valid_loc_condition, 67 "specifies the activation condition. Conditions are of the form:\n" 68 "ncp|ncu|enm name is|is-not active\n" 69 "ip-address is|is-not|is-in-range|is-not-in-range| 1.2.3.4[/24]\n" 70 "advertised-domain is|is-not|contains|does-not-contain string\n" 71 "system-domain is|is-not|contains|does-not-contain string\n" 72 "essid is|is-not|contains|does-not-contain string\n" 73 "bssid is|is-not string", 74 NWAM_TYPE_ANY, NWAM_CLASS_ANY}, 75 {NWAM_LOC_PROP_ENABLED, NWAM_VALUE_TYPE_BOOLEAN, B_TRUE, 1, 1, 76 nwam_valid_boolean, 77 "specifies if location is to be enabled", 78 NWAM_TYPE_ANY, NWAM_CLASS_ANY}, 79 {NWAM_LOC_PROP_NAMESERVICES, NWAM_VALUE_TYPE_UINT64, B_FALSE, 1, 80 NWAM_MAX_NUM_VALUES, valid_nameservices, 81 "specifies name service(s) to be used - valid values are:\n" 82 "\'files\', \'dns\', \'nis\', and \'ldap\'", 83 NWAM_TYPE_ANY, NWAM_CLASS_ANY}, 84 {NWAM_LOC_PROP_NAMESERVICES_CONFIG_FILE, NWAM_VALUE_TYPE_STRING, 85 B_FALSE, 0, 1, nwam_valid_file, 86 "specifies path to configuration file for name services switch " 87 "for this location - see nsswitch.conf(5)", 88 NWAM_TYPE_ANY, NWAM_CLASS_ANY}, 89 {NWAM_LOC_PROP_DNS_NAMESERVICE_CONFIGSRC, NWAM_VALUE_TYPE_UINT64, 90 B_FALSE, 0, NWAM_MAX_NUM_VALUES, valid_configsrc, 91 "specifies sources of DNS configuration parameters - valid values " 92 "are:\n\'dhcp\', or \'manual\'", 93 NWAM_TYPE_ANY, NWAM_CLASS_ANY}, 94 {NWAM_LOC_PROP_DNS_NAMESERVICE_DOMAIN, NWAM_VALUE_TYPE_STRING, B_FALSE, 95 0, 1, nwam_valid_domain, 96 "specifies DNS domain name to be set for this location", 97 NWAM_TYPE_ANY, NWAM_CLASS_ANY}, 98 {NWAM_LOC_PROP_DNS_NAMESERVICE_SERVERS, NWAM_VALUE_TYPE_STRING, B_FALSE, 99 0, NWAM_MAX_NUM_VALUES, nwam_valid_host_any, 100 "specifies DNS server host address(es)", 101 NWAM_TYPE_ANY, NWAM_CLASS_ANY}, 102 {NWAM_LOC_PROP_DNS_NAMESERVICE_SEARCH, NWAM_VALUE_TYPE_STRING, B_FALSE, 103 0, NWAM_MAX_NUM_VALUES, nwam_valid_domain, 104 "specifies DNS search list for host name lookup", 105 NWAM_TYPE_ANY, NWAM_CLASS_ANY}, 106 {NWAM_LOC_PROP_NIS_NAMESERVICE_CONFIGSRC, NWAM_VALUE_TYPE_UINT64, 107 B_FALSE, 0, NWAM_MAX_NUM_VALUES, valid_configsrc, 108 "specifies sources of NIS configuration parameters - valid values " 109 "are:\n\'dhcp\', or \'manual\'", 110 NWAM_TYPE_ANY, NWAM_CLASS_ANY}, 111 {NWAM_LOC_PROP_NIS_NAMESERVICE_SERVERS, NWAM_VALUE_TYPE_STRING, B_FALSE, 112 0, NWAM_MAX_NUM_VALUES, nwam_valid_host_any, 113 "specifies NIS server host address(es)", 114 NWAM_TYPE_ANY, NWAM_CLASS_ANY}, 115 {NWAM_LOC_PROP_LDAP_NAMESERVICE_CONFIGSRC, NWAM_VALUE_TYPE_UINT64, 116 B_FALSE, 0, NWAM_MAX_NUM_VALUES, valid_configsrc, 117 "specifies sources of NIS configuration parameters - currently, " 118 "the only valid value is \'manual\'", 119 NWAM_TYPE_ANY, NWAM_CLASS_ANY}, 120 {NWAM_LOC_PROP_LDAP_NAMESERVICE_SERVERS, NWAM_VALUE_TYPE_STRING, 121 B_FALSE, 0, NWAM_MAX_NUM_VALUES, nwam_valid_host_or_domain, 122 "specifies LDAP server host address(es)", 123 NWAM_TYPE_ANY, NWAM_CLASS_ANY}, 124 {NWAM_LOC_PROP_DEFAULT_DOMAIN, NWAM_VALUE_TYPE_STRING, B_FALSE, 0, 1, 125 nwam_valid_domain, 126 "specifies the domainname(8) to be set for this location", 127 NWAM_TYPE_ANY, NWAM_CLASS_ANY}, 128 {NWAM_LOC_PROP_NFSV4_DOMAIN, NWAM_VALUE_TYPE_STRING, B_FALSE, 0, 1, 129 nwam_valid_domain, 130 "specifies an NFSv4 domain for this location", 131 NWAM_TYPE_ANY, NWAM_CLASS_ANY}, 132 {NWAM_LOC_PROP_IPFILTER_CONFIG_FILE, NWAM_VALUE_TYPE_STRING, B_FALSE, 133 0, 1, nwam_valid_file, 134 "specifies an absolute path to an ipf.conf(5) file for this " 135 "location", 136 NWAM_TYPE_ANY, NWAM_CLASS_ANY}, 137 {NWAM_LOC_PROP_IPFILTER_V6_CONFIG_FILE, NWAM_VALUE_TYPE_STRING, 138 B_FALSE, 0, 1, nwam_valid_file, 139 "specifies an absolute path to an ipf6.conf file for this " 140 "location", 141 NWAM_TYPE_ANY, NWAM_CLASS_ANY}, 142 {NWAM_LOC_PROP_IPNAT_CONFIG_FILE, NWAM_VALUE_TYPE_STRING, B_FALSE, 0, 143 1, nwam_valid_file, 144 "specifies an absolute path to an ipnat.conf(5) file for this " 145 "location", 146 NWAM_TYPE_ANY, NWAM_CLASS_ANY}, 147 {NWAM_LOC_PROP_IPPOOL_CONFIG_FILE, NWAM_VALUE_TYPE_STRING, B_FALSE, 0, 148 1, nwam_valid_file, 149 "specifies an absolute path to an ippool.conf(5) file for this " 150 "location", 151 NWAM_TYPE_ANY, NWAM_CLASS_ANY}, 152 {NWAM_LOC_PROP_IKE_CONFIG_FILE, NWAM_VALUE_TYPE_STRING, B_FALSE, 0, 1, 153 nwam_valid_file, 154 "specifies an absolute path to an ike config file " 155 "(see ike.config(5))", 156 NWAM_TYPE_ANY, NWAM_CLASS_ANY}, 157 {NWAM_LOC_PROP_IPSECPOLICY_CONFIG_FILE, NWAM_VALUE_TYPE_STRING, 158 B_FALSE, 0, 1, nwam_valid_file, 159 "specifies an absolute path to an IPsec policy configuration file " 160 "(see ipsecconf(8)", 161 NWAM_TYPE_ANY, NWAM_CLASS_ANY}, 162 }; 163 164 #define NWAM_NUM_LOC_PROPS (sizeof (loc_prop_table_entries) / \ 165 sizeof (*loc_prop_table_entries)) 166 167 struct nwam_prop_table loc_prop_table = 168 { NWAM_NUM_LOC_PROPS, loc_prop_table_entries }; 169 170 static uint64_t 171 nwam_loc_activation_to_flag(nwam_activation_mode_t activation) 172 { 173 switch (activation) { 174 case NWAM_ACTIVATION_MODE_MANUAL: 175 return (NWAM_FLAG_ACTIVATION_MODE_MANUAL); 176 case NWAM_ACTIVATION_MODE_SYSTEM: 177 return (NWAM_FLAG_ACTIVATION_MODE_SYSTEM); 178 case NWAM_ACTIVATION_MODE_CONDITIONAL_ANY: 179 return (NWAM_FLAG_ACTIVATION_MODE_CONDITIONAL_ANY); 180 case NWAM_ACTIVATION_MODE_CONDITIONAL_ALL: 181 return (NWAM_FLAG_ACTIVATION_MODE_CONDITIONAL_ALL); 182 default: 183 return (0); 184 } 185 } 186 187 nwam_error_t 188 nwam_loc_read(const char *name, uint64_t flags, nwam_loc_handle_t *lochp) 189 { 190 return (nwam_read(NWAM_OBJECT_TYPE_LOC, NWAM_LOC_CONF_FILE, name, 191 flags, lochp)); 192 } 193 194 nwam_error_t 195 nwam_loc_create(const char *name, nwam_loc_handle_t *lochp) 196 { 197 nwam_error_t err; 198 nwam_value_t val = NULL; 199 char *nsswitch = NULL; 200 201 assert(lochp != NULL && name != NULL); 202 203 if ((err = nwam_create(NWAM_OBJECT_TYPE_LOC, NWAM_LOC_CONF_FILE, name, 204 lochp)) != NWAM_SUCCESS) 205 return (err); 206 207 /* Create new object list for loc */ 208 if ((err = nwam_alloc_object_list(&((*lochp)->nwh_data))) 209 != NWAM_SUCCESS) 210 goto finish; 211 212 /* NWAM_LOC_PROP_ACTIVATION_MODE is mandatory */ 213 if ((err = nwam_value_create_uint64(NWAM_ACTIVATION_MODE_MANUAL, &val)) 214 != NWAM_SUCCESS) { 215 goto finish; 216 } 217 if ((err = nwam_set_prop_value((*lochp)->nwh_data, 218 NWAM_LOC_PROP_ACTIVATION_MODE, val)) != NWAM_SUCCESS) { 219 goto finish; 220 } 221 nwam_value_free(val); 222 val = NULL; 223 224 /* 225 * NWAM_LOC_PROP_ENABLED defaults to false. 226 */ 227 if ((err = nwam_value_create_boolean(B_FALSE, &val)) != NWAM_SUCCESS) 228 goto finish; 229 if ((err = nwam_set_prop_value((*lochp)->nwh_data, 230 NWAM_LOC_PROP_ENABLED, val)) != NWAM_SUCCESS) 231 goto finish; 232 nwam_value_free(val); 233 val = NULL; 234 235 /* 236 * Initialize name service properties: use DNS, configured 237 * via DHCP, with default nsswitch (/etc/nsswitch.dns). 238 */ 239 if ((err = nwam_value_create_uint64(NWAM_NAMESERVICES_DNS, &val)) != 240 NWAM_SUCCESS) 241 goto finish; 242 if ((err = nwam_set_prop_value((*lochp)->nwh_data, 243 NWAM_LOC_PROP_NAMESERVICES, val)) != NWAM_SUCCESS) 244 goto finish; 245 nwam_value_free(val); 246 val = NULL; 247 248 if ((err = nwam_value_create_uint64(NWAM_CONFIGSRC_DHCP, &val)) != 249 NWAM_SUCCESS) 250 goto finish; 251 if ((err = nwam_set_prop_value((*lochp)->nwh_data, 252 NWAM_LOC_PROP_DNS_NAMESERVICE_CONFIGSRC, val)) != NWAM_SUCCESS) 253 goto finish; 254 nwam_value_free(val); 255 val = NULL; 256 257 /* concatenate these two strings */ 258 nsswitch = strdup(NSSWITCH_PREFIX NWAM_NAMESERVICES_DNS_STRING); 259 if (nsswitch == NULL) { 260 err = NWAM_NO_MEMORY; 261 goto finish; 262 } 263 if ((err = nwam_value_create_string(nsswitch, &val)) != NWAM_SUCCESS) 264 goto finish; 265 err = nwam_set_prop_value((*lochp)->nwh_data, 266 NWAM_LOC_PROP_NAMESERVICES_CONFIG_FILE, val); 267 268 finish: 269 if (nsswitch != NULL) 270 free(nsswitch); 271 if (val != NULL) 272 nwam_value_free(val); 273 if (err != NWAM_SUCCESS) { 274 nwam_loc_free(*lochp); 275 *lochp = NULL; 276 } 277 return (err); 278 } 279 280 nwam_error_t 281 nwam_loc_get_name(nwam_loc_handle_t loch, char **namep) 282 { 283 return (nwam_get_name(loch, namep)); 284 } 285 286 nwam_error_t 287 nwam_loc_set_name(nwam_loc_handle_t loch, const char *name) 288 { 289 return (nwam_set_name(loch, name)); 290 } 291 292 boolean_t 293 nwam_loc_can_set_name(nwam_loc_handle_t loch) 294 { 295 return (!loch->nwh_committed); 296 } 297 298 /* ARGSUSED2 */ 299 static int 300 loc_selectcb(struct nwam_handle *hp, uint64_t flags, void *data) 301 { 302 nwam_loc_handle_t loch = hp; 303 char *locname; 304 uint64_t activation, actflag, walkfilter; 305 nwam_value_t activationval; 306 307 /* Skip the Legacy location in all cases */ 308 if (nwam_loc_get_name(loch, &locname) != NWAM_SUCCESS) 309 return (NWAM_INVALID_ARG); 310 if (strcmp(locname, NWAM_LOC_NAME_LEGACY) == 0) { 311 free(locname); 312 return (NWAM_INVALID_ARG); 313 } 314 free(locname); 315 316 /* 317 * Get a bitmapped flag value corresponding to this loc's 318 * activation. 319 */ 320 if (nwam_loc_get_prop_value(loch, NWAM_LOC_PROP_ACTIVATION_MODE, 321 &activationval) != NWAM_SUCCESS) { 322 return (NWAM_INVALID_ARG); 323 } 324 if (nwam_value_get_uint64(activationval, &activation) != NWAM_SUCCESS) { 325 nwam_value_free(activationval); 326 return (NWAM_INVALID_ARG); 327 } 328 329 actflag = nwam_loc_activation_to_flag(activation); 330 nwam_value_free(activationval); 331 if ((walkfilter = (flags & NWAM_WALK_FILTER_MASK)) == 0) 332 walkfilter = NWAM_FLAG_ACTIVATION_MODE_ALL; 333 if (actflag & walkfilter) 334 return (NWAM_SUCCESS); 335 return (NWAM_INVALID_ARG); 336 } 337 338 nwam_error_t 339 nwam_walk_locs(int(*cb)(nwam_loc_handle_t, void *), void *data, uint64_t flags, 340 int *retp) 341 { 342 nwam_error_t err = nwam_valid_flags(flags, 343 NWAM_FLAG_ACTIVATION_MODE_ALL | NWAM_FLAG_BLOCKING); 344 345 if (err != NWAM_SUCCESS) 346 return (err); 347 348 return (nwam_walk(NWAM_OBJECT_TYPE_LOC, NWAM_LOC_CONF_FILE, 349 cb, data, flags, retp, loc_selectcb)); 350 } 351 352 void 353 nwam_loc_free(nwam_loc_handle_t loch) 354 { 355 nwam_free(loch); 356 } 357 358 nwam_error_t 359 nwam_loc_delete_prop(nwam_loc_handle_t loch, const char *propname) 360 { 361 nwam_error_t err; 362 boolean_t ro; 363 void *olddata; 364 365 assert(loch != NULL && propname != NULL); 366 367 if ((err = nwam_loc_prop_read_only(propname, &ro)) != NWAM_SUCCESS) 368 return (err); 369 if (ro) 370 return (NWAM_ENTITY_READ_ONLY); 371 372 /* 373 * Duplicate data, remove property and validate. If validation 374 * fails, revert to data duplicated prior to remove. 375 */ 376 if ((err = nwam_dup_object_list(loch->nwh_data, &olddata)) 377 != NWAM_SUCCESS) 378 return (err); 379 if ((err = nwam_delete_prop(loch->nwh_data, propname)) 380 != NWAM_SUCCESS) { 381 nwam_free_object_list(loch->nwh_data); 382 loch->nwh_data = olddata; 383 return (err); 384 } 385 if ((err = nwam_loc_validate(loch, NULL)) != NWAM_SUCCESS) { 386 nwam_free_object_list(loch->nwh_data); 387 loch->nwh_data = olddata; 388 return (err); 389 } 390 nwam_free_object_list(olddata); 391 392 return (NWAM_SUCCESS); 393 } 394 395 nwam_error_t 396 nwam_loc_set_prop_value(nwam_loc_handle_t loch, const char *propname, 397 nwam_value_t value) 398 { 399 nwam_error_t err; 400 boolean_t ro; 401 402 assert(loch != NULL && propname != NULL && value != NULL); 403 404 if ((err = nwam_loc_validate_prop(loch, propname, value)) 405 != NWAM_SUCCESS || 406 (err = nwam_loc_prop_read_only(propname, &ro)) != NWAM_SUCCESS) 407 return (err); 408 if (ro) 409 return (NWAM_ENTITY_READ_ONLY); 410 411 return (nwam_set_prop_value(loch->nwh_data, propname, value)); 412 } 413 414 nwam_error_t 415 nwam_loc_get_prop_value(nwam_loc_handle_t loch, const char *propname, 416 nwam_value_t *valuep) 417 { 418 return (nwam_get_prop_value(loch->nwh_data, propname, valuep)); 419 } 420 421 nwam_error_t 422 nwam_loc_walk_props(nwam_loc_handle_t loch, 423 int (*cb)(const char *, nwam_value_t, void *), 424 void *data, uint64_t flags, int *retp) 425 { 426 return (nwam_walk_props(loch, cb, data, flags, retp)); 427 } 428 429 nwam_error_t 430 nwam_loc_commit(nwam_loc_handle_t loch, uint64_t flags) 431 { 432 nwam_error_t err; 433 434 assert(loch != NULL && loch->nwh_data != NULL); 435 436 if ((err = nwam_loc_validate(loch, NULL)) != NWAM_SUCCESS) 437 return (err); 438 439 return (nwam_commit(NWAM_LOC_CONF_FILE, loch, flags)); 440 } 441 442 nwam_error_t 443 nwam_loc_destroy(nwam_loc_handle_t loch, uint64_t flags) 444 { 445 nwam_error_t err; 446 nwam_value_t actval; 447 uint64_t activation; 448 449 /* 450 * Automatic and NoNet are not destroyable and Legacy is 451 * destroyable by netadm only. These have system activation-mode. 452 */ 453 if ((err = nwam_loc_get_prop_value(loch, NWAM_LOC_PROP_ACTIVATION_MODE, 454 &actval)) != NWAM_SUCCESS) 455 return (err); 456 err = nwam_value_get_uint64(actval, &activation); 457 nwam_value_free(actval); 458 if (err != NWAM_SUCCESS) 459 return (err); 460 461 if (activation == NWAM_ACTIVATION_MODE_SYSTEM) { 462 if (strcmp(loch->nwh_name, NWAM_LOC_NAME_LEGACY) == 0) { 463 if (!nwam_uid_is_special()) 464 return (NWAM_ENTITY_NOT_DESTROYABLE); 465 } else { 466 return (NWAM_ENTITY_NOT_DESTROYABLE); 467 } 468 } 469 470 return (nwam_destroy(NWAM_LOC_CONF_FILE, loch, flags)); 471 } 472 473 nwam_error_t 474 nwam_loc_get_prop_description(const char *propname, const char **descriptionp) 475 { 476 return (nwam_get_prop_description(loc_prop_table, propname, 477 descriptionp)); 478 } 479 480 nwam_error_t 481 nwam_loc_prop_read_only(const char *propname, boolean_t *readp) 482 { 483 return (nwam_prop_read_only(loc_prop_table, propname, readp)); 484 } 485 486 static nwam_error_t 487 valid_loc_activation_mode(nwam_value_t value) 488 { 489 uint64_t activation_mode; 490 491 if (nwam_value_get_uint64(value, &activation_mode) != NWAM_SUCCESS) 492 return (NWAM_ENTITY_INVALID_VALUE); 493 494 switch (activation_mode) { 495 case NWAM_ACTIVATION_MODE_MANUAL: 496 case NWAM_ACTIVATION_MODE_SYSTEM: 497 case NWAM_ACTIVATION_MODE_CONDITIONAL_ANY: 498 case NWAM_ACTIVATION_MODE_CONDITIONAL_ALL: 499 return (NWAM_SUCCESS); 500 } 501 return (NWAM_ENTITY_INVALID_VALUE); 502 } 503 504 /* 505 * Identical to nwam_valid_condition(), except locations cannot specify other 506 * location's activation as a condition, e.g. loc2 cannot specify 507 * "loc1 is active" since only one location is active at a time, and 508 * as a consequence the condition is unsatisfiable. 509 */ 510 nwam_error_t 511 valid_loc_condition(nwam_value_t value) 512 { 513 char **conditions; 514 uint_t i, numvalues; 515 nwam_condition_object_type_t object_type; 516 nwam_condition_t condition; 517 518 if (nwam_value_get_string_array(value, &conditions, &numvalues) 519 != NWAM_SUCCESS) 520 return (NWAM_ENTITY_INVALID_VALUE); 521 522 for (i = 0; i < numvalues; i++) { 523 char *object_name = NULL; 524 525 if (nwam_condition_string_to_condition(conditions[i], 526 &object_type, &condition, &object_name) != NWAM_SUCCESS) 527 return (NWAM_ENTITY_INVALID_VALUE); 528 if (object_type == NWAM_CONDITION_OBJECT_TYPE_LOC && 529 condition == NWAM_CONDITION_IS) { 530 free(object_name); 531 return (NWAM_ENTITY_INVALID_VALUE); 532 } 533 if (object_name != NULL) 534 free(object_name); 535 } 536 return (NWAM_SUCCESS); 537 } 538 539 static nwam_error_t 540 valid_nameservices(nwam_value_t value) 541 { 542 uint64_t *nameservices; 543 uint_t i, numvalues; 544 545 if (nwam_value_get_uint64_array(value, &nameservices, &numvalues) 546 != NWAM_SUCCESS) 547 return (NWAM_ENTITY_INVALID_VALUE); 548 549 for (i = 0; i < numvalues; i++) { 550 if (nameservices[i] > NWAM_NAMESERVICES_LDAP) 551 return (NWAM_ENTITY_INVALID_VALUE); 552 } 553 return (NWAM_SUCCESS); 554 } 555 556 static nwam_error_t 557 valid_configsrc(nwam_value_t value) 558 { 559 uint64_t *configsrcs; 560 uint_t i, numvalues; 561 562 if (nwam_value_get_uint64_array(value, &configsrcs, &numvalues) 563 != NWAM_SUCCESS) 564 return (NWAM_ENTITY_INVALID_VALUE); 565 566 for (i = 0; i < numvalues; i++) { 567 if (configsrcs[i] > NWAM_CONFIGSRC_DHCP) 568 return (NWAM_ENTITY_INVALID_VALUE); 569 } 570 return (NWAM_SUCCESS); 571 } 572 573 /* 574 * Validates that the activation-mode is system for Automatic and NoNet 575 * locations, and not system for all other locations. 576 */ 577 static nwam_error_t 578 nwam_loc_validate_activation_mode(nwam_loc_handle_t loch, nwam_value_t actval) 579 { 580 nwam_error_t err; 581 uint64_t activation; 582 583 if ((err = nwam_value_get_uint64(actval, &activation)) != NWAM_SUCCESS) 584 return (err); 585 586 if (NWAM_LOC_NAME_PRE_DEFINED(loch->nwh_name)) { 587 if (activation != NWAM_ACTIVATION_MODE_SYSTEM) 588 return (NWAM_ENTITY_INVALID_VALUE); 589 } else { 590 if (activation == NWAM_ACTIVATION_MODE_SYSTEM) 591 return (NWAM_ENTITY_INVALID_VALUE); 592 } 593 return (NWAM_SUCCESS); 594 } 595 596 /* 597 * Helper function to validate one nameservice, used by 598 * nwam_loc_validate_all_nameservices(). 599 * 600 * requiredprop denotes the property that is mandatory when the 601 * configsrcprop is manual. errpropp is used to return the invalid 602 * property. 603 */ 604 static nwam_error_t 605 nwam_loc_validate_one_nameservice(nwam_loc_handle_t loch, 606 const char *configsrcprop, const char *requiredprop, const char **errpropp) 607 { 608 nwam_value_t configsrcval, requiredval; 609 uint64_t *configsrcs; 610 uint_t i, numvalues; 611 612 if (nwam_loc_get_prop_value(loch, configsrcprop, &configsrcval) 613 != NWAM_SUCCESS) { 614 if (errpropp != NULL) 615 *errpropp = configsrcprop; 616 return (NWAM_ENTITY_MISSING_MEMBER); 617 } 618 619 if (nwam_value_get_uint64_array(configsrcval, &configsrcs, &numvalues) 620 != NWAM_SUCCESS) { 621 if (errpropp != NULL) 622 *errpropp = configsrcprop; 623 nwam_value_free(configsrcval); 624 return (NWAM_ENTITY_NO_VALUE); 625 } 626 627 /* If -configsrc is manual, requiredprop is required */ 628 for (i = 0; i < numvalues; i++) { 629 if (configsrcs[i] == NWAM_CONFIGSRC_MANUAL) { 630 if (nwam_loc_get_prop_value(loch, requiredprop, 631 &requiredval) != NWAM_SUCCESS) { 632 if (errpropp != NULL) 633 *errpropp = requiredprop; 634 return (NWAM_ENTITY_MISSING_MEMBER); 635 } 636 nwam_value_free(requiredval); 637 } 638 } 639 nwam_value_free(configsrcval); 640 641 return (NWAM_SUCCESS); 642 } 643 644 /* 645 * Helper function to validate LDAP nameservice, used by 646 * nwam_loc_validate_all_nameservices(). Separated because LDAP must be 647 * configured manually only and both default-domain and -servers are required. 648 */ 649 static nwam_error_t 650 nwam_loc_validate_ldap_nameservice(nwam_loc_handle_t loch, 651 const char **errpropp) 652 { 653 nwam_value_t val; 654 uint64_t *configsrcs; 655 uint_t i, numvalues; 656 657 if (nwam_loc_get_prop_value(loch, 658 NWAM_LOC_PROP_LDAP_NAMESERVICE_CONFIGSRC, &val) != NWAM_SUCCESS) { 659 if (errpropp != NULL) 660 *errpropp = NWAM_LOC_PROP_LDAP_NAMESERVICE_CONFIGSRC; 661 return (NWAM_ENTITY_MISSING_MEMBER); 662 } 663 /* -configsrc is defined as an array */ 664 if (nwam_value_get_uint64_array(val, &configsrcs, &numvalues) 665 != NWAM_SUCCESS) { 666 if (errpropp != NULL) 667 *errpropp = NWAM_LOC_PROP_LDAP_NAMESERVICE_CONFIGSRC; 668 nwam_value_free(val); 669 return (NWAM_ENTITY_NO_VALUE); 670 } 671 672 /* -configsrc must be manual */ 673 for (i = 0; i < numvalues; i++) { 674 if (configsrcs[i] != NWAM_CONFIGSRC_MANUAL) { 675 if (errpropp != NULL) 676 *errpropp = 677 NWAM_LOC_PROP_LDAP_NAMESERVICE_CONFIGSRC; 678 nwam_value_free(val); 679 return (NWAM_ENTITY_INVALID_VALUE); 680 } 681 } 682 nwam_value_free(val); 683 684 /* both default-domain and -servers are required */ 685 if (nwam_loc_get_prop_value(loch, 686 NWAM_LOC_PROP_DEFAULT_DOMAIN, &val) != NWAM_SUCCESS) { 687 if (errpropp != NULL) 688 *errpropp = NWAM_LOC_PROP_DEFAULT_DOMAIN; 689 return (NWAM_ENTITY_MISSING_MEMBER); 690 } 691 nwam_value_free(val); 692 693 if (nwam_loc_get_prop_value(loch, 694 NWAM_LOC_PROP_LDAP_NAMESERVICE_SERVERS, &val) != NWAM_SUCCESS) { 695 if (errpropp != NULL) 696 *errpropp = NWAM_LOC_PROP_LDAP_NAMESERVICE_SERVERS; 697 return (NWAM_ENTITY_MISSING_MEMBER); 698 } 699 nwam_value_free(val); 700 701 return (NWAM_SUCCESS); 702 } 703 704 /* 705 * Validates the different nameservices properties. 706 * 707 * If "nameservices" property has more than one nameservice to configure, 708 * "nameservices-config-file" must be specified. If only one nameservice 709 * is configured and "nameservices-config-file" is missing, set the 710 * property with the appropriately suffixed nsswitch file. 711 * 712 * For any nameservice being configured, the respective -configsrc property 713 * must be specified. For DNS, -servers is required if -configsrc is 714 * manual. For NIS and LDAP, default-domain is required if -configsrc is 715 * manual. For LDAP, -configsrc must be manual and -servers is required. 716 */ 717 static nwam_error_t 718 nwam_loc_validate_all_nameservices(nwam_loc_handle_t loch, 719 nwam_value_t nameservicesval, const char **errpropp) 720 { 721 nwam_error_t err; 722 nwam_value_t val; 723 uint64_t *nameservices; 724 uint_t i, numvalues; 725 726 if ((err = nwam_value_get_uint64_array(nameservicesval, &nameservices, 727 &numvalues)) != NWAM_SUCCESS) 728 return (err); 729 730 /* 731 * nameservices-config-file is required if nameservices has more 732 * than one value. 733 */ 734 if (numvalues > 1) { 735 if (nwam_loc_get_prop_value(loch, 736 NWAM_LOC_PROP_NAMESERVICES_CONFIG_FILE, &val) 737 != NWAM_SUCCESS) { 738 if (errpropp != NULL) 739 *errpropp = 740 NWAM_LOC_PROP_NAMESERVICES_CONFIG_FILE; 741 return (NWAM_ENTITY_MISSING_MEMBER); 742 } 743 nwam_value_free(val); 744 } else if (numvalues == 1) { 745 /* 746 * If only one nameservice is being configured and 747 * nameservices-config-file doesn't exist, create it to 748 * point to the respective nsswitch file. 749 */ 750 err = nwam_loc_get_prop_value(loch, 751 NWAM_LOC_PROP_NAMESERVICES_CONFIG_FILE, &val); 752 if (err == NWAM_INVALID_ARG || err == NWAM_ENTITY_NOT_FOUND) { 753 char *nsswitch; 754 const char *nsswitch_suffix; 755 756 /* get the single nameservice being configured */ 757 if ((err = nwam_uint64_get_value_string( 758 NWAM_LOC_PROP_NAMESERVICES, nameservices[0], 759 &nsswitch_suffix)) != NWAM_SUCCESS) 760 goto config_file_fail; 761 if ((nsswitch = malloc(MAXPATHLEN)) == NULL) { 762 err = NWAM_NO_MEMORY; 763 goto config_file_fail; 764 } 765 766 /* create appropriately suffixed nsswitch name */ 767 (void) snprintf(nsswitch, MAXPATHLEN, "%s%s", 768 NSSWITCH_PREFIX, nsswitch_suffix); 769 if ((err = nwam_value_create_string(nsswitch, &val)) 770 != NWAM_SUCCESS) { 771 free(nsswitch); 772 goto config_file_fail; 773 } 774 775 err = nwam_set_prop_value(loch->nwh_data, 776 NWAM_LOC_PROP_NAMESERVICES_CONFIG_FILE, val); 777 free(nsswitch); 778 nwam_value_free(val); 779 if (err != NWAM_SUCCESS) { 780 nwam_value_free(val); 781 goto config_file_fail; 782 } 783 } else if (err != NWAM_SUCCESS) { 784 goto config_file_fail; 785 } else { 786 nwam_value_free(val); 787 } 788 } 789 790 /* 791 * validate the -configsrc property and the required default-domain 792 * and/or -servers property for each nameservice being configured. 793 */ 794 for (i = 0; i < numvalues; i++) { 795 switch (nameservices[i]) { 796 case NWAM_NAMESERVICES_DNS: 797 if ((err = nwam_loc_validate_one_nameservice(loch, 798 NWAM_LOC_PROP_DNS_NAMESERVICE_CONFIGSRC, 799 NWAM_LOC_PROP_DNS_NAMESERVICE_SERVERS, errpropp)) 800 != NWAM_SUCCESS) 801 return (err); 802 break; 803 case NWAM_NAMESERVICES_NIS: 804 if ((err = nwam_loc_validate_one_nameservice(loch, 805 NWAM_LOC_PROP_NIS_NAMESERVICE_CONFIGSRC, 806 NWAM_LOC_PROP_DEFAULT_DOMAIN, errpropp)) 807 != NWAM_SUCCESS) 808 return (err); 809 break; 810 case NWAM_NAMESERVICES_LDAP: 811 if ((err = nwam_loc_validate_ldap_nameservice(loch, 812 errpropp)) != NWAM_SUCCESS) 813 return (err); 814 break; 815 case NWAM_NAMESERVICES_FILES: 816 break; 817 default: 818 return (NWAM_ENTITY_INVALID_VALUE); 819 } 820 } 821 return (NWAM_SUCCESS); 822 823 config_file_fail: 824 if (errpropp != NULL) 825 *errpropp = NWAM_LOC_PROP_NAMESERVICES_CONFIG_FILE; 826 return (err); 827 } 828 829 nwam_error_t 830 nwam_loc_validate(nwam_loc_handle_t loch, const char **errpropp) 831 { 832 nwam_error_t err; 833 nwam_value_t activationval, conditionval, nameservicesval; 834 uint64_t activation; 835 char **conditions, *name; 836 uint_t i, numvalues; 837 nwam_condition_object_type_t object_type; 838 nwam_condition_t condition; 839 840 assert(loch != NULL); 841 842 /* 843 * Make sure loc is internally consistent: if activation type is 844 * conditional, the condition string must be specified. 845 */ 846 if (nwam_loc_get_prop_value(loch, NWAM_LOC_PROP_ACTIVATION_MODE, 847 &activationval) != NWAM_SUCCESS) { 848 if (errpropp != NULL) 849 *errpropp = NWAM_LOC_PROP_ACTIVATION_MODE; 850 return (NWAM_ENTITY_MISSING_MEMBER); 851 } 852 853 if (nwam_value_get_uint64(activationval, &activation) 854 != NWAM_SUCCESS) { 855 if (errpropp != NULL) 856 *errpropp = NWAM_LOC_PROP_ACTIVATION_MODE; 857 nwam_value_free(activationval); 858 return (NWAM_ENTITY_NO_VALUE); 859 } 860 861 /* validate activation against the location first */ 862 if ((err = nwam_loc_validate_activation_mode(loch, activationval)) 863 != NWAM_SUCCESS) { 864 if (errpropp != NULL) 865 *errpropp = NWAM_LOC_PROP_ACTIVATION_MODE; 866 nwam_value_free(activationval); 867 return (err); 868 } 869 nwam_value_free(activationval); 870 871 if (activation == NWAM_ACTIVATION_MODE_CONDITIONAL_ANY || 872 activation == NWAM_ACTIVATION_MODE_CONDITIONAL_ALL) { 873 if (nwam_loc_get_prop_value(loch, NWAM_LOC_PROP_CONDITIONS, 874 &conditionval) != NWAM_SUCCESS) { 875 if (errpropp != NULL) 876 *errpropp = NWAM_LOC_PROP_CONDITIONS; 877 return (NWAM_ENTITY_MISSING_MEMBER); 878 } 879 /* 880 * Are conditions self-referential? In other words, do any 881 * of the activation conditions refer to this location? 882 */ 883 if (nwam_value_get_string_array(conditionval, &conditions, 884 &numvalues) != NWAM_SUCCESS) { 885 nwam_value_free(conditionval); 886 if (errpropp != NULL) 887 *errpropp = NWAM_LOC_PROP_CONDITIONS; 888 return (NWAM_ENTITY_INVALID_VALUE); 889 } 890 if (nwam_loc_get_name(loch, &name) != NWAM_SUCCESS) { 891 nwam_value_free(conditionval); 892 return (NWAM_INVALID_ARG); 893 } 894 for (i = 0; i < numvalues; i++) { 895 char *object_name = NULL; 896 897 if (nwam_condition_string_to_condition(conditions[i], 898 &object_type, &condition, &object_name) 899 != NWAM_SUCCESS) { 900 if (errpropp != NULL) 901 *errpropp = NWAM_LOC_PROP_CONDITIONS; 902 free(name); 903 nwam_value_free(conditionval); 904 return (NWAM_ENTITY_INVALID_VALUE); 905 } 906 if (object_name != NULL && 907 object_type == NWAM_CONDITION_OBJECT_TYPE_LOC && 908 strcmp(object_name, name) == 0) { 909 if (errpropp != NULL) 910 *errpropp = NWAM_LOC_PROP_CONDITIONS; 911 free(name); 912 free(object_name); 913 nwam_value_free(conditionval); 914 return (NWAM_ENTITY_INVALID_VALUE); 915 } 916 free(object_name); 917 } 918 free(name); 919 nwam_value_free(conditionval); 920 } 921 922 /* validate namerservices */ 923 if (nwam_loc_get_prop_value(loch, NWAM_LOC_PROP_NAMESERVICES, 924 &nameservicesval) != NWAM_SUCCESS) { 925 if (errpropp != NULL) 926 *errpropp = NWAM_LOC_PROP_NAMESERVICES; 927 return (NWAM_ENTITY_MISSING_MEMBER); 928 } 929 err = nwam_loc_validate_all_nameservices(loch, nameservicesval, 930 errpropp); 931 nwam_value_free(nameservicesval); 932 if (err != NWAM_SUCCESS) 933 return (err); 934 935 return (nwam_validate(loc_prop_table, loch, errpropp)); 936 } 937 938 nwam_error_t 939 nwam_loc_validate_prop(nwam_loc_handle_t loch, const char *propname, 940 nwam_value_t value) 941 { 942 nwam_error_t err; 943 944 assert(loch != NULL); 945 946 if (strcmp(propname, NWAM_LOC_PROP_ACTIVATION_MODE) == 0) { 947 if ((err = nwam_loc_validate_activation_mode(loch, value)) 948 != NWAM_SUCCESS) 949 return (err); 950 } 951 952 return (nwam_validate_prop(loc_prop_table, loch, propname, value)); 953 } 954 955 nwam_error_t 956 nwam_loc_copy(nwam_loc_handle_t oldloch, const char *newname, 957 nwam_loc_handle_t *newlochp) 958 { 959 nwam_error_t err; 960 nwam_value_t val; 961 962 if ((err = nwam_copy(NWAM_LOC_CONF_FILE, oldloch, newname, newlochp)) 963 != NWAM_SUCCESS) 964 return (err); 965 966 /* If the activation-mode is system, change it to manual */ 967 if ((err = nwam_loc_get_prop_value(*newlochp, 968 NWAM_LOC_PROP_ACTIVATION_MODE, &val)) != NWAM_SUCCESS) 969 goto finish; 970 err = nwam_loc_validate_activation_mode(*newlochp, val); 971 nwam_value_free(val); 972 if (err != NWAM_SUCCESS) { 973 if ((err = nwam_value_create_uint64(NWAM_ACTIVATION_MODE_MANUAL, 974 &val)) != NWAM_SUCCESS) 975 goto finish; 976 err = nwam_set_prop_value((*newlochp)->nwh_data, 977 NWAM_LOC_PROP_ACTIVATION_MODE, val); 978 nwam_value_free(val); 979 if (err != NWAM_SUCCESS) 980 goto finish; 981 982 if ((err = nwam_value_create_boolean(B_FALSE, &val)) 983 != NWAM_SUCCESS) 984 goto finish; 985 err = nwam_set_prop_value((*newlochp)->nwh_data, 986 NWAM_LOC_PROP_ENABLED, val); 987 nwam_value_free(val); 988 if (err != NWAM_SUCCESS) 989 goto finish; 990 } 991 992 return (NWAM_SUCCESS); 993 994 finish: 995 nwam_loc_free(*newlochp); 996 *newlochp = NULL; 997 return (err); 998 } 999 1000 /* 1001 * Given a property, return expected property data type 1002 */ 1003 nwam_error_t 1004 nwam_loc_get_prop_type(const char *propname, nwam_value_type_t *typep) 1005 { 1006 return (nwam_get_prop_type(loc_prop_table, propname, typep)); 1007 } 1008 1009 nwam_error_t 1010 nwam_loc_prop_multivalued(const char *propname, boolean_t *multip) 1011 { 1012 return (nwam_prop_multivalued(loc_prop_table, propname, multip)); 1013 } 1014 1015 /* 1016 * Determine if the location has manual activation-mode or not. 1017 */ 1018 nwam_error_t 1019 nwam_loc_is_manual(nwam_loc_handle_t loch, boolean_t *manualp) 1020 { 1021 nwam_error_t err; 1022 nwam_value_t actval; 1023 uint64_t activation; 1024 1025 assert(loch != NULL); 1026 1027 if ((err = nwam_loc_get_prop_value(loch, NWAM_LOC_PROP_ACTIVATION_MODE, 1028 &actval)) != NWAM_SUCCESS) 1029 return (err); 1030 err = nwam_value_get_uint64(actval, &activation); 1031 nwam_value_free(actval); 1032 if (err != NWAM_SUCCESS) 1033 return (err); 1034 1035 if (activation == NWAM_ACTIVATION_MODE_MANUAL) 1036 *manualp = B_TRUE; 1037 else 1038 *manualp = B_FALSE; 1039 return (NWAM_SUCCESS); 1040 } 1041 1042 /* Determine if location is enabled or not */ 1043 static nwam_error_t 1044 nwam_loc_is_enabled(nwam_loc_handle_t loch, boolean_t *enabledp) 1045 { 1046 nwam_error_t err; 1047 nwam_value_t enabledval; 1048 1049 assert(loch != NULL); 1050 1051 if ((err = nwam_loc_get_prop_value(loch, NWAM_LOC_PROP_ENABLED, 1052 &enabledval)) != NWAM_SUCCESS) 1053 return (err); 1054 err = nwam_value_get_boolean(enabledval, enabledp); 1055 nwam_value_free(enabledval); 1056 return (err); 1057 } 1058 1059 /* 1060 * Callback to disable all locations other than one to enable, the handle 1061 * of which we pass in as an argument. If the argument is NULL, we disable 1062 * all locations. 1063 */ 1064 static int 1065 loc_set_enabled(nwam_loc_handle_t loch, void *data) 1066 { 1067 nwam_value_t enabledval; 1068 boolean_t curr_state, enabled = B_FALSE; 1069 nwam_loc_handle_t testloch = data; 1070 nwam_error_t err = NWAM_SUCCESS; 1071 1072 if (testloch != NULL) { 1073 char *name, *testname; 1074 1075 if (nwam_loc_get_name(loch, &name) == NWAM_SUCCESS && 1076 nwam_loc_get_name(testloch, &testname) == NWAM_SUCCESS && 1077 strcmp(name, testname) == 0) { 1078 /* We enable this location. */ 1079 enabled = B_TRUE; 1080 } 1081 } 1082 1083 /* If the enabled property is not changing, don't do anything. */ 1084 if (nwam_loc_is_enabled(loch, &curr_state) == NWAM_SUCCESS && 1085 curr_state == enabled) 1086 return (0); 1087 1088 if (nwam_value_create_boolean(enabled, &enabledval) != NWAM_SUCCESS) 1089 return (0); 1090 if (nwam_set_prop_value(loch->nwh_data, NWAM_LOC_PROP_ENABLED, 1091 enabledval) == NWAM_SUCCESS) 1092 err = nwam_loc_commit(loch, NWAM_FLAG_ENTITY_ENABLE); 1093 1094 nwam_value_free(enabledval); 1095 return (err); 1096 } 1097 1098 /* 1099 * Update the enabled property for this location (and for all others 1100 * if necessary. 1101 */ 1102 static int 1103 nwam_loc_update_enabled(nwam_loc_handle_t loch, boolean_t enabled) 1104 { 1105 nwam_error_t err; 1106 int cb_ret; 1107 1108 if (enabled) { 1109 /* 1110 * Disable all other locations that are manually enabled 1111 * and enable this one - a maximum of 1 location can be 1112 * enabled at once. 1113 */ 1114 err = nwam_walk_locs(loc_set_enabled, loch, 0, &cb_ret); 1115 if (err != NWAM_SUCCESS && err != NWAM_WALK_HALTED) 1116 cb_ret = err; 1117 } else { 1118 cb_ret = loc_set_enabled(loch, NULL); 1119 } 1120 return (cb_ret); 1121 } 1122 1123 nwam_error_t 1124 nwam_loc_enable(nwam_loc_handle_t loch) 1125 { 1126 nwam_error_t err; 1127 boolean_t enabled; 1128 1129 assert(loch != NULL); 1130 1131 /* Make sure location is not enabled */ 1132 if ((err = nwam_loc_is_enabled(loch, &enabled)) != NWAM_SUCCESS) 1133 return (err); 1134 if (enabled) 1135 return (NWAM_SUCCESS); 1136 1137 if ((err = nwam_loc_update_enabled(loch, B_TRUE)) != NWAM_SUCCESS) 1138 return (err); 1139 1140 err = nwam_enable(NULL, loch); 1141 1142 /* nwamd may not be running, that's okay. */ 1143 if (err == NWAM_ERROR_BIND) 1144 return (NWAM_SUCCESS); 1145 else 1146 return (err); 1147 } 1148 1149 nwam_error_t 1150 nwam_loc_disable(nwam_loc_handle_t loch) 1151 { 1152 nwam_error_t err; 1153 boolean_t enabled; 1154 1155 assert(loch != NULL); 1156 1157 /* Make sure location is enabled */ 1158 if ((err = nwam_loc_is_enabled(loch, &enabled)) != NWAM_SUCCESS) 1159 return (err); 1160 if (!enabled) 1161 return (NWAM_SUCCESS); 1162 1163 if ((err = nwam_loc_update_enabled(loch, B_FALSE)) != NWAM_SUCCESS) 1164 return (err); 1165 1166 err = nwam_disable(NULL, loch); 1167 1168 /* nwamd may not be running, that's okay. */ 1169 if (err == NWAM_ERROR_BIND) 1170 return (NWAM_SUCCESS); 1171 else 1172 return (err); 1173 } 1174 1175 nwam_error_t 1176 nwam_loc_get_default_proplist(const char ***prop_list, uint_t *numvaluesp) 1177 { 1178 return (nwam_get_default_proplist(loc_prop_table, 1179 NWAM_TYPE_ANY, NWAM_CLASS_ANY, prop_list, numvaluesp)); 1180 } 1181 1182 nwam_error_t 1183 nwam_loc_get_state(nwam_loc_handle_t loch, nwam_state_t *statep, 1184 nwam_aux_state_t *auxp) 1185 { 1186 return (nwam_get_state(NULL, loch, statep, auxp)); 1187 } 1188