networking · beginner · ~12 min · safe pentest lab

Open a listening TCP socket on localhost

Bind a TCP socket to loopback, set SO_REUSEADDR, and put it in listen mode.

Challenge

Every TCP server begins with the same four-call sequence: socket → setsockopt → bind → listen. Wrap that sequence into one helper that returns a ready-to-accept listening socket on loopback.

Task

Implement int open_listener(int port) that creates a TCP socket, binds it to 127.0.0.1:port, and puts it in listen mode.

The function must:

  1. Create a TCP socket (AF_INET, SOCK_STREAM).
  2. Set SO_REUSEADDR (before bind) so a quick restart does not fail with EADDRINUSE.
  3. Bind to 127.0.0.1:port.
  4. Call listen(fd, 16).
  5. Return the listening file descriptor, or -1 on any failure.

Input

One int port. Pass port = 0 to let the kernel pick a free ephemeral port (the harness does this to avoid collisions).

Output

Returns a non-negative listening file descriptor on success, or -1 if any step fails.

Example

open_listener(0)   ->   fd >= 0, bound to 127.0.0.1 on a kernel-chosen port

Edge cases

  • port = 0: the kernel assigns a free port (check it with getsockname).
  • A privileged port (< 1024) without root fails to bind: return -1.
  • Close the fd on every error path so sockets are not leaked.

Rules

  • Bind to INADDR_LOOPBACK (127.0.0.1), never INADDR_ANY — traffic must never leave the machine.
  • Set SO_REUSEADDR before bind.

Why this matters

One helper, used by every TCP server you'll ever write. Master the four-call prologue once and you stop fumbling it.

Input format

One integer port. 0 means 'let the kernel pick a free port'.

Output format

A non-negative listening fd on success, -1 on any failure.

Constraints

Bind to INADDR_LOOPBACK only (never INADDR_ANY). Set SO_REUSEADDR before bind. Close the fd on every error path.

Starter code

#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <string.h>
int open_listener(int port) {
    /* TODO */
    return -1;
}

Common mistakes

Forgetting SO_REUSEADDR. Using INADDR_ANY (breaks the loopback-only rule). Missing htons/htonl.

Edge cases to handle

port=0 (kernel picks). port<1024 without root (EACCES). port already taken (EADDRINUSE).

Background lessons

Up next

Solve this exercise in the browser editor — compile and run against the test harness, no setup required.