networking · beginner · ~12 min · safe pentest lab
Bind a TCP socket to loopback, set SO_REUSEADDR, and put it in listen mode.
Every TCP server starts with the same four-call dance: socket → setsockopt → bind → listen. After that, the socket is ready to accept connections. Your job is to wrap that dance into one helper.
This is the prologue every server program executes — nginx, sshd, your own toy chat server, all of them. Done once, used everywhere.
Implement:
int open_listener(int port);
It should:
AF_INET, SOCK_STREAM).SO_REUSEADDR so a quick restart doesn't fail with EADDRINUSE.127.0.0.1:port.listen(fd, 16).-1 on any failure.Pass port = 0 to let the kernel pick an unused ephemeral port. The harness uses this to avoid colliding with other ports.
int open_listener(int port);
INADDR_LOOPBACK (127.0.0.1) — never INADDR_ANY. This is the platform's safety rule: traffic never leaves the machine.| port | what happens | returns |
|---|---|---|
| 8080 (and nothing else is on it) | binds + listens | new fd (>=0) |
| 0 | kernel picks free port | new fd; check with getsockname |
| privileged port like 22 without root | bind fails with EACCES | -1 |
EADDRINUSE on rapid relaunch → set SO_REUSEADDR before bind.EACCES on ports < 1024 → use a high port (8080+) for labs.socket() first, then setsockopt(..., SO_REUSEADDR, ...), then memset a sockaddr_in and fill family + port (htons) + addr (htonl(INADDR_LOOPBACK)), then bind, then listen.htons on the port. Without it the kernel binds to a weird port number (the bytes are swapped on little-endian CPUs).SO_REUSEADDR. Your test rerun fails with EADDRINUSE.INADDR_ANY. The lab policy is loopback only.After this you'll connect from a client (tcp-client-connect), accept (echo-server), and eventually thread-per-connection (multi-client-server-threads).
The harness verifies the bound address is 127.0.0.1. Submissions that bind to INADDR_ANY will fail the loopback check. This exercise is for defensive learning in a local lab only. Do not run it on systems you do not own.
One helper, used by every TCP server you'll ever write. Master the four-call prologue once and you stop fumbling it.
One integer port. 0 means 'let the kernel pick'.
A non-negative fd on success, -1 on any failure.
Loopback only (INADDR_LOOPBACK). SO_REUSEADDR must be set before bind.
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <string.h>
int open_listener(int port) {
/* TODO */
return -1;
}
Forgetting SO_REUSEADDR. Using INADDR_ANY (breaks the loopback-only rule). Missing htons/htonl.
port=0 (kernel picks). port<1024 without root (EACCES). port already taken (EADDRINUSE).
Solve this exercise in the browser editor — compile and run against the test harness, no setup required.