Added support for binding (-B) to a specific interface
Этот коммит содержится в:
родитель
bb0677cdfb
Коммит
a1344ede16
@ -116,6 +116,7 @@ struct iperf_test
|
||||
struct protocol *protocol;
|
||||
char state;
|
||||
char *server_hostname; /* -c option */
|
||||
char *bind_address; /* -B option */
|
||||
int server_port;
|
||||
int duration; /* total duration of test (-t flag) */
|
||||
|
||||
|
@ -164,6 +164,7 @@ iperf_parse_arguments(struct iperf_test *test, int argc, char **argv)
|
||||
{"port", required_argument, NULL, 'p'},
|
||||
{"parallel", required_argument, NULL, 'P'},
|
||||
{"udp", no_argument, NULL, 'u'},
|
||||
{"bind", required_argument, NULL, 'B'},
|
||||
{"tcpInfo", no_argument, NULL, 'T'},
|
||||
{"bandwidth", required_argument, NULL, 'b'},
|
||||
{"length", required_argument, NULL, 'l'},
|
||||
@ -192,7 +193,7 @@ iperf_parse_arguments(struct iperf_test *test, int argc, char **argv)
|
||||
};
|
||||
char ch;
|
||||
|
||||
while ((ch = getopt_long(argc, argv, "c:p:st:uP:b:l:w:i:n:mRNTvhVdM:f:", longopts, NULL)) != -1) {
|
||||
while ((ch = getopt_long(argc, argv, "c:p:st:uP:B:b:l:w:i:n:mRNTvhVdM:f:", longopts, NULL)) != -1) {
|
||||
switch (ch) {
|
||||
case 'c':
|
||||
if (test->role == 's') {
|
||||
@ -201,7 +202,7 @@ iperf_parse_arguments(struct iperf_test *test, int argc, char **argv)
|
||||
} else {
|
||||
test->role = 'c';
|
||||
test->server_hostname = (char *) malloc(strlen(optarg)+1);
|
||||
strncpy(test->server_hostname, optarg, strlen(optarg));
|
||||
strncpy(test->server_hostname, optarg, strlen(optarg)+1);
|
||||
}
|
||||
break;
|
||||
case 'p':
|
||||
@ -245,6 +246,10 @@ iperf_parse_arguments(struct iperf_test *test, int argc, char **argv)
|
||||
return (-1);
|
||||
}
|
||||
break;
|
||||
case 'B':
|
||||
test->bind_address = (char *) malloc(strlen(optarg)+1);
|
||||
strncpy(test->bind_address, optarg, strlen(optarg)+1);
|
||||
break;
|
||||
case 'b':
|
||||
if (test->role == 's') {
|
||||
i_errno = IECLIENTONLY;
|
||||
|
@ -98,7 +98,7 @@ iperf_handle_message_client(struct iperf_test *test)
|
||||
return (-1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
@ -107,15 +107,13 @@ iperf_handle_message_client(struct iperf_test *test)
|
||||
int
|
||||
iperf_connect(struct iperf_test *test)
|
||||
{
|
||||
// printf("Connecting to host %s, port %d\n", test->server_hostname, test->server_port);
|
||||
|
||||
FD_ZERO(&test->read_set);
|
||||
FD_ZERO(&test->write_set);
|
||||
|
||||
get_uuid(test->cookie);
|
||||
|
||||
/* Create and connect the control channel */
|
||||
test->ctrl_sck = netdial(Ptcp, test->server_hostname, test->server_port);
|
||||
test->ctrl_sck = netdial(Ptcp, test->bind_address, test->server_hostname, test->server_port);
|
||||
if (test->ctrl_sck < 0) {
|
||||
i_errno = IECONNECT;
|
||||
return (-1);
|
||||
|
@ -13,8 +13,9 @@ char *iperf_strerror(int);
|
||||
extern int i_errno;
|
||||
|
||||
enum {
|
||||
/* Parameter errors */
|
||||
IENONE = 0, // No error
|
||||
|
||||
/* Parameter errors */
|
||||
IESERVCLIENT = 1, // Iperf cannot be both server and client
|
||||
IENOROLE = 2, // Iperf must either be a client (-c) or server (-s)
|
||||
IECLIENTONLY = 3, // This option is client only
|
||||
|
@ -52,7 +52,7 @@ iperf_server_listen(struct iperf_test *test)
|
||||
char ubuf[UNIT_LEN];
|
||||
int x;
|
||||
|
||||
if((test->listener = netannounce(Ptcp, NULL, test->server_port)) < 0) {
|
||||
if((test->listener = netannounce(Ptcp, test->bind_address, test->server_port)) < 0) {
|
||||
i_errno = IELISTEN;
|
||||
return (-1);
|
||||
}
|
||||
@ -331,7 +331,6 @@ iperf_run_server(struct iperf_test *test)
|
||||
test->max_fd = (s > test->max_fd) ? s : test->max_fd;
|
||||
|
||||
streams_accepted++;
|
||||
// connect_msg(sp);
|
||||
if (test->on_new_stream)
|
||||
test->on_new_stream(sp);
|
||||
}
|
||||
@ -346,7 +345,7 @@ iperf_run_server(struct iperf_test *test)
|
||||
if (test->no_delay || test->settings->mss) {
|
||||
FD_CLR(test->listener, &test->read_set);
|
||||
close(test->listener);
|
||||
if ((s = netannounce(Ptcp, NULL, test->server_port)) < 0) {
|
||||
if ((s = netannounce(Ptcp, test->bind_address, test->server_port)) < 0) {
|
||||
i_errno = IELISTEN;
|
||||
return (-1);
|
||||
}
|
||||
|
@ -116,6 +116,7 @@ iperf_tcp_listen(struct iperf_test *test)
|
||||
{
|
||||
int s, opt;
|
||||
struct sockaddr_in sa;
|
||||
struct hostent *hent;
|
||||
s = test->listener;
|
||||
|
||||
if (test->no_delay || test->settings->mss) {
|
||||
@ -149,7 +150,15 @@ iperf_tcp_listen(struct iperf_test *test)
|
||||
|
||||
memset(&sa, 0, sizeof(sa));
|
||||
sa.sin_family = AF_INET;
|
||||
sa.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
if (test->bind_address) {
|
||||
if ((hent = gethostbyname(test->bind_address)) == NULL) {
|
||||
i_errno = IESTREAMLISTEN;
|
||||
return (-1);
|
||||
}
|
||||
memcpy(&sa.sin_addr, hent->h_addr_list[0], 4);
|
||||
} else {
|
||||
sa.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
}
|
||||
sa.sin_port = htons(test->server_port);
|
||||
|
||||
if (bind(s, (struct sockaddr *) &sa, sizeof(sa)) < 0) {
|
||||
@ -178,18 +187,34 @@ int
|
||||
iperf_tcp_connect(struct iperf_test *test)
|
||||
{
|
||||
int s, opt;
|
||||
struct sockaddr_in sa;
|
||||
struct sockaddr_in sa, local;
|
||||
struct hostent *hent;
|
||||
|
||||
if ((hent = gethostbyname(test->server_hostname)) == 0) {
|
||||
i_errno = IESTREAMCONNECT;
|
||||
return (-1);
|
||||
}
|
||||
if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
|
||||
i_errno = IESTREAMCONNECT;
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if (test->bind_address) {
|
||||
if ((hent = gethostbyname(test->bind_address)) == NULL) {
|
||||
/* XXX: Make IESTREAMBIND? */
|
||||
i_errno = IESTREAMCONNECT;
|
||||
return (-1);
|
||||
}
|
||||
memset(&local, 0, sizeof(local));
|
||||
memcpy(&local.sin_addr, hent->h_addr_list[0], 4);
|
||||
local.sin_family = AF_INET;
|
||||
|
||||
if (bind(s, (struct sockaddr *) &local, sizeof(local)) < 0) {
|
||||
i_errno = IESTREAMCONNECT;
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
|
||||
if ((hent = gethostbyname(test->server_hostname)) == 0) {
|
||||
i_errno = IESTREAMCONNECT;
|
||||
return (-1);
|
||||
}
|
||||
memset(&sa, 0, sizeof(sa));
|
||||
sa.sin_family = AF_INET;
|
||||
memcpy(&sa.sin_addr.s_addr, hent->h_addr, sizeof(sa.sin_addr.s_addr));
|
||||
|
@ -170,7 +170,7 @@ iperf_udp_accept(struct iperf_test *test)
|
||||
return (-1);
|
||||
}
|
||||
|
||||
test->prot_listener = netannounce(Pudp, NULL, test->server_port);
|
||||
test->prot_listener = netannounce(Pudp, test->bind_address, test->server_port);
|
||||
if (test->prot_listener < 0) {
|
||||
i_errno = IESTREAMLISTEN;
|
||||
return (-1);
|
||||
@ -198,7 +198,7 @@ iperf_udp_listen(struct iperf_test *test)
|
||||
{
|
||||
int s;
|
||||
|
||||
if ((s = netannounce(Pudp, NULL, test->server_port)) < 0) {
|
||||
if ((s = netannounce(Pudp, test->bind_address, test->server_port)) < 0) {
|
||||
i_errno = IESTREAMLISTEN;
|
||||
return (-1);
|
||||
}
|
||||
@ -216,7 +216,7 @@ iperf_udp_connect(struct iperf_test *test)
|
||||
{
|
||||
int s, buf;
|
||||
|
||||
if ((s = netdial(Pudp, test->server_hostname, test->server_port)) < 0) {
|
||||
if ((s = netdial(Pudp, test->bind_address, test->server_hostname, test->server_port)) < 0) {
|
||||
i_errno = IESTREAMCONNECT;
|
||||
return (-1);
|
||||
}
|
||||
|
36
src/net.c
36
src/net.c
@ -18,24 +18,35 @@
|
||||
*/
|
||||
|
||||
/* make connection to server */
|
||||
// XXX: Change client to server?
|
||||
int
|
||||
netdial(int proto, char *client, int port)
|
||||
netdial(int proto, char *local, char *server, int port)
|
||||
{
|
||||
int s;
|
||||
struct hostent *hent;
|
||||
struct sockaddr_in sa;
|
||||
|
||||
/* XXX: This is not working for non-fully qualified host names use getaddrinfo() instead? */
|
||||
if ((hent = gethostbyname(client)) == 0) {
|
||||
return (-1);
|
||||
}
|
||||
struct sockaddr_in sa, lo;
|
||||
|
||||
s = socket(AF_INET, proto, 0);
|
||||
if (s < 0) {
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if (local) {
|
||||
if ((hent = gethostbyname(local)) == 0)
|
||||
return (-1);
|
||||
|
||||
memset(&lo, 0, sizeof(lo));
|
||||
memmove(&lo.sin_addr, hent->h_addr_list[0], 4);
|
||||
lo.sin_family = AF_INET;
|
||||
|
||||
if (bind(s, (struct sockaddr *) &lo, sizeof(lo)) < 0)
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/* XXX: This is not working for non-fully qualified host names use getaddrinfo() instead? */
|
||||
if ((hent = gethostbyname(server)) == 0) {
|
||||
return (-1);
|
||||
}
|
||||
|
||||
memset(&sa, 0, sizeof sa);
|
||||
memmove(&sa.sin_addr, hent->h_addr, 4);
|
||||
sa.sin_port = htons(port);
|
||||
@ -55,6 +66,7 @@ netannounce(int proto, char *local, int port)
|
||||
{
|
||||
int s;
|
||||
struct sockaddr_in sa;
|
||||
struct hostent *hent;
|
||||
/* XXX: implement binding to a local address rather than * */
|
||||
|
||||
memset((void *) &sa, 0, sizeof sa);
|
||||
@ -66,6 +78,14 @@ netannounce(int proto, char *local, int port)
|
||||
int opt = 1;
|
||||
setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *) &opt, sizeof(opt));
|
||||
|
||||
if (local) {
|
||||
if ((hent = gethostbyname(local)) == NULL)
|
||||
return (-1);
|
||||
memcpy(&sa.sin_addr, hent->h_addr_list[0], 4);
|
||||
} else {
|
||||
sa.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
}
|
||||
|
||||
sa.sin_port = htons(port);
|
||||
sa.sin_family = AF_INET;
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
#ifndef __NET_H
|
||||
#define __NET_H
|
||||
|
||||
int netdial(int, char *, int);
|
||||
int netdial(int, char *, char *, int);
|
||||
int netannounce(int, char *, int);
|
||||
int Nwrite(int, void *, int, int);
|
||||
int Nread(int, void *, int, int);
|
||||
|
Загрузка…
x
Ссылка в новой задаче
Block a user