From 661b4f78e48c697429dc46154a4125892c001718 Mon Sep 17 00:00:00 2001 From: Dmitry Shmidt Date: Mon, 29 Sep 2014 14:58:27 -0700 Subject: Cumulative patch from commit a313d17de943cbaf12cbf67d666af14791be8ad2 a313d17 Extend random MAC address support to allow OUI to be kept 1cbdb9d Add helper function for generating random MAC addresses with same OUI 97ed9a0 nl80211: Remove bridge FDB entry upon sta_remove() 39323bc AP: hostapd_setup_bss() code clean-up 1595eb9 P2P: Add support for 60 GHz social channel b6ebdfb Extend STATUS command with frequency information 375f4a3 hostapd: Avoid dead code with P2P not enabled 6a60488 dbus: Add a global property to set or unset WFD IEs 4bd7e16 wifi_display: Add a utility function to set WFD subelements from IEs d417744 wifi_display: Add a utility function to get the sub-elements as IEs a8833b8 util: Don't use "\e" 8c6f4a5 ap_config.c: fix typo for "capabilities" 6e252b0 WPS: Fix WPS-in-search check when STA_AUTOCONNECT is disabled e5fdc05 P2P: Remove unecessary sanity check for global p2p ee285df P2P: Flush services based on global p2p init and not p2p ifaces 7139cf4 P2P: Decrement sd_pending_bcast_queries when sd returns success dbdc9a1 nl80211: Fix memory leak on start radar detection error path ed8e005 hostap: nl80211 use nl80211_put_freq_params c267753 Add support for using random local MAC address 4d8fb63 Add helper function for generating random MAC addresses fee354c nl80211: Add command for changing local MAC address e49cabc P2P: Set timeout when starting GO Negotiation from Probe Req RX 7549c17 P2P: Clear pending_listen_freq when starting GO Neg/Invite b497a21 nl80211: Ignore auth/assoc events when testing driver-SME 79e2b1c Add PMKSA_FLUSH ctrl_iface command 55c2bfa wpa_cli: Support action scripts with global ctrl_iface 063f850 wpa_cli: Increase event buffer size to 4096 bytes fa0e917 wpa_cli: Fix PING in interactive mode with ifname_prefix c53a9bf Check for driver's DFS offload capability before handling DFS 068e387 STA: Update scan results for ap_scan=1 skip-selection case also 7a4a93b dbus: Add SignalPoll() method to report current signal properties a6ab82d Android: Add NO_EVENTS parameter to status command df2508d P2P: Check os_get_random() return value more consistently 54461f3 RADIUS server: Remove unreachable code e4474c1 FT: Fix hostapd with driver-based SME to authorize the STA 0800f9e nl80211: Add roaming policy update using QCA vendor command 0ef023e Add support for driver command to update roaming policy 0cd9846 nl80211: Print debug info on STA flag changes 17e2091 P2P: Fix radio work issue with wait-for-peer GO Negotiation 76db5b6 Work around broken AP PMKSA caching implementation b08d5fa WPS: Set EAPOL workarounds dynamically based on association 8511a0f WPS: Extend internal entropy pool help for key/snonce derivation abc0553 Remove WPA_EVENT_SCAN_STARTED message from MSG_INFO log c45dabb P2P: Deauth p2p client just after dbus notify 3ee1856 nl80211: Register eloop after hs20 action frame 3bd3257 dbus: add BSS Age property to indicate last-seen time 5c61d21 openssl: Fix memory leak in openssl ec deinit 10e7948 Fix hostapd GET_CONFIG wpa_pairwise_cipher value 3a413e0 RADIUS client: Check getsockname() return value 9c196f7 HTTP: Fix OCSP status check cb5ef95 SME: Verify that os_get_random() succeeds for SA Query c9cd78e RADIUS server: Fix IPv6 radiusAuthClientAddress mask 5e62cfd P2P: Verify that os_get_random() succeeds 6473e80 EAP-PAX server: Add explicit CID length limit 6a6566c Remove unnecessarily shadowed local variable df756b3 hostapd: Remove unused variable assignment e47abdb TDLS: Decline Setup Request with status code 37 if BSSID does not match ce2002a TDLS: Add RSN and Timeout interval IEs in TDLS Discovery Response frame 1c2aa04 P2P: Do not add P2P IEs on P2P disabled interface f2e9083 nl80211: Add more RTM_NEWLINK/DELLINK debug messages 728ff2f nl80211: Fix RTM_DELLINK processing for bridge events e5a4b85 WPS: Merge mixed-WPA/WPA2 credentials if received in same session db9418b Add printf NULL checks to silence static analyzer 4e53675 P2P: Overwrite pending interface only after verifying BSS entry 04a258e hostapd: Check that EVENT_ASSOC data is present before using it 1cc0d6a wpa_supplicant: Use freq_list scan filtar in sched_scan Change-Id: Ibc18f6761b3ccfe8fb4479f26f53e70942068bc8 Signed-off-by: Dmitry Shmidt --- src/ap/ap_config.c | 2 +- src/ap/beacon.c | 4 + src/ap/drv_callbacks.c | 7 + src/ap/hostapd.c | 62 ++++----- src/ap/sta_info.c | 2 +- src/common/qca-vendor.h | 20 ++- src/crypto/crypto_openssl.c | 1 + src/drivers/driver.h | 27 ++++ src/drivers/driver_common.c | 21 +++ src/drivers/driver_nl80211.c | 286 ++++++++++++++++++++++++++++++++-------- src/drivers/drivers.mak | 4 + src/drivers/drivers.mk | 4 + src/eap_server/eap_server_pax.c | 9 +- src/eapol_supp/eapol_supp_sm.c | 17 ++- src/eapol_supp/eapol_supp_sm.h | 5 + src/p2p/p2p.c | 46 ++++++- src/p2p/p2p.h | 14 ++ src/p2p/p2p_go_neg.c | 5 +- src/p2p/p2p_sd.c | 10 -- src/p2p/p2p_utils.c | 23 +++- src/radius/radius_client.c | 22 ++-- src/radius/radius_server.c | 4 +- src/rsn_supp/tdls.c | 80 ++++++++++- src/utils/common.c | 24 +++- src/utils/common.h | 3 + src/utils/http_curl.c | 4 +- src/wps/wps_enrollee.c | 12 +- src/wps/wps_registrar.c | 11 +- 28 files changed, 594 insertions(+), 135 deletions(-) (limited to 'src') diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c index d1275509..c7da69e0 100644 --- a/src/ap/ap_config.c +++ b/src/ap/ap_config.c @@ -761,7 +761,7 @@ static int hostapd_config_check_bss(struct hostapd_bss_config *bss, conf->hw_mode == HOSTAPD_MODE_IEEE80211B) { bss->disable_11n = 1; wpa_printf(MSG_ERROR, "HT (IEEE 802.11n) in 11b mode is not " - "allowed, disabling HT capabilites"); + "allowed, disabling HT capabilities"); } if (full_config && conf->ieee80211n && diff --git a/src/ap/beacon.c b/src/ap/beacon.c index b3b61498..4cae0d99 100644 --- a/src/ap/beacon.c +++ b/src/ap/beacon.c @@ -113,6 +113,10 @@ static u8 * hostapd_eid_pwr_constraint(struct hostapd_data *hapd, u8 *eid) hapd->iface->current_mode->mode != HOSTAPD_MODE_IEEE80211A) return eid; + /* Let host drivers add this IE if DFS support is offloaded */ + if (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD) + return eid; + /* * There is no DFS support and power constraint was not directly * requested by config option. diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c index 93804de0..3bde7205 100644 --- a/src/ap/drv_callbacks.c +++ b/src/ap/drv_callbacks.c @@ -340,6 +340,9 @@ skip_wpa_check: sta->auth_alg, req_ies, req_ies_len); hostapd_sta_assoc(hapd, addr, reassoc, status, buf, p - buf); + + if (sta->auth_alg == WLAN_AUTH_FT) + ap_sta_set_authorized(hapd, sta, 1); #else /* CONFIG_IEEE80211R */ /* Keep compiler silent about unused variables */ if (status) { @@ -350,6 +353,8 @@ skip_wpa_check: sta->flags |= WLAN_STA_AUTH | WLAN_STA_ASSOC; sta->flags &= ~WLAN_STA_WNM_SLEEP_MODE; + hostapd_set_sta_flags(hapd, sta); + if (reassoc && (sta->auth_alg == WLAN_AUTH_FT)) wpa_auth_sm_event(sta->wpa_sm, WPA_ASSOC_FT); else @@ -1044,6 +1049,8 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event, data->eapol_rx.data_len); break; case EVENT_ASSOC: + if (!data) + return; hostapd_notif_assoc(hapd, data->assoc_info.addr, data->assoc_info.req_ies, data->assoc_info.req_ies_len, diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c index 26aca2b0..31423915 100644 --- a/src/ap/hostapd.c +++ b/src/ap/hostapd.c @@ -693,10 +693,10 @@ static int hostapd_setup_bss(struct hostapd_data *hapd, int first) u8 if_addr[ETH_ALEN]; wpa_printf(MSG_DEBUG, "%s(hapd=%p (%s), first=%d)", - __func__, hapd, hapd->conf->iface, first); + __func__, hapd, conf->iface, first); #ifdef EAP_SERVER_TNC - if (hapd->conf->tnc && tncs_global_init() < 0) { + if (conf->tnc && tncs_global_init() < 0) { wpa_printf(MSG_ERROR, "Failed to initialize TNCS"); return -1; } @@ -704,37 +704,37 @@ static int hostapd_setup_bss(struct hostapd_data *hapd, int first) if (hapd->started) { wpa_printf(MSG_ERROR, "%s: Interface %s was already started", - __func__, hapd->conf->iface); + __func__, conf->iface); return -1; } hapd->started = 1; if (!first || first == -1) { - if (hostapd_mac_comp_empty(hapd->conf->bssid) == 0) { + if (hostapd_mac_comp_empty(conf->bssid) == 0) { /* Allocate the next available BSSID. */ do { inc_byte_array(hapd->own_addr, ETH_ALEN); } while (mac_in_conf(hapd->iconf, hapd->own_addr)); } else { /* Allocate the configured BSSID. */ - os_memcpy(hapd->own_addr, hapd->conf->bssid, ETH_ALEN); + os_memcpy(hapd->own_addr, conf->bssid, ETH_ALEN); if (hostapd_mac_comp(hapd->own_addr, hapd->iface->bss[0]->own_addr) == 0) { wpa_printf(MSG_ERROR, "BSS '%s' may not have " "BSSID set to the MAC address of " - "the radio", hapd->conf->iface); + "the radio", conf->iface); return -1; } } hapd->interface_added = 1; if (hostapd_if_add(hapd->iface->bss[0], WPA_IF_AP_BSS, - hapd->conf->iface, hapd->own_addr, hapd, + conf->iface, hapd->own_addr, hapd, &hapd->drv_priv, force_ifname, if_addr, - hapd->conf->bridge[0] ? hapd->conf->bridge : - NULL, first == -1)) { + conf->bridge[0] ? conf->bridge : NULL, + first == -1)) { wpa_printf(MSG_ERROR, "Failed to add BSS (BSSID=" MACSTR ")", MAC2STR(hapd->own_addr)); hapd->interface_added = 0; @@ -749,7 +749,7 @@ static int hostapd_setup_bss(struct hostapd_data *hapd, int first) hostapd_set_privacy(hapd, 0); hostapd_broadcast_wep_clear(hapd); - if (hostapd_setup_encryption(hapd->conf->iface, hapd)) + if (hostapd_setup_encryption(conf->iface, hapd)) return -1; /* @@ -783,9 +783,8 @@ static int hostapd_setup_bss(struct hostapd_data *hapd, int first) if (!hostapd_drv_none(hapd)) { wpa_printf(MSG_ERROR, "Using interface %s with hwaddr " MACSTR " and ssid \"%s\"", - hapd->conf->iface, MAC2STR(hapd->own_addr), - wpa_ssid_txt(hapd->conf->ssid.ssid, - hapd->conf->ssid.ssid_len)); + conf->iface, MAC2STR(hapd->own_addr), + wpa_ssid_txt(conf->ssid.ssid, conf->ssid.ssid_len)); } if (hostapd_setup_wpa_psk(conf)) { @@ -810,17 +809,17 @@ static int hostapd_setup_bss(struct hostapd_data *hapd, int first) return -1; } - if (hapd->conf->radius_das_port) { + if (conf->radius_das_port) { struct radius_das_conf das_conf; os_memset(&das_conf, 0, sizeof(das_conf)); - das_conf.port = hapd->conf->radius_das_port; - das_conf.shared_secret = hapd->conf->radius_das_shared_secret; + das_conf.port = conf->radius_das_port; + das_conf.shared_secret = conf->radius_das_shared_secret; das_conf.shared_secret_len = - hapd->conf->radius_das_shared_secret_len; - das_conf.client_addr = &hapd->conf->radius_das_client_addr; - das_conf.time_window = hapd->conf->radius_das_time_window; + conf->radius_das_shared_secret_len; + das_conf.client_addr = &conf->radius_das_client_addr; + das_conf.time_window = conf->radius_das_time_window; das_conf.require_event_timestamp = - hapd->conf->radius_das_require_event_timestamp; + conf->radius_das_require_event_timestamp; das_conf.ctx = hapd; das_conf.disconnect = hostapd_das_disconnect; hapd->radius_das = radius_das_init(&das_conf); @@ -847,7 +846,7 @@ static int hostapd_setup_bss(struct hostapd_data *hapd, int first) return -1; } - if ((hapd->conf->wpa || hapd->conf->osen) && hostapd_setup_wpa(hapd)) + if ((conf->wpa || conf->osen) && hostapd_setup_wpa(hapd)) return -1; if (accounting_init(hapd)) { @@ -855,8 +854,8 @@ static int hostapd_setup_bss(struct hostapd_data *hapd, int first) return -1; } - if (hapd->conf->ieee802_11f && - (hapd->iapp = iapp_init(hapd, hapd->conf->iapp_iface)) == NULL) { + if (conf->ieee802_11f && + (hapd->iapp = iapp_init(hapd, conf->iapp_iface)) == NULL) { wpa_printf(MSG_ERROR, "IEEE 802.11F (IAPP) initialization " "failed."); return -1; @@ -881,7 +880,7 @@ static int hostapd_setup_bss(struct hostapd_data *hapd, int first) return -1; } - if (!hapd->conf->start_disabled && ieee802_11_set_beacon(hapd) < 0) + if (!conf->start_disabled && ieee802_11_set_beacon(hapd) < 0) return -1; if (hapd->wpa_auth && wpa_init_keys(hapd->wpa_auth) < 0) @@ -1182,12 +1181,15 @@ int hostapd_setup_interface_complete(struct hostapd_iface *iface, int err) iface->conf->channel, iface->freq); #ifdef NEED_AP_MLME - /* Check DFS */ - res = hostapd_handle_dfs(iface); - if (res <= 0) { - if (res < 0) - goto fail; - return res; + /* Handle DFS only if it is not offloaded to the driver */ + if (!(iface->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD)) { + /* Check DFS */ + res = hostapd_handle_dfs(iface); + if (res <= 0) { + if (res < 0) + goto fail; + return res; + } } #endif /* NEED_AP_MLME */ diff --git a/src/ap/sta_info.c b/src/ap/sta_info.c index 60f07682..efd2a724 100644 --- a/src/ap/sta_info.c +++ b/src/ap/sta_info.c @@ -956,12 +956,12 @@ void ap_sta_set_authorized(struct hostapd_data *hapd, struct sta_info *sta, dev_addr = addr; } else dev_addr = p2p_group_get_dev_addr(hapd->p2p_group, sta->addr); -#endif /* CONFIG_P2P */ if (dev_addr) os_snprintf(buf, sizeof(buf), MACSTR " p2p_dev_addr=" MACSTR, MAC2STR(sta->addr), MAC2STR(dev_addr)); else +#endif /* CONFIG_P2P */ os_snprintf(buf, sizeof(buf), MACSTR, MAC2STR(sta->addr)); if (authorized) { diff --git a/src/common/qca-vendor.h b/src/common/qca-vendor.h index 4d9efd52..de0b222b 100644 --- a/src/common/qca-vendor.h +++ b/src/common/qca-vendor.h @@ -32,6 +32,13 @@ enum qca_radiotap_vendor_ids { * * @QCA_NL80211_VENDOR_SUBCMD_TEST: Test command/event * + * @QCA_NL80211_VENDOR_SUBCMD_ROAMING: Set roaming policy for drivers that use + * internal BSS-selection. This command uses + * @QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY to specify the new roaming policy + * for the current connection (i.e., changes policy set by the nl80211 + * Connect command). @QCA_WLAN_VENDOR_ATTR_MAC_ADDR may optionally be + * included to indicate which BSS to use in case roaming is disabled. + * * @QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY: Recommendation of frequency * ranges to avoid to reduce issues due to interference or internal * co-existence information in the driver. The event data structure is @@ -47,7 +54,8 @@ enum qca_radiotap_vendor_ids { enum qca_nl80211_vendor_subcmds { QCA_NL80211_VENDOR_SUBCMD_UNSPEC = 0, QCA_NL80211_VENDOR_SUBCMD_TEST = 1, - /* subcmds 2..9 not yet allocated */ + /* subcmds 2..8 not yet allocated */ + QCA_NL80211_VENDOR_SUBCMD_ROAMING = 9, QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY = 10, QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY = 11, QCA_NL80211_VENDOR_SUBCMD_NAN = 12, @@ -66,9 +74,19 @@ enum qca_wlan_vendor_attr { QCA_WLAN_VENDOR_ATTR_STATS_EXT = 3, /* used by QCA_NL80211_VENDOR_SUBCMD_STATS_EXT */ QCA_WLAN_VENDOR_ATTR_IFINDEX = 4, + /* used by QCA_NL80211_VENDOR_SUBCMD_ROAMING, u32 with values defined + * by enum qca_roaming_policy. */ + QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY = 5, + QCA_WLAN_VENDOR_ATTR_MAC_ADDR = 6, /* keep last */ QCA_WLAN_VENDOR_ATTR_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_MAX = QCA_WLAN_VENDOR_ATTR_AFTER_LAST - 1, }; + +enum qca_roaming_policy { + QCA_ROAMING_NOT_ALLOWED, + QCA_ROAMING_ALLOWED_WITHIN_ESS, +}; + #endif /* QCA_VENDOR_H */ diff --git a/src/crypto/crypto_openssl.c b/src/crypto/crypto_openssl.c index f02aaacb..8876ebf2 100644 --- a/src/crypto/crypto_openssl.c +++ b/src/crypto/crypto_openssl.c @@ -1067,6 +1067,7 @@ void crypto_ec_deinit(struct crypto_ec *e) if (e == NULL) return; BN_clear_free(e->order); + BN_clear_free(e->prime); EC_GROUP_free(e->group); BN_CTX_free(e->bnctx); os_free(e); diff --git a/src/drivers/driver.h b/src/drivers/driver.h index 352c163b..501314bb 100644 --- a/src/drivers/driver.h +++ b/src/drivers/driver.h @@ -2804,6 +2804,30 @@ struct wpa_driver_ops { */ int (*status)(void *priv, char *buf, size_t buflen); + /** + * roaming - Set roaming policy for driver-based BSS selection + * @priv: Private driver interface data + * @allowed: Whether roaming within ESS is allowed + * @bssid: Forced BSSID if roaming is disabled or %NULL if not set + * Returns: Length of written status information or -1 on failure + * + * This optional callback can be used to update roaming policy from the + * associate() command (bssid being set there indicates that the driver + * should not roam before getting this roaming() call to allow roaming. + * If the driver does not indicate WPA_DRIVER_FLAGS_BSS_SELECTION + * capability, roaming policy is handled within wpa_supplicant and there + * is no need to implement or react to this callback. + */ + int (*roaming)(void *priv, int allowed, const u8 *bssid); + + /** + * set_mac_addr - Set MAC address + * @priv: Private driver interface data + * @addr: MAC address to use or %NULL for setting back to permanent + * Returns: 0 on success, -1 on failure + */ + int (*set_mac_addr)(void *priv, const u8 *addr); + #ifdef CONFIG_MACSEC int (*macsec_init)(void *priv, struct macsec_init_params *params); @@ -4172,6 +4196,9 @@ void wpa_scan_results_free(struct wpa_scan_results *res); /* Convert wpa_event_type to a string for logging */ const char * event_to_string(enum wpa_event_type event); +/* Convert chan_width to a string for logging and control interfaces */ +const char * channel_width_to_string(enum chan_width width); + /* NULL terminated array of linked in driver wrappers */ extern struct wpa_driver_ops *wpa_drivers[]; diff --git a/src/drivers/driver_common.c b/src/drivers/driver_common.c index 3058cd57..77e6905d 100644 --- a/src/drivers/driver_common.c +++ b/src/drivers/driver_common.c @@ -84,3 +84,24 @@ const char * event_to_string(enum wpa_event_type event) return "UNKNOWN"; #undef E2S } + + +const char * channel_width_to_string(enum chan_width width) +{ + switch (width) { + case CHAN_WIDTH_20_NOHT: + return "20 MHz (no HT)"; + case CHAN_WIDTH_20: + return "20 MHz"; + case CHAN_WIDTH_40: + return "40 MHz"; + case CHAN_WIDTH_80: + return "80 MHz"; + case CHAN_WIDTH_80P80: + return "80+80 MHz"; + case CHAN_WIDTH_160: + return "160 MHz"; + default: + return "unknown"; + } +} diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index 8ebf7d9c..5c922a05 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -19,6 +19,9 @@ #include #include #include +#ifdef CONFIG_LIBNL3_ROUTE +#include +#endif /* CONFIG_LIBNL3_ROUTE */ #include #include #include @@ -253,6 +256,7 @@ struct wpa_driver_nl80211_data { struct dl_list list; struct dl_list wiphy_list; char phyname[32]; + u8 perm_addr[ETH_ALEN]; void *ctx; int ifindex; int if_removed; @@ -307,8 +311,11 @@ struct wpa_driver_nl80211_data { unsigned int start_iface_up:1; unsigned int test_use_roc_tx:1; unsigned int ignore_deauth_event:1; + unsigned int roaming_vendor_cmd_avail:1; unsigned int dfs_vendor_cmd_avail:1; unsigned int have_low_prio_scan:1; + unsigned int force_connect_cmd:1; + unsigned int addr_changed:1; u64 remain_on_chan_cookie; u64 send_action_cookie; @@ -324,6 +331,8 @@ struct wpa_driver_nl80211_data { int eapol_sock; /* socket for EAPOL frames */ + struct nl_sock *rtnl_sk; /* nl_sock for NETLINK_ROUTE */ + int default_if_indices[16]; int *if_indices; int num_if_indices; @@ -1243,8 +1252,9 @@ static void wpa_driver_nl80211_event_rtm_newlink(void *ctx, } extra[sizeof(extra) - 1] = '\0'; - wpa_printf(MSG_DEBUG, "RTM_NEWLINK: ifi_index=%d ifname=%s%s ifi_flags=0x%x (%s%s%s%s)", - ifi->ifi_index, ifname, extra, ifi->ifi_flags, + wpa_printf(MSG_DEBUG, "RTM_NEWLINK: ifi_index=%d ifname=%s%s ifi_family=%d ifi_flags=0x%x (%s%s%s%s)", + ifi->ifi_index, ifname, extra, ifi->ifi_family, + ifi->ifi_flags, (ifi->ifi_flags & IFF_UP) ? "[UP]" : "", (ifi->ifi_flags & IFF_RUNNING) ? "[RUNNING]" : "", (ifi->ifi_flags & IFF_LOWER_UP) ? "[LOWER_UP]" : "", @@ -1340,6 +1350,7 @@ static void wpa_driver_nl80211_event_rtm_dellink(void *ctx, struct rtattr *attr; u32 brid = 0; char ifname[IFNAMSIZ + 1]; + char extra[100], *pos, *end; drv = nl80211_find_drv(global, ifi->ifi_index, buf, len); if (!drv) { @@ -1348,6 +1359,9 @@ static void wpa_driver_nl80211_event_rtm_dellink(void *ctx, return; } + extra[0] = '\0'; + pos = extra; + end = pos + sizeof(extra); ifname[0] = '\0'; attrlen = len; @@ -1362,12 +1376,30 @@ static void wpa_driver_nl80211_event_rtm_dellink(void *ctx, break; case IFLA_MASTER: brid = nla_get_u32((struct nlattr *) attr); + pos += os_snprintf(pos, end - pos, " master=%u", brid); + break; + case IFLA_OPERSTATE: + pos += os_snprintf(pos, end - pos, " operstate=%u", + nla_get_u32((struct nlattr *) attr)); + break; + case IFLA_LINKMODE: + pos += os_snprintf(pos, end - pos, " linkmode=%u", + nla_get_u32((struct nlattr *) attr)); break; } attr = RTA_NEXT(attr, attrlen); } + extra[sizeof(extra) - 1] = '\0'; - if (ifname[0]) + wpa_printf(MSG_DEBUG, "RTM_DELLINK: ifi_index=%d ifname=%s%s ifi_family=%d ifi_flags=0x%x (%s%s%s%s)", + ifi->ifi_index, ifname, extra, ifi->ifi_family, + ifi->ifi_flags, + (ifi->ifi_flags & IFF_UP) ? "[UP]" : "", + (ifi->ifi_flags & IFF_RUNNING) ? "[RUNNING]" : "", + (ifi->ifi_flags & IFF_LOWER_UP) ? "[LOWER_UP]" : "", + (ifi->ifi_flags & IFF_DORMANT) ? "[DORMANT]" : ""); + + if (ifname[0] && (ifi->ifi_family != AF_BRIDGE || !brid)) wpa_driver_nl80211_event_dellink(drv, ifname); if (ifi->ifi_family == AF_BRIDGE && brid) { @@ -1387,6 +1419,17 @@ static void mlme_event_auth(struct wpa_driver_nl80211_data *drv, const struct ieee80211_mgmt *mgmt; union wpa_event_data event; + if (!(drv->capa.flags & WPA_DRIVER_FLAGS_SME) && + drv->force_connect_cmd) { + /* + * Avoid reporting two association events that would confuse + * the core code. + */ + wpa_printf(MSG_DEBUG, + "nl80211: Ignore auth event when using driver SME"); + return; + } + wpa_printf(MSG_DEBUG, "nl80211: Authenticate event"); mgmt = (const struct ieee80211_mgmt *) frame; if (len < 24 + sizeof(mgmt->u.auth)) { @@ -1453,6 +1496,17 @@ static void mlme_event_assoc(struct wpa_driver_nl80211_data *drv, union wpa_event_data event; u16 status; + if (!(drv->capa.flags & WPA_DRIVER_FLAGS_SME) && + drv->force_connect_cmd) { + /* + * Avoid reporting two association events that would confuse + * the core code. + */ + wpa_printf(MSG_DEBUG, + "nl80211: Ignore assoc event when using driver SME"); + return; + } + wpa_printf(MSG_DEBUG, "nl80211: Associate event"); mgmt = (const struct ieee80211_mgmt *) frame; if (len < 24 + sizeof(mgmt->u.assoc_resp)) { @@ -3846,9 +3900,14 @@ static int wiphy_info_handler(struct nl_msg *msg, void *arg) continue; } vinfo = nla_data(nl); - if (vinfo->subcmd == - QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY) + switch (vinfo->subcmd) { + case QCA_NL80211_VENDOR_SUBCMD_ROAMING: + drv->roaming_vendor_cmd_avail = 1; + break; + case QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY: drv->dfs_vendor_cmd_avail = 1; + break; + } wpa_printf(MSG_DEBUG, "nl80211: Supported vendor command: vendor_id=0x%x subcmd=%u", vinfo->vendor_id, vinfo->subcmd); @@ -4550,7 +4609,7 @@ static int nl80211_mgmt_subscribe_non_ap(struct i802_bss *bss) #ifdef CONFIG_HS20 /* WNM-Notification */ if (nl80211_register_action_frame(bss, (u8 *) "\x0a\x1a", 2) < 0) - return -1; + ret = -1; #endif /* CONFIG_HS20 */ nl80211_mgmt_handle_register_eloop(bss); @@ -4822,6 +4881,7 @@ wpa_driver_nl80211_finish_drv_init(struct wpa_driver_nl80211_data *drv, if (linux_get_ifhwaddr(drv->global->ioctl_sock, bss->ifname, bss->addr)) return -1; + os_memcpy(drv->perm_addr, bss->addr, ETH_ALEN); if (send_rfkill_event) { eloop_register_timeout(0, 0, wpa_driver_nl80211_send_rfkill, @@ -4877,6 +4937,8 @@ static void wpa_driver_nl80211_deinit(struct i802_bss *bss) wpa_printf(MSG_INFO, "nl80211: Failed to remove " "interface %s from bridge %s: %s", bss->ifname, bss->brname, strerror(errno)); + if (drv->rtnl_sk) + nl_socket_free(drv->rtnl_sk); } if (bss->added_bridge) { if (linux_br_del(drv->global->ioctl_sock, bss->brname) < 0) @@ -4910,6 +4972,16 @@ static void wpa_driver_nl80211_deinit(struct i802_bss *bss) if (!drv->start_iface_up) (void) i802_set_iface_flags(bss, 0); + + if (drv->addr_changed) { + linux_set_iface_flags(drv->global->ioctl_sock, bss->ifname, 0); + if (linux_set_ifhwaddr(drv->global->ioctl_sock, bss->ifname, + drv->perm_addr) < 0) { + wpa_printf(MSG_DEBUG, + "nl80211: Could not restore permanent MAC address"); + } + } + if (drv->nlmode != NL80211_IFTYPE_P2P_DEVICE) { if (!drv->hostapd || !drv->start_mode_ap) wpa_driver_nl80211_set_mode(bss, @@ -7686,6 +7758,43 @@ static int wpa_driver_nl80211_sta_add(void *priv, } +static void rtnl_neigh_delete_fdb_entry(struct i802_bss *bss, const u8 *addr) +{ +#ifdef CONFIG_LIBNL3_ROUTE + struct wpa_driver_nl80211_data *drv = bss->drv; + struct rtnl_neigh *rn; + struct nl_addr *nl_addr; + int err; + + rn = rtnl_neigh_alloc(); + if (!rn) + return; + + rtnl_neigh_set_family(rn, AF_BRIDGE); + rtnl_neigh_set_ifindex(rn, bss->ifindex); + nl_addr = nl_addr_build(AF_BRIDGE, (void *) addr, ETH_ALEN); + if (!nl_addr) { + rtnl_neigh_put(rn); + return; + } + rtnl_neigh_set_lladdr(rn, nl_addr); + + err = rtnl_neigh_delete(drv->rtnl_sk, rn, 0); + if (err < 0) { + wpa_printf(MSG_DEBUG, "nl80211: bridge FDB entry delete for " + MACSTR " ifindex=%d failed: %s", MAC2STR(addr), + bss->ifindex, nl_geterror(err)); + } else { + wpa_printf(MSG_DEBUG, "nl80211: deleted bridge FDB entry for " + MACSTR, MAC2STR(addr)); + } + + nl_addr_put(nl_addr); + rtnl_neigh_put(rn); +#endif /* CONFIG_LIBNL3_ROUTE */ +} + + static int wpa_driver_nl80211_sta_remove(struct i802_bss *bss, const u8 *addr) { struct wpa_driver_nl80211_data *drv = bss->drv; @@ -7706,6 +7815,10 @@ static int wpa_driver_nl80211_sta_remove(struct i802_bss *bss, const u8 *addr) wpa_printf(MSG_DEBUG, "nl80211: sta_remove -> DEL_STATION %s " MACSTR " --> %d (%s)", bss->ifname, MAC2STR(addr), ret, strerror(-ret)); + + if (drv->rtnl_sk) + rtnl_neigh_delete_fdb_entry(bss, addr); + if (ret == -ENOENT) return 0; return ret; @@ -8480,6 +8593,11 @@ static int wpa_driver_nl80211_sta_set_flags(void *priv, const u8 *addr, struct nlattr *flags; struct nl80211_sta_flag_update upd; + wpa_printf(MSG_DEBUG, "nl80211: Set STA flags - ifname=%s addr=" MACSTR + " total_flags=0x%x flags_or=0x%x flags_and=0x%x authorized=%d", + bss->ifname, MAC2STR(addr), total_flags, flags_or, flags_and, + !!(total_flags & WPA_STA_AUTHORIZED)); + msg = nlmsg_alloc(); if (!msg) return -ENOMEM; @@ -9984,6 +10102,22 @@ static void *i802_init(struct hostapd_data *hapd, i802_check_bridge(drv, bss, params->bridge[0], params->ifname) < 0) goto failed; +#ifdef CONFIG_LIBNL3_ROUTE + if (bss->added_if_into_bridge) { + drv->rtnl_sk = nl_socket_alloc(); + if (drv->rtnl_sk == NULL) { + wpa_printf(MSG_ERROR, "nl80211: Failed to allocate nl_sock"); + goto failed; + } + + if (nl_connect(drv->rtnl_sk, NETLINK_ROUTE)) { + wpa_printf(MSG_ERROR, "nl80211: Failed to connect nl_sock to NETLINK_ROUTE: %s", + strerror(errno)); + goto failed; + } + } +#endif /* CONFIG_LIBNL3_ROUTE */ + drv->eapol_sock = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_PAE)); if (drv->eapol_sock < 0) { wpa_printf(MSG_ERROR, "nl80211: socket(PF_PACKET, SOCK_DGRAM, ETH_P_PAE) failed: %s", @@ -10000,6 +10134,7 @@ static void *i802_init(struct hostapd_data *hapd, if (linux_get_ifhwaddr(drv->global->ioctl_sock, bss->ifname, params->own_addr)) goto failed; + os_memcpy(drv->perm_addr, params->own_addr, ETH_ALEN); memcpy(bss->addr, params->own_addr, ETH_ALEN); @@ -10959,6 +11094,7 @@ static int nl80211_set_param(void *priv, const char *param) struct i802_bss *bss = priv; struct wpa_driver_nl80211_data *drv = bss->drv; drv->capa.flags &= ~WPA_DRIVER_FLAGS_SME; + drv->force_connect_cmd = 1; } if (os_strstr(param, "no_offchannel_tx=1")) { @@ -11450,60 +11586,18 @@ static int nl80211_start_radar_detection(void *priv, nl80211_cmd(bss->drv, msg, 0, NL80211_CMD_RADAR_DETECT); NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex); - NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, freq->freq); - if (freq->vht_enabled) { - switch (freq->bandwidth) { - case 20: - NLA_PUT_U32(msg, NL80211_ATTR_CHANNEL_WIDTH, - NL80211_CHAN_WIDTH_20); - break; - case 40: - NLA_PUT_U32(msg, NL80211_ATTR_CHANNEL_WIDTH, - NL80211_CHAN_WIDTH_40); - break; - case 80: - if (freq->center_freq2) - NLA_PUT_U32(msg, NL80211_ATTR_CHANNEL_WIDTH, - NL80211_CHAN_WIDTH_80P80); - else - NLA_PUT_U32(msg, NL80211_ATTR_CHANNEL_WIDTH, - NL80211_CHAN_WIDTH_80); - break; - case 160: - NLA_PUT_U32(msg, NL80211_ATTR_CHANNEL_WIDTH, - NL80211_CHAN_WIDTH_160); - break; - default: - return -1; - } - NLA_PUT_U32(msg, NL80211_ATTR_CENTER_FREQ1, freq->center_freq1); - if (freq->center_freq2) - NLA_PUT_U32(msg, NL80211_ATTR_CENTER_FREQ2, - freq->center_freq2); - } else if (freq->ht_enabled) { - switch (freq->sec_channel_offset) { - case -1: - NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE, - NL80211_CHAN_HT40MINUS); - break; - case 1: - NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE, - NL80211_CHAN_HT40PLUS); - break; - default: - NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE, - NL80211_CHAN_HT20); - break; - } - } + if (nl80211_put_freq_params(msg, freq) < 0) + goto nla_put_failure; ret = send_and_recv_msgs(drv, msg, NULL, NULL); + msg = NULL; if (ret == 0) return 0; wpa_printf(MSG_DEBUG, "nl80211: Failed to start radar detection: " "%d (%s)", ret, strerror(-ret)); nla_put_failure: + nlmsg_free(msg); return -1; } @@ -11954,6 +12048,7 @@ static int wpa_driver_nl80211_status(void *priv, char *buf, size_t buflen) res = os_snprintf(pos, end - pos, "phyname=%s\n" + "perm_addr=" MACSTR "\n" "drv_ifindex=%d\n" "operstate=%d\n" "scan_state=%s\n" @@ -11970,6 +12065,7 @@ static int wpa_driver_nl80211_status(void *priv, char *buf, size_t buflen) "eapol_tx_sock=%d\n" "%s%s%s%s%s%s%s%s%s%s%s%s%s%s", drv->phyname, + MAC2STR(drv->perm_addr), drv->ifindex, drv->operstate, scan_state_str(drv->scan_state), @@ -12352,6 +12448,90 @@ nla_put_failure: } +static int nl80211_roaming(void *priv, int allowed, const u8 *bssid) +{ + struct i802_bss *bss = priv; + struct wpa_driver_nl80211_data *drv = bss->drv; + struct nl_msg *msg; + struct nlattr *params; + + wpa_printf(MSG_DEBUG, "nl80211: Roaming policy: allowed=%d", allowed); + + if (!drv->roaming_vendor_cmd_avail) { + wpa_printf(MSG_DEBUG, + "nl80211: Ignore roaming policy change since driver does not provide command for setting it"); + return -1; + } + + msg = nlmsg_alloc(); + if (!msg) + return -ENOMEM; + + nl80211_cmd(drv, msg, 0, NL80211_CMD_VENDOR); + + NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex); + NLA_PUT_U32(msg, NL80211_ATTR_VENDOR_ID, OUI_QCA); + NLA_PUT_U32(msg, NL80211_ATTR_VENDOR_SUBCMD, + QCA_NL80211_VENDOR_SUBCMD_ROAMING); + + params = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA); + if (!params) + goto nla_put_failure; + NLA_PUT_U32(msg, QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY, + allowed ? QCA_ROAMING_ALLOWED_WITHIN_ESS : + QCA_ROAMING_NOT_ALLOWED); + if (bssid) + NLA_PUT(msg, QCA_WLAN_VENDOR_ATTR_MAC_ADDR, ETH_ALEN, bssid); + nla_nest_end(msg, params); + + return send_and_recv_msgs(drv, msg, NULL, NULL); + + nla_put_failure: + nlmsg_free(msg); + return -1; +} + + +static int nl80211_set_mac_addr(void *priv, const u8 *addr) +{ + struct i802_bss *bss = priv; + struct wpa_driver_nl80211_data *drv = bss->drv; + int new_addr = addr != NULL; + + if (!addr) + addr = drv->perm_addr; + + if (linux_set_iface_flags(drv->global->ioctl_sock, bss->ifname, 0) < 0) + return -1; + + if (linux_set_ifhwaddr(drv->global->ioctl_sock, bss->ifname, addr) < 0) + { + wpa_printf(MSG_DEBUG, + "nl80211: failed to set_mac_addr for %s to " MACSTR, + bss->ifname, MAC2STR(addr)); + if (linux_set_iface_flags(drv->global->ioctl_sock, bss->ifname, + 1) < 0) { + wpa_printf(MSG_DEBUG, + "nl80211: Could not restore interface UP after failed set_mac_addr"); + } + return -1; + } + + wpa_printf(MSG_DEBUG, "nl80211: set_mac_addr for %s to " MACSTR, + bss->ifname, MAC2STR(addr)); + drv->addr_changed = new_addr; + os_memcpy(bss->addr, addr, ETH_ALEN); + + if (linux_set_iface_flags(drv->global->ioctl_sock, bss->ifname, 1) < 0) + { + wpa_printf(MSG_DEBUG, + "nl80211: Could not restore interface UP after set_mac_addr"); + } + + return 0; +} + + const struct wpa_driver_ops wpa_driver_nl80211_ops = { .name = "nl80211", .desc = "Linux nl80211/cfg80211", @@ -12443,4 +12623,6 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops = { .vendor_cmd = nl80211_vendor_cmd, .set_qos_map = nl80211_set_qos_map, .set_wowlan = nl80211_set_wowlan, + .roaming = nl80211_roaming, + .set_mac_addr = nl80211_set_mac_addr, }; diff --git a/src/drivers/drivers.mak b/src/drivers/drivers.mak index 40aaba59..cdb913e3 100644 --- a/src/drivers/drivers.mak +++ b/src/drivers/drivers.mak @@ -36,6 +36,10 @@ ifdef CONFIG_LIBNL32 DRV_LIBS += -lnl-3 DRV_LIBS += -lnl-genl-3 DRV_CFLAGS += -DCONFIG_LIBNL20 -I/usr/include/libnl3 +ifdef CONFIG_LIBNL3_ROUTE + DRV_LIBS += -lnl-route-3 + DRV_CFLAGS += -DCONFIG_LIBNL3_ROUTE +endif else ifdef CONFIG_LIBNL_TINY DRV_LIBS += -lnl-tiny diff --git a/src/drivers/drivers.mk b/src/drivers/drivers.mk index db8561ae..9fa70d9c 100644 --- a/src/drivers/drivers.mk +++ b/src/drivers/drivers.mk @@ -31,6 +31,10 @@ ifdef CONFIG_LIBNL32 DRV_LIBS += -lnl-3 DRV_LIBS += -lnl-genl-3 DRV_CFLAGS += -DCONFIG_LIBNL20 -I/usr/include/libnl3 +ifdef CONFIG_LIBNL3_ROUTE + DRV_LIBS += -lnl-route-3 + DRV_CFLAGS += -DCONFIG_LIBNL3_ROUTE +endif else ifdef CONFIG_LIBNL_TINY DRV_LIBS += -lnl-tiny diff --git a/src/eap_server/eap_server_pax.c b/src/eap_server/eap_server_pax.c index c87848c4..d9d4375a 100644 --- a/src/eap_server/eap_server_pax.c +++ b/src/eap_server/eap_server_pax.c @@ -287,7 +287,7 @@ static void eap_pax_process_std_2(struct eap_sm *sm, struct eap_pax_hdr *resp; u8 mac[EAP_PAX_MAC_LEN], icvbuf[EAP_PAX_ICV_LEN]; const u8 *pos; - size_t len, left; + size_t len, left, cid_len; int i; if (data->state != PAX_STD_1) @@ -320,7 +320,12 @@ static void eap_pax_process_std_2(struct eap_sm *sm, wpa_printf(MSG_INFO, "EAP-PAX: Too short PAX_STD-2 (CID)"); return; } - data->cid_len = WPA_GET_BE16(pos); + cid_len = WPA_GET_BE16(pos); + if (cid_len > 1500) { + wpa_printf(MSG_INFO, "EAP-PAX: Too long CID"); + return; + } + data->cid_len = cid_len; os_free(data->cid); data->cid = os_malloc(data->cid_len); if (data->cid == NULL) { diff --git a/src/eapol_supp/eapol_supp_sm.c b/src/eapol_supp/eapol_supp_sm.c index cf3506d9..70258be2 100644 --- a/src/eapol_supp/eapol_supp_sm.c +++ b/src/eapol_supp/eapol_supp_sm.c @@ -255,12 +255,14 @@ SM_STATE(SUPP_PAE, CONNECTING) * delay authentication. Use a short timeout to send the first * EAPOL-Start if Authenticator does not start authentication. */ -#ifdef CONFIG_WPS - /* Reduce latency on starting WPS negotiation. */ - sm->startWhen = 1; -#else /* CONFIG_WPS */ - sm->startWhen = 3; -#endif /* CONFIG_WPS */ + if (sm->conf.wps) { + /* Reduce latency on starting WPS negotiation. */ + wpa_printf(MSG_DEBUG, + "EAPOL: Using shorter startWhen for WPS"); + sm->startWhen = 1; + } else { + sm->startWhen = 2; + } } eapol_enable_timer_tick(sm); sm->eapolEap = FALSE; @@ -1242,7 +1244,7 @@ int eapol_sm_rx_eapol(struct eapol_sm *sm, const u8 *src, const u8 *buf, return 0; } #ifdef CONFIG_WPS - if (sm->conf.workaround && + if (sm->conf.wps && sm->conf.workaround && plen < len - sizeof(*hdr) && hdr->type == IEEE802_1X_TYPE_EAP_PACKET && len - sizeof(*hdr) > sizeof(struct eap_hdr)) { @@ -1491,6 +1493,7 @@ void eapol_sm_notify_config(struct eapol_sm *sm, sm->conf.required_keys = conf->required_keys; sm->conf.fast_reauth = conf->fast_reauth; sm->conf.workaround = conf->workaround; + sm->conf.wps = conf->wps; #ifdef CONFIG_EAP_PROXY if (sm->use_eap_proxy) { /* Using EAP Proxy, so skip EAP state machine update */ diff --git a/src/eapol_supp/eapol_supp_sm.h b/src/eapol_supp/eapol_supp_sm.h index d76c8c21..5b37314f 100644 --- a/src/eapol_supp/eapol_supp_sm.h +++ b/src/eapol_supp/eapol_supp_sm.h @@ -58,6 +58,11 @@ struct eapol_config { * external_sim - Use external processing for SIM/USIM operations */ int external_sim; + + /** + * wps - Whether this connection is used for WPS + */ + int wps; }; struct eapol_sm; diff --git a/src/p2p/p2p.c b/src/p2p/p2p.c index 3a5486b9..7d4a03c5 100644 --- a/src/p2p/p2p.c +++ b/src/p2p/p2p.c @@ -259,7 +259,8 @@ static void p2p_listen_in_find(struct p2p_data *p2p, int dev_disc) return; } - os_get_random((u8 *) &r, sizeof(r)); + if (os_get_random((u8 *) &r, sizeof(r)) < 0) + r = 0; tu = (r % ((p2p->max_disc_int - p2p->min_disc_int) + 1) + p2p->min_disc_int) * 100; if (p2p->max_disc_tu >= 0 && tu > (unsigned int) p2p->max_disc_tu) @@ -1286,8 +1287,8 @@ static void p2p_prepare_channel_best(struct p2p_data *p2p) } else if (p2p_channel_random_social(&p2p->cfg->channels, &p2p->op_reg_class, &p2p->op_channel) == 0) { - p2p_dbg(p2p, "Select random available social channel %d from 2.4 GHz band as operating channel preference", - p2p->op_channel); + p2p_dbg(p2p, "Select random available social channel (op_class %u channel %u) as operating channel preference", + p2p->op_reg_class, p2p->op_channel); } else { /* Select any random available channel from the first available * operating class */ @@ -1824,8 +1825,17 @@ static void p2p_go_neg_start(void *eloop_ctx, void *timeout_ctx) struct p2p_data *p2p = eloop_ctx; if (p2p->go_neg_peer == NULL) return; + if (p2p->pending_listen_freq) { + p2p_dbg(p2p, "Clear pending_listen_freq for p2p_go_neg_start"); + p2p->pending_listen_freq = 0; + } p2p->cfg->stop_listen(p2p->cfg->cb_ctx); p2p->go_neg_peer->status = P2P_SC_SUCCESS; + /* + * Set new timeout to make sure a previously set one does not expire + * too quickly while waiting for the GO Negotiation to complete. + */ + p2p_set_timeout(p2p, 0, 500000); p2p_connect_send(p2p, p2p->go_neg_peer); } @@ -1835,6 +1845,10 @@ static void p2p_invite_start(void *eloop_ctx, void *timeout_ctx) struct p2p_data *p2p = eloop_ctx; if (p2p->invite_peer == NULL) return; + if (p2p->pending_listen_freq) { + p2p_dbg(p2p, "Clear pending_listen_freq for p2p_invite_start"); + p2p->pending_listen_freq = 0; + } p2p->cfg->stop_listen(p2p->cfg->cb_ctx); p2p_invite_send(p2p, p2p->invite_peer, p2p->invite_go_dev_addr, p2p->invite_dev_pw_id); @@ -2480,7 +2494,8 @@ struct p2p_data * p2p_init(const struct p2p_config *cfg) p2p->max_disc_int = 3; p2p->max_disc_tu = -1; - os_get_random(&p2p->next_tie_breaker, 1); + if (os_get_random(&p2p->next_tie_breaker, 1) < 0) + p2p->next_tie_breaker = 0; p2p->next_tie_breaker &= 0x01; if (cfg->sd_request) p2p->dev_capab |= P2P_DEV_CAPAB_SERVICE_DISCOVERY; @@ -2773,6 +2788,19 @@ static void p2p_sd_cb(struct p2p_data *p2p, int success) return; } + if (p2p->sd_query->for_all_peers) { + /* Update the pending broadcast SD query count for this device + */ + p2p->sd_peer->sd_pending_bcast_queries--; + + /* + * If there are no pending broadcast queries for this device, + * mark it as done (-1). + */ + if (p2p->sd_peer->sd_pending_bcast_queries == 0) + p2p->sd_peer->sd_pending_bcast_queries = -1; + } + /* Wait for response from the peer */ p2p_set_state(p2p, P2P_SD_DURING_FIND); p2p_set_timeout(p2p, 0, 200000); @@ -3003,7 +3031,8 @@ static void p2p_go_neg_req_cb(struct p2p_data *p2p, int success) * make it less likely to hit cases where we could end up in * sync with peer not listening. */ - os_get_random((u8 *) &r, sizeof(r)); + if (os_get_random((u8 *) &r, sizeof(r)) < 0) + r = 0; timeout += r % 100000; } p2p_set_timeout(p2p, 0, timeout); @@ -4075,6 +4104,13 @@ void p2p_set_managed_oper(struct p2p_data *p2p, int enabled) } +int p2p_config_get_random_social(struct p2p_config *p2p, u8 *op_class, + u8 *op_channel) +{ + return p2p_channel_random_social(&p2p->channels, op_class, op_channel); +} + + int p2p_set_listen_channel(struct p2p_data *p2p, u8 reg_class, u8 channel, u8 forced) { diff --git a/src/p2p/p2p.h b/src/p2p/p2p.h index dee79dfb..076a2ac1 100644 --- a/src/p2p/p2p.h +++ b/src/p2p/p2p.h @@ -1691,6 +1691,20 @@ void p2p_set_client_discoverability(struct p2p_data *p2p, int enabled); */ void p2p_set_managed_oper(struct p2p_data *p2p, int enabled); +/** + * p2p_config_get_random_social - Return a random social channel + * @p2p: P2P config + * @op_class: Selected operating class + * @op_channel: Selected social channel + * Returns: 0 on success, -1 on failure + * + * This function is used before p2p_init is called. A random social channel + * from supports bands 2.4 GHz (channels 1,6,11) and 60 GHz (channel 2) is + * returned on success. + */ +int p2p_config_get_random_social(struct p2p_config *p2p, u8 *op_class, + u8 *op_channel); + int p2p_set_listen_channel(struct p2p_data *p2p, u8 reg_class, u8 channel, u8 forced); diff --git a/src/p2p/p2p_go_neg.c b/src/p2p/p2p_go_neg.c index bd7a2cf5..21fae3f2 100644 --- a/src/p2p/p2p_go_neg.c +++ b/src/p2p/p2p_go_neg.c @@ -958,7 +958,10 @@ void p2p_process_go_neg_resp(struct p2p_data *p2p, const u8 *sa, p2p_dbg(p2p, "Wait for the peer to become ready for GO Negotiation"); dev->flags |= P2P_DEV_NOT_YET_READY; os_get_reltime(&dev->go_neg_wait_started); - p2p_set_state(p2p, P2P_WAIT_PEER_IDLE); + if (p2p->state == P2P_CONNECT_LISTEN) + p2p_set_state(p2p, P2P_WAIT_PEER_CONNECT); + else + p2p_set_state(p2p, P2P_WAIT_PEER_IDLE); p2p_set_timeout(p2p, 0, 0); } else { p2p_dbg(p2p, "Stop GO Negotiation attempt"); diff --git a/src/p2p/p2p_sd.c b/src/p2p/p2p_sd.c index 6235b1de..13119c20 100644 --- a/src/p2p/p2p_sd.c +++ b/src/p2p/p2p_sd.c @@ -301,16 +301,6 @@ int p2p_start_sd(struct p2p_data *p2p, struct p2p_device *dev) ret = -1; } - /* Update the pending broadcast SD query count for this device */ - dev->sd_pending_bcast_queries--; - - /* - * If there are no pending broadcast queries for this device, mark it as - * done (-1). - */ - if (dev->sd_pending_bcast_queries == 0) - dev->sd_pending_bcast_queries = -1; - wpabuf_free(req); return ret; diff --git a/src/p2p/p2p_utils.c b/src/p2p/p2p_utils.c index 189300ad..23acce76 100644 --- a/src/p2p/p2p_utils.c +++ b/src/p2p/p2p_utils.c @@ -149,6 +149,15 @@ int p2p_freq_to_channel(unsigned int freq, u8 *op_class, u8 *channel) return 0; } + if (freq >= 58320 && freq <= 64800) { + if ((freq - 58320) % 2160) + return -1; + + *op_class = 180; /* 60 GHz, channels 1..4 */ + *channel = (freq - 56160) / 2160; + return 0; + } + return -1; } @@ -441,7 +450,8 @@ void p2p_channels_dump(struct p2p_data *p2p, const char *title, static u8 p2p_channel_pick_random(const u8 *channels, unsigned int num_channels) { unsigned int r; - os_get_random((u8 *) &r, sizeof(r)); + if (os_get_random((u8 *) &r, sizeof(r)) < 0) + r = 0; r %= num_channels; return channels[r]; } @@ -481,7 +491,7 @@ int p2p_channel_select(struct p2p_channels *chans, const int *classes, int p2p_channel_random_social(struct p2p_channels *chans, u8 *op_class, u8 *op_channel) { - u8 chan[3]; + u8 chan[4]; unsigned int num_channels = 0; /* Try to find available social channels from 2.4 GHz */ @@ -492,11 +502,18 @@ int p2p_channel_random_social(struct p2p_channels *chans, u8 *op_class, if (p2p_channels_includes(chans, 81, 11)) chan[num_channels++] = 11; + /* Try to find available social channels from 60 GHz */ + if (p2p_channels_includes(chans, 180, 2)) + chan[num_channels++] = 2; + if (num_channels == 0) return -1; - *op_class = 81; *op_channel = p2p_channel_pick_random(chan, num_channels); + if (*op_channel == 2) + *op_class = 180; + else + *op_class = 81; return 0; } diff --git a/src/radius/radius_client.c b/src/radius/radius_client.c index 10056a64..e2766e2f 100644 --- a/src/radius/radius_client.c +++ b/src/radius/radius_client.c @@ -1080,19 +1080,23 @@ radius_change_server(struct radius_client_data *radius, switch (nserv->addr.af) { case AF_INET: claddrlen = sizeof(claddr); - getsockname(sel_sock, (struct sockaddr *) &claddr, &claddrlen); - wpa_printf(MSG_DEBUG, "RADIUS local address: %s:%u", - inet_ntoa(claddr.sin_addr), ntohs(claddr.sin_port)); + if (getsockname(sel_sock, (struct sockaddr *) &claddr, + &claddrlen) == 0) { + wpa_printf(MSG_DEBUG, "RADIUS local address: %s:%u", + inet_ntoa(claddr.sin_addr), + ntohs(claddr.sin_port)); + } break; #ifdef CONFIG_IPV6 case AF_INET6: { claddrlen = sizeof(claddr6); - getsockname(sel_sock, (struct sockaddr *) &claddr6, - &claddrlen); - wpa_printf(MSG_DEBUG, "RADIUS local address: %s:%u", - inet_ntop(AF_INET6, &claddr6.sin6_addr, - abuf, sizeof(abuf)), - ntohs(claddr6.sin6_port)); + if (getsockname(sel_sock, (struct sockaddr *) &claddr6, + &claddrlen) == 0) { + wpa_printf(MSG_DEBUG, "RADIUS local address: %s:%u", + inet_ntop(AF_INET6, &claddr6.sin6_addr, + abuf, sizeof(abuf)), + ntohs(claddr6.sin6_port)); + } break; } #endif /* CONFIG_IPV6 */ diff --git a/src/radius/radius_server.c b/src/radius/radius_server.c index 24348a39..00394b49 100644 --- a/src/radius/radius_server.c +++ b/src/radius/radius_server.c @@ -1926,7 +1926,7 @@ int radius_server_get_mib(struct radius_server_data *data, char *buf, if (inet_ntop(AF_INET6, &cli->addr6, abuf, sizeof(abuf)) == NULL) abuf[0] = '\0'; - if (inet_ntop(AF_INET6, &cli->mask6, abuf, + if (inet_ntop(AF_INET6, &cli->mask6, mbuf, sizeof(mbuf)) == NULL) mbuf[0] = '\0'; } @@ -2048,8 +2048,6 @@ void radius_server_eap_pending_cb(struct radius_server_data *data, void *ctx) sess = s; break; } - if (sess) - break; } if (sess) break; diff --git a/src/rsn_supp/tdls.c b/src/rsn_supp/tdls.c index cd34223f..93ae1432 100644 --- a/src/rsn_supp/tdls.c +++ b/src/rsn_supp/tdls.c @@ -1382,11 +1382,85 @@ static int wpa_tdls_send_discovery_response(struct wpa_sm *sm, struct wpa_tdls_peer *peer, u8 dialog_token) { + size_t buf_len = 0; + struct wpa_tdls_timeoutie timeoutie; + u16 rsn_capab; + u8 *rbuf, *pos, *count_pos; + u16 count; + struct rsn_ie_hdr *hdr; + int status; + wpa_printf(MSG_DEBUG, "TDLS: Sending TDLS Discovery Response " "(peer " MACSTR ")", MAC2STR(peer->addr)); + if (!wpa_tdls_get_privacy(sm)) + goto skip_rsn_ies; - return wpa_tdls_tpk_send(sm, peer->addr, WLAN_TDLS_DISCOVERY_RESPONSE, - dialog_token, 0, 0, NULL, 0); + /* Filling RSN IE */ + hdr = (struct rsn_ie_hdr *) peer->rsnie_i; + hdr->elem_id = WLAN_EID_RSN; + WPA_PUT_LE16(hdr->version, RSN_VERSION); + pos = (u8 *) (hdr + 1); + RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_NO_GROUP_ADDRESSED); + pos += RSN_SELECTOR_LEN; + count_pos = pos; + pos += 2; + count = 0; + + /* + * AES-CCMP is the default encryption preferred for TDLS, so + * RSN IE is filled only with CCMP cipher suite. + * Note: TKIP is not used to encrypt TDLS link. + * + * Regardless of the cipher used on the AP connection, select CCMP + * here. + */ + RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP); + pos += RSN_SELECTOR_LEN; + count++; + WPA_PUT_LE16(count_pos, count); + WPA_PUT_LE16(pos, 1); + pos += 2; + RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_TPK_HANDSHAKE); + pos += RSN_SELECTOR_LEN; + + rsn_capab = WPA_CAPABILITY_PEERKEY_ENABLED; + rsn_capab |= RSN_NUM_REPLAY_COUNTERS_16 << 2; + WPA_PUT_LE16(pos, rsn_capab); + pos += 2; + hdr->len = (pos - (u8 *) hdr) - 2; + peer->rsnie_i_len = pos - peer->rsnie_i; + + wpa_hexdump(MSG_DEBUG, "TDLS: RSN IE for Discovery Response", + (u8 *) hdr, hdr->len + 2); +skip_rsn_ies: + buf_len = 0; + if (wpa_tdls_get_privacy(sm)) { + /* Peer RSN IE, Lifetime */ + buf_len += peer->rsnie_i_len + + sizeof(struct wpa_tdls_timeoutie); + } + rbuf = os_zalloc(buf_len + 1); + if (rbuf == NULL) { + wpa_tdls_peer_free(sm, peer); + return -1; + } + pos = rbuf; + + if (!wpa_tdls_get_privacy(sm)) + goto skip_ies; + /* Initiator RSN IE */ + pos = wpa_add_ie(pos, peer->rsnie_i, peer->rsnie_i_len); + /* Lifetime */ + peer->lifetime = TPK_LIFETIME; + pos = wpa_add_tdls_timeoutie(pos, (u8 *) &timeoutie, + sizeof(timeoutie), peer->lifetime); + wpa_printf(MSG_DEBUG, "TDLS: TPK lifetime %u seconds", peer->lifetime); +skip_ies: + status = wpa_tdls_tpk_send(sm, peer->addr, WLAN_TDLS_DISCOVERY_RESPONSE, + dialog_token, 0, 0, rbuf, pos - rbuf); + os_free(rbuf); + + return status; } @@ -1743,7 +1817,7 @@ static int wpa_tdls_process_tpk_m1(struct wpa_sm *sm, const u8 *src_addr, lnkid = (struct wpa_tdls_lnkid *) kde.lnkid; if (os_memcmp(sm->bssid, lnkid->bssid, ETH_ALEN) != 0) { wpa_printf(MSG_INFO, "TDLS: TPK M1 from diff BSS"); - status = WLAN_STATUS_NOT_IN_SAME_BSS; + status = WLAN_STATUS_REQUEST_DECLINED; goto error; } diff --git a/src/utils/common.c b/src/utils/common.c index 5b017e57..99020049 100644 --- a/src/utils/common.c +++ b/src/utils/common.c @@ -362,7 +362,7 @@ void printf_encode(char *txt, size_t maxlen, const u8 *data, size_t len) *txt++ = '\\'; *txt++ = '\\'; break; - case '\e': + case '\033': *txt++ = '\\'; *txt++ = 'e'; break; @@ -427,7 +427,7 @@ size_t printf_decode(u8 *buf, size_t maxlen, const char *str) pos++; break; case 'e': - buf[len++] = '\e'; + buf[len++] = '\033'; pos++; break; case 'x': @@ -846,3 +846,23 @@ void bin_clear_free(void *bin, size_t len) os_free(bin); } } + + +int random_mac_addr(u8 *addr) +{ + if (os_get_random(addr, ETH_ALEN) < 0) + return -1; + addr[0] &= 0xfe; /* unicast */ + addr[0] |= 0x02; /* locally administered */ + return 0; +} + + +int random_mac_addr_keep_oui(u8 *addr) +{ + if (os_get_random(addr + 3, 3) < 0) + return -1; + addr[0] &= 0xfe; /* unicast */ + addr[0] |= 0x02; /* locally administered */ + return 0; +} diff --git a/src/utils/common.h b/src/utils/common.h index 2bc8fe14..14d9ad1e 100644 --- a/src/utils/common.h +++ b/src/utils/common.h @@ -538,6 +538,9 @@ void int_array_add_unique(int **res, int a); void str_clear_free(char *str); void bin_clear_free(void *bin, size_t len); +int random_mac_addr(u8 *addr); +int random_mac_addr_keep_oui(u8 *addr); + /* * gcc 4.4 ends up generating strict-aliasing warnings about some very common diff --git a/src/utils/http_curl.c b/src/utils/http_curl.c index eb79b862..0c18269d 100644 --- a/src/utils/http_curl.c +++ b/src/utils/http_curl.c @@ -1099,7 +1099,6 @@ static int ocsp_resp_cb(SSL *s, void *arg) certs = NULL; } if (ctx->peer_issuer_issuer) { - X509 *cert; cert = X509_dup(ctx->peer_issuer_issuer); if (cert && !sk_X509_push(certs, cert)) { tls_show_errors( @@ -1178,9 +1177,10 @@ static int ocsp_resp_cb(SSL *s, void *arg) if (status == V_OCSP_CERTSTATUS_GOOD) return 1; - if (status == V_OCSP_CERTSTATUS_REVOKED) + if (status == V_OCSP_CERTSTATUS_REVOKED) { ctx->last_err = "Server certificate has been revoked"; return 0; + } if (ctx->ocsp == MANDATORY_OCSP) { wpa_printf(MSG_DEBUG, "OpenSSL: OCSP status unknown, but OCSP required"); ctx->last_err = "OCSP status unknown"; diff --git a/src/wps/wps_enrollee.c b/src/wps/wps_enrollee.c index f7d41b4d..9f5a90ce 100644 --- a/src/wps/wps_enrollee.c +++ b/src/wps/wps_enrollee.c @@ -175,6 +175,12 @@ static struct wpabuf * wps_build_m3(struct wps_data *wps) } wps_derive_psk(wps, wps->dev_password, wps->dev_password_len); + if (wps->wps->ap && random_pool_ready() != 1) { + wpa_printf(MSG_INFO, + "WPS: Not enough entropy in random pool to proceed - do not allow AP PIN to be used"); + return NULL; + } + msg = wpabuf_alloc(1000); if (msg == NULL) return NULL; @@ -268,8 +274,12 @@ static int wps_build_cred_network_key(struct wps_data *wps, struct wpabuf *msg) char hex[65]; u8 psk[32]; /* Generate a random per-device PSK */ - if (random_get_bytes(psk, sizeof(psk)) < 0) + if (random_pool_ready() != 1 || + random_get_bytes(psk, sizeof(psk)) < 0) { + wpa_printf(MSG_INFO, + "WPS: Could not generate random PSK"); return -1; + } wpa_hexdump_key(MSG_DEBUG, "WPS: Generated per-device PSK", psk, sizeof(psk)); wpa_printf(MSG_DEBUG, "WPS: * Network Key (len=%u)", diff --git a/src/wps/wps_registrar.c b/src/wps/wps_registrar.c index 00c8299a..b90cc25e 100644 --- a/src/wps/wps_registrar.c +++ b/src/wps/wps_registrar.c @@ -1640,8 +1640,12 @@ int wps_build_cred(struct wps_data *wps, struct wpabuf *msg) !wps->wps->registrar->disable_auto_conf) { u8 r[16]; /* Generate a random passphrase */ - if (random_get_bytes(r, sizeof(r)) < 0) + if (random_pool_ready() != 1 || + random_get_bytes(r, sizeof(r)) < 0) { + wpa_printf(MSG_INFO, + "WPS: Could not generate random PSK"); return -1; + } os_free(wps->new_psk); wps->new_psk = base64_encode(r, sizeof(r), &wps->new_psk_len); if (wps->new_psk == NULL) @@ -1674,7 +1678,10 @@ int wps_build_cred(struct wps_data *wps, struct wpabuf *msg) wps->new_psk = os_malloc(wps->new_psk_len); if (wps->new_psk == NULL) return -1; - if (random_get_bytes(wps->new_psk, wps->new_psk_len) < 0) { + if (random_pool_ready() != 1 || + random_get_bytes(wps->new_psk, wps->new_psk_len) < 0) { + wpa_printf(MSG_INFO, + "WPS: Could not generate random PSK"); os_free(wps->new_psk); wps->new_psk = NULL; return -1; -- cgit v1.2.3 From 9ead16e203b81d44a2d84eadc2901ceeb7daf805 Mon Sep 17 00:00:00 2001 From: Dmitry Shmidt Date: Tue, 7 Oct 2014 13:15:23 -0700 Subject: Cumulative patch from commit d5fe4e6c18d94465e8fb4527d51df6e8539c4d6a d5fe4e6 Reserve QCA vendor specific nl80211 commands 34..49 a256506 AES: Extend key wrap implementation to support longer data eefec1e AES: Extend key wrap design to support longer AES keys 98a1571 OpenSSL: Clean up one part from the BoringSSL patch a857296 Support building with BoringSSL 1236eda Android: Remove ctrl_interface=wlan0 from config template 9ffd512 Android: Set pmf=1 to default template 45d8501 Fix out of bounds memory access when removing vendor elements a61fcc1 Clean up authenticator PMKSA cache implementation cb129db Clear PMKSA cache entry data when freeing them 8c8d26a Remove unnecessary PMKSA cache freeing step 9c82990 Fix authenticator OKC fetch from PMKSA cache to avoid infinite loop 47ea24c Fix PMKSA cache timeout from Session-Timeout in WPA/WPA2 cases dc152f3 wpa_supplicant: Enable HT for IBSS 4ec6837 wpa_supplicant: Use hostapd_freq_params in assoc_params 43f02e6 wpa_ctrl: Update wpa_ctrl_recv() documentation for non-block behavior 1274ec2 dbus: Add an interface configuration entry to set the WPS methods 3e0272c nl80211: Re-read MAC address on RTM_NEWLINK 5dfbd72 nl80211: Add get_bss_ifindex() helper f1a6131 P2P: Use only the -m config for P2P management device 08d7665 TDLS: Use WMM IE for propagating peer WMM capability 17729b0 TDLS: Fix concurrent setup test for mac80211 drivers 984dadc TDLS: Set the initiator during tdls_mgmt operations 01cb5df Sync with wireless-testing.git include/uapi/linux/nl80211.h ca3c6b4 nl80211: Fix compatibility with older version of libnl d76426c TDLS: Filter AID value properly for VHT peers Change-Id: Ia2156628a590c502d9111de2727da642ff435d9a Signed-off-by: Dmitry Shmidt --- src/ap/ieee802_1x.c | 10 ++- src/ap/pmksa_cache_auth.c | 65 +++++++++-------- src/ap/sta_info.h | 3 + src/ap/wpa_auth.c | 3 +- src/ap/wpa_auth_ft.c | 22 +++--- src/common/qca-vendor.h | 2 +- src/common/wpa_ctrl.h | 7 +- src/crypto/aes-unwrap.c | 19 +++-- src/crypto/aes-wrap.c | 20 ++++-- src/crypto/aes_wrap.h | 8 ++- src/crypto/crypto_openssl.c | 8 ++- src/crypto/tls_openssl.c | 34 +++++++-- src/drivers/driver.h | 47 ++++++------ src/drivers/driver_nl80211.c | 88 ++++++++++++++++------- src/drivers/driver_test.c | 2 +- src/drivers/driver_wext.c | 3 +- src/drivers/nl80211_copy.h | 150 +++++++++++++++++++++++++++++++++++++-- src/eap_common/eap_pwd_common.c | 2 + src/eap_server/eap_server_fast.c | 8 +-- src/pae/ieee802_1x_kay.c | 4 +- src/rsn_supp/pmksa_cache.c | 2 +- src/rsn_supp/tdls.c | 56 ++++++++++----- src/rsn_supp/wpa.c | 5 +- src/rsn_supp/wpa.h | 4 +- src/rsn_supp/wpa_ft.c | 5 +- src/rsn_supp/wpa_i.h | 14 ++-- src/rsn_supp/wpa_ie.c | 2 +- 27 files changed, 430 insertions(+), 163 deletions(-) (limited to 'src') diff --git a/src/ap/ieee802_1x.c b/src/ap/ieee802_1x.c index e4681e90..2d09b67b 100644 --- a/src/ap/ieee802_1x.c +++ b/src/ap/ieee802_1x.c @@ -1622,6 +1622,9 @@ ieee802_1x_receive_auth(struct radius_msg *msg, struct radius_msg *req, if (ap_sta_bind_vlan(hapd, sta, old_vlanid) < 0) break; + sta->session_timeout_set = !!session_timeout_set; + sta->session_timeout = session_timeout; + /* RFC 3580, Ch. 3.17 */ if (session_timeout_set && termination_action == RADIUS_TERMINATION_ACTION_RADIUS_REQUEST) { @@ -2396,6 +2399,7 @@ static void ieee802_1x_finished(struct hostapd_data *hapd, size_t len; /* TODO: get PMKLifetime from WPA parameters */ static const int dot11RSNAConfigPMKLifetime = 43200; + unsigned int session_timeout; #ifdef CONFIG_HS20 if (remediation && !sta->remediation) { @@ -2430,9 +2434,13 @@ static void ieee802_1x_finished(struct hostapd_data *hapd, #endif /* CONFIG_HS20 */ key = ieee802_1x_get_key(sta->eapol_sm, &len); + if (sta->session_timeout_set) + session_timeout = sta->session_timeout; + else + session_timeout = dot11RSNAConfigPMKLifetime; if (success && key && len >= PMK_LEN && !sta->remediation && !sta->hs20_deauth_requested && - wpa_auth_pmksa_add(sta->wpa_sm, key, dot11RSNAConfigPMKLifetime, + wpa_auth_pmksa_add(sta->wpa_sm, key, session_timeout, sta->eapol_sm) == 0) { hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_WPA, HOSTAPD_LEVEL_DEBUG, diff --git a/src/ap/pmksa_cache_auth.c b/src/ap/pmksa_cache_auth.c index 4720b59c..9de4cffe 100644 --- a/src/ap/pmksa_cache_auth.c +++ b/src/ap/pmksa_cache_auth.c @@ -37,14 +37,12 @@ static void pmksa_cache_set_expiration(struct rsn_pmksa_cache *pmksa); static void _pmksa_cache_free_entry(struct rsn_pmksa_cache_entry *entry) { - if (entry == NULL) - return; os_free(entry->identity); wpabuf_free(entry->cui); #ifndef CONFIG_NO_RADIUS radius_free_class(&entry->radius_class); #endif /* CONFIG_NO_RADIUS */ - os_free(entry); + bin_clear_free(entry, sizeof(*entry)); } @@ -52,38 +50,42 @@ void pmksa_cache_free_entry(struct rsn_pmksa_cache *pmksa, struct rsn_pmksa_cache_entry *entry) { struct rsn_pmksa_cache_entry *pos, *prev; + unsigned int hash; pmksa->pmksa_count--; pmksa->free_cb(entry, pmksa->ctx); - pos = pmksa->pmkid[PMKID_HASH(entry->pmkid)]; + + /* unlink from hash list */ + hash = PMKID_HASH(entry->pmkid); + pos = pmksa->pmkid[hash]; prev = NULL; while (pos) { if (pos == entry) { - if (prev != NULL) { - prev->hnext = pos->hnext; - } else { - pmksa->pmkid[PMKID_HASH(entry->pmkid)] = - pos->hnext; - } + if (prev != NULL) + prev->hnext = entry->hnext; + else + pmksa->pmkid[hash] = entry->hnext; break; } prev = pos; pos = pos->hnext; } + /* unlink from entry list */ pos = pmksa->pmksa; prev = NULL; while (pos) { if (pos == entry) { if (prev != NULL) - prev->next = pos->next; + prev->next = entry->next; else - pmksa->pmksa = pos->next; + pmksa->pmksa = entry->next; break; } prev = pos; pos = pos->next; } + _pmksa_cache_free_entry(entry); } @@ -188,6 +190,7 @@ static void pmksa_cache_link_entry(struct rsn_pmksa_cache *pmksa, struct rsn_pmksa_cache_entry *entry) { struct rsn_pmksa_cache_entry *pos, *prev; + int hash; /* Add the new entry; order by expiration time */ pos = pmksa->pmksa; @@ -205,8 +208,10 @@ static void pmksa_cache_link_entry(struct rsn_pmksa_cache *pmksa, entry->next = prev->next; prev->next = entry; } - entry->hnext = pmksa->pmkid[PMKID_HASH(entry->pmkid)]; - pmksa->pmkid[PMKID_HASH(entry->pmkid)] = entry; + + hash = PMKID_HASH(entry->pmkid); + entry->hnext = pmksa->pmkid[hash]; + pmksa->pmkid[hash] = entry; pmksa->pmksa_count++; if (prev == NULL) @@ -342,6 +347,8 @@ void pmksa_cache_auth_deinit(struct rsn_pmksa_cache *pmksa) _pmksa_cache_free_entry(prev); } eloop_cancel_timeout(pmksa_cache_expire, pmksa, NULL); + pmksa->pmksa_count = 0; + pmksa->pmksa = NULL; for (i = 0; i < PMKID_HASH_SIZE; i++) pmksa->pmkid[i] = NULL; os_free(pmksa); @@ -361,18 +368,22 @@ pmksa_cache_auth_get(struct rsn_pmksa_cache *pmksa, { struct rsn_pmksa_cache_entry *entry; - if (pmkid) - entry = pmksa->pmkid[PMKID_HASH(pmkid)]; - else - entry = pmksa->pmksa; - while (entry) { - if ((spa == NULL || - os_memcmp(entry->spa, spa, ETH_ALEN) == 0) && - (pmkid == NULL || - os_memcmp(entry->pmkid, pmkid, PMKID_LEN) == 0)) - return entry; - entry = pmkid ? entry->hnext : entry->next; + if (pmkid) { + for (entry = pmksa->pmkid[PMKID_HASH(pmkid)]; entry; + entry = entry->hnext) { + if ((spa == NULL || + os_memcmp(entry->spa, spa, ETH_ALEN) == 0) && + os_memcmp(entry->pmkid, pmkid, PMKID_LEN) == 0) + return entry; + } + } else { + for (entry = pmksa->pmksa; entry; entry = entry->next) { + if (spa == NULL || + os_memcmp(entry->spa, spa, ETH_ALEN) == 0) + return entry; + } } + return NULL; } @@ -394,15 +405,13 @@ struct rsn_pmksa_cache_entry * pmksa_cache_get_okc( struct rsn_pmksa_cache_entry *entry; u8 new_pmkid[PMKID_LEN]; - entry = pmksa->pmksa; - while (entry) { + for (entry = pmksa->pmksa; entry; entry = entry->next) { if (os_memcmp(entry->spa, spa, ETH_ALEN) != 0) continue; rsn_pmkid(entry->pmk, entry->pmk_len, aa, spa, new_pmkid, wpa_key_mgmt_sha256(entry->akmp)); if (os_memcmp(new_pmkid, pmkid, PMKID_LEN) == 0) return entry; - entry = entry->next; } return NULL; } diff --git a/src/ap/sta_info.h b/src/ap/sta_info.h index 03db98f6..faf32d85 100644 --- a/src/ap/sta_info.h +++ b/src/ap/sta_info.h @@ -60,6 +60,7 @@ struct sta_info { unsigned int qos_map_enabled:1; unsigned int remediation:1; unsigned int hs20_deauth_requested:1; + unsigned int session_timeout_set:1; u16 auth_alg; @@ -135,6 +136,8 @@ struct sta_info { #ifdef CONFIG_SAE struct sae_data *sae; #endif /* CONFIG_SAE */ + + u32 session_timeout; /* valid only if session_timeout_set == 1 */ }; diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c index 2bb8aab8..1a16b5c8 100644 --- a/src/ap/wpa_auth.c +++ b/src/ap/wpa_auth.c @@ -1390,7 +1390,8 @@ void __wpa_send_eapol(struct wpa_authenticator *wpa_auth, if (version == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES || sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN || version == WPA_KEY_INFO_TYPE_AES_128_CMAC) { - if (aes_wrap(sm->PTK.kek, (key_data_len - 8) / 8, buf, + if (aes_wrap(sm->PTK.kek, 16, + (key_data_len - 8) / 8, buf, (u8 *) (key + 1))) { os_free(hdr); os_free(buf); diff --git a/src/ap/wpa_auth_ft.c b/src/ap/wpa_auth_ft.c index 8a6ca71c..781f15fb 100644 --- a/src/ap/wpa_auth_ft.c +++ b/src/ap/wpa_auth_ft.c @@ -344,7 +344,8 @@ static int wpa_ft_pull_pmk_r1(struct wpa_state_machine *sm, os_memcpy(f.s1kh_id, sm->addr, ETH_ALEN); os_memset(f.pad, 0, sizeof(f.pad)); - if (aes_wrap(r0kh->key, (FT_R0KH_R1KH_PULL_DATA_LEN + 7) / 8, + if (aes_wrap(r0kh->key, sizeof(r0kh->key), + (FT_R0KH_R1KH_PULL_DATA_LEN + 7) / 8, f.nonce, frame.nonce) < 0) return -1; @@ -459,7 +460,7 @@ static u8 * wpa_ft_gtk_subelem(struct wpa_state_machine *sm, size_t *len) WPA_PUT_LE16(&subelem[2], gsm->GN & 0x03); subelem[4] = gsm->GTK_len; wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN, subelem + 5); - if (aes_wrap(sm->PTK.kek, key_len / 8, key, subelem + 13)) { + if (aes_wrap(sm->PTK.kek, 16, key_len / 8, key, subelem + 13)) { os_free(subelem); return NULL; } @@ -491,7 +492,7 @@ static u8 * wpa_ft_igtk_subelem(struct wpa_state_machine *sm, size_t *len) wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN_igtk, pos); pos += 6; *pos++ = WPA_IGTK_LEN; - if (aes_wrap(sm->PTK.kek, WPA_IGTK_LEN / 8, + if (aes_wrap(sm->PTK.kek, 16, WPA_IGTK_LEN / 8, gsm->IGTK[gsm->GN_igtk - 4], pos)) { os_free(subelem); return NULL; @@ -1336,7 +1337,8 @@ static int wpa_ft_rrb_rx_pull(struct wpa_authenticator *wpa_auth, frame = (struct ft_r0kh_r1kh_pull_frame *) data; /* aes_unwrap() does not support inplace decryption, so use a temporary * buffer for the data. */ - if (aes_unwrap(r1kh->key, (FT_R0KH_R1KH_PULL_DATA_LEN + 7) / 8, + if (aes_unwrap(r1kh->key, sizeof(r1kh->key), + (FT_R0KH_R1KH_PULL_DATA_LEN + 7) / 8, frame->nonce, f.nonce) < 0) { wpa_printf(MSG_DEBUG, "FT: Failed to decrypt PMK-R1 pull " "request from " MACSTR, MAC2STR(src_addr)); @@ -1376,7 +1378,8 @@ static int wpa_ft_rrb_rx_pull(struct wpa_authenticator *wpa_auth, r.pairwise = host_to_le16(pairwise); os_memset(r.pad, 0, sizeof(r.pad)); - if (aes_wrap(r1kh->key, (FT_R0KH_R1KH_RESP_DATA_LEN + 7) / 8, + if (aes_wrap(r1kh->key, sizeof(r1kh->key), + (FT_R0KH_R1KH_RESP_DATA_LEN + 7) / 8, r.nonce, resp.nonce) < 0) { os_memset(pmk_r0, 0, PMK_LEN); return -1; @@ -1464,7 +1467,8 @@ static int wpa_ft_rrb_rx_resp(struct wpa_authenticator *wpa_auth, frame = (struct ft_r0kh_r1kh_resp_frame *) data; /* aes_unwrap() does not support inplace decryption, so use a temporary * buffer for the data. */ - if (aes_unwrap(r0kh->key, (FT_R0KH_R1KH_RESP_DATA_LEN + 7) / 8, + if (aes_unwrap(r0kh->key, sizeof(r0kh->key), + (FT_R0KH_R1KH_RESP_DATA_LEN + 7) / 8, frame->nonce, f.nonce) < 0) { wpa_printf(MSG_DEBUG, "FT: Failed to decrypt PMK-R1 pull " "response from " MACSTR, MAC2STR(src_addr)); @@ -1530,7 +1534,8 @@ static int wpa_ft_rrb_rx_push(struct wpa_authenticator *wpa_auth, frame = (struct ft_r0kh_r1kh_push_frame *) data; /* aes_unwrap() does not support inplace decryption, so use a temporary * buffer for the data. */ - if (aes_unwrap(r0kh->key, (FT_R0KH_R1KH_PUSH_DATA_LEN + 7) / 8, + if (aes_unwrap(r0kh->key, sizeof(r0kh->key), + (FT_R0KH_R1KH_PUSH_DATA_LEN + 7) / 8, frame->timestamp, f.timestamp) < 0) { wpa_printf(MSG_DEBUG, "FT: Failed to decrypt PMK-R1 push from " MACSTR, MAC2STR(src_addr)); @@ -1727,7 +1732,8 @@ static void wpa_ft_generate_pmk_r1(struct wpa_authenticator *wpa_auth, WPA_PUT_LE32(f.timestamp, now.sec); f.pairwise = host_to_le16(pairwise); os_memset(f.pad, 0, sizeof(f.pad)); - if (aes_wrap(r1kh->key, (FT_R0KH_R1KH_PUSH_DATA_LEN + 7) / 8, + if (aes_wrap(r1kh->key, sizeof(r1kh->key), + (FT_R0KH_R1KH_PUSH_DATA_LEN + 7) / 8, f.timestamp, frame.timestamp) < 0) return; diff --git a/src/common/qca-vendor.h b/src/common/qca-vendor.h index de0b222b..ad3bdfd6 100644 --- a/src/common/qca-vendor.h +++ b/src/common/qca-vendor.h @@ -60,7 +60,7 @@ enum qca_nl80211_vendor_subcmds { QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY = 11, QCA_NL80211_VENDOR_SUBCMD_NAN = 12, QCA_NL80211_VENDOR_SUBMCD_STATS_EXT = 13, - /* 14..33 - reserved for QCA */ + /* 14..49 - reserved for QCA */ }; diff --git a/src/common/wpa_ctrl.h b/src/common/wpa_ctrl.h index d91594e3..4812f8df 100644 --- a/src/common/wpa_ctrl.h +++ b/src/common/wpa_ctrl.h @@ -345,9 +345,10 @@ int wpa_ctrl_detach(struct wpa_ctrl *ctrl); * @reply_len: Length of the reply buffer * Returns: 0 on success, -1 on failure * - * This function will receive a pending control interface message. This - * function will block if no messages are available. The received response will - * be written to reply and reply_len is set to the actual length of the reply. + * This function will receive a pending control interface message. The received + * response will be written to reply and reply_len is set to the actual length + * of the reply. + * wpa_ctrl_recv() is only used for event messages, i.e., wpa_ctrl_attach() * must have been used to register the control interface as an event monitor. */ diff --git a/src/crypto/aes-unwrap.c b/src/crypto/aes-unwrap.c index 9dd51602..ec793d9d 100644 --- a/src/crypto/aes-unwrap.c +++ b/src/crypto/aes-unwrap.c @@ -1,5 +1,5 @@ /* - * AES key unwrap (128-bit KEK, RFC3394) + * AES key unwrap (RFC3394) * * Copyright (c) 2003-2007, Jouni Malinen * @@ -14,26 +14,29 @@ #include "aes_wrap.h" /** - * aes_unwrap - Unwrap key with AES Key Wrap Algorithm (128-bit KEK) (RFC3394) + * aes_unwrap - Unwrap key with AES Key Wrap Algorithm (RFC3394) * @kek: Key encryption key (KEK) + * @kek_len: Length of KEK in octets * @n: Length of the plaintext key in 64-bit units; e.g., 2 = 128-bit = 16 * bytes * @cipher: Wrapped key to be unwrapped, (n + 1) * 64 bits * @plain: Plaintext key, n * 64 bits * Returns: 0 on success, -1 on failure (e.g., integrity verification failed) */ -int aes_unwrap(const u8 *kek, int n, const u8 *cipher, u8 *plain) +int aes_unwrap(const u8 *kek, size_t kek_len, int n, const u8 *cipher, + u8 *plain) { - u8 a[8], *r, b[16]; + u8 a[8], *r, b[AES_BLOCK_SIZE]; int i, j; void *ctx; + unsigned int t; /* 1) Initialize variables. */ os_memcpy(a, cipher, 8); r = plain; os_memcpy(r, cipher + 8, 8 * n); - ctx = aes_decrypt_init(kek, 16); + ctx = aes_decrypt_init(kek, kek_len); if (ctx == NULL) return -1; @@ -48,7 +51,11 @@ int aes_unwrap(const u8 *kek, int n, const u8 *cipher, u8 *plain) r = plain + (n - 1) * 8; for (i = n; i >= 1; i--) { os_memcpy(b, a, 8); - b[7] ^= n * j + i; + t = n * j + i; + b[7] ^= t; + b[6] ^= t >> 8; + b[5] ^= t >> 16; + b[4] ^= t >> 24; os_memcpy(b + 8, r, 8); aes_decrypt(ctx, b, b); diff --git a/src/crypto/aes-wrap.c b/src/crypto/aes-wrap.c index 89d6f94b..7ed34e80 100644 --- a/src/crypto/aes-wrap.c +++ b/src/crypto/aes-wrap.c @@ -1,5 +1,5 @@ /* - * AES Key Wrap Algorithm (128-bit KEK) (RFC3394) + * AES Key Wrap Algorithm (RFC3394) * * Copyright (c) 2003-2007, Jouni Malinen * @@ -14,19 +14,21 @@ #include "aes_wrap.h" /** - * aes_wrap - Wrap keys with AES Key Wrap Algorithm (128-bit KEK) (RFC3394) - * @kek: 16-octet Key encryption key (KEK) + * aes_wrap - Wrap keys with AES Key Wrap Algorithm (RFC3394) + * @kek: Key encryption key (KEK) + * @kek_len: Length of KEK in octets * @n: Length of the plaintext key in 64-bit units; e.g., 2 = 128-bit = 16 * bytes * @plain: Plaintext key to be wrapped, n * 64 bits * @cipher: Wrapped key, (n + 1) * 64 bits * Returns: 0 on success, -1 on failure */ -int aes_wrap(const u8 *kek, int n, const u8 *plain, u8 *cipher) +int aes_wrap(const u8 *kek, size_t kek_len, int n, const u8 *plain, u8 *cipher) { - u8 *a, *r, b[16]; + u8 *a, *r, b[AES_BLOCK_SIZE]; int i, j; void *ctx; + unsigned int t; a = cipher; r = cipher + 8; @@ -35,7 +37,7 @@ int aes_wrap(const u8 *kek, int n, const u8 *plain, u8 *cipher) os_memset(a, 0xa6, 8); os_memcpy(r, plain, 8 * n); - ctx = aes_encrypt_init(kek, 16); + ctx = aes_encrypt_init(kek, kek_len); if (ctx == NULL) return -1; @@ -53,7 +55,11 @@ int aes_wrap(const u8 *kek, int n, const u8 *plain, u8 *cipher) os_memcpy(b + 8, r, 8); aes_encrypt(ctx, b, b); os_memcpy(a, b, 8); - a[7] ^= n * j + i; + t = n * j + i; + a[7] ^= t; + a[6] ^= t >> 8; + a[5] ^= t >> 16; + a[4] ^= t >> 24; os_memcpy(r, b + 8, 8); r += 8; } diff --git a/src/crypto/aes_wrap.h b/src/crypto/aes_wrap.h index 0433c043..6b3727c7 100644 --- a/src/crypto/aes_wrap.h +++ b/src/crypto/aes_wrap.h @@ -1,7 +1,7 @@ /* * AES-based functions * - * - AES Key Wrap Algorithm (128-bit KEK) (RFC3394) + * - AES Key Wrap Algorithm (RFC3394) * - One-Key CBC MAC (OMAC1) hash with AES-128 * - AES-128 CTR mode encryption * - AES-128 EAX mode encryption/decryption @@ -18,8 +18,10 @@ #ifndef AES_WRAP_H #define AES_WRAP_H -int __must_check aes_wrap(const u8 *kek, int n, const u8 *plain, u8 *cipher); -int __must_check aes_unwrap(const u8 *kek, int n, const u8 *cipher, u8 *plain); +int __must_check aes_wrap(const u8 *kek, size_t kek_len, int n, const u8 *plain, + u8 *cipher); +int __must_check aes_unwrap(const u8 *kek, size_t kek_len, int n, + const u8 *cipher, u8 *plain); int __must_check omac1_aes_128_vector(const u8 *key, size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac); diff --git a/src/crypto/crypto_openssl.c b/src/crypto/crypto_openssl.c index 8876ebf2..b4c59d18 100644 --- a/src/crypto/crypto_openssl.c +++ b/src/crypto/crypto_openssl.c @@ -40,7 +40,7 @@ static BIGNUM * get_group5_prime(void) { -#if OPENSSL_VERSION_NUMBER < 0x00908000 +#if OPENSSL_VERSION_NUMBER < 0x00908000 || defined(OPENSSL_IS_BORINGSSL) static const unsigned char RFC3526_PRIME_1536[] = { 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC9,0x0F,0xDA,0xA2, 0x21,0x68,0xC2,0x34,0xC4,0xC6,0x62,0x8B,0x80,0xDC,0x1C,0xD1, @@ -130,7 +130,7 @@ void des_encrypt(const u8 *clear, const u8 *key, u8 *cypher) } pkey[i] = next | 1; - DES_set_key(&pkey, &ks); + DES_set_key((DES_cblock *) &pkey, &ks); DES_ecb_encrypt((DES_cblock *) clear, (DES_cblock *) cypher, &ks, DES_ENCRYPT); } @@ -199,8 +199,10 @@ static const EVP_CIPHER * aes_get_evp_cipher(size_t keylen) switch (keylen) { case 16: return EVP_aes_128_ecb(); +#ifndef OPENSSL_IS_BORINGSSL case 24: return EVP_aes_192_ecb(); +#endif /* OPENSSL_IS_BORINGSSL */ case 32: return EVP_aes_256_ecb(); } @@ -378,9 +380,11 @@ struct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg, case 16: cipher = EVP_aes_128_cbc(); break; +#ifndef OPENSSL_IS_BORINGSSL case 24: cipher = EVP_aes_192_cbc(); break; +#endif /* OPENSSL_IS_BORINGSSL */ case 32: cipher = EVP_aes_256_cbc(); break; diff --git a/src/crypto/tls_openssl.c b/src/crypto/tls_openssl.c index d2d66003..e1534224 100644 --- a/src/crypto/tls_openssl.c +++ b/src/crypto/tls_openssl.c @@ -38,14 +38,26 @@ #define OPENSSL_SUPPORTS_CTX_APP_DATA #endif -#ifdef SSL_F_SSL_SET_SESSION_TICKET_EXT -#ifdef SSL_OP_NO_TICKET +#if OPENSSL_VERSION_NUMBER < 0x10000000L +/* ERR_remove_thread_state replaces ERR_remove_state and the latter is + * deprecated. However, OpenSSL 0.9.8 doesn't include + * ERR_remove_thread_state. */ +#define ERR_remove_thread_state(tid) ERR_remove_state(0) +#endif + +#if OPENSSL_VERSION_NUMBER >= 0x10000000L /* * Session ticket override patch was merged into OpenSSL 0.9.9 tree on * 2008-11-15. This version uses a bit different API compared to the old patch. */ #define CONFIG_OPENSSL_TICKET_OVERRIDE #endif + +#if defined(OPENSSL_IS_BORINGSSL) +/* stack_index_t is the return type of OpenSSL's sk_XXX_num() functions. */ +typedef size_t stack_index_t; +#else +typedef int stack_index_t; #endif #ifdef SSL_set_tlsext_status_type @@ -853,7 +865,7 @@ void tls_deinit(void *ssl_ctx) ENGINE_cleanup(); #endif /* OPENSSL_NO_ENGINE */ CRYPTO_cleanup_all_ex_data(); - ERR_remove_state(0); + ERR_remove_thread_state(NULL); ERR_free_strings(); EVP_cleanup(); os_free(tls_global->ocsp_stapling_response); @@ -1102,7 +1114,8 @@ static int tls_match_altsubject_component(X509 *cert, int type, { GENERAL_NAME *gen; void *ext; - int i, found = 0; + int found = 0; + stack_index_t i; ext = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL); @@ -1204,6 +1217,7 @@ static int tls_match_suffix(X509 *cert, const char *match) GENERAL_NAME *gen; void *ext; int i; + stack_index_t j; int dns_name = 0; X509_NAME *name; @@ -1211,8 +1225,8 @@ static int tls_match_suffix(X509 *cert, const char *match) ext = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL); - for (i = 0; ext && i < sk_GENERAL_NAME_num(ext); i++) { - gen = sk_GENERAL_NAME_value(ext, i); + for (j = 0; ext && j < sk_GENERAL_NAME_num(ext); j++) { + gen = sk_GENERAL_NAME_value(ext, j); if (gen->type != GEN_DNS) continue; dns_name++; @@ -1639,7 +1653,7 @@ static int tls_connection_ca_cert(void *_ssl_ctx, struct tls_connection *conn, if (ca_cert && os_strncmp("keystore://", ca_cert, 11) == 0) { BIO *bio = BIO_from_keystore(&ca_cert[11]); STACK_OF(X509_INFO) *stack = NULL; - int i; + stack_index_t i; if (bio) { stack = PEM_X509_INFO_read_bio(bio, NULL, NULL, NULL); @@ -3386,9 +3400,15 @@ unsigned int tls_capabilities(void *tls_ctx) * commented out unless explicitly needed for EAP-FAST in order to be able to * build this file with unmodified openssl. */ +#ifdef OPENSSL_IS_BORINGSSL +static int tls_sess_sec_cb(SSL *s, void *secret, int *secret_len, + STACK_OF(SSL_CIPHER) *peer_ciphers, + const SSL_CIPHER **cipher, void *arg) +#else /* OPENSSL_IS_BORINGSSL */ static int tls_sess_sec_cb(SSL *s, void *secret, int *secret_len, STACK_OF(SSL_CIPHER) *peer_ciphers, SSL_CIPHER **cipher, void *arg) +#endif /* OPENSSL_IS_BORINGSSL */ { struct tls_connection *conn = arg; int ret; diff --git a/src/drivers/driver.h b/src/drivers/driver.h index 501314bb..6af72943 100644 --- a/src/drivers/driver.h +++ b/src/drivers/driver.h @@ -411,6 +411,25 @@ enum wps_mode { */ }; +struct hostapd_freq_params { + int mode; + int freq; + int channel; + /* for HT */ + int ht_enabled; + int sec_channel_offset; /* 0 = HT40 disabled, -1 = HT40 enabled, + * secondary channel below primary, 1 = HT40 + * enabled, secondary channel above primary */ + + /* for VHT */ + int vht_enabled; + + /* valid for both HT and VHT, center_freq2 is non-zero + * only for bandwidth 80 and an 80+80 channel */ + int center_freq1, center_freq2; + int bandwidth; +}; + /** * struct wpa_driver_associate_params - Association parameters * Data for struct wpa_driver_ops::associate(). @@ -443,11 +462,9 @@ struct wpa_driver_associate_params { size_t ssid_len; /** - * freq - Frequency of the channel the selected AP is using - * Frequency that the selected AP is using (in MHz as - * reported in the scan results) + * freq - channel parameters */ - int freq; + struct hostapd_freq_params freq; /** * freq_hint - Frequency of the channel the proposed AP is using @@ -1091,25 +1108,6 @@ struct hostapd_sta_add_params { size_t supp_oper_classes_len; }; -struct hostapd_freq_params { - int mode; - int freq; - int channel; - /* for HT */ - int ht_enabled; - int sec_channel_offset; /* 0 = HT40 disabled, -1 = HT40 enabled, - * secondary channel below primary, 1 = HT40 - * enabled, secondary channel above primary */ - - /* for VHT */ - int vht_enabled; - - /* valid for both HT and VHT, center_freq2 is non-zero - * only for bandwidth 80 and an 80+80 channel */ - int center_freq1, center_freq2; - int bandwidth; -}; - struct mac_address { u8 addr[ETH_ALEN]; }; @@ -2503,6 +2501,7 @@ struct wpa_driver_ops { * @dialog_token: Dialog Token to use in the message (if needed) * @status_code: Status Code or Reason Code to use (if needed) * @peer_capab: TDLS peer capability (TDLS_PEER_* bitfield) + * @initiator: Is the current end the TDLS link initiator * @buf: TDLS IEs to add to the message * @len: Length of buf in octets * Returns: 0 on success, negative (<0) on failure @@ -2512,7 +2511,7 @@ struct wpa_driver_ops { */ int (*send_tdls_mgmt)(void *priv, const u8 *dst, u8 action_code, u8 dialog_token, u16 status_code, u32 peer_capab, - const u8 *buf, size_t len); + int initiator, const u8 *buf, size_t len); /** * tdls_oper - Ask the driver to perform high-level TDLS operations diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index 5c922a05..d0304743 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -331,7 +331,7 @@ struct wpa_driver_nl80211_data { int eapol_sock; /* socket for EAPOL frames */ - struct nl_sock *rtnl_sk; /* nl_sock for NETLINK_ROUTE */ + struct nl_handle *rtnl_sk; /* nl_sock for NETLINK_ROUTE */ int default_if_indices[16]; int *if_indices; @@ -358,7 +358,8 @@ static void wpa_driver_nl80211_scan_timeout(void *eloop_ctx, void *timeout_ctx); static int wpa_driver_nl80211_set_mode(struct i802_bss *bss, enum nl80211_iftype nlmode); -static int wpa_driver_nl80211_set_mode_ibss(struct i802_bss *bss, int freq); +static int wpa_driver_nl80211_set_mode_ibss(struct i802_bss *bss, + struct hostapd_freq_params *freq); static int wpa_driver_nl80211_finish_drv_init(struct wpa_driver_nl80211_data *drv, @@ -588,6 +589,20 @@ static int is_p2p_net_interface(enum nl80211_iftype nlmode) } +static struct i802_bss * get_bss_ifindex(struct wpa_driver_nl80211_data *drv, + int ifindex) +{ + struct i802_bss *bss; + + for (bss = drv->first_bss; bss; bss = bss->next) { + if (bss->ifindex == ifindex) + return bss; + } + + return NULL; +} + + static void nl80211_mark_disconnected(struct wpa_driver_nl80211_data *drv) { if (drv->associated) @@ -1306,6 +1321,28 @@ static void wpa_driver_nl80211_event_rtm_newlink(void *ctx, "event since interface %s is marked " "removed", drv->first_bss->ifname); } else { + struct i802_bss *bss; + u8 addr[ETH_ALEN]; + + /* Re-read MAC address as it may have changed */ + bss = get_bss_ifindex(drv, ifi->ifi_index); + if (bss && + linux_get_ifhwaddr(drv->global->ioctl_sock, + bss->ifname, addr) < 0) { + wpa_printf(MSG_DEBUG, + "nl80211: %s: failed to re-read MAC address", + bss->ifname); + } else if (bss && + os_memcmp(addr, bss->addr, ETH_ALEN) != 0) { + wpa_printf(MSG_DEBUG, + "nl80211: Own MAC address on ifindex %d (%s) changed from " + MACSTR " to " MACSTR, + ifi->ifi_index, bss->ifname, + MAC2STR(bss->addr), + MAC2STR(addr)); + os_memcpy(bss->addr, addr, ETH_ALEN); + } + wpa_printf(MSG_DEBUG, "nl80211: Interface up"); drv->if_disabled = 0; wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_ENABLED, @@ -1688,10 +1725,7 @@ static void mlme_event_ch_switch(struct wpa_driver_nl80211_data *drv, return; ifidx = nla_get_u32(ifindex); - for (bss = drv->first_bss; bss; bss = bss->next) - if (bss->ifindex == ifidx) - break; - + bss = get_bss_ifindex(drv, ifidx); if (bss == NULL) { wpa_printf(MSG_WARNING, "nl80211: Unknown ifindex (%d) for channel switch, ignoring", ifidx); @@ -4938,7 +4972,7 @@ static void wpa_driver_nl80211_deinit(struct i802_bss *bss) "interface %s from bridge %s: %s", bss->ifname, bss->brname, strerror(errno)); if (drv->rtnl_sk) - nl_socket_free(drv->rtnl_sk); + nl80211_handle_destroy(drv->rtnl_sk); } if (bss->added_bridge) { if (linux_br_del(drv->global->ioctl_sock, bss->brname) < 0) @@ -8648,9 +8682,6 @@ static int wpa_driver_nl80211_ap(struct wpa_driver_nl80211_data *drv, struct wpa_driver_associate_params *params) { enum nl80211_iftype nlmode, old_mode; - struct hostapd_freq_params freq = { - .freq = params->freq, - }; if (params->p2p) { wpa_printf(MSG_DEBUG, "nl80211: Setup AP operations for P2P " @@ -8665,7 +8696,7 @@ static int wpa_driver_nl80211_ap(struct wpa_driver_nl80211_data *drv, return -1; } - if (nl80211_set_channel(drv->first_bss, &freq, 0)) { + if (nl80211_set_channel(drv->first_bss, ¶ms->freq, 0)) { if (old_mode != nlmode) wpa_driver_nl80211_set_mode(drv->first_bss, old_mode); nl80211_remove_monitor_interface(drv); @@ -8719,7 +8750,7 @@ static int wpa_driver_nl80211_ibss(struct wpa_driver_nl80211_data *drv, wpa_printf(MSG_DEBUG, "nl80211: Join IBSS (ifindex=%d)", drv->ifindex); - if (wpa_driver_nl80211_set_mode_ibss(drv->first_bss, params->freq)) { + if (wpa_driver_nl80211_set_mode_ibss(drv->first_bss, ¶ms->freq)) { wpa_printf(MSG_INFO, "nl80211: Failed to set interface into " "IBSS mode"); return -1; @@ -8743,8 +8774,16 @@ retry: os_memcpy(drv->ssid, params->ssid, params->ssid_len); drv->ssid_len = params->ssid_len; - wpa_printf(MSG_DEBUG, " * freq=%d", params->freq); - NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, params->freq); + wpa_printf(MSG_DEBUG, " * freq=%d", params->freq.freq); + wpa_printf(MSG_DEBUG, " * ht_enabled=%d", params->freq.ht_enabled); + wpa_printf(MSG_DEBUG, " * sec_channel_offset=%d", + params->freq.sec_channel_offset); + wpa_printf(MSG_DEBUG, " * vht_enabled=%d", params->freq.vht_enabled); + wpa_printf(MSG_DEBUG, " * center_freq1=%d", params->freq.center_freq1); + wpa_printf(MSG_DEBUG, " * center_freq2=%d", params->freq.center_freq2); + wpa_printf(MSG_DEBUG, " * bandwidth=%d", params->freq.bandwidth); + if (nl80211_put_freq_params(msg, ¶ms->freq) < 0) + goto nla_put_failure; if (params->beacon_int > 0) { wpa_printf(MSG_DEBUG, " * beacon_int=%d", params->beacon_int); @@ -8822,10 +8861,10 @@ static int nl80211_connect_common(struct wpa_driver_nl80211_data *drv, params->bssid_hint); } - if (params->freq) { - wpa_printf(MSG_DEBUG, " * freq=%d", params->freq); - NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, params->freq); - drv->assoc_freq = params->freq; + if (params->freq.freq) { + wpa_printf(MSG_DEBUG, " * freq=%d", params->freq.freq); + NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, params->freq.freq); + drv->assoc_freq = params->freq.freq; } else drv->assoc_freq = 0; @@ -9316,13 +9355,11 @@ static int wpa_driver_nl80211_set_mode(struct i802_bss *bss, } -static int wpa_driver_nl80211_set_mode_ibss(struct i802_bss *bss, int freq) +static int wpa_driver_nl80211_set_mode_ibss(struct i802_bss *bss, + struct hostapd_freq_params *freq) { - struct hostapd_freq_params freq_params; - os_memset(&freq_params, 0, sizeof(freq_params)); - freq_params.freq = freq; return wpa_driver_nl80211_set_mode_impl(bss, NL80211_IFTYPE_ADHOC, - &freq_params); + freq); } @@ -11605,7 +11642,8 @@ nla_put_failure: static int nl80211_send_tdls_mgmt(void *priv, const u8 *dst, u8 action_code, u8 dialog_token, u16 status_code, - u32 peer_capab, const u8 *buf, size_t len) + u32 peer_capab, int initiator, const u8 *buf, + size_t len) { struct i802_bss *bss = priv; struct wpa_driver_nl80211_data *drv = bss->drv; @@ -11636,6 +11674,8 @@ static int nl80211_send_tdls_mgmt(void *priv, const u8 *dst, u8 action_code, */ NLA_PUT_U32(msg, NL80211_ATTR_TDLS_PEER_CAPABILITY, peer_capab); } + if (initiator) + NLA_PUT_FLAG(msg, NL80211_ATTR_TDLS_INITIATOR); NLA_PUT(msg, NL80211_ATTR_IE, len, buf); return send_and_recv_msgs(drv, msg, NULL, NULL); diff --git a/src/drivers/driver_test.c b/src/drivers/driver_test.c index 3608b522..66edfa73 100644 --- a/src/drivers/driver_test.c +++ b/src/drivers/driver_test.c @@ -1478,7 +1478,7 @@ static int wpa_driver_test_associate( struct wpa_driver_test_data *drv = dbss->drv; wpa_printf(MSG_DEBUG, "%s: priv=%p freq=%d pairwise_suite=%d " "group_suite=%d key_mgmt_suite=%d auth_alg=%d mode=%d", - __func__, priv, params->freq, params->pairwise_suite, + __func__, priv, params->freq.freq, params->pairwise_suite, params->group_suite, params->key_mgmt_suite, params->auth_alg, params->mode); wpa_driver_update_mode(drv, params->mode == IEEE80211_MODE_AP); diff --git a/src/drivers/driver_wext.c b/src/drivers/driver_wext.c index 459ac481..1b3a757b 100644 --- a/src/drivers/driver_wext.c +++ b/src/drivers/driver_wext.c @@ -2119,7 +2119,8 @@ int wpa_driver_wext_associate(void *priv, if (wpa_driver_wext_set_auth_param(drv, IW_AUTH_MFP, value) < 0) ret = -1; #endif /* CONFIG_IEEE80211W */ - if (params->freq && wpa_driver_wext_set_freq(drv, params->freq) < 0) + if (params->freq.freq && + wpa_driver_wext_set_freq(drv, params->freq.freq) < 0) ret = -1; if (!drv->cfg80211 && wpa_driver_wext_set_ssid(drv, params->ssid, params->ssid_len) < 0) diff --git a/src/drivers/nl80211_copy.h b/src/drivers/nl80211_copy.h index 406010d4..4b28dc07 100644 --- a/src/drivers/nl80211_copy.h +++ b/src/drivers/nl80211_copy.h @@ -503,6 +503,9 @@ * TX status event pertaining to the TX request. * %NL80211_ATTR_TX_NO_CCK_RATE is used to decide whether to send the * management frames at CCK rate or not in 2GHz band. + * %NL80211_ATTR_CSA_C_OFFSETS_TX is an array of offsets to CSA + * counters which will be updated to the current value. This attribute + * is used during CSA period. * @NL80211_CMD_FRAME_WAIT_CANCEL: When an off-channel TX was requested, this * command may be used with the corresponding cookie to cancel the wait * time if it is known that it is no longer necessary. @@ -719,6 +722,22 @@ * QoS mapping is relevant for IP packets, it is only valid during an * association. This is cleared on disassociation and AP restart. * + * @NL80211_CMD_ADD_TX_TS: Ask the kernel to add a traffic stream for the given + * %NL80211_ATTR_TSID and %NL80211_ATTR_MAC with %NL80211_ATTR_USER_PRIO + * and %NL80211_ATTR_ADMITTED_TIME parameters. + * Note that the action frame handshake with the AP shall be handled by + * userspace via the normal management RX/TX framework, this only sets + * up the TX TS in the driver/device. + * If the admitted time attribute is not added then the request just checks + * if a subsequent setup could be successful, the intent is to use this to + * avoid setting up a session with the AP when local restrictions would + * make that impossible. However, the subsequent "real" setup may still + * fail even if the check was successful. + * @NL80211_CMD_DEL_TX_TS: Remove an existing TS with the %NL80211_ATTR_TSID + * and %NL80211_ATTR_MAC parameters. It isn't necessary to call this + * before removing a station entry entirely, or before disassociating + * or similar, cleanup will happen in the driver/device in this case. + * * @NL80211_CMD_MAX: highest used command number * @__NL80211_CMD_AFTER_LAST: internal use */ @@ -890,6 +909,9 @@ enum nl80211_commands { NL80211_CMD_SET_QOS_MAP, + NL80211_CMD_ADD_TX_TS, + NL80211_CMD_DEL_TX_TS, + /* add new commands above here */ /* used to define NL80211_CMD_MAX below */ @@ -1525,10 +1547,10 @@ enum nl80211_commands { * operation). * @NL80211_ATTR_CSA_IES: Nested set of attributes containing the IE information * for the time while performing a channel switch. - * @NL80211_ATTR_CSA_C_OFF_BEACON: Offset of the channel switch counter - * field in the beacons tail (%NL80211_ATTR_BEACON_TAIL). - * @NL80211_ATTR_CSA_C_OFF_PRESP: Offset of the channel switch counter - * field in the probe response (%NL80211_ATTR_PROBE_RESP). + * @NL80211_ATTR_CSA_C_OFF_BEACON: An array of offsets (u16) to the channel + * switch counters in the beacons tail (%NL80211_ATTR_BEACON_TAIL). + * @NL80211_ATTR_CSA_C_OFF_PRESP: An array of offsets (u16) to the channel + * switch counters in the probe response (%NL80211_ATTR_PROBE_RESP). * * @NL80211_ATTR_RXMGMT_FLAGS: flags for nl80211_send_mgmt(), u32. * As specified in the &enum nl80211_rxmgmt_flags. @@ -1576,6 +1598,11 @@ enum nl80211_commands { * advertise values that cannot always be met. In such cases, an attempt * to add a new station entry with @NL80211_CMD_NEW_STATION may fail. * + * @NL80211_ATTR_CSA_C_OFFSETS_TX: An array of csa counter offsets (u16) which + * should be updated when the frame is transmitted. + * @NL80211_ATTR_MAX_CSA_COUNTERS: U8 attribute used to advertise the maximum + * supported number of csa counters. + * * @NL80211_ATTR_TDLS_PEER_CAPABILITY: flags for TDLS peer capabilities, u32. * As specified in the &enum nl80211_tdls_peer_capability. * @@ -1583,6 +1610,34 @@ enum nl80211_commands { * creation then the new interface will be owned by the netlink socket * that created it and will be destroyed when the socket is closed * + * @NL80211_ATTR_TDLS_INITIATOR: flag attribute indicating the current end is + * the TDLS link initiator. + * + * @NL80211_ATTR_USE_RRM: flag for indicating whether the current connection + * shall support Radio Resource Measurements (11k). This attribute can be + * used with %NL80211_CMD_ASSOCIATE and %NL80211_CMD_CONNECT requests. + * User space applications are expected to use this flag only if the + * underlying device supports these minimal RRM features: + * %NL80211_FEATURE_DS_PARAM_SET_IE_IN_PROBES, + * %NL80211_FEATURE_QUIET, + * If this flag is used, driver must add the Power Capabilities IE to the + * association request. In addition, it must also set the RRM capability + * flag in the association request's Capability Info field. + * + * @NL80211_ATTR_WIPHY_DYN_ACK: flag attribute used to enable ACK timeout + * estimation algorithm (dynack). In order to activate dynack + * %NL80211_FEATURE_ACKTO_ESTIMATION feature flag must be set by lower + * drivers to indicate dynack capability. Dynack is automatically disabled + * setting valid value for coverage class. + * + * @NL80211_ATTR_TSID: a TSID value (u8 attribute) + * @NL80211_ATTR_USER_PRIO: user priority value (u8 attribute) + * @NL80211_ATTR_ADMITTED_TIME: admitted time in units of 32 microseconds + * (per second) (u16 attribute) + * + * @NL80211_ATTR_SMPS_MODE: SMPS mode to use (ap mode). see + * &enum nl80211_smps_mode. + * * @NL80211_ATTR_MAX: highest attribute number currently defined * @__NL80211_ATTR_AFTER_LAST: internal use */ @@ -1920,6 +1975,21 @@ enum nl80211_attrs { NL80211_ATTR_IFACE_SOCKET_OWNER, + NL80211_ATTR_CSA_C_OFFSETS_TX, + NL80211_ATTR_MAX_CSA_COUNTERS, + + NL80211_ATTR_TDLS_INITIATOR, + + NL80211_ATTR_USE_RRM, + + NL80211_ATTR_WIPHY_DYN_ACK, + + NL80211_ATTR_TSID, + NL80211_ATTR_USER_PRIO, + NL80211_ATTR_ADMITTED_TIME, + + NL80211_ATTR_SMPS_MODE, + /* add attributes here, update the policy in nl80211.c */ __NL80211_ATTR_AFTER_LAST, @@ -2188,6 +2258,8 @@ enum nl80211_sta_bss_param { * Contains a nested array of signal strength attributes (u8, dBm) * @NL80211_STA_INFO_CHAIN_SIGNAL_AVG: per-chain signal strength average * Same format as NL80211_STA_INFO_CHAIN_SIGNAL. + * @NL80211_STA_EXPECTED_THROUGHPUT: expected throughput considering also the + * 802.11 header (u32, kbps) * @__NL80211_STA_INFO_AFTER_LAST: internal * @NL80211_STA_INFO_MAX: highest possible station info attribute */ @@ -2219,6 +2291,7 @@ enum nl80211_sta_info { NL80211_STA_INFO_TX_BYTES64, NL80211_STA_INFO_CHAIN_SIGNAL, NL80211_STA_INFO_CHAIN_SIGNAL_AVG, + NL80211_STA_INFO_EXPECTED_THROUGHPUT, /* keep last */ __NL80211_STA_INFO_AFTER_LAST, @@ -3036,14 +3109,20 @@ enum nl80211_bss_scan_width { * @NL80211_BSS_BSSID: BSSID of the BSS (6 octets) * @NL80211_BSS_FREQUENCY: frequency in MHz (u32) * @NL80211_BSS_TSF: TSF of the received probe response/beacon (u64) + * (if @NL80211_BSS_PRESP_DATA is present then this is known to be + * from a probe response, otherwise it may be from the same beacon + * that the NL80211_BSS_BEACON_TSF will be from) * @NL80211_BSS_BEACON_INTERVAL: beacon interval of the (I)BSS (u16) * @NL80211_BSS_CAPABILITY: capability field (CPU order, u16) * @NL80211_BSS_INFORMATION_ELEMENTS: binary attribute containing the * raw information elements from the probe response/beacon (bin); - * if the %NL80211_BSS_BEACON_IES attribute is present, the IEs here are - * from a Probe Response frame; otherwise they are from a Beacon frame. + * if the %NL80211_BSS_BEACON_IES attribute is present and the data is + * different then the IEs here are from a Probe Response frame; otherwise + * they are from a Beacon frame. * However, if the driver does not indicate the source of the IEs, these * IEs may be from either frame subtype. + * If present, the @NL80211_BSS_PRESP_DATA attribute indicates that the + * data here is known to be from a probe response, without any heuristics. * @NL80211_BSS_SIGNAL_MBM: signal strength of probe response/beacon * in mBm (100 * dBm) (s32) * @NL80211_BSS_SIGNAL_UNSPEC: signal strength of the probe response/beacon @@ -3055,6 +3134,10 @@ enum nl80211_bss_scan_width { * yet been received * @NL80211_BSS_CHAN_WIDTH: channel width of the control channel * (u32, enum nl80211_bss_scan_width) + * @NL80211_BSS_BEACON_TSF: TSF of the last received beacon (u64) + * (not present if no beacon frame has been received yet) + * @NL80211_BSS_PRESP_DATA: the data in @NL80211_BSS_INFORMATION_ELEMENTS and + * @NL80211_BSS_TSF is known to be from a probe response (flag attribute) * @__NL80211_BSS_AFTER_LAST: internal * @NL80211_BSS_MAX: highest BSS attribute */ @@ -3072,6 +3155,8 @@ enum nl80211_bss { NL80211_BSS_SEEN_MS_AGO, NL80211_BSS_BEACON_IES, NL80211_BSS_CHAN_WIDTH, + NL80211_BSS_BEACON_TSF, + NL80211_BSS_PRESP_DATA, /* keep last */ __NL80211_BSS_AFTER_LAST, @@ -3688,6 +3773,8 @@ enum nl80211_iface_limit_attrs { * different channels may be used within this group. * @NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS: u32 attribute containing the bitmap * of supported channel widths for radar detection. + * @NL80211_IFACE_COMB_RADAR_DETECT_REGIONS: u32 attribute containing the bitmap + * of supported regulatory regions for radar detection. * @NUM_NL80211_IFACE_COMB: number of attributes * @MAX_NL80211_IFACE_COMB: highest attribute number * @@ -3721,6 +3808,7 @@ enum nl80211_if_combination_attrs { NL80211_IFACE_COMB_STA_AP_BI_MATCH, NL80211_IFACE_COMB_NUM_CHANNELS, NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS, + NL80211_IFACE_COMB_RADAR_DETECT_REGIONS, /* keep last */ NUM_NL80211_IFACE_COMB, @@ -3894,6 +3982,8 @@ enum nl80211_ap_sme_features { * @NL80211_FEATURE_CELL_BASE_REG_HINTS: This driver has been tested * to work properly to suppport receiving regulatory hints from * cellular base stations. + * @NL80211_FEATURE_P2P_DEVICE_NEEDS_CHANNEL: (no longer available, only + * here to reserve the value for API/ABI compatibility) * @NL80211_FEATURE_SAE: This driver supports simultaneous authentication of * equals (SAE) with user space SME (NL80211_CMD_AUTHENTICATE) in station * mode @@ -3932,13 +4022,33 @@ enum nl80211_ap_sme_features { * @NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE: This driver supports dynamic * channel bandwidth change (e.g., HT 20 <-> 40 MHz channel) during the * lifetime of a BSS. + * @NL80211_FEATURE_DS_PARAM_SET_IE_IN_PROBES: This device adds a DS Parameter + * Set IE to probe requests. + * @NL80211_FEATURE_WFA_TPC_IE_IN_PROBES: This device adds a WFA TPC Report IE + * to probe requests. + * @NL80211_FEATURE_QUIET: This device, in client mode, supports Quiet Period + * requests sent to it by an AP. + * @NL80211_FEATURE_TX_POWER_INSERTION: This device is capable of inserting the + * current tx power value into the TPC Report IE in the spectrum + * management TPC Report action frame, and in the Radio Measurement Link + * Measurement Report action frame. + * @NL80211_FEATURE_ACKTO_ESTIMATION: This driver supports dynamic ACK timeout + * estimation (dynack). %NL80211_ATTR_WIPHY_DYN_ACK flag attribute is used + * to enable dynack. + * @NL80211_FEATURE_STATIC_SMPS: Device supports static spatial + * multiplexing powersave, ie. can turn off all but one chain + * even on HT connections that should be using more chains. + * @NL80211_FEATURE_DYNAMIC_SMPS: Device supports dynamic spatial + * multiplexing powersave, ie. can turn off all but one chain + * and then wake the rest up as required after, for example, + * rts/cts handshake. */ enum nl80211_feature_flags { NL80211_FEATURE_SK_TX_STATUS = 1 << 0, NL80211_FEATURE_HT_IBSS = 1 << 1, NL80211_FEATURE_INACTIVITY_TIMER = 1 << 2, NL80211_FEATURE_CELL_BASE_REG_HINTS = 1 << 3, - /* bit 4 is reserved - don't use */ + NL80211_FEATURE_P2P_DEVICE_NEEDS_CHANNEL = 1 << 4, NL80211_FEATURE_SAE = 1 << 5, NL80211_FEATURE_LOW_PRIORITY_SCAN = 1 << 6, NL80211_FEATURE_SCAN_FLUSH = 1 << 7, @@ -3953,6 +4063,13 @@ enum nl80211_feature_flags { NL80211_FEATURE_USERSPACE_MPM = 1 << 16, NL80211_FEATURE_ACTIVE_MONITOR = 1 << 17, NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE = 1 << 18, + NL80211_FEATURE_DS_PARAM_SET_IE_IN_PROBES = 1 << 19, + NL80211_FEATURE_WFA_TPC_IE_IN_PROBES = 1 << 20, + NL80211_FEATURE_QUIET = 1 << 21, + NL80211_FEATURE_TX_POWER_INSERTION = 1 << 22, + NL80211_FEATURE_ACKTO_ESTIMATION = 1 << 23, + NL80211_FEATURE_STATIC_SMPS = 1 << 24, + NL80211_FEATURE_DYNAMIC_SMPS = 1 << 25, }; /** @@ -4026,6 +4143,25 @@ enum nl80211_acl_policy { NL80211_ACL_POLICY_DENY_UNLESS_LISTED, }; +/** + * enum nl80211_smps_mode - SMPS mode + * + * Requested SMPS mode (for AP mode) + * + * @NL80211_SMPS_OFF: SMPS off (use all antennas). + * @NL80211_SMPS_STATIC: static SMPS (use a single antenna) + * @NL80211_SMPS_DYNAMIC: dynamic smps (start with a single antenna and + * turn on other antennas after CTS/RTS). + */ +enum nl80211_smps_mode { + NL80211_SMPS_OFF, + NL80211_SMPS_STATIC, + NL80211_SMPS_DYNAMIC, + + __NL80211_SMPS_AFTER_LAST, + NL80211_SMPS_MAX = __NL80211_SMPS_AFTER_LAST - 1 +}; + /** * enum nl80211_radar_event - type of radar event for DFS operation * diff --git a/src/eap_common/eap_pwd_common.c b/src/eap_common/eap_pwd_common.c index fdcff7fa..631c363f 100644 --- a/src/eap_common/eap_pwd_common.c +++ b/src/eap_common/eap_pwd_common.c @@ -106,9 +106,11 @@ int compute_password_element(EAP_PWD_group *grp, u16 num, case 21: nid = NID_secp521r1; break; +#ifndef OPENSSL_IS_BORINGSSL case 25: nid = NID_X9_62_prime192v1; break; +#endif /* OPENSSL_IS_BORINGSSL */ case 26: nid = NID_secp224r1; break; diff --git a/src/eap_server/eap_server_fast.c b/src/eap_server/eap_server_fast.c index 4691e722..2692bced 100644 --- a/src/eap_server/eap_server_fast.c +++ b/src/eap_server/eap_server_fast.c @@ -161,8 +161,8 @@ static int eap_fast_session_ticket_cb(void *ctx, const u8 *ticket, size_t len, return 0; } - if (aes_unwrap(data->pac_opaque_encr, (pac_opaque_len - 8) / 8, - pac_opaque, buf) < 0) { + if (aes_unwrap(data->pac_opaque_encr, sizeof(data->pac_opaque_encr), + (pac_opaque_len - 8) / 8, pac_opaque, buf) < 0) { wpa_printf(MSG_DEBUG, "EAP-FAST: Failed to decrypt " "PAC-Opaque"); os_free(buf); @@ -731,8 +731,8 @@ static struct wpabuf * eap_fast_build_pac(struct eap_sm *sm, os_free(pac_buf); return NULL; } - if (aes_wrap(data->pac_opaque_encr, pac_len / 8, pac_buf, - pac_opaque) < 0) { + if (aes_wrap(data->pac_opaque_encr, sizeof(data->pac_opaque_encr), + pac_len / 8, pac_buf, pac_opaque) < 0) { os_free(pac_buf); os_free(pac_opaque); return NULL; diff --git a/src/pae/ieee802_1x_kay.c b/src/pae/ieee802_1x_kay.c index 56c195ab..b1cf32dd 100644 --- a/src/pae/ieee802_1x_kay.c +++ b/src/pae/ieee802_1x_kay.c @@ -1451,7 +1451,7 @@ ieee802_1x_mka_encode_dist_sak_body( os_memcpy(body->sak, cipher_suite_tbl[cs_index].id, CS_ID_LEN); sak_pos = CS_ID_LEN; } - if (aes_wrap(participant->kek.key, + if (aes_wrap(participant->kek.key, 16, cipher_suite_tbl[cs_index].sak_len / 8, sak->key, body->sak + sak_pos)) { wpa_printf(MSG_ERROR, "KaY: AES wrap failed"); @@ -1611,7 +1611,7 @@ ieee802_1x_mka_decode_dist_sak_body( wpa_printf(MSG_ERROR, "KaY-%s: Out of memory", __func__); return -1; } - if (aes_unwrap(participant->kek.key, sak_len >> 3, wrap_sak, + if (aes_unwrap(participant->kek.key, 16, sak_len >> 3, wrap_sak, unwrap_sak)) { wpa_printf(MSG_ERROR, "KaY: AES unwrap failed"); os_free(unwrap_sak); diff --git a/src/rsn_supp/pmksa_cache.c b/src/rsn_supp/pmksa_cache.c index b5a87fc5..885291a2 100644 --- a/src/rsn_supp/pmksa_cache.c +++ b/src/rsn_supp/pmksa_cache.c @@ -35,7 +35,7 @@ static void pmksa_cache_set_expiration(struct rsn_pmksa_cache *pmksa); static void _pmksa_cache_free_entry(struct rsn_pmksa_cache_entry *entry) { - os_free(entry); + bin_clear_free(entry, sizeof(*entry)); } diff --git a/src/rsn_supp/tdls.c b/src/rsn_supp/tdls.c index 93ae1432..8cb19a25 100644 --- a/src/rsn_supp/tdls.c +++ b/src/rsn_supp/tdls.c @@ -218,26 +218,29 @@ static int wpa_tdls_set_key(struct wpa_sm *sm, struct wpa_tdls_peer *peer) static int wpa_tdls_send_tpk_msg(struct wpa_sm *sm, const u8 *dst, u8 action_code, u8 dialog_token, u16 status_code, u32 peer_capab, - const u8 *buf, size_t len) + int initiator, const u8 *buf, size_t len) { return wpa_sm_send_tdls_mgmt(sm, dst, action_code, dialog_token, - status_code, peer_capab, buf, len); + status_code, peer_capab, initiator, buf, + len); } static int wpa_tdls_tpk_send(struct wpa_sm *sm, const u8 *dest, u8 action_code, u8 dialog_token, u16 status_code, u32 peer_capab, - const u8 *msg, size_t msg_len) + int initiator, const u8 *msg, size_t msg_len) { struct wpa_tdls_peer *peer; wpa_printf(MSG_DEBUG, "TDLS: TPK send dest=" MACSTR " action_code=%u " - "dialog_token=%u status_code=%u peer_capab=%u msg_len=%u", + "dialog_token=%u status_code=%u peer_capab=%u initiator=%d " + "msg_len=%u", MAC2STR(dest), action_code, dialog_token, status_code, - peer_capab, (unsigned int) msg_len); + peer_capab, initiator, (unsigned int) msg_len); if (wpa_tdls_send_tpk_msg(sm, dest, action_code, dialog_token, - status_code, peer_capab, msg, msg_len)) { + status_code, peer_capab, initiator, msg, + msg_len)) { wpa_printf(MSG_INFO, "TDLS: Failed to send message " "(action_code=%u)", action_code); return -1; @@ -333,6 +336,7 @@ static void wpa_tdls_tpk_retry_timeout(void *eloop_ctx, void *timeout_ctx) peer->sm_tmr.dialog_token, peer->sm_tmr.status_code, peer->sm_tmr.peer_capab, + peer->initiator, peer->sm_tmr.buf, peer->sm_tmr.buf_len)) { wpa_printf(MSG_INFO, "TDLS: Failed to retry " @@ -793,7 +797,7 @@ skip_ies: /* request driver to send Teardown using this FTIE */ wpa_tdls_tpk_send(sm, addr, WLAN_TDLS_TEARDOWN, 0, - reason_code, 0, rbuf, pos - rbuf); + reason_code, 0, peer->initiator, rbuf, pos - rbuf); os_free(rbuf); return 0; @@ -968,17 +972,19 @@ skip_ftie: * appropriate status code mentioning reason for error/failure. * @dst - MAC addr of Peer station * @tdls_action - TDLS frame type for which error code is sent + * @initiator - was this end the initiator of the connection * @status - status code mentioning reason */ static int wpa_tdls_send_error(struct wpa_sm *sm, const u8 *dst, - u8 tdls_action, u8 dialog_token, u16 status) + u8 tdls_action, u8 dialog_token, int initiator, + u16 status) { wpa_printf(MSG_DEBUG, "TDLS: Sending error to " MACSTR " (action=%u status=%u)", MAC2STR(dst), tdls_action, status); return wpa_tdls_tpk_send(sm, dst, tdls_action, dialog_token, status, - 0, NULL, 0); + 0, initiator, NULL, 0); } @@ -1184,7 +1190,7 @@ skip_ies: MAC2STR(peer->addr)); status = wpa_tdls_tpk_send(sm, peer->addr, WLAN_TDLS_SETUP_REQUEST, - 1, 0, 0, rbuf, pos - rbuf); + 1, 0, 0, peer->initiator, rbuf, pos - rbuf); os_free(rbuf); return status; @@ -1274,7 +1280,8 @@ static int wpa_tdls_send_tpk_m2(struct wpa_sm *sm, skip_ies: status = wpa_tdls_tpk_send(sm, src_addr, WLAN_TDLS_SETUP_RESPONSE, - dtoken, 0, 0, rbuf, pos - rbuf); + dtoken, 0, 0, peer->initiator, rbuf, + pos - rbuf); os_free(rbuf); return status; @@ -1371,7 +1378,8 @@ skip_ies: peer_capab |= TDLS_PEER_WMM; status = wpa_tdls_tpk_send(sm, src_addr, WLAN_TDLS_SETUP_CONFIRM, - dtoken, 0, peer_capab, rbuf, pos - rbuf); + dtoken, 0, peer_capab, peer->initiator, + rbuf, pos - rbuf); os_free(rbuf); return status; @@ -1457,7 +1465,7 @@ skip_rsn_ies: wpa_printf(MSG_DEBUG, "TDLS: TPK lifetime %u seconds", peer->lifetime); skip_ies: status = wpa_tdls_tpk_send(sm, peer->addr, WLAN_TDLS_DISCOVERY_RESPONSE, - dialog_token, 0, 0, rbuf, pos - rbuf); + dialog_token, 0, 0, 0, rbuf, pos - rbuf); os_free(rbuf); return status; @@ -1528,7 +1536,7 @@ int wpa_tdls_send_discovery_request(struct wpa_sm *sm, const u8 *addr) wpa_printf(MSG_DEBUG, "TDLS: Sending Discovery Request to peer " MACSTR, MAC2STR(addr)); return wpa_tdls_tpk_send(sm, addr, WLAN_TDLS_DISCOVERY_REQUEST, - 1, 0, 0, NULL, 0); + 1, 0, 0, 1, NULL, 0); } @@ -1713,8 +1721,8 @@ static int wpa_tdls_addset_peer(struct wpa_sm *sm, struct wpa_tdls_peer *peer, peer->supp_rates, peer->supp_rates_len, peer->ht_capabilities, peer->vht_capabilities, - peer->qos_info, peer->ext_capab, - peer->ext_capab_len, + peer->qos_info, peer->wmm_capable, + peer->ext_capab, peer->ext_capab_len, peer->supp_channels, peer->supp_channels_len, peer->supp_oper_classes, @@ -1858,6 +1866,8 @@ static int wpa_tdls_process_tpk_m1(struct wpa_sm *sm, const u8 *src_addr, wpa_printf(MSG_DEBUG, "TDLS: Testing concurrent initiation of " "TDLS setup - send own request"); peer->initiator = 1; + wpa_sm_tdls_peer_addset(sm, peer->addr, 1, 0, 0, NULL, 0, NULL, + NULL, 0, 0, NULL, 0, NULL, 0, NULL, 0); wpa_tdls_send_tpk_m1(sm, peer); } @@ -2036,10 +2046,18 @@ skip_rsn: wpa_tdls_generate_tpk(peer, sm->own_addr, sm->bssid); skip_rsn_check: +#ifdef CONFIG_TDLS_TESTING + if (tdls_testing & TDLS_TESTING_CONCURRENT_INIT) + goto skip_add_peer; +#endif /* CONFIG_TDLS_TESTING */ + /* add supported rates, capabilities, and qos_info to the TDLS peer */ if (wpa_tdls_addset_peer(sm, peer, 1) < 0) goto error; +#ifdef CONFIG_TDLS_TESTING +skip_add_peer: +#endif /* CONFIG_TDLS_TESTING */ peer->tpk_in_progress = 1; wpa_printf(MSG_DEBUG, "TDLS: Sending TDLS Setup Response / TPK M2"); @@ -2051,7 +2069,7 @@ skip_rsn_check: return 0; error: - wpa_tdls_send_error(sm, src_addr, WLAN_TDLS_SETUP_RESPONSE, dtoken, + wpa_tdls_send_error(sm, src_addr, WLAN_TDLS_SETUP_RESPONSE, dtoken, 0, status); if (peer) wpa_tdls_peer_free(sm, peer); @@ -2362,7 +2380,7 @@ skip_rsn: return ret; error: - wpa_tdls_send_error(sm, src_addr, WLAN_TDLS_SETUP_CONFIRM, dtoken, + wpa_tdls_send_error(sm, src_addr, WLAN_TDLS_SETUP_CONFIRM, dtoken, 1, status); wpa_tdls_disable_peer_link(sm, peer); return -1; @@ -2587,7 +2605,7 @@ int wpa_tdls_start(struct wpa_sm *sm, const u8 *addr) /* add the peer to the driver as a "setup in progress" peer */ if (wpa_sm_tdls_peer_addset(sm, peer->addr, 1, 0, 0, NULL, 0, NULL, - NULL, 0, NULL, 0, NULL, 0, NULL, 0)) { + NULL, 0, 0, NULL, 0, NULL, 0, NULL, 0)) { wpa_tdls_disable_peer_link(sm, peer); return -1; } diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c index 94710717..b17fc88b 100644 --- a/src/rsn_supp/wpa.c +++ b/src/rsn_supp/wpa.c @@ -1295,7 +1295,8 @@ static int wpa_supplicant_process_1_of_2_wpa(struct wpa_sm *sm, (unsigned long) maxkeylen); return -1; } - if (aes_unwrap(sm->ptk.kek, maxkeylen / 8, key_data, gd->gtk)) { + if (aes_unwrap(sm->ptk.kek, 16, maxkeylen / 8, key_data, + gd->gtk)) { wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, "WPA: AES unwrap failed - could not decrypt " "GTK"); @@ -1503,7 +1504,7 @@ static int wpa_supplicant_decrypt_key_data(struct wpa_sm *sm, "WPA: No memory for AES-UNWRAP buffer"); return -1; } - if (aes_unwrap(sm->ptk.kek, *key_data_len / 8, + if (aes_unwrap(sm->ptk.kek, 16, *key_data_len / 8, key_data, buf)) { os_free(buf); wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, diff --git a/src/rsn_supp/wpa.h b/src/rsn_supp/wpa.h index 07a7bf90..63032b02 100644 --- a/src/rsn_supp/wpa.h +++ b/src/rsn_supp/wpa.h @@ -55,14 +55,14 @@ struct wpa_sm_ctx { int (*send_tdls_mgmt)(void *ctx, const u8 *dst, u8 action_code, u8 dialog_token, u16 status_code, u32 peer_capab, - const u8 *buf, size_t len); + int initiator, const u8 *buf, size_t len); int (*tdls_oper)(void *ctx, int oper, const u8 *peer); int (*tdls_peer_addset)(void *ctx, const u8 *addr, int add, u16 aid, u16 capability, const u8 *supp_rates, size_t supp_rates_len, const struct ieee80211_ht_capabilities *ht_capab, const struct ieee80211_vht_capabilities *vht_capab, - u8 qosinfo, const u8 *ext_capab, + u8 qosinfo, int wmm, const u8 *ext_capab, size_t ext_capab_len, const u8 *supp_channels, size_t supp_channels_len, const u8 *supp_oper_classes, diff --git a/src/rsn_supp/wpa_ft.c b/src/rsn_supp/wpa_ft.c index 4a75b926..3b3c9d0d 100644 --- a/src/rsn_supp/wpa_ft.c +++ b/src/rsn_supp/wpa_ft.c @@ -566,7 +566,7 @@ static int wpa_ft_process_gtk_subelem(struct wpa_sm *sm, const u8 *gtk_elem, return -1; } gtk_len = gtk_elem_len - 19; - if (aes_unwrap(sm->ptk.kek, gtk_len / 8, gtk_elem + 11, gtk)) { + if (aes_unwrap(sm->ptk.kek, 16, gtk_len / 8, gtk_elem + 11, gtk)) { wpa_printf(MSG_WARNING, "FT: AES unwrap failed - could not " "decrypt GTK"); return -1; @@ -645,7 +645,8 @@ static int wpa_ft_process_igtk_subelem(struct wpa_sm *sm, const u8 *igtk_elem, return -1; } - if (aes_unwrap(sm->ptk.kek, WPA_IGTK_LEN / 8, igtk_elem + 9, igtk)) { + if (aes_unwrap(sm->ptk.kek, 16, WPA_IGTK_LEN / 8, igtk_elem + 9, igtk)) + { wpa_printf(MSG_WARNING, "FT: AES unwrap failed - could not " "decrypt IGTK"); return -1; diff --git a/src/rsn_supp/wpa_i.h b/src/rsn_supp/wpa_i.h index e20e9dac..839b545b 100644 --- a/src/rsn_supp/wpa_i.h +++ b/src/rsn_supp/wpa_i.h @@ -268,12 +268,14 @@ static inline int wpa_sm_tdls_get_capa(struct wpa_sm *sm, static inline int wpa_sm_send_tdls_mgmt(struct wpa_sm *sm, const u8 *dst, u8 action_code, u8 dialog_token, u16 status_code, u32 peer_capab, - const u8 *buf, size_t len) + int initiator, const u8 *buf, + size_t len) { if (sm->ctx->send_tdls_mgmt) return sm->ctx->send_tdls_mgmt(sm->ctx->ctx, dst, action_code, dialog_token, status_code, - peer_capab, buf, len); + peer_capab, initiator, buf, + len); return -1; } @@ -291,16 +293,16 @@ wpa_sm_tdls_peer_addset(struct wpa_sm *sm, const u8 *addr, int add, size_t supp_rates_len, const struct ieee80211_ht_capabilities *ht_capab, const struct ieee80211_vht_capabilities *vht_capab, - u8 qosinfo, const u8 *ext_capab, size_t ext_capab_len, - const u8 *supp_channels, size_t supp_channels_len, - const u8 *supp_oper_classes, + u8 qosinfo, int wmm, const u8 *ext_capab, + size_t ext_capab_len, const u8 *supp_channels, + size_t supp_channels_len, const u8 *supp_oper_classes, size_t supp_oper_classes_len) { if (sm->ctx->tdls_peer_addset) return sm->ctx->tdls_peer_addset(sm->ctx->ctx, addr, add, aid, capability, supp_rates, supp_rates_len, ht_capab, - vht_capab, qosinfo, + vht_capab, qosinfo, wmm, ext_capab, ext_capab_len, supp_channels, supp_channels_len, diff --git a/src/rsn_supp/wpa_ie.c b/src/rsn_supp/wpa_ie.c index 2329033e..93e8cf69 100644 --- a/src/rsn_supp/wpa_ie.c +++ b/src/rsn_supp/wpa_ie.c @@ -549,7 +549,7 @@ int wpa_supplicant_parse_ies(const u8 *buf, size_t len, ie->ht_capabilities_len = pos[1]; } else if (*pos == WLAN_EID_VHT_AID) { if (pos[1] >= 2) - ie->aid = WPA_GET_LE16(pos + 2); + ie->aid = WPA_GET_LE16(pos + 2) & 0x3fff; } else if (*pos == WLAN_EID_VHT_CAP) { ie->vht_capabilities = pos + 2; ie->vht_capabilities_len = pos[1]; -- cgit v1.2.3 From a7b06faf528d1765cc2712cc9a31ad45d7c3110b Mon Sep 17 00:00:00 2001 From: Dmitry Shmidt Date: Thu, 9 Oct 2014 12:56:52 -0700 Subject: Cumulative patch to Release 2.3 724fce8 Change version information for the 2.3 release 5cb1440 Update ChangeLog files for v2.3 2b28ef6 browser-wpadebug: Use more robust mechanism for starting browser 3d8a3ff browser-android: Use more robust mechanism for starting browser 17dc39a browser-system: Use more robust mechanism for starting browser 4a274f4 DFS: Allow 80+80 MHz be configured for VHT Change-Id: I5562ac22e5bf8a55d0f7f8944ca0d9c8ebd8d13f Signed-off-by: Dmitry Shmidt --- src/ap/dfs.c | 70 ++++++++++++++++++++++++++++++++++---------- src/common/version.h | 2 +- src/utils/browser-android.c | 6 ++-- src/utils/browser-system.c | 2 +- src/utils/browser-wpadebug.c | 13 ++++---- 5 files changed, 66 insertions(+), 27 deletions(-) (limited to 'src') diff --git a/src/ap/dfs.c b/src/ap/dfs.c index 20419f32..a6ec20bd 100644 --- a/src/ap/dfs.c +++ b/src/ap/dfs.c @@ -18,10 +18,12 @@ #include "dfs.h" -static int dfs_get_used_n_chans(struct hostapd_iface *iface) +static int dfs_get_used_n_chans(struct hostapd_iface *iface, int *seg1) { int n_chans = 1; + *seg1 = 0; + if (iface->conf->ieee80211n && iface->conf->secondary_channel) n_chans = 2; @@ -35,6 +37,10 @@ static int dfs_get_used_n_chans(struct hostapd_iface *iface) case VHT_CHANWIDTH_160MHZ: n_chans = 8; break; + case VHT_CHANWIDTH_80P80MHZ: + n_chans = 4; + *seg1 = 4; + break; default: break; } @@ -170,10 +176,10 @@ static int dfs_find_channel(struct hostapd_iface *iface, { struct hostapd_hw_modes *mode; struct hostapd_channel_data *chan; - int i, channel_idx = 0, n_chans; + int i, channel_idx = 0, n_chans, n_chans1; mode = iface->current_mode; - n_chans = dfs_get_used_n_chans(iface); + n_chans = dfs_get_used_n_chans(iface, &n_chans1); wpa_printf(MSG_DEBUG, "DFS new chan checking %d channels", n_chans); for (i = 0; i < mode->num_channels; i++) { @@ -246,12 +252,15 @@ static void dfs_adjust_vht_center_freq(struct hostapd_iface *iface, /* Return start channel idx we will use for mode->channels[idx] */ -static int dfs_get_start_chan_idx(struct hostapd_iface *iface) +static int dfs_get_start_chan_idx(struct hostapd_iface *iface, int *seg1_start) { struct hostapd_hw_modes *mode; struct hostapd_channel_data *chan; int channel_no = iface->conf->channel; int res = -1, i; + int chan_seg1 = -1; + + *seg1_start = -1; /* HT40- */ if (iface->conf->ieee80211n && iface->conf->secondary_channel == -1) @@ -270,9 +279,15 @@ static int dfs_get_start_chan_idx(struct hostapd_iface *iface) channel_no = iface->conf->vht_oper_centr_freq_seg0_idx - 14; break; + case VHT_CHANWIDTH_80P80MHZ: + channel_no = + iface->conf->vht_oper_centr_freq_seg0_idx - 6; + chan_seg1 = + iface->conf->vht_oper_centr_freq_seg1_idx - 6; + break; default: wpa_printf(MSG_INFO, - "DFS only VHT20/40/80/160 is supported now"); + "DFS only VHT20/40/80/160/80+80 is supported now"); channel_no = -1; break; } @@ -288,6 +303,23 @@ static int dfs_get_start_chan_idx(struct hostapd_iface *iface) } } + if (res != -1 && chan_seg1 > -1) { + int found = 0; + + /* Get idx for seg1 */ + mode = iface->current_mode; + for (i = 0; i < mode->num_channels; i++) { + chan = &mode->channels[i]; + if (chan->chan == chan_seg1) { + *seg1_start = i; + found = 1; + break; + } + } + if (!found) + res = -1; + } + if (res == -1) { wpa_printf(MSG_DEBUG, "DFS chan_idx seems wrong; num-ch: %d ch-no: %d conf-ch-no: %d 11n: %d sec-ch: %d vht-oper-width: %d", @@ -511,17 +543,17 @@ static int set_dfs_state(struct hostapd_iface *iface, int freq, int ht_enabled, static int dfs_are_channels_overlapped(struct hostapd_iface *iface, int freq, int chan_width, int cf1, int cf2) { - int start_chan_idx; + int start_chan_idx, start_chan_idx1; struct hostapd_hw_modes *mode; struct hostapd_channel_data *chan; - int n_chans, i, j, frequency = freq, radar_n_chans = 1; + int n_chans, n_chans1, i, j, frequency = freq, radar_n_chans = 1; u8 radar_chan; int res = 0; /* Our configuration */ mode = iface->current_mode; - start_chan_idx = dfs_get_start_chan_idx(iface); - n_chans = dfs_get_used_n_chans(iface); + start_chan_idx = dfs_get_start_chan_idx(iface, &start_chan_idx1); + n_chans = dfs_get_used_n_chans(iface, &n_chans1); /* Check we are on DFS channel(s) */ if (!dfs_check_chans_radar(iface, start_chan_idx, n_chans)) @@ -604,19 +636,20 @@ static unsigned int dfs_get_cac_time(struct hostapd_iface *iface, int hostapd_handle_dfs(struct hostapd_iface *iface) { struct hostapd_channel_data *channel; - int res, n_chans, start_chan_idx; + int res, n_chans, n_chans1, start_chan_idx, start_chan_idx1; int skip_radar = 0; iface->cac_started = 0; do { /* Get start (first) channel for current configuration */ - start_chan_idx = dfs_get_start_chan_idx(iface); + start_chan_idx = dfs_get_start_chan_idx(iface, + &start_chan_idx1); if (start_chan_idx == -1) return -1; /* Get number of used channels, depend on width */ - n_chans = dfs_get_used_n_chans(iface); + n_chans = dfs_get_used_n_chans(iface, &n_chans1); /* Setup CAC time */ iface->dfs_cac_ms = dfs_get_cac_time(iface, start_chan_idx, @@ -928,20 +961,25 @@ int hostapd_dfs_nop_finished(struct hostapd_iface *iface, int freq, int hostapd_is_dfs_required(struct hostapd_iface *iface) { - int n_chans, start_chan_idx; + int n_chans, n_chans1, start_chan_idx, start_chan_idx1, res; if (!iface->conf->ieee80211h || !iface->current_mode || iface->current_mode->mode != HOSTAPD_MODE_IEEE80211A) return 0; /* Get start (first) channel for current configuration */ - start_chan_idx = dfs_get_start_chan_idx(iface); + start_chan_idx = dfs_get_start_chan_idx(iface, &start_chan_idx1); if (start_chan_idx == -1) return -1; /* Get number of used channels, depend on width */ - n_chans = dfs_get_used_n_chans(iface); + n_chans = dfs_get_used_n_chans(iface, &n_chans1); /* Check if any of configured channels require DFS */ - return dfs_check_chans_radar(iface, start_chan_idx, n_chans); + res = dfs_check_chans_radar(iface, start_chan_idx, n_chans); + if (res) + return res; + if (start_chan_idx1 >= 0 && n_chans1 > 0) + res = dfs_check_chans_radar(iface, start_chan_idx1, n_chans1); + return res; } diff --git a/src/common/version.h b/src/common/version.h index 1f254329..726289d9 100644 --- a/src/common/version.h +++ b/src/common/version.h @@ -5,6 +5,6 @@ #define VERSION_STR_POSTFIX "" #endif /* VERSION_STR_POSTFIX */ -#define VERSION_STR "2.3-devel" VERSION_STR_POSTFIX +#define VERSION_STR "2.3" VERSION_STR_POSTFIX #endif /* VERSION_H */ diff --git a/src/utils/browser-android.c b/src/utils/browser-android.c index a0663925..d5ff5b5c 100644 --- a/src/utils/browser-android.c +++ b/src/utils/browser-android.c @@ -75,7 +75,7 @@ int hs20_web_browser(const char *url) os_memset(&data, 0, sizeof(data)); ret = os_snprintf(cmd, sizeof(cmd), - "am start -a android.intent.action.VIEW -d '%s' " + "start -a android.intent.action.VIEW -d %s " "-n com.android.browser/.BrowserActivity", url); if (ret < 0 || (size_t) ret >= sizeof(cmd)) { wpa_printf(MSG_ERROR, "Too long URL"); @@ -94,7 +94,7 @@ int hs20_web_browser(const char *url) return -1; } - if (system(cmd) != 0) { + if (os_exec("/system/bin/am", cmd, 1) != 0) { wpa_printf(MSG_INFO, "Failed to launch Android browser"); eloop_cancel_timeout(browser_timeout, NULL, NULL); http_server_deinit(http); @@ -109,7 +109,7 @@ int hs20_web_browser(const char *url) eloop_destroy(); wpa_printf(MSG_INFO, "Closing Android browser"); - if (system("input keyevent 3") != 0) { + if (os_exec("/system/bin/input", "keyevent 3", 1) != 0) { wpa_printf(MSG_INFO, "Failed to inject keyevent"); } diff --git a/src/utils/browser-system.c b/src/utils/browser-system.c index 2884d341..a080e2cb 100644 --- a/src/utils/browser-system.c +++ b/src/utils/browser-system.c @@ -92,7 +92,7 @@ int hs20_web_browser(const char *url) return -1; } - if (system(cmd) != 0) { + if (os_exec("/usr/bin/x-www-browser", url, 0) != 0) { wpa_printf(MSG_INFO, "Failed to launch browser"); eloop_cancel_timeout(browser_timeout, NULL, NULL); http_server_deinit(http); diff --git a/src/utils/browser-wpadebug.c b/src/utils/browser-wpadebug.c index eeb8f650..ce3054bb 100644 --- a/src/utils/browser-wpadebug.c +++ b/src/utils/browser-wpadebug.c @@ -76,7 +76,7 @@ int hs20_web_browser(const char *url) os_memset(&data, 0, sizeof(data)); ret = os_snprintf(cmd, sizeof(cmd), - "am start -a android.action.MAIN " + "start -a android.action.MAIN " "-c android.intent.category.LAUNCHER " "-n w1.fi.wpadebug/.WpaWebViewActivity " "-e w1.fi.wpadebug.URL '%s'", url); @@ -97,7 +97,7 @@ int hs20_web_browser(const char *url) return -1; } - if (system(cmd) != 0) { + if (os_exec("/system/bin/am", cmd, 1) != 0) { wpa_printf(MSG_INFO, "Failed to launch wpadebug browser"); eloop_cancel_timeout(browser_timeout, NULL, NULL); http_server_deinit(http); @@ -112,10 +112,11 @@ int hs20_web_browser(const char *url) eloop_destroy(); wpa_printf(MSG_INFO, "Closing Android browser"); - if (system("am start -a android.action.MAIN " - "-c android.intent.category.LAUNCHER " - "-n w1.fi.wpadebug/.WpaWebViewActivity " - "-e w1.fi.wpadebug.URL FINISH") != 0) { + if (os_exec("/system/bin/am", + "start -a android.action.MAIN " + "-c android.intent.category.LAUNCHER " + "-n w1.fi.wpadebug/.WpaWebViewActivity " + "-e w1.fi.wpadebug.URL FINISH", 1) != 0) { wpa_printf(MSG_INFO, "Failed to close wpadebug browser"); } -- cgit v1.2.3 From 658fb4adb9458c3055c64a43833f1a9e89b4db74 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 14 Nov 2014 20:57:05 +0200 Subject: Work around AP misbehavior on EAPOL-Key descriptor version It looks like some APs are incorrectly selecting descriptor version 3 (AES-128-CMAC) for EAPOL-Key frames when version 2 (HMAC-SHA1) was expected to be used. This is likely triggered by an attempt to negotiate PMF with SHA1-based AKM. Since AES-128-CMAC is considered stronger than HMAC-SHA1, allow the incorrect, but stronger, option to be used in these cases to avoid interoperability issues with deployed APs. This issue shows up with "WPA: CCMP is used, but EAPOL-Key descriptor version (3) is not 2" in debug log. With the new workaround, this issue is ignored and "WPA: Interoperability workaround: allow incorrect (should have been HMAC-SHA1), but stronger (is AES-128-CMAC), descriptor version to be used" is written to the log. Bug: 18411110 Change-Id: I9ae12e8882adc9e785f6e4cef9f30b89bf72dcd2 Signed-off-by: Jouni Malinen --- src/rsn_supp/wpa.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src') diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c index 94710717..d6fb6a15 100644 --- a/src/rsn_supp/wpa.c +++ b/src/rsn_supp/wpa.c @@ -1736,6 +1736,9 @@ int wpa_sm_rx_eapol(struct wpa_sm *sm, const u8 *src_addr, wpa_msg(sm->ctx->msg_ctx, MSG_INFO, "WPA: Backwards compatibility: allow invalid " "version for non-CCMP group keys"); + } else if (ver == WPA_KEY_INFO_TYPE_AES_128_CMAC) { + wpa_msg(sm->ctx->msg_ctx, MSG_INFO, + "WPA: Interoperability workaround: allow incorrect (should have been HMAC-SHA1), but stronger (is AES-128-CMAC), descriptor version to be used"); } else goto out; } else if (sm->pairwise_cipher == WPA_CIPHER_GCMP && -- cgit v1.2.3 From a7c60b4c03ced564d424e4cae81b85f7112aa59b Mon Sep 17 00:00:00 2001 From: Jithu Jance Date: Wed, 3 Dec 2014 18:54:40 +0530 Subject: nl80211: Ignore Connect failure for the previous association Suppose there are two APs (AP1 & AP2) and user attempted to connect to AP2 before the previous connection with AP1 could succeed. Now, if the connection event comes for the older AP with failed status, we should just ignore it as the wpa_supplicant state has moved to "ASSOCIATING" with the new AP (AP2). This is a similar to the case where a disconnection event is ignored for a case where local disconnect request can cause the extra event to show up during the next association process following that command. Signed-off-by: Jithu Jance Signed-off-by: vandwalle --- src/drivers/driver_nl80211.c | 43 ++++++++++++++++++++++++++++++++++++------- 1 file changed, 36 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index d0304743..4c8f29f3 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -1591,6 +1591,7 @@ static void mlme_event_connect(struct wpa_driver_nl80211_data *drv, struct nlattr *resp_ie) { union wpa_event_data event; + u16 status_code; if (drv->capa.flags & WPA_DRIVER_FLAGS_SME) { /* @@ -1602,21 +1603,41 @@ static void mlme_event_connect(struct wpa_driver_nl80211_data *drv, return; } - if (cmd == NL80211_CMD_CONNECT) - wpa_printf(MSG_DEBUG, "nl80211: Connect event"); - else if (cmd == NL80211_CMD_ROAM) + status_code = status ? nla_get_u16(status) : WLAN_STATUS_SUCCESS; + + if (cmd == NL80211_CMD_CONNECT) { + wpa_printf(MSG_DEBUG, + "nl80211: Connect event (status=%u ignore_next_local_disconnect=%d)", + status_code, drv->ignore_next_local_disconnect); + } else if (cmd == NL80211_CMD_ROAM) { wpa_printf(MSG_DEBUG, "nl80211: Roam event"); + } os_memset(&event, 0, sizeof(event)); - if (cmd == NL80211_CMD_CONNECT && - nla_get_u16(status) != WLAN_STATUS_SUCCESS) { + if (cmd == NL80211_CMD_CONNECT && status_code != WLAN_STATUS_SUCCESS) { if (addr) event.assoc_reject.bssid = nla_data(addr); + if (drv->ignore_next_local_disconnect) { + drv->ignore_next_local_disconnect = 0; + if (!event.assoc_reject.bssid || + (os_memcmp(event.assoc_reject.bssid, + drv->auth_attempt_bssid, + ETH_ALEN) != 0)) { + /* + * Ignore the event that came without a BSSID or + * for the old connection since this is likely + * not relevant to the new Connect command. + */ + wpa_printf(MSG_DEBUG, + "nl80211: Ignore connection failure event triggered during reassociation"); + return; + } + } if (resp_ie) { event.assoc_reject.resp_ies = nla_data(resp_ie); event.assoc_reject.resp_ies_len = nla_len(resp_ie); } - event.assoc_reject.status_code = nla_get_u16(status); + event.assoc_reject.status_code = status_code; wpa_supplicant_event(drv->ctx, EVENT_ASSOC_REJECT, &event); return; } @@ -9086,7 +9107,15 @@ static int wpa_driver_nl80211_connect( struct wpa_driver_nl80211_data *drv, struct wpa_driver_associate_params *params) { - int ret = wpa_driver_nl80211_try_connect(drv, params); + int ret; + + /* Store the connection attempted bssid for future use */ + if (params->bssid) + os_memcpy(drv->auth_attempt_bssid, params->bssid, ETH_ALEN); + else + os_memset(drv->auth_attempt_bssid, 0, ETH_ALEN); + + ret = wpa_driver_nl80211_try_connect(drv, params); if (ret == -EALREADY) { /* * cfg80211 does not currently accept new connections if -- cgit v1.2.3