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