EzDevInfo.com

icmp interview questions

Top icmp frequently asked interview questions

how to icmp ping on android

I need to do a icmp ping to a host from my android device. I need to measure the round trip time. I am proficient with android and java, just dont know what library to use. How do I do it? Is it possible via 3G, Edge?


Source: (StackOverflow)

How do I validate the ICMPv6 checksum? (Why am do I keep getting a checksum of 0x3fff?)

I'm working on a Linux userspace program that receives IPv6 router advertisement packets. As part of RFC4861 I need to verify the ICMPv6 checksum. Based on my research, most of which refers to the refers to the IP checksum in general if you compute the ones compliment checksum of the IPv6 pseudo header and the packet contents the result should be 0xffff. But I keep getting a checksum of 0x3fff.

Is there something wrong with my checksum implementation? does the Linux kernel verify the ICMPv6 checksum before passing the packets to userspace? is there a good reference source for known good ICMPv6 packets to test with?

uint16_t
checksum(const struct in6_addr *src, const struct in6_addr *dst, const void *data, size_t len) {
    uint32_t checksum = 0;
    union {
        uint32_t dword;
        uint16_t word[2];
        uint8_t byte[4];
    } temp;

    // IPv6 Pseudo header source address, destination address, length, zeros, next header
    checksum += src->s6_addr16[0];
    checksum += src->s6_addr16[1];
    checksum += src->s6_addr16[2];
    checksum += src->s6_addr16[3];
    checksum += src->s6_addr16[4];
    checksum += src->s6_addr16[5];
    checksum += src->s6_addr16[6];
    checksum += src->s6_addr16[7];

    checksum += dst->s6_addr16[0];
    checksum += dst->s6_addr16[1];
    checksum += dst->s6_addr16[2];
    checksum += dst->s6_addr16[3];
    checksum += dst->s6_addr16[4];
    checksum += dst->s6_addr16[5];
    checksum += dst->s6_addr16[6];
    checksum += dst->s6_addr16[7];

    temp.dword = htonl(len);
    checksum += temp.word[0];
    checksum += temp.word[1];

    temp.byte[0] = 0;
    temp.byte[1] = 0;
    temp.byte[2] = 0;
    temp.byte[3] = 58; // ICMPv6
    checksum += temp.word[0];
    checksum += temp.word[1];

    while (len > 1) {
        checksum += *((const uint16_t *)data);
        data = (const uint16_t *)data + 1;
        len -= 2;
    }

    if (len > 0)
        checksum += *((const uint8_t *)data);

    printf("Checksum %x\n", checksum);

    while (checksum >> 16 != 0)
        checksum = (checksum & 0xffff) + (checksum >> 16);

    checksum = ~checksum;

    return (uint16_t)checksum;
}

Source: (StackOverflow)

Advertisements

How to ICMPs and traceroutes in Java

Java does not have primitives for ICMPs and traceroute. How to overcome this? Basically I'm building code that should run in *nix and Windows, and need a piece of code that will run in both platforms.


Source: (StackOverflow)

How to Ping Using Sockets Library - C

  • Compiler: Code::Blocks(GNU GCC)
  • Platform: Windows(x86)
  • Includes: winsock.h winsock2.h (ws2_32 is linked as well)

I am currently trying to write a program that will read a text file containing a list of IP-Addresses and ping each IP-Addresses respectively. If the host responds to the ping then the host's IP-Address will be copied to a seconded file specified by the user. Unfourtantly this is the first time I have used C's socket library and I cannot find a good tutorial about how to ping using C. From what I understand of the couple tutorials I did find. I need to included a ICMP header, which is a struct containg the ICMP type, code, and checksum, in a IP datagram. But I have no idea how to go about doing so, should I declare the struct myself or is it declared in a header file? I am assuming that it is in a header but the tutorials contradicted each other about exactly where it is declared. I tired including icmp.h and netinet/icmp.h but my compiler complained that they don't exist so I created my own struct.

    struct echo_request
    {
        char type; // Type
        char code; // Code
        short checksum; // Checksum
        short id; // Identification
        short seq; // Sequence
        int time; // Time
        char data[16]; // Data
    };

I thought that I might be able to get away with it but I wasn't even able to compile my program because my compiler says that in_cksum()(checksum generator) is undefined.

To sum up my questions, what header files should I include, how do I create a ping packet, am I using the correct checksum generator function, should a ping be directed to port 80, and should the socket I use be RAW or DGRAM?

This is what I have so far, please note that I have purposely left out error checking.

    int socket_descriptor = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);

    struct sockaddr_in address; //Initialize address struct
    memset(&address, 0, sizeof(address)); //Clear address struct

    //Declare address
    address.sin_family = AF_INET;
    address.sin_addr.s_addr = inet_addr(ipaddress);
    address.sin_port = htons(80);

    //Bind socket to address
    bind(socket_descriptor, (struct sockaddr *)&address, sizeof(address));

    //Create packet
    struct echo_request packet; //See above for declaration of struct
    memset(packet.data, 1, 16);
    packet.type = 8; //ECHO_REQUEST
    packet.code = 0;
    packet.time = gettime();
    packet.checksum = 0;
    packet.checksum = in_cksum(packet, sizeof(packet));

Source: (StackOverflow)

Writing a basic traceroute script in C

I have to write a trceroute script but I'm not sure if my attempts are correct.

Right now I'm doing it like that (please correct me if I'm doing wrong or clumsy):

  1. Got an struct for ip- and udpheader
  2. A checksum function
  3. Opening 2 sockets: One for sending UDP-packets in SOCK_RAW mode (to manipulate ttl) and one to receive ICMP-answers from the routers.
  4. Using sendto() to send UDP packet
  5. Having no clue how to receive and process an ICMP answer

Are there any more comfortable ways to change the TTL than using sock_raw where I have to define all header stuff by myself? What parameters should I use for socket() when opening ICMP sock? How to receive the ICMP answer?


Source: (StackOverflow)

size of ICMP type 11 packet payload

What's the size of the ICMP packet payload when the type is 11, i.e. time exceeded? Since it contains an IP header and the first 8 Bytes of the IP packet payload generating the ICMP message, I thought its size was 20 + 8 = 28.

I'm replaying some common user traffic with TTL=1. In the ICMP messages I have dumped I noticed that:

  • all ICMP packets generated by UDP packets have payload of size 28 Bytes
  • all those generated by TCP packets have payload of size 40 Bytes

Since I need to match ICMP time-exceeded messages with the packets that triggered them by comparing those bytes, this piece of information is essential, but I can't find figure out why this happens.


Source: (StackOverflow)

Traceroute: Can it trace a path from A to B correctly?

Traceroute is an application to trace the path from A to B. (A is your location and B is the server you want to trace). In Windows, you can type tracert. The main algorithm is:

send UDP with TTL = 1
Server A1 received, and return ICMP packet to A because TTL is expired.
--> know first machine between. For example A1.

send UDP with TTL = 2
Server A1 received, and send this UDP to server A2.
Server A2 received, and return ICMP packet to A because TTL is expired
--> know second machine between. In this example is A2.

Do it until to B. we can track down: A -> A1 -> A2 -> ... ->B

Does this algorithm work correctly? Because at different time, an intermediate server can send a message to different server. For example, at first time, UDP message is sent to A1, but at a later time, it can send to another server, for example, B1. So, trace route will not work properly.

Did I misunderstand something?


Source: (StackOverflow)

Path MTU discovery - where are ICMP responses?

I'm doing some experiments with path MTU discovery in Linux. As far as I understood from RFC 1191, if a router receives a packet with non-zero DF bit and the packet can't be sent to the next host without fragmentation, then the router should drop the packet and send ICMP message to the initial sender.

I've created several VM on my computer and linked them in the following manner:

VM1 (192.168.100.2)

R1  (192.168.100.1, 
     192.168.150.1)

R2  (192.168.150.2, 
     192.168.200.1)

VM2 (192.168.200.2)

Rx - are virtual machines with Linux installed, they have two network interfaces with a static route. Pinging V2 from V1 and vice versa is successful.

traceroute from 192.168.100.2 to 192.168.200.2 (192.168.200.2)
 1  192.168.100.1 (192.168.100.1)  0.437 ms  0.310 ms  0.312 ms
 2  192.168.150.2 (192.168.150.2)  2.351 ms  2.156 ms  1.989 ms
 3  192.168.200.2 (192.168.200.2)  43.649 ms  43.418 ms  43.244 ms

tracepath 192.168.200.2
 1:  ubuntu-VirtualBox.local                               0.211ms pmtu 1500
 1:  192.168.100.1                                         0.543ms 
 1:  192.168.100.1                                         0.546ms 
 2:  192.168.150.2                                         0.971ms 
 3:  192.168.150.2                                         1.143ms pmtu 750
 3:  192.168.200.2                                         1.059ms reached

Segments 100.x and 150.x have MTU 1500. Segment 200.x has MTU 750.

I'm trying to send UDP packets with DF enabled. The fact is the VM1 doesn't send the packet at all in case of the packet's size greater than 750 (I receive EMSGSIZE error for send() invocation).

However I expect such behavior for packets which size is more than 1500. And I expect that the VM1 sends packets which size is between 750 and 1500 to the R1, and the R1 (or R2) drops such packets and returns ICMP packet to the VM1. But this doesn't happen.

There are two questions:

1) Why?

2) Is it possible to set up my virtual network to receive ICMP packets in according to RFC 1191?

Thanks.


Source: (StackOverflow)

recvfrom not returning -1 after signal

I am writing a ping program using raw sockets but recvfrom is not returning -1 with EINTR even though a SIGALRM is being handled.This SIGALRM is produced by my alarm(1).I want recvfrom to return so that i can decide that the packet has indeed been lost.

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

double total=0, max=0, min=10000000;
int totalpackets=0, packetslost=0;
int recieved=0;

void handler2()
{
  printf("host unreachable\n");
}

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

void 
handler()
{
  printf("\n");
  printf("--------------PINGING STATISTICS----------------\n");
  printf("AVG:%f MAX:%f MIN:%f TOTAL PACKETS:%d PACKETS LOST:%d SUCCESS PERCENTAGE:%f\n\n",total/(totalpackets-packetslost),max,min,totalpackets,packetslost,((double)(totalpackets-packetslost)/(double)totalpackets)*100);
  exit(0);
}

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

  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;
  struct ip* ip_hdr=(struct ip*)buf;
  addr.sin_port = htons (7);
  addr.sin_family = AF_INET;
  inet_pton (AF_INET, argv[1], &(addr.sin_addr));

  ip_hdr->ip_hl = 5;
  ip_hdr->ip_v = 4;
  ip_hdr->ip_tos = 0;
  ip_hdr->ip_len = 20 + 8 + 64;
  ip_hdr->ip_id =0;
  ip_hdr->ip_off = 64;
  ip_hdr->ip_ttl = 64;
  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, 4);

  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 =1;

  memset(buf+28,'a',64);
  icmphd->checksum = csum ((unsigned short *) (buf+20), 36);
  signal(SIGINT,handler);
  struct timeval tv1,tv2;  

  printf("Pinging %s with 64 bytes of data.\n\n",argv[1]);

  while(1)
  {
    recieved=0;     
    totalpackets++;
    sendto (sfd, buf,20+ 8+64, 0, SA & addr, sizeof addr);
    char buff[4096] = { 0 };
    struct sockaddr_in addr2;
    socklen_t len = sizeof (struct sockaddr_in);
    signal(SIGALRM,handler2);
    gettimeofday(&tv1,NULL);
    alarm(1);
    int x=recvfrom (sfd, buff, 20+8+64, 0, SA & addr2, &len);
    gettimeofday(&tv2,NULL);
    double   d=(double)(tv2.tv_sec-tv1.tv_sec)*1000+((double)(tv2.tv_usec-tv1.tv_usec))/1000;

    if(x>0) {
      struct icmphdr *icmphd2 = (struct icmphdr *) (buff + 20);
      printf ("Reached destination:%s\tTime elapsed:%f ms\n\n",
          inet_ntoa (addr2.sin_addr),d);
      total+=d;
      if(d>max)
        max=d;
      if(d<min)
        min=d;
    } else {
      printf("Packet lost\n");   
      packetslost++;
    }

    sleep(1);
  }
  return 0;
}

libsock contains headers and SA=(struct sockaddr*)

Is SIGALRM different from other signals, I have not set SA_RESTART..

Thanks.


Source: (StackOverflow)

Ping ICMP echo request

Are there any methods to ping icmp (echo request) instead of using isReachable? isReachable establish a TCP connection on port 7 and when I used wireshark I did not see any ICMP packets on Window and ICMP type 3 on Linux (not type 8 and 0). So if someone have suggestions or solutions could you please tell me. Thanks a lot!


Source: (StackOverflow)

Cannot ping/communicate with Android devices on the same network

I have a nexus 7 running CM10.1 . For some reason i cannot reach it from my laptop on the same wifi network. I cannot ping in either direction. In the past i have been only able to ping one way.

Just tried out on my stock htc sensation and havent the same issue. Also the nexus and htc cant reach each other either.

I have had similar problems with other android devices, in the past i was developing an app and i could not establish a socket connection from the android device to my computer. Once i was able to successfully ping the laptop form my device everything worked.

This isn't persisant, in the past i fiddled around they eventually talked but there was no consistant solution at the time, i never got to the root cause.

I have obvsered this on 2 different wifi networks

Not sure what is happening here my understanding of networks isn't this deep.


Source: (StackOverflow)

How do I implement ICMP ping in Ruby using only the standard the socket library?

It should be possible send and receive ICMP packets using the Ruby socket library but I do not see any good documentation on this.

I do not want to use net-ping, icmp, ping, and all of these other libraries that either fail because of cross-platform issues, require devkit and custom building, which fail during the build process, are neglected and have not been updated for a lengthy time, and/or are just in general buggy.

Does anyone have any good documentation on how to accomplish this? I want to send ICMP echo replies, not TCP or UDP packets.


Source: (StackOverflow)

python with unprivileged ping in linux IPPROTO_ICMP

according to http://kernelnewbies.org/Linux_3.0#head-c5bcc118ee946645132a834a716ef0d7d05b282e we can now ping as an unprivileged user, and I can sort of get it to work.

using https://github.com/jedie/python-ping I modified line 210 to look like

current_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_ICMP)

as root I "echo 1000 1000 > /proc/sys/net/ipv4/ping_group_range"

my group is 1000

and I can run ping.py as myself as an ordinary user, I can see echo requests and echo replies in tcpdump

18:33:24.840291 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto ICMP (1), length 269)
    127.0.0.1 > 127.0.0.1: ICMP echo request, id 38, seq 0, length 249
18:33:24.840309 IP (tos 0x0, ttl 64, id 37939, offset 0, flags [none], proto ICMP (1), length 269)
    127.0.0.1 > 127.0.0.1: ICMP echo reply, id 38, seq 0, length 249

but ping.py doesn't see the replies, and says timeout.

Any ideas how to make this work?

edit:

I'm narrowing down the issue.

print "c", icmp_header, address, self.own_id
if icmp_header["packet_id"] == self.own_id: # Our packet

the problem is icmp_header["packet_id"] is always 8247 and self.own_id is the pid of ping.py. 8247 is 2037 in hex, which I can see quite a few time in the dump.

This is a full dump of a ping on the wire

19:25:15.513285 00:00:00:00:00:00 > 00:00:00:00:00:00, ethertype IPv4 (0x0800), length 283: (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto ICMP (1), length 269)
  127.0.0.1 > 127.0.0.1: ICMP echo request, id 70, seq 2, length 249
    0x0000:  4500 010d 0000 4000 4001 3bee 7f00 0001  E.....@.@.;.....
    0x0010:  7f00 0001 0800 d932 0046 0002 5b36 362c  .......2.F..[66,
    0x0020:  2036 372c 2036 382c 2036 392c 2037 302c  .67,.68,.69,.70,
    0x0030:  2037 312c 2037 322c 2037 332c 2037 342c  .71,.72,.73,.74,
    0x0040:  2037 352c 2037 362c 2037 372c 2037 382c  .75,.76,.77,.78,
    0x0050:  2037 392c 2038 302c 2038 312c 2038 322c  .79,.80,.81,.82,
    0x0060:  2038 332c 2038 342c 2038 352c 2038 362c  .83,.84,.85,.86,
    0x0070:  2038 372c 2038 382c 2038 392c 2039 302c  .87,.88,.89,.90,
    0x0080:  2039 312c 2039 322c 2039 332c 2039 342c  .91,.92,.93,.94,
    0x0090:  2039 352c 2039 362c 2039 372c 2039 382c  .95,.96,.97,.98,
    0x00a0:  2039 392c 2031 3030 2c20 3130 312c 2031  .99,.100,.101,.1
    0x00b0:  3032 2c20 3130 332c 2031 3034 2c20 3130  02,.103,.104,.10
    0x00c0:  352c 2031 3036 2c20 3130 372c 2031 3038  5,.106,.107,.108
    0x00d0:  2c20 3130 392c 2031 3130 2c20 3131 312c  ,.109,.110,.111,
    0x00e0:  2031 3132 2c20 3131 332c 2031 3134 2c20  .112,.113,.114,.
    0x00f0:  3131 352c 2031 3136 2c20 3131 372c 2031  115,.116,.117,.1
    0x0100:  3138 2c20 3131 392c 2031 3230 5d         18,.119,.120]
19:25:15.513300 00:00:00:00:00:00 > 00:00:00:00:00:00, ethertype IPv4 (0x0800), length 283: (tos 0x0, ttl 64, id 37971, offset 0, flags [none], proto ICMP (1), length 269)
  127.0.0.1 > 127.0.0.1: ICMP echo reply, id 70, seq 2, length 249
    0x0000:  4500 010d 9453 0000 4001 e79a 7f00 0001  E....S..@.......
    0x0010:  7f00 0001 0000 e132 0046 0002 5b36 362c  .......2.F..[66,
    0x0020:  2036 372c 2036 382c 2036 392c 2037 302c  .67,.68,.69,.70,
    0x0030:  2037 312c 2037 322c 2037 332c 2037 342c  .71,.72,.73,.74,
    0x0040:  2037 352c 2037 362c 2037 372c 2037 382c  .75,.76,.77,.78,
    0x0050:  2037 392c 2038 302c 2038 312c 2038 322c  .79,.80,.81,.82,
    0x0060:  2038 332c 2038 342c 2038 352c 2038 362c  .83,.84,.85,.86,
    0x0070:  2038 372c 2038 382c 2038 392c 2039 302c  .87,.88,.89,.90,
    0x0080:  2039 312c 2039 322c 2039 332c 2039 342c  .91,.92,.93,.94,
    0x0090:  2039 352c 2039 362c 2039 372c 2039 382c  .95,.96,.97,.98,
    0x00a0:  2039 392c 2031 3030 2c20 3130 312c 2031  .99,.100,.101,.1
    0x00b0:  3032 2c20 3130 332c 2031 3034 2c20 3130  02,.103,.104,.10
    0x00c0:  352c 2031 3036 2c20 3130 372c 2031 3038  5,.106,.107,.108
    0x00d0:  2c20 3130 392c 2031 3130 2c20 3131 312c  ,.109,.110,.111,
    0x00e0:  2031 3132 2c20 3131 332c 2031 3134 2c20  .112,.113,.114,.
    0x00f0:  3131 352c 2031 3136 2c20 3131 372c 2031  115,.116,.117,.1
    0x0100:  3138 2c20 3131 392c 2031 3230 5d         18,.119,.120]

AFAICT, the icmp header might be packed wrong. however it's just a wild stab, I will stare at it some more later, in the meantime, any help would be appreciated.


Source: (StackOverflow)

Problem with isReachable in InetAddress class

As an assignment I have to find all the alive computers on a LAN. For which I am using isReachable function of InetAddress class. But problem is that nothing is shown reachable to me. So I tried to have isReachable with Google's IP but still this is unreachable.

Here is the code:

import java.net.*;

public class alive{
    public static void main(String args[]){
        try{
            InetAddress ia = InetAddress.getByAddress(new byte[]{(byte)209, (byte)85, (byte)153, (byte)104});
            boolean b = ia.isReachable(10000);
            if(b){
                System.out.println("Reachable");
            }
            else{
                System.out.println("Unrachable");
            }

        }catch(Exception e){
            System.out.println("Exception: " + e.getMessage());
        }
    }
}

Output is : Unreachable


Source: (StackOverflow)

What is the proper process for ICMP echo request/reply on unreachable destinations?

Goal:

I need to be able to ping a network switch to determine whether or not it is available. This is meant to tell the user that either the network cabling is unplugged, the network switch is unavailable, or some other problem lies within the network communication pathway. I realize this is not a comprehensive diagnosis tool, but something is better than nothing.

Design:

I planned on using ICMP with raw sockets to send five (5) ping messages to a particular address in IPv4 dot-notation. I will setup an ICMP filter on the socket and will not be creating my own IP header. Transmission of the ICMP will be through the sendto method and reception through the recvfrom method. This will occur on a single thread (though another thread can be used to break transmission and reception apart). Reception of a message will further be filtered by matching the ID of the received message to the ID that was transmitted. The ID stored will be the running process ID of the application. If an ICMP_ECHOREPLY message is received and the ID of the message and the stored ID match, then a counter is incremented until five (4) has been reached (the counter is zero-based). I will attempt to send a ping, wait for its reply, and repeat this process five (5) times.

The Problem:

After having implemented my design, whenever I ping a particular valid network address (say 192.168.11.15) with an active network participant, I receive ICMP_ECHOREPLY messages for each of the five (5) pings. However, whenever I ping a valid network address (say 192.168.30.30) with inactive network participants (meaning no device is connected to the particular address), I get one (1) ICMP_DEST_UNREACH, and four (4) ICMP_ECHOREPLY messages. The ID in the reply messages match the ID stored within the software. Whenever I perform a 'ping 192.168.30.30' from the commandline, I get 'From 192.168.40.50 icmp_seq=xx Destination Host Unreachable'. Am I not supposed to be receiving ICMP_DEST_UNREACH messages instead of ICMP_ECHOREPLY messages?

The Code:

Ping.h:

#include <netinet/in.h>
#include <linux/ip.h>
#include <linux/ipmc.h>
#include <arpa/inet.h>
#include <cstdio>
#include <cstdlib>
#include <stdint.h>
#include <time.h>
#include <errno.h>
#include <string>
#include <cstring>
#include <netdb.h>

class Ping
{
    public:
        Ping(std::string host) : _host(host) {}
        ~Ping() {}

        void start()
        {
            int sock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
            if(sock < 0)
            {
                printf("Failed to create socket!\n");
                close(sock);
                exit(1);
            }

            setuid(getuid());

            sockaddr_in pingaddr;
            memset(&pingaddr, 0, sizeof(sockaddr_in));
            pingaddr.sin_family = AF_INET;

            hostent *h = gethostbyname(_host.c_str());
            if(not h)
            {
                printf("Failed to get host by name!\n");
                close(sock);
                exit(1);
            }

            memcpy(&pingaddr.sin_addr, h->h_addr, sizeof(pingaddr.sin_addr));

            // Set the ID of the sender (will go into the ID of the echo msg)
            int pid = getpid();

            // Only want to receive the following messages
            icmp_filter filter;
            filter.data = ~((1<<ICMP_SOURCE_QUENCH) |
                            (1<<ICMP_DEST_UNREACH) |
                            (1<<ICMP_TIME_EXCEEDED) |
                            (1<<ICMP_REDIRECT) |
                            (1<<ICMP_ECHOREPLY));
            if(setsockopt(sock, SOL_RAW, ICMP_FILTER, (char *)&filter, sizeof(filter)) < 0)
            {
                perror("setsockopt(ICMP_FILTER)");
                exit(3);
            }

            // Number of valid echo receptions
            int nrec = 0;

            // Send the packet
            for(int i = 0; i < 5; ++i)
            {
                char packet[sizeof(icmphdr)];
                memset(packet, 0, sizeof(packet));

                icmphdr *pkt = (icmphdr *)packet;
                pkt->type = ICMP_ECHO;
                pkt->code = 0;
                pkt->checksum = 0;
                pkt->un.echo.id = htons(pid & 0xFFFF);
                pkt->un.echo.sequence = i;
                pkt->checksum = checksum((uint16_t *)pkt, sizeof(packet));

                int bytes = sendto(sock, packet, sizeof(packet), 0, (sockaddr *)&pingaddr, sizeof(sockaddr_in));
                if(bytes < 0)
                {
                    printf("Failed to send to receiver\n");
                    close(sock);
                    exit(1);
                }
                else if(bytes != sizeof(packet))
                {
                    printf("Failed to write the whole packet --- bytes: %d, sizeof(packet): %d\n", bytes, sizeof(packet));
                    close(sock);
                    exit(1);
                }

                while(1)
                {
                    char inbuf[192];
                    memset(inbuf, 0, sizeof(inbuf));

                    int addrlen = sizeof(sockaddr_in);
                    bytes = recvfrom(sock, inbuf, sizeof(inbuf), 0, (sockaddr *)&pingaddr, (socklen_t *)&addrlen);
                    if(bytes < 0)
                    {
                        printf("Error on recvfrom\n");
                        exit(1);
                    }
                    else
                    {
                        if(bytes < sizeof(iphdr) + sizeof(icmphdr))
                        {
                            printf("Incorrect read bytes!\n");
                            continue;
                        }

                        iphdr *iph = (iphdr *)inbuf;
                        int hlen = (iph->ihl << 2);
                        bytes -= hlen;

                        pkt = (icmphdr *)(inbuf + hlen);
                        int id = ntohs(pkt->un.echo.id);
                        if(pkt->type == ICMP_ECHOREPLY)
                        {
                            printf("    ICMP_ECHOREPLY\n");
                            if(id == pid)
                            {
                                nrec++;
                                if(i < 5) break;
                            }
                        }
                        else if(pkt->type == ICMP_DEST_UNREACH)
                        {
                            printf("    ICMP_DEST_UNREACH\n");
                            // Extract the original data out of the received message
                            int offset = sizeof(iphdr) + sizeof(icmphdr) + sizeof(iphdr);
                            if(((bytes + hlen) - offset) == sizeof(icmphdr))
                            {
                                icmphdr *p = reinterpret_cast<icmphdr *>(inbuf + offset);
                                id = ntohs(p->un.echo.id);
                                if(origid == pid)
                                {
                                    printf("        IDs match!\n");
                                    break;
                                }
                            }
                        }
                    }
                }
            }

            printf("nrec: %d\n", nrec);
        }

    private:
        int32_t checksum(uint16_t *buf, int32_t len)
        {
            int32_t nleft = len;
            int32_t sum = 0;
            uint16_t *w = buf;
            uint16_t answer = 0;

            while(nleft > 1)
            {
                sum += *w++;
                nleft -= 2;
            }

            if(nleft == 1)
            {
                *(uint16_t *)(&answer) = *(uint8_t *)w;
                sum += answer;
            }

            sum = (sum >> 16) + (sum & 0xFFFF);
            sum += (sum >> 16);
            answer = ~sum;

            return answer;
        }

        std::string _host;
};

main.cpp:

#include "Ping.h"

int main()
{
//     Ping ping("192.168.11.15");
    Ping ping("192.168.30.30");
    ping.start();

    while(1) sleep(10);
}

In order to compile, just type 'g++ main.cpp -o ping' into the command-line of a Linux box, and it should compile (that is, if all of the source code is installed).

Conclusion:

Can anyone tell me why I am receiving one (1) ICMP_DEST_UNREACH and four (4) ICMP_ECHOREPLY messages from a device that isn't on that particular network address?

NOTE: You can change the network IP address from the main.cpp file. Just change the IP to a device that actually exists on your network or a device that doesn't exist on your network.

I'm also not interested in criticisms about coding style. I know it isn't pretty, has 'C' style casting mixed with C++ casts, has poor memory management, etc, but this is only prototype code. It isn't meant to be pretty.


Source: (StackOverflow)