diff options
author | Lennart Poettering <lennart@poettering.net> | 2015-11-20 17:52:36 +0100 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2015-11-23 21:31:28 +0100 |
commit | 0a49b6b6dce3a756bd8c4d458a34c2d8035ae99d (patch) | |
tree | 5d898be726a9560f44184a9d0af43d7de2c09cd7 /src/shared/dns-domain.c | |
parent | e429762faaac0c49353d35144a9d45d283e91213 (diff) |
dns-domain: add code for verifying validity of DNS-SD service names and types
Diffstat (limited to 'src/shared/dns-domain.c')
-rw-r--r-- | src/shared/dns-domain.c | 67 |
1 files changed, 67 insertions, 0 deletions
diff --git a/src/shared/dns-domain.c b/src/shared/dns-domain.c index 423ccca9cc..014e0bd70d 100644 --- a/src/shared/dns-domain.c +++ b/src/shared/dns-domain.c @@ -29,6 +29,7 @@ #include "hexdecoct.h" #include "parse-util.h" #include "string-util.h" +#include "utf8.h" int dns_label_unescape(const char **name, char *dest, size_t sz) { const char *n; @@ -749,3 +750,69 @@ int dns_name_to_wire_format(const char *domain, uint8_t *buffer, size_t len) { return out - buffer; } + +int dns_srv_type_verify(const char *name) { + unsigned c = 0; + int r; + + if (!name) + return 0; + + for (;;) { + char label[DNS_LABEL_MAX]; + int k; + + /* This more or less implements RFC 6335, Section 5.1 */ + + r = dns_label_unescape(&name, label, sizeof(label)); + if (r == -EINVAL) + return 0; + if (r < 0) + return r; + if (r == 0) + return c >= 2; /* At least two labels */ + if (r < 2) /* Label needs to be at least 2 chars long */ + return 0; + if (label[0] != '_') /* First label char needs to be underscore */ + return 0; + + /* Second char must be a letter */ + if (!(label[1] >= 'A' && label[1] <= 'Z') && + !(label[1] >= 'a' && label[1] <= 'z')) + return 0; + + /* Third and further chars must be alphanumeric or a hyphen */ + for (k = 2; k < r; k++) { + if (!(label[k] >= 'A' && label[k] <= 'Z') && + !(label[k] >= 'a' && label[k] <= 'z') && + !(label[k] >= '0' && label[k] <= '9') && + label[k] != '-') + return 0; + } + + c++; + } +} + +bool dns_service_name_is_valid(const char *name) { + size_t l; + + /* This more or less implements RFC 6763, Section 4.1.1 */ + + if (!name) + return false; + + if (!utf8_is_valid(name)) + return false; + + if (string_has_cc(name, NULL)) + return false; + + l = strlen(name); + if (l <= 0) + return false; + if (l > 63) + return false; + + return true; +} |