diff options
author | Alexander Aring <alex.aring@gmail.com> | 2015-09-28 03:00:25 -0400 |
---|---|---|
committer | Marcel Holtmann <marcel@holtmann.org> | 2015-09-30 07:16:44 -0400 |
commit | a26c5fd7622d4951425131d54a8c99f076fe2068 (patch) | |
tree | 1a2a5c0db1ee837902382a48f655a61840a8cc73 /net/ieee802154 | |
parent | 1ee06ef1596dcc5858ea29ef9faf0f29e139dfcc (diff) |
nl802154: add support for security layer
This patch adds support for accessing mac802154 llsec implementation
over nl802154. I added for a new Kconfig entry to provide this
functionality CONFIG_IEEE802154_NL802154_EXPERIMENTAL. This interface is
still in development. It provides to change security parameters and
add/del/dump entries of security tables. Later we can add also a get to
get an entry by unique identifier.
Cc: Phoebe Buckheister <phoebe.buckheister@itwm.fraunhofer.de>
Signed-off-by: Alexander Aring <alex.aring@gmail.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Diffstat (limited to 'net/ieee802154')
-rw-r--r-- | net/ieee802154/Kconfig | 5 | ||||
-rw-r--r-- | net/ieee802154/core.c | 12 | ||||
-rw-r--r-- | net/ieee802154/core.h | 1 | ||||
-rw-r--r-- | net/ieee802154/nl802154.c | 1128 | ||||
-rw-r--r-- | net/ieee802154/rdev-ops.h | 109 |
5 files changed, 1255 insertions, 0 deletions
diff --git a/net/ieee802154/Kconfig b/net/ieee802154/Kconfig index 1370d5b0041b..188135bcb803 100644 --- a/net/ieee802154/Kconfig +++ b/net/ieee802154/Kconfig | |||
@@ -12,6 +12,11 @@ menuconfig IEEE802154 | |||
12 | 12 | ||
13 | if IEEE802154 | 13 | if IEEE802154 |
14 | 14 | ||
15 | config IEEE802154_NL802154_EXPERIMENTAL | ||
16 | bool "IEEE 802.15.4 experimental netlink support" | ||
17 | ---help--- | ||
18 | Adds experimental netlink support for nl802154. | ||
19 | |||
15 | config IEEE802154_SOCKET | 20 | config IEEE802154_SOCKET |
16 | tristate "IEEE 802.15.4 socket interface" | 21 | tristate "IEEE 802.15.4 socket interface" |
17 | default y | 22 | default y |
diff --git a/net/ieee802154/core.c b/net/ieee802154/core.c index b0248e934230..c35fdfa6d04e 100644 --- a/net/ieee802154/core.c +++ b/net/ieee802154/core.c | |||
@@ -95,6 +95,18 @@ cfg802154_rdev_by_wpan_phy_idx(int wpan_phy_idx) | |||
95 | return result; | 95 | return result; |
96 | } | 96 | } |
97 | 97 | ||
98 | struct wpan_phy *wpan_phy_idx_to_wpan_phy(int wpan_phy_idx) | ||
99 | { | ||
100 | struct cfg802154_registered_device *rdev; | ||
101 | |||
102 | ASSERT_RTNL(); | ||
103 | |||
104 | rdev = cfg802154_rdev_by_wpan_phy_idx(wpan_phy_idx); | ||
105 | if (!rdev) | ||
106 | return NULL; | ||
107 | return &rdev->wpan_phy; | ||
108 | } | ||
109 | |||
98 | struct wpan_phy * | 110 | struct wpan_phy * |
99 | wpan_phy_new(const struct cfg802154_ops *ops, size_t priv_size) | 111 | wpan_phy_new(const struct cfg802154_ops *ops, size_t priv_size) |
100 | { | 112 | { |
diff --git a/net/ieee802154/core.h b/net/ieee802154/core.h index f3e95580caee..231fade959f3 100644 --- a/net/ieee802154/core.h +++ b/net/ieee802154/core.h | |||
@@ -42,5 +42,6 @@ extern int cfg802154_rdev_list_generation; | |||
42 | void cfg802154_dev_free(struct cfg802154_registered_device *rdev); | 42 | void cfg802154_dev_free(struct cfg802154_registered_device *rdev); |
43 | struct cfg802154_registered_device * | 43 | struct cfg802154_registered_device * |
44 | cfg802154_rdev_by_wpan_phy_idx(int wpan_phy_idx); | 44 | cfg802154_rdev_by_wpan_phy_idx(int wpan_phy_idx); |
45 | struct wpan_phy *wpan_phy_idx_to_wpan_phy(int wpan_phy_idx); | ||
45 | 46 | ||
46 | #endif /* __IEEE802154_CORE_H */ | 47 | #endif /* __IEEE802154_CORE_H */ |
diff --git a/net/ieee802154/nl802154.c b/net/ieee802154/nl802154.c index 51110a6d3674..1e9e86508441 100644 --- a/net/ieee802154/nl802154.c +++ b/net/ieee802154/nl802154.c | |||
@@ -232,8 +232,86 @@ static const struct nla_policy nl802154_policy[NL802154_ATTR_MAX+1] = { | |||
232 | [NL802154_ATTR_SUPPORTED_COMMANDS] = { .type = NLA_NESTED }, | 232 | [NL802154_ATTR_SUPPORTED_COMMANDS] = { .type = NLA_NESTED }, |
233 | 233 | ||
234 | [NL802154_ATTR_ACKREQ_DEFAULT] = { .type = NLA_U8 }, | 234 | [NL802154_ATTR_ACKREQ_DEFAULT] = { .type = NLA_U8 }, |
235 | |||
236 | #ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL | ||
237 | [NL802154_ATTR_SEC_ENABLED] = { .type = NLA_U8, }, | ||
238 | [NL802154_ATTR_SEC_OUT_LEVEL] = { .type = NLA_U32, }, | ||
239 | [NL802154_ATTR_SEC_OUT_KEY_ID] = { .type = NLA_NESTED, }, | ||
240 | [NL802154_ATTR_SEC_FRAME_COUNTER] = { .type = NLA_U32 }, | ||
241 | |||
242 | [NL802154_ATTR_SEC_LEVEL] = { .type = NLA_NESTED }, | ||
243 | [NL802154_ATTR_SEC_DEVICE] = { .type = NLA_NESTED }, | ||
244 | [NL802154_ATTR_SEC_DEVKEY] = { .type = NLA_NESTED }, | ||
245 | [NL802154_ATTR_SEC_KEY] = { .type = NLA_NESTED }, | ||
246 | #endif /* CONFIG_IEEE802154_NL802154_EXPERIMENTAL */ | ||
235 | }; | 247 | }; |
236 | 248 | ||
249 | #ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL | ||
250 | static int | ||
251 | nl802154_prepare_wpan_dev_dump(struct sk_buff *skb, | ||
252 | struct netlink_callback *cb, | ||
253 | struct cfg802154_registered_device **rdev, | ||
254 | struct wpan_dev **wpan_dev) | ||
255 | { | ||
256 | int err; | ||
257 | |||
258 | rtnl_lock(); | ||
259 | |||
260 | if (!cb->args[0]) { | ||
261 | err = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl802154_fam.hdrsize, | ||
262 | nl802154_fam.attrbuf, nl802154_fam.maxattr, | ||
263 | nl802154_policy); | ||
264 | if (err) | ||
265 | goto out_unlock; | ||
266 | |||
267 | *wpan_dev = __cfg802154_wpan_dev_from_attrs(sock_net(skb->sk), | ||
268 | nl802154_fam.attrbuf); | ||
269 | if (IS_ERR(*wpan_dev)) { | ||
270 | err = PTR_ERR(*wpan_dev); | ||
271 | goto out_unlock; | ||
272 | } | ||
273 | *rdev = wpan_phy_to_rdev((*wpan_dev)->wpan_phy); | ||
274 | /* 0 is the first index - add 1 to parse only once */ | ||
275 | cb->args[0] = (*rdev)->wpan_phy_idx + 1; | ||
276 | cb->args[1] = (*wpan_dev)->identifier; | ||
277 | } else { | ||
278 | /* subtract the 1 again here */ | ||
279 | struct wpan_phy *wpan_phy = wpan_phy_idx_to_wpan_phy(cb->args[0] - 1); | ||
280 | struct wpan_dev *tmp; | ||
281 | |||
282 | if (!wpan_phy) { | ||
283 | err = -ENODEV; | ||
284 | goto out_unlock; | ||
285 | } | ||
286 | *rdev = wpan_phy_to_rdev(wpan_phy); | ||
287 | *wpan_dev = NULL; | ||
288 | |||
289 | list_for_each_entry(tmp, &(*rdev)->wpan_dev_list, list) { | ||
290 | if (tmp->identifier == cb->args[1]) { | ||
291 | *wpan_dev = tmp; | ||
292 | break; | ||
293 | } | ||
294 | } | ||
295 | |||
296 | if (!*wpan_dev) { | ||
297 | err = -ENODEV; | ||
298 | goto out_unlock; | ||
299 | } | ||
300 | } | ||
301 | |||
302 | return 0; | ||
303 | out_unlock: | ||
304 | rtnl_unlock(); | ||
305 | return err; | ||
306 | } | ||
307 | |||
308 | static void | ||
309 | nl802154_finish_wpan_dev_dump(struct cfg802154_registered_device *rdev) | ||
310 | { | ||
311 | rtnl_unlock(); | ||
312 | } | ||
313 | #endif /* CONFIG_IEEE802154_NL802154_EXPERIMENTAL */ | ||
314 | |||
237 | /* message building helper */ | 315 | /* message building helper */ |
238 | static inline void *nl802154hdr_put(struct sk_buff *skb, u32 portid, u32 seq, | 316 | static inline void *nl802154hdr_put(struct sk_buff *skb, u32 portid, u32 seq, |
239 | int flags, u8 cmd) | 317 | int flags, u8 cmd) |
@@ -612,6 +690,107 @@ static inline u64 wpan_dev_id(struct wpan_dev *wpan_dev) | |||
612 | ((u64)wpan_phy_to_rdev(wpan_dev->wpan_phy)->wpan_phy_idx << 32); | 690 | ((u64)wpan_phy_to_rdev(wpan_dev->wpan_phy)->wpan_phy_idx << 32); |
613 | } | 691 | } |
614 | 692 | ||
693 | #ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL | ||
694 | #include <net/ieee802154_netdev.h> | ||
695 | |||
696 | static int | ||
697 | ieee802154_llsec_send_key_id(struct sk_buff *msg, | ||
698 | const struct ieee802154_llsec_key_id *desc) | ||
699 | { | ||
700 | struct nlattr *nl_dev_addr; | ||
701 | |||
702 | if (nla_put_u32(msg, NL802154_KEY_ID_ATTR_MODE, desc->mode)) | ||
703 | return -ENOBUFS; | ||
704 | |||
705 | switch (desc->mode) { | ||
706 | case NL802154_KEY_ID_MODE_IMPLICIT: | ||
707 | nl_dev_addr = nla_nest_start(msg, NL802154_KEY_ID_ATTR_IMPLICIT); | ||
708 | if (!nl_dev_addr) | ||
709 | return -ENOBUFS; | ||
710 | |||
711 | if (nla_put_le16(msg, NL802154_DEV_ADDR_ATTR_PAN_ID, | ||
712 | desc->device_addr.pan_id) || | ||
713 | nla_put_u32(msg, NL802154_DEV_ADDR_ATTR_MODE, | ||
714 | desc->device_addr.mode)) | ||
715 | return -ENOBUFS; | ||
716 | |||
717 | switch (desc->device_addr.mode) { | ||
718 | case NL802154_DEV_ADDR_SHORT: | ||
719 | if (nla_put_le16(msg, NL802154_DEV_ADDR_ATTR_SHORT, | ||
720 | desc->device_addr.short_addr)) | ||
721 | return -ENOBUFS; | ||
722 | break; | ||
723 | case NL802154_DEV_ADDR_EXTENDED: | ||
724 | if (nla_put_le64(msg, NL802154_DEV_ADDR_ATTR_EXTENDED, | ||
725 | desc->device_addr.extended_addr)) | ||
726 | return -ENOBUFS; | ||
727 | break; | ||
728 | default: | ||
729 | /* userspace should handle unknown */ | ||
730 | break; | ||
731 | } | ||
732 | |||
733 | nla_nest_end(msg, nl_dev_addr); | ||
734 | break; | ||
735 | case NL802154_KEY_ID_MODE_INDEX: | ||
736 | break; | ||
737 | case NL802154_KEY_ID_MODE_INDEX_SHORT: | ||
738 | /* TODO renmae short_source? */ | ||
739 | if (nla_put_le32(msg, NL802154_KEY_ID_ATTR_SOURCE_SHORT, | ||
740 | desc->short_source)) | ||
741 | return -ENOBUFS; | ||
742 | break; | ||
743 | case NL802154_KEY_ID_MODE_INDEX_EXTENDED: | ||
744 | if (nla_put_le64(msg, NL802154_KEY_ID_ATTR_SOURCE_EXTENDED, | ||
745 | desc->extended_source)) | ||
746 | return -ENOBUFS; | ||
747 | break; | ||
748 | default: | ||
749 | /* userspace should handle unknown */ | ||
750 | break; | ||
751 | } | ||
752 | |||
753 | /* TODO key_id to key_idx ? Check naming */ | ||
754 | if (desc->mode != NL802154_KEY_ID_MODE_IMPLICIT) { | ||
755 | if (nla_put_u8(msg, NL802154_KEY_ID_ATTR_INDEX, desc->id)) | ||
756 | return -ENOBUFS; | ||
757 | } | ||
758 | |||
759 | return 0; | ||
760 | } | ||
761 | |||
762 | static int nl802154_get_llsec_params(struct sk_buff *msg, | ||
763 | struct cfg802154_registered_device *rdev, | ||
764 | struct wpan_dev *wpan_dev) | ||
765 | { | ||
766 | struct nlattr *nl_key_id; | ||
767 | struct ieee802154_llsec_params params; | ||
768 | int ret; | ||
769 | |||
770 | ret = rdev_get_llsec_params(rdev, wpan_dev, ¶ms); | ||
771 | if (ret < 0) | ||
772 | return ret; | ||
773 | |||
774 | if (nla_put_u8(msg, NL802154_ATTR_SEC_ENABLED, params.enabled) || | ||
775 | nla_put_u32(msg, NL802154_ATTR_SEC_OUT_LEVEL, params.out_level) || | ||
776 | nla_put_be32(msg, NL802154_ATTR_SEC_FRAME_COUNTER, | ||
777 | params.frame_counter)) | ||
778 | return -ENOBUFS; | ||
779 | |||
780 | nl_key_id = nla_nest_start(msg, NL802154_ATTR_SEC_OUT_KEY_ID); | ||
781 | if (!nl_key_id) | ||
782 | return -ENOBUFS; | ||
783 | |||
784 | ret = ieee802154_llsec_send_key_id(msg, ¶ms.out_key); | ||
785 | if (ret < 0) | ||
786 | return ret; | ||
787 | |||
788 | nla_nest_end(msg, nl_key_id); | ||
789 | |||
790 | return 0; | ||
791 | } | ||
792 | #endif /* CONFIG_IEEE802154_NL802154_EXPERIMENTAL */ | ||
793 | |||
615 | static int | 794 | static int |
616 | nl802154_send_iface(struct sk_buff *msg, u32 portid, u32 seq, int flags, | 795 | nl802154_send_iface(struct sk_buff *msg, u32 portid, u32 seq, int flags, |
617 | struct cfg802154_registered_device *rdev, | 796 | struct cfg802154_registered_device *rdev, |
@@ -663,6 +842,11 @@ nl802154_send_iface(struct sk_buff *msg, u32 portid, u32 seq, int flags, | |||
663 | if (nla_put_u8(msg, NL802154_ATTR_ACKREQ_DEFAULT, wpan_dev->ackreq)) | 842 | if (nla_put_u8(msg, NL802154_ATTR_ACKREQ_DEFAULT, wpan_dev->ackreq)) |
664 | goto nla_put_failure; | 843 | goto nla_put_failure; |
665 | 844 | ||
845 | #ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL | ||
846 | if (nl802154_get_llsec_params(msg, rdev, wpan_dev) < 0) | ||
847 | goto nla_put_failure; | ||
848 | #endif /* CONFIG_IEEE802154_NL802154_EXPERIMENTAL */ | ||
849 | |||
666 | genlmsg_end(msg, hdr); | 850 | genlmsg_end(msg, hdr); |
667 | return 0; | 851 | return 0; |
668 | 852 | ||
@@ -1073,6 +1257,837 @@ nl802154_set_ackreq_default(struct sk_buff *skb, struct genl_info *info) | |||
1073 | return rdev_set_ackreq_default(rdev, wpan_dev, ackreq); | 1257 | return rdev_set_ackreq_default(rdev, wpan_dev, ackreq); |
1074 | } | 1258 | } |
1075 | 1259 | ||
1260 | #ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL | ||
1261 | static const struct nla_policy nl802154_dev_addr_policy[NL802154_DEV_ADDR_ATTR_MAX + 1] = { | ||
1262 | [NL802154_DEV_ADDR_ATTR_PAN_ID] = { .type = NLA_U16 }, | ||
1263 | [NL802154_DEV_ADDR_ATTR_MODE] = { .type = NLA_U32 }, | ||
1264 | [NL802154_DEV_ADDR_ATTR_SHORT] = { .type = NLA_U16 }, | ||
1265 | [NL802154_DEV_ADDR_ATTR_EXTENDED] = { .type = NLA_U64 }, | ||
1266 | }; | ||
1267 | |||
1268 | static int | ||
1269 | ieee802154_llsec_parse_dev_addr(struct nlattr *nla, | ||
1270 | struct ieee802154_addr *addr) | ||
1271 | { | ||
1272 | struct nlattr *attrs[NL802154_DEV_ADDR_ATTR_MAX + 1]; | ||
1273 | |||
1274 | if (!nla || nla_parse_nested(attrs, NL802154_DEV_ADDR_ATTR_MAX, nla, | ||
1275 | nl802154_dev_addr_policy)) | ||
1276 | return -EINVAL; | ||
1277 | |||
1278 | if (!attrs[NL802154_DEV_ADDR_ATTR_PAN_ID] && | ||
1279 | !attrs[NL802154_DEV_ADDR_ATTR_MODE] && | ||
1280 | !(attrs[NL802154_DEV_ADDR_ATTR_SHORT] || | ||
1281 | attrs[NL802154_DEV_ADDR_ATTR_EXTENDED])) | ||
1282 | return -EINVAL; | ||
1283 | |||
1284 | addr->pan_id = nla_get_le16(attrs[NL802154_DEV_ADDR_ATTR_PAN_ID]); | ||
1285 | addr->mode = nla_get_u32(attrs[NL802154_DEV_ADDR_ATTR_MODE]); | ||
1286 | switch (addr->mode) { | ||
1287 | case NL802154_DEV_ADDR_SHORT: | ||
1288 | addr->short_addr = nla_get_le16(attrs[NL802154_DEV_ADDR_ATTR_SHORT]); | ||
1289 | break; | ||
1290 | case NL802154_DEV_ADDR_EXTENDED: | ||
1291 | addr->extended_addr = nla_get_le64(attrs[NL802154_DEV_ADDR_ATTR_EXTENDED]); | ||
1292 | break; | ||
1293 | default: | ||
1294 | return -EINVAL; | ||
1295 | } | ||
1296 | |||
1297 | return 0; | ||
1298 | } | ||
1299 | |||
1300 | static const struct nla_policy nl802154_key_id_policy[NL802154_KEY_ID_ATTR_MAX + 1] = { | ||
1301 | [NL802154_KEY_ID_ATTR_MODE] = { .type = NLA_U32 }, | ||
1302 | [NL802154_KEY_ID_ATTR_INDEX] = { .type = NLA_U8 }, | ||
1303 | [NL802154_KEY_ID_ATTR_IMPLICIT] = { .type = NLA_NESTED }, | ||
1304 | [NL802154_KEY_ID_ATTR_SOURCE_SHORT] = { .type = NLA_U32 }, | ||
1305 | [NL802154_KEY_ID_ATTR_SOURCE_EXTENDED] = { .type = NLA_U64 }, | ||
1306 | }; | ||
1307 | |||
1308 | static int | ||
1309 | ieee802154_llsec_parse_key_id(struct nlattr *nla, | ||
1310 | struct ieee802154_llsec_key_id *desc) | ||
1311 | { | ||
1312 | struct nlattr *attrs[NL802154_KEY_ID_ATTR_MAX + 1]; | ||
1313 | |||
1314 | if (!nla || nla_parse_nested(attrs, NL802154_KEY_ID_ATTR_MAX, nla, | ||
1315 | nl802154_key_id_policy)) | ||
1316 | return -EINVAL; | ||
1317 | |||
1318 | if (!attrs[NL802154_KEY_ID_ATTR_MODE]) | ||
1319 | return -EINVAL; | ||
1320 | |||
1321 | desc->mode = nla_get_u32(attrs[NL802154_KEY_ID_ATTR_MODE]); | ||
1322 | switch (desc->mode) { | ||
1323 | case NL802154_KEY_ID_MODE_IMPLICIT: | ||
1324 | if (!attrs[NL802154_KEY_ID_ATTR_IMPLICIT]) | ||
1325 | return -EINVAL; | ||
1326 | |||
1327 | if (ieee802154_llsec_parse_dev_addr(attrs[NL802154_KEY_ID_ATTR_IMPLICIT], | ||
1328 | &desc->device_addr) < 0) | ||
1329 | return -EINVAL; | ||
1330 | break; | ||
1331 | case NL802154_KEY_ID_MODE_INDEX: | ||
1332 | break; | ||
1333 | case NL802154_KEY_ID_MODE_INDEX_SHORT: | ||
1334 | if (!attrs[NL802154_KEY_ID_ATTR_SOURCE_SHORT]) | ||
1335 | return -EINVAL; | ||
1336 | |||
1337 | desc->short_source = nla_get_le32(attrs[NL802154_KEY_ID_ATTR_SOURCE_SHORT]); | ||
1338 | break; | ||
1339 | case NL802154_KEY_ID_MODE_INDEX_EXTENDED: | ||
1340 | if (!attrs[NL802154_KEY_ID_ATTR_SOURCE_EXTENDED]) | ||
1341 | return -EINVAL; | ||
1342 | |||
1343 | desc->extended_source = nla_get_le64(attrs[NL802154_KEY_ID_ATTR_SOURCE_EXTENDED]); | ||
1344 | break; | ||
1345 | default: | ||
1346 | return -EINVAL; | ||
1347 | } | ||
1348 | |||
1349 | if (desc->mode != NL802154_KEY_ID_MODE_IMPLICIT) { | ||
1350 | if (!attrs[NL802154_KEY_ID_ATTR_INDEX]) | ||
1351 | return -EINVAL; | ||
1352 | |||
1353 | /* TODO change id to idx */ | ||
1354 | desc->id = nla_get_u8(attrs[NL802154_KEY_ID_ATTR_INDEX]); | ||
1355 | } | ||
1356 | |||
1357 | return 0; | ||
1358 | } | ||
1359 | |||
1360 | static int nl802154_set_llsec_params(struct sk_buff *skb, | ||
1361 | struct genl_info *info) | ||
1362 | { | ||
1363 | struct cfg802154_registered_device *rdev = info->user_ptr[0]; | ||
1364 | struct net_device *dev = info->user_ptr[1]; | ||
1365 | struct wpan_dev *wpan_dev = dev->ieee802154_ptr; | ||
1366 | struct ieee802154_llsec_params params; | ||
1367 | u32 changed = 0; | ||
1368 | int ret; | ||
1369 | |||
1370 | if (info->attrs[NL802154_ATTR_SEC_ENABLED]) { | ||
1371 | u8 enabled; | ||
1372 | |||
1373 | enabled = nla_get_u8(info->attrs[NL802154_ATTR_SEC_ENABLED]); | ||
1374 | if (enabled != 0 && enabled != 1) | ||
1375 | return -EINVAL; | ||
1376 | |||
1377 | params.enabled = nla_get_u8(info->attrs[NL802154_ATTR_SEC_ENABLED]); | ||
1378 | changed |= IEEE802154_LLSEC_PARAM_ENABLED; | ||
1379 | } | ||
1380 | |||
1381 | if (info->attrs[NL802154_ATTR_SEC_OUT_KEY_ID]) { | ||
1382 | ret = ieee802154_llsec_parse_key_id(info->attrs[NL802154_ATTR_SEC_OUT_KEY_ID], | ||
1383 | ¶ms.out_key); | ||
1384 | if (ret < 0) | ||
1385 | return ret; | ||
1386 | |||
1387 | changed |= IEEE802154_LLSEC_PARAM_OUT_KEY; | ||
1388 | } | ||
1389 | |||
1390 | if (info->attrs[NL802154_ATTR_SEC_OUT_LEVEL]) { | ||
1391 | params.out_level = nla_get_u32(info->attrs[NL802154_ATTR_SEC_OUT_LEVEL]); | ||
1392 | if (params.out_level > NL802154_SECLEVEL_MAX) | ||
1393 | return -EINVAL; | ||
1394 | |||
1395 | changed |= IEEE802154_LLSEC_PARAM_OUT_LEVEL; | ||
1396 | } | ||
1397 | |||
1398 | if (info->attrs[NL802154_ATTR_SEC_FRAME_COUNTER]) { | ||
1399 | params.frame_counter = nla_get_be32(info->attrs[NL802154_ATTR_SEC_FRAME_COUNTER]); | ||
1400 | changed |= IEEE802154_LLSEC_PARAM_FRAME_COUNTER; | ||
1401 | } | ||
1402 | |||
1403 | return rdev_set_llsec_params(rdev, wpan_dev, ¶ms, changed); | ||
1404 | } | ||
1405 | |||
1406 | static int nl802154_send_key(struct sk_buff *msg, u32 cmd, u32 portid, | ||
1407 | u32 seq, int flags, | ||
1408 | struct cfg802154_registered_device *rdev, | ||
1409 | struct net_device *dev, | ||
1410 | const struct ieee802154_llsec_key_entry *key) | ||
1411 | { | ||
1412 | void *hdr; | ||
1413 | u32 commands[NL802154_CMD_FRAME_NR_IDS / 32]; | ||
1414 | struct nlattr *nl_key, *nl_key_id; | ||
1415 | |||
1416 | hdr = nl802154hdr_put(msg, portid, seq, flags, cmd); | ||
1417 | if (!hdr) | ||
1418 | return -1; | ||
1419 | |||
1420 | if (nla_put_u32(msg, NL802154_ATTR_IFINDEX, dev->ifindex)) | ||
1421 | goto nla_put_failure; | ||
1422 | |||
1423 | nl_key = nla_nest_start(msg, NL802154_ATTR_SEC_KEY); | ||
1424 | if (!nl_key) | ||
1425 | goto nla_put_failure; | ||
1426 | |||
1427 | nl_key_id = nla_nest_start(msg, NL802154_KEY_ATTR_ID); | ||
1428 | if (!nl_key_id) | ||
1429 | goto nla_put_failure; | ||
1430 | |||
1431 | if (ieee802154_llsec_send_key_id(msg, &key->id) < 0) | ||
1432 | goto nla_put_failure; | ||
1433 | |||
1434 | nla_nest_end(msg, nl_key_id); | ||
1435 | |||
1436 | if (nla_put_u8(msg, NL802154_KEY_ATTR_USAGE_FRAMES, | ||
1437 | key->key->frame_types)) | ||
1438 | goto nla_put_failure; | ||
1439 | |||
1440 | if (key->key->frame_types & BIT(NL802154_FRAME_CMD)) { | ||
1441 | /* TODO for each nested */ | ||
1442 | memset(commands, 0, sizeof(commands)); | ||
1443 | commands[7] = key->key->cmd_frame_ids; | ||
1444 | if (nla_put(msg, NL802154_KEY_ATTR_USAGE_CMDS, | ||
1445 | sizeof(commands), commands)) | ||
1446 | goto nla_put_failure; | ||
1447 | } | ||
1448 | |||
1449 | if (nla_put(msg, NL802154_KEY_ATTR_BYTES, NL802154_KEY_SIZE, | ||
1450 | key->key->key)) | ||
1451 | goto nla_put_failure; | ||
1452 | |||
1453 | nla_nest_end(msg, nl_key); | ||
1454 | genlmsg_end(msg, hdr); | ||
1455 | |||
1456 | return 0; | ||
1457 | |||
1458 | nla_put_failure: | ||
1459 | genlmsg_cancel(msg, hdr); | ||
1460 | return -EMSGSIZE; | ||
1461 | } | ||
1462 | |||
1463 | static int | ||
1464 | nl802154_dump_llsec_key(struct sk_buff *skb, struct netlink_callback *cb) | ||
1465 | { | ||
1466 | struct cfg802154_registered_device *rdev = NULL; | ||
1467 | struct ieee802154_llsec_key_entry *key; | ||
1468 | struct ieee802154_llsec_table *table; | ||
1469 | struct wpan_dev *wpan_dev; | ||
1470 | int err; | ||
1471 | |||
1472 | err = nl802154_prepare_wpan_dev_dump(skb, cb, &rdev, &wpan_dev); | ||
1473 | if (err) | ||
1474 | return err; | ||
1475 | |||
1476 | if (!wpan_dev->netdev) { | ||
1477 | err = -EINVAL; | ||
1478 | goto out_err; | ||
1479 | } | ||
1480 | |||
1481 | rdev_lock_llsec_table(rdev, wpan_dev); | ||
1482 | rdev_get_llsec_table(rdev, wpan_dev, &table); | ||
1483 | |||
1484 | /* TODO make it like station dump */ | ||
1485 | if (cb->args[2]) | ||
1486 | goto out; | ||
1487 | |||
1488 | list_for_each_entry(key, &table->keys, list) { | ||
1489 | if (nl802154_send_key(skb, NL802154_CMD_NEW_SEC_KEY, | ||
1490 | NETLINK_CB(cb->skb).portid, | ||
1491 | cb->nlh->nlmsg_seq, NLM_F_MULTI, | ||
1492 | rdev, wpan_dev->netdev, key) < 0) { | ||
1493 | /* TODO */ | ||
1494 | err = -EIO; | ||
1495 | rdev_unlock_llsec_table(rdev, wpan_dev); | ||
1496 | goto out_err; | ||
1497 | } | ||
1498 | } | ||
1499 | |||
1500 | cb->args[2] = 1; | ||
1501 | |||
1502 | out: | ||
1503 | rdev_unlock_llsec_table(rdev, wpan_dev); | ||
1504 | err = skb->len; | ||
1505 | out_err: | ||
1506 | nl802154_finish_wpan_dev_dump(rdev); | ||
1507 | |||
1508 | return err; | ||
1509 | } | ||
1510 | |||
1511 | static const struct nla_policy nl802154_key_policy[NL802154_KEY_ATTR_MAX + 1] = { | ||
1512 | [NL802154_KEY_ATTR_ID] = { NLA_NESTED }, | ||
1513 | /* TODO handle it as for_each_nested and NLA_FLAG? */ | ||
1514 | [NL802154_KEY_ATTR_USAGE_FRAMES] = { NLA_U8 }, | ||
1515 | /* TODO handle it as for_each_nested, not static array? */ | ||
1516 | [NL802154_KEY_ATTR_USAGE_CMDS] = { .len = NL802154_CMD_FRAME_NR_IDS / 8 }, | ||
1517 | [NL802154_KEY_ATTR_BYTES] = { .len = NL802154_KEY_SIZE }, | ||
1518 | }; | ||
1519 | |||
1520 | static int nl802154_add_llsec_key(struct sk_buff *skb, struct genl_info *info) | ||
1521 | { | ||
1522 | struct cfg802154_registered_device *rdev = info->user_ptr[0]; | ||
1523 | struct net_device *dev = info->user_ptr[1]; | ||
1524 | struct wpan_dev *wpan_dev = dev->ieee802154_ptr; | ||
1525 | struct nlattr *attrs[NL802154_KEY_ATTR_MAX + 1]; | ||
1526 | struct ieee802154_llsec_key key = { }; | ||
1527 | struct ieee802154_llsec_key_id id = { }; | ||
1528 | u32 commands[NL802154_CMD_FRAME_NR_IDS / 32] = { }; | ||
1529 | |||
1530 | if (nla_parse_nested(attrs, NL802154_KEY_ATTR_MAX, | ||
1531 | info->attrs[NL802154_ATTR_SEC_KEY], | ||
1532 | nl802154_key_policy)) | ||
1533 | return -EINVAL; | ||
1534 | |||
1535 | if (!attrs[NL802154_KEY_ATTR_USAGE_FRAMES] || | ||
1536 | !attrs[NL802154_KEY_ATTR_BYTES]) | ||
1537 | |||
1538 | if (ieee802154_llsec_parse_key_id(attrs[NL802154_KEY_ATTR_ID], &id) < 0) | ||
1539 | return -ENOBUFS; | ||
1540 | |||
1541 | key.frame_types = nla_get_u8(attrs[NL802154_KEY_ATTR_USAGE_FRAMES]); | ||
1542 | if (key.frame_types > BIT(NL802154_FRAME_MAX) || | ||
1543 | ((key.frame_types & BIT(NL802154_FRAME_CMD)) && | ||
1544 | !attrs[NL802154_KEY_ATTR_USAGE_CMDS])) | ||
1545 | return -EINVAL; | ||
1546 | |||
1547 | if (attrs[NL802154_KEY_ATTR_USAGE_CMDS]) { | ||
1548 | /* TODO for each nested */ | ||
1549 | nla_memcpy(commands, attrs[NL802154_KEY_ATTR_USAGE_CMDS], | ||
1550 | NL802154_CMD_FRAME_NR_IDS / 8); | ||
1551 | |||
1552 | /* TODO understand the -EINVAL logic here? last condition */ | ||
1553 | if (commands[0] || commands[1] || commands[2] || commands[3] || | ||
1554 | commands[4] || commands[5] || commands[6] || | ||
1555 | commands[7] > BIT(NL802154_CMD_FRAME_MAX)) | ||
1556 | return -EINVAL; | ||
1557 | |||
1558 | key.cmd_frame_ids = commands[7]; | ||
1559 | } else { | ||
1560 | key.cmd_frame_ids = 0; | ||
1561 | } | ||
1562 | |||
1563 | nla_memcpy(key.key, attrs[NL802154_KEY_ATTR_BYTES], NL802154_KEY_SIZE); | ||
1564 | |||
1565 | if (ieee802154_llsec_parse_key_id(attrs[NL802154_KEY_ATTR_ID], &id) < 0) | ||
1566 | return -ENOBUFS; | ||
1567 | |||
1568 | return rdev_add_llsec_key(rdev, wpan_dev, &id, &key); | ||
1569 | } | ||
1570 | |||
1571 | static int nl802154_del_llsec_key(struct sk_buff *skb, struct genl_info *info) | ||
1572 | { | ||
1573 | struct cfg802154_registered_device *rdev = info->user_ptr[0]; | ||
1574 | struct net_device *dev = info->user_ptr[1]; | ||
1575 | struct wpan_dev *wpan_dev = dev->ieee802154_ptr; | ||
1576 | struct nlattr *attrs[NL802154_KEY_ATTR_MAX + 1]; | ||
1577 | struct ieee802154_llsec_key_id id; | ||
1578 | |||
1579 | if (nla_parse_nested(attrs, NL802154_KEY_ATTR_MAX, | ||
1580 | info->attrs[NL802154_ATTR_SEC_KEY], | ||
1581 | nl802154_key_policy)) | ||
1582 | return -EINVAL; | ||
1583 | |||
1584 | if (ieee802154_llsec_parse_key_id(attrs[NL802154_KEY_ATTR_ID], &id) < 0) | ||
1585 | return -ENOBUFS; | ||
1586 | |||
1587 | return rdev_del_llsec_key(rdev, wpan_dev, &id); | ||
1588 | } | ||
1589 | |||
1590 | static int nl802154_send_device(struct sk_buff *msg, u32 cmd, u32 portid, | ||
1591 | u32 seq, int flags, | ||
1592 | struct cfg802154_registered_device *rdev, | ||
1593 | struct net_device *dev, | ||
1594 | const struct ieee802154_llsec_device *dev_desc) | ||
1595 | { | ||
1596 | void *hdr; | ||
1597 | struct nlattr *nl_device; | ||
1598 | |||
1599 | hdr = nl802154hdr_put(msg, portid, seq, flags, cmd); | ||
1600 | if (!hdr) | ||
1601 | return -1; | ||
1602 | |||
1603 | if (nla_put_u32(msg, NL802154_ATTR_IFINDEX, dev->ifindex)) | ||
1604 | goto nla_put_failure; | ||
1605 | |||
1606 | nl_device = nla_nest_start(msg, NL802154_ATTR_SEC_DEVICE); | ||
1607 | if (!nl_device) | ||
1608 | goto nla_put_failure; | ||
1609 | |||
1610 | if (nla_put_u32(msg, NL802154_DEV_ATTR_FRAME_COUNTER, | ||
1611 | dev_desc->frame_counter) || | ||
1612 | nla_put_le16(msg, NL802154_DEV_ATTR_PAN_ID, dev_desc->pan_id) || | ||
1613 | nla_put_le16(msg, NL802154_DEV_ATTR_SHORT_ADDR, | ||
1614 | dev_desc->short_addr) || | ||
1615 | nla_put_le64(msg, NL802154_DEV_ATTR_EXTENDED_ADDR, | ||
1616 | dev_desc->hwaddr) || | ||
1617 | nla_put_u8(msg, NL802154_DEV_ATTR_SECLEVEL_EXEMPT, | ||
1618 | dev_desc->seclevel_exempt) || | ||
1619 | nla_put_u32(msg, NL802154_DEV_ATTR_KEY_MODE, dev_desc->key_mode)) | ||
1620 | goto nla_put_failure; | ||
1621 | |||
1622 | nla_nest_end(msg, nl_device); | ||
1623 | genlmsg_end(msg, hdr); | ||
1624 | |||
1625 | return 0; | ||
1626 | |||
1627 | nla_put_failure: | ||
1628 | genlmsg_cancel(msg, hdr); | ||
1629 | return -EMSGSIZE; | ||
1630 | } | ||
1631 | |||
1632 | static int | ||
1633 | nl802154_dump_llsec_dev(struct sk_buff *skb, struct netlink_callback *cb) | ||
1634 | { | ||
1635 | struct cfg802154_registered_device *rdev = NULL; | ||
1636 | struct ieee802154_llsec_device *dev; | ||
1637 | struct ieee802154_llsec_table *table; | ||
1638 | struct wpan_dev *wpan_dev; | ||
1639 | int err; | ||
1640 | |||
1641 | err = nl802154_prepare_wpan_dev_dump(skb, cb, &rdev, &wpan_dev); | ||
1642 | if (err) | ||
1643 | return err; | ||
1644 | |||
1645 | if (!wpan_dev->netdev) { | ||
1646 | err = -EINVAL; | ||
1647 | goto out_err; | ||
1648 | } | ||
1649 | |||
1650 | rdev_lock_llsec_table(rdev, wpan_dev); | ||
1651 | rdev_get_llsec_table(rdev, wpan_dev, &table); | ||
1652 | |||
1653 | /* TODO make it like station dump */ | ||
1654 | if (cb->args[2]) | ||
1655 | goto out; | ||
1656 | |||
1657 | list_for_each_entry(dev, &table->devices, list) { | ||
1658 | if (nl802154_send_device(skb, NL802154_CMD_NEW_SEC_LEVEL, | ||
1659 | NETLINK_CB(cb->skb).portid, | ||
1660 | cb->nlh->nlmsg_seq, NLM_F_MULTI, | ||
1661 | rdev, wpan_dev->netdev, dev) < 0) { | ||
1662 | /* TODO */ | ||
1663 | err = -EIO; | ||
1664 | rdev_unlock_llsec_table(rdev, wpan_dev); | ||
1665 | goto out_err; | ||
1666 | } | ||
1667 | } | ||
1668 | |||
1669 | cb->args[2] = 1; | ||
1670 | |||
1671 | out: | ||
1672 | rdev_unlock_llsec_table(rdev, wpan_dev); | ||
1673 | err = skb->len; | ||
1674 | out_err: | ||
1675 | nl802154_finish_wpan_dev_dump(rdev); | ||
1676 | |||
1677 | return err; | ||
1678 | } | ||
1679 | |||
1680 | static const struct nla_policy nl802154_dev_policy[NL802154_DEV_ATTR_MAX + 1] = { | ||
1681 | [NL802154_DEV_ATTR_FRAME_COUNTER] = { NLA_U32 }, | ||
1682 | [NL802154_DEV_ATTR_PAN_ID] = { .type = NLA_U16 }, | ||
1683 | [NL802154_DEV_ATTR_SHORT_ADDR] = { .type = NLA_U16 }, | ||
1684 | [NL802154_DEV_ATTR_EXTENDED_ADDR] = { .type = NLA_U64 }, | ||
1685 | [NL802154_DEV_ATTR_SECLEVEL_EXEMPT] = { NLA_U8 }, | ||
1686 | [NL802154_DEV_ATTR_KEY_MODE] = { NLA_U32 }, | ||
1687 | }; | ||
1688 | |||
1689 | static int | ||
1690 | ieee802154_llsec_parse_device(struct nlattr *nla, | ||
1691 | struct ieee802154_llsec_device *dev) | ||
1692 | { | ||
1693 | struct nlattr *attrs[NL802154_DEV_ATTR_MAX + 1]; | ||
1694 | |||
1695 | if (!nla || nla_parse_nested(attrs, NL802154_DEV_ATTR_MAX, nla, | ||
1696 | nl802154_dev_policy)) | ||
1697 | return -EINVAL; | ||
1698 | |||
1699 | memset(dev, 0, sizeof(*dev)); | ||
1700 | |||
1701 | if (!attrs[NL802154_DEV_ATTR_FRAME_COUNTER] || | ||
1702 | !attrs[NL802154_DEV_ATTR_PAN_ID] || | ||
1703 | !attrs[NL802154_DEV_ATTR_SHORT_ADDR] || | ||
1704 | !attrs[NL802154_DEV_ATTR_EXTENDED_ADDR] || | ||
1705 | !attrs[NL802154_DEV_ATTR_SECLEVEL_EXEMPT] || | ||
1706 | !attrs[NL802154_DEV_ATTR_KEY_MODE]) | ||
1707 | return -EINVAL; | ||
1708 | |||
1709 | /* TODO be32 */ | ||
1710 | dev->frame_counter = nla_get_u32(attrs[NL802154_DEV_ATTR_FRAME_COUNTER]); | ||
1711 | dev->pan_id = nla_get_le16(attrs[NL802154_DEV_ATTR_PAN_ID]); | ||
1712 | dev->short_addr = nla_get_le16(attrs[NL802154_DEV_ATTR_SHORT_ADDR]); | ||
1713 | /* TODO rename hwaddr to extended_addr */ | ||
1714 | dev->hwaddr = nla_get_le64(attrs[NL802154_DEV_ATTR_EXTENDED_ADDR]); | ||
1715 | dev->seclevel_exempt = nla_get_u8(attrs[NL802154_DEV_ATTR_SECLEVEL_EXEMPT]); | ||
1716 | dev->key_mode = nla_get_u32(attrs[NL802154_DEV_ATTR_KEY_MODE]); | ||
1717 | |||
1718 | if (dev->key_mode > NL802154_DEVKEY_MAX || | ||
1719 | (dev->seclevel_exempt != 0 && dev->seclevel_exempt != 1)) | ||
1720 | return -EINVAL; | ||
1721 | |||
1722 | return 0; | ||
1723 | } | ||
1724 | |||
1725 | static int nl802154_add_llsec_dev(struct sk_buff *skb, struct genl_info *info) | ||
1726 | { | ||
1727 | struct cfg802154_registered_device *rdev = info->user_ptr[0]; | ||
1728 | struct net_device *dev = info->user_ptr[1]; | ||
1729 | struct wpan_dev *wpan_dev = dev->ieee802154_ptr; | ||
1730 | struct ieee802154_llsec_device dev_desc; | ||
1731 | |||
1732 | if (ieee802154_llsec_parse_device(info->attrs[NL802154_ATTR_SEC_DEVICE], | ||
1733 | &dev_desc) < 0) | ||
1734 | return -EINVAL; | ||
1735 | |||
1736 | return rdev_add_device(rdev, wpan_dev, &dev_desc); | ||
1737 | } | ||
1738 | |||
1739 | static int nl802154_del_llsec_dev(struct sk_buff *skb, struct genl_info *info) | ||
1740 | { | ||
1741 | struct cfg802154_registered_device *rdev = info->user_ptr[0]; | ||
1742 | struct net_device *dev = info->user_ptr[1]; | ||
1743 | struct wpan_dev *wpan_dev = dev->ieee802154_ptr; | ||
1744 | struct nlattr *attrs[NL802154_DEV_ATTR_MAX + 1]; | ||
1745 | __le64 extended_addr; | ||
1746 | |||
1747 | if (nla_parse_nested(attrs, NL802154_DEV_ATTR_MAX, | ||
1748 | info->attrs[NL802154_ATTR_SEC_DEVICE], | ||
1749 | nl802154_dev_policy)) | ||
1750 | return -EINVAL; | ||
1751 | |||
1752 | if (!attrs[NL802154_DEV_ATTR_EXTENDED_ADDR]) | ||
1753 | return -EINVAL; | ||
1754 | |||
1755 | extended_addr = nla_get_le64(attrs[NL802154_DEV_ATTR_EXTENDED_ADDR]); | ||
1756 | return rdev_del_device(rdev, wpan_dev, extended_addr); | ||
1757 | } | ||
1758 | |||
1759 | static int nl802154_send_devkey(struct sk_buff *msg, u32 cmd, u32 portid, | ||
1760 | u32 seq, int flags, | ||
1761 | struct cfg802154_registered_device *rdev, | ||
1762 | struct net_device *dev, __le64 extended_addr, | ||
1763 | const struct ieee802154_llsec_device_key *devkey) | ||
1764 | { | ||
1765 | void *hdr; | ||
1766 | struct nlattr *nl_devkey, *nl_key_id; | ||
1767 | |||
1768 | hdr = nl802154hdr_put(msg, portid, seq, flags, cmd); | ||
1769 | if (!hdr) | ||
1770 | return -1; | ||
1771 | |||
1772 | if (nla_put_u32(msg, NL802154_ATTR_IFINDEX, dev->ifindex)) | ||
1773 | goto nla_put_failure; | ||
1774 | |||
1775 | nl_devkey = nla_nest_start(msg, NL802154_ATTR_SEC_DEVKEY); | ||
1776 | if (!nl_devkey) | ||
1777 | goto nla_put_failure; | ||
1778 | |||
1779 | if (nla_put_le64(msg, NL802154_DEVKEY_ATTR_EXTENDED_ADDR, | ||
1780 | extended_addr) || | ||
1781 | nla_put_u32(msg, NL802154_DEVKEY_ATTR_FRAME_COUNTER, | ||
1782 | devkey->frame_counter)) | ||
1783 | goto nla_put_failure; | ||
1784 | |||
1785 | nl_key_id = nla_nest_start(msg, NL802154_DEVKEY_ATTR_ID); | ||
1786 | if (!nl_key_id) | ||
1787 | goto nla_put_failure; | ||
1788 | |||
1789 | if (ieee802154_llsec_send_key_id(msg, &devkey->key_id) < 0) | ||
1790 | goto nla_put_failure; | ||
1791 | |||
1792 | nla_nest_end(msg, nl_key_id); | ||
1793 | nla_nest_end(msg, nl_devkey); | ||
1794 | genlmsg_end(msg, hdr); | ||
1795 | |||
1796 | return 0; | ||
1797 | |||
1798 | nla_put_failure: | ||
1799 | genlmsg_cancel(msg, hdr); | ||
1800 | return -EMSGSIZE; | ||
1801 | } | ||
1802 | |||
1803 | static int | ||
1804 | nl802154_dump_llsec_devkey(struct sk_buff *skb, struct netlink_callback *cb) | ||
1805 | { | ||
1806 | struct cfg802154_registered_device *rdev = NULL; | ||
1807 | struct ieee802154_llsec_device_key *kpos; | ||
1808 | struct ieee802154_llsec_device *dpos; | ||
1809 | struct ieee802154_llsec_table *table; | ||
1810 | struct wpan_dev *wpan_dev; | ||
1811 | int err; | ||
1812 | |||
1813 | err = nl802154_prepare_wpan_dev_dump(skb, cb, &rdev, &wpan_dev); | ||
1814 | if (err) | ||
1815 | return err; | ||
1816 | |||
1817 | if (!wpan_dev->netdev) { | ||
1818 | err = -EINVAL; | ||
1819 | goto out_err; | ||
1820 | } | ||
1821 | |||
1822 | rdev_lock_llsec_table(rdev, wpan_dev); | ||
1823 | rdev_get_llsec_table(rdev, wpan_dev, &table); | ||
1824 | |||
1825 | /* TODO make it like station dump */ | ||
1826 | if (cb->args[2]) | ||
1827 | goto out; | ||
1828 | |||
1829 | /* TODO look if remove devkey and do some nested attribute */ | ||
1830 | list_for_each_entry(dpos, &table->devices, list) { | ||
1831 | list_for_each_entry(kpos, &dpos->keys, list) { | ||
1832 | if (nl802154_send_devkey(skb, | ||
1833 | NL802154_CMD_NEW_SEC_LEVEL, | ||
1834 | NETLINK_CB(cb->skb).portid, | ||
1835 | cb->nlh->nlmsg_seq, | ||
1836 | NLM_F_MULTI, rdev, | ||
1837 | wpan_dev->netdev, | ||
1838 | dpos->hwaddr, | ||
1839 | kpos) < 0) { | ||
1840 | /* TODO */ | ||
1841 | err = -EIO; | ||
1842 | rdev_unlock_llsec_table(rdev, wpan_dev); | ||
1843 | goto out_err; | ||
1844 | } | ||
1845 | } | ||
1846 | } | ||
1847 | |||
1848 | cb->args[2] = 1; | ||
1849 | |||
1850 | out: | ||
1851 | rdev_unlock_llsec_table(rdev, wpan_dev); | ||
1852 | err = skb->len; | ||
1853 | out_err: | ||
1854 | nl802154_finish_wpan_dev_dump(rdev); | ||
1855 | |||
1856 | return err; | ||
1857 | } | ||
1858 | |||
1859 | static const struct nla_policy nl802154_devkey_policy[NL802154_DEVKEY_ATTR_MAX + 1] = { | ||
1860 | [NL802154_DEVKEY_ATTR_FRAME_COUNTER] = { NLA_U32 }, | ||
1861 | [NL802154_DEVKEY_ATTR_EXTENDED_ADDR] = { NLA_U64 }, | ||
1862 | [NL802154_DEVKEY_ATTR_ID] = { NLA_NESTED }, | ||
1863 | }; | ||
1864 | |||
1865 | static int nl802154_add_llsec_devkey(struct sk_buff *skb, struct genl_info *info) | ||
1866 | { | ||
1867 | struct cfg802154_registered_device *rdev = info->user_ptr[0]; | ||
1868 | struct net_device *dev = info->user_ptr[1]; | ||
1869 | struct wpan_dev *wpan_dev = dev->ieee802154_ptr; | ||
1870 | struct nlattr *attrs[NL802154_DEVKEY_ATTR_MAX + 1]; | ||
1871 | struct ieee802154_llsec_device_key key; | ||
1872 | __le64 extended_addr; | ||
1873 | |||
1874 | if (!info->attrs[NL802154_ATTR_SEC_DEVKEY] || | ||
1875 | nla_parse_nested(attrs, NL802154_DEVKEY_ATTR_MAX, | ||
1876 | info->attrs[NL802154_ATTR_SEC_DEVKEY], | ||
1877 | nl802154_devkey_policy) < 0) | ||
1878 | return -EINVAL; | ||
1879 | |||
1880 | if (!attrs[NL802154_DEVKEY_ATTR_FRAME_COUNTER] || | ||
1881 | !attrs[NL802154_DEVKEY_ATTR_EXTENDED_ADDR]) | ||
1882 | return -EINVAL; | ||
1883 | |||
1884 | /* TODO change key.id ? */ | ||
1885 | if (ieee802154_llsec_parse_key_id(attrs[NL802154_DEVKEY_ATTR_ID], | ||
1886 | &key.key_id) < 0) | ||
1887 | return -ENOBUFS; | ||
1888 | |||
1889 | /* TODO be32 */ | ||
1890 | key.frame_counter = nla_get_u32(attrs[NL802154_DEVKEY_ATTR_FRAME_COUNTER]); | ||
1891 | /* TODO change naming hwaddr -> extended_addr | ||
1892 | * check unique identifier short+pan OR extended_addr | ||
1893 | */ | ||
1894 | extended_addr = nla_get_le64(attrs[NL802154_DEVKEY_ATTR_EXTENDED_ADDR]); | ||
1895 | return rdev_add_devkey(rdev, wpan_dev, extended_addr, &key); | ||
1896 | } | ||
1897 | |||
1898 | static int nl802154_del_llsec_devkey(struct sk_buff *skb, struct genl_info *info) | ||
1899 | { | ||
1900 | struct cfg802154_registered_device *rdev = info->user_ptr[0]; | ||
1901 | struct net_device *dev = info->user_ptr[1]; | ||
1902 | struct wpan_dev *wpan_dev = dev->ieee802154_ptr; | ||
1903 | struct nlattr *attrs[NL802154_DEVKEY_ATTR_MAX + 1]; | ||
1904 | struct ieee802154_llsec_device_key key; | ||
1905 | __le64 extended_addr; | ||
1906 | |||
1907 | if (nla_parse_nested(attrs, NL802154_DEVKEY_ATTR_MAX, | ||
1908 | info->attrs[NL802154_ATTR_SEC_DEVKEY], | ||
1909 | nl802154_devkey_policy)) | ||
1910 | return -EINVAL; | ||
1911 | |||
1912 | if (!attrs[NL802154_DEVKEY_ATTR_EXTENDED_ADDR]) | ||
1913 | return -EINVAL; | ||
1914 | |||
1915 | /* TODO change key.id ? */ | ||
1916 | if (ieee802154_llsec_parse_key_id(attrs[NL802154_DEVKEY_ATTR_ID], | ||
1917 | &key.key_id) < 0) | ||
1918 | return -ENOBUFS; | ||
1919 | |||
1920 | /* TODO change naming hwaddr -> extended_addr | ||
1921 | * check unique identifier short+pan OR extended_addr | ||
1922 | */ | ||
1923 | extended_addr = nla_get_le64(attrs[NL802154_DEVKEY_ATTR_EXTENDED_ADDR]); | ||
1924 | return rdev_del_devkey(rdev, wpan_dev, extended_addr, &key); | ||
1925 | } | ||
1926 | |||
1927 | static int nl802154_send_seclevel(struct sk_buff *msg, u32 cmd, u32 portid, | ||
1928 | u32 seq, int flags, | ||
1929 | struct cfg802154_registered_device *rdev, | ||
1930 | struct net_device *dev, | ||
1931 | const struct ieee802154_llsec_seclevel *sl) | ||
1932 | { | ||
1933 | void *hdr; | ||
1934 | struct nlattr *nl_seclevel; | ||
1935 | |||
1936 | hdr = nl802154hdr_put(msg, portid, seq, flags, cmd); | ||
1937 | if (!hdr) | ||
1938 | return -1; | ||
1939 | |||
1940 | if (nla_put_u32(msg, NL802154_ATTR_IFINDEX, dev->ifindex)) | ||
1941 | goto nla_put_failure; | ||
1942 | |||
1943 | nl_seclevel = nla_nest_start(msg, NL802154_ATTR_SEC_LEVEL); | ||
1944 | if (!nl_seclevel) | ||
1945 | goto nla_put_failure; | ||
1946 | |||
1947 | if (nla_put_u32(msg, NL802154_SECLEVEL_ATTR_FRAME, sl->frame_type) || | ||
1948 | nla_put_u32(msg, NL802154_SECLEVEL_ATTR_LEVELS, sl->sec_levels) || | ||
1949 | nla_put_u8(msg, NL802154_SECLEVEL_ATTR_DEV_OVERRIDE, | ||
1950 | sl->device_override)) | ||
1951 | goto nla_put_failure; | ||
1952 | |||
1953 | if (sl->frame_type == NL802154_FRAME_CMD) { | ||
1954 | if (nla_put_u32(msg, NL802154_SECLEVEL_ATTR_CMD_FRAME, | ||
1955 | sl->cmd_frame_id)) | ||
1956 | goto nla_put_failure; | ||
1957 | } | ||
1958 | |||
1959 | nla_nest_end(msg, nl_seclevel); | ||
1960 | genlmsg_end(msg, hdr); | ||
1961 | |||
1962 | return 0; | ||
1963 | |||
1964 | nla_put_failure: | ||
1965 | genlmsg_cancel(msg, hdr); | ||
1966 | return -EMSGSIZE; | ||
1967 | } | ||
1968 | |||
1969 | static int | ||
1970 | nl802154_dump_llsec_seclevel(struct sk_buff *skb, struct netlink_callback *cb) | ||
1971 | { | ||
1972 | struct cfg802154_registered_device *rdev = NULL; | ||
1973 | struct ieee802154_llsec_seclevel *sl; | ||
1974 | struct ieee802154_llsec_table *table; | ||
1975 | struct wpan_dev *wpan_dev; | ||
1976 | int err; | ||
1977 | |||
1978 | err = nl802154_prepare_wpan_dev_dump(skb, cb, &rdev, &wpan_dev); | ||
1979 | if (err) | ||
1980 | return err; | ||
1981 | |||
1982 | if (!wpan_dev->netdev) { | ||
1983 | err = -EINVAL; | ||
1984 | goto out_err; | ||
1985 | } | ||
1986 | |||
1987 | rdev_lock_llsec_table(rdev, wpan_dev); | ||
1988 | rdev_get_llsec_table(rdev, wpan_dev, &table); | ||
1989 | |||
1990 | /* TODO make it like station dump */ | ||
1991 | if (cb->args[2]) | ||
1992 | goto out; | ||
1993 | |||
1994 | list_for_each_entry(sl, &table->security_levels, list) { | ||
1995 | if (nl802154_send_seclevel(skb, NL802154_CMD_NEW_SEC_LEVEL, | ||
1996 | NETLINK_CB(cb->skb).portid, | ||
1997 | cb->nlh->nlmsg_seq, NLM_F_MULTI, | ||
1998 | rdev, wpan_dev->netdev, sl) < 0) { | ||
1999 | /* TODO */ | ||
2000 | err = -EIO; | ||
2001 | rdev_unlock_llsec_table(rdev, wpan_dev); | ||
2002 | goto out_err; | ||
2003 | } | ||
2004 | } | ||
2005 | |||
2006 | cb->args[2] = 1; | ||
2007 | |||
2008 | out: | ||
2009 | rdev_unlock_llsec_table(rdev, wpan_dev); | ||
2010 | err = skb->len; | ||
2011 | out_err: | ||
2012 | nl802154_finish_wpan_dev_dump(rdev); | ||
2013 | |||
2014 | return err; | ||
2015 | } | ||
2016 | |||
2017 | static const struct nla_policy nl802154_seclevel_policy[NL802154_SECLEVEL_ATTR_MAX + 1] = { | ||
2018 | [NL802154_SECLEVEL_ATTR_LEVELS] = { .type = NLA_U8 }, | ||
2019 | [NL802154_SECLEVEL_ATTR_FRAME] = { .type = NLA_U32 }, | ||
2020 | [NL802154_SECLEVEL_ATTR_CMD_FRAME] = { .type = NLA_U32 }, | ||
2021 | [NL802154_SECLEVEL_ATTR_DEV_OVERRIDE] = { .type = NLA_U8 }, | ||
2022 | }; | ||
2023 | |||
2024 | static int | ||
2025 | llsec_parse_seclevel(struct nlattr *nla, struct ieee802154_llsec_seclevel *sl) | ||
2026 | { | ||
2027 | struct nlattr *attrs[NL802154_SECLEVEL_ATTR_MAX + 1]; | ||
2028 | |||
2029 | if (!nla || nla_parse_nested(attrs, NL802154_SECLEVEL_ATTR_MAX, nla, | ||
2030 | nl802154_seclevel_policy)) | ||
2031 | return -EINVAL; | ||
2032 | |||
2033 | memset(sl, 0, sizeof(*sl)); | ||
2034 | |||
2035 | if (!attrs[NL802154_SECLEVEL_ATTR_LEVELS] || | ||
2036 | !attrs[NL802154_SECLEVEL_ATTR_FRAME] || | ||
2037 | !attrs[NL802154_SECLEVEL_ATTR_DEV_OVERRIDE]) | ||
2038 | return -EINVAL; | ||
2039 | |||
2040 | sl->sec_levels = nla_get_u8(attrs[NL802154_SECLEVEL_ATTR_LEVELS]); | ||
2041 | sl->frame_type = nla_get_u32(attrs[NL802154_SECLEVEL_ATTR_FRAME]); | ||
2042 | sl->device_override = nla_get_u8(attrs[NL802154_SECLEVEL_ATTR_DEV_OVERRIDE]); | ||
2043 | if (sl->frame_type > NL802154_FRAME_MAX || | ||
2044 | (sl->device_override != 0 && sl->device_override != 1)) | ||
2045 | return -EINVAL; | ||
2046 | |||
2047 | if (sl->frame_type == NL802154_FRAME_CMD) { | ||
2048 | if (!attrs[NL802154_SECLEVEL_ATTR_CMD_FRAME]) | ||
2049 | return -EINVAL; | ||
2050 | |||
2051 | sl->cmd_frame_id = nla_get_u32(attrs[NL802154_SECLEVEL_ATTR_CMD_FRAME]); | ||
2052 | if (sl->cmd_frame_id > NL802154_CMD_FRAME_MAX) | ||
2053 | return -EINVAL; | ||
2054 | } | ||
2055 | |||
2056 | return 0; | ||
2057 | } | ||
2058 | |||
2059 | static int nl802154_add_llsec_seclevel(struct sk_buff *skb, | ||
2060 | struct genl_info *info) | ||
2061 | { | ||
2062 | struct cfg802154_registered_device *rdev = info->user_ptr[0]; | ||
2063 | struct net_device *dev = info->user_ptr[1]; | ||
2064 | struct wpan_dev *wpan_dev = dev->ieee802154_ptr; | ||
2065 | struct ieee802154_llsec_seclevel sl; | ||
2066 | |||
2067 | if (llsec_parse_seclevel(info->attrs[NL802154_ATTR_SEC_LEVEL], | ||
2068 | &sl) < 0) | ||
2069 | return -EINVAL; | ||
2070 | |||
2071 | return rdev_add_seclevel(rdev, wpan_dev, &sl); | ||
2072 | } | ||
2073 | |||
2074 | static int nl802154_del_llsec_seclevel(struct sk_buff *skb, | ||
2075 | struct genl_info *info) | ||
2076 | { | ||
2077 | struct cfg802154_registered_device *rdev = info->user_ptr[0]; | ||
2078 | struct net_device *dev = info->user_ptr[1]; | ||
2079 | struct wpan_dev *wpan_dev = dev->ieee802154_ptr; | ||
2080 | struct ieee802154_llsec_seclevel sl; | ||
2081 | |||
2082 | if (!info->attrs[NL802154_ATTR_SEC_LEVEL] || | ||
2083 | llsec_parse_seclevel(info->attrs[NL802154_ATTR_SEC_LEVEL], | ||
2084 | &sl) < 0) | ||
2085 | return -EINVAL; | ||
2086 | |||
2087 | return rdev_del_seclevel(rdev, wpan_dev, &sl); | ||
2088 | } | ||
2089 | #endif /* CONFIG_IEEE802154_NL802154_EXPERIMENTAL */ | ||
2090 | |||
1076 | #define NL802154_FLAG_NEED_WPAN_PHY 0x01 | 2091 | #define NL802154_FLAG_NEED_WPAN_PHY 0x01 |
1077 | #define NL802154_FLAG_NEED_NETDEV 0x02 | 2092 | #define NL802154_FLAG_NEED_NETDEV 0x02 |
1078 | #define NL802154_FLAG_NEED_RTNL 0x04 | 2093 | #define NL802154_FLAG_NEED_RTNL 0x04 |
@@ -1287,6 +2302,119 @@ static const struct genl_ops nl802154_ops[] = { | |||
1287 | .internal_flags = NL802154_FLAG_NEED_NETDEV | | 2302 | .internal_flags = NL802154_FLAG_NEED_NETDEV | |
1288 | NL802154_FLAG_NEED_RTNL, | 2303 | NL802154_FLAG_NEED_RTNL, |
1289 | }, | 2304 | }, |
2305 | #ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL | ||
2306 | { | ||
2307 | .cmd = NL802154_CMD_SET_SEC_PARAMS, | ||
2308 | .doit = nl802154_set_llsec_params, | ||
2309 | .policy = nl802154_policy, | ||
2310 | .flags = GENL_ADMIN_PERM, | ||
2311 | .internal_flags = NL802154_FLAG_NEED_NETDEV | | ||
2312 | NL802154_FLAG_NEED_RTNL, | ||
2313 | }, | ||
2314 | { | ||
2315 | .cmd = NL802154_CMD_GET_SEC_KEY, | ||
2316 | /* TODO .doit by matching key id? */ | ||
2317 | .dumpit = nl802154_dump_llsec_key, | ||
2318 | .policy = nl802154_policy, | ||
2319 | .flags = GENL_ADMIN_PERM, | ||
2320 | .internal_flags = NL802154_FLAG_NEED_NETDEV | | ||
2321 | NL802154_FLAG_NEED_RTNL, | ||
2322 | }, | ||
2323 | { | ||
2324 | .cmd = NL802154_CMD_NEW_SEC_KEY, | ||
2325 | .doit = nl802154_add_llsec_key, | ||
2326 | .policy = nl802154_policy, | ||
2327 | .flags = GENL_ADMIN_PERM, | ||
2328 | .internal_flags = NL802154_FLAG_NEED_NETDEV | | ||
2329 | NL802154_FLAG_NEED_RTNL, | ||
2330 | }, | ||
2331 | { | ||
2332 | .cmd = NL802154_CMD_DEL_SEC_KEY, | ||
2333 | .doit = nl802154_del_llsec_key, | ||
2334 | .policy = nl802154_policy, | ||
2335 | .flags = GENL_ADMIN_PERM, | ||
2336 | .internal_flags = NL802154_FLAG_NEED_NETDEV | | ||
2337 | NL802154_FLAG_NEED_RTNL, | ||
2338 | }, | ||
2339 | /* TODO unique identifier must short+pan OR extended_addr */ | ||
2340 | { | ||
2341 | .cmd = NL802154_CMD_GET_SEC_DEV, | ||
2342 | /* TODO .doit by matching extended_addr? */ | ||
2343 | .dumpit = nl802154_dump_llsec_dev, | ||
2344 | .policy = nl802154_policy, | ||
2345 | .flags = GENL_ADMIN_PERM, | ||
2346 | .internal_flags = NL802154_FLAG_NEED_NETDEV | | ||
2347 | NL802154_FLAG_NEED_RTNL, | ||
2348 | }, | ||
2349 | { | ||
2350 | .cmd = NL802154_CMD_NEW_SEC_DEV, | ||
2351 | .doit = nl802154_add_llsec_dev, | ||
2352 | .policy = nl802154_policy, | ||
2353 | .flags = GENL_ADMIN_PERM, | ||
2354 | .internal_flags = NL802154_FLAG_NEED_NETDEV | | ||
2355 | NL802154_FLAG_NEED_RTNL, | ||
2356 | }, | ||
2357 | { | ||
2358 | .cmd = NL802154_CMD_DEL_SEC_DEV, | ||
2359 | .doit = nl802154_del_llsec_dev, | ||
2360 | .policy = nl802154_policy, | ||
2361 | .flags = GENL_ADMIN_PERM, | ||
2362 | .internal_flags = NL802154_FLAG_NEED_NETDEV | | ||
2363 | NL802154_FLAG_NEED_RTNL, | ||
2364 | }, | ||
2365 | /* TODO remove complete devkey, put it as nested? */ | ||
2366 | { | ||
2367 | .cmd = NL802154_CMD_GET_SEC_DEVKEY, | ||
2368 | /* TODO doit by matching ??? */ | ||
2369 | .dumpit = nl802154_dump_llsec_devkey, | ||
2370 | .policy = nl802154_policy, | ||
2371 | .flags = GENL_ADMIN_PERM, | ||
2372 | .internal_flags = NL802154_FLAG_NEED_NETDEV | | ||
2373 | NL802154_FLAG_NEED_RTNL, | ||
2374 | }, | ||
2375 | { | ||
2376 | .cmd = NL802154_CMD_NEW_SEC_DEVKEY, | ||
2377 | .doit = nl802154_add_llsec_devkey, | ||
2378 | .policy = nl802154_policy, | ||
2379 | .flags = GENL_ADMIN_PERM, | ||
2380 | .internal_flags = NL802154_FLAG_NEED_NETDEV | | ||
2381 | NL802154_FLAG_NEED_RTNL, | ||
2382 | }, | ||
2383 | { | ||
2384 | .cmd = NL802154_CMD_DEL_SEC_DEVKEY, | ||
2385 | .doit = nl802154_del_llsec_devkey, | ||
2386 | .policy = nl802154_policy, | ||
2387 | .flags = GENL_ADMIN_PERM, | ||
2388 | .internal_flags = NL802154_FLAG_NEED_NETDEV | | ||
2389 | NL802154_FLAG_NEED_RTNL, | ||
2390 | }, | ||
2391 | { | ||
2392 | .cmd = NL802154_CMD_GET_SEC_LEVEL, | ||
2393 | /* TODO .doit by matching frame_type? */ | ||
2394 | .dumpit = nl802154_dump_llsec_seclevel, | ||
2395 | .policy = nl802154_policy, | ||
2396 | .flags = GENL_ADMIN_PERM, | ||
2397 | .internal_flags = NL802154_FLAG_NEED_NETDEV | | ||
2398 | NL802154_FLAG_NEED_RTNL, | ||
2399 | }, | ||
2400 | { | ||
2401 | .cmd = NL802154_CMD_NEW_SEC_LEVEL, | ||
2402 | .doit = nl802154_add_llsec_seclevel, | ||
2403 | .policy = nl802154_policy, | ||
2404 | .flags = GENL_ADMIN_PERM, | ||
2405 | .internal_flags = NL802154_FLAG_NEED_NETDEV | | ||
2406 | NL802154_FLAG_NEED_RTNL, | ||
2407 | }, | ||
2408 | { | ||
2409 | .cmd = NL802154_CMD_DEL_SEC_LEVEL, | ||
2410 | /* TODO match frame_type only? */ | ||
2411 | .doit = nl802154_del_llsec_seclevel, | ||
2412 | .policy = nl802154_policy, | ||
2413 | .flags = GENL_ADMIN_PERM, | ||
2414 | .internal_flags = NL802154_FLAG_NEED_NETDEV | | ||
2415 | NL802154_FLAG_NEED_RTNL, | ||
2416 | }, | ||
2417 | #endif /* CONFIG_IEEE802154_NL802154_EXPERIMENTAL */ | ||
1290 | }; | 2418 | }; |
1291 | 2419 | ||
1292 | /* initialisation/exit functions */ | 2420 | /* initialisation/exit functions */ |
diff --git a/net/ieee802154/rdev-ops.h b/net/ieee802154/rdev-ops.h index 03b357501cc5..4441c63b3ea6 100644 --- a/net/ieee802154/rdev-ops.h +++ b/net/ieee802154/rdev-ops.h | |||
@@ -208,4 +208,113 @@ rdev_set_ackreq_default(struct cfg802154_registered_device *rdev, | |||
208 | return ret; | 208 | return ret; |
209 | } | 209 | } |
210 | 210 | ||
211 | #ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL | ||
212 | /* TODO this is already a nl802154, so move into ieee802154 */ | ||
213 | static inline void | ||
214 | rdev_get_llsec_table(struct cfg802154_registered_device *rdev, | ||
215 | struct wpan_dev *wpan_dev, | ||
216 | struct ieee802154_llsec_table **table) | ||
217 | { | ||
218 | rdev->ops->get_llsec_table(&rdev->wpan_phy, wpan_dev, table); | ||
219 | } | ||
220 | |||
221 | static inline void | ||
222 | rdev_lock_llsec_table(struct cfg802154_registered_device *rdev, | ||
223 | struct wpan_dev *wpan_dev) | ||
224 | { | ||
225 | rdev->ops->lock_llsec_table(&rdev->wpan_phy, wpan_dev); | ||
226 | } | ||
227 | |||
228 | static inline void | ||
229 | rdev_unlock_llsec_table(struct cfg802154_registered_device *rdev, | ||
230 | struct wpan_dev *wpan_dev) | ||
231 | { | ||
232 | rdev->ops->unlock_llsec_table(&rdev->wpan_phy, wpan_dev); | ||
233 | } | ||
234 | |||
235 | static inline int | ||
236 | rdev_get_llsec_params(struct cfg802154_registered_device *rdev, | ||
237 | struct wpan_dev *wpan_dev, | ||
238 | struct ieee802154_llsec_params *params) | ||
239 | { | ||
240 | return rdev->ops->get_llsec_params(&rdev->wpan_phy, wpan_dev, params); | ||
241 | } | ||
242 | |||
243 | static inline int | ||
244 | rdev_set_llsec_params(struct cfg802154_registered_device *rdev, | ||
245 | struct wpan_dev *wpan_dev, | ||
246 | const struct ieee802154_llsec_params *params, | ||
247 | u32 changed) | ||
248 | { | ||
249 | return rdev->ops->set_llsec_params(&rdev->wpan_phy, wpan_dev, params, | ||
250 | changed); | ||
251 | } | ||
252 | |||
253 | static inline int | ||
254 | rdev_add_llsec_key(struct cfg802154_registered_device *rdev, | ||
255 | struct wpan_dev *wpan_dev, | ||
256 | const struct ieee802154_llsec_key_id *id, | ||
257 | const struct ieee802154_llsec_key *key) | ||
258 | { | ||
259 | return rdev->ops->add_llsec_key(&rdev->wpan_phy, wpan_dev, id, key); | ||
260 | } | ||
261 | |||
262 | static inline int | ||
263 | rdev_del_llsec_key(struct cfg802154_registered_device *rdev, | ||
264 | struct wpan_dev *wpan_dev, | ||
265 | const struct ieee802154_llsec_key_id *id) | ||
266 | { | ||
267 | return rdev->ops->del_llsec_key(&rdev->wpan_phy, wpan_dev, id); | ||
268 | } | ||
269 | |||
270 | static inline int | ||
271 | rdev_add_seclevel(struct cfg802154_registered_device *rdev, | ||
272 | struct wpan_dev *wpan_dev, | ||
273 | const struct ieee802154_llsec_seclevel *sl) | ||
274 | { | ||
275 | return rdev->ops->add_seclevel(&rdev->wpan_phy, wpan_dev, sl); | ||
276 | } | ||
277 | |||
278 | static inline int | ||
279 | rdev_del_seclevel(struct cfg802154_registered_device *rdev, | ||
280 | struct wpan_dev *wpan_dev, | ||
281 | const struct ieee802154_llsec_seclevel *sl) | ||
282 | { | ||
283 | return rdev->ops->del_seclevel(&rdev->wpan_phy, wpan_dev, sl); | ||
284 | } | ||
285 | |||
286 | static inline int | ||
287 | rdev_add_device(struct cfg802154_registered_device *rdev, | ||
288 | struct wpan_dev *wpan_dev, | ||
289 | const struct ieee802154_llsec_device *dev_desc) | ||
290 | { | ||
291 | return rdev->ops->add_device(&rdev->wpan_phy, wpan_dev, dev_desc); | ||
292 | } | ||
293 | |||
294 | static inline int | ||
295 | rdev_del_device(struct cfg802154_registered_device *rdev, | ||
296 | struct wpan_dev *wpan_dev, __le64 extended_addr) | ||
297 | { | ||
298 | return rdev->ops->del_device(&rdev->wpan_phy, wpan_dev, extended_addr); | ||
299 | } | ||
300 | |||
301 | static inline int | ||
302 | rdev_add_devkey(struct cfg802154_registered_device *rdev, | ||
303 | struct wpan_dev *wpan_dev, __le64 extended_addr, | ||
304 | const struct ieee802154_llsec_device_key *devkey) | ||
305 | { | ||
306 | return rdev->ops->add_devkey(&rdev->wpan_phy, wpan_dev, extended_addr, | ||
307 | devkey); | ||
308 | } | ||
309 | |||
310 | static inline int | ||
311 | rdev_del_devkey(struct cfg802154_registered_device *rdev, | ||
312 | struct wpan_dev *wpan_dev, __le64 extended_addr, | ||
313 | const struct ieee802154_llsec_device_key *devkey) | ||
314 | { | ||
315 | return rdev->ops->del_devkey(&rdev->wpan_phy, wpan_dev, extended_addr, | ||
316 | devkey); | ||
317 | } | ||
318 | #endif /* CONFIG_IEEE802154_NL802154_EXPERIMENTAL */ | ||
319 | |||
211 | #endif /* __CFG802154_RDEV_OPS */ | 320 | #endif /* __CFG802154_RDEV_OPS */ |