commit de04aa6bfa9f2d49b7540b6c3558ebba4c863bbd
Author: Jan Tluka <jtluka(a)redhat.com>
Date: Tue Dec 10 17:30:06 2013 +0100
tcp_con: add support for ipv6
The tcp_conn test tools are now capable of ipv6 connections. Simply pass -6
parameter to the tool to enable it, e.g.
./tcp_listen -a fe01::1 -p 10000-10050 -6
Same goes for client program, tcp_listen,
./tcp_connect -a fe01::1 -p 10000-10050 -6
Signed-off-by: Jan Tluka <jtluka(a)redhat.com>
Signed-off-by: Jiri Pirko <jiri(a)resnulli.us>
test_tools/tcp_conn/tcp_connect.c | 54 +++++++++++++++++-----
test_tools/tcp_conn/tcp_listen.c | 91 ++++++++++++++++++++++++++++++-------
2 files changed, 118 insertions(+), 27 deletions(-)
---
diff --git a/test_tools/tcp_conn/tcp_connect.c b/test_tools/tcp_conn/tcp_connect.c
index fe351a6..3bb4597 100644
--- a/test_tools/tcp_conn/tcp_connect.c
+++ b/test_tools/tcp_conn/tcp_connect.c
@@ -31,7 +31,7 @@ sem_t *mutex;
int usage()
{
- printf("./tcp_connect -p [port_range] -a [ipaddr]\n");
+ printf("./tcp_connect -p [port_range] -a [ipaddr] [-d] [-c] [-6]\n");
return 0;
}
@@ -52,34 +52,61 @@ void terminate_connections(int p)
*term_flag = 1;
}
-int handle_connections(char* host, int port)
+int handle_connections(char* host, int port, int ipv6)
{
int conn_sock;
struct sockaddr_in my_addr;
+ struct sockaddr_in6 my_addr6;
char data[] = "abcdefghijklmnopqrstuvwxyz0123456789";
char buf[21*10*strlen(data)+1];
+ int family;
snprintf(msg, MSG_MAX, "Starting connection on %s port %i", host, port);
debug(msg);
- my_addr.sin_family = AF_INET;
- my_addr.sin_port = htons(port);
- if (inet_aton(host, &(my_addr.sin_addr)) == 0)
+ if (ipv6)
{
- printf("failed on inet_aton()\n");
- return 1;
+ family = my_addr6.sin6_family = AF_INET6;
+ my_addr6.sin6_port = htons(port);
+ if (inet_pton(AF_INET6, host, &my_addr6.sin6_addr) != 1) {
+ perror("fail on inet_pton");
+ return 1;
+ }
+ }
+ else
+ {
+ family = my_addr.sin_family = AF_INET;
+ my_addr.sin_port = htons(port);
+ if (inet_aton(host, &(my_addr.sin_addr)) == 0)
+ {
+ printf("failed on inet_aton()\n");
+ return 1;
+ }
}
do
{
- conn_sock = socket(AF_INET, SOCK_STREAM, 0);
+ conn_sock = socket(family, SOCK_STREAM, 0);
if (conn_sock == -1)
{
perror("fail on socket()");
return 1;
}
- if (connect(conn_sock, (struct sockaddr*) &my_addr, sizeof(struct sockaddr_in)) == -1)
+ struct sockaddr* sa;
+ socklen_t sa_len;
+ if (ipv6)
+ {
+ sa = (struct sockaddr*) &my_addr6;
+ sa_len = sizeof(struct sockaddr_in6);
+ }
+ else
+ {
+ sa = (struct sockaddr*) &my_addr;
+ sa_len = sizeof(struct sockaddr_in);
+ }
+
+ if (connect(conn_sock, sa, sa_len) == -1)
{
perror("fail on connect");
return 1;
@@ -137,6 +164,7 @@ int main(int argc, char **argv)
char *delimiter;
struct sigaction sa;
int shm;
+ int ipv6 = 0;
term_flag = mmap(NULL, sizeof *term_flag, PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_ANONYMOUS, -1, 0);
@@ -179,7 +207,7 @@ int main(int argc, char **argv)
handlers_count = 0;
/* collect program args */
- while ((opt = getopt(argc, argv, "p:a:dc")) != -1) {
+ while ((opt = getopt(argc, argv, "p:a:dc6")) != -1) {
switch (opt) {
case 'p':
strncpy(port_str, optarg, 256);
@@ -188,6 +216,7 @@ int main(int argc, char **argv)
if (delimiter == NULL)
{
usage();
+ return 1;
}
strncpy(str_port_start, port_str, delimiter - port_str);
str_port_start[delimiter - port_str] = '\0';
@@ -205,6 +234,9 @@ int main(int argc, char **argv)
case 'c':
cont = 1;
break;
+ case '6':
+ ipv6 = 1;
+ break;
}
}
@@ -227,7 +259,7 @@ int main(int argc, char **argv)
sa.sa_handler = SIG_DFL;
sigaction(SIGTERM, &sa, NULL);
sigaction(SIGINT, &sa, NULL);
- handle_connections(host_str, p);
+ handle_connections(host_str, p, ipv6);
return 0;
}
}
diff --git a/test_tools/tcp_conn/tcp_listen.c b/test_tools/tcp_conn/tcp_listen.c
index 2fc77f6..7a292fe 100644
--- a/test_tools/tcp_conn/tcp_listen.c
+++ b/test_tools/tcp_conn/tcp_listen.c
@@ -31,7 +31,7 @@ sem_t *mutex;
int usage()
{
- printf("./tcp_listen -p [port_range] -a [ipaddr]\n");
+ printf("./tcp_listen -p [port_range] -a [ipaddr] [-d] [-c] [-6]\n");
return 0;
}
@@ -52,42 +52,77 @@ void terminate_connections(int p)
*term_flag = 1;
}
-int handle_connections(char* host, int port)
+int handle_connections(char* host, int port, int ipv6)
{
int listen_sock;
struct sockaddr_in my_addr;
+ struct sockaddr_in6 my_addr6;
socklen_t my_addr_size = sizeof(my_addr);
+ socklen_t my_addr6_size = sizeof(my_addr6);
int remote_sock;
struct sockaddr_in remote;
+ struct sockaddr_in6 remote6;
socklen_t remote_size = sizeof(remote);
+ socklen_t remote6_size = sizeof(remote6);
char data[256];
+ int family;
snprintf(msg, MSG_MAX, "Starting listener on %s port %i", host, port);
debug(msg);
- bzero(&my_addr, my_addr_size);
- my_addr.sin_family = AF_INET;
- my_addr.sin_port = htons(port);
- if (inet_aton(host, &(my_addr.sin_addr)) == 0)
+ if (ipv6)
{
- printf("failed on inet_aton()\n");
- return 1;
+ family = AF_INET6;
+ bzero(&my_addr6, my_addr6_size);
+ my_addr6.sin6_family = family;
+ my_addr6.sin6_port = htons(port);
+ if (inet_pton(AF_INET6, host, &(my_addr6.sin6_addr)) != 1)
+ {
+ printf("failed on inet_pton()\n");
+ return 1;
+ }
+ }
+ else
+ {
+ family = AF_INET;
+ bzero(&my_addr, my_addr_size);
+ my_addr.sin_family = family;
+ my_addr.sin_port = htons(port);
+ if (inet_aton(host, &(my_addr.sin_addr)) == 0)
+ {
+ printf("failed on inet_aton()\n");
+ return 1;
+ }
}
- if ((listen_sock = socket(AF_INET, SOCK_STREAM, 0)) == -1)
+ if ((listen_sock = socket(family, SOCK_STREAM, 0)) == -1)
{
perror("fail on socket creation");
return 1;
}
int on = 1;
- if (setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR, (const char*) &on, sizeof(on)) == -1)
+ if (setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR, (const char*) &on,
+ sizeof(on)) == -1)
{
perror("fail on setsockopt");
return 1;
}
- if (bind(listen_sock, (struct sockaddr*) &my_addr, sizeof(struct sockaddr_in)))
+ struct sockaddr* sa;
+ socklen_t sa_len;
+ if (ipv6)
+ {
+ sa = (struct sockaddr*) &my_addr6;
+ sa_len = my_addr6_size;
+ }
+ else
+ {
+ sa = (struct sockaddr*) &my_addr;
+ sa_len = my_addr_size;
+ }
+
+ if (bind(listen_sock, sa, sa_len))
{
perror("fail on bind");
return 1;
@@ -102,12 +137,27 @@ int handle_connections(char* host, int port)
do
{
struct in_addr ra = remote.sin_addr;
+ struct in6_addr ra6 = remote6.sin6_addr;
char host_address_str[256];
ssize_t read_rc;
+ struct sockaddr* r_sockaddr;
+ socklen_t* r_sockaddr_size;
+
+ if (ipv6)
+ {
+ bzero(&remote6, remote6_size);
+ r_sockaddr = (struct sockaddr*) &remote6;
+ r_sockaddr_size = &remote6_size;
+ }
+ else
+ {
+ bzero(&remote, remote_size);
+ r_sockaddr = (struct sockaddr*) &remote;
+ r_sockaddr_size = &remote_size;
+ }
/* handle single connection */
- bzero(&remote, remote_size);
- remote_sock = accept(listen_sock, (struct sockaddr*) &remote, &remote_size);
+ remote_sock = accept(listen_sock, r_sockaddr, r_sockaddr_size);
if (remote_sock == -1)
{
perror("failure on accept");
@@ -119,8 +169,11 @@ int handle_connections(char* host, int port)
*connection_count += 1;
sem_post(mutex);
+ if (ipv6)
+ inet_ntop(AF_INET6, &ra6, host_address_str, 255);
+ else
+ inet_ntop(AF_INET, &ra, host_address_str, 255);
- inet_ntop(AF_INET, &ra, host_address_str, 255);
snprintf(msg, MSG_MAX, "accepted connection from host %s port %i", host_address_str, port);
debug(msg);
@@ -155,6 +208,7 @@ int main(int argc, char **argv)
struct sigaction sa;
struct sigaction sa2;
int shm;
+ int ipv6 = 0;
term_flag = mmap(NULL, sizeof *term_flag, PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_ANONYMOUS, -1, 0);
@@ -196,7 +250,7 @@ int main(int argc, char **argv)
sigaction(SIGINT, &sa, NULL);
/* collect program args */
- while ((opt = getopt(argc, argv, "p:a:dc")) != -1) {
+ while ((opt = getopt(argc, argv, "p:a:dc6")) != -1) {
switch (opt) {
case 'p':
strncpy(port_str, optarg, 256);
@@ -205,6 +259,7 @@ int main(int argc, char **argv)
if (delimiter == NULL)
{
usage();
+ return 1;
}
strncpy(str_port_start, port_str, delimiter - port_str);
str_port_start[delimiter - port_str] = '\0';
@@ -221,6 +276,10 @@ int main(int argc, char **argv)
break;
case 'c':
cont = 1;
+ break;
+ case '6':
+ ipv6 = 1;
+ break;
}
}
@@ -246,7 +305,7 @@ int main(int argc, char **argv)
sigaction(SIGINT, &sa, NULL);
/* run the main processing loop */
- handle_connections(host_str, p);
+ handle_connections(host_str, p, ipv6);
return 0;
}
}