shared: normalize the root domain to "." rather than ""
authorLennart Poettering <lennart@poettering.net>
Mon, 25 Jan 2016 20:32:14 +0000 (21:32 +0100)
committerLennart Poettering <lennart@poettering.net>
Tue, 26 Jan 2016 13:42:04 +0000 (14:42 +0100)
Let's make sure the root domain is normalized to ".", rather than then empty string, so that there's actually something
to see on screen. Normally, we don't append a trailing dot to normalized domain names, but do so in the one exception
of the root domain, taking inspiration from UNIX file system paths.

src/shared/dns-domain.c
src/test/test-dns-domain.c

index 3ad409f..7ef4ad3 100644 (file)
@@ -405,11 +405,17 @@ int dns_label_undo_idna(const char *encoded, size_t encoded_size, char *decoded,
 int dns_name_concat(const char *a, const char *b, char **_ret) {
         _cleanup_free_ char *ret = NULL;
         size_t n = 0, allocated = 0;
-        const char *p = a;
+        const char *p;
         bool first = true;
         int r;
 
-        assert(a);
+        if (a)
+                p = a;
+        else if (b) {
+                p = b;
+                b = NULL;
+        } else
+                goto finish;
 
         for (;;) {
                 char label[DNS_LABEL_MAX];
@@ -457,12 +463,21 @@ int dns_name_concat(const char *a, const char *b, char **_ret) {
                 n += r;
         }
 
+finish:
         if (n > DNS_HOSTNAME_MAX)
                 return -EINVAL;
 
         if (_ret) {
-                if (!GREEDY_REALLOC(ret, allocated, n + 1))
-                        return -ENOMEM;
+                if (n == 0) {
+                        /* Nothing appended? If so, generate at least a single dot, to indicate the DNS root domain */
+                        if (!GREEDY_REALLOC(ret, allocated, 2))
+                                return -ENOMEM;
+
+                        ret[n++] = '.';
+                } else {
+                        if (!GREEDY_REALLOC(ret, allocated, n + 1))
+                                return -ENOMEM;
+                }
 
                 ret[n] = 0;
                 *_ret = ret;
index 3b260ee..3efc61a 100644 (file)
@@ -186,7 +186,7 @@ static void test_dns_name_normalize_one(const char *what, const char *expect, in
 }
 
 static void test_dns_name_normalize(void) {
-        test_dns_name_normalize_one("", "", 0);
+        test_dns_name_normalize_one("", ".", 0);
         test_dns_name_normalize_one("f", "f", 0);
         test_dns_name_normalize_one("f.waldi", "f.waldi", 0);
         test_dns_name_normalize_one("f \\032.waldi", "f\\032\\032.waldi", 0);
@@ -194,7 +194,7 @@ static void test_dns_name_normalize(void) {
         test_dns_name_normalize_one("..", NULL, -EINVAL);
         test_dns_name_normalize_one(".foobar", NULL, -EINVAL);
         test_dns_name_normalize_one("foobar.", "foobar", 0);
-        test_dns_name_normalize_one(".", "", 0);
+        test_dns_name_normalize_one(".", ".", 0);
 }
 
 static void test_dns_name_equal_one(const char *a, const char *b, int ret) {
@@ -340,10 +340,18 @@ static void test_dns_name_concat_one(const char *a, const char *b, int r, const
 }
 
 static void test_dns_name_concat(void) {
+        test_dns_name_concat_one("", "", 0, ".");
+        test_dns_name_concat_one(".", "", 0, ".");
+        test_dns_name_concat_one("", ".", 0, ".");
+        test_dns_name_concat_one(".", ".", 0, ".");
         test_dns_name_concat_one("foo", "bar", 0, "foo.bar");
         test_dns_name_concat_one("foo.foo", "bar.bar", 0, "foo.foo.bar.bar");
         test_dns_name_concat_one("foo", NULL, 0, "foo");
+        test_dns_name_concat_one("foo", ".", 0, "foo");
         test_dns_name_concat_one("foo.", "bar.", 0, "foo.bar");
+        test_dns_name_concat_one(NULL, NULL, 0, ".");
+        test_dns_name_concat_one(NULL, ".", 0, ".");
+        test_dns_name_concat_one(NULL, "foo", 0, "foo");
 }
 
 static void test_dns_name_is_valid_one(const char *s, int ret) {
@@ -429,7 +437,7 @@ static void test_dns_service_join_one(const char *a, const char *b, const char *
         assert_se(dns_service_split(t, &x, &y, &z) >= 0);
         assert_se(streq_ptr(a, x));
         assert_se(streq_ptr(b, y));
-        assert_se(streq_ptr(c, z));
+        assert_se(dns_name_equal(c, z) > 0);
 }
 
 static void test_dns_service_join(void) {
@@ -460,18 +468,18 @@ static void test_dns_service_split_one(const char *joined, const char *a, const
 
         if (y) {
                 assert_se(dns_service_join(x, y, z, &t) == 0);
-                assert_se(streq_ptr(joined, t));
+                assert_se(dns_name_equal(joined, t) > 0);
         } else
-                assert_se(!x && streq_ptr(z, joined));
+                assert_se(!x && dns_name_equal(z, joined) > 0);
 }
 
 static void test_dns_service_split(void) {
-        test_dns_service_split_one("", NULL, NULL, "", 0);
+        test_dns_service_split_one("", NULL, NULL, ".", 0);
         test_dns_service_split_one("foo", NULL, NULL, "foo", 0);
         test_dns_service_split_one("foo.bar", NULL, NULL, "foo.bar", 0);
         test_dns_service_split_one("_foo.bar", NULL, NULL, "_foo.bar", 0);
-        test_dns_service_split_one("_foo._bar", NULL, "_foo._bar", "", 0);
-        test_dns_service_split_one("_meh._foo._bar", "_meh", "_foo._bar", "", 0);
+        test_dns_service_split_one("_foo._bar", NULL, "_foo._bar", ".", 0);
+        test_dns_service_split_one("_meh._foo._bar", "_meh", "_foo._bar", ".", 0);
         test_dns_service_split_one("Wuff\\032Wuff._foo._bar.waldo.com", "Wuff Wuff", "_foo._bar", "waldo.com", 0);
 }
 
@@ -490,7 +498,7 @@ static void test_dns_name_change_suffix(void) {
         test_dns_name_change_suffix_one("foo.bar.waldi.quux", "quux", "piff.paff", 1, "foo.bar.waldi.piff.paff");
         test_dns_name_change_suffix_one("foo.bar.waldi.quux", "", "piff.paff", 1, "foo.bar.waldi.quux.piff.paff");
         test_dns_name_change_suffix_one("", "", "piff.paff", 1, "piff.paff");
-        test_dns_name_change_suffix_one("", "", "", 1, "");
+        test_dns_name_change_suffix_one("", "", "", 1, ".");
         test_dns_name_change_suffix_one("a", "b", "c", 0, NULL);
 }