1 // SPDX-License-Identifier: GPL-2.0-only
5 * Alexander Aring <aar@pengutronix.de>
7 * Based on: net/wireless/nl80211.c
10 #include <linux/rtnetlink.h>
12 #include <net/cfg802154.h>
13 #include <net/genetlink.h>
14 #include <net/mac802154.h>
15 #include <net/netlink.h>
16 #include <net/nl802154.h>
23 /* the netlink family */
24 static struct genl_family nl802154_fam
;
26 /* multicast groups */
27 enum nl802154_multicast_groups
{
28 NL802154_MCGRP_CONFIG
,
32 static const struct genl_multicast_group nl802154_mcgrps
[] = {
33 [NL802154_MCGRP_CONFIG
] = { .name
= "config", },
34 [NL802154_MCGRP_SCAN
] = { .name
= "scan", },
37 /* returns ERR_PTR values */
38 static struct wpan_dev
*
39 __cfg802154_wpan_dev_from_attrs(struct net
*netns
, struct nlattr
**attrs
)
41 struct cfg802154_registered_device
*rdev
;
42 struct wpan_dev
*result
= NULL
;
43 bool have_ifidx
= attrs
[NL802154_ATTR_IFINDEX
];
44 bool have_wpan_dev_id
= attrs
[NL802154_ATTR_WPAN_DEV
];
46 int wpan_phy_idx
= -1;
51 if (!have_ifidx
&& !have_wpan_dev_id
)
52 return ERR_PTR(-EINVAL
);
55 ifidx
= nla_get_u32(attrs
[NL802154_ATTR_IFINDEX
]);
56 if (have_wpan_dev_id
) {
57 wpan_dev_id
= nla_get_u64(attrs
[NL802154_ATTR_WPAN_DEV
]);
58 wpan_phy_idx
= wpan_dev_id
>> 32;
61 list_for_each_entry(rdev
, &cfg802154_rdev_list
, list
) {
62 struct wpan_dev
*wpan_dev
;
64 if (wpan_phy_net(&rdev
->wpan_phy
) != netns
)
67 if (have_wpan_dev_id
&& rdev
->wpan_phy_idx
!= wpan_phy_idx
)
70 list_for_each_entry(wpan_dev
, &rdev
->wpan_dev_list
, list
) {
71 if (have_ifidx
&& wpan_dev
->netdev
&&
72 wpan_dev
->netdev
->ifindex
== ifidx
) {
76 if (have_wpan_dev_id
&&
77 wpan_dev
->identifier
== (u32
)wpan_dev_id
) {
90 return ERR_PTR(-ENODEV
);
93 static struct cfg802154_registered_device
*
94 __cfg802154_rdev_from_attrs(struct net
*netns
, struct nlattr
**attrs
)
96 struct cfg802154_registered_device
*rdev
= NULL
, *tmp
;
97 struct net_device
*netdev
;
101 if (!attrs
[NL802154_ATTR_WPAN_PHY
] &&
102 !attrs
[NL802154_ATTR_IFINDEX
] &&
103 !attrs
[NL802154_ATTR_WPAN_DEV
])
104 return ERR_PTR(-EINVAL
);
106 if (attrs
[NL802154_ATTR_WPAN_PHY
])
107 rdev
= cfg802154_rdev_by_wpan_phy_idx(
108 nla_get_u32(attrs
[NL802154_ATTR_WPAN_PHY
]));
110 if (attrs
[NL802154_ATTR_WPAN_DEV
]) {
111 u64 wpan_dev_id
= nla_get_u64(attrs
[NL802154_ATTR_WPAN_DEV
]);
112 struct wpan_dev
*wpan_dev
;
115 tmp
= cfg802154_rdev_by_wpan_phy_idx(wpan_dev_id
>> 32);
117 /* make sure wpan_dev exists */
118 list_for_each_entry(wpan_dev
, &tmp
->wpan_dev_list
, list
) {
119 if (wpan_dev
->identifier
!= (u32
)wpan_dev_id
)
128 if (rdev
&& tmp
!= rdev
)
129 return ERR_PTR(-EINVAL
);
134 if (attrs
[NL802154_ATTR_IFINDEX
]) {
135 int ifindex
= nla_get_u32(attrs
[NL802154_ATTR_IFINDEX
]);
137 netdev
= __dev_get_by_index(netns
, ifindex
);
139 if (netdev
->ieee802154_ptr
)
140 tmp
= wpan_phy_to_rdev(
141 netdev
->ieee802154_ptr
->wpan_phy
);
145 /* not wireless device -- return error */
147 return ERR_PTR(-EINVAL
);
149 /* mismatch -- return error */
150 if (rdev
&& tmp
!= rdev
)
151 return ERR_PTR(-EINVAL
);
158 return ERR_PTR(-ENODEV
);
160 if (netns
!= wpan_phy_net(&rdev
->wpan_phy
))
161 return ERR_PTR(-ENODEV
);
166 /* This function returns a pointer to the driver
167 * that the genl_info item that is passed refers to.
169 * The result of this can be a PTR_ERR and hence must
170 * be checked with IS_ERR() for errors.
172 static struct cfg802154_registered_device
*
173 cfg802154_get_dev_from_info(struct net
*netns
, struct genl_info
*info
)
175 return __cfg802154_rdev_from_attrs(netns
, info
->attrs
);
178 /* policy for the attributes */
179 static const struct nla_policy nl802154_policy
[NL802154_ATTR_MAX
+1] = {
180 [NL802154_ATTR_WPAN_PHY
] = { .type
= NLA_U32
},
181 [NL802154_ATTR_WPAN_PHY_NAME
] = { .type
= NLA_NUL_STRING
,
184 [NL802154_ATTR_IFINDEX
] = { .type
= NLA_U32
},
185 [NL802154_ATTR_IFTYPE
] = { .type
= NLA_U32
},
186 [NL802154_ATTR_IFNAME
] = { .type
= NLA_NUL_STRING
, .len
= IFNAMSIZ
-1 },
188 [NL802154_ATTR_WPAN_DEV
] = { .type
= NLA_U64
},
190 [NL802154_ATTR_PAGE
] = NLA_POLICY_MAX(NLA_U8
, IEEE802154_MAX_PAGE
),
191 [NL802154_ATTR_CHANNEL
] = NLA_POLICY_MAX(NLA_U8
, IEEE802154_MAX_CHANNEL
),
193 [NL802154_ATTR_TX_POWER
] = { .type
= NLA_S32
, },
195 [NL802154_ATTR_CCA_MODE
] = { .type
= NLA_U32
, },
196 [NL802154_ATTR_CCA_OPT
] = { .type
= NLA_U32
, },
197 [NL802154_ATTR_CCA_ED_LEVEL
] = { .type
= NLA_S32
, },
199 [NL802154_ATTR_SUPPORTED_CHANNEL
] = { .type
= NLA_U32
, },
201 [NL802154_ATTR_PAN_ID
] = { .type
= NLA_U16
, },
202 [NL802154_ATTR_EXTENDED_ADDR
] = { .type
= NLA_U64
},
203 [NL802154_ATTR_SHORT_ADDR
] = { .type
= NLA_U16
, },
205 [NL802154_ATTR_MIN_BE
] = { .type
= NLA_U8
, },
206 [NL802154_ATTR_MAX_BE
] = { .type
= NLA_U8
, },
207 [NL802154_ATTR_MAX_CSMA_BACKOFFS
] = { .type
= NLA_U8
, },
209 [NL802154_ATTR_MAX_FRAME_RETRIES
] = { .type
= NLA_S8
, },
211 [NL802154_ATTR_LBT_MODE
] = { .type
= NLA_U8
, },
213 [NL802154_ATTR_WPAN_PHY_CAPS
] = { .type
= NLA_NESTED
},
215 [NL802154_ATTR_SUPPORTED_COMMANDS
] = { .type
= NLA_NESTED
},
217 [NL802154_ATTR_ACKREQ_DEFAULT
] = { .type
= NLA_U8
},
219 [NL802154_ATTR_PID
] = { .type
= NLA_U32
},
220 [NL802154_ATTR_NETNS_FD
] = { .type
= NLA_U32
},
222 [NL802154_ATTR_COORDINATOR
] = { .type
= NLA_NESTED
},
224 [NL802154_ATTR_SCAN_TYPE
] =
225 NLA_POLICY_RANGE(NLA_U8
, NL802154_SCAN_ED
, NL802154_SCAN_RIT_PASSIVE
),
226 [NL802154_ATTR_SCAN_CHANNELS
] =
227 NLA_POLICY_MASK(NLA_U32
, GENMASK(IEEE802154_MAX_CHANNEL
, 0)),
228 [NL802154_ATTR_SCAN_PREAMBLE_CODES
] = { .type
= NLA_REJECT
},
229 [NL802154_ATTR_SCAN_MEAN_PRF
] = { .type
= NLA_REJECT
},
230 [NL802154_ATTR_SCAN_DURATION
] =
231 NLA_POLICY_MAX(NLA_U8
, IEEE802154_MAX_SCAN_DURATION
),
232 [NL802154_ATTR_SCAN_DONE_REASON
] =
233 NLA_POLICY_RANGE(NLA_U8
, NL802154_SCAN_DONE_REASON_FINISHED
,
234 NL802154_SCAN_DONE_REASON_ABORTED
),
235 [NL802154_ATTR_BEACON_INTERVAL
] =
236 NLA_POLICY_MAX(NLA_U8
, IEEE802154_ACTIVE_SCAN_DURATION
),
237 [NL802154_ATTR_MAX_ASSOCIATIONS
] = { .type
= NLA_U32
},
238 [NL802154_ATTR_PEER
] = { .type
= NLA_NESTED
},
240 #ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL
241 [NL802154_ATTR_SEC_ENABLED
] = { .type
= NLA_U8
, },
242 [NL802154_ATTR_SEC_OUT_LEVEL
] = { .type
= NLA_U32
, },
243 [NL802154_ATTR_SEC_OUT_KEY_ID
] = { .type
= NLA_NESTED
, },
244 [NL802154_ATTR_SEC_FRAME_COUNTER
] = { .type
= NLA_U32
},
246 [NL802154_ATTR_SEC_LEVEL
] = { .type
= NLA_NESTED
},
247 [NL802154_ATTR_SEC_DEVICE
] = { .type
= NLA_NESTED
},
248 [NL802154_ATTR_SEC_DEVKEY
] = { .type
= NLA_NESTED
},
249 [NL802154_ATTR_SEC_KEY
] = { .type
= NLA_NESTED
},
250 #endif /* CONFIG_IEEE802154_NL802154_EXPERIMENTAL */
254 nl802154_prepare_wpan_dev_dump(struct sk_buff
*skb
,
255 struct netlink_callback
*cb
,
256 struct cfg802154_registered_device
**rdev
,
257 struct wpan_dev
**wpan_dev
)
259 const struct genl_dumpit_info
*info
= genl_dumpit_info(cb
);
265 *wpan_dev
= __cfg802154_wpan_dev_from_attrs(sock_net(skb
->sk
),
267 if (IS_ERR(*wpan_dev
)) {
268 err
= PTR_ERR(*wpan_dev
);
271 *rdev
= wpan_phy_to_rdev((*wpan_dev
)->wpan_phy
);
272 /* 0 is the first index - add 1 to parse only once */
273 cb
->args
[0] = (*rdev
)->wpan_phy_idx
+ 1;
274 cb
->args
[1] = (*wpan_dev
)->identifier
;
276 /* subtract the 1 again here */
277 struct wpan_phy
*wpan_phy
= wpan_phy_idx_to_wpan_phy(cb
->args
[0] - 1);
278 struct wpan_dev
*tmp
;
284 *rdev
= wpan_phy_to_rdev(wpan_phy
);
287 list_for_each_entry(tmp
, &(*rdev
)->wpan_dev_list
, list
) {
288 if (tmp
->identifier
== cb
->args
[1]) {
307 nl802154_finish_wpan_dev_dump(struct cfg802154_registered_device
*rdev
)
312 /* message building helper */
313 static inline void *nl802154hdr_put(struct sk_buff
*skb
, u32 portid
, u32 seq
,
316 /* since there is no private header just add the generic one */
317 return genlmsg_put(skb
, portid
, seq
, &nl802154_fam
, flags
, cmd
);
321 nl802154_put_flags(struct sk_buff
*msg
, int attr
, u32 mask
)
323 struct nlattr
*nl_flags
= nla_nest_start_noflag(msg
, attr
);
331 if ((mask
& 1) && nla_put_flag(msg
, i
))
338 nla_nest_end(msg
, nl_flags
);
343 nl802154_send_wpan_phy_channels(struct cfg802154_registered_device
*rdev
,
346 struct nlattr
*nl_page
;
349 nl_page
= nla_nest_start_noflag(msg
, NL802154_ATTR_CHANNELS_SUPPORTED
);
353 for (page
= 0; page
<= IEEE802154_MAX_PAGE
; page
++) {
354 if (nla_put_u32(msg
, NL802154_ATTR_SUPPORTED_CHANNEL
,
355 rdev
->wpan_phy
.supported
.channels
[page
]))
358 nla_nest_end(msg
, nl_page
);
364 nl802154_put_capabilities(struct sk_buff
*msg
,
365 struct cfg802154_registered_device
*rdev
)
367 const struct wpan_phy_supported
*caps
= &rdev
->wpan_phy
.supported
;
368 struct nlattr
*nl_caps
, *nl_channels
;
371 nl_caps
= nla_nest_start_noflag(msg
, NL802154_ATTR_WPAN_PHY_CAPS
);
375 nl_channels
= nla_nest_start_noflag(msg
, NL802154_CAP_ATTR_CHANNELS
);
379 for (i
= 0; i
<= IEEE802154_MAX_PAGE
; i
++) {
380 if (caps
->channels
[i
]) {
381 if (nl802154_put_flags(msg
, i
, caps
->channels
[i
]))
386 nla_nest_end(msg
, nl_channels
);
388 if (rdev
->wpan_phy
.flags
& WPAN_PHY_FLAG_CCA_ED_LEVEL
) {
389 struct nlattr
*nl_ed_lvls
;
391 nl_ed_lvls
= nla_nest_start_noflag(msg
,
392 NL802154_CAP_ATTR_CCA_ED_LEVELS
);
396 for (i
= 0; i
< caps
->cca_ed_levels_size
; i
++) {
397 if (nla_put_s32(msg
, i
, caps
->cca_ed_levels
[i
]))
401 nla_nest_end(msg
, nl_ed_lvls
);
404 if (rdev
->wpan_phy
.flags
& WPAN_PHY_FLAG_TXPOWER
) {
405 struct nlattr
*nl_tx_pwrs
;
407 nl_tx_pwrs
= nla_nest_start_noflag(msg
,
408 NL802154_CAP_ATTR_TX_POWERS
);
412 for (i
= 0; i
< caps
->tx_powers_size
; i
++) {
413 if (nla_put_s32(msg
, i
, caps
->tx_powers
[i
]))
417 nla_nest_end(msg
, nl_tx_pwrs
);
420 if (rdev
->wpan_phy
.flags
& WPAN_PHY_FLAG_CCA_MODE
) {
421 if (nl802154_put_flags(msg
, NL802154_CAP_ATTR_CCA_MODES
,
423 nl802154_put_flags(msg
, NL802154_CAP_ATTR_CCA_OPTS
,
428 if (nla_put_u8(msg
, NL802154_CAP_ATTR_MIN_MINBE
, caps
->min_minbe
) ||
429 nla_put_u8(msg
, NL802154_CAP_ATTR_MAX_MINBE
, caps
->max_minbe
) ||
430 nla_put_u8(msg
, NL802154_CAP_ATTR_MIN_MAXBE
, caps
->min_maxbe
) ||
431 nla_put_u8(msg
, NL802154_CAP_ATTR_MAX_MAXBE
, caps
->max_maxbe
) ||
432 nla_put_u8(msg
, NL802154_CAP_ATTR_MIN_CSMA_BACKOFFS
,
433 caps
->min_csma_backoffs
) ||
434 nla_put_u8(msg
, NL802154_CAP_ATTR_MAX_CSMA_BACKOFFS
,
435 caps
->max_csma_backoffs
) ||
436 nla_put_s8(msg
, NL802154_CAP_ATTR_MIN_FRAME_RETRIES
,
437 caps
->min_frame_retries
) ||
438 nla_put_s8(msg
, NL802154_CAP_ATTR_MAX_FRAME_RETRIES
,
439 caps
->max_frame_retries
) ||
440 nl802154_put_flags(msg
, NL802154_CAP_ATTR_IFTYPES
,
442 nla_put_u32(msg
, NL802154_CAP_ATTR_LBT
, caps
->lbt
))
445 nla_nest_end(msg
, nl_caps
);
450 static int nl802154_send_wpan_phy(struct cfg802154_registered_device
*rdev
,
451 enum nl802154_commands cmd
,
452 struct sk_buff
*msg
, u32 portid
, u32 seq
,
455 struct nlattr
*nl_cmds
;
459 hdr
= nl802154hdr_put(msg
, portid
, seq
, flags
, cmd
);
463 if (nla_put_u32(msg
, NL802154_ATTR_WPAN_PHY
, rdev
->wpan_phy_idx
) ||
464 nla_put_string(msg
, NL802154_ATTR_WPAN_PHY_NAME
,
465 wpan_phy_name(&rdev
->wpan_phy
)) ||
466 nla_put_u32(msg
, NL802154_ATTR_GENERATION
,
467 cfg802154_rdev_list_generation
))
468 goto nla_put_failure
;
470 if (cmd
!= NL802154_CMD_NEW_WPAN_PHY
)
475 /* current channel settings */
476 if (nla_put_u8(msg
, NL802154_ATTR_PAGE
,
477 rdev
->wpan_phy
.current_page
) ||
478 nla_put_u8(msg
, NL802154_ATTR_CHANNEL
,
479 rdev
->wpan_phy
.current_channel
))
480 goto nla_put_failure
;
482 /* TODO remove this behaviour, we still keep support it for a while
483 * so users can change the behaviour to the new one.
485 if (nl802154_send_wpan_phy_channels(rdev
, msg
))
486 goto nla_put_failure
;
489 if (rdev
->wpan_phy
.flags
& WPAN_PHY_FLAG_CCA_MODE
) {
490 if (nla_put_u32(msg
, NL802154_ATTR_CCA_MODE
,
491 rdev
->wpan_phy
.cca
.mode
))
492 goto nla_put_failure
;
494 if (rdev
->wpan_phy
.cca
.mode
== NL802154_CCA_ENERGY_CARRIER
) {
495 if (nla_put_u32(msg
, NL802154_ATTR_CCA_OPT
,
496 rdev
->wpan_phy
.cca
.opt
))
497 goto nla_put_failure
;
501 if (rdev
->wpan_phy
.flags
& WPAN_PHY_FLAG_TXPOWER
) {
502 if (nla_put_s32(msg
, NL802154_ATTR_TX_POWER
,
503 rdev
->wpan_phy
.transmit_power
))
504 goto nla_put_failure
;
507 if (rdev
->wpan_phy
.flags
& WPAN_PHY_FLAG_CCA_ED_LEVEL
) {
508 if (nla_put_s32(msg
, NL802154_ATTR_CCA_ED_LEVEL
,
509 rdev
->wpan_phy
.cca_ed_level
))
510 goto nla_put_failure
;
513 if (nl802154_put_capabilities(msg
, rdev
))
514 goto nla_put_failure
;
516 nl_cmds
= nla_nest_start_noflag(msg
, NL802154_ATTR_SUPPORTED_COMMANDS
);
518 goto nla_put_failure
;
523 if (rdev->ops->op) { \
525 if (nla_put_u32(msg, i, NL802154_CMD_ ## n)) \
526 goto nla_put_failure; \
530 CMD(add_virtual_intf
, NEW_INTERFACE
);
531 CMD(del_virtual_intf
, DEL_INTERFACE
);
532 CMD(set_channel
, SET_CHANNEL
);
533 CMD(set_pan_id
, SET_PAN_ID
);
534 CMD(set_short_addr
, SET_SHORT_ADDR
);
535 CMD(set_backoff_exponent
, SET_BACKOFF_EXPONENT
);
536 CMD(set_max_csma_backoffs
, SET_MAX_CSMA_BACKOFFS
);
537 CMD(set_max_frame_retries
, SET_MAX_FRAME_RETRIES
);
538 CMD(set_lbt_mode
, SET_LBT_MODE
);
539 CMD(set_ackreq_default
, SET_ACKREQ_DEFAULT
);
541 if (rdev
->wpan_phy
.flags
& WPAN_PHY_FLAG_TXPOWER
)
542 CMD(set_tx_power
, SET_TX_POWER
);
544 if (rdev
->wpan_phy
.flags
& WPAN_PHY_FLAG_CCA_ED_LEVEL
)
545 CMD(set_cca_ed_level
, SET_CCA_ED_LEVEL
);
547 if (rdev
->wpan_phy
.flags
& WPAN_PHY_FLAG_CCA_MODE
)
548 CMD(set_cca_mode
, SET_CCA_MODE
);
551 nla_nest_end(msg
, nl_cmds
);
554 genlmsg_end(msg
, hdr
);
558 genlmsg_cancel(msg
, hdr
);
562 struct nl802154_dump_wpan_phy_state
{
568 static int nl802154_dump_wpan_phy_parse(struct sk_buff
*skb
,
569 struct netlink_callback
*cb
,
570 struct nl802154_dump_wpan_phy_state
*state
)
572 const struct genl_dumpit_info
*info
= genl_dumpit_info(cb
);
573 struct nlattr
**tb
= info
->info
.attrs
;
575 if (tb
[NL802154_ATTR_WPAN_PHY
])
576 state
->filter_wpan_phy
= nla_get_u32(tb
[NL802154_ATTR_WPAN_PHY
]);
577 if (tb
[NL802154_ATTR_WPAN_DEV
])
578 state
->filter_wpan_phy
= nla_get_u64(tb
[NL802154_ATTR_WPAN_DEV
]) >> 32;
579 if (tb
[NL802154_ATTR_IFINDEX
]) {
580 struct net_device
*netdev
;
581 struct cfg802154_registered_device
*rdev
;
582 int ifidx
= nla_get_u32(tb
[NL802154_ATTR_IFINDEX
]);
584 netdev
= __dev_get_by_index(&init_net
, ifidx
);
587 if (netdev
->ieee802154_ptr
) {
588 rdev
= wpan_phy_to_rdev(
589 netdev
->ieee802154_ptr
->wpan_phy
);
590 state
->filter_wpan_phy
= rdev
->wpan_phy_idx
;
598 nl802154_dump_wpan_phy(struct sk_buff
*skb
, struct netlink_callback
*cb
)
601 struct nl802154_dump_wpan_phy_state
*state
= (void *)cb
->args
[0];
602 struct cfg802154_registered_device
*rdev
;
606 state
= kzalloc(sizeof(*state
), GFP_KERNEL
);
611 state
->filter_wpan_phy
= -1;
612 ret
= nl802154_dump_wpan_phy_parse(skb
, cb
, state
);
618 cb
->args
[0] = (long)state
;
621 list_for_each_entry(rdev
, &cfg802154_rdev_list
, list
) {
622 if (!net_eq(wpan_phy_net(&rdev
->wpan_phy
), sock_net(skb
->sk
)))
624 if (++idx
<= state
->start
)
626 if (state
->filter_wpan_phy
!= -1 &&
627 state
->filter_wpan_phy
!= rdev
->wpan_phy_idx
)
629 /* attempt to fit multiple wpan_phy data chunks into the skb */
630 ret
= nl802154_send_wpan_phy(rdev
,
631 NL802154_CMD_NEW_WPAN_PHY
,
633 NETLINK_CB(cb
->skb
).portid
,
634 cb
->nlh
->nlmsg_seq
, NLM_F_MULTI
);
636 if ((ret
== -ENOBUFS
|| ret
== -EMSGSIZE
) &&
637 !skb
->len
&& cb
->min_dump_alloc
< 4096) {
638 cb
->min_dump_alloc
= 4096;
654 static int nl802154_dump_wpan_phy_done(struct netlink_callback
*cb
)
656 kfree((void *)cb
->args
[0]);
660 static int nl802154_get_wpan_phy(struct sk_buff
*skb
, struct genl_info
*info
)
663 struct cfg802154_registered_device
*rdev
= info
->user_ptr
[0];
665 msg
= nlmsg_new(NLMSG_DEFAULT_SIZE
, GFP_KERNEL
);
669 if (nl802154_send_wpan_phy(rdev
, NL802154_CMD_NEW_WPAN_PHY
, msg
,
670 info
->snd_portid
, info
->snd_seq
, 0) < 0) {
675 return genlmsg_reply(msg
, info
);
678 static inline u64
wpan_dev_id(struct wpan_dev
*wpan_dev
)
680 return (u64
)wpan_dev
->identifier
|
681 ((u64
)wpan_phy_to_rdev(wpan_dev
->wpan_phy
)->wpan_phy_idx
<< 32);
684 #ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL
685 #include <net/ieee802154_netdev.h>
688 ieee802154_llsec_send_key_id(struct sk_buff
*msg
,
689 const struct ieee802154_llsec_key_id
*desc
)
691 struct nlattr
*nl_dev_addr
;
693 if (nla_put_u32(msg
, NL802154_KEY_ID_ATTR_MODE
, desc
->mode
))
696 switch (desc
->mode
) {
697 case NL802154_KEY_ID_MODE_IMPLICIT
:
698 nl_dev_addr
= nla_nest_start_noflag(msg
,
699 NL802154_KEY_ID_ATTR_IMPLICIT
);
703 if (nla_put_le16(msg
, NL802154_DEV_ADDR_ATTR_PAN_ID
,
704 desc
->device_addr
.pan_id
) ||
705 nla_put_u32(msg
, NL802154_DEV_ADDR_ATTR_MODE
,
706 desc
->device_addr
.mode
))
709 switch (desc
->device_addr
.mode
) {
710 case NL802154_DEV_ADDR_SHORT
:
711 if (nla_put_le16(msg
, NL802154_DEV_ADDR_ATTR_SHORT
,
712 desc
->device_addr
.short_addr
))
715 case NL802154_DEV_ADDR_EXTENDED
:
716 if (nla_put_le64(msg
, NL802154_DEV_ADDR_ATTR_EXTENDED
,
717 desc
->device_addr
.extended_addr
,
718 NL802154_DEV_ADDR_ATTR_PAD
))
722 /* userspace should handle unknown */
726 nla_nest_end(msg
, nl_dev_addr
);
728 case NL802154_KEY_ID_MODE_INDEX
:
730 case NL802154_KEY_ID_MODE_INDEX_SHORT
:
731 /* TODO renmae short_source? */
732 if (nla_put_le32(msg
, NL802154_KEY_ID_ATTR_SOURCE_SHORT
,
736 case NL802154_KEY_ID_MODE_INDEX_EXTENDED
:
737 if (nla_put_le64(msg
, NL802154_KEY_ID_ATTR_SOURCE_EXTENDED
,
738 desc
->extended_source
,
739 NL802154_KEY_ID_ATTR_PAD
))
743 /* userspace should handle unknown */
747 /* TODO key_id to key_idx ? Check naming */
748 if (desc
->mode
!= NL802154_KEY_ID_MODE_IMPLICIT
) {
749 if (nla_put_u8(msg
, NL802154_KEY_ID_ATTR_INDEX
, desc
->id
))
756 static int nl802154_get_llsec_params(struct sk_buff
*msg
,
757 struct cfg802154_registered_device
*rdev
,
758 struct wpan_dev
*wpan_dev
)
760 struct nlattr
*nl_key_id
;
761 struct ieee802154_llsec_params params
;
764 ret
= rdev_get_llsec_params(rdev
, wpan_dev
, ¶ms
);
768 if (nla_put_u8(msg
, NL802154_ATTR_SEC_ENABLED
, params
.enabled
) ||
769 nla_put_u32(msg
, NL802154_ATTR_SEC_OUT_LEVEL
, params
.out_level
) ||
770 nla_put_be32(msg
, NL802154_ATTR_SEC_FRAME_COUNTER
,
771 params
.frame_counter
))
774 nl_key_id
= nla_nest_start_noflag(msg
, NL802154_ATTR_SEC_OUT_KEY_ID
);
778 ret
= ieee802154_llsec_send_key_id(msg
, ¶ms
.out_key
);
782 nla_nest_end(msg
, nl_key_id
);
786 #endif /* CONFIG_IEEE802154_NL802154_EXPERIMENTAL */
789 nl802154_send_iface(struct sk_buff
*msg
, u32 portid
, u32 seq
, int flags
,
790 struct cfg802154_registered_device
*rdev
,
791 struct wpan_dev
*wpan_dev
)
793 struct net_device
*dev
= wpan_dev
->netdev
;
796 hdr
= nl802154hdr_put(msg
, portid
, seq
, flags
,
797 NL802154_CMD_NEW_INTERFACE
);
802 (nla_put_u32(msg
, NL802154_ATTR_IFINDEX
, dev
->ifindex
) ||
803 nla_put_string(msg
, NL802154_ATTR_IFNAME
, dev
->name
)))
804 goto nla_put_failure
;
806 if (nla_put_u32(msg
, NL802154_ATTR_WPAN_PHY
, rdev
->wpan_phy_idx
) ||
807 nla_put_u32(msg
, NL802154_ATTR_IFTYPE
, wpan_dev
->iftype
) ||
808 nla_put_u64_64bit(msg
, NL802154_ATTR_WPAN_DEV
,
809 wpan_dev_id(wpan_dev
), NL802154_ATTR_PAD
) ||
810 nla_put_u32(msg
, NL802154_ATTR_GENERATION
,
811 rdev
->devlist_generation
^
812 (cfg802154_rdev_list_generation
<< 2)))
813 goto nla_put_failure
;
815 /* address settings */
816 if (nla_put_le64(msg
, NL802154_ATTR_EXTENDED_ADDR
,
817 wpan_dev
->extended_addr
,
818 NL802154_ATTR_PAD
) ||
819 nla_put_le16(msg
, NL802154_ATTR_SHORT_ADDR
,
820 wpan_dev
->short_addr
) ||
821 nla_put_le16(msg
, NL802154_ATTR_PAN_ID
, wpan_dev
->pan_id
))
822 goto nla_put_failure
;
825 if (nla_put_s8(msg
, NL802154_ATTR_MAX_FRAME_RETRIES
,
826 wpan_dev
->frame_retries
) ||
827 nla_put_u8(msg
, NL802154_ATTR_MAX_BE
, wpan_dev
->max_be
) ||
828 nla_put_u8(msg
, NL802154_ATTR_MAX_CSMA_BACKOFFS
,
829 wpan_dev
->csma_retries
) ||
830 nla_put_u8(msg
, NL802154_ATTR_MIN_BE
, wpan_dev
->min_be
))
831 goto nla_put_failure
;
833 /* listen before transmit */
834 if (nla_put_u8(msg
, NL802154_ATTR_LBT_MODE
, wpan_dev
->lbt
))
835 goto nla_put_failure
;
837 /* ackreq default behaviour */
838 if (nla_put_u8(msg
, NL802154_ATTR_ACKREQ_DEFAULT
, wpan_dev
->ackreq
))
839 goto nla_put_failure
;
841 #ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL
842 if (wpan_dev
->iftype
== NL802154_IFTYPE_MONITOR
)
845 if (nl802154_get_llsec_params(msg
, rdev
, wpan_dev
) < 0)
846 goto nla_put_failure
;
849 #endif /* CONFIG_IEEE802154_NL802154_EXPERIMENTAL */
851 genlmsg_end(msg
, hdr
);
855 genlmsg_cancel(msg
, hdr
);
860 nl802154_dump_interface(struct sk_buff
*skb
, struct netlink_callback
*cb
)
864 int wp_start
= cb
->args
[0];
865 int if_start
= cb
->args
[1];
866 struct cfg802154_registered_device
*rdev
;
867 struct wpan_dev
*wpan_dev
;
870 list_for_each_entry(rdev
, &cfg802154_rdev_list
, list
) {
871 if (!net_eq(wpan_phy_net(&rdev
->wpan_phy
), sock_net(skb
->sk
)))
873 if (wp_idx
< wp_start
) {
879 list_for_each_entry(wpan_dev
, &rdev
->wpan_dev_list
, list
) {
880 if (if_idx
< if_start
) {
884 if (nl802154_send_iface(skb
, NETLINK_CB(cb
->skb
).portid
,
885 cb
->nlh
->nlmsg_seq
, NLM_F_MULTI
,
886 rdev
, wpan_dev
) < 0) {
897 cb
->args
[0] = wp_idx
;
898 cb
->args
[1] = if_idx
;
903 static int nl802154_get_interface(struct sk_buff
*skb
, struct genl_info
*info
)
906 struct cfg802154_registered_device
*rdev
= info
->user_ptr
[0];
907 struct wpan_dev
*wdev
= info
->user_ptr
[1];
909 msg
= nlmsg_new(NLMSG_DEFAULT_SIZE
, GFP_KERNEL
);
913 if (nl802154_send_iface(msg
, info
->snd_portid
, info
->snd_seq
, 0,
919 return genlmsg_reply(msg
, info
);
922 static int nl802154_new_interface(struct sk_buff
*skb
, struct genl_info
*info
)
924 struct cfg802154_registered_device
*rdev
= info
->user_ptr
[0];
925 enum nl802154_iftype type
= NL802154_IFTYPE_UNSPEC
;
926 __le64 extended_addr
= cpu_to_le64(0x0000000000000000ULL
);
928 /* TODO avoid failing a new interface
929 * creation due to pending removal?
932 if (!info
->attrs
[NL802154_ATTR_IFNAME
])
935 if (info
->attrs
[NL802154_ATTR_IFTYPE
]) {
936 type
= nla_get_u32(info
->attrs
[NL802154_ATTR_IFTYPE
]);
937 if (type
> NL802154_IFTYPE_MAX
||
938 !(rdev
->wpan_phy
.supported
.iftypes
& BIT(type
)))
942 if (info
->attrs
[NL802154_ATTR_EXTENDED_ADDR
])
943 extended_addr
= nla_get_le64(info
->attrs
[NL802154_ATTR_EXTENDED_ADDR
]);
945 if (!rdev
->ops
->add_virtual_intf
)
948 return rdev_add_virtual_intf(rdev
,
949 nla_data(info
->attrs
[NL802154_ATTR_IFNAME
]),
950 NET_NAME_USER
, type
, extended_addr
);
953 static int nl802154_del_interface(struct sk_buff
*skb
, struct genl_info
*info
)
955 struct cfg802154_registered_device
*rdev
= info
->user_ptr
[0];
956 struct wpan_dev
*wpan_dev
= info
->user_ptr
[1];
958 if (!rdev
->ops
->del_virtual_intf
)
961 /* If we remove a wpan device without a netdev then clear
962 * user_ptr[1] so that nl802154_post_doit won't dereference it
963 * to check if it needs to do dev_put(). Otherwise it crashes
964 * since the wpan_dev has been freed, unlike with a netdev where
965 * we need the dev_put() for the netdev to really be freed.
967 if (!wpan_dev
->netdev
)
968 info
->user_ptr
[1] = NULL
;
970 return rdev_del_virtual_intf(rdev
, wpan_dev
);
973 static int nl802154_set_channel(struct sk_buff
*skb
, struct genl_info
*info
)
975 struct cfg802154_registered_device
*rdev
= info
->user_ptr
[0];
978 if (!info
->attrs
[NL802154_ATTR_PAGE
] ||
979 !info
->attrs
[NL802154_ATTR_CHANNEL
])
982 page
= nla_get_u8(info
->attrs
[NL802154_ATTR_PAGE
]);
983 channel
= nla_get_u8(info
->attrs
[NL802154_ATTR_CHANNEL
]);
985 /* check 802.15.4 constraints */
986 if (!ieee802154_chan_is_valid(&rdev
->wpan_phy
, page
, channel
))
989 return rdev_set_channel(rdev
, page
, channel
);
992 static int nl802154_set_cca_mode(struct sk_buff
*skb
, struct genl_info
*info
)
994 struct cfg802154_registered_device
*rdev
= info
->user_ptr
[0];
995 struct wpan_phy_cca cca
;
997 if (!(rdev
->wpan_phy
.flags
& WPAN_PHY_FLAG_CCA_MODE
))
1000 if (!info
->attrs
[NL802154_ATTR_CCA_MODE
])
1003 cca
.mode
= nla_get_u32(info
->attrs
[NL802154_ATTR_CCA_MODE
]);
1004 /* checking 802.15.4 constraints */
1005 if (cca
.mode
< NL802154_CCA_ENERGY
||
1006 cca
.mode
> NL802154_CCA_ATTR_MAX
||
1007 !(rdev
->wpan_phy
.supported
.cca_modes
& BIT(cca
.mode
)))
1010 if (cca
.mode
== NL802154_CCA_ENERGY_CARRIER
) {
1011 if (!info
->attrs
[NL802154_ATTR_CCA_OPT
])
1014 cca
.opt
= nla_get_u32(info
->attrs
[NL802154_ATTR_CCA_OPT
]);
1015 if (cca
.opt
> NL802154_CCA_OPT_ATTR_MAX
||
1016 !(rdev
->wpan_phy
.supported
.cca_opts
& BIT(cca
.opt
)))
1020 return rdev_set_cca_mode(rdev
, &cca
);
1023 static int nl802154_set_cca_ed_level(struct sk_buff
*skb
, struct genl_info
*info
)
1025 struct cfg802154_registered_device
*rdev
= info
->user_ptr
[0];
1029 if (!(rdev
->wpan_phy
.flags
& WPAN_PHY_FLAG_CCA_ED_LEVEL
))
1032 if (!info
->attrs
[NL802154_ATTR_CCA_ED_LEVEL
])
1035 ed_level
= nla_get_s32(info
->attrs
[NL802154_ATTR_CCA_ED_LEVEL
]);
1037 for (i
= 0; i
< rdev
->wpan_phy
.supported
.cca_ed_levels_size
; i
++) {
1038 if (ed_level
== rdev
->wpan_phy
.supported
.cca_ed_levels
[i
])
1039 return rdev_set_cca_ed_level(rdev
, ed_level
);
1045 static int nl802154_set_tx_power(struct sk_buff
*skb
, struct genl_info
*info
)
1047 struct cfg802154_registered_device
*rdev
= info
->user_ptr
[0];
1051 if (!(rdev
->wpan_phy
.flags
& WPAN_PHY_FLAG_TXPOWER
))
1054 if (!info
->attrs
[NL802154_ATTR_TX_POWER
])
1057 power
= nla_get_s32(info
->attrs
[NL802154_ATTR_TX_POWER
]);
1059 for (i
= 0; i
< rdev
->wpan_phy
.supported
.tx_powers_size
; i
++) {
1060 if (power
== rdev
->wpan_phy
.supported
.tx_powers
[i
])
1061 return rdev_set_tx_power(rdev
, power
);
1067 static int nl802154_set_pan_id(struct sk_buff
*skb
, struct genl_info
*info
)
1069 struct cfg802154_registered_device
*rdev
= info
->user_ptr
[0];
1070 struct net_device
*dev
= info
->user_ptr
[1];
1071 struct wpan_dev
*wpan_dev
= dev
->ieee802154_ptr
;
1074 /* conflict here while tx/rx calls */
1075 if (netif_running(dev
))
1078 if (wpan_dev
->lowpan_dev
) {
1079 if (netif_running(wpan_dev
->lowpan_dev
))
1083 /* don't change address fields on monitor */
1084 if (wpan_dev
->iftype
== NL802154_IFTYPE_MONITOR
||
1085 !info
->attrs
[NL802154_ATTR_PAN_ID
])
1088 pan_id
= nla_get_le16(info
->attrs
[NL802154_ATTR_PAN_ID
]);
1090 /* Only allow changing the PAN ID when the device has no more
1091 * associations ongoing to avoid confusing peers.
1093 if (cfg802154_device_is_associated(wpan_dev
)) {
1094 NL_SET_ERR_MSG(info
->extack
,
1095 "Existing associations, changing PAN ID forbidden");
1099 return rdev_set_pan_id(rdev
, wpan_dev
, pan_id
);
1102 static int nl802154_set_short_addr(struct sk_buff
*skb
, struct genl_info
*info
)
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
;
1109 /* conflict here while tx/rx calls */
1110 if (netif_running(dev
))
1113 if (wpan_dev
->lowpan_dev
) {
1114 if (netif_running(wpan_dev
->lowpan_dev
))
1118 /* don't change address fields on monitor */
1119 if (wpan_dev
->iftype
== NL802154_IFTYPE_MONITOR
||
1120 !info
->attrs
[NL802154_ATTR_SHORT_ADDR
])
1123 short_addr
= nla_get_le16(info
->attrs
[NL802154_ATTR_SHORT_ADDR
]);
1125 /* The short address only has a meaning when part of a PAN, after a
1126 * proper association procedure. However, we want to still offer the
1127 * possibility to create static networks so changing the short address
1128 * is only allowed when not already associated to other devices with
1129 * the official handshake.
1131 if (cfg802154_device_is_associated(wpan_dev
)) {
1132 NL_SET_ERR_MSG(info
->extack
,
1133 "Existing associations, changing short address forbidden");
1137 return rdev_set_short_addr(rdev
, wpan_dev
, short_addr
);
1141 nl802154_set_backoff_exponent(struct sk_buff
*skb
, struct genl_info
*info
)
1143 struct cfg802154_registered_device
*rdev
= info
->user_ptr
[0];
1144 struct net_device
*dev
= info
->user_ptr
[1];
1145 struct wpan_dev
*wpan_dev
= dev
->ieee802154_ptr
;
1148 /* should be set on netif open inside phy settings */
1149 if (netif_running(dev
))
1152 if (!info
->attrs
[NL802154_ATTR_MIN_BE
] ||
1153 !info
->attrs
[NL802154_ATTR_MAX_BE
])
1156 min_be
= nla_get_u8(info
->attrs
[NL802154_ATTR_MIN_BE
]);
1157 max_be
= nla_get_u8(info
->attrs
[NL802154_ATTR_MAX_BE
]);
1159 /* check 802.15.4 constraints */
1160 if (min_be
< rdev
->wpan_phy
.supported
.min_minbe
||
1161 min_be
> rdev
->wpan_phy
.supported
.max_minbe
||
1162 max_be
< rdev
->wpan_phy
.supported
.min_maxbe
||
1163 max_be
> rdev
->wpan_phy
.supported
.max_maxbe
||
1167 return rdev_set_backoff_exponent(rdev
, wpan_dev
, min_be
, max_be
);
1171 nl802154_set_max_csma_backoffs(struct sk_buff
*skb
, struct genl_info
*info
)
1173 struct cfg802154_registered_device
*rdev
= info
->user_ptr
[0];
1174 struct net_device
*dev
= info
->user_ptr
[1];
1175 struct wpan_dev
*wpan_dev
= dev
->ieee802154_ptr
;
1176 u8 max_csma_backoffs
;
1178 /* conflict here while other running iface settings */
1179 if (netif_running(dev
))
1182 if (!info
->attrs
[NL802154_ATTR_MAX_CSMA_BACKOFFS
])
1185 max_csma_backoffs
= nla_get_u8(
1186 info
->attrs
[NL802154_ATTR_MAX_CSMA_BACKOFFS
]);
1188 /* check 802.15.4 constraints */
1189 if (max_csma_backoffs
< rdev
->wpan_phy
.supported
.min_csma_backoffs
||
1190 max_csma_backoffs
> rdev
->wpan_phy
.supported
.max_csma_backoffs
)
1193 return rdev_set_max_csma_backoffs(rdev
, wpan_dev
, max_csma_backoffs
);
1197 nl802154_set_max_frame_retries(struct sk_buff
*skb
, struct genl_info
*info
)
1199 struct cfg802154_registered_device
*rdev
= info
->user_ptr
[0];
1200 struct net_device
*dev
= info
->user_ptr
[1];
1201 struct wpan_dev
*wpan_dev
= dev
->ieee802154_ptr
;
1202 s8 max_frame_retries
;
1204 if (netif_running(dev
))
1207 if (!info
->attrs
[NL802154_ATTR_MAX_FRAME_RETRIES
])
1210 max_frame_retries
= nla_get_s8(
1211 info
->attrs
[NL802154_ATTR_MAX_FRAME_RETRIES
]);
1213 /* check 802.15.4 constraints */
1214 if (max_frame_retries
< rdev
->wpan_phy
.supported
.min_frame_retries
||
1215 max_frame_retries
> rdev
->wpan_phy
.supported
.max_frame_retries
)
1218 return rdev_set_max_frame_retries(rdev
, wpan_dev
, max_frame_retries
);
1221 static int nl802154_set_lbt_mode(struct sk_buff
*skb
, struct genl_info
*info
)
1223 struct cfg802154_registered_device
*rdev
= info
->user_ptr
[0];
1224 struct net_device
*dev
= info
->user_ptr
[1];
1225 struct wpan_dev
*wpan_dev
= dev
->ieee802154_ptr
;
1228 if (netif_running(dev
))
1231 if (!info
->attrs
[NL802154_ATTR_LBT_MODE
])
1234 mode
= nla_get_u8(info
->attrs
[NL802154_ATTR_LBT_MODE
]);
1236 if (mode
!= 0 && mode
!= 1)
1239 if (!wpan_phy_supported_bool(mode
, rdev
->wpan_phy
.supported
.lbt
))
1242 return rdev_set_lbt_mode(rdev
, wpan_dev
, mode
);
1246 nl802154_set_ackreq_default(struct sk_buff
*skb
, struct genl_info
*info
)
1248 struct cfg802154_registered_device
*rdev
= info
->user_ptr
[0];
1249 struct net_device
*dev
= info
->user_ptr
[1];
1250 struct wpan_dev
*wpan_dev
= dev
->ieee802154_ptr
;
1253 if (netif_running(dev
))
1256 if (!info
->attrs
[NL802154_ATTR_ACKREQ_DEFAULT
])
1259 ackreq
= nla_get_u8(info
->attrs
[NL802154_ATTR_ACKREQ_DEFAULT
]);
1261 if (ackreq
!= 0 && ackreq
!= 1)
1264 return rdev_set_ackreq_default(rdev
, wpan_dev
, ackreq
);
1267 static int nl802154_wpan_phy_netns(struct sk_buff
*skb
, struct genl_info
*info
)
1269 struct cfg802154_registered_device
*rdev
= info
->user_ptr
[0];
1273 if (info
->attrs
[NL802154_ATTR_PID
]) {
1274 u32 pid
= nla_get_u32(info
->attrs
[NL802154_ATTR_PID
]);
1276 net
= get_net_ns_by_pid(pid
);
1277 } else if (info
->attrs
[NL802154_ATTR_NETNS_FD
]) {
1278 u32 fd
= nla_get_u32(info
->attrs
[NL802154_ATTR_NETNS_FD
]);
1280 net
= get_net_ns_by_fd(fd
);
1286 return PTR_ERR(net
);
1290 /* check if anything to do */
1291 if (!net_eq(wpan_phy_net(&rdev
->wpan_phy
), net
))
1292 err
= cfg802154_switch_netns(rdev
, net
);
1298 static int nl802154_prep_scan_event_msg(struct sk_buff
*msg
,
1299 struct cfg802154_registered_device
*rdev
,
1300 struct wpan_dev
*wpan_dev
,
1301 u32 portid
, u32 seq
, int flags
, u8 cmd
,
1302 struct ieee802154_coord_desc
*desc
)
1307 hdr
= nl802154hdr_put(msg
, portid
, seq
, flags
, cmd
);
1311 if (nla_put_u32(msg
, NL802154_ATTR_WPAN_PHY
, rdev
->wpan_phy_idx
))
1312 goto nla_put_failure
;
1314 if (wpan_dev
->netdev
&&
1315 nla_put_u32(msg
, NL802154_ATTR_IFINDEX
, wpan_dev
->netdev
->ifindex
))
1316 goto nla_put_failure
;
1318 if (nla_put_u64_64bit(msg
, NL802154_ATTR_WPAN_DEV
,
1319 wpan_dev_id(wpan_dev
), NL802154_ATTR_PAD
))
1320 goto nla_put_failure
;
1322 nla
= nla_nest_start_noflag(msg
, NL802154_ATTR_COORDINATOR
);
1324 goto nla_put_failure
;
1326 if (nla_put(msg
, NL802154_COORD_PANID
, IEEE802154_PAN_ID_LEN
,
1327 &desc
->addr
.pan_id
))
1328 goto nla_put_failure
;
1330 if (desc
->addr
.mode
== IEEE802154_ADDR_SHORT
) {
1331 if (nla_put(msg
, NL802154_COORD_ADDR
,
1332 IEEE802154_SHORT_ADDR_LEN
,
1333 &desc
->addr
.short_addr
))
1334 goto nla_put_failure
;
1336 if (nla_put(msg
, NL802154_COORD_ADDR
,
1337 IEEE802154_EXTENDED_ADDR_LEN
,
1338 &desc
->addr
.extended_addr
))
1339 goto nla_put_failure
;
1342 if (nla_put_u8(msg
, NL802154_COORD_CHANNEL
, desc
->channel
))
1343 goto nla_put_failure
;
1345 if (nla_put_u8(msg
, NL802154_COORD_PAGE
, desc
->page
))
1346 goto nla_put_failure
;
1348 if (nla_put_u16(msg
, NL802154_COORD_SUPERFRAME_SPEC
,
1349 desc
->superframe_spec
))
1350 goto nla_put_failure
;
1352 if (nla_put_u8(msg
, NL802154_COORD_LINK_QUALITY
, desc
->link_quality
))
1353 goto nla_put_failure
;
1355 if (desc
->gts_permit
&& nla_put_flag(msg
, NL802154_COORD_GTS_PERMIT
))
1356 goto nla_put_failure
;
1358 /* TODO: NL802154_COORD_PAYLOAD_DATA if any */
1360 nla_nest_end(msg
, nla
);
1362 genlmsg_end(msg
, hdr
);
1367 genlmsg_cancel(msg
, hdr
);
1372 int nl802154_scan_event(struct wpan_phy
*wpan_phy
, struct wpan_dev
*wpan_dev
,
1373 struct ieee802154_coord_desc
*desc
)
1375 struct cfg802154_registered_device
*rdev
= wpan_phy_to_rdev(wpan_phy
);
1376 struct sk_buff
*msg
;
1379 msg
= nlmsg_new(NLMSG_DEFAULT_SIZE
, GFP_ATOMIC
);
1383 ret
= nl802154_prep_scan_event_msg(msg
, rdev
, wpan_dev
, 0, 0, 0,
1384 NL802154_CMD_SCAN_EVENT
,
1391 return genlmsg_multicast_netns(&nl802154_fam
, wpan_phy_net(wpan_phy
),
1392 msg
, 0, NL802154_MCGRP_SCAN
, GFP_ATOMIC
);
1394 EXPORT_SYMBOL_GPL(nl802154_scan_event
);
1396 static int nl802154_trigger_scan(struct sk_buff
*skb
, struct genl_info
*info
)
1398 struct cfg802154_registered_device
*rdev
= info
->user_ptr
[0];
1399 struct net_device
*dev
= info
->user_ptr
[1];
1400 struct wpan_dev
*wpan_dev
= dev
->ieee802154_ptr
;
1401 struct wpan_phy
*wpan_phy
= &rdev
->wpan_phy
;
1402 struct cfg802154_scan_request
*request
;
1406 if (wpan_dev
->iftype
== NL802154_IFTYPE_MONITOR
) {
1407 NL_SET_ERR_MSG(info
->extack
, "Monitors are not allowed to perform scans");
1411 if (!info
->attrs
[NL802154_ATTR_SCAN_TYPE
]) {
1412 NL_SET_ERR_MSG(info
->extack
, "Malformed request, missing scan type");
1416 if (wpan_phy
->flags
& WPAN_PHY_FLAG_DATAGRAMS_ONLY
) {
1417 NL_SET_ERR_MSG(info
->extack
, "PHY only supports datagrams");
1421 request
= kzalloc(sizeof(*request
), GFP_KERNEL
);
1425 request
->wpan_dev
= wpan_dev
;
1426 request
->wpan_phy
= wpan_phy
;
1428 type
= nla_get_u8(info
->attrs
[NL802154_ATTR_SCAN_TYPE
]);
1430 case NL802154_SCAN_ACTIVE
:
1431 case NL802154_SCAN_PASSIVE
:
1432 request
->type
= type
;
1435 NL_SET_ERR_MSG_FMT(info
->extack
, "Unsupported scan type: %d", type
);
1440 /* Use current page by default */
1441 request
->page
= nla_get_u8_default(info
->attrs
[NL802154_ATTR_PAGE
],
1442 wpan_phy
->current_page
);
1444 /* Scan all supported channels by default */
1446 nla_get_u32_default(info
->attrs
[NL802154_ATTR_SCAN_CHANNELS
],
1447 wpan_phy
->supported
.channels
[request
->page
]);
1449 /* Use maximum duration order by default */
1451 nla_get_u8_default(info
->attrs
[NL802154_ATTR_SCAN_DURATION
],
1452 IEEE802154_MAX_SCAN_DURATION
);
1454 err
= rdev_trigger_scan(rdev
, request
);
1456 pr_err("Failure starting scanning (%d)\n", err
);
1468 static int nl802154_prep_scan_msg(struct sk_buff
*msg
,
1469 struct cfg802154_registered_device
*rdev
,
1470 struct wpan_dev
*wpan_dev
, u32 portid
,
1471 u32 seq
, int flags
, u8 cmd
, u8 arg
)
1475 hdr
= nl802154hdr_put(msg
, portid
, seq
, flags
, cmd
);
1479 if (nla_put_u32(msg
, NL802154_ATTR_WPAN_PHY
, rdev
->wpan_phy_idx
))
1480 goto nla_put_failure
;
1482 if (wpan_dev
->netdev
&&
1483 nla_put_u32(msg
, NL802154_ATTR_IFINDEX
, wpan_dev
->netdev
->ifindex
))
1484 goto nla_put_failure
;
1486 if (nla_put_u64_64bit(msg
, NL802154_ATTR_WPAN_DEV
,
1487 wpan_dev_id(wpan_dev
), NL802154_ATTR_PAD
))
1488 goto nla_put_failure
;
1490 if (cmd
== NL802154_CMD_SCAN_DONE
&&
1491 nla_put_u8(msg
, NL802154_ATTR_SCAN_DONE_REASON
, arg
))
1492 goto nla_put_failure
;
1494 genlmsg_end(msg
, hdr
);
1499 genlmsg_cancel(msg
, hdr
);
1504 static int nl802154_send_scan_msg(struct cfg802154_registered_device
*rdev
,
1505 struct wpan_dev
*wpan_dev
, u8 cmd
, u8 arg
)
1507 struct sk_buff
*msg
;
1510 msg
= nlmsg_new(NLMSG_DEFAULT_SIZE
, GFP_KERNEL
);
1514 ret
= nl802154_prep_scan_msg(msg
, rdev
, wpan_dev
, 0, 0, 0, cmd
, arg
);
1520 return genlmsg_multicast_netns(&nl802154_fam
,
1521 wpan_phy_net(&rdev
->wpan_phy
), msg
, 0,
1522 NL802154_MCGRP_SCAN
, GFP_KERNEL
);
1525 int nl802154_scan_started(struct wpan_phy
*wpan_phy
, struct wpan_dev
*wpan_dev
)
1527 struct cfg802154_registered_device
*rdev
= wpan_phy_to_rdev(wpan_phy
);
1530 /* Ignore errors when there are no listeners */
1531 err
= nl802154_send_scan_msg(rdev
, wpan_dev
, NL802154_CMD_TRIGGER_SCAN
, 0);
1537 EXPORT_SYMBOL_GPL(nl802154_scan_started
);
1539 int nl802154_scan_done(struct wpan_phy
*wpan_phy
, struct wpan_dev
*wpan_dev
,
1540 enum nl802154_scan_done_reasons reason
)
1542 struct cfg802154_registered_device
*rdev
= wpan_phy_to_rdev(wpan_phy
);
1545 /* Ignore errors when there are no listeners */
1546 err
= nl802154_send_scan_msg(rdev
, wpan_dev
, NL802154_CMD_SCAN_DONE
, reason
);
1552 EXPORT_SYMBOL_GPL(nl802154_scan_done
);
1554 static int nl802154_abort_scan(struct sk_buff
*skb
, struct genl_info
*info
)
1556 struct cfg802154_registered_device
*rdev
= info
->user_ptr
[0];
1557 struct net_device
*dev
= info
->user_ptr
[1];
1558 struct wpan_dev
*wpan_dev
= dev
->ieee802154_ptr
;
1560 /* Resources are released in the notification helper above */
1561 return rdev_abort_scan(rdev
, wpan_dev
);
1565 nl802154_send_beacons(struct sk_buff
*skb
, struct genl_info
*info
)
1567 struct cfg802154_registered_device
*rdev
= info
->user_ptr
[0];
1568 struct net_device
*dev
= info
->user_ptr
[1];
1569 struct wpan_dev
*wpan_dev
= dev
->ieee802154_ptr
;
1570 struct wpan_phy
*wpan_phy
= &rdev
->wpan_phy
;
1571 struct cfg802154_beacon_request
*request
;
1574 if (wpan_dev
->iftype
!= NL802154_IFTYPE_COORD
) {
1575 NL_SET_ERR_MSG(info
->extack
, "Only coordinators can send beacons");
1579 if (wpan_dev
->pan_id
== cpu_to_le16(IEEE802154_PANID_BROADCAST
)) {
1580 NL_SET_ERR_MSG(info
->extack
, "Device is not part of any PAN");
1584 if (wpan_phy
->flags
& WPAN_PHY_FLAG_DATAGRAMS_ONLY
) {
1585 NL_SET_ERR_MSG(info
->extack
, "PHY only supports datagrams");
1589 request
= kzalloc(sizeof(*request
), GFP_KERNEL
);
1593 request
->wpan_dev
= wpan_dev
;
1594 request
->wpan_phy
= wpan_phy
;
1596 /* Use maximum duration order by default */
1597 request
->interval
= nla_get_u8_default(info
->attrs
[NL802154_ATTR_BEACON_INTERVAL
],
1598 IEEE802154_MAX_SCAN_DURATION
);
1600 err
= rdev_send_beacons(rdev
, request
);
1602 pr_err("Failure starting sending beacons (%d)\n", err
);
1614 void nl802154_beaconing_done(struct wpan_dev
*wpan_dev
)
1618 EXPORT_SYMBOL_GPL(nl802154_beaconing_done
);
1621 nl802154_stop_beacons(struct sk_buff
*skb
, struct genl_info
*info
)
1623 struct cfg802154_registered_device
*rdev
= info
->user_ptr
[0];
1624 struct net_device
*dev
= info
->user_ptr
[1];
1625 struct wpan_dev
*wpan_dev
= dev
->ieee802154_ptr
;
1627 /* Resources are released in the notification helper above */
1628 return rdev_stop_beacons(rdev
, wpan_dev
);
1631 static int nl802154_associate(struct sk_buff
*skb
, struct genl_info
*info
)
1633 struct cfg802154_registered_device
*rdev
= info
->user_ptr
[0];
1634 struct net_device
*dev
= info
->user_ptr
[1];
1635 struct wpan_dev
*wpan_dev
;
1636 struct wpan_phy
*wpan_phy
;
1637 struct ieee802154_addr coord
;
1640 wpan_dev
= dev
->ieee802154_ptr
;
1641 wpan_phy
= &rdev
->wpan_phy
;
1643 if (wpan_phy
->flags
& WPAN_PHY_FLAG_DATAGRAMS_ONLY
) {
1644 NL_SET_ERR_MSG(info
->extack
, "PHY only supports datagrams");
1648 if (!info
->attrs
[NL802154_ATTR_PAN_ID
] ||
1649 !info
->attrs
[NL802154_ATTR_EXTENDED_ADDR
])
1652 coord
.pan_id
= nla_get_le16(info
->attrs
[NL802154_ATTR_PAN_ID
]);
1653 coord
.mode
= IEEE802154_ADDR_LONG
;
1654 coord
.extended_addr
= nla_get_le64(info
->attrs
[NL802154_ATTR_EXTENDED_ADDR
]);
1656 mutex_lock(&wpan_dev
->association_lock
);
1657 err
= rdev_associate(rdev
, wpan_dev
, &coord
);
1658 mutex_unlock(&wpan_dev
->association_lock
);
1660 pr_err("Association with PAN ID 0x%x failed (%d)\n",
1661 le16_to_cpu(coord
.pan_id
), err
);
1666 static int nl802154_disassociate(struct sk_buff
*skb
, struct genl_info
*info
)
1668 struct cfg802154_registered_device
*rdev
= info
->user_ptr
[0];
1669 struct net_device
*dev
= info
->user_ptr
[1];
1670 struct wpan_dev
*wpan_dev
= dev
->ieee802154_ptr
;
1671 struct wpan_phy
*wpan_phy
= &rdev
->wpan_phy
;
1672 struct ieee802154_addr target
;
1674 if (wpan_phy
->flags
& WPAN_PHY_FLAG_DATAGRAMS_ONLY
) {
1675 NL_SET_ERR_MSG(info
->extack
, "PHY only supports datagrams");
1679 target
.pan_id
= wpan_dev
->pan_id
;
1681 if (info
->attrs
[NL802154_ATTR_EXTENDED_ADDR
]) {
1682 target
.mode
= IEEE802154_ADDR_LONG
;
1683 target
.extended_addr
= nla_get_le64(info
->attrs
[NL802154_ATTR_EXTENDED_ADDR
]);
1684 } else if (info
->attrs
[NL802154_ATTR_SHORT_ADDR
]) {
1685 target
.mode
= IEEE802154_ADDR_SHORT
;
1686 target
.short_addr
= nla_get_le16(info
->attrs
[NL802154_ATTR_SHORT_ADDR
]);
1688 NL_SET_ERR_MSG(info
->extack
, "Device address is missing");
1692 mutex_lock(&wpan_dev
->association_lock
);
1693 rdev_disassociate(rdev
, wpan_dev
, &target
);
1694 mutex_unlock(&wpan_dev
->association_lock
);
1699 static int nl802154_set_max_associations(struct sk_buff
*skb
, struct genl_info
*info
)
1701 struct net_device
*dev
= info
->user_ptr
[1];
1702 struct wpan_dev
*wpan_dev
= dev
->ieee802154_ptr
;
1703 unsigned int max_assoc
;
1705 if (!info
->attrs
[NL802154_ATTR_MAX_ASSOCIATIONS
]) {
1706 NL_SET_ERR_MSG(info
->extack
, "No maximum number of association given");
1710 max_assoc
= nla_get_u32(info
->attrs
[NL802154_ATTR_MAX_ASSOCIATIONS
]);
1712 mutex_lock(&wpan_dev
->association_lock
);
1713 cfg802154_set_max_associations(wpan_dev
, max_assoc
);
1714 mutex_unlock(&wpan_dev
->association_lock
);
1719 static int nl802154_send_peer_info(struct sk_buff
*msg
,
1720 struct netlink_callback
*cb
,
1722 struct cfg802154_registered_device
*rdev
,
1723 struct wpan_dev
*wpan_dev
,
1724 struct ieee802154_pan_device
*peer
,
1725 enum nl802154_peer_type type
)
1732 hdr
= nl802154hdr_put(msg
, NETLINK_CB(cb
->skb
).portid
, seq
, flags
,
1733 NL802154_CMD_LIST_ASSOCIATIONS
);
1737 genl_dump_check_consistent(cb
, hdr
);
1739 nla
= nla_nest_start_noflag(msg
, NL802154_ATTR_PEER
);
1741 goto nla_put_failure
;
1743 if (nla_put_u8(msg
, NL802154_DEV_ADDR_ATTR_PEER_TYPE
, type
))
1744 goto nla_put_failure
;
1746 if (nla_put_u8(msg
, NL802154_DEV_ADDR_ATTR_MODE
, peer
->mode
))
1747 goto nla_put_failure
;
1749 if (nla_put(msg
, NL802154_DEV_ADDR_ATTR_SHORT
,
1750 IEEE802154_SHORT_ADDR_LEN
, &peer
->short_addr
))
1751 goto nla_put_failure
;
1753 if (nla_put(msg
, NL802154_DEV_ADDR_ATTR_EXTENDED
,
1754 IEEE802154_EXTENDED_ADDR_LEN
, &peer
->extended_addr
))
1755 goto nla_put_failure
;
1757 nla_nest_end(msg
, nla
);
1759 genlmsg_end(msg
, hdr
);
1764 genlmsg_cancel(msg
, hdr
);
1768 static int nl802154_list_associations(struct sk_buff
*skb
,
1769 struct netlink_callback
*cb
)
1771 struct cfg802154_registered_device
*rdev
;
1772 struct ieee802154_pan_device
*child
;
1773 struct wpan_dev
*wpan_dev
;
1776 err
= nl802154_prepare_wpan_dev_dump(skb
, cb
, &rdev
, &wpan_dev
);
1780 mutex_lock(&wpan_dev
->association_lock
);
1785 if (wpan_dev
->parent
) {
1786 err
= nl802154_send_peer_info(skb
, cb
, cb
->nlh
->nlmsg_seq
,
1787 NLM_F_MULTI
, rdev
, wpan_dev
,
1789 NL802154_PEER_TYPE_PARENT
);
1794 list_for_each_entry(child
, &wpan_dev
->children
, node
) {
1795 err
= nl802154_send_peer_info(skb
, cb
, cb
->nlh
->nlmsg_seq
,
1796 NLM_F_MULTI
, rdev
, wpan_dev
,
1798 NL802154_PEER_TYPE_CHILD
);
1807 mutex_unlock(&wpan_dev
->association_lock
);
1809 nl802154_finish_wpan_dev_dump(rdev
);
1814 #ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL
1815 static const struct nla_policy nl802154_dev_addr_policy
[NL802154_DEV_ADDR_ATTR_MAX
+ 1] = {
1816 [NL802154_DEV_ADDR_ATTR_PAN_ID
] = { .type
= NLA_U16
},
1817 [NL802154_DEV_ADDR_ATTR_MODE
] = { .type
= NLA_U32
},
1818 [NL802154_DEV_ADDR_ATTR_SHORT
] = { .type
= NLA_U16
},
1819 [NL802154_DEV_ADDR_ATTR_EXTENDED
] = { .type
= NLA_U64
},
1823 ieee802154_llsec_parse_dev_addr(struct nlattr
*nla
,
1824 struct ieee802154_addr
*addr
)
1826 struct nlattr
*attrs
[NL802154_DEV_ADDR_ATTR_MAX
+ 1];
1828 if (!nla
|| nla_parse_nested_deprecated(attrs
, NL802154_DEV_ADDR_ATTR_MAX
, nla
, nl802154_dev_addr_policy
, NULL
))
1831 if (!attrs
[NL802154_DEV_ADDR_ATTR_PAN_ID
] || !attrs
[NL802154_DEV_ADDR_ATTR_MODE
])
1834 addr
->pan_id
= nla_get_le16(attrs
[NL802154_DEV_ADDR_ATTR_PAN_ID
]);
1835 addr
->mode
= nla_get_u32(attrs
[NL802154_DEV_ADDR_ATTR_MODE
]);
1836 switch (addr
->mode
) {
1837 case NL802154_DEV_ADDR_SHORT
:
1838 if (!attrs
[NL802154_DEV_ADDR_ATTR_SHORT
])
1840 addr
->short_addr
= nla_get_le16(attrs
[NL802154_DEV_ADDR_ATTR_SHORT
]);
1842 case NL802154_DEV_ADDR_EXTENDED
:
1843 if (!attrs
[NL802154_DEV_ADDR_ATTR_EXTENDED
])
1845 addr
->extended_addr
= nla_get_le64(attrs
[NL802154_DEV_ADDR_ATTR_EXTENDED
]);
1854 static const struct nla_policy nl802154_key_id_policy
[NL802154_KEY_ID_ATTR_MAX
+ 1] = {
1855 [NL802154_KEY_ID_ATTR_MODE
] = { .type
= NLA_U32
},
1856 [NL802154_KEY_ID_ATTR_INDEX
] = { .type
= NLA_U8
},
1857 [NL802154_KEY_ID_ATTR_IMPLICIT
] = { .type
= NLA_NESTED
},
1858 [NL802154_KEY_ID_ATTR_SOURCE_SHORT
] = { .type
= NLA_U32
},
1859 [NL802154_KEY_ID_ATTR_SOURCE_EXTENDED
] = { .type
= NLA_U64
},
1863 ieee802154_llsec_parse_key_id(struct nlattr
*nla
,
1864 struct ieee802154_llsec_key_id
*desc
)
1866 struct nlattr
*attrs
[NL802154_KEY_ID_ATTR_MAX
+ 1];
1868 if (!nla
|| nla_parse_nested_deprecated(attrs
, NL802154_KEY_ID_ATTR_MAX
, nla
, nl802154_key_id_policy
, NULL
))
1871 if (!attrs
[NL802154_KEY_ID_ATTR_MODE
])
1874 desc
->mode
= nla_get_u32(attrs
[NL802154_KEY_ID_ATTR_MODE
]);
1875 switch (desc
->mode
) {
1876 case NL802154_KEY_ID_MODE_IMPLICIT
:
1877 if (!attrs
[NL802154_KEY_ID_ATTR_IMPLICIT
])
1880 if (ieee802154_llsec_parse_dev_addr(attrs
[NL802154_KEY_ID_ATTR_IMPLICIT
],
1881 &desc
->device_addr
) < 0)
1884 case NL802154_KEY_ID_MODE_INDEX
:
1886 case NL802154_KEY_ID_MODE_INDEX_SHORT
:
1887 if (!attrs
[NL802154_KEY_ID_ATTR_SOURCE_SHORT
])
1890 desc
->short_source
= nla_get_le32(attrs
[NL802154_KEY_ID_ATTR_SOURCE_SHORT
]);
1892 case NL802154_KEY_ID_MODE_INDEX_EXTENDED
:
1893 if (!attrs
[NL802154_KEY_ID_ATTR_SOURCE_EXTENDED
])
1896 desc
->extended_source
= nla_get_le64(attrs
[NL802154_KEY_ID_ATTR_SOURCE_EXTENDED
]);
1902 if (desc
->mode
!= NL802154_KEY_ID_MODE_IMPLICIT
) {
1903 if (!attrs
[NL802154_KEY_ID_ATTR_INDEX
])
1906 /* TODO change id to idx */
1907 desc
->id
= nla_get_u8(attrs
[NL802154_KEY_ID_ATTR_INDEX
]);
1913 static int nl802154_set_llsec_params(struct sk_buff
*skb
,
1914 struct genl_info
*info
)
1916 struct cfg802154_registered_device
*rdev
= info
->user_ptr
[0];
1917 struct net_device
*dev
= info
->user_ptr
[1];
1918 struct wpan_dev
*wpan_dev
= dev
->ieee802154_ptr
;
1919 struct ieee802154_llsec_params params
;
1923 if (wpan_dev
->iftype
== NL802154_IFTYPE_MONITOR
)
1926 if (info
->attrs
[NL802154_ATTR_SEC_ENABLED
]) {
1929 enabled
= nla_get_u8(info
->attrs
[NL802154_ATTR_SEC_ENABLED
]);
1930 if (enabled
!= 0 && enabled
!= 1)
1933 params
.enabled
= nla_get_u8(info
->attrs
[NL802154_ATTR_SEC_ENABLED
]);
1934 changed
|= IEEE802154_LLSEC_PARAM_ENABLED
;
1937 if (info
->attrs
[NL802154_ATTR_SEC_OUT_KEY_ID
]) {
1938 ret
= ieee802154_llsec_parse_key_id(info
->attrs
[NL802154_ATTR_SEC_OUT_KEY_ID
],
1943 changed
|= IEEE802154_LLSEC_PARAM_OUT_KEY
;
1946 if (info
->attrs
[NL802154_ATTR_SEC_OUT_LEVEL
]) {
1947 params
.out_level
= nla_get_u32(info
->attrs
[NL802154_ATTR_SEC_OUT_LEVEL
]);
1948 if (params
.out_level
> NL802154_SECLEVEL_MAX
)
1951 changed
|= IEEE802154_LLSEC_PARAM_OUT_LEVEL
;
1954 if (info
->attrs
[NL802154_ATTR_SEC_FRAME_COUNTER
]) {
1955 params
.frame_counter
= nla_get_be32(info
->attrs
[NL802154_ATTR_SEC_FRAME_COUNTER
]);
1956 changed
|= IEEE802154_LLSEC_PARAM_FRAME_COUNTER
;
1959 return rdev_set_llsec_params(rdev
, wpan_dev
, ¶ms
, changed
);
1962 static int nl802154_send_key(struct sk_buff
*msg
, u32 cmd
, u32 portid
,
1964 struct cfg802154_registered_device
*rdev
,
1965 struct net_device
*dev
,
1966 const struct ieee802154_llsec_key_entry
*key
)
1969 u32 commands
[NL802154_CMD_FRAME_NR_IDS
/ 32];
1970 struct nlattr
*nl_key
, *nl_key_id
;
1972 hdr
= nl802154hdr_put(msg
, portid
, seq
, flags
, cmd
);
1976 if (nla_put_u32(msg
, NL802154_ATTR_IFINDEX
, dev
->ifindex
))
1977 goto nla_put_failure
;
1979 nl_key
= nla_nest_start_noflag(msg
, NL802154_ATTR_SEC_KEY
);
1981 goto nla_put_failure
;
1983 nl_key_id
= nla_nest_start_noflag(msg
, NL802154_KEY_ATTR_ID
);
1985 goto nla_put_failure
;
1987 if (ieee802154_llsec_send_key_id(msg
, &key
->id
) < 0)
1988 goto nla_put_failure
;
1990 nla_nest_end(msg
, nl_key_id
);
1992 if (nla_put_u8(msg
, NL802154_KEY_ATTR_USAGE_FRAMES
,
1993 key
->key
->frame_types
))
1994 goto nla_put_failure
;
1996 if (key
->key
->frame_types
& BIT(NL802154_FRAME_CMD
)) {
1997 /* TODO for each nested */
1998 memset(commands
, 0, sizeof(commands
));
1999 commands
[7] = key
->key
->cmd_frame_ids
;
2000 if (nla_put(msg
, NL802154_KEY_ATTR_USAGE_CMDS
,
2001 sizeof(commands
), commands
))
2002 goto nla_put_failure
;
2005 if (nla_put(msg
, NL802154_KEY_ATTR_BYTES
, NL802154_KEY_SIZE
,
2007 goto nla_put_failure
;
2009 nla_nest_end(msg
, nl_key
);
2010 genlmsg_end(msg
, hdr
);
2015 genlmsg_cancel(msg
, hdr
);
2020 nl802154_dump_llsec_key(struct sk_buff
*skb
, struct netlink_callback
*cb
)
2022 struct cfg802154_registered_device
*rdev
= NULL
;
2023 struct ieee802154_llsec_key_entry
*key
;
2024 struct ieee802154_llsec_table
*table
;
2025 struct wpan_dev
*wpan_dev
;
2028 err
= nl802154_prepare_wpan_dev_dump(skb
, cb
, &rdev
, &wpan_dev
);
2032 if (wpan_dev
->iftype
== NL802154_IFTYPE_MONITOR
) {
2037 if (!wpan_dev
->netdev
) {
2042 rdev_lock_llsec_table(rdev
, wpan_dev
);
2043 rdev_get_llsec_table(rdev
, wpan_dev
, &table
);
2045 /* TODO make it like station dump */
2049 list_for_each_entry(key
, &table
->keys
, list
) {
2050 if (nl802154_send_key(skb
, NL802154_CMD_NEW_SEC_KEY
,
2051 NETLINK_CB(cb
->skb
).portid
,
2052 cb
->nlh
->nlmsg_seq
, NLM_F_MULTI
,
2053 rdev
, wpan_dev
->netdev
, key
) < 0) {
2056 rdev_unlock_llsec_table(rdev
, wpan_dev
);
2064 rdev_unlock_llsec_table(rdev
, wpan_dev
);
2067 nl802154_finish_wpan_dev_dump(rdev
);
2072 static const struct nla_policy nl802154_key_policy
[NL802154_KEY_ATTR_MAX
+ 1] = {
2073 [NL802154_KEY_ATTR_ID
] = { NLA_NESTED
},
2074 /* TODO handle it as for_each_nested and NLA_FLAG? */
2075 [NL802154_KEY_ATTR_USAGE_FRAMES
] = { NLA_U8
},
2076 /* TODO handle it as for_each_nested, not static array? */
2077 [NL802154_KEY_ATTR_USAGE_CMDS
] = { .len
= NL802154_CMD_FRAME_NR_IDS
/ 8 },
2078 [NL802154_KEY_ATTR_BYTES
] = { .len
= NL802154_KEY_SIZE
},
2081 static int nl802154_add_llsec_key(struct sk_buff
*skb
, struct genl_info
*info
)
2083 struct cfg802154_registered_device
*rdev
= info
->user_ptr
[0];
2084 struct net_device
*dev
= info
->user_ptr
[1];
2085 struct wpan_dev
*wpan_dev
= dev
->ieee802154_ptr
;
2086 struct nlattr
*attrs
[NL802154_KEY_ATTR_MAX
+ 1];
2087 struct ieee802154_llsec_key key
= { };
2088 struct ieee802154_llsec_key_id id
= { };
2089 u32 commands
[NL802154_CMD_FRAME_NR_IDS
/ 32] = { };
2091 if (wpan_dev
->iftype
== NL802154_IFTYPE_MONITOR
)
2094 if (!info
->attrs
[NL802154_ATTR_SEC_KEY
] ||
2095 nla_parse_nested_deprecated(attrs
, NL802154_KEY_ATTR_MAX
, info
->attrs
[NL802154_ATTR_SEC_KEY
], nl802154_key_policy
, info
->extack
))
2098 if (!attrs
[NL802154_KEY_ATTR_USAGE_FRAMES
] ||
2099 !attrs
[NL802154_KEY_ATTR_BYTES
])
2102 if (ieee802154_llsec_parse_key_id(attrs
[NL802154_KEY_ATTR_ID
], &id
) < 0)
2105 key
.frame_types
= nla_get_u8(attrs
[NL802154_KEY_ATTR_USAGE_FRAMES
]);
2106 if (key
.frame_types
> BIT(NL802154_FRAME_MAX
) ||
2107 ((key
.frame_types
& BIT(NL802154_FRAME_CMD
)) &&
2108 !attrs
[NL802154_KEY_ATTR_USAGE_CMDS
]))
2111 if (attrs
[NL802154_KEY_ATTR_USAGE_CMDS
]) {
2112 /* TODO for each nested */
2113 nla_memcpy(commands
, attrs
[NL802154_KEY_ATTR_USAGE_CMDS
],
2114 NL802154_CMD_FRAME_NR_IDS
/ 8);
2116 /* TODO understand the -EINVAL logic here? last condition */
2117 if (commands
[0] || commands
[1] || commands
[2] || commands
[3] ||
2118 commands
[4] || commands
[5] || commands
[6] ||
2119 commands
[7] > BIT(NL802154_CMD_FRAME_MAX
))
2122 key
.cmd_frame_ids
= commands
[7];
2124 key
.cmd_frame_ids
= 0;
2127 nla_memcpy(key
.key
, attrs
[NL802154_KEY_ATTR_BYTES
], NL802154_KEY_SIZE
);
2129 if (ieee802154_llsec_parse_key_id(attrs
[NL802154_KEY_ATTR_ID
], &id
) < 0)
2132 return rdev_add_llsec_key(rdev
, wpan_dev
, &id
, &key
);
2135 static int nl802154_del_llsec_key(struct sk_buff
*skb
, struct genl_info
*info
)
2137 struct cfg802154_registered_device
*rdev
= info
->user_ptr
[0];
2138 struct net_device
*dev
= info
->user_ptr
[1];
2139 struct wpan_dev
*wpan_dev
= dev
->ieee802154_ptr
;
2140 struct nlattr
*attrs
[NL802154_KEY_ATTR_MAX
+ 1];
2141 struct ieee802154_llsec_key_id id
;
2143 if (wpan_dev
->iftype
== NL802154_IFTYPE_MONITOR
)
2146 if (!info
->attrs
[NL802154_ATTR_SEC_KEY
] ||
2147 nla_parse_nested_deprecated(attrs
, NL802154_KEY_ATTR_MAX
, info
->attrs
[NL802154_ATTR_SEC_KEY
], nl802154_key_policy
, info
->extack
))
2150 if (ieee802154_llsec_parse_key_id(attrs
[NL802154_KEY_ATTR_ID
], &id
) < 0)
2153 return rdev_del_llsec_key(rdev
, wpan_dev
, &id
);
2156 static int nl802154_send_device(struct sk_buff
*msg
, u32 cmd
, u32 portid
,
2158 struct cfg802154_registered_device
*rdev
,
2159 struct net_device
*dev
,
2160 const struct ieee802154_llsec_device
*dev_desc
)
2163 struct nlattr
*nl_device
;
2165 hdr
= nl802154hdr_put(msg
, portid
, seq
, flags
, cmd
);
2169 if (nla_put_u32(msg
, NL802154_ATTR_IFINDEX
, dev
->ifindex
))
2170 goto nla_put_failure
;
2172 nl_device
= nla_nest_start_noflag(msg
, NL802154_ATTR_SEC_DEVICE
);
2174 goto nla_put_failure
;
2176 if (nla_put_u32(msg
, NL802154_DEV_ATTR_FRAME_COUNTER
,
2177 dev_desc
->frame_counter
) ||
2178 nla_put_le16(msg
, NL802154_DEV_ATTR_PAN_ID
, dev_desc
->pan_id
) ||
2179 nla_put_le16(msg
, NL802154_DEV_ATTR_SHORT_ADDR
,
2180 dev_desc
->short_addr
) ||
2181 nla_put_le64(msg
, NL802154_DEV_ATTR_EXTENDED_ADDR
,
2182 dev_desc
->hwaddr
, NL802154_DEV_ATTR_PAD
) ||
2183 nla_put_u8(msg
, NL802154_DEV_ATTR_SECLEVEL_EXEMPT
,
2184 dev_desc
->seclevel_exempt
) ||
2185 nla_put_u32(msg
, NL802154_DEV_ATTR_KEY_MODE
, dev_desc
->key_mode
))
2186 goto nla_put_failure
;
2188 nla_nest_end(msg
, nl_device
);
2189 genlmsg_end(msg
, hdr
);
2194 genlmsg_cancel(msg
, hdr
);
2199 nl802154_dump_llsec_dev(struct sk_buff
*skb
, struct netlink_callback
*cb
)
2201 struct cfg802154_registered_device
*rdev
= NULL
;
2202 struct ieee802154_llsec_device
*dev
;
2203 struct ieee802154_llsec_table
*table
;
2204 struct wpan_dev
*wpan_dev
;
2207 err
= nl802154_prepare_wpan_dev_dump(skb
, cb
, &rdev
, &wpan_dev
);
2211 if (wpan_dev
->iftype
== NL802154_IFTYPE_MONITOR
) {
2216 if (!wpan_dev
->netdev
) {
2221 rdev_lock_llsec_table(rdev
, wpan_dev
);
2222 rdev_get_llsec_table(rdev
, wpan_dev
, &table
);
2224 /* TODO make it like station dump */
2228 list_for_each_entry(dev
, &table
->devices
, list
) {
2229 if (nl802154_send_device(skb
, NL802154_CMD_NEW_SEC_LEVEL
,
2230 NETLINK_CB(cb
->skb
).portid
,
2231 cb
->nlh
->nlmsg_seq
, NLM_F_MULTI
,
2232 rdev
, wpan_dev
->netdev
, dev
) < 0) {
2235 rdev_unlock_llsec_table(rdev
, wpan_dev
);
2243 rdev_unlock_llsec_table(rdev
, wpan_dev
);
2246 nl802154_finish_wpan_dev_dump(rdev
);
2251 static const struct nla_policy nl802154_dev_policy
[NL802154_DEV_ATTR_MAX
+ 1] = {
2252 [NL802154_DEV_ATTR_FRAME_COUNTER
] = { NLA_U32
},
2253 [NL802154_DEV_ATTR_PAN_ID
] = { .type
= NLA_U16
},
2254 [NL802154_DEV_ATTR_SHORT_ADDR
] = { .type
= NLA_U16
},
2255 [NL802154_DEV_ATTR_EXTENDED_ADDR
] = { .type
= NLA_U64
},
2256 [NL802154_DEV_ATTR_SECLEVEL_EXEMPT
] = { NLA_U8
},
2257 [NL802154_DEV_ATTR_KEY_MODE
] = { NLA_U32
},
2261 ieee802154_llsec_parse_device(struct nlattr
*nla
,
2262 struct ieee802154_llsec_device
*dev
)
2264 struct nlattr
*attrs
[NL802154_DEV_ATTR_MAX
+ 1];
2266 if (!nla
|| nla_parse_nested_deprecated(attrs
, NL802154_DEV_ATTR_MAX
, nla
, nl802154_dev_policy
, NULL
))
2269 memset(dev
, 0, sizeof(*dev
));
2271 if (!attrs
[NL802154_DEV_ATTR_FRAME_COUNTER
] ||
2272 !attrs
[NL802154_DEV_ATTR_PAN_ID
] ||
2273 !attrs
[NL802154_DEV_ATTR_SHORT_ADDR
] ||
2274 !attrs
[NL802154_DEV_ATTR_EXTENDED_ADDR
] ||
2275 !attrs
[NL802154_DEV_ATTR_SECLEVEL_EXEMPT
] ||
2276 !attrs
[NL802154_DEV_ATTR_KEY_MODE
])
2280 dev
->frame_counter
= nla_get_u32(attrs
[NL802154_DEV_ATTR_FRAME_COUNTER
]);
2281 dev
->pan_id
= nla_get_le16(attrs
[NL802154_DEV_ATTR_PAN_ID
]);
2282 dev
->short_addr
= nla_get_le16(attrs
[NL802154_DEV_ATTR_SHORT_ADDR
]);
2283 /* TODO rename hwaddr to extended_addr */
2284 dev
->hwaddr
= nla_get_le64(attrs
[NL802154_DEV_ATTR_EXTENDED_ADDR
]);
2285 dev
->seclevel_exempt
= nla_get_u8(attrs
[NL802154_DEV_ATTR_SECLEVEL_EXEMPT
]);
2286 dev
->key_mode
= nla_get_u32(attrs
[NL802154_DEV_ATTR_KEY_MODE
]);
2288 if (dev
->key_mode
> NL802154_DEVKEY_MAX
||
2289 (dev
->seclevel_exempt
!= 0 && dev
->seclevel_exempt
!= 1))
2295 static int nl802154_add_llsec_dev(struct sk_buff
*skb
, struct genl_info
*info
)
2297 struct cfg802154_registered_device
*rdev
= info
->user_ptr
[0];
2298 struct net_device
*dev
= info
->user_ptr
[1];
2299 struct wpan_dev
*wpan_dev
= dev
->ieee802154_ptr
;
2300 struct ieee802154_llsec_device dev_desc
;
2302 if (wpan_dev
->iftype
== NL802154_IFTYPE_MONITOR
)
2305 if (ieee802154_llsec_parse_device(info
->attrs
[NL802154_ATTR_SEC_DEVICE
],
2309 return rdev_add_device(rdev
, wpan_dev
, &dev_desc
);
2312 static int nl802154_del_llsec_dev(struct sk_buff
*skb
, struct genl_info
*info
)
2314 struct cfg802154_registered_device
*rdev
= info
->user_ptr
[0];
2315 struct net_device
*dev
= info
->user_ptr
[1];
2316 struct wpan_dev
*wpan_dev
= dev
->ieee802154_ptr
;
2317 struct nlattr
*attrs
[NL802154_DEV_ATTR_MAX
+ 1];
2318 __le64 extended_addr
;
2320 if (wpan_dev
->iftype
== NL802154_IFTYPE_MONITOR
)
2323 if (!info
->attrs
[NL802154_ATTR_SEC_DEVICE
] ||
2324 nla_parse_nested_deprecated(attrs
, NL802154_DEV_ATTR_MAX
, info
->attrs
[NL802154_ATTR_SEC_DEVICE
], nl802154_dev_policy
, info
->extack
))
2327 if (!attrs
[NL802154_DEV_ATTR_EXTENDED_ADDR
])
2330 extended_addr
= nla_get_le64(attrs
[NL802154_DEV_ATTR_EXTENDED_ADDR
]);
2331 return rdev_del_device(rdev
, wpan_dev
, extended_addr
);
2334 static int nl802154_send_devkey(struct sk_buff
*msg
, u32 cmd
, u32 portid
,
2336 struct cfg802154_registered_device
*rdev
,
2337 struct net_device
*dev
, __le64 extended_addr
,
2338 const struct ieee802154_llsec_device_key
*devkey
)
2341 struct nlattr
*nl_devkey
, *nl_key_id
;
2343 hdr
= nl802154hdr_put(msg
, portid
, seq
, flags
, cmd
);
2347 if (nla_put_u32(msg
, NL802154_ATTR_IFINDEX
, dev
->ifindex
))
2348 goto nla_put_failure
;
2350 nl_devkey
= nla_nest_start_noflag(msg
, NL802154_ATTR_SEC_DEVKEY
);
2352 goto nla_put_failure
;
2354 if (nla_put_le64(msg
, NL802154_DEVKEY_ATTR_EXTENDED_ADDR
,
2355 extended_addr
, NL802154_DEVKEY_ATTR_PAD
) ||
2356 nla_put_u32(msg
, NL802154_DEVKEY_ATTR_FRAME_COUNTER
,
2357 devkey
->frame_counter
))
2358 goto nla_put_failure
;
2360 nl_key_id
= nla_nest_start_noflag(msg
, NL802154_DEVKEY_ATTR_ID
);
2362 goto nla_put_failure
;
2364 if (ieee802154_llsec_send_key_id(msg
, &devkey
->key_id
) < 0)
2365 goto nla_put_failure
;
2367 nla_nest_end(msg
, nl_key_id
);
2368 nla_nest_end(msg
, nl_devkey
);
2369 genlmsg_end(msg
, hdr
);
2374 genlmsg_cancel(msg
, hdr
);
2379 nl802154_dump_llsec_devkey(struct sk_buff
*skb
, struct netlink_callback
*cb
)
2381 struct cfg802154_registered_device
*rdev
= NULL
;
2382 struct ieee802154_llsec_device_key
*kpos
;
2383 struct ieee802154_llsec_device
*dpos
;
2384 struct ieee802154_llsec_table
*table
;
2385 struct wpan_dev
*wpan_dev
;
2388 err
= nl802154_prepare_wpan_dev_dump(skb
, cb
, &rdev
, &wpan_dev
);
2392 if (wpan_dev
->iftype
== NL802154_IFTYPE_MONITOR
) {
2397 if (!wpan_dev
->netdev
) {
2402 rdev_lock_llsec_table(rdev
, wpan_dev
);
2403 rdev_get_llsec_table(rdev
, wpan_dev
, &table
);
2405 /* TODO make it like station dump */
2409 /* TODO look if remove devkey and do some nested attribute */
2410 list_for_each_entry(dpos
, &table
->devices
, list
) {
2411 list_for_each_entry(kpos
, &dpos
->keys
, list
) {
2412 if (nl802154_send_devkey(skb
,
2413 NL802154_CMD_NEW_SEC_LEVEL
,
2414 NETLINK_CB(cb
->skb
).portid
,
2422 rdev_unlock_llsec_table(rdev
, wpan_dev
);
2431 rdev_unlock_llsec_table(rdev
, wpan_dev
);
2434 nl802154_finish_wpan_dev_dump(rdev
);
2439 static const struct nla_policy nl802154_devkey_policy
[NL802154_DEVKEY_ATTR_MAX
+ 1] = {
2440 [NL802154_DEVKEY_ATTR_FRAME_COUNTER
] = { NLA_U32
},
2441 [NL802154_DEVKEY_ATTR_EXTENDED_ADDR
] = { NLA_U64
},
2442 [NL802154_DEVKEY_ATTR_ID
] = { NLA_NESTED
},
2445 static int nl802154_add_llsec_devkey(struct sk_buff
*skb
, struct genl_info
*info
)
2447 struct cfg802154_registered_device
*rdev
= info
->user_ptr
[0];
2448 struct net_device
*dev
= info
->user_ptr
[1];
2449 struct wpan_dev
*wpan_dev
= dev
->ieee802154_ptr
;
2450 struct nlattr
*attrs
[NL802154_DEVKEY_ATTR_MAX
+ 1];
2451 struct ieee802154_llsec_device_key key
;
2452 __le64 extended_addr
;
2454 if (wpan_dev
->iftype
== NL802154_IFTYPE_MONITOR
)
2457 if (!info
->attrs
[NL802154_ATTR_SEC_DEVKEY
] ||
2458 nla_parse_nested_deprecated(attrs
, NL802154_DEVKEY_ATTR_MAX
, info
->attrs
[NL802154_ATTR_SEC_DEVKEY
], nl802154_devkey_policy
, info
->extack
) < 0)
2461 if (!attrs
[NL802154_DEVKEY_ATTR_FRAME_COUNTER
] ||
2462 !attrs
[NL802154_DEVKEY_ATTR_EXTENDED_ADDR
])
2465 /* TODO change key.id ? */
2466 if (ieee802154_llsec_parse_key_id(attrs
[NL802154_DEVKEY_ATTR_ID
],
2471 key
.frame_counter
= nla_get_u32(attrs
[NL802154_DEVKEY_ATTR_FRAME_COUNTER
]);
2472 /* TODO change naming hwaddr -> extended_addr
2473 * check unique identifier short+pan OR extended_addr
2475 extended_addr
= nla_get_le64(attrs
[NL802154_DEVKEY_ATTR_EXTENDED_ADDR
]);
2476 return rdev_add_devkey(rdev
, wpan_dev
, extended_addr
, &key
);
2479 static int nl802154_del_llsec_devkey(struct sk_buff
*skb
, struct genl_info
*info
)
2481 struct cfg802154_registered_device
*rdev
= info
->user_ptr
[0];
2482 struct net_device
*dev
= info
->user_ptr
[1];
2483 struct wpan_dev
*wpan_dev
= dev
->ieee802154_ptr
;
2484 struct nlattr
*attrs
[NL802154_DEVKEY_ATTR_MAX
+ 1];
2485 struct ieee802154_llsec_device_key key
;
2486 __le64 extended_addr
;
2488 if (wpan_dev
->iftype
== NL802154_IFTYPE_MONITOR
)
2491 if (!info
->attrs
[NL802154_ATTR_SEC_DEVKEY
] ||
2492 nla_parse_nested_deprecated(attrs
, NL802154_DEVKEY_ATTR_MAX
, info
->attrs
[NL802154_ATTR_SEC_DEVKEY
], nl802154_devkey_policy
, info
->extack
))
2495 if (!attrs
[NL802154_DEVKEY_ATTR_EXTENDED_ADDR
])
2498 /* TODO change key.id ? */
2499 if (ieee802154_llsec_parse_key_id(attrs
[NL802154_DEVKEY_ATTR_ID
],
2503 /* TODO change naming hwaddr -> extended_addr
2504 * check unique identifier short+pan OR extended_addr
2506 extended_addr
= nla_get_le64(attrs
[NL802154_DEVKEY_ATTR_EXTENDED_ADDR
]);
2507 return rdev_del_devkey(rdev
, wpan_dev
, extended_addr
, &key
);
2510 static int nl802154_send_seclevel(struct sk_buff
*msg
, u32 cmd
, u32 portid
,
2512 struct cfg802154_registered_device
*rdev
,
2513 struct net_device
*dev
,
2514 const struct ieee802154_llsec_seclevel
*sl
)
2517 struct nlattr
*nl_seclevel
;
2519 hdr
= nl802154hdr_put(msg
, portid
, seq
, flags
, cmd
);
2523 if (nla_put_u32(msg
, NL802154_ATTR_IFINDEX
, dev
->ifindex
))
2524 goto nla_put_failure
;
2526 nl_seclevel
= nla_nest_start_noflag(msg
, NL802154_ATTR_SEC_LEVEL
);
2528 goto nla_put_failure
;
2530 if (nla_put_u32(msg
, NL802154_SECLEVEL_ATTR_FRAME
, sl
->frame_type
) ||
2531 nla_put_u32(msg
, NL802154_SECLEVEL_ATTR_LEVELS
, sl
->sec_levels
) ||
2532 nla_put_u8(msg
, NL802154_SECLEVEL_ATTR_DEV_OVERRIDE
,
2533 sl
->device_override
))
2534 goto nla_put_failure
;
2536 if (sl
->frame_type
== NL802154_FRAME_CMD
) {
2537 if (nla_put_u32(msg
, NL802154_SECLEVEL_ATTR_CMD_FRAME
,
2539 goto nla_put_failure
;
2542 nla_nest_end(msg
, nl_seclevel
);
2543 genlmsg_end(msg
, hdr
);
2548 genlmsg_cancel(msg
, hdr
);
2553 nl802154_dump_llsec_seclevel(struct sk_buff
*skb
, struct netlink_callback
*cb
)
2555 struct cfg802154_registered_device
*rdev
= NULL
;
2556 struct ieee802154_llsec_seclevel
*sl
;
2557 struct ieee802154_llsec_table
*table
;
2558 struct wpan_dev
*wpan_dev
;
2561 err
= nl802154_prepare_wpan_dev_dump(skb
, cb
, &rdev
, &wpan_dev
);
2565 if (wpan_dev
->iftype
== NL802154_IFTYPE_MONITOR
) {
2570 if (!wpan_dev
->netdev
) {
2575 rdev_lock_llsec_table(rdev
, wpan_dev
);
2576 rdev_get_llsec_table(rdev
, wpan_dev
, &table
);
2578 /* TODO make it like station dump */
2582 list_for_each_entry(sl
, &table
->security_levels
, list
) {
2583 if (nl802154_send_seclevel(skb
, NL802154_CMD_NEW_SEC_LEVEL
,
2584 NETLINK_CB(cb
->skb
).portid
,
2585 cb
->nlh
->nlmsg_seq
, NLM_F_MULTI
,
2586 rdev
, wpan_dev
->netdev
, sl
) < 0) {
2589 rdev_unlock_llsec_table(rdev
, wpan_dev
);
2597 rdev_unlock_llsec_table(rdev
, wpan_dev
);
2600 nl802154_finish_wpan_dev_dump(rdev
);
2605 static const struct nla_policy nl802154_seclevel_policy
[NL802154_SECLEVEL_ATTR_MAX
+ 1] = {
2606 [NL802154_SECLEVEL_ATTR_LEVELS
] = { .type
= NLA_U8
},
2607 [NL802154_SECLEVEL_ATTR_FRAME
] = { .type
= NLA_U32
},
2608 [NL802154_SECLEVEL_ATTR_CMD_FRAME
] = { .type
= NLA_U32
},
2609 [NL802154_SECLEVEL_ATTR_DEV_OVERRIDE
] = { .type
= NLA_U8
},
2613 llsec_parse_seclevel(struct nlattr
*nla
, struct ieee802154_llsec_seclevel
*sl
)
2615 struct nlattr
*attrs
[NL802154_SECLEVEL_ATTR_MAX
+ 1];
2617 if (!nla
|| nla_parse_nested_deprecated(attrs
, NL802154_SECLEVEL_ATTR_MAX
, nla
, nl802154_seclevel_policy
, NULL
))
2620 memset(sl
, 0, sizeof(*sl
));
2622 if (!attrs
[NL802154_SECLEVEL_ATTR_LEVELS
] ||
2623 !attrs
[NL802154_SECLEVEL_ATTR_FRAME
] ||
2624 !attrs
[NL802154_SECLEVEL_ATTR_DEV_OVERRIDE
])
2627 sl
->sec_levels
= nla_get_u8(attrs
[NL802154_SECLEVEL_ATTR_LEVELS
]);
2628 sl
->frame_type
= nla_get_u32(attrs
[NL802154_SECLEVEL_ATTR_FRAME
]);
2629 sl
->device_override
= nla_get_u8(attrs
[NL802154_SECLEVEL_ATTR_DEV_OVERRIDE
]);
2630 if (sl
->frame_type
> NL802154_FRAME_MAX
||
2631 (sl
->device_override
!= 0 && sl
->device_override
!= 1))
2634 if (sl
->frame_type
== NL802154_FRAME_CMD
) {
2635 if (!attrs
[NL802154_SECLEVEL_ATTR_CMD_FRAME
])
2638 sl
->cmd_frame_id
= nla_get_u32(attrs
[NL802154_SECLEVEL_ATTR_CMD_FRAME
]);
2639 if (sl
->cmd_frame_id
> NL802154_CMD_FRAME_MAX
)
2646 static int nl802154_add_llsec_seclevel(struct sk_buff
*skb
,
2647 struct genl_info
*info
)
2649 struct cfg802154_registered_device
*rdev
= info
->user_ptr
[0];
2650 struct net_device
*dev
= info
->user_ptr
[1];
2651 struct wpan_dev
*wpan_dev
= dev
->ieee802154_ptr
;
2652 struct ieee802154_llsec_seclevel sl
;
2654 if (wpan_dev
->iftype
== NL802154_IFTYPE_MONITOR
)
2657 if (llsec_parse_seclevel(info
->attrs
[NL802154_ATTR_SEC_LEVEL
],
2661 return rdev_add_seclevel(rdev
, wpan_dev
, &sl
);
2664 static int nl802154_del_llsec_seclevel(struct sk_buff
*skb
,
2665 struct genl_info
*info
)
2667 struct cfg802154_registered_device
*rdev
= info
->user_ptr
[0];
2668 struct net_device
*dev
= info
->user_ptr
[1];
2669 struct wpan_dev
*wpan_dev
= dev
->ieee802154_ptr
;
2670 struct ieee802154_llsec_seclevel sl
;
2672 if (wpan_dev
->iftype
== NL802154_IFTYPE_MONITOR
)
2675 if (llsec_parse_seclevel(info
->attrs
[NL802154_ATTR_SEC_LEVEL
],
2679 return rdev_del_seclevel(rdev
, wpan_dev
, &sl
);
2681 #endif /* CONFIG_IEEE802154_NL802154_EXPERIMENTAL */
2683 #define NL802154_FLAG_NEED_WPAN_PHY 0x01
2684 #define NL802154_FLAG_NEED_NETDEV 0x02
2685 #define NL802154_FLAG_NEED_RTNL 0x04
2686 #define NL802154_FLAG_CHECK_NETDEV_UP 0x08
2687 #define NL802154_FLAG_NEED_WPAN_DEV 0x10
2689 static int nl802154_pre_doit(const struct genl_split_ops
*ops
,
2690 struct sk_buff
*skb
,
2691 struct genl_info
*info
)
2693 struct cfg802154_registered_device
*rdev
;
2694 struct wpan_dev
*wpan_dev
;
2695 struct net_device
*dev
;
2696 bool rtnl
= ops
->internal_flags
& NL802154_FLAG_NEED_RTNL
;
2701 if (ops
->internal_flags
& NL802154_FLAG_NEED_WPAN_PHY
) {
2702 rdev
= cfg802154_get_dev_from_info(genl_info_net(info
), info
);
2706 return PTR_ERR(rdev
);
2708 info
->user_ptr
[0] = rdev
;
2709 } else if (ops
->internal_flags
& NL802154_FLAG_NEED_NETDEV
||
2710 ops
->internal_flags
& NL802154_FLAG_NEED_WPAN_DEV
) {
2712 wpan_dev
= __cfg802154_wpan_dev_from_attrs(genl_info_net(info
),
2714 if (IS_ERR(wpan_dev
)) {
2717 return PTR_ERR(wpan_dev
);
2720 dev
= wpan_dev
->netdev
;
2721 rdev
= wpan_phy_to_rdev(wpan_dev
->wpan_phy
);
2723 if (ops
->internal_flags
& NL802154_FLAG_NEED_NETDEV
) {
2730 info
->user_ptr
[1] = dev
;
2732 info
->user_ptr
[1] = wpan_dev
;
2736 if (ops
->internal_flags
& NL802154_FLAG_CHECK_NETDEV_UP
&&
2737 !netif_running(dev
)) {
2746 info
->user_ptr
[0] = rdev
;
2752 static void nl802154_post_doit(const struct genl_split_ops
*ops
,
2753 struct sk_buff
*skb
,
2754 struct genl_info
*info
)
2756 if (info
->user_ptr
[1]) {
2757 if (ops
->internal_flags
& NL802154_FLAG_NEED_WPAN_DEV
) {
2758 struct wpan_dev
*wpan_dev
= info
->user_ptr
[1];
2760 dev_put(wpan_dev
->netdev
);
2762 dev_put(info
->user_ptr
[1]);
2766 if (ops
->internal_flags
& NL802154_FLAG_NEED_RTNL
)
2770 static const struct genl_ops nl802154_ops
[] = {
2772 .cmd
= NL802154_CMD_GET_WPAN_PHY
,
2773 .validate
= GENL_DONT_VALIDATE_STRICT
|
2774 GENL_DONT_VALIDATE_DUMP_STRICT
,
2775 .doit
= nl802154_get_wpan_phy
,
2776 .dumpit
= nl802154_dump_wpan_phy
,
2777 .done
= nl802154_dump_wpan_phy_done
,
2778 /* can be retrieved by unprivileged users */
2779 .internal_flags
= NL802154_FLAG_NEED_WPAN_PHY
|
2780 NL802154_FLAG_NEED_RTNL
,
2783 .cmd
= NL802154_CMD_GET_INTERFACE
,
2784 .validate
= GENL_DONT_VALIDATE_STRICT
| GENL_DONT_VALIDATE_DUMP
,
2785 .doit
= nl802154_get_interface
,
2786 .dumpit
= nl802154_dump_interface
,
2787 /* can be retrieved by unprivileged users */
2788 .internal_flags
= NL802154_FLAG_NEED_WPAN_DEV
|
2789 NL802154_FLAG_NEED_RTNL
,
2792 .cmd
= NL802154_CMD_NEW_INTERFACE
,
2793 .validate
= GENL_DONT_VALIDATE_STRICT
| GENL_DONT_VALIDATE_DUMP
,
2794 .doit
= nl802154_new_interface
,
2795 .flags
= GENL_ADMIN_PERM
,
2796 .internal_flags
= NL802154_FLAG_NEED_WPAN_PHY
|
2797 NL802154_FLAG_NEED_RTNL
,
2800 .cmd
= NL802154_CMD_DEL_INTERFACE
,
2801 .validate
= GENL_DONT_VALIDATE_STRICT
| GENL_DONT_VALIDATE_DUMP
,
2802 .doit
= nl802154_del_interface
,
2803 .flags
= GENL_ADMIN_PERM
,
2804 .internal_flags
= NL802154_FLAG_NEED_WPAN_DEV
|
2805 NL802154_FLAG_NEED_RTNL
,
2808 .cmd
= NL802154_CMD_SET_CHANNEL
,
2809 .validate
= GENL_DONT_VALIDATE_STRICT
| GENL_DONT_VALIDATE_DUMP
,
2810 .doit
= nl802154_set_channel
,
2811 .flags
= GENL_ADMIN_PERM
,
2812 .internal_flags
= NL802154_FLAG_NEED_WPAN_PHY
|
2813 NL802154_FLAG_NEED_RTNL
,
2816 .cmd
= NL802154_CMD_SET_CCA_MODE
,
2817 .validate
= GENL_DONT_VALIDATE_STRICT
| GENL_DONT_VALIDATE_DUMP
,
2818 .doit
= nl802154_set_cca_mode
,
2819 .flags
= GENL_ADMIN_PERM
,
2820 .internal_flags
= NL802154_FLAG_NEED_WPAN_PHY
|
2821 NL802154_FLAG_NEED_RTNL
,
2824 .cmd
= NL802154_CMD_SET_CCA_ED_LEVEL
,
2825 .validate
= GENL_DONT_VALIDATE_STRICT
| GENL_DONT_VALIDATE_DUMP
,
2826 .doit
= nl802154_set_cca_ed_level
,
2827 .flags
= GENL_ADMIN_PERM
,
2828 .internal_flags
= NL802154_FLAG_NEED_WPAN_PHY
|
2829 NL802154_FLAG_NEED_RTNL
,
2832 .cmd
= NL802154_CMD_SET_TX_POWER
,
2833 .validate
= GENL_DONT_VALIDATE_STRICT
| GENL_DONT_VALIDATE_DUMP
,
2834 .doit
= nl802154_set_tx_power
,
2835 .flags
= GENL_ADMIN_PERM
,
2836 .internal_flags
= NL802154_FLAG_NEED_WPAN_PHY
|
2837 NL802154_FLAG_NEED_RTNL
,
2840 .cmd
= NL802154_CMD_SET_WPAN_PHY_NETNS
,
2841 .validate
= GENL_DONT_VALIDATE_STRICT
| GENL_DONT_VALIDATE_DUMP
,
2842 .doit
= nl802154_wpan_phy_netns
,
2843 .flags
= GENL_ADMIN_PERM
,
2844 .internal_flags
= NL802154_FLAG_NEED_WPAN_PHY
|
2845 NL802154_FLAG_NEED_RTNL
,
2848 .cmd
= NL802154_CMD_SET_PAN_ID
,
2849 .validate
= GENL_DONT_VALIDATE_STRICT
| GENL_DONT_VALIDATE_DUMP
,
2850 .doit
= nl802154_set_pan_id
,
2851 .flags
= GENL_ADMIN_PERM
,
2852 .internal_flags
= NL802154_FLAG_NEED_NETDEV
|
2853 NL802154_FLAG_NEED_RTNL
,
2856 .cmd
= NL802154_CMD_SET_SHORT_ADDR
,
2857 .validate
= GENL_DONT_VALIDATE_STRICT
| GENL_DONT_VALIDATE_DUMP
,
2858 .doit
= nl802154_set_short_addr
,
2859 .flags
= GENL_ADMIN_PERM
,
2860 .internal_flags
= NL802154_FLAG_NEED_NETDEV
|
2861 NL802154_FLAG_NEED_RTNL
,
2864 .cmd
= NL802154_CMD_SET_BACKOFF_EXPONENT
,
2865 .validate
= GENL_DONT_VALIDATE_STRICT
| GENL_DONT_VALIDATE_DUMP
,
2866 .doit
= nl802154_set_backoff_exponent
,
2867 .flags
= GENL_ADMIN_PERM
,
2868 .internal_flags
= NL802154_FLAG_NEED_NETDEV
|
2869 NL802154_FLAG_NEED_RTNL
,
2872 .cmd
= NL802154_CMD_SET_MAX_CSMA_BACKOFFS
,
2873 .validate
= GENL_DONT_VALIDATE_STRICT
| GENL_DONT_VALIDATE_DUMP
,
2874 .doit
= nl802154_set_max_csma_backoffs
,
2875 .flags
= GENL_ADMIN_PERM
,
2876 .internal_flags
= NL802154_FLAG_NEED_NETDEV
|
2877 NL802154_FLAG_NEED_RTNL
,
2880 .cmd
= NL802154_CMD_SET_MAX_FRAME_RETRIES
,
2881 .validate
= GENL_DONT_VALIDATE_STRICT
| GENL_DONT_VALIDATE_DUMP
,
2882 .doit
= nl802154_set_max_frame_retries
,
2883 .flags
= GENL_ADMIN_PERM
,
2884 .internal_flags
= NL802154_FLAG_NEED_NETDEV
|
2885 NL802154_FLAG_NEED_RTNL
,
2888 .cmd
= NL802154_CMD_SET_LBT_MODE
,
2889 .validate
= GENL_DONT_VALIDATE_STRICT
| GENL_DONT_VALIDATE_DUMP
,
2890 .doit
= nl802154_set_lbt_mode
,
2891 .flags
= GENL_ADMIN_PERM
,
2892 .internal_flags
= NL802154_FLAG_NEED_NETDEV
|
2893 NL802154_FLAG_NEED_RTNL
,
2896 .cmd
= NL802154_CMD_SET_ACKREQ_DEFAULT
,
2897 .validate
= GENL_DONT_VALIDATE_STRICT
| GENL_DONT_VALIDATE_DUMP
,
2898 .doit
= nl802154_set_ackreq_default
,
2899 .flags
= GENL_ADMIN_PERM
,
2900 .internal_flags
= NL802154_FLAG_NEED_NETDEV
|
2901 NL802154_FLAG_NEED_RTNL
,
2904 .cmd
= NL802154_CMD_TRIGGER_SCAN
,
2905 .doit
= nl802154_trigger_scan
,
2906 .flags
= GENL_ADMIN_PERM
,
2907 .internal_flags
= NL802154_FLAG_NEED_NETDEV
|
2908 NL802154_FLAG_CHECK_NETDEV_UP
|
2909 NL802154_FLAG_NEED_RTNL
,
2912 .cmd
= NL802154_CMD_ABORT_SCAN
,
2913 .doit
= nl802154_abort_scan
,
2914 .flags
= GENL_ADMIN_PERM
,
2915 .internal_flags
= NL802154_FLAG_NEED_NETDEV
|
2916 NL802154_FLAG_CHECK_NETDEV_UP
|
2917 NL802154_FLAG_NEED_RTNL
,
2920 .cmd
= NL802154_CMD_SEND_BEACONS
,
2921 .doit
= nl802154_send_beacons
,
2922 .flags
= GENL_ADMIN_PERM
,
2923 .internal_flags
= NL802154_FLAG_NEED_NETDEV
|
2924 NL802154_FLAG_CHECK_NETDEV_UP
|
2925 NL802154_FLAG_NEED_RTNL
,
2928 .cmd
= NL802154_CMD_STOP_BEACONS
,
2929 .doit
= nl802154_stop_beacons
,
2930 .flags
= GENL_ADMIN_PERM
,
2931 .internal_flags
= NL802154_FLAG_NEED_NETDEV
|
2932 NL802154_FLAG_CHECK_NETDEV_UP
|
2933 NL802154_FLAG_NEED_RTNL
,
2936 .cmd
= NL802154_CMD_ASSOCIATE
,
2937 .doit
= nl802154_associate
,
2938 .flags
= GENL_ADMIN_PERM
,
2939 .internal_flags
= NL802154_FLAG_NEED_NETDEV
|
2940 NL802154_FLAG_CHECK_NETDEV_UP
|
2941 NL802154_FLAG_NEED_RTNL
,
2944 .cmd
= NL802154_CMD_DISASSOCIATE
,
2945 .doit
= nl802154_disassociate
,
2946 .flags
= GENL_ADMIN_PERM
,
2947 .internal_flags
= NL802154_FLAG_NEED_NETDEV
|
2948 NL802154_FLAG_CHECK_NETDEV_UP
|
2949 NL802154_FLAG_NEED_RTNL
,
2952 .cmd
= NL802154_CMD_SET_MAX_ASSOCIATIONS
,
2953 .doit
= nl802154_set_max_associations
,
2954 .flags
= GENL_ADMIN_PERM
,
2955 .internal_flags
= NL802154_FLAG_NEED_NETDEV
|
2956 NL802154_FLAG_NEED_RTNL
,
2959 .cmd
= NL802154_CMD_LIST_ASSOCIATIONS
,
2960 .dumpit
= nl802154_list_associations
,
2961 /* can be retrieved by unprivileged users */
2963 #ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL
2965 .cmd
= NL802154_CMD_SET_SEC_PARAMS
,
2966 .validate
= GENL_DONT_VALIDATE_STRICT
| GENL_DONT_VALIDATE_DUMP
,
2967 .doit
= nl802154_set_llsec_params
,
2968 .flags
= GENL_ADMIN_PERM
,
2969 .internal_flags
= NL802154_FLAG_NEED_NETDEV
|
2970 NL802154_FLAG_NEED_RTNL
,
2973 .cmd
= NL802154_CMD_GET_SEC_KEY
,
2974 .validate
= GENL_DONT_VALIDATE_STRICT
|
2975 GENL_DONT_VALIDATE_DUMP_STRICT
,
2976 /* TODO .doit by matching key id? */
2977 .dumpit
= nl802154_dump_llsec_key
,
2978 .flags
= GENL_ADMIN_PERM
,
2979 .internal_flags
= NL802154_FLAG_NEED_NETDEV
|
2980 NL802154_FLAG_NEED_RTNL
,
2983 .cmd
= NL802154_CMD_NEW_SEC_KEY
,
2984 .validate
= GENL_DONT_VALIDATE_STRICT
| GENL_DONT_VALIDATE_DUMP
,
2985 .doit
= nl802154_add_llsec_key
,
2986 .flags
= GENL_ADMIN_PERM
,
2987 .internal_flags
= NL802154_FLAG_NEED_NETDEV
|
2988 NL802154_FLAG_NEED_RTNL
,
2991 .cmd
= NL802154_CMD_DEL_SEC_KEY
,
2992 .validate
= GENL_DONT_VALIDATE_STRICT
| GENL_DONT_VALIDATE_DUMP
,
2993 .doit
= nl802154_del_llsec_key
,
2994 .flags
= GENL_ADMIN_PERM
,
2995 .internal_flags
= NL802154_FLAG_NEED_NETDEV
|
2996 NL802154_FLAG_NEED_RTNL
,
2998 /* TODO unique identifier must short+pan OR extended_addr */
3000 .cmd
= NL802154_CMD_GET_SEC_DEV
,
3001 .validate
= GENL_DONT_VALIDATE_STRICT
|
3002 GENL_DONT_VALIDATE_DUMP_STRICT
,
3003 /* TODO .doit by matching extended_addr? */
3004 .dumpit
= nl802154_dump_llsec_dev
,
3005 .flags
= GENL_ADMIN_PERM
,
3006 .internal_flags
= NL802154_FLAG_NEED_NETDEV
|
3007 NL802154_FLAG_NEED_RTNL
,
3010 .cmd
= NL802154_CMD_NEW_SEC_DEV
,
3011 .validate
= GENL_DONT_VALIDATE_STRICT
| GENL_DONT_VALIDATE_DUMP
,
3012 .doit
= nl802154_add_llsec_dev
,
3013 .flags
= GENL_ADMIN_PERM
,
3014 .internal_flags
= NL802154_FLAG_NEED_NETDEV
|
3015 NL802154_FLAG_NEED_RTNL
,
3018 .cmd
= NL802154_CMD_DEL_SEC_DEV
,
3019 .validate
= GENL_DONT_VALIDATE_STRICT
| GENL_DONT_VALIDATE_DUMP
,
3020 .doit
= nl802154_del_llsec_dev
,
3021 .flags
= GENL_ADMIN_PERM
,
3022 .internal_flags
= NL802154_FLAG_NEED_NETDEV
|
3023 NL802154_FLAG_NEED_RTNL
,
3025 /* TODO remove complete devkey, put it as nested? */
3027 .cmd
= NL802154_CMD_GET_SEC_DEVKEY
,
3028 .validate
= GENL_DONT_VALIDATE_STRICT
|
3029 GENL_DONT_VALIDATE_DUMP_STRICT
,
3030 /* TODO doit by matching ??? */
3031 .dumpit
= nl802154_dump_llsec_devkey
,
3032 .flags
= GENL_ADMIN_PERM
,
3033 .internal_flags
= NL802154_FLAG_NEED_NETDEV
|
3034 NL802154_FLAG_NEED_RTNL
,
3037 .cmd
= NL802154_CMD_NEW_SEC_DEVKEY
,
3038 .validate
= GENL_DONT_VALIDATE_STRICT
| GENL_DONT_VALIDATE_DUMP
,
3039 .doit
= nl802154_add_llsec_devkey
,
3040 .flags
= GENL_ADMIN_PERM
,
3041 .internal_flags
= NL802154_FLAG_NEED_NETDEV
|
3042 NL802154_FLAG_NEED_RTNL
,
3045 .cmd
= NL802154_CMD_DEL_SEC_DEVKEY
,
3046 .validate
= GENL_DONT_VALIDATE_STRICT
| GENL_DONT_VALIDATE_DUMP
,
3047 .doit
= nl802154_del_llsec_devkey
,
3048 .flags
= GENL_ADMIN_PERM
,
3049 .internal_flags
= NL802154_FLAG_NEED_NETDEV
|
3050 NL802154_FLAG_NEED_RTNL
,
3053 .cmd
= NL802154_CMD_GET_SEC_LEVEL
,
3054 .validate
= GENL_DONT_VALIDATE_STRICT
|
3055 GENL_DONT_VALIDATE_DUMP_STRICT
,
3056 /* TODO .doit by matching frame_type? */
3057 .dumpit
= nl802154_dump_llsec_seclevel
,
3058 .flags
= GENL_ADMIN_PERM
,
3059 .internal_flags
= NL802154_FLAG_NEED_NETDEV
|
3060 NL802154_FLAG_NEED_RTNL
,
3063 .cmd
= NL802154_CMD_NEW_SEC_LEVEL
,
3064 .validate
= GENL_DONT_VALIDATE_STRICT
| GENL_DONT_VALIDATE_DUMP
,
3065 .doit
= nl802154_add_llsec_seclevel
,
3066 .flags
= GENL_ADMIN_PERM
,
3067 .internal_flags
= NL802154_FLAG_NEED_NETDEV
|
3068 NL802154_FLAG_NEED_RTNL
,
3071 .cmd
= NL802154_CMD_DEL_SEC_LEVEL
,
3072 .validate
= GENL_DONT_VALIDATE_STRICT
| GENL_DONT_VALIDATE_DUMP
,
3073 /* TODO match frame_type only? */
3074 .doit
= nl802154_del_llsec_seclevel
,
3075 .flags
= GENL_ADMIN_PERM
,
3076 .internal_flags
= NL802154_FLAG_NEED_NETDEV
|
3077 NL802154_FLAG_NEED_RTNL
,
3079 #endif /* CONFIG_IEEE802154_NL802154_EXPERIMENTAL */
3082 static struct genl_family nl802154_fam __ro_after_init
= {
3083 .name
= NL802154_GENL_NAME
, /* have users key off the name instead */
3084 .hdrsize
= 0, /* no private header */
3085 .version
= 1, /* no particular meaning now */
3086 .maxattr
= NL802154_ATTR_MAX
,
3087 .policy
= nl802154_policy
,
3089 .pre_doit
= nl802154_pre_doit
,
3090 .post_doit
= nl802154_post_doit
,
3091 .module
= THIS_MODULE
,
3092 .ops
= nl802154_ops
,
3093 .n_ops
= ARRAY_SIZE(nl802154_ops
),
3094 .resv_start_op
= NL802154_CMD_DEL_SEC_LEVEL
+ 1,
3095 .mcgrps
= nl802154_mcgrps
,
3096 .n_mcgrps
= ARRAY_SIZE(nl802154_mcgrps
),
3099 /* initialisation/exit functions */
3100 int __init
nl802154_init(void)
3102 return genl_register_family(&nl802154_fam
);
3105 void nl802154_exit(void)
3107 genl_unregister_family(&nl802154_fam
);