Question

I am trying to implement traceroute using icmp raw sockets by constructing the appropriate ip header and icmp header.The port number i am using is 7 and i have calculated the checksums.The hop limit is incremented each time and a packet is sent till the reply message contains the echo reply of type 0.

#include "libsock"
#include<netinet/ip.h>
#include<netinet/ip_icmp.h>


unsigned short
csum (unsigned short *buf, int nwords)
{
  unsigned long sum;
  for (sum = 0; nwords > 0; nwords--)
    sum += *buf++;
  sum = (sum >> 16) + (sum & 0xffff);
  sum += (sum >> 16);
  return ~sum;
}

int
main (int argc, char *argv[])
{
  if (argc != 2)
    {
      printf ("need destination for tracert\n");
      exit (0);
    }
  int sfd = socket (AF_INET, SOCK_RAW, IPPROTO_ICMP);
  char buf[4096] = { 0 };
  struct ip *ip_hdr = (struct ip *) buf;
  int hop = 0;

  int one = 1;
  const int *val = &one;
  if (setsockopt (sfd, IPPROTO_IP, IP_HDRINCL, val, sizeof (one)) < 0)
    printf ("Cannot set HDRINCL!\n");

  struct sockaddr_in addr;
  addr.sin_port = htons (7);
  addr.sin_family = AF_INET;
  inet_pton (AF_INET, argv[1], &(addr.sin_addr));


  while (1)
    {
      ip_hdr->ip_hl = 5;
      ip_hdr->ip_v = 4;
      ip_hdr->ip_tos = 0;
      ip_hdr->ip_len = 20 + 8;
      ip_hdr->ip_id = 10000;
      ip_hdr->ip_off = 0;
      ip_hdr->ip_ttl = hop;
      ip_hdr->ip_p = IPPROTO_ICMP;
      inet_pton (AF_INET, "172.30.104.59", &(ip_hdr->ip_src));
      inet_pton (AF_INET, argv[1], &(ip_hdr->ip_dst));
      ip_hdr->ip_sum = csum ((unsigned short *) buf, 9);

      struct icmphdr *icmphd = (struct icmphdr *) (buf + 20);
      icmphd->type = ICMP_ECHO;
      icmphd->code = 0;
      icmphd->checksum = 0;
      icmphd->un.echo.id = 0;
      icmphd->un.echo.sequence = hop + 1;
      icmphd->checksum = csum ((unsigned short *) (buf + 20), 4);
      sendto (sfd, buf, 28, 0, SA & addr, sizeof addr);
      char buff[4096] = { 0 };
      struct sockaddr_in addr2;
      socklen_t len = sizeof (struct sockaddr_in);
      recvfrom (sfd, buff, 28, 0, SA & addr2, &len);
      struct icmphdr *icmphd2 = (struct icmphdr *) (buff + 20);
      if (icmphd2->type != 0)
    printf ("hop limit:%d Address:%s\n", hop, inet_ntoa (addr2.sin_addr));
      else
    {
      printf ("Reached destination:%s with hop limit:%d\n",
          inet_ntoa (addr2.sin_addr), hop);
      exit (0);
    }

      hop++;
    }

  return 0;
}

When the input ie argv[1] is "127.0.0.1" the o/p is

hop limit:0 Address:127.0.0.1

Reached destination:127.0.0.1 with hop limit:1

but for other addresses present in my lan for whom tracepath works my program blocks at recvfrom.

Can you please point out the reasons?

Thank you.

Here's libsock:-

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<arpa/inet.h>
#include<sys/types.h>
#include<netinet/in.h>
#include<sys/socket.h>
#include<unistd.h>
#include<pthread.h>
#include<poll.h>
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/ipc.h>
#include<fcntl.h>
#include<sys/stat.h>
#include<signal.h>
#include<sys/sem.h>
#include<poll.h>
#include<pthread.h>
#include<sys/select.h>
#include<sys/un.h>
#define SA (struct sockaddr*)
Was it helpful?

Solution

If you want to build the IP headers by hand, you have to set the source address to an IP which has routability to the IP address you give as a destination. E.g. for localhost, you can set the source to 127.0.0.1, since localhost "can ping" localhost (i.e. has routability there).

The sizes you give the send and receive seem really too small. I made the following changes on my home computer (it is behind a NAT device, thus the 192.168.1.0/24 address).

inet_pton (AF_INET, "192.168.1.168", &(ip_hdr->ip_src));
....
sendto (sfd, buf, sizeof(struct ip) + sizeof(struct icmphdr), 0, SA & addr, sizeof addr);
....
recvfrom (sfd, buff, sizeof(buff), 0, SA & addr2, &len);

Example output:

thuovila@glx:~/src/so$ sudo ./a.out 128.214.248.132
hop limit:0 Address:192.168.1.1
hop limit:1 Address:192.168.1.1
hop limit:2 Address:91.156.128.1
hop limit:3 Address:139.97.9.58
hop limit:4 Address:139.97.6.209
hop limit:5 Address:139.97.6.250
hop limit:6 Address:193.110.224.14
hop limit:7 Address:193.166.255.93
Reached destination:128.214.248.132 with hop limit:8
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top