314 lines
10 KiB
C
314 lines
10 KiB
C
/*
|
|
* This file is part of the rtap localisation project.
|
|
*/
|
|
|
|
|
|
#include "ap.h"
|
|
|
|
|
|
unsigned char mac[6] ; // Adresse MAC de l'AP
|
|
|
|
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
struct sigaction action ; // Structure de mise en place des gestionnaires de signaux
|
|
char *mac_string ; // MAC de l'AP sous forme de chaîne
|
|
int ret ; // Code de retour du programme
|
|
|
|
if (argc != ARGC)
|
|
{
|
|
print_usage(argv[0]) ;
|
|
return ERR_BAD_USAGE ;
|
|
}
|
|
|
|
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) ;
|
|
|
|
get_mac_addr(argv[ARGV_WIFI_IFACE], mac) ;
|
|
mac_string = mac_bytes_to_string(mac) ;
|
|
printf("Ma mac est : %s\n", mac_string) ;
|
|
free(mac_string) ;
|
|
|
|
ret = capture(argv[ARGV_RTAP_IFACE], argv[ARGV_AGGREG_IP], TRUE) ;
|
|
|
|
printf("%s : fin.\n", argv[0]) ;
|
|
return ret ;
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 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".
|
|
*/
|
|
int capture(char *capture_iface, char *aggregated_ip, BOOL print_values)
|
|
{
|
|
pcap_t *handle ; // Descripteur de capture de paquets
|
|
char errbuf[PCAP_ERRBUF_SIZE] ; // Message d'erreur
|
|
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)
|
|
{
|
|
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.
|
|
}
|
|
|
|
|
|
handle = pcap_open_live(capture_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) ;
|
|
return ERR_OPENING_IFACE ;
|
|
}
|
|
|
|
/* Ouverture de la socket UDP vers le serveur d'aggrégation */
|
|
sockfd = create_udp_sending_socket(aggregated_ip, AGGREGATE_DEFAULT_PORT, &server, &client);
|
|
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 ;
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 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)
|
|
{
|
|
unsigned char *data = (unsigned char *) packet ; // Recopie dans data l'adresse du paquet capturé
|
|
unsigned short rtap_bytes ; // Taille des données reçues
|
|
unsigned int rtap_presentflags, rtap_position ;
|
|
couple_message couple ; // Message à envoyer à l'agrégateur
|
|
ssize_t nsent ; // Retour de sendto
|
|
BOOL check[15] ; // Champs présents
|
|
unsigned char raw_packet_type ; // Type du packet reçu (beacon, data...)
|
|
char packet_type ; // Type de demande de localisation (demande, calibration)
|
|
unsigned short dst_port ; // Port destination du paquet capturé
|
|
int i ; // Compteur
|
|
|
|
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)
|
|
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)
|
|
memcpy((unsigned char*) &dst_port, &data[rtap_bytes+24+8+20+3], 1) ; // On récupère le port de destination (mais il faut retourner les deux octets)
|
|
memcpy(&((unsigned char*) &dst_port)[1], &data[rtap_bytes+24+8+20+2], 1) ; // (20 : longueur de l'en-tête IP, le port de destination étant les troisièmes et quatrièmes octet suivant).
|
|
|
|
if (raw_packet_type == RAW_PACKET_TYPE_DATA // Si le paquet est de type data,
|
|
&& data[rtap_bytes+24+8+9] == RAW_PACKET_PROTO_UDP // et de protocole UDP (24 : en-tête 802.11, 8 : en-tête LLC, 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.
|
|
{
|
|
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
|
|
gettimeofday(&couple.start_time, NULL) ;
|
|
|
|
packet_type = data[rtap_bytes+24+8+20+8] ;
|
|
|
|
memcpy(&couple.request_time, &data[rtap_bytes+24+8+20+8+1], sizeof(struct timeval));
|
|
|
|
|
|
switch(packet_type)
|
|
{
|
|
case PACKET_TYPE_NORMAL :
|
|
if (print_values)
|
|
printf("\nPaquet normal reçu.\n") ;
|
|
couple.direction = 0 ;
|
|
couple.x_position = 0 ;
|
|
couple.y_position = 0 ;
|
|
couple.z_position = 0 ;
|
|
break ;
|
|
|
|
case PACKET_TYPE_CALIBRATION :
|
|
if (print_values)
|
|
printf("\nPaquet de calibration reçu.\n") ;
|
|
couple.direction = data[rtap_bytes+24+8+20+8 + 9];
|
|
memcpy(&couple.x_position, &data[rtap_bytes+24+8+20+8+10], sizeof(float));
|
|
memcpy(&couple.y_position, &data[rtap_bytes+24+8+20+8+14], sizeof(float));
|
|
memcpy(&couple.z_position, &data[rtap_bytes+24+8+20+8+18], sizeof(float));
|
|
break ;
|
|
|
|
default :
|
|
if (print_values)
|
|
printf("\nPaquet bizarre reçu.\n") ;
|
|
fprintf(stderr, "Erreur ! Type de paquet inconnu (%d).\n", packet_type) ;
|
|
return ;
|
|
}
|
|
|
|
|
|
memcpy(&rtap_presentflags, &data[RTAP_P_PRESENTFLAGS], RTAP_L_PRESENTFLAGS); // Récupère les flags de l'en-tête rtap
|
|
|
|
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
|
|
|
|
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
|
|
{
|
|
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 (print_values)
|
|
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 ;
|
|
}
|
|
|
|
if (print_values)
|
|
{
|
|
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("\
|
|
*** Couple à envoyer ***\n\
|
|
\tMAC AP : %s\n\
|
|
\tMAC mobile : %s\n\
|
|
\tNuméro de séquence (heure de la demande) : %lu\n\
|
|
\tHeure d'arrivée de la demande de localisation sur l'AP : %lu\n\
|
|
\tSignal : %d dBm\n\
|
|
\tPosition X : %f\n\
|
|
\tPosition Y : %f\n\
|
|
\tPosition Z : %f\n\
|
|
\tDirection : %hhd\n\
|
|
",
|
|
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) ;
|
|
}
|
|
|
|
/* 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))
|
|
{
|
|
perror("Erreur lors de l'envoi du couple au serveur ") ;
|
|
return ;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 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)
|
|
printf("Can't open socket\n") ;
|
|
|
|
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\
|
|
\t%s ip_agrégation rtap_iface wifi_iface\n\
|
|
- ip_agrégation est l'adresse IP du serveur d'agrégation.\n\
|
|
- rtap_iface est l'interface de capture radiotap.\n\
|
|
- wifi_iface est l'interface physique correspondant à rtap_iface.\n\
|
|
", prog) ;
|
|
}
|