Send connman mailing list submissions to
        [email protected]

To subscribe or unsubscribe via the World Wide Web, visit
        https://lists.01.org/mailman/listinfo/connman
or, via email, send a message with subject or body 'help' to
        [email protected]

You can reach the person managing the list at
        [email protected]

When replying, please edit your Subject line so it is more specific
than "Re: Contents of connman digest..."


Today's Topics:

   1. RE: [RFC] vpn: Restrict connman-vpnd capabilities (Andrew Bibb)
   2. [RFC] Storage based service retrieval + removal
      (MANIEZZO Marco (MM))


----------------------------------------------------------------------

Message: 1
Date: Wed, 10 Feb 2016 19:30:22 -0500
From: Andrew Bibb <[email protected]>
To: Patrik Flykt <[email protected]>
Cc: "[email protected]" <[email protected]>
Subject: RE: [RFC] vpn: Restrict connman-vpnd capabilities
Message-ID: <[email protected]>
Content-Type: text/plain; charset="iso-8859-1"



> Subject: Re: [RFC] vpn: Restrict connman-vpnd capabilities
> From: [email protected]
> To: [email protected]
> CC: [email protected]
> Date: Wed, 10 Feb 2016 09:48:25 +0200
> 
> 
>       Hi,
> 
> On Tue, 2016-02-09 at 19:24 -0500, Andrew Bibb wrote:
> 
> > The file pointed to by OpenVPN.ConfigFile has no entry for --tmp-dir,
> > so I tried adding that line with it pointing /var and then /tmp
> > (reboot between) and no luck.
> 
> --tmp-dir is better placed in /tmp. Stopping the vpn service and killing
> connman-vpnd should be enough.
> 
> > ps axu | grep openvpn returns one line so it appears that the daemon
> > starts.
> > 
> > In connmanctl immediately after typing "connect" an error is returned:
> > Error /net/connman/service/SERVICE_NAME: Input/output error
> 
> Is connman-vpnd trying to ask input from you? Have a connmanctl running
> with 'vpnagent on' to see if the user is prompted for something.
> 
> > I was thinking it was a permissions error which is what led me to the
> > mailing list posting.  After trying the --tmp-dir option with no luck
> > I removed the single line:
> > 
> > CapabilityBoundingSet=CAP_KILL CAP_NET_ADMIN CAP_NET_BIND_SERVICE
> > CAP_NET_RAW
> 
> If this worked, then VPNC started by connman-vpnd needs some extra
> capability. For startes check that the VPNC daemon is capable of writing
> into the temporary directory as it is one possible source of problems
> since the capalities are now limited.
> 
> > The ProtectHome and ProtectSystem lines I left in and that combination
> > of lines work.  I can make a connection just as it used to.  
> > 
> > 
> > It is very much sounding like it is not a Connman issue, but rather a
> > packaging issue. I can open a bug report on Arch. I also want to see
> > what they did between 1.31-1 and 1-31-2.  I upgrade on a weekly basis
> > and completely missed the 1.31-1 release.  It must not have been out
> > there for long.
> 
> The 1.31-2 does something funny when symlinking /etc/resolv.conf, it
> basically drops the /run direcotory creation. But the previous version,
> if installed, has already created the symlink from /etc/resolv.conf or
> similar. I was unable to quickly figure out whether something else was
> modified, I'm not familiar with Arch Linux packaging.
> 
> Cheers,
> 
>       Patrik
> 
To your questions:I ran connmanctl again (had also done so before) with 
vpnagent on and no difference.  Connmanctl immediately exits with the 
Input/output error.  
I checked the change log on Arch and the change between 1.31-1 and 1.31-2 is 
that they delete /usr/lib/tmpfiles.d/connman/connman_resolveconf.conf after 
install.  That does not seem right to me, but it is after the install so unless 
Connman sources that file I suppose it would not make any difference.  The 
change was made because someone's custom /etc/resolve.conf was being 
overwritten by Connman.  I also think that is wrong as I though once you 
installed Connman you were supposed to let Connman deal with all the routing 
stuff.  I don't believe that is directly related to this problem (but if it is 
wrong let me know and I'll file a bug report on it) Anyway, I got a copy of 
1.31-1, installed it (stopped and started connman-vpn) and no changes.
Lastly I decided to play around with the CapabiliyBoundingSet a bit based on 
your suggestion.  Adding CAP_DAC_READ_SEARCH to the "as shipped" list will 
allow OpenVPN to connect.  I never even knew these existed until this evening, 
and I only picked that one based on reading the manpage, so the probability of 
it being the proper one is likely not great.  Using CAP_DAC_OVERRIDE also 
works, but that bypasses write permissions and seems to be overkill.
Andrew                                    
-------------- next part --------------
An HTML attachment was scrubbed...
URL: 
<http://lists.01.org/pipermail/connman/attachments/20160210/b61688a9/attachment-0001.html>

------------------------------

Message: 2
Date: Thu, 11 Feb 2016 08:20:03 +0000
From: "MANIEZZO Marco (MM)" <[email protected]>
To: Patrik Flykt <[email protected]>, Marcel Holtmann
        <[email protected]>
Cc: "[email protected]" <[email protected]>
Subject: [RFC] Storage based service retrieval + removal
Message-ID: <[email protected]>
Content-Type: text/plain; charset="utf-8"

>-----Messaggio originale-----
>Da: Patrik Flykt [mailto:[email protected]]
>Inviato: luned? 1 febbraio 2016 14:26
>A: Marcel Holtmann
>Cc: MANIEZZO Marco (MM); [email protected]
>Oggetto: Re: [RFC 1/2] Storage based service retrieval
>
>On Mon, 2016-02-01 at 14:18 +0100, Marcel Holtmann wrote:
>> calling Remove on an immutable service (provided by a .config)
>> essentially means resetting that service to its defaults. If that is
>> not working, then it is a bug.
>
>Ok, in this case the current implementation may (or may not) have a bug with 
>Remove().
>
>Cheers,
>
>Patrik


Hello Patrick, Marcel,

Thank you for your feedback, I worked on the subject trying to follow your 
suggestions but keeping at minimum the modifications and resources usage.

Currently the services that are available (say visible Access Points for WiFi) 
are kept in the heap and they have an active DBUS path for methods and signals. 
I could add to these data structures also the services got from storage, for 
removal purposes mainly, but also for config methods like you mentioned. But I 
thought that I would waste memory doubling data related to services both 
available and stored.

Another solution could be to reuse the Favorite property of the service and 
keep in the heap these so they could be accessed by GetKnowServices but I saw 
too much logic change with related risks, in actual architecture in the 
mechanism to insert/remove of available services in/from heap.

Then I preferred to implement a solution that doesn?t touch the current logic 
on available service and does not introduce extra permanent allocated heap: the 
available services have their location in heap plus in the storage once they 
become favorite and saved services can be accessed only reading from storage. 
If they are also available some properties (like state) are read from heap 
structures. To be accessed by the DBUS I added them to it with a "_stored" 
appended to the path so to not confuse with their heap location, and DBUS path, 
that can be present or not, depending on availability or not. For now I have 
only supported the Remove method, but being services all the current methods 
can be extended to take care of them. So the user will get the list of 
available services with GetServices and the list of the stored services with 
GetKnownServices. On both the Remove method will apply, while the other methods 
will apply only on available ones.

The Remove method keeps current strategy where immutable services .config file 
is not touched; only the service folder and its content is deleted while heap 
info are re-provisioned from .config file implementing the requested "reset to 
its default". For mutable services like now it will clear heap data but it 
introduces the missing removal of the folder and its content, as well as 
"_stored" DBUS path.

The modifications showed no issues with valgrind, and 1000+ stored services did 
not show excessive lag.

You can find below the new modification, please let me know your comments.

Thanks and Regards,
Marco

client/commands.c   |  13 ++
 doc/connmanctl.1.in |   7 +
 doc/manager-api.txt |  17 ++
 doc/service-api.txt |  13 +-
 include/provision.h |   4 +
 src/config.c        |   5 +
 src/connman.h       |   1 +
 src/manager.c       |  23 +++
 src/service.c       | 498 +++++++++++++++++++++++++++++++++++++++++++++-------
 tools/manager-api.c |  33 ++++
 10 files changed, 543 insertions(+), 71 deletions(-)


diff --git a/client/commands.c b/client/commands.c
index eec200f..f7941e2 100644
--- a/client/commands.c
+++ b/client/commands.c
@@ -348,6 +348,17 @@ static int object_properties(DBusMessageIter *iter,
 return 0;
 }

+static int cmd_known_services(char *args[], int num, struct connman_option 
*options)
+{
+if (num > 1)
+return -E2BIG;
+
+return __connmanctl_dbus_method_call(connection,
+CONNMAN_SERVICE, CONNMAN_PATH,
+"net.connman.Manager", "GetKnownServices",
+services_list, NULL, NULL, NULL);
+}
+
 static int cmd_services(char *args[], int num, struct connman_option *options)
 {
 char *service_name = NULL;
@@ -2553,6 +2564,8 @@ static const struct {
   lookup_tether },
 { "services",     "[<service>]",  service_options, cmd_services,
   "Display services", lookup_service_arg },
+{ "known-services",     NULL,  NULL, cmd_known_services,
+    "Display known services", NULL },
 { "peers",        "[peer]",       NULL,            cmd_peers,
   "Display peers", lookup_peer_arg },
 { "scan",         "<technology>", NULL,            cmd_scan,
diff --git a/doc/connmanctl.1.in b/doc/connmanctl.1.in
index 0f891bd..2c6e569 100644
--- a/doc/connmanctl.1.in
+++ b/doc/connmanctl.1.in
@@ -12,6 +12,7 @@ SYNOPSIS
 .BI tether \ technology\ \fRon|off\ |
 .BI tether\fR\ wifi\ on|off\  ssid\ passphrase\fR\ |
 .BR services \ [\fIservice\fR]\ |
+.BR known-services\fR\ |
 .BI peers \ peer\fR\ |
 .BI scan \ technology\fR\ |
 .RI \fBconnect \ service | peer \ |
@@ -103,6 +104,12 @@ Only the service path (e.g. 
wifi_6834534139723_managed_none)
 is accepted as a parameter.
 .PP
 .TP
+.B known-services
+Returns a sorted list of tuples with service object path and dictionary of 
service
+properties, for the known services (both mutable and immutable).
+This list will not contain sensitive information like passphrases etc.
+.PP
+.TP
 .BI scan \ technology
 Scans for new services on the given technology.
 .PP
diff --git a/doc/manager-api.txt b/doc/manager-api.txt
index 31e137c..f2a2267 100644
--- a/doc/manager-api.txt
+++ b/doc/manager-api.txt
@@ -45,6 +45,23 @@ Methodsdict GetProperties()
 and dictionary of peer properties

 Possible Errors: [service].Error.InvalidArguments
+
+array{object,dict} GetKnownServices() [experimental]
+
+Returns a sorted list of tuples with service object
+path and dictionary of service properties, for the
+known services (both mutable and immutable).
+
+This list will not contain sensitive information
+like passphrases etc.
+
+The objects have a "_stored" appended to the path
+(e.g. wifi_6067208eac78_474f4c5045_managed_psk_stored)
+and the only available method of this kind of services
+is currently Remove, while the other Service methods
+will return error.
+
+Possible Errors: [service].Error.InvalidArguments

 object ConnectProvider(dict provider)[deprecated]

diff --git a/doc/service-api.txt b/doc/service-api.txt
index e2e9e84..1e23072 100644
--- a/doc/service-api.txt
+++ b/doc/service-api.txt
@@ -94,11 +94,14 @@ Methodsdict GetProperties()  [deprecated]
 service is in the State=failure, this method can
 also be used to reset the service.

-Calling this method on Ethernet devices, hidden WiFi
-services or provisioned services will cause an error
-message. It is not possible to remove these kind of
-services.
-
+Calling this method on Ethernet devices and hidden WiFi
+services will cause an error message. It is not possible
+to remove these kind ofservices.
+
+For the other services the removal will cause the
+deletion of their folder inSTORAGEDIR. Immutable
+services .config file will not be deleted.
+
 Possible Errors: [service].Error.InvalidArguments

 void MoveBefore(object service)
diff --git a/include/provision.h b/include/provision.h
index 3eb80a8..a497415 100644
--- a/include/provision.h
+++ b/include/provision.h
@@ -23,6 +23,7 @@
 #define __CONNMAN_PROVISION_H

 #include <stdbool.h>
+#include <connman/service.h>

 #ifdef __cplusplus
 extern "C" {
@@ -40,6 +41,9 @@ struct connman_config_entry {
 void *ssid;
 unsigned int ssid_len;
 bool hidden;
+char *config_ident;
+char *config_entry;
+enum connman_service_security security;
 };

 int connman_config_provision_mutable_service(GKeyFile *keyfile);
diff --git a/src/config.c b/src/config.c
index 344b8ce..6e1151a 100644
--- a/src/config.c
+++ b/src/config.c
@@ -1575,6 +1575,9 @@ struct connman_config_entry 
**connman_config_get_entries(const char *type)

 entries[i]->ident = g_strdup(config->ident);
 entries[i]->name = g_strdup(config->name);
+entries[i]->security = config->security;
+entries[i]->config_ident = g_strdup(config->config_ident);
+entries[i]->config_entry = g_strdup(config->config_entry);
 entries[i]->ssid = g_try_malloc0(config->ssid_len + 1);
 if (!entries[i]->ssid)
 goto cleanup;
@@ -1617,6 +1620,8 @@ void connman_config_free_entries(struct 
connman_config_entry **entries)
 g_free(entries[i]->ident);
 g_free(entries[i]->name);
 g_free(entries[i]->ssid);
+g_free(entries[i]->config_ident);
+g_free(entries[i]->config_entry);
 g_free(entries[i]);
 }

diff --git a/src/connman.h b/src/connman.h
index 447bdd7..041b191 100644
--- a/src/connman.h
+++ b/src/connman.h
@@ -654,6 +654,7 @@ int __connman_service_init(void);
 void __connman_service_cleanup(void);
 int __connman_service_load_modifiable(struct connman_service *service);

+void __connman_known_service_list_struct(DBusMessageIter *iter);
 void __connman_service_list_struct(DBusMessageIter *iter);

 int __connman_service_compare(const struct connman_service *a,
diff --git a/src/manager.c b/src/manager.c
index d15ce20..1f59644 100644
--- a/src/manager.c
+++ b/src/manager.c
@@ -175,6 +175,11 @@ static struct connman_notifier technology_notifier = {
 .idle_state= idle_state,
 };

+static void append_known_service_structs(DBusMessageIter *iter, void 
*user_data)
+{
+__connman_known_service_list_struct(iter);
+}
+
 static void append_service_structs(DBusMessageIter *iter, void *user_data)
 {
 __connman_service_list_struct(iter);
@@ -195,6 +200,21 @@ static DBusMessage *get_services(DBusConnection *conn,
 return reply;
 }

+static DBusMessage *get_known_services(DBusConnection *conn,
+DBusMessage *msg, void *data)
+{
+DBusMessage *reply;
+
+reply = dbus_message_new_method_return(msg);
+if (!reply)
+return NULL;
+
+__connman_dbus_append_objpath_dict_array(reply,
+append_known_service_structs, NULL);
+
+return reply;
+}
+
 static void append_peer_structs(DBusMessageIter *iter, void *user_data)
 {
 __connman_peer_list_struct(iter);
@@ -513,6 +533,9 @@ static const GDBusMethodTable manager_methods[] = {
 { GDBUS_DEPRECATED_METHOD("RemoveProvider",
 GDBUS_ARGS({ "provider", "o" }), NULL,
 remove_provider) },
+{ GDBUS_METHOD("GetKnownServices",
+NULL, GDBUS_ARGS({ "knownServices", "a(oa{sv})" }),
+get_known_services) },
 { GDBUS_METHOD("GetServices",
 NULL, GDBUS_ARGS({ "services", "a(oa{sv})" }),
 get_services) },
diff --git a/src/service.c b/src/service.c
index a93aebf..b04afba 100644
--- a/src/service.c
+++ b/src/service.c
@@ -34,7 +34,7 @@
 #include <connman/storage.h>
 #include <connman/setting.h>
 #include <connman/agent.h>
-
+#include <connman/provision.h>
 #include "connman.h"

 #define CONNECT_TIMEOUT120
@@ -49,6 +49,11 @@ static unsigned int vpn_autoconnect_timeout = 0;
 static struct connman_service *current_default = NULL;
 static bool services_dirty = false;

+struct provision_user_data {
+const char *ident;
+int ret;
+};
+
 struct connman_stats {
 bool valid;
 bool enabled;
@@ -127,6 +132,12 @@ struct connman_service {
 char *config_entry;
 };

+static void service_free_data(struct connman_service *service);
+
+static void provision_changed(gpointer value, gpointer user_data);
+
+static void service_free(gpointer user_data);
+
 static bool allow_property_changed(struct connman_service *service);

 static struct connman_ipconfig *create_ip4config(struct connman_service 
*service,
@@ -589,6 +600,20 @@ static int service_load(struct connman_service *service)
 service->hidden_service = g_key_file_get_boolean(keyfile,
 service->identifier, "Hidden", NULL);

+str = g_key_file_get_string(keyfile,
+service->identifier, "Config.ident", NULL);
+if (str) {
+g_free(service->config_entry);
+service->config_entry = str;
+}
+
+str = g_key_file_get_string(keyfile,
+service->identifier, "Config.file", NULL);
+if (str) {
+g_free(service->config_file);
+service->config_file = str;
+}
+
 done:
 g_key_file_free(keyfile);

@@ -4085,7 +4110,7 @@ bool __connman_service_remove(struct connman_service 
*service)
 service->type == CONNMAN_SERVICE_TYPE_GADGET)
 return false;

-if (service->immutable || service->hidden ||
+if (service->hidden ||
 __connman_provider_is_immutable(service->provider))
 return false;

@@ -4095,6 +4120,12 @@ bool __connman_service_remove(struct connman_service 
*service)

 __connman_service_disconnect(service);

+/* in case of immutable service don't touch data, it will be
+     * re-provisioned from .config file by __connman_known_service_remove
+     */
+if (service->immutable)
+return(true);
+
 g_free(service->passphrase);
 service->passphrase = NULL;

@@ -4118,17 +4149,118 @@ bool __connman_service_remove(struct connman_service 
*service)

 service_save(service);

+return(true);
+}
+
+bool __connman_known_service_remove(struct connman_service *service)
+{
+DBG("Removing %s", service->identifier);
+
+if (service->type == CONNMAN_SERVICE_TYPE_ETHERNET ||
+service->type == CONNMAN_SERVICE_TYPE_GADGET)
+{
+return false;
+}
+
+if (service->hidden ||
+__connman_provider_is_immutable(service->provider))
+{
+return false;
+}
+
+__connman_storage_remove_service(service->identifier);
+
+
+if (service->immutable == true && service->config_file)
+{/* force reprovision of immutable services */
+struct provision_user_data data = {
+.ident = service->config_file,
+.ret = 0,
+};
+
+provision_changed(service, &data);
+}
+
 return true;
 }

 static DBusMessage *remove_service(DBusConnection *conn,
 DBusMessage *msg, void *user_data)
 {
-struct connman_service *service = user_data;
+struct connman_service *service = NULL;
+struct connman_service *available_service = NULL;
+char *available_service_path = NULL;
+gchar **service_ID_parts = NULL;
+gchar *identifier;
+int return_val = 0;
+
+if(user_data == NULL)
+{//if it is null then we are talking about a saved service
+service = connman_service_create();
+
+if(service != NULL)
+{
+service->path = g_strdup(dbus_message_get_path(msg));
+service_ID_parts = g_strsplit(service->path, "/", -1);
+identifier = g_strdup(service_ID_parts[g_strv_length(service_ID_parts)-1]);
+g_strfreev(service_ID_parts);
+service_ID_parts = g_strsplit(identifier, "_stored", -1);
+g_free(identifier);
+service->identifier = g_strdup(service_ID_parts[0]);
+g_strfreev(service_ID_parts);
+service_ID_parts = g_strsplit(service->identifier, "_", -1);
+service->type = __connman_service_string2type(service_ID_parts[0]);
+g_strfreev(service_ID_parts);
+
+/*get service from available service list, if present*/
+available_service_path = g_strconcat(CONNMAN_PATH, 
"/service/",service->identifier,NULL);
+available_service = find_service(available_service_path);
+g_free(available_service_path);
+
+if(available_service == NULL)
+{/*remove asked for a stored service not currently available*/
+
+/*retrieve mutable/immutable info*/
+if (-EIO == service_load(service) || (service->config_file != NULL && 
service->config_entry != NULL))
+service->immutable = true;
+
+/*remove from storage if present*/
+return_val = __connman_known_service_remove(service);
+
+/*once removed the _stored service must disappear from DBUS*/
+g_dbus_unregister_interface(connection, service->path, 
CONNMAN_SERVICE_INTERFACE);
+}
+else
+{/*remove asked for a stored service currently available*/

-DBG("service %p", service);
+/*disconnect + reset data in memory*/
+return_val = __connman_service_remove(available_service);
+
+/*remove from storage if present*/
+return_val &= __connman_known_service_remove(available_service);
+}
+}
+else
+return __connman_error_operation_aborted(msg);
+
+}
+else
+{/* remove asked for an available service*/
+service = user_data;
+DBG("service %p", service);
+
+/*disconnect + reset data*/
+return_val = __connman_service_remove(service);
+
+/*remove from storage if present*/
+return_val &= __connman_known_service_remove(service);
+}
+
+
+if(user_data == NULL)
+service_free_data(service);

-if (!__connman_service_remove(service))
+if (!return_val)
 return __connman_error_not_supported(msg);

 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
@@ -4467,7 +4599,7 @@ static const GDBusMethodTable service_methods[] = {
 GDBUS_ARGS({ "name", "s" }), NULL,
 clear_property) },
 { GDBUS_ASYNC_METHOD("Connect", NULL, NULL,
-      connect_service) },
+connect_service) },
 { GDBUS_METHOD("Disconnect", NULL, NULL,
 disconnect_service) },
 { GDBUS_METHOD("Remove", NULL, NULL, remove_service) },
@@ -4487,92 +4619,153 @@ static const GDBusSignalTable service_signals[] = {
 { },
 };

-static void service_free(gpointer user_data)
-{
-struct connman_service *service = user_data;
-char *path = service->path;
-
-DBG("service %p", service);
-
-reply_pending(service, ENOENT);
-
-__connman_notifier_service_remove(service);
-service_schedule_removed(service);
-
-__connman_wispr_stop(service);
-stats_stop(service);

-service->path = NULL;
-
-if (path) {
-__connman_connection_update_gateway();
-
-g_dbus_unregister_interface(connection, path,
-CONNMAN_SERVICE_INTERFACE);
-g_free(path);
-}
+static void service_free_data(struct connman_service *service)
+{
+if(service->path != NULL)
+g_free(service->path);

-g_hash_table_destroy(service->counter_table);
+if(service->counter_table != NULL)
+g_hash_table_destroy(service->counter_table);

-if (service->network) {
+if (service->network != NULL) {
 __connman_network_disconnect(service->network);
 connman_network_unref(service->network);
 service->network = NULL;
 }

-if (service->provider)
+if (service->provider != NULL)
 connman_provider_unref(service->provider);

-if (service->ipconfig_ipv4) {
+if (service->ipconfig_ipv4 != NULL) {
 __connman_ipconfig_set_ops(service->ipconfig_ipv4, NULL);
 __connman_ipconfig_set_data(service->ipconfig_ipv4, NULL);
 __connman_ipconfig_unref(service->ipconfig_ipv4);
 service->ipconfig_ipv4 = NULL;
 }

-if (service->ipconfig_ipv6) {
+if (service->ipconfig_ipv6 != NULL) {
 __connman_ipconfig_set_ops(service->ipconfig_ipv6, NULL);
 __connman_ipconfig_set_data(service->ipconfig_ipv6, NULL);
 __connman_ipconfig_unref(service->ipconfig_ipv6);
 service->ipconfig_ipv6 = NULL;
 }

-g_strfreev(service->timeservers);
-g_strfreev(service->timeservers_config);
-g_strfreev(service->nameservers);
-g_strfreev(service->nameservers_config);
-g_strfreev(service->nameservers_auto);
-g_strfreev(service->domains);
-g_strfreev(service->proxies);
-g_strfreev(service->excludes);
+if(service->timeservers != NULL)
+g_strfreev(service->timeservers);

-g_free(service->hostname);
-g_free(service->domainname);
-g_free(service->pac);
-g_free(service->name);
-g_free(service->passphrase);
-g_free(service->identifier);
-g_free(service->eap);
-g_free(service->identity);
-g_free(service->anonymous_identity);
-g_free(service->agent_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);
-g_free(service->config_file);
-g_free(service->config_entry);
+if(service->timeservers_config != NULL)
+g_strfreev(service->timeservers_config);
+
+if(service->nameservers != NULL)
+g_strfreev(service->nameservers);
+
+if(service->nameservers_config != NULL)
+g_strfreev(service->nameservers_config);
+
+if(service->nameservers_auto != NULL)
+g_strfreev(service->nameservers_auto);
+
+if(service->domains != NULL)
+g_strfreev(service->domains);

-if (service->stats.timer)
+if(service->proxies != NULL)
+g_strfreev(service->proxies);
+
+if(service->excludes != NULL)
+g_strfreev(service->excludes);
+
+if(service->hostname != NULL)
+g_free(service->hostname);
+
+if(service->domainname != NULL)
+g_free(service->domainname);
+
+if(service->pac != NULL)
+g_free(service->pac);
+
+if(service->name != NULL)
+g_free(service->name);
+
+if(service->passphrase != NULL)
+g_free(service->passphrase);
+
+if(service->identifier != NULL)
+g_free(service->identifier);
+
+if(service->eap != NULL)
+g_free(service->eap);
+
+if(service->identity != NULL)
+g_free(service->identity);
+
+if(service->anonymous_identity != NULL)
+g_free(service->anonymous_identity);
+
+if(service->agent_identity != NULL)
+g_free(service->agent_identity);
+
+if(service->ca_cert_file != NULL)
+g_free(service->ca_cert_file);
+
+if(service->client_cert_file != NULL)
+g_free(service->client_cert_file);
+
+if(service->private_key_file != NULL)
+g_free(service->private_key_file);
+
+if(service->private_key_passphrase != NULL)
+g_free(service->private_key_passphrase);
+
+if(service->phase2 != NULL)
+g_free(service->phase2);
+
+if(service->config_file != NULL)
+g_free(service->config_file);
+
+if(service->config_entry != NULL)
+g_free(service->config_entry);
+
+if (service->stats.timer != NULL)
 g_timer_destroy(service->stats.timer);
-if (service->stats_roaming.timer)
+
+if (service->stats_roaming.timer != NULL)
 g_timer_destroy(service->stats_roaming.timer);

+if(service != NULL)
+g_free(service);
+}
+
+
+static void service_free(gpointer user_data)
+{
+struct connman_service *service = user_data;
+char *path = service->path;
+
+DBG("service %p", service);
+
+
+reply_pending(service, ENOENT);
+
+__connman_notifier_service_remove(service);
+service_schedule_removed(service);
+
+__connman_wispr_stop(service);
+stats_stop(service);
+
+
+if (path) {
+
+__connman_connection_update_gateway();
+
+g_dbus_unregister_interface(connection, path,
+CONNMAN_SERVICE_INTERFACE);
+}
+
 if (current_default == service)
 current_default = NULL;

-g_free(service);
+service_free_data(service);
 }

 static void stats_init(struct connman_service *service)
@@ -6195,10 +6388,7 @@ static struct connman_service 
*lookup_by_identifier(const char *identifier)
 return g_hash_table_lookup(service_hash, identifier);
 }

-struct provision_user_data {
-const char *ident;
-int ret;
-};
+

 static void provision_changed(gpointer value, gpointer user_data)
 {
@@ -7149,3 +7339,179 @@ void __connman_service_cleanup(void)

 dbus_connection_unref(connection);
 }
+
+static const GDBusMethodTable known_service_methods[] = {
+{ GDBUS_METHOD("Remove", NULL, NULL, remove_service) },
+{ },
+};
+
+struct find_provision {
+char *provision;
+bool found;
+};
+
+static void find_provision(gpointer value, gpointer user_data)
+{
+gchar *current_provision = value;
+struct find_provision *data = user_data;
+
+if (data->found)
+return;
+
+if (g_strcmp0(current_provision, data->provision) == 0)
+data->found = true;
+}
+
+void __connman_known_service_list_struct(DBusMessageIter *iter)
+{
+gchar **services = NULL;
+gchar **service_ID_parts = NULL;
+gchar *provision_string = NULL;
+GSList *provisions_list = NULL;
+struct connman_config_entry **comman_config_entries;
+int i = 0, j = 0;
+struct connman_service *service = NULL;
+struct find_provision data = { .provision = NULL, .found = false };
+
+DBG("listing known services");
+
+services = connman_storage_get_services();
+if (services == NULL)
+return;
+
+for (i = 0; i < g_strv_length(services); i++)
+{
+service = connman_service_create();
+if (service == NULL)
+{
+connman_error("connman_service_create() allocation failed");
+return ;
+}
+
+service->identifier = g_strdup(services[i]);
+service_ID_parts = g_strsplit(services[i], "_", -1);
+
+if(service_ID_parts != NULL)
+{
+service->type = __connman_service_string2type(service_ID_parts[0]);
+service->path = g_strdup_printf("%s/service/%s", CONNMAN_PATH, 
service->identifier);
+if(service->type == CONNMAN_SERVICE_TYPE_WIFI)
+service->security = 
__connman_service_string2security(service_ID_parts[g_strv_length(service_ID_parts)-1]);
+
+if(service->path != NULL)
+{
+if(find_service(service->path) != NULL)
+{
+service->state = (find_service(service->path))->state;
+service->name = g_strdup((find_service(service->path))->name);
+service->autoconnect = (find_service(service->path))->autoconnect;
+service->favorite = (find_service(service->path))->favorite;
+}
+
+if (service_load(service) != 0)
+{
+connman_error("service_load() returned error");
+service_free_data(service);
+g_strfreev(service_ID_parts);
+g_strfreev(services);
+return;
+}
+
+/* save immutable ident and entry, if present, to be used later while
+ * adding immutable services*/
+if(service->config_entry != NULL && service->config_file != NULL)
+{
+provision_string = 
g_strdup_printf("%s%s",service->config_entry,service->config_file);
+
+if (provision_string != NULL)
+{
+provisions_list = g_slist_insert_sorted(provisions_list,
+g_strdup(provision_string),
+(GCompareFunc)strcmp);
+
+g_free(provision_string);
+provision_string = NULL;
+}
+}
+
+/* append "_stored" to the service path, to distinguish it from available 
services */
+g_free(service->path);
+service->path = g_strdup_printf("%s/service/%s_stored", CONNMAN_PATH, 
service->identifier);
+
+append_struct_service(iter, append_dict_properties, service);
+
+g_dbus_register_interface(connection, service->path,
+CONNMAN_SERVICE_INTERFACE,
+known_service_methods, NULL,
+NULL, NULL, NULL);
+}
+g_strfreev(service_ID_parts);
+}
+service_free_data(service);
+}
+g_strfreev(services);
+
+
+/* Now read the services provided of a .config file*/
+for(j=CONNMAN_SERVICE_TYPE_SYSTEM; j <MAX_CONNMAN_SERVICE_TYPES; j++)
+{
+comman_config_entries = 
connman_config_get_entries(__connman_service_type2string(j));
+for(i=0; comman_config_entries != NULL && comman_config_entries[i] != NULL; 
i++)
+{
+/*check we haven't already loaded it*/
+data.provision = g_strdup_printf("%s%s",
+comman_config_entries[i]->config_entry,
+comman_config_entries[i]->config_ident);
+data.found = false;
+g_slist_foreach(provisions_list, find_provision, &data);
+
+g_free(data.provision);
+
+if(!data.found)
+{
+service = connman_service_create();
+if (service == NULL)
+{
+connman_error("connman_service_create() allocation failed");
+connman_config_free_entries(comman_config_entries);
+g_slist_free_full(provisions_list, g_free);
+return ;
+}
+
+service->type = j;
+/*create an obj path for service, using unique fields */
+service->identifier = g_strdup_printf("%s_%s_%s",
+__connman_service_type2string(service->type),
+comman_config_entries[i]->config_ident,
+comman_config_entries[i]->config_entry);
+service->path = g_strdup_printf("%s/service/%s_stored", CONNMAN_PATH, 
service->identifier);
+if(find_service(service->path) != NULL)
+{
+service->state = (find_service(service->path))->state;
+service->security = (find_service(service->path))->security;
+service->name = g_strdup((find_service(service->path))->name);
+service->autoconnect = (find_service(service->path))->autoconnect;
+service->favorite = (find_service(service->path))->favorite;
+}
+else
+{
+service->security = comman_config_entries[i]->security;
+if(comman_config_entries[i]->name != NULL)
+service->name = g_strdup(comman_config_entries[i]->name);
+}
+
+append_struct_service(iter, append_dict_properties, service);
+
+g_dbus_register_interface(connection, service->path,
+CONNMAN_SERVICE_INTERFACE,
+known_service_methods, NULL,
+NULL, NULL, NULL);
+
+service_free_data(service);
+}
+}
+connman_config_free_entries(comman_config_entries);
+}
+
+g_slist_free_full(provisions_list, g_free);
+}
diff --git a/tools/manager-api.c b/tools/manager-api.c
index e082962..9e97f70 100644
--- a/tools/manager-api.c
+++ b/tools/manager-api.c
@@ -64,6 +64,39 @@ static DBusMessage *set_property(DBusConnection *connection,
 return reply;
 }

+DBusMessage *manager_get_known_services(DBusConnection *connection)
+{
+DBusMessage *message, *reply;
+DBusError error;
+
+message = dbus_message_new_method_call(CONNMAN_SERVICE,
+CONNMAN_MANAGER_PATH,
+CONNMAN_MANAGER_INTERFACE,
+"GetKnownServices");
+
+if (!message)
+return NULL;
+
+dbus_error_init(&error);
+
+reply = dbus_connection_send_with_reply_and_block(connection,
+message, -1, &error);
+if (!reply) {
+if (dbus_error_is_set(&error)) {
+LOG("%s", error.message);
+dbus_error_free(&error);
+} else {
+LOG("Failed to get known services");
+}
+dbus_message_unref(message);
+return NULL;
+}
+
+dbus_message_unref(message);
+
+return reply;
+}
+
 DBusMessage *manager_get_services(DBusConnection *connection)
 {
 DBusMessage *message, *reply;








________________________________

VISITA IL NOSTRO NUOVO SITO WEB! - VISIT OUR NEW WEB SITE! 
www.magnetimarelli.com

Confidential Notice: This message - including its attachments - may contain 
proprietary, confidential and/or legally protected information and is intended 
solely for the use of the designated addressee(s) above. If you are not the 
intended recipient be aware that any downloading, copying, disclosure, 
distribution or use of the contents of the above information is strictly 
prohibited.
If you have received this communication by mistake, please forward the message 
back to the sender at the email address above, delete the message from all 
mailboxes and any other electronic storage medium and destroy all copies.
Disclaimer Notice: Internet communications cannot be guaranteed to be safe or 
error-free. Therefore we do not assure that this message is complete or 
accurate and we do not accept liability for any errors or omissions in the 
contents of this message.

------------------------------

Subject: Digest Footer

_______________________________________________
connman mailing list
[email protected]
https://lists.01.org/mailman/listinfo/connman


------------------------------

End of connman Digest, Vol 4, Issue 13
**************************************

Reply via email to