Skip to content

Instantly share code, notes, and snippets.

@p4bl0-
Created January 29, 2017 21:31
Show Gist options
  • Save p4bl0-/0a3c8db1e4510c2a6797bd6b9494c741 to your computer and use it in GitHub Desktop.
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).
#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