aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/cfg80211.h63
-rw-r--r--net/mac80211/ieee80211_i.h63
-rw-r--r--net/mac80211/util.c167
-rw-r--r--net/wireless/util.c168
4 files changed, 230 insertions, 231 deletions
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 26890045dbd6..6a1d849c597a 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -2391,69 +2391,6 @@ extern int ieee80211_radiotap_iterator_next(
2391extern const unsigned char rfc1042_header[6]; 2391extern const unsigned char rfc1042_header[6];
2392extern const unsigned char bridge_tunnel_header[6]; 2392extern const unsigned char bridge_tunnel_header[6];
2393 2393
2394/* Parsed Information Elements */
2395struct ieee802_11_elems {
2396 u8 *ie_start;
2397 size_t total_len;
2398
2399 /* pointers to IEs */
2400 u8 *ssid;
2401 u8 *supp_rates;
2402 u8 *fh_params;
2403 u8 *ds_params;
2404 u8 *cf_params;
2405 struct ieee80211_tim_ie *tim;
2406 u8 *ibss_params;
2407 u8 *challenge;
2408 u8 *wpa;
2409 u8 *rsn;
2410 u8 *erp_info;
2411 u8 *ext_supp_rates;
2412 u8 *wmm_info;
2413 u8 *wmm_param;
2414 struct ieee80211_ht_cap *ht_cap_elem;
2415 struct ieee80211_ht_info *ht_info_elem;
2416 struct ieee80211_meshconf_ie *mesh_config;
2417 u8 *mesh_id;
2418 u8 *peering;
2419 u8 *preq;
2420 u8 *prep;
2421 u8 *perr;
2422 struct ieee80211_rann_ie *rann;
2423 u8 *ch_switch_elem;
2424 u8 *country_elem;
2425 u8 *pwr_constr_elem;
2426 u8 *quiet_elem; /* first quite element */
2427 u8 *timeout_int;
2428
2429 /* length of them, respectively */
2430 u8 ssid_len;
2431 u8 supp_rates_len;
2432 u8 fh_params_len;
2433 u8 ds_params_len;
2434 u8 cf_params_len;
2435 u8 tim_len;
2436 u8 ibss_params_len;
2437 u8 challenge_len;
2438 u8 wpa_len;
2439 u8 rsn_len;
2440 u8 erp_info_len;
2441 u8 ext_supp_rates_len;
2442 u8 wmm_info_len;
2443 u8 wmm_param_len;
2444 u8 mesh_id_len;
2445 u8 peering_len;
2446 u8 preq_len;
2447 u8 prep_len;
2448 u8 perr_len;
2449 u8 ch_switch_elem_len;
2450 u8 country_elem_len;
2451 u8 pwr_constr_elem_len;
2452 u8 quiet_elem_len;
2453 u8 num_of_quiet_elem; /* can be more the one */
2454 u8 timeout_int_len;
2455};
2456
2457/** 2394/**
2458 * ieee80211_get_hdrlen_from_skb - get header length from data 2395 * ieee80211_get_hdrlen_from_skb - get header length from data
2459 * 2396 *
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index f2785056d8d9..17661df1515f 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -1040,6 +1040,69 @@ struct ieee80211_ra_tid {
1040 u16 tid; 1040 u16 tid;
1041}; 1041};
1042 1042
1043/* Parsed Information Elements */
1044struct ieee802_11_elems {
1045 u8 *ie_start;
1046 size_t total_len;
1047
1048 /* pointers to IEs */
1049 u8 *ssid;
1050 u8 *supp_rates;
1051 u8 *fh_params;
1052 u8 *ds_params;
1053 u8 *cf_params;
1054 struct ieee80211_tim_ie *tim;
1055 u8 *ibss_params;
1056 u8 *challenge;
1057 u8 *wpa;
1058 u8 *rsn;
1059 u8 *erp_info;
1060 u8 *ext_supp_rates;
1061 u8 *wmm_info;
1062 u8 *wmm_param;
1063 struct ieee80211_ht_cap *ht_cap_elem;
1064 struct ieee80211_ht_info *ht_info_elem;
1065 struct ieee80211_meshconf_ie *mesh_config;
1066 u8 *mesh_id;
1067 u8 *peering;
1068 u8 *preq;
1069 u8 *prep;
1070 u8 *perr;
1071 struct ieee80211_rann_ie *rann;
1072 u8 *ch_switch_elem;
1073 u8 *country_elem;
1074 u8 *pwr_constr_elem;
1075 u8 *quiet_elem; /* first quite element */
1076 u8 *timeout_int;
1077
1078 /* length of them, respectively */
1079 u8 ssid_len;
1080 u8 supp_rates_len;
1081 u8 fh_params_len;
1082 u8 ds_params_len;
1083 u8 cf_params_len;
1084 u8 tim_len;
1085 u8 ibss_params_len;
1086 u8 challenge_len;
1087 u8 wpa_len;
1088 u8 rsn_len;
1089 u8 erp_info_len;
1090 u8 ext_supp_rates_len;
1091 u8 wmm_info_len;
1092 u8 wmm_param_len;
1093 u8 mesh_id_len;
1094 u8 peering_len;
1095 u8 preq_len;
1096 u8 prep_len;
1097 u8 perr_len;
1098 u8 ch_switch_elem_len;
1099 u8 country_elem_len;
1100 u8 pwr_constr_elem_len;
1101 u8 quiet_elem_len;
1102 u8 num_of_quiet_elem; /* can be more the one */
1103 u8 timeout_int_len;
1104};
1105
1043static inline struct ieee80211_local *hw_to_local( 1106static inline struct ieee80211_local *hw_to_local(
1044 struct ieee80211_hw *hw) 1107 struct ieee80211_hw *hw)
1045{ 1108{
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 939bf248ec73..e2cb00df8c36 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -19,6 +19,7 @@
19#include <linux/etherdevice.h> 19#include <linux/etherdevice.h>
20#include <linux/if_arp.h> 20#include <linux/if_arp.h>
21#include <linux/bitmap.h> 21#include <linux/bitmap.h>
22#include <linux/crc32.h>
22#include <net/net_namespace.h> 23#include <net/net_namespace.h>
23#include <net/cfg80211.h> 24#include <net/cfg80211.h>
24#include <net/rtnetlink.h> 25#include <net/rtnetlink.h>
@@ -563,6 +564,172 @@ void ieee80211_queue_delayed_work(struct ieee80211_hw *hw,
563} 564}
564EXPORT_SYMBOL(ieee80211_queue_delayed_work); 565EXPORT_SYMBOL(ieee80211_queue_delayed_work);
565 566
567u32 ieee802_11_parse_elems_crc(u8 *start, size_t len,
568 struct ieee802_11_elems *elems,
569 u64 filter, u32 crc)
570{
571 size_t left = len;
572 u8 *pos = start;
573 bool calc_crc = filter != 0;
574
575 memset(elems, 0, sizeof(*elems));
576 elems->ie_start = start;
577 elems->total_len = len;
578
579 while (left >= 2) {
580 u8 id, elen;
581
582 id = *pos++;
583 elen = *pos++;
584 left -= 2;
585
586 if (elen > left)
587 break;
588
589 if (calc_crc && id < 64 && (filter & (1ULL << id)))
590 crc = crc32_be(crc, pos - 2, elen + 2);
591
592 switch (id) {
593 case WLAN_EID_SSID:
594 elems->ssid = pos;
595 elems->ssid_len = elen;
596 break;
597 case WLAN_EID_SUPP_RATES:
598 elems->supp_rates = pos;
599 elems->supp_rates_len = elen;
600 break;
601 case WLAN_EID_FH_PARAMS:
602 elems->fh_params = pos;
603 elems->fh_params_len = elen;
604 break;
605 case WLAN_EID_DS_PARAMS:
606 elems->ds_params = pos;
607 elems->ds_params_len = elen;
608 break;
609 case WLAN_EID_CF_PARAMS:
610 elems->cf_params = pos;
611 elems->cf_params_len = elen;
612 break;
613 case WLAN_EID_TIM:
614 if (elen >= sizeof(struct ieee80211_tim_ie)) {
615 elems->tim = (void *)pos;
616 elems->tim_len = elen;
617 }
618 break;
619 case WLAN_EID_IBSS_PARAMS:
620 elems->ibss_params = pos;
621 elems->ibss_params_len = elen;
622 break;
623 case WLAN_EID_CHALLENGE:
624 elems->challenge = pos;
625 elems->challenge_len = elen;
626 break;
627 case WLAN_EID_VENDOR_SPECIFIC:
628 if (elen >= 4 && pos[0] == 0x00 && pos[1] == 0x50 &&
629 pos[2] == 0xf2) {
630 /* Microsoft OUI (00:50:F2) */
631
632 if (calc_crc)
633 crc = crc32_be(crc, pos - 2, elen + 2);
634
635 if (pos[3] == 1) {
636 /* OUI Type 1 - WPA IE */
637 elems->wpa = pos;
638 elems->wpa_len = elen;
639 } else if (elen >= 5 && pos[3] == 2) {
640 /* OUI Type 2 - WMM IE */
641 if (pos[4] == 0) {
642 elems->wmm_info = pos;
643 elems->wmm_info_len = elen;
644 } else if (pos[4] == 1) {
645 elems->wmm_param = pos;
646 elems->wmm_param_len = elen;
647 }
648 }
649 }
650 break;
651 case WLAN_EID_RSN:
652 elems->rsn = pos;
653 elems->rsn_len = elen;
654 break;
655 case WLAN_EID_ERP_INFO:
656 elems->erp_info = pos;
657 elems->erp_info_len = elen;
658 break;
659 case WLAN_EID_EXT_SUPP_RATES:
660 elems->ext_supp_rates = pos;
661 elems->ext_supp_rates_len = elen;
662 break;
663 case WLAN_EID_HT_CAPABILITY:
664 if (elen >= sizeof(struct ieee80211_ht_cap))
665 elems->ht_cap_elem = (void *)pos;
666 break;
667 case WLAN_EID_HT_INFORMATION:
668 if (elen >= sizeof(struct ieee80211_ht_info))
669 elems->ht_info_elem = (void *)pos;
670 break;
671 case WLAN_EID_MESH_ID:
672 elems->mesh_id = pos;
673 elems->mesh_id_len = elen;
674 break;
675 case WLAN_EID_MESH_CONFIG:
676 if (elen >= sizeof(struct ieee80211_meshconf_ie))
677 elems->mesh_config = (void *)pos;
678 break;
679 case WLAN_EID_PEER_MGMT:
680 elems->peering = pos;
681 elems->peering_len = elen;
682 break;
683 case WLAN_EID_PREQ:
684 elems->preq = pos;
685 elems->preq_len = elen;
686 break;
687 case WLAN_EID_PREP:
688 elems->prep = pos;
689 elems->prep_len = elen;
690 break;
691 case WLAN_EID_PERR:
692 elems->perr = pos;
693 elems->perr_len = elen;
694 break;
695 case WLAN_EID_RANN:
696 if (elen >= sizeof(struct ieee80211_rann_ie))
697 elems->rann = (void *)pos;
698 break;
699 case WLAN_EID_CHANNEL_SWITCH:
700 elems->ch_switch_elem = pos;
701 elems->ch_switch_elem_len = elen;
702 break;
703 case WLAN_EID_QUIET:
704 if (!elems->quiet_elem) {
705 elems->quiet_elem = pos;
706 elems->quiet_elem_len = elen;
707 }
708 elems->num_of_quiet_elem++;
709 break;
710 case WLAN_EID_COUNTRY:
711 elems->country_elem = pos;
712 elems->country_elem_len = elen;
713 break;
714 case WLAN_EID_PWR_CONSTRAINT:
715 elems->pwr_constr_elem = pos;
716 elems->pwr_constr_elem_len = elen;
717 break;
718 case WLAN_EID_TIMEOUT_INTERVAL:
719 elems->timeout_int = pos;
720 elems->timeout_int_len = elen;
721 break;
722 default:
723 break;
724 }
725
726 left -= elen;
727 pos += elen;
728 }
729
730 return crc;
731}
732
566void ieee802_11_parse_elems(u8 *start, size_t len, 733void ieee802_11_parse_elems(u8 *start, size_t len,
567 struct ieee802_11_elems *elems) 734 struct ieee802_11_elems *elems)
568{ 735{
diff --git a/net/wireless/util.c b/net/wireless/util.c
index 2f178f73943f..a21dd3ad2b3a 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -6,7 +6,6 @@
6#include <linux/bitops.h> 6#include <linux/bitops.h>
7#include <linux/etherdevice.h> 7#include <linux/etherdevice.h>
8#include <linux/slab.h> 8#include <linux/slab.h>
9#include <linux/crc32.h>
10#include <net/cfg80211.h> 9#include <net/cfg80211.h>
11#include <net/ip.h> 10#include <net/ip.h>
12#include "core.h" 11#include "core.h"
@@ -1049,170 +1048,3 @@ int ieee80211_get_ratemask(struct ieee80211_supported_band *sband,
1049 1048
1050 return 0; 1049 return 0;
1051} 1050}
1052
1053u32 ieee802_11_parse_elems_crc(u8 *start, size_t len,
1054 struct ieee802_11_elems *elems,
1055 u64 filter, u32 crc)
1056{
1057 size_t left = len;
1058 u8 *pos = start;
1059 bool calc_crc = filter != 0;
1060
1061 memset(elems, 0, sizeof(*elems));
1062 elems->ie_start = start;
1063 elems->total_len = len;
1064
1065 while (left >= 2) {
1066 u8 id, elen;
1067
1068 id = *pos++;
1069 elen = *pos++;
1070 left -= 2;
1071
1072 if (elen > left)
1073 break;
1074
1075 if (calc_crc && id < 64 && (filter & (1ULL << id)))
1076 crc = crc32_be(crc, pos - 2, elen + 2);
1077
1078 switch (id) {
1079 case WLAN_EID_SSID:
1080 elems->ssid = pos;
1081 elems->ssid_len = elen;
1082 break;
1083 case WLAN_EID_SUPP_RATES:
1084 elems->supp_rates = pos;
1085 elems->supp_rates_len = elen;
1086 break;
1087 case WLAN_EID_FH_PARAMS:
1088 elems->fh_params = pos;
1089 elems->fh_params_len = elen;
1090 break;
1091 case WLAN_EID_DS_PARAMS:
1092 elems->ds_params = pos;
1093 elems->ds_params_len = elen;
1094 break;
1095 case WLAN_EID_CF_PARAMS:
1096 elems->cf_params = pos;
1097 elems->cf_params_len = elen;
1098 break;
1099 case WLAN_EID_TIM:
1100 if (elen >= sizeof(struct ieee80211_tim_ie)) {
1101 elems->tim = (void *)pos;
1102 elems->tim_len = elen;
1103 }
1104 break;
1105 case WLAN_EID_IBSS_PARAMS:
1106 elems->ibss_params = pos;
1107 elems->ibss_params_len = elen;
1108 break;
1109 case WLAN_EID_CHALLENGE:
1110 elems->challenge = pos;
1111 elems->challenge_len = elen;
1112 break;
1113 case WLAN_EID_VENDOR_SPECIFIC:
1114 if (elen >= 4 && pos[0] == 0x00 && pos[1] == 0x50 &&
1115 pos[2] == 0xf2) {
1116 /* Microsoft OUI (00:50:F2) */
1117
1118 if (calc_crc)
1119 crc = crc32_be(crc, pos - 2, elen + 2);
1120
1121 if (pos[3] == 1) {
1122 /* OUI Type 1 - WPA IE */
1123 elems->wpa = pos;
1124 elems->wpa_len = elen;
1125 } else if (elen >= 5 && pos[3] == 2) {
1126 /* OUI Type 2 - WMM IE */
1127 if (pos[4] == 0) {
1128 elems->wmm_info = pos;
1129 elems->wmm_info_len = elen;
1130 } else if (pos[4] == 1) {
1131 elems->wmm_param = pos;
1132 elems->wmm_param_len = elen;
1133 }
1134 }
1135 }
1136 break;
1137 case WLAN_EID_RSN:
1138 elems->rsn = pos;
1139 elems->rsn_len = elen;
1140 break;
1141 case WLAN_EID_ERP_INFO:
1142 elems->erp_info = pos;
1143 elems->erp_info_len = elen;
1144 break;
1145 case WLAN_EID_EXT_SUPP_RATES:
1146 elems->ext_supp_rates = pos;
1147 elems->ext_supp_rates_len = elen;
1148 break;
1149 case WLAN_EID_HT_CAPABILITY:
1150 if (elen >= sizeof(struct ieee80211_ht_cap))
1151 elems->ht_cap_elem = (void *)pos;
1152 break;
1153 case WLAN_EID_HT_INFORMATION:
1154 if (elen >= sizeof(struct ieee80211_ht_info))
1155 elems->ht_info_elem = (void *)pos;
1156 break;
1157 case WLAN_EID_MESH_ID:
1158 elems->mesh_id = pos;
1159 elems->mesh_id_len = elen;
1160 break;
1161 case WLAN_EID_MESH_CONFIG:
1162 if (elen >= sizeof(struct ieee80211_meshconf_ie))
1163 elems->mesh_config = (void *)pos;
1164 break;
1165 case WLAN_EID_PEER_MGMT:
1166 elems->peering = pos;
1167 elems->peering_len = elen;
1168 break;
1169 case WLAN_EID_PREQ:
1170 elems->preq = pos;
1171 elems->preq_len = elen;
1172 break;
1173 case WLAN_EID_PREP:
1174 elems->prep = pos;
1175 elems->prep_len = elen;
1176 break;
1177 case WLAN_EID_PERR:
1178 elems->perr = pos;
1179 elems->perr_len = elen;
1180 break;
1181 case WLAN_EID_RANN:
1182 if (elen >= sizeof(struct ieee80211_rann_ie))
1183 elems->rann = (void *)pos;
1184 break;
1185 case WLAN_EID_CHANNEL_SWITCH:
1186 elems->ch_switch_elem = pos;
1187 elems->ch_switch_elem_len = elen;
1188 break;
1189 case WLAN_EID_QUIET:
1190 if (!elems->quiet_elem) {
1191 elems->quiet_elem = pos;
1192 elems->quiet_elem_len = elen;
1193 }
1194 elems->num_of_quiet_elem++;
1195 break;
1196 case WLAN_EID_COUNTRY:
1197 elems->country_elem = pos;
1198 elems->country_elem_len = elen;
1199 break;
1200 case WLAN_EID_PWR_CONSTRAINT:
1201 elems->pwr_constr_elem = pos;
1202 elems->pwr_constr_elem_len = elen;
1203 break;
1204 case WLAN_EID_TIMEOUT_INTERVAL:
1205 elems->timeout_int = pos;
1206 elems->timeout_int_len = elen;
1207 break;
1208 default:
1209 break;
1210 }
1211
1212 left -= elen;
1213 pos += elen;
1214 }
1215
1216 return crc;
1217}
1218EXPORT_SYMBOL(ieee802_11_parse_elems_crc);