LCOV - code coverage report
Current view: top level - wpa_supplicant - mesh.c (source / functions) Hit Total Coverage
Test: wpa_supplicant/hostapd combined for hwsim test run 1426431149 Lines: 234 290 80.7 %
Date: 2015-03-15 Functions: 13 13 100.0 %

          Line data    Source code
       1             : /*
       2             :  * WPA Supplicant - Basic mesh mode routines
       3             :  * Copyright (c) 2013-2014, cozybit, Inc.  All rights reserved.
       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             : 
      11             : #include "utils/common.h"
      12             : #include "utils/eloop.h"
      13             : #include "utils/uuid.h"
      14             : #include "common/ieee802_11_defs.h"
      15             : #include "common/wpa_ctrl.h"
      16             : #include "ap/sta_info.h"
      17             : #include "ap/hostapd.h"
      18             : #include "ap/ieee802_11.h"
      19             : #include "config_ssid.h"
      20             : #include "config.h"
      21             : #include "wpa_supplicant_i.h"
      22             : #include "driver_i.h"
      23             : #include "notify.h"
      24             : #include "ap.h"
      25             : #include "mesh_mpm.h"
      26             : #include "mesh_rsn.h"
      27             : #include "mesh.h"
      28             : 
      29             : 
      30          68 : static void wpa_supplicant_mesh_deinit(struct wpa_supplicant *wpa_s)
      31             : {
      32          68 :         wpa_supplicant_mesh_iface_deinit(wpa_s, wpa_s->ifmsh);
      33          68 :         wpa_s->ifmsh = NULL;
      34          68 :         wpa_s->current_ssid = NULL;
      35          68 :         os_free(wpa_s->mesh_rsn);
      36          68 :         wpa_s->mesh_rsn = NULL;
      37             :         /* TODO: leave mesh (stop beacon). This will happen on link down
      38             :          * anyway, so it's not urgent */
      39          68 : }
      40             : 
      41             : 
      42          68 : void wpa_supplicant_mesh_iface_deinit(struct wpa_supplicant *wpa_s,
      43             :                                       struct hostapd_iface *ifmsh)
      44             : {
      45          68 :         if (!ifmsh)
      46         102 :                 return;
      47             : 
      48          34 :         if (ifmsh->mconf) {
      49          34 :                 mesh_mpm_deinit(wpa_s, ifmsh);
      50          34 :                 if (ifmsh->mconf->ies) {
      51          12 :                         ifmsh->mconf->ies = NULL;
      52             :                         /* We cannot free this struct
      53             :                          * because wpa_authenticator on
      54             :                          * hostapd side is also using it
      55             :                          * for now just set to NULL and
      56             :                          * let hostapd code free it.
      57             :                          */
      58             :                 }
      59          34 :                 os_free(ifmsh->mconf);
      60          34 :                 ifmsh->mconf = NULL;
      61             :         }
      62             : 
      63             :         /* take care of shared data */
      64          34 :         hostapd_interface_deinit(ifmsh);
      65          34 :         hostapd_interface_free(ifmsh);
      66             : }
      67             : 
      68             : 
      69          34 : static struct mesh_conf * mesh_config_create(struct wpa_ssid *ssid)
      70             : {
      71             :         struct mesh_conf *conf;
      72             : 
      73          34 :         conf = os_zalloc(sizeof(struct mesh_conf));
      74          34 :         if (!conf)
      75           0 :                 return NULL;
      76             : 
      77          34 :         os_memcpy(conf->meshid, ssid->ssid, ssid->ssid_len);
      78          34 :         conf->meshid_len = ssid->ssid_len;
      79             : 
      80          34 :         if (ssid->key_mgmt & WPA_KEY_MGMT_SAE)
      81          13 :                 conf->security |= MESH_CONF_SEC_AUTH |
      82             :                         MESH_CONF_SEC_AMPE;
      83             :         else
      84          21 :                 conf->security |= MESH_CONF_SEC_NONE;
      85             : 
      86             :         /* defaults */
      87          34 :         conf->mesh_pp_id = MESH_PATH_PROTOCOL_HWMP;
      88          34 :         conf->mesh_pm_id = MESH_PATH_METRIC_AIRTIME;
      89          34 :         conf->mesh_cc_id = 0;
      90          34 :         conf->mesh_sp_id = MESH_SYNC_METHOD_NEIGHBOR_OFFSET;
      91          34 :         conf->mesh_auth_id = (conf->security & MESH_CONF_SEC_AUTH) ? 1 : 0;
      92          34 :         conf->dot11MeshMaxRetries = ssid->dot11MeshMaxRetries;
      93          34 :         conf->dot11MeshRetryTimeout = ssid->dot11MeshRetryTimeout;
      94          34 :         conf->dot11MeshConfirmTimeout = ssid->dot11MeshConfirmTimeout;
      95          34 :         conf->dot11MeshHoldingTimeout = ssid->dot11MeshHoldingTimeout;
      96             : 
      97          34 :         return conf;
      98             : }
      99             : 
     100             : 
     101           5 : static void wpas_mesh_copy_groups(struct hostapd_data *bss,
     102             :                                   struct wpa_supplicant *wpa_s)
     103             : {
     104             :         int num_groups;
     105             :         size_t groups_size;
     106             : 
     107          16 :         for (num_groups = 0; wpa_s->conf->sae_groups[num_groups] > 0;
     108           6 :              num_groups++)
     109             :                 ;
     110             : 
     111           5 :         groups_size = (num_groups + 1) * sizeof(wpa_s->conf->sae_groups[0]);
     112           5 :         bss->conf->sae_groups = os_malloc(groups_size);
     113           5 :         if (bss->conf->sae_groups)
     114           5 :                 os_memcpy(bss->conf->sae_groups, wpa_s->conf->sae_groups,
     115             :                           groups_size);
     116           5 : }
     117             : 
     118             : 
     119          34 : static int wpa_supplicant_mesh_init(struct wpa_supplicant *wpa_s,
     120             :                                     struct wpa_ssid *ssid)
     121             : {
     122             :         struct hostapd_iface *ifmsh;
     123             :         struct hostapd_data *bss;
     124             :         struct hostapd_config *conf;
     125             :         struct mesh_conf *mconf;
     126          34 :         int basic_rates_erp[] = { 10, 20, 55, 60, 110, 120, 240, -1 };
     127             :         static int default_groups[] = { 19, 20, 21, 25, 26, -1 };
     128             :         size_t len;
     129             :         int rate_len;
     130             : 
     131          34 :         if (!wpa_s->conf->user_mpm) {
     132             :                 /* not much for us to do here */
     133           0 :                 wpa_msg(wpa_s, MSG_WARNING,
     134             :                         "user_mpm is not enabled in configuration");
     135           0 :                 return 0;
     136             :         }
     137             : 
     138          34 :         wpa_s->ifmsh = ifmsh = os_zalloc(sizeof(*wpa_s->ifmsh));
     139          34 :         if (!ifmsh)
     140           0 :                 return -ENOMEM;
     141             : 
     142          34 :         ifmsh->drv_flags = wpa_s->drv_flags;
     143          34 :         ifmsh->num_bss = 1;
     144          34 :         ifmsh->bss = os_calloc(wpa_s->ifmsh->num_bss,
     145             :                                sizeof(struct hostapd_data *));
     146          34 :         if (!ifmsh->bss)
     147           0 :                 goto out_free;
     148             : 
     149          34 :         ifmsh->bss[0] = bss = os_zalloc(sizeof(struct hostapd_data));
     150          34 :         if (!bss)
     151           0 :                 goto out_free;
     152             : 
     153          34 :         os_memcpy(bss->own_addr, wpa_s->own_addr, ETH_ALEN);
     154          34 :         bss->driver = wpa_s->driver;
     155          34 :         bss->drv_priv = wpa_s->drv_priv;
     156          34 :         bss->iface = ifmsh;
     157          34 :         bss->mesh_sta_free_cb = mesh_mpm_free_sta;
     158          34 :         wpa_s->assoc_freq = ssid->frequency;
     159          34 :         wpa_s->current_ssid = ssid;
     160             : 
     161             :         /* setup an AP config for auth processing */
     162          34 :         conf = hostapd_config_defaults();
     163          34 :         if (!conf)
     164           0 :                 goto out_free;
     165             : 
     166          34 :         bss->conf = *conf->bss;
     167          34 :         bss->conf->start_disabled = 1;
     168          34 :         bss->conf->mesh = MESH_ENABLED;
     169          34 :         bss->conf->ap_max_inactivity = wpa_s->conf->mesh_max_inactivity;
     170          34 :         bss->iconf = conf;
     171          34 :         ifmsh->conf = conf;
     172             : 
     173          34 :         ifmsh->bss[0]->max_plinks = wpa_s->conf->max_peer_links;
     174          34 :         os_strlcpy(bss->conf->iface, wpa_s->ifname, sizeof(bss->conf->iface));
     175             : 
     176          34 :         mconf = mesh_config_create(ssid);
     177          34 :         if (!mconf)
     178           0 :                 goto out_free;
     179          34 :         ifmsh->mconf = mconf;
     180             : 
     181             :         /* need conf->hw_mode for supported rates. */
     182          34 :         if (ssid->frequency == 0) {
     183           0 :                 conf->hw_mode = HOSTAPD_MODE_IEEE80211G;
     184           0 :                 conf->channel = 1;
     185             :         } else {
     186          34 :                 conf->hw_mode = ieee80211_freq_to_chan(ssid->frequency,
     187             :                                                        &conf->channel);
     188             :         }
     189          34 :         if (conf->hw_mode == NUM_HOSTAPD_MODES) {
     190           0 :                 wpa_printf(MSG_ERROR, "Unsupported mesh mode frequency: %d MHz",
     191             :                            ssid->frequency);
     192           0 :                 goto out_free;
     193             :         }
     194             : 
     195          34 :         if (ssid->mesh_basic_rates == NULL) {
     196             :                 /*
     197             :                  * XXX: Hack! This is so an MPM which correctly sets the ERP
     198             :                  * mandatory rates as BSSBasicRateSet doesn't reject us. We
     199             :                  * could add a new hw_mode HOSTAPD_MODE_IEEE80211G_ERP, but
     200             :                  * this is way easier. This also makes our BSSBasicRateSet
     201             :                  * advertised in beacons match the one in peering frames, sigh.
     202             :                  */
     203          34 :                 if (conf->hw_mode == HOSTAPD_MODE_IEEE80211G) {
     204          32 :                         conf->basic_rates = os_malloc(sizeof(basic_rates_erp));
     205          32 :                         if (!conf->basic_rates)
     206           0 :                                 goto out_free;
     207          32 :                         os_memcpy(conf->basic_rates, basic_rates_erp,
     208             :                                   sizeof(basic_rates_erp));
     209             :                 }
     210             :         } else {
     211           0 :                 rate_len = 0;
     212             :                 while (1) {
     213           0 :                         if (ssid->mesh_basic_rates[rate_len] < 1)
     214           0 :                                 break;
     215           0 :                         rate_len++;
     216           0 :                 }
     217           0 :                 conf->basic_rates = os_calloc(rate_len + 1, sizeof(int));
     218           0 :                 if (conf->basic_rates == NULL)
     219           0 :                         goto out_free;
     220           0 :                 os_memcpy(conf->basic_rates, ssid->mesh_basic_rates,
     221             :                           rate_len * sizeof(int));
     222           0 :                 conf->basic_rates[rate_len] = -1;
     223             :         }
     224             : 
     225          34 :         if (hostapd_setup_interface(ifmsh)) {
     226           0 :                 wpa_printf(MSG_ERROR,
     227             :                            "Failed to initialize hostapd interface for mesh");
     228           0 :                 return -1;
     229             :         }
     230             : 
     231          34 :         if (wpa_drv_init_mesh(wpa_s)) {
     232           0 :                 wpa_msg(wpa_s, MSG_ERROR, "Failed to init mesh in driver");
     233           0 :                 return -1;
     234             :         }
     235             : 
     236          34 :         if (mconf->security != MESH_CONF_SEC_NONE) {
     237          13 :                 if (ssid->passphrase == NULL) {
     238           1 :                         wpa_printf(MSG_ERROR,
     239             :                                    "mesh: Passphrase for SAE not configured");
     240           1 :                         goto out_free;
     241             :                 }
     242             : 
     243          12 :                 bss->conf->wpa = ssid->proto;
     244          12 :                 bss->conf->wpa_key_mgmt = ssid->key_mgmt;
     245             : 
     246          24 :                 if (wpa_s->conf->sae_groups &&
     247          12 :                     wpa_s->conf->sae_groups[0] > 0) {
     248           5 :                         wpas_mesh_copy_groups(bss, wpa_s);
     249             :                 } else {
     250          14 :                         bss->conf->sae_groups =
     251           7 :                                 os_malloc(sizeof(default_groups));
     252           7 :                         if (!bss->conf->sae_groups)
     253           0 :                                 goto out_free;
     254           7 :                         os_memcpy(bss->conf->sae_groups, default_groups,
     255             :                                   sizeof(default_groups));
     256             :                 }
     257             : 
     258          12 :                 len = os_strlen(ssid->passphrase);
     259          24 :                 bss->conf->ssid.wpa_passphrase =
     260          12 :                         dup_binstr(ssid->passphrase, len);
     261             : 
     262          12 :                 wpa_s->mesh_rsn = mesh_rsn_auth_init(wpa_s, mconf);
     263          12 :                 if (!wpa_s->mesh_rsn)
     264           0 :                         goto out_free;
     265             :         }
     266             : 
     267          33 :         wpa_supplicant_conf_ap_ht(wpa_s, ssid, conf);
     268             : 
     269          33 :         return 0;
     270             : out_free:
     271           1 :         wpa_supplicant_mesh_deinit(wpa_s);
     272           1 :         return -ENOMEM;
     273             : }
     274             : 
     275             : 
     276          54 : void wpa_mesh_notify_peer(struct wpa_supplicant *wpa_s, const u8 *addr,
     277             :                           const u8 *ies, size_t ie_len)
     278             : {
     279             :         struct ieee802_11_elems elems;
     280             : 
     281         324 :         wpa_msg(wpa_s, MSG_INFO,
     282         324 :                 "new peer notification for " MACSTR, MAC2STR(addr));
     283             : 
     284          54 :         if (ieee802_11_parse_elems(ies, ie_len, &elems, 0) == ParseFailed) {
     285           0 :                 wpa_msg(wpa_s, MSG_INFO, "Could not parse beacon from " MACSTR,
     286           0 :                         MAC2STR(addr));
     287          54 :                 return;
     288             :         }
     289          54 :         wpa_mesh_new_mesh_peer(wpa_s, addr, &elems);
     290             : }
     291             : 
     292             : 
     293        2020 : void wpa_supplicant_mesh_add_scan_ie(struct wpa_supplicant *wpa_s,
     294             :                                      struct wpabuf **extra_ie)
     295             : {
     296             :         /* EID + 0-length (wildcard) mesh-id */
     297        2020 :         size_t ielen = 2;
     298             : 
     299        2020 :         if (wpabuf_resize(extra_ie, ielen) == 0) {
     300        2020 :                 wpabuf_put_u8(*extra_ie, WLAN_EID_MESH_ID);
     301        2020 :                 wpabuf_put_u8(*extra_ie, 0);
     302             :         }
     303        2020 : }
     304             : 
     305             : 
     306          34 : int wpa_supplicant_join_mesh(struct wpa_supplicant *wpa_s,
     307             :                              struct wpa_ssid *ssid)
     308             : {
     309             :         struct wpa_driver_mesh_join_params params;
     310          34 :         int ret = 0;
     311             : 
     312          34 :         if (!ssid || !ssid->ssid || !ssid->ssid_len || !ssid->frequency) {
     313           0 :                 ret = -ENOENT;
     314           0 :                 goto out;
     315             :         }
     316             : 
     317          34 :         wpa_supplicant_mesh_deinit(wpa_s);
     318             : 
     319          34 :         os_memset(&params, 0, sizeof(params));
     320          34 :         params.meshid = ssid->ssid;
     321          34 :         params.meshid_len = ssid->ssid_len;
     322          34 :         ibss_mesh_setup_freq(wpa_s, ssid, &params.freq);
     323          34 :         wpa_s->mesh_ht_enabled = !!params.freq.ht_enabled;
     324          34 :         if (ssid->beacon_int > 0)
     325           3 :                 params.beacon_int = ssid->beacon_int;
     326          31 :         else if (wpa_s->conf->beacon_int > 0)
     327           0 :                 params.beacon_int = wpa_s->conf->beacon_int;
     328          34 :         params.max_peer_links = wpa_s->conf->max_peer_links;
     329             : 
     330          34 :         if (ssid->key_mgmt & WPA_KEY_MGMT_SAE) {
     331          13 :                 params.flags |= WPA_DRIVER_MESH_FLAG_SAE_AUTH;
     332          13 :                 params.flags |= WPA_DRIVER_MESH_FLAG_AMPE;
     333          13 :                 wpa_s->conf->user_mpm = 1;
     334             :         }
     335             : 
     336          34 :         if (wpa_s->conf->user_mpm) {
     337          34 :                 params.flags |= WPA_DRIVER_MESH_FLAG_USER_MPM;
     338          34 :                 params.conf.flags &= ~WPA_DRIVER_MESH_CONF_FLAG_AUTO_PLINKS;
     339             :         } else {
     340           0 :                 params.flags |= WPA_DRIVER_MESH_FLAG_DRIVER_MPM;
     341           0 :                 params.conf.flags |= WPA_DRIVER_MESH_CONF_FLAG_AUTO_PLINKS;
     342             :         }
     343          34 :         params.conf.peer_link_timeout = wpa_s->conf->mesh_max_inactivity;
     344             : 
     345          34 :         if (wpa_supplicant_mesh_init(wpa_s, ssid)) {
     346           1 :                 wpa_msg(wpa_s, MSG_ERROR, "Failed to init mesh");
     347           1 :                 wpa_drv_leave_mesh(wpa_s);
     348           1 :                 ret = -1;
     349           1 :                 goto out;
     350             :         }
     351             : 
     352          33 :         if (wpa_s->ifmsh) {
     353          33 :                 params.ies = wpa_s->ifmsh->mconf->ies;
     354          33 :                 params.ie_len = wpa_s->ifmsh->mconf->ie_len;
     355          33 :                 params.basic_rates = wpa_s->ifmsh->basic_rates;
     356             :         }
     357             : 
     358          66 :         wpa_msg(wpa_s, MSG_INFO, "joining mesh %s",
     359          33 :                 wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
     360          33 :         ret = wpa_drv_join_mesh(wpa_s, &params);
     361          33 :         if (ret)
     362           0 :                 wpa_msg(wpa_s, MSG_ERROR, "mesh join error=%d\n", ret);
     363             : 
     364             :         /* hostapd sets the interface down until we associate */
     365          33 :         wpa_drv_set_operstate(wpa_s, 1);
     366             : 
     367             : out:
     368          34 :         return ret;
     369             : }
     370             : 
     371             : 
     372          33 : int wpa_supplicant_leave_mesh(struct wpa_supplicant *wpa_s)
     373             : {
     374          33 :         int ret = 0;
     375             : 
     376          33 :         wpa_msg(wpa_s, MSG_INFO, "leaving mesh");
     377             : 
     378             :         /* Need to send peering close messages first */
     379          33 :         wpa_supplicant_mesh_deinit(wpa_s);
     380             : 
     381          33 :         ret = wpa_drv_leave_mesh(wpa_s);
     382          33 :         if (ret)
     383           0 :                 wpa_msg(wpa_s, MSG_ERROR, "mesh leave error=%d", ret);
     384             : 
     385          33 :         wpa_drv_set_operstate(wpa_s, 1);
     386             : 
     387          33 :         return ret;
     388             : }
     389             : 
     390             : 
     391         423 : static int mesh_attr_text(const u8 *ies, size_t ies_len, char *buf, char *end)
     392             : {
     393             :         struct ieee802_11_elems elems;
     394         423 :         char *mesh_id, *pos = buf;
     395             :         u8 *bss_basic_rate_set;
     396             :         int bss_basic_rate_set_len, ret, i;
     397             : 
     398         423 :         if (ieee802_11_parse_elems(ies, ies_len, &elems, 0) == ParseFailed)
     399           0 :                 return -1;
     400             : 
     401         423 :         if (elems.mesh_id_len < 1)
     402         422 :                 return 0;
     403             : 
     404           1 :         mesh_id = os_malloc(elems.mesh_id_len + 1);
     405           1 :         if (mesh_id == NULL)
     406           0 :                 return -1;
     407             : 
     408           1 :         os_memcpy(mesh_id, elems.mesh_id, elems.mesh_id_len);
     409           1 :         mesh_id[elems.mesh_id_len] = '\0';
     410           1 :         ret = os_snprintf(pos, end - pos, "mesh_id=%s\n", mesh_id);
     411           1 :         os_free(mesh_id);
     412           1 :         if (os_snprintf_error(end - pos, ret))
     413           0 :                 return pos - buf;
     414           1 :         pos += ret;
     415             : 
     416           1 :         if (elems.mesh_config_len > 6) {
     417           7 :                 ret = os_snprintf(pos, end - pos,
     418             :                                   "active_path_selection_protocol_id=0x%02x\n"
     419             :                                   "active_path_selection_metric_id=0x%02x\n"
     420             :                                   "congestion_control_mode_id=0x%02x\n"
     421             :                                   "synchronization_method_id=0x%02x\n"
     422             :                                   "authentication_protocol_id=0x%02x\n"
     423             :                                   "mesh_formation_info=0x%02x\n"
     424             :                                   "mesh_capability=0x%02x\n",
     425           2 :                                   elems.mesh_config[0], elems.mesh_config[1],
     426           2 :                                   elems.mesh_config[2], elems.mesh_config[3],
     427           2 :                                   elems.mesh_config[4], elems.mesh_config[5],
     428           1 :                                   elems.mesh_config[6]);
     429           1 :                 if (os_snprintf_error(end - pos, ret))
     430           0 :                         return pos - buf;
     431           1 :                 pos += ret;
     432             :         }
     433             : 
     434           2 :         bss_basic_rate_set = os_malloc(elems.supp_rates_len +
     435           1 :                 elems.ext_supp_rates_len);
     436           1 :         if (bss_basic_rate_set == NULL)
     437           0 :                 return -1;
     438             : 
     439           1 :         bss_basic_rate_set_len = 0;
     440           9 :         for (i = 0; i < elems.supp_rates_len; i++) {
     441           8 :                 if (elems.supp_rates[i] & 0x80) {
     442          12 :                         bss_basic_rate_set[bss_basic_rate_set_len++] =
     443           6 :                                 (elems.supp_rates[i] & 0x7f) * 5;
     444             :                 }
     445             :         }
     446           5 :         for (i = 0; i < elems.ext_supp_rates_len; i++) {
     447           4 :                 if (elems.ext_supp_rates[i] & 0x80) {
     448           2 :                         bss_basic_rate_set[bss_basic_rate_set_len++] =
     449           1 :                                 (elems.ext_supp_rates[i] & 0x7f) * 5;
     450             :                 }
     451             :         }
     452           1 :         if (bss_basic_rate_set_len > 0) {
     453           1 :                 ret = os_snprintf(pos, end - pos, "bss_basic_rate_set=%d",
     454           1 :                                   bss_basic_rate_set[0]);
     455           1 :                 if (os_snprintf_error(end - pos, ret))
     456           0 :                         return pos - buf;
     457           1 :                 pos += ret;
     458             : 
     459           7 :                 for (i = 1; i < bss_basic_rate_set_len; i++) {
     460           6 :                         ret = os_snprintf(pos, end - pos, " %d",
     461           6 :                                           bss_basic_rate_set[i]);
     462           6 :                         if (os_snprintf_error(end - pos, ret))
     463           0 :                                 return pos - buf;
     464           6 :                         pos += ret;
     465             :                 }
     466             : 
     467           1 :                 ret = os_snprintf(pos, end - pos, "\n");
     468           1 :                 if (os_snprintf_error(end - pos, ret))
     469           0 :                         return pos - buf;
     470           1 :                 pos += ret;
     471             :         }
     472           1 :         os_free(bss_basic_rate_set);
     473             : 
     474           1 :         return pos - buf;
     475             : }
     476             : 
     477             : 
     478         423 : int wpas_mesh_scan_result_text(const u8 *ies, size_t ies_len, char *buf,
     479             :                                char *end)
     480             : {
     481         423 :         return mesh_attr_text(ies, ies_len, buf, end);
     482             : }
     483             : 
     484             : 
     485           2 : static int wpas_mesh_get_ifname(struct wpa_supplicant *wpa_s, char *ifname,
     486             :                                 size_t len)
     487             : {
     488           2 :         char *ifname_ptr = wpa_s->ifname;
     489             :         int res;
     490             : 
     491           2 :         res = os_snprintf(ifname, len, "mesh-%s-%d", ifname_ptr,
     492             :                           wpa_s->mesh_if_idx);
     493           4 :         if (os_snprintf_error(len, res) ||
     494           2 :             (os_strlen(ifname) >= IFNAMSIZ &&
     495           0 :              os_strlen(wpa_s->ifname) < IFNAMSIZ)) {
     496             :                 /* Try to avoid going over the IFNAMSIZ length limit */
     497           0 :                 res = os_snprintf(ifname, len, "mesh-%d", wpa_s->mesh_if_idx);
     498           0 :                 if (os_snprintf_error(len, res))
     499           0 :                         return -1;
     500             :         }
     501           2 :         wpa_s->mesh_if_idx++;
     502           2 :         return 0;
     503             : }
     504             : 
     505             : 
     506           4 : int wpas_mesh_add_interface(struct wpa_supplicant *wpa_s, char *ifname,
     507             :                             size_t len)
     508             : {
     509             :         struct wpa_interface iface;
     510             :         struct wpa_supplicant *mesh_wpa_s;
     511             :         u8 addr[ETH_ALEN];
     512             : 
     513           4 :         if (ifname[0] == '\0' && wpas_mesh_get_ifname(wpa_s, ifname, len) < 0)
     514           0 :                 return -1;
     515             : 
     516           4 :         if (wpa_drv_if_add(wpa_s, WPA_IF_MESH, ifname, NULL, NULL, NULL, addr,
     517             :                            NULL) < 0) {
     518           0 :                 wpa_printf(MSG_ERROR,
     519             :                            "mesh: Failed to create new mesh interface");
     520           0 :                 return -1;
     521             :         }
     522          24 :         wpa_printf(MSG_INFO, "mesh: Created virtual interface %s addr "
     523          24 :                    MACSTR, ifname, MAC2STR(addr));
     524             : 
     525           4 :         os_memset(&iface, 0, sizeof(iface));
     526           4 :         iface.ifname = ifname;
     527           4 :         iface.driver = wpa_s->driver->name;
     528           4 :         iface.driver_param = wpa_s->conf->driver_param;
     529           4 :         iface.ctrl_interface = wpa_s->conf->ctrl_interface;
     530             : 
     531           4 :         mesh_wpa_s = wpa_supplicant_add_iface(wpa_s->global, &iface, wpa_s);
     532           4 :         if (!mesh_wpa_s) {
     533           0 :                 wpa_printf(MSG_ERROR,
     534             :                            "mesh: Failed to create new wpa_supplicant interface");
     535           0 :                 wpa_supplicant_remove_iface(wpa_s->global, wpa_s, 0);
     536           0 :                 return -1;
     537             :         }
     538           4 :         mesh_wpa_s->mesh_if_created = 1;
     539           4 :         return 0;
     540             : }

Generated by: LCOV version 1.10