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
**************************************