aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless/nl80211.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2013-02-14 10:19:38 -0500
committerJohannes Berg <johannes.berg@intel.com>2013-03-06 10:35:42 -0500
commit3713b4e364effef4b170c97d54528b1cdb16aa6b (patch)
tree1fb304fe4b02d44f0958e0931108bd1537ea1643 /net/wireless/nl80211.c
parent191922cd4bfda551205c3a2dfe5b33287e8326ab (diff)
nl80211: allow splitting wiphy information in dumps
The per-wiphy information is getting large, to the point where with more than the typical number of channels it's too large and overflows, and userspace can't get any of the information at all. To address this (in a way that doesn't require making all messages bigger) allow userspace to specify that it can deal with wiphy information split across multiple parts of the dump, and if it can split up the data. This also splits up each channel separately so an arbitrary number of channels can be supported. Additionally, since GET_WIPHY has the same problem, add support for filtering the wiphy dump and get information for a single wiphy only, this allows userspace apps to use dump in this case to retrieve all data from a single device. As userspace needs to know if all this this is supported, add a global nl80211 feature set and include a bit for this behaviour in it. Cc: Dennis H Jensen <dennis.h.jensen@siemens.com> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/wireless/nl80211.c')
-rw-r--r--net/wireless/nl80211.c933
1 files changed, 571 insertions, 362 deletions
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 83151a50e5ad..f187a920ec71 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -370,6 +370,7 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = {
370 [NL80211_ATTR_MAC_ADDRS] = { .type = NLA_NESTED }, 370 [NL80211_ATTR_MAC_ADDRS] = { .type = NLA_NESTED },
371 [NL80211_ATTR_STA_CAPABILITY] = { .type = NLA_U16 }, 371 [NL80211_ATTR_STA_CAPABILITY] = { .type = NLA_U16 },
372 [NL80211_ATTR_STA_EXT_CAPABILITY] = { .type = NLA_BINARY, }, 372 [NL80211_ATTR_STA_EXT_CAPABILITY] = { .type = NLA_BINARY, },
373 [NL80211_ATTR_SPLIT_WIPHY_DUMP] = { .type = NLA_FLAG, },
373}; 374};
374 375
375/* policy for the key attributes */ 376/* policy for the key attributes */
@@ -892,412 +893,545 @@ nla_put_failure:
892 return -ENOBUFS; 893 return -ENOBUFS;
893} 894}
894 895
895static int nl80211_send_wiphy(struct sk_buff *msg, u32 portid, u32 seq, int flags, 896#ifdef CONFIG_PM
896 struct cfg80211_registered_device *dev) 897static int nl80211_send_wowlan(struct sk_buff *msg,
898 struct cfg80211_registered_device *dev)
897{ 899{
898 void *hdr; 900 struct nlattr *nl_wowlan;
899 struct nlattr *nl_bands, *nl_band;
900 struct nlattr *nl_freqs, *nl_freq;
901 struct nlattr *nl_rates, *nl_rate;
902 struct nlattr *nl_cmds;
903 enum ieee80211_band band;
904 struct ieee80211_channel *chan;
905 struct ieee80211_rate *rate;
906 int i;
907 const struct ieee80211_txrx_stypes *mgmt_stypes =
908 dev->wiphy.mgmt_stypes;
909 901
910 hdr = nl80211hdr_put(msg, portid, seq, flags, NL80211_CMD_NEW_WIPHY); 902 if (!dev->wiphy.wowlan.flags && !dev->wiphy.wowlan.n_patterns)
911 if (!hdr) 903 return 0;
912 return -1;
913 904
914 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, dev->wiphy_idx) || 905 nl_wowlan = nla_nest_start(msg, NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED);
915 nla_put_string(msg, NL80211_ATTR_WIPHY_NAME, wiphy_name(&dev->wiphy)) || 906 if (!nl_wowlan)
916 nla_put_u32(msg, NL80211_ATTR_GENERATION, 907 return -ENOBUFS;
917 cfg80211_rdev_list_generation) ||
918 nla_put_u8(msg, NL80211_ATTR_WIPHY_RETRY_SHORT,
919 dev->wiphy.retry_short) ||
920 nla_put_u8(msg, NL80211_ATTR_WIPHY_RETRY_LONG,
921 dev->wiphy.retry_long) ||
922 nla_put_u32(msg, NL80211_ATTR_WIPHY_FRAG_THRESHOLD,
923 dev->wiphy.frag_threshold) ||
924 nla_put_u32(msg, NL80211_ATTR_WIPHY_RTS_THRESHOLD,
925 dev->wiphy.rts_threshold) ||
926 nla_put_u8(msg, NL80211_ATTR_WIPHY_COVERAGE_CLASS,
927 dev->wiphy.coverage_class) ||
928 nla_put_u8(msg, NL80211_ATTR_MAX_NUM_SCAN_SSIDS,
929 dev->wiphy.max_scan_ssids) ||
930 nla_put_u8(msg, NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS,
931 dev->wiphy.max_sched_scan_ssids) ||
932 nla_put_u16(msg, NL80211_ATTR_MAX_SCAN_IE_LEN,
933 dev->wiphy.max_scan_ie_len) ||
934 nla_put_u16(msg, NL80211_ATTR_MAX_SCHED_SCAN_IE_LEN,
935 dev->wiphy.max_sched_scan_ie_len) ||
936 nla_put_u8(msg, NL80211_ATTR_MAX_MATCH_SETS,
937 dev->wiphy.max_match_sets))
938 goto nla_put_failure;
939 908
940 if ((dev->wiphy.flags & WIPHY_FLAG_IBSS_RSN) && 909 if (((dev->wiphy.wowlan.flags & WIPHY_WOWLAN_ANY) &&
941 nla_put_flag(msg, NL80211_ATTR_SUPPORT_IBSS_RSN)) 910 nla_put_flag(msg, NL80211_WOWLAN_TRIG_ANY)) ||
942 goto nla_put_failure; 911 ((dev->wiphy.wowlan.flags & WIPHY_WOWLAN_DISCONNECT) &&
943 if ((dev->wiphy.flags & WIPHY_FLAG_MESH_AUTH) && 912 nla_put_flag(msg, NL80211_WOWLAN_TRIG_DISCONNECT)) ||
944 nla_put_flag(msg, NL80211_ATTR_SUPPORT_MESH_AUTH)) 913 ((dev->wiphy.wowlan.flags & WIPHY_WOWLAN_MAGIC_PKT) &&
945 goto nla_put_failure; 914 nla_put_flag(msg, NL80211_WOWLAN_TRIG_MAGIC_PKT)) ||
946 if ((dev->wiphy.flags & WIPHY_FLAG_AP_UAPSD) && 915 ((dev->wiphy.wowlan.flags & WIPHY_WOWLAN_SUPPORTS_GTK_REKEY) &&
947 nla_put_flag(msg, NL80211_ATTR_SUPPORT_AP_UAPSD)) 916 nla_put_flag(msg, NL80211_WOWLAN_TRIG_GTK_REKEY_SUPPORTED)) ||
948 goto nla_put_failure; 917 ((dev->wiphy.wowlan.flags & WIPHY_WOWLAN_GTK_REKEY_FAILURE) &&
949 if ((dev->wiphy.flags & WIPHY_FLAG_SUPPORTS_FW_ROAM) && 918 nla_put_flag(msg, NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE)) ||
950 nla_put_flag(msg, NL80211_ATTR_ROAM_SUPPORT)) 919 ((dev->wiphy.wowlan.flags & WIPHY_WOWLAN_EAP_IDENTITY_REQ) &&
951 goto nla_put_failure; 920 nla_put_flag(msg, NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST)) ||
952 if ((dev->wiphy.flags & WIPHY_FLAG_SUPPORTS_TDLS) && 921 ((dev->wiphy.wowlan.flags & WIPHY_WOWLAN_4WAY_HANDSHAKE) &&
953 nla_put_flag(msg, NL80211_ATTR_TDLS_SUPPORT)) 922 nla_put_flag(msg, NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE)) ||
954 goto nla_put_failure; 923 ((dev->wiphy.wowlan.flags & WIPHY_WOWLAN_RFKILL_RELEASE) &&
955 if ((dev->wiphy.flags & WIPHY_FLAG_TDLS_EXTERNAL_SETUP) && 924 nla_put_flag(msg, NL80211_WOWLAN_TRIG_RFKILL_RELEASE)))
956 nla_put_flag(msg, NL80211_ATTR_TDLS_EXTERNAL_SETUP)) 925 return -ENOBUFS;
957 goto nla_put_failure;
958 926
959 if (nla_put(msg, NL80211_ATTR_CIPHER_SUITES, 927 if (dev->wiphy.wowlan.n_patterns) {
960 sizeof(u32) * dev->wiphy.n_cipher_suites, 928 struct nl80211_wowlan_pattern_support pat = {
961 dev->wiphy.cipher_suites)) 929 .max_patterns = dev->wiphy.wowlan.n_patterns,
962 goto nla_put_failure; 930 .min_pattern_len = dev->wiphy.wowlan.pattern_min_len,
931 .max_pattern_len = dev->wiphy.wowlan.pattern_max_len,
932 .max_pkt_offset = dev->wiphy.wowlan.max_pkt_offset,
933 };
963 934
964 if (nla_put_u8(msg, NL80211_ATTR_MAX_NUM_PMKIDS, 935 if (nla_put(msg, NL80211_WOWLAN_TRIG_PKT_PATTERN,
965 dev->wiphy.max_num_pmkids)) 936 sizeof(pat), &pat))
966 goto nla_put_failure; 937 return -ENOBUFS;
938 }
967 939
968 if ((dev->wiphy.flags & WIPHY_FLAG_CONTROL_PORT_PROTOCOL) && 940 nla_nest_end(msg, nl_wowlan);
969 nla_put_flag(msg, NL80211_ATTR_CONTROL_PORT_ETHERTYPE))
970 goto nla_put_failure;
971 941
972 if (nla_put_u32(msg, NL80211_ATTR_WIPHY_ANTENNA_AVAIL_TX, 942 return 0;
973 dev->wiphy.available_antennas_tx) || 943}
974 nla_put_u32(msg, NL80211_ATTR_WIPHY_ANTENNA_AVAIL_RX, 944#endif
975 dev->wiphy.available_antennas_rx))
976 goto nla_put_failure;
977 945
978 if ((dev->wiphy.flags & WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD) && 946static int nl80211_send_band_rateinfo(struct sk_buff *msg,
979 nla_put_u32(msg, NL80211_ATTR_PROBE_RESP_OFFLOAD, 947 struct ieee80211_supported_band *sband)
980 dev->wiphy.probe_resp_offload)) 948{
981 goto nla_put_failure; 949 struct nlattr *nl_rates, *nl_rate;
950 struct ieee80211_rate *rate;
951 int i;
982 952
983 if ((dev->wiphy.available_antennas_tx || 953 /* add HT info */
984 dev->wiphy.available_antennas_rx) && dev->ops->get_antenna) { 954 if (sband->ht_cap.ht_supported &&
985 u32 tx_ant = 0, rx_ant = 0; 955 (nla_put(msg, NL80211_BAND_ATTR_HT_MCS_SET,
986 int res; 956 sizeof(sband->ht_cap.mcs),
987 res = rdev_get_antenna(dev, &tx_ant, &rx_ant); 957 &sband->ht_cap.mcs) ||
988 if (!res) { 958 nla_put_u16(msg, NL80211_BAND_ATTR_HT_CAPA,
989 if (nla_put_u32(msg, NL80211_ATTR_WIPHY_ANTENNA_TX, 959 sband->ht_cap.cap) ||
990 tx_ant) || 960 nla_put_u8(msg, NL80211_BAND_ATTR_HT_AMPDU_FACTOR,
991 nla_put_u32(msg, NL80211_ATTR_WIPHY_ANTENNA_RX, 961 sband->ht_cap.ampdu_factor) ||
992 rx_ant)) 962 nla_put_u8(msg, NL80211_BAND_ATTR_HT_AMPDU_DENSITY,
993 goto nla_put_failure; 963 sband->ht_cap.ampdu_density)))
994 } 964 return -ENOBUFS;
995 }
996 965
997 if (nl80211_put_iftypes(msg, NL80211_ATTR_SUPPORTED_IFTYPES, 966 /* add VHT info */
998 dev->wiphy.interface_modes)) 967 if (sband->vht_cap.vht_supported &&
999 goto nla_put_failure; 968 (nla_put(msg, NL80211_BAND_ATTR_VHT_MCS_SET,
969 sizeof(sband->vht_cap.vht_mcs),
970 &sband->vht_cap.vht_mcs) ||
971 nla_put_u32(msg, NL80211_BAND_ATTR_VHT_CAPA,
972 sband->vht_cap.cap)))
973 return -ENOBUFS;
1000 974
1001 nl_bands = nla_nest_start(msg, NL80211_ATTR_WIPHY_BANDS); 975 /* add bitrates */
1002 if (!nl_bands) 976 nl_rates = nla_nest_start(msg, NL80211_BAND_ATTR_RATES);
1003 goto nla_put_failure; 977 if (!nl_rates)
978 return -ENOBUFS;
1004 979
1005 for (band = 0; band < IEEE80211_NUM_BANDS; band++) { 980 for (i = 0; i < sband->n_bitrates; i++) {
1006 if (!dev->wiphy.bands[band]) 981 nl_rate = nla_nest_start(msg, i);
1007 continue; 982 if (!nl_rate)
983 return -ENOBUFS;
1008 984
1009 nl_band = nla_nest_start(msg, band); 985 rate = &sband->bitrates[i];
1010 if (!nl_band) 986 if (nla_put_u32(msg, NL80211_BITRATE_ATTR_RATE,
1011 goto nla_put_failure; 987 rate->bitrate))
988 return -ENOBUFS;
989 if ((rate->flags & IEEE80211_RATE_SHORT_PREAMBLE) &&
990 nla_put_flag(msg,
991 NL80211_BITRATE_ATTR_2GHZ_SHORTPREAMBLE))
992 return -ENOBUFS;
1012 993
1013 /* add HT info */ 994 nla_nest_end(msg, nl_rate);
1014 if (dev->wiphy.bands[band]->ht_cap.ht_supported && 995 }
1015 (nla_put(msg, NL80211_BAND_ATTR_HT_MCS_SET,
1016 sizeof(dev->wiphy.bands[band]->ht_cap.mcs),
1017 &dev->wiphy.bands[band]->ht_cap.mcs) ||
1018 nla_put_u16(msg, NL80211_BAND_ATTR_HT_CAPA,
1019 dev->wiphy.bands[band]->ht_cap.cap) ||
1020 nla_put_u8(msg, NL80211_BAND_ATTR_HT_AMPDU_FACTOR,
1021 dev->wiphy.bands[band]->ht_cap.ampdu_factor) ||
1022 nla_put_u8(msg, NL80211_BAND_ATTR_HT_AMPDU_DENSITY,
1023 dev->wiphy.bands[band]->ht_cap.ampdu_density)))
1024 goto nla_put_failure;
1025 996
1026 /* add VHT info */ 997 nla_nest_end(msg, nl_rates);
1027 if (dev->wiphy.bands[band]->vht_cap.vht_supported &&
1028 (nla_put(msg, NL80211_BAND_ATTR_VHT_MCS_SET,
1029 sizeof(dev->wiphy.bands[band]->vht_cap.vht_mcs),
1030 &dev->wiphy.bands[band]->vht_cap.vht_mcs) ||
1031 nla_put_u32(msg, NL80211_BAND_ATTR_VHT_CAPA,
1032 dev->wiphy.bands[band]->vht_cap.cap)))
1033 goto nla_put_failure;
1034 998
1035 /* add frequencies */ 999 return 0;
1036 nl_freqs = nla_nest_start(msg, NL80211_BAND_ATTR_FREQS); 1000}
1037 if (!nl_freqs)
1038 goto nla_put_failure;
1039 1001
1040 for (i = 0; i < dev->wiphy.bands[band]->n_channels; i++) { 1002static int
1041 nl_freq = nla_nest_start(msg, i); 1003nl80211_send_mgmt_stypes(struct sk_buff *msg,
1042 if (!nl_freq) 1004 const struct ieee80211_txrx_stypes *mgmt_stypes)
1043 goto nla_put_failure; 1005{
1006 u16 stypes;
1007 struct nlattr *nl_ftypes, *nl_ifs;
1008 enum nl80211_iftype ift;
1009 int i;
1044 1010
1045 chan = &dev->wiphy.bands[band]->channels[i]; 1011 if (!mgmt_stypes)
1012 return 0;
1046 1013
1047 if (nl80211_msg_put_channel(msg, chan)) 1014 nl_ifs = nla_nest_start(msg, NL80211_ATTR_TX_FRAME_TYPES);
1048 goto nla_put_failure; 1015 if (!nl_ifs)
1016 return -ENOBUFS;
1049 1017
1050 nla_nest_end(msg, nl_freq); 1018 for (ift = 0; ift < NUM_NL80211_IFTYPES; ift++) {
1019 nl_ftypes = nla_nest_start(msg, ift);
1020 if (!nl_ftypes)
1021 return -ENOBUFS;
1022 i = 0;
1023 stypes = mgmt_stypes[ift].tx;
1024 while (stypes) {
1025 if ((stypes & 1) &&
1026 nla_put_u16(msg, NL80211_ATTR_FRAME_TYPE,
1027 (i << 4) | IEEE80211_FTYPE_MGMT))
1028 return -ENOBUFS;
1029 stypes >>= 1;
1030 i++;
1051 } 1031 }
1032 nla_nest_end(msg, nl_ftypes);
1033 }
1052 1034
1053 nla_nest_end(msg, nl_freqs); 1035 nla_nest_end(msg, nl_ifs);
1054 1036
1055 /* add bitrates */ 1037 nl_ifs = nla_nest_start(msg, NL80211_ATTR_RX_FRAME_TYPES);
1056 nl_rates = nla_nest_start(msg, NL80211_BAND_ATTR_RATES); 1038 if (!nl_ifs)
1057 if (!nl_rates) 1039 return -ENOBUFS;
1058 goto nla_put_failure;
1059 1040
1060 for (i = 0; i < dev->wiphy.bands[band]->n_bitrates; i++) { 1041 for (ift = 0; ift < NUM_NL80211_IFTYPES; ift++) {
1061 nl_rate = nla_nest_start(msg, i); 1042 nl_ftypes = nla_nest_start(msg, ift);
1062 if (!nl_rate) 1043 if (!nl_ftypes)
1063 goto nla_put_failure; 1044 return -ENOBUFS;
1045 i = 0;
1046 stypes = mgmt_stypes[ift].rx;
1047 while (stypes) {
1048 if ((stypes & 1) &&
1049 nla_put_u16(msg, NL80211_ATTR_FRAME_TYPE,
1050 (i << 4) | IEEE80211_FTYPE_MGMT))
1051 return -ENOBUFS;
1052 stypes >>= 1;
1053 i++;
1054 }
1055 nla_nest_end(msg, nl_ftypes);
1056 }
1057 nla_nest_end(msg, nl_ifs);
1064 1058
1065 rate = &dev->wiphy.bands[band]->bitrates[i]; 1059 return 0;
1066 if (nla_put_u32(msg, NL80211_BITRATE_ATTR_RATE, 1060}
1067 rate->bitrate))
1068 goto nla_put_failure;
1069 if ((rate->flags & IEEE80211_RATE_SHORT_PREAMBLE) &&
1070 nla_put_flag(msg,
1071 NL80211_BITRATE_ATTR_2GHZ_SHORTPREAMBLE))
1072 goto nla_put_failure;
1073 1061
1074 nla_nest_end(msg, nl_rate); 1062static int nl80211_send_wiphy(struct cfg80211_registered_device *dev,
1075 } 1063 struct sk_buff *msg, u32 portid, u32 seq,
1064 int flags, bool split, long *split_start,
1065 long *band_start, long *chan_start)
1066{
1067 void *hdr;
1068 struct nlattr *nl_bands, *nl_band;
1069 struct nlattr *nl_freqs, *nl_freq;
1070 struct nlattr *nl_cmds;
1071 enum ieee80211_band band;
1072 struct ieee80211_channel *chan;
1073 int i;
1074 const struct ieee80211_txrx_stypes *mgmt_stypes =
1075 dev->wiphy.mgmt_stypes;
1076 long start = 0, start_chan = 0, start_band = 0;
1076 1077
1077 nla_nest_end(msg, nl_rates); 1078 hdr = nl80211hdr_put(msg, portid, seq, flags, NL80211_CMD_NEW_WIPHY);
1079 if (!hdr)
1080 return -ENOBUFS;
1078 1081
1079 nla_nest_end(msg, nl_band); 1082 /* allow always using the variables */
1083 if (!split) {
1084 split_start = &start;
1085 band_start = &start_band;
1086 chan_start = &start_chan;
1080 } 1087 }
1081 nla_nest_end(msg, nl_bands);
1082 1088
1083 nl_cmds = nla_nest_start(msg, NL80211_ATTR_SUPPORTED_COMMANDS); 1089 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, dev->wiphy_idx) ||
1084 if (!nl_cmds) 1090 nla_put_string(msg, NL80211_ATTR_WIPHY_NAME,
1085 goto nla_put_failure; 1091 wiphy_name(&dev->wiphy)) ||
1092 nla_put_u32(msg, NL80211_ATTR_GENERATION,
1093 cfg80211_rdev_list_generation))
1094 goto nla_put_failure;
1095
1096 switch (*split_start) {
1097 case 0:
1098 if (nla_put_u8(msg, NL80211_ATTR_WIPHY_RETRY_SHORT,
1099 dev->wiphy.retry_short) ||
1100 nla_put_u8(msg, NL80211_ATTR_WIPHY_RETRY_LONG,
1101 dev->wiphy.retry_long) ||
1102 nla_put_u32(msg, NL80211_ATTR_WIPHY_FRAG_THRESHOLD,
1103 dev->wiphy.frag_threshold) ||
1104 nla_put_u32(msg, NL80211_ATTR_WIPHY_RTS_THRESHOLD,
1105 dev->wiphy.rts_threshold) ||
1106 nla_put_u8(msg, NL80211_ATTR_WIPHY_COVERAGE_CLASS,
1107 dev->wiphy.coverage_class) ||
1108 nla_put_u8(msg, NL80211_ATTR_MAX_NUM_SCAN_SSIDS,
1109 dev->wiphy.max_scan_ssids) ||
1110 nla_put_u8(msg, NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS,
1111 dev->wiphy.max_sched_scan_ssids) ||
1112 nla_put_u16(msg, NL80211_ATTR_MAX_SCAN_IE_LEN,
1113 dev->wiphy.max_scan_ie_len) ||
1114 nla_put_u16(msg, NL80211_ATTR_MAX_SCHED_SCAN_IE_LEN,
1115 dev->wiphy.max_sched_scan_ie_len) ||
1116 nla_put_u8(msg, NL80211_ATTR_MAX_MATCH_SETS,
1117 dev->wiphy.max_match_sets))
1118 goto nla_put_failure;
1086 1119
1087 i = 0; 1120 if ((dev->wiphy.flags & WIPHY_FLAG_IBSS_RSN) &&
1088#define CMD(op, n) \ 1121 nla_put_flag(msg, NL80211_ATTR_SUPPORT_IBSS_RSN))
1089 do { \
1090 if (dev->ops->op) { \
1091 i++; \
1092 if (nla_put_u32(msg, i, NL80211_CMD_ ## n)) \
1093 goto nla_put_failure; \
1094 } \
1095 } while (0)
1096
1097 CMD(add_virtual_intf, NEW_INTERFACE);
1098 CMD(change_virtual_intf, SET_INTERFACE);
1099 CMD(add_key, NEW_KEY);
1100 CMD(start_ap, START_AP);
1101 CMD(add_station, NEW_STATION);
1102 CMD(add_mpath, NEW_MPATH);
1103 CMD(update_mesh_config, SET_MESH_CONFIG);
1104 CMD(change_bss, SET_BSS);
1105 CMD(auth, AUTHENTICATE);
1106 CMD(assoc, ASSOCIATE);
1107 CMD(deauth, DEAUTHENTICATE);
1108 CMD(disassoc, DISASSOCIATE);
1109 CMD(join_ibss, JOIN_IBSS);
1110 CMD(join_mesh, JOIN_MESH);
1111 CMD(set_pmksa, SET_PMKSA);
1112 CMD(del_pmksa, DEL_PMKSA);
1113 CMD(flush_pmksa, FLUSH_PMKSA);
1114 if (dev->wiphy.flags & WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL)
1115 CMD(remain_on_channel, REMAIN_ON_CHANNEL);
1116 CMD(set_bitrate_mask, SET_TX_BITRATE_MASK);
1117 CMD(mgmt_tx, FRAME);
1118 CMD(mgmt_tx_cancel_wait, FRAME_WAIT_CANCEL);
1119 if (dev->wiphy.flags & WIPHY_FLAG_NETNS_OK) {
1120 i++;
1121 if (nla_put_u32(msg, i, NL80211_CMD_SET_WIPHY_NETNS))
1122 goto nla_put_failure; 1122 goto nla_put_failure;
1123 } 1123 if ((dev->wiphy.flags & WIPHY_FLAG_MESH_AUTH) &&
1124 if (dev->ops->set_monitor_channel || dev->ops->start_ap || 1124 nla_put_flag(msg, NL80211_ATTR_SUPPORT_MESH_AUTH))
1125 dev->ops->join_mesh) {
1126 i++;
1127 if (nla_put_u32(msg, i, NL80211_CMD_SET_CHANNEL))
1128 goto nla_put_failure; 1125 goto nla_put_failure;
1129 } 1126 if ((dev->wiphy.flags & WIPHY_FLAG_AP_UAPSD) &&
1130 CMD(set_wds_peer, SET_WDS_PEER); 1127 nla_put_flag(msg, NL80211_ATTR_SUPPORT_AP_UAPSD))
1131 if (dev->wiphy.flags & WIPHY_FLAG_SUPPORTS_TDLS) { 1128 goto nla_put_failure;
1132 CMD(tdls_mgmt, TDLS_MGMT); 1129 if ((dev->wiphy.flags & WIPHY_FLAG_SUPPORTS_FW_ROAM) &&
1133 CMD(tdls_oper, TDLS_OPER); 1130 nla_put_flag(msg, NL80211_ATTR_ROAM_SUPPORT))
1134 } 1131 goto nla_put_failure;
1135 if (dev->wiphy.flags & WIPHY_FLAG_SUPPORTS_SCHED_SCAN) 1132 if ((dev->wiphy.flags & WIPHY_FLAG_SUPPORTS_TDLS) &&
1136 CMD(sched_scan_start, START_SCHED_SCAN); 1133 nla_put_flag(msg, NL80211_ATTR_TDLS_SUPPORT))
1137 CMD(probe_client, PROBE_CLIENT); 1134 goto nla_put_failure;
1138 CMD(set_noack_map, SET_NOACK_MAP); 1135 if ((dev->wiphy.flags & WIPHY_FLAG_TDLS_EXTERNAL_SETUP) &&
1139 if (dev->wiphy.flags & WIPHY_FLAG_REPORTS_OBSS) { 1136 nla_put_flag(msg, NL80211_ATTR_TDLS_EXTERNAL_SETUP))
1140 i++;
1141 if (nla_put_u32(msg, i, NL80211_CMD_REGISTER_BEACONS))
1142 goto nla_put_failure; 1137 goto nla_put_failure;
1143 }
1144 CMD(start_p2p_device, START_P2P_DEVICE);
1145 CMD(set_mcast_rate, SET_MCAST_RATE);
1146 1138
1147#ifdef CONFIG_NL80211_TESTMODE 1139 (*split_start)++;
1148 CMD(testmode_cmd, TESTMODE); 1140 if (split)
1149#endif 1141 break;
1142 case 1:
1143 if (nla_put(msg, NL80211_ATTR_CIPHER_SUITES,
1144 sizeof(u32) * dev->wiphy.n_cipher_suites,
1145 dev->wiphy.cipher_suites))
1146 goto nla_put_failure;
1150 1147
1151#undef CMD 1148 if (nla_put_u8(msg, NL80211_ATTR_MAX_NUM_PMKIDS,
1149 dev->wiphy.max_num_pmkids))
1150 goto nla_put_failure;
1152 1151
1153 if (dev->ops->connect || dev->ops->auth) { 1152 if ((dev->wiphy.flags & WIPHY_FLAG_CONTROL_PORT_PROTOCOL) &&
1154 i++; 1153 nla_put_flag(msg, NL80211_ATTR_CONTROL_PORT_ETHERTYPE))
1155 if (nla_put_u32(msg, i, NL80211_CMD_CONNECT))
1156 goto nla_put_failure; 1154 goto nla_put_failure;
1157 }
1158 1155
1159 if (dev->ops->disconnect || dev->ops->deauth) { 1156 if (nla_put_u32(msg, NL80211_ATTR_WIPHY_ANTENNA_AVAIL_TX,
1160 i++; 1157 dev->wiphy.available_antennas_tx) ||
1161 if (nla_put_u32(msg, i, NL80211_CMD_DISCONNECT)) 1158 nla_put_u32(msg, NL80211_ATTR_WIPHY_ANTENNA_AVAIL_RX,
1159 dev->wiphy.available_antennas_rx))
1162 goto nla_put_failure; 1160 goto nla_put_failure;
1163 }
1164 1161
1165 nla_nest_end(msg, nl_cmds); 1162 if ((dev->wiphy.flags & WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD) &&
1163 nla_put_u32(msg, NL80211_ATTR_PROBE_RESP_OFFLOAD,
1164 dev->wiphy.probe_resp_offload))
1165 goto nla_put_failure;
1166 1166
1167 if (dev->ops->remain_on_channel && 1167 if ((dev->wiphy.available_antennas_tx ||
1168 (dev->wiphy.flags & WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL) && 1168 dev->wiphy.available_antennas_rx) &&
1169 nla_put_u32(msg, NL80211_ATTR_MAX_REMAIN_ON_CHANNEL_DURATION, 1169 dev->ops->get_antenna) {
1170 dev->wiphy.max_remain_on_channel_duration)) 1170 u32 tx_ant = 0, rx_ant = 0;
1171 goto nla_put_failure; 1171 int res;
1172 res = rdev_get_antenna(dev, &tx_ant, &rx_ant);
1173 if (!res) {
1174 if (nla_put_u32(msg,
1175 NL80211_ATTR_WIPHY_ANTENNA_TX,
1176 tx_ant) ||
1177 nla_put_u32(msg,
1178 NL80211_ATTR_WIPHY_ANTENNA_RX,
1179 rx_ant))
1180 goto nla_put_failure;
1181 }
1182 }
1172 1183
1173 if ((dev->wiphy.flags & WIPHY_FLAG_OFFCHAN_TX) && 1184 (*split_start)++;
1174 nla_put_flag(msg, NL80211_ATTR_OFFCHANNEL_TX_OK)) 1185 if (split)
1175 goto nla_put_failure; 1186 break;
1187 case 2:
1188 if (nl80211_put_iftypes(msg, NL80211_ATTR_SUPPORTED_IFTYPES,
1189 dev->wiphy.interface_modes))
1190 goto nla_put_failure;
1191 (*split_start)++;
1192 if (split)
1193 break;
1194 case 3:
1195 nl_bands = nla_nest_start(msg, NL80211_ATTR_WIPHY_BANDS);
1196 if (!nl_bands)
1197 goto nla_put_failure;
1176 1198
1177 if (mgmt_stypes) { 1199 for (band = *band_start; band < IEEE80211_NUM_BANDS; band++) {
1178 u16 stypes; 1200 struct ieee80211_supported_band *sband;
1179 struct nlattr *nl_ftypes, *nl_ifs;
1180 enum nl80211_iftype ift;
1181 1201
1182 nl_ifs = nla_nest_start(msg, NL80211_ATTR_TX_FRAME_TYPES); 1202 sband = dev->wiphy.bands[band];
1183 if (!nl_ifs)
1184 goto nla_put_failure;
1185 1203
1186 for (ift = 0; ift < NUM_NL80211_IFTYPES; ift++) { 1204 if (!sband)
1187 nl_ftypes = nla_nest_start(msg, ift); 1205 continue;
1188 if (!nl_ftypes) 1206
1207 nl_band = nla_nest_start(msg, band);
1208 if (!nl_band)
1189 goto nla_put_failure; 1209 goto nla_put_failure;
1190 i = 0; 1210
1191 stypes = mgmt_stypes[ift].tx; 1211 switch (*chan_start) {
1192 while (stypes) { 1212 case 0:
1193 if ((stypes & 1) && 1213 if (nl80211_send_band_rateinfo(msg, sband))
1194 nla_put_u16(msg, NL80211_ATTR_FRAME_TYPE,
1195 (i << 4) | IEEE80211_FTYPE_MGMT))
1196 goto nla_put_failure; 1214 goto nla_put_failure;
1197 stypes >>= 1; 1215 (*chan_start)++;
1198 i++; 1216 if (split)
1217 break;
1218 default:
1219 /* add frequencies */
1220 nl_freqs = nla_nest_start(
1221 msg, NL80211_BAND_ATTR_FREQS);
1222 if (!nl_freqs)
1223 goto nla_put_failure;
1224
1225 for (i = *chan_start - 1;
1226 i < sband->n_channels;
1227 i++) {
1228 nl_freq = nla_nest_start(msg, i);
1229 if (!nl_freq)
1230 goto nla_put_failure;
1231
1232 chan = &sband->channels[i];
1233
1234 if (nl80211_msg_put_channel(msg, chan))
1235 goto nla_put_failure;
1236
1237 nla_nest_end(msg, nl_freq);
1238 if (split)
1239 break;
1240 }
1241 if (i < sband->n_channels)
1242 *chan_start = i + 2;
1243 else
1244 *chan_start = 0;
1245 nla_nest_end(msg, nl_freqs);
1246 }
1247
1248 nla_nest_end(msg, nl_band);
1249
1250 if (split) {
1251 /* start again here */
1252 if (*chan_start)
1253 band--;
1254 break;
1199 } 1255 }
1200 nla_nest_end(msg, nl_ftypes);
1201 } 1256 }
1257 nla_nest_end(msg, nl_bands);
1202 1258
1203 nla_nest_end(msg, nl_ifs); 1259 if (band < IEEE80211_NUM_BANDS)
1260 *band_start = band + 1;
1261 else
1262 *band_start = 0;
1204 1263
1205 nl_ifs = nla_nest_start(msg, NL80211_ATTR_RX_FRAME_TYPES); 1264 /* if bands & channels are done, continue outside */
1206 if (!nl_ifs) 1265 if (*band_start == 0 && *chan_start == 0)
1266 (*split_start)++;
1267 if (split)
1268 break;
1269 case 4:
1270 nl_cmds = nla_nest_start(msg, NL80211_ATTR_SUPPORTED_COMMANDS);
1271 if (!nl_cmds)
1207 goto nla_put_failure; 1272 goto nla_put_failure;
1208 1273
1209 for (ift = 0; ift < NUM_NL80211_IFTYPES; ift++) { 1274 i = 0;
1210 nl_ftypes = nla_nest_start(msg, ift); 1275#define CMD(op, n) \
1211 if (!nl_ftypes) 1276 do { \
1277 if (dev->ops->op) { \
1278 i++; \
1279 if (nla_put_u32(msg, i, NL80211_CMD_ ## n)) \
1280 goto nla_put_failure; \
1281 } \
1282 } while (0)
1283
1284 CMD(add_virtual_intf, NEW_INTERFACE);
1285 CMD(change_virtual_intf, SET_INTERFACE);
1286 CMD(add_key, NEW_KEY);
1287 CMD(start_ap, START_AP);
1288 CMD(add_station, NEW_STATION);
1289 CMD(add_mpath, NEW_MPATH);
1290 CMD(update_mesh_config, SET_MESH_CONFIG);
1291 CMD(change_bss, SET_BSS);
1292 CMD(auth, AUTHENTICATE);
1293 CMD(assoc, ASSOCIATE);
1294 CMD(deauth, DEAUTHENTICATE);
1295 CMD(disassoc, DISASSOCIATE);
1296 CMD(join_ibss, JOIN_IBSS);
1297 CMD(join_mesh, JOIN_MESH);
1298 CMD(set_pmksa, SET_PMKSA);
1299 CMD(del_pmksa, DEL_PMKSA);
1300 CMD(flush_pmksa, FLUSH_PMKSA);
1301 if (dev->wiphy.flags & WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL)
1302 CMD(remain_on_channel, REMAIN_ON_CHANNEL);
1303 CMD(set_bitrate_mask, SET_TX_BITRATE_MASK);
1304 CMD(mgmt_tx, FRAME);
1305 CMD(mgmt_tx_cancel_wait, FRAME_WAIT_CANCEL);
1306 if (dev->wiphy.flags & WIPHY_FLAG_NETNS_OK) {
1307 i++;
1308 if (nla_put_u32(msg, i, NL80211_CMD_SET_WIPHY_NETNS))
1212 goto nla_put_failure; 1309 goto nla_put_failure;
1213 i = 0;
1214 stypes = mgmt_stypes[ift].rx;
1215 while (stypes) {
1216 if ((stypes & 1) &&
1217 nla_put_u16(msg, NL80211_ATTR_FRAME_TYPE,
1218 (i << 4) | IEEE80211_FTYPE_MGMT))
1219 goto nla_put_failure;
1220 stypes >>= 1;
1221 i++;
1222 }
1223 nla_nest_end(msg, nl_ftypes);
1224 } 1310 }
1225 nla_nest_end(msg, nl_ifs); 1311 if (dev->ops->set_monitor_channel || dev->ops->start_ap ||
1226 } 1312 dev->ops->join_mesh) {
1313 i++;
1314 if (nla_put_u32(msg, i, NL80211_CMD_SET_CHANNEL))
1315 goto nla_put_failure;
1316 }
1317 CMD(set_wds_peer, SET_WDS_PEER);
1318 if (dev->wiphy.flags & WIPHY_FLAG_SUPPORTS_TDLS) {
1319 CMD(tdls_mgmt, TDLS_MGMT);
1320 CMD(tdls_oper, TDLS_OPER);
1321 }
1322 if (dev->wiphy.flags & WIPHY_FLAG_SUPPORTS_SCHED_SCAN)
1323 CMD(sched_scan_start, START_SCHED_SCAN);
1324 CMD(probe_client, PROBE_CLIENT);
1325 CMD(set_noack_map, SET_NOACK_MAP);
1326 if (dev->wiphy.flags & WIPHY_FLAG_REPORTS_OBSS) {
1327 i++;
1328 if (nla_put_u32(msg, i, NL80211_CMD_REGISTER_BEACONS))
1329 goto nla_put_failure;
1330 }
1331 CMD(start_p2p_device, START_P2P_DEVICE);
1332 CMD(set_mcast_rate, SET_MCAST_RATE);
1227 1333
1228#ifdef CONFIG_PM 1334#ifdef CONFIG_NL80211_TESTMODE
1229 if (dev->wiphy.wowlan.flags || dev->wiphy.wowlan.n_patterns) { 1335 CMD(testmode_cmd, TESTMODE);
1230 struct nlattr *nl_wowlan; 1336#endif
1231 1337
1232 nl_wowlan = nla_nest_start(msg, 1338#undef CMD
1233 NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED);
1234 if (!nl_wowlan)
1235 goto nla_put_failure;
1236 1339
1237 if (((dev->wiphy.wowlan.flags & WIPHY_WOWLAN_ANY) && 1340 if (dev->ops->connect || dev->ops->auth) {
1238 nla_put_flag(msg, NL80211_WOWLAN_TRIG_ANY)) || 1341 i++;
1239 ((dev->wiphy.wowlan.flags & WIPHY_WOWLAN_DISCONNECT) && 1342 if (nla_put_u32(msg, i, NL80211_CMD_CONNECT))
1240 nla_put_flag(msg, NL80211_WOWLAN_TRIG_DISCONNECT)) ||
1241 ((dev->wiphy.wowlan.flags & WIPHY_WOWLAN_MAGIC_PKT) &&
1242 nla_put_flag(msg, NL80211_WOWLAN_TRIG_MAGIC_PKT)) ||
1243 ((dev->wiphy.wowlan.flags & WIPHY_WOWLAN_SUPPORTS_GTK_REKEY) &&
1244 nla_put_flag(msg, NL80211_WOWLAN_TRIG_GTK_REKEY_SUPPORTED)) ||
1245 ((dev->wiphy.wowlan.flags & WIPHY_WOWLAN_GTK_REKEY_FAILURE) &&
1246 nla_put_flag(msg, NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE)) ||
1247 ((dev->wiphy.wowlan.flags & WIPHY_WOWLAN_EAP_IDENTITY_REQ) &&
1248 nla_put_flag(msg, NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST)) ||
1249 ((dev->wiphy.wowlan.flags & WIPHY_WOWLAN_4WAY_HANDSHAKE) &&
1250 nla_put_flag(msg, NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE)) ||
1251 ((dev->wiphy.wowlan.flags & WIPHY_WOWLAN_RFKILL_RELEASE) &&
1252 nla_put_flag(msg, NL80211_WOWLAN_TRIG_RFKILL_RELEASE)))
1253 goto nla_put_failure;
1254 if (dev->wiphy.wowlan.n_patterns) {
1255 struct nl80211_wowlan_pattern_support pat = {
1256 .max_patterns = dev->wiphy.wowlan.n_patterns,
1257 .min_pattern_len =
1258 dev->wiphy.wowlan.pattern_min_len,
1259 .max_pattern_len =
1260 dev->wiphy.wowlan.pattern_max_len,
1261 .max_pkt_offset =
1262 dev->wiphy.wowlan.max_pkt_offset,
1263 };
1264 if (nla_put(msg, NL80211_WOWLAN_TRIG_PKT_PATTERN,
1265 sizeof(pat), &pat))
1266 goto nla_put_failure; 1343 goto nla_put_failure;
1267 } 1344 }
1268 1345
1269 nla_nest_end(msg, nl_wowlan); 1346 if (dev->ops->disconnect || dev->ops->deauth) {
1270 } 1347 i++;
1348 if (nla_put_u32(msg, i, NL80211_CMD_DISCONNECT))
1349 goto nla_put_failure;
1350 }
1351
1352 nla_nest_end(msg, nl_cmds);
1353 (*split_start)++;
1354 if (split)
1355 break;
1356 case 5:
1357 if (dev->ops->remain_on_channel &&
1358 (dev->wiphy.flags & WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL) &&
1359 nla_put_u32(msg,
1360 NL80211_ATTR_MAX_REMAIN_ON_CHANNEL_DURATION,
1361 dev->wiphy.max_remain_on_channel_duration))
1362 goto nla_put_failure;
1363
1364 if ((dev->wiphy.flags & WIPHY_FLAG_OFFCHAN_TX) &&
1365 nla_put_flag(msg, NL80211_ATTR_OFFCHANNEL_TX_OK))
1366 goto nla_put_failure;
1367
1368 if (nl80211_send_mgmt_stypes(msg, mgmt_stypes))
1369 goto nla_put_failure;
1370 (*split_start)++;
1371 if (split)
1372 break;
1373 case 6:
1374#ifdef CONFIG_PM
1375 if (nl80211_send_wowlan(msg, dev))
1376 goto nla_put_failure;
1377 (*split_start)++;
1378 if (split)
1379 break;
1380#else
1381 (*split_start)++;
1271#endif 1382#endif
1383 case 7:
1384 if (nl80211_put_iftypes(msg, NL80211_ATTR_SOFTWARE_IFTYPES,
1385 dev->wiphy.software_iftypes))
1386 goto nla_put_failure;
1272 1387
1273 if (nl80211_put_iftypes(msg, NL80211_ATTR_SOFTWARE_IFTYPES, 1388 if (nl80211_put_iface_combinations(&dev->wiphy, msg))
1274 dev->wiphy.software_iftypes)) 1389 goto nla_put_failure;
1275 goto nla_put_failure;
1276 1390
1277 if (nl80211_put_iface_combinations(&dev->wiphy, msg)) 1391 (*split_start)++;
1278 goto nla_put_failure; 1392 if (split)
1393 break;
1394 case 8:
1395 if ((dev->wiphy.flags & WIPHY_FLAG_HAVE_AP_SME) &&
1396 nla_put_u32(msg, NL80211_ATTR_DEVICE_AP_SME,
1397 dev->wiphy.ap_sme_capa))
1398 goto nla_put_failure;
1279 1399
1280 if ((dev->wiphy.flags & WIPHY_FLAG_HAVE_AP_SME) && 1400 if (nla_put_u32(msg, NL80211_ATTR_FEATURE_FLAGS,
1281 nla_put_u32(msg, NL80211_ATTR_DEVICE_AP_SME, 1401 dev->wiphy.features))
1282 dev->wiphy.ap_sme_capa)) 1402 goto nla_put_failure;
1283 goto nla_put_failure;
1284 1403
1285 if (nla_put_u32(msg, NL80211_ATTR_FEATURE_FLAGS, 1404 if (dev->wiphy.ht_capa_mod_mask &&
1286 dev->wiphy.features)) 1405 nla_put(msg, NL80211_ATTR_HT_CAPABILITY_MASK,
1287 goto nla_put_failure; 1406 sizeof(*dev->wiphy.ht_capa_mod_mask),
1407 dev->wiphy.ht_capa_mod_mask))
1408 goto nla_put_failure;
1288 1409
1289 if (dev->wiphy.ht_capa_mod_mask && 1410 if (dev->wiphy.flags & WIPHY_FLAG_HAVE_AP_SME &&
1290 nla_put(msg, NL80211_ATTR_HT_CAPABILITY_MASK, 1411 dev->wiphy.max_acl_mac_addrs &&
1291 sizeof(*dev->wiphy.ht_capa_mod_mask), 1412 nla_put_u32(msg, NL80211_ATTR_MAC_ACL_MAX,
1292 dev->wiphy.ht_capa_mod_mask)) 1413 dev->wiphy.max_acl_mac_addrs))
1293 goto nla_put_failure; 1414 goto nla_put_failure;
1294 1415
1295 if (dev->wiphy.flags & WIPHY_FLAG_HAVE_AP_SME && 1416 /*
1296 dev->wiphy.max_acl_mac_addrs && 1417 * Any information below this point is only available to
1297 nla_put_u32(msg, NL80211_ATTR_MAC_ACL_MAX, 1418 * applications that can deal with it being split. This
1298 dev->wiphy.max_acl_mac_addrs)) 1419 * helps ensure that newly added capabilities don't break
1299 goto nla_put_failure; 1420 * older tools by overrunning their buffers.
1421 *
1422 * We still increment split_start so that in the split
1423 * case we'll continue with more data in the next round,
1424 * but break unconditionally so unsplit data stops here.
1425 */
1426 (*split_start)++;
1427 break;
1428 case 9:
1429 /* placeholder */
1300 1430
1431 /* done */
1432 *split_start = 0;
1433 break;
1434 }
1301 return genlmsg_end(msg, hdr); 1435 return genlmsg_end(msg, hdr);
1302 1436
1303 nla_put_failure: 1437 nla_put_failure:
@@ -1310,39 +1444,80 @@ static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb)
1310 int idx = 0, ret; 1444 int idx = 0, ret;
1311 int start = cb->args[0]; 1445 int start = cb->args[0];
1312 struct cfg80211_registered_device *dev; 1446 struct cfg80211_registered_device *dev;
1447 s64 filter_wiphy = -1;
1448 bool split = false;
1449 struct nlattr **tb = nl80211_fam.attrbuf;
1450 int res;
1313 1451
1314 mutex_lock(&cfg80211_mutex); 1452 mutex_lock(&cfg80211_mutex);
1453 res = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize,
1454 tb, nl80211_fam.maxattr, nl80211_policy);
1455 if (res == 0) {
1456 split = tb[NL80211_ATTR_SPLIT_WIPHY_DUMP];
1457 if (tb[NL80211_ATTR_WIPHY])
1458 filter_wiphy = nla_get_u32(tb[NL80211_ATTR_WIPHY]);
1459 if (tb[NL80211_ATTR_WDEV])
1460 filter_wiphy = nla_get_u64(tb[NL80211_ATTR_WDEV]) >> 32;
1461 if (tb[NL80211_ATTR_IFINDEX]) {
1462 struct net_device *netdev;
1463 int ifidx = nla_get_u32(tb[NL80211_ATTR_IFINDEX]);
1464
1465 netdev = dev_get_by_index(sock_net(skb->sk), ifidx);
1466 if (!netdev) {
1467 mutex_unlock(&cfg80211_mutex);
1468 return -ENODEV;
1469 }
1470 if (netdev->ieee80211_ptr) {
1471 dev = wiphy_to_dev(
1472 netdev->ieee80211_ptr->wiphy);
1473 filter_wiphy = dev->wiphy_idx;
1474 }
1475 dev_put(netdev);
1476 }
1477 }
1478
1315 list_for_each_entry(dev, &cfg80211_rdev_list, list) { 1479 list_for_each_entry(dev, &cfg80211_rdev_list, list) {
1316 if (!net_eq(wiphy_net(&dev->wiphy), sock_net(skb->sk))) 1480 if (!net_eq(wiphy_net(&dev->wiphy), sock_net(skb->sk)))
1317 continue; 1481 continue;
1318 if (++idx <= start) 1482 if (++idx <= start)
1319 continue; 1483 continue;
1320 ret = nl80211_send_wiphy(skb, NETLINK_CB(cb->skb).portid, 1484 if (filter_wiphy != -1 && dev->wiphy_idx != filter_wiphy)
1321 cb->nlh->nlmsg_seq, NLM_F_MULTI, 1485 continue;
1322 dev); 1486 /* attempt to fit multiple wiphy data chunks into the skb */
1323 if (ret < 0) { 1487 do {
1324 /* 1488 ret = nl80211_send_wiphy(dev, skb,
1325 * If sending the wiphy data didn't fit (ENOBUFS or 1489 NETLINK_CB(cb->skb).portid,
1326 * EMSGSIZE returned), this SKB is still empty (so 1490 cb->nlh->nlmsg_seq,
1327 * it's not too big because another wiphy dataset is 1491 NLM_F_MULTI,
1328 * already in the skb) and we've not tried to adjust 1492 split, &cb->args[1],
1329 * the dump allocation yet ... then adjust the alloc 1493 &cb->args[2],
1330 * size to be bigger, and return 1 but with the empty 1494 &cb->args[3]);
1331 * skb. This results in an empty message being RX'ed 1495 if (ret < 0) {
1332 * in userspace, but that is ignored. 1496 /*
1333 * 1497 * If sending the wiphy data didn't fit (ENOBUFS
1334 * We can then retry with the larger buffer. 1498 * or EMSGSIZE returned), this SKB is still
1335 */ 1499 * empty (so it's not too big because another
1336 if ((ret == -ENOBUFS || ret == -EMSGSIZE) && 1500 * wiphy dataset is already in the skb) and
1337 !skb->len && 1501 * we've not tried to adjust the dump allocation
1338 cb->min_dump_alloc < 4096) { 1502 * yet ... then adjust the alloc size to be
1339 cb->min_dump_alloc = 4096; 1503 * bigger, and return 1 but with the empty skb.
1340 mutex_unlock(&cfg80211_mutex); 1504 * This results in an empty message being RX'ed
1341 return 1; 1505 * in userspace, but that is ignored.
1506 *
1507 * We can then retry with the larger buffer.
1508 */
1509 if ((ret == -ENOBUFS || ret == -EMSGSIZE) &&
1510 !skb->len &&
1511 cb->min_dump_alloc < 4096) {
1512 cb->min_dump_alloc = 4096;
1513 mutex_unlock(&cfg80211_mutex);
1514 return 1;
1515 }
1516 idx--;
1517 break;
1342 } 1518 }
1343 idx--; 1519 } while (cb->args[1] > 0);
1344 break; 1520 break;
1345 }
1346 } 1521 }
1347 mutex_unlock(&cfg80211_mutex); 1522 mutex_unlock(&cfg80211_mutex);
1348 1523
@@ -1360,7 +1535,8 @@ static int nl80211_get_wiphy(struct sk_buff *skb, struct genl_info *info)
1360 if (!msg) 1535 if (!msg)
1361 return -ENOMEM; 1536 return -ENOMEM;
1362 1537
1363 if (nl80211_send_wiphy(msg, info->snd_portid, info->snd_seq, 0, dev) < 0) { 1538 if (nl80211_send_wiphy(dev, msg, info->snd_portid, info->snd_seq, 0,
1539 false, NULL, NULL, NULL) < 0) {
1364 nlmsg_free(msg); 1540 nlmsg_free(msg);
1365 return -ENOBUFS; 1541 return -ENOBUFS;
1366 } 1542 }
@@ -7821,6 +7997,33 @@ static int nl80211_stop_p2p_device(struct sk_buff *skb, struct genl_info *info)
7821 return 0; 7997 return 0;
7822} 7998}
7823 7999
8000static int nl80211_get_protocol_features(struct sk_buff *skb,
8001 struct genl_info *info)
8002{
8003 void *hdr;
8004 struct sk_buff *msg;
8005
8006 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
8007 if (!msg)
8008 return -ENOMEM;
8009
8010 hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
8011 NL80211_CMD_GET_PROTOCOL_FEATURES);
8012 if (!hdr)
8013 goto nla_put_failure;
8014
8015 if (nla_put_u32(msg, NL80211_ATTR_PROTOCOL_FEATURES,
8016 NL80211_PROTOCOL_FEATURE_SPLIT_WIPHY_DUMP))
8017 goto nla_put_failure;
8018
8019 genlmsg_end(msg, hdr);
8020 return genlmsg_reply(msg, info);
8021
8022 nla_put_failure:
8023 kfree_skb(msg);
8024 return -ENOBUFS;
8025}
8026
7824#define NL80211_FLAG_NEED_WIPHY 0x01 8027#define NL80211_FLAG_NEED_WIPHY 0x01
7825#define NL80211_FLAG_NEED_NETDEV 0x02 8028#define NL80211_FLAG_NEED_NETDEV 0x02
7826#define NL80211_FLAG_NEED_RTNL 0x04 8029#define NL80211_FLAG_NEED_RTNL 0x04
@@ -8497,6 +8700,11 @@ static struct genl_ops nl80211_ops[] = {
8497 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | 8700 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
8498 NL80211_FLAG_NEED_RTNL, 8701 NL80211_FLAG_NEED_RTNL,
8499 }, 8702 },
8703 {
8704 .cmd = NL80211_CMD_GET_PROTOCOL_FEATURES,
8705 .doit = nl80211_get_protocol_features,
8706 .policy = nl80211_policy,
8707 },
8500}; 8708};
8501 8709
8502static struct genl_multicast_group nl80211_mlme_mcgrp = { 8710static struct genl_multicast_group nl80211_mlme_mcgrp = {
@@ -8524,7 +8732,8 @@ void nl80211_notify_dev_rename(struct cfg80211_registered_device *rdev)
8524 if (!msg) 8732 if (!msg)
8525 return; 8733 return;
8526 8734
8527 if (nl80211_send_wiphy(msg, 0, 0, 0, rdev) < 0) { 8735 if (nl80211_send_wiphy(rdev, msg, 0, 0, 0,
8736 false, NULL, NULL, NULL) < 0) {
8528 nlmsg_free(msg); 8737 nlmsg_free(msg);
8529 return; 8738 return;
8530 } 8739 }