1 // SPDX-License-Identifier: GPL-2.0-only
3 * Netlink interface for IEEE 802.15.4 stack
5 * Copyright 2007, 2008 Siemens AG
8 * Sergey Lapin <slapin@ossfans.org>
9 * Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
10 * Maxim Osipov <maxim.osipov@siemens.com>
13 #include <linux/gfp.h>
14 #include <linux/kernel.h>
15 #include <linux/if_arp.h>
16 #include <linux/netdevice.h>
17 #include <linux/ieee802154.h>
18 #include <net/netlink.h>
19 #include <net/genetlink.h>
21 #include <linux/nl802154.h>
22 #include <linux/export.h>
23 #include <net/af_ieee802154.h>
24 #include <net/ieee802154_netdev.h>
25 #include <net/cfg802154.h>
27 #include "ieee802154.h"
29 static int nla_put_hwaddr(struct sk_buff
*msg
, int type
, __le64 hwaddr
,
32 return nla_put_u64_64bit(msg
, type
, swab64((__force u64
)hwaddr
),
36 static __le64
nla_get_hwaddr(const struct nlattr
*nla
)
38 return ieee802154_devaddr_from_raw(nla_data(nla
));
41 static int nla_put_shortaddr(struct sk_buff
*msg
, int type
, __le16 addr
)
43 return nla_put_u16(msg
, type
, le16_to_cpu(addr
));
46 static __le16
nla_get_shortaddr(const struct nlattr
*nla
)
48 return cpu_to_le16(nla_get_u16(nla
));
51 static int ieee802154_nl_start_confirm(struct net_device
*dev
, u8 status
)
55 pr_debug("%s\n", __func__
);
57 msg
= ieee802154_nl_create(0, IEEE802154_START_CONF
);
61 if (nla_put_string(msg
, IEEE802154_ATTR_DEV_NAME
, dev
->name
) ||
62 nla_put_u32(msg
, IEEE802154_ATTR_DEV_INDEX
, dev
->ifindex
) ||
63 nla_put(msg
, IEEE802154_ATTR_HW_ADDR
, IEEE802154_ADDR_LEN
,
65 nla_put_u8(msg
, IEEE802154_ATTR_STATUS
, status
))
67 return ieee802154_nl_mcast(msg
, IEEE802154_COORD_MCGRP
);
74 static int ieee802154_nl_fill_iface(struct sk_buff
*msg
, u32 portid
,
75 u32 seq
, int flags
, struct net_device
*dev
)
79 struct ieee802154_mlme_ops
*ops
;
80 __le16 short_addr
, pan_id
;
82 pr_debug("%s\n", __func__
);
84 hdr
= genlmsg_put(msg
, 0, seq
, &nl802154_family
, flags
,
85 IEEE802154_LIST_IFACE
);
89 ops
= ieee802154_mlme_ops(dev
);
90 phy
= dev
->ieee802154_ptr
->wpan_phy
;
92 get_device(&phy
->dev
);
95 short_addr
= dev
->ieee802154_ptr
->short_addr
;
96 pan_id
= dev
->ieee802154_ptr
->pan_id
;
99 if (nla_put_string(msg
, IEEE802154_ATTR_DEV_NAME
, dev
->name
) ||
100 nla_put_string(msg
, IEEE802154_ATTR_PHY_NAME
, wpan_phy_name(phy
)) ||
101 nla_put_u32(msg
, IEEE802154_ATTR_DEV_INDEX
, dev
->ifindex
) ||
102 nla_put(msg
, IEEE802154_ATTR_HW_ADDR
, IEEE802154_ADDR_LEN
,
104 nla_put_shortaddr(msg
, IEEE802154_ATTR_SHORT_ADDR
, short_addr
) ||
105 nla_put_shortaddr(msg
, IEEE802154_ATTR_PAN_ID
, pan_id
))
106 goto nla_put_failure
;
108 if (ops
->get_mac_params
) {
109 struct ieee802154_mac_params params
;
112 ops
->get_mac_params(dev
, ¶ms
);
115 if (nla_put_s8(msg
, IEEE802154_ATTR_TXPOWER
,
116 params
.transmit_power
/ 100) ||
117 nla_put_u8(msg
, IEEE802154_ATTR_LBT_ENABLED
, params
.lbt
) ||
118 nla_put_u8(msg
, IEEE802154_ATTR_CCA_MODE
,
120 nla_put_s32(msg
, IEEE802154_ATTR_CCA_ED_LEVEL
,
121 params
.cca_ed_level
/ 100) ||
122 nla_put_u8(msg
, IEEE802154_ATTR_CSMA_RETRIES
,
123 params
.csma_retries
) ||
124 nla_put_u8(msg
, IEEE802154_ATTR_CSMA_MIN_BE
,
126 nla_put_u8(msg
, IEEE802154_ATTR_CSMA_MAX_BE
,
128 nla_put_s8(msg
, IEEE802154_ATTR_FRAME_RETRIES
,
129 params
.frame_retries
))
130 goto nla_put_failure
;
134 genlmsg_end(msg
, hdr
);
139 genlmsg_cancel(msg
, hdr
);
144 /* Requests from userspace */
145 static struct net_device
*ieee802154_nl_get_dev(struct genl_info
*info
)
147 struct net_device
*dev
;
149 if (info
->attrs
[IEEE802154_ATTR_DEV_NAME
]) {
150 char name
[IFNAMSIZ
+ 1];
152 nla_strlcpy(name
, info
->attrs
[IEEE802154_ATTR_DEV_NAME
],
154 dev
= dev_get_by_name(&init_net
, name
);
155 } else if (info
->attrs
[IEEE802154_ATTR_DEV_INDEX
]) {
156 dev
= dev_get_by_index(&init_net
,
157 nla_get_u32(info
->attrs
[IEEE802154_ATTR_DEV_INDEX
]));
165 if (dev
->type
!= ARPHRD_IEEE802154
) {
173 int ieee802154_associate_req(struct sk_buff
*skb
, struct genl_info
*info
)
175 struct net_device
*dev
;
176 struct ieee802154_addr addr
;
178 int ret
= -EOPNOTSUPP
;
180 if (!info
->attrs
[IEEE802154_ATTR_CHANNEL
] ||
181 !info
->attrs
[IEEE802154_ATTR_COORD_PAN_ID
] ||
182 (!info
->attrs
[IEEE802154_ATTR_COORD_HW_ADDR
] &&
183 !info
->attrs
[IEEE802154_ATTR_COORD_SHORT_ADDR
]) ||
184 !info
->attrs
[IEEE802154_ATTR_CAPABILITY
])
187 dev
= ieee802154_nl_get_dev(info
);
190 if (!ieee802154_mlme_ops(dev
)->assoc_req
)
193 if (info
->attrs
[IEEE802154_ATTR_COORD_HW_ADDR
]) {
194 addr
.mode
= IEEE802154_ADDR_LONG
;
195 addr
.extended_addr
= nla_get_hwaddr(
196 info
->attrs
[IEEE802154_ATTR_COORD_HW_ADDR
]);
198 addr
.mode
= IEEE802154_ADDR_SHORT
;
199 addr
.short_addr
= nla_get_shortaddr(
200 info
->attrs
[IEEE802154_ATTR_COORD_SHORT_ADDR
]);
202 addr
.pan_id
= nla_get_shortaddr(
203 info
->attrs
[IEEE802154_ATTR_COORD_PAN_ID
]);
205 if (info
->attrs
[IEEE802154_ATTR_PAGE
])
206 page
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_PAGE
]);
210 ret
= ieee802154_mlme_ops(dev
)->assoc_req(dev
, &addr
,
211 nla_get_u8(info
->attrs
[IEEE802154_ATTR_CHANNEL
]),
213 nla_get_u8(info
->attrs
[IEEE802154_ATTR_CAPABILITY
]));
220 int ieee802154_associate_resp(struct sk_buff
*skb
, struct genl_info
*info
)
222 struct net_device
*dev
;
223 struct ieee802154_addr addr
;
224 int ret
= -EOPNOTSUPP
;
226 if (!info
->attrs
[IEEE802154_ATTR_STATUS
] ||
227 !info
->attrs
[IEEE802154_ATTR_DEST_HW_ADDR
] ||
228 !info
->attrs
[IEEE802154_ATTR_DEST_SHORT_ADDR
])
231 dev
= ieee802154_nl_get_dev(info
);
234 if (!ieee802154_mlme_ops(dev
)->assoc_resp
)
237 addr
.mode
= IEEE802154_ADDR_LONG
;
238 addr
.extended_addr
= nla_get_hwaddr(
239 info
->attrs
[IEEE802154_ATTR_DEST_HW_ADDR
]);
241 addr
.pan_id
= dev
->ieee802154_ptr
->pan_id
;
244 ret
= ieee802154_mlme_ops(dev
)->assoc_resp(dev
, &addr
,
245 nla_get_shortaddr(info
->attrs
[IEEE802154_ATTR_DEST_SHORT_ADDR
]),
246 nla_get_u8(info
->attrs
[IEEE802154_ATTR_STATUS
]));
253 int ieee802154_disassociate_req(struct sk_buff
*skb
, struct genl_info
*info
)
255 struct net_device
*dev
;
256 struct ieee802154_addr addr
;
257 int ret
= -EOPNOTSUPP
;
259 if ((!info
->attrs
[IEEE802154_ATTR_DEST_HW_ADDR
] &&
260 !info
->attrs
[IEEE802154_ATTR_DEST_SHORT_ADDR
]) ||
261 !info
->attrs
[IEEE802154_ATTR_REASON
])
264 dev
= ieee802154_nl_get_dev(info
);
267 if (!ieee802154_mlme_ops(dev
)->disassoc_req
)
270 if (info
->attrs
[IEEE802154_ATTR_DEST_HW_ADDR
]) {
271 addr
.mode
= IEEE802154_ADDR_LONG
;
272 addr
.extended_addr
= nla_get_hwaddr(
273 info
->attrs
[IEEE802154_ATTR_DEST_HW_ADDR
]);
275 addr
.mode
= IEEE802154_ADDR_SHORT
;
276 addr
.short_addr
= nla_get_shortaddr(
277 info
->attrs
[IEEE802154_ATTR_DEST_SHORT_ADDR
]);
280 addr
.pan_id
= dev
->ieee802154_ptr
->pan_id
;
283 ret
= ieee802154_mlme_ops(dev
)->disassoc_req(dev
, &addr
,
284 nla_get_u8(info
->attrs
[IEEE802154_ATTR_REASON
]));
291 /* PANid, channel, beacon_order = 15, superframe_order = 15,
292 * PAN_coordinator, battery_life_extension = 0,
293 * coord_realignment = 0, security_enable = 0
295 int ieee802154_start_req(struct sk_buff
*skb
, struct genl_info
*info
)
297 struct net_device
*dev
;
298 struct ieee802154_addr addr
;
300 u8 channel
, bcn_ord
, sf_ord
;
302 int pan_coord
, blx
, coord_realign
;
305 if (!info
->attrs
[IEEE802154_ATTR_COORD_PAN_ID
] ||
306 !info
->attrs
[IEEE802154_ATTR_COORD_SHORT_ADDR
] ||
307 !info
->attrs
[IEEE802154_ATTR_CHANNEL
] ||
308 !info
->attrs
[IEEE802154_ATTR_BCN_ORD
] ||
309 !info
->attrs
[IEEE802154_ATTR_SF_ORD
] ||
310 !info
->attrs
[IEEE802154_ATTR_PAN_COORD
] ||
311 !info
->attrs
[IEEE802154_ATTR_BAT_EXT
] ||
312 !info
->attrs
[IEEE802154_ATTR_COORD_REALIGN
]
316 dev
= ieee802154_nl_get_dev(info
);
320 if (netif_running(dev
))
323 if (!ieee802154_mlme_ops(dev
)->start_req
) {
328 addr
.mode
= IEEE802154_ADDR_SHORT
;
329 addr
.short_addr
= nla_get_shortaddr(
330 info
->attrs
[IEEE802154_ATTR_COORD_SHORT_ADDR
]);
331 addr
.pan_id
= nla_get_shortaddr(
332 info
->attrs
[IEEE802154_ATTR_COORD_PAN_ID
]);
334 channel
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_CHANNEL
]);
335 bcn_ord
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_BCN_ORD
]);
336 sf_ord
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_SF_ORD
]);
337 pan_coord
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_PAN_COORD
]);
338 blx
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_BAT_EXT
]);
339 coord_realign
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_COORD_REALIGN
]);
341 if (info
->attrs
[IEEE802154_ATTR_PAGE
])
342 page
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_PAGE
]);
346 if (addr
.short_addr
== cpu_to_le16(IEEE802154_ADDR_BROADCAST
)) {
347 ieee802154_nl_start_confirm(dev
, IEEE802154_NO_SHORT_ADDRESS
);
353 ret
= ieee802154_mlme_ops(dev
)->start_req(dev
, &addr
, channel
, page
,
354 bcn_ord
, sf_ord
, pan_coord
, blx
, coord_realign
);
357 /* FIXME: add validation for unused parameters to be sane
360 ieee802154_nl_start_confirm(dev
, IEEE802154_SUCCESS
);
367 int ieee802154_scan_req(struct sk_buff
*skb
, struct genl_info
*info
)
369 struct net_device
*dev
;
370 int ret
= -EOPNOTSUPP
;
376 if (!info
->attrs
[IEEE802154_ATTR_SCAN_TYPE
] ||
377 !info
->attrs
[IEEE802154_ATTR_CHANNELS
] ||
378 !info
->attrs
[IEEE802154_ATTR_DURATION
])
381 dev
= ieee802154_nl_get_dev(info
);
384 if (!ieee802154_mlme_ops(dev
)->scan_req
)
387 type
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_SCAN_TYPE
]);
388 channels
= nla_get_u32(info
->attrs
[IEEE802154_ATTR_CHANNELS
]);
389 duration
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_DURATION
]);
391 if (info
->attrs
[IEEE802154_ATTR_PAGE
])
392 page
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_PAGE
]);
396 ret
= ieee802154_mlme_ops(dev
)->scan_req(dev
, type
, channels
,
404 int ieee802154_list_iface(struct sk_buff
*skb
, struct genl_info
*info
)
406 /* Request for interface name, index, type, IEEE address,
407 * PAN Id, short address
410 struct net_device
*dev
= NULL
;
413 pr_debug("%s\n", __func__
);
415 dev
= ieee802154_nl_get_dev(info
);
419 msg
= nlmsg_new(NLMSG_DEFAULT_SIZE
, GFP_KERNEL
);
423 rc
= ieee802154_nl_fill_iface(msg
, info
->snd_portid
, info
->snd_seq
,
430 return genlmsg_reply(msg
, info
);
438 int ieee802154_dump_iface(struct sk_buff
*skb
, struct netlink_callback
*cb
)
440 struct net
*net
= sock_net(skb
->sk
);
441 struct net_device
*dev
;
443 int s_idx
= cb
->args
[0];
445 pr_debug("%s\n", __func__
);
448 for_each_netdev(net
, dev
) {
449 if (idx
< s_idx
|| dev
->type
!= ARPHRD_IEEE802154
)
452 if (ieee802154_nl_fill_iface(skb
, NETLINK_CB(cb
->skb
).portid
,
454 NLM_F_MULTI
, dev
) < 0)
464 int ieee802154_set_macparams(struct sk_buff
*skb
, struct genl_info
*info
)
466 struct net_device
*dev
= NULL
;
467 struct ieee802154_mlme_ops
*ops
;
468 struct ieee802154_mac_params params
;
469 struct wpan_phy
*phy
;
472 pr_debug("%s\n", __func__
);
474 dev
= ieee802154_nl_get_dev(info
);
478 ops
= ieee802154_mlme_ops(dev
);
480 if (!ops
->get_mac_params
|| !ops
->set_mac_params
) {
485 if (netif_running(dev
)) {
490 if (!info
->attrs
[IEEE802154_ATTR_LBT_ENABLED
] &&
491 !info
->attrs
[IEEE802154_ATTR_CCA_MODE
] &&
492 !info
->attrs
[IEEE802154_ATTR_CCA_ED_LEVEL
] &&
493 !info
->attrs
[IEEE802154_ATTR_CSMA_RETRIES
] &&
494 !info
->attrs
[IEEE802154_ATTR_CSMA_MIN_BE
] &&
495 !info
->attrs
[IEEE802154_ATTR_CSMA_MAX_BE
] &&
496 !info
->attrs
[IEEE802154_ATTR_FRAME_RETRIES
])
499 phy
= dev
->ieee802154_ptr
->wpan_phy
;
500 get_device(&phy
->dev
);
503 ops
->get_mac_params(dev
, ¶ms
);
505 if (info
->attrs
[IEEE802154_ATTR_TXPOWER
])
506 params
.transmit_power
= nla_get_s8(info
->attrs
[IEEE802154_ATTR_TXPOWER
]) * 100;
508 if (info
->attrs
[IEEE802154_ATTR_LBT_ENABLED
])
509 params
.lbt
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_LBT_ENABLED
]);
511 if (info
->attrs
[IEEE802154_ATTR_CCA_MODE
])
512 params
.cca
.mode
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_CCA_MODE
]);
514 if (info
->attrs
[IEEE802154_ATTR_CCA_ED_LEVEL
])
515 params
.cca_ed_level
= nla_get_s32(info
->attrs
[IEEE802154_ATTR_CCA_ED_LEVEL
]) * 100;
517 if (info
->attrs
[IEEE802154_ATTR_CSMA_RETRIES
])
518 params
.csma_retries
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_CSMA_RETRIES
]);
520 if (info
->attrs
[IEEE802154_ATTR_CSMA_MIN_BE
])
521 params
.min_be
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_CSMA_MIN_BE
]);
523 if (info
->attrs
[IEEE802154_ATTR_CSMA_MAX_BE
])
524 params
.max_be
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_CSMA_MAX_BE
]);
526 if (info
->attrs
[IEEE802154_ATTR_FRAME_RETRIES
])
527 params
.frame_retries
= nla_get_s8(info
->attrs
[IEEE802154_ATTR_FRAME_RETRIES
]);
529 rc
= ops
->set_mac_params(dev
, ¶ms
);
543 ieee802154_llsec_parse_key_id(struct genl_info
*info
,
544 struct ieee802154_llsec_key_id
*desc
)
546 memset(desc
, 0, sizeof(*desc
));
548 if (!info
->attrs
[IEEE802154_ATTR_LLSEC_KEY_MODE
])
551 desc
->mode
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_LLSEC_KEY_MODE
]);
553 if (desc
->mode
== IEEE802154_SCF_KEY_IMPLICIT
) {
554 if (!info
->attrs
[IEEE802154_ATTR_PAN_ID
] &&
555 !(info
->attrs
[IEEE802154_ATTR_SHORT_ADDR
] ||
556 info
->attrs
[IEEE802154_ATTR_HW_ADDR
]))
559 desc
->device_addr
.pan_id
= nla_get_shortaddr(info
->attrs
[IEEE802154_ATTR_PAN_ID
]);
561 if (info
->attrs
[IEEE802154_ATTR_SHORT_ADDR
]) {
562 desc
->device_addr
.mode
= IEEE802154_ADDR_SHORT
;
563 desc
->device_addr
.short_addr
= nla_get_shortaddr(info
->attrs
[IEEE802154_ATTR_SHORT_ADDR
]);
565 desc
->device_addr
.mode
= IEEE802154_ADDR_LONG
;
566 desc
->device_addr
.extended_addr
= nla_get_hwaddr(info
->attrs
[IEEE802154_ATTR_HW_ADDR
]);
570 if (desc
->mode
!= IEEE802154_SCF_KEY_IMPLICIT
&&
571 !info
->attrs
[IEEE802154_ATTR_LLSEC_KEY_ID
])
574 if (desc
->mode
== IEEE802154_SCF_KEY_SHORT_INDEX
&&
575 !info
->attrs
[IEEE802154_ATTR_LLSEC_KEY_SOURCE_SHORT
])
578 if (desc
->mode
== IEEE802154_SCF_KEY_HW_INDEX
&&
579 !info
->attrs
[IEEE802154_ATTR_LLSEC_KEY_SOURCE_EXTENDED
])
582 if (desc
->mode
!= IEEE802154_SCF_KEY_IMPLICIT
)
583 desc
->id
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_LLSEC_KEY_ID
]);
585 switch (desc
->mode
) {
586 case IEEE802154_SCF_KEY_SHORT_INDEX
:
588 u32 source
= nla_get_u32(info
->attrs
[IEEE802154_ATTR_LLSEC_KEY_SOURCE_SHORT
]);
590 desc
->short_source
= cpu_to_le32(source
);
593 case IEEE802154_SCF_KEY_HW_INDEX
:
594 desc
->extended_source
= nla_get_hwaddr(info
->attrs
[IEEE802154_ATTR_LLSEC_KEY_SOURCE_EXTENDED
]);
602 ieee802154_llsec_fill_key_id(struct sk_buff
*msg
,
603 const struct ieee802154_llsec_key_id
*desc
)
605 if (nla_put_u8(msg
, IEEE802154_ATTR_LLSEC_KEY_MODE
, desc
->mode
))
608 if (desc
->mode
== IEEE802154_SCF_KEY_IMPLICIT
) {
609 if (nla_put_shortaddr(msg
, IEEE802154_ATTR_PAN_ID
,
610 desc
->device_addr
.pan_id
))
613 if (desc
->device_addr
.mode
== IEEE802154_ADDR_SHORT
&&
614 nla_put_shortaddr(msg
, IEEE802154_ATTR_SHORT_ADDR
,
615 desc
->device_addr
.short_addr
))
618 if (desc
->device_addr
.mode
== IEEE802154_ADDR_LONG
&&
619 nla_put_hwaddr(msg
, IEEE802154_ATTR_HW_ADDR
,
620 desc
->device_addr
.extended_addr
,
621 IEEE802154_ATTR_PAD
))
625 if (desc
->mode
!= IEEE802154_SCF_KEY_IMPLICIT
&&
626 nla_put_u8(msg
, IEEE802154_ATTR_LLSEC_KEY_ID
, desc
->id
))
629 if (desc
->mode
== IEEE802154_SCF_KEY_SHORT_INDEX
&&
630 nla_put_u32(msg
, IEEE802154_ATTR_LLSEC_KEY_SOURCE_SHORT
,
631 le32_to_cpu(desc
->short_source
)))
634 if (desc
->mode
== IEEE802154_SCF_KEY_HW_INDEX
&&
635 nla_put_hwaddr(msg
, IEEE802154_ATTR_LLSEC_KEY_SOURCE_EXTENDED
,
636 desc
->extended_source
, IEEE802154_ATTR_PAD
))
642 int ieee802154_llsec_getparams(struct sk_buff
*skb
, struct genl_info
*info
)
645 struct net_device
*dev
= NULL
;
647 struct ieee802154_mlme_ops
*ops
;
649 struct ieee802154_llsec_params params
;
651 pr_debug("%s\n", __func__
);
653 dev
= ieee802154_nl_get_dev(info
);
657 ops
= ieee802154_mlme_ops(dev
);
663 msg
= nlmsg_new(NLMSG_DEFAULT_SIZE
, GFP_KERNEL
);
667 hdr
= genlmsg_put(msg
, 0, info
->snd_seq
, &nl802154_family
, 0,
668 IEEE802154_LLSEC_GETPARAMS
);
672 rc
= ops
->llsec
->get_params(dev
, ¶ms
);
676 if (nla_put_string(msg
, IEEE802154_ATTR_DEV_NAME
, dev
->name
) ||
677 nla_put_u32(msg
, IEEE802154_ATTR_DEV_INDEX
, dev
->ifindex
) ||
678 nla_put_u8(msg
, IEEE802154_ATTR_LLSEC_ENABLED
, params
.enabled
) ||
679 nla_put_u8(msg
, IEEE802154_ATTR_LLSEC_SECLEVEL
, params
.out_level
) ||
680 nla_put_u32(msg
, IEEE802154_ATTR_LLSEC_FRAME_COUNTER
,
681 be32_to_cpu(params
.frame_counter
)) ||
682 ieee802154_llsec_fill_key_id(msg
, ¶ms
.out_key
))
687 return ieee802154_nl_reply(msg
, info
);
695 int ieee802154_llsec_setparams(struct sk_buff
*skb
, struct genl_info
*info
)
697 struct net_device
*dev
= NULL
;
699 struct ieee802154_mlme_ops
*ops
;
700 struct ieee802154_llsec_params params
;
703 pr_debug("%s\n", __func__
);
705 dev
= ieee802154_nl_get_dev(info
);
709 if (!info
->attrs
[IEEE802154_ATTR_LLSEC_ENABLED
] &&
710 !info
->attrs
[IEEE802154_ATTR_LLSEC_KEY_MODE
] &&
711 !info
->attrs
[IEEE802154_ATTR_LLSEC_SECLEVEL
])
714 ops
= ieee802154_mlme_ops(dev
);
720 if (info
->attrs
[IEEE802154_ATTR_LLSEC_SECLEVEL
] &&
721 nla_get_u8(info
->attrs
[IEEE802154_ATTR_LLSEC_SECLEVEL
]) > 7)
724 if (info
->attrs
[IEEE802154_ATTR_LLSEC_ENABLED
]) {
725 params
.enabled
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_LLSEC_ENABLED
]);
726 changed
|= IEEE802154_LLSEC_PARAM_ENABLED
;
729 if (info
->attrs
[IEEE802154_ATTR_LLSEC_KEY_MODE
]) {
730 if (ieee802154_llsec_parse_key_id(info
, ¶ms
.out_key
))
733 changed
|= IEEE802154_LLSEC_PARAM_OUT_KEY
;
736 if (info
->attrs
[IEEE802154_ATTR_LLSEC_SECLEVEL
]) {
737 params
.out_level
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_LLSEC_SECLEVEL
]);
738 changed
|= IEEE802154_LLSEC_PARAM_OUT_LEVEL
;
741 if (info
->attrs
[IEEE802154_ATTR_LLSEC_FRAME_COUNTER
]) {
742 u32 fc
= nla_get_u32(info
->attrs
[IEEE802154_ATTR_LLSEC_FRAME_COUNTER
]);
744 params
.frame_counter
= cpu_to_be32(fc
);
745 changed
|= IEEE802154_LLSEC_PARAM_FRAME_COUNTER
;
748 rc
= ops
->llsec
->set_params(dev
, ¶ms
, changed
);
758 struct llsec_dump_data
{
763 struct net_device
*dev
;
764 struct ieee802154_mlme_ops
*ops
;
765 struct ieee802154_llsec_table
*table
;
769 ieee802154_llsec_dump_table(struct sk_buff
*skb
, struct netlink_callback
*cb
,
770 int (*step
)(struct llsec_dump_data
*))
772 struct net
*net
= sock_net(skb
->sk
);
773 struct net_device
*dev
;
774 struct llsec_dump_data data
;
776 int first_dev
= cb
->args
[0];
779 for_each_netdev(net
, dev
) {
780 if (idx
< first_dev
|| dev
->type
!= ARPHRD_IEEE802154
)
783 data
.ops
= ieee802154_mlme_ops(dev
);
784 if (!data
.ops
->llsec
)
788 data
.s_idx
= cb
->args
[1];
789 data
.s_idx2
= cb
->args
[2];
791 data
.portid
= NETLINK_CB(cb
->skb
).portid
;
792 data
.nlmsg_seq
= cb
->nlh
->nlmsg_seq
;
794 data
.ops
->llsec
->lock_table(dev
);
795 data
.ops
->llsec
->get_table(data
.dev
, &data
.table
);
797 data
.ops
->llsec
->unlock_table(dev
);
811 ieee802154_nl_llsec_change(struct sk_buff
*skb
, struct genl_info
*info
,
812 int (*fn
)(struct net_device
*, struct genl_info
*))
814 struct net_device
*dev
= NULL
;
817 dev
= ieee802154_nl_get_dev(info
);
821 if (!ieee802154_mlme_ops(dev
)->llsec
)
831 ieee802154_llsec_parse_key(struct genl_info
*info
,
832 struct ieee802154_llsec_key
*key
)
835 u32 commands
[256 / 32];
837 memset(key
, 0, sizeof(*key
));
839 if (!info
->attrs
[IEEE802154_ATTR_LLSEC_KEY_USAGE_FRAME_TYPES
] ||
840 !info
->attrs
[IEEE802154_ATTR_LLSEC_KEY_BYTES
])
843 frames
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_LLSEC_KEY_USAGE_FRAME_TYPES
]);
844 if ((frames
& BIT(IEEE802154_FC_TYPE_MAC_CMD
)) &&
845 !info
->attrs
[IEEE802154_ATTR_LLSEC_KEY_USAGE_COMMANDS
])
848 if (info
->attrs
[IEEE802154_ATTR_LLSEC_KEY_USAGE_COMMANDS
]) {
850 info
->attrs
[IEEE802154_ATTR_LLSEC_KEY_USAGE_COMMANDS
],
853 if (commands
[0] || commands
[1] || commands
[2] || commands
[3] ||
854 commands
[4] || commands
[5] || commands
[6] ||
855 commands
[7] >= BIT(IEEE802154_CMD_GTS_REQ
+ 1))
858 key
->cmd_frame_ids
= commands
[7];
861 key
->frame_types
= frames
;
863 nla_memcpy(key
->key
, info
->attrs
[IEEE802154_ATTR_LLSEC_KEY_BYTES
],
864 IEEE802154_LLSEC_KEY_SIZE
);
869 static int llsec_add_key(struct net_device
*dev
, struct genl_info
*info
)
871 struct ieee802154_mlme_ops
*ops
= ieee802154_mlme_ops(dev
);
872 struct ieee802154_llsec_key key
;
873 struct ieee802154_llsec_key_id id
;
875 if (ieee802154_llsec_parse_key(info
, &key
) ||
876 ieee802154_llsec_parse_key_id(info
, &id
))
879 return ops
->llsec
->add_key(dev
, &id
, &key
);
882 int ieee802154_llsec_add_key(struct sk_buff
*skb
, struct genl_info
*info
)
884 if ((info
->nlhdr
->nlmsg_flags
& (NLM_F_CREATE
| NLM_F_EXCL
)) !=
885 (NLM_F_CREATE
| NLM_F_EXCL
))
888 return ieee802154_nl_llsec_change(skb
, info
, llsec_add_key
);
891 static int llsec_remove_key(struct net_device
*dev
, struct genl_info
*info
)
893 struct ieee802154_mlme_ops
*ops
= ieee802154_mlme_ops(dev
);
894 struct ieee802154_llsec_key_id id
;
896 if (ieee802154_llsec_parse_key_id(info
, &id
))
899 return ops
->llsec
->del_key(dev
, &id
);
902 int ieee802154_llsec_del_key(struct sk_buff
*skb
, struct genl_info
*info
)
904 return ieee802154_nl_llsec_change(skb
, info
, llsec_remove_key
);
908 ieee802154_nl_fill_key(struct sk_buff
*msg
, u32 portid
, u32 seq
,
909 const struct ieee802154_llsec_key_entry
*key
,
910 const struct net_device
*dev
)
913 u32 commands
[256 / 32];
915 hdr
= genlmsg_put(msg
, 0, seq
, &nl802154_family
, NLM_F_MULTI
,
916 IEEE802154_LLSEC_LIST_KEY
);
920 if (nla_put_string(msg
, IEEE802154_ATTR_DEV_NAME
, dev
->name
) ||
921 nla_put_u32(msg
, IEEE802154_ATTR_DEV_INDEX
, dev
->ifindex
) ||
922 ieee802154_llsec_fill_key_id(msg
, &key
->id
) ||
923 nla_put_u8(msg
, IEEE802154_ATTR_LLSEC_KEY_USAGE_FRAME_TYPES
,
924 key
->key
->frame_types
))
925 goto nla_put_failure
;
927 if (key
->key
->frame_types
& BIT(IEEE802154_FC_TYPE_MAC_CMD
)) {
928 memset(commands
, 0, sizeof(commands
));
929 commands
[7] = key
->key
->cmd_frame_ids
;
930 if (nla_put(msg
, IEEE802154_ATTR_LLSEC_KEY_USAGE_COMMANDS
,
931 sizeof(commands
), commands
))
932 goto nla_put_failure
;
935 if (nla_put(msg
, IEEE802154_ATTR_LLSEC_KEY_BYTES
,
936 IEEE802154_LLSEC_KEY_SIZE
, key
->key
->key
))
937 goto nla_put_failure
;
939 genlmsg_end(msg
, hdr
);
943 genlmsg_cancel(msg
, hdr
);
948 static int llsec_iter_keys(struct llsec_dump_data
*data
)
950 struct ieee802154_llsec_key_entry
*pos
;
953 list_for_each_entry(pos
, &data
->table
->keys
, list
) {
954 if (idx
++ < data
->s_idx
)
957 if (ieee802154_nl_fill_key(data
->skb
, data
->portid
,
958 data
->nlmsg_seq
, pos
, data
->dev
)) {
969 int ieee802154_llsec_dump_keys(struct sk_buff
*skb
, struct netlink_callback
*cb
)
971 return ieee802154_llsec_dump_table(skb
, cb
, llsec_iter_keys
);
975 llsec_parse_dev(struct genl_info
*info
,
976 struct ieee802154_llsec_device
*dev
)
978 memset(dev
, 0, sizeof(*dev
));
980 if (!info
->attrs
[IEEE802154_ATTR_LLSEC_FRAME_COUNTER
] ||
981 !info
->attrs
[IEEE802154_ATTR_HW_ADDR
] ||
982 !info
->attrs
[IEEE802154_ATTR_LLSEC_DEV_OVERRIDE
] ||
983 !info
->attrs
[IEEE802154_ATTR_LLSEC_DEV_KEY_MODE
] ||
984 (!!info
->attrs
[IEEE802154_ATTR_PAN_ID
] !=
985 !!info
->attrs
[IEEE802154_ATTR_SHORT_ADDR
]))
988 if (info
->attrs
[IEEE802154_ATTR_PAN_ID
]) {
989 dev
->pan_id
= nla_get_shortaddr(info
->attrs
[IEEE802154_ATTR_PAN_ID
]);
990 dev
->short_addr
= nla_get_shortaddr(info
->attrs
[IEEE802154_ATTR_SHORT_ADDR
]);
992 dev
->short_addr
= cpu_to_le16(IEEE802154_ADDR_UNDEF
);
995 dev
->hwaddr
= nla_get_hwaddr(info
->attrs
[IEEE802154_ATTR_HW_ADDR
]);
996 dev
->frame_counter
= nla_get_u32(info
->attrs
[IEEE802154_ATTR_LLSEC_FRAME_COUNTER
]);
997 dev
->seclevel_exempt
= !!nla_get_u8(info
->attrs
[IEEE802154_ATTR_LLSEC_DEV_OVERRIDE
]);
998 dev
->key_mode
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_LLSEC_DEV_KEY_MODE
]);
1000 if (dev
->key_mode
>= __IEEE802154_LLSEC_DEVKEY_MAX
)
1006 static int llsec_add_dev(struct net_device
*dev
, struct genl_info
*info
)
1008 struct ieee802154_mlme_ops
*ops
= ieee802154_mlme_ops(dev
);
1009 struct ieee802154_llsec_device desc
;
1011 if (llsec_parse_dev(info
, &desc
))
1014 return ops
->llsec
->add_dev(dev
, &desc
);
1017 int ieee802154_llsec_add_dev(struct sk_buff
*skb
, struct genl_info
*info
)
1019 if ((info
->nlhdr
->nlmsg_flags
& (NLM_F_CREATE
| NLM_F_EXCL
)) !=
1020 (NLM_F_CREATE
| NLM_F_EXCL
))
1023 return ieee802154_nl_llsec_change(skb
, info
, llsec_add_dev
);
1026 static int llsec_del_dev(struct net_device
*dev
, struct genl_info
*info
)
1028 struct ieee802154_mlme_ops
*ops
= ieee802154_mlme_ops(dev
);
1031 if (!info
->attrs
[IEEE802154_ATTR_HW_ADDR
])
1034 devaddr
= nla_get_hwaddr(info
->attrs
[IEEE802154_ATTR_HW_ADDR
]);
1036 return ops
->llsec
->del_dev(dev
, devaddr
);
1039 int ieee802154_llsec_del_dev(struct sk_buff
*skb
, struct genl_info
*info
)
1041 return ieee802154_nl_llsec_change(skb
, info
, llsec_del_dev
);
1045 ieee802154_nl_fill_dev(struct sk_buff
*msg
, u32 portid
, u32 seq
,
1046 const struct ieee802154_llsec_device
*desc
,
1047 const struct net_device
*dev
)
1051 hdr
= genlmsg_put(msg
, 0, seq
, &nl802154_family
, NLM_F_MULTI
,
1052 IEEE802154_LLSEC_LIST_DEV
);
1056 if (nla_put_string(msg
, IEEE802154_ATTR_DEV_NAME
, dev
->name
) ||
1057 nla_put_u32(msg
, IEEE802154_ATTR_DEV_INDEX
, dev
->ifindex
) ||
1058 nla_put_shortaddr(msg
, IEEE802154_ATTR_PAN_ID
, desc
->pan_id
) ||
1059 nla_put_shortaddr(msg
, IEEE802154_ATTR_SHORT_ADDR
,
1060 desc
->short_addr
) ||
1061 nla_put_hwaddr(msg
, IEEE802154_ATTR_HW_ADDR
, desc
->hwaddr
,
1062 IEEE802154_ATTR_PAD
) ||
1063 nla_put_u32(msg
, IEEE802154_ATTR_LLSEC_FRAME_COUNTER
,
1064 desc
->frame_counter
) ||
1065 nla_put_u8(msg
, IEEE802154_ATTR_LLSEC_DEV_OVERRIDE
,
1066 desc
->seclevel_exempt
) ||
1067 nla_put_u8(msg
, IEEE802154_ATTR_LLSEC_DEV_KEY_MODE
, desc
->key_mode
))
1068 goto nla_put_failure
;
1070 genlmsg_end(msg
, hdr
);
1074 genlmsg_cancel(msg
, hdr
);
1079 static int llsec_iter_devs(struct llsec_dump_data
*data
)
1081 struct ieee802154_llsec_device
*pos
;
1082 int rc
= 0, idx
= 0;
1084 list_for_each_entry(pos
, &data
->table
->devices
, list
) {
1085 if (idx
++ < data
->s_idx
)
1088 if (ieee802154_nl_fill_dev(data
->skb
, data
->portid
,
1089 data
->nlmsg_seq
, pos
, data
->dev
)) {
1100 int ieee802154_llsec_dump_devs(struct sk_buff
*skb
, struct netlink_callback
*cb
)
1102 return ieee802154_llsec_dump_table(skb
, cb
, llsec_iter_devs
);
1105 static int llsec_add_devkey(struct net_device
*dev
, struct genl_info
*info
)
1107 struct ieee802154_mlme_ops
*ops
= ieee802154_mlme_ops(dev
);
1108 struct ieee802154_llsec_device_key key
;
1111 if (!info
->attrs
[IEEE802154_ATTR_LLSEC_FRAME_COUNTER
] ||
1112 !info
->attrs
[IEEE802154_ATTR_HW_ADDR
] ||
1113 ieee802154_llsec_parse_key_id(info
, &key
.key_id
))
1116 devaddr
= nla_get_hwaddr(info
->attrs
[IEEE802154_ATTR_HW_ADDR
]);
1117 key
.frame_counter
= nla_get_u32(info
->attrs
[IEEE802154_ATTR_LLSEC_FRAME_COUNTER
]);
1119 return ops
->llsec
->add_devkey(dev
, devaddr
, &key
);
1122 int ieee802154_llsec_add_devkey(struct sk_buff
*skb
, struct genl_info
*info
)
1124 if ((info
->nlhdr
->nlmsg_flags
& (NLM_F_CREATE
| NLM_F_EXCL
)) !=
1125 (NLM_F_CREATE
| NLM_F_EXCL
))
1128 return ieee802154_nl_llsec_change(skb
, info
, llsec_add_devkey
);
1131 static int llsec_del_devkey(struct net_device
*dev
, struct genl_info
*info
)
1133 struct ieee802154_mlme_ops
*ops
= ieee802154_mlme_ops(dev
);
1134 struct ieee802154_llsec_device_key key
;
1137 if (!info
->attrs
[IEEE802154_ATTR_HW_ADDR
] ||
1138 ieee802154_llsec_parse_key_id(info
, &key
.key_id
))
1141 devaddr
= nla_get_hwaddr(info
->attrs
[IEEE802154_ATTR_HW_ADDR
]);
1143 return ops
->llsec
->del_devkey(dev
, devaddr
, &key
);
1146 int ieee802154_llsec_del_devkey(struct sk_buff
*skb
, struct genl_info
*info
)
1148 return ieee802154_nl_llsec_change(skb
, info
, llsec_del_devkey
);
1152 ieee802154_nl_fill_devkey(struct sk_buff
*msg
, u32 portid
, u32 seq
,
1154 const struct ieee802154_llsec_device_key
*devkey
,
1155 const struct net_device
*dev
)
1159 hdr
= genlmsg_put(msg
, 0, seq
, &nl802154_family
, NLM_F_MULTI
,
1160 IEEE802154_LLSEC_LIST_DEVKEY
);
1164 if (nla_put_string(msg
, IEEE802154_ATTR_DEV_NAME
, dev
->name
) ||
1165 nla_put_u32(msg
, IEEE802154_ATTR_DEV_INDEX
, dev
->ifindex
) ||
1166 nla_put_hwaddr(msg
, IEEE802154_ATTR_HW_ADDR
, devaddr
,
1167 IEEE802154_ATTR_PAD
) ||
1168 nla_put_u32(msg
, IEEE802154_ATTR_LLSEC_FRAME_COUNTER
,
1169 devkey
->frame_counter
) ||
1170 ieee802154_llsec_fill_key_id(msg
, &devkey
->key_id
))
1171 goto nla_put_failure
;
1173 genlmsg_end(msg
, hdr
);
1177 genlmsg_cancel(msg
, hdr
);
1182 static int llsec_iter_devkeys(struct llsec_dump_data
*data
)
1184 struct ieee802154_llsec_device
*dpos
;
1185 struct ieee802154_llsec_device_key
*kpos
;
1186 int rc
= 0, idx
= 0, idx2
;
1188 list_for_each_entry(dpos
, &data
->table
->devices
, list
) {
1189 if (idx
++ < data
->s_idx
)
1194 list_for_each_entry(kpos
, &dpos
->keys
, list
) {
1195 if (idx2
++ < data
->s_idx2
)
1198 if (ieee802154_nl_fill_devkey(data
->skb
, data
->portid
,
1202 return rc
= -EMSGSIZE
;
1214 int ieee802154_llsec_dump_devkeys(struct sk_buff
*skb
,
1215 struct netlink_callback
*cb
)
1217 return ieee802154_llsec_dump_table(skb
, cb
, llsec_iter_devkeys
);
1221 llsec_parse_seclevel(struct genl_info
*info
,
1222 struct ieee802154_llsec_seclevel
*sl
)
1224 memset(sl
, 0, sizeof(*sl
));
1226 if (!info
->attrs
[IEEE802154_ATTR_LLSEC_FRAME_TYPE
] ||
1227 !info
->attrs
[IEEE802154_ATTR_LLSEC_SECLEVELS
] ||
1228 !info
->attrs
[IEEE802154_ATTR_LLSEC_DEV_OVERRIDE
])
1231 sl
->frame_type
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_LLSEC_FRAME_TYPE
]);
1232 if (sl
->frame_type
== IEEE802154_FC_TYPE_MAC_CMD
) {
1233 if (!info
->attrs
[IEEE802154_ATTR_LLSEC_CMD_FRAME_ID
])
1236 sl
->cmd_frame_id
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_LLSEC_CMD_FRAME_ID
]);
1239 sl
->sec_levels
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_LLSEC_SECLEVELS
]);
1240 sl
->device_override
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_LLSEC_DEV_OVERRIDE
]);
1245 static int llsec_add_seclevel(struct net_device
*dev
, struct genl_info
*info
)
1247 struct ieee802154_mlme_ops
*ops
= ieee802154_mlme_ops(dev
);
1248 struct ieee802154_llsec_seclevel sl
;
1250 if (llsec_parse_seclevel(info
, &sl
))
1253 return ops
->llsec
->add_seclevel(dev
, &sl
);
1256 int ieee802154_llsec_add_seclevel(struct sk_buff
*skb
, struct genl_info
*info
)
1258 if ((info
->nlhdr
->nlmsg_flags
& (NLM_F_CREATE
| NLM_F_EXCL
)) !=
1259 (NLM_F_CREATE
| NLM_F_EXCL
))
1262 return ieee802154_nl_llsec_change(skb
, info
, llsec_add_seclevel
);
1265 static int llsec_del_seclevel(struct net_device
*dev
, struct genl_info
*info
)
1267 struct ieee802154_mlme_ops
*ops
= ieee802154_mlme_ops(dev
);
1268 struct ieee802154_llsec_seclevel sl
;
1270 if (llsec_parse_seclevel(info
, &sl
))
1273 return ops
->llsec
->del_seclevel(dev
, &sl
);
1276 int ieee802154_llsec_del_seclevel(struct sk_buff
*skb
, struct genl_info
*info
)
1278 return ieee802154_nl_llsec_change(skb
, info
, llsec_del_seclevel
);
1282 ieee802154_nl_fill_seclevel(struct sk_buff
*msg
, u32 portid
, u32 seq
,
1283 const struct ieee802154_llsec_seclevel
*sl
,
1284 const struct net_device
*dev
)
1288 hdr
= genlmsg_put(msg
, 0, seq
, &nl802154_family
, NLM_F_MULTI
,
1289 IEEE802154_LLSEC_LIST_SECLEVEL
);
1293 if (nla_put_string(msg
, IEEE802154_ATTR_DEV_NAME
, dev
->name
) ||
1294 nla_put_u32(msg
, IEEE802154_ATTR_DEV_INDEX
, dev
->ifindex
) ||
1295 nla_put_u8(msg
, IEEE802154_ATTR_LLSEC_FRAME_TYPE
, sl
->frame_type
) ||
1296 nla_put_u8(msg
, IEEE802154_ATTR_LLSEC_SECLEVELS
, sl
->sec_levels
) ||
1297 nla_put_u8(msg
, IEEE802154_ATTR_LLSEC_DEV_OVERRIDE
,
1298 sl
->device_override
))
1299 goto nla_put_failure
;
1301 if (sl
->frame_type
== IEEE802154_FC_TYPE_MAC_CMD
&&
1302 nla_put_u8(msg
, IEEE802154_ATTR_LLSEC_CMD_FRAME_ID
,
1304 goto nla_put_failure
;
1306 genlmsg_end(msg
, hdr
);
1310 genlmsg_cancel(msg
, hdr
);
1315 static int llsec_iter_seclevels(struct llsec_dump_data
*data
)
1317 struct ieee802154_llsec_seclevel
*pos
;
1318 int rc
= 0, idx
= 0;
1320 list_for_each_entry(pos
, &data
->table
->security_levels
, list
) {
1321 if (idx
++ < data
->s_idx
)
1324 if (ieee802154_nl_fill_seclevel(data
->skb
, data
->portid
,
1325 data
->nlmsg_seq
, pos
,
1337 int ieee802154_llsec_dump_seclevels(struct sk_buff
*skb
,
1338 struct netlink_callback
*cb
)
1340 return ieee802154_llsec_dump_table(skb
, cb
, llsec_iter_seclevels
);