1 /*
2 * IEEE 802.11 Common routines
3 * Copyright (c) 2002-2015, Jouni Malinen <j@w1.fi>
4 *
5 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
7 */
8
9 #include "includes.h"
10
11 #include "common.h"
12 #include "defs.h"
13 #include "wpa_common.h"
14 #include "ieee802_11_defs.h"
15 #include "ieee802_11_common.h"
16
17
ieee802_11_parse_vendor_specific(const u8 * pos,size_t elen,struct ieee802_11_elems * elems,int show_errors)18 static int ieee802_11_parse_vendor_specific(const u8 *pos, size_t elen,
19 struct ieee802_11_elems *elems,
20 int show_errors)
21 {
22 unsigned int oui;
23
24 /* first 3 bytes in vendor specific information element are the IEEE
25 * OUI of the vendor. The following byte is used a vendor specific
26 * sub-type. */
27 if (elen < 4) {
28 if (show_errors) {
29 wpa_printf(MSG_MSGDUMP, "short vendor specific "
30 "information element ignored (len=%lu)",
31 (unsigned long) elen);
32 }
33 return -1;
34 }
35
36 oui = WPA_GET_BE24(pos);
37 switch (oui) {
38 case OUI_MICROSOFT:
39 /* Microsoft/Wi-Fi information elements are further typed and
40 * subtyped */
41 switch (pos[3]) {
42 case 1:
43 /* Microsoft OUI (00:50:F2) with OUI Type 1:
44 * real WPA information element */
45 elems->wpa_ie = pos;
46 elems->wpa_ie_len = elen;
47 break;
48 case WMM_OUI_TYPE:
49 /* WMM information element */
50 if (elen < 5) {
51 wpa_printf(MSG_MSGDUMP, "short WMM "
52 "information element ignored "
53 "(len=%lu)",
54 (unsigned long) elen);
55 return -1;
56 }
57 switch (pos[4]) {
58 case WMM_OUI_SUBTYPE_INFORMATION_ELEMENT:
59 case WMM_OUI_SUBTYPE_PARAMETER_ELEMENT:
60 /*
61 * Share same pointer since only one of these
62 * is used and they start with same data.
63 * Length field can be used to distinguish the
64 * IEs.
65 */
66 elems->wmm = pos;
67 elems->wmm_len = elen;
68 break;
69 case WMM_OUI_SUBTYPE_TSPEC_ELEMENT:
70 elems->wmm_tspec = pos;
71 elems->wmm_tspec_len = elen;
72 break;
73 default:
74 wpa_printf(MSG_EXCESSIVE, "unknown WMM "
75 "information element ignored "
76 "(subtype=%d len=%lu)",
77 pos[4], (unsigned long) elen);
78 return -1;
79 }
80 break;
81 case 4:
82 /* Wi-Fi Protected Setup (WPS) IE */
83 elems->wps_ie = pos;
84 elems->wps_ie_len = elen;
85 break;
86 default:
87 wpa_printf(MSG_EXCESSIVE, "Unknown Microsoft "
88 "information element ignored "
89 "(type=%d len=%lu)",
90 pos[3], (unsigned long) elen);
91 return -1;
92 }
93 break;
94
95 case OUI_WFA:
96 switch (pos[3]) {
97 case P2P_OUI_TYPE:
98 /* Wi-Fi Alliance - P2P IE */
99 elems->p2p = pos;
100 elems->p2p_len = elen;
101 break;
102 case WFD_OUI_TYPE:
103 /* Wi-Fi Alliance - WFD IE */
104 elems->wfd = pos;
105 elems->wfd_len = elen;
106 break;
107 case HS20_INDICATION_OUI_TYPE:
108 /* Hotspot 2.0 */
109 elems->hs20 = pos;
110 elems->hs20_len = elen;
111 break;
112 case HS20_OSEN_OUI_TYPE:
113 /* Hotspot 2.0 OSEN */
114 elems->osen = pos;
115 elems->osen_len = elen;
116 break;
117 default:
118 wpa_printf(MSG_MSGDUMP, "Unknown WFA "
119 "information element ignored "
120 "(type=%d len=%lu)",
121 pos[3], (unsigned long) elen);
122 return -1;
123 }
124 break;
125
126 case OUI_BROADCOM:
127 switch (pos[3]) {
128 case VENDOR_HT_CAPAB_OUI_TYPE:
129 elems->vendor_ht_cap = pos;
130 elems->vendor_ht_cap_len = elen;
131 break;
132 case VENDOR_VHT_TYPE:
133 if (elen > 4 &&
134 (pos[4] == VENDOR_VHT_SUBTYPE ||
135 pos[4] == VENDOR_VHT_SUBTYPE2)) {
136 elems->vendor_vht = pos;
137 elems->vendor_vht_len = elen;
138 } else
139 return -1;
140 break;
141 default:
142 wpa_printf(MSG_EXCESSIVE, "Unknown Broadcom "
143 "information element ignored "
144 "(type=%d len=%lu)",
145 pos[3], (unsigned long) elen);
146 return -1;
147 }
148 break;
149
150 default:
151 wpa_printf(MSG_EXCESSIVE, "unknown vendor specific "
152 "information element ignored (vendor OUI "
153 "%02x:%02x:%02x len=%lu)",
154 pos[0], pos[1], pos[2], (unsigned long) elen);
155 return -1;
156 }
157
158 return 0;
159 }
160
161
162 /**
163 * ieee802_11_parse_elems - Parse information elements in management frames
164 * @start: Pointer to the start of IEs
165 * @len: Length of IE buffer in octets
166 * @elems: Data structure for parsed elements
167 * @show_errors: Whether to show parsing errors in debug log
168 * Returns: Parsing result
169 */
ieee802_11_parse_elems(const u8 * start,size_t len,struct ieee802_11_elems * elems,int show_errors)170 ParseRes ieee802_11_parse_elems(const u8 *start, size_t len,
171 struct ieee802_11_elems *elems,
172 int show_errors)
173 {
174 size_t left = len;
175 const u8 *pos = start;
176 int unknown = 0;
177
178 os_memset(elems, 0, sizeof(*elems));
179
180 while (left >= 2) {
181 u8 id, elen;
182
183 id = *pos++;
184 elen = *pos++;
185 left -= 2;
186
187 if (elen > left) {
188 if (show_errors) {
189 wpa_printf(MSG_DEBUG, "IEEE 802.11 element "
190 "parse failed (id=%d elen=%d "
191 "left=%lu)",
192 id, elen, (unsigned long) left);
193 wpa_hexdump(MSG_MSGDUMP, "IEs", start, len);
194 }
195 return ParseFailed;
196 }
197
198 switch (id) {
199 case WLAN_EID_SSID:
200 if (elen > SSID_MAX_LEN) {
201 wpa_printf(MSG_DEBUG,
202 "Ignored too long SSID element (elen=%u)",
203 elen);
204 break;
205 }
206 elems->ssid = pos;
207 elems->ssid_len = elen;
208 break;
209 case WLAN_EID_SUPP_RATES:
210 elems->supp_rates = pos;
211 elems->supp_rates_len = elen;
212 break;
213 case WLAN_EID_DS_PARAMS:
214 if (elen < 1)
215 break;
216 elems->ds_params = pos;
217 break;
218 case WLAN_EID_CF_PARAMS:
219 case WLAN_EID_TIM:
220 break;
221 case WLAN_EID_CHALLENGE:
222 elems->challenge = pos;
223 elems->challenge_len = elen;
224 break;
225 case WLAN_EID_ERP_INFO:
226 if (elen < 1)
227 break;
228 elems->erp_info = pos;
229 break;
230 case WLAN_EID_EXT_SUPP_RATES:
231 elems->ext_supp_rates = pos;
232 elems->ext_supp_rates_len = elen;
233 break;
234 case WLAN_EID_VENDOR_SPECIFIC:
235 if (ieee802_11_parse_vendor_specific(pos, elen,
236 elems,
237 show_errors))
238 unknown++;
239 break;
240 case WLAN_EID_RSN:
241 elems->rsn_ie = pos;
242 elems->rsn_ie_len = elen;
243 break;
244 case WLAN_EID_PWR_CAPABILITY:
245 break;
246 case WLAN_EID_SUPPORTED_CHANNELS:
247 elems->supp_channels = pos;
248 elems->supp_channels_len = elen;
249 break;
250 case WLAN_EID_MOBILITY_DOMAIN:
251 if (elen < sizeof(struct rsn_mdie))
252 break;
253 elems->mdie = pos;
254 elems->mdie_len = elen;
255 break;
256 case WLAN_EID_FAST_BSS_TRANSITION:
257 if (elen < sizeof(struct rsn_ftie))
258 break;
259 elems->ftie = pos;
260 elems->ftie_len = elen;
261 break;
262 case WLAN_EID_TIMEOUT_INTERVAL:
263 if (elen != 5)
264 break;
265 elems->timeout_int = pos;
266 break;
267 case WLAN_EID_HT_CAP:
268 if (elen < sizeof(struct ieee80211_ht_capabilities))
269 break;
270 elems->ht_capabilities = pos;
271 break;
272 case WLAN_EID_HT_OPERATION:
273 if (elen < sizeof(struct ieee80211_ht_operation))
274 break;
275 elems->ht_operation = pos;
276 break;
277 case WLAN_EID_MESH_CONFIG:
278 elems->mesh_config = pos;
279 elems->mesh_config_len = elen;
280 break;
281 case WLAN_EID_MESH_ID:
282 elems->mesh_id = pos;
283 elems->mesh_id_len = elen;
284 break;
285 case WLAN_EID_PEER_MGMT:
286 elems->peer_mgmt = pos;
287 elems->peer_mgmt_len = elen;
288 break;
289 case WLAN_EID_VHT_CAP:
290 if (elen < sizeof(struct ieee80211_vht_capabilities))
291 break;
292 elems->vht_capabilities = pos;
293 break;
294 case WLAN_EID_VHT_OPERATION:
295 if (elen < sizeof(struct ieee80211_vht_operation))
296 break;
297 elems->vht_operation = pos;
298 break;
299 case WLAN_EID_VHT_OPERATING_MODE_NOTIFICATION:
300 if (elen != 1)
301 break;
302 elems->vht_opmode_notif = pos;
303 break;
304 case WLAN_EID_LINK_ID:
305 if (elen < 18)
306 break;
307 elems->link_id = pos;
308 break;
309 case WLAN_EID_INTERWORKING:
310 elems->interworking = pos;
311 elems->interworking_len = elen;
312 break;
313 case WLAN_EID_QOS_MAP_SET:
314 if (elen < 16)
315 break;
316 elems->qos_map_set = pos;
317 elems->qos_map_set_len = elen;
318 break;
319 case WLAN_EID_EXT_CAPAB:
320 elems->ext_capab = pos;
321 elems->ext_capab_len = elen;
322 break;
323 case WLAN_EID_BSS_MAX_IDLE_PERIOD:
324 if (elen < 3)
325 break;
326 elems->bss_max_idle_period = pos;
327 break;
328 case WLAN_EID_SSID_LIST:
329 elems->ssid_list = pos;
330 elems->ssid_list_len = elen;
331 break;
332 case WLAN_EID_AMPE:
333 elems->ampe = pos;
334 elems->ampe_len = elen;
335 break;
336 case WLAN_EID_MIC:
337 elems->mic = pos;
338 elems->mic_len = elen;
339 /* after mic everything is encrypted, so stop. */
340 left = elen;
341 break;
342 default:
343 unknown++;
344 if (!show_errors)
345 break;
346 wpa_printf(MSG_MSGDUMP, "IEEE 802.11 element parse "
347 "ignored unknown element (id=%d elen=%d)",
348 id, elen);
349 break;
350 }
351
352 left -= elen;
353 pos += elen;
354 }
355
356 if (left)
357 return ParseFailed;
358
359 return unknown ? ParseUnknown : ParseOK;
360 }
361
362
ieee802_11_ie_count(const u8 * ies,size_t ies_len)363 int ieee802_11_ie_count(const u8 *ies, size_t ies_len)
364 {
365 int count = 0;
366 const u8 *pos, *end;
367
368 if (ies == NULL)
369 return 0;
370
371 pos = ies;
372 end = ies + ies_len;
373
374 while (pos + 2 <= end) {
375 if (pos + 2 + pos[1] > end)
376 break;
377 count++;
378 pos += 2 + pos[1];
379 }
380
381 return count;
382 }
383
384
ieee802_11_vendor_ie_concat(const u8 * ies,size_t ies_len,u32 oui_type)385 struct wpabuf * ieee802_11_vendor_ie_concat(const u8 *ies, size_t ies_len,
386 u32 oui_type)
387 {
388 struct wpabuf *buf;
389 const u8 *end, *pos, *ie;
390
391 pos = ies;
392 end = ies + ies_len;
393 ie = NULL;
394
395 while (pos + 1 < end) {
396 if (pos + 2 + pos[1] > end)
397 return NULL;
398 if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 &&
399 WPA_GET_BE32(&pos[2]) == oui_type) {
400 ie = pos;
401 break;
402 }
403 pos += 2 + pos[1];
404 }
405
406 if (ie == NULL)
407 return NULL; /* No specified vendor IE found */
408
409 buf = wpabuf_alloc(ies_len);
410 if (buf == NULL)
411 return NULL;
412
413 /*
414 * There may be multiple vendor IEs in the message, so need to
415 * concatenate their data fields.
416 */
417 while (pos + 1 < end) {
418 if (pos + 2 + pos[1] > end)
419 break;
420 if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 &&
421 WPA_GET_BE32(&pos[2]) == oui_type)
422 wpabuf_put_data(buf, pos + 6, pos[1] - 4);
423 pos += 2 + pos[1];
424 }
425
426 return buf;
427 }
428
429
get_hdr_bssid(const struct ieee80211_hdr * hdr,size_t len)430 const u8 * get_hdr_bssid(const struct ieee80211_hdr *hdr, size_t len)
431 {
432 u16 fc, type, stype;
433
434 /*
435 * PS-Poll frames are 16 bytes. All other frames are
436 * 24 bytes or longer.
437 */
438 if (len < 16)
439 return NULL;
440
441 fc = le_to_host16(hdr->frame_control);
442 type = WLAN_FC_GET_TYPE(fc);
443 stype = WLAN_FC_GET_STYPE(fc);
444
445 switch (type) {
446 case WLAN_FC_TYPE_DATA:
447 if (len < 24)
448 return NULL;
449 switch (fc & (WLAN_FC_FROMDS | WLAN_FC_TODS)) {
450 case WLAN_FC_FROMDS | WLAN_FC_TODS:
451 case WLAN_FC_TODS:
452 return hdr->addr1;
453 case WLAN_FC_FROMDS:
454 return hdr->addr2;
455 default:
456 return NULL;
457 }
458 case WLAN_FC_TYPE_CTRL:
459 if (stype != WLAN_FC_STYPE_PSPOLL)
460 return NULL;
461 return hdr->addr1;
462 case WLAN_FC_TYPE_MGMT:
463 return hdr->addr3;
464 default:
465 return NULL;
466 }
467 }
468
469
hostapd_config_wmm_ac(struct hostapd_wmm_ac_params wmm_ac_params[],const char * name,const char * val)470 int hostapd_config_wmm_ac(struct hostapd_wmm_ac_params wmm_ac_params[],
471 const char *name, const char *val)
472 {
473 int num, v;
474 const char *pos;
475 struct hostapd_wmm_ac_params *ac;
476
477 /* skip 'wme_ac_' or 'wmm_ac_' prefix */
478 pos = name + 7;
479 if (os_strncmp(pos, "be_", 3) == 0) {
480 num = 0;
481 pos += 3;
482 } else if (os_strncmp(pos, "bk_", 3) == 0) {
483 num = 1;
484 pos += 3;
485 } else if (os_strncmp(pos, "vi_", 3) == 0) {
486 num = 2;
487 pos += 3;
488 } else if (os_strncmp(pos, "vo_", 3) == 0) {
489 num = 3;
490 pos += 3;
491 } else {
492 wpa_printf(MSG_ERROR, "Unknown WMM name '%s'", pos);
493 return -1;
494 }
495
496 ac = &wmm_ac_params[num];
497
498 if (os_strcmp(pos, "aifs") == 0) {
499 v = atoi(val);
500 if (v < 1 || v > 255) {
501 wpa_printf(MSG_ERROR, "Invalid AIFS value %d", v);
502 return -1;
503 }
504 ac->aifs = v;
505 } else if (os_strcmp(pos, "cwmin") == 0) {
506 v = atoi(val);
507 if (v < 0 || v > 15) {
508 wpa_printf(MSG_ERROR, "Invalid cwMin value %d", v);
509 return -1;
510 }
511 ac->cwmin = v;
512 } else if (os_strcmp(pos, "cwmax") == 0) {
513 v = atoi(val);
514 if (v < 0 || v > 15) {
515 wpa_printf(MSG_ERROR, "Invalid cwMax value %d", v);
516 return -1;
517 }
518 ac->cwmax = v;
519 } else if (os_strcmp(pos, "txop_limit") == 0) {
520 v = atoi(val);
521 if (v < 0 || v > 0xffff) {
522 wpa_printf(MSG_ERROR, "Invalid txop value %d", v);
523 return -1;
524 }
525 ac->txop_limit = v;
526 } else if (os_strcmp(pos, "acm") == 0) {
527 v = atoi(val);
528 if (v < 0 || v > 1) {
529 wpa_printf(MSG_ERROR, "Invalid acm value %d", v);
530 return -1;
531 }
532 ac->admission_control_mandatory = v;
533 } else {
534 wpa_printf(MSG_ERROR, "Unknown wmm_ac_ field '%s'", pos);
535 return -1;
536 }
537
538 return 0;
539 }
540
541
ieee80211_freq_to_chan(int freq,u8 * channel)542 enum hostapd_hw_mode ieee80211_freq_to_chan(int freq, u8 *channel)
543 {
544 enum hostapd_hw_mode mode = NUM_HOSTAPD_MODES;
545
546 if (freq >= 2412 && freq <= 2472) {
547 mode = HOSTAPD_MODE_IEEE80211G;
548 *channel = (freq - 2407) / 5;
549 } else if (freq == 2484) {
550 mode = HOSTAPD_MODE_IEEE80211B;
551 *channel = 14;
552 } else if (freq >= 4900 && freq < 5000) {
553 mode = HOSTAPD_MODE_IEEE80211A;
554 *channel = (freq - 4000) / 5;
555 } else if (freq >= 5000 && freq < 5900) {
556 mode = HOSTAPD_MODE_IEEE80211A;
557 *channel = (freq - 5000) / 5;
558 } else if (freq >= 56160 + 2160 * 1 && freq <= 56160 + 2160 * 4) {
559 mode = HOSTAPD_MODE_IEEE80211AD;
560 *channel = (freq - 56160) / 2160;
561 }
562
563 return mode;
564 }
565
566
567 static const char *const us_op_class_cc[] = {
568 "US", "CA", NULL
569 };
570
571 static const char *const eu_op_class_cc[] = {
572 "AL", "AM", "AT", "AZ", "BA", "BE", "BG", "BY", "CH", "CY", "CZ", "DE",
573 "DK", "EE", "EL", "ES", "FI", "FR", "GE", "HR", "HU", "IE", "IS", "IT",
574 "LI", "LT", "LU", "LV", "MD", "ME", "MK", "MT", "NL", "NO", "PL", "PT",
575 "RO", "RS", "RU", "SE", "SI", "SK", "TR", "UA", "UK", NULL
576 };
577
578 static const char *const jp_op_class_cc[] = {
579 "JP", NULL
580 };
581
582 static const char *const cn_op_class_cc[] = {
583 "CN", NULL
584 };
585
586
country_match(const char * const cc[],const char * const country)587 static int country_match(const char *const cc[], const char *const country)
588 {
589 int i;
590
591 if (country == NULL)
592 return 0;
593 for (i = 0; cc[i]; i++) {
594 if (cc[i][0] == country[0] && cc[i][1] == country[1])
595 return 1;
596 }
597
598 return 0;
599 }
600
601
ieee80211_chan_to_freq_us(u8 op_class,u8 chan)602 static int ieee80211_chan_to_freq_us(u8 op_class, u8 chan)
603 {
604 switch (op_class) {
605 case 12: /* channels 1..11 */
606 case 32: /* channels 1..7; 40 MHz */
607 case 33: /* channels 5..11; 40 MHz */
608 if (chan < 1 || chan > 11)
609 return -1;
610 return 2407 + 5 * chan;
611 case 1: /* channels 36,40,44,48 */
612 case 2: /* channels 52,56,60,64; dfs */
613 case 22: /* channels 36,44; 40 MHz */
614 case 23: /* channels 52,60; 40 MHz */
615 case 27: /* channels 40,48; 40 MHz */
616 case 28: /* channels 56,64; 40 MHz */
617 if (chan < 36 || chan > 64)
618 return -1;
619 return 5000 + 5 * chan;
620 case 4: /* channels 100-144 */
621 case 24: /* channels 100-140; 40 MHz */
622 if (chan < 100 || chan > 144)
623 return -1;
624 return 5000 + 5 * chan;
625 case 3: /* channels 149,153,157,161 */
626 case 25: /* channels 149,157; 40 MHz */
627 case 26: /* channels 149,157; 40 MHz */
628 case 30: /* channels 153,161; 40 MHz */
629 case 31: /* channels 153,161; 40 MHz */
630 if (chan < 149 || chan > 161)
631 return -1;
632 return 5000 + 5 * chan;
633 case 5: /* channels 149,153,157,161,165 */
634 if (chan < 149 || chan > 165)
635 return -1;
636 return 5000 + 5 * chan;
637 case 34: /* 60 GHz band, channels 1..3 */
638 if (chan < 1 || chan > 3)
639 return -1;
640 return 56160 + 2160 * chan;
641 }
642 return -1;
643 }
644
645
ieee80211_chan_to_freq_eu(u8 op_class,u8 chan)646 static int ieee80211_chan_to_freq_eu(u8 op_class, u8 chan)
647 {
648 switch (op_class) {
649 case 4: /* channels 1..13 */
650 case 11: /* channels 1..9; 40 MHz */
651 case 12: /* channels 5..13; 40 MHz */
652 if (chan < 1 || chan > 13)
653 return -1;
654 return 2407 + 5 * chan;
655 case 1: /* channels 36,40,44,48 */
656 case 2: /* channels 52,56,60,64; dfs */
657 case 5: /* channels 36,44; 40 MHz */
658 case 6: /* channels 52,60; 40 MHz */
659 case 8: /* channels 40,48; 40 MHz */
660 case 9: /* channels 56,64; 40 MHz */
661 if (chan < 36 || chan > 64)
662 return -1;
663 return 5000 + 5 * chan;
664 case 3: /* channels 100-140 */
665 case 7: /* channels 100-132; 40 MHz */
666 case 10: /* channels 104-136; 40 MHz */
667 case 16: /* channels 100-140 */
668 if (chan < 100 || chan > 140)
669 return -1;
670 return 5000 + 5 * chan;
671 case 17: /* channels 149,153,157,161,165,169 */
672 if (chan < 149 || chan > 169)
673 return -1;
674 return 5000 + 5 * chan;
675 case 18: /* 60 GHz band, channels 1..4 */
676 if (chan < 1 || chan > 4)
677 return -1;
678 return 56160 + 2160 * chan;
679 }
680 return -1;
681 }
682
683
ieee80211_chan_to_freq_jp(u8 op_class,u8 chan)684 static int ieee80211_chan_to_freq_jp(u8 op_class, u8 chan)
685 {
686 switch (op_class) {
687 case 30: /* channels 1..13 */
688 case 56: /* channels 1..9; 40 MHz */
689 case 57: /* channels 5..13; 40 MHz */
690 if (chan < 1 || chan > 13)
691 return -1;
692 return 2407 + 5 * chan;
693 case 31: /* channel 14 */
694 if (chan != 14)
695 return -1;
696 return 2414 + 5 * chan;
697 case 1: /* channels 34,38,42,46(old) or 36,40,44,48 */
698 case 32: /* channels 52,56,60,64 */
699 case 33: /* channels 52,56,60,64 */
700 case 36: /* channels 36,44; 40 MHz */
701 case 37: /* channels 52,60; 40 MHz */
702 case 38: /* channels 52,60; 40 MHz */
703 case 41: /* channels 40,48; 40 MHz */
704 case 42: /* channels 56,64; 40 MHz */
705 case 43: /* channels 56,64; 40 MHz */
706 if (chan < 34 || chan > 64)
707 return -1;
708 return 5000 + 5 * chan;
709 case 34: /* channels 100-140 */
710 case 35: /* channels 100-140 */
711 case 39: /* channels 100-132; 40 MHz */
712 case 40: /* channels 100-132; 40 MHz */
713 case 44: /* channels 104-136; 40 MHz */
714 case 45: /* channels 104-136; 40 MHz */
715 case 58: /* channels 100-140 */
716 if (chan < 100 || chan > 140)
717 return -1;
718 return 5000 + 5 * chan;
719 case 59: /* 60 GHz band, channels 1..4 */
720 if (chan < 1 || chan > 3)
721 return -1;
722 return 56160 + 2160 * chan;
723 }
724 return -1;
725 }
726
727
ieee80211_chan_to_freq_cn(u8 op_class,u8 chan)728 static int ieee80211_chan_to_freq_cn(u8 op_class, u8 chan)
729 {
730 switch (op_class) {
731 case 7: /* channels 1..13 */
732 case 8: /* channels 1..9; 40 MHz */
733 case 9: /* channels 5..13; 40 MHz */
734 if (chan < 1 || chan > 13)
735 return -1;
736 return 2407 + 5 * chan;
737 case 1: /* channels 36,40,44,48 */
738 case 2: /* channels 52,56,60,64; dfs */
739 case 4: /* channels 36,44; 40 MHz */
740 case 5: /* channels 52,60; 40 MHz */
741 if (chan < 36 || chan > 64)
742 return -1;
743 return 5000 + 5 * chan;
744 case 3: /* channels 149,153,157,161,165 */
745 case 6: /* channels 149,157; 40 MHz */
746 if (chan < 149 || chan > 165)
747 return -1;
748 return 5000 + 5 * chan;
749 }
750 return -1;
751 }
752
753
ieee80211_chan_to_freq_global(u8 op_class,u8 chan)754 static int ieee80211_chan_to_freq_global(u8 op_class, u8 chan)
755 {
756 /* Table E-4 in IEEE Std 802.11-2012 - Global operating classes */
757 switch (op_class) {
758 case 81:
759 /* channels 1..13 */
760 if (chan < 1 || chan > 13)
761 return -1;
762 return 2407 + 5 * chan;
763 case 82:
764 /* channel 14 */
765 if (chan != 14)
766 return -1;
767 return 2414 + 5 * chan;
768 case 83: /* channels 1..9; 40 MHz */
769 case 84: /* channels 5..13; 40 MHz */
770 if (chan < 1 || chan > 13)
771 return -1;
772 return 2407 + 5 * chan;
773 case 115: /* channels 36,40,44,48; indoor only */
774 case 116: /* channels 36,44; 40 MHz; indoor only */
775 case 117: /* channels 40,48; 40 MHz; indoor only */
776 case 118: /* channels 52,56,60,64; dfs */
777 case 119: /* channels 52,60; 40 MHz; dfs */
778 case 120: /* channels 56,64; 40 MHz; dfs */
779 if (chan < 36 || chan > 64)
780 return -1;
781 return 5000 + 5 * chan;
782 case 121: /* channels 100-140 */
783 case 122: /* channels 100-142; 40 MHz */
784 case 123: /* channels 104-136; 40 MHz */
785 if (chan < 100 || chan > 140)
786 return -1;
787 return 5000 + 5 * chan;
788 case 124: /* channels 149,153,157,161 */
789 case 126: /* channels 149,157; 40 MHz */
790 case 127: /* channels 153,161; 40 MHz */
791 if (chan < 149 || chan > 161)
792 return -1;
793 return 5000 + 5 * chan;
794 case 125: /* channels 149,153,157,161,165,169 */
795 if (chan < 149 || chan > 169)
796 return -1;
797 return 5000 + 5 * chan;
798 case 128: /* center freqs 42, 58, 106, 122, 138, 155; 80 MHz */
799 case 130: /* center freqs 42, 58, 106, 122, 138, 155; 80 MHz */
800 if (chan < 36 || chan > 161)
801 return -1;
802 return 5000 + 5 * chan;
803 case 129: /* center freqs 50, 114; 160 MHz */
804 if (chan < 50 || chan > 114)
805 return -1;
806 return 5000 + 5 * chan;
807 case 180: /* 60 GHz band, channels 1..4 */
808 if (chan < 1 || chan > 4)
809 return -1;
810 return 56160 + 2160 * chan;
811 }
812 return -1;
813 }
814
815 /**
816 * ieee80211_chan_to_freq - Convert channel info to frequency
817 * @country: Country code, if known; otherwise, global operating class is used
818 * @op_class: Operating class
819 * @chan: Channel number
820 * Returns: Frequency in MHz or -1 if the specified channel is unknown
821 */
ieee80211_chan_to_freq(const char * country,u8 op_class,u8 chan)822 int ieee80211_chan_to_freq(const char *country, u8 op_class, u8 chan)
823 {
824 int freq;
825
826 if (country_match(us_op_class_cc, country)) {
827 freq = ieee80211_chan_to_freq_us(op_class, chan);
828 if (freq > 0)
829 return freq;
830 }
831
832 if (country_match(eu_op_class_cc, country)) {
833 freq = ieee80211_chan_to_freq_eu(op_class, chan);
834 if (freq > 0)
835 return freq;
836 }
837
838 if (country_match(jp_op_class_cc, country)) {
839 freq = ieee80211_chan_to_freq_jp(op_class, chan);
840 if (freq > 0)
841 return freq;
842 }
843
844 if (country_match(cn_op_class_cc, country)) {
845 freq = ieee80211_chan_to_freq_cn(op_class, chan);
846 if (freq > 0)
847 return freq;
848 }
849
850 return ieee80211_chan_to_freq_global(op_class, chan);
851 }
852
853
ieee80211_is_dfs(int freq)854 int ieee80211_is_dfs(int freq)
855 {
856 /* TODO: this could be more accurate to better cover all domains */
857 return (freq >= 5260 && freq <= 5320) || (freq >= 5500 && freq <= 5700);
858 }
859
860
is_11b(u8 rate)861 static int is_11b(u8 rate)
862 {
863 return rate == 0x02 || rate == 0x04 || rate == 0x0b || rate == 0x16;
864 }
865
866
supp_rates_11b_only(struct ieee802_11_elems * elems)867 int supp_rates_11b_only(struct ieee802_11_elems *elems)
868 {
869 int num_11b = 0, num_others = 0;
870 int i;
871
872 if (elems->supp_rates == NULL && elems->ext_supp_rates == NULL)
873 return 0;
874
875 for (i = 0; elems->supp_rates && i < elems->supp_rates_len; i++) {
876 if (is_11b(elems->supp_rates[i]))
877 num_11b++;
878 else
879 num_others++;
880 }
881
882 for (i = 0; elems->ext_supp_rates && i < elems->ext_supp_rates_len;
883 i++) {
884 if (is_11b(elems->ext_supp_rates[i]))
885 num_11b++;
886 else
887 num_others++;
888 }
889
890 return num_11b > 0 && num_others == 0;
891 }
892
893
fc2str(u16 fc)894 const char * fc2str(u16 fc)
895 {
896 u16 stype = WLAN_FC_GET_STYPE(fc);
897 #define C2S(x) case x: return #x;
898
899 switch (WLAN_FC_GET_TYPE(fc)) {
900 case WLAN_FC_TYPE_MGMT:
901 switch (stype) {
902 C2S(WLAN_FC_STYPE_ASSOC_REQ)
903 C2S(WLAN_FC_STYPE_ASSOC_RESP)
904 C2S(WLAN_FC_STYPE_REASSOC_REQ)
905 C2S(WLAN_FC_STYPE_REASSOC_RESP)
906 C2S(WLAN_FC_STYPE_PROBE_REQ)
907 C2S(WLAN_FC_STYPE_PROBE_RESP)
908 C2S(WLAN_FC_STYPE_BEACON)
909 C2S(WLAN_FC_STYPE_ATIM)
910 C2S(WLAN_FC_STYPE_DISASSOC)
911 C2S(WLAN_FC_STYPE_AUTH)
912 C2S(WLAN_FC_STYPE_DEAUTH)
913 C2S(WLAN_FC_STYPE_ACTION)
914 }
915 break;
916 case WLAN_FC_TYPE_CTRL:
917 switch (stype) {
918 C2S(WLAN_FC_STYPE_PSPOLL)
919 C2S(WLAN_FC_STYPE_RTS)
920 C2S(WLAN_FC_STYPE_CTS)
921 C2S(WLAN_FC_STYPE_ACK)
922 C2S(WLAN_FC_STYPE_CFEND)
923 C2S(WLAN_FC_STYPE_CFENDACK)
924 }
925 break;
926 case WLAN_FC_TYPE_DATA:
927 switch (stype) {
928 C2S(WLAN_FC_STYPE_DATA)
929 C2S(WLAN_FC_STYPE_DATA_CFACK)
930 C2S(WLAN_FC_STYPE_DATA_CFPOLL)
931 C2S(WLAN_FC_STYPE_DATA_CFACKPOLL)
932 C2S(WLAN_FC_STYPE_NULLFUNC)
933 C2S(WLAN_FC_STYPE_CFACK)
934 C2S(WLAN_FC_STYPE_CFPOLL)
935 C2S(WLAN_FC_STYPE_CFACKPOLL)
936 C2S(WLAN_FC_STYPE_QOS_DATA)
937 C2S(WLAN_FC_STYPE_QOS_DATA_CFACK)
938 C2S(WLAN_FC_STYPE_QOS_DATA_CFPOLL)
939 C2S(WLAN_FC_STYPE_QOS_DATA_CFACKPOLL)
940 C2S(WLAN_FC_STYPE_QOS_NULL)
941 C2S(WLAN_FC_STYPE_QOS_CFPOLL)
942 C2S(WLAN_FC_STYPE_QOS_CFACKPOLL)
943 }
944 break;
945 }
946 return "WLAN_FC_TYPE_UNKNOWN";
947 #undef C2S
948 }
949