From e4e17ce862f99e5c8a8378b72cb55bba5d82a0eb Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Sat, 13 Feb 2016 00:38:35 +0000 Subject: [PATCH] Improve IPv6 portability and consistency After discussions with Greg N1DAM I have changed the dual stack support to explicitly allow IPv4 connections mapped to IPv6 for any AF_INET6 address since BSD as well as Windows defaults this socket option to on (disallowed). IPv4 mapped to IPv6 makes sense for Hamlib servers since starting two servers one for each protocol family (the other option) is not possible since there is only a single rig/rotator which cannot be shared between two servers. --- tests/rigctld.c | 24 +++++++++++++++--------- tests/rotctld.c | 25 ++++++++++++++++--------- 2 files changed, 31 insertions(+), 18 deletions(-) diff --git a/tests/rigctld.c b/tests/rigctld.c index 51e080920..601d27ac1 100644 --- a/tests/rigctld.c +++ b/tests/rigctld.c @@ -169,6 +169,7 @@ int main (int argc, char *argv[]) struct addrinfo hints, *result, *saved_result; int sock_listen; + int sockopt; int reuseaddr = 1; char host[NI_MAXHOST]; char serv[NI_MAXSERV]; @@ -402,7 +403,7 @@ int main (int argc, char *argv[]) exit(1); } - int sockopt = SO_SYNCHRONOUS_NONALERT; + sockopt = SO_SYNCHRONOUS_NONALERT; setsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE, (char *)&sockopt, sizeof(sockopt)); #endif @@ -439,14 +440,17 @@ int main (int argc, char *argv[]) exit (1); } -#if defined(__MINGW32__) && HAVE_WS2TCPIP_H - /* allow IPv4 mapped to IPv6 clients, MS default this to 1! */ - sockopt = 0; - if (setsockopt(sock_listen, IPPROTO_IPV6, IPV6_V6ONLY, - (char *)&sockopt, sizeof(sockopt)) < 0) { - handle_error (RIG_DEBUG_ERR, "setsockopt"); - freeaddrinfo(saved_result); /* No longer needed */ - exit (1); +#ifdef IPV6_V6ONLY + if (AF_INET6 == result->ai_family) { + /* allow IPv4 mapped to IPv6 clients Windows and BSD default + this to 1 (i.e. disallowed) and we prefer it off */ + sockopt = 0; + if (setsockopt(sock_listen, IPPROTO_IPV6, IPV6_V6ONLY, + (char *)&sockopt, sizeof(sockopt)) < 0) { + handle_error (RIG_DEBUG_ERR, "setsockopt"); + freeaddrinfo(saved_result); /* No longer needed */ + exit (1); + } } #endif @@ -588,7 +592,9 @@ void * handle_socket(void *arg) host, serv); fclose(fsockin); +#ifndef __MINGW32__ fclose(fsockout); +#endif handle_exit: #ifdef __MINGW32__ diff --git a/tests/rotctld.c b/tests/rotctld.c index d5a5263c2..95f23d8e1 100644 --- a/tests/rotctld.c +++ b/tests/rotctld.c @@ -158,6 +158,7 @@ int main (int argc, char *argv[]) struct addrinfo hints, *result, *saved_result; int sock_listen; int reuseaddr = 1; + int sockopt; char host[NI_MAXHOST]; char serv[NI_MAXSERV]; @@ -314,7 +315,7 @@ int main (int argc, char *argv[]) exit(1); } - int sockopt = SO_SYNCHRONOUS_NONALERT; + sockopt = SO_SYNCHRONOUS_NONALERT; setsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE, (char *)&sockopt, sizeof(sockopt)); #endif @@ -352,14 +353,17 @@ int main (int argc, char *argv[]) exit (1); } -#if defined(__MINGW32__) && HAVE_WS2TCPIP_H - /* allow IPv4 mapped to IPv6 clients, MS default this to 1! */ - sockopt = 0; - if (setsockopt(sock_listen, IPPROTO_IPV6, IPV6_V6ONLY, - (char *)&sockopt, sizeof(sockopt)) < 0) { - handle_error (RIG_DEBUG_ERR, "setsockopt"); - freeaddrinfo(saved_result); /* No longer needed */ - exit (1); +#ifdef IPV6_V6ONLY + if (AF_INET6 == result->ai_family) { + /* allow IPv4 mapped to IPv6 clients, MS & BSD default this + to 1 i.e. disallowed */ + sockopt = 0; + if (setsockopt(sock_listen, IPPROTO_IPV6, IPV6_V6ONLY, + (char *)&sockopt, sizeof(sockopt)) < 0) { + handle_error (RIG_DEBUG_ERR, "setsockopt"); + freeaddrinfo(saved_result); /* No longer needed */ + exit (1); + } } #endif @@ -501,7 +505,10 @@ void * handle_socket(void *arg) host, serv); fclose(fsockin); +#ifndef __MINGW32__ fclose(fsockout); +#endif + handle_exit: #ifdef __MINGW32__ closesocket(handle_data_arg->sock);