1d71dbb73Sjbeck /* 2d71dbb73Sjbeck * CDDL HEADER START 3d71dbb73Sjbeck * 4d71dbb73Sjbeck * The contents of this file are subject to the terms of the 5d71dbb73Sjbeck * Common Development and Distribution License (the "License"). 6d71dbb73Sjbeck * You may not use this file except in compliance with the License. 7d71dbb73Sjbeck * 8d71dbb73Sjbeck * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9d71dbb73Sjbeck * or http://www.opensolaris.org/os/licensing. 10d71dbb73Sjbeck * See the License for the specific language governing permissions 11d71dbb73Sjbeck * and limitations under the License. 12d71dbb73Sjbeck * 13d71dbb73Sjbeck * When distributing Covered Code, include this CDDL HEADER in each 14d71dbb73Sjbeck * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15d71dbb73Sjbeck * If applicable, add the following below this CDDL HEADER, with the 16d71dbb73Sjbeck * fields enclosed by brackets "[]" replaced with your own identifying 17d71dbb73Sjbeck * information: Portions Copyright [yyyy] [name of copyright owner] 18d71dbb73Sjbeck * 19d71dbb73Sjbeck * CDDL HEADER END 20d71dbb73Sjbeck */ 21d71dbb73Sjbeck 22d71dbb73Sjbeck /* 2371ed50cfSAnurag S. Maskey * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. 24d71dbb73Sjbeck */ 25d71dbb73Sjbeck 266ba597c5SAnurag S. Maskey #include <errno.h> 276ba597c5SAnurag S. Maskey #include <fcntl.h> 286ba597c5SAnurag S. Maskey #include <libdllink.h> 296ba597c5SAnurag S. Maskey #include <libintl.h> 306ba597c5SAnurag S. Maskey #include <libnwam.h> 316ba597c5SAnurag S. Maskey #include <locale.h> 326ba597c5SAnurag S. Maskey #include <priv.h> 336ba597c5SAnurag S. Maskey #include <pthread.h> 346ba597c5SAnurag S. Maskey #include <signal.h> 356ba597c5SAnurag S. Maskey #include <stdio.h> 366ba597c5SAnurag S. Maskey #include <stdlib.h> 376ba597c5SAnurag S. Maskey #include <string.h> 386ba597c5SAnurag S. Maskey #include <sys/stat.h> 396ba597c5SAnurag S. Maskey #include <sys/types.h> 406ba597c5SAnurag S. Maskey #include <sys/wait.h> 416ba597c5SAnurag S. Maskey #include <unistd.h> 426ba597c5SAnurag S. Maskey 436ba597c5SAnurag S. Maskey #include <libnwam.h> 446ba597c5SAnurag S. Maskey #include "conditions.h" 456ba597c5SAnurag S. Maskey #include "events.h" 466ba597c5SAnurag S. Maskey #include "llp.h" 476ba597c5SAnurag S. Maskey #include "ncp.h" 486ba597c5SAnurag S. Maskey #include "objects.h" 496ba597c5SAnurag S. Maskey #include "util.h" 506ba597c5SAnurag S. Maskey 51d71dbb73Sjbeck /* 52d71dbb73Sjbeck * nwamd - NetWork Auto-Magic Daemon 53d71dbb73Sjbeck */ 54d71dbb73Sjbeck 55d71dbb73Sjbeck boolean_t fg = B_FALSE; 566ba597c5SAnurag S. Maskey dladm_handle_t dld_handle = NULL; 57*f6da83d4SAnurag S. Maskey ipadm_handle_t ipadm_handle = NULL; 586ba597c5SAnurag S. Maskey boolean_t shutting_down = B_FALSE; 596ba597c5SAnurag S. Maskey 60d71dbb73Sjbeck sigset_t original_sigmask; 618b2954c8SRenee Danson Sommerfeld static sigset_t sigwaitset; 626ba597c5SAnurag S. Maskey 636ba597c5SAnurag S. Maskey static void nwamd_refresh(void); 646ba597c5SAnurag S. Maskey static void graceful_shutdown(void); 65d71dbb73Sjbeck 66d71dbb73Sjbeck /* 67d71dbb73Sjbeck * nwamd 68d71dbb73Sjbeck * 69d71dbb73Sjbeck * This is the Network Auto-Magic daemon. For further high level information 70d71dbb73Sjbeck * see the Network Auto-Magic project and the Approachability communities 716ba597c5SAnurag S. Maskey * on opensolaris.org, nwamd(1M), and the README in the source directory. 72d71dbb73Sjbeck * 736ba597c5SAnurag S. Maskey * The general structure of the code is as a set of event source threads 746ba597c5SAnurag S. Maskey * which feed events into the event handling thread. Some of these events 756ba597c5SAnurag S. Maskey * are internal-only (e.g UPGRADE), but some also involve propogation 766ba597c5SAnurag S. Maskey * to external listeners (who register via a door call into the daemon). 77d71dbb73Sjbeck * 78d71dbb73Sjbeck * signal management 79d71dbb73Sjbeck * Due to being threaded, a simple set of signal handlers would not work 806ba597c5SAnurag S. Maskey * very well for nwamd. Instead nwamd blocks signals in all but the 816ba597c5SAnurag S. Maskey * signal handling thread at startup. 82d71dbb73Sjbeck * 83d71dbb73Sjbeck */ 84d71dbb73Sjbeck 85d71dbb73Sjbeck /* 86d71dbb73Sjbeck * In this file there are several utility functions which might otherwise 87d71dbb73Sjbeck * belong in util.c, but since they are only called from main(), they can 88d71dbb73Sjbeck * live here as static functions: 896ba597c5SAnurag S. Maskey * - nlog set-up 90d71dbb73Sjbeck * - daemonizing 91d71dbb73Sjbeck * - looking up SMF(5) properties 92d71dbb73Sjbeck * - signal handling 93d71dbb73Sjbeck * - managing privileges(5) 94d71dbb73Sjbeck */ 95d71dbb73Sjbeck 96d71dbb73Sjbeck static void 97d71dbb73Sjbeck start_logging(void) 98d71dbb73Sjbeck { 99d71dbb73Sjbeck openlog("nwamd", LOG_PID | LOG_NDELAY, LOG_DAEMON); 100d71dbb73Sjbeck } 101d71dbb73Sjbeck 102d71dbb73Sjbeck static void 103d71dbb73Sjbeck daemonize(void) 104d71dbb73Sjbeck { 105d71dbb73Sjbeck pid_t pid; 106d71dbb73Sjbeck 107d71dbb73Sjbeck /* 108d71dbb73Sjbeck * A little bit of magic here. By the first fork+setsid, we 109d71dbb73Sjbeck * disconnect from our current controlling terminal and become 110d71dbb73Sjbeck * a session group leader. By forking again without calling 111d71dbb73Sjbeck * setsid again, we make certain that we are not the session 112d71dbb73Sjbeck * group leader and can never reacquire a controlling terminal. 113d71dbb73Sjbeck */ 1146ba597c5SAnurag S. Maskey if ((pid = fork()) == (pid_t)-1) 1156ba597c5SAnurag S. Maskey pfail("fork 1 failed"); 116d71dbb73Sjbeck if (pid != 0) { 117d71dbb73Sjbeck (void) wait(NULL); 1186ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "child %ld exited, daemonizing", pid); 119d71dbb73Sjbeck _exit(0); 120d71dbb73Sjbeck } 1216ba597c5SAnurag S. Maskey if (setsid() == (pid_t)-1) 1226ba597c5SAnurag S. Maskey pfail("setsid"); 1236ba597c5SAnurag S. Maskey if ((pid = fork()) == (pid_t)-1) 1246ba597c5SAnurag S. Maskey pfail("fork 2 failed"); 125d71dbb73Sjbeck if (pid != 0) { 126d71dbb73Sjbeck _exit(0); 127d71dbb73Sjbeck } 128d71dbb73Sjbeck (void) chdir("/"); 129d71dbb73Sjbeck (void) umask(022); 130d71dbb73Sjbeck } 131d71dbb73Sjbeck 132d71dbb73Sjbeck /* ARGSUSED */ 133d71dbb73Sjbeck static void * 134d71dbb73Sjbeck sighandler(void *arg) 135d71dbb73Sjbeck { 1366ba597c5SAnurag S. Maskey int sig; 137d71dbb73Sjbeck 138b00044a2SJames Carlson while (!shutting_down) { 1398b2954c8SRenee Danson Sommerfeld sig = sigwait(&sigwaitset); 1406ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "signal %s caught", strsignal(sig)); 1416ba597c5SAnurag S. Maskey 1426ba597c5SAnurag S. Maskey switch (sig) { 1436ba597c5SAnurag S. Maskey case SIGTHAW: 144d71dbb73Sjbeck case SIGHUP: 145d71dbb73Sjbeck /* 1466ba597c5SAnurag S. Maskey * Resumed from suspend or refresh. Clear up all 1476ba597c5SAnurag S. Maskey * objects so their states start from scratch; 1486ba597c5SAnurag S. Maskey * then refresh(). 149d71dbb73Sjbeck */ 1506ba597c5SAnurag S. Maskey nwamd_fini_enms(); 1516ba597c5SAnurag S. Maskey nwamd_fini_ncus(); 1526ba597c5SAnurag S. Maskey nwamd_fini_locs(); 1536ba597c5SAnurag S. Maskey nwamd_refresh(); 154d71dbb73Sjbeck break; 1556ba597c5SAnurag S. Maskey case SIGUSR1: 156b00044a2SJames Carlson /* 1576ba597c5SAnurag S. Maskey * Undocumented "log ncu list" signal. 158b00044a2SJames Carlson */ 1596ba597c5SAnurag S. Maskey nwamd_log_ncus(); 160ab32bdf2SJames Carlson break; 1618b2954c8SRenee Danson Sommerfeld case SIGTERM: 1626ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "%s received, shutting down", 163d71dbb73Sjbeck strsignal(sig)); 1646ba597c5SAnurag S. Maskey graceful_shutdown(); 165d71dbb73Sjbeck break; 1668b2954c8SRenee Danson Sommerfeld default: 1676ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "unexpected signal %s received, " 1688b2954c8SRenee Danson Sommerfeld "ignoring", strsignal(sig)); 1698b2954c8SRenee Danson Sommerfeld break; 170d71dbb73Sjbeck } 171d71dbb73Sjbeck } 172b00044a2SJames Carlson return (NULL); 173d71dbb73Sjbeck } 174d71dbb73Sjbeck 175d71dbb73Sjbeck static void 176d71dbb73Sjbeck init_signalhandling(void) 177d71dbb73Sjbeck { 178d71dbb73Sjbeck pthread_attr_t attr; 179d71dbb73Sjbeck pthread_t sighand; 180d71dbb73Sjbeck int err; 181d71dbb73Sjbeck 182d71dbb73Sjbeck (void) pthread_attr_init(&attr); 183d71dbb73Sjbeck (void) pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 184d71dbb73Sjbeck if (err = pthread_create(&sighand, &attr, sighandler, NULL)) { 1856ba597c5SAnurag S. Maskey nlog(LOG_ERR, "pthread_create system: %s", strerror(err)); 186d71dbb73Sjbeck exit(EXIT_FAILURE); 187d71dbb73Sjbeck } else { 1886ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "signal handler thread: %d", sighand); 189d71dbb73Sjbeck } 190d71dbb73Sjbeck (void) pthread_attr_destroy(&attr); 191d71dbb73Sjbeck } 192d71dbb73Sjbeck 1936ba597c5SAnurag S. Maskey /* 1946ba597c5SAnurag S. Maskey * Construct the set of signals that we explicitly want to deal with. 1956ba597c5SAnurag S. Maskey * We block these while we're still single-threaded; this block will 1966ba597c5SAnurag S. Maskey * be inherited by all the threads we create. When we are ready to 1976ba597c5SAnurag S. Maskey * start handling signals, we will start the signal handling thread, 1986ba597c5SAnurag S. Maskey * which will sigwait() this same set of signals, and will thus receive 1996ba597c5SAnurag S. Maskey * and handle any that are sent to the process. 2006ba597c5SAnurag S. Maskey */ 201d71dbb73Sjbeck static void 2026ba597c5SAnurag S. Maskey block_signals(void) 203d71dbb73Sjbeck { 2046ba597c5SAnurag S. Maskey (void) sigemptyset(&sigwaitset); 2056ba597c5SAnurag S. Maskey (void) sigaddset(&sigwaitset, SIGHUP); 2066ba597c5SAnurag S. Maskey (void) sigaddset(&sigwaitset, SIGUSR1); 2076ba597c5SAnurag S. Maskey (void) sigaddset(&sigwaitset, SIGUSR2); 2086ba597c5SAnurag S. Maskey (void) sigaddset(&sigwaitset, SIGTERM); 2096ba597c5SAnurag S. Maskey (void) sigaddset(&sigwaitset, SIGTHAW); 2106ba597c5SAnurag S. Maskey (void) pthread_sigmask(SIG_BLOCK, &sigwaitset, &original_sigmask); 2116ba597c5SAnurag S. Maskey } 212d71dbb73Sjbeck 2136ba597c5SAnurag S. Maskey /* 2146ba597c5SAnurag S. Maskey * Look up nwamd property values and set daemon variables appropriately. 2156ba597c5SAnurag S. Maskey * This function will be called on startup and via the signal handling 2166ba597c5SAnurag S. Maskey * thread on receiving a HUP (which occurs when the nwam service is 2176ba597c5SAnurag S. Maskey * refreshed). 2186ba597c5SAnurag S. Maskey */ 2196ba597c5SAnurag S. Maskey static void 2206ba597c5SAnurag S. Maskey lookup_daemon_properties(void) 2216ba597c5SAnurag S. Maskey { 2226ba597c5SAnurag S. Maskey char *active_ncp_tmp; 2236ba597c5SAnurag S. Maskey char *scan_level_tmp; 2246ba597c5SAnurag S. Maskey 2256ba597c5SAnurag S. Maskey (void) nwamd_lookup_boolean_property(OUR_FMRI, OUR_PG, 2266ba597c5SAnurag S. Maskey OUR_DEBUG_PROP_NAME, &debug); 2276ba597c5SAnurag S. Maskey (void) nwamd_lookup_boolean_property(OUR_FMRI, OUR_PG, 2286ba597c5SAnurag S. Maskey OUR_AUTOCONF_PROP_NAME, &wireless_autoconf); 2296ba597c5SAnurag S. Maskey (void) nwamd_lookup_boolean_property(OUR_FMRI, OUR_PG, 2306ba597c5SAnurag S. Maskey OUR_STRICT_BSSID_PROP_NAME, &wireless_strict_bssid); 2316ba597c5SAnurag S. Maskey 2326ba597c5SAnurag S. Maskey (void) pthread_mutex_lock(&active_ncp_mutex); 2336ba597c5SAnurag S. Maskey if ((active_ncp_tmp = malloc(NWAM_MAX_NAME_LEN)) == NULL || 2346ba597c5SAnurag S. Maskey nwamd_lookup_string_property(OUR_FMRI, OUR_PG, 2356ba597c5SAnurag S. Maskey OUR_ACTIVE_NCP_PROP_NAME, active_ncp_tmp, NWAM_MAX_NAME_LEN) != 0) { 2366ba597c5SAnurag S. Maskey (void) strlcpy(active_ncp, NWAM_NCP_NAME_AUTOMATIC, 2376ba597c5SAnurag S. Maskey NWAM_MAX_NAME_LEN); 238d71dbb73Sjbeck } else { 2396ba597c5SAnurag S. Maskey (void) strlcpy(active_ncp, active_ncp_tmp, NWAM_MAX_NAME_LEN); 2406ba597c5SAnurag S. Maskey } 2416ba597c5SAnurag S. Maskey (void) pthread_mutex_unlock(&active_ncp_mutex); 2426ba597c5SAnurag S. Maskey free(active_ncp_tmp); 243d71dbb73Sjbeck 2446ba597c5SAnurag S. Maskey if (nwamd_lookup_count_property(OUR_FMRI, OUR_PG, 2456ba597c5SAnurag S. Maskey OUR_CONDITION_CHECK_INTERVAL_PROP_NAME, 2466ba597c5SAnurag S. Maskey &condition_check_interval) != 0) 2476ba597c5SAnurag S. Maskey condition_check_interval = CONDITION_CHECK_INTERVAL_DEFAULT; 2486ba597c5SAnurag S. Maskey 2496ba597c5SAnurag S. Maskey if ((scan_level_tmp = malloc(NWAM_MAX_NAME_LEN)) == NULL || 2506ba597c5SAnurag S. Maskey nwamd_lookup_string_property(OUR_FMRI, OUR_PG, 2516ba597c5SAnurag S. Maskey OUR_WIRELESS_SCAN_LEVEL_PROP_NAME, scan_level_tmp, 2526ba597c5SAnurag S. Maskey NWAM_MAX_NAME_LEN) != 0) { 2536ba597c5SAnurag S. Maskey wireless_scan_level = WIRELESS_SCAN_LEVEL_DEFAULT; 2546ba597c5SAnurag S. Maskey } else { 2556ba597c5SAnurag S. Maskey if (dladm_wlan_str2strength(scan_level_tmp, 2566ba597c5SAnurag S. Maskey &wireless_scan_level) != DLADM_STATUS_OK) 2576ba597c5SAnurag S. Maskey wireless_scan_level = DLADM_WLAN_STRENGTH_VERY_WEAK; 2586ba597c5SAnurag S. Maskey } 2596ba597c5SAnurag S. Maskey free(scan_level_tmp); 2606ba597c5SAnurag S. Maskey 2616ba597c5SAnurag S. Maskey if (nwamd_lookup_count_property(OUR_FMRI, OUR_PG, 2626ba597c5SAnurag S. Maskey OUR_WIRELESS_SCAN_INTERVAL_PROP_NAME, &wireless_scan_interval) != 0) 2636ba597c5SAnurag S. Maskey wireless_scan_interval = WIRELESS_SCAN_INTERVAL_DEFAULT; 2646ba597c5SAnurag S. Maskey 2656ba597c5SAnurag S. Maskey if (nwamd_lookup_count_property(OUR_FMRI, OUR_PG, 2666ba597c5SAnurag S. Maskey OUR_NCU_WAIT_TIME_PROP_NAME, &ncu_wait_time) != 0) 2676ba597c5SAnurag S. Maskey ncu_wait_time = NCU_WAIT_TIME_DEFAULT; 2686ba597c5SAnurag S. Maskey 2696ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "Read daemon configuration properties."); 270d71dbb73Sjbeck } 271d71dbb73Sjbeck 2726ba597c5SAnurag S. Maskey /* 2736ba597c5SAnurag S. Maskey * Re-read the SMF properties. 2746ba597c5SAnurag S. Maskey * Reset ncu priority group (since the NCUs will have to walk 2756ba597c5SAnurag S. Maskey * through their state machines again) and schedule a check 2766ba597c5SAnurag S. Maskey * Re-read objects from libnwam. 2776ba597c5SAnurag S. Maskey * Also, run condition checking for locations and ENMs. 2786ba597c5SAnurag S. Maskey */ 2796ba597c5SAnurag S. Maskey static void 2806ba597c5SAnurag S. Maskey nwamd_refresh(void) 2816ba597c5SAnurag S. Maskey { 2826ba597c5SAnurag S. Maskey lookup_daemon_properties(); 283d71dbb73Sjbeck 2846ba597c5SAnurag S. Maskey (void) pthread_mutex_lock(&active_ncp_mutex); 2856ba597c5SAnurag S. Maskey current_ncu_priority_group = INVALID_PRIORITY_GROUP; 2866ba597c5SAnurag S. Maskey (void) pthread_mutex_unlock(&active_ncp_mutex); 287d71dbb73Sjbeck 2886ba597c5SAnurag S. Maskey nwamd_init_ncus(); 2896ba597c5SAnurag S. Maskey nwamd_init_enms(); 2906ba597c5SAnurag S. Maskey nwamd_init_locs(); 291d71dbb73Sjbeck 2926ba597c5SAnurag S. Maskey nwamd_create_ncu_check_event(0); 2936ba597c5SAnurag S. Maskey nwamd_create_triggered_condition_check_event(0); 294d71dbb73Sjbeck } 295d71dbb73Sjbeck 296b00044a2SJames Carlson static void 2976ba597c5SAnurag S. Maskey graceful_shutdown(void) 298b00044a2SJames Carlson { 2996ba597c5SAnurag S. Maskey nwamd_event_t event; 300b00044a2SJames Carlson 3016ba597c5SAnurag S. Maskey shutting_down = B_TRUE; 3026ba597c5SAnurag S. Maskey nwamd_event_sources_fini(); 3036ba597c5SAnurag S. Maskey nwamd_door_fini(); 3046ba597c5SAnurag S. Maskey nwamd_fini_enms(); 3056ba597c5SAnurag S. Maskey nwamd_fini_ncus(); 3066ba597c5SAnurag S. Maskey nwamd_fini_locs(); 3076ba597c5SAnurag S. Maskey 3086ba597c5SAnurag S. Maskey event = nwamd_event_init_shutdown(); 3096ba597c5SAnurag S. Maskey if (event == NULL) 3106ba597c5SAnurag S. Maskey pfail("nwamd could not create shutdown event, exiting"); 3116ba597c5SAnurag S. Maskey nwamd_event_enqueue(event); 312b00044a2SJames Carlson } 313b00044a2SJames Carlson 314d71dbb73Sjbeck int 315d71dbb73Sjbeck main(int argc, char *argv[]) 316d71dbb73Sjbeck { 317d71dbb73Sjbeck int c; 3186ba597c5SAnurag S. Maskey uint64_t version; 3196ba597c5SAnurag S. Maskey nwamd_event_t event; 320*f6da83d4SAnurag S. Maskey dladm_status_t drc; 321*f6da83d4SAnurag S. Maskey ipadm_status_t irc; 3226ba597c5SAnurag S. Maskey uid_t uid = getuid(); 3236ba597c5SAnurag S. Maskey 3246ba597c5SAnurag S. Maskey /* 3256ba597c5SAnurag S. Maskey * Block the signals we care about (and which might cause us to 3266ba597c5SAnurag S. Maskey * exit based on default disposition) until we're ready to start 3276ba597c5SAnurag S. Maskey * handling them properly...see init_signalhandling() below. 3286ba597c5SAnurag S. Maskey */ 3296ba597c5SAnurag S. Maskey block_signals(); 3306ba597c5SAnurag S. Maskey 33169b43529SMichael Hunter if (uid != UID_NETADM && uid != 0) { 3326ba597c5SAnurag S. Maskey /* 3336ba597c5SAnurag S. Maskey * This shouldn't happen normally. On upgrade the service might 3346ba597c5SAnurag S. Maskey * need reloading. 3356ba597c5SAnurag S. Maskey */ 3366ba597c5SAnurag S. Maskey pfail("nwamd should run as uid %d, not uid %d\n", UID_NETADM, 3376ba597c5SAnurag S. Maskey uid); 3386ba597c5SAnurag S. Maskey } 339d71dbb73Sjbeck 340d71dbb73Sjbeck (void) setlocale(LC_ALL, ""); 341d71dbb73Sjbeck (void) textdomain(TEXT_DOMAIN); 342d71dbb73Sjbeck 343d71dbb73Sjbeck start_logging(); 3446ba597c5SAnurag S. Maskey nlog(LOG_INFO, "nwamd pid %d started", getpid()); 345d71dbb73Sjbeck 346d71dbb73Sjbeck while ((c = getopt(argc, argv, "fs:")) != -1) { 347d71dbb73Sjbeck switch (c) { 348d71dbb73Sjbeck case 'f': 349d71dbb73Sjbeck fg = B_TRUE; 350d71dbb73Sjbeck break; 351d71dbb73Sjbeck default: 3526ba597c5SAnurag S. Maskey nlog(LOG_ERR, "unrecognized option %c", 353d71dbb73Sjbeck optopt); 354d71dbb73Sjbeck break; 355d71dbb73Sjbeck } 356d71dbb73Sjbeck } 357d71dbb73Sjbeck 358d71dbb73Sjbeck lookup_daemon_properties(); 359d71dbb73Sjbeck 360d71dbb73Sjbeck if (!fg) 361d71dbb73Sjbeck daemonize(); 362d71dbb73Sjbeck 3636ba597c5SAnurag S. Maskey /* 3646ba597c5SAnurag S. Maskey * The dladm handle *must* be opened before privileges are dropped. 3656ba597c5SAnurag S. Maskey * The device privilege requirements, which are stored in 3666ba597c5SAnurag S. Maskey * /etc/security/device_policy, may not be loaded yet, as that's 3676ba597c5SAnurag S. Maskey * done by svc:/system/filesystem/root. If they are not loaded, 3686ba597c5SAnurag S. Maskey * then one must have *all* privs in order to open /dev/dld, which 3696ba597c5SAnurag S. Maskey * is one of the steps performed in dladm_open(). 3706ba597c5SAnurag S. Maskey */ 371*f6da83d4SAnurag S. Maskey drc = dladm_open(&dld_handle); 372*f6da83d4SAnurag S. Maskey if (drc != DLADM_STATUS_OK) { 3736ba597c5SAnurag S. Maskey char status_str[DLADM_STRSIZE]; 374*f6da83d4SAnurag S. Maskey pfail("failed to open dladm handle: %s", 375*f6da83d4SAnurag S. Maskey dladm_status2str(drc, status_str)); 3766ba597c5SAnurag S. Maskey } 3776ba597c5SAnurag S. Maskey 378*f6da83d4SAnurag S. Maskey irc = ipadm_open(&ipadm_handle, 0); 379*f6da83d4SAnurag S. Maskey if (irc != IPADM_SUCCESS) 380*f6da83d4SAnurag S. Maskey pfail("failed to open ipadm handle: %s", ipadm_status2str(irc)); 381*f6da83d4SAnurag S. Maskey 3826ba597c5SAnurag S. Maskey /* 38371ed50cfSAnurag S. Maskey * Create the event queue before starting event sources, including 38471ed50cfSAnurag S. Maskey * signal handling, so we are ready to handle incoming events. Also 38571ed50cfSAnurag S. Maskey * start before attempting to upgrade, in case there's a problem 38671ed50cfSAnurag S. Maskey * upgrading and we need to retry (in which case we schedule an event 38771ed50cfSAnurag S. Maskey * to do so). 38871ed50cfSAnurag S. Maskey */ 38971ed50cfSAnurag S. Maskey nwamd_event_queue_init(); 39071ed50cfSAnurag S. Maskey 39171ed50cfSAnurag S. Maskey /* 3926ba597c5SAnurag S. Maskey * Handle upgrade of legacy config. Absence of version property 3936ba597c5SAnurag S. Maskey * (which did not exist in phase 0 or 0.5) is the indication that 3946ba597c5SAnurag S. Maskey * we need to upgrade to phase 1 (version 1). 3956ba597c5SAnurag S. Maskey */ 3966ba597c5SAnurag S. Maskey if (nwamd_lookup_count_property(OUR_FMRI, OUR_PG, OUR_VERSION_PROP_NAME, 3976ba597c5SAnurag S. Maskey &version) != 0) 3986ba597c5SAnurag S. Maskey nwamd_handle_upgrade(NULL); 3996ba597c5SAnurag S. Maskey 4006ba597c5SAnurag S. Maskey /* 4016ba597c5SAnurag S. Maskey * Initialize lists handling internal representations of objects. 4026ba597c5SAnurag S. Maskey */ 4036ba597c5SAnurag S. Maskey nwamd_object_lists_init(); 4046ba597c5SAnurag S. Maskey 405d71dbb73Sjbeck init_signalhandling(); 406d71dbb73Sjbeck 4076ba597c5SAnurag S. Maskey /* Enqueue init event */ 4086ba597c5SAnurag S. Maskey event = nwamd_event_init_init(); 4096ba597c5SAnurag S. Maskey if (event == NULL) 4106ba597c5SAnurag S. Maskey pfail("nwamd could not create init event, exiting"); 4116ba597c5SAnurag S. Maskey nwamd_event_enqueue(event); 41271ed50cfSAnurag S. Maskey 4136ba597c5SAnurag S. Maskey /* 4146ba597c5SAnurag S. Maskey * Collect initial user configuration. 4156ba597c5SAnurag S. Maskey */ 416d71dbb73Sjbeck 4176ba597c5SAnurag S. Maskey /* 4186ba597c5SAnurag S. Maskey * Walk the physical interfaces and update the Automatic NCP to 4196ba597c5SAnurag S. Maskey * contain the IP and link NCUs for the interfaces that exist in 4206ba597c5SAnurag S. Maskey * the system. 4216ba597c5SAnurag S. Maskey */ 4226ba597c5SAnurag S. Maskey nwamd_walk_physical_configuration(); 423d71dbb73Sjbeck 4246ba597c5SAnurag S. Maskey /* 4256ba597c5SAnurag S. Maskey * We should initialize the door at the point that we can respond to 4266ba597c5SAnurag S. Maskey * user requests about the system but before we start actually process 4276ba597c5SAnurag S. Maskey * state changes or effecting the system. 4286ba597c5SAnurag S. Maskey */ 4296ba597c5SAnurag S. Maskey nwamd_door_init(); 430b00044a2SJames Carlson 4316ba597c5SAnurag S. Maskey /* 4326ba597c5SAnurag S. Maskey * Initialize data objects. 4336ba597c5SAnurag S. Maskey * 4346ba597c5SAnurag S. Maskey * Enabling an NCP involves refreshing nwam, which initializes the 4356ba597c5SAnurag S. Maskey * objects (ncu, enm, loc, known wlan). Thus, no need to 4366ba597c5SAnurag S. Maskey * explicitly initialize these objects here. The refresh also 4376ba597c5SAnurag S. Maskey * enqueues and NCU activation checking event. Location and ENM 4386ba597c5SAnurag S. Maskey * condition checking are triggered by changes in NCU states. 4396ba597c5SAnurag S. Maskey */ 4406ba597c5SAnurag S. Maskey (void) pthread_mutex_lock(&active_ncp_mutex); 4416ba597c5SAnurag S. Maskey if (nwamd_ncp_action(active_ncp, NWAM_ACTION_ENABLE) != 0) 4426ba597c5SAnurag S. Maskey pfail("Initial enable failed for active NCP %s", active_ncp); 4436ba597c5SAnurag S. Maskey (void) pthread_mutex_unlock(&active_ncp_mutex); 444d71dbb73Sjbeck 4456ba597c5SAnurag S. Maskey /* 4466ba597c5SAnurag S. Maskey * Enqueue an event to start periodic checking of activation conditions. 4476ba597c5SAnurag S. Maskey */ 4486ba597c5SAnurag S. Maskey nwamd_create_timed_condition_check_event(); 449d71dbb73Sjbeck 45038f140aaSMichael Hunter /* 45138f140aaSMichael Hunter * These two routines safely minimize our privilege set. They 45238f140aaSMichael Hunter * use reference counting to be safe in a threaded program. It is 45338f140aaSMichael Hunter * gross that we escalate/deescalate to initialize this functionality 45438f140aaSMichael Hunter * but a real fix is to add functionality to do fine grained privs 45538f140aaSMichael Hunter * (and if necessary set uid to 0) in this threaded daemon. 45638f140aaSMichael Hunter */ 45738f140aaSMichael Hunter nwamd_escalate(); 45838f140aaSMichael Hunter nwamd_deescalate(); 45938f140aaSMichael Hunter 4606ba597c5SAnurag S. Maskey /* 4616ba597c5SAnurag S. Maskey * Start the various agents (hooks on fds, threads) which collect events 4626ba597c5SAnurag S. Maskey */ 4636ba597c5SAnurag S. Maskey nwamd_event_sources_init(); 464b00044a2SJames Carlson 4656ba597c5SAnurag S. Maskey /* 4666ba597c5SAnurag S. Maskey * nwamd_event_handler() only returns on shutdown. 4676ba597c5SAnurag S. Maskey */ 4686ba597c5SAnurag S. Maskey nwamd_event_handler(); 469d71dbb73Sjbeck 470*f6da83d4SAnurag S. Maskey ipadm_close(ipadm_handle); 4714ac67f02SAnurag S. Maskey dladm_close(dld_handle); 4726ba597c5SAnurag S. Maskey 473b00044a2SJames Carlson return (EXIT_SUCCESS); 474d71dbb73Sjbeck } 475