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. [PATCH v2 1/2] dns: support for systemd-resolved and backend
      selection. (Ismo Puustinen)
   2. [PATCH v2 2/2] doc: added documentation for running without
      DNS resolving. (Ismo Puustinen)
   3. Re: [PATCH 1/2] dns: support for systemd-resolved and backend
      selection. (Daniel Wagner)


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

Message: 1
Date: Thu,  5 Oct 2017 16:50:30 +0300
From: Ismo Puustinen <[email protected]>
To: [email protected]
Subject: [PATCH v2 1/2] dns: support for systemd-resolved and backend
        selection.
Message-ID: <[email protected]>

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.
---
 Makefile.am                |  15 +-
 configure.ac               |  14 ++
 src/dns-systemd-resolved.c | 454 +++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 481 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..a7d9c6d8
--- /dev/null
+++ b/src/dns-systemd-resolved.c
@@ -0,0 +1,454 @@
+/*
+ *
+ *  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;
+
+/* update after a full set of instructions has been received */
+static guint update_interfaces_source = 0;
+
+struct dns_interface {
+       GList *domains;
+       GList *servers;
+       int index;
+       bool needs_domain_update;
+       bool needs_server_update;
+};
+
+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;
+
+       if (!iface)
+               return;
+
+       g_list_free_full(iface->domains, g_free);
+       g_list_free_full(iface->servers, g_free);
+
+       g_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) {
+                       result = inet_pton(type, server, ipv4_bytes);
+                       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) {
+                       result = inet_pton(type, server, ipv6_bytes);
+                       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 (iface->needs_server_update) {
+               if (!g_dbus_proxy_method_call(resolved_proxy, "SetLinkDNS",
+                               setlinkdns_append, NULL, iface, NULL))
+                       return -EINVAL;
+
+               iface->needs_server_update = FALSE;
+       }
+
+       if (iface->needs_domain_update) {
+               if (!g_dbus_proxy_method_call(resolved_proxy, "SetLinkDomains",
+                               setlinkdomains_append, NULL, iface, NULL))
+                       return -EINVAL;
+
+               iface->needs_domain_update = FALSE;
+       }
+
+       return 0;
+}
+
+static bool is_empty(struct dns_interface *iface)
+{
+       if (!iface)
+               return FALSE;
+
+       return (!iface->domains && !iface->servers);
+}
+
+static gboolean update_interface(gpointer key, gpointer value, gpointer data)
+{
+       struct dns_interface *iface = value;
+       GList **removed_items = data;
+
+       set_systemd_resolved_values(iface);
+
+       if (is_empty(iface))
+               *removed_items = g_list_prepend(*removed_items, iface);
+
+       /* don't stop the tree traversal */
+       return FALSE;
+}
+
+static int update_systemd_resolved(gpointer data)
+{
+       GList *removed_items = NULL, *list;
+
+       if (!interface_map) {
+               DBG("no interface map when updating");
+               return G_SOURCE_REMOVE;
+       }
+
+       g_tree_foreach(interface_map, update_interface, &removed_items);
+
+       for (list = removed_items; list; list = g_list_next(list)) {
+               struct dns_interface *iface = list->data;
+               g_tree_remove(interface_map, GUINT_TO_POINTER(iface->index));
+       }
+
+       g_list_free(removed_items);
+
+       update_interfaces_source = 0;
+       return G_SOURCE_REMOVE;
+}
+
+static GList *remove_string(GList *str_list, const char *str)
+{
+       GList *match = NULL;
+
+       match = g_list_find_custom(str_list, str,
+                       (GCompareFunc) g_strcmp0);
+
+       if (match) {
+               g_free(match->data);
+                       return g_list_delete_link(str_list, match);
+       }
+
+       return str_list;
+}
+
+static void remove_values(struct dns_interface *iface, const char *domain,
+                                                       const char *server)
+{
+       if (!iface)
+               return;
+
+       if (domain) {
+               iface->domains = remove_string(iface->domains, domain);
+               iface->needs_domain_update = TRUE;
+       }
+
+       if (server) {
+               iface->servers = remove_string(iface->servers, server);
+               iface->needs_server_update = TRUE;
+       }
+}
+
+int __connman_dnsproxy_remove(int index, const char *domain,
+                                                       const char *server)
+{
+       struct dns_interface *iface;
+
+       DBG("%d, %s, %s", index, domain ? domain : "no domain",
+                       server ? server : "no server");
+
+       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);
+
+       if (!update_interfaces_source)
+               update_interfaces_source = g_idle_add(update_systemd_resolved,
+                               NULL);
+
+       return 0;
+}
+
+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 (g_strcmp0(orig, str) == 0) {
+                       str_list = g_list_remove(str_list, orig);
+                       g_free(orig);
+                       break;
+               }
+       }
+
+       return g_list_append(str_list, g_strdup(str));
+}
+
+int __connman_dnsproxy_append(int index, const char *domain,
+                                                       const char *server)
+{
+       struct dns_interface *iface;
+
+       DBG("%d, %s, %s", index, domain ? domain : "no domain",
+                       server ? server : "no server");
+
+       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;
+
+               iface->index = index;
+               g_tree_insert(interface_map, GUINT_TO_POINTER(index), iface);
+       }
+
+       if (domain) {
+               iface->domains = replace_to_end(iface->domains, domain);
+               iface->needs_domain_update = TRUE;
+       }
+
+       if (server) {
+               iface->servers = replace_to_end(iface->servers, server);
+               iface->needs_server_update = TRUE;
+       }
+
+       if (!update_interfaces_source)
+               update_interfaces_source = g_idle_add(update_systemd_resolved,
+                               NULL);
+
+       return 0;
+}
+
+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 (update_interfaces_source) {
+               /* It might be that we don't get to an idle loop anymore, so
+                * run the update function once more to clean up.
+                */
+                g_source_remove(update_interfaces_source);
+                update_systemd_resolved(NULL);
+                update_interfaces_source = 0;
+       }
+
+       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;
+       }
+}
-- 
2.13.6



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

Message: 2
Date: Thu,  5 Oct 2017 16:50:31 +0300
From: Ismo Puustinen <[email protected]>
To: [email protected]
Subject: [PATCH v2 2/2] doc: added documentation for running without
        DNS resolving.
Message-ID: <[email protected]>

If '-r' option is used, do not use either dnsproxy or systemd-resolved
backend. Instead update /etc/resolv.conf and let applications do the
resolving.
---
 README           | 10 ++++++++++
 doc/connman.8.in | 16 +++++++++-------
 src/main.c       |  2 +-
 3 files changed, 20 insertions(+), 8 deletions(-)

diff --git a/README b/README
index cbd86a5f..f9610e13 100644
--- a/README
+++ b/README
@@ -220,6 +220,16 @@ For a working system, certain configuration options need 
to be enabled:
                        # semodule -i connman-task.pp
                in order to enable the dbus access.
 
+    --with-dns-backend=TYPE
+
+               Enable support for a DNS resolving backend
+
+               Select a DNS backend to use. Supported values are "internal"
+               and "systemd-resolved". If "internal" is selected, ConnMan
+               will be build with a caching DNS proxy. If "systemd-resolved"
+               is selected, ConnMan configures systemd-resolved to do DNS
+               resolving. The default value is "internal".
+
 
 Activating debugging
 ====================
diff --git a/doc/connman.8.in b/doc/connman.8.in
index ddfba09b..85e7c5e0 100644
--- a/doc/connman.8.in
+++ b/doc/connman.8.in
@@ -88,13 +88,15 @@ Do not daemonize. This is useful for debugging, and directs 
log output to
 the controlling terminal in addition to syslog.
 .TP
 .BR \-r ", " \-\-nodnsproxy
-Do not act as a DNS proxy. By default ConnMan will direct all DNS traffic
-to itself by setting nameserver to 127.0.0.1 in \fBresolv.conf\fP(5) file.
-If this is not desired and you want that all programs call directly some
-DNS server, then you can use the \fB--nodnsproxy\fP option.
-If this option is used, then ConnMan is not able to cache the DNS queries
-because the DNS traffic is not going through ConnMan and that can cause
-some extra network traffic.
+Do not act as a DNS proxy or support external DNS resolving. Depending
+on how ConnMan is compiled, it will by default direct all DNS traffic
+to itself by setting nameserver to 127.0.0.1 in \fBresolv.conf\fP(5)
+file or leave DNS management to an external entity, such as
+systemd-resolved. If this is not desired and you want that all programs
+call directly some DNS server, then you can use the \fB--nodnsproxy\fP
+option. If this option is used, then ConnMan is not able to cache the
+DNS queries because the DNS traffic is not going through ConnMan and that
+can cause some extra network traffic.
 .SH SEE ALSO
 .BR connmanctl (1), \ connman.conf (5), \ connman-service.config (5), \c
 .BR \ connman-vpn (8)
diff --git a/src/main.c b/src/main.c
index b78a0461..7b00eb3e 100644
--- a/src/main.c
+++ b/src/main.c
@@ -571,7 +571,7 @@ static GOptionEntry options[] = {
                                "Don't fork daemon to background" },
        { "nodnsproxy", 'r', G_OPTION_FLAG_REVERSE,
                                G_OPTION_ARG_NONE, &option_dnsproxy,
-                               "Don't enable DNS Proxy" },
+                               "Don't support DNS resolving" },
        { "nobacktrace", 0, G_OPTION_FLAG_REVERSE,
                                G_OPTION_ARG_NONE, &option_backtrace,
                                "Don't print out backtrace information" },
-- 
2.13.6



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

Message: 3
Date: Thu, 5 Oct 2017 19:44:42 +0200
From: Daniel Wagner <[email protected]>
To: "Puustinen, Ismo" <[email protected]>
Cc: "[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/05/2017 03:38 PM, Puustinen, Ismo wrote:
>> 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.

Thanks these tips help a lot. I wonder if we should put them into some 
hacking file. Might be handy.

Anyway, I found the problem. So my version of systemd-resolved doesn't 
follow CNAMEs. It is fixed in v233 but my system still ships v231

https://github.com/systemd/systemd/issues/3826

>> 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.
The main reason I am not keen on adding g_tree_*() is that there is 
still the plan to use ELL instead of glib. Not sure if that library has 
something like a binary tree container. And since we use in many places 
already a hash table for index lookup I wouldn't worry too much about 
performance anyway :)

Thanks,
Daniel


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

Subject: Digest Footer

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


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

End of connman Digest, Vol 24, Issue 8
**************************************

Reply via email to