dnsproxy: Add a "invalidate cache" function
authorArjan van de Ven <arjan@linux.intel.com>
Tue, 10 Jan 2012 00:08:53 +0000 (16:08 -0800)
committerDaniel Wagner <daniel.wagner@bmw-carit.de>
Tue, 10 Jan 2012 12:43:57 +0000 (13:43 +0100)
When something changes in the network topology, we need to invalidate the cache.
This first implementation will delete all entries (which could have been done
more efficiently), but in later patches in this series we'll enhance this logic
to only delete the cached data, not the names. With keeping the names,
we can then re-lookup popular data in the new topology.

src/dnsproxy.c

index 730b033..b97b1d4 100644 (file)
@@ -1028,6 +1028,44 @@ static void cache_cleanup(void)
                max_timeout = 0;
 }
 
+static gboolean cache_invalidate_entry(gpointer key, gpointer value,
+                                       gpointer user_data)
+{
+       struct cache_entry *entry = value;
+
+       /* first, delete any expired elements */
+       cache_enforce_validity(entry);
+
+       /* delete the cached data */
+       if (entry->ipv4) {
+               g_free(entry->ipv4->data);
+               g_free(entry->ipv4);
+               entry->ipv4 = NULL;
+       }
+
+       if (entry->ipv6) {
+               g_free(entry->ipv6->data);
+               g_free(entry->ipv6);
+               entry->ipv6 = NULL;
+       }
+
+       return TRUE;
+}
+
+/*
+ * cache_invalidate is called from places where the DNS landscape
+ * has changed, say because connections are added or we entered a VPN.
+ * The logic is to wipe all cache data, but mark all non-expired
+ * parts of the cache for refresh rather than deleting the whole cache.
+ */
+static void cache_invalidate(void)
+{
+       DBG("Invalidating the DNS cache");
+        g_hash_table_foreach_remove(cache, cache_invalidate_entry,
+                                               NULL);
+}
+
+
 static int reply_query_type(unsigned char *msg, int len)
 {
        unsigned char *c;
@@ -2014,9 +2052,11 @@ static void dnsproxy_offline_mode(connman_bool_t enabled)
                if (enabled == FALSE) {
                        connman_info("Enabling DNS server %s", data->server);
                        data->enabled = TRUE;
+                       cache_invalidate();
                } else {
                        connman_info("Disabling DNS server %s", data->server);
                        data->enabled = FALSE;
+                       cache_invalidate();
                }
        }
 }
@@ -2028,6 +2068,9 @@ static void dnsproxy_default_changed(struct connman_service *service)
 
        DBG("service %p", service);
 
+       /* DNS has changed, invalidate the cache */
+       cache_invalidate();
+
        if (service == NULL) {
                /* When no services are active, then disable DNS proxying */
                dnsproxy_offline_mode(TRUE);