TP4 : Réseaux locaux - transmission et analyse des trames Ethernet (sur architectures x86 et ARM)



Documents pareils
1. Fonctionnement de l Internet 2. Protocoles applicatifs 3. Programmation réseau

Programmation système de commandes en C

Cahier des charges. driver WIFI pour chipset Ralink RT2571W. sur hardware ARM7

1. Structure d un programme C. 2. Commentaire: /*..texte */ On utilise aussi le commentaire du C++ qui est valable pour C: 3.

Travaux Pratiques Introduction aux réseaux IP

DNS Server RPC Interface buffer overflow. Céline COLLUMEAU Nicolas BODIN

Couche application. La couche application est la plus élevée du modèle de référence.

Applications client/serveur TCP/IP - Sockets Rappels. C.Crochepeyre Applications CS 1

Skype (v2.5) Protocol Data Structures (French) Author : Ouanilo MEDEGAN

II/ Le modèle OSI II.1/ Présentation du modèle OSI(Open Systems Interconnection)

Présentation du modèle OSI(Open Systems Interconnection)

Archivage Messagerie Evolution pour usage HTML en utilisant Hypermail

ETHEREAL. Introduction. 1. Qu'est-ce qu'ethereal Historique Le statut d'ethereal

OS Réseaux et Programmation Système - C5

Exercice sur les Dockers

Introduction. Adresses

Communication par sockets

Outils d'analyse de la sécurité des réseaux. HADJALI Anis VESA Vlad

Protocoles réseaux. Abréviation de Binary Digit. C'est la plus petite unité d'information (0, 1).

Plan. École Supérieure d Économie Électronique. Plan. Chap 9: Composants et systèmes de sécurité. Rhouma Rhouma. 21 Juillet 2014

L3 informatique Réseaux : Configuration d une interface réseau

Le prototype de la fonction main()

Firewall. Souvent les routeurs incluent une fonction firewall qui permet une première sécurité pour le réseau.

TP2 - Conguration réseau et commandes utiles. 1 Généralités. 2 Conguration de la machine. 2.1 Commande hostname

Introduction à la Programmation Parallèle: MPI

Internet Protocol. «La couche IP du réseau Internet»

STS SE. FreeRTOS. Programmation réseau WIFI. Programmation réseau. Socket Tcp. FlyPort smart Wi-Fi module

TP 1 : LES COMMANDES RESEAUX Matière: RESEAUX LOCAUX

DHCP et NAT. Cyril Rabat Master 2 ASR - Info Architecture des réseaux d entreprise

Master d'informatique 1ère année. Réseaux et protocoles. Architecture : les bases

Configuration réseau Basique

Chapitre 6 -TP : Support Réseau des Accès Utilisateurs

Systèmes et Réseaux (ASR 2) - Notes de cours Cours 14

Chapitre I. La couche réseau. 1. Couche réseau 1. Historique de l Internet

Communication sous UNIX les sockets

Capture, Filtrage et Analyse de trames ETHERNET avec le logiciel Wireshark. Etape 1 : Lancement des machines virtuelles VMWARE et de Wireshark

Réseaux IUP2 / 2005 IPv6

Internet Le service de noms - DNS

Téléphonie Cisco. - CME Manager Express = Logiciel dans un routeur, version simplifiée du call manager.

Année Universitaire session 1 d automne Parcours : CSB5 Licence 3 STS Informatique

Couche Transport TCP et UDP

Réseau - VirtualBox. Sommaire

DIFF AVANCÉE. Samy.

Programmation client-serveur sockets - RPC

Cours 6 : Tubes anonymes et nommés

Communication inter-processus (IPC) : tubes & sockets. exemples en C et en Java. F. Butelle

L annuaire et le Service DNS

I>~I.J 4j1.bJ1UlJ ~..;W:i 1U

Les possibilités de paramétrage réseau des logiciels de virtualisation sont les suivantes quant à la connexion réseau :

Projet de programmation (IK3) : TP n 1 Correction

Sécuriser son réseau. Sécuriser son réseau Philippe Weill (IPSL/LATMOS) Frédéric Bongat (SSI/GOUV/FR)

SYSTEME DE GESTION DES ENERGIES EWTS EMBEDDED WIRELESS TELEMETRY SYSTEM

Le Langage C Version 1.2 c 2002 Florence HENRY Observatoire de Paris Université de Versailles florence.henry@obspm.fr

DHCPD v3 Installation et configuration

Rappels réseaux TCP/IP

I. Adresse IP et nom DNS

Configuration automatique

3IS - Système d'exploitation linux - Programmation système

Protocoles IP (2/2) M. Berthet. Les illustrations sont tirées de l ouvrage de Guy Pujolle, Cours réseaux et Télécom Contributions : S Lohier

Rappel: Le routage dans Internet. Contraintes. Environnement et contraintes. La décision dans IP du routage: - Table de routage:

La qualité de service (QoS)

SECURIDAY 2012 Pro Edition

NOTICE INSTALLATION. ARCHANGE Simplex Office N&B/Couleur KONICA MINOLTA BUSINESS SOLUTIONS FRANCE

Les Réseaux Privés Virtuels (VPN) Définition d'un VPN

Mr. B. Benaissa. Centre universitaire Nâama LOGO

CONVERTISSEUR RS 232/485 NOTICE

Bases de programmation. Cours 5. Structurer les données

Plan. Programmation Internet Cours 3. Organismes de standardisation

Introduction à l'analyse réseau Philippe Latu philippe.latu(at)linux-france.org

Les Virtual LAN. F. Nolot. Master 1 STIC-Informatique 1

Plan. Rappels sur Netflow v1 v8. Netflow v9. Collecteur UTC «IPFlow» Cisco IOS : Implémentation de Netflow IPv6

Réseau : Interconnexion de réseaux, routage et application de règles de filtrage.

Cours de C. Petits secrets du C & programmation avancée. Sébastien Paumier

Administration du WG302 en SSH par Magicsam

Chapitre 2 Machines virtuelles et services

Playing with ptrace() for fun and profit

Internet Group Management Protocol (IGMP) Multicast Listener Discovery ( MLD ) RFC 2710 (MLD version 1) RFC 3810 (MLD version 2)

Mise en place d un cluster NLB (v1.12)

Réseaux et protocoles Damien Nouvel

Le protocole TCP. Services de TCP

Dynamic Host Configuration Protocol

COMMANDES RÉSEAUX TCP/IP WINDOWS.

INTRODUCTION A JAVA. Fichier en langage machine Exécutable

Cours d Algorithmique-Programmation 2 e partie (IAP2): programmation 24 octobre 2007impérative 1 / 44 et. structures de données simples

Administration Réseau sous Ubuntu SERVER Serveur DHCP

Surveillance de Scripts LUA et de réception d EVENT. avec LoriotPro Extended & Broadcast Edition

Contrôleur de communications réseau. Guide de configuration rapide DN

TP : STATION BLANI 2000 SIMULATION DU RESEAU INFORMATIQUE

FILTRAGE de PAQUETS NetFilter

2. MAQUETTAGE DES SOLUTIONS CONSTRUCTIVES. 2.2 Architecture fonctionnelle d un système communicant.

EPREUVE OPTIONNELLE d INFORMATIQUE CORRIGE

Développement d un logiciel de messagerie instantanée avec Dotnet (version simplifiée)

Le Multicast. A Guyancourt le

Télécommunications. IPv4. IPv4 classes. IPv4 réseau locaux. IV - IPv4&6, ARP, DHCP, DNS

Technique de défense dans un réseau

Les ACL Cisco. F. Nolot Master 2 Professionnel STIC-Informatique 1

NanoSense. Protocole Modbus de la sonde Particules P4000. (Version 01F)

INITIATION AU LANGAGE C SUR PIC DE MICROSHIP

DHCP. Dynamic Host Configuration Protocol

Introduction au langage C

Transcription:

TP4 : Réseaux locaux - transmission et analyse des trames Ethernet (sur architectures x86 et ARM) Dans ce TP nous allons écrire/utiliser des applications de transfert des messages et des fichiers directemment au niveau de la couche physique Ethernet. La configuration du TP est basée sur 6 ordinateurs PC traditionnels (architecture x86) et 6 cartes Raspberry-Pi conçus sur l'architecture ARM. Le système d'exploitation est Ubuntu (Debian) pour les PC et Raspbian (Debian) pour les Raspberry PI. L'ensemble est connecté en réseau local avec les adresses IP distribuées dynamiquement par le protocole DHCP. Le développement de 2 applications : 1. Emission/diffusion et réception des fichiers 2. Sniffing des trames Ethernet avec les paquets IP doit être réalisé en mode root. Seulement l'utilisateur root a les droits d'exploitation de l'interface Ethernet par le biais de la programmation avec raw-sockets. Nous allons donc contourner la pile de protocoles (Ethernet/IP/TCP-UDP) pour s'attaquer directemment à la couche physique. En plus nous allons communiquer entre les systèmes basés sur les architectures matérielles différentes : x86 et ARM. Avant de se lancer dans la programmation nous proposons de lire le texte suivant concernant l'interface de programmation raw-sockets.

Introduction à la programmation avec l'api Raw-Sockets Dans les TP précédants nous avons dévellopé un certain nombre d'applications s'appuyant sur les primitives socket fonctionnant au niveau de la couche de transport en mode datagramme (protocole UDP) et en mode connecté (protocole TCP). Un programmeur avec les droits de root peut ếgalement accéder aux niveaux inférieurs de la pile TCP- UDP/IP/Ethernet par le biais des mécanismes raw-socket. On commence par la création d'un socket en mode raw: int s; s = socket(pf_packet, SOCK_RAW, htons(eth_p_all)); Le socket s peut fonctionner directement au niveau des paquets envoyés/réçus par le protocole Ethernet. Dans une trame Ethernet on peut insérer un paquet IP et un segment TCP ou un datagramme UDP. Dans ce contexte on peut, soit suivre les standards Internet et reproduire le fonctionnement des protocoles IP/TCP-UDP soit développer sa propre pile de protocoles. Envoi d'une trame Ethernet L'envoi d'une trame Ethernet nécessite la préparation de l'adresse source (6 octets), l'adresse de destination (6 octets), le type de protocole utilisateur (2 octets) plus les données utilisateur à transmettre par la trame. Fig.1. Trame Ethernet

Rappelons qu'une trame Ethernet est composée: de 2 adresses (source et destination) de 6 octets, d'un champs de contrôle de 2 octets, d'un champs de données de min 46 et max 1500 octets, et de la somme de test sur 4 octet qui est générée automatiquement par le l'interface. La structure ci-dessous doit être préparée avant son utilisation dans la fonction sendto(). struct sockaddr_ll destaddr; // addresse d'un socket au niveau de lien Les adresses Ethernet peuvent être préparées/initialisées comme suit: MacAddress localmac = 0x00,0x00,0x00,0x00,0x00,0x00; //MacAddress localmac = 0x00,0x17,0xB3,0x00,0xa0,0x20; MacAddress destmac = 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF; //MacAddress destmac= 0x00,0xB0,0xD0,0x4C,0xD5,0xC6; La trame avec ses données est préparée dans un tampon: char buffer[buffer_len]; avant son utilisation la structure destaddr et le buffer doivent être initialisés par: memset(&destaddr, 0, sizeof(struct sockaddr_ll)); memset(buffer, 0, BUFFER_LEN); Puis la structure destaddr doit être remplie par: destaddr.sll_family = PF_PACKET; destaddr.sll_protocol = htons(eth_p_all); destaddr.sll_halen = 6; destaddr.sll_ifindex = 2; memcpy(&(destaddr.sll_addr),destmac,mac_addr_len); Ensuite nous préparons l'en-tête de la trame: short int ethertypet = htons(0x8200); // champs de controle memcpy(buffer,destmac,mac_addr_len); memcpy((buffer+mac_addr_len),localmac,mac_addr_len); memcpy((buffer+(2*mac_addr_len)),&(ethertypet),sizeof(ethertypet)); Pour finir la création de la trame nous y ajoutons nos données (mes_data): memcpy((buffer+ethertype_len+(2*mac_addr_len)),mes_data,len); Enfin la trame est envoyée par la fonction sendto(): int tl= 14+len; int ssockll = sizeof(struct sockaddr_ll); sendto(sockfd,buffer,tlen,0,(struct sockaddr *)&(destaddr),ssockll);

Réception d'une trame Ethernet La réception d'une trame Ethernet nécessite la préparation de l'interface qui doit capter les trames. Cet interface peut fonctionner en mode normal ou mode de promiscuité. Dans le mode normal seulement les trames destinées à cette interface serons captées par la station (les trames en diffusion inclues). Dans le mode de promiscuité une interface peut capter/sniffer toutes les trames. Dans chaque cas il faut identifier (bind) l'interface à utiliser par la captage des trames. Voici les éléménts d'un programme permettant de capter les trames envoyées sur l'interface donnée avec l'adressage UNICAST et l'adressage BROADCAST. Réception en mode normal La fonction de la création d'un socket en mode raw: int CreateRawSocket(int protocol) int rs; if((rs = socket(pf_packet,sock_raw,htons(protocol)))== 1) printf("error creating raw socket: "); exit( 1); return rs; La fonction de la réception d'une trame dans le buffer: unsigned char* ReceiveRawEth(int sd) unsigned char* buffer = (unsigned char*)malloc(eth_frame_len); memset(buffer, '\0', ETH_FRAME_LEN); // frame buffer reset int l = 0; // frame buffer length l=recvfrom(sd,buffer,eth_frame_len,0,(struct sockaddr *)0,(int*)0); return buffer;

Réception en mode de promiscuité Pour effectuer la lecture de toutes les trames nous avons besoin de mettre l'interface Ethernet en mode de fonctionnement en promiscuité. L'interface doit être explicitement liée au socket avant l'application du mode en promiscuité. Ci-dessous la fonction qui crée et lie le socket à l'interface Ethernet spécifiée (bind) et qui ajoute le mode de promiscuité. La fonction possède 1 argument: nom de l'interface à sniffer. int CreatePromiscuousSocket(char *name) int sd; struct ifreq ifr; struct sockaddr_ll interfaceaddr; struct packet_mreq mreq; if ((sd = socket(pf_packet,sock_raw,htons(eth_p_all))) < 0) return 1; // clearing the interfaceaddr link layer socket address memset(&interfaceaddr,0,sizeof(interfaceaddr)); // clearing the ifr interface control registers memset(&ifr,0,sizeof(ifr)); // clearing mreq packet control registers memset(&mreq,0,sizeof(mreq)); // preparing the interface name memcpy(&ifr.ifr_name,name,ifnamsiz); // setting the interface name to find the interface index ioctl(sd,siocgifindex,&ifr); // setting the interface index interfaceaddr.sll_ifindex = ifr.ifr_ifindex; // setting the address family for interface interfaceaddr.sll_family = AF_PACKET; // binding the socket to the identified interface if (bind(sd, (struct sockaddr *)&interfaceaddr,sizeof(interfaceaddr)) < 0) return 2; // preparing the interface index in packet control mreq.mr_ifindex = ifr.ifr_ifindex; // preparing the promiscuous mode for packet sniffing mreq.mr_type = PACKET_MR_PROMISC; // setting the MAC address size mreq.mr_alen = 6; // setting the promiscuous mode to the interface for packet sniffing if (setsockopt(sd,sol_packet,packet_add_membership, (void*)&mreq,(socklen_t)sizeof(mreq)) < 0) return 3; return sd;

Dans la fonction principale main() nous pouvons lire/capter les paquets Ethernet par la fonction recvfrom(): int len; unsigned char buffer[2000]; struct sockaddr_ll paddr; int spaddr = sizeof(packet_info); len = recvfrom(raw,buffer,2000,0,(struct sockaddr*)&paddr,&spaddr); Le paquet est reçu dans le buffer, la taille de la trame réçue est enregistrée dans la varaible len. La fonction suivante permet de visualiser/imprimer le contenu de la trame en caractères héxadécimaux: void PrintPacketInHex(unsigned char *packet, int len, int com) unsigned char *p = packet; int beg,end,num; int ip=0; int udp=0,tcp=0; static int count=0; count++; beg=0;end=0; ip=(*(packet+12)==0x08 && *(packet+13)==0x00); //IP protocol in ETH frame udp= ip && (*(packet+23)==0x11); // UDP protocol in IP packet tcp= ip && (*(packet+23)==0x06); // TCP protocol in IP packet switch (com) case 0: beg=0;end=len;break; // print all packet case 1: beg=0;end=13;break; // print header case 2: beg=0;end=5;break; // print destination address case 3: beg=6;end=11;break; // print source address case 4: beg=14;end=len 14;break; // print data only case 5: if(ip)beg=14;end=33;;break; // print IP header 8 bytes case 6: if(udp)beg=34;end=41;;break; // print UDP header 8 bytes case 7: if(tcp)beg=34;end=53;;break; // print TCP header 20 bytes // Exercise: here you put your modes: // 5 IP header // 6 IP/UDP header // 7 IP/TCP header default: beg=0;end=len; // print all packet printf("\n\n Packet nr %d size %d \n\n",count,len); if(end)num=end beg+1; else num=0; while(num ) printf("%.2x ", *(p+beg)); p++; printf("\n\n Packet ends \n"); Remarque Après cette introduction générale à l'utilisation de l'interface raw-socket dans le réseau Ethernet nous proposons 2 sujets de développement à partir du code préparé. Le premier sujet est une application qui permet de diffuser et de récevoir les fichiers transmis directement dans les trames Ethernet. Cette application ne peut fonctionner que sur un réseau local. Le deuxième sujet est préparé pour l'analyse des trames Ethernet portant les protocoles de plus haut niveau: le protocole IP, puis le protocoles UDP et TCP.

Sujet 1: Ecrire une application qui permet de diffuser/émettre et récevoir sur le réseau local les fichiers transmis directemment dans les trames Ethernet. L'émetteur doit fonctionner en mode de diffusion (BROADCAST) et en mode simple (UNICAST). Eléments de l'application faire des modifications/versions du programme fourni dans l'annexe: 1. programme/processus émetteur qui envoie les trames en diffusion ou en unicast 2. programme récépteur qui réçoit les trames lui destinées (BROADCAST ou UNICAST) Nous avons besoin de déterminer la valeur du champ ethertypefname pour pouvoir différencier notre protocole des protocoles existants sur le réseau et de différencier les types de données à envoyer dans les trames. Par exemple nous pouvons proposer: x0201 : pour la trame qui porte le nom du fichier à lire sur le poste distant x0202: pour la trame qui porte le contenu/fragment du fichier envoyé par le poste distant Le protocoles standard tels que IP ou ARP utilisent des valeurs spécifiques: IP 0x0800, ARP - 0x0806 Rappelons que la longueur d'un segment doit être limitée à 1500 octets ou moins selon la taille du tampon de réception. int CreateRawSocket(int protocol) int rs; if((rs = socket(pf_packet,sock_raw,htons(protocol)))== 1) printf("error creating raw socket: "); exit( 1); return rs; Le programme de l'émmeteur doit pouvoir fonctionner avec une adresse simple ou une adresse de diffusion: MacAddress localmac = 0x00,0x00,0x00,0x00,0x00,0x00; //MacAddress localmac = 0x00,0x17,0xB3,0x00,0xa0,0x20; MacAddress destmacbrd = 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF; //MacAddress destmacuni= 0x00,0xB0,0xD0,0x4C,0xD5,0xC6; Le programme du serveur/émetteur doit créer et envoyer une trame avec le type (x0201) et le nom du fichier à créer sur le poste du client puis envoyer le fichier, segment par segment, vers le client/récepteur avec le type Ethernet égal à x0202. Attention: L'ensemble peut fonctionner seulement avec un seul serveur/émetteur et un fiichier transmis à l'instant donné. Imaginez une amelioration qui permet d'identifier les séquences de trames (sessions) de

transmission appartennant au même fichier envoyé par un ou plusieurs serveurs. Annexe: Voici le programme complet du transfert des fichiers ( émetteur et récepteur ) à comprendre et à re-utiliser pour la création/intégration de votre application. Emetteur/diffuseur des fichiers #include <stdio.h> #include <stdlib.h> #include <errno.h> #include <string.h> #include <sys/types.h> #include <sys/socket.h> #include <linux/if_ether.h> #include <netpacket/packet.h> extern int errno; #define ETHERTYPE_LEN 2 #define MAC_ADDR_LEN 6 #define BUFFER_LEN 320 #include <net/ethernet.h> #include <netinet/ether.h> typedef unsigned char MacAddress[MAC_ADDR_LEN]; // frame buffer // 6+6+2+2+data:for data 320 16=304 //MacAddress localmac = 0x00, 0x00, 0x00, 0x00, 0x00, 0x00; // unknown MacAddress localmac = 0x00, 0xB0, 0xD0, 0x4C, 0xD5, 0xC6; //MacAddress destmac= 0x00, 0xB0, 0xD0, 0x4C, 0xD5, 0xC6; MacAddress destmac = 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF; // broadcast int main(int c, char *a[]) int sd = 0, retvalue = 0, len=0; int fd = 0; unsigned short nb=1; char buffer[buffer_len]; struct sockaddr_ll destaddr; short int ethertypet = htons(0x8200); short int ethertypefname = htons(0x0201); // send name short int ethertypefdata = htons(0x0202); // send data short int dlen; // data length if(getuid()) printf("you must be root (uid=0) to run this program!\n"); exit(0); memset(&destaddr, 0, sizeof(struct sockaddr_ll)); memset(buffer, 0, BUFFER_LEN); if((sd = socket(pf_packet, SOCK_RAW, htons(eth_p_all))) < 0) printf("socket() error\n"); exit(1); printf("socket creation success.\n"); fd=open(a[1],0); // local file to open and send if(fd<0) printf("no such file: %s\n",a[1]); exit(2); destaddr.sll_family =PF_PACKET; destaddr.sll_protocol = htons(eth_p_all);

destaddr.sll_halen = 6; destaddr.sll_ifindex = 2; memcpy(&(destaddr.sll_addr), destmac, MAC_ADDR_LEN); // Ethernet Header Construction: addresses 2*6 bytes memcpy(buffer, destmac, MAC_ADDR_LEN); memcpy((buffer+mac_addr_len), localmac, MAC_ADDR_LEN); // Ethernet Header Construction: type 2 bytes memcpy((buffer+(2*mac_addr_len)), &(ethertypefname), 2); // protocol type field: file name or file data memcpy((buffer+(2*mac_addr_len)+ethertype_len), &dlen, 2); // protocol data field length dlen=htons(strlen(a[2])+1); // file name memcpy((buffer+(2*mac_addr_len)+ethertype_len)+2, a[2], strlen(a[2])+1); len = 2*6+2+2+strlen(a[2])+1; // total frame length // sending the frame with the file name to be created at receiver side retvalue = sendto(sd, buffer, len, 0, (struct sockaddr *)&(destaddr), sizeof(struct sockaddr_ll)); while(nb) // reading the local file into frame buffer nb = read(fd,buffer+16,sizeof(buffer) 16); // preparing the frame header memcpy((buffer+(2*mac_addr_len)), &(ethertypefdata), 2); dlen=htons(nb); // convert short value in network format memcpy((buffer+(2*mac_addr_len)+ethertype_len), &dlen, 2); // sending the file data frame if((retvalue = sendto(sd, buffer, nb+16, 0, (struct sockaddr *)&(destaddr), sizeof(struct sockaddr_ll))) < 0) printf("sendto()) error \n"); exit(3); printf("send success (%d).\n", retvalue); // waiting for 200 microseconds before sending next frame usleep(200); return(0);

Récepteur des fichiers #include <stdio.h> #include <stdlib.h> #include <sys/socket.h> #include <linux/if_packet.h> #include <linux/if_ether.h> #include <linux/if_arp.h> #include <string.h> #define ETHERTYPE_LEN 2 #define MAC_ADDR_LEN 6 #define ETH_FRAME_LEN 320 int main(int c, char **a) int nb=1, fd; unsigned short count=1; int sd; // socket descriptor if(geteuid()) printf("you must be root (uid=0) to run this program! %d\n",geteuid()); exit(0); sd = socket(af_packet, SOCK_RAW, ntohs(eth_p_all)); if (sd == 1) printf("socket() error\n"); exit(1); // prepare the frame buffer unsigned char* buffer = (unsigned char*)malloc(eth_frame_len); memset(buffer, '\0', ETH_FRAME_LEN); // frame buffer reset int len = 0; // frame buffer length while(count) len = recvfrom(sd,buffer,eth_frame_len,0,(struct sockaddr *) 0,(int *) 0); printf("len:%d\n",len); if (len == 1) printf("error while receiving ethernet frame...\n"); exit(2); else printf("frame type %4.4x\n",*(buffer+12)); // frame type on 12th and 13th byte memcpy(&count,buffer+14,2); printf("counter %.4x\n",ntohs(count)); // print number of data bytes in frame : convert to host format if(*(buffer+12)==0x02 && *(buffer+13)==0x01) printf("name: %s\n",buffer+16); fd=creat(buffer+16,0777); // frame with file name : create the file if(*(buffer+12)==0x02 && *(buffer+13)==0x02) write(fd,buffer+16,ntohs(count)); // frame with file data : write to the file memset(buffer, '\0', ETH_FRAME_LEN); close(sd); close(fd);

Sujet 2: Ecrire une application qui permet de récevoir les trames en mode de promiscuité et d'afficher le contenu formaté des trames captées. 1. Afficher les en-têtes de trames Ethernet. 2. Afficher les en-têtes de trames Ethernet et des paquets IP et segments TCP/UDP portés dans les trames. Elements de l'application: int CreatePromiscuousSocket(char *name) int sd; struct ifreq ifr; struct sockaddr_ll interfaceaddr; struct packet_mreq mreq; if ((sd = socket(pf_packet,sock_raw,htons(eth_p_all))) < 0) return 1; // clearing the interfaceaddr link layer socket address memset(&interfaceaddr,0,sizeof(interfaceaddr)); // clearing the ifr interface control registers memset(&ifr,0,sizeof(ifr)); // clearing mreq packet control registers memset(&mreq,0,sizeof(mreq)); // preparing the interface name memcpy(&ifr.ifr_name,name,ifnamsiz); // setting the interface name to find the iterface index ioctl(sd,siocgifindex,&ifr); // setting the interface index interfaceaddr.sll_ifindex = ifr.ifr_ifindex; // setting the address family for interface interfaceaddr.sll_family = AF_PACKET; // binding the socket to the identified interface if (bind(sd, (struct sockaddr *)&interfaceaddr,sizeof(interfaceaddr)) < 0) return 2; // preparing the interface index in packet control mreq.mr_ifindex = ifr.ifr_ifindex; // preparing the promiscuous mode for packet sniffing mreq.mr_type = PACKET_MR_PROMISC; // setting the MAC address size mreq.mr_alen = 6; // setting the promiscuous mode to the interface for packet sniffing if (setsockopt(sd,sol_packet,packet_add_membership, (void*)&mreq,(socklen_t)sizeof(mreq)) < 0) return 3; return sd;

unsigned char* ReceiveRawEth(int sd) unsigned char* buffer = (unsigned char*)malloc(eth_frame_len); memset(buffer, '\0', ETH_FRAME_LEN); // frame buffer reset int l = 0; // frame buffer length l=recvfrom(sd,buffer,eth_frame_len,0,(struct sockaddr *)0,(int*)0); return buffer; void PrintPacketInHex(unsigned char *packet, int len, int com) unsigned char *p = packet; int beg,end,num; int ip=0; int udp=0,tcp=0; static int count=0; count++; beg=0;end=0; ip=(*(packet+12)==0x08 && *(packet+13)==0x00); //IP protocol in ETH frame udp= ip && (*(packet+23)==0x11); // UDP protocol in IP packet tcp= ip && (*(packet+23)==0x06); // TCP protocol in IP packet switch (com) case 0: beg=0;end=len;break; // print all packet case 1: beg=0;end=13;break; // print header case 2: beg=0;end=5;break; // print destination address case 3: beg=6;end=11;break; // print source address case 4: beg=14;end=len 14;break; // print data only case 5: if(ip)beg=14;end=33;;break; // print IP header 8 bytes case 6: if(udp)beg=34;end=41;;break; // print UDP header 8 bytes case 7: if(tcp)beg=34;end=53;;break; // print TCP header 20 bytes // Exercise: here you put your modes: // 5 IP header // 6 IP/UDP header // 7 IP/TCP header default: beg=0;end=len; // print all packet printf("\n\n Packet nr %d size %d \n\n",count,len); if(end)num=end beg+1; else num=0; while(num ) printf("%.2x ", *(p+beg)); p++; printf("\n\n Packet ends \n"); Attention: Cette fonction doit être completée afin de pouvoir imprimer/afficher les en-têtes du protocole IP et des protocoles TCP/UDP.

Le format d'un en-tête de protocole IP de base est donné ci-dessous (sans options 20 octets): La valeur du champ Protocol est 6 (0x06) pour TCP et 17 (0x11) pour UDP Le format d'un en-tête UDP est illustré ci-dessous (8 octets): Le format d'u en-tête TCP est donné ci-dessous (20 octets sans options):

Annexe: #include<stdio.h> #include<stdlib.h> #include<sys/socket.h> #include<features.h> #include<linux/if_packet.h> #include<linux/if_ether.h> #include<errno.h> #include<sys/ioctl.h> #include<net/if.h> int CreatePromiscuousSocket(char *name) int sd; struct ifreq ifr; struct sockaddr_ll interfaceaddr; struct packet_mreq mreq; if ((sd = socket(pf_packet,sock_raw,htons(eth_p_all))) < 0) return 1; // clearing the interfaceaddr link layer socket address memset(&interfaceaddr,0,sizeof(interfaceaddr)); // clearing the ifr interface control registers memset(&ifr,0,sizeof(ifr)); // clearing mreq packet control registers memset(&mreq,0,sizeof(mreq)); // preparing the interface name memcpy(&ifr.ifr_name,name,ifnamsiz); // setting the interface name to find the iterface index ioctl(sd,siocgifindex,&ifr); // setting the interface index interfaceaddr.sll_ifindex = ifr.ifr_ifindex; // setting the address family for interface interfaceaddr.sll_family = AF_PACKET; // binding the socket to the identified interface if (bind(sd, (struct sockaddr *)&interfaceaddr,sizeof(interfaceaddr)) < 0) return 2; // preparing the interface index in packet control mreq.mr_ifindex = ifr.ifr_ifindex; // preparing the promiscuous mode for packet sniffing mreq.mr_type = PACKET_MR_PROMISC; // setting the MAC address size mreq.mr_alen = 6; // setting the promiscuous mode to the interface for packet sniffing if (setsockopt(sd,sol_packet,packet_add_membership, (void*)&mreq,(socklen_t)sizeof(mreq)) < 0) return 3; return sd;

void PrintPacketInHex(unsigned char *packet, int len, int com) unsigned char *p = packet; int beg,end,num; int ip=0; int udp=0,tcp=0; static int count=0; count++; beg=0;end=0; ip=(*(packet+12)==0x08 && *(packet+13)==0x00); //IP protocol in ETH frame udp= ip && (*(packet+23)==0x11); // UDP protocol in IP packet tcp= ip && (*(packet+23)==0x06); // TCP protocol in IP packet switch (com) case 0: beg=0;end=len;break; // print all packet case 1: beg=0;end=13;break; // print header case 2: beg=0;end=5;break; // print destination address case 3: beg=6;end=11;break; // print source address case 4: beg=14;end=len 14;break; // print data only case 5: if(ip)beg=14;end=33;;break; // print IP header 8 bytes case 6: if(udp)beg=34;end=41;;break; // print UDP header 8 bytes case 7: if(tcp)beg=34;end=53;;break; // print TCP header 20 bytes // Exercise: here you put your modes: // 5 IP header // 6 IP/UDP header // 7 IP/TCP header default: beg=0;end=len; // print all packet printf("\n\n Packet nr %d size %d \n\n",count,len); if(end)num=end beg+1; else num=0; while(num ) printf("%.2x ", *(p+beg)); p++; printf("\n\n Packet ends \n");

main(int c,char **a) int sd; unsigned char buf[1500]; struct sockaddr_ll addr; socklen_t addr_len = sizeof(addr); int n; int com; if(getuid()) printf("you must be root (uid=0) to run this program!\n"); exit(0); if(c!=3) printf("usage: s2.sniffall interface_name protocol_to_sniff\n"); printf("0 all packet\n"); printf("1 ETH header\n"); printf("2 ETH dest address\n"); printf("3 ETH source address\n"); printf("4 ETH data\n"); printf("5 IP header\n"); printf("6 UDP header\n"); printf("7 TCP header\n"); exit(1); sd=createpromiscuoussocket(a[1]); // a[1] interface name com = atoi(a[2]); // protocol to sniff while(1) n = recvfrom(sd, buf, 2000, 0, (struct sockaddr*)&addr, &addr_len); if (n <= 0) printf("error reading\n"); else PrintPacketInHex(buf,n,com);