From 32c33357d3404071ad95681cb8038eab3d80dc2f Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Wed, 23 Sep 2015 15:37:23 +0200 Subject: [PATCH] Respect the user preference Try to resolve the address using the user-specified ip version and fail gracefully if the network doesn't support it. --- src/core/chat-commands.c | 2 +- src/core/net-nonblock.c | 6 +++--- src/core/net-nonblock.h | 2 +- src/core/network.c | 9 +++++---- src/core/network.h | 2 +- src/core/servers-setup.c | 4 ++-- src/core/servers.c | 15 +++++++++------ src/irc/proxy/listen.c | 2 +- 8 files changed, 23 insertions(+), 19 deletions(-) diff --git a/src/core/chat-commands.c b/src/core/chat-commands.c index 9c28a1fc..9f7a0671 100644 --- a/src/core/chat-commands.c +++ b/src/core/chat-commands.c @@ -130,7 +130,7 @@ static SERVER_CONNECT_REC *get_server_connect(const char *data, int *plus_addr, if (host != NULL && *host != '\0') { IPADDR ip; - if (net_gethostbyname(host, &ip) == 0) + if (net_gethostbyname(host, &ip, conn->family) == 0) server_connect_own_ip_save(conn, &ip); } diff --git a/src/core/net-nonblock.c b/src/core/net-nonblock.c index bc8c4b96..50f48e42 100644 --- a/src/core/net-nonblock.c +++ b/src/core/net-nonblock.c @@ -73,7 +73,7 @@ static int g_io_channel_read_block(GIOChannel *channel, void *data, int len) /* nonblocking gethostbyname(), ip (IPADDR) + error (int, 0 = not error) is written to pipe when found PID of the resolver child is returned */ int net_gethostbyname_nonblock(const char *addr, GIOChannel *pipe, - int reverse_lookup) + int family, int reverse_lookup) { RESOLVED_IP_REC rec; const char *errorstr; @@ -103,7 +103,7 @@ int net_gethostbyname_nonblock(const char *addr, GIOChannel *pipe, srand(time(NULL)); memset(&rec, 0, sizeof(rec)); - rec.error = net_gethostbyname(addr, &rec.ip); + rec.error = net_gethostbyname(addr, &rec.ip, family); if (rec.error == 0) { errorstr = NULL; if (reverse_lookup) { @@ -267,7 +267,7 @@ int net_connect_nonblock(const char *server, int port, const IPADDR *my_ip, rec->pipes[1] = g_io_channel_new(fd[1]); /* start nonblocking host name lookup */ - net_gethostbyname_nonblock(server, rec->pipes[1], 0); + net_gethostbyname_nonblock(server, rec->pipes[1], 0, 0); rec->tag = g_input_add(rec->pipes[0], G_INPUT_READ, (GInputFunction) simple_readpipe, rec); diff --git a/src/core/net-nonblock.h b/src/core/net-nonblock.h index 581536b3..96ad06c3 100644 --- a/src/core/net-nonblock.h +++ b/src/core/net-nonblock.h @@ -26,7 +26,7 @@ typedef void (*NET_HOST_CALLBACK) (RESOLVED_NAME_REC *, void *); /* nonblocking gethostbyname(), PID of the resolver child is returned. */ int net_gethostbyname_nonblock(const char *addr, GIOChannel *pipe, - int reverse_lookup); + int family, int reverse_lookup); /* Get host's name, call func when finished */ int net_gethostbyaddr_nonblock(IPADDR *ip, NET_HOST_CALLBACK func, void *data); /* get the resolved IP address. returns -1 if some error occurred with read() */ diff --git a/src/core/network.c b/src/core/network.c index 303483c6..ec7aed6e 100644 --- a/src/core/network.c +++ b/src/core/network.c @@ -141,7 +141,8 @@ GIOChannel *net_connect(const char *addr, int port, IPADDR *my_ip) g_return_val_if_fail(addr != NULL, NULL); - if (net_gethostbyname(addr, &ip) == -1) + // XXX : should we use the my_ip->family instead ? + if (net_gethostbyname(addr, &ip, 0) == -1) return NULL; return net_connect_ip(&ip, port, my_ip); @@ -392,9 +393,9 @@ int net_getsockname(GIOChannel *handle, IPADDR *addr, int *port) /* Get IP addresses for host, both IPv4 and IPv6 if possible. If ip->family is 0, the address wasn't found. Returns 0 = ok, others = error code for net_gethosterror() */ -int net_gethostbyname(const char *addr, IPADDR *ip) +int net_gethostbyname(const char *addr, IPADDR *ip, int family) { - union sockaddr_union *so; + const union sockaddr_union *so; struct addrinfo hints, *ailist; int ret; @@ -405,7 +406,7 @@ int net_gethostbyname(const char *addr, IPADDR *ip) memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_socktype = SOCK_STREAM; #ifdef HAVE_IPV6 - hints.ai_family = AF_UNSPEC; + hints.ai_family = (family == 0) ? AF_UNSPEC : family; #else hints.ai_family = AF_INET; #endif diff --git a/src/core/network.h b/src/core/network.h index ea8b3055..1e1313a3 100644 --- a/src/core/network.h +++ b/src/core/network.h @@ -71,7 +71,7 @@ int net_transmit(GIOChannel *handle, const char *data, int len); /* Get IP addresses for host, both IPv4 and IPv6 if possible. If ip->family is 0, the address wasn't found. Returns 0 = ok, others = error code for net_gethosterror() */ -int net_gethostbyname(const char *addr, IPADDR *ip); +int net_gethostbyname(const char *addr, IPADDR *ip, int family); /* Get name for host, *name should be g_free()'d unless it's NULL. Return values are the same as with net_gethostbyname() */ int net_gethostbyaddr(IPADDR *ip, char **name); diff --git a/src/core/servers-setup.c b/src/core/servers-setup.c index e8506f0f..37cd5b8b 100644 --- a/src/core/servers-setup.c +++ b/src/core/servers-setup.c @@ -56,7 +56,7 @@ static void get_source_host_ip(void) /* FIXME: This will block! */ hostname = settings_get_str("hostname"); source_host_ok = *hostname != '\0' && - net_gethostbyname(hostname, &source_host_ip) == 0; + net_gethostbyname(hostname, &source_host_ip, 0) == 0; } static void conn_set_ip(SERVER_CONNECT_REC *conn, const char *own_host, @@ -66,7 +66,7 @@ static void conn_set_ip(SERVER_CONNECT_REC *conn, const char *own_host, if (*own_ip == NULL) { /* resolve the IP */ - if (net_gethostbyname(own_host, &ip) == 0) + if (net_gethostbyname(own_host, &ip, 0) == 0) save_ips(&ip, own_ip); } diff --git a/src/core/servers.c b/src/core/servers.c index 66060a7f..f8efd62f 100644 --- a/src/core/servers.c +++ b/src/core/servers.c @@ -283,12 +283,14 @@ static void server_connect_callback_readpipe(SERVER_REC *server) ip = NULL; if (iprec.error == 0) { - // FIXME : REMOVE THIS BEFORE MERGE - if (server->connrec->family) - g_assert(server->connrec->family == iprec.ip.family); - - ip = &iprec.ip; - servername = iprec.host; + /* we've resolved the server address, now check whether the version + * of the one returned by the system matches the one required by the + * user by using -{4,6} or by specifying the "family" parameter for + * the server */ + if (server->connrec->family == 0 || server->connrec->family == iprec.ip.family) { + ip = &iprec.ip; + servername = iprec.host; + } } if (ip != NULL) { @@ -407,6 +409,7 @@ int server_start_connect(SERVER_REC *server) server->connect_pid = net_gethostbyname_nonblock(connect_address, server->connect_pipe[1], + server->connrec->family, settings_get_bool("resolve_reverse_lookup")); server->connect_tag = g_input_add(server->connect_pipe[0], G_INPUT_READ, diff --git a/src/irc/proxy/listen.c b/src/irc/proxy/listen.c index 16950c79..27c7a0f2 100644 --- a/src/irc/proxy/listen.c +++ b/src/irc/proxy/listen.c @@ -593,7 +593,7 @@ static void add_listen(const char *ircnet, int port) /* bind to specific host/ip? */ my_ip = NULL; if (*settings_get_str("irssiproxy_bind") != '\0') { - if (net_gethostbyname(settings_get_str("irssiproxy_bind"), &ip) != 0) { + if (net_gethostbyname(settings_get_str("irssiproxy_bind"), &ip, 0) != 0) { printtext(NULL, NULL, MSGLEVEL_CLIENTERROR, "Proxy: can not resolve '%s' - aborting", settings_get_str("irssiproxy_bind"));