/* * This file is part of the Owl Positioning System (OwlPS). * OwlPS is a project of the University of Franche-Comte * (Université de Franche-Comté), France. * * Copyright © Université de Franche-Comté 2007-2012. * * Corresponding author: Matteo Cypriani * *********************************************************************** * * This software is governed by the CeCILL license under French law and * abiding by the rules of distribution of free software. You can use, * modify and/or redistribute the software under the terms of the CeCILL * license as circulated by CEA, CNRS and INRIA at the following URL: * http://www.cecill.info * * As a counterpart to the access to the source code and rights to copy, * modify and redistribute granted by the license, users are provided * only with a limited warranty and the software's authors, the holder * of the economic rights, and the successive licensors have only * limited liability. * * In this respect, the user's attention is drawn to the risks * associated with loading, using, modifying and/or developing or * reproducing the software by the user in light of its specific status * of free software, that may mean that it is complicated to manipulate, * and that also therefore means that it is reserved for developers and * experienced professionals having in-depth computer knowledge. Users * are therefore encouraged to load and test the software's suitability * as regards their requirements in conditions enabling the security of * their systems and/or data to be ensured and, more generally, to use * and operate it in the same conditions as regards security. * * The fact that you are presently reading this means that you have had * knowledge of the CeCILL license and that you accept its terms. * *********************************************************************** * * This is the header file of OwlPS Listener. */ #ifndef _OWLPS_LISTENER_H_ #define _OWLPS_LISTENER_H_ /* Compilation-time options: to activate, uncomment or compile with -D * option. */ //#define USE_CONFIG_FILE // Use libconfuse to read a config file //#define USE_PTHREAD // POSIX threads available? //#define ENABLE_KEEP_MONITOR // Enable the -K option (requires USE_PTHREAD) #ifdef ENABLE_KEEP_MONITOR # ifndef USE_PTHREAD # error "The option ENABLE_KEEP_MONITOR requires the option USE_PTHREAD" # endif // USE_PTHREAD #endif // ENABLE_KEEP_MONITOR #include #include #include #include #ifdef __GLIBC__ # include /* defines le*toh only in glibc >= 2.9. If we use an older * version of glibc, or another glibc-friendly libc (e.g. uClibc), we * must define them manually. */ # if __BYTE_ORDER == __LITTLE_ENDIAN # ifndef le32toh # define le32toh(x) (x) # endif // le32toh # ifndef le16toh # define le16toh(x) (x) # endif // le16toh # elif __BYTE_ORDER == __BIG_ENDIAN # ifndef le32toh # include # define le32toh(x) bswap_32(x) # endif // le32toh # ifndef le16toh # include # define le16toh(x) bswap_16(x) # endif // le16toh # else // __BYTE_ORDER # error "This program does not handle strange architectures." # endif // __BYTE_ORDER #else // __GLIBC__ # include # ifdef OpenBSD # define le32toh letoh32 # define le16toh letoh16 # endif // OpenBSD #endif // __GLIBC__ /* Arguments & program configuration */ #define OPTIONS "ADf:hH:i:I:Kl:m:n:O:p:P:qr:R:t:T:vVw:" // getopt string #define DEFAULT_CONFIG_FILE "/usr/local/etc/owlps/owlps-listener.conf" enum {MODE_ACTIVE = 'a', MODE_PASSIVE = 'p', MODE_MIXED = 'm'} ; #define DEFAULT_AUTOCALIBRATION_HELLO_DELAY 15 // seconds #define DEFAULT_AUTOCALIBRATION_DELAY 25 // milliseconds #define DEFAULT_AUTOCALIBRATION_NBPKT 20 /* Verbosity levels */ #define VERBOSE_QUIET GET_VERBOSE() == 0 #define VERBOSE_WARNING GET_VERBOSE() >= 1 #define VERBOSE_INFO GET_VERBOSE() >= 2 #define VERBOSE_CHATTERBOX GET_VERBOSE() >= 3 #define VERBOSE_DISPLAY_CAPTURED GET_VERBOSE() >= 4 /* Packet header sizes (in bytes) */ #define IEEE80211_HEADER_SIZE_DATA 24 // Header size for a Data frame #define LLC_HEADER_SIZE 8 /* IEEE 802.11 frame types */ // Beacon (TODO: convert to mask) #define RAW_PACKET_TYPE_BEACON 0x80 // Data frame #define FRAME_TYPE_DATA_MASK 0x08 #define IS_DATA_FRAME(FC1) \ (((FC1) & FRAME_TYPE_DATA_MASK) == FRAME_TYPE_DATA_MASK) // QoS Data frame #define FRAME_SUBTYPE_QOS_MASK 0x80 #define DATA_FRAME_IS_QOS(FC1) \ (((FC1) & FRAME_SUBTYPE_QOS_MASK) == FRAME_SUBTYPE_QOS_MASK) // To/From DS #define FRAME_FROM_STA_MASK 0x02 #define IS_FRAME_FROM_STA(FC2) \ (((FC2) & FRAME_FROM_STA_MASK) != FRAME_FROM_STA_MASK) /* * Test if a IEEE 802.11 frame is a retry. * Input: IEEE 802.11 header flags. * Returns 0 if the Retry bit is absent, a positive value if present. */ #define IS_RETRY(IEEE80211_FLAGS) ((IEEE80211_FLAGS) & 0x08) /* Positions of the radiotap header fixed fields (in bytes) */ #define RTAP_P_HREVISION 0 // Header revision #define RTAP_P_HPAD 1 // Header pad #define RTAP_P_HLENGTH 2 // Header length #define RTAP_P_PRESENTFLAGS 4 // Present flags /* Radiotap field lengths (in bytes) */ #define RTAP_L_HREVISION 1 // Header revision #define RTAP_L_HPAD 1 // Header pad #define RTAP_L_HLENGTH 2 // Header length #define RTAP_L_PRESENTFLAGS 4 // Present flags #define RTAP_L_MACTS 8 // MAC timestamp (Time Synchronization Function Timer) #define RTAP_L_FLAGS 1 // autre champ de flags #define RTAP_L_RATE 1 // Data rate #define RTAP_L_CHANNEL 2 // Channel frequency #define RTAP_L_CHANNELTYPE 2 // Channel type #define RTAP_L_ANTENNASIGNALDBM 1 // SSI signal (dBm) #define RTAP_L_ANTENNANOISEDBM 1 // SSI noise (dBm) #define RTAP_L_ANTENNA 1 // Antenna number #define RTAP_L_FHSS 2 // Hop set and pattern for Frequency-Hopping Spread Spectrum #define RTAP_L_LOCKQUALITY 2 // Signal quality #define RTAP_L_TXATTENUATION 2 // Transmit power from max power #define RTAP_L_TXATTENUATIONDB 2 // Idem (dB) #define RTAP_L_TXATTENUATIONDBM 1 // Idem (dBm) #define RTAP_L_ANTENNASIGNALDB 1 // SSI signal (dB) #define RTAP_L_ANTENNANOISEDB 1 // SSI noise (dB) #define RTAP_L_FCS 4 // Frame Check Sequence //#define RTAP_L_CHANNELP // Extended channel info (not implemented) //#define RTAP_L_EXT // Present flags' extension (not emplemented) /* Positions in 'Present flags' (and present fields 'check' array) */ #define RTAP_MACTS 0 #define RTAP_FLAGS 1 #define RTAP_RATE 2 #define RTAP_CHANNEL 3 // and RTAP_CHANNELTYPE #define RTAP_FHSS 4 #define RTAP_ANTENNASIGNALDBM 5 #define RTAP_ANTENNANOISEDBM 6 #define RTAP_LOCKQUALITY 7 #define RTAP_TXATTENUATION 8 #define RTAP_TXATTENUATIONDB 9 #define RTAP_TXATTENUATIONDBM 10 #define RTAP_ANTENNA 11 #define RTAP_ANTENNASIGNALDB 12 #define RTAP_ANTENNANOISEDB 13 #define RTAP_FCS 14 //#define RTAP_CHANNELP 18 //#define RTAP_EXT 31 /* Function headers */ int initialise_configuration(int argc, char **argv) ; int parse_config_file(int argc, char **argv) ; int parse_command_line(int argc, char **argv) ; int parse_main_options(int argc, char **argv) ; #ifdef USE_PTHREAD int parse_calibration_data(int argc, char **argv) ; #endif // USE_PTHREAD int check_configuration(void) ; #ifdef DEBUG void print_configuration(void) ; #endif // DEBUG #ifdef ENABLE_KEEP_MONITOR void* keep_mode_monitor(void *iface) ; int iface_mode_monitor(const char *const iface) ; #endif // ENABLE_KEEP_MONITOR int capture(void) ; void read_packet(const struct pcap_pkthdr *pkt_header, const u_char *pkt_data) ; 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, owl_bool rtap_fields[15]) ; void get_mac_addr(char *eth, uint8_t mac_bytes[ETHER_ADDR_LEN]) ; void get_ip_addr(char *eth, char *ip_bytes) ; #ifdef USE_PTHREAD void* autocalibrate(void *NULL_value) ; void* autocalibrate_hello(void *NULL_value) ; void send_autocalibration_request(void) ; uint_fast16_t make_packet(uint8_t **packet) ; #endif // USE_PTHREAD void sigint_handler(int num) ; void sigterm_handler(int num) ; void print_usage(void) ; void print_version(void) ; /* Macros to allow switching option handling with the libconfuse * structure and a home-made structure (if program is not compiled * with libconfuse support). */ /* libconfuse macros */ #ifdef USE_CONFIG_FILE #define SET_MODE(MODE) \ (cfg_setint(cfg, "mode", (MODE))) #define GET_MODE() \ (cfg_getint(cfg, "mode")) #define SET_DAEMON() \ (cfg_setbool(cfg, "daemon", cfg_true)) #define UNSET_DAEMON() \ (cfg_setbool(cfg, "daemon", cfg_false)) #define GET_DAEMON() \ (cfg_getbool(cfg, "daemon")) #define SET_AGGREGATION_IP(IP) \ (cfg_setstr(cfg, "aggregation_ip", (IP))) #define GET_AGGREGATION_IP() \ (cfg_getstr(cfg, "aggregation_ip")) #ifdef ENABLE_KEEP_MONITOR #define SET_KEEP_MONITOR() \ (cfg_setbool(cfg, "keep_monitor", cfg_true)) #define UNSET_KEEP_MONITOR() \ (cfg_setbool(cfg, "keep_monitor", cfg_false)) #define GET_KEEP_MONITOR() \ (cfg_getbool(cfg, "keep_monitor")) #endif // ENABLE_KEEP_MONITOR #define SET_AGGREGATION_PORT(PORT) \ (cfg_setint(cfg, "aggregation_port", (PORT))) #define GET_AGGREGATION_PORT() \ (cfg_getint(cfg, "aggregation_port")) #define SET_LISTENING_PORT(PORT) \ (cfg_setint(cfg, "listening_port", (PORT))) #define GET_LISTENING_PORT() \ (cfg_getint(cfg, "listening_port")) #define SET_RTAP_IFACE(IFACE) \ (cfg_setstr(cfg, "rtap_iface", (IFACE))) #define GET_RTAP_IFACE() \ (cfg_getstr(cfg, "rtap_iface")) #define SET_PCAP_FILE(PATH) \ (cfg_setstr(cfg, "pcap_file", (PATH))) #define GET_PCAP_FILE() \ (cfg_getstr(cfg, "pcap_file")) #define SET_WIFI_IFACE(IFACE) \ (cfg_setstr(cfg, "wifi_iface", (IFACE))) #define GET_WIFI_IFACE() \ (cfg_getstr(cfg, "wifi_iface")) #ifdef USE_PTHREAD #define SET_AUTOCALIBRATION() \ (cfg_setbool(cfg, "autocalibration", cfg_true)) #define UNSET_AUTOCALIBRATION() \ (cfg_setbool(cfg, "autocalibration", cfg_false)) #define GET_AUTOCALIBRATION() \ (cfg_getbool(cfg, "autocalibration")) #define SET_AUTOCALIBRATION_IP(IP) \ (cfg_setstr(cfg, "autocalibration_ip", (IP))) #define GET_AUTOCALIBRATION_IP() \ (cfg_getstr(cfg, "autocalibration_ip")) #define SET_AUTOCALIBRATION_REQUEST_PORT(PORT) \ (cfg_setint(cfg, "autocalibration_request_port", (PORT))) #define GET_AUTOCALIBRATION_REQUEST_PORT() \ (cfg_getint(cfg, "autocalibration_request_port")) #define SET_AUTOCALIBRATION_ORDER_PORT(PORT) \ (cfg_setint(cfg, "autocalibration_order_port", (PORT))) #define GET_AUTOCALIBRATION_ORDER_PORT() \ (cfg_getint(cfg, "autocalibration_order_port")) #define SET_AUTOCALIBRATION_HELLO_PORT(PORT) \ (cfg_setint(cfg, "autocalibration_hello_port", (PORT))) #define GET_AUTOCALIBRATION_HELLO_PORT() \ (cfg_getint(cfg, "autocalibration_hello_port")) #define SET_AUTOCALIBRATION_HELLO_DELAY(DELAY) \ (cfg_setint(cfg, "autocalibration_hello_delay", (DELAY))) #define GET_AUTOCALIBRATION_HELLO_DELAY() \ (cfg_getint(cfg, "autocalibration_hello_delay")) #define SET_AUTOCALIBRATION_DELAY(DELAY) \ (cfg_setint(cfg, "autocalibration_delay", (DELAY))) #define GET_AUTOCALIBRATION_DELAY() \ (cfg_getint(cfg, "autocalibration_delay")) #define SET_AUTOCALIBRATION_NBPKT(NBPKT) \ (cfg_setint(cfg, "autocalibration_nb_packets", (NBPKT))) #define GET_AUTOCALIBRATION_NBPKT() \ (cfg_getint(cfg, "autocalibration_nb_packets")) #define SET_MY_DIRECTION(DIRECTION) \ (cfg_setint(cfg, "my_direction", (DIRECTION))) #define GET_MY_DIRECTION() \ (cfg_getint(cfg, "my_direction")) #define SET_MY_POSITION_X(POSITION) \ (cfg_setfloat(cfg, "my_position_x", (POSITION))) #define GET_MY_POSITION_X() \ (cfg_getfloat(cfg, "my_position_x")) #define SET_MY_POSITION_Y(POSITION) \ (cfg_setfloat(cfg, "my_position_y", (POSITION))) #define GET_MY_POSITION_Y() \ (cfg_getfloat(cfg, "my_position_y")) #define SET_MY_POSITION_Z(POSITION) \ (cfg_setfloat(cfg, "my_position_z", (POSITION))) #define GET_MY_POSITION_Z() \ (cfg_getfloat(cfg, "my_position_z")) #endif // USE_PTHREAD #define INCREMENT_VERBOSE() \ (cfg_setint(cfg, "verbose", cfg_getint(cfg, "verbose") + 1)) #define RESET_VERBOSE() \ (cfg_setint(cfg, "verbose", 0)) #define GET_VERBOSE() \ (cfg_getint(cfg, "verbose")) /* Home-made structure macros */ #else // USE_CONFIG_FILE #define SET_DAEMON() \ (options.daemon = owl_true) #define UNSET_DAEMON() \ (options.daemon = owl_false) #define GET_DAEMON() \ (options.daemon) #define SET_MODE(MODE) \ (options.mode = (MODE)) #define GET_MODE() \ (options.mode) #define SET_AGGREGATION_IP(IP) \ (strncpy(options.aggregation_ip, (IP), INET_ADDRSTRLEN)) #define GET_AGGREGATION_IP() \ (options.aggregation_ip) #ifdef ENABLE_KEEP_MONITOR #define SET_KEEP_MONITOR() \ (options.keep_monitor = owl_true) #define UNSET_KEEP_MONITOR() \ (options.keep_monitor = owl_false) #define GET_KEEP_MONITOR() \ (options.keep_monitor) #endif // ENABLE_KEEP_MONITOR #define SET_AGGREGATION_PORT(PORT) \ (options.aggregation_port = (PORT)) #define GET_AGGREGATION_PORT() \ (options.aggregation_port) #define SET_LISTENING_PORT(PORT) \ (options.listening_port = (PORT)) #define GET_LISTENING_PORT() \ (options.listening_port) #define SET_RTAP_IFACE(IFACE) \ (strncpy(options.rtap_iface, (IFACE), IFNAMSIZ+1)) #define GET_RTAP_IFACE() \ (options.rtap_iface) #define SET_PCAP_FILE(PATH) \ do { \ char *path = (PATH) ; \ size_t path_len = strlen(path) ; \ free(options.pcap_file) ; \ options.pcap_file = malloc(path_len + 1) ; \ assert(options.pcap_file) ; \ strncpy(options.pcap_file, path, path_len) ; \ } while (0) #define GET_PCAP_FILE() \ (options.pcap_file) #define SET_WIFI_IFACE(IFACE) \ (strncpy(options.wifi_iface, (IFACE), IFNAMSIZ+1)) #define GET_WIFI_IFACE() \ (options.wifi_iface) #ifdef USE_PTHREAD #define SET_AUTOCALIBRATION() \ (options.autocalibration = owl_true) #define UNSET_AUTOCALIBRATION() \ (options.autocalibration = owl_false) #define GET_AUTOCALIBRATION() \ (options.autocalibration) #define SET_AUTOCALIBRATION_IP(IP) \ (strncpy(options.autocalibration_ip, (IP), INET_ADDRSTRLEN)) #define GET_AUTOCALIBRATION_IP() \ (options.autocalibration_ip) #define SET_AUTOCALIBRATION_REQUEST_PORT(PORT) \ (options.autocalibration_request_port = (PORT)) #define GET_AUTOCALIBRATION_REQUEST_PORT() \ (options.autocalibration_request_port) #define SET_AUTOCALIBRATION_ORDER_PORT(PORT) \ (options.autocalibration_order_port = (PORT)) #define GET_AUTOCALIBRATION_ORDER_PORT() \ (options.autocalibration_order_port) #define SET_AUTOCALIBRATION_HELLO_PORT(PORT) \ (options.autocalibration_hello_port = (PORT)) #define GET_AUTOCALIBRATION_HELLO_PORT() \ (options.autocalibration_hello_port) #define SET_AUTOCALIBRATION_HELLO_DELAY(DELAY) \ (options.autocalibration_hello_delay = (DELAY)) #define GET_AUTOCALIBRATION_HELLO_DELAY() \ (options.autocalibration_hello_delay) #define SET_AUTOCALIBRATION_DELAY(DELAY) \ (options.autocalibration_delay = (DELAY)) #define GET_AUTOCALIBRATION_DELAY() \ (options.autocalibration_delay) #define SET_AUTOCALIBRATION_NBPKT(NBPKT) \ (options.autocalibration_nb_packets = (NBPKT)) #define GET_AUTOCALIBRATION_NBPKT() \ (options.autocalibration_nb_packets) #define SET_MY_DIRECTION(DIRECTION) \ (options.my_direction = (DIRECTION)) #define GET_MY_DIRECTION() \ (options.my_direction) #define SET_MY_POSITION_X(POSITION) \ (options.my_position_x = (POSITION)) #define GET_MY_POSITION_X() \ (options.my_position_x) #define SET_MY_POSITION_Y(POSITION) \ (options.my_position_y = (POSITION)) #define GET_MY_POSITION_Y() \ (options.my_position_y) #define SET_MY_POSITION_Z(POSITION) \ (options.my_position_z = (POSITION)) #define GET_MY_POSITION_Z() \ (options.my_position_z) #endif // USE_PTHREAD #define INCREMENT_VERBOSE() \ (++options.verbose) #define RESET_VERBOSE() \ (options.verbose = 0) #define GET_VERBOSE() \ (options.verbose) #endif // USE_CONFIG_FILE /* Returns true if we are capturing packet from a network interface, or * false if we are reading from a pcap file. */ #define LIVE_CAPTURING \ (! GET_PCAP_FILE()) #endif // _OWLPS_LISTENER_H_