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 1475438200 Lines: 315 438 71.9 %
Date: 2016-10-02 Functions: 16 20 80.0 %

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

Generated by: LCOV version 1.10