static __always_inline void process_write_data()

in bpf/accesslog/syscalls/transfer.h [74:197]


static __always_inline void process_write_data(void *ctx, __u64 id, struct sock_data_args_t *args, ssize_t bytes_count,
                                        __u32 data_direction, const bool vecs, __u8 func_name, bool ssl) {
    __u64 curr_nacs = bpf_ktime_get_ns();
    __u32 tgid = (__u32)(id >> 32);

    if (vecs && args->iovlen <= 0) {
        return;
    }
    if (args->fd < 0) {
        return;
    }
    if (bytes_count <= 0) {
        return;
    }

    // get current connection
    struct active_connection_t *conn = get_or_create_active_conn(ctx, tgid, args->fd, func_name, args->sk_role);
    if (conn == NULL) {
        return;
    }
    // only trace ipv4, v6, or unknown
    if (family_should_trace(conn->socket_family) == false) {
        return;
    }
    // process the ssl request if the fd not found
    struct sock_data_args_t *ssl_data_args = bpf_map_lookup_elem(&openssl_sock_data_args, &id);
    if (ssl_data_args != NULL && ssl_data_args->fd == 0) {
        ssl_data_args->fd = args->fd;
        conn->ssl = true;
    } else if (ssl) {
        conn->ssl = true;
    }

    // if the cannot getting the package size and count, then try to get it from the data args
    if (args->total_package_size == 0 && args->package_count == 0) {
        args->total_package_size = bytes_count;
        args->package_count = 1;
    }

    // if the protocol or role is unknown in the connection and the current data content is plaintext
    // then try to use protocol analyzer to analyze request or response and protocol type
    __u32 msg_type = 0;
    if ((conn->role == CONNECTION_ROLE_TYPE_UNKNOWN || conn->protocol == 0) && conn->ssl == ssl) {
        struct socket_buffer_reader_t *buf_reader = read_socket_data(args->buf, args->iovec, bytes_count);
        if (buf_reader != NULL) {
            msg_type = analyze_protocol(buf_reader->buffer, buf_reader->data_len, &conn->protocol);
            // if send request data to remote address or receive response data from remote address
            // then, recognized current connection is client
            if ((msg_type == CONNECTION_MESSAGE_TYPE_REQUEST && data_direction == SOCK_DATA_DIRECTION_EGRESS) ||
                (msg_type == CONNECTION_MESSAGE_TYPE_RESPONSE && data_direction == SOCK_DATA_DIRECTION_INGRESS)) {
                conn->role = CONNECTION_ROLE_TYPE_CLIENT;

            // if send response data to remote address or receive request data from remote address
            // then, recognized current connection is server
            } else if ((msg_type == CONNECTION_MESSAGE_TYPE_RESPONSE && data_direction == SOCK_DATA_DIRECTION_EGRESS) ||
                       (msg_type == CONNECTION_MESSAGE_TYPE_REQUEST && data_direction == SOCK_DATA_DIRECTION_INGRESS)) {
                conn->role = CONNECTION_ROLE_TYPE_SERVER;
            }
        }
    }

    __u64 conid = gen_tgid_fd(tgid, args->fd);
    // upload the socket detail, detail can only be send when the ssl are same:
    // 1. when the SSL connection sends SSL(unencrypted) message
    // 2. when the not SSL connection sends plain data
    if (conn->ssl == ssl) {
        struct socket_detail_t *detail;
        detail = rover_reserve_buf(&socket_detail_queue, sizeof(*detail));
        if (detail != NULL) {
            detail->connection_id = conid;
            detail->random_id = conn->random_id;
            detail->data_id = args->data_id;

            detail->start_nacs = args->start_nacs;
            detail->end_nacs = curr_nacs;

            detail->l4_duration = args->exit_l4_time - args->enter_l4_time;
            detail->l3_duration = args->l3_duration;
            detail->l3_local_duration = args->l3_local_duration;
            detail->l3_output_duration = args->l3_output_duration;
            detail->l3_resolve_mac_duration = args->total_resolve_mac_time;
            detail->l3_net_filter_duration = args->total_net_filter_time;
            detail->l2_duration = args->l2_duration;
            detail->l2_ready_send_duration = args->l2_ready_send_duration;
            detail->l2_send_duration = args->l2_send_duration;
            detail->ifindex = args->ifindex;
            detail->l4_total_package_size = args->total_package_size;
            detail->l4_package_count = args->package_count;
            detail->l4_retransmit_package_count = args->retransmit_package_count;
            detail->l3_resolve_mac_count = args->total_resolve_mac_count;
            detail->l3_net_filter_count = args->total_net_filter_count;
            detail->op_func_name = func_name;
            detail->data_protocol = conn->protocol;
            detail->ssl = conn->ssl;
            detail->l2_package_to_queue_time = args->total_package_to_queue_time;
            detail->l3_total_recv_time = args->l3_rcv_duration;
            detail->l2_enter_queue_count = args->l2_enter_queue_count;
            detail->l4_package_rcv_from_queue_time = args->total_package_receive_from_queue_time;

            rover_submit_buf(ctx, &socket_detail_queue, detail, sizeof(*detail));
        }
    }

    // upload the socket data if need
    struct upload_data_args *upload_data_args = generate_socket_upload_args();
    if (upload_data_args != NULL) {
        upload_data_args->start_time = args->start_nacs;
        upload_data_args->end_time = curr_nacs;
        upload_data_args->con_id = conid;
        upload_data_args->random_id = conn->random_id;
        upload_data_args->socket_data_id = args->data_id;
        upload_data_args->socket_data_iovec = args->iovec;
        upload_data_args->socket_data_iovlen = args->iovlen;
        upload_data_args->bytes_count = bytes_count;
        upload_data_args->socket_data_buf = args->buf;
        upload_data_args->data_direction = data_direction;
        upload_data_args->connection_protocol = conn->protocol;
        upload_data_args->connection_ssl = conn->ssl;
        upload_data_args->socket_ssl_buffer_force_unfinished = args->ssl_buffer_force_unfinished;
        upload_data_args->connection_skip_data_upload = conn->skip_data_upload;
        upload_data_args->socket_data_ssl = ssl;
        upload_socket_data(ctx, upload_data_args);
    };
}