aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless/nl80211.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/wireless/nl80211.c')
-rw-r--r--net/wireless/nl80211.c417
1 files changed, 405 insertions, 12 deletions
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 572793c8c7ab..1e728fff474e 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -58,6 +58,9 @@ static struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] __read_mostly = {
58 [NL80211_ATTR_WIPHY] = { .type = NLA_U32 }, 58 [NL80211_ATTR_WIPHY] = { .type = NLA_U32 },
59 [NL80211_ATTR_WIPHY_NAME] = { .type = NLA_NUL_STRING, 59 [NL80211_ATTR_WIPHY_NAME] = { .type = NLA_NUL_STRING,
60 .len = BUS_ID_SIZE-1 }, 60 .len = BUS_ID_SIZE-1 },
61 [NL80211_ATTR_WIPHY_TXQ_PARAMS] = { .type = NLA_NESTED },
62 [NL80211_ATTR_WIPHY_FREQ] = { .type = NLA_U32 },
63 [NL80211_ATTR_WIPHY_CHANNEL_TYPE] = { .type = NLA_U32 },
61 64
62 [NL80211_ATTR_IFTYPE] = { .type = NLA_U32 }, 65 [NL80211_ATTR_IFTYPE] = { .type = NLA_U32 },
63 [NL80211_ATTR_IFINDEX] = { .type = NLA_U32 }, 66 [NL80211_ATTR_IFINDEX] = { .type = NLA_U32 },
@@ -84,7 +87,7 @@ static struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] __read_mostly = {
84 .len = NL80211_MAX_SUPP_RATES }, 87 .len = NL80211_MAX_SUPP_RATES },
85 [NL80211_ATTR_STA_PLINK_ACTION] = { .type = NLA_U8 }, 88 [NL80211_ATTR_STA_PLINK_ACTION] = { .type = NLA_U8 },
86 [NL80211_ATTR_STA_VLAN] = { .type = NLA_U32 }, 89 [NL80211_ATTR_STA_VLAN] = { .type = NLA_U32 },
87 [NL80211_ATTR_MNTR_FLAGS] = { .type = NLA_NESTED }, 90 [NL80211_ATTR_MNTR_FLAGS] = { /* NLA_NESTED can't be empty */ },
88 [NL80211_ATTR_MESH_ID] = { .type = NLA_BINARY, 91 [NL80211_ATTR_MESH_ID] = { .type = NLA_BINARY,
89 .len = IEEE80211_MAX_MESH_ID_LEN }, 92 .len = IEEE80211_MAX_MESH_ID_LEN },
90 [NL80211_ATTR_MPATH_NEXT_HOP] = { .type = NLA_U32 }, 93 [NL80211_ATTR_MPATH_NEXT_HOP] = { .type = NLA_U32 },
@@ -95,6 +98,10 @@ static struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] __read_mostly = {
95 [NL80211_ATTR_BSS_CTS_PROT] = { .type = NLA_U8 }, 98 [NL80211_ATTR_BSS_CTS_PROT] = { .type = NLA_U8 },
96 [NL80211_ATTR_BSS_SHORT_PREAMBLE] = { .type = NLA_U8 }, 99 [NL80211_ATTR_BSS_SHORT_PREAMBLE] = { .type = NLA_U8 },
97 [NL80211_ATTR_BSS_SHORT_SLOT_TIME] = { .type = NLA_U8 }, 100 [NL80211_ATTR_BSS_SHORT_SLOT_TIME] = { .type = NLA_U8 },
101 [NL80211_ATTR_BSS_BASIC_RATES] = { .type = NLA_BINARY,
102 .len = NL80211_MAX_SUPP_RATES },
103
104 [NL80211_ATTR_MESH_PARAMS] = { .type = NLA_NESTED },
98 105
99 [NL80211_ATTR_HT_CAPABILITY] = { .type = NLA_BINARY, 106 [NL80211_ATTR_HT_CAPABILITY] = { .type = NLA_BINARY,
100 .len = NL80211_HT_CAPABILITY_LEN }, 107 .len = NL80211_HT_CAPABILITY_LEN },
@@ -157,6 +164,19 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags,
157 if (!nl_band) 164 if (!nl_band)
158 goto nla_put_failure; 165 goto nla_put_failure;
159 166
167 /* add HT info */
168 if (dev->wiphy.bands[band]->ht_cap.ht_supported) {
169 NLA_PUT(msg, NL80211_BAND_ATTR_HT_MCS_SET,
170 sizeof(dev->wiphy.bands[band]->ht_cap.mcs),
171 &dev->wiphy.bands[band]->ht_cap.mcs);
172 NLA_PUT_U16(msg, NL80211_BAND_ATTR_HT_CAPA,
173 dev->wiphy.bands[band]->ht_cap.cap);
174 NLA_PUT_U8(msg, NL80211_BAND_ATTR_HT_AMPDU_FACTOR,
175 dev->wiphy.bands[band]->ht_cap.ampdu_factor);
176 NLA_PUT_U8(msg, NL80211_BAND_ATTR_HT_AMPDU_DENSITY,
177 dev->wiphy.bands[band]->ht_cap.ampdu_density);
178 }
179
160 /* add frequencies */ 180 /* add frequencies */
161 nl_freqs = nla_nest_start(msg, NL80211_BAND_ATTR_FREQS); 181 nl_freqs = nla_nest_start(msg, NL80211_BAND_ATTR_FREQS);
162 if (!nl_freqs) 182 if (!nl_freqs)
@@ -180,6 +200,9 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags,
180 if (chan->flags & IEEE80211_CHAN_RADAR) 200 if (chan->flags & IEEE80211_CHAN_RADAR)
181 NLA_PUT_FLAG(msg, NL80211_FREQUENCY_ATTR_RADAR); 201 NLA_PUT_FLAG(msg, NL80211_FREQUENCY_ATTR_RADAR);
182 202
203 NLA_PUT_U32(msg, NL80211_FREQUENCY_ATTR_MAX_TX_POWER,
204 DBM_TO_MBM(chan->max_power));
205
183 nla_nest_end(msg, nl_freq); 206 nla_nest_end(msg, nl_freq);
184 } 207 }
185 208
@@ -269,20 +292,142 @@ static int nl80211_get_wiphy(struct sk_buff *skb, struct genl_info *info)
269 return -ENOBUFS; 292 return -ENOBUFS;
270} 293}
271 294
295static const struct nla_policy txq_params_policy[NL80211_TXQ_ATTR_MAX + 1] = {
296 [NL80211_TXQ_ATTR_QUEUE] = { .type = NLA_U8 },
297 [NL80211_TXQ_ATTR_TXOP] = { .type = NLA_U16 },
298 [NL80211_TXQ_ATTR_CWMIN] = { .type = NLA_U16 },
299 [NL80211_TXQ_ATTR_CWMAX] = { .type = NLA_U16 },
300 [NL80211_TXQ_ATTR_AIFS] = { .type = NLA_U8 },
301};
302
303static int parse_txq_params(struct nlattr *tb[],
304 struct ieee80211_txq_params *txq_params)
305{
306 if (!tb[NL80211_TXQ_ATTR_QUEUE] || !tb[NL80211_TXQ_ATTR_TXOP] ||
307 !tb[NL80211_TXQ_ATTR_CWMIN] || !tb[NL80211_TXQ_ATTR_CWMAX] ||
308 !tb[NL80211_TXQ_ATTR_AIFS])
309 return -EINVAL;
310
311 txq_params->queue = nla_get_u8(tb[NL80211_TXQ_ATTR_QUEUE]);
312 txq_params->txop = nla_get_u16(tb[NL80211_TXQ_ATTR_TXOP]);
313 txq_params->cwmin = nla_get_u16(tb[NL80211_TXQ_ATTR_CWMIN]);
314 txq_params->cwmax = nla_get_u16(tb[NL80211_TXQ_ATTR_CWMAX]);
315 txq_params->aifs = nla_get_u8(tb[NL80211_TXQ_ATTR_AIFS]);
316
317 return 0;
318}
319
272static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) 320static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
273{ 321{
274 struct cfg80211_registered_device *rdev; 322 struct cfg80211_registered_device *rdev;
275 int result; 323 int result = 0, rem_txq_params = 0;
276 324 struct nlattr *nl_txq_params;
277 if (!info->attrs[NL80211_ATTR_WIPHY_NAME])
278 return -EINVAL;
279 325
280 rdev = cfg80211_get_dev_from_info(info); 326 rdev = cfg80211_get_dev_from_info(info);
281 if (IS_ERR(rdev)) 327 if (IS_ERR(rdev))
282 return PTR_ERR(rdev); 328 return PTR_ERR(rdev);
283 329
284 result = cfg80211_dev_rename(rdev, nla_data(info->attrs[NL80211_ATTR_WIPHY_NAME])); 330 if (info->attrs[NL80211_ATTR_WIPHY_NAME]) {
331 result = cfg80211_dev_rename(
332 rdev, nla_data(info->attrs[NL80211_ATTR_WIPHY_NAME]));
333 if (result)
334 goto bad_res;
335 }
336
337 if (info->attrs[NL80211_ATTR_WIPHY_TXQ_PARAMS]) {
338 struct ieee80211_txq_params txq_params;
339 struct nlattr *tb[NL80211_TXQ_ATTR_MAX + 1];
340
341 if (!rdev->ops->set_txq_params) {
342 result = -EOPNOTSUPP;
343 goto bad_res;
344 }
345
346 nla_for_each_nested(nl_txq_params,
347 info->attrs[NL80211_ATTR_WIPHY_TXQ_PARAMS],
348 rem_txq_params) {
349 nla_parse(tb, NL80211_TXQ_ATTR_MAX,
350 nla_data(nl_txq_params),
351 nla_len(nl_txq_params),
352 txq_params_policy);
353 result = parse_txq_params(tb, &txq_params);
354 if (result)
355 goto bad_res;
356
357 result = rdev->ops->set_txq_params(&rdev->wiphy,
358 &txq_params);
359 if (result)
360 goto bad_res;
361 }
362 }
363
364 if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) {
365 enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT;
366 struct ieee80211_channel *chan;
367 struct ieee80211_sta_ht_cap *ht_cap;
368 u32 freq, sec_freq;
369
370 if (!rdev->ops->set_channel) {
371 result = -EOPNOTSUPP;
372 goto bad_res;
373 }
374
375 result = -EINVAL;
376
377 if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) {
378 channel_type = nla_get_u32(info->attrs[
379 NL80211_ATTR_WIPHY_CHANNEL_TYPE]);
380 if (channel_type != NL80211_CHAN_NO_HT &&
381 channel_type != NL80211_CHAN_HT20 &&
382 channel_type != NL80211_CHAN_HT40PLUS &&
383 channel_type != NL80211_CHAN_HT40MINUS)
384 goto bad_res;
385 }
386
387 freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]);
388 chan = ieee80211_get_channel(&rdev->wiphy, freq);
389
390 /* Primary channel not allowed */
391 if (!chan || chan->flags & IEEE80211_CHAN_DISABLED)
392 goto bad_res;
393
394 if (channel_type == NL80211_CHAN_HT40MINUS)
395 sec_freq = freq - 20;
396 else if (channel_type == NL80211_CHAN_HT40PLUS)
397 sec_freq = freq + 20;
398 else
399 sec_freq = 0;
400
401 ht_cap = &rdev->wiphy.bands[chan->band]->ht_cap;
285 402
403 /* no HT capabilities */
404 if (channel_type != NL80211_CHAN_NO_HT &&
405 !ht_cap->ht_supported)
406 goto bad_res;
407
408 if (sec_freq) {
409 struct ieee80211_channel *schan;
410
411 /* no 40 MHz capabilities */
412 if (!(ht_cap->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) ||
413 (ht_cap->cap & IEEE80211_HT_CAP_40MHZ_INTOLERANT))
414 goto bad_res;
415
416 schan = ieee80211_get_channel(&rdev->wiphy, sec_freq);
417
418 /* Secondary channel not allowed */
419 if (!schan || schan->flags & IEEE80211_CHAN_DISABLED)
420 goto bad_res;
421 }
422
423 result = rdev->ops->set_channel(&rdev->wiphy, chan,
424 channel_type);
425 if (result)
426 goto bad_res;
427 }
428
429
430 bad_res:
286 cfg80211_put_dev(rdev); 431 cfg80211_put_dev(rdev);
287 return result; 432 return result;
288} 433}
@@ -945,12 +1090,46 @@ static int parse_station_flags(struct nlattr *nla, u32 *staflags)
945 return 0; 1090 return 0;
946} 1091}
947 1092
1093static u16 nl80211_calculate_bitrate(struct rate_info *rate)
1094{
1095 int modulation, streams, bitrate;
1096
1097 if (!(rate->flags & RATE_INFO_FLAGS_MCS))
1098 return rate->legacy;
1099
1100 /* the formula below does only work for MCS values smaller than 32 */
1101 if (rate->mcs >= 32)
1102 return 0;
1103
1104 modulation = rate->mcs & 7;
1105 streams = (rate->mcs >> 3) + 1;
1106
1107 bitrate = (rate->flags & RATE_INFO_FLAGS_40_MHZ_WIDTH) ?
1108 13500000 : 6500000;
1109
1110 if (modulation < 4)
1111 bitrate *= (modulation + 1);
1112 else if (modulation == 4)
1113 bitrate *= (modulation + 2);
1114 else
1115 bitrate *= (modulation + 3);
1116
1117 bitrate *= streams;
1118
1119 if (rate->flags & RATE_INFO_FLAGS_SHORT_GI)
1120 bitrate = (bitrate / 9) * 10;
1121
1122 /* do NOT round down here */
1123 return (bitrate + 50000) / 100000;
1124}
1125
948static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq, 1126static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq,
949 int flags, struct net_device *dev, 1127 int flags, struct net_device *dev,
950 u8 *mac_addr, struct station_info *sinfo) 1128 u8 *mac_addr, struct station_info *sinfo)
951{ 1129{
952 void *hdr; 1130 void *hdr;
953 struct nlattr *sinfoattr; 1131 struct nlattr *sinfoattr, *txrate;
1132 u16 bitrate;
954 1133
955 hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_STATION); 1134 hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_STATION);
956 if (!hdr) 1135 if (!hdr)
@@ -980,7 +1159,29 @@ static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq,
980 if (sinfo->filled & STATION_INFO_PLINK_STATE) 1159 if (sinfo->filled & STATION_INFO_PLINK_STATE)
981 NLA_PUT_U8(msg, NL80211_STA_INFO_PLINK_STATE, 1160 NLA_PUT_U8(msg, NL80211_STA_INFO_PLINK_STATE,
982 sinfo->plink_state); 1161 sinfo->plink_state);
1162 if (sinfo->filled & STATION_INFO_SIGNAL)
1163 NLA_PUT_U8(msg, NL80211_STA_INFO_SIGNAL,
1164 sinfo->signal);
1165 if (sinfo->filled & STATION_INFO_TX_BITRATE) {
1166 txrate = nla_nest_start(msg, NL80211_STA_INFO_TX_BITRATE);
1167 if (!txrate)
1168 goto nla_put_failure;
1169
1170 /* nl80211_calculate_bitrate will return 0 for mcs >= 32 */
1171 bitrate = nl80211_calculate_bitrate(&sinfo->txrate);
1172 if (bitrate > 0)
1173 NLA_PUT_U16(msg, NL80211_RATE_INFO_BITRATE, bitrate);
1174
1175 if (sinfo->txrate.flags & RATE_INFO_FLAGS_MCS)
1176 NLA_PUT_U8(msg, NL80211_RATE_INFO_MCS,
1177 sinfo->txrate.mcs);
1178 if (sinfo->txrate.flags & RATE_INFO_FLAGS_40_MHZ_WIDTH)
1179 NLA_PUT_FLAG(msg, NL80211_RATE_INFO_40_MHZ_WIDTH);
1180 if (sinfo->txrate.flags & RATE_INFO_FLAGS_SHORT_GI)
1181 NLA_PUT_FLAG(msg, NL80211_RATE_INFO_SHORT_GI);
983 1182
1183 nla_nest_end(msg, txrate);
1184 }
984 nla_nest_end(msg, sinfoattr); 1185 nla_nest_end(msg, sinfoattr);
985 1186
986 return genlmsg_end(msg, hdr); 1187 return genlmsg_end(msg, hdr);
@@ -1598,6 +1799,12 @@ static int nl80211_set_bss(struct sk_buff *skb, struct genl_info *info)
1598 if (info->attrs[NL80211_ATTR_BSS_SHORT_SLOT_TIME]) 1799 if (info->attrs[NL80211_ATTR_BSS_SHORT_SLOT_TIME])
1599 params.use_short_slot_time = 1800 params.use_short_slot_time =
1600 nla_get_u8(info->attrs[NL80211_ATTR_BSS_SHORT_SLOT_TIME]); 1801 nla_get_u8(info->attrs[NL80211_ATTR_BSS_SHORT_SLOT_TIME]);
1802 if (info->attrs[NL80211_ATTR_BSS_BASIC_RATES]) {
1803 params.basic_rates =
1804 nla_data(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]);
1805 params.basic_rates_len =
1806 nla_len(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]);
1807 }
1601 1808
1602 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); 1809 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
1603 if (err) 1810 if (err)
@@ -1680,11 +1887,188 @@ static int nl80211_req_set_reg(struct sk_buff *skb, struct genl_info *info)
1680 return -EINVAL; 1887 return -EINVAL;
1681#endif 1888#endif
1682 mutex_lock(&cfg80211_drv_mutex); 1889 mutex_lock(&cfg80211_drv_mutex);
1683 r = __regulatory_hint(NULL, REGDOM_SET_BY_USER, data, NULL); 1890 r = __regulatory_hint(NULL, REGDOM_SET_BY_USER, data, 0, ENVIRON_ANY);
1684 mutex_unlock(&cfg80211_drv_mutex); 1891 mutex_unlock(&cfg80211_drv_mutex);
1685 return r; 1892 return r;
1686} 1893}
1687 1894
1895static int nl80211_get_mesh_params(struct sk_buff *skb,
1896 struct genl_info *info)
1897{
1898 struct cfg80211_registered_device *drv;
1899 struct mesh_config cur_params;
1900 int err;
1901 struct net_device *dev;
1902 void *hdr;
1903 struct nlattr *pinfoattr;
1904 struct sk_buff *msg;
1905
1906 /* Look up our device */
1907 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
1908 if (err)
1909 return err;
1910
1911 /* Get the mesh params */
1912 rtnl_lock();
1913 err = drv->ops->get_mesh_params(&drv->wiphy, dev, &cur_params);
1914 rtnl_unlock();
1915 if (err)
1916 goto out;
1917
1918 /* Draw up a netlink message to send back */
1919 msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
1920 if (!msg) {
1921 err = -ENOBUFS;
1922 goto out;
1923 }
1924 hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0,
1925 NL80211_CMD_GET_MESH_PARAMS);
1926 if (!hdr)
1927 goto nla_put_failure;
1928 pinfoattr = nla_nest_start(msg, NL80211_ATTR_MESH_PARAMS);
1929 if (!pinfoattr)
1930 goto nla_put_failure;
1931 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex);
1932 NLA_PUT_U16(msg, NL80211_MESHCONF_RETRY_TIMEOUT,
1933 cur_params.dot11MeshRetryTimeout);
1934 NLA_PUT_U16(msg, NL80211_MESHCONF_CONFIRM_TIMEOUT,
1935 cur_params.dot11MeshConfirmTimeout);
1936 NLA_PUT_U16(msg, NL80211_MESHCONF_HOLDING_TIMEOUT,
1937 cur_params.dot11MeshHoldingTimeout);
1938 NLA_PUT_U16(msg, NL80211_MESHCONF_MAX_PEER_LINKS,
1939 cur_params.dot11MeshMaxPeerLinks);
1940 NLA_PUT_U8(msg, NL80211_MESHCONF_MAX_RETRIES,
1941 cur_params.dot11MeshMaxRetries);
1942 NLA_PUT_U8(msg, NL80211_MESHCONF_TTL,
1943 cur_params.dot11MeshTTL);
1944 NLA_PUT_U8(msg, NL80211_MESHCONF_AUTO_OPEN_PLINKS,
1945 cur_params.auto_open_plinks);
1946 NLA_PUT_U8(msg, NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES,
1947 cur_params.dot11MeshHWMPmaxPREQretries);
1948 NLA_PUT_U32(msg, NL80211_MESHCONF_PATH_REFRESH_TIME,
1949 cur_params.path_refresh_time);
1950 NLA_PUT_U16(msg, NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT,
1951 cur_params.min_discovery_timeout);
1952 NLA_PUT_U32(msg, NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT,
1953 cur_params.dot11MeshHWMPactivePathTimeout);
1954 NLA_PUT_U16(msg, NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL,
1955 cur_params.dot11MeshHWMPpreqMinInterval);
1956 NLA_PUT_U16(msg, NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME,
1957 cur_params.dot11MeshHWMPnetDiameterTraversalTime);
1958 nla_nest_end(msg, pinfoattr);
1959 genlmsg_end(msg, hdr);
1960 err = genlmsg_unicast(msg, info->snd_pid);
1961 goto out;
1962
1963nla_put_failure:
1964 genlmsg_cancel(msg, hdr);
1965 err = -EMSGSIZE;
1966out:
1967 /* Cleanup */
1968 cfg80211_put_dev(drv);
1969 dev_put(dev);
1970 return err;
1971}
1972
1973#define FILL_IN_MESH_PARAM_IF_SET(table, cfg, param, mask, attr_num, nla_fn) \
1974do {\
1975 if (table[attr_num]) {\
1976 cfg.param = nla_fn(table[attr_num]); \
1977 mask |= (1 << (attr_num - 1)); \
1978 } \
1979} while (0);\
1980
1981static struct nla_policy
1982nl80211_meshconf_params_policy[NL80211_MESHCONF_ATTR_MAX+1] __read_mostly = {
1983 [NL80211_MESHCONF_RETRY_TIMEOUT] = { .type = NLA_U16 },
1984 [NL80211_MESHCONF_CONFIRM_TIMEOUT] = { .type = NLA_U16 },
1985 [NL80211_MESHCONF_HOLDING_TIMEOUT] = { .type = NLA_U16 },
1986 [NL80211_MESHCONF_MAX_PEER_LINKS] = { .type = NLA_U16 },
1987 [NL80211_MESHCONF_MAX_RETRIES] = { .type = NLA_U8 },
1988 [NL80211_MESHCONF_TTL] = { .type = NLA_U8 },
1989 [NL80211_MESHCONF_AUTO_OPEN_PLINKS] = { .type = NLA_U8 },
1990
1991 [NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES] = { .type = NLA_U8 },
1992 [NL80211_MESHCONF_PATH_REFRESH_TIME] = { .type = NLA_U32 },
1993 [NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT] = { .type = NLA_U16 },
1994 [NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT] = { .type = NLA_U32 },
1995 [NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL] = { .type = NLA_U16 },
1996 [NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME] = { .type = NLA_U16 },
1997};
1998
1999static int nl80211_set_mesh_params(struct sk_buff *skb, struct genl_info *info)
2000{
2001 int err;
2002 u32 mask;
2003 struct cfg80211_registered_device *drv;
2004 struct net_device *dev;
2005 struct mesh_config cfg;
2006 struct nlattr *tb[NL80211_MESHCONF_ATTR_MAX + 1];
2007 struct nlattr *parent_attr;
2008
2009 parent_attr = info->attrs[NL80211_ATTR_MESH_PARAMS];
2010 if (!parent_attr)
2011 return -EINVAL;
2012 if (nla_parse_nested(tb, NL80211_MESHCONF_ATTR_MAX,
2013 parent_attr, nl80211_meshconf_params_policy))
2014 return -EINVAL;
2015
2016 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
2017 if (err)
2018 return err;
2019
2020 /* This makes sure that there aren't more than 32 mesh config
2021 * parameters (otherwise our bitfield scheme would not work.) */
2022 BUILD_BUG_ON(NL80211_MESHCONF_ATTR_MAX > 32);
2023
2024 /* Fill in the params struct */
2025 mask = 0;
2026 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshRetryTimeout,
2027 mask, NL80211_MESHCONF_RETRY_TIMEOUT, nla_get_u16);
2028 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshConfirmTimeout,
2029 mask, NL80211_MESHCONF_CONFIRM_TIMEOUT, nla_get_u16);
2030 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHoldingTimeout,
2031 mask, NL80211_MESHCONF_HOLDING_TIMEOUT, nla_get_u16);
2032 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshMaxPeerLinks,
2033 mask, NL80211_MESHCONF_MAX_PEER_LINKS, nla_get_u16);
2034 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshMaxRetries,
2035 mask, NL80211_MESHCONF_MAX_RETRIES, nla_get_u8);
2036 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshTTL,
2037 mask, NL80211_MESHCONF_TTL, nla_get_u8);
2038 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, auto_open_plinks,
2039 mask, NL80211_MESHCONF_AUTO_OPEN_PLINKS, nla_get_u8);
2040 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPmaxPREQretries,
2041 mask, NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES,
2042 nla_get_u8);
2043 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, path_refresh_time,
2044 mask, NL80211_MESHCONF_PATH_REFRESH_TIME, nla_get_u32);
2045 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, min_discovery_timeout,
2046 mask, NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT,
2047 nla_get_u16);
2048 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPactivePathTimeout,
2049 mask, NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT,
2050 nla_get_u32);
2051 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPpreqMinInterval,
2052 mask, NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL,
2053 nla_get_u16);
2054 FILL_IN_MESH_PARAM_IF_SET(tb, cfg,
2055 dot11MeshHWMPnetDiameterTraversalTime,
2056 mask, NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME,
2057 nla_get_u16);
2058
2059 /* Apply changes */
2060 rtnl_lock();
2061 err = drv->ops->set_mesh_params(&drv->wiphy, dev, &cfg, mask);
2062 rtnl_unlock();
2063
2064 /* cleanup */
2065 cfg80211_put_dev(drv);
2066 dev_put(dev);
2067 return err;
2068}
2069
2070#undef FILL_IN_MESH_PARAM_IF_SET
2071
1688static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info) 2072static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info)
1689{ 2073{
1690 struct nlattr *tb[NL80211_REG_RULE_ATTR_MAX + 1]; 2074 struct nlattr *tb[NL80211_REG_RULE_ATTR_MAX + 1];
@@ -1743,12 +2127,9 @@ static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info)
1743 mutex_lock(&cfg80211_drv_mutex); 2127 mutex_lock(&cfg80211_drv_mutex);
1744 r = set_regdom(rd); 2128 r = set_regdom(rd);
1745 mutex_unlock(&cfg80211_drv_mutex); 2129 mutex_unlock(&cfg80211_drv_mutex);
1746 if (r)
1747 goto bad_reg;
1748
1749 return r; 2130 return r;
1750 2131
1751bad_reg: 2132 bad_reg:
1752 kfree(rd); 2133 kfree(rd);
1753 return -EINVAL; 2134 return -EINVAL;
1754} 2135}
@@ -1902,6 +2283,18 @@ static struct genl_ops nl80211_ops[] = {
1902 .policy = nl80211_policy, 2283 .policy = nl80211_policy,
1903 .flags = GENL_ADMIN_PERM, 2284 .flags = GENL_ADMIN_PERM,
1904 }, 2285 },
2286 {
2287 .cmd = NL80211_CMD_GET_MESH_PARAMS,
2288 .doit = nl80211_get_mesh_params,
2289 .policy = nl80211_policy,
2290 /* can be retrieved by unprivileged users */
2291 },
2292 {
2293 .cmd = NL80211_CMD_SET_MESH_PARAMS,
2294 .doit = nl80211_set_mesh_params,
2295 .policy = nl80211_policy,
2296 .flags = GENL_ADMIN_PERM,
2297 },
1905}; 2298};
1906 2299
1907/* multicast groups */ 2300/* multicast groups */