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 | |
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>
-rw-r--r-- | include/net/cfg802154.h | 131 | ||||
-rw-r--r-- | include/net/ieee802154_netdev.h | 75 | ||||
-rw-r--r-- | include/net/nl802154.h | 191 | ||||
-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 | ||||
-rw-r--r-- | net/mac802154/cfg.c | 205 |
9 files changed, 1782 insertions, 75 deletions
diff --git a/include/net/cfg802154.h b/include/net/cfg802154.h index 242273ccf34b..171cd76558fb 100644 --- a/include/net/cfg802154.h +++ b/include/net/cfg802154.h | |||
@@ -27,6 +27,16 @@ | |||
27 | struct wpan_phy; | 27 | struct wpan_phy; |
28 | struct wpan_phy_cca; | 28 | struct wpan_phy_cca; |
29 | 29 | ||
30 | #ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL | ||
31 | struct ieee802154_llsec_device_key; | ||
32 | struct ieee802154_llsec_seclevel; | ||
33 | struct ieee802154_llsec_params; | ||
34 | struct ieee802154_llsec_device; | ||
35 | struct ieee802154_llsec_table; | ||
36 | struct ieee802154_llsec_key_id; | ||
37 | struct ieee802154_llsec_key; | ||
38 | #endif /* CONFIG_IEEE802154_NL802154_EXPERIMENTAL */ | ||
39 | |||
30 | struct cfg802154_ops { | 40 | struct cfg802154_ops { |
31 | struct net_device * (*add_virtual_intf_deprecated)(struct wpan_phy *wpan_phy, | 41 | struct net_device * (*add_virtual_intf_deprecated)(struct wpan_phy *wpan_phy, |
32 | const char *name, | 42 | const char *name, |
@@ -65,6 +75,51 @@ struct cfg802154_ops { | |||
65 | struct wpan_dev *wpan_dev, bool mode); | 75 | struct wpan_dev *wpan_dev, bool mode); |
66 | int (*set_ackreq_default)(struct wpan_phy *wpan_phy, | 76 | int (*set_ackreq_default)(struct wpan_phy *wpan_phy, |
67 | struct wpan_dev *wpan_dev, bool ackreq); | 77 | struct wpan_dev *wpan_dev, bool ackreq); |
78 | #ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL | ||
79 | void (*get_llsec_table)(struct wpan_phy *wpan_phy, | ||
80 | struct wpan_dev *wpan_dev, | ||
81 | struct ieee802154_llsec_table **table); | ||
82 | void (*lock_llsec_table)(struct wpan_phy *wpan_phy, | ||
83 | struct wpan_dev *wpan_dev); | ||
84 | void (*unlock_llsec_table)(struct wpan_phy *wpan_phy, | ||
85 | struct wpan_dev *wpan_dev); | ||
86 | /* TODO remove locking/get table callbacks, this is part of the | ||
87 | * nl802154 interface and should be accessible from ieee802154 layer. | ||
88 | */ | ||
89 | int (*get_llsec_params)(struct wpan_phy *wpan_phy, | ||
90 | struct wpan_dev *wpan_dev, | ||
91 | struct ieee802154_llsec_params *params); | ||
92 | int (*set_llsec_params)(struct wpan_phy *wpan_phy, | ||
93 | struct wpan_dev *wpan_dev, | ||
94 | const struct ieee802154_llsec_params *params, | ||
95 | int changed); | ||
96 | int (*add_llsec_key)(struct wpan_phy *wpan_phy, | ||
97 | struct wpan_dev *wpan_dev, | ||
98 | const struct ieee802154_llsec_key_id *id, | ||
99 | const struct ieee802154_llsec_key *key); | ||
100 | int (*del_llsec_key)(struct wpan_phy *wpan_phy, | ||
101 | struct wpan_dev *wpan_dev, | ||
102 | const struct ieee802154_llsec_key_id *id); | ||
103 | int (*add_seclevel)(struct wpan_phy *wpan_phy, | ||
104 | struct wpan_dev *wpan_dev, | ||
105 | const struct ieee802154_llsec_seclevel *sl); | ||
106 | int (*del_seclevel)(struct wpan_phy *wpan_phy, | ||
107 | struct wpan_dev *wpan_dev, | ||
108 | const struct ieee802154_llsec_seclevel *sl); | ||
109 | int (*add_device)(struct wpan_phy *wpan_phy, | ||
110 | struct wpan_dev *wpan_dev, | ||
111 | const struct ieee802154_llsec_device *dev); | ||
112 | int (*del_device)(struct wpan_phy *wpan_phy, | ||
113 | struct wpan_dev *wpan_dev, __le64 extended_addr); | ||
114 | int (*add_devkey)(struct wpan_phy *wpan_phy, | ||
115 | struct wpan_dev *wpan_dev, | ||
116 | __le64 extended_addr, | ||
117 | const struct ieee802154_llsec_device_key *key); | ||
118 | int (*del_devkey)(struct wpan_phy *wpan_phy, | ||
119 | struct wpan_dev *wpan_dev, | ||
120 | __le64 extended_addr, | ||
121 | const struct ieee802154_llsec_device_key *key); | ||
122 | #endif /* CONFIG_IEEE802154_NL802154_EXPERIMENTAL */ | ||
68 | }; | 123 | }; |
69 | 124 | ||
70 | static inline bool | 125 | static inline bool |
@@ -176,6 +231,82 @@ struct ieee802154_addr { | |||
176 | }; | 231 | }; |
177 | }; | 232 | }; |
178 | 233 | ||
234 | struct ieee802154_llsec_key_id { | ||
235 | u8 mode; | ||
236 | u8 id; | ||
237 | union { | ||
238 | struct ieee802154_addr device_addr; | ||
239 | __le32 short_source; | ||
240 | __le64 extended_source; | ||
241 | }; | ||
242 | }; | ||
243 | |||
244 | #define IEEE802154_LLSEC_KEY_SIZE 16 | ||
245 | |||
246 | struct ieee802154_llsec_key { | ||
247 | u8 frame_types; | ||
248 | u32 cmd_frame_ids; | ||
249 | /* TODO replace with NL802154_KEY_SIZE */ | ||
250 | u8 key[IEEE802154_LLSEC_KEY_SIZE]; | ||
251 | }; | ||
252 | |||
253 | struct ieee802154_llsec_key_entry { | ||
254 | struct list_head list; | ||
255 | |||
256 | struct ieee802154_llsec_key_id id; | ||
257 | struct ieee802154_llsec_key *key; | ||
258 | }; | ||
259 | |||
260 | struct ieee802154_llsec_params { | ||
261 | bool enabled; | ||
262 | |||
263 | __be32 frame_counter; | ||
264 | u8 out_level; | ||
265 | struct ieee802154_llsec_key_id out_key; | ||
266 | |||
267 | __le64 default_key_source; | ||
268 | |||
269 | __le16 pan_id; | ||
270 | __le64 hwaddr; | ||
271 | __le64 coord_hwaddr; | ||
272 | __le16 coord_shortaddr; | ||
273 | }; | ||
274 | |||
275 | struct ieee802154_llsec_table { | ||
276 | struct list_head keys; | ||
277 | struct list_head devices; | ||
278 | struct list_head security_levels; | ||
279 | }; | ||
280 | |||
281 | struct ieee802154_llsec_seclevel { | ||
282 | struct list_head list; | ||
283 | |||
284 | u8 frame_type; | ||
285 | u8 cmd_frame_id; | ||
286 | bool device_override; | ||
287 | u32 sec_levels; | ||
288 | }; | ||
289 | |||
290 | struct ieee802154_llsec_device { | ||
291 | struct list_head list; | ||
292 | |||
293 | __le16 pan_id; | ||
294 | __le16 short_addr; | ||
295 | __le64 hwaddr; | ||
296 | u32 frame_counter; | ||
297 | bool seclevel_exempt; | ||
298 | |||
299 | u8 key_mode; | ||
300 | struct list_head keys; | ||
301 | }; | ||
302 | |||
303 | struct ieee802154_llsec_device_key { | ||
304 | struct list_head list; | ||
305 | |||
306 | struct ieee802154_llsec_key_id key_id; | ||
307 | u32 frame_counter; | ||
308 | }; | ||
309 | |||
179 | struct wpan_dev_header_ops { | 310 | struct wpan_dev_header_ops { |
180 | /* TODO create callback currently assumes ieee802154_mac_cb inside | 311 | /* TODO create callback currently assumes ieee802154_mac_cb inside |
181 | * skb->cb. This should be changed to give these information as | 312 | * skb->cb. This should be changed to give these information as |
diff --git a/include/net/ieee802154_netdev.h b/include/net/ieee802154_netdev.h index aebb9d8d7a11..a62a051a3a2f 100644 --- a/include/net/ieee802154_netdev.h +++ b/include/net/ieee802154_netdev.h | |||
@@ -234,38 +234,6 @@ static inline struct ieee802154_mac_cb *mac_cb_init(struct sk_buff *skb) | |||
234 | return mac_cb(skb); | 234 | return mac_cb(skb); |
235 | } | 235 | } |
236 | 236 | ||
237 | #define IEEE802154_LLSEC_KEY_SIZE 16 | ||
238 | |||
239 | struct ieee802154_llsec_key_id { | ||
240 | u8 mode; | ||
241 | u8 id; | ||
242 | union { | ||
243 | struct ieee802154_addr device_addr; | ||
244 | __le32 short_source; | ||
245 | __le64 extended_source; | ||
246 | }; | ||
247 | }; | ||
248 | |||
249 | struct ieee802154_llsec_key { | ||
250 | u8 frame_types; | ||
251 | u32 cmd_frame_ids; | ||
252 | u8 key[IEEE802154_LLSEC_KEY_SIZE]; | ||
253 | }; | ||
254 | |||
255 | struct ieee802154_llsec_key_entry { | ||
256 | struct list_head list; | ||
257 | |||
258 | struct ieee802154_llsec_key_id id; | ||
259 | struct ieee802154_llsec_key *key; | ||
260 | }; | ||
261 | |||
262 | struct ieee802154_llsec_device_key { | ||
263 | struct list_head list; | ||
264 | |||
265 | struct ieee802154_llsec_key_id key_id; | ||
266 | u32 frame_counter; | ||
267 | }; | ||
268 | |||
269 | enum { | 237 | enum { |
270 | IEEE802154_LLSEC_DEVKEY_IGNORE, | 238 | IEEE802154_LLSEC_DEVKEY_IGNORE, |
271 | IEEE802154_LLSEC_DEVKEY_RESTRICT, | 239 | IEEE802154_LLSEC_DEVKEY_RESTRICT, |
@@ -274,49 +242,6 @@ enum { | |||
274 | __IEEE802154_LLSEC_DEVKEY_MAX, | 242 | __IEEE802154_LLSEC_DEVKEY_MAX, |
275 | }; | 243 | }; |
276 | 244 | ||
277 | struct ieee802154_llsec_device { | ||
278 | struct list_head list; | ||
279 | |||
280 | __le16 pan_id; | ||
281 | __le16 short_addr; | ||
282 | __le64 hwaddr; | ||
283 | u32 frame_counter; | ||
284 | bool seclevel_exempt; | ||
285 | |||
286 | u8 key_mode; | ||
287 | struct list_head keys; | ||
288 | }; | ||
289 | |||
290 | struct ieee802154_llsec_seclevel { | ||
291 | struct list_head list; | ||
292 | |||
293 | u8 frame_type; | ||
294 | u8 cmd_frame_id; | ||
295 | bool device_override; | ||
296 | u32 sec_levels; | ||
297 | }; | ||
298 | |||
299 | struct ieee802154_llsec_params { | ||
300 | bool enabled; | ||
301 | |||
302 | __be32 frame_counter; | ||
303 | u8 out_level; | ||
304 | struct ieee802154_llsec_key_id out_key; | ||
305 | |||
306 | __le64 default_key_source; | ||
307 | |||
308 | __le16 pan_id; | ||
309 | __le64 hwaddr; | ||
310 | __le64 coord_hwaddr; | ||
311 | __le16 coord_shortaddr; | ||
312 | }; | ||
313 | |||
314 | struct ieee802154_llsec_table { | ||
315 | struct list_head keys; | ||
316 | struct list_head devices; | ||
317 | struct list_head security_levels; | ||
318 | }; | ||
319 | |||
320 | #define IEEE802154_MAC_SCAN_ED 0 | 245 | #define IEEE802154_MAC_SCAN_ED 0 |
321 | #define IEEE802154_MAC_SCAN_ACTIVE 1 | 246 | #define IEEE802154_MAC_SCAN_ACTIVE 1 |
322 | #define IEEE802154_MAC_SCAN_PASSIVE 2 | 247 | #define IEEE802154_MAC_SCAN_PASSIVE 2 |
diff --git a/include/net/nl802154.h b/include/net/nl802154.h index cf2713d8b975..32cb3e591e07 100644 --- a/include/net/nl802154.h +++ b/include/net/nl802154.h | |||
@@ -56,6 +56,22 @@ enum nl802154_commands { | |||
56 | 56 | ||
57 | /* add new commands above here */ | 57 | /* add new commands above here */ |
58 | 58 | ||
59 | #ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL | ||
60 | NL802154_CMD_SET_SEC_PARAMS, | ||
61 | NL802154_CMD_GET_SEC_KEY, /* can dump */ | ||
62 | NL802154_CMD_NEW_SEC_KEY, | ||
63 | NL802154_CMD_DEL_SEC_KEY, | ||
64 | NL802154_CMD_GET_SEC_DEV, /* can dump */ | ||
65 | NL802154_CMD_NEW_SEC_DEV, | ||
66 | NL802154_CMD_DEL_SEC_DEV, | ||
67 | NL802154_CMD_GET_SEC_DEVKEY, /* can dump */ | ||
68 | NL802154_CMD_NEW_SEC_DEVKEY, | ||
69 | NL802154_CMD_DEL_SEC_DEVKEY, | ||
70 | NL802154_CMD_GET_SEC_LEVEL, /* can dump */ | ||
71 | NL802154_CMD_NEW_SEC_LEVEL, | ||
72 | NL802154_CMD_DEL_SEC_LEVEL, | ||
73 | #endif /* CONFIG_IEEE802154_NL802154_EXPERIMENTAL */ | ||
74 | |||
59 | /* used to define NL802154_CMD_MAX below */ | 75 | /* used to define NL802154_CMD_MAX below */ |
60 | __NL802154_CMD_AFTER_LAST, | 76 | __NL802154_CMD_AFTER_LAST, |
61 | NL802154_CMD_MAX = __NL802154_CMD_AFTER_LAST - 1 | 77 | NL802154_CMD_MAX = __NL802154_CMD_AFTER_LAST - 1 |
@@ -110,6 +126,18 @@ enum nl802154_attrs { | |||
110 | 126 | ||
111 | /* add attributes here, update the policy in nl802154.c */ | 127 | /* add attributes here, update the policy in nl802154.c */ |
112 | 128 | ||
129 | #ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL | ||
130 | NL802154_ATTR_SEC_ENABLED, | ||
131 | NL802154_ATTR_SEC_OUT_LEVEL, | ||
132 | NL802154_ATTR_SEC_OUT_KEY_ID, | ||
133 | NL802154_ATTR_SEC_FRAME_COUNTER, | ||
134 | |||
135 | NL802154_ATTR_SEC_LEVEL, | ||
136 | NL802154_ATTR_SEC_DEVICE, | ||
137 | NL802154_ATTR_SEC_DEVKEY, | ||
138 | NL802154_ATTR_SEC_KEY, | ||
139 | #endif /* CONFIG_IEEE802154_NL802154_EXPERIMENTAL */ | ||
140 | |||
113 | __NL802154_ATTR_AFTER_LAST, | 141 | __NL802154_ATTR_AFTER_LAST, |
114 | NL802154_ATTR_MAX = __NL802154_ATTR_AFTER_LAST - 1 | 142 | NL802154_ATTR_MAX = __NL802154_ATTR_AFTER_LAST - 1 |
115 | }; | 143 | }; |
@@ -247,4 +275,167 @@ enum nl802154_supported_bool_states { | |||
247 | NL802154_SUPPORTED_BOOL_MAX = __NL802154_SUPPORTED_BOOL_AFTER_LAST - 1 | 275 | NL802154_SUPPORTED_BOOL_MAX = __NL802154_SUPPORTED_BOOL_AFTER_LAST - 1 |
248 | }; | 276 | }; |
249 | 277 | ||
278 | #ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL | ||
279 | |||
280 | enum nl802154_dev_addr_modes { | ||
281 | NL802154_DEV_ADDR_NONE, | ||
282 | __NL802154_DEV_ADDR_INVALID, | ||
283 | NL802154_DEV_ADDR_SHORT, | ||
284 | NL802154_DEV_ADDR_EXTENDED, | ||
285 | |||
286 | /* keep last */ | ||
287 | __NL802154_DEV_ADDR_AFTER_LAST, | ||
288 | NL802154_DEV_ADDR_MAX = __NL802154_DEV_ADDR_AFTER_LAST - 1 | ||
289 | }; | ||
290 | |||
291 | enum nl802154_dev_addr_attrs { | ||
292 | NL802154_DEV_ADDR_ATTR_UNSPEC, | ||
293 | |||
294 | NL802154_DEV_ADDR_ATTR_PAN_ID, | ||
295 | NL802154_DEV_ADDR_ATTR_MODE, | ||
296 | NL802154_DEV_ADDR_ATTR_SHORT, | ||
297 | NL802154_DEV_ADDR_ATTR_EXTENDED, | ||
298 | |||
299 | /* keep last */ | ||
300 | __NL802154_DEV_ADDR_ATTR_AFTER_LAST, | ||
301 | NL802154_DEV_ADDR_ATTR_MAX = __NL802154_DEV_ADDR_ATTR_AFTER_LAST - 1 | ||
302 | }; | ||
303 | |||
304 | enum nl802154_key_id_modes { | ||
305 | NL802154_KEY_ID_MODE_IMPLICIT, | ||
306 | NL802154_KEY_ID_MODE_INDEX, | ||
307 | NL802154_KEY_ID_MODE_INDEX_SHORT, | ||
308 | NL802154_KEY_ID_MODE_INDEX_EXTENDED, | ||
309 | |||
310 | /* keep last */ | ||
311 | __NL802154_KEY_ID_MODE_AFTER_LAST, | ||
312 | NL802154_KEY_ID_MODE_MAX = __NL802154_KEY_ID_MODE_AFTER_LAST - 1 | ||
313 | }; | ||
314 | |||
315 | enum nl802154_key_id_attrs { | ||
316 | NL802154_KEY_ID_ATTR_UNSPEC, | ||
317 | |||
318 | NL802154_KEY_ID_ATTR_MODE, | ||
319 | NL802154_KEY_ID_ATTR_INDEX, | ||
320 | NL802154_KEY_ID_ATTR_IMPLICIT, | ||
321 | NL802154_KEY_ID_ATTR_SOURCE_SHORT, | ||
322 | NL802154_KEY_ID_ATTR_SOURCE_EXTENDED, | ||
323 | |||
324 | /* keep last */ | ||
325 | __NL802154_KEY_ID_ATTR_AFTER_LAST, | ||
326 | NL802154_KEY_ID_ATTR_MAX = __NL802154_KEY_ID_ATTR_AFTER_LAST - 1 | ||
327 | }; | ||
328 | |||
329 | enum nl802154_seclevels { | ||
330 | NL802154_SECLEVEL_NONE, | ||
331 | NL802154_SECLEVEL_MIC32, | ||
332 | NL802154_SECLEVEL_MIC64, | ||
333 | NL802154_SECLEVEL_MIC128, | ||
334 | NL802154_SECLEVEL_ENC, | ||
335 | NL802154_SECLEVEL_ENC_MIC32, | ||
336 | NL802154_SECLEVEL_ENC_MIC64, | ||
337 | NL802154_SECLEVEL_ENC_MIC128, | ||
338 | |||
339 | /* keep last */ | ||
340 | __NL802154_SECLEVEL_AFTER_LAST, | ||
341 | NL802154_SECLEVEL_MAX = __NL802154_SECLEVEL_AFTER_LAST - 1 | ||
342 | }; | ||
343 | |||
344 | enum nl802154_frames { | ||
345 | NL802154_FRAME_BEACON, | ||
346 | NL802154_FRAME_DATA, | ||
347 | NL802154_FRAME_ACK, | ||
348 | NL802154_FRAME_CMD, | ||
349 | |||
350 | /* keep last */ | ||
351 | __NL802154_FRAME_AFTER_LAST, | ||
352 | NL802154_FRAME_MAX = __NL802154_FRAME_AFTER_LAST - 1 | ||
353 | }; | ||
354 | |||
355 | enum nl802154_cmd_frames { | ||
356 | __NL802154_CMD_FRAME_INVALID, | ||
357 | NL802154_CMD_FRAME_ASSOC_REQUEST, | ||
358 | NL802154_CMD_FRAME_ASSOC_RESPONSE, | ||
359 | NL802154_CMD_FRAME_DISASSOC_NOTIFY, | ||
360 | NL802154_CMD_FRAME_DATA_REQUEST, | ||
361 | NL802154_CMD_FRAME_PAN_ID_CONFLICT_NOTIFY, | ||
362 | NL802154_CMD_FRAME_ORPHAN_NOTIFY, | ||
363 | NL802154_CMD_FRAME_BEACON_REQUEST, | ||
364 | NL802154_CMD_FRAME_COORD_REALIGNMENT, | ||
365 | NL802154_CMD_FRAME_GTS_REQUEST, | ||
366 | |||
367 | /* keep last */ | ||
368 | __NL802154_CMD_FRAME_AFTER_LAST, | ||
369 | NL802154_CMD_FRAME_MAX = __NL802154_CMD_FRAME_AFTER_LAST - 1 | ||
370 | }; | ||
371 | |||
372 | enum nl802154_seclevel_attrs { | ||
373 | NL802154_SECLEVEL_ATTR_UNSPEC, | ||
374 | |||
375 | NL802154_SECLEVEL_ATTR_LEVELS, | ||
376 | NL802154_SECLEVEL_ATTR_FRAME, | ||
377 | NL802154_SECLEVEL_ATTR_CMD_FRAME, | ||
378 | NL802154_SECLEVEL_ATTR_DEV_OVERRIDE, | ||
379 | |||
380 | /* keep last */ | ||
381 | __NL802154_SECLEVEL_ATTR_AFTER_LAST, | ||
382 | NL802154_SECLEVEL_ATTR_MAX = __NL802154_SECLEVEL_ATTR_AFTER_LAST - 1 | ||
383 | }; | ||
384 | |||
385 | /* TODO what is this? couldn't find in mib */ | ||
386 | enum { | ||
387 | NL802154_DEVKEY_IGNORE, | ||
388 | NL802154_DEVKEY_RESTRICT, | ||
389 | NL802154_DEVKEY_RECORD, | ||
390 | |||
391 | /* keep last */ | ||
392 | __NL802154_DEVKEY_AFTER_LAST, | ||
393 | NL802154_DEVKEY_MAX = __NL802154_DEVKEY_AFTER_LAST - 1 | ||
394 | }; | ||
395 | |||
396 | enum nl802154_dev { | ||
397 | NL802154_DEV_ATTR_UNSPEC, | ||
398 | |||
399 | NL802154_DEV_ATTR_FRAME_COUNTER, | ||
400 | NL802154_DEV_ATTR_PAN_ID, | ||
401 | NL802154_DEV_ATTR_SHORT_ADDR, | ||
402 | NL802154_DEV_ATTR_EXTENDED_ADDR, | ||
403 | NL802154_DEV_ATTR_SECLEVEL_EXEMPT, | ||
404 | NL802154_DEV_ATTR_KEY_MODE, | ||
405 | |||
406 | /* keep last */ | ||
407 | __NL802154_DEV_ATTR_AFTER_LAST, | ||
408 | NL802154_DEV_ATTR_MAX = __NL802154_DEV_ATTR_AFTER_LAST - 1 | ||
409 | }; | ||
410 | |||
411 | enum nl802154_devkey { | ||
412 | NL802154_DEVKEY_ATTR_UNSPEC, | ||
413 | |||
414 | NL802154_DEVKEY_ATTR_FRAME_COUNTER, | ||
415 | NL802154_DEVKEY_ATTR_EXTENDED_ADDR, | ||
416 | NL802154_DEVKEY_ATTR_ID, | ||
417 | |||
418 | /* keep last */ | ||
419 | __NL802154_DEVKEY_ATTR_AFTER_LAST, | ||
420 | NL802154_DEVKEY_ATTR_MAX = __NL802154_DEVKEY_ATTR_AFTER_LAST - 1 | ||
421 | }; | ||
422 | |||
423 | enum nl802154_key { | ||
424 | NL802154_KEY_ATTR_UNSPEC, | ||
425 | |||
426 | NL802154_KEY_ATTR_ID, | ||
427 | NL802154_KEY_ATTR_USAGE_FRAMES, | ||
428 | NL802154_KEY_ATTR_USAGE_CMDS, | ||
429 | NL802154_KEY_ATTR_BYTES, | ||
430 | |||
431 | /* keep last */ | ||
432 | __NL802154_KEY_ATTR_AFTER_LAST, | ||
433 | NL802154_KEY_ATTR_MAX = __NL802154_KEY_ATTR_AFTER_LAST - 1 | ||
434 | }; | ||
435 | |||
436 | #define NL802154_KEY_SIZE 16 | ||
437 | #define NL802154_CMD_FRAME_NR_IDS 256 | ||
438 | |||
439 | #endif /* CONFIG_IEEE802154_NL802154_EXPERIMENTAL */ | ||
440 | |||
250 | #endif /* __NL802154_H */ | 441 | #endif /* __NL802154_H */ |
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 */ |
diff --git a/net/mac802154/cfg.c b/net/mac802154/cfg.c index c865ebb2ace2..57b5e94471af 100644 --- a/net/mac802154/cfg.c +++ b/net/mac802154/cfg.c | |||
@@ -266,6 +266,195 @@ ieee802154_set_ackreq_default(struct wpan_phy *wpan_phy, | |||
266 | return 0; | 266 | return 0; |
267 | } | 267 | } |
268 | 268 | ||
269 | #ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL | ||
270 | static void | ||
271 | ieee802154_get_llsec_table(struct wpan_phy *wpan_phy, | ||
272 | struct wpan_dev *wpan_dev, | ||
273 | struct ieee802154_llsec_table **table) | ||
274 | { | ||
275 | struct net_device *dev = wpan_dev->netdev; | ||
276 | struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev); | ||
277 | |||
278 | *table = &sdata->sec.table; | ||
279 | } | ||
280 | |||
281 | static void | ||
282 | ieee802154_lock_llsec_table(struct wpan_phy *wpan_phy, | ||
283 | struct wpan_dev *wpan_dev) | ||
284 | { | ||
285 | struct net_device *dev = wpan_dev->netdev; | ||
286 | struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev); | ||
287 | |||
288 | mutex_lock(&sdata->sec_mtx); | ||
289 | } | ||
290 | |||
291 | static void | ||
292 | ieee802154_unlock_llsec_table(struct wpan_phy *wpan_phy, | ||
293 | struct wpan_dev *wpan_dev) | ||
294 | { | ||
295 | struct net_device *dev = wpan_dev->netdev; | ||
296 | struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev); | ||
297 | |||
298 | mutex_unlock(&sdata->sec_mtx); | ||
299 | } | ||
300 | |||
301 | static int | ||
302 | ieee802154_set_llsec_params(struct wpan_phy *wpan_phy, | ||
303 | struct wpan_dev *wpan_dev, | ||
304 | const struct ieee802154_llsec_params *params, | ||
305 | int changed) | ||
306 | { | ||
307 | struct net_device *dev = wpan_dev->netdev; | ||
308 | struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev); | ||
309 | int res; | ||
310 | |||
311 | mutex_lock(&sdata->sec_mtx); | ||
312 | res = mac802154_llsec_set_params(&sdata->sec, params, changed); | ||
313 | mutex_unlock(&sdata->sec_mtx); | ||
314 | |||
315 | return res; | ||
316 | } | ||
317 | |||
318 | static int | ||
319 | ieee802154_get_llsec_params(struct wpan_phy *wpan_phy, | ||
320 | struct wpan_dev *wpan_dev, | ||
321 | struct ieee802154_llsec_params *params) | ||
322 | { | ||
323 | struct net_device *dev = wpan_dev->netdev; | ||
324 | struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev); | ||
325 | int res; | ||
326 | |||
327 | mutex_lock(&sdata->sec_mtx); | ||
328 | res = mac802154_llsec_get_params(&sdata->sec, params); | ||
329 | mutex_unlock(&sdata->sec_mtx); | ||
330 | |||
331 | return res; | ||
332 | } | ||
333 | |||
334 | static int | ||
335 | ieee802154_add_llsec_key(struct wpan_phy *wpan_phy, struct wpan_dev *wpan_dev, | ||
336 | const struct ieee802154_llsec_key_id *id, | ||
337 | const struct ieee802154_llsec_key *key) | ||
338 | { | ||
339 | struct net_device *dev = wpan_dev->netdev; | ||
340 | struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev); | ||
341 | int res; | ||
342 | |||
343 | mutex_lock(&sdata->sec_mtx); | ||
344 | res = mac802154_llsec_key_add(&sdata->sec, id, key); | ||
345 | mutex_unlock(&sdata->sec_mtx); | ||
346 | |||
347 | return res; | ||
348 | } | ||
349 | |||
350 | static int | ||
351 | ieee802154_del_llsec_key(struct wpan_phy *wpan_phy, struct wpan_dev *wpan_dev, | ||
352 | const struct ieee802154_llsec_key_id *id) | ||
353 | { | ||
354 | struct net_device *dev = wpan_dev->netdev; | ||
355 | struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev); | ||
356 | int res; | ||
357 | |||
358 | mutex_lock(&sdata->sec_mtx); | ||
359 | res = mac802154_llsec_key_del(&sdata->sec, id); | ||
360 | mutex_unlock(&sdata->sec_mtx); | ||
361 | |||
362 | return res; | ||
363 | } | ||
364 | |||
365 | static int | ||
366 | ieee802154_add_seclevel(struct wpan_phy *wpan_phy, struct wpan_dev *wpan_dev, | ||
367 | const struct ieee802154_llsec_seclevel *sl) | ||
368 | { | ||
369 | struct net_device *dev = wpan_dev->netdev; | ||
370 | struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev); | ||
371 | int res; | ||
372 | |||
373 | mutex_lock(&sdata->sec_mtx); | ||
374 | res = mac802154_llsec_seclevel_add(&sdata->sec, sl); | ||
375 | mutex_unlock(&sdata->sec_mtx); | ||
376 | |||
377 | return res; | ||
378 | } | ||
379 | |||
380 | static int | ||
381 | ieee802154_del_seclevel(struct wpan_phy *wpan_phy, struct wpan_dev *wpan_dev, | ||
382 | const struct ieee802154_llsec_seclevel *sl) | ||
383 | { | ||
384 | struct net_device *dev = wpan_dev->netdev; | ||
385 | struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev); | ||
386 | int res; | ||
387 | |||
388 | mutex_lock(&sdata->sec_mtx); | ||
389 | res = mac802154_llsec_seclevel_del(&sdata->sec, sl); | ||
390 | mutex_unlock(&sdata->sec_mtx); | ||
391 | |||
392 | return res; | ||
393 | } | ||
394 | |||
395 | static int | ||
396 | ieee802154_add_device(struct wpan_phy *wpan_phy, struct wpan_dev *wpan_dev, | ||
397 | const struct ieee802154_llsec_device *dev_desc) | ||
398 | { | ||
399 | struct net_device *dev = wpan_dev->netdev; | ||
400 | struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev); | ||
401 | int res; | ||
402 | |||
403 | mutex_lock(&sdata->sec_mtx); | ||
404 | res = mac802154_llsec_dev_add(&sdata->sec, dev_desc); | ||
405 | mutex_unlock(&sdata->sec_mtx); | ||
406 | |||
407 | return res; | ||
408 | } | ||
409 | |||
410 | static int | ||
411 | ieee802154_del_device(struct wpan_phy *wpan_phy, struct wpan_dev *wpan_dev, | ||
412 | __le64 extended_addr) | ||
413 | { | ||
414 | struct net_device *dev = wpan_dev->netdev; | ||
415 | struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev); | ||
416 | int res; | ||
417 | |||
418 | mutex_lock(&sdata->sec_mtx); | ||
419 | res = mac802154_llsec_dev_del(&sdata->sec, extended_addr); | ||
420 | mutex_unlock(&sdata->sec_mtx); | ||
421 | |||
422 | return res; | ||
423 | } | ||
424 | |||
425 | static int | ||
426 | ieee802154_add_devkey(struct wpan_phy *wpan_phy, struct wpan_dev *wpan_dev, | ||
427 | __le64 extended_addr, | ||
428 | const struct ieee802154_llsec_device_key *key) | ||
429 | { | ||
430 | struct net_device *dev = wpan_dev->netdev; | ||
431 | struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev); | ||
432 | int res; | ||
433 | |||
434 | mutex_lock(&sdata->sec_mtx); | ||
435 | res = mac802154_llsec_devkey_add(&sdata->sec, extended_addr, key); | ||
436 | mutex_unlock(&sdata->sec_mtx); | ||
437 | |||
438 | return res; | ||
439 | } | ||
440 | |||
441 | static int | ||
442 | ieee802154_del_devkey(struct wpan_phy *wpan_phy, struct wpan_dev *wpan_dev, | ||
443 | __le64 extended_addr, | ||
444 | const struct ieee802154_llsec_device_key *key) | ||
445 | { | ||
446 | struct net_device *dev = wpan_dev->netdev; | ||
447 | struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev); | ||
448 | int res; | ||
449 | |||
450 | mutex_lock(&sdata->sec_mtx); | ||
451 | res = mac802154_llsec_devkey_del(&sdata->sec, extended_addr, key); | ||
452 | mutex_unlock(&sdata->sec_mtx); | ||
453 | |||
454 | return res; | ||
455 | } | ||
456 | #endif /* CONFIG_IEEE802154_NL802154_EXPERIMENTAL */ | ||
457 | |||
269 | const struct cfg802154_ops mac802154_config_ops = { | 458 | const struct cfg802154_ops mac802154_config_ops = { |
270 | .add_virtual_intf_deprecated = ieee802154_add_iface_deprecated, | 459 | .add_virtual_intf_deprecated = ieee802154_add_iface_deprecated, |
271 | .del_virtual_intf_deprecated = ieee802154_del_iface_deprecated, | 460 | .del_virtual_intf_deprecated = ieee802154_del_iface_deprecated, |
@@ -284,4 +473,20 @@ const struct cfg802154_ops mac802154_config_ops = { | |||
284 | .set_max_frame_retries = ieee802154_set_max_frame_retries, | 473 | .set_max_frame_retries = ieee802154_set_max_frame_retries, |
285 | .set_lbt_mode = ieee802154_set_lbt_mode, | 474 | .set_lbt_mode = ieee802154_set_lbt_mode, |
286 | .set_ackreq_default = ieee802154_set_ackreq_default, | 475 | .set_ackreq_default = ieee802154_set_ackreq_default, |
476 | #ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL | ||
477 | .get_llsec_table = ieee802154_get_llsec_table, | ||
478 | .lock_llsec_table = ieee802154_lock_llsec_table, | ||
479 | .unlock_llsec_table = ieee802154_unlock_llsec_table, | ||
480 | /* TODO above */ | ||
481 | .set_llsec_params = ieee802154_set_llsec_params, | ||
482 | .get_llsec_params = ieee802154_get_llsec_params, | ||
483 | .add_llsec_key = ieee802154_add_llsec_key, | ||
484 | .del_llsec_key = ieee802154_del_llsec_key, | ||
485 | .add_seclevel = ieee802154_add_seclevel, | ||
486 | .del_seclevel = ieee802154_del_seclevel, | ||
487 | .add_device = ieee802154_add_device, | ||
488 | .del_device = ieee802154_del_device, | ||
489 | .add_devkey = ieee802154_add_devkey, | ||
490 | .del_devkey = ieee802154_del_devkey, | ||
491 | #endif /* CONFIG_IEEE802154_NL802154_EXPERIMENTAL */ | ||
287 | }; | 492 | }; |