title: android ndk dev use c traceroute command，why can't I receive the timeout echo？
body: <ol>
  <li>Create socket：socket(AF_INET, SOCK_DGRAM, IPPROTO_ICMP)</li>
  <li>Phenomenon: by default I can send request and reply echo on this socket.  </li>
  </ol>
  
  <p>But for <strong>traceroute</strong> implement, when tt1 was set to 1, 2, 3, 4... then send request echo, at this time I assumed to receive the timeout echo, and furthermore I can obtain router address bypass.</p>
  
  <p>But in my program, method recvfrom can't receive this timeout echo, and always been blocked, meanwhile when I capture packets using <strong>wireshark</strong>, I can capture this timeout echo precisely, and my question is why this echo couldn't be received by my program?</p>
  
  <p>Question is in which part what org filter this timeout echo?</p>
  
  <p>timeout reply echo can be captured by wireshark, but can't be obtain by my program, the detail as below png:
  <a href="https://i.stack.imgur.com/s2T1G.png" rel="nofollow noreferrer">enter image description here</a></p>
  
  <p>my source code below :</p>
  
  <pre><code>#include&lt;stdio.h&gt;
  #include&lt;stdlib.h&gt;
  #include&lt;signal.h&gt;
  #include&lt;unistd.h&gt;
  #include&lt;netinet/ip_icmp.h&gt;
  #include&lt;netdb.h&gt;
  #include&lt;string.h&gt;
  #include&lt;sys/types.h&gt;
  #include&lt;sys/socket.h&gt;
  #include&lt;sys/time.h&gt;
  #include&lt;netinet/in.h&gt;
  #include&lt;arpa/inet.h&gt;
  #include&lt;pthread.h&gt;
  
  struct sockaddr_in dst_addr;
  struct sockaddr_in recv_addr;
  char icmp_pkt[1024] = {0};
  char recv_pkt[1024] = {0};
  int bytes = 56, nsend_pkt = 0, nrecv_pkt = 0;
  
  int in_chksum(unsigned short *buf, int size);
  int pack(int send_pkt, pid_t pid);
  void send_traceroute(int sockfd, pid_t pid);
  int unpack(int sockfd, char *recv_pkt, struct sockaddr_in *src_addr, int size, pid_t pid);
  int recv_traceroutes(int sockfd, pid_t pid);
  void tv_sub(struct timeval *out,struct timeval *in);
  
  int main(int argc, char **argv)
  {
      int size = 50 * 1024;
      int errno = -1;
      int tried_times = 30, i = 0;
      int ttl = 0, ret = 0;
      int sockfd = 0;
      struct in_addr ipv4_addr;
      struct hostent *ipv4_host;
      struct protoent *protocol = NULL;
      pid_t pid;
  
      if (argc &lt; 2)
      {
          printf("usage: ./ping &lt;host&gt;\n");
          return -1;
      }
      if ((protocol = getprotobyname("icmp")) == NULL)
      {
          printf("unkown protocol\n");
          return -1;
      }
      pid = getpid();
  
      for(i = 0; i &lt; tried_times; i++)
      {
          ttl = i + 1;
          if ((sockfd = socket(AF_INET, SOCK_DGRAM, protocol-&gt;p_proto)) &lt; 0)
          {
              printf("socket fail, need root\n");
              return -1;
          }
          setsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, &amp;size, sizeof(size));
          setsockopt(sockfd, IPPROTO_IP, IP_MULTICAST_TTL, &amp;ttl, sizeof(ttl));
          setsockopt(sockfd, IPPROTO_IP, IP_TTL, &amp;ttl, sizeof(ttl));
  
          memset(&amp;dst_addr, 0, sizeof(dst_addr));
          dst_addr.sin_family = AF_INET;
          errno = inet_aton(argv[1], &amp;ipv4_addr);
          if (errno == 0)
          {
              ipv4_host = gethostbyname(argv[1]);
              if (NULL == ipv4_host)
              {
                  printf("connect: Invalid argument\n");
                  return -1;
              }
              memcpy(&amp;(dst_addr.sin_addr), ipv4_host-&gt;h_addr, sizeof(struct in_addr));
          }
          else
          {
              memcpy(&amp;(dst_addr.sin_addr), &amp;(ipv4_addr.s_addr), sizeof(struct in_addr));
          }
          printf("%d    ", i + 1);
          send_traceroute(sockfd, pid);
          ret = recv_traceroutes(sockfd, pid);
          close(sockfd);
          if(ret == 1)
          {
              break;
          }
      }
  
      return 0;
  }
  
  int in_chksum(unsigned short *buf, int size)
  {
      int nleft = size;
      int sum = 0;
      unsigned short *w = buf;
      unsigned short ans = 0;
  
      while(nleft &gt; 1)
      {
          sum += *w++;
          nleft -= 2;
      }
      if (nleft == 1)
      {
          *(unsigned char *) (&amp;ans) = *(unsigned char *)w;
          sum += ans;
      }
      sum = (sum &gt;&gt; 16) + (sum &amp; 0xFFFF);
      sum += (sum &gt;&gt; 16);
      ans = ~sum;
      return ans;
  }
  
  int pack(int send_pkt, pid_t pid)
  {
      struct icmp *pkt = (struct icmp *)icmp_pkt;
  
      pkt-&gt;icmp_type = ICMP_ECHO;
      pkt-&gt;icmp_cksum = 0;
      pkt-&gt;icmp_seq = htons(nsend_pkt);
      pkt-&gt;icmp_id = pid;
      pkt-&gt;icmp_cksum = in_chksum((unsigned short *)pkt, bytes + 8);
  
      return bytes + 8;
  }
  
  void send_traceroute(int sockfd, pid_t pid)
  {
      int send_bytes = 0;
      int ret = -1;
  
      nsend_pkt++;
      send_bytes = pack(nsend_pkt, pid);
      ret = sendto(sockfd, icmp_pkt, send_bytes, 0, (struct sockaddr *)&amp;dst_addr, sizeof(dst_addr));
      if (ret == -1)
      {
          printf("send fail\n");
          sleep(1);
          return ;
      }
  }
  
  int unpack(int sockfd, char *recv_pkt, struct sockaddr_in *src_addr, int size, pid_t pid)
  {
      struct iphdr *ip = NULL;
      int iphdrlen;
      struct icmp *icmp;
      struct timeval *tvsend;
      double rtt;
      struct sockaddr peer_addr;
      struct sockaddr_in *tmp_addr = NULL;
      size_t len = 0;
  
      memset(&amp;peer_addr, 0, sizeof(struct sockaddr));
  
      ip = (struct iphdr *)recv_pkt;
      iphdrlen = ip-&gt;ihl&lt;&lt;2;
      icmp = (struct icmp *)(recv_pkt + iphdrlen);
  
      size -= iphdrlen;
      if (size &lt; 8)
      {
          printf("ICMP size is less than 8\n");
          return -1;
      }
  
      len = sizeof(peer_addr);
  
      if ((icmp-&gt;icmp_type == ICMP_TIME_EXCEEDED))
      {    
          tmp_addr = (struct sockaddr_in *)src_addr;
          printf("%s\n", inet_ntoa(tmp_addr-&gt;sin_addr));
      }
      else if((icmp-&gt;icmp_type == ICMP_ECHOREPLY) &amp;&amp; (icmp-&gt;icmp_id == pid))
      {
          tmp_addr = (struct sockaddr_in *)src_addr;
          printf("%s\n", inet_ntoa(tmp_addr-&gt;sin_addr));
          return 1;
      }
      return 0;
  }
  
  int recv_traceroutes(int sockfd, pid_t pid)
  {
      fd_set rd_set;
      struct timeval time;
      time.tv_sec = 5;
      time.tv_usec = 0;
      int ret = 0, nread = 0,recv_len = 0;
  
      recv_len = sizeof(recv_addr);
      FD_ZERO(&amp;rd_set);
      FD_SET(sockfd, &amp;rd_set);
      ret = select(sockfd + 1, &amp;rd_set, NULL, NULL, &amp;time);
      if (ret &lt;= 0)
      {
          return -1;
      }
      else if (FD_ISSET(sockfd, &amp;rd_set))
      {
          nread = recvfrom(sockfd, recv_pkt, sizeof(recv_pkt), 0, (struct sockaddr *)&amp;recv_addr,(socklen_t *) &amp;recv_len);
          if (nread &lt; 0)
          {
              return -1;
          }
  
          ret = unpack(sockfd, recv_pkt, &amp;recv_addr, nread, pid);
          return ret;
      }
  }
  </code></pre>