OSDN Git Service

Accumulative patch from commit 565110cd554801fa301c55010b3e9e14f43d7973
authorDmitry Shmidt <dimitrysh@google.com>
Fri, 15 Mar 2013 21:14:44 +0000 (14:14 -0700)
committerDmitry Shmidt <dimitrysh@google.com>
Mon, 18 Mar 2013 19:55:26 +0000 (12:55 -0700)
nl80211: Include interface name in more debug prints
Convert WPS NFC python scripts from using wpactrl to wpaspy
wpa_supplicant: Fix lookup of cached PMKSA
Add capability flag for IBSS and add get_capability modes
hostapd: Fix client reassociation after disconnect due to ACK failure
Fix build with CONFIG_NO_CONFIG_BLOBS
Fix build without CONFIG_CTRL_IFACE or CONFIG_NO_STDOUT_DEBUG
libtommath: Avoid a compiler warning on unused variable
libtommath: Condition fast_s_mp_mul_digs() on LTM_FAST
P2P: Remove persistent group peer if it rejects invitation
P2P: Allow shared interface channel preference to be ignored
P2P: Fix shared frequency preference for concurrent operations
P2P: Use best-overall channel in p2p_reselect_channel()
P2P: Allow all channels for multi-channel concurrency (no negotiation)
TDLS: Disable link to existing peer with lower address
Fix compiler warning when CONFIG_IEEE80211R is not included
WPS NFC: Fix build without CONFIG_WPS_ER
FT: Add support for IEEE 802.11r with driver-based SME

Change-Id: I1d5ced870c33d5cb73ecc6f04e272a3cf50f344a
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
28 files changed:
hostapd/wps-ap-nfc.py
src/ap/sta_info.c
src/common/ieee802_11_defs.h
src/drivers/driver.h
src/drivers/driver_nl80211.c
src/p2p/p2p.c
src/p2p/p2p.h
src/p2p/p2p_go_neg.c
src/p2p/p2p_i.h
src/p2p/p2p_invitation.c
src/rsn_supp/tdls.c
src/rsn_supp/wpa_ft.c
src/tls/libtommath.c
wpa_supplicant/config.c
wpa_supplicant/config.h
wpa_supplicant/ctrl_iface.c
wpa_supplicant/dbus/dbus_new.c
wpa_supplicant/dbus/dbus_new_handlers.c
wpa_supplicant/dbus/dbus_old.c
wpa_supplicant/dbus/dbus_old_handlers.c
wpa_supplicant/events.c
wpa_supplicant/examples/wps-nfc.py
wpa_supplicant/p2p_supplicant.c
wpa_supplicant/wpa_cli.c
wpa_supplicant/wpa_supplicant.c
wpa_supplicant/wpa_supplicant_i.h
wpa_supplicant/wpas_glue.c
wpa_supplicant/wps_supplicant.c

index 6ad0b43..61b5519 100755 (executable)
@@ -18,7 +18,7 @@ import nfc.handover
 import logging
 logging.basicConfig()
 
-import wpactrl
+import wpaspy
 
 wpas_ctrl = '/var/run/hostapd'
 
@@ -37,10 +37,9 @@ def wpas_connect():
 
     for ctrl in ifaces:
         try:
-            wpas = wpactrl.WPACtrl(ctrl)
+            wpas = wpaspy.Ctrl(ctrl)
             return wpas
-        except wpactrl.error, error:
-            print "Error: ", error
+        except Exception, e:
             pass
     return None
 
index 8ada121..cbafb47 100644 (file)
@@ -576,7 +576,7 @@ void ap_sta_disassociate(struct hostapd_data *hapd, struct sta_info *sta,
 {
        wpa_printf(MSG_DEBUG, "%s: disassociate STA " MACSTR,
                   hapd->conf->iface, MAC2STR(sta->addr));
-       sta->flags &= ~WLAN_STA_ASSOC;
+       sta->flags &= ~(WLAN_STA_ASSOC | WLAN_STA_ASSOC_REQ_OK);
        ap_sta_set_authorized(hapd, sta, 0);
        sta->timeout_next = STA_DEAUTH;
        wpa_printf(MSG_DEBUG, "%s: reschedule ap_handle_timer timeout "
index 652476f..f782c86 100644 (file)
@@ -1005,6 +1005,8 @@ enum wifi_display_subelem {
 /* AKM suite selectors */
 #define WLAN_AKM_SUITE_8021X           0x000FAC01
 #define WLAN_AKM_SUITE_PSK             0x000FAC02
+#define WLAN_AKM_SUITE_FT_8021X                0x000FAC03
+#define WLAN_AKM_SUITE_FT_PSK          0x000FAC04
 #define WLAN_AKM_SUITE_CCKM            0x00409600
 
 
index f12f4bc..63f90bc 100644 (file)
@@ -864,6 +864,8 @@ struct wpa_driver_capa {
 #define WPA_DRIVER_FLAGS_SAE                           0x02000000
 /* Driver makes use of OBSS scan mechanism in wpa_supplicant */
 #define WPA_DRIVER_FLAGS_OBSS_SCAN                     0x04000000
+/* Driver supports IBSS (Ad-hoc) mode */
+#define WPA_DRIVER_FLAGS_IBSS                          0x08000000
        unsigned int flags;
 
        int max_scan_ssids;
index 3a35a6b..efd5cab 100644 (file)
@@ -1642,6 +1642,34 @@ static void mlme_event_remain_on_channel(struct wpa_driver_nl80211_data *drv,
 }
 
 
+static void mlme_event_ft_event(struct wpa_driver_nl80211_data *drv,
+                               struct nlattr *tb[])
+{
+       union wpa_event_data data;
+
+       os_memset(&data, 0, sizeof(data));
+
+       if (tb[NL80211_ATTR_IE]) {
+               data.ft_ies.ies = nla_data(tb[NL80211_ATTR_IE]);
+               data.ft_ies.ies_len = nla_len(tb[NL80211_ATTR_IE]);
+       }
+
+       if (tb[NL80211_ATTR_IE_RIC]) {
+               data.ft_ies.ric_ies = nla_data(tb[NL80211_ATTR_IE_RIC]);
+               data.ft_ies.ric_ies_len = nla_len(tb[NL80211_ATTR_IE_RIC]);
+       }
+
+       if (tb[NL80211_ATTR_MAC])
+               os_memcpy(data.ft_ies.target_ap,
+                         nla_data(tb[NL80211_ATTR_MAC]), ETH_ALEN);
+
+       wpa_printf(MSG_DEBUG, "nl80211: FT event target_ap " MACSTR,
+                  MAC2STR(data.ft_ies.target_ap));
+
+       wpa_supplicant_event(drv->ctx, EVENT_FT_RESPONSE, &data);
+}
+
+
 static void send_scan_event(struct wpa_driver_nl80211_data *drv, int aborted,
                            struct nlattr *tb[])
 {
@@ -2232,29 +2260,30 @@ static void do_process_drv_event(struct i802_bss *bss, int cmd,
 
        switch (cmd) {
        case NL80211_CMD_TRIGGER_SCAN:
-               wpa_printf(MSG_DEBUG, "nl80211: Scan trigger");
+               wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: Scan trigger");
                break;
        case NL80211_CMD_START_SCHED_SCAN:
-               wpa_printf(MSG_DEBUG, "nl80211: Sched scan started");
+               wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: Sched scan started");
                break;
        case NL80211_CMD_SCHED_SCAN_STOPPED:
-               wpa_printf(MSG_DEBUG, "nl80211: Sched scan stopped");
+               wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: Sched scan stopped");
                wpa_supplicant_event(drv->ctx, EVENT_SCHED_SCAN_STOPPED, NULL);
                break;
        case NL80211_CMD_NEW_SCAN_RESULTS:
-               wpa_printf(MSG_DEBUG, "nl80211: New scan results available");
+               wpa_dbg(drv->ctx, MSG_DEBUG,
+                       "nl80211: New scan results available");
                drv->scan_complete_events = 1;
                eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout, drv,
                                     drv->ctx);
                send_scan_event(drv, 0, tb);
                break;
        case NL80211_CMD_SCHED_SCAN_RESULTS:
-               wpa_printf(MSG_DEBUG,
-                          "nl80211: New sched scan results available");
+               wpa_dbg(drv->ctx, MSG_DEBUG,
+                       "nl80211: New sched scan results available");
                send_scan_event(drv, 0, tb);
                break;
        case NL80211_CMD_SCAN_ABORTED:
-               wpa_printf(MSG_DEBUG, "nl80211: Scan aborted");
+               wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: Scan aborted");
                /*
                 * Need to indicate that scan results are available in order
                 * not to make wpa_supplicant stop its scanning.
@@ -2339,9 +2368,12 @@ static void do_process_drv_event(struct i802_bss *bss, int cmd,
        case NL80211_CMD_CONN_FAILED:
                nl80211_connect_failed_event(drv, tb);
                break;
+       case NL80211_CMD_FT_EVENT:
+               mlme_event_ft_event(drv, tb);
+               break;
        default:
-               wpa_printf(MSG_DEBUG, "nl80211: Ignored unknown event "
-                          "(cmd=%d)", cmd);
+               wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: Ignored unknown event "
+                       "(cmd=%d)", cmd);
                break;
        }
 }
@@ -2569,6 +2601,9 @@ static void wiphy_info_supported_iftypes(struct wiphy_info_data *info,
                case NL80211_IFTYPE_AP:
                        info->capa->flags |= WPA_DRIVER_FLAGS_AP;
                        break;
+               case NL80211_IFTYPE_ADHOC:
+                       info->capa->flags |= WPA_DRIVER_FLAGS_IBSS;
+                       break;
                case NL80211_IFTYPE_P2P_GO:
                        info->p2p_go_supported = 1;
                        break;
@@ -3831,6 +3866,7 @@ static int wpa_driver_nl80211_scan(struct i802_bss *bss,
        int ret = -1, timeout;
        struct nl_msg *msg, *rates = NULL;
 
+       wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: scan request");
        drv->scan_for_auth = 0;
 
        msg = nl80211_scan_common(drv, NL80211_CMD_TRIGGER_SCAN, params);
@@ -3932,6 +3968,8 @@ static int wpa_driver_nl80211_sched_scan(void *priv,
        struct nl_msg *match_set_rssi = NULL;
        size_t i;
 
+       wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: sched_scan request");
+
 #ifdef ANDROID
        if (!drv->capa.sched_scan_supported)
                return android_pno_start(bss, params);
@@ -7173,6 +7211,8 @@ skip_auth_type:
 
        if (params->key_mgmt_suite == KEY_MGMT_802_1X ||
            params->key_mgmt_suite == KEY_MGMT_PSK ||
+           params->key_mgmt_suite == KEY_MGMT_FT_802_1X ||
+           params->key_mgmt_suite == KEY_MGMT_FT_PSK ||
            params->key_mgmt_suite == KEY_MGMT_CCKM) {
                int mgmt = WLAN_AKM_SUITE_PSK;
 
@@ -7183,6 +7223,12 @@ skip_auth_type:
                case KEY_MGMT_802_1X:
                        mgmt = WLAN_AKM_SUITE_8021X;
                        break;
+               case KEY_MGMT_FT_802_1X:
+                       mgmt = WLAN_AKM_SUITE_FT_8021X;
+                       break;
+               case KEY_MGMT_FT_PSK:
+                       mgmt = WLAN_AKM_SUITE_FT_PSK;
+                       break;
                case KEY_MGMT_PSK:
                default:
                        mgmt = WLAN_AKM_SUITE_PSK;
@@ -9676,6 +9722,39 @@ static int driver_nl80211_probe_req_report(void *priv, int report)
 }
 
 
+static int wpa_driver_nl80211_update_ft_ies(void *priv, const u8 *md,
+                                           const u8 *ies, size_t ies_len)
+{
+       int ret;
+       struct nl_msg *msg;
+       struct i802_bss *bss = priv;
+       struct wpa_driver_nl80211_data *drv = bss->drv;
+       u16 mdid = WPA_GET_LE16(md);
+
+       msg = nlmsg_alloc();
+       if (!msg)
+               return -ENOMEM;
+
+       wpa_printf(MSG_DEBUG, "nl80211: Updating FT IEs");
+       nl80211_cmd(drv, msg, 0, NL80211_CMD_UPDATE_FT_IES);
+       NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
+       NLA_PUT(msg, NL80211_ATTR_IE, ies_len, ies);
+       NLA_PUT_U16(msg, NL80211_ATTR_MDID, mdid);
+
+       ret = send_and_recv_msgs(drv, msg, NULL, NULL);
+       if (ret) {
+               wpa_printf(MSG_DEBUG, "nl80211: update_ft_ies failed "
+                          "err=%d (%s)", ret, strerror(-ret));
+       }
+
+       return ret;
+
+nla_put_failure:
+       nlmsg_free(msg);
+       return -ENOBUFS;
+}
+
+
 const struct wpa_driver_ops wpa_driver_nl80211_ops = {
        .name = "nl80211",
        .desc = "Linux nl80211/cfg80211",
@@ -9751,6 +9830,7 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops = {
        .send_tdls_mgmt = nl80211_send_tdls_mgmt,
        .tdls_oper = nl80211_tdls_oper,
 #endif /* CONFIG_TDLS */
+       .update_ft_ies = wpa_driver_nl80211_update_ft_ies,
 #ifdef ANDROID_P2P
        .set_noa = wpa_driver_set_p2p_noa,
        .get_noa = wpa_driver_get_p2p_noa,
index 704e531..2b5e5bd 100644 (file)
@@ -3490,7 +3490,8 @@ static void p2p_timeout_invite_listen(struct p2p_data *p2p)
                                "P2P: Invitation Request retry limit reached");
                        if (p2p->cfg->invitation_result)
                                p2p->cfg->invitation_result(
-                                       p2p->cfg->cb_ctx, -1, NULL, NULL);
+                                       p2p->cfg->cb_ctx, -1, NULL, NULL,
+                                       p2p->invite_peer->info.p2p_device_addr);
                }
                p2p_set_state(p2p, P2P_IDLE);
        }
@@ -4319,6 +4320,14 @@ void p2p_set_best_channels(struct p2p_data *p2p, int freq_24, int freq_5,
 }
 
 
+void p2p_set_own_freq_preference(struct p2p_data *p2p, int freq)
+{
+       wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Own frequency preference: "
+               "%d MHz", freq);
+       p2p->own_freq_preference = freq;
+}
+
+
 const u8 * p2p_get_go_neg_peer(struct p2p_data *p2p)
 {
        if (p2p == NULL || p2p->go_neg_peer == NULL)
index 4f9b75d..28a0a1d 100644 (file)
@@ -743,6 +743,7 @@ struct p2p_config {
         * @status: Negotiation result (Status Code)
         * @bssid: P2P Group BSSID or %NULL if not received
         * @channels: Available operating channels for the group
+        * @addr: Peer address
         *
         * This callback is used to indicate result of an Invitation procedure
         * started with a call to p2p_invite(). The indicated status code is
@@ -751,7 +752,8 @@ struct p2p_config {
         * local failure in transmitting the Invitation Request.
         */
        void (*invitation_result)(void *ctx, int status, const u8 *bssid,
-                                 const struct p2p_channels *channels);
+                                 const struct p2p_channels *channels,
+                                 const u8 *addr);
 
        /**
         * go_connected - Check whether we are connected to a GO
@@ -1658,6 +1660,17 @@ void p2p_update_channel_list(struct p2p_data *p2p, struct p2p_channels *chan);
 void p2p_set_best_channels(struct p2p_data *p2p, int freq_24, int freq_5,
                           int freq_overall);
 
+/**
+ * p2p_set_own_freq_preference - Set own preference for channel
+ * @p2p: P2P module context from p2p_init()
+ * @freq: Frequency (MHz) of the preferred channel or 0 if no preference
+ *
+ * This function can be used to set a preference on the operating channel based
+ * on frequencies used on the other virtual interfaces that share the same
+ * radio. If non-zero, this is used to try to avoid multi-channel concurrency.
+ */
+void p2p_set_own_freq_preference(struct p2p_data *p2p, int freq);
+
 const u8 * p2p_get_go_neg_peer(struct p2p_data *p2p);
 
 /**
index 61153d4..c143ef4 100644 (file)
@@ -350,14 +350,36 @@ void p2p_reselect_channel(struct p2p_data *p2p,
        u8 op_reg_class, op_channel;
        unsigned int i;
 
-       wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Selected operating "
-               "channel (reg_class %u channel %u) not acceptable to the "
-               "peer", p2p->op_reg_class, p2p->op_channel);
+       if (p2p->own_freq_preference > 0 &&
+           p2p_freq_to_channel(p2p->cfg->country, p2p->own_freq_preference,
+                               &op_reg_class, &op_channel) == 0 &&
+           p2p_channels_includes(intersection, op_reg_class, op_channel)) {
+               wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Pick own channel "
+                       "preference (reg_class %u channel %u) from "
+                       "intersection", op_reg_class, op_channel);
+               p2p->op_reg_class = op_reg_class;
+               p2p->op_channel = op_channel;
+               return;
+       }
+
+       if (p2p->best_freq_overall > 0 &&
+           p2p_freq_to_channel(p2p->cfg->country, p2p->best_freq_overall,
+                               &op_reg_class, &op_channel) == 0 &&
+           p2p_channels_includes(intersection, op_reg_class, op_channel)) {
+               wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Pick best overall "
+                       "channel (reg_class %u channel %u) from intersection",
+                       op_reg_class, op_channel);
+               p2p->op_reg_class = op_reg_class;
+               p2p->op_channel = op_channel;
+               return;
+       }
 
        /* First, try to pick the best channel from another band */
        freq = p2p_channel_to_freq(p2p->cfg->country, p2p->op_reg_class,
                                   p2p->op_channel);
        if (freq >= 2400 && freq < 2500 && p2p->best_freq_5 > 0 &&
+           !p2p_channels_includes(intersection, p2p->op_reg_class,
+                                  p2p->op_channel) &&
            p2p_freq_to_channel(p2p->cfg->country, p2p->best_freq_5,
                                &op_reg_class, &op_channel) == 0 &&
            p2p_channels_includes(intersection, op_reg_class, op_channel)) {
@@ -370,6 +392,8 @@ void p2p_reselect_channel(struct p2p_data *p2p,
        }
 
        if (freq >= 4900 && freq < 6000 && p2p->best_freq_24 > 0 &&
+           !p2p_channels_includes(intersection, p2p->op_reg_class,
+                                  p2p->op_channel) &&
            p2p_freq_to_channel(p2p->cfg->country, p2p->best_freq_24,
                                &op_reg_class, &op_channel) == 0 &&
            p2p_channels_includes(intersection, op_reg_class, op_channel)) {
index 5286b02..d5ce52f 100644 (file)
@@ -430,6 +430,7 @@ struct p2p_data {
        int best_freq_24;
        int best_freq_5;
        int best_freq_overall;
+       int own_freq_preference;
 
        /**
         * wps_vendor_ext - WPS Vendor Extensions to add
index 43d9475..2ed9730 100644 (file)
@@ -466,7 +466,7 @@ void p2p_process_invitation_resp(struct p2p_data *p2p, const u8 *sa,
 
        if (p2p->cfg->invitation_result)
                p2p->cfg->invitation_result(p2p->cfg->cb_ctx, *msg.status,
-                                           msg.group_bssid, channels);
+                                           msg.group_bssid, channels, sa);
 
        p2p_parse_free(&msg);
 
index 09abdbb..bcd924c 100644 (file)
@@ -1636,7 +1636,7 @@ skip_rsn:
                                           MACSTR " (terminate previously "
                                           "initiated negotiation",
                                           MAC2STR(src_addr));
-                               wpa_tdls_peer_free(sm, peer);
+                               wpa_tdls_disable_link(sm, peer->addr);
                        }
                }
        }
index 2df060c..4b08a62 100644 (file)
@@ -788,9 +788,12 @@ int wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, const u8 *ies,
        if (parse.ric) {
                wpa_hexdump(MSG_MSGDUMP, "FT: RIC Response",
                            parse.ric, parse.ric_len);
-               /* TODO: parse response and inform driver about results */
+               /* TODO: parse response and inform driver about results when
+                * using wpa_supplicant SME */
        }
 
+       wpa_printf(MSG_DEBUG, "FT: Completed successfully");
+
        return 0;
 }
 
index 741b442..3fb8fbe 100644 (file)
@@ -42,6 +42,9 @@
 /* Include faster sqr at the cost of about 0.5 kB in code */
 #define BN_FAST_S_MP_SQR_C
 
+/* About 0.25 kB of code, but ~1.7kB of stack space! */
+#define BN_FAST_S_MP_MUL_DIGS_C
+
 #else /* LTM_FAST */
 
 #define BN_MP_DIV_SMALL
@@ -139,7 +142,9 @@ static int s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs);
 static int s_mp_sqr(mp_int * a, mp_int * b);
 static int s_mp_mul_high_digs(mp_int * a, mp_int * b, mp_int * c, int digs);
 
+#ifdef BN_FAST_S_MP_MUL_DIGS_C
 static int fast_s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs);
+#endif
 
 #ifdef BN_MP_INIT_MULTI_C
 static int mp_init_multi(mp_int *mp, ...);
@@ -671,6 +676,9 @@ static int mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y)
 #ifdef BN_MP_EXPTMOD_FAST_C
   }
 #endif
+  if (dr == 0) {
+    /* avoid compiler warnings about possibly unused variable */
+  }
 }
 
 
@@ -2339,12 +2347,14 @@ static int s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs)
   mp_word r;
   mp_digit tmpx, *tmpt, *tmpy;
 
+#ifdef BN_FAST_S_MP_MUL_DIGS_C
   /* can we use the fast multiplier? */
   if (((digs) < MP_WARRAY) &&
       MIN (a->used, b->used) < 
           (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) {
     return fast_s_mp_mul_digs (a, b, c, digs);
   }
+#endif
 
   if ((res = mp_init_size (&t, digs)) != MP_OKAY) {
     return res;
@@ -2397,6 +2407,7 @@ static int s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs)
 }
 
 
+#ifdef BN_FAST_S_MP_MUL_DIGS_C
 /* Fast (comba) multiplier
  *
  * This is the fast column-array [comba] multiplier.  It is 
@@ -2482,6 +2493,7 @@ static int fast_s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs)
   mp_clamp (c);
   return MP_OKAY;
 }
+#endif /* BN_FAST_S_MP_MUL_DIGS_C */
 
 
 /* init an mp_init for a given size */
index 6860765..1ffe05e 100644 (file)
@@ -3019,6 +3019,7 @@ static const struct global_parse_data global_fields[] = {
        { INT(p2p_go_ht40), 0 },
        { INT(p2p_disabled), 0 },
        { INT(p2p_no_group_iface), 0 },
+       { INT_RANGE(p2p_ignore_shared_freq, 0, 1), 0 },
 #endif /* CONFIG_P2P */
        { FUNC(country), CFG_CHANGED_COUNTRY },
        { INT(bss_max_count), 0 },
index 2e3e76b..03fe6fc 100644 (file)
@@ -571,6 +571,7 @@ struct wpa_config {
        int p2p_intra_bss;
        unsigned int num_p2p_pref_chan;
        struct p2p_channel *p2p_pref_chan;
+       int p2p_ignore_shared_freq;
 
        struct wpabuf *wps_vendor_ext_m1;
 
index d636a67..a8c57eb 100644 (file)
@@ -2869,6 +2869,46 @@ static int ctrl_iface_get_capability_auth_alg(int res, char *strict,
 }
 
 
+static int ctrl_iface_get_capability_modes(int res, char *strict,
+                                          struct wpa_driver_capa *capa,
+                                          char *buf, size_t buflen)
+{
+       int ret, first = 1;
+       char *pos, *end;
+       size_t len;
+
+       pos = buf;
+       end = pos + buflen;
+
+       if (res < 0) {
+               if (strict)
+                       return 0;
+               len = os_strlcpy(buf, "IBSS AP", buflen);
+               if (len >= buflen)
+                       return -1;
+               return len;
+       }
+
+       if (capa->flags & WPA_DRIVER_FLAGS_IBSS) {
+               ret = os_snprintf(pos, end - pos, "%sIBSS", first ? "" : " ");
+               if (ret < 0 || ret >= end - pos)
+                       return pos - buf;
+               pos += ret;
+               first = 0;
+       }
+
+       if (capa->flags & WPA_DRIVER_FLAGS_AP) {
+               ret = os_snprintf(pos, end - pos, "%sAP", first ? "" : " ");
+               if (ret < 0 || ret >= end - pos)
+                       return pos - buf;
+               pos += ret;
+               first = 0;
+       }
+
+       return pos - buf;
+}
+
+
 static int ctrl_iface_get_capability_channels(struct wpa_supplicant *wpa_s,
                                              char *buf, size_t buflen)
 {
@@ -2969,6 +3009,10 @@ static int wpa_supplicant_ctrl_iface_get_capability(
                return ctrl_iface_get_capability_auth_alg(res, strict, &capa,
                                                          buf, buflen);
 
+       if (os_strcmp(field, "modes") == 0)
+               return ctrl_iface_get_capability_modes(res, strict, &capa,
+                                                      buf, buflen);
+
        if (os_strcmp(field, "channels") == 0)
                return ctrl_iface_get_capability_channels(wpa_s, buf, buflen);
 
index 5b4a0a4..136dd1a 100644 (file)
@@ -2430,6 +2430,7 @@ static const struct wpa_dbus_method_desc wpas_dbus_interface_methods[] = {
                  END_ARGS
          }
        },
+#ifndef CONFIG_NO_CONFIG_BLOBS
        { "AddBlob", WPAS_DBUS_NEW_IFACE_INTERFACE,
          (WPADBusMethodHandler) &wpas_dbus_handler_add_blob,
          {
@@ -2453,6 +2454,7 @@ static const struct wpa_dbus_method_desc wpas_dbus_interface_methods[] = {
                  END_ARGS
          }
        },
+#endif /* CONFIG_NO_CONFIG_BLOBS */
 #ifdef CONFIG_WPS
        { "Start", WPAS_DBUS_NEW_IFACE_WPS,
          (WPADBusMethodHandler) &wpas_dbus_handler_wps_start,
index 8088755..335c25f 100644 (file)
@@ -1696,6 +1696,8 @@ out:
 }
 
 
+#ifndef CONFIG_NO_CONFIG_BLOBS
+
 /**
  * wpas_dbus_handler_add_blob - Store named binary blob (ie, for certificates)
  * @message: Pointer to incoming dbus message
@@ -1860,6 +1862,9 @@ DBusMessage * wpas_dbus_handler_remove_blob(DBusMessage *message,
 
 }
 
+#endif /* CONFIG_NO_CONFIG_BLOBS */
+
+
 /*
  * wpas_dbus_handler_flush_bss - Flush the BSS cache
  * @message: Pointer to incoming dbus message
index 5f298e7..85d8a78 100644 (file)
@@ -268,10 +268,12 @@ static DBusHandlerResult wpas_iface_message_handler(DBusConnection *connection,
                        reply = wpas_dbus_iface_get_state(message, wpa_s);
                else if (!strcmp(method, "scanning"))
                        reply = wpas_dbus_iface_get_scanning(message, wpa_s);
+#ifndef CONFIG_NO_CONFIG_BLOBS
                else if (!strcmp(method, "setBlobs"))
                        reply = wpas_dbus_iface_set_blobs(message, wpa_s);
                else if (!strcmp(method, "removeBlobs"))
                        reply = wpas_dbus_iface_remove_blobs(message, wpa_s);
+#endif /* CONFIG_NO_CONFIG_BLOBS */
 #ifdef CONFIG_WPS
                else if (!os_strcmp(method, "wpsPbc"))
                        reply = wpas_dbus_iface_wps_pbc(message, wpa_s);
index 68e5515..e565de9 100644 (file)
@@ -1300,6 +1300,8 @@ DBusMessage * wpas_dbus_iface_get_scanning(DBusMessage *message,
 }
 
 
+#ifndef CONFIG_NO_CONFIG_BLOBS
+
 /**
  * wpas_dbus_iface_set_blobs - Store named binary blobs (ie, for certificates)
  * @message: Pointer to incoming dbus message
@@ -1429,6 +1431,8 @@ DBusMessage * wpas_dbus_iface_remove_blobs(DBusMessage *message,
        return wpas_dbus_new_success_reply(message);
 }
 
+#endif /* CONFIG_NO_CONFIG_BLOBS */
+
 
 /**
  * wpas_dbus_iface_flush - Clear BSS of old or all inactive entries
index 871e99c..6b0b6f9 100644 (file)
@@ -1477,6 +1477,9 @@ static int wpa_supplicant_event_associnfo(struct wpa_supplicant *wpa_s,
 {
        int l, len, found = 0, wpa_found, rsn_found;
        const u8 *p;
+#ifdef CONFIG_IEEE80211R
+       u8 bssid[ETH_ALEN];
+#endif /* CONFIG_IEEE80211R */
 
        wpa_dbg(wpa_s, MSG_DEBUG, "Association info event");
        if (data->assoc_info.req_ies)
@@ -1531,7 +1534,6 @@ static int wpa_supplicant_event_associnfo(struct wpa_supplicant *wpa_s,
 #ifdef CONFIG_IEEE80211R
 #ifdef CONFIG_SME
        if (wpa_s->sme.auth_alg == WPA_AUTH_ALG_FT) {
-               u8 bssid[ETH_ALEN];
                if (wpa_drv_get_bssid(wpa_s, bssid) < 0 ||
                    wpa_ft_validate_reassoc_resp(wpa_s->wpa,
                                                 data->assoc_info.resp_ies,
@@ -1589,6 +1591,23 @@ static int wpa_supplicant_event_associnfo(struct wpa_supplicant *wpa_s,
        }
 #endif /* CONFIG_SME */
 
+       /* Process FT when SME is in the driver */
+       if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
+           wpa_ft_is_completed(wpa_s->wpa)) {
+               if (wpa_drv_get_bssid(wpa_s, bssid) < 0 ||
+                   wpa_ft_validate_reassoc_resp(wpa_s->wpa,
+                                                data->assoc_info.resp_ies,
+                                                data->assoc_info.resp_ies_len,
+                                                bssid) < 0) {
+                       wpa_dbg(wpa_s, MSG_DEBUG, "FT: Validation of "
+                               "Reassociation Response failed");
+                       wpa_supplicant_deauthenticate(
+                               wpa_s, WLAN_REASON_INVALID_IE);
+                       return -1;
+               }
+               wpa_dbg(wpa_s, MSG_DEBUG, "FT: Reassociation Response done");
+       }
+
        wpa_sm_set_ft_params(wpa_s->wpa, data->assoc_info.resp_ies,
                             data->assoc_info.resp_ies_len);
 #endif /* CONFIG_IEEE80211R */
index 9a6da5f..86473cd 100755 (executable)
@@ -20,7 +20,7 @@ import nfc.handover
 import logging
 logging.basicConfig()
 
-import wpactrl
+import wpaspy
 
 wpas_ctrl = '/var/run/wpa_supplicant'
 
@@ -39,10 +39,9 @@ def wpas_connect():
 
     for ctrl in ifaces:
         try:
-            wpas = wpactrl.WPACtrl(ctrl)
+            wpas = wpaspy.Ctrl(ctrl)
             return wpas
-        except wpactrl.error, error:
-            print "Error: ", error
+        except Exception, e:
             pass
     return None
 
index db7cd6e..6246dc0 100644 (file)
@@ -100,6 +100,19 @@ static void wpas_p2p_fallback_to_go_neg(struct wpa_supplicant *wpa_s,
 static int wpas_p2p_stop_find_oper(struct wpa_supplicant *wpa_s);
 
 
+static void wpas_p2p_set_own_freq_preference(struct wpa_supplicant *wpa_s,
+                                            int freq)
+{
+       if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
+               return;
+       if (freq > 0 &&
+           (wpa_s->drv_flags & WPA_DRIVER_FLAGS_MULTI_CHANNEL_CONCURRENT) &&
+           wpa_s->parent->conf->p2p_ignore_shared_freq)
+               freq = 0;
+       p2p_set_own_freq_preference(wpa_s->global->p2p, freq);
+}
+
+
 static void wpas_p2p_scan_res_handler(struct wpa_supplicant *wpa_s,
                                      struct wpa_scan_results *scan_res)
 {
@@ -2471,11 +2484,14 @@ static u8 wpas_invitation_process(void *ctx, const u8 *sa, const u8 *bssid,
        }
 
 accept_inv:
+       wpas_p2p_set_own_freq_preference(wpa_s, 0);
+
        if (wpa_s->current_ssid && wpa_drv_get_bssid(wpa_s, cur_bssid) == 0 &&
            wpa_s->assoc_freq) {
                wpa_printf(MSG_DEBUG, "P2P: Trying to force channel to match "
                           "the channel we are already using");
                *force_freq = wpa_s->assoc_freq;
+               wpas_p2p_set_own_freq_preference(wpa_s, wpa_s->assoc_freq);
        }
 
        res = wpa_drv_shared_freq(wpa_s);
@@ -2484,6 +2500,7 @@ accept_inv:
                           "with the channel we are already using on a "
                           "shared interface");
                *force_freq = res;
+               wpas_p2p_set_own_freq_preference(wpa_s, res);
        }
 
        return P2P_SC_SUCCESS;
@@ -2554,8 +2571,68 @@ static void wpas_invitation_received(void *ctx, const u8 *sa, const u8 *bssid,
 }
 
 
+static void wpas_remove_persistent_peer(struct wpa_supplicant *wpa_s,
+                                       struct wpa_ssid *ssid,
+                                       const u8 *peer)
+{
+       size_t i;
+
+       if (ssid == NULL)
+               return;
+
+       for (i = 0; ssid->p2p_client_list && i < ssid->num_p2p_clients; i++) {
+               if (os_memcmp(ssid->p2p_client_list + i * ETH_ALEN, peer,
+                             ETH_ALEN) == 0)
+                       break;
+       }
+       if (i >= ssid->num_p2p_clients) {
+               if (ssid->mode != WPAS_MODE_P2P_GO &&
+                   os_memcmp(ssid->bssid, peer, ETH_ALEN) == 0) {
+                       wpa_printf(MSG_DEBUG, "P2P: Remove persistent group %d "
+                                  "due to invitation result", ssid->id);
+                       wpas_notify_network_removed(wpa_s, ssid);
+                       wpa_config_remove_network(wpa_s->conf, ssid->id);
+                       return;
+               }
+               return; /* Peer not found in client list */
+       }
+
+       wpa_printf(MSG_DEBUG, "P2P: Remove peer " MACSTR " from persistent "
+                  "group %d client list due to invitation result",
+                  MAC2STR(peer), ssid->id);
+       os_memmove(ssid->p2p_client_list + i * ETH_ALEN,
+                  ssid->p2p_client_list + (i + 1) * ETH_ALEN,
+                  (ssid->num_p2p_clients - i - 1) * ETH_ALEN);
+       ssid->num_p2p_clients--;
+#ifndef CONFIG_NO_CONFIG_WRITE
+       if (wpa_s->parent->conf->update_config &&
+           wpa_config_write(wpa_s->parent->confname, wpa_s->parent->conf))
+               wpa_printf(MSG_DEBUG, "P2P: Failed to update configuration");
+#endif /* CONFIG_NO_CONFIG_WRITE */
+}
+
+
+static void wpas_remove_persistent_client(struct wpa_supplicant *wpa_s,
+                                         const u8 *peer)
+{
+       struct wpa_ssid *ssid;
+
+       wpa_s = wpa_s->global->p2p_invite_group;
+       if (wpa_s == NULL)
+               return; /* No known invitation group */
+       ssid = wpa_s->current_ssid;
+       if (ssid == NULL || ssid->mode != WPAS_MODE_P2P_GO ||
+           !ssid->p2p_persistent_group)
+               return; /* Not operating as a GO in persistent group */
+       ssid = wpas_p2p_get_persistent(wpa_s->parent, peer,
+                                      ssid->ssid, ssid->ssid_len);
+       wpas_remove_persistent_peer(wpa_s, ssid, peer);
+}
+
+
 static void wpas_invitation_result(void *ctx, int status, const u8 *bssid,
-                                  const struct p2p_channels *channels)
+                                  const struct p2p_channels *channels,
+                                  const u8 *peer)
 {
        struct wpa_supplicant *wpa_s = ctx;
        struct wpa_ssid *ssid;
@@ -2570,8 +2647,13 @@ static void wpas_invitation_result(void *ctx, int status, const u8 *bssid,
        }
        wpas_notify_p2p_invitation_result(wpa_s, status, bssid);
 
-       if (wpa_s->pending_invite_ssid_id == -1)
+       wpa_printf(MSG_DEBUG, "P2P: Invitation result - status=%d peer=" MACSTR,
+                  status, MAC2STR(peer));
+       if (wpa_s->pending_invite_ssid_id == -1) {
+               if (status == P2P_SC_FAIL_UNKNOWN_GROUP)
+                       wpas_remove_persistent_client(wpa_s, peer);
                return; /* Invitation to active group */
+       }
 
        if (status == P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE) {
                wpa_printf(MSG_DEBUG, "P2P: Waiting for peer to start another "
@@ -2580,6 +2662,11 @@ static void wpas_invitation_result(void *ctx, int status, const u8 *bssid,
        }
 
        if (status != P2P_SC_SUCCESS) {
+               if (status == P2P_SC_FAIL_UNKNOWN_GROUP) {
+                       ssid = wpa_config_get_network(
+                               wpa_s->conf, wpa_s->pending_invite_ssid_id);
+                       wpas_remove_persistent_peer(wpa_s, ssid, peer);
+               }
                wpas_p2p_remove_pending_group_interface(wpa_s);
                return;
        }
@@ -3824,6 +3911,7 @@ int wpas_p2p_connect(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
                                   &oper_freq);
        if (res)
                return res;
+       wpas_p2p_set_own_freq_preference(wpa_s, oper_freq);
 
        wpa_s->create_p2p_iface = wpas_p2p_create_iface(wpa_s);
 
@@ -4056,18 +4144,45 @@ static int wpas_p2p_init_go_params(struct wpa_supplicant *wpa_s,
 
        if (wpa_s->current_ssid && wpa_drv_get_bssid(wpa_s, bssid) == 0 &&
            wpa_s->assoc_freq && !freq) {
-               wpa_printf(MSG_DEBUG, "P2P: Force GO on the channel we are "
-                          "already using");
-               params->freq = wpa_s->assoc_freq;
-               if (!freq_included(channels, params->freq)) {
-                       wpa_printf(MSG_DEBUG, "P2P: Forced GO freq %d MHz not "
-                                  "accepted", params->freq);
-                       return -1;
+               if (!p2p_supported_freq(wpa_s->global->p2p, wpa_s->assoc_freq)
+                   || !freq_included(channels, wpa_s->assoc_freq)) {
+                       if (wpa_s->drv_flags &
+                           WPA_DRIVER_FLAGS_MULTI_CHANNEL_CONCURRENT) {
+                               wpa_printf(MSG_DEBUG, "P2P: Cannot force GO on "
+                                          "the channel we are already using "
+                                          "(%u MHz) - allow multi-channel "
+                                          "concurrency", wpa_s->assoc_freq);
+                       } else {
+                               wpa_printf(MSG_DEBUG, "P2P: Cannot force GO on "
+                                          "the channel we are already using "
+                                          "(%u MHz)", wpa_s->assoc_freq);
+                               return -1;
+                       }
+               } else {
+                       wpa_printf(MSG_DEBUG, "P2P: Force GO on the channel we "
+                                  "are already using (%u MHz)",
+                                  wpa_s->assoc_freq);
+                       params->freq = wpa_s->assoc_freq;
                }
        }
 
        res = wpa_drv_shared_freq(wpa_s);
-       if (res > 0 && !freq) {
+       if (res > 0 && !freq &&
+           (!p2p_supported_freq(wpa_s->global->p2p, res) ||
+            !freq_included(channels, res))) {
+               if (wpa_s->drv_flags &
+                   WPA_DRIVER_FLAGS_MULTI_CHANNEL_CONCURRENT) {
+                       wpa_printf(MSG_DEBUG, "P2P: Cannot force GO on the "
+                                  "channel we are already using on a shared "
+                                  "interface (%u MHz) - allow multi-channel "
+                                  "concurrency", res);
+               } else {
+                       wpa_printf(MSG_DEBUG, "P2P: Cannot force GO on the "
+                                  "channel we are already using on a shared "
+                                  "interface (%u MHz)", res);
+                       return -1;
+               }
+       } else if (res > 0 && !freq) {
                wpa_printf(MSG_DEBUG, "P2P: Force GO on the channel we are "
                           "already using on a shared interface");
                params->freq = res;
@@ -4730,6 +4845,7 @@ int wpas_p2p_invite(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
        int force_freq = 0, oper_freq = 0;
        int res;
 
+       wpa_s->global->p2p_invite_group = NULL;
        if (peer_addr)
                os_memcpy(wpa_s->p2p_auth_invite, peer_addr, ETH_ALEN);
        else
@@ -4822,6 +4938,7 @@ int wpas_p2p_invite_group(struct wpa_supplicant *wpa_s, const char *ifname,
                return -1;
        }
 
+       wpa_s->global->p2p_invite_group = wpa_s;
        persistent = ssid->p2p_persistent_group &&
                wpas_p2p_get_persistent(wpa_s->parent, peer_addr,
                                        ssid->ssid, ssid->ssid_len);
@@ -4868,6 +4985,7 @@ int wpas_p2p_invite_group(struct wpa_supplicant *wpa_s, const char *ifname,
                                   &oper_freq);
        if (res)
                return res;
+       wpas_p2p_set_own_freq_preference(wpa_s, oper_freq);
 
        return p2p_invite(wpa_s->global->p2p, peer_addr, role, bssid,
                          ssid->ssid, ssid->ssid_len, force_freq,
index 662a131..90e4169 100644 (file)
@@ -2483,7 +2483,7 @@ static struct wpa_cli_cmd wpa_cli_commands[] = {
          "<<idx> | <bssid>> = get detailed scan result info" },
        { "get_capability", wpa_cli_cmd_get_capability, NULL,
          cli_cmd_flag_none,
-         "<eap/pairwise/group/key_mgmt/proto/auth_alg/channels> "
+         "<eap/pairwise/group/key_mgmt/proto/auth_alg/channels/modes> "
          "= get capabilies" },
        { "reconfigure", wpa_cli_cmd_reconfigure, NULL,
          cli_cmd_flag_none,
index 7d50e4d..7a93716 100644 (file)
@@ -661,8 +661,8 @@ void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s,
                wpa_supplicant_notify_scanning(wpa_s, 0);
 
        if (state == WPA_COMPLETED && wpa_s->new_connection) {
-#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
                struct wpa_ssid *ssid = wpa_s->current_ssid;
+#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
                wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_CONNECTED "- Connection to "
                        MACSTR " completed (auth) [id=%d id_str=%s]",
                        MAC2STR(wpa_s->bssid),
@@ -1361,8 +1361,7 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
                                     ssid->proactive_key_caching) &&
                        (ssid->proto & WPA_PROTO_RSN);
                if (pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid,
-                                           wpa_s->current_ssid,
-                                           try_opportunistic) == 0)
+                                           ssid, try_opportunistic) == 0)
                        eapol_sm_notify_pmkid_attempt(wpa_s->eapol, 1);
                wpa_ie_len = sizeof(wpa_ie);
                if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
@@ -3146,6 +3145,8 @@ int wpa_supplicant_remove_iface(struct wpa_global *global,
 
        if (global->p2p_group_formation == wpa_s)
                global->p2p_group_formation = NULL;
+       if (global->p2p_invite_group == wpa_s)
+               global->p2p_invite_group = NULL;
        wpa_supplicant_deinit_iface(wpa_s, 1, terminate);
        os_free(wpa_s);
 
index 4ec15c1..5465c4f 100644 (file)
@@ -228,6 +228,7 @@ struct wpa_global {
        struct p2p_data *p2p;
        struct wpa_supplicant *p2p_init_wpa_s;
        struct wpa_supplicant *p2p_group_formation;
+       struct wpa_supplicant *p2p_invite_group;
        u8 p2p_dev_addr[ETH_ALEN];
        struct dl_list p2p_srv_bonjour; /* struct p2p_srv_bonjour */
        struct dl_list p2p_srv_upnp; /* struct p2p_srv_upnp */
index 7585b86..cd51873 100644 (file)
@@ -798,8 +798,10 @@ int wpa_supplicant_init_eapol(struct wpa_supplicant *wpa_s)
        ctx->eapol_done_cb = wpa_supplicant_notify_eapol_done;
        ctx->eapol_send = wpa_supplicant_eapol_send;
        ctx->set_wep_key = wpa_eapol_set_wep_key;
+#ifndef CONFIG_NO_CONFIG_BLOBS
        ctx->set_config_blob = wpa_supplicant_set_config_blob;
        ctx->get_config_blob = wpa_supplicant_get_config_blob;
+#endif /* CONFIG_NO_CONFIG_BLOBS */
        ctx->aborted_cached = wpa_supplicant_aborted_cached;
        ctx->opensc_engine_path = wpa_s->conf->opensc_engine_path;
        ctx->pkcs11_engine_path = wpa_s->conf->pkcs11_engine_path;
index 509a7c0..1b1b5f7 100644 (file)
@@ -2007,6 +2007,7 @@ struct wpabuf * wpas_wps_nfc_handover_req(struct wpa_supplicant *wpa_s, int cr)
 struct wpabuf * wpas_wps_er_nfc_handover_sel(struct wpa_supplicant *wpa_s,
                                             int ndef, const char *uuid)
 {
+#ifdef CONFIG_WPS_ER
        struct wpabuf *ret;
        u8 u[UUID_LEN];
 
@@ -2031,6 +2032,9 @@ struct wpabuf * wpas_wps_er_nfc_handover_sel(struct wpa_supplicant *wpa_s,
        }
 
        return ret;
+#else /* CONFIG_WPS_ER */
+       return NULL;
+#endif /* CONFIG_WPS_ER */
 }
 #endif /* CONFIG_WPS_NFC */