/*
* 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 <atomic.h>
#include <ctype.h>
#include <errno.h>
#include <libintl.h>
#include <libproc.h>
#include <libscf.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <unistd.h>
#include "libnwam_impl.h"
#include <libnwam_priv.h>
#include <libnwam.h>
/*
* Utility functions for door access, common validation functions etc.
*/
static int
{
int err = 0;
(void) pthread_mutex_lock(&door_mutex);
if (*door_fdp != -1) {
/* Check door fd is not old (from previous nwamd). */
*door_fdp = -1;
}
}
if (*door_fdp == -1) {
if (*door_fdp == -1)
}
(void) pthread_mutex_unlock(&door_mutex);
return (err);
}
int
{
int err;
return (err);
return (errno);
return (0);
}
static nwam_error_t
{
int err;
request, sizeof (nwamd_door_arg_t))) != 0) {
return (NWAM_ERROR_NWAMD_BIND);
return (nwam_errno_to_nwam_error(err));
}
switch (request->nwda_status) {
case NWAM_REQUEST_STATUS_OK:
return (NWAM_SUCCESS);
return (NWAM_INVALID_ARG);
return (NWAM_ENTITY_IN_USE);
return (request->nwda_error);
default:
return (NWAM_ERROR_INTERNAL);
}
}
const char *event_msg_file)
{
return (send_msg_to_nwam(&req));
}
{
} else {
}
return (send_msg_to_nwam(&req));
}
{
}
if (err == NWAM_SUCCESS) {
}
return (err);
}
{
} else {
}
} else {
}
} else {
}
return (send_msg_to_nwam(&req));
}
{
return (err);
return (NWAM_NO_MEMORY);
*num_wlansp * sizeof (nwam_wlan_t));
return (NWAM_SUCCESS);
}
{
if (err == NWAM_SUCCESS)
*priorityp =
return (err);
}
/* String conversion functions */
const char *
{
switch (type) {
case NWAM_VALUE_TYPE_BOOLEAN:
return ("boolean");
case NWAM_VALUE_TYPE_INT64:
return ("int64");
case NWAM_VALUE_TYPE_UINT64:
return ("uint64");
case NWAM_VALUE_TYPE_STRING:
return ("string");
default:
return ("unknown");
}
}
{
return (NWAM_VALUE_TYPE_BOOLEAN);
return (NWAM_VALUE_TYPE_INT64);
return (NWAM_VALUE_TYPE_UINT64);
return (NWAM_VALUE_TYPE_STRING);
return (NWAM_VALUE_TYPE_UNKNOWN);
}
const char *
{
switch (action) {
case NWAM_ACTION_ADD:
return ("add");
case NWAM_ACTION_REMOVE:
return ("remove");
case NWAM_ACTION_REFRESH:
return ("refresh");
case NWAM_ACTION_ENABLE:
return ("enable");
case NWAM_ACTION_DISABLE:
return ("disable");
case NWAM_ACTION_DESTROY:
return ("destroy");
case NWAM_ACTION_EXT_ADD:
return ("external add");
case NWAM_ACTION_EXT_DESTROY:
return ("external destroy");
case NWAM_ACTION_OFFLINE:
return ("offline");
case NWAM_ACTION_ONLINE:
return ("online");
default:
return ("unknown");
}
}
const char *
{
switch (event_type) {
case NWAM_EVENT_TYPE_NOOP:
return ("NOOP");
case NWAM_EVENT_TYPE_INIT:
return ("INIT");
case NWAM_EVENT_TYPE_SHUTDOWN:
return ("SHUTDOWN");
return ("OBJECT_ACTION");
return ("OBJECT_STATE");
return ("PRIORITY_GROUP");
case NWAM_EVENT_TYPE_INFO:
return ("INFO");
return ("WLAN_SCAN_REPORT");
return ("WLAN_NEED_CHOICE");
return ("WLAN_NEED_KEY");
return ("WLAN_CONNECTION_REPORT");
return ("IF_ACTION");
case NWAM_EVENT_TYPE_IF_STATE:
return ("IF_STATE");
return ("LINK_ACTION");
return ("LINK_STATE");
default:
return ("UNKNOWN");
}
}
const char *
{
switch (state) {
case NWAM_STATE_UNINITIALIZED:
return ("uninitialized");
case NWAM_STATE_INITIALIZED:
return ("initialized");
case NWAM_STATE_OFFLINE:
return ("offline");
return ("offline*");
return ("online*");
case NWAM_STATE_ONLINE:
return ("online");
case NWAM_STATE_MAINTENANCE:
return ("maintenance");
case NWAM_STATE_DEGRADED:
return ("degraded");
case NWAM_STATE_DISABLED:
return ("disabled");
default:
return ("unknown");
}
}
const char *
{
switch (aux_state) {
return ("uninitialized");
return ("(re)initialized but not configured");
return ("conditions for activation are unmet");
return ("disabled by administrator");
return ("method or FMRI not specified");
return ("invalid configuration values");
return ("Dynamic Reconfiguration offline");
case NWAM_AUX_STATE_DR_ONLINE:
return ("Dynamic Reconfiguration online");
case NWAM_AUX_STATE_ACTIVE:
return ("active");
return ("scanning for WiFi networks");
return ("need WiFi network selection");
return ("need WiFi security key");
return ("connecting to WiFi network");
return ("waiting for IP address to be set");
return ("DHCP wait timeout, still trying...");
return ("duplicate address detected");
return ("externally managed");
case NWAM_AUX_STATE_UP:
case NWAM_AUX_STATE_DOWN:
case NWAM_AUX_STATE_NOT_FOUND:
default:
return ("unknown");
}
}
const char *
{
switch (type) {
case NWAM_OBJECT_TYPE_NCP:
return ("ncp");
case NWAM_OBJECT_TYPE_NCU:
return ("ncu");
case NWAM_OBJECT_TYPE_LOC:
return ("loc");
case NWAM_OBJECT_TYPE_ENM:
return ("enm");
return ("known wlan");
default:
return ("unknown");
}
}
{
if (strcasecmp(typestr,
return (NWAM_OBJECT_TYPE_NCP);
if (strcasecmp(typestr,
return (NWAM_OBJECT_TYPE_NCU);
if (strcasecmp(typestr,
return (NWAM_OBJECT_TYPE_LOC);
if (strcasecmp(typestr,
return (NWAM_OBJECT_TYPE_ENM);
if (strcasecmp(typestr,
return (NWAM_OBJECT_TYPE_KNOWN_WLAN);
return (NWAM_OBJECT_TYPE_UNKNOWN);
}
{
switch (errnum) {
case 0:
return (NWAM_SUCCESS);
case EBADF:
return (NWAM_ERROR_NWAMD_BIND);
case EPERM:
case EACCES:
return (NWAM_PERMISSION_DENIED);
case ENOENT:
return (NWAM_ENTITY_NOT_FOUND);
case EIDRM:
return (NWAM_ENTITY_INVALID);
case EEXIST:
return (NWAM_ENTITY_EXISTS);
case EAGAIN:
case EBUSY:
return (NWAM_ENTITY_IN_USE);
case ENOMEM:
case ENOSPC:
return (NWAM_NO_MEMORY);
case EINVAL:
case E2BIG:
return (NWAM_INVALID_ARG);
default:
return (NWAM_ERROR_INTERNAL);
}
}
{
switch (nerr) {
case NETCFG_SUCCESS:
return (NWAM_SUCCESS);
case NETCFG_EPERM:
return (NWAM_PERMISSION_DENIED);
case NETCFG_INVALID_ARG:
return (NWAM_INVALID_ARG);
case NETCFG_EXISTS:
return (NWAM_ENTITY_EXISTS);
case NETCFG_NOT_FOUND:
return (NWAM_ENTITY_NOT_FOUND);
case NETCFG_WALK_HALTED:
return (NWAM_WALK_HALTED);
case NETCFG_ERROR_BIND:
return (NWAM_ERROR_NETCFGD_BIND);
case NETCFG_NO_MEMORY:
return (NWAM_NO_MEMORY);
case NETCFG_FAILURE:
default:
return (NWAM_ERROR_INTERNAL);
}
}
/* Common validation functions */
/*
* Do the flags represent a subset of valid_flags?
*/
{
return (NWAM_INVALID_ARG);
return (NWAM_SUCCESS);
}
{
char **conditions;
!= NWAM_SUCCESS)
return (NWAM_ENTITY_INVALID_VALUE);
for (i = 0; i < numvalues; i++) {
return (NWAM_ENTITY_INVALID_VALUE);
if (object_name != NULL)
}
return (NWAM_SUCCESS);
}
/* check if boolean values are correct, generalize for array of booleans */
{
!= NWAM_SUCCESS)
return (NWAM_ENTITY_INVALID_VALUE);
for (i = 0; i < numvalues; i++) {
return (NWAM_ENTITY_INVALID_VALUE);
}
return (NWAM_SUCCESS);
}
/* check if uint64 values are correct, generalize for array of ints */
{
!= NWAM_SUCCESS)
return (NWAM_ENTITY_INVALID_VALUE);
for (i = 0; i < numvalues; i++) {
if (val[i] < 0)
return (NWAM_ENTITY_INVALID_VALUE);
}
return (NWAM_SUCCESS);
}
/* check if domain names are correct, generalize for array of domains */
{
int len, j;
!= NWAM_SUCCESS)
return (NWAM_ENTITY_INVALID_VALUE);
for (i = 0; i < numvalues; i++) {
/*
* First and last character must be alphanumeric.
* Only '.', '-' and '_' are allowed.
*/
domain = domainvalues[i];
return (NWAM_ENTITY_INVALID_VALUE);
for (j = 0; j < len; j++) {
domain[j] != '_')
return (NWAM_ENTITY_INVALID_VALUE);
}
}
return (NWAM_SUCCESS);
}
/* check if address prefix is valid */
static nwam_error_t
{
int prefixlen;
prefix++;
return (NWAM_ENTITY_INVALID_VALUE);
}
return (NWAM_SUCCESS);
}
/* check if IPv4 addresses are correct, generalize for array of addresses */
{
!= NWAM_SUCCESS)
return (NWAM_ENTITY_INVALID_VALUE);
for (i = 0; i < numvalues; i++) {
return (NWAM_ENTITY_INVALID_VALUE);
}
/* replace '/' with '\0' */
return (NWAM_ENTITY_INVALID_VALUE);
}
}
return (NWAM_SUCCESS);
}
/* Check if IPv4 address for default route is valid */
{
char *addrvalue;
return (NWAM_ENTITY_INVALID_VALUE);
return (NWAM_ENTITY_INVALID_VALUE);
return (NWAM_SUCCESS);
}
/* check if IPv6 addresses are correct, generalize for array of addresses */
{
!= NWAM_SUCCESS)
return (NWAM_ENTITY_INVALID_VALUE);
for (i = 0; i < numvalues; i++) {
return (NWAM_ENTITY_INVALID_VALUE);
}
/* replace '/' with '\0' */
return (NWAM_ENTITY_INVALID_VALUE);
}
}
return (NWAM_SUCCESS);
}
/* Check if IPv4 address for default route is valid */
{
char *addrvalue;
return (NWAM_ENTITY_INVALID_VALUE);
return (NWAM_ENTITY_INVALID_VALUE);
return (NWAM_SUCCESS);
}
{
return (NWAM_ENTITY_INVALID_VALUE);
return (NWAM_SUCCESS);
}
{
return (NWAM_ENTITY_INVALID_VALUE);
return (NWAM_SUCCESS);
}
/* We do not validate file existence, merely that it is an absolute path. */
{
char **files;
!= NWAM_SUCCESS)
return (NWAM_ENTITY_INVALID_VALUE);
for (i = 0; i < numvalues; i++) {
int j = 0;
j++;
if (files[i][j] != '/')
return (NWAM_ENTITY_INVALID_VALUE);
}
return (NWAM_SUCCESS);
}
/*
* We do not validate existence of the object pointed to by the FMRI
* but merely ensure that it is a valid FMRI. We do this by
* using scf_handle_decode_fmri(), but ignore all errors bar
* SCF_ERROR_INVALID_ARGUMENT (which indicates the FMRI is invalid).
*/
{
char **valstr;
scf_handle_t *h = NULL;
!= NWAM_SUCCESS)
return (err);
h = scf_handle_create(SCF_VERSION);
if (h == NULL)
return (NWAM_ERROR_INTERNAL);
if (scf_handle_bind(h) != 0) {
goto out;
}
goto out;
}
for (i = 0; i < numvalues; i++) {
scf_error() != SCF_ERROR_INVALID_ARGUMENT) {
err = NWAM_SUCCESS;
continue;
}
break;
}
out:
return (err);
}
/* verifies mac-address and bssids */
{
int hwaddrlen, j;
!= NWAM_SUCCESS)
return (NWAM_ENTITY_INVALID_VALUE);
for (i = 0; i < numvalues; i++) {
j = 0;
/* validate that a-fA-F0-9 and ':' only */
while (addr[j] != 0) {
return (NWAM_ENTITY_INVALID_VALUE);
j++;
}
return (NWAM_ENTITY_INVALID_VALUE);
}
return (NWAM_SUCCESS);
}
/*
* Returns B_TRUE if libnwam should override restrictions on properties and
* objects. nwamd is allowed to override restrictions on read-only objects
* and properties by passing the NWAM_FLAG_OVERRIDE_READ_ONLY flag.
* Restrictions on objects include:
* - modifying the Automatic NCP
* - modifying "enabled" property
* - deleting the DefaultFixed location
*/
{
return ((flags & NWAM_FLAG_OVERRIDE_READ_ONLY));
}
{
scf_handle_t *h = NULL;
return (NWAM_NO_MEMORY);
scf_handle_bind(h) != 0 ||
goto out;
}
goto out;
}
/* Retrieve value from running snapshot (if present) */
}
}
out:
if (err != NWAM_SUCCESS)
return (err);
}
{
scf_handle_t *h = NULL;
int result;
scf_handle_bind(h) != 0 ||
goto out;
}
goto out;
}
goto out;
}
switch (result) {
case 1:
(void) smf_refresh_instance(fmri);
break;
case 0:
goto out;
}
goto retry;
default:
break;
}
out:
return (err);
}