diff options
Diffstat (limited to 'net/wireless/nl80211.c')
-rw-r--r-- | net/wireless/nl80211.c | 814 |
1 files changed, 415 insertions, 399 deletions
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index b14b7e3cb6e6..1cc47aca7f05 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -37,10 +37,10 @@ static void nl80211_post_doit(struct genl_ops *ops, struct sk_buff *skb, | |||
37 | 37 | ||
38 | /* the netlink family */ | 38 | /* the netlink family */ |
39 | static struct genl_family nl80211_fam = { | 39 | static struct genl_family nl80211_fam = { |
40 | .id = GENL_ID_GENERATE, /* don't bother with a hardcoded ID */ | 40 | .id = GENL_ID_GENERATE, /* don't bother with a hardcoded ID */ |
41 | .name = "nl80211", /* have users key off the name instead */ | 41 | .name = NL80211_GENL_NAME, /* have users key off the name instead */ |
42 | .hdrsize = 0, /* no private header */ | 42 | .hdrsize = 0, /* no private header */ |
43 | .version = 1, /* no particular meaning now */ | 43 | .version = 1, /* no particular meaning now */ |
44 | .maxattr = NL80211_ATTR_MAX, | 44 | .maxattr = NL80211_ATTR_MAX, |
45 | .netnsok = true, | 45 | .netnsok = true, |
46 | .pre_doit = nl80211_pre_doit, | 46 | .pre_doit = nl80211_pre_doit, |
@@ -59,7 +59,7 @@ __cfg80211_wdev_from_attrs(struct net *netns, struct nlattr **attrs) | |||
59 | int wiphy_idx = -1; | 59 | int wiphy_idx = -1; |
60 | int ifidx = -1; | 60 | int ifidx = -1; |
61 | 61 | ||
62 | assert_cfg80211_lock(); | 62 | ASSERT_RTNL(); |
63 | 63 | ||
64 | if (!have_ifidx && !have_wdev_id) | 64 | if (!have_ifidx && !have_wdev_id) |
65 | return ERR_PTR(-EINVAL); | 65 | return ERR_PTR(-EINVAL); |
@@ -80,7 +80,6 @@ __cfg80211_wdev_from_attrs(struct net *netns, struct nlattr **attrs) | |||
80 | if (have_wdev_id && rdev->wiphy_idx != wiphy_idx) | 80 | if (have_wdev_id && rdev->wiphy_idx != wiphy_idx) |
81 | continue; | 81 | continue; |
82 | 82 | ||
83 | mutex_lock(&rdev->devlist_mtx); | ||
84 | list_for_each_entry(wdev, &rdev->wdev_list, list) { | 83 | list_for_each_entry(wdev, &rdev->wdev_list, list) { |
85 | if (have_ifidx && wdev->netdev && | 84 | if (have_ifidx && wdev->netdev && |
86 | wdev->netdev->ifindex == ifidx) { | 85 | wdev->netdev->ifindex == ifidx) { |
@@ -92,7 +91,6 @@ __cfg80211_wdev_from_attrs(struct net *netns, struct nlattr **attrs) | |||
92 | break; | 91 | break; |
93 | } | 92 | } |
94 | } | 93 | } |
95 | mutex_unlock(&rdev->devlist_mtx); | ||
96 | 94 | ||
97 | if (result) | 95 | if (result) |
98 | break; | 96 | break; |
@@ -109,7 +107,7 @@ __cfg80211_rdev_from_attrs(struct net *netns, struct nlattr **attrs) | |||
109 | struct cfg80211_registered_device *rdev = NULL, *tmp; | 107 | struct cfg80211_registered_device *rdev = NULL, *tmp; |
110 | struct net_device *netdev; | 108 | struct net_device *netdev; |
111 | 109 | ||
112 | assert_cfg80211_lock(); | 110 | ASSERT_RTNL(); |
113 | 111 | ||
114 | if (!attrs[NL80211_ATTR_WIPHY] && | 112 | if (!attrs[NL80211_ATTR_WIPHY] && |
115 | !attrs[NL80211_ATTR_IFINDEX] && | 113 | !attrs[NL80211_ATTR_IFINDEX] && |
@@ -128,14 +126,12 @@ __cfg80211_rdev_from_attrs(struct net *netns, struct nlattr **attrs) | |||
128 | tmp = cfg80211_rdev_by_wiphy_idx(wdev_id >> 32); | 126 | tmp = cfg80211_rdev_by_wiphy_idx(wdev_id >> 32); |
129 | if (tmp) { | 127 | if (tmp) { |
130 | /* make sure wdev exists */ | 128 | /* make sure wdev exists */ |
131 | mutex_lock(&tmp->devlist_mtx); | ||
132 | list_for_each_entry(wdev, &tmp->wdev_list, list) { | 129 | list_for_each_entry(wdev, &tmp->wdev_list, list) { |
133 | if (wdev->identifier != (u32)wdev_id) | 130 | if (wdev->identifier != (u32)wdev_id) |
134 | continue; | 131 | continue; |
135 | found = true; | 132 | found = true; |
136 | break; | 133 | break; |
137 | } | 134 | } |
138 | mutex_unlock(&tmp->devlist_mtx); | ||
139 | 135 | ||
140 | if (!found) | 136 | if (!found) |
141 | tmp = NULL; | 137 | tmp = NULL; |
@@ -182,19 +178,6 @@ __cfg80211_rdev_from_attrs(struct net *netns, struct nlattr **attrs) | |||
182 | /* | 178 | /* |
183 | * This function returns a pointer to the driver | 179 | * This function returns a pointer to the driver |
184 | * that the genl_info item that is passed refers to. | 180 | * that the genl_info item that is passed refers to. |
185 | * If successful, it returns non-NULL and also locks | ||
186 | * the driver's mutex! | ||
187 | * | ||
188 | * This means that you need to call cfg80211_unlock_rdev() | ||
189 | * before being allowed to acquire &cfg80211_mutex! | ||
190 | * | ||
191 | * This is necessary because we need to lock the global | ||
192 | * mutex to get an item off the list safely, and then | ||
193 | * we lock the rdev mutex so it doesn't go away under us. | ||
194 | * | ||
195 | * We don't want to keep cfg80211_mutex locked | ||
196 | * for all the time in order to allow requests on | ||
197 | * other interfaces to go through at the same time. | ||
198 | * | 181 | * |
199 | * The result of this can be a PTR_ERR and hence must | 182 | * The result of this can be a PTR_ERR and hence must |
200 | * be checked with IS_ERR() for errors. | 183 | * be checked with IS_ERR() for errors. |
@@ -202,20 +185,7 @@ __cfg80211_rdev_from_attrs(struct net *netns, struct nlattr **attrs) | |||
202 | static struct cfg80211_registered_device * | 185 | static struct cfg80211_registered_device * |
203 | cfg80211_get_dev_from_info(struct net *netns, struct genl_info *info) | 186 | cfg80211_get_dev_from_info(struct net *netns, struct genl_info *info) |
204 | { | 187 | { |
205 | struct cfg80211_registered_device *rdev; | 188 | return __cfg80211_rdev_from_attrs(netns, info->attrs); |
206 | |||
207 | mutex_lock(&cfg80211_mutex); | ||
208 | rdev = __cfg80211_rdev_from_attrs(netns, info->attrs); | ||
209 | |||
210 | /* if it is not an error we grab the lock on | ||
211 | * it to assure it won't be going away while | ||
212 | * we operate on it */ | ||
213 | if (!IS_ERR(rdev)) | ||
214 | mutex_lock(&rdev->mtx); | ||
215 | |||
216 | mutex_unlock(&cfg80211_mutex); | ||
217 | |||
218 | return rdev; | ||
219 | } | 189 | } |
220 | 190 | ||
221 | /* policy for the attributes */ | 191 | /* policy for the attributes */ |
@@ -378,6 +348,7 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = { | |||
378 | [NL80211_ATTR_MDID] = { .type = NLA_U16 }, | 348 | [NL80211_ATTR_MDID] = { .type = NLA_U16 }, |
379 | [NL80211_ATTR_IE_RIC] = { .type = NLA_BINARY, | 349 | [NL80211_ATTR_IE_RIC] = { .type = NLA_BINARY, |
380 | .len = IEEE80211_MAX_DATA_LEN }, | 350 | .len = IEEE80211_MAX_DATA_LEN }, |
351 | [NL80211_ATTR_PEER_AID] = { .type = NLA_U16 }, | ||
381 | }; | 352 | }; |
382 | 353 | ||
383 | /* policy for the key attributes */ | 354 | /* policy for the key attributes */ |
@@ -455,7 +426,6 @@ static int nl80211_prepare_wdev_dump(struct sk_buff *skb, | |||
455 | int err; | 426 | int err; |
456 | 427 | ||
457 | rtnl_lock(); | 428 | rtnl_lock(); |
458 | mutex_lock(&cfg80211_mutex); | ||
459 | 429 | ||
460 | if (!cb->args[0]) { | 430 | if (!cb->args[0]) { |
461 | err = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize, | 431 | err = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize, |
@@ -484,14 +454,12 @@ static int nl80211_prepare_wdev_dump(struct sk_buff *skb, | |||
484 | *rdev = wiphy_to_dev(wiphy); | 454 | *rdev = wiphy_to_dev(wiphy); |
485 | *wdev = NULL; | 455 | *wdev = NULL; |
486 | 456 | ||
487 | mutex_lock(&(*rdev)->devlist_mtx); | ||
488 | list_for_each_entry(tmp, &(*rdev)->wdev_list, list) { | 457 | list_for_each_entry(tmp, &(*rdev)->wdev_list, list) { |
489 | if (tmp->identifier == cb->args[1]) { | 458 | if (tmp->identifier == cb->args[1]) { |
490 | *wdev = tmp; | 459 | *wdev = tmp; |
491 | break; | 460 | break; |
492 | } | 461 | } |
493 | } | 462 | } |
494 | mutex_unlock(&(*rdev)->devlist_mtx); | ||
495 | 463 | ||
496 | if (!*wdev) { | 464 | if (!*wdev) { |
497 | err = -ENODEV; | 465 | err = -ENODEV; |
@@ -499,19 +467,14 @@ static int nl80211_prepare_wdev_dump(struct sk_buff *skb, | |||
499 | } | 467 | } |
500 | } | 468 | } |
501 | 469 | ||
502 | cfg80211_lock_rdev(*rdev); | ||
503 | |||
504 | mutex_unlock(&cfg80211_mutex); | ||
505 | return 0; | 470 | return 0; |
506 | out_unlock: | 471 | out_unlock: |
507 | mutex_unlock(&cfg80211_mutex); | ||
508 | rtnl_unlock(); | 472 | rtnl_unlock(); |
509 | return err; | 473 | return err; |
510 | } | 474 | } |
511 | 475 | ||
512 | static void nl80211_finish_wdev_dump(struct cfg80211_registered_device *rdev) | 476 | static void nl80211_finish_wdev_dump(struct cfg80211_registered_device *rdev) |
513 | { | 477 | { |
514 | cfg80211_unlock_rdev(rdev); | ||
515 | rtnl_unlock(); | 478 | rtnl_unlock(); |
516 | } | 479 | } |
517 | 480 | ||
@@ -837,12 +800,9 @@ static int nl80211_key_allowed(struct wireless_dev *wdev) | |||
837 | case NL80211_IFTYPE_MESH_POINT: | 800 | case NL80211_IFTYPE_MESH_POINT: |
838 | break; | 801 | break; |
839 | case NL80211_IFTYPE_ADHOC: | 802 | case NL80211_IFTYPE_ADHOC: |
840 | if (!wdev->current_bss) | ||
841 | return -ENOLINK; | ||
842 | break; | ||
843 | case NL80211_IFTYPE_STATION: | 803 | case NL80211_IFTYPE_STATION: |
844 | case NL80211_IFTYPE_P2P_CLIENT: | 804 | case NL80211_IFTYPE_P2P_CLIENT: |
845 | if (wdev->sme_state != CFG80211_SME_CONNECTED) | 805 | if (!wdev->current_bss) |
846 | return -ENOLINK; | 806 | return -ENOLINK; |
847 | break; | 807 | break; |
848 | default: | 808 | default: |
@@ -945,7 +905,7 @@ nla_put_failure: | |||
945 | static int nl80211_send_wowlan_tcp_caps(struct cfg80211_registered_device *rdev, | 905 | static int nl80211_send_wowlan_tcp_caps(struct cfg80211_registered_device *rdev, |
946 | struct sk_buff *msg) | 906 | struct sk_buff *msg) |
947 | { | 907 | { |
948 | const struct wiphy_wowlan_tcp_support *tcp = rdev->wiphy.wowlan.tcp; | 908 | const struct wiphy_wowlan_tcp_support *tcp = rdev->wiphy.wowlan->tcp; |
949 | struct nlattr *nl_tcp; | 909 | struct nlattr *nl_tcp; |
950 | 910 | ||
951 | if (!tcp) | 911 | if (!tcp) |
@@ -988,37 +948,37 @@ static int nl80211_send_wowlan(struct sk_buff *msg, | |||
988 | { | 948 | { |
989 | struct nlattr *nl_wowlan; | 949 | struct nlattr *nl_wowlan; |
990 | 950 | ||
991 | if (!dev->wiphy.wowlan.flags && !dev->wiphy.wowlan.n_patterns) | 951 | if (!dev->wiphy.wowlan) |
992 | return 0; | 952 | return 0; |
993 | 953 | ||
994 | nl_wowlan = nla_nest_start(msg, NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED); | 954 | nl_wowlan = nla_nest_start(msg, NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED); |
995 | if (!nl_wowlan) | 955 | if (!nl_wowlan) |
996 | return -ENOBUFS; | 956 | return -ENOBUFS; |
997 | 957 | ||
998 | if (((dev->wiphy.wowlan.flags & WIPHY_WOWLAN_ANY) && | 958 | if (((dev->wiphy.wowlan->flags & WIPHY_WOWLAN_ANY) && |
999 | nla_put_flag(msg, NL80211_WOWLAN_TRIG_ANY)) || | 959 | nla_put_flag(msg, NL80211_WOWLAN_TRIG_ANY)) || |
1000 | ((dev->wiphy.wowlan.flags & WIPHY_WOWLAN_DISCONNECT) && | 960 | ((dev->wiphy.wowlan->flags & WIPHY_WOWLAN_DISCONNECT) && |
1001 | nla_put_flag(msg, NL80211_WOWLAN_TRIG_DISCONNECT)) || | 961 | nla_put_flag(msg, NL80211_WOWLAN_TRIG_DISCONNECT)) || |
1002 | ((dev->wiphy.wowlan.flags & WIPHY_WOWLAN_MAGIC_PKT) && | 962 | ((dev->wiphy.wowlan->flags & WIPHY_WOWLAN_MAGIC_PKT) && |
1003 | nla_put_flag(msg, NL80211_WOWLAN_TRIG_MAGIC_PKT)) || | 963 | nla_put_flag(msg, NL80211_WOWLAN_TRIG_MAGIC_PKT)) || |
1004 | ((dev->wiphy.wowlan.flags & WIPHY_WOWLAN_SUPPORTS_GTK_REKEY) && | 964 | ((dev->wiphy.wowlan->flags & WIPHY_WOWLAN_SUPPORTS_GTK_REKEY) && |
1005 | nla_put_flag(msg, NL80211_WOWLAN_TRIG_GTK_REKEY_SUPPORTED)) || | 965 | nla_put_flag(msg, NL80211_WOWLAN_TRIG_GTK_REKEY_SUPPORTED)) || |
1006 | ((dev->wiphy.wowlan.flags & WIPHY_WOWLAN_GTK_REKEY_FAILURE) && | 966 | ((dev->wiphy.wowlan->flags & WIPHY_WOWLAN_GTK_REKEY_FAILURE) && |
1007 | nla_put_flag(msg, NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE)) || | 967 | nla_put_flag(msg, NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE)) || |
1008 | ((dev->wiphy.wowlan.flags & WIPHY_WOWLAN_EAP_IDENTITY_REQ) && | 968 | ((dev->wiphy.wowlan->flags & WIPHY_WOWLAN_EAP_IDENTITY_REQ) && |
1009 | nla_put_flag(msg, NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST)) || | 969 | nla_put_flag(msg, NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST)) || |
1010 | ((dev->wiphy.wowlan.flags & WIPHY_WOWLAN_4WAY_HANDSHAKE) && | 970 | ((dev->wiphy.wowlan->flags & WIPHY_WOWLAN_4WAY_HANDSHAKE) && |
1011 | nla_put_flag(msg, NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE)) || | 971 | nla_put_flag(msg, NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE)) || |
1012 | ((dev->wiphy.wowlan.flags & WIPHY_WOWLAN_RFKILL_RELEASE) && | 972 | ((dev->wiphy.wowlan->flags & WIPHY_WOWLAN_RFKILL_RELEASE) && |
1013 | nla_put_flag(msg, NL80211_WOWLAN_TRIG_RFKILL_RELEASE))) | 973 | nla_put_flag(msg, NL80211_WOWLAN_TRIG_RFKILL_RELEASE))) |
1014 | return -ENOBUFS; | 974 | return -ENOBUFS; |
1015 | 975 | ||
1016 | if (dev->wiphy.wowlan.n_patterns) { | 976 | if (dev->wiphy.wowlan->n_patterns) { |
1017 | struct nl80211_wowlan_pattern_support pat = { | 977 | struct nl80211_wowlan_pattern_support pat = { |
1018 | .max_patterns = dev->wiphy.wowlan.n_patterns, | 978 | .max_patterns = dev->wiphy.wowlan->n_patterns, |
1019 | .min_pattern_len = dev->wiphy.wowlan.pattern_min_len, | 979 | .min_pattern_len = dev->wiphy.wowlan->pattern_min_len, |
1020 | .max_pattern_len = dev->wiphy.wowlan.pattern_max_len, | 980 | .max_pattern_len = dev->wiphy.wowlan->pattern_max_len, |
1021 | .max_pkt_offset = dev->wiphy.wowlan.max_pkt_offset, | 981 | .max_pkt_offset = dev->wiphy.wowlan->max_pkt_offset, |
1022 | }; | 982 | }; |
1023 | 983 | ||
1024 | if (nla_put(msg, NL80211_WOWLAN_TRIG_PKT_PATTERN, | 984 | if (nla_put(msg, NL80211_WOWLAN_TRIG_PKT_PATTERN, |
@@ -1151,10 +1111,16 @@ nl80211_send_mgmt_stypes(struct sk_buff *msg, | |||
1151 | return 0; | 1111 | return 0; |
1152 | } | 1112 | } |
1153 | 1113 | ||
1114 | struct nl80211_dump_wiphy_state { | ||
1115 | s64 filter_wiphy; | ||
1116 | long start; | ||
1117 | long split_start, band_start, chan_start; | ||
1118 | bool split; | ||
1119 | }; | ||
1120 | |||
1154 | static int nl80211_send_wiphy(struct cfg80211_registered_device *dev, | 1121 | static int nl80211_send_wiphy(struct cfg80211_registered_device *dev, |
1155 | struct sk_buff *msg, u32 portid, u32 seq, | 1122 | struct sk_buff *msg, u32 portid, u32 seq, |
1156 | int flags, bool split, long *split_start, | 1123 | int flags, struct nl80211_dump_wiphy_state *state) |
1157 | long *band_start, long *chan_start) | ||
1158 | { | 1124 | { |
1159 | void *hdr; | 1125 | void *hdr; |
1160 | struct nlattr *nl_bands, *nl_band; | 1126 | struct nlattr *nl_bands, *nl_band; |
@@ -1165,19 +1131,14 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev, | |||
1165 | int i; | 1131 | int i; |
1166 | const struct ieee80211_txrx_stypes *mgmt_stypes = | 1132 | const struct ieee80211_txrx_stypes *mgmt_stypes = |
1167 | dev->wiphy.mgmt_stypes; | 1133 | dev->wiphy.mgmt_stypes; |
1168 | long start = 0, start_chan = 0, start_band = 0; | ||
1169 | u32 features; | 1134 | u32 features; |
1170 | 1135 | ||
1171 | hdr = nl80211hdr_put(msg, portid, seq, flags, NL80211_CMD_NEW_WIPHY); | 1136 | hdr = nl80211hdr_put(msg, portid, seq, flags, NL80211_CMD_NEW_WIPHY); |
1172 | if (!hdr) | 1137 | if (!hdr) |
1173 | return -ENOBUFS; | 1138 | return -ENOBUFS; |
1174 | 1139 | ||
1175 | /* allow always using the variables */ | 1140 | if (WARN_ON(!state)) |
1176 | if (!split) { | 1141 | return -EINVAL; |
1177 | split_start = &start; | ||
1178 | band_start = &start_band; | ||
1179 | chan_start = &start_chan; | ||
1180 | } | ||
1181 | 1142 | ||
1182 | if (nla_put_u32(msg, NL80211_ATTR_WIPHY, dev->wiphy_idx) || | 1143 | if (nla_put_u32(msg, NL80211_ATTR_WIPHY, dev->wiphy_idx) || |
1183 | nla_put_string(msg, NL80211_ATTR_WIPHY_NAME, | 1144 | nla_put_string(msg, NL80211_ATTR_WIPHY_NAME, |
@@ -1186,7 +1147,7 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev, | |||
1186 | cfg80211_rdev_list_generation)) | 1147 | cfg80211_rdev_list_generation)) |
1187 | goto nla_put_failure; | 1148 | goto nla_put_failure; |
1188 | 1149 | ||
1189 | switch (*split_start) { | 1150 | switch (state->split_start) { |
1190 | case 0: | 1151 | case 0: |
1191 | if (nla_put_u8(msg, NL80211_ATTR_WIPHY_RETRY_SHORT, | 1152 | if (nla_put_u8(msg, NL80211_ATTR_WIPHY_RETRY_SHORT, |
1192 | dev->wiphy.retry_short) || | 1153 | dev->wiphy.retry_short) || |
@@ -1228,9 +1189,12 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev, | |||
1228 | if ((dev->wiphy.flags & WIPHY_FLAG_TDLS_EXTERNAL_SETUP) && | 1189 | if ((dev->wiphy.flags & WIPHY_FLAG_TDLS_EXTERNAL_SETUP) && |
1229 | nla_put_flag(msg, NL80211_ATTR_TDLS_EXTERNAL_SETUP)) | 1190 | nla_put_flag(msg, NL80211_ATTR_TDLS_EXTERNAL_SETUP)) |
1230 | goto nla_put_failure; | 1191 | goto nla_put_failure; |
1192 | if ((dev->wiphy.flags & WIPHY_FLAG_SUPPORTS_5_10_MHZ) && | ||
1193 | nla_put_flag(msg, WIPHY_FLAG_SUPPORTS_5_10_MHZ)) | ||
1194 | goto nla_put_failure; | ||
1231 | 1195 | ||
1232 | (*split_start)++; | 1196 | state->split_start++; |
1233 | if (split) | 1197 | if (state->split) |
1234 | break; | 1198 | break; |
1235 | case 1: | 1199 | case 1: |
1236 | if (nla_put(msg, NL80211_ATTR_CIPHER_SUITES, | 1200 | if (nla_put(msg, NL80211_ATTR_CIPHER_SUITES, |
@@ -1274,22 +1238,23 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev, | |||
1274 | } | 1238 | } |
1275 | } | 1239 | } |
1276 | 1240 | ||
1277 | (*split_start)++; | 1241 | state->split_start++; |
1278 | if (split) | 1242 | if (state->split) |
1279 | break; | 1243 | break; |
1280 | case 2: | 1244 | case 2: |
1281 | if (nl80211_put_iftypes(msg, NL80211_ATTR_SUPPORTED_IFTYPES, | 1245 | if (nl80211_put_iftypes(msg, NL80211_ATTR_SUPPORTED_IFTYPES, |
1282 | dev->wiphy.interface_modes)) | 1246 | dev->wiphy.interface_modes)) |
1283 | goto nla_put_failure; | 1247 | goto nla_put_failure; |
1284 | (*split_start)++; | 1248 | state->split_start++; |
1285 | if (split) | 1249 | if (state->split) |
1286 | break; | 1250 | break; |
1287 | case 3: | 1251 | case 3: |
1288 | nl_bands = nla_nest_start(msg, NL80211_ATTR_WIPHY_BANDS); | 1252 | nl_bands = nla_nest_start(msg, NL80211_ATTR_WIPHY_BANDS); |
1289 | if (!nl_bands) | 1253 | if (!nl_bands) |
1290 | goto nla_put_failure; | 1254 | goto nla_put_failure; |
1291 | 1255 | ||
1292 | for (band = *band_start; band < IEEE80211_NUM_BANDS; band++) { | 1256 | for (band = state->band_start; |
1257 | band < IEEE80211_NUM_BANDS; band++) { | ||
1293 | struct ieee80211_supported_band *sband; | 1258 | struct ieee80211_supported_band *sband; |
1294 | 1259 | ||
1295 | sband = dev->wiphy.bands[band]; | 1260 | sband = dev->wiphy.bands[band]; |
@@ -1301,12 +1266,12 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev, | |||
1301 | if (!nl_band) | 1266 | if (!nl_band) |
1302 | goto nla_put_failure; | 1267 | goto nla_put_failure; |
1303 | 1268 | ||
1304 | switch (*chan_start) { | 1269 | switch (state->chan_start) { |
1305 | case 0: | 1270 | case 0: |
1306 | if (nl80211_send_band_rateinfo(msg, sband)) | 1271 | if (nl80211_send_band_rateinfo(msg, sband)) |
1307 | goto nla_put_failure; | 1272 | goto nla_put_failure; |
1308 | (*chan_start)++; | 1273 | state->chan_start++; |
1309 | if (split) | 1274 | if (state->split) |
1310 | break; | 1275 | break; |
1311 | default: | 1276 | default: |
1312 | /* add frequencies */ | 1277 | /* add frequencies */ |
@@ -1315,7 +1280,7 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev, | |||
1315 | if (!nl_freqs) | 1280 | if (!nl_freqs) |
1316 | goto nla_put_failure; | 1281 | goto nla_put_failure; |
1317 | 1282 | ||
1318 | for (i = *chan_start - 1; | 1283 | for (i = state->chan_start - 1; |
1319 | i < sband->n_channels; | 1284 | i < sband->n_channels; |
1320 | i++) { | 1285 | i++) { |
1321 | nl_freq = nla_nest_start(msg, i); | 1286 | nl_freq = nla_nest_start(msg, i); |
@@ -1324,26 +1289,27 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev, | |||
1324 | 1289 | ||
1325 | chan = &sband->channels[i]; | 1290 | chan = &sband->channels[i]; |
1326 | 1291 | ||
1327 | if (nl80211_msg_put_channel(msg, chan, | 1292 | if (nl80211_msg_put_channel( |
1328 | split)) | 1293 | msg, chan, |
1294 | state->split)) | ||
1329 | goto nla_put_failure; | 1295 | goto nla_put_failure; |
1330 | 1296 | ||
1331 | nla_nest_end(msg, nl_freq); | 1297 | nla_nest_end(msg, nl_freq); |
1332 | if (split) | 1298 | if (state->split) |
1333 | break; | 1299 | break; |
1334 | } | 1300 | } |
1335 | if (i < sband->n_channels) | 1301 | if (i < sband->n_channels) |
1336 | *chan_start = i + 2; | 1302 | state->chan_start = i + 2; |
1337 | else | 1303 | else |
1338 | *chan_start = 0; | 1304 | state->chan_start = 0; |
1339 | nla_nest_end(msg, nl_freqs); | 1305 | nla_nest_end(msg, nl_freqs); |
1340 | } | 1306 | } |
1341 | 1307 | ||
1342 | nla_nest_end(msg, nl_band); | 1308 | nla_nest_end(msg, nl_band); |
1343 | 1309 | ||
1344 | if (split) { | 1310 | if (state->split) { |
1345 | /* start again here */ | 1311 | /* start again here */ |
1346 | if (*chan_start) | 1312 | if (state->chan_start) |
1347 | band--; | 1313 | band--; |
1348 | break; | 1314 | break; |
1349 | } | 1315 | } |
@@ -1351,14 +1317,14 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev, | |||
1351 | nla_nest_end(msg, nl_bands); | 1317 | nla_nest_end(msg, nl_bands); |
1352 | 1318 | ||
1353 | if (band < IEEE80211_NUM_BANDS) | 1319 | if (band < IEEE80211_NUM_BANDS) |
1354 | *band_start = band + 1; | 1320 | state->band_start = band + 1; |
1355 | else | 1321 | else |
1356 | *band_start = 0; | 1322 | state->band_start = 0; |
1357 | 1323 | ||
1358 | /* if bands & channels are done, continue outside */ | 1324 | /* if bands & channels are done, continue outside */ |
1359 | if (*band_start == 0 && *chan_start == 0) | 1325 | if (state->band_start == 0 && state->chan_start == 0) |
1360 | (*split_start)++; | 1326 | state->split_start++; |
1361 | if (split) | 1327 | if (state->split) |
1362 | break; | 1328 | break; |
1363 | case 4: | 1329 | case 4: |
1364 | nl_cmds = nla_nest_start(msg, NL80211_ATTR_SUPPORTED_COMMANDS); | 1330 | nl_cmds = nla_nest_start(msg, NL80211_ATTR_SUPPORTED_COMMANDS); |
@@ -1424,7 +1390,7 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev, | |||
1424 | } | 1390 | } |
1425 | CMD(start_p2p_device, START_P2P_DEVICE); | 1391 | CMD(start_p2p_device, START_P2P_DEVICE); |
1426 | CMD(set_mcast_rate, SET_MCAST_RATE); | 1392 | CMD(set_mcast_rate, SET_MCAST_RATE); |
1427 | if (split) { | 1393 | if (state->split) { |
1428 | CMD(crit_proto_start, CRIT_PROTOCOL_START); | 1394 | CMD(crit_proto_start, CRIT_PROTOCOL_START); |
1429 | CMD(crit_proto_stop, CRIT_PROTOCOL_STOP); | 1395 | CMD(crit_proto_stop, CRIT_PROTOCOL_STOP); |
1430 | } | 1396 | } |
@@ -1448,8 +1414,8 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev, | |||
1448 | } | 1414 | } |
1449 | 1415 | ||
1450 | nla_nest_end(msg, nl_cmds); | 1416 | nla_nest_end(msg, nl_cmds); |
1451 | (*split_start)++; | 1417 | state->split_start++; |
1452 | if (split) | 1418 | if (state->split) |
1453 | break; | 1419 | break; |
1454 | case 5: | 1420 | case 5: |
1455 | if (dev->ops->remain_on_channel && | 1421 | if (dev->ops->remain_on_channel && |
@@ -1465,29 +1431,30 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev, | |||
1465 | 1431 | ||
1466 | if (nl80211_send_mgmt_stypes(msg, mgmt_stypes)) | 1432 | if (nl80211_send_mgmt_stypes(msg, mgmt_stypes)) |
1467 | goto nla_put_failure; | 1433 | goto nla_put_failure; |
1468 | (*split_start)++; | 1434 | state->split_start++; |
1469 | if (split) | 1435 | if (state->split) |
1470 | break; | 1436 | break; |
1471 | case 6: | 1437 | case 6: |
1472 | #ifdef CONFIG_PM | 1438 | #ifdef CONFIG_PM |
1473 | if (nl80211_send_wowlan(msg, dev, split)) | 1439 | if (nl80211_send_wowlan(msg, dev, state->split)) |
1474 | goto nla_put_failure; | 1440 | goto nla_put_failure; |
1475 | (*split_start)++; | 1441 | state->split_start++; |
1476 | if (split) | 1442 | if (state->split) |
1477 | break; | 1443 | break; |
1478 | #else | 1444 | #else |
1479 | (*split_start)++; | 1445 | state->split_start++; |
1480 | #endif | 1446 | #endif |
1481 | case 7: | 1447 | case 7: |
1482 | if (nl80211_put_iftypes(msg, NL80211_ATTR_SOFTWARE_IFTYPES, | 1448 | if (nl80211_put_iftypes(msg, NL80211_ATTR_SOFTWARE_IFTYPES, |
1483 | dev->wiphy.software_iftypes)) | 1449 | dev->wiphy.software_iftypes)) |
1484 | goto nla_put_failure; | 1450 | goto nla_put_failure; |
1485 | 1451 | ||
1486 | if (nl80211_put_iface_combinations(&dev->wiphy, msg, split)) | 1452 | if (nl80211_put_iface_combinations(&dev->wiphy, msg, |
1453 | state->split)) | ||
1487 | goto nla_put_failure; | 1454 | goto nla_put_failure; |
1488 | 1455 | ||
1489 | (*split_start)++; | 1456 | state->split_start++; |
1490 | if (split) | 1457 | if (state->split) |
1491 | break; | 1458 | break; |
1492 | case 8: | 1459 | case 8: |
1493 | if ((dev->wiphy.flags & WIPHY_FLAG_HAVE_AP_SME) && | 1460 | if ((dev->wiphy.flags & WIPHY_FLAG_HAVE_AP_SME) && |
@@ -1501,7 +1468,7 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev, | |||
1501 | * dump is split, otherwise it makes it too big. Therefore | 1468 | * dump is split, otherwise it makes it too big. Therefore |
1502 | * only advertise it in that case. | 1469 | * only advertise it in that case. |
1503 | */ | 1470 | */ |
1504 | if (split) | 1471 | if (state->split) |
1505 | features |= NL80211_FEATURE_ADVERTISE_CHAN_LIMITS; | 1472 | features |= NL80211_FEATURE_ADVERTISE_CHAN_LIMITS; |
1506 | if (nla_put_u32(msg, NL80211_ATTR_FEATURE_FLAGS, features)) | 1473 | if (nla_put_u32(msg, NL80211_ATTR_FEATURE_FLAGS, features)) |
1507 | goto nla_put_failure; | 1474 | goto nla_put_failure; |
@@ -1528,7 +1495,7 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev, | |||
1528 | * case we'll continue with more data in the next round, | 1495 | * case we'll continue with more data in the next round, |
1529 | * but break unconditionally so unsplit data stops here. | 1496 | * but break unconditionally so unsplit data stops here. |
1530 | */ | 1497 | */ |
1531 | (*split_start)++; | 1498 | state->split_start++; |
1532 | break; | 1499 | break; |
1533 | case 9: | 1500 | case 9: |
1534 | if (dev->wiphy.extended_capabilities && | 1501 | if (dev->wiphy.extended_capabilities && |
@@ -1547,7 +1514,7 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev, | |||
1547 | goto nla_put_failure; | 1514 | goto nla_put_failure; |
1548 | 1515 | ||
1549 | /* done */ | 1516 | /* done */ |
1550 | *split_start = 0; | 1517 | state->split_start = 0; |
1551 | break; | 1518 | break; |
1552 | } | 1519 | } |
1553 | return genlmsg_end(msg, hdr); | 1520 | return genlmsg_end(msg, hdr); |
@@ -1557,66 +1524,78 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev, | |||
1557 | return -EMSGSIZE; | 1524 | return -EMSGSIZE; |
1558 | } | 1525 | } |
1559 | 1526 | ||
1527 | static int nl80211_dump_wiphy_parse(struct sk_buff *skb, | ||
1528 | struct netlink_callback *cb, | ||
1529 | struct nl80211_dump_wiphy_state *state) | ||
1530 | { | ||
1531 | struct nlattr **tb = nl80211_fam.attrbuf; | ||
1532 | int ret = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize, | ||
1533 | tb, nl80211_fam.maxattr, nl80211_policy); | ||
1534 | /* ignore parse errors for backward compatibility */ | ||
1535 | if (ret) | ||
1536 | return 0; | ||
1537 | |||
1538 | state->split = tb[NL80211_ATTR_SPLIT_WIPHY_DUMP]; | ||
1539 | if (tb[NL80211_ATTR_WIPHY]) | ||
1540 | state->filter_wiphy = nla_get_u32(tb[NL80211_ATTR_WIPHY]); | ||
1541 | if (tb[NL80211_ATTR_WDEV]) | ||
1542 | state->filter_wiphy = nla_get_u64(tb[NL80211_ATTR_WDEV]) >> 32; | ||
1543 | if (tb[NL80211_ATTR_IFINDEX]) { | ||
1544 | struct net_device *netdev; | ||
1545 | struct cfg80211_registered_device *rdev; | ||
1546 | int ifidx = nla_get_u32(tb[NL80211_ATTR_IFINDEX]); | ||
1547 | |||
1548 | netdev = dev_get_by_index(sock_net(skb->sk), ifidx); | ||
1549 | if (!netdev) | ||
1550 | return -ENODEV; | ||
1551 | if (netdev->ieee80211_ptr) { | ||
1552 | rdev = wiphy_to_dev( | ||
1553 | netdev->ieee80211_ptr->wiphy); | ||
1554 | state->filter_wiphy = rdev->wiphy_idx; | ||
1555 | } | ||
1556 | dev_put(netdev); | ||
1557 | } | ||
1558 | |||
1559 | return 0; | ||
1560 | } | ||
1561 | |||
1560 | static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb) | 1562 | static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb) |
1561 | { | 1563 | { |
1562 | int idx = 0, ret; | 1564 | int idx = 0, ret; |
1563 | int start = cb->args[0]; | 1565 | struct nl80211_dump_wiphy_state *state = (void *)cb->args[0]; |
1564 | struct cfg80211_registered_device *dev; | 1566 | struct cfg80211_registered_device *dev; |
1565 | s64 filter_wiphy = -1; | ||
1566 | bool split = false; | ||
1567 | struct nlattr **tb; | ||
1568 | int res; | ||
1569 | 1567 | ||
1570 | /* will be zeroed in nlmsg_parse() */ | 1568 | rtnl_lock(); |
1571 | tb = kmalloc(sizeof(*tb) * (NL80211_ATTR_MAX + 1), GFP_KERNEL); | 1569 | if (!state) { |
1572 | if (!tb) | 1570 | state = kzalloc(sizeof(*state), GFP_KERNEL); |
1573 | return -ENOMEM; | 1571 | if (!state) { |
1574 | 1572 | rtnl_unlock(); | |
1575 | mutex_lock(&cfg80211_mutex); | 1573 | return -ENOMEM; |
1576 | res = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize, | 1574 | } |
1577 | tb, NL80211_ATTR_MAX, nl80211_policy); | 1575 | state->filter_wiphy = -1; |
1578 | if (res == 0) { | 1576 | ret = nl80211_dump_wiphy_parse(skb, cb, state); |
1579 | split = tb[NL80211_ATTR_SPLIT_WIPHY_DUMP]; | 1577 | if (ret) { |
1580 | if (tb[NL80211_ATTR_WIPHY]) | 1578 | kfree(state); |
1581 | filter_wiphy = nla_get_u32(tb[NL80211_ATTR_WIPHY]); | 1579 | rtnl_unlock(); |
1582 | if (tb[NL80211_ATTR_WDEV]) | 1580 | return ret; |
1583 | filter_wiphy = nla_get_u64(tb[NL80211_ATTR_WDEV]) >> 32; | ||
1584 | if (tb[NL80211_ATTR_IFINDEX]) { | ||
1585 | struct net_device *netdev; | ||
1586 | int ifidx = nla_get_u32(tb[NL80211_ATTR_IFINDEX]); | ||
1587 | |||
1588 | netdev = dev_get_by_index(sock_net(skb->sk), ifidx); | ||
1589 | if (!netdev) { | ||
1590 | mutex_unlock(&cfg80211_mutex); | ||
1591 | kfree(tb); | ||
1592 | return -ENODEV; | ||
1593 | } | ||
1594 | if (netdev->ieee80211_ptr) { | ||
1595 | dev = wiphy_to_dev( | ||
1596 | netdev->ieee80211_ptr->wiphy); | ||
1597 | filter_wiphy = dev->wiphy_idx; | ||
1598 | } | ||
1599 | dev_put(netdev); | ||
1600 | } | 1581 | } |
1582 | cb->args[0] = (long)state; | ||
1601 | } | 1583 | } |
1602 | kfree(tb); | ||
1603 | 1584 | ||
1604 | list_for_each_entry(dev, &cfg80211_rdev_list, list) { | 1585 | list_for_each_entry(dev, &cfg80211_rdev_list, list) { |
1605 | if (!net_eq(wiphy_net(&dev->wiphy), sock_net(skb->sk))) | 1586 | if (!net_eq(wiphy_net(&dev->wiphy), sock_net(skb->sk))) |
1606 | continue; | 1587 | continue; |
1607 | if (++idx <= start) | 1588 | if (++idx <= state->start) |
1608 | continue; | 1589 | continue; |
1609 | if (filter_wiphy != -1 && dev->wiphy_idx != filter_wiphy) | 1590 | if (state->filter_wiphy != -1 && |
1591 | state->filter_wiphy != dev->wiphy_idx) | ||
1610 | continue; | 1592 | continue; |
1611 | /* attempt to fit multiple wiphy data chunks into the skb */ | 1593 | /* attempt to fit multiple wiphy data chunks into the skb */ |
1612 | do { | 1594 | do { |
1613 | ret = nl80211_send_wiphy(dev, skb, | 1595 | ret = nl80211_send_wiphy(dev, skb, |
1614 | NETLINK_CB(cb->skb).portid, | 1596 | NETLINK_CB(cb->skb).portid, |
1615 | cb->nlh->nlmsg_seq, | 1597 | cb->nlh->nlmsg_seq, |
1616 | NLM_F_MULTI, | 1598 | NLM_F_MULTI, state); |
1617 | split, &cb->args[1], | ||
1618 | &cb->args[2], | ||
1619 | &cb->args[3]); | ||
1620 | if (ret < 0) { | 1599 | if (ret < 0) { |
1621 | /* | 1600 | /* |
1622 | * If sending the wiphy data didn't fit (ENOBUFS | 1601 | * If sending the wiphy data didn't fit (ENOBUFS |
@@ -1635,33 +1614,40 @@ static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb) | |||
1635 | !skb->len && | 1614 | !skb->len && |
1636 | cb->min_dump_alloc < 4096) { | 1615 | cb->min_dump_alloc < 4096) { |
1637 | cb->min_dump_alloc = 4096; | 1616 | cb->min_dump_alloc = 4096; |
1638 | mutex_unlock(&cfg80211_mutex); | 1617 | rtnl_unlock(); |
1639 | return 1; | 1618 | return 1; |
1640 | } | 1619 | } |
1641 | idx--; | 1620 | idx--; |
1642 | break; | 1621 | break; |
1643 | } | 1622 | } |
1644 | } while (cb->args[1] > 0); | 1623 | } while (state->split_start > 0); |
1645 | break; | 1624 | break; |
1646 | } | 1625 | } |
1647 | mutex_unlock(&cfg80211_mutex); | 1626 | rtnl_unlock(); |
1648 | 1627 | ||
1649 | cb->args[0] = idx; | 1628 | state->start = idx; |
1650 | 1629 | ||
1651 | return skb->len; | 1630 | return skb->len; |
1652 | } | 1631 | } |
1653 | 1632 | ||
1633 | static int nl80211_dump_wiphy_done(struct netlink_callback *cb) | ||
1634 | { | ||
1635 | kfree((void *)cb->args[0]); | ||
1636 | return 0; | ||
1637 | } | ||
1638 | |||
1654 | static int nl80211_get_wiphy(struct sk_buff *skb, struct genl_info *info) | 1639 | static int nl80211_get_wiphy(struct sk_buff *skb, struct genl_info *info) |
1655 | { | 1640 | { |
1656 | struct sk_buff *msg; | 1641 | struct sk_buff *msg; |
1657 | struct cfg80211_registered_device *dev = info->user_ptr[0]; | 1642 | struct cfg80211_registered_device *dev = info->user_ptr[0]; |
1643 | struct nl80211_dump_wiphy_state state = {}; | ||
1658 | 1644 | ||
1659 | msg = nlmsg_new(4096, GFP_KERNEL); | 1645 | msg = nlmsg_new(4096, GFP_KERNEL); |
1660 | if (!msg) | 1646 | if (!msg) |
1661 | return -ENOMEM; | 1647 | return -ENOMEM; |
1662 | 1648 | ||
1663 | if (nl80211_send_wiphy(dev, msg, info->snd_portid, info->snd_seq, 0, | 1649 | if (nl80211_send_wiphy(dev, msg, info->snd_portid, info->snd_seq, 0, |
1664 | false, NULL, NULL, NULL) < 0) { | 1650 | &state) < 0) { |
1665 | nlmsg_free(msg); | 1651 | nlmsg_free(msg); |
1666 | return -ENOBUFS; | 1652 | return -ENOBUFS; |
1667 | } | 1653 | } |
@@ -1778,6 +1764,11 @@ static int nl80211_parse_chandef(struct cfg80211_registered_device *rdev, | |||
1778 | IEEE80211_CHAN_DISABLED)) | 1764 | IEEE80211_CHAN_DISABLED)) |
1779 | return -EINVAL; | 1765 | return -EINVAL; |
1780 | 1766 | ||
1767 | if ((chandef->width == NL80211_CHAN_WIDTH_5 || | ||
1768 | chandef->width == NL80211_CHAN_WIDTH_10) && | ||
1769 | !(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_5_10_MHZ)) | ||
1770 | return -EINVAL; | ||
1771 | |||
1781 | return 0; | 1772 | return 0; |
1782 | } | 1773 | } |
1783 | 1774 | ||
@@ -1799,7 +1790,6 @@ static int __nl80211_set_channel(struct cfg80211_registered_device *rdev, | |||
1799 | if (result) | 1790 | if (result) |
1800 | return result; | 1791 | return result; |
1801 | 1792 | ||
1802 | mutex_lock(&rdev->devlist_mtx); | ||
1803 | switch (iftype) { | 1793 | switch (iftype) { |
1804 | case NL80211_IFTYPE_AP: | 1794 | case NL80211_IFTYPE_AP: |
1805 | case NL80211_IFTYPE_P2P_GO: | 1795 | case NL80211_IFTYPE_P2P_GO: |
@@ -1823,7 +1813,6 @@ static int __nl80211_set_channel(struct cfg80211_registered_device *rdev, | |||
1823 | default: | 1813 | default: |
1824 | result = -EINVAL; | 1814 | result = -EINVAL; |
1825 | } | 1815 | } |
1826 | mutex_unlock(&rdev->devlist_mtx); | ||
1827 | 1816 | ||
1828 | return result; | 1817 | return result; |
1829 | } | 1818 | } |
@@ -1872,6 +1861,8 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) | |||
1872 | u32 frag_threshold = 0, rts_threshold = 0; | 1861 | u32 frag_threshold = 0, rts_threshold = 0; |
1873 | u8 coverage_class = 0; | 1862 | u8 coverage_class = 0; |
1874 | 1863 | ||
1864 | ASSERT_RTNL(); | ||
1865 | |||
1875 | /* | 1866 | /* |
1876 | * Try to find the wiphy and netdev. Normally this | 1867 | * Try to find the wiphy and netdev. Normally this |
1877 | * function shouldn't need the netdev, but this is | 1868 | * function shouldn't need the netdev, but this is |
@@ -1881,31 +1872,25 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) | |||
1881 | * also passed a netdev to set_wiphy, so that it is | 1872 | * also passed a netdev to set_wiphy, so that it is |
1882 | * possible to let that go to the right netdev! | 1873 | * possible to let that go to the right netdev! |
1883 | */ | 1874 | */ |
1884 | mutex_lock(&cfg80211_mutex); | ||
1885 | 1875 | ||
1886 | if (info->attrs[NL80211_ATTR_IFINDEX]) { | 1876 | if (info->attrs[NL80211_ATTR_IFINDEX]) { |
1887 | int ifindex = nla_get_u32(info->attrs[NL80211_ATTR_IFINDEX]); | 1877 | int ifindex = nla_get_u32(info->attrs[NL80211_ATTR_IFINDEX]); |
1888 | 1878 | ||
1889 | netdev = dev_get_by_index(genl_info_net(info), ifindex); | 1879 | netdev = dev_get_by_index(genl_info_net(info), ifindex); |
1890 | if (netdev && netdev->ieee80211_ptr) { | 1880 | if (netdev && netdev->ieee80211_ptr) |
1891 | rdev = wiphy_to_dev(netdev->ieee80211_ptr->wiphy); | 1881 | rdev = wiphy_to_dev(netdev->ieee80211_ptr->wiphy); |
1892 | mutex_lock(&rdev->mtx); | 1882 | else |
1893 | } else | ||
1894 | netdev = NULL; | 1883 | netdev = NULL; |
1895 | } | 1884 | } |
1896 | 1885 | ||
1897 | if (!netdev) { | 1886 | if (!netdev) { |
1898 | rdev = __cfg80211_rdev_from_attrs(genl_info_net(info), | 1887 | rdev = __cfg80211_rdev_from_attrs(genl_info_net(info), |
1899 | info->attrs); | 1888 | info->attrs); |
1900 | if (IS_ERR(rdev)) { | 1889 | if (IS_ERR(rdev)) |
1901 | mutex_unlock(&cfg80211_mutex); | ||
1902 | return PTR_ERR(rdev); | 1890 | return PTR_ERR(rdev); |
1903 | } | ||
1904 | wdev = NULL; | 1891 | wdev = NULL; |
1905 | netdev = NULL; | 1892 | netdev = NULL; |
1906 | result = 0; | 1893 | result = 0; |
1907 | |||
1908 | mutex_lock(&rdev->mtx); | ||
1909 | } else | 1894 | } else |
1910 | wdev = netdev->ieee80211_ptr; | 1895 | wdev = netdev->ieee80211_ptr; |
1911 | 1896 | ||
@@ -1918,8 +1903,6 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) | |||
1918 | result = cfg80211_dev_rename( | 1903 | result = cfg80211_dev_rename( |
1919 | rdev, nla_data(info->attrs[NL80211_ATTR_WIPHY_NAME])); | 1904 | rdev, nla_data(info->attrs[NL80211_ATTR_WIPHY_NAME])); |
1920 | 1905 | ||
1921 | mutex_unlock(&cfg80211_mutex); | ||
1922 | |||
1923 | if (result) | 1906 | if (result) |
1924 | goto bad_res; | 1907 | goto bad_res; |
1925 | 1908 | ||
@@ -2126,7 +2109,6 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) | |||
2126 | } | 2109 | } |
2127 | 2110 | ||
2128 | bad_res: | 2111 | bad_res: |
2129 | mutex_unlock(&rdev->mtx); | ||
2130 | if (netdev) | 2112 | if (netdev) |
2131 | dev_put(netdev); | 2113 | dev_put(netdev); |
2132 | return result; | 2114 | return result; |
@@ -2224,7 +2206,7 @@ static int nl80211_dump_interface(struct sk_buff *skb, struct netlink_callback * | |||
2224 | struct cfg80211_registered_device *rdev; | 2206 | struct cfg80211_registered_device *rdev; |
2225 | struct wireless_dev *wdev; | 2207 | struct wireless_dev *wdev; |
2226 | 2208 | ||
2227 | mutex_lock(&cfg80211_mutex); | 2209 | rtnl_lock(); |
2228 | list_for_each_entry(rdev, &cfg80211_rdev_list, list) { | 2210 | list_for_each_entry(rdev, &cfg80211_rdev_list, list) { |
2229 | if (!net_eq(wiphy_net(&rdev->wiphy), sock_net(skb->sk))) | 2211 | if (!net_eq(wiphy_net(&rdev->wiphy), sock_net(skb->sk))) |
2230 | continue; | 2212 | continue; |
@@ -2234,7 +2216,6 @@ static int nl80211_dump_interface(struct sk_buff *skb, struct netlink_callback * | |||
2234 | } | 2216 | } |
2235 | if_idx = 0; | 2217 | if_idx = 0; |
2236 | 2218 | ||
2237 | mutex_lock(&rdev->devlist_mtx); | ||
2238 | list_for_each_entry(wdev, &rdev->wdev_list, list) { | 2219 | list_for_each_entry(wdev, &rdev->wdev_list, list) { |
2239 | if (if_idx < if_start) { | 2220 | if (if_idx < if_start) { |
2240 | if_idx++; | 2221 | if_idx++; |
@@ -2243,17 +2224,15 @@ static int nl80211_dump_interface(struct sk_buff *skb, struct netlink_callback * | |||
2243 | if (nl80211_send_iface(skb, NETLINK_CB(cb->skb).portid, | 2224 | if (nl80211_send_iface(skb, NETLINK_CB(cb->skb).portid, |
2244 | cb->nlh->nlmsg_seq, NLM_F_MULTI, | 2225 | cb->nlh->nlmsg_seq, NLM_F_MULTI, |
2245 | rdev, wdev) < 0) { | 2226 | rdev, wdev) < 0) { |
2246 | mutex_unlock(&rdev->devlist_mtx); | ||
2247 | goto out; | 2227 | goto out; |
2248 | } | 2228 | } |
2249 | if_idx++; | 2229 | if_idx++; |
2250 | } | 2230 | } |
2251 | mutex_unlock(&rdev->devlist_mtx); | ||
2252 | 2231 | ||
2253 | wp_idx++; | 2232 | wp_idx++; |
2254 | } | 2233 | } |
2255 | out: | 2234 | out: |
2256 | mutex_unlock(&cfg80211_mutex); | 2235 | rtnl_unlock(); |
2257 | 2236 | ||
2258 | cb->args[0] = wp_idx; | 2237 | cb->args[0] = wp_idx; |
2259 | cb->args[1] = if_idx; | 2238 | cb->args[1] = if_idx; |
@@ -2286,6 +2265,7 @@ static const struct nla_policy mntr_flags_policy[NL80211_MNTR_FLAG_MAX + 1] = { | |||
2286 | [NL80211_MNTR_FLAG_CONTROL] = { .type = NLA_FLAG }, | 2265 | [NL80211_MNTR_FLAG_CONTROL] = { .type = NLA_FLAG }, |
2287 | [NL80211_MNTR_FLAG_OTHER_BSS] = { .type = NLA_FLAG }, | 2266 | [NL80211_MNTR_FLAG_OTHER_BSS] = { .type = NLA_FLAG }, |
2288 | [NL80211_MNTR_FLAG_COOK_FRAMES] = { .type = NLA_FLAG }, | 2267 | [NL80211_MNTR_FLAG_COOK_FRAMES] = { .type = NLA_FLAG }, |
2268 | [NL80211_MNTR_FLAG_ACTIVE] = { .type = NLA_FLAG }, | ||
2289 | }; | 2269 | }; |
2290 | 2270 | ||
2291 | static int parse_monitor_flags(struct nlattr *nla, u32 *mntrflags) | 2271 | static int parse_monitor_flags(struct nlattr *nla, u32 *mntrflags) |
@@ -2397,6 +2377,10 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info) | |||
2397 | change = true; | 2377 | change = true; |
2398 | } | 2378 | } |
2399 | 2379 | ||
2380 | if (flags && (*flags & NL80211_MNTR_FLAG_ACTIVE) && | ||
2381 | !(rdev->wiphy.features & NL80211_FEATURE_ACTIVE_MONITOR)) | ||
2382 | return -EOPNOTSUPP; | ||
2383 | |||
2400 | if (change) | 2384 | if (change) |
2401 | err = cfg80211_change_iface(rdev, dev, ntype, flags, ¶ms); | 2385 | err = cfg80211_change_iface(rdev, dev, ntype, flags, ¶ms); |
2402 | else | 2386 | else |
@@ -2454,6 +2438,11 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info) | |||
2454 | err = parse_monitor_flags(type == NL80211_IFTYPE_MONITOR ? | 2438 | err = parse_monitor_flags(type == NL80211_IFTYPE_MONITOR ? |
2455 | info->attrs[NL80211_ATTR_MNTR_FLAGS] : NULL, | 2439 | info->attrs[NL80211_ATTR_MNTR_FLAGS] : NULL, |
2456 | &flags); | 2440 | &flags); |
2441 | |||
2442 | if (!err && (flags & NL80211_MNTR_FLAG_ACTIVE) && | ||
2443 | !(rdev->wiphy.features & NL80211_FEATURE_ACTIVE_MONITOR)) | ||
2444 | return -EOPNOTSUPP; | ||
2445 | |||
2457 | wdev = rdev_add_virtual_intf(rdev, | 2446 | wdev = rdev_add_virtual_intf(rdev, |
2458 | nla_data(info->attrs[NL80211_ATTR_IFNAME]), | 2447 | nla_data(info->attrs[NL80211_ATTR_IFNAME]), |
2459 | type, err ? NULL : &flags, ¶ms); | 2448 | type, err ? NULL : &flags, ¶ms); |
@@ -2486,11 +2475,9 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info) | |||
2486 | INIT_LIST_HEAD(&wdev->mgmt_registrations); | 2475 | INIT_LIST_HEAD(&wdev->mgmt_registrations); |
2487 | spin_lock_init(&wdev->mgmt_registrations_lock); | 2476 | spin_lock_init(&wdev->mgmt_registrations_lock); |
2488 | 2477 | ||
2489 | mutex_lock(&rdev->devlist_mtx); | ||
2490 | wdev->identifier = ++rdev->wdev_id; | 2478 | wdev->identifier = ++rdev->wdev_id; |
2491 | list_add_rcu(&wdev->list, &rdev->wdev_list); | 2479 | list_add_rcu(&wdev->list, &rdev->wdev_list); |
2492 | rdev->devlist_generation++; | 2480 | rdev->devlist_generation++; |
2493 | mutex_unlock(&rdev->devlist_mtx); | ||
2494 | break; | 2481 | break; |
2495 | default: | 2482 | default: |
2496 | break; | 2483 | break; |
@@ -2933,61 +2920,58 @@ static int nl80211_set_mac_acl(struct sk_buff *skb, struct genl_info *info) | |||
2933 | return err; | 2920 | return err; |
2934 | } | 2921 | } |
2935 | 2922 | ||
2936 | static int nl80211_parse_beacon(struct genl_info *info, | 2923 | static int nl80211_parse_beacon(struct nlattr *attrs[], |
2937 | struct cfg80211_beacon_data *bcn) | 2924 | struct cfg80211_beacon_data *bcn) |
2938 | { | 2925 | { |
2939 | bool haveinfo = false; | 2926 | bool haveinfo = false; |
2940 | 2927 | ||
2941 | if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_BEACON_TAIL]) || | 2928 | if (!is_valid_ie_attr(attrs[NL80211_ATTR_BEACON_TAIL]) || |
2942 | !is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]) || | 2929 | !is_valid_ie_attr(attrs[NL80211_ATTR_IE]) || |
2943 | !is_valid_ie_attr(info->attrs[NL80211_ATTR_IE_PROBE_RESP]) || | 2930 | !is_valid_ie_attr(attrs[NL80211_ATTR_IE_PROBE_RESP]) || |
2944 | !is_valid_ie_attr(info->attrs[NL80211_ATTR_IE_ASSOC_RESP])) | 2931 | !is_valid_ie_attr(attrs[NL80211_ATTR_IE_ASSOC_RESP])) |
2945 | return -EINVAL; | 2932 | return -EINVAL; |
2946 | 2933 | ||
2947 | memset(bcn, 0, sizeof(*bcn)); | 2934 | memset(bcn, 0, sizeof(*bcn)); |
2948 | 2935 | ||
2949 | if (info->attrs[NL80211_ATTR_BEACON_HEAD]) { | 2936 | if (attrs[NL80211_ATTR_BEACON_HEAD]) { |
2950 | bcn->head = nla_data(info->attrs[NL80211_ATTR_BEACON_HEAD]); | 2937 | bcn->head = nla_data(attrs[NL80211_ATTR_BEACON_HEAD]); |
2951 | bcn->head_len = nla_len(info->attrs[NL80211_ATTR_BEACON_HEAD]); | 2938 | bcn->head_len = nla_len(attrs[NL80211_ATTR_BEACON_HEAD]); |
2952 | if (!bcn->head_len) | 2939 | if (!bcn->head_len) |
2953 | return -EINVAL; | 2940 | return -EINVAL; |
2954 | haveinfo = true; | 2941 | haveinfo = true; |
2955 | } | 2942 | } |
2956 | 2943 | ||
2957 | if (info->attrs[NL80211_ATTR_BEACON_TAIL]) { | 2944 | if (attrs[NL80211_ATTR_BEACON_TAIL]) { |
2958 | bcn->tail = nla_data(info->attrs[NL80211_ATTR_BEACON_TAIL]); | 2945 | bcn->tail = nla_data(attrs[NL80211_ATTR_BEACON_TAIL]); |
2959 | bcn->tail_len = | 2946 | bcn->tail_len = nla_len(attrs[NL80211_ATTR_BEACON_TAIL]); |
2960 | nla_len(info->attrs[NL80211_ATTR_BEACON_TAIL]); | ||
2961 | haveinfo = true; | 2947 | haveinfo = true; |
2962 | } | 2948 | } |
2963 | 2949 | ||
2964 | if (!haveinfo) | 2950 | if (!haveinfo) |
2965 | return -EINVAL; | 2951 | return -EINVAL; |
2966 | 2952 | ||
2967 | if (info->attrs[NL80211_ATTR_IE]) { | 2953 | if (attrs[NL80211_ATTR_IE]) { |
2968 | bcn->beacon_ies = nla_data(info->attrs[NL80211_ATTR_IE]); | 2954 | bcn->beacon_ies = nla_data(attrs[NL80211_ATTR_IE]); |
2969 | bcn->beacon_ies_len = nla_len(info->attrs[NL80211_ATTR_IE]); | 2955 | bcn->beacon_ies_len = nla_len(attrs[NL80211_ATTR_IE]); |
2970 | } | 2956 | } |
2971 | 2957 | ||
2972 | if (info->attrs[NL80211_ATTR_IE_PROBE_RESP]) { | 2958 | if (attrs[NL80211_ATTR_IE_PROBE_RESP]) { |
2973 | bcn->proberesp_ies = | 2959 | bcn->proberesp_ies = |
2974 | nla_data(info->attrs[NL80211_ATTR_IE_PROBE_RESP]); | 2960 | nla_data(attrs[NL80211_ATTR_IE_PROBE_RESP]); |
2975 | bcn->proberesp_ies_len = | 2961 | bcn->proberesp_ies_len = |
2976 | nla_len(info->attrs[NL80211_ATTR_IE_PROBE_RESP]); | 2962 | nla_len(attrs[NL80211_ATTR_IE_PROBE_RESP]); |
2977 | } | 2963 | } |
2978 | 2964 | ||
2979 | if (info->attrs[NL80211_ATTR_IE_ASSOC_RESP]) { | 2965 | if (attrs[NL80211_ATTR_IE_ASSOC_RESP]) { |
2980 | bcn->assocresp_ies = | 2966 | bcn->assocresp_ies = |
2981 | nla_data(info->attrs[NL80211_ATTR_IE_ASSOC_RESP]); | 2967 | nla_data(attrs[NL80211_ATTR_IE_ASSOC_RESP]); |
2982 | bcn->assocresp_ies_len = | 2968 | bcn->assocresp_ies_len = |
2983 | nla_len(info->attrs[NL80211_ATTR_IE_ASSOC_RESP]); | 2969 | nla_len(attrs[NL80211_ATTR_IE_ASSOC_RESP]); |
2984 | } | 2970 | } |
2985 | 2971 | ||
2986 | if (info->attrs[NL80211_ATTR_PROBE_RESP]) { | 2972 | if (attrs[NL80211_ATTR_PROBE_RESP]) { |
2987 | bcn->probe_resp = | 2973 | bcn->probe_resp = nla_data(attrs[NL80211_ATTR_PROBE_RESP]); |
2988 | nla_data(info->attrs[NL80211_ATTR_PROBE_RESP]); | 2974 | bcn->probe_resp_len = nla_len(attrs[NL80211_ATTR_PROBE_RESP]); |
2989 | bcn->probe_resp_len = | ||
2990 | nla_len(info->attrs[NL80211_ATTR_PROBE_RESP]); | ||
2991 | } | 2975 | } |
2992 | 2976 | ||
2993 | return 0; | 2977 | return 0; |
@@ -2999,8 +2983,6 @@ static bool nl80211_get_ap_channel(struct cfg80211_registered_device *rdev, | |||
2999 | struct wireless_dev *wdev; | 2983 | struct wireless_dev *wdev; |
3000 | bool ret = false; | 2984 | bool ret = false; |
3001 | 2985 | ||
3002 | mutex_lock(&rdev->devlist_mtx); | ||
3003 | |||
3004 | list_for_each_entry(wdev, &rdev->wdev_list, list) { | 2986 | list_for_each_entry(wdev, &rdev->wdev_list, list) { |
3005 | if (wdev->iftype != NL80211_IFTYPE_AP && | 2987 | if (wdev->iftype != NL80211_IFTYPE_AP && |
3006 | wdev->iftype != NL80211_IFTYPE_P2P_GO) | 2988 | wdev->iftype != NL80211_IFTYPE_P2P_GO) |
@@ -3014,8 +2996,6 @@ static bool nl80211_get_ap_channel(struct cfg80211_registered_device *rdev, | |||
3014 | break; | 2996 | break; |
3015 | } | 2997 | } |
3016 | 2998 | ||
3017 | mutex_unlock(&rdev->devlist_mtx); | ||
3018 | |||
3019 | return ret; | 2999 | return ret; |
3020 | } | 3000 | } |
3021 | 3001 | ||
@@ -3070,7 +3050,7 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info) | |||
3070 | !info->attrs[NL80211_ATTR_BEACON_HEAD]) | 3050 | !info->attrs[NL80211_ATTR_BEACON_HEAD]) |
3071 | return -EINVAL; | 3051 | return -EINVAL; |
3072 | 3052 | ||
3073 | err = nl80211_parse_beacon(info, ¶ms.beacon); | 3053 | err = nl80211_parse_beacon(info->attrs, ¶ms.beacon); |
3074 | if (err) | 3054 | if (err) |
3075 | return err; | 3055 | return err; |
3076 | 3056 | ||
@@ -3177,13 +3157,10 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info) | |||
3177 | params.radar_required = true; | 3157 | params.radar_required = true; |
3178 | } | 3158 | } |
3179 | 3159 | ||
3180 | mutex_lock(&rdev->devlist_mtx); | ||
3181 | err = cfg80211_can_use_iftype_chan(rdev, wdev, wdev->iftype, | 3160 | err = cfg80211_can_use_iftype_chan(rdev, wdev, wdev->iftype, |
3182 | params.chandef.chan, | 3161 | params.chandef.chan, |
3183 | CHAN_MODE_SHARED, | 3162 | CHAN_MODE_SHARED, |
3184 | radar_detect_width); | 3163 | radar_detect_width); |
3185 | mutex_unlock(&rdev->devlist_mtx); | ||
3186 | |||
3187 | if (err) | 3164 | if (err) |
3188 | return err; | 3165 | return err; |
3189 | 3166 | ||
@@ -3225,7 +3202,7 @@ static int nl80211_set_beacon(struct sk_buff *skb, struct genl_info *info) | |||
3225 | if (!wdev->beacon_interval) | 3202 | if (!wdev->beacon_interval) |
3226 | return -EINVAL; | 3203 | return -EINVAL; |
3227 | 3204 | ||
3228 | err = nl80211_parse_beacon(info, ¶ms); | 3205 | err = nl80211_parse_beacon(info->attrs, ¶ms); |
3229 | if (err) | 3206 | if (err) |
3230 | return err; | 3207 | return err; |
3231 | 3208 | ||
@@ -3383,6 +3360,32 @@ static bool nl80211_put_sta_rate(struct sk_buff *msg, struct rate_info *info, | |||
3383 | return true; | 3360 | return true; |
3384 | } | 3361 | } |
3385 | 3362 | ||
3363 | static bool nl80211_put_signal(struct sk_buff *msg, u8 mask, s8 *signal, | ||
3364 | int id) | ||
3365 | { | ||
3366 | void *attr; | ||
3367 | int i = 0; | ||
3368 | |||
3369 | if (!mask) | ||
3370 | return true; | ||
3371 | |||
3372 | attr = nla_nest_start(msg, id); | ||
3373 | if (!attr) | ||
3374 | return false; | ||
3375 | |||
3376 | for (i = 0; i < IEEE80211_MAX_CHAINS; i++) { | ||
3377 | if (!(mask & BIT(i))) | ||
3378 | continue; | ||
3379 | |||
3380 | if (nla_put_u8(msg, i, signal[i])) | ||
3381 | return false; | ||
3382 | } | ||
3383 | |||
3384 | nla_nest_end(msg, attr); | ||
3385 | |||
3386 | return true; | ||
3387 | } | ||
3388 | |||
3386 | static int nl80211_send_station(struct sk_buff *msg, u32 portid, u32 seq, | 3389 | static int nl80211_send_station(struct sk_buff *msg, u32 portid, u32 seq, |
3387 | int flags, | 3390 | int flags, |
3388 | struct cfg80211_registered_device *rdev, | 3391 | struct cfg80211_registered_device *rdev, |
@@ -3454,6 +3457,18 @@ static int nl80211_send_station(struct sk_buff *msg, u32 portid, u32 seq, | |||
3454 | default: | 3457 | default: |
3455 | break; | 3458 | break; |
3456 | } | 3459 | } |
3460 | if (sinfo->filled & STATION_INFO_CHAIN_SIGNAL) { | ||
3461 | if (!nl80211_put_signal(msg, sinfo->chains, | ||
3462 | sinfo->chain_signal, | ||
3463 | NL80211_STA_INFO_CHAIN_SIGNAL)) | ||
3464 | goto nla_put_failure; | ||
3465 | } | ||
3466 | if (sinfo->filled & STATION_INFO_CHAIN_SIGNAL_AVG) { | ||
3467 | if (!nl80211_put_signal(msg, sinfo->chains, | ||
3468 | sinfo->chain_signal_avg, | ||
3469 | NL80211_STA_INFO_CHAIN_SIGNAL_AVG)) | ||
3470 | goto nla_put_failure; | ||
3471 | } | ||
3457 | if (sinfo->filled & STATION_INFO_TX_BITRATE) { | 3472 | if (sinfo->filled & STATION_INFO_TX_BITRATE) { |
3458 | if (!nl80211_put_sta_rate(msg, &sinfo->txrate, | 3473 | if (!nl80211_put_sta_rate(msg, &sinfo->txrate, |
3459 | NL80211_STA_INFO_TX_BITRATE)) | 3474 | NL80211_STA_INFO_TX_BITRATE)) |
@@ -3841,6 +3856,8 @@ static int nl80211_set_station_tdls(struct genl_info *info, | |||
3841 | struct station_parameters *params) | 3856 | struct station_parameters *params) |
3842 | { | 3857 | { |
3843 | /* Dummy STA entry gets updated once the peer capabilities are known */ | 3858 | /* Dummy STA entry gets updated once the peer capabilities are known */ |
3859 | if (info->attrs[NL80211_ATTR_PEER_AID]) | ||
3860 | params->aid = nla_get_u16(info->attrs[NL80211_ATTR_PEER_AID]); | ||
3844 | if (info->attrs[NL80211_ATTR_HT_CAPABILITY]) | 3861 | if (info->attrs[NL80211_ATTR_HT_CAPABILITY]) |
3845 | params->ht_capa = | 3862 | params->ht_capa = |
3846 | nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]); | 3863 | nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]); |
@@ -3981,7 +3998,8 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) | |||
3981 | if (!info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]) | 3998 | if (!info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]) |
3982 | return -EINVAL; | 3999 | return -EINVAL; |
3983 | 4000 | ||
3984 | if (!info->attrs[NL80211_ATTR_STA_AID]) | 4001 | if (!info->attrs[NL80211_ATTR_STA_AID] && |
4002 | !info->attrs[NL80211_ATTR_PEER_AID]) | ||
3985 | return -EINVAL; | 4003 | return -EINVAL; |
3986 | 4004 | ||
3987 | mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); | 4005 | mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); |
@@ -3992,7 +4010,10 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) | |||
3992 | params.listen_interval = | 4010 | params.listen_interval = |
3993 | nla_get_u16(info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]); | 4011 | nla_get_u16(info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]); |
3994 | 4012 | ||
3995 | params.aid = nla_get_u16(info->attrs[NL80211_ATTR_STA_AID]); | 4013 | if (info->attrs[NL80211_ATTR_PEER_AID]) |
4014 | params.aid = nla_get_u16(info->attrs[NL80211_ATTR_PEER_AID]); | ||
4015 | else | ||
4016 | params.aid = nla_get_u16(info->attrs[NL80211_ATTR_STA_AID]); | ||
3996 | if (!params.aid || params.aid > IEEE80211_MAX_AID) | 4017 | if (!params.aid || params.aid > IEEE80211_MAX_AID) |
3997 | return -EINVAL; | 4018 | return -EINVAL; |
3998 | 4019 | ||
@@ -4044,7 +4065,8 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) | |||
4044 | params.sta_modify_mask &= ~STATION_PARAM_APPLY_UAPSD; | 4065 | params.sta_modify_mask &= ~STATION_PARAM_APPLY_UAPSD; |
4045 | 4066 | ||
4046 | /* TDLS peers cannot be added */ | 4067 | /* TDLS peers cannot be added */ |
4047 | if (params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) | 4068 | if ((params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) || |
4069 | info->attrs[NL80211_ATTR_PEER_AID]) | ||
4048 | return -EINVAL; | 4070 | return -EINVAL; |
4049 | /* but don't bother the driver with it */ | 4071 | /* but don't bother the driver with it */ |
4050 | params.sta_flags_mask &= ~BIT(NL80211_STA_FLAG_TDLS_PEER); | 4072 | params.sta_flags_mask &= ~BIT(NL80211_STA_FLAG_TDLS_PEER); |
@@ -4070,7 +4092,8 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) | |||
4070 | if (params.sta_flags_mask & BIT(NL80211_STA_FLAG_ASSOCIATED)) | 4092 | if (params.sta_flags_mask & BIT(NL80211_STA_FLAG_ASSOCIATED)) |
4071 | return -EINVAL; | 4093 | return -EINVAL; |
4072 | /* TDLS peers cannot be added */ | 4094 | /* TDLS peers cannot be added */ |
4073 | if (params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) | 4095 | if ((params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) || |
4096 | info->attrs[NL80211_ATTR_PEER_AID]) | ||
4074 | return -EINVAL; | 4097 | return -EINVAL; |
4075 | break; | 4098 | break; |
4076 | case NL80211_IFTYPE_STATION: | 4099 | case NL80211_IFTYPE_STATION: |
@@ -4592,7 +4615,9 @@ static int nl80211_get_mesh_config(struct sk_buff *skb, | |||
4592 | nla_put_u32(msg, NL80211_MESHCONF_POWER_MODE, | 4615 | nla_put_u32(msg, NL80211_MESHCONF_POWER_MODE, |
4593 | cur_params.power_mode) || | 4616 | cur_params.power_mode) || |
4594 | nla_put_u16(msg, NL80211_MESHCONF_AWAKE_WINDOW, | 4617 | nla_put_u16(msg, NL80211_MESHCONF_AWAKE_WINDOW, |
4595 | cur_params.dot11MeshAwakeWindowDuration)) | 4618 | cur_params.dot11MeshAwakeWindowDuration) || |
4619 | nla_put_u32(msg, NL80211_MESHCONF_PLINK_TIMEOUT, | ||
4620 | cur_params.plink_timeout)) | ||
4596 | goto nla_put_failure; | 4621 | goto nla_put_failure; |
4597 | nla_nest_end(msg, pinfoattr); | 4622 | nla_nest_end(msg, pinfoattr); |
4598 | genlmsg_end(msg, hdr); | 4623 | genlmsg_end(msg, hdr); |
@@ -4633,6 +4658,7 @@ static const struct nla_policy nl80211_meshconf_params_policy[NL80211_MESHCONF_A | |||
4633 | [NL80211_MESHCONF_HWMP_CONFIRMATION_INTERVAL] = { .type = NLA_U16 }, | 4658 | [NL80211_MESHCONF_HWMP_CONFIRMATION_INTERVAL] = { .type = NLA_U16 }, |
4634 | [NL80211_MESHCONF_POWER_MODE] = { .type = NLA_U32 }, | 4659 | [NL80211_MESHCONF_POWER_MODE] = { .type = NLA_U32 }, |
4635 | [NL80211_MESHCONF_AWAKE_WINDOW] = { .type = NLA_U16 }, | 4660 | [NL80211_MESHCONF_AWAKE_WINDOW] = { .type = NLA_U16 }, |
4661 | [NL80211_MESHCONF_PLINK_TIMEOUT] = { .type = NLA_U32 }, | ||
4636 | }; | 4662 | }; |
4637 | 4663 | ||
4638 | static const struct nla_policy | 4664 | static const struct nla_policy |
@@ -4641,6 +4667,7 @@ static const struct nla_policy | |||
4641 | [NL80211_MESH_SETUP_ENABLE_VENDOR_PATH_SEL] = { .type = NLA_U8 }, | 4667 | [NL80211_MESH_SETUP_ENABLE_VENDOR_PATH_SEL] = { .type = NLA_U8 }, |
4642 | [NL80211_MESH_SETUP_ENABLE_VENDOR_METRIC] = { .type = NLA_U8 }, | 4668 | [NL80211_MESH_SETUP_ENABLE_VENDOR_METRIC] = { .type = NLA_U8 }, |
4643 | [NL80211_MESH_SETUP_USERSPACE_AUTH] = { .type = NLA_FLAG }, | 4669 | [NL80211_MESH_SETUP_USERSPACE_AUTH] = { .type = NLA_FLAG }, |
4670 | [NL80211_MESH_SETUP_AUTH_PROTOCOL] = { .type = NLA_U8 }, | ||
4644 | [NL80211_MESH_SETUP_USERSPACE_MPM] = { .type = NLA_FLAG }, | 4671 | [NL80211_MESH_SETUP_USERSPACE_MPM] = { .type = NLA_FLAG }, |
4645 | [NL80211_MESH_SETUP_IE] = { .type = NLA_BINARY, | 4672 | [NL80211_MESH_SETUP_IE] = { .type = NLA_BINARY, |
4646 | .len = IEEE80211_MAX_DATA_LEN }, | 4673 | .len = IEEE80211_MAX_DATA_LEN }, |
@@ -4769,6 +4796,9 @@ do { \ | |||
4769 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshAwakeWindowDuration, | 4796 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshAwakeWindowDuration, |
4770 | 0, 65535, mask, | 4797 | 0, 65535, mask, |
4771 | NL80211_MESHCONF_AWAKE_WINDOW, nla_get_u16); | 4798 | NL80211_MESHCONF_AWAKE_WINDOW, nla_get_u16); |
4799 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, plink_timeout, 1, 0xffffffff, | ||
4800 | mask, NL80211_MESHCONF_PLINK_TIMEOUT, | ||
4801 | nla_get_u32); | ||
4772 | if (mask_out) | 4802 | if (mask_out) |
4773 | *mask_out = mask; | 4803 | *mask_out = mask; |
4774 | 4804 | ||
@@ -4826,6 +4856,13 @@ static int nl80211_parse_mesh_setup(struct genl_info *info, | |||
4826 | if (setup->is_secure) | 4856 | if (setup->is_secure) |
4827 | setup->user_mpm = true; | 4857 | setup->user_mpm = true; |
4828 | 4858 | ||
4859 | if (tb[NL80211_MESH_SETUP_AUTH_PROTOCOL]) { | ||
4860 | if (!setup->user_mpm) | ||
4861 | return -EINVAL; | ||
4862 | setup->auth_id = | ||
4863 | nla_get_u8(tb[NL80211_MESH_SETUP_AUTH_PROTOCOL]); | ||
4864 | } | ||
4865 | |||
4829 | return 0; | 4866 | return 0; |
4830 | } | 4867 | } |
4831 | 4868 | ||
@@ -4868,18 +4905,13 @@ static int nl80211_get_reg(struct sk_buff *skb, struct genl_info *info) | |||
4868 | void *hdr = NULL; | 4905 | void *hdr = NULL; |
4869 | struct nlattr *nl_reg_rules; | 4906 | struct nlattr *nl_reg_rules; |
4870 | unsigned int i; | 4907 | unsigned int i; |
4871 | int err = -EINVAL; | ||
4872 | |||
4873 | mutex_lock(&cfg80211_mutex); | ||
4874 | 4908 | ||
4875 | if (!cfg80211_regdomain) | 4909 | if (!cfg80211_regdomain) |
4876 | goto out; | 4910 | return -EINVAL; |
4877 | 4911 | ||
4878 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); | 4912 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); |
4879 | if (!msg) { | 4913 | if (!msg) |
4880 | err = -ENOBUFS; | 4914 | return -ENOBUFS; |
4881 | goto out; | ||
4882 | } | ||
4883 | 4915 | ||
4884 | hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0, | 4916 | hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0, |
4885 | NL80211_CMD_GET_REG); | 4917 | NL80211_CMD_GET_REG); |
@@ -4938,8 +4970,7 @@ static int nl80211_get_reg(struct sk_buff *skb, struct genl_info *info) | |||
4938 | nla_nest_end(msg, nl_reg_rules); | 4970 | nla_nest_end(msg, nl_reg_rules); |
4939 | 4971 | ||
4940 | genlmsg_end(msg, hdr); | 4972 | genlmsg_end(msg, hdr); |
4941 | err = genlmsg_reply(msg, info); | 4973 | return genlmsg_reply(msg, info); |
4942 | goto out; | ||
4943 | 4974 | ||
4944 | nla_put_failure_rcu: | 4975 | nla_put_failure_rcu: |
4945 | rcu_read_unlock(); | 4976 | rcu_read_unlock(); |
@@ -4947,10 +4978,7 @@ nla_put_failure: | |||
4947 | genlmsg_cancel(msg, hdr); | 4978 | genlmsg_cancel(msg, hdr); |
4948 | put_failure: | 4979 | put_failure: |
4949 | nlmsg_free(msg); | 4980 | nlmsg_free(msg); |
4950 | err = -EMSGSIZE; | 4981 | return -EMSGSIZE; |
4951 | out: | ||
4952 | mutex_unlock(&cfg80211_mutex); | ||
4953 | return err; | ||
4954 | } | 4982 | } |
4955 | 4983 | ||
4956 | static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info) | 4984 | static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info) |
@@ -5016,12 +5044,9 @@ static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info) | |||
5016 | } | 5044 | } |
5017 | } | 5045 | } |
5018 | 5046 | ||
5019 | mutex_lock(&cfg80211_mutex); | ||
5020 | |||
5021 | r = set_regdom(rd); | 5047 | r = set_regdom(rd); |
5022 | /* set_regdom took ownership */ | 5048 | /* set_regdom took ownership */ |
5023 | rd = NULL; | 5049 | rd = NULL; |
5024 | mutex_unlock(&cfg80211_mutex); | ||
5025 | 5050 | ||
5026 | bad_reg: | 5051 | bad_reg: |
5027 | kfree(rd); | 5052 | kfree(rd); |
@@ -5071,7 +5096,6 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) | |||
5071 | if (!rdev->ops->scan) | 5096 | if (!rdev->ops->scan) |
5072 | return -EOPNOTSUPP; | 5097 | return -EOPNOTSUPP; |
5073 | 5098 | ||
5074 | mutex_lock(&rdev->sched_scan_mtx); | ||
5075 | if (rdev->scan_req) { | 5099 | if (rdev->scan_req) { |
5076 | err = -EBUSY; | 5100 | err = -EBUSY; |
5077 | goto unlock; | 5101 | goto unlock; |
@@ -5257,7 +5281,6 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) | |||
5257 | } | 5281 | } |
5258 | 5282 | ||
5259 | unlock: | 5283 | unlock: |
5260 | mutex_unlock(&rdev->sched_scan_mtx); | ||
5261 | return err; | 5284 | return err; |
5262 | } | 5285 | } |
5263 | 5286 | ||
@@ -5329,8 +5352,6 @@ static int nl80211_start_sched_scan(struct sk_buff *skb, | |||
5329 | if (ie_len > wiphy->max_sched_scan_ie_len) | 5352 | if (ie_len > wiphy->max_sched_scan_ie_len) |
5330 | return -EINVAL; | 5353 | return -EINVAL; |
5331 | 5354 | ||
5332 | mutex_lock(&rdev->sched_scan_mtx); | ||
5333 | |||
5334 | if (rdev->sched_scan_req) { | 5355 | if (rdev->sched_scan_req) { |
5335 | err = -EINPROGRESS; | 5356 | err = -EINPROGRESS; |
5336 | goto out; | 5357 | goto out; |
@@ -5498,7 +5519,6 @@ static int nl80211_start_sched_scan(struct sk_buff *skb, | |||
5498 | out_free: | 5519 | out_free: |
5499 | kfree(request); | 5520 | kfree(request); |
5500 | out: | 5521 | out: |
5501 | mutex_unlock(&rdev->sched_scan_mtx); | ||
5502 | return err; | 5522 | return err; |
5503 | } | 5523 | } |
5504 | 5524 | ||
@@ -5506,17 +5526,12 @@ static int nl80211_stop_sched_scan(struct sk_buff *skb, | |||
5506 | struct genl_info *info) | 5526 | struct genl_info *info) |
5507 | { | 5527 | { |
5508 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; | 5528 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
5509 | int err; | ||
5510 | 5529 | ||
5511 | if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_SCHED_SCAN) || | 5530 | if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_SCHED_SCAN) || |
5512 | !rdev->ops->sched_scan_stop) | 5531 | !rdev->ops->sched_scan_stop) |
5513 | return -EOPNOTSUPP; | 5532 | return -EOPNOTSUPP; |
5514 | 5533 | ||
5515 | mutex_lock(&rdev->sched_scan_mtx); | 5534 | return __cfg80211_stop_sched_scan(rdev, false); |
5516 | err = __cfg80211_stop_sched_scan(rdev, false); | ||
5517 | mutex_unlock(&rdev->sched_scan_mtx); | ||
5518 | |||
5519 | return err; | ||
5520 | } | 5535 | } |
5521 | 5536 | ||
5522 | static int nl80211_start_radar_detection(struct sk_buff *skb, | 5537 | static int nl80211_start_radar_detection(struct sk_buff *skb, |
@@ -5548,12 +5563,11 @@ static int nl80211_start_radar_detection(struct sk_buff *skb, | |||
5548 | if (!rdev->ops->start_radar_detection) | 5563 | if (!rdev->ops->start_radar_detection) |
5549 | return -EOPNOTSUPP; | 5564 | return -EOPNOTSUPP; |
5550 | 5565 | ||
5551 | mutex_lock(&rdev->devlist_mtx); | ||
5552 | err = cfg80211_can_use_iftype_chan(rdev, wdev, wdev->iftype, | 5566 | err = cfg80211_can_use_iftype_chan(rdev, wdev, wdev->iftype, |
5553 | chandef.chan, CHAN_MODE_SHARED, | 5567 | chandef.chan, CHAN_MODE_SHARED, |
5554 | BIT(chandef.width)); | 5568 | BIT(chandef.width)); |
5555 | if (err) | 5569 | if (err) |
5556 | goto err_locked; | 5570 | return err; |
5557 | 5571 | ||
5558 | err = rdev->ops->start_radar_detection(&rdev->wiphy, dev, &chandef); | 5572 | err = rdev->ops->start_radar_detection(&rdev->wiphy, dev, &chandef); |
5559 | if (!err) { | 5573 | if (!err) { |
@@ -5561,9 +5575,6 @@ static int nl80211_start_radar_detection(struct sk_buff *skb, | |||
5561 | wdev->cac_started = true; | 5575 | wdev->cac_started = true; |
5562 | wdev->cac_start_time = jiffies; | 5576 | wdev->cac_start_time = jiffies; |
5563 | } | 5577 | } |
5564 | err_locked: | ||
5565 | mutex_unlock(&rdev->devlist_mtx); | ||
5566 | |||
5567 | return err; | 5578 | return err; |
5568 | } | 5579 | } |
5569 | 5580 | ||
@@ -5946,10 +5957,13 @@ static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info) | |||
5946 | if (local_state_change) | 5957 | if (local_state_change) |
5947 | return 0; | 5958 | return 0; |
5948 | 5959 | ||
5949 | return cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid, | 5960 | wdev_lock(dev->ieee80211_ptr); |
5950 | ssid, ssid_len, ie, ie_len, | 5961 | err = cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid, |
5951 | key.p.key, key.p.key_len, key.idx, | 5962 | ssid, ssid_len, ie, ie_len, |
5952 | sae_data, sae_data_len); | 5963 | key.p.key, key.p.key_len, key.idx, |
5964 | sae_data, sae_data_len); | ||
5965 | wdev_unlock(dev->ieee80211_ptr); | ||
5966 | return err; | ||
5953 | } | 5967 | } |
5954 | 5968 | ||
5955 | static int nl80211_crypto_settings(struct cfg80211_registered_device *rdev, | 5969 | static int nl80211_crypto_settings(struct cfg80211_registered_device *rdev, |
@@ -6116,9 +6130,12 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info) | |||
6116 | } | 6130 | } |
6117 | 6131 | ||
6118 | err = nl80211_crypto_settings(rdev, info, &req.crypto, 1); | 6132 | err = nl80211_crypto_settings(rdev, info, &req.crypto, 1); |
6119 | if (!err) | 6133 | if (!err) { |
6134 | wdev_lock(dev->ieee80211_ptr); | ||
6120 | err = cfg80211_mlme_assoc(rdev, dev, chan, bssid, | 6135 | err = cfg80211_mlme_assoc(rdev, dev, chan, bssid, |
6121 | ssid, ssid_len, &req); | 6136 | ssid, ssid_len, &req); |
6137 | wdev_unlock(dev->ieee80211_ptr); | ||
6138 | } | ||
6122 | 6139 | ||
6123 | return err; | 6140 | return err; |
6124 | } | 6141 | } |
@@ -6128,7 +6145,7 @@ static int nl80211_deauthenticate(struct sk_buff *skb, struct genl_info *info) | |||
6128 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; | 6145 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
6129 | struct net_device *dev = info->user_ptr[1]; | 6146 | struct net_device *dev = info->user_ptr[1]; |
6130 | const u8 *ie = NULL, *bssid; | 6147 | const u8 *ie = NULL, *bssid; |
6131 | int ie_len = 0; | 6148 | int ie_len = 0, err; |
6132 | u16 reason_code; | 6149 | u16 reason_code; |
6133 | bool local_state_change; | 6150 | bool local_state_change; |
6134 | 6151 | ||
@@ -6163,8 +6180,11 @@ static int nl80211_deauthenticate(struct sk_buff *skb, struct genl_info *info) | |||
6163 | 6180 | ||
6164 | local_state_change = !!info->attrs[NL80211_ATTR_LOCAL_STATE_CHANGE]; | 6181 | local_state_change = !!info->attrs[NL80211_ATTR_LOCAL_STATE_CHANGE]; |
6165 | 6182 | ||
6166 | return cfg80211_mlme_deauth(rdev, dev, bssid, ie, ie_len, reason_code, | 6183 | wdev_lock(dev->ieee80211_ptr); |
6167 | local_state_change); | 6184 | err = cfg80211_mlme_deauth(rdev, dev, bssid, ie, ie_len, reason_code, |
6185 | local_state_change); | ||
6186 | wdev_unlock(dev->ieee80211_ptr); | ||
6187 | return err; | ||
6168 | } | 6188 | } |
6169 | 6189 | ||
6170 | static int nl80211_disassociate(struct sk_buff *skb, struct genl_info *info) | 6190 | static int nl80211_disassociate(struct sk_buff *skb, struct genl_info *info) |
@@ -6172,7 +6192,7 @@ static int nl80211_disassociate(struct sk_buff *skb, struct genl_info *info) | |||
6172 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; | 6192 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
6173 | struct net_device *dev = info->user_ptr[1]; | 6193 | struct net_device *dev = info->user_ptr[1]; |
6174 | const u8 *ie = NULL, *bssid; | 6194 | const u8 *ie = NULL, *bssid; |
6175 | int ie_len = 0; | 6195 | int ie_len = 0, err; |
6176 | u16 reason_code; | 6196 | u16 reason_code; |
6177 | bool local_state_change; | 6197 | bool local_state_change; |
6178 | 6198 | ||
@@ -6207,8 +6227,11 @@ static int nl80211_disassociate(struct sk_buff *skb, struct genl_info *info) | |||
6207 | 6227 | ||
6208 | local_state_change = !!info->attrs[NL80211_ATTR_LOCAL_STATE_CHANGE]; | 6228 | local_state_change = !!info->attrs[NL80211_ATTR_LOCAL_STATE_CHANGE]; |
6209 | 6229 | ||
6210 | return cfg80211_mlme_disassoc(rdev, dev, bssid, ie, ie_len, reason_code, | 6230 | wdev_lock(dev->ieee80211_ptr); |
6211 | local_state_change); | 6231 | err = cfg80211_mlme_disassoc(rdev, dev, bssid, ie, ie_len, reason_code, |
6232 | local_state_change); | ||
6233 | wdev_unlock(dev->ieee80211_ptr); | ||
6234 | return err; | ||
6212 | } | 6235 | } |
6213 | 6236 | ||
6214 | static bool | 6237 | static bool |
@@ -6295,11 +6318,16 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info) | |||
6295 | if (!cfg80211_reg_can_beacon(&rdev->wiphy, &ibss.chandef)) | 6318 | if (!cfg80211_reg_can_beacon(&rdev->wiphy, &ibss.chandef)) |
6296 | return -EINVAL; | 6319 | return -EINVAL; |
6297 | 6320 | ||
6298 | if (ibss.chandef.width > NL80211_CHAN_WIDTH_40) | 6321 | switch (ibss.chandef.width) { |
6299 | return -EINVAL; | 6322 | case NL80211_CHAN_WIDTH_20_NOHT: |
6300 | if (ibss.chandef.width != NL80211_CHAN_WIDTH_20_NOHT && | 6323 | break; |
6301 | !(rdev->wiphy.features & NL80211_FEATURE_HT_IBSS)) | 6324 | case NL80211_CHAN_WIDTH_20: |
6325 | case NL80211_CHAN_WIDTH_40: | ||
6326 | if (rdev->wiphy.features & NL80211_FEATURE_HT_IBSS) | ||
6327 | break; | ||
6328 | default: | ||
6302 | return -EINVAL; | 6329 | return -EINVAL; |
6330 | } | ||
6303 | 6331 | ||
6304 | ibss.channel_fixed = !!info->attrs[NL80211_ATTR_FREQ_FIXED]; | 6332 | ibss.channel_fixed = !!info->attrs[NL80211_ATTR_FREQ_FIXED]; |
6305 | ibss.privacy = !!info->attrs[NL80211_ATTR_PRIVACY]; | 6333 | ibss.privacy = !!info->attrs[NL80211_ATTR_PRIVACY]; |
@@ -6426,6 +6454,8 @@ static int nl80211_testmode_dump(struct sk_buff *skb, | |||
6426 | void *data = NULL; | 6454 | void *data = NULL; |
6427 | int data_len = 0; | 6455 | int data_len = 0; |
6428 | 6456 | ||
6457 | rtnl_lock(); | ||
6458 | |||
6429 | if (cb->args[0]) { | 6459 | if (cb->args[0]) { |
6430 | /* | 6460 | /* |
6431 | * 0 is a valid index, but not valid for args[0], | 6461 | * 0 is a valid index, but not valid for args[0], |
@@ -6437,18 +6467,16 @@ static int nl80211_testmode_dump(struct sk_buff *skb, | |||
6437 | nl80211_fam.attrbuf, nl80211_fam.maxattr, | 6467 | nl80211_fam.attrbuf, nl80211_fam.maxattr, |
6438 | nl80211_policy); | 6468 | nl80211_policy); |
6439 | if (err) | 6469 | if (err) |
6440 | return err; | 6470 | goto out_err; |
6441 | 6471 | ||
6442 | mutex_lock(&cfg80211_mutex); | ||
6443 | rdev = __cfg80211_rdev_from_attrs(sock_net(skb->sk), | 6472 | rdev = __cfg80211_rdev_from_attrs(sock_net(skb->sk), |
6444 | nl80211_fam.attrbuf); | 6473 | nl80211_fam.attrbuf); |
6445 | if (IS_ERR(rdev)) { | 6474 | if (IS_ERR(rdev)) { |
6446 | mutex_unlock(&cfg80211_mutex); | 6475 | err = PTR_ERR(rdev); |
6447 | return PTR_ERR(rdev); | 6476 | goto out_err; |
6448 | } | 6477 | } |
6449 | phy_idx = rdev->wiphy_idx; | 6478 | phy_idx = rdev->wiphy_idx; |
6450 | rdev = NULL; | 6479 | rdev = NULL; |
6451 | mutex_unlock(&cfg80211_mutex); | ||
6452 | 6480 | ||
6453 | if (nl80211_fam.attrbuf[NL80211_ATTR_TESTDATA]) | 6481 | if (nl80211_fam.attrbuf[NL80211_ATTR_TESTDATA]) |
6454 | cb->args[1] = | 6482 | cb->args[1] = |
@@ -6460,14 +6488,11 @@ static int nl80211_testmode_dump(struct sk_buff *skb, | |||
6460 | data_len = nla_len((void *)cb->args[1]); | 6488 | data_len = nla_len((void *)cb->args[1]); |
6461 | } | 6489 | } |
6462 | 6490 | ||
6463 | mutex_lock(&cfg80211_mutex); | ||
6464 | rdev = cfg80211_rdev_by_wiphy_idx(phy_idx); | 6491 | rdev = cfg80211_rdev_by_wiphy_idx(phy_idx); |
6465 | if (!rdev) { | 6492 | if (!rdev) { |
6466 | mutex_unlock(&cfg80211_mutex); | 6493 | err = -ENOENT; |
6467 | return -ENOENT; | 6494 | goto out_err; |
6468 | } | 6495 | } |
6469 | cfg80211_lock_rdev(rdev); | ||
6470 | mutex_unlock(&cfg80211_mutex); | ||
6471 | 6496 | ||
6472 | if (!rdev->ops->testmode_dump) { | 6497 | if (!rdev->ops->testmode_dump) { |
6473 | err = -EOPNOTSUPP; | 6498 | err = -EOPNOTSUPP; |
@@ -6508,7 +6533,7 @@ static int nl80211_testmode_dump(struct sk_buff *skb, | |||
6508 | /* see above */ | 6533 | /* see above */ |
6509 | cb->args[0] = phy_idx + 1; | 6534 | cb->args[0] = phy_idx + 1; |
6510 | out_err: | 6535 | out_err: |
6511 | cfg80211_unlock_rdev(rdev); | 6536 | rtnl_unlock(); |
6512 | return err; | 6537 | return err; |
6513 | } | 6538 | } |
6514 | 6539 | ||
@@ -6716,7 +6741,9 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info) | |||
6716 | sizeof(connect.vht_capa)); | 6741 | sizeof(connect.vht_capa)); |
6717 | } | 6742 | } |
6718 | 6743 | ||
6719 | err = cfg80211_connect(rdev, dev, &connect, connkeys); | 6744 | wdev_lock(dev->ieee80211_ptr); |
6745 | err = cfg80211_connect(rdev, dev, &connect, connkeys, NULL); | ||
6746 | wdev_unlock(dev->ieee80211_ptr); | ||
6720 | if (err) | 6747 | if (err) |
6721 | kfree(connkeys); | 6748 | kfree(connkeys); |
6722 | return err; | 6749 | return err; |
@@ -6727,6 +6754,7 @@ static int nl80211_disconnect(struct sk_buff *skb, struct genl_info *info) | |||
6727 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; | 6754 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
6728 | struct net_device *dev = info->user_ptr[1]; | 6755 | struct net_device *dev = info->user_ptr[1]; |
6729 | u16 reason; | 6756 | u16 reason; |
6757 | int ret; | ||
6730 | 6758 | ||
6731 | if (!info->attrs[NL80211_ATTR_REASON_CODE]) | 6759 | if (!info->attrs[NL80211_ATTR_REASON_CODE]) |
6732 | reason = WLAN_REASON_DEAUTH_LEAVING; | 6760 | reason = WLAN_REASON_DEAUTH_LEAVING; |
@@ -6740,7 +6768,10 @@ static int nl80211_disconnect(struct sk_buff *skb, struct genl_info *info) | |||
6740 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT) | 6768 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT) |
6741 | return -EOPNOTSUPP; | 6769 | return -EOPNOTSUPP; |
6742 | 6770 | ||
6743 | return cfg80211_disconnect(rdev, dev, reason, true); | 6771 | wdev_lock(dev->ieee80211_ptr); |
6772 | ret = cfg80211_disconnect(rdev, dev, reason, true); | ||
6773 | wdev_unlock(dev->ieee80211_ptr); | ||
6774 | return ret; | ||
6744 | } | 6775 | } |
6745 | 6776 | ||
6746 | static int nl80211_wiphy_netns(struct sk_buff *skb, struct genl_info *info) | 6777 | static int nl80211_wiphy_netns(struct sk_buff *skb, struct genl_info *info) |
@@ -7159,6 +7190,9 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info) | |||
7159 | return -EOPNOTSUPP; | 7190 | return -EOPNOTSUPP; |
7160 | 7191 | ||
7161 | switch (wdev->iftype) { | 7192 | switch (wdev->iftype) { |
7193 | case NL80211_IFTYPE_P2P_DEVICE: | ||
7194 | if (!info->attrs[NL80211_ATTR_WIPHY_FREQ]) | ||
7195 | return -EINVAL; | ||
7162 | case NL80211_IFTYPE_STATION: | 7196 | case NL80211_IFTYPE_STATION: |
7163 | case NL80211_IFTYPE_ADHOC: | 7197 | case NL80211_IFTYPE_ADHOC: |
7164 | case NL80211_IFTYPE_P2P_CLIENT: | 7198 | case NL80211_IFTYPE_P2P_CLIENT: |
@@ -7166,7 +7200,6 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info) | |||
7166 | case NL80211_IFTYPE_AP_VLAN: | 7200 | case NL80211_IFTYPE_AP_VLAN: |
7167 | case NL80211_IFTYPE_MESH_POINT: | 7201 | case NL80211_IFTYPE_MESH_POINT: |
7168 | case NL80211_IFTYPE_P2P_GO: | 7202 | case NL80211_IFTYPE_P2P_GO: |
7169 | case NL80211_IFTYPE_P2P_DEVICE: | ||
7170 | break; | 7203 | break; |
7171 | default: | 7204 | default: |
7172 | return -EOPNOTSUPP; | 7205 | return -EOPNOTSUPP; |
@@ -7194,9 +7227,18 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info) | |||
7194 | 7227 | ||
7195 | no_cck = nla_get_flag(info->attrs[NL80211_ATTR_TX_NO_CCK_RATE]); | 7228 | no_cck = nla_get_flag(info->attrs[NL80211_ATTR_TX_NO_CCK_RATE]); |
7196 | 7229 | ||
7197 | err = nl80211_parse_chandef(rdev, info, &chandef); | 7230 | /* get the channel if any has been specified, otherwise pass NULL to |
7198 | if (err) | 7231 | * the driver. The latter will use the current one |
7199 | return err; | 7232 | */ |
7233 | chandef.chan = NULL; | ||
7234 | if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) { | ||
7235 | err = nl80211_parse_chandef(rdev, info, &chandef); | ||
7236 | if (err) | ||
7237 | return err; | ||
7238 | } | ||
7239 | |||
7240 | if (!chandef.chan && offchan) | ||
7241 | return -EINVAL; | ||
7200 | 7242 | ||
7201 | if (!dont_wait_for_ack) { | 7243 | if (!dont_wait_for_ack) { |
7202 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); | 7244 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); |
@@ -7501,6 +7543,23 @@ static int nl80211_join_mesh(struct sk_buff *skb, struct genl_info *info) | |||
7501 | setup.chandef.chan = NULL; | 7543 | setup.chandef.chan = NULL; |
7502 | } | 7544 | } |
7503 | 7545 | ||
7546 | if (info->attrs[NL80211_ATTR_BSS_BASIC_RATES]) { | ||
7547 | u8 *rates = nla_data(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]); | ||
7548 | int n_rates = | ||
7549 | nla_len(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]); | ||
7550 | struct ieee80211_supported_band *sband; | ||
7551 | |||
7552 | if (!setup.chandef.chan) | ||
7553 | return -EINVAL; | ||
7554 | |||
7555 | sband = rdev->wiphy.bands[setup.chandef.chan->band]; | ||
7556 | |||
7557 | err = ieee80211_get_ratemask(sband, rates, n_rates, | ||
7558 | &setup.basic_rates); | ||
7559 | if (err) | ||
7560 | return err; | ||
7561 | } | ||
7562 | |||
7504 | return cfg80211_join_mesh(rdev, dev, &setup, &cfg); | 7563 | return cfg80211_join_mesh(rdev, dev, &setup, &cfg); |
7505 | } | 7564 | } |
7506 | 7565 | ||
@@ -7516,28 +7575,29 @@ static int nl80211_leave_mesh(struct sk_buff *skb, struct genl_info *info) | |||
7516 | static int nl80211_send_wowlan_patterns(struct sk_buff *msg, | 7575 | static int nl80211_send_wowlan_patterns(struct sk_buff *msg, |
7517 | struct cfg80211_registered_device *rdev) | 7576 | struct cfg80211_registered_device *rdev) |
7518 | { | 7577 | { |
7578 | struct cfg80211_wowlan *wowlan = rdev->wiphy.wowlan_config; | ||
7519 | struct nlattr *nl_pats, *nl_pat; | 7579 | struct nlattr *nl_pats, *nl_pat; |
7520 | int i, pat_len; | 7580 | int i, pat_len; |
7521 | 7581 | ||
7522 | if (!rdev->wowlan->n_patterns) | 7582 | if (!wowlan->n_patterns) |
7523 | return 0; | 7583 | return 0; |
7524 | 7584 | ||
7525 | nl_pats = nla_nest_start(msg, NL80211_WOWLAN_TRIG_PKT_PATTERN); | 7585 | nl_pats = nla_nest_start(msg, NL80211_WOWLAN_TRIG_PKT_PATTERN); |
7526 | if (!nl_pats) | 7586 | if (!nl_pats) |
7527 | return -ENOBUFS; | 7587 | return -ENOBUFS; |
7528 | 7588 | ||
7529 | for (i = 0; i < rdev->wowlan->n_patterns; i++) { | 7589 | for (i = 0; i < wowlan->n_patterns; i++) { |
7530 | nl_pat = nla_nest_start(msg, i + 1); | 7590 | nl_pat = nla_nest_start(msg, i + 1); |
7531 | if (!nl_pat) | 7591 | if (!nl_pat) |
7532 | return -ENOBUFS; | 7592 | return -ENOBUFS; |
7533 | pat_len = rdev->wowlan->patterns[i].pattern_len; | 7593 | pat_len = wowlan->patterns[i].pattern_len; |
7534 | if (nla_put(msg, NL80211_WOWLAN_PKTPAT_MASK, | 7594 | if (nla_put(msg, NL80211_WOWLAN_PKTPAT_MASK, |
7535 | DIV_ROUND_UP(pat_len, 8), | 7595 | DIV_ROUND_UP(pat_len, 8), |
7536 | rdev->wowlan->patterns[i].mask) || | 7596 | wowlan->patterns[i].mask) || |
7537 | nla_put(msg, NL80211_WOWLAN_PKTPAT_PATTERN, | 7597 | nla_put(msg, NL80211_WOWLAN_PKTPAT_PATTERN, |
7538 | pat_len, rdev->wowlan->patterns[i].pattern) || | 7598 | pat_len, wowlan->patterns[i].pattern) || |
7539 | nla_put_u32(msg, NL80211_WOWLAN_PKTPAT_OFFSET, | 7599 | nla_put_u32(msg, NL80211_WOWLAN_PKTPAT_OFFSET, |
7540 | rdev->wowlan->patterns[i].pkt_offset)) | 7600 | wowlan->patterns[i].pkt_offset)) |
7541 | return -ENOBUFS; | 7601 | return -ENOBUFS; |
7542 | nla_nest_end(msg, nl_pat); | 7602 | nla_nest_end(msg, nl_pat); |
7543 | } | 7603 | } |
@@ -7596,16 +7656,15 @@ static int nl80211_get_wowlan(struct sk_buff *skb, struct genl_info *info) | |||
7596 | void *hdr; | 7656 | void *hdr; |
7597 | u32 size = NLMSG_DEFAULT_SIZE; | 7657 | u32 size = NLMSG_DEFAULT_SIZE; |
7598 | 7658 | ||
7599 | if (!rdev->wiphy.wowlan.flags && !rdev->wiphy.wowlan.n_patterns && | 7659 | if (!rdev->wiphy.wowlan) |
7600 | !rdev->wiphy.wowlan.tcp) | ||
7601 | return -EOPNOTSUPP; | 7660 | return -EOPNOTSUPP; |
7602 | 7661 | ||
7603 | if (rdev->wowlan && rdev->wowlan->tcp) { | 7662 | if (rdev->wiphy.wowlan_config && rdev->wiphy.wowlan_config->tcp) { |
7604 | /* adjust size to have room for all the data */ | 7663 | /* adjust size to have room for all the data */ |
7605 | size += rdev->wowlan->tcp->tokens_size + | 7664 | size += rdev->wiphy.wowlan_config->tcp->tokens_size + |
7606 | rdev->wowlan->tcp->payload_len + | 7665 | rdev->wiphy.wowlan_config->tcp->payload_len + |
7607 | rdev->wowlan->tcp->wake_len + | 7666 | rdev->wiphy.wowlan_config->tcp->wake_len + |
7608 | rdev->wowlan->tcp->wake_len / 8; | 7667 | rdev->wiphy.wowlan_config->tcp->wake_len / 8; |
7609 | } | 7668 | } |
7610 | 7669 | ||
7611 | msg = nlmsg_new(size, GFP_KERNEL); | 7670 | msg = nlmsg_new(size, GFP_KERNEL); |
@@ -7617,33 +7676,34 @@ static int nl80211_get_wowlan(struct sk_buff *skb, struct genl_info *info) | |||
7617 | if (!hdr) | 7676 | if (!hdr) |
7618 | goto nla_put_failure; | 7677 | goto nla_put_failure; |
7619 | 7678 | ||
7620 | if (rdev->wowlan) { | 7679 | if (rdev->wiphy.wowlan_config) { |
7621 | struct nlattr *nl_wowlan; | 7680 | struct nlattr *nl_wowlan; |
7622 | 7681 | ||
7623 | nl_wowlan = nla_nest_start(msg, NL80211_ATTR_WOWLAN_TRIGGERS); | 7682 | nl_wowlan = nla_nest_start(msg, NL80211_ATTR_WOWLAN_TRIGGERS); |
7624 | if (!nl_wowlan) | 7683 | if (!nl_wowlan) |
7625 | goto nla_put_failure; | 7684 | goto nla_put_failure; |
7626 | 7685 | ||
7627 | if ((rdev->wowlan->any && | 7686 | if ((rdev->wiphy.wowlan_config->any && |
7628 | nla_put_flag(msg, NL80211_WOWLAN_TRIG_ANY)) || | 7687 | nla_put_flag(msg, NL80211_WOWLAN_TRIG_ANY)) || |
7629 | (rdev->wowlan->disconnect && | 7688 | (rdev->wiphy.wowlan_config->disconnect && |
7630 | nla_put_flag(msg, NL80211_WOWLAN_TRIG_DISCONNECT)) || | 7689 | nla_put_flag(msg, NL80211_WOWLAN_TRIG_DISCONNECT)) || |
7631 | (rdev->wowlan->magic_pkt && | 7690 | (rdev->wiphy.wowlan_config->magic_pkt && |
7632 | nla_put_flag(msg, NL80211_WOWLAN_TRIG_MAGIC_PKT)) || | 7691 | nla_put_flag(msg, NL80211_WOWLAN_TRIG_MAGIC_PKT)) || |
7633 | (rdev->wowlan->gtk_rekey_failure && | 7692 | (rdev->wiphy.wowlan_config->gtk_rekey_failure && |
7634 | nla_put_flag(msg, NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE)) || | 7693 | nla_put_flag(msg, NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE)) || |
7635 | (rdev->wowlan->eap_identity_req && | 7694 | (rdev->wiphy.wowlan_config->eap_identity_req && |
7636 | nla_put_flag(msg, NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST)) || | 7695 | nla_put_flag(msg, NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST)) || |
7637 | (rdev->wowlan->four_way_handshake && | 7696 | (rdev->wiphy.wowlan_config->four_way_handshake && |
7638 | nla_put_flag(msg, NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE)) || | 7697 | nla_put_flag(msg, NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE)) || |
7639 | (rdev->wowlan->rfkill_release && | 7698 | (rdev->wiphy.wowlan_config->rfkill_release && |
7640 | nla_put_flag(msg, NL80211_WOWLAN_TRIG_RFKILL_RELEASE))) | 7699 | nla_put_flag(msg, NL80211_WOWLAN_TRIG_RFKILL_RELEASE))) |
7641 | goto nla_put_failure; | 7700 | goto nla_put_failure; |
7642 | 7701 | ||
7643 | if (nl80211_send_wowlan_patterns(msg, rdev)) | 7702 | if (nl80211_send_wowlan_patterns(msg, rdev)) |
7644 | goto nla_put_failure; | 7703 | goto nla_put_failure; |
7645 | 7704 | ||
7646 | if (nl80211_send_wowlan_tcp(msg, rdev->wowlan->tcp)) | 7705 | if (nl80211_send_wowlan_tcp(msg, |
7706 | rdev->wiphy.wowlan_config->tcp)) | ||
7647 | goto nla_put_failure; | 7707 | goto nla_put_failure; |
7648 | 7708 | ||
7649 | nla_nest_end(msg, nl_wowlan); | 7709 | nla_nest_end(msg, nl_wowlan); |
@@ -7669,7 +7729,7 @@ static int nl80211_parse_wowlan_tcp(struct cfg80211_registered_device *rdev, | |||
7669 | u32 data_size, wake_size, tokens_size = 0, wake_mask_size; | 7729 | u32 data_size, wake_size, tokens_size = 0, wake_mask_size; |
7670 | int err, port; | 7730 | int err, port; |
7671 | 7731 | ||
7672 | if (!rdev->wiphy.wowlan.tcp) | 7732 | if (!rdev->wiphy.wowlan->tcp) |
7673 | return -EINVAL; | 7733 | return -EINVAL; |
7674 | 7734 | ||
7675 | err = nla_parse(tb, MAX_NL80211_WOWLAN_TCP, | 7735 | err = nla_parse(tb, MAX_NL80211_WOWLAN_TCP, |
@@ -7689,16 +7749,16 @@ static int nl80211_parse_wowlan_tcp(struct cfg80211_registered_device *rdev, | |||
7689 | return -EINVAL; | 7749 | return -EINVAL; |
7690 | 7750 | ||
7691 | data_size = nla_len(tb[NL80211_WOWLAN_TCP_DATA_PAYLOAD]); | 7751 | data_size = nla_len(tb[NL80211_WOWLAN_TCP_DATA_PAYLOAD]); |
7692 | if (data_size > rdev->wiphy.wowlan.tcp->data_payload_max) | 7752 | if (data_size > rdev->wiphy.wowlan->tcp->data_payload_max) |
7693 | return -EINVAL; | 7753 | return -EINVAL; |
7694 | 7754 | ||
7695 | if (nla_get_u32(tb[NL80211_WOWLAN_TCP_DATA_INTERVAL]) > | 7755 | if (nla_get_u32(tb[NL80211_WOWLAN_TCP_DATA_INTERVAL]) > |
7696 | rdev->wiphy.wowlan.tcp->data_interval_max || | 7756 | rdev->wiphy.wowlan->tcp->data_interval_max || |
7697 | nla_get_u32(tb[NL80211_WOWLAN_TCP_DATA_INTERVAL]) == 0) | 7757 | nla_get_u32(tb[NL80211_WOWLAN_TCP_DATA_INTERVAL]) == 0) |
7698 | return -EINVAL; | 7758 | return -EINVAL; |
7699 | 7759 | ||
7700 | wake_size = nla_len(tb[NL80211_WOWLAN_TCP_WAKE_PAYLOAD]); | 7760 | wake_size = nla_len(tb[NL80211_WOWLAN_TCP_WAKE_PAYLOAD]); |
7701 | if (wake_size > rdev->wiphy.wowlan.tcp->wake_payload_max) | 7761 | if (wake_size > rdev->wiphy.wowlan->tcp->wake_payload_max) |
7702 | return -EINVAL; | 7762 | return -EINVAL; |
7703 | 7763 | ||
7704 | wake_mask_size = nla_len(tb[NL80211_WOWLAN_TCP_WAKE_MASK]); | 7764 | wake_mask_size = nla_len(tb[NL80211_WOWLAN_TCP_WAKE_MASK]); |
@@ -7713,13 +7773,13 @@ static int nl80211_parse_wowlan_tcp(struct cfg80211_registered_device *rdev, | |||
7713 | 7773 | ||
7714 | if (!tok->len || tokens_size % tok->len) | 7774 | if (!tok->len || tokens_size % tok->len) |
7715 | return -EINVAL; | 7775 | return -EINVAL; |
7716 | if (!rdev->wiphy.wowlan.tcp->tok) | 7776 | if (!rdev->wiphy.wowlan->tcp->tok) |
7717 | return -EINVAL; | 7777 | return -EINVAL; |
7718 | if (tok->len > rdev->wiphy.wowlan.tcp->tok->max_len) | 7778 | if (tok->len > rdev->wiphy.wowlan->tcp->tok->max_len) |
7719 | return -EINVAL; | 7779 | return -EINVAL; |
7720 | if (tok->len < rdev->wiphy.wowlan.tcp->tok->min_len) | 7780 | if (tok->len < rdev->wiphy.wowlan->tcp->tok->min_len) |
7721 | return -EINVAL; | 7781 | return -EINVAL; |
7722 | if (tokens_size > rdev->wiphy.wowlan.tcp->tok->bufsize) | 7782 | if (tokens_size > rdev->wiphy.wowlan->tcp->tok->bufsize) |
7723 | return -EINVAL; | 7783 | return -EINVAL; |
7724 | if (tok->offset + tok->len > data_size) | 7784 | if (tok->offset + tok->len > data_size) |
7725 | return -EINVAL; | 7785 | return -EINVAL; |
@@ -7727,7 +7787,7 @@ static int nl80211_parse_wowlan_tcp(struct cfg80211_registered_device *rdev, | |||
7727 | 7787 | ||
7728 | if (tb[NL80211_WOWLAN_TCP_DATA_PAYLOAD_SEQ]) { | 7788 | if (tb[NL80211_WOWLAN_TCP_DATA_PAYLOAD_SEQ]) { |
7729 | seq = nla_data(tb[NL80211_WOWLAN_TCP_DATA_PAYLOAD_SEQ]); | 7789 | seq = nla_data(tb[NL80211_WOWLAN_TCP_DATA_PAYLOAD_SEQ]); |
7730 | if (!rdev->wiphy.wowlan.tcp->seq) | 7790 | if (!rdev->wiphy.wowlan->tcp->seq) |
7731 | return -EINVAL; | 7791 | return -EINVAL; |
7732 | if (seq->len == 0 || seq->len > 4) | 7792 | if (seq->len == 0 || seq->len > 4) |
7733 | return -EINVAL; | 7793 | return -EINVAL; |
@@ -7808,17 +7868,16 @@ static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info) | |||
7808 | struct nlattr *tb[NUM_NL80211_WOWLAN_TRIG]; | 7868 | struct nlattr *tb[NUM_NL80211_WOWLAN_TRIG]; |
7809 | struct cfg80211_wowlan new_triggers = {}; | 7869 | struct cfg80211_wowlan new_triggers = {}; |
7810 | struct cfg80211_wowlan *ntrig; | 7870 | struct cfg80211_wowlan *ntrig; |
7811 | struct wiphy_wowlan_support *wowlan = &rdev->wiphy.wowlan; | 7871 | const struct wiphy_wowlan_support *wowlan = rdev->wiphy.wowlan; |
7812 | int err, i; | 7872 | int err, i; |
7813 | bool prev_enabled = rdev->wowlan; | 7873 | bool prev_enabled = rdev->wiphy.wowlan_config; |
7814 | 7874 | ||
7815 | if (!rdev->wiphy.wowlan.flags && !rdev->wiphy.wowlan.n_patterns && | 7875 | if (!wowlan) |
7816 | !rdev->wiphy.wowlan.tcp) | ||
7817 | return -EOPNOTSUPP; | 7876 | return -EOPNOTSUPP; |
7818 | 7877 | ||
7819 | if (!info->attrs[NL80211_ATTR_WOWLAN_TRIGGERS]) { | 7878 | if (!info->attrs[NL80211_ATTR_WOWLAN_TRIGGERS]) { |
7820 | cfg80211_rdev_free_wowlan(rdev); | 7879 | cfg80211_rdev_free_wowlan(rdev); |
7821 | rdev->wowlan = NULL; | 7880 | rdev->wiphy.wowlan_config = NULL; |
7822 | goto set_wakeup; | 7881 | goto set_wakeup; |
7823 | } | 7882 | } |
7824 | 7883 | ||
@@ -7954,11 +8013,12 @@ static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info) | |||
7954 | goto error; | 8013 | goto error; |
7955 | } | 8014 | } |
7956 | cfg80211_rdev_free_wowlan(rdev); | 8015 | cfg80211_rdev_free_wowlan(rdev); |
7957 | rdev->wowlan = ntrig; | 8016 | rdev->wiphy.wowlan_config = ntrig; |
7958 | 8017 | ||
7959 | set_wakeup: | 8018 | set_wakeup: |
7960 | if (rdev->ops->set_wakeup && prev_enabled != !!rdev->wowlan) | 8019 | if (rdev->ops->set_wakeup && |
7961 | rdev_set_wakeup(rdev, rdev->wowlan); | 8020 | prev_enabled != !!rdev->wiphy.wowlan_config) |
8021 | rdev_set_wakeup(rdev, rdev->wiphy.wowlan_config); | ||
7962 | 8022 | ||
7963 | return 0; | 8023 | return 0; |
7964 | error: | 8024 | error: |
@@ -8143,9 +8203,7 @@ static int nl80211_start_p2p_device(struct sk_buff *skb, struct genl_info *info) | |||
8143 | if (wdev->p2p_started) | 8203 | if (wdev->p2p_started) |
8144 | return 0; | 8204 | return 0; |
8145 | 8205 | ||
8146 | mutex_lock(&rdev->devlist_mtx); | ||
8147 | err = cfg80211_can_add_interface(rdev, wdev->iftype); | 8206 | err = cfg80211_can_add_interface(rdev, wdev->iftype); |
8148 | mutex_unlock(&rdev->devlist_mtx); | ||
8149 | if (err) | 8207 | if (err) |
8150 | return err; | 8208 | return err; |
8151 | 8209 | ||
@@ -8154,9 +8212,7 @@ static int nl80211_start_p2p_device(struct sk_buff *skb, struct genl_info *info) | |||
8154 | return err; | 8212 | return err; |
8155 | 8213 | ||
8156 | wdev->p2p_started = true; | 8214 | wdev->p2p_started = true; |
8157 | mutex_lock(&rdev->devlist_mtx); | ||
8158 | rdev->opencount++; | 8215 | rdev->opencount++; |
8159 | mutex_unlock(&rdev->devlist_mtx); | ||
8160 | 8216 | ||
8161 | return 0; | 8217 | return 0; |
8162 | } | 8218 | } |
@@ -8172,11 +8228,7 @@ static int nl80211_stop_p2p_device(struct sk_buff *skb, struct genl_info *info) | |||
8172 | if (!rdev->ops->stop_p2p_device) | 8228 | if (!rdev->ops->stop_p2p_device) |
8173 | return -EOPNOTSUPP; | 8229 | return -EOPNOTSUPP; |
8174 | 8230 | ||
8175 | mutex_lock(&rdev->devlist_mtx); | ||
8176 | mutex_lock(&rdev->sched_scan_mtx); | ||
8177 | cfg80211_stop_p2p_device(rdev, wdev); | 8231 | cfg80211_stop_p2p_device(rdev, wdev); |
8178 | mutex_unlock(&rdev->sched_scan_mtx); | ||
8179 | mutex_unlock(&rdev->devlist_mtx); | ||
8180 | 8232 | ||
8181 | return 0; | 8233 | return 0; |
8182 | } | 8234 | } |
@@ -8319,11 +8371,11 @@ static int nl80211_pre_doit(struct genl_ops *ops, struct sk_buff *skb, | |||
8319 | info->user_ptr[0] = rdev; | 8371 | info->user_ptr[0] = rdev; |
8320 | } else if (ops->internal_flags & NL80211_FLAG_NEED_NETDEV || | 8372 | } else if (ops->internal_flags & NL80211_FLAG_NEED_NETDEV || |
8321 | ops->internal_flags & NL80211_FLAG_NEED_WDEV) { | 8373 | ops->internal_flags & NL80211_FLAG_NEED_WDEV) { |
8322 | mutex_lock(&cfg80211_mutex); | 8374 | ASSERT_RTNL(); |
8375 | |||
8323 | wdev = __cfg80211_wdev_from_attrs(genl_info_net(info), | 8376 | wdev = __cfg80211_wdev_from_attrs(genl_info_net(info), |
8324 | info->attrs); | 8377 | info->attrs); |
8325 | if (IS_ERR(wdev)) { | 8378 | if (IS_ERR(wdev)) { |
8326 | mutex_unlock(&cfg80211_mutex); | ||
8327 | if (rtnl) | 8379 | if (rtnl) |
8328 | rtnl_unlock(); | 8380 | rtnl_unlock(); |
8329 | return PTR_ERR(wdev); | 8381 | return PTR_ERR(wdev); |
@@ -8334,7 +8386,6 @@ static int nl80211_pre_doit(struct genl_ops *ops, struct sk_buff *skb, | |||
8334 | 8386 | ||
8335 | if (ops->internal_flags & NL80211_FLAG_NEED_NETDEV) { | 8387 | if (ops->internal_flags & NL80211_FLAG_NEED_NETDEV) { |
8336 | if (!dev) { | 8388 | if (!dev) { |
8337 | mutex_unlock(&cfg80211_mutex); | ||
8338 | if (rtnl) | 8389 | if (rtnl) |
8339 | rtnl_unlock(); | 8390 | rtnl_unlock(); |
8340 | return -EINVAL; | 8391 | return -EINVAL; |
@@ -8348,7 +8399,6 @@ static int nl80211_pre_doit(struct genl_ops *ops, struct sk_buff *skb, | |||
8348 | if (dev) { | 8399 | if (dev) { |
8349 | if (ops->internal_flags & NL80211_FLAG_CHECK_NETDEV_UP && | 8400 | if (ops->internal_flags & NL80211_FLAG_CHECK_NETDEV_UP && |
8350 | !netif_running(dev)) { | 8401 | !netif_running(dev)) { |
8351 | mutex_unlock(&cfg80211_mutex); | ||
8352 | if (rtnl) | 8402 | if (rtnl) |
8353 | rtnl_unlock(); | 8403 | rtnl_unlock(); |
8354 | return -ENETDOWN; | 8404 | return -ENETDOWN; |
@@ -8357,17 +8407,12 @@ static int nl80211_pre_doit(struct genl_ops *ops, struct sk_buff *skb, | |||
8357 | dev_hold(dev); | 8407 | dev_hold(dev); |
8358 | } else if (ops->internal_flags & NL80211_FLAG_CHECK_NETDEV_UP) { | 8408 | } else if (ops->internal_flags & NL80211_FLAG_CHECK_NETDEV_UP) { |
8359 | if (!wdev->p2p_started) { | 8409 | if (!wdev->p2p_started) { |
8360 | mutex_unlock(&cfg80211_mutex); | ||
8361 | if (rtnl) | 8410 | if (rtnl) |
8362 | rtnl_unlock(); | 8411 | rtnl_unlock(); |
8363 | return -ENETDOWN; | 8412 | return -ENETDOWN; |
8364 | } | 8413 | } |
8365 | } | 8414 | } |
8366 | 8415 | ||
8367 | cfg80211_lock_rdev(rdev); | ||
8368 | |||
8369 | mutex_unlock(&cfg80211_mutex); | ||
8370 | |||
8371 | info->user_ptr[0] = rdev; | 8416 | info->user_ptr[0] = rdev; |
8372 | } | 8417 | } |
8373 | 8418 | ||
@@ -8377,8 +8422,6 @@ static int nl80211_pre_doit(struct genl_ops *ops, struct sk_buff *skb, | |||
8377 | static void nl80211_post_doit(struct genl_ops *ops, struct sk_buff *skb, | 8422 | static void nl80211_post_doit(struct genl_ops *ops, struct sk_buff *skb, |
8378 | struct genl_info *info) | 8423 | struct genl_info *info) |
8379 | { | 8424 | { |
8380 | if (info->user_ptr[0]) | ||
8381 | cfg80211_unlock_rdev(info->user_ptr[0]); | ||
8382 | if (info->user_ptr[1]) { | 8425 | if (info->user_ptr[1]) { |
8383 | if (ops->internal_flags & NL80211_FLAG_NEED_WDEV) { | 8426 | if (ops->internal_flags & NL80211_FLAG_NEED_WDEV) { |
8384 | struct wireless_dev *wdev = info->user_ptr[1]; | 8427 | struct wireless_dev *wdev = info->user_ptr[1]; |
@@ -8398,9 +8441,11 @@ static struct genl_ops nl80211_ops[] = { | |||
8398 | .cmd = NL80211_CMD_GET_WIPHY, | 8441 | .cmd = NL80211_CMD_GET_WIPHY, |
8399 | .doit = nl80211_get_wiphy, | 8442 | .doit = nl80211_get_wiphy, |
8400 | .dumpit = nl80211_dump_wiphy, | 8443 | .dumpit = nl80211_dump_wiphy, |
8444 | .done = nl80211_dump_wiphy_done, | ||
8401 | .policy = nl80211_policy, | 8445 | .policy = nl80211_policy, |
8402 | /* can be retrieved by unprivileged users */ | 8446 | /* can be retrieved by unprivileged users */ |
8403 | .internal_flags = NL80211_FLAG_NEED_WIPHY, | 8447 | .internal_flags = NL80211_FLAG_NEED_WIPHY | |
8448 | NL80211_FLAG_NEED_RTNL, | ||
8404 | }, | 8449 | }, |
8405 | { | 8450 | { |
8406 | .cmd = NL80211_CMD_SET_WIPHY, | 8451 | .cmd = NL80211_CMD_SET_WIPHY, |
@@ -8415,7 +8460,8 @@ static struct genl_ops nl80211_ops[] = { | |||
8415 | .dumpit = nl80211_dump_interface, | 8460 | .dumpit = nl80211_dump_interface, |
8416 | .policy = nl80211_policy, | 8461 | .policy = nl80211_policy, |
8417 | /* can be retrieved by unprivileged users */ | 8462 | /* can be retrieved by unprivileged users */ |
8418 | .internal_flags = NL80211_FLAG_NEED_WDEV, | 8463 | .internal_flags = NL80211_FLAG_NEED_WDEV | |
8464 | NL80211_FLAG_NEED_RTNL, | ||
8419 | }, | 8465 | }, |
8420 | { | 8466 | { |
8421 | .cmd = NL80211_CMD_SET_INTERFACE, | 8467 | .cmd = NL80211_CMD_SET_INTERFACE, |
@@ -8574,6 +8620,7 @@ static struct genl_ops nl80211_ops[] = { | |||
8574 | .cmd = NL80211_CMD_GET_REG, | 8620 | .cmd = NL80211_CMD_GET_REG, |
8575 | .doit = nl80211_get_reg, | 8621 | .doit = nl80211_get_reg, |
8576 | .policy = nl80211_policy, | 8622 | .policy = nl80211_policy, |
8623 | .internal_flags = NL80211_FLAG_NEED_RTNL, | ||
8577 | /* can be retrieved by unprivileged users */ | 8624 | /* can be retrieved by unprivileged users */ |
8578 | }, | 8625 | }, |
8579 | { | 8626 | { |
@@ -8581,6 +8628,7 @@ static struct genl_ops nl80211_ops[] = { | |||
8581 | .doit = nl80211_set_reg, | 8628 | .doit = nl80211_set_reg, |
8582 | .policy = nl80211_policy, | 8629 | .policy = nl80211_policy, |
8583 | .flags = GENL_ADMIN_PERM, | 8630 | .flags = GENL_ADMIN_PERM, |
8631 | .internal_flags = NL80211_FLAG_NEED_RTNL, | ||
8584 | }, | 8632 | }, |
8585 | { | 8633 | { |
8586 | .cmd = NL80211_CMD_REQ_SET_REG, | 8634 | .cmd = NL80211_CMD_REQ_SET_REG, |
@@ -9014,13 +9062,13 @@ static struct genl_multicast_group nl80211_regulatory_mcgrp = { | |||
9014 | void nl80211_notify_dev_rename(struct cfg80211_registered_device *rdev) | 9062 | void nl80211_notify_dev_rename(struct cfg80211_registered_device *rdev) |
9015 | { | 9063 | { |
9016 | struct sk_buff *msg; | 9064 | struct sk_buff *msg; |
9065 | struct nl80211_dump_wiphy_state state = {}; | ||
9017 | 9066 | ||
9018 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); | 9067 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); |
9019 | if (!msg) | 9068 | if (!msg) |
9020 | return; | 9069 | return; |
9021 | 9070 | ||
9022 | if (nl80211_send_wiphy(rdev, msg, 0, 0, 0, | 9071 | if (nl80211_send_wiphy(rdev, msg, 0, 0, 0, &state) < 0) { |
9023 | false, NULL, NULL, NULL) < 0) { | ||
9024 | nlmsg_free(msg); | 9072 | nlmsg_free(msg); |
9025 | return; | 9073 | return; |
9026 | } | 9074 | } |
@@ -9036,8 +9084,6 @@ static int nl80211_add_scan_req(struct sk_buff *msg, | |||
9036 | struct nlattr *nest; | 9084 | struct nlattr *nest; |
9037 | int i; | 9085 | int i; |
9038 | 9086 | ||
9039 | lockdep_assert_held(&rdev->sched_scan_mtx); | ||
9040 | |||
9041 | if (WARN_ON(!req)) | 9087 | if (WARN_ON(!req)) |
9042 | return 0; | 9088 | return 0; |
9043 | 9089 | ||
@@ -9344,31 +9390,27 @@ void nl80211_send_disassoc(struct cfg80211_registered_device *rdev, | |||
9344 | NL80211_CMD_DISASSOCIATE, gfp); | 9390 | NL80211_CMD_DISASSOCIATE, gfp); |
9345 | } | 9391 | } |
9346 | 9392 | ||
9347 | void cfg80211_send_unprot_deauth(struct net_device *dev, const u8 *buf, | 9393 | void cfg80211_rx_unprot_mlme_mgmt(struct net_device *dev, const u8 *buf, |
9348 | size_t len) | 9394 | size_t len) |
9349 | { | 9395 | { |
9350 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 9396 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
9351 | struct wiphy *wiphy = wdev->wiphy; | 9397 | struct wiphy *wiphy = wdev->wiphy; |
9352 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | 9398 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); |
9399 | const struct ieee80211_mgmt *mgmt = (void *)buf; | ||
9400 | u32 cmd; | ||
9353 | 9401 | ||
9354 | trace_cfg80211_send_unprot_deauth(dev); | 9402 | if (WARN_ON(len < 2)) |
9355 | nl80211_send_mlme_event(rdev, dev, buf, len, | 9403 | return; |
9356 | NL80211_CMD_UNPROT_DEAUTHENTICATE, GFP_ATOMIC); | ||
9357 | } | ||
9358 | EXPORT_SYMBOL(cfg80211_send_unprot_deauth); | ||
9359 | 9404 | ||
9360 | void cfg80211_send_unprot_disassoc(struct net_device *dev, const u8 *buf, | 9405 | if (ieee80211_is_deauth(mgmt->frame_control)) |
9361 | size_t len) | 9406 | cmd = NL80211_CMD_UNPROT_DEAUTHENTICATE; |
9362 | { | 9407 | else |
9363 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 9408 | cmd = NL80211_CMD_UNPROT_DISASSOCIATE; |
9364 | struct wiphy *wiphy = wdev->wiphy; | ||
9365 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | ||
9366 | 9409 | ||
9367 | trace_cfg80211_send_unprot_disassoc(dev); | 9410 | trace_cfg80211_rx_unprot_mlme_mgmt(dev, buf, len); |
9368 | nl80211_send_mlme_event(rdev, dev, buf, len, | 9411 | nl80211_send_mlme_event(rdev, dev, buf, len, cmd, GFP_ATOMIC); |
9369 | NL80211_CMD_UNPROT_DISASSOCIATE, GFP_ATOMIC); | ||
9370 | } | 9412 | } |
9371 | EXPORT_SYMBOL(cfg80211_send_unprot_disassoc); | 9413 | EXPORT_SYMBOL(cfg80211_rx_unprot_mlme_mgmt); |
9372 | 9414 | ||
9373 | static void nl80211_send_mlme_timeout(struct cfg80211_registered_device *rdev, | 9415 | static void nl80211_send_mlme_timeout(struct cfg80211_registered_device *rdev, |
9374 | struct net_device *netdev, int cmd, | 9416 | struct net_device *netdev, int cmd, |
@@ -9879,7 +9921,6 @@ static bool __nl80211_unexpected_frame(struct net_device *dev, u8 cmd, | |||
9879 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); | 9921 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); |
9880 | struct sk_buff *msg; | 9922 | struct sk_buff *msg; |
9881 | void *hdr; | 9923 | void *hdr; |
9882 | int err; | ||
9883 | u32 nlportid = ACCESS_ONCE(wdev->ap_unexpected_nlportid); | 9924 | u32 nlportid = ACCESS_ONCE(wdev->ap_unexpected_nlportid); |
9884 | 9925 | ||
9885 | if (!nlportid) | 9926 | if (!nlportid) |
@@ -9900,12 +9941,7 @@ static bool __nl80211_unexpected_frame(struct net_device *dev, u8 cmd, | |||
9900 | nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr)) | 9941 | nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr)) |
9901 | goto nla_put_failure; | 9942 | goto nla_put_failure; |
9902 | 9943 | ||
9903 | err = genlmsg_end(msg, hdr); | 9944 | genlmsg_end(msg, hdr); |
9904 | if (err < 0) { | ||
9905 | nlmsg_free(msg); | ||
9906 | return true; | ||
9907 | } | ||
9908 | |||
9909 | genlmsg_unicast(wiphy_net(&rdev->wiphy), msg, nlportid); | 9945 | genlmsg_unicast(wiphy_net(&rdev->wiphy), msg, nlportid); |
9910 | return true; | 9946 | return true; |
9911 | 9947 | ||
@@ -10348,10 +10384,7 @@ nl80211_radar_notify(struct cfg80211_registered_device *rdev, | |||
10348 | if (nl80211_send_chandef(msg, chandef)) | 10384 | if (nl80211_send_chandef(msg, chandef)) |
10349 | goto nla_put_failure; | 10385 | goto nla_put_failure; |
10350 | 10386 | ||
10351 | if (genlmsg_end(msg, hdr) < 0) { | 10387 | genlmsg_end(msg, hdr); |
10352 | nlmsg_free(msg); | ||
10353 | return; | ||
10354 | } | ||
10355 | 10388 | ||
10356 | genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0, | 10389 | genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0, |
10357 | nl80211_mlme_mcgrp.id, gfp); | 10390 | nl80211_mlme_mcgrp.id, gfp); |
@@ -10417,7 +10450,6 @@ void cfg80211_probe_status(struct net_device *dev, const u8 *addr, | |||
10417 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); | 10450 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); |
10418 | struct sk_buff *msg; | 10451 | struct sk_buff *msg; |
10419 | void *hdr; | 10452 | void *hdr; |
10420 | int err; | ||
10421 | 10453 | ||
10422 | trace_cfg80211_probe_status(dev, addr, cookie, acked); | 10454 | trace_cfg80211_probe_status(dev, addr, cookie, acked); |
10423 | 10455 | ||
@@ -10439,11 +10471,7 @@ void cfg80211_probe_status(struct net_device *dev, const u8 *addr, | |||
10439 | (acked && nla_put_flag(msg, NL80211_ATTR_ACK))) | 10471 | (acked && nla_put_flag(msg, NL80211_ATTR_ACK))) |
10440 | goto nla_put_failure; | 10472 | goto nla_put_failure; |
10441 | 10473 | ||
10442 | err = genlmsg_end(msg, hdr); | 10474 | genlmsg_end(msg, hdr); |
10443 | if (err < 0) { | ||
10444 | nlmsg_free(msg); | ||
10445 | return; | ||
10446 | } | ||
10447 | 10475 | ||
10448 | genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0, | 10476 | genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0, |
10449 | nl80211_mlme_mcgrp.id, gfp); | 10477 | nl80211_mlme_mcgrp.id, gfp); |
@@ -10509,7 +10537,7 @@ void cfg80211_report_wowlan_wakeup(struct wireless_dev *wdev, | |||
10509 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); | 10537 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); |
10510 | struct sk_buff *msg; | 10538 | struct sk_buff *msg; |
10511 | void *hdr; | 10539 | void *hdr; |
10512 | int err, size = 200; | 10540 | int size = 200; |
10513 | 10541 | ||
10514 | trace_cfg80211_report_wowlan_wakeup(wdev->wiphy, wdev, wakeup); | 10542 | trace_cfg80211_report_wowlan_wakeup(wdev->wiphy, wdev, wakeup); |
10515 | 10543 | ||
@@ -10595,9 +10623,7 @@ void cfg80211_report_wowlan_wakeup(struct wireless_dev *wdev, | |||
10595 | nla_nest_end(msg, reasons); | 10623 | nla_nest_end(msg, reasons); |
10596 | } | 10624 | } |
10597 | 10625 | ||
10598 | err = genlmsg_end(msg, hdr); | 10626 | genlmsg_end(msg, hdr); |
10599 | if (err < 0) | ||
10600 | goto free_msg; | ||
10601 | 10627 | ||
10602 | genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0, | 10628 | genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0, |
10603 | nl80211_mlme_mcgrp.id, gfp); | 10629 | nl80211_mlme_mcgrp.id, gfp); |
@@ -10617,7 +10643,6 @@ void cfg80211_tdls_oper_request(struct net_device *dev, const u8 *peer, | |||
10617 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); | 10643 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); |
10618 | struct sk_buff *msg; | 10644 | struct sk_buff *msg; |
10619 | void *hdr; | 10645 | void *hdr; |
10620 | int err; | ||
10621 | 10646 | ||
10622 | trace_cfg80211_tdls_oper_request(wdev->wiphy, dev, peer, oper, | 10647 | trace_cfg80211_tdls_oper_request(wdev->wiphy, dev, peer, oper, |
10623 | reason_code); | 10648 | reason_code); |
@@ -10640,11 +10665,7 @@ void cfg80211_tdls_oper_request(struct net_device *dev, const u8 *peer, | |||
10640 | nla_put_u16(msg, NL80211_ATTR_REASON_CODE, reason_code))) | 10665 | nla_put_u16(msg, NL80211_ATTR_REASON_CODE, reason_code))) |
10641 | goto nla_put_failure; | 10666 | goto nla_put_failure; |
10642 | 10667 | ||
10643 | err = genlmsg_end(msg, hdr); | 10668 | genlmsg_end(msg, hdr); |
10644 | if (err < 0) { | ||
10645 | nlmsg_free(msg); | ||
10646 | return; | ||
10647 | } | ||
10648 | 10669 | ||
10649 | genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0, | 10670 | genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0, |
10650 | nl80211_mlme_mcgrp.id, gfp); | 10671 | nl80211_mlme_mcgrp.id, gfp); |
@@ -10702,7 +10723,6 @@ void cfg80211_ft_event(struct net_device *netdev, | |||
10702 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | 10723 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); |
10703 | struct sk_buff *msg; | 10724 | struct sk_buff *msg; |
10704 | void *hdr; | 10725 | void *hdr; |
10705 | int err; | ||
10706 | 10726 | ||
10707 | trace_cfg80211_ft_event(wiphy, netdev, ft_event); | 10727 | trace_cfg80211_ft_event(wiphy, netdev, ft_event); |
10708 | 10728 | ||
@@ -10728,11 +10748,7 @@ void cfg80211_ft_event(struct net_device *netdev, | |||
10728 | nla_put(msg, NL80211_ATTR_IE_RIC, ft_event->ric_ies_len, | 10748 | nla_put(msg, NL80211_ATTR_IE_RIC, ft_event->ric_ies_len, |
10729 | ft_event->ric_ies); | 10749 | ft_event->ric_ies); |
10730 | 10750 | ||
10731 | err = genlmsg_end(msg, hdr); | 10751 | genlmsg_end(msg, hdr); |
10732 | if (err < 0) { | ||
10733 | nlmsg_free(msg); | ||
10734 | return; | ||
10735 | } | ||
10736 | 10752 | ||
10737 | genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0, | 10753 | genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0, |
10738 | nl80211_mlme_mcgrp.id, GFP_KERNEL); | 10754 | nl80211_mlme_mcgrp.id, GFP_KERNEL); |