kopia lustrzana https://github.com/Hamlib/Hamlib
Proper IPv6 and dual stack networking for rotator net daemon
This means that rigctl & rigctld now work with default arguments on a modern Windows machine with dual stack and localhost being [::1] as the first interface returned by getaddrinfo(). Try all the interfaces return by DNS lookups to establish a connection or listening port. Handle Windows network errors correctly so that meaningful messages are printed. The rigctl program now accepts IPv6 numeric addresses in the portname field like [<addr>}:<port> for example the IPv6 loopback on port 4531 would be [::1]:4531.libusb-1-0
rodzic
ca7cbd89f4
commit
6061cae8df
112
tests/rotctld.c
112
tests/rotctld.c
|
@ -68,7 +68,7 @@
|
||||||
struct handle_data {
|
struct handle_data {
|
||||||
ROT *rot;
|
ROT *rot;
|
||||||
int sock;
|
int sock;
|
||||||
struct sockaddr_in cli_addr;
|
struct sockaddr_storage cli_addr;
|
||||||
socklen_t clilen;
|
socklen_t clilen;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -111,6 +111,36 @@ char send_cmd_term = '\r'; /* send_cmd termination char */
|
||||||
#define MAXCONFLEN 128
|
#define MAXCONFLEN 128
|
||||||
|
|
||||||
|
|
||||||
|
static void handle_error (enum rig_debug_level_e lvl, const char *msg)
|
||||||
|
{
|
||||||
|
int e;
|
||||||
|
#ifdef __MINGW32__
|
||||||
|
LPVOID lpMsgBuf;
|
||||||
|
|
||||||
|
lpMsgBuf = (LPVOID)"Unknown error";
|
||||||
|
e = WSAGetLastError();
|
||||||
|
if (FormatMessage(
|
||||||
|
FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
||||||
|
FORMAT_MESSAGE_FROM_SYSTEM |
|
||||||
|
FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||||
|
NULL, e,
|
||||||
|
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||||
|
// Default language
|
||||||
|
(LPTSTR)&lpMsgBuf, 0, NULL))
|
||||||
|
{
|
||||||
|
rig_debug (lvl, "%s: Network error %d: %s\n", msg, e, lpMsgBuf);
|
||||||
|
LocalFree(lpMsgBuf);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rig_debug (lvl, "%s: Network error %d\n", msg, e);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
e = errno;
|
||||||
|
rig_debug (lvl, "%s: Network error %d: %s\n", msg, e, strerror (e));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
int main (int argc, char *argv[])
|
int main (int argc, char *argv[])
|
||||||
{
|
{
|
||||||
ROT *my_rot; /* handle to rot (instance) */
|
ROT *my_rot; /* handle to rot (instance) */
|
||||||
|
@ -125,9 +155,11 @@ int main (int argc, char *argv[])
|
||||||
int serial_rate = 0;
|
int serial_rate = 0;
|
||||||
char conf_parms[MAXCONFLEN] = "";
|
char conf_parms[MAXCONFLEN] = "";
|
||||||
|
|
||||||
struct addrinfo hints, *result;
|
struct addrinfo hints, *result, *saved_result;
|
||||||
int sock_listen;
|
int sock_listen;
|
||||||
int reuseaddr = 1;
|
int reuseaddr = 1;
|
||||||
|
char host[NI_MAXHOST];
|
||||||
|
char serv[NI_MAXSERV];
|
||||||
|
|
||||||
while(1) {
|
while(1) {
|
||||||
int c;
|
int c;
|
||||||
|
@ -301,27 +333,56 @@ int main (int argc, char *argv[])
|
||||||
exit(2);
|
exit(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
saved_result = result;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
sock_listen = socket(result->ai_family, result->ai_socktype,
|
sock_listen = socket(result->ai_family, result->ai_socktype,
|
||||||
result->ai_protocol);
|
result->ai_protocol);
|
||||||
if (sock_listen < 0) {
|
if (sock_listen < 0) {
|
||||||
perror("ERROR opening socket");
|
handle_error (RIG_DEBUG_ERR, "socket");
|
||||||
|
freeaddrinfo(result); /* No longer needed */
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (setsockopt(sock_listen, SOL_SOCKET, SO_REUSEADDR,
|
if (setsockopt(sock_listen, SOL_SOCKET, SO_REUSEADDR,
|
||||||
(char *)&reuseaddr,sizeof(reuseaddr)) < 0) {
|
(char *)&reuseaddr,sizeof(reuseaddr)) < 0) {
|
||||||
rig_debug(RIG_DEBUG_ERR, "setsockopt: %s\n", strerror(errno));
|
handle_error (RIG_DEBUG_ERR, "setsockopt");
|
||||||
exit (1);
|
|
||||||
}
|
|
||||||
if (bind(sock_listen, result->ai_addr, result->ai_addrlen) < 0) {
|
|
||||||
rig_debug(RIG_DEBUG_ERR, "binding: %s\n", strerror(errno));
|
|
||||||
exit (1);
|
|
||||||
}
|
|
||||||
|
|
||||||
freeaddrinfo(result); /* No longer needed */
|
freeaddrinfo(result); /* No longer needed */
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
|
||||||
if (listen(sock_listen,4) < 0) {
|
#ifdef __MINGW32__
|
||||||
rig_debug(RIG_DEBUG_ERR, "listening: %s\n", strerror(errno));
|
/* 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);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (0 == bind(sock_listen, result->ai_addr, result->ai_addrlen)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
handle_error (RIG_DEBUG_WARN, "binding failed (trying next interface)");
|
||||||
|
#ifdef __MINGW32__
|
||||||
|
closesocket (sock_listen);
|
||||||
|
#else
|
||||||
|
close (sock_listen);
|
||||||
|
#endif
|
||||||
|
} while ((result = result->ai_next) != NULL);
|
||||||
|
|
||||||
|
freeaddrinfo(saved_result); /* No longer needed */
|
||||||
|
if (NULL == result)
|
||||||
|
{
|
||||||
|
rig_debug(RIG_DEBUG_ERR, "bind error - no available interface\n");
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (listen(sock_listen, 4) < 0) {
|
||||||
|
handle_error (RIG_DEBUG_ERR, "listening");
|
||||||
exit (1);
|
exit (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -346,13 +407,17 @@ int main (int argc, char *argv[])
|
||||||
arg->sock = accept(sock_listen, (struct sockaddr *) &arg->cli_addr,
|
arg->sock = accept(sock_listen, (struct sockaddr *) &arg->cli_addr,
|
||||||
&arg->clilen);
|
&arg->clilen);
|
||||||
if (arg->sock < 0) {
|
if (arg->sock < 0) {
|
||||||
rig_debug(RIG_DEBUG_ERR, "accept: %s\n", strerror(errno));
|
handle_error (RIG_DEBUG_ERR, "accept");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
rig_debug(RIG_DEBUG_VERBOSE, "Connection opened from %s:%d\n",
|
if ((retcode = getnameinfo ((struct sockaddr const *)&arg->cli_addr, arg->clilen, host, sizeof (host)
|
||||||
inet_ntoa(arg->cli_addr.sin_addr),
|
, serv, sizeof (serv), NI_NOFQDN)) < 0)
|
||||||
ntohs(arg->cli_addr.sin_port));
|
{
|
||||||
|
rig_debug (RIG_DEBUG_WARN, "Peer lookup error: %s", gai_strerror (retcode));
|
||||||
|
}
|
||||||
|
rig_debug(RIG_DEBUG_VERBOSE, "Connection opened from %s:%s\n",
|
||||||
|
host, serv);
|
||||||
|
|
||||||
#ifdef HAVE_PTHREAD
|
#ifdef HAVE_PTHREAD
|
||||||
pthread_attr_init(&attr);
|
pthread_attr_init(&attr);
|
||||||
|
@ -389,6 +454,8 @@ void * handle_socket(void *arg)
|
||||||
FILE *fsockin;
|
FILE *fsockin;
|
||||||
FILE *fsockout;
|
FILE *fsockout;
|
||||||
int retcode;
|
int retcode;
|
||||||
|
char host[NI_MAXHOST];
|
||||||
|
char serv[NI_MAXSERV];
|
||||||
|
|
||||||
#ifdef __MINGW32__
|
#ifdef __MINGW32__
|
||||||
int sock_osfhandle = _open_osfhandle(handle_data_arg->sock, _O_RDONLY);
|
int sock_osfhandle = _open_osfhandle(handle_data_arg->sock, _O_RDONLY);
|
||||||
|
@ -424,9 +491,14 @@ void * handle_socket(void *arg)
|
||||||
}
|
}
|
||||||
while (retcode == 0 || retcode == 2);
|
while (retcode == 0 || retcode == 2);
|
||||||
|
|
||||||
rig_debug(RIG_DEBUG_VERBOSE, "Connection closed from %s:%d\n",
|
if ((retcode = getnameinfo ((struct sockaddr const *)&handle_data_arg->cli_addr
|
||||||
inet_ntoa(handle_data_arg->cli_addr.sin_addr),
|
, handle_data_arg->clilen, host, sizeof (host)
|
||||||
ntohs(handle_data_arg->cli_addr.sin_port));
|
, serv, sizeof (serv), NI_NOFQDN)) < 0)
|
||||||
|
{
|
||||||
|
rig_debug (RIG_DEBUG_WARN, "Peer lookup error: %s", gai_strerror (retcode));
|
||||||
|
}
|
||||||
|
rig_debug(RIG_DEBUG_VERBOSE, "Connection closed from %s:%s\n",
|
||||||
|
host, serv);
|
||||||
|
|
||||||
fclose(fsockin);
|
fclose(fsockin);
|
||||||
fclose(fsockout);
|
fclose(fsockout);
|
||||||
|
|
Ładowanie…
Reference in New Issue