aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorYogesh Ashok Powar <yogeshp@marvell.com>2011-08-09 21:02:26 -0400
committerJohn W. Linville <linville@tuxdriver.com>2011-08-12 13:45:03 -0400
commit0879fa44b54101c9955123582018cb511047a2b6 (patch)
tree0a9c1f5fc10a3b320d0db793598822a43b2dc719 /net
parentf3d4505de539f754b78d5c30e5d2cb41a0ed0117 (diff)
cfg80211/mac80211: move information element parsing logic to cfg80211
Moving the parsing logic for retrieving the information elements stored in management frames, e.g. beacons or probe responses, and making it available to other cfg80211 drivers. Signed-off-by: Yogesh Ashok Powar <yogeshp@marvell.com> Signed-off-by: Amitkumar Karwar <akarwar@marvell.com> Signed-off-by: Bing Zhao <bzhao@marvell.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net')
-rw-r--r--net/mac80211/ieee80211_i.h63
-rw-r--r--net/mac80211/util.c167
-rw-r--r--net/wireless/util.c168
3 files changed, 168 insertions, 230 deletions
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 286ac5dbeeea..ea7419050846 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -1021,69 +1021,6 @@ struct ieee80211_ra_tid {
1021 u16 tid; 1021 u16 tid;
1022}; 1022};
1023 1023
1024/* Parsed Information Elements */
1025struct ieee802_11_elems {
1026 u8 *ie_start;
1027 size_t total_len;
1028
1029 /* pointers to IEs */
1030 u8 *ssid;
1031 u8 *supp_rates;
1032 u8 *fh_params;
1033 u8 *ds_params;
1034 u8 *cf_params;
1035 struct ieee80211_tim_ie *tim;
1036 u8 *ibss_params;
1037 u8 *challenge;
1038 u8 *wpa;
1039 u8 *rsn;
1040 u8 *erp_info;
1041 u8 *ext_supp_rates;
1042 u8 *wmm_info;
1043 u8 *wmm_param;
1044 struct ieee80211_ht_cap *ht_cap_elem;
1045 struct ieee80211_ht_info *ht_info_elem;
1046 struct ieee80211_meshconf_ie *mesh_config;
1047 u8 *mesh_id;
1048 u8 *peer_link;
1049 u8 *preq;
1050 u8 *prep;
1051 u8 *perr;
1052 struct ieee80211_rann_ie *rann;
1053 u8 *ch_switch_elem;
1054 u8 *country_elem;
1055 u8 *pwr_constr_elem;
1056 u8 *quiet_elem; /* first quite element */
1057 u8 *timeout_int;
1058
1059 /* length of them, respectively */
1060 u8 ssid_len;
1061 u8 supp_rates_len;
1062 u8 fh_params_len;
1063 u8 ds_params_len;
1064 u8 cf_params_len;
1065 u8 tim_len;
1066 u8 ibss_params_len;
1067 u8 challenge_len;
1068 u8 wpa_len;
1069 u8 rsn_len;
1070 u8 erp_info_len;
1071 u8 ext_supp_rates_len;
1072 u8 wmm_info_len;
1073 u8 wmm_param_len;
1074 u8 mesh_id_len;
1075 u8 peer_link_len;
1076 u8 preq_len;
1077 u8 prep_len;
1078 u8 perr_len;
1079 u8 ch_switch_elem_len;
1080 u8 country_elem_len;
1081 u8 pwr_constr_elem_len;
1082 u8 quiet_elem_len;
1083 u8 num_of_quiet_elem; /* can be more the one */
1084 u8 timeout_int_len;
1085};
1086
1087static inline struct ieee80211_local *hw_to_local( 1024static inline struct ieee80211_local *hw_to_local(
1088 struct ieee80211_hw *hw) 1025 struct ieee80211_hw *hw)
1089{ 1026{
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 7a0e351a510e..ce916ff6ef08 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -19,7 +19,6 @@
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>
23#include <net/net_namespace.h> 22#include <net/net_namespace.h>
24#include <net/cfg80211.h> 23#include <net/cfg80211.h>
25#include <net/rtnetlink.h> 24#include <net/rtnetlink.h>
@@ -573,172 +572,6 @@ void ieee802_11_parse_elems(u8 *start, size_t len,
573 ieee802_11_parse_elems_crc(start, len, elems, 0, 0); 572 ieee802_11_parse_elems_crc(start, len, elems, 0, 0);
574} 573}
575 574
576u32 ieee802_11_parse_elems_crc(u8 *start, size_t len,
577 struct ieee802_11_elems *elems,
578 u64 filter, u32 crc)
579{
580 size_t left = len;
581 u8 *pos = start;
582 bool calc_crc = filter != 0;
583
584 memset(elems, 0, sizeof(*elems));
585 elems->ie_start = start;
586 elems->total_len = len;
587
588 while (left >= 2) {
589 u8 id, elen;
590
591 id = *pos++;
592 elen = *pos++;
593 left -= 2;
594
595 if (elen > left)
596 break;
597
598 if (calc_crc && id < 64 && (filter & (1ULL << id)))
599 crc = crc32_be(crc, pos - 2, elen + 2);
600
601 switch (id) {
602 case WLAN_EID_SSID:
603 elems->ssid = pos;
604 elems->ssid_len = elen;
605 break;
606 case WLAN_EID_SUPP_RATES:
607 elems->supp_rates = pos;
608 elems->supp_rates_len = elen;
609 break;
610 case WLAN_EID_FH_PARAMS:
611 elems->fh_params = pos;
612 elems->fh_params_len = elen;
613 break;
614 case WLAN_EID_DS_PARAMS:
615 elems->ds_params = pos;
616 elems->ds_params_len = elen;
617 break;
618 case WLAN_EID_CF_PARAMS:
619 elems->cf_params = pos;
620 elems->cf_params_len = elen;
621 break;
622 case WLAN_EID_TIM:
623 if (elen >= sizeof(struct ieee80211_tim_ie)) {
624 elems->tim = (void *)pos;
625 elems->tim_len = elen;
626 }
627 break;
628 case WLAN_EID_IBSS_PARAMS:
629 elems->ibss_params = pos;
630 elems->ibss_params_len = elen;
631 break;
632 case WLAN_EID_CHALLENGE:
633 elems->challenge = pos;
634 elems->challenge_len = elen;
635 break;
636 case WLAN_EID_VENDOR_SPECIFIC:
637 if (elen >= 4 && pos[0] == 0x00 && pos[1] == 0x50 &&
638 pos[2] == 0xf2) {
639 /* Microsoft OUI (00:50:F2) */
640
641 if (calc_crc)
642 crc = crc32_be(crc, pos - 2, elen + 2);
643
644 if (pos[3] == 1) {
645 /* OUI Type 1 - WPA IE */
646 elems->wpa = pos;
647 elems->wpa_len = elen;
648 } else if (elen >= 5 && pos[3] == 2) {
649 /* OUI Type 2 - WMM IE */
650 if (pos[4] == 0) {
651 elems->wmm_info = pos;
652 elems->wmm_info_len = elen;
653 } else if (pos[4] == 1) {
654 elems->wmm_param = pos;
655 elems->wmm_param_len = elen;
656 }
657 }
658 }
659 break;
660 case WLAN_EID_RSN:
661 elems->rsn = pos;
662 elems->rsn_len = elen;
663 break;
664 case WLAN_EID_ERP_INFO:
665 elems->erp_info = pos;
666 elems->erp_info_len = elen;
667 break;
668 case WLAN_EID_EXT_SUPP_RATES:
669 elems->ext_supp_rates = pos;
670 elems->ext_supp_rates_len = elen;
671 break;
672 case WLAN_EID_HT_CAPABILITY:
673 if (elen >= sizeof(struct ieee80211_ht_cap))
674 elems->ht_cap_elem = (void *)pos;
675 break;
676 case WLAN_EID_HT_INFORMATION:
677 if (elen >= sizeof(struct ieee80211_ht_info))
678 elems->ht_info_elem = (void *)pos;
679 break;
680 case WLAN_EID_MESH_ID:
681 elems->mesh_id = pos;
682 elems->mesh_id_len = elen;
683 break;
684 case WLAN_EID_MESH_CONFIG:
685 if (elen >= sizeof(struct ieee80211_meshconf_ie))
686 elems->mesh_config = (void *)pos;
687 break;
688 case WLAN_EID_PEER_LINK:
689 elems->peer_link = pos;
690 elems->peer_link_len = elen;
691 break;
692 case WLAN_EID_PREQ:
693 elems->preq = pos;
694 elems->preq_len = elen;
695 break;
696 case WLAN_EID_PREP:
697 elems->prep = pos;
698 elems->prep_len = elen;
699 break;
700 case WLAN_EID_PERR:
701 elems->perr = pos;
702 elems->perr_len = elen;
703 break;
704 case WLAN_EID_RANN:
705 if (elen >= sizeof(struct ieee80211_rann_ie))
706 elems->rann = (void *)pos;
707 break;
708 case WLAN_EID_CHANNEL_SWITCH:
709 elems->ch_switch_elem = pos;
710 elems->ch_switch_elem_len = elen;
711 break;
712 case WLAN_EID_QUIET:
713 if (!elems->quiet_elem) {
714 elems->quiet_elem = pos;
715 elems->quiet_elem_len = elen;
716 }
717 elems->num_of_quiet_elem++;
718 break;
719 case WLAN_EID_COUNTRY:
720 elems->country_elem = pos;
721 elems->country_elem_len = elen;
722 break;
723 case WLAN_EID_PWR_CONSTRAINT:
724 elems->pwr_constr_elem = pos;
725 elems->pwr_constr_elem_len = elen;
726 break;
727 case WLAN_EID_TIMEOUT_INTERVAL:
728 elems->timeout_int = pos;
729 elems->timeout_int_len = elen;
730 break;
731 default:
732 break;
733 }
734
735 left -= elen;
736 pos += elen;
737 }
738
739 return crc;
740}
741
742void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata) 575void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata)
743{ 576{
744 struct ieee80211_local *local = sdata->local; 577 struct ieee80211_local *local = sdata->local;
diff --git a/net/wireless/util.c b/net/wireless/util.c
index be75a3a0424e..844ddb0aa653 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -6,6 +6,7 @@
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>
9#include <net/cfg80211.h> 10#include <net/cfg80211.h>
10#include <net/ip.h> 11#include <net/ip.h>
11#include "core.h" 12#include "core.h"
@@ -1044,3 +1045,170 @@ int ieee80211_get_ratemask(struct ieee80211_supported_band *sband,
1044 1045
1045 return 0; 1046 return 0;
1046} 1047}
1048
1049u32 ieee802_11_parse_elems_crc(u8 *start, size_t len,
1050 struct ieee802_11_elems *elems,
1051 u64 filter, u32 crc)
1052{
1053 size_t left = len;
1054 u8 *pos = start;
1055 bool calc_crc = filter != 0;
1056
1057 memset(elems, 0, sizeof(*elems));
1058 elems->ie_start = start;
1059 elems->total_len = len;
1060
1061 while (left >= 2) {
1062 u8 id, elen;
1063
1064 id = *pos++;
1065 elen = *pos++;
1066 left -= 2;
1067
1068 if (elen > left)
1069 break;
1070
1071 if (calc_crc && id < 64 && (filter & (1ULL << id)))
1072 crc = crc32_be(crc, pos - 2, elen + 2);
1073
1074 switch (id) {
1075 case WLAN_EID_SSID:
1076 elems->ssid = pos;
1077 elems->ssid_len = elen;
1078 break;
1079 case WLAN_EID_SUPP_RATES:
1080 elems->supp_rates = pos;
1081 elems->supp_rates_len = elen;
1082 break;
1083 case WLAN_EID_FH_PARAMS:
1084 elems->fh_params = pos;
1085 elems->fh_params_len = elen;
1086 break;
1087 case WLAN_EID_DS_PARAMS:
1088 elems->ds_params = pos;
1089 elems->ds_params_len = elen;
1090 break;
1091 case WLAN_EID_CF_PARAMS:
1092 elems->cf_params = pos;
1093 elems->cf_params_len = elen;
1094 break;
1095 case WLAN_EID_TIM:
1096 if (elen >= sizeof(struct ieee80211_tim_ie)) {
1097 elems->tim = (void *)pos;
1098 elems->tim_len = elen;
1099 }
1100 break;
1101 case WLAN_EID_IBSS_PARAMS:
1102 elems->ibss_params = pos;
1103 elems->ibss_params_len = elen;
1104 break;
1105 case WLAN_EID_CHALLENGE:
1106 elems->challenge = pos;
1107 elems->challenge_len = elen;
1108 break;
1109 case WLAN_EID_VENDOR_SPECIFIC:
1110 if (elen >= 4 && pos[0] == 0x00 && pos[1] == 0x50 &&
1111 pos[2] == 0xf2) {
1112 /* Microsoft OUI (00:50:F2) */
1113
1114 if (calc_crc)
1115 crc = crc32_be(crc, pos - 2, elen + 2);
1116
1117 if (pos[3] == 1) {
1118 /* OUI Type 1 - WPA IE */
1119 elems->wpa = pos;
1120 elems->wpa_len = elen;
1121 } else if (elen >= 5 && pos[3] == 2) {
1122 /* OUI Type 2 - WMM IE */
1123 if (pos[4] == 0) {
1124 elems->wmm_info = pos;
1125 elems->wmm_info_len = elen;
1126 } else if (pos[4] == 1) {
1127 elems->wmm_param = pos;
1128 elems->wmm_param_len = elen;
1129 }
1130 }
1131 }
1132 break;
1133 case WLAN_EID_RSN:
1134 elems->rsn = pos;
1135 elems->rsn_len = elen;
1136 break;
1137 case WLAN_EID_ERP_INFO:
1138 elems->erp_info = pos;
1139 elems->erp_info_len = elen;
1140 break;
1141 case WLAN_EID_EXT_SUPP_RATES:
1142 elems->ext_supp_rates = pos;
1143 elems->ext_supp_rates_len = elen;
1144 break;
1145 case WLAN_EID_HT_CAPABILITY:
1146 if (elen >= sizeof(struct ieee80211_ht_cap))
1147 elems->ht_cap_elem = (void *)pos;
1148 break;
1149 case WLAN_EID_HT_INFORMATION:
1150 if (elen >= sizeof(struct ieee80211_ht_info))
1151 elems->ht_info_elem = (void *)pos;
1152 break;
1153 case WLAN_EID_MESH_ID:
1154 elems->mesh_id = pos;
1155 elems->mesh_id_len = elen;
1156 break;
1157 case WLAN_EID_MESH_CONFIG:
1158 if (elen >= sizeof(struct ieee80211_meshconf_ie))
1159 elems->mesh_config = (void *)pos;
1160 break;
1161 case WLAN_EID_PEER_LINK:
1162 elems->peer_link = pos;
1163 elems->peer_link_len = elen;
1164 break;
1165 case WLAN_EID_PREQ:
1166 elems->preq = pos;
1167 elems->preq_len = elen;
1168 break;
1169 case WLAN_EID_PREP:
1170 elems->prep = pos;
1171 elems->prep_len = elen;
1172 break;
1173 case WLAN_EID_PERR:
1174 elems->perr = pos;
1175 elems->perr_len = elen;
1176 break;
1177 case WLAN_EID_RANN:
1178 if (elen >= sizeof(struct ieee80211_rann_ie))
1179 elems->rann = (void *)pos;
1180 break;
1181 case WLAN_EID_CHANNEL_SWITCH:
1182 elems->ch_switch_elem = pos;
1183 elems->ch_switch_elem_len = elen;
1184 break;
1185 case WLAN_EID_QUIET:
1186 if (!elems->quiet_elem) {
1187 elems->quiet_elem = pos;
1188 elems->quiet_elem_len = elen;
1189 }
1190 elems->num_of_quiet_elem++;
1191 break;
1192 case WLAN_EID_COUNTRY:
1193 elems->country_elem = pos;
1194 elems->country_elem_len = elen;
1195 break;
1196 case WLAN_EID_PWR_CONSTRAINT:
1197 elems->pwr_constr_elem = pos;
1198 elems->pwr_constr_elem_len = elen;
1199 break;
1200 case WLAN_EID_TIMEOUT_INTERVAL:
1201 elems->timeout_int = pos;
1202 elems->timeout_int_len = elen;
1203 break;
1204 default:
1205 break;
1206 }
1207
1208 left -= elen;
1209 pos += elen;
1210 }
1211
1212 return crc;
1213}
1214EXPORT_SYMBOL(ieee802_11_parse_elems_crc);