resolved-dns-domain.c revision 7b9f7afcc04e80b77a2567b0750aa2cd03c1a1cd
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen This file is part of systemd.
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen Copyright 2014 Lennart Poettering
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen systemd is free software; you can redistribute it and/or modify it
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen under the terms of the GNU Lesser General Public License as published by
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen the Free Software Foundation; either version 2.1 of the License, or
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen (at your option) any later version.
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen systemd is distributed in the hope that it will be useful, but
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen WITHOUT ANY WARRANTY; without even the implied warranty of
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen Lesser General Public License for more details.
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen You should have received a copy of the GNU Lesser General Public License
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen along with systemd; If not, see <http://www.gnu.org/licenses/>.
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringint dns_label_unescape(const char **name, char *dest, size_t sz) {
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen const char *n;
3df3e884ae1237ef0d4d23b0e80f4ffda95ac135Ronny Chevalier if (*n == '.') {
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen if (*n == '\\') {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering /* Escaped character */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering /* Ending NUL */
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen /* Escaped backslash or dot */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering *(d++) = *(n++);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering /* Escaped literal ASCII character */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering /* Don't allow CC characters or anything that doesn't fit in 8bit */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering *(d++) = (char) k;
a2a416f768e2aa7db5b975cd50eb19237cac9cceLennart Poettering } else if ((uint8_t) *n >= (uint8_t) ' ' && *n != 127) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering /* Normal character */
a2a416f768e2aa7db5b975cd50eb19237cac9cceLennart Poettering *(d++) = *(n++);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering /* Empty label that is not at the end? */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r == 0 && *n)
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersenint dns_label_escape(const char *p, size_t l, char **ret) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering while (l > 0) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering /* Dot or backslash */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering *(q++) = '\\';
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering } else if (*p == '_' ||
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering /* Proper character */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering } else if ((uint8_t) *p >= (uint8_t) ' ' && *p != 127) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering /* Everything else */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering *(q++) = '\\';
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering *(q++) = '0' + (char) ((uint8_t) *p / 100);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering *(q++) = '0' + (char) (((uint8_t) *p / 10) % 10);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering *(q++) = '0' + (char) ((uint8_t) *p % 10);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringint dns_name_normalize(const char *s, char **_ret) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering const char *p = s;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = dns_label_unescape(&p, label, sizeof(label));
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (!GREEDY_REALLOC(ret, allocated, n + !first + strlen(t) + 1))
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringunsigned long dns_name_hash_func(const void *s, const uint8_t hash_key[HASH_KEY_SIZE]) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering const char *p = s;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = dns_label_unescape(&p, label, sizeof(label));
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering ul = ul * hash_key[1] + ul + string_hash_func(label, hash_key);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringint dns_name_compare_func(const void *a, const void *b) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering const char *x = a, *y = b;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering char la[DNS_LABEL_MAX+1], lb[DNS_LABEL_MAX+1];
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (*x == 0 && *y == 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = dns_label_unescape(&x, la, sizeof(la));
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering q = dns_label_unescape(&y, lb, sizeof(lb));
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen if (r < 0 || q < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringint dns_name_equal(const char *x, const char *y) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering char la[DNS_LABEL_MAX+1], lb[DNS_LABEL_MAX+1];
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (*x == 0 && *y == 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = dns_label_unescape(&x, la, sizeof(la));
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringint dns_name_endswith(const char *name, const char *suffix) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering char ln[DNS_LABEL_MAX+1], ls[DNS_LABEL_MAX+1];
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = dns_label_unescape(&n, ln, sizeof(ln));
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering q = dns_label_unescape(&s, ls, sizeof(ls));
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering if (r == 0 && q == 0)
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering if (r == 0 && saved_n == n)
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering /* Not the same, let's jump back, and try with the next label again */
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poetteringint dns_name_reverse(int family, const union in_addr_union *a, char **ret) {
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering p = (const uint8_t*) a;
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering r = asprintf(ret, "%u.%u.%u.%u.in-addr.arpa", p[3], p[2], p[1], p[0]);
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering r = asprintf(ret, "%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.ip6.arpa",
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering hexchar(p[15] & 0xF), hexchar(p[15] >> 4), hexchar(p[14] & 0xF), hexchar(p[14] >> 4),
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering hexchar(p[13] & 0xF), hexchar(p[13] >> 4), hexchar(p[12] & 0xF), hexchar(p[12] >> 4),
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering hexchar(p[11] & 0xF), hexchar(p[11] >> 4), hexchar(p[10] & 0xF), hexchar(p[10] >> 4),
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering hexchar(p[ 9] & 0xF), hexchar(p[ 9] >> 4), hexchar(p[ 8] & 0xF), hexchar(p[ 8] >> 4),
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering hexchar(p[ 7] & 0xF), hexchar(p[ 7] >> 4), hexchar(p[ 6] & 0xF), hexchar(p[ 6] >> 4),
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering hexchar(p[ 5] & 0xF), hexchar(p[ 5] >> 4), hexchar(p[ 4] & 0xF), hexchar(p[ 4] >> 4),
422baca0f230913158078fddf884e06c8c64a316Lennart Poettering hexchar(p[ 3] & 0xF), hexchar(p[ 3] >> 4), hexchar(p[ 2] & 0xF), hexchar(p[ 2] >> 4),
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering hexchar(p[ 1] & 0xF), hexchar(p[ 1] >> 4), hexchar(p[ 0] & 0xF), hexchar(p[ 0] >> 4));
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poetteringint dns_name_address(const char *p, int *family, union in_addr_union *address) {
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering r = dns_name_endswith(p, "in-addr.arpa");
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering for (i = 0; i < ELEMENTSOF(a); i++) {
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering r = dns_label_unescape(&p, label, sizeof(label));
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering address->in.s_addr = htobe32(((uint32_t) a[3] << 24) |
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering for (i = 0; i < ELEMENTSOF(a.s6_addr); i++) {
8d3d7072e609ef0e0fb37e1d19a29307d58146c3Michal Schmidt r = dns_label_unescape(&p, label, sizeof(label));
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering r = dns_label_unescape(&p, label, sizeof(label));
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering a.s6_addr[ELEMENTSOF(a.s6_addr) - i - 1] = (uint8_t) y << 4 | (uint8_t) x;
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering r = dns_label_unescape(&name, label, sizeof(label));
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering return r == 0 && *name == 0;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringint dns_name_single_label(const char *name) {
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen r = dns_label_unescape(&name, label, sizeof(label));
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering r = dns_label_unescape(&name, label, sizeof(label));
00fa60ae3b2823036cb3e7734f16bce30cb7441dLennart Poettering return r == 0 && *name == 0;