Merge traceroute with full history

This commit is contained in:
Jack 2026-01-29 18:05:27 -03:00
commit af4f50ad40
No known key found for this signature in database
14 changed files with 771 additions and 0 deletions

2
traceroute/.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
traceroute
ft_traceroute

68
traceroute/Makefile Normal file
View file

@ -0,0 +1,68 @@
# **************************************************************************** #
# #
# ::: :::::::: #
# Makefile :+: :+: :+: #
# +:+ +:+ +:+ #
# By: wescande <wescande@student.42.fr> +#+ +:+ +#+ #
# +#+#+#+#+#+ +#+ #
# Created: 2016/08/29 21:32:58 by wescande #+# #+# #
# Updated: 2017/10/08 14:36:33 by jhalford ### ########.fr #
# #
# **************************************************************************** #
SHELL := bash
NAME = ft_traceroute
CC = gcc
RM = rm -rf 2>&-
W_FLAGS = -Wall -Wextra -Werror
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)
SRC_DIR = ./
INC_DIR = ./
OBJ_DIR = objs/
SRC_BASE = \
main.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))
NB = $(words $(SRC_BASE))
INDEX = 0
all :
@make -j $(NAME)
$(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)
$(CC) $(FLAGS) $(OBJ_FLAG) -MMD -c $< -o $@ -I $(INC_DIR)
clean:
$(RM) $(OBJ_DIR)
re: fclean all
fclean: clean
$(RM) $(NAME)
.PHONY : fclean clean re
-include $(OBJS:.o=.d)

29
traceroute/cksum.c Normal file
View file

@ -0,0 +1,29 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* cksum.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: jhalford <jack@crans.org> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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)));
}

132
traceroute/cliopts.c Normal file
View file

@ -0,0 +1,132 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* cliopts_get.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: jhalford <jack@crans.org> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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);
}

40
traceroute/cliopts.h Normal file
View file

@ -0,0 +1,40 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* cliopts.h :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: jhalford <jack@crans.org> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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 <string.h>
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);

31
traceroute/epoch.c Normal file
View file

@ -0,0 +1,31 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* epoch.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: jhalford <jack@crans.org> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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.));
}

68
traceroute/error.c Normal file
View file

@ -0,0 +1,68 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* error.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: jhalford <jhalford@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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;
}
}

64
traceroute/error.h Normal file
View file

@ -0,0 +1,64 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* error.h :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: jhalford <jack@crans.org> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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 <stdarg.h>
# include <stdlib.h>
# include <stdio.h>
/*
** 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

56
traceroute/main.c Normal file
View file

@ -0,0 +1,56 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* main.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: jhalford <jack@crans.org> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2017/10/08 17:18:05 by jhalford #+# #+# */
/* Updated: 2017/10/08 17:55:15 by jhalford ### ########.fr */
/* */
/* ************************************************************************** */
#include "traceroute.h"
int g_pid = -1;
struct addrinfo *resolve_host(char *hostname, char ip[])
{
struct addrinfo *result;
struct addrinfo hints;
struct sockaddr_in *addr;
memset(&hints, 0, sizeof(hints));
hints.ai_family = PF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags |= AI_CANONNAME;
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), ip, INET_ADDRSTRLEN);
return (result);
}
int main(int ac, char **av)
{
struct addrinfo *result;
char ip[INET_ADDRSTRLEN];
if (ac != 2)
{
ft_usage("%s <addr>\n", av[0]);
return (1);
}
result = resolve_host(av[1], ip);
if (result->ai_next)
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",
result->ai_canonname, ip, 64, PACKETSIZE);
traceroute(result->ai_addr);
return (0);
}

29
traceroute/net.c Normal file
View file

@ -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));
}

61
traceroute/rs.c Normal file
View file

@ -0,0 +1,61 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* rs.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: jhalford <jack@crans.org> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2017/10/07 17:57:54 by jhalford #+# #+# */
/* Updated: 2017/10/07 18:19:47 by jhalford ### ########.fr */
/* */
/* ************************************************************************** */
#include "rs.h"
#include <math.h>
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);
}

34
traceroute/rs.h Normal file
View file

@ -0,0 +1,34 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* rs.h :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: jhalford <jack@crans.org> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2017/10/07 18:05:30 by jhalford #+# #+# */
/* Updated: 2017/10/08 15:59:58 by jhalford ### ########.fr */
/* */
/* ************************************************************************** */
#pragma once
# include <strings.h>
# include <float.h>
# include <dlfcn.h>
# include <math.h>
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);

111
traceroute/traceroute.c Normal file
View file

@ -0,0 +1,111 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* main.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: jhalford <jack@crans.org> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2017/04/22 14:10:24 by jhalford #+# #+# */
/* Updated: 2017/10/08 17:55:05 by jhalford ### ########.fr */
/* */
/* ************************************************************************** */
#include "traceroute.h"
int g_pid;
static int wait_for_reply(struct sockaddr *addr, unsigned char buf[1024])
{
static int sd;;
sd = 0;
if (sd == 0)
{
if ((sd = socket(PF_INET, SOCK_RAW, IPPROTO_ICMP)) < 0)
{
perror("socket");
exit(1);
}
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);
return (recvfrom(sd, buf, 1024, 0, addr, NULL));
}
static int probe_once(int sd, struct sockaddr *addr,
struct s_packet *pkt, struct icmp *icmp)
{
int bytes;
unsigned char buf[1024];
double time;
if (sendto(sd, &pkt, sizeof(pkt), 0,
addr, sizeof(*addr)) <= 0)
{
perror("sendto");
exit(1);
}
time = time_milli();
bytes = wait_for_reply(addr, buf);
time = time_milli() - time;
if (bytes < 0)
printf(" *");
else
{
ip_load_icmp(icmp, buf);
printf(" %.3f ms", time);
}
return (0);
}
static int probe_depth(int sd, struct sockaddr *addr,
struct s_packet pkt)
{
struct icmp icmp;
int probe;
probe = -1;
host_format(addr);
while (++probe < 3)
{
pkt.hdr.icmp_seq++;
pkt.hdr.icmp_cksum = cksum(&pkt, sizeof(pkt));
probe_once(sd, addr, &pkt, &icmp);
}
printf("\n");
return (icmp.icmp_type == ICMP_ECHOREPLY);
}
void traceroute(struct sockaddr *addr)
{
int sd;
int ttl;
struct s_packet pkt;
if ((sd = socket(PF_INET, SOCK_RAW, IPPROTO_ICMP)) < 0)
{
perror("socket");
exit(1);
}
g_pid = getpid();
bzero(&pkt, sizeof(pkt));
pkt.hdr.icmp_type = ICMP_ECHO;
pkt.hdr.icmp_id = g_pid;
ttl = 0;
while (++ttl < 255)
{
printf("%2d ", ttl);
if (setsockopt(sd, 0, IP_TTL, &ttl, sizeof(ttl)) != 0)
{
perror("set TTL option");
exit(1);
}
pkt.hdr.icmp_seq = (ttl - 1) * 3;
if (probe_depth(sd, addr, pkt))
break ;
}
}

46
traceroute/traceroute.h Normal file
View file

@ -0,0 +1,46 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* ft_ping.h :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: jhalford <jack@crans.org> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2017/04/22 14:10:24 by jhalford #+# #+# */
/* Updated: 2017/10/08 17:52:17 by jhalford ### ########.fr */
/* */
/* ************************************************************************** */
#pragma once
# include "error.h"
# include "cliopts.h"
# include <unistd.h>
# include <stdlib.h>
# include <sys/socket.h>
# include <sys/time.h>
# include <sys/types.h>
# include <fcntl.h>
# include <errno.h>
# include <resolv.h>
# include <netdb.h>
# include <arpa/inet.h>
# include <netinet/in.h>
# include <netinet/ip.h>
# include <netinet/ip_icmp.h>
#define PACKETSIZE 56
struct s_packet
{
struct icmp hdr;
char msg[PACKETSIZE - sizeof(struct icmp)];
};
void traceroute(struct sockaddr *addr);
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);