42-archive/traceroute/srcs/traceroute.c
2017-10-08 17:55:38 +02:00

111 lines
2.7 KiB
C

/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* 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)
ft_printf(" *");
else
{
ip_load_icmp(icmp, buf);
ft_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);
}
ft_putchar('\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)
{
ft_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 ;
}
}