src/tcpkali_iface.c
int
detect_source_ips(struct addresses *dsts, struct addresses *srcs) {
    struct ifaddrs *interfaces = 0;

    int rc = getifaddrs(&interfaces);
    if(rc == -1) {
        /* Can't get interfaces... Won't try to use several source IPs. */
        warning(
            "Can't enumerate interfaces, "
            "won't use multiple source IPs: %s\n",
            strerror(errno));
        return 0;
    }

    /* If we are not supposed to go anywhere, we won't invoke this function. */
    if(dsts->n_addrs == 0) {
        fprintf(stderr,
                "Source IP detection failed: "
                "No destination IPs are given\n");
        freeifaddrs(interfaces);
        return -1;
    }

    sa_family_t common_ss_family = 0;

    for(size_t dst_idx = 0; dst_idx < dsts->n_addrs; dst_idx++) {
        struct sockaddr_storage *ds = &dsts->addrs[dst_idx];
        char tmpbuf[256];

        /*
         * For now, we can reliably detect source ips only
         * when the address families of the destination ips are the same.
         */
        if(common_ss_family == 0) {
            common_ss_family = ds->ss_family;
        } else if(common_ss_family != ds->ss_family) {
            warning(
                "Could not detect local address when connecting to %s:"
                " Multiple incompatible address families in destination.\n",
                format_sockaddr(ds, tmpbuf, sizeof(tmpbuf)));
            warning("Would not open more than 64k connections to %s\n",
                    format_sockaddr(ds, tmpbuf, sizeof(tmpbuf)));
            srcs->n_addrs = 0;
            freeifaddrs(interfaces);
            return 0;
        }

        /*
         * Attempt to create a connection and see what our
         * local address looks like. Then search for that address
         * among the interfaces.
         */
        struct sockaddr_storage local_addr;
        if(detect_local_ip_for_remote(interfaces, ds, &local_addr)) {
            freeifaddrs(interfaces);
            return -1;
        }

        const char *ifname =
            interface_by_addr(interfaces, (struct sockaddr *)&local_addr);
        if(ifname == NULL) {
            warning("Can't determine local interface to connect to %s\n",
                    format_sockaddr(ds, tmpbuf, sizeof(tmpbuf)));
            warning("Would not open more than 64k connections to %s\n",
                    format_sockaddr(ds, tmpbuf, sizeof(tmpbuf)));
            srcs->n_addrs = 0;
            freeifaddrs(interfaces);
            return 0;
        }

        if(collect_interface_addresses(interfaces, ifname, ds->ss_family, srcs)
           == 0) {
            fprintf(stderr, "Using interface %s to connect to %s\n", ifname,
                    format_sockaddr(ds, tmpbuf, sizeof(tmpbuf)));
        } else {
            fprintf(stderr, "Failed to collect IPs from interface %s\n",
                    ifname);
            freeifaddrs(interfaces);
            return -1;
        }
    }

    freeifaddrs(interfaces);
    return 0;
}
/*
 * Given a list of destination addresses, populate the list of source
 * addresses with compatible source (local) IPs.
 */
Given a list of destination addresses, populate the list of source
addresses with compatible source (local) IPs.
Given a list of destination addresses populate the list of source addresses with compatible source ( local ) IPs .
int
detect_source_ips(struct addresses *dsts, struct addresses *srcs) {
    struct ifaddrs *interfaces = 0;
    int rc = getifaddrs(&interfaces);
    if(rc == -1) {
        warning(
            "Can't enumerate interfaces, "
            "won't use multiple source IPs: %s\n",
            strerror(errno));
        return 0;
    }
    if(dsts->n_addrs == 0) {
        fprintf(stderr,
                "Source IP detection failed: "
                "No destination IPs are given\n");
        freeifaddrs(interfaces);
        return -1;
    }
    sa_family_t common_ss_family = 0;
    for(size_t dst_idx = 0; dst_idx < dsts->n_addrs; dst_idx++) {
        struct sockaddr_storage *ds = &dsts->addrs[dst_idx];
        char tmpbuf[256];
        if(common_ss_family == 0) {
            common_ss_family = ds->ss_family;
        } else if(common_ss_family != ds->ss_family) {
            warning(
                "Could not detect local address when connecting to %s:"
                " Multiple incompatible address families in destination.\n",
                format_sockaddr(ds, tmpbuf, sizeof(tmpbuf)));
            warning("Would not open more than 64k connections to %s\n",
                    format_sockaddr(ds, tmpbuf, sizeof(tmpbuf)));
            srcs->n_addrs = 0;
            freeifaddrs(interfaces);
            return 0;
        }
        struct sockaddr_storage local_addr;
        if(detect_local_ip_for_remote(interfaces, ds, &local_addr)) {
            freeifaddrs(interfaces);
            return -1;
        }
        const char *ifname =
            interface_by_addr(interfaces, (struct sockaddr *)&local_addr);
        if(ifname == NULL) {
            warning("Can't determine local interface to connect to %s\n",
                    format_sockaddr(ds, tmpbuf, sizeof(tmpbuf)));
            warning("Would not open more than 64k connections to %s\n",
                    format_sockaddr(ds, tmpbuf, sizeof(tmpbuf)));
            srcs->n_addrs = 0;
            freeifaddrs(interfaces);
            return 0;
        }
        if(collect_interface_addresses(interfaces, ifname, ds->ss_family, srcs)
           == 0) {
            fprintf(stderr, "Using interface %s to connect to %s\n", ifname,
                    format_sockaddr(ds, tmpbuf, sizeof(tmpbuf)));
        } else {
            fprintf(stderr, "Failed to collect IPs from interface %s\n",
                    ifname);
            freeifaddrs(interfaces);
            return -1;
        }
    }
    freeifaddrs(interfaces);
    return 0;
}
int detect_source_ips ( struct addresses * dsts , struct addresses * srcs ) { struct ifaddrs * interfaces = 0 ; int rc = getifaddrs ( & interfaces ) ; if ( rc == -1 ) { warning ( " " " \n " , strerror ( errno ) ) ; return 0 ; } if ( dsts -> n_addrs == 0 ) { fprintf ( stderr , " " " \n " ) ; freeifaddrs ( interfaces ) ; return -1 ; } sa_family_t common_ss_family = 0 ; for ( size_t dst_idx = 0 ; dst_idx < dsts -> n_addrs ; dst_idx ++ ) { struct sockaddr_storage * ds = & dsts -> addrs [ dst_idx ] ; char tmpbuf [ 256 ] ; if ( common_ss_family == 0 ) { common_ss_family = ds -> ss_family ; } else if ( common_ss_family != ds -> ss_family ) { warning ( " " " \n " , format_sockaddr ( ds , tmpbuf , sizeof ( tmpbuf ) ) ) ; warning ( " \n " , format_sockaddr ( ds , tmpbuf , sizeof ( tmpbuf ) ) ) ; srcs -> n_addrs = 0 ; freeifaddrs ( interfaces ) ; return 0 ; } struct sockaddr_storage local_addr ; if ( detect_local_ip_for_remote ( interfaces , ds , & local_addr ) ) { freeifaddrs ( interfaces ) ; return -1 ; } const char * ifname = interface_by_addr ( interfaces , ( struct sockaddr * ) & local_addr ) ; if ( ifname == NULL ) { warning ( " \n " , format_sockaddr ( ds , tmpbuf , sizeof ( tmpbuf ) ) ) ; warning ( " \n " , format_sockaddr ( ds , tmpbuf , sizeof ( tmpbuf ) ) ) ; srcs -> n_addrs = 0 ; freeifaddrs ( interfaces ) ; return 0 ; } if ( collect_interface_addresses ( interfaces , ifname , ds -> ss_family , srcs ) == 0 ) { fprintf ( stderr , " \n " , ifname , format_sockaddr ( ds , tmpbuf , sizeof ( tmpbuf ) ) ) ; } else { fprintf ( stderr , " \n " , ifname ) ; freeifaddrs ( interfaces ) ; return -1 ; } } freeifaddrs ( interfaces ) ; return 0 ; }
Given a list of destination addresses, populate the list of source
 addresses with compatible source (local) IPs.
Given a list of destination addresses populate the list of source addresses with compatible source ( local ) IPs .
/* Can't get interfaces... Won't try to use several source IPs. */ /* If we are not supposed to go anywhere, we won't invoke this function. */ /*
         * For now, we can reliably detect source ips only
         * when the address families of the destination ips are the same.
         */ /*
         * Attempt to create a connection and see what our
         * local address looks like. Then search for that address
         * among the interfaces.
         */