This commit is contained in:
Jack Halford 2017-08-02 19:21:37 +02:00
parent 66d9a2a514
commit ff629391b0
4 changed files with 70 additions and 112 deletions

View file

@ -10,6 +10,8 @@
# # # #
# **************************************************************************** # # **************************************************************************** #
SHELL := bash
NAME = ft_ping NAME = ft_ping
CC = gcc CC = gcc
@ -44,7 +46,8 @@ $(NAME): $(LIBFT_LIB) $(OBJ_DIR) $(OBJS) $(CLIENT_OBJ)
@$(CC) $(OBJS) -o $@ \ @$(CC) $(OBJS) -o $@ \
-I $(INC_DIR) \ -I $(INC_DIR) \
-I $(LIBFT_INC) \ -I $(LIBFT_INC) \
$(LIBFT_LIB) $(CLIENT_OBJ) $(FLAGS) $(LIBFT_LIB) $(CLIENT_OBJ) $(FLAGS) \
-lm
@printf "\r\033[38;5;117m✓ MAKE $@ \033[0m\033[K\n" @printf "\r\033[38;5;117m✓ MAKE $@ \033[0m\033[K\n"
$(LIBFT_LIB): $(LIBFT_LIB):

View file

@ -23,6 +23,7 @@
# include <netinet/in.h> # include <netinet/in.h>
# include <netinet/ip.h> # include <netinet/ip.h>
# include <netinet/ip_icmp.h> # include <netinet/ip_icmp.h>
# include <sys/wait.h>
#define PACKETSIZE 64 #define PACKETSIZE 64

@ -1 +1 @@
Subproject commit 23c69f13242ecbff493356c57cb1384eb1dd45f5 Subproject commit 57475bdafefca069981276b44dd8c5d8998b5a13

View file

@ -6,177 +6,131 @@
/* By: jhalford <jack@crans.org> +#+ +:+ +#+ */ /* By: jhalford <jack@crans.org> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2017/04/22 14:10:24 by jhalford #+# #+# */ /* Created: 2017/04/22 14:10:24 by jhalford #+# #+# */
/* Updated: 2017/04/23 18:18:41 by jhalford ### ########.fr */ /* Updated: 2017/10/08 14:26:15 by jhalford ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
#include "ping.h" #include "ping.h"
#define TIME_START 0
#define TIME_END 1
#define TIME_TRIPTIME 2
int g_pid=-1; int g_pid = -1;
int g_pkt_rec=0; int g_pkt_rec = 0;
char g_domain[256]; char g_domain[256];
struct s_stats g_rs;
unsigned short checksum(void *b, int len)
{
unsigned short *buf = b;
unsigned int sum=0;
unsigned short result;
for (sum = 0; len > 1; len -= 2)
sum += *buf++;
if (len == 1)
sum += *(unsigned char*)buf;
sum = (sum >> 16) + (sum & 0xFFFF);
sum += (sum >> 16);
result = ~sum;
return (result);
}
void display(void *buf, int bytes, struct sockaddr_in *addr) void display(void *buf, int bytes, struct sockaddr_in *addr)
{ {
struct ip *ip = buf; struct ip *ip;
struct icmp *icmp; struct icmp *icmp;
struct s_packet *pkt; struct s_packet *pkt;
int hlen; int hlen;
char addrstr[INET_ADDRSTRLEN]; double triptime;
struct timeval start, end, triptime;
double diff;
ip = buf;
(void)bytes; (void)bytes;
hlen = ip->ip_hl << 2; hlen = ip->ip_hl << 2;
pkt = (struct s_packet*)(buf + hlen); pkt = (struct s_packet*)(buf + hlen);
icmp = &pkt->hdr; icmp = &pkt->hdr;
start = *(struct timeval*)&pkt->msg; if (icmp->icmp_id != g_pid)
if (gettimeofday(&end, NULL) != 0)
return ; return ;
timersub(&end, &start, &triptime); triptime = time_milli() - *(double*)&pkt->msg;
diff = (triptime.tv_sec + triptime.tv_usec / 1000000.0) * 1000.0; rs_push(triptime);
rs_push(diff);
g_pkt_rec++; g_pkt_rec++;
printf("%d bytes from %s: icmp_seq=%d ttl=%i time=%.3f ms\n", printf("%d bytes from %s: icmp_seq=%d ttl=%i time=%.3f ms\n",
ip->ip_len, ip->ip_len,
inet_ntop(AF_INET, &(addr->sin_addr), addrstr, INET_ADDRSTRLEN), inet_ntop(AF_INET, &(addr->sin_addr), g_domain, INET_ADDRSTRLEN),
icmp->icmp_seq, ip->ip_ttl, diff); icmp->icmp_seq, ip->ip_ttl, triptime);
}
void listener(void)
{ int sd;
struct sockaddr_in addr;
unsigned char buf[1024];
sd = socket(PF_INET, SOCK_DGRAM, IPPROTO_ICMP);
if ( sd < 0 )
{
perror("socket");
exit(0);
}
for (;;)
{ int bytes;
socklen_t len=sizeof(addr);
bzero(buf, sizeof(buf));
bytes = recvfrom(sd, buf, sizeof(buf), 0, (struct sockaddr*)&addr, &len);
if ( bytes > 0 )
display(buf, bytes, &addr);
else
perror("recvfrom");
}
exit(0);
} }
void ping(struct sockaddr_in *addr) void ping(struct sockaddr_in *addr)
{ {
const int val = 255;
int i;
int sd; int sd;
int cnt; int cnt;
socklen_t len;
struct s_packet pkt; struct s_packet pkt;
struct sockaddr_in r_addr; double epoch;
struct timeval time;
if ((sd = socket(PF_INET, SOCK_DGRAM, IPPROTO_ICMP)) < 0) if ((sd = socket(PF_INET, SOCK_RAW, IPPROTO_ICMP)) < 0)
{ return (perror("sender socket"));
perror("socket"); if (setsockopt(sd, 0, IP_TTL, (int[]){255, 0}, sizeof(int)) != 0)
return ;
}
if (setsockopt(sd, 0, IP_TTL, &val, sizeof(val)) != 0)
perror("set TTL option"); perror("set TTL option");
if (fcntl(sd, F_SETFL, O_NONBLOCK) != 0)
perror("Request non blocking IO");
cnt = 0; cnt = 0;
while (1) while (1)
{ {
len = sizeof(r_addr);
bzero(&pkt, sizeof(pkt)); bzero(&pkt, sizeof(pkt));
pkt.hdr.icmp_type = ICMP_ECHO; pkt.hdr.icmp_type = ICMP_ECHO;
pkt.hdr.icmp_id = g_pid; pkt.hdr.icmp_id = g_pid;
pkt.hdr.icmp_seq = cnt++; pkt.hdr.icmp_seq = cnt++;
epoch = time_milli();
for (i=0; i < (int)sizeof(pkt.msg); i++) ft_memcpy(pkt.msg, (void*)&epoch, sizeof(epoch));
pkt.msg[i] = i+'0'; pkt.hdr.icmp_cksum = cksum(&pkt, sizeof(pkt));
pkt.msg[i] = 0; if (sendto(sd, &pkt, sizeof(pkt), 0,
if (gettimeofday(&time, NULL) != 0) (struct sockaddr*)addr, sizeof(*addr)) <= 0)
return ; return (perror("sendto"));
ft_memcpy(pkt.msg, (void*)&time, sizeof(time));
time = *(struct timeval*)&pkt.msg;
pkt.hdr.icmp_cksum = checksum(&pkt, sizeof(pkt));
if (sendto(sd, &pkt, sizeof(pkt), 0, (struct sockaddr*)addr, sizeof(*addr)) <= 0)
perror("sendto");
sleep(1); sleep(1);
} }
} }
void sigint_handler(int signo) void stats_recap(int signo)
{ {
double loss; double loss;
(void)signo; (void)signo;
rs_calcmore(); rs_calcmore();
loss = g_rs.count ? 100 * ((float) (g_rs.count - g_pkt_rec) / (float)g_rs.count) : 0; loss = FT_PCT(g_pkt_rec, g_rs.count);
printf("\n--- %s ping statistics ---", g_domain); printf("\n--- %s ping statistics ---", g_domain);
printf("\n%d packets transmitted, %d packets received, %0.1f%% packet loss", g_rs.count, g_pkt_rec, loss); printf("\n%d packets transmitted, %d packets received, %0.1f%% packet loss",
printf("\nround-trip min/avg/max/stddev = %.3f/%.3f/%.3f/%.3f ms", g_rs.min, g_rs.avg, g_rs.max, g_rs.stdev); g_rs.count, g_pkt_rec, loss);
printf("\nround-trip min/avg/max/stddev = %.3f/%.3f/%.3f/%.3f ms",
g_rs.min, g_rs.avg, g_rs.max, g_rs.stdev);
exit(0); exit(0);
} }
int main(int ac, char **av) struct addrinfo *resolve_host(char *hostname)
{ {
struct addrinfo *result;
struct addrinfo hints;
struct sockaddr_in *addr; struct sockaddr_in *addr;
struct addrinfo *result, hints;
char addrstr[INET_ADDRSTRLEN];
if (ac != 2) memset(&hints, 0, sizeof(hints));
{
printf("usage: %s <addr>\n", av[0]);
exit(1);
}
memset (&hints, 0, sizeof (hints));
hints.ai_family = PF_UNSPEC; hints.ai_family = PF_UNSPEC;
hints.ai_socktype = SOCK_STREAM; hints.ai_socktype = SOCK_STREAM;
hints.ai_flags |= AI_CANONNAME; hints.ai_flags |= AI_CANONNAME;
if (getaddrinfo(av[1], NULL, &hints, &result) != 0) if (getaddrinfo(hostname, NULL, &hints, &result) != 0)
{ {
perror("getaddrinfo"); perror("getaddrinfo");
exit(1); exit(1);
} }
addr = (struct sockaddr_in*)result->ai_addr; addr = (struct sockaddr_in*)result->ai_addr;
inet_ntop(AF_INET, &(addr->sin_addr), addrstr, INET_ADDRSTRLEN); inet_ntop(AF_INET, &(addr->sin_addr), g_domain, INET_ADDRSTRLEN);
g_pid = getpid();
ft_strcpy(g_domain, addrstr);
if (result->ai_canonname) if (result->ai_canonname)
ft_strcpy(g_domain, result->ai_canonname); ft_strcpy(g_domain, result->ai_canonname);
printf("PING %s (%s): %i data bytes\n", FT_TRY(result->ai_canonname, addrstr), addrstr, 64); return (result);
}
int main(int ac, char **av)
{
struct addrinfo *result;
if (ac != 2)
{
ft_usage("%s <addr>\n", av[0]);
exit(1);
}
g_pid = getpid();
result = resolve_host(av[1]);
if (result->ai_canonname)
printf("PING %s (%s): %i data bytes\n",
result->ai_canonname, g_domain, 64);
else
printf("PING %s: %i data bytes\n", g_domain, 64);
if (fork() == 0) if (fork() == 0)
{ {
signal(SIGINT, sigint_handler); signal(SIGINT, stats_recap);
rs_clear(); rs_clear();
listener(); listener(PF_INET, SOCK_RAW, IPPROTO_ICMP, &display);
exit(0);
} }
else ping((struct sockaddr_in*)result->ai_addr);
ping(addr);
wait(0);
return (0); return (0);
} }