[systemd-commits] 4 commits - src/resolve

Lennart Poettering lennart at kemper.freedesktop.org
Thu Jul 31 10:56:36 PDT 2014


 src/resolve/resolved-bus.c        |    7 +-
 src/resolve/resolved-dns-domain.c |   18 ++---
 src/resolve/resolved-dns-packet.c |    2 
 src/resolve/resolved-manager.c    |  128 +++++++++++++++++++++++++++++++++-----
 src/resolve/resolved.h            |    5 +
 5 files changed, 136 insertions(+), 24 deletions(-)

New commits:
commit eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Jul 31 19:54:43 2014 +0200

    hostnamed: watch system hostname changes and update LLMNR RRs accordingly

diff --git a/src/resolve/resolved-manager.c b/src/resolve/resolved-manager.c
index 72034c1..6987c29 100644
--- a/src/resolve/resolved-manager.c
+++ b/src/resolve/resolved-manager.c
@@ -34,6 +34,8 @@
 #include "socket-util.h"
 #include "af-list.h"
 #include "resolved.h"
+#include "utf8.h"
+#include "resolved-dns-domain.h"
 
 #define SEND_TIMEOUT_USEC (200 * USEC_PER_MSEC)
 
@@ -384,6 +386,92 @@ int manager_parse_config_file(Manager *m) {
                             false, false, true, m);
 }
 
+static int determine_hostname(char **ret) {
+        _cleanup_free_ char *h = NULL, *n = NULL;
+        int r;
+
+        assert(ret);
+
+        h = gethostname_malloc();
+        if (!h)
+                return log_oom();
+
+        if (!utf8_is_valid(h)) {
+                log_error("System hostname is not UTF-8 clean.");
+                return -EINVAL;
+        }
+
+        r = dns_name_normalize(h, &n);
+        if (r < 0) {
+                log_error("System hostname '%s' cannot be normalized.", h);
+                return r;
+        }
+
+        *ret = n;
+        n = NULL;
+
+        return 0;
+}
+
+static int on_hostname_change(sd_event_source *es, int fd, uint32_t revents, void *userdata) {
+        _cleanup_free_ char *h = NULL;
+        Manager *m = userdata;
+        int r;
+
+        assert(m);
+
+        r = determine_hostname(&h);
+        if (r < 0)
+                return 0; /* ignore invalid hostnames */
+
+        if (streq(h, m->hostname))
+                return 0;
+
+        log_info("System hostname changed to '%s'.", h);
+        free(m->hostname);
+        m->hostname = h;
+        h = NULL;
+
+        manager_refresh_rrs(m);
+
+        return 0;
+}
+
+static int manager_watch_hostname(Manager *m) {
+        _cleanup_free_ char *h = NULL;
+        int r;
+
+        assert(m);
+
+        m->hostname_fd = open("/proc/sys/kernel/hostname", O_RDONLY|O_CLOEXEC|O_NDELAY|O_NOCTTY);
+        if (m->hostname_fd < 0) {
+                log_warning("Failed to watch hostname: %m");
+                return 0;
+        }
+
+        r = sd_event_add_io(m->event, &m->hostname_event_source, m->hostname_fd, 0, on_hostname_change, m);
+        if (r < 0) {
+                if (r == -EPERM)
+                        /* kernels prior to 3.2 don't support polling this file. Ignore the failure. */
+                        m->hostname_fd = safe_close(m->hostname_fd);
+                else {
+                        log_error("Failed to add hostname event source: %s", strerror(-r));
+                        return r;
+                }
+        }
+
+        r = determine_hostname(&m->hostname);
+        if (r < 0) {
+                log_info("Defaulting to hostname 'linux'.");
+                m->hostname = strdup("linux");
+                if (!m->hostname)
+                        return log_oom();
+        } else
+                log_info("Using system hostname '%s'.", m->hostname);
+
+        return 0;
+}
+
 int manager_new(Manager **ret) {
         _cleanup_(manager_freep) Manager *m = NULL;
         int r;
@@ -397,6 +485,7 @@ int manager_new(Manager **ret) {
         m->dns_ipv4_fd = m->dns_ipv6_fd = -1;
         m->llmnr_ipv4_udp_fd = m->llmnr_ipv6_udp_fd = -1;
         m->llmnr_ipv4_tcp_fd = m->llmnr_ipv6_tcp_fd = -1;
+        m->hostname_fd = -1;
 
         m->use_llmnr = true;
 
@@ -404,10 +493,6 @@ int manager_new(Manager **ret) {
         if (r < 0)
                 return r;
 
-        m->hostname = gethostname_malloc();
-        if (!m->hostname)
-                return -ENOMEM;
-
         r = sd_event_default(&m->event);
         if (r < 0)
                 return r;
@@ -417,6 +502,10 @@ int manager_new(Manager **ret) {
 
         sd_event_set_watchdog(m->event, true);
 
+        r = manager_watch_hostname(m);
+        if (r < 0)
+                return r;
+
         r = dns_scope_new(m, &m->unicast_scope, NULL, DNS_PROTOCOL_DNS, AF_UNSPEC);
         if (r < 0)
                 return r;
@@ -497,7 +586,11 @@ Manager *manager_free(Manager *m) {
 
         dns_resource_key_unref(m->host_ipv4_key);
         dns_resource_key_unref(m->host_ipv6_key);
+
+        safe_close(m->hostname_fd);
+        sd_event_source_unref(m->hostname_event_source);
         free(m->hostname);
+
         free(m);
 
         return NULL;
@@ -1408,12 +1501,25 @@ int manager_find_ifindex(Manager *m, int family, const union in_addr_union *in_a
         return 0;
 }
 
+void manager_refresh_rrs(Manager *m) {
+        Iterator i;
+        Link *l;
+
+        assert(m);
+
+        m->host_ipv4_key = dns_resource_key_unref(m->host_ipv4_key);
+        m->host_ipv6_key = dns_resource_key_unref(m->host_ipv6_key);
+
+        HASHMAP_FOREACH(l, m->links, i) {
+                link_add_rrs(l, true);
+                link_add_rrs(l, false);
+        }
+}
+
 int manager_next_hostname(Manager *m) {
         const char *p;
-        Iterator i;
         uint64_t u;
         char *h;
-        Link *l;
 
         assert(m);
 
@@ -1435,18 +1541,12 @@ int manager_next_hostname(Manager *m) {
         if (asprintf(&h, "%.*s%" PRIu64, (int) (p - m->hostname), m->hostname, u) < 0)
                 return -ENOMEM;
 
-        log_info("Hostname conflict, changing local hostname from '%s' to '%s'.", m->hostname, h);
+        log_info("Hostname conflict, changing published hostname from '%s' to '%s'.", m->hostname, h);
 
         free(m->hostname);
         m->hostname = h;
 
-        m->host_ipv4_key = dns_resource_key_unref(m->host_ipv4_key);
-        m->host_ipv6_key = dns_resource_key_unref(m->host_ipv6_key);
-
-        HASHMAP_FOREACH(l, m->links, i) {
-                link_add_rrs(l, true);
-                link_add_rrs(l, false);
-        }
+        manager_refresh_rrs(m);
 
         return 0;
 }
diff --git a/src/resolve/resolved.h b/src/resolve/resolved.h
index 0756055..34eb7b5 100644
--- a/src/resolve/resolved.h
+++ b/src/resolve/resolved.h
@@ -90,6 +90,10 @@ struct Manager {
         char *hostname;
         DnsResourceKey *host_ipv4_key;
         DnsResourceKey *host_ipv6_key;
+
+        /* Watch the system hostname */
+        int hostname_fd;
+        sd_event_source *hostname_event_source;
 };
 
 /* Manager */
@@ -120,6 +124,7 @@ int manager_ifindex_is_loopback(Manager *m, int ifindex);
 int manager_find_ifindex(Manager *m, int family, const union in_addr_union *in_addr);
 LinkAddress* manager_find_address(Manager *m, int family, const union in_addr_union *in_addr);
 
+void manager_refresh_rrs(Manager *m);
 int manager_next_hostname(Manager *m);
 
 int manager_our_packet(Manager *m, DnsPacket *p);

commit 85818582574bcd1c3707c2a4609c9e283e47493f
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Jul 31 19:54:24 2014 +0200

    resolved: fix deserialization of UTF8 host names

diff --git a/src/resolve/resolved-dns-packet.c b/src/resolve/resolved-dns-packet.c
index 3eda803..7793a01 100644
--- a/src/resolve/resolved-dns-packet.c
+++ b/src/resolve/resolved-dns-packet.c
@@ -840,7 +840,7 @@ int dns_packet_read_name(DnsPacket *p, char **_ret, size_t *start) {
                         else
                                 first = false;
 
-                        memcpy(ret + n, t, c);
+                        memcpy(ret + n, t, r);
                         n += r;
                         continue;
                 } else if ((c & 0xc0) == 0xc0) {

commit 7b9f7afcc04e80b77a2567b0750aa2cd03c1a1cd
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Jul 31 19:53:59 2014 +0200

    resolved: accept UTF-8 hostnames from bus clients

diff --git a/src/resolve/resolved-bus.c b/src/resolve/resolved-bus.c
index bfb060d..6bd2b53 100644
--- a/src/resolve/resolved-bus.c
+++ b/src/resolve/resolved-bus.c
@@ -275,7 +275,8 @@ static int bus_method_resolve_hostname(sd_bus *bus, sd_bus_message *message, voi
         if (!IN_SET(family, AF_INET, AF_INET6, AF_UNSPEC))
                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown address family %i", family);
 
-        if (!hostname_is_valid(hostname))
+        r = dns_name_normalize(hostname, NULL);
+        if (r < 0)
                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid hostname '%s'", hostname);
 
         question = dns_question_new(family == AF_UNSPEC ? 2 : 1);
@@ -566,6 +567,10 @@ static int bus_method_resolve_record(sd_bus *bus, sd_bus_message *message, void
         if (r < 0)
                 return r;
 
+        r = dns_name_normalize(name, NULL);
+        if (r < 0)
+                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid name '%s'", name);
+
         question = dns_question_new(1);
         if (!question)
                 return -ENOMEM;
diff --git a/src/resolve/resolved-dns-domain.c b/src/resolve/resolved-dns-domain.c
index c2a4359..1bb011d 100644
--- a/src/resolve/resolved-dns-domain.c
+++ b/src/resolve/resolved-dns-domain.c
@@ -172,7 +172,6 @@ int dns_name_normalize(const char *s, char **_ret) {
         int r;
 
         assert(s);
-        assert(_ret);
 
         for (;;) {
                 _cleanup_free_ char *t = NULL;
@@ -210,8 +209,11 @@ int dns_name_normalize(const char *s, char **_ret) {
                 return -ENOMEM;
 
         ret[n] = 0;
-        *_ret = ret;
-        ret = NULL;
+
+        if (_ret) {
+                *_ret = ret;
+                ret = NULL;
+        }
 
         return 0;
 }

commit 07bed172edc819cf85b72d5c67613511cbde5453
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Jul 31 19:51:11 2014 +0200

    resolved: various fixes regarding encoding of UTF8 characters in DNS RRs

diff --git a/src/resolve/resolved-dns-domain.c b/src/resolve/resolved-dns-domain.c
index f3e7df7..c2a4359 100644
--- a/src/resolve/resolved-dns-domain.c
+++ b/src/resolve/resolved-dns-domain.c
@@ -88,7 +88,7 @@ int dns_label_unescape(const char **name, char *dest, size_t sz) {
                         } else
                                 return -EINVAL;
 
-                } else if (*n >= ' ' && *n != 127) {
+                } else if ((uint8_t) *n >= (uint8_t) ' ' && *n != 127) {
 
                         /* Normal character */
                         *(d++) = *(n++);
@@ -141,13 +141,13 @@ int dns_label_escape(const char *p, size_t l, char **ret) {
 
                         /* Proper character */
                         *(q++) = *p;
-                } else if (*p >= ' ' && *p != 127) {
+                } else if ((uint8_t) *p >= (uint8_t) ' ' && *p != 127) {
 
                         /* Everything else */
                         *(q++) = '\\';
-                        *(q++) = '0' + (char) ((unsigned) *p / 100);
-                        *(q++) = '0' + (char) (((unsigned) *p / 10) % 10);
-                        *(q++) = '0' + (char) ((unsigned) *p % 10);
+                        *(q++) = '0' + (char) ((uint8_t) *p / 100);
+                        *(q++) = '0' + (char) (((uint8_t) *p / 10) % 10);
+                        *(q++) = '0' + (char) ((uint8_t) *p % 10);
 
                 } else
                         return -EINVAL;



More information about the systemd-commits mailing list