3

I wrote a program which uses raw socket to send UDP packets with TTL=1, when I run this program on my local host, I can receive ICMP packets. but when I run it on a Planetlab node, it can't receive ICMP packets.

On planetlab node, each node is shared by many users, and each user is allocated only a virtual slice. So generally, only if you have a process bound to a specific port, you can receive packets from that port, otherwise, random packets can't be delivered to your slice by the system.

But I downloaded traceroute source code and run it on the planetlab node, it can receive ICMP TTL exceeded packets.

That is: I use tcpdump to capture ICMP packets on Planetlab node. when I run my program to send a UDP packet with TTL=1, the tcpdump can't capture an ICMP packet, but when I use traceroute to send a UDP packet with TTL=1, the tcpdump can capture an ICMP packet.

what are potential reasons for this difference?

thanks!

some of my source codes:

if ((sendfd = socket(PF_INET, SOCK_RAW, IPPROTO_UDP)) < 0) {
    perror("Failed in creating socket\n");
    exit(1);
}   

    if ((recvfd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) < 0) {
            perror("Failed in creating socket\n");
            exit(1);
    }



memset(&local_addr, 0, sizeof(local_addr));
local_addr.sin_port = htons(src_port);

if ((bind(sendfd, (struct sockaddr *)& local_addr, sizeof(local_addr))) < 0) {
    perror("Failed in binding socket\n");
    exit(1);
}


if (setsockopt(sendfd, IPPROTO_IP, IP_HDRINCL, &on, sizeof(on)) < 0) {
    perror("Failed in setsockopt!\n");
    exit(1);
}


    if ((bind(recvfd, (struct sockaddr *)& local_addr, sizeof(local_addr))) < 0) {
            perror("Failed in binding socket\n");
            exit(1);
    }


    if (setsockopt(recvfd, IPPROTO_IP, IP_HDRINCL, &on, sizeof(on)) < 0) {
            perror("Failed in setsockopt!\n");
            exit(1);
    }


memset(&dst_addr, 0, sizeof(dst_addr));
dst_addr.sin_family = AF_INET;
dst_addr.sin_addr.s_addr = inet_addr(dst_ip);
dst_addr.sin_port = htons(dst_port);


    nr_bytes = sendto(sendfd, UDPpacket, pkt_len, 0, (struct sockaddr *)&dst_addr, sizeof(dst_addr));

    nr_bytes = recvfrom(recvfd, buf, 2000, 0, (struct sockaddr *)&dst_addr, &len);
nouney
  • 4,363
  • 19
  • 31
misteryes
  • 2,167
  • 4
  • 32
  • 58
  • Are you sure that traceroute uses the ICMP approach ? – nouney Jul 02 '13 at 12:03
  • I'm not sure, the traceroute source codes are a bit complex, I'm still reading it. – misteryes Jul 02 '13 at 12:31
  • Actually traceroutes can use different methods (which can use ICMP, TCP or UDP). Take a look at [the List Of Available Methods in this man](http://linux.die.net/man/8/traceroute). I'v always assumed that `traceroute` can dynamically choose the more apropriate method (however I'm not sure about that), so use Wireshark (or similar tool) in order to find out the method used by `traceroute` on a Planetlab node. – nouney Jul 02 '13 at 12:36
  • Ah, I misunderstood your question, I thought you meant the recv socket protocol. Now I get your idea. Yes, traceroute can send different packets, icmp, udp, tcp, etc. But I don't know why on planetlab node, the traceroute program can make the system deliver the ICMP TTL exceeded packet to my virtual slice, but my program can't. – misteryes Jul 02 '13 at 13:00
  • 2
    I didn't try it, but try changing `(recvfd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)` into `(recvfd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP_UDP)`, as they say here: http://www.planet-lab.org/raw_sockets/api_icmp.html . – Ricky Robinson Sep 24 '13 at 17:08

0 Answers0