From b22f93203c225527ccfa78ca15b8b78d987de5f8 Mon Sep 17 00:00:00 2001 From: Denis Kenzior Date: Wed, 17 Dec 2014 17:44:44 -0600 Subject: [PATCH] mpdu: Rework to a zero-copy based framework --- src/mpdu.c | 159 +++++++++++++++++------------------------------------ src/mpdu.h | 63 +++++++++++++++------ 2 files changed, 96 insertions(+), 126 deletions(-) diff --git a/src/mpdu.c b/src/mpdu.c index 392ebacf..2594390f 100644 --- a/src/mpdu.c +++ b/src/mpdu.c @@ -26,127 +26,77 @@ #include +#include "ie.h" #include "mpdu.h" -static inline unsigned char bit_field(unsigned char oct, int start, int num) +static bool validate_mgmt_header(const struct mpdu *mpdu, int len, int *offset) { - unsigned char mask = (1 << num) - 1; - - return (oct >> start) & mask; -} - -static inline bool next_byte(const unsigned char *mpdu, int len, - int *offset, unsigned char *holder) -{ - if (len == *offset) + /* Duration + Address1 + Address 2 + Address 3 + SeqCntrl */ + if (len < *offset + 22) return false; - *holder = mpdu[*offset]; - *offset = *offset + 1; + *offset += 22; + + if (!mpdu->fc.order) + return true; + + if (len < *offset + 4) + return false; + + *offset += 4; return true; } -static inline bool next_2bytes(const unsigned char *mpdu, int len, - int *offset, uint16_t *holder) +static bool validate_authentication_mgmt_mpdu(const struct mpdu *mpdu, + int len, int *offset) { - if (len < *offset + 2) + if (len < *offset + 6) return false; - *holder = L_LE16_TO_CPU(*(uint16_t *)(mpdu + *offset)); - *offset = *offset + 2; + switch (mpdu->auth.algorithm) { + case MPDU_AUTH_ALGO_OPEN_SYSTEM: + return *offset <= len; + case MPDU_AUTH_ALGO_SHARED_KEY: + if (mpdu->auth.transaction_sequence < 2 || + mpdu->auth.transaction_sequence > 3) + return *offset == len; - return true; -} - -static inline bool next_data(const unsigned char *mpdu, int len, - int *offset, unsigned char *holder, int t_len) -{ - if (len < *offset + t_len) - return false; - - memcpy(holder, mpdu + *offset, t_len); - *offset += t_len; - - return true; -} - -static bool decode_mgmt_header(const unsigned char *mpdu, int len, - int *offset, struct mpdu *out) -{ - uint16_t sequence_control; - - if (!next_2bytes(mpdu, len, offset, &out->mgmt_hdr.duration)) - return false; - - if (!next_data(mpdu, len, offset, out->mgmt_hdr.address_1, 6)) - return false; - - if (!next_data(mpdu, len, offset, out->mgmt_hdr.address_2, 6)) - return false; - - if (!next_data(mpdu, len, offset, out->mgmt_hdr.address_3, 6)) - return false; - - if (!next_2bytes(mpdu, len, offset, &sequence_control)) - return false; - - out->mgmt_hdr.fragment_number = sequence_control & 0x0f; - out->mgmt_hdr.sequence_number = sequence_control >> 4; - - if (out->fc.order) - *offset += sizeof(uint32_t); /* Skipping ht_control for now */ - - return true; -} - -static bool decode_authentication_mgmt_mpdu(const unsigned char *mpdu, - int len, int *offset, struct mpdu *out) -{ - if (!next_2bytes(mpdu, len, offset, &out->auth.algorithm)) - return false; - - if (!next_2bytes(mpdu, len, offset, &out->auth.transaction_sequence)) - return false; - - if (!next_2bytes(mpdu, len, offset, &out->auth.status)) - return false; - - if (out->auth.algorithm == MPDU_AUTH_ALGO_SK) { - if (out->auth.transaction_sequence < 2 && - out->auth.transaction_sequence > 3) - return true; - - if (!next_byte(mpdu, len, offset, - &out->auth.challenge_text_len)) + if (len < *offset + 2) return false; - if (!next_data(mpdu, len, offset, out->auth.challenge_text, - out->auth.challenge_text_len)) + *offset += 2; + + if (mpdu->auth.shared_key_23.element_id != + IE_TYPE_CHALLENGE_TEXT) return false; + + *offset += mpdu->auth.shared_key_23.challenge_text_len; + return *offset <= len; + default: + return false; } - return true; + return false; } -static bool decode_deauthentication_mgmt_mpdu(const unsigned char *mpdu, - int len, int *offset, struct mpdu *out) +static bool validate_deauthentication_mgmt_mpdu(const struct mpdu *mpdu, + int len, int *offset) { - return next_2bytes(mpdu, len, offset, &out->deauth.reason_code); + *offset += 2; + return *offset <= len; } -static bool decode_mgmt_mpdu(const unsigned char *mpdu, int len, - int *offset, struct mpdu *out) +static bool validate_mgmt_mpdu(const struct mpdu *mpdu, int len, int *offset) { - if (!decode_mgmt_header(mpdu, len, offset, out)) + if (!validate_mgmt_header(mpdu, len, offset)) return false; - switch (out->fc.subtype) { + switch (mpdu->fc.subtype) { case MPDU_MANAGEMENT_SUBTYPE_AUTHENTICATION: - return decode_authentication_mgmt_mpdu(mpdu, len, offset, out); + return validate_authentication_mgmt_mpdu(mpdu, len, offset); case MPDU_MANAGEMENT_SUBTYPE_DEAUTHENTICATION: - return decode_deauthentication_mgmt_mpdu(mpdu, len, offset, - out); + return validate_deauthentication_mgmt_mpdu(mpdu, len, offset); default: return false; } @@ -154,34 +104,23 @@ static bool decode_mgmt_mpdu(const unsigned char *mpdu, int len, return true; } -bool mpdu_decode(const unsigned char *mpdu, int len, struct mpdu *out) +bool mpdu_validate(const unsigned char *frame, int len) { + struct mpdu *mpdu; int offset; - if (!mpdu || !out) + if (!frame) return false; if (len < 2) return false; - out->fc.protocol_version = bit_field(mpdu[0], 0, 2); - out->fc.type = bit_field(mpdu[0], 2, 2); - out->fc.subtype = bit_field(mpdu[0], 4, 4); - - out->fc.to_ds = bit_field(mpdu[1], 0, 1); - out->fc.from_ds = bit_field(mpdu[1], 1, 1); - out->fc.more_fragments = bit_field(mpdu[1], 2, 1); - out->fc.retry = bit_field(mpdu[1], 3, 1); - out->fc.power_mgmt = bit_field(mpdu[1], 4, 1); - out->fc.more_data = bit_field(mpdu[1], 5, 1); - out->fc.protected_frame = bit_field(mpdu[1], 6, 1); - out->fc.order = bit_field(mpdu[1], 7, 1); - offset = 2; + mpdu = (struct mpdu *) frame; - switch (out->fc.type) { + switch (mpdu->fc.type) { case MPDU_TYPE_MANAGEMENT: - return decode_mgmt_mpdu(mpdu, len, &offset, out); + return validate_mgmt_mpdu(mpdu, len, &offset); default: return false; } diff --git a/src/mpdu.h b/src/mpdu.h index 458b3707..d6672cca 100644 --- a/src/mpdu.h +++ b/src/mpdu.h @@ -22,6 +22,8 @@ #include #include +#include +#include /* 802.11, Table 8-1 "Valid type and subtype combinations" */ enum mpdu_type { @@ -36,12 +38,13 @@ enum mpdu_management_subtype { /* 802.11, Section 8.4.1.1 Authentication Algorithm Number field */ enum mpdu_authentication_algorithm_number { - MPDU_AUTH_ALGO_OPEN = 0, - MPDU_AUTH_ALGO_SK, + MPDU_AUTH_ALGO_OPEN_SYSTEM = 0, + MPDU_AUTH_ALGO_SHARED_KEY, }; /* 802.11, Section 8.2.4.1.1, Figure 8-2 */ struct mpdu_fc { +#if defined(__LITTLE_ENDIAN_BITFIELD) uint8_t protocol_version:2; uint8_t type:2; uint8_t subtype:4; @@ -53,34 +56,62 @@ struct mpdu_fc { bool more_data:1; bool protected_frame:1; bool order:1; +#elif defined (__BIG_ENDIAN_BITFIELD) + uint8_t subtype:4; + uint8_t type:2; + uint8_t protocol_version:2; + bool order:1; + bool protected_frame:1; + bool more_data:1; + bool power_mgmt:1; + bool retry:1; + bool more_fragments:1; + bool from_ds:1; + bool to_ds:1; +#else +#error "Please fix " +#endif } __attribute__ ((packed)); /* 802.11, Section 8.3.3.1 */ struct mpdu_mgmt_header { - uint16_t duration; + __le16 duration; unsigned char address_1[6]; unsigned char address_2[6]; unsigned char address_3[6]; - uint16_t fragment_number:4; - uint16_t sequence_number:12; - uint32_t ht_control; /* ToDo? */ +#if defined(__LITTLE_ENDIAN_BITFIELD) + __le16 fragment_number:4; + __le16 sequence_number:12; +#elif defined (__BIG_ENDIAN_BITFIELD) + __le16 sequence_number:12; + __le16 fragment_number:4; +#else +#error "Please fix " +#endif + __le32 ht_control; /* ToDo? */ } __attribute__ ((packed)); /* 802.11, Section 8.3.3.11 */ struct mpdu_authentication { - uint16_t algorithm; - uint16_t transaction_sequence; - uint16_t status; - uint8_t challenge_text_len; - unsigned char challenge_text[253]; + __le16 algorithm; + __le16 transaction_sequence; + __le16 status; + + union { + struct { + uint8_t element_id; + uint8_t challenge_text_len; + unsigned char challenge_text[253]; + } __attribute__ ((packed)) shared_key_23; + }; /* ToDo: FT and SAE parts? */ -}; +} __attribute__ ((packed)); /* 802.11, Section 8.3.3.12 */ struct mpdu_deauthentication { - uint16_t reason_code; + __le16 reason_code; /* ToDo: Vendor specific IE? MME? */ -}; +} __attribute__ ((packed)); struct mpdu { struct mpdu_fc fc; @@ -89,6 +120,6 @@ struct mpdu { struct mpdu_authentication auth; struct mpdu_deauthentication deauth; }; -}; +} __attribute__ ((packed)); -bool mpdu_decode(const unsigned char *mpdu, int len, struct mpdu *out); +bool mpdu_validate(const unsigned char *mpdu, int len);