P2P: Filter Probe Request frames based on DA and BSSID in Listen state
authorJouni Malinen <j@w1.fi>
Fri, 15 Jul 2011 17:25:53 +0000 (20:25 +0300)
committerJouni Malinen <j@w1.fi>
Fri, 15 Jul 2011 17:28:46 +0000 (20:28 +0300)
Only accept Probe Request frames that have a Wildcard BSSID and a
destination address that matches with our P2P Device Address or is the
broadcast address per P2P specification 3.1.2.1.1.

15 files changed:
src/ap/beacon.c
src/ap/drv_callbacks.c
src/ap/hostapd.h
src/ap/utils.c
src/ap/wps_hostapd.c
src/drivers/driver.h
src/drivers/driver_atheros.c
src/drivers/driver_madwifi.c
src/drivers/driver_test.c
src/p2p/p2p.c
src/p2p/p2p.h
wpa_supplicant/ap.c
wpa_supplicant/events.c
wpa_supplicant/p2p_supplicant.c
wpa_supplicant/p2p_supplicant.h

index 5544925..49dd034 100644 (file)
@@ -217,7 +217,8 @@ void handle_probe_req(struct hostapd_data *hapd,
 
        for (i = 0; hapd->probereq_cb && i < hapd->num_probereq_cb; i++)
                if (hapd->probereq_cb[i].cb(hapd->probereq_cb[i].ctx,
-                                           mgmt->sa, ie, ie_len) > 0)
+                                           mgmt->sa, mgmt->da, mgmt->bssid,
+                                           ie, ie_len) > 0)
                        return;
 
        if (!hapd->iconf->send_probe_response)
index fc4bc31..db2d5f2 100644 (file)
@@ -250,8 +250,8 @@ void hostapd_event_sta_low_ack(struct hostapd_data *hapd, const u8 *addr)
 }
 
 
-int hostapd_probe_req_rx(struct hostapd_data *hapd, const u8 *sa,
-                        const u8 *ie, size_t ie_len)
+int hostapd_probe_req_rx(struct hostapd_data *hapd, const u8 *sa, const u8 *da,
+                        const u8 *bssid, const u8 *ie, size_t ie_len)
 {
        size_t i;
        int ret = 0;
@@ -262,7 +262,7 @@ int hostapd_probe_req_rx(struct hostapd_data *hapd, const u8 *sa,
        random_add_randomness(sa, ETH_ALEN);
        for (i = 0; hapd->probereq_cb && i < hapd->num_probereq_cb; i++) {
                if (hapd->probereq_cb[i].cb(hapd->probereq_cb[i].ctx,
-                                           sa, ie, ie_len) > 0) {
+                                           sa, da, bssid, ie, ie_len) > 0) {
                        ret = 1;
                        break;
                }
@@ -540,6 +540,8 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
                    data->rx_probe_req.ie == NULL)
                        break;
                hostapd_probe_req_rx(hapd, data->rx_probe_req.sa,
+                                    data->rx_probe_req.da,
+                                    data->rx_probe_req.bssid,
                                     data->rx_probe_req.ie,
                                     data->rx_probe_req.ie_len);
                break;
index d4501a1..8d12d8b 100644 (file)
@@ -31,7 +31,8 @@ enum wps_event;
 union wps_event_data;
 
 struct hostapd_probereq_cb {
-       int (*cb)(void *ctx, const u8 *sa, const u8 *ie, size_t ie_len);
+       int (*cb)(void *ctx, const u8 *sa, const u8 *da, const u8 *bssid,
+                 const u8 *ie, size_t ie_len);
        void *ctx;
 };
 
@@ -247,6 +248,7 @@ void hostapd_new_assoc_sta(struct hostapd_data *hapd, struct sta_info *sta,
 /* utils.c */
 int hostapd_register_probereq_cb(struct hostapd_data *hapd,
                                 int (*cb)(void *ctx, const u8 *sa,
+                                          const u8 *da, const u8 *bssid,
                                           const u8 *ie, size_t ie_len),
                                 void *ctx);
 void hostapd_prune_associations(struct hostapd_data *hapd, const u8 *addr);
@@ -256,7 +258,7 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
                        const u8 *ie, size_t ielen, int reassoc);
 void hostapd_notif_disassoc(struct hostapd_data *hapd, const u8 *addr);
 void hostapd_event_sta_low_ack(struct hostapd_data *hapd, const u8 *addr);
-int hostapd_probe_req_rx(struct hostapd_data *hapd, const u8 *sa,
-                        const u8 *ie, size_t ie_len);
+int hostapd_probe_req_rx(struct hostapd_data *hapd, const u8 *sa, const u8 *da,
+                        const u8 *bssid, const u8 *ie, size_t ie_len);
 
 #endif /* HOSTAPD_H */
index 0ff48ae..09bc32f 100644 (file)
@@ -22,6 +22,7 @@
 
 int hostapd_register_probereq_cb(struct hostapd_data *hapd,
                                 int (*cb)(void *ctx, const u8 *sa,
+                                          const u8 *da, const u8 *bssid,
                                           const u8 *ie, size_t ie_len),
                                 void *ctx)
 {
index 640e8cd..5d910b1 100644 (file)
@@ -41,7 +41,8 @@ static int hostapd_wps_upnp_init(struct hostapd_data *hapd,
 static void hostapd_wps_upnp_deinit(struct hostapd_data *hapd);
 #endif /* CONFIG_WPS_UPNP */
 
-static int hostapd_wps_probe_req_rx(void *ctx, const u8 *addr,
+static int hostapd_wps_probe_req_rx(void *ctx, const u8 *addr, const u8 *da,
+                                   const u8 *bssid,
                                    const u8 *ie, size_t ie_len);
 static void hostapd_wps_ap_pin_timeout(void *eloop_data, void *user_ctx);
 
@@ -1076,7 +1077,8 @@ error:
 #endif /* CONFIG_WPS_OOB */
 
 
-static int hostapd_wps_probe_req_rx(void *ctx, const u8 *addr,
+static int hostapd_wps_probe_req_rx(void *ctx, const u8 *addr, const u8 *da,
+                                   const u8 *bssid,
                                    const u8 *ie, size_t ie_len)
 {
        struct hostapd_data *hapd = ctx;
index 828948d..0d8a6a3 100644 (file)
@@ -3081,6 +3081,18 @@ union wpa_event_data {
                const u8 *sa;
 
                /**
+                * da - Destination address of the received Probe Request frame
+                *      or %NULL if not available
+                */
+               const u8 *da;
+
+               /**
+                * bssid - BSSID of the received Probe Request frame or %NULL
+                *      if not available
+                */
+               const u8 *bssid;
+
+               /**
                 * ie - IEs from the Probe Request body
                 */
                const u8 *ie;
index 1e78f6e..0587050 100644 (file)
@@ -748,6 +748,8 @@ static void atheros_raw_receive(void *ctx, const u8 *src_addr, const u8 *buf,
 
        os_memset(&event, 0, sizeof(event));
        event.rx_probe_req.sa = mgmt->sa;
+       event.rx_probe_req.da = mgmt->da;
+       event.rx_probe_req.bssid = mgmt->bssid;
        event.rx_probe_req.ie = mgmt->u.probe_req.variable;
        event.rx_probe_req.ie_len =
                len - (IEEE80211_HDRLEN + sizeof(mgmt->u.probe_req));
index 630fbf4..b4abe9c 100644 (file)
@@ -734,6 +734,8 @@ static void madwifi_raw_receive(void *ctx, const u8 *src_addr, const u8 *buf,
 
        os_memset(&event, 0, sizeof(event));
        event.rx_probe_req.sa = mgmt->sa;
+       event.rx_probe_req.da = mgmt->da;
+       event.rx_probe_req.bssid = mgmt->bssid;
        event.rx_probe_req.ie = mgmt->u.probe_req.variable;
        event.rx_probe_req.ie_len =
                len - (IEEE80211_HDRLEN + sizeof(mgmt->u.probe_req));
index 6bfa46d..cdae739 100644 (file)
@@ -561,7 +561,7 @@ static void test_driver_scan(struct wpa_driver_test_data *drv,
                wpa_supplicant_event(drv->ctx, EVENT_RX_PROBE_REQ, &event);
 #ifdef CONFIG_P2P
                if (drv->p2p)
-                       p2p_probe_req_rx(drv->p2p, sa, ie, ielen);
+                       p2p_probe_req_rx(drv->p2p, sa, NULL, NULL, ie, ielen);
 #endif /* CONFIG_P2P */
        }
 
@@ -1966,6 +1966,8 @@ static void wpa_driver_test_mlme(struct wpa_driver_test_data *drv,
                    WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_PROBE_REQ) {
                        os_memset(&event, 0, sizeof(event));
                        event.rx_probe_req.sa = mgmt->sa;
+                       event.rx_probe_req.da = mgmt->da;
+                       event.rx_probe_req.bssid = mgmt->bssid;
                        event.rx_probe_req.ie = mgmt->u.probe_req.variable;
                        event.rx_probe_req.ie_len =
                                data_len - (mgmt->u.probe_req.variable - data);
@@ -1974,6 +1976,7 @@ static void wpa_driver_test_mlme(struct wpa_driver_test_data *drv,
 #ifdef CONFIG_P2P
                        if (drv->p2p)
                                p2p_probe_req_rx(drv->p2p, mgmt->sa,
+                                                mgmt->da, mgmt->bssid,
                                                 event.rx_probe_req.ie,
                                                 event.rx_probe_req.ie_len);
 #endif /* CONFIG_P2P */
@@ -2028,7 +2031,7 @@ static void wpa_driver_test_scan_cmd(struct wpa_driver_test_data *drv,
                        ielen = 0;
                drv->probe_from = from;
                drv->probe_from_len = fromlen;
-               p2p_probe_req_rx(drv->p2p, sa, ie, ielen);
+               p2p_probe_req_rx(drv->p2p, sa, NULL, NULL, ie, ielen);
                drv->probe_from = NULL;
        }
 #endif /* CONFIG_P2P */
index d4fac56..2eb91ce 100644 (file)
@@ -1644,7 +1644,8 @@ struct wpabuf * p2p_build_probe_resp_ies(struct p2p_data *p2p)
 }
 
 
-static void p2p_reply_probe(struct p2p_data *p2p, const u8 *addr, const u8 *ie,
+static void p2p_reply_probe(struct p2p_data *p2p, const u8 *addr,
+                           const u8 *dst, const u8 *bssid, const u8 *ie,
                            size_t ie_len)
 {
        struct ieee802_11_elems elems;
@@ -1669,6 +1670,18 @@ static void p2p_reply_probe(struct p2p_data *p2p, const u8 *addr, const u8 *ie,
                return;
        }
 
+       if (dst && !is_broadcast_ether_addr(dst) &&
+           os_memcmp(dst, p2p->cfg->dev_addr, ETH_ALEN) != 0) {
+               /* Not sent to the broadcast address or our P2P Device Address
+                */
+               return;
+       }
+
+       if (bssid && !is_broadcast_ether_addr(bssid)) {
+               /* Not sent to the Wildcard BSSID */
+               return;
+       }
+
        if (elems.ssid == NULL || elems.ssid_len != P2P_WILDCARD_SSID_LEN ||
            os_memcmp(elems.ssid, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN) !=
            0) {
@@ -1750,12 +1763,12 @@ static void p2p_reply_probe(struct p2p_data *p2p, const u8 *addr, const u8 *ie,
 }
 
 
-int p2p_probe_req_rx(struct p2p_data *p2p, const u8 *addr, const u8 *ie,
-                    size_t ie_len)
+int p2p_probe_req_rx(struct p2p_data *p2p, const u8 *addr, const u8 *dst,
+                    const u8 *bssid, const u8 *ie, size_t ie_len)
 {
        p2p_add_dev_from_probe_req(p2p, addr, ie, ie_len);
 
-       p2p_reply_probe(p2p, addr, ie, ie_len);
+       p2p_reply_probe(p2p, addr, dst, bssid, ie, ie_len);
 
        if ((p2p->state == P2P_CONNECT || p2p->state == P2P_CONNECT_LISTEN) &&
            p2p->go_neg_peer &&
index db816a6..f56cc97 100644 (file)
@@ -1035,12 +1035,14 @@ void p2p_group_formation_failed(struct p2p_data *p2p);
  * p2p_probe_req_rx - Report reception of a Probe Request frame
  * @p2p: P2P module context from p2p_init()
  * @addr: Source MAC address
+ * @dst: Destination MAC address if available or %NULL
+ * @bssid: BSSID if available or %NULL
  * @ie: Information elements from the Probe Request frame body
  * @ie_len: Length of ie buffer in octets
  * Returns: 0 to indicate the frame was not processed or 1 if it was
  */
-int p2p_probe_req_rx(struct p2p_data *p2p, const u8 *addr, const u8 *ie,
-                    size_t ie_len);
+int p2p_probe_req_rx(struct p2p_data *p2p, const u8 *addr, const u8 *dst,
+                    const u8 *bssid, const u8 *ie, size_t ie_len);
 
 /**
  * p2p_rx_action - Report received Action frame
index b7e1175..f6a03ba 100644 (file)
@@ -303,12 +303,12 @@ static int ap_vendor_action_rx(void *ctx, const u8 *buf, size_t len, int freq)
 }
 
 
-static int ap_probe_req_rx(void *ctx, const u8 *addr, const u8 *ie,
-                          size_t ie_len)
+static int ap_probe_req_rx(void *ctx, const u8 *sa, const u8 *da,
+                          const u8 *bssid, const u8 *ie, size_t ie_len)
 {
 #ifdef CONFIG_P2P
        struct wpa_supplicant *wpa_s = ctx;
-       return wpas_p2p_probe_req_rx(wpa_s, addr, ie, ie_len);
+       return wpas_p2p_probe_req_rx(wpa_s, sa, da, bssid, ie, ie_len);
 #else /* CONFIG_P2P */
        return 0;
 #endif /* CONFIG_P2P */
index b398792..a307eda 100644 (file)
@@ -1987,7 +1987,8 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
                                size_t ie_len = data->rx_mgmt.frame_len -
                                        (mgmt->u.probe_req.variable -
                                         data->rx_mgmt.frame);
-                               wpas_p2p_probe_req_rx(wpa_s, src, ie, ie_len);
+                               wpas_p2p_probe_req_rx(wpa_s, src, mgmt->da,
+                                                     mgmt->bssid, ie, ie_len);
                                break;
                        }
 #endif /* CONFIG_P2P */
@@ -2038,6 +2039,8 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
                if (wpa_s->ap_iface) {
                        hostapd_probe_req_rx(wpa_s->ap_iface->bss[0],
                                             data->rx_probe_req.sa,
+                                            data->rx_probe_req.da,
+                                            data->rx_probe_req.bssid,
                                             data->rx_probe_req.ie,
                                             data->rx_probe_req.ie_len);
                        break;
@@ -2045,6 +2048,8 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
 #endif /* CONFIG_AP */
 #ifdef CONFIG_P2P
                wpas_p2p_probe_req_rx(wpa_s, data->rx_probe_req.sa,
+                                     data->rx_probe_req.da,
+                                     data->rx_probe_req.bssid,
                                      data->rx_probe_req.ie,
                                      data->rx_probe_req.ie_len);
 #endif /* CONFIG_P2P */
index f1b90cf..400b6cc 100644 (file)
@@ -3650,6 +3650,7 @@ int wpas_p2p_assoc_req_ie(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
 
 
 int wpas_p2p_probe_req_rx(struct wpa_supplicant *wpa_s, const u8 *addr,
+                         const u8 *dst, const u8 *bssid,
                          const u8 *ie, size_t ie_len)
 {
        if (wpa_s->global->p2p_disabled)
@@ -3657,7 +3658,8 @@ int wpas_p2p_probe_req_rx(struct wpa_supplicant *wpa_s, const u8 *addr,
        if (wpa_s->global->p2p == NULL)
                return 0;
 
-       return p2p_probe_req_rx(wpa_s->global->p2p, addr, ie, ie_len);
+       return p2p_probe_req_rx(wpa_s->global->p2p, addr, dst, bssid,
+                               ie, ie_len);
 }
 
 
index b1080a5..ad74217 100644 (file)
@@ -58,6 +58,7 @@ int wpas_p2p_listen(struct wpa_supplicant *wpa_s, unsigned int timeout);
 int wpas_p2p_assoc_req_ie(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
                          u8 *buf, size_t len, int p2p_group);
 int wpas_p2p_probe_req_rx(struct wpa_supplicant *wpa_s, const u8 *addr,
+                         const u8 *dst, const u8 *bssid,
                          const u8 *ie, size_t ie_len);
 void wpas_p2p_rx_action(struct wpa_supplicant *wpa_s, const u8 *da,
                        const u8 *sa, const u8 *bssid,