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