blob: 82d3e62f43e523da47ff809a0809c9eaf94efd9c [file] [log] [blame] [edit]
// Copyright 2024 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// bpf_helpers.h uses types defined here
#include "include/vm_tools/port_listener/vmlinux/vmlinux.h"
#include <bpf/bpf_helpers.h>
#include "vm_tools/port_listener/common.h"
// For some reason 6.1 doesn't include these symbols in the debug build
// so they don't get included in vmlinux.h. These features have existed since
// well before 6.1.
#define BPF_F_NO_PREALLOC (1U << 0)
#define BPF_ANY 0
struct {
__uint(type, BPF_MAP_TYPE_RINGBUF);
__uint(max_entries, 1 << 24);
} events SEC(".maps");
struct {
__uint(type, BPF_MAP_TYPE_HASH);
__type(key, struct sock*);
__type(value, __u8);
__uint(max_entries, 65535);
__uint(map_flags, BPF_F_NO_PREALLOC);
} sockmap SEC(".maps");
const __u8 set_value = 0;
SEC("tp/sock/inet_sock_set_state")
int tracepoint_inet_sock_set_state(
struct trace_event_raw_inet_sock_set_state* ctx) {
// We don't support anything other than TCP.
if (ctx->protocol != IPPROTO_TCP) {
return 0;
}
struct sock* sk = (struct sock*)ctx->skaddr;
// If we're transitioning away from LISTEN but we don't know about this
// socket yet then don't report anything.
if (ctx->oldstate == BPF_TCP_LISTEN &&
bpf_map_lookup_elem(&sockmap, &sk) == NULL) {
return 0;
}
// If we aren't transitioning to or from TCP_LISTEN then we don't care.
if (ctx->newstate != BPF_TCP_LISTEN && ctx->oldstate != BPF_TCP_LISTEN) {
return 0;
}
struct event* ev;
ev = bpf_ringbuf_reserve(&events, sizeof(*ev), 0);
if (!ev) {
return 0;
}
ev->port = ctx->sport;
if (ctx->newstate == BPF_TCP_LISTEN) {
bpf_map_update_elem(&sockmap, &sk, &set_value, BPF_ANY);
ev->state = kPortListenerUp;
}
if (ctx->oldstate == BPF_TCP_LISTEN) {
bpf_map_delete_elem(&sockmap, &sk);
ev->state = kPortListenerDown;
}
bpf_ringbuf_submit(ev, 0);
return 0;
}