RRM: Modify the processing of a received neighbor report
authorIlan Peer <ilan.peer@intel.com>
Wed, 6 Apr 2016 16:42:18 +0000 (19:42 +0300)
committerJouni Malinen <j@w1.fi>
Sun, 17 Apr 2016 14:45:14 +0000 (17:45 +0300)
Parse a received neighbor report and report for each neighbor report the
data received for it:

RRM-NEIGHBOR-REP-RECEIVED bssid=<BSSID> info=0x<hex> op_class=<class> chan=<chan> [lci=hex] [civic=hex]

Note that this modifies the previous format that originally reported
only the length of the received frame.

Signed-off-by: Ilan Peer <ilan.peer@intel.com>
wpa_supplicant/ctrl_iface.c

index e450e3b..3c97819 100644 (file)
@@ -8236,15 +8236,103 @@ static int wpas_ctrl_vendor_elem_remove(struct wpa_supplicant *wpa_s, char *cmd)
 static void wpas_ctrl_neighbor_rep_cb(void *ctx, struct wpabuf *neighbor_rep)
 {
        struct wpa_supplicant *wpa_s = ctx;
+       size_t len;
+       const u8 *data;
 
-       if (neighbor_rep) {
-               wpa_msg_ctrl(wpa_s, MSG_INFO, RRM_EVENT_NEIGHBOR_REP_RXED
-                            "length=%u",
-                            (unsigned int) wpabuf_len(neighbor_rep));
-               wpabuf_free(neighbor_rep);
-       } else {
+       /*
+        * Neighbor Report element (IEEE P802.11-REVmc/D5.0)
+        * BSSID[6]
+        * BSSID Information[4]
+        * Operating Class[1]
+        * Channel Number[1]
+        * PHY Type[1]
+        * Optional Subelements[variable]
+        */
+#define NR_IE_MIN_LEN (ETH_ALEN + 4 + 1 + 1 + 1)
+
+       if (!neighbor_rep || wpabuf_len(neighbor_rep) == 0) {
                wpa_msg_ctrl(wpa_s, MSG_INFO, RRM_EVENT_NEIGHBOR_REP_FAILED);
+               goto out;
+       }
+
+       data = wpabuf_head_u8(neighbor_rep);
+       len = wpabuf_len(neighbor_rep);
+
+       while (len >= 2 + NR_IE_MIN_LEN) {
+               const u8 *nr;
+               char lci[256 * 2 + 1];
+               char civic[256 * 2 + 1];
+               u8 nr_len = data[1];
+               const u8 *pos = data, *end;
+
+               if (pos[0] != WLAN_EID_NEIGHBOR_REPORT ||
+                   nr_len < NR_IE_MIN_LEN) {
+                       wpa_printf(MSG_DEBUG,
+                                  "CTRL: Invalid Neighbor Report element: id=%u len=%u",
+                                  data[0], nr_len);
+                       goto out;
+               }
+
+               if (2U + nr_len > len) {
+                       wpa_printf(MSG_DEBUG,
+                                  "CTRL: Invalid Neighbor Report element: id=%u len=%zu nr_len=%u",
+                                  data[0], len, nr_len);
+                       goto out;
+               }
+               pos += 2;
+               end = pos + nr_len;
+
+               nr = pos;
+               pos += NR_IE_MIN_LEN;
+
+               lci[0] = '\0';
+               civic[0] = '\0';
+               while (end - pos > 2) {
+                       u8 s_id, s_len;
+
+                       s_id = *pos++;
+                       s_len = *pos++;
+                       if (s_len > end - pos)
+                               goto out;
+                       if (s_id == WLAN_EID_MEASURE_REPORT && s_len > 3) {
+                               /* Measurement Token[1] */
+                               /* Measurement Report Mode[1] */
+                               /* Measurement Type[1] */
+                               /* Measurement Report[variable] */
+                               switch (pos[2]) {
+                               case MEASURE_TYPE_LCI:
+                                       if (lci[0])
+                                               break;
+                                       wpa_snprintf_hex(lci, sizeof(lci),
+                                                        pos, s_len);
+                                       break;
+                               case MEASURE_TYPE_LOCATION_CIVIC:
+                                       if (civic[0])
+                                               break;
+                                       wpa_snprintf_hex(civic, sizeof(civic),
+                                                        pos, s_len);
+                                       break;
+                               }
+                       }
+
+                       pos += s_len;
+               }
+
+               wpa_msg(wpa_s, MSG_INFO, RRM_EVENT_NEIGHBOR_REP_RXED
+                       "bssid=" MACSTR
+                       " info=0x%x op_class=%u chan=%u phy_type=%u%s%s%s%s",
+                       MAC2STR(nr), WPA_GET_LE32(nr + ETH_ALEN),
+                       nr[ETH_ALEN + 4], nr[ETH_ALEN + 5],
+                       nr[ETH_ALEN + 6],
+                       lci[0] ? " lci=" : "", lci,
+                       civic[0] ? " civic=" : "", civic);
+
+               data = end;
+               len -= 2 + nr_len;
        }
+
+out:
+       wpabuf_free(neighbor_rep);
 }