/*
* 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
*/
/*
*/
#include <assert.h>
#include <ctype.h>
#include <dirent.h>
#include <libnetcfg.h>
#include <libscf.h>
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <unistd.h>
#include <libnwam.h>
#include "libnwam_impl.h"
#include <libnwam_priv.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).
*/
"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 IP address and optional netmask pairs (separated by "
"slashes) which allows addresses returned by gethostbyname() "
"to be sorted (see resolv.conf(4))",
0, NWAM_MAX_NUM_VALUES, NULL,
"specifies internal resolver variables that are to be modified "
"see (resolv.conf(4))",
"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)",
};
sizeof (*loc_prop_table_entries))
static uint64_t
{
switch (activation) {
return (NWAM_FLAG_ACTIVATION_MODE_MANUAL);
return (NWAM_FLAG_ACTIVATION_MODE_SYSTEM);
default:
return (0);
}
}
{
lochp));
}
{
lochp)) != NWAM_SUCCESS)
return (err);
/* 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);
}
static int
{
char *locname;
!= NWAM_SUCCESS)
return (err);
/* 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);
loc_selectcb));
}
void
{
}
/*
* Returns B_TRUE if the DefaultFixed location is being modified and the UID
* is netadm. This is to ensure that the net-loc script running as the netadm
* user can use netcfg to modify the DefaultFixed location.
*/
static boolean_t
{
getuid() == UID_NETADM);
}
{
void *olddata;
return (err);
return (NWAM_ENTITY_READ_ONLY);
/*
* A 'fixed' location cannot have properties deleted unless the caller
* is the special netadm UID and the DefaultFixed location's property
* is being cleared.
*/
return (NWAM_ENTITY_FIXED);
}
/*
* 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);
return (NWAM_ENTITY_READ_ONLY);
/*
* A 'fixed' location cannot have properties set, unless the caller is
* the special netadm UID and the DefaultFixed location's property is
* being set.
*/
return (NWAM_ENTITY_FIXED);
}
}
{
}
int (*cb)(const char *, nwam_value_t, void *),
{
}
{
return (err);
}
static void
{
/*
* it. We know that the directory does not have sub-directories.
*/
name);
return;
}
/* Finally, remove the directory itself */
}
{
/*
* Pre-defined locations Automatic and NoNet are not destroyable and
* DefaultFixed and Legacy are destroyable by netadm only. These
* locations are determined by the NWAM_LOC_NAME_PRE_DEFINED macro.
*/
if (!nwam_override_readonly(flags))
return (NWAM_ENTITY_NOT_DESTROYABLE);
} else {
return (NWAM_ENTITY_NOT_DESTROYABLE);
}
}
/*
* containing the config files.
*/
}
{
descriptionp));
}
{
}
{
/* DefaultFixed location is the only fixed location */
else
return (NWAM_SUCCESS);
}
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++) {
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);
}
static nwam_error_t
{
!= NWAM_SUCCESS)
return (NWAM_ENTITY_INVALID_VALUE);
for (i = 0; i < numvalues; i++) {
/* may include netmask, which is separated by a slash */
!= NWAM_SUCCESS)
goto fail;
goto fail;
/* "copy" now points to the netmask, if any */
!= NWAM_SUCCESS)
goto fail;
goto fail;
}
}
return (NWAM_SUCCESS);
fail:
return (err);
}
/*
* Validates that the activation-mode is
* - system for Automatic and NoNet locations
* - not system for all other reactive locations
* - anything for all fixed locations (those automatically created by nwamd
* are system; the user may also create them with manual or conditional)
*/
static nwam_error_t
{
!= NWAM_SUCCESS ||
return (err);
if (is_fixed)
return (NWAM_SUCCESS);
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);
/* Also, -domain and -search are mutually exclusive */
!= NWAM_ENTITY_NOT_FOUND &&
!= NWAM_ENTITY_NOT_FOUND) {
return (NWAM_ENTITY_MULTIPLE_VALUES);
}
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);
}
{
/*
* 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++) {
!= 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);
}
}
{
/* Locations of "fixed" type cannot be copied */
return (err);
if (fixed)
return (NWAM_ENTITY_FIXED);
!= 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 */
{
&enabledval)) != NWAM_SUCCESS)
return (err);
return (err);
}
{
/* Fixed locations cannot be enabled */
return (err);
if (fixed)
return (NWAM_ENTITY_FIXED);
/* Get the enabled property */
return (err);
/*
* If nwamd says fixed NCP is active, return that error regardless of
* the enabled property.
*/
if (err == NWAM_ENTITY_FIXED_ACTIVE)
return (err);
else if (enabled)
return (NWAM_ENTITY_ENABLED);
return (err);
}
{
/* Fixed locations cannot be disabled */
return (err);
if (fixed)
return (NWAM_ENTITY_FIXED);
/* Get the enabled property */
return (err);
/*
* If nwamd says fixed NCP is active, return that error regardless of
* the enabled property.
*/
if (err == NWAM_ENTITY_FIXED_ACTIVE)
return (err);
else if (!enabled)
return (NWAM_ENTITY_DISABLED);
return (err);
}
{
return (nwam_get_default_proplist(loc_prop_table,
}
{
}