From 94b4f6c21cf54029377a0645675a9d81b6cf890d Mon Sep 17 00:00:00 2001 From: Phoebe Buckheister Date: Fri, 14 Mar 2014 21:24:00 +0100 Subject: ieee802154: add header structs with endiannes and operations This patch provides a set of structures to represent 802.15.4 MAC headers, and a set of operations to push/pull/peek these structs from skbs. We cannot simply pointer-cast the skb MAC header pointer to these structs, because 802.15.4 headers are wildly variable - depending on the first three bytes, virtually all other fields of the header may be present or not, and be present with different lengths. The new header creation/parsing routines also support 802.15.4 security headers, which are currently not supported by the mac802154 implementation of the protocol. Signed-off-by: Phoebe Buckheister Signed-off-by: David S. Miller --- include/net/ieee802154_netdev.h | 87 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) (limited to 'include/net/ieee802154_netdev.h') diff --git a/include/net/ieee802154_netdev.h b/include/net/ieee802154_netdev.h index e4810d566b1b..c3fc33a78920 100644 --- a/include/net/ieee802154_netdev.h +++ b/include/net/ieee802154_netdev.h @@ -28,6 +28,28 @@ #define IEEE802154_NETDEVICE_H #include +#include +#include + +struct ieee802154_sechdr { +#if defined(__LITTLE_ENDIAN_BITFIELD) + u8 level:3, + key_id_mode:2, + reserved:3; +#elif defined(__BIG_ENDIAN_BITFIELD) + u8 reserved:3, + key_id_mode:2, + level:3; +#else +#error "Please fix " +#endif + u8 key_id; + __le32 frame_counter; + union { + __le32 short_src; + __le64 extended_src; + }; +}; struct ieee802154_addr { u8 mode; @@ -38,6 +60,71 @@ struct ieee802154_addr { }; }; +struct ieee802154_hdr_fc { +#if defined(__LITTLE_ENDIAN_BITFIELD) + u16 type:3, + security_enabled:1, + frame_pending:1, + ack_request:1, + intra_pan:1, + reserved:3, + dest_addr_mode:2, + version:2, + source_addr_mode:2; +#elif defined(__BIG_ENDIAN_BITFIELD) + u16 reserved:1, + intra_pan:1, + ack_request:1, + frame_pending:1, + security_enabled:1, + type:3, + source_addr_mode:2, + version:2, + dest_addr_mode:2, + reserved2:2; +#else +#error "Please fix " +#endif +}; + +struct ieee802154_hdr { + struct ieee802154_hdr_fc fc; + u8 seq; + struct ieee802154_addr source; + struct ieee802154_addr dest; + struct ieee802154_sechdr sec; +}; + +/* pushes hdr onto the skb. fields of hdr->fc that can be calculated from + * the contents of hdr will be, and the actual value of those bits in + * hdr->fc will be ignored. this includes the INTRA_PAN bit and the frame + * version, if SECEN is set. + */ +int ieee802154_hdr_push(struct sk_buff *skb, const struct ieee802154_hdr *hdr); + +/* pulls the entire 802.15.4 header off of the skb, including the security + * header, and performs pan id decompression + */ +int ieee802154_hdr_pull(struct sk_buff *skb, struct ieee802154_hdr *hdr); + +/* parses the frame control, sequence number of address fields in 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_addrs(const struct sk_buff *skb, + struct ieee802154_hdr *hdr); + +static inline int ieee802154_hdr_length(struct sk_buff *skb) +{ + struct ieee802154_hdr hdr; + int len = ieee802154_hdr_pull(skb, &hdr); + + if (len > 0) + skb_push(skb, len); + + return len; +} + static inline bool ieee802154_addr_equal(const struct ieee802154_addr *a1, const struct ieee802154_addr *a2) { -- cgit v1.2.3