nl80211: Validate NL80211_ATTR_KEY_SEQ length
[deliverable/linux.git] / net / wireless / util.c
1 /*
2 * Wireless utility functions
3 *
4 * Copyright 2007-2009 Johannes Berg <johannes@sipsolutions.net>
5 */
6 #include <linux/bitops.h>
7 #include <net/cfg80211.h>
8 #include "core.h"
9
10 struct ieee80211_rate *
11 ieee80211_get_response_rate(struct ieee80211_supported_band *sband,
12 u32 basic_rates, int bitrate)
13 {
14 struct ieee80211_rate *result = &sband->bitrates[0];
15 int i;
16
17 for (i = 0; i < sband->n_bitrates; i++) {
18 if (!(basic_rates & BIT(i)))
19 continue;
20 if (sband->bitrates[i].bitrate > bitrate)
21 continue;
22 result = &sband->bitrates[i];
23 }
24
25 return result;
26 }
27 EXPORT_SYMBOL(ieee80211_get_response_rate);
28
29 int ieee80211_channel_to_frequency(int chan)
30 {
31 if (chan < 14)
32 return 2407 + chan * 5;
33
34 if (chan == 14)
35 return 2484;
36
37 /* FIXME: 802.11j 17.3.8.3.2 */
38 return (chan + 1000) * 5;
39 }
40 EXPORT_SYMBOL(ieee80211_channel_to_frequency);
41
42 int ieee80211_frequency_to_channel(int freq)
43 {
44 if (freq == 2484)
45 return 14;
46
47 if (freq < 2484)
48 return (freq - 2407) / 5;
49
50 /* FIXME: 802.11j 17.3.8.3.2 */
51 return freq/5 - 1000;
52 }
53 EXPORT_SYMBOL(ieee80211_frequency_to_channel);
54
55 struct ieee80211_channel *__ieee80211_get_channel(struct wiphy *wiphy,
56 int freq)
57 {
58 enum ieee80211_band band;
59 struct ieee80211_supported_band *sband;
60 int i;
61
62 for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
63 sband = wiphy->bands[band];
64
65 if (!sband)
66 continue;
67
68 for (i = 0; i < sband->n_channels; i++) {
69 if (sband->channels[i].center_freq == freq)
70 return &sband->channels[i];
71 }
72 }
73
74 return NULL;
75 }
76 EXPORT_SYMBOL(__ieee80211_get_channel);
77
78 static void set_mandatory_flags_band(struct ieee80211_supported_band *sband,
79 enum ieee80211_band band)
80 {
81 int i, want;
82
83 switch (band) {
84 case IEEE80211_BAND_5GHZ:
85 want = 3;
86 for (i = 0; i < sband->n_bitrates; i++) {
87 if (sband->bitrates[i].bitrate == 60 ||
88 sband->bitrates[i].bitrate == 120 ||
89 sband->bitrates[i].bitrate == 240) {
90 sband->bitrates[i].flags |=
91 IEEE80211_RATE_MANDATORY_A;
92 want--;
93 }
94 }
95 WARN_ON(want);
96 break;
97 case IEEE80211_BAND_2GHZ:
98 want = 7;
99 for (i = 0; i < sband->n_bitrates; i++) {
100 if (sband->bitrates[i].bitrate == 10) {
101 sband->bitrates[i].flags |=
102 IEEE80211_RATE_MANDATORY_B |
103 IEEE80211_RATE_MANDATORY_G;
104 want--;
105 }
106
107 if (sband->bitrates[i].bitrate == 20 ||
108 sband->bitrates[i].bitrate == 55 ||
109 sband->bitrates[i].bitrate == 110 ||
110 sband->bitrates[i].bitrate == 60 ||
111 sband->bitrates[i].bitrate == 120 ||
112 sband->bitrates[i].bitrate == 240) {
113 sband->bitrates[i].flags |=
114 IEEE80211_RATE_MANDATORY_G;
115 want--;
116 }
117
118 if (sband->bitrates[i].bitrate != 10 &&
119 sband->bitrates[i].bitrate != 20 &&
120 sband->bitrates[i].bitrate != 55 &&
121 sband->bitrates[i].bitrate != 110)
122 sband->bitrates[i].flags |=
123 IEEE80211_RATE_ERP_G;
124 }
125 WARN_ON(want != 0 && want != 3 && want != 6);
126 break;
127 case IEEE80211_NUM_BANDS:
128 WARN_ON(1);
129 break;
130 }
131 }
132
133 void ieee80211_set_bitrate_flags(struct wiphy *wiphy)
134 {
135 enum ieee80211_band band;
136
137 for (band = 0; band < IEEE80211_NUM_BANDS; band++)
138 if (wiphy->bands[band])
139 set_mandatory_flags_band(wiphy->bands[band], band);
140 }
141
142 int cfg80211_validate_key_settings(struct key_params *params, int key_idx,
143 const u8 *mac_addr)
144 {
145 if (key_idx > 5)
146 return -EINVAL;
147
148 /*
149 * Disallow pairwise keys with non-zero index unless it's WEP
150 * (because current deployments use pairwise WEP keys with
151 * non-zero indizes but 802.11i clearly specifies to use zero)
152 */
153 if (mac_addr && key_idx &&
154 params->cipher != WLAN_CIPHER_SUITE_WEP40 &&
155 params->cipher != WLAN_CIPHER_SUITE_WEP104)
156 return -EINVAL;
157
158 /* TODO: add definitions for the lengths to linux/ieee80211.h */
159 switch (params->cipher) {
160 case WLAN_CIPHER_SUITE_WEP40:
161 if (params->key_len != 5)
162 return -EINVAL;
163 break;
164 case WLAN_CIPHER_SUITE_TKIP:
165 if (params->key_len != 32)
166 return -EINVAL;
167 break;
168 case WLAN_CIPHER_SUITE_CCMP:
169 if (params->key_len != 16)
170 return -EINVAL;
171 break;
172 case WLAN_CIPHER_SUITE_WEP104:
173 if (params->key_len != 13)
174 return -EINVAL;
175 break;
176 case WLAN_CIPHER_SUITE_AES_CMAC:
177 if (params->key_len != 16)
178 return -EINVAL;
179 break;
180 default:
181 return -EINVAL;
182 }
183
184 if (params->seq) {
185 switch (params->cipher) {
186 case WLAN_CIPHER_SUITE_WEP40:
187 case WLAN_CIPHER_SUITE_WEP104:
188 /* These ciphers do not use key sequence */
189 return -EINVAL;
190 case WLAN_CIPHER_SUITE_TKIP:
191 case WLAN_CIPHER_SUITE_CCMP:
192 case WLAN_CIPHER_SUITE_AES_CMAC:
193 if (params->seq_len != 6)
194 return -EINVAL;
195 break;
196 }
197 }
198
199 return 0;
200 }
This page took 0.038152 seconds and 5 git commands to generate.