2 * Netlink interface 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
,
40 return nla_put_u64_64bit(msg
, type
, swab64((__force u64
)hwaddr
),
44 static __le64
nla_get_hwaddr(const struct nlattr
*nla
)
46 return ieee802154_devaddr_from_raw(nla_data(nla
));
49 static int nla_put_shortaddr(struct sk_buff
*msg
, int type
, __le16 addr
)
51 return nla_put_u16(msg
, type
, le16_to_cpu(addr
));
54 static __le16
nla_get_shortaddr(const struct nlattr
*nla
)
56 return cpu_to_le16(nla_get_u16(nla
));
59 static int ieee802154_nl_start_confirm(struct net_device
*dev
, u8 status
)
63 pr_debug("%s\n", __func__
);
65 msg
= ieee802154_nl_create(0, IEEE802154_START_CONF
);
69 if (nla_put_string(msg
, IEEE802154_ATTR_DEV_NAME
, dev
->name
) ||
70 nla_put_u32(msg
, IEEE802154_ATTR_DEV_INDEX
, dev
->ifindex
) ||
71 nla_put(msg
, IEEE802154_ATTR_HW_ADDR
, IEEE802154_ADDR_LEN
,
73 nla_put_u8(msg
, IEEE802154_ATTR_STATUS
, status
))
75 return ieee802154_nl_mcast(msg
, IEEE802154_COORD_MCGRP
);
82 static int ieee802154_nl_fill_iface(struct sk_buff
*msg
, u32 portid
,
83 u32 seq
, int flags
, struct net_device
*dev
)
87 struct ieee802154_mlme_ops
*ops
;
88 __le16 short_addr
, pan_id
;
90 pr_debug("%s\n", __func__
);
92 hdr
= genlmsg_put(msg
, 0, seq
, &nl802154_family
, flags
,
93 IEEE802154_LIST_IFACE
);
97 ops
= ieee802154_mlme_ops(dev
);
98 phy
= dev
->ieee802154_ptr
->wpan_phy
;
100 get_device(&phy
->dev
);
103 short_addr
= dev
->ieee802154_ptr
->short_addr
;
104 pan_id
= dev
->ieee802154_ptr
->pan_id
;
107 if (nla_put_string(msg
, IEEE802154_ATTR_DEV_NAME
, dev
->name
) ||
108 nla_put_string(msg
, IEEE802154_ATTR_PHY_NAME
, wpan_phy_name(phy
)) ||
109 nla_put_u32(msg
, IEEE802154_ATTR_DEV_INDEX
, dev
->ifindex
) ||
110 nla_put(msg
, IEEE802154_ATTR_HW_ADDR
, IEEE802154_ADDR_LEN
,
112 nla_put_shortaddr(msg
, IEEE802154_ATTR_SHORT_ADDR
, short_addr
) ||
113 nla_put_shortaddr(msg
, IEEE802154_ATTR_PAN_ID
, pan_id
))
114 goto nla_put_failure
;
116 if (ops
->get_mac_params
) {
117 struct ieee802154_mac_params params
;
120 ops
->get_mac_params(dev
, ¶ms
);
123 if (nla_put_s8(msg
, IEEE802154_ATTR_TXPOWER
,
124 params
.transmit_power
/ 100) ||
125 nla_put_u8(msg
, IEEE802154_ATTR_LBT_ENABLED
, params
.lbt
) ||
126 nla_put_u8(msg
, IEEE802154_ATTR_CCA_MODE
,
128 nla_put_s32(msg
, IEEE802154_ATTR_CCA_ED_LEVEL
,
129 params
.cca_ed_level
/ 100) ||
130 nla_put_u8(msg
, IEEE802154_ATTR_CSMA_RETRIES
,
131 params
.csma_retries
) ||
132 nla_put_u8(msg
, IEEE802154_ATTR_CSMA_MIN_BE
,
134 nla_put_u8(msg
, IEEE802154_ATTR_CSMA_MAX_BE
,
136 nla_put_s8(msg
, IEEE802154_ATTR_FRAME_RETRIES
,
137 params
.frame_retries
))
138 goto nla_put_failure
;
142 genlmsg_end(msg
, hdr
);
147 genlmsg_cancel(msg
, hdr
);
152 /* Requests from userspace */
153 static struct net_device
*ieee802154_nl_get_dev(struct genl_info
*info
)
155 struct net_device
*dev
;
157 if (info
->attrs
[IEEE802154_ATTR_DEV_NAME
]) {
158 char name
[IFNAMSIZ
+ 1];
160 nla_strlcpy(name
, info
->attrs
[IEEE802154_ATTR_DEV_NAME
],
162 dev
= dev_get_by_name(&init_net
, name
);
163 } else if (info
->attrs
[IEEE802154_ATTR_DEV_INDEX
]) {
164 dev
= dev_get_by_index(&init_net
,
165 nla_get_u32(info
->attrs
[IEEE802154_ATTR_DEV_INDEX
]));
173 if (dev
->type
!= ARPHRD_IEEE802154
) {
181 int ieee802154_associate_req(struct sk_buff
*skb
, struct genl_info
*info
)
183 struct net_device
*dev
;
184 struct ieee802154_addr addr
;
186 int ret
= -EOPNOTSUPP
;
188 if (!info
->attrs
[IEEE802154_ATTR_CHANNEL
] ||
189 !info
->attrs
[IEEE802154_ATTR_COORD_PAN_ID
] ||
190 (!info
->attrs
[IEEE802154_ATTR_COORD_HW_ADDR
] &&
191 !info
->attrs
[IEEE802154_ATTR_COORD_SHORT_ADDR
]) ||
192 !info
->attrs
[IEEE802154_ATTR_CAPABILITY
])
195 dev
= ieee802154_nl_get_dev(info
);
198 if (!ieee802154_mlme_ops(dev
)->assoc_req
)
201 if (info
->attrs
[IEEE802154_ATTR_COORD_HW_ADDR
]) {
202 addr
.mode
= IEEE802154_ADDR_LONG
;
203 addr
.extended_addr
= nla_get_hwaddr(
204 info
->attrs
[IEEE802154_ATTR_COORD_HW_ADDR
]);
206 addr
.mode
= IEEE802154_ADDR_SHORT
;
207 addr
.short_addr
= nla_get_shortaddr(
208 info
->attrs
[IEEE802154_ATTR_COORD_SHORT_ADDR
]);
210 addr
.pan_id
= nla_get_shortaddr(
211 info
->attrs
[IEEE802154_ATTR_COORD_PAN_ID
]);
213 if (info
->attrs
[IEEE802154_ATTR_PAGE
])
214 page
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_PAGE
]);
218 ret
= ieee802154_mlme_ops(dev
)->assoc_req(dev
, &addr
,
219 nla_get_u8(info
->attrs
[IEEE802154_ATTR_CHANNEL
]),
221 nla_get_u8(info
->attrs
[IEEE802154_ATTR_CAPABILITY
]));
228 int ieee802154_associate_resp(struct sk_buff
*skb
, struct genl_info
*info
)
230 struct net_device
*dev
;
231 struct ieee802154_addr addr
;
232 int ret
= -EOPNOTSUPP
;
234 if (!info
->attrs
[IEEE802154_ATTR_STATUS
] ||
235 !info
->attrs
[IEEE802154_ATTR_DEST_HW_ADDR
] ||
236 !info
->attrs
[IEEE802154_ATTR_DEST_SHORT_ADDR
])
239 dev
= ieee802154_nl_get_dev(info
);
242 if (!ieee802154_mlme_ops(dev
)->assoc_resp
)
245 addr
.mode
= IEEE802154_ADDR_LONG
;
246 addr
.extended_addr
= nla_get_hwaddr(
247 info
->attrs
[IEEE802154_ATTR_DEST_HW_ADDR
]);
249 addr
.pan_id
= dev
->ieee802154_ptr
->pan_id
;
252 ret
= ieee802154_mlme_ops(dev
)->assoc_resp(dev
, &addr
,
253 nla_get_shortaddr(info
->attrs
[IEEE802154_ATTR_DEST_SHORT_ADDR
]),
254 nla_get_u8(info
->attrs
[IEEE802154_ATTR_STATUS
]));
261 int ieee802154_disassociate_req(struct sk_buff
*skb
, struct genl_info
*info
)
263 struct net_device
*dev
;
264 struct ieee802154_addr addr
;
265 int ret
= -EOPNOTSUPP
;
267 if ((!info
->attrs
[IEEE802154_ATTR_DEST_HW_ADDR
] &&
268 !info
->attrs
[IEEE802154_ATTR_DEST_SHORT_ADDR
]) ||
269 !info
->attrs
[IEEE802154_ATTR_REASON
])
272 dev
= ieee802154_nl_get_dev(info
);
275 if (!ieee802154_mlme_ops(dev
)->disassoc_req
)
278 if (info
->attrs
[IEEE802154_ATTR_DEST_HW_ADDR
]) {
279 addr
.mode
= IEEE802154_ADDR_LONG
;
280 addr
.extended_addr
= nla_get_hwaddr(
281 info
->attrs
[IEEE802154_ATTR_DEST_HW_ADDR
]);
283 addr
.mode
= IEEE802154_ADDR_SHORT
;
284 addr
.short_addr
= nla_get_shortaddr(
285 info
->attrs
[IEEE802154_ATTR_DEST_SHORT_ADDR
]);
288 addr
.pan_id
= dev
->ieee802154_ptr
->pan_id
;
291 ret
= ieee802154_mlme_ops(dev
)->disassoc_req(dev
, &addr
,
292 nla_get_u8(info
->attrs
[IEEE802154_ATTR_REASON
]));
299 /* PANid, channel, beacon_order = 15, superframe_order = 15,
300 * PAN_coordinator, battery_life_extension = 0,
301 * coord_realignment = 0, security_enable = 0
303 int ieee802154_start_req(struct sk_buff
*skb
, struct genl_info
*info
)
305 struct net_device
*dev
;
306 struct ieee802154_addr addr
;
308 u8 channel
, bcn_ord
, sf_ord
;
310 int pan_coord
, blx
, coord_realign
;
313 if (!info
->attrs
[IEEE802154_ATTR_COORD_PAN_ID
] ||
314 !info
->attrs
[IEEE802154_ATTR_COORD_SHORT_ADDR
] ||
315 !info
->attrs
[IEEE802154_ATTR_CHANNEL
] ||
316 !info
->attrs
[IEEE802154_ATTR_BCN_ORD
] ||
317 !info
->attrs
[IEEE802154_ATTR_SF_ORD
] ||
318 !info
->attrs
[IEEE802154_ATTR_PAN_COORD
] ||
319 !info
->attrs
[IEEE802154_ATTR_BAT_EXT
] ||
320 !info
->attrs
[IEEE802154_ATTR_COORD_REALIGN
]
324 dev
= ieee802154_nl_get_dev(info
);
328 if (netif_running(dev
))
331 if (!ieee802154_mlme_ops(dev
)->start_req
) {
336 addr
.mode
= IEEE802154_ADDR_SHORT
;
337 addr
.short_addr
= nla_get_shortaddr(
338 info
->attrs
[IEEE802154_ATTR_COORD_SHORT_ADDR
]);
339 addr
.pan_id
= nla_get_shortaddr(
340 info
->attrs
[IEEE802154_ATTR_COORD_PAN_ID
]);
342 channel
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_CHANNEL
]);
343 bcn_ord
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_BCN_ORD
]);
344 sf_ord
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_SF_ORD
]);
345 pan_coord
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_PAN_COORD
]);
346 blx
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_BAT_EXT
]);
347 coord_realign
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_COORD_REALIGN
]);
349 if (info
->attrs
[IEEE802154_ATTR_PAGE
])
350 page
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_PAGE
]);
354 if (addr
.short_addr
== cpu_to_le16(IEEE802154_ADDR_BROADCAST
)) {
355 ieee802154_nl_start_confirm(dev
, IEEE802154_NO_SHORT_ADDRESS
);
361 ret
= ieee802154_mlme_ops(dev
)->start_req(dev
, &addr
, channel
, page
,
362 bcn_ord
, sf_ord
, pan_coord
, blx
, coord_realign
);
365 /* FIXME: add validation for unused parameters to be sane
368 ieee802154_nl_start_confirm(dev
, IEEE802154_SUCCESS
);
375 int ieee802154_scan_req(struct sk_buff
*skb
, struct genl_info
*info
)
377 struct net_device
*dev
;
378 int ret
= -EOPNOTSUPP
;
384 if (!info
->attrs
[IEEE802154_ATTR_SCAN_TYPE
] ||
385 !info
->attrs
[IEEE802154_ATTR_CHANNELS
] ||
386 !info
->attrs
[IEEE802154_ATTR_DURATION
])
389 dev
= ieee802154_nl_get_dev(info
);
392 if (!ieee802154_mlme_ops(dev
)->scan_req
)
395 type
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_SCAN_TYPE
]);
396 channels
= nla_get_u32(info
->attrs
[IEEE802154_ATTR_CHANNELS
]);
397 duration
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_DURATION
]);
399 if (info
->attrs
[IEEE802154_ATTR_PAGE
])
400 page
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_PAGE
]);
404 ret
= ieee802154_mlme_ops(dev
)->scan_req(dev
, type
, channels
,
412 int ieee802154_list_iface(struct sk_buff
*skb
, struct genl_info
*info
)
414 /* Request for interface name, index, type, IEEE address,
415 * PAN Id, short address
418 struct net_device
*dev
= NULL
;
421 pr_debug("%s\n", __func__
);
423 dev
= ieee802154_nl_get_dev(info
);
427 msg
= nlmsg_new(NLMSG_DEFAULT_SIZE
, GFP_KERNEL
);
431 rc
= ieee802154_nl_fill_iface(msg
, info
->snd_portid
, info
->snd_seq
,
438 return genlmsg_reply(msg
, info
);
446 int ieee802154_dump_iface(struct sk_buff
*skb
, struct netlink_callback
*cb
)
448 struct net
*net
= sock_net(skb
->sk
);
449 struct net_device
*dev
;
451 int s_idx
= cb
->args
[0];
453 pr_debug("%s\n", __func__
);
456 for_each_netdev(net
, dev
) {
457 if (idx
< s_idx
|| dev
->type
!= ARPHRD_IEEE802154
)
460 if (ieee802154_nl_fill_iface(skb
, NETLINK_CB(cb
->skb
).portid
,
462 NLM_F_MULTI
, dev
) < 0)
472 int ieee802154_set_macparams(struct sk_buff
*skb
, struct genl_info
*info
)
474 struct net_device
*dev
= NULL
;
475 struct ieee802154_mlme_ops
*ops
;
476 struct ieee802154_mac_params params
;
477 struct wpan_phy
*phy
;
480 pr_debug("%s\n", __func__
);
482 dev
= ieee802154_nl_get_dev(info
);
486 ops
= ieee802154_mlme_ops(dev
);
488 if (!ops
->get_mac_params
|| !ops
->set_mac_params
) {
493 if (netif_running(dev
)) {
498 if (!info
->attrs
[IEEE802154_ATTR_LBT_ENABLED
] &&
499 !info
->attrs
[IEEE802154_ATTR_CCA_MODE
] &&
500 !info
->attrs
[IEEE802154_ATTR_CCA_ED_LEVEL
] &&
501 !info
->attrs
[IEEE802154_ATTR_CSMA_RETRIES
] &&
502 !info
->attrs
[IEEE802154_ATTR_CSMA_MIN_BE
] &&
503 !info
->attrs
[IEEE802154_ATTR_CSMA_MAX_BE
] &&
504 !info
->attrs
[IEEE802154_ATTR_FRAME_RETRIES
])
507 phy
= dev
->ieee802154_ptr
->wpan_phy
;
508 get_device(&phy
->dev
);
511 ops
->get_mac_params(dev
, ¶ms
);
513 if (info
->attrs
[IEEE802154_ATTR_TXPOWER
])
514 params
.transmit_power
= nla_get_s8(info
->attrs
[IEEE802154_ATTR_TXPOWER
]) * 100;
516 if (info
->attrs
[IEEE802154_ATTR_LBT_ENABLED
])
517 params
.lbt
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_LBT_ENABLED
]);
519 if (info
->attrs
[IEEE802154_ATTR_CCA_MODE
])
520 params
.cca
.mode
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_CCA_MODE
]);
522 if (info
->attrs
[IEEE802154_ATTR_CCA_ED_LEVEL
])
523 params
.cca_ed_level
= nla_get_s32(info
->attrs
[IEEE802154_ATTR_CCA_ED_LEVEL
]) * 100;
525 if (info
->attrs
[IEEE802154_ATTR_CSMA_RETRIES
])
526 params
.csma_retries
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_CSMA_RETRIES
]);
528 if (info
->attrs
[IEEE802154_ATTR_CSMA_MIN_BE
])
529 params
.min_be
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_CSMA_MIN_BE
]);
531 if (info
->attrs
[IEEE802154_ATTR_CSMA_MAX_BE
])
532 params
.max_be
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_CSMA_MAX_BE
]);
534 if (info
->attrs
[IEEE802154_ATTR_FRAME_RETRIES
])
535 params
.frame_retries
= nla_get_s8(info
->attrs
[IEEE802154_ATTR_FRAME_RETRIES
]);
537 rc
= ops
->set_mac_params(dev
, ¶ms
);
551 ieee802154_llsec_parse_key_id(struct genl_info
*info
,
552 struct ieee802154_llsec_key_id
*desc
)
554 memset(desc
, 0, sizeof(*desc
));
556 if (!info
->attrs
[IEEE802154_ATTR_LLSEC_KEY_MODE
])
559 desc
->mode
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_LLSEC_KEY_MODE
]);
561 if (desc
->mode
== IEEE802154_SCF_KEY_IMPLICIT
) {
562 if (!info
->attrs
[IEEE802154_ATTR_PAN_ID
] &&
563 !(info
->attrs
[IEEE802154_ATTR_SHORT_ADDR
] ||
564 info
->attrs
[IEEE802154_ATTR_HW_ADDR
]))
567 desc
->device_addr
.pan_id
= nla_get_shortaddr(info
->attrs
[IEEE802154_ATTR_PAN_ID
]);
569 if (info
->attrs
[IEEE802154_ATTR_SHORT_ADDR
]) {
570 desc
->device_addr
.mode
= IEEE802154_ADDR_SHORT
;
571 desc
->device_addr
.short_addr
= nla_get_shortaddr(info
->attrs
[IEEE802154_ATTR_SHORT_ADDR
]);
573 desc
->device_addr
.mode
= IEEE802154_ADDR_LONG
;
574 desc
->device_addr
.extended_addr
= nla_get_hwaddr(info
->attrs
[IEEE802154_ATTR_HW_ADDR
]);
578 if (desc
->mode
!= IEEE802154_SCF_KEY_IMPLICIT
&&
579 !info
->attrs
[IEEE802154_ATTR_LLSEC_KEY_ID
])
582 if (desc
->mode
== IEEE802154_SCF_KEY_SHORT_INDEX
&&
583 !info
->attrs
[IEEE802154_ATTR_LLSEC_KEY_SOURCE_SHORT
])
586 if (desc
->mode
== IEEE802154_SCF_KEY_HW_INDEX
&&
587 !info
->attrs
[IEEE802154_ATTR_LLSEC_KEY_SOURCE_EXTENDED
])
590 if (desc
->mode
!= IEEE802154_SCF_KEY_IMPLICIT
)
591 desc
->id
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_LLSEC_KEY_ID
]);
593 switch (desc
->mode
) {
594 case IEEE802154_SCF_KEY_SHORT_INDEX
:
596 u32 source
= nla_get_u32(info
->attrs
[IEEE802154_ATTR_LLSEC_KEY_SOURCE_SHORT
]);
598 desc
->short_source
= cpu_to_le32(source
);
601 case IEEE802154_SCF_KEY_HW_INDEX
:
602 desc
->extended_source
= nla_get_hwaddr(info
->attrs
[IEEE802154_ATTR_LLSEC_KEY_SOURCE_EXTENDED
]);
610 ieee802154_llsec_fill_key_id(struct sk_buff
*msg
,
611 const struct ieee802154_llsec_key_id
*desc
)
613 if (nla_put_u8(msg
, IEEE802154_ATTR_LLSEC_KEY_MODE
, desc
->mode
))
616 if (desc
->mode
== IEEE802154_SCF_KEY_IMPLICIT
) {
617 if (nla_put_shortaddr(msg
, IEEE802154_ATTR_PAN_ID
,
618 desc
->device_addr
.pan_id
))
621 if (desc
->device_addr
.mode
== IEEE802154_ADDR_SHORT
&&
622 nla_put_shortaddr(msg
, IEEE802154_ATTR_SHORT_ADDR
,
623 desc
->device_addr
.short_addr
))
626 if (desc
->device_addr
.mode
== IEEE802154_ADDR_LONG
&&
627 nla_put_hwaddr(msg
, IEEE802154_ATTR_HW_ADDR
,
628 desc
->device_addr
.extended_addr
,
629 IEEE802154_ATTR_PAD
))
633 if (desc
->mode
!= IEEE802154_SCF_KEY_IMPLICIT
&&
634 nla_put_u8(msg
, IEEE802154_ATTR_LLSEC_KEY_ID
, desc
->id
))
637 if (desc
->mode
== IEEE802154_SCF_KEY_SHORT_INDEX
&&
638 nla_put_u32(msg
, IEEE802154_ATTR_LLSEC_KEY_SOURCE_SHORT
,
639 le32_to_cpu(desc
->short_source
)))
642 if (desc
->mode
== IEEE802154_SCF_KEY_HW_INDEX
&&
643 nla_put_hwaddr(msg
, IEEE802154_ATTR_LLSEC_KEY_SOURCE_EXTENDED
,
644 desc
->extended_source
, IEEE802154_ATTR_PAD
))
650 int ieee802154_llsec_getparams(struct sk_buff
*skb
, struct genl_info
*info
)
653 struct net_device
*dev
= NULL
;
655 struct ieee802154_mlme_ops
*ops
;
657 struct ieee802154_llsec_params params
;
659 pr_debug("%s\n", __func__
);
661 dev
= ieee802154_nl_get_dev(info
);
665 ops
= ieee802154_mlme_ops(dev
);
671 msg
= nlmsg_new(NLMSG_DEFAULT_SIZE
, GFP_KERNEL
);
675 hdr
= genlmsg_put(msg
, 0, info
->snd_seq
, &nl802154_family
, 0,
676 IEEE802154_LLSEC_GETPARAMS
);
680 rc
= ops
->llsec
->get_params(dev
, ¶ms
);
684 if (nla_put_string(msg
, IEEE802154_ATTR_DEV_NAME
, dev
->name
) ||
685 nla_put_u32(msg
, IEEE802154_ATTR_DEV_INDEX
, dev
->ifindex
) ||
686 nla_put_u8(msg
, IEEE802154_ATTR_LLSEC_ENABLED
, params
.enabled
) ||
687 nla_put_u8(msg
, IEEE802154_ATTR_LLSEC_SECLEVEL
, params
.out_level
) ||
688 nla_put_u32(msg
, IEEE802154_ATTR_LLSEC_FRAME_COUNTER
,
689 be32_to_cpu(params
.frame_counter
)) ||
690 ieee802154_llsec_fill_key_id(msg
, ¶ms
.out_key
))
695 return ieee802154_nl_reply(msg
, info
);
703 int ieee802154_llsec_setparams(struct sk_buff
*skb
, struct genl_info
*info
)
705 struct net_device
*dev
= NULL
;
707 struct ieee802154_mlme_ops
*ops
;
708 struct ieee802154_llsec_params params
;
711 pr_debug("%s\n", __func__
);
713 dev
= ieee802154_nl_get_dev(info
);
717 if (!info
->attrs
[IEEE802154_ATTR_LLSEC_ENABLED
] &&
718 !info
->attrs
[IEEE802154_ATTR_LLSEC_KEY_MODE
] &&
719 !info
->attrs
[IEEE802154_ATTR_LLSEC_SECLEVEL
])
722 ops
= ieee802154_mlme_ops(dev
);
728 if (info
->attrs
[IEEE802154_ATTR_LLSEC_SECLEVEL
] &&
729 nla_get_u8(info
->attrs
[IEEE802154_ATTR_LLSEC_SECLEVEL
]) > 7)
732 if (info
->attrs
[IEEE802154_ATTR_LLSEC_ENABLED
]) {
733 params
.enabled
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_LLSEC_ENABLED
]);
734 changed
|= IEEE802154_LLSEC_PARAM_ENABLED
;
737 if (info
->attrs
[IEEE802154_ATTR_LLSEC_KEY_MODE
]) {
738 if (ieee802154_llsec_parse_key_id(info
, ¶ms
.out_key
))
741 changed
|= IEEE802154_LLSEC_PARAM_OUT_KEY
;
744 if (info
->attrs
[IEEE802154_ATTR_LLSEC_SECLEVEL
]) {
745 params
.out_level
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_LLSEC_SECLEVEL
]);
746 changed
|= IEEE802154_LLSEC_PARAM_OUT_LEVEL
;
749 if (info
->attrs
[IEEE802154_ATTR_LLSEC_FRAME_COUNTER
]) {
750 u32 fc
= nla_get_u32(info
->attrs
[IEEE802154_ATTR_LLSEC_FRAME_COUNTER
]);
752 params
.frame_counter
= cpu_to_be32(fc
);
753 changed
|= IEEE802154_LLSEC_PARAM_FRAME_COUNTER
;
756 rc
= ops
->llsec
->set_params(dev
, ¶ms
, changed
);
766 struct llsec_dump_data
{
771 struct net_device
*dev
;
772 struct ieee802154_mlme_ops
*ops
;
773 struct ieee802154_llsec_table
*table
;
777 ieee802154_llsec_dump_table(struct sk_buff
*skb
, struct netlink_callback
*cb
,
778 int (*step
)(struct llsec_dump_data
*))
780 struct net
*net
= sock_net(skb
->sk
);
781 struct net_device
*dev
;
782 struct llsec_dump_data data
;
784 int first_dev
= cb
->args
[0];
787 for_each_netdev(net
, dev
) {
788 if (idx
< first_dev
|| dev
->type
!= ARPHRD_IEEE802154
)
791 data
.ops
= ieee802154_mlme_ops(dev
);
792 if (!data
.ops
->llsec
)
796 data
.s_idx
= cb
->args
[1];
797 data
.s_idx2
= cb
->args
[2];
799 data
.portid
= NETLINK_CB(cb
->skb
).portid
;
800 data
.nlmsg_seq
= cb
->nlh
->nlmsg_seq
;
802 data
.ops
->llsec
->lock_table(dev
);
803 data
.ops
->llsec
->get_table(data
.dev
, &data
.table
);
805 data
.ops
->llsec
->unlock_table(dev
);
819 ieee802154_nl_llsec_change(struct sk_buff
*skb
, struct genl_info
*info
,
820 int (*fn
)(struct net_device
*, struct genl_info
*))
822 struct net_device
*dev
= NULL
;
825 dev
= ieee802154_nl_get_dev(info
);
829 if (!ieee802154_mlme_ops(dev
)->llsec
)
839 ieee802154_llsec_parse_key(struct genl_info
*info
,
840 struct ieee802154_llsec_key
*key
)
843 u32 commands
[256 / 32];
845 memset(key
, 0, sizeof(*key
));
847 if (!info
->attrs
[IEEE802154_ATTR_LLSEC_KEY_USAGE_FRAME_TYPES
] ||
848 !info
->attrs
[IEEE802154_ATTR_LLSEC_KEY_BYTES
])
851 frames
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_LLSEC_KEY_USAGE_FRAME_TYPES
]);
852 if ((frames
& BIT(IEEE802154_FC_TYPE_MAC_CMD
)) &&
853 !info
->attrs
[IEEE802154_ATTR_LLSEC_KEY_USAGE_COMMANDS
])
856 if (info
->attrs
[IEEE802154_ATTR_LLSEC_KEY_USAGE_COMMANDS
]) {
858 info
->attrs
[IEEE802154_ATTR_LLSEC_KEY_USAGE_COMMANDS
],
861 if (commands
[0] || commands
[1] || commands
[2] || commands
[3] ||
862 commands
[4] || commands
[5] || commands
[6] ||
863 commands
[7] >= BIT(IEEE802154_CMD_GTS_REQ
+ 1))
866 key
->cmd_frame_ids
= commands
[7];
869 key
->frame_types
= frames
;
871 nla_memcpy(key
->key
, info
->attrs
[IEEE802154_ATTR_LLSEC_KEY_BYTES
],
872 IEEE802154_LLSEC_KEY_SIZE
);
877 static int llsec_add_key(struct net_device
*dev
, struct genl_info
*info
)
879 struct ieee802154_mlme_ops
*ops
= ieee802154_mlme_ops(dev
);
880 struct ieee802154_llsec_key key
;
881 struct ieee802154_llsec_key_id id
;
883 if (ieee802154_llsec_parse_key(info
, &key
) ||
884 ieee802154_llsec_parse_key_id(info
, &id
))
887 return ops
->llsec
->add_key(dev
, &id
, &key
);
890 int ieee802154_llsec_add_key(struct sk_buff
*skb
, struct genl_info
*info
)
892 if ((info
->nlhdr
->nlmsg_flags
& (NLM_F_CREATE
| NLM_F_EXCL
)) !=
893 (NLM_F_CREATE
| NLM_F_EXCL
))
896 return ieee802154_nl_llsec_change(skb
, info
, llsec_add_key
);
899 static int llsec_remove_key(struct net_device
*dev
, struct genl_info
*info
)
901 struct ieee802154_mlme_ops
*ops
= ieee802154_mlme_ops(dev
);
902 struct ieee802154_llsec_key_id id
;
904 if (ieee802154_llsec_parse_key_id(info
, &id
))
907 return ops
->llsec
->del_key(dev
, &id
);
910 int ieee802154_llsec_del_key(struct sk_buff
*skb
, struct genl_info
*info
)
912 return ieee802154_nl_llsec_change(skb
, info
, llsec_remove_key
);
916 ieee802154_nl_fill_key(struct sk_buff
*msg
, u32 portid
, u32 seq
,
917 const struct ieee802154_llsec_key_entry
*key
,
918 const struct net_device
*dev
)
921 u32 commands
[256 / 32];
923 hdr
= genlmsg_put(msg
, 0, seq
, &nl802154_family
, NLM_F_MULTI
,
924 IEEE802154_LLSEC_LIST_KEY
);
928 if (nla_put_string(msg
, IEEE802154_ATTR_DEV_NAME
, dev
->name
) ||
929 nla_put_u32(msg
, IEEE802154_ATTR_DEV_INDEX
, dev
->ifindex
) ||
930 ieee802154_llsec_fill_key_id(msg
, &key
->id
) ||
931 nla_put_u8(msg
, IEEE802154_ATTR_LLSEC_KEY_USAGE_FRAME_TYPES
,
932 key
->key
->frame_types
))
933 goto nla_put_failure
;
935 if (key
->key
->frame_types
& BIT(IEEE802154_FC_TYPE_MAC_CMD
)) {
936 memset(commands
, 0, sizeof(commands
));
937 commands
[7] = key
->key
->cmd_frame_ids
;
938 if (nla_put(msg
, IEEE802154_ATTR_LLSEC_KEY_USAGE_COMMANDS
,
939 sizeof(commands
), commands
))
940 goto nla_put_failure
;
943 if (nla_put(msg
, IEEE802154_ATTR_LLSEC_KEY_BYTES
,
944 IEEE802154_LLSEC_KEY_SIZE
, key
->key
->key
))
945 goto nla_put_failure
;
947 genlmsg_end(msg
, hdr
);
951 genlmsg_cancel(msg
, hdr
);
956 static int llsec_iter_keys(struct llsec_dump_data
*data
)
958 struct ieee802154_llsec_key_entry
*pos
;
961 list_for_each_entry(pos
, &data
->table
->keys
, list
) {
962 if (idx
++ < data
->s_idx
)
965 if (ieee802154_nl_fill_key(data
->skb
, data
->portid
,
966 data
->nlmsg_seq
, pos
, data
->dev
)) {
977 int ieee802154_llsec_dump_keys(struct sk_buff
*skb
, struct netlink_callback
*cb
)
979 return ieee802154_llsec_dump_table(skb
, cb
, llsec_iter_keys
);
983 llsec_parse_dev(struct genl_info
*info
,
984 struct ieee802154_llsec_device
*dev
)
986 memset(dev
, 0, sizeof(*dev
));
988 if (!info
->attrs
[IEEE802154_ATTR_LLSEC_FRAME_COUNTER
] ||
989 !info
->attrs
[IEEE802154_ATTR_HW_ADDR
] ||
990 !info
->attrs
[IEEE802154_ATTR_LLSEC_DEV_OVERRIDE
] ||
991 !info
->attrs
[IEEE802154_ATTR_LLSEC_DEV_KEY_MODE
] ||
992 (!!info
->attrs
[IEEE802154_ATTR_PAN_ID
] !=
993 !!info
->attrs
[IEEE802154_ATTR_SHORT_ADDR
]))
996 if (info
->attrs
[IEEE802154_ATTR_PAN_ID
]) {
997 dev
->pan_id
= nla_get_shortaddr(info
->attrs
[IEEE802154_ATTR_PAN_ID
]);
998 dev
->short_addr
= nla_get_shortaddr(info
->attrs
[IEEE802154_ATTR_SHORT_ADDR
]);
1000 dev
->short_addr
= cpu_to_le16(IEEE802154_ADDR_UNDEF
);
1003 dev
->hwaddr
= nla_get_hwaddr(info
->attrs
[IEEE802154_ATTR_HW_ADDR
]);
1004 dev
->frame_counter
= nla_get_u32(info
->attrs
[IEEE802154_ATTR_LLSEC_FRAME_COUNTER
]);
1005 dev
->seclevel_exempt
= !!nla_get_u8(info
->attrs
[IEEE802154_ATTR_LLSEC_DEV_OVERRIDE
]);
1006 dev
->key_mode
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_LLSEC_DEV_KEY_MODE
]);
1008 if (dev
->key_mode
>= __IEEE802154_LLSEC_DEVKEY_MAX
)
1014 static int llsec_add_dev(struct net_device
*dev
, struct genl_info
*info
)
1016 struct ieee802154_mlme_ops
*ops
= ieee802154_mlme_ops(dev
);
1017 struct ieee802154_llsec_device desc
;
1019 if (llsec_parse_dev(info
, &desc
))
1022 return ops
->llsec
->add_dev(dev
, &desc
);
1025 int ieee802154_llsec_add_dev(struct sk_buff
*skb
, struct genl_info
*info
)
1027 if ((info
->nlhdr
->nlmsg_flags
& (NLM_F_CREATE
| NLM_F_EXCL
)) !=
1028 (NLM_F_CREATE
| NLM_F_EXCL
))
1031 return ieee802154_nl_llsec_change(skb
, info
, llsec_add_dev
);
1034 static int llsec_del_dev(struct net_device
*dev
, struct genl_info
*info
)
1036 struct ieee802154_mlme_ops
*ops
= ieee802154_mlme_ops(dev
);
1039 if (!info
->attrs
[IEEE802154_ATTR_HW_ADDR
])
1042 devaddr
= nla_get_hwaddr(info
->attrs
[IEEE802154_ATTR_HW_ADDR
]);
1044 return ops
->llsec
->del_dev(dev
, devaddr
);
1047 int ieee802154_llsec_del_dev(struct sk_buff
*skb
, struct genl_info
*info
)
1049 return ieee802154_nl_llsec_change(skb
, info
, llsec_del_dev
);
1053 ieee802154_nl_fill_dev(struct sk_buff
*msg
, u32 portid
, u32 seq
,
1054 const struct ieee802154_llsec_device
*desc
,
1055 const struct net_device
*dev
)
1059 hdr
= genlmsg_put(msg
, 0, seq
, &nl802154_family
, NLM_F_MULTI
,
1060 IEEE802154_LLSEC_LIST_DEV
);
1064 if (nla_put_string(msg
, IEEE802154_ATTR_DEV_NAME
, dev
->name
) ||
1065 nla_put_u32(msg
, IEEE802154_ATTR_DEV_INDEX
, dev
->ifindex
) ||
1066 nla_put_shortaddr(msg
, IEEE802154_ATTR_PAN_ID
, desc
->pan_id
) ||
1067 nla_put_shortaddr(msg
, IEEE802154_ATTR_SHORT_ADDR
,
1068 desc
->short_addr
) ||
1069 nla_put_hwaddr(msg
, IEEE802154_ATTR_HW_ADDR
, desc
->hwaddr
,
1070 IEEE802154_ATTR_PAD
) ||
1071 nla_put_u32(msg
, IEEE802154_ATTR_LLSEC_FRAME_COUNTER
,
1072 desc
->frame_counter
) ||
1073 nla_put_u8(msg
, IEEE802154_ATTR_LLSEC_DEV_OVERRIDE
,
1074 desc
->seclevel_exempt
) ||
1075 nla_put_u8(msg
, IEEE802154_ATTR_LLSEC_DEV_KEY_MODE
, desc
->key_mode
))
1076 goto nla_put_failure
;
1078 genlmsg_end(msg
, hdr
);
1082 genlmsg_cancel(msg
, hdr
);
1087 static int llsec_iter_devs(struct llsec_dump_data
*data
)
1089 struct ieee802154_llsec_device
*pos
;
1090 int rc
= 0, idx
= 0;
1092 list_for_each_entry(pos
, &data
->table
->devices
, list
) {
1093 if (idx
++ < data
->s_idx
)
1096 if (ieee802154_nl_fill_dev(data
->skb
, data
->portid
,
1097 data
->nlmsg_seq
, pos
, data
->dev
)) {
1108 int ieee802154_llsec_dump_devs(struct sk_buff
*skb
, struct netlink_callback
*cb
)
1110 return ieee802154_llsec_dump_table(skb
, cb
, llsec_iter_devs
);
1113 static int llsec_add_devkey(struct net_device
*dev
, struct genl_info
*info
)
1115 struct ieee802154_mlme_ops
*ops
= ieee802154_mlme_ops(dev
);
1116 struct ieee802154_llsec_device_key key
;
1119 if (!info
->attrs
[IEEE802154_ATTR_LLSEC_FRAME_COUNTER
] ||
1120 !info
->attrs
[IEEE802154_ATTR_HW_ADDR
] ||
1121 ieee802154_llsec_parse_key_id(info
, &key
.key_id
))
1124 devaddr
= nla_get_hwaddr(info
->attrs
[IEEE802154_ATTR_HW_ADDR
]);
1125 key
.frame_counter
= nla_get_u32(info
->attrs
[IEEE802154_ATTR_LLSEC_FRAME_COUNTER
]);
1127 return ops
->llsec
->add_devkey(dev
, devaddr
, &key
);
1130 int ieee802154_llsec_add_devkey(struct sk_buff
*skb
, struct genl_info
*info
)
1132 if ((info
->nlhdr
->nlmsg_flags
& (NLM_F_CREATE
| NLM_F_EXCL
)) !=
1133 (NLM_F_CREATE
| NLM_F_EXCL
))
1136 return ieee802154_nl_llsec_change(skb
, info
, llsec_add_devkey
);
1139 static int llsec_del_devkey(struct net_device
*dev
, struct genl_info
*info
)
1141 struct ieee802154_mlme_ops
*ops
= ieee802154_mlme_ops(dev
);
1142 struct ieee802154_llsec_device_key key
;
1145 if (!info
->attrs
[IEEE802154_ATTR_HW_ADDR
] ||
1146 ieee802154_llsec_parse_key_id(info
, &key
.key_id
))
1149 devaddr
= nla_get_hwaddr(info
->attrs
[IEEE802154_ATTR_HW_ADDR
]);
1151 return ops
->llsec
->del_devkey(dev
, devaddr
, &key
);
1154 int ieee802154_llsec_del_devkey(struct sk_buff
*skb
, struct genl_info
*info
)
1156 return ieee802154_nl_llsec_change(skb
, info
, llsec_del_devkey
);
1160 ieee802154_nl_fill_devkey(struct sk_buff
*msg
, u32 portid
, u32 seq
,
1162 const struct ieee802154_llsec_device_key
*devkey
,
1163 const struct net_device
*dev
)
1167 hdr
= genlmsg_put(msg
, 0, seq
, &nl802154_family
, NLM_F_MULTI
,
1168 IEEE802154_LLSEC_LIST_DEVKEY
);
1172 if (nla_put_string(msg
, IEEE802154_ATTR_DEV_NAME
, dev
->name
) ||
1173 nla_put_u32(msg
, IEEE802154_ATTR_DEV_INDEX
, dev
->ifindex
) ||
1174 nla_put_hwaddr(msg
, IEEE802154_ATTR_HW_ADDR
, devaddr
,
1175 IEEE802154_ATTR_PAD
) ||
1176 nla_put_u32(msg
, IEEE802154_ATTR_LLSEC_FRAME_COUNTER
,
1177 devkey
->frame_counter
) ||
1178 ieee802154_llsec_fill_key_id(msg
, &devkey
->key_id
))
1179 goto nla_put_failure
;
1181 genlmsg_end(msg
, hdr
);
1185 genlmsg_cancel(msg
, hdr
);
1190 static int llsec_iter_devkeys(struct llsec_dump_data
*data
)
1192 struct ieee802154_llsec_device
*dpos
;
1193 struct ieee802154_llsec_device_key
*kpos
;
1194 int rc
= 0, idx
= 0, idx2
;
1196 list_for_each_entry(dpos
, &data
->table
->devices
, list
) {
1197 if (idx
++ < data
->s_idx
)
1202 list_for_each_entry(kpos
, &dpos
->keys
, list
) {
1203 if (idx2
++ < data
->s_idx2
)
1206 if (ieee802154_nl_fill_devkey(data
->skb
, data
->portid
,
1210 return rc
= -EMSGSIZE
;
1222 int ieee802154_llsec_dump_devkeys(struct sk_buff
*skb
,
1223 struct netlink_callback
*cb
)
1225 return ieee802154_llsec_dump_table(skb
, cb
, llsec_iter_devkeys
);
1229 llsec_parse_seclevel(struct genl_info
*info
,
1230 struct ieee802154_llsec_seclevel
*sl
)
1232 memset(sl
, 0, sizeof(*sl
));
1234 if (!info
->attrs
[IEEE802154_ATTR_LLSEC_FRAME_TYPE
] ||
1235 !info
->attrs
[IEEE802154_ATTR_LLSEC_SECLEVELS
] ||
1236 !info
->attrs
[IEEE802154_ATTR_LLSEC_DEV_OVERRIDE
])
1239 sl
->frame_type
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_LLSEC_FRAME_TYPE
]);
1240 if (sl
->frame_type
== IEEE802154_FC_TYPE_MAC_CMD
) {
1241 if (!info
->attrs
[IEEE802154_ATTR_LLSEC_CMD_FRAME_ID
])
1244 sl
->cmd_frame_id
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_LLSEC_CMD_FRAME_ID
]);
1247 sl
->sec_levels
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_LLSEC_SECLEVELS
]);
1248 sl
->device_override
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_LLSEC_DEV_OVERRIDE
]);
1253 static int llsec_add_seclevel(struct net_device
*dev
, struct genl_info
*info
)
1255 struct ieee802154_mlme_ops
*ops
= ieee802154_mlme_ops(dev
);
1256 struct ieee802154_llsec_seclevel sl
;
1258 if (llsec_parse_seclevel(info
, &sl
))
1261 return ops
->llsec
->add_seclevel(dev
, &sl
);
1264 int ieee802154_llsec_add_seclevel(struct sk_buff
*skb
, struct genl_info
*info
)
1266 if ((info
->nlhdr
->nlmsg_flags
& (NLM_F_CREATE
| NLM_F_EXCL
)) !=
1267 (NLM_F_CREATE
| NLM_F_EXCL
))
1270 return ieee802154_nl_llsec_change(skb
, info
, llsec_add_seclevel
);
1273 static int llsec_del_seclevel(struct net_device
*dev
, struct genl_info
*info
)
1275 struct ieee802154_mlme_ops
*ops
= ieee802154_mlme_ops(dev
);
1276 struct ieee802154_llsec_seclevel sl
;
1278 if (llsec_parse_seclevel(info
, &sl
))
1281 return ops
->llsec
->del_seclevel(dev
, &sl
);
1284 int ieee802154_llsec_del_seclevel(struct sk_buff
*skb
, struct genl_info
*info
)
1286 return ieee802154_nl_llsec_change(skb
, info
, llsec_del_seclevel
);
1290 ieee802154_nl_fill_seclevel(struct sk_buff
*msg
, u32 portid
, u32 seq
,
1291 const struct ieee802154_llsec_seclevel
*sl
,
1292 const struct net_device
*dev
)
1296 hdr
= genlmsg_put(msg
, 0, seq
, &nl802154_family
, NLM_F_MULTI
,
1297 IEEE802154_LLSEC_LIST_SECLEVEL
);
1301 if (nla_put_string(msg
, IEEE802154_ATTR_DEV_NAME
, dev
->name
) ||
1302 nla_put_u32(msg
, IEEE802154_ATTR_DEV_INDEX
, dev
->ifindex
) ||
1303 nla_put_u8(msg
, IEEE802154_ATTR_LLSEC_FRAME_TYPE
, sl
->frame_type
) ||
1304 nla_put_u8(msg
, IEEE802154_ATTR_LLSEC_SECLEVELS
, sl
->sec_levels
) ||
1305 nla_put_u8(msg
, IEEE802154_ATTR_LLSEC_DEV_OVERRIDE
,
1306 sl
->device_override
))
1307 goto nla_put_failure
;
1309 if (sl
->frame_type
== IEEE802154_FC_TYPE_MAC_CMD
&&
1310 nla_put_u8(msg
, IEEE802154_ATTR_LLSEC_CMD_FRAME_ID
,
1312 goto nla_put_failure
;
1314 genlmsg_end(msg
, hdr
);
1318 genlmsg_cancel(msg
, hdr
);
1323 static int llsec_iter_seclevels(struct llsec_dump_data
*data
)
1325 struct ieee802154_llsec_seclevel
*pos
;
1326 int rc
= 0, idx
= 0;
1328 list_for_each_entry(pos
, &data
->table
->security_levels
, list
) {
1329 if (idx
++ < data
->s_idx
)
1332 if (ieee802154_nl_fill_seclevel(data
->skb
, data
->portid
,
1333 data
->nlmsg_seq
, pos
,
1345 int ieee802154_llsec_dump_seclevels(struct sk_buff
*skb
,
1346 struct netlink_callback
*cb
)
1348 return ieee802154_llsec_dump_table(skb
, cb
, llsec_iter_seclevels
);