GNU Linux-libre 4.4.288-gnu1
[releases.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 (wpan_dev->iftype == NL802154_IFTYPE_MONITOR)
847                 goto out;
848
849         if (nl802154_get_llsec_params(msg, rdev, wpan_dev) < 0)
850                 goto nla_put_failure;
851
852 out:
853 #endif /* CONFIG_IEEE802154_NL802154_EXPERIMENTAL */
854
855         genlmsg_end(msg, hdr);
856         return 0;
857
858 nla_put_failure:
859         genlmsg_cancel(msg, hdr);
860         return -EMSGSIZE;
861 }
862
863 static int
864 nl802154_dump_interface(struct sk_buff *skb, struct netlink_callback *cb)
865 {
866         int wp_idx = 0;
867         int if_idx = 0;
868         int wp_start = cb->args[0];
869         int if_start = cb->args[1];
870         struct cfg802154_registered_device *rdev;
871         struct wpan_dev *wpan_dev;
872
873         rtnl_lock();
874         list_for_each_entry(rdev, &cfg802154_rdev_list, list) {
875                 /* TODO netns compare */
876                 if (wp_idx < wp_start) {
877                         wp_idx++;
878                         continue;
879                 }
880                 if_idx = 0;
881
882                 list_for_each_entry(wpan_dev, &rdev->wpan_dev_list, list) {
883                         if (if_idx < if_start) {
884                                 if_idx++;
885                                 continue;
886                         }
887                         if (nl802154_send_iface(skb, NETLINK_CB(cb->skb).portid,
888                                                 cb->nlh->nlmsg_seq, NLM_F_MULTI,
889                                                 rdev, wpan_dev) < 0) {
890                                 goto out;
891                         }
892                         if_idx++;
893                 }
894
895                 wp_idx++;
896         }
897 out:
898         rtnl_unlock();
899
900         cb->args[0] = wp_idx;
901         cb->args[1] = if_idx;
902
903         return skb->len;
904 }
905
906 static int nl802154_get_interface(struct sk_buff *skb, struct genl_info *info)
907 {
908         struct sk_buff *msg;
909         struct cfg802154_registered_device *rdev = info->user_ptr[0];
910         struct wpan_dev *wdev = info->user_ptr[1];
911
912         msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
913         if (!msg)
914                 return -ENOMEM;
915
916         if (nl802154_send_iface(msg, info->snd_portid, info->snd_seq, 0,
917                                 rdev, wdev) < 0) {
918                 nlmsg_free(msg);
919                 return -ENOBUFS;
920         }
921
922         return genlmsg_reply(msg, info);
923 }
924
925 static int nl802154_new_interface(struct sk_buff *skb, struct genl_info *info)
926 {
927         struct cfg802154_registered_device *rdev = info->user_ptr[0];
928         enum nl802154_iftype type = NL802154_IFTYPE_UNSPEC;
929         __le64 extended_addr = cpu_to_le64(0x0000000000000000ULL);
930
931         /* TODO avoid failing a new interface
932          * creation due to pending removal?
933          */
934
935         if (!info->attrs[NL802154_ATTR_IFNAME])
936                 return -EINVAL;
937
938         if (info->attrs[NL802154_ATTR_IFTYPE]) {
939                 type = nla_get_u32(info->attrs[NL802154_ATTR_IFTYPE]);
940                 if (type > NL802154_IFTYPE_MAX ||
941                     !(rdev->wpan_phy.supported.iftypes & BIT(type)))
942                         return -EINVAL;
943         }
944
945         if (info->attrs[NL802154_ATTR_EXTENDED_ADDR])
946                 extended_addr = nla_get_le64(info->attrs[NL802154_ATTR_EXTENDED_ADDR]);
947
948         if (!rdev->ops->add_virtual_intf)
949                 return -EOPNOTSUPP;
950
951         return rdev_add_virtual_intf(rdev,
952                                      nla_data(info->attrs[NL802154_ATTR_IFNAME]),
953                                      NET_NAME_USER, type, extended_addr);
954 }
955
956 static int nl802154_del_interface(struct sk_buff *skb, struct genl_info *info)
957 {
958         struct cfg802154_registered_device *rdev = info->user_ptr[0];
959         struct wpan_dev *wpan_dev = info->user_ptr[1];
960
961         if (!rdev->ops->del_virtual_intf)
962                 return -EOPNOTSUPP;
963
964         /* If we remove a wpan device without a netdev then clear
965          * user_ptr[1] so that nl802154_post_doit won't dereference it
966          * to check if it needs to do dev_put(). Otherwise it crashes
967          * since the wpan_dev has been freed, unlike with a netdev where
968          * we need the dev_put() for the netdev to really be freed.
969          */
970         if (!wpan_dev->netdev)
971                 info->user_ptr[1] = NULL;
972
973         return rdev_del_virtual_intf(rdev, wpan_dev);
974 }
975
976 static int nl802154_set_channel(struct sk_buff *skb, struct genl_info *info)
977 {
978         struct cfg802154_registered_device *rdev = info->user_ptr[0];
979         u8 channel, page;
980
981         if (!info->attrs[NL802154_ATTR_PAGE] ||
982             !info->attrs[NL802154_ATTR_CHANNEL])
983                 return -EINVAL;
984
985         page = nla_get_u8(info->attrs[NL802154_ATTR_PAGE]);
986         channel = nla_get_u8(info->attrs[NL802154_ATTR_CHANNEL]);
987
988         /* check 802.15.4 constraints */
989         if (page > IEEE802154_MAX_PAGE || channel > IEEE802154_MAX_CHANNEL ||
990             !(rdev->wpan_phy.supported.channels[page] & BIT(channel)))
991                 return -EINVAL;
992
993         return rdev_set_channel(rdev, page, channel);
994 }
995
996 static int nl802154_set_cca_mode(struct sk_buff *skb, struct genl_info *info)
997 {
998         struct cfg802154_registered_device *rdev = info->user_ptr[0];
999         struct wpan_phy_cca cca;
1000
1001         if (!(rdev->wpan_phy.flags & WPAN_PHY_FLAG_CCA_MODE))
1002                 return -EOPNOTSUPP;
1003
1004         if (!info->attrs[NL802154_ATTR_CCA_MODE])
1005                 return -EINVAL;
1006
1007         cca.mode = nla_get_u32(info->attrs[NL802154_ATTR_CCA_MODE]);
1008         /* checking 802.15.4 constraints */
1009         if (cca.mode < NL802154_CCA_ENERGY ||
1010             cca.mode > NL802154_CCA_ATTR_MAX ||
1011             !(rdev->wpan_phy.supported.cca_modes & BIT(cca.mode)))
1012                 return -EINVAL;
1013
1014         if (cca.mode == NL802154_CCA_ENERGY_CARRIER) {
1015                 if (!info->attrs[NL802154_ATTR_CCA_OPT])
1016                         return -EINVAL;
1017
1018                 cca.opt = nla_get_u32(info->attrs[NL802154_ATTR_CCA_OPT]);
1019                 if (cca.opt > NL802154_CCA_OPT_ATTR_MAX ||
1020                     !(rdev->wpan_phy.supported.cca_opts & BIT(cca.opt)))
1021                         return -EINVAL;
1022         }
1023
1024         return rdev_set_cca_mode(rdev, &cca);
1025 }
1026
1027 static int nl802154_set_cca_ed_level(struct sk_buff *skb, struct genl_info *info)
1028 {
1029         struct cfg802154_registered_device *rdev = info->user_ptr[0];
1030         s32 ed_level;
1031         int i;
1032
1033         if (!(rdev->wpan_phy.flags & WPAN_PHY_FLAG_CCA_ED_LEVEL))
1034                 return -EOPNOTSUPP;
1035
1036         if (!info->attrs[NL802154_ATTR_CCA_ED_LEVEL])
1037                 return -EINVAL;
1038
1039         ed_level = nla_get_s32(info->attrs[NL802154_ATTR_CCA_ED_LEVEL]);
1040
1041         for (i = 0; i < rdev->wpan_phy.supported.cca_ed_levels_size; i++) {
1042                 if (ed_level == rdev->wpan_phy.supported.cca_ed_levels[i])
1043                         return rdev_set_cca_ed_level(rdev, ed_level);
1044         }
1045
1046         return -EINVAL;
1047 }
1048
1049 static int nl802154_set_tx_power(struct sk_buff *skb, struct genl_info *info)
1050 {
1051         struct cfg802154_registered_device *rdev = info->user_ptr[0];
1052         s32 power;
1053         int i;
1054
1055         if (!(rdev->wpan_phy.flags & WPAN_PHY_FLAG_TXPOWER))
1056                 return -EOPNOTSUPP;
1057
1058         if (!info->attrs[NL802154_ATTR_TX_POWER])
1059                 return -EINVAL;
1060
1061         power = nla_get_s32(info->attrs[NL802154_ATTR_TX_POWER]);
1062
1063         for (i = 0; i < rdev->wpan_phy.supported.tx_powers_size; i++) {
1064                 if (power == rdev->wpan_phy.supported.tx_powers[i])
1065                         return rdev_set_tx_power(rdev, power);
1066         }
1067
1068         return -EINVAL;
1069 }
1070
1071 static int nl802154_set_pan_id(struct sk_buff *skb, struct genl_info *info)
1072 {
1073         struct cfg802154_registered_device *rdev = info->user_ptr[0];
1074         struct net_device *dev = info->user_ptr[1];
1075         struct wpan_dev *wpan_dev = dev->ieee802154_ptr;
1076         __le16 pan_id;
1077
1078         /* conflict here while tx/rx calls */
1079         if (netif_running(dev))
1080                 return -EBUSY;
1081
1082         /* don't change address fields on monitor */
1083         if (wpan_dev->iftype == NL802154_IFTYPE_MONITOR ||
1084             !info->attrs[NL802154_ATTR_PAN_ID])
1085                 return -EINVAL;
1086
1087         pan_id = nla_get_le16(info->attrs[NL802154_ATTR_PAN_ID]);
1088
1089         /* TODO
1090          * I am not sure about to check here on broadcast pan_id.
1091          * Broadcast is a valid setting, comment from 802.15.4:
1092          * If this value is 0xffff, the device is not associated.
1093          *
1094          * This could useful to simple deassociate an device.
1095          */
1096         if (pan_id == cpu_to_le16(IEEE802154_PAN_ID_BROADCAST))
1097                 return -EINVAL;
1098
1099         return rdev_set_pan_id(rdev, wpan_dev, pan_id);
1100 }
1101
1102 static int nl802154_set_short_addr(struct sk_buff *skb, struct genl_info *info)
1103 {
1104         struct cfg802154_registered_device *rdev = info->user_ptr[0];
1105         struct net_device *dev = info->user_ptr[1];
1106         struct wpan_dev *wpan_dev = dev->ieee802154_ptr;
1107         __le16 short_addr;
1108
1109         /* conflict here while tx/rx calls */
1110         if (netif_running(dev))
1111                 return -EBUSY;
1112
1113         /* don't change address fields on monitor */
1114         if (wpan_dev->iftype == NL802154_IFTYPE_MONITOR ||
1115             !info->attrs[NL802154_ATTR_SHORT_ADDR])
1116                 return -EINVAL;
1117
1118         short_addr = nla_get_le16(info->attrs[NL802154_ATTR_SHORT_ADDR]);
1119
1120         /* TODO
1121          * I am not sure about to check here on broadcast short_addr.
1122          * Broadcast is a valid setting, comment from 802.15.4:
1123          * A value of 0xfffe indicates that the device has
1124          * associated but has not been allocated an address. A
1125          * value of 0xffff indicates that the device does not
1126          * have a short address.
1127          *
1128          * I think we should allow to set these settings but
1129          * don't allow to allow socket communication with it.
1130          */
1131         if (short_addr == cpu_to_le16(IEEE802154_ADDR_SHORT_UNSPEC) ||
1132             short_addr == cpu_to_le16(IEEE802154_ADDR_SHORT_BROADCAST))
1133                 return -EINVAL;
1134
1135         return rdev_set_short_addr(rdev, wpan_dev, short_addr);
1136 }
1137
1138 static int
1139 nl802154_set_backoff_exponent(struct sk_buff *skb, struct genl_info *info)
1140 {
1141         struct cfg802154_registered_device *rdev = info->user_ptr[0];
1142         struct net_device *dev = info->user_ptr[1];
1143         struct wpan_dev *wpan_dev = dev->ieee802154_ptr;
1144         u8 min_be, max_be;
1145
1146         /* should be set on netif open inside phy settings */
1147         if (netif_running(dev))
1148                 return -EBUSY;
1149
1150         if (!info->attrs[NL802154_ATTR_MIN_BE] ||
1151             !info->attrs[NL802154_ATTR_MAX_BE])
1152                 return -EINVAL;
1153
1154         min_be = nla_get_u8(info->attrs[NL802154_ATTR_MIN_BE]);
1155         max_be = nla_get_u8(info->attrs[NL802154_ATTR_MAX_BE]);
1156
1157         /* check 802.15.4 constraints */
1158         if (min_be < rdev->wpan_phy.supported.min_minbe ||
1159             min_be > rdev->wpan_phy.supported.max_minbe ||
1160             max_be < rdev->wpan_phy.supported.min_maxbe ||
1161             max_be > rdev->wpan_phy.supported.max_maxbe ||
1162             min_be > max_be)
1163                 return -EINVAL;
1164
1165         return rdev_set_backoff_exponent(rdev, wpan_dev, min_be, max_be);
1166 }
1167
1168 static int
1169 nl802154_set_max_csma_backoffs(struct sk_buff *skb, struct genl_info *info)
1170 {
1171         struct cfg802154_registered_device *rdev = info->user_ptr[0];
1172         struct net_device *dev = info->user_ptr[1];
1173         struct wpan_dev *wpan_dev = dev->ieee802154_ptr;
1174         u8 max_csma_backoffs;
1175
1176         /* conflict here while other running iface settings */
1177         if (netif_running(dev))
1178                 return -EBUSY;
1179
1180         if (!info->attrs[NL802154_ATTR_MAX_CSMA_BACKOFFS])
1181                 return -EINVAL;
1182
1183         max_csma_backoffs = nla_get_u8(
1184                         info->attrs[NL802154_ATTR_MAX_CSMA_BACKOFFS]);
1185
1186         /* check 802.15.4 constraints */
1187         if (max_csma_backoffs < rdev->wpan_phy.supported.min_csma_backoffs ||
1188             max_csma_backoffs > rdev->wpan_phy.supported.max_csma_backoffs)
1189                 return -EINVAL;
1190
1191         return rdev_set_max_csma_backoffs(rdev, wpan_dev, max_csma_backoffs);
1192 }
1193
1194 static int
1195 nl802154_set_max_frame_retries(struct sk_buff *skb, struct genl_info *info)
1196 {
1197         struct cfg802154_registered_device *rdev = info->user_ptr[0];
1198         struct net_device *dev = info->user_ptr[1];
1199         struct wpan_dev *wpan_dev = dev->ieee802154_ptr;
1200         s8 max_frame_retries;
1201
1202         if (netif_running(dev))
1203                 return -EBUSY;
1204
1205         if (!info->attrs[NL802154_ATTR_MAX_FRAME_RETRIES])
1206                 return -EINVAL;
1207
1208         max_frame_retries = nla_get_s8(
1209                         info->attrs[NL802154_ATTR_MAX_FRAME_RETRIES]);
1210
1211         /* check 802.15.4 constraints */
1212         if (max_frame_retries < rdev->wpan_phy.supported.min_frame_retries ||
1213             max_frame_retries > rdev->wpan_phy.supported.max_frame_retries)
1214                 return -EINVAL;
1215
1216         return rdev_set_max_frame_retries(rdev, wpan_dev, max_frame_retries);
1217 }
1218
1219 static int nl802154_set_lbt_mode(struct sk_buff *skb, struct genl_info *info)
1220 {
1221         struct cfg802154_registered_device *rdev = info->user_ptr[0];
1222         struct net_device *dev = info->user_ptr[1];
1223         struct wpan_dev *wpan_dev = dev->ieee802154_ptr;
1224         int mode;
1225
1226         if (netif_running(dev))
1227                 return -EBUSY;
1228
1229         if (!info->attrs[NL802154_ATTR_LBT_MODE])
1230                 return -EINVAL;
1231
1232         mode = nla_get_u8(info->attrs[NL802154_ATTR_LBT_MODE]);
1233
1234         if (mode != 0 && mode != 1)
1235                 return -EINVAL;
1236
1237         if (!wpan_phy_supported_bool(mode, rdev->wpan_phy.supported.lbt))
1238                 return -EINVAL;
1239
1240         return rdev_set_lbt_mode(rdev, wpan_dev, mode);
1241 }
1242
1243 static int
1244 nl802154_set_ackreq_default(struct sk_buff *skb, struct genl_info *info)
1245 {
1246         struct cfg802154_registered_device *rdev = info->user_ptr[0];
1247         struct net_device *dev = info->user_ptr[1];
1248         struct wpan_dev *wpan_dev = dev->ieee802154_ptr;
1249         int ackreq;
1250
1251         if (netif_running(dev))
1252                 return -EBUSY;
1253
1254         if (!info->attrs[NL802154_ATTR_ACKREQ_DEFAULT])
1255                 return -EINVAL;
1256
1257         ackreq = nla_get_u8(info->attrs[NL802154_ATTR_ACKREQ_DEFAULT]);
1258
1259         if (ackreq != 0 && ackreq != 1)
1260                 return -EINVAL;
1261
1262         return rdev_set_ackreq_default(rdev, wpan_dev, ackreq);
1263 }
1264
1265 #ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL
1266 static const struct nla_policy nl802154_dev_addr_policy[NL802154_DEV_ADDR_ATTR_MAX + 1] = {
1267         [NL802154_DEV_ADDR_ATTR_PAN_ID] = { .type = NLA_U16 },
1268         [NL802154_DEV_ADDR_ATTR_MODE] = { .type = NLA_U32 },
1269         [NL802154_DEV_ADDR_ATTR_SHORT] = { .type = NLA_U16 },
1270         [NL802154_DEV_ADDR_ATTR_EXTENDED] = { .type = NLA_U64 },
1271 };
1272
1273 static int
1274 ieee802154_llsec_parse_dev_addr(struct nlattr *nla,
1275                                 struct ieee802154_addr *addr)
1276 {
1277         struct nlattr *attrs[NL802154_DEV_ADDR_ATTR_MAX + 1];
1278
1279         if (!nla || nla_parse_nested(attrs, NL802154_DEV_ADDR_ATTR_MAX, nla,
1280                                      nl802154_dev_addr_policy))
1281                 return -EINVAL;
1282
1283         if (!attrs[NL802154_DEV_ADDR_ATTR_PAN_ID] &&
1284             !attrs[NL802154_DEV_ADDR_ATTR_MODE] &&
1285             !(attrs[NL802154_DEV_ADDR_ATTR_SHORT] ||
1286               attrs[NL802154_DEV_ADDR_ATTR_EXTENDED]))
1287                 return -EINVAL;
1288
1289         addr->pan_id = nla_get_le16(attrs[NL802154_DEV_ADDR_ATTR_PAN_ID]);
1290         addr->mode = nla_get_u32(attrs[NL802154_DEV_ADDR_ATTR_MODE]);
1291         switch (addr->mode) {
1292         case NL802154_DEV_ADDR_SHORT:
1293                 addr->short_addr = nla_get_le16(attrs[NL802154_DEV_ADDR_ATTR_SHORT]);
1294                 break;
1295         case NL802154_DEV_ADDR_EXTENDED:
1296                 addr->extended_addr = nla_get_le64(attrs[NL802154_DEV_ADDR_ATTR_EXTENDED]);
1297                 break;
1298         default:
1299                 return -EINVAL;
1300         }
1301
1302         return 0;
1303 }
1304
1305 static const struct nla_policy nl802154_key_id_policy[NL802154_KEY_ID_ATTR_MAX + 1] = {
1306         [NL802154_KEY_ID_ATTR_MODE] = { .type = NLA_U32 },
1307         [NL802154_KEY_ID_ATTR_INDEX] = { .type = NLA_U8 },
1308         [NL802154_KEY_ID_ATTR_IMPLICIT] = { .type = NLA_NESTED },
1309         [NL802154_KEY_ID_ATTR_SOURCE_SHORT] = { .type = NLA_U32 },
1310         [NL802154_KEY_ID_ATTR_SOURCE_EXTENDED] = { .type = NLA_U64 },
1311 };
1312
1313 static int
1314 ieee802154_llsec_parse_key_id(struct nlattr *nla,
1315                               struct ieee802154_llsec_key_id *desc)
1316 {
1317         struct nlattr *attrs[NL802154_KEY_ID_ATTR_MAX + 1];
1318
1319         if (!nla || nla_parse_nested(attrs, NL802154_KEY_ID_ATTR_MAX, nla,
1320                                      nl802154_key_id_policy))
1321                 return -EINVAL;
1322
1323         if (!attrs[NL802154_KEY_ID_ATTR_MODE])
1324                 return -EINVAL;
1325
1326         desc->mode = nla_get_u32(attrs[NL802154_KEY_ID_ATTR_MODE]);
1327         switch (desc->mode) {
1328         case NL802154_KEY_ID_MODE_IMPLICIT:
1329                 if (!attrs[NL802154_KEY_ID_ATTR_IMPLICIT])
1330                         return -EINVAL;
1331
1332                 if (ieee802154_llsec_parse_dev_addr(attrs[NL802154_KEY_ID_ATTR_IMPLICIT],
1333                                                     &desc->device_addr) < 0)
1334                         return -EINVAL;
1335                 break;
1336         case NL802154_KEY_ID_MODE_INDEX:
1337                 break;
1338         case NL802154_KEY_ID_MODE_INDEX_SHORT:
1339                 if (!attrs[NL802154_KEY_ID_ATTR_SOURCE_SHORT])
1340                         return -EINVAL;
1341
1342                 desc->short_source = nla_get_le32(attrs[NL802154_KEY_ID_ATTR_SOURCE_SHORT]);
1343                 break;
1344         case NL802154_KEY_ID_MODE_INDEX_EXTENDED:
1345                 if (!attrs[NL802154_KEY_ID_ATTR_SOURCE_EXTENDED])
1346                         return -EINVAL;
1347
1348                 desc->extended_source = nla_get_le64(attrs[NL802154_KEY_ID_ATTR_SOURCE_EXTENDED]);
1349                 break;
1350         default:
1351                 return -EINVAL;
1352         }
1353
1354         if (desc->mode != NL802154_KEY_ID_MODE_IMPLICIT) {
1355                 if (!attrs[NL802154_KEY_ID_ATTR_INDEX])
1356                         return -EINVAL;
1357
1358                 /* TODO change id to idx */
1359                 desc->id = nla_get_u8(attrs[NL802154_KEY_ID_ATTR_INDEX]);
1360         }
1361
1362         return 0;
1363 }
1364
1365 static int nl802154_set_llsec_params(struct sk_buff *skb,
1366                                      struct genl_info *info)
1367 {
1368         struct cfg802154_registered_device *rdev = info->user_ptr[0];
1369         struct net_device *dev = info->user_ptr[1];
1370         struct wpan_dev *wpan_dev = dev->ieee802154_ptr;
1371         struct ieee802154_llsec_params params;
1372         u32 changed = 0;
1373         int ret;
1374
1375         if (wpan_dev->iftype == NL802154_IFTYPE_MONITOR)
1376                 return -EOPNOTSUPP;
1377
1378         if (info->attrs[NL802154_ATTR_SEC_ENABLED]) {
1379                 u8 enabled;
1380
1381                 enabled = nla_get_u8(info->attrs[NL802154_ATTR_SEC_ENABLED]);
1382                 if (enabled != 0 && enabled != 1)
1383                         return -EINVAL;
1384
1385                 params.enabled = nla_get_u8(info->attrs[NL802154_ATTR_SEC_ENABLED]);
1386                 changed |= IEEE802154_LLSEC_PARAM_ENABLED;
1387         }
1388
1389         if (info->attrs[NL802154_ATTR_SEC_OUT_KEY_ID]) {
1390                 ret = ieee802154_llsec_parse_key_id(info->attrs[NL802154_ATTR_SEC_OUT_KEY_ID],
1391                                                     &params.out_key);
1392                 if (ret < 0)
1393                         return ret;
1394
1395                 changed |= IEEE802154_LLSEC_PARAM_OUT_KEY;
1396         }
1397
1398         if (info->attrs[NL802154_ATTR_SEC_OUT_LEVEL]) {
1399                 params.out_level = nla_get_u32(info->attrs[NL802154_ATTR_SEC_OUT_LEVEL]);
1400                 if (params.out_level > NL802154_SECLEVEL_MAX)
1401                         return -EINVAL;
1402
1403                 changed |= IEEE802154_LLSEC_PARAM_OUT_LEVEL;
1404         }
1405
1406         if (info->attrs[NL802154_ATTR_SEC_FRAME_COUNTER]) {
1407                 params.frame_counter = nla_get_be32(info->attrs[NL802154_ATTR_SEC_FRAME_COUNTER]);
1408                 changed |= IEEE802154_LLSEC_PARAM_FRAME_COUNTER;
1409         }
1410
1411         return rdev_set_llsec_params(rdev, wpan_dev, &params, changed);
1412 }
1413
1414 static int nl802154_send_key(struct sk_buff *msg, u32 cmd, u32 portid,
1415                              u32 seq, int flags,
1416                              struct cfg802154_registered_device *rdev,
1417                              struct net_device *dev,
1418                              const struct ieee802154_llsec_key_entry *key)
1419 {
1420         void *hdr;
1421         u32 commands[NL802154_CMD_FRAME_NR_IDS / 32];
1422         struct nlattr *nl_key, *nl_key_id;
1423
1424         hdr = nl802154hdr_put(msg, portid, seq, flags, cmd);
1425         if (!hdr)
1426                 return -1;
1427
1428         if (nla_put_u32(msg, NL802154_ATTR_IFINDEX, dev->ifindex))
1429                 goto nla_put_failure;
1430
1431         nl_key = nla_nest_start(msg, NL802154_ATTR_SEC_KEY);
1432         if (!nl_key)
1433                 goto nla_put_failure;
1434
1435         nl_key_id = nla_nest_start(msg, NL802154_KEY_ATTR_ID);
1436         if (!nl_key_id)
1437                 goto nla_put_failure;
1438
1439         if (ieee802154_llsec_send_key_id(msg, &key->id) < 0)
1440                 goto nla_put_failure;
1441
1442         nla_nest_end(msg, nl_key_id);
1443
1444         if (nla_put_u8(msg, NL802154_KEY_ATTR_USAGE_FRAMES,
1445                        key->key->frame_types))
1446                 goto nla_put_failure;
1447
1448         if (key->key->frame_types & BIT(NL802154_FRAME_CMD)) {
1449                 /* TODO for each nested */
1450                 memset(commands, 0, sizeof(commands));
1451                 commands[7] = key->key->cmd_frame_ids;
1452                 if (nla_put(msg, NL802154_KEY_ATTR_USAGE_CMDS,
1453                             sizeof(commands), commands))
1454                         goto nla_put_failure;
1455         }
1456
1457         if (nla_put(msg, NL802154_KEY_ATTR_BYTES, NL802154_KEY_SIZE,
1458                     key->key->key))
1459                 goto nla_put_failure;
1460
1461         nla_nest_end(msg, nl_key);
1462         genlmsg_end(msg, hdr);
1463
1464         return 0;
1465
1466 nla_put_failure:
1467         genlmsg_cancel(msg, hdr);
1468         return -EMSGSIZE;
1469 }
1470
1471 static int
1472 nl802154_dump_llsec_key(struct sk_buff *skb, struct netlink_callback *cb)
1473 {
1474         struct cfg802154_registered_device *rdev = NULL;
1475         struct ieee802154_llsec_key_entry *key;
1476         struct ieee802154_llsec_table *table;
1477         struct wpan_dev *wpan_dev;
1478         int err;
1479
1480         err = nl802154_prepare_wpan_dev_dump(skb, cb, &rdev, &wpan_dev);
1481         if (err)
1482                 return err;
1483
1484         if (wpan_dev->iftype == NL802154_IFTYPE_MONITOR) {
1485                 err = skb->len;
1486                 goto out_err;
1487         }
1488
1489         if (!wpan_dev->netdev) {
1490                 err = -EINVAL;
1491                 goto out_err;
1492         }
1493
1494         rdev_lock_llsec_table(rdev, wpan_dev);
1495         rdev_get_llsec_table(rdev, wpan_dev, &table);
1496
1497         /* TODO make it like station dump */
1498         if (cb->args[2])
1499                 goto out;
1500
1501         list_for_each_entry(key, &table->keys, list) {
1502                 if (nl802154_send_key(skb, NL802154_CMD_NEW_SEC_KEY,
1503                                       NETLINK_CB(cb->skb).portid,
1504                                       cb->nlh->nlmsg_seq, NLM_F_MULTI,
1505                                       rdev, wpan_dev->netdev, key) < 0) {
1506                         /* TODO */
1507                         err = -EIO;
1508                         rdev_unlock_llsec_table(rdev, wpan_dev);
1509                         goto out_err;
1510                 }
1511         }
1512
1513         cb->args[2] = 1;
1514
1515 out:
1516         rdev_unlock_llsec_table(rdev, wpan_dev);
1517         err = skb->len;
1518 out_err:
1519         nl802154_finish_wpan_dev_dump(rdev);
1520
1521         return err;
1522 }
1523
1524 static const struct nla_policy nl802154_key_policy[NL802154_KEY_ATTR_MAX + 1] = {
1525         [NL802154_KEY_ATTR_ID] = { NLA_NESTED },
1526         /* TODO handle it as for_each_nested and NLA_FLAG? */
1527         [NL802154_KEY_ATTR_USAGE_FRAMES] = { NLA_U8 },
1528         /* TODO handle it as for_each_nested, not static array? */
1529         [NL802154_KEY_ATTR_USAGE_CMDS] = { .len = NL802154_CMD_FRAME_NR_IDS / 8 },
1530         [NL802154_KEY_ATTR_BYTES] = { .len = NL802154_KEY_SIZE },
1531 };
1532
1533 static int nl802154_add_llsec_key(struct sk_buff *skb, struct genl_info *info)
1534 {
1535         struct cfg802154_registered_device *rdev = info->user_ptr[0];
1536         struct net_device *dev = info->user_ptr[1];
1537         struct wpan_dev *wpan_dev = dev->ieee802154_ptr;
1538         struct nlattr *attrs[NL802154_KEY_ATTR_MAX + 1];
1539         struct ieee802154_llsec_key key = { };
1540         struct ieee802154_llsec_key_id id = { };
1541         u32 commands[NL802154_CMD_FRAME_NR_IDS / 32] = { };
1542
1543         if (!info->attrs[NL802154_ATTR_SEC_KEY] ||
1544             nla_parse_nested(attrs, NL802154_KEY_ATTR_MAX,
1545                              info->attrs[NL802154_ATTR_SEC_KEY],
1546                              nl802154_key_policy))
1547                 return -EINVAL;
1548
1549         if (!attrs[NL802154_KEY_ATTR_USAGE_FRAMES] ||
1550             !attrs[NL802154_KEY_ATTR_BYTES])
1551                 return -EINVAL;
1552
1553         if (ieee802154_llsec_parse_key_id(attrs[NL802154_KEY_ATTR_ID], &id) < 0)
1554                 return -ENOBUFS;
1555
1556         key.frame_types = nla_get_u8(attrs[NL802154_KEY_ATTR_USAGE_FRAMES]);
1557         if (key.frame_types > BIT(NL802154_FRAME_MAX) ||
1558             ((key.frame_types & BIT(NL802154_FRAME_CMD)) &&
1559              !attrs[NL802154_KEY_ATTR_USAGE_CMDS]))
1560                 return -EINVAL;
1561
1562         if (attrs[NL802154_KEY_ATTR_USAGE_CMDS]) {
1563                 /* TODO for each nested */
1564                 nla_memcpy(commands, attrs[NL802154_KEY_ATTR_USAGE_CMDS],
1565                            NL802154_CMD_FRAME_NR_IDS / 8);
1566
1567                 /* TODO understand the -EINVAL logic here? last condition */
1568                 if (commands[0] || commands[1] || commands[2] || commands[3] ||
1569                     commands[4] || commands[5] || commands[6] ||
1570                     commands[7] > BIT(NL802154_CMD_FRAME_MAX))
1571                         return -EINVAL;
1572
1573                 key.cmd_frame_ids = commands[7];
1574         } else {
1575                 key.cmd_frame_ids = 0;
1576         }
1577
1578         nla_memcpy(key.key, attrs[NL802154_KEY_ATTR_BYTES], NL802154_KEY_SIZE);
1579
1580         if (ieee802154_llsec_parse_key_id(attrs[NL802154_KEY_ATTR_ID], &id) < 0)
1581                 return -ENOBUFS;
1582
1583         return rdev_add_llsec_key(rdev, wpan_dev, &id, &key);
1584 }
1585
1586 static int nl802154_del_llsec_key(struct sk_buff *skb, struct genl_info *info)
1587 {
1588         struct cfg802154_registered_device *rdev = info->user_ptr[0];
1589         struct net_device *dev = info->user_ptr[1];
1590         struct wpan_dev *wpan_dev = dev->ieee802154_ptr;
1591         struct nlattr *attrs[NL802154_KEY_ATTR_MAX + 1];
1592         struct ieee802154_llsec_key_id id;
1593
1594         if (!info->attrs[NL802154_ATTR_SEC_KEY] ||
1595             nla_parse_nested(attrs, NL802154_KEY_ATTR_MAX,
1596                              info->attrs[NL802154_ATTR_SEC_KEY],
1597                              nl802154_key_policy))
1598                 return -EINVAL;
1599
1600         if (ieee802154_llsec_parse_key_id(attrs[NL802154_KEY_ATTR_ID], &id) < 0)
1601                 return -ENOBUFS;
1602
1603         return rdev_del_llsec_key(rdev, wpan_dev, &id);
1604 }
1605
1606 static int nl802154_send_device(struct sk_buff *msg, u32 cmd, u32 portid,
1607                                 u32 seq, int flags,
1608                                 struct cfg802154_registered_device *rdev,
1609                                 struct net_device *dev,
1610                                 const struct ieee802154_llsec_device *dev_desc)
1611 {
1612         void *hdr;
1613         struct nlattr *nl_device;
1614
1615         hdr = nl802154hdr_put(msg, portid, seq, flags, cmd);
1616         if (!hdr)
1617                 return -1;
1618
1619         if (nla_put_u32(msg, NL802154_ATTR_IFINDEX, dev->ifindex))
1620                 goto nla_put_failure;
1621
1622         nl_device = nla_nest_start(msg, NL802154_ATTR_SEC_DEVICE);
1623         if (!nl_device)
1624                 goto nla_put_failure;
1625
1626         if (nla_put_u32(msg, NL802154_DEV_ATTR_FRAME_COUNTER,
1627                         dev_desc->frame_counter) ||
1628             nla_put_le16(msg, NL802154_DEV_ATTR_PAN_ID, dev_desc->pan_id) ||
1629             nla_put_le16(msg, NL802154_DEV_ATTR_SHORT_ADDR,
1630                          dev_desc->short_addr) ||
1631             nla_put_le64(msg, NL802154_DEV_ATTR_EXTENDED_ADDR,
1632                          dev_desc->hwaddr) ||
1633             nla_put_u8(msg, NL802154_DEV_ATTR_SECLEVEL_EXEMPT,
1634                        dev_desc->seclevel_exempt) ||
1635             nla_put_u32(msg, NL802154_DEV_ATTR_KEY_MODE, dev_desc->key_mode))
1636                 goto nla_put_failure;
1637
1638         nla_nest_end(msg, nl_device);
1639         genlmsg_end(msg, hdr);
1640
1641         return 0;
1642
1643 nla_put_failure:
1644         genlmsg_cancel(msg, hdr);
1645         return -EMSGSIZE;
1646 }
1647
1648 static int
1649 nl802154_dump_llsec_dev(struct sk_buff *skb, struct netlink_callback *cb)
1650 {
1651         struct cfg802154_registered_device *rdev = NULL;
1652         struct ieee802154_llsec_device *dev;
1653         struct ieee802154_llsec_table *table;
1654         struct wpan_dev *wpan_dev;
1655         int err;
1656
1657         err = nl802154_prepare_wpan_dev_dump(skb, cb, &rdev, &wpan_dev);
1658         if (err)
1659                 return err;
1660
1661         if (wpan_dev->iftype == NL802154_IFTYPE_MONITOR) {
1662                 err = skb->len;
1663                 goto out_err;
1664         }
1665
1666         if (!wpan_dev->netdev) {
1667                 err = -EINVAL;
1668                 goto out_err;
1669         }
1670
1671         rdev_lock_llsec_table(rdev, wpan_dev);
1672         rdev_get_llsec_table(rdev, wpan_dev, &table);
1673
1674         /* TODO make it like station dump */
1675         if (cb->args[2])
1676                 goto out;
1677
1678         list_for_each_entry(dev, &table->devices, list) {
1679                 if (nl802154_send_device(skb, NL802154_CMD_NEW_SEC_LEVEL,
1680                                          NETLINK_CB(cb->skb).portid,
1681                                          cb->nlh->nlmsg_seq, NLM_F_MULTI,
1682                                          rdev, wpan_dev->netdev, dev) < 0) {
1683                         /* TODO */
1684                         err = -EIO;
1685                         rdev_unlock_llsec_table(rdev, wpan_dev);
1686                         goto out_err;
1687                 }
1688         }
1689
1690         cb->args[2] = 1;
1691
1692 out:
1693         rdev_unlock_llsec_table(rdev, wpan_dev);
1694         err = skb->len;
1695 out_err:
1696         nl802154_finish_wpan_dev_dump(rdev);
1697
1698         return err;
1699 }
1700
1701 static const struct nla_policy nl802154_dev_policy[NL802154_DEV_ATTR_MAX + 1] = {
1702         [NL802154_DEV_ATTR_FRAME_COUNTER] = { NLA_U32 },
1703         [NL802154_DEV_ATTR_PAN_ID] = { .type = NLA_U16 },
1704         [NL802154_DEV_ATTR_SHORT_ADDR] = { .type = NLA_U16 },
1705         [NL802154_DEV_ATTR_EXTENDED_ADDR] = { .type = NLA_U64 },
1706         [NL802154_DEV_ATTR_SECLEVEL_EXEMPT] = { NLA_U8 },
1707         [NL802154_DEV_ATTR_KEY_MODE] = { NLA_U32 },
1708 };
1709
1710 static int
1711 ieee802154_llsec_parse_device(struct nlattr *nla,
1712                               struct ieee802154_llsec_device *dev)
1713 {
1714         struct nlattr *attrs[NL802154_DEV_ATTR_MAX + 1];
1715
1716         if (!nla || nla_parse_nested(attrs, NL802154_DEV_ATTR_MAX, nla,
1717                                      nl802154_dev_policy))
1718                 return -EINVAL;
1719
1720         memset(dev, 0, sizeof(*dev));
1721
1722         if (!attrs[NL802154_DEV_ATTR_FRAME_COUNTER] ||
1723             !attrs[NL802154_DEV_ATTR_PAN_ID] ||
1724             !attrs[NL802154_DEV_ATTR_SHORT_ADDR] ||
1725             !attrs[NL802154_DEV_ATTR_EXTENDED_ADDR] ||
1726             !attrs[NL802154_DEV_ATTR_SECLEVEL_EXEMPT] ||
1727             !attrs[NL802154_DEV_ATTR_KEY_MODE])
1728                 return -EINVAL;
1729
1730         /* TODO be32 */
1731         dev->frame_counter = nla_get_u32(attrs[NL802154_DEV_ATTR_FRAME_COUNTER]);
1732         dev->pan_id = nla_get_le16(attrs[NL802154_DEV_ATTR_PAN_ID]);
1733         dev->short_addr = nla_get_le16(attrs[NL802154_DEV_ATTR_SHORT_ADDR]);
1734         /* TODO rename hwaddr to extended_addr */
1735         dev->hwaddr = nla_get_le64(attrs[NL802154_DEV_ATTR_EXTENDED_ADDR]);
1736         dev->seclevel_exempt = nla_get_u8(attrs[NL802154_DEV_ATTR_SECLEVEL_EXEMPT]);
1737         dev->key_mode = nla_get_u32(attrs[NL802154_DEV_ATTR_KEY_MODE]);
1738
1739         if (dev->key_mode > NL802154_DEVKEY_MAX ||
1740             (dev->seclevel_exempt != 0 && dev->seclevel_exempt != 1))
1741                 return -EINVAL;
1742
1743         return 0;
1744 }
1745
1746 static int nl802154_add_llsec_dev(struct sk_buff *skb, struct genl_info *info)
1747 {
1748         struct cfg802154_registered_device *rdev = info->user_ptr[0];
1749         struct net_device *dev = info->user_ptr[1];
1750         struct wpan_dev *wpan_dev = dev->ieee802154_ptr;
1751         struct ieee802154_llsec_device dev_desc;
1752
1753         if (wpan_dev->iftype == NL802154_IFTYPE_MONITOR)
1754                 return -EOPNOTSUPP;
1755
1756         if (ieee802154_llsec_parse_device(info->attrs[NL802154_ATTR_SEC_DEVICE],
1757                                           &dev_desc) < 0)
1758                 return -EINVAL;
1759
1760         return rdev_add_device(rdev, wpan_dev, &dev_desc);
1761 }
1762
1763 static int nl802154_del_llsec_dev(struct sk_buff *skb, struct genl_info *info)
1764 {
1765         struct cfg802154_registered_device *rdev = info->user_ptr[0];
1766         struct net_device *dev = info->user_ptr[1];
1767         struct wpan_dev *wpan_dev = dev->ieee802154_ptr;
1768         struct nlattr *attrs[NL802154_DEV_ATTR_MAX + 1];
1769         __le64 extended_addr;
1770
1771         if (!info->attrs[NL802154_ATTR_SEC_DEVICE] ||
1772             nla_parse_nested(attrs, NL802154_DEV_ATTR_MAX,
1773                              info->attrs[NL802154_ATTR_SEC_DEVICE],
1774                              nl802154_dev_policy))
1775                 return -EINVAL;
1776
1777         if (!attrs[NL802154_DEV_ATTR_EXTENDED_ADDR])
1778                 return -EINVAL;
1779
1780         extended_addr = nla_get_le64(attrs[NL802154_DEV_ATTR_EXTENDED_ADDR]);
1781         return rdev_del_device(rdev, wpan_dev, extended_addr);
1782 }
1783
1784 static int nl802154_send_devkey(struct sk_buff *msg, u32 cmd, u32 portid,
1785                                 u32 seq, int flags,
1786                                 struct cfg802154_registered_device *rdev,
1787                                 struct net_device *dev, __le64 extended_addr,
1788                                 const struct ieee802154_llsec_device_key *devkey)
1789 {
1790         void *hdr;
1791         struct nlattr *nl_devkey, *nl_key_id;
1792
1793         hdr = nl802154hdr_put(msg, portid, seq, flags, cmd);
1794         if (!hdr)
1795                 return -1;
1796
1797         if (nla_put_u32(msg, NL802154_ATTR_IFINDEX, dev->ifindex))
1798                 goto nla_put_failure;
1799
1800         nl_devkey = nla_nest_start(msg, NL802154_ATTR_SEC_DEVKEY);
1801         if (!nl_devkey)
1802                 goto nla_put_failure;
1803
1804         if (nla_put_le64(msg, NL802154_DEVKEY_ATTR_EXTENDED_ADDR,
1805                          extended_addr) ||
1806             nla_put_u32(msg, NL802154_DEVKEY_ATTR_FRAME_COUNTER,
1807                         devkey->frame_counter))
1808                 goto nla_put_failure;
1809
1810         nl_key_id = nla_nest_start(msg, NL802154_DEVKEY_ATTR_ID);
1811         if (!nl_key_id)
1812                 goto nla_put_failure;
1813
1814         if (ieee802154_llsec_send_key_id(msg, &devkey->key_id) < 0)
1815                 goto nla_put_failure;
1816
1817         nla_nest_end(msg, nl_key_id);
1818         nla_nest_end(msg, nl_devkey);
1819         genlmsg_end(msg, hdr);
1820
1821         return 0;
1822
1823 nla_put_failure:
1824         genlmsg_cancel(msg, hdr);
1825         return -EMSGSIZE;
1826 }
1827
1828 static int
1829 nl802154_dump_llsec_devkey(struct sk_buff *skb, struct netlink_callback *cb)
1830 {
1831         struct cfg802154_registered_device *rdev = NULL;
1832         struct ieee802154_llsec_device_key *kpos;
1833         struct ieee802154_llsec_device *dpos;
1834         struct ieee802154_llsec_table *table;
1835         struct wpan_dev *wpan_dev;
1836         int err;
1837
1838         err = nl802154_prepare_wpan_dev_dump(skb, cb, &rdev, &wpan_dev);
1839         if (err)
1840                 return err;
1841
1842         if (wpan_dev->iftype == NL802154_IFTYPE_MONITOR) {
1843                 err = skb->len;
1844                 goto out_err;
1845         }
1846
1847         if (!wpan_dev->netdev) {
1848                 err = -EINVAL;
1849                 goto out_err;
1850         }
1851
1852         rdev_lock_llsec_table(rdev, wpan_dev);
1853         rdev_get_llsec_table(rdev, wpan_dev, &table);
1854
1855         /* TODO make it like station dump */
1856         if (cb->args[2])
1857                 goto out;
1858
1859         /* TODO look if remove devkey and do some nested attribute */
1860         list_for_each_entry(dpos, &table->devices, list) {
1861                 list_for_each_entry(kpos, &dpos->keys, list) {
1862                         if (nl802154_send_devkey(skb,
1863                                                  NL802154_CMD_NEW_SEC_LEVEL,
1864                                                  NETLINK_CB(cb->skb).portid,
1865                                                  cb->nlh->nlmsg_seq,
1866                                                  NLM_F_MULTI, rdev,
1867                                                  wpan_dev->netdev,
1868                                                  dpos->hwaddr,
1869                                                  kpos) < 0) {
1870                                 /* TODO */
1871                                 err = -EIO;
1872                                 rdev_unlock_llsec_table(rdev, wpan_dev);
1873                                 goto out_err;
1874                         }
1875                 }
1876         }
1877
1878         cb->args[2] = 1;
1879
1880 out:
1881         rdev_unlock_llsec_table(rdev, wpan_dev);
1882         err = skb->len;
1883 out_err:
1884         nl802154_finish_wpan_dev_dump(rdev);
1885
1886         return err;
1887 }
1888
1889 static const struct nla_policy nl802154_devkey_policy[NL802154_DEVKEY_ATTR_MAX + 1] = {
1890         [NL802154_DEVKEY_ATTR_FRAME_COUNTER] = { NLA_U32 },
1891         [NL802154_DEVKEY_ATTR_EXTENDED_ADDR] = { NLA_U64 },
1892         [NL802154_DEVKEY_ATTR_ID] = { NLA_NESTED },
1893 };
1894
1895 static int nl802154_add_llsec_devkey(struct sk_buff *skb, struct genl_info *info)
1896 {
1897         struct cfg802154_registered_device *rdev = info->user_ptr[0];
1898         struct net_device *dev = info->user_ptr[1];
1899         struct wpan_dev *wpan_dev = dev->ieee802154_ptr;
1900         struct nlattr *attrs[NL802154_DEVKEY_ATTR_MAX + 1];
1901         struct ieee802154_llsec_device_key key;
1902         __le64 extended_addr;
1903
1904         if (wpan_dev->iftype == NL802154_IFTYPE_MONITOR)
1905                 return -EOPNOTSUPP;
1906
1907         if (!info->attrs[NL802154_ATTR_SEC_DEVKEY] ||
1908             nla_parse_nested(attrs, NL802154_DEVKEY_ATTR_MAX,
1909                              info->attrs[NL802154_ATTR_SEC_DEVKEY],
1910                              nl802154_devkey_policy) < 0)
1911                 return -EINVAL;
1912
1913         if (!attrs[NL802154_DEVKEY_ATTR_FRAME_COUNTER] ||
1914             !attrs[NL802154_DEVKEY_ATTR_EXTENDED_ADDR])
1915                 return -EINVAL;
1916
1917         /* TODO change key.id ? */
1918         if (ieee802154_llsec_parse_key_id(attrs[NL802154_DEVKEY_ATTR_ID],
1919                                           &key.key_id) < 0)
1920                 return -ENOBUFS;
1921
1922         /* TODO be32 */
1923         key.frame_counter = nla_get_u32(attrs[NL802154_DEVKEY_ATTR_FRAME_COUNTER]);
1924         /* TODO change naming hwaddr -> extended_addr
1925          * check unique identifier short+pan OR extended_addr
1926          */
1927         extended_addr = nla_get_le64(attrs[NL802154_DEVKEY_ATTR_EXTENDED_ADDR]);
1928         return rdev_add_devkey(rdev, wpan_dev, extended_addr, &key);
1929 }
1930
1931 static int nl802154_del_llsec_devkey(struct sk_buff *skb, struct genl_info *info)
1932 {
1933         struct cfg802154_registered_device *rdev = info->user_ptr[0];
1934         struct net_device *dev = info->user_ptr[1];
1935         struct wpan_dev *wpan_dev = dev->ieee802154_ptr;
1936         struct nlattr *attrs[NL802154_DEVKEY_ATTR_MAX + 1];
1937         struct ieee802154_llsec_device_key key;
1938         __le64 extended_addr;
1939
1940         if (!info->attrs[NL802154_ATTR_SEC_DEVKEY] ||
1941             nla_parse_nested(attrs, NL802154_DEVKEY_ATTR_MAX,
1942                              info->attrs[NL802154_ATTR_SEC_DEVKEY],
1943                              nl802154_devkey_policy))
1944                 return -EINVAL;
1945
1946         if (!attrs[NL802154_DEVKEY_ATTR_EXTENDED_ADDR])
1947                 return -EINVAL;
1948
1949         /* TODO change key.id ? */
1950         if (ieee802154_llsec_parse_key_id(attrs[NL802154_DEVKEY_ATTR_ID],
1951                                           &key.key_id) < 0)
1952                 return -ENOBUFS;
1953
1954         /* TODO change naming hwaddr -> extended_addr
1955          * check unique identifier short+pan OR extended_addr
1956          */
1957         extended_addr = nla_get_le64(attrs[NL802154_DEVKEY_ATTR_EXTENDED_ADDR]);
1958         return rdev_del_devkey(rdev, wpan_dev, extended_addr, &key);
1959 }
1960
1961 static int nl802154_send_seclevel(struct sk_buff *msg, u32 cmd, u32 portid,
1962                                   u32 seq, int flags,
1963                                   struct cfg802154_registered_device *rdev,
1964                                   struct net_device *dev,
1965                                   const struct ieee802154_llsec_seclevel *sl)
1966 {
1967         void *hdr;
1968         struct nlattr *nl_seclevel;
1969
1970         hdr = nl802154hdr_put(msg, portid, seq, flags, cmd);
1971         if (!hdr)
1972                 return -1;
1973
1974         if (nla_put_u32(msg, NL802154_ATTR_IFINDEX, dev->ifindex))
1975                 goto nla_put_failure;
1976
1977         nl_seclevel = nla_nest_start(msg, NL802154_ATTR_SEC_LEVEL);
1978         if (!nl_seclevel)
1979                 goto nla_put_failure;
1980
1981         if (nla_put_u32(msg, NL802154_SECLEVEL_ATTR_FRAME, sl->frame_type) ||
1982             nla_put_u32(msg, NL802154_SECLEVEL_ATTR_LEVELS, sl->sec_levels) ||
1983             nla_put_u8(msg, NL802154_SECLEVEL_ATTR_DEV_OVERRIDE,
1984                        sl->device_override))
1985                 goto nla_put_failure;
1986
1987         if (sl->frame_type == NL802154_FRAME_CMD) {
1988                 if (nla_put_u32(msg, NL802154_SECLEVEL_ATTR_CMD_FRAME,
1989                                 sl->cmd_frame_id))
1990                         goto nla_put_failure;
1991         }
1992
1993         nla_nest_end(msg, nl_seclevel);
1994         genlmsg_end(msg, hdr);
1995
1996         return 0;
1997
1998 nla_put_failure:
1999         genlmsg_cancel(msg, hdr);
2000         return -EMSGSIZE;
2001 }
2002
2003 static int
2004 nl802154_dump_llsec_seclevel(struct sk_buff *skb, struct netlink_callback *cb)
2005 {
2006         struct cfg802154_registered_device *rdev = NULL;
2007         struct ieee802154_llsec_seclevel *sl;
2008         struct ieee802154_llsec_table *table;
2009         struct wpan_dev *wpan_dev;
2010         int err;
2011
2012         err = nl802154_prepare_wpan_dev_dump(skb, cb, &rdev, &wpan_dev);
2013         if (err)
2014                 return err;
2015
2016         if (wpan_dev->iftype == NL802154_IFTYPE_MONITOR) {
2017                 err = skb->len;
2018                 goto out_err;
2019         }
2020
2021         if (!wpan_dev->netdev) {
2022                 err = -EINVAL;
2023                 goto out_err;
2024         }
2025
2026         rdev_lock_llsec_table(rdev, wpan_dev);
2027         rdev_get_llsec_table(rdev, wpan_dev, &table);
2028
2029         /* TODO make it like station dump */
2030         if (cb->args[2])
2031                 goto out;
2032
2033         list_for_each_entry(sl, &table->security_levels, list) {
2034                 if (nl802154_send_seclevel(skb, NL802154_CMD_NEW_SEC_LEVEL,
2035                                            NETLINK_CB(cb->skb).portid,
2036                                            cb->nlh->nlmsg_seq, NLM_F_MULTI,
2037                                            rdev, wpan_dev->netdev, sl) < 0) {
2038                         /* TODO */
2039                         err = -EIO;
2040                         rdev_unlock_llsec_table(rdev, wpan_dev);
2041                         goto out_err;
2042                 }
2043         }
2044
2045         cb->args[2] = 1;
2046
2047 out:
2048         rdev_unlock_llsec_table(rdev, wpan_dev);
2049         err = skb->len;
2050 out_err:
2051         nl802154_finish_wpan_dev_dump(rdev);
2052
2053         return err;
2054 }
2055
2056 static const struct nla_policy nl802154_seclevel_policy[NL802154_SECLEVEL_ATTR_MAX + 1] = {
2057         [NL802154_SECLEVEL_ATTR_LEVELS] = { .type = NLA_U8 },
2058         [NL802154_SECLEVEL_ATTR_FRAME] = { .type = NLA_U32 },
2059         [NL802154_SECLEVEL_ATTR_CMD_FRAME] = { .type = NLA_U32 },
2060         [NL802154_SECLEVEL_ATTR_DEV_OVERRIDE] = { .type = NLA_U8 },
2061 };
2062
2063 static int
2064 llsec_parse_seclevel(struct nlattr *nla, struct ieee802154_llsec_seclevel *sl)
2065 {
2066         struct nlattr *attrs[NL802154_SECLEVEL_ATTR_MAX + 1];
2067
2068         if (!nla || nla_parse_nested(attrs, NL802154_SECLEVEL_ATTR_MAX, nla,
2069                                      nl802154_seclevel_policy))
2070                 return -EINVAL;
2071
2072         memset(sl, 0, sizeof(*sl));
2073
2074         if (!attrs[NL802154_SECLEVEL_ATTR_LEVELS] ||
2075             !attrs[NL802154_SECLEVEL_ATTR_FRAME] ||
2076             !attrs[NL802154_SECLEVEL_ATTR_DEV_OVERRIDE])
2077                 return -EINVAL;
2078
2079         sl->sec_levels = nla_get_u8(attrs[NL802154_SECLEVEL_ATTR_LEVELS]);
2080         sl->frame_type = nla_get_u32(attrs[NL802154_SECLEVEL_ATTR_FRAME]);
2081         sl->device_override = nla_get_u8(attrs[NL802154_SECLEVEL_ATTR_DEV_OVERRIDE]);
2082         if (sl->frame_type > NL802154_FRAME_MAX ||
2083             (sl->device_override != 0 && sl->device_override != 1))
2084                 return -EINVAL;
2085
2086         if (sl->frame_type == NL802154_FRAME_CMD) {
2087                 if (!attrs[NL802154_SECLEVEL_ATTR_CMD_FRAME])
2088                         return -EINVAL;
2089
2090                 sl->cmd_frame_id = nla_get_u32(attrs[NL802154_SECLEVEL_ATTR_CMD_FRAME]);
2091                 if (sl->cmd_frame_id > NL802154_CMD_FRAME_MAX)
2092                         return -EINVAL;
2093         }
2094
2095         return 0;
2096 }
2097
2098 static int nl802154_add_llsec_seclevel(struct sk_buff *skb,
2099                                        struct genl_info *info)
2100 {
2101         struct cfg802154_registered_device *rdev = info->user_ptr[0];
2102         struct net_device *dev = info->user_ptr[1];
2103         struct wpan_dev *wpan_dev = dev->ieee802154_ptr;
2104         struct ieee802154_llsec_seclevel sl;
2105
2106         if (wpan_dev->iftype == NL802154_IFTYPE_MONITOR)
2107                 return -EOPNOTSUPP;
2108
2109         if (llsec_parse_seclevel(info->attrs[NL802154_ATTR_SEC_LEVEL],
2110                                  &sl) < 0)
2111                 return -EINVAL;
2112
2113         return rdev_add_seclevel(rdev, wpan_dev, &sl);
2114 }
2115
2116 static int nl802154_del_llsec_seclevel(struct sk_buff *skb,
2117                                        struct genl_info *info)
2118 {
2119         struct cfg802154_registered_device *rdev = info->user_ptr[0];
2120         struct net_device *dev = info->user_ptr[1];
2121         struct wpan_dev *wpan_dev = dev->ieee802154_ptr;
2122         struct ieee802154_llsec_seclevel sl;
2123
2124         if (wpan_dev->iftype == NL802154_IFTYPE_MONITOR)
2125                 return -EOPNOTSUPP;
2126
2127         if (!info->attrs[NL802154_ATTR_SEC_LEVEL] ||
2128             llsec_parse_seclevel(info->attrs[NL802154_ATTR_SEC_LEVEL],
2129                                  &sl) < 0)
2130                 return -EINVAL;
2131
2132         return rdev_del_seclevel(rdev, wpan_dev, &sl);
2133 }
2134 #endif /* CONFIG_IEEE802154_NL802154_EXPERIMENTAL */
2135
2136 #define NL802154_FLAG_NEED_WPAN_PHY     0x01
2137 #define NL802154_FLAG_NEED_NETDEV       0x02
2138 #define NL802154_FLAG_NEED_RTNL         0x04
2139 #define NL802154_FLAG_CHECK_NETDEV_UP   0x08
2140 #define NL802154_FLAG_NEED_NETDEV_UP    (NL802154_FLAG_NEED_NETDEV |\
2141                                          NL802154_FLAG_CHECK_NETDEV_UP)
2142 #define NL802154_FLAG_NEED_WPAN_DEV     0x10
2143 #define NL802154_FLAG_NEED_WPAN_DEV_UP  (NL802154_FLAG_NEED_WPAN_DEV |\
2144                                          NL802154_FLAG_CHECK_NETDEV_UP)
2145
2146 static int nl802154_pre_doit(const struct genl_ops *ops, struct sk_buff *skb,
2147                              struct genl_info *info)
2148 {
2149         struct cfg802154_registered_device *rdev;
2150         struct wpan_dev *wpan_dev;
2151         struct net_device *dev;
2152         bool rtnl = ops->internal_flags & NL802154_FLAG_NEED_RTNL;
2153
2154         if (rtnl)
2155                 rtnl_lock();
2156
2157         if (ops->internal_flags & NL802154_FLAG_NEED_WPAN_PHY) {
2158                 rdev = cfg802154_get_dev_from_info(genl_info_net(info), info);
2159                 if (IS_ERR(rdev)) {
2160                         if (rtnl)
2161                                 rtnl_unlock();
2162                         return PTR_ERR(rdev);
2163                 }
2164                 info->user_ptr[0] = rdev;
2165         } else if (ops->internal_flags & NL802154_FLAG_NEED_NETDEV ||
2166                    ops->internal_flags & NL802154_FLAG_NEED_WPAN_DEV) {
2167                 ASSERT_RTNL();
2168                 wpan_dev = __cfg802154_wpan_dev_from_attrs(genl_info_net(info),
2169                                                            info->attrs);
2170                 if (IS_ERR(wpan_dev)) {
2171                         if (rtnl)
2172                                 rtnl_unlock();
2173                         return PTR_ERR(wpan_dev);
2174                 }
2175
2176                 dev = wpan_dev->netdev;
2177                 rdev = wpan_phy_to_rdev(wpan_dev->wpan_phy);
2178
2179                 if (ops->internal_flags & NL802154_FLAG_NEED_NETDEV) {
2180                         if (!dev) {
2181                                 if (rtnl)
2182                                         rtnl_unlock();
2183                                 return -EINVAL;
2184                         }
2185
2186                         info->user_ptr[1] = dev;
2187                 } else {
2188                         info->user_ptr[1] = wpan_dev;
2189                 }
2190
2191                 if (dev) {
2192                         if (ops->internal_flags & NL802154_FLAG_CHECK_NETDEV_UP &&
2193                             !netif_running(dev)) {
2194                                 if (rtnl)
2195                                         rtnl_unlock();
2196                                 return -ENETDOWN;
2197                         }
2198
2199                         dev_hold(dev);
2200                 }
2201
2202                 info->user_ptr[0] = rdev;
2203         }
2204
2205         return 0;
2206 }
2207
2208 static void nl802154_post_doit(const struct genl_ops *ops, struct sk_buff *skb,
2209                                struct genl_info *info)
2210 {
2211         if (info->user_ptr[1]) {
2212                 if (ops->internal_flags & NL802154_FLAG_NEED_WPAN_DEV) {
2213                         struct wpan_dev *wpan_dev = info->user_ptr[1];
2214
2215                         if (wpan_dev->netdev)
2216                                 dev_put(wpan_dev->netdev);
2217                 } else {
2218                         dev_put(info->user_ptr[1]);
2219                 }
2220         }
2221
2222         if (ops->internal_flags & NL802154_FLAG_NEED_RTNL)
2223                 rtnl_unlock();
2224 }
2225
2226 static const struct genl_ops nl802154_ops[] = {
2227         {
2228                 .cmd = NL802154_CMD_GET_WPAN_PHY,
2229                 .doit = nl802154_get_wpan_phy,
2230                 .dumpit = nl802154_dump_wpan_phy,
2231                 .done = nl802154_dump_wpan_phy_done,
2232                 .policy = nl802154_policy,
2233                 /* can be retrieved by unprivileged users */
2234                 .internal_flags = NL802154_FLAG_NEED_WPAN_PHY |
2235                                   NL802154_FLAG_NEED_RTNL,
2236         },
2237         {
2238                 .cmd = NL802154_CMD_GET_INTERFACE,
2239                 .doit = nl802154_get_interface,
2240                 .dumpit = nl802154_dump_interface,
2241                 .policy = nl802154_policy,
2242                 /* can be retrieved by unprivileged users */
2243                 .internal_flags = NL802154_FLAG_NEED_WPAN_DEV |
2244                                   NL802154_FLAG_NEED_RTNL,
2245         },
2246         {
2247                 .cmd = NL802154_CMD_NEW_INTERFACE,
2248                 .doit = nl802154_new_interface,
2249                 .policy = nl802154_policy,
2250                 .flags = GENL_ADMIN_PERM,
2251                 .internal_flags = NL802154_FLAG_NEED_WPAN_PHY |
2252                                   NL802154_FLAG_NEED_RTNL,
2253         },
2254         {
2255                 .cmd = NL802154_CMD_DEL_INTERFACE,
2256                 .doit = nl802154_del_interface,
2257                 .policy = nl802154_policy,
2258                 .flags = GENL_ADMIN_PERM,
2259                 .internal_flags = NL802154_FLAG_NEED_WPAN_DEV |
2260                                   NL802154_FLAG_NEED_RTNL,
2261         },
2262         {
2263                 .cmd = NL802154_CMD_SET_CHANNEL,
2264                 .doit = nl802154_set_channel,
2265                 .policy = nl802154_policy,
2266                 .flags = GENL_ADMIN_PERM,
2267                 .internal_flags = NL802154_FLAG_NEED_WPAN_PHY |
2268                                   NL802154_FLAG_NEED_RTNL,
2269         },
2270         {
2271                 .cmd = NL802154_CMD_SET_CCA_MODE,
2272                 .doit = nl802154_set_cca_mode,
2273                 .policy = nl802154_policy,
2274                 .flags = GENL_ADMIN_PERM,
2275                 .internal_flags = NL802154_FLAG_NEED_WPAN_PHY |
2276                                   NL802154_FLAG_NEED_RTNL,
2277         },
2278         {
2279                 .cmd = NL802154_CMD_SET_CCA_ED_LEVEL,
2280                 .doit = nl802154_set_cca_ed_level,
2281                 .policy = nl802154_policy,
2282                 .flags = GENL_ADMIN_PERM,
2283                 .internal_flags = NL802154_FLAG_NEED_WPAN_PHY |
2284                                   NL802154_FLAG_NEED_RTNL,
2285         },
2286         {
2287                 .cmd = NL802154_CMD_SET_TX_POWER,
2288                 .doit = nl802154_set_tx_power,
2289                 .policy = nl802154_policy,
2290                 .flags = GENL_ADMIN_PERM,
2291                 .internal_flags = NL802154_FLAG_NEED_WPAN_PHY |
2292                                   NL802154_FLAG_NEED_RTNL,
2293         },
2294         {
2295                 .cmd = NL802154_CMD_SET_PAN_ID,
2296                 .doit = nl802154_set_pan_id,
2297                 .policy = nl802154_policy,
2298                 .flags = GENL_ADMIN_PERM,
2299                 .internal_flags = NL802154_FLAG_NEED_NETDEV |
2300                                   NL802154_FLAG_NEED_RTNL,
2301         },
2302         {
2303                 .cmd = NL802154_CMD_SET_SHORT_ADDR,
2304                 .doit = nl802154_set_short_addr,
2305                 .policy = nl802154_policy,
2306                 .flags = GENL_ADMIN_PERM,
2307                 .internal_flags = NL802154_FLAG_NEED_NETDEV |
2308                                   NL802154_FLAG_NEED_RTNL,
2309         },
2310         {
2311                 .cmd = NL802154_CMD_SET_BACKOFF_EXPONENT,
2312                 .doit = nl802154_set_backoff_exponent,
2313                 .policy = nl802154_policy,
2314                 .flags = GENL_ADMIN_PERM,
2315                 .internal_flags = NL802154_FLAG_NEED_NETDEV |
2316                                   NL802154_FLAG_NEED_RTNL,
2317         },
2318         {
2319                 .cmd = NL802154_CMD_SET_MAX_CSMA_BACKOFFS,
2320                 .doit = nl802154_set_max_csma_backoffs,
2321                 .policy = nl802154_policy,
2322                 .flags = GENL_ADMIN_PERM,
2323                 .internal_flags = NL802154_FLAG_NEED_NETDEV |
2324                                   NL802154_FLAG_NEED_RTNL,
2325         },
2326         {
2327                 .cmd = NL802154_CMD_SET_MAX_FRAME_RETRIES,
2328                 .doit = nl802154_set_max_frame_retries,
2329                 .policy = nl802154_policy,
2330                 .flags = GENL_ADMIN_PERM,
2331                 .internal_flags = NL802154_FLAG_NEED_NETDEV |
2332                                   NL802154_FLAG_NEED_RTNL,
2333         },
2334         {
2335                 .cmd = NL802154_CMD_SET_LBT_MODE,
2336                 .doit = nl802154_set_lbt_mode,
2337                 .policy = nl802154_policy,
2338                 .flags = GENL_ADMIN_PERM,
2339                 .internal_flags = NL802154_FLAG_NEED_NETDEV |
2340                                   NL802154_FLAG_NEED_RTNL,
2341         },
2342         {
2343                 .cmd = NL802154_CMD_SET_ACKREQ_DEFAULT,
2344                 .doit = nl802154_set_ackreq_default,
2345                 .policy = nl802154_policy,
2346                 .flags = GENL_ADMIN_PERM,
2347                 .internal_flags = NL802154_FLAG_NEED_NETDEV |
2348                                   NL802154_FLAG_NEED_RTNL,
2349         },
2350 #ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL
2351         {
2352                 .cmd = NL802154_CMD_SET_SEC_PARAMS,
2353                 .doit = nl802154_set_llsec_params,
2354                 .policy = nl802154_policy,
2355                 .flags = GENL_ADMIN_PERM,
2356                 .internal_flags = NL802154_FLAG_NEED_NETDEV |
2357                                   NL802154_FLAG_NEED_RTNL,
2358         },
2359         {
2360                 .cmd = NL802154_CMD_GET_SEC_KEY,
2361                 /* TODO .doit by matching key id? */
2362                 .dumpit = nl802154_dump_llsec_key,
2363                 .policy = nl802154_policy,
2364                 .flags = GENL_ADMIN_PERM,
2365                 .internal_flags = NL802154_FLAG_NEED_NETDEV |
2366                                   NL802154_FLAG_NEED_RTNL,
2367         },
2368         {
2369                 .cmd = NL802154_CMD_NEW_SEC_KEY,
2370                 .doit = nl802154_add_llsec_key,
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_DEL_SEC_KEY,
2378                 .doit = nl802154_del_llsec_key,
2379                 .policy = nl802154_policy,
2380                 .flags = GENL_ADMIN_PERM,
2381                 .internal_flags = NL802154_FLAG_NEED_NETDEV |
2382                                   NL802154_FLAG_NEED_RTNL,
2383         },
2384         /* TODO unique identifier must short+pan OR extended_addr */
2385         {
2386                 .cmd = NL802154_CMD_GET_SEC_DEV,
2387                 /* TODO .doit by matching extended_addr? */
2388                 .dumpit = nl802154_dump_llsec_dev,
2389                 .policy = nl802154_policy,
2390                 .flags = GENL_ADMIN_PERM,
2391                 .internal_flags = NL802154_FLAG_NEED_NETDEV |
2392                                   NL802154_FLAG_NEED_RTNL,
2393         },
2394         {
2395                 .cmd = NL802154_CMD_NEW_SEC_DEV,
2396                 .doit = nl802154_add_llsec_dev,
2397                 .policy = nl802154_policy,
2398                 .flags = GENL_ADMIN_PERM,
2399                 .internal_flags = NL802154_FLAG_NEED_NETDEV |
2400                                   NL802154_FLAG_NEED_RTNL,
2401         },
2402         {
2403                 .cmd = NL802154_CMD_DEL_SEC_DEV,
2404                 .doit = nl802154_del_llsec_dev,
2405                 .policy = nl802154_policy,
2406                 .flags = GENL_ADMIN_PERM,
2407                 .internal_flags = NL802154_FLAG_NEED_NETDEV |
2408                                   NL802154_FLAG_NEED_RTNL,
2409         },
2410         /* TODO remove complete devkey, put it as nested? */
2411         {
2412                 .cmd = NL802154_CMD_GET_SEC_DEVKEY,
2413                 /* TODO doit by matching ??? */
2414                 .dumpit = nl802154_dump_llsec_devkey,
2415                 .policy = nl802154_policy,
2416                 .flags = GENL_ADMIN_PERM,
2417                 .internal_flags = NL802154_FLAG_NEED_NETDEV |
2418                                   NL802154_FLAG_NEED_RTNL,
2419         },
2420         {
2421                 .cmd = NL802154_CMD_NEW_SEC_DEVKEY,
2422                 .doit = nl802154_add_llsec_devkey,
2423                 .policy = nl802154_policy,
2424                 .flags = GENL_ADMIN_PERM,
2425                 .internal_flags = NL802154_FLAG_NEED_NETDEV |
2426                                   NL802154_FLAG_NEED_RTNL,
2427         },
2428         {
2429                 .cmd = NL802154_CMD_DEL_SEC_DEVKEY,
2430                 .doit = nl802154_del_llsec_devkey,
2431                 .policy = nl802154_policy,
2432                 .flags = GENL_ADMIN_PERM,
2433                 .internal_flags = NL802154_FLAG_NEED_NETDEV |
2434                                   NL802154_FLAG_NEED_RTNL,
2435         },
2436         {
2437                 .cmd = NL802154_CMD_GET_SEC_LEVEL,
2438                 /* TODO .doit by matching frame_type? */
2439                 .dumpit = nl802154_dump_llsec_seclevel,
2440                 .policy = nl802154_policy,
2441                 .flags = GENL_ADMIN_PERM,
2442                 .internal_flags = NL802154_FLAG_NEED_NETDEV |
2443                                   NL802154_FLAG_NEED_RTNL,
2444         },
2445         {
2446                 .cmd = NL802154_CMD_NEW_SEC_LEVEL,
2447                 .doit = nl802154_add_llsec_seclevel,
2448                 .policy = nl802154_policy,
2449                 .flags = GENL_ADMIN_PERM,
2450                 .internal_flags = NL802154_FLAG_NEED_NETDEV |
2451                                   NL802154_FLAG_NEED_RTNL,
2452         },
2453         {
2454                 .cmd = NL802154_CMD_DEL_SEC_LEVEL,
2455                 /* TODO match frame_type only? */
2456                 .doit = nl802154_del_llsec_seclevel,
2457                 .policy = nl802154_policy,
2458                 .flags = GENL_ADMIN_PERM,
2459                 .internal_flags = NL802154_FLAG_NEED_NETDEV |
2460                                   NL802154_FLAG_NEED_RTNL,
2461         },
2462 #endif /* CONFIG_IEEE802154_NL802154_EXPERIMENTAL */
2463 };
2464
2465 /* initialisation/exit functions */
2466 int nl802154_init(void)
2467 {
2468         return genl_register_family_with_ops_groups(&nl802154_fam, nl802154_ops,
2469                                                     nl802154_mcgrps);
2470 }
2471
2472 void nl802154_exit(void)
2473 {
2474         genl_unregister_family(&nl802154_fam);
2475 }