summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2015-08-18 00:05:41 +0200
committerLennart Poettering <lennart@poettering.net>2015-08-21 12:41:07 +0200
commit9ca45586e67c6d061d0db7bdf5b05d30e37e368d (patch)
tree0a9c3677c7a49602f715d93dc678228c8b077680 /src
parent46a5e0e7421bcc47755ae15d430c15a16dc9e03e (diff)
dns-domain: add call for concatenating two domain names
This is specifically useful for appending the mDNS ".local" suffix to a single-label hostname in the most correct way. (used in later commit)
Diffstat (limited to 'src')
-rw-r--r--src/shared/dns-domain.c40
-rw-r--r--src/shared/dns-domain.h10
-rw-r--r--src/test/test-dns-domain.c35
3 files changed, 69 insertions, 16 deletions
diff --git a/src/shared/dns-domain.c b/src/shared/dns-domain.c
index 8a0dec1540..6dc04d51e4 100644
--- a/src/shared/dns-domain.c
+++ b/src/shared/dns-domain.c
@@ -308,14 +308,14 @@ int dns_label_undo_idna(const char *encoded, size_t encoded_size, char *decoded,
#endif
}
-int dns_name_normalize(const char *s, char **_ret) {
+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 = s;
+ const char *p = a;
bool first = true;
int r;
- assert(s);
+ assert(a);
for (;;) {
_cleanup_free_ char *t = NULL;
@@ -328,6 +328,14 @@ int dns_name_normalize(const char *s, char **_ret) {
if (r == 0) {
if (*p != 0)
return -EINVAL;
+
+ if (b) {
+ /* Now continue with the second string, if there is one */
+ p = b;
+ b = NULL;
+ continue;
+ }
+
break;
}
@@ -341,27 +349,29 @@ int dns_name_normalize(const char *s, char **_ret) {
if (r < 0)
return r;
- if (!GREEDY_REALLOC(ret, allocated, n + !first + strlen(t) + 1))
- return -ENOMEM;
+ if (_ret) {
+ if (!GREEDY_REALLOC(ret, allocated, n + !first + strlen(t) + 1))
+ return -ENOMEM;
- if (!first)
- ret[n++] = '.';
- else
- first = false;
+ if (!first)
+ ret[n++] = '.';
+ else
+ first = false;
+
+ memcpy(ret + n, t, r);
+ }
- memcpy(ret + n, t, r);
n += r;
}
if (n > DNS_NAME_MAX)
return -EINVAL;
- if (!GREEDY_REALLOC(ret, allocated, n + 1))
- return -ENOMEM;
-
- ret[n] = 0;
-
if (_ret) {
+ if (!GREEDY_REALLOC(ret, allocated, n + 1))
+ return -ENOMEM;
+
+ ret[n] = 0;
*_ret = ret;
ret = NULL;
}
diff --git a/src/shared/dns-domain.h b/src/shared/dns-domain.h
index bd50ad3e6d..8e73d9c20f 100644
--- a/src/shared/dns-domain.h
+++ b/src/shared/dns-domain.h
@@ -35,9 +35,17 @@ 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);
+int dns_name_concat(const char *a, const char *b, char **ret);
+
+static inline int dns_name_normalize(const char *s, char **ret) {
+ /* dns_name_concat() normalizes as a side-effect */
+ return dns_name_concat(s, NULL, ret);
+}
+
static inline int dns_name_is_valid(const char *s) {
int r;
+
+ /* dns_name_normalize() verifies as a side effect */
r = dns_name_normalize(s, NULL);
if (r == -EINVAL)
return 0;
diff --git a/src/test/test-dns-domain.c b/src/test/test-dns-domain.c
index 0042722c99..2193eb6f7d 100644
--- a/src/test/test-dns-domain.c
+++ b/src/test/test-dns-domain.c
@@ -251,6 +251,39 @@ static void test_dns_name_reverse(void) {
test_dns_name_reverse_one("::1", "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa");
}
+static void test_dns_name_concat_one(const char *a, const char *b, int r, const char *result) {
+ _cleanup_free_ char *p = NULL;
+
+ assert_se(dns_name_concat(a, b, &p) == r);
+ assert_se(streq_ptr(p, result));
+}
+
+static void test_dns_name_concat(void) {
+ 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.", "bar.", 0, "foo.bar");
+}
+
+static void test_dns_name_is_valid_one(const char *s, int ret) {
+ assert_se(dns_name_is_valid(s) == ret);
+}
+
+static void test_dns_name_is_valid(void) {
+ test_dns_name_is_valid_one("foo", 1);
+ test_dns_name_is_valid_one("foo.", 1);
+ test_dns_name_is_valid_one("Foo", 1);
+ test_dns_name_is_valid_one("foo.bar", 1);
+ test_dns_name_is_valid_one("foo.bar.baz", 1);
+ test_dns_name_is_valid_one("", 1);
+ test_dns_name_is_valid_one("foo..bar", 0);
+ test_dns_name_is_valid_one(".foo.bar", 0);
+ test_dns_name_is_valid_one("foo.bar.", 1);
+ test_dns_name_is_valid_one("\\zbar", 0);
+ test_dns_name_is_valid_one("รค", 1);
+ test_dns_name_is_valid_one("\n", 0);
+}
+
int main(int argc, char *argv[]) {
test_dns_label_unescape();
@@ -263,6 +296,8 @@ int main(int argc, char *argv[]) {
test_dns_name_root();
test_dns_name_single_label();
test_dns_name_reverse();
+ test_dns_name_concat();
+ test_dns_name_is_valid();
return 0;
}