dns-domain.c revision 54adabf727fbcf1a4f49b59362e92b79da1082f1
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering/***
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering This file is part of systemd.
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering Copyright 2014 Lennart Poettering
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering systemd is free software; you can redistribute it and/or modify it
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering under the terms of the GNU Lesser General Public License as published by
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering the Free Software Foundation; either version 2.1 of the License, or
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering (at your option) any later version.
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering systemd is distributed in the hope that it will be useful, but
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering Lesser General Public License for more details.
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering You should have received a copy of the GNU Lesser General Public License
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering ***/
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering#ifdef HAVE_LIBIDN
a9cdc94f7ff40f22a3cf9472f612a80730a1b010Dave Reisner#include <idna.h>
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering#include <stringprep.h>
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering#endif
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering#include "alloc-util.h"
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering#include "dns-domain.h"
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering#include "hexdecoct.h"
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering#include "parse-util.h"
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering#include "string-util.h"
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sieversint dns_label_unescape(const char **name, char *dest, size_t sz) {
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers const char *n;
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers char *d;
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers int r = 0;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering assert(name);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering assert(*name);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering assert(dest);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering n = *name;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering d = dest;
0affed79d2e30013f07cb94e6f07e3fcb81c02faLennart Poettering
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmek for (;;) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (*n == '.') {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering n++;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering break;
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers }
7085053a437456ab87d726f3697002dd811fdf7aDaniel Wallace
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (*n == 0)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering break;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (sz <= 0)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return -ENOSPC;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (r >= DNS_LABEL_MAX)
1b12a7b5896f94bdf33b3a6661ebabd761ea6adcHarald Hoyer return -EINVAL;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (*n == '\\') {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering /* Escaped character */
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering n++;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (*n == 0)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering /* Ending NUL */
46e65dcc3a522b5e992e165b5e61d14254026859Lennart Poettering return -EINVAL;
46e65dcc3a522b5e992e165b5e61d14254026859Lennart Poettering
46e65dcc3a522b5e992e165b5e61d14254026859Lennart Poettering else if (*n == '\\' || *n == '.') {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering /* Escaped backslash or dot */
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering *(d++) = *(n++);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering sz--;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r++;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering } else if (n[0] >= '0' && n[0] <= '9') {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering unsigned k;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering /* Escaped literal ASCII character */
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (!(n[1] >= '0' && n[1] <= '9') ||
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering !(n[2] >= '0' && n[2] <= '9'))
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return -EINVAL;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering k = ((unsigned) (n[0] - '0') * 100) +
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering ((unsigned) (n[1] - '0') * 10) +
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering ((unsigned) (n[2] - '0'));
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering /* Don't allow CC characters or anything that doesn't fit in 8bit */
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (k < ' ' || k > 255 || k == 127)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return -EINVAL;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering *(d++) = (char) k;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering sz--;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r++;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering n += 3;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering } else
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return -EINVAL;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering } else if ((uint8_t) *n >= (uint8_t) ' ' && *n != 127) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering /* Normal character */
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering *(d++) = *(n++);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering sz--;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r++;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering } else
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return -EINVAL;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering }
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers
b92bea5d2a9481de69bb627a7b442a9f58fca43dZbigniew Jędrzejewski-Szmek /* Empty label that is not at the end? */
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers if (r == 0 && *n)
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers return -EINVAL;
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers if (sz >= 1)
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers *d = 0;
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers *name = n;
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers return r;
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers}
ffc06c3513d9a0693c7f810d03b20705127ba55aKay Sievers
ffc06c3513d9a0693c7f810d03b20705127ba55aKay Sievers/* @label_terminal: terminal character of a label, updated to point to the terminal character of
ffc06c3513d9a0693c7f810d03b20705127ba55aKay Sievers * the previous label (always skipping one dot) or to NULL if there are no more
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering * labels. */
ffc06c3513d9a0693c7f810d03b20705127ba55aKay Sieversint dns_label_unescape_suffix(const char *name, const char **label_terminal, char *dest, size_t sz) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering const char *terminal;
ffc06c3513d9a0693c7f810d03b20705127ba55aKay Sievers int r;
ffc06c3513d9a0693c7f810d03b20705127ba55aKay Sievers
ffc06c3513d9a0693c7f810d03b20705127ba55aKay Sievers assert(name);
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers assert(label_terminal);
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers assert(dest);
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers /* no more labels */
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (!*label_terminal) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (sz >= 1)
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers *dest = 0;
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return 0;
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers }
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering assert(**label_terminal == '.' || **label_terminal == 0);
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers /* skip current terminal character */
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers terminal = *label_terminal - 1;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering /* point name to the last label, and terminal to the preceding terminal symbol (or make it a NULL pointer) */
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering for (;;) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (terminal < name) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering /* reached the first label, so indicate that there are no more */
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering terminal = NULL;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering break;
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers }
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering /* find the start of the last label */
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (*terminal == '.') {
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers const char *y;
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers unsigned slashes = 0;
94676f3e9352cbf1f72e0a512ee0d2ed83ff676dLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering for (y = terminal - 1; y >= name && *y == '\\'; y--)
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers slashes ++;
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers
94676f3e9352cbf1f72e0a512ee0d2ed83ff676dLennart Poettering if (slashes % 2 == 0) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering /* the '.' was not escaped */
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers name = terminal + 1;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering break;
94676f3e9352cbf1f72e0a512ee0d2ed83ff676dLennart Poettering } else {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering terminal = y;
c49b30a23583ff39daaa26696bcab478d2fee0bbLennart Poettering continue;
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers }
e1636421f46db6d06fbd028ef20a3113fa3e11f8Lennart Poettering }
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering terminal --;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering }
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = dns_label_unescape(&name, dest, sz);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (r < 0)
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna return r;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering *label_terminal = terminal;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return r;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering}
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poetteringint dns_label_escape(const char *p, size_t l, char **ret) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering _cleanup_free_ char *s = NULL;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering char *q;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering int r;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering assert(p);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering assert(ret);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (l > DNS_LABEL_MAX)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return -EINVAL;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering s = malloc(l * 4 + 1);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (!s)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return -ENOMEM;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering q = s;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering while (l > 0) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (*p == '.' || *p == '\\') {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering /* Dot or backslash */
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering *(q++) = '\\';
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering *(q++) = *p;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering } else if (*p == '_' ||
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering *p == '-' ||
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering (*p >= '0' && *p <= '9') ||
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering (*p >= 'a' && *p <= 'z') ||
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering (*p >= 'A' && *p <= 'Z')) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering /* Proper character */
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering *(q++) = *p;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering } else if ((uint8_t) *p >= (uint8_t) ' ' && *p != 127) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering /* Everything else */
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering *(q++) = '\\';
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering *(q++) = '0' + (char) ((uint8_t) *p / 100);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering *(q++) = '0' + (char) (((uint8_t) *p / 10) % 10);
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna *(q++) = '0' + (char) ((uint8_t) *p % 10);
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering } else
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return -EINVAL;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering p++;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering l--;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering }
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering *q = 0;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering *ret = s;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = q - s;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering s = NULL;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return r;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering}
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poetteringint dns_label_apply_idna(const char *encoded, size_t encoded_size, char *decoded, size_t decoded_max) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering#ifdef HAVE_LIBIDN
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering _cleanup_free_ uint32_t *input = NULL;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering size_t input_size;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering const char *p;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering bool contains_8bit = false;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering assert(encoded);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering assert(decoded);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering assert(decoded_max >= DNS_LABEL_MAX);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (encoded_size <= 0)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return 0;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering for (p = encoded; p < encoded + encoded_size; p++)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if ((uint8_t) *p > 127)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering contains_8bit = true;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (!contains_8bit)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return 0;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2f7a4867babd3fd382e5495f21724358f30fa67dMichal Sekletar input = stringprep_utf8_to_ucs4(encoded, encoded_size, &input_size);
2f7a4867babd3fd382e5495f21724358f30fa67dMichal Sekletar if (!input)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return -ENOMEM;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (idna_to_ascii_4i(input, input_size, decoded, 0) != 0)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return -EINVAL;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return strlen(decoded);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering#else
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return 0;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering#endif
0affed79d2e30013f07cb94e6f07e3fcb81c02faLennart Poettering}
0affed79d2e30013f07cb94e6f07e3fcb81c02faLennart Poettering
0affed79d2e30013f07cb94e6f07e3fcb81c02faLennart Poetteringint dns_label_undo_idna(const char *encoded, size_t encoded_size, char *decoded, size_t decoded_max) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering#ifdef HAVE_LIBIDN
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering size_t input_size, output_size;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering _cleanup_free_ uint32_t *input = NULL;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering _cleanup_free_ char *result = NULL;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering uint32_t *output = NULL;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering size_t w;
ef42202ac8ed27e7ff1fc90ef8bc2590046dff25Zbigniew Jędrzejewski-Szmek
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering /* To be invoked after unescaping */
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering assert(encoded);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering assert(decoded);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (encoded_size < sizeof(IDNA_ACE_PREFIX)-1)
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna return 0;
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna if (memcmp(encoded, IDNA_ACE_PREFIX, sizeof(IDNA_ACE_PREFIX) -1) != 0)
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna return 0;
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna input = stringprep_utf8_to_ucs4(encoded, encoded_size, &input_size);
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna if (!input)
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna return -ENOMEM;
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna output_size = input_size;
7fd1b19bc9e9f5574f2877936b8ac267c7706947Harald Hoyer output = newa(uint32_t, output_size);
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna idna_to_unicode_44i(input, input_size, output, &output_size, 0);
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna result = stringprep_ucs4_to_utf8(output, output_size, NULL, &w);
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna if (!result)
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna return -ENOMEM;
bac3c8eefe23a820caac930d41629cebafbfc7b2Zbigniew Jędrzejewski-Szmek if (w <= 0)
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna return 0;
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna if (w+1 > decoded_max)
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna return -EINVAL;
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna memcpy(decoded, result, w+1);
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna return w;
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna#else
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna return 0;
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna#endif
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna}
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagnaint dns_name_concat(const char *a, const char *b, char **_ret) {
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna _cleanup_free_ char *ret = NULL;
bac3c8eefe23a820caac930d41629cebafbfc7b2Zbigniew Jędrzejewski-Szmek size_t n = 0, allocated = 0;
bac3c8eefe23a820caac930d41629cebafbfc7b2Zbigniew Jędrzejewski-Szmek const char *p = a;
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna bool first = true;
ef42202ac8ed27e7ff1fc90ef8bc2590046dff25Zbigniew Jędrzejewski-Szmek int r;
ef42202ac8ed27e7ff1fc90ef8bc2590046dff25Zbigniew Jędrzejewski-Szmek
ef42202ac8ed27e7ff1fc90ef8bc2590046dff25Zbigniew Jędrzejewski-Szmek assert(a);
ef42202ac8ed27e7ff1fc90ef8bc2590046dff25Zbigniew Jędrzejewski-Szmek
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna for (;;) {
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna _cleanup_free_ char *t = NULL;
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna char label[DNS_LABEL_MAX];
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna int k;
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna
8333c77edf8fd1654cd96f3f6ee0f078dd64b58bZbigniew Jędrzejewski-Szmek r = dns_label_unescape(&p, label, sizeof(label));
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna if (r < 0)
bac3c8eefe23a820caac930d41629cebafbfc7b2Zbigniew Jędrzejewski-Szmek return r;
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna if (r == 0) {
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna if (*p != 0)
bac3c8eefe23a820caac930d41629cebafbfc7b2Zbigniew Jędrzejewski-Szmek return -EINVAL;
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna if (b) {
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers /* Now continue with the second string, if there is one */
bac3c8eefe23a820caac930d41629cebafbfc7b2Zbigniew Jędrzejewski-Szmek p = b;
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna b = NULL;
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna continue;
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna }
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna break;
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna }
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna k = dns_label_undo_idna(label, r, label, sizeof(label));
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna if (k < 0)
bac3c8eefe23a820caac930d41629cebafbfc7b2Zbigniew Jędrzejewski-Szmek return k;
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna if (k > 0)
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna r = k;
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna
bac3c8eefe23a820caac930d41629cebafbfc7b2Zbigniew Jędrzejewski-Szmek r = dns_label_escape(label, r, &t);
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna if (r < 0)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return r;
bac3c8eefe23a820caac930d41629cebafbfc7b2Zbigniew Jędrzejewski-Szmek
bac3c8eefe23a820caac930d41629cebafbfc7b2Zbigniew Jędrzejewski-Szmek if (_ret) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (!GREEDY_REALLOC(ret, allocated, n + !first + strlen(t) + 1))
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return -ENOMEM;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (!first)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering ret[n++] = '.';
7c2d80944afb4196f2eff614e8da1450dffcbeaaThomas Hindoe Paaboel Andersen else
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering first = false;
bac3c8eefe23a820caac930d41629cebafbfc7b2Zbigniew Jędrzejewski-Szmek
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering memcpy(ret + n, t, r);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering }
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers n += r;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering }
e1636421f46db6d06fbd028ef20a3113fa3e11f8Lennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (n > DNS_NAME_MAX)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return -EINVAL;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (_ret) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (!GREEDY_REALLOC(ret, allocated, n + 1))
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return -ENOMEM;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering ret[n] = 0;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering *_ret = ret;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering ret = NULL;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering }
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return 0;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering}
e1636421f46db6d06fbd028ef20a3113fa3e11f8Lennart Poettering
e1636421f46db6d06fbd028ef20a3113fa3e11f8Lennart Poetteringvoid dns_name_hash_func(const void *s, struct siphash *state) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering const char *p = s;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering int r;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering assert(p);
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering while (*p) {
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers char label[DNS_LABEL_MAX+1];
e1636421f46db6d06fbd028ef20a3113fa3e11f8Lennart Poettering int k;
e1636421f46db6d06fbd028ef20a3113fa3e11f8Lennart Poettering
e1636421f46db6d06fbd028ef20a3113fa3e11f8Lennart Poettering r = dns_label_unescape(&p, label, sizeof(label));
e1636421f46db6d06fbd028ef20a3113fa3e11f8Lennart Poettering if (r < 0)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering break;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering k = dns_label_undo_idna(label, r, label, sizeof(label));
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (k < 0)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering break;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (k > 0)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = k;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (r == 0)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering break;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering label[r] = 0;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering ascii_strlower(label);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering string_hash_func(label, state);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering }
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering /* enforce that all names are terminated by the empty label */
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering string_hash_func("", state);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering}
2b6bf07dd23bb467099d213c97b3875c5e453491Zbigniew Jędrzejewski-Szmek
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poetteringint dns_name_compare_func(const void *a, const void *b) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering const char *x, *y;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering int r, q, k, w;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering assert(a);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering assert(b);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering x = (const char *) a + strlen(a);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering y = (const char *) b + strlen(b);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering for (;;) {
ef42202ac8ed27e7ff1fc90ef8bc2590046dff25Zbigniew Jędrzejewski-Szmek char la[DNS_LABEL_MAX+1], lb[DNS_LABEL_MAX+1];
ef42202ac8ed27e7ff1fc90ef8bc2590046dff25Zbigniew Jędrzejewski-Szmek
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (x == NULL && y == NULL)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return 0;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = dns_label_unescape_suffix(a, &x, la, sizeof(la));
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering q = dns_label_unescape_suffix(b, &y, lb, sizeof(lb));
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (r < 0 || q < 0)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return r - q;
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers
7fd1b19bc9e9f5574f2877936b8ac267c7706947Harald Hoyer k = dns_label_undo_idna(la, r, la, sizeof(la));
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmek w = dns_label_undo_idna(lb, q, lb, sizeof(lb));
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (k < 0 || w < 0)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return k - w;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (k > 0)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = k;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (w > 0)
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmek r = w;
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmek
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering la[r] = lb[q] = 0;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = strcasecmp(la, lb);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (r != 0)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return r;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering }
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering}
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poetteringconst struct hash_ops dns_name_hash_ops = {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering .hash = dns_name_hash_func,
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering .compare = dns_name_compare_func
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering};
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poetteringint dns_name_equal(const char *x, const char *y) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering int r, q, k, w;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering assert(x);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering assert(y);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
7c2d80944afb4196f2eff614e8da1450dffcbeaaThomas Hindoe Paaboel Andersen for (;;) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering char la[DNS_LABEL_MAX+1], lb[DNS_LABEL_MAX+1];
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (*x == 0 && *y == 0)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return true;
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers r = dns_label_unescape(&x, la, sizeof(la));
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (r < 0)
e1636421f46db6d06fbd028ef20a3113fa3e11f8Lennart Poettering return r;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering k = dns_label_undo_idna(la, r, la, sizeof(la));
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (k < 0)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return k;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (k > 0)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = k;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering q = dns_label_unescape(&y, lb, sizeof(lb));
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (q < 0)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return q;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering w = dns_label_undo_idna(lb, q, lb, sizeof(lb));
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (w < 0)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return w;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (w > 0)
6b2b6f30e38d67b032d6bdc6b47ae05e143e96c5Michal Schmidt q = w;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
e1636421f46db6d06fbd028ef20a3113fa3e11f8Lennart Poettering la[r] = lb[q] = 0;
e1636421f46db6d06fbd028ef20a3113fa3e11f8Lennart Poettering if (strcasecmp(la, lb))
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return false;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering }
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering}
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sieversint dns_name_endswith(const char *name, const char *suffix) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering const char *n, *s, *saved_n = NULL;
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers int r, q, k, w;
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers
e1636421f46db6d06fbd028ef20a3113fa3e11f8Lennart Poettering assert(name);
e1636421f46db6d06fbd028ef20a3113fa3e11f8Lennart Poettering assert(suffix);
e1636421f46db6d06fbd028ef20a3113fa3e11f8Lennart Poettering
e1636421f46db6d06fbd028ef20a3113fa3e11f8Lennart Poettering n = name;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering s = suffix;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers for (;;) {
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering char ln[DNS_LABEL_MAX+1], ls[DNS_LABEL_MAX+1];
7fd1b19bc9e9f5574f2877936b8ac267c7706947Harald Hoyer
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering r = dns_label_unescape(&n, ln, sizeof(ln));
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering if (r < 0)
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering return r;
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering k = dns_label_undo_idna(ln, r, ln, sizeof(ln));
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering if (k < 0)
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering return k;
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering if (k > 0)
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering r = k;
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering if (!saved_n)
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering saved_n = n;
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering q = dns_label_unescape(&s, ls, sizeof(ls));
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering if (q < 0)
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering return q;
c62e11ce3966c55d23520b9f0785c7e839cf7f37Lennart Poettering w = dns_label_undo_idna(ls, q, ls, sizeof(ls));
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering if (w < 0)
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering return w;
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering if (w > 0)
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering q = w;
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering if (r == 0 && q == 0)
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering return true;
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering if (r == 0 && saved_n == n)
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering return false;
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering ln[r] = ls[q] = 0;
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering if (r != q || strcasecmp(ln, ls)) {
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering /* Not the same, let's jump back, and try with the next label again */
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering s = suffix;
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering n = saved_n;
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering saved_n = NULL;
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering }
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering }
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering}
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poetteringint dns_name_between(const char *a, const char *b, const char *c) {
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering int n;
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering /* Determine if b is strictly greater than a and strictly smaller than c.
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering We consider the order of names to be circular, so that if a is
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering strictly greater than c, we consider b to be between them if it is
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering either greater than a or smaller than c. This is how the canonical
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering DNS name order used in NSEC records work. */
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering n = dns_name_compare_func(a, c);
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering if (n == 0)
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering return -EINVAL;
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering else if (n < 0)
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering /* a<---b--->c */
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering return dns_name_compare_func(a, b) < 0 &&
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering dns_name_compare_func(b, c) < 0;
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering else
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering /* <--b--c a--b--> */
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering return dns_name_compare_func(b, c) < 0 ||
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering dns_name_compare_func(a, b) < 0;
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering}
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poetteringint dns_name_reverse(int family, const union in_addr_union *a, char **ret) {
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering const uint8_t *p;
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering int r;
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering assert(a);
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering assert(ret);
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering p = (const uint8_t*) a;
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering if (family == AF_INET)
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering r = asprintf(ret, "%u.%u.%u.%u.in-addr.arpa", p[3], p[2], p[1], p[0]);
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering else if (family == AF_INET6)
50cfc579280fb42569488079bd2e249e32a27df2Lennart 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",
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering hexchar(p[15] & 0xF), hexchar(p[15] >> 4), hexchar(p[14] & 0xF), hexchar(p[14] >> 4),
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering hexchar(p[13] & 0xF), hexchar(p[13] >> 4), hexchar(p[12] & 0xF), hexchar(p[12] >> 4),
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering hexchar(p[11] & 0xF), hexchar(p[11] >> 4), hexchar(p[10] & 0xF), hexchar(p[10] >> 4),
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering hexchar(p[ 9] & 0xF), hexchar(p[ 9] >> 4), hexchar(p[ 8] & 0xF), hexchar(p[ 8] >> 4),
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering hexchar(p[ 7] & 0xF), hexchar(p[ 7] >> 4), hexchar(p[ 6] & 0xF), hexchar(p[ 6] >> 4),
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering hexchar(p[ 5] & 0xF), hexchar(p[ 5] >> 4), hexchar(p[ 4] & 0xF), hexchar(p[ 4] >> 4),
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering hexchar(p[ 3] & 0xF), hexchar(p[ 3] >> 4), hexchar(p[ 2] & 0xF), hexchar(p[ 2] >> 4),
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering hexchar(p[ 1] & 0xF), hexchar(p[ 1] >> 4), hexchar(p[ 0] & 0xF), hexchar(p[ 0] >> 4));
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering else
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering return -EAFNOSUPPORT;
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering if (r < 0)
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering return -ENOMEM;
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering return 0;
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering}
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poetteringint dns_name_address(const char *p, int *family, union in_addr_union *address) {
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering int r;
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering assert(p);
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering assert(family);
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering assert(address);
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering r = dns_name_endswith(p, "in-addr.arpa");
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering if (r < 0)
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering return r;
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering if (r > 0) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering uint8_t a[4];
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering unsigned i;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
82c1d8f4eb74ddd9be2c9b9b56d9dc564c599effLennart Poettering for (i = 0; i < ELEMENTSOF(a); i++) {
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering char label[DNS_LABEL_MAX+1];
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering r = dns_label_unescape(&p, label, sizeof(label));
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering if (r < 0)
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers return r;
a86a47ce1f63476631635fbcbc10af8877172114Lennart Poettering if (r == 0)
a86a47ce1f63476631635fbcbc10af8877172114Lennart Poettering return -EINVAL;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (r > 3)
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering return -EINVAL;
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering r = safe_atou8(label, &a[i]);
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering if (r < 0)
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering return r;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering }
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering r = dns_name_equal(p, "in-addr.arpa");
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering if (r <= 0)
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering return r;
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering *family = AF_INET;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering address->in.s_addr = htobe32(((uint32_t) a[3] << 24) |
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering ((uint32_t) a[2] << 16) |
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering ((uint32_t) a[1] << 8) |
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering (uint32_t) a[0]);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return 1;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering }
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = dns_name_endswith(p, "ip6.arpa");
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (r < 0)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return r;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (r > 0) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering struct in6_addr a;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering unsigned i;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers for (i = 0; i < ELEMENTSOF(a.s6_addr); i++) {
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers char label[DNS_LABEL_MAX+1];
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers int x, y;
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers r = dns_label_unescape(&p, label, sizeof(label));
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers if (r <= 0)
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers return r;
eb9da376d76b48585b3b63b4f91903b54f7abd36Lennart Poettering if (r != 1)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return -EINVAL;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering x = unhexchar(label[0]);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (x < 0)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return -EINVAL;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = dns_label_unescape(&p, label, sizeof(label));
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (r <= 0)
4b4bec19582c3ad2b7d25116f3c22c783274feadThomas Hindoe Paaboel Andersen return r;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (r != 1)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return -EINVAL;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering y = unhexchar(label[0]);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (y < 0)
eb9da376d76b48585b3b63b4f91903b54f7abd36Lennart Poettering return -EINVAL;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering a.s6_addr[ELEMENTSOF(a.s6_addr) - i - 1] = (uint8_t) y << 4 | (uint8_t) x;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering }
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = dns_name_equal(p, "ip6.arpa");
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (r <= 0)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return r;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering *family = AF_INET6;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering address->in6 = a;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return 1;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering }
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return 0;
546158bc6f46f8004cc11e81d19d223e0da56730Jan Janssen}
546158bc6f46f8004cc11e81d19d223e0da56730Jan Janssen
546158bc6f46f8004cc11e81d19d223e0da56730Jan Janssenint dns_name_root(const char *name) {
546158bc6f46f8004cc11e81d19d223e0da56730Jan Janssen char label[DNS_LABEL_MAX+1];
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers int r;
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers assert(name);
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers r = dns_label_unescape(&name, label, sizeof(label));
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers if (r < 0)
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers return r;
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers return r == 0 && *name == 0;
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers}
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poetteringint dns_name_single_label(const char *name) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering char label[DNS_LABEL_MAX+1];
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering int r;
eb9da376d76b48585b3b63b4f91903b54f7abd36Lennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering assert(name);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = dns_label_unescape(&name, label, sizeof(label));
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (r < 0)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return r;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (r == 0)
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers return 0;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = dns_label_unescape(&name, label, sizeof(label));
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (r < 0)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return r;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return r == 0 && *name == 0;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering}
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering/* Encode a domain name according to RFC 1035 Section 3.1 */
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sieversint dns_name_to_wire_format(const char *domain, uint8_t *buffer, size_t len) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering uint8_t *label_length;
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering uint8_t *out;
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering int r;
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering assert_return(buffer, -EINVAL);
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering assert_return(domain, -EINVAL);
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering assert_return(domain[0], -EINVAL);
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering out = buffer;
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering do {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering /* reserve a byte for label length */
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (len == 0)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return -ENOBUFS;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering len--;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering label_length = out;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering out++;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering /* convert and copy a single label */
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = dns_label_unescape(&domain, (char *) out, len);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (r < 0)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return r;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering /* fill label length, move forward */
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering *label_length = r;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering out += r;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering len -= r;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering } while (r != 0);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return out - buffer;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering}
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering