From 5a0a708e904b0f0be8c60780e0afe35722f0a852 Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Tue, 28 Nov 2017 16:25:31 +0000 Subject: [PATCH] refactor like ping, easy to hand in --- traceroute/Makefile | 73 +++++++--------------- traceroute/cksum.c | 29 +++++++++ traceroute/cliopts.c | 132 ++++++++++++++++++++++++++++++++++++++++ traceroute/cliopts.h | 40 ++++++++++++ traceroute/epoch.c | 31 ++++++++++ traceroute/error.c | 68 +++++++++++++++++++++ traceroute/error.h | 64 +++++++++++++++++++ traceroute/main.c | 2 +- traceroute/net.c | 29 +++++++++ traceroute/rs.c | 61 +++++++++++++++++++ traceroute/rs.h | 34 +++++++++++ traceroute/traceroute.c | 10 +-- traceroute/traceroute.h | 23 ++++--- 13 files changed, 533 insertions(+), 63 deletions(-) create mode 100644 traceroute/cksum.c create mode 100644 traceroute/cliopts.c create mode 100644 traceroute/cliopts.h create mode 100644 traceroute/epoch.c create mode 100644 traceroute/error.c create mode 100644 traceroute/error.h create mode 100644 traceroute/net.c create mode 100644 traceroute/rs.c create mode 100644 traceroute/rs.h diff --git a/traceroute/Makefile b/traceroute/Makefile index fb4b340a..c1b7779a 100644 --- a/traceroute/Makefile +++ b/traceroute/Makefile @@ -6,32 +6,36 @@ # By: wescande +#+ +:+ +#+ # # +#+#+#+#+#+ +#+ # # Created: 2016/08/29 21:32:58 by wescande #+# #+# # -# Updated: 2017/10/08 17:53:44 by jhalford ### ########.fr # +# Updated: 2017/10/08 14:36:33 by jhalford ### ########.fr # # # # **************************************************************************** # +SHELL := bash + NAME = ft_traceroute -SHELL := /bin/bash 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` 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 = \ main.c\ -traceroute.c +traceroute.c\ +cksum.c\ +rs.c\ +epoch.c\ +net.c\ +cliopts.c\ +error.c\ SRCS = $(addprefix $(SRC_DIR), $(SRC_BASE)) OBJS = $(addprefix $(OBJ_DIR), $(SRC_BASE:.c=.o)) @@ -39,57 +43,26 @@ 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) +$(NAME): $(OBJ_DIR) $(OBJS) $(CLIENT_OBJ) + $(CC) $(OBJS) -o $@ -I $(INC_DIR) $(CLIENT_OBJ) $(FLAGS) -lm + # 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/traceroute/cksum.c b/traceroute/cksum.c new file mode 100644 index 00000000..62c94bdf --- /dev/null +++ b/traceroute/cksum.c @@ -0,0 +1,29 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* cksum.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: jhalford +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2017/10/08 12:45:43 by jhalford #+# #+# */ +/* Updated: 2017/10/08 12:48:41 by jhalford ### ########.fr */ +/* */ +/* ************************************************************************** */ + +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/traceroute/cliopts.c b/traceroute/cliopts.c new file mode 100644 index 00000000..5a7bd001 --- /dev/null +++ b/traceroute/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/traceroute/cliopts.h b/traceroute/cliopts.h new file mode 100644 index 00000000..cb12f929 --- /dev/null +++ b/traceroute/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/traceroute/epoch.c b/traceroute/epoch.c new file mode 100644 index 00000000..e567150d --- /dev/null +++ b/traceroute/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 "traceroute.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/traceroute/error.c b/traceroute/error.c new file mode 100644 index 00000000..cbc459dc --- /dev/null +++ b/traceroute/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/traceroute/error.h b/traceroute/error.h new file mode 100644 index 00000000..4ff21d9c --- /dev/null +++ b/traceroute/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/traceroute/main.c b/traceroute/main.c index 2781263e..63f55964 100644 --- a/traceroute/main.c +++ b/traceroute/main.c @@ -49,7 +49,7 @@ int main(int ac, char **av) printf("traceroute: Warning: %s has multiple addresses; using %s\n", result->ai_canonname, ip); printf("traceroute to %s (%s), %i hops max %i byte packets\n", - FT_TRY(result->ai_canonname, ip), ip, 64, PACKETSIZE); + result->ai_canonname, ip, 64, PACKETSIZE); traceroute(result->ai_addr); return (0); } diff --git a/traceroute/net.c b/traceroute/net.c new file mode 100644 index 00000000..475df20f --- /dev/null +++ b/traceroute/net.c @@ -0,0 +1,29 @@ +#include "traceroute.h" + +int host_format(struct sockaddr *addr) +{ + char dn[1024]; + char sv[20]; + char ip[INET_ADDRSTRLEN]; + + if (getnameinfo(addr, sizeof(*addr), dn, sizeof(dn), + sv, sizeof(sv), 0)) + { + perror("getnameinfo"); + return (1); + } + printf(" %s (%s)", dn, + inet_ntop(AF_INET, &(((struct sockaddr_in*)addr)->sin_addr), + ip, INET_ADDRSTRLEN)); + return (0); +} + +void ip_load_icmp(struct icmp *icmp, void *buf) +{ + struct ip *ip; + int hlen; + + ip = buf; + hlen = ip->ip_hl << 2; + memcpy(icmp, buf + hlen, sizeof(struct icmp)); +} diff --git a/traceroute/rs.c b/traceroute/rs.c new file mode 100644 index 00000000..9d4906ae --- /dev/null +++ b/traceroute/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/traceroute/rs.h b/traceroute/rs.h new file mode 100644 index 00000000..3aa6bd6b --- /dev/null +++ b/traceroute/rs.h @@ -0,0 +1,34 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* rs.h :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: jhalford +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2017/10/07 18:05:30 by jhalford #+# #+# */ +/* Updated: 2017/10/08 15:59:58 by jhalford ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#pragma once + +# 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); diff --git a/traceroute/traceroute.c b/traceroute/traceroute.c index 940e1400..643dcb78 100644 --- a/traceroute/traceroute.c +++ b/traceroute/traceroute.c @@ -16,7 +16,7 @@ int g_pid; static int wait_for_reply(struct sockaddr *addr, unsigned char buf[1024]) { - static int sd; + static int sd;; sd = 0; if (sd == 0) @@ -53,11 +53,11 @@ static int probe_once(int sd, struct sockaddr *addr, bytes = wait_for_reply(addr, buf); time = time_milli() - time; if (bytes < 0) - ft_printf(" *"); + printf(" *"); else { ip_load_icmp(icmp, buf); - ft_printf(" %.3f ms", time); + printf(" %.3f ms", time); } return (0); } @@ -76,7 +76,7 @@ static int probe_depth(int sd, struct sockaddr *addr, pkt.hdr.icmp_cksum = cksum(&pkt, sizeof(pkt)); probe_once(sd, addr, &pkt, &icmp); } - ft_putchar('\n'); + printf("\n"); return (icmp.icmp_type == ICMP_ECHOREPLY); } @@ -98,7 +98,7 @@ void traceroute(struct sockaddr *addr) ttl = 0; while (++ttl < 255) { - ft_printf("%2d ", ttl); + printf("%2d ", ttl); if (setsockopt(sd, 0, IP_TTL, &ttl, sizeof(ttl)) != 0) { perror("set TTL option"); diff --git a/traceroute/traceroute.h b/traceroute/traceroute.h index b5538052..aac77a69 100644 --- a/traceroute/traceroute.h +++ b/traceroute/traceroute.h @@ -10,16 +10,23 @@ /* */ /* ************************************************************************** */ -#ifndef FT_PING_H -# define FT_PING_H +#pragma once + +# include "error.h" +# include "cliopts.h" + +# include +# include -# include "libft.h" -# include -# include # include # include +# include + +# include +# include # include # include +# include # include # include # include @@ -33,5 +40,7 @@ struct s_packet }; void traceroute(struct sockaddr *addr); - -#endif +unsigned short cksum(void *b, int len); +int host_format(struct sockaddr *addr); +void ip_load_icmp(struct icmp *icmp, void *buf); +double time_milli(void);