[systemd-commits] 5 commits - Makefile.am TODO configure.ac src/resolve

Lennart Poettering lennart at kemper.freedesktop.org
Thu Jul 31 15:58:27 PDT 2014


 Makefile.am                            |    9 +-
 TODO                                   |    3 
 configure.ac                           |   16 ++++
 src/resolve/resolved-dns-cache.c       |    6 +
 src/resolve/resolved-dns-domain.c      |  132 ++++++++++++++++++++++++++++++++-
 src/resolve/resolved-dns-domain.h      |    3 
 src/resolve/resolved-dns-packet.c      |   12 +++
 src/resolve/resolved-dns-query.c       |    7 +
 src/resolve/resolved-dns-stream.c      |    7 +
 src/resolve/resolved-dns-transaction.c |    7 +
 10 files changed, 188 insertions(+), 14 deletions(-)

New commits:
commit 95dd6257a6befedb5b811f16d2cc4a0d8f147751
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Aug 1 00:57:19 2014 +0200

    resolved: don't bother caching negative RRs when the SOA TTL is 0 anyway

diff --git a/src/resolve/resolved-dns-cache.c b/src/resolve/resolved-dns-cache.c
index f7091f0..40fb6c3 100644
--- a/src/resolve/resolved-dns-cache.c
+++ b/src/resolve/resolved-dns-cache.c
@@ -320,6 +320,8 @@ static int dns_cache_put_negative(DnsCache *c, DnsResourceKey *key, int rcode, u
                 return 0;
         if (key->type == DNS_TYPE_ANY)
                 return 0;
+        if (soa_ttl <= 0)
+                return 0;
 
         if (!IN_SET(rcode, DNS_RCODE_SUCCESS, DNS_RCODE_NXDOMAIN))
                 return 0;

commit 7be6885326d8316850062a5002c801102496d3bc
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Aug 1 00:57:12 2014 +0200

    update TODO

diff --git a/TODO b/TODO
index fa0282b..c203a63 100644
--- a/TODO
+++ b/TODO
@@ -29,7 +29,6 @@ Features:
     releases (probably not even a directory in /run for it)
 
 * resolved:
-  - IDN (?)
   - DNSSEC
   - LLMNR:
         - do not fail daemon startup if socket is already busy (container)
@@ -39,12 +38,10 @@ Features:
         - collect multiple responses
         - jitter interval support
         - watch udev initialization state
-        - watch local host name
         - reprobe after suspend
   - mDNS/DNS-SD
         - avahi compat
   - DNS-SD service registration from socket units
-  - port sd-resolve to direct bus calls
   - nss module: fallback to glibc dns modules if resolved cannot be contacted
   - edns0
   - dname

commit 9a015429b3bbfe1c2802570c1621e73d6cb57ac3
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Aug 1 00:55:51 2014 +0200

    resolved: use CLOCK_BOOTTIME instead of CLOCK_MONOTONIC when aging caches and timeing out transactions
    
    That way the cache doens't get confused when the system is suspended.

diff --git a/src/resolve/resolved-dns-cache.c b/src/resolve/resolved-dns-cache.c
index 7359dfa..f7091f0 100644
--- a/src/resolve/resolved-dns-cache.c
+++ b/src/resolve/resolved-dns-cache.c
@@ -153,7 +153,7 @@ void dns_cache_prune(DnsCache *c) {
                         break;
 
                 if (t <= 0)
-                        t = now(CLOCK_MONOTONIC);
+                        t = now(CLOCK_BOOTTIME);
 
                 if (i->until > t)
                         break;
@@ -376,7 +376,7 @@ int dns_cache_put(DnsCache *c, DnsQuestion *q, int rcode, DnsAnswer *answer, uns
         dns_cache_make_space(c, answer->n_rrs + q->n_keys);
 
         if (timestamp <= 0)
-                timestamp = now(CLOCK_MONOTONIC);
+                timestamp = now(CLOCK_BOOTTIME);
 
         /* Second, add in positive entries for all contained RRs */
         for (i = 0; i < MIN(max_rrs, answer->n_rrs); i++) {
diff --git a/src/resolve/resolved-dns-query.c b/src/resolve/resolved-dns-query.c
index 57f7467..36cfc02 100644
--- a/src/resolve/resolved-dns-query.c
+++ b/src/resolve/resolved-dns-query.c
@@ -278,7 +278,12 @@ int dns_query_go(DnsQuery *q) {
         q->answer_ifindex = 0;
         q->answer_rcode = 0;
 
-        r = sd_event_add_time(q->manager->event, &q->timeout_event_source, CLOCK_MONOTONIC, now(CLOCK_MONOTONIC) + QUERY_TIMEOUT_USEC, 0, on_query_timeout, q);
+        r = sd_event_add_time(
+                        q->manager->event,
+                        &q->timeout_event_source,
+                        clock_boottime_or_monotonic(),
+                        now(clock_boottime_or_monotonic()) + QUERY_TIMEOUT_USEC, 0,
+                        on_query_timeout, q);
         if (r < 0)
                 goto fail;
 
diff --git a/src/resolve/resolved-dns-stream.c b/src/resolve/resolved-dns-stream.c
index 47130c4..9a0d59d 100644
--- a/src/resolve/resolved-dns-stream.c
+++ b/src/resolve/resolved-dns-stream.c
@@ -368,7 +368,12 @@ int dns_stream_new(Manager *m, DnsStream **ret, DnsProtocol protocol, int fd) {
         if (r < 0)
                 return r;
 
-        r = sd_event_add_time(m->event, &s->timeout_event_source, CLOCK_MONOTONIC, now(CLOCK_MONOTONIC) + DNS_STREAM_TIMEOUT_USEC, 0, on_stream_timeout, s);
+        r = sd_event_add_time(
+                        m->event,
+                        &s->timeout_event_source,
+                        clock_boottime_or_monotonic(),
+                        now(clock_boottime_or_monotonic()) + DNS_STREAM_TIMEOUT_USEC, 0,
+                        on_stream_timeout, s);
         if (r < 0)
                 return r;
 
diff --git a/src/resolve/resolved-dns-transaction.c b/src/resolve/resolved-dns-transaction.c
index 92f7e4c..faa1de9 100644
--- a/src/resolve/resolved-dns-transaction.c
+++ b/src/resolve/resolved-dns-transaction.c
@@ -515,7 +515,12 @@ int dns_transaction_go(DnsTransaction *t) {
                 return dns_transaction_go(t);
         }
 
-        r = sd_event_add_time(t->scope->manager->event, &t->timeout_event_source, CLOCK_MONOTONIC, now(CLOCK_MONOTONIC) + TRANSACTION_TIMEOUT_USEC(t->scope->protocol), 0, on_transaction_timeout, t);
+        r = sd_event_add_time(
+                        t->scope->manager->event,
+                        &t->timeout_event_source,
+                        clock_boottime_or_monotonic(),
+                        now(clock_boottime_or_monotonic()) + TRANSACTION_TIMEOUT_USEC(t->scope->protocol), 0,
+                        on_transaction_timeout, t);
         if (r < 0)
                 return r;
 

commit 7da40fc10879d122cc6ebfba9609b56212a0ef77
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Aug 1 00:39:59 2014 +0200

    resolved: fix negative caching of IDNA domains

diff --git a/src/resolve/resolved-dns-domain.c b/src/resolve/resolved-dns-domain.c
index 80a2b3c..6152047 100644
--- a/src/resolve/resolved-dns-domain.c
+++ b/src/resolve/resolved-dns-domain.c
@@ -324,7 +324,7 @@ unsigned long dns_name_hash_func(const void *s, const uint8_t hash_key[HASH_KEY_
 
                 k = dns_label_undo_idna(label, r, label, sizeof(label));
                 if (k < 0)
-                        return k;
+                        break;
                 if (k > 0)
                         r = k;
 
@@ -436,7 +436,7 @@ int dns_name_endswith(const char *name, const char *suffix) {
                 q = dns_label_unescape(&s, ls, sizeof(ls));
                 if (r < 0)
                         return r;
-                w = dns_label_undo_idna(ls, r, ls, sizeof(ls));
+                w = dns_label_undo_idna(ls, q, ls, sizeof(ls));
                 if (w < 0)
                         return w;
                 if (w > 0)

commit bdf10b5b4d9e7abdc08bdca4b073d021b0043d1f
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Jul 31 23:43:10 2014 +0200

    resolved: handle IDNA domains
    
    Make sure we format UTF-8 labels as IDNA when writing them to DNS
    packets, and as native UTF-8 when writing them to mDNS or LLMNR packets.
    
    When comparing or processing labels always consider native UTF-8 and
    IDNA formats equivalent.

diff --git a/Makefile.am b/Makefile.am
index 2d7f76d..364e622 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -4778,7 +4778,8 @@ systemd_resolved_LDADD = \
 	libsystemd-label.la \
 	libsystemd-internal.la \
 	libsystemd-shared.la \
-	-lm
+	-lm \
+	$(LIBIDN_LIBS)
 
 rootlibexec_PROGRAMS += \
 	systemd-resolved
@@ -4829,7 +4830,8 @@ test_dns_domain_LDADD = \
 	libsystemd-network.la \
 	libsystemd-label.la \
 	libsystemd-internal.la \
-	libsystemd-shared.la
+	libsystemd-shared.la \
+	$(LIBIDN_LIBS)
 
 libnss_resolve_la_SOURCES = \
 	src/nss-resolve/nss-resolve.sym \
@@ -4867,7 +4869,8 @@ systemd_resolve_host_SOURCES = \
 systemd_resolve_host_LDADD = \
 	libsystemd-internal.la \
 	libsystemd-shared.la \
-	-lm
+	-lm \
+	$(LIBIDN_LIBS)
 
 rootlibexec_PROGRAMS += \
 	systemd-resolve-host
diff --git a/configure.ac b/configure.ac
index 0802cfc..6d5536b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -811,6 +811,21 @@ fi
 AM_CONDITIONAL(HAVE_LIBCURL, [test "$have_libcurl" = "yes"])
 
 # ------------------------------------------------------------------------------
+have_libidn=no
+AC_ARG_ENABLE(libidn, AS_HELP_STRING([--disable-libidn], [Disable optional LIBIDN support]))
+if test "x$enable_libidn" != "xno"; then
+        PKG_CHECK_MODULES(LIBIDN, [libidn],
+               [AC_DEFINE(HAVE_LIBIDN, 1, [Define if libidn is available])
+                have_libidn=yes
+                M4_DEFINES="$M4_DEFINES -DHAVE_LIBIDN"],
+               [have_libidn=no])
+        if test "x$have_libidn" = "xno" -a "x$enable_libidn" = "xyes"; then
+                AC_MSG_ERROR([*** libidn support requested but libraries not found])
+        fi
+fi
+AM_CONDITIONAL(HAVE_LIBIDN, [test "$have_libidn" = "yes"])
+
+# ------------------------------------------------------------------------------
 have_binfmt=no
 AC_ARG_ENABLE(binfmt, AS_HELP_STRING([--disable-binfmt], [disable binfmt tool]))
 if test "x$enable_binfmt" != "xno"; then
@@ -1326,6 +1341,7 @@ AC_MSG_RESULT([
         CHKCONFIG:               ${have_chkconfig}
         GNUTLS:                  ${have_gnutls}
         libcurl:                 ${have_libcurl}
+        libidn:                  ${have_libidn}
         ELFUTILS:                ${have_elfutils}
         binfmt:                  ${have_binfmt}
         vconsole:                ${have_vconsole}
diff --git a/src/resolve/resolved-dns-domain.c b/src/resolve/resolved-dns-domain.c
index 1bb011d..80a2b3c 100644
--- a/src/resolve/resolved-dns-domain.c
+++ b/src/resolve/resolved-dns-domain.c
@@ -19,6 +19,11 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
  ***/
 
+#ifdef HAVE_LIBIDN
+#include <idna.h>
+#include <stringprep.h>
+#endif
+
 #include "resolved-dns-domain.h"
 
 int dns_label_unescape(const char **name, char *dest, size_t sz) {
@@ -164,6 +169,83 @@ int dns_label_escape(const char *p, size_t l, char **ret) {
         return r;
 }
 
+int dns_label_apply_idna(const char *encoded, size_t encoded_size, char *decoded, size_t decoded_max) {
+#ifdef HAVE_LIBIDN
+        _cleanup_free_ uint32_t *input = NULL;
+        size_t input_size;
+        const char *p;
+        bool contains_8bit = false;
+
+        assert(encoded);
+        assert(decoded);
+        assert(decoded_max >= DNS_LABEL_MAX);
+
+        if (encoded_size <= 0)
+                return 0;
+
+        for (p = encoded; p < encoded + encoded_size; p++)
+                if ((uint8_t) *p > 127)
+                        contains_8bit = true;
+
+        if (!contains_8bit)
+                return 0;
+
+        input = stringprep_utf8_to_ucs4(encoded, encoded_size, &input_size);
+        if (!input)
+                return -ENOMEM;
+
+        if (idna_to_ascii_4i(input, input_size, decoded, 0) != 0)
+                return -EINVAL;
+
+        return strlen(decoded);
+#else
+        return 0;
+#endif
+}
+
+int dns_label_undo_idna(const char *encoded, size_t encoded_size, char *decoded, size_t decoded_max) {
+#ifdef HAVE_LIBIDN
+        size_t input_size, output_size;
+        _cleanup_free_ uint32_t *input = NULL;
+        _cleanup_free_ char *result = NULL;
+        uint32_t *output = NULL;
+        size_t w;
+
+        /* To be invoked after unescaping */
+
+        assert(encoded);
+        assert(decoded);
+
+        if (encoded_size < sizeof(IDNA_ACE_PREFIX)-1)
+                return 0;
+
+        if (memcmp(encoded, IDNA_ACE_PREFIX, sizeof(IDNA_ACE_PREFIX) -1) != 0)
+                return 0;
+
+        input = stringprep_utf8_to_ucs4(encoded, encoded_size, &input_size);
+        if (!input)
+                return -ENOMEM;
+
+        output_size = input_size;
+        output = newa(uint32_t, output_size);
+
+        idna_to_unicode_44i(input, input_size, output, &output_size, 0);
+
+        result = stringprep_ucs4_to_utf8(output, output_size, NULL, &w);
+        if (!result)
+                return -ENOMEM;
+        if (w <= 0)
+                return 0;
+        if (w+1 > decoded_max)
+                return -EINVAL;
+
+        memcpy(decoded, result, w+1);
+        return w;
+#else
+        return 0;
+#endif
+}
+
 int dns_name_normalize(const char *s, char **_ret) {
         _cleanup_free_ char *ret = NULL;
         size_t n = 0, allocated = 0;
@@ -176,6 +258,7 @@ int dns_name_normalize(const char *s, char **_ret) {
         for (;;) {
                 _cleanup_free_ char *t = NULL;
                 char label[DNS_LABEL_MAX];
+                int k;
 
                 r = dns_label_unescape(&p, label, sizeof(label));
                 if (r < 0)
@@ -186,6 +269,12 @@ int dns_name_normalize(const char *s, char **_ret) {
                         break;
                 }
 
+                k = dns_label_undo_idna(label, r, label, sizeof(label));
+                if (k < 0)
+                        return k;
+                if (k > 0)
+                        r = k;
+
                 r = dns_label_escape(label, r, &t);
                 if (r < 0)
                         return r;
@@ -227,11 +316,18 @@ unsigned long dns_name_hash_func(const void *s, const uint8_t hash_key[HASH_KEY_
 
         while (*p) {
                 char label[DNS_LABEL_MAX+1];
+                int k;
 
                 r = dns_label_unescape(&p, label, sizeof(label));
                 if (r < 0)
                         break;
 
+                k = dns_label_undo_idna(label, r, label, sizeof(label));
+                if (k < 0)
+                        return k;
+                if (k > 0)
+                        r = k;
+
                 label[r] = 0;
                 ascii_strlower(label);
 
@@ -243,7 +339,7 @@ unsigned long dns_name_hash_func(const void *s, const uint8_t hash_key[HASH_KEY_
 
 int dns_name_compare_func(const void *a, const void *b) {
         const char *x = a, *y = b;
-        int r, q;
+        int r, q, k, w;
 
         assert(a);
         assert(b);
@@ -259,6 +355,15 @@ int dns_name_compare_func(const void *a, const void *b) {
                 if (r < 0 || q < 0)
                         return r - q;
 
+                k = dns_label_undo_idna(la, r, la, sizeof(la));
+                w = dns_label_undo_idna(lb, q, lb, sizeof(lb));
+                if (k < 0 || w < 0)
+                        return k - w;
+                if (k > 0)
+                        r = k;
+                if (w > 0)
+                        r = w;
+
                 la[r] = lb[q] = 0;
                 r = strcasecmp(la, lb);
                 if (r != 0)
@@ -267,7 +372,7 @@ int dns_name_compare_func(const void *a, const void *b) {
 }
 
 int dns_name_equal(const char *x, const char *y) {
-        int r, q;
+        int r, q, k, w;
 
         assert(x);
         assert(y);
@@ -282,9 +387,20 @@ int dns_name_equal(const char *x, const char *y) {
                 if (r < 0)
                         return r;
 
+                k = dns_label_undo_idna(la, r, la, sizeof(la));
+                if (k < 0)
+                        return k;
+                if (k > 0)
+                        r = k;
+
                 q = dns_label_unescape(&y, lb, sizeof(lb));
                 if (q < 0)
                         return q;
+                w = dns_label_undo_idna(lb, q, lb, sizeof(lb));
+                if (w < 0)
+                        return w;
+                if (w > 0)
+                        q = w;
 
                 la[r] = lb[q] = 0;
                 if (strcasecmp(la, lb))
@@ -294,7 +410,7 @@ int dns_name_equal(const char *x, const char *y) {
 
 int dns_name_endswith(const char *name, const char *suffix) {
         const char *n, *s, *saved_n = NULL;
-        int r, q;
+        int r, q, k, w;
 
         assert(name);
         assert(suffix);
@@ -308,6 +424,11 @@ int dns_name_endswith(const char *name, const char *suffix) {
                 r = dns_label_unescape(&n, ln, sizeof(ln));
                 if (r < 0)
                         return r;
+                k = dns_label_undo_idna(ln, r, ln, sizeof(ln));
+                if (k < 0)
+                        return k;
+                if (k > 0)
+                        r = k;
 
                 if (!saved_n)
                         saved_n = n;
@@ -315,6 +436,11 @@ int dns_name_endswith(const char *name, const char *suffix) {
                 q = dns_label_unescape(&s, ls, sizeof(ls));
                 if (r < 0)
                         return r;
+                w = dns_label_undo_idna(ls, r, ls, sizeof(ls));
+                if (w < 0)
+                        return w;
+                if (w > 0)
+                        q = w;
 
                 if (r == 0 && q == 0)
                         return true;
diff --git a/src/resolve/resolved-dns-domain.h b/src/resolve/resolved-dns-domain.h
index 16372fd..e674c5d 100644
--- a/src/resolve/resolved-dns-domain.h
+++ b/src/resolve/resolved-dns-domain.h
@@ -30,6 +30,9 @@
 int dns_label_unescape(const char **name, char *dest, size_t sz);
 int dns_label_escape(const char *p, size_t l, char **ret);
 
+int dns_label_apply_idna(const char *encoded, size_t encoded_size, char *decoded, size_t decoded_max);
+int dns_label_undo_idna(const char *encoded, size_t encoded_size, char *decoded, size_t decoded_max);
+
 int dns_name_normalize(const char *s, char **_ret);
 
 unsigned long dns_name_hash_func(const void *s, const uint8_t hash_key[HASH_KEY_SIZE]);
diff --git a/src/resolve/resolved-dns-packet.c b/src/resolve/resolved-dns-packet.c
index ba6fb3d..ba056f1 100644
--- a/src/resolve/resolved-dns-packet.c
+++ b/src/resolve/resolved-dns-packet.c
@@ -390,6 +390,7 @@ int dns_packet_append_name(DnsPacket *p, const char *name, size_t *start) {
                 _cleanup_free_ char *s = NULL;
                 char label[DNS_LABEL_MAX];
                 size_t n;
+                int k;
 
                 n = PTR_TO_SIZE(hashmap_get(p->names, name));
                 if (n > 0) {
@@ -414,6 +415,17 @@ int dns_packet_append_name(DnsPacket *p, const char *name, size_t *start) {
                 if (r < 0)
                         goto fail;
 
+                if (p->protocol == DNS_PROTOCOL_DNS)
+                        k = dns_label_apply_idna(label, r, label, sizeof(label));
+                else
+                        k = dns_label_undo_idna(label, r, label, sizeof(label));
+                if (k < 0) {
+                        r = k;
+                        goto fail;
+                }
+                if (k > 0)
+                        r = k;
+
                 r = dns_packet_append_label(p, label, r, &n);
                 if (r < 0)
                         goto fail;



More information about the systemd-commits mailing list