From aad2c32df36c15ccafaadd5c0f7f71aff4c21995 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sat, 13 Dec 2008 19:25:04 +0100 Subject: [PATCH] Add improved resolver framework --- include/resolver.h | 8 +++ src/connman.h | 2 + src/resolver.c | 167 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/selftest.c | 6 +- 4 files changed, 182 insertions(+), 1 deletion(-) diff --git a/include/resolver.h b/include/resolver.h index 5c02375..d849e08 100644 --- a/include/resolver.h +++ b/include/resolver.h @@ -39,11 +39,19 @@ extern "C" { struct connman_resolver { const char *name; int priority; + int (*append) (const char *interface, const char *domain, + const char *server); + int (*remove) (const char *interface, const char *domain, + const char *server); }; extern int connman_resolver_register(struct connman_resolver *resolver); extern void connman_resolver_unregister(struct connman_resolver *resolver); +extern int connman_resolver_append(const char *interface, const char *domain, + const char *server); +extern int connman_resolver_remove_all(const char *interface); + #ifdef __cplusplus } #endif diff --git a/src/connman.h b/src/connman.h index 9fbe9ec..4fca050 100644 --- a/src/connman.h +++ b/src/connman.h @@ -71,6 +71,8 @@ enum connman_ipv4_method __connman_ipv4_string2method(const char *method); #include +int __connman_resolver_selftest(void); + #include void __connman_driver_rescan(struct connman_driver *driver); diff --git a/src/resolver.c b/src/resolver.c index a813236..d77ebc2 100644 --- a/src/resolver.c +++ b/src/resolver.c @@ -25,8 +25,39 @@ #include "connman.h" +struct entry_data { + struct connman_resolver *resolver; + char *interface; + char *domain; + char *server; +}; + +static GSList *entry_list = NULL; static GSList *resolver_list = NULL; +static void remove_entries(GSList *entries) +{ + GSList *list; + + for (list = entries; list; list = list->next) { + struct entry_data *entry = list->data; + struct connman_resolver *resolver = entry->resolver; + + entry_list = g_slist_remove(entry_list, entry); + + if (resolver->remove) + resolver->remove(entry->interface, entry->domain, + entry->server); + + g_free(entry->server); + g_free(entry->domain); + g_free(entry->interface); + g_free(entry); + } + + g_slist_free(entries); +} + static gint compare_priority(gconstpointer a, gconstpointer b) { const struct connman_resolver *resolver1 = a; @@ -45,11 +76,27 @@ static gint compare_priority(gconstpointer a, gconstpointer b) */ int connman_resolver_register(struct connman_resolver *resolver) { + GSList *list; + DBG("resolver %p name %s", resolver, resolver->name); resolver_list = g_slist_insert_sorted(resolver_list, resolver, compare_priority); + if (resolver->append == NULL) + return 0; + + for (list = entry_list; list; list = list->next) { + struct entry_data *entry = list->data; + + if (entry->resolver) + continue; + + if (resolver->append(entry->interface, entry->domain, + entry->server) == 0) + entry->resolver = resolver; + } + return 0; } @@ -61,7 +108,127 @@ int connman_resolver_register(struct connman_resolver *resolver) */ void connman_resolver_unregister(struct connman_resolver *resolver) { + GSList *list, *matches = NULL; + DBG("resolver %p name %s", resolver, resolver->name); resolver_list = g_slist_remove(resolver_list, resolver); + + for (list = entry_list; list; list = list->next) { + struct entry_data *entry = list->data; + + if (entry->resolver != resolver) + continue; + + matches = g_slist_append(matches, entry); + } + + remove_entries(matches); +} + +/** + * connman_resolver_append: + * @interface: network interface + * @domain: domain limitation + * @server: server address + * + * Append resolver server address to current list + */ +int connman_resolver_append(const char *interface, const char *domain, + const char *server) +{ + struct entry_data *entry; + GSList *list; + + DBG("interface %s domain %s server %s", interface, domain, server); + + entry = g_try_new0(struct entry_data, 1); + if (entry == NULL) + return -ENOMEM; + + entry->interface = g_strdup(interface); + entry->domain = g_strdup(domain); + entry->server = g_strdup(server); + + entry_list = g_slist_append(entry_list, entry); + + for (list = resolver_list; list; list = list->next) { + struct connman_resolver *resolver = list->data; + + if (resolver->append == NULL) + continue; + + if (resolver->append(interface, domain, server) == 0) { + entry->resolver = resolver; + break; + } + } + + return 0; +} + +/** + * connman_resolver_remove_all: + * @interface: network interface + * + * Remove all resolver server address for the specified interface + */ +int connman_resolver_remove_all(const char *interface) +{ + GSList *list, *matches = NULL; + + DBG("interface %s", interface); + + for (list = entry_list; list; list = list->next) { + struct entry_data *entry = list->data; + struct connman_resolver *resolver; + + if (g_str_equal(entry->interface, interface) == FALSE) + continue; + + matches = g_slist_append(matches, entry); + } + + remove_entries(matches); + + return 0; +} + +static int selftest_append(const char *interface, const char *domain, + const char *server) +{ + DBG("server %s", server); + + return 0; +} + +static int selftest_remove(const char *interface, const char *domain, + const char *server) +{ + DBG("server %s", server); + + return 0; +} + +static struct connman_resolver selftest = { + .name = "selftest", + .priority = CONNMAN_RESOLVER_PRIORITY_HIGH + 42, + .append = selftest_append, + .remove = selftest_remove, +}; + +int __connman_resolver_selftest(void) +{ + connman_resolver_append("wlan0", "lwn.net", "192.168.0.1"); + + connman_resolver_register(&selftest); + + connman_resolver_append("eth0", "moblin.org", "192.168.42.1"); + connman_resolver_append("wlan0", "lwn.net", "192.168.0.2"); + + connman_resolver_remove_all("wlan0"); + + connman_resolver_unregister(&selftest); + + return 0; } diff --git a/src/selftest.c b/src/selftest.c index b3e0c23..17f7758 100644 --- a/src/selftest.c +++ b/src/selftest.c @@ -31,8 +31,12 @@ int __connman_selftest(void) connman_info("Start self testing"); - err = 0; + connman_info("Testing resolver unit"); + err = __connman_resolver_selftest(); + if (err < 0) + goto done; +done: connman_info("Finished self testing"); return err; -- 1.7.9.5