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