From 3ff7262ed26840a697c914a7905543d6c3efac6c Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sun, 4 Jan 2009 16:13:35 +0100 Subject: [PATCH] Add support for RTNL newlink watches --- include/rtnl.h | 7 +++++ src/rtnl.c | 90 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 97 insertions(+) diff --git a/include/rtnl.h b/include/rtnl.h index 758e549..c78556b 100644 --- a/include/rtnl.h +++ b/include/rtnl.h @@ -32,6 +32,13 @@ extern "C" { * @short_description: Functions for registering RTNL modules */ +typedef void (* connman_rtnl_link_cb_t) (unsigned flags, unsigned change, + void *user_data); + +extern unsigned int connman_rtnl_add_newlink_watch(int index, + connman_rtnl_link_cb_t callback, void *user_data); +extern void connman_rtnl_remove_watch(unsigned int id); + #define CONNMAN_RTNL_PRIORITY_LOW -100 #define CONNMAN_RTNL_PRIORITY_DEFAULT 0 #define CONNMAN_RTNL_PRIORITY_HIGH 100 diff --git a/src/rtnl.c b/src/rtnl.c index 8107933..3ea7608 100644 --- a/src/rtnl.c +++ b/src/rtnl.c @@ -36,6 +36,74 @@ #include "connman.h" +struct watch_data { + unsigned int id; + int index; + connman_rtnl_link_cb_t newlink; + void *user_data; +}; + +static GSList *watch_list = NULL; +static unsigned int watch_id = 0; + +/** + * connman_rtnl_add_newlink_watch: + * @index: network device index + * @callback: callback function + * @user_data: callback data; + * + * Add a new RTNL watch for newlink events + * + * Returns: %0 on failure and a unique id on success + */ +unsigned int connman_rtnl_add_newlink_watch(int index, + connman_rtnl_link_cb_t callback, void *user_data) +{ + struct watch_data *watch; + + watch = g_try_new0(struct watch_data, 1); + if (watch == NULL) + return 0; + + watch->id = ++watch_id; + watch->index = index; + + watch->newlink = callback; + watch->user_data = user_data; + + watch_list = g_slist_prepend(watch_list, watch); + + DBG("id %d", watch->id); + + return watch->id; +} + +/** + * connman_rtnl_remove_watch: + * @id: watch identifier + * + * Remove the RTNL watch for the identifier + */ +void connman_rtnl_remove_watch(unsigned int id) +{ + GSList *list; + + DBG("id %d", id); + + if (id == 0) + return; + + for (list = watch_list; list; list = list->next) { + struct watch_data *watch = list->data; + + if (watch->id == id) { + watch_list = g_slist_remove(watch_list, watch); + g_free(watch); + break; + } + } +} + static GSList *rtnl_list = NULL; static gint compare_priority(gconstpointer a, gconstpointer b) @@ -88,6 +156,16 @@ static void process_newlink(unsigned short type, int index, if (rtnl->newlink) rtnl->newlink(type, index, flags, change); } + + for (list = watch_list; list; list = list->next) { + struct watch_data *watch = list->data; + + if (watch->index != index) + continue; + + if (watch->newlink) + watch->newlink(flags, change, watch->user_data); + } } static void process_dellink(unsigned short type, int index, @@ -687,6 +765,18 @@ void __connman_rtnl_cleanup(void) DBG(""); + for (list = watch_list; list; list = list->next) { + struct watch_data *watch = list->data; + + DBG("removing watch %d", watch->id); + + g_free(watch); + list->data = NULL; + } + + g_slist_free(watch_list); + watch_list = NULL; + for (list = request_list; list; list = list->next) { struct rtnl_request *req = list->data; -- 1.7.9.5