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