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 /* 23634e26ecSCasper H.S. Dik * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 24d71dbb73Sjbeck * Use is subject to license terms. 25d71dbb73Sjbeck */ 26d71dbb73Sjbeck 276ba597c5SAnurag S. Maskey #include <errno.h> 286ba597c5SAnurag S. Maskey #include <fcntl.h> 296ba597c5SAnurag S. Maskey #include <inetcfg.h> 306ba597c5SAnurag S. Maskey #include <libdllink.h> 316ba597c5SAnurag S. Maskey #include <libintl.h> 326ba597c5SAnurag S. Maskey #include <libnwam.h> 336ba597c5SAnurag S. Maskey #include <locale.h> 346ba597c5SAnurag S. Maskey #include <priv.h> 356ba597c5SAnurag S. Maskey #include <pthread.h> 366ba597c5SAnurag S. Maskey #include <signal.h> 376ba597c5SAnurag S. Maskey #include <stdio.h> 386ba597c5SAnurag S. Maskey #include <stdlib.h> 396ba597c5SAnurag S. Maskey #include <string.h> 406ba597c5SAnurag S. Maskey #include <sys/stat.h> 416ba597c5SAnurag S. Maskey #include <sys/types.h> 426ba597c5SAnurag S. Maskey #include <sys/wait.h> 436ba597c5SAnurag S. Maskey #include <unistd.h> 446ba597c5SAnurag S. Maskey 456ba597c5SAnurag S. Maskey #include <libnwam.h> 466ba597c5SAnurag S. Maskey #include "conditions.h" 476ba597c5SAnurag S. Maskey #include "events.h" 486ba597c5SAnurag S. Maskey #include "llp.h" 496ba597c5SAnurag S. Maskey #include "ncp.h" 506ba597c5SAnurag S. Maskey #include "objects.h" 516ba597c5SAnurag S. Maskey #include "util.h" 526ba597c5SAnurag S. Maskey 53d71dbb73Sjbeck /* 54d71dbb73Sjbeck * nwamd - NetWork Auto-Magic Daemon 55d71dbb73Sjbeck */ 56d71dbb73Sjbeck 57d71dbb73Sjbeck boolean_t fg = B_FALSE; 586ba597c5SAnurag S. Maskey dladm_handle_t dld_handle = NULL; 596ba597c5SAnurag S. Maskey boolean_t shutting_down = B_FALSE; 606ba597c5SAnurag S. Maskey 61d71dbb73Sjbeck sigset_t original_sigmask; 628b2954c8SRenee Danson Sommerfeld static sigset_t sigwaitset; 636ba597c5SAnurag S. Maskey 646ba597c5SAnurag S. Maskey static void nwamd_refresh(void); 656ba597c5SAnurag S. Maskey static void graceful_shutdown(void); 66d71dbb73Sjbeck 67d71dbb73Sjbeck /* 68d71dbb73Sjbeck * nwamd 69d71dbb73Sjbeck * 70d71dbb73Sjbeck * This is the Network Auto-Magic daemon. For further high level information 71d71dbb73Sjbeck * see the Network Auto-Magic project and the Approachability communities 726ba597c5SAnurag S. Maskey * on opensolaris.org, nwamd(1M), and the README in the source directory. 73d71dbb73Sjbeck * 746ba597c5SAnurag S. Maskey * The general structure of the code is as a set of event source threads 756ba597c5SAnurag S. Maskey * which feed events into the event handling thread. Some of these events 766ba597c5SAnurag S. Maskey * are internal-only (e.g UPGRADE), but some also involve propogation 776ba597c5SAnurag S. Maskey * to external listeners (who register via a door call into the daemon). 78d71dbb73Sjbeck * 79d71dbb73Sjbeck * signal management 80d71dbb73Sjbeck * Due to being threaded, a simple set of signal handlers would not work 816ba597c5SAnurag S. Maskey * very well for nwamd. Instead nwamd blocks signals in all but the 826ba597c5SAnurag S. Maskey * signal handling thread at startup. 83d71dbb73Sjbeck * 84d71dbb73Sjbeck */ 85d71dbb73Sjbeck 86d71dbb73Sjbeck /* 87d71dbb73Sjbeck * In this file there are several utility functions which might otherwise 88d71dbb73Sjbeck * belong in util.c, but since they are only called from main(), they can 89d71dbb73Sjbeck * live here as static functions: 906ba597c5SAnurag S. Maskey * - nlog set-up 91d71dbb73Sjbeck * - daemonizing 92d71dbb73Sjbeck * - looking up SMF(5) properties 93d71dbb73Sjbeck * - signal handling 94d71dbb73Sjbeck * - managing privileges(5) 95d71dbb73Sjbeck */ 96d71dbb73Sjbeck 97d71dbb73Sjbeck static void 98d71dbb73Sjbeck start_logging(void) 99d71dbb73Sjbeck { 100d71dbb73Sjbeck openlog("nwamd", LOG_PID | LOG_NDELAY, LOG_DAEMON); 101d71dbb73Sjbeck } 102d71dbb73Sjbeck 103d71dbb73Sjbeck static void 104d71dbb73Sjbeck daemonize(void) 105d71dbb73Sjbeck { 106d71dbb73Sjbeck pid_t pid; 107d71dbb73Sjbeck 108d71dbb73Sjbeck /* 109d71dbb73Sjbeck * A little bit of magic here. By the first fork+setsid, we 110d71dbb73Sjbeck * disconnect from our current controlling terminal and become 111d71dbb73Sjbeck * a session group leader. By forking again without calling 112d71dbb73Sjbeck * setsid again, we make certain that we are not the session 113d71dbb73Sjbeck * group leader and can never reacquire a controlling terminal. 114d71dbb73Sjbeck */ 1156ba597c5SAnurag S. Maskey if ((pid = fork()) == (pid_t)-1) 1166ba597c5SAnurag S. Maskey pfail("fork 1 failed"); 117d71dbb73Sjbeck if (pid != 0) { 118d71dbb73Sjbeck (void) wait(NULL); 1196ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "child %ld exited, daemonizing", pid); 120d71dbb73Sjbeck _exit(0); 121d71dbb73Sjbeck } 1226ba597c5SAnurag S. Maskey if (setsid() == (pid_t)-1) 1236ba597c5SAnurag S. Maskey pfail("setsid"); 1246ba597c5SAnurag S. Maskey if ((pid = fork()) == (pid_t)-1) 1256ba597c5SAnurag S. Maskey pfail("fork 2 failed"); 126d71dbb73Sjbeck if (pid != 0) { 127d71dbb73Sjbeck _exit(0); 128d71dbb73Sjbeck } 129d71dbb73Sjbeck (void) chdir("/"); 130d71dbb73Sjbeck (void) umask(022); 131d71dbb73Sjbeck } 132d71dbb73Sjbeck 133d71dbb73Sjbeck /* ARGSUSED */ 134d71dbb73Sjbeck static void * 135d71dbb73Sjbeck sighandler(void *arg) 136d71dbb73Sjbeck { 1376ba597c5SAnurag S. Maskey int sig; 138d71dbb73Sjbeck 139b00044a2SJames Carlson while (!shutting_down) { 1408b2954c8SRenee Danson Sommerfeld sig = sigwait(&sigwaitset); 1416ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "signal %s caught", strsignal(sig)); 1426ba597c5SAnurag S. Maskey 1436ba597c5SAnurag S. Maskey switch (sig) { 1446ba597c5SAnurag S. Maskey case SIGTHAW: 145d71dbb73Sjbeck case SIGHUP: 146d71dbb73Sjbeck /* 1476ba597c5SAnurag S. Maskey * Resumed from suspend or refresh. Clear up all 1486ba597c5SAnurag S. Maskey * objects so their states start from scratch; 1496ba597c5SAnurag S. Maskey * then refresh(). 150d71dbb73Sjbeck */ 1516ba597c5SAnurag S. Maskey nwamd_fini_enms(); 1526ba597c5SAnurag S. Maskey nwamd_fini_ncus(); 1536ba597c5SAnurag S. Maskey nwamd_fini_locs(); 1546ba597c5SAnurag S. Maskey nwamd_refresh(); 155d71dbb73Sjbeck break; 1566ba597c5SAnurag S. Maskey case SIGUSR1: 157b00044a2SJames Carlson /* 1586ba597c5SAnurag S. Maskey * Undocumented "log ncu list" signal. 159b00044a2SJames Carlson */ 1606ba597c5SAnurag S. Maskey nwamd_log_ncus(); 161ab32bdf2SJames Carlson break; 1628b2954c8SRenee Danson Sommerfeld case SIGTERM: 1636ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "%s received, shutting down", 164d71dbb73Sjbeck strsignal(sig)); 1656ba597c5SAnurag S. Maskey graceful_shutdown(); 166d71dbb73Sjbeck break; 1678b2954c8SRenee Danson Sommerfeld default: 1686ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "unexpected signal %s received, " 1698b2954c8SRenee Danson Sommerfeld "ignoring", strsignal(sig)); 1708b2954c8SRenee Danson Sommerfeld break; 171d71dbb73Sjbeck } 172d71dbb73Sjbeck } 173b00044a2SJames Carlson return (NULL); 174d71dbb73Sjbeck } 175d71dbb73Sjbeck 176d71dbb73Sjbeck static void 177d71dbb73Sjbeck init_signalhandling(void) 178d71dbb73Sjbeck { 179d71dbb73Sjbeck pthread_attr_t attr; 180d71dbb73Sjbeck pthread_t sighand; 181d71dbb73Sjbeck int err; 182d71dbb73Sjbeck 183d71dbb73Sjbeck (void) pthread_attr_init(&attr); 184d71dbb73Sjbeck (void) pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 185d71dbb73Sjbeck if (err = pthread_create(&sighand, &attr, sighandler, NULL)) { 1866ba597c5SAnurag S. Maskey nlog(LOG_ERR, "pthread_create system: %s", strerror(err)); 187d71dbb73Sjbeck exit(EXIT_FAILURE); 188d71dbb73Sjbeck } else { 1896ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "signal handler thread: %d", sighand); 190d71dbb73Sjbeck } 191d71dbb73Sjbeck (void) pthread_attr_destroy(&attr); 192d71dbb73Sjbeck } 193d71dbb73Sjbeck 1946ba597c5SAnurag S. Maskey /* 1956ba597c5SAnurag S. Maskey * Construct the set of signals that we explicitly want to deal with. 1966ba597c5SAnurag S. Maskey * We block these while we're still single-threaded; this block will 1976ba597c5SAnurag S. Maskey * be inherited by all the threads we create. When we are ready to 1986ba597c5SAnurag S. Maskey * start handling signals, we will start the signal handling thread, 1996ba597c5SAnurag S. Maskey * which will sigwait() this same set of signals, and will thus receive 2006ba597c5SAnurag S. Maskey * and handle any that are sent to the process. 2016ba597c5SAnurag S. Maskey */ 202d71dbb73Sjbeck static void 2036ba597c5SAnurag S. Maskey block_signals(void) 204d71dbb73Sjbeck { 2056ba597c5SAnurag S. Maskey (void) sigemptyset(&sigwaitset); 2066ba597c5SAnurag S. Maskey (void) sigaddset(&sigwaitset, SIGHUP); 2076ba597c5SAnurag S. Maskey (void) sigaddset(&sigwaitset, SIGUSR1); 2086ba597c5SAnurag S. Maskey (void) sigaddset(&sigwaitset, SIGUSR2); 2096ba597c5SAnurag S. Maskey (void) sigaddset(&sigwaitset, SIGTERM); 2106ba597c5SAnurag S. Maskey (void) sigaddset(&sigwaitset, SIGTHAW); 2116ba597c5SAnurag S. Maskey (void) pthread_sigmask(SIG_BLOCK, &sigwaitset, &original_sigmask); 2126ba597c5SAnurag S. Maskey } 213d71dbb73Sjbeck 2146ba597c5SAnurag S. Maskey /* 2156ba597c5SAnurag S. Maskey * Look up nwamd property values and set daemon variables appropriately. 2166ba597c5SAnurag S. Maskey * This function will be called on startup and via the signal handling 2176ba597c5SAnurag S. Maskey * thread on receiving a HUP (which occurs when the nwam service is 2186ba597c5SAnurag S. Maskey * refreshed). 2196ba597c5SAnurag S. Maskey */ 2206ba597c5SAnurag S. Maskey static void 2216ba597c5SAnurag S. Maskey lookup_daemon_properties(void) 2226ba597c5SAnurag S. Maskey { 2236ba597c5SAnurag S. Maskey char *active_ncp_tmp; 2246ba597c5SAnurag S. Maskey char *scan_level_tmp; 2256ba597c5SAnurag S. Maskey 2266ba597c5SAnurag S. Maskey (void) nwamd_lookup_boolean_property(OUR_FMRI, OUR_PG, 2276ba597c5SAnurag S. Maskey OUR_DEBUG_PROP_NAME, &debug); 2286ba597c5SAnurag S. Maskey (void) nwamd_lookup_boolean_property(OUR_FMRI, OUR_PG, 2296ba597c5SAnurag S. Maskey OUR_AUTOCONF_PROP_NAME, &wireless_autoconf); 2306ba597c5SAnurag S. Maskey (void) nwamd_lookup_boolean_property(OUR_FMRI, OUR_PG, 2316ba597c5SAnurag S. Maskey OUR_STRICT_BSSID_PROP_NAME, &wireless_strict_bssid); 2326ba597c5SAnurag S. Maskey 2336ba597c5SAnurag S. Maskey (void) pthread_mutex_lock(&active_ncp_mutex); 2346ba597c5SAnurag S. Maskey if ((active_ncp_tmp = malloc(NWAM_MAX_NAME_LEN)) == NULL || 2356ba597c5SAnurag S. Maskey nwamd_lookup_string_property(OUR_FMRI, OUR_PG, 2366ba597c5SAnurag S. Maskey OUR_ACTIVE_NCP_PROP_NAME, active_ncp_tmp, NWAM_MAX_NAME_LEN) != 0) { 2376ba597c5SAnurag S. Maskey (void) strlcpy(active_ncp, NWAM_NCP_NAME_AUTOMATIC, 2386ba597c5SAnurag S. Maskey NWAM_MAX_NAME_LEN); 239d71dbb73Sjbeck } else { 2406ba597c5SAnurag S. Maskey (void) strlcpy(active_ncp, active_ncp_tmp, NWAM_MAX_NAME_LEN); 2416ba597c5SAnurag S. Maskey } 2426ba597c5SAnurag S. Maskey (void) pthread_mutex_unlock(&active_ncp_mutex); 2436ba597c5SAnurag S. Maskey free(active_ncp_tmp); 244d71dbb73Sjbeck 2456ba597c5SAnurag S. Maskey if (nwamd_lookup_count_property(OUR_FMRI, OUR_PG, 2466ba597c5SAnurag S. Maskey OUR_CONDITION_CHECK_INTERVAL_PROP_NAME, 2476ba597c5SAnurag S. Maskey &condition_check_interval) != 0) 2486ba597c5SAnurag S. Maskey condition_check_interval = CONDITION_CHECK_INTERVAL_DEFAULT; 2496ba597c5SAnurag S. Maskey 2506ba597c5SAnurag S. Maskey if ((scan_level_tmp = malloc(NWAM_MAX_NAME_LEN)) == NULL || 2516ba597c5SAnurag S. Maskey nwamd_lookup_string_property(OUR_FMRI, OUR_PG, 2526ba597c5SAnurag S. Maskey OUR_WIRELESS_SCAN_LEVEL_PROP_NAME, scan_level_tmp, 2536ba597c5SAnurag S. Maskey NWAM_MAX_NAME_LEN) != 0) { 2546ba597c5SAnurag S. Maskey wireless_scan_level = WIRELESS_SCAN_LEVEL_DEFAULT; 2556ba597c5SAnurag S. Maskey } else { 2566ba597c5SAnurag S. Maskey if (dladm_wlan_str2strength(scan_level_tmp, 2576ba597c5SAnurag S. Maskey &wireless_scan_level) != DLADM_STATUS_OK) 2586ba597c5SAnurag S. Maskey wireless_scan_level = DLADM_WLAN_STRENGTH_VERY_WEAK; 2596ba597c5SAnurag S. Maskey } 2606ba597c5SAnurag S. Maskey free(scan_level_tmp); 2616ba597c5SAnurag S. Maskey 2626ba597c5SAnurag S. Maskey if (nwamd_lookup_count_property(OUR_FMRI, OUR_PG, 2636ba597c5SAnurag S. Maskey OUR_WIRELESS_SCAN_INTERVAL_PROP_NAME, &wireless_scan_interval) != 0) 2646ba597c5SAnurag S. Maskey wireless_scan_interval = WIRELESS_SCAN_INTERVAL_DEFAULT; 2656ba597c5SAnurag S. Maskey 2666ba597c5SAnurag S. Maskey if (nwamd_lookup_count_property(OUR_FMRI, OUR_PG, 2676ba597c5SAnurag S. Maskey OUR_NCU_WAIT_TIME_PROP_NAME, &ncu_wait_time) != 0) 2686ba597c5SAnurag S. Maskey ncu_wait_time = NCU_WAIT_TIME_DEFAULT; 2696ba597c5SAnurag S. Maskey 2706ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "Read daemon configuration properties."); 271d71dbb73Sjbeck } 272d71dbb73Sjbeck 2736ba597c5SAnurag S. Maskey /* 2746ba597c5SAnurag S. Maskey * Re-read the SMF properties. 2756ba597c5SAnurag S. Maskey * Reset ncu priority group (since the NCUs will have to walk 2766ba597c5SAnurag S. Maskey * through their state machines again) and schedule a check 2776ba597c5SAnurag S. Maskey * Re-read objects from libnwam. 2786ba597c5SAnurag S. Maskey * Also, run condition checking for locations and ENMs. 2796ba597c5SAnurag S. Maskey */ 2806ba597c5SAnurag S. Maskey static void 2816ba597c5SAnurag S. Maskey nwamd_refresh(void) 2826ba597c5SAnurag S. Maskey { 2836ba597c5SAnurag S. Maskey lookup_daemon_properties(); 284d71dbb73Sjbeck 2856ba597c5SAnurag S. Maskey (void) pthread_mutex_lock(&active_ncp_mutex); 2866ba597c5SAnurag S. Maskey current_ncu_priority_group = INVALID_PRIORITY_GROUP; 2876ba597c5SAnurag S. Maskey (void) pthread_mutex_unlock(&active_ncp_mutex); 288d71dbb73Sjbeck 2896ba597c5SAnurag S. Maskey nwamd_init_ncus(); 2906ba597c5SAnurag S. Maskey nwamd_init_enms(); 2916ba597c5SAnurag S. Maskey nwamd_init_locs(); 292d71dbb73Sjbeck 2936ba597c5SAnurag S. Maskey nwamd_create_ncu_check_event(0); 2946ba597c5SAnurag S. Maskey nwamd_create_triggered_condition_check_event(0); 295d71dbb73Sjbeck } 296d71dbb73Sjbeck 297b00044a2SJames Carlson static void 2986ba597c5SAnurag S. Maskey graceful_shutdown(void) 299b00044a2SJames Carlson { 3006ba597c5SAnurag S. Maskey nwamd_event_t event; 301b00044a2SJames Carlson 3026ba597c5SAnurag S. Maskey shutting_down = B_TRUE; 3036ba597c5SAnurag S. Maskey nwamd_event_sources_fini(); 3046ba597c5SAnurag S. Maskey nwamd_door_fini(); 3056ba597c5SAnurag S. Maskey nwamd_fini_enms(); 3066ba597c5SAnurag S. Maskey nwamd_fini_ncus(); 3076ba597c5SAnurag S. Maskey nwamd_fini_locs(); 3086ba597c5SAnurag S. Maskey 3096ba597c5SAnurag S. Maskey event = nwamd_event_init_shutdown(); 3106ba597c5SAnurag S. Maskey if (event == NULL) 3116ba597c5SAnurag S. Maskey pfail("nwamd could not create shutdown event, exiting"); 3126ba597c5SAnurag S. Maskey nwamd_event_enqueue(event); 313b00044a2SJames Carlson } 314b00044a2SJames Carlson 315d71dbb73Sjbeck int 316d71dbb73Sjbeck main(int argc, char *argv[]) 317d71dbb73Sjbeck { 318d71dbb73Sjbeck int c; 3196ba597c5SAnurag S. Maskey uint64_t version; 3206ba597c5SAnurag S. Maskey nwamd_event_t event; 3216ba597c5SAnurag S. Maskey dladm_status_t rc; 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 331*69b43529SMichael 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 */ 3716ba597c5SAnurag S. Maskey rc = dladm_open(&dld_handle); 3726ba597c5SAnurag S. Maskey if (rc != DLADM_STATUS_OK) { 3736ba597c5SAnurag S. Maskey char status_str[DLADM_STRSIZE]; 3746ba597c5SAnurag S. Maskey (void) dladm_status2str(rc, status_str); 3756ba597c5SAnurag S. Maskey pfail("failed to open dladm handle: %s", status_str); 3766ba597c5SAnurag S. Maskey } 3776ba597c5SAnurag S. Maskey 3786ba597c5SAnurag S. Maskey /* 3796ba597c5SAnurag S. Maskey * Handle upgrade of legacy config. Absence of version property 3806ba597c5SAnurag S. Maskey * (which did not exist in phase 0 or 0.5) is the indication that 3816ba597c5SAnurag S. Maskey * we need to upgrade to phase 1 (version 1). 3826ba597c5SAnurag S. Maskey */ 3836ba597c5SAnurag S. Maskey if (nwamd_lookup_count_property(OUR_FMRI, OUR_PG, OUR_VERSION_PROP_NAME, 3846ba597c5SAnurag S. Maskey &version) != 0) 3856ba597c5SAnurag S. Maskey nwamd_handle_upgrade(NULL); 3866ba597c5SAnurag S. Maskey 3876ba597c5SAnurag S. Maskey /* 3886ba597c5SAnurag S. Maskey * Initialize lists handling internal representations of objects. 3896ba597c5SAnurag S. Maskey */ 3906ba597c5SAnurag S. Maskey nwamd_object_lists_init(); 3916ba597c5SAnurag S. Maskey 3926ba597c5SAnurag S. Maskey /* 3936ba597c5SAnurag S. Maskey * Start the event handling thread before starting event sources, 3946ba597c5SAnurag S. Maskey * including signal handling, so we are ready to handle incoming 3956ba597c5SAnurag S. Maskey * events. 3966ba597c5SAnurag S. Maskey */ 3976ba597c5SAnurag S. Maskey nwamd_event_queue_init(); 398b00044a2SJames Carlson 399d71dbb73Sjbeck init_signalhandling(); 400d71dbb73Sjbeck 4016ba597c5SAnurag S. Maskey /* Enqueue init event */ 4026ba597c5SAnurag S. Maskey event = nwamd_event_init_init(); 4036ba597c5SAnurag S. Maskey if (event == NULL) 4046ba597c5SAnurag S. Maskey pfail("nwamd could not create init event, exiting"); 4056ba597c5SAnurag S. Maskey nwamd_event_enqueue(event); 4066ba597c5SAnurag S. Maskey /* 4076ba597c5SAnurag S. Maskey * Collect initial user configuration. 4086ba597c5SAnurag S. Maskey */ 409d71dbb73Sjbeck 4106ba597c5SAnurag S. Maskey /* 4116ba597c5SAnurag S. Maskey * Walk the physical interfaces and update the Automatic NCP to 4126ba597c5SAnurag S. Maskey * contain the IP and link NCUs for the interfaces that exist in 4136ba597c5SAnurag S. Maskey * the system. 4146ba597c5SAnurag S. Maskey */ 4156ba597c5SAnurag S. Maskey nwamd_walk_physical_configuration(); 416d71dbb73Sjbeck 4176ba597c5SAnurag S. Maskey /* 4186ba597c5SAnurag S. Maskey * We should initialize the door at the point that we can respond to 4196ba597c5SAnurag S. Maskey * user requests about the system but before we start actually process 4206ba597c5SAnurag S. Maskey * state changes or effecting the system. 4216ba597c5SAnurag S. Maskey */ 4226ba597c5SAnurag S. Maskey nwamd_door_init(); 423b00044a2SJames Carlson 4246ba597c5SAnurag S. Maskey /* 4256ba597c5SAnurag S. Maskey * Initialize data objects. 4266ba597c5SAnurag S. Maskey * 4276ba597c5SAnurag S. Maskey * Enabling an NCP involves refreshing nwam, which initializes the 4286ba597c5SAnurag S. Maskey * objects (ncu, enm, loc, known wlan). Thus, no need to 4296ba597c5SAnurag S. Maskey * explicitly initialize these objects here. The refresh also 4306ba597c5SAnurag S. Maskey * enqueues and NCU activation checking event. Location and ENM 4316ba597c5SAnurag S. Maskey * condition checking are triggered by changes in NCU states. 4326ba597c5SAnurag S. Maskey */ 4336ba597c5SAnurag S. Maskey (void) pthread_mutex_lock(&active_ncp_mutex); 4346ba597c5SAnurag S. Maskey if (nwamd_ncp_action(active_ncp, NWAM_ACTION_ENABLE) != 0) 4356ba597c5SAnurag S. Maskey pfail("Initial enable failed for active NCP %s", active_ncp); 4366ba597c5SAnurag S. Maskey (void) pthread_mutex_unlock(&active_ncp_mutex); 437d71dbb73Sjbeck 4386ba597c5SAnurag S. Maskey /* 4396ba597c5SAnurag S. Maskey * Enqueue an event to start periodic checking of activation conditions. 4406ba597c5SAnurag S. Maskey */ 4416ba597c5SAnurag S. Maskey nwamd_create_timed_condition_check_event(); 442d71dbb73Sjbeck 44338f140aaSMichael Hunter /* 44438f140aaSMichael Hunter * These two routines safely minimize our privilege set. They 44538f140aaSMichael Hunter * use reference counting to be safe in a threaded program. It is 44638f140aaSMichael Hunter * gross that we escalate/deescalate to initialize this functionality 44738f140aaSMichael Hunter * but a real fix is to add functionality to do fine grained privs 44838f140aaSMichael Hunter * (and if necessary set uid to 0) in this threaded daemon. 44938f140aaSMichael Hunter */ 45038f140aaSMichael Hunter nwamd_escalate(); 45138f140aaSMichael Hunter nwamd_deescalate(); 45238f140aaSMichael Hunter 4536ba597c5SAnurag S. Maskey /* 4546ba597c5SAnurag S. Maskey * Start the various agents (hooks on fds, threads) which collect events 4556ba597c5SAnurag S. Maskey */ 4566ba597c5SAnurag S. Maskey nwamd_event_sources_init(); 457b00044a2SJames Carlson 4586ba597c5SAnurag S. Maskey /* 4596ba597c5SAnurag S. Maskey * nwamd_event_handler() only returns on shutdown. 4606ba597c5SAnurag S. Maskey */ 4616ba597c5SAnurag S. Maskey nwamd_event_handler(); 462d71dbb73Sjbeck 4634ac67f02SAnurag S. Maskey dladm_close(dld_handle); 4646ba597c5SAnurag S. Maskey 465b00044a2SJames Carlson return (EXIT_SUCCESS); 466d71dbb73Sjbeck } 467