first commit, seems almost finished. gotta see bonus option and linux compatibility issues
This commit is contained in:
commit
adc4965e38
6 changed files with 300 additions and 0 deletions
3
traceroute/.gitmodules
vendored
Normal file
3
traceroute/.gitmodules
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
[submodule "libft"]
|
||||
path = libft
|
||||
url = https://github.com/jzck/libft
|
||||
93
traceroute/Makefile
Normal file
93
traceroute/Makefile
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
# **************************************************************************** #
|
||||
# #
|
||||
# ::: :::::::: #
|
||||
# Makefile :+: :+: :+: #
|
||||
# +:+ +:+ +:+ #
|
||||
# By: wescande <wescande@student.42.fr> +#+ +:+ +#+ #
|
||||
# +#+#+#+#+#+ +#+ #
|
||||
# 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)
|
||||
BIN
traceroute/ft_traceroute
Executable file
BIN
traceroute/ft_traceroute
Executable file
Binary file not shown.
35
traceroute/includes/traceroute.h
Normal file
35
traceroute/includes/traceroute.h
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* ft_ping.h :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: jhalford <jack@crans.org> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* 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 <fcntl.h>
|
||||
# include <errno.h>
|
||||
# include <sys/socket.h>
|
||||
# include <sys/time.h>
|
||||
# include <resolv.h>
|
||||
# include <netdb.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)];
|
||||
};
|
||||
|
||||
#endif
|
||||
1
traceroute/libft
Submodule
1
traceroute/libft
Submodule
|
|
@ -0,0 +1 @@
|
|||
Subproject commit 23c69f13242ecbff493356c57cb1384eb1dd45f5
|
||||
168
traceroute/srcs/traceroute.c
Normal file
168
traceroute/srcs/traceroute.c
Normal file
|
|
@ -0,0 +1,168 @@
|
|||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* main.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: jhalford <jack@crans.org> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* 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 <addr>\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));
|
||||
}
|
||||
Loading…
Reference in a new issue