Created
January 29, 2017 21:31
-
-
Save p4bl0-/0a3c8db1e4510c2a6797bd6b9494c741 to your computer and use it in GitHub Desktop.
Version simplifiée de ping pour jouer avec les protocoles IP et ICMP, et avec la programmation réseau bas niveau (raw socket).
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdlib.h> | |
#include <stdio.h> | |
#include <strings.h> | |
#include <stdint.h> | |
#include <unistd.h> | |
#include <sys/socket.h> | |
#include <netdb.h> | |
#include <netinet/in.h> | |
#include <netinet/ip.h> | |
#include <netinet/ip_icmp.h> | |
#include <errno.h> | |
uint16_t | |
checksum (void *buf, uint32_t len) | |
{ | |
uint16_t *b = buf; | |
uint32_t sum = 0; | |
for (sum = 0; len > 1; len -= 2) { | |
sum += *b++; | |
} | |
if (len == 1) { | |
sum += *((uint8_t *) b); | |
} | |
sum = (sum >> 16) + (sum & 0xffff); | |
sum += (sum >> 16); | |
return ~sum; | |
} | |
void | |
display_ip_hdr (struct iphdr *ip) | |
{ | |
uint8_t *src = (uint8_t *) &ip->saddr; | |
uint8_t *dst = (uint8_t *) &ip->daddr; | |
printf("IP packet:\n" | |
" version : %d\n" | |
" IHL : %d\n" | |
" ToS : %d\n" | |
" Len : %d\n" | |
" id : %d\n" | |
" offset : %d\n" | |
" TTL : %d\n" | |
" protocol : %d\n" | |
" checksum : %d\n" | |
" source : %d.%d.%d.%d\n" | |
" dest : %d.%d.%d.%d\n\n", | |
ip->version, | |
ip->ihl, | |
ip->tos, | |
ip->tot_len, | |
ip->id, | |
ip->frag_off, | |
ip->ttl, | |
ip->protocol, | |
ip->check, | |
src[0], src[1], src[2], src[3], | |
dst[0], dst[1], dst[2], dst[3]); | |
} | |
void | |
display_icmp_hdr (struct icmphdr *icmp) | |
{ | |
printf("ICMP datagram:\n" | |
" type : %d\n" | |
" code : %d\n" | |
" checksum : %d\n" | |
" echo id : %d\n" | |
" echo seq : %d\n\n", | |
icmp->type, | |
icmp->code, | |
icmp->checksum, | |
icmp->un.echo.id, | |
icmp->un.echo.sequence); | |
} | |
void | |
listen_echo_replies () | |
{ | |
int sock; | |
struct sockaddr_in addr; | |
socklen_t addrlen; | |
uint8_t buf[1024]; | |
int len; | |
struct iphdr *ip; | |
struct icmphdr *icmp; | |
sock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP); | |
if (sock < 0) { | |
perror("(listen) socket"); | |
exit(1); | |
} | |
for (;;) { | |
bzero(buf, sizeof(buf)); | |
len = recvfrom(sock, buf, sizeof(buf), 0, | |
(struct sockaddr *) &addr, &addrlen); | |
if (len <= 0) { | |
perror("(listen) recvfrom"); | |
} | |
else { | |
ip = (struct iphdr *) buf; | |
icmp = (struct icmphdr *) (buf + ip->ihl * 4); | |
if (icmp->type == 0 && icmp->un.echo.id == getpid()) { | |
printf("> Got our echo reply!\n"); | |
display_ip_hdr(ip); | |
display_icmp_hdr(icmp); | |
} | |
else { | |
printf("> Got something else :).\n"); | |
} | |
} | |
} | |
} | |
void | |
send_echo_requests (struct sockaddr_in *addr) | |
{ | |
int sock; | |
int len; | |
int counter = 0; | |
struct icmphdr icmp; | |
icmp.type = ICMP_ECHO; | |
icmp.code = 0; | |
icmp.un.echo.id = getppid(); | |
sock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP); | |
if (sock < 0) { | |
perror("(sender) socket"); | |
exit(1); | |
} | |
for (;;) { | |
icmp.un.echo.sequence = counter++; | |
icmp.checksum = 0; | |
icmp.checksum = checksum(&icmp, sizeof(icmp)); | |
len = sendto(sock, &icmp, sizeof(icmp), 0, | |
(struct sockaddr*) addr, sizeof(*addr)); | |
if (len <= 0) { | |
perror("(sender) sendto"); | |
} | |
else { | |
printf("> Sent echo request…\n"); | |
} | |
sleep(1); | |
} | |
} | |
int | |
main (int argc, char *argv[]) | |
{ | |
pid_t pid; | |
struct hostent *host; | |
struct sockaddr_in addr; | |
if (argc < 2) { | |
printf("Usage: pingue <host>\n"); | |
exit(1); | |
} | |
host = gethostbyname(argv[1]); | |
if (host == NULL) { | |
perror("gethostbyname"); | |
} | |
addr.sin_family = host->h_addrtype; | |
addr.sin_port = 0; | |
addr.sin_addr.s_addr = *((uint64_t *) host->h_addr); | |
pid = fork(); | |
if (pid < 0) { | |
perror("fork"); | |
exit(1); | |
} | |
if (pid == 0) { /* child */ | |
send_echo_requests(&addr); | |
} | |
else { /* parent */ | |
listen_echo_replies(); | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment