diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/core/net-nonblock.c | 44 | ||||
-rw-r--r-- | src/core/net-nonblock.h | 4 | ||||
-rw-r--r-- | src/core/servers.c | 26 |
3 files changed, 66 insertions, 8 deletions
diff --git a/src/core/net-nonblock.c b/src/core/net-nonblock.c index 6af87a96..ce6be49a 100644 --- a/src/core/net-nonblock.c +++ b/src/core/net-nonblock.c @@ -73,13 +73,15 @@ 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 net_gethostbyname_nonblock(const char *addr, GIOChannel *pipe, + int reverse_lookup) { RESOLVED_IP_REC rec; const char *errorstr; #ifndef WIN32 int pid; #endif + int len; g_return_val_if_fail(addr != NULL, FALSE); @@ -103,6 +105,13 @@ int net_gethostbyname_nonblock(const char *addr, GIOChannel *pipe) rec.error = net_gethostbyname(addr, &rec.ip4, &rec.ip6); if (rec.error == 0) { errorstr = NULL; + if (reverse_lookup) { + /* reverse lookup the IP, ignore any error */ + if (rec.ip4.family != 0) + net_gethostbyaddr(&rec.ip4, &rec.host4); + if (rec.ip6.family != 0) + net_gethostbyaddr(&rec.ip6, &rec.host6); + } } else { errorstr = net_gethosterror(rec.error); rec.errlen = errorstr == NULL ? 0 : strlen(errorstr)+1; @@ -111,6 +120,22 @@ int net_gethostbyname_nonblock(const char *addr, GIOChannel *pipe) g_io_channel_write_block(pipe, &rec, sizeof(rec)); if (rec.errlen != 0) g_io_channel_write_block(pipe, (void *) errorstr, rec.errlen); + else { + if (rec.host4) { + len = strlen(rec.host4) + 1; + g_io_channel_write_block(pipe, (void *) &len, + sizeof(int)); + g_io_channel_write_block(pipe, (void *) rec.host4, + len); + } + if (rec.host6) { + len = strlen(rec.host6) + 1; + g_io_channel_write_block(pipe, (void *) &len, + sizeof(int)); + g_io_channel_write_block(pipe, (void *) rec.host6, + len); + } + } #ifndef WIN32 if (pid == 0) @@ -124,8 +149,12 @@ int net_gethostbyname_nonblock(const char *addr, GIOChannel *pipe) /* get the resolved IP address */ int net_gethostbyname_return(GIOChannel *pipe, RESOLVED_IP_REC *rec) { + int len; + rec->error = -1; rec->errorstr = NULL; + rec->host4 = NULL; + rec->host6 = NULL; #ifndef WIN32 fcntl(g_io_channel_unix_get_fd(pipe), F_SETFL, O_NONBLOCK); @@ -143,6 +172,17 @@ int net_gethostbyname_return(GIOChannel *pipe, RESOLVED_IP_REC *rec) reason, just ignore it. */ rec->errorstr = g_malloc0(rec->errlen+1); g_io_channel_read_block(pipe, rec->errorstr, rec->errlen); + } else { + if (rec->host4) { + g_io_channel_read_block(pipe, &len, sizeof(int)); + rec->host4 = g_malloc0(len); + g_io_channel_read_block(pipe, rec->host4, len); + } + if (rec->host6) { + g_io_channel_read_block(pipe, &len, sizeof(int)); + rec->host6 = g_malloc0(len); + g_io_channel_read_block(pipe, rec->host6, len); + } } return 0; @@ -244,7 +284,7 @@ int net_connect_nonblock(const char *server, int port, const IPADDR *my_ip, rec->pipes[1] = g_io_channel_unix_new(fd[1]); /* start nonblocking host name lookup */ - net_gethostbyname_nonblock(server, rec->pipes[1]); + net_gethostbyname_nonblock(server, rec->pipes[1], 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 a0e5cddf..32cfac70 100644 --- a/src/core/net-nonblock.h +++ b/src/core/net-nonblock.h @@ -9,6 +9,7 @@ typedef struct { int errlen; /* error text length */ char *errorstr; /* error string - dynamically allocated, you'll need to free() it yourself unless it's NULL */ + char *host4, *host6; /* dito */ } RESOLVED_IP_REC; typedef struct { @@ -24,7 +25,8 @@ typedef void (*NET_CALLBACK) (GIOChannel *, void *); 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 net_gethostbyname_nonblock(const char *addr, GIOChannel *pipe, + 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 occured with read() */ diff --git a/src/core/servers.c b/src/core/servers.c index 92a6e5ac..f9ab791a 100644 --- a/src/core/servers.c +++ b/src/core/servers.c @@ -213,6 +213,7 @@ static void server_connect_callback_readpipe(SERVER_REC *server) RESOLVED_IP_REC iprec; IPADDR *ip; const char *errormsg; + char *servername = NULL; g_source_remove(server->connect_tag); server->connect_tag = -1; @@ -234,20 +235,31 @@ static void server_connect_callback_readpipe(SERVER_REC *server) } else if (server->connrec->family == AF_INET) { /* force IPv4 connection */ ip = iprec.ip4.family == 0 ? NULL : &iprec.ip4; + servername = iprec.host4; } else if (server->connrec->family == AF_INET6) { /* force IPv6 connection */ ip = iprec.ip6.family == 0 ? NULL : &iprec.ip6; + servername = iprec.host6; } else { /* pick the one that was found, or if both do it like /SET resolve_prefer_ipv6 says. */ - ip = iprec.ip4.family == 0 || - (iprec.ip6.family != 0 && - settings_get_bool("resolve_prefer_ipv6")) ? - &iprec.ip6 : &iprec.ip4; + if (iprec.ip4.family == 0 || + (iprec.ip6.family != 0 && + settings_get_bool("resolve_prefer_ipv6"))) { + ip = &iprec.ip6; + servername = iprec.host6; + } else { + ip = &iprec.ip4; + servername = iprec.host4; + } } if (ip != NULL) { /* host lookup ok */ + if (servername) { + g_free(server->connrec->address); + server->connrec->address = g_strdup(servername); + } server_real_connect(server, ip, NULL); errormsg = NULL; } else { @@ -273,6 +285,8 @@ static void server_connect_callback_readpipe(SERVER_REC *server) } g_free(iprec.errorstr); + g_free(iprec.host4); + g_free(iprec.host6); } SERVER_REC *server_connect(SERVER_CONNECT_REC *conn) @@ -356,7 +370,8 @@ int server_start_connect(SERVER_REC *server) server->connrec->proxy : server->connrec->address; server->connect_pid = net_gethostbyname_nonblock(connect_address, - server->connect_pipe[1]); + server->connect_pipe[1], + settings_get_bool("resolve_reverse_lookup")); server->connect_tag = g_input_add(server->connect_pipe[0], G_INPUT_READ, (GInputFunction) @@ -666,6 +681,7 @@ static void sig_chat_protocol_deinit(CHAT_PROTOCOL_REC *proto) void servers_init(void) { settings_add_bool("server", "resolve_prefer_ipv6", FALSE); + settings_add_bool("server", "resolve_reverse_lookup", FALSE); lookup_servers = servers = NULL; signal_add("chat protocol deinit", (SIGNAL_FUNC) sig_chat_protocol_deinit); |