summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarcel Holtmann <marcel@holtmann.org>2009-01-04 16:13:35 +0100
committerMarcel Holtmann <marcel@holtmann.org>2009-01-04 16:13:35 +0100
commit3ff7262ed26840a697c914a7905543d6c3efac6c (patch)
treecdf14b7aa64e387479a051307026a8883861e598
parent5ae55853fca4017221895b03cece096e361dac36 (diff)
downloadconnman-3ff7262ed26840a697c914a7905543d6c3efac6c.tar.gz
connman-3ff7262ed26840a697c914a7905543d6c3efac6c.tar.bz2
connman-3ff7262ed26840a697c914a7905543d6c3efac6c.zip
Add support for RTNL newlink watches
-rw-r--r--include/rtnl.h7
-rw-r--r--src/rtnl.c90
2 files changed, 97 insertions, 0 deletions
diff --git a/include/rtnl.h b/include/rtnl.h
index 758e5497..c78556b9 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 8107933d..3ea7608c 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;