aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/util.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/util.c')
-rw-r--r--net/mac80211/util.c176
1 files changed, 176 insertions, 0 deletions
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 92ea1770461b..dee17e5cbb89 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -750,6 +750,27 @@ void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata)
750 local->ops->conf_tx(local_to_hw(local), i, &qparam); 750 local->ops->conf_tx(local_to_hw(local), i, &qparam);
751} 751}
752 752
753void ieee80211_sta_def_wmm_params(struct ieee80211_sub_if_data *sdata,
754 const size_t supp_rates_len,
755 const u8 *supp_rates)
756{
757 struct ieee80211_local *local = sdata->local;
758 int i, have_higher_than_11mbit = 0;
759
760 /* cf. IEEE 802.11 9.2.12 */
761 for (i = 0; i < supp_rates_len; i++)
762 if ((supp_rates[i] & 0x7f) * 5 > 110)
763 have_higher_than_11mbit = 1;
764
765 if (local->hw.conf.channel->band == IEEE80211_BAND_2GHZ &&
766 have_higher_than_11mbit)
767 sdata->flags |= IEEE80211_SDATA_OPERATING_GMODE;
768 else
769 sdata->flags &= ~IEEE80211_SDATA_OPERATING_GMODE;
770
771 ieee80211_set_wmm_default(sdata);
772}
773
753void ieee80211_tx_skb(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, 774void ieee80211_tx_skb(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb,
754 int encrypt) 775 int encrypt)
755{ 776{
@@ -816,3 +837,158 @@ u32 ieee80211_mandatory_rates(struct ieee80211_local *local,
816 mandatory_rates |= BIT(i); 837 mandatory_rates |= BIT(i);
817 return mandatory_rates; 838 return mandatory_rates;
818} 839}
840
841void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata,
842 u16 transaction, u16 auth_alg,
843 u8 *extra, size_t extra_len,
844 const u8 *bssid, int encrypt)
845{
846 struct ieee80211_local *local = sdata->local;
847 struct sk_buff *skb;
848 struct ieee80211_mgmt *mgmt;
849 const u8 *ie_auth = NULL;
850 int ie_auth_len = 0;
851
852 if (sdata->vif.type == NL80211_IFTYPE_STATION) {
853 ie_auth_len = sdata->u.mgd.ie_auth_len;
854 ie_auth = sdata->u.mgd.ie_auth;
855 }
856
857 skb = dev_alloc_skb(local->hw.extra_tx_headroom +
858 sizeof(*mgmt) + 6 + extra_len + ie_auth_len);
859 if (!skb) {
860 printk(KERN_DEBUG "%s: failed to allocate buffer for auth "
861 "frame\n", sdata->dev->name);
862 return;
863 }
864 skb_reserve(skb, local->hw.extra_tx_headroom);
865
866 mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24 + 6);
867 memset(mgmt, 0, 24 + 6);
868 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
869 IEEE80211_STYPE_AUTH);
870 if (encrypt)
871 mgmt->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED);
872 memcpy(mgmt->da, bssid, ETH_ALEN);
873 memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN);
874 memcpy(mgmt->bssid, bssid, ETH_ALEN);
875 mgmt->u.auth.auth_alg = cpu_to_le16(auth_alg);
876 mgmt->u.auth.auth_transaction = cpu_to_le16(transaction);
877 mgmt->u.auth.status_code = cpu_to_le16(0);
878 if (extra)
879 memcpy(skb_put(skb, extra_len), extra, extra_len);
880 if (ie_auth)
881 memcpy(skb_put(skb, ie_auth_len), ie_auth, ie_auth_len);
882
883 ieee80211_tx_skb(sdata, skb, encrypt);
884}
885
886void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst,
887 u8 *ssid, size_t ssid_len)
888{
889 struct ieee80211_local *local = sdata->local;
890 struct ieee80211_supported_band *sband;
891 struct sk_buff *skb;
892 struct ieee80211_mgmt *mgmt;
893 u8 *pos, *supp_rates, *esupp_rates = NULL, *extra_preq_ie = NULL;
894 int i, extra_preq_ie_len = 0;
895
896 switch (sdata->vif.type) {
897 case NL80211_IFTYPE_STATION:
898 extra_preq_ie_len = sdata->u.mgd.ie_probereq_len;
899 extra_preq_ie = sdata->u.mgd.ie_probereq;
900 break;
901 default:
902 break;
903 }
904
905 skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt) + 200 +
906 extra_preq_ie_len);
907 if (!skb) {
908 printk(KERN_DEBUG "%s: failed to allocate buffer for probe "
909 "request\n", sdata->dev->name);
910 return;
911 }
912 skb_reserve(skb, local->hw.extra_tx_headroom);
913
914 mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
915 memset(mgmt, 0, 24);
916 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
917 IEEE80211_STYPE_PROBE_REQ);
918 memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN);
919 if (dst) {
920 memcpy(mgmt->da, dst, ETH_ALEN);
921 memcpy(mgmt->bssid, dst, ETH_ALEN);
922 } else {
923 memset(mgmt->da, 0xff, ETH_ALEN);
924 memset(mgmt->bssid, 0xff, ETH_ALEN);
925 }
926 pos = skb_put(skb, 2 + ssid_len);
927 *pos++ = WLAN_EID_SSID;
928 *pos++ = ssid_len;
929 memcpy(pos, ssid, ssid_len);
930
931 supp_rates = skb_put(skb, 2);
932 supp_rates[0] = WLAN_EID_SUPP_RATES;
933 supp_rates[1] = 0;
934 sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
935
936 for (i = 0; i < sband->n_bitrates; i++) {
937 struct ieee80211_rate *rate = &sband->bitrates[i];
938 if (esupp_rates) {
939 pos = skb_put(skb, 1);
940 esupp_rates[1]++;
941 } else if (supp_rates[1] == 8) {
942 esupp_rates = skb_put(skb, 3);
943 esupp_rates[0] = WLAN_EID_EXT_SUPP_RATES;
944 esupp_rates[1] = 1;
945 pos = &esupp_rates[2];
946 } else {
947 pos = skb_put(skb, 1);
948 supp_rates[1]++;
949 }
950 *pos = rate->bitrate / 5;
951 }
952
953 if (extra_preq_ie)
954 memcpy(skb_put(skb, extra_preq_ie_len), extra_preq_ie,
955 extra_preq_ie_len);
956
957 ieee80211_tx_skb(sdata, skb, 0);
958}
959
960u32 ieee80211_sta_get_rates(struct ieee80211_local *local,
961 struct ieee802_11_elems *elems,
962 enum ieee80211_band band)
963{
964 struct ieee80211_supported_band *sband;
965 struct ieee80211_rate *bitrates;
966 size_t num_rates;
967 u32 supp_rates;
968 int i, j;
969 sband = local->hw.wiphy->bands[band];
970
971 if (!sband) {
972 WARN_ON(1);
973 sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
974 }
975
976 bitrates = sband->bitrates;
977 num_rates = sband->n_bitrates;
978 supp_rates = 0;
979 for (i = 0; i < elems->supp_rates_len +
980 elems->ext_supp_rates_len; i++) {
981 u8 rate = 0;
982 int own_rate;
983 if (i < elems->supp_rates_len)
984 rate = elems->supp_rates[i];
985 else if (elems->ext_supp_rates)
986 rate = elems->ext_supp_rates
987 [i - elems->supp_rates_len];
988 own_rate = 5 * (rate & 0x7f);
989 for (j = 0; j < num_rates; j++)
990 if (bitrates[j].bitrate == own_rate)
991 supp_rates |= BIT(j);
992 }
993 return supp_rates;
994}