nl80211.c 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242
  1. /*
  2. * This is the new netlink-based wireless configuration interface.
  3. *
  4. * Copyright 2006, 2007 Johannes Berg <johannes@sipsolutions.net>
  5. */
  6. #include <linux/if.h>
  7. #include <linux/module.h>
  8. #include <linux/err.h>
  9. #include <linux/mutex.h>
  10. #include <linux/list.h>
  11. #include <linux/if_ether.h>
  12. #include <linux/ieee80211.h>
  13. #include <linux/nl80211.h>
  14. #include <linux/rtnetlink.h>
  15. #include <linux/netlink.h>
  16. #include <net/genetlink.h>
  17. #include <net/cfg80211.h>
  18. #include "core.h"
  19. #include "nl80211.h"
  20. /* the netlink family */
  21. static struct genl_family nl80211_fam = {
  22. .id = GENL_ID_GENERATE, /* don't bother with a hardcoded ID */
  23. .name = "nl80211", /* have users key off the name instead */
  24. .hdrsize = 0, /* no private header */
  25. .version = 1, /* no particular meaning now */
  26. .maxattr = NL80211_ATTR_MAX,
  27. };
  28. /* internal helper: get drv and dev */
  29. static int get_drv_dev_by_info_ifindex(struct genl_info *info,
  30. struct cfg80211_registered_device **drv,
  31. struct net_device **dev)
  32. {
  33. int ifindex;
  34. if (!info->attrs[NL80211_ATTR_IFINDEX])
  35. return -EINVAL;
  36. ifindex = nla_get_u32(info->attrs[NL80211_ATTR_IFINDEX]);
  37. *dev = dev_get_by_index(&init_net, ifindex);
  38. if (!*dev)
  39. return -ENODEV;
  40. *drv = cfg80211_get_dev_from_ifindex(ifindex);
  41. if (IS_ERR(*drv)) {
  42. dev_put(*dev);
  43. return PTR_ERR(*drv);
  44. }
  45. return 0;
  46. }
  47. /* policy for the attributes */
  48. static struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] __read_mostly = {
  49. [NL80211_ATTR_WIPHY] = { .type = NLA_U32 },
  50. [NL80211_ATTR_WIPHY_NAME] = { .type = NLA_NUL_STRING,
  51. .len = BUS_ID_SIZE-1 },
  52. [NL80211_ATTR_IFTYPE] = { .type = NLA_U32 },
  53. [NL80211_ATTR_IFINDEX] = { .type = NLA_U32 },
  54. [NL80211_ATTR_IFNAME] = { .type = NLA_NUL_STRING, .len = IFNAMSIZ-1 },
  55. [NL80211_ATTR_MAC] = { .type = NLA_BINARY, .len = ETH_ALEN },
  56. [NL80211_ATTR_KEY_DATA] = { .type = NLA_BINARY,
  57. .len = WLAN_MAX_KEY_LEN },
  58. [NL80211_ATTR_KEY_IDX] = { .type = NLA_U8 },
  59. [NL80211_ATTR_KEY_CIPHER] = { .type = NLA_U32 },
  60. [NL80211_ATTR_KEY_DEFAULT] = { .type = NLA_FLAG },
  61. [NL80211_ATTR_BEACON_INTERVAL] = { .type = NLA_U32 },
  62. [NL80211_ATTR_DTIM_PERIOD] = { .type = NLA_U32 },
  63. [NL80211_ATTR_BEACON_HEAD] = { .type = NLA_BINARY,
  64. .len = IEEE80211_MAX_DATA_LEN },
  65. [NL80211_ATTR_BEACON_TAIL] = { .type = NLA_BINARY,
  66. .len = IEEE80211_MAX_DATA_LEN },
  67. [NL80211_ATTR_STA_AID] = { .type = NLA_U16 },
  68. [NL80211_ATTR_STA_FLAGS] = { .type = NLA_NESTED },
  69. [NL80211_ATTR_STA_LISTEN_INTERVAL] = { .type = NLA_U16 },
  70. [NL80211_ATTR_STA_SUPPORTED_RATES] = { .type = NLA_BINARY,
  71. .len = NL80211_MAX_SUPP_RATES },
  72. [NL80211_ATTR_STA_VLAN] = { .type = NLA_U32 },
  73. };
  74. /* message building helper */
  75. static inline void *nl80211hdr_put(struct sk_buff *skb, u32 pid, u32 seq,
  76. int flags, u8 cmd)
  77. {
  78. /* since there is no private header just add the generic one */
  79. return genlmsg_put(skb, pid, seq, &nl80211_fam, flags, cmd);
  80. }
  81. /* netlink command implementations */
  82. static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags,
  83. struct cfg80211_registered_device *dev)
  84. {
  85. void *hdr;
  86. struct nlattr *nl_bands, *nl_band;
  87. struct nlattr *nl_freqs, *nl_freq;
  88. struct nlattr *nl_rates, *nl_rate;
  89. enum ieee80211_band band;
  90. struct ieee80211_channel *chan;
  91. struct ieee80211_rate *rate;
  92. int i;
  93. hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_WIPHY);
  94. if (!hdr)
  95. return -1;
  96. NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, dev->idx);
  97. NLA_PUT_STRING(msg, NL80211_ATTR_WIPHY_NAME, wiphy_name(&dev->wiphy));
  98. nl_bands = nla_nest_start(msg, NL80211_ATTR_WIPHY_BANDS);
  99. if (!nl_bands)
  100. goto nla_put_failure;
  101. for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
  102. if (!dev->wiphy.bands[band])
  103. continue;
  104. nl_band = nla_nest_start(msg, band);
  105. if (!nl_band)
  106. goto nla_put_failure;
  107. /* add frequencies */
  108. nl_freqs = nla_nest_start(msg, NL80211_BAND_ATTR_FREQS);
  109. if (!nl_freqs)
  110. goto nla_put_failure;
  111. for (i = 0; i < dev->wiphy.bands[band]->n_channels; i++) {
  112. nl_freq = nla_nest_start(msg, i);
  113. if (!nl_freq)
  114. goto nla_put_failure;
  115. chan = &dev->wiphy.bands[band]->channels[i];
  116. NLA_PUT_U32(msg, NL80211_FREQUENCY_ATTR_FREQ,
  117. chan->center_freq);
  118. if (chan->flags & IEEE80211_CHAN_DISABLED)
  119. NLA_PUT_FLAG(msg, NL80211_FREQUENCY_ATTR_DISABLED);
  120. if (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN)
  121. NLA_PUT_FLAG(msg, NL80211_FREQUENCY_ATTR_PASSIVE_SCAN);
  122. if (chan->flags & IEEE80211_CHAN_NO_IBSS)
  123. NLA_PUT_FLAG(msg, NL80211_FREQUENCY_ATTR_NO_IBSS);
  124. if (chan->flags & IEEE80211_CHAN_RADAR)
  125. NLA_PUT_FLAG(msg, NL80211_FREQUENCY_ATTR_RADAR);
  126. nla_nest_end(msg, nl_freq);
  127. }
  128. nla_nest_end(msg, nl_freqs);
  129. /* add bitrates */
  130. nl_rates = nla_nest_start(msg, NL80211_BAND_ATTR_RATES);
  131. if (!nl_rates)
  132. goto nla_put_failure;
  133. for (i = 0; i < dev->wiphy.bands[band]->n_bitrates; i++) {
  134. nl_rate = nla_nest_start(msg, i);
  135. if (!nl_rate)
  136. goto nla_put_failure;
  137. rate = &dev->wiphy.bands[band]->bitrates[i];
  138. NLA_PUT_U32(msg, NL80211_BITRATE_ATTR_RATE,
  139. rate->bitrate);
  140. if (rate->flags & IEEE80211_RATE_SHORT_PREAMBLE)
  141. NLA_PUT_FLAG(msg,
  142. NL80211_BITRATE_ATTR_2GHZ_SHORTPREAMBLE);
  143. nla_nest_end(msg, nl_rate);
  144. }
  145. nla_nest_end(msg, nl_rates);
  146. nla_nest_end(msg, nl_band);
  147. }
  148. nla_nest_end(msg, nl_bands);
  149. return genlmsg_end(msg, hdr);
  150. nla_put_failure:
  151. return genlmsg_cancel(msg, hdr);
  152. }
  153. static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb)
  154. {
  155. int idx = 0;
  156. int start = cb->args[0];
  157. struct cfg80211_registered_device *dev;
  158. mutex_lock(&cfg80211_drv_mutex);
  159. list_for_each_entry(dev, &cfg80211_drv_list, list) {
  160. if (++idx < start)
  161. continue;
  162. if (nl80211_send_wiphy(skb, NETLINK_CB(cb->skb).pid,
  163. cb->nlh->nlmsg_seq, NLM_F_MULTI,
  164. dev) < 0)
  165. break;
  166. }
  167. mutex_unlock(&cfg80211_drv_mutex);
  168. cb->args[0] = idx;
  169. return skb->len;
  170. }
  171. static int nl80211_get_wiphy(struct sk_buff *skb, struct genl_info *info)
  172. {
  173. struct sk_buff *msg;
  174. struct cfg80211_registered_device *dev;
  175. dev = cfg80211_get_dev_from_info(info);
  176. if (IS_ERR(dev))
  177. return PTR_ERR(dev);
  178. msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
  179. if (!msg)
  180. goto out_err;
  181. if (nl80211_send_wiphy(msg, info->snd_pid, info->snd_seq, 0, dev) < 0)
  182. goto out_free;
  183. cfg80211_put_dev(dev);
  184. return genlmsg_unicast(msg, info->snd_pid);
  185. out_free:
  186. nlmsg_free(msg);
  187. out_err:
  188. cfg80211_put_dev(dev);
  189. return -ENOBUFS;
  190. }
  191. static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
  192. {
  193. struct cfg80211_registered_device *rdev;
  194. int result;
  195. if (!info->attrs[NL80211_ATTR_WIPHY_NAME])
  196. return -EINVAL;
  197. rdev = cfg80211_get_dev_from_info(info);
  198. if (IS_ERR(rdev))
  199. return PTR_ERR(rdev);
  200. result = cfg80211_dev_rename(rdev, nla_data(info->attrs[NL80211_ATTR_WIPHY_NAME]));
  201. cfg80211_put_dev(rdev);
  202. return result;
  203. }
  204. static int nl80211_send_iface(struct sk_buff *msg, u32 pid, u32 seq, int flags,
  205. struct net_device *dev)
  206. {
  207. void *hdr;
  208. hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_INTERFACE);
  209. if (!hdr)
  210. return -1;
  211. NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex);
  212. NLA_PUT_STRING(msg, NL80211_ATTR_IFNAME, dev->name);
  213. /* TODO: interface type */
  214. return genlmsg_end(msg, hdr);
  215. nla_put_failure:
  216. return genlmsg_cancel(msg, hdr);
  217. }
  218. static int nl80211_dump_interface(struct sk_buff *skb, struct netlink_callback *cb)
  219. {
  220. int wp_idx = 0;
  221. int if_idx = 0;
  222. int wp_start = cb->args[0];
  223. int if_start = cb->args[1];
  224. struct cfg80211_registered_device *dev;
  225. struct wireless_dev *wdev;
  226. mutex_lock(&cfg80211_drv_mutex);
  227. list_for_each_entry(dev, &cfg80211_drv_list, list) {
  228. if (++wp_idx < wp_start)
  229. continue;
  230. if_idx = 0;
  231. mutex_lock(&dev->devlist_mtx);
  232. list_for_each_entry(wdev, &dev->netdev_list, list) {
  233. if (++if_idx < if_start)
  234. continue;
  235. if (nl80211_send_iface(skb, NETLINK_CB(cb->skb).pid,
  236. cb->nlh->nlmsg_seq, NLM_F_MULTI,
  237. wdev->netdev) < 0)
  238. break;
  239. }
  240. mutex_unlock(&dev->devlist_mtx);
  241. }
  242. mutex_unlock(&cfg80211_drv_mutex);
  243. cb->args[0] = wp_idx;
  244. cb->args[1] = if_idx;
  245. return skb->len;
  246. }
  247. static int nl80211_get_interface(struct sk_buff *skb, struct genl_info *info)
  248. {
  249. struct sk_buff *msg;
  250. struct cfg80211_registered_device *dev;
  251. struct net_device *netdev;
  252. int err;
  253. err = get_drv_dev_by_info_ifindex(info, &dev, &netdev);
  254. if (err)
  255. return err;
  256. msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
  257. if (!msg)
  258. goto out_err;
  259. if (nl80211_send_iface(msg, info->snd_pid, info->snd_seq, 0, netdev) < 0)
  260. goto out_free;
  261. dev_put(netdev);
  262. cfg80211_put_dev(dev);
  263. return genlmsg_unicast(msg, info->snd_pid);
  264. out_free:
  265. nlmsg_free(msg);
  266. out_err:
  267. dev_put(netdev);
  268. cfg80211_put_dev(dev);
  269. return -ENOBUFS;
  270. }
  271. static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info)
  272. {
  273. struct cfg80211_registered_device *drv;
  274. int err, ifindex;
  275. enum nl80211_iftype type;
  276. struct net_device *dev;
  277. if (info->attrs[NL80211_ATTR_IFTYPE]) {
  278. type = nla_get_u32(info->attrs[NL80211_ATTR_IFTYPE]);
  279. if (type > NL80211_IFTYPE_MAX)
  280. return -EINVAL;
  281. } else
  282. return -EINVAL;
  283. err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
  284. if (err)
  285. return err;
  286. ifindex = dev->ifindex;
  287. dev_put(dev);
  288. if (!drv->ops->change_virtual_intf) {
  289. err = -EOPNOTSUPP;
  290. goto unlock;
  291. }
  292. rtnl_lock();
  293. err = drv->ops->change_virtual_intf(&drv->wiphy, ifindex, type);
  294. rtnl_unlock();
  295. unlock:
  296. cfg80211_put_dev(drv);
  297. return err;
  298. }
  299. static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
  300. {
  301. struct cfg80211_registered_device *drv;
  302. int err;
  303. enum nl80211_iftype type = NL80211_IFTYPE_UNSPECIFIED;
  304. if (!info->attrs[NL80211_ATTR_IFNAME])
  305. return -EINVAL;
  306. if (info->attrs[NL80211_ATTR_IFTYPE]) {
  307. type = nla_get_u32(info->attrs[NL80211_ATTR_IFTYPE]);
  308. if (type > NL80211_IFTYPE_MAX)
  309. return -EINVAL;
  310. }
  311. drv = cfg80211_get_dev_from_info(info);
  312. if (IS_ERR(drv))
  313. return PTR_ERR(drv);
  314. if (!drv->ops->add_virtual_intf) {
  315. err = -EOPNOTSUPP;
  316. goto unlock;
  317. }
  318. rtnl_lock();
  319. err = drv->ops->add_virtual_intf(&drv->wiphy,
  320. nla_data(info->attrs[NL80211_ATTR_IFNAME]), type);
  321. rtnl_unlock();
  322. unlock:
  323. cfg80211_put_dev(drv);
  324. return err;
  325. }
  326. static int nl80211_del_interface(struct sk_buff *skb, struct genl_info *info)
  327. {
  328. struct cfg80211_registered_device *drv;
  329. int ifindex, err;
  330. struct net_device *dev;
  331. err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
  332. if (err)
  333. return err;
  334. ifindex = dev->ifindex;
  335. dev_put(dev);
  336. if (!drv->ops->del_virtual_intf) {
  337. err = -EOPNOTSUPP;
  338. goto out;
  339. }
  340. rtnl_lock();
  341. err = drv->ops->del_virtual_intf(&drv->wiphy, ifindex);
  342. rtnl_unlock();
  343. out:
  344. cfg80211_put_dev(drv);
  345. return err;
  346. }
  347. struct get_key_cookie {
  348. struct sk_buff *msg;
  349. int error;
  350. };
  351. static void get_key_callback(void *c, struct key_params *params)
  352. {
  353. struct get_key_cookie *cookie = c;
  354. if (params->key)
  355. NLA_PUT(cookie->msg, NL80211_ATTR_KEY_DATA,
  356. params->key_len, params->key);
  357. if (params->seq)
  358. NLA_PUT(cookie->msg, NL80211_ATTR_KEY_SEQ,
  359. params->seq_len, params->seq);
  360. if (params->cipher)
  361. NLA_PUT_U32(cookie->msg, NL80211_ATTR_KEY_CIPHER,
  362. params->cipher);
  363. return;
  364. nla_put_failure:
  365. cookie->error = 1;
  366. }
  367. static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info)
  368. {
  369. struct cfg80211_registered_device *drv;
  370. int err;
  371. struct net_device *dev;
  372. u8 key_idx = 0;
  373. u8 *mac_addr = NULL;
  374. struct get_key_cookie cookie = {
  375. .error = 0,
  376. };
  377. void *hdr;
  378. struct sk_buff *msg;
  379. if (info->attrs[NL80211_ATTR_KEY_IDX])
  380. key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]);
  381. if (key_idx > 3)
  382. return -EINVAL;
  383. if (info->attrs[NL80211_ATTR_MAC])
  384. mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
  385. err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
  386. if (err)
  387. return err;
  388. if (!drv->ops->get_key) {
  389. err = -EOPNOTSUPP;
  390. goto out;
  391. }
  392. msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
  393. if (!msg) {
  394. err = -ENOMEM;
  395. goto out;
  396. }
  397. hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0,
  398. NL80211_CMD_NEW_KEY);
  399. if (IS_ERR(hdr)) {
  400. err = PTR_ERR(hdr);
  401. goto out;
  402. }
  403. cookie.msg = msg;
  404. NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex);
  405. NLA_PUT_U8(msg, NL80211_ATTR_KEY_IDX, key_idx);
  406. if (mac_addr)
  407. NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr);
  408. rtnl_lock();
  409. err = drv->ops->get_key(&drv->wiphy, dev, key_idx, mac_addr,
  410. &cookie, get_key_callback);
  411. rtnl_unlock();
  412. if (err)
  413. goto out;
  414. if (cookie.error)
  415. goto nla_put_failure;
  416. genlmsg_end(msg, hdr);
  417. err = genlmsg_unicast(msg, info->snd_pid);
  418. goto out;
  419. nla_put_failure:
  420. err = -ENOBUFS;
  421. nlmsg_free(msg);
  422. out:
  423. cfg80211_put_dev(drv);
  424. dev_put(dev);
  425. return err;
  426. }
  427. static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info)
  428. {
  429. struct cfg80211_registered_device *drv;
  430. int err;
  431. struct net_device *dev;
  432. u8 key_idx;
  433. if (!info->attrs[NL80211_ATTR_KEY_IDX])
  434. return -EINVAL;
  435. key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]);
  436. if (key_idx > 3)
  437. return -EINVAL;
  438. /* currently only support setting default key */
  439. if (!info->attrs[NL80211_ATTR_KEY_DEFAULT])
  440. return -EINVAL;
  441. err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
  442. if (err)
  443. return err;
  444. if (!drv->ops->set_default_key) {
  445. err = -EOPNOTSUPP;
  446. goto out;
  447. }
  448. rtnl_lock();
  449. err = drv->ops->set_default_key(&drv->wiphy, dev, key_idx);
  450. rtnl_unlock();
  451. out:
  452. cfg80211_put_dev(drv);
  453. dev_put(dev);
  454. return err;
  455. }
  456. static int nl80211_new_key(struct sk_buff *skb, struct genl_info *info)
  457. {
  458. struct cfg80211_registered_device *drv;
  459. int err;
  460. struct net_device *dev;
  461. struct key_params params;
  462. u8 key_idx = 0;
  463. u8 *mac_addr = NULL;
  464. memset(&params, 0, sizeof(params));
  465. if (!info->attrs[NL80211_ATTR_KEY_CIPHER])
  466. return -EINVAL;
  467. if (info->attrs[NL80211_ATTR_KEY_DATA]) {
  468. params.key = nla_data(info->attrs[NL80211_ATTR_KEY_DATA]);
  469. params.key_len = nla_len(info->attrs[NL80211_ATTR_KEY_DATA]);
  470. }
  471. if (info->attrs[NL80211_ATTR_KEY_IDX])
  472. key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]);
  473. params.cipher = nla_get_u32(info->attrs[NL80211_ATTR_KEY_CIPHER]);
  474. if (info->attrs[NL80211_ATTR_MAC])
  475. mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
  476. if (key_idx > 3)
  477. return -EINVAL;
  478. /*
  479. * Disallow pairwise keys with non-zero index unless it's WEP
  480. * (because current deployments use pairwise WEP keys with
  481. * non-zero indizes but 802.11i clearly specifies to use zero)
  482. */
  483. if (mac_addr && key_idx &&
  484. params.cipher != WLAN_CIPHER_SUITE_WEP40 &&
  485. params.cipher != WLAN_CIPHER_SUITE_WEP104)
  486. return -EINVAL;
  487. /* TODO: add definitions for the lengths to linux/ieee80211.h */
  488. switch (params.cipher) {
  489. case WLAN_CIPHER_SUITE_WEP40:
  490. if (params.key_len != 5)
  491. return -EINVAL;
  492. break;
  493. case WLAN_CIPHER_SUITE_TKIP:
  494. if (params.key_len != 32)
  495. return -EINVAL;
  496. break;
  497. case WLAN_CIPHER_SUITE_CCMP:
  498. if (params.key_len != 16)
  499. return -EINVAL;
  500. break;
  501. case WLAN_CIPHER_SUITE_WEP104:
  502. if (params.key_len != 13)
  503. return -EINVAL;
  504. break;
  505. default:
  506. return -EINVAL;
  507. }
  508. err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
  509. if (err)
  510. return err;
  511. if (!drv->ops->add_key) {
  512. err = -EOPNOTSUPP;
  513. goto out;
  514. }
  515. rtnl_lock();
  516. err = drv->ops->add_key(&drv->wiphy, dev, key_idx, mac_addr, &params);
  517. rtnl_unlock();
  518. out:
  519. cfg80211_put_dev(drv);
  520. dev_put(dev);
  521. return err;
  522. }
  523. static int nl80211_del_key(struct sk_buff *skb, struct genl_info *info)
  524. {
  525. struct cfg80211_registered_device *drv;
  526. int err;
  527. struct net_device *dev;
  528. u8 key_idx = 0;
  529. u8 *mac_addr = NULL;
  530. if (info->attrs[NL80211_ATTR_KEY_IDX])
  531. key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]);
  532. if (key_idx > 3)
  533. return -EINVAL;
  534. if (info->attrs[NL80211_ATTR_MAC])
  535. mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
  536. err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
  537. if (err)
  538. return err;
  539. if (!drv->ops->del_key) {
  540. err = -EOPNOTSUPP;
  541. goto out;
  542. }
  543. rtnl_lock();
  544. err = drv->ops->del_key(&drv->wiphy, dev, key_idx, mac_addr);
  545. rtnl_unlock();
  546. out:
  547. cfg80211_put_dev(drv);
  548. dev_put(dev);
  549. return err;
  550. }
  551. static int nl80211_addset_beacon(struct sk_buff *skb, struct genl_info *info)
  552. {
  553. int (*call)(struct wiphy *wiphy, struct net_device *dev,
  554. struct beacon_parameters *info);
  555. struct cfg80211_registered_device *drv;
  556. int err;
  557. struct net_device *dev;
  558. struct beacon_parameters params;
  559. int haveinfo = 0;
  560. err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
  561. if (err)
  562. return err;
  563. switch (info->genlhdr->cmd) {
  564. case NL80211_CMD_NEW_BEACON:
  565. /* these are required for NEW_BEACON */
  566. if (!info->attrs[NL80211_ATTR_BEACON_INTERVAL] ||
  567. !info->attrs[NL80211_ATTR_DTIM_PERIOD] ||
  568. !info->attrs[NL80211_ATTR_BEACON_HEAD]) {
  569. err = -EINVAL;
  570. goto out;
  571. }
  572. call = drv->ops->add_beacon;
  573. break;
  574. case NL80211_CMD_SET_BEACON:
  575. call = drv->ops->set_beacon;
  576. break;
  577. default:
  578. WARN_ON(1);
  579. err = -EOPNOTSUPP;
  580. goto out;
  581. }
  582. if (!call) {
  583. err = -EOPNOTSUPP;
  584. goto out;
  585. }
  586. memset(&params, 0, sizeof(params));
  587. if (info->attrs[NL80211_ATTR_BEACON_INTERVAL]) {
  588. params.interval =
  589. nla_get_u32(info->attrs[NL80211_ATTR_BEACON_INTERVAL]);
  590. haveinfo = 1;
  591. }
  592. if (info->attrs[NL80211_ATTR_DTIM_PERIOD]) {
  593. params.dtim_period =
  594. nla_get_u32(info->attrs[NL80211_ATTR_DTIM_PERIOD]);
  595. haveinfo = 1;
  596. }
  597. if (info->attrs[NL80211_ATTR_BEACON_HEAD]) {
  598. params.head = nla_data(info->attrs[NL80211_ATTR_BEACON_HEAD]);
  599. params.head_len =
  600. nla_len(info->attrs[NL80211_ATTR_BEACON_HEAD]);
  601. haveinfo = 1;
  602. }
  603. if (info->attrs[NL80211_ATTR_BEACON_TAIL]) {
  604. params.tail = nla_data(info->attrs[NL80211_ATTR_BEACON_TAIL]);
  605. params.tail_len =
  606. nla_len(info->attrs[NL80211_ATTR_BEACON_TAIL]);
  607. haveinfo = 1;
  608. }
  609. if (!haveinfo) {
  610. err = -EINVAL;
  611. goto out;
  612. }
  613. rtnl_lock();
  614. err = call(&drv->wiphy, dev, &params);
  615. rtnl_unlock();
  616. out:
  617. cfg80211_put_dev(drv);
  618. dev_put(dev);
  619. return err;
  620. }
  621. static int nl80211_del_beacon(struct sk_buff *skb, struct genl_info *info)
  622. {
  623. struct cfg80211_registered_device *drv;
  624. int err;
  625. struct net_device *dev;
  626. err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
  627. if (err)
  628. return err;
  629. if (!drv->ops->del_beacon) {
  630. err = -EOPNOTSUPP;
  631. goto out;
  632. }
  633. rtnl_lock();
  634. err = drv->ops->del_beacon(&drv->wiphy, dev);
  635. rtnl_unlock();
  636. out:
  637. cfg80211_put_dev(drv);
  638. dev_put(dev);
  639. return err;
  640. }
  641. static const struct nla_policy sta_flags_policy[NL80211_STA_FLAG_MAX + 1] = {
  642. [NL80211_STA_FLAG_AUTHORIZED] = { .type = NLA_FLAG },
  643. [NL80211_STA_FLAG_SHORT_PREAMBLE] = { .type = NLA_FLAG },
  644. [NL80211_STA_FLAG_WME] = { .type = NLA_FLAG },
  645. };
  646. static int parse_station_flags(struct nlattr *nla, u32 *staflags)
  647. {
  648. struct nlattr *flags[NL80211_STA_FLAG_MAX + 1];
  649. int flag;
  650. *staflags = 0;
  651. if (!nla)
  652. return 0;
  653. if (nla_parse_nested(flags, NL80211_STA_FLAG_MAX,
  654. nla, sta_flags_policy))
  655. return -EINVAL;
  656. *staflags = STATION_FLAG_CHANGED;
  657. for (flag = 1; flag <= NL80211_STA_FLAG_MAX; flag++)
  658. if (flags[flag])
  659. *staflags |= (1<<flag);
  660. return 0;
  661. }
  662. static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq,
  663. int flags, struct net_device *dev,
  664. u8 *mac_addr, struct station_stats *stats)
  665. {
  666. void *hdr;
  667. struct nlattr *statsattr;
  668. hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_STATION);
  669. if (!hdr)
  670. return -1;
  671. NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex);
  672. NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr);
  673. statsattr = nla_nest_start(msg, NL80211_ATTR_STA_STATS);
  674. if (!statsattr)
  675. goto nla_put_failure;
  676. if (stats->filled & STATION_STAT_INACTIVE_TIME)
  677. NLA_PUT_U32(msg, NL80211_STA_STAT_INACTIVE_TIME,
  678. stats->inactive_time);
  679. if (stats->filled & STATION_STAT_RX_BYTES)
  680. NLA_PUT_U32(msg, NL80211_STA_STAT_RX_BYTES,
  681. stats->rx_bytes);
  682. if (stats->filled & STATION_STAT_TX_BYTES)
  683. NLA_PUT_U32(msg, NL80211_STA_STAT_TX_BYTES,
  684. stats->tx_bytes);
  685. nla_nest_end(msg, statsattr);
  686. return genlmsg_end(msg, hdr);
  687. nla_put_failure:
  688. return genlmsg_cancel(msg, hdr);
  689. }
  690. static int nl80211_get_station(struct sk_buff *skb, struct genl_info *info)
  691. {
  692. struct cfg80211_registered_device *drv;
  693. int err;
  694. struct net_device *dev;
  695. struct station_stats stats;
  696. struct sk_buff *msg;
  697. u8 *mac_addr = NULL;
  698. memset(&stats, 0, sizeof(stats));
  699. if (!info->attrs[NL80211_ATTR_MAC])
  700. return -EINVAL;
  701. mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
  702. err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
  703. if (err)
  704. return err;
  705. if (!drv->ops->get_station) {
  706. err = -EOPNOTSUPP;
  707. goto out;
  708. }
  709. rtnl_lock();
  710. err = drv->ops->get_station(&drv->wiphy, dev, mac_addr, &stats);
  711. rtnl_unlock();
  712. msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
  713. if (!msg)
  714. goto out;
  715. if (nl80211_send_station(msg, info->snd_pid, info->snd_seq, 0,
  716. dev, mac_addr, &stats) < 0)
  717. goto out_free;
  718. err = genlmsg_unicast(msg, info->snd_pid);
  719. goto out;
  720. out_free:
  721. nlmsg_free(msg);
  722. out:
  723. cfg80211_put_dev(drv);
  724. dev_put(dev);
  725. return err;
  726. }
  727. /*
  728. * Get vlan interface making sure it is on the right wiphy.
  729. */
  730. static int get_vlan(struct nlattr *vlanattr,
  731. struct cfg80211_registered_device *rdev,
  732. struct net_device **vlan)
  733. {
  734. *vlan = NULL;
  735. if (vlanattr) {
  736. *vlan = dev_get_by_index(&init_net, nla_get_u32(vlanattr));
  737. if (!*vlan)
  738. return -ENODEV;
  739. if (!(*vlan)->ieee80211_ptr)
  740. return -EINVAL;
  741. if ((*vlan)->ieee80211_ptr->wiphy != &rdev->wiphy)
  742. return -EINVAL;
  743. }
  744. return 0;
  745. }
  746. static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info)
  747. {
  748. struct cfg80211_registered_device *drv;
  749. int err;
  750. struct net_device *dev;
  751. struct station_parameters params;
  752. u8 *mac_addr = NULL;
  753. memset(&params, 0, sizeof(params));
  754. params.listen_interval = -1;
  755. if (info->attrs[NL80211_ATTR_STA_AID])
  756. return -EINVAL;
  757. if (!info->attrs[NL80211_ATTR_MAC])
  758. return -EINVAL;
  759. mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
  760. if (info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]) {
  761. params.supported_rates =
  762. nla_data(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]);
  763. params.supported_rates_len =
  764. nla_len(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]);
  765. }
  766. if (info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL])
  767. params.listen_interval =
  768. nla_get_u16(info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]);
  769. if (parse_station_flags(info->attrs[NL80211_ATTR_STA_FLAGS],
  770. &params.station_flags))
  771. return -EINVAL;
  772. err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
  773. if (err)
  774. return err;
  775. err = get_vlan(info->attrs[NL80211_ATTR_STA_VLAN], drv, &params.vlan);
  776. if (err)
  777. goto out;
  778. if (!drv->ops->change_station) {
  779. err = -EOPNOTSUPP;
  780. goto out;
  781. }
  782. rtnl_lock();
  783. err = drv->ops->change_station(&drv->wiphy, dev, mac_addr, &params);
  784. rtnl_unlock();
  785. out:
  786. if (params.vlan)
  787. dev_put(params.vlan);
  788. cfg80211_put_dev(drv);
  789. dev_put(dev);
  790. return err;
  791. }
  792. static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
  793. {
  794. struct cfg80211_registered_device *drv;
  795. int err;
  796. struct net_device *dev;
  797. struct station_parameters params;
  798. u8 *mac_addr = NULL;
  799. memset(&params, 0, sizeof(params));
  800. if (!info->attrs[NL80211_ATTR_MAC])
  801. return -EINVAL;
  802. if (!info->attrs[NL80211_ATTR_STA_AID])
  803. return -EINVAL;
  804. if (!info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL])
  805. return -EINVAL;
  806. if (!info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES])
  807. return -EINVAL;
  808. mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
  809. params.supported_rates =
  810. nla_data(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]);
  811. params.supported_rates_len =
  812. nla_len(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]);
  813. params.listen_interval =
  814. nla_get_u16(info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]);
  815. params.listen_interval = nla_get_u16(info->attrs[NL80211_ATTR_STA_AID]);
  816. if (parse_station_flags(info->attrs[NL80211_ATTR_STA_FLAGS],
  817. &params.station_flags))
  818. return -EINVAL;
  819. err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
  820. if (err)
  821. return err;
  822. err = get_vlan(info->attrs[NL80211_ATTR_STA_VLAN], drv, &params.vlan);
  823. if (err)
  824. goto out;
  825. if (!drv->ops->add_station) {
  826. err = -EOPNOTSUPP;
  827. goto out;
  828. }
  829. rtnl_lock();
  830. err = drv->ops->add_station(&drv->wiphy, dev, mac_addr, &params);
  831. rtnl_unlock();
  832. out:
  833. if (params.vlan)
  834. dev_put(params.vlan);
  835. cfg80211_put_dev(drv);
  836. dev_put(dev);
  837. return err;
  838. }
  839. static int nl80211_del_station(struct sk_buff *skb, struct genl_info *info)
  840. {
  841. struct cfg80211_registered_device *drv;
  842. int err;
  843. struct net_device *dev;
  844. u8 *mac_addr = NULL;
  845. if (info->attrs[NL80211_ATTR_MAC])
  846. mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
  847. err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
  848. if (err)
  849. return err;
  850. if (!drv->ops->del_station) {
  851. err = -EOPNOTSUPP;
  852. goto out;
  853. }
  854. rtnl_lock();
  855. err = drv->ops->del_station(&drv->wiphy, dev, mac_addr);
  856. rtnl_unlock();
  857. out:
  858. cfg80211_put_dev(drv);
  859. dev_put(dev);
  860. return err;
  861. }
  862. static struct genl_ops nl80211_ops[] = {
  863. {
  864. .cmd = NL80211_CMD_GET_WIPHY,
  865. .doit = nl80211_get_wiphy,
  866. .dumpit = nl80211_dump_wiphy,
  867. .policy = nl80211_policy,
  868. /* can be retrieved by unprivileged users */
  869. },
  870. {
  871. .cmd = NL80211_CMD_SET_WIPHY,
  872. .doit = nl80211_set_wiphy,
  873. .policy = nl80211_policy,
  874. .flags = GENL_ADMIN_PERM,
  875. },
  876. {
  877. .cmd = NL80211_CMD_GET_INTERFACE,
  878. .doit = nl80211_get_interface,
  879. .dumpit = nl80211_dump_interface,
  880. .policy = nl80211_policy,
  881. /* can be retrieved by unprivileged users */
  882. },
  883. {
  884. .cmd = NL80211_CMD_SET_INTERFACE,
  885. .doit = nl80211_set_interface,
  886. .policy = nl80211_policy,
  887. .flags = GENL_ADMIN_PERM,
  888. },
  889. {
  890. .cmd = NL80211_CMD_NEW_INTERFACE,
  891. .doit = nl80211_new_interface,
  892. .policy = nl80211_policy,
  893. .flags = GENL_ADMIN_PERM,
  894. },
  895. {
  896. .cmd = NL80211_CMD_DEL_INTERFACE,
  897. .doit = nl80211_del_interface,
  898. .policy = nl80211_policy,
  899. .flags = GENL_ADMIN_PERM,
  900. },
  901. {
  902. .cmd = NL80211_CMD_GET_KEY,
  903. .doit = nl80211_get_key,
  904. .policy = nl80211_policy,
  905. .flags = GENL_ADMIN_PERM,
  906. },
  907. {
  908. .cmd = NL80211_CMD_SET_KEY,
  909. .doit = nl80211_set_key,
  910. .policy = nl80211_policy,
  911. .flags = GENL_ADMIN_PERM,
  912. },
  913. {
  914. .cmd = NL80211_CMD_NEW_KEY,
  915. .doit = nl80211_new_key,
  916. .policy = nl80211_policy,
  917. .flags = GENL_ADMIN_PERM,
  918. },
  919. {
  920. .cmd = NL80211_CMD_DEL_KEY,
  921. .doit = nl80211_del_key,
  922. .policy = nl80211_policy,
  923. .flags = GENL_ADMIN_PERM,
  924. },
  925. {
  926. .cmd = NL80211_CMD_SET_BEACON,
  927. .policy = nl80211_policy,
  928. .flags = GENL_ADMIN_PERM,
  929. .doit = nl80211_addset_beacon,
  930. },
  931. {
  932. .cmd = NL80211_CMD_NEW_BEACON,
  933. .policy = nl80211_policy,
  934. .flags = GENL_ADMIN_PERM,
  935. .doit = nl80211_addset_beacon,
  936. },
  937. {
  938. .cmd = NL80211_CMD_DEL_BEACON,
  939. .policy = nl80211_policy,
  940. .flags = GENL_ADMIN_PERM,
  941. .doit = nl80211_del_beacon,
  942. },
  943. {
  944. .cmd = NL80211_CMD_GET_STATION,
  945. .doit = nl80211_get_station,
  946. /* TODO: implement dumpit */
  947. .policy = nl80211_policy,
  948. .flags = GENL_ADMIN_PERM,
  949. },
  950. {
  951. .cmd = NL80211_CMD_SET_STATION,
  952. .doit = nl80211_set_station,
  953. .policy = nl80211_policy,
  954. .flags = GENL_ADMIN_PERM,
  955. },
  956. {
  957. .cmd = NL80211_CMD_NEW_STATION,
  958. .doit = nl80211_new_station,
  959. .policy = nl80211_policy,
  960. .flags = GENL_ADMIN_PERM,
  961. },
  962. {
  963. .cmd = NL80211_CMD_DEL_STATION,
  964. .doit = nl80211_del_station,
  965. .policy = nl80211_policy,
  966. .flags = GENL_ADMIN_PERM,
  967. },
  968. };
  969. /* multicast groups */
  970. static struct genl_multicast_group nl80211_config_mcgrp = {
  971. .name = "config",
  972. };
  973. /* notification functions */
  974. void nl80211_notify_dev_rename(struct cfg80211_registered_device *rdev)
  975. {
  976. struct sk_buff *msg;
  977. msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
  978. if (!msg)
  979. return;
  980. if (nl80211_send_wiphy(msg, 0, 0, 0, rdev) < 0) {
  981. nlmsg_free(msg);
  982. return;
  983. }
  984. genlmsg_multicast(msg, 0, nl80211_config_mcgrp.id, GFP_KERNEL);
  985. }
  986. /* initialisation/exit functions */
  987. int nl80211_init(void)
  988. {
  989. int err, i;
  990. err = genl_register_family(&nl80211_fam);
  991. if (err)
  992. return err;
  993. for (i = 0; i < ARRAY_SIZE(nl80211_ops); i++) {
  994. err = genl_register_ops(&nl80211_fam, &nl80211_ops[i]);
  995. if (err)
  996. goto err_out;
  997. }
  998. err = genl_register_mc_group(&nl80211_fam, &nl80211_config_mcgrp);
  999. if (err)
  1000. goto err_out;
  1001. return 0;
  1002. err_out:
  1003. genl_unregister_family(&nl80211_fam);
  1004. return err;
  1005. }
  1006. void nl80211_exit(void)
  1007. {
  1008. genl_unregister_family(&nl80211_fam);
  1009. }