nl802154.c 65 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431
  1. /* This program is free software; you can redistribute it and/or modify
  2. * it under the terms of the GNU General Public License version 2
  3. * as published by the Free Software Foundation.
  4. *
  5. * This program is distributed in the hope that it will be useful,
  6. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  7. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  8. * GNU General Public License for more details.
  9. *
  10. * Authors:
  11. * Alexander Aring <aar@pengutronix.de>
  12. *
  13. * Based on: net/wireless/nl80211.c
  14. */
  15. #include <linux/rtnetlink.h>
  16. #include <net/cfg802154.h>
  17. #include <net/genetlink.h>
  18. #include <net/mac802154.h>
  19. #include <net/netlink.h>
  20. #include <net/nl802154.h>
  21. #include <net/sock.h>
  22. #include "nl802154.h"
  23. #include "rdev-ops.h"
  24. #include "core.h"
  25. static int nl802154_pre_doit(const struct genl_ops *ops, struct sk_buff *skb,
  26. struct genl_info *info);
  27. static void nl802154_post_doit(const struct genl_ops *ops, struct sk_buff *skb,
  28. struct genl_info *info);
  29. /* the netlink family */
  30. static struct genl_family nl802154_fam = {
  31. .id = GENL_ID_GENERATE, /* don't bother with a hardcoded ID */
  32. .name = NL802154_GENL_NAME, /* have users key off the name instead */
  33. .hdrsize = 0, /* no private header */
  34. .version = 1, /* no particular meaning now */
  35. .maxattr = NL802154_ATTR_MAX,
  36. .netnsok = true,
  37. .pre_doit = nl802154_pre_doit,
  38. .post_doit = nl802154_post_doit,
  39. };
  40. /* multicast groups */
  41. enum nl802154_multicast_groups {
  42. NL802154_MCGRP_CONFIG,
  43. };
  44. static const struct genl_multicast_group nl802154_mcgrps[] = {
  45. [NL802154_MCGRP_CONFIG] = { .name = "config", },
  46. };
  47. /* returns ERR_PTR values */
  48. static struct wpan_dev *
  49. __cfg802154_wpan_dev_from_attrs(struct net *netns, struct nlattr **attrs)
  50. {
  51. struct cfg802154_registered_device *rdev;
  52. struct wpan_dev *result = NULL;
  53. bool have_ifidx = attrs[NL802154_ATTR_IFINDEX];
  54. bool have_wpan_dev_id = attrs[NL802154_ATTR_WPAN_DEV];
  55. u64 wpan_dev_id;
  56. int wpan_phy_idx = -1;
  57. int ifidx = -1;
  58. ASSERT_RTNL();
  59. if (!have_ifidx && !have_wpan_dev_id)
  60. return ERR_PTR(-EINVAL);
  61. if (have_ifidx)
  62. ifidx = nla_get_u32(attrs[NL802154_ATTR_IFINDEX]);
  63. if (have_wpan_dev_id) {
  64. wpan_dev_id = nla_get_u64(attrs[NL802154_ATTR_WPAN_DEV]);
  65. wpan_phy_idx = wpan_dev_id >> 32;
  66. }
  67. list_for_each_entry(rdev, &cfg802154_rdev_list, list) {
  68. struct wpan_dev *wpan_dev;
  69. /* TODO netns compare */
  70. if (have_wpan_dev_id && rdev->wpan_phy_idx != wpan_phy_idx)
  71. continue;
  72. list_for_each_entry(wpan_dev, &rdev->wpan_dev_list, list) {
  73. if (have_ifidx && wpan_dev->netdev &&
  74. wpan_dev->netdev->ifindex == ifidx) {
  75. result = wpan_dev;
  76. break;
  77. }
  78. if (have_wpan_dev_id &&
  79. wpan_dev->identifier == (u32)wpan_dev_id) {
  80. result = wpan_dev;
  81. break;
  82. }
  83. }
  84. if (result)
  85. break;
  86. }
  87. if (result)
  88. return result;
  89. return ERR_PTR(-ENODEV);
  90. }
  91. static struct cfg802154_registered_device *
  92. __cfg802154_rdev_from_attrs(struct net *netns, struct nlattr **attrs)
  93. {
  94. struct cfg802154_registered_device *rdev = NULL, *tmp;
  95. struct net_device *netdev;
  96. ASSERT_RTNL();
  97. if (!attrs[NL802154_ATTR_WPAN_PHY] &&
  98. !attrs[NL802154_ATTR_IFINDEX] &&
  99. !attrs[NL802154_ATTR_WPAN_DEV])
  100. return ERR_PTR(-EINVAL);
  101. if (attrs[NL802154_ATTR_WPAN_PHY])
  102. rdev = cfg802154_rdev_by_wpan_phy_idx(
  103. nla_get_u32(attrs[NL802154_ATTR_WPAN_PHY]));
  104. if (attrs[NL802154_ATTR_WPAN_DEV]) {
  105. u64 wpan_dev_id = nla_get_u64(attrs[NL802154_ATTR_WPAN_DEV]);
  106. struct wpan_dev *wpan_dev;
  107. bool found = false;
  108. tmp = cfg802154_rdev_by_wpan_phy_idx(wpan_dev_id >> 32);
  109. if (tmp) {
  110. /* make sure wpan_dev exists */
  111. list_for_each_entry(wpan_dev, &tmp->wpan_dev_list, list) {
  112. if (wpan_dev->identifier != (u32)wpan_dev_id)
  113. continue;
  114. found = true;
  115. break;
  116. }
  117. if (!found)
  118. tmp = NULL;
  119. if (rdev && tmp != rdev)
  120. return ERR_PTR(-EINVAL);
  121. rdev = tmp;
  122. }
  123. }
  124. if (attrs[NL802154_ATTR_IFINDEX]) {
  125. int ifindex = nla_get_u32(attrs[NL802154_ATTR_IFINDEX]);
  126. netdev = __dev_get_by_index(netns, ifindex);
  127. if (netdev) {
  128. if (netdev->ieee802154_ptr)
  129. tmp = wpan_phy_to_rdev(
  130. netdev->ieee802154_ptr->wpan_phy);
  131. else
  132. tmp = NULL;
  133. /* not wireless device -- return error */
  134. if (!tmp)
  135. return ERR_PTR(-EINVAL);
  136. /* mismatch -- return error */
  137. if (rdev && tmp != rdev)
  138. return ERR_PTR(-EINVAL);
  139. rdev = tmp;
  140. }
  141. }
  142. if (!rdev)
  143. return ERR_PTR(-ENODEV);
  144. /* TODO netns compare */
  145. return rdev;
  146. }
  147. /* This function returns a pointer to the driver
  148. * that the genl_info item that is passed refers to.
  149. *
  150. * The result of this can be a PTR_ERR and hence must
  151. * be checked with IS_ERR() for errors.
  152. */
  153. static struct cfg802154_registered_device *
  154. cfg802154_get_dev_from_info(struct net *netns, struct genl_info *info)
  155. {
  156. return __cfg802154_rdev_from_attrs(netns, info->attrs);
  157. }
  158. /* policy for the attributes */
  159. static const struct nla_policy nl802154_policy[NL802154_ATTR_MAX+1] = {
  160. [NL802154_ATTR_WPAN_PHY] = { .type = NLA_U32 },
  161. [NL802154_ATTR_WPAN_PHY_NAME] = { .type = NLA_NUL_STRING,
  162. .len = 20-1 },
  163. [NL802154_ATTR_IFINDEX] = { .type = NLA_U32 },
  164. [NL802154_ATTR_IFTYPE] = { .type = NLA_U32 },
  165. [NL802154_ATTR_IFNAME] = { .type = NLA_NUL_STRING, .len = IFNAMSIZ-1 },
  166. [NL802154_ATTR_WPAN_DEV] = { .type = NLA_U64 },
  167. [NL802154_ATTR_PAGE] = { .type = NLA_U8, },
  168. [NL802154_ATTR_CHANNEL] = { .type = NLA_U8, },
  169. [NL802154_ATTR_TX_POWER] = { .type = NLA_S32, },
  170. [NL802154_ATTR_CCA_MODE] = { .type = NLA_U32, },
  171. [NL802154_ATTR_CCA_OPT] = { .type = NLA_U32, },
  172. [NL802154_ATTR_CCA_ED_LEVEL] = { .type = NLA_S32, },
  173. [NL802154_ATTR_SUPPORTED_CHANNEL] = { .type = NLA_U32, },
  174. [NL802154_ATTR_PAN_ID] = { .type = NLA_U16, },
  175. [NL802154_ATTR_EXTENDED_ADDR] = { .type = NLA_U64 },
  176. [NL802154_ATTR_SHORT_ADDR] = { .type = NLA_U16, },
  177. [NL802154_ATTR_MIN_BE] = { .type = NLA_U8, },
  178. [NL802154_ATTR_MAX_BE] = { .type = NLA_U8, },
  179. [NL802154_ATTR_MAX_CSMA_BACKOFFS] = { .type = NLA_U8, },
  180. [NL802154_ATTR_MAX_FRAME_RETRIES] = { .type = NLA_S8, },
  181. [NL802154_ATTR_LBT_MODE] = { .type = NLA_U8, },
  182. [NL802154_ATTR_WPAN_PHY_CAPS] = { .type = NLA_NESTED },
  183. [NL802154_ATTR_SUPPORTED_COMMANDS] = { .type = NLA_NESTED },
  184. [NL802154_ATTR_ACKREQ_DEFAULT] = { .type = NLA_U8 },
  185. #ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL
  186. [NL802154_ATTR_SEC_ENABLED] = { .type = NLA_U8, },
  187. [NL802154_ATTR_SEC_OUT_LEVEL] = { .type = NLA_U32, },
  188. [NL802154_ATTR_SEC_OUT_KEY_ID] = { .type = NLA_NESTED, },
  189. [NL802154_ATTR_SEC_FRAME_COUNTER] = { .type = NLA_U32 },
  190. [NL802154_ATTR_SEC_LEVEL] = { .type = NLA_NESTED },
  191. [NL802154_ATTR_SEC_DEVICE] = { .type = NLA_NESTED },
  192. [NL802154_ATTR_SEC_DEVKEY] = { .type = NLA_NESTED },
  193. [NL802154_ATTR_SEC_KEY] = { .type = NLA_NESTED },
  194. #endif /* CONFIG_IEEE802154_NL802154_EXPERIMENTAL */
  195. };
  196. #ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL
  197. static int
  198. nl802154_prepare_wpan_dev_dump(struct sk_buff *skb,
  199. struct netlink_callback *cb,
  200. struct cfg802154_registered_device **rdev,
  201. struct wpan_dev **wpan_dev)
  202. {
  203. int err;
  204. rtnl_lock();
  205. if (!cb->args[0]) {
  206. err = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl802154_fam.hdrsize,
  207. nl802154_fam.attrbuf, nl802154_fam.maxattr,
  208. nl802154_policy);
  209. if (err)
  210. goto out_unlock;
  211. *wpan_dev = __cfg802154_wpan_dev_from_attrs(sock_net(skb->sk),
  212. nl802154_fam.attrbuf);
  213. if (IS_ERR(*wpan_dev)) {
  214. err = PTR_ERR(*wpan_dev);
  215. goto out_unlock;
  216. }
  217. *rdev = wpan_phy_to_rdev((*wpan_dev)->wpan_phy);
  218. /* 0 is the first index - add 1 to parse only once */
  219. cb->args[0] = (*rdev)->wpan_phy_idx + 1;
  220. cb->args[1] = (*wpan_dev)->identifier;
  221. } else {
  222. /* subtract the 1 again here */
  223. struct wpan_phy *wpan_phy = wpan_phy_idx_to_wpan_phy(cb->args[0] - 1);
  224. struct wpan_dev *tmp;
  225. if (!wpan_phy) {
  226. err = -ENODEV;
  227. goto out_unlock;
  228. }
  229. *rdev = wpan_phy_to_rdev(wpan_phy);
  230. *wpan_dev = NULL;
  231. list_for_each_entry(tmp, &(*rdev)->wpan_dev_list, list) {
  232. if (tmp->identifier == cb->args[1]) {
  233. *wpan_dev = tmp;
  234. break;
  235. }
  236. }
  237. if (!*wpan_dev) {
  238. err = -ENODEV;
  239. goto out_unlock;
  240. }
  241. }
  242. return 0;
  243. out_unlock:
  244. rtnl_unlock();
  245. return err;
  246. }
  247. static void
  248. nl802154_finish_wpan_dev_dump(struct cfg802154_registered_device *rdev)
  249. {
  250. rtnl_unlock();
  251. }
  252. #endif /* CONFIG_IEEE802154_NL802154_EXPERIMENTAL */
  253. /* message building helper */
  254. static inline void *nl802154hdr_put(struct sk_buff *skb, u32 portid, u32 seq,
  255. int flags, u8 cmd)
  256. {
  257. /* since there is no private header just add the generic one */
  258. return genlmsg_put(skb, portid, seq, &nl802154_fam, flags, cmd);
  259. }
  260. static int
  261. nl802154_put_flags(struct sk_buff *msg, int attr, u32 mask)
  262. {
  263. struct nlattr *nl_flags = nla_nest_start(msg, attr);
  264. int i;
  265. if (!nl_flags)
  266. return -ENOBUFS;
  267. i = 0;
  268. while (mask) {
  269. if ((mask & 1) && nla_put_flag(msg, i))
  270. return -ENOBUFS;
  271. mask >>= 1;
  272. i++;
  273. }
  274. nla_nest_end(msg, nl_flags);
  275. return 0;
  276. }
  277. static int
  278. nl802154_send_wpan_phy_channels(struct cfg802154_registered_device *rdev,
  279. struct sk_buff *msg)
  280. {
  281. struct nlattr *nl_page;
  282. unsigned long page;
  283. nl_page = nla_nest_start(msg, NL802154_ATTR_CHANNELS_SUPPORTED);
  284. if (!nl_page)
  285. return -ENOBUFS;
  286. for (page = 0; page <= IEEE802154_MAX_PAGE; page++) {
  287. if (nla_put_u32(msg, NL802154_ATTR_SUPPORTED_CHANNEL,
  288. rdev->wpan_phy.supported.channels[page]))
  289. return -ENOBUFS;
  290. }
  291. nla_nest_end(msg, nl_page);
  292. return 0;
  293. }
  294. static int
  295. nl802154_put_capabilities(struct sk_buff *msg,
  296. struct cfg802154_registered_device *rdev)
  297. {
  298. const struct wpan_phy_supported *caps = &rdev->wpan_phy.supported;
  299. struct nlattr *nl_caps, *nl_channels;
  300. int i;
  301. nl_caps = nla_nest_start(msg, NL802154_ATTR_WPAN_PHY_CAPS);
  302. if (!nl_caps)
  303. return -ENOBUFS;
  304. nl_channels = nla_nest_start(msg, NL802154_CAP_ATTR_CHANNELS);
  305. if (!nl_channels)
  306. return -ENOBUFS;
  307. for (i = 0; i <= IEEE802154_MAX_PAGE; i++) {
  308. if (caps->channels[i]) {
  309. if (nl802154_put_flags(msg, i, caps->channels[i]))
  310. return -ENOBUFS;
  311. }
  312. }
  313. nla_nest_end(msg, nl_channels);
  314. if (rdev->wpan_phy.flags & WPAN_PHY_FLAG_CCA_ED_LEVEL) {
  315. struct nlattr *nl_ed_lvls;
  316. nl_ed_lvls = nla_nest_start(msg,
  317. NL802154_CAP_ATTR_CCA_ED_LEVELS);
  318. if (!nl_ed_lvls)
  319. return -ENOBUFS;
  320. for (i = 0; i < caps->cca_ed_levels_size; i++) {
  321. if (nla_put_s32(msg, i, caps->cca_ed_levels[i]))
  322. return -ENOBUFS;
  323. }
  324. nla_nest_end(msg, nl_ed_lvls);
  325. }
  326. if (rdev->wpan_phy.flags & WPAN_PHY_FLAG_TXPOWER) {
  327. struct nlattr *nl_tx_pwrs;
  328. nl_tx_pwrs = nla_nest_start(msg, NL802154_CAP_ATTR_TX_POWERS);
  329. if (!nl_tx_pwrs)
  330. return -ENOBUFS;
  331. for (i = 0; i < caps->tx_powers_size; i++) {
  332. if (nla_put_s32(msg, i, caps->tx_powers[i]))
  333. return -ENOBUFS;
  334. }
  335. nla_nest_end(msg, nl_tx_pwrs);
  336. }
  337. if (rdev->wpan_phy.flags & WPAN_PHY_FLAG_CCA_MODE) {
  338. if (nl802154_put_flags(msg, NL802154_CAP_ATTR_CCA_MODES,
  339. caps->cca_modes) ||
  340. nl802154_put_flags(msg, NL802154_CAP_ATTR_CCA_OPTS,
  341. caps->cca_opts))
  342. return -ENOBUFS;
  343. }
  344. if (nla_put_u8(msg, NL802154_CAP_ATTR_MIN_MINBE, caps->min_minbe) ||
  345. nla_put_u8(msg, NL802154_CAP_ATTR_MAX_MINBE, caps->max_minbe) ||
  346. nla_put_u8(msg, NL802154_CAP_ATTR_MIN_MAXBE, caps->min_maxbe) ||
  347. nla_put_u8(msg, NL802154_CAP_ATTR_MAX_MAXBE, caps->max_maxbe) ||
  348. nla_put_u8(msg, NL802154_CAP_ATTR_MIN_CSMA_BACKOFFS,
  349. caps->min_csma_backoffs) ||
  350. nla_put_u8(msg, NL802154_CAP_ATTR_MAX_CSMA_BACKOFFS,
  351. caps->max_csma_backoffs) ||
  352. nla_put_s8(msg, NL802154_CAP_ATTR_MIN_FRAME_RETRIES,
  353. caps->min_frame_retries) ||
  354. nla_put_s8(msg, NL802154_CAP_ATTR_MAX_FRAME_RETRIES,
  355. caps->max_frame_retries) ||
  356. nl802154_put_flags(msg, NL802154_CAP_ATTR_IFTYPES,
  357. caps->iftypes) ||
  358. nla_put_u32(msg, NL802154_CAP_ATTR_LBT, caps->lbt))
  359. return -ENOBUFS;
  360. nla_nest_end(msg, nl_caps);
  361. return 0;
  362. }
  363. static int nl802154_send_wpan_phy(struct cfg802154_registered_device *rdev,
  364. enum nl802154_commands cmd,
  365. struct sk_buff *msg, u32 portid, u32 seq,
  366. int flags)
  367. {
  368. struct nlattr *nl_cmds;
  369. void *hdr;
  370. int i;
  371. hdr = nl802154hdr_put(msg, portid, seq, flags, cmd);
  372. if (!hdr)
  373. return -ENOBUFS;
  374. if (nla_put_u32(msg, NL802154_ATTR_WPAN_PHY, rdev->wpan_phy_idx) ||
  375. nla_put_string(msg, NL802154_ATTR_WPAN_PHY_NAME,
  376. wpan_phy_name(&rdev->wpan_phy)) ||
  377. nla_put_u32(msg, NL802154_ATTR_GENERATION,
  378. cfg802154_rdev_list_generation))
  379. goto nla_put_failure;
  380. if (cmd != NL802154_CMD_NEW_WPAN_PHY)
  381. goto finish;
  382. /* DUMP PHY PIB */
  383. /* current channel settings */
  384. if (nla_put_u8(msg, NL802154_ATTR_PAGE,
  385. rdev->wpan_phy.current_page) ||
  386. nla_put_u8(msg, NL802154_ATTR_CHANNEL,
  387. rdev->wpan_phy.current_channel))
  388. goto nla_put_failure;
  389. /* TODO remove this behaviour, we still keep support it for a while
  390. * so users can change the behaviour to the new one.
  391. */
  392. if (nl802154_send_wpan_phy_channels(rdev, msg))
  393. goto nla_put_failure;
  394. /* cca mode */
  395. if (rdev->wpan_phy.flags & WPAN_PHY_FLAG_CCA_MODE) {
  396. if (nla_put_u32(msg, NL802154_ATTR_CCA_MODE,
  397. rdev->wpan_phy.cca.mode))
  398. goto nla_put_failure;
  399. if (rdev->wpan_phy.cca.mode == NL802154_CCA_ENERGY_CARRIER) {
  400. if (nla_put_u32(msg, NL802154_ATTR_CCA_OPT,
  401. rdev->wpan_phy.cca.opt))
  402. goto nla_put_failure;
  403. }
  404. }
  405. if (rdev->wpan_phy.flags & WPAN_PHY_FLAG_TXPOWER) {
  406. if (nla_put_s32(msg, NL802154_ATTR_TX_POWER,
  407. rdev->wpan_phy.transmit_power))
  408. goto nla_put_failure;
  409. }
  410. if (rdev->wpan_phy.flags & WPAN_PHY_FLAG_CCA_ED_LEVEL) {
  411. if (nla_put_s32(msg, NL802154_ATTR_CCA_ED_LEVEL,
  412. rdev->wpan_phy.cca_ed_level))
  413. goto nla_put_failure;
  414. }
  415. if (nl802154_put_capabilities(msg, rdev))
  416. goto nla_put_failure;
  417. nl_cmds = nla_nest_start(msg, NL802154_ATTR_SUPPORTED_COMMANDS);
  418. if (!nl_cmds)
  419. goto nla_put_failure;
  420. i = 0;
  421. #define CMD(op, n) \
  422. do { \
  423. if (rdev->ops->op) { \
  424. i++; \
  425. if (nla_put_u32(msg, i, NL802154_CMD_ ## n)) \
  426. goto nla_put_failure; \
  427. } \
  428. } while (0)
  429. CMD(add_virtual_intf, NEW_INTERFACE);
  430. CMD(del_virtual_intf, DEL_INTERFACE);
  431. CMD(set_channel, SET_CHANNEL);
  432. CMD(set_pan_id, SET_PAN_ID);
  433. CMD(set_short_addr, SET_SHORT_ADDR);
  434. CMD(set_backoff_exponent, SET_BACKOFF_EXPONENT);
  435. CMD(set_max_csma_backoffs, SET_MAX_CSMA_BACKOFFS);
  436. CMD(set_max_frame_retries, SET_MAX_FRAME_RETRIES);
  437. CMD(set_lbt_mode, SET_LBT_MODE);
  438. CMD(set_ackreq_default, SET_ACKREQ_DEFAULT);
  439. if (rdev->wpan_phy.flags & WPAN_PHY_FLAG_TXPOWER)
  440. CMD(set_tx_power, SET_TX_POWER);
  441. if (rdev->wpan_phy.flags & WPAN_PHY_FLAG_CCA_ED_LEVEL)
  442. CMD(set_cca_ed_level, SET_CCA_ED_LEVEL);
  443. if (rdev->wpan_phy.flags & WPAN_PHY_FLAG_CCA_MODE)
  444. CMD(set_cca_mode, SET_CCA_MODE);
  445. #undef CMD
  446. nla_nest_end(msg, nl_cmds);
  447. finish:
  448. genlmsg_end(msg, hdr);
  449. return 0;
  450. nla_put_failure:
  451. genlmsg_cancel(msg, hdr);
  452. return -EMSGSIZE;
  453. }
  454. struct nl802154_dump_wpan_phy_state {
  455. s64 filter_wpan_phy;
  456. long start;
  457. };
  458. static int nl802154_dump_wpan_phy_parse(struct sk_buff *skb,
  459. struct netlink_callback *cb,
  460. struct nl802154_dump_wpan_phy_state *state)
  461. {
  462. struct nlattr **tb = nl802154_fam.attrbuf;
  463. int ret = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl802154_fam.hdrsize,
  464. tb, nl802154_fam.maxattr, nl802154_policy);
  465. /* TODO check if we can handle error here,
  466. * we have no backward compatibility
  467. */
  468. if (ret)
  469. return 0;
  470. if (tb[NL802154_ATTR_WPAN_PHY])
  471. state->filter_wpan_phy = nla_get_u32(tb[NL802154_ATTR_WPAN_PHY]);
  472. if (tb[NL802154_ATTR_WPAN_DEV])
  473. state->filter_wpan_phy = nla_get_u64(tb[NL802154_ATTR_WPAN_DEV]) >> 32;
  474. if (tb[NL802154_ATTR_IFINDEX]) {
  475. struct net_device *netdev;
  476. struct cfg802154_registered_device *rdev;
  477. int ifidx = nla_get_u32(tb[NL802154_ATTR_IFINDEX]);
  478. /* TODO netns */
  479. netdev = __dev_get_by_index(&init_net, ifidx);
  480. if (!netdev)
  481. return -ENODEV;
  482. if (netdev->ieee802154_ptr) {
  483. rdev = wpan_phy_to_rdev(
  484. netdev->ieee802154_ptr->wpan_phy);
  485. state->filter_wpan_phy = rdev->wpan_phy_idx;
  486. }
  487. }
  488. return 0;
  489. }
  490. static int
  491. nl802154_dump_wpan_phy(struct sk_buff *skb, struct netlink_callback *cb)
  492. {
  493. int idx = 0, ret;
  494. struct nl802154_dump_wpan_phy_state *state = (void *)cb->args[0];
  495. struct cfg802154_registered_device *rdev;
  496. rtnl_lock();
  497. if (!state) {
  498. state = kzalloc(sizeof(*state), GFP_KERNEL);
  499. if (!state) {
  500. rtnl_unlock();
  501. return -ENOMEM;
  502. }
  503. state->filter_wpan_phy = -1;
  504. ret = nl802154_dump_wpan_phy_parse(skb, cb, state);
  505. if (ret) {
  506. kfree(state);
  507. rtnl_unlock();
  508. return ret;
  509. }
  510. cb->args[0] = (long)state;
  511. }
  512. list_for_each_entry(rdev, &cfg802154_rdev_list, list) {
  513. /* TODO net ns compare */
  514. if (++idx <= state->start)
  515. continue;
  516. if (state->filter_wpan_phy != -1 &&
  517. state->filter_wpan_phy != rdev->wpan_phy_idx)
  518. continue;
  519. /* attempt to fit multiple wpan_phy data chunks into the skb */
  520. ret = nl802154_send_wpan_phy(rdev,
  521. NL802154_CMD_NEW_WPAN_PHY,
  522. skb,
  523. NETLINK_CB(cb->skb).portid,
  524. cb->nlh->nlmsg_seq, NLM_F_MULTI);
  525. if (ret < 0) {
  526. if ((ret == -ENOBUFS || ret == -EMSGSIZE) &&
  527. !skb->len && cb->min_dump_alloc < 4096) {
  528. cb->min_dump_alloc = 4096;
  529. rtnl_unlock();
  530. return 1;
  531. }
  532. idx--;
  533. break;
  534. }
  535. break;
  536. }
  537. rtnl_unlock();
  538. state->start = idx;
  539. return skb->len;
  540. }
  541. static int nl802154_dump_wpan_phy_done(struct netlink_callback *cb)
  542. {
  543. kfree((void *)cb->args[0]);
  544. return 0;
  545. }
  546. static int nl802154_get_wpan_phy(struct sk_buff *skb, struct genl_info *info)
  547. {
  548. struct sk_buff *msg;
  549. struct cfg802154_registered_device *rdev = info->user_ptr[0];
  550. msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
  551. if (!msg)
  552. return -ENOMEM;
  553. if (nl802154_send_wpan_phy(rdev, NL802154_CMD_NEW_WPAN_PHY, msg,
  554. info->snd_portid, info->snd_seq, 0) < 0) {
  555. nlmsg_free(msg);
  556. return -ENOBUFS;
  557. }
  558. return genlmsg_reply(msg, info);
  559. }
  560. static inline u64 wpan_dev_id(struct wpan_dev *wpan_dev)
  561. {
  562. return (u64)wpan_dev->identifier |
  563. ((u64)wpan_phy_to_rdev(wpan_dev->wpan_phy)->wpan_phy_idx << 32);
  564. }
  565. #ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL
  566. #include <net/ieee802154_netdev.h>
  567. static int
  568. ieee802154_llsec_send_key_id(struct sk_buff *msg,
  569. const struct ieee802154_llsec_key_id *desc)
  570. {
  571. struct nlattr *nl_dev_addr;
  572. if (nla_put_u32(msg, NL802154_KEY_ID_ATTR_MODE, desc->mode))
  573. return -ENOBUFS;
  574. switch (desc->mode) {
  575. case NL802154_KEY_ID_MODE_IMPLICIT:
  576. nl_dev_addr = nla_nest_start(msg, NL802154_KEY_ID_ATTR_IMPLICIT);
  577. if (!nl_dev_addr)
  578. return -ENOBUFS;
  579. if (nla_put_le16(msg, NL802154_DEV_ADDR_ATTR_PAN_ID,
  580. desc->device_addr.pan_id) ||
  581. nla_put_u32(msg, NL802154_DEV_ADDR_ATTR_MODE,
  582. desc->device_addr.mode))
  583. return -ENOBUFS;
  584. switch (desc->device_addr.mode) {
  585. case NL802154_DEV_ADDR_SHORT:
  586. if (nla_put_le16(msg, NL802154_DEV_ADDR_ATTR_SHORT,
  587. desc->device_addr.short_addr))
  588. return -ENOBUFS;
  589. break;
  590. case NL802154_DEV_ADDR_EXTENDED:
  591. if (nla_put_le64(msg, NL802154_DEV_ADDR_ATTR_EXTENDED,
  592. desc->device_addr.extended_addr))
  593. return -ENOBUFS;
  594. break;
  595. default:
  596. /* userspace should handle unknown */
  597. break;
  598. }
  599. nla_nest_end(msg, nl_dev_addr);
  600. break;
  601. case NL802154_KEY_ID_MODE_INDEX:
  602. break;
  603. case NL802154_KEY_ID_MODE_INDEX_SHORT:
  604. /* TODO renmae short_source? */
  605. if (nla_put_le32(msg, NL802154_KEY_ID_ATTR_SOURCE_SHORT,
  606. desc->short_source))
  607. return -ENOBUFS;
  608. break;
  609. case NL802154_KEY_ID_MODE_INDEX_EXTENDED:
  610. if (nla_put_le64(msg, NL802154_KEY_ID_ATTR_SOURCE_EXTENDED,
  611. desc->extended_source))
  612. return -ENOBUFS;
  613. break;
  614. default:
  615. /* userspace should handle unknown */
  616. break;
  617. }
  618. /* TODO key_id to key_idx ? Check naming */
  619. if (desc->mode != NL802154_KEY_ID_MODE_IMPLICIT) {
  620. if (nla_put_u8(msg, NL802154_KEY_ID_ATTR_INDEX, desc->id))
  621. return -ENOBUFS;
  622. }
  623. return 0;
  624. }
  625. static int nl802154_get_llsec_params(struct sk_buff *msg,
  626. struct cfg802154_registered_device *rdev,
  627. struct wpan_dev *wpan_dev)
  628. {
  629. struct nlattr *nl_key_id;
  630. struct ieee802154_llsec_params params;
  631. int ret;
  632. ret = rdev_get_llsec_params(rdev, wpan_dev, &params);
  633. if (ret < 0)
  634. return ret;
  635. if (nla_put_u8(msg, NL802154_ATTR_SEC_ENABLED, params.enabled) ||
  636. nla_put_u32(msg, NL802154_ATTR_SEC_OUT_LEVEL, params.out_level) ||
  637. nla_put_be32(msg, NL802154_ATTR_SEC_FRAME_COUNTER,
  638. params.frame_counter))
  639. return -ENOBUFS;
  640. nl_key_id = nla_nest_start(msg, NL802154_ATTR_SEC_OUT_KEY_ID);
  641. if (!nl_key_id)
  642. return -ENOBUFS;
  643. ret = ieee802154_llsec_send_key_id(msg, &params.out_key);
  644. if (ret < 0)
  645. return ret;
  646. nla_nest_end(msg, nl_key_id);
  647. return 0;
  648. }
  649. #endif /* CONFIG_IEEE802154_NL802154_EXPERIMENTAL */
  650. static int
  651. nl802154_send_iface(struct sk_buff *msg, u32 portid, u32 seq, int flags,
  652. struct cfg802154_registered_device *rdev,
  653. struct wpan_dev *wpan_dev)
  654. {
  655. struct net_device *dev = wpan_dev->netdev;
  656. void *hdr;
  657. hdr = nl802154hdr_put(msg, portid, seq, flags,
  658. NL802154_CMD_NEW_INTERFACE);
  659. if (!hdr)
  660. return -1;
  661. if (dev &&
  662. (nla_put_u32(msg, NL802154_ATTR_IFINDEX, dev->ifindex) ||
  663. nla_put_string(msg, NL802154_ATTR_IFNAME, dev->name)))
  664. goto nla_put_failure;
  665. if (nla_put_u32(msg, NL802154_ATTR_WPAN_PHY, rdev->wpan_phy_idx) ||
  666. nla_put_u32(msg, NL802154_ATTR_IFTYPE, wpan_dev->iftype) ||
  667. nla_put_u64(msg, NL802154_ATTR_WPAN_DEV, wpan_dev_id(wpan_dev)) ||
  668. nla_put_u32(msg, NL802154_ATTR_GENERATION,
  669. rdev->devlist_generation ^
  670. (cfg802154_rdev_list_generation << 2)))
  671. goto nla_put_failure;
  672. /* address settings */
  673. if (nla_put_le64(msg, NL802154_ATTR_EXTENDED_ADDR,
  674. wpan_dev->extended_addr) ||
  675. nla_put_le16(msg, NL802154_ATTR_SHORT_ADDR,
  676. wpan_dev->short_addr) ||
  677. nla_put_le16(msg, NL802154_ATTR_PAN_ID, wpan_dev->pan_id))
  678. goto nla_put_failure;
  679. /* ARET handling */
  680. if (nla_put_s8(msg, NL802154_ATTR_MAX_FRAME_RETRIES,
  681. wpan_dev->frame_retries) ||
  682. nla_put_u8(msg, NL802154_ATTR_MAX_BE, wpan_dev->max_be) ||
  683. nla_put_u8(msg, NL802154_ATTR_MAX_CSMA_BACKOFFS,
  684. wpan_dev->csma_retries) ||
  685. nla_put_u8(msg, NL802154_ATTR_MIN_BE, wpan_dev->min_be))
  686. goto nla_put_failure;
  687. /* listen before transmit */
  688. if (nla_put_u8(msg, NL802154_ATTR_LBT_MODE, wpan_dev->lbt))
  689. goto nla_put_failure;
  690. /* ackreq default behaviour */
  691. if (nla_put_u8(msg, NL802154_ATTR_ACKREQ_DEFAULT, wpan_dev->ackreq))
  692. goto nla_put_failure;
  693. #ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL
  694. if (nl802154_get_llsec_params(msg, rdev, wpan_dev) < 0)
  695. goto nla_put_failure;
  696. #endif /* CONFIG_IEEE802154_NL802154_EXPERIMENTAL */
  697. genlmsg_end(msg, hdr);
  698. return 0;
  699. nla_put_failure:
  700. genlmsg_cancel(msg, hdr);
  701. return -EMSGSIZE;
  702. }
  703. static int
  704. nl802154_dump_interface(struct sk_buff *skb, struct netlink_callback *cb)
  705. {
  706. int wp_idx = 0;
  707. int if_idx = 0;
  708. int wp_start = cb->args[0];
  709. int if_start = cb->args[1];
  710. struct cfg802154_registered_device *rdev;
  711. struct wpan_dev *wpan_dev;
  712. rtnl_lock();
  713. list_for_each_entry(rdev, &cfg802154_rdev_list, list) {
  714. /* TODO netns compare */
  715. if (wp_idx < wp_start) {
  716. wp_idx++;
  717. continue;
  718. }
  719. if_idx = 0;
  720. list_for_each_entry(wpan_dev, &rdev->wpan_dev_list, list) {
  721. if (if_idx < if_start) {
  722. if_idx++;
  723. continue;
  724. }
  725. if (nl802154_send_iface(skb, NETLINK_CB(cb->skb).portid,
  726. cb->nlh->nlmsg_seq, NLM_F_MULTI,
  727. rdev, wpan_dev) < 0) {
  728. goto out;
  729. }
  730. if_idx++;
  731. }
  732. wp_idx++;
  733. }
  734. out:
  735. rtnl_unlock();
  736. cb->args[0] = wp_idx;
  737. cb->args[1] = if_idx;
  738. return skb->len;
  739. }
  740. static int nl802154_get_interface(struct sk_buff *skb, struct genl_info *info)
  741. {
  742. struct sk_buff *msg;
  743. struct cfg802154_registered_device *rdev = info->user_ptr[0];
  744. struct wpan_dev *wdev = info->user_ptr[1];
  745. msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
  746. if (!msg)
  747. return -ENOMEM;
  748. if (nl802154_send_iface(msg, info->snd_portid, info->snd_seq, 0,
  749. rdev, wdev) < 0) {
  750. nlmsg_free(msg);
  751. return -ENOBUFS;
  752. }
  753. return genlmsg_reply(msg, info);
  754. }
  755. static int nl802154_new_interface(struct sk_buff *skb, struct genl_info *info)
  756. {
  757. struct cfg802154_registered_device *rdev = info->user_ptr[0];
  758. enum nl802154_iftype type = NL802154_IFTYPE_UNSPEC;
  759. __le64 extended_addr = cpu_to_le64(0x0000000000000000ULL);
  760. /* TODO avoid failing a new interface
  761. * creation due to pending removal?
  762. */
  763. if (!info->attrs[NL802154_ATTR_IFNAME])
  764. return -EINVAL;
  765. if (info->attrs[NL802154_ATTR_IFTYPE]) {
  766. type = nla_get_u32(info->attrs[NL802154_ATTR_IFTYPE]);
  767. if (type > NL802154_IFTYPE_MAX ||
  768. !(rdev->wpan_phy.supported.iftypes & BIT(type)))
  769. return -EINVAL;
  770. }
  771. if (info->attrs[NL802154_ATTR_EXTENDED_ADDR])
  772. extended_addr = nla_get_le64(info->attrs[NL802154_ATTR_EXTENDED_ADDR]);
  773. if (!rdev->ops->add_virtual_intf)
  774. return -EOPNOTSUPP;
  775. return rdev_add_virtual_intf(rdev,
  776. nla_data(info->attrs[NL802154_ATTR_IFNAME]),
  777. NET_NAME_USER, type, extended_addr);
  778. }
  779. static int nl802154_del_interface(struct sk_buff *skb, struct genl_info *info)
  780. {
  781. struct cfg802154_registered_device *rdev = info->user_ptr[0];
  782. struct wpan_dev *wpan_dev = info->user_ptr[1];
  783. if (!rdev->ops->del_virtual_intf)
  784. return -EOPNOTSUPP;
  785. /* If we remove a wpan device without a netdev then clear
  786. * user_ptr[1] so that nl802154_post_doit won't dereference it
  787. * to check if it needs to do dev_put(). Otherwise it crashes
  788. * since the wpan_dev has been freed, unlike with a netdev where
  789. * we need the dev_put() for the netdev to really be freed.
  790. */
  791. if (!wpan_dev->netdev)
  792. info->user_ptr[1] = NULL;
  793. return rdev_del_virtual_intf(rdev, wpan_dev);
  794. }
  795. static int nl802154_set_channel(struct sk_buff *skb, struct genl_info *info)
  796. {
  797. struct cfg802154_registered_device *rdev = info->user_ptr[0];
  798. u8 channel, page;
  799. if (!info->attrs[NL802154_ATTR_PAGE] ||
  800. !info->attrs[NL802154_ATTR_CHANNEL])
  801. return -EINVAL;
  802. page = nla_get_u8(info->attrs[NL802154_ATTR_PAGE]);
  803. channel = nla_get_u8(info->attrs[NL802154_ATTR_CHANNEL]);
  804. /* check 802.15.4 constraints */
  805. if (page > IEEE802154_MAX_PAGE || channel > IEEE802154_MAX_CHANNEL ||
  806. !(rdev->wpan_phy.supported.channels[page] & BIT(channel)))
  807. return -EINVAL;
  808. return rdev_set_channel(rdev, page, channel);
  809. }
  810. static int nl802154_set_cca_mode(struct sk_buff *skb, struct genl_info *info)
  811. {
  812. struct cfg802154_registered_device *rdev = info->user_ptr[0];
  813. struct wpan_phy_cca cca;
  814. if (!(rdev->wpan_phy.flags & WPAN_PHY_FLAG_CCA_MODE))
  815. return -EOPNOTSUPP;
  816. if (!info->attrs[NL802154_ATTR_CCA_MODE])
  817. return -EINVAL;
  818. cca.mode = nla_get_u32(info->attrs[NL802154_ATTR_CCA_MODE]);
  819. /* checking 802.15.4 constraints */
  820. if (cca.mode < NL802154_CCA_ENERGY ||
  821. cca.mode > NL802154_CCA_ATTR_MAX ||
  822. !(rdev->wpan_phy.supported.cca_modes & BIT(cca.mode)))
  823. return -EINVAL;
  824. if (cca.mode == NL802154_CCA_ENERGY_CARRIER) {
  825. if (!info->attrs[NL802154_ATTR_CCA_OPT])
  826. return -EINVAL;
  827. cca.opt = nla_get_u32(info->attrs[NL802154_ATTR_CCA_OPT]);
  828. if (cca.opt > NL802154_CCA_OPT_ATTR_MAX ||
  829. !(rdev->wpan_phy.supported.cca_opts & BIT(cca.opt)))
  830. return -EINVAL;
  831. }
  832. return rdev_set_cca_mode(rdev, &cca);
  833. }
  834. static int nl802154_set_cca_ed_level(struct sk_buff *skb, struct genl_info *info)
  835. {
  836. struct cfg802154_registered_device *rdev = info->user_ptr[0];
  837. s32 ed_level;
  838. int i;
  839. if (!(rdev->wpan_phy.flags & WPAN_PHY_FLAG_CCA_ED_LEVEL))
  840. return -EOPNOTSUPP;
  841. if (!info->attrs[NL802154_ATTR_CCA_ED_LEVEL])
  842. return -EINVAL;
  843. ed_level = nla_get_s32(info->attrs[NL802154_ATTR_CCA_ED_LEVEL]);
  844. for (i = 0; i < rdev->wpan_phy.supported.cca_ed_levels_size; i++) {
  845. if (ed_level == rdev->wpan_phy.supported.cca_ed_levels[i])
  846. return rdev_set_cca_ed_level(rdev, ed_level);
  847. }
  848. return -EINVAL;
  849. }
  850. static int nl802154_set_tx_power(struct sk_buff *skb, struct genl_info *info)
  851. {
  852. struct cfg802154_registered_device *rdev = info->user_ptr[0];
  853. s32 power;
  854. int i;
  855. if (!(rdev->wpan_phy.flags & WPAN_PHY_FLAG_TXPOWER))
  856. return -EOPNOTSUPP;
  857. if (!info->attrs[NL802154_ATTR_TX_POWER])
  858. return -EINVAL;
  859. power = nla_get_s32(info->attrs[NL802154_ATTR_TX_POWER]);
  860. for (i = 0; i < rdev->wpan_phy.supported.tx_powers_size; i++) {
  861. if (power == rdev->wpan_phy.supported.tx_powers[i])
  862. return rdev_set_tx_power(rdev, power);
  863. }
  864. return -EINVAL;
  865. }
  866. static int nl802154_set_pan_id(struct sk_buff *skb, struct genl_info *info)
  867. {
  868. struct cfg802154_registered_device *rdev = info->user_ptr[0];
  869. struct net_device *dev = info->user_ptr[1];
  870. struct wpan_dev *wpan_dev = dev->ieee802154_ptr;
  871. __le16 pan_id;
  872. /* conflict here while tx/rx calls */
  873. if (netif_running(dev))
  874. return -EBUSY;
  875. /* don't change address fields on monitor */
  876. if (wpan_dev->iftype == NL802154_IFTYPE_MONITOR ||
  877. !info->attrs[NL802154_ATTR_PAN_ID])
  878. return -EINVAL;
  879. pan_id = nla_get_le16(info->attrs[NL802154_ATTR_PAN_ID]);
  880. /* TODO
  881. * I am not sure about to check here on broadcast pan_id.
  882. * Broadcast is a valid setting, comment from 802.15.4:
  883. * If this value is 0xffff, the device is not associated.
  884. *
  885. * This could useful to simple deassociate an device.
  886. */
  887. if (pan_id == cpu_to_le16(IEEE802154_PAN_ID_BROADCAST))
  888. return -EINVAL;
  889. return rdev_set_pan_id(rdev, wpan_dev, pan_id);
  890. }
  891. static int nl802154_set_short_addr(struct sk_buff *skb, struct genl_info *info)
  892. {
  893. struct cfg802154_registered_device *rdev = info->user_ptr[0];
  894. struct net_device *dev = info->user_ptr[1];
  895. struct wpan_dev *wpan_dev = dev->ieee802154_ptr;
  896. __le16 short_addr;
  897. /* conflict here while tx/rx calls */
  898. if (netif_running(dev))
  899. return -EBUSY;
  900. /* don't change address fields on monitor */
  901. if (wpan_dev->iftype == NL802154_IFTYPE_MONITOR ||
  902. !info->attrs[NL802154_ATTR_SHORT_ADDR])
  903. return -EINVAL;
  904. short_addr = nla_get_le16(info->attrs[NL802154_ATTR_SHORT_ADDR]);
  905. /* TODO
  906. * I am not sure about to check here on broadcast short_addr.
  907. * Broadcast is a valid setting, comment from 802.15.4:
  908. * A value of 0xfffe indicates that the device has
  909. * associated but has not been allocated an address. A
  910. * value of 0xffff indicates that the device does not
  911. * have a short address.
  912. *
  913. * I think we should allow to set these settings but
  914. * don't allow to allow socket communication with it.
  915. */
  916. if (short_addr == cpu_to_le16(IEEE802154_ADDR_SHORT_UNSPEC) ||
  917. short_addr == cpu_to_le16(IEEE802154_ADDR_SHORT_BROADCAST))
  918. return -EINVAL;
  919. return rdev_set_short_addr(rdev, wpan_dev, short_addr);
  920. }
  921. static int
  922. nl802154_set_backoff_exponent(struct sk_buff *skb, struct genl_info *info)
  923. {
  924. struct cfg802154_registered_device *rdev = info->user_ptr[0];
  925. struct net_device *dev = info->user_ptr[1];
  926. struct wpan_dev *wpan_dev = dev->ieee802154_ptr;
  927. u8 min_be, max_be;
  928. /* should be set on netif open inside phy settings */
  929. if (netif_running(dev))
  930. return -EBUSY;
  931. if (!info->attrs[NL802154_ATTR_MIN_BE] ||
  932. !info->attrs[NL802154_ATTR_MAX_BE])
  933. return -EINVAL;
  934. min_be = nla_get_u8(info->attrs[NL802154_ATTR_MIN_BE]);
  935. max_be = nla_get_u8(info->attrs[NL802154_ATTR_MAX_BE]);
  936. /* check 802.15.4 constraints */
  937. if (min_be < rdev->wpan_phy.supported.min_minbe ||
  938. min_be > rdev->wpan_phy.supported.max_minbe ||
  939. max_be < rdev->wpan_phy.supported.min_maxbe ||
  940. max_be > rdev->wpan_phy.supported.max_maxbe ||
  941. min_be > max_be)
  942. return -EINVAL;
  943. return rdev_set_backoff_exponent(rdev, wpan_dev, min_be, max_be);
  944. }
  945. static int
  946. nl802154_set_max_csma_backoffs(struct sk_buff *skb, struct genl_info *info)
  947. {
  948. struct cfg802154_registered_device *rdev = info->user_ptr[0];
  949. struct net_device *dev = info->user_ptr[1];
  950. struct wpan_dev *wpan_dev = dev->ieee802154_ptr;
  951. u8 max_csma_backoffs;
  952. /* conflict here while other running iface settings */
  953. if (netif_running(dev))
  954. return -EBUSY;
  955. if (!info->attrs[NL802154_ATTR_MAX_CSMA_BACKOFFS])
  956. return -EINVAL;
  957. max_csma_backoffs = nla_get_u8(
  958. info->attrs[NL802154_ATTR_MAX_CSMA_BACKOFFS]);
  959. /* check 802.15.4 constraints */
  960. if (max_csma_backoffs < rdev->wpan_phy.supported.min_csma_backoffs ||
  961. max_csma_backoffs > rdev->wpan_phy.supported.max_csma_backoffs)
  962. return -EINVAL;
  963. return rdev_set_max_csma_backoffs(rdev, wpan_dev, max_csma_backoffs);
  964. }
  965. static int
  966. nl802154_set_max_frame_retries(struct sk_buff *skb, struct genl_info *info)
  967. {
  968. struct cfg802154_registered_device *rdev = info->user_ptr[0];
  969. struct net_device *dev = info->user_ptr[1];
  970. struct wpan_dev *wpan_dev = dev->ieee802154_ptr;
  971. s8 max_frame_retries;
  972. if (netif_running(dev))
  973. return -EBUSY;
  974. if (!info->attrs[NL802154_ATTR_MAX_FRAME_RETRIES])
  975. return -EINVAL;
  976. max_frame_retries = nla_get_s8(
  977. info->attrs[NL802154_ATTR_MAX_FRAME_RETRIES]);
  978. /* check 802.15.4 constraints */
  979. if (max_frame_retries < rdev->wpan_phy.supported.min_frame_retries ||
  980. max_frame_retries > rdev->wpan_phy.supported.max_frame_retries)
  981. return -EINVAL;
  982. return rdev_set_max_frame_retries(rdev, wpan_dev, max_frame_retries);
  983. }
  984. static int nl802154_set_lbt_mode(struct sk_buff *skb, struct genl_info *info)
  985. {
  986. struct cfg802154_registered_device *rdev = info->user_ptr[0];
  987. struct net_device *dev = info->user_ptr[1];
  988. struct wpan_dev *wpan_dev = dev->ieee802154_ptr;
  989. int mode;
  990. if (netif_running(dev))
  991. return -EBUSY;
  992. if (!info->attrs[NL802154_ATTR_LBT_MODE])
  993. return -EINVAL;
  994. mode = nla_get_u8(info->attrs[NL802154_ATTR_LBT_MODE]);
  995. if (mode != 0 && mode != 1)
  996. return -EINVAL;
  997. if (!wpan_phy_supported_bool(mode, rdev->wpan_phy.supported.lbt))
  998. return -EINVAL;
  999. return rdev_set_lbt_mode(rdev, wpan_dev, mode);
  1000. }
  1001. static int
  1002. nl802154_set_ackreq_default(struct sk_buff *skb, struct genl_info *info)
  1003. {
  1004. struct cfg802154_registered_device *rdev = info->user_ptr[0];
  1005. struct net_device *dev = info->user_ptr[1];
  1006. struct wpan_dev *wpan_dev = dev->ieee802154_ptr;
  1007. int ackreq;
  1008. if (netif_running(dev))
  1009. return -EBUSY;
  1010. if (!info->attrs[NL802154_ATTR_ACKREQ_DEFAULT])
  1011. return -EINVAL;
  1012. ackreq = nla_get_u8(info->attrs[NL802154_ATTR_ACKREQ_DEFAULT]);
  1013. if (ackreq != 0 && ackreq != 1)
  1014. return -EINVAL;
  1015. return rdev_set_ackreq_default(rdev, wpan_dev, ackreq);
  1016. }
  1017. #ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL
  1018. static const struct nla_policy nl802154_dev_addr_policy[NL802154_DEV_ADDR_ATTR_MAX + 1] = {
  1019. [NL802154_DEV_ADDR_ATTR_PAN_ID] = { .type = NLA_U16 },
  1020. [NL802154_DEV_ADDR_ATTR_MODE] = { .type = NLA_U32 },
  1021. [NL802154_DEV_ADDR_ATTR_SHORT] = { .type = NLA_U16 },
  1022. [NL802154_DEV_ADDR_ATTR_EXTENDED] = { .type = NLA_U64 },
  1023. };
  1024. static int
  1025. ieee802154_llsec_parse_dev_addr(struct nlattr *nla,
  1026. struct ieee802154_addr *addr)
  1027. {
  1028. struct nlattr *attrs[NL802154_DEV_ADDR_ATTR_MAX + 1];
  1029. if (!nla || nla_parse_nested(attrs, NL802154_DEV_ADDR_ATTR_MAX, nla,
  1030. nl802154_dev_addr_policy))
  1031. return -EINVAL;
  1032. if (!attrs[NL802154_DEV_ADDR_ATTR_PAN_ID] &&
  1033. !attrs[NL802154_DEV_ADDR_ATTR_MODE] &&
  1034. !(attrs[NL802154_DEV_ADDR_ATTR_SHORT] ||
  1035. attrs[NL802154_DEV_ADDR_ATTR_EXTENDED]))
  1036. return -EINVAL;
  1037. addr->pan_id = nla_get_le16(attrs[NL802154_DEV_ADDR_ATTR_PAN_ID]);
  1038. addr->mode = nla_get_u32(attrs[NL802154_DEV_ADDR_ATTR_MODE]);
  1039. switch (addr->mode) {
  1040. case NL802154_DEV_ADDR_SHORT:
  1041. addr->short_addr = nla_get_le16(attrs[NL802154_DEV_ADDR_ATTR_SHORT]);
  1042. break;
  1043. case NL802154_DEV_ADDR_EXTENDED:
  1044. addr->extended_addr = nla_get_le64(attrs[NL802154_DEV_ADDR_ATTR_EXTENDED]);
  1045. break;
  1046. default:
  1047. return -EINVAL;
  1048. }
  1049. return 0;
  1050. }
  1051. static const struct nla_policy nl802154_key_id_policy[NL802154_KEY_ID_ATTR_MAX + 1] = {
  1052. [NL802154_KEY_ID_ATTR_MODE] = { .type = NLA_U32 },
  1053. [NL802154_KEY_ID_ATTR_INDEX] = { .type = NLA_U8 },
  1054. [NL802154_KEY_ID_ATTR_IMPLICIT] = { .type = NLA_NESTED },
  1055. [NL802154_KEY_ID_ATTR_SOURCE_SHORT] = { .type = NLA_U32 },
  1056. [NL802154_KEY_ID_ATTR_SOURCE_EXTENDED] = { .type = NLA_U64 },
  1057. };
  1058. static int
  1059. ieee802154_llsec_parse_key_id(struct nlattr *nla,
  1060. struct ieee802154_llsec_key_id *desc)
  1061. {
  1062. struct nlattr *attrs[NL802154_KEY_ID_ATTR_MAX + 1];
  1063. if (!nla || nla_parse_nested(attrs, NL802154_KEY_ID_ATTR_MAX, nla,
  1064. nl802154_key_id_policy))
  1065. return -EINVAL;
  1066. if (!attrs[NL802154_KEY_ID_ATTR_MODE])
  1067. return -EINVAL;
  1068. desc->mode = nla_get_u32(attrs[NL802154_KEY_ID_ATTR_MODE]);
  1069. switch (desc->mode) {
  1070. case NL802154_KEY_ID_MODE_IMPLICIT:
  1071. if (!attrs[NL802154_KEY_ID_ATTR_IMPLICIT])
  1072. return -EINVAL;
  1073. if (ieee802154_llsec_parse_dev_addr(attrs[NL802154_KEY_ID_ATTR_IMPLICIT],
  1074. &desc->device_addr) < 0)
  1075. return -EINVAL;
  1076. break;
  1077. case NL802154_KEY_ID_MODE_INDEX:
  1078. break;
  1079. case NL802154_KEY_ID_MODE_INDEX_SHORT:
  1080. if (!attrs[NL802154_KEY_ID_ATTR_SOURCE_SHORT])
  1081. return -EINVAL;
  1082. desc->short_source = nla_get_le32(attrs[NL802154_KEY_ID_ATTR_SOURCE_SHORT]);
  1083. break;
  1084. case NL802154_KEY_ID_MODE_INDEX_EXTENDED:
  1085. if (!attrs[NL802154_KEY_ID_ATTR_SOURCE_EXTENDED])
  1086. return -EINVAL;
  1087. desc->extended_source = nla_get_le64(attrs[NL802154_KEY_ID_ATTR_SOURCE_EXTENDED]);
  1088. break;
  1089. default:
  1090. return -EINVAL;
  1091. }
  1092. if (desc->mode != NL802154_KEY_ID_MODE_IMPLICIT) {
  1093. if (!attrs[NL802154_KEY_ID_ATTR_INDEX])
  1094. return -EINVAL;
  1095. /* TODO change id to idx */
  1096. desc->id = nla_get_u8(attrs[NL802154_KEY_ID_ATTR_INDEX]);
  1097. }
  1098. return 0;
  1099. }
  1100. static int nl802154_set_llsec_params(struct sk_buff *skb,
  1101. struct genl_info *info)
  1102. {
  1103. struct cfg802154_registered_device *rdev = info->user_ptr[0];
  1104. struct net_device *dev = info->user_ptr[1];
  1105. struct wpan_dev *wpan_dev = dev->ieee802154_ptr;
  1106. struct ieee802154_llsec_params params;
  1107. u32 changed = 0;
  1108. int ret;
  1109. if (info->attrs[NL802154_ATTR_SEC_ENABLED]) {
  1110. u8 enabled;
  1111. enabled = nla_get_u8(info->attrs[NL802154_ATTR_SEC_ENABLED]);
  1112. if (enabled != 0 && enabled != 1)
  1113. return -EINVAL;
  1114. params.enabled = nla_get_u8(info->attrs[NL802154_ATTR_SEC_ENABLED]);
  1115. changed |= IEEE802154_LLSEC_PARAM_ENABLED;
  1116. }
  1117. if (info->attrs[NL802154_ATTR_SEC_OUT_KEY_ID]) {
  1118. ret = ieee802154_llsec_parse_key_id(info->attrs[NL802154_ATTR_SEC_OUT_KEY_ID],
  1119. &params.out_key);
  1120. if (ret < 0)
  1121. return ret;
  1122. changed |= IEEE802154_LLSEC_PARAM_OUT_KEY;
  1123. }
  1124. if (info->attrs[NL802154_ATTR_SEC_OUT_LEVEL]) {
  1125. params.out_level = nla_get_u32(info->attrs[NL802154_ATTR_SEC_OUT_LEVEL]);
  1126. if (params.out_level > NL802154_SECLEVEL_MAX)
  1127. return -EINVAL;
  1128. changed |= IEEE802154_LLSEC_PARAM_OUT_LEVEL;
  1129. }
  1130. if (info->attrs[NL802154_ATTR_SEC_FRAME_COUNTER]) {
  1131. params.frame_counter = nla_get_be32(info->attrs[NL802154_ATTR_SEC_FRAME_COUNTER]);
  1132. changed |= IEEE802154_LLSEC_PARAM_FRAME_COUNTER;
  1133. }
  1134. return rdev_set_llsec_params(rdev, wpan_dev, &params, changed);
  1135. }
  1136. static int nl802154_send_key(struct sk_buff *msg, u32 cmd, u32 portid,
  1137. u32 seq, int flags,
  1138. struct cfg802154_registered_device *rdev,
  1139. struct net_device *dev,
  1140. const struct ieee802154_llsec_key_entry *key)
  1141. {
  1142. void *hdr;
  1143. u32 commands[NL802154_CMD_FRAME_NR_IDS / 32];
  1144. struct nlattr *nl_key, *nl_key_id;
  1145. hdr = nl802154hdr_put(msg, portid, seq, flags, cmd);
  1146. if (!hdr)
  1147. return -1;
  1148. if (nla_put_u32(msg, NL802154_ATTR_IFINDEX, dev->ifindex))
  1149. goto nla_put_failure;
  1150. nl_key = nla_nest_start(msg, NL802154_ATTR_SEC_KEY);
  1151. if (!nl_key)
  1152. goto nla_put_failure;
  1153. nl_key_id = nla_nest_start(msg, NL802154_KEY_ATTR_ID);
  1154. if (!nl_key_id)
  1155. goto nla_put_failure;
  1156. if (ieee802154_llsec_send_key_id(msg, &key->id) < 0)
  1157. goto nla_put_failure;
  1158. nla_nest_end(msg, nl_key_id);
  1159. if (nla_put_u8(msg, NL802154_KEY_ATTR_USAGE_FRAMES,
  1160. key->key->frame_types))
  1161. goto nla_put_failure;
  1162. if (key->key->frame_types & BIT(NL802154_FRAME_CMD)) {
  1163. /* TODO for each nested */
  1164. memset(commands, 0, sizeof(commands));
  1165. commands[7] = key->key->cmd_frame_ids;
  1166. if (nla_put(msg, NL802154_KEY_ATTR_USAGE_CMDS,
  1167. sizeof(commands), commands))
  1168. goto nla_put_failure;
  1169. }
  1170. if (nla_put(msg, NL802154_KEY_ATTR_BYTES, NL802154_KEY_SIZE,
  1171. key->key->key))
  1172. goto nla_put_failure;
  1173. nla_nest_end(msg, nl_key);
  1174. genlmsg_end(msg, hdr);
  1175. return 0;
  1176. nla_put_failure:
  1177. genlmsg_cancel(msg, hdr);
  1178. return -EMSGSIZE;
  1179. }
  1180. static int
  1181. nl802154_dump_llsec_key(struct sk_buff *skb, struct netlink_callback *cb)
  1182. {
  1183. struct cfg802154_registered_device *rdev = NULL;
  1184. struct ieee802154_llsec_key_entry *key;
  1185. struct ieee802154_llsec_table *table;
  1186. struct wpan_dev *wpan_dev;
  1187. int err;
  1188. err = nl802154_prepare_wpan_dev_dump(skb, cb, &rdev, &wpan_dev);
  1189. if (err)
  1190. return err;
  1191. if (!wpan_dev->netdev) {
  1192. err = -EINVAL;
  1193. goto out_err;
  1194. }
  1195. rdev_lock_llsec_table(rdev, wpan_dev);
  1196. rdev_get_llsec_table(rdev, wpan_dev, &table);
  1197. /* TODO make it like station dump */
  1198. if (cb->args[2])
  1199. goto out;
  1200. list_for_each_entry(key, &table->keys, list) {
  1201. if (nl802154_send_key(skb, NL802154_CMD_NEW_SEC_KEY,
  1202. NETLINK_CB(cb->skb).portid,
  1203. cb->nlh->nlmsg_seq, NLM_F_MULTI,
  1204. rdev, wpan_dev->netdev, key) < 0) {
  1205. /* TODO */
  1206. err = -EIO;
  1207. rdev_unlock_llsec_table(rdev, wpan_dev);
  1208. goto out_err;
  1209. }
  1210. }
  1211. cb->args[2] = 1;
  1212. out:
  1213. rdev_unlock_llsec_table(rdev, wpan_dev);
  1214. err = skb->len;
  1215. out_err:
  1216. nl802154_finish_wpan_dev_dump(rdev);
  1217. return err;
  1218. }
  1219. static const struct nla_policy nl802154_key_policy[NL802154_KEY_ATTR_MAX + 1] = {
  1220. [NL802154_KEY_ATTR_ID] = { NLA_NESTED },
  1221. /* TODO handle it as for_each_nested and NLA_FLAG? */
  1222. [NL802154_KEY_ATTR_USAGE_FRAMES] = { NLA_U8 },
  1223. /* TODO handle it as for_each_nested, not static array? */
  1224. [NL802154_KEY_ATTR_USAGE_CMDS] = { .len = NL802154_CMD_FRAME_NR_IDS / 8 },
  1225. [NL802154_KEY_ATTR_BYTES] = { .len = NL802154_KEY_SIZE },
  1226. };
  1227. static int nl802154_add_llsec_key(struct sk_buff *skb, struct genl_info *info)
  1228. {
  1229. struct cfg802154_registered_device *rdev = info->user_ptr[0];
  1230. struct net_device *dev = info->user_ptr[1];
  1231. struct wpan_dev *wpan_dev = dev->ieee802154_ptr;
  1232. struct nlattr *attrs[NL802154_KEY_ATTR_MAX + 1];
  1233. struct ieee802154_llsec_key key = { };
  1234. struct ieee802154_llsec_key_id id = { };
  1235. u32 commands[NL802154_CMD_FRAME_NR_IDS / 32] = { };
  1236. if (nla_parse_nested(attrs, NL802154_KEY_ATTR_MAX,
  1237. info->attrs[NL802154_ATTR_SEC_KEY],
  1238. nl802154_key_policy))
  1239. return -EINVAL;
  1240. if (!attrs[NL802154_KEY_ATTR_USAGE_FRAMES] ||
  1241. !attrs[NL802154_KEY_ATTR_BYTES])
  1242. return -EINVAL;
  1243. if (ieee802154_llsec_parse_key_id(attrs[NL802154_KEY_ATTR_ID], &id) < 0)
  1244. return -ENOBUFS;
  1245. key.frame_types = nla_get_u8(attrs[NL802154_KEY_ATTR_USAGE_FRAMES]);
  1246. if (key.frame_types > BIT(NL802154_FRAME_MAX) ||
  1247. ((key.frame_types & BIT(NL802154_FRAME_CMD)) &&
  1248. !attrs[NL802154_KEY_ATTR_USAGE_CMDS]))
  1249. return -EINVAL;
  1250. if (attrs[NL802154_KEY_ATTR_USAGE_CMDS]) {
  1251. /* TODO for each nested */
  1252. nla_memcpy(commands, attrs[NL802154_KEY_ATTR_USAGE_CMDS],
  1253. NL802154_CMD_FRAME_NR_IDS / 8);
  1254. /* TODO understand the -EINVAL logic here? last condition */
  1255. if (commands[0] || commands[1] || commands[2] || commands[3] ||
  1256. commands[4] || commands[5] || commands[6] ||
  1257. commands[7] > BIT(NL802154_CMD_FRAME_MAX))
  1258. return -EINVAL;
  1259. key.cmd_frame_ids = commands[7];
  1260. } else {
  1261. key.cmd_frame_ids = 0;
  1262. }
  1263. nla_memcpy(key.key, attrs[NL802154_KEY_ATTR_BYTES], NL802154_KEY_SIZE);
  1264. if (ieee802154_llsec_parse_key_id(attrs[NL802154_KEY_ATTR_ID], &id) < 0)
  1265. return -ENOBUFS;
  1266. return rdev_add_llsec_key(rdev, wpan_dev, &id, &key);
  1267. }
  1268. static int nl802154_del_llsec_key(struct sk_buff *skb, struct genl_info *info)
  1269. {
  1270. struct cfg802154_registered_device *rdev = info->user_ptr[0];
  1271. struct net_device *dev = info->user_ptr[1];
  1272. struct wpan_dev *wpan_dev = dev->ieee802154_ptr;
  1273. struct nlattr *attrs[NL802154_KEY_ATTR_MAX + 1];
  1274. struct ieee802154_llsec_key_id id;
  1275. if (nla_parse_nested(attrs, NL802154_KEY_ATTR_MAX,
  1276. info->attrs[NL802154_ATTR_SEC_KEY],
  1277. nl802154_key_policy))
  1278. return -EINVAL;
  1279. if (ieee802154_llsec_parse_key_id(attrs[NL802154_KEY_ATTR_ID], &id) < 0)
  1280. return -ENOBUFS;
  1281. return rdev_del_llsec_key(rdev, wpan_dev, &id);
  1282. }
  1283. static int nl802154_send_device(struct sk_buff *msg, u32 cmd, u32 portid,
  1284. u32 seq, int flags,
  1285. struct cfg802154_registered_device *rdev,
  1286. struct net_device *dev,
  1287. const struct ieee802154_llsec_device *dev_desc)
  1288. {
  1289. void *hdr;
  1290. struct nlattr *nl_device;
  1291. hdr = nl802154hdr_put(msg, portid, seq, flags, cmd);
  1292. if (!hdr)
  1293. return -1;
  1294. if (nla_put_u32(msg, NL802154_ATTR_IFINDEX, dev->ifindex))
  1295. goto nla_put_failure;
  1296. nl_device = nla_nest_start(msg, NL802154_ATTR_SEC_DEVICE);
  1297. if (!nl_device)
  1298. goto nla_put_failure;
  1299. if (nla_put_u32(msg, NL802154_DEV_ATTR_FRAME_COUNTER,
  1300. dev_desc->frame_counter) ||
  1301. nla_put_le16(msg, NL802154_DEV_ATTR_PAN_ID, dev_desc->pan_id) ||
  1302. nla_put_le16(msg, NL802154_DEV_ATTR_SHORT_ADDR,
  1303. dev_desc->short_addr) ||
  1304. nla_put_le64(msg, NL802154_DEV_ATTR_EXTENDED_ADDR,
  1305. dev_desc->hwaddr) ||
  1306. nla_put_u8(msg, NL802154_DEV_ATTR_SECLEVEL_EXEMPT,
  1307. dev_desc->seclevel_exempt) ||
  1308. nla_put_u32(msg, NL802154_DEV_ATTR_KEY_MODE, dev_desc->key_mode))
  1309. goto nla_put_failure;
  1310. nla_nest_end(msg, nl_device);
  1311. genlmsg_end(msg, hdr);
  1312. return 0;
  1313. nla_put_failure:
  1314. genlmsg_cancel(msg, hdr);
  1315. return -EMSGSIZE;
  1316. }
  1317. static int
  1318. nl802154_dump_llsec_dev(struct sk_buff *skb, struct netlink_callback *cb)
  1319. {
  1320. struct cfg802154_registered_device *rdev = NULL;
  1321. struct ieee802154_llsec_device *dev;
  1322. struct ieee802154_llsec_table *table;
  1323. struct wpan_dev *wpan_dev;
  1324. int err;
  1325. err = nl802154_prepare_wpan_dev_dump(skb, cb, &rdev, &wpan_dev);
  1326. if (err)
  1327. return err;
  1328. if (!wpan_dev->netdev) {
  1329. err = -EINVAL;
  1330. goto out_err;
  1331. }
  1332. rdev_lock_llsec_table(rdev, wpan_dev);
  1333. rdev_get_llsec_table(rdev, wpan_dev, &table);
  1334. /* TODO make it like station dump */
  1335. if (cb->args[2])
  1336. goto out;
  1337. list_for_each_entry(dev, &table->devices, list) {
  1338. if (nl802154_send_device(skb, NL802154_CMD_NEW_SEC_LEVEL,
  1339. NETLINK_CB(cb->skb).portid,
  1340. cb->nlh->nlmsg_seq, NLM_F_MULTI,
  1341. rdev, wpan_dev->netdev, dev) < 0) {
  1342. /* TODO */
  1343. err = -EIO;
  1344. rdev_unlock_llsec_table(rdev, wpan_dev);
  1345. goto out_err;
  1346. }
  1347. }
  1348. cb->args[2] = 1;
  1349. out:
  1350. rdev_unlock_llsec_table(rdev, wpan_dev);
  1351. err = skb->len;
  1352. out_err:
  1353. nl802154_finish_wpan_dev_dump(rdev);
  1354. return err;
  1355. }
  1356. static const struct nla_policy nl802154_dev_policy[NL802154_DEV_ATTR_MAX + 1] = {
  1357. [NL802154_DEV_ATTR_FRAME_COUNTER] = { NLA_U32 },
  1358. [NL802154_DEV_ATTR_PAN_ID] = { .type = NLA_U16 },
  1359. [NL802154_DEV_ATTR_SHORT_ADDR] = { .type = NLA_U16 },
  1360. [NL802154_DEV_ATTR_EXTENDED_ADDR] = { .type = NLA_U64 },
  1361. [NL802154_DEV_ATTR_SECLEVEL_EXEMPT] = { NLA_U8 },
  1362. [NL802154_DEV_ATTR_KEY_MODE] = { NLA_U32 },
  1363. };
  1364. static int
  1365. ieee802154_llsec_parse_device(struct nlattr *nla,
  1366. struct ieee802154_llsec_device *dev)
  1367. {
  1368. struct nlattr *attrs[NL802154_DEV_ATTR_MAX + 1];
  1369. if (!nla || nla_parse_nested(attrs, NL802154_DEV_ATTR_MAX, nla,
  1370. nl802154_dev_policy))
  1371. return -EINVAL;
  1372. memset(dev, 0, sizeof(*dev));
  1373. if (!attrs[NL802154_DEV_ATTR_FRAME_COUNTER] ||
  1374. !attrs[NL802154_DEV_ATTR_PAN_ID] ||
  1375. !attrs[NL802154_DEV_ATTR_SHORT_ADDR] ||
  1376. !attrs[NL802154_DEV_ATTR_EXTENDED_ADDR] ||
  1377. !attrs[NL802154_DEV_ATTR_SECLEVEL_EXEMPT] ||
  1378. !attrs[NL802154_DEV_ATTR_KEY_MODE])
  1379. return -EINVAL;
  1380. /* TODO be32 */
  1381. dev->frame_counter = nla_get_u32(attrs[NL802154_DEV_ATTR_FRAME_COUNTER]);
  1382. dev->pan_id = nla_get_le16(attrs[NL802154_DEV_ATTR_PAN_ID]);
  1383. dev->short_addr = nla_get_le16(attrs[NL802154_DEV_ATTR_SHORT_ADDR]);
  1384. /* TODO rename hwaddr to extended_addr */
  1385. dev->hwaddr = nla_get_le64(attrs[NL802154_DEV_ATTR_EXTENDED_ADDR]);
  1386. dev->seclevel_exempt = nla_get_u8(attrs[NL802154_DEV_ATTR_SECLEVEL_EXEMPT]);
  1387. dev->key_mode = nla_get_u32(attrs[NL802154_DEV_ATTR_KEY_MODE]);
  1388. if (dev->key_mode > NL802154_DEVKEY_MAX ||
  1389. (dev->seclevel_exempt != 0 && dev->seclevel_exempt != 1))
  1390. return -EINVAL;
  1391. return 0;
  1392. }
  1393. static int nl802154_add_llsec_dev(struct sk_buff *skb, struct genl_info *info)
  1394. {
  1395. struct cfg802154_registered_device *rdev = info->user_ptr[0];
  1396. struct net_device *dev = info->user_ptr[1];
  1397. struct wpan_dev *wpan_dev = dev->ieee802154_ptr;
  1398. struct ieee802154_llsec_device dev_desc;
  1399. if (ieee802154_llsec_parse_device(info->attrs[NL802154_ATTR_SEC_DEVICE],
  1400. &dev_desc) < 0)
  1401. return -EINVAL;
  1402. return rdev_add_device(rdev, wpan_dev, &dev_desc);
  1403. }
  1404. static int nl802154_del_llsec_dev(struct sk_buff *skb, struct genl_info *info)
  1405. {
  1406. struct cfg802154_registered_device *rdev = info->user_ptr[0];
  1407. struct net_device *dev = info->user_ptr[1];
  1408. struct wpan_dev *wpan_dev = dev->ieee802154_ptr;
  1409. struct nlattr *attrs[NL802154_DEV_ATTR_MAX + 1];
  1410. __le64 extended_addr;
  1411. if (nla_parse_nested(attrs, NL802154_DEV_ATTR_MAX,
  1412. info->attrs[NL802154_ATTR_SEC_DEVICE],
  1413. nl802154_dev_policy))
  1414. return -EINVAL;
  1415. if (!attrs[NL802154_DEV_ATTR_EXTENDED_ADDR])
  1416. return -EINVAL;
  1417. extended_addr = nla_get_le64(attrs[NL802154_DEV_ATTR_EXTENDED_ADDR]);
  1418. return rdev_del_device(rdev, wpan_dev, extended_addr);
  1419. }
  1420. static int nl802154_send_devkey(struct sk_buff *msg, u32 cmd, u32 portid,
  1421. u32 seq, int flags,
  1422. struct cfg802154_registered_device *rdev,
  1423. struct net_device *dev, __le64 extended_addr,
  1424. const struct ieee802154_llsec_device_key *devkey)
  1425. {
  1426. void *hdr;
  1427. struct nlattr *nl_devkey, *nl_key_id;
  1428. hdr = nl802154hdr_put(msg, portid, seq, flags, cmd);
  1429. if (!hdr)
  1430. return -1;
  1431. if (nla_put_u32(msg, NL802154_ATTR_IFINDEX, dev->ifindex))
  1432. goto nla_put_failure;
  1433. nl_devkey = nla_nest_start(msg, NL802154_ATTR_SEC_DEVKEY);
  1434. if (!nl_devkey)
  1435. goto nla_put_failure;
  1436. if (nla_put_le64(msg, NL802154_DEVKEY_ATTR_EXTENDED_ADDR,
  1437. extended_addr) ||
  1438. nla_put_u32(msg, NL802154_DEVKEY_ATTR_FRAME_COUNTER,
  1439. devkey->frame_counter))
  1440. goto nla_put_failure;
  1441. nl_key_id = nla_nest_start(msg, NL802154_DEVKEY_ATTR_ID);
  1442. if (!nl_key_id)
  1443. goto nla_put_failure;
  1444. if (ieee802154_llsec_send_key_id(msg, &devkey->key_id) < 0)
  1445. goto nla_put_failure;
  1446. nla_nest_end(msg, nl_key_id);
  1447. nla_nest_end(msg, nl_devkey);
  1448. genlmsg_end(msg, hdr);
  1449. return 0;
  1450. nla_put_failure:
  1451. genlmsg_cancel(msg, hdr);
  1452. return -EMSGSIZE;
  1453. }
  1454. static int
  1455. nl802154_dump_llsec_devkey(struct sk_buff *skb, struct netlink_callback *cb)
  1456. {
  1457. struct cfg802154_registered_device *rdev = NULL;
  1458. struct ieee802154_llsec_device_key *kpos;
  1459. struct ieee802154_llsec_device *dpos;
  1460. struct ieee802154_llsec_table *table;
  1461. struct wpan_dev *wpan_dev;
  1462. int err;
  1463. err = nl802154_prepare_wpan_dev_dump(skb, cb, &rdev, &wpan_dev);
  1464. if (err)
  1465. return err;
  1466. if (!wpan_dev->netdev) {
  1467. err = -EINVAL;
  1468. goto out_err;
  1469. }
  1470. rdev_lock_llsec_table(rdev, wpan_dev);
  1471. rdev_get_llsec_table(rdev, wpan_dev, &table);
  1472. /* TODO make it like station dump */
  1473. if (cb->args[2])
  1474. goto out;
  1475. /* TODO look if remove devkey and do some nested attribute */
  1476. list_for_each_entry(dpos, &table->devices, list) {
  1477. list_for_each_entry(kpos, &dpos->keys, list) {
  1478. if (nl802154_send_devkey(skb,
  1479. NL802154_CMD_NEW_SEC_LEVEL,
  1480. NETLINK_CB(cb->skb).portid,
  1481. cb->nlh->nlmsg_seq,
  1482. NLM_F_MULTI, rdev,
  1483. wpan_dev->netdev,
  1484. dpos->hwaddr,
  1485. kpos) < 0) {
  1486. /* TODO */
  1487. err = -EIO;
  1488. rdev_unlock_llsec_table(rdev, wpan_dev);
  1489. goto out_err;
  1490. }
  1491. }
  1492. }
  1493. cb->args[2] = 1;
  1494. out:
  1495. rdev_unlock_llsec_table(rdev, wpan_dev);
  1496. err = skb->len;
  1497. out_err:
  1498. nl802154_finish_wpan_dev_dump(rdev);
  1499. return err;
  1500. }
  1501. static const struct nla_policy nl802154_devkey_policy[NL802154_DEVKEY_ATTR_MAX + 1] = {
  1502. [NL802154_DEVKEY_ATTR_FRAME_COUNTER] = { NLA_U32 },
  1503. [NL802154_DEVKEY_ATTR_EXTENDED_ADDR] = { NLA_U64 },
  1504. [NL802154_DEVKEY_ATTR_ID] = { NLA_NESTED },
  1505. };
  1506. static int nl802154_add_llsec_devkey(struct sk_buff *skb, struct genl_info *info)
  1507. {
  1508. struct cfg802154_registered_device *rdev = info->user_ptr[0];
  1509. struct net_device *dev = info->user_ptr[1];
  1510. struct wpan_dev *wpan_dev = dev->ieee802154_ptr;
  1511. struct nlattr *attrs[NL802154_DEVKEY_ATTR_MAX + 1];
  1512. struct ieee802154_llsec_device_key key;
  1513. __le64 extended_addr;
  1514. if (!info->attrs[NL802154_ATTR_SEC_DEVKEY] ||
  1515. nla_parse_nested(attrs, NL802154_DEVKEY_ATTR_MAX,
  1516. info->attrs[NL802154_ATTR_SEC_DEVKEY],
  1517. nl802154_devkey_policy) < 0)
  1518. return -EINVAL;
  1519. if (!attrs[NL802154_DEVKEY_ATTR_FRAME_COUNTER] ||
  1520. !attrs[NL802154_DEVKEY_ATTR_EXTENDED_ADDR])
  1521. return -EINVAL;
  1522. /* TODO change key.id ? */
  1523. if (ieee802154_llsec_parse_key_id(attrs[NL802154_DEVKEY_ATTR_ID],
  1524. &key.key_id) < 0)
  1525. return -ENOBUFS;
  1526. /* TODO be32 */
  1527. key.frame_counter = nla_get_u32(attrs[NL802154_DEVKEY_ATTR_FRAME_COUNTER]);
  1528. /* TODO change naming hwaddr -> extended_addr
  1529. * check unique identifier short+pan OR extended_addr
  1530. */
  1531. extended_addr = nla_get_le64(attrs[NL802154_DEVKEY_ATTR_EXTENDED_ADDR]);
  1532. return rdev_add_devkey(rdev, wpan_dev, extended_addr, &key);
  1533. }
  1534. static int nl802154_del_llsec_devkey(struct sk_buff *skb, struct genl_info *info)
  1535. {
  1536. struct cfg802154_registered_device *rdev = info->user_ptr[0];
  1537. struct net_device *dev = info->user_ptr[1];
  1538. struct wpan_dev *wpan_dev = dev->ieee802154_ptr;
  1539. struct nlattr *attrs[NL802154_DEVKEY_ATTR_MAX + 1];
  1540. struct ieee802154_llsec_device_key key;
  1541. __le64 extended_addr;
  1542. if (nla_parse_nested(attrs, NL802154_DEVKEY_ATTR_MAX,
  1543. info->attrs[NL802154_ATTR_SEC_DEVKEY],
  1544. nl802154_devkey_policy))
  1545. return -EINVAL;
  1546. if (!attrs[NL802154_DEVKEY_ATTR_EXTENDED_ADDR])
  1547. return -EINVAL;
  1548. /* TODO change key.id ? */
  1549. if (ieee802154_llsec_parse_key_id(attrs[NL802154_DEVKEY_ATTR_ID],
  1550. &key.key_id) < 0)
  1551. return -ENOBUFS;
  1552. /* TODO change naming hwaddr -> extended_addr
  1553. * check unique identifier short+pan OR extended_addr
  1554. */
  1555. extended_addr = nla_get_le64(attrs[NL802154_DEVKEY_ATTR_EXTENDED_ADDR]);
  1556. return rdev_del_devkey(rdev, wpan_dev, extended_addr, &key);
  1557. }
  1558. static int nl802154_send_seclevel(struct sk_buff *msg, u32 cmd, u32 portid,
  1559. u32 seq, int flags,
  1560. struct cfg802154_registered_device *rdev,
  1561. struct net_device *dev,
  1562. const struct ieee802154_llsec_seclevel *sl)
  1563. {
  1564. void *hdr;
  1565. struct nlattr *nl_seclevel;
  1566. hdr = nl802154hdr_put(msg, portid, seq, flags, cmd);
  1567. if (!hdr)
  1568. return -1;
  1569. if (nla_put_u32(msg, NL802154_ATTR_IFINDEX, dev->ifindex))
  1570. goto nla_put_failure;
  1571. nl_seclevel = nla_nest_start(msg, NL802154_ATTR_SEC_LEVEL);
  1572. if (!nl_seclevel)
  1573. goto nla_put_failure;
  1574. if (nla_put_u32(msg, NL802154_SECLEVEL_ATTR_FRAME, sl->frame_type) ||
  1575. nla_put_u32(msg, NL802154_SECLEVEL_ATTR_LEVELS, sl->sec_levels) ||
  1576. nla_put_u8(msg, NL802154_SECLEVEL_ATTR_DEV_OVERRIDE,
  1577. sl->device_override))
  1578. goto nla_put_failure;
  1579. if (sl->frame_type == NL802154_FRAME_CMD) {
  1580. if (nla_put_u32(msg, NL802154_SECLEVEL_ATTR_CMD_FRAME,
  1581. sl->cmd_frame_id))
  1582. goto nla_put_failure;
  1583. }
  1584. nla_nest_end(msg, nl_seclevel);
  1585. genlmsg_end(msg, hdr);
  1586. return 0;
  1587. nla_put_failure:
  1588. genlmsg_cancel(msg, hdr);
  1589. return -EMSGSIZE;
  1590. }
  1591. static int
  1592. nl802154_dump_llsec_seclevel(struct sk_buff *skb, struct netlink_callback *cb)
  1593. {
  1594. struct cfg802154_registered_device *rdev = NULL;
  1595. struct ieee802154_llsec_seclevel *sl;
  1596. struct ieee802154_llsec_table *table;
  1597. struct wpan_dev *wpan_dev;
  1598. int err;
  1599. err = nl802154_prepare_wpan_dev_dump(skb, cb, &rdev, &wpan_dev);
  1600. if (err)
  1601. return err;
  1602. if (!wpan_dev->netdev) {
  1603. err = -EINVAL;
  1604. goto out_err;
  1605. }
  1606. rdev_lock_llsec_table(rdev, wpan_dev);
  1607. rdev_get_llsec_table(rdev, wpan_dev, &table);
  1608. /* TODO make it like station dump */
  1609. if (cb->args[2])
  1610. goto out;
  1611. list_for_each_entry(sl, &table->security_levels, list) {
  1612. if (nl802154_send_seclevel(skb, NL802154_CMD_NEW_SEC_LEVEL,
  1613. NETLINK_CB(cb->skb).portid,
  1614. cb->nlh->nlmsg_seq, NLM_F_MULTI,
  1615. rdev, wpan_dev->netdev, sl) < 0) {
  1616. /* TODO */
  1617. err = -EIO;
  1618. rdev_unlock_llsec_table(rdev, wpan_dev);
  1619. goto out_err;
  1620. }
  1621. }
  1622. cb->args[2] = 1;
  1623. out:
  1624. rdev_unlock_llsec_table(rdev, wpan_dev);
  1625. err = skb->len;
  1626. out_err:
  1627. nl802154_finish_wpan_dev_dump(rdev);
  1628. return err;
  1629. }
  1630. static const struct nla_policy nl802154_seclevel_policy[NL802154_SECLEVEL_ATTR_MAX + 1] = {
  1631. [NL802154_SECLEVEL_ATTR_LEVELS] = { .type = NLA_U8 },
  1632. [NL802154_SECLEVEL_ATTR_FRAME] = { .type = NLA_U32 },
  1633. [NL802154_SECLEVEL_ATTR_CMD_FRAME] = { .type = NLA_U32 },
  1634. [NL802154_SECLEVEL_ATTR_DEV_OVERRIDE] = { .type = NLA_U8 },
  1635. };
  1636. static int
  1637. llsec_parse_seclevel(struct nlattr *nla, struct ieee802154_llsec_seclevel *sl)
  1638. {
  1639. struct nlattr *attrs[NL802154_SECLEVEL_ATTR_MAX + 1];
  1640. if (!nla || nla_parse_nested(attrs, NL802154_SECLEVEL_ATTR_MAX, nla,
  1641. nl802154_seclevel_policy))
  1642. return -EINVAL;
  1643. memset(sl, 0, sizeof(*sl));
  1644. if (!attrs[NL802154_SECLEVEL_ATTR_LEVELS] ||
  1645. !attrs[NL802154_SECLEVEL_ATTR_FRAME] ||
  1646. !attrs[NL802154_SECLEVEL_ATTR_DEV_OVERRIDE])
  1647. return -EINVAL;
  1648. sl->sec_levels = nla_get_u8(attrs[NL802154_SECLEVEL_ATTR_LEVELS]);
  1649. sl->frame_type = nla_get_u32(attrs[NL802154_SECLEVEL_ATTR_FRAME]);
  1650. sl->device_override = nla_get_u8(attrs[NL802154_SECLEVEL_ATTR_DEV_OVERRIDE]);
  1651. if (sl->frame_type > NL802154_FRAME_MAX ||
  1652. (sl->device_override != 0 && sl->device_override != 1))
  1653. return -EINVAL;
  1654. if (sl->frame_type == NL802154_FRAME_CMD) {
  1655. if (!attrs[NL802154_SECLEVEL_ATTR_CMD_FRAME])
  1656. return -EINVAL;
  1657. sl->cmd_frame_id = nla_get_u32(attrs[NL802154_SECLEVEL_ATTR_CMD_FRAME]);
  1658. if (sl->cmd_frame_id > NL802154_CMD_FRAME_MAX)
  1659. return -EINVAL;
  1660. }
  1661. return 0;
  1662. }
  1663. static int nl802154_add_llsec_seclevel(struct sk_buff *skb,
  1664. struct genl_info *info)
  1665. {
  1666. struct cfg802154_registered_device *rdev = info->user_ptr[0];
  1667. struct net_device *dev = info->user_ptr[1];
  1668. struct wpan_dev *wpan_dev = dev->ieee802154_ptr;
  1669. struct ieee802154_llsec_seclevel sl;
  1670. if (llsec_parse_seclevel(info->attrs[NL802154_ATTR_SEC_LEVEL],
  1671. &sl) < 0)
  1672. return -EINVAL;
  1673. return rdev_add_seclevel(rdev, wpan_dev, &sl);
  1674. }
  1675. static int nl802154_del_llsec_seclevel(struct sk_buff *skb,
  1676. struct genl_info *info)
  1677. {
  1678. struct cfg802154_registered_device *rdev = info->user_ptr[0];
  1679. struct net_device *dev = info->user_ptr[1];
  1680. struct wpan_dev *wpan_dev = dev->ieee802154_ptr;
  1681. struct ieee802154_llsec_seclevel sl;
  1682. if (!info->attrs[NL802154_ATTR_SEC_LEVEL] ||
  1683. llsec_parse_seclevel(info->attrs[NL802154_ATTR_SEC_LEVEL],
  1684. &sl) < 0)
  1685. return -EINVAL;
  1686. return rdev_del_seclevel(rdev, wpan_dev, &sl);
  1687. }
  1688. #endif /* CONFIG_IEEE802154_NL802154_EXPERIMENTAL */
  1689. #define NL802154_FLAG_NEED_WPAN_PHY 0x01
  1690. #define NL802154_FLAG_NEED_NETDEV 0x02
  1691. #define NL802154_FLAG_NEED_RTNL 0x04
  1692. #define NL802154_FLAG_CHECK_NETDEV_UP 0x08
  1693. #define NL802154_FLAG_NEED_NETDEV_UP (NL802154_FLAG_NEED_NETDEV |\
  1694. NL802154_FLAG_CHECK_NETDEV_UP)
  1695. #define NL802154_FLAG_NEED_WPAN_DEV 0x10
  1696. #define NL802154_FLAG_NEED_WPAN_DEV_UP (NL802154_FLAG_NEED_WPAN_DEV |\
  1697. NL802154_FLAG_CHECK_NETDEV_UP)
  1698. static int nl802154_pre_doit(const struct genl_ops *ops, struct sk_buff *skb,
  1699. struct genl_info *info)
  1700. {
  1701. struct cfg802154_registered_device *rdev;
  1702. struct wpan_dev *wpan_dev;
  1703. struct net_device *dev;
  1704. bool rtnl = ops->internal_flags & NL802154_FLAG_NEED_RTNL;
  1705. if (rtnl)
  1706. rtnl_lock();
  1707. if (ops->internal_flags & NL802154_FLAG_NEED_WPAN_PHY) {
  1708. rdev = cfg802154_get_dev_from_info(genl_info_net(info), info);
  1709. if (IS_ERR(rdev)) {
  1710. if (rtnl)
  1711. rtnl_unlock();
  1712. return PTR_ERR(rdev);
  1713. }
  1714. info->user_ptr[0] = rdev;
  1715. } else if (ops->internal_flags & NL802154_FLAG_NEED_NETDEV ||
  1716. ops->internal_flags & NL802154_FLAG_NEED_WPAN_DEV) {
  1717. ASSERT_RTNL();
  1718. wpan_dev = __cfg802154_wpan_dev_from_attrs(genl_info_net(info),
  1719. info->attrs);
  1720. if (IS_ERR(wpan_dev)) {
  1721. if (rtnl)
  1722. rtnl_unlock();
  1723. return PTR_ERR(wpan_dev);
  1724. }
  1725. dev = wpan_dev->netdev;
  1726. rdev = wpan_phy_to_rdev(wpan_dev->wpan_phy);
  1727. if (ops->internal_flags & NL802154_FLAG_NEED_NETDEV) {
  1728. if (!dev) {
  1729. if (rtnl)
  1730. rtnl_unlock();
  1731. return -EINVAL;
  1732. }
  1733. info->user_ptr[1] = dev;
  1734. } else {
  1735. info->user_ptr[1] = wpan_dev;
  1736. }
  1737. if (dev) {
  1738. if (ops->internal_flags & NL802154_FLAG_CHECK_NETDEV_UP &&
  1739. !netif_running(dev)) {
  1740. if (rtnl)
  1741. rtnl_unlock();
  1742. return -ENETDOWN;
  1743. }
  1744. dev_hold(dev);
  1745. }
  1746. info->user_ptr[0] = rdev;
  1747. }
  1748. return 0;
  1749. }
  1750. static void nl802154_post_doit(const struct genl_ops *ops, struct sk_buff *skb,
  1751. struct genl_info *info)
  1752. {
  1753. if (info->user_ptr[1]) {
  1754. if (ops->internal_flags & NL802154_FLAG_NEED_WPAN_DEV) {
  1755. struct wpan_dev *wpan_dev = info->user_ptr[1];
  1756. if (wpan_dev->netdev)
  1757. dev_put(wpan_dev->netdev);
  1758. } else {
  1759. dev_put(info->user_ptr[1]);
  1760. }
  1761. }
  1762. if (ops->internal_flags & NL802154_FLAG_NEED_RTNL)
  1763. rtnl_unlock();
  1764. }
  1765. static const struct genl_ops nl802154_ops[] = {
  1766. {
  1767. .cmd = NL802154_CMD_GET_WPAN_PHY,
  1768. .doit = nl802154_get_wpan_phy,
  1769. .dumpit = nl802154_dump_wpan_phy,
  1770. .done = nl802154_dump_wpan_phy_done,
  1771. .policy = nl802154_policy,
  1772. /* can be retrieved by unprivileged users */
  1773. .internal_flags = NL802154_FLAG_NEED_WPAN_PHY |
  1774. NL802154_FLAG_NEED_RTNL,
  1775. },
  1776. {
  1777. .cmd = NL802154_CMD_GET_INTERFACE,
  1778. .doit = nl802154_get_interface,
  1779. .dumpit = nl802154_dump_interface,
  1780. .policy = nl802154_policy,
  1781. /* can be retrieved by unprivileged users */
  1782. .internal_flags = NL802154_FLAG_NEED_WPAN_DEV |
  1783. NL802154_FLAG_NEED_RTNL,
  1784. },
  1785. {
  1786. .cmd = NL802154_CMD_NEW_INTERFACE,
  1787. .doit = nl802154_new_interface,
  1788. .policy = nl802154_policy,
  1789. .flags = GENL_ADMIN_PERM,
  1790. .internal_flags = NL802154_FLAG_NEED_WPAN_PHY |
  1791. NL802154_FLAG_NEED_RTNL,
  1792. },
  1793. {
  1794. .cmd = NL802154_CMD_DEL_INTERFACE,
  1795. .doit = nl802154_del_interface,
  1796. .policy = nl802154_policy,
  1797. .flags = GENL_ADMIN_PERM,
  1798. .internal_flags = NL802154_FLAG_NEED_WPAN_DEV |
  1799. NL802154_FLAG_NEED_RTNL,
  1800. },
  1801. {
  1802. .cmd = NL802154_CMD_SET_CHANNEL,
  1803. .doit = nl802154_set_channel,
  1804. .policy = nl802154_policy,
  1805. .flags = GENL_ADMIN_PERM,
  1806. .internal_flags = NL802154_FLAG_NEED_WPAN_PHY |
  1807. NL802154_FLAG_NEED_RTNL,
  1808. },
  1809. {
  1810. .cmd = NL802154_CMD_SET_CCA_MODE,
  1811. .doit = nl802154_set_cca_mode,
  1812. .policy = nl802154_policy,
  1813. .flags = GENL_ADMIN_PERM,
  1814. .internal_flags = NL802154_FLAG_NEED_WPAN_PHY |
  1815. NL802154_FLAG_NEED_RTNL,
  1816. },
  1817. {
  1818. .cmd = NL802154_CMD_SET_CCA_ED_LEVEL,
  1819. .doit = nl802154_set_cca_ed_level,
  1820. .policy = nl802154_policy,
  1821. .flags = GENL_ADMIN_PERM,
  1822. .internal_flags = NL802154_FLAG_NEED_WPAN_PHY |
  1823. NL802154_FLAG_NEED_RTNL,
  1824. },
  1825. {
  1826. .cmd = NL802154_CMD_SET_TX_POWER,
  1827. .doit = nl802154_set_tx_power,
  1828. .policy = nl802154_policy,
  1829. .flags = GENL_ADMIN_PERM,
  1830. .internal_flags = NL802154_FLAG_NEED_WPAN_PHY |
  1831. NL802154_FLAG_NEED_RTNL,
  1832. },
  1833. {
  1834. .cmd = NL802154_CMD_SET_PAN_ID,
  1835. .doit = nl802154_set_pan_id,
  1836. .policy = nl802154_policy,
  1837. .flags = GENL_ADMIN_PERM,
  1838. .internal_flags = NL802154_FLAG_NEED_NETDEV |
  1839. NL802154_FLAG_NEED_RTNL,
  1840. },
  1841. {
  1842. .cmd = NL802154_CMD_SET_SHORT_ADDR,
  1843. .doit = nl802154_set_short_addr,
  1844. .policy = nl802154_policy,
  1845. .flags = GENL_ADMIN_PERM,
  1846. .internal_flags = NL802154_FLAG_NEED_NETDEV |
  1847. NL802154_FLAG_NEED_RTNL,
  1848. },
  1849. {
  1850. .cmd = NL802154_CMD_SET_BACKOFF_EXPONENT,
  1851. .doit = nl802154_set_backoff_exponent,
  1852. .policy = nl802154_policy,
  1853. .flags = GENL_ADMIN_PERM,
  1854. .internal_flags = NL802154_FLAG_NEED_NETDEV |
  1855. NL802154_FLAG_NEED_RTNL,
  1856. },
  1857. {
  1858. .cmd = NL802154_CMD_SET_MAX_CSMA_BACKOFFS,
  1859. .doit = nl802154_set_max_csma_backoffs,
  1860. .policy = nl802154_policy,
  1861. .flags = GENL_ADMIN_PERM,
  1862. .internal_flags = NL802154_FLAG_NEED_NETDEV |
  1863. NL802154_FLAG_NEED_RTNL,
  1864. },
  1865. {
  1866. .cmd = NL802154_CMD_SET_MAX_FRAME_RETRIES,
  1867. .doit = nl802154_set_max_frame_retries,
  1868. .policy = nl802154_policy,
  1869. .flags = GENL_ADMIN_PERM,
  1870. .internal_flags = NL802154_FLAG_NEED_NETDEV |
  1871. NL802154_FLAG_NEED_RTNL,
  1872. },
  1873. {
  1874. .cmd = NL802154_CMD_SET_LBT_MODE,
  1875. .doit = nl802154_set_lbt_mode,
  1876. .policy = nl802154_policy,
  1877. .flags = GENL_ADMIN_PERM,
  1878. .internal_flags = NL802154_FLAG_NEED_NETDEV |
  1879. NL802154_FLAG_NEED_RTNL,
  1880. },
  1881. {
  1882. .cmd = NL802154_CMD_SET_ACKREQ_DEFAULT,
  1883. .doit = nl802154_set_ackreq_default,
  1884. .policy = nl802154_policy,
  1885. .flags = GENL_ADMIN_PERM,
  1886. .internal_flags = NL802154_FLAG_NEED_NETDEV |
  1887. NL802154_FLAG_NEED_RTNL,
  1888. },
  1889. #ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL
  1890. {
  1891. .cmd = NL802154_CMD_SET_SEC_PARAMS,
  1892. .doit = nl802154_set_llsec_params,
  1893. .policy = nl802154_policy,
  1894. .flags = GENL_ADMIN_PERM,
  1895. .internal_flags = NL802154_FLAG_NEED_NETDEV |
  1896. NL802154_FLAG_NEED_RTNL,
  1897. },
  1898. {
  1899. .cmd = NL802154_CMD_GET_SEC_KEY,
  1900. /* TODO .doit by matching key id? */
  1901. .dumpit = nl802154_dump_llsec_key,
  1902. .policy = nl802154_policy,
  1903. .flags = GENL_ADMIN_PERM,
  1904. .internal_flags = NL802154_FLAG_NEED_NETDEV |
  1905. NL802154_FLAG_NEED_RTNL,
  1906. },
  1907. {
  1908. .cmd = NL802154_CMD_NEW_SEC_KEY,
  1909. .doit = nl802154_add_llsec_key,
  1910. .policy = nl802154_policy,
  1911. .flags = GENL_ADMIN_PERM,
  1912. .internal_flags = NL802154_FLAG_NEED_NETDEV |
  1913. NL802154_FLAG_NEED_RTNL,
  1914. },
  1915. {
  1916. .cmd = NL802154_CMD_DEL_SEC_KEY,
  1917. .doit = nl802154_del_llsec_key,
  1918. .policy = nl802154_policy,
  1919. .flags = GENL_ADMIN_PERM,
  1920. .internal_flags = NL802154_FLAG_NEED_NETDEV |
  1921. NL802154_FLAG_NEED_RTNL,
  1922. },
  1923. /* TODO unique identifier must short+pan OR extended_addr */
  1924. {
  1925. .cmd = NL802154_CMD_GET_SEC_DEV,
  1926. /* TODO .doit by matching extended_addr? */
  1927. .dumpit = nl802154_dump_llsec_dev,
  1928. .policy = nl802154_policy,
  1929. .flags = GENL_ADMIN_PERM,
  1930. .internal_flags = NL802154_FLAG_NEED_NETDEV |
  1931. NL802154_FLAG_NEED_RTNL,
  1932. },
  1933. {
  1934. .cmd = NL802154_CMD_NEW_SEC_DEV,
  1935. .doit = nl802154_add_llsec_dev,
  1936. .policy = nl802154_policy,
  1937. .flags = GENL_ADMIN_PERM,
  1938. .internal_flags = NL802154_FLAG_NEED_NETDEV |
  1939. NL802154_FLAG_NEED_RTNL,
  1940. },
  1941. {
  1942. .cmd = NL802154_CMD_DEL_SEC_DEV,
  1943. .doit = nl802154_del_llsec_dev,
  1944. .policy = nl802154_policy,
  1945. .flags = GENL_ADMIN_PERM,
  1946. .internal_flags = NL802154_FLAG_NEED_NETDEV |
  1947. NL802154_FLAG_NEED_RTNL,
  1948. },
  1949. /* TODO remove complete devkey, put it as nested? */
  1950. {
  1951. .cmd = NL802154_CMD_GET_SEC_DEVKEY,
  1952. /* TODO doit by matching ??? */
  1953. .dumpit = nl802154_dump_llsec_devkey,
  1954. .policy = nl802154_policy,
  1955. .flags = GENL_ADMIN_PERM,
  1956. .internal_flags = NL802154_FLAG_NEED_NETDEV |
  1957. NL802154_FLAG_NEED_RTNL,
  1958. },
  1959. {
  1960. .cmd = NL802154_CMD_NEW_SEC_DEVKEY,
  1961. .doit = nl802154_add_llsec_devkey,
  1962. .policy = nl802154_policy,
  1963. .flags = GENL_ADMIN_PERM,
  1964. .internal_flags = NL802154_FLAG_NEED_NETDEV |
  1965. NL802154_FLAG_NEED_RTNL,
  1966. },
  1967. {
  1968. .cmd = NL802154_CMD_DEL_SEC_DEVKEY,
  1969. .doit = nl802154_del_llsec_devkey,
  1970. .policy = nl802154_policy,
  1971. .flags = GENL_ADMIN_PERM,
  1972. .internal_flags = NL802154_FLAG_NEED_NETDEV |
  1973. NL802154_FLAG_NEED_RTNL,
  1974. },
  1975. {
  1976. .cmd = NL802154_CMD_GET_SEC_LEVEL,
  1977. /* TODO .doit by matching frame_type? */
  1978. .dumpit = nl802154_dump_llsec_seclevel,
  1979. .policy = nl802154_policy,
  1980. .flags = GENL_ADMIN_PERM,
  1981. .internal_flags = NL802154_FLAG_NEED_NETDEV |
  1982. NL802154_FLAG_NEED_RTNL,
  1983. },
  1984. {
  1985. .cmd = NL802154_CMD_NEW_SEC_LEVEL,
  1986. .doit = nl802154_add_llsec_seclevel,
  1987. .policy = nl802154_policy,
  1988. .flags = GENL_ADMIN_PERM,
  1989. .internal_flags = NL802154_FLAG_NEED_NETDEV |
  1990. NL802154_FLAG_NEED_RTNL,
  1991. },
  1992. {
  1993. .cmd = NL802154_CMD_DEL_SEC_LEVEL,
  1994. /* TODO match frame_type only? */
  1995. .doit = nl802154_del_llsec_seclevel,
  1996. .policy = nl802154_policy,
  1997. .flags = GENL_ADMIN_PERM,
  1998. .internal_flags = NL802154_FLAG_NEED_NETDEV |
  1999. NL802154_FLAG_NEED_RTNL,
  2000. },
  2001. #endif /* CONFIG_IEEE802154_NL802154_EXPERIMENTAL */
  2002. };
  2003. /* initialisation/exit functions */
  2004. int nl802154_init(void)
  2005. {
  2006. return genl_register_family_with_ops_groups(&nl802154_fam, nl802154_ops,
  2007. nl802154_mcgrps);
  2008. }
  2009. void nl802154_exit(void)
  2010. {
  2011. genl_unregister_family(&nl802154_fam);
  2012. }