diff options
author | Jef Poskanzer <jef@mail.acme.com> | 2013-03-29 17:49:27 -0700 |
---|---|---|
committer | Jef Poskanzer <jef@mail.acme.com> | 2013-03-29 17:49:27 -0700 |
commit | a6b3f26be128cbeaccb736151e2d864a1a63ee61 (patch) | |
tree | 92045e93208b0e1cdc6d3cbbb4fad90c268fbc6b /src/net.c | |
parent | 5bafe6e6cf32b4d618729872e4eb8f43b7af97d5 (diff) | |
download | iperf3-a6b3f26be128cbeaccb736151e2d864a1a63ee61.tar.gz |
Dual-stack operation - IPv4 and IP46 in the same server.
Also added -4 flag to force IPv4.
Diffstat (limited to 'src/net.c')
-rw-r--r-- | src/net.c | 74 |
1 files changed, 43 insertions, 31 deletions
@@ -44,45 +44,38 @@ int netdial(int domain, int proto, char *local, char *server, int port) { + struct addrinfo hints, *local_res, *server_res; int s; - struct addrinfo hints, *res; - - s = socket(domain, proto, 0); - if (s < 0) { - return -1; - } if (local) { memset(&hints, 0, sizeof(hints)); hints.ai_family = domain; hints.ai_socktype = proto; - - // XXX: Check getaddrinfo for errors! - if (getaddrinfo(local, NULL, &hints, &res) != 0) + if (getaddrinfo(local, NULL, &hints, &local_res) != 0) return -1; - - if (bind(s, (struct sockaddr *) res->ai_addr, res->ai_addrlen) < 0) - return -1; - - freeaddrinfo(res); } memset(&hints, 0, sizeof(hints)); hints.ai_family = domain; hints.ai_socktype = proto; - - // XXX: Check getaddrinfo for errors! - if (getaddrinfo(server, NULL, &hints, &res) != 0) + if (getaddrinfo(server, NULL, &hints, &server_res) != 0) return -1; - ((struct sockaddr_in *) res->ai_addr)->sin_port = htons(port); - - if (connect(s, (struct sockaddr *) res->ai_addr, res->ai_addrlen) < 0 && errno != EINPROGRESS) { + s = socket(server_res->ai_family, proto, 0); + if (s < 0) return -1; + + if (local) { + if (bind(s, (struct sockaddr *) local_res->ai_addr, local_res->ai_addrlen) < 0) + return -1; + freeaddrinfo(local_res); } - freeaddrinfo(res); + ((struct sockaddr_in *) server_res->ai_addr)->sin_port = htons(port); + if (connect(s, (struct sockaddr *) server_res->ai_addr, server_res->ai_addrlen) < 0 && errno != EINPROGRESS) + return -1; + freeaddrinfo(server_res); return s; } @@ -91,26 +84,32 @@ netdial(int domain, int proto, char *local, char *server, int port) int netannounce(int domain, int proto, char *local, int port) { - int s, opt; struct addrinfo hints, *res; char portstr[6]; - - s = socket(domain, proto, 0); - if (s < 0) { - return -1; - } - opt = 1; - setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *) &opt, sizeof(opt)); + int s, opt; snprintf(portstr, 6, "%d", port); memset(&hints, 0, sizeof(hints)); - hints.ai_family = domain; + hints.ai_family = (domain == AF_UNSPEC ? AF_INET6 : domain); hints.ai_socktype = proto; hints.ai_flags = AI_PASSIVE; - // XXX: Check getaddrinfo for errors! if (getaddrinfo(local, portstr, &hints, &res) != 0) return -1; + s = socket(res->ai_family, proto, 0); + if (s < 0) + return -1; + + opt = 1; + setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *) &opt, sizeof(opt)); + if (domain == AF_UNSPEC || domain == AF_INET6) { + if (domain == AF_UNSPEC) + opt = 0; + else if (domain == AF_INET6) + opt = 1; + setsockopt(s, SOL_SOCKET, IPV6_V6ONLY, (char *) &opt, sizeof(opt)); + } + if (bind(s, (struct sockaddr *) res->ai_addr, res->ai_addrlen) < 0) { close(s); return -1; @@ -357,3 +356,16 @@ setnonblocking(int fd, int nonblocking) } return 0; } + +/****************************************************************************/ + +int +getsockdomain(int sock) +{ + struct sockaddr sa; + socklen_t len; + + if (getsockname(sock, &sa, &len) < 0) + return -1; + return sa.sa_family; +} |