Sending ICMP with C


I am familiar with Layer 4 of the OSI model, the transport layer, which uses TCP or UDP. I also wanted to explore Layer 3, the Network Layer. Since I am already comfortable with bits and bytes because I have created an emulator and explored irPDA (Bluetooth OBEX) used by mobile phones for file transfer, I felt confident I could handle it.

First, I needed the packet specification to send. I looked it up on Wikipedia and found an article on ICMP. Like IP, ICMP has both v4 and v6 versions and also has a specification in RFC 792.

After obtaining the specification, I created a struct:

struct icmp_hdr
{
    uint8_t type;
    uint8_t code;
    uint16_t checksum;
    uint16_t id;
    uint16_t sequence;
};

Next, I created a socket, defined the destination, and got the process ID:

int
main(void)
/* ...................... */
    sock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
    if(sock < 0){
        perror("SOCK");
        return -1;
    }

    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr = inet_addr(TARGET_IP);

    pid = getpid() & 0xFFFF;
/* ...................... */

Then, I started filling the ICMP struct. Since the ICMP packet size is 64 bytes, I created a 64-byte buffer and placed the ICMP header there:

/* ...................... */
#define CTL_MSG 8
/* ...................... */
for(int i; i < 1; i++){
/* ...................... */
    memset(sendbuf, 0, sizeof sendbuf);
    icmp = (struct icmp_hdr *)sendbuf;
    icmp->type     = CTL_MSG;
    icmp->code     = 0;
    icmp->id       = htons((uint16_t)pid);
    icmp->sequence = htons((uint16_t)i);
    icmp->checksum = 0;
    icmp->checksum = checksum(sendbuf, sizeof sendbuf);
/* ...................... */

After that, I sent the packet and received the response. I can also verify if the response is correct, which should be an Echo Response (type 0):

    if(icmp->type == 0 && ntohs(icmp->id) == (unsigned short)pid)
            printf("reply: %u\n", ntohs(icmp->sequence));

I can also verify using tcpdump:

tcpdump -n icmp

BTW, need root to run it.