summaryrefslogtreecommitdiff
path: root/src/shared
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2015-11-24 00:18:49 +0100
committerLennart Poettering <lennart@poettering.net>2015-11-24 00:20:39 +0100
commit58db254ade4fb2ef77de68f28c4f13814819f6a1 (patch)
tree597cc7eb7ec7822f62b91e25558e3e9d490b655c /src/shared
parent5ce1946f4def03e0ab7127dd5729949a32e060ac (diff)
resolved: implement client-side DNAME resolution
Most servers apparently always implicitly convert DNAME to CNAME, but some servers don't, hence implement this properly, as this is required by edns0.
Diffstat (limited to 'src/shared')
-rw-r--r--src/shared/dns-domain.c67
-rw-r--r--src/shared/dns-domain.h4
2 files changed, 71 insertions, 0 deletions
diff --git a/src/shared/dns-domain.c b/src/shared/dns-domain.c
index e08143c3be..e6aad39c74 100644
--- a/src/shared/dns-domain.c
+++ b/src/shared/dns-domain.c
@@ -547,6 +547,73 @@ int dns_name_endswith(const char *name, const char *suffix) {
}
}
+int dns_name_change_suffix(const char *name, const char *old_suffix, const char *new_suffix, char **ret) {
+ const char *n, *s, *saved_before = NULL, *saved_after = NULL, *prefix;
+ int r, q, k, w;
+
+ assert(name);
+ assert(old_suffix);
+ assert(new_suffix);
+ assert(ret);
+
+ n = name;
+ s = old_suffix;
+
+ for (;;) {
+ char ln[DNS_LABEL_MAX+1], ls[DNS_LABEL_MAX+1];
+
+ if (!saved_before)
+ saved_before = n;
+
+ 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_after)
+ saved_after = n;
+
+ q = dns_label_unescape(&s, ls, sizeof(ls));
+ if (q < 0)
+ return q;
+ w = dns_label_undo_idna(ls, q, ls, sizeof(ls));
+ if (w < 0)
+ return w;
+ if (w > 0)
+ q = w;
+
+ if (r == 0 && q == 0)
+ break;
+ if (r == 0 && saved_after == n) {
+ *ret = NULL; /* doesn't match */
+ return 0;
+ }
+
+ ln[r] = ls[q] = 0;
+
+ if (r != q || strcasecmp(ln, ls)) {
+
+ /* Not the same, let's jump back, and try with the next label again */
+ s = old_suffix;
+ n = saved_after;
+ saved_after = saved_before = NULL;
+ }
+ }
+
+ /* Found it! Now generate the new name */
+ prefix = strndupa(name, saved_before - name);
+
+ r = dns_name_concat(prefix, new_suffix, ret);
+ if (r < 0)
+ return r;
+
+ return 1;
+}
+
int dns_name_between(const char *a, const char *b, const char *c) {
int n;
diff --git a/src/shared/dns-domain.h b/src/shared/dns-domain.h
index c6d7623e09..a68df330e6 100644
--- a/src/shared/dns-domain.h
+++ b/src/shared/dns-domain.h
@@ -62,6 +62,8 @@ int dns_name_between(const char *a, const char *b, const char *c);
int dns_name_equal(const char *x, const char *y);
int dns_name_endswith(const char *name, const char *suffix);
+int dns_name_change_suffix(const char *name, const char *old_suffix, const char *new_suffix, char **ret);
+
int dns_name_reverse(int family, const union in_addr_union *a, char **ret);
int dns_name_address(const char *p, int *family, union in_addr_union *a);
@@ -76,3 +78,5 @@ bool dns_service_name_is_valid(const char *name);
int dns_service_join(const char *name, const char *type, const char *domain, char **ret);
int dns_service_split(const char *joined, char **name, char **type, char **domain);
+
+int dns_name_replace_suffix(const char *name, const char *old_suffix, const char *new_suffix, char **ret);