summaryrefslogtreecommitdiff
path: root/src/service.c
diff options
context:
space:
mode:
authorNiraj Kumar Goit <niraj.g@samsung.com>2022-02-15 10:23:07 +0530
committerNiraj Kumar Goit <niraj.g@samsung.com>2022-02-15 10:25:05 +0530
commitf89b473dfd8e916314b534b3397442f8c869c783 (patch)
treeb6f15a191886ac5b78e98b1b2b210adefae69cf2 /src/service.c
parentdd3cccc5e67548dcc2dd6c6254ed6c97859085d5 (diff)
downloadconnman-f89b473dfd8e916314b534b3397442f8c869c783.tar.gz
connman-f89b473dfd8e916314b534b3397442f8c869c783.tar.bz2
connman-f89b473dfd8e916314b534b3397442f8c869c783.zip
Imported Upstream version 1.40upstream/1.40
Change-Id: Id3e405d088ee3fb19fd0ca049e1cb7f812b40fca Signed-off-by: Niraj Kumar Goit <niraj.g@samsung.com>
Diffstat (limited to 'src/service.c')
-rw-r--r--src/service.c407
1 files changed, 278 insertions, 129 deletions
diff --git a/src/service.c b/src/service.c
index 2f497d10..20917a89 100644
--- a/src/service.c
+++ b/src/service.c
@@ -54,6 +54,9 @@ static unsigned int autoconnect_id = 0;
static unsigned int vpn_autoconnect_id = 0;
static struct connman_service *current_default = NULL;
static bool services_dirty = false;
+static bool enable_online_to_ready_transition = false;
+static unsigned int online_check_initial_interval = 0;
+static unsigned int online_check_max_interval = 0;
struct connman_stats {
bool valid;
@@ -134,8 +137,8 @@ struct connman_service {
bool wps;
bool wps_advertizing;
guint online_timeout;
- int online_check_interval_ipv4;
- int online_check_interval_ipv6;
+ unsigned int online_check_interval_ipv4;
+ unsigned int online_check_interval_ipv6;
bool do_split_routing;
bool new_service;
bool hidden_service;
@@ -192,6 +195,8 @@ static const char *reason2string(enum connman_service_connect_reason reason)
return "auto";
case CONNMAN_SERVICE_CONNECT_REASON_SESSION:
return "session";
+ case CONNMAN_SERVICE_CONNECT_REASON_NATIVE:
+ return "native";
}
return "unknown";
@@ -367,7 +372,26 @@ static enum connman_service_proxy_method string2proxymethod(const char *method)
return CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN;
}
-static void set_split_routing(struct connman_service *service, bool value)
+void __connman_service_split_routing_changed(struct connman_service *service)
+{
+ dbus_bool_t split_routing;
+
+ if (!service->path)
+ return;
+
+ if (!allow_property_changed(service))
+ return;
+
+ split_routing = service->do_split_routing;
+ if (!connman_dbus_property_changed_basic(service->path,
+ CONNMAN_SERVICE_INTERFACE, "SplitRouting",
+ DBUS_TYPE_BOOLEAN, &split_routing))
+ connman_warn("cannot send SplitRouting property change on %s",
+ service->identifier);
+}
+
+void __connman_service_set_split_routing(struct connman_service *service,
+ bool value)
{
if (service->type != CONNMAN_SERVICE_TYPE_VPN)
return;
@@ -378,6 +402,12 @@ static void set_split_routing(struct connman_service *service, bool value)
service->order = 0;
else
service->order = 10;
+
+ /*
+ * In order to make sure the value is propagated also when loading the
+ * VPN service signal the value regardless of the value change.
+ */
+ __connman_service_split_routing_changed(service);
}
int __connman_service_load_modifiable(struct connman_service *service)
@@ -400,9 +430,10 @@ int __connman_service_load_modifiable(struct connman_service *service)
case CONNMAN_SERVICE_TYPE_P2P:
break;
case CONNMAN_SERVICE_TYPE_VPN:
- set_split_routing(service, g_key_file_get_boolean(keyfile,
- service->identifier,
- "SplitRouting", NULL));
+ __connman_service_set_split_routing(service,
+ g_key_file_get_boolean(keyfile,
+ service->identifier,
+ "SplitRouting", NULL));
/* fall through */
case CONNMAN_SERVICE_TYPE_WIFI:
@@ -456,9 +487,10 @@ static int service_load(struct connman_service *service)
case CONNMAN_SERVICE_TYPE_P2P:
break;
case CONNMAN_SERVICE_TYPE_VPN:
- set_split_routing(service, g_key_file_get_boolean(keyfile,
- service->identifier,
- "SplitRouting", NULL));
+ __connman_service_set_split_routing(service,
+ g_key_file_get_boolean(keyfile,
+ service->identifier,
+ "SplitRouting", NULL));
autoconnect = g_key_file_get_boolean(keyfile,
service->identifier, "AutoConnect", &error);
@@ -545,8 +577,10 @@ static int service_load(struct connman_service *service)
str = g_key_file_get_string(keyfile,
service->identifier, "Passphrase", NULL);
if (str) {
+ char *dec = g_strcompress(str);
+ g_free(str);
g_free(service->passphrase);
- service->passphrase = str;
+ service->passphrase = dec;
}
if (service->ipconfig_ipv4)
@@ -709,9 +743,12 @@ static int service_save(struct connman_service *service)
g_free(str);
}
- if (service->passphrase && strlen(service->passphrase) > 0)
+ if (service->passphrase && strlen(service->passphrase) > 0) {
+ char *enc = g_strescape(service->passphrase, NULL);
g_key_file_set_string(keyfile, service->identifier,
- "Passphrase", service->passphrase);
+ "Passphrase", enc);
+ g_free(enc);
+ }
if (service->ipconfig_ipv4)
__connman_ipconfig_save(service->ipconfig_ipv4, keyfile,
@@ -1416,6 +1453,12 @@ static void start_online_check(struct connman_service *service,
"Default service remains in READY state.");
return;
}
+ enable_online_to_ready_transition =
+ connman_setting_get_bool("EnableOnlineToReadyTransition");
+ online_check_initial_interval =
+ connman_setting_get_uint("OnlineCheckInitialInterval");
+ online_check_max_interval =
+ connman_setting_get_uint("OnlineCheckMaxInterval");
if (type != CONNMAN_IPCONFIG_TYPE_IPV4 || check_proxy_setup(service)) {
cancel_online_check(service);
@@ -1575,6 +1618,16 @@ static void default_changed(void)
connman_setting_get_bool("AllowDomainnameUpdates"))
__connman_utsname_set_domainname(service->domainname);
+ if (__connman_service_is_connected_state(service,
+ CONNMAN_IPCONFIG_TYPE_IPV4))
+ __connman_service_wispr_start(service,
+ CONNMAN_IPCONFIG_TYPE_IPV4);
+
+ if (__connman_service_is_connected_state(service,
+ CONNMAN_IPCONFIG_TYPE_IPV6))
+ __connman_service_wispr_start(service,
+ CONNMAN_IPCONFIG_TYPE_IPV6);
+
/*
* Connect VPN automatically when new default service
* is set and connected, unless new default is VPN
@@ -1693,6 +1746,8 @@ bool connman_service_set_autoconnect(struct connman_service *service,
service->autoconnect = autoconnect;
autoconnect_changed(service);
+ connman_network_set_autoconnect(service->network, autoconnect);
+
return true;
}
@@ -3428,15 +3483,28 @@ static void do_auto_connect(struct connman_service *service,
return;
/*
+ * Only user interaction should get VPN or WIFI connected in failure
+ * state.
+ */
+ if (service->state == CONNMAN_SERVICE_STATE_FAILURE &&
+ reason != CONNMAN_SERVICE_CONNECT_REASON_USER &&
+ (service->type == CONNMAN_SERVICE_TYPE_VPN ||
+ service->type == CONNMAN_SERVICE_TYPE_WIFI))
+ return;
+
+ /*
+ * Do not use the builtin auto connect, instead rely on the
+ * native auto connect feature of the service.
+ */
+ if (service->connect_reason == CONNMAN_SERVICE_CONNECT_REASON_NATIVE)
+ return;
+
+ /*
* Run service auto connect for other than VPN services. Afterwards
* start also VPN auto connect process.
*/
if (service->type != CONNMAN_SERVICE_TYPE_VPN)
__connman_service_auto_connect(reason);
- /* Only user interaction should get VPN connected in failure state. */
- else if (service->state == CONNMAN_SERVICE_STATE_FAILURE &&
- reason != CONNMAN_SERVICE_CONNECT_REASON_USER)
- return;
vpn_auto_connect();
}
@@ -3515,14 +3583,6 @@ int __connman_service_reset_ipconfig(struct connman_service *service,
return err;
}
-/*
- * We set the timeout to 1 sec so that we have a chance to get
- * necessary IPv6 router advertisement messages that might have
- * DNS data etc.
- */
-#define ONLINE_CHECK_INITIAL_INTERVAL 1
-#define ONLINE_CHECK_MAX_INTERVAL 12
-
void __connman_service_wispr_start(struct connman_service *service,
enum connman_ipconfig_type type)
{
@@ -3530,10 +3590,10 @@ void __connman_service_wispr_start(struct connman_service *service,
if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
service->online_check_interval_ipv4 =
- ONLINE_CHECK_INITIAL_INTERVAL;
+ online_check_initial_interval;
else
service->online_check_interval_ipv6 =
- ONLINE_CHECK_INITIAL_INTERVAL;
+ online_check_initial_interval;
__connman_wispr_start(service, type);
}
@@ -3717,9 +3777,7 @@ static DBusMessage *set_property(DBusConnection *conn,
service_save(service);
timeservers_configuration_changed(service);
-
- if (service == connman_service_get_default())
- __connman_timeserver_sync(service);
+ __connman_timeserver_conf_update(service);
} else if (g_str_equal(name, "Domains.Configuration")) {
DBusMessageIter entry;
@@ -4166,6 +4224,12 @@ static bool auto_connect_service(GList *services,
continue;
}
+ if (service->connect_reason ==
+ CONNMAN_SERVICE_CONNECT_REASON_NATIVE) {
+ DBG("service %p uses native autonnect, skip", service);
+ continue;
+ }
+
if (service->pending ||
is_connecting(service->state) ||
is_connected(service->state)) {
@@ -4495,7 +4559,7 @@ static DBusMessage *connect_service(DBusConnection *conn,
struct connman_service *temp = list->data;
if (!is_connecting(temp->state) && !is_connected(temp->state))
- break;
+ continue;
if (service == temp)
continue;
@@ -4762,27 +4826,22 @@ static void service_schedule_changed(void)
services_notify->id = g_timeout_add(100, service_send_changed, NULL);
}
-static DBusMessage *move_service(DBusConnection *conn,
- DBusMessage *msg, void *user_data,
- bool before)
+int __connman_service_move(struct connman_service *service,
+ struct connman_service *target, bool before)
{
- struct connman_service *service = user_data;
- struct connman_service *target;
- const char *path;
enum connman_ipconfig_method target4, target6;
enum connman_ipconfig_method service4, service6;
DBG("service %p", service);
- dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
- DBUS_TYPE_INVALID);
+ if (!service)
+ return -EINVAL;
if (!service->favorite)
- return __connman_error_not_supported(msg);
+ return -EOPNOTSUPP;
- target = find_service(path);
if (!target || !target->favorite || target == service)
- return __connman_error_invalid_service(msg);
+ return -EINVAL;
if (target->type == CONNMAN_SERVICE_TYPE_VPN) {
/*
@@ -4793,14 +4852,14 @@ static DBusMessage *move_service(DBusConnection *conn,
connman_info("Cannot move service. "
"No routes defined for provider %s",
__connman_provider_get_ident(target->provider));
- return __connman_error_invalid_service(msg);
+ return -EINVAL;
}
- set_split_routing(target, true);
+ __connman_service_set_split_routing(target, true);
} else
- set_split_routing(target, false);
+ __connman_service_set_split_routing(target, false);
- set_split_routing(service, false);
+ __connman_service_set_split_routing(service, false);
target4 = __connman_ipconfig_get_method(target->ipconfig_ipv4);
target6 = __connman_ipconfig_get_method(target->ipconfig_ipv6);
@@ -4823,7 +4882,7 @@ static DBusMessage *move_service(DBusConnection *conn,
if (service6 != CONNMAN_IPCONFIG_METHOD_OFF) {
if (!check_suitable_state(target->state_ipv6,
service->state_ipv6))
- return __connman_error_invalid_service(msg);
+ return -EINVAL;
}
}
@@ -4831,7 +4890,7 @@ static DBusMessage *move_service(DBusConnection *conn,
if (service4 != CONNMAN_IPCONFIG_METHOD_OFF) {
if (!check_suitable_state(target->state_ipv4,
service->state_ipv4))
- return __connman_error_invalid_service(msg);
+ return -EINVAL;
}
}
@@ -4839,7 +4898,7 @@ static DBusMessage *move_service(DBusConnection *conn,
if (target6 != CONNMAN_IPCONFIG_METHOD_OFF) {
if (!check_suitable_state(target->state_ipv6,
service->state_ipv6))
- return __connman_error_invalid_service(msg);
+ return -EINVAL;
}
}
@@ -4847,7 +4906,7 @@ static DBusMessage *move_service(DBusConnection *conn,
if (target4 != CONNMAN_IPCONFIG_METHOD_OFF) {
if (!check_suitable_state(target->state_ipv4,
service->state_ipv4))
- return __connman_error_invalid_service(msg);
+ return -EINVAL;
}
}
@@ -4870,6 +4929,39 @@ static DBusMessage *move_service(DBusConnection *conn,
service_schedule_changed();
+ return 0;
+}
+
+static DBusMessage *move_service(DBusConnection *conn,
+ DBusMessage *msg, void *user_data,
+ bool before)
+{
+ struct connman_service *service = user_data;
+ struct connman_service *target;
+ const char *path;
+ int err;
+
+ DBG("service %p", service);
+
+ dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
+ DBUS_TYPE_INVALID);
+
+ target = find_service(path);
+
+ err = __connman_service_move(service, target, before);
+ switch (err) {
+ case 0:
+ break;
+ case -EINVAL:
+ return __connman_error_invalid_service(msg);
+ case -EOPNOTSUPP:
+ return __connman_error_not_supported(msg);
+ default:
+ connman_warn("unsupported error code %d in move_service()",
+ err);
+ break;
+ }
+
return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
}
@@ -5190,6 +5282,40 @@ void connman_service_unref_debug(struct connman_service *service,
g_hash_table_remove(service_hash, service->identifier);
}
+static gint service_compare(gconstpointer a, gconstpointer b);
+
+static gint service_compare_vpn(struct connman_service *a,
+ struct connman_service *b)
+{
+ struct connman_provider *provider;
+ struct connman_service *service;
+ struct connman_service *transport;
+ const char *ident;
+ bool reverse;
+
+ if (a->provider) {
+ provider = a->provider;
+ service = b;
+ reverse = false;
+ } else if (b->provider) {
+ provider = b->provider;
+ service = a;
+ reverse = true;
+ } else {
+ return 0;
+ }
+
+ ident = __connman_provider_get_transport_ident(provider);
+ transport = connman_service_lookup_from_identifier(ident);
+ if (!transport)
+ return 0;
+
+ if (reverse)
+ return service_compare(service, transport);
+
+ return service_compare(transport, service);
+}
+
static gint service_compare(gconstpointer a, gconstpointer b)
{
struct connman_service *service_a = (void *) a;
@@ -5204,6 +5330,17 @@ static gint service_compare(gconstpointer a, gconstpointer b)
b_connected = is_connected(state_b);
if (a_connected && b_connected) {
+ int rval;
+
+ /* Compare the VPN transport and the service */
+ if ((service_a->type == CONNMAN_SERVICE_TYPE_VPN ||
+ service_b->type == CONNMAN_SERVICE_TYPE_VPN) &&
+ service_b->type != service_a->type) {
+ rval = service_compare_vpn(service_a, service_b);
+ if (rval)
+ return rval;
+ }
+
if (service_a->order > service_b->order)
return -1;
@@ -5596,6 +5733,7 @@ static void report_error_cb(void *user_context, bool retry,
__connman_service_clear_error(service);
service_complete(service);
+ service_list_sort();
__connman_connection_update_gateway();
}
}
@@ -5667,14 +5805,18 @@ static void request_input_cb(struct connman_service *service,
goto done;
}
- if (service->hidden && name_len > 0 && name_len <= 32) {
- device = connman_network_get_device(service->network);
- security = connman_network_get_string(service->network,
- "WiFi.Security");
- err = __connman_device_request_hidden_scan(device,
- name, name_len,
- identity, passphrase,
- security, user_data);
+ if (service->hidden) {
+ if (name_len > 0 && name_len <= 32) {
+ device = connman_network_get_device(service->network);
+ security = connman_network_get_string(service->network,
+ "WiFi.Security");
+ err = __connman_device_request_hidden_scan(device,
+ name, name_len,
+ identity, passphrase,
+ security, user_data);
+ } else {
+ err = -EINVAL;
+ }
if (err < 0)
__connman_service_return_error(service, -err,
user_data);
@@ -5989,6 +6131,7 @@ static int service_indicate_state(struct connman_service *service)
report_error_cb,
get_dbus_sender(service),
NULL);
+ goto notifier;
}
service_complete(service);
break;
@@ -5998,6 +6141,7 @@ static int service_indicate_state(struct connman_service *service)
__connman_connection_update_gateway();
+notifier:
if ((old_state == CONNMAN_SERVICE_STATE_ONLINE &&
new_state != CONNMAN_SERVICE_STATE_READY) ||
(old_state == CONNMAN_SERVICE_STATE_READY &&
@@ -6184,11 +6328,13 @@ static gboolean redo_wispr_ipv6(gpointer user_data)
return FALSE;
}
-int __connman_service_online_check_failed(struct connman_service *service,
- enum connman_ipconfig_type type)
+void __connman_service_online_check(struct connman_service *service,
+ enum connman_ipconfig_type type,
+ bool success)
{
GSourceFunc redo_func;
- int *interval;
+ unsigned int *interval;
+ enum connman_service_state current_state;
if (type == CONNMAN_IPCONFIG_TYPE_IPV4) {
interval = &service->online_check_interval_ipv4;
@@ -6198,6 +6344,22 @@ int __connman_service_online_check_failed(struct connman_service *service,
redo_func = redo_wispr_ipv6;
}
+ if(!enable_online_to_ready_transition)
+ goto redo_func;
+
+ if (success) {
+ *interval = online_check_max_interval;
+ } else {
+ current_state = service->state;
+ downgrade_state(service);
+ if (current_state != service->state)
+ *interval = online_check_initial_interval;
+ if (service != connman_service_get_default()) {
+ return;
+ }
+ }
+
+redo_func:
DBG("service %p type %s interval %d", service,
__connman_ipconfig_type2string(type), *interval);
@@ -6205,12 +6367,10 @@ int __connman_service_online_check_failed(struct connman_service *service,
redo_func, connman_service_ref(service));
/* Increment the interval for the next time, set a maximum timeout of
- * ONLINE_CHECK_MAX_INTERVAL * ONLINE_CHECK_MAX_INTERVAL seconds.
+ * online_check_max_interval seconds * online_check_max_interval seconds.
*/
- if (*interval < ONLINE_CHECK_MAX_INTERVAL)
+ if (*interval < online_check_max_interval)
(*interval)++;
-
- return EAGAIN;
}
int __connman_service_ipconfig_indicate_state(struct connman_service *service,
@@ -6567,6 +6727,12 @@ int __connman_service_connect(struct connman_service *service,
__connman_service_clear_error(service);
+ if (service->network && service->autoconnect &&
+ __connman_network_native_autoconnect(service->network)) {
+ DBG("service %p switch connecting reason to native", service);
+ reason = CONNMAN_SERVICE_CONNECT_REASON_NATIVE;
+ }
+
err = service_connect(service);
DBG("service %p err %d", service, err);
@@ -6665,36 +6831,6 @@ int __connman_service_disconnect(struct connman_service *service)
return err;
}
-int __connman_service_disconnect_all(void)
-{
- struct connman_service *service;
- GSList *services = NULL, *list;
- GList *iter;
-
- DBG("");
-
- for (iter = service_list; iter; iter = iter->next) {
- service = iter->data;
-
- if (!is_connected(service->state))
- break;
-
- services = g_slist_prepend(services, service);
- }
-
- for (list = services; list; list = list->next) {
- struct connman_service *service = list->data;
-
- service->ignore = true;
-
- __connman_service_disconnect(service);
- }
-
- g_slist_free(services);
-
- return 0;
-}
-
/**
* lookup_by_identifier:
* @identifier: service identifier
@@ -6810,14 +6946,14 @@ static int service_register(struct connman_service *service)
DBG("path %s", service->path);
- if (__connman_config_provision_service(service) < 0)
- service_load(service);
-
g_dbus_register_interface(connection, service->path,
CONNMAN_SERVICE_INTERFACE,
service_methods, service_signals,
NULL, service, NULL);
+ if (__connman_config_provision_service(service) < 0)
+ service_load(service);
+
service_list_sort();
__connman_connection_update_gateway();
@@ -7222,6 +7358,50 @@ static void update_from_network(struct connman_service *service,
service_list_sort();
}
+static void trigger_autoconnect(struct connman_service *service)
+{
+ struct connman_device *device;
+ bool native;
+
+ if (!service->favorite)
+ return;
+
+ native = __connman_network_native_autoconnect(service->network);
+ if (native && service->autoconnect) {
+ DBG("trigger native autoconnect");
+ connman_network_set_autoconnect(service->network, true);
+ return;
+ }
+
+ device = connman_network_get_device(service->network);
+ if (device && connman_device_get_scanning(device, CONNMAN_SERVICE_TYPE_UNKNOWN))
+ return;
+
+ switch (service->type) {
+ case CONNMAN_SERVICE_TYPE_UNKNOWN:
+ case CONNMAN_SERVICE_TYPE_SYSTEM:
+ case CONNMAN_SERVICE_TYPE_P2P:
+ break;
+
+ case CONNMAN_SERVICE_TYPE_GADGET:
+ case CONNMAN_SERVICE_TYPE_ETHERNET:
+ if (service->autoconnect) {
+ __connman_service_connect(service,
+ CONNMAN_SERVICE_CONNECT_REASON_AUTO);
+ break;
+ }
+
+ /* fall through */
+ case CONNMAN_SERVICE_TYPE_BLUETOOTH:
+ case CONNMAN_SERVICE_TYPE_GPS:
+ case CONNMAN_SERVICE_TYPE_VPN:
+ case CONNMAN_SERVICE_TYPE_WIFI:
+ case CONNMAN_SERVICE_TYPE_CELLULAR:
+ do_auto_connect(service, CONNMAN_SERVICE_CONNECT_REASON_AUTO);
+ break;
+ }
+}
+
/**
* __connman_service_create_from_network:
* @network: network structure
@@ -7231,7 +7411,6 @@ static void update_from_network(struct connman_service *service,
struct connman_service * __connman_service_create_from_network(struct connman_network *network)
{
struct connman_service *service;
- struct connman_device *device;
const char *ident, *group;
char *name;
unsigned int *auto_connect_types, *favorite_types;
@@ -7305,37 +7484,7 @@ struct connman_service * __connman_service_create_from_network(struct connman_ne
service_register(service);
service_schedule_added(service);
- if (service->favorite) {
- device = connman_network_get_device(service->network);
- if (device && !connman_device_get_scanning(device,
- CONNMAN_SERVICE_TYPE_UNKNOWN)) {
-
- switch (service->type) {
- case CONNMAN_SERVICE_TYPE_UNKNOWN:
- case CONNMAN_SERVICE_TYPE_SYSTEM:
- case CONNMAN_SERVICE_TYPE_P2P:
- break;
-
- case CONNMAN_SERVICE_TYPE_GADGET:
- case CONNMAN_SERVICE_TYPE_ETHERNET:
- if (service->autoconnect) {
- __connman_service_connect(service,
- CONNMAN_SERVICE_CONNECT_REASON_AUTO);
- break;
- }
-
- /* fall through */
- case CONNMAN_SERVICE_TYPE_BLUETOOTH:
- case CONNMAN_SERVICE_TYPE_GPS:
- case CONNMAN_SERVICE_TYPE_VPN:
- case CONNMAN_SERVICE_TYPE_WIFI:
- case CONNMAN_SERVICE_TYPE_CELLULAR:
- do_auto_connect(service,
- CONNMAN_SERVICE_CONNECT_REASON_AUTO);
- break;
- }
- }
- }
+ trigger_autoconnect(service);
__connman_notifier_service_add(service, service->name);