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 descriptorctx->args[1]= pointer tosockaddrstructure (user space)
At exit (sys_exit_connect):
ctx->ret == 0→ Connection succeededctx->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:
- At
connectentry: Read thesockaddr_instructure and store the port in a temporary map - At
connectexit: 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 mapconst void* keypointer to keyconst void* valuepointer to valueu64 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 mapconst void* keypointer to key
Remove entry from map
Function bpf_map_delete_elem Full documentation
- Args:
void* mappointer to mapconst void* keypointer to key to delete
On success, returns 0
On error, returns negative error code if key not found