/*
* 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 <errno.h>
#include <fcntl.h>
#include <libdllink.h>
#include <libintl.h>
#include <libnwam.h>
#include <locale.h>
#include <priv.h>
#include <pthread.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <libnwam.h>
#include "conditions.h"
#include "events.h"
#include "llp.h"
#include "ncp.h"
#include "objects.h"
#include "util.h"
/*
* nwamd - NetWork Auto-Magic Daemon
*/
static void nwamd_refresh(void);
static void graceful_shutdown(void);
/*
* nwamd
*
* This is the Network Auto-Magic daemon. For further high level information
* see the Network Auto-Magic project and the Approachability communities
* on opensolaris.org, nwamd(1M), and the README in the source directory.
*
* The general structure of the code is as a set of event source threads
* which feed events into the event handling thread. Some of these events
* are internal-only (e.g UPGRADE), but some also involve propogation
* to external listeners (who register via a door call into the daemon).
*
* signal management
* Due to being threaded, a simple set of signal handlers would not work
* very well for nwamd. Instead nwamd blocks signals in all but the
* signal handling thread at startup.
*
*/
/*
* In this file there are several utility functions which might otherwise
* belong in util.c, but since they are only called from main(), they can
* live here as static functions:
* - nlog set-up
* - daemonizing
* - looking up SMF(5) properties
* - signal handling
* - managing privileges(5)
*/
static void
start_logging(void)
{
}
static void
daemonize(void)
{
/*
* A little bit of magic here. By the first fork+setsid, we
* disconnect from our current controlling terminal and become
* a session group leader. By forking again without calling
* setsid again, we make certain that we are not the session
* group leader and can never reacquire a controlling terminal.
*/
pfail("fork 1 failed");
if (pid != 0) {
_exit(0);
}
pfail("setsid");
pfail("fork 2 failed");
if (pid != 0) {
_exit(0);
}
(void) chdir("/");
(void) umask(022);
}
/* ARGSUSED */
static void *
{
int sig;
while (!shutting_down) {
switch (sig) {
case SIGTHAW:
case SIGHUP:
/*
* Resumed from suspend or refresh. Clear up all
* objects so their states start from scratch;
* then refresh().
*/
break;
case SIGUSR1:
/*
* Undocumented "log ncu list" signal.
*/
break;
case SIGTERM:
break;
default:
break;
}
}
return (NULL);
}
static void
init_signalhandling(void)
{
int err;
(void) pthread_attr_init(&attr);
} else {
}
(void) pthread_attr_destroy(&attr);
}
/*
* Construct the set of signals that we explicitly want to deal with.
* We block these while we're still single-threaded; this block will
* be inherited by all the threads we create. When we are ready to
* start handling signals, we will start the signal handling thread,
* which will sigwait() this same set of signals, and will thus receive
* and handle any that are sent to the process.
*/
static void
block_signals(void)
{
(void) sigemptyset(&sigwaitset);
}
/*
* Look up nwamd property values and set daemon variables appropriately.
* This function will be called on startup and via the signal handling
* thread on receiving a HUP (which occurs when the nwam service is
* refreshed).
*/
static void
lookup_daemon_properties(void)
{
char *active_ncp_tmp;
char *scan_level_tmp;
(void) pthread_mutex_lock(&active_ncp_mutex);
} else {
}
(void) pthread_mutex_unlock(&active_ncp_mutex);
&condition_check_interval) != 0)
NWAM_MAX_NAME_LEN) != 0) {
} else {
}
OUR_NCU_WAIT_TIME_PROP_NAME, &ncu_wait_time) != 0)
}
/*
* Re-read the SMF properties.
* Reset ncu priority group (since the NCUs will have to walk
* through their state machines again) and schedule a check
* Re-read objects from libnwam.
* Also, run condition checking for locations and ENMs.
*/
static void
nwamd_refresh(void)
{
(void) pthread_mutex_lock(&active_ncp_mutex);
(void) pthread_mutex_unlock(&active_ncp_mutex);
}
static void
graceful_shutdown(void)
{
pfail("nwamd could not create shutdown event, exiting");
}
int
{
int c;
/*
* Block the signals we care about (and which might cause us to
* exit based on default disposition) until we're ready to start
* handling them properly...see init_signalhandling() below.
*/
/*
* This shouldn't happen normally. On upgrade the service might
* need reloading.
*/
uid);
}
(void) textdomain(TEXT_DOMAIN);
switch (c) {
case 'f':
break;
default:
optopt);
break;
}
}
if (!fg)
daemonize();
/*
* The dladm handle *must* be opened before privileges are dropped.
* The device privilege requirements, which are stored in
* /etc/security/device_policy, may not be loaded yet, as that's
* done by svc:/system/filesystem/root. If they are not loaded,
* is one of the steps performed in dladm_open().
*/
if (drc != DLADM_STATUS_OK) {
pfail("failed to open dladm handle: %s",
}
if (irc != IPADM_SUCCESS)
/*
* Create the event queue before starting event sources, including
* signal handling, so we are ready to handle incoming events. Also
* start before attempting to upgrade, in case there's a problem
* upgrading and we need to retry (in which case we schedule an event
* to do so).
*/
/*
* Handle upgrade of legacy config. Absence of version property
* (which did not exist in phase 0 or 0.5) is the indication that
* we need to upgrade to phase 1 (version 1).
*/
&version) != 0)
/*
* Initialize lists handling internal representations of objects.
*/
/* Enqueue init event */
pfail("nwamd could not create init event, exiting");
/*
* Collect initial user configuration.
*/
/*
* Walk the physical interfaces and update the Automatic NCP to
* contain the IP and link NCUs for the interfaces that exist in
* the system.
*/
/*
* We should initialize the door at the point that we can respond to
* user requests about the system but before we start actually process
* state changes or effecting the system.
*/
/*
* Initialize data objects.
*
* Enabling an NCP involves refreshing nwam, which initializes the
* objects (ncu, enm, loc, known wlan). Thus, no need to
* explicitly initialize these objects here. The refresh also
* enqueues and NCU activation checking event. Location and ENM
* condition checking are triggered by changes in NCU states.
*/
(void) pthread_mutex_lock(&active_ncp_mutex);
(void) pthread_mutex_unlock(&active_ncp_mutex);
/*
* Enqueue an event to start periodic checking of activation conditions.
*/
/*
* These two routines safely minimize our privilege set. They
* use reference counting to be safe in a threaded program. It is
* gross that we escalate/deescalate to initialize this functionality
* but a real fix is to add functionality to do fine grained privs
* (and if necessary set uid to 0) in this threaded daemon.
*/
/*
* Start the various agents (hooks on fds, threads) which collect events
*/
/*
* nwamd_event_handler() only returns on shutdown.
*/
return (EXIT_SUCCESS);
}