I'm trying to write a very simple version of the traceroute program using raw sockets and ICMP. But when I run it i just always get an endless loop of echo requests by myself back.
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <errno.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <ifaddrs.h>
int mysock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
int ttl = 0;
char buffr[4069] = { 0 };
struct ip *myIpHeader = (struct ip*)buffr;
struct ifaddrs *ifa;
getifaddrs(&ifa);
then i just do some input checks and set setsocketopt to HDRINCL
struct sockaddr_in cliAddr;
cliAddr.sin_port = htons(7);
cliAddr.sin_family = AF_INET;
inet_pton(AF_INET, argv[1], &(cliAddr.sin_addr));
then the endless while loop where i set up the ip and icmp header like this
myIpHeader->ip_v = 4;
myIpHeader->ip_hl = 5;
myIpHeader->ip_tos = 0;
myIpHeader->ip_len = 20+8;
myIpHeader->ip_off = 0;
myIpHeader->ip_p = IPPROTO_ICMP;
inet_pton(AF_INET, argv[1], &(myIpHeader->ip_dst));
inet_pton(AF_INET, ifa->ifa_name, &(myIpHeader->ip_src));
myIpHeader->ip_sum = 0;
myIpHeader->ip_id = htonl(12345);
myIpHeader->ip_ttl = ttl;
struct icmphdr *myicmphead = (struct icmphdr *) (buffr + 20);
myicmphead->type = 8;
myicmphead->code = 0;
myicmphead->checksum = 0;
then follows send and recv
sendto(mysock, buffr , sizeof (struct ip) + sizeof (struct icmphdr), 0, (struct sockaddr*)&cliAddr, sizeof cliAddr);
char buff[4096] = { 0 };
struct sockaddr_in serverAddr;
socklen_t inlen = sizeof(struct sockaddr_in);
recvfrom(mysock, buff, sizeof(buff), 0, (struct sockaddr*) & serverAddr, &inlen);
struct icmphdr *icmphd2 = (struct icmphdr *) (buff + 20);
and then i just check if the type i receive equals 0 if so the destination is reached and i exit if not im gonna print the ttl and address and increase the ttl
printf("ttl: %d Address:%s\n", ttl, inet_ntoa(serverAddr.sin_addr));
But like i said i just print out the source address i put in the ip head in an endless loop. Basically looking like that:(I just put placeholders for ip addresses and so on)
trace route to '...' (IP: 160.....)
ICMP msgtype=8, code=0
ttl limit: 0 Address 127.0.0.1
ICMP msgtype=8, code=0
ttl limit: 1 Address 127.0.0.1
ICMP msgtype=8, code=0
ttl limit: 2 Address 127.0.0.1
ICMP msgtype=8, code=0
ttl limit: 3 Address 127.0.0.1
ICMP msgtype=8, code=0
ttl limit: 4 Address 127.0.0.1
and so on as example what i get
I would really appreciate any tips how i could solve this.
What I have tried:
Thanks to Jochen Arndt, I could solve this problem and now put the right addresses. But now I got a new problem. The program somehow just gets the first rcv, so I guess I forgot to do something before I receive again because it says the resource is temporarily unavailable as error for receive(when I put it to not wait for an reply). Any idea what I forgot?