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