From b7d722c12182908d523234093a60a77c14394f6a Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sat, 8 Aug 2009 12:39:18 -0700 Subject: [PATCH] Track IP configuration based on RTNL interface list --- include/ipconfig.h | 2 +- src/connman.h | 6 ++++-- src/device.c | 6 +++--- src/ipconfig.c | 31 +++++++++++++++++++++++-------- src/rtnl.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 79 insertions(+), 14 deletions(-) diff --git a/include/ipconfig.h b/include/ipconfig.h index c8062ba..e347063 100644 --- a/include/ipconfig.h +++ b/include/ipconfig.h @@ -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); diff --git a/src/connman.h b/src/connman.h index a5fb709..b907977 100644 --- a/src/connman.h +++ b/src/connman.h @@ -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); diff --git a/src/device.c b/src/device.c index 751d190..b238f46 100644 --- a/src/device.c +++ b/src/device.c @@ -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); } /** diff --git a/src/ipconfig.c b/src/ipconfig.c index e08f1e7..dbf0bc8 100644 --- a/src/ipconfig.c +++ b/src/ipconfig.c @@ -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); } diff --git a/src/rtnl.c b/src/rtnl.c index 40b3ea9..70d6512 100644 --- a/src/rtnl.c +++ b/src/rtnl.c @@ -29,6 +29,7 @@ #include #include +#include #include #include @@ -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; -- 2.7.4