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