Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

-B option is not processed correctly #193

Closed
kyanite opened this issue Jul 10, 2014 · 8 comments
Closed

-B option is not processed correctly #193

kyanite opened this issue Jul 10, 2014 · 8 comments
Assignees
Labels

Comments

@kyanite
Copy link

kyanite commented Jul 10, 2014

-B, --bind bind to a specific interface or multicast address
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-B option is the client only option from the help information, but still can pass by server mode.

$>/opt/iperf3/bin/iperf3 -s -B 192.168.1.3
iperf3: error - unable to start listener for connections:


Server listening on 5201

@bmah888 bmah888 added the bug label Jul 10, 2014
@bmah888 bmah888 self-assigned this Jul 10, 2014
@bmah888 bmah888 added this to the 3.0.x milestone Jul 10, 2014
@bmah888
Copy link
Contributor

bmah888 commented Jul 10, 2014

Initial findings: There seem to be several problems here. First, in my own testing, it looks like the -B parameter isn't taking effect; I get the same error message originally reported as well as seeing the process bind to the wildcard address (this is on MacOS, I wonder if there is any platform specific behavior at work also).

Second, the -B option is I believe applicable to both the client and server sides. If this is true, the help text is wrong.

Finally, there is no multicast support at all in iperf3, so the mention of multicast addresses is incorrect (if there were multicast support, it would be implemented significantly differently than how iperf3 binds to TCP or UDP ports).

Just for completeness, on what platform was this seen?

@bmah888
Copy link
Contributor

bmah888 commented Jul 10, 2014

I've looked into this a little bit more. This bug has something to do with iperf3 trying to be smart about auto-detecting the correct address family (i.e. AF_INET vs. AF_INET6). It appears to happen if the argument to the "-B" option resolves to (only) an IPv4 address, for example an IPv4 literal or an FQDN that has only an A record in DNS. It works fine in these cases if you provide a "-4" flag, so I'd say for now use that as a workaround if you need it.

Another facet of this bug is that if you give an argument to -B that has no relation to any interface address on the host at all, iperf3 fails in the same way and binds to the wildcard address, where it really should just die.

Still trying to figure out what the real problem is.

Reports of people trying this on different platforms would be appreciated. I've seen identical behavior on MacOS and FreeBSD.

@kyanite
Copy link
Author

kyanite commented Jul 11, 2014

I do this on Ubuntu Linux and MacOS. Following is what i think.

  1. -B option should applicable to both the client and server sides.
  2. $>/opt/iperf3/bin/iperf3 -s -B 192.168.1.3 is still can work but bind to wildcard address.
    The code in main.c as below, it will call iperf_reset_test, so the first time output error, and second time it start iperf correctly but bind to wildcard address.
    main.c
    112 for (;;) {
    113 if (iperf_run_server(test) < 0) {
    114 iperf_err(test, "error - %s", iperf_strerror(i_errno));
    115 fprintf(stderr, "\n");
    116 ++consecutive_errors;
    117 if (consecutive_errors >= 5) {
    118 fprintf(stderr, "too many errors, exiting\n");
    119 break;
    120 }
    121 } else {
    122 consecutive_errors = 0;
    123 }
    124 iperf_reset_test(test);
    125 }
  3. In net.c
    109 hints.ai_flags = AI_PASSIVE;
    110 if (getaddrinfo(local, portstr, &hints, &res) != 0)
    111 return -1;

Return socket address structures suitable for a passive open (i.e., a listening
socket). In this case, host should be NULL, and the IP address component
of the socket address structure(s) returned by result will contain a wildcard
IP address (i.e., INADDR_ANY or IN6ADDR_ANY_INIT). (From the linux programming interface)

@bmah888
Copy link
Contributor

bmah888 commented Jul 15, 2014

So the reason there's an error is that in netannounce(), we convert AF_UNSPEC to AF_INET6. This means that in any case we don't specify an address family, the code would assume that a -B argument was to be treated as an IPv6 address. This broke for the case of specifying an IPv4 literal or an FQDN that only resolved to an IPv4 address.

The previous comment explained why iperf3 would "recover" and bind to the wildcard address...it was calling iperf_reset_test(), which zapped out test->bind_address. It shouldn't do that; a common use case for binding a server to a particular address is because you don't want it to be reachable on all interfaces. That code was updated in revision c7ddeba to fix some memory leaks, but iperf_reset_test() probably shouldn't be trying to clear strings that were originally set via command-line arguments.

I'm not sure why we transmorgify AF_UNSPEC to AF_INET6 in the first place. If I make it not do that, as well as a couple of other minor tweaks, it behaves as I'd expect to see, at least on the server side. I think it works on the client side too but I'm not 100% sure.

The following excerpt from RFC 6724 is probably applicable in some way here:

   Well-behaved applications SHOULD NOT simply use the first address
   returned from an API such as getaddrinfo() and then give up if it
   fails.  For many applications, it is appropriate to iterate through
   the list of addresses returned from getaddrinfo() until a working
   address is found.  For other applications, it might be appropriate to
   try multiple addresses in parallel (e.g., with some small delay in
   between) and use the first one to succeed.

Also Issue #177 is probably related in some way as this is also related to address family selection.

bmah888 added a commit that referenced this issue Jul 17, 2014
If specifying -B with an IPv4 literal address or with an FQDN that
resolved to an IPv4 address, but we had not explicitly specified an
address family with -4, we failed to set up the socket correctly
because we assumed binding to an IPv6 address, and instead (after some
error spewage) wound up binding to wildcard address.

The fix in this commit has multiple parts:  First, if the address
family hasn't been explictly specified, don't force AF_INET6 in the
hints to getaddrinfo(3).  AF_UNSPEC should generate the correct
(according to RFC 6724) behavior.

Second, iperf_reset_test() should not discard members that were passed
from command-line parameters, because that alters the behavior of the
iperf3 when it tries to recreate the listening socket.  In the failure
situation described in this issue (and possibly other as well), the
value of -B gets discarded, so on subsequent attempts to set up the
listening socket it just binds to the wildcard address.

While here, fix on-line help related to the -B option to match
reality.

Note that we're not completely in compliance with RFC 6724, which
states that we should actually try all of the addresses in returned by
getaddrinfo(3), rather than just the first one.

Fixes Issue #193.

(cherry picked from commit 5b760ee)
Signed-off-by: Bruce A. Mah <bmah@es.net>

Conflicts:
	src/locale.c
bmah888 added a commit that referenced this issue Jul 17, 2014
If specifying -B with an IPv4 literal address or with an FQDN that
resolved to an IPv4 address, but we had not explicitly specified an
address family with -4, we failed to set up the socket correctly
because we assumed binding to an IPv6 address, and instead (after some
error spewage) wound up binding to wildcard address.

The fix in this commit has multiple parts:  First, if the address
family hasn't been explictly specified, don't force AF_INET6 in the
hints to getaddrinfo(3).  AF_UNSPEC should generate the correct
(according to RFC 6724) behavior.

Second, iperf_reset_test() should not discard members that were passed
from command-line parameters, because that alters the behavior of the
iperf3 when it tries to recreate the listening socket.  In the failure
situation described in this issue (and possibly other as well), the
value of -B gets discarded, so on subsequent attempts to set up the
listening socket it just binds to the wildcard address.

While here, fix on-line help related to the -B option to match
reality.

Note that we're not completely in compliance with RFC 6724, which
states that we should actually try all of the addresses in returned by
getaddrinfo(3), rather than just the first one.

Fixes Issue #193.
@bmah888
Copy link
Contributor

bmah888 commented Jul 17, 2014

Something's still not quite right. Now, if the user doesn't give -B and doesn't specify an address family we bind to the IPv4 wildcard address (we shouldn't force IPv4 in this case). I'm trying to sort this out, but if I haven't solved this by the end of today I'm going to temporarily revert the above change.

bmah888 added a commit that referenced this issue Jul 18, 2014
On CentOS 6 and MacOS, if no address family was specified, we'd
get back an IPv4 address from getaddrinfo(3), with the result that
we couldn't accept IPv6 connections in the default server configuration.

There was an earlier attempt at fixing this problem that caused
Issue #193.  This change is a follow-up fix to that issue.

While here, put lots of comments around the fix so we remember
why we're doing these shenanigans.
bmah888 added a commit that referenced this issue Jul 18, 2014
On CentOS 6 and MacOS, if no address family was specified, we'd
get back an IPv4 address from getaddrinfo(3), with the result that
we couldn't accept IPv6 connections in the default server configuration.

There was an earlier attempt at fixing this problem that caused
Issue #193.  This change is a follow-up fix to that issue.

While here, put lots of comments around the fix so we remember
why we're doing these shenanigans.

(cherry picked from commit 76b5942)
Signed-off-by: Bruce A. Mah <bmah@es.net>
@bmah888
Copy link
Contributor

bmah888 commented Jul 21, 2014

This appears to be working correctly now. Closing this issue.

@bmah888 bmah888 closed this as completed Jul 21, 2014
@bmah888
Copy link
Contributor

bmah888 commented Aug 1, 2014

@i2aaron and @arlake228 have reported some problems with a combination of -B and -w (because setting the window size causes the listening socket used for the control connection to be recreated, and I missed fixing the socket-binding stuff for this case). We're working this out over email; both @i2aaron and I have patches in hand for this.

@bmah888 bmah888 reopened this Aug 1, 2014
bmah888 added a commit that referenced this issue Aug 1, 2014
When we do TCP tests and specify the socket buffer size, MSS, or
TCP no delay option, the iperf3 server destroys the socket it was
using to listen for the control connection and opens up a new
listening socket for the test's data connections.  This is (I think)
to make sure that the data connections all have the correct TCP
parameters.

When we re-create the listening socket, we also need to go through
the binding logic again (with all of the address family selectiion,
etc. goop).  The bug fixes that were a part of issue #193 need to
be ported to this code as well.

This problem only affects TCP tests, because for other protocols,
the listening socket for data cannot be the same listening sock as
for the control connection.

While here, add some comments so anybody trying to understand this
code will have an easier time.

Based on patch by:	@i2aaron
bmah888 added a commit that referenced this issue Aug 1, 2014
When we do TCP tests and specify the socket buffer size, MSS, or
TCP no delay option, the iperf3 server destroys the socket it was
using to listen for the control connection and opens up a new
listening socket for the test's data connections.  This is (I think)
to make sure that the data connections all have the correct TCP
parameters.

When we re-create the listening socket, we also need to go through
the binding logic again (with all of the address family selectiion,
etc. goop).  The bug fixes that were a part of issue #193 need to
be ported to this code as well.

This problem only affects TCP tests, because for other protocols,
the listening socket for data cannot be the same listening sock as
for the control connection.

While here, add some comments so anybody trying to understand this
code will have an easier time.

Based on patch by:	@i2aaron
(cherry picked from commit eb1cfe5)

Signed-off-by: Bruce A. Mah <bmah@es.net>
@bmah888
Copy link
Contributor

bmah888 commented Aug 1, 2014

Close this for now. I hope we fixed this for good this time.

@bmah888 bmah888 closed this as completed Aug 1, 2014
jijianwen added a commit to jijianwen/iperf that referenced this issue Mar 13, 2018
Got the following error when running server side with -B option:

Server side:
    ./iperf3 -s -B <server_ipv4_address>
    -----------------------------------------------------------
    Server listening on 5201
    -----------------------------------------------------------
    iperf3: error - unable to start stream listener: Bad file descriptor
    -----------------------------------------------------------

Client side:
    ./iperf3 -c <server_ipv4_address> --sctp
    iperf3: error - unable to start stream listener: No such file or directory

Similar fix as below for TCP:
    commit eb1cfe5
    Author: Bruce A. Mah <bmah@es.net>
    Date:   Fri Aug 1 16:24:14 2014 -0700

        Another iteration on issue esnet#193, fixes -B with some TCP tests.

Signed-off-by: Jianwen Ji <jijianwen@gmail.com>
bmah888 pushed a commit that referenced this issue Mar 23, 2018
Got the following error when running server side with -B option:

Server side:
    ./iperf3 -s -B <server_ipv4_address>
    -----------------------------------------------------------
    Server listening on 5201
    -----------------------------------------------------------
    iperf3: error - unable to start stream listener: Bad file descriptor
    -----------------------------------------------------------

Client side:
    ./iperf3 -c <server_ipv4_address> --sctp
    iperf3: error - unable to start stream listener: No such file or directory

Similar fix as below for TCP:
    commit eb1cfe5
    Author: Bruce A. Mah <bmah@es.net>
    Date:   Fri Aug 1 16:24:14 2014 -0700

        Another iteration on issue #193, fixes -B with some TCP tests.

Signed-off-by: Jianwen Ji <jijianwen@gmail.com>
palmerc pushed a commit to palmerc/iperf that referenced this issue Jul 8, 2018
Got the following error when running server side with -B option:

Server side:
    ./iperf3 -s -B <server_ipv4_address>
    -----------------------------------------------------------
    Server listening on 5201
    -----------------------------------------------------------
    iperf3: error - unable to start stream listener: Bad file descriptor
    -----------------------------------------------------------

Client side:
    ./iperf3 -c <server_ipv4_address> --sctp
    iperf3: error - unable to start stream listener: No such file or directory

Similar fix as below for TCP:
    commit eb1cfe5
    Author: Bruce A. Mah <bmah@es.net>
    Date:   Fri Aug 1 16:24:14 2014 -0700

        Another iteration on issue esnet#193, fixes -B with some TCP tests.

Signed-off-by: Jianwen Ji <jijianwen@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants