LCOV - code coverage report
Current view: top level - src/ap - rrm.c (source / functions) Hit Total Coverage
Test: wpa_supplicant/hostapd combined for hwsim test run 1475438200 Lines: 157 261 60.2 %
Date: 2016-10-02 Functions: 11 14 78.6 %

          Line data    Source code
       1             : /*
       2             :  * hostapd / Radio Measurement (RRM)
       3             :  * Copyright(c) 2013 - 2016 Intel Mobile Communications GmbH.
       4             :  * Copyright(c) 2011 - 2016 Intel Corporation. All rights reserved.
       5             :  *
       6             :  * This software may be distributed under the terms of the BSD license.
       7             :  * See README for more details.
       8             :  */
       9             : 
      10             : #include "utils/includes.h"
      11             : 
      12             : #include "utils/common.h"
      13             : #include "hostapd.h"
      14             : #include "ap_drv_ops.h"
      15             : #include "sta_info.h"
      16             : #include "eloop.h"
      17             : #include "neighbor_db.h"
      18             : #include "rrm.h"
      19             : 
      20             : #define HOSTAPD_RRM_REQUEST_TIMEOUT 5
      21             : 
      22             : 
      23           0 : static void hostapd_lci_rep_timeout_handler(void *eloop_data, void *user_ctx)
      24             : {
      25           0 :         struct hostapd_data *hapd = eloop_data;
      26             : 
      27           0 :         wpa_printf(MSG_DEBUG, "RRM: LCI request (token %u) timed out",
      28           0 :                    hapd->lci_req_token);
      29           0 :         hapd->lci_req_active = 0;
      30           0 : }
      31             : 
      32             : 
      33           1 : static void hostapd_handle_lci_report(struct hostapd_data *hapd, u8 token,
      34             :                                       const u8 *pos, size_t len)
      35             : {
      36           1 :         if (!hapd->lci_req_active || hapd->lci_req_token != token) {
      37           0 :                 wpa_printf(MSG_DEBUG, "Unexpected LCI report, token %u", token);
      38           1 :                 return;
      39             :         }
      40             : 
      41           1 :         hapd->lci_req_active = 0;
      42           1 :         eloop_cancel_timeout(hostapd_lci_rep_timeout_handler, hapd, NULL);
      43           1 :         wpa_printf(MSG_DEBUG, "LCI report token %u len %zu", token, len);
      44             : }
      45             : 
      46             : 
      47           0 : static void hostapd_range_rep_timeout_handler(void *eloop_data, void *user_ctx)
      48             : {
      49           0 :         struct hostapd_data *hapd = eloop_data;
      50             : 
      51           0 :         wpa_printf(MSG_DEBUG, "RRM: Range request (token %u) timed out",
      52           0 :                    hapd->range_req_token);
      53           0 :         hapd->range_req_active = 0;
      54           0 : }
      55             : 
      56             : 
      57           0 : static void hostapd_handle_range_report(struct hostapd_data *hapd, u8 token,
      58             :                                         const u8 *pos, size_t len)
      59             : {
      60           0 :         if (!hapd->range_req_active || hapd->range_req_token != token) {
      61           0 :                 wpa_printf(MSG_DEBUG, "Unexpected range report, token %u",
      62             :                            token);
      63           0 :                 return;
      64             :         }
      65             : 
      66           0 :         hapd->range_req_active = 0;
      67           0 :         eloop_cancel_timeout(hostapd_range_rep_timeout_handler, hapd, NULL);
      68           0 :         wpa_printf(MSG_DEBUG, "Range report token %u len %zu", token, len);
      69             : }
      70             : 
      71             : 
      72           1 : static void hostapd_handle_radio_msmt_report(struct hostapd_data *hapd,
      73             :                                              const u8 *buf, size_t len)
      74             : {
      75           1 :         const struct ieee80211_mgmt *mgmt = (const struct ieee80211_mgmt *) buf;
      76             :         const u8 *pos, *ie, *end;
      77             :         u8 token;
      78             : 
      79           1 :         end = buf + len;
      80           1 :         token = mgmt->u.action.u.rrm.dialog_token;
      81           1 :         pos = mgmt->u.action.u.rrm.variable;
      82             : 
      83           3 :         while ((ie = get_ie(pos, end - pos, WLAN_EID_MEASURE_REPORT))) {
      84           1 :                 if (ie[1] < 5) {
      85           0 :                         wpa_printf(MSG_DEBUG, "Bad Measurement Report element");
      86           0 :                         break;
      87             :                 }
      88             : 
      89           1 :                 wpa_printf(MSG_DEBUG, "Measurement report type %u", ie[4]);
      90             : 
      91           1 :                 switch (ie[4]) {
      92             :                 case MEASURE_TYPE_LCI:
      93           1 :                         hostapd_handle_lci_report(hapd, token, ie + 2, ie[1]);
      94           1 :                         break;
      95             :                 case MEASURE_TYPE_FTM_RANGE:
      96           0 :                         hostapd_handle_range_report(hapd, token, ie + 2, ie[1]);
      97           0 :                         break;
      98             :                 default:
      99           0 :                         wpa_printf(MSG_DEBUG,
     100             :                                    "Measurement report type %u is not supported",
     101           0 :                                    ie[4]);
     102           0 :                         break;
     103             :                 }
     104             : 
     105           1 :                 pos = ie + ie[1] + 2;
     106             :         }
     107           1 : }
     108             : 
     109             : 
     110           9 : static u16 hostapd_parse_location_lci_req_age(const u8 *buf, size_t len)
     111             : {
     112             :         const u8 *subelem;
     113             : 
     114             :         /* Range Request element + Location Subject + Maximum Age subelement */
     115           9 :         if (len < 3 + 1 + 4)
     116           0 :                 return 0;
     117             : 
     118             :         /* Subelements are arranged as IEs */
     119           9 :         subelem = get_ie(buf + 4, len - 4, LCI_REQ_SUBELEM_MAX_AGE);
     120           9 :         if (subelem && subelem[1] == 2)
     121           9 :                 return *(u16 *) (subelem + 2);
     122             : 
     123           0 :         return 0;
     124             : }
     125             : 
     126             : 
     127          10 : static int hostapd_check_lci_age(struct hostapd_neighbor_entry *nr, u16 max_age)
     128             : {
     129             :         struct os_time curr, diff;
     130             :         unsigned long diff_l;
     131             : 
     132          10 :         if (!max_age)
     133           0 :                 return 0;
     134             : 
     135          10 :         if (max_age == 0xffff)
     136          10 :                 return 1;
     137             : 
     138           0 :         if (os_get_time(&curr))
     139           0 :                 return 0;
     140             : 
     141           0 :         os_time_sub(&curr, &nr->lci_date, &diff);
     142             : 
     143             :         /* avoid overflow */
     144           0 :         if (diff.sec > 0xffff)
     145           0 :                 return 0;
     146             : 
     147             :         /* LCI age is calculated in 10th of a second units. */
     148           0 :         diff_l = diff.sec * 10 + diff.usec / 100000;
     149             : 
     150           0 :         return max_age > diff_l;
     151             : }
     152             : 
     153             : 
     154          19 : static size_t hostapd_neighbor_report_len(struct wpabuf *buf,
     155             :                                           struct hostapd_neighbor_entry *nr,
     156             :                                           int send_lci, int send_civic)
     157             : {
     158          19 :         size_t len = 2 + wpabuf_len(nr->nr);
     159             : 
     160          19 :         if (send_lci && nr->lci)
     161           8 :                 len += 2 + wpabuf_len(nr->lci);
     162             : 
     163          19 :         if (send_civic && nr->civic)
     164           6 :                 len += 2 + wpabuf_len(nr->civic);
     165             : 
     166          19 :         return len;
     167             : }
     168             : 
     169             : 
     170          17 : static void hostapd_send_nei_report_resp(struct hostapd_data *hapd,
     171             :                                          const u8 *addr, u8 dialog_token,
     172             :                                          struct wpa_ssid_value *ssid, u8 lci,
     173             :                                          u8 civic, u16 lci_max_age)
     174             : {
     175             :         struct hostapd_neighbor_entry *nr;
     176             :         struct wpabuf *buf;
     177             :         u8 *msmt_token;
     178             : 
     179             :         /*
     180             :          * The number and length of the Neighbor Report elements in a Neighbor
     181             :          * Report frame is limited by the maximum allowed MMPDU size; + 3 bytes
     182             :          * of RRM header.
     183             :          */
     184          17 :         buf = wpabuf_alloc(3 + IEEE80211_MAX_MMPDU_SIZE);
     185          17 :         if (!buf)
     186          17 :                 return;
     187             : 
     188          17 :         wpabuf_put_u8(buf, WLAN_ACTION_RADIO_MEASUREMENT);
     189          17 :         wpabuf_put_u8(buf, WLAN_RRM_NEIGHBOR_REPORT_RESPONSE);
     190          17 :         wpabuf_put_u8(buf, dialog_token);
     191             : 
     192          82 :         dl_list_for_each(nr, &hapd->nr_db, struct hostapd_neighbor_entry,
     193             :                          list) {
     194             :                 int send_lci;
     195             :                 size_t len;
     196             : 
     197         130 :                 if (ssid->ssid_len != nr->ssid.ssid_len ||
     198          65 :                     os_memcmp(ssid->ssid, nr->ssid.ssid, ssid->ssid_len) != 0)
     199          46 :                         continue;
     200             : 
     201          19 :                 send_lci = (lci != 0) && hostapd_check_lci_age(nr, lci_max_age);
     202          19 :                 len = hostapd_neighbor_report_len(buf, nr, send_lci, civic);
     203             : 
     204          19 :                 if (len - 2 > 0xff) {
     205           0 :                         wpa_printf(MSG_DEBUG,
     206             :                                    "NR entry for " MACSTR " exceeds 0xFF bytes",
     207           0 :                                    MAC2STR(nr->bssid));
     208           0 :                         continue;
     209             :                 }
     210             : 
     211          19 :                 if (len > wpabuf_tailroom(buf))
     212           0 :                         break;
     213             : 
     214          19 :                 wpabuf_put_u8(buf, WLAN_EID_NEIGHBOR_REPORT);
     215          19 :                 wpabuf_put_u8(buf, len - 2);
     216          19 :                 wpabuf_put_buf(buf, nr->nr);
     217             : 
     218          19 :                 if (send_lci && nr->lci) {
     219           8 :                         wpabuf_put_u8(buf, WLAN_EID_MEASURE_REPORT);
     220           8 :                         wpabuf_put_u8(buf, wpabuf_len(nr->lci));
     221             :                         /*
     222             :                          * Override measurement token - the first byte of the
     223             :                          * Measurement Report element.
     224             :                          */
     225           8 :                         msmt_token = wpabuf_put(buf, 0);
     226           8 :                         wpabuf_put_buf(buf, nr->lci);
     227           8 :                         *msmt_token = lci;
     228             :                 }
     229             : 
     230          19 :                 if (civic && nr->civic) {
     231           6 :                         wpabuf_put_u8(buf, WLAN_EID_MEASURE_REPORT);
     232           6 :                         wpabuf_put_u8(buf, wpabuf_len(nr->civic));
     233             :                         /*
     234             :                          * Override measurement token - the first byte of the
     235             :                          * Measurement Report element.
     236             :                          */
     237           6 :                         msmt_token = wpabuf_put(buf, 0);
     238           6 :                         wpabuf_put_buf(buf, nr->civic);
     239           6 :                         *msmt_token = civic;
     240             :                 }
     241             :         }
     242             : 
     243          34 :         hostapd_drv_send_action(hapd, hapd->iface->freq, 0, addr,
     244          17 :                                 wpabuf_head(buf), wpabuf_len(buf));
     245          17 :         wpabuf_free(buf);
     246             : }
     247             : 
     248             : 
     249          17 : static void hostapd_handle_nei_report_req(struct hostapd_data *hapd,
     250             :                                           const u8 *buf, size_t len)
     251             : {
     252          17 :         const struct ieee80211_mgmt *mgmt = (const struct ieee80211_mgmt *) buf;
     253             :         const u8 *pos, *ie, *end;
     254          17 :         struct wpa_ssid_value ssid = {
     255             :                 .ssid_len = 0
     256             :         };
     257             :         u8 token;
     258          17 :         u8 lci = 0, civic = 0; /* Measurement tokens */
     259          17 :         u16 lci_max_age = 0;
     260             : 
     261          17 :         if (!(hapd->conf->radio_measurements[0] &
     262             :               WLAN_RRM_CAPS_NEIGHBOR_REPORT))
     263          17 :                 return;
     264             : 
     265          17 :         end = buf + len;
     266             : 
     267          17 :         token = mgmt->u.action.u.rrm.dialog_token;
     268          17 :         pos = mgmt->u.action.u.rrm.variable;
     269          17 :         len = end - pos;
     270             : 
     271          17 :         ie = get_ie(pos, len, WLAN_EID_SSID);
     272          17 :         if (ie && ie[1] && ie[1] <= SSID_MAX_LEN) {
     273          14 :                 ssid.ssid_len = ie[1];
     274          14 :                 os_memcpy(ssid.ssid, ie + 2, ssid.ssid_len);
     275             :         } else {
     276           3 :                 ssid.ssid_len = hapd->conf->ssid.ssid_len;
     277           3 :                 os_memcpy(ssid.ssid, hapd->conf->ssid.ssid, ssid.ssid_len);
     278             :         }
     279             : 
     280          51 :         while ((ie = get_ie(pos, len, WLAN_EID_MEASURE_REQUEST))) {
     281          17 :                 if (ie[1] < 3)
     282           0 :                         break;
     283             : 
     284          17 :                 wpa_printf(MSG_DEBUG,
     285             :                            "Neighbor report request, measure type %u",
     286          17 :                            ie[4]);
     287             : 
     288          17 :                 switch (ie[4]) { /* Measurement Type */
     289             :                 case MEASURE_TYPE_LCI:
     290           9 :                         lci = ie[2]; /* Measurement Token */
     291           9 :                         lci_max_age = hostapd_parse_location_lci_req_age(ie + 2,
     292           9 :                                                                          ie[1]);
     293           9 :                         break;
     294             :                 case MEASURE_TYPE_LOCATION_CIVIC:
     295           8 :                         civic = ie[2]; /* Measurement token */
     296           8 :                         break;
     297             :                 }
     298             : 
     299          17 :                 pos = ie + ie[1] + 2;
     300          17 :                 len = end - pos;
     301             :         }
     302             : 
     303          17 :         hostapd_send_nei_report_resp(hapd, mgmt->sa, token, &ssid, lci, civic,
     304             :                                      lci_max_age);
     305             : }
     306             : 
     307             : 
     308          18 : void hostapd_handle_radio_measurement(struct hostapd_data *hapd,
     309             :                                       const u8 *buf, size_t len)
     310             : {
     311          18 :         const struct ieee80211_mgmt *mgmt = (const struct ieee80211_mgmt *) buf;
     312             : 
     313             :         /*
     314             :          * Check for enough bytes: header + (1B)Category + (1B)Action +
     315             :          * (1B)Dialog Token.
     316             :          */
     317          18 :         if (len < IEEE80211_HDRLEN + 3)
     318          18 :                 return;
     319             : 
     320         126 :         wpa_printf(MSG_DEBUG, "Radio measurement frame, action %u from " MACSTR,
     321         126 :                    mgmt->u.action.u.rrm.action, MAC2STR(mgmt->sa));
     322             : 
     323          18 :         switch (mgmt->u.action.u.rrm.action) {
     324             :         case WLAN_RRM_RADIO_MEASUREMENT_REPORT:
     325           1 :                 hostapd_handle_radio_msmt_report(hapd, buf, len);
     326           1 :                 break;
     327             :         case WLAN_RRM_NEIGHBOR_REPORT_REQUEST:
     328          17 :                 hostapd_handle_nei_report_req(hapd, buf, len);
     329          17 :                 break;
     330             :         default:
     331           0 :                 wpa_printf(MSG_DEBUG, "RRM action %u is not supported",
     332           0 :                            mgmt->u.action.u.rrm.action);
     333           0 :                 break;
     334             :         }
     335             : }
     336             : 
     337             : 
     338           4 : int hostapd_send_lci_req(struct hostapd_data *hapd, const u8 *addr)
     339             : {
     340             :         struct wpabuf *buf;
     341           4 :         struct sta_info *sta = ap_get_sta(hapd, addr);
     342             :         int ret;
     343             : 
     344           4 :         if (!sta) {
     345           2 :                 wpa_printf(MSG_INFO,
     346             :                            "Request LCI: Destination address is not in station list");
     347           2 :                 return -1;
     348             :         }
     349             : 
     350           2 :         if (!(sta->flags & WLAN_STA_AUTHORIZED)) {
     351           0 :                 wpa_printf(MSG_INFO,
     352             :                            "Request LCI: Destination address is not connected");
     353           0 :                 return -1;
     354             :         }
     355             : 
     356           2 :         if (!(sta->rrm_enabled_capa[1] & WLAN_RRM_CAPS_LCI_MEASUREMENT)) {
     357           1 :                 wpa_printf(MSG_INFO,
     358             :                            "Request LCI: Station does not support LCI in RRM");
     359           1 :                 return -1;
     360             :         }
     361             : 
     362           1 :         if (hapd->lci_req_active) {
     363           0 :                 wpa_printf(MSG_DEBUG,
     364             :                            "Request LCI: LCI request is already in process, overriding");
     365           0 :                 hapd->lci_req_active = 0;
     366           0 :                 eloop_cancel_timeout(hostapd_lci_rep_timeout_handler, hapd,
     367             :                                      NULL);
     368             :         }
     369             : 
     370             :         /* Measurement request (5) + Measurement element with LCI (10) */
     371           1 :         buf = wpabuf_alloc(5 + 10);
     372           1 :         if (!buf)
     373           0 :                 return -1;
     374             : 
     375           1 :         hapd->lci_req_token++;
     376             :         /* For wraparounds - the token must be nonzero */
     377           1 :         if (!hapd->lci_req_token)
     378           0 :                 hapd->lci_req_token++;
     379             : 
     380           1 :         wpabuf_put_u8(buf, WLAN_ACTION_RADIO_MEASUREMENT);
     381           1 :         wpabuf_put_u8(buf, WLAN_RRM_RADIO_MEASUREMENT_REQUEST);
     382           1 :         wpabuf_put_u8(buf, hapd->lci_req_token);
     383           1 :         wpabuf_put_le16(buf, 0); /* Number of repetitions */
     384             : 
     385           1 :         wpabuf_put_u8(buf, WLAN_EID_MEASURE_REQUEST);
     386           1 :         wpabuf_put_u8(buf, 3 + 1 + 4);
     387             : 
     388           1 :         wpabuf_put_u8(buf, 1); /* Measurement Token */
     389             :         /*
     390             :          * Parallel and Enable bits are 0, Duration, Request, and Report are
     391             :          * reserved.
     392             :          */
     393           1 :         wpabuf_put_u8(buf, 0);
     394           1 :         wpabuf_put_u8(buf, MEASURE_TYPE_LCI);
     395             : 
     396           1 :         wpabuf_put_u8(buf, LOCATION_SUBJECT_REMOTE);
     397             : 
     398           1 :         wpabuf_put_u8(buf, LCI_REQ_SUBELEM_MAX_AGE);
     399           1 :         wpabuf_put_u8(buf, 2);
     400           1 :         wpabuf_put_le16(buf, 0xffff);
     401             : 
     402           2 :         ret = hostapd_drv_send_action(hapd, hapd->iface->freq, 0, addr,
     403           1 :                                       wpabuf_head(buf), wpabuf_len(buf));
     404           1 :         wpabuf_free(buf);
     405           1 :         if (ret)
     406           0 :                 return ret;
     407             : 
     408           1 :         hapd->lci_req_active = 1;
     409             : 
     410           1 :         eloop_register_timeout(HOSTAPD_RRM_REQUEST_TIMEOUT, 0,
     411             :                                hostapd_lci_rep_timeout_handler, hapd, NULL);
     412             : 
     413           1 :         return 0;
     414             : }
     415             : 
     416             : 
     417           2 : int hostapd_send_range_req(struct hostapd_data *hapd, const u8 *addr,
     418             :                            u16 random_interval, u8 min_ap,
     419             :                            const u8 *responders, unsigned int n_responders)
     420             : {
     421             :         struct wpabuf *buf;
     422             :         struct sta_info *sta;
     423             :         u8 *len;
     424             :         unsigned int i;
     425             :         int ret;
     426             : 
     427          14 :         wpa_printf(MSG_DEBUG, "Request range: dest addr " MACSTR
     428          12 :                    " rand interval %u min AP %u n_responders %u", MAC2STR(addr),
     429             :                    random_interval, min_ap, n_responders);
     430             : 
     431           2 :         if (min_ap == 0 || min_ap > n_responders) {
     432           2 :                 wpa_printf(MSG_INFO, "Request range: Wrong min AP count");
     433           2 :                 return -1;
     434             :         }
     435             : 
     436           0 :         sta = ap_get_sta(hapd, addr);
     437           0 :         if (!sta || !(sta->flags & WLAN_STA_AUTHORIZED)) {
     438           0 :                 wpa_printf(MSG_INFO,
     439             :                            "Request range: Destination address is not connected");
     440           0 :                 return -1;
     441             :         }
     442             : 
     443           0 :         if (!(sta->rrm_enabled_capa[4] & WLAN_RRM_CAPS_FTM_RANGE_REPORT)) {
     444           0 :                 wpa_printf(MSG_ERROR,
     445             :                            "Request range: Destination station does not support FTM range report in RRM");
     446           0 :                 return -1;
     447             :         }
     448             : 
     449           0 :         if (hapd->range_req_active) {
     450           0 :                 wpa_printf(MSG_DEBUG,
     451             :                            "Request range: Range request is already in process; overriding");
     452           0 :                 hapd->range_req_active = 0;
     453           0 :                 eloop_register_timeout(HOSTAPD_RRM_REQUEST_TIMEOUT, 0,
     454             :                                        hostapd_range_rep_timeout_handler, hapd,
     455             :                                        NULL);
     456             :         }
     457             : 
     458             :         /* Action + measurement type + token + reps + EID + len = 7 */
     459           0 :         buf = wpabuf_alloc(7 + 255);
     460           0 :         if (!buf)
     461           0 :                 return -1;
     462             : 
     463           0 :         hapd->range_req_token++;
     464           0 :         if (!hapd->range_req_token) /* For wraparounds */
     465           0 :                 hapd->range_req_token++;
     466             : 
     467             :         /* IEEE P802.11-REVmc/D5.0, 9.6.7.2 */
     468           0 :         wpabuf_put_u8(buf, WLAN_ACTION_RADIO_MEASUREMENT);
     469           0 :         wpabuf_put_u8(buf, WLAN_RRM_RADIO_MEASUREMENT_REQUEST);
     470           0 :         wpabuf_put_u8(buf, hapd->range_req_token); /* Dialog Token */
     471           0 :         wpabuf_put_le16(buf, 0); /* Number of Repetitions */
     472             : 
     473             :         /* IEEE P802.11-REVmc/D5.0, 9.4.2.21 */
     474           0 :         wpabuf_put_u8(buf, WLAN_EID_MEASURE_REQUEST);
     475           0 :         len = wpabuf_put(buf, 1); /* Length will be set later */
     476             : 
     477           0 :         wpabuf_put_u8(buf, 1); /* Measurement Token */
     478             :         /*
     479             :          * Parallel and Enable bits are 0; Duration, Request, and Report are
     480             :          * reserved.
     481             :          */
     482           0 :         wpabuf_put_u8(buf, 0); /* Measurement Request Mode */
     483           0 :         wpabuf_put_u8(buf, MEASURE_TYPE_FTM_RANGE); /* Measurement Type */
     484             : 
     485             :         /* IEEE P802.11-REVmc/D5.0, 9.4.2.21.19 */
     486           0 :         wpabuf_put_le16(buf, random_interval); /* Randomization Interval */
     487           0 :         wpabuf_put_u8(buf, min_ap); /* Minimum AP Count */
     488             : 
     489             :         /* FTM Range Subelements */
     490             : 
     491             :         /*
     492             :          * Taking the neighbor report part of the range request from neighbor
     493             :          * database instead of requesting the separate bits of data from the
     494             :          * user.
     495             :          */
     496           0 :         for (i = 0; i < n_responders; i++) {
     497             :                 struct hostapd_neighbor_entry *nr;
     498             : 
     499           0 :                 nr = hostapd_neighbor_get(hapd, responders + ETH_ALEN * i,
     500             :                                           NULL);
     501           0 :                 if (!nr) {
     502           0 :                         wpa_printf(MSG_INFO, "Missing neighbor report for "
     503           0 :                                    MACSTR, MAC2STR(responders + ETH_ALEN * i));
     504           0 :                         wpabuf_free(buf);
     505           0 :                         return -1;
     506             :                 }
     507             : 
     508           0 :                 if (wpabuf_tailroom(buf) < 2 + wpabuf_len(nr->nr)) {
     509           0 :                         wpa_printf(MSG_ERROR, "Too long range request");
     510           0 :                         wpabuf_free(buf);
     511           0 :                         return -1;
     512             :                 }
     513             : 
     514           0 :                 wpabuf_put_u8(buf, WLAN_EID_NEIGHBOR_REPORT);
     515           0 :                 wpabuf_put_u8(buf, wpabuf_len(nr->nr));
     516           0 :                 wpabuf_put_buf(buf, nr->nr);
     517             :         }
     518             : 
     519             :         /* Action + measurement type + token + reps + EID + len = 7 */
     520           0 :         *len = wpabuf_len(buf) - 7;
     521             : 
     522           0 :         ret = hostapd_drv_send_action(hapd, hapd->iface->freq, 0, addr,
     523           0 :                                       wpabuf_head(buf), wpabuf_len(buf));
     524           0 :         wpabuf_free(buf);
     525           0 :         if (ret)
     526           0 :                 return ret;
     527             : 
     528           0 :         hapd->range_req_active = 1;
     529             : 
     530           0 :         eloop_register_timeout(HOSTAPD_RRM_REQUEST_TIMEOUT, 0,
     531             :                                hostapd_range_rep_timeout_handler, hapd, NULL);
     532             : 
     533           0 :         return 0;
     534             : }
     535             : 
     536             : 
     537        2659 : void hostapd_clean_rrm(struct hostapd_data *hapd)
     538             : {
     539        2659 :         hostpad_free_neighbor_db(hapd);
     540        2659 :         eloop_cancel_timeout(hostapd_lci_rep_timeout_handler, hapd, NULL);
     541        2659 :         hapd->lci_req_active = 0;
     542        2659 :         eloop_cancel_timeout(hostapd_range_rep_timeout_handler, hapd, NULL);
     543        2659 :         hapd->range_req_active = 0;
     544        2659 : }

Generated by: LCOV version 1.10