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