Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Re-coding the ping command will let you get acquainted with TCP/IP communication between two machines on a network

License

Notifications You must be signed in to change notification settings

kichkiro/ft_ping

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

2 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

This project is about recoding the ping command.

subject v.5.1

Project Structure πŸ“‚
.
β”œβ”€β”€ Dockerfile
β”œβ”€β”€ LICENSE
β”œβ”€β”€ README.md
β”œβ”€β”€ _subject
β”‚   └── en.subject.pdf
└── project
    β”œβ”€β”€ Makefile
    β”œβ”€β”€ ft_ping
    β”œβ”€β”€ include
    β”‚   └── ft_ping.h
    └── src
        β”œβ”€β”€ libft
        β”‚   β”œβ”€β”€ ft_free.c
        β”‚   β”œβ”€β”€ ft_int_len.c
        β”‚   β”œβ”€β”€ ft_str_realloc.c
        β”‚   └── ft_strf.c
        β”œβ”€β”€ logger.c
        β”œβ”€β”€ main.c
        β”œβ”€β”€ packets.c
        β”œβ”€β”€ parser.c
        β”œβ”€β”€ ping.c
        β”œβ”€β”€ socket.c
        └── verbose.c

πŸ“‘ Index

πŸ› οΈ Usage

After cloning the repository, you can opt to install it on a Debian-based system, or via Docker for greater portability.

[+] Debian-based OS

In this case you will need to make sure you have all the dependencies, or install the meta-packege build-essential, which already contains all the tools needed to compile the program:

apt-get install -y --no-install-recommends build-essential

and then:

cd ft_ping/project
make
./ft_ping [COMMAND] [OPTIONS]

[+] Docker

If you choose installation via Docker, you don't need anything other than Docker itself.

cd ft_ping/
docker build -t ft_ping .
docker run --rm ft_ping [COMMAND] [OPTIONS]

πŸ“Œ Key Topics

[+] PING (GNU inetutils v2.0)

This reimplementation of ping is inspired by the version of GNU inetutils v2.0, below is a brief introduction and installation guide for testing purposes.

The ping command sends ICMP ECHO_REQUEST packets to a host to check connectivity.

It is commonly used to:

  • Verify network status.
  • Diagnose connectivity issues.
  • Measure response times and packet loss.

Each request includes IP and ICMP headers plus timing data. By default, ping sends packets once per second until interrupted (Ctrl-C). It reports round-trip times, statistics, and a summary upon completion. The target can be a hostname or IP address.

Installing GNU inetutils 2.0 on Debian-based systems:

  1. Remove the default ping:

    apt remove iputils-ping
  2. Install build tools:

    apt update
    apt install build-essential wget
  3. Download version 2.0 sources:

    wget https://ftp.gnu.org/gnu/inetutils/inetutils-2.0.tar.gz
  4. Extract and compile:

    tar -xvf inetutils-2.0.tar.gz
    cd inetutils-2.0
    ./configure --prefix=/usr/local/inetutils-2.0
    make
    make install
  5. Use the specific binary:

    /usr/local/inetutils-2.0/bin/ping --version

    or create an alias:

    echo "alias ping='/usr/local/inetutils-2.0/bin/ping'" >> ~/.bashrc
    source ~/.bashrc

[+] RAW Sockets

This implementation uses raw sockets to craft and send fully custom ICMP packets, including the IPv4 header. Two separate sockets are created:

  • A raw IP socket socket(AF_INET, SOCK_RAW, IPPROTO_RAW) for sending packets with manually constructed IPv4 headers.

  • A raw ICMP socket socket(AF_INET, SOCK_RAW, IPPROTO_ICMP) for receiving ICMP Echo Replies and other ICMP messages.

With raw sockets and the IP_HDRINCL socket option enabled, the application takes full control over the entire packet structure:

  • The kernel does not generate the IPv4 header automatically. Instead, your program must manually construct the IPv4 header, specifying all fields (Version, Header Length, Total Length, Identification, TTL, Protocol, etc.).

  • You must also build the ICMP header yourself, setting the Type, Code, Identifier, Sequence Number, and computing the correct checksum.

  • A custom payload is appended to the ICMP packet, it includes a timestamp and arbitrary data for testing round-trip times and verifying packet integrity.

  • On reception, the program receives the full raw IP packet (including the IPv4 header), so it must parse the header manually to extract and validate the embedded ICMP Echo Reply.

Note:

  • Without IP_HDRINCL, the kernel would automatically fill in the IPv4 header based on your destination address and other defaults, and you would only need to provide the transport-layer payload (ICMP). With IP_HDRINCL, you get full control but also full responsibility.

  • Because raw sockets allow generating arbitrary network traffic, they require elevated privileges (root or CAP_NET_RAW capability).

[+] IPv4 Header

Each packet sent by this implementation contains a manually constructed IPv4 header.
Below is an overview of its fields:

Field Size (bits) Description
Version 4 IP protocol version. Always set to 4 for IPv4.
IHL 4 Internet Header Length in 32-bit words. Usually 5 (20 bytes).
Type of Service 8 Specifies priority and QoS.
Total Length 16 Full length of the packet (header + payload).
Identification 16 Unique identifier for fragmentation.
Flags 3 Control flags (e.g., Don't Fragment).
Fragment Offset 13 Offset of a fragment in the original datagram.
TTL 8 Time To Live, decremented by each router hop.
Protocol 8 Encapsulated protocol number (1 for ICMP).
Header Checksum 16 Checksum of the header. Calculated manually.
Source Address 32 IPv4 address of the sender.
Destination Address 32 IPv4 address of the recipient.

Note:

  • The IP_HDRINCL socket option requires the application to populate all fields and compute the header checksum.
  • The "Don't Fragment" flag is set to avoid fragmentation.
  • The source address can be set to INADDR_ANY, in which case the kernel fill in the actual address.

[+] ICMP

The Internet Control Message Protocol (ICMP) is part of the Internet protocol suite (RFC 792). It is used by network devices to send error messages and operational information, such as when a host is unreachable or a service is unavailable. Unlike TCP and UDP, ICMP is mainly for diagnostics (e.g., ping, traceroute) and error reporting (RFC 1122).

ICMP operates at Layer 3 (the Network Layer) of the OSI model, the same layer as IP.

- ICMP Header

Each ICMP message starts with a fixed header:

Field Size (bits) Description
Type 8 Specifies the ICMP message type (e.g., 0=Echo Reply, 8=Echo Request).
Code 8 Further refines the message type.
Checksum 16 Verifies the integrity of the ICMP header and payload.
Rest of Header 32 Depends on Type and Code. For Echo messages, contains Identifier and Sequence Number.

Echo Request/Reply additional fields:

Subfield Size (bits) Description
Identifier 16 Helps match requests to replies.
Sequence 16 Incremented with each request.

- ICMP Type

These message types define ICMP control and diagnostic functions as specified in RFC 792 and related updates.
Each Type identifies the high-level purpose of the message, while the Code field provides additional context. Below are common ICMP types:

Type Name Description
0 Echo Reply Reply to an Echo Request.
3 Destination Unreachable Packet could not be delivered.
5 Redirect Redirect routing (e.g., better gateway).
8 Echo Request Ping request.
9 Router Advertisement Router discovery messages.
10 Router Solicitation Request for router advertisement.
11 Time Exceeded TTL expired in transit.
12 Parameter Problem Invalid header field.
13 Timestamp Request Request timestamp.
14 Timestamp Reply Reply to timestamp request.

- ICMP Code

The meaning of the Code field depends on the Type.
Below are common codes for a few types:

Type Code Meaning
3 0 Network Unreachable
3 1 Host Unreachable
3 2 Protocol Unreachable
3 3 Port Unreachable
3 4 Fragmentation needed and DF set
3 5 Source Route Failed
11 0 TTL expired in transit
11 1 Fragment reassembly time exceeded

- ICMP Payload

The ICMP payload immediately follows the header.
For Echo Request and Echo Reply packets, it typically contains:

  • A timestamp (e.g., struct timeval) used to measure round-trip time (RTT).
  • Arbitrary data bytes (padding) to reach the desired packet size.

- ICMP Checksum

The checksum field covers the entire ICMP message, including both the header and the payload. It is calculated as the one's complement of the one's complement sum of all 16-bit words in the message.

If the total length of the message is odd, the final byte is padded with a zero byte before computing the checksum.

Formula: checksum = ~ (sum of all 16-bit words)

Note:
A valid checksum is required for the receiver to accept and process the ICMP packet. If the checksum is incorrect, the packet will be discarded.

[+] Packet Inspection

You can inspect the data both live during execution, using GDB and passively using Wireshark.

- GDB

When you receive a packet via recvfrom(), the buffer contains the entire raw IP packet, starting from the first byte of the IPv4 header (offset 0).

This means:

  • Offset 0–19: IPv4 header (fixed part, 20 bytes)
  • Offset 20–N: ICMP header and payload

Each field occupies specific offsets in the buffer, matching the protocol specification (RFC 791 for IPv4, RFC 792 for ICMP).

In the example below, we display the full packet ([IPv4 header] + [ICMP header] + [ICMP payload]), which by default is 84 bytes long:

(gdb) x/84bx rbuf 
0x55555555db00: 0x45    0x00    0x00    0x54    0x34    0x48    0x00    0x00
0x55555555db08: 0xfc    0x01    0x78    0x30    0x0a    0x00    0x00    0x01
0x55555555db10: 0xac    0x1e    0x5c    0x11    0x00    0x00    0x90    0x88
0x55555555db18: 0xe7    0xc3    0x00    0x00    0xee    0xea    0x66    0x68
0x55555555db20: 0x00    0x00    0x00    0x00    0xae    0xce    0x06    0x00
0x55555555db28: 0x00    0x00    0x00    0x00    0x00    0x01    0x02    0x03
0x55555555db30: 0x04    0x05    0x06    0x07    0x08    0x09    0x0a    0x0b
0x55555555db38: 0x0c    0x0d    0x0e    0x0f    0x10    0x11    0x12    0x13
0x55555555db40: 0x14    0x15    0x16    0x17    0x18    0x19    0x1a    0x1b
0x55555555db48: 0x1c    0x1d    0x1e    0x1f    0x20    0x21    0x22    0x23
0x55555555db50: 0x24    0x25    0x26    0x27

Knowing the offset of each field inside the IPv4 header, you can extract and print readable values.

For example the source IP address is located between byte 12 and byte 15 of the IPv4 header and destination between byte 16 and byte 19, you can print it as a human-readable string like this:

(gdb) printf "%d.%d.%d.%d\n", rbuf[12], rbuf[13], rbuf[14], rbuf[15]
10.0.0.1
(gdb) printf "%d.%d.%d.%d\n", rbuf[16], rbuf[17], rbuf[18], rbuf[19]
172.30.92.17

- Wireshark

Wireshark can capture and decode ICMP packets in real time.

It provides a detailed, human-readable view of each field in the IPv4 and ICMP headers, making it an essential tool to verify that raw packets are crafted correctly.

You can filter the traffic with some useful filters:

  • icmp – Show all ICMP packets (requests and replies).
  • icmp.type == 8 – Show only Echo Requests.
  • icmp.type == 0 – Show only Echo Replies.
  • ip.src == <your_ip> – Filter packets sent by your host.
  • ip.dst == <target_ip> – Filter packets sent to the target.

Below is an example of an ICMP Echo Request packet as dissected by Wireshark:

Internet Protocol Version 4, Src: 172.30.92.17, Dst: 10.0.0.1
    0100 .... = Version: 4
    .... 0101 = Header Length: 20 bytes (5)
    Differentiated Services Field: 0x00 (DSCP: CS0, ECN: Not-ECT)
    Total Length: 84
    Identification: 0xcecd (52941)
    010. .... = Flags: 0x2, Don't fragment
    ...0 0000 0000 0000 = Fragment Offset: 0
    Time to Live: 64
    Protocol: ICMP (1)
    Header Checksum: 0x59ab [validation disabled]
    [Header checksum status: Unverified]
    Source Address: 172.30.92.17
    Destination Address: 10.0.0.1
    [Stream index: 1]
Internet Control Message Protocol
    Type: 8 (Echo (ping) request)
    Code: 0
    Checksum: 0xb471 [correct]
    [Checksum Status: Good]
    Identifier (BE): 52941 (0xcecd)
    Identifier (LE): 52686 (0xcdce)
    Sequence Number (BE): 0 (0x0000)
    Sequence Number (LE): 0 (0x0000)
    [Response frame: 8]
    Timestamp from icmp data: Jul  3, 2025 22:23:51.516017000 W. Europe Daylight Time
    [Timestamp from icmp data (relative): -0.303915000 seconds]
    Data (40 bytes)
        Data: 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f2021222324252627
        [Length: 40]

Here is the same packet shown as a raw hex dump:

# IPv4 Header (20 bytes)
45 00 00 54 ce cd 40 00 40 01 59 ab ac 1e 5c 11
0a 00 00 01
# ICMP Header + Payload
08 00 b4 71 ce cd 00 00 d7 e6 66 68 00 00 00 00
b1 df 07 00 00 00 00 00 00 01 02 03 04 05 06 07
08 09 0a 0b 0c 0d 0e 0f 10 11 12 13 14 15 16 17
18 19 1a 1b 1c 1d 1e 1f 20 21 22 23 24 25 26 27

πŸ“š References

βš–οΈ License

See LICENSE

About

Re-coding the ping command will let you get acquainted with TCP/IP communication between two machines on a network

Topics

Resources

License

Stars

Watchers

Forks