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
, u8 cap
)
67 pr_debug("%s\n", __func__
);
69 if (addr
->mode
!= IEEE802154_ADDR_LONG
) {
70 pr_err("%s: received non-long source address!\n", __func__
);
74 msg
= ieee802154_nl_create(0, IEEE802154_ASSOCIATE_INDIC
);
78 if (nla_put_string(msg
, IEEE802154_ATTR_DEV_NAME
, dev
->name
) ||
79 nla_put_u32(msg
, IEEE802154_ATTR_DEV_INDEX
, dev
->ifindex
) ||
80 nla_put(msg
, IEEE802154_ATTR_HW_ADDR
, IEEE802154_ADDR_LEN
,
82 nla_put_hwaddr(msg
, IEEE802154_ATTR_SRC_HW_ADDR
,
83 addr
->extended_addr
) ||
84 nla_put_u8(msg
, IEEE802154_ATTR_CAPABILITY
, cap
))
87 return ieee802154_nl_mcast(msg
, IEEE802154_COORD_MCGRP
);
93 EXPORT_SYMBOL(ieee802154_nl_assoc_indic
);
95 int ieee802154_nl_assoc_confirm(struct net_device
*dev
, __le16 short_addr
,
100 pr_debug("%s\n", __func__
);
102 msg
= ieee802154_nl_create(0, IEEE802154_ASSOCIATE_CONF
);
106 if (nla_put_string(msg
, IEEE802154_ATTR_DEV_NAME
, dev
->name
) ||
107 nla_put_u32(msg
, IEEE802154_ATTR_DEV_INDEX
, dev
->ifindex
) ||
108 nla_put(msg
, IEEE802154_ATTR_HW_ADDR
, IEEE802154_ADDR_LEN
,
110 nla_put_shortaddr(msg
, IEEE802154_ATTR_SHORT_ADDR
, short_addr
) ||
111 nla_put_u8(msg
, IEEE802154_ATTR_STATUS
, status
))
112 goto nla_put_failure
;
113 return ieee802154_nl_mcast(msg
, IEEE802154_COORD_MCGRP
);
119 EXPORT_SYMBOL(ieee802154_nl_assoc_confirm
);
121 int ieee802154_nl_disassoc_indic(struct net_device
*dev
,
122 struct ieee802154_addr
*addr
, u8 reason
)
126 pr_debug("%s\n", __func__
);
128 msg
= ieee802154_nl_create(0, IEEE802154_DISASSOCIATE_INDIC
);
132 if (nla_put_string(msg
, IEEE802154_ATTR_DEV_NAME
, dev
->name
) ||
133 nla_put_u32(msg
, IEEE802154_ATTR_DEV_INDEX
, dev
->ifindex
) ||
134 nla_put(msg
, IEEE802154_ATTR_HW_ADDR
, IEEE802154_ADDR_LEN
,
136 goto nla_put_failure
;
137 if (addr
->mode
== IEEE802154_ADDR_LONG
) {
138 if (nla_put_hwaddr(msg
, IEEE802154_ATTR_SRC_HW_ADDR
,
139 addr
->extended_addr
))
140 goto nla_put_failure
;
142 if (nla_put_shortaddr(msg
, IEEE802154_ATTR_SRC_SHORT_ADDR
,
144 goto nla_put_failure
;
146 if (nla_put_u8(msg
, IEEE802154_ATTR_REASON
, reason
))
147 goto nla_put_failure
;
148 return ieee802154_nl_mcast(msg
, IEEE802154_COORD_MCGRP
);
154 EXPORT_SYMBOL(ieee802154_nl_disassoc_indic
);
156 int ieee802154_nl_disassoc_confirm(struct net_device
*dev
, u8 status
)
160 pr_debug("%s\n", __func__
);
162 msg
= ieee802154_nl_create(0, IEEE802154_DISASSOCIATE_CONF
);
166 if (nla_put_string(msg
, IEEE802154_ATTR_DEV_NAME
, dev
->name
) ||
167 nla_put_u32(msg
, IEEE802154_ATTR_DEV_INDEX
, dev
->ifindex
) ||
168 nla_put(msg
, IEEE802154_ATTR_HW_ADDR
, IEEE802154_ADDR_LEN
,
170 nla_put_u8(msg
, IEEE802154_ATTR_STATUS
, status
))
171 goto nla_put_failure
;
172 return ieee802154_nl_mcast(msg
, IEEE802154_COORD_MCGRP
);
178 EXPORT_SYMBOL(ieee802154_nl_disassoc_confirm
);
180 int ieee802154_nl_beacon_indic(struct net_device
*dev
, __le16 panid
,
185 pr_debug("%s\n", __func__
);
187 msg
= ieee802154_nl_create(0, IEEE802154_BEACON_NOTIFY_INDIC
);
191 if (nla_put_string(msg
, IEEE802154_ATTR_DEV_NAME
, dev
->name
) ||
192 nla_put_u32(msg
, IEEE802154_ATTR_DEV_INDEX
, dev
->ifindex
) ||
193 nla_put(msg
, IEEE802154_ATTR_HW_ADDR
, IEEE802154_ADDR_LEN
,
195 nla_put_shortaddr(msg
, IEEE802154_ATTR_COORD_SHORT_ADDR
,
197 nla_put_shortaddr(msg
, IEEE802154_ATTR_COORD_PAN_ID
, panid
))
198 goto nla_put_failure
;
199 return ieee802154_nl_mcast(msg
, IEEE802154_COORD_MCGRP
);
205 EXPORT_SYMBOL(ieee802154_nl_beacon_indic
);
207 int ieee802154_nl_scan_confirm(struct net_device
*dev
,
208 u8 status
, u8 scan_type
, u32 unscanned
, u8 page
,
209 u8
*edl
/* , struct list_head *pan_desc_list */)
213 pr_debug("%s\n", __func__
);
215 msg
= ieee802154_nl_create(0, IEEE802154_SCAN_CONF
);
219 if (nla_put_string(msg
, IEEE802154_ATTR_DEV_NAME
, dev
->name
) ||
220 nla_put_u32(msg
, IEEE802154_ATTR_DEV_INDEX
, dev
->ifindex
) ||
221 nla_put(msg
, IEEE802154_ATTR_HW_ADDR
, IEEE802154_ADDR_LEN
,
223 nla_put_u8(msg
, IEEE802154_ATTR_STATUS
, status
) ||
224 nla_put_u8(msg
, IEEE802154_ATTR_SCAN_TYPE
, scan_type
) ||
225 nla_put_u32(msg
, IEEE802154_ATTR_CHANNELS
, unscanned
) ||
226 nla_put_u8(msg
, IEEE802154_ATTR_PAGE
, page
) ||
228 nla_put(msg
, IEEE802154_ATTR_ED_LIST
, 27, edl
)))
229 goto nla_put_failure
;
230 return ieee802154_nl_mcast(msg
, IEEE802154_COORD_MCGRP
);
236 EXPORT_SYMBOL(ieee802154_nl_scan_confirm
);
238 int ieee802154_nl_start_confirm(struct net_device
*dev
, u8 status
)
242 pr_debug("%s\n", __func__
);
244 msg
= ieee802154_nl_create(0, IEEE802154_START_CONF
);
248 if (nla_put_string(msg
, IEEE802154_ATTR_DEV_NAME
, dev
->name
) ||
249 nla_put_u32(msg
, IEEE802154_ATTR_DEV_INDEX
, dev
->ifindex
) ||
250 nla_put(msg
, IEEE802154_ATTR_HW_ADDR
, IEEE802154_ADDR_LEN
,
252 nla_put_u8(msg
, IEEE802154_ATTR_STATUS
, status
))
253 goto nla_put_failure
;
254 return ieee802154_nl_mcast(msg
, IEEE802154_COORD_MCGRP
);
260 EXPORT_SYMBOL(ieee802154_nl_start_confirm
);
262 static int ieee802154_nl_fill_iface(struct sk_buff
*msg
, u32 portid
,
263 u32 seq
, int flags
, struct net_device
*dev
)
266 struct wpan_phy
*phy
;
267 struct ieee802154_mlme_ops
*ops
;
268 __le16 short_addr
, pan_id
;
270 pr_debug("%s\n", __func__
);
272 hdr
= genlmsg_put(msg
, 0, seq
, &nl802154_family
, flags
,
273 IEEE802154_LIST_IFACE
);
277 ops
= ieee802154_mlme_ops(dev
);
278 phy
= ops
->get_phy(dev
);
281 short_addr
= ops
->get_short_addr(dev
);
282 pan_id
= ops
->get_pan_id(dev
);
284 if (nla_put_string(msg
, IEEE802154_ATTR_DEV_NAME
, dev
->name
) ||
285 nla_put_string(msg
, IEEE802154_ATTR_PHY_NAME
, wpan_phy_name(phy
)) ||
286 nla_put_u32(msg
, IEEE802154_ATTR_DEV_INDEX
, dev
->ifindex
) ||
287 nla_put(msg
, IEEE802154_ATTR_HW_ADDR
, IEEE802154_ADDR_LEN
,
289 nla_put_shortaddr(msg
, IEEE802154_ATTR_SHORT_ADDR
, short_addr
) ||
290 nla_put_shortaddr(msg
, IEEE802154_ATTR_PAN_ID
, pan_id
))
291 goto nla_put_failure
;
293 if (ops
->get_mac_params
) {
294 struct ieee802154_mac_params params
;
296 ops
->get_mac_params(dev
, ¶ms
);
298 if (nla_put_s8(msg
, IEEE802154_ATTR_TXPOWER
,
299 params
.transmit_power
) ||
300 nla_put_u8(msg
, IEEE802154_ATTR_LBT_ENABLED
, params
.lbt
) ||
301 nla_put_u8(msg
, IEEE802154_ATTR_CCA_MODE
,
303 nla_put_s32(msg
, IEEE802154_ATTR_CCA_ED_LEVEL
,
304 params
.cca_ed_level
) ||
305 nla_put_u8(msg
, IEEE802154_ATTR_CSMA_RETRIES
,
306 params
.csma_retries
) ||
307 nla_put_u8(msg
, IEEE802154_ATTR_CSMA_MIN_BE
,
309 nla_put_u8(msg
, IEEE802154_ATTR_CSMA_MAX_BE
,
311 nla_put_s8(msg
, IEEE802154_ATTR_FRAME_RETRIES
,
312 params
.frame_retries
))
313 goto nla_put_failure
;
317 return genlmsg_end(msg
, hdr
);
321 genlmsg_cancel(msg
, hdr
);
326 /* Requests from userspace */
327 static struct net_device
*ieee802154_nl_get_dev(struct genl_info
*info
)
329 struct net_device
*dev
;
331 if (info
->attrs
[IEEE802154_ATTR_DEV_NAME
]) {
332 char name
[IFNAMSIZ
+ 1];
333 nla_strlcpy(name
, info
->attrs
[IEEE802154_ATTR_DEV_NAME
],
335 dev
= dev_get_by_name(&init_net
, name
);
336 } else if (info
->attrs
[IEEE802154_ATTR_DEV_INDEX
])
337 dev
= dev_get_by_index(&init_net
,
338 nla_get_u32(info
->attrs
[IEEE802154_ATTR_DEV_INDEX
]));
345 if (dev
->type
!= ARPHRD_IEEE802154
) {
353 int ieee802154_associate_req(struct sk_buff
*skb
, struct genl_info
*info
)
355 struct net_device
*dev
;
356 struct ieee802154_addr addr
;
358 int ret
= -EOPNOTSUPP
;
360 if (!info
->attrs
[IEEE802154_ATTR_CHANNEL
] ||
361 !info
->attrs
[IEEE802154_ATTR_COORD_PAN_ID
] ||
362 (!info
->attrs
[IEEE802154_ATTR_COORD_HW_ADDR
] &&
363 !info
->attrs
[IEEE802154_ATTR_COORD_SHORT_ADDR
]) ||
364 !info
->attrs
[IEEE802154_ATTR_CAPABILITY
])
367 dev
= ieee802154_nl_get_dev(info
);
370 if (!ieee802154_mlme_ops(dev
)->assoc_req
)
373 if (info
->attrs
[IEEE802154_ATTR_COORD_HW_ADDR
]) {
374 addr
.mode
= IEEE802154_ADDR_LONG
;
375 addr
.extended_addr
= nla_get_hwaddr(
376 info
->attrs
[IEEE802154_ATTR_COORD_HW_ADDR
]);
378 addr
.mode
= IEEE802154_ADDR_SHORT
;
379 addr
.short_addr
= nla_get_shortaddr(
380 info
->attrs
[IEEE802154_ATTR_COORD_SHORT_ADDR
]);
382 addr
.pan_id
= nla_get_shortaddr(
383 info
->attrs
[IEEE802154_ATTR_COORD_PAN_ID
]);
385 if (info
->attrs
[IEEE802154_ATTR_PAGE
])
386 page
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_PAGE
]);
390 ret
= ieee802154_mlme_ops(dev
)->assoc_req(dev
, &addr
,
391 nla_get_u8(info
->attrs
[IEEE802154_ATTR_CHANNEL
]),
393 nla_get_u8(info
->attrs
[IEEE802154_ATTR_CAPABILITY
]));
400 int ieee802154_associate_resp(struct sk_buff
*skb
, struct genl_info
*info
)
402 struct net_device
*dev
;
403 struct ieee802154_addr addr
;
404 int ret
= -EOPNOTSUPP
;
406 if (!info
->attrs
[IEEE802154_ATTR_STATUS
] ||
407 !info
->attrs
[IEEE802154_ATTR_DEST_HW_ADDR
] ||
408 !info
->attrs
[IEEE802154_ATTR_DEST_SHORT_ADDR
])
411 dev
= ieee802154_nl_get_dev(info
);
414 if (!ieee802154_mlme_ops(dev
)->assoc_resp
)
417 addr
.mode
= IEEE802154_ADDR_LONG
;
418 addr
.extended_addr
= nla_get_hwaddr(
419 info
->attrs
[IEEE802154_ATTR_DEST_HW_ADDR
]);
420 addr
.pan_id
= ieee802154_mlme_ops(dev
)->get_pan_id(dev
);
422 ret
= ieee802154_mlme_ops(dev
)->assoc_resp(dev
, &addr
,
423 nla_get_shortaddr(info
->attrs
[IEEE802154_ATTR_DEST_SHORT_ADDR
]),
424 nla_get_u8(info
->attrs
[IEEE802154_ATTR_STATUS
]));
431 int ieee802154_disassociate_req(struct sk_buff
*skb
, struct genl_info
*info
)
433 struct net_device
*dev
;
434 struct ieee802154_addr addr
;
435 int ret
= -EOPNOTSUPP
;
437 if ((!info
->attrs
[IEEE802154_ATTR_DEST_HW_ADDR
] &&
438 !info
->attrs
[IEEE802154_ATTR_DEST_SHORT_ADDR
]) ||
439 !info
->attrs
[IEEE802154_ATTR_REASON
])
442 dev
= ieee802154_nl_get_dev(info
);
445 if (!ieee802154_mlme_ops(dev
)->disassoc_req
)
448 if (info
->attrs
[IEEE802154_ATTR_DEST_HW_ADDR
]) {
449 addr
.mode
= IEEE802154_ADDR_LONG
;
450 addr
.extended_addr
= nla_get_hwaddr(
451 info
->attrs
[IEEE802154_ATTR_DEST_HW_ADDR
]);
453 addr
.mode
= IEEE802154_ADDR_SHORT
;
454 addr
.short_addr
= nla_get_shortaddr(
455 info
->attrs
[IEEE802154_ATTR_DEST_SHORT_ADDR
]);
457 addr
.pan_id
= ieee802154_mlme_ops(dev
)->get_pan_id(dev
);
459 ret
= ieee802154_mlme_ops(dev
)->disassoc_req(dev
, &addr
,
460 nla_get_u8(info
->attrs
[IEEE802154_ATTR_REASON
]));
468 * PANid, channel, beacon_order = 15, superframe_order = 15,
469 * PAN_coordinator, battery_life_extension = 0,
470 * coord_realignment = 0, security_enable = 0
472 int ieee802154_start_req(struct sk_buff
*skb
, struct genl_info
*info
)
474 struct net_device
*dev
;
475 struct ieee802154_addr addr
;
477 u8 channel
, bcn_ord
, sf_ord
;
479 int pan_coord
, blx
, coord_realign
;
480 int ret
= -EOPNOTSUPP
;
482 if (!info
->attrs
[IEEE802154_ATTR_COORD_PAN_ID
] ||
483 !info
->attrs
[IEEE802154_ATTR_COORD_SHORT_ADDR
] ||
484 !info
->attrs
[IEEE802154_ATTR_CHANNEL
] ||
485 !info
->attrs
[IEEE802154_ATTR_BCN_ORD
] ||
486 !info
->attrs
[IEEE802154_ATTR_SF_ORD
] ||
487 !info
->attrs
[IEEE802154_ATTR_PAN_COORD
] ||
488 !info
->attrs
[IEEE802154_ATTR_BAT_EXT
] ||
489 !info
->attrs
[IEEE802154_ATTR_COORD_REALIGN
]
493 dev
= ieee802154_nl_get_dev(info
);
496 if (!ieee802154_mlme_ops(dev
)->start_req
)
499 addr
.mode
= IEEE802154_ADDR_SHORT
;
500 addr
.short_addr
= nla_get_shortaddr(
501 info
->attrs
[IEEE802154_ATTR_COORD_SHORT_ADDR
]);
502 addr
.pan_id
= nla_get_shortaddr(
503 info
->attrs
[IEEE802154_ATTR_COORD_PAN_ID
]);
505 channel
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_CHANNEL
]);
506 bcn_ord
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_BCN_ORD
]);
507 sf_ord
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_SF_ORD
]);
508 pan_coord
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_PAN_COORD
]);
509 blx
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_BAT_EXT
]);
510 coord_realign
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_COORD_REALIGN
]);
512 if (info
->attrs
[IEEE802154_ATTR_PAGE
])
513 page
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_PAGE
]);
518 if (addr
.short_addr
== cpu_to_le16(IEEE802154_ADDR_BROADCAST
)) {
519 ieee802154_nl_start_confirm(dev
, IEEE802154_NO_SHORT_ADDRESS
);
524 ret
= ieee802154_mlme_ops(dev
)->start_req(dev
, &addr
, channel
, page
,
525 bcn_ord
, sf_ord
, pan_coord
, blx
, coord_realign
);
532 int ieee802154_scan_req(struct sk_buff
*skb
, struct genl_info
*info
)
534 struct net_device
*dev
;
535 int ret
= -EOPNOTSUPP
;
541 if (!info
->attrs
[IEEE802154_ATTR_SCAN_TYPE
] ||
542 !info
->attrs
[IEEE802154_ATTR_CHANNELS
] ||
543 !info
->attrs
[IEEE802154_ATTR_DURATION
])
546 dev
= ieee802154_nl_get_dev(info
);
549 if (!ieee802154_mlme_ops(dev
)->scan_req
)
552 type
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_SCAN_TYPE
]);
553 channels
= nla_get_u32(info
->attrs
[IEEE802154_ATTR_CHANNELS
]);
554 duration
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_DURATION
]);
556 if (info
->attrs
[IEEE802154_ATTR_PAGE
])
557 page
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_PAGE
]);
562 ret
= ieee802154_mlme_ops(dev
)->scan_req(dev
, type
, channels
, page
,
570 int ieee802154_list_iface(struct sk_buff
*skb
, struct genl_info
*info
)
572 /* Request for interface name, index, type, IEEE address,
573 PAN Id, short address */
575 struct net_device
*dev
= NULL
;
578 pr_debug("%s\n", __func__
);
580 dev
= ieee802154_nl_get_dev(info
);
584 msg
= nlmsg_new(NLMSG_DEFAULT_SIZE
, GFP_KERNEL
);
588 rc
= ieee802154_nl_fill_iface(msg
, info
->snd_portid
, info
->snd_seq
,
595 return genlmsg_reply(msg
, info
);
604 int ieee802154_dump_iface(struct sk_buff
*skb
, struct netlink_callback
*cb
)
606 struct net
*net
= sock_net(skb
->sk
);
607 struct net_device
*dev
;
609 int s_idx
= cb
->args
[0];
611 pr_debug("%s\n", __func__
);
614 for_each_netdev(net
, dev
) {
615 if (idx
< s_idx
|| (dev
->type
!= ARPHRD_IEEE802154
))
618 if (ieee802154_nl_fill_iface(skb
, NETLINK_CB(cb
->skb
).portid
,
619 cb
->nlh
->nlmsg_seq
, NLM_F_MULTI
, dev
) < 0)
629 int ieee802154_set_macparams(struct sk_buff
*skb
, struct genl_info
*info
)
631 struct net_device
*dev
= NULL
;
632 struct ieee802154_mlme_ops
*ops
;
633 struct ieee802154_mac_params params
;
634 struct wpan_phy
*phy
;
637 pr_debug("%s\n", __func__
);
639 dev
= ieee802154_nl_get_dev(info
);
643 ops
= ieee802154_mlme_ops(dev
);
645 if (!ops
->get_mac_params
|| !ops
->set_mac_params
) {
650 if (netif_running(dev
)) {
655 if (!info
->attrs
[IEEE802154_ATTR_LBT_ENABLED
] &&
656 !info
->attrs
[IEEE802154_ATTR_CCA_MODE
] &&
657 !info
->attrs
[IEEE802154_ATTR_CCA_ED_LEVEL
] &&
658 !info
->attrs
[IEEE802154_ATTR_CSMA_RETRIES
] &&
659 !info
->attrs
[IEEE802154_ATTR_CSMA_MIN_BE
] &&
660 !info
->attrs
[IEEE802154_ATTR_CSMA_MAX_BE
] &&
661 !info
->attrs
[IEEE802154_ATTR_FRAME_RETRIES
])
664 phy
= ops
->get_phy(dev
);
666 if ((!phy
->set_lbt
&& info
->attrs
[IEEE802154_ATTR_LBT_ENABLED
]) ||
667 (!phy
->set_cca_mode
&& info
->attrs
[IEEE802154_ATTR_CCA_MODE
]) ||
668 (!phy
->set_cca_ed_level
&&
669 info
->attrs
[IEEE802154_ATTR_CCA_ED_LEVEL
]) ||
670 (!phy
->set_csma_params
&&
671 (info
->attrs
[IEEE802154_ATTR_CSMA_RETRIES
] ||
672 info
->attrs
[IEEE802154_ATTR_CSMA_MIN_BE
] ||
673 info
->attrs
[IEEE802154_ATTR_CSMA_MAX_BE
])) ||
674 (!phy
->set_frame_retries
&&
675 info
->attrs
[IEEE802154_ATTR_FRAME_RETRIES
])) {
680 ops
->get_mac_params(dev
, ¶ms
);
682 if (info
->attrs
[IEEE802154_ATTR_TXPOWER
])
683 params
.transmit_power
= nla_get_s8(info
->attrs
[IEEE802154_ATTR_TXPOWER
]);
685 if (info
->attrs
[IEEE802154_ATTR_LBT_ENABLED
])
686 params
.lbt
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_LBT_ENABLED
]);
688 if (info
->attrs
[IEEE802154_ATTR_CCA_MODE
])
689 params
.cca_mode
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_CCA_MODE
]);
691 if (info
->attrs
[IEEE802154_ATTR_CCA_ED_LEVEL
])
692 params
.cca_ed_level
= nla_get_s32(info
->attrs
[IEEE802154_ATTR_CCA_ED_LEVEL
]);
694 if (info
->attrs
[IEEE802154_ATTR_CSMA_RETRIES
])
695 params
.csma_retries
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_CSMA_RETRIES
]);
697 if (info
->attrs
[IEEE802154_ATTR_CSMA_MIN_BE
])
698 params
.min_be
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_CSMA_MIN_BE
]);
700 if (info
->attrs
[IEEE802154_ATTR_CSMA_MAX_BE
])
701 params
.max_be
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_CSMA_MAX_BE
]);
703 if (info
->attrs
[IEEE802154_ATTR_FRAME_RETRIES
])
704 params
.frame_retries
= nla_get_s8(info
->attrs
[IEEE802154_ATTR_FRAME_RETRIES
]);
706 rc
= ops
->set_mac_params(dev
, ¶ms
);
722 ieee802154_llsec_parse_key_id(struct genl_info
*info
,
723 struct ieee802154_llsec_key_id
*desc
)
725 memset(desc
, 0, sizeof(*desc
));
727 if (!info
->attrs
[IEEE802154_ATTR_LLSEC_KEY_MODE
])
730 desc
->mode
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_LLSEC_KEY_MODE
]);
732 if (desc
->mode
== IEEE802154_SCF_KEY_IMPLICIT
) {
733 if (!info
->attrs
[IEEE802154_ATTR_PAN_ID
] &&
734 !(info
->attrs
[IEEE802154_ATTR_SHORT_ADDR
] ||
735 info
->attrs
[IEEE802154_ATTR_HW_ADDR
]))
738 desc
->device_addr
.pan_id
= nla_get_shortaddr(info
->attrs
[IEEE802154_ATTR_PAN_ID
]);
740 if (info
->attrs
[IEEE802154_ATTR_SHORT_ADDR
]) {
741 desc
->device_addr
.mode
= IEEE802154_ADDR_SHORT
;
742 desc
->device_addr
.short_addr
= nla_get_shortaddr(info
->attrs
[IEEE802154_ATTR_SHORT_ADDR
]);
744 desc
->device_addr
.mode
= IEEE802154_ADDR_LONG
;
745 desc
->device_addr
.extended_addr
= nla_get_hwaddr(info
->attrs
[IEEE802154_ATTR_HW_ADDR
]);
749 if (desc
->mode
!= IEEE802154_SCF_KEY_IMPLICIT
&&
750 !info
->attrs
[IEEE802154_ATTR_LLSEC_KEY_ID
])
753 if (desc
->mode
== IEEE802154_SCF_KEY_SHORT_INDEX
&&
754 !info
->attrs
[IEEE802154_ATTR_LLSEC_KEY_SOURCE_SHORT
])
757 if (desc
->mode
== IEEE802154_SCF_KEY_HW_INDEX
&&
758 !info
->attrs
[IEEE802154_ATTR_LLSEC_KEY_SOURCE_EXTENDED
])
761 if (desc
->mode
!= IEEE802154_SCF_KEY_IMPLICIT
)
762 desc
->id
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_LLSEC_KEY_ID
]);
764 switch (desc
->mode
) {
765 case IEEE802154_SCF_KEY_SHORT_INDEX
:
767 u32 source
= nla_get_u32(info
->attrs
[IEEE802154_ATTR_LLSEC_KEY_SOURCE_SHORT
]);
768 desc
->short_source
= cpu_to_le32(source
);
771 case IEEE802154_SCF_KEY_HW_INDEX
:
772 desc
->extended_source
= nla_get_hwaddr(info
->attrs
[IEEE802154_ATTR_LLSEC_KEY_SOURCE_EXTENDED
]);
780 ieee802154_llsec_fill_key_id(struct sk_buff
*msg
,
781 const struct ieee802154_llsec_key_id
*desc
)
783 if (nla_put_u8(msg
, IEEE802154_ATTR_LLSEC_KEY_MODE
, desc
->mode
))
786 if (desc
->mode
== IEEE802154_SCF_KEY_IMPLICIT
) {
787 if (nla_put_shortaddr(msg
, IEEE802154_ATTR_PAN_ID
,
788 desc
->device_addr
.pan_id
))
791 if (desc
->device_addr
.mode
== IEEE802154_ADDR_SHORT
&&
792 nla_put_shortaddr(msg
, IEEE802154_ATTR_SHORT_ADDR
,
793 desc
->device_addr
.short_addr
))
796 if (desc
->device_addr
.mode
== IEEE802154_ADDR_LONG
&&
797 nla_put_hwaddr(msg
, IEEE802154_ATTR_HW_ADDR
,
798 desc
->device_addr
.extended_addr
))
802 if (desc
->mode
!= IEEE802154_SCF_KEY_IMPLICIT
&&
803 nla_put_u8(msg
, IEEE802154_ATTR_LLSEC_KEY_ID
, desc
->id
))
806 if (desc
->mode
== IEEE802154_SCF_KEY_SHORT_INDEX
&&
807 nla_put_u32(msg
, IEEE802154_ATTR_LLSEC_KEY_SOURCE_SHORT
,
808 le32_to_cpu(desc
->short_source
)))
811 if (desc
->mode
== IEEE802154_SCF_KEY_HW_INDEX
&&
812 nla_put_hwaddr(msg
, IEEE802154_ATTR_LLSEC_KEY_SOURCE_EXTENDED
,
813 desc
->extended_source
))
819 int ieee802154_llsec_getparams(struct sk_buff
*skb
, struct genl_info
*info
)
822 struct net_device
*dev
= NULL
;
824 struct ieee802154_mlme_ops
*ops
;
826 struct ieee802154_llsec_params params
;
828 pr_debug("%s\n", __func__
);
830 dev
= ieee802154_nl_get_dev(info
);
834 ops
= ieee802154_mlme_ops(dev
);
840 msg
= nlmsg_new(NLMSG_DEFAULT_SIZE
, GFP_KERNEL
);
844 hdr
= genlmsg_put(msg
, 0, info
->snd_seq
, &nl802154_family
, 0,
845 IEEE802154_LLSEC_GETPARAMS
);
849 rc
= ops
->llsec
->get_params(dev
, ¶ms
);
853 if (nla_put_string(msg
, IEEE802154_ATTR_DEV_NAME
, dev
->name
) ||
854 nla_put_u32(msg
, IEEE802154_ATTR_DEV_INDEX
, dev
->ifindex
) ||
855 nla_put_u8(msg
, IEEE802154_ATTR_LLSEC_ENABLED
, params
.enabled
) ||
856 nla_put_u8(msg
, IEEE802154_ATTR_LLSEC_SECLEVEL
, params
.out_level
) ||
857 nla_put_u32(msg
, IEEE802154_ATTR_LLSEC_FRAME_COUNTER
,
858 be32_to_cpu(params
.frame_counter
)) ||
859 ieee802154_llsec_fill_key_id(msg
, ¶ms
.out_key
))
864 return ieee802154_nl_reply(msg
, info
);
872 int ieee802154_llsec_setparams(struct sk_buff
*skb
, struct genl_info
*info
)
874 struct net_device
*dev
= NULL
;
876 struct ieee802154_mlme_ops
*ops
;
877 struct ieee802154_llsec_params params
;
880 pr_debug("%s\n", __func__
);
882 dev
= ieee802154_nl_get_dev(info
);
886 if (!info
->attrs
[IEEE802154_ATTR_LLSEC_ENABLED
] &&
887 !info
->attrs
[IEEE802154_ATTR_LLSEC_KEY_MODE
] &&
888 !info
->attrs
[IEEE802154_ATTR_LLSEC_SECLEVEL
])
891 ops
= ieee802154_mlme_ops(dev
);
897 if (info
->attrs
[IEEE802154_ATTR_LLSEC_SECLEVEL
] &&
898 nla_get_u8(info
->attrs
[IEEE802154_ATTR_LLSEC_SECLEVEL
]) > 7)
901 if (info
->attrs
[IEEE802154_ATTR_LLSEC_ENABLED
]) {
902 params
.enabled
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_LLSEC_ENABLED
]);
903 changed
|= IEEE802154_LLSEC_PARAM_ENABLED
;
906 if (info
->attrs
[IEEE802154_ATTR_LLSEC_KEY_MODE
]) {
907 if (ieee802154_llsec_parse_key_id(info
, ¶ms
.out_key
))
910 changed
|= IEEE802154_LLSEC_PARAM_OUT_KEY
;
913 if (info
->attrs
[IEEE802154_ATTR_LLSEC_SECLEVEL
]) {
914 params
.out_level
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_LLSEC_SECLEVEL
]);
915 changed
|= IEEE802154_LLSEC_PARAM_OUT_LEVEL
;
918 if (info
->attrs
[IEEE802154_ATTR_LLSEC_FRAME_COUNTER
]) {
919 u32 fc
= nla_get_u32(info
->attrs
[IEEE802154_ATTR_LLSEC_FRAME_COUNTER
]);
921 params
.frame_counter
= cpu_to_be32(fc
);
922 changed
|= IEEE802154_LLSEC_PARAM_FRAME_COUNTER
;
925 rc
= ops
->llsec
->set_params(dev
, ¶ms
, changed
);
937 struct llsec_dump_data
{
942 struct net_device
*dev
;
943 struct ieee802154_mlme_ops
*ops
;
944 struct ieee802154_llsec_table
*table
;
948 ieee802154_llsec_dump_table(struct sk_buff
*skb
, struct netlink_callback
*cb
,
949 int (*step
)(struct llsec_dump_data
*))
951 struct net
*net
= sock_net(skb
->sk
);
952 struct net_device
*dev
;
953 struct llsec_dump_data data
;
955 int first_dev
= cb
->args
[0];
958 for_each_netdev(net
, dev
) {
959 if (idx
< first_dev
|| dev
->type
!= ARPHRD_IEEE802154
)
962 data
.ops
= ieee802154_mlme_ops(dev
);
963 if (!data
.ops
->llsec
)
967 data
.s_idx
= cb
->args
[1];
968 data
.s_idx2
= cb
->args
[2];
970 data
.portid
= NETLINK_CB(cb
->skb
).portid
;
971 data
.nlmsg_seq
= cb
->nlh
->nlmsg_seq
;
973 data
.ops
->llsec
->lock_table(dev
);
974 data
.ops
->llsec
->get_table(data
.dev
, &data
.table
);
976 data
.ops
->llsec
->unlock_table(dev
);
990 ieee802154_nl_llsec_change(struct sk_buff
*skb
, struct genl_info
*info
,
991 int (*fn
)(struct net_device
*, struct genl_info
*))
993 struct net_device
*dev
= NULL
;
996 dev
= ieee802154_nl_get_dev(info
);
1000 if (!ieee802154_mlme_ops(dev
)->llsec
)
1012 ieee802154_llsec_parse_key(struct genl_info
*info
,
1013 struct ieee802154_llsec_key
*key
)
1016 u32 commands
[256 / 32];
1018 memset(key
, 0, sizeof(*key
));
1020 if (!info
->attrs
[IEEE802154_ATTR_LLSEC_KEY_USAGE_FRAME_TYPES
] ||
1021 !info
->attrs
[IEEE802154_ATTR_LLSEC_KEY_BYTES
])
1024 frames
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_LLSEC_KEY_USAGE_FRAME_TYPES
]);
1025 if ((frames
& BIT(IEEE802154_FC_TYPE_MAC_CMD
)) &&
1026 !info
->attrs
[IEEE802154_ATTR_LLSEC_KEY_USAGE_COMMANDS
])
1029 if (info
->attrs
[IEEE802154_ATTR_LLSEC_KEY_USAGE_COMMANDS
]) {
1030 nla_memcpy(commands
,
1031 info
->attrs
[IEEE802154_ATTR_LLSEC_KEY_USAGE_COMMANDS
],
1034 if (commands
[0] || commands
[1] || commands
[2] || commands
[3] ||
1035 commands
[4] || commands
[5] || commands
[6] ||
1036 commands
[7] >= BIT(IEEE802154_CMD_GTS_REQ
+ 1))
1039 key
->cmd_frame_ids
= commands
[7];
1042 key
->frame_types
= frames
;
1044 nla_memcpy(key
->key
, info
->attrs
[IEEE802154_ATTR_LLSEC_KEY_BYTES
],
1045 IEEE802154_LLSEC_KEY_SIZE
);
1050 static int llsec_add_key(struct net_device
*dev
, struct genl_info
*info
)
1052 struct ieee802154_mlme_ops
*ops
= ieee802154_mlme_ops(dev
);
1053 struct ieee802154_llsec_key key
;
1054 struct ieee802154_llsec_key_id id
;
1056 if (ieee802154_llsec_parse_key(info
, &key
) ||
1057 ieee802154_llsec_parse_key_id(info
, &id
))
1060 return ops
->llsec
->add_key(dev
, &id
, &key
);
1063 int ieee802154_llsec_add_key(struct sk_buff
*skb
, struct genl_info
*info
)
1065 if ((info
->nlhdr
->nlmsg_flags
& (NLM_F_CREATE
| NLM_F_EXCL
)) !=
1066 (NLM_F_CREATE
| NLM_F_EXCL
))
1069 return ieee802154_nl_llsec_change(skb
, info
, llsec_add_key
);
1072 static int llsec_remove_key(struct net_device
*dev
, struct genl_info
*info
)
1074 struct ieee802154_mlme_ops
*ops
= ieee802154_mlme_ops(dev
);
1075 struct ieee802154_llsec_key_id id
;
1077 if (ieee802154_llsec_parse_key_id(info
, &id
))
1080 return ops
->llsec
->del_key(dev
, &id
);
1083 int ieee802154_llsec_del_key(struct sk_buff
*skb
, struct genl_info
*info
)
1085 return ieee802154_nl_llsec_change(skb
, info
, llsec_remove_key
);
1089 ieee802154_nl_fill_key(struct sk_buff
*msg
, u32 portid
, u32 seq
,
1090 const struct ieee802154_llsec_key_entry
*key
,
1091 const struct net_device
*dev
)
1094 u32 commands
[256 / 32];
1096 hdr
= genlmsg_put(msg
, 0, seq
, &nl802154_family
, NLM_F_MULTI
,
1097 IEEE802154_LLSEC_LIST_KEY
);
1101 if (nla_put_string(msg
, IEEE802154_ATTR_DEV_NAME
, dev
->name
) ||
1102 nla_put_u32(msg
, IEEE802154_ATTR_DEV_INDEX
, dev
->ifindex
) ||
1103 ieee802154_llsec_fill_key_id(msg
, &key
->id
) ||
1104 nla_put_u8(msg
, IEEE802154_ATTR_LLSEC_KEY_USAGE_FRAME_TYPES
,
1105 key
->key
->frame_types
))
1106 goto nla_put_failure
;
1108 if (key
->key
->frame_types
& BIT(IEEE802154_FC_TYPE_MAC_CMD
)) {
1109 memset(commands
, 0, sizeof(commands
));
1110 commands
[7] = key
->key
->cmd_frame_ids
;
1111 if (nla_put(msg
, IEEE802154_ATTR_LLSEC_KEY_USAGE_COMMANDS
,
1112 sizeof(commands
), commands
))
1113 goto nla_put_failure
;
1116 if (nla_put(msg
, IEEE802154_ATTR_LLSEC_KEY_BYTES
,
1117 IEEE802154_LLSEC_KEY_SIZE
, key
->key
->key
))
1118 goto nla_put_failure
;
1120 genlmsg_end(msg
, hdr
);
1124 genlmsg_cancel(msg
, hdr
);
1129 static int llsec_iter_keys(struct llsec_dump_data
*data
)
1131 struct ieee802154_llsec_key_entry
*pos
;
1132 int rc
= 0, idx
= 0;
1134 list_for_each_entry(pos
, &data
->table
->keys
, list
) {
1135 if (idx
++ < data
->s_idx
)
1138 if (ieee802154_nl_fill_key(data
->skb
, data
->portid
,
1139 data
->nlmsg_seq
, pos
, data
->dev
)) {
1150 int ieee802154_llsec_dump_keys(struct sk_buff
*skb
, struct netlink_callback
*cb
)
1152 return ieee802154_llsec_dump_table(skb
, cb
, llsec_iter_keys
);
1158 llsec_parse_dev(struct genl_info
*info
,
1159 struct ieee802154_llsec_device
*dev
)
1161 memset(dev
, 0, sizeof(*dev
));
1163 if (!info
->attrs
[IEEE802154_ATTR_LLSEC_FRAME_COUNTER
] ||
1164 !info
->attrs
[IEEE802154_ATTR_HW_ADDR
] ||
1165 !info
->attrs
[IEEE802154_ATTR_LLSEC_DEV_OVERRIDE
] ||
1166 !info
->attrs
[IEEE802154_ATTR_LLSEC_DEV_KEY_MODE
] ||
1167 (!!info
->attrs
[IEEE802154_ATTR_PAN_ID
] !=
1168 !!info
->attrs
[IEEE802154_ATTR_SHORT_ADDR
]))
1171 if (info
->attrs
[IEEE802154_ATTR_PAN_ID
]) {
1172 dev
->pan_id
= nla_get_shortaddr(info
->attrs
[IEEE802154_ATTR_PAN_ID
]);
1173 dev
->short_addr
= nla_get_shortaddr(info
->attrs
[IEEE802154_ATTR_SHORT_ADDR
]);
1175 dev
->short_addr
= cpu_to_le16(IEEE802154_ADDR_UNDEF
);
1178 dev
->hwaddr
= nla_get_hwaddr(info
->attrs
[IEEE802154_ATTR_HW_ADDR
]);
1179 dev
->frame_counter
= nla_get_u32(info
->attrs
[IEEE802154_ATTR_LLSEC_FRAME_COUNTER
]);
1180 dev
->seclevel_exempt
= !!nla_get_u8(info
->attrs
[IEEE802154_ATTR_LLSEC_DEV_OVERRIDE
]);
1181 dev
->key_mode
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_LLSEC_DEV_KEY_MODE
]);
1183 if (dev
->key_mode
>= __IEEE802154_LLSEC_DEVKEY_MAX
)
1189 static int llsec_add_dev(struct net_device
*dev
, struct genl_info
*info
)
1191 struct ieee802154_mlme_ops
*ops
= ieee802154_mlme_ops(dev
);
1192 struct ieee802154_llsec_device desc
;
1194 if (llsec_parse_dev(info
, &desc
))
1197 return ops
->llsec
->add_dev(dev
, &desc
);
1200 int ieee802154_llsec_add_dev(struct sk_buff
*skb
, struct genl_info
*info
)
1202 if ((info
->nlhdr
->nlmsg_flags
& (NLM_F_CREATE
| NLM_F_EXCL
)) !=
1203 (NLM_F_CREATE
| NLM_F_EXCL
))
1206 return ieee802154_nl_llsec_change(skb
, info
, llsec_add_dev
);
1209 static int llsec_del_dev(struct net_device
*dev
, struct genl_info
*info
)
1211 struct ieee802154_mlme_ops
*ops
= ieee802154_mlme_ops(dev
);
1214 if (!info
->attrs
[IEEE802154_ATTR_HW_ADDR
])
1217 devaddr
= nla_get_hwaddr(info
->attrs
[IEEE802154_ATTR_HW_ADDR
]);
1219 return ops
->llsec
->del_dev(dev
, devaddr
);
1222 int ieee802154_llsec_del_dev(struct sk_buff
*skb
, struct genl_info
*info
)
1224 return ieee802154_nl_llsec_change(skb
, info
, llsec_del_dev
);
1228 ieee802154_nl_fill_dev(struct sk_buff
*msg
, u32 portid
, u32 seq
,
1229 const struct ieee802154_llsec_device
*desc
,
1230 const struct net_device
*dev
)
1234 hdr
= genlmsg_put(msg
, 0, seq
, &nl802154_family
, NLM_F_MULTI
,
1235 IEEE802154_LLSEC_LIST_DEV
);
1239 if (nla_put_string(msg
, IEEE802154_ATTR_DEV_NAME
, dev
->name
) ||
1240 nla_put_u32(msg
, IEEE802154_ATTR_DEV_INDEX
, dev
->ifindex
) ||
1241 nla_put_shortaddr(msg
, IEEE802154_ATTR_PAN_ID
, desc
->pan_id
) ||
1242 nla_put_shortaddr(msg
, IEEE802154_ATTR_SHORT_ADDR
,
1243 desc
->short_addr
) ||
1244 nla_put_hwaddr(msg
, IEEE802154_ATTR_HW_ADDR
, desc
->hwaddr
) ||
1245 nla_put_u32(msg
, IEEE802154_ATTR_LLSEC_FRAME_COUNTER
,
1246 desc
->frame_counter
) ||
1247 nla_put_u8(msg
, IEEE802154_ATTR_LLSEC_DEV_OVERRIDE
,
1248 desc
->seclevel_exempt
) ||
1249 nla_put_u8(msg
, IEEE802154_ATTR_LLSEC_DEV_KEY_MODE
, desc
->key_mode
))
1250 goto nla_put_failure
;
1252 genlmsg_end(msg
, hdr
);
1256 genlmsg_cancel(msg
, hdr
);
1261 static int llsec_iter_devs(struct llsec_dump_data
*data
)
1263 struct ieee802154_llsec_device
*pos
;
1264 int rc
= 0, idx
= 0;
1266 list_for_each_entry(pos
, &data
->table
->devices
, list
) {
1267 if (idx
++ < data
->s_idx
)
1270 if (ieee802154_nl_fill_dev(data
->skb
, data
->portid
,
1271 data
->nlmsg_seq
, pos
, data
->dev
)) {
1282 int ieee802154_llsec_dump_devs(struct sk_buff
*skb
, struct netlink_callback
*cb
)
1284 return ieee802154_llsec_dump_table(skb
, cb
, llsec_iter_devs
);
1289 static int llsec_add_devkey(struct net_device
*dev
, struct genl_info
*info
)
1291 struct ieee802154_mlme_ops
*ops
= ieee802154_mlme_ops(dev
);
1292 struct ieee802154_llsec_device_key key
;
1295 if (!info
->attrs
[IEEE802154_ATTR_LLSEC_FRAME_COUNTER
] ||
1296 !info
->attrs
[IEEE802154_ATTR_HW_ADDR
] ||
1297 ieee802154_llsec_parse_key_id(info
, &key
.key_id
))
1300 devaddr
= nla_get_hwaddr(info
->attrs
[IEEE802154_ATTR_HW_ADDR
]);
1301 key
.frame_counter
= nla_get_u32(info
->attrs
[IEEE802154_ATTR_LLSEC_FRAME_COUNTER
]);
1303 return ops
->llsec
->add_devkey(dev
, devaddr
, &key
);
1306 int ieee802154_llsec_add_devkey(struct sk_buff
*skb
, struct genl_info
*info
)
1308 if ((info
->nlhdr
->nlmsg_flags
& (NLM_F_CREATE
| NLM_F_EXCL
)) !=
1309 (NLM_F_CREATE
| NLM_F_EXCL
))
1312 return ieee802154_nl_llsec_change(skb
, info
, llsec_add_devkey
);
1315 static int llsec_del_devkey(struct net_device
*dev
, struct genl_info
*info
)
1317 struct ieee802154_mlme_ops
*ops
= ieee802154_mlme_ops(dev
);
1318 struct ieee802154_llsec_device_key key
;
1321 if (!info
->attrs
[IEEE802154_ATTR_HW_ADDR
] ||
1322 ieee802154_llsec_parse_key_id(info
, &key
.key_id
))
1325 devaddr
= nla_get_hwaddr(info
->attrs
[IEEE802154_ATTR_HW_ADDR
]);
1327 return ops
->llsec
->del_devkey(dev
, devaddr
, &key
);
1330 int ieee802154_llsec_del_devkey(struct sk_buff
*skb
, struct genl_info
*info
)
1332 return ieee802154_nl_llsec_change(skb
, info
, llsec_del_devkey
);
1336 ieee802154_nl_fill_devkey(struct sk_buff
*msg
, u32 portid
, u32 seq
,
1338 const struct ieee802154_llsec_device_key
*devkey
,
1339 const struct net_device
*dev
)
1343 hdr
= genlmsg_put(msg
, 0, seq
, &nl802154_family
, NLM_F_MULTI
,
1344 IEEE802154_LLSEC_LIST_DEVKEY
);
1348 if (nla_put_string(msg
, IEEE802154_ATTR_DEV_NAME
, dev
->name
) ||
1349 nla_put_u32(msg
, IEEE802154_ATTR_DEV_INDEX
, dev
->ifindex
) ||
1350 nla_put_hwaddr(msg
, IEEE802154_ATTR_HW_ADDR
, devaddr
) ||
1351 nla_put_u32(msg
, IEEE802154_ATTR_LLSEC_FRAME_COUNTER
,
1352 devkey
->frame_counter
) ||
1353 ieee802154_llsec_fill_key_id(msg
, &devkey
->key_id
))
1354 goto nla_put_failure
;
1356 genlmsg_end(msg
, hdr
);
1360 genlmsg_cancel(msg
, hdr
);
1365 static int llsec_iter_devkeys(struct llsec_dump_data
*data
)
1367 struct ieee802154_llsec_device
*dpos
;
1368 struct ieee802154_llsec_device_key
*kpos
;
1369 int rc
= 0, idx
= 0, idx2
;
1371 list_for_each_entry(dpos
, &data
->table
->devices
, list
) {
1372 if (idx
++ < data
->s_idx
)
1377 list_for_each_entry(kpos
, &dpos
->keys
, list
) {
1378 if (idx2
++ < data
->s_idx2
)
1381 if (ieee802154_nl_fill_devkey(data
->skb
, data
->portid
,
1385 return rc
= -EMSGSIZE
;
1397 int ieee802154_llsec_dump_devkeys(struct sk_buff
*skb
,
1398 struct netlink_callback
*cb
)
1400 return ieee802154_llsec_dump_table(skb
, cb
, llsec_iter_devkeys
);
1406 llsec_parse_seclevel(struct genl_info
*info
,
1407 struct ieee802154_llsec_seclevel
*sl
)
1409 memset(sl
, 0, sizeof(*sl
));
1411 if (!info
->attrs
[IEEE802154_ATTR_LLSEC_FRAME_TYPE
] ||
1412 !info
->attrs
[IEEE802154_ATTR_LLSEC_SECLEVELS
] ||
1413 !info
->attrs
[IEEE802154_ATTR_LLSEC_DEV_OVERRIDE
])
1416 sl
->frame_type
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_LLSEC_FRAME_TYPE
]);
1417 if (sl
->frame_type
== IEEE802154_FC_TYPE_MAC_CMD
) {
1418 if (!info
->attrs
[IEEE802154_ATTR_LLSEC_CMD_FRAME_ID
])
1421 sl
->cmd_frame_id
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_LLSEC_CMD_FRAME_ID
]);
1424 sl
->sec_levels
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_LLSEC_SECLEVELS
]);
1425 sl
->device_override
= nla_get_u8(info
->attrs
[IEEE802154_ATTR_LLSEC_DEV_OVERRIDE
]);
1430 static int llsec_add_seclevel(struct net_device
*dev
, struct genl_info
*info
)
1432 struct ieee802154_mlme_ops
*ops
= ieee802154_mlme_ops(dev
);
1433 struct ieee802154_llsec_seclevel sl
;
1435 if (llsec_parse_seclevel(info
, &sl
))
1438 return ops
->llsec
->add_seclevel(dev
, &sl
);
1441 int ieee802154_llsec_add_seclevel(struct sk_buff
*skb
, struct genl_info
*info
)
1443 if ((info
->nlhdr
->nlmsg_flags
& (NLM_F_CREATE
| NLM_F_EXCL
)) !=
1444 (NLM_F_CREATE
| NLM_F_EXCL
))
1447 return ieee802154_nl_llsec_change(skb
, info
, llsec_add_seclevel
);
1450 static int llsec_del_seclevel(struct net_device
*dev
, struct genl_info
*info
)
1452 struct ieee802154_mlme_ops
*ops
= ieee802154_mlme_ops(dev
);
1453 struct ieee802154_llsec_seclevel sl
;
1455 if (llsec_parse_seclevel(info
, &sl
))
1458 return ops
->llsec
->del_seclevel(dev
, &sl
);
1461 int ieee802154_llsec_del_seclevel(struct sk_buff
*skb
, struct genl_info
*info
)
1463 return ieee802154_nl_llsec_change(skb
, info
, llsec_del_seclevel
);
1467 ieee802154_nl_fill_seclevel(struct sk_buff
*msg
, u32 portid
, u32 seq
,
1468 const struct ieee802154_llsec_seclevel
*sl
,
1469 const struct net_device
*dev
)
1473 hdr
= genlmsg_put(msg
, 0, seq
, &nl802154_family
, NLM_F_MULTI
,
1474 IEEE802154_LLSEC_LIST_SECLEVEL
);
1478 if (nla_put_string(msg
, IEEE802154_ATTR_DEV_NAME
, dev
->name
) ||
1479 nla_put_u32(msg
, IEEE802154_ATTR_DEV_INDEX
, dev
->ifindex
) ||
1480 nla_put_u8(msg
, IEEE802154_ATTR_LLSEC_FRAME_TYPE
, sl
->frame_type
) ||
1481 nla_put_u8(msg
, IEEE802154_ATTR_LLSEC_SECLEVELS
, sl
->sec_levels
) ||
1482 nla_put_u8(msg
, IEEE802154_ATTR_LLSEC_DEV_OVERRIDE
,
1483 sl
->device_override
))
1484 goto nla_put_failure
;
1486 if (sl
->frame_type
== IEEE802154_FC_TYPE_MAC_CMD
&&
1487 nla_put_u8(msg
, IEEE802154_ATTR_LLSEC_CMD_FRAME_ID
,
1489 goto nla_put_failure
;
1491 genlmsg_end(msg
, hdr
);
1495 genlmsg_cancel(msg
, hdr
);
1500 static int llsec_iter_seclevels(struct llsec_dump_data
*data
)
1502 struct ieee802154_llsec_seclevel
*pos
;
1503 int rc
= 0, idx
= 0;
1505 list_for_each_entry(pos
, &data
->table
->security_levels
, list
) {
1506 if (idx
++ < data
->s_idx
)
1509 if (ieee802154_nl_fill_seclevel(data
->skb
, data
->portid
,
1510 data
->nlmsg_seq
, pos
,
1522 int ieee802154_llsec_dump_seclevels(struct sk_buff
*skb
,
1523 struct netlink_callback
*cb
)
1525 return ieee802154_llsec_dump_table(skb
, cb
, llsec_iter_seclevels
);