]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
P2P: Allow WPS_PBC command on GO to select on P2P Device Address
authorJouni Malinen <jouni.malinen@atheros.com>
Mon, 7 Feb 2011 16:28:36 +0000 (18:28 +0200)
committerJouni Malinen <j@w1.fi>
Mon, 7 Feb 2011 16:28:36 +0000 (18:28 +0200)
An optional parameter, p2p_dev_addr, can now be given to WPS_PBC
command on P2P GO to indicate that only the P2P device with the
specified P2P Device Address is allowed to connect using PBC. If
any other device tries to use PBC, a session overlap is indicated
and the negotiation is rejected with M2D. The command format for
specifying the address is "WPS_PBC p2p_dev_addr=<address>", e.g.,
WPS_PBC p2p_dev_addr=02:03:04:05:06:07

In addition, show the PBC session overlap indication as a WPS failure
event on an AP/GO interface. This particular new case shows up as
"WPS-FAIL msg=4 config_error=12".

14 files changed:
hostapd/ctrl_iface.c
src/ap/drv_callbacks.c
src/ap/wps_hostapd.c
src/ap/wps_hostapd.h
src/eap_server/eap_server_wsc.c
src/wps/wps.c
src/wps/wps.h
src/wps/wps_er.c
src/wps/wps_i.h
src/wps/wps_registrar.c
wpa_supplicant/ap.c
wpa_supplicant/ap.h
wpa_supplicant/ctrl_iface.c
wpa_supplicant/p2p_supplicant.c

index d3ab6242af6555ff0c67193dd67367dafff84bdd..195b8a73c737ae7a1acf2f345fc302965de52c19 100644 (file)
@@ -865,7 +865,7 @@ static void hostapd_ctrl_iface_receive(int sock, void *eloop_ctx,
                reply_len = hostapd_ctrl_iface_wps_check_pin(
                        hapd, buf + 14, reply, reply_size);
        } else if (os_strcmp(buf, "WPS_PBC") == 0) {
-               if (hostapd_wps_button_pushed(hapd))
+               if (hostapd_wps_button_pushed(hapd, NULL))
                        reply_len = -1;
 #ifdef CONFIG_WPS_OOB
        } else if (os_strncmp(buf, "WPS_OOB ", 8) == 0) {
index a49248fde3dca63d0fdaf1028614ad00a12107f4..c1fdba6b987dfb70bf46d36ec47bf37d1585970c 100644 (file)
@@ -463,7 +463,7 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
                break;
 #endif /* CONFIG_IEEE80211R */
        case EVENT_WPS_BUTTON_PUSHED:
-               hostapd_wps_button_pushed(hapd);
+               hostapd_wps_button_pushed(hapd, NULL);
                break;
 #ifdef NEED_AP_MLME
        case EVENT_TX_STATUS:
index cfff55cdf142bb6bceabf656a9b7a86577ffde38..d5042c04666f136c17e3610b099e0f8e0d484b5c 100644 (file)
@@ -965,15 +965,18 @@ int hostapd_wps_add_pin(struct hostapd_data *hapd, const u8 *addr,
 
 static int wps_button_pushed(struct hostapd_data *hapd, void *ctx)
 {
+       const u8 *p2p_dev_addr = ctx;
        if (hapd->wps == NULL)
                return 0;
-       return wps_registrar_button_pushed(hapd->wps->registrar);
+       return wps_registrar_button_pushed(hapd->wps->registrar, p2p_dev_addr);
 }
 
 
-int hostapd_wps_button_pushed(struct hostapd_data *hapd)
+int hostapd_wps_button_pushed(struct hostapd_data *hapd,
+                             const u8 *p2p_dev_addr)
 {
-       return hostapd_wps_for_each(hapd, wps_button_pushed, NULL);
+       return hostapd_wps_for_each(hapd, wps_button_pushed,
+                                   (void *) p2p_dev_addr);
 }
 
 
index 36401be3863e7c8ba8506ab1bcffd42351c263d6..338a2208850078a1a9be37bd05e27915a833bbad 100644 (file)
@@ -23,7 +23,8 @@ void hostapd_deinit_wps(struct hostapd_data *hapd);
 void hostapd_update_wps(struct hostapd_data *hapd);
 int hostapd_wps_add_pin(struct hostapd_data *hapd, const u8 *addr,
                        const char *uuid, const char *pin, int timeout);
-int hostapd_wps_button_pushed(struct hostapd_data *hapd);
+int hostapd_wps_button_pushed(struct hostapd_data *hapd,
+                             const u8 *p2p_dev_addr);
 int hostapd_wps_start_oob(struct hostapd_data *hapd, char *device_type,
                          char *path, char *method, char *name);
 int hostapd_wps_get_mib_sta(struct hostapd_data *hapd, const u8 *addr,
@@ -60,7 +61,8 @@ static inline int hostapd_wps_get_mib_sta(struct hostapd_data *hapd,
        return 0;
 }
 
-static inline int hostapd_wps_button_pushed(struct hostapd_data *hapd)
+static inline int hostapd_wps_button_pushed(struct hostapd_data *hapd,
+                                           const u8 *p2p_dev_addr)
 {
        return 0;
 }
index 83e55d9f191e71c52aa8e7df5b98ab705f8975a2..e944a4d437273ac2232aae1ebc14278edfb24f4e 100644 (file)
@@ -18,6 +18,7 @@
 #include "eloop.h"
 #include "eap_i.h"
 #include "eap_common/eap_wsc_common.h"
+#include "p2p/p2p.h"
 #include "wps/wps.h"
 
 
@@ -135,11 +136,14 @@ static void * eap_wsc_init(struct eap_sm *sm)
        }
        cfg.assoc_wps_ie = sm->assoc_wps_ie;
        cfg.peer_addr = sm->peer_addr;
+#ifdef CONFIG_P2P
        if (sm->assoc_p2p_ie) {
                wpa_printf(MSG_DEBUG, "EAP-WSC: Prefer PSK format for P2P "
                           "client");
                cfg.use_psk_key = 1;
+               cfg.p2p_dev_addr = p2p_get_go_dev_addr(sm->assoc_p2p_ie);
        }
+#endif /* CONFIG_P2P */
        data->wps = wps_init(&cfg);
        if (data->wps == NULL) {
                os_free(data);
index 73dd58cbabb065b6bf07211c5e54c191ce538786..a9d41d039e8336a352b174e1a4d9f70f0da61ea5 100644 (file)
@@ -109,6 +109,8 @@ struct wps_data * wps_init(const struct wps_config *cfg)
 
        if (cfg->peer_addr)
                os_memcpy(data->peer_dev.mac_addr, cfg->peer_addr, ETH_ALEN);
+       if (cfg->p2p_dev_addr)
+               os_memcpy(data->p2p_dev_addr, cfg->p2p_dev_addr, ETH_ALEN);
 
        data->use_psk_key = cfg->use_psk_key;
 
index 771551a85ad64868f85ae59ad231ea1698c38a57..47b3e760e94ead43976dd3033f1ae760f07ef125 100644 (file)
@@ -164,6 +164,16 @@ struct wps_config {
         * dev_pw_id - Device Password ID for Enrollee when PIN is used
         */
        u16 dev_pw_id;
+
+       /**
+        * p2p_dev_addr - P2P Device Address from (Re)Association Request
+        *
+        * On AP/GO, this is set to the P2P Device Address of the associating
+        * P2P client if a P2P IE is included in the (Re)Association Request
+        * frame and the P2P Device Address is included. Otherwise, this is set
+        * to %NULL to indicate the station does not have a P2P Device Address.
+        */
+       const u8 *p2p_dev_addr;
 };
 
 struct wps_data * wps_init(const struct wps_config *cfg);
@@ -747,7 +757,8 @@ int wps_registrar_add_pin(struct wps_registrar *reg, const u8 *addr,
 int wps_registrar_invalidate_pin(struct wps_registrar *reg, const u8 *uuid);
 int wps_registrar_wps_cancel(struct wps_registrar *reg);
 int wps_registrar_unlock_pin(struct wps_registrar *reg, const u8 *uuid);
-int wps_registrar_button_pushed(struct wps_registrar *reg);
+int wps_registrar_button_pushed(struct wps_registrar *reg,
+                               const u8 *p2p_dev_addr);
 void wps_registrar_probe_req_rx(struct wps_registrar *reg, const u8 *addr,
                                const struct wpabuf *wps_data,
                                int p2p_wildcard);
index d3aee2d953326faf8a424838e06320a138f25b60..a4618369516c7c5f04355bfb24154951680e3366 100644 (file)
@@ -1550,7 +1550,7 @@ int wps_er_pbc(struct wps_er *er, const u8 *uuid)
        }
 
        er->set_sel_reg_uuid_filter = uuid;
-       res = wps_registrar_button_pushed(er->wps->registrar);
+       res = wps_registrar_button_pushed(er->wps->registrar, NULL);
        er->set_sel_reg_uuid_filter = NULL;
        if (res)
                return -1;
index 316e1f69fdc012857a64e17ff4cdfd3fd588c12f..a9f8949e7866007009d9d19a6e2f24a39c549d04 100644 (file)
@@ -117,6 +117,8 @@ struct wps_data {
        struct wps_credential *use_cred;
 
        int use_psk_key;
+       u8 p2p_dev_addr[ETH_ALEN]; /* P2P Device Address of the client or
+                                   * 00:00:00:00:00:00 if not a P2p client */
 };
 
 
index ec429f831dcfc64e871e8f5668867d57a94dd5a8..a01066c7723ddc2d3f8f196d32768013583a5ac2 100644 (file)
@@ -135,6 +135,8 @@ struct wps_registrar {
 
        u8 authorized_macs[WPS_MAX_AUTHORIZED_MACS][ETH_ALEN];
        u8 authorized_macs_union[WPS_MAX_AUTHORIZED_MACS][ETH_ALEN];
+
+       u8 p2p_dev_addr[ETH_ALEN];
 };
 
 
@@ -842,6 +844,7 @@ static void wps_registrar_stop_pbc(struct wps_registrar *reg)
 {
        reg->selected_registrar = 0;
        reg->pbc = 0;
+       os_memset(reg->p2p_dev_addr, 0, ETH_ALEN);
        wps_registrar_remove_authorized_mac(reg,
                                            (u8 *) "\xff\xff\xff\xff\xff\xff");
        wps_registrar_selected_registrar_changed(reg);
@@ -861,13 +864,16 @@ static void wps_registrar_pbc_timeout(void *eloop_ctx, void *timeout_ctx)
 /**
  * wps_registrar_button_pushed - Notify Registrar that AP button was pushed
  * @reg: Registrar data from wps_registrar_init()
+ * @p2p_dev_addr: Limit allowed PBC devices to the specified P2P device, %NULL
+ *     indicates no such filtering
  * Returns: 0 on success, -1 on failure
  *
  * This function is called on an AP when a push button is pushed to activate
  * PBC mode. The PBC mode will be stopped after walk time (2 minutes) timeout
  * or when a PBC registration is completed.
  */
-int wps_registrar_button_pushed(struct wps_registrar *reg)
+int wps_registrar_button_pushed(struct wps_registrar *reg,
+                               const u8 *p2p_dev_addr)
 {
        if (wps_registrar_pbc_overlap(reg, NULL, NULL)) {
                wpa_printf(MSG_DEBUG, "WPS: PBC overlap - do not start PBC "
@@ -879,6 +885,10 @@ int wps_registrar_button_pushed(struct wps_registrar *reg)
        reg->force_pbc_overlap = 0;
        reg->selected_registrar = 1;
        reg->pbc = 1;
+       if (p2p_dev_addr)
+               os_memcpy(reg->p2p_dev_addr, p2p_dev_addr, ETH_ALEN);
+       else
+               os_memset(reg->p2p_dev_addr, 0, ETH_ALEN);
        wps_registrar_add_authorized_mac(reg,
                                         (u8 *) "\xff\xff\xff\xff\xff\xff");
        wps_registrar_selected_registrar_changed(reg);
@@ -2226,6 +2236,27 @@ static int wps_process_config_error(struct wps_data *wps, const u8 *err)
 }
 
 
+static int wps_registrar_p2p_dev_addr_match(struct wps_data *wps)
+{
+#ifdef CONFIG_P2P
+       struct wps_registrar *reg = wps->wps->registrar;
+
+       if (is_zero_ether_addr(reg->p2p_dev_addr))
+               return 1; /* no filtering in use */
+
+       if (os_memcmp(reg->p2p_dev_addr, wps->p2p_dev_addr, ETH_ALEN) != 0) {
+               wpa_printf(MSG_DEBUG, "WPS: No match on P2P Device Address "
+                          "filtering for PBC: expected " MACSTR " was "
+                          MACSTR " - indicate PBC session overlap",
+                          MAC2STR(reg->p2p_dev_addr),
+                          MAC2STR(wps->p2p_dev_addr));
+               return 0;
+       }
+#endif /* CONFIG_P2P */
+       return 1;
+}
+
+
 static enum wps_process_res wps_process_m1(struct wps_data *wps,
                                           struct wps_parse_attr *attr)
 {
@@ -2280,12 +2311,16 @@ static enum wps_process_res wps_process_m1(struct wps_data *wps,
        if (wps->dev_pw_id == DEV_PW_PUSHBUTTON) {
                if (wps->wps->registrar->force_pbc_overlap ||
                    wps_registrar_pbc_overlap(wps->wps->registrar,
-                                             wps->mac_addr_e, wps->uuid_e)) {
+                                             wps->mac_addr_e, wps->uuid_e) ||
+                   !wps_registrar_p2p_dev_addr_match(wps)) {
                        wpa_printf(MSG_DEBUG, "WPS: PBC overlap - deny PBC "
                                   "negotiation");
                        wps->state = SEND_M2D;
                        wps->config_error = WPS_CFG_MULTIPLE_PBC_DETECTED;
                        wps_pbc_overlap_event(wps->wps);
+                       wps_fail_event(wps->wps, WPS_M1,
+                                      WPS_CFG_MULTIPLE_PBC_DETECTED,
+                                      WPS_EI_NO_ERROR);
                        wps->wps->registrar->force_pbc_overlap = 1;
                        return WPS_CONTINUE;
                }
index 26ccdeab29a95fc6160aa57bf8111f4b24eccb01..2597816b4320a5fdf5fc80484cd7fad772560d32 100644 (file)
@@ -517,11 +517,13 @@ void wpa_supplicant_ap_rx_eapol(struct wpa_supplicant *wpa_s,
 
 #ifdef CONFIG_WPS
 
-int wpa_supplicant_ap_wps_pbc(struct wpa_supplicant *wpa_s, const u8 *bssid)
+int wpa_supplicant_ap_wps_pbc(struct wpa_supplicant *wpa_s, const u8 *bssid,
+                             const u8 *p2p_dev_addr)
 {
        if (!wpa_s->ap_iface)
                return -1;
-       return hostapd_wps_button_pushed(wpa_s->ap_iface->bss[0]);
+       return hostapd_wps_button_pushed(wpa_s->ap_iface->bss[0],
+                                        p2p_dev_addr);
 }
 
 
index d3bab2490c531d6adca24d38cb1ff5b6d981a099..b913be3e228a3f4f26e832b51a67ce560a183b6f 100644 (file)
@@ -21,7 +21,8 @@ int wpa_supplicant_create_ap(struct wpa_supplicant *wpa_s,
 void wpa_supplicant_ap_deinit(struct wpa_supplicant *wpa_s);
 void wpa_supplicant_ap_rx_eapol(struct wpa_supplicant *wpa_s,
                                const u8 *src_addr, const u8 *buf, size_t len);
-int wpa_supplicant_ap_wps_pbc(struct wpa_supplicant *wpa_s, const u8 *bssid);
+int wpa_supplicant_ap_wps_pbc(struct wpa_supplicant *wpa_s, const u8 *bssid,
+                             const u8 *p2p_dev_addr);
 int wpa_supplicant_ap_wps_pin(struct wpa_supplicant *wpa_s, const u8 *bssid,
                              const char *pin, char *buf, size_t buflen);
 int wpa_supplicant_ap_wps_cancel(struct wpa_supplicant *wpa_s);
index 7731895f4082750401745ec56337283eb80f33a0..31ec5d663357c7970e88faa30577e719d9c7334d 100644 (file)
@@ -213,10 +213,21 @@ static int wpa_supplicant_ctrl_iface_wps_pbc(struct wpa_supplicant *wpa_s,
                                             char *cmd)
 {
        u8 bssid[ETH_ALEN], *_bssid = bssid;
+       u8 p2p_dev_addr[ETH_ALEN], *_p2p_dev_addr = NULL;
 
-       if (cmd == NULL || os_strcmp(cmd, "any") == 0)
+       if (cmd == NULL || os_strcmp(cmd, "any") == 0) {
                _bssid = NULL;
-       else if (hwaddr_aton(cmd, bssid)) {
+#ifdef CONFIG_P2P
+       } else if (os_strncmp(cmd, "p2p_dev_addr=", 13) == 0) {
+               if (hwaddr_aton(cmd + 13, p2p_dev_addr)) {
+                       wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PBC: invalid "
+                                  "P2P Device Address '%s'",
+                                  cmd + 13);
+                       return -1;
+               }
+               _p2p_dev_addr = p2p_dev_addr;
+#endif /* CONFIG_P2P */
+       } else if (hwaddr_aton(cmd, bssid)) {
                wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PBC: invalid BSSID '%s'",
                           cmd);
                return -1;
@@ -224,7 +235,7 @@ static int wpa_supplicant_ctrl_iface_wps_pbc(struct wpa_supplicant *wpa_s,
 
 #ifdef CONFIG_AP
        if (wpa_s->ap_iface)
-               return wpa_supplicant_ap_wps_pbc(wpa_s, _bssid);
+               return wpa_supplicant_ap_wps_pbc(wpa_s, _bssid, _p2p_dev_addr);
 #endif /* CONFIG_AP */
 
        return wpas_wps_start_pbc(wpa_s, _bssid, 0);
index dfc50c529a685e8568f50f0a342240c5a9bc5582..85c3fbe3e52ef964a6fe17ddabcab1570cb33c06 100644 (file)
@@ -857,7 +857,8 @@ static void p2p_go_configured(void *ctx, void *data)
                return;
        }
        if (params->wps_method == WPS_PBC)
-               wpa_supplicant_ap_wps_pbc(wpa_s, params->peer_interface_addr);
+               wpa_supplicant_ap_wps_pbc(wpa_s, params->peer_interface_addr,
+                                         NULL);
        else if (wpa_s->p2p_pin[0])
                wpa_supplicant_ap_wps_pin(wpa_s, params->peer_interface_addr,
                                          wpa_s->p2p_pin, NULL, 0);