owlps/loc-mobile/code/librtapanalyser/tx.c

218 lines
6.9 KiB
C

/*
* This is the rtapanalyser library, Wi-Fi packet sniffer and analyser,
* thanks to the radiotap header of each packet.
*/
#include "rtapanalyser.h"
/* Options du programme */
#define DEFAULT_IFACE "rtap0" // Interface de capture par défaut.
#define DEFAULT_CAPTURE_TIME 5000 // Temps de capture par défaut en milli-secondes.
#define MAX_FILENAME_LENGTH 500 // Longueur maximale du nom des fichiers.
#define MAX_IFACENAME_LENGTH 50 // Longueur maximale du nom de l'interface de capture.
#define MAX_OPT_LENGTH 5 // Longueur maximale des options sur la ligne de commandes.
#define NB_OPTIONS 7 // Nombre d'options.
enum {NUM_OPT_HELP, NUM_OPT_IFACE, NUM_OPT_CAPTURE_TIME, NUM_OPT_OUTPUT, NUM_OPT_INPUT, NUM_OPT_VERB, NUM_OPT_VERB2} ; // Liste des numéros d'options.
#define OPT_HELP "-h" // Option d'affichage de l'aide.
#define OPT_OUTPUT "-o" // Option d'enregistrement des résultats dans un fichier.
#define OPT_INPUT "-i" // Option de lecture des trames enregistrées avec -o.
#define OPT_IFACE "-d" // Option de spécification de l'interface de capture.
#define OPT_CAPTURE_TIME "-t" // Option de spécification du temps de capture.
#define OPT_VERB "-v" // Option de verbosité.
#define OPT_VERB2 "-vv" // Option de verbosité maximale.
#define ERR_BAD_OPTION 50 // Code d'erreur en cas de mauvaise option de ligne de commande.
#define ERR_OPT_INPUT_OUTPUT 51 // Erreur d'incompatibilité entre les deux options entrée et sortie de/vers fichier.
/* Affiche la syntaxe du programme */
void print_usage(char *prog)
{
printf("Usage :\n\
\t%s -h\n\
\t%s [ -v ] [ -i fichier ]\n\
\t%s [ -v | -vv ] [ -d interface ] [ -t temps ] [ -o fichier ]\n\
", prog, prog, prog) ;
}
/* Affiche la syntaxe du programme */
void print_usage_only(char *prog)
{
putchar('\n') ;
print_usage(prog) ;
printf("\nPour afficher l'aide, tapez « %s -h ».\n", prog) ;
}
/* Affiche l'aide complète du programme */
void print_help(char *prog)
{
print_usage(prog) ;
printf("\n\
Options :\n\
\t-h : affiche cette aide.\n\
\t-v : affichage détaillé.\n\
\t-vv : affichage très détaillé.\n\
\t-i fichier : lit les informations depuis le fichier « fichier » plutôt que de tenter de capturer des paquets.\n\
\t-o fichier : enregistre les informations capturées dans le fichier « fichier ».\n\
\t-d interface : les paquets sont capturés sur l'interface réseau « interface ». Par défaut, « %s » est utilisée.\n\
\t-t temps : les paquets sont capturés pendant « temps » millisecondes. Par défaut, « temps » vaut %d.\n\
\n\
Note : votre interface de capture doit être en mode « monitor », et supporter radiotap.\n\
", DEFAULT_IFACE, DEFAULT_CAPTURE_TIME) ;
}
/* Analyse les options de la ligne de commandes */
void read_options(int argc, char **argv, BOOL *options, char *capture_iface, int *capture_time, char *file)
{
int i ; // Compteur.
char num_prev_opt = -1 ; // Numéro de la dernière option lue, si elle prend un argument. Ne doit pas être positionné lors de la lecture des options ne prenant pas d'argument ; doit être repositionnée à -1 après le traitement de l'option.
/* Initialisation du tableau d'options à FALSE */
for (i = 0 ; i < NB_OPTIONS ; i++)
options[i] = FALSE ;
/* Lecture des options */
for (i = 1 ; i < argc ; i++)
{
if (num_prev_opt != -1)
{
/* Cas des options suivies d'un argument (exemple : « -o fichier ») */
switch (num_prev_opt)
{
case NUM_OPT_OUTPUT :
case NUM_OPT_INPUT :
strncpy(file, argv[i], MAX_FILENAME_LENGTH) ;
num_prev_opt = -1 ;
break ;
case NUM_OPT_IFACE :
strncpy(capture_iface, argv[i], MAX_IFACENAME_LENGTH) ;
num_prev_opt = -1 ;
break ;
case NUM_OPT_CAPTURE_TIME :
*capture_time = atoi(argv[i]) ;
num_prev_opt = -1 ;
break ;
}
}
else if (strncmp(argv[i], OPT_HELP, MAX_OPT_LENGTH) == 0)
{
print_help(argv[0]) ;
exit(0) ;
}
else if (strncmp(argv[i], OPT_IFACE, MAX_OPT_LENGTH) == 0)
{
options[NUM_OPT_IFACE] = TRUE ;
num_prev_opt = NUM_OPT_IFACE ;
}
else if (strncmp(argv[i], OPT_CAPTURE_TIME, MAX_OPT_LENGTH) == 0)
{
options[NUM_OPT_CAPTURE_TIME] = TRUE ;
num_prev_opt = NUM_OPT_CAPTURE_TIME ;
}
else if (strncmp(argv[i], OPT_OUTPUT, MAX_OPT_LENGTH) == 0)
{
options[NUM_OPT_OUTPUT] = TRUE ;
num_prev_opt = NUM_OPT_OUTPUT ;
}
else if (strncmp(argv[i], OPT_INPUT, MAX_OPT_LENGTH) == 0)
{
options[NUM_OPT_INPUT] = TRUE ;
num_prev_opt = NUM_OPT_INPUT ;
}
else if (strncmp(argv[i], OPT_VERB, MAX_OPT_LENGTH) == 0)
{
if (options[NUM_OPT_VERB] == TRUE) // Si l'option est déjà présente,
options[NUM_OPT_VERB2] = TRUE ; // on active le deuxième niveau de verbosité.
else
options[NUM_OPT_VERB] = TRUE ;
}
else if (strncmp(argv[i], OPT_VERB2, MAX_OPT_LENGTH) == 0)
{
options[NUM_OPT_VERB] = TRUE ;
options[NUM_OPT_VERB2] = TRUE ;
}
else
{
print_usage_only(argv[0]) ;
fprintf(stderr, "Option inconnue « %s » !\n\n", argv[i]) ;
exit(ERR_BAD_OPTION) ;
}
}
/* Vérifications des options */
if (options[NUM_OPT_OUTPUT] == TRUE || options[NUM_OPT_INPUT] == TRUE)
if (file[0] == '\0')
{
fprintf(stderr, "Vous devez spécifier un nom de fichier après les options -i et -o !\n") ;
print_usage_only(argv[0]) ;
exit(ERR_FILENAME) ;
}
if (options[NUM_OPT_OUTPUT] == TRUE && options[NUM_OPT_INPUT] == TRUE)
{
fprintf(stderr, "Les options -i et -o sont incompatibles !\n") ;
print_usage_only(argv[0]) ;
exit(ERR_OPT_INPUT_OUTPUT) ;
}
}
int main(int argc, char **argv)
{
BOOL options[NB_OPTIONS] ; // Tableau des options présentes.
char capture_iface[MAX_IFACENAME_LENGTH] = DEFAULT_IFACE ; // Interface d'entrée
int capture_time = DEFAULT_CAPTURE_TIME ; // Temps de capture
char file[MAX_FILENAME_LENGTH] = "\0" ; // Nom du fichier à lire ou écrire.
mac_list *results = NULL ;
int ret = 0 ; // Valeur de retour des fonctions appelées.
/* Lecture des options de la ligne de commande */
read_options(argc, argv, options, capture_iface, &capture_time, file) ;
if (options[NUM_OPT_INPUT] == TRUE) // Si l'option INPUT est présente,
{
if ((ret = read_mac_list_from_file(file, &results)) != 0) // Lecture du fichier.
return ret ;
print_mac_list(results, options[NUM_OPT_VERB]) ; // Affichage.
free_mac_list(&results) ; // Nettoyage
return 0 ;
}
printf("Interface de capture : %s\nTemps de capture : %d\n\n", capture_iface, capture_time) ;
if ((ret = capture(capture_iface, capture_time, &results, options[NUM_OPT_VERB])) != 0) // Capture de paquets.
return ret ; // On quitte avec le code d'erreur si la capture a mal fini.
print_mac_list(results, options[NUM_OPT_VERB2]) ; // Affichage des paquets capturés.
if (options[NUM_OPT_OUTPUT] == TRUE) // Si l'option OUTPUT est présente,
ret = write_mac_list_to_file(file, results) ;
free_mac_list(&results) ; // Nettoyage
return ret ;
}