Tracing hops ttl reciveform on ios

I am trying to implement a simple traceroute for iOS. Everything seems to be working fine, except that somehow, when I run my application on a simulator or on a device, it only finds the few (6-7) first routers in the path when the CLI trace finds all 14 routers.

const char *c = "www.gmail.com"; struct hostent *host_entry = gethostbyname(c); char *ip_addr; ip_addr = inet_ntoa(*((struct in_addr *)host_entry->h_addr_list[0])); struct sockaddr_in destination, fromAddr; int recv_sock; int send_sock; // Creting Sockets/// if ((recv_sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_ICMP)) < 0) // using UDP socket. { NSLog(@"Could not cretae recv_sock.\n"); } if ((send_sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { NSLog(@"Could not cretae send_sock.\n"); } memset(&destination, 0, sizeof(destination)); destination.sin_family = AF_INET; destination.sin_addr.s_addr = inet_addr(ip_addr); destination.sin_port = htons(80); struct timeval tv; tv.tv_sec = 0; tv.tv_usec = 10000; setsockopt(recv_sock, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(struct timeval)); char *cmsg = "GET / HTTP/1.1\r\n\r\n"; int max_ttl = 20; int num_attempts = 5; socklen_t n = sizeof(fromAddr); char buf[100]; for (int ttl = 1; ttl <= max_ttl; ttl++) { memset(&fromAddr, 0, sizeof(fromAddr)); if (setsockopt(send_sock, IPPROTO_IP, IP_TTL, &ttl, sizeof(ttl)) < 0) NSLog(@"error in setsockopt\n"); for (int try = 0; try < num_attempts; try ++) { if (sendto(send_sock, cmsg, sizeof(cmsg), 0, (struct sockaddr *)&destination, sizeof(destination)) != sizeof(cmsg)) NSLog(@"error in send to...\ n@ "); int res = 0; if ((res = recvfrom(recv_sock, buf, 100, 0, (struct sockaddr *)&fromAddr, &n)) < 0) { NSLog(@"an error: %s; recvfrom returned %d\n", strerror(errno), res); } else { char display[16] = {0}; inet_ntop(AF_INET, &fromAddr.sin_addr.s_addr, display, sizeof(display)); NSLog(@"Received packet from%s for TTL=%d\n", display, ttl); break; } } } 

I tried to bind a send socket, but have the same results, and I cannot use Sock_raw on iOS. I tried running it on my mac and got the same results. The error I get is “Resource temporarily unavailable”; for recvfrom() . Why is this? How can i fix this?

+4
source share
1 answer

The EAGAIN error (creating the string "Resource temporarily unavailable;") can be increased by the timeout of the receiving socket.

Since you set only 10,000 microseconds as read timeout (this is really a short IMHO) with this line ...

 struct timeval tv; tv.tv_sec = 0; tv.tv_usec = 10000; setsockopt(recv_sock, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv,sizeof(struct timeval)); 

... it is possible that the longer (I mean the number of routers you have to go through), the more likely you will be in this situation.

Try increasing the timeout value and let us know if it gets better.

EDIT

I tried the source code under linux, and I noticed two problems.

  • As mentioned above: Timeouts
  • Problem with port 80

I just raised the timeout and used a port other than 80 (in my case, I sent an udp message to port 40000) and I returned all the haps as a traceroute command.

I am not sure why this behavior occurs. Perhaps some kind of “possible malicious burst” is triggered by a router that discards it

FURTHER IMAGE

Take a look at this link: man traceroute

In the List of Available Methods section , you can find many ways to achieve what you need. Your method is similar to the default default:

Probe packets are udp datagrams with so-called "unlikely" destination ports. The "wrong" port of the first probe is 33434, then for each next probe it increases by one. Since it is assumed that the ports are not used, the destination host usually returns "icmp unreach port" as the final answer. ( No one knows what happens when some application listens on such ports, though ).

So, if you need to fully emulate the behavior of the general Linux trace, you should increase by 1 destination port every time the TTL is incremented (or every time you cannot get an IMHO response)

MAYBE, sometimes your command doesn’t work on certain ports, because the router listens on the latter (as the Linux manual suggests and boldly emphasized by me).

+3
source