aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2012-10-29 14:48:40 -0400
committerJohannes Berg <johannes.berg@intel.com>2012-11-06 07:24:52 -0500
commit0ee453552f0b1ea87f6f50a077b0ed9d9ac7d6ac (patch)
treecd0940bf0378b56494a7d41d56d10c8e2209021f /net/wireless
parent37c73b5f323c973c1db6857494a6685260440be1 (diff)
wireless: add utility function to get P2P attribute
Parsing the P2P attributes can be tricky as their contents can be split across multiple (vendor) IEs. Thus, it's not possible to parse them like IEs (by returning a pointer to the data.) Instead, provide a function that copies the attribute data into a caller-provided buffer and returns the size needed (useful in case the buffer was too small.) Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/wireless')
-rw-r--r--net/wireless/util.c99
1 files changed, 99 insertions, 0 deletions
diff --git a/net/wireless/util.c b/net/wireless/util.c
index 5b6c1df72f31..b99f01cda1f6 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -980,6 +980,105 @@ u32 cfg80211_calculate_bitrate(struct rate_info *rate)
980} 980}
981EXPORT_SYMBOL(cfg80211_calculate_bitrate); 981EXPORT_SYMBOL(cfg80211_calculate_bitrate);
982 982
983unsigned int cfg80211_get_p2p_attr(const u8 *ies, unsigned int len,
984 u8 attr, u8 *buf, unsigned int bufsize)
985{
986 u8 *out = buf;
987 u16 attr_remaining = 0;
988 bool desired_attr = false;
989 u16 desired_len = 0;
990
991 while (len > 0) {
992 unsigned int iedatalen;
993 unsigned int copy;
994 const u8 *iedata;
995
996 if (len < 2)
997 return -EILSEQ;
998 iedatalen = ies[1];
999 if (iedatalen + 2 > len)
1000 return -EILSEQ;
1001
1002 if (ies[0] != WLAN_EID_VENDOR_SPECIFIC)
1003 goto cont;
1004
1005 if (iedatalen < 4)
1006 goto cont;
1007
1008 iedata = ies + 2;
1009
1010 /* check WFA OUI, P2P subtype */
1011 if (iedata[0] != 0x50 || iedata[1] != 0x6f ||
1012 iedata[2] != 0x9a || iedata[3] != 0x09)
1013 goto cont;
1014
1015 iedatalen -= 4;
1016 iedata += 4;
1017
1018 /* check attribute continuation into this IE */
1019 copy = min_t(unsigned int, attr_remaining, iedatalen);
1020 if (copy && desired_attr) {
1021 desired_len += copy;
1022 if (out) {
1023 memcpy(out, iedata, min(bufsize, copy));
1024 out += min(bufsize, copy);
1025 bufsize -= min(bufsize, copy);
1026 }
1027
1028
1029 if (copy == attr_remaining)
1030 return desired_len;
1031 }
1032
1033 attr_remaining -= copy;
1034 if (attr_remaining)
1035 goto cont;
1036
1037 iedatalen -= copy;
1038 iedata += copy;
1039
1040 while (iedatalen > 0) {
1041 u16 attr_len;
1042
1043 /* P2P attribute ID & size must fit */
1044 if (iedatalen < 3)
1045 return -EILSEQ;
1046 desired_attr = iedata[0] == attr;
1047 attr_len = get_unaligned_le16(iedata + 1);
1048 iedatalen -= 3;
1049 iedata += 3;
1050
1051 copy = min_t(unsigned int, attr_len, iedatalen);
1052
1053 if (desired_attr) {
1054 desired_len += copy;
1055 if (out) {
1056 memcpy(out, iedata, min(bufsize, copy));
1057 out += min(bufsize, copy);
1058 bufsize -= min(bufsize, copy);
1059 }
1060
1061 if (copy == attr_len)
1062 return desired_len;
1063 }
1064
1065 iedata += copy;
1066 iedatalen -= copy;
1067 attr_remaining = attr_len - copy;
1068 }
1069
1070 cont:
1071 len -= ies[1] + 2;
1072 ies += ies[1] + 2;
1073 }
1074
1075 if (attr_remaining && desired_attr)
1076 return -EILSEQ;
1077
1078 return -ENOENT;
1079}
1080EXPORT_SYMBOL(cfg80211_get_p2p_attr);
1081
983int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev, 1082int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev,
984 u32 beacon_int) 1083 u32 beacon_int)
985{ 1084{