[Listener] Add -v -q -m + other modifications

owlps-listener :
* Détail des erreurs d'ouverture / parcours du fichier de configuration.
* Ajout des option -v et -q permettant de choisir si le programme doit
  être verbeux ou silencieux.
* Modification des en-têtes de capture() et read_packet() pour utiliser
  la structure de configuration plutôt que des passages d'arguments.
  Note : peut-être serait-il bien de déplacer read_packet() dans
  capture() (à la place de got_packet) pour éviter le passage incessant
  des arguments sockfd et server.
* Ajout de l'option -m permettant de choisir le mode (actif, passif,
  mixte).
* Préparation de l'implantation du mode passif (dans read_packet).

git-svn-id: https://pif.pu-pm.univ-fcomte.fr/svn/loc@106 785a6c6c-259e-4ff1-8b91-dc31627914f0
This commit is contained in:
Matteo Cypriani 2009-08-04 10:02:52 +00:00
parent c2f18d715e
commit 24fef29457
2 changed files with 81 additions and 23 deletions

View File

@ -36,16 +36,16 @@
/* Arguments & configuration du programme */
#define OPTIONS "d:f:kl:p:r:w:" // Chaîne pour getopt
#define OPTIONS "m:d:f:kl:p:r:w:v" // Chaîne pour getopt
#define DEFAULT_CONFIG_FILE "/usr/local/etc/owlps/owlps-listener.conf"
enum {MODE_ACTIVE = 'a', MODE_PASSIVE = 'p', MODE_MIXED = 'm'} ;
/* En-têtes des fonctions */
#ifdef USE_PTHREAD
void* keep_mode_monitor(char *iface) ;
#endif // USE_PTHREAD
int capture(char *capture_iface, char *aggregation_ip, unsigned int aggregation_port, BOOL print_values) ;
void read_packet(u_char *args, const struct pcap_pkthdr *header, const u_char *packet, int sockfd, struct sockaddr_in *server, BOOL print_values) ;
int capture(void) ;
void read_packet(u_char *args, const struct pcap_pkthdr *header, const u_char *packet, int sockfd, struct sockaddr_in *server) ;
void get_mac_addr(char *eth, unsigned char mac_bytes[6]) ;
void print_usage(char *prog) ;
@ -56,6 +56,8 @@ void print_usage(char *prog) ;
*/
/* Macros utilisant libconfuse : */
#ifdef USE_CONFIG_FILE
#define SET_MODE(MODE) (cfg_setint(cfg, "mode", (MODE)))
#define GET_MODE() (cfg_getint(cfg, "mode"))
#define SET_AGGREGATION_IP(IP) (cfg_setstr(cfg, "aggregation_ip", (IP)))
#define GET_AGGREGATION_IP() (cfg_getstr(cfg, "aggregation_ip"))
#ifdef USE_PTHREAD
@ -70,9 +72,14 @@ void print_usage(char *prog) ;
#define GET_RTAP_IFACE() (cfg_getstr(cfg, "rtap_iface"))
#define SET_WIFI_IFACE(IFACE) (cfg_setstr(cfg, "wifi_iface", (IFACE)))
#define GET_WIFI_IFACE() (cfg_getstr(cfg, "wifi_iface"))
#define SET_VERBOSE() (cfg_setbool(cfg, "verbose", cfg_true))
#define UNSET_VERBOSE() (cfg_setbool(cfg, "verbose", cfg_false))
#define GET_VERBOSE() (cfg_getbool(cfg, "verbose"))
/* Macros utilisant la structure maison : */
#else // USE_CONFIG_FILE
#define SET_MODE(MODE) (options.mode = (MODE))
#define GET_MODE() (options.mode)
#define SET_AGGREGATION_IP(IP) (strncpy(options.aggregation_ip, (IP), 16))
#define GET_AGGREGATION_IP() (options.aggregation_ip)
#ifdef USE_PTHREAD
@ -87,6 +94,9 @@ void print_usage(char *prog) ;
#define GET_RTAP_IFACE() (options.rtap_iface)
#define SET_WIFI_IFACE(IFACE) (strncpy(options.wifi_iface, (IFACE), IFNAMSIZ+1))
#define GET_WIFI_IFACE() (options.wifi_iface)
#define SET_VERBOSE() (options.verbose = TRUE)
#define UNSET_VERBOSE() (options.verbose = FALSE)
#define GET_VERBOSE() (options.verbose)
#endif // USE_CONFIG_FILE

View File

@ -14,6 +14,7 @@ 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 :
char mode ;
char aggregation_ip[16] ;
long aggregation_port ;
long listening_port ;
@ -22,14 +23,17 @@ struct { // structure qui servira à stocker les options getopt
#endif // USE_PTHREAD
char rtap_iface[IFNAMSIZ + 1] ;
char wifi_iface[IFNAMSIZ + 1] ;
BOOL verbose ;
} options = { // et on initalise les options par défaut :
MODE_ACTIVE,
"127.0.0.1",
AGGREGATE_DEFAULT_PORT,
#ifdef USE_PTHREAD
FALSE,
#endif // USE_PTHREAD
"",
""
"",
FALSE
} ;
#endif // USE_CONFIG_FILE
@ -45,6 +49,7 @@ int main(int argc, char *argv[])
#ifdef USE_CONFIG_FILE // Si on utilise libconfuse, on déclare les options :
cfg_opt_t opts[] = { // Options reconnues par confuse dans le fichier de config
CFG_INT("mode", MODE_ACTIVE, CFGF_NONE), // Mode d'écoute : a pour actif, p pour passif, m pour mixte (défaut : a)
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
CFG_INT("listening_port", LOC_REQUEST_DEFAULT_PORT, CFGF_NONE), // Port d'écoute des demandes des mobiles
@ -53,6 +58,7 @@ int main(int argc, char *argv[])
#endif // USE_PTHREAD
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)
CFG_BOOL("verbose", cfg_false, CFGF_NONE), // Afficher les paquets capturés ou pas
CFG_END() } ;
char *config_file ; // Nom du fichier de configuration
@ -84,8 +90,13 @@ int main(int argc, char *argv[])
/* Lecture du fichier de configuration */
cfg = cfg_init(opts, CFGF_NONE) ; // Initialisation des options
if (cfg_parse(cfg, config_file) == CFG_PARSE_ERROR)
switch (cfg_parse(cfg, config_file))
{
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) ;
free(config_file) ;
return ERR_PARSING_CONFIG_FILE ;
}
@ -115,12 +126,21 @@ int main(int argc, char *argv[])
case 'l' :
SET_LISTENING_PORT(strtol(optarg, NULL, 0)) ;
break ;
case 'm' :
SET_MODE(optarg[0]) ;
break ;
case 'p' :
SET_AGGREGATION_PORT(strtol(optarg, NULL, 0)) ;
break ;
case 'q' :
UNSET_VERBOSE() ;
break ;
case 'r' :
SET_RTAP_IFACE(optarg) ;
break ;
case 'v' :
SET_VERBOSE() ;
break ;
case 'w' :
SET_WIFI_IFACE(optarg) ;
break ;
@ -131,6 +151,17 @@ int main(int argc, char *argv[])
}
/* Vérification des arguments */
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 ;
}
if (GET_RTAP_IFACE()[0] == '\0')
{
fprintf(stderr, "Erreur ! Vous devez spécifier une interface radiotap pour la capture.\n") ;
@ -192,7 +223,7 @@ wifi_iface = \"%s\"\n\
printf("Ma mac est : %s\n", mac_string) ;
free(mac_string) ;
ret = capture(GET_RTAP_IFACE(), GET_AGGREGATION_IP(), GET_AGGREGATION_PORT(), TRUE) ;
ret = capture() ;
#ifdef USE_CONFIG_FILE
cfg_free(cfg) ; // Nettoyage de la configuration
@ -222,10 +253,11 @@ void* keep_mode_monitor(char *iface)
/* Capture des paquets en utilisant l'interface "capture_iface".
* Les données capturées sont envoyées au serveur d'aggrégation dont l'IP est "aggregated_ip".
/* 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.
*/
int capture(char *capture_iface, char *aggregation_ip, unsigned int aggregation_port, BOOL print_values)
int capture()
{
pcap_t *handle ; // Descripteur de capture de paquets
char errbuf[PCAP_ERRBUF_SIZE] ; // Message d'erreur
@ -236,19 +268,21 @@ int capture(char *capture_iface, char *aggregation_ip, unsigned int aggregation_
/* Sous-fonction de traitement des paquets capturés */
void got_packet(u_char *args, const struct pcap_pkthdr *header, const u_char *packet)
{
read_packet(args, header, packet, sockfd, &server, print_values) ; // On appelle la fonction read_packet() avec les mêmes arguments, plus "print_values" qui indique si on doit afficher le paquet.
// On appelle la fonction read_packet() avec les mêmes arguments,
// plus les informations concernant le serveur :
read_packet(args, header, packet, sockfd, &server) ;
}
handle = pcap_open_live(capture_iface, BUFSIZ, 1, 1000, errbuf) ; // Début de la capture
handle = pcap_open_live(GET_RTAP_IFACE(), BUFSIZ, 1, 1000, errbuf) ; // Début de la capture
if (handle == NULL) // Le lancement de la capture a-t-il échoué ?
{
fprintf(stderr, "Impossible d'ouvrir l'interface « %s » : %s\n", capture_iface, errbuf) ;
fprintf(stderr, "Impossible d'ouvrir l'interface « %s » : %s\n", GET_RTAP_IFACE(), errbuf) ;
return ERR_OPENING_IFACE ;
}
/* Ouverture de la socket UDP vers le serveur d'aggrégation */
sockfd = create_udp_sending_socket(aggregation_ip, aggregation_port, &server, &client);
sockfd = create_udp_sending_socket(GET_AGGREGATION_IP(), GET_AGGREGATION_PORT(), &server, &client);
if (sockfd < 0)
{
perror("Erreur ! Impossible de créer la socket vers le serveur d'aggrégation \n");
@ -270,7 +304,7 @@ int capture(char *capture_iface, char *aggregation_ip, unsigned int aggregation_
/* Traite un paquet et l'envoie au serveur d'agrégation sur la socket UDP "sockfd", au serveur "server". */
void read_packet(u_char *args, const struct pcap_pkthdr *header, const u_char *packet, int sockfd, struct sockaddr_in *server, BOOL print_values)
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é
unsigned short rtap_bytes ; // Taille des données reçues
@ -311,7 +345,9 @@ void read_packet(u_char *args, const struct pcap_pkthdr *header, const u_char *p
}
#endif // DEBUG
if (raw_packet_type == RAW_PACKET_TYPE_DATA // Si le paquet est de type data,
/* Mode actif */
if ((GET_MODE() == MODE_ACTIVE || GET_MODE() == MODE_MIXED)
&& raw_packet_type == RAW_PACKET_TYPE_DATA // Si le paquet est de type data,
&& data[rtap_bytes + IEEE80211_HEADER_SIZE + LLC_HEADER_SIZE + 9] == RAW_PACKET_PROTO_UDP // et de protocole UDP (9 : position du champ "Protocol" de l'en-tête IP),
&& dst_port == LOC_REQUEST_DEFAULT_PORT // et le port de destination est le bon,
&& ! IS_RETRY(raw_packet_flags)) // et ce n'est pas un Retry.
@ -329,7 +365,7 @@ void read_packet(u_char *args, const struct pcap_pkthdr *header, const u_char *p
switch(packet_type)
{
case PACKET_TYPE_NORMAL :
if (print_values)
if (GET_VERBOSE())
printf("\nPaquet normal reçu.\n") ;
couple.direction = 0 ;
couple.x_position = 0 ;
@ -338,7 +374,7 @@ void read_packet(u_char *args, const struct pcap_pkthdr *header, const u_char *p
break ;
case PACKET_TYPE_CALIBRATION :
if (print_values)
if (GET_VERBOSE())
printf("\nPaquet de calibration reçu.\n") ;
couple.direction = data[rtap_bytes + IEEE80211_HEADER_SIZE + LLC_HEADER_SIZE + IP_HEADER_SIZE + UDP_HEADER_SIZE + 9];
memcpy(&couple.x_position, &data[rtap_bytes + IEEE80211_HEADER_SIZE + LLC_HEADER_SIZE + IP_HEADER_SIZE + UDP_HEADER_SIZE + 10], sizeof(float));
@ -347,7 +383,7 @@ void read_packet(u_char *args, const struct pcap_pkthdr *header, const u_char *p
break ;
default :
if (print_values)
if (GET_VERBOSE())
printf("\nPaquet bizarre reçu.\n") ;
fprintf(stderr, "Erreur ! Type de paquet inconnu (%d).\n", packet_type) ;
return ;
@ -392,7 +428,7 @@ void read_packet(u_char *args, const struct pcap_pkthdr *header, const u_char *p
case RTAP_ANTENNASIGNALDBM:
memcpy(&(couple.antenna_signal_dbm), &data[rtap_position], RTAP_L_ANTENNASIGNALDBM) ;
check[RTAP_ANTENNASIGNALDBM] = TRUE;
if (print_values)
if (GET_VERBOSE())
printf("Antenna Signal : %d dBm\n", couple.antenna_signal_dbm - 0x100);
rtap_position += RTAP_L_ANTENNASIGNALDBM ;
break ;
@ -437,7 +473,7 @@ void read_packet(u_char *args, const struct pcap_pkthdr *header, const u_char *p
rtap_presentflags /= 2 ;
}
if (print_values)
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) ;
@ -475,6 +511,12 @@ void read_packet(u_char *args, const struct pcap_pkthdr *header, const u_char *p
return ;
}
}
/* Mode passif */
else if (GET_MODE() == MODE_PASSIVE || GET_MODE() == MODE_MIXED)
{
/* TODO */
}
}
@ -510,12 +552,18 @@ void get_mac_addr(char *eth, unsigned char mac_bytes[6])
void print_usage(char *prog)
{
printf("Usage :\n\
\t%s [-f config_file] [-d ip_agrégation] [-l listening_port] [-p port_agrégation] -r rtap_iface [-w wifi_iface] [-k]\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\
- 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\
- mode est le mode de fonctionnement : a(ctif), p(assif), m(ixte) (par défaut : a).\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\
- wifi_iface est l'interface physique correspondant à rtap_iface (par défaut : rtap_iface).\n\
- 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\
- 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\
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\
", prog, AGGREGATE_DEFAULT_PORT, DEFAULT_CONFIG_FILE) ;
",
prog,
AGGREGATE_DEFAULT_PORT,
DEFAULT_CONFIG_FILE
) ;
}