shared: add new dns_name_startswith() call

dns_name_startswith() is to dns_name_endswith() as startswith() is to endswith().
This commit is contained in:
Lennart Poettering 2016-01-13 02:23:08 +01:00
parent 522d85ae0a
commit eb241cdbee
3 changed files with 69 additions and 1 deletions

View File

@ -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;

View File

@ -83,6 +83,7 @@ extern const struct hash_ops dns_name_hash_ops;
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_startswith(const char *name, const char *prefix);
int dns_name_change_suffix(const char *name, const char *old_suffix, const char *new_suffix, char **ret);

View File

@ -276,6 +276,25 @@ static void test_dns_name_endswith(void) {
test_dns_name_endswith_one("x.y\001.z", "waldo", -EINVAL);
}
static void test_dns_name_startswith_one(const char *a, const char *b, int ret) {
assert_se(dns_name_startswith(a, b) == ret);
}
static void test_dns_name_startswith(void) {
test_dns_name_startswith_one("", "", true);
test_dns_name_startswith_one("", "xxx", false);
test_dns_name_startswith_one("xxx", "", true);
test_dns_name_startswith_one("x", "x", true);
test_dns_name_startswith_one("x", "y", false);
test_dns_name_startswith_one("x.y", "x.y", true);
test_dns_name_startswith_one("x.y", "y.x", false);
test_dns_name_startswith_one("x.y", "x", true);
test_dns_name_startswith_one("x.y", "X", true);
test_dns_name_startswith_one("x.y", "y", false);
test_dns_name_startswith_one("x.y", "", true);
test_dns_name_startswith_one("x.y", "X", true);
}
static void test_dns_name_is_root(void) {
assert_se(dns_name_is_root(""));
assert_se(dns_name_is_root("."));
@ -567,6 +586,7 @@ int main(int argc, char *argv[]) {
test_dns_name_normalize();
test_dns_name_equal();
test_dns_name_endswith();
test_dns_name_startswith();
test_dns_name_between();
test_dns_name_is_root();
test_dns_name_is_single_label();