From a046dcd3fbbe7c3ce4e983aa07aa9986fcc7f8b5 Mon Sep 17 00:00:00 2001 From: Matteo Cypriani Date: Tue, 23 Apr 2013 18:50:41 -0400 Subject: [PATCH] [Listener] Fix radiotap alignment bug The fields in the radiotap header are naturally aligned, which was not taken into account by the parser. --- owlps-listener/owlps-listener.h | 11 ++++++ owlps-listener/owlps-listenerd.c | 61 ++++++++++++++++++++++++-------- 2 files changed, 57 insertions(+), 15 deletions(-) diff --git a/owlps-listener/owlps-listener.h b/owlps-listener/owlps-listener.h index a9c1370..ebc245e 100644 --- a/owlps-listener/owlps-listener.h +++ b/owlps-listener/owlps-listener.h @@ -198,6 +198,16 @@ enum {MODE_ACTIVE = 'a', MODE_PASSIVE = 'p', MODE_MIXED = 'm'} ; //#define RTAP_EXT 31 +/* + * Returns the number of bytes needed to jump after a (radiotap) field of + * length 'FIELD_LEN' that should sit at the position 'OFFSET' in the + * buffer, taking into account alignment considerations. + */ +#define SKIP_FIELD(OFFSET, FIELD_LEN) \ + ((FIELD_LEN) + nat_align((OFFSET), (FIELD_LEN))) + + + /* Function headers */ int initialise_configuration(int argc, char **argv) ; int parse_config_file(int argc, char **argv) ; @@ -225,6 +235,7 @@ void extract_packet_numbers(const u_char *pkt_data, void extract_radiotap_data(const u_char *pkt_data, owl_captured_request *request, owl_bool rtap_fields[15]) ; +uint_fast16_t nat_align(uint_fast16_t offset, uint_fast8_t field_len) ; void get_mac_addr(char *eth, uint8_t mac_bytes[ETHER_ADDR_LEN]) ; void get_ip_addr(char *eth, char *ip_bytes) ; diff --git a/owlps-listener/owlps-listenerd.c b/owlps-listener/owlps-listenerd.c index dfa85ad..43f31ae 100644 --- a/owlps-listener/owlps-listenerd.c +++ b/owlps-listener/owlps-listenerd.c @@ -1311,27 +1311,32 @@ void extract_radiotap_data(const u_char *pkt_data, { case RTAP_MACTS: rtap_fields[RTAP_MACTS] = owl_true ; - rtap_position += RTAP_L_MACTS ; + rtap_position += SKIP_FIELD(rtap_position, RTAP_L_MACTS) ; break ; case RTAP_FLAGS: rtap_fields[RTAP_FLAGS] = owl_true; - rtap_position += RTAP_L_FLAGS ; + rtap_position += SKIP_FIELD(rtap_position, RTAP_L_FLAGS) ; break ; case RTAP_RATE: rtap_fields[RTAP_RATE] = owl_true; - rtap_position += RTAP_L_RATE ; + rtap_position += SKIP_FIELD(rtap_position, RTAP_L_RATE) ; break ; case RTAP_CHANNEL: rtap_fields[RTAP_CHANNEL] = owl_true ; - rtap_position += RTAP_L_CHANNEL ; - rtap_position += RTAP_L_CHANNELTYPE ; + // The channel field is actually two fields that must be + // aligned independently + rtap_position += SKIP_FIELD(rtap_position, RTAP_L_CHANNEL) ; + rtap_position += SKIP_FIELD(rtap_position, + RTAP_L_CHANNELTYPE) ; break ; case RTAP_FHSS: rtap_fields[RTAP_FHSS] = owl_true; - rtap_position += RTAP_L_FHSS ; + rtap_position += SKIP_FIELD(rtap_position, RTAP_L_FHSS) ; break ; case RTAP_ANTENNASIGNALDBM: rtap_fields[RTAP_ANTENNASIGNALDBM] = owl_true ; + rtap_position += nat_align(rtap_position, + RTAP_L_ANTENNASIGNALDBM) ; memcpy(&request->ss_dbm, &pkt_data[rtap_position], RTAP_L_ANTENNASIGNALDBM) ; if (VERBOSE_INFO) @@ -1341,39 +1346,46 @@ void extract_radiotap_data(const u_char *pkt_data, break ; case RTAP_ANTENNANOISEDBM: rtap_fields[RTAP_ANTENNANOISEDBM] = owl_true; - rtap_position += RTAP_L_ANTENNANOISEDBM ; + rtap_position += SKIP_FIELD(rtap_position, + RTAP_L_ANTENNANOISEDBM) ; break ; case RTAP_LOCKQUALITY: rtap_fields[RTAP_LOCKQUALITY] = owl_true; - rtap_position += RTAP_L_LOCKQUALITY ; + rtap_position += SKIP_FIELD(rtap_position, + RTAP_L_LOCKQUALITY) ; break ; case RTAP_TXATTENUATION: rtap_fields[RTAP_TXATTENUATION] = owl_true; - rtap_position += RTAP_L_TXATTENUATION ; + rtap_position += SKIP_FIELD(rtap_position, + RTAP_L_TXATTENUATION) ; break ; case RTAP_TXATTENUATIONDB: rtap_fields[RTAP_TXATTENUATIONDB] = owl_true; - rtap_position += RTAP_L_TXATTENUATIONDB ; + rtap_position += SKIP_FIELD(rtap_position, + RTAP_L_TXATTENUATIONDB) ; break ; case RTAP_TXATTENUATIONDBM: rtap_fields[RTAP_TXATTENUATIONDBM] = owl_true; - rtap_position += RTAP_L_TXATTENUATIONDBM ; + rtap_position += SKIP_FIELD(rtap_position, + RTAP_L_TXATTENUATIONDBM) ; break ; case RTAP_ANTENNA: rtap_fields[RTAP_ANTENNA] = owl_true; - rtap_position += RTAP_L_ANTENNA ; + rtap_position += SKIP_FIELD(rtap_position, RTAP_L_ANTENNA) ; break ; case RTAP_ANTENNASIGNALDB: rtap_fields[RTAP_ANTENNASIGNALDB] = owl_true; - rtap_position += RTAP_L_ANTENNASIGNALDB ; + rtap_position += SKIP_FIELD(rtap_position, + RTAP_L_ANTENNASIGNALDB) ; break ; case RTAP_ANTENNANOISEDB: rtap_fields[RTAP_ANTENNANOISEDB] = owl_true; - rtap_position += RTAP_L_ANTENNANOISEDB ; + rtap_position += SKIP_FIELD(rtap_position, + RTAP_L_ANTENNANOISEDB) ; break ; case RTAP_FCS: rtap_fields[RTAP_FCS] = owl_true; - rtap_position += RTAP_L_FCS ; + rtap_position += SKIP_FIELD(rtap_position, RTAP_L_FCS) ; break ; default: fprintf(stderr, "Warning! Radiotap field not handled: bit" @@ -1386,6 +1398,25 @@ void extract_radiotap_data(const u_char *pkt_data, +/* + * Computes the number of padding bytes required to achieve natural + * alignment of a field of length 'field_len', given the position + * 'offset' it should normally be at in the buffer. The aligned + * position is the sum of 'offset' and the returned value. + * + * To advance to the next available position, you can also use the macro + * SKIP_FIELD(), which is a simple wrapper around this function. + */ +uint_fast16_t nat_align(uint_fast16_t offset, uint_fast8_t field_len) +{ + uint_fast8_t alignment = offset % field_len ; + if (alignment == 0) + return 0 ; + return field_len - alignment ; +} + + + /* * Get our own MAC address and copy it to 'mac_bytes'. */