nl80211.c 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680
  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_PLINK_ACTION] = { .type = NLA_U8 },
  73. [NL80211_ATTR_STA_VLAN] = { .type = NLA_U32 },
  74. [NL80211_ATTR_MNTR_FLAGS] = { .type = NLA_NESTED },
  75. [NL80211_ATTR_MESH_ID] = { .type = NLA_BINARY,
  76. .len = IEEE80211_MAX_MESH_ID_LEN },
  77. [NL80211_ATTR_MPATH_NEXT_HOP] = { .type = NLA_U32 },
  78. };
  79. /* message building helper */
  80. static inline void *nl80211hdr_put(struct sk_buff *skb, u32 pid, u32 seq,
  81. int flags, u8 cmd)
  82. {
  83. /* since there is no private header just add the generic one */
  84. return genlmsg_put(skb, pid, seq, &nl80211_fam, flags, cmd);
  85. }
  86. /* netlink command implementations */
  87. static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags,
  88. struct cfg80211_registered_device *dev)
  89. {
  90. void *hdr;
  91. struct nlattr *nl_bands, *nl_band;
  92. struct nlattr *nl_freqs, *nl_freq;
  93. struct nlattr *nl_rates, *nl_rate;
  94. enum ieee80211_band band;
  95. struct ieee80211_channel *chan;
  96. struct ieee80211_rate *rate;
  97. int i;
  98. hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_WIPHY);
  99. if (!hdr)
  100. return -1;
  101. NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, dev->idx);
  102. NLA_PUT_STRING(msg, NL80211_ATTR_WIPHY_NAME, wiphy_name(&dev->wiphy));
  103. nl_bands = nla_nest_start(msg, NL80211_ATTR_WIPHY_BANDS);
  104. if (!nl_bands)
  105. goto nla_put_failure;
  106. for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
  107. if (!dev->wiphy.bands[band])
  108. continue;
  109. nl_band = nla_nest_start(msg, band);
  110. if (!nl_band)
  111. goto nla_put_failure;
  112. /* add frequencies */
  113. nl_freqs = nla_nest_start(msg, NL80211_BAND_ATTR_FREQS);
  114. if (!nl_freqs)
  115. goto nla_put_failure;
  116. for (i = 0; i < dev->wiphy.bands[band]->n_channels; i++) {
  117. nl_freq = nla_nest_start(msg, i);
  118. if (!nl_freq)
  119. goto nla_put_failure;
  120. chan = &dev->wiphy.bands[band]->channels[i];
  121. NLA_PUT_U32(msg, NL80211_FREQUENCY_ATTR_FREQ,
  122. chan->center_freq);
  123. if (chan->flags & IEEE80211_CHAN_DISABLED)
  124. NLA_PUT_FLAG(msg, NL80211_FREQUENCY_ATTR_DISABLED);
  125. if (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN)
  126. NLA_PUT_FLAG(msg, NL80211_FREQUENCY_ATTR_PASSIVE_SCAN);
  127. if (chan->flags & IEEE80211_CHAN_NO_IBSS)
  128. NLA_PUT_FLAG(msg, NL80211_FREQUENCY_ATTR_NO_IBSS);
  129. if (chan->flags & IEEE80211_CHAN_RADAR)
  130. NLA_PUT_FLAG(msg, NL80211_FREQUENCY_ATTR_RADAR);
  131. nla_nest_end(msg, nl_freq);
  132. }
  133. nla_nest_end(msg, nl_freqs);
  134. /* add bitrates */
  135. nl_rates = nla_nest_start(msg, NL80211_BAND_ATTR_RATES);
  136. if (!nl_rates)
  137. goto nla_put_failure;
  138. for (i = 0; i < dev->wiphy.bands[band]->n_bitrates; i++) {
  139. nl_rate = nla_nest_start(msg, i);
  140. if (!nl_rate)
  141. goto nla_put_failure;
  142. rate = &dev->wiphy.bands[band]->bitrates[i];
  143. NLA_PUT_U32(msg, NL80211_BITRATE_ATTR_RATE,
  144. rate->bitrate);
  145. if (rate->flags & IEEE80211_RATE_SHORT_PREAMBLE)
  146. NLA_PUT_FLAG(msg,
  147. NL80211_BITRATE_ATTR_2GHZ_SHORTPREAMBLE);
  148. nla_nest_end(msg, nl_rate);
  149. }
  150. nla_nest_end(msg, nl_rates);
  151. nla_nest_end(msg, nl_band);
  152. }
  153. nla_nest_end(msg, nl_bands);
  154. return genlmsg_end(msg, hdr);
  155. nla_put_failure:
  156. genlmsg_cancel(msg, hdr);
  157. return -EMSGSIZE;
  158. }
  159. static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb)
  160. {
  161. int idx = 0;
  162. int start = cb->args[0];
  163. struct cfg80211_registered_device *dev;
  164. mutex_lock(&cfg80211_drv_mutex);
  165. list_for_each_entry(dev, &cfg80211_drv_list, list) {
  166. if (++idx < start)
  167. continue;
  168. if (nl80211_send_wiphy(skb, NETLINK_CB(cb->skb).pid,
  169. cb->nlh->nlmsg_seq, NLM_F_MULTI,
  170. dev) < 0)
  171. break;
  172. }
  173. mutex_unlock(&cfg80211_drv_mutex);
  174. cb->args[0] = idx;
  175. return skb->len;
  176. }
  177. static int nl80211_get_wiphy(struct sk_buff *skb, struct genl_info *info)
  178. {
  179. struct sk_buff *msg;
  180. struct cfg80211_registered_device *dev;
  181. dev = cfg80211_get_dev_from_info(info);
  182. if (IS_ERR(dev))
  183. return PTR_ERR(dev);
  184. msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
  185. if (!msg)
  186. goto out_err;
  187. if (nl80211_send_wiphy(msg, info->snd_pid, info->snd_seq, 0, dev) < 0)
  188. goto out_free;
  189. cfg80211_put_dev(dev);
  190. return genlmsg_unicast(msg, info->snd_pid);
  191. out_free:
  192. nlmsg_free(msg);
  193. out_err:
  194. cfg80211_put_dev(dev);
  195. return -ENOBUFS;
  196. }
  197. static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
  198. {
  199. struct cfg80211_registered_device *rdev;
  200. int result;
  201. if (!info->attrs[NL80211_ATTR_WIPHY_NAME])
  202. return -EINVAL;
  203. rdev = cfg80211_get_dev_from_info(info);
  204. if (IS_ERR(rdev))
  205. return PTR_ERR(rdev);
  206. result = cfg80211_dev_rename(rdev, nla_data(info->attrs[NL80211_ATTR_WIPHY_NAME]));
  207. cfg80211_put_dev(rdev);
  208. return result;
  209. }
  210. static int nl80211_send_iface(struct sk_buff *msg, u32 pid, u32 seq, int flags,
  211. struct net_device *dev)
  212. {
  213. void *hdr;
  214. hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_INTERFACE);
  215. if (!hdr)
  216. return -1;
  217. NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex);
  218. NLA_PUT_STRING(msg, NL80211_ATTR_IFNAME, dev->name);
  219. /* TODO: interface type */
  220. return genlmsg_end(msg, hdr);
  221. nla_put_failure:
  222. genlmsg_cancel(msg, hdr);
  223. return -EMSGSIZE;
  224. }
  225. static int nl80211_dump_interface(struct sk_buff *skb, struct netlink_callback *cb)
  226. {
  227. int wp_idx = 0;
  228. int if_idx = 0;
  229. int wp_start = cb->args[0];
  230. int if_start = cb->args[1];
  231. struct cfg80211_registered_device *dev;
  232. struct wireless_dev *wdev;
  233. mutex_lock(&cfg80211_drv_mutex);
  234. list_for_each_entry(dev, &cfg80211_drv_list, list) {
  235. if (++wp_idx < wp_start)
  236. continue;
  237. if_idx = 0;
  238. mutex_lock(&dev->devlist_mtx);
  239. list_for_each_entry(wdev, &dev->netdev_list, list) {
  240. if (++if_idx < if_start)
  241. continue;
  242. if (nl80211_send_iface(skb, NETLINK_CB(cb->skb).pid,
  243. cb->nlh->nlmsg_seq, NLM_F_MULTI,
  244. wdev->netdev) < 0)
  245. break;
  246. }
  247. mutex_unlock(&dev->devlist_mtx);
  248. }
  249. mutex_unlock(&cfg80211_drv_mutex);
  250. cb->args[0] = wp_idx;
  251. cb->args[1] = if_idx;
  252. return skb->len;
  253. }
  254. static int nl80211_get_interface(struct sk_buff *skb, struct genl_info *info)
  255. {
  256. struct sk_buff *msg;
  257. struct cfg80211_registered_device *dev;
  258. struct net_device *netdev;
  259. int err;
  260. err = get_drv_dev_by_info_ifindex(info, &dev, &netdev);
  261. if (err)
  262. return err;
  263. msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
  264. if (!msg)
  265. goto out_err;
  266. if (nl80211_send_iface(msg, info->snd_pid, info->snd_seq, 0, netdev) < 0)
  267. goto out_free;
  268. dev_put(netdev);
  269. cfg80211_put_dev(dev);
  270. return genlmsg_unicast(msg, info->snd_pid);
  271. out_free:
  272. nlmsg_free(msg);
  273. out_err:
  274. dev_put(netdev);
  275. cfg80211_put_dev(dev);
  276. return -ENOBUFS;
  277. }
  278. static const struct nla_policy mntr_flags_policy[NL80211_MNTR_FLAG_MAX + 1] = {
  279. [NL80211_MNTR_FLAG_FCSFAIL] = { .type = NLA_FLAG },
  280. [NL80211_MNTR_FLAG_PLCPFAIL] = { .type = NLA_FLAG },
  281. [NL80211_MNTR_FLAG_CONTROL] = { .type = NLA_FLAG },
  282. [NL80211_MNTR_FLAG_OTHER_BSS] = { .type = NLA_FLAG },
  283. [NL80211_MNTR_FLAG_COOK_FRAMES] = { .type = NLA_FLAG },
  284. };
  285. static int parse_monitor_flags(struct nlattr *nla, u32 *mntrflags)
  286. {
  287. struct nlattr *flags[NL80211_MNTR_FLAG_MAX + 1];
  288. int flag;
  289. *mntrflags = 0;
  290. if (!nla)
  291. return -EINVAL;
  292. if (nla_parse_nested(flags, NL80211_MNTR_FLAG_MAX,
  293. nla, mntr_flags_policy))
  294. return -EINVAL;
  295. for (flag = 1; flag <= NL80211_MNTR_FLAG_MAX; flag++)
  296. if (flags[flag])
  297. *mntrflags |= (1<<flag);
  298. return 0;
  299. }
  300. static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info)
  301. {
  302. struct cfg80211_registered_device *drv;
  303. struct vif_params params;
  304. int err, ifindex;
  305. enum nl80211_iftype type;
  306. struct net_device *dev;
  307. u32 flags;
  308. memset(&params, 0, sizeof(params));
  309. if (info->attrs[NL80211_ATTR_IFTYPE]) {
  310. type = nla_get_u32(info->attrs[NL80211_ATTR_IFTYPE]);
  311. if (type > NL80211_IFTYPE_MAX)
  312. return -EINVAL;
  313. } else
  314. return -EINVAL;
  315. err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
  316. if (err)
  317. return err;
  318. ifindex = dev->ifindex;
  319. dev_put(dev);
  320. if (!drv->ops->change_virtual_intf) {
  321. err = -EOPNOTSUPP;
  322. goto unlock;
  323. }
  324. if (type == NL80211_IFTYPE_MESH_POINT &&
  325. info->attrs[NL80211_ATTR_MESH_ID]) {
  326. params.mesh_id = nla_data(info->attrs[NL80211_ATTR_MESH_ID]);
  327. params.mesh_id_len = nla_len(info->attrs[NL80211_ATTR_MESH_ID]);
  328. }
  329. rtnl_lock();
  330. err = parse_monitor_flags(type == NL80211_IFTYPE_MONITOR ?
  331. info->attrs[NL80211_ATTR_MNTR_FLAGS] : NULL,
  332. &flags);
  333. err = drv->ops->change_virtual_intf(&drv->wiphy, ifindex,
  334. type, err ? NULL : &flags, &params);
  335. rtnl_unlock();
  336. unlock:
  337. cfg80211_put_dev(drv);
  338. return err;
  339. }
  340. static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
  341. {
  342. struct cfg80211_registered_device *drv;
  343. struct vif_params params;
  344. int err;
  345. enum nl80211_iftype type = NL80211_IFTYPE_UNSPECIFIED;
  346. u32 flags;
  347. memset(&params, 0, sizeof(params));
  348. if (!info->attrs[NL80211_ATTR_IFNAME])
  349. return -EINVAL;
  350. if (info->attrs[NL80211_ATTR_IFTYPE]) {
  351. type = nla_get_u32(info->attrs[NL80211_ATTR_IFTYPE]);
  352. if (type > NL80211_IFTYPE_MAX)
  353. return -EINVAL;
  354. }
  355. drv = cfg80211_get_dev_from_info(info);
  356. if (IS_ERR(drv))
  357. return PTR_ERR(drv);
  358. if (!drv->ops->add_virtual_intf) {
  359. err = -EOPNOTSUPP;
  360. goto unlock;
  361. }
  362. if (type == NL80211_IFTYPE_MESH_POINT &&
  363. info->attrs[NL80211_ATTR_MESH_ID]) {
  364. params.mesh_id = nla_data(info->attrs[NL80211_ATTR_MESH_ID]);
  365. params.mesh_id_len = nla_len(info->attrs[NL80211_ATTR_MESH_ID]);
  366. }
  367. rtnl_lock();
  368. err = parse_monitor_flags(type == NL80211_IFTYPE_MONITOR ?
  369. info->attrs[NL80211_ATTR_MNTR_FLAGS] : NULL,
  370. &flags);
  371. err = drv->ops->add_virtual_intf(&drv->wiphy,
  372. nla_data(info->attrs[NL80211_ATTR_IFNAME]),
  373. type, err ? NULL : &flags, &params);
  374. rtnl_unlock();
  375. unlock:
  376. cfg80211_put_dev(drv);
  377. return err;
  378. }
  379. static int nl80211_del_interface(struct sk_buff *skb, struct genl_info *info)
  380. {
  381. struct cfg80211_registered_device *drv;
  382. int ifindex, err;
  383. struct net_device *dev;
  384. err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
  385. if (err)
  386. return err;
  387. ifindex = dev->ifindex;
  388. dev_put(dev);
  389. if (!drv->ops->del_virtual_intf) {
  390. err = -EOPNOTSUPP;
  391. goto out;
  392. }
  393. rtnl_lock();
  394. err = drv->ops->del_virtual_intf(&drv->wiphy, ifindex);
  395. rtnl_unlock();
  396. out:
  397. cfg80211_put_dev(drv);
  398. return err;
  399. }
  400. struct get_key_cookie {
  401. struct sk_buff *msg;
  402. int error;
  403. };
  404. static void get_key_callback(void *c, struct key_params *params)
  405. {
  406. struct get_key_cookie *cookie = c;
  407. if (params->key)
  408. NLA_PUT(cookie->msg, NL80211_ATTR_KEY_DATA,
  409. params->key_len, params->key);
  410. if (params->seq)
  411. NLA_PUT(cookie->msg, NL80211_ATTR_KEY_SEQ,
  412. params->seq_len, params->seq);
  413. if (params->cipher)
  414. NLA_PUT_U32(cookie->msg, NL80211_ATTR_KEY_CIPHER,
  415. params->cipher);
  416. return;
  417. nla_put_failure:
  418. cookie->error = 1;
  419. }
  420. static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info)
  421. {
  422. struct cfg80211_registered_device *drv;
  423. int err;
  424. struct net_device *dev;
  425. u8 key_idx = 0;
  426. u8 *mac_addr = NULL;
  427. struct get_key_cookie cookie = {
  428. .error = 0,
  429. };
  430. void *hdr;
  431. struct sk_buff *msg;
  432. if (info->attrs[NL80211_ATTR_KEY_IDX])
  433. key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]);
  434. if (key_idx > 3)
  435. return -EINVAL;
  436. if (info->attrs[NL80211_ATTR_MAC])
  437. mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
  438. err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
  439. if (err)
  440. return err;
  441. if (!drv->ops->get_key) {
  442. err = -EOPNOTSUPP;
  443. goto out;
  444. }
  445. msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
  446. if (!msg) {
  447. err = -ENOMEM;
  448. goto out;
  449. }
  450. hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0,
  451. NL80211_CMD_NEW_KEY);
  452. if (IS_ERR(hdr)) {
  453. err = PTR_ERR(hdr);
  454. goto out;
  455. }
  456. cookie.msg = msg;
  457. NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex);
  458. NLA_PUT_U8(msg, NL80211_ATTR_KEY_IDX, key_idx);
  459. if (mac_addr)
  460. NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr);
  461. rtnl_lock();
  462. err = drv->ops->get_key(&drv->wiphy, dev, key_idx, mac_addr,
  463. &cookie, get_key_callback);
  464. rtnl_unlock();
  465. if (err)
  466. goto out;
  467. if (cookie.error)
  468. goto nla_put_failure;
  469. genlmsg_end(msg, hdr);
  470. err = genlmsg_unicast(msg, info->snd_pid);
  471. goto out;
  472. nla_put_failure:
  473. err = -ENOBUFS;
  474. nlmsg_free(msg);
  475. out:
  476. cfg80211_put_dev(drv);
  477. dev_put(dev);
  478. return err;
  479. }
  480. static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info)
  481. {
  482. struct cfg80211_registered_device *drv;
  483. int err;
  484. struct net_device *dev;
  485. u8 key_idx;
  486. if (!info->attrs[NL80211_ATTR_KEY_IDX])
  487. return -EINVAL;
  488. key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]);
  489. if (key_idx > 3)
  490. return -EINVAL;
  491. /* currently only support setting default key */
  492. if (!info->attrs[NL80211_ATTR_KEY_DEFAULT])
  493. return -EINVAL;
  494. err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
  495. if (err)
  496. return err;
  497. if (!drv->ops->set_default_key) {
  498. err = -EOPNOTSUPP;
  499. goto out;
  500. }
  501. rtnl_lock();
  502. err = drv->ops->set_default_key(&drv->wiphy, dev, key_idx);
  503. rtnl_unlock();
  504. out:
  505. cfg80211_put_dev(drv);
  506. dev_put(dev);
  507. return err;
  508. }
  509. static int nl80211_new_key(struct sk_buff *skb, struct genl_info *info)
  510. {
  511. struct cfg80211_registered_device *drv;
  512. int err;
  513. struct net_device *dev;
  514. struct key_params params;
  515. u8 key_idx = 0;
  516. u8 *mac_addr = NULL;
  517. memset(&params, 0, sizeof(params));
  518. if (!info->attrs[NL80211_ATTR_KEY_CIPHER])
  519. return -EINVAL;
  520. if (info->attrs[NL80211_ATTR_KEY_DATA]) {
  521. params.key = nla_data(info->attrs[NL80211_ATTR_KEY_DATA]);
  522. params.key_len = nla_len(info->attrs[NL80211_ATTR_KEY_DATA]);
  523. }
  524. if (info->attrs[NL80211_ATTR_KEY_IDX])
  525. key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]);
  526. params.cipher = nla_get_u32(info->attrs[NL80211_ATTR_KEY_CIPHER]);
  527. if (info->attrs[NL80211_ATTR_MAC])
  528. mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
  529. if (key_idx > 3)
  530. return -EINVAL;
  531. /*
  532. * Disallow pairwise keys with non-zero index unless it's WEP
  533. * (because current deployments use pairwise WEP keys with
  534. * non-zero indizes but 802.11i clearly specifies to use zero)
  535. */
  536. if (mac_addr && key_idx &&
  537. params.cipher != WLAN_CIPHER_SUITE_WEP40 &&
  538. params.cipher != WLAN_CIPHER_SUITE_WEP104)
  539. return -EINVAL;
  540. /* TODO: add definitions for the lengths to linux/ieee80211.h */
  541. switch (params.cipher) {
  542. case WLAN_CIPHER_SUITE_WEP40:
  543. if (params.key_len != 5)
  544. return -EINVAL;
  545. break;
  546. case WLAN_CIPHER_SUITE_TKIP:
  547. if (params.key_len != 32)
  548. return -EINVAL;
  549. break;
  550. case WLAN_CIPHER_SUITE_CCMP:
  551. if (params.key_len != 16)
  552. return -EINVAL;
  553. break;
  554. case WLAN_CIPHER_SUITE_WEP104:
  555. if (params.key_len != 13)
  556. return -EINVAL;
  557. break;
  558. default:
  559. return -EINVAL;
  560. }
  561. err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
  562. if (err)
  563. return err;
  564. if (!drv->ops->add_key) {
  565. err = -EOPNOTSUPP;
  566. goto out;
  567. }
  568. rtnl_lock();
  569. err = drv->ops->add_key(&drv->wiphy, dev, key_idx, mac_addr, &params);
  570. rtnl_unlock();
  571. out:
  572. cfg80211_put_dev(drv);
  573. dev_put(dev);
  574. return err;
  575. }
  576. static int nl80211_del_key(struct sk_buff *skb, struct genl_info *info)
  577. {
  578. struct cfg80211_registered_device *drv;
  579. int err;
  580. struct net_device *dev;
  581. u8 key_idx = 0;
  582. u8 *mac_addr = NULL;
  583. if (info->attrs[NL80211_ATTR_KEY_IDX])
  584. key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]);
  585. if (key_idx > 3)
  586. return -EINVAL;
  587. if (info->attrs[NL80211_ATTR_MAC])
  588. mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
  589. err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
  590. if (err)
  591. return err;
  592. if (!drv->ops->del_key) {
  593. err = -EOPNOTSUPP;
  594. goto out;
  595. }
  596. rtnl_lock();
  597. err = drv->ops->del_key(&drv->wiphy, dev, key_idx, mac_addr);
  598. rtnl_unlock();
  599. out:
  600. cfg80211_put_dev(drv);
  601. dev_put(dev);
  602. return err;
  603. }
  604. static int nl80211_addset_beacon(struct sk_buff *skb, struct genl_info *info)
  605. {
  606. int (*call)(struct wiphy *wiphy, struct net_device *dev,
  607. struct beacon_parameters *info);
  608. struct cfg80211_registered_device *drv;
  609. int err;
  610. struct net_device *dev;
  611. struct beacon_parameters params;
  612. int haveinfo = 0;
  613. err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
  614. if (err)
  615. return err;
  616. switch (info->genlhdr->cmd) {
  617. case NL80211_CMD_NEW_BEACON:
  618. /* these are required for NEW_BEACON */
  619. if (!info->attrs[NL80211_ATTR_BEACON_INTERVAL] ||
  620. !info->attrs[NL80211_ATTR_DTIM_PERIOD] ||
  621. !info->attrs[NL80211_ATTR_BEACON_HEAD]) {
  622. err = -EINVAL;
  623. goto out;
  624. }
  625. call = drv->ops->add_beacon;
  626. break;
  627. case NL80211_CMD_SET_BEACON:
  628. call = drv->ops->set_beacon;
  629. break;
  630. default:
  631. WARN_ON(1);
  632. err = -EOPNOTSUPP;
  633. goto out;
  634. }
  635. if (!call) {
  636. err = -EOPNOTSUPP;
  637. goto out;
  638. }
  639. memset(&params, 0, sizeof(params));
  640. if (info->attrs[NL80211_ATTR_BEACON_INTERVAL]) {
  641. params.interval =
  642. nla_get_u32(info->attrs[NL80211_ATTR_BEACON_INTERVAL]);
  643. haveinfo = 1;
  644. }
  645. if (info->attrs[NL80211_ATTR_DTIM_PERIOD]) {
  646. params.dtim_period =
  647. nla_get_u32(info->attrs[NL80211_ATTR_DTIM_PERIOD]);
  648. haveinfo = 1;
  649. }
  650. if (info->attrs[NL80211_ATTR_BEACON_HEAD]) {
  651. params.head = nla_data(info->attrs[NL80211_ATTR_BEACON_HEAD]);
  652. params.head_len =
  653. nla_len(info->attrs[NL80211_ATTR_BEACON_HEAD]);
  654. haveinfo = 1;
  655. }
  656. if (info->attrs[NL80211_ATTR_BEACON_TAIL]) {
  657. params.tail = nla_data(info->attrs[NL80211_ATTR_BEACON_TAIL]);
  658. params.tail_len =
  659. nla_len(info->attrs[NL80211_ATTR_BEACON_TAIL]);
  660. haveinfo = 1;
  661. }
  662. if (!haveinfo) {
  663. err = -EINVAL;
  664. goto out;
  665. }
  666. rtnl_lock();
  667. err = call(&drv->wiphy, dev, &params);
  668. rtnl_unlock();
  669. out:
  670. cfg80211_put_dev(drv);
  671. dev_put(dev);
  672. return err;
  673. }
  674. static int nl80211_del_beacon(struct sk_buff *skb, struct genl_info *info)
  675. {
  676. struct cfg80211_registered_device *drv;
  677. int err;
  678. struct net_device *dev;
  679. err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
  680. if (err)
  681. return err;
  682. if (!drv->ops->del_beacon) {
  683. err = -EOPNOTSUPP;
  684. goto out;
  685. }
  686. rtnl_lock();
  687. err = drv->ops->del_beacon(&drv->wiphy, dev);
  688. rtnl_unlock();
  689. out:
  690. cfg80211_put_dev(drv);
  691. dev_put(dev);
  692. return err;
  693. }
  694. static const struct nla_policy sta_flags_policy[NL80211_STA_FLAG_MAX + 1] = {
  695. [NL80211_STA_FLAG_AUTHORIZED] = { .type = NLA_FLAG },
  696. [NL80211_STA_FLAG_SHORT_PREAMBLE] = { .type = NLA_FLAG },
  697. [NL80211_STA_FLAG_WME] = { .type = NLA_FLAG },
  698. };
  699. static int parse_station_flags(struct nlattr *nla, u32 *staflags)
  700. {
  701. struct nlattr *flags[NL80211_STA_FLAG_MAX + 1];
  702. int flag;
  703. *staflags = 0;
  704. if (!nla)
  705. return 0;
  706. if (nla_parse_nested(flags, NL80211_STA_FLAG_MAX,
  707. nla, sta_flags_policy))
  708. return -EINVAL;
  709. *staflags = STATION_FLAG_CHANGED;
  710. for (flag = 1; flag <= NL80211_STA_FLAG_MAX; flag++)
  711. if (flags[flag])
  712. *staflags |= (1<<flag);
  713. return 0;
  714. }
  715. static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq,
  716. int flags, struct net_device *dev,
  717. u8 *mac_addr, struct station_info *sinfo)
  718. {
  719. void *hdr;
  720. struct nlattr *sinfoattr;
  721. hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_STATION);
  722. if (!hdr)
  723. return -1;
  724. NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex);
  725. NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr);
  726. sinfoattr = nla_nest_start(msg, NL80211_ATTR_STA_INFO);
  727. if (!sinfoattr)
  728. goto nla_put_failure;
  729. if (sinfo->filled & STATION_INFO_INACTIVE_TIME)
  730. NLA_PUT_U32(msg, NL80211_STA_INFO_INACTIVE_TIME,
  731. sinfo->inactive_time);
  732. if (sinfo->filled & STATION_INFO_RX_BYTES)
  733. NLA_PUT_U32(msg, NL80211_STA_INFO_RX_BYTES,
  734. sinfo->rx_bytes);
  735. if (sinfo->filled & STATION_INFO_TX_BYTES)
  736. NLA_PUT_U32(msg, NL80211_STA_INFO_TX_BYTES,
  737. sinfo->tx_bytes);
  738. if (sinfo->filled & STATION_INFO_LLID)
  739. NLA_PUT_U16(msg, NL80211_STA_INFO_LLID,
  740. sinfo->llid);
  741. if (sinfo->filled & STATION_INFO_PLID)
  742. NLA_PUT_U16(msg, NL80211_STA_INFO_PLID,
  743. sinfo->plid);
  744. if (sinfo->filled & STATION_INFO_PLINK_STATE)
  745. NLA_PUT_U8(msg, NL80211_STA_INFO_PLINK_STATE,
  746. sinfo->plink_state);
  747. nla_nest_end(msg, sinfoattr);
  748. return genlmsg_end(msg, hdr);
  749. nla_put_failure:
  750. genlmsg_cancel(msg, hdr);
  751. return -EMSGSIZE;
  752. }
  753. static int nl80211_dump_station(struct sk_buff *skb,
  754. struct netlink_callback *cb)
  755. {
  756. int wp_idx = 0;
  757. int if_idx = 0;
  758. int sta_idx = cb->args[2];
  759. int wp_start = cb->args[0];
  760. int if_start = cb->args[1];
  761. struct station_info sinfo;
  762. struct cfg80211_registered_device *dev;
  763. struct wireless_dev *wdev;
  764. u8 mac_addr[ETH_ALEN];
  765. int err;
  766. int exit = 0;
  767. /* TODO: filter by device */
  768. mutex_lock(&cfg80211_drv_mutex);
  769. list_for_each_entry(dev, &cfg80211_drv_list, list) {
  770. if (exit)
  771. break;
  772. if (++wp_idx < wp_start)
  773. continue;
  774. if_idx = 0;
  775. mutex_lock(&dev->devlist_mtx);
  776. list_for_each_entry(wdev, &dev->netdev_list, list) {
  777. if (exit)
  778. break;
  779. if (++if_idx < if_start)
  780. continue;
  781. if (!dev->ops->dump_station)
  782. continue;
  783. for (;; ++sta_idx) {
  784. rtnl_lock();
  785. err = dev->ops->dump_station(&dev->wiphy,
  786. wdev->netdev, sta_idx, mac_addr,
  787. &sinfo);
  788. rtnl_unlock();
  789. if (err) {
  790. sta_idx = 0;
  791. break;
  792. }
  793. if (nl80211_send_station(skb,
  794. NETLINK_CB(cb->skb).pid,
  795. cb->nlh->nlmsg_seq, NLM_F_MULTI,
  796. wdev->netdev, mac_addr,
  797. &sinfo) < 0) {
  798. exit = 1;
  799. break;
  800. }
  801. }
  802. }
  803. mutex_unlock(&dev->devlist_mtx);
  804. }
  805. mutex_unlock(&cfg80211_drv_mutex);
  806. cb->args[0] = wp_idx;
  807. cb->args[1] = if_idx;
  808. cb->args[2] = sta_idx;
  809. return skb->len;
  810. }
  811. static int nl80211_get_station(struct sk_buff *skb, struct genl_info *info)
  812. {
  813. struct cfg80211_registered_device *drv;
  814. int err;
  815. struct net_device *dev;
  816. struct station_info sinfo;
  817. struct sk_buff *msg;
  818. u8 *mac_addr = NULL;
  819. memset(&sinfo, 0, sizeof(sinfo));
  820. if (!info->attrs[NL80211_ATTR_MAC])
  821. return -EINVAL;
  822. mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
  823. err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
  824. if (err)
  825. return err;
  826. if (!drv->ops->get_station) {
  827. err = -EOPNOTSUPP;
  828. goto out;
  829. }
  830. rtnl_lock();
  831. err = drv->ops->get_station(&drv->wiphy, dev, mac_addr, &sinfo);
  832. rtnl_unlock();
  833. if (err)
  834. goto out;
  835. msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
  836. if (!msg)
  837. goto out;
  838. if (nl80211_send_station(msg, info->snd_pid, info->snd_seq, 0,
  839. dev, mac_addr, &sinfo) < 0)
  840. goto out_free;
  841. err = genlmsg_unicast(msg, info->snd_pid);
  842. goto out;
  843. out_free:
  844. nlmsg_free(msg);
  845. out:
  846. cfg80211_put_dev(drv);
  847. dev_put(dev);
  848. return err;
  849. }
  850. /*
  851. * Get vlan interface making sure it is on the right wiphy.
  852. */
  853. static int get_vlan(struct nlattr *vlanattr,
  854. struct cfg80211_registered_device *rdev,
  855. struct net_device **vlan)
  856. {
  857. *vlan = NULL;
  858. if (vlanattr) {
  859. *vlan = dev_get_by_index(&init_net, nla_get_u32(vlanattr));
  860. if (!*vlan)
  861. return -ENODEV;
  862. if (!(*vlan)->ieee80211_ptr)
  863. return -EINVAL;
  864. if ((*vlan)->ieee80211_ptr->wiphy != &rdev->wiphy)
  865. return -EINVAL;
  866. }
  867. return 0;
  868. }
  869. static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info)
  870. {
  871. struct cfg80211_registered_device *drv;
  872. int err;
  873. struct net_device *dev;
  874. struct station_parameters params;
  875. u8 *mac_addr = NULL;
  876. memset(&params, 0, sizeof(params));
  877. params.listen_interval = -1;
  878. if (info->attrs[NL80211_ATTR_STA_AID])
  879. return -EINVAL;
  880. if (!info->attrs[NL80211_ATTR_MAC])
  881. return -EINVAL;
  882. mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
  883. if (info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]) {
  884. params.supported_rates =
  885. nla_data(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]);
  886. params.supported_rates_len =
  887. nla_len(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]);
  888. }
  889. if (info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL])
  890. params.listen_interval =
  891. nla_get_u16(info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]);
  892. if (parse_station_flags(info->attrs[NL80211_ATTR_STA_FLAGS],
  893. &params.station_flags))
  894. return -EINVAL;
  895. if (info->attrs[NL80211_ATTR_STA_PLINK_ACTION])
  896. params.plink_action =
  897. nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_ACTION]);
  898. err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
  899. if (err)
  900. return err;
  901. err = get_vlan(info->attrs[NL80211_ATTR_STA_VLAN], drv, &params.vlan);
  902. if (err)
  903. goto out;
  904. if (!drv->ops->change_station) {
  905. err = -EOPNOTSUPP;
  906. goto out;
  907. }
  908. rtnl_lock();
  909. err = drv->ops->change_station(&drv->wiphy, dev, mac_addr, &params);
  910. rtnl_unlock();
  911. out:
  912. if (params.vlan)
  913. dev_put(params.vlan);
  914. cfg80211_put_dev(drv);
  915. dev_put(dev);
  916. return err;
  917. }
  918. static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
  919. {
  920. struct cfg80211_registered_device *drv;
  921. int err;
  922. struct net_device *dev;
  923. struct station_parameters params;
  924. u8 *mac_addr = NULL;
  925. memset(&params, 0, sizeof(params));
  926. if (!info->attrs[NL80211_ATTR_MAC])
  927. return -EINVAL;
  928. if (!info->attrs[NL80211_ATTR_STA_AID])
  929. return -EINVAL;
  930. if (!info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL])
  931. return -EINVAL;
  932. if (!info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES])
  933. return -EINVAL;
  934. mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
  935. params.supported_rates =
  936. nla_data(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]);
  937. params.supported_rates_len =
  938. nla_len(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]);
  939. params.listen_interval =
  940. nla_get_u16(info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]);
  941. params.aid = nla_get_u16(info->attrs[NL80211_ATTR_STA_AID]);
  942. if (parse_station_flags(info->attrs[NL80211_ATTR_STA_FLAGS],
  943. &params.station_flags))
  944. return -EINVAL;
  945. err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
  946. if (err)
  947. return err;
  948. err = get_vlan(info->attrs[NL80211_ATTR_STA_VLAN], drv, &params.vlan);
  949. if (err)
  950. goto out;
  951. if (!drv->ops->add_station) {
  952. err = -EOPNOTSUPP;
  953. goto out;
  954. }
  955. rtnl_lock();
  956. err = drv->ops->add_station(&drv->wiphy, dev, mac_addr, &params);
  957. rtnl_unlock();
  958. out:
  959. if (params.vlan)
  960. dev_put(params.vlan);
  961. cfg80211_put_dev(drv);
  962. dev_put(dev);
  963. return err;
  964. }
  965. static int nl80211_del_station(struct sk_buff *skb, struct genl_info *info)
  966. {
  967. struct cfg80211_registered_device *drv;
  968. int err;
  969. struct net_device *dev;
  970. u8 *mac_addr = NULL;
  971. if (info->attrs[NL80211_ATTR_MAC])
  972. mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
  973. err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
  974. if (err)
  975. return err;
  976. if (!drv->ops->del_station) {
  977. err = -EOPNOTSUPP;
  978. goto out;
  979. }
  980. rtnl_lock();
  981. err = drv->ops->del_station(&drv->wiphy, dev, mac_addr);
  982. rtnl_unlock();
  983. out:
  984. cfg80211_put_dev(drv);
  985. dev_put(dev);
  986. return err;
  987. }
  988. static int nl80211_send_mpath(struct sk_buff *msg, u32 pid, u32 seq,
  989. int flags, struct net_device *dev,
  990. u8 *dst, u8 *next_hop,
  991. struct mpath_info *pinfo)
  992. {
  993. void *hdr;
  994. struct nlattr *pinfoattr;
  995. hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_STATION);
  996. if (!hdr)
  997. return -1;
  998. NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex);
  999. NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, dst);
  1000. NLA_PUT(msg, NL80211_ATTR_MPATH_NEXT_HOP, ETH_ALEN, next_hop);
  1001. pinfoattr = nla_nest_start(msg, NL80211_ATTR_MPATH_INFO);
  1002. if (!pinfoattr)
  1003. goto nla_put_failure;
  1004. if (pinfo->filled & MPATH_INFO_FRAME_QLEN)
  1005. NLA_PUT_U32(msg, NL80211_MPATH_INFO_FRAME_QLEN,
  1006. pinfo->frame_qlen);
  1007. if (pinfo->filled & MPATH_INFO_DSN)
  1008. NLA_PUT_U32(msg, NL80211_MPATH_INFO_DSN,
  1009. pinfo->dsn);
  1010. if (pinfo->filled & MPATH_INFO_METRIC)
  1011. NLA_PUT_U32(msg, NL80211_MPATH_INFO_METRIC,
  1012. pinfo->metric);
  1013. if (pinfo->filled & MPATH_INFO_EXPTIME)
  1014. NLA_PUT_U32(msg, NL80211_MPATH_INFO_EXPTIME,
  1015. pinfo->exptime);
  1016. if (pinfo->filled & MPATH_INFO_FLAGS)
  1017. NLA_PUT_U8(msg, NL80211_MPATH_INFO_FLAGS,
  1018. pinfo->flags);
  1019. if (pinfo->filled & MPATH_INFO_DISCOVERY_TIMEOUT)
  1020. NLA_PUT_U32(msg, NL80211_MPATH_INFO_DISCOVERY_TIMEOUT,
  1021. pinfo->discovery_timeout);
  1022. if (pinfo->filled & MPATH_INFO_DISCOVERY_RETRIES)
  1023. NLA_PUT_U8(msg, NL80211_MPATH_INFO_DISCOVERY_RETRIES,
  1024. pinfo->discovery_retries);
  1025. nla_nest_end(msg, pinfoattr);
  1026. return genlmsg_end(msg, hdr);
  1027. nla_put_failure:
  1028. genlmsg_cancel(msg, hdr);
  1029. return -EMSGSIZE;
  1030. }
  1031. static int nl80211_dump_mpath(struct sk_buff *skb,
  1032. struct netlink_callback *cb)
  1033. {
  1034. int wp_idx = 0;
  1035. int if_idx = 0;
  1036. int sta_idx = cb->args[2];
  1037. int wp_start = cb->args[0];
  1038. int if_start = cb->args[1];
  1039. struct mpath_info pinfo;
  1040. struct cfg80211_registered_device *dev;
  1041. struct wireless_dev *wdev;
  1042. u8 dst[ETH_ALEN];
  1043. u8 next_hop[ETH_ALEN];
  1044. int err;
  1045. int exit = 0;
  1046. /* TODO: filter by device */
  1047. mutex_lock(&cfg80211_drv_mutex);
  1048. list_for_each_entry(dev, &cfg80211_drv_list, list) {
  1049. if (exit)
  1050. break;
  1051. if (++wp_idx < wp_start)
  1052. continue;
  1053. if_idx = 0;
  1054. mutex_lock(&dev->devlist_mtx);
  1055. list_for_each_entry(wdev, &dev->netdev_list, list) {
  1056. if (exit)
  1057. break;
  1058. if (++if_idx < if_start)
  1059. continue;
  1060. if (!dev->ops->dump_mpath)
  1061. continue;
  1062. for (;; ++sta_idx) {
  1063. rtnl_lock();
  1064. err = dev->ops->dump_mpath(&dev->wiphy,
  1065. wdev->netdev, sta_idx, dst,
  1066. next_hop, &pinfo);
  1067. rtnl_unlock();
  1068. if (err) {
  1069. sta_idx = 0;
  1070. break;
  1071. }
  1072. if (nl80211_send_mpath(skb,
  1073. NETLINK_CB(cb->skb).pid,
  1074. cb->nlh->nlmsg_seq, NLM_F_MULTI,
  1075. wdev->netdev, dst, next_hop,
  1076. &pinfo) < 0) {
  1077. exit = 1;
  1078. break;
  1079. }
  1080. }
  1081. }
  1082. mutex_unlock(&dev->devlist_mtx);
  1083. }
  1084. mutex_unlock(&cfg80211_drv_mutex);
  1085. cb->args[0] = wp_idx;
  1086. cb->args[1] = if_idx;
  1087. cb->args[2] = sta_idx;
  1088. return skb->len;
  1089. }
  1090. static int nl80211_get_mpath(struct sk_buff *skb, struct genl_info *info)
  1091. {
  1092. struct cfg80211_registered_device *drv;
  1093. int err;
  1094. struct net_device *dev;
  1095. struct mpath_info pinfo;
  1096. struct sk_buff *msg;
  1097. u8 *dst = NULL;
  1098. u8 next_hop[ETH_ALEN];
  1099. memset(&pinfo, 0, sizeof(pinfo));
  1100. if (!info->attrs[NL80211_ATTR_MAC])
  1101. return -EINVAL;
  1102. dst = nla_data(info->attrs[NL80211_ATTR_MAC]);
  1103. err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
  1104. if (err)
  1105. return err;
  1106. if (!drv->ops->get_mpath) {
  1107. err = -EOPNOTSUPP;
  1108. goto out;
  1109. }
  1110. rtnl_lock();
  1111. err = drv->ops->get_mpath(&drv->wiphy, dev, dst, next_hop, &pinfo);
  1112. rtnl_unlock();
  1113. if (err)
  1114. goto out;
  1115. msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
  1116. if (!msg)
  1117. goto out;
  1118. if (nl80211_send_mpath(msg, info->snd_pid, info->snd_seq, 0,
  1119. dev, dst, next_hop, &pinfo) < 0)
  1120. goto out_free;
  1121. err = genlmsg_unicast(msg, info->snd_pid);
  1122. goto out;
  1123. out_free:
  1124. nlmsg_free(msg);
  1125. out:
  1126. cfg80211_put_dev(drv);
  1127. dev_put(dev);
  1128. return err;
  1129. }
  1130. static int nl80211_set_mpath(struct sk_buff *skb, struct genl_info *info)
  1131. {
  1132. struct cfg80211_registered_device *drv;
  1133. int err;
  1134. struct net_device *dev;
  1135. u8 *dst = NULL;
  1136. u8 *next_hop = NULL;
  1137. if (!info->attrs[NL80211_ATTR_MAC])
  1138. return -EINVAL;
  1139. if (!info->attrs[NL80211_ATTR_MPATH_NEXT_HOP])
  1140. return -EINVAL;
  1141. dst = nla_data(info->attrs[NL80211_ATTR_MAC]);
  1142. next_hop = nla_data(info->attrs[NL80211_ATTR_MPATH_NEXT_HOP]);
  1143. err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
  1144. if (err)
  1145. return err;
  1146. if (!drv->ops->change_mpath) {
  1147. err = -EOPNOTSUPP;
  1148. goto out;
  1149. }
  1150. rtnl_lock();
  1151. err = drv->ops->change_mpath(&drv->wiphy, dev, dst, next_hop);
  1152. rtnl_unlock();
  1153. out:
  1154. cfg80211_put_dev(drv);
  1155. dev_put(dev);
  1156. return err;
  1157. }
  1158. static int nl80211_new_mpath(struct sk_buff *skb, struct genl_info *info)
  1159. {
  1160. struct cfg80211_registered_device *drv;
  1161. int err;
  1162. struct net_device *dev;
  1163. u8 *dst = NULL;
  1164. u8 *next_hop = NULL;
  1165. if (!info->attrs[NL80211_ATTR_MAC])
  1166. return -EINVAL;
  1167. if (!info->attrs[NL80211_ATTR_MPATH_NEXT_HOP])
  1168. return -EINVAL;
  1169. dst = nla_data(info->attrs[NL80211_ATTR_MAC]);
  1170. next_hop = nla_data(info->attrs[NL80211_ATTR_MPATH_NEXT_HOP]);
  1171. err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
  1172. if (err)
  1173. return err;
  1174. if (!drv->ops->add_mpath) {
  1175. err = -EOPNOTSUPP;
  1176. goto out;
  1177. }
  1178. rtnl_lock();
  1179. err = drv->ops->add_mpath(&drv->wiphy, dev, dst, next_hop);
  1180. rtnl_unlock();
  1181. out:
  1182. cfg80211_put_dev(drv);
  1183. dev_put(dev);
  1184. return err;
  1185. }
  1186. static int nl80211_del_mpath(struct sk_buff *skb, struct genl_info *info)
  1187. {
  1188. struct cfg80211_registered_device *drv;
  1189. int err;
  1190. struct net_device *dev;
  1191. u8 *dst = NULL;
  1192. if (info->attrs[NL80211_ATTR_MAC])
  1193. dst = nla_data(info->attrs[NL80211_ATTR_MAC]);
  1194. err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
  1195. if (err)
  1196. return err;
  1197. if (!drv->ops->del_mpath) {
  1198. err = -EOPNOTSUPP;
  1199. goto out;
  1200. }
  1201. rtnl_lock();
  1202. err = drv->ops->del_mpath(&drv->wiphy, dev, dst);
  1203. rtnl_unlock();
  1204. out:
  1205. cfg80211_put_dev(drv);
  1206. dev_put(dev);
  1207. return err;
  1208. }
  1209. static struct genl_ops nl80211_ops[] = {
  1210. {
  1211. .cmd = NL80211_CMD_GET_WIPHY,
  1212. .doit = nl80211_get_wiphy,
  1213. .dumpit = nl80211_dump_wiphy,
  1214. .policy = nl80211_policy,
  1215. /* can be retrieved by unprivileged users */
  1216. },
  1217. {
  1218. .cmd = NL80211_CMD_SET_WIPHY,
  1219. .doit = nl80211_set_wiphy,
  1220. .policy = nl80211_policy,
  1221. .flags = GENL_ADMIN_PERM,
  1222. },
  1223. {
  1224. .cmd = NL80211_CMD_GET_INTERFACE,
  1225. .doit = nl80211_get_interface,
  1226. .dumpit = nl80211_dump_interface,
  1227. .policy = nl80211_policy,
  1228. /* can be retrieved by unprivileged users */
  1229. },
  1230. {
  1231. .cmd = NL80211_CMD_SET_INTERFACE,
  1232. .doit = nl80211_set_interface,
  1233. .policy = nl80211_policy,
  1234. .flags = GENL_ADMIN_PERM,
  1235. },
  1236. {
  1237. .cmd = NL80211_CMD_NEW_INTERFACE,
  1238. .doit = nl80211_new_interface,
  1239. .policy = nl80211_policy,
  1240. .flags = GENL_ADMIN_PERM,
  1241. },
  1242. {
  1243. .cmd = NL80211_CMD_DEL_INTERFACE,
  1244. .doit = nl80211_del_interface,
  1245. .policy = nl80211_policy,
  1246. .flags = GENL_ADMIN_PERM,
  1247. },
  1248. {
  1249. .cmd = NL80211_CMD_GET_KEY,
  1250. .doit = nl80211_get_key,
  1251. .policy = nl80211_policy,
  1252. .flags = GENL_ADMIN_PERM,
  1253. },
  1254. {
  1255. .cmd = NL80211_CMD_SET_KEY,
  1256. .doit = nl80211_set_key,
  1257. .policy = nl80211_policy,
  1258. .flags = GENL_ADMIN_PERM,
  1259. },
  1260. {
  1261. .cmd = NL80211_CMD_NEW_KEY,
  1262. .doit = nl80211_new_key,
  1263. .policy = nl80211_policy,
  1264. .flags = GENL_ADMIN_PERM,
  1265. },
  1266. {
  1267. .cmd = NL80211_CMD_DEL_KEY,
  1268. .doit = nl80211_del_key,
  1269. .policy = nl80211_policy,
  1270. .flags = GENL_ADMIN_PERM,
  1271. },
  1272. {
  1273. .cmd = NL80211_CMD_SET_BEACON,
  1274. .policy = nl80211_policy,
  1275. .flags = GENL_ADMIN_PERM,
  1276. .doit = nl80211_addset_beacon,
  1277. },
  1278. {
  1279. .cmd = NL80211_CMD_NEW_BEACON,
  1280. .policy = nl80211_policy,
  1281. .flags = GENL_ADMIN_PERM,
  1282. .doit = nl80211_addset_beacon,
  1283. },
  1284. {
  1285. .cmd = NL80211_CMD_DEL_BEACON,
  1286. .policy = nl80211_policy,
  1287. .flags = GENL_ADMIN_PERM,
  1288. .doit = nl80211_del_beacon,
  1289. },
  1290. {
  1291. .cmd = NL80211_CMD_GET_STATION,
  1292. .doit = nl80211_get_station,
  1293. .dumpit = nl80211_dump_station,
  1294. .policy = nl80211_policy,
  1295. .flags = GENL_ADMIN_PERM,
  1296. },
  1297. {
  1298. .cmd = NL80211_CMD_SET_STATION,
  1299. .doit = nl80211_set_station,
  1300. .policy = nl80211_policy,
  1301. .flags = GENL_ADMIN_PERM,
  1302. },
  1303. {
  1304. .cmd = NL80211_CMD_NEW_STATION,
  1305. .doit = nl80211_new_station,
  1306. .policy = nl80211_policy,
  1307. .flags = GENL_ADMIN_PERM,
  1308. },
  1309. {
  1310. .cmd = NL80211_CMD_DEL_STATION,
  1311. .doit = nl80211_del_station,
  1312. .policy = nl80211_policy,
  1313. .flags = GENL_ADMIN_PERM,
  1314. },
  1315. {
  1316. .cmd = NL80211_CMD_GET_MPATH,
  1317. .doit = nl80211_get_mpath,
  1318. .dumpit = nl80211_dump_mpath,
  1319. .policy = nl80211_policy,
  1320. .flags = GENL_ADMIN_PERM,
  1321. },
  1322. {
  1323. .cmd = NL80211_CMD_SET_MPATH,
  1324. .doit = nl80211_set_mpath,
  1325. .policy = nl80211_policy,
  1326. .flags = GENL_ADMIN_PERM,
  1327. },
  1328. {
  1329. .cmd = NL80211_CMD_NEW_MPATH,
  1330. .doit = nl80211_new_mpath,
  1331. .policy = nl80211_policy,
  1332. .flags = GENL_ADMIN_PERM,
  1333. },
  1334. {
  1335. .cmd = NL80211_CMD_DEL_MPATH,
  1336. .doit = nl80211_del_mpath,
  1337. .policy = nl80211_policy,
  1338. .flags = GENL_ADMIN_PERM,
  1339. },
  1340. };
  1341. /* multicast groups */
  1342. static struct genl_multicast_group nl80211_config_mcgrp = {
  1343. .name = "config",
  1344. };
  1345. /* notification functions */
  1346. void nl80211_notify_dev_rename(struct cfg80211_registered_device *rdev)
  1347. {
  1348. struct sk_buff *msg;
  1349. msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
  1350. if (!msg)
  1351. return;
  1352. if (nl80211_send_wiphy(msg, 0, 0, 0, rdev) < 0) {
  1353. nlmsg_free(msg);
  1354. return;
  1355. }
  1356. genlmsg_multicast(msg, 0, nl80211_config_mcgrp.id, GFP_KERNEL);
  1357. }
  1358. /* initialisation/exit functions */
  1359. int nl80211_init(void)
  1360. {
  1361. int err, i;
  1362. err = genl_register_family(&nl80211_fam);
  1363. if (err)
  1364. return err;
  1365. for (i = 0; i < ARRAY_SIZE(nl80211_ops); i++) {
  1366. err = genl_register_ops(&nl80211_fam, &nl80211_ops[i]);
  1367. if (err)
  1368. goto err_out;
  1369. }
  1370. err = genl_register_mc_group(&nl80211_fam, &nl80211_config_mcgrp);
  1371. if (err)
  1372. goto err_out;
  1373. return 0;
  1374. err_out:
  1375. genl_unregister_family(&nl80211_fam);
  1376. return err;
  1377. }
  1378. void nl80211_exit(void)
  1379. {
  1380. genl_unregister_family(&nl80211_fam);
  1381. }