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