2008-02-14 08:54:51 +01:00
/*
* This file is part of the rtap localisation project .
*/
2008-10-06 17:27:33 +02:00
# include "owlps-listener.h"
2008-02-14 08:54:51 +01:00
2009-09-03 11:09:48 +02:00
2008-02-14 08:54:51 +01:00
unsigned char mac [ 6 ] ; // Adresse MAC de l'AP
2009-07-02 13:12:51 +02:00
# ifdef USE_CONFIG_FILE
cfg_t * cfg ; // Structure contenant la configuration
# else // USE_CONFIG_FILE // Si on n'utilise pas libconfuse, on déclare une
struct { // structure qui servira à stocker les options getopt :
2009-08-04 12:02:52 +02:00
char mode ;
2009-07-02 13:12:51 +02:00
char aggregation_ip [ 16 ] ;
long aggregation_port ;
long listening_port ;
# ifdef USE_PTHREAD
BOOL keep_monitor ;
# endif // USE_PTHREAD
char rtap_iface [ IFNAMSIZ + 1 ] ;
char wifi_iface [ IFNAMSIZ + 1 ] ;
2009-08-04 12:02:52 +02:00
BOOL verbose ;
2009-07-02 13:12:51 +02:00
} options = { // et on initalise les options par défaut :
2009-08-04 12:02:52 +02:00
MODE_ACTIVE ,
2009-07-02 13:12:51 +02:00
" 127.0.0.1 " ,
AGGREGATE_DEFAULT_PORT ,
2009-11-09 10:42:23 +01:00
LOC_REQUEST_DEFAULT_PORT ,
2009-07-02 13:12:51 +02:00
# ifdef USE_PTHREAD
FALSE ,
# endif // USE_PTHREAD
" " ,
2009-08-04 12:02:52 +02:00
" " ,
FALSE
2009-07-02 13:12:51 +02:00
} ;
# endif // USE_CONFIG_FILE
2008-02-14 08:54:51 +01:00
2008-02-22 16:04:49 +01:00
2008-02-14 08:54:51 +01:00
int main ( int argc , char * argv [ ] )
{
struct sigaction action ; // Structure de mise en place des gestionnaires de signaux
2008-02-19 11:59:22 +01:00
char * mac_string ; // MAC de l'AP sous forme de chaîne
int ret ; // Code de retour du programme
2009-07-02 09:42:15 +02:00
# ifdef USE_PTHREAD
2008-02-27 17:37:08 +01:00
pthread_t thread ; // Thread pour le repassage en mode monitor
2009-07-02 09:42:15 +02:00
# endif // USE_PTHREAD
2008-02-14 08:54:51 +01:00
2009-07-02 13:12:51 +02:00
# ifdef USE_CONFIG_FILE // Si on utilise libconfuse, on déclare les options :
2009-04-15 14:15:49 +02:00
cfg_opt_t opts [ ] = { // Options reconnues par confuse dans le fichier de config
2009-08-04 12:02:52 +02:00
CFG_INT ( " mode " , MODE_ACTIVE , CFGF_NONE ) , // Mode d'écoute : a pour actif, p pour passif, m pour mixte (défaut : a)
2009-04-15 14:15:49 +02:00
CFG_STR ( " aggregation_ip " , " 127.0.0.1 " , CFGF_NONE ) , // Adresse IP du serveur d'agrégation (défaut : boucle locale)
2009-07-02 13:12:51 +02:00
CFG_INT ( " aggregation_port " , AGGREGATE_DEFAULT_PORT , CFGF_NONE ) , // Port d'envoi sur le serveur d'agrégation
CFG_INT ( " listening_port " , LOC_REQUEST_DEFAULT_PORT , CFGF_NONE ) , // Port d'écoute des demandes des mobiles
2009-07-02 09:42:15 +02:00
# ifdef USE_PTHREAD
CFG_BOOL ( " keep_monitor " , cfg_false , CFGF_NONE ) , // Active le maintien actif du mode monitor
# endif // USE_PTHREAD
2009-04-15 14:15:49 +02:00
CFG_STR ( " rtap_iface " , " " , CFGF_NONE ) , // Interface radiotap utilisée pour la capture
CFG_STR ( " wifi_iface " , " " , CFGF_NONE ) , // Interface physique correspondante (utilisée pour récupérer l'adresse MAC)
2009-08-04 12:02:52 +02:00
CFG_BOOL ( " verbose " , cfg_false , CFGF_NONE ) , // Afficher les paquets capturés ou pas
2009-04-15 14:15:49 +02:00
CFG_END ( ) } ;
2009-07-02 13:12:51 +02:00
2009-04-15 14:15:49 +02:00
char * config_file ; // Nom du fichier de configuration
2009-07-02 09:42:15 +02:00
# endif // USE_CONFIG_FILE
2009-04-15 14:15:49 +02:00
int opt ; // Retour de getopt
/* L'option -f sert à spécifier un fichier de configuration alternatif,
* on regarde en premier si elle est présente */
do
opt = getopt ( argc , argv , OPTIONS ) ;
while ( opt ! = ' f ' & & opt ! = - 1 ) ;
if ( opt = = ' f ' )
2008-02-14 08:54:51 +01:00
{
2009-07-02 09:42:15 +02:00
# ifdef USE_CONFIG_FILE
2009-04-15 14:15:49 +02:00
config_file = malloc ( ( strlen ( optarg ) + 1 ) * sizeof ( char ) ) ;
strcpy ( config_file , optarg ) ;
2009-07-02 09:42:15 +02:00
# 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 " ) ;
# endif // USE_CONFIG_FILE
2009-04-15 14:15:49 +02:00
}
2009-07-02 09:42:15 +02:00
# ifdef USE_CONFIG_FILE
2009-04-15 14:15:49 +02:00
else // Si -f n'est pas présente, on utilise le fichier de config par défaut
{
config_file = malloc ( ( strlen ( DEFAULT_CONFIG_FILE ) + 1 ) * sizeof ( char ) ) ;
strcpy ( config_file , DEFAULT_CONFIG_FILE ) ;
}
/* Lecture du fichier de configuration */
cfg = cfg_init ( opts , CFGF_NONE ) ; // Initialisation des options
2009-08-04 12:02:52 +02:00
switch ( cfg_parse ( cfg , config_file ) )
2009-04-15 14:15:49 +02:00
{
2009-08-04 12:02:52 +02:00
case CFG_FILE_ERROR :
fprintf ( stderr , " Erreur lors de l'ouverture du fichier de configuration « %s » : %s. \n " , config_file , strerror ( errno ) ) ;
break ;
case CFG_PARSE_ERROR :
fprintf ( stderr , " Erreur lors de la lecture du fichier de configuration « %s » ! \n " , config_file ) ;
2009-04-15 14:15:49 +02:00
free ( config_file ) ;
return ERR_PARSING_CONFIG_FILE ;
}
free ( config_file ) ;
2009-07-02 09:42:15 +02:00
# endif // USE_CONFIG_FILE
2009-04-15 14:15:49 +02:00
/* Lecture des arguments de la ligne de commandes */
optind = 1 ; // On reprend l'analyse des arguments au début
while ( ( opt = getopt ( argc , argv , OPTIONS ) ) ! = - 1 )
{
switch ( opt )
{
case ' d ' :
2009-07-02 09:42:15 +02:00
SET_AGGREGATION_IP ( optarg ) ;
break ;
2009-07-02 13:12:51 +02:00
case ' f ' : // Fichier de configuration
// Déjà traité.
break ;
2009-07-02 09:42:15 +02:00
case ' k ' :
# ifdef USE_PTHREAD
SET_KEEP_MONITOR ( ) ;
# 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 " ) ;
# endif // USE_PTHREAD
2009-04-15 14:15:49 +02:00
break ;
2009-07-02 13:12:51 +02:00
case ' l ' :
SET_LISTENING_PORT ( strtol ( optarg , NULL , 0 ) ) ;
break ;
2009-08-04 12:02:52 +02:00
case ' m ' :
SET_MODE ( optarg [ 0 ] ) ;
break ;
2009-04-15 14:15:49 +02:00
case ' p ' :
2009-07-02 09:42:15 +02:00
SET_AGGREGATION_PORT ( strtol ( optarg , NULL , 0 ) ) ;
2009-04-15 14:15:49 +02:00
break ;
2009-08-04 12:02:52 +02:00
case ' q ' :
UNSET_VERBOSE ( ) ;
break ;
2009-04-15 14:15:49 +02:00
case ' r ' :
2009-07-02 09:42:15 +02:00
SET_RTAP_IFACE ( optarg ) ;
2009-04-15 14:15:49 +02:00
break ;
2009-08-04 12:02:52 +02:00
case ' v ' :
SET_VERBOSE ( ) ;
break ;
2009-04-15 14:15:49 +02:00
case ' w ' :
2009-07-02 09:42:15 +02:00
SET_WIFI_IFACE ( optarg ) ;
2009-04-15 14:15:49 +02:00
break ;
default :
print_usage ( argv [ 0 ] ) ;
return ERR_BAD_USAGE ;
}
}
/* Vérification des arguments */
2009-08-04 12:02:52 +02:00
switch ( GET_MODE ( ) )
{
case MODE_ACTIVE :
case MODE_MIXED :
case MODE_PASSIVE :
break ;
default :
fprintf ( stderr , " Erreur ! Mode « %c » inconnu. \n " , ( char ) GET_MODE ( ) ) ;
print_usage ( argv [ 0 ] ) ;
return ERR_BAD_USAGE ;
}
2009-07-02 09:42:15 +02:00
if ( GET_RTAP_IFACE ( ) [ 0 ] = = ' \0 ' )
2009-04-15 14:15:49 +02:00
{
fprintf ( stderr , " Erreur ! Vous devez spécifier une interface radiotap pour la capture. \n " ) ;
2008-02-14 08:54:51 +01:00
print_usage ( argv [ 0 ] ) ;
return ERR_BAD_USAGE ;
}
2009-07-02 09:42:15 +02:00
if ( GET_WIFI_IFACE ( ) [ 0 ] = = ' \0 ' )
2009-04-15 14:15:49 +02:00
{
# ifdef DEBUG
2009-07-02 09:42:15 +02:00
fprintf ( stderr , " Attention ! Aucune interface Wi-Fi spécifiée. Utilisation de l'interface radiotap (%s) à la place. \n " , GET_RTAP_IFACE ( ) ) ;
2009-04-15 14:15:49 +02:00
# endif // DEBUG
2009-07-02 09:42:15 +02:00
SET_WIFI_IFACE ( GET_RTAP_IFACE ( ) ) ;
2009-04-15 14:15:49 +02:00
}
# ifdef DEBUG
/* Affichage de la configuration */
fprintf ( stderr , " Configuration : \n " ) ;
2009-07-02 09:42:15 +02:00
# ifdef USE_CONFIG_FILE
2009-04-15 14:15:49 +02:00
cfg_print ( cfg , stderr ) ;
2009-07-02 09:42:15 +02:00
# else // USE_CONFIG_FILE
fprintf ( stderr , " \
aggregation_ip = \ " %s \" \n \
2009-07-02 13:12:51 +02:00
aggregation_port = % ld \ n \
listening_port = % ld \ n \
2009-07-02 09:42:15 +02:00
rtap_iface = \ " %s \" \n \
wifi_iface = \ " %s \" \n \
" ,
GET_AGGREGATION_IP ( ) ,
GET_AGGREGATION_PORT ( ) ,
2009-07-02 13:12:51 +02:00
GET_LISTENING_PORT ( ) ,
2009-07-02 09:42:15 +02:00
GET_RTAP_IFACE ( ) ,
GET_WIFI_IFACE ( )
) ;
# ifdef USE_PTHREAD
fprintf ( stderr , " keep_monitor = %s \n " ,
GET_KEEP_MONITOR ( ) ? " true " : " false "
) ;
# endif // USE_PTHREAD
# endif // USE_CONFIG_FILE
2009-04-15 14:15:49 +02:00
# endif // DEBUG
2008-02-14 08:54:51 +01:00
run = TRUE ;
/* Mise en place des gestionnaires de signaux */
sigemptyset ( & action . sa_mask ) ;
action . sa_handler = sigint_handler ;
sigaction ( SIGINT , & action , NULL ) ;
action . sa_handler = sigterm_handler ;
sigaction ( SIGTERM , & action , NULL ) ;
2009-07-02 09:42:15 +02:00
# ifdef USE_PTHREAD
2008-02-27 17:37:08 +01:00
/* Création du thread */
2009-07-02 09:42:15 +02:00
if ( GET_KEEP_MONITOR ( ) )
pthread_create ( & thread , NULL , ( void * ) & keep_mode_monitor , GET_WIFI_IFACE ( ) ) ;
# endif // USE_PTHREAD
2008-02-27 17:37:08 +01:00
2009-07-02 09:42:15 +02:00
get_mac_addr ( GET_WIFI_IFACE ( ) , mac ) ;
2008-02-14 08:54:51 +01:00
mac_string = mac_bytes_to_string ( mac ) ;
printf ( " Ma mac est : %s \n " , mac_string ) ;
free ( mac_string ) ;
2009-08-04 12:02:52 +02:00
ret = capture ( ) ;
2009-04-15 14:15:49 +02:00
2009-07-02 09:42:15 +02:00
# ifdef USE_CONFIG_FILE
2009-04-15 14:15:49 +02:00
cfg_free ( cfg ) ; // Nettoyage de la configuration
2009-07-02 09:42:15 +02:00
# endif // USE_CONFIG_FILE
2008-02-14 08:54:51 +01:00
printf ( " %s : fin. \n " , argv [ 0 ] ) ;
return ret ;
}
2008-03-14 11:31:04 +01:00
2009-07-02 09:42:15 +02:00
# ifdef USE_PTHREAD
2008-02-27 17:37:08 +01:00
/* Fonction du thread, qui surveille la liste et envoie les infos au serveur de localisation au bout du timeout */
void * keep_mode_monitor ( char * iface )
{
while ( run )
{
iface_mode_monitor ( iface ) ; // Passage de l'interface en mode Monitor.
2008-03-14 11:31:04 +01:00
sleep ( 1 ) ; // Pause de 1 secondes.
2008-02-27 17:37:08 +01:00
}
2009-07-02 09:42:15 +02:00
pthread_exit ( NULL ) ;
2008-02-27 17:37:08 +01:00
}
2009-07-02 09:42:15 +02:00
# endif // USE_PTHREAD
2008-02-27 17:37:08 +01:00
2008-02-14 08:54:51 +01:00
2009-08-04 12:02:52 +02:00
/* Capture des paquets en utilisant l'interface RTAP figurant dans les options.
* Les données capturées sont envoyées au serveur d ' aggrégation dont l ' IP
* figure é galement dans les options .
2008-02-22 16:04:49 +01:00
*/
2009-08-04 12:02:52 +02:00
int capture ( )
2008-02-14 08:54:51 +01:00
{
2008-02-22 16:04:49 +01:00
pcap_t * handle ; // Descripteur de capture de paquets
char errbuf [ PCAP_ERRBUF_SIZE ] ; // Message d'erreur
2008-02-14 08:54:51 +01:00
int sockfd ; // Descripteur de la socket vers le serveur d'aggrégation
struct sockaddr_in server , client ;
/* Sous-fonction de traitement des paquets capturés */
void got_packet ( u_char * args , const struct pcap_pkthdr * header , const u_char * packet )
{
2009-08-04 12:02:52 +02:00
// On appelle la fonction read_packet() avec les mêmes arguments,
// plus les informations concernant le serveur :
read_packet ( args , header , packet , sockfd , & server ) ;
2008-02-14 08:54:51 +01:00
}
2009-08-04 12:02:52 +02:00
handle = pcap_open_live ( GET_RTAP_IFACE ( ) , BUFSIZ , 1 , 1000 , errbuf ) ; // Début de la capture
2008-02-14 08:54:51 +01:00
if ( handle = = NULL ) // Le lancement de la capture a-t-il échoué ?
{
2009-08-04 12:02:52 +02:00
fprintf ( stderr , " Impossible d'ouvrir l'interface « %s » : %s \n " , GET_RTAP_IFACE ( ) , errbuf ) ;
2008-02-14 08:54:51 +01:00
return ERR_OPENING_IFACE ;
}
/* Ouverture de la socket UDP vers le serveur d'aggrégation */
2009-08-04 12:02:52 +02:00
sockfd = create_udp_sending_socket ( GET_AGGREGATION_IP ( ) , GET_AGGREGATION_PORT ( ) , & server , & client ) ;
2008-02-14 08:54:51 +01:00
if ( sockfd < 0 )
{
perror ( " Erreur ! Impossible de créer la socket vers le serveur d'aggrégation \n " ) ;
return ERR_CREATING_SOCKET ;
}
while ( run )
{
pcap_loop ( handle , 1 , got_packet , NULL ) ; // Collecte 1 paquet et appelle la fonction got_packet quand pcaploop a recupéré des paquets
}
pcap_close ( handle ) ; // Arrêt de la capture.
( void ) close ( sockfd ) ; // Fermeture de la socket
return 0 ;
}
2008-02-22 16:04:49 +01:00
/* Traite un paquet et l'envoie au serveur d'agrégation sur la socket UDP "sockfd", au serveur "server". */
2009-08-04 12:02:52 +02:00
void read_packet ( u_char * args , const struct pcap_pkthdr * header , const u_char * packet , int sockfd , struct sockaddr_in * server )
2008-02-14 08:54:51 +01:00
{
unsigned char * data = ( unsigned char * ) packet ; // Recopie dans data l'adresse du paquet capturé
2008-02-20 16:36:44 +01:00
unsigned short rtap_bytes ; // Taille des données reçues
2008-02-14 08:54:51 +01:00
unsigned int rtap_presentflags , rtap_position ;
2008-02-20 16:36:44 +01:00
couple_message couple ; // Message à envoyer à l'agrégateur
2008-02-14 08:54:51 +01:00
ssize_t nsent ; // Retour de sendto
BOOL check [ 15 ] ; // Champs présents
2008-02-20 16:36:44 +01:00
unsigned char raw_packet_type ; // Type du packet reçu (beacon, data...)
2008-03-14 11:31:04 +01:00
unsigned char raw_packet_flags ; // Flags de l'en-tête IEEE 802.11
2009-09-03 18:43:38 +02:00
unsigned short llc_packet_type = 0 ;
struct iphdr * packet_ip_header = NULL ; // Pointeur sur l'éventuel en-tête IP du paquet
struct udphdr * packet_udp_header = NULL ; // Pointeur sur l'éventuel en-tête UDP du paquet
2008-02-20 16:36:44 +01:00
char packet_type ; // Type de demande de localisation (demande, calibration)
2009-09-03 18:43:38 +02:00
BOOL is_explicit_packet = TRUE ; // Le paquet constitue-t-il une demande ?
2008-02-20 16:36:44 +01:00
int i ; // Compteur
2008-02-14 08:54:51 +01:00
2009-09-03 18:43:38 +02:00
2009-09-03 11:09:48 +02:00
/* Traitements communs */
2009-09-03 18:43:38 +02:00
2008-02-20 16:36:44 +01:00
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)
2010-07-02 13:04:00 +02:00
rtap_bytes = ntohs ( rtap_bytes ) ;
2009-07-02 11:10:22 +02:00
2008-02-20 16:36:44 +01:00
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)
2009-07-02 11:10:22 +02:00
2009-09-03 18:43:38 +02:00
if ( raw_packet_type = = RAW_PACKET_TYPE_DATA ) // Si le paquet est de type data,
{ // 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 ) ;
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
{
packet_ip_header = ( struct iphdr * ) & data [ rtap_bytes + IEEE80211_HEADER_SIZE + LLC_HEADER_SIZE ] ;
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 ( packet_ip_header - > protocol = = IPPROTO_UDP ) // Le protocole du paquet est UDP pour une demande explicite
{ // On teste le port de destination :
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 )
return ;
is_explicit_packet = FALSE ;
}
}
}
}
else if ( GET_MODE ( ) ! = MODE_ACTIVE ) // Mode passif ou mixte
{
is_explicit_packet = FALSE ;
bzero ( couple . mobile_ip_addr_bytes , 4 ) ; // On positionne l'IP à zéro
}
else // On est en mode actif et le paquet n'est pas IP donc pas une demande
return ;
}
else
{ // Le paquet n'est pas de la donnée donc pas une demande
if ( GET_MODE ( ) = = MODE_ACTIVE )
return ;
is_explicit_packet = FALSE ;
}
2009-07-02 11:10:22 +02:00
2008-03-14 11:31:04 +01:00
raw_packet_flags = data [ rtap_bytes + 1 ] ; // On récupère les flags 802.11, qui sont dans l'en-tête 802.11.
# ifdef DEBUG
2009-09-03 18:43:38 +02:00
printf ( " raw_packet_flags : %02x \n " , raw_packet_flags ) ;
if ( IS_RETRY ( raw_packet_flags ) )
printf ( " Ce paquet est un Retry. \n " ) ;
2009-04-15 14:15:49 +02:00
# endif // DEBUG
2008-02-20 16:36:44 +01:00
2009-09-03 11:09:48 +02:00
memcpy ( couple . ap_mac_addr_bytes , mac , 6 ) ; // On copie la MAC de l'AP
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
couple . start_time = header - > ts ; // L'heure de capture du paquet est contenue dans l'en-tête pcap
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 . request_time . tv_usec = 0 ;
2009-08-04 12:02:52 +02:00
/* Mode actif */
2009-09-03 18:43:38 +02:00
if ( is_explicit_packet
& & ( GET_MODE ( ) = = MODE_ACTIVE | | GET_MODE ( ) = = MODE_MIXED )
// FIXME : faut-il toujours ignorer les retry ?
2008-03-14 11:31:04 +01:00
& & ! IS_RETRY ( raw_packet_flags ) ) // et ce n'est pas un Retry.
2008-02-14 08:54:51 +01:00
{
2009-09-03 18:43:38 +02:00
packet_type = data [ rtap_bytes + IEEE80211_HEADER_SIZE + LLC_HEADER_SIZE + sizeof ( struct iphdr ) + sizeof ( struct udphdr ) ] ;
2008-02-14 08:54:51 +01:00
switch ( packet_type )
{
case PACKET_TYPE_NORMAL :
2009-08-04 12:02:52 +02:00
if ( GET_VERBOSE ( ) )
2009-09-03 11:09:48 +02:00
printf ( " \n Paquet explicite normal reçu. \n " ) ;
2008-02-14 08:54:51 +01:00
couple . direction = 0 ;
couple . x_position = 0 ;
couple . y_position = 0 ;
couple . z_position = 0 ;
break ;
case PACKET_TYPE_CALIBRATION :
2009-08-04 12:02:52 +02:00
if ( GET_VERBOSE ( ) )
2009-09-03 11:09:48 +02:00
printf ( " \n Paquet explicite de calibration reçu. \n " ) ;
2009-09-03 18:43:38 +02:00
couple . direction = data [ rtap_bytes + IEEE80211_HEADER_SIZE + LLC_HEADER_SIZE + sizeof ( struct iphdr ) + sizeof ( struct udphdr ) + 9 ] ;
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 ) ) ;
2008-02-14 08:54:51 +01:00
break ;
default :
2009-08-04 12:02:52 +02:00
if ( GET_VERBOSE ( ) )
2009-09-03 11:09:48 +02:00
printf ( " \n Paquet explicite bizarre reçu. \n " ) ;
fprintf ( stderr , " Erreur ! Type de paquet explicite inconnu (%d). \n " , packet_type ) ;
2009-09-03 18:43:38 +02:00
is_explicit_packet = FALSE ;
2008-02-14 08:54:51 +01:00
}
2009-09-03 18:43:38 +02:00
if ( ! is_explicit_packet )
2009-09-03 11:09:48 +02:00
{
if ( GET_MODE ( ) = = MODE_ACTIVE )
return ;
else if ( GET_VERBOSE ( ) )
printf ( " \n Ce paquet explicite bizarre sera traité comme implicite. \n " ) ;
}
else
2009-09-03 18:43:38 +02:00
memcpy ( & couple . request_time , & data [ rtap_bytes + IEEE80211_HEADER_SIZE + LLC_HEADER_SIZE + sizeof ( struct iphdr ) + sizeof ( struct udphdr ) + 1 ] , sizeof ( struct timeval ) ) ;
2009-09-03 11:09:48 +02:00
}
else if ( GET_MODE ( ) = = MODE_PASSIVE | | GET_MODE ( ) = = MODE_MIXED )
{
if ( GET_VERBOSE ( ) )
printf ( " \n Paquet implicite reçu. \n " ) ;
}
else // Mode actif uniquement, le paquet n'étant pas une demande explicite
return ;
2008-02-14 08:54:51 +01:00
2009-09-03 18:43:38 +02:00
2009-09-03 11:09:48 +02:00
/* Traitement de l'en-tête Radiotap */
2009-09-03 18:43:38 +02:00
2009-11-09 10:42:23 +01:00
memcpy ( & rtap_presentflags , & data [ RTAP_P_PRESENTFLAGS ] , RTAP_L_PRESENTFLAGS ) ; // Récupère les flags de l'en-tête rtap
// Note : on récupère les flags en big-endian (net-endianess), mais on
// travaille dessus comme si c'était du little-endian. Cela nous permet
// de déclarer un tableau de seulement 15 bits (au lieu de 32) car ce
// sont ces bits (de poids faible) qui nous intéressent. C'est un peu de
// la triche :-)
// Du coup, sur les architectures big-endian, il faut retourner les bits
// en faisant comme si on avait récupéré les flags en little-endian :
rtap_presentflags = le32toh ( rtap_presentflags ) ;
2008-02-14 08:54:51 +01:00
2009-09-03 11:09:48 +02:00
for ( i = 0 ; i < 15 ; i + + ) // Initialisation de la structure des champs présents
check [ i ] = FALSE ;
rtap_position = 8 ; // Début des champs déterminés par le present flag
2008-02-14 08:54:51 +01:00
2010-03-16 17:12:19 +01:00
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
2009-09-03 11:09:48 +02:00
{
if ( ( rtap_presentflags % 2 ) = = 1 )
{
switch ( i )
{
case RTAP_MACTS :
check [ RTAP_MACTS ] = TRUE ;
rtap_position + = RTAP_L_MACTS ;
break ;
case RTAP_FLAGS :
check [ RTAP_FLAGS ] = TRUE ;
rtap_position + = RTAP_L_FLAGS ;
break ;
case RTAP_RATE :
check [ RTAP_RATE ] = TRUE ;
rtap_position + = RTAP_L_RATE ;
break ;
case RTAP_CHANNEL :
rtap_position + = RTAP_L_CHANNEL ;
rtap_position + = RTAP_L_CHANNELTYPE ;
break ;
case RTAP_FHSS :
check [ RTAP_FHSS ] = TRUE ;
rtap_position + = RTAP_L_FHSS ;
break ;
case RTAP_ANTENNASIGNALDBM :
memcpy ( & ( couple . antenna_signal_dbm ) , & data [ rtap_position ] , RTAP_L_ANTENNASIGNALDBM ) ;
check [ RTAP_ANTENNASIGNALDBM ] = TRUE ;
if ( GET_VERBOSE ( ) )
printf ( " Antenna Signal : %d dBm \n " , couple . antenna_signal_dbm - 0x100 ) ;
rtap_position + = RTAP_L_ANTENNASIGNALDBM ;
break ;
case RTAP_ANTENNANOISEDBM :
check [ RTAP_ANTENNANOISEDBM ] = TRUE ;
rtap_position + = RTAP_L_ANTENNANOISEDBM ;
break ;
case RTAP_LOCKQUALITY :
check [ RTAP_LOCKQUALITY ] = TRUE ;
rtap_position + = RTAP_L_LOCKQUALITY ;
break ;
case RTAP_TXATTENUATION :
check [ RTAP_TXATTENUATION ] = TRUE ;
rtap_position + = RTAP_L_TXATTENUATION ;
break ;
case RTAP_TXATTENUATIONDB :
check [ RTAP_TXATTENUATIONDB ] = TRUE ;
rtap_position + = RTAP_L_TXATTENUATIONDB ;
break ;
case RTAP_TXATTENUATIONDBM :
check [ RTAP_TXATTENUATIONDBM ] = TRUE ;
rtap_position + = RTAP_L_TXATTENUATIONDBM ;
break ;
case RTAP_ANTENNA :
check [ RTAP_ANTENNA ] = TRUE ;
rtap_position + = RTAP_L_ANTENNA ;
break ;
case RTAP_ANTENNASIGNALDB :
check [ RTAP_ANTENNASIGNALDB ] = TRUE ;
rtap_position + = RTAP_L_ANTENNASIGNALDB ;
break ;
case RTAP_ANTENNANOISEDB :
check [ RTAP_ANTENNANOISEDB ] = TRUE ;
rtap_position + = RTAP_L_ANTENNANOISEDB ;
break ;
case RTAP_FCS :
check [ RTAP_FCS ] = TRUE ;
rtap_position + = RTAP_L_FCS ;
break ;
}
}
rtap_presentflags / = 2 ;
}
2008-02-14 08:54:51 +01:00
2009-09-03 11:09:48 +02:00
if ( GET_VERBOSE ( ) )
{
char * ap_mac_string = mac_bytes_to_string ( couple . ap_mac_addr_bytes ) ;
char * mobile_mac_string = mac_bytes_to_string ( couple . mobile_mac_addr_bytes ) ;
printf ( " \
2008-02-14 08:54:51 +01:00
* * * Couple à envoyer * * * \ n \
\ tMAC AP : % s \ n \
\ tMAC mobile : % s \ n \
2008-03-14 11:31:04 +01:00
\ tNuméro de séquence ( heure de la demande ) : % llu \ n \
\ tHeure d ' arrivée de la demande de localisation sur l ' AP : % llu \ n \
2008-02-14 08:54:51 +01:00
\ tSignal : % d dBm \ n \
\ tPosition X : % f \ n \
\ tPosition Y : % f \ n \
\ tPosition Z : % f \ n \
\ tDirection : % hhd \ n \
" ,
2009-09-03 11:09:48 +02:00
ap_mac_string ,
mobile_mac_string ,
timeval_to_ms ( couple . request_time ) ,
timeval_to_ms ( couple . start_time ) ,
couple . antenna_signal_dbm - 0x100 ,
couple . x_position ,
couple . y_position ,
couple . z_position ,
couple . direction
) ;
free ( ap_mac_string ) ;
free ( mobile_mac_string ) ;
2008-02-14 08:54:51 +01:00
}
2009-08-04 12:02:52 +02:00
2009-09-03 11:09:48 +02:00
/* Envoi du couple au serveur d'aggrégation */
nsent = sendto ( sockfd , ( void * ) & couple , sizeof ( couple ) , 0 , ( struct sockaddr * ) server , ( socklen_t ) sizeof ( * server ) ) ;
if ( nsent ! = ( ssize_t ) sizeof ( couple ) )
2009-08-04 12:02:52 +02:00
{
2009-09-03 11:09:48 +02:00
perror ( " Erreur lors de l'envoi du couple au serveur " ) ;
return ;
2009-08-04 12:02:52 +02:00
}
2008-02-14 08:54:51 +01:00
}
/* Fonction permettant de récupérer sa propre adresse MAC (interface 'eth') dans le tableau 'mac_bytes' */
void get_mac_addr ( char * eth , unsigned char mac_bytes [ 6 ] )
{
struct ifreq ifr ;
int sockfd ;
bzero ( mac_bytes , sizeof ( unsigned char ) * 6 ) ; // RàZ
sockfd = socket ( AF_INET , SOCK_DGRAM , 0 ) ;
if ( sockfd < 0 )
2008-02-27 17:37:08 +01:00
perror ( " Impossible d'ouvrir la socket pour récupérer l'adresse MAC " ) ;
2008-02-14 08:54:51 +01:00
strncpy ( ifr . ifr_name , eth , IFNAMSIZ ) ;
if ( ioctl ( sockfd , SIOCGIFFLAGS , & ifr ) < 0 )
return ;
if ( ioctl ( sockfd , SIOCGIFHWADDR , & ifr ) < 0 )
return ;
memcpy ( mac_bytes , ifr . ifr_hwaddr . sa_data , 6 ) ;
}
/* Affiche le mode d'emploi du programme */
void print_usage ( char * prog )
{
printf ( " Usage : \n \
2009-08-04 12:02:52 +02:00
\ 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 \
2009-07-02 09:42:15 +02:00
- 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 é té compilé avec le support de libconfuse . \ n \
2009-08-04 12:02:52 +02:00
- mode est le mode de fonctionnement : a ( ctif ) , p ( assif ) , m ( ixte ) ( par défaut : a ) . \ n \
2009-04-15 14:15:49 +02:00
- 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 \
2008-02-14 08:54:51 +01:00
- rtap_iface est l ' interface de capture radiotap . \ n \
2009-04-15 14:15:49 +02:00
- wifi_iface est l ' interface physique correspondant à rtap_iface ( par défaut : rtap_iface ) . \ n \
2009-07-02 09:42:15 +02:00
- L ' option - k active le maintien actif du mode monitor . À utiliser avec des pilotes bogués . Disponible uniquement si le programme a é té compilé avec le support des threads POSIX . \ n \
2009-08-04 12:02:52 +02:00
- 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 \
2009-04-15 14:15:49 +02:00
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 \
2009-08-04 12:02:52 +02:00
" ,
prog ,
AGGREGATE_DEFAULT_PORT ,
DEFAULT_CONFIG_FILE
) ;
2008-02-14 08:54:51 +01:00
}