【问题标题】:Hops tracing ttl reciveform on ios在 ios 上跟踪 ttl reciveform 的啤酒花
【发布时间】:2013-01-13 14:47:01
【问题描述】:

我正在尝试为 iOS 实现简单的跟踪路由。一切似乎都运行良好,但不知何故,当我在模拟器或设备上运行我的应用程序时,当 CLI traceroute 找到所有 14 个路由器时,它只在途中发现了少数 (6-7) 个第一路由器。

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;
    }
  }
}

我尝试绑定发送套接字,但结果相同,我无法在 iOS 上使用 Sock_raw。我试图在我的 Mac 上运行它并得到相同的结果。我得到的错误是“资源暂时不可用;”对于recvfrom()。这是为什么?我该如何解决?

【问题讨论】:

    标签: ios c sockets network-programming ttl


    【解决方案1】:

    接收套接字超时可能引发EAGAIN 错误(产生“资源暂时不可用;”字符串)。

    由于您使用此行仅将 10000 微秒设置为读取超时(恕我直言,这真的很短)...

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

    ...可能路越远(我的意思是您必须通过的路由器数量),您在这种情况下遇到的机会就越大。

    尝试提高超时值,如果它变得更好,请告诉我们。

    编辑

    我在linux下试了源码,发现有两种问题。

    • 如上所述:超时
    • 80 端口问题

    我刚刚提高了超时时间并使用了一个不同于 80 的端口(在我的情况下,我将 udp 消息发送到 40000 端口)并且我像traceroute 命令一样取回了所有跃点。

    我不确定为什么会出现这种行为。也许某种“可能的恶意数据包警报”被丢弃它的路由器触发

    进一步编辑

    看这个链接:man traceroute

    可用方法列表部分中,您可以找到许多方法来实现您所需要的。您的方法与默认方法类似,说明:

    探测数据包是具有所谓“不太可能”的目标端口的 udp 数据报。第一个探针的“不太可能”端口是 33434,然后对于每个下一个探针,它都会增加 1。由于这些端口预计不会被使用,因此目标主机通常会返回“icmp unreach port”作为最终响应。 (没有人知道当某些应用程序监听此类端口时会发生什么)。

    因此,如果您需要完全模拟常见 Linux 跟踪路由的行为,您必须将目标端口增加 1,每次 TTL 增加(或者每次您无法得到响应恕我直言)

    也许,有时您的命令在某些端口上不起作用,因为路由器正在侦听后者(正如 Linux 手册所建议的那样,我用粗体下划线)。

    【讨论】:

    • 我忘了提及我尝试更改超时、ttl 和尝试次数但没有帮助。实际上,在短时间内它甚至效果更好。
    • 您是否尝试将 timout 提高到一个非常大的值?就像 10 秒。另外,根据我看到的代码,如果您无法从路由器获得响应,则程序迟早应该提高 ttl 值并尝试知道下一跳是什么。发生这种情况,或者您不能仅从某个跃点(比如第 6 个跃点)获得任何结果?
    • 我试图在linux下编译它来研究它的行为。我更新了我的答案。看看吧
    • TNX 很多寻求帮助。ttl 根据循环上升,但在一些路由器之后我只是停下来接收任何接收。对于​​ ttl 6,我得到了 ttl 7 的 ip,所以我得到了“资源暂时不可用;"
    • 我把端口换成更大的,它开始在我的公寓里工作。但是当我开始工作并尝试运行该应用程序时,它仍然向我显示了 3 个第一批路由器,而 CLI 跟踪路由找到了 14 个路由器。有什么想法吗?
    猜你喜欢
    • 1970-01-01
    • 2016-10-06
    • 1970-01-01
    • 2016-08-22
    • 2014-08-03
    • 1970-01-01
    • 2020-04-03
    • 2014-12-09
    • 1970-01-01
    相关资源
    最近更新 更多