diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/mac80211/cfg.c | 42 | ||||
-rw-r--r-- | net/mac80211/ieee80211_i.h | 18 | ||||
-rw-r--r-- | net/mac80211/main.c | 5 | ||||
-rw-r--r-- | net/mac80211/mlme.c | 230 | ||||
-rw-r--r-- | net/mac80211/wme.c | 2 | ||||
-rw-r--r-- | net/rfkill/rfkill.c | 104 | ||||
-rw-r--r-- | net/wireless/nl80211.c | 62 |
7 files changed, 267 insertions, 196 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 6d2ad2bf3ab5..928813ce08e2 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -674,6 +674,11 @@ static void sta_apply_parameters(struct ieee80211_local *local, | |||
674 | sta->supp_rates[local->oper_channel->band] = rates; | 674 | sta->supp_rates[local->oper_channel->band] = rates; |
675 | } | 675 | } |
676 | 676 | ||
677 | if (params->ht_capa) { | ||
678 | ieee80211_ht_cap_ie_to_ht_info(params->ht_capa, | ||
679 | &sta->ht_info); | ||
680 | } | ||
681 | |||
677 | if (ieee80211_vif_is_mesh(&sdata->vif) && params->plink_action) { | 682 | if (ieee80211_vif_is_mesh(&sdata->vif) && params->plink_action) { |
678 | switch (params->plink_action) { | 683 | switch (params->plink_action) { |
679 | case PLINK_ACTION_OPEN: | 684 | case PLINK_ACTION_OPEN: |
@@ -1010,6 +1015,42 @@ static int ieee80211_dump_mpath(struct wiphy *wiphy, struct net_device *dev, | |||
1010 | } | 1015 | } |
1011 | #endif | 1016 | #endif |
1012 | 1017 | ||
1018 | static int ieee80211_change_bss(struct wiphy *wiphy, | ||
1019 | struct net_device *dev, | ||
1020 | struct bss_parameters *params) | ||
1021 | { | ||
1022 | struct ieee80211_local *local = wiphy_priv(wiphy); | ||
1023 | struct ieee80211_sub_if_data *sdata; | ||
1024 | u32 changed = 0; | ||
1025 | |||
1026 | if (dev == local->mdev) | ||
1027 | return -EOPNOTSUPP; | ||
1028 | |||
1029 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
1030 | |||
1031 | if (sdata->vif.type != IEEE80211_IF_TYPE_AP) | ||
1032 | return -EINVAL; | ||
1033 | |||
1034 | if (params->use_cts_prot >= 0) { | ||
1035 | sdata->bss_conf.use_cts_prot = params->use_cts_prot; | ||
1036 | changed |= BSS_CHANGED_ERP_CTS_PROT; | ||
1037 | } | ||
1038 | if (params->use_short_preamble >= 0) { | ||
1039 | sdata->bss_conf.use_short_preamble = | ||
1040 | params->use_short_preamble; | ||
1041 | changed |= BSS_CHANGED_ERP_PREAMBLE; | ||
1042 | } | ||
1043 | if (params->use_short_slot_time >= 0) { | ||
1044 | sdata->bss_conf.use_short_slot = | ||
1045 | params->use_short_slot_time; | ||
1046 | changed |= BSS_CHANGED_ERP_SLOT; | ||
1047 | } | ||
1048 | |||
1049 | ieee80211_bss_info_change_notify(sdata, changed); | ||
1050 | |||
1051 | return 0; | ||
1052 | } | ||
1053 | |||
1013 | struct cfg80211_ops mac80211_config_ops = { | 1054 | struct cfg80211_ops mac80211_config_ops = { |
1014 | .add_virtual_intf = ieee80211_add_iface, | 1055 | .add_virtual_intf = ieee80211_add_iface, |
1015 | .del_virtual_intf = ieee80211_del_iface, | 1056 | .del_virtual_intf = ieee80211_del_iface, |
@@ -1033,4 +1074,5 @@ struct cfg80211_ops mac80211_config_ops = { | |||
1033 | .get_mpath = ieee80211_get_mpath, | 1074 | .get_mpath = ieee80211_get_mpath, |
1034 | .dump_mpath = ieee80211_dump_mpath, | 1075 | .dump_mpath = ieee80211_dump_mpath, |
1035 | #endif | 1076 | #endif |
1077 | .change_bss = ieee80211_change_bss, | ||
1036 | }; | 1078 | }; |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 8361054fb7cf..2bb546744b94 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -79,16 +79,11 @@ struct ieee80211_sta_bss { | |||
79 | enum ieee80211_band band; | 79 | enum ieee80211_band band; |
80 | int freq; | 80 | int freq; |
81 | int signal, noise, qual; | 81 | int signal, noise, qual; |
82 | u8 *wpa_ie; | 82 | u8 *ies; /* all information elements from the last Beacon or Probe |
83 | size_t wpa_ie_len; | 83 | * Response frames; note Beacon frame is not allowed to |
84 | u8 *rsn_ie; | 84 | * override values from Probe Response */ |
85 | size_t rsn_ie_len; | 85 | size_t ies_len; |
86 | u8 *wmm_ie; | 86 | bool wmm_used; |
87 | size_t wmm_ie_len; | ||
88 | u8 *ht_ie; | ||
89 | size_t ht_ie_len; | ||
90 | u8 *ht_add_ie; | ||
91 | size_t ht_add_ie_len; | ||
92 | #ifdef CONFIG_MAC80211_MESH | 87 | #ifdef CONFIG_MAC80211_MESH |
93 | u8 *mesh_id; | 88 | u8 *mesh_id; |
94 | size_t mesh_id_len; | 89 | size_t mesh_id_len; |
@@ -773,6 +768,9 @@ struct ieee80211_ra_tid { | |||
773 | 768 | ||
774 | /* Parsed Information Elements */ | 769 | /* Parsed Information Elements */ |
775 | struct ieee802_11_elems { | 770 | struct ieee802_11_elems { |
771 | u8 *ie_start; | ||
772 | size_t total_len; | ||
773 | |||
776 | /* pointers to IEs */ | 774 | /* pointers to IEs */ |
777 | u8 *ssid; | 775 | u8 *ssid; |
778 | u8 *supp_rates; | 776 | u8 *supp_rates; |
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 398ca66bdfcb..638b75f36e23 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -598,7 +598,7 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid) | |||
598 | struct ieee80211_local *local = hw_to_local(hw); | 598 | struct ieee80211_local *local = hw_to_local(hw); |
599 | struct sta_info *sta; | 599 | struct sta_info *sta; |
600 | struct ieee80211_sub_if_data *sdata; | 600 | struct ieee80211_sub_if_data *sdata; |
601 | u16 start_seq_num = 0; | 601 | u16 start_seq_num; |
602 | u8 *state; | 602 | u8 *state; |
603 | int ret; | 603 | int ret; |
604 | DECLARE_MAC_BUF(mac); | 604 | DECLARE_MAC_BUF(mac); |
@@ -678,6 +678,9 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid) | |||
678 | * call back right away, it must see that the flow has begun */ | 678 | * call back right away, it must see that the flow has begun */ |
679 | *state |= HT_ADDBA_REQUESTED_MSK; | 679 | *state |= HT_ADDBA_REQUESTED_MSK; |
680 | 680 | ||
681 | /* This is slightly racy because the queue isn't stopped */ | ||
682 | start_seq_num = sta->tid_seq[tid]; | ||
683 | |||
681 | if (local->ops->ampdu_action) | 684 | if (local->ops->ampdu_action) |
682 | ret = local->ops->ampdu_action(hw, IEEE80211_AMPDU_TX_START, | 685 | ret = local->ops->ampdu_action(hw, IEEE80211_AMPDU_TX_START, |
683 | ra, tid, &start_seq_num); | 686 | ra, tid, &start_seq_num); |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 84999791a332..e088b440aafa 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -98,6 +98,8 @@ void ieee802_11_parse_elems(u8 *start, size_t len, | |||
98 | u8 *pos = start; | 98 | u8 *pos = start; |
99 | 99 | ||
100 | memset(elems, 0, sizeof(*elems)); | 100 | memset(elems, 0, sizeof(*elems)); |
101 | elems->ie_start = start; | ||
102 | elems->total_len = len; | ||
101 | 103 | ||
102 | while (left >= 2) { | 104 | while (left >= 2) { |
103 | u8 id, elen; | 105 | u8 id, elen; |
@@ -234,6 +236,27 @@ void ieee802_11_parse_elems(u8 *start, size_t len, | |||
234 | } | 236 | } |
235 | 237 | ||
236 | 238 | ||
239 | static u8 * ieee80211_bss_get_ie(struct ieee80211_sta_bss *bss, u8 ie) | ||
240 | { | ||
241 | u8 *end, *pos; | ||
242 | |||
243 | pos = bss->ies; | ||
244 | if (pos == NULL) | ||
245 | return NULL; | ||
246 | end = pos + bss->ies_len; | ||
247 | |||
248 | while (pos + 1 < end) { | ||
249 | if (pos + 2 + pos[1] > end) | ||
250 | break; | ||
251 | if (pos[0] == ie) | ||
252 | return pos; | ||
253 | pos += 2 + pos[1]; | ||
254 | } | ||
255 | |||
256 | return NULL; | ||
257 | } | ||
258 | |||
259 | |||
237 | static int ecw2cw(int ecw) | 260 | static int ecw2cw(int ecw) |
238 | { | 261 | { |
239 | return (1 << ecw) - 1; | 262 | return (1 << ecw) - 1; |
@@ -737,7 +760,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata, | |||
737 | struct ieee80211_local *local = sdata->local; | 760 | struct ieee80211_local *local = sdata->local; |
738 | struct sk_buff *skb; | 761 | struct sk_buff *skb; |
739 | struct ieee80211_mgmt *mgmt; | 762 | struct ieee80211_mgmt *mgmt; |
740 | u8 *pos, *ies; | 763 | u8 *pos, *ies, *ht_add_ie; |
741 | int i, len, count, rates_len, supp_rates_len; | 764 | int i, len, count, rates_len, supp_rates_len; |
742 | u16 capab; | 765 | u16 capab; |
743 | struct ieee80211_sta_bss *bss; | 766 | struct ieee80211_sta_bss *bss; |
@@ -772,7 +795,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata, | |||
772 | if (bss) { | 795 | if (bss) { |
773 | if (bss->capability & WLAN_CAPABILITY_PRIVACY) | 796 | if (bss->capability & WLAN_CAPABILITY_PRIVACY) |
774 | capab |= WLAN_CAPABILITY_PRIVACY; | 797 | capab |= WLAN_CAPABILITY_PRIVACY; |
775 | if (bss->wmm_ie) | 798 | if (bss->wmm_used) |
776 | wmm = 1; | 799 | wmm = 1; |
777 | 800 | ||
778 | /* get all rates supported by the device and the AP as | 801 | /* get all rates supported by the device and the AP as |
@@ -894,9 +917,10 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata, | |||
894 | 917 | ||
895 | /* wmm support is a must to HT */ | 918 | /* wmm support is a must to HT */ |
896 | if (wmm && (ifsta->flags & IEEE80211_STA_WMM_ENABLED) && | 919 | if (wmm && (ifsta->flags & IEEE80211_STA_WMM_ENABLED) && |
897 | sband->ht_info.ht_supported && bss->ht_add_ie) { | 920 | sband->ht_info.ht_supported && |
921 | (ht_add_ie = ieee80211_bss_get_ie(bss, WLAN_EID_HT_EXTRA_INFO))) { | ||
898 | struct ieee80211_ht_addt_info *ht_add_info = | 922 | struct ieee80211_ht_addt_info *ht_add_info = |
899 | (struct ieee80211_ht_addt_info *)bss->ht_add_ie; | 923 | (struct ieee80211_ht_addt_info *)ht_add_ie; |
900 | u16 cap = sband->ht_info.cap; | 924 | u16 cap = sband->ht_info.cap; |
901 | __le16 tmp; | 925 | __le16 tmp; |
902 | u32 flags = local->hw.conf.channel->flags; | 926 | u32 flags = local->hw.conf.channel->flags; |
@@ -2372,11 +2396,7 @@ ieee80211_rx_mesh_bss_add(struct ieee80211_local *local, u8 *mesh_id, int mesh_i | |||
2372 | 2396 | ||
2373 | static void ieee80211_rx_bss_free(struct ieee80211_sta_bss *bss) | 2397 | static void ieee80211_rx_bss_free(struct ieee80211_sta_bss *bss) |
2374 | { | 2398 | { |
2375 | kfree(bss->wpa_ie); | 2399 | kfree(bss->ies); |
2376 | kfree(bss->rsn_ie); | ||
2377 | kfree(bss->wmm_ie); | ||
2378 | kfree(bss->ht_ie); | ||
2379 | kfree(bss->ht_add_ie); | ||
2380 | kfree(bss_mesh_id(bss)); | 2400 | kfree(bss_mesh_id(bss)); |
2381 | kfree(bss_mesh_cfg(bss)); | 2401 | kfree(bss_mesh_cfg(bss)); |
2382 | kfree(bss); | 2402 | kfree(bss); |
@@ -2662,43 +2682,6 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
2662 | bss->has_erp_value = 1; | 2682 | bss->has_erp_value = 1; |
2663 | } | 2683 | } |
2664 | 2684 | ||
2665 | if (elems->ht_cap_elem && | ||
2666 | (!bss->ht_ie || bss->ht_ie_len != elems->ht_cap_elem_len || | ||
2667 | memcmp(bss->ht_ie, elems->ht_cap_elem, elems->ht_cap_elem_len))) { | ||
2668 | kfree(bss->ht_ie); | ||
2669 | bss->ht_ie = kmalloc(elems->ht_cap_elem_len + 2, GFP_ATOMIC); | ||
2670 | if (bss->ht_ie) { | ||
2671 | memcpy(bss->ht_ie, elems->ht_cap_elem - 2, | ||
2672 | elems->ht_cap_elem_len + 2); | ||
2673 | bss->ht_ie_len = elems->ht_cap_elem_len + 2; | ||
2674 | } else | ||
2675 | bss->ht_ie_len = 0; | ||
2676 | } else if (!elems->ht_cap_elem && bss->ht_ie) { | ||
2677 | kfree(bss->ht_ie); | ||
2678 | bss->ht_ie = NULL; | ||
2679 | bss->ht_ie_len = 0; | ||
2680 | } | ||
2681 | |||
2682 | if (elems->ht_info_elem && | ||
2683 | (!bss->ht_add_ie || | ||
2684 | bss->ht_add_ie_len != elems->ht_info_elem_len || | ||
2685 | memcmp(bss->ht_add_ie, elems->ht_info_elem, | ||
2686 | elems->ht_info_elem_len))) { | ||
2687 | kfree(bss->ht_add_ie); | ||
2688 | bss->ht_add_ie = | ||
2689 | kmalloc(elems->ht_info_elem_len + 2, GFP_ATOMIC); | ||
2690 | if (bss->ht_add_ie) { | ||
2691 | memcpy(bss->ht_add_ie, elems->ht_info_elem - 2, | ||
2692 | elems->ht_info_elem_len + 2); | ||
2693 | bss->ht_add_ie_len = elems->ht_info_elem_len + 2; | ||
2694 | } else | ||
2695 | bss->ht_add_ie_len = 0; | ||
2696 | } else if (!elems->ht_info_elem && bss->ht_add_ie) { | ||
2697 | kfree(bss->ht_add_ie); | ||
2698 | bss->ht_add_ie = NULL; | ||
2699 | bss->ht_add_ie_len = 0; | ||
2700 | } | ||
2701 | |||
2702 | bss->beacon_int = le16_to_cpu(mgmt->u.beacon.beacon_int); | 2685 | bss->beacon_int = le16_to_cpu(mgmt->u.beacon.beacon_int); |
2703 | bss->capability = le16_to_cpu(mgmt->u.beacon.capab_info); | 2686 | bss->capability = le16_to_cpu(mgmt->u.beacon.capab_info); |
2704 | 2687 | ||
@@ -2749,88 +2732,17 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
2749 | return; | 2732 | return; |
2750 | } | 2733 | } |
2751 | 2734 | ||
2752 | if (elems->wpa && | 2735 | if (bss->ies == NULL || bss->ies_len < elems->total_len) { |
2753 | (!bss->wpa_ie || bss->wpa_ie_len != elems->wpa_len || | 2736 | kfree(bss->ies); |
2754 | memcmp(bss->wpa_ie, elems->wpa, elems->wpa_len))) { | 2737 | bss->ies = kmalloc(elems->total_len, GFP_ATOMIC); |
2755 | kfree(bss->wpa_ie); | ||
2756 | bss->wpa_ie = kmalloc(elems->wpa_len + 2, GFP_ATOMIC); | ||
2757 | if (bss->wpa_ie) { | ||
2758 | memcpy(bss->wpa_ie, elems->wpa - 2, elems->wpa_len + 2); | ||
2759 | bss->wpa_ie_len = elems->wpa_len + 2; | ||
2760 | } else | ||
2761 | bss->wpa_ie_len = 0; | ||
2762 | } else if (!elems->wpa && bss->wpa_ie) { | ||
2763 | kfree(bss->wpa_ie); | ||
2764 | bss->wpa_ie = NULL; | ||
2765 | bss->wpa_ie_len = 0; | ||
2766 | } | ||
2767 | |||
2768 | if (elems->rsn && | ||
2769 | (!bss->rsn_ie || bss->rsn_ie_len != elems->rsn_len || | ||
2770 | memcmp(bss->rsn_ie, elems->rsn, elems->rsn_len))) { | ||
2771 | kfree(bss->rsn_ie); | ||
2772 | bss->rsn_ie = kmalloc(elems->rsn_len + 2, GFP_ATOMIC); | ||
2773 | if (bss->rsn_ie) { | ||
2774 | memcpy(bss->rsn_ie, elems->rsn - 2, elems->rsn_len + 2); | ||
2775 | bss->rsn_ie_len = elems->rsn_len + 2; | ||
2776 | } else | ||
2777 | bss->rsn_ie_len = 0; | ||
2778 | } else if (!elems->rsn && bss->rsn_ie) { | ||
2779 | kfree(bss->rsn_ie); | ||
2780 | bss->rsn_ie = NULL; | ||
2781 | bss->rsn_ie_len = 0; | ||
2782 | } | 2738 | } |
2739 | if (bss->ies) { | ||
2740 | memcpy(bss->ies, elems->ie_start, elems->total_len); | ||
2741 | bss->ies_len = elems->total_len; | ||
2742 | } else | ||
2743 | bss->ies_len = 0; | ||
2783 | 2744 | ||
2784 | /* | 2745 | bss->wmm_used = elems->wmm_param || elems->wmm_info; |
2785 | * Cf. | ||
2786 | * http://www.wipo.int/pctdb/en/wo.jsp?wo=2007047181&IA=WO2007047181&DISPLAY=DESC | ||
2787 | * | ||
2788 | * quoting: | ||
2789 | * | ||
2790 | * In particular, "Wi-Fi CERTIFIED for WMM - Support for Multimedia | ||
2791 | * Applications with Quality of Service in Wi-Fi Networks," Wi- Fi | ||
2792 | * Alliance (September 1, 2004) is incorporated by reference herein. | ||
2793 | * The inclusion of the WMM Parameters in probe responses and | ||
2794 | * association responses is mandatory for WMM enabled networks. The | ||
2795 | * inclusion of the WMM Parameters in beacons, however, is optional. | ||
2796 | */ | ||
2797 | |||
2798 | if (elems->wmm_param && | ||
2799 | (!bss->wmm_ie || bss->wmm_ie_len != elems->wmm_param_len || | ||
2800 | memcmp(bss->wmm_ie, elems->wmm_param, elems->wmm_param_len))) { | ||
2801 | kfree(bss->wmm_ie); | ||
2802 | bss->wmm_ie = kmalloc(elems->wmm_param_len + 2, GFP_ATOMIC); | ||
2803 | if (bss->wmm_ie) { | ||
2804 | memcpy(bss->wmm_ie, elems->wmm_param - 2, | ||
2805 | elems->wmm_param_len + 2); | ||
2806 | bss->wmm_ie_len = elems->wmm_param_len + 2; | ||
2807 | } else | ||
2808 | bss->wmm_ie_len = 0; | ||
2809 | } else if (elems->wmm_info && | ||
2810 | (!bss->wmm_ie || bss->wmm_ie_len != elems->wmm_info_len || | ||
2811 | memcmp(bss->wmm_ie, elems->wmm_info, | ||
2812 | elems->wmm_info_len))) { | ||
2813 | /* As for certain AP's Fifth bit is not set in WMM IE in | ||
2814 | * beacon frames.So while parsing the beacon frame the | ||
2815 | * wmm_info structure is used instead of wmm_param. | ||
2816 | * wmm_info structure was never used to set bss->wmm_ie. | ||
2817 | * This code fixes this problem by copying the WME | ||
2818 | * information from wmm_info to bss->wmm_ie and enabling | ||
2819 | * n-band association. | ||
2820 | */ | ||
2821 | kfree(bss->wmm_ie); | ||
2822 | bss->wmm_ie = kmalloc(elems->wmm_info_len + 2, GFP_ATOMIC); | ||
2823 | if (bss->wmm_ie) { | ||
2824 | memcpy(bss->wmm_ie, elems->wmm_info - 2, | ||
2825 | elems->wmm_info_len + 2); | ||
2826 | bss->wmm_ie_len = elems->wmm_info_len + 2; | ||
2827 | } else | ||
2828 | bss->wmm_ie_len = 0; | ||
2829 | } else if (!elems->wmm_param && !elems->wmm_info && bss->wmm_ie) { | ||
2830 | kfree(bss->wmm_ie); | ||
2831 | bss->wmm_ie = NULL; | ||
2832 | bss->wmm_ie_len = 0; | ||
2833 | } | ||
2834 | 2746 | ||
2835 | /* check if we need to merge IBSS */ | 2747 | /* check if we need to merge IBSS */ |
2836 | if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS && beacon && | 2748 | if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS && beacon && |
@@ -4146,6 +4058,48 @@ int ieee80211_sta_req_scan(struct ieee80211_sub_if_data *sdata, u8 *ssid, size_t | |||
4146 | return 0; | 4058 | return 0; |
4147 | } | 4059 | } |
4148 | 4060 | ||
4061 | |||
4062 | static void ieee80211_sta_add_scan_ies(struct iw_request_info *info, | ||
4063 | struct ieee80211_sta_bss *bss, | ||
4064 | char **current_ev, char *end_buf) | ||
4065 | { | ||
4066 | u8 *pos, *end, *next; | ||
4067 | struct iw_event iwe; | ||
4068 | |||
4069 | if (bss == NULL || bss->ies == NULL) | ||
4070 | return; | ||
4071 | |||
4072 | /* | ||
4073 | * If needed, fragment the IEs buffer (at IE boundaries) into short | ||
4074 | * enough fragments to fit into IW_GENERIC_IE_MAX octet messages. | ||
4075 | */ | ||
4076 | pos = bss->ies; | ||
4077 | end = pos + bss->ies_len; | ||
4078 | |||
4079 | while (end - pos > IW_GENERIC_IE_MAX) { | ||
4080 | next = pos + 2 + pos[1]; | ||
4081 | while (next + 2 + next[1] - pos < IW_GENERIC_IE_MAX) | ||
4082 | next = next + 2 + next[1]; | ||
4083 | |||
4084 | memset(&iwe, 0, sizeof(iwe)); | ||
4085 | iwe.cmd = IWEVGENIE; | ||
4086 | iwe.u.data.length = next - pos; | ||
4087 | *current_ev = iwe_stream_add_point(info, *current_ev, | ||
4088 | end_buf, &iwe, pos); | ||
4089 | |||
4090 | pos = next; | ||
4091 | } | ||
4092 | |||
4093 | if (end > pos) { | ||
4094 | memset(&iwe, 0, sizeof(iwe)); | ||
4095 | iwe.cmd = IWEVGENIE; | ||
4096 | iwe.u.data.length = end - pos; | ||
4097 | *current_ev = iwe_stream_add_point(info, *current_ev, | ||
4098 | end_buf, &iwe, pos); | ||
4099 | } | ||
4100 | } | ||
4101 | |||
4102 | |||
4149 | static char * | 4103 | static char * |
4150 | ieee80211_sta_scan_result(struct ieee80211_local *local, | 4104 | ieee80211_sta_scan_result(struct ieee80211_local *local, |
4151 | struct iw_request_info *info, | 4105 | struct iw_request_info *info, |
@@ -4225,29 +4179,7 @@ ieee80211_sta_scan_result(struct ieee80211_local *local, | |||
4225 | current_ev = iwe_stream_add_point(info, current_ev, end_buf, | 4179 | current_ev = iwe_stream_add_point(info, current_ev, end_buf, |
4226 | &iwe, ""); | 4180 | &iwe, ""); |
4227 | 4181 | ||
4228 | if (bss && bss->wpa_ie) { | 4182 | ieee80211_sta_add_scan_ies(info, bss, ¤t_ev, end_buf); |
4229 | memset(&iwe, 0, sizeof(iwe)); | ||
4230 | iwe.cmd = IWEVGENIE; | ||
4231 | iwe.u.data.length = bss->wpa_ie_len; | ||
4232 | current_ev = iwe_stream_add_point(info, current_ev, end_buf, | ||
4233 | &iwe, bss->wpa_ie); | ||
4234 | } | ||
4235 | |||
4236 | if (bss && bss->rsn_ie) { | ||
4237 | memset(&iwe, 0, sizeof(iwe)); | ||
4238 | iwe.cmd = IWEVGENIE; | ||
4239 | iwe.u.data.length = bss->rsn_ie_len; | ||
4240 | current_ev = iwe_stream_add_point(info, current_ev, end_buf, | ||
4241 | &iwe, bss->rsn_ie); | ||
4242 | } | ||
4243 | |||
4244 | if (bss && bss->ht_ie) { | ||
4245 | memset(&iwe, 0, sizeof(iwe)); | ||
4246 | iwe.cmd = IWEVGENIE; | ||
4247 | iwe.u.data.length = bss->ht_ie_len; | ||
4248 | current_ev = iwe_stream_add_point(info, current_ev, end_buf, | ||
4249 | &iwe, bss->ht_ie); | ||
4250 | } | ||
4251 | 4183 | ||
4252 | if (bss && bss->supp_rates_len > 0) { | 4184 | if (bss && bss->supp_rates_len > 0) { |
4253 | /* display all supported rates in readable format */ | 4185 | /* display all supported rates in readable format */ |
diff --git a/net/mac80211/wme.c b/net/mac80211/wme.c index 4310e2f65661..7229e958879d 100644 --- a/net/mac80211/wme.c +++ b/net/mac80211/wme.c | |||
@@ -47,8 +47,6 @@ static unsigned int classify_1d(struct sk_buff *skb) | |||
47 | return 0; | 47 | return 0; |
48 | } | 48 | } |
49 | 49 | ||
50 | if (dscp & 0x1c) | ||
51 | return 0; | ||
52 | return dscp >> 5; | 50 | return dscp >> 5; |
53 | } | 51 | } |
54 | 52 | ||
diff --git a/net/rfkill/rfkill.c b/net/rfkill/rfkill.c index 47e0b2d232e3..d5735799ccd9 100644 --- a/net/rfkill/rfkill.c +++ b/net/rfkill/rfkill.c | |||
@@ -37,7 +37,7 @@ MODULE_DESCRIPTION("RF switch support"); | |||
37 | MODULE_LICENSE("GPL"); | 37 | MODULE_LICENSE("GPL"); |
38 | 38 | ||
39 | static LIST_HEAD(rfkill_list); /* list of registered rf switches */ | 39 | static LIST_HEAD(rfkill_list); /* list of registered rf switches */ |
40 | static DEFINE_MUTEX(rfkill_mutex); | 40 | static DEFINE_MUTEX(rfkill_global_mutex); |
41 | 41 | ||
42 | static unsigned int rfkill_default_state = RFKILL_STATE_UNBLOCKED; | 42 | static unsigned int rfkill_default_state = RFKILL_STATE_UNBLOCKED; |
43 | module_param_named(default_state, rfkill_default_state, uint, 0444); | 43 | module_param_named(default_state, rfkill_default_state, uint, 0444); |
@@ -76,6 +76,7 @@ static BLOCKING_NOTIFIER_HEAD(rfkill_notifier_list); | |||
76 | */ | 76 | */ |
77 | int register_rfkill_notifier(struct notifier_block *nb) | 77 | int register_rfkill_notifier(struct notifier_block *nb) |
78 | { | 78 | { |
79 | BUG_ON(!nb); | ||
79 | return blocking_notifier_chain_register(&rfkill_notifier_list, nb); | 80 | return blocking_notifier_chain_register(&rfkill_notifier_list, nb); |
80 | } | 81 | } |
81 | EXPORT_SYMBOL_GPL(register_rfkill_notifier); | 82 | EXPORT_SYMBOL_GPL(register_rfkill_notifier); |
@@ -91,6 +92,7 @@ EXPORT_SYMBOL_GPL(register_rfkill_notifier); | |||
91 | */ | 92 | */ |
92 | int unregister_rfkill_notifier(struct notifier_block *nb) | 93 | int unregister_rfkill_notifier(struct notifier_block *nb) |
93 | { | 94 | { |
95 | BUG_ON(!nb); | ||
94 | return blocking_notifier_chain_unregister(&rfkill_notifier_list, nb); | 96 | return blocking_notifier_chain_unregister(&rfkill_notifier_list, nb); |
95 | } | 97 | } |
96 | EXPORT_SYMBOL_GPL(unregister_rfkill_notifier); | 98 | EXPORT_SYMBOL_GPL(unregister_rfkill_notifier); |
@@ -202,6 +204,9 @@ static int rfkill_toggle_radio(struct rfkill *rfkill, | |||
202 | * RFKILL_STATE_HARD_BLOCKED */ | 204 | * RFKILL_STATE_HARD_BLOCKED */ |
203 | break; | 205 | break; |
204 | default: | 206 | default: |
207 | WARN(1, KERN_WARNING | ||
208 | "rfkill: illegal state %d passed as parameter " | ||
209 | "to rfkill_toggle_radio\n", state); | ||
205 | return -EINVAL; | 210 | return -EINVAL; |
206 | } | 211 | } |
207 | 212 | ||
@@ -229,14 +234,18 @@ static int rfkill_toggle_radio(struct rfkill *rfkill, | |||
229 | * unless a specific switch is claimed by userspace (in which case, | 234 | * unless a specific switch is claimed by userspace (in which case, |
230 | * that switch is left alone) or suspended. | 235 | * that switch is left alone) or suspended. |
231 | * | 236 | * |
232 | * Caller must have acquired rfkill_mutex. | 237 | * Caller must have acquired rfkill_global_mutex. |
233 | */ | 238 | */ |
234 | static void __rfkill_switch_all(const enum rfkill_type type, | 239 | static void __rfkill_switch_all(const enum rfkill_type type, |
235 | const enum rfkill_state state) | 240 | const enum rfkill_state state) |
236 | { | 241 | { |
237 | struct rfkill *rfkill; | 242 | struct rfkill *rfkill; |
238 | 243 | ||
239 | if (unlikely(state >= RFKILL_STATE_MAX)) | 244 | if (WARN((state >= RFKILL_STATE_MAX || type >= RFKILL_TYPE_MAX), |
245 | KERN_WARNING | ||
246 | "rfkill: illegal state %d or type %d " | ||
247 | "passed as parameter to __rfkill_switch_all\n", | ||
248 | state, type)) | ||
240 | return; | 249 | return; |
241 | 250 | ||
242 | rfkill_global_states[type].current_state = state; | 251 | rfkill_global_states[type].current_state = state; |
@@ -254,14 +263,14 @@ static void __rfkill_switch_all(const enum rfkill_type type, | |||
254 | * @type: type of interfaces to be affected | 263 | * @type: type of interfaces to be affected |
255 | * @state: the new state | 264 | * @state: the new state |
256 | * | 265 | * |
257 | * Acquires rfkill_mutex and calls __rfkill_switch_all(@type, @state). | 266 | * Acquires rfkill_global_mutex and calls __rfkill_switch_all(@type, @state). |
258 | * Please refer to __rfkill_switch_all() for details. | 267 | * Please refer to __rfkill_switch_all() for details. |
259 | */ | 268 | */ |
260 | void rfkill_switch_all(enum rfkill_type type, enum rfkill_state state) | 269 | void rfkill_switch_all(enum rfkill_type type, enum rfkill_state state) |
261 | { | 270 | { |
262 | mutex_lock(&rfkill_mutex); | 271 | mutex_lock(&rfkill_global_mutex); |
263 | __rfkill_switch_all(type, state); | 272 | __rfkill_switch_all(type, state); |
264 | mutex_unlock(&rfkill_mutex); | 273 | mutex_unlock(&rfkill_global_mutex); |
265 | } | 274 | } |
266 | EXPORT_SYMBOL(rfkill_switch_all); | 275 | EXPORT_SYMBOL(rfkill_switch_all); |
267 | 276 | ||
@@ -269,7 +278,7 @@ EXPORT_SYMBOL(rfkill_switch_all); | |||
269 | * rfkill_epo - emergency power off all transmitters | 278 | * rfkill_epo - emergency power off all transmitters |
270 | * | 279 | * |
271 | * This kicks all non-suspended rfkill devices to RFKILL_STATE_SOFT_BLOCKED, | 280 | * This kicks all non-suspended rfkill devices to RFKILL_STATE_SOFT_BLOCKED, |
272 | * ignoring everything in its path but rfkill_mutex and rfkill->mutex. | 281 | * ignoring everything in its path but rfkill_global_mutex and rfkill->mutex. |
273 | * | 282 | * |
274 | * The global state before the EPO is saved and can be restored later | 283 | * The global state before the EPO is saved and can be restored later |
275 | * using rfkill_restore_states(). | 284 | * using rfkill_restore_states(). |
@@ -279,7 +288,8 @@ void rfkill_epo(void) | |||
279 | struct rfkill *rfkill; | 288 | struct rfkill *rfkill; |
280 | int i; | 289 | int i; |
281 | 290 | ||
282 | mutex_lock(&rfkill_mutex); | 291 | mutex_lock(&rfkill_global_mutex); |
292 | |||
283 | list_for_each_entry(rfkill, &rfkill_list, node) { | 293 | list_for_each_entry(rfkill, &rfkill_list, node) { |
284 | mutex_lock(&rfkill->mutex); | 294 | mutex_lock(&rfkill->mutex); |
285 | rfkill_toggle_radio(rfkill, RFKILL_STATE_SOFT_BLOCKED, 1); | 295 | rfkill_toggle_radio(rfkill, RFKILL_STATE_SOFT_BLOCKED, 1); |
@@ -291,7 +301,7 @@ void rfkill_epo(void) | |||
291 | rfkill_global_states[i].current_state = | 301 | rfkill_global_states[i].current_state = |
292 | RFKILL_STATE_SOFT_BLOCKED; | 302 | RFKILL_STATE_SOFT_BLOCKED; |
293 | } | 303 | } |
294 | mutex_unlock(&rfkill_mutex); | 304 | mutex_unlock(&rfkill_global_mutex); |
295 | } | 305 | } |
296 | EXPORT_SYMBOL_GPL(rfkill_epo); | 306 | EXPORT_SYMBOL_GPL(rfkill_epo); |
297 | 307 | ||
@@ -306,10 +316,11 @@ void rfkill_restore_states(void) | |||
306 | { | 316 | { |
307 | int i; | 317 | int i; |
308 | 318 | ||
309 | mutex_lock(&rfkill_mutex); | 319 | mutex_lock(&rfkill_global_mutex); |
320 | |||
310 | for (i = 0; i < RFKILL_TYPE_MAX; i++) | 321 | for (i = 0; i < RFKILL_TYPE_MAX; i++) |
311 | __rfkill_switch_all(i, rfkill_global_states[i].default_state); | 322 | __rfkill_switch_all(i, rfkill_global_states[i].default_state); |
312 | mutex_unlock(&rfkill_mutex); | 323 | mutex_unlock(&rfkill_global_mutex); |
313 | } | 324 | } |
314 | EXPORT_SYMBOL_GPL(rfkill_restore_states); | 325 | EXPORT_SYMBOL_GPL(rfkill_restore_states); |
315 | 326 | ||
@@ -334,7 +345,11 @@ int rfkill_force_state(struct rfkill *rfkill, enum rfkill_state state) | |||
334 | { | 345 | { |
335 | enum rfkill_state oldstate; | 346 | enum rfkill_state oldstate; |
336 | 347 | ||
337 | if (unlikely(state >= RFKILL_STATE_MAX)) | 348 | BUG_ON(!rfkill); |
349 | if (WARN((state >= RFKILL_STATE_MAX), | ||
350 | KERN_WARNING | ||
351 | "rfkill: illegal state %d passed as parameter " | ||
352 | "to rfkill_force_state\n", state)) | ||
338 | return -EINVAL; | 353 | return -EINVAL; |
339 | 354 | ||
340 | mutex_lock(&rfkill->mutex); | 355 | mutex_lock(&rfkill->mutex); |
@@ -402,12 +417,16 @@ static ssize_t rfkill_state_store(struct device *dev, | |||
402 | const char *buf, size_t count) | 417 | const char *buf, size_t count) |
403 | { | 418 | { |
404 | struct rfkill *rfkill = to_rfkill(dev); | 419 | struct rfkill *rfkill = to_rfkill(dev); |
405 | unsigned int state = simple_strtoul(buf, NULL, 0); | 420 | unsigned long state; |
406 | int error; | 421 | int error; |
407 | 422 | ||
408 | if (!capable(CAP_NET_ADMIN)) | 423 | if (!capable(CAP_NET_ADMIN)) |
409 | return -EPERM; | 424 | return -EPERM; |
410 | 425 | ||
426 | error = strict_strtoul(buf, 0, &state); | ||
427 | if (error) | ||
428 | return error; | ||
429 | |||
411 | /* RFKILL_STATE_HARD_BLOCKED is illegal here... */ | 430 | /* RFKILL_STATE_HARD_BLOCKED is illegal here... */ |
412 | if (state != RFKILL_STATE_UNBLOCKED && | 431 | if (state != RFKILL_STATE_UNBLOCKED && |
413 | state != RFKILL_STATE_SOFT_BLOCKED) | 432 | state != RFKILL_STATE_SOFT_BLOCKED) |
@@ -427,7 +446,7 @@ static ssize_t rfkill_claim_show(struct device *dev, | |||
427 | { | 446 | { |
428 | struct rfkill *rfkill = to_rfkill(dev); | 447 | struct rfkill *rfkill = to_rfkill(dev); |
429 | 448 | ||
430 | return sprintf(buf, "%d", rfkill->user_claim); | 449 | return sprintf(buf, "%d\n", rfkill->user_claim); |
431 | } | 450 | } |
432 | 451 | ||
433 | static ssize_t rfkill_claim_store(struct device *dev, | 452 | static ssize_t rfkill_claim_store(struct device *dev, |
@@ -435,7 +454,8 @@ static ssize_t rfkill_claim_store(struct device *dev, | |||
435 | const char *buf, size_t count) | 454 | const char *buf, size_t count) |
436 | { | 455 | { |
437 | struct rfkill *rfkill = to_rfkill(dev); | 456 | struct rfkill *rfkill = to_rfkill(dev); |
438 | bool claim = !!simple_strtoul(buf, NULL, 0); | 457 | unsigned long claim_tmp; |
458 | bool claim; | ||
439 | int error; | 459 | int error; |
440 | 460 | ||
441 | if (!capable(CAP_NET_ADMIN)) | 461 | if (!capable(CAP_NET_ADMIN)) |
@@ -444,11 +464,16 @@ static ssize_t rfkill_claim_store(struct device *dev, | |||
444 | if (rfkill->user_claim_unsupported) | 464 | if (rfkill->user_claim_unsupported) |
445 | return -EOPNOTSUPP; | 465 | return -EOPNOTSUPP; |
446 | 466 | ||
467 | error = strict_strtoul(buf, 0, &claim_tmp); | ||
468 | if (error) | ||
469 | return error; | ||
470 | claim = !!claim_tmp; | ||
471 | |||
447 | /* | 472 | /* |
448 | * Take the global lock to make sure the kernel is not in | 473 | * Take the global lock to make sure the kernel is not in |
449 | * the middle of rfkill_switch_all | 474 | * the middle of rfkill_switch_all |
450 | */ | 475 | */ |
451 | error = mutex_lock_interruptible(&rfkill_mutex); | 476 | error = mutex_lock_interruptible(&rfkill_global_mutex); |
452 | if (error) | 477 | if (error) |
453 | return error; | 478 | return error; |
454 | 479 | ||
@@ -463,7 +488,7 @@ static ssize_t rfkill_claim_store(struct device *dev, | |||
463 | rfkill->user_claim = claim; | 488 | rfkill->user_claim = claim; |
464 | } | 489 | } |
465 | 490 | ||
466 | mutex_unlock(&rfkill_mutex); | 491 | mutex_unlock(&rfkill_global_mutex); |
467 | 492 | ||
468 | return error ? error : count; | 493 | return error ? error : count; |
469 | } | 494 | } |
@@ -583,10 +608,10 @@ static int rfkill_check_duplicity(const struct rfkill *rfkill) | |||
583 | memset(seen, 0, sizeof(seen)); | 608 | memset(seen, 0, sizeof(seen)); |
584 | 609 | ||
585 | list_for_each_entry(p, &rfkill_list, node) { | 610 | list_for_each_entry(p, &rfkill_list, node) { |
586 | if (p == rfkill) { | 611 | if (WARN((p == rfkill), KERN_WARNING |
587 | WARN_ON(1); | 612 | "rfkill: illegal attempt to register " |
613 | "an already registered rfkill struct\n")) | ||
588 | return -EEXIST; | 614 | return -EEXIST; |
589 | } | ||
590 | set_bit(p->type, seen); | 615 | set_bit(p->type, seen); |
591 | } | 616 | } |
592 | 617 | ||
@@ -598,7 +623,7 @@ static int rfkill_add_switch(struct rfkill *rfkill) | |||
598 | { | 623 | { |
599 | int error; | 624 | int error; |
600 | 625 | ||
601 | mutex_lock(&rfkill_mutex); | 626 | mutex_lock(&rfkill_global_mutex); |
602 | 627 | ||
603 | error = rfkill_check_duplicity(rfkill); | 628 | error = rfkill_check_duplicity(rfkill); |
604 | if (error < 0) | 629 | if (error < 0) |
@@ -619,16 +644,16 @@ static int rfkill_add_switch(struct rfkill *rfkill) | |||
619 | 644 | ||
620 | error = 0; | 645 | error = 0; |
621 | unlock_out: | 646 | unlock_out: |
622 | mutex_unlock(&rfkill_mutex); | 647 | mutex_unlock(&rfkill_global_mutex); |
623 | 648 | ||
624 | return error; | 649 | return error; |
625 | } | 650 | } |
626 | 651 | ||
627 | static void rfkill_remove_switch(struct rfkill *rfkill) | 652 | static void rfkill_remove_switch(struct rfkill *rfkill) |
628 | { | 653 | { |
629 | mutex_lock(&rfkill_mutex); | 654 | mutex_lock(&rfkill_global_mutex); |
630 | list_del_init(&rfkill->node); | 655 | list_del_init(&rfkill->node); |
631 | mutex_unlock(&rfkill_mutex); | 656 | mutex_unlock(&rfkill_global_mutex); |
632 | 657 | ||
633 | mutex_lock(&rfkill->mutex); | 658 | mutex_lock(&rfkill->mutex); |
634 | rfkill_toggle_radio(rfkill, RFKILL_STATE_SOFT_BLOCKED, 1); | 659 | rfkill_toggle_radio(rfkill, RFKILL_STATE_SOFT_BLOCKED, 1); |
@@ -654,6 +679,12 @@ struct rfkill * __must_check rfkill_allocate(struct device *parent, | |||
654 | struct rfkill *rfkill; | 679 | struct rfkill *rfkill; |
655 | struct device *dev; | 680 | struct device *dev; |
656 | 681 | ||
682 | if (WARN((type >= RFKILL_TYPE_MAX), | ||
683 | KERN_WARNING | ||
684 | "rfkill: illegal type %d passed as parameter " | ||
685 | "to rfkill_allocate\n", type)) | ||
686 | return NULL; | ||
687 | |||
657 | rfkill = kzalloc(sizeof(struct rfkill), GFP_KERNEL); | 688 | rfkill = kzalloc(sizeof(struct rfkill), GFP_KERNEL); |
658 | if (!rfkill) | 689 | if (!rfkill) |
659 | return NULL; | 690 | return NULL; |
@@ -726,11 +757,12 @@ int __must_check rfkill_register(struct rfkill *rfkill) | |||
726 | struct device *dev = &rfkill->dev; | 757 | struct device *dev = &rfkill->dev; |
727 | int error; | 758 | int error; |
728 | 759 | ||
729 | if (!rfkill->toggle_radio) | 760 | if (WARN((!rfkill || !rfkill->toggle_radio || |
730 | return -EINVAL; | 761 | rfkill->type >= RFKILL_TYPE_MAX || |
731 | if (rfkill->type >= RFKILL_TYPE_MAX) | 762 | rfkill->state >= RFKILL_STATE_MAX), |
732 | return -EINVAL; | 763 | KERN_WARNING |
733 | if (rfkill->state >= RFKILL_STATE_MAX) | 764 | "rfkill: attempt to register a " |
765 | "badly initialized rfkill struct\n")) | ||
734 | return -EINVAL; | 766 | return -EINVAL; |
735 | 767 | ||
736 | snprintf(dev->bus_id, sizeof(dev->bus_id), | 768 | snprintf(dev->bus_id, sizeof(dev->bus_id), |
@@ -765,6 +797,7 @@ EXPORT_SYMBOL(rfkill_register); | |||
765 | */ | 797 | */ |
766 | void rfkill_unregister(struct rfkill *rfkill) | 798 | void rfkill_unregister(struct rfkill *rfkill) |
767 | { | 799 | { |
800 | BUG_ON(!rfkill); | ||
768 | device_del(&rfkill->dev); | 801 | device_del(&rfkill->dev); |
769 | rfkill_remove_switch(rfkill); | 802 | rfkill_remove_switch(rfkill); |
770 | rfkill_led_trigger_unregister(rfkill); | 803 | rfkill_led_trigger_unregister(rfkill); |
@@ -801,12 +834,15 @@ int rfkill_set_default(enum rfkill_type type, enum rfkill_state state) | |||
801 | { | 834 | { |
802 | int error; | 835 | int error; |
803 | 836 | ||
804 | if (type >= RFKILL_TYPE_MAX || | 837 | if (WARN((type >= RFKILL_TYPE_MAX || |
805 | (state != RFKILL_STATE_SOFT_BLOCKED && | 838 | (state != RFKILL_STATE_SOFT_BLOCKED && |
806 | state != RFKILL_STATE_UNBLOCKED)) | 839 | state != RFKILL_STATE_UNBLOCKED)), |
840 | KERN_WARNING | ||
841 | "rfkill: illegal state %d or type %d passed as " | ||
842 | "parameter to rfkill_set_default\n", state, type)) | ||
807 | return -EINVAL; | 843 | return -EINVAL; |
808 | 844 | ||
809 | mutex_lock(&rfkill_mutex); | 845 | mutex_lock(&rfkill_global_mutex); |
810 | 846 | ||
811 | if (!test_and_set_bit(type, rfkill_states_lockdflt)) { | 847 | if (!test_and_set_bit(type, rfkill_states_lockdflt)) { |
812 | rfkill_global_states[type].default_state = state; | 848 | rfkill_global_states[type].default_state = state; |
@@ -814,7 +850,7 @@ int rfkill_set_default(enum rfkill_type type, enum rfkill_state state) | |||
814 | } else | 850 | } else |
815 | error = -EPERM; | 851 | error = -EPERM; |
816 | 852 | ||
817 | mutex_unlock(&rfkill_mutex); | 853 | mutex_unlock(&rfkill_global_mutex); |
818 | return error; | 854 | return error; |
819 | } | 855 | } |
820 | EXPORT_SYMBOL_GPL(rfkill_set_default); | 856 | EXPORT_SYMBOL_GPL(rfkill_set_default); |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 59eb2cf42e5f..4d6c02afd6f5 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -87,6 +87,13 @@ static struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] __read_mostly = { | |||
87 | [NL80211_ATTR_MESH_ID] = { .type = NLA_BINARY, | 87 | [NL80211_ATTR_MESH_ID] = { .type = NLA_BINARY, |
88 | .len = IEEE80211_MAX_MESH_ID_LEN }, | 88 | .len = IEEE80211_MAX_MESH_ID_LEN }, |
89 | [NL80211_ATTR_MPATH_NEXT_HOP] = { .type = NLA_U32 }, | 89 | [NL80211_ATTR_MPATH_NEXT_HOP] = { .type = NLA_U32 }, |
90 | |||
91 | [NL80211_ATTR_BSS_CTS_PROT] = { .type = NLA_U8 }, | ||
92 | [NL80211_ATTR_BSS_SHORT_PREAMBLE] = { .type = NLA_U8 }, | ||
93 | [NL80211_ATTR_BSS_SHORT_SLOT_TIME] = { .type = NLA_U8 }, | ||
94 | |||
95 | [NL80211_ATTR_HT_CAPABILITY] = { .type = NLA_BINARY, | ||
96 | .len = NL80211_HT_CAPABILITY_LEN }, | ||
90 | }; | 97 | }; |
91 | 98 | ||
92 | /* message building helper */ | 99 | /* message building helper */ |
@@ -1125,6 +1132,10 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info) | |||
1125 | params.listen_interval = | 1132 | params.listen_interval = |
1126 | nla_get_u16(info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]); | 1133 | nla_get_u16(info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]); |
1127 | 1134 | ||
1135 | if (info->attrs[NL80211_ATTR_HT_CAPABILITY]) | ||
1136 | params.ht_capa = | ||
1137 | nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]); | ||
1138 | |||
1128 | if (parse_station_flags(info->attrs[NL80211_ATTR_STA_FLAGS], | 1139 | if (parse_station_flags(info->attrs[NL80211_ATTR_STA_FLAGS], |
1129 | ¶ms.station_flags)) | 1140 | ¶ms.station_flags)) |
1130 | return -EINVAL; | 1141 | return -EINVAL; |
@@ -1188,6 +1199,9 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) | |||
1188 | params.listen_interval = | 1199 | params.listen_interval = |
1189 | nla_get_u16(info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]); | 1200 | nla_get_u16(info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]); |
1190 | params.aid = nla_get_u16(info->attrs[NL80211_ATTR_STA_AID]); | 1201 | params.aid = nla_get_u16(info->attrs[NL80211_ATTR_STA_AID]); |
1202 | if (info->attrs[NL80211_ATTR_HT_CAPABILITY]) | ||
1203 | params.ht_capa = | ||
1204 | nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]); | ||
1191 | 1205 | ||
1192 | if (parse_station_flags(info->attrs[NL80211_ATTR_STA_FLAGS], | 1206 | if (parse_station_flags(info->attrs[NL80211_ATTR_STA_FLAGS], |
1193 | ¶ms.station_flags)) | 1207 | ¶ms.station_flags)) |
@@ -1525,6 +1539,48 @@ static int nl80211_del_mpath(struct sk_buff *skb, struct genl_info *info) | |||
1525 | return err; | 1539 | return err; |
1526 | } | 1540 | } |
1527 | 1541 | ||
1542 | static int nl80211_set_bss(struct sk_buff *skb, struct genl_info *info) | ||
1543 | { | ||
1544 | struct cfg80211_registered_device *drv; | ||
1545 | int err; | ||
1546 | struct net_device *dev; | ||
1547 | struct bss_parameters params; | ||
1548 | |||
1549 | memset(¶ms, 0, sizeof(params)); | ||
1550 | /* default to not changing parameters */ | ||
1551 | params.use_cts_prot = -1; | ||
1552 | params.use_short_preamble = -1; | ||
1553 | params.use_short_slot_time = -1; | ||
1554 | |||
1555 | if (info->attrs[NL80211_ATTR_BSS_CTS_PROT]) | ||
1556 | params.use_cts_prot = | ||
1557 | nla_get_u8(info->attrs[NL80211_ATTR_BSS_CTS_PROT]); | ||
1558 | if (info->attrs[NL80211_ATTR_BSS_SHORT_PREAMBLE]) | ||
1559 | params.use_short_preamble = | ||
1560 | nla_get_u8(info->attrs[NL80211_ATTR_BSS_SHORT_PREAMBLE]); | ||
1561 | if (info->attrs[NL80211_ATTR_BSS_SHORT_SLOT_TIME]) | ||
1562 | params.use_short_slot_time = | ||
1563 | nla_get_u8(info->attrs[NL80211_ATTR_BSS_SHORT_SLOT_TIME]); | ||
1564 | |||
1565 | err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); | ||
1566 | if (err) | ||
1567 | return err; | ||
1568 | |||
1569 | if (!drv->ops->change_bss) { | ||
1570 | err = -EOPNOTSUPP; | ||
1571 | goto out; | ||
1572 | } | ||
1573 | |||
1574 | rtnl_lock(); | ||
1575 | err = drv->ops->change_bss(&drv->wiphy, dev, ¶ms); | ||
1576 | rtnl_unlock(); | ||
1577 | |||
1578 | out: | ||
1579 | cfg80211_put_dev(drv); | ||
1580 | dev_put(dev); | ||
1581 | return err; | ||
1582 | } | ||
1583 | |||
1528 | static struct genl_ops nl80211_ops[] = { | 1584 | static struct genl_ops nl80211_ops[] = { |
1529 | { | 1585 | { |
1530 | .cmd = NL80211_CMD_GET_WIPHY, | 1586 | .cmd = NL80211_CMD_GET_WIPHY, |
@@ -1656,6 +1712,12 @@ static struct genl_ops nl80211_ops[] = { | |||
1656 | .policy = nl80211_policy, | 1712 | .policy = nl80211_policy, |
1657 | .flags = GENL_ADMIN_PERM, | 1713 | .flags = GENL_ADMIN_PERM, |
1658 | }, | 1714 | }, |
1715 | { | ||
1716 | .cmd = NL80211_CMD_SET_BSS, | ||
1717 | .doit = nl80211_set_bss, | ||
1718 | .policy = nl80211_policy, | ||
1719 | .flags = GENL_ADMIN_PERM, | ||
1720 | }, | ||
1659 | }; | 1721 | }; |
1660 | 1722 | ||
1661 | /* multicast groups */ | 1723 | /* multicast groups */ |