return device->element.path;
}
-static void device_up(struct connman_ipconfig *ipconfig)
-{
- connman_info("%s up", connman_ipconfig_get_ifname(ipconfig));
-}
-
-static void device_down(struct connman_ipconfig *ipconfig)
-{
- connman_info("%s down", connman_ipconfig_get_ifname(ipconfig));
-}
-
-static void device_lower_up(struct connman_ipconfig *ipconfig)
-{
- connman_info("%s lower up", connman_ipconfig_get_ifname(ipconfig));
-}
-
-static void device_lower_down(struct connman_ipconfig *ipconfig)
-{
- connman_info("%s lower down", connman_ipconfig_get_ifname(ipconfig));
-}
-
-static void device_ip_bound(struct connman_ipconfig *ipconfig)
-{
- connman_info("%s ip bound", connman_ipconfig_get_ifname(ipconfig));
-}
-
-static void device_ip_release(struct connman_ipconfig *ipconfig)
-{
- connman_info("%s ip release", connman_ipconfig_get_ifname(ipconfig));
-}
-
-static const struct connman_ipconfig_ops device_ops = {
- .up = device_up,
- .down = device_down,
- .lower_up = device_lower_up,
- .lower_down = device_lower_down,
- .ip_bound = device_ip_bound,
- .ip_release = device_ip_release,
-};
-
/**
* connman_device_set_index:
* @device: device structure
}
device->ipconfig = connman_ipconfig_create(index);
-
- connman_ipconfig_set_ops(device->ipconfig, &device_ops);
}
/**
gint refcount;
int index;
+ struct connman_ipconfig *origin;
+
const struct connman_ipconfig_ops *ops;
void *ops_data;
char *gateway;
struct connman_ipconfig *config;
+
struct connman_ipconfig_driver *driver;
+ struct connman_ipconfig *driver_config;
};
static GHashTable *ipdevice_hash = NULL;
void connman_ipaddress_free(struct connman_ipaddress *ipaddress)
{
+ if (ipaddress == NULL)
+ return;
+
g_free(ipaddress->broadcast);
g_free(ipaddress->peer);
g_free(ipaddress->local);
void connman_ipaddress_copy(struct connman_ipaddress *ipaddress,
struct connman_ipaddress *source)
{
+ if (ipaddress == NULL || source == NULL)
+ return;
+
ipaddress->prefixlen = source->prefixlen;
g_free(ipaddress->local);
if (ipdevice->driver != NULL)
return;
+ ipdevice->driver_config = connman_ipconfig_clone(ipdevice->config);
+ if (ipdevice->driver_config == NULL)
+ return;
+
for (list = driver_list; list; list = list->next) {
struct connman_ipconfig_driver *driver = list->data;
- if (driver->request(ipdevice->config) == 0) {
+ if (driver->request(ipdevice->driver_config) == 0) {
ipdevice->driver = driver;
break;
}
}
+
+ if (ipdevice->driver == NULL) {
+ connman_ipconfig_unref(ipdevice->driver_config);
+ ipdevice->driver_config = NULL;
+ }
}
static void __connman_ipconfig_lower_down(struct connman_ipdevice *ipdevice)
if (ipdevice->driver == NULL)
return;
- ipdevice->driver->release(ipdevice->config);
+ ipdevice->driver->release(ipdevice->driver_config);
+
+ ipdevice->driver = NULL;
+
+ connman_ipconfig_unref(ipdevice->driver_config);
+ ipdevice->driver_config = NULL;
connman_inet_clear_address(ipdevice->index);
}
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,
}
/**
+ * connman_ipconfig_clone:
+ *
+ * Clone an ipconfig structure and create new reference.
+ *
+ * Returns: a newly-allocated #connman_ipconfig structure
+ */
+struct connman_ipconfig *connman_ipconfig_clone(struct connman_ipconfig *ipconfig)
+{
+ struct connman_ipconfig *ipconfig_clone;
+
+ DBG("ipconfig %p", ipconfig);
+
+ ipconfig_clone = g_try_new0(struct connman_ipconfig, 1);
+ if (ipconfig_clone == NULL)
+ return NULL;
+
+ ipconfig_clone->refcount = 1;
+
+ ipconfig_clone->origin = connman_ipconfig_ref(ipconfig);
+
+ ipconfig_clone->index = -1;
+
+ return ipconfig_clone;
+}
+
+/**
* connman_ipconfig_ref:
* @ipconfig: ipconfig structure
*
if (g_atomic_int_dec_and_test(&ipconfig->refcount) == TRUE) {
connman_ipconfig_set_ops(ipconfig, NULL);
+ if (ipconfig->origin != NULL) {
+ connman_ipconfig_unref(ipconfig->origin);
+ ipconfig->origin = NULL;
+ }
+
connman_ipaddress_free(ipconfig->address);
g_free(ipconfig);
}
*/
int connman_ipconfig_get_index(struct connman_ipconfig *ipconfig)
{
+ if (ipconfig->origin != NULL)
+ return ipconfig->origin->index;
+
return ipconfig->index;
}
void connman_ipconfig_bind(struct connman_ipconfig *ipconfig,
struct connman_ipaddress *ipaddress)
{
- connman_ipaddress_copy(ipconfig->address, ipaddress);
+ struct connman_ipconfig *origin;
- connman_inet_set_address(ipconfig->index, ipconfig->address);
+ origin = ipconfig->origin ? ipconfig->origin : ipconfig;
+
+ connman_ipaddress_copy(origin->address, ipaddress);
+
+ connman_inet_set_address(origin->index, origin->address);
+}
+
+int __connman_ipconfig_enable(struct connman_ipconfig *ipconfig)
+{
+ struct connman_ipdevice *ipdevice;
+
+ DBG("ipconfig %p", ipconfig);
+
+ if (ipconfig == NULL || ipconfig->index < 0)
+ return -ENODEV;
+
+ ipdevice = g_hash_table_lookup(ipdevice_hash,
+ GINT_TO_POINTER(ipconfig->index));
+ if (ipdevice == NULL)
+ return -ENXIO;
+
+ if (ipdevice->config != NULL)
+ connman_ipconfig_unref(ipdevice->config);
+
+ ipdevice->config = connman_ipconfig_ref(ipconfig);
+
+ return 0;
+}
+
+int __connman_ipconfig_disable(struct connman_ipconfig *ipconfig)
+{
+ struct connman_ipdevice *ipdevice;
+
+ DBG("ipconfig %p", ipconfig);
+
+ if (ipconfig == NULL || ipconfig->index < 0)
+ return -ENODEV;
+
+ ipdevice = g_hash_table_lookup(ipdevice_hash,
+ GINT_TO_POINTER(ipconfig->index));
+ if (ipdevice == NULL)
+ return -ENXIO;
+
+ if (ipdevice->config == NULL || ipdevice->config != ipconfig)
+ return -EINVAL;
+
+ connman_ipconfig_unref(ipdevice->config);
+ ipdevice->config = NULL;
+
+ return 0;
}
const char *__connman_ipconfig_method2string(enum connman_ipconfig_method method)
else if (service->device != NULL)
__connman_device_disconnect(service->device);
+ __connman_ipconfig_disable(service->ipconfig);
+
if (service->pending != NULL) {
DBusMessage *reply;
if (prepare_network(service) == FALSE)
return -EINVAL;
+ __connman_ipconfig_enable(service->ipconfig);
+
err = __connman_network_connect(service->network);
} else if (service->device != NULL) {
if (service->favorite == FALSE)
return -ENOLINK;
+ __connman_ipconfig_enable(service->ipconfig);
+
err = __connman_device_connect(service->device);
} else
return -EOPNOTSUPP;
if (err < 0) {
- if (err != -EINPROGRESS)
+ if (err != -EINPROGRESS) {
+ __connman_ipconfig_disable(service->ipconfig);
return err;
+ }
service->timeout = g_timeout_add_seconds(45,
connect_timeout, service);
} else
return -EOPNOTSUPP;
+ __connman_ipconfig_disable(service->ipconfig);
+
if (err < 0) {
if (err != -EINPROGRESS)
return err;
return 0;
}
+static void service_up(struct connman_ipconfig *ipconfig)
+{
+ connman_info("%s up", connman_ipconfig_get_ifname(ipconfig));
+}
+
+static void service_down(struct connman_ipconfig *ipconfig)
+{
+ connman_info("%s down", connman_ipconfig_get_ifname(ipconfig));
+}
+
+static void service_lower_up(struct connman_ipconfig *ipconfig)
+{
+ connman_info("%s lower up", connman_ipconfig_get_ifname(ipconfig));
+}
+
+static void service_lower_down(struct connman_ipconfig *ipconfig)
+{
+ connman_info("%s lower down", connman_ipconfig_get_ifname(ipconfig));
+}
+
+static void service_ip_bound(struct connman_ipconfig *ipconfig)
+{
+ connman_info("%s ip bound", connman_ipconfig_get_ifname(ipconfig));
+}
+
+static void service_ip_release(struct connman_ipconfig *ipconfig)
+{
+ connman_info("%s ip release", connman_ipconfig_get_ifname(ipconfig));
+}
+
+static const struct connman_ipconfig_ops service_ops = {
+ .up = service_up,
+ .down = service_down,
+ .lower_up = service_lower_up,
+ .lower_down = service_lower_down,
+ .ip_bound = service_ip_bound,
+ .ip_release = service_ip_release,
+};
+
+static void setup_ipconfig(struct connman_service *service, int index)
+{
+ if (index < 0)
+ return;
+
+ service->ipconfig = connman_ipconfig_create(index);
+ if (service->ipconfig == NULL)
+ return;
+
+ connman_ipconfig_set_method(service->ipconfig,
+ CONNMAN_IPCONFIG_METHOD_DHCP);
+
+ __connman_storage_load_service(service);
+
+ connman_ipconfig_set_data(service->ipconfig, service);
+
+ connman_ipconfig_set_ops(service->ipconfig, &service_ops);
+}
+
/**
* __connman_service_lookup_from_device:
* @device: device structure
service->device = device;
+ setup_ipconfig(service, connman_device_get_index(device));
+
service_register(service);
__connman_profile_changed(TRUE);
update_from_network(service, network);
+ setup_ipconfig(service, connman_network_get_index(network));
+
service_register(service);
__connman_profile_changed(TRUE);