IP โ The Post Office of the Internet
IP (Internet Protocol) is the most fundamental protocol of the internet. It provides one service: take a chunk of data and deliver it from a source address to a destination address. It does this without establishing a connection, without guarantees, and without caring about order.
Think of IP like a postal service that will try to deliver your letter โ but may lose it, deliver it late, or even deliver it twice. For simple tasks that is fine. For important tasks, you need TCP (registered mail with receipt).
No handshake before sending. Each datagram is independent. Two packets from the same stream can take completely different routes.
IP does not guarantee delivery. Packets can be lost, reordered, or duplicated. No retransmission. No acknowledgment.
Uses IP addresses to identify source and destination hosts. Routers read these addresses to forward packets toward the destination.
If a packet is too large for a network link (exceeds MTU), IP splits it into smaller fragments. The receiver reassembles them.
An IPv4 datagram has a header (minimum 20 bytes) followed by the payload (data from transport layer).
| IPv4 Header (20 bytes minimum) | |||
|---|---|---|---|
| Version (4 bits) = 4 |
IHL (4 bits) Header length |
DSCP / ToS (8 bits) QoS / priority |
Total Length (16 bits) header + data |
| Identification (16 bits) fragment group ID |
Flags (3 bits) DF, MF |
Fragment Offset (13 bits) | |
| TTL (8 bits) hop limit |
Protocol (8 bits) 6=TCP, 17=UDP |
Header Checksum (16 bits) | |
| Source IP Address (32 bits) | |||
| Destination IP Address (32 bits) | |||
| Options (variable, if IHL > 5) + Payload / Data | |||
โข Protocol: Tells IP what is inside โ 6 = TCP, 17 = UDP, 1 = ICMP
โข TTL: Decremented at each router. Drop when = 0.
โข DF flag (Don’t Fragment): If set, router must drop and send ICMP error instead of fragmenting.
โข MF flag (More Fragments): Set on all fragments except the last one.
IPv4 uses a 32-bit address โ written as 4 decimal numbers separated by dots (dotted-decimal notation). This gives a theoretical maximum of 2ยณยฒ = ~4.3 billion unique addresses.
192.168.1.100
Each group = 1 byte (0โ255)
4 groups ร 8 bits = 32 bits total
192.168.1.100/24
/24 = 24 bits for network
8 bits for host (256 hosts)
127.0.0.1 = loopback
0.0.0.0 = any/unspecified
255.255.255.255 = broadcast
| Range | CIDR Notation | Common Use |
|---|---|---|
| 10.0.0.0 โ 10.255.255.255 | 10.0.0.0/8 | Private (large networks) |
| 172.16.0.0 โ 172.31.255.255 | 172.16.0.0/12 | Private (medium networks) |
| 192.168.0.0 โ 192.168.255.255 | 192.168.0.0/16 | Private (home/office) |
| 127.0.0.0 โ 127.255.255.255 | 127.0.0.0/8 | Loopback (local testing) |
IPv4 was running out of addresses by the 1990s. IPv6 was designed in 1995โ1998 to solve this. The key change: address size grew from 32 bits โ 128 bits.
192.168.1.100Max ~4.3 billion addresses ๐ฌ
2001:0db8:85a3:0000:0000:8a2e:0370:7334Max 3.4 ร 10ยณโธ addresses ๐
โข Larger addresses โ no more address exhaustion
โข Simpler header โ fixed 40 bytes (no options, no checksum in header)
โข No fragmentation at routers โ only the sender can fragment
โข Built-in security (IPsec support)
โข Better multicast support (replaces broadcast)
โข Auto-configuration (SLAAC) โ no DHCP needed
โข Flow labels for QoS
::1 = loopback (equivalent of 127.0.0.1):: = unspecified (equivalent of 0.0.0.0)fe80::/10 = link-local (auto-assigned on network interface)2001::/32 = Teredo (IPv6 tunneled over IPv4)Linux provides functions to convert between human-readable IP strings and binary format.
#include <stdio.h>
#include <arpa/inet.h> /* inet_pton(), inet_ntop() */
int main(void) {
/* ---------- IPv4 ---------- */
struct in_addr ipv4_addr;
/* Convert string "192.168.1.100" โ binary (network byte order) */
if (inet_pton(AF_INET, "192.168.1.100", &ipv4_addr) != 1) {
perror("inet_pton IPv4 failed");
return 1;
}
printf("IPv4 binary (hex): 0x%08X\n", ntohl(ipv4_addr.s_addr));
/* Convert binary โ string */
char str4[INET_ADDRSTRLEN]; /* INET_ADDRSTRLEN = 16 */
inet_ntop(AF_INET, &ipv4_addr, str4, sizeof(str4));
printf("IPv4 string: %s\n", str4); /* "192.168.1.100" */
/* ---------- IPv6 ---------- */
struct in6_addr ipv6_addr;
if (inet_pton(AF_INET6, "2001:db8::1", &ipv6_addr) != 1) {
perror("inet_pton IPv6 failed");
return 1;
}
char str6[INET6_ADDRSTRLEN]; /* INET6_ADDRSTRLEN = 46 */
inet_ntop(AF_INET6, &ipv6_addr, str6, sizeof(str6));
printf("IPv6 string: %s\n", str6); /* "2001:db8::1" */
return 0;
}
/* Compile and run: */
/* gcc -o ip_addr ip_addr.c && ./ip_addr */
/* Output:
IPv4 binary (hex): 0xC0A80164
IPv4 string: 192.168.1.100
IPv6 string: 2001:db8::1
*/
โข
inet_pton() = “presentation to network” โ string โ binaryโข
inet_ntop() = “network to presentation” โ binary โ stringโข These replace the older
inet_aton() and inet_ntoa() which were IPv4-only.โข AF_INET = IPv4 family, AF_INET6 = IPv6 family
Every network link has a maximum frame size called MTU (Maximum Transmission Unit). Ethernet’s MTU is 1500 bytes. If an IP datagram is larger than the MTU of a link it needs to cross, it must be fragmented โ broken into smaller pieces.
1480 bytes data
offset=0, MF=1
1480 bytes data
offset=185, MF=1
40 bytes data
offset=370, MF=0
A: IPv4 uses 32-bit addresses (dotted decimal), IPv6 uses 128-bit addresses (colon hex). IPv4 supports ~4.3B addresses; IPv6 supports 3.4ร10ยณโธ. IPv6 has a simpler, fixed-length 40-byte header with no checksum (offloaded to transport layer), no fragmentation at routers, built-in IPsec support, better multicast, and stateless auto-configuration (SLAAC).
A: MTU (Maximum Transmission Unit) is the largest frame a link layer can carry. Ethernet MTU = 1500 bytes. If an IP datagram exceeds the MTU of a link, it must be fragmented. Fragmentation is inefficient โ if one fragment is lost, the entire datagram must be retransmitted. TCP uses Path MTU Discovery to avoid fragmentation by never sending segments larger than the smallest MTU on the path.
A: The Protocol field (8 bits) tells the receiving IP layer what protocol is in the payload: 6 = TCP, 17 = UDP, 1 = ICMP. This is called a demultiplexing key โ when IP receives a datagram, it reads this field and hands the payload to the correct transport-layer handler.
A: 127.0.0.1 (IPv4) or ::1 (IPv6). It is a virtual network interface that routes traffic back to the same machine without going to the physical network card. Used for testing (client and server on same machine), inter-process communication over sockets, and by many system services that only need local access (e.g., database listening on 127.0.0.1). Packets to 127.x.x.x never leave the host.
A: inet_pton() converts an IP address from human-readable string (presentation) to binary network byte order. You use it when you have an IP address as a string (e.g., from user input or config file) and need to store it in a sockaddr_in or in_addr struct for socket calls. It supports both IPv4 (AF_INET) and IPv6 (AF_INET6), unlike the older inet_aton().
