2 * Netlink inteface for IEEE 802.15.4 stack
4 * Copyright 2007, 2008 Siemens AG
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2
8 * as published by the Free Software Foundation.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
16 * Sergey Lapin <slapin@ossfans.org>
17 * Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
18 * Maxim Osipov <maxim.osipov@siemens.com>
21 #include <linux/gfp.h>
22 #include <linux/kernel.h>
23 #include <linux/if_arp.h>
24 #include <linux/netdevice.h>
25 #include <linux/ieee802154.h>
26 #include <net/netlink.h>
27 #include <net/genetlink.h>
29 #include <linux/nl802154.h>
30 #include <linux/export.h>
31 #include <net/af_ieee802154.h>
32 #include <net/ieee802154_netdev.h>
33 #include <net/cfg802154.h>
35 #include "ieee802154.h"
37 static int nla_put_hwaddr(struct sk_buff
*msg
, int type
, __le64 hwaddr
)
39 return nla_put_u64(msg
, type
, swab64((__force u64
)hwaddr
));
42 static __le64
nla_get_hwaddr(const struct nlattr
*nla
)
44 return ieee802154_devaddr_from_raw(nla_data(nla
));
47 static int nla_put_shortaddr(struct sk_buff
*msg
, int type
, __le16 addr
)
49 return nla_put_u16(msg
, type
, le16_to_cpu(addr
));
52 static __le16
nla_get_shortaddr(const struct nlattr
*nla
)
54 return cpu_to_le16(nla_get_u16(nla
));
57 static int ieee802154_nl_start_confirm(struct net_device
*dev
, u8 status
)
61 pr_debug("%s\n", __func__
);
63 msg
= ieee802154_nl_create(0, IEEE802154_START_CONF
);
67 if (nla_put_string(msg
, IEEE802154_ATTR_DEV_NAME
, dev
->name
) ||
68 nla_put_u32(msg
, IEEE802154_ATTR_DEV_INDEX
, dev
->ifindex
) ||
69 nla_put(msg
, IEEE802154_ATTR_HW_ADDR
, IEEE802154_ADDR_LEN
,
71 nla_put_u8(msg
, IEEE802154_ATTR_STATUS
, status
))
73 return ieee802154_nl_mcast(msg
, IEEE802154_COORD_MCGRP
);
79 EXPORT_SYMBOL(ieee802154_nl_start_confirm
);
81 static int ieee802154_nl_fill_iface(struct sk_buff
*msg
, u32 portid
,
82 u32 seq
, int flags
, struct net_device
*dev
)
86 struct ieee802154_mlme_ops
*ops
;
87 __le16 short_addr
, pan_id
;
89 pr_debug("%s\n", __func__
);
91 hdr
= genlmsg_put(msg
, 0, seq
, &nl802154_family
, flags
,
92 IEEE802154_LIST_IFACE
);
96 ops
= ieee802154_mlme_ops(dev
);
97 phy
= ops
->get_phy(dev
);
100 short_addr
= ops
->get_short_addr(dev
);
101 pan_id
= ops
->get_pan_id(dev
);
103 if (nla_put_string(msg
, IEEE802154_ATTR_DEV_NAME
, dev
->name
) ||
104 nla_put_string(msg
, IEEE802154_ATTR_PHY_NAME
, wpan_phy_name(phy
)) ||
105 nla_put_u32(msg
, IEEE802154_ATTR_DEV_INDEX
, dev
->ifindex
) ||
106 nla_put(msg
, IEEE802154_ATTR_HW_ADDR
, IEEE802154_ADDR_LEN
,
108 nla_put_shortaddr(msg
, IEEE802154_ATTR_SHORT_ADDR
, short_addr
) ||
109 nla_put_shortaddr(msg
, IEEE802154_ATTR_PAN_ID
, pan_id
))
110 goto nla_put_failure
;
112 if (ops
->get_mac_params
) {
113 struct ieee802154_mac_params params
;
115 ops
->get_mac_params(dev
, ¶ms
);
117 if (nla_put_s8(msg
, IEEE802154_ATTR_TXPOWER
,
118 params
.transmit_power
) ||
119 nla_put_u8(msg
, IEEE802154_ATTR_LBT_ENABLED
, params
.lbt
) ||
120 nla_put_u8(msg
, IEEE802154_ATTR_CCA_MODE
,
122 nla_put_s32(msg
, IEEE802154_ATTR_CCA_ED_LEVEL
,
123 params
.cca_ed_level
) ||
124 nla_put_u8(msg
, IEEE802154_ATTR_CSMA_RETRIES
,
125 params
.csma_retries
) ||
126 nla_put_u8(msg
, IEEE802154_ATTR_CSMA_MIN_BE
,
128 nla_put_u8(msg
, IEEE802154_ATTR_CSMA_MAX_BE
,
130 nla_put_s8(msg
, IEEE802154_ATTR_FRAME_RETRIES
,
131 params
.frame_retries
))
132 goto nla_put_failure
;
136 return genlmsg_end(msg
, hdr
);
140 genlmsg_cancel(msg
, hdr
);
145 /* Requests from userspace */
146 static struct net_device
*ieee802154_nl_get_dev(struct genl_info
*info
)
148 struct net_device
*dev
;
150 if (info
->attrs
[IEEE802154_ATTR_DEV_NAME
]) {
151 char name
[IFNAMSIZ
+ 1];
153 nla_strlcpy(name
, info
->attrs
[IEEE802154_ATTR_DEV_NAME
],
155 dev
= dev_get_by_name(&init_net
, name
);
156 } else if (info
->attrs
[IEEE802154_ATTR_DEV_INDEX
]) {
157 dev
= dev_get_by_index(&init_net
,
158 nla_get_u32(info
->attrs
[IEEE802154_ATTR_DEV_INDEX
]));
166 if (dev
->type
!= ARPHRD_IEEE802154
) {
174 int ieee802154_associate_req(struct sk_buff
*skb
, struct genl_info
*info
)
176 struct net_device
*dev
;
177 struct ieee802154_addr addr
;
179 int ret
= -EOPNOTSUPP
;
181 if (!info
->attrs
[IEEE802154_ATTR_CHANNEL
] ||
182 !info
->attrs
[IEEE802154_ATTR_COORD_PAN_ID
] ||
183 (!info
->attrs
[IEEE802154_ATTR_COORD_HW_ADDR
] &&
184 !info
->attrs
[IEEE802154_ATTR_COORD_SHORT_ADDR
]) ||
185 !info
->attrs
[IEEE802154_ATTR_CAPABILITY
])
188 dev
= ieee802154_nl_get_dev(info
);
191 if (!ieee802154_mlme_ops(dev
)->assoc_req
)
194 if (info
->attrs
[IEEE802154_ATTR_COORD_HW_ADDR
]) {
195 addr
.mode
= IEEE802154_ADDR_LONG
;
196 addr
.extended_addr
= nla_get_hwaddr(
197 info
->attrs
[IEEE802154_ATTR_COORD_HW_ADDR
]);
199 addr
.mode
= IEEE802154_ADDR_SHORT
;
200 addr
.short_addr
= nla_get_shortaddr(
201 info
->attrs
[IEEE802154_ATTR_COORD_SHORT_ADDR
]);
203 addr
.pan_id
= nla_get_shortaddr(
204 info
->attrs
[IEEE802154_ATTR_COORD_PAN_ID
]);
206 if (info
->attrs
[IEEE802154_ATTR_PAGE
])
207 page
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_PAGE
]);
211 ret
= ieee802154_mlme_ops(dev
)->assoc_req(dev
, &addr
,
212 nla_get_u8(info
->attrs
[IEEE802154_ATTR_CHANNEL
]),
214 nla_get_u8(info
->attrs
[IEEE802154_ATTR_CAPABILITY
]));
221 int ieee802154_associate_resp(struct sk_buff
*skb
, struct genl_info
*info
)
223 struct net_device
*dev
;
224 struct ieee802154_addr addr
;
225 int ret
= -EOPNOTSUPP
;
227 if (!info
->attrs
[IEEE802154_ATTR_STATUS
] ||
228 !info
->attrs
[IEEE802154_ATTR_DEST_HW_ADDR
] ||
229 !info
->attrs
[IEEE802154_ATTR_DEST_SHORT_ADDR
])
232 dev
= ieee802154_nl_get_dev(info
);
235 if (!ieee802154_mlme_ops(dev
)->assoc_resp
)
238 addr
.mode
= IEEE802154_ADDR_LONG
;
239 addr
.extended_addr
= nla_get_hwaddr(
240 info
->attrs
[IEEE802154_ATTR_DEST_HW_ADDR
]);
241 addr
.pan_id
= ieee802154_mlme_ops(dev
)->get_pan_id(dev
);
243 ret
= ieee802154_mlme_ops(dev
)->assoc_resp(dev
, &addr
,
244 nla_get_shortaddr(info
->attrs
[IEEE802154_ATTR_DEST_SHORT_ADDR
]),
245 nla_get_u8(info
->attrs
[IEEE802154_ATTR_STATUS
]));
252 int ieee802154_disassociate_req(struct sk_buff
*skb
, struct genl_info
*info
)
254 struct net_device
*dev
;
255 struct ieee802154_addr addr
;
256 int ret
= -EOPNOTSUPP
;
258 if ((!info
->attrs
[IEEE802154_ATTR_DEST_HW_ADDR
] &&
259 !info
->attrs
[IEEE802154_ATTR_DEST_SHORT_ADDR
]) ||
260 !info
->attrs
[IEEE802154_ATTR_REASON
])
263 dev
= ieee802154_nl_get_dev(info
);
266 if (!ieee802154_mlme_ops(dev
)->disassoc_req
)
269 if (info
->attrs
[IEEE802154_ATTR_DEST_HW_ADDR
]) {
270 addr
.mode
= IEEE802154_ADDR_LONG
;
271 addr
.extended_addr
= nla_get_hwaddr(
272 info
->attrs
[IEEE802154_ATTR_DEST_HW_ADDR
]);
274 addr
.mode
= IEEE802154_ADDR_SHORT
;
275 addr
.short_addr
= nla_get_shortaddr(
276 info
->attrs
[IEEE802154_ATTR_DEST_SHORT_ADDR
]);
278 addr
.pan_id
= ieee802154_mlme_ops(dev
)->get_pan_id(dev
);
280 ret
= ieee802154_mlme_ops(dev
)->disassoc_req(dev
, &addr
,
281 nla_get_u8(info
->attrs
[IEEE802154_ATTR_REASON
]));
288 /* PANid, channel, beacon_order = 15, superframe_order = 15,
289 * PAN_coordinator, battery_life_extension = 0,
290 * coord_realignment = 0, security_enable = 0
292 int ieee802154_start_req(struct sk_buff
*skb
, struct genl_info
*info
)
294 struct net_device
*dev
;
295 struct ieee802154_addr addr
;
297 u8 channel
, bcn_ord
, sf_ord
;
299 int pan_coord
, blx
, coord_realign
;
302 if (!info
->attrs
[IEEE802154_ATTR_COORD_PAN_ID
] ||
303 !info
->attrs
[IEEE802154_ATTR_COORD_SHORT_ADDR
] ||
304 !info
->attrs
[IEEE802154_ATTR_CHANNEL
] ||
305 !info
->attrs
[IEEE802154_ATTR_BCN_ORD
] ||
306 !info
->attrs
[IEEE802154_ATTR_SF_ORD
] ||
307 !info
->attrs
[IEEE802154_ATTR_PAN_COORD
] ||
308 !info
->attrs
[IEEE802154_ATTR_BAT_EXT
] ||
309 !info
->attrs
[IEEE802154_ATTR_COORD_REALIGN
]
313 dev
= ieee802154_nl_get_dev(info
);
317 if (netif_running(dev
))
320 if (!ieee802154_mlme_ops(dev
)->start_req
) {
325 addr
.mode
= IEEE802154_ADDR_SHORT
;
326 addr
.short_addr
= nla_get_shortaddr(
327 info
->attrs
[IEEE802154_ATTR_COORD_SHORT_ADDR
]);
328 addr
.pan_id
= nla_get_shortaddr(
329 info
->attrs
[IEEE802154_ATTR_COORD_PAN_ID
]);
331 channel
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_CHANNEL
]);
332 bcn_ord
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_BCN_ORD
]);
333 sf_ord
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_SF_ORD
]);
334 pan_coord
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_PAN_COORD
]);
335 blx
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_BAT_EXT
]);
336 coord_realign
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_COORD_REALIGN
]);
338 if (info
->attrs
[IEEE802154_ATTR_PAGE
])
339 page
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_PAGE
]);
344 if (addr
.short_addr
== cpu_to_le16(IEEE802154_ADDR_BROADCAST
)) {
345 ieee802154_nl_start_confirm(dev
, IEEE802154_NO_SHORT_ADDRESS
);
350 ret
= ieee802154_mlme_ops(dev
)->start_req(dev
, &addr
, channel
, page
,
351 bcn_ord
, sf_ord
, pan_coord
, blx
, coord_realign
);
353 /* FIXME: add validation for unused parameters to be sane
356 ieee802154_nl_start_confirm(dev
, IEEE802154_SUCCESS
);
363 int ieee802154_scan_req(struct sk_buff
*skb
, struct genl_info
*info
)
365 struct net_device
*dev
;
366 int ret
= -EOPNOTSUPP
;
372 if (!info
->attrs
[IEEE802154_ATTR_SCAN_TYPE
] ||
373 !info
->attrs
[IEEE802154_ATTR_CHANNELS
] ||
374 !info
->attrs
[IEEE802154_ATTR_DURATION
])
377 dev
= ieee802154_nl_get_dev(info
);
380 if (!ieee802154_mlme_ops(dev
)->scan_req
)
383 type
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_SCAN_TYPE
]);
384 channels
= nla_get_u32(info
->attrs
[IEEE802154_ATTR_CHANNELS
]);
385 duration
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_DURATION
]);
387 if (info
->attrs
[IEEE802154_ATTR_PAGE
])
388 page
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_PAGE
]);
393 ret
= ieee802154_mlme_ops(dev
)->scan_req(dev
, type
, channels
,
401 int ieee802154_list_iface(struct sk_buff
*skb
, struct genl_info
*info
)
403 /* Request for interface name, index, type, IEEE address,
404 * PAN Id, short address
407 struct net_device
*dev
= NULL
;
410 pr_debug("%s\n", __func__
);
412 dev
= ieee802154_nl_get_dev(info
);
416 msg
= nlmsg_new(NLMSG_DEFAULT_SIZE
, GFP_KERNEL
);
420 rc
= ieee802154_nl_fill_iface(msg
, info
->snd_portid
, info
->snd_seq
,
427 return genlmsg_reply(msg
, info
);
435 int ieee802154_dump_iface(struct sk_buff
*skb
, struct netlink_callback
*cb
)
437 struct net
*net
= sock_net(skb
->sk
);
438 struct net_device
*dev
;
440 int s_idx
= cb
->args
[0];
442 pr_debug("%s\n", __func__
);
445 for_each_netdev(net
, dev
) {
446 if (idx
< s_idx
|| (dev
->type
!= ARPHRD_IEEE802154
))
449 if (ieee802154_nl_fill_iface(skb
, NETLINK_CB(cb
->skb
).portid
,
451 NLM_F_MULTI
, dev
) < 0)
461 int ieee802154_set_macparams(struct sk_buff
*skb
, struct genl_info
*info
)
463 struct net_device
*dev
= NULL
;
464 struct ieee802154_mlme_ops
*ops
;
465 struct ieee802154_mac_params params
;
466 struct wpan_phy
*phy
;
469 pr_debug("%s\n", __func__
);
471 dev
= ieee802154_nl_get_dev(info
);
475 ops
= ieee802154_mlme_ops(dev
);
477 if (!ops
->get_mac_params
|| !ops
->set_mac_params
) {
482 if (netif_running(dev
)) {
487 if (!info
->attrs
[IEEE802154_ATTR_LBT_ENABLED
] &&
488 !info
->attrs
[IEEE802154_ATTR_CCA_MODE
] &&
489 !info
->attrs
[IEEE802154_ATTR_CCA_ED_LEVEL
] &&
490 !info
->attrs
[IEEE802154_ATTR_CSMA_RETRIES
] &&
491 !info
->attrs
[IEEE802154_ATTR_CSMA_MIN_BE
] &&
492 !info
->attrs
[IEEE802154_ATTR_CSMA_MAX_BE
] &&
493 !info
->attrs
[IEEE802154_ATTR_FRAME_RETRIES
])
496 phy
= ops
->get_phy(dev
);
498 ops
->get_mac_params(dev
, ¶ms
);
500 if (info
->attrs
[IEEE802154_ATTR_TXPOWER
])
501 params
.transmit_power
= nla_get_s8(info
->attrs
[IEEE802154_ATTR_TXPOWER
]);
503 if (info
->attrs
[IEEE802154_ATTR_LBT_ENABLED
])
504 params
.lbt
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_LBT_ENABLED
]);
506 if (info
->attrs
[IEEE802154_ATTR_CCA_MODE
])
507 params
.cca_mode
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_CCA_MODE
]);
509 if (info
->attrs
[IEEE802154_ATTR_CCA_ED_LEVEL
])
510 params
.cca_ed_level
= nla_get_s32(info
->attrs
[IEEE802154_ATTR_CCA_ED_LEVEL
]);
512 if (info
->attrs
[IEEE802154_ATTR_CSMA_RETRIES
])
513 params
.csma_retries
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_CSMA_RETRIES
]);
515 if (info
->attrs
[IEEE802154_ATTR_CSMA_MIN_BE
])
516 params
.min_be
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_CSMA_MIN_BE
]);
518 if (info
->attrs
[IEEE802154_ATTR_CSMA_MAX_BE
])
519 params
.max_be
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_CSMA_MAX_BE
]);
521 if (info
->attrs
[IEEE802154_ATTR_FRAME_RETRIES
])
522 params
.frame_retries
= nla_get_s8(info
->attrs
[IEEE802154_ATTR_FRAME_RETRIES
]);
524 rc
= ops
->set_mac_params(dev
, ¶ms
);
539 ieee802154_llsec_parse_key_id(struct genl_info
*info
,
540 struct ieee802154_llsec_key_id
*desc
)
542 memset(desc
, 0, sizeof(*desc
));
544 if (!info
->attrs
[IEEE802154_ATTR_LLSEC_KEY_MODE
])
547 desc
->mode
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_LLSEC_KEY_MODE
]);
549 if (desc
->mode
== IEEE802154_SCF_KEY_IMPLICIT
) {
550 if (!info
->attrs
[IEEE802154_ATTR_PAN_ID
] &&
551 !(info
->attrs
[IEEE802154_ATTR_SHORT_ADDR
] ||
552 info
->attrs
[IEEE802154_ATTR_HW_ADDR
]))
555 desc
->device_addr
.pan_id
= nla_get_shortaddr(info
->attrs
[IEEE802154_ATTR_PAN_ID
]);
557 if (info
->attrs
[IEEE802154_ATTR_SHORT_ADDR
]) {
558 desc
->device_addr
.mode
= IEEE802154_ADDR_SHORT
;
559 desc
->device_addr
.short_addr
= nla_get_shortaddr(info
->attrs
[IEEE802154_ATTR_SHORT_ADDR
]);
561 desc
->device_addr
.mode
= IEEE802154_ADDR_LONG
;
562 desc
->device_addr
.extended_addr
= nla_get_hwaddr(info
->attrs
[IEEE802154_ATTR_HW_ADDR
]);
566 if (desc
->mode
!= IEEE802154_SCF_KEY_IMPLICIT
&&
567 !info
->attrs
[IEEE802154_ATTR_LLSEC_KEY_ID
])
570 if (desc
->mode
== IEEE802154_SCF_KEY_SHORT_INDEX
&&
571 !info
->attrs
[IEEE802154_ATTR_LLSEC_KEY_SOURCE_SHORT
])
574 if (desc
->mode
== IEEE802154_SCF_KEY_HW_INDEX
&&
575 !info
->attrs
[IEEE802154_ATTR_LLSEC_KEY_SOURCE_EXTENDED
])
578 if (desc
->mode
!= IEEE802154_SCF_KEY_IMPLICIT
)
579 desc
->id
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_LLSEC_KEY_ID
]);
581 switch (desc
->mode
) {
582 case IEEE802154_SCF_KEY_SHORT_INDEX
:
584 u32 source
= nla_get_u32(info
->attrs
[IEEE802154_ATTR_LLSEC_KEY_SOURCE_SHORT
]);
586 desc
->short_source
= cpu_to_le32(source
);
589 case IEEE802154_SCF_KEY_HW_INDEX
:
590 desc
->extended_source
= nla_get_hwaddr(info
->attrs
[IEEE802154_ATTR_LLSEC_KEY_SOURCE_EXTENDED
]);
598 ieee802154_llsec_fill_key_id(struct sk_buff
*msg
,
599 const struct ieee802154_llsec_key_id
*desc
)
601 if (nla_put_u8(msg
, IEEE802154_ATTR_LLSEC_KEY_MODE
, desc
->mode
))
604 if (desc
->mode
== IEEE802154_SCF_KEY_IMPLICIT
) {
605 if (nla_put_shortaddr(msg
, IEEE802154_ATTR_PAN_ID
,
606 desc
->device_addr
.pan_id
))
609 if (desc
->device_addr
.mode
== IEEE802154_ADDR_SHORT
&&
610 nla_put_shortaddr(msg
, IEEE802154_ATTR_SHORT_ADDR
,
611 desc
->device_addr
.short_addr
))
614 if (desc
->device_addr
.mode
== IEEE802154_ADDR_LONG
&&
615 nla_put_hwaddr(msg
, IEEE802154_ATTR_HW_ADDR
,
616 desc
->device_addr
.extended_addr
))
620 if (desc
->mode
!= IEEE802154_SCF_KEY_IMPLICIT
&&
621 nla_put_u8(msg
, IEEE802154_ATTR_LLSEC_KEY_ID
, desc
->id
))
624 if (desc
->mode
== IEEE802154_SCF_KEY_SHORT_INDEX
&&
625 nla_put_u32(msg
, IEEE802154_ATTR_LLSEC_KEY_SOURCE_SHORT
,
626 le32_to_cpu(desc
->short_source
)))
629 if (desc
->mode
== IEEE802154_SCF_KEY_HW_INDEX
&&
630 nla_put_hwaddr(msg
, IEEE802154_ATTR_LLSEC_KEY_SOURCE_EXTENDED
,
631 desc
->extended_source
))
637 int ieee802154_llsec_getparams(struct sk_buff
*skb
, struct genl_info
*info
)
640 struct net_device
*dev
= NULL
;
642 struct ieee802154_mlme_ops
*ops
;
644 struct ieee802154_llsec_params params
;
646 pr_debug("%s\n", __func__
);
648 dev
= ieee802154_nl_get_dev(info
);
652 ops
= ieee802154_mlme_ops(dev
);
658 msg
= nlmsg_new(NLMSG_DEFAULT_SIZE
, GFP_KERNEL
);
662 hdr
= genlmsg_put(msg
, 0, info
->snd_seq
, &nl802154_family
, 0,
663 IEEE802154_LLSEC_GETPARAMS
);
667 rc
= ops
->llsec
->get_params(dev
, ¶ms
);
671 if (nla_put_string(msg
, IEEE802154_ATTR_DEV_NAME
, dev
->name
) ||
672 nla_put_u32(msg
, IEEE802154_ATTR_DEV_INDEX
, dev
->ifindex
) ||
673 nla_put_u8(msg
, IEEE802154_ATTR_LLSEC_ENABLED
, params
.enabled
) ||
674 nla_put_u8(msg
, IEEE802154_ATTR_LLSEC_SECLEVEL
, params
.out_level
) ||
675 nla_put_u32(msg
, IEEE802154_ATTR_LLSEC_FRAME_COUNTER
,
676 be32_to_cpu(params
.frame_counter
)) ||
677 ieee802154_llsec_fill_key_id(msg
, ¶ms
.out_key
))
682 return ieee802154_nl_reply(msg
, info
);
690 int ieee802154_llsec_setparams(struct sk_buff
*skb
, struct genl_info
*info
)
692 struct net_device
*dev
= NULL
;
694 struct ieee802154_mlme_ops
*ops
;
695 struct ieee802154_llsec_params params
;
698 pr_debug("%s\n", __func__
);
700 dev
= ieee802154_nl_get_dev(info
);
704 if (!info
->attrs
[IEEE802154_ATTR_LLSEC_ENABLED
] &&
705 !info
->attrs
[IEEE802154_ATTR_LLSEC_KEY_MODE
] &&
706 !info
->attrs
[IEEE802154_ATTR_LLSEC_SECLEVEL
])
709 ops
= ieee802154_mlme_ops(dev
);
715 if (info
->attrs
[IEEE802154_ATTR_LLSEC_SECLEVEL
] &&
716 nla_get_u8(info
->attrs
[IEEE802154_ATTR_LLSEC_SECLEVEL
]) > 7)
719 if (info
->attrs
[IEEE802154_ATTR_LLSEC_ENABLED
]) {
720 params
.enabled
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_LLSEC_ENABLED
]);
721 changed
|= IEEE802154_LLSEC_PARAM_ENABLED
;
724 if (info
->attrs
[IEEE802154_ATTR_LLSEC_KEY_MODE
]) {
725 if (ieee802154_llsec_parse_key_id(info
, ¶ms
.out_key
))
728 changed
|= IEEE802154_LLSEC_PARAM_OUT_KEY
;
731 if (info
->attrs
[IEEE802154_ATTR_LLSEC_SECLEVEL
]) {
732 params
.out_level
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_LLSEC_SECLEVEL
]);
733 changed
|= IEEE802154_LLSEC_PARAM_OUT_LEVEL
;
736 if (info
->attrs
[IEEE802154_ATTR_LLSEC_FRAME_COUNTER
]) {
737 u32 fc
= nla_get_u32(info
->attrs
[IEEE802154_ATTR_LLSEC_FRAME_COUNTER
]);
739 params
.frame_counter
= cpu_to_be32(fc
);
740 changed
|= IEEE802154_LLSEC_PARAM_FRAME_COUNTER
;
743 rc
= ops
->llsec
->set_params(dev
, ¶ms
, changed
);
755 struct llsec_dump_data
{
760 struct net_device
*dev
;
761 struct ieee802154_mlme_ops
*ops
;
762 struct ieee802154_llsec_table
*table
;
766 ieee802154_llsec_dump_table(struct sk_buff
*skb
, struct netlink_callback
*cb
,
767 int (*step
)(struct llsec_dump_data
*))
769 struct net
*net
= sock_net(skb
->sk
);
770 struct net_device
*dev
;
771 struct llsec_dump_data data
;
773 int first_dev
= cb
->args
[0];
776 for_each_netdev(net
, dev
) {
777 if (idx
< first_dev
|| dev
->type
!= ARPHRD_IEEE802154
)
780 data
.ops
= ieee802154_mlme_ops(dev
);
781 if (!data
.ops
->llsec
)
785 data
.s_idx
= cb
->args
[1];
786 data
.s_idx2
= cb
->args
[2];
788 data
.portid
= NETLINK_CB(cb
->skb
).portid
;
789 data
.nlmsg_seq
= cb
->nlh
->nlmsg_seq
;
791 data
.ops
->llsec
->lock_table(dev
);
792 data
.ops
->llsec
->get_table(data
.dev
, &data
.table
);
794 data
.ops
->llsec
->unlock_table(dev
);
808 ieee802154_nl_llsec_change(struct sk_buff
*skb
, struct genl_info
*info
,
809 int (*fn
)(struct net_device
*, struct genl_info
*))
811 struct net_device
*dev
= NULL
;
814 dev
= ieee802154_nl_get_dev(info
);
818 if (!ieee802154_mlme_ops(dev
)->llsec
)
830 ieee802154_llsec_parse_key(struct genl_info
*info
,
831 struct ieee802154_llsec_key
*key
)
834 u32 commands
[256 / 32];
836 memset(key
, 0, sizeof(*key
));
838 if (!info
->attrs
[IEEE802154_ATTR_LLSEC_KEY_USAGE_FRAME_TYPES
] ||
839 !info
->attrs
[IEEE802154_ATTR_LLSEC_KEY_BYTES
])
842 frames
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_LLSEC_KEY_USAGE_FRAME_TYPES
]);
843 if ((frames
& BIT(IEEE802154_FC_TYPE_MAC_CMD
)) &&
844 !info
->attrs
[IEEE802154_ATTR_LLSEC_KEY_USAGE_COMMANDS
])
847 if (info
->attrs
[IEEE802154_ATTR_LLSEC_KEY_USAGE_COMMANDS
]) {
849 info
->attrs
[IEEE802154_ATTR_LLSEC_KEY_USAGE_COMMANDS
],
852 if (commands
[0] || commands
[1] || commands
[2] || commands
[3] ||
853 commands
[4] || commands
[5] || commands
[6] ||
854 commands
[7] >= BIT(IEEE802154_CMD_GTS_REQ
+ 1))
857 key
->cmd_frame_ids
= commands
[7];
860 key
->frame_types
= frames
;
862 nla_memcpy(key
->key
, info
->attrs
[IEEE802154_ATTR_LLSEC_KEY_BYTES
],
863 IEEE802154_LLSEC_KEY_SIZE
);
868 static int llsec_add_key(struct net_device
*dev
, struct genl_info
*info
)
870 struct ieee802154_mlme_ops
*ops
= ieee802154_mlme_ops(dev
);
871 struct ieee802154_llsec_key key
;
872 struct ieee802154_llsec_key_id id
;
874 if (ieee802154_llsec_parse_key(info
, &key
) ||
875 ieee802154_llsec_parse_key_id(info
, &id
))
878 return ops
->llsec
->add_key(dev
, &id
, &key
);
881 int ieee802154_llsec_add_key(struct sk_buff
*skb
, struct genl_info
*info
)
883 if ((info
->nlhdr
->nlmsg_flags
& (NLM_F_CREATE
| NLM_F_EXCL
)) !=
884 (NLM_F_CREATE
| NLM_F_EXCL
))
887 return ieee802154_nl_llsec_change(skb
, info
, llsec_add_key
);
890 static int llsec_remove_key(struct net_device
*dev
, struct genl_info
*info
)
892 struct ieee802154_mlme_ops
*ops
= ieee802154_mlme_ops(dev
);
893 struct ieee802154_llsec_key_id id
;
895 if (ieee802154_llsec_parse_key_id(info
, &id
))
898 return ops
->llsec
->del_key(dev
, &id
);
901 int ieee802154_llsec_del_key(struct sk_buff
*skb
, struct genl_info
*info
)
903 return ieee802154_nl_llsec_change(skb
, info
, llsec_remove_key
);
907 ieee802154_nl_fill_key(struct sk_buff
*msg
, u32 portid
, u32 seq
,
908 const struct ieee802154_llsec_key_entry
*key
,
909 const struct net_device
*dev
)
912 u32 commands
[256 / 32];
914 hdr
= genlmsg_put(msg
, 0, seq
, &nl802154_family
, NLM_F_MULTI
,
915 IEEE802154_LLSEC_LIST_KEY
);
919 if (nla_put_string(msg
, IEEE802154_ATTR_DEV_NAME
, dev
->name
) ||
920 nla_put_u32(msg
, IEEE802154_ATTR_DEV_INDEX
, dev
->ifindex
) ||
921 ieee802154_llsec_fill_key_id(msg
, &key
->id
) ||
922 nla_put_u8(msg
, IEEE802154_ATTR_LLSEC_KEY_USAGE_FRAME_TYPES
,
923 key
->key
->frame_types
))
924 goto nla_put_failure
;
926 if (key
->key
->frame_types
& BIT(IEEE802154_FC_TYPE_MAC_CMD
)) {
927 memset(commands
, 0, sizeof(commands
));
928 commands
[7] = key
->key
->cmd_frame_ids
;
929 if (nla_put(msg
, IEEE802154_ATTR_LLSEC_KEY_USAGE_COMMANDS
,
930 sizeof(commands
), commands
))
931 goto nla_put_failure
;
934 if (nla_put(msg
, IEEE802154_ATTR_LLSEC_KEY_BYTES
,
935 IEEE802154_LLSEC_KEY_SIZE
, key
->key
->key
))
936 goto nla_put_failure
;
938 genlmsg_end(msg
, hdr
);
942 genlmsg_cancel(msg
, hdr
);
947 static int llsec_iter_keys(struct llsec_dump_data
*data
)
949 struct ieee802154_llsec_key_entry
*pos
;
952 list_for_each_entry(pos
, &data
->table
->keys
, list
) {
953 if (idx
++ < data
->s_idx
)
956 if (ieee802154_nl_fill_key(data
->skb
, data
->portid
,
957 data
->nlmsg_seq
, pos
, data
->dev
)) {
968 int ieee802154_llsec_dump_keys(struct sk_buff
*skb
, struct netlink_callback
*cb
)
970 return ieee802154_llsec_dump_table(skb
, cb
, llsec_iter_keys
);
976 llsec_parse_dev(struct genl_info
*info
,
977 struct ieee802154_llsec_device
*dev
)
979 memset(dev
, 0, sizeof(*dev
));
981 if (!info
->attrs
[IEEE802154_ATTR_LLSEC_FRAME_COUNTER
] ||
982 !info
->attrs
[IEEE802154_ATTR_HW_ADDR
] ||
983 !info
->attrs
[IEEE802154_ATTR_LLSEC_DEV_OVERRIDE
] ||
984 !info
->attrs
[IEEE802154_ATTR_LLSEC_DEV_KEY_MODE
] ||
985 (!!info
->attrs
[IEEE802154_ATTR_PAN_ID
] !=
986 !!info
->attrs
[IEEE802154_ATTR_SHORT_ADDR
]))
989 if (info
->attrs
[IEEE802154_ATTR_PAN_ID
]) {
990 dev
->pan_id
= nla_get_shortaddr(info
->attrs
[IEEE802154_ATTR_PAN_ID
]);
991 dev
->short_addr
= nla_get_shortaddr(info
->attrs
[IEEE802154_ATTR_SHORT_ADDR
]);
993 dev
->short_addr
= cpu_to_le16(IEEE802154_ADDR_UNDEF
);
996 dev
->hwaddr
= nla_get_hwaddr(info
->attrs
[IEEE802154_ATTR_HW_ADDR
]);
997 dev
->frame_counter
= nla_get_u32(info
->attrs
[IEEE802154_ATTR_LLSEC_FRAME_COUNTER
]);
998 dev
->seclevel_exempt
= !!nla_get_u8(info
->attrs
[IEEE802154_ATTR_LLSEC_DEV_OVERRIDE
]);
999 dev
->key_mode
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_LLSEC_DEV_KEY_MODE
]);
1001 if (dev
->key_mode
>= __IEEE802154_LLSEC_DEVKEY_MAX
)
1007 static int llsec_add_dev(struct net_device
*dev
, struct genl_info
*info
)
1009 struct ieee802154_mlme_ops
*ops
= ieee802154_mlme_ops(dev
);
1010 struct ieee802154_llsec_device desc
;
1012 if (llsec_parse_dev(info
, &desc
))
1015 return ops
->llsec
->add_dev(dev
, &desc
);
1018 int ieee802154_llsec_add_dev(struct sk_buff
*skb
, struct genl_info
*info
)
1020 if ((info
->nlhdr
->nlmsg_flags
& (NLM_F_CREATE
| NLM_F_EXCL
)) !=
1021 (NLM_F_CREATE
| NLM_F_EXCL
))
1024 return ieee802154_nl_llsec_change(skb
, info
, llsec_add_dev
);
1027 static int llsec_del_dev(struct net_device
*dev
, struct genl_info
*info
)
1029 struct ieee802154_mlme_ops
*ops
= ieee802154_mlme_ops(dev
);
1032 if (!info
->attrs
[IEEE802154_ATTR_HW_ADDR
])
1035 devaddr
= nla_get_hwaddr(info
->attrs
[IEEE802154_ATTR_HW_ADDR
]);
1037 return ops
->llsec
->del_dev(dev
, devaddr
);
1040 int ieee802154_llsec_del_dev(struct sk_buff
*skb
, struct genl_info
*info
)
1042 return ieee802154_nl_llsec_change(skb
, info
, llsec_del_dev
);
1046 ieee802154_nl_fill_dev(struct sk_buff
*msg
, u32 portid
, u32 seq
,
1047 const struct ieee802154_llsec_device
*desc
,
1048 const struct net_device
*dev
)
1052 hdr
= genlmsg_put(msg
, 0, seq
, &nl802154_family
, NLM_F_MULTI
,
1053 IEEE802154_LLSEC_LIST_DEV
);
1057 if (nla_put_string(msg
, IEEE802154_ATTR_DEV_NAME
, dev
->name
) ||
1058 nla_put_u32(msg
, IEEE802154_ATTR_DEV_INDEX
, dev
->ifindex
) ||
1059 nla_put_shortaddr(msg
, IEEE802154_ATTR_PAN_ID
, desc
->pan_id
) ||
1060 nla_put_shortaddr(msg
, IEEE802154_ATTR_SHORT_ADDR
,
1061 desc
->short_addr
) ||
1062 nla_put_hwaddr(msg
, IEEE802154_ATTR_HW_ADDR
, desc
->hwaddr
) ||
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
);
1107 static int llsec_add_devkey(struct net_device
*dev
, struct genl_info
*info
)
1109 struct ieee802154_mlme_ops
*ops
= ieee802154_mlme_ops(dev
);
1110 struct ieee802154_llsec_device_key key
;
1113 if (!info
->attrs
[IEEE802154_ATTR_LLSEC_FRAME_COUNTER
] ||
1114 !info
->attrs
[IEEE802154_ATTR_HW_ADDR
] ||
1115 ieee802154_llsec_parse_key_id(info
, &key
.key_id
))
1118 devaddr
= nla_get_hwaddr(info
->attrs
[IEEE802154_ATTR_HW_ADDR
]);
1119 key
.frame_counter
= nla_get_u32(info
->attrs
[IEEE802154_ATTR_LLSEC_FRAME_COUNTER
]);
1121 return ops
->llsec
->add_devkey(dev
, devaddr
, &key
);
1124 int ieee802154_llsec_add_devkey(struct sk_buff
*skb
, struct genl_info
*info
)
1126 if ((info
->nlhdr
->nlmsg_flags
& (NLM_F_CREATE
| NLM_F_EXCL
)) !=
1127 (NLM_F_CREATE
| NLM_F_EXCL
))
1130 return ieee802154_nl_llsec_change(skb
, info
, llsec_add_devkey
);
1133 static int llsec_del_devkey(struct net_device
*dev
, struct genl_info
*info
)
1135 struct ieee802154_mlme_ops
*ops
= ieee802154_mlme_ops(dev
);
1136 struct ieee802154_llsec_device_key key
;
1139 if (!info
->attrs
[IEEE802154_ATTR_HW_ADDR
] ||
1140 ieee802154_llsec_parse_key_id(info
, &key
.key_id
))
1143 devaddr
= nla_get_hwaddr(info
->attrs
[IEEE802154_ATTR_HW_ADDR
]);
1145 return ops
->llsec
->del_devkey(dev
, devaddr
, &key
);
1148 int ieee802154_llsec_del_devkey(struct sk_buff
*skb
, struct genl_info
*info
)
1150 return ieee802154_nl_llsec_change(skb
, info
, llsec_del_devkey
);
1154 ieee802154_nl_fill_devkey(struct sk_buff
*msg
, u32 portid
, u32 seq
,
1156 const struct ieee802154_llsec_device_key
*devkey
,
1157 const struct net_device
*dev
)
1161 hdr
= genlmsg_put(msg
, 0, seq
, &nl802154_family
, NLM_F_MULTI
,
1162 IEEE802154_LLSEC_LIST_DEVKEY
);
1166 if (nla_put_string(msg
, IEEE802154_ATTR_DEV_NAME
, dev
->name
) ||
1167 nla_put_u32(msg
, IEEE802154_ATTR_DEV_INDEX
, dev
->ifindex
) ||
1168 nla_put_hwaddr(msg
, IEEE802154_ATTR_HW_ADDR
, devaddr
) ||
1169 nla_put_u32(msg
, IEEE802154_ATTR_LLSEC_FRAME_COUNTER
,
1170 devkey
->frame_counter
) ||
1171 ieee802154_llsec_fill_key_id(msg
, &devkey
->key_id
))
1172 goto nla_put_failure
;
1174 genlmsg_end(msg
, hdr
);
1178 genlmsg_cancel(msg
, hdr
);
1183 static int llsec_iter_devkeys(struct llsec_dump_data
*data
)
1185 struct ieee802154_llsec_device
*dpos
;
1186 struct ieee802154_llsec_device_key
*kpos
;
1187 int rc
= 0, idx
= 0, idx2
;
1189 list_for_each_entry(dpos
, &data
->table
->devices
, list
) {
1190 if (idx
++ < data
->s_idx
)
1195 list_for_each_entry(kpos
, &dpos
->keys
, list
) {
1196 if (idx2
++ < data
->s_idx2
)
1199 if (ieee802154_nl_fill_devkey(data
->skb
, data
->portid
,
1203 return rc
= -EMSGSIZE
;
1215 int ieee802154_llsec_dump_devkeys(struct sk_buff
*skb
,
1216 struct netlink_callback
*cb
)
1218 return ieee802154_llsec_dump_table(skb
, cb
, llsec_iter_devkeys
);
1224 llsec_parse_seclevel(struct genl_info
*info
,
1225 struct ieee802154_llsec_seclevel
*sl
)
1227 memset(sl
, 0, sizeof(*sl
));
1229 if (!info
->attrs
[IEEE802154_ATTR_LLSEC_FRAME_TYPE
] ||
1230 !info
->attrs
[IEEE802154_ATTR_LLSEC_SECLEVELS
] ||
1231 !info
->attrs
[IEEE802154_ATTR_LLSEC_DEV_OVERRIDE
])
1234 sl
->frame_type
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_LLSEC_FRAME_TYPE
]);
1235 if (sl
->frame_type
== IEEE802154_FC_TYPE_MAC_CMD
) {
1236 if (!info
->attrs
[IEEE802154_ATTR_LLSEC_CMD_FRAME_ID
])
1239 sl
->cmd_frame_id
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_LLSEC_CMD_FRAME_ID
]);
1242 sl
->sec_levels
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_LLSEC_SECLEVELS
]);
1243 sl
->device_override
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_LLSEC_DEV_OVERRIDE
]);
1248 static int llsec_add_seclevel(struct net_device
*dev
, struct genl_info
*info
)
1250 struct ieee802154_mlme_ops
*ops
= ieee802154_mlme_ops(dev
);
1251 struct ieee802154_llsec_seclevel sl
;
1253 if (llsec_parse_seclevel(info
, &sl
))
1256 return ops
->llsec
->add_seclevel(dev
, &sl
);
1259 int ieee802154_llsec_add_seclevel(struct sk_buff
*skb
, struct genl_info
*info
)
1261 if ((info
->nlhdr
->nlmsg_flags
& (NLM_F_CREATE
| NLM_F_EXCL
)) !=
1262 (NLM_F_CREATE
| NLM_F_EXCL
))
1265 return ieee802154_nl_llsec_change(skb
, info
, llsec_add_seclevel
);
1268 static int llsec_del_seclevel(struct net_device
*dev
, struct genl_info
*info
)
1270 struct ieee802154_mlme_ops
*ops
= ieee802154_mlme_ops(dev
);
1271 struct ieee802154_llsec_seclevel sl
;
1273 if (llsec_parse_seclevel(info
, &sl
))
1276 return ops
->llsec
->del_seclevel(dev
, &sl
);
1279 int ieee802154_llsec_del_seclevel(struct sk_buff
*skb
, struct genl_info
*info
)
1281 return ieee802154_nl_llsec_change(skb
, info
, llsec_del_seclevel
);
1285 ieee802154_nl_fill_seclevel(struct sk_buff
*msg
, u32 portid
, u32 seq
,
1286 const struct ieee802154_llsec_seclevel
*sl
,
1287 const struct net_device
*dev
)
1291 hdr
= genlmsg_put(msg
, 0, seq
, &nl802154_family
, NLM_F_MULTI
,
1292 IEEE802154_LLSEC_LIST_SECLEVEL
);
1296 if (nla_put_string(msg
, IEEE802154_ATTR_DEV_NAME
, dev
->name
) ||
1297 nla_put_u32(msg
, IEEE802154_ATTR_DEV_INDEX
, dev
->ifindex
) ||
1298 nla_put_u8(msg
, IEEE802154_ATTR_LLSEC_FRAME_TYPE
, sl
->frame_type
) ||
1299 nla_put_u8(msg
, IEEE802154_ATTR_LLSEC_SECLEVELS
, sl
->sec_levels
) ||
1300 nla_put_u8(msg
, IEEE802154_ATTR_LLSEC_DEV_OVERRIDE
,
1301 sl
->device_override
))
1302 goto nla_put_failure
;
1304 if (sl
->frame_type
== IEEE802154_FC_TYPE_MAC_CMD
&&
1305 nla_put_u8(msg
, IEEE802154_ATTR_LLSEC_CMD_FRAME_ID
,
1307 goto nla_put_failure
;
1309 genlmsg_end(msg
, hdr
);
1313 genlmsg_cancel(msg
, hdr
);
1318 static int llsec_iter_seclevels(struct llsec_dump_data
*data
)
1320 struct ieee802154_llsec_seclevel
*pos
;
1321 int rc
= 0, idx
= 0;
1323 list_for_each_entry(pos
, &data
->table
->security_levels
, list
) {
1324 if (idx
++ < data
->s_idx
)
1327 if (ieee802154_nl_fill_seclevel(data
->skb
, data
->portid
,
1328 data
->nlmsg_seq
, pos
,
1340 int ieee802154_llsec_dump_seclevels(struct sk_buff
*skb
,
1341 struct netlink_callback
*cb
)
1343 return ieee802154_llsec_dump_table(skb
, cb
, llsec_iter_seclevels
);