gresolv: Do not remove a query on failure if other results are pending
authorTomasz Bursztyka <tomasz.bursztyka@linux.intel.com>
Fri, 15 Feb 2013 10:30:19 +0000 (12:30 +0200)
committerPatrik Flykt <patrik.flykt@linux.intel.com>
Mon, 18 Feb 2013 08:49:49 +0000 (10:49 +0200)
Fixes BMC#25973

In the case one of the resolving failed, the query is removed and
destroyed from the queue. So the responses of the requests sent to
the other namerservers - which might be successful - will thus be
lost since they cannot be matched anymore to their initial request.

gweb/gresolv.c

index 71b70dc..9505f67 100644 (file)
@@ -79,6 +79,7 @@ struct resolv_lookup {
 struct resolv_query {
        GResolv *resolv;
 
+       int nr_ns;
        guint timeout;
 
        uint16_t msgid;
@@ -579,12 +580,13 @@ static void flush_nameservers(GResolv *resolv)
 static int send_query(GResolv *resolv, const unsigned char *buf, int len)
 {
        GList *list;
+       int nr_ns;
 
        if (resolv->nameserver_list == NULL)
                return -ENOENT;
 
-       for (list = g_list_first(resolv->nameserver_list);
-                                       list; list = g_list_next(list)) {
+       for (list = g_list_first(resolv->nameserver_list), nr_ns = 0;
+                               list; list = g_list_next(list), nr_ns++) {
                struct resolv_nameserver *nameserver = list->data;
                int sk, sent;
 
@@ -598,7 +600,7 @@ static int send_query(GResolv *resolv, const unsigned char *buf, int len)
                        continue;
        }
 
-       return 0;
+       return nr_ns;
 }
 
 static gint compare_lookup_id(gconstpointer a, gconstpointer b)
@@ -701,15 +703,14 @@ static void parse_response(struct resolv_nameserver *nameserver,
                return;
 
        query = list->data;
+       query->nr_ns--;
+
        lookup = query->lookup;
 
-       if (query == lookup->ipv6_query) {
+       if (query == lookup->ipv6_query)
                lookup->ipv6_status = status;
-               lookup->ipv6_query = NULL;
-       } else if (query == lookup->ipv4_query) {
+       else if (query == lookup->ipv4_query)
                lookup->ipv4_status = status;
-               lookup->ipv4_query = NULL;
-       }
 
        for (i = 0; i < count; i++) {
                ns_parserr(&msg, ns_s_an, i, &rr);
@@ -729,6 +730,14 @@ static void parse_response(struct resolv_nameserver *nameserver,
                }
        }
 
+       if (status != G_RESOLV_RESULT_STATUS_SUCCESS && query->nr_ns > 0)
+               return;
+
+       if (query == lookup->ipv6_query)
+               lookup->ipv6_query = NULL;
+       else
+               lookup->ipv4_query = NULL;
+
        g_queue_remove(resolv->query_queue, query);
        destroy_query(query);
 
@@ -975,7 +984,8 @@ static gint add_query(struct resolv_lookup *lookup, const char *hostname, int ty
 
        debug(lookup->resolv, "sending %d bytes", len);
 
-       if (send_query(lookup->resolv, buf, len) < 0) {
+       query->nr_ns = send_query(lookup->resolv, buf, len);
+       if (query->nr_ns <= 0) {
                g_free(query);
                return -EIO;
        }