Skip to content

May 30, 2017


ICMP Identifier field in UDP between Linux and OSX

by Joe Kuan

Ping packet is traditionally created as a raw packet and formatted into ICMP ECHO REQUEST. The problem with creating a raw socket requires root privilege. It is alright if the program is running as part of the system service under root anyway. However, running as a non privilege user, the program requires extra care by configuring the setuid bit which poses security risks e.g. the program may have memory leak which can be hijacked with shellcode.

Fortunately, there is a proper way to issue ICMP request for non privilege use, by creating a UDP socket:


This avoids escalating to root privilege. Here is a link to my ping demo code in C which sends the ICMP ECHO request as UDP and shows the identifier value in request and reply.

Make sure you have configured the group permission for creating ping sockets, otherwise you will get “Permission denied” error message in socket system call. To grant the permission, issues a sysctl command to set the kernel state. Below is an example granting to all user groups.

sysctl -w net.ipv4.ping_group_range="0   65536"

One interesting observation of ICMP as UDP packet is the behaviour of identifier field on Linux. In general, identifier is assigned as the PID value for matching against the same field in ECHO REPLY. This is necessary when multiple pings are running and looking for the correct ECHO REPLY. Since it is in UDP, this is not necessary the case anymore. In fact, the kernel will change the identifier to store for the local port. See this, and this.

Compiles the ping_demo program and runs in on Ubuntu, here is the result:

itrinegy@neone-devel:~$ ./pingdemo
Sent ICMP ECHO (ident : 6789) to
Recieved ICMP REPLY - id: 6

As we can see, the ICMP ECHO request is sent with a hardcoded identifier, 6789, value, whereas the ICMP REPLY comes back with a different value. If we use tcpdump, we can see the identifier in ICMP ECHO REQUEST have been converted to 6 instead of 6789.

itrinegy@neone-devel:~$ sudo tcpdump icmp -vvv
tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
21:14:33.593357 IP (tos 0x0, ttl 64, id 28437, offset 0, flags [DF], proto ICMP (1), length 33) > ICMP echo request, id 6, seq 1, length 13
21:14:33.597027 IP (tos 0x0, ttl 55, id 0, offset 0, flags [none], proto ICMP (1), length 33) > ICMP echo reply, id 6, seq 1, length 13

Since Android is derived from Linux, it has the exact same behaviour in UDP ping.

As for OSX, the network layer is very much based on FreeBSD. The behaviour is different, the identifier value is maintained throughout the ping.

Joe-New-MBP:ping_demo Joe$ ./pingdemo
Sent ICMP ECHO (ident : 6789) to
Recieved ICMP REPLY - id: 6789



Read more from C, Mac OS X, Networking, Ubuntu
1 Comment Post a comment
  1. Brett Wooldridge
    Oct 12 2017

    Thank you, btw. I thought I was loosing my mind. Ported some code that relied on the identifier I set coming back, and on Linux it was different. Also interesting to note that IPv6 is not supported on Linux for user-space DGRAM/ICMP.


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )


Connecting to %s

Note: HTML is allowed. Your email address will never be published.

Subscribe to comments

%d bloggers like this: