diff options
Diffstat (limited to 'net')
33 files changed, 1437 insertions, 1840 deletions
diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c index ef92864ac62..72eb187a5f6 100644 --- a/net/bluetooth/af_bluetooth.c +++ b/net/bluetooth/af_bluetooth.c @@ -71,19 +71,16 @@ static const char *const bt_slock_key_strings[BT_MAX_PROTO] = { "slock-AF_BLUETOOTH-BTPROTO_AVDTP", }; -static inline void bt_sock_reclassify_lock(struct socket *sock, int proto) +void bt_sock_reclassify_lock(struct sock *sk, int proto) { - struct sock *sk = sock->sk; - - if (!sk) - return; - + BUG_ON(!sk); BUG_ON(sock_owned_by_user(sk)); sock_lock_init_class_and_name(sk, bt_slock_key_strings[proto], &bt_slock_key[proto], bt_key_strings[proto], &bt_lock_key[proto]); } +EXPORT_SYMBOL(bt_sock_reclassify_lock); int bt_sock_register(int proto, const struct net_proto_family *ops) { @@ -145,7 +142,8 @@ static int bt_sock_create(struct net *net, struct socket *sock, int proto, if (bt_proto[proto] && try_module_get(bt_proto[proto]->owner)) { err = bt_proto[proto]->create(net, sock, proto, kern); - bt_sock_reclassify_lock(sock, proto); + if (!err) + bt_sock_reclassify_lock(sock->sk, proto); module_put(bt_proto[proto]->owner); } diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index 3db432473ad..07bc69ed949 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -635,6 +635,10 @@ static int hci_conn_auth(struct hci_conn *conn, __u8 sec_level, __u8 auth_type) if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->pend)) { struct hci_cp_auth_requested cp; + + /* encrypt must be pending if auth is also pending */ + set_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend); + cp.handle = cpu_to_le16(conn->handle); hci_send_cmd(conn->hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp); diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 9de93714213..5aeb6249119 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -640,7 +640,8 @@ static int hci_dev_do_close(struct hci_dev *hdev) /* Reset device */ skb_queue_purge(&hdev->cmd_q); atomic_set(&hdev->cmd_cnt, 1); - if (!test_bit(HCI_RAW, &hdev->flags)) { + if (!test_bit(HCI_RAW, &hdev->flags) && + test_bit(HCI_QUIRK_NO_RESET, &hdev->quirks)) { set_bit(HCI_INIT, &hdev->flags); __hci_request(hdev, hci_reset_req, 0, msecs_to_jiffies(250)); diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index faf0b11ac1d..32d338c30e6 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -1018,10 +1018,10 @@ static void l2cap_conn_del(struct hci_conn *hcon, int err) hci_chan_del(conn->hchan); if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) - __cancel_delayed_work(&conn->info_timer); + cancel_delayed_work_sync(&conn->info_timer); if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &hcon->pend)) { - __cancel_delayed_work(&conn->security_timer); + cancel_delayed_work_sync(&conn->security_timer); smp_chan_destroy(conn); } @@ -1120,7 +1120,7 @@ static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm, bdaddr return c1; } -inline int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, bdaddr_t *dst) +int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, bdaddr_t *dst) { struct sock *sk = chan->sk; bdaddr_t *src = &bt_sk(sk)->src; @@ -2574,7 +2574,7 @@ static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hd if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) && cmd->ident == conn->info_ident) { - __cancel_delayed_work(&conn->info_timer); + cancel_delayed_work(&conn->info_timer); conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; conn->info_ident = 0; @@ -2970,7 +2970,8 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr default: sk->sk_err = ECONNRESET; - __set_chan_timer(chan, L2CAP_DISC_REJ_TIMEOUT); + __set_chan_timer(chan, + msecs_to_jiffies(L2CAP_DISC_REJ_TIMEOUT)); l2cap_send_disconn_req(conn, chan, ECONNRESET); goto done; } @@ -3120,7 +3121,7 @@ static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cm conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) return 0; - __cancel_delayed_work(&conn->info_timer); + cancel_delayed_work(&conn->info_timer); if (result != L2CAP_IR_SUCCESS) { conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; @@ -4478,7 +4479,8 @@ static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt) if (encrypt == 0x00) { if (chan->sec_level == BT_SECURITY_MEDIUM) { __clear_chan_timer(chan); - __set_chan_timer(chan, L2CAP_ENC_TIMEOUT); + __set_chan_timer(chan, + msecs_to_jiffies(L2CAP_ENC_TIMEOUT)); } else if (chan->sec_level == BT_SECURITY_HIGH) l2cap_chan_close(chan, ECONNREFUSED); } else { @@ -4499,7 +4501,7 @@ int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) if (hcon->type == LE_LINK) { smp_distribute_keys(conn, 0); - __cancel_delayed_work(&conn->security_timer); + cancel_delayed_work(&conn->security_timer); } rcu_read_lock(); @@ -4546,7 +4548,8 @@ int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) L2CAP_CONN_REQ, sizeof(req), &req); } else { __clear_chan_timer(chan); - __set_chan_timer(chan, L2CAP_DISC_TIMEOUT); + __set_chan_timer(chan, + msecs_to_jiffies(L2CAP_DISC_TIMEOUT)); } } else if (chan->state == BT_CONNECT2) { struct l2cap_conn_rsp rsp; @@ -4566,7 +4569,8 @@ int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) } } else { l2cap_state_change(chan, BT_DISCONN); - __set_chan_timer(chan, L2CAP_DISC_TIMEOUT); + __set_chan_timer(chan, + msecs_to_jiffies(L2CAP_DISC_TIMEOUT)); res = L2CAP_CR_SEC_BLOCK; stat = L2CAP_CS_NO_INFO; } diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index c61d967012b..401d9428ae4 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -849,6 +849,8 @@ static struct l2cap_chan *l2cap_sock_new_connection_cb(void *data) if (!sk) return NULL; + bt_sock_reclassify_lock(sk, BTPROTO_L2CAP); + l2cap_sock_init(sk, parent); return l2cap_pi(sk)->chan; @@ -1002,7 +1004,7 @@ static struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock, int p INIT_LIST_HEAD(&bt_sk(sk)->accept_q); sk->sk_destruct = l2cap_sock_destruct; - sk->sk_sndtimeo = L2CAP_CONN_TIMEOUT; + sk->sk_sndtimeo = msecs_to_jiffies(L2CAP_CONN_TIMEOUT); sock_reset_flag(sk, SOCK_ZAPPED); diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c index 501649bf559..8a602388f1e 100644 --- a/net/bluetooth/rfcomm/core.c +++ b/net/bluetooth/rfcomm/core.c @@ -1164,12 +1164,18 @@ static int rfcomm_recv_ua(struct rfcomm_session *s, u8 dlci) break; case BT_DISCONN: - /* When socket is closed and we are not RFCOMM - * initiator rfcomm_process_rx already calls - * rfcomm_session_put() */ - if (s->sock->sk->sk_state != BT_CLOSED) - if (list_empty(&s->dlcs)) - rfcomm_session_put(s); + /* rfcomm_session_put is called later so don't do + * anything here otherwise we will mess up the session + * reference counter: + * + * (a) when we are the initiator dlc_unlink will drive + * the reference counter to 0 (there is no initial put + * after session_add) + * + * (b) when we are not the initiator rfcomm_rx_process + * will explicitly call put to balance the initial hold + * done after session add. + */ break; } } diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c index f066678faee..22169c3f148 100644 --- a/net/bluetooth/rfcomm/sock.c +++ b/net/bluetooth/rfcomm/sock.c @@ -956,6 +956,8 @@ int rfcomm_connect_ind(struct rfcomm_session *s, u8 channel, struct rfcomm_dlc * if (!sk) goto done; + bt_sock_reclassify_lock(sk, BTPROTO_RFCOMM); + rfcomm_sock_init(sk, parent); bacpy(&bt_sk(sk)->src, &src); bacpy(&bt_sk(sk)->dst, &dst); diff --git a/net/mac80211/Makefile b/net/mac80211/Makefile index d540c3b160f..1be7a454aa7 100644 --- a/net/mac80211/Makefile +++ b/net/mac80211/Makefile @@ -9,7 +9,7 @@ mac80211-y := \ scan.o offchannel.o \ ht.o agg-tx.o agg-rx.o \ ibss.o \ - mlme.o work.o \ + work.o \ iface.o \ rate.o \ michael.o \ @@ -25,7 +25,7 @@ mac80211-y := \ wme.o \ event.o \ chan.o \ - driver-trace.o + driver-trace.o mlme.o mac80211-$(CONFIG_MAC80211_LEDS) += led.o mac80211-$(CONFIG_MAC80211_DEBUGFS) += \ diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index d15ba0d0de9..c3de921c8cf 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -2028,7 +2028,7 @@ ieee80211_offchan_tx_done(struct ieee80211_work *wk, struct sk_buff *skb) if (wk->offchan_tx.wait && !wk->offchan_tx.status) cfg80211_mgmt_tx_status(wk->sdata->dev, (unsigned long) wk->offchan_tx.frame, - wk->ie, wk->ie_len, false, GFP_KERNEL); + wk->data, wk->data_len, false, GFP_KERNEL); return WORK_DONE_DESTROY; } @@ -2179,8 +2179,8 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev, wk->done = ieee80211_offchan_tx_done; wk->offchan_tx.frame = skb; wk->offchan_tx.wait = wait; - wk->ie_len = len; - memcpy(wk->ie, buf, len); + wk->data_len = len; + memcpy(wk->data, buf, len); ieee80211_add_work(wk); return 0; diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c index affe64be909..483e96ed95c 100644 --- a/net/mac80211/debugfs.c +++ b/net/mac80211/debugfs.c @@ -263,6 +263,8 @@ static ssize_t hwflags_read(struct file *file, char __user *user_buf, sf += snprintf(buf + sf, mxln - sf, "AP_LINK_PS\n"); if (local->hw.flags & IEEE80211_HW_TX_AMPDU_SETUP_IN_HW) sf += snprintf(buf + sf, mxln - sf, "TX_AMPDU_SETUP_IN_HW\n"); + if (local->hw.flags & IEEE80211_HW_SCAN_WHILE_IDLE) + sf += snprintf(buf + sf, mxln - sf, "SCAN_WHILE_IDLE\n"); rv = simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf)); kfree(buf); diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c index c8383712fde..6d45804d09b 100644 --- a/net/mac80211/debugfs_sta.c +++ b/net/mac80211/debugfs_sta.c @@ -63,7 +63,7 @@ static ssize_t sta_flags_read(struct file *file, char __user *userbuf, test_sta_flag(sta, WLAN_STA_##flg) ? #flg "\n" : "" int res = scnprintf(buf, sizeof(buf), - "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", + "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", TEST(AUTH), TEST(ASSOC), TEST(PS_STA), TEST(PS_DRIVER), TEST(AUTHORIZED), TEST(SHORT_PREAMBLE), @@ -71,7 +71,7 @@ static ssize_t sta_flags_read(struct file *file, char __user *userbuf, TEST(MFP), TEST(BLOCK_BA), TEST(PSPOLL), TEST(UAPSD), TEST(SP), TEST(TDLS_PEER), TEST(TDLS_PEER_AUTH), TEST(4ADDR_EVENT), - TEST(INSERTED)); + TEST(INSERTED), TEST(RATE_CONTROL)); #undef TEST return simple_read_from_buffer(userbuf, count, ppos, buf, res); } diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h index e8960ae3986..70dfb6415c2 100644 --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h @@ -253,6 +253,7 @@ static inline int drv_set_key(struct ieee80211_local *local, might_sleep(); + sdata = get_bss_sdata(sdata); check_sdata_in_driver(sdata); trace_drv_set_key(local, cmd, sdata, sta, key); @@ -272,6 +273,7 @@ static inline void drv_update_tkip_key(struct ieee80211_local *local, if (sta) ista = &sta->sta; + sdata = get_bss_sdata(sdata); check_sdata_in_driver(sdata); trace_drv_update_tkip_key(local, sdata, conf, ista, iv32); @@ -476,6 +478,37 @@ static inline void drv_sta_remove(struct ieee80211_local *local, trace_drv_return_void(local); } +static inline __must_check +int drv_sta_state(struct ieee80211_local *local, + struct ieee80211_sub_if_data *sdata, + struct sta_info *sta, + enum ieee80211_sta_state old_state, + enum ieee80211_sta_state new_state) +{ + int ret = 0; + + might_sleep(); + + sdata = get_bss_sdata(sdata); + check_sdata_in_driver(sdata); + + trace_drv_sta_state(local, sdata, &sta->sta, old_state, new_state); + if (local->ops->sta_state) { + ret = local->ops->sta_state(&local->hw, &sdata->vif, &sta->sta, + old_state, new_state); + } else if (old_state == IEEE80211_STA_AUTH && + new_state == IEEE80211_STA_ASSOC) { + ret = drv_sta_add(local, sdata, &sta->sta); + if (ret == 0) + sta->uploaded = true; + } else if (old_state == IEEE80211_STA_ASSOC && + new_state == IEEE80211_STA_AUTH) { + drv_sta_remove(local, sdata, &sta->sta); + } + trace_drv_return_int(local, ret); + return ret; +} + static inline int drv_conf_tx(struct ieee80211_local *local, struct ieee80211_sub_if_data *sdata, u16 queue, const struct ieee80211_tx_queue_params *params) diff --git a/net/mac80211/driver-trace.h b/net/mac80211/driver-trace.h index 6e9df8fd8fb..384e2f08c18 100644 --- a/net/mac80211/driver-trace.h +++ b/net/mac80211/driver-trace.h @@ -635,6 +635,38 @@ TRACE_EVENT(drv_sta_notify, ) ); +TRACE_EVENT(drv_sta_state, + TP_PROTO(struct ieee80211_local *local, + struct ieee80211_sub_if_data *sdata, + struct ieee80211_sta *sta, + enum ieee80211_sta_state old_state, + enum ieee80211_sta_state new_state), + + TP_ARGS(local, sdata, sta, old_state, new_state), + + TP_STRUCT__entry( + LOCAL_ENTRY + VIF_ENTRY + STA_ENTRY + __field(u32, old_state) + __field(u32, new_state) + ), + + TP_fast_assign( + LOCAL_ASSIGN; + VIF_ASSIGN; + STA_ASSIGN; + __entry->old_state = old_state; + __entry->new_state = new_state; + ), + + TP_printk( + LOCAL_PR_FMT VIF_PR_FMT STA_PR_FMT " state: %d->%d", + LOCAL_PR_ARG, VIF_PR_ARG, STA_PR_ARG, + __entry->old_state, __entry->new_state + ) +); + TRACE_EVENT(drv_sta_add, TP_PROTO(struct ieee80211_local *local, struct ieee80211_sub_if_data *sdata, diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index 7b3a0b0aa24..8361da4b36a 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c @@ -268,7 +268,10 @@ static struct sta_info *ieee80211_ibss_finish_sta(struct sta_info *sta, sta_info_pre_move_state(sta, IEEE80211_STA_AUTH); sta_info_pre_move_state(sta, IEEE80211_STA_ASSOC); - sta_info_pre_move_state(sta, IEEE80211_STA_AUTHORIZED); + /* authorize the station only if the network is not RSN protected. If + * not wait for the userspace to authorize it */ + if (!sta->sdata->u.ibss.control_port) + sta_info_pre_move_state(sta, IEEE80211_STA_AUTHORIZED); rate_control_rate_init(sta); @@ -1075,6 +1078,7 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata, sdata->u.ibss.fixed_bssid = false; sdata->u.ibss.privacy = params->privacy; + sdata->u.ibss.control_port = params->control_port; sdata->u.ibss.basic_rates = params->basic_rates; memcpy(sdata->vif.bss_conf.mcast_rate, params->mcast_rate, sizeof(params->mcast_rate)); diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index d47e8c110b1..74594f012cd 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -280,10 +280,6 @@ struct mesh_preq_queue { enum ieee80211_work_type { IEEE80211_WORK_ABORT, - IEEE80211_WORK_DIRECT_PROBE, - IEEE80211_WORK_AUTH, - IEEE80211_WORK_ASSOC_BEACON_WAIT, - IEEE80211_WORK_ASSOC, IEEE80211_WORK_REMAIN_ON_CHANNEL, IEEE80211_WORK_OFFCHANNEL_TX, }; @@ -316,36 +312,10 @@ struct ieee80211_work { unsigned long timeout; enum ieee80211_work_type type; - u8 filter_ta[ETH_ALEN]; - bool started; union { struct { - int tries; - u16 algorithm, transaction; - u8 ssid[IEEE80211_MAX_SSID_LEN]; - u8 ssid_len; - u8 key[WLAN_KEY_LEN_WEP104]; - u8 key_len, key_idx; - bool privacy; - bool synced; - } probe_auth; - struct { - struct cfg80211_bss *bss; - const u8 *supp_rates; - const u8 *ht_information_ie; - enum ieee80211_smps_mode smps; - int tries; - u16 capability; - u8 prev_bssid[ETH_ALEN]; - u8 ssid[IEEE80211_MAX_SSID_LEN]; - u8 ssid_len; - u8 supp_rates_len; - bool wmm_used, use_11n, uapsd_used; - bool synced; - } assoc; - struct { u32 duration; } remain; struct { @@ -355,9 +325,8 @@ struct ieee80211_work { } offchan_tx; }; - int ie_len; - /* must be last */ - u8 ie[0]; + size_t data_len; + u8 data[]; }; /* flags used in struct ieee80211_if_managed.flags */ @@ -373,6 +342,43 @@ enum ieee80211_sta_flags { IEEE80211_STA_RESET_SIGNAL_AVE = BIT(9), }; +struct ieee80211_mgd_auth_data { + struct cfg80211_bss *bss; + unsigned long timeout; + int tries; + u16 algorithm, expected_transaction; + + u8 key[WLAN_KEY_LEN_WEP104]; + u8 key_len, key_idx; + bool synced; + bool done; + + size_t ie_len; + u8 ie[]; +}; + +struct ieee80211_mgd_assoc_data { + struct cfg80211_bss *bss; + const u8 *supp_rates; + const u8 *ht_information_ie; + + unsigned long timeout; + int tries; + + u16 capability; + u8 prev_bssid[ETH_ALEN]; + u8 ssid[IEEE80211_MAX_SSID_LEN]; + u8 ssid_len; + u8 supp_rates_len; + bool wmm_used, uapsd_used; + bool have_beacon; + bool sent_assoc; + bool synced; + + size_t ie_len; + u8 ie[]; +}; + struct ieee80211_if_managed { struct timer_list timer; struct timer_list conn_mon_timer; @@ -389,6 +395,8 @@ struct ieee80211_if_managed { struct mutex mtx; struct cfg80211_bss *associated; + struct ieee80211_mgd_auth_data *auth_data; + struct ieee80211_mgd_assoc_data *assoc_data; u8 bssid[ETH_ALEN]; @@ -470,6 +478,8 @@ struct ieee80211_if_ibss { bool fixed_channel; bool privacy; + bool control_port; + u8 bssid[ETH_ALEN]; u8 ssid[IEEE80211_MAX_SSID_LEN]; u8 ssid_len, ie_len; @@ -770,7 +780,6 @@ struct ieee80211_local { struct list_head work_list; struct timer_list work_timer; struct work_struct work_work; - struct sk_buff_head work_skb_queue; /* * private workqueue to mac80211. mac80211 makes this accessible @@ -1437,8 +1446,6 @@ void ieee80211_work_init(struct ieee80211_local *local); void ieee80211_add_work(struct ieee80211_work *wk); void free_work(struct ieee80211_work *wk); void ieee80211_work_purge(struct ieee80211_sub_if_data *sdata); -ieee80211_rx_result ieee80211_work_rx_mgmt(struct ieee80211_sub_if_data *sdata, - struct sk_buff *skb); int ieee80211_wk_remain_on_channel(struct ieee80211_sub_if_data *sdata, struct ieee80211_channel *chan, enum nl80211_channel_type channel_type, diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 2efd595b2f7..6b3cd65d1e0 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -1310,7 +1310,9 @@ u32 __ieee80211_recalc_idle(struct ieee80211_local *local) /* do not count disabled managed interfaces */ if (sdata->vif.type == NL80211_IFTYPE_STATION && - !sdata->u.mgd.associated) { + !sdata->u.mgd.associated && + !sdata->u.mgd.auth_data && + !sdata->u.mgd.assoc_data) { sdata->vif.bss_conf.idle = true; continue; } @@ -1330,7 +1332,8 @@ u32 __ieee80211_recalc_idle(struct ieee80211_local *local) wk->sdata->vif.bss_conf.idle = false; } - if (local->scan_sdata) { + if (local->scan_sdata && + !(local->hw.flags & IEEE80211_HW_SCAN_WHILE_IDLE)) { scanning = true; local->scan_sdata->vif.bss_conf.idle = false; } diff --git a/net/mac80211/key.c b/net/mac80211/key.c index 87a89741432..e8616b3ff63 100644 --- a/net/mac80211/key.c +++ b/net/mac80211/key.c @@ -54,14 +54,6 @@ static void assert_key_lock(struct ieee80211_local *local) lockdep_assert_held(&local->key_mtx); } -static struct ieee80211_sta *get_sta_for_key(struct ieee80211_key *key) -{ - if (key->sta) - return &key->sta->sta; - - return NULL; -} - static void increment_tailroom_need_count(struct ieee80211_sub_if_data *sdata) { /* @@ -95,7 +87,7 @@ static void increment_tailroom_need_count(struct ieee80211_sub_if_data *sdata) static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key) { struct ieee80211_sub_if_data *sdata; - struct ieee80211_sta *sta; + struct sta_info *sta; int ret; might_sleep(); @@ -105,7 +97,7 @@ static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key) assert_key_lock(key->local); - sta = get_sta_for_key(key); + sta = key->sta; /* * If this is a per-STA GTK, check if it @@ -115,6 +107,9 @@ static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key) !(key->local->hw.flags & IEEE80211_HW_SUPPORTS_PER_STA_GTK)) goto out_unsupported; + if (sta && !sta->uploaded) + goto out_unsupported; + sdata = key->sdata; if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) { /* @@ -123,12 +118,10 @@ static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key) */ if (!(key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE)) goto out_unsupported; - sdata = container_of(sdata->bss, - struct ieee80211_sub_if_data, - u.ap); } - ret = drv_set_key(key->local, SET_KEY, sdata, sta, &key->conf); + ret = drv_set_key(key->local, SET_KEY, sdata, + sta ? &sta->sta : NULL, &key->conf); if (!ret) { key->flags |= KEY_FLAG_UPLOADED_TO_HARDWARE; @@ -147,7 +140,8 @@ static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key) if (ret != -ENOSPC && ret != -EOPNOTSUPP) wiphy_err(key->local->hw.wiphy, "failed to set key (%d, %pM) to hardware (%d)\n", - key->conf.keyidx, sta ? sta->addr : bcast_addr, ret); + key->conf.keyidx, + sta ? sta->sta.addr : bcast_addr, ret); out_unsupported: switch (key->conf.cipher) { @@ -166,7 +160,7 @@ static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key) static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key) { struct ieee80211_sub_if_data *sdata; - struct ieee80211_sta *sta; + struct sta_info *sta; int ret; might_sleep(); @@ -179,7 +173,7 @@ static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key) if (!(key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)) return; - sta = get_sta_for_key(key); + sta = key->sta; sdata = key->sdata; if (!((key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC) || @@ -187,18 +181,14 @@ static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key) (key->conf.flags & IEEE80211_KEY_FLAG_PUT_IV_SPACE))) increment_tailroom_need_count(sdata); - if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) - sdata = container_of(sdata->bss, - struct ieee80211_sub_if_data, - u.ap); - ret = drv_set_key(key->local, DISABLE_KEY, sdata, - sta, &key->conf); + sta ? &sta->sta : NULL, &key->conf); if (ret) wiphy_err(key->local->hw.wiphy, "failed to remove key (%d, %pM) from hardware (%d)\n", - key->conf.keyidx, sta ? sta->addr : bcast_addr, ret); + key->conf.keyidx, + sta ? sta->sta.addr : bcast_addr, ret); key->flags &= ~KEY_FLAG_UPLOADED_TO_HARDWARE; } diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 0ec18618fcf..2306d7514ff 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -199,15 +199,7 @@ void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata, return; if (sdata->vif.type == NL80211_IFTYPE_STATION) { - /* - * While not associated, claim a BSSID of all-zeroes - * so that drivers don't do any weird things with the - * BSSID at that time. - */ - if (sdata->vif.bss_conf.assoc) - sdata->vif.bss_conf.bssid = sdata->u.mgd.bssid; - else - sdata->vif.bss_conf.bssid = zero; + sdata->vif.bss_conf.bssid = sdata->u.mgd.bssid; } else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) sdata->vif.bss_conf.bssid = sdata->u.ibss.bssid; else if (sdata->vif.type == NL80211_IFTYPE_AP) @@ -535,6 +527,9 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, int priv_size, i; struct wiphy *wiphy; + if (WARN_ON(ops->sta_state && (ops->sta_add || ops->sta_remove))) + return NULL; + /* Ensure 32-byte alignment of our private data and hw private data. * We use the wiphy priv data for both our ieee80211_local and for * the driver's private data @@ -702,6 +697,9 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) ) return -EINVAL; + if ((hw->flags & IEEE80211_HW_SCAN_WHILE_IDLE) && !local->ops->hw_scan) + return -EINVAL; + if (hw->max_report_rates == 0) hw->max_report_rates = hw->max_rates; diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c index edf167e3b8f..dc51669e67d 100644 --- a/net/mac80211/mesh_pathtbl.c +++ b/net/mac80211/mesh_pathtbl.c @@ -336,7 +336,7 @@ static void mesh_path_move_to_queue(struct mesh_path *gate_mpath, } -static struct mesh_path *path_lookup(struct mesh_table *tbl, u8 *dst, +static struct mesh_path *mpath_lookup(struct mesh_table *tbl, u8 *dst, struct ieee80211_sub_if_data *sdata) { struct mesh_path *mpath; @@ -371,12 +371,12 @@ static struct mesh_path *path_lookup(struct mesh_table *tbl, u8 *dst, */ struct mesh_path *mesh_path_lookup(u8 *dst, struct ieee80211_sub_if_data *sdata) { - return path_lookup(rcu_dereference(mesh_paths), dst, sdata); + return mpath_lookup(rcu_dereference(mesh_paths), dst, sdata); } struct mesh_path *mpp_path_lookup(u8 *dst, struct ieee80211_sub_if_data *sdata) { - return path_lookup(rcu_dereference(mpp_paths), dst, sdata); + return mpath_lookup(rcu_dereference(mpp_paths), dst, sdata); } diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 49fd1acd5d1..52133dab929 100644 |