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