LCOV - code coverage report
Current view: top level - hostapd - main.c (source / functions) Hit Total Coverage
Test: wpa_supplicant/hostapd combined for hwsim test run 1443382998 Lines: 298 390 76.4 %
Date: 2015-09-27 Functions: 16 19 84.2 %

          Line data    Source code
       1             : /*
       2             :  * hostapd / main()
       3             :  * Copyright (c) 2002-2015, Jouni Malinen <j@w1.fi>
       4             :  *
       5             :  * This software may be distributed under the terms of the BSD license.
       6             :  * See README for more details.
       7             :  */
       8             : 
       9             : #include "utils/includes.h"
      10             : #ifndef CONFIG_NATIVE_WINDOWS
      11             : #include <syslog.h>
      12             : #include <grp.h>
      13             : #endif /* CONFIG_NATIVE_WINDOWS */
      14             : 
      15             : #include "utils/common.h"
      16             : #include "utils/eloop.h"
      17             : #include "utils/uuid.h"
      18             : #include "crypto/random.h"
      19             : #include "crypto/tls.h"
      20             : #include "common/version.h"
      21             : #include "drivers/driver.h"
      22             : #include "eap_server/eap.h"
      23             : #include "eap_server/tncs.h"
      24             : #include "ap/hostapd.h"
      25             : #include "ap/ap_config.h"
      26             : #include "ap/ap_drv_ops.h"
      27             : #include "fst/fst.h"
      28             : #include "config_file.h"
      29             : #include "eap_register.h"
      30             : #include "ctrl_iface.h"
      31             : 
      32             : 
      33             : struct hapd_global {
      34             :         void **drv_priv;
      35             :         size_t drv_count;
      36             : };
      37             : 
      38             : static struct hapd_global global;
      39             : 
      40             : 
      41             : #ifndef CONFIG_NO_HOSTAPD_LOGGER
      42       95536 : static void hostapd_logger_cb(void *ctx, const u8 *addr, unsigned int module,
      43             :                               int level, const char *txt, size_t len)
      44             : {
      45       95536 :         struct hostapd_data *hapd = ctx;
      46             :         char *format, *module_str;
      47             :         int maxlen;
      48             :         int conf_syslog_level, conf_stdout_level;
      49             :         unsigned int conf_syslog, conf_stdout;
      50             : 
      51       95536 :         maxlen = len + 100;
      52       95536 :         format = os_malloc(maxlen);
      53       95536 :         if (!format)
      54       95583 :                 return;
      55             : 
      56       95489 :         if (hapd && hapd->conf) {
      57       95489 :                 conf_syslog_level = hapd->conf->logger_syslog_level;
      58       95489 :                 conf_stdout_level = hapd->conf->logger_stdout_level;
      59       95489 :                 conf_syslog = hapd->conf->logger_syslog;
      60       95489 :                 conf_stdout = hapd->conf->logger_stdout;
      61             :         } else {
      62           0 :                 conf_syslog_level = conf_stdout_level = 0;
      63           0 :                 conf_syslog = conf_stdout = (unsigned int) -1;
      64             :         }
      65             : 
      66       95489 :         switch (module) {
      67             :         case HOSTAPD_MODULE_IEEE80211:
      68       17190 :                 module_str = "IEEE 802.11";
      69       17190 :                 break;
      70             :         case HOSTAPD_MODULE_IEEE8021X:
      71       24525 :                 module_str = "IEEE 802.1X";
      72       24525 :                 break;
      73             :         case HOSTAPD_MODULE_RADIUS:
      74       24163 :                 module_str = "RADIUS";
      75       24163 :                 break;
      76             :         case HOSTAPD_MODULE_WPA:
      77       13356 :                 module_str = "WPA";
      78       13356 :                 break;
      79             :         case HOSTAPD_MODULE_DRIVER:
      80           0 :                 module_str = "DRIVER";
      81           0 :                 break;
      82             :         case HOSTAPD_MODULE_IAPP:
      83           0 :                 module_str = "IAPP";
      84           0 :                 break;
      85             :         case HOSTAPD_MODULE_MLME:
      86       16255 :                 module_str = "MLME";
      87       16255 :                 break;
      88             :         default:
      89           0 :                 module_str = NULL;
      90           0 :                 break;
      91             :         }
      92             : 
      93       95489 :         if (hapd && hapd->conf && addr)
      94      623576 :                 os_snprintf(format, maxlen, "%s: STA " MACSTR "%s%s: %s",
      95      545629 :                             hapd->conf->iface, MAC2STR(addr),
      96             :                             module_str ? " " : "", module_str ? module_str : "",
      97             :                             txt);
      98       17542 :         else if (hapd && hapd->conf)
      99       35084 :                 os_snprintf(format, maxlen, "%s:%s%s %s",
     100       17542 :                             hapd->conf->iface, module_str ? " " : "",
     101             :                             module_str ? module_str : "", txt);
     102           0 :         else if (addr)
     103           0 :                 os_snprintf(format, maxlen, "STA " MACSTR "%s%s: %s",
     104           0 :                             MAC2STR(addr), module_str ? " " : "",
     105             :                             module_str ? module_str : "", txt);
     106             :         else
     107           0 :                 os_snprintf(format, maxlen, "%s%s%s",
     108             :                             module_str ? module_str : "",
     109             :                             module_str ? ": " : "", txt);
     110             : 
     111       95489 :         if ((conf_stdout & module) && level >= conf_stdout_level) {
     112       94541 :                 wpa_debug_print_timestamp();
     113       94541 :                 wpa_printf(MSG_INFO, "%s", format);
     114             :         }
     115             : 
     116             : #ifndef CONFIG_NATIVE_WINDOWS
     117       95489 :         if ((conf_syslog & module) && level >= conf_syslog_level) {
     118             :                 int priority;
     119       11034 :                 switch (level) {
     120             :                 case HOSTAPD_LEVEL_DEBUG_VERBOSE:
     121             :                 case HOSTAPD_LEVEL_DEBUG:
     122           0 :                         priority = LOG_DEBUG;
     123           0 :                         break;
     124             :                 case HOSTAPD_LEVEL_INFO:
     125       10650 :                         priority = LOG_INFO;
     126       10650 :                         break;
     127             :                 case HOSTAPD_LEVEL_NOTICE:
     128           6 :                         priority = LOG_NOTICE;
     129           6 :                         break;
     130             :                 case HOSTAPD_LEVEL_WARNING:
     131         378 :                         priority = LOG_WARNING;
     132         378 :                         break;
     133             :                 default:
     134           0 :                         priority = LOG_INFO;
     135           0 :                         break;
     136             :                 }
     137       11034 :                 syslog(priority, "%s", format);
     138             :         }
     139             : #endif /* CONFIG_NATIVE_WINDOWS */
     140             : 
     141       95489 :         os_free(format);
     142             : }
     143             : #endif /* CONFIG_NO_HOSTAPD_LOGGER */
     144             : 
     145             : 
     146             : /**
     147             :  * hostapd_driver_init - Preparate driver interface
     148             :  */
     149        1667 : static int hostapd_driver_init(struct hostapd_iface *iface)
     150             : {
     151             :         struct wpa_init_params params;
     152             :         size_t i;
     153        1667 :         struct hostapd_data *hapd = iface->bss[0];
     154        1667 :         struct hostapd_bss_config *conf = hapd->conf;
     155        1667 :         u8 *b = conf->bssid;
     156             :         struct wpa_driver_capa capa;
     157             : 
     158        1667 :         if (hapd->driver == NULL || hapd->driver->hapd_init == NULL) {
     159           0 :                 wpa_printf(MSG_ERROR, "No hostapd driver wrapper available");
     160           0 :                 return -1;
     161             :         }
     162             : 
     163             :         /* Initialize the driver interface */
     164        1667 :         if (!(b[0] | b[1] | b[2] | b[3] | b[4] | b[5]))
     165        1619 :                 b = NULL;
     166             : 
     167        1667 :         os_memset(&params, 0, sizeof(params));
     168        3358 :         for (i = 0; wpa_drivers[i]; i++) {
     169        1679 :                 if (wpa_drivers[i] != hapd->driver)
     170          12 :                         continue;
     171             : 
     172        1689 :                 if (global.drv_priv[i] == NULL &&
     173          22 :                     wpa_drivers[i]->global_init) {
     174          10 :                         global.drv_priv[i] = wpa_drivers[i]->global_init();
     175          10 :                         if (global.drv_priv[i] == NULL) {
     176           0 :                                 wpa_printf(MSG_ERROR, "Failed to initialize "
     177             :                                            "driver '%s'",
     178           0 :                                            wpa_drivers[i]->name);
     179           0 :                                 return -1;
     180             :                         }
     181             :                 }
     182             : 
     183        1667 :                 params.global_priv = global.drv_priv[i];
     184        1667 :                 break;
     185             :         }
     186        1667 :         params.bssid = b;
     187        1667 :         params.ifname = hapd->conf->iface;
     188        1667 :         params.driver_params = hapd->iconf->driver_params;
     189        1667 :         params.use_pae_group_addr = hapd->conf->use_pae_group_addr;
     190             : 
     191        1667 :         params.num_bridge = hapd->iface->num_bss;
     192        1667 :         params.bridge = os_calloc(hapd->iface->num_bss, sizeof(char *));
     193        1667 :         if (params.bridge == NULL)
     194           4 :                 return -1;
     195        3334 :         for (i = 0; i < hapd->iface->num_bss; i++) {
     196        1671 :                 struct hostapd_data *bss = hapd->iface->bss[i];
     197        1671 :                 if (bss->conf->bridge[0])
     198          19 :                         params.bridge[i] = bss->conf->bridge;
     199             :         }
     200             : 
     201        1663 :         params.own_addr = hapd->own_addr;
     202             : 
     203        1663 :         hapd->drv_priv = hapd->driver->hapd_init(hapd, &params);
     204        1663 :         os_free(params.bridge);
     205        1663 :         if (hapd->drv_priv == NULL) {
     206          13 :                 wpa_printf(MSG_ERROR, "%s driver initialization failed.",
     207          13 :                            hapd->driver->name);
     208          13 :                 hapd->driver = NULL;
     209          13 :                 return -1;
     210             :         }
     211             : 
     212        3288 :         if (hapd->driver->get_capa &&
     213        1638 :             hapd->driver->get_capa(hapd->drv_priv, &capa) == 0) {
     214             :                 struct wowlan_triggers *triggs;
     215             : 
     216        1638 :                 iface->drv_flags = capa.flags;
     217        1638 :                 iface->smps_modes = capa.smps_modes;
     218        1638 :                 iface->probe_resp_offloads = capa.probe_resp_offloads;
     219        1638 :                 iface->extended_capa = capa.extended_capa;
     220        1638 :                 iface->extended_capa_mask = capa.extended_capa_mask;
     221        1638 :                 iface->extended_capa_len = capa.extended_capa_len;
     222        1638 :                 iface->drv_max_acl_mac_addrs = capa.max_acl_mac_addrs;
     223             : 
     224        1638 :                 triggs = wpa_get_wowlan_triggers(conf->wowlan_triggers, &capa);
     225        1638 :                 if (triggs && hapd->driver->set_wowlan) {
     226           0 :                         if (hapd->driver->set_wowlan(hapd->drv_priv, triggs))
     227           0 :                                 wpa_printf(MSG_ERROR, "set_wowlan failed");
     228             :                 }
     229        1638 :                 os_free(triggs);
     230             :         }
     231             : 
     232        1650 :         return 0;
     233             : }
     234             : 
     235             : 
     236             : /**
     237             :  * hostapd_interface_init - Read configuration file and init BSS data
     238             :  *
     239             :  * This function is used to parse configuration file for a full interface (one
     240             :  * or more BSSes sharing the same radio) and allocate memory for the BSS
     241             :  * interfaces. No actiual driver operations are started.
     242             :  */
     243             : static struct hostapd_iface *
     244          37 : hostapd_interface_init(struct hapd_interfaces *interfaces,
     245             :                        const char *config_fname, int debug)
     246             : {
     247             :         struct hostapd_iface *iface;
     248             :         int k;
     249             : 
     250          37 :         wpa_printf(MSG_ERROR, "Configuration file: %s", config_fname);
     251          37 :         iface = hostapd_init(interfaces, config_fname);
     252          37 :         if (!iface)
     253           9 :                 return NULL;
     254          28 :         iface->interfaces = interfaces;
     255             : 
     256         100 :         for (k = 0; k < debug; k++) {
     257          72 :                 if (iface->bss[0]->conf->logger_stdout_level > 0)
     258          56 :                         iface->bss[0]->conf->logger_stdout_level--;
     259             :         }
     260             : 
     261          28 :         if (iface->conf->bss[0]->iface[0] == '\0' &&
     262           0 :             !hostapd_drv_none(iface->bss[0])) {
     263           0 :                 wpa_printf(MSG_ERROR, "Interface name not specified in %s",
     264             :                            config_fname);
     265           0 :                 hostapd_interface_deinit_free(iface);
     266           0 :                 return NULL;
     267             :         }
     268             : 
     269          28 :         return iface;
     270             : }
     271             : 
     272             : 
     273             : /**
     274             :  * handle_term - SIGINT and SIGTERM handler to terminate hostapd process
     275             :  */
     276          16 : static void handle_term(int sig, void *signal_ctx)
     277             : {
     278          16 :         wpa_printf(MSG_DEBUG, "Signal %d received - terminating", sig);
     279          16 :         eloop_terminate();
     280          16 : }
     281             : 
     282             : 
     283             : #ifndef CONFIG_NATIVE_WINDOWS
     284             : 
     285           0 : static int handle_reload_iface(struct hostapd_iface *iface, void *ctx)
     286             : {
     287           0 :         if (hostapd_reload_config(iface) < 0) {
     288           0 :                 wpa_printf(MSG_WARNING, "Failed to read new configuration "
     289             :                            "file - continuing with old.");
     290             :         }
     291           0 :         return 0;
     292             : }
     293             : 
     294             : 
     295             : /**
     296             :  * handle_reload - SIGHUP handler to reload configuration
     297             :  */
     298           0 : static void handle_reload(int sig, void *signal_ctx)
     299             : {
     300           0 :         struct hapd_interfaces *interfaces = signal_ctx;
     301           0 :         wpa_printf(MSG_DEBUG, "Signal %d received - reloading configuration",
     302             :                    sig);
     303           0 :         hostapd_for_each_interface(interfaces, handle_reload_iface, NULL);
     304           0 : }
     305             : 
     306             : 
     307           0 : static void handle_dump_state(int sig, void *signal_ctx)
     308             : {
     309             :         /* Not used anymore - ignore signal */
     310           0 : }
     311             : #endif /* CONFIG_NATIVE_WINDOWS */
     312             : 
     313             : 
     314          25 : static int hostapd_global_init(struct hapd_interfaces *interfaces,
     315             :                                const char *entropy_file)
     316             : {
     317             :         int i;
     318             : 
     319          25 :         os_memset(&global, 0, sizeof(global));
     320             : 
     321          25 :         hostapd_logger_register_cb(hostapd_logger_cb);
     322             : 
     323          25 :         if (eap_server_register_methods()) {
     324           0 :                 wpa_printf(MSG_ERROR, "Failed to register EAP methods");
     325           0 :                 return -1;
     326             :         }
     327             : 
     328          25 :         if (eloop_init()) {
     329           0 :                 wpa_printf(MSG_ERROR, "Failed to initialize event loop");
     330           0 :                 return -1;
     331             :         }
     332             : 
     333             :         random_init(entropy_file);
     334             : 
     335             : #ifndef CONFIG_NATIVE_WINDOWS
     336          25 :         eloop_register_signal(SIGHUP, handle_reload, interfaces);
     337          25 :         eloop_register_signal(SIGUSR1, handle_dump_state, interfaces);
     338             : #endif /* CONFIG_NATIVE_WINDOWS */
     339          25 :         eloop_register_signal_terminate(handle_term, interfaces);
     340             : 
     341             : #ifndef CONFIG_NATIVE_WINDOWS
     342          25 :         openlog("hostapd", 0, LOG_DAEMON);
     343             : #endif /* CONFIG_NATIVE_WINDOWS */
     344             : 
     345          75 :         for (i = 0; wpa_drivers[i]; i++)
     346          50 :                 global.drv_count++;
     347          25 :         if (global.drv_count == 0) {
     348           0 :                 wpa_printf(MSG_ERROR, "No drivers enabled");
     349           0 :                 return -1;
     350             :         }
     351          25 :         global.drv_priv = os_calloc(global.drv_count, sizeof(void *));
     352          25 :         if (global.drv_priv == NULL)
     353           0 :                 return -1;
     354             : 
     355          25 :         return 0;
     356             : }
     357             : 
     358             : 
     359          25 : static void hostapd_global_deinit(const char *pid_file)
     360             : {
     361             :         int i;
     362             : 
     363          75 :         for (i = 0; wpa_drivers[i] && global.drv_priv; i++) {
     364          50 :                 if (!global.drv_priv[i])
     365          40 :                         continue;
     366          10 :                 wpa_drivers[i]->global_deinit(global.drv_priv[i]);
     367             :         }
     368          25 :         os_free(global.drv_priv);
     369          25 :         global.drv_priv = NULL;
     370             : 
     371             : #ifdef EAP_SERVER_TNC
     372          25 :         tncs_global_deinit();
     373             : #endif /* EAP_SERVER_TNC */
     374             : 
     375             :         random_deinit();
     376             : 
     377          25 :         eloop_destroy();
     378             : 
     379             : #ifndef CONFIG_NATIVE_WINDOWS
     380          25 :         closelog();
     381             : #endif /* CONFIG_NATIVE_WINDOWS */
     382             : 
     383          25 :         eap_server_unregister_methods();
     384             : 
     385          25 :         os_daemonize_terminate(pid_file);
     386          25 : }
     387             : 
     388             : 
     389          16 : static int hostapd_global_run(struct hapd_interfaces *ifaces, int daemonize,
     390             :                               const char *pid_file)
     391             : {
     392             : #ifdef EAP_SERVER_TNC
     393          16 :         int tnc = 0;
     394             :         size_t i, k;
     395             : 
     396          35 :         for (i = 0; !tnc && i < ifaces->count; i++) {
     397          38 :                 for (k = 0; k < ifaces->iface[i]->num_bss; k++) {
     398          19 :                         if (ifaces->iface[i]->bss[0]->conf->tnc) {
     399           0 :                                 tnc++;
     400           0 :                                 break;
     401             :                         }
     402             :                 }
     403             :         }
     404             : 
     405          16 :         if (tnc && tncs_global_init() < 0) {
     406           0 :                 wpa_printf(MSG_ERROR, "Failed to initialize TNCS");
     407           0 :                 return -1;
     408             :         }
     409             : #endif /* EAP_SERVER_TNC */
     410             : 
     411          16 :         if (daemonize && os_daemonize(pid_file)) {
     412           0 :                 wpa_printf(MSG_ERROR, "daemon: %s", strerror(errno));
     413           0 :                 return -1;
     414             :         }
     415             : 
     416          16 :         eloop_run();
     417             : 
     418          16 :         return 0;
     419             : }
     420             : 
     421             : 
     422          24 : static void show_version(void)
     423             : {
     424          24 :         fprintf(stderr,
     425             :                 "hostapd v" VERSION_STR "\n"
     426             :                 "User space daemon for IEEE 802.11 AP management,\n"
     427             :                 "IEEE 802.1X/WPA/WPA2/EAP/RADIUS Authenticator\n"
     428             :                 "Copyright (c) 2002-2015, Jouni Malinen <j@w1.fi> "
     429             :                 "and contributors\n");
     430          24 : }
     431             : 
     432             : 
     433          18 : static void usage(void)
     434             : {
     435          18 :         show_version();
     436          18 :         fprintf(stderr,
     437             :                 "\n"
     438             :                 "usage: hostapd [-hdBKtv] [-P <PID file>] [-e <entropy file>] "
     439             :                 "\\\n"
     440             :                 "         [-g <global ctrl_iface>] [-G <group>] \\\n"
     441             :                 "         <configuration file(s)>\n"
     442             :                 "\n"
     443             :                 "options:\n"
     444             :                 "   -h   show this usage\n"
     445             :                 "   -d   show more debug messages (-dd for even more)\n"
     446             :                 "   -B   run daemon in the background\n"
     447             :                 "   -e   entropy file\n"
     448             :                 "   -g   global control interface path\n"
     449             :                 "   -G   group for control interfaces\n"
     450             :                 "   -P   PID file\n"
     451             :                 "   -K   include key data in debug messages\n"
     452             : #ifdef CONFIG_DEBUG_FILE
     453             :                 "   -f   log output to debug file instead of stdout\n"
     454             : #endif /* CONFIG_DEBUG_FILE */
     455             : #ifdef CONFIG_DEBUG_LINUX_TRACING
     456             :                 "   -T = record to Linux tracing in addition to logging\n"
     457             :                 "        (records all messages regardless of debug verbosity)\n"
     458             : #endif /* CONFIG_DEBUG_LINUX_TRACING */
     459             :                 "   -t   include timestamps in some debug messages\n"
     460             :                 "   -v   show hostapd version\n");
     461             : 
     462          18 :         exit(1);
     463             : }
     464             : 
     465             : 
     466       80332 : static const char * hostapd_msg_ifname_cb(void *ctx)
     467             : {
     468       80332 :         struct hostapd_data *hapd = ctx;
     469      160664 :         if (hapd && hapd->iconf && hapd->iconf->bss &&
     470      160664 :             hapd->iconf->num_bss > 0 && hapd->iconf->bss[0])
     471       80332 :                 return hapd->iconf->bss[0]->iface;
     472           0 :         return NULL;
     473             : }
     474             : 
     475             : 
     476          25 : static int hostapd_get_global_ctrl_iface(struct hapd_interfaces *interfaces,
     477             :                                          const char *path)
     478             : {
     479             :         char *pos;
     480          25 :         os_free(interfaces->global_iface_path);
     481          25 :         interfaces->global_iface_path = os_strdup(path);
     482          25 :         if (interfaces->global_iface_path == NULL)
     483           0 :                 return -1;
     484          25 :         pos = os_strrchr(interfaces->global_iface_path, '/');
     485          25 :         if (pos == NULL) {
     486           6 :                 wpa_printf(MSG_ERROR, "No '/' in the global control interface "
     487             :                            "file");
     488           6 :                 os_free(interfaces->global_iface_path);
     489           6 :                 interfaces->global_iface_path = NULL;
     490           6 :                 return -1;
     491             :         }
     492             : 
     493          19 :         *pos = '\0';
     494          19 :         interfaces->global_iface_name = pos + 1;
     495             : 
     496          19 :         return 0;
     497             : }
     498             : 
     499             : 
     500          12 : static int hostapd_get_ctrl_iface_group(struct hapd_interfaces *interfaces,
     501             :                                         const char *group)
     502             : {
     503             : #ifndef CONFIG_NATIVE_WINDOWS
     504             :         struct group *grp;
     505          12 :         grp = getgrnam(group);
     506          12 :         if (grp == NULL) {
     507           6 :                 wpa_printf(MSG_ERROR, "Unknown group '%s'", group);
     508           6 :                 return -1;
     509             :         }
     510           6 :         interfaces->ctrl_iface_group = grp->gr_gid;
     511             : #endif /* CONFIG_NATIVE_WINDOWS */
     512           6 :         return 0;
     513             : }
     514             : 
     515             : 
     516             : #ifdef CONFIG_WPS
     517          12 : static int gen_uuid(const char *txt_addr)
     518             : {
     519             :         u8 addr[ETH_ALEN];
     520             :         u8 uuid[UUID_LEN];
     521             :         char buf[100];
     522             : 
     523          12 :         if (hwaddr_aton(txt_addr, addr) < 0)
     524           6 :                 return -1;
     525             : 
     526           6 :         uuid_gen_mac_addr(addr, uuid);
     527           6 :         if (uuid_bin2str(uuid, buf, sizeof(buf)) < 0)
     528           0 :                 return -1;
     529             : 
     530           6 :         printf("%s\n", buf);
     531             : 
     532           6 :         return 0;
     533             : }
     534             : #endif /* CONFIG_WPS */
     535             : 
     536             : 
     537             : #ifndef HOSTAPD_CLEANUP_INTERVAL
     538             : #define HOSTAPD_CLEANUP_INTERVAL 10
     539             : #endif /* HOSTAPD_CLEANUP_INTERVAL */
     540             : 
     541        1474 : static int hostapd_periodic_call(struct hostapd_iface *iface, void *ctx)
     542             : {
     543        1474 :         hostapd_periodic_iface(iface);
     544        1474 :         return 0;
     545             : }
     546             : 
     547             : 
     548             : /* Periodic cleanup tasks */
     549        1078 : static void hostapd_periodic(void *eloop_ctx, void *timeout_ctx)
     550             : {
     551        1078 :         struct hapd_interfaces *interfaces = eloop_ctx;
     552             : 
     553        1078 :         eloop_register_timeout(HOSTAPD_CLEANUP_INTERVAL, 0,
     554             :                                hostapd_periodic, interfaces, NULL);
     555        1078 :         hostapd_for_each_interface(interfaces, hostapd_periodic_call, NULL);
     556        1078 : }
     557             : 
     558             : 
     559          73 : int main(int argc, char *argv[])
     560             : {
     561             :         struct hapd_interfaces interfaces;
     562          73 :         int ret = 1;
     563             :         size_t i, j;
     564          73 :         int c, debug = 0, daemonize = 0;
     565          73 :         char *pid_file = NULL;
     566          73 :         const char *log_file = NULL;
     567          73 :         const char *entropy_file = NULL;
     568          73 :         char **bss_config = NULL, **tmp_bss;
     569          73 :         size_t num_bss_configs = 0;
     570             : #ifdef CONFIG_DEBUG_LINUX_TRACING
     571          73 :         int enable_trace_dbg = 0;
     572             : #endif /* CONFIG_DEBUG_LINUX_TRACING */
     573             : 
     574          73 :         if (os_program_init())
     575           0 :                 return -1;
     576             : 
     577          73 :         os_memset(&interfaces, 0, sizeof(interfaces));
     578          73 :         interfaces.reload_config = hostapd_reload_config;
     579          73 :         interfaces.config_read_cb = hostapd_config_read;
     580          73 :         interfaces.for_each_interface = hostapd_for_each_interface;
     581          73 :         interfaces.ctrl_iface_init = hostapd_ctrl_iface_init;
     582          73 :         interfaces.ctrl_iface_deinit = hostapd_ctrl_iface_deinit;
     583          73 :         interfaces.driver_init = hostapd_driver_init;
     584          73 :         interfaces.global_iface_path = NULL;
     585          73 :         interfaces.global_iface_name = NULL;
     586          73 :         interfaces.global_ctrl_sock = -1;
     587          73 :         interfaces.global_ctrl_dst = NULL;
     588             : 
     589             :         for (;;) {
     590         260 :                 c = getopt(argc, argv, "b:Bde:f:hKP:Ttu:vg:G:");
     591         260 :                 if (c < 0)
     592          31 :                         break;
     593         229 :                 switch (c) {
     594             :                 case 'h':
     595           6 :                         usage();
     596           0 :                         break;
     597             :                 case 'd':
     598          63 :                         debug++;
     599          63 :                         if (wpa_debug_level > 0)
     600          63 :                                 wpa_debug_level--;
     601          63 :                         break;
     602             :                 case 'B':
     603          19 :                         daemonize++;
     604          19 :                         break;
     605             :                 case 'e':
     606           6 :                         entropy_file = optarg;
     607           6 :                         break;
     608             :                 case 'f':
     609          19 :                         log_file = optarg;
     610          19 :                         break;
     611             :                 case 'K':
     612          12 :                         wpa_debug_show_keys++;
     613          12 :                         break;
     614             :                 case 'P':
     615          19 :                         os_free(pid_file);
     616          19 :                         pid_file = os_rel2abs_path(optarg);
     617          19 :                         break;
     618             :                 case 't':
     619          12 :                         wpa_debug_timestamp++;
     620          12 :                         break;
     621             : #ifdef CONFIG_DEBUG_LINUX_TRACING
     622             :                 case 'T':
     623           6 :                         enable_trace_dbg = 1;
     624           6 :                         break;
     625             : #endif /* CONFIG_DEBUG_LINUX_TRACING */
     626             :                 case 'v':
     627           6 :                         show_version();
     628           6 :                         exit(1);
     629             :                         break;
     630             :                 case 'g':
     631          25 :                         if (hostapd_get_global_ctrl_iface(&interfaces, optarg))
     632           6 :                                 return -1;
     633          19 :                         break;
     634             :                 case 'G':
     635          12 :                         if (hostapd_get_ctrl_iface_group(&interfaces, optarg))
     636           6 :                                 return -1;
     637           6 :                         break;
     638             :                 case 'b':
     639           6 :                         tmp_bss = os_realloc_array(bss_config,
     640             :                                                    num_bss_configs + 1,
     641             :                                                    sizeof(char *));
     642           6 :                         if (tmp_bss == NULL)
     643           0 :                                 goto out;
     644           6 :                         bss_config = tmp_bss;
     645           6 :                         bss_config[num_bss_configs++] = optarg;
     646           6 :                         break;
     647             : #ifdef CONFIG_WPS
     648             :                 case 'u':
     649          12 :                         return gen_uuid(optarg);
     650             : #endif /* CONFIG_WPS */
     651             :                 default:
     652           6 :                         usage();
     653           0 :                         break;
     654             :                 }
     655         187 :         }
     656             : 
     657          31 :         if (optind == argc && interfaces.global_iface_path == NULL &&
     658             :             num_bss_configs == 0)
     659           6 :                 usage();
     660             : 
     661          25 :         wpa_msg_register_ifname_cb(hostapd_msg_ifname_cb);
     662             : 
     663          25 :         if (log_file)
     664          19 :                 wpa_debug_open_file(log_file);
     665             :         else
     666           6 :                 wpa_debug_setup_stdout();
     667             : #ifdef CONFIG_DEBUG_LINUX_TRACING
     668          25 :         if (enable_trace_dbg) {
     669           0 :                 int tret = wpa_debug_open_linux_tracing();
     670           0 :                 if (tret) {
     671           0 :                         wpa_printf(MSG_ERROR, "Failed to enable trace logging");
     672           0 :                         return -1;
     673             :                 }
     674             :         }
     675             : #endif /* CONFIG_DEBUG_LINUX_TRACING */
     676             : 
     677          25 :         interfaces.count = argc - optind;
     678          25 :         if (interfaces.count || num_bss_configs) {
     679          19 :                 interfaces.iface = os_calloc(interfaces.count + num_bss_configs,
     680             :                                              sizeof(struct hostapd_iface *));
     681          19 :                 if (interfaces.iface == NULL) {
     682           0 :                         wpa_printf(MSG_ERROR, "malloc failed");
     683           0 :                         return -1;
     684             :                 }
     685             :         }
     686             : 
     687          25 :         if (hostapd_global_init(&interfaces, entropy_file)) {
     688           0 :                 wpa_printf(MSG_ERROR, "Failed to initialize global context");
     689           0 :                 return -1;
     690             :         }
     691             : 
     692          25 :         eloop_register_timeout(HOSTAPD_CLEANUP_INTERVAL, 0,
     693             :                                hostapd_periodic, &interfaces, NULL);
     694             : 
     695          25 :         if (fst_global_init()) {
     696           0 :                 wpa_printf(MSG_ERROR,
     697             :                            "Failed to initialize global FST context");
     698           0 :                 goto out;
     699             :         }
     700             : 
     701             : #if defined(CONFIG_FST) && defined(CONFIG_CTRL_IFACE)
     702          25 :         if (!fst_global_add_ctrl(fst_ctrl_cli))
     703           0 :                 wpa_printf(MSG_WARNING, "Failed to add CLI FST ctrl");
     704             : #endif /* CONFIG_FST && CONFIG_CTRL_IFACE */
     705             : 
     706             :         /* Allocate and parse configuration for full interface files */
     707          53 :         for (i = 0; i < interfaces.count; i++) {
     708          74 :                 interfaces.iface[i] = hostapd_interface_init(&interfaces,
     709          37 :                                                              argv[optind + i],
     710             :                                                              debug);
     711          37 :                 if (!interfaces.iface[i]) {
     712           9 :                         wpa_printf(MSG_ERROR, "Failed to initialize interface");
     713           9 :                         goto out;
     714             :                 }
     715             :         }
     716             : 
     717             :         /* Allocate and parse configuration for per-BSS files */
     718          16 :         for (i = 0; i < num_bss_configs; i++) {
     719             :                 struct hostapd_iface *iface;
     720             :                 char *fname;
     721             : 
     722           0 :                 wpa_printf(MSG_INFO, "BSS config: %s", bss_config[i]);
     723           0 :                 fname = os_strchr(bss_config[i], ':');
     724           0 :                 if (fname == NULL) {
     725           0 :                         wpa_printf(MSG_ERROR,
     726             :                                    "Invalid BSS config identifier '%s'",
     727           0 :                                    bss_config[i]);
     728           0 :                         goto out;
     729             :                 }
     730           0 :                 *fname++ = '\0';
     731           0 :                 iface = hostapd_interface_init_bss(&interfaces, bss_config[i],
     732             :                                                    fname, debug);
     733           0 :                 if (iface == NULL)
     734           0 :                         goto out;
     735           0 :                 for (j = 0; j < interfaces.count; j++) {
     736           0 :                         if (interfaces.iface[j] == iface)
     737           0 :                                 break;
     738             :                 }
     739           0 :                 if (j == interfaces.count) {
     740             :                         struct hostapd_iface **tmp;
     741           0 :                         tmp = os_realloc_array(interfaces.iface,
     742           0 :                                                interfaces.count + 1,
     743             :                                                sizeof(struct hostapd_iface *));
     744           0 :                         if (tmp == NULL) {
     745           0 :                                 hostapd_interface_deinit_free(iface);
     746           0 :                                 goto out;
     747             :                         }
     748           0 :                         interfaces.iface = tmp;
     749           0 :                         interfaces.iface[interfaces.count++] = iface;
     750             :                 }
     751             :         }
     752             : 
     753             :         /*
     754             :          * Enable configured interfaces. Depending on channel configuration,
     755             :          * this may complete full initialization before returning or use a
     756             :          * callback mechanism to complete setup in case of operations like HT
     757             :          * co-ex scans, ACS, or DFS are needed to determine channel parameters.
     758             :          * In such case, the interface will be enabled from eloop context within
     759             :          * hostapd_global_run().
     760             :          */
     761          16 :         interfaces.terminate_on_error = interfaces.count;
     762          35 :         for (i = 0; i < interfaces.count; i++) {
     763          38 :                 if (hostapd_driver_init(interfaces.iface[i]) ||
     764          19 :                     hostapd_setup_interface(interfaces.iface[i]))
     765             :                         goto out;
     766             :         }
     767             : 
     768          16 :         hostapd_global_ctrl_iface_init(&interfaces);
     769             : 
     770          16 :         if (hostapd_global_run(&interfaces, daemonize, pid_file)) {
     771           0 :                 wpa_printf(MSG_ERROR, "Failed to start eloop");
     772           0 :                 goto out;
     773             :         }
     774             : 
     775          16 :         ret = 0;
     776             : 
     777             :  out:
     778          25 :         hostapd_global_ctrl_iface_deinit(&interfaces);
     779             :         /* Deinitialize all interfaces */
     780          62 :         for (i = 0; i < interfaces.count; i++) {
     781          37 :                 if (!interfaces.iface[i])
     782           9 :                         continue;
     783          56 :                 interfaces.iface[i]->driver_ap_teardown =
     784          28 :                         !!(interfaces.iface[i]->drv_flags &
     785             :                            WPA_DRIVER_FLAGS_AP_TEARDOWN_SUPPORT);
     786          28 :                 hostapd_interface_deinit_free(interfaces.iface[i]);
     787             :         }
     788          25 :         os_free(interfaces.iface);
     789             : 
     790          25 :         eloop_cancel_timeout(hostapd_periodic, &interfaces, NULL);
     791          25 :         hostapd_global_deinit(pid_file);
     792          25 :         os_free(pid_file);
     793             : 
     794          25 :         if (log_file)
     795          19 :                 wpa_debug_close_file();
     796          25 :         wpa_debug_close_linux_tracing();
     797             : 
     798          25 :         os_free(bss_config);
     799             : 
     800          25 :         fst_global_deinit();
     801             : 
     802          25 :         os_program_deinit();
     803             : 
     804          25 :         return ret;
     805             : }

Generated by: LCOV version 1.10