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