From 9ae3b172e886c851d8cd6a88569025160b485e95 Mon Sep 17 00:00:00 2001 From: Tova Mussai Date: Sun, 29 Oct 2017 11:51:11 +0200 Subject: cfg80211: IBSS: Add support for static WEP in driver for IBSS Add support for drivers that implement static WEP internally for IBSS. Add the WEP keys to the IBSS params struct, that will allow the driver to use the keys in the join flow, and not only after the connection. Signed-off-by: Tova Mussai Signed-off-by: Luca Coelho Signed-off-by: Johannes Berg --- net/wireless/ibss.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'net/wireless') diff --git a/net/wireless/ibss.c b/net/wireless/ibss.c index 413d4f4e6334..a1d10993d08a 100644 --- a/net/wireless/ibss.c +++ b/net/wireless/ibss.c @@ -126,6 +126,11 @@ static int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev, wdev->ibss_fixed = params->channel_fixed; wdev->ibss_dfs_possible = params->userspace_handles_dfs; wdev->chandef = params->chandef; + if (connkeys) { + params->wep_keys = connkeys->params; + params->wep_tx_key = connkeys->def; + } + #ifdef CONFIG_CFG80211_WEXT wdev->wext.ibss.chandef = params->chandef; #endif -- cgit 1.4.1 From 6c2fb1e6527b1092e09c786fee66b1759fa9d574 Mon Sep 17 00:00:00 2001 From: Sergey Matyukevich Date: Thu, 9 Nov 2017 14:46:30 +0300 Subject: cfg80211: cleanup signal strength units notation Both cfg80211_rx_mgmt and cfg80211_report_obss_beacon functions send reports to userspace using NL80211_ATTR_RX_SIGNAL_DBM attribute w/o any processing of their input signal values. Which means that in order to match userspace tools expectations, input signal values for those functions are supposed to be in dBm units. This patch cleans up comments, variable names, and trace reports for those functions, replacing confusing 'mBm' by 'dBm'. Signed-off-by: Sergey Matyukevich Signed-off-by: Johannes Berg --- include/net/cfg80211.h | 4 ++-- net/wireless/mlme.c | 6 +++--- net/wireless/trace.h | 12 ++++++------ 3 files changed, 11 insertions(+), 11 deletions(-) (limited to 'net/wireless') diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 698cebf2de2a..d7f8e7b96bcb 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -5581,7 +5581,7 @@ void cfg80211_conn_failed(struct net_device *dev, const u8 *mac_addr, * cfg80211_rx_mgmt - notification of received, unprocessed management frame * @wdev: wireless device receiving the frame * @freq: Frequency on which the frame was received in MHz - * @sig_dbm: signal strength in mBm, or 0 if unknown + * @sig_dbm: signal strength in dBm, or 0 if unknown * @buf: Management frame (header + body) * @len: length of the frame data * @flags: flags, as defined in enum nl80211_rxmgmt_flags @@ -5760,7 +5760,7 @@ void cfg80211_probe_status(struct net_device *dev, const u8 *addr, * @frame: the frame * @len: length of the frame * @freq: frequency the frame was received on - * @sig_dbm: signal strength in mBm, or 0 if unknown + * @sig_dbm: signal strength in dBm, or 0 if unknown * * Use this function to report to userspace when a beacon was * received. It is not useful to call this when there is no diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c index e7c64a8dce54..bbb9907bfa86 100644 --- a/net/wireless/mlme.c +++ b/net/wireless/mlme.c @@ -692,7 +692,7 @@ int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev, return rdev_mgmt_tx(rdev, wdev, params, cookie); } -bool cfg80211_rx_mgmt(struct wireless_dev *wdev, int freq, int sig_mbm, +bool cfg80211_rx_mgmt(struct wireless_dev *wdev, int freq, int sig_dbm, const u8 *buf, size_t len, u32 flags) { struct wiphy *wiphy = wdev->wiphy; @@ -708,7 +708,7 @@ bool cfg80211_rx_mgmt(struct wireless_dev *wdev, int freq, int sig_mbm, cpu_to_le16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE); u16 stype; - trace_cfg80211_rx_mgmt(wdev, freq, sig_mbm); + trace_cfg80211_rx_mgmt(wdev, freq, sig_dbm); stype = (le16_to_cpu(mgmt->frame_control) & IEEE80211_FCTL_STYPE) >> 4; if (!(stypes->rx & BIT(stype))) { @@ -735,7 +735,7 @@ bool cfg80211_rx_mgmt(struct wireless_dev *wdev, int freq, int sig_mbm, /* Indicate the received Action frame to user space */ if (nl80211_send_mgmt(rdev, wdev, reg->nlportid, - freq, sig_mbm, + freq, sig_dbm, buf, len, flags, GFP_ATOMIC)) continue; diff --git a/net/wireless/trace.h b/net/wireless/trace.h index f3353fe5b35b..bcfedd39e7a3 100644 --- a/net/wireless/trace.h +++ b/net/wireless/trace.h @@ -2544,20 +2544,20 @@ DEFINE_EVENT(cfg80211_netdev_mac_evt, cfg80211_del_sta, ); TRACE_EVENT(cfg80211_rx_mgmt, - TP_PROTO(struct wireless_dev *wdev, int freq, int sig_mbm), - TP_ARGS(wdev, freq, sig_mbm), + TP_PROTO(struct wireless_dev *wdev, int freq, int sig_dbm), + TP_ARGS(wdev, freq, sig_dbm), TP_STRUCT__entry( WDEV_ENTRY __field(int, freq) - __field(int, sig_mbm) + __field(int, sig_dbm) ), TP_fast_assign( WDEV_ASSIGN; __entry->freq = freq; - __entry->sig_mbm = sig_mbm; + __entry->sig_dbm = sig_dbm; ), - TP_printk(WDEV_PR_FMT ", freq: %d, sig mbm: %d", - WDEV_PR_ARG, __entry->freq, __entry->sig_mbm) + TP_printk(WDEV_PR_FMT ", freq: %d, sig dbm: %d", + WDEV_PR_ARG, __entry->freq, __entry->sig_dbm) ); TRACE_EVENT(cfg80211_mgmt_tx_status, -- cgit 1.4.1 From 768075ebc238d11900b27975e649286d292eb8cf Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 13 Nov 2017 15:35:06 +0100 Subject: nl80211: add a few extended error strings to key parsing This mostly serves as an example for how to add error strings and erroneous attribute pointers. Signed-off-by: Johannes Berg --- net/wireless/nl80211.c | 61 +++++++++++++++++++++++++++++++++----------------- 1 file changed, 41 insertions(+), 20 deletions(-) (limited to 'net/wireless') diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index b1ac23ca20c8..e4522ad5f770 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -734,11 +734,12 @@ struct key_parse { bool def_uni, def_multi; }; -static int nl80211_parse_key_new(struct nlattr *key, struct key_parse *k) +static int nl80211_parse_key_new(struct genl_info *info, struct nlattr *key, + struct key_parse *k) { struct nlattr *tb[NL80211_KEY_MAX + 1]; int err = nla_parse_nested(tb, NL80211_KEY_MAX, key, - nl80211_key_policy, NULL); + nl80211_key_policy, info->extack); if (err) return err; @@ -771,7 +772,8 @@ static int nl80211_parse_key_new(struct nlattr *key, struct key_parse *k) if (tb[NL80211_KEY_TYPE]) { k->type = nla_get_u32(tb[NL80211_KEY_TYPE]); if (k->type < 0 || k->type >= NUM_NL80211_KEYTYPES) - return -EINVAL; + return genl_err_attr(info, -EINVAL, + tb[NL80211_KEY_TYPE]); } if (tb[NL80211_KEY_DEFAULT_TYPES]) { @@ -779,7 +781,8 @@ static int nl80211_parse_key_new(struct nlattr *key, struct key_parse *k) err = nla_parse_nested(kdt, NUM_NL80211_KEY_DEFAULT_TYPES - 1, tb[NL80211_KEY_DEFAULT_TYPES], - nl80211_key_default_policy, NULL); + nl80211_key_default_policy, + info->extack); if (err) return err; @@ -820,8 +823,10 @@ static int nl80211_parse_key_old(struct genl_info *info, struct key_parse *k) if (info->attrs[NL80211_ATTR_KEY_TYPE]) { k->type = nla_get_u32(info->attrs[NL80211_ATTR_KEY_TYPE]); - if (k->type < 0 || k->type >= NUM_NL80211_KEYTYPES) + if (k->type < 0 || k->type >= NUM_NL80211_KEYTYPES) { + GENL_SET_ERR_MSG(info, "key type out of range"); return -EINVAL; + } } if (info->attrs[NL80211_ATTR_KEY_DEFAULT_TYPES]) { @@ -850,31 +855,42 @@ static int nl80211_parse_key(struct genl_info *info, struct key_parse *k) k->type = -1; if (info->attrs[NL80211_ATTR_KEY]) - err = nl80211_parse_key_new(info->attrs[NL80211_ATTR_KEY], k); + err = nl80211_parse_key_new(info, info->attrs[NL80211_ATTR_KEY], k); else err = nl80211_parse_key_old(info, k); if (err) return err; - if (k->def && k->defmgmt) + if (k->def && k->defmgmt) { + GENL_SET_ERR_MSG(info, "key with def && defmgmt is invalid"); return -EINVAL; + } if (k->defmgmt) { - if (k->def_uni || !k->def_multi) + if (k->def_uni || !k->def_multi) { + GENL_SET_ERR_MSG(info, "defmgmt key must be mcast"); return -EINVAL; + } } if (k->idx != -1) { if (k->defmgmt) { - if (k->idx < 4 || k->idx > 5) + if (k->idx < 4 || k->idx > 5) { + GENL_SET_ERR_MSG(info, + "defmgmt key idx not 4 or 5"); return -EINVAL; + } } else if (k->def) { - if (k->idx < 0 || k->idx > 3) + if (k->idx < 0 || k->idx > 3) { + GENL_SET_ERR_MSG(info, "def key idx not 0-3"); return -EINVAL; + } } else { - if (k->idx < 0 || k->idx > 5) + if (k->idx < 0 || k->idx > 5) { + GENL_SET_ERR_MSG(info, "key idx not 0-5"); return -EINVAL; + } } } @@ -883,8 +899,9 @@ static int nl80211_parse_key(struct genl_info *info, struct key_parse *k) static struct cfg80211_cached_keys * nl80211_parse_connkeys(struct cfg80211_registered_device *rdev, - struct nlattr *keys, bool *no_ht) + struct genl_info *info, bool *no_ht) { + struct nlattr *keys = info->attrs[NL80211_ATTR_KEYS]; struct key_parse parse; struct nlattr *key; struct cfg80211_cached_keys *result; @@ -909,17 +926,22 @@ nl80211_parse_connkeys(struct cfg80211_registered_device *rdev, memset(&parse, 0, sizeof(parse)); parse.idx = -1; - err = nl80211_parse_key_new(key, &parse); + err = nl80211_parse_key_new(info, key, &parse); if (err) goto error; err = -EINVAL; if (!parse.p.key) goto error; - if (parse.idx < 0 || parse.idx > 3) + if (parse.idx < 0 || parse.idx > 3) { + GENL_SET_ERR_MSG(info, "key index out of range [0-3]"); goto error; + } if (parse.def) { - if (def) + if (def) { + GENL_SET_ERR_MSG(info, + "only one key can be default"); goto error; + } def = 1; result->def = parse.idx; if (!parse.def_uni || !parse.def_multi) @@ -932,6 +954,7 @@ nl80211_parse_connkeys(struct cfg80211_registered_device *rdev, goto error; if (parse.p.cipher != WLAN_CIPHER_SUITE_WEP40 && parse.p.cipher != WLAN_CIPHER_SUITE_WEP104) { + GENL_SET_ERR_MSG(info, "connect key must be WEP"); err = -EINVAL; goto error; } @@ -947,6 +970,7 @@ nl80211_parse_connkeys(struct cfg80211_registered_device *rdev, if (result->def < 0) { err = -EINVAL; + GENL_SET_ERR_MSG(info, "need a default/TX key"); goto error; } @@ -8611,9 +8635,7 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info) if (ibss.privacy && info->attrs[NL80211_ATTR_KEYS]) { bool no_ht = false; - connkeys = nl80211_parse_connkeys(rdev, - info->attrs[NL80211_ATTR_KEYS], - &no_ht); + connkeys = nl80211_parse_connkeys(rdev, info, &no_ht); if (IS_ERR(connkeys)) return PTR_ERR(connkeys); @@ -9017,8 +9039,7 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info) } if (connect.privacy && info->attrs[NL80211_ATTR_KEYS]) { - connkeys = nl80211_parse_connkeys(rdev, - info->attrs[NL80211_ATTR_KEYS], NULL); + connkeys = nl80211_parse_connkeys(rdev, info, NULL); if (IS_ERR(connkeys)) return PTR_ERR(connkeys); } -- cgit 1.4.1 From 86b6c465727cc917ec8367fef29b20ccf8ffa081 Mon Sep 17 00:00:00 2001 From: David Spinadel Date: Mon, 18 Dec 2017 12:14:05 +0200 Subject: nl80211: send deauth reason if locally generated Send disconnection reason code to user space even if it's locally generated, since some tests that check reason code may fail because of the current behavior. Signed-off-by: David Spinadel Signed-off-by: Luca Coelho Signed-off-by: Johannes Berg --- net/wireless/nl80211.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net/wireless') diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index e4522ad5f770..e4dddfb64ced 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -13963,7 +13963,7 @@ void nl80211_send_disconnected(struct cfg80211_registered_device *rdev, if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) || - (from_ap && reason && + (reason && nla_put_u16(msg, NL80211_ATTR_REASON_CODE, reason)) || (from_ap && nla_put_flag(msg, NL80211_ATTR_DISCONNECTED_BY_AP)) || -- cgit 1.4.1 From 983dafaab799511e092ffd006f3a064b37ccbccf Mon Sep 17 00:00:00 2001 From: Sunil Dutt Date: Wed, 13 Dec 2017 19:51:36 +0200 Subject: cfg80211: Scan results to also report the per chain signal strength This commit enhances the scan results to report the per chain signal strength based on the latest BSS update. This provides similar information to what is already available through STA information. Signed-off-by: Sunil Dutt Signed-off-by: Jouni Malinen Signed-off-by: Johannes Berg --- include/net/cfg80211.h | 8 ++++++++ include/uapi/linux/nl80211.h | 4 ++++ net/wireless/nl80211.c | 5 +++++ net/wireless/scan.c | 5 +++++ 4 files changed, 22 insertions(+) (limited to 'net/wireless') diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index d7f8e7b96bcb..3a4a1a903a4d 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -1773,6 +1773,8 @@ enum cfg80211_signal_type { * by %parent_bssid. * @parent_bssid: the BSS according to which %parent_tsf is set. This is set to * the BSS that requested the scan in which the beacon/probe was received. + * @chains: bitmask for filled values in @chain_signal. + * @chain_signal: per-chain signal strength of last received BSS in dBm. */ struct cfg80211_inform_bss { struct ieee80211_channel *chan; @@ -1781,6 +1783,8 @@ struct cfg80211_inform_bss { u64 boottime_ns; u64 parent_tsf; u8 parent_bssid[ETH_ALEN] __aligned(2); + u8 chains; + s8 chain_signal[IEEE80211_MAX_CHAINS]; }; /** @@ -1824,6 +1828,8 @@ struct cfg80211_bss_ies { * that holds the beacon data. @beacon_ies is still valid, of course, and * points to the same data as hidden_beacon_bss->beacon_ies in that case. * @signal: signal strength value (type depends on the wiphy's signal_type) + * @chains: bitmask for filled values in @chain_signal. + * @chain_signal: per-chain signal strength of last received BSS in dBm. * @priv: private area for driver use, has at least wiphy->bss_priv_size bytes */ struct cfg80211_bss { @@ -1842,6 +1848,8 @@ struct cfg80211_bss { u16 capability; u8 bssid[ETH_ALEN]; + u8 chains; + s8 chain_signal[IEEE80211_MAX_CHAINS]; u8 priv[0] __aligned(sizeof(void *)); }; diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h index f882fe1f9709..c587a61c32bf 100644 --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h @@ -3862,6 +3862,9 @@ enum nl80211_bss_scan_width { * @NL80211_BSS_PARENT_BSSID. (u64). * @NL80211_BSS_PARENT_BSSID: the BSS according to which @NL80211_BSS_PARENT_TSF * is set. + * @NL80211_BSS_CHAIN_SIGNAL: per-chain signal strength of last BSS update. + * Contains a nested array of signal strength attributes (u8, dBm), + * using the nesting index as the antenna number. * @__NL80211_BSS_AFTER_LAST: internal * @NL80211_BSS_MAX: highest BSS attribute */ @@ -3885,6 +3888,7 @@ enum nl80211_bss { NL80211_BSS_PAD, NL80211_BSS_PARENT_TSF, NL80211_BSS_PARENT_BSSID, + NL80211_BSS_CHAIN_SIGNAL, /* keep last */ __NL80211_BSS_AFTER_LAST, diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index e4dddfb64ced..b3f8970c3a47 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -7839,6 +7839,11 @@ static int nl80211_send_bss(struct sk_buff *msg, struct netlink_callback *cb, intbss->ts_boottime, NL80211_BSS_PAD)) goto nla_put_failure; + if (!nl80211_put_signal(msg, intbss->pub.chains, + intbss->pub.chain_signal, + NL80211_BSS_CHAIN_SIGNAL)) + goto nla_put_failure; + switch (rdev->wiphy.signal_type) { case CFG80211_SIGNAL_TYPE_MBM: if (nla_put_u32(msg, NL80211_BSS_SIGNAL_MBM, res->signal)) diff --git a/net/wireless/scan.c b/net/wireless/scan.c index f6c5fe482506..d36c3eb7b931 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c @@ -981,6 +981,9 @@ cfg80211_bss_update(struct cfg80211_registered_device *rdev, found->ts = tmp->ts; found->ts_boottime = tmp->ts_boottime; found->parent_tsf = tmp->parent_tsf; + found->pub.chains = tmp->pub.chains; + memcpy(found->pub.chain_signal, tmp->pub.chain_signal, + IEEE80211_MAX_CHAINS); ether_addr_copy(found->parent_bssid, tmp->parent_bssid); } else { struct cfg80211_internal_bss *new; @@ -1233,6 +1236,8 @@ cfg80211_inform_bss_frame_data(struct wiphy *wiphy, tmp.pub.capability = le16_to_cpu(mgmt->u.probe_resp.capab_info); tmp.ts_boottime = data->boottime_ns; tmp.parent_tsf = data->parent_tsf; + tmp.pub.chains = data->chains; + memcpy(tmp.pub.chain_signal, data->chain_signal, IEEE80211_MAX_CHAINS); ether_addr_copy(tmp.parent_bssid, data->parent_bssid); signal_valid = abs(data->chan->center_freq - channel->center_freq) <= -- cgit 1.4.1