diff options
Diffstat (limited to 'net/wireless/util.c')
-rw-r--r-- | net/wireless/util.c | 99 |
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 | } |
981 | EXPORT_SYMBOL(cfg80211_calculate_bitrate); | 981 | EXPORT_SYMBOL(cfg80211_calculate_bitrate); |
982 | 982 | ||
983 | unsigned 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 | } | ||
1080 | EXPORT_SYMBOL(cfg80211_get_p2p_attr); | ||
1081 | |||
983 | int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev, | 1082 | int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev, |
984 | u32 beacon_int) | 1083 | u32 beacon_int) |
985 | { | 1084 | { |