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. Fw: Re: Connman coredump (Cliff McDiarmid)
   2. Re: Fw: Re: Connman coredump (Daniel Wagner)
   3. [PATCH 1/2] resolver: add support for systemd-resolved.
      (Ismo Puustinen)
   4. [PATCH 2/2] service: add mDNS support on per-interface basis.
      (Ismo Puustinen)


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

Message: 1
Date: Tue, 26 Sep 2017 21:24:00 +0200
From: "Cliff McDiarmid" <[email protected]>
To: [email protected]
Subject: Fw: Re: Connman coredump
Message-ID:
        
<trinity-1b7c72fe-bd46-4fc2-9728-27f7b5fe6cba-1506453840779@3c-app-mailcom-lxa06>
        
Content-Type: text/plain; charset=UTF-8

Sent:?Tuesday, September 26, 2017 at 8:18 PM
From:?"Cliff McDiarmid" <[email protected]>
To:?"Daniel Wagner" <[email protected]>
Subject:?Re: Connman coredump
Sent:?Monday, September 25, 2017 at 8:20 PM

From:?"Daniel Wagner" <[email protected]>
To:?"Cliff McDiarmid" <[email protected]>, [email protected]
Subject:?Re: Connman coredump
>connmand[3059]: src/stats.c:__connman_stats_update() ring buffer is full, 
>update history file

>When the buffer is full, ConnMan creates a summary and adds it
>to the history file.

>connmand[3059]: src/stats.c:stats_file_remap() file 0x7ffe2ee42090 size 4096
>addr (nil) len 0

>So this looks still okay. The first remap is the history file open (empty
>.file), the secon remap is a the temporay new history file (also empty).

>(connmand:3059): GLib-CRITICAL **: g_date_set_time_t: assertion
>g_date_valid_dmy (date->day, date->month, date->year)' failed


>Since the first glib message is about g_data_set_time_t(), it could be that
>glib is not happy with the timezone settings.

>https://developer.gnome.org/glib/stable/glib-Date-and-Time-Functions.html#g-date-set-time-t[https://developer.gnome.org/glib/stable/glib-Date-and-Time-Functions.html#g-date-set-time-t[https://developer.gnome.org/glib/stable/glib-Date-and-Time-Functions.html#g-date-set-time-t]]

>g_data_set_time_t() calls g_date_valid_dmy eventually which is pretty unhappy:

>/**
>* g_date_valid_dmy:
>@day: day
>* @month: month
>* @year: year
>*
>* Returns %TRUE if the day-month-year triplet forms a valid, existing day
>* in the range of days #GDate understands (Year 1 or later, no more than
>* a few thousand years in the future).
>*
>* Returns: %TRUE if the date is a valid one
>*/
>gboolean
>g_date_valid_dmy (GDateDay d,
>GDateMonth m,
>GDateYear y)
>{
>return ( (m > G_DATE_BAD_MONTH) &&
>(m < 13) &&
>(d > G_DATE_BAD_DAY) &&
>(y > G_DATE_BAD_YEAR) && /* must check before using g_date_is_leap_year */
>(d <= (g_date_is_leap_year (y) ?
>days_in_months[1][m] : days_in_months[0][m])) );
>}

>Can you check if your time settings are correct on your platform?
?
Thanks Daniel for the advice.?? My time and zone settings look okay:
?
'timedatectl status' gives
?

???? Local time: Tue 2017-09-26 19:30:34 BST
Universal time: Tue 2017-09-26 18:30:34 UTC
????? RTC time: Tue 2017-09-26 18:30:34
????? Time zone: Europe/London (BST, +0100)
Network time on: no
NTP synchronized: no
RTC in local TZ: no
?
Is it possible that this is a bug and ugrading Gilb might help?
?
Connman has been a breeze to run in the past.? This IS my first 64bit system.
?
Cliff
?
?


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

Message: 2
Date: Wed, 27 Sep 2017 09:34:32 +0200
From: Daniel Wagner <[email protected]>
To: Cliff McDiarmid <[email protected]>, [email protected]
Subject: Re: Fw: Re: Connman coredump
Message-ID: <[email protected]>
Content-Type: text/plain; charset=utf-8; format=flowed

Hi Cliff,

> 'timedatectl status' gives
>   
> 
>  ???? Local time: Tue 2017-09-26 19:30:34 BST
> Universal time: Tue 2017-09-26 18:30:34 UTC
>  ????? RTC time: Tue 2017-09-26 18:30:34
>  ????? Time zone: Europe/London (BST, +0100)
> Network time on: no
> NTP synchronized: no
> RTC in local TZ: no
>   
> Is it possible that this is a bug and ugrading Gilb might help?

Maybe, but unlikely. But if it is easy to upgrade or try a different 
version it might be worth to try.

> Connman has been a breeze to run in the past.? This IS my first 64bit system.

What kind of distro are you using? Did you upgrade from a 32bit 
installation to 64bit and keeping the /var/lib/connman directory? If so, 
we just might have to problem, that the history files etc are in 32bit 
and not in 64bit. Just a wild guess.

Thanks,
Daniel


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

Message: 3
Date: Wed, 27 Sep 2017 15:05:39 +0300
From: Ismo Puustinen <[email protected]>
To: [email protected]
Subject: [PATCH 1/2] resolver: add support for systemd-resolved.
Message-ID: <[email protected]>

If systemd-resolved is running, use it for DNS address resolution. In
this case just deliver the DNS addresses to systemd-resolved and do not
run our own DNS proxy. The systemd-resolved support is selected to
be used if command line option "-s" is passed to connmand. This
implicitly disables connmand's DNS proxy.
---
 src/connman.h  |   2 +-
 src/main.c     |   5 +-
 src/resolver.c | 234 ++++++++++++++++++++++++++++++++++++++++++++++++++++++---
 3 files changed, 229 insertions(+), 12 deletions(-)

diff --git a/src/connman.h b/src/connman.h
index 21b70802..1f7afdbc 100644
--- a/src/connman.h
+++ b/src/connman.h
@@ -249,7 +249,7 @@ char **__connman_inet_get_pnp_nameservers(const char 
*pnp_file);
 
 #include <connman/resolver.h>
 
-int __connman_resolver_init(gboolean dnsproxy);
+int __connman_resolver_init(gboolean dnsproxy, gboolean resolved);
 void __connman_resolver_cleanup(void);
 void __connman_resolver_append_fallback_nameservers(void);
 int __connman_resolvfile_append(int index, const char *domain, const char 
*server);
diff --git a/src/main.c b/src/main.c
index b78a0461..2cb5c56e 100644
--- a/src/main.c
+++ b/src/main.c
@@ -511,6 +511,7 @@ static gchar *option_noplugin = NULL;
 static gchar *option_wifi = NULL;
 static gboolean option_detach = TRUE;
 static gboolean option_dnsproxy = TRUE;
+static gboolean option_resolved = FALSE;
 static gboolean option_backtrace = TRUE;
 static gboolean option_version = FALSE;
 
@@ -572,6 +573,8 @@ static GOptionEntry options[] = {
        { "nodnsproxy", 'r', G_OPTION_FLAG_REVERSE,
                                G_OPTION_ARG_NONE, &option_dnsproxy,
                                "Don't enable DNS Proxy" },
+       { "resolvedproxy", 's', 0, G_OPTION_ARG_NONE, &option_resolved,
+                               "Use systemd-resolved for DNS management" },
        { "nobacktrace", 0, G_OPTION_FLAG_REVERSE,
                                G_OPTION_ARG_NONE, &option_backtrace,
                                "Don't print out backtrace information" },
@@ -762,7 +765,7 @@ int main(int argc, char *argv[])
 
        __connman_plugin_init(option_plugin, option_noplugin);
 
-       __connman_resolver_init(option_dnsproxy);
+       __connman_resolver_init(option_dnsproxy, option_resolved);
        __connman_rtnl_start();
        __connman_dhcp_init();
        __connman_dhcpv6_init();
diff --git a/src/resolver.c b/src/resolver.c
index 75ea5ba6..62abb4a2 100644
--- a/src/resolver.c
+++ b/src/resolver.c
@@ -32,11 +32,15 @@
 #include <sys/stat.h>
 #include <resolv.h>
 #include <netdb.h>
+#include <gdbus.h>
 
+#include <connman/dbus.h>
 #include "connman.h"
 
 #define RESOLV_CONF_STATEDIR STATEDIR"/resolv.conf"
 #define RESOLV_CONF_ETC "/etc/resolv.conf"
+#define SYSTEMD_RESOLVED_SERVICE "org.freedesktop.resolve1"
+#define SYSTEMD_RESOLVED_PATH "/org/freedesktop/resolve1"
 
 #define RESOLVER_FLAG_PUBLIC (1 << 0)
 
@@ -58,6 +62,9 @@ struct entry_data {
 
 static GSList *entry_list = NULL;
 static bool dnsproxy_enabled = false;
+static DBusConnection *connection = NULL;
+static GDBusClient *client = NULL;
+static GDBusProxy *resolved_proxy = NULL;
 
 struct resolvfile_entry {
        int index;
@@ -67,6 +74,154 @@ struct resolvfile_entry {
 
 static GList *resolvfile_list = NULL;
 
+static void revertlink_append(DBusMessageIter *iter, void *user_data)
+{
+       int *index = user_data;
+
+       dbus_message_iter_append_basic(iter, DBUS_TYPE_INT32, index);
+}
+
+static int resolved_remove_all(int index)
+{
+       gboolean result;
+
+       result = g_dbus_proxy_method_call(resolved_proxy, "RevertLink",
+                       revertlink_append, NULL, &index, NULL);
+
+       if (result == FALSE)
+               return -EINVAL;
+
+       return 0;
+}
+
+static void setlinkdns_append(DBusMessageIter *iter, void *user_data)
+{
+       struct resolvfile_entry *entry = NULL;
+       int result, *index = user_data;
+       unsigned 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, index);
+
+       dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY, "(iay)",
+                       &address_array);
+
+       for (list = g_list_first(resolvfile_list); list; list = 
g_list_next(list)) {
+               entry = list->data;
+
+               DBG("setlinkdns_append: index: %d, server: %s, domain: %s",
+                               entry->index, entry->server ? entry->server : 
"NULL",
+                               entry->domain ? entry->domain : "NULL");
+
+               if (entry->index != *index || entry->server == NULL)
+                       continue;
+
+               dbus_message_iter_open_container(&address_array, 
DBUS_TYPE_STRUCT, NULL,
+                               &struct_array);
+
+               type = connman_inet_check_ipaddress(entry->server);
+
+               if (type == AF_INET) {
+                       result = inet_pton(type, entry->server, ipv4_bytes);
+                       if (!result) {
+                               DBG("Failed to parse IPv4 address: %s", 
entry->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 {
+                       result = inet_pton(type, entry->server, ipv6_bytes);
+                       if (!result) {
+                               DBG("Failed to parse IPv4 address: %s", 
entry->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 resolvfile_entry *entry;
+       int *index = user_data;
+       DBusMessageIter domain_array, struct_array;
+       gboolean only_routing = FALSE;
+       GList *list;
+
+       dbus_message_iter_append_basic(iter, DBUS_TYPE_INT32, index);
+
+       dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY, "(sb)",
+                       &domain_array);
+
+       for (list = g_list_first(resolvfile_list); list; list = 
g_list_next(list)) {
+               entry = list->data;
+
+               DBG("setlinkdomains_append: index: %d, server: %s, domain: %s",
+                               entry->index, entry->server ? entry->server : 
"NULL",
+                               entry->domain ? entry->domain : "NULL");
+
+               if (entry->index != *index || entry->domain == NULL)
+                       continue;
+
+               dbus_message_iter_open_container(&domain_array, 
DBUS_TYPE_STRUCT, NULL,
+                               &struct_array);
+
+               dbus_message_iter_append_basic(&struct_array, DBUS_TYPE_STRING,
+                               &entry->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 resolved_export(int index)
+{
+       gboolean result;
+
+       if (!resolved_proxy)
+               return -ENOENT;
+
+       /* No async error processing -- just fire and forget */
+
+       result = g_dbus_proxy_method_call(resolved_proxy, "SetLinkDNS",
+                       setlinkdns_append, NULL, &index, NULL);
+       if (result == FALSE)
+               return -EINVAL;
+
+       result = g_dbus_proxy_method_call(resolved_proxy, "SetLinkDomains",
+                       setlinkdomains_append, NULL, &index, NULL);
+       if (result == FALSE)
+               return -EINVAL;
+
+       return 0;
+}
+
 static void resolvfile_remove_entries(GList *entries)
 {
        GList *list;
@@ -188,11 +343,14 @@ int __connman_resolvfile_append(int index, const char 
*domain,
 
        resolvfile_list = g_list_append(resolvfile_list, entry);
 
+       if (resolved_proxy)
+               return resolved_export(index);
+
        return resolvfile_export();
 }
 
-int __connman_resolvfile_remove(int index, const char *domain,
-                                                       const char *server)
+static int __connman_resolvfile_remove_entry(int index, const char *domain,
+                                                       const char *server, 
gboolean remove_from_resolved)
 {
        GList *list, *matches = NULL;
 
@@ -215,9 +373,22 @@ int __connman_resolvfile_remove(int index, const char 
*domain,
 
        resolvfile_remove_entries(matches);
 
+       if (resolved_proxy) {
+               if (remove_from_resolved)
+                       return resolved_export(index);
+               else
+                       return 0; /* whole link is reset later */
+       }
+
        return resolvfile_export();
 }
 
+int __connman_resolvfile_remove(int index, const char *domain,
+                                                       const char *server)
+{
+       return __connman_resolvfile_remove_entry(index, domain, server, TRUE);
+}
+
 void __connman_resolver_append_fallback_nameservers(void)
 {
        GSList *list;
@@ -269,7 +440,7 @@ static void remove_fallback_nameservers(void)
        }
 }
 
-static void remove_entries(GSList *entries)
+static void remove_entries(GSList *entries, int index)
 {
        GSList *list;
 
@@ -282,8 +453,8 @@ static void remove_entries(GSList *entries)
                        __connman_dnsproxy_remove(entry->index, entry->domain,
                                                        entry->server);
                } else {
-                       __connman_resolvfile_remove(entry->index, entry->domain,
-                                                       entry->server);
+                       __connman_resolvfile_remove_entry(entry->index, 
entry->domain,
+                                                       entry->server, index < 
0 ? TRUE : FALSE);
                }
 
                if (entry->timeout)
@@ -295,6 +466,9 @@ static void remove_entries(GSList *entries)
 
        g_slist_free(entries);
 
+       if (resolved_proxy && index >= 0)
+               resolved_remove_all(index);
+
        __connman_resolver_append_fallback_nameservers();
 }
 
@@ -316,7 +490,7 @@ static gboolean resolver_expire_cb(gpointer user_data)
                                                        entry->server, true);
        }
 
-       remove_entries(list);
+       remove_entries(list, -1);
 
        return FALSE;
 }
@@ -538,7 +712,7 @@ int connman_resolver_remove(int index, const char *domain, 
const char *server)
        if (!matches)
                return -ENOENT;
 
-       remove_entries(matches);
+       remove_entries(matches, -1);
 
        return 0;
 }
@@ -570,7 +744,10 @@ int connman_resolver_remove_all(int index)
        if (!matches)
                return -ENOENT;
 
-       remove_entries(matches);
+       if (resolved_proxy)
+               return resolved_remove_all(index);
+
+       remove_entries(matches, index);
 
        return 0;
 }
@@ -652,12 +829,34 @@ static void free_resolvfile(gpointer data)
        g_free(entry);
 }
 
-int __connman_resolver_init(gboolean dnsproxy)
+int __connman_resolver_init(gboolean dnsproxy, gboolean resolved)
 {
        int i;
        char **ns;
 
-       DBG("dnsproxy %d", dnsproxy);
+       DBG("dnsproxy %d, resolved %d", dnsproxy, resolved);
+
+       if (resolved) {
+               connection = connman_dbus_get_connection();
+
+               if (connection) {
+                       client = g_dbus_client_new(connection,
+                                       SYSTEMD_RESOLVED_SERVICE, 
SYSTEMD_RESOLVED_PATH);
+                       if (!client)
+                               DBG("Failed to initialize proxy for 
systemd-resolved");
+                       else {
+                               resolved_proxy = g_dbus_proxy_new(client, 
SYSTEMD_RESOLVED_PATH,
+                                               
"org.freedesktop.resolve1.Manager");
+
+                               if (resolved_proxy) {
+                                       /* setup succeeded, disable dnsproxy */
+                                       dnsproxy = FALSE;
+                               }
+                               else
+                                       DBG("Failed to initialize proxy for 
systemd-resolved");
+                       }
+               }
+       }
 
        /* get autoip nameservers */
        ns = __connman_inet_get_pnp_nameservers(NULL);
@@ -706,4 +905,19 @@ void __connman_resolver_cleanup(void)
                g_slist_free(entry_list);
                entry_list = 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.5



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

Message: 4
Date: Wed, 27 Sep 2017 15:05:40 +0300
From: Ismo Puustinen <[email protected]>
To: [email protected]
Subject: [PATCH 2/2] service: add mDNS support on per-interface basis.
Message-ID: <[email protected]>

Currently mDNS support requires systemd-resolved. However, there's
nothing to prevent other mDNS backends. The mDNS state is exposed over
D-Bus for service objects.

The mDNS activation is triggered via "Method" key for mDNS.Configuration
property. Allowed string values are "enabled", "disabled", and
"resolve_only". Value "enabled" means that mDNS domains are resolved by
systemd-resolved and current host name is registered. Value "no" means
that mDNS is turned off for the service. Value "resolve_only" means that
the hostname is not registered, but mDNS resolving is supported.

You can test this by enabling mDNS support for service "service_name"
with the following command:

  busctl call net.connman /net/connman/service/service_name \
      net.connman.Service SetProperty sv mDNS.Configuration \
      a{sv} 1 Method s enabled
---
 doc/config-format.txt |   7 ++
 doc/service-api.txt   |  18 +++++
 include/service.h     |   8 +++
 src/config.c          |  15 ++++
 src/connman.h         |   3 +
 src/resolver.c        |  49 +++++++++++++
 src/service.c         | 193 ++++++++++++++++++++++++++++++++++++++++++++++++++
 7 files changed, 293 insertions(+)

diff --git a/doc/config-format.txt b/doc/config-format.txt
index ed3123aa..68e5bf2e 100644
--- a/doc/config-format.txt
+++ b/doc/config-format.txt
@@ -63,6 +63,13 @@ Allowed fields:
 - SearchDomains: Comma separated list of DNS search domains
 - Timeservers: Comma separated list of timeservers
 - Domain: Domain name to be used
+- mDNS.Method: Supported values are "enabled", "disabled", or
+  "only_resolve". The "only_resolve" value doesn't register the hostname
+  for mDNS, but allows resolving of mDNS domains. Value "enabled" means
+  support for both resolving and hostname registration, and "disabled"
+  means that mDNS support is disabled. Note that mDNS support requires
+  at the moment using systemd-resolved for DNS (use -s command line option
+  for connmand).
 
 If IPv4 address is missing then DHCP is used. If IPv6 address is missing,
 then SLAAC or DHCPv6 is used.
diff --git a/doc/service-api.txt b/doc/service-api.txt
index 6cdb0bb5..dbdada59 100644
--- a/doc/service-api.txt
+++ b/doc/service-api.txt
@@ -500,3 +500,21 @@ Properties string State [readonly]
                                Possible values are "half" and "full".
 
                                This information is not available.
+
+               dict mDNS [readonly]
+
+                       string Method [readonly]
+
+                               Possible values are "enabled", "disabled", and
+                               "only_resolve".
+
+                               If both mDNS resolving and hostname 
registration are needed,
+                               "enabled" should be selected. If only mDNS 
resolving is
+                               required, select "only_resolve". Select 
"disabled" if mDNS
+                               should be disabled for this service.
+
+               dict mDNS.Configuration [readwrite]
+
+                       Same values as mDNS property. The mDNS represents
+                       the actual system configuration while this allows
+                       user configuration.
diff --git a/include/service.h b/include/service.h
index 958e7fd1..5475b26a 100644
--- a/include/service.h
+++ b/include/service.h
@@ -89,6 +89,13 @@ enum connman_service_proxy_method {
        CONNMAN_SERVICE_PROXY_METHOD_AUTO        = 3,
 };
 
+enum connman_service_mdns_method {
+       CONNMAN_SERVICE_MDNS_METHOD_UNKNOWN      = 0,
+       CONNMAN_SERVICE_MDNS_METHOD_ENABLED      = 1,
+       CONNMAN_SERVICE_MDNS_METHOD_ONLY_RESOLVE = 2,
+       CONNMAN_SERVICE_MDNS_METHOD_DISABLED     = 3,
+};
+
 enum connman_service_connect_reason {
        CONNMAN_SERVICE_CONNECT_REASON_NONE     = 0,
        CONNMAN_SERVICE_CONNECT_REASON_AUTO     = 1,
@@ -96,6 +103,7 @@ enum connman_service_connect_reason {
        CONNMAN_SERVICE_CONNECT_REASON_SESSION  = 3,
 };
 
+
 struct connman_service;
 struct connman_network;
 
diff --git a/src/config.c b/src/config.c
index a8c3da89..5f6abb19 100644
--- a/src/config.c
+++ b/src/config.c
@@ -72,6 +72,7 @@ struct connman_config_service {
        char *ipv6_gateway;
        char *ipv6_privacy;
        char *mac;
+       char *mdns;
        char **nameservers;
        char **search_domains;
        char **timeservers;
@@ -112,6 +113,7 @@ static bool cleanup = false;
 #define SERVICE_KEY_PASSPHRASE         "Passphrase"
 #define SERVICE_KEY_SECURITY           "Security"
 #define SERVICE_KEY_HIDDEN             "Hidden"
+#define SERVICE_KEY_MDNS               "mDNS.Method"
 
 #define SERVICE_KEY_IPv4               "IPv4"
 #define SERVICE_KEY_IPv6               "IPv6"
@@ -152,6 +154,7 @@ static const char *service_possible_keys[] = {
        SERVICE_KEY_IPv6,
        SERVICE_KEY_IPv6_PRIVACY,
        SERVICE_KEY_MAC,
+       SERVICE_KEY_MDNS,
        SERVICE_KEY_NAMESERVERS,
        SERVICE_KEY_SEARCH_DOMAINS,
        SERVICE_KEY_TIMESERVERS,
@@ -254,6 +257,7 @@ free_only:
        g_free(config_service->ipv6_gateway);
        g_free(config_service->ipv6_privacy);
        g_free(config_service->mac);
+       g_free(config_service->mdns);
        g_strfreev(config_service->nameservers);
        g_strfreev(config_service->search_domains);
        g_strfreev(config_service->timeservers);
@@ -514,6 +518,13 @@ static bool load_service_generic(GKeyFile *keyfile,
                        g_strfreev(strlist);
        }
 
+       str = __connman_config_get_string(keyfile, group,
+                                       SERVICE_KEY_MDNS, NULL);
+       if (str) {
+               g_free(service->mdns);
+               service->mdns = str;
+       }
+
        return true;
 
 err:
@@ -525,6 +536,7 @@ err:
        g_free(service->ipv6_address);
        g_free(service->ipv6_gateway);
        g_free(service->mac);
+       g_free(service->mdns);
        g_free(service);
 
        return false;
@@ -1377,6 +1389,9 @@ static int try_provision_service(struct 
connman_config_service *config,
                __connman_service_set_search_domains(service,
                                                config->search_domains);
 
+       if (config->mdns)
+               __connman_service_set_mdns(service, config->mdns);
+
        if (config->timeservers)
                __connman_service_set_timeservers(service,
                                                config->timeservers);
diff --git a/src/connman.h b/src/connman.h
index 1f7afdbc..bebe2420 100644
--- a/src/connman.h
+++ b/src/connman.h
@@ -255,6 +255,7 @@ void __connman_resolver_append_fallback_nameservers(void);
 int __connman_resolvfile_append(int index, const char *domain, const char 
*server);
 int __connman_resolvfile_remove(int index, const char *domain, const char 
*server);
 int __connman_resolver_redo_servers(int index);
+int __connman_resolver_set_mdns(int index, const char *mdns);
 
 GKeyFile *__connman_storage_open_global(void);
 GKeyFile *__connman_storage_load_global(void);
@@ -704,6 +705,8 @@ int __connman_service_set_ignore(struct connman_service 
*service,
                                                bool ignore);
 void __connman_service_set_search_domains(struct connman_service *service,
                                        char **domains);
+int __connman_service_set_mdns(struct connman_service *service,
+                                       const char *mdns);
 
 void __connman_service_set_string(struct connman_service *service,
                                        const char *key, const char *value);
diff --git a/src/resolver.c b/src/resolver.c
index 62abb4a2..f6f7fab6 100644
--- a/src/resolver.c
+++ b/src/resolver.c
@@ -72,6 +72,11 @@ struct resolvfile_entry {
        char *server;
 };
 
+struct mdns_data {
+       int index;
+       const char *mdns;
+};
+
 static GList *resolvfile_list = NULL;
 
 static void revertlink_append(DBusMessageIter *iter, void *user_data)
@@ -85,6 +90,10 @@ static int resolved_remove_all(int index)
 {
        gboolean result;
 
+    /* FIXME: Reverting the link also removes the current mDNS settings.
+     * However, it's not clear whether the purpose is to disable DNS
+     * resolution fully when connman_resolver_remove_all is called. */
+
        result = g_dbus_proxy_method_call(resolved_proxy, "RevertLink",
                        revertlink_append, NULL, &index, NULL);
 
@@ -222,6 +231,46 @@ static int resolved_export(int index)
        return 0;
 }
 
+static void setlinkmulticastdns_append(DBusMessageIter *iter, void *user_data)
+{
+       struct mdns_data *data = user_data;
+       char *val = NULL;
+
+       if (strcmp(data->mdns, "enabled") == 0)
+               val = "yes";
+       else if (strcmp(data->mdns, "disabled") == 0)
+               val = "no";
+       else if (strcmp(data->mdns, "only_resolve") == 0)
+               val = "resolve";
+       if (val == NULL)
+               val = ""; /* use system default */
+
+       DBG("SetLinkMulticastDNS: %d/%s", data->index, val);
+
+       dbus_message_iter_append_basic(iter, DBUS_TYPE_INT32, &data->index);
+       dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &val);
+}
+
+int __connman_resolver_set_mdns(int index, const char *mdns)
+{
+       gboolean result;
+       struct mdns_data data = { index, mdns };
+
+       /* Currently supported only for systemd-resolved */
+       if (!resolved_proxy)
+               return -ENOENT;
+
+       if (mdns == NULL || index < 0)
+               return -EINVAL;
+
+       result = g_dbus_proxy_method_call(resolved_proxy, "SetLinkMulticastDNS",
+                       setlinkmulticastdns_append, NULL, &data, NULL);
+       if (result == FALSE)
+               return -EINVAL;
+
+       return 0;
+}
+
 static void resolvfile_remove_entries(GList *entries)
 {
        GList *list;
diff --git a/src/service.c b/src/service.c
index 02cd51f2..4e8cbed4 100644
--- a/src/service.c
+++ b/src/service.c
@@ -94,6 +94,8 @@ struct connman_service {
        char **nameservers_auto;
        int nameservers_timeout;
        char **domains;
+       enum connman_service_mdns_method mdns;
+       enum connman_service_mdns_method mdns_config;
        char *hostname;
        char *domainname;
        char **timeservers;
@@ -355,6 +357,34 @@ static enum connman_service_proxy_method 
string2proxymethod(const char *method)
                return CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN;
 }
 
+static const char * mdnsmethod2string(enum connman_service_mdns_method method)
+{
+       switch (method) {
+       case CONNMAN_SERVICE_MDNS_METHOD_ENABLED:
+               return "enabled";
+       case CONNMAN_SERVICE_MDNS_METHOD_DISABLED:
+               return "disabled";
+       case CONNMAN_SERVICE_MDNS_METHOD_ONLY_RESOLVE:
+               return "only_resolve";
+       case CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN:
+               return "unknown";
+       }
+
+       return NULL;
+}
+
+static enum connman_service_mdns_method string2mdnsmethod(const char *method)
+{
+       if (g_strcmp0(method, "enabled") == 0)
+               return CONNMAN_SERVICE_MDNS_METHOD_ENABLED;
+       else if (g_strcmp0(method, "disabled") == 0)
+               return CONNMAN_SERVICE_MDNS_METHOD_DISABLED;
+       else if (g_strcmp0(method, "only_resolve") == 0)
+               return CONNMAN_SERVICE_MDNS_METHOD_ONLY_RESOLVE;
+       else
+               return CONNMAN_SERVICE_MDNS_METHOD_UNKNOWN;
+}
+
 static void set_split_routing(struct connman_service *service, bool value)
 {
        if (service->type != CONNMAN_SERVICE_TYPE_VPN)
@@ -594,6 +624,13 @@ static int service_load(struct connman_service *service)
                service->pac = str;
        }
 
+       str = g_key_file_get_string(keyfile,
+                               service->identifier, "mDNS.Method", NULL);
+       if (str)
+               service->mdns_config = string2mdnsmethod(str);
+
+       g_free(str);
+
        service->hidden_service = g_key_file_get_boolean(keyfile,
                                        service->identifier, "Hidden", NULL);
 
@@ -774,6 +811,13 @@ static int service_save(struct connman_service *service)
                g_key_file_remove_key(keyfile, service->identifier,
                                                        "Proxy.URL", NULL);
 
+       if (service->mdns_config != CONNMAN_SERVICE_MDNS_METHOD_UNKNOWN)
+               g_key_file_set_string(keyfile, service->identifier,
+                                               "mDNS.Method", 
mdnsmethod2string(service->mdns_config));
+       else
+               g_key_file_remove_key(keyfile, service->identifier,
+                                               "mDNS.Method", NULL);
+
        if (service->hidden_service)
                g_key_file_set_boolean(keyfile, service->identifier, "Hidden",
                                                                        TRUE);
@@ -1942,6 +1986,28 @@ static void append_proxyconfig(DBusMessageIter *iter, 
void *user_data)
                                DBUS_TYPE_STRING, &method);
 }
 
+static void append_mdnsconfig(DBusMessageIter *iter, void *user_data)
+{
+       struct connman_service *service = user_data;
+       const char *method;
+
+       method = mdnsmethod2string(service->mdns_config);
+
+       connman_dbus_dict_append_basic(iter, "Method",
+                               DBUS_TYPE_STRING, &method);
+}
+
+static void append_mdns(DBusMessageIter *iter, void *user_data)
+{
+       struct connman_service *service = user_data;
+       const char *method;
+
+       method = mdnsmethod2string(service->mdns);
+
+       connman_dbus_dict_append_basic(iter, "Method",
+                               DBUS_TYPE_STRING, &method);
+}
+
 static void append_provider(DBusMessageIter *iter, void *user_data)
 {
        struct connman_service *service = user_data;
@@ -2075,6 +2141,47 @@ static void proxy_configuration_changed(struct 
connman_service *service)
        proxy_changed(service);
 }
 
+static void mdns_changed(struct connman_service *service)
+{
+       if (!allow_property_changed(service))
+               return;
+
+       connman_dbus_property_changed_dict(service->path,
+                                       CONNMAN_SERVICE_INTERFACE, "mDNS",
+                                                       append_mdns, service);
+}
+
+static void mdns_configuration_changed(struct connman_service *service)
+{
+       if (!allow_property_changed(service))
+               return;
+
+       connman_dbus_property_changed_dict(service->path,
+                       CONNMAN_SERVICE_INTERFACE, "mDNS.Configuration",
+                                               append_mdnsconfig, service);
+}
+
+static int set_mdns(struct connman_service *service,
+                       enum connman_service_mdns_method method)
+{
+       int result;
+
+       if (method == CONNMAN_SERVICE_MDNS_METHOD_UNKNOWN)
+               return -EINVAL;
+
+       result = 
__connman_resolver_set_mdns(__connman_service_get_index(service),
+                       mdnsmethod2string(method));
+
+       if (result == 0) {
+               if (service->mdns != method) {
+                       service->mdns = method;
+                       mdns_changed(service);
+               }
+       }
+
+       return result;
+}
+
 static void timeservers_configuration_changed(struct connman_service *service)
 {
        if (!allow_property_changed(service))
@@ -2452,6 +2559,11 @@ static void append_properties(DBusMessageIter *dict, 
dbus_bool_t limited,
        connman_dbus_dict_append_dict(dict, "Proxy.Configuration",
                                                append_proxyconfig, service);
 
+       connman_dbus_dict_append_dict(dict, "mDNS", append_mdns, service);
+
+       connman_dbus_dict_append_dict(dict, "mDNS.Configuration",
+                                               append_mdnsconfig, service);
+
        connman_dbus_dict_append_dict(dict, "Provider",
                                                append_provider, service);
 }
@@ -3257,6 +3369,59 @@ error:
        return -EINVAL;
 }
 
+static int update_mdns_configuration(struct connman_service *service,
+                               DBusMessageIter *array)
+{
+       DBusMessageIter dict;
+       enum connman_service_mdns_method method;
+
+       method = CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN;
+
+       dbus_message_iter_recurse(array, &dict);
+
+       while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
+               DBusMessageIter entry, variant;
+               const char *key;
+               int type;
+
+               dbus_message_iter_recurse(&dict, &entry);
+
+               if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
+                       goto error;
+
+               dbus_message_iter_get_basic(&entry, &key);
+               dbus_message_iter_next(&entry);
+
+               if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT)
+                       goto error;
+
+               dbus_message_iter_recurse(&entry, &variant);
+
+               type = dbus_message_iter_get_arg_type(&variant);
+
+               if (g_str_equal(key, "Method")) {
+                       const char *val;
+
+                       if (type != DBUS_TYPE_STRING)
+                               goto error;
+
+                       dbus_message_iter_get_basic(&variant, &val);
+                       method = string2mdnsmethod(val);
+
+                       if (method == CONNMAN_SERVICE_MDNS_METHOD_UNKNOWN)
+                               goto error;
+               }
+
+               dbus_message_iter_next(&dict);
+       }
+
+       service->mdns_config = method;
+       return 0;
+
+error:
+       return -EINVAL;
+}
+
 int __connman_service_reset_ipconfig(struct connman_service *service,
                enum connman_ipconfig_type type, DBusMessageIter *array,
                enum connman_service_state *new_state)
@@ -3571,6 +3736,25 @@ static DBusMessage *set_property(DBusConnection *conn,
                __connman_notifier_proxy_changed(service);
 
                service_save(service);
+       } else if (g_str_equal(name, "mDNS.Configuration")) {
+               int err;
+
+               if (service->immutable)
+                       return __connman_error_not_supported(msg);
+
+               if (type != DBUS_TYPE_ARRAY)
+                       return __connman_error_invalid_arguments(msg);
+
+               err = update_mdns_configuration(service, &value);
+
+               if (err < 0)
+                       return __connman_error_failed(msg, -err);
+
+               mdns_configuration_changed(service);
+
+               set_mdns(service, service->mdns_config);
+
+               service_save(service);
        } else if (g_str_equal(name, "IPv4.Configuration") ||
                        g_str_equal(name, "IPv6.Configuration")) {
 
@@ -5273,6 +5457,14 @@ void __connman_service_set_search_domains(struct 
connman_service *service,
        searchdomain_add_all(service);
 }
 
+int __connman_service_set_mdns(struct connman_service *service,
+                       const char *mdns)
+{
+       /* double conversion for validating input */
+
+       return set_mdns(service, string2mdnsmethod(mdns));
+}
+
 static void report_error_cb(void *user_context, bool retry,
                                                        void *user_data)
 {
@@ -6001,6 +6193,7 @@ int __connman_service_ipconfig_indicate_state(struct 
connman_service *service,
                                "Default service remains in READY state.");
                if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
                        service_rp_filter(service, true);
+               set_mdns(service, service->mdns_config);
                break;
        case CONNMAN_SERVICE_STATE_ONLINE:
                break;
-- 
2.13.5



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

Subject: Digest Footer

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


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

End of connman Digest, Vol 23, Issue 18
***************************************

Reply via email to