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