[Listener] Translation of comments, 72 col.

This commit is contained in:
Matteo Cypriani 2010-07-13 14:39:03 +02:00
parent 7f262a8573
commit 5eb11af87f
2 changed files with 314 additions and 209 deletions

View File

@ -2,8 +2,8 @@
* This file is part of the rtap localisation project. * This file is part of the rtap localisation project.
*/ */
#ifndef _AP_H #ifndef _OWLPS_LISTENER_H_
#define _AP_H #define _OWLPS_LISTENER_H_
/* Compilation-time options: to activate, uncomment or compile with -D /* Compilation-time options: to activate, uncomment or compile with -D
* option. * option.
@ -39,26 +39,26 @@
# endif // __BYTE_ORDER == __LITTLE_ENDIAN # endif // __BYTE_ORDER == __LITTLE_ENDIAN
#endif // le32toh #endif // le32toh
// Pour la fonction get_mac_addr() : // Used by get_mac_addr():
#include <netinet/if_ether.h> #include <netinet/if_ether.h>
#include <netinet/udp.h> #include <netinet/udp.h>
#include <netinet/ip.h> #include <netinet/ip.h>
/* Codes d'erreurs */ /* Arguments & program configuration */
#define ERR_CREATING_SOCKET 1 // Erreur lors de la création de la socket d'envoi #define OPTIONS "d:f:kl:m:p:qr:vw:" // getopt string
#define ERR_OPENING_IFACE 2 // Erreur lors de l'ouverture de l'interface de capture
#define ERR_BAD_USAGE 3 // Mauvais appel au programme
#define ERR_PARSING_CONFIG_FILE 4 // Erreur lors de la lecture du fichier de configuration
/* Arguments & configuration du programme */
#define OPTIONS "d:f:kl:m:p:qr:vw:" // Chaîne pour getopt
#define DEFAULT_CONFIG_FILE "/usr/local/etc/owlps/owlps-listener.conf" #define DEFAULT_CONFIG_FILE "/usr/local/etc/owlps/owlps-listener.conf"
enum {MODE_ACTIVE = 'a', MODE_PASSIVE = 'p', MODE_MIXED = 'm'} ; enum {MODE_ACTIVE = 'a', MODE_PASSIVE = 'p', MODE_MIXED = 'm'} ;
/* En-têtes des fonctions */ /* Error codes */
#define ERR_CREATING_SOCKET 1 // Error when creating output socket
#define ERR_OPENING_IFACE 2 // Error when opening capture interface
#define ERR_BAD_USAGE 3 // Bad program call
#define ERR_PARSING_CONFIG_FILE 4 // Error reading the configuration file
/* Function headers */
#ifdef USE_PTHREAD #ifdef USE_PTHREAD
void* keep_mode_monitor(char *iface) ; void* keep_mode_monitor(char *iface) ;
#endif // USE_PTHREAD #endif // USE_PTHREAD
@ -68,11 +68,11 @@ void get_mac_addr(char *eth, unsigned char mac_bytes[6]) ;
void print_usage(char *prog) ; void print_usage(char *prog) ;
/* Macros permettant de jongler entre la gestion des options via la /* Macros to allow switching option handling with the libconfuse
* structure offerte par libconfuse, et une structure maison si cette * structure and a home-made structure (if program is not compiled
* dernière est désactivée. * with libconfuse support).
*/ */
/* Macros utilisant libconfuse : */ /* libconfuse macros */
#ifdef USE_CONFIG_FILE #ifdef USE_CONFIG_FILE
#define SET_MODE(MODE) (cfg_setint(cfg, "mode", (MODE))) #define SET_MODE(MODE) (cfg_setint(cfg, "mode", (MODE)))
#define GET_MODE() (cfg_getint(cfg, "mode")) #define GET_MODE() (cfg_getint(cfg, "mode"))
@ -94,7 +94,7 @@ void print_usage(char *prog) ;
#define UNSET_VERBOSE() (cfg_setbool(cfg, "verbose", cfg_false)) #define UNSET_VERBOSE() (cfg_setbool(cfg, "verbose", cfg_false))
#define GET_VERBOSE() (cfg_getbool(cfg, "verbose")) #define GET_VERBOSE() (cfg_getbool(cfg, "verbose"))
/* Macros utilisant la structure maison : */ /* Home-made structure macros */
#else // USE_CONFIG_FILE #else // USE_CONFIG_FILE
#define SET_MODE(MODE) (options.mode = (MODE)) #define SET_MODE(MODE) (options.mode = (MODE))
#define GET_MODE() (options.mode) #define GET_MODE() (options.mode)
@ -118,4 +118,4 @@ void print_usage(char *prog) ;
#endif // USE_CONFIG_FILE #endif // USE_CONFIG_FILE
#endif // _AP_H #endif // _OWLPS_LISTENER_H_

View File

@ -7,13 +7,16 @@
unsigned char mac[6] ; // Adresse MAC de l'AP unsigned char mac[6] ; // AP MAC address
#ifdef USE_CONFIG_FILE #ifdef USE_CONFIG_FILE
cfg_t *cfg ; // Structure contenant la configuration cfg_t *cfg ; // Configuration structure
#else // USE_CONFIG_FILE // Si on n'utilise pas libconfuse, on déclare une #else // USE_CONFIG_FILE
struct { // structure qui servira à stocker les options getopt : /* If we do not use libconfuse, we declare a structure to store getopt
* options.
*/
struct {
char mode ; char mode ;
char aggregation_ip[16] ; char aggregation_ip[16] ;
long aggregation_port ; long aggregation_port ;
@ -24,7 +27,7 @@ struct { // structure qui servira à stocker les options getopt
char rtap_iface[IFNAMSIZ + 1] ; char rtap_iface[IFNAMSIZ + 1] ;
char wifi_iface[IFNAMSIZ + 1] ; char wifi_iface[IFNAMSIZ + 1] ;
BOOL verbose ; BOOL verbose ;
} options = { // et on initalise les options par défaut : } options = { // Initalise default options:
MODE_ACTIVE, MODE_ACTIVE,
"127.0.0.1", "127.0.0.1",
AGGREGATE_DEFAULT_PORT, AGGREGATE_DEFAULT_PORT,
@ -39,37 +42,50 @@ struct { // structure qui servira à stocker les options getopt
#endif // USE_CONFIG_FILE #endif // USE_CONFIG_FILE
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
struct sigaction action ; // Structure de mise en place des gestionnaires de signaux struct sigaction action ; // Signal handler structure
char *mac_string ; // MAC de l'AP sous forme de chaîne char *mac_string ; // AP MAC (string value)
int ret ; // Code de retour du programme int ret ; // Program return value
#ifdef USE_PTHREAD #ifdef USE_PTHREAD
pthread_t thread ; // Thread pour le repassage en mode monitor pthread_t thread ; // Thread pour le repassage en mode monitor
#endif // USE_PTHREAD #endif // USE_PTHREAD
#ifdef USE_CONFIG_FILE // Si on utilise libconfuse, on déclare les options : #ifdef USE_CONFIG_FILE
cfg_opt_t opts[] = { // Options reconnues par confuse dans le fichier de config // If we use libconfuse, we declare options:
CFG_INT("mode", MODE_ACTIVE, CFGF_NONE), // Mode d'écoute : a pour actif, p pour passif, m pour mixte (défaut : a) cfg_opt_t opts[] =
CFG_STR("aggregation_ip", "127.0.0.1", CFGF_NONE), // Adresse IP du serveur d'agrégation (défaut : boucle locale) {
CFG_INT("aggregation_port", AGGREGATE_DEFAULT_PORT, CFGF_NONE), // Port d'envoi sur le serveur d'agrégation // Listening mode: a for active, p for passive, m for mixed
CFG_INT("listening_port", LOC_REQUEST_DEFAULT_PORT, CFGF_NONE), // Port d'écoute des demandes des mobiles // (default: a):
CFG_INT("mode", MODE_ACTIVE, CFGF_NONE),
// IP address of the aggregator (default: loopback):
CFG_STR("aggregation_ip", "127.0.0.1", CFGF_NONE),
// Port on which the aggregator listens:
CFG_INT("aggregation_port", AGGREGATE_DEFAULT_PORT, CFGF_NONE),
// Port on which mobiles send active requests:
CFG_INT("listening_port", LOC_REQUEST_DEFAULT_PORT, CFGF_NONE),
#ifdef USE_PTHREAD #ifdef USE_PTHREAD
CFG_BOOL("keep_monitor", cfg_false, CFGF_NONE), // Active le maintien actif du mode monitor // Activate the active monitor mode keeping-up (read the code if
// you do not understand what I mean):
CFG_BOOL("keep_monitor", cfg_false, CFGF_NONE),
#endif // USE_PTHREAD #endif // USE_PTHREAD
CFG_STR("rtap_iface", "", CFGF_NONE), // Interface radiotap utilisée pour la capture // Radiotap interface, used to capture:
CFG_STR("wifi_iface", "", CFGF_NONE), // Interface physique correspondante (utilisée pour récupérer l'adresse MAC) CFG_STR("rtap_iface", "", CFGF_NONE),
CFG_BOOL("verbose", cfg_false, CFGF_NONE), // Afficher les paquets capturés ou pas // Physical interface corresponding to the radiotap interface (used
CFG_END() } ; // to get the MAC address):
CFG_STR("wifi_iface", "", CFGF_NONE),
// Display capture packets, or not:
CFG_BOOL("verbose", cfg_false, CFGF_NONE),
CFG_END()
} ;
char *config_file ; // Nom du fichier de configuration char *config_file ; // Configuration file name
#endif // USE_CONFIG_FILE #endif // USE_CONFIG_FILE
int opt ; // Retour de getopt int opt ; // getopt return value
// Option -f specifies a config file, so we search for it first
/* L'option -f sert à spécifier un fichier de configuration alternatif,
* on regarde en premier si elle est présente */
do do
opt = getopt(argc, argv, OPTIONS) ; opt = getopt(argc, argv, OPTIONS) ;
while (opt != 'f' && opt != -1) ; while (opt != 'f' && opt != -1) ;
@ -79,34 +95,42 @@ int main(int argc, char *argv[])
config_file = malloc((strlen(optarg) + 1) * sizeof(char)) ; config_file = malloc((strlen(optarg) + 1) * sizeof(char)) ;
strcpy(config_file, optarg) ; strcpy(config_file, optarg) ;
#else // USE_CONFIG_FILE #else // USE_CONFIG_FILE
fprintf(stderr, "Attention ! Le programme a été compilé sans le support des fichiers de configuration, l'option -f n'est donc pas disponible. Vous devez passer toutes les options sur la ligne de commandes, sans quoi les valeurs par défaut seront utilisées.\n") ; fprintf(stderr, "Warning! Program was not compiled with"
" configuration file support, so -f is not available. You"
" must specify all options on the command line, or default"
" value will be used.\n") ;
#endif // USE_CONFIG_FILE #endif // USE_CONFIG_FILE
} }
#ifdef USE_CONFIG_FILE #ifdef USE_CONFIG_FILE
else // Si -f n'est pas présente, on utilise le fichier de config par défaut else // If -f isn't found, we use the default config file
{ {
config_file = malloc((strlen(DEFAULT_CONFIG_FILE) + 1) * sizeof(char)) ; config_file =
malloc((strlen(DEFAULT_CONFIG_FILE) + 1) * sizeof(char)) ;
strcpy(config_file, DEFAULT_CONFIG_FILE) ; strcpy(config_file, DEFAULT_CONFIG_FILE) ;
} }
/* Lecture du fichier de configuration */ /* Parse config file */
cfg = cfg_init(opts, CFGF_NONE) ; // Initialisation des options cfg = cfg_init(opts, CFGF_NONE) ; // Initialise options
switch (cfg_parse(cfg, config_file)) switch (cfg_parse(cfg, config_file))
{ {
case CFG_FILE_ERROR : case CFG_FILE_ERROR :
fprintf(stderr, "Erreur lors de l'ouverture du fichier de configuration « %s » : %s.\n", config_file, strerror(errno)) ; fprintf(stderr,
"Error! Cannot open configuration file « %s »: %s.\n",
config_file, strerror(errno)) ;
break ; break ;
case CFG_PARSE_ERROR : case CFG_PARSE_ERROR :
fprintf(stderr, "Erreur lors de la lecture du fichier de configuration « %s » !\n", config_file) ; fprintf(stderr,
"Error! Parsing of configuration file « %s » failed!\n",
config_file) ;
free(config_file) ; free(config_file) ;
return ERR_PARSING_CONFIG_FILE ; exit(ERR_PARSING_CONFIG_FILE) ;
} }
free(config_file) ; free(config_file) ;
#endif // USE_CONFIG_FILE #endif // USE_CONFIG_FILE
/* Lecture des arguments de la ligne de commandes */ /* Parse command line */
optind = 1 ; // On reprend l'analyse des arguments au début optind = 1 ; // Rewind argument parsing
while ((opt = getopt(argc, argv, OPTIONS)) != -1) while ((opt = getopt(argc, argv, OPTIONS)) != -1)
{ {
switch (opt) switch (opt)
@ -114,14 +138,16 @@ int main(int argc, char *argv[])
case 'd' : case 'd' :
SET_AGGREGATION_IP(optarg) ; SET_AGGREGATION_IP(optarg) ;
break ; break ;
case 'f' : // Fichier de configuration case 'f' : // Config file
// Déjà traité. break ; // (already parsed)
break ;
case 'k' : case 'k' :
#ifdef USE_PTHREAD #ifdef USE_PTHREAD
SET_KEEP_MONITOR() ; SET_KEEP_MONITOR() ;
#else // USE_PTHREAD #else // USE_PTHREAD
fprintf(stderr, "Attention ! Le programme a été compilé sans le support des threads POSIX, l'option -k (maintien du mode monitor) n'est donc pas disponible et sera ignorée.\n") ; fprintf(stderr, "Warning! The program was compiled without"
" support of POSIX threads, so -k (monitor mode"
" keeping-up) is not available and will be ignored."
"\n") ;
#endif // USE_PTHREAD #endif // USE_PTHREAD
break ; break ;
case 'l' : case 'l' :
@ -151,7 +177,7 @@ int main(int argc, char *argv[])
} }
} }
/* Vérification des arguments */ /* Check arguments */
switch (GET_MODE()) switch (GET_MODE())
{ {
case MODE_ACTIVE : case MODE_ACTIVE :
@ -159,37 +185,40 @@ int main(int argc, char *argv[])
case MODE_PASSIVE : case MODE_PASSIVE :
break ; break ;
default : default :
fprintf(stderr, "Erreur ! Mode « %c » inconnu.\n", (char) GET_MODE()) ; fprintf(stderr, "Error! Unknown mode « %c ».\n", (char) GET_MODE()) ;
print_usage(argv[0]) ; print_usage(argv[0]) ;
return ERR_BAD_USAGE ; return ERR_BAD_USAGE ;
} }
if (GET_RTAP_IFACE()[0] == '\0') if (GET_RTAP_IFACE()[0] == '\0')
{ {
fprintf(stderr, "Erreur ! Vous devez spécifier une interface radiotap pour la capture.\n") ; fprintf(stderr, "Error! You must specify a radiotap interface"
" for the capture.\n") ;
print_usage(argv[0]) ; print_usage(argv[0]) ;
return ERR_BAD_USAGE ; return ERR_BAD_USAGE ;
} }
if (GET_WIFI_IFACE()[0] == '\0') if (GET_WIFI_IFACE()[0] == '\0')
{ {
#ifdef DEBUG #ifdef DEBUG
fprintf(stderr, "Attention ! Aucune interface Wi-Fi spécifiée. Utilisation de l'interface radiotap (%s) à la place.\n", GET_RTAP_IFACE()) ; fprintf(stderr, "Warning! No Wi-Fi was specified. Failing back to"
" the radiotap interface (%s) instead.\n",
GET_RTAP_IFACE()) ;
#endif // DEBUG #endif // DEBUG
SET_WIFI_IFACE(GET_RTAP_IFACE()) ; SET_WIFI_IFACE(GET_RTAP_IFACE()) ;
} }
#ifdef DEBUG #ifdef DEBUG
/* Affichage de la configuration */ /* Print configuration */
fprintf(stderr, "Configuration :\n") ; fprintf(stderr, "Configuration:\n") ;
#ifdef USE_CONFIG_FILE #ifdef USE_CONFIG_FILE
cfg_print(cfg, stderr) ; cfg_print(cfg, stderr) ;
#else // USE_CONFIG_FILE #else // USE_CONFIG_FILE
fprintf(stderr, "\ fprintf(stderr,
aggregation_ip = \"%s\"\n\ "aggregation_ip = \"%s\"\n"
aggregation_port = %ld\n\ "aggregation_port = %ld\n"
listening_port = %ld\n\ "listening_port = %ld\n"
rtap_iface = \"%s\"\n\ "rtap_iface = \"%s\"\n"
wifi_iface = \"%s\"\n\ "wifi_iface = \"%s\"\n"
", ,
GET_AGGREGATION_IP(), GET_AGGREGATION_IP(),
GET_AGGREGATION_PORT(), GET_AGGREGATION_PORT(),
GET_LISTENING_PORT(), GET_LISTENING_PORT(),
@ -206,7 +235,7 @@ wifi_iface = \"%s\"\n\
run = TRUE ; run = TRUE ;
/* Mise en place des gestionnaires de signaux */ /* Set up signal handlers */
sigemptyset(&action.sa_mask) ; sigemptyset(&action.sa_mask) ;
action.sa_handler = sigint_handler ; action.sa_handler = sigint_handler ;
sigaction(SIGINT, &action, NULL) ; sigaction(SIGINT, &action, NULL) ;
@ -214,37 +243,40 @@ wifi_iface = \"%s\"\n\
sigaction(SIGTERM, &action, NULL) ; sigaction(SIGTERM, &action, NULL) ;
#ifdef USE_PTHREAD #ifdef USE_PTHREAD
/* Création du thread */ /* Set up thread */
if (GET_KEEP_MONITOR()) if (GET_KEEP_MONITOR())
pthread_create(&thread, NULL, (void *) &keep_mode_monitor, GET_WIFI_IFACE()) ; pthread_create(&thread, NULL,
(void *) &keep_mode_monitor, GET_WIFI_IFACE()) ;
#endif // USE_PTHREAD #endif // USE_PTHREAD
get_mac_addr(GET_WIFI_IFACE(), mac) ; get_mac_addr(GET_WIFI_IFACE(), mac) ;
mac_string = mac_bytes_to_string(mac) ; mac_string = mac_bytes_to_string(mac) ;
printf("Ma mac est : %s\n", mac_string) ; printf("My MAC address is: %s\n", mac_string) ;
free(mac_string) ; free(mac_string) ;
ret = capture() ; ret = capture() ;
#ifdef USE_CONFIG_FILE #ifdef USE_CONFIG_FILE
cfg_free(cfg) ; // Nettoyage de la configuration cfg_free(cfg) ; // Clean configuration
#endif // USE_CONFIG_FILE #endif // USE_CONFIG_FILE
printf("%s : fin.\n", argv[0]) ; printf("%s: end.\n", argv[0]) ;
return ret ; return ret ;
} }
#ifdef USE_PTHREAD #ifdef USE_PTHREAD
/* Fonction du thread, qui surveille la liste et envoie les infos au serveur de localisation au bout du timeout */ /*
* Thread function. Switches interface 'iface' to monitor mode every
* second.
*/
void* keep_mode_monitor(char *iface) void* keep_mode_monitor(char *iface)
{ {
while (run) while (run)
{ {
iface_mode_monitor(iface) ; // Passage de l'interface en mode Monitor. iface_mode_monitor(iface) ; // Switch the interface to monitor mode
sleep(1) ; // Pause de 1 secondes. sleep(1) ; // Wait for 1 second
} }
pthread_exit(NULL) ; pthread_exit(NULL) ;
@ -253,99 +285,123 @@ void* keep_mode_monitor(char *iface)
/*
/* Capture des paquets en utilisant l'interface RTAP figurant dans les options. * Captures packets using the radiotap interface.
* Les données capturées sont envoyées au serveur d'aggrégation dont l'IP * Captured data is transmitted to the aggregator.
* figure également dans les options.
*/ */
int capture() int capture()
{ {
pcap_t *handle ; // Descripteur de capture de paquets pcap_t *handle ; // Packet capture descriptor
char errbuf[PCAP_ERRBUF_SIZE] ; // Message d'erreur char errbuf[PCAP_ERRBUF_SIZE] ; // Error message
int sockfd ; // Descripteur de la socket vers le serveur d'aggrégation int sockfd ; // Output socket descriptor
struct sockaddr_in server, client ; struct sockaddr_in server, client ;
/* Sous-fonction de traitement des paquets capturés */ /* Sub-function that treats captured packets */
void got_packet(u_char *args, const struct pcap_pkthdr *header, const u_char *packet) void got_packet(u_char *args, const struct pcap_pkthdr *header,
const u_char *packet)
{ {
// On appelle la fonction read_packet() avec les mêmes arguments, // Call function read_packet() with the same arguments, plus server
// plus les informations concernant le serveur : // information:
read_packet(args, header, packet, sockfd, &server) ; read_packet(args, header, packet, sockfd, &server) ;
} }
handle = pcap_open_live(GET_RTAP_IFACE(), BUFSIZ, 1, 1000, errbuf) ; // Début de la capture // Start capture:
if (handle == NULL) // Le lancement de la capture a-t-il échoué ? handle = pcap_open_live(GET_RTAP_IFACE(), BUFSIZ, 1, 1000, errbuf) ;
if (handle == NULL) // Capture starting failed
{ {
fprintf(stderr, "Impossible d'ouvrir l'interface « %s » : %s\n", GET_RTAP_IFACE(), errbuf) ; fprintf(stderr, "Cannot open interface « %s »: %s\n",
GET_RTAP_IFACE(), errbuf) ;
return ERR_OPENING_IFACE ; return ERR_OPENING_IFACE ;
} }
/* Ouverture de la socket UDP vers le serveur d'aggrégation */ /* Open UDP socket to the aggregator */
sockfd = create_udp_sending_socket(GET_AGGREGATION_IP(), GET_AGGREGATION_PORT(), &server, &client); sockfd = create_udp_sending_socket(GET_AGGREGATION_IP(),
GET_AGGREGATION_PORT(),
&server, &client) ;
if (sockfd < 0) if (sockfd < 0)
{ {
perror("Erreur ! Impossible de créer la socket vers le serveur d'aggrégation \n"); perror("Error! Cannot create socket to the aggregation server");
return ERR_CREATING_SOCKET ; return ERR_CREATING_SOCKET ;
} }
while(run) while(run)
{ // Capture one packet at time, and call got_packet() on it:
pcap_loop(handle, 1, got_packet, NULL) ; // Collecte 1 paquet et appelle la fonction got_packet quand pcaploop a recupéré des paquets pcap_loop(handle, 1, got_packet, NULL) ;
}
pcap_close(handle) ; // Arrêt de la capture. pcap_close(handle) ; // Stop capture
(void) close(sockfd) ; // Fermeture de la socket (void) close(sockfd) ; // Close socket
return 0 ; return 0 ;
} }
/*
/* Traite un paquet et l'envoie au serveur d'agrégation sur la socket UDP "sockfd", au serveur "server". */ * Treats a packet and sends it to the aggregator (on the UDP socket
void read_packet(u_char *args, const struct pcap_pkthdr *header, const u_char *packet, int sockfd, struct sockaddr_in *server) * 'sockfd', to the server 'server').
*/
void read_packet(u_char *args, const struct pcap_pkthdr *header,
const u_char *packet, int sockfd,
struct sockaddr_in *server)
{ {
unsigned char *data = (unsigned char *) packet ; // Recopie dans data l'adresse du paquet capturé // Copy packet address into data:
unsigned short rtap_bytes ; // Taille des données reçues unsigned char *data = (unsigned char *) packet ;
unsigned int rtap_presentflags, rtap_position ; unsigned short rtap_bytes ; // Received data size
couple_message couple ; // Message à envoyer à l'agrégateur unsigned int
ssize_t nsent ; // Retour de sendto rtap_presentflags,
BOOL check[15] ; // Champs présents rtap_position ;
unsigned char raw_packet_type ; // Type du packet reçu (beacon, data...) couple_message couple ; // Message to send to the aggregator
unsigned char raw_packet_flags ; // Flags de l'en-tête IEEE 802.11 ssize_t nsent ; // sendto return value
BOOL check[15] ; // Present flags
unsigned char raw_packet_type ; // Received packet type (beacon, data…)
unsigned char raw_packet_flags ; // IEEE 802.11 header flags
unsigned short llc_packet_type = 0 ; unsigned short llc_packet_type = 0 ;
struct iphdr *packet_ip_header = NULL ; // Pointeur sur l'éventuel en-tête IP du paquet // Pointer to the (possible) IP header of the packet:
struct udphdr *packet_udp_header = NULL ; // Pointeur sur l'éventuel en-tête UDP du paquet struct iphdr *packet_ip_header = NULL ;
char packet_type ; // Type de demande de localisation (demande, calibration) // Pointer to the (possible) UDP header of the packet:
BOOL is_explicit_packet = TRUE ; // Le paquet constitue-t-il une demande ? struct udphdr *packet_udp_header = NULL ;
int i ; // Compteur char packet_type ; // Localisation request type (request, calibration)
BOOL is_explicit_packet = TRUE ; // Is the packet an explicit request?
int i ; // Iterator
/* Traitements communs */ /* Common treatements */
memcpy(&rtap_bytes, &data[2], sizeof(unsigned short)) ; // Recopie les deux octets à partir du troisième octet de donnée qui est la taille de l'en-tête rtap (change avec des flags) // Copy 2 bytes from the 3rd data byte, that is the size of the rtap
// header (changes with the flags):
memcpy(&rtap_bytes, &data[2], sizeof(unsigned short)) ;
rtap_bytes = ntohs(rtap_bytes) ; rtap_bytes = ntohs(rtap_bytes) ;
raw_packet_type = data[rtap_bytes] ; // Au bout de l'en-tête rtap il y a celle du 802.11 dont le premier determine le type (beacon ou pas) // After the rtap header, there is the 802.11 header; the first byte
// is the packet type (beacon or not):
raw_packet_type = data[rtap_bytes] ;
if (raw_packet_type == RAW_PACKET_TYPE_DATA) // Si le paquet est de type data, if (raw_packet_type == RAW_PACKET_TYPE_DATA) // Data packet
{ // on récupère le type de paquet (protocole, sur 2 octets) dans l'en-tête LLC : {
memcpy((unsigned char*) &llc_packet_type, &data[rtap_bytes + IEEE80211_HEADER_SIZE + 6], 2) ; // Get the packet type (protocol, 2 bytes) from the LLC header:
memcpy((unsigned char*) &llc_packet_type,
&data[rtap_bytes + IEEE80211_HEADER_SIZE + 6], 2) ;
llc_packet_type = ntohs(llc_packet_type) ; llc_packet_type = ntohs(llc_packet_type) ;
if (llc_packet_type == ETH_P_IP) // Si c'est un paquet IP on récupère l'IP source if (llc_packet_type == ETH_P_IP) // IP packet
{ {
packet_ip_header = (struct iphdr *) &data[rtap_bytes + IEEE80211_HEADER_SIZE + LLC_HEADER_SIZE] ; packet_ip_header = (struct iphdr *)
&data[rtap_bytes + IEEE80211_HEADER_SIZE + LLC_HEADER_SIZE] ;
// Get the source IP:
memcpy(couple.mobile_ip_addr_bytes, &packet_ip_header->saddr, 4) ; memcpy(couple.mobile_ip_addr_bytes, &packet_ip_header->saddr, 4) ;
if (GET_MODE() != MODE_PASSIVE) // Si on est en mode actif ou mixte if (GET_MODE() != MODE_PASSIVE) // If mode is active or mixed
{ {
if (packet_ip_header->protocol == IPPROTO_UDP) // Le protocole du paquet est UDP pour une demande explicite // Protocol for an explicit request is UDP
{ // On teste le port de destination : if (packet_ip_header->protocol == IPPROTO_UDP)
packet_udp_header = (struct udphdr *) &data[rtap_bytes + IEEE80211_HEADER_SIZE + LLC_HEADER_SIZE + sizeof(struct iphdr)] ; { // Check destination port:
if (ntohs(packet_udp_header->dest) != GET_LISTENING_PORT()) packet_udp_header = (struct udphdr *)
&data[rtap_bytes + IEEE80211_HEADER_SIZE +
LLC_HEADER_SIZE + sizeof(struct iphdr)] ;
if (ntohs(packet_udp_header->dest) !=
GET_LISTENING_PORT())
{ {
if (GET_MODE() == MODE_ACTIVE) if (GET_MODE() == MODE_ACTIVE)
return ; return ;
@ -354,47 +410,54 @@ void read_packet(u_char *args, const struct pcap_pkthdr *header, const u_char *p
} }
} }
} }
else if (GET_MODE() != MODE_ACTIVE) // Mode passif ou mixte else if (GET_MODE() != MODE_ACTIVE) // Passive or mixed mode
{ {
is_explicit_packet = FALSE ; is_explicit_packet = FALSE ;
bzero(couple.mobile_ip_addr_bytes, 4) ; // On positionne l'IP à zéro bzero(couple.mobile_ip_addr_bytes, 4) ; // Blank the IP
} }
else // On est en mode actif et le paquet n'est pas IP donc pas une demande else // Active mode and not an IP packet, so it is not a request
return ; return ;
} }
else
{ // Le paquet n'est pas de la donnée donc pas une demande else // Packet is not data, so it is not a localisation request
{
if (GET_MODE() == MODE_ACTIVE) if (GET_MODE() == MODE_ACTIVE)
return ; return ;
is_explicit_packet = FALSE ; is_explicit_packet = FALSE ;
} }
raw_packet_flags = data[rtap_bytes+1] ; // On récupère les flags 802.11, qui sont dans l'en-tête 802.11. // Get 802.11 flags from the 802.11 header:
raw_packet_flags = data[rtap_bytes+1] ;
#ifdef DEBUG #ifdef DEBUG
printf("raw_packet_flags : %02x\n", raw_packet_flags) ; printf("raw_packet_flags: %02x\n", raw_packet_flags) ;
if (IS_RETRY(raw_packet_flags)) if (IS_RETRY(raw_packet_flags))
printf("Ce paquet est un Retry.\n") ; printf("This packet is a Retry.\n") ;
#endif // DEBUG #endif // DEBUG
memcpy(couple.ap_mac_addr_bytes, mac, 6); // On copie la MAC de l'AP memcpy(couple.ap_mac_addr_bytes, mac, 6) ; // Copy AP MAC
memcpy(couple.mobile_mac_addr_bytes, &data[rtap_bytes+10], 6); // L'adresse MAC source est 10 octets plus loin que le type de paquet 802.11 // Source MAC address is 10 bytes after the 802.11 packet type:
couple.start_time = header->ts ; // L'heure de capture du paquet est contenue dans l'en-tête pcap memcpy(couple.mobile_mac_addr_bytes, &data[rtap_bytes+10], 6) ;
couple.request_time.tv_sec = 0 ; // L'heure d'envoi par le mobile est inconnue (à moins qu'il ne s'agisse d'un paquet explicite) couple.start_time = header->ts ; // Capture time is in the pcap header
// Transmission time on the mobile is unknown (unless the packet is
// an explicit request):
couple.request_time.tv_sec = 0 ;
couple.request_time.tv_usec = 0 ; couple.request_time.tv_usec = 0 ;
/* Mode actif */ /* Active mode */
if (is_explicit_packet if (is_explicit_packet
&& (GET_MODE() == MODE_ACTIVE || GET_MODE() == MODE_MIXED) && (GET_MODE() == MODE_ACTIVE || GET_MODE() == MODE_MIXED)
// FIXME : faut-il toujours ignorer les retry ? // FIXME: should we really ignore Retries?
&& ! IS_RETRY(raw_packet_flags)) // et ce n'est pas un Retry. && ! IS_RETRY(raw_packet_flags))
{ {
packet_type = data[rtap_bytes + IEEE80211_HEADER_SIZE + LLC_HEADER_SIZE + sizeof(struct iphdr) + sizeof(struct udphdr)] ; packet_type =
data[rtap_bytes + IEEE80211_HEADER_SIZE + LLC_HEADER_SIZE
+ sizeof(struct iphdr) + sizeof(struct udphdr)] ;
switch(packet_type) switch(packet_type)
{ {
case PACKET_TYPE_NORMAL : case PACKET_TYPE_NORMAL :
if (GET_VERBOSE()) if (GET_VERBOSE())
printf("\nPaquet explicite normal reçu.\n") ; printf("\nExplicit packet received.\n") ;
couple.direction = 0 ; couple.direction = 0 ;
couple.x_position = 0 ; couple.x_position = 0 ;
couple.y_position = 0 ; couple.y_position = 0 ;
@ -403,17 +466,29 @@ void read_packet(u_char *args, const struct pcap_pkthdr *header, const u_char *p
case PACKET_TYPE_CALIBRATION : case PACKET_TYPE_CALIBRATION :
if (GET_VERBOSE()) if (GET_VERBOSE())
printf("\nPaquet explicite de calibration reçu.\n") ; printf("\nExplicite calibration packet received.\n") ;
couple.direction = data[rtap_bytes + IEEE80211_HEADER_SIZE + LLC_HEADER_SIZE + sizeof(struct iphdr) + sizeof(struct udphdr) + 9]; couple.direction =
memcpy(&couple.x_position, &data[rtap_bytes + IEEE80211_HEADER_SIZE + LLC_HEADER_SIZE + sizeof(struct iphdr) + sizeof(struct udphdr) + 10], sizeof(float)); data[rtap_bytes + IEEE80211_HEADER_SIZE + LLC_HEADER_SIZE
memcpy(&couple.y_position, &data[rtap_bytes + IEEE80211_HEADER_SIZE + LLC_HEADER_SIZE + sizeof(struct iphdr) + sizeof(struct udphdr) + 14], sizeof(float)); + sizeof(struct iphdr) + sizeof(struct udphdr) + 9];
memcpy(&couple.z_position, &data[rtap_bytes + IEEE80211_HEADER_SIZE + LLC_HEADER_SIZE + sizeof(struct iphdr) + sizeof(struct udphdr) + 18], sizeof(float)); memcpy(&couple.x_position,
&data[rtap_bytes + IEEE80211_HEADER_SIZE
+ LLC_HEADER_SIZE + sizeof(struct iphdr)
+ sizeof(struct udphdr) + 10], sizeof(float)) ;
memcpy(&couple.y_position,
&data[rtap_bytes + IEEE80211_HEADER_SIZE
+ LLC_HEADER_SIZE + sizeof(struct iphdr)
+ sizeof(struct udphdr) + 14], sizeof(float)) ;
memcpy(&couple.z_position,
&data[rtap_bytes + IEEE80211_HEADER_SIZE
+ LLC_HEADER_SIZE + sizeof(struct iphdr)
+ sizeof(struct udphdr) + 18], sizeof(float)) ;
break ; break ;
default : default :
if (GET_VERBOSE()) if (GET_VERBOSE())
printf("\nPaquet explicite bizarre reçu.\n") ; printf("\nStrange explicit packet received\n") ;
fprintf(stderr, "Erreur ! Type de paquet explicite inconnu (%d).\n", packet_type) ; fprintf(stderr,
"Error! Unknown packet type (%d).\n", packet_type) ;
is_explicit_packet = FALSE ; is_explicit_packet = FALSE ;
} }
@ -422,39 +497,47 @@ void read_packet(u_char *args, const struct pcap_pkthdr *header, const u_char *p
if (GET_MODE() == MODE_ACTIVE) if (GET_MODE() == MODE_ACTIVE)
return ; return ;
else if (GET_VERBOSE()) else if (GET_VERBOSE())
printf("\nCe paquet explicite bizarre sera traité comme implicite.\n") ; printf("\nThis strange explicit packet will be handled as"
" an implicit one.\n") ;
} }
else else
memcpy(&couple.request_time, &data[rtap_bytes + IEEE80211_HEADER_SIZE + LLC_HEADER_SIZE + sizeof(struct iphdr) + sizeof(struct udphdr) + 1], sizeof(struct timeval)); memcpy(&couple.request_time,
&data[rtap_bytes + IEEE80211_HEADER_SIZE + LLC_HEADER_SIZE
+ sizeof(struct iphdr) + sizeof(struct udphdr) + 1],
sizeof(struct timeval)) ;
} }
else if (GET_MODE() == MODE_PASSIVE || GET_MODE() == MODE_MIXED) else if (GET_MODE() == MODE_PASSIVE || GET_MODE() == MODE_MIXED)
{ {
if (GET_VERBOSE()) if (GET_VERBOSE())
printf("\nPaquet implicite reçu.\n") ; printf("\nImplicit packet received.\n") ;
} }
else // Mode actif uniquement, le paquet n'étant pas une demande explicite else // Active mode, packet was not an explicit request
return ; return ;
/* Traitement de l'en-tête Radiotap */ /* Radiotap header handling */
memcpy(&rtap_presentflags, &data[RTAP_P_PRESENTFLAGS], RTAP_L_PRESENTFLAGS) ; // Récupère les flags de l'en-tête rtap // Get rtap flags:
// Note : on récupère les flags en big-endian (net-endianess), mais on memcpy(&rtap_presentflags,
// travaille dessus comme si c'était du little-endian. Cela nous permet &data[RTAP_P_PRESENTFLAGS], RTAP_L_PRESENTFLAGS) ;
// de déclarer un tableau de seulement 15 bits (au lieu de 32) car ce /* We get the flags in big-endian (net-endianess), but we work on them
// sont ces bits (de poids faible) qui nous intéressent. C'est un peu de * as if it was in little-endian. This allows to declare an array of 15
// la triche :-) * bits (instead of 32), because we work only on the least significant
// Du coup, sur les architectures big-endian, il faut retourner les bits * bits (and so we do not reserve space for most significant bits that
// en faisant comme si on avait récupéré les flags en little-endian : * are useless). It's kind of cheat :-)
* So, on big-endian architectures, we must inverse bits as if we had
* got flags in little-endian: */
rtap_presentflags = le32toh(rtap_presentflags) ; rtap_presentflags = le32toh(rtap_presentflags) ;
for (i = 0 ; i < 15 ; i++) // Initialisation de la structure des champs présents for (i = 0 ; i < 15 ; i++) // Initialise present flags structure
check[i] = FALSE ; check[i] = FALSE ;
rtap_position = 8 ; // Début des champs déterminés par le present flag rtap_position = 8 ; // Begining of the present flags determined fields
for (i=0 ; i < 15 ; i++) // on teste les 15 premiers bits du champ flag afin de valider la présence et de les copier // Test the first 15 bits of the flag field in order to check their
// presence and to copy them:
for (i = 0 ; i < 15 ; i++)
{ {
if ((rtap_presentflags % 2) == 1) if ((rtap_presentflags % 2) == 1)
{ {
@ -481,10 +564,12 @@ void read_packet(u_char *args, const struct pcap_pkthdr *header, const u_char *p
rtap_position += RTAP_L_FHSS ; rtap_position += RTAP_L_FHSS ;
break ; break ;
case RTAP_ANTENNASIGNALDBM: case RTAP_ANTENNASIGNALDBM:
memcpy(&(couple.antenna_signal_dbm), &data[rtap_position], RTAP_L_ANTENNASIGNALDBM) ; memcpy(&(couple.antenna_signal_dbm),
&data[rtap_position], RTAP_L_ANTENNASIGNALDBM) ;
check[RTAP_ANTENNASIGNALDBM] = TRUE; check[RTAP_ANTENNASIGNALDBM] = TRUE;
if (GET_VERBOSE()) if (GET_VERBOSE())
printf("Antenna Signal : %d dBm\n", couple.antenna_signal_dbm - 0x100); printf("Antenna signal: %d dBm\n",
couple.antenna_signal_dbm - 0x100);
rtap_position += RTAP_L_ANTENNASIGNALDBM ; rtap_position += RTAP_L_ANTENNASIGNALDBM ;
break ; break ;
case RTAP_ANTENNANOISEDBM: case RTAP_ANTENNANOISEDBM:
@ -530,20 +615,21 @@ void read_packet(u_char *args, const struct pcap_pkthdr *header, const u_char *p
if (GET_VERBOSE()) if (GET_VERBOSE())
{ {
char *ap_mac_string = mac_bytes_to_string(couple.ap_mac_addr_bytes) ; char *ap_mac_string =
char *mobile_mac_string = mac_bytes_to_string(couple.mobile_mac_addr_bytes) ; mac_bytes_to_string(couple.ap_mac_addr_bytes) ;
printf("\ char *mobile_mac_string =
*** Couple à envoyer ***\n\ mac_bytes_to_string(couple.mobile_mac_addr_bytes) ;
\tMAC AP : %s\n\ printf("*** Couple to send ***\n"
\tMAC mobile : %s\n\ "\tMAC AP: %s\n"
\tNuméro de séquence (heure de la demande) : %llu\n\ "\tMobile MAC: %s\n"
\tHeure d'arrivée de la demande de localisation sur l'AP : %llu\n\ "\tSequence number (request time): %llu\n"
\tSignal : %d dBm\n\ "\tRequest arrival time on the AP: %llu\n"
\tPosition X : %f\n\ "\tSignal: %d dBm\n"
\tPosition Y : %f\n\ "\tPosition X: %f\n"
\tPosition Z : %f\n\ "\tPosition Y: %f\n"
\tDirection : %hhd\n\ "\tPosition Z: %f\n"
", "\tDirection: %hhd\n"
,
ap_mac_string, ap_mac_string,
mobile_mac_string, mobile_mac_string,
timeval_to_ms(couple.request_time), timeval_to_ms(couple.request_time),
@ -558,29 +644,32 @@ void read_packet(u_char *args, const struct pcap_pkthdr *header, const u_char *p
free(mobile_mac_string) ; free(mobile_mac_string) ;
} }
/* Envoi du couple au serveur d'aggrégation */ /* Send couple to the aggregator */
nsent = sendto(sockfd, (void *) &couple, sizeof(couple), 0, (struct sockaddr *) server, (socklen_t) sizeof(*server)) ; nsent =
sendto(sockfd, (void *) &couple, sizeof(couple), 0,
(struct sockaddr *) server, (socklen_t) sizeof(*server)) ;
if (nsent != (ssize_t) sizeof(couple)) if (nsent != (ssize_t) sizeof(couple))
{ {
perror("Erreur lors de l'envoi du couple au serveur ") ; perror("Error sending couple to the aggregation server") ;
return ; return ;
} }
} }
/*
/* Fonction permettant de récupérer sa propre adresse MAC (interface 'eth') dans le tableau 'mac_bytes' */ * Get our own MAC address and copy it to 'mac_bytes'.
*/
void get_mac_addr(char *eth, unsigned char mac_bytes[6]) void get_mac_addr(char *eth, unsigned char mac_bytes[6])
{ {
struct ifreq ifr; struct ifreq ifr;
int sockfd ; int sockfd ;
bzero(mac_bytes, sizeof(unsigned char) * 6) ; // RàZ bzero(mac_bytes, sizeof(unsigned char) * 6) ; // Empty mac_bytes
sockfd = socket(AF_INET, SOCK_DGRAM, 0) ; sockfd = socket(AF_INET, SOCK_DGRAM, 0) ;
if(sockfd < 0) if(sockfd < 0)
perror("Impossible d'ouvrir la socket pour récupérer l'adresse MAC ") ; perror("Cannot open socket to read MAC address") ;
strncpy(ifr.ifr_name, eth, IFNAMSIZ) ; strncpy(ifr.ifr_name, eth, IFNAMSIZ) ;
@ -595,23 +684,39 @@ void get_mac_addr(char *eth, unsigned char mac_bytes[6])
/* Affiche le mode d'emploi du programme */
void print_usage(char *prog) void print_usage(char *prog)
{ {
printf("Usage :\n\ printf("Usage :\n"
\t%s [-f config_file] [-m mode] [-d ip_agrégation] [-l listening_port] [-p port_agrégation] -r rtap_iface [-w wifi_iface] [-k] [-v|-q]\n\ "\t%s [-f config_file] [-m mode] [-d aggregation_ip]"
- L'option -f permet de spécifier un fichier de configuration alternatif (le fichier de configuration par défaut ne sera pas lu). Disponible uniquement si le programme a é compilé avec le support de libconfuse.\n\ " [-l listening_port] [-p aggregation_port] -r rtap_iface"
- mode est le mode de fonctionnement : a(ctif), p(assif), m(ixte) (par défaut : a).\n\ " [-w wifi_iface] [-k] [-v | -q]\n"
- ip_agrégation est l'adresse IP du serveur d'agrégation (par défaut : 127.0.0.1), et port_agrégation le port sur lequel il écoute (par défaut : %d).\n\
- rtap_iface est l'interface de capture radiotap.\n\ "Main options:\n"
- wifi_iface est l'interface physique correspondant à rtap_iface (par défaut : rtap_iface).\n\ "\t-f config_file\tUse 'config_file' instead of the default"
- L'option -k active le maintien actif du mode monitor. À utiliser avec des pilotes bogués. Disponible uniquement si le programme a é compilé avec le support des threads POSIX.\n\ " configuration file (%s). Available only if program was"
- L'option -v rend le programme bavard (affichage des paquets capturés) ; l'option -q annule le bavardage s'il est activé par ailleurs (e.g. fichier de configuration). Par défaut le mode verbeux est désactivé.\n\ " compiled with libconfuse.\n"
Note : tous les paramètres sont facultatifs si les options correspondantes sont renseignées dans un fichier de configuration. L'option -f permet de spécifier un fichier de configuration alternatif (par défaut : %s).\n\
", "Capture options:\n"
"\t-m mode\t\t\tCapture mode: a(ctive), p(assive), m(ixed)"
" (default: a).\n"
"\t-d aggregation_ip\tIP address of the aggregation server"
" (default: 127.0.0.1)\n"
"\t-l aggregation_port\tListening port on the aggregation server"
" (default: %d).\n"
"\t-r rtap_iface\t\tRadiotap capture interface.\n"
"\t-w wifi_iface\t\tPhysical interface behind rtap_iface"
" (default: rtap_iface).\n"
"Other options:\n"
"\t-k\tKeep the monitor mode up on wifi_iface. Use it with buggy"
" drivers that disable monitor mode periodically. Available"
" only if the program was compiled with support of POSIX"
" threads.\n"
"\t-v\tVerbose mode (display captured packets).\n"
"\t-q\tQuiet mode (default).\n"
,
prog, prog,
AGGREGATE_DEFAULT_PORT, DEFAULT_CONFIG_FILE,
DEFAULT_CONFIG_FILE AGGREGATE_DEFAULT_PORT
) ; ) ;
} }