*
* Connection Manager
*
- * Copyright (C) 2007-2010 Intel Corporation. All rights reserved.
+ * Copyright (C) 2007-2012 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
while (networks[i] != NULL) {
char **elems = g_strsplit(networks[i], "/", 0);
- char *network, *netmask = NULL;
+ char *network, *netmask;
int family = PF_UNSPEC, ret;
if (elems == NULL)
break;
network = elems[0];
- if (elems[1] != NULL)
- netmask = elems[1];
+ if (network == NULL || *network == '\0') {
+ DBG("no network/netmask set");
+ g_strfreev(elems);
+ break;
+ }
+
+ netmask = elems[1];
+ if (netmask != NULL && *netmask == '\0') {
+ DBG("no netmask set");
+ g_strfreev(elems);
+ break;
+ }
if (g_strrstr(network, ":") != NULL)
family = AF_INET6;
/* We have netmask length */
in_addr_t addr;
struct in_addr netmask_in;
- unsigned char prefix_len = atoi(netmask);
+ unsigned char prefix_len = 32;
+
+ if (netmask != NULL)
+ prefix_len = atoi(netmask);
addr = 0xffffffff << (32 - prefix_len);
netmask_in.s_addr = htonl(addr);
g_strfreev(providers);
}
+static char **get_user_networks(DBusMessageIter *array, int *count)
+{
+ DBusMessageIter entry;
+ char **networks = NULL;
+ GSList *list = NULL, *l;
+ int len;
+
+ dbus_message_iter_recurse(array, &entry);
+
+ while (dbus_message_iter_get_arg_type(&entry) == DBUS_TYPE_STRING) {
+ const char *val;
+ dbus_message_iter_get_basic(&entry, &val);
+
+ list = g_slist_prepend(list, g_strdup(val));
+ dbus_message_iter_next(&entry);
+ }
+
+ len = g_slist_length(list);
+ if (len == 0)
+ goto out;
+
+ networks = g_try_new(char *, len + 1);
+ if (networks == NULL)
+ goto out;
+
+ *count = len;
+ networks[len] = 0;
+
+ for (l = list; l != NULL; l = g_slist_next(l))
+ networks[--len] = l->data;
+
+out:
+ g_slist_free(list);
+
+ return networks;
+}
+
int __connman_provider_create_and_connect(DBusMessage *msg)
{
struct connman_provider *provider;
DBusMessageIter iter, array;
const char *type = NULL, *name = NULL, *service_path;
const char *host = NULL, *domain = NULL;
+ char **networks = NULL;
char *ident;
- int err;
+ int err, count = 0;
dbus_message_iter_init(msg, &iter);
dbus_message_iter_recurse(&iter, &array);
else if (g_str_equal(key, "VPN.Domain") == TRUE)
dbus_message_iter_get_basic(&value, &domain);
break;
+ case DBUS_TYPE_ARRAY:
+ if (g_str_equal(key, "Networks") == TRUE)
+ networks = get_user_networks(&value, &count);
+ break;
}
dbus_message_iter_next(&array);
if (host == NULL || domain == NULL)
return -EINVAL;
- DBG("Type %s name %s", type, name);
+ DBG("Type %s name %s networks %p", type, name, networks);
if (type == NULL || name == NULL)
return -EOPNOTSUPP;
connman_provider_load(provider);
}
+ if (networks != NULL) {
+ g_strfreev(provider->user_networks);
+ provider->user_networks = networks;
+ provider->num_user_networks = count;
+ set_user_networks(provider, provider->user_networks);
+ }
+
dbus_message_iter_init(msg, &iter);
dbus_message_iter_recurse(&iter, &array);
return g_hash_table_lookup(provider->setting_strings, key);
}
+connman_bool_t
+__connman_provider_check_routes(struct connman_provider *provider)
+{
+ if (provider == NULL)
+ return FALSE;
+
+ if (provider->user_routes != NULL &&
+ g_hash_table_size(provider->user_routes) > 0)
+ return TRUE;
+
+ if (provider->routes != NULL &&
+ g_hash_table_size(provider->routes) > 0)
+ return TRUE;
+
+ return FALSE;
+}
+
void *connman_provider_get_data(struct connman_provider *provider)
{
return provider->driver_data;
}
+static struct connman_provider *provider_get(int index)
+{
+ GHashTableIter iter;
+ gpointer value, key;
+
+ g_hash_table_iter_init(&iter, provider_hash);
+
+ while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
+ struct connman_provider *provider = value;
+
+ if (provider->index == index)
+ return provider;
+ }
+
+ return NULL;
+}
+
+static void provider_service_changed(struct connman_service *service,
+ enum connman_service_state state)
+{
+ struct connman_provider *provider;
+ int vpn_index, service_index;
+
+ if (service == NULL)
+ return;
+
+ switch (state) {
+ case CONNMAN_SERVICE_STATE_UNKNOWN:
+ case CONNMAN_SERVICE_STATE_IDLE:
+ case CONNMAN_SERVICE_STATE_ASSOCIATION:
+ case CONNMAN_SERVICE_STATE_CONFIGURATION:
+ case CONNMAN_SERVICE_STATE_READY:
+ case CONNMAN_SERVICE_STATE_ONLINE:
+ return;
+ case CONNMAN_SERVICE_STATE_DISCONNECT:
+ case CONNMAN_SERVICE_STATE_FAILURE:
+ break;
+ }
+
+ service_index = __connman_service_get_index(service);
+
+ vpn_index = __connman_connection_get_vpn_index(service_index);
+
+ DBG("service %p %s state %d index %d/%d", service,
+ __connman_service_get_ident(service),
+ state, service_index, vpn_index);
+
+ if (vpn_index < 0)
+ return;
+
+ provider = provider_get(vpn_index);
+ if (provider == NULL)
+ return;
+
+ DBG("disconnect %p index %d", provider, vpn_index);
+
+ __connman_provider_disconnect(provider);
+
+ return;
+}
+
static struct connman_notifier provider_notifier = {
.name = "provider",
.offline_mode = provider_offline_mode,
+ .service_state_changed = provider_service_changed,
};
int __connman_provider_init(void)