OSDN Git Service

wpa_supplicant: P2P-related fixes
authorDmitry Shmidt <dimitrysh@google.com>
Mon, 24 Sep 2012 17:35:31 +0000 (10:35 -0700)
committerDmitry Shmidt <dimitrysh@google.com>
Mon, 24 Sep 2012 17:35:31 +0000 (10:35 -0700)
- Remove unused function warning in WPS-NFC case
- P2P: Fix p2p_ctrl_invite_persistent to parse peer parameter
- hostapd: Fix CONFIG_INTERWORKING=y build without CONFIG_HS20=y
- hostapd: Fix WDS VLAN bridge handling
- hostapd: Send EAPOL frames from the VO queue if WMM is active
- P2P: Remove channel 14 from supported P2P channels
- hostapd: Clear WLAN_STA_ASSOC_REQ_OK if sending the assoc response failed
- hostapd: Add check for the wds sta flag before creating 4addr VLANs
- nl80211: Use the monitor interface if socket tx status is not supported
- wpa_supplicant: Set state to DISCONNECTED on AP creation errors
- P2P: Fix p2p_group_idle in no-group-interface P2P client case
- P2P: Fix PSK configuration for GO network
- Print control interface commands in easier format
- Add debug print for no enabled networks case
- P2P: Add more debug prints for GO start routines
- P2P: Fix pending sta scan processing for concurrent operation cases

BUG: 6940646
Change-Id: I1b1c54a08c61ec4af2bfd2274afc93501004eea2

Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
src/ap/gas_serv.c
src/ap/ieee802_11.c
src/drivers/driver_nl80211.c
wpa_supplicant/ctrl_iface.c
wpa_supplicant/events.c
wpa_supplicant/p2p_supplicant.c
wpa_supplicant/scan.c
wpa_supplicant/wpa_supplicant.c
wpa_supplicant/wps_supplicant.c

index 53e6cbb..851c183 100644 (file)
@@ -128,6 +128,7 @@ static void gas_serv_free_dialogs(struct hostapd_data *hapd,
 }
 
 
+#ifdef CONFIG_HS20
 static void anqp_add_hs_capab_list(struct hostapd_data *hapd,
                                   struct wpabuf *buf)
 {
@@ -151,6 +152,7 @@ static void anqp_add_hs_capab_list(struct hostapd_data *hapd,
                wpabuf_put_u8(buf, HS20_STYPE_OPERATING_CLASS);
        gas_anqp_set_element_len(buf, len);
 }
+#endif /* CONFIG_HS20 */
 
 
 static void anqp_add_capab_list(struct hostapd_data *hapd,
@@ -174,7 +176,9 @@ static void anqp_add_capab_list(struct hostapd_data *hapd,
                wpabuf_put_le16(buf, ANQP_3GPP_CELLULAR_NETWORK);
        if (hapd->conf->domain_name)
                wpabuf_put_le16(buf, ANQP_DOMAIN_NAME);
+#ifdef CONFIG_HS20
        anqp_add_hs_capab_list(hapd, buf);
+#endif /* CONFIG_HS20 */
        gas_anqp_set_element_len(buf, len);
 }
 
@@ -429,6 +433,8 @@ static void anqp_add_domain_name(struct hostapd_data *hapd, struct wpabuf *buf)
 }
 
 
+#ifdef CONFIG_HS20
+
 static void anqp_add_operator_friendly_name(struct hostapd_data *hapd,
                                            struct wpabuf *buf)
 {
@@ -499,6 +505,8 @@ static void anqp_add_operating_class(struct hostapd_data *hapd,
        }
 }
 
+#endif /* CONFIG_HS20 */
+
 
 static struct wpabuf *
 gas_serv_build_gas_resp_payload(struct hostapd_data *hapd,
@@ -531,6 +539,7 @@ gas_serv_build_gas_resp_payload(struct hostapd_data *hapd,
        if (request & ANQP_REQ_DOMAIN_NAME)
                anqp_add_domain_name(hapd, buf);
 
+#ifdef CONFIG_HS20
        if (request & ANQP_REQ_HS_CAPABILITY_LIST)
                anqp_add_hs_capab_list(hapd, buf);
        if (request & ANQP_REQ_OPERATOR_FRIENDLY_NAME)
@@ -541,6 +550,7 @@ gas_serv_build_gas_resp_payload(struct hostapd_data *hapd,
                anqp_add_connection_capability(hapd, buf);
        if (request & ANQP_REQ_OPERATING_CLASS)
                anqp_add_operating_class(hapd, buf);
+#endif /* CONFIG_HS20 */
 
        return buf;
 }
@@ -649,6 +659,8 @@ static void rx_anqp_query_list(struct hostapd_data *hapd,
 }
 
 
+#ifdef CONFIG_HS20
+
 static void rx_anqp_hs_query_list(struct hostapd_data *hapd, u8 subtype,
                                  struct anqp_query_info *qi)
 {
@@ -755,6 +767,8 @@ static void rx_anqp_vendor_specific(struct hostapd_data *hapd,
        }
 }
 
+#endif /* CONFIG_HS20 */
+
 
 static void gas_serv_req_local_processing(struct hostapd_data *hapd,
                                          const u8 *sa, u8 dialog_token,
@@ -899,9 +913,11 @@ static void gas_serv_rx_gas_initial_req(struct hostapd_data *hapd,
                case ANQP_QUERY_LIST:
                        rx_anqp_query_list(hapd, pos, pos + elen, &qi);
                        break;
+#ifdef CONFIG_HS20
                case ANQP_VENDOR_SPECIFIC:
                        rx_anqp_vendor_specific(hapd, pos, pos + elen, &qi);
                        break;
+#endif /* CONFIG_HS20 */
                default:
                        wpa_printf(MSG_DEBUG, "ANQP: Unsupported Query "
                                   "Request element %u", info_id);
index 211ee1b..ce20e5f 100644 (file)
@@ -1506,13 +1506,6 @@ static void handle_assoc_cb(struct hostapd_data *hapd,
        int new_assoc = 1;
        struct ieee80211_ht_capabilities ht_cap;
 
-       if (!ok) {
-               hostapd_logger(hapd, mgmt->da, HOSTAPD_MODULE_IEEE80211,
-                              HOSTAPD_LEVEL_DEBUG,
-                              "did not acknowledge association response");
-               return;
-       }
-
        if (len < IEEE80211_HDRLEN + (reassoc ? sizeof(mgmt->u.reassoc_resp) :
                                      sizeof(mgmt->u.assoc_resp))) {
                printf("handle_assoc_cb(reassoc=%d) - too short payload "
@@ -1520,11 +1513,6 @@ static void handle_assoc_cb(struct hostapd_data *hapd,
                return;
        }
 
-       if (reassoc)
-               status = le_to_host16(mgmt->u.reassoc_resp.status_code);
-       else
-               status = le_to_host16(mgmt->u.assoc_resp.status_code);
-
        sta = ap_get_sta(hapd, mgmt->da);
        if (!sta) {
                printf("handle_assoc_cb: STA " MACSTR " not found\n",
@@ -1532,6 +1520,19 @@ static void handle_assoc_cb(struct hostapd_data *hapd,
                return;
        }
 
+       if (!ok) {
+               hostapd_logger(hapd, mgmt->da, HOSTAPD_MODULE_IEEE80211,
+                              HOSTAPD_LEVEL_DEBUG,
+                              "did not acknowledge association response");
+               sta->flags &= ~WLAN_STA_ASSOC_REQ_OK;
+               return;
+       }
+
+       if (reassoc)
+               status = le_to_host16(mgmt->u.reassoc_resp.status_code);
+       else
+               status = le_to_host16(mgmt->u.assoc_resp.status_code);
+
        if (status != WLAN_STATUS_SUCCESS)
                goto fail;
 
@@ -1830,6 +1831,9 @@ void ieee802_11_rx_from_unknown(struct hostapd_data *hapd, const u8 *src,
 
        sta = ap_get_sta(hapd, src);
        if (sta && (sta->flags & WLAN_STA_ASSOC)) {
+               if (!hapd->conf->wds_sta)
+                       return;
+
                if (wds && !(sta->flags & WLAN_STA_WDS)) {
                        wpa_printf(MSG_DEBUG, "Enable 4-address WDS mode for "
                                   "STA " MACSTR " (aid %u)",
index a9e6139..4574938 100644 (file)
@@ -2678,10 +2678,10 @@ static int wpa_driver_nl80211_capa(struct wpa_driver_nl80211_data *drv)
        }
 #else
        /*
-        * If poll command is supported mac80211 is new enough to
-        * have everything we need to not need monitor interfaces.
+        * If poll command and tx status are supported, mac80211 is new enough
+        * to have everything we need to not need monitor interfaces.
         */
-       drv->use_monitor = !info.poll_command_supported;
+       drv->use_monitor = !info.poll_command_supported || !info.data_tx_status;
 #endif
 
        if (drv->device_ap_sme && drv->use_monitor) {
@@ -6423,8 +6423,8 @@ static int wpa_driver_nl80211_hapd_send_eapol(
        pos = (u8 *) (hdr + 1);
 
        if (qos) {
-               /* add an empty QoS header if needed */
-               pos[0] = 0;
+               /* Set highest priority in QoS header */
+               pos[0] = 7;
                pos[1] = 0;
                pos += 2;
        }
@@ -7729,6 +7729,10 @@ static int i802_set_wds_sta(void *priv, const u8 *addr, int aid, int val,
                }
                return i802_set_sta_vlan(priv, addr, name, 0);
        } else {
+               if (bridge_ifname)
+                       linux_br_del_if(drv->global->ioctl_sock, bridge_ifname,
+                                       name);
+
                i802_set_sta_vlan(priv, addr, bss->ifname, 0);
                return wpa_driver_nl80211_if_remove(priv, WPA_IF_AP_VLAN,
                                                    name);
@@ -8096,7 +8100,12 @@ static int wpa_driver_nl80211_if_remove(void *priv,
        if (ifindex <= 0)
                return -1;
 
+       nl80211_remove_iface(drv, ifindex);
+
 #ifdef HOSTAPD
+       if (type != WPA_IF_AP_BSS)
+               return 0;
+
        if (bss->added_if_into_bridge) {
                if (linux_br_del_if(drv->global->ioctl_sock, bss->brname,
                                    bss->ifname) < 0)
@@ -8110,13 +8119,6 @@ static int wpa_driver_nl80211_if_remove(void *priv,
                                   "bridge %s: %s",
                                   bss->brname, strerror(errno));
        }
-#endif /* HOSTAPD */
-
-       nl80211_remove_iface(drv, ifindex);
-
-#ifdef HOSTAPD
-       if (type != WPA_IF_AP_BSS)
-               return 0;
 
        if (bss != &drv->first_bss) {
                struct i802_bss *tbss;
index 0d8821b..bcf27be 100644 (file)
@@ -3547,11 +3547,18 @@ static int p2p_ctrl_invite_persistent(struct wpa_supplicant *wpa_s, char *cmd)
        char *pos;
        int id;
        struct wpa_ssid *ssid;
-       u8 peer[ETH_ALEN];
+       u8 *_peer = NULL, peer[ETH_ALEN];
        int freq = 0;
        int ht40;
 
        id = atoi(cmd);
+       pos = os_strstr(cmd, " peer=");
+       if (pos) {
+               pos += 6;
+               if (hwaddr_aton(pos, peer))
+                       return -1;
+               _peer = peer;
+       }
        ssid = wpa_config_get_network(wpa_s->conf, id);
        if (ssid == NULL || ssid->disabled != 2) {
                wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
@@ -3568,17 +3575,9 @@ static int p2p_ctrl_invite_persistent(struct wpa_supplicant *wpa_s, char *cmd)
                        return -1;
        }
 
-       pos = os_strstr(cmd, " peer=");
-       if (pos) {
-               pos += 6;
-               if (hwaddr_aton(pos, peer))
-                       return -1;
-       }
-
        ht40 = os_strstr(cmd, " ht40") != NULL;
 
-       return wpas_p2p_invite(wpa_s, pos ? peer : NULL, ssid, NULL, freq,
-                              ht40);
+       return wpas_p2p_invite(wpa_s, _peer, ssid, NULL, freq, ht40);
 }
 
 
@@ -4402,6 +4401,7 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
                        level = MSG_EXCESSIVE;
                wpa_hexdump_ascii(level, "RX ctrl_iface",
                                  (const u8 *) buf, os_strlen(buf));
+               wpa_dbg(wpa_s, level, "Control interface command '%s'", buf);
        }
 
        reply = os_malloc(reply_size);
index fdcbcc2..6e9d7ba 100644 (file)
@@ -854,7 +854,12 @@ static void wpa_supplicant_req_new_scan(struct wpa_supplicant *wpa_s,
                 * we don't wait timeout seconds before transitioning
                 * to INACTIVE state.
                 */
+               wpa_dbg(wpa_s, MSG_DEBUG, "Short-circuit new scan request "
+                       "since there are no enabled networks");
                wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
+#ifdef CONFIG_P2P
+               wpa_s->sta_scan_pending = 0;
+#endif /* CONFIG_P2P */
                return;
        }
        wpa_supplicant_req_scan(wpa_s, timeout_sec, timeout_usec);
@@ -1059,7 +1064,8 @@ static int _wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s,
 #ifdef CONFIG_P2P
        if (wpa_s->global->p2p_cb_on_scan_complete &&
            !wpa_s->global->p2p_disabled &&
-           wpa_s->global->p2p != NULL && !wpa_s->sta_scan_pending) {
+           wpa_s->global->p2p != NULL && !wpa_s->sta_scan_pending &&
+           !wpa_s->scan_res_handler) {
                wpa_s->global->p2p_cb_on_scan_complete = 0;
                if (p2p_other_scan_completed(wpa_s->global->p2p) == 1) {
                        wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Pending P2P operation "
index 903c94f..cf8f935 100644 (file)
@@ -267,13 +267,12 @@ static int wpas_p2p_group_delete(struct wpa_supplicant *wpa_s,
        if (ssid == NULL) {
                /*
                 * The current SSID was not known, but there may still be a
-                * pending P2P group interface waiting for provisioning.
+                * pending P2P group interface waiting for provisioning or a
+                * P2P group that is trying to reconnect.
                 */
                ssid = wpa_s->conf->ssid;
                while (ssid) {
-                       if (ssid->p2p_group &&
-                           (ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION ||
-                            (ssid->key_mgmt & WPA_KEY_MGMT_WPS)))
+                       if (ssid->p2p_group)
                                break;
                        ssid = ssid->next;
                }
@@ -873,12 +872,18 @@ static void wpas_start_wps_go(struct wpa_supplicant *wpa_s,
 {
        struct wpa_ssid *ssid;
 
-       if (wpas_copy_go_neg_results(wpa_s, params) < 0)
+       wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Starting GO");
+       if (wpas_copy_go_neg_results(wpa_s, params) < 0) {
+               wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Could not copy GO Negotiation "
+                       "results");
                return;
+       }
 
        ssid = wpa_config_add_network(wpa_s->conf);
-       if (ssid == NULL)
+       if (ssid == NULL) {
+               wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Could not add network for GO");
                return;
+       }
 
        wpa_s->show_group_started = 0;
 
@@ -900,6 +905,13 @@ static void wpas_start_wps_go(struct wpa_supplicant *wpa_s,
        ssid->proto = WPA_PROTO_RSN;
        ssid->pairwise_cipher = WPA_CIPHER_CCMP;
        ssid->passphrase = os_strdup(params->passphrase);
+       if (ssid->passphrase == NULL) {
+               wpa_msg(wpa_s, MSG_ERROR, "P2P: Failed to copy passphrase for "
+                       "GO");
+               wpa_config_remove_network(wpa_s->conf, ssid->id);
+               return;
+       }
+       wpa_config_update_psk(ssid);
        ssid->ap_max_inactivity = wpa_s->parent->conf->p2p_go_max_inactivity;
 
        wpa_s->ap_configured_cb = p2p_go_configured;
@@ -908,6 +920,8 @@ static void wpas_start_wps_go(struct wpa_supplicant *wpa_s,
        wpa_s->connect_without_scan = ssid;
        wpa_s->reassociate = 1;
        wpa_s->disconnected = 0;
+       wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Request scan (that will be skipped) to "
+               "start GO)");
        wpa_supplicant_req_scan(wpa_s, 0, 0);
 }
 
@@ -2517,7 +2531,6 @@ struct p2p_oper_class_map {
 
 static struct p2p_oper_class_map op_class[] = {
        { HOSTAPD_MODE_IEEE80211G, 81, 1, 13, 1, BW20 },
-       { HOSTAPD_MODE_IEEE80211G, 82, 14, 14, 1, BW20 },
 #if 0 /* Do not enable HT40 on 2 GHz for now */
        { HOSTAPD_MODE_IEEE80211G, 83, 1, 9, 1, BW40PLUS },
        { HOSTAPD_MODE_IEEE80211G, 84, 5, 13, 1, BW40MINUS },
@@ -3820,18 +3833,27 @@ wpas_p2p_get_group_iface(struct wpa_supplicant *wpa_s, int addr_allocated,
 {
        struct wpa_supplicant *group_wpa_s;
 
-       if (!wpas_p2p_create_iface(wpa_s))
+       if (!wpas_p2p_create_iface(wpa_s)) {
+               wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Use same interface for group "
+                       "operations");
                return wpa_s;
+       }
 
        if (wpas_p2p_add_group_interface(wpa_s, go ? WPA_IF_P2P_GO :
-                                        WPA_IF_P2P_CLIENT) < 0)
+                                        WPA_IF_P2P_CLIENT) < 0) {
+               wpa_msg(wpa_s, MSG_ERROR, "P2P: Failed to add group interface");
                return NULL;
+       }
        group_wpa_s = wpas_p2p_init_group_interface(wpa_s, go);
        if (group_wpa_s == NULL) {
+               wpa_msg(wpa_s, MSG_ERROR, "P2P: Failed to initialize group "
+                       "interface");
                wpas_p2p_remove_pending_group_interface(wpa_s);
                return NULL;
        }
 
+       wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Use separate group interface %s",
+               group_wpa_s->ifname);
        return group_wpa_s;
 }
 
index bf55f5e..0f6433b 100644 (file)
@@ -83,15 +83,21 @@ static int wpas_wps_in_use(struct wpa_supplicant *wpa_s,
 int wpa_supplicant_enabled_networks(struct wpa_supplicant *wpa_s)
 {
        struct wpa_ssid *ssid = wpa_s->conf->ssid;
-       int count = 0;
+       int count = 0, disabled = 0;
        while (ssid) {
                if (!wpas_network_disabled(wpa_s, ssid))
                        count++;
+               else
+                       disabled++;
                ssid = ssid->next;
        }
        if (wpa_s->conf->cred && wpa_s->conf->interworking &&
            wpa_s->conf->auto_interworking)
                count++;
+       if (count == 0 && disabled > 0) {
+               wpa_dbg(wpa_s, MSG_DEBUG, "No enabled networks (%d disabled "
+                       "networks)", disabled);
+       }
        return count;
 }
 
@@ -450,6 +456,7 @@ static void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx)
        }
 
        if (wpa_s->disconnected && !wpa_s->scan_req) {
+               wpa_dbg(wpa_s, MSG_DEBUG, "Disconnected - do not scan");
                wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
                return;
        }
@@ -464,6 +471,9 @@ static void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx)
            !wpa_s->scan_req) {
                wpa_dbg(wpa_s, MSG_DEBUG, "No enabled networks - do not scan");
                wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
+#ifdef CONFIG_P2P
+               wpa_s->sta_scan_pending = 0;
+#endif /* CONFIG_P2P */
                return;
        }
 
index 49830d6..d8f3c44 100644 (file)
@@ -1255,7 +1255,10 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
                                "mode");
                        return;
                }
-               wpa_supplicant_create_ap(wpa_s, ssid);
+               if (wpa_supplicant_create_ap(wpa_s, ssid) < 0) {
+                       wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
+                       return;
+               }
                wpa_s->current_bss = bss;
 #else /* CONFIG_AP */
                wpa_msg(wpa_s, MSG_ERROR, "AP mode support not included in "
index 130f3ab..915ca57 100644 (file)
@@ -1869,6 +1869,7 @@ static int wpas_wps_use_cred(struct wpa_supplicant *wpa_s,
 }
 
 
+#ifdef CONFIG_WPS_ER
 static int wpas_wps_add_nfc_password_token(struct wpa_supplicant *wpa_s,
                                           struct wps_parse_attr *attr)
 {
@@ -1876,6 +1877,7 @@ static int wpas_wps_add_nfc_password_token(struct wpa_supplicant *wpa_s,
                wpa_s->wps->registrar, attr->oob_dev_password,
                attr->oob_dev_password_len);
 }
+#endif /* CONFIG_WPS_ER */
 
 
 static int wpas_wps_nfc_tag_process(struct wpa_supplicant *wpa_s,