diff options
author | Tomasz Bursztyka <tomasz.bursztyka@linux.intel.com> | 2013-02-15 12:30:19 +0200 |
---|---|---|
committer | Patrik Flykt <patrik.flykt@linux.intel.com> | 2013-02-18 10:49:49 +0200 |
commit | 5441662cf582d86736f94ed42f68bec9a031e42f (patch) | |
tree | 93d075c9c5028b06d8734f43c2c745693ff20d23 /gweb | |
parent | 6af0579c434058536fb40480f40f5e9895cfe863 (diff) | |
download | connman-5441662cf582d86736f94ed42f68bec9a031e42f.tar.gz connman-5441662cf582d86736f94ed42f68bec9a031e42f.tar.bz2 connman-5441662cf582d86736f94ed42f68bec9a031e42f.zip |
gresolv: Do not remove a query on failure if other results are pending
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.
Diffstat (limited to 'gweb')
-rw-r--r-- | gweb/gresolv.c | 28 |
1 files changed, 19 insertions, 9 deletions
diff --git a/gweb/gresolv.c b/gweb/gresolv.c index 71b70dc7..9505f677 100644 --- a/gweb/gresolv.c +++ b/gweb/gresolv.c @@ -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; } |