diff options
author | Phoebe Buckheister <phoebe.buckheister@itwm.fraunhofer.de> | 2014-05-14 11:43:06 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-05-15 15:51:42 -0400 |
commit | c3a6114f31600b94ee10ebf62e4d493b401ade87 (patch) | |
tree | a854819cfede389764da13bcc0d7670e1f1e964f | |
parent | 9dbccc30f3306114e1ca4a89da69be6d5f675782 (diff) |
ieee802154: add definitions for link-layer security and header functions
When dealing with 802.15.4, one often has to know the maximum payload
size for a given packet. This depends on many factors, one of which is
whether or not a security header is present in the frame. These
definitions and functions provide an easy way for any upper layer to
calculate the maximum payload size for a packet. The first obvious user
for this is 6lowpan, which duplicates this calculation and gets it
partially wrong because it ignores security headers.
Signed-off-by: Phoebe Buckheister <phoebe.buckheister@itwm.fraunhofer.de>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | include/net/ieee802154.h | 9 | ||||
-rw-r--r-- | include/net/ieee802154_netdev.h | 29 | ||||
-rw-r--r-- | net/ieee802154/header_ops.c | 52 |
3 files changed, 83 insertions, 7 deletions
diff --git a/include/net/ieee802154.h b/include/net/ieee802154.h index c7ae0ac528dc..0aa7122e8f15 100644 --- a/include/net/ieee802154.h +++ b/include/net/ieee802154.h | |||
@@ -79,6 +79,15 @@ | |||
79 | #define IEEE802154_SCF_KEY_SHORT_INDEX 2 | 79 | #define IEEE802154_SCF_KEY_SHORT_INDEX 2 |
80 | #define IEEE802154_SCF_KEY_HW_INDEX 3 | 80 | #define IEEE802154_SCF_KEY_HW_INDEX 3 |
81 | 81 | ||
82 | #define IEEE802154_SCF_SECLEVEL_NONE 0 | ||
83 | #define IEEE802154_SCF_SECLEVEL_MIC32 1 | ||
84 | #define IEEE802154_SCF_SECLEVEL_MIC64 2 | ||
85 | #define IEEE802154_SCF_SECLEVEL_MIC128 3 | ||
86 | #define IEEE802154_SCF_SECLEVEL_ENC 4 | ||
87 | #define IEEE802154_SCF_SECLEVEL_ENC_MIC32 5 | ||
88 | #define IEEE802154_SCF_SECLEVEL_ENC_MIC64 6 | ||
89 | #define IEEE802154_SCF_SECLEVEL_ENC_MIC128 7 | ||
90 | |||
82 | /* MAC footer size */ | 91 | /* MAC footer size */ |
83 | #define IEEE802154_MFR_SIZE 2 /* 2 octets */ | 92 | #define IEEE802154_MFR_SIZE 2 /* 2 octets */ |
84 | 93 | ||
diff --git a/include/net/ieee802154_netdev.h b/include/net/ieee802154_netdev.h index 5a719ca892f4..6e4d3e1071b5 100644 --- a/include/net/ieee802154_netdev.h +++ b/include/net/ieee802154_netdev.h | |||
@@ -27,6 +27,7 @@ | |||
27 | #ifndef IEEE802154_NETDEVICE_H | 27 | #ifndef IEEE802154_NETDEVICE_H |
28 | #define IEEE802154_NETDEVICE_H | 28 | #define IEEE802154_NETDEVICE_H |
29 | 29 | ||
30 | #include <net/ieee802154.h> | ||
30 | #include <net/af_ieee802154.h> | 31 | #include <net/af_ieee802154.h> |
31 | #include <linux/netdevice.h> | 32 | #include <linux/netdevice.h> |
32 | #include <linux/skbuff.h> | 33 | #include <linux/skbuff.h> |
@@ -114,6 +115,34 @@ int ieee802154_hdr_pull(struct sk_buff *skb, struct ieee802154_hdr *hdr); | |||
114 | int ieee802154_hdr_peek_addrs(const struct sk_buff *skb, | 115 | int ieee802154_hdr_peek_addrs(const struct sk_buff *skb, |
115 | struct ieee802154_hdr *hdr); | 116 | struct ieee802154_hdr *hdr); |
116 | 117 | ||
118 | /* parses the full 802.15.4 header a given skb and stores them into hdr, | ||
119 | * performing pan id decompression and length checks to be suitable for use in | ||
120 | * header_ops.parse | ||
121 | */ | ||
122 | int ieee802154_hdr_peek(const struct sk_buff *skb, struct ieee802154_hdr *hdr); | ||
123 | |||
124 | int ieee802154_max_payload(const struct ieee802154_hdr *hdr); | ||
125 | |||
126 | static inline int | ||
127 | ieee802154_sechdr_authtag_len(const struct ieee802154_sechdr *sec) | ||
128 | { | ||
129 | switch (sec->level) { | ||
130 | case IEEE802154_SCF_SECLEVEL_MIC32: | ||
131 | case IEEE802154_SCF_SECLEVEL_ENC_MIC32: | ||
132 | return 4; | ||
133 | case IEEE802154_SCF_SECLEVEL_MIC64: | ||
134 | case IEEE802154_SCF_SECLEVEL_ENC_MIC64: | ||
135 | return 8; | ||
136 | case IEEE802154_SCF_SECLEVEL_MIC128: | ||
137 | case IEEE802154_SCF_SECLEVEL_ENC_MIC128: | ||
138 | return 16; | ||
139 | case IEEE802154_SCF_SECLEVEL_NONE: | ||
140 | case IEEE802154_SCF_SECLEVEL_ENC: | ||
141 | default: | ||
142 | return 0; | ||
143 | } | ||
144 | } | ||
145 | |||
117 | static inline int ieee802154_hdr_length(struct sk_buff *skb) | 146 | static inline int ieee802154_hdr_length(struct sk_buff *skb) |
118 | { | 147 | { |
119 | struct ieee802154_hdr hdr; | 148 | struct ieee802154_hdr hdr; |
diff --git a/net/ieee802154/header_ops.c b/net/ieee802154/header_ops.c index bed42a48408c..c09294e39ca6 100644 --- a/net/ieee802154/header_ops.c +++ b/net/ieee802154/header_ops.c | |||
@@ -195,15 +195,16 @@ ieee802154_hdr_get_sechdr(const u8 *buf, struct ieee802154_sechdr *hdr) | |||
195 | return pos; | 195 | return pos; |
196 | } | 196 | } |
197 | 197 | ||
198 | static int ieee802154_sechdr_lengths[4] = { | ||
199 | [IEEE802154_SCF_KEY_IMPLICIT] = 5, | ||
200 | [IEEE802154_SCF_KEY_INDEX] = 6, | ||
201 | [IEEE802154_SCF_KEY_SHORT_INDEX] = 10, | ||
202 | [IEEE802154_SCF_KEY_HW_INDEX] = 14, | ||
203 | }; | ||
204 | |||
198 | static int ieee802154_hdr_sechdr_len(u8 sc) | 205 | static int ieee802154_hdr_sechdr_len(u8 sc) |
199 | { | 206 | { |
200 | switch (IEEE802154_SCF_KEY_ID_MODE(sc)) { | 207 | return ieee802154_sechdr_lengths[IEEE802154_SCF_KEY_ID_MODE(sc)]; |
201 | case IEEE802154_SCF_KEY_IMPLICIT: return 5; | ||
202 | case IEEE802154_SCF_KEY_INDEX: return 6; | ||
203 | case IEEE802154_SCF_KEY_SHORT_INDEX: return 10; | ||
204 | case IEEE802154_SCF_KEY_HW_INDEX: return 14; | ||
205 | default: return -EINVAL; | ||
206 | } | ||
207 | } | 208 | } |
208 | 209 | ||
209 | static int ieee802154_hdr_minlen(const struct ieee802154_hdr *hdr) | 210 | static int ieee802154_hdr_minlen(const struct ieee802154_hdr *hdr) |
@@ -285,3 +286,40 @@ ieee802154_hdr_peek_addrs(const struct sk_buff *skb, struct ieee802154_hdr *hdr) | |||
285 | return pos; | 286 | return pos; |
286 | } | 287 | } |
287 | EXPORT_SYMBOL_GPL(ieee802154_hdr_peek_addrs); | 288 | EXPORT_SYMBOL_GPL(ieee802154_hdr_peek_addrs); |
289 | |||
290 | int | ||
291 | ieee802154_hdr_peek(const struct sk_buff *skb, struct ieee802154_hdr *hdr) | ||
292 | { | ||
293 | const u8 *buf = skb_mac_header(skb); | ||
294 | int pos; | ||
295 | |||
296 | pos = ieee802154_hdr_peek_addrs(skb, hdr); | ||
297 | if (pos < 0) | ||
298 | return -EINVAL; | ||
299 | |||
300 | if (hdr->fc.security_enabled) { | ||
301 | u8 key_id_mode = IEEE802154_SCF_KEY_ID_MODE(*(buf + pos)); | ||
302 | int want = pos + ieee802154_sechdr_lengths[key_id_mode]; | ||
303 | |||
304 | if (buf + want > skb_tail_pointer(skb)) | ||
305 | return -EINVAL; | ||
306 | |||
307 | pos += ieee802154_hdr_get_sechdr(buf + pos, &hdr->sec); | ||
308 | } | ||
309 | |||
310 | return pos; | ||
311 | } | ||
312 | EXPORT_SYMBOL_GPL(ieee802154_hdr_peek); | ||
313 | |||
314 | int ieee802154_max_payload(const struct ieee802154_hdr *hdr) | ||
315 | { | ||
316 | int hlen = ieee802154_hdr_minlen(hdr); | ||
317 | |||
318 | if (hdr->fc.security_enabled) { | ||
319 | hlen += ieee802154_sechdr_lengths[hdr->sec.key_id_mode] - 1; | ||
320 | hlen += ieee802154_sechdr_authtag_len(&hdr->sec); | ||
321 | } | ||
322 | |||
323 | return IEEE802154_MTU - hlen - IEEE802154_MFR_SIZE; | ||
324 | } | ||
325 | EXPORT_SYMBOL_GPL(ieee802154_max_payload); | ||