1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87
|
#include "structures.h"
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <errno.h>
int main(){
// Déclaration des variables utiles
int sock; // La raw socket
int optval; // Les options de la raw socket
int res;
struct icmphdr* icmp; // En-tête icmp
struct iphdr* ip; // En-tête ip
struct icmphdr* ricmp; // En-tête icmp de retour
struct iphdr* rip; // En-tête ip de retour
char* packet; // Paquet à envoyer
char* tmp; // Pointeur tampon pour la copie
char* buffer; // Buffer de reception
char* source = "127.0.0.1"; // @ source du datagramme
char* dest = "127.0.0.1"; // @ destination du datagramme
char* proxy = "127.0.0.1"; // @ de l'intermédiaire qui enverra au destinataire à notre place
struct sockaddr_in peer; // Adresse du destinataire
// Allocation d'espace pour les pointeurs
ip = (struct iphdr *)malloc(sizeof(struct iphdr));
icmp = (struct icmphdr *)malloc(sizeof(struct icmphdr));
packet = (char*)malloc(sizeof(struct iphdr) + sizeof(struct icmphdr));
buffer = (char*)malloc(sizeof(struct iphdr) + sizeof(struct icmphdr)); // On reçoit en retour la même taille de données
// Remplissage iphdr
ip->ihl = 5; // Longuer de l'en-tête
ip->version = 4; // Version du protoole IP utilisé (IPV4)
ip->tos = 0; // (routine, retard standard, debit standard, taux d'erreur standard)
ip->tot_len = sizeof(struct iphdr) + sizeof(struct icmphdr); // Taille du datagramme (iphdr + données: icmphdr)
ip->id = htons(getuid()); // Identifiateur du datagramme (utilisé en cas de fragmentation)
ip->frag_off = 0; // Offset du fragment à zero
ip->ttl = 1; // Valeur max
ip->protocol = IPPROTO_ICMP; // Protocol de couche IP utilisé (ICMP)
ip->saddr = inet_addr(source); // Adresse source
ip->daddr = inet_addr(dest); // Adresse destination
ip->check = 0; // Champ de contrôle d'en-tête
/* Il n'ya pas d'option mais à la place, on met directement les données qui sont en fait le message ICMP*/
// Remplissage icmphdr
icmp->type = ICMP_ECHO; // Requête IMP de type echo
icmp->code = 0;
icmp->un.echo.id = 0;
icmp->un.echo.sequence = 0;
icmp->checksum = 0;
// Création de la soket
sock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
if(sock == -1) {printf("Erreur de création de la socket\n%s\n", strerror(errno)); return -1; }
res = setsockopt(sock, IPPROTO_IP, IP_HDRINCL, &optval, sizeof(int));
if(res == -1) {printf("Erreur d'attribution de paramètres à la socket\n%s\n", strerror(errno)); return -1; }
// Mise en tampon du message (dans paquet)
tmp = packet;
memcpy(tmp, ip, sizeof(struct iphdr));
tmp += sizeof(struct iphdr);
memcpy(tmp, icmp, sizeof(struct icmphdr));
// Paramétrage de l'adresse d'envoi direct (On peut ne pas être directement lié au destinataire du msg)
peer.sin_family = AF_INET;
peer.sin_addr.s_addr = inet_addr(proxy);
// Envoi du message
res = sendto(sock, packet, ip->tot_len, 0, (struct sockaddr *)&peer, sizeof(struct sockaddr_in));
if(res == -1) {printf("Erreur d'envoi\n%s\n", strerror(errno)); return -1; }
// Attente de la réponse
bzero(buffer, sizeof(struct iphdr) + sizeof(struct icmphdr));
res = recv(sock, buffer, sizeof(struct iphdr)+sizeof(struct icmphdr), 0);
if(res == -1) {printf("Erreur de réception\n%s\n", strerror(errno)); return -1; }
printf("Received the ECHO REPLY\n");
rip = (struct iphdr *)buffer;
printf("ihl: %i\nver: %i\nttl: %i\nid: %i\n", rip->ihl, rip->version, rip->ttl, rip->id);
close(sock);
return 0;
} |