Make --cport work without --bind (#697).
This commit also adds SCTP support for --cport. Fixes #616.
Этот коммит содержится в:
родитель
571ff3ae7e
Коммит
e7aa59b6b8
@ -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) {
|
||||
|
37
src/net.c
37
src/net.c
@ -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) {
|
||||
|
Загрузка…
x
Ссылка в новой задаче
Block a user