From 9f9c66295700c27a8620b3b2d1707f46835b2541 Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Sun, 23 Apr 2017 18:19:00 +0200 Subject: [PATCH 01/13] first commit --- ping/.gitmodules | 3 + ping/Makefile | 93 +++++++++++++++++++++++++ ping/includes/ft_ping.h | 33 +++++++++ ping/libft | 1 + ping/srcs/ping.c | 146 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 276 insertions(+) create mode 100644 ping/.gitmodules create mode 100644 ping/Makefile create mode 100644 ping/includes/ft_ping.h create mode 160000 ping/libft create mode 100644 ping/srcs/ping.c diff --git a/ping/.gitmodules b/ping/.gitmodules new file mode 100644 index 00000000..c82793fb --- /dev/null +++ b/ping/.gitmodules @@ -0,0 +1,3 @@ +[submodule "libft"] + path = libft + url = https://github.com/jzck/libft diff --git a/ping/Makefile b/ping/Makefile new file mode 100644 index 00000000..8023554f --- /dev/null +++ b/ping/Makefile @@ -0,0 +1,93 @@ +# **************************************************************************** # +# # +# ::: :::::::: # +# Makefile :+: :+: :+: # +# +:+ +:+ +:+ # +# By: wescande +#+ +:+ +#+ # +# +#+#+#+#+#+ +#+ # +# Created: 2016/08/29 21:32:58 by wescande #+# #+# # +# Updated: 2017/04/22 19:26:34 by jhalford ### ########.fr # +# # +# **************************************************************************** # + +NAME = ft_ping + +CC = gcc +W_FLAGS = -Wall -Wextra -Werror +D_FLAGS = +FLAGS = $(W_FLAGS) $(D_FLAGS) + +LEN_NAME = `printf "%s" $(NAME) |wc -c` +DELTA = $$(echo "$$(tput cols)-31-$(LEN_NAME)"|bc) + +LIBFT_DIR = libft/ +LIBFT_LIB = $(LIBFT_DIR)libft.a +LIBFT_INC = $(LIBFT_DIR)includes/ + +SRC_DIR = srcs/ +INC_DIR = includes/ +OBJ_DIR = objs/ + +SRC_BASE = \ +ping.c\ + +SRCS = $(addprefix $(SRC_DIR), $(SRC_BASE)) +OBJS = $(addprefix $(OBJ_DIR), $(SRC_BASE:.c=.o)) +NB = $(words $(SRC_BASE)) +INDEX = 0 + +all : + @make -C $(LIBFT_DIR) + @make -j $(NAME) + +$(NAME): $(LIBFT_LIB) $(OBJ_DIR) $(OBJS) $(CLIENT_OBJ) + @$(CC) $(OBJS) -o $@ \ + -I $(INC_DIR) \ + -I $(LIBFT_INC) \ + $(LIBFT_LIB) $(CLIENT_OBJ) $(FLAGS) + @printf "\r\033[38;5;117m✓ MAKE $@ \033[0m\033[K\n" + +$(LIBFT_LIB): + @make -C $(LIBFT_DIR) + +$(OBJ_DIR) : + @mkdir -p $(OBJ_DIR) + +$(OBJ_DIR)%.o : $(SRC_DIR)%.c | $(OBJ_DIR) + @$(eval DONE=$(shell echo $$(($(INDEX)*20/$(NB))))) + @$(eval PERCENT=$(shell echo $$(($(INDEX)*100/$(NB))))) + @$(eval TO_DO=$(shell echo $$((20-$(INDEX)*20/$(NB) - 1)))) + @$(eval COLOR=$(shell list=(160 196 202 208 215 221 226 227 190 154 118 82 46); index=$$(($(PERCENT) * $${#list[@]} / 100)); echo "$${list[$$index]}")) + @printf "\r\033[38;5;%dm⌛ [%s]: %2d%% `printf '█%.0s' {0..$(DONE)}`%*s❙%*.*s\033[0m\033[K" $(COLOR) ft_p $(PERCENT) $(TO_DO) "" $(DELTA) $(DELTA) "$(shell echo "$@" | sed 's/^.*\///')" + @$(CC) $(FLAGS) $(OBJ_FLAG) -MMD -c $< -o $@\ + -I $(INC_DIR)\ + -I $(LIBFT_INC) + @$(eval INDEX=$(shell echo $$(($(INDEX)+1)))) + +clean: cleanlib + @if [ -e $(OBJ_DIR) ]; then \ + rm -rf $(OBJ_DIR); \ + printf "\r\033[38;5;202m✗ clean $(NAME) \033[0m\033[K\n"; \ + fi; + +cleanlib: + @make -C $(LIBFT_DIR) clean + +fclean: clean fcleanlib + @for file in $(NAME); do \ + if [ -e $$file ]; then \ + rm -f $$file ; \ + printf "\r\033[38;5;196m✗ fclean $$file\033[0m\033[K\n"; \ + fi; \ + done; + +fcleanlib: cleanlib + @make -C $(LIBFT_DIR) fclean + +re: fclean all + +relib: fcleanlib $(LIBFT_LIB) + +.PHONY : fclean clean re relib cleanlib fcleanlib + +-include $(OBJS:.o=.d) diff --git a/ping/includes/ft_ping.h b/ping/includes/ft_ping.h new file mode 100644 index 00000000..9c727acf --- /dev/null +++ b/ping/includes/ft_ping.h @@ -0,0 +1,33 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_ping.h :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: jhalford +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2017/04/22 14:10:24 by jhalford #+# #+# */ +/* Updated: 2017/04/22 15:52:07 by jhalford ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#ifndef FT_PING_H +# define FT_PING_H + +# include "libft.h" +# include +# include +# include +# include +# include +# include +# include +# include + +#define PACKETSIZE 64 +struct s_packet +{ + struct icmp icmp; + char msg[PACKETSIZE-sizeof(struct icmp)]; +}; + +#endif diff --git a/ping/libft b/ping/libft new file mode 160000 index 00000000..61ecc913 --- /dev/null +++ b/ping/libft @@ -0,0 +1 @@ +Subproject commit 61ecc913bbc31dafab3fff2386e1cbfffd34596a diff --git a/ping/srcs/ping.c b/ping/srcs/ping.c new file mode 100644 index 00000000..a40cee6e --- /dev/null +++ b/ping/srcs/ping.c @@ -0,0 +1,146 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* main.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: jhalford +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2017/04/22 14:10:24 by jhalford #+# #+# */ +/* Updated: 2017/04/23 18:18:41 by jhalford ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "ft_ping.h" + +int g_pid=-1; + +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) +{ + int i; + struct ip *ip = buf; + struct icmp *icmp = buf + ip->ip_hl*4; + + printf("%d bytes from %s: ttl=%i\n", + ip->ip_len, inet_ntoa(addr->sin_addr), ip->ip_ttl); + printf("IPv%d: hrd-size=%d, pkt-size=%d, id=%d, frag-off=%d, protocol=%c\n, ttl=%i", + ip->ip_v, ip->ip_hl, ip->ip_len, ip->ip_id, ip->ip_off, ip->ip_p, ip->ip_ttl); + if (icmp->icmp_hun.ih_idseq.icd_id == g_pid) + { + printf("ICMP: type[%d/%d] checksum[%d] id[%d] seq[%d]\n", + icmp->icmp_type, icmp->icmp_code, ntohs(icmp->icmp_cksum), + icmp->icmp_hun.ih_idseq.icd_id, icmp->icmp_hun.ih_idseq.icd_seq); + (void)bytes; + } + for (i=0; i < bytes; i++) + { + if ( !(i & 15) ) printf("\n%i: ", i); + printf("%c ", ((char*)buf)[i]); + } + printf("\n"); +} + +void listener(struct sockaddr_in *addr) +{ + int sd; + struct sockaddr_in r_addr; + int bytes; + socklen_t len; + unsigned char buf[1024]; + + if ((sd = socket(PF_INET, SOCK_DGRAM, IPPROTO_ICMP)) < 0) + { + perror("socket"); + exit(0); + } + for (;;) + { + bzero(buf, sizeof(buf)); + len = sizeof(r_addr); + bytes = recvfrom(sd, buf, sizeof(buf), 0, (struct sockaddr*)&r_addr, &len); + if (bytes > 0) + display(buf, bytes, addr); + else + perror("recvfrom"); + } +} + +void ping(struct sockaddr_in *addr) +{ + const int val; + int i; + int sd; + int cnt; + socklen_t len; + struct s_packet pkt; + struct sockaddr_in r_addr; + + if ((sd = socket(PF_INET, SOCK_DGRAM, IPPROTO_ICMP)) < 0) + { + perror("socket"); + return ; + } + if (setsockopt(sd, 0, IP_TTL, &val, sizeof(val)) != 0) + perror("set TTL option"); + if (fcntl(sd, F_SETFL, O_NONBLOCK) != 0) + perror("Request non blocking IO"); + cnt = 1; + while (1) + { + len = sizeof(r_addr); + recvfrom(sd, &pkt, sizeof(pkt), 0, (struct sockaddr*)&r_addr, &len); + bzero(&pkt, sizeof(pkt)); + pkt.icmp.icmp_type = ICMP_ECHO; + pkt.icmp.icmp_hun.ih_idseq.icd_id = g_pid; + for (i=0; i < (int)sizeof(pkt.msg); i++) + pkt.msg[i] = i+'0'; + pkt.msg[i] = 0; + pkt.icmp.icmp_hun.ih_idseq.icd_seq = cnt++; + pkt.icmp.icmp_cksum = checksum(&pkt, sizeof(pkt)); + if (sendto(sd, &pkt, sizeof(pkt), 0, (struct sockaddr*)addr, sizeof(*addr)) <= 0) + perror("sendto"); + sleep(1); + } +} + +int main(int ac, char **av) +{ + struct sockaddr_in *addr; + struct addrinfo *result; + + if (ac != 2) + { + printf("usage: %s \n", av[0]); + exit(1); + } + if (getaddrinfo(av[1], NULL, NULL, &result) != 0) + { + perror("getaddrinfo"); + exit(1); + } + addr = (struct sockaddr_in*)result->ai_addr; + if (fork() == 0) + { + listener(addr); + exit(0); + } + else + ping(addr); + wait(0); + return (0); +} From 66d9a2a5142fc5e568c1727b4155e64ae84b618b Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Sat, 13 May 2017 23:15:50 +0200 Subject: [PATCH 02/13] much progress, need to remove non blocking IO because its not allowed --- ping/.gitignore | 1 + ping/includes/{ft_ping.h => ping.h} | 6 +- ping/libft | 2 +- ping/srcs/ping.c | 126 ++++++++++++++++++---------- 4 files changed, 87 insertions(+), 48 deletions(-) create mode 100644 ping/.gitignore rename ping/includes/{ft_ping.h => ping.h} (93%) diff --git a/ping/.gitignore b/ping/.gitignore new file mode 100644 index 00000000..7c63a771 --- /dev/null +++ b/ping/.gitignore @@ -0,0 +1 @@ +ft_ping diff --git a/ping/includes/ft_ping.h b/ping/includes/ping.h similarity index 93% rename from ping/includes/ft_ping.h rename to ping/includes/ping.h index 9c727acf..c3343d9d 100644 --- a/ping/includes/ft_ping.h +++ b/ping/includes/ping.h @@ -17,6 +17,7 @@ # include # include # include +# include # include # include # include @@ -24,10 +25,11 @@ # include #define PACKETSIZE 64 + struct s_packet { - struct icmp icmp; - char msg[PACKETSIZE-sizeof(struct icmp)]; + struct icmp hdr; + char msg[PACKETSIZE - sizeof(struct icmp)]; }; #endif diff --git a/ping/libft b/ping/libft index 61ecc913..23c69f13 160000 --- a/ping/libft +++ b/ping/libft @@ -1 +1 @@ -Subproject commit 61ecc913bbc31dafab3fff2386e1cbfffd34596a +Subproject commit 23c69f13242ecbff493356c57cb1384eb1dd45f5 diff --git a/ping/srcs/ping.c b/ping/srcs/ping.c index a40cee6e..c3589fca 100644 --- a/ping/srcs/ping.c +++ b/ping/srcs/ping.c @@ -10,9 +10,11 @@ /* */ /* ************************************************************************** */ -#include "ft_ping.h" +#include "ping.h" -int g_pid=-1; +int g_pid=-1; +int g_pkt_rec=0; +char g_domain[256]; unsigned short checksum(void *b, int len) { @@ -32,63 +34,67 @@ unsigned short checksum(void *b, int len) void display(void *buf, int bytes, struct sockaddr_in *addr) { - int i; struct ip *ip = buf; - struct icmp *icmp = buf + ip->ip_hl*4; + struct icmp *icmp; + struct s_packet *pkt; + int hlen; + char addrstr[INET_ADDRSTRLEN]; + struct timeval start, end, triptime; + double diff; - printf("%d bytes from %s: ttl=%i\n", - ip->ip_len, inet_ntoa(addr->sin_addr), ip->ip_ttl); - printf("IPv%d: hrd-size=%d, pkt-size=%d, id=%d, frag-off=%d, protocol=%c\n, ttl=%i", - ip->ip_v, ip->ip_hl, ip->ip_len, ip->ip_id, ip->ip_off, ip->ip_p, ip->ip_ttl); - if (icmp->icmp_hun.ih_idseq.icd_id == g_pid) - { - printf("ICMP: type[%d/%d] checksum[%d] id[%d] seq[%d]\n", - icmp->icmp_type, icmp->icmp_code, ntohs(icmp->icmp_cksum), - icmp->icmp_hun.ih_idseq.icd_id, icmp->icmp_hun.ih_idseq.icd_seq); - (void)bytes; - } - for (i=0; i < bytes; i++) - { - if ( !(i & 15) ) printf("\n%i: ", i); - printf("%c ", ((char*)buf)[i]); - } - printf("\n"); + (void)bytes; + hlen = ip->ip_hl << 2; + pkt = (struct s_packet*)(buf + hlen); + icmp = &pkt->hdr; + start = *(struct timeval*)&pkt->msg; + + if (gettimeofday(&end, NULL) != 0) + return ; + timersub(&end, &start, &triptime); + diff = (triptime.tv_sec + triptime.tv_usec / 1000000.0) * 1000.0; + rs_push(diff); + g_pkt_rec++; + printf("%d bytes from %s: icmp_seq=%d ttl=%i time=%.3f ms\n", + ip->ip_len, + inet_ntop(AF_INET, &(addr->sin_addr), addrstr, INET_ADDRSTRLEN), + icmp->icmp_seq, ip->ip_ttl, diff); } -void listener(struct sockaddr_in *addr) -{ - int sd; - struct sockaddr_in r_addr; - int bytes; - socklen_t len; - unsigned char buf[1024]; - - if ((sd = socket(PF_INET, SOCK_DGRAM, IPPROTO_ICMP)) < 0) +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)); - len = sizeof(r_addr); - bytes = recvfrom(sd, buf, sizeof(buf), 0, (struct sockaddr*)&r_addr, &len); - if (bytes > 0) - display(buf, bytes, addr); + 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) { - const int val; + const int val = 255; int i; int sd; int cnt; socklen_t len; struct s_packet pkt; struct sockaddr_in r_addr; + struct timeval time; if ((sd = socket(PF_INET, SOCK_DGRAM, IPPROTO_ICMP)) < 0) { @@ -99,44 +105,74 @@ void ping(struct sockaddr_in *addr) perror("set TTL option"); if (fcntl(sd, F_SETFL, O_NONBLOCK) != 0) perror("Request non blocking IO"); - cnt = 1; + cnt = 0; while (1) { len = sizeof(r_addr); - recvfrom(sd, &pkt, sizeof(pkt), 0, (struct sockaddr*)&r_addr, &len); bzero(&pkt, sizeof(pkt)); - pkt.icmp.icmp_type = ICMP_ECHO; - pkt.icmp.icmp_hun.ih_idseq.icd_id = g_pid; + pkt.hdr.icmp_type = ICMP_ECHO; + pkt.hdr.icmp_id = g_pid; + pkt.hdr.icmp_seq = cnt++; + for (i=0; i < (int)sizeof(pkt.msg); i++) pkt.msg[i] = i+'0'; pkt.msg[i] = 0; - pkt.icmp.icmp_hun.ih_idseq.icd_seq = cnt++; - pkt.icmp.icmp_cksum = checksum(&pkt, sizeof(pkt)); + if (gettimeofday(&time, NULL) != 0) + return ; + 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); } } +void sigint_handler(int signo) +{ + double loss; + + (void)signo; + rs_calcmore(); + loss = g_rs.count ? 100 * ((float) (g_rs.count - g_pkt_rec) / (float)g_rs.count) : 0; + 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("\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); +} + int main(int ac, char **av) { struct sockaddr_in *addr; - struct addrinfo *result; + struct addrinfo *result, hints; + char addrstr[INET_ADDRSTRLEN]; if (ac != 2) { printf("usage: %s \n", av[0]); exit(1); } - if (getaddrinfo(av[1], NULL, NULL, &result) != 0) + memset (&hints, 0, sizeof (hints)); + hints.ai_family = PF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags |= AI_CANONNAME; + if (getaddrinfo(av[1], NULL, &hints, &result) != 0) { perror("getaddrinfo"); exit(1); } addr = (struct sockaddr_in*)result->ai_addr; + inet_ntop(AF_INET, &(addr->sin_addr), addrstr, INET_ADDRSTRLEN); + g_pid = getpid(); + ft_strcpy(g_domain, addrstr); + if (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); if (fork() == 0) { - listener(addr); + signal(SIGINT, sigint_handler); + rs_clear(); + listener(); exit(0); } else From ff629391b0aaa08d5fc004c563617c3983c9c107 Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Wed, 2 Aug 2017 19:21:37 +0200 Subject: [PATCH 03/13] stuff --- ping/Makefile | 5 +- ping/includes/ping.h | 1 + ping/libft | 2 +- ping/srcs/ping.c | 174 ++++++++++++++++--------------------------- 4 files changed, 70 insertions(+), 112 deletions(-) diff --git a/ping/Makefile b/ping/Makefile index 8023554f..57f53f08 100644 --- a/ping/Makefile +++ b/ping/Makefile @@ -10,6 +10,8 @@ # # # **************************************************************************** # +SHELL := bash + NAME = ft_ping CC = gcc @@ -44,7 +46,8 @@ $(NAME): $(LIBFT_LIB) $(OBJ_DIR) $(OBJS) $(CLIENT_OBJ) @$(CC) $(OBJS) -o $@ \ -I $(INC_DIR) \ -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" $(LIBFT_LIB): diff --git a/ping/includes/ping.h b/ping/includes/ping.h index c3343d9d..62399797 100644 --- a/ping/includes/ping.h +++ b/ping/includes/ping.h @@ -23,6 +23,7 @@ # include # include # include +# include #define PACKETSIZE 64 diff --git a/ping/libft b/ping/libft index 23c69f13..57475bda 160000 --- a/ping/libft +++ b/ping/libft @@ -1 +1 @@ -Subproject commit 23c69f13242ecbff493356c57cb1384eb1dd45f5 +Subproject commit 57475bdafefca069981276b44dd8c5d8998b5a13 diff --git a/ping/srcs/ping.c b/ping/srcs/ping.c index c3589fca..0fa5105b 100644 --- a/ping/srcs/ping.c +++ b/ping/srcs/ping.c @@ -6,177 +6,131 @@ /* 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" +#define TIME_START 0 +#define TIME_END 1 +#define TIME_TRIPTIME 2 -int g_pid=-1; -int g_pkt_rec=0; -char g_domain[256]; +int g_pid = -1; +int g_pkt_rec = 0; +char g_domain[256]; +struct s_stats g_rs; -unsigned short checksum(void *b, int len) +void display(void *buf, int bytes, struct sockaddr_in *addr) { - 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) -{ - struct ip *ip = buf; - struct icmp *icmp; + struct ip *ip; + struct icmp *icmp; struct s_packet *pkt; - int hlen; - char addrstr[INET_ADDRSTRLEN]; - struct timeval start, end, triptime; - double diff; + int hlen; + double triptime; + ip = buf; (void)bytes; hlen = ip->ip_hl << 2; pkt = (struct s_packet*)(buf + hlen); icmp = &pkt->hdr; - start = *(struct timeval*)&pkt->msg; - - if (gettimeofday(&end, NULL) != 0) + if (icmp->icmp_id != g_pid) return ; - timersub(&end, &start, &triptime); - diff = (triptime.tv_sec + triptime.tv_usec / 1000000.0) * 1000.0; - rs_push(diff); + triptime = time_milli() - *(double*)&pkt->msg; + rs_push(triptime); g_pkt_rec++; printf("%d bytes from %s: icmp_seq=%d ttl=%i time=%.3f ms\n", ip->ip_len, - inet_ntop(AF_INET, &(addr->sin_addr), addrstr, INET_ADDRSTRLEN), - icmp->icmp_seq, ip->ip_ttl, diff); + inet_ntop(AF_INET, &(addr->sin_addr), g_domain, INET_ADDRSTRLEN), + 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 cnt; - socklen_t len; struct s_packet pkt; - struct sockaddr_in r_addr; - struct timeval time; + double epoch; - if ((sd = socket(PF_INET, SOCK_DGRAM, IPPROTO_ICMP)) < 0) - { - perror("socket"); - return ; - } - if (setsockopt(sd, 0, IP_TTL, &val, sizeof(val)) != 0) + if ((sd = socket(PF_INET, SOCK_RAW, IPPROTO_ICMP)) < 0) + return (perror("sender socket")); + if (setsockopt(sd, 0, IP_TTL, (int[]){255, 0}, sizeof(int)) != 0) perror("set TTL option"); - if (fcntl(sd, F_SETFL, O_NONBLOCK) != 0) - perror("Request non blocking IO"); cnt = 0; while (1) { - len = sizeof(r_addr); bzero(&pkt, sizeof(pkt)); pkt.hdr.icmp_type = ICMP_ECHO; pkt.hdr.icmp_id = g_pid; pkt.hdr.icmp_seq = cnt++; - - for (i=0; i < (int)sizeof(pkt.msg); i++) - pkt.msg[i] = i+'0'; - pkt.msg[i] = 0; - if (gettimeofday(&time, NULL) != 0) - return ; - 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"); + epoch = time_milli(); + ft_memcpy(pkt.msg, (void*)&epoch, sizeof(epoch)); + pkt.hdr.icmp_cksum = cksum(&pkt, sizeof(pkt)); + if (sendto(sd, &pkt, sizeof(pkt), 0, + (struct sockaddr*)addr, sizeof(*addr)) <= 0) + return (perror("sendto")); sleep(1); } } -void sigint_handler(int signo) +void stats_recap(int signo) { double loss; (void)signo; 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%d packets transmitted, %d packets received, %0.1f%% packet loss", 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); + printf("\n%d packets transmitted, %d packets received, %0.1f%% packet loss", + 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); } -int main(int ac, char **av) +struct addrinfo *resolve_host(char *hostname) { + struct addrinfo *result; + struct addrinfo hints; struct sockaddr_in *addr; - struct addrinfo *result, hints; - char addrstr[INET_ADDRSTRLEN]; - if (ac != 2) - { - printf("usage: %s \n", av[0]); - exit(1); - } - memset (&hints, 0, sizeof (hints)); + memset(&hints, 0, sizeof(hints)); hints.ai_family = PF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_flags |= AI_CANONNAME; - if (getaddrinfo(av[1], NULL, &hints, &result) != 0) + if (getaddrinfo(hostname, NULL, &hints, &result) != 0) { perror("getaddrinfo"); exit(1); } addr = (struct sockaddr_in*)result->ai_addr; - inet_ntop(AF_INET, &(addr->sin_addr), addrstr, INET_ADDRSTRLEN); - g_pid = getpid(); - ft_strcpy(g_domain, addrstr); + inet_ntop(AF_INET, &(addr->sin_addr), g_domain, INET_ADDRSTRLEN); if (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 \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) { - signal(SIGINT, sigint_handler); + signal(SIGINT, stats_recap); rs_clear(); - listener(); - exit(0); + listener(PF_INET, SOCK_RAW, IPPROTO_ICMP, &display); } - else - ping(addr); - wait(0); + ping((struct sockaddr_in*)result->ai_addr); return (0); } From 728fc5b2965f359ac276e584af8d6723a5b3b4e5 Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Sun, 8 Oct 2017 14:37:05 +0200 Subject: [PATCH 04/13] norme --- ping/Makefile | 2 +- ping/includes/ping.h | 10 +++++----- ping/libft | 2 +- ping/srcs/ping.c | 6 +++--- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/ping/Makefile b/ping/Makefile index 57f53f08..9503eed4 100644 --- a/ping/Makefile +++ b/ping/Makefile @@ -6,7 +6,7 @@ # By: wescande +#+ +:+ +#+ # # +#+#+#+#+#+ +#+ # # Created: 2016/08/29 21:32:58 by wescande #+# #+# # -# Updated: 2017/04/22 19:26:34 by jhalford ### ########.fr # +# Updated: 2017/10/08 14:36:33 by jhalford ### ########.fr # # # # **************************************************************************** # diff --git a/ping/includes/ping.h b/ping/includes/ping.h index 62399797..590698e2 100644 --- a/ping/includes/ping.h +++ b/ping/includes/ping.h @@ -6,7 +6,7 @@ /* By: jhalford +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2017/04/22 14:10:24 by jhalford #+# #+# */ -/* Updated: 2017/04/22 15:52:07 by jhalford ### ########.fr */ +/* Updated: 2017/10/08 14:36:37 by jhalford ### ########.fr */ /* */ /* ************************************************************************** */ @@ -25,12 +25,12 @@ # include # include -#define PACKETSIZE 64 +# define PACKETSIZE 64 -struct s_packet +struct s_packet { - struct icmp hdr; - char msg[PACKETSIZE - sizeof(struct icmp)]; + struct icmp hdr; + char msg[PACKETSIZE - sizeof(struct icmp)]; }; #endif diff --git a/ping/libft b/ping/libft index 57475bda..0da748d1 160000 --- a/ping/libft +++ b/ping/libft @@ -1 +1 @@ -Subproject commit 57475bdafefca069981276b44dd8c5d8998b5a13 +Subproject commit 0da748d10513bbc70705998fb5ac914c1047c6dc diff --git a/ping/srcs/ping.c b/ping/srcs/ping.c index 0fa5105b..c3a45e2d 100644 --- a/ping/srcs/ping.c +++ b/ping/srcs/ping.c @@ -6,7 +6,7 @@ /* By: jhalford +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2017/04/22 14:10:24 by jhalford #+# #+# */ -/* Updated: 2017/10/08 14:26:15 by jhalford ### ########.fr */ +/* Updated: 2017/10/08 14:35:02 by jhalford ### ########.fr */ /* */ /* ************************************************************************** */ @@ -122,9 +122,9 @@ int main(int ac, char **av) result = resolve_host(av[1]); if (result->ai_canonname) printf("PING %s (%s): %i data bytes\n", - result->ai_canonname, g_domain, 64); + result->ai_canonname, g_domain, PACKETSIZE); else - printf("PING %s: %i data bytes\n", g_domain, 64); + printf("PING %s: %i data bytes\n", g_domain, PACKETSIZE); if (fork() == 0) { signal(SIGINT, stats_recap); From c90606706babfef1554873ba8cb0a092d815e2bf Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Mon, 13 Nov 2017 15:33:42 +0100 Subject: [PATCH 05/13] stuff --- ping/includes/ping.h | 21 ++++++++ ping/srcs/ping.c | 112 +++++++++++++++++++++---------------------- 2 files changed, 75 insertions(+), 58 deletions(-) diff --git a/ping/includes/ping.h b/ping/includes/ping.h index 590698e2..9b3cfb06 100644 --- a/ping/includes/ping.h +++ b/ping/includes/ping.h @@ -27,6 +27,27 @@ # define PACKETSIZE 64 +typedef struct s_ping t_ping; + +struct s_ping +{ + pid_t pid; + t_rs rs; + int pkt_sent; + int pkt_recv; + int sock; + struct addrinfo *sa; + union + { + char ip4[INET_ADDRSTRLEN]; + char ip6[INET6_ADDRSTRLEN]; + } ip; +#define ip4 ip.ip4 +#define ip6 ip.ip6 +}; + +extern t_ping g_ping; + struct s_packet { struct icmp hdr; diff --git a/ping/srcs/ping.c b/ping/srcs/ping.c index c3a45e2d..6babb3be 100644 --- a/ping/srcs/ping.c +++ b/ping/srcs/ping.c @@ -15,86 +15,78 @@ #define TIME_END 1 #define TIME_TRIPTIME 2 -int g_pid = -1; -int g_pkt_rec = 0; -char g_domain[256]; -struct s_stats g_rs; +t_ping g_ping = +{ + .pid = -1, + .pkt_sent = -1, + .pkt_recv = 0, +}; -void display(void *buf, int bytes, struct sockaddr_in *addr) +void display(void *buf, int bytes, struct sockaddr_in *addr) { struct ip *ip; struct icmp *icmp; struct s_packet *pkt; int hlen; double triptime; + char strbuf[INET_ADDRSTRLEN]; ip = buf; (void)bytes; hlen = ip->ip_hl << 2; pkt = (struct s_packet*)(buf + hlen); icmp = &pkt->hdr; - if (icmp->icmp_id != g_pid) + if (icmp->icmp_id != g_ping.pid) return ; triptime = time_milli() - *(double*)&pkt->msg; - rs_push(triptime); - g_pkt_rec++; + rs_push(&g_ping.rs, triptime); + g_ping.pkt_recv++; printf("%d bytes from %s: icmp_seq=%d ttl=%i time=%.3f ms\n", ip->ip_len, - inet_ntop(AF_INET, &(addr->sin_addr), g_domain, INET_ADDRSTRLEN), + inet_ntop(AF_INET, &(addr->sin_addr), strbuf, INET_ADDRSTRLEN), icmp->icmp_seq, ip->ip_ttl, triptime); } -void ping(struct sockaddr_in *addr) +void ping(int signo) { - int sd; - int cnt; struct s_packet pkt; double epoch; - if ((sd = socket(PF_INET, SOCK_RAW, IPPROTO_ICMP)) < 0) - return (perror("sender socket")); - if (setsockopt(sd, 0, IP_TTL, (int[]){255, 0}, sizeof(int)) != 0) - perror("set TTL option"); - cnt = 0; - while (1) - { - bzero(&pkt, sizeof(pkt)); - pkt.hdr.icmp_type = ICMP_ECHO; - pkt.hdr.icmp_id = g_pid; - pkt.hdr.icmp_seq = cnt++; - epoch = time_milli(); - ft_memcpy(pkt.msg, (void*)&epoch, sizeof(epoch)); - pkt.hdr.icmp_cksum = cksum(&pkt, sizeof(pkt)); - if (sendto(sd, &pkt, sizeof(pkt), 0, - (struct sockaddr*)addr, sizeof(*addr)) <= 0) - return (perror("sendto")); - sleep(1); - } + (void)signo; + bzero(&pkt, sizeof(pkt)); + pkt.hdr.icmp_type = ICMP_ECHO; + pkt.hdr.icmp_id = g_ping.pid; + pkt.hdr.icmp_seq = ++g_ping.pkt_sent; + epoch = time_milli(); + ft_memcpy(pkt.msg, (void*)&epoch, sizeof(epoch)); + pkt.hdr.icmp_cksum = cksum(&pkt, sizeof(pkt)); + sendto(g_ping.sock, &pkt, sizeof(pkt), 0, g_ping.sa->ai_addr, + sizeof(struct sockaddr)); } -void stats_recap(int signo) +void stats_recap(int signo) { double loss; (void)signo; - rs_calcmore(); - loss = FT_PCT(g_pkt_rec, g_rs.count); - printf("\n--- %s ping statistics ---", g_domain); + rs_final(&g_ping.rs); + loss = FT_PCT(g_ping.pkt_recv, g_ping.pkt_sent); + printf("\n--- %s ping statistics ---", g_ping.ip4); printf("\n%d packets transmitted, %d packets received, %0.1f%% packet loss", - g_rs.count, g_pkt_rec, loss); + g_ping.rs.count, g_ping.pkt_recv, 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_ping.rs.min, g_ping.rs.avg, g_ping.rs.max, g_ping.rs.stdev); + freeaddrinfo(g_ping.sa); exit(0); } -struct addrinfo *resolve_host(char *hostname) +int resolve_host(char *hostname, t_ping *ping) { struct addrinfo *result; struct addrinfo hints; - struct sockaddr_in *addr; memset(&hints, 0, sizeof(hints)); - hints.ai_family = PF_UNSPEC; + hints.ai_family = PF_INET; hints.ai_socktype = SOCK_STREAM; hints.ai_flags |= AI_CANONNAME; if (getaddrinfo(hostname, NULL, &hints, &result) != 0) @@ -102,35 +94,39 @@ struct addrinfo *resolve_host(char *hostname) perror("getaddrinfo"); exit(1); } - addr = (struct sockaddr_in*)result->ai_addr; - inet_ntop(AF_INET, &(addr->sin_addr), g_domain, INET_ADDRSTRLEN); - if (result->ai_canonname) - ft_strcpy(g_domain, result->ai_canonname); - return (result); + ping->sa = result; + inet_ntop(AF_INET, &(((struct sockaddr_in*)ping->sa->ai_addr)->sin_addr), ping->ip4, INET_ADDRSTRLEN); + return (0); } -int main(int ac, char **av) +int main(int ac, char **av) { - struct addrinfo *result; - if (ac != 2) { ft_usage("%s \n", av[0]); exit(1); } - g_pid = getpid(); - result = resolve_host(av[1]); - if (result->ai_canonname) + resolve_host(av[1], &g_ping); + if (g_ping.sa->ai_canonname) printf("PING %s (%s): %i data bytes\n", - result->ai_canonname, g_domain, PACKETSIZE); + g_ping.sa->ai_canonname, g_ping.ip4, PACKETSIZE); else - printf("PING %s: %i data bytes\n", g_domain, PACKETSIZE); - if (fork() == 0) + printf("PING %s: %i data bytes\n", g_ping.ip4, PACKETSIZE); + if ((g_ping.sock = socket(PF_INET, SOCK_RAW, IPPROTO_ICMP)) < 0) { - signal(SIGINT, stats_recap); - rs_clear(); - listener(PF_INET, SOCK_RAW, IPPROTO_ICMP, &display); + ft_dprintf(2, "socket(2) error\n"); + exit(1); } - ping((struct sockaddr_in*)result->ai_addr); + if (setsockopt(g_ping.sock, 0, IP_TTL, (int[]){255, 0}, sizeof(int)) != 0) + { + ft_dprintf(2, "setsockopt(2) error\n"); + exit(1); + } + g_ping.pid = getpid(); + rs_init(&g_ping.rs); + signal(SIGINT, stats_recap); + signal(SIGALRM, ping); + alarm(1); + listener(PF_INET, SOCK_RAW, IPPROTO_ICMP, &display); return (0); } From 1c980a35ccdb783ff30007e8b33f6a7526dca3c9 Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Mon, 13 Nov 2017 16:24:40 +0100 Subject: [PATCH 06/13] libft: --- ping/libft | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ping/libft b/ping/libft index 0da748d1..de5fb7c0 160000 --- a/ping/libft +++ b/ping/libft @@ -1 +1 @@ -Subproject commit 0da748d10513bbc70705998fb5ac914c1047c6dc +Subproject commit de5fb7c07d5ffe0009b2d5b459b23c8487a32a16 From 26892b9cf7fd4ebf723a725e4cb8e76a9a515c52 Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Mon, 13 Nov 2017 16:25:13 +0100 Subject: [PATCH 07/13] libft --- ping/libft | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ping/libft b/ping/libft index 0da748d1..de5fb7c0 160000 --- a/ping/libft +++ b/ping/libft @@ -1 +1 @@ -Subproject commit 0da748d10513bbc70705998fb5ac914c1047c6dc +Subproject commit de5fb7c07d5ffe0009b2d5b459b23c8487a32a16 From 76a06c4fc96da366c5889660326a270261aa2d58 Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Thu, 16 Nov 2017 21:39:20 +0100 Subject: [PATCH 08/13] more stuff --- ping/srcs/ping.c | 65 +++++++++++++++++++++++++++--------------------- 1 file changed, 37 insertions(+), 28 deletions(-) diff --git a/ping/srcs/ping.c b/ping/srcs/ping.c index 6babb3be..b767e991 100644 --- a/ping/srcs/ping.c +++ b/ping/srcs/ping.c @@ -11,8 +11,7 @@ /* ************************************************************************** */ #include "ping.h" -#define TIME_START 0 -#define TIME_END 1 +#define TIME_START 0 #define TIME_END 1 #define TIME_TRIPTIME 2 t_ping g_ping = @@ -22,14 +21,35 @@ t_ping g_ping = .pkt_recv = 0, }; -void display(void *buf, int bytes, struct sockaddr_in *addr) +int resolve_host(char *node, t_ping *ping) +{ + struct addrinfo *result; + struct addrinfo hints; + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = PF_INET; + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags |= AI_CANONNAME; + if (getaddrinfo(node, NULL, &hints, &result) != 0) + { + perror("getaddrinfo"); + exit(1); + } + ping->sa = result; + inet_ntop(AF_INET, &(((struct sockaddr_in*)ping->sa->ai_addr)->sin_addr), ping->ip4, INET_ADDRSTRLEN); + return (0); +} + + +void display(void *buf, int bytes, struct sockaddr *addr) { struct ip *ip; struct icmp *icmp; struct s_packet *pkt; int hlen; double triptime; - char strbuf[INET_ADDRSTRLEN]; + char hbuf[NI_MAXHOST]; + char ipbuf[INET_ADDRSTRLEN]; ip = buf; (void)bytes; @@ -41,10 +61,17 @@ void display(void *buf, int bytes, struct sockaddr_in *addr) triptime = time_milli() - *(double*)&pkt->msg; rs_push(&g_ping.rs, triptime); g_ping.pkt_recv++; - printf("%d bytes from %s: icmp_seq=%d ttl=%i time=%.3f ms\n", - ip->ip_len, - inet_ntop(AF_INET, &(addr->sin_addr), strbuf, INET_ADDRSTRLEN), - icmp->icmp_seq, ip->ip_ttl, triptime); + + bzero(hbuf, NI_MAXHOST); + bzero(ipbuf, INET_ADDRSTRLEN); + getnameinfo(addr, sizeof(struct sockaddr_in), ipbuf, INET_ADDRSTRLEN, NULL, 0, NI_NUMERICHOST); + if (getnameinfo(addr, sizeof(struct sockaddr_in), hbuf, NI_MAXHOST, NULL, 0, 0) == 0) + printf("%d bytes from %s (%s): icmp_seq=%d ttl=%i time=%.1f ms\n", + hlen, hbuf, ipbuf, icmp->icmp_seq, ip->ip_ttl, triptime); + else + printf("%d bytes from %s: icmp_seq=%d ttl=%i time=%.1f ms\n", + hlen, ipbuf, icmp->icmp_seq, ip->ip_ttl, triptime); + } void ping(int signo) @@ -58,10 +85,11 @@ void ping(int signo) pkt.hdr.icmp_id = g_ping.pid; pkt.hdr.icmp_seq = ++g_ping.pkt_sent; epoch = time_milli(); - ft_memcpy(pkt.msg, (void*)&epoch, sizeof(epoch)); + ft_memcpy(pkt.msg, (void*)&epoch, sizeof(double)); pkt.hdr.icmp_cksum = cksum(&pkt, sizeof(pkt)); sendto(g_ping.sock, &pkt, sizeof(pkt), 0, g_ping.sa->ai_addr, sizeof(struct sockaddr)); + alarm(1); } void stats_recap(int signo) @@ -80,25 +108,6 @@ void stats_recap(int signo) exit(0); } -int resolve_host(char *hostname, t_ping *ping) -{ - struct addrinfo *result; - struct addrinfo hints; - - memset(&hints, 0, sizeof(hints)); - hints.ai_family = PF_INET; - hints.ai_socktype = SOCK_STREAM; - hints.ai_flags |= AI_CANONNAME; - if (getaddrinfo(hostname, NULL, &hints, &result) != 0) - { - perror("getaddrinfo"); - exit(1); - } - ping->sa = result; - inet_ntop(AF_INET, &(((struct sockaddr_in*)ping->sa->ai_addr)->sin_addr), ping->ip4, INET_ADDRSTRLEN); - return (0); -} - int main(int ac, char **av) { if (ac != 2) From 71d6e49acb44472b6496d28918995660a1b45f2a Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Sun, 19 Nov 2017 21:38:41 +0100 Subject: [PATCH 09/13] some code --- ping/Makefile | 2 ++ ping/includes/ping.h | 9 +----- ping/srcs/ping.c | 76 ++++++++++++++++++++++++++++---------------- 3 files changed, 51 insertions(+), 36 deletions(-) diff --git a/ping/Makefile b/ping/Makefile index 9503eed4..61823b4c 100644 --- a/ping/Makefile +++ b/ping/Makefile @@ -49,6 +49,8 @@ $(NAME): $(LIBFT_LIB) $(OBJ_DIR) $(OBJS) $(CLIENT_OBJ) $(LIBFT_LIB) $(CLIENT_OBJ) $(FLAGS) \ -lm @printf "\r\033[38;5;117m✓ MAKE $@ \033[0m\033[K\n" + @sudo setcap cap_net_raw+ep $@ + @printf "\r\033[38;5;117m✓ SETCAP $@ \033[0m\033[K\n" $(LIBFT_LIB): @make -C $(LIBFT_DIR) diff --git a/ping/includes/ping.h b/ping/includes/ping.h index 9b3cfb06..3835cf7e 100644 --- a/ping/includes/ping.h +++ b/ping/includes/ping.h @@ -25,12 +25,11 @@ # include # include -# define PACKETSIZE 64 - typedef struct s_ping t_ping; struct s_ping { + size_t pkt_size; pid_t pid; t_rs rs; int pkt_sent; @@ -48,10 +47,4 @@ struct s_ping extern t_ping g_ping; -struct s_packet -{ - struct icmp hdr; - char msg[PACKETSIZE - sizeof(struct icmp)]; -}; - #endif diff --git a/ping/srcs/ping.c b/ping/srcs/ping.c index b767e991..ab7527b1 100644 --- a/ping/srcs/ping.c +++ b/ping/srcs/ping.c @@ -11,12 +11,11 @@ /* ************************************************************************** */ #include "ping.h" -#define TIME_START 0 #define TIME_END 1 -#define TIME_TRIPTIME 2 t_ping g_ping = { .pid = -1, + .pkt_size = 56, .pkt_sent = -1, .pkt_recv = 0, }; @@ -36,16 +35,26 @@ int resolve_host(char *node, t_ping *ping) exit(1); } ping->sa = result; - inet_ntop(AF_INET, &(((struct sockaddr_in*)ping->sa->ai_addr)->sin_addr), ping->ip4, INET_ADDRSTRLEN); + inet_ntop(AF_INET, &(((struct sockaddr_in*)ping->sa->ai_addr)->sin_addr), + ping->ip4, INET_ADDRSTRLEN); return (0); } +void display_time_exceeded(struct sockaddr *addr, struct icmp *icmp) +{ + char ipbuf[INET_ADDRSTRLEN]; + + bzero(ipbuf, INET_ADDRSTRLEN); + getnameinfo(addr, sizeof(struct sockaddr_in), ipbuf, INET_ADDRSTRLEN, + NULL, 0, NI_NUMERICHOST); + printf("From %s icmp_seq=%d Time to live exceeded\n", + ipbuf, icmp->icmp_id); +} void display(void *buf, int bytes, struct sockaddr *addr) { struct ip *ip; struct icmp *icmp; - struct s_packet *pkt; int hlen; double triptime; char hbuf[NI_MAXHOST]; @@ -54,39 +63,48 @@ void display(void *buf, int bytes, struct sockaddr *addr) ip = buf; (void)bytes; hlen = ip->ip_hl << 2; - pkt = (struct s_packet*)(buf + hlen); - icmp = &pkt->hdr; - if (icmp->icmp_id != g_ping.pid) + icmp = (struct icmp*)(buf + hlen); + if (icmp->icmp_type == ICMP_TIME_EXCEEDED) + return (display_time_exceeded(addr, icmp)); + else if (icmp->icmp_id != g_ping.pid) + { + dprintf(2, "id = %i\n", icmp->icmp_id); return ; - triptime = time_milli() - *(double*)&pkt->msg; + } + triptime = time_milli() - *(double*)(icmp + 1); rs_push(&g_ping.rs, triptime); g_ping.pkt_recv++; bzero(hbuf, NI_MAXHOST); bzero(ipbuf, INET_ADDRSTRLEN); - getnameinfo(addr, sizeof(struct sockaddr_in), ipbuf, INET_ADDRSTRLEN, NULL, 0, NI_NUMERICHOST); + getnameinfo(addr, sizeof(struct sockaddr_in), ipbuf, INET_ADDRSTRLEN, + NULL, 0, NI_NUMERICHOST); if (getnameinfo(addr, sizeof(struct sockaddr_in), hbuf, NI_MAXHOST, NULL, 0, 0) == 0) - printf("%d bytes from %s (%s): icmp_seq=%d ttl=%i time=%.1f ms\n", - hlen, hbuf, ipbuf, icmp->icmp_seq, ip->ip_ttl, triptime); + printf("%zu bytes from %s (%s): icmp_seq=%d ttl=%i time=%.1f ms\n", + bytes - hlen - sizeof(struct icmphdr), hbuf, ipbuf, icmp->icmp_seq, ip->ip_ttl, triptime); else - printf("%d bytes from %s: icmp_seq=%d ttl=%i time=%.1f ms\n", - hlen, ipbuf, icmp->icmp_seq, ip->ip_ttl, triptime); + printf("%zu bytes from %s: icmp_seq=%d ttl=%i time=%.1f ms\n", + bytes - hlen - sizeof(struct icmphdr), ipbuf, icmp->icmp_seq, ip->ip_ttl, triptime); } void ping(int signo) { - struct s_packet pkt; + char pkt[g_ping.pkt_size + sizeof(struct icmp)]; + double *msg; + struct icmp *hdr; double epoch; (void)signo; + hdr = (struct icmp*)&pkt; bzero(&pkt, sizeof(pkt)); - pkt.hdr.icmp_type = ICMP_ECHO; - pkt.hdr.icmp_id = g_ping.pid; - pkt.hdr.icmp_seq = ++g_ping.pkt_sent; + hdr->icmp_type = ICMP_ECHO; + hdr->icmp_id = g_ping.pid; + hdr->icmp_seq = ++g_ping.pkt_sent; + msg = (double*)(pkt + sizeof(struct icmp)); epoch = time_milli(); - ft_memcpy(pkt.msg, (void*)&epoch, sizeof(double)); - pkt.hdr.icmp_cksum = cksum(&pkt, sizeof(pkt)); + ft_memcpy(msg, (void*)&epoch, sizeof(double)); + hdr->icmp_cksum = cksum(&pkt, sizeof(pkt)); sendto(g_ping.sock, &pkt, sizeof(pkt), 0, g_ping.sa->ai_addr, sizeof(struct sockaddr)); alarm(1); @@ -99,10 +117,10 @@ void stats_recap(int signo) (void)signo; rs_final(&g_ping.rs); loss = FT_PCT(g_ping.pkt_recv, g_ping.pkt_sent); - printf("\n--- %s ping statistics ---", g_ping.ip4); + printf("\n--- %s ping statistics ---", g_ping.sa->ai_canonname); printf("\n%d packets transmitted, %d packets received, %0.1f%% packet loss", - g_ping.rs.count, g_ping.pkt_recv, loss); - printf("\nround-trip min/avg/max/stddev = %.3f/%.3f/%.3f/%.3f ms", + g_ping.pkt_sent, g_ping.pkt_recv, loss); + printf("\nrtt min/avg/max/stddev = %.3f/%.3f/%.3f/%.3f ms\n", g_ping.rs.min, g_ping.rs.avg, g_ping.rs.max, g_ping.rs.stdev); freeaddrinfo(g_ping.sa); exit(0); @@ -117,18 +135,20 @@ int main(int ac, char **av) } resolve_host(av[1], &g_ping); if (g_ping.sa->ai_canonname) - printf("PING %s (%s): %i data bytes\n", - g_ping.sa->ai_canonname, g_ping.ip4, PACKETSIZE); + printf("PING %s (%s): %zu(%zu) data bytes\n", + g_ping.sa->ai_canonname, g_ping.ip4, + g_ping.pkt_size, g_ping.pkt_size + sizeof(struct icmp)); else - printf("PING %s: %i data bytes\n", g_ping.ip4, PACKETSIZE); + printf("PING %s: %zu(%zu) data bytes\n", g_ping.ip4, + g_ping.pkt_size, g_ping.pkt_size + sizeof(struct icmp)); if ((g_ping.sock = socket(PF_INET, SOCK_RAW, IPPROTO_ICMP)) < 0) { - ft_dprintf(2, "socket(2) error\n"); + perror("socket"); exit(1); } - if (setsockopt(g_ping.sock, 0, IP_TTL, (int[]){255, 0}, sizeof(int)) != 0) + if (setsockopt(g_ping.sock, 0, IP_TTL, (int[]){255}, sizeof(int)) != 0) { - ft_dprintf(2, "setsockopt(2) error\n"); + perror("setsockopt"); exit(1); } g_ping.pid = getpid(); From da72d6e922645ab438ae8dda23d4af783c99579b Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Fri, 24 Nov 2017 00:48:00 +0100 Subject: [PATCH 10/13] libft submodule commit --- ping/libft | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ping/libft b/ping/libft index de5fb7c0..4563133f 160000 --- a/ping/libft +++ b/ping/libft @@ -1 +1 @@ -Subproject commit de5fb7c07d5ffe0009b2d5b459b23c8487a32a16 +Subproject commit 4563133fc6afe6034da8b3bc8c0391b52df1352f From dff0d5f79eae69f7998b57aab8afd2efe96ba6be Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Mon, 27 Nov 2017 17:28:56 +0000 Subject: [PATCH 11/13] libft gone --- ping/.gitmodules | 3 --- ping/libft | 1 - 2 files changed, 4 deletions(-) delete mode 100644 ping/.gitmodules delete mode 160000 ping/libft diff --git a/ping/.gitmodules b/ping/.gitmodules deleted file mode 100644 index c82793fb..00000000 --- a/ping/.gitmodules +++ /dev/null @@ -1,3 +0,0 @@ -[submodule "libft"] - path = libft - url = https://github.com/jzck/libft diff --git a/ping/libft b/ping/libft deleted file mode 160000 index 4563133f..00000000 --- a/ping/libft +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 4563133fc6afe6034da8b3bc8c0391b52df1352f From ee26baea8a5e0bf4589010029b2bbdc64428c764 Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Mon, 27 Nov 2017 18:15:35 +0000 Subject: [PATCH 12/13] refactor for docker ubuntu, no more libft --- ping/Makefile | 64 ++++++++++---------------------------- ping/cksum.c | 31 ++++++++++++++++++ ping/create_client.c | 59 +++++++++++++++++++++++++++++++++++ ping/epoch.c | 31 ++++++++++++++++++ ping/{srcs => }/ping.c | 4 +-- ping/{includes => }/ping.h | 18 +++++++++-- ping/rs.c | 61 ++++++++++++++++++++++++++++++++++++ ping/rs.h | 37 ++++++++++++++++++++++ 8 files changed, 254 insertions(+), 51 deletions(-) create mode 100644 ping/cksum.c create mode 100644 ping/create_client.c create mode 100644 ping/epoch.c rename ping/{srcs => }/ping.c (98%) rename ping/{includes => }/ping.h (79%) create mode 100644 ping/rs.c create mode 100644 ping/rs.h diff --git a/ping/Makefile b/ping/Makefile index 61823b4c..11b6c1c0 100644 --- a/ping/Makefile +++ b/ping/Makefile @@ -15,6 +15,7 @@ SHELL := bash NAME = ft_ping CC = gcc +RM = rm -rf 2>&- W_FLAGS = -Wall -Wextra -Werror D_FLAGS = FLAGS = $(W_FLAGS) $(D_FLAGS) @@ -22,16 +23,16 @@ FLAGS = $(W_FLAGS) $(D_FLAGS) LEN_NAME = `printf "%s" $(NAME) |wc -c` DELTA = $$(echo "$$(tput cols)-31-$(LEN_NAME)"|bc) -LIBFT_DIR = libft/ -LIBFT_LIB = $(LIBFT_DIR)libft.a -LIBFT_INC = $(LIBFT_DIR)includes/ - -SRC_DIR = srcs/ -INC_DIR = includes/ +SRC_DIR = ./ +INC_DIR = ./ OBJ_DIR = objs/ SRC_BASE = \ ping.c\ +create_client.c\ +epoch.c\ +cksum.c\ +rs.c\ SRCS = $(addprefix $(SRC_DIR), $(SRC_BASE)) OBJS = $(addprefix $(OBJ_DIR), $(SRC_BASE:.c=.o)) @@ -39,60 +40,29 @@ NB = $(words $(SRC_BASE)) INDEX = 0 all : - @make -C $(LIBFT_DIR) @make -j $(NAME) -$(NAME): $(LIBFT_LIB) $(OBJ_DIR) $(OBJS) $(CLIENT_OBJ) - @$(CC) $(OBJS) -o $@ \ +$(NAME): $(OBJ_DIR) $(OBJS) $(CLIENT_OBJ) + $(CC) $(OBJS) -o $@ \ -I $(INC_DIR) \ - -I $(LIBFT_INC) \ - $(LIBFT_LIB) $(CLIENT_OBJ) $(FLAGS) \ + $(CLIENT_OBJ) $(FLAGS) \ -lm - @printf "\r\033[38;5;117m✓ MAKE $@ \033[0m\033[K\n" - @sudo setcap cap_net_raw+ep $@ - @printf "\r\033[38;5;117m✓ SETCAP $@ \033[0m\033[K\n" - -$(LIBFT_LIB): - @make -C $(LIBFT_DIR) + # sudo setcap cap_net_raw+ep $@ 2>&- $(OBJ_DIR) : @mkdir -p $(OBJ_DIR) $(OBJ_DIR)%.o : $(SRC_DIR)%.c | $(OBJ_DIR) - @$(eval DONE=$(shell echo $$(($(INDEX)*20/$(NB))))) - @$(eval PERCENT=$(shell echo $$(($(INDEX)*100/$(NB))))) - @$(eval TO_DO=$(shell echo $$((20-$(INDEX)*20/$(NB) - 1)))) - @$(eval COLOR=$(shell list=(160 196 202 208 215 221 226 227 190 154 118 82 46); index=$$(($(PERCENT) * $${#list[@]} / 100)); echo "$${list[$$index]}")) - @printf "\r\033[38;5;%dm⌛ [%s]: %2d%% `printf '█%.0s' {0..$(DONE)}`%*s❙%*.*s\033[0m\033[K" $(COLOR) ft_p $(PERCENT) $(TO_DO) "" $(DELTA) $(DELTA) "$(shell echo "$@" | sed 's/^.*\///')" - @$(CC) $(FLAGS) $(OBJ_FLAG) -MMD -c $< -o $@\ - -I $(INC_DIR)\ - -I $(LIBFT_INC) - @$(eval INDEX=$(shell echo $$(($(INDEX)+1)))) + $(CC) $(FLAGS) $(OBJ_FLAG) -MMD -c $< -o $@ -I $(INC_DIR) -clean: cleanlib - @if [ -e $(OBJ_DIR) ]; then \ - rm -rf $(OBJ_DIR); \ - printf "\r\033[38;5;202m✗ clean $(NAME) \033[0m\033[K\n"; \ - fi; - -cleanlib: - @make -C $(LIBFT_DIR) clean - -fclean: clean fcleanlib - @for file in $(NAME); do \ - if [ -e $$file ]; then \ - rm -f $$file ; \ - printf "\r\033[38;5;196m✗ fclean $$file\033[0m\033[K\n"; \ - fi; \ - done; - -fcleanlib: cleanlib - @make -C $(LIBFT_DIR) fclean +clean: + $(RM) $(OBJ_DIR) re: fclean all -relib: fcleanlib $(LIBFT_LIB) +fclean: clean + $(RM) $(NAME) -.PHONY : fclean clean re relib cleanlib fcleanlib +.PHONY : fclean clean re -include $(OBJS:.o=.d) diff --git a/ping/cksum.c b/ping/cksum.c new file mode 100644 index 00000000..e4da4227 --- /dev/null +++ b/ping/cksum.c @@ -0,0 +1,31 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* cksum.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: jhalford +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2017/10/08 12:45:43 by jhalford #+# #+# */ +/* Updated: 2017/10/08 12:48:41 by jhalford ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "ping.h" + +unsigned short cksum(void *b, int len) +{ + unsigned short *buf; + unsigned int sum; + + buf = b; + sum = 0; + while (len > 1) + { + sum += *((unsigned short*)buf++); + len -= 2; + } + if (len == 1) + sum += *(unsigned char*)buf; + sum = (sum >> 16) + (sum & 0xFFFF); + return (~(sum + (sum >> 16))); +} diff --git a/ping/create_client.c b/ping/create_client.c new file mode 100644 index 00000000..ccc63429 --- /dev/null +++ b/ping/create_client.c @@ -0,0 +1,59 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* create_client.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: jhalford +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2017/10/07 17:59:28 by jhalford #+# #+# */ +/* Updated: 2017/10/08 13:33:51 by jhalford ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "ping.h" + +int create_client(char *addr, int port, char *protoname) +{ + int sock; + struct protoent *proto; + struct sockaddr_in sin; + + if (!(proto = getprotobyname(protoname))) + return (-1); + sock = socket(PF_INET, SOCK_STREAM, proto->p_proto); + sin.sin_family = AF_INET; + sin.sin_port = htons(port); + sin.sin_addr.s_addr = inet_addr(addr); + if (connect(sock, (const struct sockaddr *)&sin, sizeof(sin)) < 0) + return (-1); + return (sock); +} + +void listener(int domain, int sock, int proto, + void (*handler)(void *buf, int bytes, struct sockaddr *addr)) +{ + int sd; + struct sockaddr addr; + unsigned char buf[1024]; + int bytes; + socklen_t len; + + len = sizeof(addr); + sd = socket(domain, sock, proto); + if (sd < 0) + { + perror("listener socket"); + exit(0); + } + while (1) + { + bzero(buf, sizeof(buf)); + bytes = recvfrom(sd, buf, sizeof(buf), 0, + &addr, &len); + if (bytes > 0 && handler) + handler(buf, bytes, &addr); + else + perror("recvfrom"); + } + exit(0); +} diff --git a/ping/epoch.c b/ping/epoch.c new file mode 100644 index 00000000..42a7df27 --- /dev/null +++ b/ping/epoch.c @@ -0,0 +1,31 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* epoch.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: jhalford +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2017/10/07 17:58:42 by jhalford #+# #+# */ +/* Updated: 2017/10/08 13:15:50 by jhalford ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "ping.h" + +uint64_t epoch_micro(void) +{ + struct timeval tv; + + if (gettimeofday(&tv, NULL)) + return (0); + return (tv.tv_sec * 1000000 + tv.tv_usec); +} + +double time_milli(void) +{ + struct timeval tv; + + if (gettimeofday(&tv, NULL)) + return (0); + return ((double)(tv.tv_sec * 1000. + (double)tv.tv_usec / 1000.)); +} diff --git a/ping/srcs/ping.c b/ping/ping.c similarity index 98% rename from ping/srcs/ping.c rename to ping/ping.c index ab7527b1..504fc963 100644 --- a/ping/srcs/ping.c +++ b/ping/ping.c @@ -103,7 +103,7 @@ void ping(int signo) hdr->icmp_seq = ++g_ping.pkt_sent; msg = (double*)(pkt + sizeof(struct icmp)); epoch = time_milli(); - ft_memcpy(msg, (void*)&epoch, sizeof(double)); + memcpy(msg, (void*)&epoch, sizeof(double)); hdr->icmp_cksum = cksum(&pkt, sizeof(pkt)); sendto(g_ping.sock, &pkt, sizeof(pkt), 0, g_ping.sa->ai_addr, sizeof(struct sockaddr)); @@ -130,7 +130,7 @@ int main(int ac, char **av) { if (ac != 2) { - ft_usage("%s \n", av[0]); + dprintf(2, "%s \n", av[0]); exit(1); } resolve_host(av[1], &g_ping); diff --git a/ping/includes/ping.h b/ping/ping.h similarity index 79% rename from ping/includes/ping.h rename to ping/ping.h index 3835cf7e..2f9a039d 100644 --- a/ping/includes/ping.h +++ b/ping/ping.h @@ -13,18 +13,27 @@ #ifndef FT_PING_H # define FT_PING_H -# include "libft.h" +# include "rs.h" + +# include +# include +# include +# include + # include # include -# include # include # include # include +# include +# include # include # include # include # include +# define FT_PCT(a, t) (t ? 100 * (float)(t - a)/(float)t : 0) + typedef struct s_ping t_ping; struct s_ping @@ -47,4 +56,9 @@ struct s_ping extern t_ping g_ping; +unsigned short cksum(void *b, int len); +double time_milli(void); +void listener(int domain, int sock, int proto, + void (*handler)(void *buf, int bytes, struct sockaddr *addr)); + #endif diff --git a/ping/rs.c b/ping/rs.c new file mode 100644 index 00000000..9d4906ae --- /dev/null +++ b/ping/rs.c @@ -0,0 +1,61 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* rs.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: jhalford +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2017/10/07 17:57:54 by jhalford #+# #+# */ +/* Updated: 2017/10/07 18:19:47 by jhalford ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "rs.h" +#include + +double sqrt(double x); + +void rs_init(t_rs *rs) +{ + bzero(rs, sizeof(t_rs)); + rs->count = 0; + rs->min = DBL_MAX; + rs->max = -DBL_MAX; +} + +void rs_push(t_rs *rs, double n) +{ + double delta; + + rs->count++; + n < rs->min ? rs->min = n : (0); + n > rs->max ? rs->max = n : (0); + if (rs->count == 1) + { + rs->avg = n; + rs->m = 0; + } + else + { + delta = n - rs->avg; + rs->avg += delta / rs->count; + rs->m += delta * (n - rs->avg); + } +} + +void rs_final(t_rs *rs) +{ + if (rs->count == 0) + { + rs->min = 0; + rs->max = 0; + } + if (rs->count < 2) + { + rs->var = 0; + rs->stdev = 0; + return ; + } + rs->var = rs->m / (rs->count - 1); + rs->stdev = sqrt(rs->var); +} diff --git a/ping/rs.h b/ping/rs.h new file mode 100644 index 00000000..40bf6fc1 --- /dev/null +++ b/ping/rs.h @@ -0,0 +1,37 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* rs.h :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: jhalford +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2017/10/07 18:05:30 by jhalford #+# #+# */ +/* Updated: 2017/10/08 15:59:58 by jhalford ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#ifndef LIBFT_RS_H +# define LIBFT_RS_H + +# include +# include +# include +# include + +typedef struct s_rs t_rs; + +struct s_rs { + int count; + double min; + double max; + double avg; + double m; + double stdev; + double var; +}; + +void rs_init(t_rs *rs); +void rs_push(t_rs *rs, double n); +void rs_final(t_rs *rs); + +#endif From 9d11475d99925a1dd4093de26c5906aaa59a41fc Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Tue, 28 Nov 2017 15:47:10 +0000 Subject: [PATCH 13/13] added cliopts and -t option, ipv6 next --- ping/Makefile | 11 ++--- ping/cliopts.c | 132 +++++++++++++++++++++++++++++++++++++++++++++++++ ping/cliopts.h | 40 +++++++++++++++ ping/error.c | 68 +++++++++++++++++++++++++ ping/error.h | 64 ++++++++++++++++++++++++ ping/ping.c | 42 ++++++++++++++-- ping/ping.h | 16 +++--- ping/rs.h | 5 +- 8 files changed, 357 insertions(+), 21 deletions(-) create mode 100644 ping/cliopts.c create mode 100644 ping/cliopts.h create mode 100644 ping/error.c create mode 100644 ping/error.h diff --git a/ping/Makefile b/ping/Makefile index 11b6c1c0..e6031de4 100644 --- a/ping/Makefile +++ b/ping/Makefile @@ -17,7 +17,7 @@ NAME = ft_ping CC = gcc RM = rm -rf 2>&- W_FLAGS = -Wall -Wextra -Werror -D_FLAGS = +D_FLAGS = -D _GNU_SOURCE FLAGS = $(W_FLAGS) $(D_FLAGS) LEN_NAME = `printf "%s" $(NAME) |wc -c` @@ -30,9 +30,11 @@ OBJ_DIR = objs/ SRC_BASE = \ ping.c\ create_client.c\ -epoch.c\ cksum.c\ rs.c\ +epoch.c\ +cliopts.c\ +error.c\ SRCS = $(addprefix $(SRC_DIR), $(SRC_BASE)) OBJS = $(addprefix $(OBJ_DIR), $(SRC_BASE:.c=.o)) @@ -43,10 +45,7 @@ all : @make -j $(NAME) $(NAME): $(OBJ_DIR) $(OBJS) $(CLIENT_OBJ) - $(CC) $(OBJS) -o $@ \ - -I $(INC_DIR) \ - $(CLIENT_OBJ) $(FLAGS) \ - -lm + $(CC) $(OBJS) -o $@ -I $(INC_DIR) $(CLIENT_OBJ) $(FLAGS) -lm # sudo setcap cap_net_raw+ep $@ 2>&- $(OBJ_DIR) : diff --git a/ping/cliopts.c b/ping/cliopts.c new file mode 100644 index 00000000..5a7bd001 --- /dev/null +++ b/ping/cliopts.c @@ -0,0 +1,132 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* cliopts_get.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: jhalford +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2017/03/14 20:04:04 by jhalford #+# #+# */ +/* Updated: 2017/04/02 20:45:11 by jhalford ### ########.fr */ +/* */ +/* ************************************************************************** */ + +/* +** void *data must be a structure starting with `int flag` +** to do polymorphism with t_data_template ! +*/ + +#include "cliopts.h" + +t_cliopts *cliopts_getmap_long(t_cliopts opt_map[], char *arg) +{ + int i; + + i = -1; + while (opt_map[++i].c) + if (!strcmp(opt_map[i].str, arg)) + return (&opt_map[i]); + return (NULL); +} + +t_cliopts *cliopts_getmap_short(t_cliopts opt_map[], char arg) +{ + int i; + + i = -1; + while (opt_map[++i].c) + if (opt_map[i].c == arg) + return (&opt_map[i]); + return (NULL); +} + +static char *check_required(char ***av, char *arg) +{ + char *ret; + + if (!av || !*av) + return (NULL); + if (!arg || !*arg || !*(arg + 1)) + return (*++(*av)); + ret = arg + 1; + return (ret); +} + +static int cliopts_parse_short( + char ***av, t_cliopts opt_map[], void *data) +{ + t_cliopts *map; + char *arg; + int i; + char *tmp; + + arg = **av + 1; + i = -1; + while (arg[++i] && !(tmp = NULL)) + { + if (!(map = cliopts_getmap_short(opt_map, arg[i]))) + return (ERR_SET(E_CO_INV, arg[i])); + ((t_data_template*)data)->flag |= map->flag_on; + ((t_data_template*)data)->flag &= ~map->flag_off; + if (map->get) + { + if (map->arg_required && !(tmp = check_required(av, arg + i))) + return (ERR_SET(E_CO_MISS, *arg)); + tmp = tmp ? tmp : **av; + if ((map->get)(tmp, data)) + return (ERR_SET(E_CO_MISS, *arg)); + if (map->arg_required) + break ; + } + } + return (++(*av) ? 0 : 0); +} + +static int cliopts_parse_long( + char ***av, t_cliopts opt_map[], void *data) +{ + t_cliopts *map; + char *arg; + char *tmp; + + arg = **av + 2; + tmp = NULL; + if (!(map = cliopts_getmap_long(opt_map, arg))) + return (ERR_SET(E_CO_INVL, arg)); + ((t_data_template*)data)->flag |= map->flag_on; + ((t_data_template*)data)->flag &= ~map->flag_off; + if (map->get) + { + if (map->arg_required && !(tmp = check_required(av, NULL))) + return (ERR_SET(E_CO_MISS, *arg)); + if ((map->get)(tmp, data)) + return (ERR_SET(E_CO_MISSL, arg)); + } + ++(*av); + return (0); +} + +int cliopts_get(char **av, t_cliopts opt_map[], void *data) +{ + if (!av) + return (1); + av++; + while (av && *av) + { + if (strcmp(*av, "-") == 0 || (strcmp(*av, "--") == 0 && av++)) + break ; + else if ((*av)[0] == '-' && (*av)[1] == '-') + { + if (cliopts_parse_long(&av, opt_map, data)) + return (1); + } + else if ((*av)[0] == '-') + { + if (cliopts_parse_short(&av, opt_map, data)) + return (1); + } + else + break ; + } + ((t_data_template*)data)->av_data = av; + return (0); +} diff --git a/ping/cliopts.h b/ping/cliopts.h new file mode 100644 index 00000000..cb12f929 --- /dev/null +++ b/ping/cliopts.h @@ -0,0 +1,40 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* cliopts.h :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: jhalford +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2017/03/14 20:22:56 by jhalford #+# #+# */ +/* Updated: 2017/10/07 18:04:53 by jhalford ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#pragma once + +# include "error.h" +# include + +typedef struct s_cliopts t_cliopts; +typedef struct s_data_template t_data_template; +typedef long long t_flag; + +struct s_cliopts +{ + char c; + char *str; + t_flag flag_on; + t_flag flag_off; + int (*get)(); // (char *arg, void *data) + int arg_required:1; +}; + +struct s_data_template +{ + t_flag flag; + char **av_data; +}; + +int cliopts_get(char **av, t_cliopts opt_map[], void *data); +t_cliopts *cliopts_getmap_long(t_cliopts opt_map[], char *arg); +t_cliopts *cliopts_getmap_short(t_cliopts opt_map[], char arg); diff --git a/ping/error.c b/ping/error.c new file mode 100644 index 00000000..cbc459dc --- /dev/null +++ b/ping/error.c @@ -0,0 +1,68 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* error.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: jhalford +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2017/03/14 16:47:00 by jhalford #+# #+# */ +/* Updated: 2017/03/25 01:53:25 by jhalford ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "error.h" + +char g_error_msglist[E_MAX][ERRMSG_MAX_SIZE] = +{ + "unknown error 0", + "invalid option -%c", + "invalid option --%s", + "option '%c' awaits argument(s): please don't combine", + "option '%c': missing argument", + "option '%s': missing argument", + "%s: no such file or directory", + "%s: Is a directory", + "%s: Permission denied", +}; + +int g_errnum = 0; +char *g_errmsg = NULL; +char **g_argv; + +int error_set(int n, ...) +{ + va_list ap; + + g_errnum = n; + va_start(ap, n); + if (g_errmsg) + { + free(g_errmsg); + g_errmsg = NULL; + } + vasprintf(&g_errmsg, g_error_msglist[n], ap); + return (g_errnum); +} + +int ft_perror(char *utility) +{ + utility = utility ? utility : g_argv[0]; + ERR_MSG(utility, g_errmsg); + return (g_errnum); +} + +void ft_usage(char *format, ...) +{ + va_list ap; + char *usage; + + va_start(ap, format); + usage = NULL; + vasprintf(&usage, format, ap); + dprintf(2, "usage: %s\n", usage); + if (usage) + { + free(usage); + usage = NULL; + } +} diff --git a/ping/error.h b/ping/error.h new file mode 100644 index 00000000..4ff21d9c --- /dev/null +++ b/ping/error.h @@ -0,0 +1,64 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* error.h :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: jhalford +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2017/03/14 15:34:21 by jhalford #+# #+# */ +/* Updated: 2017/05/15 17:37:29 by ariard ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#ifndef ERROR_H +# define ERROR_H + +# include +# include +# include + +/* +** DEBUG with malloc +*/ +# define DG_MSG "{inv}{ran}%5i{yel}%21s {bol}{blu}%-3d{eoc}" +# define DG_ARGS getpid(), getpid(), ft_path_notdir(__FILE__), __LINE__ +# define DG(s, ...) dprintf(STDBUG,DG_MSG s "{eoc}\n",DG_ARGS,##__VA_ARGS__) + +/* +** DEBUG with no malloc +*/ +# define DG2 ft_putstr(__FILE__"\t");ft_putnbr(__LINE__) +# define DGW(d) DG2;d;ft_putchar('\n') +# define DGS(s) DGW(ft_putstr(": "s"=")) +# define DGSN(s, n) DGW(ft_putstr(": "s"=");ft_putnbr(n)) +# define DGSH(s, n) DGW(ft_putstr(": "s"=");ft_putnbr_hex(n)) + +# define ERR_PROTO(u, m) "%s: %s\n", u, m +# define ERR_MSG(u, m) dprintf(2, ERR_PROTO(u, m)) +# define ERR_SET(n, ...) error_set(n, ##__VA_ARGS__) +# define ERRMSG_MAX_SIZE 150 + +enum e_errors +{ + E_NOERR, + E_CO_INV, + E_CO_INVL, + E_CO_MULT, + E_CO_MISS, + E_CO_MISSL, + E_SYS_NOFILE, + E_SYS_ISDIR, + E_SYS_NOPERM, + E_MAX, +}; + +extern char g_error_msg[E_MAX][ERRMSG_MAX_SIZE]; +extern char *g_errmsg; +extern int g_errnum; +extern char **g_argv; + +int error_set(int n, ...); +int ft_perror(char *utility); +void ft_usage(char *format, ...); + +#endif diff --git a/ping/ping.c b/ping/ping.c index 504fc963..0ec0e764 100644 --- a/ping/ping.c +++ b/ping/ping.c @@ -12,12 +12,27 @@ #include "ping.h" +#define PING_USAGE "%s [-hv] [-t ttl] destination" + t_ping g_ping = { .pid = -1, .pkt_size = 56, .pkt_sent = -1, .pkt_recv = 0, + .ttl = 255, +}; + +int get_ttl(char *arg, t_ping *data); + +t_cliopts opts[] = +{ +#define FLAG_HELP (1 << 0) +#define FLAG_VERBOSE (1 << 1) +#define FLAG_TTL (1 << 2) + {'h', NULL, FLAG_HELP, 0, NULL, 0}, + {'v', NULL, FLAG_VERBOSE, 0, NULL, 0}, + {'t', NULL, FLAG_TTL, 0, get_ttl, 1}, }; int resolve_host(char *node, t_ping *ping) @@ -126,14 +141,33 @@ void stats_recap(int signo) exit(0); } +int get_interval(char *arg, t_ping *data) +{ + data->interval = atof(arg); + return (0); +} + +int get_ttl(char *arg, t_ping *data) +{ + data->ttl = atoi(arg); + return (0); +} + int main(int ac, char **av) { - if (ac != 2) + (void)ac; + if (cliopts_get(av, opts, &g_ping)) { - dprintf(2, "%s \n", av[0]); + ft_perror(av[0]); + ft_usage(PING_USAGE, av[0]); exit(1); } - resolve_host(av[1], &g_ping); + if (g_ping.flag & FLAG_HELP || !g_ping.av_data[0]) + { + ft_usage(PING_USAGE, av[0]); + exit(!(g_ping.flag & FLAG_HELP)); + } + resolve_host(g_ping.av_data[0], &g_ping); if (g_ping.sa->ai_canonname) printf("PING %s (%s): %zu(%zu) data bytes\n", g_ping.sa->ai_canonname, g_ping.ip4, @@ -146,7 +180,7 @@ int main(int ac, char **av) perror("socket"); exit(1); } - if (setsockopt(g_ping.sock, 0, IP_TTL, (int[]){255}, sizeof(int)) != 0) + if (setsockopt(g_ping.sock, 0, IP_TTL, &g_ping.ttl, sizeof(g_ping.ttl)) != 0) { perror("setsockopt"); exit(1); diff --git a/ping/ping.h b/ping/ping.h index 2f9a039d..26773ba8 100644 --- a/ping/ping.h +++ b/ping/ping.h @@ -10,27 +10,27 @@ /* */ /* ************************************************************************** */ -#ifndef FT_PING_H -# define FT_PING_H +#pragma once # include "rs.h" +# include "cliopts.h" # include # include # include # include +# include +# include +# include # include # include -# include # include # include -# include # include # include # include # include -# include # define FT_PCT(a, t) (t ? 100 * (float)(t - a)/(float)t : 0) @@ -38,11 +38,15 @@ typedef struct s_ping t_ping; struct s_ping { + t_flag flag; + char **av_data; size_t pkt_size; pid_t pid; t_rs rs; int pkt_sent; int pkt_recv; + int ttl; + float interval; int sock; struct addrinfo *sa; union @@ -60,5 +64,3 @@ unsigned short cksum(void *b, int len); double time_milli(void); void listener(int domain, int sock, int proto, void (*handler)(void *buf, int bytes, struct sockaddr *addr)); - -#endif diff --git a/ping/rs.h b/ping/rs.h index 40bf6fc1..3aa6bd6b 100644 --- a/ping/rs.h +++ b/ping/rs.h @@ -10,8 +10,7 @@ /* */ /* ************************************************************************** */ -#ifndef LIBFT_RS_H -# define LIBFT_RS_H +#pragma once # include # include @@ -33,5 +32,3 @@ struct s_rs { void rs_init(t_rs *rs); void rs_push(t_rs *rs, double n); void rs_final(t_rs *rs); - -#endif