diff options
Diffstat (limited to 'src/shared/dns-domain.c')
-rw-r--r-- | src/shared/dns-domain.c | 49 |
1 files changed, 48 insertions, 1 deletions
diff --git a/src/shared/dns-domain.c b/src/shared/dns-domain.c index 59475115ba..e777badb6b 100644 --- a/src/shared/dns-domain.c +++ b/src/shared/dns-domain.c @@ -263,7 +263,6 @@ int dns_label_escape(const char *p, size_t l, char *dest, size_t sz) { *(q++) = '0' + (char) ((uint8_t) *p % 10); sz -= 4; - } p++; @@ -653,6 +652,54 @@ int dns_name_endswith(const char *name, const char *suffix) { } } +static int dns_label_unescape_undo_idna(const char **name, char *dest, size_t sz) { + int r, k; + + /* Clobbers all arguments on failure... */ + + r = dns_label_unescape(name, dest, sz); + if (r <= 0) + return r; + + k = dns_label_undo_idna(dest, r, dest, sz); + if (k < 0) + return k; + if (k == 0) /* not an IDNA name */ + return r; + + return k; +} + +int dns_name_startswith(const char *name, const char *prefix) { + const char *n, *p; + int r, q; + + assert(name); + assert(prefix); + + n = name; + p = prefix; + + for (;;) { + char ln[DNS_LABEL_MAX], lp[DNS_LABEL_MAX]; + + r = dns_label_unescape_undo_idna(&p, lp, sizeof(lp)); + if (r < 0) + return r; + if (r == 0) + return true; + + q = dns_label_unescape_undo_idna(&n, ln, sizeof(ln)); + if (q < 0) + return q; + + if (r != q) + return false; + if (ascii_strcasecmp_n(ln, lp, r) != 0) + return false; + } +} + 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; |