static __always_inline void submit_new_connection()

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);
        }
    }
}