[Listener] Improve radiotap parsing

Get rid of the useless parsing loop; make clear we only want to extract
the signal strength and work only for that.
This commit is contained in:
Matteo Cypriani 2013-05-16 13:52:57 -04:00
parent 7a5ed8ec51
commit b3f688b2cf
3 changed files with 53 additions and 69 deletions

View File

@ -180,10 +180,6 @@ Work to do in OwlPS
http://www.unixgarden.com/index.php/programmation/introduction-a-la-programmation-wifi-en-c-sous-netbsd
- Use the "official" radiotap parser?
http://git.sipsolutions.net/?p=radiotap.git (Expat license)

View File

@ -178,6 +178,12 @@ enum {MODE_ACTIVE = 'a', MODE_PASSIVE = 'p', MODE_MIXED = 'm'} ;
#define RTAP_L_FHSSHOPPATTERN 1 // FHSS hop pattern
#define RTAP_L_ANTENNASIGNAL 1 // Signal power at the antenna (dBm)
/*
* Tests if a bit (field) is present in the present flags field.
*/
#define FIELD_PRESENT(PRESENT_FLAGS, BIT) \
(((PRESENT_FLAGS) >> (BIT)) & 1)
/*
* 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
@ -212,9 +218,8 @@ void extract_calibration_data(const u_char *pkt_data,
owl_captured_request *request) ;
void extract_packet_numbers(const u_char *pkt_data,
owl_captured_request *request) ;
void extract_radiotap_data(const u_char *pkt_data,
owl_captured_request *request,
bool rtap_fields[RTAP_ANTENNASIGNAL + 1]) ;
bool extract_radiotap_ss(const u_char *pkt_data,
owl_captured_request *request) ;
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) ;

View File

@ -977,7 +977,7 @@ void read_packet(const struct pcap_pkthdr *pkt_header,
owl_captured_request request ; // Message to send to the aggregator
uint16_t rtap_bytes ; // Radiotap header size
uint_fast16_t offset ; // Offset to read the packet
bool rtap_fields[RTAP_ANTENNASIGNAL + 1] ; // Present flags
bool antenna_signal_present ; // Is the antenna signal field present?
uint8_t raw_packet_fc1 ; // First byte of the received frame's FC
uint8_t raw_packet_fc2 ; // Second byte of the received frame's FC
// Size of the IEEE 802.11 header:
@ -1168,7 +1168,7 @@ void read_packet(const struct pcap_pkthdr *pkt_header,
return ;
/* Radiotap header handling */
extract_radiotap_data(pkt_data, &request, rtap_fields) ;
antenna_signal_present = extract_radiotap_ss(pkt_data, &request) ;
/* Display the packet details */
if (VERBOSE_DISPLAY_CAPTURED)
@ -1215,7 +1215,7 @@ void read_packet(const struct pcap_pkthdr *pkt_header,
mobile_ip_str,
request_time_str,
capture_time_str,
rtap_fields[RTAP_ANTENNASIGNAL] ? request.ss_dbm : 0,
antenna_signal_present ? request.ss_dbm : 0,
owl_ntohf(request.x_position),
owl_ntohf(request.y_position),
owl_ntohf(request.z_position),
@ -1279,17 +1279,16 @@ void extract_packet_numbers(const u_char *pkt_data,
/*
* Fills 'request' with the required data extracted from the Radiotap
* header of 'pkt_data'. The elements of 'rtap_fields' are set to
* true when the corresponding Radiotap flag is found in the packet.
* Fills 'request' with the signal strength extracted from the radiotap
* header of 'pkt_data'.
* Returns true if the antenna signal radiotap field was found, false
* otherwhise.
*/
void extract_radiotap_data(const u_char *pkt_data,
owl_captured_request *request,
bool rtap_fields[RTAP_ANTENNASIGNAL + 1])
bool extract_radiotap_ss(const u_char *pkt_data,
owl_captured_request *request)
{
uint32_t rtap_presentflags ;
uint_fast16_t rtap_position ;
int i ; // Iterator
// Get rtap flags:
memcpy(&rtap_presentflags,
@ -1297,64 +1296,48 @@ void extract_radiotap_data(const u_char *pkt_data,
// The Radiotap header is little-endian
rtap_presentflags = le32toh(rtap_presentflags) ;
// Initialise the present flags array
for (i = 0 ; i <= RTAP_ANTENNASIGNAL ; ++i)
rtap_fields[i] = false ;
rtap_position = 8 ; // Begining of the present flags determined fields
// The fields dependent on present flags start at byte 8
rtap_position = 8 ;
// Test the first bits of the flag field in order to check their
// presence, up to the antenna signal field which is the only one
// we need:
for (i = 0 ; i <= RTAP_ANTENNASIGNAL ; ++i)
if (FIELD_PRESENT(rtap_presentflags, RTAP_TSFT))
rtap_position += SKIP_FIELD(rtap_position, RTAP_L_TSFT) ;
if (FIELD_PRESENT(rtap_presentflags, RTAP_FLAGS))
rtap_position += SKIP_FIELD(rtap_position, RTAP_L_FLAGS) ;
if (FIELD_PRESENT(rtap_presentflags, RTAP_RATE))
rtap_position += SKIP_FIELD(rtap_position, RTAP_L_RATE) ;
if (FIELD_PRESENT(rtap_presentflags, RTAP_CHANNEL))
{
if ((rtap_presentflags % 2) == 1)
{
switch(i)
{
case RTAP_TSFT:
rtap_fields[RTAP_TSFT] = true ;
rtap_position += SKIP_FIELD(rtap_position, RTAP_L_TSFT) ;
break ;
case RTAP_FLAGS:
rtap_fields[RTAP_FLAGS] = true;
rtap_position += SKIP_FIELD(rtap_position, RTAP_L_FLAGS) ;
break ;
case RTAP_RATE:
rtap_fields[RTAP_RATE] = true;
rtap_position += SKIP_FIELD(rtap_position, RTAP_L_RATE) ;
break ;
case RTAP_CHANNEL:
rtap_fields[RTAP_CHANNEL] = true ;
// 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_CHANNELFLAGS) ;
break ;
case RTAP_FHSS:
rtap_fields[RTAP_FHSS] = true;
rtap_position += SKIP_FIELD(rtap_position,
RTAP_L_FHSSHOPSET) ;
rtap_position += SKIP_FIELD(rtap_position,
RTAP_L_FHSSHOPPATTERN) ;
break ;
case RTAP_ANTENNASIGNAL:
rtap_fields[RTAP_ANTENNASIGNAL] = true ;
rtap_position += nat_align(rtap_position,
RTAP_L_ANTENNASIGNAL) ;
memcpy(&request->ss_dbm,
&pkt_data[rtap_position], RTAP_L_ANTENNASIGNAL) ;
if (VERBOSE_INFO)
printf("Antenna signal: %"PRId8" dBm\n", request->ss_dbm) ;
rtap_position += RTAP_L_ANTENNASIGNAL ;
break ;
default:
fprintf(stderr, "Warning! Radiotap field not handled: bit"
" %d. This should be investigated.", i) ;
}
}
rtap_presentflags /= 2 ;
// 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_CHANNELFLAGS) ;
}
if (FIELD_PRESENT(rtap_presentflags, RTAP_FHSS))
{
rtap_position += SKIP_FIELD(rtap_position, RTAP_L_FHSSHOPSET) ;
rtap_position += SKIP_FIELD(rtap_position, RTAP_L_FHSSHOPPATTERN) ;
}
if (FIELD_PRESENT(rtap_presentflags, RTAP_ANTENNASIGNAL))
{
rtap_position += nat_align(rtap_position, RTAP_L_ANTENNASIGNAL) ;
memcpy(&request->ss_dbm, &pkt_data[rtap_position],
RTAP_L_ANTENNASIGNAL) ;
if (VERBOSE_INFO)
printf("Antenna signal: %"PRId8" dBm\n", request->ss_dbm) ;
return true ;
}
// Antenna signal not extracted
return false ;
}