Track IP configuration based on RTNL interface list
authorMarcel Holtmann <marcel@holtmann.org>
Sat, 8 Aug 2009 19:39:18 +0000 (12:39 -0700)
committerMarcel Holtmann <marcel@holtmann.org>
Sat, 8 Aug 2009 19:39:18 +0000 (12:39 -0700)
include/ipconfig.h
src/connman.h
src/device.c
src/ipconfig.c
src/rtnl.c

index c8062ba..e347063 100644 (file)
@@ -47,7 +47,7 @@ enum connman_ipconfig_method {
 
 struct connman_ipconfig;
 
-struct connman_ipconfig *connman_ipconfig_create(unsigned int index);
+struct connman_ipconfig *connman_ipconfig_create(int index);
 struct connman_ipconfig *connman_ipconfig_ref(struct connman_ipconfig *ipconfig);
 void connman_ipconfig_unref(struct connman_ipconfig *ipconfig);
 
index a5fb709..b907977 100644 (file)
@@ -93,11 +93,13 @@ int __connman_security_check_privilege(DBusMessage *message,
 
 int __connman_ipconfig_get_index(struct connman_ipconfig *ipconfig);
 
+void __connman_ipconfig_update_link(struct connman_ipconfig *ipconfig,
+                                       unsigned flags, unsigned change);
 void __connman_ipconfig_add_address(struct connman_ipconfig *ipconfig,
-                               const char *label, unsigned int prefixlen,
+                               const char *label, unsigned char prefixlen,
                                const char *address, const char *broadcast);
 void __connman_ipconfig_del_address(struct connman_ipconfig *ipconfig,
-                               const char *label, unsigned int prefixlen,
+                               const char *label, unsigned char prefixlen,
                                const char *address, const char *broadcast);
 
 const char *__connman_ipconfig_method2string(enum connman_ipconfig_method method);
index 751d190..b238f46 100644 (file)
@@ -1030,10 +1030,10 @@ void connman_device_set_index(struct connman_device *device, int index)
 {
        device->element.index = index;
 
-       if (device->ipconfig != NULL)
-               connman_ipconfig_unref(device->ipconfig);
+       //if (device->ipconfig != NULL)
+       //      connman_ipconfig_unref(device->ipconfig);
 
-       device->ipconfig = connman_ipconfig_create(index);
+       //device->ipconfig = connman_ipconfig_create(index);
 }
 
 /**
index e08f1e7..dbf0bc8 100644 (file)
@@ -29,7 +29,7 @@
 
 struct connman_ipconfig {
        gint refcount;
-       unsigned int index;
+       int index;
        char *interface;
        enum connman_ipconfig_method method;
 };
@@ -41,7 +41,7 @@ struct connman_ipconfig {
  *
  * Returns: a newly-allocated #connman_ipconfig structure
  */
-struct connman_ipconfig *connman_ipconfig_create(unsigned int index)
+struct connman_ipconfig *connman_ipconfig_create(int index)
 {
        struct connman_ipconfig *ipconfig;
 
@@ -51,12 +51,17 @@ struct connman_ipconfig *connman_ipconfig_create(unsigned int index)
        if (ipconfig == NULL)
                return NULL;
 
+       ipconfig->refcount = 1;
+
        ipconfig->index = index;
        ipconfig->interface = connman_inet_ifname(index);
 
        DBG("ipconfig %p", ipconfig);
 
-       __connman_rtnl_register_ipconfig(ipconfig);
+       //__connman_rtnl_register_ipconfig(ipconfig);
+
+       connman_info("%s {create} index %d", ipconfig->interface,
+                                                       ipconfig->index);
 
        return ipconfig;
 }
@@ -83,7 +88,10 @@ struct connman_ipconfig *connman_ipconfig_ref(struct connman_ipconfig *ipconfig)
 void connman_ipconfig_unref(struct connman_ipconfig *ipconfig)
 {
        if (g_atomic_int_dec_and_test(&ipconfig->refcount) == TRUE) {
-               __connman_rtnl_unregister_ipconfig(ipconfig);
+               //__connman_rtnl_unregister_ipconfig(ipconfig);
+
+               connman_info("%s {remove} index %d", ipconfig->interface,
+                                                       ipconfig->index);
 
                g_free(ipconfig->interface);
                g_free(ipconfig);
@@ -110,19 +118,26 @@ int __connman_ipconfig_get_index(struct connman_ipconfig *ipconfig)
        return ipconfig->index;
 }
 
+void __connman_ipconfig_update_link(struct connman_ipconfig *ipconfig,
+                                       unsigned flags, unsigned change)
+{
+       connman_info("%s {update} flags %u change %u", ipconfig->interface,
+                                                       flags, change);
+}
+
 void __connman_ipconfig_add_address(struct connman_ipconfig *ipconfig,
-                               const char *label, unsigned int prefixlen,
+                               const char *label, unsigned char prefixlen,
                                const char *address, const char *broadcast)
 {
-       connman_info("%s {add} address %s/%d label %s", ipconfig->interface,
+       connman_info("%s {add} address %s/%u label %s", ipconfig->interface,
                                                address, prefixlen, label);
 }
 
 void __connman_ipconfig_del_address(struct connman_ipconfig *ipconfig,
-                               const char *label, unsigned int prefixlen,
+                               const char *label, unsigned char prefixlen,
                                const char *address, const char *broadcast)
 {
-       connman_info("%s {del} address %s/%d label %s", ipconfig->interface,
+       connman_info("%s {del} address %s/%u label %s", ipconfig->interface,
                                                address, prefixlen, label);
 }
 
index 40b3ea9..70d6512 100644 (file)
@@ -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;