nl802154.c 67 KB

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