int get_net_connections_from_proc_buf()

in source/linux/network.c [145:268]


int get_net_connections_from_proc_buf(
    struct aws_array_list *net_conns,
    struct aws_allocator *allocator,
    struct aws_byte_cursor *proc_net_data,
    const struct aws_iotdevice_network_ifconfig *ifconfig,
    enum aws_iotdevice_network_protocol protocol) {
    AWS_PRECONDITION(net_conns != NULL);
    AWS_PRECONDITION(allocator != NULL);
    AWS_PRECONDITION(ifconfig != NULL);
    AWS_PRECONDITION(aws_byte_cursor_is_valid(proc_net_data));

    int return_value = AWS_OP_SUCCESS;
    struct aws_array_list lines;
    AWS_ZERO_STRUCT(lines);

    aws_array_list_init_dynamic(&lines, allocator, 10, sizeof(struct aws_byte_cursor));
    aws_byte_cursor_split_on_char(proc_net_data, '\n', &lines);

    /* first line is header text info */
    aws_array_list_pop_front_n(&lines, 1);
    /* last line is empty */
    aws_array_list_pop_back(&lines);

    struct aws_byte_cursor line;
    struct aws_iotdevice_metric_net_connection *connection = NULL;
    while (AWS_OP_SUCCESS == aws_array_list_front(&lines, &line)) {
        aws_array_list_pop_front(&lines);

        char local_addr_h[9];
        char local_port_h[6];
        char remote_addr_h[9];
        char remote_port_h[6];
        char state_h[3];
        int tokens_read = sscanf(
            (const char *)line.ptr,
            "%*s %8s %*c %4s %8s %*c %4s %2s %*s",
            local_addr_h,
            local_port_h,
            remote_addr_h,
            remote_port_h,
            state_h);

        if (tokens_read != EXPECTED_NETWORK_CONFIG_TOKENS) {
            AWS_LOGF_WARN(AWS_LS_IOTDEVICE_NETWORK_CONFIG, "id=%p: Bad line in /proc/net/*** file", (void *)ifconfig);
            continue;
        }

        uint16_t state = strtol(state_h, NULL, 16);
        if (state == LINUX_NCS_ESTABLISHED || state == LINUX_NCS_LISTEN) {
            connection = aws_mem_calloc(allocator, 1, sizeof(struct aws_iotdevice_metric_net_connection));
            if (connection == NULL) {
                return_value = AWS_OP_ERR;
                AWS_LOGF_ERROR(
                    AWS_LS_IOTDEVICE_NETWORK_CONFIG,
                    "id=%p: Could not allocate memory for network connection",
                    (void *)ifconfig);
                goto cleanup;
            }

            AWS_ZERO_STRUCT(*connection);

            char local_addr[IPV4_ADDRESS_SIZE];
            char remote_addr[IPV4_ADDRESS_SIZE];
            s_hex_addr_to_ip_str(local_addr, IPV4_ADDRESS_SIZE, local_addr_h);
            s_hex_addr_to_ip_str(remote_addr, IPV4_ADDRESS_SIZE, remote_addr_h);
            connection->local_port = strtol(local_port_h, NULL, 16);
            connection->remote_port = strtol(remote_port_h, NULL, 16);
            connection->state = map_network_state(strtol(state_h, NULL, 16));

            struct aws_hash_element *element;
            int return_code = aws_hash_table_find(&ifconfig->iface_name_to_info, local_addr, &element);
            if (element == NULL || return_code != AWS_OP_SUCCESS) {
                AWS_LOGF_WARN(
                    AWS_LS_IOTDEVICE_NETWORK_CONFIG,
                    "id=%p: Could not retrieve interface mapping for address: %s",
                    (void *)ifconfig,
                    local_addr);
                aws_mem_release(allocator, connection);
                connection = NULL;
                continue;
            }

            struct aws_iotdevice_network_iface *iface = (struct aws_iotdevice_network_iface *)element->value;
            connection->local_interface = aws_string_new_from_c_str(allocator, iface->iface_name);
            if (!connection->local_interface) {
                return_value = AWS_OP_ERR;
                AWS_LOGF_ERROR(
                    AWS_LS_IOTDEVICE_NETWORK_CONFIG,
                    "id=%p: Could not allocate memory for connection local address",
                    (void *)ifconfig);
                goto cleanup;
            }

            connection->remote_address = aws_string_new_from_c_str(allocator, remote_addr);
            if (!connection->remote_address) {
                return_value = AWS_OP_ERR;
                AWS_LOGF_ERROR(
                    AWS_LS_IOTDEVICE_NETWORK_CONFIG,
                    "id=%p: Could not allocate memory for connection remote address",
                    (void *)ifconfig);
                goto cleanup;
            }
            connection->protocol = protocol;

            if (AWS_OP_SUCCESS != aws_array_list_push_back(net_conns, connection)) {
                goto cleanup;
            } else {
                aws_mem_release(allocator, connection);
                connection = NULL;
            }
        }
    }

cleanup:
    if (connection != NULL) {
        aws_string_destroy(connection->local_interface);
        aws_string_destroy(connection->remote_address);
        aws_mem_release(allocator, connection);
    }

    aws_array_list_clean_up(&lines);

    return return_value;
}