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