in bpf/profiling/network/netmonitor.c [51:156]
static __always_inline void submit_new_connection(struct pt_regs* ctx, __u32 func_name, __u32 tgid, __u32 fd, __u64 start_nacs,
struct sockaddr* addr, const struct socket* socket) {
__u64 curr_nacs = bpf_ktime_get_ns();
// active connection save
struct active_connection_t con = {};
con.pid = tgid;
con.sockfd = fd;
// generate random id to keep current connection is unique
con.random_id = bpf_get_prandom_u32();
if (func_name == SOCKET_OPTS_TYPE_CONNECT) {
con.role = CONNECTION_ROLE_TYPE_CLIENT;
} else if (func_name == SOCKET_OPTS_TYPE_ACCEPT) {
con.role = CONNECTION_ROLE_TYPE_SERVER;
} else {
con.role = CONNECTION_ROLE_TYPE_UNKNOWN;
}
__u16 port;
__u32 need_complete_addr = 1;
if (socket != NULL) {
need_complete_addr = 0;
// only get from accept function(server side)
struct sock* s;
BPF_CORE_READ_INTO(&s, socket, sk);
short unsigned int skc_family;
BPF_CORE_READ_INTO(&skc_family, s, __sk_common.skc_family);
con.socket_family = skc_family;
if (con.socket_family == AF_INET) {
BPF_CORE_READ_INTO(&port, s, __sk_common.skc_num);
con.local_port = port;
BPF_CORE_READ_INTO(&con.local_addr_v4, s, __sk_common.skc_rcv_saddr);
BPF_CORE_READ_INTO(&port, s, __sk_common.skc_dport);
con.remote_port = bpf_ntohs(port);
BPF_CORE_READ_INTO(&con.remote_addr_v4, s, __sk_common.skc_daddr);
} else if (con.socket_family == AF_INET6) {
BPF_CORE_READ_INTO(&port, s, __sk_common.skc_num);
con.local_port = port;
BPF_CORE_READ_INTO(&con.local_addr_v6, s, __sk_common.skc_v6_rcv_saddr.in6_u.u6_addr8);
BPF_CORE_READ_INTO(&port, s, __sk_common.skc_dport);
con.remote_port = bpf_ntohs(port);
BPF_CORE_READ_INTO(&con.remote_addr_v6, s, __sk_common.skc_v6_daddr.in6_u.u6_addr8);
}
} else if (addr != NULL) {
con.socket_family = _(addr->sa_family);
if (con.socket_family == AF_INET) {
struct sockaddr_in *daddr = (struct sockaddr_in *)addr;
bpf_probe_read(&con.remote_addr_v4, sizeof(con.remote_addr_v4), &daddr->sin_addr.s_addr);
bpf_probe_read(&port, sizeof(port), &daddr->sin_port);
con.remote_port = bpf_ntohs(port);
} else if (con.socket_family == AF_INET6) {
struct sockaddr_in6 *daddr = (struct sockaddr_in6 *)addr;
bpf_probe_read(&con.remote_addr_v6, sizeof(con.remote_addr_v6), &daddr->sin6_addr.s6_addr);
bpf_probe_read(&port, sizeof(port), &daddr->sin6_port);
con.remote_port = bpf_ntohs(port);
}
} else {
con.socket_family = AF_UNKNOWN;
}
// save to the active connection map
__u64 conid = gen_tgid_fd(tgid, fd);
struct socket_connect_event_t *event = create_socket_connect_event();
// only trace ipv4, v6, or unknown
// pid is not contains(monitored)
// cannot create connect event object
if (family_should_trace(con.socket_family) == false || tgid_should_trace(tgid) == false || !event) {
con.connect_event_send = false;
bpf_map_update_elem(&active_connection_map, &conid, &con, 0);
return;
}
// default setting as sent
con.connect_event_send = true;
bpf_map_update_elem(&active_connection_map, &conid, &con, 0);
// send to user-space that have connection activated
event->conid = conid;
event->random_id = con.random_id;
event->func_name = func_name;
if (con.role != CONNECTION_ROLE_TYPE_UNKNOWN) {
event->exe_time = curr_nacs - start_nacs;
}
event->pid = tgid;
event->sockfd = fd;
// fill the connection
event->role = con.role;
event->socket_family = con.socket_family;
event->need_complete_addr = need_complete_addr;
event->local_addr_v4 = con.local_addr_v4;
__builtin_memcpy(&event->local_addr_v6, &con.local_addr_v4, 16*sizeof(__u8));
event->local_port = con.local_port;
event->remote_addr_v4 = con.remote_addr_v4;
__builtin_memcpy(&event->remote_addr_v6, &con.remote_addr_v6, 16*sizeof(__u8));
event->remote_port = con.remote_port;
__u32 ret = bpf_perf_event_output(ctx, &socket_connection_event_queue, BPF_F_CURRENT_CPU, event, sizeof(*event));
// if not send event success, then update to the event not sent
if (ret < 0) {
struct active_connection_t *con = bpf_map_lookup_elem(&active_connection_map, &conid);
if (con != NULL) {
con->connect_event_send = false;
bpf_map_update_elem(&active_connection_map, &conid, con, 0);
}
}
}