wps_registrar_deinit(hapd->wps->registrar);
os_free(hapd->wps->network_key);
wps_device_data_free(&hapd->wps->dev);
- wpabuf_free(hapd->wps->upnp_msg);
+ wps_free_pending_msgs(hapd->wps->upnp_msgs);
os_free(hapd->wps);
hapd->wps = NULL;
hostapd_wps_clear_ies(hapd);
static int hostapd_rx_req_put_wlan_event_response(
void *priv, enum upnp_wps_wlanevent_type ev_type,
- const u8 *mac_addr, const struct wpabuf *msg)
+ const u8 *mac_addr, const struct wpabuf *msg,
+ enum wps_msg_type msg_type)
{
struct hostapd_data *hapd = priv;
struct sta_info *sta;
+ struct upnp_pending_message *p;
wpa_printf(MSG_DEBUG, "WPS UPnP: PutWLANResponse ev_type=%d mac_addr="
MACSTR, ev_type, MAC2STR(mac_addr));
* server implementation for delivery to the peer.
*/
- /* TODO: support multiple pending UPnP messages */
- os_memcpy(hapd->wps->upnp_msg_addr, mac_addr, ETH_ALEN);
- wpabuf_free(hapd->wps->upnp_msg);
- hapd->wps->upnp_msg = wpabuf_dup(msg);
-
sta = ap_get_sta(hapd, mac_addr);
if (!sta) {
/*
wpa_printf(MSG_DEBUG, "WPS UPnP: No matching STA found based "
"on NewWLANEventMAC; try wildcard match");
for (sta = hapd->sta_list; sta; sta = sta->next) {
- if (sta->eapol_sm &&
- sta->eapol_sm->eap == hapd->wps->pending_session)
+ if (sta->eapol_sm && (sta->flags & WLAN_STA_WPS))
break;
}
}
- if (sta)
- return eapol_auth_eap_pending_cb(sta->eapol_sm,
- hapd->wps->pending_session);
- wpa_printf(MSG_DEBUG, "WPS UPnP: No matching STA found");
+ if (!sta) {
+ wpa_printf(MSG_DEBUG, "WPS UPnP: No matching STA found");
+ return 0;
+ }
- return 0;
+ p = os_zalloc(sizeof(*p));
+ if (p == NULL)
+ return -1;
+ os_memcpy(p->addr, sta->addr, ETH_ALEN);
+ p->msg = wpabuf_dup(msg);
+ p->type = msg_type;
+ p->next = hapd->wps->upnp_msgs;
+ hapd->wps->upnp_msgs = p;
+
+ return eapol_auth_eap_pending_cb(sta->eapol_sm, sta->eapol_sm->eap);
}
case WPS_PENDING:
eap_wsc_state(data, MSG);
sm->method_pending = METHOD_PENDING_WAIT;
- sm->wps->pending_session = sm;
eloop_cancel_timeout(eap_wsc_ext_reg_timeout, sm, data);
eloop_register_timeout(5, 0, eap_wsc_ext_reg_timeout,
sm, data);
return ie;
}
+
+
+void wps_free_pending_msgs(struct upnp_pending_message *msgs)
+{
+ struct upnp_pending_message *p, *prev;
+ p = msgs;
+ while (p) {
+ prev = p;
+ p = p->next;
+ wpabuf_free(prev->msg);
+ os_free(prev);
+ }
+}
} pwd_auth_fail;
};
+/**
+ * struct upnp_pending_message - Pending PutWLANResponse messages
+ * @next: Pointer to next pending message or %NULL
+ * @addr: NewWLANEventMAC
+ * @msg: NewMessage
+ * @type: Message Type
+ */
+struct upnp_pending_message {
+ struct upnp_pending_message *next;
+ u8 addr[ETH_ALEN];
+ struct wpabuf *msg;
+ enum wps_msg_type type;
+};
+
/**
* struct wps_context - Long term WPS context data
*
struct upnp_wps_device_sm *wps_upnp;
- /* TODO: support multiple pending messages from UPnP PutWLANResponse */
- u8 upnp_msg_addr[ETH_ALEN];
- struct wpabuf *upnp_msg;
- void *pending_session;
+ /* Pending messages from UPnP PutWLANResponse */
+ struct upnp_pending_message *upnp_msgs;
};
unsigned int wps_pin_checksum(unsigned int pin);
unsigned int wps_pin_valid(unsigned int pin);
unsigned int wps_generate_pin(void);
+void wps_free_pending_msgs(struct upnp_pending_message *msgs);
#endif /* WPS_H */
}
+#ifdef CONFIG_WPS_UPNP
+static void wps_registrar_free_pending_m2(struct wps_context *wps)
+{
+ struct upnp_pending_message *p, *p2, *prev = NULL;
+ p = wps->upnp_msgs;
+ while (p) {
+ if (p->type == WPS_M2 || p->type == WPS_M2D) {
+ if (prev == NULL)
+ wps->upnp_msgs = p->next;
+ else
+ prev->next = p->next;
+ wpa_printf(MSG_DEBUG, "WPS UPnP: Drop pending M2/M2D");
+ p2 = p;
+ p = p->next;
+ wpabuf_free(p2->msg);
+ os_free(p2);
+ continue;
+ }
+ prev = p;
+ p = p->next;
+ }
+}
+#endif /* CONFIG_WPS_UPNP */
+
+
static int wps_build_ap_setup_locked(struct wps_context *wps,
struct wpabuf *msg)
{
struct wpabuf *msg;
#ifdef CONFIG_WPS_UPNP
- if (wps->wps->wps_upnp && wps->wps->upnp_msg) {
- wpa_printf(MSG_DEBUG, "WPS: Use pending message from UPnP");
- msg = wps->wps->upnp_msg;
- wps->wps->upnp_msg = NULL;
- *op_code = WSC_MSG; /* FIX: ack/nack */
- wps->ext_reg = 1;
- return msg;
+ if (wps->wps->wps_upnp) {
+ struct upnp_pending_message *p, *prev = NULL;
+ if (wps->ext_reg > 1)
+ wps_registrar_free_pending_m2(wps->wps);
+ p = wps->wps->upnp_msgs;
+ /* TODO: check pending message MAC address */
+ while (p && p->next) {
+ prev = p;
+ p = p->next;
+ }
+ if (p) {
+ wpa_printf(MSG_DEBUG, "WPS: Use pending message from "
+ "UPnP");
+ if (prev)
+ prev->next = NULL;
+ else
+ wps->wps->upnp_msgs = NULL;
+ msg = p->msg;
+ os_free(p);
+ *op_code = WSC_MSG;
+ if (wps->ext_reg == 0)
+ wps->ext_reg = 1;
+ return msg;
+ }
}
if (wps->ext_reg) {
wpa_printf(MSG_DEBUG, "WPS: Using external Registrar, but no "
#ifdef CONFIG_WPS_UPNP
if (wps->wps->wps_upnp && attr.mac_addr) {
/* Remove old pending messages when starting new run */
- wpabuf_free(wps->wps->upnp_msg);
- wps->wps->upnp_msg = NULL;
+ wps_free_pending_msgs(wps->wps->upnp_msgs);
+ wps->wps->upnp_msgs = NULL;
upnp_wps_device_send_wlan_event(
wps->wps->wps_upnp, attr.mac_addr,
#ifdef CONFIG_WPS_UPNP
if (wps->wps->wps_upnp && wps->ext_reg && wps->state == RECV_M2D_ACK &&
upnp_wps_subscribers(wps->wps->wps_upnp)) {
- if (wps->wps->upnp_msg)
+ if (wps->wps->upnp_msgs)
return WPS_CONTINUE;
wpa_printf(MSG_DEBUG, "WPS: Wait for response from an "
"external Registrar");
#ifdef CONFIG_WPS_UPNP
if (wps->wps->wps_upnp &&
upnp_wps_subscribers(wps->wps->wps_upnp)) {
- if (wps->wps->upnp_msg)
+ if (wps->wps->upnp_msgs)
return WPS_CONTINUE;
+ if (wps->ext_reg == 0)
+ wps->ext_reg = 1;
wpa_printf(MSG_DEBUG, "WPS: Wait for response from an "
"external Registrar");
return WPS_PENDING;
(unsigned long) wpabuf_len(msg), op_code);
#ifdef CONFIG_WPS_UPNP
- if (wps->wps->wps_upnp && wps->ext_reg && wps->wps->upnp_msg == NULL &&
+ if (wps->wps->wps_upnp && op_code == WSC_MSG && wps->ext_reg == 1) {
+ struct wps_parse_attr attr;
+ if (wps_parse_msg(msg, &attr) == 0 && attr.msg_type &&
+ *attr.msg_type == WPS_M3)
+ wps->ext_reg = 2; /* past M2/M2D phase */
+ }
+ if (wps->ext_reg > 1)
+ wps_registrar_free_pending_m2(wps->wps);
+ if (wps->wps->wps_upnp && wps->ext_reg &&
+ wps->wps->upnp_msgs == NULL &&
(op_code == WSC_MSG || op_code == WSC_Done)) {
struct wps_parse_attr attr;
int type;
int (*rx_req_del_sta_settings)(void *priv, const struct wpabuf *msg);
int (*rx_req_put_wlan_event_response)(
void *priv, enum upnp_wps_wlanevent_type ev_type,
- const u8 *mac_addr, const struct wpabuf *msg);
+ const u8 *mac_addr, const struct wpabuf *msg,
+ enum wps_msg_type msg_type);
int (*rx_req_set_selected_registrar)(void *priv,
const struct wpabuf *msg);
int (*rx_req_reboot_ap)(void *priv, const struct wpabuf *msg);
#include "eloop.h"
#include "uuid.h"
#include "httpread.h"
+#include "wps_defs.h"
#include "wps_upnp.h"
#include "wps_upnp_i.h"
enum http_reply_code ret;
u8 macaddr[ETH_ALEN];
int ev_type;
+ int type;
char *val;
/*
os_free(val);
if (ev_type == UPNP_WPS_WLANEVENT_TYPE_EAP) {
struct wps_parse_attr attr;
- int type;
if (wps_parse_msg(msg, &attr) < 0 ||
attr.msg_type == NULL)
type = -1;
else
type = *attr.msg_type;
wpa_printf(MSG_DEBUG, "WPS UPnP: Message Type %d", type);
- }
+ } else
+ type = -1;
if (!sm->ctx->rx_req_put_wlan_event_response ||
sm->ctx->rx_req_put_wlan_event_response(sm->priv, ev_type,
- macaddr, msg)) {
+ macaddr, msg, type)) {
wpa_printf(MSG_INFO, "WPS UPnP: Fail: sm->ctx->"
"rx_req_put_wlan_event_response");
wpabuf_free(msg);