218 lines
6.9 KiB
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 ;
|
|
}
|