Last active
June 6, 2020 19:02
-
-
Save plonk/633aa81e55889a292c30f68587b7623e to your computer and use it in GitHub Desktop.
Simple ping
This file contains hidden or 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 <stdio.h> | |
#include <stdlib.h> | |
#include <sys/socket.h> | |
#include <netinet/in.h> | |
#include <string.h> | |
#include <netdb.h> | |
#include <sys/time.h> | |
const char *TYPE_STRING[256] = { | |
[0] = "Echo Reply", | |
[3] = "Destination Unreachable", | |
[4] = "Source Quench", | |
[8] = "Echo Request", | |
}; | |
int main(int argc, char **argv) | |
{ | |
char *dest=0; | |
for (int i = 1; i < argc; i++) { | |
if (dest) { | |
fprintf(stderr,"Error: Multiple destinations.\n"); | |
exit(1); | |
} | |
dest = argv[i]; | |
} | |
if (!dest) { | |
fprintf(stderr,"Usage: (sudo) ping DESTINATION\n"); | |
exit(1); | |
} | |
struct hostent *he = gethostbyname(dest); | |
if (!he) { | |
fprintf(stderr, "Error while looking up host %s\n", dest); | |
exit(1); | |
} | |
// --------------------------------------------------------- | |
int raw_socket = socket(AF_INET, SOCK_RAW, 1 /* ICMP */); | |
if (raw_socket == -1) { | |
perror("socket"); | |
exit(1); | |
} | |
#define BUFFER_SIZE 100 | |
unsigned char buf[BUFFER_SIZE] = { | |
8, 0, | |
0, 0, /* checksum */ | |
0x71, 0x44, /* ID */ | |
0, 1, /* seq. number */ | |
'A','B','C','D', /* payload */ | |
}; | |
int size = 8 + 4; | |
struct sockaddr_in addr; | |
memset(&addr, 0, sizeof(struct sockaddr_in)); | |
addr.sin_family = AF_INET; | |
addr.sin_addr.s_addr = *(uint32_t*)he->h_addr; | |
int sum = 0; | |
for (int i = 0; i < size; i += 2) { | |
sum += *(unsigned short*)(buf+i); | |
if (sum >= 0x10000) { | |
sum &= 0xffff; | |
sum += 1; | |
} | |
} | |
/* set checksum */ | |
buf[2] = ~sum; | |
buf[3] = ~sum >> 8; | |
struct timeval start; | |
gettimeofday(&start, NULL); | |
int r; | |
r = sendto(raw_socket, buf, size, 0, (struct sockaddr*)&addr, sizeof(struct sockaddr_in)); | |
printf("%d bytes sent\n", r); | |
struct sockaddr_in addr2; | |
int addrlen; | |
r = recvfrom(raw_socket, buf, sizeof(buf), 0, | |
(struct sockaddr*)&addr2, &addrlen); | |
printf("%d bytes read (including 20-byte IP header)\n", r); | |
struct timeval end; | |
gettimeofday(&end, NULL); | |
const int type = buf[20]; | |
const int code = buf[21]; | |
printf("Type: %d (%s)\n", type, TYPE_STRING[type]); | |
printf("Code: %d\n", code); | |
if (type == 0 && code == 0) { | |
printf("Round-trip time: %.03f ms\n", | |
((end.tv_sec + end.tv_usec/1000000.0) - | |
(start.tv_sec + start.tv_usec/1000000.0)) * 1000); | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment