summaryrefslogtreecommitdiff
path: root/src/rtnl.c
diff options
context:
space:
mode:
authorMarcel Holtmann <marcel@holtmann.org>2009-08-08 12:39:18 -0700
committerMarcel Holtmann <marcel@holtmann.org>2009-08-08 12:39:18 -0700
commitb7d722c12182908d523234093a60a77c14394f6a (patch)
tree4d2072dc59aa1cdcfe76db7bb8f93480204cb16e /src/rtnl.c
parentafc99f394364a5bf1a60e558b5672f721d47a68e (diff)
downloadconnman-b7d722c12182908d523234093a60a77c14394f6a.tar.gz
connman-b7d722c12182908d523234093a60a77c14394f6a.tar.bz2
connman-b7d722c12182908d523234093a60a77c14394f6a.zip
Track IP configuration based on RTNL interface list
Diffstat (limited to 'src/rtnl.c')
-rw-r--r--src/rtnl.c48
1 files changed, 48 insertions, 0 deletions
diff --git a/src/rtnl.c b/src/rtnl.c
index 40b3ea93..70d65124 100644
--- a/src/rtnl.c
+++ b/src/rtnl.c
@@ -29,6 +29,7 @@
#include <arpa/inet.h>
#include <linux/if.h>
+#include <linux/if_arp.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
@@ -145,11 +146,43 @@ void connman_rtnl_unregister(struct connman_rtnl *rtnl)
rtnl_list = g_slist_remove(rtnl_list, rtnl);
}
+static GHashTable *ipconfig_hash = NULL;
+
+static void free_ipconfig(gpointer data)
+{
+ struct connman_ipconfig *ipconfig = data;
+
+ __connman_rtnl_unregister_ipconfig(ipconfig);
+
+ connman_ipconfig_unref(ipconfig);
+}
+
static void process_newlink(unsigned short type, int index,
unsigned flags, unsigned change)
{
+ struct connman_ipconfig *ipconfig;
GSList *list;
+ switch (type) {
+ case ARPHRD_ETHER:
+ case ARPHRD_LOOPBACK:
+ case ARPHRD_NONE:
+ ipconfig = g_hash_table_lookup(ipconfig_hash, &index);
+ if (ipconfig == NULL) {
+ ipconfig = connman_ipconfig_create(index);
+ if (ipconfig != NULL) {
+ g_hash_table_insert(ipconfig_hash,
+ &index, ipconfig);
+
+ __connman_rtnl_register_ipconfig(ipconfig);
+
+ __connman_ipconfig_update_link(ipconfig,
+ flags, change);
+ }
+ }
+ break;
+ }
+
for (list = rtnl_list; list; list = list->next) {
struct connman_rtnl *rtnl = list->data;
@@ -179,6 +212,14 @@ static void process_dellink(unsigned short type, int index,
if (rtnl->dellink)
rtnl->dellink(type, index, flags, change);
}
+
+ switch (type) {
+ case ARPHRD_ETHER:
+ case ARPHRD_LOOPBACK:
+ case ARPHRD_NONE:
+ g_hash_table_remove(ipconfig_hash, &index);
+ break;
+ }
}
static char *extract_gateway(struct rtmsg *msg, int bytes, int *index)
@@ -876,6 +917,9 @@ int __connman_rtnl_init(void)
DBG("");
+ ipconfig_hash = g_hash_table_new_full(g_int_hash, g_int_equal,
+ NULL, free_ipconfig);
+
sk = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE);
if (sk < 0)
return -1;
@@ -902,6 +946,7 @@ void __connman_rtnl_start(void)
{
DBG("");
+ connman_rtnl_send_getlink();
send_getaddr();
}
@@ -914,6 +959,9 @@ void __connman_rtnl_cleanup(void)
g_slist_free(ipconfig_list);
ipconfig_list = NULL;
+ g_hash_table_destroy(ipconfig_hash);
+ ipconfig_hash = NULL;
+
for (list = watch_list; list; list = list->next) {
struct watch_data *watch = list->data;