xref: /linux/net/ieee802154/nl802154.c (revision 0883c2c06fb5bcf5b9e008270827e63c09a88c1e)
1 /* This program is free software; you can redistribute it and/or modify
2  * it under the terms of the GNU General Public License version 2
3  * as published by the Free Software Foundation.
4  *
5  * This program is distributed in the hope that it will be useful,
6  * but WITHOUT ANY WARRANTY; without even the implied warranty of
7  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
8  * GNU General Public License for more details.
9  *
10  * Authors:
11  * Alexander Aring <aar@pengutronix.de>
12  *
13  * Based on: net/wireless/nl80211.c
14  */
15 
16 #include <linux/rtnetlink.h>
17 
18 #include <net/cfg802154.h>
19 #include <net/genetlink.h>
20 #include <net/mac802154.h>
21 #include <net/netlink.h>
22 #include <net/nl802154.h>
23 #include <net/sock.h>
24 
25 #include "nl802154.h"
26 #include "rdev-ops.h"
27 #include "core.h"
28 
29 static int nl802154_pre_doit(const struct genl_ops *ops, struct sk_buff *skb,
30 			     struct genl_info *info);
31 
32 static void nl802154_post_doit(const struct genl_ops *ops, struct sk_buff *skb,
33 			       struct genl_info *info);
34 
35 /* the netlink family */
36 static struct genl_family nl802154_fam = {
37 	.id = GENL_ID_GENERATE,		/* don't bother with a hardcoded ID */
38 	.name = NL802154_GENL_NAME,	/* have users key off the name instead */
39 	.hdrsize = 0,			/* no private header */
40 	.version = 1,			/* no particular meaning now */
41 	.maxattr = NL802154_ATTR_MAX,
42 	.netnsok = true,
43 	.pre_doit = nl802154_pre_doit,
44 	.post_doit = nl802154_post_doit,
45 };
46 
47 /* multicast groups */
48 enum nl802154_multicast_groups {
49 	NL802154_MCGRP_CONFIG,
50 };
51 
52 static const struct genl_multicast_group nl802154_mcgrps[] = {
53 	[NL802154_MCGRP_CONFIG] = { .name = "config", },
54 };
55 
56 /* returns ERR_PTR values */
57 static struct wpan_dev *
58 __cfg802154_wpan_dev_from_attrs(struct net *netns, struct nlattr **attrs)
59 {
60 	struct cfg802154_registered_device *rdev;
61 	struct wpan_dev *result = NULL;
62 	bool have_ifidx = attrs[NL802154_ATTR_IFINDEX];
63 	bool have_wpan_dev_id = attrs[NL802154_ATTR_WPAN_DEV];
64 	u64 wpan_dev_id;
65 	int wpan_phy_idx = -1;
66 	int ifidx = -1;
67 
68 	ASSERT_RTNL();
69 
70 	if (!have_ifidx && !have_wpan_dev_id)
71 		return ERR_PTR(-EINVAL);
72 
73 	if (have_ifidx)
74 		ifidx = nla_get_u32(attrs[NL802154_ATTR_IFINDEX]);
75 	if (have_wpan_dev_id) {
76 		wpan_dev_id = nla_get_u64(attrs[NL802154_ATTR_WPAN_DEV]);
77 		wpan_phy_idx = wpan_dev_id >> 32;
78 	}
79 
80 	list_for_each_entry(rdev, &cfg802154_rdev_list, list) {
81 		struct wpan_dev *wpan_dev;
82 
83 		/* 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 
111 static 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  */
189 static struct cfg802154_registered_device *
190 cfg802154_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 */
196 static 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
250 static int
251 nl802154_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 
308 static void
309 nl802154_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 */
316 static 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 
323 static int
324 nl802154_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 
345 static int
346 nl802154_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 
366 static int
367 nl802154_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 
452 static 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 
555 finish:
556 	genlmsg_end(msg, hdr);
557 	return 0;
558 
559 nla_put_failure:
560 	genlmsg_cancel(msg, hdr);
561 	return -EMSGSIZE;
562 }
563 
564 struct nl802154_dump_wpan_phy_state {
565 	s64 filter_wpan_phy;
566 	long start;
567 
568 };
569 
570 static 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 
607 static int
608 nl802154_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 
663 static int nl802154_dump_wpan_phy_done(struct netlink_callback *cb)
664 {
665 	kfree((void *)cb->args[0]);
666 	return 0;
667 }
668 
669 static 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 
687 static 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 
696 static int
697 ieee802154_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 					 NL802154_DEV_ADDR_ATTR_PAD))
727 				return -ENOBUFS;
728 			break;
729 		default:
730 			/* userspace should handle unknown */
731 			break;
732 		}
733 
734 		nla_nest_end(msg, nl_dev_addr);
735 		break;
736 	case NL802154_KEY_ID_MODE_INDEX:
737 		break;
738 	case NL802154_KEY_ID_MODE_INDEX_SHORT:
739 		/* TODO renmae short_source? */
740 		if (nla_put_le32(msg, NL802154_KEY_ID_ATTR_SOURCE_SHORT,
741 				 desc->short_source))
742 			return -ENOBUFS;
743 		break;
744 	case NL802154_KEY_ID_MODE_INDEX_EXTENDED:
745 		if (nla_put_le64(msg, NL802154_KEY_ID_ATTR_SOURCE_EXTENDED,
746 				 desc->extended_source,
747 				 NL802154_KEY_ID_ATTR_PAD))
748 			return -ENOBUFS;
749 		break;
750 	default:
751 		/* userspace should handle unknown */
752 		break;
753 	}
754 
755 	/* TODO key_id to key_idx ? Check naming */
756 	if (desc->mode != NL802154_KEY_ID_MODE_IMPLICIT) {
757 		if (nla_put_u8(msg, NL802154_KEY_ID_ATTR_INDEX, desc->id))
758 			return -ENOBUFS;
759 	}
760 
761 	return 0;
762 }
763 
764 static int nl802154_get_llsec_params(struct sk_buff *msg,
765 				     struct cfg802154_registered_device *rdev,
766 				     struct wpan_dev *wpan_dev)
767 {
768 	struct nlattr *nl_key_id;
769 	struct ieee802154_llsec_params params;
770 	int ret;
771 
772 	ret = rdev_get_llsec_params(rdev, wpan_dev, &params);
773 	if (ret < 0)
774 		return ret;
775 
776 	if (nla_put_u8(msg, NL802154_ATTR_SEC_ENABLED, params.enabled) ||
777 	    nla_put_u32(msg, NL802154_ATTR_SEC_OUT_LEVEL, params.out_level) ||
778 	    nla_put_be32(msg, NL802154_ATTR_SEC_FRAME_COUNTER,
779 			 params.frame_counter))
780 		return -ENOBUFS;
781 
782 	nl_key_id = nla_nest_start(msg, NL802154_ATTR_SEC_OUT_KEY_ID);
783 	if (!nl_key_id)
784 		return -ENOBUFS;
785 
786 	ret = ieee802154_llsec_send_key_id(msg, &params.out_key);
787 	if (ret < 0)
788 		return ret;
789 
790 	nla_nest_end(msg, nl_key_id);
791 
792 	return 0;
793 }
794 #endif /* CONFIG_IEEE802154_NL802154_EXPERIMENTAL */
795 
796 static int
797 nl802154_send_iface(struct sk_buff *msg, u32 portid, u32 seq, int flags,
798 		    struct cfg802154_registered_device *rdev,
799 		    struct wpan_dev *wpan_dev)
800 {
801 	struct net_device *dev = wpan_dev->netdev;
802 	void *hdr;
803 
804 	hdr = nl802154hdr_put(msg, portid, seq, flags,
805 			      NL802154_CMD_NEW_INTERFACE);
806 	if (!hdr)
807 		return -1;
808 
809 	if (dev &&
810 	    (nla_put_u32(msg, NL802154_ATTR_IFINDEX, dev->ifindex) ||
811 	     nla_put_string(msg, NL802154_ATTR_IFNAME, dev->name)))
812 		goto nla_put_failure;
813 
814 	if (nla_put_u32(msg, NL802154_ATTR_WPAN_PHY, rdev->wpan_phy_idx) ||
815 	    nla_put_u32(msg, NL802154_ATTR_IFTYPE, wpan_dev->iftype) ||
816 	    nla_put_u64_64bit(msg, NL802154_ATTR_WPAN_DEV,
817 			      wpan_dev_id(wpan_dev), NL802154_ATTR_PAD) ||
818 	    nla_put_u32(msg, NL802154_ATTR_GENERATION,
819 			rdev->devlist_generation ^
820 			(cfg802154_rdev_list_generation << 2)))
821 		goto nla_put_failure;
822 
823 	/* address settings */
824 	if (nla_put_le64(msg, NL802154_ATTR_EXTENDED_ADDR,
825 			 wpan_dev->extended_addr,
826 			 NL802154_ATTR_PAD) ||
827 	    nla_put_le16(msg, NL802154_ATTR_SHORT_ADDR,
828 			 wpan_dev->short_addr) ||
829 	    nla_put_le16(msg, NL802154_ATTR_PAN_ID, wpan_dev->pan_id))
830 		goto nla_put_failure;
831 
832 	/* ARET handling */
833 	if (nla_put_s8(msg, NL802154_ATTR_MAX_FRAME_RETRIES,
834 		       wpan_dev->frame_retries) ||
835 	    nla_put_u8(msg, NL802154_ATTR_MAX_BE, wpan_dev->max_be) ||
836 	    nla_put_u8(msg, NL802154_ATTR_MAX_CSMA_BACKOFFS,
837 		       wpan_dev->csma_retries) ||
838 	    nla_put_u8(msg, NL802154_ATTR_MIN_BE, wpan_dev->min_be))
839 		goto nla_put_failure;
840 
841 	/* listen before transmit */
842 	if (nla_put_u8(msg, NL802154_ATTR_LBT_MODE, wpan_dev->lbt))
843 		goto nla_put_failure;
844 
845 	/* ackreq default behaviour */
846 	if (nla_put_u8(msg, NL802154_ATTR_ACKREQ_DEFAULT, wpan_dev->ackreq))
847 		goto nla_put_failure;
848 
849 #ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL
850 	if (nl802154_get_llsec_params(msg, rdev, wpan_dev) < 0)
851 		goto nla_put_failure;
852 #endif /* CONFIG_IEEE802154_NL802154_EXPERIMENTAL */
853 
854 	genlmsg_end(msg, hdr);
855 	return 0;
856 
857 nla_put_failure:
858 	genlmsg_cancel(msg, hdr);
859 	return -EMSGSIZE;
860 }
861 
862 static int
863 nl802154_dump_interface(struct sk_buff *skb, struct netlink_callback *cb)
864 {
865 	int wp_idx = 0;
866 	int if_idx = 0;
867 	int wp_start = cb->args[0];
868 	int if_start = cb->args[1];
869 	struct cfg802154_registered_device *rdev;
870 	struct wpan_dev *wpan_dev;
871 
872 	rtnl_lock();
873 	list_for_each_entry(rdev, &cfg802154_rdev_list, list) {
874 		/* TODO netns compare */
875 		if (wp_idx < wp_start) {
876 			wp_idx++;
877 			continue;
878 		}
879 		if_idx = 0;
880 
881 		list_for_each_entry(wpan_dev, &rdev->wpan_dev_list, list) {
882 			if (if_idx < if_start) {
883 				if_idx++;
884 				continue;
885 			}
886 			if (nl802154_send_iface(skb, NETLINK_CB(cb->skb).portid,
887 						cb->nlh->nlmsg_seq, NLM_F_MULTI,
888 						rdev, wpan_dev) < 0) {
889 				goto out;
890 			}
891 			if_idx++;
892 		}
893 
894 		wp_idx++;
895 	}
896 out:
897 	rtnl_unlock();
898 
899 	cb->args[0] = wp_idx;
900 	cb->args[1] = if_idx;
901 
902 	return skb->len;
903 }
904 
905 static int nl802154_get_interface(struct sk_buff *skb, struct genl_info *info)
906 {
907 	struct sk_buff *msg;
908 	struct cfg802154_registered_device *rdev = info->user_ptr[0];
909 	struct wpan_dev *wdev = info->user_ptr[1];
910 
911 	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
912 	if (!msg)
913 		return -ENOMEM;
914 
915 	if (nl802154_send_iface(msg, info->snd_portid, info->snd_seq, 0,
916 				rdev, wdev) < 0) {
917 		nlmsg_free(msg);
918 		return -ENOBUFS;
919 	}
920 
921 	return genlmsg_reply(msg, info);
922 }
923 
924 static int nl802154_new_interface(struct sk_buff *skb, struct genl_info *info)
925 {
926 	struct cfg802154_registered_device *rdev = info->user_ptr[0];
927 	enum nl802154_iftype type = NL802154_IFTYPE_UNSPEC;
928 	__le64 extended_addr = cpu_to_le64(0x0000000000000000ULL);
929 
930 	/* TODO avoid failing a new interface
931 	 * creation due to pending removal?
932 	 */
933 
934 	if (!info->attrs[NL802154_ATTR_IFNAME])
935 		return -EINVAL;
936 
937 	if (info->attrs[NL802154_ATTR_IFTYPE]) {
938 		type = nla_get_u32(info->attrs[NL802154_ATTR_IFTYPE]);
939 		if (type > NL802154_IFTYPE_MAX ||
940 		    !(rdev->wpan_phy.supported.iftypes & BIT(type)))
941 			return -EINVAL;
942 	}
943 
944 	if (info->attrs[NL802154_ATTR_EXTENDED_ADDR])
945 		extended_addr = nla_get_le64(info->attrs[NL802154_ATTR_EXTENDED_ADDR]);
946 
947 	if (!rdev->ops->add_virtual_intf)
948 		return -EOPNOTSUPP;
949 
950 	return rdev_add_virtual_intf(rdev,
951 				     nla_data(info->attrs[NL802154_ATTR_IFNAME]),
952 				     NET_NAME_USER, type, extended_addr);
953 }
954 
955 static int nl802154_del_interface(struct sk_buff *skb, struct genl_info *info)
956 {
957 	struct cfg802154_registered_device *rdev = info->user_ptr[0];
958 	struct wpan_dev *wpan_dev = info->user_ptr[1];
959 
960 	if (!rdev->ops->del_virtual_intf)
961 		return -EOPNOTSUPP;
962 
963 	/* If we remove a wpan device without a netdev then clear
964 	 * user_ptr[1] so that nl802154_post_doit won't dereference it
965 	 * to check if it needs to do dev_put(). Otherwise it crashes
966 	 * since the wpan_dev has been freed, unlike with a netdev where
967 	 * we need the dev_put() for the netdev to really be freed.
968 	 */
969 	if (!wpan_dev->netdev)
970 		info->user_ptr[1] = NULL;
971 
972 	return rdev_del_virtual_intf(rdev, wpan_dev);
973 }
974 
975 static int nl802154_set_channel(struct sk_buff *skb, struct genl_info *info)
976 {
977 	struct cfg802154_registered_device *rdev = info->user_ptr[0];
978 	u8 channel, page;
979 
980 	if (!info->attrs[NL802154_ATTR_PAGE] ||
981 	    !info->attrs[NL802154_ATTR_CHANNEL])
982 		return -EINVAL;
983 
984 	page = nla_get_u8(info->attrs[NL802154_ATTR_PAGE]);
985 	channel = nla_get_u8(info->attrs[NL802154_ATTR_CHANNEL]);
986 
987 	/* check 802.15.4 constraints */
988 	if (page > IEEE802154_MAX_PAGE || channel > IEEE802154_MAX_CHANNEL ||
989 	    !(rdev->wpan_phy.supported.channels[page] & BIT(channel)))
990 		return -EINVAL;
991 
992 	return rdev_set_channel(rdev, page, channel);
993 }
994 
995 static int nl802154_set_cca_mode(struct sk_buff *skb, struct genl_info *info)
996 {
997 	struct cfg802154_registered_device *rdev = info->user_ptr[0];
998 	struct wpan_phy_cca cca;
999 
1000 	if (!(rdev->wpan_phy.flags & WPAN_PHY_FLAG_CCA_MODE))
1001 		return -EOPNOTSUPP;
1002 
1003 	if (!info->attrs[NL802154_ATTR_CCA_MODE])
1004 		return -EINVAL;
1005 
1006 	cca.mode = nla_get_u32(info->attrs[NL802154_ATTR_CCA_MODE]);
1007 	/* checking 802.15.4 constraints */
1008 	if (cca.mode < NL802154_CCA_ENERGY ||
1009 	    cca.mode > NL802154_CCA_ATTR_MAX ||
1010 	    !(rdev->wpan_phy.supported.cca_modes & BIT(cca.mode)))
1011 		return -EINVAL;
1012 
1013 	if (cca.mode == NL802154_CCA_ENERGY_CARRIER) {
1014 		if (!info->attrs[NL802154_ATTR_CCA_OPT])
1015 			return -EINVAL;
1016 
1017 		cca.opt = nla_get_u32(info->attrs[NL802154_ATTR_CCA_OPT]);
1018 		if (cca.opt > NL802154_CCA_OPT_ATTR_MAX ||
1019 		    !(rdev->wpan_phy.supported.cca_opts & BIT(cca.opt)))
1020 			return -EINVAL;
1021 	}
1022 
1023 	return rdev_set_cca_mode(rdev, &cca);
1024 }
1025 
1026 static int nl802154_set_cca_ed_level(struct sk_buff *skb, struct genl_info *info)
1027 {
1028 	struct cfg802154_registered_device *rdev = info->user_ptr[0];
1029 	s32 ed_level;
1030 	int i;
1031 
1032 	if (!(rdev->wpan_phy.flags & WPAN_PHY_FLAG_CCA_ED_LEVEL))
1033 		return -EOPNOTSUPP;
1034 
1035 	if (!info->attrs[NL802154_ATTR_CCA_ED_LEVEL])
1036 		return -EINVAL;
1037 
1038 	ed_level = nla_get_s32(info->attrs[NL802154_ATTR_CCA_ED_LEVEL]);
1039 
1040 	for (i = 0; i < rdev->wpan_phy.supported.cca_ed_levels_size; i++) {
1041 		if (ed_level == rdev->wpan_phy.supported.cca_ed_levels[i])
1042 			return rdev_set_cca_ed_level(rdev, ed_level);
1043 	}
1044 
1045 	return -EINVAL;
1046 }
1047 
1048 static int nl802154_set_tx_power(struct sk_buff *skb, struct genl_info *info)
1049 {
1050 	struct cfg802154_registered_device *rdev = info->user_ptr[0];
1051 	s32 power;
1052 	int i;
1053 
1054 	if (!(rdev->wpan_phy.flags & WPAN_PHY_FLAG_TXPOWER))
1055 		return -EOPNOTSUPP;
1056 
1057 	if (!info->attrs[NL802154_ATTR_TX_POWER])
1058 		return -EINVAL;
1059 
1060 	power = nla_get_s32(info->attrs[NL802154_ATTR_TX_POWER]);
1061 
1062 	for (i = 0; i < rdev->wpan_phy.supported.tx_powers_size; i++) {
1063 		if (power == rdev->wpan_phy.supported.tx_powers[i])
1064 			return rdev_set_tx_power(rdev, power);
1065 	}
1066 
1067 	return -EINVAL;
1068 }
1069 
1070 static int nl802154_set_pan_id(struct sk_buff *skb, struct genl_info *info)
1071 {
1072 	struct cfg802154_registered_device *rdev = info->user_ptr[0];
1073 	struct net_device *dev = info->user_ptr[1];
1074 	struct wpan_dev *wpan_dev = dev->ieee802154_ptr;
1075 	__le16 pan_id;
1076 
1077 	/* conflict here while tx/rx calls */
1078 	if (netif_running(dev))
1079 		return -EBUSY;
1080 
1081 	if (wpan_dev->lowpan_dev) {
1082 		if (netif_running(wpan_dev->lowpan_dev))
1083 			return -EBUSY;
1084 	}
1085 
1086 	/* don't change address fields on monitor */
1087 	if (wpan_dev->iftype == NL802154_IFTYPE_MONITOR ||
1088 	    !info->attrs[NL802154_ATTR_PAN_ID])
1089 		return -EINVAL;
1090 
1091 	pan_id = nla_get_le16(info->attrs[NL802154_ATTR_PAN_ID]);
1092 
1093 	/* TODO
1094 	 * I am not sure about to check here on broadcast pan_id.
1095 	 * Broadcast is a valid setting, comment from 802.15.4:
1096 	 * If this value is 0xffff, the device is not associated.
1097 	 *
1098 	 * This could useful to simple deassociate an device.
1099 	 */
1100 	if (pan_id == cpu_to_le16(IEEE802154_PAN_ID_BROADCAST))
1101 		return -EINVAL;
1102 
1103 	return rdev_set_pan_id(rdev, wpan_dev, pan_id);
1104 }
1105 
1106 static int nl802154_set_short_addr(struct sk_buff *skb, struct genl_info *info)
1107 {
1108 	struct cfg802154_registered_device *rdev = info->user_ptr[0];
1109 	struct net_device *dev = info->user_ptr[1];
1110 	struct wpan_dev *wpan_dev = dev->ieee802154_ptr;
1111 	__le16 short_addr;
1112 
1113 	/* conflict here while tx/rx calls */
1114 	if (netif_running(dev))
1115 		return -EBUSY;
1116 
1117 	if (wpan_dev->lowpan_dev) {
1118 		if (netif_running(wpan_dev->lowpan_dev))
1119 			return -EBUSY;
1120 	}
1121 
1122 	/* don't change address fields on monitor */
1123 	if (wpan_dev->iftype == NL802154_IFTYPE_MONITOR ||
1124 	    !info->attrs[NL802154_ATTR_SHORT_ADDR])
1125 		return -EINVAL;
1126 
1127 	short_addr = nla_get_le16(info->attrs[NL802154_ATTR_SHORT_ADDR]);
1128 
1129 	/* TODO
1130 	 * I am not sure about to check here on broadcast short_addr.
1131 	 * Broadcast is a valid setting, comment from 802.15.4:
1132 	 * A value of 0xfffe indicates that the device has
1133 	 * associated but has not been allocated an address. A
1134 	 * value of 0xffff indicates that the device does not
1135 	 * have a short address.
1136 	 *
1137 	 * I think we should allow to set these settings but
1138 	 * don't allow to allow socket communication with it.
1139 	 */
1140 	if (short_addr == cpu_to_le16(IEEE802154_ADDR_SHORT_UNSPEC) ||
1141 	    short_addr == cpu_to_le16(IEEE802154_ADDR_SHORT_BROADCAST))
1142 		return -EINVAL;
1143 
1144 	return rdev_set_short_addr(rdev, wpan_dev, short_addr);
1145 }
1146 
1147 static int
1148 nl802154_set_backoff_exponent(struct sk_buff *skb, struct genl_info *info)
1149 {
1150 	struct cfg802154_registered_device *rdev = info->user_ptr[0];
1151 	struct net_device *dev = info->user_ptr[1];
1152 	struct wpan_dev *wpan_dev = dev->ieee802154_ptr;
1153 	u8 min_be, max_be;
1154 
1155 	/* should be set on netif open inside phy settings */
1156 	if (netif_running(dev))
1157 		return -EBUSY;
1158 
1159 	if (!info->attrs[NL802154_ATTR_MIN_BE] ||
1160 	    !info->attrs[NL802154_ATTR_MAX_BE])
1161 		return -EINVAL;
1162 
1163 	min_be = nla_get_u8(info->attrs[NL802154_ATTR_MIN_BE]);
1164 	max_be = nla_get_u8(info->attrs[NL802154_ATTR_MAX_BE]);
1165 
1166 	/* check 802.15.4 constraints */
1167 	if (min_be < rdev->wpan_phy.supported.min_minbe ||
1168 	    min_be > rdev->wpan_phy.supported.max_minbe ||
1169 	    max_be < rdev->wpan_phy.supported.min_maxbe ||
1170 	    max_be > rdev->wpan_phy.supported.max_maxbe ||
1171 	    min_be > max_be)
1172 		return -EINVAL;
1173 
1174 	return rdev_set_backoff_exponent(rdev, wpan_dev, min_be, max_be);
1175 }
1176 
1177 static int
1178 nl802154_set_max_csma_backoffs(struct sk_buff *skb, struct genl_info *info)
1179 {
1180 	struct cfg802154_registered_device *rdev = info->user_ptr[0];
1181 	struct net_device *dev = info->user_ptr[1];
1182 	struct wpan_dev *wpan_dev = dev->ieee802154_ptr;
1183 	u8 max_csma_backoffs;
1184 
1185 	/* conflict here while other running iface settings */
1186 	if (netif_running(dev))
1187 		return -EBUSY;
1188 
1189 	if (!info->attrs[NL802154_ATTR_MAX_CSMA_BACKOFFS])
1190 		return -EINVAL;
1191 
1192 	max_csma_backoffs = nla_get_u8(
1193 			info->attrs[NL802154_ATTR_MAX_CSMA_BACKOFFS]);
1194 
1195 	/* check 802.15.4 constraints */
1196 	if (max_csma_backoffs < rdev->wpan_phy.supported.min_csma_backoffs ||
1197 	    max_csma_backoffs > rdev->wpan_phy.supported.max_csma_backoffs)
1198 		return -EINVAL;
1199 
1200 	return rdev_set_max_csma_backoffs(rdev, wpan_dev, max_csma_backoffs);
1201 }
1202 
1203 static int
1204 nl802154_set_max_frame_retries(struct sk_buff *skb, struct genl_info *info)
1205 {
1206 	struct cfg802154_registered_device *rdev = info->user_ptr[0];
1207 	struct net_device *dev = info->user_ptr[1];
1208 	struct wpan_dev *wpan_dev = dev->ieee802154_ptr;
1209 	s8 max_frame_retries;
1210 
1211 	if (netif_running(dev))
1212 		return -EBUSY;
1213 
1214 	if (!info->attrs[NL802154_ATTR_MAX_FRAME_RETRIES])
1215 		return -EINVAL;
1216 
1217 	max_frame_retries = nla_get_s8(
1218 			info->attrs[NL802154_ATTR_MAX_FRAME_RETRIES]);
1219 
1220 	/* check 802.15.4 constraints */
1221 	if (max_frame_retries < rdev->wpan_phy.supported.min_frame_retries ||
1222 	    max_frame_retries > rdev->wpan_phy.supported.max_frame_retries)
1223 		return -EINVAL;
1224 
1225 	return rdev_set_max_frame_retries(rdev, wpan_dev, max_frame_retries);
1226 }
1227 
1228 static int nl802154_set_lbt_mode(struct sk_buff *skb, struct genl_info *info)
1229 {
1230 	struct cfg802154_registered_device *rdev = info->user_ptr[0];
1231 	struct net_device *dev = info->user_ptr[1];
1232 	struct wpan_dev *wpan_dev = dev->ieee802154_ptr;
1233 	int mode;
1234 
1235 	if (netif_running(dev))
1236 		return -EBUSY;
1237 
1238 	if (!info->attrs[NL802154_ATTR_LBT_MODE])
1239 		return -EINVAL;
1240 
1241 	mode = nla_get_u8(info->attrs[NL802154_ATTR_LBT_MODE]);
1242 
1243 	if (mode != 0 && mode != 1)
1244 		return -EINVAL;
1245 
1246 	if (!wpan_phy_supported_bool(mode, rdev->wpan_phy.supported.lbt))
1247 		return -EINVAL;
1248 
1249 	return rdev_set_lbt_mode(rdev, wpan_dev, mode);
1250 }
1251 
1252 static int
1253 nl802154_set_ackreq_default(struct sk_buff *skb, struct genl_info *info)
1254 {
1255 	struct cfg802154_registered_device *rdev = info->user_ptr[0];
1256 	struct net_device *dev = info->user_ptr[1];
1257 	struct wpan_dev *wpan_dev = dev->ieee802154_ptr;
1258 	int ackreq;
1259 
1260 	if (netif_running(dev))
1261 		return -EBUSY;
1262 
1263 	if (!info->attrs[NL802154_ATTR_ACKREQ_DEFAULT])
1264 		return -EINVAL;
1265 
1266 	ackreq = nla_get_u8(info->attrs[NL802154_ATTR_ACKREQ_DEFAULT]);
1267 
1268 	if (ackreq != 0 && ackreq != 1)
1269 		return -EINVAL;
1270 
1271 	return rdev_set_ackreq_default(rdev, wpan_dev, ackreq);
1272 }
1273 
1274 #ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL
1275 static const struct nla_policy nl802154_dev_addr_policy[NL802154_DEV_ADDR_ATTR_MAX + 1] = {
1276 	[NL802154_DEV_ADDR_ATTR_PAN_ID] = { .type = NLA_U16 },
1277 	[NL802154_DEV_ADDR_ATTR_MODE] = { .type = NLA_U32 },
1278 	[NL802154_DEV_ADDR_ATTR_SHORT] = { .type = NLA_U16 },
1279 	[NL802154_DEV_ADDR_ATTR_EXTENDED] = { .type = NLA_U64 },
1280 };
1281 
1282 static int
1283 ieee802154_llsec_parse_dev_addr(struct nlattr *nla,
1284 				struct ieee802154_addr *addr)
1285 {
1286 	struct nlattr *attrs[NL802154_DEV_ADDR_ATTR_MAX + 1];
1287 
1288 	if (!nla || nla_parse_nested(attrs, NL802154_DEV_ADDR_ATTR_MAX, nla,
1289 				     nl802154_dev_addr_policy))
1290 		return -EINVAL;
1291 
1292 	if (!attrs[NL802154_DEV_ADDR_ATTR_PAN_ID] ||
1293 	    !attrs[NL802154_DEV_ADDR_ATTR_MODE] ||
1294 	    !(attrs[NL802154_DEV_ADDR_ATTR_SHORT] ||
1295 	      attrs[NL802154_DEV_ADDR_ATTR_EXTENDED]))
1296 		return -EINVAL;
1297 
1298 	addr->pan_id = nla_get_le16(attrs[NL802154_DEV_ADDR_ATTR_PAN_ID]);
1299 	addr->mode = nla_get_u32(attrs[NL802154_DEV_ADDR_ATTR_MODE]);
1300 	switch (addr->mode) {
1301 	case NL802154_DEV_ADDR_SHORT:
1302 		addr->short_addr = nla_get_le16(attrs[NL802154_DEV_ADDR_ATTR_SHORT]);
1303 		break;
1304 	case NL802154_DEV_ADDR_EXTENDED:
1305 		addr->extended_addr = nla_get_le64(attrs[NL802154_DEV_ADDR_ATTR_EXTENDED]);
1306 		break;
1307 	default:
1308 		return -EINVAL;
1309 	}
1310 
1311 	return 0;
1312 }
1313 
1314 static const struct nla_policy nl802154_key_id_policy[NL802154_KEY_ID_ATTR_MAX + 1] = {
1315 	[NL802154_KEY_ID_ATTR_MODE] = { .type = NLA_U32 },
1316 	[NL802154_KEY_ID_ATTR_INDEX] = { .type = NLA_U8 },
1317 	[NL802154_KEY_ID_ATTR_IMPLICIT] = { .type = NLA_NESTED },
1318 	[NL802154_KEY_ID_ATTR_SOURCE_SHORT] = { .type = NLA_U32 },
1319 	[NL802154_KEY_ID_ATTR_SOURCE_EXTENDED] = { .type = NLA_U64 },
1320 };
1321 
1322 static int
1323 ieee802154_llsec_parse_key_id(struct nlattr *nla,
1324 			      struct ieee802154_llsec_key_id *desc)
1325 {
1326 	struct nlattr *attrs[NL802154_KEY_ID_ATTR_MAX + 1];
1327 
1328 	if (!nla || nla_parse_nested(attrs, NL802154_KEY_ID_ATTR_MAX, nla,
1329 				     nl802154_key_id_policy))
1330 		return -EINVAL;
1331 
1332 	if (!attrs[NL802154_KEY_ID_ATTR_MODE])
1333 		return -EINVAL;
1334 
1335 	desc->mode = nla_get_u32(attrs[NL802154_KEY_ID_ATTR_MODE]);
1336 	switch (desc->mode) {
1337 	case NL802154_KEY_ID_MODE_IMPLICIT:
1338 		if (!attrs[NL802154_KEY_ID_ATTR_IMPLICIT])
1339 			return -EINVAL;
1340 
1341 		if (ieee802154_llsec_parse_dev_addr(attrs[NL802154_KEY_ID_ATTR_IMPLICIT],
1342 						    &desc->device_addr) < 0)
1343 			return -EINVAL;
1344 		break;
1345 	case NL802154_KEY_ID_MODE_INDEX:
1346 		break;
1347 	case NL802154_KEY_ID_MODE_INDEX_SHORT:
1348 		if (!attrs[NL802154_KEY_ID_ATTR_SOURCE_SHORT])
1349 			return -EINVAL;
1350 
1351 		desc->short_source = nla_get_le32(attrs[NL802154_KEY_ID_ATTR_SOURCE_SHORT]);
1352 		break;
1353 	case NL802154_KEY_ID_MODE_INDEX_EXTENDED:
1354 		if (!attrs[NL802154_KEY_ID_ATTR_SOURCE_EXTENDED])
1355 			return -EINVAL;
1356 
1357 		desc->extended_source = nla_get_le64(attrs[NL802154_KEY_ID_ATTR_SOURCE_EXTENDED]);
1358 		break;
1359 	default:
1360 		return -EINVAL;
1361 	}
1362 
1363 	if (desc->mode != NL802154_KEY_ID_MODE_IMPLICIT) {
1364 		if (!attrs[NL802154_KEY_ID_ATTR_INDEX])
1365 			return -EINVAL;
1366 
1367 		/* TODO change id to idx */
1368 		desc->id = nla_get_u8(attrs[NL802154_KEY_ID_ATTR_INDEX]);
1369 	}
1370 
1371 	return 0;
1372 }
1373 
1374 static int nl802154_set_llsec_params(struct sk_buff *skb,
1375 				     struct genl_info *info)
1376 {
1377 	struct cfg802154_registered_device *rdev = info->user_ptr[0];
1378 	struct net_device *dev = info->user_ptr[1];
1379 	struct wpan_dev *wpan_dev = dev->ieee802154_ptr;
1380 	struct ieee802154_llsec_params params;
1381 	u32 changed = 0;
1382 	int ret;
1383 
1384 	if (info->attrs[NL802154_ATTR_SEC_ENABLED]) {
1385 		u8 enabled;
1386 
1387 		enabled = nla_get_u8(info->attrs[NL802154_ATTR_SEC_ENABLED]);
1388 		if (enabled != 0 && enabled != 1)
1389 			return -EINVAL;
1390 
1391 		params.enabled = nla_get_u8(info->attrs[NL802154_ATTR_SEC_ENABLED]);
1392 		changed |= IEEE802154_LLSEC_PARAM_ENABLED;
1393 	}
1394 
1395 	if (info->attrs[NL802154_ATTR_SEC_OUT_KEY_ID]) {
1396 		ret = ieee802154_llsec_parse_key_id(info->attrs[NL802154_ATTR_SEC_OUT_KEY_ID],
1397 						    &params.out_key);
1398 		if (ret < 0)
1399 			return ret;
1400 
1401 		changed |= IEEE802154_LLSEC_PARAM_OUT_KEY;
1402 	}
1403 
1404 	if (info->attrs[NL802154_ATTR_SEC_OUT_LEVEL]) {
1405 		params.out_level = nla_get_u32(info->attrs[NL802154_ATTR_SEC_OUT_LEVEL]);
1406 		if (params.out_level > NL802154_SECLEVEL_MAX)
1407 			return -EINVAL;
1408 
1409 		changed |= IEEE802154_LLSEC_PARAM_OUT_LEVEL;
1410 	}
1411 
1412 	if (info->attrs[NL802154_ATTR_SEC_FRAME_COUNTER]) {
1413 		params.frame_counter = nla_get_be32(info->attrs[NL802154_ATTR_SEC_FRAME_COUNTER]);
1414 		changed |= IEEE802154_LLSEC_PARAM_FRAME_COUNTER;
1415 	}
1416 
1417 	return rdev_set_llsec_params(rdev, wpan_dev, &params, changed);
1418 }
1419 
1420 static int nl802154_send_key(struct sk_buff *msg, u32 cmd, u32 portid,
1421 			     u32 seq, int flags,
1422 			     struct cfg802154_registered_device *rdev,
1423 			     struct net_device *dev,
1424 			     const struct ieee802154_llsec_key_entry *key)
1425 {
1426 	void *hdr;
1427 	u32 commands[NL802154_CMD_FRAME_NR_IDS / 32];
1428 	struct nlattr *nl_key, *nl_key_id;
1429 
1430 	hdr = nl802154hdr_put(msg, portid, seq, flags, cmd);
1431 	if (!hdr)
1432 		return -1;
1433 
1434 	if (nla_put_u32(msg, NL802154_ATTR_IFINDEX, dev->ifindex))
1435 		goto nla_put_failure;
1436 
1437 	nl_key = nla_nest_start(msg, NL802154_ATTR_SEC_KEY);
1438 	if (!nl_key)
1439 		goto nla_put_failure;
1440 
1441 	nl_key_id = nla_nest_start(msg, NL802154_KEY_ATTR_ID);
1442 	if (!nl_key_id)
1443 		goto nla_put_failure;
1444 
1445 	if (ieee802154_llsec_send_key_id(msg, &key->id) < 0)
1446 		goto nla_put_failure;
1447 
1448 	nla_nest_end(msg, nl_key_id);
1449 
1450 	if (nla_put_u8(msg, NL802154_KEY_ATTR_USAGE_FRAMES,
1451 		       key->key->frame_types))
1452 		goto nla_put_failure;
1453 
1454 	if (key->key->frame_types & BIT(NL802154_FRAME_CMD)) {
1455 		/* TODO for each nested */
1456 		memset(commands, 0, sizeof(commands));
1457 		commands[7] = key->key->cmd_frame_ids;
1458 		if (nla_put(msg, NL802154_KEY_ATTR_USAGE_CMDS,
1459 			    sizeof(commands), commands))
1460 			goto nla_put_failure;
1461 	}
1462 
1463 	if (nla_put(msg, NL802154_KEY_ATTR_BYTES, NL802154_KEY_SIZE,
1464 		    key->key->key))
1465 		goto nla_put_failure;
1466 
1467 	nla_nest_end(msg, nl_key);
1468 	genlmsg_end(msg, hdr);
1469 
1470 	return 0;
1471 
1472 nla_put_failure:
1473 	genlmsg_cancel(msg, hdr);
1474 	return -EMSGSIZE;
1475 }
1476 
1477 static int
1478 nl802154_dump_llsec_key(struct sk_buff *skb, struct netlink_callback *cb)
1479 {
1480 	struct cfg802154_registered_device *rdev = NULL;
1481 	struct ieee802154_llsec_key_entry *key;
1482 	struct ieee802154_llsec_table *table;
1483 	struct wpan_dev *wpan_dev;
1484 	int err;
1485 
1486 	err = nl802154_prepare_wpan_dev_dump(skb, cb, &rdev, &wpan_dev);
1487 	if (err)
1488 		return err;
1489 
1490 	if (!wpan_dev->netdev) {
1491 		err = -EINVAL;
1492 		goto out_err;
1493 	}
1494 
1495 	rdev_lock_llsec_table(rdev, wpan_dev);
1496 	rdev_get_llsec_table(rdev, wpan_dev, &table);
1497 
1498 	/* TODO make it like station dump */
1499 	if (cb->args[2])
1500 		goto out;
1501 
1502 	list_for_each_entry(key, &table->keys, list) {
1503 		if (nl802154_send_key(skb, NL802154_CMD_NEW_SEC_KEY,
1504 				      NETLINK_CB(cb->skb).portid,
1505 				      cb->nlh->nlmsg_seq, NLM_F_MULTI,
1506 				      rdev, wpan_dev->netdev, key) < 0) {
1507 			/* TODO */
1508 			err = -EIO;
1509 			rdev_unlock_llsec_table(rdev, wpan_dev);
1510 			goto out_err;
1511 		}
1512 	}
1513 
1514 	cb->args[2] = 1;
1515 
1516 out:
1517 	rdev_unlock_llsec_table(rdev, wpan_dev);
1518 	err = skb->len;
1519 out_err:
1520 	nl802154_finish_wpan_dev_dump(rdev);
1521 
1522 	return err;
1523 }
1524 
1525 static const struct nla_policy nl802154_key_policy[NL802154_KEY_ATTR_MAX + 1] = {
1526 	[NL802154_KEY_ATTR_ID] = { NLA_NESTED },
1527 	/* TODO handle it as for_each_nested and NLA_FLAG? */
1528 	[NL802154_KEY_ATTR_USAGE_FRAMES] = { NLA_U8 },
1529 	/* TODO handle it as for_each_nested, not static array? */
1530 	[NL802154_KEY_ATTR_USAGE_CMDS] = { .len = NL802154_CMD_FRAME_NR_IDS / 8 },
1531 	[NL802154_KEY_ATTR_BYTES] = { .len = NL802154_KEY_SIZE },
1532 };
1533 
1534 static int nl802154_add_llsec_key(struct sk_buff *skb, struct genl_info *info)
1535 {
1536 	struct cfg802154_registered_device *rdev = info->user_ptr[0];
1537 	struct net_device *dev = info->user_ptr[1];
1538 	struct wpan_dev *wpan_dev = dev->ieee802154_ptr;
1539 	struct nlattr *attrs[NL802154_KEY_ATTR_MAX + 1];
1540 	struct ieee802154_llsec_key key = { };
1541 	struct ieee802154_llsec_key_id id = { };
1542 	u32 commands[NL802154_CMD_FRAME_NR_IDS / 32] = { };
1543 
1544 	if (nla_parse_nested(attrs, NL802154_KEY_ATTR_MAX,
1545 			     info->attrs[NL802154_ATTR_SEC_KEY],
1546 			     nl802154_key_policy))
1547 		return -EINVAL;
1548 
1549 	if (!attrs[NL802154_KEY_ATTR_USAGE_FRAMES] ||
1550 	    !attrs[NL802154_KEY_ATTR_BYTES])
1551 		return -EINVAL;
1552 
1553 	if (ieee802154_llsec_parse_key_id(attrs[NL802154_KEY_ATTR_ID], &id) < 0)
1554 		return -ENOBUFS;
1555 
1556 	key.frame_types = nla_get_u8(attrs[NL802154_KEY_ATTR_USAGE_FRAMES]);
1557 	if (key.frame_types > BIT(NL802154_FRAME_MAX) ||
1558 	    ((key.frame_types & BIT(NL802154_FRAME_CMD)) &&
1559 	     !attrs[NL802154_KEY_ATTR_USAGE_CMDS]))
1560 		return -EINVAL;
1561 
1562 	if (attrs[NL802154_KEY_ATTR_USAGE_CMDS]) {
1563 		/* TODO for each nested */
1564 		nla_memcpy(commands, attrs[NL802154_KEY_ATTR_USAGE_CMDS],
1565 			   NL802154_CMD_FRAME_NR_IDS / 8);
1566 
1567 		/* TODO understand the -EINVAL logic here? last condition */
1568 		if (commands[0] || commands[1] || commands[2] || commands[3] ||
1569 		    commands[4] || commands[5] || commands[6] ||
1570 		    commands[7] > BIT(NL802154_CMD_FRAME_MAX))
1571 			return -EINVAL;
1572 
1573 		key.cmd_frame_ids = commands[7];
1574 	} else {
1575 		key.cmd_frame_ids = 0;
1576 	}
1577 
1578 	nla_memcpy(key.key, attrs[NL802154_KEY_ATTR_BYTES], NL802154_KEY_SIZE);
1579 
1580 	if (ieee802154_llsec_parse_key_id(attrs[NL802154_KEY_ATTR_ID], &id) < 0)
1581 		return -ENOBUFS;
1582 
1583 	return rdev_add_llsec_key(rdev, wpan_dev, &id, &key);
1584 }
1585 
1586 static int nl802154_del_llsec_key(struct sk_buff *skb, struct genl_info *info)
1587 {
1588 	struct cfg802154_registered_device *rdev = info->user_ptr[0];
1589 	struct net_device *dev = info->user_ptr[1];
1590 	struct wpan_dev *wpan_dev = dev->ieee802154_ptr;
1591 	struct nlattr *attrs[NL802154_KEY_ATTR_MAX + 1];
1592 	struct ieee802154_llsec_key_id id;
1593 
1594 	if (nla_parse_nested(attrs, NL802154_KEY_ATTR_MAX,
1595 			     info->attrs[NL802154_ATTR_SEC_KEY],
1596 			     nl802154_key_policy))
1597 		return -EINVAL;
1598 
1599 	if (ieee802154_llsec_parse_key_id(attrs[NL802154_KEY_ATTR_ID], &id) < 0)
1600 		return -ENOBUFS;
1601 
1602 	return rdev_del_llsec_key(rdev, wpan_dev, &id);
1603 }
1604 
1605 static int nl802154_send_device(struct sk_buff *msg, u32 cmd, u32 portid,
1606 				u32 seq, int flags,
1607 				struct cfg802154_registered_device *rdev,
1608 				struct net_device *dev,
1609 				const struct ieee802154_llsec_device *dev_desc)
1610 {
1611 	void *hdr;
1612 	struct nlattr *nl_device;
1613 
1614 	hdr = nl802154hdr_put(msg, portid, seq, flags, cmd);
1615 	if (!hdr)
1616 		return -1;
1617 
1618 	if (nla_put_u32(msg, NL802154_ATTR_IFINDEX, dev->ifindex))
1619 		goto nla_put_failure;
1620 
1621 	nl_device = nla_nest_start(msg, NL802154_ATTR_SEC_DEVICE);
1622 	if (!nl_device)
1623 		goto nla_put_failure;
1624 
1625 	if (nla_put_u32(msg, NL802154_DEV_ATTR_FRAME_COUNTER,
1626 			dev_desc->frame_counter) ||
1627 	    nla_put_le16(msg, NL802154_DEV_ATTR_PAN_ID, dev_desc->pan_id) ||
1628 	    nla_put_le16(msg, NL802154_DEV_ATTR_SHORT_ADDR,
1629 			 dev_desc->short_addr) ||
1630 	    nla_put_le64(msg, NL802154_DEV_ATTR_EXTENDED_ADDR,
1631 			 dev_desc->hwaddr, NL802154_DEV_ATTR_PAD) ||
1632 	    nla_put_u8(msg, NL802154_DEV_ATTR_SECLEVEL_EXEMPT,
1633 		       dev_desc->seclevel_exempt) ||
1634 	    nla_put_u32(msg, NL802154_DEV_ATTR_KEY_MODE, dev_desc->key_mode))
1635 		goto nla_put_failure;
1636 
1637 	nla_nest_end(msg, nl_device);
1638 	genlmsg_end(msg, hdr);
1639 
1640 	return 0;
1641 
1642 nla_put_failure:
1643 	genlmsg_cancel(msg, hdr);
1644 	return -EMSGSIZE;
1645 }
1646 
1647 static int
1648 nl802154_dump_llsec_dev(struct sk_buff *skb, struct netlink_callback *cb)
1649 {
1650 	struct cfg802154_registered_device *rdev = NULL;
1651 	struct ieee802154_llsec_device *dev;
1652 	struct ieee802154_llsec_table *table;
1653 	struct wpan_dev *wpan_dev;
1654 	int err;
1655 
1656 	err = nl802154_prepare_wpan_dev_dump(skb, cb, &rdev, &wpan_dev);
1657 	if (err)
1658 		return err;
1659 
1660 	if (!wpan_dev->netdev) {
1661 		err = -EINVAL;
1662 		goto out_err;
1663 	}
1664 
1665 	rdev_lock_llsec_table(rdev, wpan_dev);
1666 	rdev_get_llsec_table(rdev, wpan_dev, &table);
1667 
1668 	/* TODO make it like station dump */
1669 	if (cb->args[2])
1670 		goto out;
1671 
1672 	list_for_each_entry(dev, &table->devices, list) {
1673 		if (nl802154_send_device(skb, NL802154_CMD_NEW_SEC_LEVEL,
1674 					 NETLINK_CB(cb->skb).portid,
1675 					 cb->nlh->nlmsg_seq, NLM_F_MULTI,
1676 					 rdev, wpan_dev->netdev, dev) < 0) {
1677 			/* TODO */
1678 			err = -EIO;
1679 			rdev_unlock_llsec_table(rdev, wpan_dev);
1680 			goto out_err;
1681 		}
1682 	}
1683 
1684 	cb->args[2] = 1;
1685 
1686 out:
1687 	rdev_unlock_llsec_table(rdev, wpan_dev);
1688 	err = skb->len;
1689 out_err:
1690 	nl802154_finish_wpan_dev_dump(rdev);
1691 
1692 	return err;
1693 }
1694 
1695 static const struct nla_policy nl802154_dev_policy[NL802154_DEV_ATTR_MAX + 1] = {
1696 	[NL802154_DEV_ATTR_FRAME_COUNTER] = { NLA_U32 },
1697 	[NL802154_DEV_ATTR_PAN_ID] = { .type = NLA_U16 },
1698 	[NL802154_DEV_ATTR_SHORT_ADDR] = { .type = NLA_U16 },
1699 	[NL802154_DEV_ATTR_EXTENDED_ADDR] = { .type = NLA_U64 },
1700 	[NL802154_DEV_ATTR_SECLEVEL_EXEMPT] = { NLA_U8 },
1701 	[NL802154_DEV_ATTR_KEY_MODE] = { NLA_U32 },
1702 };
1703 
1704 static int
1705 ieee802154_llsec_parse_device(struct nlattr *nla,
1706 			      struct ieee802154_llsec_device *dev)
1707 {
1708 	struct nlattr *attrs[NL802154_DEV_ATTR_MAX + 1];
1709 
1710 	if (!nla || nla_parse_nested(attrs, NL802154_DEV_ATTR_MAX, nla,
1711 				     nl802154_dev_policy))
1712 		return -EINVAL;
1713 
1714 	memset(dev, 0, sizeof(*dev));
1715 
1716 	if (!attrs[NL802154_DEV_ATTR_FRAME_COUNTER] ||
1717 	    !attrs[NL802154_DEV_ATTR_PAN_ID] ||
1718 	    !attrs[NL802154_DEV_ATTR_SHORT_ADDR] ||
1719 	    !attrs[NL802154_DEV_ATTR_EXTENDED_ADDR] ||
1720 	    !attrs[NL802154_DEV_ATTR_SECLEVEL_EXEMPT] ||
1721 	    !attrs[NL802154_DEV_ATTR_KEY_MODE])
1722 		return -EINVAL;
1723 
1724 	/* TODO be32 */
1725 	dev->frame_counter = nla_get_u32(attrs[NL802154_DEV_ATTR_FRAME_COUNTER]);
1726 	dev->pan_id = nla_get_le16(attrs[NL802154_DEV_ATTR_PAN_ID]);
1727 	dev->short_addr = nla_get_le16(attrs[NL802154_DEV_ATTR_SHORT_ADDR]);
1728 	/* TODO rename hwaddr to extended_addr */
1729 	dev->hwaddr = nla_get_le64(attrs[NL802154_DEV_ATTR_EXTENDED_ADDR]);
1730 	dev->seclevel_exempt = nla_get_u8(attrs[NL802154_DEV_ATTR_SECLEVEL_EXEMPT]);
1731 	dev->key_mode = nla_get_u32(attrs[NL802154_DEV_ATTR_KEY_MODE]);
1732 
1733 	if (dev->key_mode > NL802154_DEVKEY_MAX ||
1734 	    (dev->seclevel_exempt != 0 && dev->seclevel_exempt != 1))
1735 		return -EINVAL;
1736 
1737 	return 0;
1738 }
1739 
1740 static int nl802154_add_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 ieee802154_llsec_device dev_desc;
1746 
1747 	if (ieee802154_llsec_parse_device(info->attrs[NL802154_ATTR_SEC_DEVICE],
1748 					  &dev_desc) < 0)
1749 		return -EINVAL;
1750 
1751 	return rdev_add_device(rdev, wpan_dev, &dev_desc);
1752 }
1753 
1754 static int nl802154_del_llsec_dev(struct sk_buff *skb, struct genl_info *info)
1755 {
1756 	struct cfg802154_registered_device *rdev = info->user_ptr[0];
1757 	struct net_device *dev = info->user_ptr[1];
1758 	struct wpan_dev *wpan_dev = dev->ieee802154_ptr;
1759 	struct nlattr *attrs[NL802154_DEV_ATTR_MAX + 1];
1760 	__le64 extended_addr;
1761 
1762 	if (nla_parse_nested(attrs, NL802154_DEV_ATTR_MAX,
1763 			     info->attrs[NL802154_ATTR_SEC_DEVICE],
1764 			     nl802154_dev_policy))
1765 		return -EINVAL;
1766 
1767 	if (!attrs[NL802154_DEV_ATTR_EXTENDED_ADDR])
1768 		return -EINVAL;
1769 
1770 	extended_addr = nla_get_le64(attrs[NL802154_DEV_ATTR_EXTENDED_ADDR]);
1771 	return rdev_del_device(rdev, wpan_dev, extended_addr);
1772 }
1773 
1774 static int nl802154_send_devkey(struct sk_buff *msg, u32 cmd, u32 portid,
1775 				u32 seq, int flags,
1776 				struct cfg802154_registered_device *rdev,
1777 				struct net_device *dev, __le64 extended_addr,
1778 				const struct ieee802154_llsec_device_key *devkey)
1779 {
1780 	void *hdr;
1781 	struct nlattr *nl_devkey, *nl_key_id;
1782 
1783 	hdr = nl802154hdr_put(msg, portid, seq, flags, cmd);
1784 	if (!hdr)
1785 		return -1;
1786 
1787 	if (nla_put_u32(msg, NL802154_ATTR_IFINDEX, dev->ifindex))
1788 		goto nla_put_failure;
1789 
1790 	nl_devkey = nla_nest_start(msg, NL802154_ATTR_SEC_DEVKEY);
1791 	if (!nl_devkey)
1792 		goto nla_put_failure;
1793 
1794 	if (nla_put_le64(msg, NL802154_DEVKEY_ATTR_EXTENDED_ADDR,
1795 			 extended_addr, NL802154_DEVKEY_ATTR_PAD) ||
1796 	    nla_put_u32(msg, NL802154_DEVKEY_ATTR_FRAME_COUNTER,
1797 			devkey->frame_counter))
1798 		goto nla_put_failure;
1799 
1800 	nl_key_id = nla_nest_start(msg, NL802154_DEVKEY_ATTR_ID);
1801 	if (!nl_key_id)
1802 		goto nla_put_failure;
1803 
1804 	if (ieee802154_llsec_send_key_id(msg, &devkey->key_id) < 0)
1805 		goto nla_put_failure;
1806 
1807 	nla_nest_end(msg, nl_key_id);
1808 	nla_nest_end(msg, nl_devkey);
1809 	genlmsg_end(msg, hdr);
1810 
1811 	return 0;
1812 
1813 nla_put_failure:
1814 	genlmsg_cancel(msg, hdr);
1815 	return -EMSGSIZE;
1816 }
1817 
1818 static int
1819 nl802154_dump_llsec_devkey(struct sk_buff *skb, struct netlink_callback *cb)
1820 {
1821 	struct cfg802154_registered_device *rdev = NULL;
1822 	struct ieee802154_llsec_device_key *kpos;
1823 	struct ieee802154_llsec_device *dpos;
1824 	struct ieee802154_llsec_table *table;
1825 	struct wpan_dev *wpan_dev;
1826 	int err;
1827 
1828 	err = nl802154_prepare_wpan_dev_dump(skb, cb, &rdev, &wpan_dev);
1829 	if (err)
1830 		return err;
1831 
1832 	if (!wpan_dev->netdev) {
1833 		err = -EINVAL;
1834 		goto out_err;
1835 	}
1836 
1837 	rdev_lock_llsec_table(rdev, wpan_dev);
1838 	rdev_get_llsec_table(rdev, wpan_dev, &table);
1839 
1840 	/* TODO make it like station dump */
1841 	if (cb->args[2])
1842 		goto out;
1843 
1844 	/* TODO look if remove devkey and do some nested attribute */
1845 	list_for_each_entry(dpos, &table->devices, list) {
1846 		list_for_each_entry(kpos, &dpos->keys, list) {
1847 			if (nl802154_send_devkey(skb,
1848 						 NL802154_CMD_NEW_SEC_LEVEL,
1849 						 NETLINK_CB(cb->skb).portid,
1850 						 cb->nlh->nlmsg_seq,
1851 						 NLM_F_MULTI, rdev,
1852 						 wpan_dev->netdev,
1853 						 dpos->hwaddr,
1854 						 kpos) < 0) {
1855 				/* TODO */
1856 				err = -EIO;
1857 				rdev_unlock_llsec_table(rdev, wpan_dev);
1858 				goto out_err;
1859 			}
1860 		}
1861 	}
1862 
1863 	cb->args[2] = 1;
1864 
1865 out:
1866 	rdev_unlock_llsec_table(rdev, wpan_dev);
1867 	err = skb->len;
1868 out_err:
1869 	nl802154_finish_wpan_dev_dump(rdev);
1870 
1871 	return err;
1872 }
1873 
1874 static const struct nla_policy nl802154_devkey_policy[NL802154_DEVKEY_ATTR_MAX + 1] = {
1875 	[NL802154_DEVKEY_ATTR_FRAME_COUNTER] = { NLA_U32 },
1876 	[NL802154_DEVKEY_ATTR_EXTENDED_ADDR] = { NLA_U64 },
1877 	[NL802154_DEVKEY_ATTR_ID] = { NLA_NESTED },
1878 };
1879 
1880 static int nl802154_add_llsec_devkey(struct sk_buff *skb, struct genl_info *info)
1881 {
1882 	struct cfg802154_registered_device *rdev = info->user_ptr[0];
1883 	struct net_device *dev = info->user_ptr[1];
1884 	struct wpan_dev *wpan_dev = dev->ieee802154_ptr;
1885 	struct nlattr *attrs[NL802154_DEVKEY_ATTR_MAX + 1];
1886 	struct ieee802154_llsec_device_key key;
1887 	__le64 extended_addr;
1888 
1889 	if (!info->attrs[NL802154_ATTR_SEC_DEVKEY] ||
1890 	    nla_parse_nested(attrs, NL802154_DEVKEY_ATTR_MAX,
1891 			     info->attrs[NL802154_ATTR_SEC_DEVKEY],
1892 			     nl802154_devkey_policy) < 0)
1893 		return -EINVAL;
1894 
1895 	if (!attrs[NL802154_DEVKEY_ATTR_FRAME_COUNTER] ||
1896 	    !attrs[NL802154_DEVKEY_ATTR_EXTENDED_ADDR])
1897 		return -EINVAL;
1898 
1899 	/* TODO change key.id ? */
1900 	if (ieee802154_llsec_parse_key_id(attrs[NL802154_DEVKEY_ATTR_ID],
1901 					  &key.key_id) < 0)
1902 		return -ENOBUFS;
1903 
1904 	/* TODO be32 */
1905 	key.frame_counter = nla_get_u32(attrs[NL802154_DEVKEY_ATTR_FRAME_COUNTER]);
1906 	/* TODO change naming hwaddr -> extended_addr
1907 	 * check unique identifier short+pan OR extended_addr
1908 	 */
1909 	extended_addr = nla_get_le64(attrs[NL802154_DEVKEY_ATTR_EXTENDED_ADDR]);
1910 	return rdev_add_devkey(rdev, wpan_dev, extended_addr, &key);
1911 }
1912 
1913 static int nl802154_del_llsec_devkey(struct sk_buff *skb, struct genl_info *info)
1914 {
1915 	struct cfg802154_registered_device *rdev = info->user_ptr[0];
1916 	struct net_device *dev = info->user_ptr[1];
1917 	struct wpan_dev *wpan_dev = dev->ieee802154_ptr;
1918 	struct nlattr *attrs[NL802154_DEVKEY_ATTR_MAX + 1];
1919 	struct ieee802154_llsec_device_key key;
1920 	__le64 extended_addr;
1921 
1922 	if (nla_parse_nested(attrs, NL802154_DEVKEY_ATTR_MAX,
1923 			     info->attrs[NL802154_ATTR_SEC_DEVKEY],
1924 			     nl802154_devkey_policy))
1925 		return -EINVAL;
1926 
1927 	if (!attrs[NL802154_DEVKEY_ATTR_EXTENDED_ADDR])
1928 		return -EINVAL;
1929 
1930 	/* TODO change key.id ? */
1931 	if (ieee802154_llsec_parse_key_id(attrs[NL802154_DEVKEY_ATTR_ID],
1932 					  &key.key_id) < 0)
1933 		return -ENOBUFS;
1934 
1935 	/* TODO change naming hwaddr -> extended_addr
1936 	 * check unique identifier short+pan OR extended_addr
1937 	 */
1938 	extended_addr = nla_get_le64(attrs[NL802154_DEVKEY_ATTR_EXTENDED_ADDR]);
1939 	return rdev_del_devkey(rdev, wpan_dev, extended_addr, &key);
1940 }
1941 
1942 static int nl802154_send_seclevel(struct sk_buff *msg, u32 cmd, u32 portid,
1943 				  u32 seq, int flags,
1944 				  struct cfg802154_registered_device *rdev,
1945 				  struct net_device *dev,
1946 				  const struct ieee802154_llsec_seclevel *sl)
1947 {
1948 	void *hdr;
1949 	struct nlattr *nl_seclevel;
1950 
1951 	hdr = nl802154hdr_put(msg, portid, seq, flags, cmd);
1952 	if (!hdr)
1953 		return -1;
1954 
1955 	if (nla_put_u32(msg, NL802154_ATTR_IFINDEX, dev->ifindex))
1956 		goto nla_put_failure;
1957 
1958 	nl_seclevel = nla_nest_start(msg, NL802154_ATTR_SEC_LEVEL);
1959 	if (!nl_seclevel)
1960 		goto nla_put_failure;
1961 
1962 	if (nla_put_u32(msg, NL802154_SECLEVEL_ATTR_FRAME, sl->frame_type) ||
1963 	    nla_put_u32(msg, NL802154_SECLEVEL_ATTR_LEVELS, sl->sec_levels) ||
1964 	    nla_put_u8(msg, NL802154_SECLEVEL_ATTR_DEV_OVERRIDE,
1965 		       sl->device_override))
1966 		goto nla_put_failure;
1967 
1968 	if (sl->frame_type == NL802154_FRAME_CMD) {
1969 		if (nla_put_u32(msg, NL802154_SECLEVEL_ATTR_CMD_FRAME,
1970 				sl->cmd_frame_id))
1971 			goto nla_put_failure;
1972 	}
1973 
1974 	nla_nest_end(msg, nl_seclevel);
1975 	genlmsg_end(msg, hdr);
1976 
1977 	return 0;
1978 
1979 nla_put_failure:
1980 	genlmsg_cancel(msg, hdr);
1981 	return -EMSGSIZE;
1982 }
1983 
1984 static int
1985 nl802154_dump_llsec_seclevel(struct sk_buff *skb, struct netlink_callback *cb)
1986 {
1987 	struct cfg802154_registered_device *rdev = NULL;
1988 	struct ieee802154_llsec_seclevel *sl;
1989 	struct ieee802154_llsec_table *table;
1990 	struct wpan_dev *wpan_dev;
1991 	int err;
1992 
1993 	err = nl802154_prepare_wpan_dev_dump(skb, cb, &rdev, &wpan_dev);
1994 	if (err)
1995 		return err;
1996 
1997 	if (!wpan_dev->netdev) {
1998 		err = -EINVAL;
1999 		goto out_err;
2000 	}
2001 
2002 	rdev_lock_llsec_table(rdev, wpan_dev);
2003 	rdev_get_llsec_table(rdev, wpan_dev, &table);
2004 
2005 	/* TODO make it like station dump */
2006 	if (cb->args[2])
2007 		goto out;
2008 
2009 	list_for_each_entry(sl, &table->security_levels, list) {
2010 		if (nl802154_send_seclevel(skb, NL802154_CMD_NEW_SEC_LEVEL,
2011 					   NETLINK_CB(cb->skb).portid,
2012 					   cb->nlh->nlmsg_seq, NLM_F_MULTI,
2013 					   rdev, wpan_dev->netdev, sl) < 0) {
2014 			/* TODO */
2015 			err = -EIO;
2016 			rdev_unlock_llsec_table(rdev, wpan_dev);
2017 			goto out_err;
2018 		}
2019 	}
2020 
2021 	cb->args[2] = 1;
2022 
2023 out:
2024 	rdev_unlock_llsec_table(rdev, wpan_dev);
2025 	err = skb->len;
2026 out_err:
2027 	nl802154_finish_wpan_dev_dump(rdev);
2028 
2029 	return err;
2030 }
2031 
2032 static const struct nla_policy nl802154_seclevel_policy[NL802154_SECLEVEL_ATTR_MAX + 1] = {
2033 	[NL802154_SECLEVEL_ATTR_LEVELS] = { .type = NLA_U8 },
2034 	[NL802154_SECLEVEL_ATTR_FRAME] = { .type = NLA_U32 },
2035 	[NL802154_SECLEVEL_ATTR_CMD_FRAME] = { .type = NLA_U32 },
2036 	[NL802154_SECLEVEL_ATTR_DEV_OVERRIDE] = { .type = NLA_U8 },
2037 };
2038 
2039 static int
2040 llsec_parse_seclevel(struct nlattr *nla, struct ieee802154_llsec_seclevel *sl)
2041 {
2042 	struct nlattr *attrs[NL802154_SECLEVEL_ATTR_MAX + 1];
2043 
2044 	if (!nla || nla_parse_nested(attrs, NL802154_SECLEVEL_ATTR_MAX, nla,
2045 				     nl802154_seclevel_policy))
2046 		return -EINVAL;
2047 
2048 	memset(sl, 0, sizeof(*sl));
2049 
2050 	if (!attrs[NL802154_SECLEVEL_ATTR_LEVELS] ||
2051 	    !attrs[NL802154_SECLEVEL_ATTR_FRAME] ||
2052 	    !attrs[NL802154_SECLEVEL_ATTR_DEV_OVERRIDE])
2053 		return -EINVAL;
2054 
2055 	sl->sec_levels = nla_get_u8(attrs[NL802154_SECLEVEL_ATTR_LEVELS]);
2056 	sl->frame_type = nla_get_u32(attrs[NL802154_SECLEVEL_ATTR_FRAME]);
2057 	sl->device_override = nla_get_u8(attrs[NL802154_SECLEVEL_ATTR_DEV_OVERRIDE]);
2058 	if (sl->frame_type > NL802154_FRAME_MAX ||
2059 	    (sl->device_override != 0 && sl->device_override != 1))
2060 		return -EINVAL;
2061 
2062 	if (sl->frame_type == NL802154_FRAME_CMD) {
2063 		if (!attrs[NL802154_SECLEVEL_ATTR_CMD_FRAME])
2064 			return -EINVAL;
2065 
2066 		sl->cmd_frame_id = nla_get_u32(attrs[NL802154_SECLEVEL_ATTR_CMD_FRAME]);
2067 		if (sl->cmd_frame_id > NL802154_CMD_FRAME_MAX)
2068 			return -EINVAL;
2069 	}
2070 
2071 	return 0;
2072 }
2073 
2074 static int nl802154_add_llsec_seclevel(struct sk_buff *skb,
2075 				       struct genl_info *info)
2076 {
2077 	struct cfg802154_registered_device *rdev = info->user_ptr[0];
2078 	struct net_device *dev = info->user_ptr[1];
2079 	struct wpan_dev *wpan_dev = dev->ieee802154_ptr;
2080 	struct ieee802154_llsec_seclevel sl;
2081 
2082 	if (llsec_parse_seclevel(info->attrs[NL802154_ATTR_SEC_LEVEL],
2083 				 &sl) < 0)
2084 		return -EINVAL;
2085 
2086 	return rdev_add_seclevel(rdev, wpan_dev, &sl);
2087 }
2088 
2089 static int nl802154_del_llsec_seclevel(struct sk_buff *skb,
2090 				       struct genl_info *info)
2091 {
2092 	struct cfg802154_registered_device *rdev = info->user_ptr[0];
2093 	struct net_device *dev = info->user_ptr[1];
2094 	struct wpan_dev *wpan_dev = dev->ieee802154_ptr;
2095 	struct ieee802154_llsec_seclevel sl;
2096 
2097 	if (!info->attrs[NL802154_ATTR_SEC_LEVEL] ||
2098 	    llsec_parse_seclevel(info->attrs[NL802154_ATTR_SEC_LEVEL],
2099 				 &sl) < 0)
2100 		return -EINVAL;
2101 
2102 	return rdev_del_seclevel(rdev, wpan_dev, &sl);
2103 }
2104 #endif /* CONFIG_IEEE802154_NL802154_EXPERIMENTAL */
2105 
2106 #define NL802154_FLAG_NEED_WPAN_PHY	0x01
2107 #define NL802154_FLAG_NEED_NETDEV	0x02
2108 #define NL802154_FLAG_NEED_RTNL		0x04
2109 #define NL802154_FLAG_CHECK_NETDEV_UP	0x08
2110 #define NL802154_FLAG_NEED_NETDEV_UP	(NL802154_FLAG_NEED_NETDEV |\
2111 					 NL802154_FLAG_CHECK_NETDEV_UP)
2112 #define NL802154_FLAG_NEED_WPAN_DEV	0x10
2113 #define NL802154_FLAG_NEED_WPAN_DEV_UP	(NL802154_FLAG_NEED_WPAN_DEV |\
2114 					 NL802154_FLAG_CHECK_NETDEV_UP)
2115 
2116 static int nl802154_pre_doit(const struct genl_ops *ops, struct sk_buff *skb,
2117 			     struct genl_info *info)
2118 {
2119 	struct cfg802154_registered_device *rdev;
2120 	struct wpan_dev *wpan_dev;
2121 	struct net_device *dev;
2122 	bool rtnl = ops->internal_flags & NL802154_FLAG_NEED_RTNL;
2123 
2124 	if (rtnl)
2125 		rtnl_lock();
2126 
2127 	if (ops->internal_flags & NL802154_FLAG_NEED_WPAN_PHY) {
2128 		rdev = cfg802154_get_dev_from_info(genl_info_net(info), info);
2129 		if (IS_ERR(rdev)) {
2130 			if (rtnl)
2131 				rtnl_unlock();
2132 			return PTR_ERR(rdev);
2133 		}
2134 		info->user_ptr[0] = rdev;
2135 	} else if (ops->internal_flags & NL802154_FLAG_NEED_NETDEV ||
2136 		   ops->internal_flags & NL802154_FLAG_NEED_WPAN_DEV) {
2137 		ASSERT_RTNL();
2138 		wpan_dev = __cfg802154_wpan_dev_from_attrs(genl_info_net(info),
2139 							   info->attrs);
2140 		if (IS_ERR(wpan_dev)) {
2141 			if (rtnl)
2142 				rtnl_unlock();
2143 			return PTR_ERR(wpan_dev);
2144 		}
2145 
2146 		dev = wpan_dev->netdev;
2147 		rdev = wpan_phy_to_rdev(wpan_dev->wpan_phy);
2148 
2149 		if (ops->internal_flags & NL802154_FLAG_NEED_NETDEV) {
2150 			if (!dev) {
2151 				if (rtnl)
2152 					rtnl_unlock();
2153 				return -EINVAL;
2154 			}
2155 
2156 			info->user_ptr[1] = dev;
2157 		} else {
2158 			info->user_ptr[1] = wpan_dev;
2159 		}
2160 
2161 		if (dev) {
2162 			if (ops->internal_flags & NL802154_FLAG_CHECK_NETDEV_UP &&
2163 			    !netif_running(dev)) {
2164 				if (rtnl)
2165 					rtnl_unlock();
2166 				return -ENETDOWN;
2167 			}
2168 
2169 			dev_hold(dev);
2170 		}
2171 
2172 		info->user_ptr[0] = rdev;
2173 	}
2174 
2175 	return 0;
2176 }
2177 
2178 static void nl802154_post_doit(const struct genl_ops *ops, struct sk_buff *skb,
2179 			       struct genl_info *info)
2180 {
2181 	if (info->user_ptr[1]) {
2182 		if (ops->internal_flags & NL802154_FLAG_NEED_WPAN_DEV) {
2183 			struct wpan_dev *wpan_dev = info->user_ptr[1];
2184 
2185 			if (wpan_dev->netdev)
2186 				dev_put(wpan_dev->netdev);
2187 		} else {
2188 			dev_put(info->user_ptr[1]);
2189 		}
2190 	}
2191 
2192 	if (ops->internal_flags & NL802154_FLAG_NEED_RTNL)
2193 		rtnl_unlock();
2194 }
2195 
2196 static const struct genl_ops nl802154_ops[] = {
2197 	{
2198 		.cmd = NL802154_CMD_GET_WPAN_PHY,
2199 		.doit = nl802154_get_wpan_phy,
2200 		.dumpit = nl802154_dump_wpan_phy,
2201 		.done = nl802154_dump_wpan_phy_done,
2202 		.policy = nl802154_policy,
2203 		/* can be retrieved by unprivileged users */
2204 		.internal_flags = NL802154_FLAG_NEED_WPAN_PHY |
2205 				  NL802154_FLAG_NEED_RTNL,
2206 	},
2207 	{
2208 		.cmd = NL802154_CMD_GET_INTERFACE,
2209 		.doit = nl802154_get_interface,
2210 		.dumpit = nl802154_dump_interface,
2211 		.policy = nl802154_policy,
2212 		/* can be retrieved by unprivileged users */
2213 		.internal_flags = NL802154_FLAG_NEED_WPAN_DEV |
2214 				  NL802154_FLAG_NEED_RTNL,
2215 	},
2216 	{
2217 		.cmd = NL802154_CMD_NEW_INTERFACE,
2218 		.doit = nl802154_new_interface,
2219 		.policy = nl802154_policy,
2220 		.flags = GENL_ADMIN_PERM,
2221 		.internal_flags = NL802154_FLAG_NEED_WPAN_PHY |
2222 				  NL802154_FLAG_NEED_RTNL,
2223 	},
2224 	{
2225 		.cmd = NL802154_CMD_DEL_INTERFACE,
2226 		.doit = nl802154_del_interface,
2227 		.policy = nl802154_policy,
2228 		.flags = GENL_ADMIN_PERM,
2229 		.internal_flags = NL802154_FLAG_NEED_WPAN_DEV |
2230 				  NL802154_FLAG_NEED_RTNL,
2231 	},
2232 	{
2233 		.cmd = NL802154_CMD_SET_CHANNEL,
2234 		.doit = nl802154_set_channel,
2235 		.policy = nl802154_policy,
2236 		.flags = GENL_ADMIN_PERM,
2237 		.internal_flags = NL802154_FLAG_NEED_WPAN_PHY |
2238 				  NL802154_FLAG_NEED_RTNL,
2239 	},
2240 	{
2241 		.cmd = NL802154_CMD_SET_CCA_MODE,
2242 		.doit = nl802154_set_cca_mode,
2243 		.policy = nl802154_policy,
2244 		.flags = GENL_ADMIN_PERM,
2245 		.internal_flags = NL802154_FLAG_NEED_WPAN_PHY |
2246 				  NL802154_FLAG_NEED_RTNL,
2247 	},
2248 	{
2249 		.cmd = NL802154_CMD_SET_CCA_ED_LEVEL,
2250 		.doit = nl802154_set_cca_ed_level,
2251 		.policy = nl802154_policy,
2252 		.flags = GENL_ADMIN_PERM,
2253 		.internal_flags = NL802154_FLAG_NEED_WPAN_PHY |
2254 				  NL802154_FLAG_NEED_RTNL,
2255 	},
2256 	{
2257 		.cmd = NL802154_CMD_SET_TX_POWER,
2258 		.doit = nl802154_set_tx_power,
2259 		.policy = nl802154_policy,
2260 		.flags = GENL_ADMIN_PERM,
2261 		.internal_flags = NL802154_FLAG_NEED_WPAN_PHY |
2262 				  NL802154_FLAG_NEED_RTNL,
2263 	},
2264 	{
2265 		.cmd = NL802154_CMD_SET_PAN_ID,
2266 		.doit = nl802154_set_pan_id,
2267 		.policy = nl802154_policy,
2268 		.flags = GENL_ADMIN_PERM,
2269 		.internal_flags = NL802154_FLAG_NEED_NETDEV |
2270 				  NL802154_FLAG_NEED_RTNL,
2271 	},
2272 	{
2273 		.cmd = NL802154_CMD_SET_SHORT_ADDR,
2274 		.doit = nl802154_set_short_addr,
2275 		.policy = nl802154_policy,
2276 		.flags = GENL_ADMIN_PERM,
2277 		.internal_flags = NL802154_FLAG_NEED_NETDEV |
2278 				  NL802154_FLAG_NEED_RTNL,
2279 	},
2280 	{
2281 		.cmd = NL802154_CMD_SET_BACKOFF_EXPONENT,
2282 		.doit = nl802154_set_backoff_exponent,
2283 		.policy = nl802154_policy,
2284 		.flags = GENL_ADMIN_PERM,
2285 		.internal_flags = NL802154_FLAG_NEED_NETDEV |
2286 				  NL802154_FLAG_NEED_RTNL,
2287 	},
2288 	{
2289 		.cmd = NL802154_CMD_SET_MAX_CSMA_BACKOFFS,
2290 		.doit = nl802154_set_max_csma_backoffs,
2291 		.policy = nl802154_policy,
2292 		.flags = GENL_ADMIN_PERM,
2293 		.internal_flags = NL802154_FLAG_NEED_NETDEV |
2294 				  NL802154_FLAG_NEED_RTNL,
2295 	},
2296 	{
2297 		.cmd = NL802154_CMD_SET_MAX_FRAME_RETRIES,
2298 		.doit = nl802154_set_max_frame_retries,
2299 		.policy = nl802154_policy,
2300 		.flags = GENL_ADMIN_PERM,
2301 		.internal_flags = NL802154_FLAG_NEED_NETDEV |
2302 				  NL802154_FLAG_NEED_RTNL,
2303 	},
2304 	{
2305 		.cmd = NL802154_CMD_SET_LBT_MODE,
2306 		.doit = nl802154_set_lbt_mode,
2307 		.policy = nl802154_policy,
2308 		.flags = GENL_ADMIN_PERM,
2309 		.internal_flags = NL802154_FLAG_NEED_NETDEV |
2310 				  NL802154_FLAG_NEED_RTNL,
2311 	},
2312 	{
2313 		.cmd = NL802154_CMD_SET_ACKREQ_DEFAULT,
2314 		.doit = nl802154_set_ackreq_default,
2315 		.policy = nl802154_policy,
2316 		.flags = GENL_ADMIN_PERM,
2317 		.internal_flags = NL802154_FLAG_NEED_NETDEV |
2318 				  NL802154_FLAG_NEED_RTNL,
2319 	},
2320 #ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL
2321 	{
2322 		.cmd = NL802154_CMD_SET_SEC_PARAMS,
2323 		.doit = nl802154_set_llsec_params,
2324 		.policy = nl802154_policy,
2325 		.flags = GENL_ADMIN_PERM,
2326 		.internal_flags = NL802154_FLAG_NEED_NETDEV |
2327 				  NL802154_FLAG_NEED_RTNL,
2328 	},
2329 	{
2330 		.cmd = NL802154_CMD_GET_SEC_KEY,
2331 		/* TODO .doit by matching key id? */
2332 		.dumpit = nl802154_dump_llsec_key,
2333 		.policy = nl802154_policy,
2334 		.flags = GENL_ADMIN_PERM,
2335 		.internal_flags = NL802154_FLAG_NEED_NETDEV |
2336 				  NL802154_FLAG_NEED_RTNL,
2337 	},
2338 	{
2339 		.cmd = NL802154_CMD_NEW_SEC_KEY,
2340 		.doit = nl802154_add_llsec_key,
2341 		.policy = nl802154_policy,
2342 		.flags = GENL_ADMIN_PERM,
2343 		.internal_flags = NL802154_FLAG_NEED_NETDEV |
2344 				  NL802154_FLAG_NEED_RTNL,
2345 	},
2346 	{
2347 		.cmd = NL802154_CMD_DEL_SEC_KEY,
2348 		.doit = nl802154_del_llsec_key,
2349 		.policy = nl802154_policy,
2350 		.flags = GENL_ADMIN_PERM,
2351 		.internal_flags = NL802154_FLAG_NEED_NETDEV |
2352 				  NL802154_FLAG_NEED_RTNL,
2353 	},
2354 	/* TODO unique identifier must short+pan OR extended_addr */
2355 	{
2356 		.cmd = NL802154_CMD_GET_SEC_DEV,
2357 		/* TODO .doit by matching extended_addr? */
2358 		.dumpit = nl802154_dump_llsec_dev,
2359 		.policy = nl802154_policy,
2360 		.flags = GENL_ADMIN_PERM,
2361 		.internal_flags = NL802154_FLAG_NEED_NETDEV |
2362 				  NL802154_FLAG_NEED_RTNL,
2363 	},
2364 	{
2365 		.cmd = NL802154_CMD_NEW_SEC_DEV,
2366 		.doit = nl802154_add_llsec_dev,
2367 		.policy = nl802154_policy,
2368 		.flags = GENL_ADMIN_PERM,
2369 		.internal_flags = NL802154_FLAG_NEED_NETDEV |
2370 				  NL802154_FLAG_NEED_RTNL,
2371 	},
2372 	{
2373 		.cmd = NL802154_CMD_DEL_SEC_DEV,
2374 		.doit = nl802154_del_llsec_dev,
2375 		.policy = nl802154_policy,
2376 		.flags = GENL_ADMIN_PERM,
2377 		.internal_flags = NL802154_FLAG_NEED_NETDEV |
2378 				  NL802154_FLAG_NEED_RTNL,
2379 	},
2380 	/* TODO remove complete devkey, put it as nested? */
2381 	{
2382 		.cmd = NL802154_CMD_GET_SEC_DEVKEY,
2383 		/* TODO doit by matching ??? */
2384 		.dumpit = nl802154_dump_llsec_devkey,
2385 		.policy = nl802154_policy,
2386 		.flags = GENL_ADMIN_PERM,
2387 		.internal_flags = NL802154_FLAG_NEED_NETDEV |
2388 				  NL802154_FLAG_NEED_RTNL,
2389 	},
2390 	{
2391 		.cmd = NL802154_CMD_NEW_SEC_DEVKEY,
2392 		.doit = nl802154_add_llsec_devkey,
2393 		.policy = nl802154_policy,
2394 		.flags = GENL_ADMIN_PERM,
2395 		.internal_flags = NL802154_FLAG_NEED_NETDEV |
2396 				  NL802154_FLAG_NEED_RTNL,
2397 	},
2398 	{
2399 		.cmd = NL802154_CMD_DEL_SEC_DEVKEY,
2400 		.doit = nl802154_del_llsec_devkey,
2401 		.policy = nl802154_policy,
2402 		.flags = GENL_ADMIN_PERM,
2403 		.internal_flags = NL802154_FLAG_NEED_NETDEV |
2404 				  NL802154_FLAG_NEED_RTNL,
2405 	},
2406 	{
2407 		.cmd = NL802154_CMD_GET_SEC_LEVEL,
2408 		/* TODO .doit by matching frame_type? */
2409 		.dumpit = nl802154_dump_llsec_seclevel,
2410 		.policy = nl802154_policy,
2411 		.flags = GENL_ADMIN_PERM,
2412 		.internal_flags = NL802154_FLAG_NEED_NETDEV |
2413 				  NL802154_FLAG_NEED_RTNL,
2414 	},
2415 	{
2416 		.cmd = NL802154_CMD_NEW_SEC_LEVEL,
2417 		.doit = nl802154_add_llsec_seclevel,
2418 		.policy = nl802154_policy,
2419 		.flags = GENL_ADMIN_PERM,
2420 		.internal_flags = NL802154_FLAG_NEED_NETDEV |
2421 				  NL802154_FLAG_NEED_RTNL,
2422 	},
2423 	{
2424 		.cmd = NL802154_CMD_DEL_SEC_LEVEL,
2425 		/* TODO match frame_type only? */
2426 		.doit = nl802154_del_llsec_seclevel,
2427 		.policy = nl802154_policy,
2428 		.flags = GENL_ADMIN_PERM,
2429 		.internal_flags = NL802154_FLAG_NEED_NETDEV |
2430 				  NL802154_FLAG_NEED_RTNL,
2431 	},
2432 #endif /* CONFIG_IEEE802154_NL802154_EXPERIMENTAL */
2433 };
2434 
2435 /* initialisation/exit functions */
2436 int nl802154_init(void)
2437 {
2438 	return genl_register_family_with_ops_groups(&nl802154_fam, nl802154_ops,
2439 						    nl802154_mcgrps);
2440 }
2441 
2442 void nl802154_exit(void)
2443 {
2444 	genl_unregister_family(&nl802154_fam);
2445 }
2446