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>
This commit is contained in:
parent
9dbccc30f3
commit
c3a6114f31
|
@ -79,6 +79,15 @@
|
|||
#define IEEE802154_SCF_KEY_SHORT_INDEX 2
|
||||
#define IEEE802154_SCF_KEY_HW_INDEX 3
|
||||
|
||||
#define IEEE802154_SCF_SECLEVEL_NONE 0
|
||||
#define IEEE802154_SCF_SECLEVEL_MIC32 1
|
||||
#define IEEE802154_SCF_SECLEVEL_MIC64 2
|
||||
#define IEEE802154_SCF_SECLEVEL_MIC128 3
|
||||
#define IEEE802154_SCF_SECLEVEL_ENC 4
|
||||
#define IEEE802154_SCF_SECLEVEL_ENC_MIC32 5
|
||||
#define IEEE802154_SCF_SECLEVEL_ENC_MIC64 6
|
||||
#define IEEE802154_SCF_SECLEVEL_ENC_MIC128 7
|
||||
|
||||
/* MAC footer size */
|
||||
#define IEEE802154_MFR_SIZE 2 /* 2 octets */
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#ifndef IEEE802154_NETDEVICE_H
|
||||
#define IEEE802154_NETDEVICE_H
|
||||
|
||||
#include <net/ieee802154.h>
|
||||
#include <net/af_ieee802154.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/skbuff.h>
|
||||
|
@ -114,6 +115,34 @@ int ieee802154_hdr_pull(struct sk_buff *skb, struct ieee802154_hdr *hdr);
|
|||
int ieee802154_hdr_peek_addrs(const struct sk_buff *skb,
|
||||
struct ieee802154_hdr *hdr);
|
||||
|
||||
/* parses the full 802.15.4 header a given skb and stores them into hdr,
|
||||
* performing pan id decompression and length checks to be suitable for use in
|
||||
* header_ops.parse
|
||||
*/
|
||||
int ieee802154_hdr_peek(const struct sk_buff *skb, struct ieee802154_hdr *hdr);
|
||||
|
||||
int ieee802154_max_payload(const struct ieee802154_hdr *hdr);
|
||||
|
||||
static inline int
|
||||
ieee802154_sechdr_authtag_len(const struct ieee802154_sechdr *sec)
|
||||
{
|
||||
switch (sec->level) {
|
||||
case IEEE802154_SCF_SECLEVEL_MIC32:
|
||||
case IEEE802154_SCF_SECLEVEL_ENC_MIC32:
|
||||
return 4;
|
||||
case IEEE802154_SCF_SECLEVEL_MIC64:
|
||||
case IEEE802154_SCF_SECLEVEL_ENC_MIC64:
|
||||
return 8;
|
||||
case IEEE802154_SCF_SECLEVEL_MIC128:
|
||||
case IEEE802154_SCF_SECLEVEL_ENC_MIC128:
|
||||
return 16;
|
||||
case IEEE802154_SCF_SECLEVEL_NONE:
|
||||
case IEEE802154_SCF_SECLEVEL_ENC:
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static inline int ieee802154_hdr_length(struct sk_buff *skb)
|
||||
{
|
||||
struct ieee802154_hdr hdr;
|
||||
|
|
|
@ -195,15 +195,16 @@ ieee802154_hdr_get_sechdr(const u8 *buf, struct ieee802154_sechdr *hdr)
|
|||
return pos;
|
||||
}
|
||||
|
||||
static int ieee802154_sechdr_lengths[4] = {
|
||||
[IEEE802154_SCF_KEY_IMPLICIT] = 5,
|
||||
[IEEE802154_SCF_KEY_INDEX] = 6,
|
||||
[IEEE802154_SCF_KEY_SHORT_INDEX] = 10,
|
||||
[IEEE802154_SCF_KEY_HW_INDEX] = 14,
|
||||
};
|
||||
|
||||
static int ieee802154_hdr_sechdr_len(u8 sc)
|
||||
{
|
||||
switch (IEEE802154_SCF_KEY_ID_MODE(sc)) {
|
||||
case IEEE802154_SCF_KEY_IMPLICIT: return 5;
|
||||
case IEEE802154_SCF_KEY_INDEX: return 6;
|
||||
case IEEE802154_SCF_KEY_SHORT_INDEX: return 10;
|
||||
case IEEE802154_SCF_KEY_HW_INDEX: return 14;
|
||||
default: return -EINVAL;
|
||||
}
|
||||
return ieee802154_sechdr_lengths[IEEE802154_SCF_KEY_ID_MODE(sc)];
|
||||
}
|
||||
|
||||
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)
|
|||
return pos;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ieee802154_hdr_peek_addrs);
|
||||
|
||||
int
|
||||
ieee802154_hdr_peek(const struct sk_buff *skb, struct ieee802154_hdr *hdr)
|
||||
{
|
||||
const u8 *buf = skb_mac_header(skb);
|
||||
int pos;
|
||||
|
||||
pos = ieee802154_hdr_peek_addrs(skb, hdr);
|
||||
if (pos < 0)
|
||||
return -EINVAL;
|
||||
|
||||
if (hdr->fc.security_enabled) {
|
||||
u8 key_id_mode = IEEE802154_SCF_KEY_ID_MODE(*(buf + pos));
|
||||
int want = pos + ieee802154_sechdr_lengths[key_id_mode];
|
||||
|
||||
if (buf + want > skb_tail_pointer(skb))
|
||||
return -EINVAL;
|
||||
|
||||
pos += ieee802154_hdr_get_sechdr(buf + pos, &hdr->sec);
|
||||
}
|
||||
|
||||
return pos;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ieee802154_hdr_peek);
|
||||
|
||||
int ieee802154_max_payload(const struct ieee802154_hdr *hdr)
|
||||
{
|
||||
int hlen = ieee802154_hdr_minlen(hdr);
|
||||
|
||||
if (hdr->fc.security_enabled) {
|
||||
hlen += ieee802154_sechdr_lengths[hdr->sec.key_id_mode] - 1;
|
||||
hlen += ieee802154_sechdr_authtag_len(&hdr->sec);
|
||||
}
|
||||
|
||||
return IEEE802154_MTU - hlen - IEEE802154_MFR_SIZE;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ieee802154_max_payload);
|
||||
|
|
Loading…
Reference in New Issue