X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Fdnsproxy.c;h=d1f5e9cfe7a52dd450e62880e73efe479cdb81a0;hb=6c8213f23b60fb46e6cd2572a6adc7ce4da13691;hp=6f8d39a47ef992e33951fd160666387170ea2ef7;hpb=d0fa0d7b6c2e6cb6834ab048742bdffc41371aa4;p=framework%2Fconnectivity%2Fconnman.git diff --git a/src/dnsproxy.c b/src/dnsproxy.c index 6f8d39a..d1f5e9c 100644 --- a/src/dnsproxy.c +++ b/src/dnsproxy.c @@ -2,7 +2,7 @@ * * Connection Manager * - * Copyright (C) 2007-2010 Intel Corporation. All rights reserved. + * Copyright (C) 2007-2012 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -565,7 +565,7 @@ static gboolean cache_check_is_valid(struct cache_data *data, */ static void cache_enforce_validity(struct cache_entry *entry) { - time_t current_time = time(0); + time_t current_time = time(NULL); if (cache_check_is_valid(entry->ipv4, current_time) == FALSE && entry->ipv4) { @@ -588,7 +588,7 @@ static void cache_enforce_validity(struct cache_entry *entry) static uint16_t cache_check_validity(char *question, uint16_t type, struct cache_entry *entry) { - time_t current_time = time(0); + time_t current_time = time(NULL); int want_refresh = 0; /* @@ -1053,7 +1053,7 @@ static void cache_cleanup(void) struct cache_timeout data; int count = 0; - data.current_time = time(0); + data.current_time = time(NULL); data.max_timeout = 0; data.try_harder = 0; @@ -1130,9 +1130,12 @@ static gboolean cache_invalidate_entry(gpointer key, gpointer value, */ static void cache_invalidate(void) { - DBG("Invalidating the DNS cache"); - g_hash_table_foreach_remove(cache, cache_invalidate_entry, - NULL); + DBG("Invalidating the DNS cache %p", cache); + + if (cache == NULL) + return; + + g_hash_table_foreach_remove(cache, cache_invalidate_entry, NULL); } static void cache_refresh_entry(struct cache_entry *entry) @@ -1175,6 +1178,9 @@ static void cache_refresh_iterator(gpointer key, gpointer value, static void cache_refresh(void) { + if (cache == NULL) + return; + g_hash_table_foreach(cache, cache_refresh_iterator, NULL); } @@ -1195,7 +1201,6 @@ static int reply_query_type(unsigned char *msg, int len) /* now the query, which is a name and 2 16 bit words */ l = dns_name_length(c) + 1; c += l; - len -= l; w = (uint16_t *) c; type = ntohs(*w); @@ -1224,7 +1229,7 @@ static int cache_update(struct server_data *srv, unsigned char *msg, return 0; } - current_time = time(0); + current_time = time(NULL); /* don't do a cache refresh more than twice a minute */ if (next_refresh < current_time) { @@ -1410,7 +1415,7 @@ static int ns_resolv(struct server_data *server, struct request_data *req, data = entry->ipv6; if (data) { - ttl_left = data->valid_until - time(0); + ttl_left = data->valid_until - time(NULL); entry->hits++; } @@ -1437,6 +1442,8 @@ static int ns_resolv(struct server_data *server, struct request_data *req, sk = g_io_channel_unix_get_fd(server->channel); err = send(sk, request, req->request_len, 0); + if (err < 0) + return -EIO; req->numserv++; @@ -1621,6 +1628,18 @@ static void cache_element_destroy(gpointer value) cache_size = 0; } +static gboolean try_remove_cache(gpointer user_data) +{ + if (__sync_fetch_and_sub(&cache_refcount, 1) == 1) { + DBG("No cache users, removing it."); + + g_hash_table_destroy(cache); + cache = NULL; + } + + return FALSE; +} + static void destroy_server(struct server_data *server) { GList *list; @@ -1650,8 +1669,16 @@ static void destroy_server(struct server_data *server) } g_free(server->interface); - if (__sync_fetch_and_sub(&cache_refcount, 1) == 1) - g_hash_table_destroy(cache); + /* + * We do not remove cache right away but delay it few seconds. + * The idea is that when IPv6 DNS server is added via RDNSS, it has a + * lifetime. When the lifetime expires we decrease the refcount so it + * is possible that the cache is then removed. Because a new DNS server + * is usually created almost immediately we would then loose the cache + * without any good reason. The small delay allows the new RDNSS to + * create a new DNS server instance and the refcount does not go to 0. + */ + g_timeout_add_seconds(3, try_remove_cache, NULL); g_free(server); } @@ -2642,6 +2669,17 @@ static int create_listener(struct listener_data *ifdata) return 0; } +static void destroy_request_data(struct request_data *req) +{ + if (req->timeout > 0) + g_source_remove(req->timeout); + + g_free(req->resp); + g_free(req->request); + g_free(req->name); + g_free(req); +} + static void destroy_listener(struct listener_data *ifdata) { GSList *list; @@ -2654,11 +2692,7 @@ static void destroy_listener(struct listener_data *ifdata) DBG("Dropping pending request (id 0x%04x -> 0x%04x)", req->srcid, req->dstid); - - g_free(req->resp); - g_free(req->request); - g_free(req->name); - g_free(req); + destroy_request_data(req); list->data = NULL; } @@ -2670,11 +2704,7 @@ static void destroy_listener(struct listener_data *ifdata) DBG("Dropping request (id 0x%04x -> 0x%04x)", req->srcid, req->dstid); - - g_free(req->resp); - g_free(req->request); - g_free(req->name); - g_free(req); + destroy_request_data(req); list->data = NULL; }