*
* Connection Manager
*
- * Copyright (C) 2007-2009 Intel Corporation. All rights reserved.
+ * Copyright (C) 2007-2010 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
static GSequence *service_list = NULL;
static GHashTable *service_hash = NULL;
+struct connman_stats {
+ connman_bool_t valid;
+ connman_bool_t enabled;
+ unsigned int rx_packets_last;
+ unsigned int tx_packets_last;
+ unsigned int rx_packets;
+ unsigned int tx_packets;
+ unsigned int rx_bytes_last;
+ unsigned int tx_bytes_last;
+ unsigned int rx_bytes;
+ unsigned int tx_bytes;
+ unsigned int rx_errors_last;
+ unsigned int tx_errors_last;
+ unsigned int rx_errors;
+ unsigned int tx_errors;
+ unsigned int rx_dropped_last;
+ unsigned int tx_dropped_last;
+ unsigned int rx_dropped;
+ unsigned int tx_dropped;
+ unsigned int time_start;
+ unsigned int time;
+ GTimer *timer;
+};
+
struct connman_service {
gint refcount;
char *identifier;
enum connman_service_error error;
connman_uint8_t strength;
connman_bool_t favorite;
+ connman_bool_t immutable;
connman_bool_t hidden;
connman_bool_t ignore;
connman_bool_t autoconnect;
char *mcc;
char *mnc;
connman_bool_t roaming;
+ connman_bool_t login_required;
struct connman_ipconfig *ipconfig;
struct connman_network *network;
+ char **nameservers;
+ char *nameserver;
+ char **domains;
+ /* 802.1x settings from the config files */
+ char *eap;
+ char *identity;
+ char *ca_cert_file;
+ char *client_cert_file;
+ char *private_key_file;
+ char *private_key_passphrase;
+ char *phase2;
DBusMessage *pending;
guint timeout;
+ struct connman_location *location;
+ struct connman_stats stats;
};
static void append_path(gpointer value, gpointer user_data)
&service->path);
}
-void __connman_service_list(DBusMessageIter *iter)
+void __connman_service_list(DBusMessageIter *iter, void *user_data)
{
- DBG("");
-
g_sequence_foreach(service_list, append_path, iter);
}
return "bluetooth";
case CONNMAN_SERVICE_TYPE_CELLULAR:
return "cellular";
+ case CONNMAN_SERVICE_TYPE_GPS:
+ return "gps";
case CONNMAN_SERVICE_TYPE_VPN:
return "vpn";
}
return "configuration";
case CONNMAN_SERVICE_STATE_READY:
return "ready";
+ case CONNMAN_SERVICE_STATE_ONLINE:
+ return "online";
case CONNMAN_SERVICE_STATE_DISCONNECT:
return "disconnect";
case CONNMAN_SERVICE_STATE_FAILURE:
return CONNMAN_SERVICE_ERROR_UNKNOWN;
}
+static connman_bool_t is_connecting(struct connman_service *service)
+{
+ switch (service->state) {
+ case CONNMAN_SERVICE_STATE_UNKNOWN:
+ case CONNMAN_SERVICE_STATE_IDLE:
+ case CONNMAN_SERVICE_STATE_FAILURE:
+ case CONNMAN_SERVICE_STATE_DISCONNECT:
+ case CONNMAN_SERVICE_STATE_READY:
+ case CONNMAN_SERVICE_STATE_ONLINE:
+ break;
+ case CONNMAN_SERVICE_STATE_ASSOCIATION:
+ case CONNMAN_SERVICE_STATE_CONFIGURATION:
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static connman_bool_t is_connected(const struct connman_service *service)
+{
+ switch (service->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_DISCONNECT:
+ case CONNMAN_SERVICE_STATE_FAILURE:
+ break;
+ case CONNMAN_SERVICE_STATE_READY:
+ case CONNMAN_SERVICE_STATE_ONLINE:
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static void update_nameservers(struct connman_service *service)
+{
+ const char *ifname = connman_ipconfig_get_ifname(service->ipconfig);
+
+ if (ifname == NULL)
+ return;
+
+ switch (service->state) {
+ case CONNMAN_SERVICE_STATE_UNKNOWN:
+ case CONNMAN_SERVICE_STATE_IDLE:
+ case CONNMAN_SERVICE_STATE_ASSOCIATION:
+ case CONNMAN_SERVICE_STATE_CONFIGURATION:
+ return;
+ case CONNMAN_SERVICE_STATE_FAILURE:
+ case CONNMAN_SERVICE_STATE_DISCONNECT:
+ connman_resolver_remove_all(ifname);
+ return;
+ case CONNMAN_SERVICE_STATE_READY:
+ case CONNMAN_SERVICE_STATE_ONLINE:
+ break;
+ }
+
+ connman_resolver_remove_all(ifname);
+
+ if (service->nameservers != NULL) {
+ int i;
+
+ for (i = 0; service->nameservers[i]; i++)
+ connman_resolver_append(ifname, NULL,
+ service->nameservers[i]);
+ } else if (service->nameserver != NULL)
+ connman_resolver_append(ifname, NULL, service->nameserver);
+
+ connman_resolver_flush();
+}
+
+void __connman_service_append_nameserver(struct connman_service *service,
+ const char *nameserver)
+{
+ DBG("service %p nameserver %s", service, nameserver);
+
+ if (nameserver == NULL)
+ return;
+
+ g_free(service->nameserver);
+ service->nameserver = g_strdup(nameserver);
+
+ update_nameservers(service);
+}
+
+void __connman_service_remove_nameserver(struct connman_service *service,
+ const char *nameserver)
+{
+ DBG("service %p nameserver %s", service, nameserver);
+
+ if (nameserver == NULL)
+ return;
+
+ g_free(service->nameserver);
+ service->nameserver = NULL;
+
+ update_nameservers(service);
+}
+
+void __connman_service_nameserver_add_routes(struct connman_service *service,
+ const char *gw)
+{
+ int index;
+
+ if (service == NULL)
+ return;
+
+ index = connman_network_get_index(service->network);
+
+ if (service->nameservers != NULL) {
+ int i;
+
+ /*
+ * We add nameservers host routes for nameservers that
+ * are not on our subnet. For those who are, the subnet
+ * route will be installed by the time the dns proxy code
+ * tries to reach them. The subnet route is installed
+ * when setting the interface IP address.
+ */
+ for (i = 0; service->nameservers[i]; i++) {
+ if (connman_inet_compare_subnet(index,
+ service->nameservers[i]))
+ continue;
+
+ connman_inet_add_host_route(index,
+ service->nameservers[i], gw);
+ }
+ } else if (service->nameserver != NULL) {
+ if (connman_inet_compare_subnet(index, service->nameserver))
+ return;
+
+ connman_inet_add_host_route(index, service->nameserver, gw);
+ }
+}
+
+void __connman_service_nameserver_del_routes(struct connman_service *service)
+{
+ int index;
+
+ if (service == NULL)
+ return;
+
+ index = connman_network_get_index(service->network);
+
+ if (service->nameservers != NULL) {
+ int i;
+
+ for (i = 0; service->nameservers[i]; i++)
+ connman_inet_del_host_route(index,
+ service->nameservers[i]);
+ } else if (service->nameserver != NULL) {
+ connman_inet_del_host_route(index, service->nameserver);
+ }
+}
+
+static void __connman_service_stats_start(struct connman_service *service)
+{
+ DBG("service %p", service);
+
+ if (service->stats.timer == NULL)
+ return;
+
+ service->stats.enabled = TRUE;
+
+ service->stats.time_start = service->stats.time;
+
+ g_timer_start(service->stats.timer);
+
+ __connman_counter_add_service(service);
+}
+
+static void __connman_service_stats_stop(struct connman_service *service)
+{
+ unsigned int seconds;
+
+ DBG("service %p", service);
+
+ if (service->stats.timer == NULL)
+ return;
+
+ if (service->stats.enabled == FALSE)
+ return;
+
+ __connman_counter_remove_service(service);
+
+ g_timer_stop(service->stats.timer);
+
+ seconds = g_timer_elapsed(service->stats.timer, NULL);
+ service->stats.time = service->stats.time_start + seconds;
+
+ service->stats.enabled = FALSE;
+}
+
+static int __connman_service_stats_load(struct connman_service *service,
+ GKeyFile *keyfile, const char *identifier)
+{
+ service->stats.rx_packets = g_key_file_get_integer(keyfile,
+ identifier, "rx_packets", NULL);
+ service->stats.tx_packets = g_key_file_get_integer(keyfile,
+ identifier, "tx_packets", NULL);
+ service->stats.rx_bytes = g_key_file_get_integer(keyfile,
+ identifier, "rx_bytes", NULL);
+ service->stats.tx_bytes = g_key_file_get_integer(keyfile,
+ identifier, "tx_bytes", NULL);
+ service->stats.rx_errors = g_key_file_get_integer(keyfile,
+ identifier, "rx_errors", NULL);
+ service->stats.tx_errors = g_key_file_get_integer(keyfile,
+ identifier, "tx_errors", NULL);
+ service->stats.rx_dropped = g_key_file_get_integer(keyfile,
+ identifier, "rx_dropped", NULL);
+ service->stats.tx_dropped = g_key_file_get_integer(keyfile,
+ identifier, "tx_dropped", NULL);
+ service->stats.time = g_key_file_get_integer(keyfile,
+ identifier, "time", NULL);
+
+ return 0;
+}
+
+static int __connman_service_stats_save(struct connman_service *service,
+ GKeyFile *keyfile, const char *identifier)
+{
+ g_key_file_set_integer(keyfile, identifier, "rx_packets",
+ service->stats.rx_packets);
+ g_key_file_set_integer(keyfile, identifier, "tx_packets",
+ service->stats.tx_packets);
+ g_key_file_set_integer(keyfile, identifier, "rx_bytes",
+ service->stats.rx_bytes);
+ g_key_file_set_integer(keyfile, identifier, "tx_bytes",
+ service->stats.tx_bytes);
+ g_key_file_set_integer(keyfile, identifier, "rx_errors",
+ service->stats.rx_errors);
+ g_key_file_set_integer(keyfile, identifier, "tx_errors",
+ service->stats.tx_errors);
+ g_key_file_set_integer(keyfile, identifier, "rx_dropped",
+ service->stats.rx_dropped);
+ g_key_file_set_integer(keyfile, identifier, "tx_dropped",
+ service->stats.tx_dropped);
+ g_key_file_set_integer(keyfile, identifier, "time",
+ service->stats.time);
+
+ return 0;
+}
+
+static void __connman_service_reset_stats(struct connman_service *service)
+{
+ DBG("service %p", service);
+
+ service->stats.valid = FALSE;
+ service->stats.rx_packets = 0;
+ service->stats.tx_packets = 0;
+ service->stats.rx_bytes = 0;
+ service->stats.tx_bytes = 0;
+ service->stats.rx_errors = 0;
+ service->stats.tx_errors = 0;
+ service->stats.rx_dropped = 0;
+ service->stats.tx_dropped = 0;
+ service->stats.time = 0;
+ service->stats.time_start = 0;
+ g_timer_reset(service->stats.timer);
+
+}
+
+unsigned long __connman_service_stats_get_rx_packets(struct connman_service *service)
+{
+ return service->stats.rx_packets;
+}
+
+unsigned long __connman_service_stats_get_tx_packets(struct connman_service *service)
+{
+ return service->stats.tx_packets;
+}
+
+unsigned long __connman_service_stats_get_rx_bytes(struct connman_service *service)
+{
+ return service->stats.rx_bytes;
+}
+
+unsigned long __connman_service_stats_get_tx_bytes(struct connman_service *service)
+{
+ return service->stats.tx_bytes;
+}
+
+unsigned long __connman_service_stats_get_rx_errors(struct connman_service *service)
+{
+ return service->stats.rx_errors;
+}
+
+unsigned long __connman_service_stats_get_tx_errors(struct connman_service *service)
+{
+ return service->stats.tx_errors;
+}
+
+unsigned long __connman_service_stats_get_rx_dropped(struct connman_service *service)
+{
+ return service->stats.rx_dropped;
+}
+
+unsigned long __connman_service_stats_get_tx_dropped(struct connman_service *service)
+{
+ return service->stats.tx_dropped;
+}
+
+unsigned long __connman_service_stats_get_time(struct connman_service *service)
+{
+ return service->stats.time;
+}
+
static struct connman_service *get_default(void)
{
struct connman_service *service;
service = g_sequence_get(iter);
- if (service->state != CONNMAN_SERVICE_STATE_READY)
+ if (is_connected(service) == FALSE)
return NULL;
return service;
static void mode_changed(struct connman_service *service)
{
- DBusMessage *signal;
- DBusMessageIter entry, value;
- const char *str, *key = "Mode";
-
- if (service->path == NULL)
- return;
+ const char *str;
str = mode2string(service->mode);
if (str == NULL)
return;
- signal = dbus_message_new_signal(service->path,
- CONNMAN_SERVICE_INTERFACE, "PropertyChanged");
- if (signal == NULL)
- return;
-
- dbus_message_iter_init_append(signal, &entry);
-
- dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
-
- dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
- DBUS_TYPE_STRING_AS_STRING, &value);
- dbus_message_iter_append_basic(&value, DBUS_TYPE_STRING, &str);
- dbus_message_iter_close_container(&entry, &value);
-
- g_dbus_send_message(connection, signal);
+ connman_dbus_property_changed_basic(service->path,
+ CONNMAN_SERVICE_INTERFACE, "Mode",
+ DBUS_TYPE_STRING, &str);
}
static void state_changed(struct connman_service *service)
{
- DBusMessage *signal;
- DBusMessageIter entry, value;
- const char *str, *key = "State";
-
- if (service->path == NULL)
- return;
+ const char *str;
str = state2string(service->state);
if (str == NULL)
return;
- signal = dbus_message_new_signal(service->path,
- CONNMAN_SERVICE_INTERFACE, "PropertyChanged");
- if (signal == NULL)
- return;
-
- dbus_message_iter_init_append(signal, &entry);
-
- dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
-
- dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
- DBUS_TYPE_STRING_AS_STRING, &value);
- dbus_message_iter_append_basic(&value, DBUS_TYPE_STRING, &str);
- dbus_message_iter_close_container(&entry, &value);
-
- g_dbus_send_message(connection, signal);
+ connman_dbus_property_changed_basic(service->path,
+ CONNMAN_SERVICE_INTERFACE, "State",
+ DBUS_TYPE_STRING, &str);
}
static void strength_changed(struct connman_service *service)
{
- DBusMessage *signal;
- DBusMessageIter entry, value;
- const char *key = "Strength";
-
- if (service->path == NULL)
- return;
-
if (service->strength == 0)
return;
- signal = dbus_message_new_signal(service->path,
- CONNMAN_SERVICE_INTERFACE, "PropertyChanged");
- if (signal == NULL)
- return;
+ connman_dbus_property_changed_basic(service->path,
+ CONNMAN_SERVICE_INTERFACE, "Strength",
+ DBUS_TYPE_BYTE, &service->strength);
+}
- dbus_message_iter_init_append(signal, &entry);
+static void favorite_changed(struct connman_service *service)
+{
+ if (service->path == NULL)
+ return;
- dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
+ connman_dbus_property_changed_basic(service->path,
+ CONNMAN_SERVICE_INTERFACE, "Favorite",
+ DBUS_TYPE_BOOLEAN, &service->favorite);
+}
- dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
- DBUS_TYPE_BYTE_AS_STRING, &value);
- dbus_message_iter_append_basic(&value, DBUS_TYPE_BYTE,
- &service->strength);
- dbus_message_iter_close_container(&entry, &value);
+static void immutable_changed(struct connman_service *service)
+{
+ if (service->path == NULL)
+ return;
- g_dbus_send_message(connection, signal);
+ connman_dbus_property_changed_basic(service->path,
+ CONNMAN_SERVICE_INTERFACE, "Immutable",
+ DBUS_TYPE_BOOLEAN, &service->immutable);
}
static void roaming_changed(struct connman_service *service)
{
- DBusMessage *signal;
- DBusMessageIter entry, value;
- const char *key = "Roaming";
-
if (service->path == NULL)
return;
- signal = dbus_message_new_signal(service->path,
- CONNMAN_SERVICE_INTERFACE, "PropertyChanged");
- if (signal == NULL)
- return;
-
- dbus_message_iter_init_append(signal, &entry);
-
- dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
-
- dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
- DBUS_TYPE_BOOLEAN_AS_STRING, &value);
- dbus_message_iter_append_basic(&value, DBUS_TYPE_BOOLEAN,
- &service->roaming);
- dbus_message_iter_close_container(&entry, &value);
-
- g_dbus_send_message(connection, signal);
+ connman_dbus_property_changed_basic(service->path,
+ CONNMAN_SERVICE_INTERFACE, "Roaming",
+ DBUS_TYPE_BOOLEAN, &service->roaming);
}
static void autoconnect_changed(struct connman_service *service)
{
- DBusMessage *signal;
- DBusMessageIter entry, value;
- const char *key = "AutoConnect";
-
if (service->path == NULL)
return;
- signal = dbus_message_new_signal(service->path,
- CONNMAN_SERVICE_INTERFACE, "PropertyChanged");
- if (signal == NULL)
- return;
-
- dbus_message_iter_init_append(signal, &entry);
-
- dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
-
- dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
- DBUS_TYPE_BOOLEAN_AS_STRING, &value);
- dbus_message_iter_append_basic(&value, DBUS_TYPE_BOOLEAN,
- &service->autoconnect);
- dbus_message_iter_close_container(&entry, &value);
-
- g_dbus_send_message(connection, signal);
+ connman_dbus_property_changed_basic(service->path,
+ CONNMAN_SERVICE_INTERFACE, "AutoConnect",
+ DBUS_TYPE_BOOLEAN, &service->autoconnect);
}
static void passphrase_changed(struct connman_service *service)
{
- DBusMessage *signal;
- DBusMessageIter entry, value;
dbus_bool_t required;
- const char *key = "PassphraseRequired";
-
- if (service->path == NULL)
- return;
switch (service->type) {
case CONNMAN_SERVICE_TYPE_UNKNOWN:
case CONNMAN_SERVICE_TYPE_WIMAX:
case CONNMAN_SERVICE_TYPE_BLUETOOTH:
case CONNMAN_SERVICE_TYPE_CELLULAR:
+ case CONNMAN_SERVICE_TYPE_GPS:
case CONNMAN_SERVICE_TYPE_VPN:
return;
case CONNMAN_SERVICE_TYPE_WIFI:
switch (service->security) {
case CONNMAN_SERVICE_SECURITY_UNKNOWN:
case CONNMAN_SERVICE_SECURITY_NONE:
- case CONNMAN_SERVICE_SECURITY_8021X:
break;
case CONNMAN_SERVICE_SECURITY_WEP:
case CONNMAN_SERVICE_SECURITY_PSK:
if (service->passphrase == NULL)
required = TRUE;
break;
+ case CONNMAN_SERVICE_SECURITY_8021X:
+ break;
}
break;
}
- signal = dbus_message_new_signal(service->path,
- CONNMAN_SERVICE_INTERFACE, "PropertyChanged");
- if (signal == NULL)
- return;
-
- dbus_message_iter_init_append(signal, &entry);
+ connman_dbus_property_changed_basic(service->path,
+ CONNMAN_SERVICE_INTERFACE, "PassphraseRequired",
+ DBUS_TYPE_BOOLEAN, &required);
+}
- dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
+static void login_changed(struct connman_service *service)
+{
+ dbus_bool_t required = service->login_required;
- dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
- DBUS_TYPE_BOOLEAN_AS_STRING, &value);
- dbus_message_iter_append_basic(&value, DBUS_TYPE_BOOLEAN, &required);
- dbus_message_iter_close_container(&entry, &value);
+ if (service->path == NULL)
+ return;
- g_dbus_send_message(connection, signal);
+ connman_dbus_property_changed_basic(service->path,
+ CONNMAN_SERVICE_INTERFACE, "LoginRequired",
+ DBUS_TYPE_BOOLEAN, &required);
}
static void apn_changed(struct connman_service *service)
{
- DBusMessage *signal;
- DBusMessageIter entry, value;
dbus_bool_t required;
- const char *key = "SetupRequired";
-
- if (service->path == NULL)
- return;
switch (service->type) {
case CONNMAN_SERVICE_TYPE_UNKNOWN:
case CONNMAN_SERVICE_TYPE_WIMAX:
case CONNMAN_SERVICE_TYPE_BLUETOOTH:
case CONNMAN_SERVICE_TYPE_WIFI:
+ case CONNMAN_SERVICE_TYPE_GPS:
case CONNMAN_SERVICE_TYPE_VPN:
return;
case CONNMAN_SERVICE_TYPE_CELLULAR:
required = (service->apn == NULL) ? TRUE : FALSE;
- signal = dbus_message_new_signal(service->path,
- CONNMAN_SERVICE_INTERFACE, "PropertyChanged");
- if (signal == NULL)
+ connman_dbus_property_changed_basic(service->path,
+ CONNMAN_SERVICE_INTERFACE, "SetupRequired",
+ DBUS_TYPE_BOOLEAN, &required);
+}
+
+static void append_ethernet(DBusMessageIter *iter, void *user_data)
+{
+ struct connman_service *service = user_data;
+
+ if (is_connecting(service) == FALSE &&
+ is_connected(service) == FALSE)
return;
- dbus_message_iter_init_append(signal, &entry);
+ if (service->ipconfig != NULL)
+ __connman_ipconfig_append_ethernet(service->ipconfig, iter);
+}
- dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
+static void append_ipv4(DBusMessageIter *iter, void *user_data)
+{
+ struct connman_service *service = user_data;
- dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
- DBUS_TYPE_BOOLEAN_AS_STRING, &value);
- dbus_message_iter_append_basic(&value, DBUS_TYPE_BOOLEAN, &required);
- dbus_message_iter_close_container(&entry, &value);
+ if (is_connected(service) == FALSE)
+ return;
- g_dbus_send_message(connection, signal);
+ if (service->ipconfig != NULL)
+ __connman_ipconfig_append_ipv4(service->ipconfig, iter);
}
-static DBusMessage *get_properties(DBusConnection *conn,
- DBusMessage *msg, void *user_data)
+static void append_ipv6(DBusMessageIter *iter, void *user_data)
{
struct connman_service *service = user_data;
- DBusMessage *reply;
- DBusMessageIter array, dict;
- dbus_bool_t required;
- const char *str;
+ struct connman_ipconfig *ipv6config;
- DBG("service %p", service);
+ if (is_connected(service) == FALSE)
+ return;
- reply = dbus_message_new_method_return(msg);
- if (reply == NULL)
- return NULL;
+ if (service->ipconfig == NULL)
+ return;
- dbus_message_iter_init_append(reply, &array);
+ ipv6config = connman_ipconfig_get_ipv6config(service->ipconfig);
+ if (ipv6config == NULL)
+ return;
+
+ __connman_ipconfig_append_ipv6(ipv6config, iter);
+}
+
+static void append_ipv4config(DBusMessageIter *iter, void *user_data)
+{
+ struct connman_service *service = user_data;
+
+ if (service->ipconfig != NULL)
+ __connman_ipconfig_append_ipv4config(service->ipconfig, iter);
+}
+
+static void append_ipv6config(DBusMessageIter *iter, void *user_data)
+{
+ struct connman_service *service = user_data;
+ struct connman_ipconfig *ipv6config;
+
+ if (service->ipconfig == NULL)
+ return;
+
+ ipv6config = connman_ipconfig_get_ipv6config(service->ipconfig);
+ if (ipv6config == NULL)
+ return;
+
+ __connman_ipconfig_append_ipv6config(ipv6config, iter);
+}
+
+static void append_dns(DBusMessageIter *iter, void *user_data)
+{
+ struct connman_service *service = user_data;
+
+ if (is_connected(service) == FALSE)
+ return;
+
+ if (service->nameservers != NULL) {
+ int i;
- dbus_message_iter_open_container(&array, DBUS_TYPE_ARRAY,
- DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
- DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
- DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
+ for (i = 0; service->nameservers[i]; i++)
+ dbus_message_iter_append_basic(iter,
+ DBUS_TYPE_STRING, &service->nameservers[i]);
+
+ return;
+ }
+
+ if (service->nameserver == NULL)
+ return;
+
+ dbus_message_iter_append_basic(iter,
+ DBUS_TYPE_STRING, &service->nameserver);
+}
+
+static void append_dnsconfig(DBusMessageIter *iter, void *user_data)
+{
+ struct connman_service *service = user_data;
+ int i;
+
+ if (service->nameservers == NULL)
+ return;
+
+ for (i = 0; service->nameservers[i]; i++)
+ dbus_message_iter_append_basic(iter,
+ DBUS_TYPE_STRING, &service->nameservers[i]);
+}
+
+static void append_domain(DBusMessageIter *iter, void *user_data)
+{
+ struct connman_service *service = user_data;
+
+ if (is_connected(service) == FALSE)
+ return;
+}
+
+static void append_domainconfig(DBusMessageIter *iter, void *user_data)
+{
+ struct connman_service *service = user_data;
+ int i;
+
+ if (service->domains == NULL)
+ return;
+
+ for (i = 0; service->domains[i]; i++)
+ dbus_message_iter_append_basic(iter,
+ DBUS_TYPE_STRING, &service->domains[i]);
+}
+
+static void append_proxy(DBusMessageIter *iter, void *user_data)
+{
+ struct connman_service *service = user_data;
+
+ if (is_connected(service) == FALSE)
+ return;
+
+ if (service->ipconfig != NULL)
+ __connman_ipconfig_append_proxy(service->ipconfig, iter);
+}
+
+static void settings_changed(struct connman_service *service)
+{
+ connman_dbus_property_changed_dict(service->path,
+ CONNMAN_SERVICE_INTERFACE, "IPv4",
+ append_ipv4, service);
+
+ connman_dbus_property_changed_dict(service->path,
+ CONNMAN_SERVICE_INTERFACE, "IPv6",
+ append_ipv6, service);
+}
+
+static void ipv4_configuration_changed(struct connman_service *service)
+{
+ connman_dbus_property_changed_dict(service->path,
+ CONNMAN_SERVICE_INTERFACE,
+ "IPv4.Configuration",
+ append_ipv4config,
+ service);
+}
+
+static void ipv6_configuration_changed(struct connman_service *service)
+{
+ connman_dbus_property_changed_dict(service->path,
+ CONNMAN_SERVICE_INTERFACE,
+ "IPv6.Configuration",
+ append_ipv6config,
+ service);
+}
+
+static void dns_changed(struct connman_service *service)
+{
+ if (is_connected(service) == FALSE)
+ return;
+
+ connman_dbus_property_changed_array(service->path,
+ CONNMAN_SERVICE_INTERFACE, "Nameservers",
+ DBUS_TYPE_STRING, append_dns, service);
+}
+
+static void dns_configuration_changed(struct connman_service *service)
+{
+ connman_dbus_property_changed_array(service->path,
+ CONNMAN_SERVICE_INTERFACE,
+ "Nameservers.Configuration",
+ DBUS_TYPE_STRING, append_dnsconfig, service);
+
+ dns_changed(service);
+}
+
+static void domain_configuration_changed(struct connman_service *service)
+{
+ connman_dbus_property_changed_array(service->path,
+ CONNMAN_SERVICE_INTERFACE,
+ "Domains.Configuration",
+ DBUS_TYPE_STRING, append_domainconfig, service);
+}
+
+static void append_properties(DBusMessageIter *dict, dbus_bool_t limited,
+ struct connman_service *service)
+{
+ dbus_bool_t required;
+ const char *str;
str = __connman_service_type2string(service->type);
if (str != NULL)
- connman_dbus_dict_append_variant(&dict, "Type",
+ connman_dbus_dict_append_basic(dict, "Type",
DBUS_TYPE_STRING, &str);
str = mode2string(service->mode);
if (str != NULL)
- connman_dbus_dict_append_variant(&dict, "Mode",
+ connman_dbus_dict_append_basic(dict, "Mode",
DBUS_TYPE_STRING, &str);
str = security2string(service->security);
if (str != NULL)
- connman_dbus_dict_append_variant(&dict, "Security",
+ connman_dbus_dict_append_basic(dict, "Security",
DBUS_TYPE_STRING, &str);
str = state2string(service->state);
if (str != NULL)
- connman_dbus_dict_append_variant(&dict, "State",
+ connman_dbus_dict_append_basic(dict, "State",
DBUS_TYPE_STRING, &str);
str = error2string(service->error);
if (str != NULL)
- connman_dbus_dict_append_variant(&dict, "Error",
+ connman_dbus_dict_append_basic(dict, "Error",
DBUS_TYPE_STRING, &str);
if (service->strength > 0)
- connman_dbus_dict_append_variant(&dict, "Strength",
+ connman_dbus_dict_append_basic(dict, "Strength",
DBUS_TYPE_BYTE, &service->strength);
- connman_dbus_dict_append_variant(&dict, "Favorite",
+ connman_dbus_dict_append_basic(dict, "Favorite",
DBUS_TYPE_BOOLEAN, &service->favorite);
+ connman_dbus_dict_append_basic(dict, "Immutable",
+ DBUS_TYPE_BOOLEAN, &service->immutable);
+
if (service->favorite == TRUE)
- connman_dbus_dict_append_variant(&dict, "AutoConnect",
+ connman_dbus_dict_append_basic(dict, "AutoConnect",
DBUS_TYPE_BOOLEAN, &service->autoconnect);
else
- connman_dbus_dict_append_variant(&dict, "AutoConnect",
+ connman_dbus_dict_append_basic(dict, "AutoConnect",
DBUS_TYPE_BOOLEAN, &service->favorite);
if (service->name != NULL)
- connman_dbus_dict_append_variant(&dict, "Name",
+ connman_dbus_dict_append_basic(dict, "Name",
DBUS_TYPE_STRING, &service->name);
+ connman_dbus_dict_append_basic(dict, "LoginRequired",
+ DBUS_TYPE_BOOLEAN, &service->login_required);
+
switch (service->type) {
case CONNMAN_SERVICE_TYPE_UNKNOWN:
case CONNMAN_SERVICE_TYPE_SYSTEM:
- case CONNMAN_SERVICE_TYPE_ETHERNET:
- case CONNMAN_SERVICE_TYPE_WIMAX:
- case CONNMAN_SERVICE_TYPE_BLUETOOTH:
+ case CONNMAN_SERVICE_TYPE_GPS:
case CONNMAN_SERVICE_TYPE_VPN:
break;
case CONNMAN_SERVICE_TYPE_CELLULAR:
- connman_dbus_dict_append_variant(&dict, "Roaming",
+ connman_dbus_dict_append_basic(dict, "Roaming",
DBUS_TYPE_BOOLEAN, &service->roaming);
if (service->mcc != NULL && service->mnc != NULL) {
- connman_dbus_dict_append_variant(&dict, "MCC",
+ connman_dbus_dict_append_basic(dict, "MCC",
DBUS_TYPE_STRING, &service->mcc);
- connman_dbus_dict_append_variant(&dict, "MNC",
+ connman_dbus_dict_append_basic(dict, "MNC",
DBUS_TYPE_STRING, &service->mnc);
}
if (service->apn != NULL) {
- connman_dbus_dict_append_variant(&dict, "APN",
+ connman_dbus_dict_append_basic(dict, "APN",
DBUS_TYPE_STRING, &service->apn);
if (service->username != NULL)
- connman_dbus_dict_append_variant(&dict,
+ connman_dbus_dict_append_basic(dict,
"Username", DBUS_TYPE_STRING,
&service->username);
if (service->password != NULL)
- connman_dbus_dict_append_variant(&dict,
+ connman_dbus_dict_append_basic(dict,
"Password", DBUS_TYPE_STRING,
&service->password);
} else
required = TRUE;
- connman_dbus_dict_append_variant(&dict, "SetupRequired",
+ connman_dbus_dict_append_basic(dict, "SetupRequired",
DBUS_TYPE_BOOLEAN, &required);
+ connman_dbus_dict_append_dict(dict, "Ethernet",
+ append_ethernet, service);
break;
case CONNMAN_SERVICE_TYPE_WIFI:
- if (service->passphrase != NULL &&
- __connman_security_check_privilege(msg,
- CONNMAN_SECURITY_PRIVILEGE_SECRET) == 0)
- connman_dbus_dict_append_variant(&dict, "Passphrase",
+ if (service->passphrase != NULL && limited == FALSE)
+ connman_dbus_dict_append_basic(dict, "Passphrase",
DBUS_TYPE_STRING, &service->passphrase);
required = FALSE;
switch (service->security) {
case CONNMAN_SERVICE_SECURITY_UNKNOWN:
case CONNMAN_SERVICE_SECURITY_NONE:
- case CONNMAN_SERVICE_SECURITY_8021X:
break;
case CONNMAN_SERVICE_SECURITY_WEP:
case CONNMAN_SERVICE_SECURITY_PSK:
if (service->passphrase == NULL)
required = TRUE;
break;
+ case CONNMAN_SERVICE_SECURITY_8021X:
+ break;
}
- connman_dbus_dict_append_variant(&dict, "PassphraseRequired",
+ connman_dbus_dict_append_basic(dict, "PassphraseRequired",
DBUS_TYPE_BOOLEAN, &required);
+ /* fall through */
+ case CONNMAN_SERVICE_TYPE_ETHERNET:
+ case CONNMAN_SERVICE_TYPE_WIMAX:
+ case CONNMAN_SERVICE_TYPE_BLUETOOTH:
+ connman_dbus_dict_append_dict(dict, "Ethernet",
+ append_ethernet, service);
break;
}
- if (service->ipconfig != NULL)
- __connman_ipconfig_append_ipv4(service->ipconfig,
- &dict, "IPv4.");
+ connman_dbus_dict_append_dict(dict, "IPv4", append_ipv4, service);
+
+ connman_dbus_dict_append_dict(dict, "IPv4.Configuration",
+ append_ipv4config, service);
+
+ connman_dbus_dict_append_dict(dict, "IPv6", append_ipv6, service);
+
+ connman_dbus_dict_append_dict(dict, "IPv6.Configuration",
+ append_ipv6config, service);
+
+ connman_dbus_dict_append_array(dict, "Nameservers",
+ DBUS_TYPE_STRING, append_dns, service);
+
+ connman_dbus_dict_append_array(dict, "Nameservers.Configuration",
+ DBUS_TYPE_STRING, append_dnsconfig, service);
+
+ connman_dbus_dict_append_array(dict, "Domains",
+ DBUS_TYPE_STRING, append_domain, service);
+
+ connman_dbus_dict_append_array(dict, "Domains.Configuration",
+ DBUS_TYPE_STRING, append_domainconfig, service);
+
+ connman_dbus_dict_append_dict(dict, "Proxy", append_proxy, service);
+}
+
+static void append_struct(gpointer value, gpointer user_data)
+{
+ struct connman_service *service = value;
+ DBusMessageIter *iter = user_data;
+ DBusMessageIter entry, dict;
+
+ if (service->path == NULL || service->hidden == TRUE)
+ return;
+
+ dbus_message_iter_open_container(iter, DBUS_TYPE_STRUCT, NULL, &entry);
+
+ dbus_message_iter_append_basic(&entry, DBUS_TYPE_OBJECT_PATH,
+ &service->path);
- dbus_message_iter_close_container(&array, &dict);
+ connman_dbus_dict_open(&entry, &dict);
+ append_properties(&dict, TRUE, service);
+ connman_dbus_dict_close(&entry, &dict);
+
+ dbus_message_iter_close_container(iter, &entry);
+}
+
+void __connman_service_list_struct(DBusMessageIter *iter)
+{
+ g_sequence_foreach(service_list, append_struct, iter);
+}
+
+static DBusMessage *get_properties(DBusConnection *conn,
+ DBusMessage *msg, void *user_data)
+{
+ struct connman_service *service = user_data;
+ DBusMessage *reply;
+ DBusMessageIter array, dict;
+ dbus_bool_t limited = TRUE;
+
+ DBG("service %p", service);
+
+ if (__connman_security_check_privilege(msg,
+ CONNMAN_SECURITY_PRIVILEGE_SECRET) == 0)
+ limited = FALSE;
+
+ reply = dbus_message_new_method_return(msg);
+ if (reply == NULL)
+ return NULL;
+
+ dbus_message_iter_init_append(reply, &array);
+
+ connman_dbus_dict_open(&array, &dict);
+ append_properties(&dict, limited, service);
+ connman_dbus_dict_close(&array, &dict);
return reply;
}
if (type != DBUS_TYPE_STRING)
return __connman_error_invalid_arguments(msg);
+ if (service->immutable == TRUE)
+ return __connman_error_not_supported(msg);
+
if (__connman_security_check_privilege(msg,
CONNMAN_SECURITY_PRIVILEGE_SECRET) < 0)
return __connman_error_permission_denied(msg);
if (type != DBUS_TYPE_STRING)
return __connman_error_invalid_arguments(msg);
+ if (service->immutable == TRUE)
+ return __connman_error_not_supported(msg);
+
if (service->type != CONNMAN_SERVICE_TYPE_CELLULAR)
return __connman_error_invalid_service(msg);
if (type != DBUS_TYPE_STRING)
return __connman_error_invalid_arguments(msg);
+ if (service->immutable == TRUE)
+ return __connman_error_not_supported(msg);
+
if (service->type != CONNMAN_SERVICE_TYPE_CELLULAR)
return __connman_error_invalid_service(msg);
if (type != DBUS_TYPE_STRING)
return __connman_error_invalid_arguments(msg);
+ if (service->immutable == TRUE)
+ return __connman_error_not_supported(msg);
+
if (service->type != CONNMAN_SERVICE_TYPE_CELLULAR)
return __connman_error_invalid_service(msg);
"Cellular.Password", service->password);
__connman_storage_save_service(service);
- } else if (g_str_has_prefix(name, "IPv4.") == TRUE) {
- int err;
+ } else if (g_str_equal(name, "Nameservers.Configuration") == TRUE) {
+ DBusMessageIter entry;
+ GString *str;
+ int index;
+ const char *gw;
+
+ if (type != DBUS_TYPE_ARRAY)
+ return __connman_error_invalid_arguments(msg);
+
+ str = g_string_new(NULL);
+ if (str == NULL)
+ return __connman_error_invalid_arguments(msg);
+
+ index = connman_network_get_index(service->network);
+ gw = __connman_ipconfig_get_gateway(index);
+
+ if (gw && strlen(gw))
+ __connman_service_nameserver_del_routes(service);
+
+ dbus_message_iter_recurse(&value, &entry);
+
+ while (dbus_message_iter_get_arg_type(&entry) == DBUS_TYPE_STRING) {
+ const char *val;
+ dbus_message_iter_get_basic(&entry, &val);
+ dbus_message_iter_next(&entry);
+ if (str->len > 0)
+ g_string_append_printf(str, " %s", val);
+ else
+ g_string_append(str, val);
+ }
+
+ g_strfreev(service->nameservers);
+
+ if (str->len > 0)
+ service->nameservers = g_strsplit_set(str->str, " ", 0);
+ else
+ service->nameservers = NULL;
+
+ g_string_free(str, TRUE);
+
+ if (gw && strlen(gw))
+ __connman_service_nameserver_add_routes(service, gw);
+
+ update_nameservers(service);
+ dns_configuration_changed(service);
+
+ __connman_storage_save_service(service);
+ } else if (g_str_equal(name, "Domains.Configuration") == TRUE) {
+ DBusMessageIter entry;
+ GString *str;
+
+ if (type != DBUS_TYPE_ARRAY)
+ return __connman_error_invalid_arguments(msg);
+
+ str = g_string_new(NULL);
+ if (str == NULL)
+ return __connman_error_invalid_arguments(msg);
+
+ dbus_message_iter_recurse(&value, &entry);
+
+ while (dbus_message_iter_get_arg_type(&entry) == DBUS_TYPE_STRING) {
+ const char *val;
+ dbus_message_iter_get_basic(&entry, &val);
+ dbus_message_iter_next(&entry);
+ if (str->len > 0)
+ g_string_append_printf(str, " %s", val);
+ else
+ g_string_append(str, val);
+ }
+
+ g_strfreev(service->domains);
+
+ if (str->len > 0)
+ service->domains = g_strsplit_set(str->str, " ", 0);
+ else
+ service->domains = NULL;
+
+ g_string_free(str, TRUE);
+
+ //update_domains(service);
+ domain_configuration_changed(service);
+
+ __connman_storage_save_service(service);
+ } else if (g_str_equal(name, "IPv4.Configuration") == TRUE ||
+ g_str_equal(name, "IPv6.Configuration")) {
+
+ enum connman_ipconfig_type type = CONNMAN_IPCONFIG_TYPE_UNKNOWN;
+ int err = 0;
+ struct connman_ipconfig *ipv6config;
+
+ DBG("%s", name);
+ ipv6config = connman_ipconfig_get_ipv6config(
+ service->ipconfig);
if (service->ipconfig == NULL)
return __connman_error_invalid_property(msg);
- err = __connman_ipconfig_set_ipv4(service->ipconfig,
- name + 5, &value);
- if (err < 0)
+ if (is_connecting(service) ||
+ is_connected(service)) {
+ __connman_network_clear_ipconfig(service->network,
+ service->ipconfig);
+ __connman_network_clear_ipconfig(service->network,
+ ipv6config);
+ }
+
+ if (g_str_equal(name, "IPv4.Configuration") == TRUE) {
+ type = CONNMAN_IPCONFIG_TYPE_IPV4;
+ err = __connman_ipconfig_set_config(
+ service->ipconfig, type, &value);
+ } else if (g_str_equal(name, "IPv6.Configuration") == TRUE) {
+ type = CONNMAN_IPCONFIG_TYPE_IPV6;
+ err = __connman_ipconfig_set_config(
+ ipv6config, type, &value);
+ }
+
+ if (err < 0) {
+ if (is_connected(service) ||
+ is_connecting(service))
+ __connman_network_set_ipconfig(
+ service->network,
+ service->ipconfig);
return __connman_error_failed(msg, -err);
+ }
+
+ if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
+ ipv4_configuration_changed(service);
+ else if (type == CONNMAN_IPCONFIG_TYPE_IPV6)
+ ipv6_configuration_changed(service);
+
+ if (is_connecting(service) ||
+ is_connected(service))
+ __connman_network_set_ipconfig(service->network,
+ service->ipconfig);
+
+ __connman_storage_save_service(service);
} else
return __connman_error_invalid_property(msg);
g_get_current_time(&service->modified);
__connman_storage_save_service(service);
} else if (g_str_equal(name, "Passphrase") == TRUE) {
+ if (service->immutable == TRUE)
+ return __connman_error_not_supported(msg);
+
g_free(service->passphrase);
service->passphrase = NULL;
return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
}
-static connman_bool_t is_connecting(struct connman_service *service)
-{
- switch (service->state) {
- case CONNMAN_SERVICE_STATE_UNKNOWN:
- case CONNMAN_SERVICE_STATE_IDLE:
- case CONNMAN_SERVICE_STATE_FAILURE:
- case CONNMAN_SERVICE_STATE_DISCONNECT:
- case CONNMAN_SERVICE_STATE_READY:
- break;
- case CONNMAN_SERVICE_STATE_ASSOCIATION:
- case CONNMAN_SERVICE_STATE_CONFIGURATION:
- return TRUE;
- }
-
- return FALSE;
-}
-
static connman_bool_t is_ignore(struct connman_service *service)
{
if (service->autoconnect == FALSE)
if (service->favorite == FALSE)
return;
- if (service->state == CONNMAN_SERVICE_STATE_READY)
+ if (is_connected(service) == TRUE)
return;
if (is_ignore(service) == FALSE &&
if (device == NULL)
return;
- __connman_device_set_reconnect(device, reconnect);
-}
+ __connman_device_set_reconnect(device, reconnect);
+}
+
+static connman_bool_t get_reconnect_state(struct connman_service *service)
+{
+ struct connman_device *device;
+
+ if (service->network == NULL)
+ return FALSE;
+
+ device = connman_network_get_device(service->network);
+ if (device == NULL)
+ return FALSE;
+
+ return __connman_device_get_reconnect(device);
+}
+
+struct connman_service *
+__connman_service_connect_type(enum connman_service_type type)
+{
+ struct connman_service *service;
+ GSequenceIter *iter;
+ int err;
+
+ DBG("type %d", type);
+
+ /*
+ * We go through the already sorted service list.
+ * We pick the first one matching our type, or just
+ * the first available one if we have no type.
+ */
+ iter = g_sequence_get_begin_iter(service_list);
+ if (g_sequence_iter_is_end(iter))
+ return NULL;
+ service = g_sequence_get(iter);
+
+ /*
+ * If the first service is connected or about to be
+ * connected, we return it, regardless of the type.
+ */
+ if ((g_sequence_iter_is_end(iter) == FALSE) &&
+ (is_connecting(service) == TRUE ||
+ is_connected(service) == TRUE))
+ return service;
+
+ while (g_sequence_iter_is_end(iter) == FALSE) {
+ if (service->type == type ||
+ type == CONNMAN_SERVICE_TYPE_UNKNOWN)
+ break;
+
+ iter = g_sequence_iter_next(iter);
+ service = g_sequence_get(iter);
+ }
+
+ if (g_sequence_iter_is_end(iter))
+ return NULL;
+
+ service->ignore = FALSE;
+
+ service->userconnect = TRUE;
-static connman_bool_t get_reconnect_state(struct connman_service *service)
-{
- struct connman_device *device;
+ set_reconnect_state(service, FALSE);
- if (service->network == NULL)
- return FALSE;
+ err = __connman_service_connect(service);
+ if (err < 0) {
+ if (err == -ENOKEY)
+ if (__connman_agent_request_passphrase(service,
+ NULL, NULL))
+ return service;
- device = connman_network_get_device(service->network);
- if (device == NULL)
- return FALSE;
+ if (err != -EINPROGRESS)
+ return NULL;
+ }
- return __connman_device_get_reconnect(device);
+ return service;
}
static DBusMessage *connect_service(DBusConnection *conn,
return NULL;
}
- dbus_message_unref(service->pending);
- service->pending = NULL;
-
return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
}
if (service->type == CONNMAN_SERVICE_TYPE_ETHERNET)
return __connman_error_not_supported(msg);
+ if (service->immutable == TRUE)
+ return __connman_error_not_supported(msg);
+
if (service->favorite == FALSE &&
service->state != CONNMAN_SERVICE_STATE_FAILURE)
return __connman_error_not_supported(msg);
set_idle(service);
- connman_service_set_favorite(service, FALSE);
+ __connman_service_set_favorite(service, FALSE);
__connman_storage_save_service(service);
return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
}
-static DBusMessage *move_before(DBusConnection *conn,
- DBusMessage *msg, void *user_data)
+static DBusMessage *move_service(DBusConnection *conn,
+ DBusMessage *msg, void *user_data,
+ gboolean before)
{
struct connman_service *service = user_data;
struct connman_service *target;
src = g_hash_table_lookup(service_hash, service->identifier);
dst = g_hash_table_lookup(service_hash, target->identifier);
- g_sequence_move(src, dst);
+ before ? g_sequence_move(src, dst) : g_sequence_move(dst, src);
__connman_profile_changed(FALSE);
return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
}
-static DBusMessage *move_after(DBusConnection *conn,
+static DBusMessage *move_before(DBusConnection *conn,
DBusMessage *msg, void *user_data)
{
- struct connman_service *service = user_data;
- struct connman_service *target;
- const char *path;
-
- DBG("service %p", service);
-
- dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
- DBUS_TYPE_INVALID);
-
- if (service->favorite == FALSE)
- return __connman_error_not_supported(msg);
-
- target = find_service(path);
- if (target == NULL || target->favorite == FALSE || target == service)
- return __connman_error_invalid_service(msg);
+ return move_service(conn, msg, user_data, TRUE);
+}
- DBG("target %s", target->identifier);
+static DBusMessage *move_after(DBusConnection *conn,
+ DBusMessage *msg, void *user_data)
+{
+ return move_service(conn, msg, user_data, FALSE);
+}
- if (target->state != service->state)
- return __connman_error_invalid_service(msg);
+static DBusMessage *reset_stats(DBusConnection *conn,
+ DBusMessage *msg, void *user_data)
+{
+ struct connman_service *service = user_data;
- g_get_current_time(&service->modified);
- __connman_storage_save_service(service);
+ __connman_service_reset_stats(service);
- return __connman_error_not_implemented(msg);
+ return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
}
static GDBusMethodTable service_methods[] = {
{ "Remove", "", "", remove_service },
{ "MoveBefore", "o", "", move_before },
{ "MoveAfter", "o", "", move_after },
+ { "ResetCounters", "", "", reset_stats },
{ },
};
g_hash_table_remove(service_hash, service->identifier);
+ __connman_service_stats_stop(service);
+ __connman_storage_save_service(service);
+
service->path = NULL;
if (path != NULL) {
service->ipconfig = NULL;
}
+ if (service->location != NULL)
+ connman_location_unref(service->location);
+
+ g_strfreev(service->nameservers);
+ g_strfreev(service->domains);
+
+ g_free(service->nameserver);
g_free(service->mcc);
g_free(service->mnc);
g_free(service->apn);
g_free(service->name);
g_free(service->passphrase);
g_free(service->identifier);
+ g_free(service->eap);
+ g_free(service->identity);
+ g_free(service->ca_cert_file);
+ g_free(service->client_cert_file);
+ g_free(service->private_key_file);
+ g_free(service->private_key_passphrase);
+ g_free(service->phase2);
+
+ if (service->stats.timer != NULL)
+ g_timer_destroy(service->stats.timer);
+
g_free(service);
}
service->security = CONNMAN_SERVICE_SECURITY_UNKNOWN;
service->state = CONNMAN_SERVICE_STATE_UNKNOWN;
- service->favorite = FALSE;
+ service->favorite = FALSE;
+ service->immutable = FALSE;
service->hidden = FALSE;
service->ignore = FALSE;
service->userconnect = FALSE;
service->order = 0;
+
+ service->stats.valid = FALSE;
+ service->stats.enabled = FALSE;
+ service->stats.timer = g_timer_new();
}
/**
__connman_service_initialize(service);
+ service->location = __connman_location_create(service);
+
return service;
}
+struct connman_location *__connman_service_get_location(struct connman_service *service)
+{
+ return service->location;
+}
+
/**
* connman_service_ref:
* @service: service structure
struct connman_service *service_b = (void *) b;
if (service_a->state != service_b->state) {
- if (service_a->state == CONNMAN_SERVICE_STATE_READY)
+ if (is_connected(service_a) == TRUE)
return -1;
- if (service_b->state == CONNMAN_SERVICE_STATE_READY)
+ if (is_connected(service_b) == TRUE)
return 1;
}
case CONNMAN_SERVICE_TYPE_UNKNOWN:
case CONNMAN_SERVICE_TYPE_SYSTEM:
case CONNMAN_SERVICE_TYPE_ETHERNET:
+ case CONNMAN_SERVICE_TYPE_GPS:
case CONNMAN_SERVICE_TYPE_VPN:
break;
case CONNMAN_SERVICE_TYPE_WIFI:
return (gint) service_b->strength - (gint) service_a->strength;
}
-static void favorite_changed(struct connman_service *service)
-{
- DBusMessage *signal;
- DBusMessageIter entry, value;
- const char *key = "Favorite";
-
- if (service->path == NULL)
- return;
-
- signal = dbus_message_new_signal(service->path,
- CONNMAN_SERVICE_INTERFACE, "PropertyChanged");
- if (signal == NULL)
- return;
-
- dbus_message_iter_init_append(signal, &entry);
-
- dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
-
- dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
- DBUS_TYPE_BOOLEAN_AS_STRING, &value);
- dbus_message_iter_append_basic(&value, DBUS_TYPE_BOOLEAN,
- &service->favorite);
- dbus_message_iter_close_container(&entry, &value);
-
- g_dbus_send_message(connection, signal);
-}
-
/**
* connman_service_get_type:
* @service: service structure
}
/**
- * connman_service_set_favorite:
+ * connman_service_get_network:
+ * @service: service structure
+ *
+ * Get the service network
+ */
+struct connman_network *
+__connman_service_get_network(struct connman_service *service)
+{
+ if (service == NULL)
+ return NULL;
+
+ return service->network;
+}
+
+struct connman_ipconfig *__connman_service_get_ipconfig(struct connman_service *service)
+{
+ if (service == NULL)
+ return NULL;
+
+ return service->ipconfig;
+}
+
+/**
+ * __connman_service_set_favorite:
* @service: service structure
* @favorite: favorite value
*
* Change the favorite setting of service
*/
-int connman_service_set_favorite(struct connman_service *service,
+int __connman_service_set_favorite(struct connman_service *service,
connman_bool_t favorite)
{
GSequenceIter *iter;
return 0;
}
+int __connman_service_set_immutable(struct connman_service *service,
+ connman_bool_t immutable)
+{
+ service->immutable = immutable;
+
+ immutable_changed(service);
+
+ return 0;
+}
+
+void __connman_service_set_string(struct connman_service *service,
+ const char *key, const char *value)
+{
+ if (g_str_equal(key, "EAP") == TRUE) {
+ g_free(service->eap);
+ service->eap = g_strdup(value);
+ } else if (g_str_equal(key, "Identity") == TRUE) {
+ g_free(service->identity);
+ service->identity = g_strdup(value);
+ } else if (g_str_equal(key, "CACertFile") == TRUE) {
+ g_free(service->ca_cert_file);
+ service->ca_cert_file = g_strdup(value);
+ } else if (g_str_equal(key, "ClientCertFile") == TRUE) {
+ g_free(service->client_cert_file);
+ service->client_cert_file = g_strdup(value);
+ } else if (g_str_equal(key, "PrivateKeyFile") == TRUE) {
+ g_free(service->private_key_file);
+ service->private_key_file = g_strdup(value);
+ } else if (g_str_equal(key, "PrivateKeyPassphrase") == TRUE) {
+ g_free(service->private_key_passphrase);
+ service->private_key_passphrase = g_strdup(value);
+ } else if (g_str_equal(key, "Phase2") == TRUE) {
+ g_free(service->phase2);
+ service->phase2 = g_strdup(value);
+ } else if (g_str_equal(key, "Passphrase") == TRUE) {
+ g_free(service->passphrase);
+ service->passphrase = g_strdup(value);
+ }
+}
int __connman_service_indicate_state(struct connman_service *service,
enum connman_service_state state)
__connman_service_disconnect(service);
}
+ if (state == CONNMAN_SERVICE_STATE_CONFIGURATION)
+ __connman_ipconfig_enable(service->ipconfig);
+
service->state = state;
state_changed(service);
+ if (state == CONNMAN_SERVICE_STATE_ONLINE) {
+ if (service->login_required == TRUE) {
+ service->login_required = FALSE;
+ login_changed(service);
+ }
+
+ connman_timeserver_sync();
+ }
+
if (state == CONNMAN_SERVICE_STATE_IDLE) {
connman_bool_t reconnect;
if (state == CONNMAN_SERVICE_STATE_READY) {
set_reconnect_state(service, TRUE);
- connman_service_set_favorite(service, TRUE);
+ __connman_service_set_favorite(service, TRUE);
reply_pending(service, 0);
g_get_current_time(&service->modified);
__connman_storage_save_service(service);
+ update_nameservers(service);
+ dns_changed(service);
+
__connman_notifier_connect(service->type);
default_changed();
} else if (state == CONNMAN_SERVICE_STATE_DISCONNECT) {
+ __connman_location_finish(service);
+
default_changed();
+ update_nameservers(service);
+ dns_changed(service);
+
__connman_notifier_disconnect(service->type);
}
default_changed();
+ __connman_location_detect(service);
+
+ return 0;
+}
+
+int __connman_service_request_login(struct connman_service *service)
+{
+ DBG("service %p", service);
+
+ if (service == NULL)
+ return -EINVAL;
+
+ service->login_required = TRUE;
+ login_changed(service);
+
return 0;
}
case CONNMAN_NETWORK_TYPE_WIMAX:
case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN:
case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN:
- case CONNMAN_NETWORK_TYPE_CELLULAR:
break;
- case CONNMAN_NETWORK_TYPE_MBM:
- case CONNMAN_NETWORK_TYPE_HSO:
+ case CONNMAN_NETWORK_TYPE_CELLULAR:
connman_network_set_string(service->network,
"Cellular.APN", service->apn);
return TRUE;
}
+static void prepare_8021x(struct connman_service *service)
+{
+ if (service->eap != NULL)
+ connman_network_set_string(service->network, "WiFi.EAP",
+ service->eap);
+
+ if (service->identity != NULL)
+ connman_network_set_string(service->network, "WiFi.Identity",
+ service->identity);
+
+ if (service->ca_cert_file != NULL)
+ connman_network_set_string(service->network, "WiFi.CACertFile",
+ service->ca_cert_file);
+
+ if (service->client_cert_file != NULL)
+ connman_network_set_string(service->network,
+ "WiFi.ClientCertFile",
+ service->client_cert_file);
+
+ if (service->private_key_file != NULL)
+ connman_network_set_string(service->network,
+ "WiFi.PrivateKeyFile",
+ service->private_key_file);
+
+ if (service->private_key_passphrase != NULL)
+ connman_network_set_string(service->network,
+ "WiFi.PrivateKeyPassphrase",
+ service->private_key_passphrase);
+
+ if (service->phase2 != NULL)
+ connman_network_set_string(service->network, "WiFi.Phase2",
+ service->phase2);
+}
+
int __connman_service_connect(struct connman_service *service)
{
int err;
DBG("service %p", service);
- if (service->state == CONNMAN_SERVICE_STATE_READY)
+ if (is_connected(service) == TRUE)
return -EISCONN;
if (is_connecting(service) == TRUE)
switch (service->type) {
case CONNMAN_SERVICE_TYPE_UNKNOWN:
case CONNMAN_SERVICE_TYPE_SYSTEM:
+ case CONNMAN_SERVICE_TYPE_GPS:
case CONNMAN_SERVICE_TYPE_VPN:
return -EINVAL;
case CONNMAN_SERVICE_TYPE_ETHERNET:
switch (service->security) {
case CONNMAN_SERVICE_SECURITY_UNKNOWN:
case CONNMAN_SERVICE_SECURITY_NONE:
- case CONNMAN_SERVICE_SECURITY_8021X:
break;
case CONNMAN_SERVICE_SECURITY_WEP:
case CONNMAN_SERVICE_SECURITY_PSK:
if (service->passphrase == NULL)
return -ENOKEY;
break;
+ case CONNMAN_SERVICE_SECURITY_8021X:
+ break;
}
break;
}
if (prepare_network(service) == FALSE)
return -EINVAL;
+ switch (service->security) {
+ case CONNMAN_SERVICE_SECURITY_UNKNOWN:
+ case CONNMAN_SERVICE_SECURITY_NONE:
+ case CONNMAN_SERVICE_SECURITY_WEP:
+ case CONNMAN_SERVICE_SECURITY_PSK:
+ case CONNMAN_SERVICE_SECURITY_WPA:
+ case CONNMAN_SERVICE_SECURITY_RSN:
+ break;
+ case CONNMAN_SERVICE_SECURITY_8021X:
+ prepare_8021x(service);
+ break;
+ }
+
__connman_ipconfig_enable(service->ipconfig);
err = __connman_network_connect(service->network);
int __connman_service_disconnect(struct connman_service *service)
{
+ struct connman_ipconfig *ipv6config;
int err;
DBG("service %p", service);
} else
return -EOPNOTSUPP;
+ __connman_ipconfig_clear_address(service->ipconfig);
+
+ ipv6config = connman_ipconfig_get_ipv6config(service->ipconfig);
+
+ __connman_ipconfig_clear_address(ipv6config);
+
__connman_ipconfig_disable(service->ipconfig);
if (err < 0) {
/**
* __connman_service_lookup:
+ * @pattern: search pattern
+ * @path: return object path
+ *
+ * Look up a service path from a search pattern
+ */
+int __connman_service_lookup(const char *pattern, const char **path)
+{
+ GHashTableIter iter;
+ gpointer key, value;
+
+ g_hash_table_iter_init(&iter, service_hash);
+
+ while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
+ GSequenceIter *iter = value;
+ struct connman_service *service = g_sequence_get(iter);
+
+ if (g_strcmp0(service->identifier, pattern) == 0 ||
+ g_strcmp0(service->name, pattern) == 0) {
+ *path = (const char *) service->path;
+ return 0;
+ }
+ }
+
+ return -ENXIO;
+}
+
+/**
+ * lookup_by_identifier:
* @identifier: service identifier
*
* Look up a service by identifier (reference count will not be increased)
*/
-static struct connman_service *__connman_service_lookup(const char *identifier)
+static struct connman_service *lookup_by_identifier(const char *identifier)
{
GSequenceIter *iter;
struct connman_network *network;
struct connman_device *device;
DBusMessageIter iter, array;
- const char *mode = "managed", *security = "none";
+ const char *mode = "managed", *security = "none", *group_security;
const char *type = NULL, *ssid = NULL, *passphrase = NULL;
unsigned int ssid_len = 0;
const char *ident;
return -EINVAL;
if (g_strcmp0(security, "none") != 0 &&
- g_strcmp0(security, "wep") != 0 &&
+ g_strcmp0(security, "wep") != 0 &&
+ g_strcmp0(security, "psk") != 0 &&
g_strcmp0(security, "wpa") != 0 &&
- g_strcmp0(security, "rsn") != 0)
+ g_strcmp0(security, "rsn") != 0 &&
+ g_strcmp0(security, "ieee8021x") != 0)
return -EINVAL;
- device = __connman_element_find_device(CONNMAN_SERVICE_TYPE_WIFI);
+ device = __connman_element_find_device(CONNMAN_DEVICE_TYPE_WIFI);
if (device == NULL)
return -EOPNOTSUPP;
if (ident == NULL)
return -EOPNOTSUPP;
+
+ if (!g_strcmp0(security, "wpa") ||
+ !g_strcmp0(security, "rsn"))
+ group_security = "psk";
+ else
+ group_security = security;
+
group = connman_wifi_build_group_name((unsigned char *) ssid,
- ssid_len, mode, security);
+ ssid_len, mode, group_security);
if (group == NULL)
return -EINVAL;
name = g_strdup_printf("%s_%s_%s", type, ident, group);
- service = __connman_service_lookup(name);
+ service = lookup_by_identifier(name);
if (service != NULL)
goto done;
created = TRUE;
}
- service = __connman_service_lookup(name);
+ service = lookup_by_identifier(name);
done:
g_free(name);
if (network != NULL) {
connman_network_set_available(network, FALSE);
__connman_device_cleanup_networks(device);
- }
-
- __connman_service_put(service);
+ } else
+ __connman_service_put(service);
}
return err;
service->profile = g_strdup(__connman_profile_active_ident());
- __connman_storage_load_service(service);
-
iter = g_sequence_insert_sorted(service_list, service,
service_compare, NULL);
DBG("path %s", service->path);
+ __connman_config_provision_service(service);
+
+ __connman_storage_load_service(service);
+
g_dbus_register_interface(connection, service->path,
CONNMAN_SERVICE_INTERFACE,
service_methods, service_signals,
NULL, service, NULL);
- __connman_storage_load_service(service);
-
iter = g_hash_table_lookup(service_hash, service->identifier);
if (iter != NULL)
g_sequence_sort_changed(iter, service_compare, NULL);
static void service_up(struct connman_ipconfig *ipconfig)
{
+ struct connman_service *service = connman_ipconfig_get_data(ipconfig);
+
connman_info("%s up", connman_ipconfig_get_ifname(ipconfig));
+
+ service->stats.valid = FALSE;
}
static void service_down(struct connman_ipconfig *ipconfig)
static void service_lower_up(struct connman_ipconfig *ipconfig)
{
+ struct connman_service *service = connman_ipconfig_get_data(ipconfig);
+
connman_info("%s lower up", connman_ipconfig_get_ifname(ipconfig));
+
+ __connman_service_stats_start(service);
}
static void service_lower_down(struct connman_ipconfig *ipconfig)
{
+ struct connman_service *service = connman_ipconfig_get_data(ipconfig);
+
connman_info("%s lower down", connman_ipconfig_get_ifname(ipconfig));
+
+ __connman_service_stats_stop(service);
+ __connman_storage_save_service(service);
}
static void service_ip_bound(struct connman_ipconfig *ipconfig)
{
+ struct connman_service *service = connman_ipconfig_get_data(ipconfig);
+
connman_info("%s ip bound", connman_ipconfig_get_ifname(ipconfig));
+
+ settings_changed(service);
}
static void service_ip_release(struct connman_ipconfig *ipconfig)
{
+ struct connman_service *service = connman_ipconfig_get_data(ipconfig);
+
connman_info("%s ip release", connman_ipconfig_get_ifname(ipconfig));
+
+ settings_changed(service);
}
static const struct connman_ipconfig_ops service_ops = {
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_ipconfig_set_ops(service->ipconfig, NULL);
+}
+
+void __connman_service_create_ipconfig(struct connman_service *service,
+ int index)
+{
+ struct connman_ipconfig *ipv6config;
+ const char *ident = service->profile;
+ GKeyFile *keyfile;
+
+ if (service->ipconfig != NULL)
+ return;
+
+ setup_ipconfig(service, index);
+
+ if (ident == NULL)
+ return;
+
+ keyfile = __connman_storage_open_profile(ident);
+ if (keyfile == NULL)
+ return;
+
+
+ ipv6config = connman_ipconfig_get_ipv6config(service->ipconfig);
+ if (ipv6config != NULL)
+ __connman_ipconfig_load(ipv6config, keyfile,
+ service->identifier, "IPv6.");
+
+ __connman_ipconfig_load(service->ipconfig, keyfile,
+ service->identifier, "IPv4.");
+ g_key_file_free(keyfile);
}
/**
name = g_strdup_printf("%s_%s_%s",
__connman_network_get_type(network), ident, group);
- service = __connman_service_lookup(name);
+ service = lookup_by_identifier(name);
g_free(name);
return service;
case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN:
return CONNMAN_SERVICE_TYPE_BLUETOOTH;
case CONNMAN_NETWORK_TYPE_CELLULAR:
- case CONNMAN_NETWORK_TYPE_MBM:
- case CONNMAN_NETWORK_TYPE_HSO:
return CONNMAN_SERVICE_TYPE_CELLULAR;
}
return CONNMAN_SERVICE_SECURITY_NONE;
else if (g_str_equal(security, "wep") == TRUE)
return CONNMAN_SERVICE_SECURITY_WEP;
- else if (g_str_equal(security, "wep") == TRUE)
+ else if (g_str_equal(security, "psk") == TRUE)
return CONNMAN_SERVICE_SECURITY_PSK;
else if (g_str_equal(security, "ieee8021x") == TRUE)
return CONNMAN_SERVICE_SECURITY_8021X;
DBG("service %p network %p", service, network);
- if (service->state == CONNMAN_SERVICE_STATE_READY)
+ if (is_connected(service) == TRUE)
return;
if (is_connecting(service) == TRUE)
case CONNMAN_SERVICE_TYPE_ETHERNET:
case CONNMAN_SERVICE_TYPE_WIMAX:
case CONNMAN_SERVICE_TYPE_BLUETOOTH:
+ case CONNMAN_SERVICE_TYPE_GPS:
case CONNMAN_SERVICE_TYPE_VPN:
service->autoconnect = FALSE;
break;
service_register(service);
- __connman_profile_changed(TRUE);
-
if (service->favorite == TRUE)
__connman_service_auto_connect();
connman_uint8_t strength, value;
connman_bool_t roaming;
GSequenceIter *iter;
+ const char *name;
DBG("network %p", network);
if (service->network == NULL)
return;
+ name = connman_network_get_string(service->network, "Name");
+ if (g_strcmp0(service->name, name) != 0) {
+ g_free(service->name);
+ service->name = g_strdup(name);
+ connman_dbus_property_changed_basic(service->path,
+ CONNMAN_SERVICE_INTERFACE, "Name",
+ DBUS_TYPE_STRING, &service->name);
+ }
+
strength = connman_network_get_uint8(service->network, "Strength");
if (strength == service->strength)
goto roaming;
__connman_service_put(service);
}
+void __connman_service_stats_update(struct connman_service *service,
+ unsigned int rx_packets, unsigned int tx_packets,
+ unsigned int rx_bytes, unsigned int tx_bytes,
+ unsigned int rx_errors, unsigned int tx_errors,
+ unsigned int rx_dropped, unsigned int tx_dropped)
+{
+ unsigned int seconds;
+ struct connman_stats *stats = &service->stats;
+
+ DBG("service %p", service);
+
+ if (is_connected(service) == FALSE)
+ return;
+
+ if (stats->valid == TRUE) {
+ stats->rx_packets +=
+ rx_packets - stats->rx_packets_last;
+ stats->tx_packets +=
+ tx_packets - stats->tx_packets_last;
+ stats->rx_bytes +=
+ rx_bytes - stats->rx_bytes_last;
+ stats->tx_bytes +=
+ tx_bytes - stats->tx_bytes_last;
+ stats->rx_errors +=
+ rx_errors - stats->rx_errors_last;
+ stats->tx_errors +=
+ tx_errors - stats->tx_errors_last;
+ stats->rx_dropped +=
+ rx_dropped - stats->rx_dropped_last;
+ stats->tx_dropped +=
+ tx_dropped - stats->tx_dropped_last;
+ } else {
+ stats->valid = TRUE;
+ }
+
+ stats->rx_packets_last = rx_packets;
+ stats->tx_packets_last = tx_packets;
+ stats->rx_bytes_last = rx_bytes;
+ stats->tx_bytes_last = tx_bytes;
+ stats->rx_errors_last = rx_errors;
+ stats->tx_errors_last = tx_errors;
+ stats->rx_dropped_last = rx_dropped;
+ stats->tx_dropped_last = tx_dropped;
+
+ seconds = g_timer_elapsed(stats->timer, NULL);
+ stats->time = stats->time_start + seconds;
+}
+
static int service_load(struct connman_service *service)
{
const char *ident = service->profile;
case CONNMAN_SERVICE_TYPE_UNKNOWN:
case CONNMAN_SERVICE_TYPE_SYSTEM:
case CONNMAN_SERVICE_TYPE_ETHERNET:
+ case CONNMAN_SERVICE_TYPE_GPS:
case CONNMAN_SERVICE_TYPE_VPN:
break;
case CONNMAN_SERVICE_TYPE_WIFI:
service->username = g_key_file_get_string(keyfile,
service->identifier, "Username", NULL);
- service->username = g_key_file_get_string(keyfile,
+ service->password = g_key_file_get_string(keyfile,
service->identifier, "Password", NULL);
service->favorite = g_key_file_get_boolean(keyfile,
service->passphrase = str;
}
- if (service->ipconfig != NULL)
+ if (service->ipconfig != NULL) {
+ struct connman_ipconfig *ipv6config;
+
+ ipv6config = connman_ipconfig_get_ipv6config(
+ service->ipconfig);
+ if (ipv6config != NULL)
+ __connman_ipconfig_load(ipv6config, keyfile,
+ service->identifier, "IPv6.");
+
__connman_ipconfig_load(service->ipconfig, keyfile,
service->identifier, "IPv4.");
+ }
+
+ service->nameservers = g_key_file_get_string_list(keyfile,
+ service->identifier, "Nameservers", &length, NULL);
+ if (service->nameservers != NULL && length == 0) {
+ g_strfreev(service->nameservers);
+ service->nameservers = NULL;
+ }
+ service->domains = g_key_file_get_string_list(keyfile,
+ service->identifier, "Domains", &length, NULL);
+ if (service->domains != NULL && length == 0) {
+ g_strfreev(service->domains);
+ service->domains = NULL;
+ }
+
+ __connman_service_stats_load(service, keyfile, service->identifier);
done:
g_key_file_free(keyfile);
case CONNMAN_SERVICE_TYPE_UNKNOWN:
case CONNMAN_SERVICE_TYPE_SYSTEM:
case CONNMAN_SERVICE_TYPE_ETHERNET:
+ case CONNMAN_SERVICE_TYPE_GPS:
case CONNMAN_SERVICE_TYPE_VPN:
break;
case CONNMAN_SERVICE_TYPE_WIFI:
g_key_file_remove_key(keyfile, service->identifier,
"Passphrase", NULL);
- if (service->ipconfig != NULL)
+ if (service->ipconfig != NULL) {
+ struct connman_ipconfig *ipv6config;
+
+ ipv6config = connman_ipconfig_get_ipv6config(service->ipconfig);
+ if (ipv6config != NULL)
+ __connman_ipconfig_save(ipv6config, keyfile,
+ service->identifier, "IPv6.");
+
__connman_ipconfig_save(service->ipconfig, keyfile,
service->identifier, "IPv4.");
+ }
+
+ if (service->nameservers != NULL) {
+ guint len = g_strv_length(service->nameservers);
+
+ g_key_file_set_string_list(keyfile, service->identifier,
+ "Nameservers",
+ (const gchar **) service->nameservers, len);
+ } else
+ g_key_file_remove_key(keyfile, service->identifier,
+ "Nameservers", NULL);
+
+ if (service->domains != NULL) {
+ guint len = g_strv_length(service->domains);
+
+ g_key_file_set_string_list(keyfile, service->identifier,
+ "Domains",
+ (const gchar **) service->domains, len);
+ } else
+ g_key_file_remove_key(keyfile, service->identifier,
+ "Domains", NULL);
+
+ __connman_service_stats_save(service, keyfile, service->identifier);
data = g_key_file_to_data(keyfile, &length, NULL);