nl-mac.c 39 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519
  1. /*
  2. * Netlink inteface for IEEE 802.15.4 stack
  3. *
  4. * Copyright 2007, 2008 Siemens AG
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License version 2
  8. * as published by the Free Software Foundation.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * Written by:
  16. * Sergey Lapin <slapin@ossfans.org>
  17. * Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
  18. * Maxim Osipov <maxim.osipov@siemens.com>
  19. */
  20. #include <linux/gfp.h>
  21. #include <linux/kernel.h>
  22. #include <linux/if_arp.h>
  23. #include <linux/netdevice.h>
  24. #include <linux/ieee802154.h>
  25. #include <net/netlink.h>
  26. #include <net/genetlink.h>
  27. #include <net/sock.h>
  28. #include <linux/nl802154.h>
  29. #include <linux/export.h>
  30. #include <net/af_ieee802154.h>
  31. #include <net/nl802154.h>
  32. #include <net/ieee802154_netdev.h>
  33. #include <net/cfg802154.h>
  34. #include "ieee802154.h"
  35. static int nla_put_hwaddr(struct sk_buff *msg, int type, __le64 hwaddr)
  36. {
  37. return nla_put_u64(msg, type, swab64((__force u64)hwaddr));
  38. }
  39. static __le64 nla_get_hwaddr(const struct nlattr *nla)
  40. {
  41. return ieee802154_devaddr_from_raw(nla_data(nla));
  42. }
  43. static int nla_put_shortaddr(struct sk_buff *msg, int type, __le16 addr)
  44. {
  45. return nla_put_u16(msg, type, le16_to_cpu(addr));
  46. }
  47. static __le16 nla_get_shortaddr(const struct nlattr *nla)
  48. {
  49. return cpu_to_le16(nla_get_u16(nla));
  50. }
  51. int ieee802154_nl_assoc_indic(struct net_device *dev,
  52. struct ieee802154_addr *addr,
  53. u8 cap)
  54. {
  55. struct sk_buff *msg;
  56. pr_debug("%s\n", __func__);
  57. if (addr->mode != IEEE802154_ADDR_LONG) {
  58. pr_err("%s: received non-long source address!\n", __func__);
  59. return -EINVAL;
  60. }
  61. msg = ieee802154_nl_create(0, IEEE802154_ASSOCIATE_INDIC);
  62. if (!msg)
  63. return -ENOBUFS;
  64. if (nla_put_string(msg, IEEE802154_ATTR_DEV_NAME, dev->name) ||
  65. nla_put_u32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex) ||
  66. nla_put(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN,
  67. dev->dev_addr) ||
  68. nla_put_hwaddr(msg, IEEE802154_ATTR_SRC_HW_ADDR,
  69. addr->extended_addr) ||
  70. nla_put_u8(msg, IEEE802154_ATTR_CAPABILITY, cap))
  71. goto nla_put_failure;
  72. return ieee802154_nl_mcast(msg, IEEE802154_COORD_MCGRP);
  73. nla_put_failure:
  74. nlmsg_free(msg);
  75. return -ENOBUFS;
  76. }
  77. EXPORT_SYMBOL(ieee802154_nl_assoc_indic);
  78. int ieee802154_nl_assoc_confirm(struct net_device *dev, __le16 short_addr,
  79. u8 status)
  80. {
  81. struct sk_buff *msg;
  82. pr_debug("%s\n", __func__);
  83. msg = ieee802154_nl_create(0, IEEE802154_ASSOCIATE_CONF);
  84. if (!msg)
  85. return -ENOBUFS;
  86. if (nla_put_string(msg, IEEE802154_ATTR_DEV_NAME, dev->name) ||
  87. nla_put_u32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex) ||
  88. nla_put(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN,
  89. dev->dev_addr) ||
  90. nla_put_shortaddr(msg, IEEE802154_ATTR_SHORT_ADDR, short_addr) ||
  91. nla_put_u8(msg, IEEE802154_ATTR_STATUS, status))
  92. goto nla_put_failure;
  93. return ieee802154_nl_mcast(msg, IEEE802154_COORD_MCGRP);
  94. nla_put_failure:
  95. nlmsg_free(msg);
  96. return -ENOBUFS;
  97. }
  98. EXPORT_SYMBOL(ieee802154_nl_assoc_confirm);
  99. int ieee802154_nl_disassoc_indic(struct net_device *dev,
  100. struct ieee802154_addr *addr,
  101. u8 reason)
  102. {
  103. struct sk_buff *msg;
  104. pr_debug("%s\n", __func__);
  105. msg = ieee802154_nl_create(0, IEEE802154_DISASSOCIATE_INDIC);
  106. if (!msg)
  107. return -ENOBUFS;
  108. if (nla_put_string(msg, IEEE802154_ATTR_DEV_NAME, dev->name) ||
  109. nla_put_u32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex) ||
  110. nla_put(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN,
  111. dev->dev_addr))
  112. goto nla_put_failure;
  113. if (addr->mode == IEEE802154_ADDR_LONG) {
  114. if (nla_put_hwaddr(msg, IEEE802154_ATTR_SRC_HW_ADDR,
  115. addr->extended_addr))
  116. goto nla_put_failure;
  117. } else {
  118. if (nla_put_shortaddr(msg, IEEE802154_ATTR_SRC_SHORT_ADDR,
  119. addr->short_addr))
  120. goto nla_put_failure;
  121. }
  122. if (nla_put_u8(msg, IEEE802154_ATTR_REASON, reason))
  123. goto nla_put_failure;
  124. return ieee802154_nl_mcast(msg, IEEE802154_COORD_MCGRP);
  125. nla_put_failure:
  126. nlmsg_free(msg);
  127. return -ENOBUFS;
  128. }
  129. EXPORT_SYMBOL(ieee802154_nl_disassoc_indic);
  130. int ieee802154_nl_disassoc_confirm(struct net_device *dev, u8 status)
  131. {
  132. struct sk_buff *msg;
  133. pr_debug("%s\n", __func__);
  134. msg = ieee802154_nl_create(0, IEEE802154_DISASSOCIATE_CONF);
  135. if (!msg)
  136. return -ENOBUFS;
  137. if (nla_put_string(msg, IEEE802154_ATTR_DEV_NAME, dev->name) ||
  138. nla_put_u32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex) ||
  139. nla_put(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN,
  140. dev->dev_addr) ||
  141. nla_put_u8(msg, IEEE802154_ATTR_STATUS, status))
  142. goto nla_put_failure;
  143. return ieee802154_nl_mcast(msg, IEEE802154_COORD_MCGRP);
  144. nla_put_failure:
  145. nlmsg_free(msg);
  146. return -ENOBUFS;
  147. }
  148. EXPORT_SYMBOL(ieee802154_nl_disassoc_confirm);
  149. int ieee802154_nl_beacon_indic(struct net_device *dev, __le16 panid,
  150. __le16 coord_addr)
  151. {
  152. struct sk_buff *msg;
  153. pr_debug("%s\n", __func__);
  154. msg = ieee802154_nl_create(0, IEEE802154_BEACON_NOTIFY_INDIC);
  155. if (!msg)
  156. return -ENOBUFS;
  157. if (nla_put_string(msg, IEEE802154_ATTR_DEV_NAME, dev->name) ||
  158. nla_put_u32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex) ||
  159. nla_put(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN,
  160. dev->dev_addr) ||
  161. nla_put_shortaddr(msg, IEEE802154_ATTR_COORD_SHORT_ADDR,
  162. coord_addr) ||
  163. nla_put_shortaddr(msg, IEEE802154_ATTR_COORD_PAN_ID, panid))
  164. goto nla_put_failure;
  165. return ieee802154_nl_mcast(msg, IEEE802154_COORD_MCGRP);
  166. nla_put_failure:
  167. nlmsg_free(msg);
  168. return -ENOBUFS;
  169. }
  170. EXPORT_SYMBOL(ieee802154_nl_beacon_indic);
  171. int ieee802154_nl_scan_confirm(struct net_device *dev,
  172. u8 status, u8 scan_type,
  173. u32 unscanned, u8 page,
  174. u8 *edl/* , struct list_head *pan_desc_list */)
  175. {
  176. struct sk_buff *msg;
  177. pr_debug("%s\n", __func__);
  178. msg = ieee802154_nl_create(0, IEEE802154_SCAN_CONF);
  179. if (!msg)
  180. return -ENOBUFS;
  181. if (nla_put_string(msg, IEEE802154_ATTR_DEV_NAME, dev->name) ||
  182. nla_put_u32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex) ||
  183. nla_put(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN,
  184. dev->dev_addr) ||
  185. nla_put_u8(msg, IEEE802154_ATTR_STATUS, status) ||
  186. nla_put_u8(msg, IEEE802154_ATTR_SCAN_TYPE, scan_type) ||
  187. nla_put_u32(msg, IEEE802154_ATTR_CHANNELS, unscanned) ||
  188. nla_put_u8(msg, IEEE802154_ATTR_PAGE, page) ||
  189. (edl &&
  190. nla_put(msg, IEEE802154_ATTR_ED_LIST, 27, edl)))
  191. goto nla_put_failure;
  192. return ieee802154_nl_mcast(msg, IEEE802154_COORD_MCGRP);
  193. nla_put_failure:
  194. nlmsg_free(msg);
  195. return -ENOBUFS;
  196. }
  197. EXPORT_SYMBOL(ieee802154_nl_scan_confirm);
  198. int ieee802154_nl_start_confirm(struct net_device *dev, u8 status)
  199. {
  200. struct sk_buff *msg;
  201. pr_debug("%s\n", __func__);
  202. msg = ieee802154_nl_create(0, IEEE802154_START_CONF);
  203. if (!msg)
  204. return -ENOBUFS;
  205. if (nla_put_string(msg, IEEE802154_ATTR_DEV_NAME, dev->name) ||
  206. nla_put_u32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex) ||
  207. nla_put(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN,
  208. dev->dev_addr) ||
  209. nla_put_u8(msg, IEEE802154_ATTR_STATUS, status))
  210. goto nla_put_failure;
  211. return ieee802154_nl_mcast(msg, IEEE802154_COORD_MCGRP);
  212. nla_put_failure:
  213. nlmsg_free(msg);
  214. return -ENOBUFS;
  215. }
  216. EXPORT_SYMBOL(ieee802154_nl_start_confirm);
  217. static int ieee802154_nl_fill_iface(struct sk_buff *msg, u32 portid,
  218. u32 seq, int flags, struct net_device *dev)
  219. {
  220. void *hdr;
  221. struct wpan_phy *phy;
  222. struct ieee802154_mlme_ops *ops;
  223. __le16 short_addr, pan_id;
  224. pr_debug("%s\n", __func__);
  225. hdr = genlmsg_put(msg, 0, seq, &nl802154_family, flags,
  226. IEEE802154_LIST_IFACE);
  227. if (!hdr)
  228. goto out;
  229. ops = ieee802154_mlme_ops(dev);
  230. phy = ops->get_phy(dev);
  231. BUG_ON(!phy);
  232. short_addr = ops->get_short_addr(dev);
  233. pan_id = ops->get_pan_id(dev);
  234. if (nla_put_string(msg, IEEE802154_ATTR_DEV_NAME, dev->name) ||
  235. nla_put_string(msg, IEEE802154_ATTR_PHY_NAME, wpan_phy_name(phy)) ||
  236. nla_put_u32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex) ||
  237. nla_put(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN,
  238. dev->dev_addr) ||
  239. nla_put_shortaddr(msg, IEEE802154_ATTR_SHORT_ADDR, short_addr) ||
  240. nla_put_shortaddr(msg, IEEE802154_ATTR_PAN_ID, pan_id))
  241. goto nla_put_failure;
  242. if (ops->get_mac_params) {
  243. struct ieee802154_mac_params params;
  244. ops->get_mac_params(dev, &params);
  245. if (nla_put_s8(msg, IEEE802154_ATTR_TXPOWER,
  246. params.transmit_power) ||
  247. nla_put_u8(msg, IEEE802154_ATTR_LBT_ENABLED, params.lbt) ||
  248. nla_put_u8(msg, IEEE802154_ATTR_CCA_MODE,
  249. params.cca_mode) ||
  250. nla_put_s32(msg, IEEE802154_ATTR_CCA_ED_LEVEL,
  251. params.cca_ed_level) ||
  252. nla_put_u8(msg, IEEE802154_ATTR_CSMA_RETRIES,
  253. params.csma_retries) ||
  254. nla_put_u8(msg, IEEE802154_ATTR_CSMA_MIN_BE,
  255. params.min_be) ||
  256. nla_put_u8(msg, IEEE802154_ATTR_CSMA_MAX_BE,
  257. params.max_be) ||
  258. nla_put_s8(msg, IEEE802154_ATTR_FRAME_RETRIES,
  259. params.frame_retries))
  260. goto nla_put_failure;
  261. }
  262. wpan_phy_put(phy);
  263. return genlmsg_end(msg, hdr);
  264. nla_put_failure:
  265. wpan_phy_put(phy);
  266. genlmsg_cancel(msg, hdr);
  267. out:
  268. return -EMSGSIZE;
  269. }
  270. /* Requests from userspace */
  271. static struct net_device *ieee802154_nl_get_dev(struct genl_info *info)
  272. {
  273. struct net_device *dev;
  274. if (info->attrs[IEEE802154_ATTR_DEV_NAME]) {
  275. char name[IFNAMSIZ + 1];
  276. nla_strlcpy(name, info->attrs[IEEE802154_ATTR_DEV_NAME],
  277. sizeof(name));
  278. dev = dev_get_by_name(&init_net, name);
  279. } else if (info->attrs[IEEE802154_ATTR_DEV_INDEX]) {
  280. dev = dev_get_by_index(&init_net,
  281. nla_get_u32(info->attrs[IEEE802154_ATTR_DEV_INDEX]));
  282. } else {
  283. return NULL;
  284. }
  285. if (!dev)
  286. return NULL;
  287. if (dev->type != ARPHRD_IEEE802154) {
  288. dev_put(dev);
  289. return NULL;
  290. }
  291. return dev;
  292. }
  293. int ieee802154_associate_req(struct sk_buff *skb, struct genl_info *info)
  294. {
  295. struct net_device *dev;
  296. struct ieee802154_addr addr;
  297. u8 page;
  298. int ret = -EOPNOTSUPP;
  299. if (!info->attrs[IEEE802154_ATTR_CHANNEL] ||
  300. !info->attrs[IEEE802154_ATTR_COORD_PAN_ID] ||
  301. (!info->attrs[IEEE802154_ATTR_COORD_HW_ADDR] &&
  302. !info->attrs[IEEE802154_ATTR_COORD_SHORT_ADDR]) ||
  303. !info->attrs[IEEE802154_ATTR_CAPABILITY])
  304. return -EINVAL;
  305. dev = ieee802154_nl_get_dev(info);
  306. if (!dev)
  307. return -ENODEV;
  308. if (!ieee802154_mlme_ops(dev)->assoc_req)
  309. goto out;
  310. if (info->attrs[IEEE802154_ATTR_COORD_HW_ADDR]) {
  311. addr.mode = IEEE802154_ADDR_LONG;
  312. addr.extended_addr = nla_get_hwaddr(
  313. info->attrs[IEEE802154_ATTR_COORD_HW_ADDR]);
  314. } else {
  315. addr.mode = IEEE802154_ADDR_SHORT;
  316. addr.short_addr = nla_get_shortaddr(
  317. info->attrs[IEEE802154_ATTR_COORD_SHORT_ADDR]);
  318. }
  319. addr.pan_id = nla_get_shortaddr(
  320. info->attrs[IEEE802154_ATTR_COORD_PAN_ID]);
  321. if (info->attrs[IEEE802154_ATTR_PAGE])
  322. page = nla_get_u8(info->attrs[IEEE802154_ATTR_PAGE]);
  323. else
  324. page = 0;
  325. ret = ieee802154_mlme_ops(dev)->assoc_req(dev, &addr,
  326. nla_get_u8(info->attrs[IEEE802154_ATTR_CHANNEL]),
  327. page,
  328. nla_get_u8(info->attrs[IEEE802154_ATTR_CAPABILITY]));
  329. out:
  330. dev_put(dev);
  331. return ret;
  332. }
  333. int ieee802154_associate_resp(struct sk_buff *skb, struct genl_info *info)
  334. {
  335. struct net_device *dev;
  336. struct ieee802154_addr addr;
  337. int ret = -EOPNOTSUPP;
  338. if (!info->attrs[IEEE802154_ATTR_STATUS] ||
  339. !info->attrs[IEEE802154_ATTR_DEST_HW_ADDR] ||
  340. !info->attrs[IEEE802154_ATTR_DEST_SHORT_ADDR])
  341. return -EINVAL;
  342. dev = ieee802154_nl_get_dev(info);
  343. if (!dev)
  344. return -ENODEV;
  345. if (!ieee802154_mlme_ops(dev)->assoc_resp)
  346. goto out;
  347. addr.mode = IEEE802154_ADDR_LONG;
  348. addr.extended_addr = nla_get_hwaddr(
  349. info->attrs[IEEE802154_ATTR_DEST_HW_ADDR]);
  350. addr.pan_id = ieee802154_mlme_ops(dev)->get_pan_id(dev);
  351. ret = ieee802154_mlme_ops(dev)->assoc_resp(dev, &addr,
  352. nla_get_shortaddr(info->attrs[IEEE802154_ATTR_DEST_SHORT_ADDR]),
  353. nla_get_u8(info->attrs[IEEE802154_ATTR_STATUS]));
  354. out:
  355. dev_put(dev);
  356. return ret;
  357. }
  358. int ieee802154_disassociate_req(struct sk_buff *skb, struct genl_info *info)
  359. {
  360. struct net_device *dev;
  361. struct ieee802154_addr addr;
  362. int ret = -EOPNOTSUPP;
  363. if ((!info->attrs[IEEE802154_ATTR_DEST_HW_ADDR] &&
  364. !info->attrs[IEEE802154_ATTR_DEST_SHORT_ADDR]) ||
  365. !info->attrs[IEEE802154_ATTR_REASON])
  366. return -EINVAL;
  367. dev = ieee802154_nl_get_dev(info);
  368. if (!dev)
  369. return -ENODEV;
  370. if (!ieee802154_mlme_ops(dev)->disassoc_req)
  371. goto out;
  372. if (info->attrs[IEEE802154_ATTR_DEST_HW_ADDR]) {
  373. addr.mode = IEEE802154_ADDR_LONG;
  374. addr.extended_addr = nla_get_hwaddr(
  375. info->attrs[IEEE802154_ATTR_DEST_HW_ADDR]);
  376. } else {
  377. addr.mode = IEEE802154_ADDR_SHORT;
  378. addr.short_addr = nla_get_shortaddr(
  379. info->attrs[IEEE802154_ATTR_DEST_SHORT_ADDR]);
  380. }
  381. addr.pan_id = ieee802154_mlme_ops(dev)->get_pan_id(dev);
  382. ret = ieee802154_mlme_ops(dev)->disassoc_req(dev, &addr,
  383. nla_get_u8(info->attrs[IEEE802154_ATTR_REASON]));
  384. out:
  385. dev_put(dev);
  386. return ret;
  387. }
  388. /* PANid, channel, beacon_order = 15, superframe_order = 15,
  389. * PAN_coordinator, battery_life_extension = 0,
  390. * coord_realignment = 0, security_enable = 0
  391. */
  392. int ieee802154_start_req(struct sk_buff *skb, struct genl_info *info)
  393. {
  394. struct net_device *dev;
  395. struct ieee802154_addr addr;
  396. u8 channel, bcn_ord, sf_ord;
  397. u8 page;
  398. int pan_coord, blx, coord_realign;
  399. int ret = -EBUSY;
  400. if (!info->attrs[IEEE802154_ATTR_COORD_PAN_ID] ||
  401. !info->attrs[IEEE802154_ATTR_COORD_SHORT_ADDR] ||
  402. !info->attrs[IEEE802154_ATTR_CHANNEL] ||
  403. !info->attrs[IEEE802154_ATTR_BCN_ORD] ||
  404. !info->attrs[IEEE802154_ATTR_SF_ORD] ||
  405. !info->attrs[IEEE802154_ATTR_PAN_COORD] ||
  406. !info->attrs[IEEE802154_ATTR_BAT_EXT] ||
  407. !info->attrs[IEEE802154_ATTR_COORD_REALIGN]
  408. )
  409. return -EINVAL;
  410. dev = ieee802154_nl_get_dev(info);
  411. if (!dev)
  412. return -ENODEV;
  413. if (netif_running(dev))
  414. goto out;
  415. if (!ieee802154_mlme_ops(dev)->start_req) {
  416. ret = -EOPNOTSUPP;
  417. goto out;
  418. }
  419. addr.mode = IEEE802154_ADDR_SHORT;
  420. addr.short_addr = nla_get_shortaddr(
  421. info->attrs[IEEE802154_ATTR_COORD_SHORT_ADDR]);
  422. addr.pan_id = nla_get_shortaddr(
  423. info->attrs[IEEE802154_ATTR_COORD_PAN_ID]);
  424. channel = nla_get_u8(info->attrs[IEEE802154_ATTR_CHANNEL]);
  425. bcn_ord = nla_get_u8(info->attrs[IEEE802154_ATTR_BCN_ORD]);
  426. sf_ord = nla_get_u8(info->attrs[IEEE802154_ATTR_SF_ORD]);
  427. pan_coord = nla_get_u8(info->attrs[IEEE802154_ATTR_PAN_COORD]);
  428. blx = nla_get_u8(info->attrs[IEEE802154_ATTR_BAT_EXT]);
  429. coord_realign = nla_get_u8(info->attrs[IEEE802154_ATTR_COORD_REALIGN]);
  430. if (info->attrs[IEEE802154_ATTR_PAGE])
  431. page = nla_get_u8(info->attrs[IEEE802154_ATTR_PAGE]);
  432. else
  433. page = 0;
  434. if (addr.short_addr == cpu_to_le16(IEEE802154_ADDR_BROADCAST)) {
  435. ieee802154_nl_start_confirm(dev, IEEE802154_NO_SHORT_ADDRESS);
  436. dev_put(dev);
  437. return -EINVAL;
  438. }
  439. ret = ieee802154_mlme_ops(dev)->start_req(dev, &addr, channel, page,
  440. bcn_ord, sf_ord, pan_coord, blx, coord_realign);
  441. out:
  442. dev_put(dev);
  443. return ret;
  444. }
  445. int ieee802154_scan_req(struct sk_buff *skb, struct genl_info *info)
  446. {
  447. struct net_device *dev;
  448. int ret = -EOPNOTSUPP;
  449. u8 type;
  450. u32 channels;
  451. u8 duration;
  452. u8 page;
  453. if (!info->attrs[IEEE802154_ATTR_SCAN_TYPE] ||
  454. !info->attrs[IEEE802154_ATTR_CHANNELS] ||
  455. !info->attrs[IEEE802154_ATTR_DURATION])
  456. return -EINVAL;
  457. dev = ieee802154_nl_get_dev(info);
  458. if (!dev)
  459. return -ENODEV;
  460. if (!ieee802154_mlme_ops(dev)->scan_req)
  461. goto out;
  462. type = nla_get_u8(info->attrs[IEEE802154_ATTR_SCAN_TYPE]);
  463. channels = nla_get_u32(info->attrs[IEEE802154_ATTR_CHANNELS]);
  464. duration = nla_get_u8(info->attrs[IEEE802154_ATTR_DURATION]);
  465. if (info->attrs[IEEE802154_ATTR_PAGE])
  466. page = nla_get_u8(info->attrs[IEEE802154_ATTR_PAGE]);
  467. else
  468. page = 0;
  469. ret = ieee802154_mlme_ops(dev)->scan_req(dev, type, channels,
  470. page, duration);
  471. out:
  472. dev_put(dev);
  473. return ret;
  474. }
  475. int ieee802154_list_iface(struct sk_buff *skb, struct genl_info *info)
  476. {
  477. /* Request for interface name, index, type, IEEE address,
  478. * PAN Id, short address
  479. */
  480. struct sk_buff *msg;
  481. struct net_device *dev = NULL;
  482. int rc = -ENOBUFS;
  483. pr_debug("%s\n", __func__);
  484. dev = ieee802154_nl_get_dev(info);
  485. if (!dev)
  486. return -ENODEV;
  487. msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
  488. if (!msg)
  489. goto out_dev;
  490. rc = ieee802154_nl_fill_iface(msg, info->snd_portid, info->snd_seq,
  491. 0, dev);
  492. if (rc < 0)
  493. goto out_free;
  494. dev_put(dev);
  495. return genlmsg_reply(msg, info);
  496. out_free:
  497. nlmsg_free(msg);
  498. out_dev:
  499. dev_put(dev);
  500. return rc;
  501. }
  502. int ieee802154_dump_iface(struct sk_buff *skb, struct netlink_callback *cb)
  503. {
  504. struct net *net = sock_net(skb->sk);
  505. struct net_device *dev;
  506. int idx;
  507. int s_idx = cb->args[0];
  508. pr_debug("%s\n", __func__);
  509. idx = 0;
  510. for_each_netdev(net, dev) {
  511. if (idx < s_idx || (dev->type != ARPHRD_IEEE802154))
  512. goto cont;
  513. if (ieee802154_nl_fill_iface(skb, NETLINK_CB(cb->skb).portid,
  514. cb->nlh->nlmsg_seq,
  515. NLM_F_MULTI, dev) < 0)
  516. break;
  517. cont:
  518. idx++;
  519. }
  520. cb->args[0] = idx;
  521. return skb->len;
  522. }
  523. int ieee802154_set_macparams(struct sk_buff *skb, struct genl_info *info)
  524. {
  525. struct net_device *dev = NULL;
  526. struct ieee802154_mlme_ops *ops;
  527. struct ieee802154_mac_params params;
  528. struct wpan_phy *phy;
  529. int rc = -EINVAL;
  530. pr_debug("%s\n", __func__);
  531. dev = ieee802154_nl_get_dev(info);
  532. if (!dev)
  533. return -ENODEV;
  534. ops = ieee802154_mlme_ops(dev);
  535. if (!ops->get_mac_params || !ops->set_mac_params) {
  536. rc = -EOPNOTSUPP;
  537. goto out;
  538. }
  539. if (netif_running(dev)) {
  540. rc = -EBUSY;
  541. goto out;
  542. }
  543. if (!info->attrs[IEEE802154_ATTR_LBT_ENABLED] &&
  544. !info->attrs[IEEE802154_ATTR_CCA_MODE] &&
  545. !info->attrs[IEEE802154_ATTR_CCA_ED_LEVEL] &&
  546. !info->attrs[IEEE802154_ATTR_CSMA_RETRIES] &&
  547. !info->attrs[IEEE802154_ATTR_CSMA_MIN_BE] &&
  548. !info->attrs[IEEE802154_ATTR_CSMA_MAX_BE] &&
  549. !info->attrs[IEEE802154_ATTR_FRAME_RETRIES])
  550. goto out;
  551. phy = ops->get_phy(dev);
  552. ops->get_mac_params(dev, &params);
  553. if (info->attrs[IEEE802154_ATTR_TXPOWER])
  554. params.transmit_power = nla_get_s8(info->attrs[IEEE802154_ATTR_TXPOWER]);
  555. if (info->attrs[IEEE802154_ATTR_LBT_ENABLED])
  556. params.lbt = nla_get_u8(info->attrs[IEEE802154_ATTR_LBT_ENABLED]);
  557. if (info->attrs[IEEE802154_ATTR_CCA_MODE])
  558. params.cca_mode = nla_get_u8(info->attrs[IEEE802154_ATTR_CCA_MODE]);
  559. if (info->attrs[IEEE802154_ATTR_CCA_ED_LEVEL])
  560. params.cca_ed_level = nla_get_s32(info->attrs[IEEE802154_ATTR_CCA_ED_LEVEL]);
  561. if (info->attrs[IEEE802154_ATTR_CSMA_RETRIES])
  562. params.csma_retries = nla_get_u8(info->attrs[IEEE802154_ATTR_CSMA_RETRIES]);
  563. if (info->attrs[IEEE802154_ATTR_CSMA_MIN_BE])
  564. params.min_be = nla_get_u8(info->attrs[IEEE802154_ATTR_CSMA_MIN_BE]);
  565. if (info->attrs[IEEE802154_ATTR_CSMA_MAX_BE])
  566. params.max_be = nla_get_u8(info->attrs[IEEE802154_ATTR_CSMA_MAX_BE]);
  567. if (info->attrs[IEEE802154_ATTR_FRAME_RETRIES])
  568. params.frame_retries = nla_get_s8(info->attrs[IEEE802154_ATTR_FRAME_RETRIES]);
  569. rc = ops->set_mac_params(dev, &params);
  570. wpan_phy_put(phy);
  571. dev_put(dev);
  572. return 0;
  573. out:
  574. dev_put(dev);
  575. return rc;
  576. }
  577. static int
  578. ieee802154_llsec_parse_key_id(struct genl_info *info,
  579. struct ieee802154_llsec_key_id *desc)
  580. {
  581. memset(desc, 0, sizeof(*desc));
  582. if (!info->attrs[IEEE802154_ATTR_LLSEC_KEY_MODE])
  583. return -EINVAL;
  584. desc->mode = nla_get_u8(info->attrs[IEEE802154_ATTR_LLSEC_KEY_MODE]);
  585. if (desc->mode == IEEE802154_SCF_KEY_IMPLICIT) {
  586. if (!info->attrs[IEEE802154_ATTR_PAN_ID] &&
  587. !(info->attrs[IEEE802154_ATTR_SHORT_ADDR] ||
  588. info->attrs[IEEE802154_ATTR_HW_ADDR]))
  589. return -EINVAL;
  590. desc->device_addr.pan_id = nla_get_shortaddr(info->attrs[IEEE802154_ATTR_PAN_ID]);
  591. if (info->attrs[IEEE802154_ATTR_SHORT_ADDR]) {
  592. desc->device_addr.mode = IEEE802154_ADDR_SHORT;
  593. desc->device_addr.short_addr = nla_get_shortaddr(info->attrs[IEEE802154_ATTR_SHORT_ADDR]);
  594. } else {
  595. desc->device_addr.mode = IEEE802154_ADDR_LONG;
  596. desc->device_addr.extended_addr = nla_get_hwaddr(info->attrs[IEEE802154_ATTR_HW_ADDR]);
  597. }
  598. }
  599. if (desc->mode != IEEE802154_SCF_KEY_IMPLICIT &&
  600. !info->attrs[IEEE802154_ATTR_LLSEC_KEY_ID])
  601. return -EINVAL;
  602. if (desc->mode == IEEE802154_SCF_KEY_SHORT_INDEX &&
  603. !info->attrs[IEEE802154_ATTR_LLSEC_KEY_SOURCE_SHORT])
  604. return -EINVAL;
  605. if (desc->mode == IEEE802154_SCF_KEY_HW_INDEX &&
  606. !info->attrs[IEEE802154_ATTR_LLSEC_KEY_SOURCE_EXTENDED])
  607. return -EINVAL;
  608. if (desc->mode != IEEE802154_SCF_KEY_IMPLICIT)
  609. desc->id = nla_get_u8(info->attrs[IEEE802154_ATTR_LLSEC_KEY_ID]);
  610. switch (desc->mode) {
  611. case IEEE802154_SCF_KEY_SHORT_INDEX:
  612. {
  613. u32 source = nla_get_u32(info->attrs[IEEE802154_ATTR_LLSEC_KEY_SOURCE_SHORT]);
  614. desc->short_source = cpu_to_le32(source);
  615. break;
  616. }
  617. case IEEE802154_SCF_KEY_HW_INDEX:
  618. desc->extended_source = nla_get_hwaddr(info->attrs[IEEE802154_ATTR_LLSEC_KEY_SOURCE_EXTENDED]);
  619. break;
  620. }
  621. return 0;
  622. }
  623. static int
  624. ieee802154_llsec_fill_key_id(struct sk_buff *msg,
  625. const struct ieee802154_llsec_key_id *desc)
  626. {
  627. if (nla_put_u8(msg, IEEE802154_ATTR_LLSEC_KEY_MODE, desc->mode))
  628. return -EMSGSIZE;
  629. if (desc->mode == IEEE802154_SCF_KEY_IMPLICIT) {
  630. if (nla_put_shortaddr(msg, IEEE802154_ATTR_PAN_ID,
  631. desc->device_addr.pan_id))
  632. return -EMSGSIZE;
  633. if (desc->device_addr.mode == IEEE802154_ADDR_SHORT &&
  634. nla_put_shortaddr(msg, IEEE802154_ATTR_SHORT_ADDR,
  635. desc->device_addr.short_addr))
  636. return -EMSGSIZE;
  637. if (desc->device_addr.mode == IEEE802154_ADDR_LONG &&
  638. nla_put_hwaddr(msg, IEEE802154_ATTR_HW_ADDR,
  639. desc->device_addr.extended_addr))
  640. return -EMSGSIZE;
  641. }
  642. if (desc->mode != IEEE802154_SCF_KEY_IMPLICIT &&
  643. nla_put_u8(msg, IEEE802154_ATTR_LLSEC_KEY_ID, desc->id))
  644. return -EMSGSIZE;
  645. if (desc->mode == IEEE802154_SCF_KEY_SHORT_INDEX &&
  646. nla_put_u32(msg, IEEE802154_ATTR_LLSEC_KEY_SOURCE_SHORT,
  647. le32_to_cpu(desc->short_source)))
  648. return -EMSGSIZE;
  649. if (desc->mode == IEEE802154_SCF_KEY_HW_INDEX &&
  650. nla_put_hwaddr(msg, IEEE802154_ATTR_LLSEC_KEY_SOURCE_EXTENDED,
  651. desc->extended_source))
  652. return -EMSGSIZE;
  653. return 0;
  654. }
  655. int ieee802154_llsec_getparams(struct sk_buff *skb, struct genl_info *info)
  656. {
  657. struct sk_buff *msg;
  658. struct net_device *dev = NULL;
  659. int rc = -ENOBUFS;
  660. struct ieee802154_mlme_ops *ops;
  661. void *hdr;
  662. struct ieee802154_llsec_params params;
  663. pr_debug("%s\n", __func__);
  664. dev = ieee802154_nl_get_dev(info);
  665. if (!dev)
  666. return -ENODEV;
  667. ops = ieee802154_mlme_ops(dev);
  668. if (!ops->llsec) {
  669. rc = -EOPNOTSUPP;
  670. goto out_dev;
  671. }
  672. msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
  673. if (!msg)
  674. goto out_dev;
  675. hdr = genlmsg_put(msg, 0, info->snd_seq, &nl802154_family, 0,
  676. IEEE802154_LLSEC_GETPARAMS);
  677. if (!hdr)
  678. goto out_free;
  679. rc = ops->llsec->get_params(dev, &params);
  680. if (rc < 0)
  681. goto out_free;
  682. if (nla_put_string(msg, IEEE802154_ATTR_DEV_NAME, dev->name) ||
  683. nla_put_u32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex) ||
  684. nla_put_u8(msg, IEEE802154_ATTR_LLSEC_ENABLED, params.enabled) ||
  685. nla_put_u8(msg, IEEE802154_ATTR_LLSEC_SECLEVEL, params.out_level) ||
  686. nla_put_u32(msg, IEEE802154_ATTR_LLSEC_FRAME_COUNTER,
  687. be32_to_cpu(params.frame_counter)) ||
  688. ieee802154_llsec_fill_key_id(msg, &params.out_key))
  689. goto out_free;
  690. dev_put(dev);
  691. return ieee802154_nl_reply(msg, info);
  692. out_free:
  693. nlmsg_free(msg);
  694. out_dev:
  695. dev_put(dev);
  696. return rc;
  697. }
  698. int ieee802154_llsec_setparams(struct sk_buff *skb, struct genl_info *info)
  699. {
  700. struct net_device *dev = NULL;
  701. int rc = -EINVAL;
  702. struct ieee802154_mlme_ops *ops;
  703. struct ieee802154_llsec_params params;
  704. int changed = 0;
  705. pr_debug("%s\n", __func__);
  706. dev = ieee802154_nl_get_dev(info);
  707. if (!dev)
  708. return -ENODEV;
  709. if (!info->attrs[IEEE802154_ATTR_LLSEC_ENABLED] &&
  710. !info->attrs[IEEE802154_ATTR_LLSEC_KEY_MODE] &&
  711. !info->attrs[IEEE802154_ATTR_LLSEC_SECLEVEL])
  712. goto out;
  713. ops = ieee802154_mlme_ops(dev);
  714. if (!ops->llsec) {
  715. rc = -EOPNOTSUPP;
  716. goto out;
  717. }
  718. if (info->attrs[IEEE802154_ATTR_LLSEC_SECLEVEL] &&
  719. nla_get_u8(info->attrs[IEEE802154_ATTR_LLSEC_SECLEVEL]) > 7)
  720. goto out;
  721. if (info->attrs[IEEE802154_ATTR_LLSEC_ENABLED]) {
  722. params.enabled = nla_get_u8(info->attrs[IEEE802154_ATTR_LLSEC_ENABLED]);
  723. changed |= IEEE802154_LLSEC_PARAM_ENABLED;
  724. }
  725. if (info->attrs[IEEE802154_ATTR_LLSEC_KEY_MODE]) {
  726. if (ieee802154_llsec_parse_key_id(info, &params.out_key))
  727. goto out;
  728. changed |= IEEE802154_LLSEC_PARAM_OUT_KEY;
  729. }
  730. if (info->attrs[IEEE802154_ATTR_LLSEC_SECLEVEL]) {
  731. params.out_level = nla_get_u8(info->attrs[IEEE802154_ATTR_LLSEC_SECLEVEL]);
  732. changed |= IEEE802154_LLSEC_PARAM_OUT_LEVEL;
  733. }
  734. if (info->attrs[IEEE802154_ATTR_LLSEC_FRAME_COUNTER]) {
  735. u32 fc = nla_get_u32(info->attrs[IEEE802154_ATTR_LLSEC_FRAME_COUNTER]);
  736. params.frame_counter = cpu_to_be32(fc);
  737. changed |= IEEE802154_LLSEC_PARAM_FRAME_COUNTER;
  738. }
  739. rc = ops->llsec->set_params(dev, &params, changed);
  740. dev_put(dev);
  741. return rc;
  742. out:
  743. dev_put(dev);
  744. return rc;
  745. }
  746. struct llsec_dump_data {
  747. struct sk_buff *skb;
  748. int s_idx, s_idx2;
  749. int portid;
  750. int nlmsg_seq;
  751. struct net_device *dev;
  752. struct ieee802154_mlme_ops *ops;
  753. struct ieee802154_llsec_table *table;
  754. };
  755. static int
  756. ieee802154_llsec_dump_table(struct sk_buff *skb, struct netlink_callback *cb,
  757. int (*step)(struct llsec_dump_data *))
  758. {
  759. struct net *net = sock_net(skb->sk);
  760. struct net_device *dev;
  761. struct llsec_dump_data data;
  762. int idx = 0;
  763. int first_dev = cb->args[0];
  764. int rc;
  765. for_each_netdev(net, dev) {
  766. if (idx < first_dev || dev->type != ARPHRD_IEEE802154)
  767. goto skip;
  768. data.ops = ieee802154_mlme_ops(dev);
  769. if (!data.ops->llsec)
  770. goto skip;
  771. data.skb = skb;
  772. data.s_idx = cb->args[1];
  773. data.s_idx2 = cb->args[2];
  774. data.dev = dev;
  775. data.portid = NETLINK_CB(cb->skb).portid;
  776. data.nlmsg_seq = cb->nlh->nlmsg_seq;
  777. data.ops->llsec->lock_table(dev);
  778. data.ops->llsec->get_table(data.dev, &data.table);
  779. rc = step(&data);
  780. data.ops->llsec->unlock_table(dev);
  781. if (rc < 0)
  782. break;
  783. skip:
  784. idx++;
  785. }
  786. cb->args[0] = idx;
  787. return skb->len;
  788. }
  789. static int
  790. ieee802154_nl_llsec_change(struct sk_buff *skb, struct genl_info *info,
  791. int (*fn)(struct net_device*, struct genl_info*))
  792. {
  793. struct net_device *dev = NULL;
  794. int rc = -EINVAL;
  795. dev = ieee802154_nl_get_dev(info);
  796. if (!dev)
  797. return -ENODEV;
  798. if (!ieee802154_mlme_ops(dev)->llsec)
  799. rc = -EOPNOTSUPP;
  800. else
  801. rc = fn(dev, info);
  802. dev_put(dev);
  803. return rc;
  804. }
  805. static int
  806. ieee802154_llsec_parse_key(struct genl_info *info,
  807. struct ieee802154_llsec_key *key)
  808. {
  809. u8 frames;
  810. u32 commands[256 / 32];
  811. memset(key, 0, sizeof(*key));
  812. if (!info->attrs[IEEE802154_ATTR_LLSEC_KEY_USAGE_FRAME_TYPES] ||
  813. !info->attrs[IEEE802154_ATTR_LLSEC_KEY_BYTES])
  814. return -EINVAL;
  815. frames = nla_get_u8(info->attrs[IEEE802154_ATTR_LLSEC_KEY_USAGE_FRAME_TYPES]);
  816. if ((frames & BIT(IEEE802154_FC_TYPE_MAC_CMD)) &&
  817. !info->attrs[IEEE802154_ATTR_LLSEC_KEY_USAGE_COMMANDS])
  818. return -EINVAL;
  819. if (info->attrs[IEEE802154_ATTR_LLSEC_KEY_USAGE_COMMANDS]) {
  820. nla_memcpy(commands,
  821. info->attrs[IEEE802154_ATTR_LLSEC_KEY_USAGE_COMMANDS],
  822. 256 / 8);
  823. if (commands[0] || commands[1] || commands[2] || commands[3] ||
  824. commands[4] || commands[5] || commands[6] ||
  825. commands[7] >= BIT(IEEE802154_CMD_GTS_REQ + 1))
  826. return -EINVAL;
  827. key->cmd_frame_ids = commands[7];
  828. }
  829. key->frame_types = frames;
  830. nla_memcpy(key->key, info->attrs[IEEE802154_ATTR_LLSEC_KEY_BYTES],
  831. IEEE802154_LLSEC_KEY_SIZE);
  832. return 0;
  833. }
  834. static int llsec_add_key(struct net_device *dev, struct genl_info *info)
  835. {
  836. struct ieee802154_mlme_ops *ops = ieee802154_mlme_ops(dev);
  837. struct ieee802154_llsec_key key;
  838. struct ieee802154_llsec_key_id id;
  839. if (ieee802154_llsec_parse_key(info, &key) ||
  840. ieee802154_llsec_parse_key_id(info, &id))
  841. return -EINVAL;
  842. return ops->llsec->add_key(dev, &id, &key);
  843. }
  844. int ieee802154_llsec_add_key(struct sk_buff *skb, struct genl_info *info)
  845. {
  846. if ((info->nlhdr->nlmsg_flags & (NLM_F_CREATE | NLM_F_EXCL)) !=
  847. (NLM_F_CREATE | NLM_F_EXCL))
  848. return -EINVAL;
  849. return ieee802154_nl_llsec_change(skb, info, llsec_add_key);
  850. }
  851. static int llsec_remove_key(struct net_device *dev, struct genl_info *info)
  852. {
  853. struct ieee802154_mlme_ops *ops = ieee802154_mlme_ops(dev);
  854. struct ieee802154_llsec_key_id id;
  855. if (ieee802154_llsec_parse_key_id(info, &id))
  856. return -EINVAL;
  857. return ops->llsec->del_key(dev, &id);
  858. }
  859. int ieee802154_llsec_del_key(struct sk_buff *skb, struct genl_info *info)
  860. {
  861. return ieee802154_nl_llsec_change(skb, info, llsec_remove_key);
  862. }
  863. static int
  864. ieee802154_nl_fill_key(struct sk_buff *msg, u32 portid, u32 seq,
  865. const struct ieee802154_llsec_key_entry *key,
  866. const struct net_device *dev)
  867. {
  868. void *hdr;
  869. u32 commands[256 / 32];
  870. hdr = genlmsg_put(msg, 0, seq, &nl802154_family, NLM_F_MULTI,
  871. IEEE802154_LLSEC_LIST_KEY);
  872. if (!hdr)
  873. goto out;
  874. if (nla_put_string(msg, IEEE802154_ATTR_DEV_NAME, dev->name) ||
  875. nla_put_u32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex) ||
  876. ieee802154_llsec_fill_key_id(msg, &key->id) ||
  877. nla_put_u8(msg, IEEE802154_ATTR_LLSEC_KEY_USAGE_FRAME_TYPES,
  878. key->key->frame_types))
  879. goto nla_put_failure;
  880. if (key->key->frame_types & BIT(IEEE802154_FC_TYPE_MAC_CMD)) {
  881. memset(commands, 0, sizeof(commands));
  882. commands[7] = key->key->cmd_frame_ids;
  883. if (nla_put(msg, IEEE802154_ATTR_LLSEC_KEY_USAGE_COMMANDS,
  884. sizeof(commands), commands))
  885. goto nla_put_failure;
  886. }
  887. if (nla_put(msg, IEEE802154_ATTR_LLSEC_KEY_BYTES,
  888. IEEE802154_LLSEC_KEY_SIZE, key->key->key))
  889. goto nla_put_failure;
  890. genlmsg_end(msg, hdr);
  891. return 0;
  892. nla_put_failure:
  893. genlmsg_cancel(msg, hdr);
  894. out:
  895. return -EMSGSIZE;
  896. }
  897. static int llsec_iter_keys(struct llsec_dump_data *data)
  898. {
  899. struct ieee802154_llsec_key_entry *pos;
  900. int rc = 0, idx = 0;
  901. list_for_each_entry(pos, &data->table->keys, list) {
  902. if (idx++ < data->s_idx)
  903. continue;
  904. if (ieee802154_nl_fill_key(data->skb, data->portid,
  905. data->nlmsg_seq, pos, data->dev)) {
  906. rc = -EMSGSIZE;
  907. break;
  908. }
  909. data->s_idx++;
  910. }
  911. return rc;
  912. }
  913. int ieee802154_llsec_dump_keys(struct sk_buff *skb, struct netlink_callback *cb)
  914. {
  915. return ieee802154_llsec_dump_table(skb, cb, llsec_iter_keys);
  916. }
  917. static int
  918. llsec_parse_dev(struct genl_info *info,
  919. struct ieee802154_llsec_device *dev)
  920. {
  921. memset(dev, 0, sizeof(*dev));
  922. if (!info->attrs[IEEE802154_ATTR_LLSEC_FRAME_COUNTER] ||
  923. !info->attrs[IEEE802154_ATTR_HW_ADDR] ||
  924. !info->attrs[IEEE802154_ATTR_LLSEC_DEV_OVERRIDE] ||
  925. !info->attrs[IEEE802154_ATTR_LLSEC_DEV_KEY_MODE] ||
  926. (!!info->attrs[IEEE802154_ATTR_PAN_ID] !=
  927. !!info->attrs[IEEE802154_ATTR_SHORT_ADDR]))
  928. return -EINVAL;
  929. if (info->attrs[IEEE802154_ATTR_PAN_ID]) {
  930. dev->pan_id = nla_get_shortaddr(info->attrs[IEEE802154_ATTR_PAN_ID]);
  931. dev->short_addr = nla_get_shortaddr(info->attrs[IEEE802154_ATTR_SHORT_ADDR]);
  932. } else {
  933. dev->short_addr = cpu_to_le16(IEEE802154_ADDR_UNDEF);
  934. }
  935. dev->hwaddr = nla_get_hwaddr(info->attrs[IEEE802154_ATTR_HW_ADDR]);
  936. dev->frame_counter = nla_get_u32(info->attrs[IEEE802154_ATTR_LLSEC_FRAME_COUNTER]);
  937. dev->seclevel_exempt = !!nla_get_u8(info->attrs[IEEE802154_ATTR_LLSEC_DEV_OVERRIDE]);
  938. dev->key_mode = nla_get_u8(info->attrs[IEEE802154_ATTR_LLSEC_DEV_KEY_MODE]);
  939. if (dev->key_mode >= __IEEE802154_LLSEC_DEVKEY_MAX)
  940. return -EINVAL;
  941. return 0;
  942. }
  943. static int llsec_add_dev(struct net_device *dev, struct genl_info *info)
  944. {
  945. struct ieee802154_mlme_ops *ops = ieee802154_mlme_ops(dev);
  946. struct ieee802154_llsec_device desc;
  947. if (llsec_parse_dev(info, &desc))
  948. return -EINVAL;
  949. return ops->llsec->add_dev(dev, &desc);
  950. }
  951. int ieee802154_llsec_add_dev(struct sk_buff *skb, struct genl_info *info)
  952. {
  953. if ((info->nlhdr->nlmsg_flags & (NLM_F_CREATE | NLM_F_EXCL)) !=
  954. (NLM_F_CREATE | NLM_F_EXCL))
  955. return -EINVAL;
  956. return ieee802154_nl_llsec_change(skb, info, llsec_add_dev);
  957. }
  958. static int llsec_del_dev(struct net_device *dev, struct genl_info *info)
  959. {
  960. struct ieee802154_mlme_ops *ops = ieee802154_mlme_ops(dev);
  961. __le64 devaddr;
  962. if (!info->attrs[IEEE802154_ATTR_HW_ADDR])
  963. return -EINVAL;
  964. devaddr = nla_get_hwaddr(info->attrs[IEEE802154_ATTR_HW_ADDR]);
  965. return ops->llsec->del_dev(dev, devaddr);
  966. }
  967. int ieee802154_llsec_del_dev(struct sk_buff *skb, struct genl_info *info)
  968. {
  969. return ieee802154_nl_llsec_change(skb, info, llsec_del_dev);
  970. }
  971. static int
  972. ieee802154_nl_fill_dev(struct sk_buff *msg, u32 portid, u32 seq,
  973. const struct ieee802154_llsec_device *desc,
  974. const struct net_device *dev)
  975. {
  976. void *hdr;
  977. hdr = genlmsg_put(msg, 0, seq, &nl802154_family, NLM_F_MULTI,
  978. IEEE802154_LLSEC_LIST_DEV);
  979. if (!hdr)
  980. goto out;
  981. if (nla_put_string(msg, IEEE802154_ATTR_DEV_NAME, dev->name) ||
  982. nla_put_u32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex) ||
  983. nla_put_shortaddr(msg, IEEE802154_ATTR_PAN_ID, desc->pan_id) ||
  984. nla_put_shortaddr(msg, IEEE802154_ATTR_SHORT_ADDR,
  985. desc->short_addr) ||
  986. nla_put_hwaddr(msg, IEEE802154_ATTR_HW_ADDR, desc->hwaddr) ||
  987. nla_put_u32(msg, IEEE802154_ATTR_LLSEC_FRAME_COUNTER,
  988. desc->frame_counter) ||
  989. nla_put_u8(msg, IEEE802154_ATTR_LLSEC_DEV_OVERRIDE,
  990. desc->seclevel_exempt) ||
  991. nla_put_u8(msg, IEEE802154_ATTR_LLSEC_DEV_KEY_MODE, desc->key_mode))
  992. goto nla_put_failure;
  993. genlmsg_end(msg, hdr);
  994. return 0;
  995. nla_put_failure:
  996. genlmsg_cancel(msg, hdr);
  997. out:
  998. return -EMSGSIZE;
  999. }
  1000. static int llsec_iter_devs(struct llsec_dump_data *data)
  1001. {
  1002. struct ieee802154_llsec_device *pos;
  1003. int rc = 0, idx = 0;
  1004. list_for_each_entry(pos, &data->table->devices, list) {
  1005. if (idx++ < data->s_idx)
  1006. continue;
  1007. if (ieee802154_nl_fill_dev(data->skb, data->portid,
  1008. data->nlmsg_seq, pos, data->dev)) {
  1009. rc = -EMSGSIZE;
  1010. break;
  1011. }
  1012. data->s_idx++;
  1013. }
  1014. return rc;
  1015. }
  1016. int ieee802154_llsec_dump_devs(struct sk_buff *skb, struct netlink_callback *cb)
  1017. {
  1018. return ieee802154_llsec_dump_table(skb, cb, llsec_iter_devs);
  1019. }
  1020. static int llsec_add_devkey(struct net_device *dev, struct genl_info *info)
  1021. {
  1022. struct ieee802154_mlme_ops *ops = ieee802154_mlme_ops(dev);
  1023. struct ieee802154_llsec_device_key key;
  1024. __le64 devaddr;
  1025. if (!info->attrs[IEEE802154_ATTR_LLSEC_FRAME_COUNTER] ||
  1026. !info->attrs[IEEE802154_ATTR_HW_ADDR] ||
  1027. ieee802154_llsec_parse_key_id(info, &key.key_id))
  1028. return -EINVAL;
  1029. devaddr = nla_get_hwaddr(info->attrs[IEEE802154_ATTR_HW_ADDR]);
  1030. key.frame_counter = nla_get_u32(info->attrs[IEEE802154_ATTR_LLSEC_FRAME_COUNTER]);
  1031. return ops->llsec->add_devkey(dev, devaddr, &key);
  1032. }
  1033. int ieee802154_llsec_add_devkey(struct sk_buff *skb, struct genl_info *info)
  1034. {
  1035. if ((info->nlhdr->nlmsg_flags & (NLM_F_CREATE | NLM_F_EXCL)) !=
  1036. (NLM_F_CREATE | NLM_F_EXCL))
  1037. return -EINVAL;
  1038. return ieee802154_nl_llsec_change(skb, info, llsec_add_devkey);
  1039. }
  1040. static int llsec_del_devkey(struct net_device *dev, struct genl_info *info)
  1041. {
  1042. struct ieee802154_mlme_ops *ops = ieee802154_mlme_ops(dev);
  1043. struct ieee802154_llsec_device_key key;
  1044. __le64 devaddr;
  1045. if (!info->attrs[IEEE802154_ATTR_HW_ADDR] ||
  1046. ieee802154_llsec_parse_key_id(info, &key.key_id))
  1047. return -EINVAL;
  1048. devaddr = nla_get_hwaddr(info->attrs[IEEE802154_ATTR_HW_ADDR]);
  1049. return ops->llsec->del_devkey(dev, devaddr, &key);
  1050. }
  1051. int ieee802154_llsec_del_devkey(struct sk_buff *skb, struct genl_info *info)
  1052. {
  1053. return ieee802154_nl_llsec_change(skb, info, llsec_del_devkey);
  1054. }
  1055. static int
  1056. ieee802154_nl_fill_devkey(struct sk_buff *msg, u32 portid, u32 seq,
  1057. __le64 devaddr,
  1058. const struct ieee802154_llsec_device_key *devkey,
  1059. const struct net_device *dev)
  1060. {
  1061. void *hdr;
  1062. hdr = genlmsg_put(msg, 0, seq, &nl802154_family, NLM_F_MULTI,
  1063. IEEE802154_LLSEC_LIST_DEVKEY);
  1064. if (!hdr)
  1065. goto out;
  1066. if (nla_put_string(msg, IEEE802154_ATTR_DEV_NAME, dev->name) ||
  1067. nla_put_u32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex) ||
  1068. nla_put_hwaddr(msg, IEEE802154_ATTR_HW_ADDR, devaddr) ||
  1069. nla_put_u32(msg, IEEE802154_ATTR_LLSEC_FRAME_COUNTER,
  1070. devkey->frame_counter) ||
  1071. ieee802154_llsec_fill_key_id(msg, &devkey->key_id))
  1072. goto nla_put_failure;
  1073. genlmsg_end(msg, hdr);
  1074. return 0;
  1075. nla_put_failure:
  1076. genlmsg_cancel(msg, hdr);
  1077. out:
  1078. return -EMSGSIZE;
  1079. }
  1080. static int llsec_iter_devkeys(struct llsec_dump_data *data)
  1081. {
  1082. struct ieee802154_llsec_device *dpos;
  1083. struct ieee802154_llsec_device_key *kpos;
  1084. int rc = 0, idx = 0, idx2;
  1085. list_for_each_entry(dpos, &data->table->devices, list) {
  1086. if (idx++ < data->s_idx)
  1087. continue;
  1088. idx2 = 0;
  1089. list_for_each_entry(kpos, &dpos->keys, list) {
  1090. if (idx2++ < data->s_idx2)
  1091. continue;
  1092. if (ieee802154_nl_fill_devkey(data->skb, data->portid,
  1093. data->nlmsg_seq,
  1094. dpos->hwaddr, kpos,
  1095. data->dev)) {
  1096. return rc = -EMSGSIZE;
  1097. }
  1098. data->s_idx2++;
  1099. }
  1100. data->s_idx++;
  1101. }
  1102. return rc;
  1103. }
  1104. int ieee802154_llsec_dump_devkeys(struct sk_buff *skb,
  1105. struct netlink_callback *cb)
  1106. {
  1107. return ieee802154_llsec_dump_table(skb, cb, llsec_iter_devkeys);
  1108. }
  1109. static int
  1110. llsec_parse_seclevel(struct genl_info *info,
  1111. struct ieee802154_llsec_seclevel *sl)
  1112. {
  1113. memset(sl, 0, sizeof(*sl));
  1114. if (!info->attrs[IEEE802154_ATTR_LLSEC_FRAME_TYPE] ||
  1115. !info->attrs[IEEE802154_ATTR_LLSEC_SECLEVELS] ||
  1116. !info->attrs[IEEE802154_ATTR_LLSEC_DEV_OVERRIDE])
  1117. return -EINVAL;
  1118. sl->frame_type = nla_get_u8(info->attrs[IEEE802154_ATTR_LLSEC_FRAME_TYPE]);
  1119. if (sl->frame_type == IEEE802154_FC_TYPE_MAC_CMD) {
  1120. if (!info->attrs[IEEE802154_ATTR_LLSEC_CMD_FRAME_ID])
  1121. return -EINVAL;
  1122. sl->cmd_frame_id = nla_get_u8(info->attrs[IEEE802154_ATTR_LLSEC_CMD_FRAME_ID]);
  1123. }
  1124. sl->sec_levels = nla_get_u8(info->attrs[IEEE802154_ATTR_LLSEC_SECLEVELS]);
  1125. sl->device_override = nla_get_u8(info->attrs[IEEE802154_ATTR_LLSEC_DEV_OVERRIDE]);
  1126. return 0;
  1127. }
  1128. static int llsec_add_seclevel(struct net_device *dev, struct genl_info *info)
  1129. {
  1130. struct ieee802154_mlme_ops *ops = ieee802154_mlme_ops(dev);
  1131. struct ieee802154_llsec_seclevel sl;
  1132. if (llsec_parse_seclevel(info, &sl))
  1133. return -EINVAL;
  1134. return ops->llsec->add_seclevel(dev, &sl);
  1135. }
  1136. int ieee802154_llsec_add_seclevel(struct sk_buff *skb, struct genl_info *info)
  1137. {
  1138. if ((info->nlhdr->nlmsg_flags & (NLM_F_CREATE | NLM_F_EXCL)) !=
  1139. (NLM_F_CREATE | NLM_F_EXCL))
  1140. return -EINVAL;
  1141. return ieee802154_nl_llsec_change(skb, info, llsec_add_seclevel);
  1142. }
  1143. static int llsec_del_seclevel(struct net_device *dev, struct genl_info *info)
  1144. {
  1145. struct ieee802154_mlme_ops *ops = ieee802154_mlme_ops(dev);
  1146. struct ieee802154_llsec_seclevel sl;
  1147. if (llsec_parse_seclevel(info, &sl))
  1148. return -EINVAL;
  1149. return ops->llsec->del_seclevel(dev, &sl);
  1150. }
  1151. int ieee802154_llsec_del_seclevel(struct sk_buff *skb, struct genl_info *info)
  1152. {
  1153. return ieee802154_nl_llsec_change(skb, info, llsec_del_seclevel);
  1154. }
  1155. static int
  1156. ieee802154_nl_fill_seclevel(struct sk_buff *msg, u32 portid, u32 seq,
  1157. const struct ieee802154_llsec_seclevel *sl,
  1158. const struct net_device *dev)
  1159. {
  1160. void *hdr;
  1161. hdr = genlmsg_put(msg, 0, seq, &nl802154_family, NLM_F_MULTI,
  1162. IEEE802154_LLSEC_LIST_SECLEVEL);
  1163. if (!hdr)
  1164. goto out;
  1165. if (nla_put_string(msg, IEEE802154_ATTR_DEV_NAME, dev->name) ||
  1166. nla_put_u32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex) ||
  1167. nla_put_u8(msg, IEEE802154_ATTR_LLSEC_FRAME_TYPE, sl->frame_type) ||
  1168. nla_put_u8(msg, IEEE802154_ATTR_LLSEC_SECLEVELS, sl->sec_levels) ||
  1169. nla_put_u8(msg, IEEE802154_ATTR_LLSEC_DEV_OVERRIDE,
  1170. sl->device_override))
  1171. goto nla_put_failure;
  1172. if (sl->frame_type == IEEE802154_FC_TYPE_MAC_CMD &&
  1173. nla_put_u8(msg, IEEE802154_ATTR_LLSEC_CMD_FRAME_ID,
  1174. sl->cmd_frame_id))
  1175. goto nla_put_failure;
  1176. genlmsg_end(msg, hdr);
  1177. return 0;
  1178. nla_put_failure:
  1179. genlmsg_cancel(msg, hdr);
  1180. out:
  1181. return -EMSGSIZE;
  1182. }
  1183. static int llsec_iter_seclevels(struct llsec_dump_data *data)
  1184. {
  1185. struct ieee802154_llsec_seclevel *pos;
  1186. int rc = 0, idx = 0;
  1187. list_for_each_entry(pos, &data->table->security_levels, list) {
  1188. if (idx++ < data->s_idx)
  1189. continue;
  1190. if (ieee802154_nl_fill_seclevel(data->skb, data->portid,
  1191. data->nlmsg_seq, pos,
  1192. data->dev)) {
  1193. rc = -EMSGSIZE;
  1194. break;
  1195. }
  1196. data->s_idx++;
  1197. }
  1198. return rc;
  1199. }
  1200. int ieee802154_llsec_dump_seclevels(struct sk_buff *skb,
  1201. struct netlink_callback *cb)
  1202. {
  1203. return ieee802154_llsec_dump_table(skb, cb, llsec_iter_seclevels);
  1204. }