commit adc4965e383cf076b8091f03c2858155575b2ab1 Author: Jack Halford Date: Sun May 14 22:26:43 2017 +0200 first commit, seems almost finished. gotta see bonus option and linux compatibility issues diff --git a/traceroute/.gitmodules b/traceroute/.gitmodules new file mode 100644 index 00000000..c82793fb --- /dev/null +++ b/traceroute/.gitmodules @@ -0,0 +1,3 @@ +[submodule "libft"] + path = libft + url = https://github.com/jzck/libft diff --git a/traceroute/Makefile b/traceroute/Makefile new file mode 100644 index 00000000..0ce6ee61 --- /dev/null +++ b/traceroute/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_traceroute + +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 = \ +traceroute.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/traceroute/ft_traceroute b/traceroute/ft_traceroute new file mode 100755 index 00000000..560582df Binary files /dev/null and b/traceroute/ft_traceroute differ diff --git a/traceroute/includes/traceroute.h b/traceroute/includes/traceroute.h new file mode 100644 index 00000000..ba996d9a --- /dev/null +++ b/traceroute/includes/traceroute.h @@ -0,0 +1,35 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* 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 +# include + +#define PACKETSIZE 56 + +struct s_packet +{ + struct icmp hdr; + char msg[PACKETSIZE - sizeof(struct icmp)]; +}; + +#endif diff --git a/traceroute/libft b/traceroute/libft new file mode 160000 index 00000000..23c69f13 --- /dev/null +++ b/traceroute/libft @@ -0,0 +1 @@ +Subproject commit 23c69f13242ecbff493356c57cb1384eb1dd45f5 diff --git a/traceroute/srcs/traceroute.c b/traceroute/srcs/traceroute.c new file mode 100644 index 00000000..02b37fd6 --- /dev/null +++ b/traceroute/srcs/traceroute.c @@ -0,0 +1,168 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* main.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: jhalford +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2017/04/22 14:10:24 by jhalford #+# #+# */ +/* Updated: 2017/04/23 18:18:41 by jhalford ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "traceroute.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); +} + +int wait_for_reply(struct sockaddr_in *addr, unsigned char buf[1024]) +{ + static int sd = 0; + + if (sd == 0) + { + if ((sd = socket(PF_INET, SOCK_DGRAM, IPPROTO_ICMP)) < 0) + { + perror("socket"); + exit(0); + } + struct timeval tv; + tv.tv_sec = 5; + tv.tv_usec = 0; + setsockopt(sd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv, sizeof(struct timeval)); + } + bzero(buf, 1024); + + socklen_t len = sizeof(*addr); + return (recvfrom(sd, buf, 1024, 0, (struct sockaddr*)addr, &len)); +} + +struct icmp *get_icmp(void *buf) +{ + struct ip *ip = buf; + struct icmp *icmp; + struct s_packet *pkt; + + int hlen = ip->ip_hl << 2; + pkt = (struct s_packet*)(buf + hlen); + icmp = &pkt->hdr; + return (icmp); +} + +int traceroute(struct sockaddr_in *dest) +{ + int ttl; + int sd; + char addrstr[INET_ADDRSTRLEN]; + unsigned char buf[1024]; + struct s_packet pkt; + struct sockaddr_in addr; + struct timeval t1, t2, trip; + double diff; + + if ((sd = socket(PF_INET, SOCK_DGRAM, IPPROTO_ICMP)) < 0) + { + perror("socket"); + return (1); + } + if (fcntl(sd, F_SETFL, O_NONBLOCK) != 0) + perror("Request non blocking IO"); + for (ttl = 1; ttl < 255; ttl++) + { + if (setsockopt(sd, 0, IP_TTL, &ttl, sizeof(ttl)) != 0) + perror("set TTL option"); + printf("%2d ", ttl); + fflush(stdout); + int addrshow = 0; + for (int probe = 0; probe < 3; probe++) + { + bzero(&pkt, sizeof(pkt)); + pkt.hdr.icmp_type = ICMP_ECHO; + pkt.hdr.icmp_id = g_pid; + pkt.hdr.icmp_seq = (ttl - 1) * 3 + probe; + pkt.hdr.icmp_cksum = checksum(&pkt, sizeof(pkt)); + if (sendto(sd, &pkt, sizeof(pkt), 0, (struct sockaddr*)dest, sizeof(*dest)) <= 0) + perror("sendto"); + + if (gettimeofday(&t1, NULL) != 0) + return (1); + + int bytes = wait_for_reply(&addr, buf); + + if (gettimeofday(&t2, NULL) != 0) + return (1); + + if (bytes < 0) + { + printf(" *"); + fflush(stdout); + continue ; + } + timersub(&t2, &t1, &trip); + diff = (trip.tv_sec + trip.tv_usec / 1000000.0) * 1000.0; + if (!addrshow) + { + char hostname[1024]; + char servname[20]; + + if (getnameinfo((struct sockaddr*)&addr, sizeof(addr), hostname, sizeof(hostname), servname, sizeof(servname), 0)) + { + perror("getnameinfo"); + exit(1); + } + printf(" %s (%s)", hostname, inet_ntop(AF_INET, &(addr.sin_addr), addrstr, INET_ADDRSTRLEN)); addrshow = 1; + } + printf(" %.3f ms", diff); + } + printf("\n"); + struct icmp *icmp = get_icmp(buf); + if (icmp->icmp_type == ICMP_ECHOREPLY) + break ; + } + exit(0); +} + +int main(int ac, char **av) +{ + 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)); + 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(); + if (result->ai_next) + printf("traceroute: Warning: %s has multiple addresses; using %s\n", result->ai_canonname, addrstr); + printf("traceroute to %s (%s), %i hops max %i byte packets\n", + FT_TRY(result->ai_canonname, addrstr), addrstr, 64, PACKETSIZE); + exit(traceroute(addr)); +}