libnwam_loc.c revision 69b43529e65fb6eb0c88e6b7b42025e9bf025b8a
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#include <assert.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <unistd.h>
#include <libscf.h>
#include "libnwam_impl.h"
#include <libnwam_priv.h>
#include <libnwam.h>
/*
* Functions to support creating, modifying, destroying, querying the
* state of and changing the state of location objects. Locations
* represent the configuration to be applied once basic network configuration
* has been established - name services, IPsec config, etc, and can be enabled
* either manually or conditionally for a combination of the set of
* available conditions (an IP address is present, an ENM is active etc).
*/
#define NSSWITCH_PREFIX "/etc/nsswitch."
struct nwam_prop_table_entry loc_prop_table_entries[] = {
"specifies the location activation mode - valid values are:\n"
"\'manual\', \'conditional-any\' and \'conditional-all\'",
"specifies the activation condition. Conditions are of the form:\n"
"ncp|ncu|enm name is|is-not active\n"
"ip-address is|is-not|is-in-range|is-not-in-range| 1.2.3.4[/24]\n"
"advertised-domain is|is-not|contains|does-not-contain string\n"
"system-domain is|is-not|contains|does-not-contain string\n"
"essid is|is-not|contains|does-not-contain string\n"
"bssid is|is-not string",
"specifies if location is to be enabled",
"specifies name service(s) to be used - valid values are:\n"
"\'files\', \'dns\', \'nis\', and \'ldap\'",
"specifies path to configuration file for name services switch "
"for this location - see nsswitch.conf(4)",
"specifies sources of DNS configuration parameters - valid values "
"are:\n\'dhcp\', or \'manual\'",
0, 1, nwam_valid_domain,
"specifies DNS domain name to be set for this location",
"specifies DNS server host address(es)",
"specifies DNS search list for host name lookup",
"specifies sources of NIS configuration parameters - valid values "
"are:\n\'dhcp\', or \'manual\'",
"specifies NIS server host address(es)",
"specifies sources of NIS configuration parameters - currently, "
"the only valid value is \'manual\'",
"specifies LDAP server host address(es)",
"specifies the domainname(1M) to be set for this location",
"specifies an NFSv4 domain for this location",
0, 1, nwam_valid_file,
"specifies an absolute path to an ipf.conf(4) file for this "
"location",
"specifies an absolute path to an ipf6.conf file for this "
"location",
1, nwam_valid_file,
"specifies an absolute path to an ipnat.conf(4) file for this "
"location",
1, nwam_valid_file,
"specifies an absolute path to an ippool.conf(4) file for this "
"location",
"specifies an absolute path to an ike config file "
"(see ike.config(4))",
"specifies an absolute path to an IPsec policy configuration file "
"(see ipsecconf(1M)",
};
#define NWAM_NUM_LOC_PROPS (sizeof (loc_prop_table_entries) / \
sizeof (*loc_prop_table_entries))
struct nwam_prop_table loc_prop_table =
static uint64_t
{
switch (activation) {
return (NWAM_FLAG_ACTIVATION_MODE_MANUAL);
return (NWAM_FLAG_ACTIVATION_MODE_SYSTEM);
default:
return (0);
}
}
{
}
{
lochp)) != NWAM_SUCCESS)
return (err);
/* Create new object list for loc */
!= NWAM_SUCCESS)
goto finish;
/* NWAM_LOC_PROP_ACTIVATION_MODE is mandatory */
!= NWAM_SUCCESS) {
goto finish;
}
goto finish;
}
/*
* NWAM_LOC_PROP_ENABLED defaults to false.
*/
goto finish;
goto finish;
/*
* Initialize name service properties: use DNS, configured
* via DHCP, with default nsswitch (/etc/nsswitch.dns).
*/
goto finish;
goto finish;
goto finish;
goto finish;
/* concatenate these two strings */
goto finish;
}
goto finish;
if (err != NWAM_SUCCESS) {
}
return (err);
}
{
}
{
}
{
return (!loch->nwh_committed);
}
/* ARGSUSED2 */
static int
{
char *locname;
/* Skip the Legacy location in all cases */
return (NWAM_INVALID_ARG);
return (NWAM_INVALID_ARG);
}
/*
* Get a bitmapped flag value corresponding to this loc's
* activation.
*/
&activationval) != NWAM_SUCCESS) {
return (NWAM_INVALID_ARG);
}
return (NWAM_INVALID_ARG);
}
if (actflag & walkfilter)
return (NWAM_SUCCESS);
return (NWAM_INVALID_ARG);
}
int *retp)
{
if (err != NWAM_SUCCESS)
return (err);
}
void
{
}
{
void *olddata;
return (err);
if (ro)
return (NWAM_ENTITY_READ_ONLY);
/*
* Duplicate data, remove property and validate. If validation
* fails, revert to data duplicated prior to remove.
*/
!= NWAM_SUCCESS)
return (err);
!= NWAM_SUCCESS) {
return (err);
}
return (err);
}
return (NWAM_SUCCESS);
}
{
!= NWAM_SUCCESS ||
return (err);
if (ro)
return (NWAM_ENTITY_READ_ONLY);
}
{
}
int (*cb)(const char *, nwam_value_t, void *),
{
}
{
return (err);
}
{
/*
* Automatic and NoNet are not destroyable and Legacy is
* destroyable by netadm only. These have system activation-mode.
*/
&actval)) != NWAM_SUCCESS)
return (err);
if (err != NWAM_SUCCESS)
return (err);
if (activation == NWAM_ACTIVATION_MODE_SYSTEM) {
if (!nwam_uid_is_special())
return (NWAM_ENTITY_NOT_DESTROYABLE);
} else {
return (NWAM_ENTITY_NOT_DESTROYABLE);
}
}
}
{
descriptionp));
}
{
}
static nwam_error_t
{
return (NWAM_ENTITY_INVALID_VALUE);
switch (activation_mode) {
return (NWAM_SUCCESS);
}
return (NWAM_ENTITY_INVALID_VALUE);
}
/*
* Identical to nwam_valid_condition(), except locations cannot specify other
* location's activation as a condition, e.g. loc2 cannot specify
* "loc1 is active" since only one location is active at a time, and
* as a consequence the condition is unsatisfiable.
*/
{
char **conditions;
!= NWAM_SUCCESS)
return (NWAM_ENTITY_INVALID_VALUE);
for (i = 0; i < numvalues; i++) {
char *object_name = NULL;
return (NWAM_ENTITY_INVALID_VALUE);
if (object_type == NWAM_CONDITION_OBJECT_TYPE_LOC &&
condition == NWAM_CONDITION_IS) {
return (NWAM_ENTITY_INVALID_VALUE);
}
if (object_name != NULL)
}
return (NWAM_SUCCESS);
}
static nwam_error_t
{
!= NWAM_SUCCESS)
return (NWAM_ENTITY_INVALID_VALUE);
for (i = 0; i < numvalues; i++) {
if (nameservices[i] > NWAM_NAMESERVICES_LDAP)
return (NWAM_ENTITY_INVALID_VALUE);
}
return (NWAM_SUCCESS);
}
static nwam_error_t
{
!= NWAM_SUCCESS)
return (NWAM_ENTITY_INVALID_VALUE);
for (i = 0; i < numvalues; i++) {
if (configsrcs[i] > NWAM_CONFIGSRC_DHCP)
return (NWAM_ENTITY_INVALID_VALUE);
}
return (NWAM_SUCCESS);
}
/*
* Validates that the activation-mode is system for Automatic and NoNet
* locations, and not system for all other locations.
*/
static nwam_error_t
{
return (err);
return (NWAM_ENTITY_INVALID_VALUE);
} else {
return (NWAM_ENTITY_INVALID_VALUE);
}
return (NWAM_SUCCESS);
}
/*
* Helper function to validate one nameservice, used by
* nwam_loc_validate_all_nameservices().
*
* requiredprop denotes the property that is mandatory when the
* configsrcprop is manual. errpropp is used to return the invalid
* property.
*/
static nwam_error_t
{
!= NWAM_SUCCESS) {
return (NWAM_ENTITY_MISSING_MEMBER);
}
!= NWAM_SUCCESS) {
return (NWAM_ENTITY_NO_VALUE);
}
/* If -configsrc is manual, requiredprop is required */
for (i = 0; i < numvalues; i++) {
if (configsrcs[i] == NWAM_CONFIGSRC_MANUAL) {
&requiredval) != NWAM_SUCCESS) {
*errpropp = requiredprop;
return (NWAM_ENTITY_MISSING_MEMBER);
}
}
}
return (NWAM_SUCCESS);
}
/*
* Helper function to validate LDAP nameservice, used by
* nwam_loc_validate_all_nameservices(). Separated because LDAP must be
* configured manually only and both default-domain and -servers are required.
*/
static nwam_error_t
const char **errpropp)
{
return (NWAM_ENTITY_MISSING_MEMBER);
}
/* -configsrc is defined as an array */
!= NWAM_SUCCESS) {
return (NWAM_ENTITY_NO_VALUE);
}
/* -configsrc must be manual */
for (i = 0; i < numvalues; i++) {
if (configsrcs[i] != NWAM_CONFIGSRC_MANUAL) {
*errpropp =
return (NWAM_ENTITY_INVALID_VALUE);
}
}
/* both default-domain and -servers are required */
return (NWAM_ENTITY_MISSING_MEMBER);
}
return (NWAM_ENTITY_MISSING_MEMBER);
}
return (NWAM_SUCCESS);
}
/*
* Validates the different nameservices properties.
*
* If "nameservices" property has more than one nameservice to configure,
* "nameservices-config-file" must be specified. If only one nameservice
* is configured and "nameservices-config-file" is missing, set the
* property with the appropriately suffixed nsswitch file.
*
* For any nameservice being configured, the respective -configsrc property
* must be specified. For DNS, -servers is required if -configsrc is
* manual. For NIS and LDAP, default-domain is required if -configsrc is
* manual. For LDAP, -configsrc must be manual and -servers is required.
*/
static nwam_error_t
{
&numvalues)) != NWAM_SUCCESS)
return (err);
/*
* nameservices-config-file is required if nameservices has more
* than one value.
*/
if (numvalues > 1) {
!= NWAM_SUCCESS) {
*errpropp =
return (NWAM_ENTITY_MISSING_MEMBER);
}
} else if (numvalues == 1) {
/*
* If only one nameservice is being configured and
* nameservices-config-file doesn't exist, create it to
* point to the respective nsswitch file.
*/
char *nsswitch;
const char *nsswitch_suffix;
/* get the single nameservice being configured */
if ((err = nwam_uint64_get_value_string(
&nsswitch_suffix)) != NWAM_SUCCESS)
goto config_file_fail;
goto config_file_fail;
}
/* create appropriately suffixed nsswitch name */
!= NWAM_SUCCESS) {
goto config_file_fail;
}
if (err != NWAM_SUCCESS) {
goto config_file_fail;
}
} else if (err != NWAM_SUCCESS) {
goto config_file_fail;
} else {
}
}
/*
* validate the -configsrc property and the required default-domain
*/
for (i = 0; i < numvalues; i++) {
switch (nameservices[i]) {
case NWAM_NAMESERVICES_DNS:
!= NWAM_SUCCESS)
return (err);
break;
case NWAM_NAMESERVICES_NIS:
!= NWAM_SUCCESS)
return (err);
break;
case NWAM_NAMESERVICES_LDAP:
errpropp)) != NWAM_SUCCESS)
return (err);
break;
case NWAM_NAMESERVICES_FILES:
break;
default:
return (NWAM_ENTITY_INVALID_VALUE);
}
}
return (NWAM_SUCCESS);
return (err);
}
{
char **conditions, *name;
/*
* Make sure loc is internally consistent: if activation type is
* conditional, the condition string must be specified.
*/
&activationval) != NWAM_SUCCESS) {
return (NWAM_ENTITY_MISSING_MEMBER);
}
!= NWAM_SUCCESS) {
return (NWAM_ENTITY_NO_VALUE);
}
/* validate activation against the location first */
!= NWAM_SUCCESS) {
return (err);
}
&conditionval) != NWAM_SUCCESS) {
return (NWAM_ENTITY_MISSING_MEMBER);
}
/*
* Are conditions self-referential? In other words, do any
* of the activation conditions refer to this location?
*/
&numvalues) != NWAM_SUCCESS) {
return (NWAM_ENTITY_INVALID_VALUE);
}
return (NWAM_INVALID_ARG);
}
for (i = 0; i < numvalues; i++) {
char *object_name = NULL;
!= NWAM_SUCCESS) {
return (NWAM_ENTITY_INVALID_VALUE);
}
if (object_name != NULL &&
return (NWAM_ENTITY_INVALID_VALUE);
}
}
}
/* validate namerservices */
&nameservicesval) != NWAM_SUCCESS) {
return (NWAM_ENTITY_MISSING_MEMBER);
}
errpropp);
if (err != NWAM_SUCCESS)
return (err);
}
{
!= NWAM_SUCCESS)
return (err);
}
}
{
!= NWAM_SUCCESS)
return (err);
/* If the activation-mode is system, change it to manual */
goto finish;
if (err != NWAM_SUCCESS) {
&val)) != NWAM_SUCCESS)
goto finish;
if (err != NWAM_SUCCESS)
goto finish;
!= NWAM_SUCCESS)
goto finish;
if (err != NWAM_SUCCESS)
goto finish;
}
return (NWAM_SUCCESS);
return (err);
}
/*
* Given a property, return expected property data type
*/
{
}
{
}
/*
* Determine if the location has manual activation-mode or not.
*/
{
&actval)) != NWAM_SUCCESS)
return (err);
if (err != NWAM_SUCCESS)
return (err);
else
return (NWAM_SUCCESS);
}
/* Determine if location is enabled or not */
static nwam_error_t
{
&enabledval)) != NWAM_SUCCESS)
return (err);
return (err);
}
/*
* Callback to disable all locations other than one to enable, the handle
* of which we pass in as an argument. If the argument is NULL, we disable
* all locations.
*/
static int
{
/* We enable this location. */
}
}
return (0);
enabledval) == NWAM_SUCCESS)
return (err);
}
/*
* Update the enabled property for this location (and for all others
* if necessary.
*/
static int
{
int cb_ret;
if (enabled) {
/*
* Disable all other locations that are manually enabled
* and enable this one - a maximum of 1 location can be
* enabled at once.
*/
} else {
}
return (cb_ret);
}
{
/* Make sure location is not enabled */
return (err);
if (enabled)
return (NWAM_SUCCESS);
return (err);
/* nwamd may not be running, that's okay. */
if (err == NWAM_ERROR_BIND)
return (NWAM_SUCCESS);
else
return (err);
}
{
/* Make sure location is enabled */
return (err);
if (!enabled)
return (NWAM_SUCCESS);
return (err);
/* nwamd may not be running, that's okay. */
if (err == NWAM_ERROR_BIND)
return (NWAM_SUCCESS);
else
return (err);
}
{
return (nwam_get_default_proplist(loc_prop_table,
}
{
}