The SimplePing sample from Apple can fail to perform a ping request (ICMP).

SimplePing is a small example to show how to use the Internet Control Message Protocol (ICMP) “ECHO” facility, measure round-trip-delays and packet loss across network paths.

The code is relatively simple and contains a main function int SimplePing(...) which pings a given remote host with a given number of packets and with a given timeout to wait for responses on each packet.

There is yet a major issue in that code.

If you look at the function which creates the ICMP packet CreateAndSendICMPPacket(...) you should see that the pid of the application is stored in the icmp_id field (identifier) of the ICMP packet:

CreateAndSendICMPPacket in SimplePing

This is used to know later that the ping originated from our application (here SimplePing). If you look at the function WaitAndPrintICMPs(...) which waits for the answer, you see:

WaitAndPrintICMPs in SimplePing

When you first read that code, it seems to be right. There is yet a major issue.

getpid() is delared as pid_t getpid(void); (see unistd.h) and thus returns a 32 bits value. However the field icmp_id of the icmp header structure (see ip_icmp.h) is a n_short which can only contains 16 bits:

icmp header structure

As a consequence, if the pid of the SimplePing application is bigger than 0xFFFF (65535), the pings will fail.

If you search on google “icmp_id getpid”, you will see a lot of souce code containing the exact same issue, even in Apple source code.

If your application contains such code, verify that you store correctly only 16 bits of the pid in the icmp_id field:

icmpHeader.icmp_id = getpid() & 0xFFFF;

and that you compare only 16 bits of the ping answer:

if (icmpPacket->icmpHeader.icmp_id == (getpid() & 0xFFFF))

Note:

A bug report has been made to Apple: rdar://6385021.