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: [PATCH 1/2] dns: support for systemd-resolved and backend
selection. (Daniel Wagner)
2. Re: [PATCH 1/2] dns: support for systemd-resolved and backend
selection. (Daniel Wagner)
3. RE: [PATCH 1/2] dns: support for systemd-resolved and backend
selection. (Puustinen, Ismo)
4. RE: [PATCH 1/2] dns: support for systemd-resolved and backend
selection. (Puustinen, Ismo)
----------------------------------------------------------------------
Message: 1
Date: Wed, 4 Oct 2017 22:36:57 +0200
From: Daniel Wagner <[email protected]>
To: Ismo Puustinen <[email protected]>, [email protected]
Subject: Re: [PATCH 1/2] dns: support for systemd-resolved and backend
selection.
Message-ID: <[email protected]>
Content-Type: text/plain; charset=utf-8
Hi Ismo,
On 10/03/2017 04:02 PM, Ismo Puustinen wrote:
> During configure, use --with-dns-backend to declare which DNS backend
> you want to use during build. The two options available are "internal"
> and "systemd-resolved".
>
> The internal backend works as previously. The systemd-resolved backend
> configures systemd-resolved over D-Bus.
>
> The "-r" command line option for connmand still works. It means that the
> DNS servers (either internal DNS proxy or systemd-resolved) aren't used,
> and instead connmand just updates /etc/resolv.conf file.
I got my setup working. I just had to RTFM systemd-resolved :)
This version looks much better and it seems all to work fine.
Just a question. In the log I see following things:
connmand[22701]: wlp2s0b1 {add} address 192.168.154.54/24 label wlp2s0b1 family
2
connmand[22701]: src/dns-systemd-resolved.c:__connman_dnsproxy_remove()
connmand[22701]: src/dns-systemd-resolved.c:setlinkdns_append() index: 3,
server: 192.168.154.1
connmand[22701]: src/dns-systemd-resolved.c:setlinkdomains_append() index: 3,
domain: localdomain
connmand[22701]: src/dns-systemd-resolved.c:__connman_dnsproxy_remove()
connmand[22701]: src/dns-systemd-resolved.c:setlinkdns_append() index: 3,
server: 192.168.154.1
connmand[22701]: src/dns-systemd-resolved.c:setlinkdomains_append() index: 3,
domain: localdomain
connmand[22701]: src/dns-systemd-resolved.c:__connman_dnsproxy_append()
connmand[22701]: src/dns-systemd-resolved.c:setlinkdns_append() index: 3,
server: 192.168.154.1
connmand[22701]: src/dns-systemd-resolved.c:setlinkdomains_append() index: 3,
domain: localdomain
connmand[22701]: src/dns-systemd-resolved.c:__connman_dnsproxy_append()
connmand[22701]: src/dns-systemd-resolved.c:setlinkdns_append() index: 3,
server: 192.168.154.1
connmand[22701]: src/dns-systemd-resolved.c:setlinkdomains_append() index: 3,
domain: localdomain
Is this supposed to be like this? I mean appending two times the server
for interface with index 3?
There is only one real thing I would like you to fixup (apart of
my usual nitpicking). There seems to be some allocation done using glib
function such as g_new0 and then the allocation is freed by free(). Please
use the g_free() version which allows us the glib memory allocation debugging
facility to use. Quite handy to find memory leaks.
> ---
> Makefile.am | 15 +-
> configure.ac | 14 ++
> src/dns-systemd-resolved.c | 378
> +++++++++++++++++++++++++++++++++++++++++++++
> 3 files changed, 405 insertions(+), 2 deletions(-)
> create mode 100644 src/dns-systemd-resolved.c
>
> diff --git a/Makefile.am b/Makefile.am
> index e67a7a55..97f1c87d 100644
> --- a/Makefile.am
> +++ b/Makefile.am
> @@ -120,11 +120,18 @@ src_connmand_SOURCES = $(gdhcp_sources) $(gweb_sources)
> $(backtrace_sources) \
> src/storage.c src/dbus.c src/config.c \
> src/technology.c src/counter.c src/ntp.c \
> src/session.c src/tethering.c src/wpad.c src/wispr.c \
> - src/stats.c src/dnsproxy.c src/6to4.c \
> + src/stats.c src/6to4.c \
> src/ippool.c src/bridge.c src/nat.c src/ipaddress.c \
> src/inotify.c src/ipv6pd.c src/peer.c \
> src/peer_service.c src/machine.c src/util.c
>
> +if INTERNAL_DNS_BACKEND
> +src_connmand_SOURCES += src/dnsproxy.c
> +endif
> +if SYSTEMD_RESOLVED_DNS_BACKEND
> +src_connmand_SOURCES += src/dns-systemd-resolved.c
> +endif
> +
> src_connmand_LDADD = gdbus/libgdbus-internal.la $(builtin_libadd) \
> @GLIB_LIBS@ @DBUS_LIBS@ @GNUTLS_LIBS@ \
> -lresolv -ldl -lrt
> @@ -178,7 +185,11 @@ vpn_connman_vpnd_LDFLAGS = -Wl,--export-dynamic \
> endif
>
> BUILT_SOURCES = $(local_headers) src/builtin.h $(service_files) \
> - scripts/connman scripts/connman_resolvconf.conf
> + scripts/connman
> +
> +if INTERNAL_DNS_BACKEND
> +BUILT_SOURCES += scripts/connman_resolvconf.conf
> +endif
>
> if VPN
> BUILT_SOURCES += vpn/builtin.h
> diff --git a/configure.ac b/configure.ac
> index 4baa6852..4feccc08 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -433,4 +433,18 @@ AM_CONDITIONAL(VPN, test "${enable_openconnect}" != "no"
> -o \
> "${enable_l2tp}" != "no" -o \
> "${enable_pptp}" != "no")
>
> +AC_MSG_CHECKING(which DNS backend to use)
> +AC_ARG_WITH(dns-backend, AC_HELP_STRING([--with-dns-backend=TYPE],
> + [specify which DNS backend to use: internal or systemd-resolved
> [default=internal]]),
> + [dns_backend=${withval}],
> + [dns_backend="internal"])
> +
> +if (test "${dns_backend}" != "internal" -a \
> + "${dns_backend}" != "systemd-resolved"); then
> + AC_MSG_ERROR(no suitable DNS backend defined)
> +fi
> +AM_CONDITIONAL(INTERNAL_DNS_BACKEND, test "${dns_backend}" = "internal")
> +AM_CONDITIONAL(SYSTEMD_RESOLVED_DNS_BACKEND, test "${dns_backend}" =
> "systemd-resolved")
> +AC_MSG_RESULT(${dns_backend})
> +
> AC_OUTPUT(Makefile include/version.h connman.pc)
> diff --git a/src/dns-systemd-resolved.c b/src/dns-systemd-resolved.c
> new file mode 100644
> index 00000000..3cb752e6
> --- /dev/null
> +++ b/src/dns-systemd-resolved.c
> @@ -0,0 +1,378 @@
> +/*
> + *
> + * Connection Manager
> + *
> + * Copyright (C) 2007-2017 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
> + * published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
> USA
> + *
> + */
> +
> +#ifdef HAVE_CONFIG_H
> +#include <config.h>
> +#endif
> +
> +#include <errno.h>
> +#include <stdlib.h>
> +#include <unistd.h>
> +#include <string.h>
> +#include <gdbus.h>
> +#include <glib.h>
> +#include <connman/dbus.h>
> +
> +#include "connman.h"
> +
> +#define SYSTEMD_RESOLVED_SERVICE "org.freedesktop.resolve1"
> +#define SYSTEMD_RESOLVED_PATH "/org/freedesktop/resolve1"
> +
> +static GTree *interface_map = NULL;
> +static DBusConnection *connection = NULL;
> +static GDBusClient *client = NULL;
> +static GDBusProxy *resolved_proxy = NULL;
> +
> +struct dns_interface {
> + GList *domains;
> + GList *servers;
> + int index;
> +};
> +
> +static gint int_cmp(gconstpointer a, gconstpointer b, void *data)
> +{
> + gint ai = GPOINTER_TO_UINT(a);
> + gint bi = GPOINTER_TO_UINT(b);
> +
> + return ai - bi;
> +}> +
> +static void free_dns_interface(gpointer data)
> +{
> + struct dns_interface *iface = data;
> +
> + DBG("%p", data);
> +
> + if (!iface)
> + return;
> +
> + g_list_free_full(iface->domains, free);
> + g_list_free_full(iface->servers, free);
If I got it right domains and servers are allocated via glib
allocators, e.g g_new0. In this case you should use the matching
free function, that is g_free. That allows us the memory debugging
facilities of glib.
> +
> + free(iface);
> +}
> +
> +static void setlinkdns_append(DBusMessageIter *iter, void *user_data)
> +{
> + struct dns_interface *iface = user_data;
> + int result;
> + unsigned int i;
> + int type;
> + char ipv4_bytes[4];
> + char ipv6_bytes[16];
> + GList *list;
> + DBusMessageIter address_array, struct_array, byte_array;
> +
> + dbus_message_iter_append_basic(iter, DBUS_TYPE_INT32, &iface->index);
> +
> + dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY, "(iay)",
> + &address_array);
> +
> + for (list = iface->servers; list; list = g_list_next(list)) {
> + char *server = list->data;
> +
> + DBG("index: %d, server: %s", iface->index, server);
> +
> + dbus_message_iter_open_container(&address_array,
> + DBUS_TYPE_STRUCT, NULL, &struct_array);
> +
> + type = connman_inet_check_ipaddress(server);
> +
> + if (type == AF_INET) {
> +
No need for a new line here.
> + result = inet_pton(type, server, ipv4_bytes);
> +
or here.
> + if (!result) {
> + DBG("Failed to parse IPv4 address: %s",
> + server);
> + return;
> + }
> +
> + dbus_message_iter_append_basic(&struct_array,
> + DBUS_TYPE_INT32, &type);
> +
> + dbus_message_iter_open_container(&struct_array,
> + DBUS_TYPE_ARRAY, "y", &byte_array);
> +
> + for (i = 0; i < sizeof(ipv4_bytes); i++) {
> + dbus_message_iter_append_basic(&byte_array,
> + DBUS_TYPE_BYTE,
> + &(ipv4_bytes[i]));
> + }
> +
> + dbus_message_iter_close_container(&struct_array,
> + &byte_array);
> + } else if (type == AF_INET6) {
> +
no new line.
> + result = inet_pton(type, server, ipv6_bytes);
> +
and here.
> + if (!result) {
> + DBG("Failed to parse IPv6 address: %s",
> + server);
> + return;
> + }
> +
> + dbus_message_iter_append_basic(&struct_array,
> + DBUS_TYPE_INT32, &type);
> +
> + dbus_message_iter_open_container(&struct_array,
> + DBUS_TYPE_ARRAY, "y", &byte_array);
> +
> + for (i = 0; i < sizeof(ipv6_bytes); i++) {
> + dbus_message_iter_append_basic(&byte_array,
> + DBUS_TYPE_BYTE,
> + &(ipv6_bytes[i]));
> + }
> +
> + dbus_message_iter_close_container(&struct_array,
> + &byte_array);
> + }
> +
> + dbus_message_iter_close_container(&address_array,
> + &struct_array);
> + }
> +
> + dbus_message_iter_close_container(iter, &address_array);
> +}
> +
> +static void setlinkdomains_append(DBusMessageIter *iter, void *user_data)
> +{
> + struct dns_interface *iface = user_data;
> + GList *list;
> + DBusMessageIter domain_array, struct_array;
> + gboolean only_routing = FALSE;
> +
> + dbus_message_iter_append_basic(iter, DBUS_TYPE_INT32, &iface->index);
> +
> + dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY, "(sb)",
> + &domain_array);
> +
> + for (list = iface->domains; list; list = g_list_next(list)) {
> + char *domain = list->data;
> +
> + DBG("index: %d, domain: %s", iface->index, domain);
> +
> + dbus_message_iter_open_container(&domain_array,
> + DBUS_TYPE_STRUCT, NULL, &struct_array);
> +
> + dbus_message_iter_append_basic(&struct_array, DBUS_TYPE_STRING,
> + &domain);
> +
> + dbus_message_iter_append_basic(&struct_array, DBUS_TYPE_BOOLEAN,
> + &only_routing);
> +
> + dbus_message_iter_close_container(&domain_array, &struct_array);
> + }
> +
> + dbus_message_iter_close_container(iter, &domain_array);
> +}
> +
> +static int set_systemd_resolved_values(struct dns_interface *iface)
> +{
> + if (!resolved_proxy || !iface)
> + return -ENOENT;
> +
> + /* No async error processing -- just fire and forget */
> +
> + if (!g_dbus_proxy_method_call(resolved_proxy, "SetLinkDNS",
> + setlinkdns_append, NULL, iface, NULL))
> + return -EINVAL;
> +
> + if (!g_dbus_proxy_method_call(resolved_proxy, "SetLinkDomains",
> + setlinkdomains_append, NULL, iface, NULL))
> + return -EINVAL;
> +
> + return 0;
> +}
> +
> +static void remove_values(struct dns_interface *iface, const char *domain,
> + const char *server)
> +{
> + if (!iface)
> + return;
> +
> + if (domain)
> + iface->domains = g_list_remove(iface->domains, domain);
> +
> + if (server)
> + iface->servers = g_list_remove(iface->servers, server);
> +}
> +
> +static bool is_empty(struct dns_interface *iface)
> +{
> + if (!iface)
> + return FALSE;
> +
> + return (!iface->domains && !iface->servers);
> +}
> +
> +int __connman_dnsproxy_remove(int index, const char *domain,
> + const char *server)
> +{
> + struct dns_interface *iface;
> + int ret = 0;
> +
> + DBG("");
> +
> + if (!interface_map || index < 0)
> + return -EINVAL;
> +
> + iface = g_tree_lookup(interface_map, GUINT_TO_POINTER(index));
> +
> + if (!iface)
> + return -EINVAL;
> +
> + remove_values(iface, domain, server);
> +
> + ret = set_systemd_resolved_values(iface);
> +
> + if (is_empty(iface))
> + g_tree_remove(interface_map, GUINT_TO_POINTER(index));
> +
> + /* freed during g_tree_remove */
> + iface = NULL;
> +
> + return ret;
> +}
> +
> +static GList *replace_to_end(GList *str_list, const char *str)
> +{
> + GList *list;
> +
> + for (list = str_list; list; list = g_list_next(list)) {
> + char *orig = list->data;
> +
> + if (strcmp(orig, str) == 0) {
I would probably use here the g_strcmp() version just for
consistency sake. But it just nitpicking.
> + str_list = g_list_remove(str_list, orig);
> + free(orig);
> + break;
> + }
> + }
> +
> + return g_list_append(str_list, strdup(str));
> +}
> +
> +int __connman_dnsproxy_append(int index, const char *domain,
> + const char *server)
> +{
> + struct dns_interface *iface;
> +
> + DBG("");
> +
> + if (!interface_map || index < 0)
> + return -EINVAL;
> +
> + iface = g_tree_lookup(interface_map, GUINT_TO_POINTER(index));
> +
> + if (!iface) {
> + iface = g_new0(struct dns_interface, 1);
> + if (!iface)
> + return -ENOMEM;
> + g_tree_insert(interface_map, GUINT_TO_POINTER(index), iface);
> + }
> +
> + if (domain)
> + iface->domains = replace_to_end(iface->domains, domain);
> +
> + if (server)
> + iface->servers = replace_to_end(iface->servers, server);
> +
> + iface->index = index;
> +
> + return set_systemd_resolved_values(iface);
> +}
> +
> +int __connman_dnsproxy_add_listener(int index)
> +{
> + DBG("");
> +
> + return -ENXIO;
> +}
> +
> +void __connman_dnsproxy_remove_listener(int index)
> +{
> + DBG("");
> +}
> +
> +static int setup_resolved(void)
> +{
> + connection = connman_dbus_get_connection();
> +
> + if (!connection)
> + return -ENXIO;
> +
> + client = g_dbus_client_new(connection, SYSTEMD_RESOLVED_SERVICE,
> + SYSTEMD_RESOLVED_PATH);
> +
> + if (!client)
> + return -EINVAL;
> +
> + resolved_proxy = g_dbus_proxy_new(client, SYSTEMD_RESOLVED_PATH,
> + "org.freedesktop.resolve1.Manager");
> +
> + if (!resolved_proxy)
> + return -EINVAL;
> +
> + return 0;
> +}
> +
> +int __connman_dnsproxy_init(void)
> +{
> + int ret;
> +
> + DBG("");
> +
> + if ((ret = setup_resolved()) < 0)
> + return ret;
> +
> + interface_map = g_tree_new_full(int_cmp, NULL, NULL,
> + free_dns_interface);
> +
> + if (!interface_map)
> + return -ENOMEM;
> +
> + return 0;
> +}
> +
> +void __connman_dnsproxy_cleanup(void)
> +{
> + DBG("");
> +
> + if (interface_map) {
> + g_tree_destroy(interface_map);
> + interface_map = NULL;
> + }
> +
> + if (resolved_proxy) {
> + g_dbus_proxy_unref(resolved_proxy);
> + resolved_proxy = NULL;
> + }
> +
> + if (client) {
> + g_dbus_client_unref(client);
> + client = NULL;
> + }
> +
> + if (connection) {
> + dbus_connection_unref(connection);
> + connection = NULL;
> + }
> +}
>
Thanks,
Daniel
------------------------------
Message: 2
Date: Wed, 4 Oct 2017 22:44:37 +0200
From: Daniel Wagner <[email protected]>
To: Ismo Puustinen <[email protected]>, [email protected]
Subject: Re: [PATCH 1/2] dns: support for systemd-resolved and backend
selection.
Message-ID: <[email protected]>
Content-Type: text/plain; charset=utf-8; format=flowed
On 10/04/2017 10:36 PM, Daniel Wagner wrote:
> On 10/03/2017 04:02 PM, Ismo Puustinen wrote:
>> During configure, use --with-dns-backend to declare which DNS backend
>> you want to use during build. The two options available are "internal"
>> and "systemd-resolved".
>>
>> The internal backend works as previously. The systemd-resolved backend
>> configures systemd-resolved over D-Bus.
>>
>> The "-r" command line option for connmand still works. It means that the
>> DNS servers (either internal DNS proxy or systemd-resolved) aren't used,
>> and instead connmand just updates /etc/resolv.conf file.
>
> I got my setup working. I just had to RTFM systemd-resolved :)
>
> This version looks much better and it seems all to work fine.
Maybe I was a bit too fast with 'seems to work'. The browser
is able to reach google but then I get 'server not found'. As far
I can tell systemd-resolved gets the query. Need to debug a bit more
though I run out of steam for now.
Just one more thing. I saw you use g_tree_*() as collocation.
Is there a real need for a balanced binary tree? We try to avoid to
exploit to many APIs of glib. I rather stick hash tables and lists.
Thanks,
Daniel
------------------------------
Message: 3
Date: Thu, 5 Oct 2017 13:31:37 +0000
From: "Puustinen, Ismo" <[email protected]>
To: Daniel Wagner <[email protected]>, "[email protected]"
<[email protected]>
Subject: RE: [PATCH 1/2] dns: support for systemd-resolved and backend
selection.
Message-ID:
<ccdeb7c6a88959479c736e89d8e0adc78ee1f...@irsmsx107.ger.corp.intel.com>
Content-Type: text/plain; charset="utf-8"
> I got my setup working. I just had to RTFM systemd-resolved :)
Great! :-)
> This version looks much better and it seems all to work fine.
> Just a question. In the log I see following things:
>
> connmand[22701]: wlp2s0b1 {add} address 192.168.154.54/24 label wlp2s0b1
> family 2
> connmand[22701]: src/dns-systemd-resolved.c:__connman_dnsproxy_remove()
> connmand[22701]: src/dns-systemd-resolved.c:setlinkdns_append() index: 3,
> server: 192.168.154.1
> connmand[22701]: src/dns-systemd-resolved.c:setlinkdomains_append() index:
> 3, domain: localdomain
> connmand[22701]: src/dns-systemd-resolved.c:__connman_dnsproxy_remove()
> connmand[22701]: src/dns-systemd-resolved.c:setlinkdns_append() index: 3,
> server: 192.168.154.1
> connmand[22701]: src/dns-systemd-resolved.c:setlinkdomains_append() index:
> 3, domain: localdomain
> connmand[22701]: src/dns-systemd-resolved.c:__connman_dnsproxy_append()
> connmand[22701]: src/dns-systemd-resolved.c:setlinkdns_append() index: 3,
> server: 192.168.154.1
> connmand[22701]: src/dns-systemd-resolved.c:setlinkdomains_append() index:
> 3, domain: localdomain
> connmand[22701]: src/dns-systemd-resolved.c:__connman_dnsproxy_append()
> connmand[22701]: src/dns-systemd-resolved.c:setlinkdns_append() index: 3,
> server: 192.168.154.1
> connmand[22701]: src/dns-systemd-resolved.c:setlinkdomains_append() index:
> 3, domain: localdomain
>
>
> Is this supposed to be like this? I mean appending two times the server for
> interface with index 3?
Unfortunately I'm not sure. The __connman_dnsproxy_append() calls reflect what
Connman thinks is going on. I added logging so that we'll know for sure the
parameters to the function call. I also fixed a bug when removing DNS servers
(I was comparing pointers instead of strings, so nothing got removed). Another
change is that I moved sending the DNS D-Bus messages to the idle loop -- this
means that we send only one message when __append and __remove have been called
for multiple times. I'm posting a revised patch set shortly.
I was thinking that I would do some fixes to the overall DNS code after the
systemd-resolved work is done. There are some oddities (for example, Connman
doesn't appear to request search domain removal from an interface when Connman
shuts down). There's also some dead code which we could be removed.
> There is only one real thing I would like you to fixup (apart of my usual
> nitpicking). There seems to be some allocation done using glib function such
> as
> g_new0 and then the allocation is freed by free(). Please use the g_free()
> version
> which allows us the glib memory allocation debugging facility to use. Quite
> handy to find memory leaks.
This is done. I also made the style changes you requested.
Ismo
------------------------------
Message: 4
Date: Thu, 5 Oct 2017 13:38:09 +0000
From: "Puustinen, Ismo" <[email protected]>
To: Daniel Wagner <[email protected]>, "[email protected]"
<[email protected]>
Subject: RE: [PATCH 1/2] dns: support for systemd-resolved and backend
selection.
Message-ID:
<ccdeb7c6a88959479c736e89d8e0adc78ee1f...@irsmsx107.ger.corp.intel.com>
Content-Type: text/plain; charset="utf-8"
> Maybe I was a bit too fast with 'seems to work'. The browser is able to reach
> google but then I get 'server not found'. As far I can tell systemd-resolved
> gets
> the query. Need to debug a bit more though I run out of steam for now.
Argh. Could be many things, for example IPv6 addresses being returned when IPv6
setup is not fully functional. Or something else entirely. Which server is not
found? DNS server or the Google host you browsed to?
If you like, you can turn on debugging for systemd-resolved with the following
commands:
mkdir -p /etc/systemd/system/systemd-resolved.service.d/
cat > /etc/systemd/system/systemd-resolved.service.d/10-debug.conf << EOF
[Service]
Environment=SYSTEMD_LOG_LEVEL=debug
EOF
After this you should either reload system configuration and restart
systemd-resolved, or reboot.
> Just one more thing. I saw you use g_tree_*() as collocation.
> Is there a real need for a balanced binary tree? We try to avoid to exploit to
> many APIs of glib. I rather stick hash tables and lists.
Well, I thought that a tree would be a good data structure for a map from
integers to pointers... fast and probably bit more light-weight than a hash
table. the API is very similar to the hash tables and lists. But if you like, I
can change it to just use lists. Probably we won't be having so many interfaces
that iterating over them would be a problem.
Ismo
------------------------------
Subject: Digest Footer
_______________________________________________
connman mailing list
[email protected]
https://lists.01.org/mailman/listinfo/connman
------------------------------
End of connman Digest, Vol 24, Issue 7
**************************************