aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJouni Malinen <jouni.malinen@atheros.com>2011-02-07 16:28:36 (GMT)
committerJouni Malinen <j@w1.fi>2011-02-07 16:28:36 (GMT)
commitd601247ca9b1dff6bb97e6d8608bf32f54e6d98a (patch)
tree22858c6f9c7b479b178bd6712b24e5140e3b88e5 /src
parent379ff7b9d41307ce48814a2be675e2f8ecc47f40 (diff)
downloadhostap-d601247ca9b1dff6bb97e6d8608bf32f54e6d98a.zip
hostap-d601247ca9b1dff6bb97e6d8608bf32f54e6d98a.tar.gz
hostap-d601247ca9b1dff6bb97e6d8608bf32f54e6d98a.tar.bz2
P2P: Allow WPS_PBC command on GO to select on P2P Device Address
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".
Diffstat (limited to 'src')
-rw-r--r--src/ap/drv_callbacks.c2
-rw-r--r--src/ap/wps_hostapd.c9
-rw-r--r--src/ap/wps_hostapd.h6
-rw-r--r--src/eap_server/eap_server_wsc.c4
-rw-r--r--src/wps/wps.c2
-rw-r--r--src/wps/wps.h13
-rw-r--r--src/wps/wps_er.c2
-rw-r--r--src/wps/wps_i.h2
-rw-r--r--src/wps/wps_registrar.c39
9 files changed, 69 insertions, 10 deletions
diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c
index a49248f..c1fdba6 100644
--- a/src/ap/drv_callbacks.c
+++ b/src/ap/drv_callbacks.c
@@ -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:
diff --git a/src/ap/wps_hostapd.c b/src/ap/wps_hostapd.c
index cfff55c..d5042c0 100644
--- a/src/ap/wps_hostapd.c
+++ b/src/ap/wps_hostapd.c
@@ -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);
}
diff --git a/src/ap/wps_hostapd.h b/src/ap/wps_hostapd.h
index 36401be..338a220 100644
--- a/src/ap/wps_hostapd.h
+++ b/src/ap/wps_hostapd.h
@@ -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;
}
diff --git a/src/eap_server/eap_server_wsc.c b/src/eap_server/eap_server_wsc.c
index 83e55d9..e944a4d 100644
--- a/src/eap_server/eap_server_wsc.c
+++ b/src/eap_server/eap_server_wsc.c
@@ -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);
diff --git a/src/wps/wps.c b/src/wps/wps.c
index 73dd58c..a9d41d0 100644
--- a/src/wps/wps.c
+++ b/src/wps/wps.c
@@ -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;
diff --git a/src/wps/wps.h b/src/wps/wps.h
index 771551a..47b3e76 100644
--- a/src/wps/wps.h
+++ b/src/wps/wps.h
@@ -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);
diff --git a/src/wps/wps_er.c b/src/wps/wps_er.c
index d3aee2d..a461836 100644
--- a/src/wps/wps_er.c
+++ b/src/wps/wps_er.c
@@ -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;
diff --git a/src/wps/wps_i.h b/src/wps/wps_i.h
index 316e1f6..a9f8949 100644
--- a/src/wps/wps_i.h
+++ b/src/wps/wps_i.h
@@ -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 */
};
diff --git a/src/wps/wps_registrar.c b/src/wps/wps_registrar.c
index ec429f8..a01066c 100644
--- a/src/wps/wps_registrar.c
+++ b/src/wps/wps_registrar.c
@@ -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;
}