/* * This file is part of the Owl Positioning System (OwlPS) project. * It is subject to the copyright notice and license terms in the * COPYRIGHT.t2t file found in the top-level directory of this * distribution and at * https://code.lm7.fr/mcy/owlps/src/master/COPYRIGHT.t2t * No part of the OwlPS Project, including this file, may be copied, * modified, propagated, or distributed except according to the terms * contained in the COPYRIGHT.t2t file; the COPYRIGHT.t2t file must be * distributed along with this file, either separately or by replacing * this notice by the COPYRIGHT.t2t file's contents. * *********************************************************************** * * This is the header file of OwlPS Listener. */ #ifndef _OWLPS_LISTENER_H_ #define _OWLPS_LISTENER_H_ #include #include #ifdef OWLPS_LISTENER_KEEPS_MONITOR # ifndef OWLPS_LISTENER_USES_PTHREAD # error "The option OWLPS_LISTENER_KEEPS_MONITOR requires the option OWLPS_LISTENER_USES_PTHREAD" # endif // OWLPS_LISTENER_USES_PTHREAD #endif // OWLPS_LISTENER_KEEPS_MONITOR #include #include #include #include #include #include // for MAXHOSTNAMELEN #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 /* Non-glibc systems (mostly BSDs at this point). * - OpenBSD 5.6 and higher defines le*toh in . Former versions * defined letoh* in . * - NetBSD, FreeBSD and DragonFly define le*toh in . */ #else // __GLIBC__ # if defined(OpenBSD) # if OpenBSD < 201411 // OpenBSD < 5.6 # include # define le32toh letoh32 # define le16toh letoh16 # else // OpenBSD < 5.6 # include # endif // OpenBSD < 5.6 # else // OpenBSD # include # endif // OpenBSD #endif // __GLIBC__ /* Arguments & program configuration */ #define OPTIONS "ADf:GhH:i:I:Kl:m:n:O:p:P:qr:R:t:T:vVw:" // getopt string #define DEFAULT_CONFIG_FILE OWL_CONFIG_PREFIX "/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 #define DEFAULT_AGGREGATION_HOST "localhost" /* 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 #define MAX_VERBOSE_LEVEL 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 /* Lengths of the radiotap fixed fields (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 /* Bits of the radiotap "Present flags" field */ #define RTAP_TSFT 0 #define RTAP_FLAGS 1 #define RTAP_RATE 2 #define RTAP_CHANNEL 3 // Channel frequency and flags #define RTAP_FHSS 4 // FHSS hop set and hop pattern #define RTAP_ANTENNASIGNAL 5 /* We use only the first Antenna Signal field, so we don't need to handle * the bits greater than RTAP_ANTENNASIGNAL, except for the Ext bit * (Extended Presence), to be able to jump after all the Present Flags * fields: */ #define RTAP_EXT 31 /* Lengths of the radiotap optional fields (in bytes) */ #define RTAP_L_TSFT 8 // MAC timestamp (Time Synchronization Function Timer) #define RTAP_L_FLAGS 1 // Flags #define RTAP_L_RATE 1 // Data rate #define RTAP_L_CHANNEL 2 // Channel frequency #define RTAP_L_CHANNELFLAGS 2 // Channel flags (channel type) #define RTAP_L_FHSSHOPSET 1 // FHSS hop set #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 * buffer, taking into account alignment considerations. * Warning: do *not* pass an incremented number as FIELD_LEN (e.g. * field_len++ or ++field_len). This shouldn't normally be useful anyway. */ #define SKIP_FIELD(OFFSET, FIELD_LEN) \ ((FIELD_LEN) + nat_align((OFFSET), (FIELD_LEN))) /* Function headers */ int initialise_configuration(const int argc, char *const *argv) ; int parse_config_file(const int argc, char *const *argv) ; int parse_command_line(const int argc, char *const *argv) ; int parse_main_options(const int argc, char *const *argv) ; #ifdef OWLPS_LISTENER_USES_PTHREAD int parse_calibration_data(const int argc, char *const *argv) ; #endif // OWLPS_LISTENER_USES_PTHREAD int check_configuration(void) ; void print_configuration(FILE *const stream) ; #ifdef OWLPS_LISTENER_KEEPS_MONITOR void* keep_mode_monitor(void *const iface) ; int iface_mode_monitor(const char *const iface) ; #endif // OWLPS_LISTENER_KEEPS_MONITOR int capture(void) ; void read_packet(const struct pcap_pkthdr *const pkt_header, const u_char *const pkt_data) ; void extract_calibration_data(const u_char *const pkt_data, owl_captured_request *const request) ; void extract_packet_numbers(const u_char *const pkt_data, owl_captured_request *const request) ; bool extract_radiotap_ss(const u_char *const pkt_data, owl_captured_request *const request) ; uint_fast16_t nat_align(const uint_fast16_t offset, const uint_fast8_t field_len) ; void display_captured_request(const owl_captured_request *const request, const struct pcap_pkthdr *const pkt_header) ; void get_mac_addr(const char *const iface, uint8_t mac_bytes[ETHER_ADDR_LEN]) ; void get_ip_addr(const char *const iface, char ip[INET_ADDRSTRLEN]) ; #ifdef OWLPS_LISTENER_USES_PTHREAD void* autocalibrate_hello(void *const NULL_value) ; void* autocalibrate(void *const NULL_value) ; void send_autocalibration_request(void) ; uint_fast16_t make_packet(uint8_t **const packet) ; #endif // OWLPS_LISTENER_USES_PTHREAD void sigint_handler(const int num) ; void sigterm_handler(const 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 OWLPS_LISTENER_USES_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_HOST(HOST) \ (cfg_setstr(cfg, "aggregation_host", (HOST))) #define GET_AGGREGATION_HOST() \ (cfg_getstr(cfg, "aggregation_host")) #ifdef OWLPS_LISTENER_KEEPS_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 // OWLPS_LISTENER_KEEPS_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 OWLPS_LISTENER_USES_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_HOST(HOST) \ (cfg_setstr(cfg, "autocalibration_host", (HOST))) #define GET_AUTOCALIBRATION_HOST() \ (cfg_getstr(cfg, "autocalibration_host")) #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 // OWLPS_LISTENER_USES_PTHREAD #define INCREMENT_VERBOSE() \ do { \ long vlevel = cfg_getint(cfg, "verbose") ; \ if (vlevel < MAX_VERBOSE_LEVEL) \ cfg_setint(cfg, "verbose", vlevel + 1) ; \ } while (0) #define RESET_VERBOSE() \ (cfg_setint(cfg, "verbose", 0)) #define GET_VERBOSE() \ (cfg_getint(cfg, "verbose")) /* Home-made structure macros */ #else // OWLPS_LISTENER_USES_CONFIG_FILE #define SET_DAEMON() \ (options.daemon = true) #define UNSET_DAEMON() \ (options.daemon = false) #define GET_DAEMON() \ (options.daemon) #define SET_MODE(MODE) \ (options.mode = (MODE)) #define GET_MODE() \ (options.mode) #define SET_AGGREGATION_HOST(HOST) \ (strncpy(options.aggregation_host, (HOST), MAXHOSTNAMELEN)) #define GET_AGGREGATION_HOST() \ (options.aggregation_host) #ifdef OWLPS_LISTENER_KEEPS_MONITOR #define SET_KEEP_MONITOR() \ (options.keep_monitor = true) #define UNSET_KEEP_MONITOR() \ (options.keep_monitor = false) #define GET_KEEP_MONITOR() \ (options.keep_monitor) #endif // OWLPS_LISTENER_KEEPS_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 OWLPS_LISTENER_USES_PTHREAD #define SET_AUTOCALIBRATION() \ (options.autocalibration = true) #define UNSET_AUTOCALIBRATION() \ (options.autocalibration = false) #define GET_AUTOCALIBRATION() \ (options.autocalibration) #define SET_AUTOCALIBRATION_HOST(HOST) \ (strncpy(options.autocalibration_host, (HOST), MAXHOSTNAMELEN)) #define GET_AUTOCALIBRATION_HOST() \ (options.autocalibration_host) #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 // OWLPS_LISTENER_USES_PTHREAD #define INCREMENT_VERBOSE() \ if (options.verbose < MAX_VERBOSE_LEVEL) \ ++options.verbose #define RESET_VERBOSE() \ (options.verbose = 0) #define GET_VERBOSE() \ (options.verbose) #endif // OWLPS_LISTENER_USES_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_RTAP_IFACE()[0] != '\0') #endif // _OWLPS_LISTENER_H_