changeset 27016:c162a088489f

Call res_init() when DNS queries fail in case the failure indicates a timeout because we've moved networks. Closes #2825.
author Paul Aurich <paul@darkrain42.org>
date Fri, 22 May 2009 04:44:07 +0000
parents f500336f9881
children 31f65046b92d
files ChangeLog libpurple/dnsquery.c libpurple/dnssrv.c
diffstat 3 files changed, 80 insertions(+), 51 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Fri May 22 04:08:38 2009 +0000
+++ b/ChangeLog	Fri May 22 04:44:07 2009 +0000
@@ -16,6 +16,8 @@
 	* Report idle time 'From last message sent' should work properly.
 	* Show the invite message for buddies that requested authorization
 	  from you on MSN.
+	* DNS servers are re-read when DNS queries fail in case the system has
+	  moved to a new network and the old servers are not accessible.
 
 	XMPP:
 	* Voice & Video support with Jingle (XEP-0166, 0167, 0176, & 0177), and
--- a/libpurple/dnsquery.c	Fri May 22 04:08:38 2009 +0000
+++ b/libpurple/dnsquery.c	Fri May 22 04:44:07 2009 +0000
@@ -32,6 +32,10 @@
 #include "prefs.h"
 #include "util.h"
 
+#ifndef _WIN32
+#include <resolv.h>
+#endif
+
 #if (defined(__APPLE__) || defined (__unix__)) && !defined(__osf__)
 #define PURPLE_DNSQUERY_USE_FORK
 #endif
@@ -571,8 +575,10 @@
 		g_snprintf(message, sizeof(message), _("Error resolving %s: %d"),
 				query_data->hostname, err);
 #endif
+		/* Re-read resolv.conf and friends in case DNS servers have changed */
+		res_init();
+
 		purple_dnsquery_failed(query_data, message);
-
 	} else if (rc > 0) {
 		/* Success! */
 		while (rc > 0) {
--- a/libpurple/dnssrv.c	Fri May 22 04:08:38 2009 +0000
+++ b/libpurple/dnssrv.c	Fri May 22 04:44:07 2009 +0000
@@ -141,7 +141,14 @@
 	}
 
 	size = res_query( query.query, C_IN, query.type, (u_char*)&answer, sizeof( answer));
-	
+	if (size == -1) {
+		write(out, &(query.type), sizeof(query.type));
+		write(out, &size, sizeof(int));
+		close(out);
+		close(in);
+		_exit(0);
+	}
+
 	qdcount = ntohs(answer.hdr.qdcount);
 	ancount = ntohs(answer.hdr.ancount);
 	cp = (guchar*)&answer + sizeof(HEADER);
@@ -223,59 +230,73 @@
 	PurpleSrvQueryData *query_data = (PurpleSrvQueryData*)data;
 	int i;
 	int status;
-	
+
 	if (read(source, &type, sizeof(type)) == sizeof(type)) {
-		if (type == T_SRV) {
-			PurpleSrvResponse *res;
-			PurpleSrvResponse *tmp;
-			PurpleSrvCallback cb = query_data->cb.srv;
-			if (read(source, &size, sizeof(int)) == sizeof(int)) {
-				ssize_t red;
-				purple_debug_info("dnssrv","found %d SRV entries\n", size);
-				tmp = res = g_new0(PurpleSrvResponse, size);
-				for (i = 0; i < size; i++) {
-					red = read(source, tmp++, sizeof(PurpleSrvResponse));
-					if (red != sizeof(PurpleSrvResponse)) {
-						purple_debug_error("dnssrv","unable to read srv "
-								"response: %s\n", g_strerror(errno));
-						size = 0;
-						g_free(res);
-						res = NULL;
+		if (read(source, &size, sizeof(size)) == sizeof(size)) {
+			if (size == -1 || size == 0) {
+				if (size == -1) {
+					purple_debug_warning("dnssrv", "res_query returned an error\n");
+					/* Re-read resolv.conf and friends in case DNS servers have changed */
+					res_init();
+				} else
+					purple_debug_info("dnssrv", "Found 0 entries, errno is %i\n", errno);
+
+				if (type == T_SRV) {
+					PurpleSrvCallback cb = query_data->cb.srv;
+					cb(NULL, 0, query_data->extradata);
+				} else if (type == T_TXT) {
+					PurpleTxtCallback cb = query_data->cb.txt;
+					cb(NULL, query_data->extradata);
+				} else {
+					purple_debug_error("dnssrv", "type unknown of DNS result entry; errno is %i\n", errno);
+				}
+
+			} else if (size) {
+				if (type == T_SRV) {
+					PurpleSrvResponse *res;
+					PurpleSrvResponse *tmp;
+					PurpleSrvCallback cb = query_data->cb.srv;
+					ssize_t red;
+					purple_debug_info("dnssrv","found %d SRV entries\n", size);
+					tmp = res = g_new0(PurpleSrvResponse, size);
+					for (i = 0; i < size; i++) {
+						red = read(source, tmp++, sizeof(PurpleSrvResponse));
+						if (red != sizeof(PurpleSrvResponse)) {
+							purple_debug_error("dnssrv","unable to read srv "
+									"response: %s\n", g_strerror(errno));
+							size = 0;
+							g_free(res);
+							res = NULL;
+						}
 					}
+
+					cb(res, size, query_data->extradata);
+				} else if (type == T_TXT) {
+					GSList *responses = NULL;
+					PurpleTxtResponse *res;
+					PurpleTxtCallback cb = query_data->cb.txt;
+					ssize_t red;
+					purple_debug_info("dnssrv","found %d TXT entries\n", size);
+					res = g_new0(PurpleTxtResponse, 1);
+					for (i = 0; i < size; i++) {
+						red = read(source, res, sizeof(PurpleTxtResponse));
+						if (red != sizeof(PurpleTxtResponse)) {
+							purple_debug_error("dnssrv","unable to read txt "
+									"response: %s\n", g_strerror(errno));
+							size = 0;
+							g_free(res);
+							g_slist_foreach(responses, (GFunc)purple_txt_response_destroy, NULL);
+							g_slist_free(responses);
+							responses = NULL;
+							break;
+						}
+					}
+
+					cb(responses, query_data->extradata);
+				} else {
+					purple_debug_error("dnssrv", "type unknown of DNS result entry; errno is %i\n", errno);
 				}
-			} else {
-				purple_debug_info("dnssrv","found 0 SRV entries; errno is %i\n", errno);
-				size = 0;
-				res = NULL;
 			}
-			cb(res, size, query_data->extradata);
-		} else if (type == T_TXT) {
-			GSList *responses = NULL;
-			PurpleTxtResponse *res;
-			PurpleTxtCallback cb = query_data->cb.txt;
-			if (read(source, &size, sizeof(int)) == sizeof(int)) {
-				ssize_t red;
-				purple_debug_info("dnssrv","found %d TXT entries\n", size);
-				res = g_new0(PurpleTxtResponse, 1);
-				for (i = 0; i < size; i++) {
-					red = read(source, res, sizeof(PurpleTxtResponse));
-					if (red != sizeof(PurpleTxtResponse)) {
-						purple_debug_error("dnssrv","unable to read txt "
-								"response: %s\n", g_strerror(errno));
-						size = 0;
-						g_free(res);
-						g_slist_foreach(responses, (GFunc)purple_txt_response_destroy, NULL);
-						g_slist_free(responses);
-						responses = NULL;
-						break;
-					}
-				}
-			} else {
-				purple_debug_info("dnssrv","found 0 TXT entries; errno is %i\n", errno);
-			}
-			cb(responses, query_data->extradata);			
-		} else {
-			purple_debug_info("dnssrv","type unknown of DNS result entry; errno is %i\n", errno);
 		}
 	}