2N/A/*
2N/A * CDDL HEADER START
2N/A *
2N/A * The contents of this file are subject to the terms of the
2N/A * Common Development and Distribution License (the "License").
2N/A * You may not use this file except in compliance with the License.
2N/A *
2N/A * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
2N/A * or http://www.opensolaris.org/os/licensing.
2N/A * See the License for the specific language governing permissions
2N/A * and limitations under the License.
2N/A *
2N/A * When distributing Covered Code, include this CDDL HEADER in each
2N/A * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
2N/A * If applicable, add the following below this CDDL HEADER, with the
2N/A * fields enclosed by brackets "[]" replaced with your own identifying
2N/A * information: Portions Copyright [yyyy] [name of copyright owner]
2N/A *
2N/A * CDDL HEADER END
2N/A */
2N/A
2N/A/*
2N/A * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
2N/A */
2N/A
2N/A#include <assert.h>
2N/A#include <ctype.h>
2N/A#include <dirent.h>
2N/A#include <libnetcfg.h>
2N/A#include <libscf.h>
2N/A#include <stdio.h>
2N/A#include <stdlib.h>
2N/A#include <strings.h>
2N/A#include <sys/param.h>
2N/A#include <sys/types.h>
2N/A#include <sys/stat.h>
2N/A#include <unistd.h>
2N/A
2N/A#include <libnwam.h>
2N/A#include "libnwam_impl.h"
2N/A#include <libnwam_priv.h>
2N/A
2N/A/*
2N/A * Functions to support creating, modifying, destroying, querying the
2N/A * state of and changing the state of location objects. Locations
2N/A * represent the configuration to be applied once basic network configuration
2N/A * has been established - name services, IPsec config, etc, and can be enabled
2N/A * either manually or conditionally for a combination of the set of
2N/A * available conditions (an IP address is present, an ENM is active etc).
2N/A */
2N/A
2N/A#define NSSWITCH_PREFIX "/etc/nsswitch."
2N/A
2N/Atypedef nwam_error_t (*nwam_loc_prop_validate_func_t)(nwam_value_t);
2N/A
2N/Astatic nwam_error_t valid_loc_activation_mode(nwam_value_t);
2N/Astatic nwam_error_t valid_loc_condition(nwam_value_t);
2N/Astatic nwam_error_t valid_nameservices(nwam_value_t);
2N/Astatic nwam_error_t valid_configsrc(nwam_value_t);
2N/Astatic nwam_error_t valid_resolv_sortlist(nwam_value_t);
2N/A
2N/Astruct nwam_prop_table_entry loc_prop_table_entries[] = {
2N/A {NWAM_LOC_PROP_ACTIVATION_MODE, NWAM_VALUE_TYPE_UINT64, B_FALSE, 1, 1,
2N/A valid_loc_activation_mode,
2N/A "specifies the location activation mode - valid values are:\n"
2N/A "\'manual\', \'conditional-any\' and \'conditional-all\'",
2N/A NWAM_TYPE_ANY, NWAM_CLASS_ANY},
2N/A {NWAM_LOC_PROP_CONDITIONS, NWAM_VALUE_TYPE_STRING, B_FALSE, 0,
2N/A NWAM_MAX_NUM_VALUES, valid_loc_condition,
2N/A "specifies the activation condition. Conditions are of the form:\n"
2N/A "ncp|ncu|enm name is|is-not active\n"
2N/A "ip-address is|is-not|is-in-range|is-not-in-range| 1.2.3.4[/24]\n"
2N/A "advertised-domain is|is-not|contains|does-not-contain string\n"
2N/A "system-domain is|is-not|contains|does-not-contain string\n"
2N/A "essid is|is-not|contains|does-not-contain string\n"
2N/A "bssid is|is-not string",
2N/A NWAM_TYPE_ANY, NWAM_CLASS_ANY},
2N/A {NWAM_LOC_PROP_ENABLED, NWAM_VALUE_TYPE_BOOLEAN, B_TRUE, 1, 1,
2N/A nwam_valid_boolean,
2N/A "specifies if location is to be enabled",
2N/A NWAM_TYPE_ANY, NWAM_CLASS_ANY},
2N/A {NWAM_LOC_PROP_NAMESERVICES, NWAM_VALUE_TYPE_UINT64, B_FALSE, 1,
2N/A NWAM_MAX_NUM_VALUES, valid_nameservices,
2N/A "specifies name service(s) to be used - valid values are:\n"
2N/A "\'files\', \'dns\', \'nis\', and \'ldap\'",
2N/A NWAM_TYPE_ANY, NWAM_CLASS_ANY},
2N/A {NWAM_LOC_PROP_NAMESERVICES_CONFIG_FILE, NWAM_VALUE_TYPE_STRING,
2N/A B_FALSE, 0, 1, nwam_valid_file,
2N/A "specifies path to configuration file for name services switch "
2N/A "for this location - see nsswitch.conf(4)",
2N/A NWAM_TYPE_ANY, NWAM_CLASS_ANY},
2N/A {NWAM_LOC_PROP_DNS_NAMESERVICE_CONFIGSRC, NWAM_VALUE_TYPE_UINT64,
2N/A B_FALSE, 0, NWAM_MAX_NUM_VALUES, valid_configsrc,
2N/A "specifies sources of DNS configuration parameters - valid values "
2N/A "are:\n\'dhcp\', or \'manual\'",
2N/A NWAM_TYPE_ANY, NWAM_CLASS_ANY},
2N/A {NWAM_LOC_PROP_DNS_NAMESERVICE_DOMAIN, NWAM_VALUE_TYPE_STRING, B_FALSE,
2N/A 0, 1, nwam_valid_domain,
2N/A "specifies DNS domain name to be set for this location",
2N/A NWAM_TYPE_ANY, NWAM_CLASS_ANY},
2N/A {NWAM_LOC_PROP_DNS_NAMESERVICE_SERVERS, NWAM_VALUE_TYPE_STRING, B_FALSE,
2N/A 0, NWAM_MAX_NUM_VALUES, nwam_valid_host_any,
2N/A "specifies DNS server host address(es)",
2N/A NWAM_TYPE_ANY, NWAM_CLASS_ANY},
2N/A {NWAM_LOC_PROP_DNS_NAMESERVICE_SEARCH, NWAM_VALUE_TYPE_STRING, B_FALSE,
2N/A 0, NWAM_MAX_NUM_VALUES, nwam_valid_domain,
2N/A "specifies DNS search list for host name lookup",
2N/A NWAM_TYPE_ANY, NWAM_CLASS_ANY},
2N/A {NWAM_LOC_PROP_DNS_NAMESERVICE_SORTLIST, NWAM_VALUE_TYPE_STRING,
2N/A B_FALSE, 0, NWAM_MAX_NUM_VALUES, valid_resolv_sortlist,
2N/A "specifies IP address and optional netmask pairs (separated by "
2N/A "slashes) which allows addresses returned by gethostbyname() "
2N/A "to be sorted (see resolv.conf(4))",
2N/A NWAM_TYPE_ANY, NWAM_CLASS_ANY},
2N/A {NWAM_LOC_PROP_DNS_NAMESERVICE_OPTIONS, NWAM_VALUE_TYPE_STRING, B_FALSE,
2N/A 0, NWAM_MAX_NUM_VALUES, NULL,
2N/A "specifies internal resolver variables that are to be modified "
2N/A "see (resolv.conf(4))",
2N/A NWAM_TYPE_ANY, NWAM_CLASS_ANY},
2N/A {NWAM_LOC_PROP_NIS_NAMESERVICE_CONFIGSRC, NWAM_VALUE_TYPE_UINT64,
2N/A B_FALSE, 0, NWAM_MAX_NUM_VALUES, valid_configsrc,
2N/A "specifies sources of NIS configuration parameters - valid values "
2N/A "are:\n\'dhcp\', or \'manual\'",
2N/A NWAM_TYPE_ANY, NWAM_CLASS_ANY},
2N/A {NWAM_LOC_PROP_NIS_NAMESERVICE_SERVERS, NWAM_VALUE_TYPE_STRING, B_FALSE,
2N/A 0, NWAM_MAX_NUM_VALUES, nwam_valid_host_any,
2N/A "specifies NIS server host address(es)",
2N/A NWAM_TYPE_ANY, NWAM_CLASS_ANY},
2N/A {NWAM_LOC_PROP_LDAP_NAMESERVICE_CONFIGSRC, NWAM_VALUE_TYPE_UINT64,
2N/A B_FALSE, 0, NWAM_MAX_NUM_VALUES, valid_configsrc,
2N/A "specifies sources of NIS configuration parameters - currently, "
2N/A "the only valid value is \'manual\'",
2N/A NWAM_TYPE_ANY, NWAM_CLASS_ANY},
2N/A {NWAM_LOC_PROP_LDAP_NAMESERVICE_SERVERS, NWAM_VALUE_TYPE_STRING,
2N/A B_FALSE, 0, NWAM_MAX_NUM_VALUES, nwam_valid_host_or_domain,
2N/A "specifies LDAP server host address(es)",
2N/A NWAM_TYPE_ANY, NWAM_CLASS_ANY},
2N/A {NWAM_LOC_PROP_DEFAULT_DOMAIN, NWAM_VALUE_TYPE_STRING, B_FALSE, 0, 1,
2N/A nwam_valid_domain,
2N/A "specifies the domainname(1M) to be set for this location",
2N/A NWAM_TYPE_ANY, NWAM_CLASS_ANY},
2N/A {NWAM_LOC_PROP_NFSV4_DOMAIN, NWAM_VALUE_TYPE_STRING, B_FALSE, 0, 1,
2N/A nwam_valid_domain,
2N/A "specifies an NFSv4 domain for this location",
2N/A NWAM_TYPE_ANY, NWAM_CLASS_ANY},
2N/A {NWAM_LOC_PROP_IPFILTER_CONFIG_FILE, NWAM_VALUE_TYPE_STRING, B_FALSE,
2N/A 0, 1, nwam_valid_file,
2N/A "specifies an absolute path to an ipf.conf(4) file for this "
2N/A "location",
2N/A NWAM_TYPE_ANY, NWAM_CLASS_ANY},
2N/A {NWAM_LOC_PROP_IPFILTER_V6_CONFIG_FILE, NWAM_VALUE_TYPE_STRING,
2N/A B_FALSE, 0, 1, nwam_valid_file,
2N/A "specifies an absolute path to an ipf6.conf file for this "
2N/A "location",
2N/A NWAM_TYPE_ANY, NWAM_CLASS_ANY},
2N/A {NWAM_LOC_PROP_IPNAT_CONFIG_FILE, NWAM_VALUE_TYPE_STRING, B_FALSE, 0,
2N/A 1, nwam_valid_file,
2N/A "specifies an absolute path to an ipnat.conf(4) file for this "
2N/A "location",
2N/A NWAM_TYPE_ANY, NWAM_CLASS_ANY},
2N/A {NWAM_LOC_PROP_IPPOOL_CONFIG_FILE, NWAM_VALUE_TYPE_STRING, B_FALSE, 0,
2N/A 1, nwam_valid_file,
2N/A "specifies an absolute path to an ippool.conf(4) file for this "
2N/A "location",
2N/A NWAM_TYPE_ANY, NWAM_CLASS_ANY},
2N/A {NWAM_LOC_PROP_IKE_CONFIG_FILE, NWAM_VALUE_TYPE_STRING, B_FALSE, 0, 1,
2N/A nwam_valid_file,
2N/A "specifies an absolute path to an ike config file "
2N/A "(see ike.config(4))",
2N/A NWAM_TYPE_ANY, NWAM_CLASS_ANY},
2N/A {NWAM_LOC_PROP_IPSECPOLICY_CONFIG_FILE, NWAM_VALUE_TYPE_STRING,
2N/A B_FALSE, 0, 1, nwam_valid_file,
2N/A "specifies an absolute path to an IPsec policy configuration file "
2N/A "(see ipsecconf(1M)",
2N/A NWAM_TYPE_ANY, NWAM_CLASS_ANY},
2N/A};
2N/A
2N/A#define NWAM_NUM_LOC_PROPS (sizeof (loc_prop_table_entries) / \
2N/A sizeof (*loc_prop_table_entries))
2N/A
2N/Astruct nwam_prop_table loc_prop_table =
2N/A { NWAM_NUM_LOC_PROPS, loc_prop_table_entries };
2N/A
2N/Astatic uint64_t
2N/Anwam_loc_activation_to_flag(nwam_activation_mode_t activation)
2N/A{
2N/A switch (activation) {
2N/A case NWAM_ACTIVATION_MODE_MANUAL:
2N/A return (NWAM_FLAG_ACTIVATION_MODE_MANUAL);
2N/A case NWAM_ACTIVATION_MODE_SYSTEM:
2N/A return (NWAM_FLAG_ACTIVATION_MODE_SYSTEM);
2N/A case NWAM_ACTIVATION_MODE_CONDITIONAL_ANY:
2N/A return (NWAM_FLAG_ACTIVATION_MODE_CONDITIONAL_ANY);
2N/A case NWAM_ACTIVATION_MODE_CONDITIONAL_ALL:
2N/A return (NWAM_FLAG_ACTIVATION_MODE_CONDITIONAL_ALL);
2N/A default:
2N/A return (0);
2N/A }
2N/A}
2N/A
2N/Anwam_error_t
2N/Anwam_loc_read(const char *name, uint64_t flags, nwam_loc_handle_t *lochp)
2N/A{
2N/A return (nwam_read(NWAM_OBJECT_TYPE_LOC, NWAM_LOC_CONF_FILE, name, flags,
2N/A lochp));
2N/A}
2N/A
2N/Anwam_error_t
2N/Anwam_loc_create(const char *name, nwam_loc_handle_t *lochp)
2N/A{
2N/A nwam_error_t err;
2N/A nwam_value_t val = NULL;
2N/A char *nsswitch = NULL;
2N/A
2N/A assert(lochp != NULL && name != NULL);
2N/A
2N/A if ((err = nwam_create(NWAM_OBJECT_TYPE_LOC, NWAM_LOC_CONF_FILE, name,
2N/A lochp)) != NWAM_SUCCESS)
2N/A return (err);
2N/A
2N/A /* NWAM_LOC_PROP_ACTIVATION_MODE is mandatory */
2N/A if ((err = nwam_value_create_uint64(NWAM_ACTIVATION_MODE_MANUAL, &val))
2N/A != NWAM_SUCCESS)
2N/A goto finish;
2N/A if ((err = nwam_set_prop_value((*lochp)->nwh_data,
2N/A NWAM_LOC_PROP_ACTIVATION_MODE, val)) != NWAM_SUCCESS)
2N/A goto finish;
2N/A nwam_value_free(val);
2N/A val = NULL;
2N/A
2N/A /*
2N/A * NWAM_LOC_PROP_ENABLED defaults to false.
2N/A */
2N/A if ((err = nwam_value_create_boolean(B_FALSE, &val)) != NWAM_SUCCESS)
2N/A goto finish;
2N/A if ((err = nwam_set_prop_value((*lochp)->nwh_data,
2N/A NWAM_LOC_PROP_ENABLED, val)) != NWAM_SUCCESS)
2N/A goto finish;
2N/A nwam_value_free(val);
2N/A val = NULL;
2N/A
2N/A /*
2N/A * Initialize name service properties: use DNS, configured
2N/A * via DHCP, with default nsswitch (/etc/nsswitch.dns).
2N/A */
2N/A if ((err = nwam_value_create_uint64(NWAM_NAMESERVICES_DNS, &val)) !=
2N/A NWAM_SUCCESS)
2N/A goto finish;
2N/A if ((err = nwam_set_prop_value((*lochp)->nwh_data,
2N/A NWAM_LOC_PROP_NAMESERVICES, val)) != NWAM_SUCCESS)
2N/A goto finish;
2N/A nwam_value_free(val);
2N/A val = NULL;
2N/A
2N/A if ((err = nwam_value_create_uint64(NWAM_CONFIGSRC_DHCP, &val)) !=
2N/A NWAM_SUCCESS)
2N/A goto finish;
2N/A if ((err = nwam_set_prop_value((*lochp)->nwh_data,
2N/A NWAM_LOC_PROP_DNS_NAMESERVICE_CONFIGSRC, val)) != NWAM_SUCCESS)
2N/A goto finish;
2N/A nwam_value_free(val);
2N/A val = NULL;
2N/A
2N/A /* concatenate these two strings */
2N/A nsswitch = strdup(NSSWITCH_PREFIX NWAM_NAMESERVICES_DNS_STRING);
2N/A if (nsswitch == NULL) {
2N/A err = NWAM_NO_MEMORY;
2N/A goto finish;
2N/A }
2N/A if ((err = nwam_value_create_string(nsswitch, &val)) != NWAM_SUCCESS)
2N/A goto finish;
2N/A err = nwam_set_prop_value((*lochp)->nwh_data,
2N/A NWAM_LOC_PROP_NAMESERVICES_CONFIG_FILE, val);
2N/A
2N/Afinish:
2N/A if (nsswitch != NULL)
2N/A free(nsswitch);
2N/A if (val != NULL)
2N/A nwam_value_free(val);
2N/A if (err != NWAM_SUCCESS) {
2N/A nwam_loc_free(*lochp);
2N/A *lochp = NULL;
2N/A }
2N/A return (err);
2N/A}
2N/A
2N/Anwam_error_t
2N/Anwam_loc_get_name(nwam_loc_handle_t loch, char **namep)
2N/A{
2N/A return (nwam_get_name(loch, namep));
2N/A}
2N/A
2N/Anwam_error_t
2N/Anwam_loc_set_name(nwam_loc_handle_t loch, const char *name)
2N/A{
2N/A return (nwam_set_name(loch, name));
2N/A}
2N/A
2N/Aboolean_t
2N/Anwam_loc_can_set_name(nwam_loc_handle_t loch)
2N/A{
2N/A assert(loch != NULL);
2N/A
2N/A return (!loch->nwh_committed);
2N/A}
2N/A
2N/Astatic int
2N/Aloc_selectcb(nvlist_t *idp, nvlist_t *objp, uint64_t flags, void **cbobj)
2N/A{
2N/A nwam_loc_handle_t loch;
2N/A char *locname;
2N/A uint64_t activation, actflag, walkfilter;
2N/A nwam_value_t activationval;
2N/A nwam_error_t err;
2N/A
2N/A if ((err = nwam_lists_to_handle(idp, objp, NWAM_OBJECT_TYPE_LOC, &loch))
2N/A != NWAM_SUCCESS)
2N/A return (err);
2N/A
2N/A /* Skip the Legacy location in all cases */
2N/A if (nwam_loc_get_name(loch, &locname) != NWAM_SUCCESS) {
2N/A nwam_free(loch, B_FALSE);
2N/A return (NWAM_INVALID_ARG);
2N/A }
2N/A if (strcmp(locname, NWAM_LOC_NAME_LEGACY) == 0) {
2N/A free(locname);
2N/A nwam_free(loch, B_FALSE);
2N/A return (NWAM_INVALID_ARG);
2N/A }
2N/A free(locname);
2N/A
2N/A /*
2N/A * Get a bitmapped flag value corresponding to this loc's
2N/A * activation.
2N/A */
2N/A if (nwam_loc_get_prop_value(loch, NWAM_LOC_PROP_ACTIVATION_MODE,
2N/A &activationval) != NWAM_SUCCESS) {
2N/A nwam_free(loch, B_FALSE);
2N/A return (NWAM_INVALID_ARG);
2N/A }
2N/A if (nwam_value_get_uint64(activationval, &activation) != NWAM_SUCCESS) {
2N/A nwam_value_free(activationval);
2N/A nwam_free(loch, B_FALSE);
2N/A return (NWAM_INVALID_ARG);
2N/A }
2N/A
2N/A actflag = nwam_loc_activation_to_flag(activation);
2N/A nwam_value_free(activationval);
2N/A if ((walkfilter = (flags & NWAM_WALK_FILTER_MASK)) == 0)
2N/A walkfilter = NWAM_FLAG_ACTIVATION_MODE_ALL;
2N/A if (actflag & walkfilter) {
2N/A *cbobj = loch;
2N/A return (NWAM_SUCCESS);
2N/A }
2N/A
2N/A nwam_free(loch, B_FALSE);
2N/A return (NWAM_INVALID_ARG);
2N/A}
2N/A
2N/Anwam_error_t
2N/Anwam_walk_locs(int(*cb)(nwam_loc_handle_t, void *), void *data, uint64_t flags,
2N/A int *retp)
2N/A{
2N/A netcfg_walkcb_t *nccb = (netcfg_walkcb_t *)cb;
2N/A
2N/A nwam_error_t err = nwam_valid_flags(flags,
2N/A NWAM_FLAG_ACTIVATION_MODE_ALL);
2N/A
2N/A if (err != NWAM_SUCCESS)
2N/A return (err);
2N/A
2N/A return (nwam_walk(NWAM_LOC_CONF_FILE, nccb, data, flags, retp,
2N/A loc_selectcb));
2N/A}
2N/A
2N/Avoid
2N/Anwam_loc_free(nwam_loc_handle_t loch)
2N/A{
2N/A nwam_free(loch, B_TRUE);
2N/A}
2N/A
2N/A/*
2N/A * Returns B_TRUE if the DefaultFixed location is being modified and the UID
2N/A * is netadm. This is to ensure that the net-loc script running as the netadm
2N/A * user can use netcfg to modify the DefaultFixed location.
2N/A */
2N/Astatic boolean_t
2N/Adefault_fixed_override(const char *name)
2N/A{
2N/A return (strcasecmp(name, NWAM_LOC_NAME_DEFAULT_FIXED) == 0 &&
2N/A getuid() == UID_NETADM);
2N/A}
2N/A
2N/Anwam_error_t
2N/Anwam_loc_delete_prop(nwam_loc_handle_t loch, const char *propname,
2N/A uint64_t flags)
2N/A{
2N/A nwam_error_t err;
2N/A boolean_t ro, fixed;
2N/A void *olddata;
2N/A
2N/A assert(loch != NULL && propname != NULL);
2N/A
2N/A if (default_fixed_override(loch->nwh_name))
2N/A flags |= NWAM_FLAG_OVERRIDE_READ_ONLY;
2N/A
2N/A if ((err = nwam_loc_prop_read_only(propname, &ro)) != NWAM_SUCCESS)
2N/A return (err);
2N/A if (ro && !nwam_override_readonly(flags))
2N/A return (NWAM_ENTITY_READ_ONLY);
2N/A
2N/A /*
2N/A * A 'fixed' location cannot have properties deleted unless the caller
2N/A * is the special netadm UID and the DefaultFixed location's property
2N/A * is being cleared.
2N/A */
2N/A if ((err = nwam_loc_is_fixed(loch, &fixed)) == NWAM_SUCCESS) {
2N/A if (fixed && !nwam_override_readonly(flags))
2N/A return (NWAM_ENTITY_FIXED);
2N/A }
2N/A
2N/A /*
2N/A * Duplicate data, remove property and validate. If validation
2N/A * fails, revert to data duplicated prior to remove.
2N/A */
2N/A if ((err = nwam_dup_object_list(loch->nwh_data, &olddata))
2N/A != NWAM_SUCCESS)
2N/A return (err);
2N/A if ((err = nwam_delete_prop(loch->nwh_data, propname))
2N/A != NWAM_SUCCESS) {
2N/A nwam_free_object_list(loch->nwh_data);
2N/A loch->nwh_data = olddata;
2N/A return (err);
2N/A }
2N/A if ((err = nwam_loc_validate(loch, NULL)) != NWAM_SUCCESS) {
2N/A nwam_free_object_list(loch->nwh_data);
2N/A loch->nwh_data = olddata;
2N/A return (err);
2N/A }
2N/A nwam_free_object_list(olddata);
2N/A
2N/A return (NWAM_SUCCESS);
2N/A}
2N/A
2N/Anwam_error_t
2N/Anwam_loc_set_prop_value(nwam_loc_handle_t loch, const char *propname,
2N/A nwam_value_t value, uint64_t flags)
2N/A{
2N/A nwam_error_t err;
2N/A boolean_t ro, fixed;
2N/A
2N/A assert(loch != NULL && propname != NULL && value != NULL);
2N/A
2N/A if (default_fixed_override(loch->nwh_name))
2N/A flags |= NWAM_FLAG_OVERRIDE_READ_ONLY;
2N/A
2N/A if ((err = nwam_loc_validate_prop(loch, propname, value))
2N/A != NWAM_SUCCESS ||
2N/A (err = nwam_loc_prop_read_only(propname, &ro)) != NWAM_SUCCESS)
2N/A return (err);
2N/A if (ro && !nwam_override_readonly(flags))
2N/A return (NWAM_ENTITY_READ_ONLY);
2N/A
2N/A /*
2N/A * A 'fixed' location cannot have properties set, unless the caller is
2N/A * the special netadm UID and the DefaultFixed location's property is
2N/A * being set.
2N/A */
2N/A if ((err = nwam_loc_is_fixed(loch, &fixed)) == NWAM_SUCCESS) {
2N/A if (fixed && !nwam_override_readonly(flags))
2N/A return (NWAM_ENTITY_FIXED);
2N/A }
2N/A
2N/A return (nwam_set_prop_value(loch->nwh_data, propname, value));
2N/A}
2N/A
2N/Anwam_error_t
2N/Anwam_loc_get_prop_value(nwam_loc_handle_t loch, const char *propname,
2N/A nwam_value_t *valuep)
2N/A{
2N/A assert(loch != NULL);
2N/A
2N/A return (nwam_get_prop_value(loch->nwh_data, propname, valuep));
2N/A}
2N/A
2N/Anwam_error_t
2N/Anwam_loc_walk_props(nwam_loc_handle_t loch,
2N/A int (*cb)(const char *, nwam_value_t, void *),
2N/A void *data, uint64_t flags, int *retp)
2N/A{
2N/A return (nwam_walk_props(loch, cb, data, flags, retp));
2N/A}
2N/A
2N/Anwam_error_t
2N/Anwam_loc_commit(nwam_loc_handle_t loch, uint64_t flags)
2N/A{
2N/A nwam_error_t err;
2N/A
2N/A assert(loch != NULL && loch->nwh_data != NULL);
2N/A
2N/A if (default_fixed_override(loch->nwh_name))
2N/A flags |= NWAM_FLAG_OVERRIDE_READ_ONLY;
2N/A
2N/A if ((err = nwam_loc_validate(loch, NULL)) != NWAM_SUCCESS)
2N/A return (err);
2N/A
2N/A return (nwam_commit(NWAM_LOC_CONF_FILE, loch, flags));
2N/A}
2N/A
2N/Astatic void
2N/Aremove_loc_dir(const char *name)
2N/A{
2N/A DIR *dirp = NULL;
2N/A struct dirent *dp;
2N/A char dirname[MAXPATHLEN], filename[MAXPATHLEN];
2N/A
2N/A /*
2N/A * Open the /etc/nwam/loc/<name>/ directory and remove all files in
2N/A * it. We know that the directory does not have sub-directories.
2N/A */
2N/A (void) snprintf(dirname, sizeof (dirname), "%sloc/%s", NWAM_CONF_DIR,
2N/A name);
2N/A if ((dirp = opendir(dirname)) == NULL)
2N/A return;
2N/A while ((dp = readdir(dirp)) != NULL) {
2N/A (void) snprintf(filename, sizeof (filename), "%s/%s", dirname,
2N/A dp->d_name);
2N/A (void) unlink(filename);
2N/A }
2N/A (void) closedir(dirp);
2N/A
2N/A /* Finally, remove the directory itself */
2N/A (void) rmdir(dirname);
2N/A}
2N/A
2N/Anwam_error_t
2N/Anwam_loc_destroy(nwam_loc_handle_t loch, uint64_t flags)
2N/A{
2N/A boolean_t fixed;
2N/A
2N/A assert(loch != NULL);
2N/A
2N/A if (default_fixed_override(loch->nwh_name))
2N/A flags |= NWAM_FLAG_OVERRIDE_READ_ONLY;
2N/A
2N/A /*
2N/A * Pre-defined locations Automatic and NoNet are not destroyable and
2N/A * DefaultFixed and Legacy are destroyable by netadm only. These
2N/A * locations are determined by the NWAM_LOC_NAME_PRE_DEFINED macro.
2N/A */
2N/A if (NWAM_LOC_NAME_PRE_DEFINED(loch->nwh_name)) {
2N/A if (strcmp(loch->nwh_name, NWAM_LOC_NAME_LEGACY) == 0 ||
2N/A strcmp(loch->nwh_name, NWAM_LOC_NAME_DEFAULT_FIXED) == 0) {
2N/A if (!nwam_override_readonly(flags))
2N/A return (NWAM_ENTITY_NOT_DESTROYABLE);
2N/A } else {
2N/A return (NWAM_ENTITY_NOT_DESTROYABLE);
2N/A }
2N/A }
2N/A
2N/A /*
2N/A * For fixed locations, remove the /etc/nwam/loc/<name>/ directory
2N/A * containing the config files.
2N/A */
2N/A if (nwam_loc_is_fixed(loch, &fixed) == NWAM_SUCCESS && fixed)
2N/A remove_loc_dir(loch->nwh_name);
2N/A
2N/A return (nwam_destroy(NWAM_LOC_CONF_FILE, loch, flags));
2N/A}
2N/A
2N/Anwam_error_t
2N/Anwam_loc_get_prop_description(const char *propname, const char **descriptionp)
2N/A{
2N/A return (nwam_get_prop_description(loc_prop_table, propname,
2N/A descriptionp));
2N/A}
2N/A
2N/Anwam_error_t
2N/Anwam_loc_prop_read_only(const char *propname, boolean_t *readp)
2N/A{
2N/A return (nwam_prop_read_only(loc_prop_table, propname, readp));
2N/A}
2N/A
2N/Anwam_error_t
2N/Anwam_loc_is_fixed(nwam_loc_handle_t loch, boolean_t *fixedp)
2N/A{
2N/A assert(loch != NULL);
2N/A
2N/A /* DefaultFixed location is the only fixed location */
2N/A if (strcasecmp(loch->nwh_name, NWAM_LOC_NAME_DEFAULT_FIXED) == 0)
2N/A *fixedp = B_TRUE;
2N/A else
2N/A *fixedp = B_FALSE;
2N/A return (NWAM_SUCCESS);
2N/A}
2N/A
2N/Astatic nwam_error_t
2N/Avalid_loc_activation_mode(nwam_value_t value)
2N/A{
2N/A uint64_t activation_mode;
2N/A
2N/A if (nwam_value_get_uint64(value, &activation_mode) != NWAM_SUCCESS)
2N/A return (NWAM_ENTITY_INVALID_VALUE);
2N/A
2N/A switch (activation_mode) {
2N/A case NWAM_ACTIVATION_MODE_MANUAL:
2N/A case NWAM_ACTIVATION_MODE_SYSTEM:
2N/A case NWAM_ACTIVATION_MODE_CONDITIONAL_ANY:
2N/A case NWAM_ACTIVATION_MODE_CONDITIONAL_ALL:
2N/A return (NWAM_SUCCESS);
2N/A }
2N/A return (NWAM_ENTITY_INVALID_VALUE);
2N/A}
2N/A
2N/A/*
2N/A * Identical to nwam_valid_condition(), except locations cannot specify other
2N/A * location's activation as a condition, e.g. loc2 cannot specify
2N/A * "loc1 is active" since only one location is active at a time, and
2N/A * as a consequence the condition is unsatisfiable.
2N/A */
2N/Anwam_error_t
2N/Avalid_loc_condition(nwam_value_t value)
2N/A{
2N/A char **conditions;
2N/A uint_t i, numvalues;
2N/A nwam_condition_object_type_t object_type;
2N/A nwam_condition_t condition;
2N/A
2N/A if (nwam_value_get_string_array(value, &conditions, &numvalues)
2N/A != NWAM_SUCCESS)
2N/A return (NWAM_ENTITY_INVALID_VALUE);
2N/A
2N/A for (i = 0; i < numvalues; i++) {
2N/A char *object_name = NULL;
2N/A
2N/A if (nwam_condition_string_to_condition(conditions[i],
2N/A &object_type, &condition, &object_name) != NWAM_SUCCESS)
2N/A return (NWAM_ENTITY_INVALID_VALUE);
2N/A if (object_type == NWAM_CONDITION_OBJECT_TYPE_LOC &&
2N/A condition == NWAM_CONDITION_IS) {
2N/A free(object_name);
2N/A return (NWAM_ENTITY_INVALID_VALUE);
2N/A }
2N/A if (object_name != NULL)
2N/A free(object_name);
2N/A }
2N/A return (NWAM_SUCCESS);
2N/A}
2N/A
2N/Astatic nwam_error_t
2N/Avalid_nameservices(nwam_value_t value)
2N/A{
2N/A uint64_t *nameservices;
2N/A uint_t i, numvalues;
2N/A
2N/A if (nwam_value_get_uint64_array(value, &nameservices, &numvalues)
2N/A != NWAM_SUCCESS)
2N/A return (NWAM_ENTITY_INVALID_VALUE);
2N/A
2N/A for (i = 0; i < numvalues; i++) {
2N/A if (nameservices[i] > NWAM_NAMESERVICES_LDAP)
2N/A return (NWAM_ENTITY_INVALID_VALUE);
2N/A }
2N/A return (NWAM_SUCCESS);
2N/A}
2N/A
2N/Astatic nwam_error_t
2N/Avalid_configsrc(nwam_value_t value)
2N/A{
2N/A uint64_t *configsrcs;
2N/A uint_t i, numvalues;
2N/A
2N/A if (nwam_value_get_uint64_array(value, &configsrcs, &numvalues)
2N/A != NWAM_SUCCESS)
2N/A return (NWAM_ENTITY_INVALID_VALUE);
2N/A
2N/A for (i = 0; i < numvalues; i++) {
2N/A if (configsrcs[i] > NWAM_CONFIGSRC_DHCP)
2N/A return (NWAM_ENTITY_INVALID_VALUE);
2N/A }
2N/A return (NWAM_SUCCESS);
2N/A}
2N/A
2N/Astatic nwam_error_t
2N/Avalid_resolv_sortlist(nwam_value_t value)
2N/A{
2N/A char **sortvalues, *copy, *addr = NULL;
2N/A uint_t i, numvalues;
2N/A nwam_value_t val = NULL;
2N/A nwam_error_t err;
2N/A
2N/A if (nwam_value_get_string_array(value, &sortvalues, &numvalues)
2N/A != NWAM_SUCCESS)
2N/A return (NWAM_ENTITY_INVALID_VALUE);
2N/A
2N/A for (i = 0; i < numvalues; i++) {
2N/A copy = strdup(sortvalues[i]);
2N/A
2N/A /* may include netmask, which is separated by a slash */
2N/A addr = strsep(&copy, "/");
2N/A
2N/A if ((err = nwam_value_create_string(addr, &val))
2N/A != NWAM_SUCCESS)
2N/A goto fail;
2N/A if ((err = nwam_valid_host_any(val)) != NWAM_SUCCESS)
2N/A goto fail;
2N/A nwam_value_free(val);
2N/A val = NULL;
2N/A
2N/A /* "copy" now points to the netmask, if any */
2N/A if (copy != NULL) {
2N/A if ((err = nwam_value_create_string(copy, &val))
2N/A != NWAM_SUCCESS)
2N/A goto fail;
2N/A if ((err = nwam_valid_host_any(val)) != NWAM_SUCCESS)
2N/A goto fail;
2N/A nwam_value_free(val);
2N/A val = NULL;
2N/A }
2N/A free(addr);
2N/A }
2N/A return (NWAM_SUCCESS);
2N/A
2N/Afail:
2N/A free(addr);
2N/A nwam_value_free(val);
2N/A return (err);
2N/A}
2N/A
2N/A/*
2N/A * Validates that the activation-mode is
2N/A * - system for Automatic and NoNet locations
2N/A * - not system for all other reactive locations
2N/A * - anything for all fixed locations (those automatically created by nwamd
2N/A * are system; the user may also create them with manual or conditional)
2N/A */
2N/Astatic nwam_error_t
2N/Anwam_loc_validate_activation_mode(nwam_loc_handle_t loch, nwam_value_t actval)
2N/A{
2N/A nwam_error_t err;
2N/A uint64_t activation;
2N/A boolean_t is_fixed;
2N/A
2N/A if ((err = nwam_value_get_uint64(actval, &activation))
2N/A != NWAM_SUCCESS ||
2N/A (err = nwam_loc_is_fixed(loch, &is_fixed)) != NWAM_SUCCESS)
2N/A return (err);
2N/A
2N/A if (is_fixed)
2N/A return (NWAM_SUCCESS);
2N/A
2N/A if (NWAM_LOC_NAME_PRE_DEFINED(loch->nwh_name)) {
2N/A if (activation != NWAM_ACTIVATION_MODE_SYSTEM)
2N/A return (NWAM_ENTITY_INVALID_VALUE);
2N/A } else {
2N/A if (activation == NWAM_ACTIVATION_MODE_SYSTEM)
2N/A return (NWAM_ENTITY_INVALID_VALUE);
2N/A }
2N/A return (NWAM_SUCCESS);
2N/A}
2N/A
2N/A/*
2N/A * Helper function to validate one nameservice, used by
2N/A * nwam_loc_validate_all_nameservices().
2N/A *
2N/A * requiredprop denotes the property that is mandatory when the
2N/A * configsrcprop is manual. errpropp is used to return the invalid
2N/A * property.
2N/A */
2N/Astatic nwam_error_t
2N/Anwam_loc_validate_one_nameservice(nwam_loc_handle_t loch,
2N/A const char *configsrcprop, const char *requiredprop, const char **errpropp)
2N/A{
2N/A nwam_value_t configsrcval, requiredval;
2N/A uint64_t *configsrcs;
2N/A uint_t i, numvalues;
2N/A
2N/A if (nwam_loc_get_prop_value(loch, configsrcprop, &configsrcval)
2N/A != NWAM_SUCCESS) {
2N/A if (errpropp != NULL)
2N/A *errpropp = configsrcprop;
2N/A return (NWAM_ENTITY_MISSING_MEMBER);
2N/A }
2N/A
2N/A if (nwam_value_get_uint64_array(configsrcval, &configsrcs, &numvalues)
2N/A != NWAM_SUCCESS) {
2N/A if (errpropp != NULL)
2N/A *errpropp = configsrcprop;
2N/A nwam_value_free(configsrcval);
2N/A return (NWAM_ENTITY_NO_VALUE);
2N/A }
2N/A
2N/A /* If -configsrc is manual, requiredprop is required */
2N/A for (i = 0; i < numvalues; i++) {
2N/A if (configsrcs[i] == NWAM_CONFIGSRC_MANUAL) {
2N/A if (nwam_loc_get_prop_value(loch, requiredprop,
2N/A &requiredval) != NWAM_SUCCESS) {
2N/A if (errpropp != NULL)
2N/A *errpropp = requiredprop;
2N/A return (NWAM_ENTITY_MISSING_MEMBER);
2N/A }
2N/A nwam_value_free(requiredval);
2N/A }
2N/A }
2N/A nwam_value_free(configsrcval);
2N/A
2N/A return (NWAM_SUCCESS);
2N/A}
2N/A
2N/A/*
2N/A * Helper function to validate LDAP nameservice, used by
2N/A * nwam_loc_validate_all_nameservices(). Separated because LDAP must be
2N/A * configured manually only and both default-domain and -servers are required.
2N/A */
2N/Astatic nwam_error_t
2N/Anwam_loc_validate_ldap_nameservice(nwam_loc_handle_t loch,
2N/A const char **errpropp)
2N/A{
2N/A nwam_value_t val;
2N/A uint64_t *configsrcs;
2N/A uint_t i, numvalues;
2N/A
2N/A if (nwam_loc_get_prop_value(loch,
2N/A NWAM_LOC_PROP_LDAP_NAMESERVICE_CONFIGSRC, &val) != NWAM_SUCCESS) {
2N/A if (errpropp != NULL)
2N/A *errpropp = NWAM_LOC_PROP_LDAP_NAMESERVICE_CONFIGSRC;
2N/A return (NWAM_ENTITY_MISSING_MEMBER);
2N/A }
2N/A /* -configsrc is defined as an array */
2N/A if (nwam_value_get_uint64_array(val, &configsrcs, &numvalues)
2N/A != NWAM_SUCCESS) {
2N/A if (errpropp != NULL)
2N/A *errpropp = NWAM_LOC_PROP_LDAP_NAMESERVICE_CONFIGSRC;
2N/A nwam_value_free(val);
2N/A return (NWAM_ENTITY_NO_VALUE);
2N/A }
2N/A
2N/A /* -configsrc must be manual */
2N/A for (i = 0; i < numvalues; i++) {
2N/A if (configsrcs[i] != NWAM_CONFIGSRC_MANUAL) {
2N/A if (errpropp != NULL)
2N/A *errpropp =
2N/A NWAM_LOC_PROP_LDAP_NAMESERVICE_CONFIGSRC;
2N/A nwam_value_free(val);
2N/A return (NWAM_ENTITY_INVALID_VALUE);
2N/A }
2N/A }
2N/A nwam_value_free(val);
2N/A
2N/A /* both default-domain and -servers are required */
2N/A if (nwam_loc_get_prop_value(loch,
2N/A NWAM_LOC_PROP_DEFAULT_DOMAIN, &val) != NWAM_SUCCESS) {
2N/A if (errpropp != NULL)
2N/A *errpropp = NWAM_LOC_PROP_DEFAULT_DOMAIN;
2N/A return (NWAM_ENTITY_MISSING_MEMBER);
2N/A }
2N/A nwam_value_free(val);
2N/A
2N/A if (nwam_loc_get_prop_value(loch,
2N/A NWAM_LOC_PROP_LDAP_NAMESERVICE_SERVERS, &val) != NWAM_SUCCESS) {
2N/A if (errpropp != NULL)
2N/A *errpropp = NWAM_LOC_PROP_LDAP_NAMESERVICE_SERVERS;
2N/A return (NWAM_ENTITY_MISSING_MEMBER);
2N/A }
2N/A nwam_value_free(val);
2N/A
2N/A return (NWAM_SUCCESS);
2N/A}
2N/A
2N/A/*
2N/A * Validates the different nameservices properties.
2N/A *
2N/A * If "nameservices" property has more than one nameservice to configure,
2N/A * "nameservices-config-file" must be specified. If only one nameservice
2N/A * is configured and "nameservices-config-file" is missing, set the
2N/A * property with the appropriately suffixed nsswitch file.
2N/A *
2N/A * For any nameservice being configured, the respective -configsrc property
2N/A * must be specified. For DNS, -servers is required if -configsrc is
2N/A * manual. For NIS and LDAP, default-domain is required if -configsrc is
2N/A * manual. For LDAP, -configsrc must be manual and -servers is required.
2N/A */
2N/Astatic nwam_error_t
2N/Anwam_loc_validate_all_nameservices(nwam_loc_handle_t loch,
2N/A nwam_value_t nameservicesval, const char **errpropp)
2N/A{
2N/A nwam_error_t err;
2N/A nwam_value_t val;
2N/A uint64_t *nameservices;
2N/A uint_t i, numvalues;
2N/A
2N/A if ((err = nwam_value_get_uint64_array(nameservicesval, &nameservices,
2N/A &numvalues)) != NWAM_SUCCESS)
2N/A return (err);
2N/A
2N/A /*
2N/A * nameservices-config-file is required if nameservices has more
2N/A * than one value.
2N/A */
2N/A if (numvalues > 1) {
2N/A if (nwam_loc_get_prop_value(loch,
2N/A NWAM_LOC_PROP_NAMESERVICES_CONFIG_FILE, &val)
2N/A != NWAM_SUCCESS) {
2N/A if (errpropp != NULL)
2N/A *errpropp =
2N/A NWAM_LOC_PROP_NAMESERVICES_CONFIG_FILE;
2N/A return (NWAM_ENTITY_MISSING_MEMBER);
2N/A }
2N/A nwam_value_free(val);
2N/A } else if (numvalues == 1) {
2N/A /*
2N/A * If only one nameservice is being configured and
2N/A * nameservices-config-file doesn't exist, create it to
2N/A * point to the respective nsswitch file.
2N/A */
2N/A err = nwam_loc_get_prop_value(loch,
2N/A NWAM_LOC_PROP_NAMESERVICES_CONFIG_FILE, &val);
2N/A if (err == NWAM_INVALID_ARG || err == NWAM_ENTITY_NOT_FOUND) {
2N/A char *nsswitch;
2N/A const char *nsswitch_suffix;
2N/A
2N/A /* get the single nameservice being configured */
2N/A if ((err = nwam_uint64_get_value_string(
2N/A NWAM_LOC_PROP_NAMESERVICES, nameservices[0],
2N/A &nsswitch_suffix)) != NWAM_SUCCESS)
2N/A goto config_file_fail;
2N/A if ((nsswitch = malloc(MAXPATHLEN)) == NULL) {
2N/A err = NWAM_NO_MEMORY;
2N/A goto config_file_fail;
2N/A }
2N/A
2N/A /* create appropriately suffixed nsswitch name */
2N/A (void) snprintf(nsswitch, MAXPATHLEN, "%s%s",
2N/A NSSWITCH_PREFIX, nsswitch_suffix);
2N/A if ((err = nwam_value_create_string(nsswitch, &val))
2N/A != NWAM_SUCCESS) {
2N/A free(nsswitch);
2N/A goto config_file_fail;
2N/A }
2N/A
2N/A err = nwam_set_prop_value(loch->nwh_data,
2N/A NWAM_LOC_PROP_NAMESERVICES_CONFIG_FILE, val);
2N/A free(nsswitch);
2N/A nwam_value_free(val);
2N/A if (err != NWAM_SUCCESS) {
2N/A nwam_value_free(val);
2N/A goto config_file_fail;
2N/A }
2N/A } else if (err != NWAM_SUCCESS) {
2N/A goto config_file_fail;
2N/A } else {
2N/A nwam_value_free(val);
2N/A }
2N/A }
2N/A
2N/A /*
2N/A * validate the -configsrc property and the required default-domain
2N/A * and/or -servers property for each nameservice being configured.
2N/A */
2N/A for (i = 0; i < numvalues; i++) {
2N/A nwam_value_t dom = NULL, srch = NULL;
2N/A
2N/A switch (nameservices[i]) {
2N/A case NWAM_NAMESERVICES_DNS:
2N/A if ((err = nwam_loc_validate_one_nameservice(loch,
2N/A NWAM_LOC_PROP_DNS_NAMESERVICE_CONFIGSRC,
2N/A NWAM_LOC_PROP_DNS_NAMESERVICE_SERVERS, errpropp))
2N/A != NWAM_SUCCESS)
2N/A return (err);
2N/A
2N/A /* Also, -domain and -search are mutually exclusive */
2N/A if (nwam_loc_get_prop_value(loch,
2N/A NWAM_LOC_PROP_DNS_NAMESERVICE_DOMAIN, &dom)
2N/A != NWAM_ENTITY_NOT_FOUND &&
2N/A nwam_loc_get_prop_value(loch,
2N/A NWAM_LOC_PROP_DNS_NAMESERVICE_SEARCH, &srch)
2N/A != NWAM_ENTITY_NOT_FOUND) {
2N/A nwam_value_free(dom);
2N/A nwam_value_free(srch);
2N/A return (NWAM_ENTITY_MULTIPLE_VALUES);
2N/A }
2N/A nwam_value_free(dom);
2N/A nwam_value_free(srch);
2N/A break;
2N/A case NWAM_NAMESERVICES_NIS:
2N/A if ((err = nwam_loc_validate_one_nameservice(loch,
2N/A NWAM_LOC_PROP_NIS_NAMESERVICE_CONFIGSRC,
2N/A NWAM_LOC_PROP_DEFAULT_DOMAIN, errpropp))
2N/A != NWAM_SUCCESS)
2N/A return (err);
2N/A break;
2N/A case NWAM_NAMESERVICES_LDAP:
2N/A if ((err = nwam_loc_validate_ldap_nameservice(loch,
2N/A errpropp)) != NWAM_SUCCESS)
2N/A return (err);
2N/A break;
2N/A case NWAM_NAMESERVICES_FILES:
2N/A break;
2N/A default:
2N/A return (NWAM_ENTITY_INVALID_VALUE);
2N/A }
2N/A }
2N/A return (NWAM_SUCCESS);
2N/A
2N/Aconfig_file_fail:
2N/A if (errpropp != NULL)
2N/A *errpropp = NWAM_LOC_PROP_NAMESERVICES_CONFIG_FILE;
2N/A return (err);
2N/A}
2N/A
2N/Anwam_error_t
2N/Anwam_loc_validate(nwam_loc_handle_t loch, const char **errpropp)
2N/A{
2N/A nwam_error_t err;
2N/A nwam_value_t activationval, conditionval, nameservicesval;
2N/A uint64_t activation;
2N/A char **conditions, *name;
2N/A uint_t i, numvalues;
2N/A nwam_condition_object_type_t object_type;
2N/A nwam_condition_t condition;
2N/A
2N/A assert(loch != NULL);
2N/A
2N/A /*
2N/A * Make sure loc is internally consistent: if activation type is
2N/A * conditional, the condition string must be specified.
2N/A */
2N/A if (nwam_loc_get_prop_value(loch, NWAM_LOC_PROP_ACTIVATION_MODE,
2N/A &activationval) != NWAM_SUCCESS) {
2N/A if (errpropp != NULL)
2N/A *errpropp = NWAM_LOC_PROP_ACTIVATION_MODE;
2N/A return (NWAM_ENTITY_MISSING_MEMBER);
2N/A }
2N/A
2N/A if (nwam_value_get_uint64(activationval, &activation)
2N/A != NWAM_SUCCESS) {
2N/A if (errpropp != NULL)
2N/A *errpropp = NWAM_LOC_PROP_ACTIVATION_MODE;
2N/A nwam_value_free(activationval);
2N/A return (NWAM_ENTITY_NO_VALUE);
2N/A }
2N/A
2N/A /* validate activation against the location first */
2N/A if ((err = nwam_loc_validate_activation_mode(loch, activationval))
2N/A != NWAM_SUCCESS) {
2N/A if (errpropp != NULL)
2N/A *errpropp = NWAM_LOC_PROP_ACTIVATION_MODE;
2N/A nwam_value_free(activationval);
2N/A return (err);
2N/A }
2N/A nwam_value_free(activationval);
2N/A
2N/A if (activation == NWAM_ACTIVATION_MODE_CONDITIONAL_ANY ||
2N/A activation == NWAM_ACTIVATION_MODE_CONDITIONAL_ALL) {
2N/A if (nwam_loc_get_prop_value(loch, NWAM_LOC_PROP_CONDITIONS,
2N/A &conditionval) != NWAM_SUCCESS) {
2N/A if (errpropp != NULL)
2N/A *errpropp = NWAM_LOC_PROP_CONDITIONS;
2N/A return (NWAM_ENTITY_MISSING_MEMBER);
2N/A }
2N/A /*
2N/A * Are conditions self-referential? In other words, do any
2N/A * of the activation conditions refer to this location?
2N/A */
2N/A if (nwam_value_get_string_array(conditionval, &conditions,
2N/A &numvalues) != NWAM_SUCCESS) {
2N/A nwam_value_free(conditionval);
2N/A if (errpropp != NULL)
2N/A *errpropp = NWAM_LOC_PROP_CONDITIONS;
2N/A return (NWAM_ENTITY_INVALID_VALUE);
2N/A }
2N/A if (nwam_loc_get_name(loch, &name) != NWAM_SUCCESS) {
2N/A nwam_value_free(conditionval);
2N/A return (NWAM_INVALID_ARG);
2N/A }
2N/A for (i = 0; i < numvalues; i++) {
2N/A char *object_name = NULL;
2N/A
2N/A if (nwam_condition_string_to_condition(conditions[i],
2N/A &object_type, &condition, &object_name)
2N/A != NWAM_SUCCESS) {
2N/A if (errpropp != NULL)
2N/A *errpropp = NWAM_LOC_PROP_CONDITIONS;
2N/A free(name);
2N/A nwam_value_free(conditionval);
2N/A return (NWAM_ENTITY_INVALID_VALUE);
2N/A }
2N/A if (object_name != NULL &&
2N/A object_type == NWAM_CONDITION_OBJECT_TYPE_LOC &&
2N/A strcmp(object_name, name) == 0) {
2N/A if (errpropp != NULL)
2N/A *errpropp = NWAM_LOC_PROP_CONDITIONS;
2N/A free(name);
2N/A free(object_name);
2N/A nwam_value_free(conditionval);
2N/A return (NWAM_ENTITY_INVALID_VALUE);
2N/A }
2N/A free(object_name);
2N/A }
2N/A free(name);
2N/A nwam_value_free(conditionval);
2N/A }
2N/A
2N/A /* validate namerservices */
2N/A if (nwam_loc_get_prop_value(loch, NWAM_LOC_PROP_NAMESERVICES,
2N/A &nameservicesval) != NWAM_SUCCESS) {
2N/A if (errpropp != NULL)
2N/A *errpropp = NWAM_LOC_PROP_NAMESERVICES;
2N/A return (NWAM_ENTITY_MISSING_MEMBER);
2N/A }
2N/A err = nwam_loc_validate_all_nameservices(loch, nameservicesval,
2N/A errpropp);
2N/A nwam_value_free(nameservicesval);
2N/A if (err != NWAM_SUCCESS)
2N/A return (err);
2N/A
2N/A return (nwam_validate(loc_prop_table, loch, errpropp));
2N/A}
2N/A
2N/Anwam_error_t
2N/Anwam_loc_validate_prop(nwam_loc_handle_t loch, const char *propname,
2N/A nwam_value_t value)
2N/A{
2N/A nwam_error_t err;
2N/A
2N/A assert(loch != NULL);
2N/A
2N/A if (strcmp(propname, NWAM_LOC_PROP_ACTIVATION_MODE) == 0) {
2N/A if ((err = nwam_loc_validate_activation_mode(loch, value))
2N/A != NWAM_SUCCESS)
2N/A return (err);
2N/A }
2N/A
2N/A return (nwam_validate_prop(loc_prop_table, loch, propname, value));
2N/A}
2N/A
2N/Anwam_error_t
2N/Anwam_loc_copy(nwam_loc_handle_t oldloch, const char *newname,
2N/A nwam_loc_handle_t *newlochp)
2N/A{
2N/A nwam_error_t err;
2N/A nwam_value_t val;
2N/A boolean_t fixed;
2N/A
2N/A /* Locations of "fixed" type cannot be copied */
2N/A if ((err = nwam_loc_is_fixed(oldloch, &fixed)) != NWAM_SUCCESS)
2N/A return (err);
2N/A if (fixed)
2N/A return (NWAM_ENTITY_FIXED);
2N/A
2N/A if ((err = nwam_copy(NWAM_LOC_CONF_FILE, oldloch, newname, newlochp))
2N/A != NWAM_SUCCESS)
2N/A return (err);
2N/A
2N/A /* If the activation-mode is system, change it to manual */
2N/A if ((err = nwam_loc_get_prop_value(*newlochp,
2N/A NWAM_LOC_PROP_ACTIVATION_MODE, &val)) != NWAM_SUCCESS)
2N/A goto finish;
2N/A err = nwam_loc_validate_activation_mode(*newlochp, val);
2N/A nwam_value_free(val);
2N/A if (err != NWAM_SUCCESS) {
2N/A if ((err = nwam_value_create_uint64(NWAM_ACTIVATION_MODE_MANUAL,
2N/A &val)) != NWAM_SUCCESS)
2N/A goto finish;
2N/A err = nwam_set_prop_value((*newlochp)->nwh_data,
2N/A NWAM_LOC_PROP_ACTIVATION_MODE, val);
2N/A nwam_value_free(val);
2N/A if (err != NWAM_SUCCESS)
2N/A goto finish;
2N/A
2N/A if ((err = nwam_value_create_boolean(B_FALSE, &val))
2N/A != NWAM_SUCCESS)
2N/A goto finish;
2N/A err = nwam_set_prop_value((*newlochp)->nwh_data,
2N/A NWAM_LOC_PROP_ENABLED, val);
2N/A nwam_value_free(val);
2N/A if (err != NWAM_SUCCESS)
2N/A goto finish;
2N/A }
2N/A
2N/A return (NWAM_SUCCESS);
2N/A
2N/Afinish:
2N/A nwam_loc_free(*newlochp);
2N/A *newlochp = NULL;
2N/A return (err);
2N/A}
2N/A
2N/A/*
2N/A * Given a property, return expected property data type
2N/A */
2N/Anwam_error_t
2N/Anwam_loc_get_prop_type(const char *propname, nwam_value_type_t *typep)
2N/A{
2N/A return (nwam_get_prop_type(loc_prop_table, propname, typep));
2N/A}
2N/A
2N/Anwam_error_t
2N/Anwam_loc_prop_multivalued(const char *propname, boolean_t *multip)
2N/A{
2N/A return (nwam_prop_multivalued(loc_prop_table, propname, multip));
2N/A}
2N/A
2N/A/*
2N/A * Determine if the location has manual activation-mode or not.
2N/A */
2N/Anwam_error_t
2N/Anwam_loc_is_manual(nwam_loc_handle_t loch, boolean_t *manualp)
2N/A{
2N/A nwam_error_t err;
2N/A nwam_value_t actval;
2N/A uint64_t activation;
2N/A
2N/A assert(loch != NULL);
2N/A
2N/A if ((err = nwam_loc_get_prop_value(loch, NWAM_LOC_PROP_ACTIVATION_MODE,
2N/A &actval)) != NWAM_SUCCESS)
2N/A return (err);
2N/A err = nwam_value_get_uint64(actval, &activation);
2N/A nwam_value_free(actval);
2N/A if (err != NWAM_SUCCESS)
2N/A return (err);
2N/A
2N/A if (activation == NWAM_ACTIVATION_MODE_MANUAL)
2N/A *manualp = B_TRUE;
2N/A else
2N/A *manualp = B_FALSE;
2N/A return (NWAM_SUCCESS);
2N/A}
2N/A
2N/A/* Determine if location is enabled or not */
2N/Anwam_error_t
2N/Anwam_loc_is_enabled(nwam_loc_handle_t loch, boolean_t *enabledp)
2N/A{
2N/A nwam_error_t err;
2N/A nwam_value_t enabledval;
2N/A
2N/A assert(loch != NULL);
2N/A
2N/A if ((err = nwam_loc_get_prop_value(loch, NWAM_LOC_PROP_ENABLED,
2N/A &enabledval)) != NWAM_SUCCESS)
2N/A return (err);
2N/A err = nwam_value_get_boolean(enabledval, enabledp);
2N/A nwam_value_free(enabledval);
2N/A return (err);
2N/A}
2N/A
2N/Anwam_error_t
2N/Anwam_loc_enable(nwam_loc_handle_t loch)
2N/A{
2N/A nwam_error_t err;
2N/A boolean_t enabled, fixed;
2N/A
2N/A assert(loch != NULL);
2N/A
2N/A /* Fixed locations cannot be enabled */
2N/A if ((err = nwam_loc_is_fixed(loch, &fixed)) != NWAM_SUCCESS)
2N/A return (err);
2N/A if (fixed)
2N/A return (NWAM_ENTITY_FIXED);
2N/A
2N/A /* Get the enabled property */
2N/A if ((err = nwam_loc_is_enabled(loch, &enabled)) != NWAM_SUCCESS)
2N/A return (err);
2N/A err = nwam_enable(NULL, loch);
2N/A /*
2N/A * If nwamd says fixed NCP is active, return that error regardless of
2N/A * the enabled property.
2N/A */
2N/A if (err == NWAM_ENTITY_FIXED_ACTIVE)
2N/A return (err);
2N/A else if (enabled)
2N/A return (NWAM_ENTITY_ENABLED);
2N/A return (err);
2N/A}
2N/A
2N/Anwam_error_t
2N/Anwam_loc_disable(nwam_loc_handle_t loch)
2N/A{
2N/A nwam_error_t err;
2N/A boolean_t enabled, fixed;
2N/A
2N/A assert(loch != NULL);
2N/A
2N/A /* Fixed locations cannot be disabled */
2N/A if ((err = nwam_loc_is_fixed(loch, &fixed)) != NWAM_SUCCESS)
2N/A return (err);
2N/A if (fixed)
2N/A return (NWAM_ENTITY_FIXED);
2N/A
2N/A /* Get the enabled property */
2N/A if ((err = nwam_loc_is_enabled(loch, &enabled)) != NWAM_SUCCESS)
2N/A return (err);
2N/A err = nwam_disable(NULL, loch);
2N/A /*
2N/A * If nwamd says fixed NCP is active, return that error regardless of
2N/A * the enabled property.
2N/A */
2N/A if (err == NWAM_ENTITY_FIXED_ACTIVE)
2N/A return (err);
2N/A else if (!enabled)
2N/A return (NWAM_ENTITY_DISABLED);
2N/A return (err);
2N/A}
2N/A
2N/Anwam_error_t
2N/Anwam_loc_get_default_proplist(const char ***prop_list, uint_t *numvaluesp)
2N/A{
2N/A return (nwam_get_default_proplist(loc_prop_table,
2N/A NWAM_TYPE_ANY, NWAM_CLASS_ANY, prop_list, numvaluesp));
2N/A}
2N/A
2N/Anwam_error_t
2N/Anwam_loc_get_state(nwam_loc_handle_t loch, nwam_state_t *statep,
2N/A nwam_aux_state_t *auxp)
2N/A{
2N/A return (nwam_get_state(NULL, loch, statep, auxp));
2N/A}