4343#include <unistd.h>
4444#include <arpa/inet.h>
4545#include <netinet/in.h>
46+ #include <stdbool.h>
4647#include "qperf.h"
4748
48-
4949/*
5050 * Parameters.
5151 */
@@ -107,7 +107,7 @@ static void rds_makeaddr(SS *addr, socklen_t *len, char *host, int port);
107107static void set_parameters (long msgSize );
108108static void server_get_hosts (char * lhost , char * rhost );
109109static void set_socket_buffer_size (int fd );
110-
110+ static inline bool ipv6_addr_v4mapped ( const struct in6_addr * a );
111111
112112/*
113113 * Static variables.
@@ -314,6 +314,15 @@ init(void)
314314}
315315
316316
317+ /*
318+ * Check if it is IPv4-mapped IPv6 address
319+ */
320+ static inline bool ipv6_addr_v4mapped (const struct in6_addr * a )
321+ {
322+ return (a -> s6_addr32 [0 ] | a -> s6_addr32 [1 ] |
323+ (a -> s6_addr32 [2 ] ^ htonl (0x0000ffff ))) == 0 ;
324+ }
325+
317326/*
318327 * Have an exchange with the client over TCP/IP and get the IP of our local
319328 * host.
@@ -323,34 +332,42 @@ server_get_hosts(char *lhost, char *rhost)
323332{
324333 int fd , lfd ;
325334 uint32_t port ;
326- struct sockaddr_in laddr , raddr ;
327335 socklen_t rlen ;
336+ struct sockaddr_in6 v6addr ;
337+ struct sockaddr_in v4addr ;
338+ SA * raddr ;
328339
329- lfd = socket (AF_INET , SOCK_STREAM , 0 );
340+ lfd = socket (AF_INET6 , SOCK_STREAM , 0 );
330341 if (lfd < 0 )
331342 error (SYS , "socket failed" );
332343 setsockopt_one (lfd , SO_REUSEADDR );
333-
334- memset (& laddr , 0 , sizeof (laddr ));
335- laddr .sin_family = AF_INET ;
336- laddr .sin_addr .s_addr = INADDR_ANY ;
337- laddr .sin_port = htons (0 );
338- if (bind (lfd , (SA * )& laddr , sizeof (laddr )) < 0 )
339- error (SYS , "bind INET failed" );
344+ memset (& v6addr , 0 , sizeof (v6addr ));
345+ v6addr .sin6_family = AF_INET6 ;
346+ if (bind (lfd , (SA * )& v6addr , sizeof (v6addr )) < 0 )
347+ error (SYS , "bind INET6 failed" );
340348
341349 port = get_socket_port (lfd );
342350 encode_uint32 (& port , port );
343- send_mesg (& port , sizeof (port ), "TCP IPv4 server port" );
344-
351+ send_mesg (& port , sizeof (port ), "TCP server port" );
345352 if (listen (lfd , 1 ) < 0 )
346353 error (SYS , "listen failed" );
347354
348- rlen = sizeof (raddr );
349- fd = accept (lfd , (SA * )& raddr , & rlen );
355+ rlen = sizeof (v6addr );
356+ fd = accept (lfd , (SA * )& v6addr , & rlen );
350357 if (fd < 0 )
351358 error (SYS , "accept failed" );
352359 close (lfd );
353- get_socket_ip ((SA * )& raddr , rlen , rhost , NI_MAXHOST );
360+
361+ if (ipv6_addr_v4mapped (& v6addr .sin6_addr )) {
362+ v4addr .sin_family = AF_INET ;
363+ v4addr .sin_addr .s_addr = v6addr .sin6_addr .s6_addr32 [3 ];
364+ v4addr .sin_port = v6addr .sin6_port ;
365+ raddr = (SA * )& v4addr ;
366+ rlen = sizeof (v4addr );
367+ } else {
368+ raddr = (SA * )& v6addr ;
369+ }
370+ get_socket_ip (raddr , rlen , rhost , NI_MAXHOST );
354371 send_mesg (rhost , NI_MAXHOST , "client IP" );
355372 recv_mesg (lhost , NI_MAXHOST , "server IP" );
356373 close (fd );
@@ -410,13 +427,30 @@ rds_socket(char *host, int port)
410427static void
411428rds_makeaddr (SS * addr , socklen_t * len , char * host , int port )
412429{
430+ int stat ;
431+ struct addrinfo * ailist ;
413432 struct sockaddr_in * sap = (struct sockaddr_in * )addr ;
433+ struct sockaddr_in6 * sap6 = (struct sockaddr_in6 * )addr ;
414434
435+ stat = getaddrinfo (host , NULL , NULL , & ailist );
436+ if (stat != 0 )
437+ error (0 , "getaddrinfo failed: %s" , gai_strerror (stat ));
438+ switch (ailist -> ai_family ) {
439+ case AF_INET :
415440 memset (sap , 0 , sizeof (* sap ));
416- sap -> sin_family = AF_INET ;
417- inet_pton (AF_INET , host , & sap -> sin_addr .s_addr );
441+ memcpy (addr , ailist -> ai_addr , ailist -> ai_addrlen );
418442 sap -> sin_port = htons (port );
419443 * len = sizeof (struct sockaddr_in );
444+ break ;
445+ case AF_INET6 :
446+ memset (sap6 , 0 , sizeof (* sap6 ));
447+ memcpy (sap6 , ailist -> ai_addr , ailist -> ai_addrlen );
448+ sap6 -> sin6_port = htons (port );
449+ * len = sizeof (struct sockaddr_in6 );
450+ break ;
451+ default :
452+ error (0 , "Unsupported Address family" );
453+ }
420454}
421455
422456
@@ -431,7 +465,7 @@ connect_tcp(char *server, char *port, SS *addr, socklen_t *len, int *fd)
431465 struct addrinfo * aip , * ailist ;
432466 struct addrinfo hints = {
433467 .ai_flags = AI_NUMERICSERV ,
434- .ai_family = AF_INET ,
468+ .ai_family = AF_UNSPEC ,
435469 .ai_socktype = SOCK_STREAM
436470 };
437471
0 commit comments