aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPhoebe Buckheister <phoebe.buckheister@itwm.fraunhofer.de>2014-05-14 11:43:06 -0400
committerDavid S. Miller <davem@davemloft.net>2014-05-15 15:51:42 -0400
commitc3a6114f31600b94ee10ebf62e4d493b401ade87 (patch)
treea854819cfede389764da13bcc0d7670e1f1e964f
parent9dbccc30f3306114e1ca4a89da69be6d5f675782 (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.h9
-rw-r--r--include/net/ieee802154_netdev.h29
-rw-r--r--net/ieee802154/header_ops.c52
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);
114int ieee802154_hdr_peek_addrs(const struct sk_buff *skb, 115int 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 */
122int ieee802154_hdr_peek(const struct sk_buff *skb, struct ieee802154_hdr *hdr);
123
124int ieee802154_max_payload(const struct ieee802154_hdr *hdr);
125
126static inline int
127ieee802154_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
117static inline int ieee802154_hdr_length(struct sk_buff *skb) 146static 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
198static 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
198static int ieee802154_hdr_sechdr_len(u8 sc) 205static 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
209static int ieee802154_hdr_minlen(const struct ieee802154_hdr *hdr) 210static 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}
287EXPORT_SYMBOL_GPL(ieee802154_hdr_peek_addrs); 288EXPORT_SYMBOL_GPL(ieee802154_hdr_peek_addrs);
289
290int
291ieee802154_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}
312EXPORT_SYMBOL_GPL(ieee802154_hdr_peek);
313
314int 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}
325EXPORT_SYMBOL_GPL(ieee802154_max_payload);