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