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.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 * Sergey Lapin <slapin@ossfans.org>
21 * Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
22 * Maxim Osipov <maxim.osipov@siemens.com>
25 #include <linux/gfp.h>
26 #include <linux/kernel.h>
27 #include <linux/if_arp.h>
28 #include <linux/netdevice.h>
29 #include <net/netlink.h>
30 #include <net/genetlink.h>
32 #include <linux/nl802154.h>
33 #include <linux/export.h>
34 #include <net/af_ieee802154.h>
35 #include <net/nl802154.h>
36 #include <net/ieee802154.h>
37 #include <net/ieee802154_netdev.h>
38 #include <net/wpan-phy.h>
40 #include "ieee802154.h"
42 static int nla_put_hwaddr(struct sk_buff
*msg
, int type
, __le64 hwaddr
)
44 return nla_put_u64(msg
, type
, swab64((__force u64
)hwaddr
));
47 static __le64
nla_get_hwaddr(const struct nlattr
*nla
)
49 return ieee802154_devaddr_from_raw(nla_data(nla
));
52 static int nla_put_shortaddr(struct sk_buff
*msg
, int type
, __le16 addr
)
54 return nla_put_u16(msg
, type
, le16_to_cpu(addr
));
57 static __le16
nla_get_shortaddr(const struct nlattr
*nla
)
59 return cpu_to_le16(nla_get_u16(nla
));
62 int ieee802154_nl_assoc_indic(struct net_device
*dev
,
63 struct ieee802154_addr
*addr
,
68 pr_debug("%s\n", __func__
);
70 if (addr
->mode
!= IEEE802154_ADDR_LONG
) {
71 pr_err("%s: received non-long source address!\n", __func__
);
75 msg
= ieee802154_nl_create(0, IEEE802154_ASSOCIATE_INDIC
);
79 if (nla_put_string(msg
, IEEE802154_ATTR_DEV_NAME
, dev
->name
) ||
80 nla_put_u32(msg
, IEEE802154_ATTR_DEV_INDEX
, dev
->ifindex
) ||
81 nla_put(msg
, IEEE802154_ATTR_HW_ADDR
, IEEE802154_ADDR_LEN
,
83 nla_put_hwaddr(msg
, IEEE802154_ATTR_SRC_HW_ADDR
,
84 addr
->extended_addr
) ||
85 nla_put_u8(msg
, IEEE802154_ATTR_CAPABILITY
, cap
))
88 return ieee802154_nl_mcast(msg
, IEEE802154_COORD_MCGRP
);
94 EXPORT_SYMBOL(ieee802154_nl_assoc_indic
);
96 int ieee802154_nl_assoc_confirm(struct net_device
*dev
, __le16 short_addr
,
101 pr_debug("%s\n", __func__
);
103 msg
= ieee802154_nl_create(0, IEEE802154_ASSOCIATE_CONF
);
107 if (nla_put_string(msg
, IEEE802154_ATTR_DEV_NAME
, dev
->name
) ||
108 nla_put_u32(msg
, IEEE802154_ATTR_DEV_INDEX
, dev
->ifindex
) ||
109 nla_put(msg
, IEEE802154_ATTR_HW_ADDR
, IEEE802154_ADDR_LEN
,
111 nla_put_shortaddr(msg
, IEEE802154_ATTR_SHORT_ADDR
, short_addr
) ||
112 nla_put_u8(msg
, IEEE802154_ATTR_STATUS
, status
))
113 goto nla_put_failure
;
114 return ieee802154_nl_mcast(msg
, IEEE802154_COORD_MCGRP
);
120 EXPORT_SYMBOL(ieee802154_nl_assoc_confirm
);
122 int ieee802154_nl_disassoc_indic(struct net_device
*dev
,
123 struct ieee802154_addr
*addr
,
128 pr_debug("%s\n", __func__
);
130 msg
= ieee802154_nl_create(0, IEEE802154_DISASSOCIATE_INDIC
);
134 if (nla_put_string(msg
, IEEE802154_ATTR_DEV_NAME
, dev
->name
) ||
135 nla_put_u32(msg
, IEEE802154_ATTR_DEV_INDEX
, dev
->ifindex
) ||
136 nla_put(msg
, IEEE802154_ATTR_HW_ADDR
, IEEE802154_ADDR_LEN
,
138 goto nla_put_failure
;
139 if (addr
->mode
== IEEE802154_ADDR_LONG
) {
140 if (nla_put_hwaddr(msg
, IEEE802154_ATTR_SRC_HW_ADDR
,
141 addr
->extended_addr
))
142 goto nla_put_failure
;
144 if (nla_put_shortaddr(msg
, IEEE802154_ATTR_SRC_SHORT_ADDR
,
146 goto nla_put_failure
;
148 if (nla_put_u8(msg
, IEEE802154_ATTR_REASON
, reason
))
149 goto nla_put_failure
;
150 return ieee802154_nl_mcast(msg
, IEEE802154_COORD_MCGRP
);
156 EXPORT_SYMBOL(ieee802154_nl_disassoc_indic
);
158 int ieee802154_nl_disassoc_confirm(struct net_device
*dev
, u8 status
)
162 pr_debug("%s\n", __func__
);
164 msg
= ieee802154_nl_create(0, IEEE802154_DISASSOCIATE_CONF
);
168 if (nla_put_string(msg
, IEEE802154_ATTR_DEV_NAME
, dev
->name
) ||
169 nla_put_u32(msg
, IEEE802154_ATTR_DEV_INDEX
, dev
->ifindex
) ||
170 nla_put(msg
, IEEE802154_ATTR_HW_ADDR
, IEEE802154_ADDR_LEN
,
172 nla_put_u8(msg
, IEEE802154_ATTR_STATUS
, status
))
173 goto nla_put_failure
;
174 return ieee802154_nl_mcast(msg
, IEEE802154_COORD_MCGRP
);
180 EXPORT_SYMBOL(ieee802154_nl_disassoc_confirm
);
182 int ieee802154_nl_beacon_indic(struct net_device
*dev
, __le16 panid
,
187 pr_debug("%s\n", __func__
);
189 msg
= ieee802154_nl_create(0, IEEE802154_BEACON_NOTIFY_INDIC
);
193 if (nla_put_string(msg
, IEEE802154_ATTR_DEV_NAME
, dev
->name
) ||
194 nla_put_u32(msg
, IEEE802154_ATTR_DEV_INDEX
, dev
->ifindex
) ||
195 nla_put(msg
, IEEE802154_ATTR_HW_ADDR
, IEEE802154_ADDR_LEN
,
197 nla_put_shortaddr(msg
, IEEE802154_ATTR_COORD_SHORT_ADDR
,
199 nla_put_shortaddr(msg
, IEEE802154_ATTR_COORD_PAN_ID
, panid
))
200 goto nla_put_failure
;
201 return ieee802154_nl_mcast(msg
, IEEE802154_COORD_MCGRP
);
207 EXPORT_SYMBOL(ieee802154_nl_beacon_indic
);
209 int ieee802154_nl_scan_confirm(struct net_device
*dev
,
210 u8 status
, u8 scan_type
,
211 u32 unscanned
, u8 page
,
212 u8
*edl
/* , struct list_head *pan_desc_list */)
216 pr_debug("%s\n", __func__
);
218 msg
= ieee802154_nl_create(0, IEEE802154_SCAN_CONF
);
222 if (nla_put_string(msg
, IEEE802154_ATTR_DEV_NAME
, dev
->name
) ||
223 nla_put_u32(msg
, IEEE802154_ATTR_DEV_INDEX
, dev
->ifindex
) ||
224 nla_put(msg
, IEEE802154_ATTR_HW_ADDR
, IEEE802154_ADDR_LEN
,
226 nla_put_u8(msg
, IEEE802154_ATTR_STATUS
, status
) ||
227 nla_put_u8(msg
, IEEE802154_ATTR_SCAN_TYPE
, scan_type
) ||
228 nla_put_u32(msg
, IEEE802154_ATTR_CHANNELS
, unscanned
) ||
229 nla_put_u8(msg
, IEEE802154_ATTR_PAGE
, page
) ||
231 nla_put(msg
, IEEE802154_ATTR_ED_LIST
, 27, edl
)))
232 goto nla_put_failure
;
233 return ieee802154_nl_mcast(msg
, IEEE802154_COORD_MCGRP
);
239 EXPORT_SYMBOL(ieee802154_nl_scan_confirm
);
241 int ieee802154_nl_start_confirm(struct net_device
*dev
, u8 status
)
245 pr_debug("%s\n", __func__
);
247 msg
= ieee802154_nl_create(0, IEEE802154_START_CONF
);
251 if (nla_put_string(msg
, IEEE802154_ATTR_DEV_NAME
, dev
->name
) ||
252 nla_put_u32(msg
, IEEE802154_ATTR_DEV_INDEX
, dev
->ifindex
) ||
253 nla_put(msg
, IEEE802154_ATTR_HW_ADDR
, IEEE802154_ADDR_LEN
,
255 nla_put_u8(msg
, IEEE802154_ATTR_STATUS
, status
))
256 goto nla_put_failure
;
257 return ieee802154_nl_mcast(msg
, IEEE802154_COORD_MCGRP
);
263 EXPORT_SYMBOL(ieee802154_nl_start_confirm
);
265 static int ieee802154_nl_fill_iface(struct sk_buff
*msg
, u32 portid
,
266 u32 seq
, int flags
, struct net_device
*dev
)
269 struct wpan_phy
*phy
;
270 struct ieee802154_mlme_ops
*ops
;
271 __le16 short_addr
, pan_id
;
273 pr_debug("%s\n", __func__
);
275 hdr
= genlmsg_put(msg
, 0, seq
, &nl802154_family
, flags
,
276 IEEE802154_LIST_IFACE
);
280 ops
= ieee802154_mlme_ops(dev
);
281 phy
= ops
->get_phy(dev
);
284 short_addr
= ops
->get_short_addr(dev
);
285 pan_id
= ops
->get_pan_id(dev
);
287 if (nla_put_string(msg
, IEEE802154_ATTR_DEV_NAME
, dev
->name
) ||
288 nla_put_string(msg
, IEEE802154_ATTR_PHY_NAME
, wpan_phy_name(phy
)) ||
289 nla_put_u32(msg
, IEEE802154_ATTR_DEV_INDEX
, dev
->ifindex
) ||
290 nla_put(msg
, IEEE802154_ATTR_HW_ADDR
, IEEE802154_ADDR_LEN
,
292 nla_put_shortaddr(msg
, IEEE802154_ATTR_SHORT_ADDR
, short_addr
) ||
293 nla_put_shortaddr(msg
, IEEE802154_ATTR_PAN_ID
, pan_id
))
294 goto nla_put_failure
;
296 if (ops
->get_mac_params
) {
297 struct ieee802154_mac_params params
;
299 ops
->get_mac_params(dev
, ¶ms
);
301 if (nla_put_s8(msg
, IEEE802154_ATTR_TXPOWER
,
302 params
.transmit_power
) ||
303 nla_put_u8(msg
, IEEE802154_ATTR_LBT_ENABLED
, params
.lbt
) ||
304 nla_put_u8(msg
, IEEE802154_ATTR_CCA_MODE
,
306 nla_put_s32(msg
, IEEE802154_ATTR_CCA_ED_LEVEL
,
307 params
.cca_ed_level
) ||
308 nla_put_u8(msg
, IEEE802154_ATTR_CSMA_RETRIES
,
309 params
.csma_retries
) ||
310 nla_put_u8(msg
, IEEE802154_ATTR_CSMA_MIN_BE
,
312 nla_put_u8(msg
, IEEE802154_ATTR_CSMA_MAX_BE
,
314 nla_put_s8(msg
, IEEE802154_ATTR_FRAME_RETRIES
,
315 params
.frame_retries
))
316 goto nla_put_failure
;
320 return genlmsg_end(msg
, hdr
);
324 genlmsg_cancel(msg
, hdr
);
329 /* Requests from userspace */
330 static struct net_device
*ieee802154_nl_get_dev(struct genl_info
*info
)
332 struct net_device
*dev
;
334 if (info
->attrs
[IEEE802154_ATTR_DEV_NAME
]) {
335 char name
[IFNAMSIZ
+ 1];
337 nla_strlcpy(name
, info
->attrs
[IEEE802154_ATTR_DEV_NAME
],
339 dev
= dev_get_by_name(&init_net
, name
);
340 } else if (info
->attrs
[IEEE802154_ATTR_DEV_INDEX
]) {
341 dev
= dev_get_by_index(&init_net
,
342 nla_get_u32(info
->attrs
[IEEE802154_ATTR_DEV_INDEX
]));
350 if (dev
->type
!= ARPHRD_IEEE802154
) {
358 int ieee802154_associate_req(struct sk_buff
*skb
, struct genl_info
*info
)
360 struct net_device
*dev
;
361 struct ieee802154_addr addr
;
363 int ret
= -EOPNOTSUPP
;
365 if (!info
->attrs
[IEEE802154_ATTR_CHANNEL
] ||
366 !info
->attrs
[IEEE802154_ATTR_COORD_PAN_ID
] ||
367 (!info
->attrs
[IEEE802154_ATTR_COORD_HW_ADDR
] &&
368 !info
->attrs
[IEEE802154_ATTR_COORD_SHORT_ADDR
]) ||
369 !info
->attrs
[IEEE802154_ATTR_CAPABILITY
])
372 dev
= ieee802154_nl_get_dev(info
);
375 if (!ieee802154_mlme_ops(dev
)->assoc_req
)
378 if (info
->attrs
[IEEE802154_ATTR_COORD_HW_ADDR
]) {
379 addr
.mode
= IEEE802154_ADDR_LONG
;
380 addr
.extended_addr
= nla_get_hwaddr(
381 info
->attrs
[IEEE802154_ATTR_COORD_HW_ADDR
]);
383 addr
.mode
= IEEE802154_ADDR_SHORT
;
384 addr
.short_addr
= nla_get_shortaddr(
385 info
->attrs
[IEEE802154_ATTR_COORD_SHORT_ADDR
]);
387 addr
.pan_id
= nla_get_shortaddr(
388 info
->attrs
[IEEE802154_ATTR_COORD_PAN_ID
]);
390 if (info
->attrs
[IEEE802154_ATTR_PAGE
])
391 page
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_PAGE
]);
395 ret
= ieee802154_mlme_ops(dev
)->assoc_req(dev
, &addr
,
396 nla_get_u8(info
->attrs
[IEEE802154_ATTR_CHANNEL
]),
398 nla_get_u8(info
->attrs
[IEEE802154_ATTR_CAPABILITY
]));
405 int ieee802154_associate_resp(struct sk_buff
*skb
, struct genl_info
*info
)
407 struct net_device
*dev
;
408 struct ieee802154_addr addr
;
409 int ret
= -EOPNOTSUPP
;
411 if (!info
->attrs
[IEEE802154_ATTR_STATUS
] ||
412 !info
->attrs
[IEEE802154_ATTR_DEST_HW_ADDR
] ||
413 !info
->attrs
[IEEE802154_ATTR_DEST_SHORT_ADDR
])
416 dev
= ieee802154_nl_get_dev(info
);
419 if (!ieee802154_mlme_ops(dev
)->assoc_resp
)
422 addr
.mode
= IEEE802154_ADDR_LONG
;
423 addr
.extended_addr
= nla_get_hwaddr(
424 info
->attrs
[IEEE802154_ATTR_DEST_HW_ADDR
]);
425 addr
.pan_id
= ieee802154_mlme_ops(dev
)->get_pan_id(dev
);
427 ret
= ieee802154_mlme_ops(dev
)->assoc_resp(dev
, &addr
,
428 nla_get_shortaddr(info
->attrs
[IEEE802154_ATTR_DEST_SHORT_ADDR
]),
429 nla_get_u8(info
->attrs
[IEEE802154_ATTR_STATUS
]));
436 int ieee802154_disassociate_req(struct sk_buff
*skb
, struct genl_info
*info
)
438 struct net_device
*dev
;
439 struct ieee802154_addr addr
;
440 int ret
= -EOPNOTSUPP
;
442 if ((!info
->attrs
[IEEE802154_ATTR_DEST_HW_ADDR
] &&
443 !info
->attrs
[IEEE802154_ATTR_DEST_SHORT_ADDR
]) ||
444 !info
->attrs
[IEEE802154_ATTR_REASON
])
447 dev
= ieee802154_nl_get_dev(info
);
450 if (!ieee802154_mlme_ops(dev
)->disassoc_req
)
453 if (info
->attrs
[IEEE802154_ATTR_DEST_HW_ADDR
]) {
454 addr
.mode
= IEEE802154_ADDR_LONG
;
455 addr
.extended_addr
= nla_get_hwaddr(
456 info
->attrs
[IEEE802154_ATTR_DEST_HW_ADDR
]);
458 addr
.mode
= IEEE802154_ADDR_SHORT
;
459 addr
.short_addr
= nla_get_shortaddr(
460 info
->attrs
[IEEE802154_ATTR_DEST_SHORT_ADDR
]);
462 addr
.pan_id
= ieee802154_mlme_ops(dev
)->get_pan_id(dev
);
464 ret
= ieee802154_mlme_ops(dev
)->disassoc_req(dev
, &addr
,
465 nla_get_u8(info
->attrs
[IEEE802154_ATTR_REASON
]));
472 /* PANid, channel, beacon_order = 15, superframe_order = 15,
473 * PAN_coordinator, battery_life_extension = 0,
474 * coord_realignment = 0, security_enable = 0
476 int ieee802154_start_req(struct sk_buff
*skb
, struct genl_info
*info
)
478 struct net_device
*dev
;
479 struct ieee802154_addr addr
;
481 u8 channel
, bcn_ord
, sf_ord
;
483 int pan_coord
, blx
, coord_realign
;
484 int ret
= -EOPNOTSUPP
;
486 if (!info
->attrs
[IEEE802154_ATTR_COORD_PAN_ID
] ||
487 !info
->attrs
[IEEE802154_ATTR_COORD_SHORT_ADDR
] ||
488 !info
->attrs
[IEEE802154_ATTR_CHANNEL
] ||
489 !info
->attrs
[IEEE802154_ATTR_BCN_ORD
] ||
490 !info
->attrs
[IEEE802154_ATTR_SF_ORD
] ||
491 !info
->attrs
[IEEE802154_ATTR_PAN_COORD
] ||
492 !info
->attrs
[IEEE802154_ATTR_BAT_EXT
] ||
493 !info
->attrs
[IEEE802154_ATTR_COORD_REALIGN
]
497 dev
= ieee802154_nl_get_dev(info
);
500 if (!ieee802154_mlme_ops(dev
)->start_req
)
503 addr
.mode
= IEEE802154_ADDR_SHORT
;
504 addr
.short_addr
= nla_get_shortaddr(
505 info
->attrs
[IEEE802154_ATTR_COORD_SHORT_ADDR
]);
506 addr
.pan_id
= nla_get_shortaddr(
507 info
->attrs
[IEEE802154_ATTR_COORD_PAN_ID
]);
509 channel
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_CHANNEL
]);
510 bcn_ord
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_BCN_ORD
]);
511 sf_ord
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_SF_ORD
]);
512 pan_coord
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_PAN_COORD
]);
513 blx
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_BAT_EXT
]);
514 coord_realign
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_COORD_REALIGN
]);
516 if (info
->attrs
[IEEE802154_ATTR_PAGE
])
517 page
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_PAGE
]);
522 if (addr
.short_addr
== cpu_to_le16(IEEE802154_ADDR_BROADCAST
)) {
523 ieee802154_nl_start_confirm(dev
, IEEE802154_NO_SHORT_ADDRESS
);
528 ret
= ieee802154_mlme_ops(dev
)->start_req(dev
, &addr
, channel
, page
,
529 bcn_ord
, sf_ord
, pan_coord
, blx
, coord_realign
);
536 int ieee802154_scan_req(struct sk_buff
*skb
, struct genl_info
*info
)
538 struct net_device
*dev
;
539 int ret
= -EOPNOTSUPP
;
545 if (!info
->attrs
[IEEE802154_ATTR_SCAN_TYPE
] ||
546 !info
->attrs
[IEEE802154_ATTR_CHANNELS
] ||
547 !info
->attrs
[IEEE802154_ATTR_DURATION
])
550 dev
= ieee802154_nl_get_dev(info
);
553 if (!ieee802154_mlme_ops(dev
)->scan_req
)
556 type
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_SCAN_TYPE
]);
557 channels
= nla_get_u32(info
->attrs
[IEEE802154_ATTR_CHANNELS
]);
558 duration
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_DURATION
]);
560 if (info
->attrs
[IEEE802154_ATTR_PAGE
])
561 page
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_PAGE
]);
566 ret
= ieee802154_mlme_ops(dev
)->scan_req(dev
, type
, channels
,
574 int ieee802154_list_iface(struct sk_buff
*skb
, struct genl_info
*info
)
576 /* Request for interface name, index, type, IEEE address,
577 * PAN Id, short address
580 struct net_device
*dev
= NULL
;
583 pr_debug("%s\n", __func__
);
585 dev
= ieee802154_nl_get_dev(info
);
589 msg
= nlmsg_new(NLMSG_DEFAULT_SIZE
, GFP_KERNEL
);
593 rc
= ieee802154_nl_fill_iface(msg
, info
->snd_portid
, info
->snd_seq
,
600 return genlmsg_reply(msg
, info
);
608 int ieee802154_dump_iface(struct sk_buff
*skb
, struct netlink_callback
*cb
)
610 struct net
*net
= sock_net(skb
->sk
);
611 struct net_device
*dev
;
613 int s_idx
= cb
->args
[0];
615 pr_debug("%s\n", __func__
);
618 for_each_netdev(net
, dev
) {
619 if (idx
< s_idx
|| (dev
->type
!= ARPHRD_IEEE802154
))
622 if (ieee802154_nl_fill_iface(skb
, NETLINK_CB(cb
->skb
).portid
,
624 NLM_F_MULTI
, dev
) < 0)
634 int ieee802154_set_macparams(struct sk_buff
*skb
, struct genl_info
*info
)
636 struct net_device
*dev
= NULL
;
637 struct ieee802154_mlme_ops
*ops
;
638 struct ieee802154_mac_params params
;
639 struct wpan_phy
*phy
;
642 pr_debug("%s\n", __func__
);
644 dev
= ieee802154_nl_get_dev(info
);
648 ops
= ieee802154_mlme_ops(dev
);
650 if (!ops
->get_mac_params
|| !ops
->set_mac_params
) {
655 if (netif_running(dev
)) {
660 if (!info
->attrs
[IEEE802154_ATTR_LBT_ENABLED
] &&
661 !info
->attrs
[IEEE802154_ATTR_CCA_MODE
] &&
662 !info
->attrs
[IEEE802154_ATTR_CCA_ED_LEVEL
] &&
663 !info
->attrs
[IEEE802154_ATTR_CSMA_RETRIES
] &&
664 !info
->attrs
[IEEE802154_ATTR_CSMA_MIN_BE
] &&
665 !info
->attrs
[IEEE802154_ATTR_CSMA_MAX_BE
] &&
666 !info
->attrs
[IEEE802154_ATTR_FRAME_RETRIES
])
669 phy
= ops
->get_phy(dev
);
671 if ((!phy
->set_lbt
&& info
->attrs
[IEEE802154_ATTR_LBT_ENABLED
]) ||
672 (!phy
->set_cca_mode
&& info
->attrs
[IEEE802154_ATTR_CCA_MODE
]) ||
673 (!phy
->set_cca_ed_level
&&
674 info
->attrs
[IEEE802154_ATTR_CCA_ED_LEVEL
]) ||
675 (!phy
->set_csma_params
&&
676 (info
->attrs
[IEEE802154_ATTR_CSMA_RETRIES
] ||
677 info
->attrs
[IEEE802154_ATTR_CSMA_MIN_BE
] ||
678 info
->attrs
[IEEE802154_ATTR_CSMA_MAX_BE
])) ||
679 (!phy
->set_frame_retries
&&
680 info
->attrs
[IEEE802154_ATTR_FRAME_RETRIES
])) {
685 ops
->get_mac_params(dev
, ¶ms
);
687 if (info
->attrs
[IEEE802154_ATTR_TXPOWER
])
688 params
.transmit_power
= nla_get_s8(info
->attrs
[IEEE802154_ATTR_TXPOWER
]);
690 if (info
->attrs
[IEEE802154_ATTR_LBT_ENABLED
])
691 params
.lbt
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_LBT_ENABLED
]);
693 if (info
->attrs
[IEEE802154_ATTR_CCA_MODE
])
694 params
.cca_mode
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_CCA_MODE
]);
696 if (info
->attrs
[IEEE802154_ATTR_CCA_ED_LEVEL
])
697 params
.cca_ed_level
= nla_get_s32(info
->attrs
[IEEE802154_ATTR_CCA_ED_LEVEL
]);
699 if (info
->attrs
[IEEE802154_ATTR_CSMA_RETRIES
])
700 params
.csma_retries
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_CSMA_RETRIES
]);
702 if (info
->attrs
[IEEE802154_ATTR_CSMA_MIN_BE
])
703 params
.min_be
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_CSMA_MIN_BE
]);
705 if (info
->attrs
[IEEE802154_ATTR_CSMA_MAX_BE
])
706 params
.max_be
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_CSMA_MAX_BE
]);
708 if (info
->attrs
[IEEE802154_ATTR_FRAME_RETRIES
])
709 params
.frame_retries
= nla_get_s8(info
->attrs
[IEEE802154_ATTR_FRAME_RETRIES
]);
711 rc
= ops
->set_mac_params(dev
, ¶ms
);
727 ieee802154_llsec_parse_key_id(struct genl_info
*info
,
728 struct ieee802154_llsec_key_id
*desc
)
730 memset(desc
, 0, sizeof(*desc
));
732 if (!info
->attrs
[IEEE802154_ATTR_LLSEC_KEY_MODE
])
735 desc
->mode
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_LLSEC_KEY_MODE
]);
737 if (desc
->mode
== IEEE802154_SCF_KEY_IMPLICIT
) {
738 if (!info
->attrs
[IEEE802154_ATTR_PAN_ID
] &&
739 !(info
->attrs
[IEEE802154_ATTR_SHORT_ADDR
] ||
740 info
->attrs
[IEEE802154_ATTR_HW_ADDR
]))
743 desc
->device_addr
.pan_id
= nla_get_shortaddr(info
->attrs
[IEEE802154_ATTR_PAN_ID
]);
745 if (info
->attrs
[IEEE802154_ATTR_SHORT_ADDR
]) {
746 desc
->device_addr
.mode
= IEEE802154_ADDR_SHORT
;
747 desc
->device_addr
.short_addr
= nla_get_shortaddr(info
->attrs
[IEEE802154_ATTR_SHORT_ADDR
]);
749 desc
->device_addr
.mode
= IEEE802154_ADDR_LONG
;
750 desc
->device_addr
.extended_addr
= nla_get_hwaddr(info
->attrs
[IEEE802154_ATTR_HW_ADDR
]);
754 if (desc
->mode
!= IEEE802154_SCF_KEY_IMPLICIT
&&
755 !info
->attrs
[IEEE802154_ATTR_LLSEC_KEY_ID
])
758 if (desc
->mode
== IEEE802154_SCF_KEY_SHORT_INDEX
&&
759 !info
->attrs
[IEEE802154_ATTR_LLSEC_KEY_SOURCE_SHORT
])
762 if (desc
->mode
== IEEE802154_SCF_KEY_HW_INDEX
&&
763 !info
->attrs
[IEEE802154_ATTR_LLSEC_KEY_SOURCE_EXTENDED
])
766 if (desc
->mode
!= IEEE802154_SCF_KEY_IMPLICIT
)
767 desc
->id
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_LLSEC_KEY_ID
]);
769 switch (desc
->mode
) {
770 case IEEE802154_SCF_KEY_SHORT_INDEX
:
772 u32 source
= nla_get_u32(info
->attrs
[IEEE802154_ATTR_LLSEC_KEY_SOURCE_SHORT
]);
774 desc
->short_source
= cpu_to_le32(source
);
777 case IEEE802154_SCF_KEY_HW_INDEX
:
778 desc
->extended_source
= nla_get_hwaddr(info
->attrs
[IEEE802154_ATTR_LLSEC_KEY_SOURCE_EXTENDED
]);
786 ieee802154_llsec_fill_key_id(struct sk_buff
*msg
,
787 const struct ieee802154_llsec_key_id
*desc
)
789 if (nla_put_u8(msg
, IEEE802154_ATTR_LLSEC_KEY_MODE
, desc
->mode
))
792 if (desc
->mode
== IEEE802154_SCF_KEY_IMPLICIT
) {
793 if (nla_put_shortaddr(msg
, IEEE802154_ATTR_PAN_ID
,
794 desc
->device_addr
.pan_id
))
797 if (desc
->device_addr
.mode
== IEEE802154_ADDR_SHORT
&&
798 nla_put_shortaddr(msg
, IEEE802154_ATTR_SHORT_ADDR
,
799 desc
->device_addr
.short_addr
))
802 if (desc
->device_addr
.mode
== IEEE802154_ADDR_LONG
&&
803 nla_put_hwaddr(msg
, IEEE802154_ATTR_HW_ADDR
,
804 desc
->device_addr
.extended_addr
))
808 if (desc
->mode
!= IEEE802154_SCF_KEY_IMPLICIT
&&
809 nla_put_u8(msg
, IEEE802154_ATTR_LLSEC_KEY_ID
, desc
->id
))
812 if (desc
->mode
== IEEE802154_SCF_KEY_SHORT_INDEX
&&
813 nla_put_u32(msg
, IEEE802154_ATTR_LLSEC_KEY_SOURCE_SHORT
,
814 le32_to_cpu(desc
->short_source
)))
817 if (desc
->mode
== IEEE802154_SCF_KEY_HW_INDEX
&&
818 nla_put_hwaddr(msg
, IEEE802154_ATTR_LLSEC_KEY_SOURCE_EXTENDED
,
819 desc
->extended_source
))
825 int ieee802154_llsec_getparams(struct sk_buff
*skb
, struct genl_info
*info
)
828 struct net_device
*dev
= NULL
;
830 struct ieee802154_mlme_ops
*ops
;
832 struct ieee802154_llsec_params params
;
834 pr_debug("%s\n", __func__
);
836 dev
= ieee802154_nl_get_dev(info
);
840 ops
= ieee802154_mlme_ops(dev
);
846 msg
= nlmsg_new(NLMSG_DEFAULT_SIZE
, GFP_KERNEL
);
850 hdr
= genlmsg_put(msg
, 0, info
->snd_seq
, &nl802154_family
, 0,
851 IEEE802154_LLSEC_GETPARAMS
);
855 rc
= ops
->llsec
->get_params(dev
, ¶ms
);
859 if (nla_put_string(msg
, IEEE802154_ATTR_DEV_NAME
, dev
->name
) ||
860 nla_put_u32(msg
, IEEE802154_ATTR_DEV_INDEX
, dev
->ifindex
) ||
861 nla_put_u8(msg
, IEEE802154_ATTR_LLSEC_ENABLED
, params
.enabled
) ||
862 nla_put_u8(msg
, IEEE802154_ATTR_LLSEC_SECLEVEL
, params
.out_level
) ||
863 nla_put_u32(msg
, IEEE802154_ATTR_LLSEC_FRAME_COUNTER
,
864 be32_to_cpu(params
.frame_counter
)) ||
865 ieee802154_llsec_fill_key_id(msg
, ¶ms
.out_key
))
870 return ieee802154_nl_reply(msg
, info
);
878 int ieee802154_llsec_setparams(struct sk_buff
*skb
, struct genl_info
*info
)
880 struct net_device
*dev
= NULL
;
882 struct ieee802154_mlme_ops
*ops
;
883 struct ieee802154_llsec_params params
;
886 pr_debug("%s\n", __func__
);
888 dev
= ieee802154_nl_get_dev(info
);
892 if (!info
->attrs
[IEEE802154_ATTR_LLSEC_ENABLED
] &&
893 !info
->attrs
[IEEE802154_ATTR_LLSEC_KEY_MODE
] &&
894 !info
->attrs
[IEEE802154_ATTR_LLSEC_SECLEVEL
])
897 ops
= ieee802154_mlme_ops(dev
);
903 if (info
->attrs
[IEEE802154_ATTR_LLSEC_SECLEVEL
] &&
904 nla_get_u8(info
->attrs
[IEEE802154_ATTR_LLSEC_SECLEVEL
]) > 7)
907 if (info
->attrs
[IEEE802154_ATTR_LLSEC_ENABLED
]) {
908 params
.enabled
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_LLSEC_ENABLED
]);
909 changed
|= IEEE802154_LLSEC_PARAM_ENABLED
;
912 if (info
->attrs
[IEEE802154_ATTR_LLSEC_KEY_MODE
]) {
913 if (ieee802154_llsec_parse_key_id(info
, ¶ms
.out_key
))
916 changed
|= IEEE802154_LLSEC_PARAM_OUT_KEY
;
919 if (info
->attrs
[IEEE802154_ATTR_LLSEC_SECLEVEL
]) {
920 params
.out_level
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_LLSEC_SECLEVEL
]);
921 changed
|= IEEE802154_LLSEC_PARAM_OUT_LEVEL
;
924 if (info
->attrs
[IEEE802154_ATTR_LLSEC_FRAME_COUNTER
]) {
925 u32 fc
= nla_get_u32(info
->attrs
[IEEE802154_ATTR_LLSEC_FRAME_COUNTER
]);
927 params
.frame_counter
= cpu_to_be32(fc
);
928 changed
|= IEEE802154_LLSEC_PARAM_FRAME_COUNTER
;
931 rc
= ops
->llsec
->set_params(dev
, ¶ms
, changed
);
943 struct llsec_dump_data
{
948 struct net_device
*dev
;
949 struct ieee802154_mlme_ops
*ops
;
950 struct ieee802154_llsec_table
*table
;
954 ieee802154_llsec_dump_table(struct sk_buff
*skb
, struct netlink_callback
*cb
,
955 int (*step
)(struct llsec_dump_data
*))
957 struct net
*net
= sock_net(skb
->sk
);
958 struct net_device
*dev
;
959 struct llsec_dump_data data
;
961 int first_dev
= cb
->args
[0];
964 for_each_netdev(net
, dev
) {
965 if (idx
< first_dev
|| dev
->type
!= ARPHRD_IEEE802154
)
968 data
.ops
= ieee802154_mlme_ops(dev
);
969 if (!data
.ops
->llsec
)
973 data
.s_idx
= cb
->args
[1];
974 data
.s_idx2
= cb
->args
[2];
976 data
.portid
= NETLINK_CB(cb
->skb
).portid
;
977 data
.nlmsg_seq
= cb
->nlh
->nlmsg_seq
;
979 data
.ops
->llsec
->lock_table(dev
);
980 data
.ops
->llsec
->get_table(data
.dev
, &data
.table
);
982 data
.ops
->llsec
->unlock_table(dev
);
996 ieee802154_nl_llsec_change(struct sk_buff
*skb
, struct genl_info
*info
,
997 int (*fn
)(struct net_device
*, struct genl_info
*))
999 struct net_device
*dev
= NULL
;
1002 dev
= ieee802154_nl_get_dev(info
);
1006 if (!ieee802154_mlme_ops(dev
)->llsec
)
1018 ieee802154_llsec_parse_key(struct genl_info
*info
,
1019 struct ieee802154_llsec_key
*key
)
1022 u32 commands
[256 / 32];
1024 memset(key
, 0, sizeof(*key
));
1026 if (!info
->attrs
[IEEE802154_ATTR_LLSEC_KEY_USAGE_FRAME_TYPES
] ||
1027 !info
->attrs
[IEEE802154_ATTR_LLSEC_KEY_BYTES
])
1030 frames
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_LLSEC_KEY_USAGE_FRAME_TYPES
]);
1031 if ((frames
& BIT(IEEE802154_FC_TYPE_MAC_CMD
)) &&
1032 !info
->attrs
[IEEE802154_ATTR_LLSEC_KEY_USAGE_COMMANDS
])
1035 if (info
->attrs
[IEEE802154_ATTR_LLSEC_KEY_USAGE_COMMANDS
]) {
1036 nla_memcpy(commands
,
1037 info
->attrs
[IEEE802154_ATTR_LLSEC_KEY_USAGE_COMMANDS
],
1040 if (commands
[0] || commands
[1] || commands
[2] || commands
[3] ||
1041 commands
[4] || commands
[5] || commands
[6] ||
1042 commands
[7] >= BIT(IEEE802154_CMD_GTS_REQ
+ 1))
1045 key
->cmd_frame_ids
= commands
[7];
1048 key
->frame_types
= frames
;
1050 nla_memcpy(key
->key
, info
->attrs
[IEEE802154_ATTR_LLSEC_KEY_BYTES
],
1051 IEEE802154_LLSEC_KEY_SIZE
);
1056 static int llsec_add_key(struct net_device
*dev
, struct genl_info
*info
)
1058 struct ieee802154_mlme_ops
*ops
= ieee802154_mlme_ops(dev
);
1059 struct ieee802154_llsec_key key
;
1060 struct ieee802154_llsec_key_id id
;
1062 if (ieee802154_llsec_parse_key(info
, &key
) ||
1063 ieee802154_llsec_parse_key_id(info
, &id
))
1066 return ops
->llsec
->add_key(dev
, &id
, &key
);
1069 int ieee802154_llsec_add_key(struct sk_buff
*skb
, struct genl_info
*info
)
1071 if ((info
->nlhdr
->nlmsg_flags
& (NLM_F_CREATE
| NLM_F_EXCL
)) !=
1072 (NLM_F_CREATE
| NLM_F_EXCL
))
1075 return ieee802154_nl_llsec_change(skb
, info
, llsec_add_key
);
1078 static int llsec_remove_key(struct net_device
*dev
, struct genl_info
*info
)
1080 struct ieee802154_mlme_ops
*ops
= ieee802154_mlme_ops(dev
);
1081 struct ieee802154_llsec_key_id id
;
1083 if (ieee802154_llsec_parse_key_id(info
, &id
))
1086 return ops
->llsec
->del_key(dev
, &id
);
1089 int ieee802154_llsec_del_key(struct sk_buff
*skb
, struct genl_info
*info
)
1091 return ieee802154_nl_llsec_change(skb
, info
, llsec_remove_key
);
1095 ieee802154_nl_fill_key(struct sk_buff
*msg
, u32 portid
, u32 seq
,
1096 const struct ieee802154_llsec_key_entry
*key
,
1097 const struct net_device
*dev
)
1100 u32 commands
[256 / 32];
1102 hdr
= genlmsg_put(msg
, 0, seq
, &nl802154_family
, NLM_F_MULTI
,
1103 IEEE802154_LLSEC_LIST_KEY
);
1107 if (nla_put_string(msg
, IEEE802154_ATTR_DEV_NAME
, dev
->name
) ||
1108 nla_put_u32(msg
, IEEE802154_ATTR_DEV_INDEX
, dev
->ifindex
) ||
1109 ieee802154_llsec_fill_key_id(msg
, &key
->id
) ||
1110 nla_put_u8(msg
, IEEE802154_ATTR_LLSEC_KEY_USAGE_FRAME_TYPES
,
1111 key
->key
->frame_types
))
1112 goto nla_put_failure
;
1114 if (key
->key
->frame_types
& BIT(IEEE802154_FC_TYPE_MAC_CMD
)) {
1115 memset(commands
, 0, sizeof(commands
));
1116 commands
[7] = key
->key
->cmd_frame_ids
;
1117 if (nla_put(msg
, IEEE802154_ATTR_LLSEC_KEY_USAGE_COMMANDS
,
1118 sizeof(commands
), commands
))
1119 goto nla_put_failure
;
1122 if (nla_put(msg
, IEEE802154_ATTR_LLSEC_KEY_BYTES
,
1123 IEEE802154_LLSEC_KEY_SIZE
, key
->key
->key
))
1124 goto nla_put_failure
;
1126 genlmsg_end(msg
, hdr
);
1130 genlmsg_cancel(msg
, hdr
);
1135 static int llsec_iter_keys(struct llsec_dump_data
*data
)
1137 struct ieee802154_llsec_key_entry
*pos
;
1138 int rc
= 0, idx
= 0;
1140 list_for_each_entry(pos
, &data
->table
->keys
, list
) {
1141 if (idx
++ < data
->s_idx
)
1144 if (ieee802154_nl_fill_key(data
->skb
, data
->portid
,
1145 data
->nlmsg_seq
, pos
, data
->dev
)) {
1156 int ieee802154_llsec_dump_keys(struct sk_buff
*skb
, struct netlink_callback
*cb
)
1158 return ieee802154_llsec_dump_table(skb
, cb
, llsec_iter_keys
);
1164 llsec_parse_dev(struct genl_info
*info
,
1165 struct ieee802154_llsec_device
*dev
)
1167 memset(dev
, 0, sizeof(*dev
));
1169 if (!info
->attrs
[IEEE802154_ATTR_LLSEC_FRAME_COUNTER
] ||
1170 !info
->attrs
[IEEE802154_ATTR_HW_ADDR
] ||
1171 !info
->attrs
[IEEE802154_ATTR_LLSEC_DEV_OVERRIDE
] ||
1172 !info
->attrs
[IEEE802154_ATTR_LLSEC_DEV_KEY_MODE
] ||
1173 (!!info
->attrs
[IEEE802154_ATTR_PAN_ID
] !=
1174 !!info
->attrs
[IEEE802154_ATTR_SHORT_ADDR
]))
1177 if (info
->attrs
[IEEE802154_ATTR_PAN_ID
]) {
1178 dev
->pan_id
= nla_get_shortaddr(info
->attrs
[IEEE802154_ATTR_PAN_ID
]);
1179 dev
->short_addr
= nla_get_shortaddr(info
->attrs
[IEEE802154_ATTR_SHORT_ADDR
]);
1181 dev
->short_addr
= cpu_to_le16(IEEE802154_ADDR_UNDEF
);
1184 dev
->hwaddr
= nla_get_hwaddr(info
->attrs
[IEEE802154_ATTR_HW_ADDR
]);
1185 dev
->frame_counter
= nla_get_u32(info
->attrs
[IEEE802154_ATTR_LLSEC_FRAME_COUNTER
]);
1186 dev
->seclevel_exempt
= !!nla_get_u8(info
->attrs
[IEEE802154_ATTR_LLSEC_DEV_OVERRIDE
]);
1187 dev
->key_mode
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_LLSEC_DEV_KEY_MODE
]);
1189 if (dev
->key_mode
>= __IEEE802154_LLSEC_DEVKEY_MAX
)
1195 static int llsec_add_dev(struct net_device
*dev
, struct genl_info
*info
)
1197 struct ieee802154_mlme_ops
*ops
= ieee802154_mlme_ops(dev
);
1198 struct ieee802154_llsec_device desc
;
1200 if (llsec_parse_dev(info
, &desc
))
1203 return ops
->llsec
->add_dev(dev
, &desc
);
1206 int ieee802154_llsec_add_dev(struct sk_buff
*skb
, struct genl_info
*info
)
1208 if ((info
->nlhdr
->nlmsg_flags
& (NLM_F_CREATE
| NLM_F_EXCL
)) !=
1209 (NLM_F_CREATE
| NLM_F_EXCL
))
1212 return ieee802154_nl_llsec_change(skb
, info
, llsec_add_dev
);
1215 static int llsec_del_dev(struct net_device
*dev
, struct genl_info
*info
)
1217 struct ieee802154_mlme_ops
*ops
= ieee802154_mlme_ops(dev
);
1220 if (!info
->attrs
[IEEE802154_ATTR_HW_ADDR
])
1223 devaddr
= nla_get_hwaddr(info
->attrs
[IEEE802154_ATTR_HW_ADDR
]);
1225 return ops
->llsec
->del_dev(dev
, devaddr
);
1228 int ieee802154_llsec_del_dev(struct sk_buff
*skb
, struct genl_info
*info
)
1230 return ieee802154_nl_llsec_change(skb
, info
, llsec_del_dev
);
1234 ieee802154_nl_fill_dev(struct sk_buff
*msg
, u32 portid
, u32 seq
,
1235 const struct ieee802154_llsec_device
*desc
,
1236 const struct net_device
*dev
)
1240 hdr
= genlmsg_put(msg
, 0, seq
, &nl802154_family
, NLM_F_MULTI
,
1241 IEEE802154_LLSEC_LIST_DEV
);
1245 if (nla_put_string(msg
, IEEE802154_ATTR_DEV_NAME
, dev
->name
) ||
1246 nla_put_u32(msg
, IEEE802154_ATTR_DEV_INDEX
, dev
->ifindex
) ||
1247 nla_put_shortaddr(msg
, IEEE802154_ATTR_PAN_ID
, desc
->pan_id
) ||
1248 nla_put_shortaddr(msg
, IEEE802154_ATTR_SHORT_ADDR
,
1249 desc
->short_addr
) ||
1250 nla_put_hwaddr(msg
, IEEE802154_ATTR_HW_ADDR
, desc
->hwaddr
) ||
1251 nla_put_u32(msg
, IEEE802154_ATTR_LLSEC_FRAME_COUNTER
,
1252 desc
->frame_counter
) ||
1253 nla_put_u8(msg
, IEEE802154_ATTR_LLSEC_DEV_OVERRIDE
,
1254 desc
->seclevel_exempt
) ||
1255 nla_put_u8(msg
, IEEE802154_ATTR_LLSEC_DEV_KEY_MODE
, desc
->key_mode
))
1256 goto nla_put_failure
;
1258 genlmsg_end(msg
, hdr
);
1262 genlmsg_cancel(msg
, hdr
);
1267 static int llsec_iter_devs(struct llsec_dump_data
*data
)
1269 struct ieee802154_llsec_device
*pos
;
1270 int rc
= 0, idx
= 0;
1272 list_for_each_entry(pos
, &data
->table
->devices
, list
) {
1273 if (idx
++ < data
->s_idx
)
1276 if (ieee802154_nl_fill_dev(data
->skb
, data
->portid
,
1277 data
->nlmsg_seq
, pos
, data
->dev
)) {
1288 int ieee802154_llsec_dump_devs(struct sk_buff
*skb
, struct netlink_callback
*cb
)
1290 return ieee802154_llsec_dump_table(skb
, cb
, llsec_iter_devs
);
1295 static int llsec_add_devkey(struct net_device
*dev
, struct genl_info
*info
)
1297 struct ieee802154_mlme_ops
*ops
= ieee802154_mlme_ops(dev
);
1298 struct ieee802154_llsec_device_key key
;
1301 if (!info
->attrs
[IEEE802154_ATTR_LLSEC_FRAME_COUNTER
] ||
1302 !info
->attrs
[IEEE802154_ATTR_HW_ADDR
] ||
1303 ieee802154_llsec_parse_key_id(info
, &key
.key_id
))
1306 devaddr
= nla_get_hwaddr(info
->attrs
[IEEE802154_ATTR_HW_ADDR
]);
1307 key
.frame_counter
= nla_get_u32(info
->attrs
[IEEE802154_ATTR_LLSEC_FRAME_COUNTER
]);
1309 return ops
->llsec
->add_devkey(dev
, devaddr
, &key
);
1312 int ieee802154_llsec_add_devkey(struct sk_buff
*skb
, struct genl_info
*info
)
1314 if ((info
->nlhdr
->nlmsg_flags
& (NLM_F_CREATE
| NLM_F_EXCL
)) !=
1315 (NLM_F_CREATE
| NLM_F_EXCL
))
1318 return ieee802154_nl_llsec_change(skb
, info
, llsec_add_devkey
);
1321 static int llsec_del_devkey(struct net_device
*dev
, struct genl_info
*info
)
1323 struct ieee802154_mlme_ops
*ops
= ieee802154_mlme_ops(dev
);
1324 struct ieee802154_llsec_device_key key
;
1327 if (!info
->attrs
[IEEE802154_ATTR_HW_ADDR
] ||
1328 ieee802154_llsec_parse_key_id(info
, &key
.key_id
))
1331 devaddr
= nla_get_hwaddr(info
->attrs
[IEEE802154_ATTR_HW_ADDR
]);
1333 return ops
->llsec
->del_devkey(dev
, devaddr
, &key
);
1336 int ieee802154_llsec_del_devkey(struct sk_buff
*skb
, struct genl_info
*info
)
1338 return ieee802154_nl_llsec_change(skb
, info
, llsec_del_devkey
);
1342 ieee802154_nl_fill_devkey(struct sk_buff
*msg
, u32 portid
, u32 seq
,
1344 const struct ieee802154_llsec_device_key
*devkey
,
1345 const struct net_device
*dev
)
1349 hdr
= genlmsg_put(msg
, 0, seq
, &nl802154_family
, NLM_F_MULTI
,
1350 IEEE802154_LLSEC_LIST_DEVKEY
);
1354 if (nla_put_string(msg
, IEEE802154_ATTR_DEV_NAME
, dev
->name
) ||
1355 nla_put_u32(msg
, IEEE802154_ATTR_DEV_INDEX
, dev
->ifindex
) ||
1356 nla_put_hwaddr(msg
, IEEE802154_ATTR_HW_ADDR
, devaddr
) ||
1357 nla_put_u32(msg
, IEEE802154_ATTR_LLSEC_FRAME_COUNTER
,
1358 devkey
->frame_counter
) ||
1359 ieee802154_llsec_fill_key_id(msg
, &devkey
->key_id
))
1360 goto nla_put_failure
;
1362 genlmsg_end(msg
, hdr
);
1366 genlmsg_cancel(msg
, hdr
);
1371 static int llsec_iter_devkeys(struct llsec_dump_data
*data
)
1373 struct ieee802154_llsec_device
*dpos
;
1374 struct ieee802154_llsec_device_key
*kpos
;
1375 int rc
= 0, idx
= 0, idx2
;
1377 list_for_each_entry(dpos
, &data
->table
->devices
, list
) {
1378 if (idx
++ < data
->s_idx
)
1383 list_for_each_entry(kpos
, &dpos
->keys
, list
) {
1384 if (idx2
++ < data
->s_idx2
)
1387 if (ieee802154_nl_fill_devkey(data
->skb
, data
->portid
,
1391 return rc
= -EMSGSIZE
;
1403 int ieee802154_llsec_dump_devkeys(struct sk_buff
*skb
,
1404 struct netlink_callback
*cb
)
1406 return ieee802154_llsec_dump_table(skb
, cb
, llsec_iter_devkeys
);
1412 llsec_parse_seclevel(struct genl_info
*info
,
1413 struct ieee802154_llsec_seclevel
*sl
)
1415 memset(sl
, 0, sizeof(*sl
));
1417 if (!info
->attrs
[IEEE802154_ATTR_LLSEC_FRAME_TYPE
] ||
1418 !info
->attrs
[IEEE802154_ATTR_LLSEC_SECLEVELS
] ||
1419 !info
->attrs
[IEEE802154_ATTR_LLSEC_DEV_OVERRIDE
])
1422 sl
->frame_type
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_LLSEC_FRAME_TYPE
]);
1423 if (sl
->frame_type
== IEEE802154_FC_TYPE_MAC_CMD
) {
1424 if (!info
->attrs
[IEEE802154_ATTR_LLSEC_CMD_FRAME_ID
])
1427 sl
->cmd_frame_id
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_LLSEC_CMD_FRAME_ID
]);
1430 sl
->sec_levels
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_LLSEC_SECLEVELS
]);
1431 sl
->device_override
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_LLSEC_DEV_OVERRIDE
]);
1436 static int llsec_add_seclevel(struct net_device
*dev
, struct genl_info
*info
)
1438 struct ieee802154_mlme_ops
*ops
= ieee802154_mlme_ops(dev
);
1439 struct ieee802154_llsec_seclevel sl
;
1441 if (llsec_parse_seclevel(info
, &sl
))
1444 return ops
->llsec
->add_seclevel(dev
, &sl
);
1447 int ieee802154_llsec_add_seclevel(struct sk_buff
*skb
, struct genl_info
*info
)
1449 if ((info
->nlhdr
->nlmsg_flags
& (NLM_F_CREATE
| NLM_F_EXCL
)) !=
1450 (NLM_F_CREATE
| NLM_F_EXCL
))
1453 return ieee802154_nl_llsec_change(skb
, info
, llsec_add_seclevel
);
1456 static int llsec_del_seclevel(struct net_device
*dev
, struct genl_info
*info
)
1458 struct ieee802154_mlme_ops
*ops
= ieee802154_mlme_ops(dev
);
1459 struct ieee802154_llsec_seclevel sl
;
1461 if (llsec_parse_seclevel(info
, &sl
))
1464 return ops
->llsec
->del_seclevel(dev
, &sl
);
1467 int ieee802154_llsec_del_seclevel(struct sk_buff
*skb
, struct genl_info
*info
)
1469 return ieee802154_nl_llsec_change(skb
, info
, llsec_del_seclevel
);
1473 ieee802154_nl_fill_seclevel(struct sk_buff
*msg
, u32 portid
, u32 seq
,
1474 const struct ieee802154_llsec_seclevel
*sl
,
1475 const struct net_device
*dev
)
1479 hdr
= genlmsg_put(msg
, 0, seq
, &nl802154_family
, NLM_F_MULTI
,
1480 IEEE802154_LLSEC_LIST_SECLEVEL
);
1484 if (nla_put_string(msg
, IEEE802154_ATTR_DEV_NAME
, dev
->name
) ||
1485 nla_put_u32(msg
, IEEE802154_ATTR_DEV_INDEX
, dev
->ifindex
) ||
1486 nla_put_u8(msg
, IEEE802154_ATTR_LLSEC_FRAME_TYPE
, sl
->frame_type
) ||
1487 nla_put_u8(msg
, IEEE802154_ATTR_LLSEC_SECLEVELS
, sl
->sec_levels
) ||
1488 nla_put_u8(msg
, IEEE802154_ATTR_LLSEC_DEV_OVERRIDE
,
1489 sl
->device_override
))
1490 goto nla_put_failure
;
1492 if (sl
->frame_type
== IEEE802154_FC_TYPE_MAC_CMD
&&
1493 nla_put_u8(msg
, IEEE802154_ATTR_LLSEC_CMD_FRAME_ID
,
1495 goto nla_put_failure
;
1497 genlmsg_end(msg
, hdr
);
1501 genlmsg_cancel(msg
, hdr
);
1506 static int llsec_iter_seclevels(struct llsec_dump_data
*data
)
1508 struct ieee802154_llsec_seclevel
*pos
;
1509 int rc
= 0, idx
= 0;
1511 list_for_each_entry(pos
, &data
->table
->security_levels
, list
) {
1512 if (idx
++ < data
->s_idx
)
1515 if (ieee802154_nl_fill_seclevel(data
->skb
, data
->portid
,
1516 data
->nlmsg_seq
, pos
,
1528 int ieee802154_llsec_dump_seclevels(struct sk_buff
*skb
,
1529 struct netlink_callback
*cb
)
1531 return ieee802154_llsec_dump_table(skb
, cb
, llsec_iter_seclevels
);