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.
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.
11 * Alexander Aring <aar@pengutronix.de>
13 * Based on: net/wireless/nl80211.c
16 #include <linux/rtnetlink.h>
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>
29 static int nl802154_pre_doit(const struct genl_ops
*ops
, struct sk_buff
*skb
,
30 struct genl_info
*info
);
32 static void nl802154_post_doit(const struct genl_ops
*ops
, struct sk_buff
*skb
,
33 struct genl_info
*info
);
35 /* the netlink family */
36 static struct genl_family nl802154_fam
= {
37 .id
= GENL_ID_GENERATE
, /* don't bother with a hardcoded ID */
38 .name
= NL802154_GENL_NAME
, /* have users key off the name instead */
39 .hdrsize
= 0, /* no private header */
40 .version
= 1, /* no particular meaning now */
41 .maxattr
= NL802154_ATTR_MAX
,
43 .pre_doit
= nl802154_pre_doit
,
44 .post_doit
= nl802154_post_doit
,
47 /* multicast groups */
48 enum nl802154_multicast_groups
{
49 NL802154_MCGRP_CONFIG
,
52 static const struct genl_multicast_group nl802154_mcgrps
[] = {
53 [NL802154_MCGRP_CONFIG
] = { .name
= "config", },
56 /* returns ERR_PTR values */
57 static struct wpan_dev
*
58 __cfg802154_wpan_dev_from_attrs(struct net
*netns
, struct nlattr
**attrs
)
60 struct cfg802154_registered_device
*rdev
;
61 struct wpan_dev
*result
= NULL
;
62 bool have_ifidx
= attrs
[NL802154_ATTR_IFINDEX
];
63 bool have_wpan_dev_id
= attrs
[NL802154_ATTR_WPAN_DEV
];
65 int wpan_phy_idx
= -1;
70 if (!have_ifidx
&& !have_wpan_dev_id
)
71 return ERR_PTR(-EINVAL
);
74 ifidx
= nla_get_u32(attrs
[NL802154_ATTR_IFINDEX
]);
75 if (have_wpan_dev_id
) {
76 wpan_dev_id
= nla_get_u64(attrs
[NL802154_ATTR_WPAN_DEV
]);
77 wpan_phy_idx
= wpan_dev_id
>> 32;
80 list_for_each_entry(rdev
, &cfg802154_rdev_list
, list
) {
81 struct wpan_dev
*wpan_dev
;
83 if (wpan_phy_net(&rdev
->wpan_phy
) != netns
)
86 if (have_wpan_dev_id
&& rdev
->wpan_phy_idx
!= wpan_phy_idx
)
89 list_for_each_entry(wpan_dev
, &rdev
->wpan_dev_list
, list
) {
90 if (have_ifidx
&& wpan_dev
->netdev
&&
91 wpan_dev
->netdev
->ifindex
== ifidx
) {
95 if (have_wpan_dev_id
&&
96 wpan_dev
->identifier
== (u32
)wpan_dev_id
) {
109 return ERR_PTR(-ENODEV
);
112 static struct cfg802154_registered_device
*
113 __cfg802154_rdev_from_attrs(struct net
*netns
, struct nlattr
**attrs
)
115 struct cfg802154_registered_device
*rdev
= NULL
, *tmp
;
116 struct net_device
*netdev
;
120 if (!attrs
[NL802154_ATTR_WPAN_PHY
] &&
121 !attrs
[NL802154_ATTR_IFINDEX
] &&
122 !attrs
[NL802154_ATTR_WPAN_DEV
])
123 return ERR_PTR(-EINVAL
);
125 if (attrs
[NL802154_ATTR_WPAN_PHY
])
126 rdev
= cfg802154_rdev_by_wpan_phy_idx(
127 nla_get_u32(attrs
[NL802154_ATTR_WPAN_PHY
]));
129 if (attrs
[NL802154_ATTR_WPAN_DEV
]) {
130 u64 wpan_dev_id
= nla_get_u64(attrs
[NL802154_ATTR_WPAN_DEV
]);
131 struct wpan_dev
*wpan_dev
;
134 tmp
= cfg802154_rdev_by_wpan_phy_idx(wpan_dev_id
>> 32);
136 /* make sure wpan_dev exists */
137 list_for_each_entry(wpan_dev
, &tmp
->wpan_dev_list
, list
) {
138 if (wpan_dev
->identifier
!= (u32
)wpan_dev_id
)
147 if (rdev
&& tmp
!= rdev
)
148 return ERR_PTR(-EINVAL
);
153 if (attrs
[NL802154_ATTR_IFINDEX
]) {
154 int ifindex
= nla_get_u32(attrs
[NL802154_ATTR_IFINDEX
]);
156 netdev
= __dev_get_by_index(netns
, ifindex
);
158 if (netdev
->ieee802154_ptr
)
159 tmp
= wpan_phy_to_rdev(
160 netdev
->ieee802154_ptr
->wpan_phy
);
164 /* not wireless device -- return error */
166 return ERR_PTR(-EINVAL
);
168 /* mismatch -- return error */
169 if (rdev
&& tmp
!= rdev
)
170 return ERR_PTR(-EINVAL
);
177 return ERR_PTR(-ENODEV
);
179 if (netns
!= wpan_phy_net(&rdev
->wpan_phy
))
180 return ERR_PTR(-ENODEV
);
185 /* This function returns a pointer to the driver
186 * that the genl_info item that is passed refers to.
188 * The result of this can be a PTR_ERR and hence must
189 * be checked with IS_ERR() for errors.
191 static struct cfg802154_registered_device
*
192 cfg802154_get_dev_from_info(struct net
*netns
, struct genl_info
*info
)
194 return __cfg802154_rdev_from_attrs(netns
, info
->attrs
);
197 /* policy for the attributes */
198 static const struct nla_policy nl802154_policy
[NL802154_ATTR_MAX
+1] = {
199 [NL802154_ATTR_WPAN_PHY
] = { .type
= NLA_U32
},
200 [NL802154_ATTR_WPAN_PHY_NAME
] = { .type
= NLA_NUL_STRING
,
203 [NL802154_ATTR_IFINDEX
] = { .type
= NLA_U32
},
204 [NL802154_ATTR_IFTYPE
] = { .type
= NLA_U32
},
205 [NL802154_ATTR_IFNAME
] = { .type
= NLA_NUL_STRING
, .len
= IFNAMSIZ
-1 },
207 [NL802154_ATTR_WPAN_DEV
] = { .type
= NLA_U64
},
209 [NL802154_ATTR_PAGE
] = { .type
= NLA_U8
, },
210 [NL802154_ATTR_CHANNEL
] = { .type
= NLA_U8
, },
212 [NL802154_ATTR_TX_POWER
] = { .type
= NLA_S32
, },
214 [NL802154_ATTR_CCA_MODE
] = { .type
= NLA_U32
, },
215 [NL802154_ATTR_CCA_OPT
] = { .type
= NLA_U32
, },
216 [NL802154_ATTR_CCA_ED_LEVEL
] = { .type
= NLA_S32
, },
218 [NL802154_ATTR_SUPPORTED_CHANNEL
] = { .type
= NLA_U32
, },
220 [NL802154_ATTR_PAN_ID
] = { .type
= NLA_U16
, },
221 [NL802154_ATTR_EXTENDED_ADDR
] = { .type
= NLA_U64
},
222 [NL802154_ATTR_SHORT_ADDR
] = { .type
= NLA_U16
, },
224 [NL802154_ATTR_MIN_BE
] = { .type
= NLA_U8
, },
225 [NL802154_ATTR_MAX_BE
] = { .type
= NLA_U8
, },
226 [NL802154_ATTR_MAX_CSMA_BACKOFFS
] = { .type
= NLA_U8
, },
228 [NL802154_ATTR_MAX_FRAME_RETRIES
] = { .type
= NLA_S8
, },
230 [NL802154_ATTR_LBT_MODE
] = { .type
= NLA_U8
, },
232 [NL802154_ATTR_WPAN_PHY_CAPS
] = { .type
= NLA_NESTED
},
234 [NL802154_ATTR_SUPPORTED_COMMANDS
] = { .type
= NLA_NESTED
},
236 [NL802154_ATTR_ACKREQ_DEFAULT
] = { .type
= NLA_U8
},
238 [NL802154_ATTR_PID
] = { .type
= NLA_U32
},
239 [NL802154_ATTR_NETNS_FD
] = { .type
= NLA_U32
},
240 #ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL
241 [NL802154_ATTR_SEC_ENABLED
] = { .type
= NLA_U8
, },
242 [NL802154_ATTR_SEC_OUT_LEVEL
] = { .type
= NLA_U32
, },
243 [NL802154_ATTR_SEC_OUT_KEY_ID
] = { .type
= NLA_NESTED
, },
244 [NL802154_ATTR_SEC_FRAME_COUNTER
] = { .type
= NLA_U32
},
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 */
253 #ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL
255 nl802154_prepare_wpan_dev_dump(struct sk_buff
*skb
,
256 struct netlink_callback
*cb
,
257 struct cfg802154_registered_device
**rdev
,
258 struct wpan_dev
**wpan_dev
)
265 err
= nlmsg_parse(cb
->nlh
, GENL_HDRLEN
+ nl802154_fam
.hdrsize
,
266 nl802154_fam
.attrbuf
, nl802154_fam
.maxattr
,
271 *wpan_dev
= __cfg802154_wpan_dev_from_attrs(sock_net(skb
->sk
),
272 nl802154_fam
.attrbuf
);
273 if (IS_ERR(*wpan_dev
)) {
274 err
= PTR_ERR(*wpan_dev
);
277 *rdev
= wpan_phy_to_rdev((*wpan_dev
)->wpan_phy
);
278 /* 0 is the first index - add 1 to parse only once */
279 cb
->args
[0] = (*rdev
)->wpan_phy_idx
+ 1;
280 cb
->args
[1] = (*wpan_dev
)->identifier
;
282 /* subtract the 1 again here */
283 struct wpan_phy
*wpan_phy
= wpan_phy_idx_to_wpan_phy(cb
->args
[0] - 1);
284 struct wpan_dev
*tmp
;
290 *rdev
= wpan_phy_to_rdev(wpan_phy
);
293 list_for_each_entry(tmp
, &(*rdev
)->wpan_dev_list
, list
) {
294 if (tmp
->identifier
== cb
->args
[1]) {
313 nl802154_finish_wpan_dev_dump(struct cfg802154_registered_device
*rdev
)
317 #endif /* CONFIG_IEEE802154_NL802154_EXPERIMENTAL */
319 /* message building helper */
320 static inline void *nl802154hdr_put(struct sk_buff
*skb
, u32 portid
, u32 seq
,
323 /* since there is no private header just add the generic one */
324 return genlmsg_put(skb
, portid
, seq
, &nl802154_fam
, flags
, cmd
);
328 nl802154_put_flags(struct sk_buff
*msg
, int attr
, u32 mask
)
330 struct nlattr
*nl_flags
= nla_nest_start(msg
, attr
);
338 if ((mask
& 1) && nla_put_flag(msg
, i
))
345 nla_nest_end(msg
, nl_flags
);
350 nl802154_send_wpan_phy_channels(struct cfg802154_registered_device
*rdev
,
353 struct nlattr
*nl_page
;
356 nl_page
= nla_nest_start(msg
, NL802154_ATTR_CHANNELS_SUPPORTED
);
360 for (page
= 0; page
<= IEEE802154_MAX_PAGE
; page
++) {
361 if (nla_put_u32(msg
, NL802154_ATTR_SUPPORTED_CHANNEL
,
362 rdev
->wpan_phy
.supported
.channels
[page
]))
365 nla_nest_end(msg
, nl_page
);
371 nl802154_put_capabilities(struct sk_buff
*msg
,
372 struct cfg802154_registered_device
*rdev
)
374 const struct wpan_phy_supported
*caps
= &rdev
->wpan_phy
.supported
;
375 struct nlattr
*nl_caps
, *nl_channels
;
378 nl_caps
= nla_nest_start(msg
, NL802154_ATTR_WPAN_PHY_CAPS
);
382 nl_channels
= nla_nest_start(msg
, NL802154_CAP_ATTR_CHANNELS
);
386 for (i
= 0; i
<= IEEE802154_MAX_PAGE
; i
++) {
387 if (caps
->channels
[i
]) {
388 if (nl802154_put_flags(msg
, i
, caps
->channels
[i
]))
393 nla_nest_end(msg
, nl_channels
);
395 if (rdev
->wpan_phy
.flags
& WPAN_PHY_FLAG_CCA_ED_LEVEL
) {
396 struct nlattr
*nl_ed_lvls
;
398 nl_ed_lvls
= nla_nest_start(msg
,
399 NL802154_CAP_ATTR_CCA_ED_LEVELS
);
403 for (i
= 0; i
< caps
->cca_ed_levels_size
; i
++) {
404 if (nla_put_s32(msg
, i
, caps
->cca_ed_levels
[i
]))
408 nla_nest_end(msg
, nl_ed_lvls
);
411 if (rdev
->wpan_phy
.flags
& WPAN_PHY_FLAG_TXPOWER
) {
412 struct nlattr
*nl_tx_pwrs
;
414 nl_tx_pwrs
= nla_nest_start(msg
, NL802154_CAP_ATTR_TX_POWERS
);
418 for (i
= 0; i
< caps
->tx_powers_size
; i
++) {
419 if (nla_put_s32(msg
, i
, caps
->tx_powers
[i
]))
423 nla_nest_end(msg
, nl_tx_pwrs
);
426 if (rdev
->wpan_phy
.flags
& WPAN_PHY_FLAG_CCA_MODE
) {
427 if (nl802154_put_flags(msg
, NL802154_CAP_ATTR_CCA_MODES
,
429 nl802154_put_flags(msg
, NL802154_CAP_ATTR_CCA_OPTS
,
434 if (nla_put_u8(msg
, NL802154_CAP_ATTR_MIN_MINBE
, caps
->min_minbe
) ||
435 nla_put_u8(msg
, NL802154_CAP_ATTR_MAX_MINBE
, caps
->max_minbe
) ||
436 nla_put_u8(msg
, NL802154_CAP_ATTR_MIN_MAXBE
, caps
->min_maxbe
) ||
437 nla_put_u8(msg
, NL802154_CAP_ATTR_MAX_MAXBE
, caps
->max_maxbe
) ||
438 nla_put_u8(msg
, NL802154_CAP_ATTR_MIN_CSMA_BACKOFFS
,
439 caps
->min_csma_backoffs
) ||
440 nla_put_u8(msg
, NL802154_CAP_ATTR_MAX_CSMA_BACKOFFS
,
441 caps
->max_csma_backoffs
) ||
442 nla_put_s8(msg
, NL802154_CAP_ATTR_MIN_FRAME_RETRIES
,
443 caps
->min_frame_retries
) ||
444 nla_put_s8(msg
, NL802154_CAP_ATTR_MAX_FRAME_RETRIES
,
445 caps
->max_frame_retries
) ||
446 nl802154_put_flags(msg
, NL802154_CAP_ATTR_IFTYPES
,
448 nla_put_u32(msg
, NL802154_CAP_ATTR_LBT
, caps
->lbt
))
451 nla_nest_end(msg
, nl_caps
);
456 static int nl802154_send_wpan_phy(struct cfg802154_registered_device
*rdev
,
457 enum nl802154_commands cmd
,
458 struct sk_buff
*msg
, u32 portid
, u32 seq
,
461 struct nlattr
*nl_cmds
;
465 hdr
= nl802154hdr_put(msg
, portid
, seq
, flags
, cmd
);
469 if (nla_put_u32(msg
, NL802154_ATTR_WPAN_PHY
, rdev
->wpan_phy_idx
) ||
470 nla_put_string(msg
, NL802154_ATTR_WPAN_PHY_NAME
,
471 wpan_phy_name(&rdev
->wpan_phy
)) ||
472 nla_put_u32(msg
, NL802154_ATTR_GENERATION
,
473 cfg802154_rdev_list_generation
))
474 goto nla_put_failure
;
476 if (cmd
!= NL802154_CMD_NEW_WPAN_PHY
)
481 /* current channel settings */
482 if (nla_put_u8(msg
, NL802154_ATTR_PAGE
,
483 rdev
->wpan_phy
.current_page
) ||
484 nla_put_u8(msg
, NL802154_ATTR_CHANNEL
,
485 rdev
->wpan_phy
.current_channel
))
486 goto nla_put_failure
;
488 /* TODO remove this behaviour, we still keep support it for a while
489 * so users can change the behaviour to the new one.
491 if (nl802154_send_wpan_phy_channels(rdev
, msg
))
492 goto nla_put_failure
;
495 if (rdev
->wpan_phy
.flags
& WPAN_PHY_FLAG_CCA_MODE
) {
496 if (nla_put_u32(msg
, NL802154_ATTR_CCA_MODE
,
497 rdev
->wpan_phy
.cca
.mode
))
498 goto nla_put_failure
;
500 if (rdev
->wpan_phy
.cca
.mode
== NL802154_CCA_ENERGY_CARRIER
) {
501 if (nla_put_u32(msg
, NL802154_ATTR_CCA_OPT
,
502 rdev
->wpan_phy
.cca
.opt
))
503 goto nla_put_failure
;
507 if (rdev
->wpan_phy
.flags
& WPAN_PHY_FLAG_TXPOWER
) {
508 if (nla_put_s32(msg
, NL802154_ATTR_TX_POWER
,
509 rdev
->wpan_phy
.transmit_power
))
510 goto nla_put_failure
;
513 if (rdev
->wpan_phy
.flags
& WPAN_PHY_FLAG_CCA_ED_LEVEL
) {
514 if (nla_put_s32(msg
, NL802154_ATTR_CCA_ED_LEVEL
,
515 rdev
->wpan_phy
.cca_ed_level
))
516 goto nla_put_failure
;
519 if (nl802154_put_capabilities(msg
, rdev
))
520 goto nla_put_failure
;
522 nl_cmds
= nla_nest_start(msg
, NL802154_ATTR_SUPPORTED_COMMANDS
);
524 goto nla_put_failure
;
529 if (rdev->ops->op) { \
531 if (nla_put_u32(msg, i, NL802154_CMD_ ## n)) \
532 goto nla_put_failure; \
536 CMD(add_virtual_intf
, NEW_INTERFACE
);
537 CMD(del_virtual_intf
, DEL_INTERFACE
);
538 CMD(set_channel
, SET_CHANNEL
);
539 CMD(set_pan_id
, SET_PAN_ID
);
540 CMD(set_short_addr
, SET_SHORT_ADDR
);
541 CMD(set_backoff_exponent
, SET_BACKOFF_EXPONENT
);
542 CMD(set_max_csma_backoffs
, SET_MAX_CSMA_BACKOFFS
);
543 CMD(set_max_frame_retries
, SET_MAX_FRAME_RETRIES
);
544 CMD(set_lbt_mode
, SET_LBT_MODE
);
545 CMD(set_ackreq_default
, SET_ACKREQ_DEFAULT
);
547 if (rdev
->wpan_phy
.flags
& WPAN_PHY_FLAG_TXPOWER
)
548 CMD(set_tx_power
, SET_TX_POWER
);
550 if (rdev
->wpan_phy
.flags
& WPAN_PHY_FLAG_CCA_ED_LEVEL
)
551 CMD(set_cca_ed_level
, SET_CCA_ED_LEVEL
);
553 if (rdev
->wpan_phy
.flags
& WPAN_PHY_FLAG_CCA_MODE
)
554 CMD(set_cca_mode
, SET_CCA_MODE
);
557 nla_nest_end(msg
, nl_cmds
);
560 genlmsg_end(msg
, hdr
);
564 genlmsg_cancel(msg
, hdr
);
568 struct nl802154_dump_wpan_phy_state
{
574 static int nl802154_dump_wpan_phy_parse(struct sk_buff
*skb
,
575 struct netlink_callback
*cb
,
576 struct nl802154_dump_wpan_phy_state
*state
)
578 struct nlattr
**tb
= nl802154_fam
.attrbuf
;
579 int ret
= nlmsg_parse(cb
->nlh
, GENL_HDRLEN
+ nl802154_fam
.hdrsize
,
580 tb
, nl802154_fam
.maxattr
, nl802154_policy
);
582 /* TODO check if we can handle error here,
583 * we have no backward compatibility
588 if (tb
[NL802154_ATTR_WPAN_PHY
])
589 state
->filter_wpan_phy
= nla_get_u32(tb
[NL802154_ATTR_WPAN_PHY
]);
590 if (tb
[NL802154_ATTR_WPAN_DEV
])
591 state
->filter_wpan_phy
= nla_get_u64(tb
[NL802154_ATTR_WPAN_DEV
]) >> 32;
592 if (tb
[NL802154_ATTR_IFINDEX
]) {
593 struct net_device
*netdev
;
594 struct cfg802154_registered_device
*rdev
;
595 int ifidx
= nla_get_u32(tb
[NL802154_ATTR_IFINDEX
]);
597 netdev
= __dev_get_by_index(&init_net
, ifidx
);
600 if (netdev
->ieee802154_ptr
) {
601 rdev
= wpan_phy_to_rdev(
602 netdev
->ieee802154_ptr
->wpan_phy
);
603 state
->filter_wpan_phy
= rdev
->wpan_phy_idx
;
611 nl802154_dump_wpan_phy(struct sk_buff
*skb
, struct netlink_callback
*cb
)
614 struct nl802154_dump_wpan_phy_state
*state
= (void *)cb
->args
[0];
615 struct cfg802154_registered_device
*rdev
;
619 state
= kzalloc(sizeof(*state
), GFP_KERNEL
);
624 state
->filter_wpan_phy
= -1;
625 ret
= nl802154_dump_wpan_phy_parse(skb
, cb
, state
);
631 cb
->args
[0] = (long)state
;
634 list_for_each_entry(rdev
, &cfg802154_rdev_list
, list
) {
635 if (!net_eq(wpan_phy_net(&rdev
->wpan_phy
), sock_net(skb
->sk
)))
637 if (++idx
<= state
->start
)
639 if (state
->filter_wpan_phy
!= -1 &&
640 state
->filter_wpan_phy
!= rdev
->wpan_phy_idx
)
642 /* attempt to fit multiple wpan_phy data chunks into the skb */
643 ret
= nl802154_send_wpan_phy(rdev
,
644 NL802154_CMD_NEW_WPAN_PHY
,
646 NETLINK_CB(cb
->skb
).portid
,
647 cb
->nlh
->nlmsg_seq
, NLM_F_MULTI
);
649 if ((ret
== -ENOBUFS
|| ret
== -EMSGSIZE
) &&
650 !skb
->len
&& cb
->min_dump_alloc
< 4096) {
651 cb
->min_dump_alloc
= 4096;
667 static int nl802154_dump_wpan_phy_done(struct netlink_callback
*cb
)
669 kfree((void *)cb
->args
[0]);
673 static int nl802154_get_wpan_phy(struct sk_buff
*skb
, struct genl_info
*info
)
676 struct cfg802154_registered_device
*rdev
= info
->user_ptr
[0];
678 msg
= nlmsg_new(NLMSG_DEFAULT_SIZE
, GFP_KERNEL
);
682 if (nl802154_send_wpan_phy(rdev
, NL802154_CMD_NEW_WPAN_PHY
, msg
,
683 info
->snd_portid
, info
->snd_seq
, 0) < 0) {
688 return genlmsg_reply(msg
, info
);
691 static inline u64
wpan_dev_id(struct wpan_dev
*wpan_dev
)
693 return (u64
)wpan_dev
->identifier
|
694 ((u64
)wpan_phy_to_rdev(wpan_dev
->wpan_phy
)->wpan_phy_idx
<< 32);
697 #ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL
698 #include <net/ieee802154_netdev.h>
701 ieee802154_llsec_send_key_id(struct sk_buff
*msg
,
702 const struct ieee802154_llsec_key_id
*desc
)
704 struct nlattr
*nl_dev_addr
;
706 if (nla_put_u32(msg
, NL802154_KEY_ID_ATTR_MODE
, desc
->mode
))
709 switch (desc
->mode
) {
710 case NL802154_KEY_ID_MODE_IMPLICIT
:
711 nl_dev_addr
= nla_nest_start(msg
, NL802154_KEY_ID_ATTR_IMPLICIT
);
715 if (nla_put_le16(msg
, NL802154_DEV_ADDR_ATTR_PAN_ID
,
716 desc
->device_addr
.pan_id
) ||
717 nla_put_u32(msg
, NL802154_DEV_ADDR_ATTR_MODE
,
718 desc
->device_addr
.mode
))
721 switch (desc
->device_addr
.mode
) {
722 case NL802154_DEV_ADDR_SHORT
:
723 if (nla_put_le16(msg
, NL802154_DEV_ADDR_ATTR_SHORT
,
724 desc
->device_addr
.short_addr
))
727 case NL802154_DEV_ADDR_EXTENDED
:
728 if (nla_put_le64(msg
, NL802154_DEV_ADDR_ATTR_EXTENDED
,
729 desc
->device_addr
.extended_addr
,
730 NL802154_DEV_ADDR_ATTR_PAD
))
734 /* userspace should handle unknown */
738 nla_nest_end(msg
, nl_dev_addr
);
740 case NL802154_KEY_ID_MODE_INDEX
:
742 case NL802154_KEY_ID_MODE_INDEX_SHORT
:
743 /* TODO renmae short_source? */
744 if (nla_put_le32(msg
, NL802154_KEY_ID_ATTR_SOURCE_SHORT
,
748 case NL802154_KEY_ID_MODE_INDEX_EXTENDED
:
749 if (nla_put_le64(msg
, NL802154_KEY_ID_ATTR_SOURCE_EXTENDED
,
750 desc
->extended_source
,
751 NL802154_KEY_ID_ATTR_PAD
))
755 /* userspace should handle unknown */
759 /* TODO key_id to key_idx ? Check naming */
760 if (desc
->mode
!= NL802154_KEY_ID_MODE_IMPLICIT
) {
761 if (nla_put_u8(msg
, NL802154_KEY_ID_ATTR_INDEX
, desc
->id
))
768 static int nl802154_get_llsec_params(struct sk_buff
*msg
,
769 struct cfg802154_registered_device
*rdev
,
770 struct wpan_dev
*wpan_dev
)
772 struct nlattr
*nl_key_id
;
773 struct ieee802154_llsec_params params
;
776 ret
= rdev_get_llsec_params(rdev
, wpan_dev
, ¶ms
);
780 if (nla_put_u8(msg
, NL802154_ATTR_SEC_ENABLED
, params
.enabled
) ||
781 nla_put_u32(msg
, NL802154_ATTR_SEC_OUT_LEVEL
, params
.out_level
) ||
782 nla_put_be32(msg
, NL802154_ATTR_SEC_FRAME_COUNTER
,
783 params
.frame_counter
))
786 nl_key_id
= nla_nest_start(msg
, NL802154_ATTR_SEC_OUT_KEY_ID
);
790 ret
= ieee802154_llsec_send_key_id(msg
, ¶ms
.out_key
);
794 nla_nest_end(msg
, nl_key_id
);
798 #endif /* CONFIG_IEEE802154_NL802154_EXPERIMENTAL */
801 nl802154_send_iface(struct sk_buff
*msg
, u32 portid
, u32 seq
, int flags
,
802 struct cfg802154_registered_device
*rdev
,
803 struct wpan_dev
*wpan_dev
)
805 struct net_device
*dev
= wpan_dev
->netdev
;
808 hdr
= nl802154hdr_put(msg
, portid
, seq
, flags
,
809 NL802154_CMD_NEW_INTERFACE
);
814 (nla_put_u32(msg
, NL802154_ATTR_IFINDEX
, dev
->ifindex
) ||
815 nla_put_string(msg
, NL802154_ATTR_IFNAME
, dev
->name
)))
816 goto nla_put_failure
;
818 if (nla_put_u32(msg
, NL802154_ATTR_WPAN_PHY
, rdev
->wpan_phy_idx
) ||
819 nla_put_u32(msg
, NL802154_ATTR_IFTYPE
, wpan_dev
->iftype
) ||
820 nla_put_u64_64bit(msg
, NL802154_ATTR_WPAN_DEV
,
821 wpan_dev_id(wpan_dev
), NL802154_ATTR_PAD
) ||
822 nla_put_u32(msg
, NL802154_ATTR_GENERATION
,
823 rdev
->devlist_generation
^
824 (cfg802154_rdev_list_generation
<< 2)))
825 goto nla_put_failure
;
827 /* address settings */
828 if (nla_put_le64(msg
, NL802154_ATTR_EXTENDED_ADDR
,
829 wpan_dev
->extended_addr
,
830 NL802154_ATTR_PAD
) ||
831 nla_put_le16(msg
, NL802154_ATTR_SHORT_ADDR
,
832 wpan_dev
->short_addr
) ||
833 nla_put_le16(msg
, NL802154_ATTR_PAN_ID
, wpan_dev
->pan_id
))
834 goto nla_put_failure
;
837 if (nla_put_s8(msg
, NL802154_ATTR_MAX_FRAME_RETRIES
,
838 wpan_dev
->frame_retries
) ||
839 nla_put_u8(msg
, NL802154_ATTR_MAX_BE
, wpan_dev
->max_be
) ||
840 nla_put_u8(msg
, NL802154_ATTR_MAX_CSMA_BACKOFFS
,
841 wpan_dev
->csma_retries
) ||
842 nla_put_u8(msg
, NL802154_ATTR_MIN_BE
, wpan_dev
->min_be
))
843 goto nla_put_failure
;
845 /* listen before transmit */
846 if (nla_put_u8(msg
, NL802154_ATTR_LBT_MODE
, wpan_dev
->lbt
))
847 goto nla_put_failure
;
849 /* ackreq default behaviour */
850 if (nla_put_u8(msg
, NL802154_ATTR_ACKREQ_DEFAULT
, wpan_dev
->ackreq
))
851 goto nla_put_failure
;
853 #ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL
854 if (nl802154_get_llsec_params(msg
, rdev
, wpan_dev
) < 0)
855 goto nla_put_failure
;
856 #endif /* CONFIG_IEEE802154_NL802154_EXPERIMENTAL */
858 genlmsg_end(msg
, hdr
);
862 genlmsg_cancel(msg
, hdr
);
867 nl802154_dump_interface(struct sk_buff
*skb
, struct netlink_callback
*cb
)
871 int wp_start
= cb
->args
[0];
872 int if_start
= cb
->args
[1];
873 struct cfg802154_registered_device
*rdev
;
874 struct wpan_dev
*wpan_dev
;
877 list_for_each_entry(rdev
, &cfg802154_rdev_list
, list
) {
878 if (!net_eq(wpan_phy_net(&rdev
->wpan_phy
), sock_net(skb
->sk
)))
880 if (wp_idx
< wp_start
) {
886 list_for_each_entry(wpan_dev
, &rdev
->wpan_dev_list
, list
) {
887 if (if_idx
< if_start
) {
891 if (nl802154_send_iface(skb
, NETLINK_CB(cb
->skb
).portid
,
892 cb
->nlh
->nlmsg_seq
, NLM_F_MULTI
,
893 rdev
, wpan_dev
) < 0) {
904 cb
->args
[0] = wp_idx
;
905 cb
->args
[1] = if_idx
;
910 static int nl802154_get_interface(struct sk_buff
*skb
, struct genl_info
*info
)
913 struct cfg802154_registered_device
*rdev
= info
->user_ptr
[0];
914 struct wpan_dev
*wdev
= info
->user_ptr
[1];
916 msg
= nlmsg_new(NLMSG_DEFAULT_SIZE
, GFP_KERNEL
);
920 if (nl802154_send_iface(msg
, info
->snd_portid
, info
->snd_seq
, 0,
926 return genlmsg_reply(msg
, info
);
929 static int nl802154_new_interface(struct sk_buff
*skb
, struct genl_info
*info
)
931 struct cfg802154_registered_device
*rdev
= info
->user_ptr
[0];
932 enum nl802154_iftype type
= NL802154_IFTYPE_UNSPEC
;
933 __le64 extended_addr
= cpu_to_le64(0x0000000000000000ULL
);
935 /* TODO avoid failing a new interface
936 * creation due to pending removal?
939 if (!info
->attrs
[NL802154_ATTR_IFNAME
])
942 if (info
->attrs
[NL802154_ATTR_IFTYPE
]) {
943 type
= nla_get_u32(info
->attrs
[NL802154_ATTR_IFTYPE
]);
944 if (type
> NL802154_IFTYPE_MAX
||
945 !(rdev
->wpan_phy
.supported
.iftypes
& BIT(type
)))
949 if (info
->attrs
[NL802154_ATTR_EXTENDED_ADDR
])
950 extended_addr
= nla_get_le64(info
->attrs
[NL802154_ATTR_EXTENDED_ADDR
]);
952 if (!rdev
->ops
->add_virtual_intf
)
955 return rdev_add_virtual_intf(rdev
,
956 nla_data(info
->attrs
[NL802154_ATTR_IFNAME
]),
957 NET_NAME_USER
, type
, extended_addr
);
960 static int nl802154_del_interface(struct sk_buff
*skb
, struct genl_info
*info
)
962 struct cfg802154_registered_device
*rdev
= info
->user_ptr
[0];
963 struct wpan_dev
*wpan_dev
= info
->user_ptr
[1];
965 if (!rdev
->ops
->del_virtual_intf
)
968 /* If we remove a wpan device without a netdev then clear
969 * user_ptr[1] so that nl802154_post_doit won't dereference it
970 * to check if it needs to do dev_put(). Otherwise it crashes
971 * since the wpan_dev has been freed, unlike with a netdev where
972 * we need the dev_put() for the netdev to really be freed.
974 if (!wpan_dev
->netdev
)
975 info
->user_ptr
[1] = NULL
;
977 return rdev_del_virtual_intf(rdev
, wpan_dev
);
980 static int nl802154_set_channel(struct sk_buff
*skb
, struct genl_info
*info
)
982 struct cfg802154_registered_device
*rdev
= info
->user_ptr
[0];
985 if (!info
->attrs
[NL802154_ATTR_PAGE
] ||
986 !info
->attrs
[NL802154_ATTR_CHANNEL
])
989 page
= nla_get_u8(info
->attrs
[NL802154_ATTR_PAGE
]);
990 channel
= nla_get_u8(info
->attrs
[NL802154_ATTR_CHANNEL
]);
992 /* check 802.15.4 constraints */
993 if (page
> IEEE802154_MAX_PAGE
|| channel
> IEEE802154_MAX_CHANNEL
||
994 !(rdev
->wpan_phy
.supported
.channels
[page
] & BIT(channel
)))
997 return rdev_set_channel(rdev
, page
, channel
);
1000 static int nl802154_set_cca_mode(struct sk_buff
*skb
, struct genl_info
*info
)
1002 struct cfg802154_registered_device
*rdev
= info
->user_ptr
[0];
1003 struct wpan_phy_cca cca
;
1005 if (!(rdev
->wpan_phy
.flags
& WPAN_PHY_FLAG_CCA_MODE
))
1008 if (!info
->attrs
[NL802154_ATTR_CCA_MODE
])
1011 cca
.mode
= nla_get_u32(info
->attrs
[NL802154_ATTR_CCA_MODE
]);
1012 /* checking 802.15.4 constraints */
1013 if (cca
.mode
< NL802154_CCA_ENERGY
||
1014 cca
.mode
> NL802154_CCA_ATTR_MAX
||
1015 !(rdev
->wpan_phy
.supported
.cca_modes
& BIT(cca
.mode
)))
1018 if (cca
.mode
== NL802154_CCA_ENERGY_CARRIER
) {
1019 if (!info
->attrs
[NL802154_ATTR_CCA_OPT
])
1022 cca
.opt
= nla_get_u32(info
->attrs
[NL802154_ATTR_CCA_OPT
]);
1023 if (cca
.opt
> NL802154_CCA_OPT_ATTR_MAX
||
1024 !(rdev
->wpan_phy
.supported
.cca_opts
& BIT(cca
.opt
)))
1028 return rdev_set_cca_mode(rdev
, &cca
);
1031 static int nl802154_set_cca_ed_level(struct sk_buff
*skb
, struct genl_info
*info
)
1033 struct cfg802154_registered_device
*rdev
= info
->user_ptr
[0];
1037 if (!(rdev
->wpan_phy
.flags
& WPAN_PHY_FLAG_CCA_ED_LEVEL
))
1040 if (!info
->attrs
[NL802154_ATTR_CCA_ED_LEVEL
])
1043 ed_level
= nla_get_s32(info
->attrs
[NL802154_ATTR_CCA_ED_LEVEL
]);
1045 for (i
= 0; i
< rdev
->wpan_phy
.supported
.cca_ed_levels_size
; i
++) {
1046 if (ed_level
== rdev
->wpan_phy
.supported
.cca_ed_levels
[i
])
1047 return rdev_set_cca_ed_level(rdev
, ed_level
);
1053 static int nl802154_set_tx_power(struct sk_buff
*skb
, struct genl_info
*info
)
1055 struct cfg802154_registered_device
*rdev
= info
->user_ptr
[0];
1059 if (!(rdev
->wpan_phy
.flags
& WPAN_PHY_FLAG_TXPOWER
))
1062 if (!info
->attrs
[NL802154_ATTR_TX_POWER
])
1065 power
= nla_get_s32(info
->attrs
[NL802154_ATTR_TX_POWER
]);
1067 for (i
= 0; i
< rdev
->wpan_phy
.supported
.tx_powers_size
; i
++) {
1068 if (power
== rdev
->wpan_phy
.supported
.tx_powers
[i
])
1069 return rdev_set_tx_power(rdev
, power
);
1075 static int nl802154_set_pan_id(struct sk_buff
*skb
, struct genl_info
*info
)
1077 struct cfg802154_registered_device
*rdev
= info
->user_ptr
[0];
1078 struct net_device
*dev
= info
->user_ptr
[1];
1079 struct wpan_dev
*wpan_dev
= dev
->ieee802154_ptr
;
1082 /* conflict here while tx/rx calls */
1083 if (netif_running(dev
))
1086 if (wpan_dev
->lowpan_dev
) {
1087 if (netif_running(wpan_dev
->lowpan_dev
))
1091 /* don't change address fields on monitor */
1092 if (wpan_dev
->iftype
== NL802154_IFTYPE_MONITOR
||
1093 !info
->attrs
[NL802154_ATTR_PAN_ID
])
1096 pan_id
= nla_get_le16(info
->attrs
[NL802154_ATTR_PAN_ID
]);
1099 * I am not sure about to check here on broadcast pan_id.
1100 * Broadcast is a valid setting, comment from 802.15.4:
1101 * If this value is 0xffff, the device is not associated.
1103 * This could useful to simple deassociate an device.
1105 if (pan_id
== cpu_to_le16(IEEE802154_PAN_ID_BROADCAST
))
1108 return rdev_set_pan_id(rdev
, wpan_dev
, pan_id
);
1111 static int nl802154_set_short_addr(struct sk_buff
*skb
, struct genl_info
*info
)
1113 struct cfg802154_registered_device
*rdev
= info
->user_ptr
[0];
1114 struct net_device
*dev
= info
->user_ptr
[1];
1115 struct wpan_dev
*wpan_dev
= dev
->ieee802154_ptr
;
1118 /* conflict here while tx/rx calls */
1119 if (netif_running(dev
))
1122 if (wpan_dev
->lowpan_dev
) {
1123 if (netif_running(wpan_dev
->lowpan_dev
))
1127 /* don't change address fields on monitor */
1128 if (wpan_dev
->iftype
== NL802154_IFTYPE_MONITOR
||
1129 !info
->attrs
[NL802154_ATTR_SHORT_ADDR
])
1132 short_addr
= nla_get_le16(info
->attrs
[NL802154_ATTR_SHORT_ADDR
]);
1135 * I am not sure about to check here on broadcast short_addr.
1136 * Broadcast is a valid setting, comment from 802.15.4:
1137 * A value of 0xfffe indicates that the device has
1138 * associated but has not been allocated an address. A
1139 * value of 0xffff indicates that the device does not
1140 * have a short address.
1142 * I think we should allow to set these settings but
1143 * don't allow to allow socket communication with it.
1145 if (short_addr
== cpu_to_le16(IEEE802154_ADDR_SHORT_UNSPEC
) ||
1146 short_addr
== cpu_to_le16(IEEE802154_ADDR_SHORT_BROADCAST
))
1149 return rdev_set_short_addr(rdev
, wpan_dev
, short_addr
);
1153 nl802154_set_backoff_exponent(struct sk_buff
*skb
, struct genl_info
*info
)
1155 struct cfg802154_registered_device
*rdev
= info
->user_ptr
[0];
1156 struct net_device
*dev
= info
->user_ptr
[1];
1157 struct wpan_dev
*wpan_dev
= dev
->ieee802154_ptr
;
1160 /* should be set on netif open inside phy settings */
1161 if (netif_running(dev
))
1164 if (!info
->attrs
[NL802154_ATTR_MIN_BE
] ||
1165 !info
->attrs
[NL802154_ATTR_MAX_BE
])
1168 min_be
= nla_get_u8(info
->attrs
[NL802154_ATTR_MIN_BE
]);
1169 max_be
= nla_get_u8(info
->attrs
[NL802154_ATTR_MAX_BE
]);
1171 /* check 802.15.4 constraints */
1172 if (min_be
< rdev
->wpan_phy
.supported
.min_minbe
||
1173 min_be
> rdev
->wpan_phy
.supported
.max_minbe
||
1174 max_be
< rdev
->wpan_phy
.supported
.min_maxbe
||
1175 max_be
> rdev
->wpan_phy
.supported
.max_maxbe
||
1179 return rdev_set_backoff_exponent(rdev
, wpan_dev
, min_be
, max_be
);
1183 nl802154_set_max_csma_backoffs(struct sk_buff
*skb
, struct genl_info
*info
)
1185 struct cfg802154_registered_device
*rdev
= info
->user_ptr
[0];
1186 struct net_device
*dev
= info
->user_ptr
[1];
1187 struct wpan_dev
*wpan_dev
= dev
->ieee802154_ptr
;
1188 u8 max_csma_backoffs
;
1190 /* conflict here while other running iface settings */
1191 if (netif_running(dev
))
1194 if (!info
->attrs
[NL802154_ATTR_MAX_CSMA_BACKOFFS
])
1197 max_csma_backoffs
= nla_get_u8(
1198 info
->attrs
[NL802154_ATTR_MAX_CSMA_BACKOFFS
]);
1200 /* check 802.15.4 constraints */
1201 if (max_csma_backoffs
< rdev
->wpan_phy
.supported
.min_csma_backoffs
||
1202 max_csma_backoffs
> rdev
->wpan_phy
.supported
.max_csma_backoffs
)
1205 return rdev_set_max_csma_backoffs(rdev
, wpan_dev
, max_csma_backoffs
);
1209 nl802154_set_max_frame_retries(struct sk_buff
*skb
, struct genl_info
*info
)
1211 struct cfg802154_registered_device
*rdev
= info
->user_ptr
[0];
1212 struct net_device
*dev
= info
->user_ptr
[1];
1213 struct wpan_dev
*wpan_dev
= dev
->ieee802154_ptr
;
1214 s8 max_frame_retries
;
1216 if (netif_running(dev
))
1219 if (!info
->attrs
[NL802154_ATTR_MAX_FRAME_RETRIES
])
1222 max_frame_retries
= nla_get_s8(
1223 info
->attrs
[NL802154_ATTR_MAX_FRAME_RETRIES
]);
1225 /* check 802.15.4 constraints */
1226 if (max_frame_retries
< rdev
->wpan_phy
.supported
.min_frame_retries
||
1227 max_frame_retries
> rdev
->wpan_phy
.supported
.max_frame_retries
)
1230 return rdev_set_max_frame_retries(rdev
, wpan_dev
, max_frame_retries
);
1233 static int nl802154_set_lbt_mode(struct sk_buff
*skb
, struct genl_info
*info
)
1235 struct cfg802154_registered_device
*rdev
= info
->user_ptr
[0];
1236 struct net_device
*dev
= info
->user_ptr
[1];
1237 struct wpan_dev
*wpan_dev
= dev
->ieee802154_ptr
;
1240 if (netif_running(dev
))
1243 if (!info
->attrs
[NL802154_ATTR_LBT_MODE
])
1246 mode
= nla_get_u8(info
->attrs
[NL802154_ATTR_LBT_MODE
]);
1248 if (mode
!= 0 && mode
!= 1)
1251 if (!wpan_phy_supported_bool(mode
, rdev
->wpan_phy
.supported
.lbt
))
1254 return rdev_set_lbt_mode(rdev
, wpan_dev
, mode
);
1258 nl802154_set_ackreq_default(struct sk_buff
*skb
, struct genl_info
*info
)
1260 struct cfg802154_registered_device
*rdev
= info
->user_ptr
[0];
1261 struct net_device
*dev
= info
->user_ptr
[1];
1262 struct wpan_dev
*wpan_dev
= dev
->ieee802154_ptr
;
1265 if (netif_running(dev
))
1268 if (!info
->attrs
[NL802154_ATTR_ACKREQ_DEFAULT
])
1271 ackreq
= nla_get_u8(info
->attrs
[NL802154_ATTR_ACKREQ_DEFAULT
]);
1273 if (ackreq
!= 0 && ackreq
!= 1)
1276 return rdev_set_ackreq_default(rdev
, wpan_dev
, ackreq
);
1279 static int nl802154_wpan_phy_netns(struct sk_buff
*skb
, struct genl_info
*info
)
1281 struct cfg802154_registered_device
*rdev
= info
->user_ptr
[0];
1285 if (info
->attrs
[NL802154_ATTR_PID
]) {
1286 u32 pid
= nla_get_u32(info
->attrs
[NL802154_ATTR_PID
]);
1288 net
= get_net_ns_by_pid(pid
);
1289 } else if (info
->attrs
[NL802154_ATTR_NETNS_FD
]) {
1290 u32 fd
= nla_get_u32(info
->attrs
[NL802154_ATTR_NETNS_FD
]);
1292 net
= get_net_ns_by_fd(fd
);
1298 return PTR_ERR(net
);
1302 /* check if anything to do */
1303 if (!net_eq(wpan_phy_net(&rdev
->wpan_phy
), net
))
1304 err
= cfg802154_switch_netns(rdev
, net
);
1310 #ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL
1311 static const struct nla_policy nl802154_dev_addr_policy
[NL802154_DEV_ADDR_ATTR_MAX
+ 1] = {
1312 [NL802154_DEV_ADDR_ATTR_PAN_ID
] = { .type
= NLA_U16
},
1313 [NL802154_DEV_ADDR_ATTR_MODE
] = { .type
= NLA_U32
},
1314 [NL802154_DEV_ADDR_ATTR_SHORT
] = { .type
= NLA_U16
},
1315 [NL802154_DEV_ADDR_ATTR_EXTENDED
] = { .type
= NLA_U64
},
1319 ieee802154_llsec_parse_dev_addr(struct nlattr
*nla
,
1320 struct ieee802154_addr
*addr
)
1322 struct nlattr
*attrs
[NL802154_DEV_ADDR_ATTR_MAX
+ 1];
1324 if (!nla
|| nla_parse_nested(attrs
, NL802154_DEV_ADDR_ATTR_MAX
, nla
,
1325 nl802154_dev_addr_policy
))
1328 if (!attrs
[NL802154_DEV_ADDR_ATTR_PAN_ID
] ||
1329 !attrs
[NL802154_DEV_ADDR_ATTR_MODE
] ||
1330 !(attrs
[NL802154_DEV_ADDR_ATTR_SHORT
] ||
1331 attrs
[NL802154_DEV_ADDR_ATTR_EXTENDED
]))
1334 addr
->pan_id
= nla_get_le16(attrs
[NL802154_DEV_ADDR_ATTR_PAN_ID
]);
1335 addr
->mode
= nla_get_u32(attrs
[NL802154_DEV_ADDR_ATTR_MODE
]);
1336 switch (addr
->mode
) {
1337 case NL802154_DEV_ADDR_SHORT
:
1338 addr
->short_addr
= nla_get_le16(attrs
[NL802154_DEV_ADDR_ATTR_SHORT
]);
1340 case NL802154_DEV_ADDR_EXTENDED
:
1341 addr
->extended_addr
= nla_get_le64(attrs
[NL802154_DEV_ADDR_ATTR_EXTENDED
]);
1350 static const struct nla_policy nl802154_key_id_policy
[NL802154_KEY_ID_ATTR_MAX
+ 1] = {
1351 [NL802154_KEY_ID_ATTR_MODE
] = { .type
= NLA_U32
},
1352 [NL802154_KEY_ID_ATTR_INDEX
] = { .type
= NLA_U8
},
1353 [NL802154_KEY_ID_ATTR_IMPLICIT
] = { .type
= NLA_NESTED
},
1354 [NL802154_KEY_ID_ATTR_SOURCE_SHORT
] = { .type
= NLA_U32
},
1355 [NL802154_KEY_ID_ATTR_SOURCE_EXTENDED
] = { .type
= NLA_U64
},
1359 ieee802154_llsec_parse_key_id(struct nlattr
*nla
,
1360 struct ieee802154_llsec_key_id
*desc
)
1362 struct nlattr
*attrs
[NL802154_KEY_ID_ATTR_MAX
+ 1];
1364 if (!nla
|| nla_parse_nested(attrs
, NL802154_KEY_ID_ATTR_MAX
, nla
,
1365 nl802154_key_id_policy
))
1368 if (!attrs
[NL802154_KEY_ID_ATTR_MODE
])
1371 desc
->mode
= nla_get_u32(attrs
[NL802154_KEY_ID_ATTR_MODE
]);
1372 switch (desc
->mode
) {
1373 case NL802154_KEY_ID_MODE_IMPLICIT
:
1374 if (!attrs
[NL802154_KEY_ID_ATTR_IMPLICIT
])
1377 if (ieee802154_llsec_parse_dev_addr(attrs
[NL802154_KEY_ID_ATTR_IMPLICIT
],
1378 &desc
->device_addr
) < 0)
1381 case NL802154_KEY_ID_MODE_INDEX
:
1383 case NL802154_KEY_ID_MODE_INDEX_SHORT
:
1384 if (!attrs
[NL802154_KEY_ID_ATTR_SOURCE_SHORT
])
1387 desc
->short_source
= nla_get_le32(attrs
[NL802154_KEY_ID_ATTR_SOURCE_SHORT
]);
1389 case NL802154_KEY_ID_MODE_INDEX_EXTENDED
:
1390 if (!attrs
[NL802154_KEY_ID_ATTR_SOURCE_EXTENDED
])
1393 desc
->extended_source
= nla_get_le64(attrs
[NL802154_KEY_ID_ATTR_SOURCE_EXTENDED
]);
1399 if (desc
->mode
!= NL802154_KEY_ID_MODE_IMPLICIT
) {
1400 if (!attrs
[NL802154_KEY_ID_ATTR_INDEX
])
1403 /* TODO change id to idx */
1404 desc
->id
= nla_get_u8(attrs
[NL802154_KEY_ID_ATTR_INDEX
]);
1410 static int nl802154_set_llsec_params(struct sk_buff
*skb
,
1411 struct genl_info
*info
)
1413 struct cfg802154_registered_device
*rdev
= info
->user_ptr
[0];
1414 struct net_device
*dev
= info
->user_ptr
[1];
1415 struct wpan_dev
*wpan_dev
= dev
->ieee802154_ptr
;
1416 struct ieee802154_llsec_params params
;
1420 if (info
->attrs
[NL802154_ATTR_SEC_ENABLED
]) {
1423 enabled
= nla_get_u8(info
->attrs
[NL802154_ATTR_SEC_ENABLED
]);
1424 if (enabled
!= 0 && enabled
!= 1)
1427 params
.enabled
= nla_get_u8(info
->attrs
[NL802154_ATTR_SEC_ENABLED
]);
1428 changed
|= IEEE802154_LLSEC_PARAM_ENABLED
;
1431 if (info
->attrs
[NL802154_ATTR_SEC_OUT_KEY_ID
]) {
1432 ret
= ieee802154_llsec_parse_key_id(info
->attrs
[NL802154_ATTR_SEC_OUT_KEY_ID
],
1437 changed
|= IEEE802154_LLSEC_PARAM_OUT_KEY
;
1440 if (info
->attrs
[NL802154_ATTR_SEC_OUT_LEVEL
]) {
1441 params
.out_level
= nla_get_u32(info
->attrs
[NL802154_ATTR_SEC_OUT_LEVEL
]);
1442 if (params
.out_level
> NL802154_SECLEVEL_MAX
)
1445 changed
|= IEEE802154_LLSEC_PARAM_OUT_LEVEL
;
1448 if (info
->attrs
[NL802154_ATTR_SEC_FRAME_COUNTER
]) {
1449 params
.frame_counter
= nla_get_be32(info
->attrs
[NL802154_ATTR_SEC_FRAME_COUNTER
]);
1450 changed
|= IEEE802154_LLSEC_PARAM_FRAME_COUNTER
;
1453 return rdev_set_llsec_params(rdev
, wpan_dev
, ¶ms
, changed
);
1456 static int nl802154_send_key(struct sk_buff
*msg
, u32 cmd
, u32 portid
,
1458 struct cfg802154_registered_device
*rdev
,
1459 struct net_device
*dev
,
1460 const struct ieee802154_llsec_key_entry
*key
)
1463 u32 commands
[NL802154_CMD_FRAME_NR_IDS
/ 32];
1464 struct nlattr
*nl_key
, *nl_key_id
;
1466 hdr
= nl802154hdr_put(msg
, portid
, seq
, flags
, cmd
);
1470 if (nla_put_u32(msg
, NL802154_ATTR_IFINDEX
, dev
->ifindex
))
1471 goto nla_put_failure
;
1473 nl_key
= nla_nest_start(msg
, NL802154_ATTR_SEC_KEY
);
1475 goto nla_put_failure
;
1477 nl_key_id
= nla_nest_start(msg
, NL802154_KEY_ATTR_ID
);
1479 goto nla_put_failure
;
1481 if (ieee802154_llsec_send_key_id(msg
, &key
->id
) < 0)
1482 goto nla_put_failure
;
1484 nla_nest_end(msg
, nl_key_id
);
1486 if (nla_put_u8(msg
, NL802154_KEY_ATTR_USAGE_FRAMES
,
1487 key
->key
->frame_types
))
1488 goto nla_put_failure
;
1490 if (key
->key
->frame_types
& BIT(NL802154_FRAME_CMD
)) {
1491 /* TODO for each nested */
1492 memset(commands
, 0, sizeof(commands
));
1493 commands
[7] = key
->key
->cmd_frame_ids
;
1494 if (nla_put(msg
, NL802154_KEY_ATTR_USAGE_CMDS
,
1495 sizeof(commands
), commands
))
1496 goto nla_put_failure
;
1499 if (nla_put(msg
, NL802154_KEY_ATTR_BYTES
, NL802154_KEY_SIZE
,
1501 goto nla_put_failure
;
1503 nla_nest_end(msg
, nl_key
);
1504 genlmsg_end(msg
, hdr
);
1509 genlmsg_cancel(msg
, hdr
);
1514 nl802154_dump_llsec_key(struct sk_buff
*skb
, struct netlink_callback
*cb
)
1516 struct cfg802154_registered_device
*rdev
= NULL
;
1517 struct ieee802154_llsec_key_entry
*key
;
1518 struct ieee802154_llsec_table
*table
;
1519 struct wpan_dev
*wpan_dev
;
1522 err
= nl802154_prepare_wpan_dev_dump(skb
, cb
, &rdev
, &wpan_dev
);
1526 if (!wpan_dev
->netdev
) {
1531 rdev_lock_llsec_table(rdev
, wpan_dev
);
1532 rdev_get_llsec_table(rdev
, wpan_dev
, &table
);
1534 /* TODO make it like station dump */
1538 list_for_each_entry(key
, &table
->keys
, list
) {
1539 if (nl802154_send_key(skb
, NL802154_CMD_NEW_SEC_KEY
,
1540 NETLINK_CB(cb
->skb
).portid
,
1541 cb
->nlh
->nlmsg_seq
, NLM_F_MULTI
,
1542 rdev
, wpan_dev
->netdev
, key
) < 0) {
1545 rdev_unlock_llsec_table(rdev
, wpan_dev
);
1553 rdev_unlock_llsec_table(rdev
, wpan_dev
);
1556 nl802154_finish_wpan_dev_dump(rdev
);
1561 static const struct nla_policy nl802154_key_policy
[NL802154_KEY_ATTR_MAX
+ 1] = {
1562 [NL802154_KEY_ATTR_ID
] = { NLA_NESTED
},
1563 /* TODO handle it as for_each_nested and NLA_FLAG? */
1564 [NL802154_KEY_ATTR_USAGE_FRAMES
] = { NLA_U8
},
1565 /* TODO handle it as for_each_nested, not static array? */
1566 [NL802154_KEY_ATTR_USAGE_CMDS
] = { .len
= NL802154_CMD_FRAME_NR_IDS
/ 8 },
1567 [NL802154_KEY_ATTR_BYTES
] = { .len
= NL802154_KEY_SIZE
},
1570 static int nl802154_add_llsec_key(struct sk_buff
*skb
, struct genl_info
*info
)
1572 struct cfg802154_registered_device
*rdev
= info
->user_ptr
[0];
1573 struct net_device
*dev
= info
->user_ptr
[1];
1574 struct wpan_dev
*wpan_dev
= dev
->ieee802154_ptr
;
1575 struct nlattr
*attrs
[NL802154_KEY_ATTR_MAX
+ 1];
1576 struct ieee802154_llsec_key key
= { };
1577 struct ieee802154_llsec_key_id id
= { };
1578 u32 commands
[NL802154_CMD_FRAME_NR_IDS
/ 32] = { };
1580 if (nla_parse_nested(attrs
, NL802154_KEY_ATTR_MAX
,
1581 info
->attrs
[NL802154_ATTR_SEC_KEY
],
1582 nl802154_key_policy
))
1585 if (!attrs
[NL802154_KEY_ATTR_USAGE_FRAMES
] ||
1586 !attrs
[NL802154_KEY_ATTR_BYTES
])
1589 if (ieee802154_llsec_parse_key_id(attrs
[NL802154_KEY_ATTR_ID
], &id
) < 0)
1592 key
.frame_types
= nla_get_u8(attrs
[NL802154_KEY_ATTR_USAGE_FRAMES
]);
1593 if (key
.frame_types
> BIT(NL802154_FRAME_MAX
) ||
1594 ((key
.frame_types
& BIT(NL802154_FRAME_CMD
)) &&
1595 !attrs
[NL802154_KEY_ATTR_USAGE_CMDS
]))
1598 if (attrs
[NL802154_KEY_ATTR_USAGE_CMDS
]) {
1599 /* TODO for each nested */
1600 nla_memcpy(commands
, attrs
[NL802154_KEY_ATTR_USAGE_CMDS
],
1601 NL802154_CMD_FRAME_NR_IDS
/ 8);
1603 /* TODO understand the -EINVAL logic here? last condition */
1604 if (commands
[0] || commands
[1] || commands
[2] || commands
[3] ||
1605 commands
[4] || commands
[5] || commands
[6] ||
1606 commands
[7] > BIT(NL802154_CMD_FRAME_MAX
))
1609 key
.cmd_frame_ids
= commands
[7];
1611 key
.cmd_frame_ids
= 0;
1614 nla_memcpy(key
.key
, attrs
[NL802154_KEY_ATTR_BYTES
], NL802154_KEY_SIZE
);
1616 if (ieee802154_llsec_parse_key_id(attrs
[NL802154_KEY_ATTR_ID
], &id
) < 0)
1619 return rdev_add_llsec_key(rdev
, wpan_dev
, &id
, &key
);
1622 static int nl802154_del_llsec_key(struct sk_buff
*skb
, struct genl_info
*info
)
1624 struct cfg802154_registered_device
*rdev
= info
->user_ptr
[0];
1625 struct net_device
*dev
= info
->user_ptr
[1];
1626 struct wpan_dev
*wpan_dev
= dev
->ieee802154_ptr
;
1627 struct nlattr
*attrs
[NL802154_KEY_ATTR_MAX
+ 1];
1628 struct ieee802154_llsec_key_id id
;
1630 if (nla_parse_nested(attrs
, NL802154_KEY_ATTR_MAX
,
1631 info
->attrs
[NL802154_ATTR_SEC_KEY
],
1632 nl802154_key_policy
))
1635 if (ieee802154_llsec_parse_key_id(attrs
[NL802154_KEY_ATTR_ID
], &id
) < 0)
1638 return rdev_del_llsec_key(rdev
, wpan_dev
, &id
);
1641 static int nl802154_send_device(struct sk_buff
*msg
, u32 cmd
, u32 portid
,
1643 struct cfg802154_registered_device
*rdev
,
1644 struct net_device
*dev
,
1645 const struct ieee802154_llsec_device
*dev_desc
)
1648 struct nlattr
*nl_device
;
1650 hdr
= nl802154hdr_put(msg
, portid
, seq
, flags
, cmd
);
1654 if (nla_put_u32(msg
, NL802154_ATTR_IFINDEX
, dev
->ifindex
))
1655 goto nla_put_failure
;
1657 nl_device
= nla_nest_start(msg
, NL802154_ATTR_SEC_DEVICE
);
1659 goto nla_put_failure
;
1661 if (nla_put_u32(msg
, NL802154_DEV_ATTR_FRAME_COUNTER
,
1662 dev_desc
->frame_counter
) ||
1663 nla_put_le16(msg
, NL802154_DEV_ATTR_PAN_ID
, dev_desc
->pan_id
) ||
1664 nla_put_le16(msg
, NL802154_DEV_ATTR_SHORT_ADDR
,
1665 dev_desc
->short_addr
) ||
1666 nla_put_le64(msg
, NL802154_DEV_ATTR_EXTENDED_ADDR
,
1667 dev_desc
->hwaddr
, NL802154_DEV_ATTR_PAD
) ||
1668 nla_put_u8(msg
, NL802154_DEV_ATTR_SECLEVEL_EXEMPT
,
1669 dev_desc
->seclevel_exempt
) ||
1670 nla_put_u32(msg
, NL802154_DEV_ATTR_KEY_MODE
, dev_desc
->key_mode
))
1671 goto nla_put_failure
;
1673 nla_nest_end(msg
, nl_device
);
1674 genlmsg_end(msg
, hdr
);
1679 genlmsg_cancel(msg
, hdr
);
1684 nl802154_dump_llsec_dev(struct sk_buff
*skb
, struct netlink_callback
*cb
)
1686 struct cfg802154_registered_device
*rdev
= NULL
;
1687 struct ieee802154_llsec_device
*dev
;
1688 struct ieee802154_llsec_table
*table
;
1689 struct wpan_dev
*wpan_dev
;
1692 err
= nl802154_prepare_wpan_dev_dump(skb
, cb
, &rdev
, &wpan_dev
);
1696 if (!wpan_dev
->netdev
) {
1701 rdev_lock_llsec_table(rdev
, wpan_dev
);
1702 rdev_get_llsec_table(rdev
, wpan_dev
, &table
);
1704 /* TODO make it like station dump */
1708 list_for_each_entry(dev
, &table
->devices
, list
) {
1709 if (nl802154_send_device(skb
, NL802154_CMD_NEW_SEC_LEVEL
,
1710 NETLINK_CB(cb
->skb
).portid
,
1711 cb
->nlh
->nlmsg_seq
, NLM_F_MULTI
,
1712 rdev
, wpan_dev
->netdev
, dev
) < 0) {
1715 rdev_unlock_llsec_table(rdev
, wpan_dev
);
1723 rdev_unlock_llsec_table(rdev
, wpan_dev
);
1726 nl802154_finish_wpan_dev_dump(rdev
);
1731 static const struct nla_policy nl802154_dev_policy
[NL802154_DEV_ATTR_MAX
+ 1] = {
1732 [NL802154_DEV_ATTR_FRAME_COUNTER
] = { NLA_U32
},
1733 [NL802154_DEV_ATTR_PAN_ID
] = { .type
= NLA_U16
},
1734 [NL802154_DEV_ATTR_SHORT_ADDR
] = { .type
= NLA_U16
},
1735 [NL802154_DEV_ATTR_EXTENDED_ADDR
] = { .type
= NLA_U64
},
1736 [NL802154_DEV_ATTR_SECLEVEL_EXEMPT
] = { NLA_U8
},
1737 [NL802154_DEV_ATTR_KEY_MODE
] = { NLA_U32
},
1741 ieee802154_llsec_parse_device(struct nlattr
*nla
,
1742 struct ieee802154_llsec_device
*dev
)
1744 struct nlattr
*attrs
[NL802154_DEV_ATTR_MAX
+ 1];
1746 if (!nla
|| nla_parse_nested(attrs
, NL802154_DEV_ATTR_MAX
, nla
,
1747 nl802154_dev_policy
))
1750 memset(dev
, 0, sizeof(*dev
));
1752 if (!attrs
[NL802154_DEV_ATTR_FRAME_COUNTER
] ||
1753 !attrs
[NL802154_DEV_ATTR_PAN_ID
] ||
1754 !attrs
[NL802154_DEV_ATTR_SHORT_ADDR
] ||
1755 !attrs
[NL802154_DEV_ATTR_EXTENDED_ADDR
] ||
1756 !attrs
[NL802154_DEV_ATTR_SECLEVEL_EXEMPT
] ||
1757 !attrs
[NL802154_DEV_ATTR_KEY_MODE
])
1761 dev
->frame_counter
= nla_get_u32(attrs
[NL802154_DEV_ATTR_FRAME_COUNTER
]);
1762 dev
->pan_id
= nla_get_le16(attrs
[NL802154_DEV_ATTR_PAN_ID
]);
1763 dev
->short_addr
= nla_get_le16(attrs
[NL802154_DEV_ATTR_SHORT_ADDR
]);
1764 /* TODO rename hwaddr to extended_addr */
1765 dev
->hwaddr
= nla_get_le64(attrs
[NL802154_DEV_ATTR_EXTENDED_ADDR
]);
1766 dev
->seclevel_exempt
= nla_get_u8(attrs
[NL802154_DEV_ATTR_SECLEVEL_EXEMPT
]);
1767 dev
->key_mode
= nla_get_u32(attrs
[NL802154_DEV_ATTR_KEY_MODE
]);
1769 if (dev
->key_mode
> NL802154_DEVKEY_MAX
||
1770 (dev
->seclevel_exempt
!= 0 && dev
->seclevel_exempt
!= 1))
1776 static int nl802154_add_llsec_dev(struct sk_buff
*skb
, struct genl_info
*info
)
1778 struct cfg802154_registered_device
*rdev
= info
->user_ptr
[0];
1779 struct net_device
*dev
= info
->user_ptr
[1];
1780 struct wpan_dev
*wpan_dev
= dev
->ieee802154_ptr
;
1781 struct ieee802154_llsec_device dev_desc
;
1783 if (ieee802154_llsec_parse_device(info
->attrs
[NL802154_ATTR_SEC_DEVICE
],
1787 return rdev_add_device(rdev
, wpan_dev
, &dev_desc
);
1790 static int nl802154_del_llsec_dev(struct sk_buff
*skb
, struct genl_info
*info
)
1792 struct cfg802154_registered_device
*rdev
= info
->user_ptr
[0];
1793 struct net_device
*dev
= info
->user_ptr
[1];
1794 struct wpan_dev
*wpan_dev
= dev
->ieee802154_ptr
;
1795 struct nlattr
*attrs
[NL802154_DEV_ATTR_MAX
+ 1];
1796 __le64 extended_addr
;
1798 if (nla_parse_nested(attrs
, NL802154_DEV_ATTR_MAX
,
1799 info
->attrs
[NL802154_ATTR_SEC_DEVICE
],
1800 nl802154_dev_policy
))
1803 if (!attrs
[NL802154_DEV_ATTR_EXTENDED_ADDR
])
1806 extended_addr
= nla_get_le64(attrs
[NL802154_DEV_ATTR_EXTENDED_ADDR
]);
1807 return rdev_del_device(rdev
, wpan_dev
, extended_addr
);
1810 static int nl802154_send_devkey(struct sk_buff
*msg
, u32 cmd
, u32 portid
,
1812 struct cfg802154_registered_device
*rdev
,
1813 struct net_device
*dev
, __le64 extended_addr
,
1814 const struct ieee802154_llsec_device_key
*devkey
)
1817 struct nlattr
*nl_devkey
, *nl_key_id
;
1819 hdr
= nl802154hdr_put(msg
, portid
, seq
, flags
, cmd
);
1823 if (nla_put_u32(msg
, NL802154_ATTR_IFINDEX
, dev
->ifindex
))
1824 goto nla_put_failure
;
1826 nl_devkey
= nla_nest_start(msg
, NL802154_ATTR_SEC_DEVKEY
);
1828 goto nla_put_failure
;
1830 if (nla_put_le64(msg
, NL802154_DEVKEY_ATTR_EXTENDED_ADDR
,
1831 extended_addr
, NL802154_DEVKEY_ATTR_PAD
) ||
1832 nla_put_u32(msg
, NL802154_DEVKEY_ATTR_FRAME_COUNTER
,
1833 devkey
->frame_counter
))
1834 goto nla_put_failure
;
1836 nl_key_id
= nla_nest_start(msg
, NL802154_DEVKEY_ATTR_ID
);
1838 goto nla_put_failure
;
1840 if (ieee802154_llsec_send_key_id(msg
, &devkey
->key_id
) < 0)
1841 goto nla_put_failure
;
1843 nla_nest_end(msg
, nl_key_id
);
1844 nla_nest_end(msg
, nl_devkey
);
1845 genlmsg_end(msg
, hdr
);
1850 genlmsg_cancel(msg
, hdr
);
1855 nl802154_dump_llsec_devkey(struct sk_buff
*skb
, struct netlink_callback
*cb
)
1857 struct cfg802154_registered_device
*rdev
= NULL
;
1858 struct ieee802154_llsec_device_key
*kpos
;
1859 struct ieee802154_llsec_device
*dpos
;
1860 struct ieee802154_llsec_table
*table
;
1861 struct wpan_dev
*wpan_dev
;
1864 err
= nl802154_prepare_wpan_dev_dump(skb
, cb
, &rdev
, &wpan_dev
);
1868 if (!wpan_dev
->netdev
) {
1873 rdev_lock_llsec_table(rdev
, wpan_dev
);
1874 rdev_get_llsec_table(rdev
, wpan_dev
, &table
);
1876 /* TODO make it like station dump */
1880 /* TODO look if remove devkey and do some nested attribute */
1881 list_for_each_entry(dpos
, &table
->devices
, list
) {
1882 list_for_each_entry(kpos
, &dpos
->keys
, list
) {
1883 if (nl802154_send_devkey(skb
,
1884 NL802154_CMD_NEW_SEC_LEVEL
,
1885 NETLINK_CB(cb
->skb
).portid
,
1893 rdev_unlock_llsec_table(rdev
, wpan_dev
);
1902 rdev_unlock_llsec_table(rdev
, wpan_dev
);
1905 nl802154_finish_wpan_dev_dump(rdev
);
1910 static const struct nla_policy nl802154_devkey_policy
[NL802154_DEVKEY_ATTR_MAX
+ 1] = {
1911 [NL802154_DEVKEY_ATTR_FRAME_COUNTER
] = { NLA_U32
},
1912 [NL802154_DEVKEY_ATTR_EXTENDED_ADDR
] = { NLA_U64
},
1913 [NL802154_DEVKEY_ATTR_ID
] = { NLA_NESTED
},
1916 static int nl802154_add_llsec_devkey(struct sk_buff
*skb
, struct genl_info
*info
)
1918 struct cfg802154_registered_device
*rdev
= info
->user_ptr
[0];
1919 struct net_device
*dev
= info
->user_ptr
[1];
1920 struct wpan_dev
*wpan_dev
= dev
->ieee802154_ptr
;
1921 struct nlattr
*attrs
[NL802154_DEVKEY_ATTR_MAX
+ 1];
1922 struct ieee802154_llsec_device_key key
;
1923 __le64 extended_addr
;
1925 if (!info
->attrs
[NL802154_ATTR_SEC_DEVKEY
] ||
1926 nla_parse_nested(attrs
, NL802154_DEVKEY_ATTR_MAX
,
1927 info
->attrs
[NL802154_ATTR_SEC_DEVKEY
],
1928 nl802154_devkey_policy
) < 0)
1931 if (!attrs
[NL802154_DEVKEY_ATTR_FRAME_COUNTER
] ||
1932 !attrs
[NL802154_DEVKEY_ATTR_EXTENDED_ADDR
])
1935 /* TODO change key.id ? */
1936 if (ieee802154_llsec_parse_key_id(attrs
[NL802154_DEVKEY_ATTR_ID
],
1941 key
.frame_counter
= nla_get_u32(attrs
[NL802154_DEVKEY_ATTR_FRAME_COUNTER
]);
1942 /* TODO change naming hwaddr -> extended_addr
1943 * check unique identifier short+pan OR extended_addr
1945 extended_addr
= nla_get_le64(attrs
[NL802154_DEVKEY_ATTR_EXTENDED_ADDR
]);
1946 return rdev_add_devkey(rdev
, wpan_dev
, extended_addr
, &key
);
1949 static int nl802154_del_llsec_devkey(struct sk_buff
*skb
, struct genl_info
*info
)
1951 struct cfg802154_registered_device
*rdev
= info
->user_ptr
[0];
1952 struct net_device
*dev
= info
->user_ptr
[1];
1953 struct wpan_dev
*wpan_dev
= dev
->ieee802154_ptr
;
1954 struct nlattr
*attrs
[NL802154_DEVKEY_ATTR_MAX
+ 1];
1955 struct ieee802154_llsec_device_key key
;
1956 __le64 extended_addr
;
1958 if (nla_parse_nested(attrs
, NL802154_DEVKEY_ATTR_MAX
,
1959 info
->attrs
[NL802154_ATTR_SEC_DEVKEY
],
1960 nl802154_devkey_policy
))
1963 if (!attrs
[NL802154_DEVKEY_ATTR_EXTENDED_ADDR
])
1966 /* TODO change key.id ? */
1967 if (ieee802154_llsec_parse_key_id(attrs
[NL802154_DEVKEY_ATTR_ID
],
1971 /* TODO change naming hwaddr -> extended_addr
1972 * check unique identifier short+pan OR extended_addr
1974 extended_addr
= nla_get_le64(attrs
[NL802154_DEVKEY_ATTR_EXTENDED_ADDR
]);
1975 return rdev_del_devkey(rdev
, wpan_dev
, extended_addr
, &key
);
1978 static int nl802154_send_seclevel(struct sk_buff
*msg
, u32 cmd
, u32 portid
,
1980 struct cfg802154_registered_device
*rdev
,
1981 struct net_device
*dev
,
1982 const struct ieee802154_llsec_seclevel
*sl
)
1985 struct nlattr
*nl_seclevel
;
1987 hdr
= nl802154hdr_put(msg
, portid
, seq
, flags
, cmd
);
1991 if (nla_put_u32(msg
, NL802154_ATTR_IFINDEX
, dev
->ifindex
))
1992 goto nla_put_failure
;
1994 nl_seclevel
= nla_nest_start(msg
, NL802154_ATTR_SEC_LEVEL
);
1996 goto nla_put_failure
;
1998 if (nla_put_u32(msg
, NL802154_SECLEVEL_ATTR_FRAME
, sl
->frame_type
) ||
1999 nla_put_u32(msg
, NL802154_SECLEVEL_ATTR_LEVELS
, sl
->sec_levels
) ||
2000 nla_put_u8(msg
, NL802154_SECLEVEL_ATTR_DEV_OVERRIDE
,
2001 sl
->device_override
))
2002 goto nla_put_failure
;
2004 if (sl
->frame_type
== NL802154_FRAME_CMD
) {
2005 if (nla_put_u32(msg
, NL802154_SECLEVEL_ATTR_CMD_FRAME
,
2007 goto nla_put_failure
;
2010 nla_nest_end(msg
, nl_seclevel
);
2011 genlmsg_end(msg
, hdr
);
2016 genlmsg_cancel(msg
, hdr
);
2021 nl802154_dump_llsec_seclevel(struct sk_buff
*skb
, struct netlink_callback
*cb
)
2023 struct cfg802154_registered_device
*rdev
= NULL
;
2024 struct ieee802154_llsec_seclevel
*sl
;
2025 struct ieee802154_llsec_table
*table
;
2026 struct wpan_dev
*wpan_dev
;
2029 err
= nl802154_prepare_wpan_dev_dump(skb
, cb
, &rdev
, &wpan_dev
);
2033 if (!wpan_dev
->netdev
) {
2038 rdev_lock_llsec_table(rdev
, wpan_dev
);
2039 rdev_get_llsec_table(rdev
, wpan_dev
, &table
);
2041 /* TODO make it like station dump */
2045 list_for_each_entry(sl
, &table
->security_levels
, list
) {
2046 if (nl802154_send_seclevel(skb
, NL802154_CMD_NEW_SEC_LEVEL
,
2047 NETLINK_CB(cb
->skb
).portid
,
2048 cb
->nlh
->nlmsg_seq
, NLM_F_MULTI
,
2049 rdev
, wpan_dev
->netdev
, sl
) < 0) {
2052 rdev_unlock_llsec_table(rdev
, wpan_dev
);
2060 rdev_unlock_llsec_table(rdev
, wpan_dev
);
2063 nl802154_finish_wpan_dev_dump(rdev
);
2068 static const struct nla_policy nl802154_seclevel_policy
[NL802154_SECLEVEL_ATTR_MAX
+ 1] = {
2069 [NL802154_SECLEVEL_ATTR_LEVELS
] = { .type
= NLA_U8
},
2070 [NL802154_SECLEVEL_ATTR_FRAME
] = { .type
= NLA_U32
},
2071 [NL802154_SECLEVEL_ATTR_CMD_FRAME
] = { .type
= NLA_U32
},
2072 [NL802154_SECLEVEL_ATTR_DEV_OVERRIDE
] = { .type
= NLA_U8
},
2076 llsec_parse_seclevel(struct nlattr
*nla
, struct ieee802154_llsec_seclevel
*sl
)
2078 struct nlattr
*attrs
[NL802154_SECLEVEL_ATTR_MAX
+ 1];
2080 if (!nla
|| nla_parse_nested(attrs
, NL802154_SECLEVEL_ATTR_MAX
, nla
,
2081 nl802154_seclevel_policy
))
2084 memset(sl
, 0, sizeof(*sl
));
2086 if (!attrs
[NL802154_SECLEVEL_ATTR_LEVELS
] ||
2087 !attrs
[NL802154_SECLEVEL_ATTR_FRAME
] ||
2088 !attrs
[NL802154_SECLEVEL_ATTR_DEV_OVERRIDE
])
2091 sl
->sec_levels
= nla_get_u8(attrs
[NL802154_SECLEVEL_ATTR_LEVELS
]);
2092 sl
->frame_type
= nla_get_u32(attrs
[NL802154_SECLEVEL_ATTR_FRAME
]);
2093 sl
->device_override
= nla_get_u8(attrs
[NL802154_SECLEVEL_ATTR_DEV_OVERRIDE
]);
2094 if (sl
->frame_type
> NL802154_FRAME_MAX
||
2095 (sl
->device_override
!= 0 && sl
->device_override
!= 1))
2098 if (sl
->frame_type
== NL802154_FRAME_CMD
) {
2099 if (!attrs
[NL802154_SECLEVEL_ATTR_CMD_FRAME
])
2102 sl
->cmd_frame_id
= nla_get_u32(attrs
[NL802154_SECLEVEL_ATTR_CMD_FRAME
]);
2103 if (sl
->cmd_frame_id
> NL802154_CMD_FRAME_MAX
)
2110 static int nl802154_add_llsec_seclevel(struct sk_buff
*skb
,
2111 struct genl_info
*info
)
2113 struct cfg802154_registered_device
*rdev
= info
->user_ptr
[0];
2114 struct net_device
*dev
= info
->user_ptr
[1];
2115 struct wpan_dev
*wpan_dev
= dev
->ieee802154_ptr
;
2116 struct ieee802154_llsec_seclevel sl
;
2118 if (llsec_parse_seclevel(info
->attrs
[NL802154_ATTR_SEC_LEVEL
],
2122 return rdev_add_seclevel(rdev
, wpan_dev
, &sl
);
2125 static int nl802154_del_llsec_seclevel(struct sk_buff
*skb
,
2126 struct genl_info
*info
)
2128 struct cfg802154_registered_device
*rdev
= info
->user_ptr
[0];
2129 struct net_device
*dev
= info
->user_ptr
[1];
2130 struct wpan_dev
*wpan_dev
= dev
->ieee802154_ptr
;
2131 struct ieee802154_llsec_seclevel sl
;
2133 if (!info
->attrs
[NL802154_ATTR_SEC_LEVEL
] ||
2134 llsec_parse_seclevel(info
->attrs
[NL802154_ATTR_SEC_LEVEL
],
2138 return rdev_del_seclevel(rdev
, wpan_dev
, &sl
);
2140 #endif /* CONFIG_IEEE802154_NL802154_EXPERIMENTAL */
2142 #define NL802154_FLAG_NEED_WPAN_PHY 0x01
2143 #define NL802154_FLAG_NEED_NETDEV 0x02
2144 #define NL802154_FLAG_NEED_RTNL 0x04
2145 #define NL802154_FLAG_CHECK_NETDEV_UP 0x08
2146 #define NL802154_FLAG_NEED_NETDEV_UP (NL802154_FLAG_NEED_NETDEV |\
2147 NL802154_FLAG_CHECK_NETDEV_UP)
2148 #define NL802154_FLAG_NEED_WPAN_DEV 0x10
2149 #define NL802154_FLAG_NEED_WPAN_DEV_UP (NL802154_FLAG_NEED_WPAN_DEV |\
2150 NL802154_FLAG_CHECK_NETDEV_UP)
2152 static int nl802154_pre_doit(const struct genl_ops
*ops
, struct sk_buff
*skb
,
2153 struct genl_info
*info
)
2155 struct cfg802154_registered_device
*rdev
;
2156 struct wpan_dev
*wpan_dev
;
2157 struct net_device
*dev
;
2158 bool rtnl
= ops
->internal_flags
& NL802154_FLAG_NEED_RTNL
;
2163 if (ops
->internal_flags
& NL802154_FLAG_NEED_WPAN_PHY
) {
2164 rdev
= cfg802154_get_dev_from_info(genl_info_net(info
), info
);
2168 return PTR_ERR(rdev
);
2170 info
->user_ptr
[0] = rdev
;
2171 } else if (ops
->internal_flags
& NL802154_FLAG_NEED_NETDEV
||
2172 ops
->internal_flags
& NL802154_FLAG_NEED_WPAN_DEV
) {
2174 wpan_dev
= __cfg802154_wpan_dev_from_attrs(genl_info_net(info
),
2176 if (IS_ERR(wpan_dev
)) {
2179 return PTR_ERR(wpan_dev
);
2182 dev
= wpan_dev
->netdev
;
2183 rdev
= wpan_phy_to_rdev(wpan_dev
->wpan_phy
);
2185 if (ops
->internal_flags
& NL802154_FLAG_NEED_NETDEV
) {
2192 info
->user_ptr
[1] = dev
;
2194 info
->user_ptr
[1] = wpan_dev
;
2198 if (ops
->internal_flags
& NL802154_FLAG_CHECK_NETDEV_UP
&&
2199 !netif_running(dev
)) {
2208 info
->user_ptr
[0] = rdev
;
2214 static void nl802154_post_doit(const struct genl_ops
*ops
, struct sk_buff
*skb
,
2215 struct genl_info
*info
)
2217 if (info
->user_ptr
[1]) {
2218 if (ops
->internal_flags
& NL802154_FLAG_NEED_WPAN_DEV
) {
2219 struct wpan_dev
*wpan_dev
= info
->user_ptr
[1];
2221 if (wpan_dev
->netdev
)
2222 dev_put(wpan_dev
->netdev
);
2224 dev_put(info
->user_ptr
[1]);
2228 if (ops
->internal_flags
& NL802154_FLAG_NEED_RTNL
)
2232 static const struct genl_ops nl802154_ops
[] = {
2234 .cmd
= NL802154_CMD_GET_WPAN_PHY
,
2235 .doit
= nl802154_get_wpan_phy
,
2236 .dumpit
= nl802154_dump_wpan_phy
,
2237 .done
= nl802154_dump_wpan_phy_done
,
2238 .policy
= nl802154_policy
,
2239 /* can be retrieved by unprivileged users */
2240 .internal_flags
= NL802154_FLAG_NEED_WPAN_PHY
|
2241 NL802154_FLAG_NEED_RTNL
,
2244 .cmd
= NL802154_CMD_GET_INTERFACE
,
2245 .doit
= nl802154_get_interface
,
2246 .dumpit
= nl802154_dump_interface
,
2247 .policy
= nl802154_policy
,
2248 /* can be retrieved by unprivileged users */
2249 .internal_flags
= NL802154_FLAG_NEED_WPAN_DEV
|
2250 NL802154_FLAG_NEED_RTNL
,
2253 .cmd
= NL802154_CMD_NEW_INTERFACE
,
2254 .doit
= nl802154_new_interface
,
2255 .policy
= nl802154_policy
,
2256 .flags
= GENL_ADMIN_PERM
,
2257 .internal_flags
= NL802154_FLAG_NEED_WPAN_PHY
|
2258 NL802154_FLAG_NEED_RTNL
,
2261 .cmd
= NL802154_CMD_DEL_INTERFACE
,
2262 .doit
= nl802154_del_interface
,
2263 .policy
= nl802154_policy
,
2264 .flags
= GENL_ADMIN_PERM
,
2265 .internal_flags
= NL802154_FLAG_NEED_WPAN_DEV
|
2266 NL802154_FLAG_NEED_RTNL
,
2269 .cmd
= NL802154_CMD_SET_CHANNEL
,
2270 .doit
= nl802154_set_channel
,
2271 .policy
= nl802154_policy
,
2272 .flags
= GENL_ADMIN_PERM
,
2273 .internal_flags
= NL802154_FLAG_NEED_WPAN_PHY
|
2274 NL802154_FLAG_NEED_RTNL
,
2277 .cmd
= NL802154_CMD_SET_CCA_MODE
,
2278 .doit
= nl802154_set_cca_mode
,
2279 .policy
= nl802154_policy
,
2280 .flags
= GENL_ADMIN_PERM
,
2281 .internal_flags
= NL802154_FLAG_NEED_WPAN_PHY
|
2282 NL802154_FLAG_NEED_RTNL
,
2285 .cmd
= NL802154_CMD_SET_CCA_ED_LEVEL
,
2286 .doit
= nl802154_set_cca_ed_level
,
2287 .policy
= nl802154_policy
,
2288 .flags
= GENL_ADMIN_PERM
,
2289 .internal_flags
= NL802154_FLAG_NEED_WPAN_PHY
|
2290 NL802154_FLAG_NEED_RTNL
,
2293 .cmd
= NL802154_CMD_SET_TX_POWER
,
2294 .doit
= nl802154_set_tx_power
,
2295 .policy
= nl802154_policy
,
2296 .flags
= GENL_ADMIN_PERM
,
2297 .internal_flags
= NL802154_FLAG_NEED_WPAN_PHY
|
2298 NL802154_FLAG_NEED_RTNL
,
2301 .cmd
= NL802154_CMD_SET_WPAN_PHY_NETNS
,
2302 .doit
= nl802154_wpan_phy_netns
,
2303 .policy
= nl802154_policy
,
2304 .flags
= GENL_ADMIN_PERM
,
2305 .internal_flags
= NL802154_FLAG_NEED_WPAN_PHY
|
2306 NL802154_FLAG_NEED_RTNL
,
2309 .cmd
= NL802154_CMD_SET_PAN_ID
,
2310 .doit
= nl802154_set_pan_id
,
2311 .policy
= nl802154_policy
,
2312 .flags
= GENL_ADMIN_PERM
,
2313 .internal_flags
= NL802154_FLAG_NEED_NETDEV
|
2314 NL802154_FLAG_NEED_RTNL
,
2317 .cmd
= NL802154_CMD_SET_SHORT_ADDR
,
2318 .doit
= nl802154_set_short_addr
,
2319 .policy
= nl802154_policy
,
2320 .flags
= GENL_ADMIN_PERM
,
2321 .internal_flags
= NL802154_FLAG_NEED_NETDEV
|
2322 NL802154_FLAG_NEED_RTNL
,
2325 .cmd
= NL802154_CMD_SET_BACKOFF_EXPONENT
,
2326 .doit
= nl802154_set_backoff_exponent
,
2327 .policy
= nl802154_policy
,
2328 .flags
= GENL_ADMIN_PERM
,
2329 .internal_flags
= NL802154_FLAG_NEED_NETDEV
|
2330 NL802154_FLAG_NEED_RTNL
,
2333 .cmd
= NL802154_CMD_SET_MAX_CSMA_BACKOFFS
,
2334 .doit
= nl802154_set_max_csma_backoffs
,
2335 .policy
= nl802154_policy
,
2336 .flags
= GENL_ADMIN_PERM
,
2337 .internal_flags
= NL802154_FLAG_NEED_NETDEV
|
2338 NL802154_FLAG_NEED_RTNL
,
2341 .cmd
= NL802154_CMD_SET_MAX_FRAME_RETRIES
,
2342 .doit
= nl802154_set_max_frame_retries
,
2343 .policy
= nl802154_policy
,
2344 .flags
= GENL_ADMIN_PERM
,
2345 .internal_flags
= NL802154_FLAG_NEED_NETDEV
|
2346 NL802154_FLAG_NEED_RTNL
,
2349 .cmd
= NL802154_CMD_SET_LBT_MODE
,
2350 .doit
= nl802154_set_lbt_mode
,
2351 .policy
= nl802154_policy
,
2352 .flags
= GENL_ADMIN_PERM
,
2353 .internal_flags
= NL802154_FLAG_NEED_NETDEV
|
2354 NL802154_FLAG_NEED_RTNL
,
2357 .cmd
= NL802154_CMD_SET_ACKREQ_DEFAULT
,
2358 .doit
= nl802154_set_ackreq_default
,
2359 .policy
= nl802154_policy
,
2360 .flags
= GENL_ADMIN_PERM
,
2361 .internal_flags
= NL802154_FLAG_NEED_NETDEV
|
2362 NL802154_FLAG_NEED_RTNL
,
2364 #ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL
2366 .cmd
= NL802154_CMD_SET_SEC_PARAMS
,
2367 .doit
= nl802154_set_llsec_params
,
2368 .policy
= nl802154_policy
,
2369 .flags
= GENL_ADMIN_PERM
,
2370 .internal_flags
= NL802154_FLAG_NEED_NETDEV
|
2371 NL802154_FLAG_NEED_RTNL
,
2374 .cmd
= NL802154_CMD_GET_SEC_KEY
,
2375 /* TODO .doit by matching key id? */
2376 .dumpit
= nl802154_dump_llsec_key
,
2377 .policy
= nl802154_policy
,
2378 .flags
= GENL_ADMIN_PERM
,
2379 .internal_flags
= NL802154_FLAG_NEED_NETDEV
|
2380 NL802154_FLAG_NEED_RTNL
,
2383 .cmd
= NL802154_CMD_NEW_SEC_KEY
,
2384 .doit
= nl802154_add_llsec_key
,
2385 .policy
= nl802154_policy
,
2386 .flags
= GENL_ADMIN_PERM
,
2387 .internal_flags
= NL802154_FLAG_NEED_NETDEV
|
2388 NL802154_FLAG_NEED_RTNL
,
2391 .cmd
= NL802154_CMD_DEL_SEC_KEY
,
2392 .doit
= nl802154_del_llsec_key
,
2393 .policy
= nl802154_policy
,
2394 .flags
= GENL_ADMIN_PERM
,
2395 .internal_flags
= NL802154_FLAG_NEED_NETDEV
|
2396 NL802154_FLAG_NEED_RTNL
,
2398 /* TODO unique identifier must short+pan OR extended_addr */
2400 .cmd
= NL802154_CMD_GET_SEC_DEV
,
2401 /* TODO .doit by matching extended_addr? */
2402 .dumpit
= nl802154_dump_llsec_dev
,
2403 .policy
= nl802154_policy
,
2404 .flags
= GENL_ADMIN_PERM
,
2405 .internal_flags
= NL802154_FLAG_NEED_NETDEV
|
2406 NL802154_FLAG_NEED_RTNL
,
2409 .cmd
= NL802154_CMD_NEW_SEC_DEV
,
2410 .doit
= nl802154_add_llsec_dev
,
2411 .policy
= nl802154_policy
,
2412 .flags
= GENL_ADMIN_PERM
,
2413 .internal_flags
= NL802154_FLAG_NEED_NETDEV
|
2414 NL802154_FLAG_NEED_RTNL
,
2417 .cmd
= NL802154_CMD_DEL_SEC_DEV
,
2418 .doit
= nl802154_del_llsec_dev
,
2419 .policy
= nl802154_policy
,
2420 .flags
= GENL_ADMIN_PERM
,
2421 .internal_flags
= NL802154_FLAG_NEED_NETDEV
|
2422 NL802154_FLAG_NEED_RTNL
,
2424 /* TODO remove complete devkey, put it as nested? */
2426 .cmd
= NL802154_CMD_GET_SEC_DEVKEY
,
2427 /* TODO doit by matching ??? */
2428 .dumpit
= nl802154_dump_llsec_devkey
,
2429 .policy
= nl802154_policy
,
2430 .flags
= GENL_ADMIN_PERM
,
2431 .internal_flags
= NL802154_FLAG_NEED_NETDEV
|
2432 NL802154_FLAG_NEED_RTNL
,
2435 .cmd
= NL802154_CMD_NEW_SEC_DEVKEY
,
2436 .doit
= nl802154_add_llsec_devkey
,
2437 .policy
= nl802154_policy
,
2438 .flags
= GENL_ADMIN_PERM
,
2439 .internal_flags
= NL802154_FLAG_NEED_NETDEV
|
2440 NL802154_FLAG_NEED_RTNL
,
2443 .cmd
= NL802154_CMD_DEL_SEC_DEVKEY
,
2444 .doit
= nl802154_del_llsec_devkey
,
2445 .policy
= nl802154_policy
,
2446 .flags
= GENL_ADMIN_PERM
,
2447 .internal_flags
= NL802154_FLAG_NEED_NETDEV
|
2448 NL802154_FLAG_NEED_RTNL
,
2451 .cmd
= NL802154_CMD_GET_SEC_LEVEL
,
2452 /* TODO .doit by matching frame_type? */
2453 .dumpit
= nl802154_dump_llsec_seclevel
,
2454 .policy
= nl802154_policy
,
2455 .flags
= GENL_ADMIN_PERM
,
2456 .internal_flags
= NL802154_FLAG_NEED_NETDEV
|
2457 NL802154_FLAG_NEED_RTNL
,
2460 .cmd
= NL802154_CMD_NEW_SEC_LEVEL
,
2461 .doit
= nl802154_add_llsec_seclevel
,
2462 .policy
= nl802154_policy
,
2463 .flags
= GENL_ADMIN_PERM
,
2464 .internal_flags
= NL802154_FLAG_NEED_NETDEV
|
2465 NL802154_FLAG_NEED_RTNL
,
2468 .cmd
= NL802154_CMD_DEL_SEC_LEVEL
,
2469 /* TODO match frame_type only? */
2470 .doit
= nl802154_del_llsec_seclevel
,
2471 .policy
= nl802154_policy
,
2472 .flags
= GENL_ADMIN_PERM
,
2473 .internal_flags
= NL802154_FLAG_NEED_NETDEV
|
2474 NL802154_FLAG_NEED_RTNL
,
2476 #endif /* CONFIG_IEEE802154_NL802154_EXPERIMENTAL */
2479 /* initialisation/exit functions */
2480 int nl802154_init(void)
2482 return genl_register_family_with_ops_groups(&nl802154_fam
, nl802154_ops
,
2486 void nl802154_exit(void)
2488 genl_unregister_family(&nl802154_fam
);