1
1

Make --cport work without --bind (#697).

This commit also adds SCTP support for --cport.

Fixes #616.
Этот коммит содержится в:
Bruce A. Mah 2018-02-12 10:30:23 -08:00 коммит произвёл GitHub
родитель 571ff3ae7e
Коммит e7aa59b6b8
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
6 изменённых файлов: 148 добавлений и 10 удалений

Просмотреть файл

@ -1115,10 +1115,6 @@ iperf_parse_arguments(struct iperf_test *test, int argc, char **argv)
return -1;
}
#endif //HAVE_SSL
if (!test->bind_address && test->bind_port) {
i_errno = IEBIND;
return -1;
}
if (blksize == 0) {
if (test->protocol->id == Pudp)
blksize = 0; /* try to dynamically determine from MSS */

Просмотреть файл

@ -1,5 +1,5 @@
/*
* iperf, Copyright (c) 2014-2017, The Regents of the University of
* iperf, Copyright (c) 2014-2018, The Regents of the University of
* California, through Lawrence Berkeley National Laboratory (subject
* to receipt of any required approvals from the U.S. Dept. of
* Energy). All rights reserved.
@ -306,7 +306,7 @@ enum {
IEENDCONDITIONS = 16, // Only one test end condition (-t, -n, -k) may be specified
IELOGFILE = 17, // Can't open log file
IENOSCTP = 18, // No SCTP support available
IEBIND = 19, // Local port specified with no local bind option
IEBIND = 19, // UNUSED: Local port specified with no local bind option
IEUDPBLOCKSIZE = 20, // Block size invalid
IEBADTOS = 21, // Bad TOS value
IESETCLIENTAUTH = 22, // Bad configuration of client authentication

Просмотреть файл

@ -122,7 +122,7 @@ iperf_strerror(int int_errno)
case IEINTERVAL:
snprintf(errstr, len, "invalid report interval (min = %g, max = %g seconds)", MIN_INTERVAL, MAX_INTERVAL);
break;
case IEBIND:
case IEBIND: /* UNUSED */
snprintf(errstr, len, "--bind must be specified to use --cport");
break;
case IEUDPBLOCKSIZE:

Просмотреть файл

@ -1,5 +1,5 @@
/*
* iperf, Copyright (c) 2014, 2015, The Regents of the University of
* iperf, Copyright (c) 2014-2018, The Regents of the University of
* California, through Lawrence Berkeley National Laboratory (subject
* to receipt of any required approvals from the U.S. Dept. of
* Energy). All rights reserved.
@ -274,6 +274,67 @@ iperf_sctp_connect(struct iperf_test *test)
return -1;
}
/*
* Various ways to bind the local end of the connection.
* 1. --bind (with or without --cport).
*/
if (test->bind_address) {
struct sockaddr_in *lcladdr;
lcladdr = (struct sockaddr_in *)local_res->ai_addr;
lcladdr->sin_port = htons(test->bind_port);
if (bind(s, (struct sockaddr *) local_res->ai_addr, local_res->ai_addrlen) < 0) {
saved_errno = errno;
close(s);
freeaddrinfo(local_res);
freeaddrinfo(server_res);
errno = saved_errno;
i_errno = IESTREAMCONNECT;
return -1;
}
freeaddrinfo(local_res);
}
/* --cport, no --bind */
else if (test->bind_port) {
size_t addrlen;
struct sockaddr_storage lcl;
/* IPv4 */
if (server_res->ai_family == AF_INET) {
struct sockaddr_in *lcladdr = (struct sockaddr_in *) &lcl;
lcladdr->sin_family = AF_INET;
lcladdr->sin_port = htons(test->bind_port);
lcladdr->sin_addr.s_addr = INADDR_ANY;
addrlen = sizeof(struct sockaddr_in);
}
/* IPv6 */
else if (server_res->ai_family == AF_INET6) {
struct sockaddr_in6 *lcladdr = (struct sockaddr_in6 *) &lcl;
lcladdr->sin6_family = AF_INET6;
lcladdr->sin6_port = htons(test->bind_port);
lcladdr->sin6_addr = in6addr_any;
addrlen = sizeof(struct sockaddr_in6);
}
/* Unknown protocol */
else {
saved_errno = errno;
close(s);
freeaddrinfo(server_res);
errno = saved_errno;
i_errno = IEPROTOCOL;
return -1;
}
if (bind(s, (struct sockaddr *) &lcl, addrlen) < 0) {
saved_errno = errno;
close(s);
freeaddrinfo(server_res);
errno = saved_errno;
i_errno = IESTREAMCONNECT;
return -1;
}
}
if (test->no_delay != 0) {
opt = 1;
if (setsockopt(s, IPPROTO_SCTP, SCTP_NODELAY, &opt, sizeof(opt)) < 0) {

Просмотреть файл

@ -349,6 +349,9 @@ iperf_tcp_listen(struct iperf_test *test)
/* iperf_tcp_connect
*
* connect to a TCP stream listener
* This function is roughly similar to netdial(), and may indeed have
* been derived from it at some point, but it sets many TCP-specific
* options between socket creation and connection.
*/
int
iperf_tcp_connect(struct iperf_test *test)
@ -389,11 +392,14 @@ iperf_tcp_connect(struct iperf_test *test)
return -1;
}
/*
* Various ways to bind the local end of the connection.
* 1. --bind (with or without --cport).
*/
if (test->bind_address) {
struct sockaddr_in *lcladdr;
lcladdr = (struct sockaddr_in *)local_res->ai_addr;
lcladdr->sin_port = htons(test->bind_port);
local_res->ai_addr = (struct sockaddr *)lcladdr;
if (bind(s, (struct sockaddr *) local_res->ai_addr, local_res->ai_addrlen) < 0) {
saved_errno = errno;
@ -406,6 +412,46 @@ iperf_tcp_connect(struct iperf_test *test)
}
freeaddrinfo(local_res);
}
/* --cport, no --bind */
else if (test->bind_port) {
size_t addrlen;
struct sockaddr_storage lcl;
/* IPv4 */
if (server_res->ai_family == AF_INET) {
struct sockaddr_in *lcladdr = (struct sockaddr_in *) &lcl;
lcladdr->sin_family = AF_INET;
lcladdr->sin_port = htons(test->bind_port);
lcladdr->sin_addr.s_addr = INADDR_ANY;
addrlen = sizeof(struct sockaddr_in);
}
/* IPv6 */
else if (server_res->ai_family == AF_INET6) {
struct sockaddr_in6 *lcladdr = (struct sockaddr_in6 *) &lcl;
lcladdr->sin6_family = AF_INET6;
lcladdr->sin6_port = htons(test->bind_port);
lcladdr->sin6_addr = in6addr_any;
addrlen = sizeof(struct sockaddr_in6);
}
/* Unknown protocol */
else {
saved_errno = errno;
close(s);
freeaddrinfo(server_res);
errno = saved_errno;
i_errno = IEPROTOCOL;
return -1;
}
if (bind(s, (struct sockaddr *) &lcl, addrlen) < 0) {
saved_errno = errno;
close(s);
freeaddrinfo(server_res);
errno = saved_errno;
i_errno = IESTREAMCONNECT;
return -1;
}
}
/* Set socket options */
if (test->no_delay) {

Просмотреть файл

@ -140,12 +140,12 @@ netdial(int domain, int proto, char *local, int local_port, char *server, int po
return -1;
}
/* Bind the local address if given a name (with or without --cport) */
if (local) {
if (local_port) {
struct sockaddr_in *lcladdr;
lcladdr = (struct sockaddr_in *)local_res->ai_addr;
lcladdr->sin_port = htons(local_port);
local_res->ai_addr = (struct sockaddr *)lcladdr;
}
if (bind(s, (struct sockaddr *) local_res->ai_addr, local_res->ai_addrlen) < 0) {
@ -158,6 +158,41 @@ netdial(int domain, int proto, char *local, int local_port, char *server, int po
}
freeaddrinfo(local_res);
}
/* No local name, but --cport given */
else if (local_port) {
size_t addrlen;
struct sockaddr_storage lcl;
/* IPv4 */
if (server_res->ai_family == AF_INET) {
struct sockaddr_in *lcladdr = (struct sockaddr_in *) &lcl;
lcladdr->sin_family = AF_INET;
lcladdr->sin_port = htons(local_port);
lcladdr->sin_addr.s_addr = INADDR_ANY;
addrlen = sizeof(struct sockaddr_in);
}
/* IPv6 */
else if (server_res->ai_family == AF_INET6) {
struct sockaddr_in6 *lcladdr = (struct sockaddr_in6 *) &lcl;
lcladdr->sin6_family = AF_INET6;
lcladdr->sin6_port = htons(local_port);
lcladdr->sin6_addr = in6addr_any;
addrlen = sizeof(struct sockaddr_in6);
}
/* Unknown protocol */
else {
errno = EAFNOSUPPORT;
return -1;
}
if (bind(s, (struct sockaddr *) &lcl, addrlen) < 0) {
saved_errno = errno;
close(s);
freeaddrinfo(server_res);
errno = saved_errno;
return -1;
}
}
((struct sockaddr_in *) server_res->ai_addr)->sin_port = htons(port);
if (timeout_connect(s, (struct sockaddr *) server_res->ai_addr, server_res->ai_addrlen, timeout) < 0 && errno != EINPROGRESS) {