157 lines
5.7 KiB
Diff
157 lines
5.7 KiB
Diff
commit 95078ef12ab30735b4280675837c64686cf9faaa
|
|
Author: Michał Kępień <github@kempniu.pl>
|
|
Date: Wed Sep 26 22:31:36 2018 +0200
|
|
|
|
Support connecting to IPv6 servers
|
|
|
|
diff --git a/KNOWN_BUGS b/KNOWN_BUGS
|
|
index 79d94f9..8e93843 100644
|
|
--- a/KNOWN_BUGS
|
|
+++ b/KNOWN_BUGS
|
|
@@ -1,2 +1 @@
|
|
-No IPv6 Support
|
|
Currently Leak Resolver Objects Due To Messy Allocation Path
|
|
diff --git a/loudmouth/lm-old-socket.c b/loudmouth/lm-old-socket.c
|
|
index eb7b31c..ab44f76 100644
|
|
--- a/loudmouth/lm-old-socket.c
|
|
+++ b/loudmouth/lm-old-socket.c
|
|
@@ -20,6 +20,7 @@
|
|
|
|
#include <config.h>
|
|
|
|
+#include <errno.h>
|
|
#include <string.h>
|
|
#include <sys/types.h>
|
|
|
|
@@ -605,7 +606,22 @@ socket_do_connect (LmConnectData *connect_data)
|
|
port = htons (socket->port);
|
|
}
|
|
|
|
- ((struct sockaddr_in *) addr->ai_addr)->sin_port = port;
|
|
+ switch (addr->ai_family) {
|
|
+ case AF_INET:
|
|
+ ((struct sockaddr_in *) addr->ai_addr)->sin_port = port;
|
|
+ break;
|
|
+ case AF_INET6:
|
|
+ ((struct sockaddr_in6 *) addr->ai_addr)->sin6_port = port;
|
|
+ break;
|
|
+ default:
|
|
+ g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_VERBOSE,
|
|
+ "Unknown socket family %d\n", addr->ai_family);
|
|
+#ifndef G_OS_WIN32
|
|
+ return _lm_old_socket_failed_with_error (connect_data, EAFNOSUPPORT);
|
|
+#else
|
|
+ return _lm_old_socket_failed_with_error (connect_data, WSAEAFNOSUPPORT);
|
|
+#endif
|
|
+ }
|
|
|
|
res = getnameinfo (addr->ai_addr,
|
|
(socklen_t)addr->ai_addrlen,
|
|
@@ -765,46 +781,48 @@ old_socket_resolver_host_cb (LmResolver *resolver,
|
|
{
|
|
LmOldSocket *socket = (LmOldSocket *) user_data;
|
|
char dispbuf[128];
|
|
- struct sockaddr_in *addr; /* FIXME:IPv6 */
|
|
- const char *converr;
|
|
+ struct addrinfo *addr;
|
|
+ void *sock_addr;
|
|
|
|
lm_verbose ("LmOldSocket::host_cb (result=%d)\n", result);
|
|
|
|
- if (result != LM_RESOLVER_RESULT_OK) {
|
|
- lm_verbose ("error while resolving, bailing out\n");
|
|
- if (socket->connect_func) {
|
|
- (socket->connect_func) (socket, FALSE, socket->user_data);
|
|
+ if (result == LM_RESOLVER_RESULT_OK) {
|
|
+ /* Find and use the first result with a supported address family */
|
|
+ while ((addr = lm_resolver_results_get_next (resolver))) {
|
|
+ switch (addr->ai_family) {
|
|
+ case AF_INET:
|
|
+ sock_addr = & (((struct sockaddr_in *) addr->ai_addr)->sin_addr);
|
|
+ break;
|
|
+ case AF_INET6:
|
|
+ sock_addr = & (((struct sockaddr_in6 *) addr->ai_addr)->sin6_addr);
|
|
+ break;
|
|
+ default:
|
|
+ g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_VERBOSE,
|
|
+ "Resolver returned a socket address with unknown family %d\n", addr->ai_family);
|
|
+ continue;
|
|
+ }
|
|
+ if (inet_ntop (addr->ai_family, sock_addr, dispbuf, sizeof(dispbuf))) {
|
|
+ g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_VERBOSE,
|
|
+ "Attempting Connection to %s\n", dispbuf);
|
|
+ } else {
|
|
+ g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_VERBOSE,
|
|
+ "Attempting Connection (unable to convert address to presentable format)\n");
|
|
+ };
|
|
+ socket->connect_data->current_addr = addr;
|
|
+ socket_do_connect (socket->connect_data);
|
|
+ return;
|
|
}
|
|
- /*FIXME: Leaking Resolvers Until Clean Up Can Be Properly Handled
|
|
- g_object_unref (socket->resolver);
|
|
- socket->resolver = NULL;*/
|
|
- g_free (socket->connect_data);
|
|
- socket->connect_data = NULL;
|
|
-
|
|
- return;
|
|
}
|
|
|
|
- socket->connect_data->current_addr =
|
|
- lm_resolver_results_get_next (resolver);
|
|
-
|
|
- if (socket->connect_data->current_addr) { /* FIXME:IPv6 */
|
|
- addr = (struct sockaddr_in *) (socket->connect_data->current_addr->ai_addr);
|
|
- converr = inet_ntop(AF_INET,&(addr->sin_addr),dispbuf,sizeof(dispbuf));
|
|
- if (converr) {
|
|
- g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_VERBOSE,
|
|
- "Attempting Connection to %s\n",dispbuf);
|
|
- } else {
|
|
- g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_VERBOSE,
|
|
- "Attempting Connection (unable to convert address to presentable format)\n");
|
|
- };
|
|
- socket_do_connect (socket->connect_data);
|
|
- } else { /* FIXME: IPv6 Support? */
|
|
- g_log (LM_LOG_DOMAIN,G_LOG_LEVEL_ERROR,
|
|
- "Unable to locate server available over IPv4.\n");
|
|
- };
|
|
-
|
|
- /* FIXME: What do we do here? How to make the mainloop exit with an
|
|
- error, while having no ref to said mainloop */
|
|
+ lm_verbose ("error while resolving, bailing out\n");
|
|
+ if (socket->connect_func) {
|
|
+ (socket->connect_func) (socket, FALSE, socket->user_data);
|
|
+ }
|
|
+ /*FIXME: Leaking Resolvers Until Clean Up Can Be Properly Handled
|
|
+ g_object_unref (socket->resolver);
|
|
+ socket->resolver = NULL;*/
|
|
+ g_free (socket->connect_data);
|
|
+ socket->connect_data = NULL;
|
|
}
|
|
|
|
/* FIXME: Need to have a way to only get srv reply and then decide if the
|
|
diff --git a/loudmouth/lm-resolver.c b/loudmouth/lm-resolver.c
|
|
index b9d7762..c44204b 100644
|
|
--- a/loudmouth/lm-resolver.c
|
|
+++ b/loudmouth/lm-resolver.c
|
|
@@ -390,7 +390,6 @@ lm_resolver_results_get_next (LmResolver *resolver)
|
|
|
|
priv = GET_PRIV (resolver);
|
|
|
|
-skipresult:
|
|
if (!priv->current_result) {
|
|
g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_VERBOSE,
|
|
"no more results from resolver\n");
|
|
@@ -399,11 +398,6 @@ skipresult:
|
|
|
|
ret_val = priv->current_result;
|
|
priv->current_result = priv->current_result->ai_next;
|
|
- if (ret_val->ai_family != AF_INET) {
|
|
- g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_VERBOSE,
|
|
- "skipping non-IPv4 resolver entry\n");
|
|
- goto skipresult;
|
|
- };
|
|
|
|
return ret_val;
|
|
}
|