aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/util.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2009-02-15 06:44:28 -0500
committerJohn W. Linville <linville@tuxdriver.com>2009-02-27 14:51:42 -0500
commit469002983fc90c2ff0959e2b03335c0fe2e4d5a9 (patch)
treefdcf78dcdaeadba897abd86d39d0275e236803b3 /net/mac80211/util.c
parent96f5e66e8a79810e2982cdcfa28e554f3d97da21 (diff)
mac80211: split IBSS/managed code
This patch splits out the ibss code and data from managed (station) mode. The reason to do this is to better separate the state machines, and have the code be contained better so it gets easier to determine what exactly a given change will affect, that in turn makes it easier to understand. This is quite some churn, especially because I split sdata->u.sta into sdata->u.mgd and sdata->u.ibss, but I think it's easier to maintain that way. I've also shuffled around some code -- null function sending is only applicable to managed interfaces so put that into that file, some other functions are needed from various places so put them into util, and also rearranged the prototypes in ieee80211_i.h accordingly. Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: John W. Linville <linville@tuxdriver.com>
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}