I'm interested in filtering ICMP packets. More precisely I open a raw socket
int sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)
and I'm interested to send PING_ECHO
and to receive PING_ECHOREPLY
packets.
I'm using respectively sendto
and recvfrom
function. So far, so good.
I would like to filter the received icmp packets using setsockopt
with ICMP_FILTER
option, which can be find in man raw
. However they are a bit cryptic to me:
ICMP_FILTER
Enable a special filter for raw sockets bound to the IPPROTO_ICMP protocol. The value has a bit set for each ICMP message type which should be filtered out. The default is to filter no ICMP messages.
How can I set these bits safely? I cannot find documentation online. Looking around I've found that there is a struct icmp_filter
defined in linux/icmp.h
header.
However I do not know if it is the correct header to include.
icmp.h
is indeed the correct header. You can examine the source code of icmp.h
for this stuff:
#define ICMP_ECHOREPLY 0 /* Echo Reply */
#define ICMP_DEST_UNREACH 3 /* Destination Unreachable */
#define ICMP_SOURCE_QUENCH 4 /* Source Quench */
#define ICMP_REDIRECT 5 /* Redirect (change route) */
#define ICMP_ECHO 8 /* Echo Request */
#define ICMP_TIME_EXCEEDED 11 /* Time Exceeded */
#define ICMP_PARAMETERPROB 12 /* Parameter Problem */
#define ICMP_TIMESTAMP 13 /* Timestamp Request */
#define ICMP_TIMESTAMPREPLY 14 /* Timestamp Reply */
#define ICMP_INFO_REQUEST 15 /* Information Request */
#define ICMP_INFO_REPLY 16 /* Information Reply */
#define ICMP_ADDRESS 17 /* Address Mask Request */
#define ICMP_ADDRESSREPLY 18 /* Address Mask Reply */
These are the bit definitions (it says so explicitly in man icmp
), so you need to set the corresponding bit for the option you want, usually using a shift, using |
to or multiple bits together. You define your filter object, then set the data field
struct icmp_filter my_filter = {
1U << ICMP_ECHO |
1U << ICMP_TIME_EXCEEDED ...
};
etc, and pass it to the socket options using setsockopt
.