P2P: Allow P2P IE without Device Info in (Re)Assoc Req
[libeap.git] / src / ap / ieee802_11.c
index b9f8564..7e0b89b 100644 (file)
@@ -25,6 +25,7 @@
 #include "common/wpa_ctrl.h"
 #include "radius/radius.h"
 #include "radius/radius_client.h"
+#include "p2p/p2p.h"
 #include "wps/wps.h"
 #include "hostapd.h"
 #include "beacon.h"
@@ -664,6 +665,11 @@ static u16 check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta,
                                                          WPS_IE_VENDOR_TYPE);
                wpa_ie = NULL;
                wpa_ie_len = 0;
+               if (sta->wps_ie && wps_validate_assoc_req(sta->wps_ie) < 0) {
+                       wpa_printf(MSG_DEBUG, "WPS: Invalid WPS IE in "
+                                  "(Re)Association Request - reject");
+                       return WLAN_STATUS_INVALID_IE;
+               }
        } else if (hapd->conf->wps_state && wpa_ie == NULL) {
                wpa_printf(MSG_DEBUG, "STA did not include WPA/RSN IE in "
                           "(Re)Association Request - possible WPS use");
@@ -768,6 +774,25 @@ static u16 check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta,
        } else
                wpa_auth_sta_no_wpa(sta->wpa_sm);
 
+#ifdef CONFIG_P2P
+       if (elems.p2p) {
+               wpabuf_free(sta->p2p_ie);
+               sta->p2p_ie = ieee802_11_vendor_ie_concat(ies, ies_len,
+                                                         P2P_IE_VENDOR_TYPE);
+
+               if (p2p_group_notif_assoc(hapd->p2p_group, sta->addr,
+                                         ies, ies_len) < 0) {
+                       wpa_printf(MSG_DEBUG, "P2P: Invalid P2P IE in "
+                                  "(Re)Association Request frame from "
+                                  MACSTR, MAC2STR(sta->addr));
+                       return WLAN_STATUS_UNSPECIFIED_FAILURE;
+               }
+       } else {
+               wpabuf_free(sta->p2p_ie);
+               sta->p2p_ie = NULL;
+       }
+#endif /* CONFIG_P2P */
+
        return WLAN_STATUS_SUCCESS;
 }
 
@@ -859,6 +884,36 @@ static void send_assoc_resp(struct hostapd_data *hapd, struct sta_info *sta,
        }
 #endif /* CONFIG_WPS */
 
+#ifdef CONFIG_P2P
+       if (sta->p2p_ie) {
+               struct wpabuf *p2p_resp_ie;
+               enum p2p_status_code status;
+               switch (status_code) {
+               case WLAN_STATUS_SUCCESS:
+                       status = P2P_SC_SUCCESS;
+                       break;
+               case WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA:
+                       status = P2P_SC_FAIL_LIMIT_REACHED;
+                       break;
+               default:
+                       status = P2P_SC_FAIL_INVALID_PARAMS;
+                       break;
+               }
+               p2p_resp_ie = p2p_group_assoc_resp_ie(hapd->p2p_group, status);
+               if (p2p_resp_ie) {
+                       os_memcpy(p, wpabuf_head(p2p_resp_ie),
+                                 wpabuf_len(p2p_resp_ie));
+                       p += wpabuf_len(p2p_resp_ie);
+                       wpabuf_free(p2p_resp_ie);
+               }
+       }
+#endif /* CONFIG_P2P */
+
+#ifdef CONFIG_P2P_MANAGER
+       if (hapd->conf->p2p & P2P_MANAGE)
+               p = hostapd_eid_p2p_manage(hapd, p);
+#endif /* CONFIG_P2P_MANAGER */
+
        send_len += p - reply->u.assoc_resp.variable;
 
        if (hapd->drv.send_mgmt_frame(hapd, reply, send_len) < 0)
@@ -1347,6 +1402,14 @@ static void handle_action(struct hostapd_data *hapd,
                        return;
                }
                break;
+       case WLAN_ACTION_VENDOR_SPECIFIC:
+               if (hapd->vendor_action_cb) {
+                       if (hapd->vendor_action_cb(hapd->vendor_action_cb_ctx,
+                                                  (u8 *) mgmt, len,
+                                                  hapd->iface->freq) == 0)
+                               return;
+               }
+               break;
        }
 
        hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211,