int get_network_config_and_transfer()

in source/linux/network.c [329:430]


int get_network_config_and_transfer(struct aws_iotdevice_network_ifconfig *ifconfig, struct aws_allocator *allocator) {
    if (aws_hash_table_init(
            &ifconfig->iface_name_to_info,
            allocator,
            sizeof(struct aws_iotdevice_network_iface),
            aws_hash_c_string,
            aws_hash_callback_c_str_eq,
            NULL,
            s_network_iface_destroy)) {
        return AWS_OP_ERR;
    }
    int result = AWS_OP_ERR;
    int fd = -1;
    struct ifaddrs *address_info = NULL;
    if (getifaddrs(&address_info)) {
        AWS_LOGF_ERROR(
            AWS_LS_IOTDEVICE_NETWORK_CONFIG, "id=%p: getifaddrs() failed: %s", (void *)ifconfig, strerror(errno));
        result = AWS_OP_ERR;
        goto cleanup;
    }
    struct ifaddrs *address = address_info;
    while (address) {
        if (address->ifa_addr == NULL || address->ifa_data == NULL) {
            goto next_interface;
        }

        struct ifreq ifr;
        AWS_ZERO_STRUCT(ifr);

        strncpy(ifr.ifr_name, address->ifa_name, IFNAMSIZ);
        ifr.ifr_name[IFNAMSIZ - 1] = 0;
        fd = socket(AF_INET, SOCK_DGRAM, 0);
        if (fd == -1) {
            AWS_LOGF_ERROR(
                AWS_LS_IOTDEVICE_NETWORK_CONFIG,
                "id=%p: socket(AF_INET, SOCK_DGRAM, 0) failed: %s",
                (void *)ifconfig,
                strerror(errno));
            result = AWS_OP_ERR;
            goto cleanup;
        }
        if (ioctl(fd, SIOCGIFADDR, &ifr) == -1) {
            AWS_LOGF_WARN(
                AWS_LS_IOTDEVICE_NETWORK_CONFIG,
                "id=%p: iotctl(fd, SIOCGIFADDR, ...) failed to get interface address: %s",
                (void *)ifconfig,
                strerror(errno));
            goto next_interface;
        }

        struct aws_iotdevice_network_iface *iface =
            aws_mem_calloc(allocator, 1, sizeof(struct aws_iotdevice_network_iface));
        if (iface == NULL) {
            goto cleanup;
        }
        iface->allocator = allocator;

        if (ifr.ifr_addr.sa_family == AF_INET) {
            inet_ntop(AF_INET, &((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr, iface->ipv4_addr_str, 16);
        }
        strncpy(iface->iface_name, ifr.ifr_name, IFACE_NAME_SIZE);
        iface->iface_name[IFACE_NAME_SIZE - 1] = 0;

        if (address->ifa_data) {
            struct rtnl_link_stats *stats = address->ifa_data;
            iface->metrics.bytes_in = stats->rx_bytes;
            iface->metrics.bytes_out = stats->tx_bytes;
            iface->metrics.packets_in = stats->rx_packets;
            iface->metrics.packets_out = stats->tx_packets;
        }

        if ((result = aws_hash_table_put(&ifconfig->iface_name_to_info, iface->ipv4_addr_str, iface, NULL))) {
            AWS_LOGF_ERROR(
                AWS_LS_IOTDEVICE_NETWORK_CONFIG,
                "id=%p: network interface address to interface info add to map failed: %s",
                (void *)ifconfig,
                aws_error_name(result));
            result = AWS_OP_ERR;
            aws_mem_release(allocator, iface);
            goto cleanup;
        }
    next_interface:
        if (fd != -1) {
            close(fd);
            fd = -1;
        }
        address = address->ifa_next;
    } /* while */
    result = AWS_OP_SUCCESS;

cleanup:
    if (result != AWS_OP_SUCCESS) {
        aws_hash_table_clean_up(&ifconfig->iface_name_to_info);
    }
    if (address_info) {
        freeifaddrs(address_info);
    }
    if (fd != -1) {
        close(fd);
    }
    return result;
}