Stateful eBPF

Tracking network connections

Like open() and read(), network connections have both an attempt (entry) and a result (exit). To correlate these events, we store data at entry and retrieve it at exit.

The connect syscall

int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

At entry (sys_enter_connect):

  • ctx->args[0] = socket file descriptor
  • ctx->args[1] = pointer to sockaddr structure (user space)

At exit (sys_exit_connect):

  • ctx->ret == 0 → Connection succeeded
  • ctx->ret < 0 → Connection failed (errno value)

Reading the sockaddr structure

The addr pointer at ctx->args[1] points to user space memory. You must use bpf_probe_read_user() to safely copy it:

struct sockaddr_in addr;
bpf_probe_read_user(&addr, sizeof(addr), (void *)ctx->args[1]);

For IPv4 connections (sin_family == 2):

struct sockaddr_in {
    u16 sin_family;  // AF_INET = 2
    u16 sin_port;    // Port (network byte order!)
    u32 sin_addr;    // IP address
    char __pad[8];
};

Port and IP are in network byte order (big-endian). Convert to host order with the helper:

u16 port = bpf_ntohs(addr.sin_port);

The challenge

A program attempts to connect to multiple ports. Most connections fail, but one succeeds. Submit the port of the connection that succeeds.

Your task:

  1. At connect entry: Read the sockaddr_in structure and store the port in a temporary map
  2. At connect exit: Check if the connection succeeded (ret == 0), then submit the port

The starter code has the structure you need to follow.

Quick reference
Insert or update map entry
Function bpf_map_update_elem Full documentation
Args:
void* mappointer to map
const void* keypointer to key
const void* valuepointer to value
u64 flagsBPF_ANY (create or update), BPF_NOEXIST (create only), or BPF_EXIST (update only)
On success, returns 0
On error, returns negative error code
Get value from map by key
Function bpf_map_lookup_elem Full documentation
Args:
void* mappointer to map
const void* keypointer to key
Returns pointer to value if found, NULL otherwise
Remove entry from map
Function bpf_map_delete_elem Full documentation
Args:
void* mappointer to map
const void* keypointer to key to delete
On success, returns 0
On error, returns negative error code if key not found
Run your code to see execution events here