summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarcel Holtmann <marcel@holtmann.org>2009-08-11 00:34:00 -0700
committerMarcel Holtmann <marcel@holtmann.org>2009-08-11 00:34:00 -0700
commit4415df317fd3c9356635703b1d3cdd329112caef (patch)
tree6e0d4293778c398395e9f8f5334f9200490633fe
parent00244ccfa4ee00b587de105acb02e42c8f90ad7a (diff)
downloadconnman-4415df317fd3c9356635703b1d3cdd329112caef.tar.gz
connman-4415df317fd3c9356635703b1d3cdd329112caef.tar.bz2
connman-4415df317fd3c9356635703b1d3cdd329112caef.zip
Add cleaner handling of IP address details
-rw-r--r--include/ipconfig.h15
-rw-r--r--src/ipconfig.c243
2 files changed, 197 insertions, 61 deletions
diff --git a/include/ipconfig.h b/include/ipconfig.h
index a9f82851..83a8172d 100644
--- a/include/ipconfig.h
+++ b/include/ipconfig.h
@@ -32,6 +32,18 @@ extern "C" {
* @short_description: Functions for IP configuration handling
*/
+struct connman_ipaddress {
+ unsigned char prefixlen;
+ char *local;
+ char *peer;
+ char *broadcast;
+};
+
+struct connman_ipaddress *connman_ipaddress_alloc(void);
+void connman_ipaddress_free(struct connman_ipaddress *ipaddress);
+void connman_ipaddress_copy(struct connman_ipaddress *ipaddress,
+ struct connman_ipaddress *source);
+
enum connman_ipconfig_type {
CONNMAN_IPCONFIG_TYPE_UNKNOWN = 0,
CONNMAN_IPCONFIG_TYPE_IPV4 = 1,
@@ -70,6 +82,9 @@ void connman_ipconfig_set_ops(struct connman_ipconfig *ipconfig,
int connman_ipconfig_set_method(struct connman_ipconfig *ipconfig,
enum connman_ipconfig_method method);
+void connman_ipconfig_bind(struct connman_ipconfig *ipconfig,
+ struct connman_ipaddress *ipaddress);
+
#define CONNMAN_IPCONFIG_PRIORITY_LOW -100
#define CONNMAN_IPCONFIG_PRIORITY_DEFAULT 0
#define CONNMAN_IPCONFIG_PRIORITY_HIGH 100
diff --git a/src/ipconfig.c b/src/ipconfig.c
index 0503b355..faed54d3 100644
--- a/src/ipconfig.c
+++ b/src/ipconfig.c
@@ -34,9 +34,15 @@
#include "connman.h"
-struct connman_ipaddress {
- unsigned char prefixlen;
- char *address;
+struct connman_ipconfig {
+ gint refcount;
+ int index;
+
+ const struct connman_ipconfig_ops *ops;
+ void *ops_data;
+
+ enum connman_ipconfig_method method;
+ struct connman_ipaddress *address;
};
struct connman_ipdevice {
@@ -47,21 +53,48 @@ struct connman_ipdevice {
GSList *address_list;
char *gateway;
-};
-
-struct connman_ipconfig {
- gint refcount;
- int index;
-
- const struct connman_ipconfig_ops *ops;
- void *ops_data;
- enum connman_ipconfig_method method;
+ struct connman_ipconfig *config;
+ struct connman_ipconfig_driver *driver;
};
static GHashTable *ipdevice_hash = NULL;
static GList *ipconfig_list = NULL;
+struct connman_ipaddress *connman_ipaddress_alloc(void)
+{
+ struct connman_ipaddress *ipaddress;
+
+ ipaddress = g_try_new0(struct connman_ipaddress, 1);
+ if (ipaddress == NULL)
+ return NULL;
+
+ return ipaddress;
+}
+
+void connman_ipaddress_free(struct connman_ipaddress *ipaddress)
+{
+ g_free(ipaddress->broadcast);
+ g_free(ipaddress->peer);
+ g_free(ipaddress->local);
+ g_free(ipaddress);
+}
+
+void connman_ipaddress_copy(struct connman_ipaddress *ipaddress,
+ struct connman_ipaddress *source)
+{
+ ipaddress->prefixlen = source->prefixlen;
+
+ g_free(ipaddress->local);
+ ipaddress->local = g_strdup(source->local);
+
+ g_free(ipaddress->peer);
+ ipaddress->peer = g_strdup(source->peer);
+
+ g_free(ipaddress->broadcast);
+ ipaddress->broadcast = g_strdup(source->broadcast);
+}
+
static void free_address_list(struct connman_ipdevice *ipdevice)
{
GSList *list;
@@ -69,8 +102,7 @@ static void free_address_list(struct connman_ipdevice *ipdevice)
for (list = ipdevice->address_list; list; list = list->next) {
struct connman_ipaddress *ipaddress = list->data;
- g_free(ipaddress->address);
- g_free(ipaddress);
+ connman_ipaddress_free(ipaddress);
list->data = NULL;
}
@@ -79,14 +111,14 @@ static void free_address_list(struct connman_ipdevice *ipdevice)
}
static struct connman_ipaddress *find_ipaddress(struct connman_ipdevice *ipdevice,
- unsigned char prefixlen, const char *address)
+ unsigned char prefixlen, const char *local)
{
GSList *list;
for (list = ipdevice->address_list; list; list = list->next) {
struct connman_ipaddress *ipaddress = list->data;
- if (g_strcmp0(ipaddress->address, address) == 0 &&
+ if (g_strcmp0(ipaddress->local, local) == 0 &&
ipaddress->prefixlen == prefixlen)
return ipaddress;
}
@@ -131,6 +163,9 @@ static void free_ipdevice(gpointer data)
connman_info("%s {remove} index %d", ipdevice->ifname,
ipdevice->index);
+ if (ipdevice->config != NULL)
+ connman_ipconfig_unref(ipdevice->config);
+
free_address_list(ipdevice);
g_free(ipdevice->gateway);
@@ -138,6 +173,91 @@ static void free_ipdevice(gpointer data)
g_free(ipdevice);
}
+static GSList *driver_list = NULL;
+
+static gint compare_priority(gconstpointer a, gconstpointer b)
+{
+ const struct connman_ipconfig_driver *driver1 = a;
+ const struct connman_ipconfig_driver *driver2 = b;
+
+ return driver2->priority - driver1->priority;
+}
+
+/**
+ * connman_ipconfig_driver_register:
+ * @driver: IP configuration driver
+ *
+ * Register a new IP configuration driver
+ *
+ * Returns: %0 on success
+ */
+int connman_ipconfig_driver_register(struct connman_ipconfig_driver *driver)
+{
+ DBG("driver %p name %s", driver, driver->name);
+
+ driver_list = g_slist_insert_sorted(driver_list, driver,
+ compare_priority);
+
+ return 0;
+}
+
+/**
+ * connman_ipconfig_driver_unregister:
+ * @driver: IP configuration driver
+ *
+ * Remove a previously registered IP configuration driver.
+ */
+void connman_ipconfig_driver_unregister(struct connman_ipconfig_driver *driver)
+{
+ DBG("driver %p name %s", driver, driver->name);
+
+ driver_list = g_slist_remove(driver_list, driver);
+}
+
+static void __connman_ipconfig_lower_up(struct connman_ipdevice *ipdevice)
+{
+ GSList *list;
+
+ DBG("ipconfig %p", ipdevice->config);
+
+ if (ipdevice->config == NULL)
+ return;
+
+ switch (ipdevice->config->method) {
+ case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
+ case CONNMAN_IPCONFIG_METHOD_IGNORE:
+ case CONNMAN_IPCONFIG_METHOD_STATIC:
+ return;
+ case CONNMAN_IPCONFIG_METHOD_DHCP:
+ break;
+ }
+
+ if (ipdevice->driver != NULL)
+ return;
+
+ for (list = driver_list; list; list = list->next) {
+ struct connman_ipconfig_driver *driver = list->data;
+
+ if (driver->request(ipdevice->config) == 0) {
+ ipdevice->driver = driver;
+ break;
+ }
+ }
+}
+
+static void __connman_ipconfig_lower_down(struct connman_ipdevice *ipdevice)
+{
+ DBG("ipconfig %p", ipdevice->config);
+
+ if (ipdevice->config == NULL)
+ return;
+
+ if (ipdevice->driver == NULL)
+ return;
+
+ ipdevice->driver->release(ipdevice->config);
+}
+
void __connman_ipconfig_newlink(int index, unsigned short type,
unsigned int flags)
{
@@ -161,6 +281,17 @@ void __connman_ipconfig_newlink(int index, unsigned short type,
ipdevice->ifname = connman_inet_ifname(index);
ipdevice->type = type;
+ ipdevice->config = connman_ipconfig_create(index);
+ if (ipdevice->config == NULL) {
+ g_free(ipdevice->ifname);
+ g_free(ipdevice);
+ return;
+ }
+
+ if (type == ARPHRD_ETHER)
+ connman_ipconfig_set_method(ipdevice->config,
+ CONNMAN_IPCONFIG_METHOD_IGNORE);
+
g_hash_table_insert(ipdevice_hash, GINT_TO_POINTER(index), ipdevice);
connman_info("%s {create} index %d type %d <%s>", ipdevice->ifname,
@@ -227,14 +358,24 @@ update:
ipconfig->ops->down(ipconfig);
}
}
+
+ if (lower_up)
+ __connman_ipconfig_lower_up(ipdevice);
+ if (lower_down)
+ __connman_ipconfig_lower_down(ipdevice);
}
void __connman_ipconfig_dellink(int index)
{
+ struct connman_ipdevice *ipdevice;
GList *list;
DBG("index %d", index);
+ ipdevice = g_hash_table_lookup(ipdevice_hash, GINT_TO_POINTER(index));
+ if (ipdevice == NULL)
+ return;
+
for (list = g_list_first(ipconfig_list); list;
list = g_list_next(list)) {
struct connman_ipconfig *ipconfig = list->data;
@@ -250,6 +391,8 @@ void __connman_ipconfig_dellink(int index)
ipconfig->ops->down(ipconfig);
}
+ __connman_ipconfig_lower_down(ipdevice);
+
g_hash_table_remove(ipdevice_hash, GINT_TO_POINTER(index));
}
@@ -265,12 +408,12 @@ void __connman_ipconfig_newaddr(int index, const char *label,
if (ipdevice == NULL)
return;
- ipaddress = g_try_new0(struct connman_ipaddress, 1);
+ ipaddress = connman_ipaddress_alloc();
if (ipaddress == NULL)
return;
ipaddress->prefixlen = prefixlen;
- ipaddress->address = g_strdup(address);
+ ipaddress->local = g_strdup(address);
ipdevice->address_list = g_slist_append(ipdevice->address_list,
ipaddress);
@@ -298,8 +441,7 @@ void __connman_ipconfig_deladdr(int index, const char *label,
ipdevice->address_list = g_slist_remove(ipdevice->address_list,
ipaddress);
- g_free(ipaddress->address);
- g_free(ipaddress);
+ connman_ipaddress_free(ipaddress);
connman_info("%s {del} address %s/%u label %s", ipdevice->ifname,
address, prefixlen, label);
@@ -419,6 +561,12 @@ struct connman_ipconfig *connman_ipconfig_create(int index)
ipconfig->index = index;
+ ipconfig->address = connman_ipaddress_alloc();
+ if (ipconfig->address == NULL) {
+ g_free(ipconfig);
+ return NULL;
+ }
+
DBG("ipconfig %p", ipconfig);
ipconfig_list = g_list_append(ipconfig_list, ipconfig);
@@ -450,6 +598,7 @@ void connman_ipconfig_unref(struct connman_ipconfig *ipconfig)
if (g_atomic_int_dec_and_test(&ipconfig->refcount) == TRUE) {
ipconfig_list = g_list_remove(ipconfig_list, ipconfig);
+ connman_ipaddress_free(ipconfig->address);
g_free(ipconfig);
}
}
@@ -537,6 +686,19 @@ int connman_ipconfig_set_method(struct connman_ipconfig *ipconfig,
return 0;
}
+/**
+ * connman_ipconfig_bind:
+ * @ipconfig: ipconfig structure
+ * @ipaddress: ipaddress structure
+ *
+ * Bind IP address details to configuration
+ */
+void connman_ipconfig_bind(struct connman_ipconfig *ipconfig,
+ struct connman_ipaddress *ipaddress)
+{
+ connman_ipaddress_copy(ipconfig->address, ipaddress);
+}
+
const char *__connman_ipconfig_method2string(enum connman_ipconfig_method method)
{
switch (method) {
@@ -632,47 +794,6 @@ int __connman_ipconfig_save(struct connman_ipconfig *ipconfig,
return 0;
}
-static GSList *driver_list = NULL;
-
-static gint compare_priority(gconstpointer a, gconstpointer b)
-{
- const struct connman_ipconfig_driver *driver1 = a;
- const struct connman_ipconfig_driver *driver2 = b;
-
- return driver2->priority - driver1->priority;
-}
-
-/**
- * connman_ipconfig_driver_register:
- * @driver: IP configuration driver
- *
- * Register a new IP configuration driver
- *
- * Returns: %0 on success
- */
-int connman_ipconfig_driver_register(struct connman_ipconfig_driver *driver)
-{
- DBG("driver %p name %s", driver, driver->name);
-
- driver_list = g_slist_insert_sorted(driver_list, driver,
- compare_priority);
-
- return 0;
-}
-
-/**
- * connman_ipconfig_driver_unregister:
- * @driver: IP configuration driver
- *
- * Remove a previously registered IP configuration driver.
- */
-void connman_ipconfig_driver_unregister(struct connman_ipconfig_driver *driver)
-{
- DBG("driver %p name %s", driver, driver->name);
-
- driver_list = g_slist_remove(driver_list, driver);
-}
-
int __connman_ipconfig_init(void)
{
DBG("");