/* * This file is part of the rtap localisation project. */ #include "owlps.h" #define DEBUG owl_bool run = TRUE ; /* * Converts a MAC address from bytes to string. * /!\ You *must* manually free the returned string. /!\ */ char* owl_mac_bytes_to_string(uint8_t *mac_binary) { char *ret = malloc(sizeof(char) * 18) ; sprintf(ret, "%02x:%02x:%02x:%02x:%02x:%02x", mac_binary[0], mac_binary[1], mac_binary[2], mac_binary[3], mac_binary[4], mac_binary[5]) ; ret[17] = '\0' ; return ret ; } /* * Converts a IEEE 802.11 frequency into a channel number. * Returns 0 if the frequency does not correspond to an official channel. */ uint_fast8_t owl_frequency_to_channel(uint_fast16_t channel) { uint_fast8_t c = 0 ; // Result switch (channel) { case CHANNEL_1 : c = 1 ; break ; case CHANNEL_2 : c = 2 ; break ; case CHANNEL_3 : c = 3 ; break ; case CHANNEL_4 : c = 4 ; break ; case CHANNEL_5 : c = 5 ; break ; case CHANNEL_6 : c = 6 ; break ; case CHANNEL_7 : c = 7 ; break ; case CHANNEL_8 : c = 8 ; break ; case CHANNEL_9 : c = 9 ; break ; case CHANNEL_10 : c = 10 ; break ; case CHANNEL_11 : c = 11 ; break ; case CHANNEL_12 : c = 12 ; break ; case CHANNEL_13 : c = 13 ; break ; case CHANNEL_14 : c = 14 ; break ; } return c ; } /* * Sets the owl_timestamp 'now' at the current time. * Returns 0 in case of success non-zero otherwise. */ int owl_timestamp_now(owl_timestamp *now) { int ret ; struct timespec now_ts ; if ((ret = clock_gettime(CLOCK_REALTIME, &now_ts))) { perror("Cannot get the current time") ; return ret ; } *now = owl_timespec_to_timestamp(now_ts) ; return 0 ; } /* * Returns a owl_timestamp from a struct timespec. */ owl_timestamp owl_timespec_to_timestamp(const struct timespec d) { owl_timestamp res ; res.tv_sec = d.tv_sec ; res.tv_nsec = d.tv_nsec ; return res ; } /* * Returns a owl_timestamp from a struct timeval. */ owl_timestamp owl_timeval_to_timestamp(const struct timeval d) { owl_timestamp res ; res.tv_sec = d.tv_sec ; res.tv_nsec = d.tv_usec * 1000u ; return res ; } /* * Converts a owl_timestamp date value into milliseconds. */ uint64_t owl_timestamp_to_ms(owl_timestamp d) { return (uint64_t) d.tv_sec * 1000u + (uint64_t) d.tv_nsec / 1000000lu ; } /* * Converts a owl_timestamp date value into a printable string. * 'dst' must be an allocated array of at least owl_timestamp_STR_LEN * characters. */ void owl_timestamp_to_string(char *dst, owl_timestamp src) { snprintf(dst, OWL_TIMESTAMP_STR_LEN, "%"PRIu32".%"PRIu32, src.tv_sec, src.tv_nsec) ; } /* * Returns the time (in milliseconds) between two dates. */ uint_fast32_t owl_time_elapsed_ms(const owl_timestamp d1, const owl_timestamp d2) { return owl_timestamp_to_ms(owl_time_elapsed(d1, d2)) ; } /* * Returns a owl_timestamp storing the time between two dates. */ owl_timestamp owl_time_elapsed(const owl_timestamp d1, const owl_timestamp d2) { owl_timestamp elapsed ; elapsed.tv_sec = abs(d1.tv_sec - d2.tv_sec) ; elapsed.tv_nsec = abs(d1.tv_nsec - d2.tv_nsec) ; #ifdef DEBUG fprintf(stderr, "time_elapsed(): %"PRIu64"ms\n", owl_timestamp_to_ms(elapsed)) ; #endif return elapsed ; } /* * Converts a owl_timestamp from host endianess to network endianess. */ owl_timestamp owl_hton_timestamp(owl_timestamp date) { owl_timestamp d ; d.tv_sec = htonl(date.tv_sec) ; d.tv_nsec = htonl(date.tv_nsec) ; return d ; } /* * Converts a owl_timestamp from network endianess to host endianess. */ owl_timestamp owl_ntoh_timestamp(owl_timestamp date) { owl_timestamp d ; d.tv_sec = ntohl(date.tv_sec) ; d.tv_nsec = ntohl(date.tv_nsec) ; return d ; } /* * Compares two MAC addresses. * Returns TRUE if they are identical, FALSE otherwise. */ owl_bool owl_mac_equals(uint8_t *mac1, uint8_t *mac2) { int i ; for(i=0 ; i < 6 ; i++) if(mac1[i] != mac2[i]) return FALSE ; return TRUE ; } /* * Creates a UDP transmission socket and returns its descriptor. * Parameters: * - server_address: the server IP address. * - server_port: the listening port on the server. * - server_description (in/out): the structure in which the server * description will be saved. * - client_description (in/out): the structure in which the client * description will be saved. */ int owl_create_udp_trx_socket(char *server_address, uint_fast16_t server_port, struct sockaddr_in *server_description, struct sockaddr_in *client_description) { int sockfd ; // Socket descriptor /* Ceate the UDP socket */ sockfd = socket(AF_INET, SOCK_DGRAM, 0) ; if (sockfd < 0) { perror("UDP socket creation failed") ; return sockfd ; } /* Initialise the client structure */ memset(client_description, 0, sizeof(*client_description)) ; client_description->sin_family = AF_INET ; // INET socket client_description->sin_addr.s_addr = htonl(INADDR_ANY) ; /* Initialise the server structure */ memset(server_description, 0, sizeof(*server_description)) ; server_description->sin_family = AF_INET ; // INET socket // Server IP address: server_description->sin_addr.s_addr = inet_addr(server_address) ; // Listening port on the server: server_description->sin_port = htons(server_port) ; return sockfd ; } /* * Creates a UDP reception socket and returns its descriptor. * Parameters: * - port: port on which the socket listens. */ int owl_create_udp_listening_socket(uint_fast16_t port) { int sockfd ; // Socket descriptor struct sockaddr_in server_description ; // Server structure int ret = 0 ; // Return value /* Create the UDP socket */ sockfd = socket(AF_INET, SOCK_DGRAM, 0) ; if (sockfd < 0) { perror("UDP socket creation failed") ; return sockfd ; } /* Initialise the server structure */ memset(&server_description, 0, sizeof(server_description)) ; server_description.sin_family = AF_INET ; // INET socket // All the connections are accepted: server_description.sin_addr.s_addr = htonl(INADDR_ANY) ; server_description.sin_port = htons(port) ; // Listening port /* Port reservation */ ret = bind(sockfd, (struct sockaddr*) &server_description, sizeof(server_description)) ; if (ret < 0) { perror("Cannot bind the UDP socket") ; close(sockfd) ; return ret ; } return sockfd ; } /* * Switches the IEEE 802.11 interface 'iface' to Monitor mode. */ int owl_iface_mode_monitor(char *iface) { struct iwreq wrq ; int sockfd = iw_sockets_open() ; strncpy((&wrq)->ifr_name, iface, IFNAMSIZ) ; if (ioctl(sockfd, SIOCGIWMODE, &wrq) == -1) // Get current mode { perror("Error reading interface mode") ; return ERR_READING_MODE ; } // If interface is not yet in Monitor mode if (wrq.u.mode != IW_MODE_MONITOR) { wrq.u.mode = IW_MODE_MONITOR ; if (ioctl(sockfd, SIOCSIWMODE, &wrq) == -1) // Set up Monitor mode { perror("Error setting up Monitor mode") ; return ERR_SETTING_MODE ; } } close(sockfd) ; return 0 ; } /* * Sets the IEEE 802.11 channel of the interface 'iface'. * 'channel' must be an integer between 1 and 14. */ int owl_iface_set_channel(char *iface, uint_fast8_t channel) { struct iwreq wrq ; int sockfd = iw_sockets_open() ; strncpy((&wrq)->ifr_name, iface, IFNAMSIZ) ; iw_float2freq(channel, &(wrq.u.freq)) ; wrq.u.freq.flags = IW_FREQ_FIXED ; if (ioctl(sockfd, SIOCSIWFREQ, &wrq) == -1) { perror("Error setting the Wi-Fi channel") ; return ERR_SETTING_CHANNEL ; } close(sockfd) ; return 0 ; } /* * Switches alternatively the Wi-Fi channel of the IEEE 802.11 interface * 'iface' to 4 or 11. */ int owl_iface_channel_hop(char *iface) { uint_fast16_t channel ; struct iwreq wrq ; int sockfd = iw_sockets_open() ; strncpy((&wrq)->ifr_name, iface, IFNAMSIZ) ; if (ioctl(sockfd, SIOCGIWFREQ, &wrq) == -1) { perror("Erreur lors de la lecture de la fréquence ") ; return ERR_READING_CHANNEL ; } // The following is not very clean: we should use iw_freq2float(), // iw_freq_to_channel() & friends, cf. /usr/include/{iwlib.h,wireless.h}. channel = wrq.u.freq.m / 100000 ; if (channel > 1000) // If the value is in Hz, we convert it to a channel = owl_frequency_to_channel(channel) ; // channel number // (with our own function, still not very clean). close(sockfd) ; /* Switch the canal */ if (channel == 4) // If channel is 4 return owl_iface_set_channel(iface, 11) ; // switch to 11 ; else return owl_iface_set_channel(iface, 4) ; // else, set it to 4. } /* * Generic signal handler for SIGINT. */ void owl_sigint_handler(int num) { if (num != SIGINT) { fprintf(stderr, "Error! The SIGINT handler was called but the" " signal is not SIGINT.\n") ; exit(ERR_BAD_SIGNAL) ; } run = FALSE ; #ifdef DEBUG fprintf(stderr, "\nSignal received: end.\n"); #endif // DEBUG fflush(NULL) ; } /* Gestionnaire de signal générique pour SIGTERM */ void owl_sigterm_handler(int num) { if (num != SIGTERM) { fprintf(stderr, "Error! The SIGTERM handler was called but the" " signal is not SIGTERM.\n") ; exit(ERR_BAD_SIGNAL) ; } owl_sigint_handler(SIGINT) ; }