P2P: Remove 802.11b rates from wpa_supplicant AP mode operations
[libeap.git] / wpa_supplicant / ap.c
index 3b5488e..ab63d6f 100644 (file)
 #include "utils/includes.h"
 
 #include "utils/common.h"
+#include "common/ieee802_11_defs.h"
 #include "ap/hostapd.h"
 #include "ap/ap_config.h"
 #ifdef NEED_AP_MLME
 #include "ap/ieee802_11.h"
 #endif /* NEED_AP_MLME */
+#include "ap/ieee802_1x.h"
 #include "ap/wps_hostapd.h"
 #include "ap/ctrl_iface_ap.h"
 #include "eap_common/eap_defs.h"
@@ -65,6 +67,34 @@ static int wpa_supplicant_conf_ap(struct wpa_supplicant *wpa_s,
        /* TODO: enable HT if driver supports it;
         * drop to 11b if driver does not support 11g */
 
+#ifdef CONFIG_P2P
+       if (conf->hw_mode == HOSTAPD_MODE_IEEE80211G) {
+               /* Remove 802.11b rates from supported and basic rate sets */
+               int *list = os_malloc(4 * sizeof(int));
+               if (list) {
+                       list[0] = 60;
+                       list[1] = 120;
+                       list[2] = 240;
+                       list[3] = -1;
+               }
+               conf->basic_rates = list;
+
+               list = os_malloc(9 * sizeof(int));
+               if (list) {
+                       list[0] = 60;
+                       list[1] = 90;
+                       list[2] = 120;
+                       list[3] = 180;
+                       list[4] = 240;
+                       list[5] = 360;
+                       list[6] = 480;
+                       list[7] = 540;
+                       list[8] = -1;
+               }
+               conf->supported_rates = list;
+       }
+#endif /* CONFIG_P2P */
+
        if (ssid->ssid_len == 0) {
                wpa_printf(MSG_ERROR, "No SSID configured for AP mode");
                return -1;
@@ -133,6 +163,24 @@ static int wpa_supplicant_conf_ap(struct wpa_supplicant *wpa_s,
 }
 
 
+static void ap_public_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)
+{
+       return 0;
+}
+
+
+static void ap_wps_reg_success_cb(void *ctx, const u8 *mac_addr,
+                                 const u8 *uuid_e)
+{
+}
+
+
 int wpa_supplicant_create_ap(struct wpa_supplicant *wpa_s,
                             struct wpa_ssid *ssid)
 {
@@ -154,9 +202,41 @@ int wpa_supplicant_create_ap(struct wpa_supplicant *wpa_s,
        os_memset(&params, 0, sizeof(params));
        params.ssid = ssid->ssid;
        params.ssid_len = ssid->ssid_len;
-       params.mode = ssid->mode;
+       switch (ssid->mode) {
+       case WPAS_MODE_INFRA:
+               params.mode = IEEE80211_MODE_INFRA;
+               break;
+       case WPAS_MODE_IBSS:
+               params.mode = IEEE80211_MODE_IBSS;
+               break;
+       case WPAS_MODE_AP:
+       case WPAS_MODE_P2P_GO:
+       case WPAS_MODE_P2P_GROUP_FORMATION:
+               params.mode = IEEE80211_MODE_AP;
+               break;
+       }
        params.freq = ssid->frequency;
 
+       if (ssid->key_mgmt & WPA_KEY_MGMT_PSK)
+               wpa_s->key_mgmt = WPA_KEY_MGMT_PSK;
+       else
+               wpa_s->key_mgmt = WPA_KEY_MGMT_NONE;
+       params.key_mgmt_suite = key_mgmt2driver(wpa_s->key_mgmt);
+
+       if (ssid->pairwise_cipher & WPA_CIPHER_CCMP)
+               wpa_s->pairwise_cipher = WPA_CIPHER_CCMP;
+       else if (ssid->pairwise_cipher & WPA_CIPHER_TKIP)
+               wpa_s->pairwise_cipher = WPA_CIPHER_TKIP;
+       else if (ssid->pairwise_cipher & WPA_CIPHER_NONE)
+               wpa_s->pairwise_cipher = WPA_CIPHER_NONE;
+       else {
+               wpa_printf(MSG_WARNING, "WPA: Failed to select pairwise "
+                          "cipher.");
+               return -1;
+       }
+       params.pairwise_suite = cipher_suite2driver(wpa_s->pairwise_cipher);
+       params.group_suite = params.pairwise_suite;
+
        if (wpa_drv_associate(wpa_s, &params) < 0) {
                wpa_msg(wpa_s, MSG_INFO, "Failed to start AP functionality");
                return -1;
@@ -197,6 +277,12 @@ int wpa_supplicant_create_ap(struct wpa_supplicant *wpa_s,
                }
 
                hapd_iface->bss[i]->msg_ctx = wpa_s;
+               hapd_iface->bss[i]->public_action_cb = ap_public_action_rx;
+               hapd_iface->bss[i]->public_action_cb_ctx = wpa_s;
+               hostapd_register_probereq_cb(hapd_iface->bss[i],
+                                            ap_probe_req_rx, wpa_s);
+               hapd_iface->bss[i]->wps_reg_success_cb = ap_wps_reg_success_cb;
+               hapd_iface->bss[i]->wps_reg_success_cb_ctx = wpa_s;
        }
 
        os_memcpy(hapd_iface->bss[0]->own_addr, wpa_s->own_addr, ETH_ALEN);
@@ -213,6 +299,10 @@ int wpa_supplicant_create_ap(struct wpa_supplicant *wpa_s,
        os_memcpy(wpa_s->bssid, wpa_s->own_addr, ETH_ALEN);
        wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
 
+       if (wpa_s->ap_configured_cb)
+               wpa_s->ap_configured_cb(wpa_s->ap_configured_cb_ctx,
+                                       wpa_s->ap_configured_cb_data);
+
        return 0;
 }
 
@@ -222,8 +312,11 @@ void wpa_supplicant_ap_deinit(struct wpa_supplicant *wpa_s)
        if (wpa_s->ap_iface == NULL)
                return;
 
+       wpa_s->current_ssid = NULL;
        hostapd_interface_deinit(wpa_s->ap_iface);
+       hostapd_interface_free(wpa_s->ap_iface);
        wpa_s->ap_iface = NULL;
+       wpa_drv_deinit_ap(wpa_s);
 }
 
 
@@ -237,11 +330,12 @@ void ap_tx_status(void *ctx, const u8 *addr,
 }
 
 
-void ap_rx_from_unknown_sta(void *ctx, const struct ieee80211_hdr *hdr,
-                           size_t len)
+void ap_rx_from_unknown_sta(void *ctx, const u8 *frame, size_t len)
 {
 #ifdef NEED_AP_MLME
        struct wpa_supplicant *wpa_s = ctx;
+       const struct ieee80211_hdr *hdr =
+               (const struct ieee80211_hdr *) frame;
        u16 fc = le_to_host16(hdr->frame_control);
        ieee802_11_rx_from_unknown(wpa_s->ap_iface->bss[0], hdr->addr2,
                                   (fc & (WLAN_FC_TODS | WLAN_FC_FROMDS)) ==
@@ -250,12 +344,16 @@ void ap_rx_from_unknown_sta(void *ctx, const struct ieee80211_hdr *hdr,
 }
 
 
-void ap_mgmt_rx(void *ctx, const u8 *buf, size_t len,
-               struct hostapd_frame_info *fi)
+void ap_mgmt_rx(void *ctx, struct rx_mgmt *rx_mgmt)
 {
 #ifdef NEED_AP_MLME
        struct wpa_supplicant *wpa_s = ctx;
-       ieee802_11_mgmt(wpa_s->ap_iface->bss[0], buf, len, fi);
+       struct hostapd_frame_info fi;
+       os_memset(&fi, 0, sizeof(fi));
+       fi.datarate = rx_mgmt->datarate;
+       fi.ssi_signal = rx_mgmt->ssi_signal;
+       ieee802_11_mgmt(wpa_s->ap_iface->bss[0], rx_mgmt->frame,
+                       rx_mgmt->frame_len, &fi);
 #endif /* NEED_AP_MLME */
 }
 
@@ -272,7 +370,7 @@ void ap_mgmt_tx_cb(void *ctx, const u8 *buf, size_t len, u16 stype, int ok)
 void wpa_supplicant_ap_rx_eapol(struct wpa_supplicant *wpa_s,
                                const u8 *src_addr, const u8 *buf, size_t len)
 {
-       hostapd_eapol_receive(wpa_s->ap_iface->bss[0], src_addr, buf, len);
+       ieee802_1x_receive(wpa_s->ap_iface->bss[0], src_addr, buf, len);
 }
 
 
@@ -280,6 +378,8 @@ void wpa_supplicant_ap_rx_eapol(struct wpa_supplicant *wpa_s,
 
 int wpa_supplicant_ap_wps_pbc(struct wpa_supplicant *wpa_s, const u8 *bssid)
 {
+       if (!wpa_s->ap_iface)
+               return -1;
        return hostapd_wps_button_pushed(wpa_s->ap_iface->bss[0]);
 }
 
@@ -289,13 +389,17 @@ int wpa_supplicant_ap_wps_pin(struct wpa_supplicant *wpa_s, const u8 *bssid,
 {
        int ret, ret_len = 0;
 
+       if (!wpa_s->ap_iface)
+               return -1;
+
        if (pin == NULL) {
                unsigned int rpin = wps_generate_pin();
                ret_len = os_snprintf(buf, buflen, "%d", rpin);
                pin = buf;
        }
 
-       ret = hostapd_wps_add_pin(wpa_s->ap_iface->bss[0], "any", pin, 0);
+       ret = hostapd_wps_add_pin(wpa_s->ap_iface->bss[0], bssid, "any", pin,
+                                 0);
        if (ret)
                return -1;
        return ret_len;
@@ -365,3 +469,44 @@ int ap_ctrl_iface_wpa_get_status(struct wpa_supplicant *wpa_s, char *buf,
 }
 
 #endif /* CONFIG_CTRL_IFACE */
+
+
+int wpa_supplicant_ap_mac_addr_filter(struct wpa_supplicant *wpa_s,
+                                     const u8 *addr)
+{
+       struct hostapd_data *hapd;
+       struct hostapd_bss_config *conf;
+
+       if (!wpa_s->ap_iface)
+               return -1;
+
+       if (addr)
+               wpa_printf(MSG_DEBUG, "AP: Set MAC address filter: " MACSTR,
+                          MAC2STR(addr));
+       else
+               wpa_printf(MSG_DEBUG, "AP: Clear MAC address filter");
+
+       hapd = wpa_s->ap_iface->bss[0];
+       conf = hapd->conf;
+
+       os_free(conf->accept_mac);
+       conf->accept_mac = NULL;
+       conf->num_accept_mac = 0;
+       os_free(conf->deny_mac);
+       conf->deny_mac = NULL;
+       conf->num_deny_mac = 0;
+
+       if (addr == NULL) {
+               conf->macaddr_acl = ACCEPT_UNLESS_DENIED;
+               return 0;
+       }
+
+       conf->macaddr_acl = DENY_UNLESS_ACCEPTED;
+       conf->accept_mac = os_zalloc(sizeof(struct mac_acl_entry));
+       if (conf->accept_mac == NULL)
+               return -1;
+       os_memcpy(conf->accept_mac[0].addr, addr, ETH_ALEN);
+       conf->num_accept_mac = 1;
+
+       return 0;
+}