diff options
-rw-r--r-- | include/net/cfg80211.h | 63 | ||||
-rw-r--r-- | net/mac80211/ieee80211_i.h | 63 | ||||
-rw-r--r-- | net/mac80211/util.c | 167 | ||||
-rw-r--r-- | net/wireless/util.c | 168 |
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( | |||
2391 | extern const unsigned char rfc1042_header[6]; | 2391 | extern const unsigned char rfc1042_header[6]; |
2392 | extern const unsigned char bridge_tunnel_header[6]; | 2392 | extern const unsigned char bridge_tunnel_header[6]; |
2393 | 2393 | ||
2394 | /* Parsed Information Elements */ | ||
2395 | struct 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 */ | ||
1044 | struct 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 | |||
1043 | static inline struct ieee80211_local *hw_to_local( | 1106 | static 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 | } |
564 | EXPORT_SYMBOL(ieee80211_queue_delayed_work); | 565 | EXPORT_SYMBOL(ieee80211_queue_delayed_work); |
565 | 566 | ||
567 | u32 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 | |||
566 | void ieee802_11_parse_elems(u8 *start, size_t len, | 733 | void 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 | |||
1053 | u32 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 | } | ||
1218 | EXPORT_SYMBOL(ieee802_11_parse_elems_crc); | ||