mirror of
https://github.com/systemd/systemd.git
synced 2025-01-27 18:04:05 +03:00
dns-domain: rework dns_label_escape() to not imply memory allocation
The new dns_label_escape() call now operates on a buffer passed in, similar to dns_label_unescape(). This should make decoding a bit faster, and nicer.
This commit is contained in:
parent
7e8131e9c6
commit
422baca0f2
@ -360,7 +360,6 @@ int dhcp6_option_parse_domainname(const uint8_t *optval, uint16_t optlen, char *
|
|||||||
/* End of name */
|
/* End of name */
|
||||||
break;
|
break;
|
||||||
else if (c <= 63) {
|
else if (c <= 63) {
|
||||||
_cleanup_free_ char *t = NULL;
|
|
||||||
const char *label;
|
const char *label;
|
||||||
|
|
||||||
/* Literal label */
|
/* Literal label */
|
||||||
@ -369,21 +368,20 @@ int dhcp6_option_parse_domainname(const uint8_t *optval, uint16_t optlen, char *
|
|||||||
if (pos > optlen)
|
if (pos > optlen)
|
||||||
return -EMSGSIZE;
|
return -EMSGSIZE;
|
||||||
|
|
||||||
r = dns_label_escape(label, c, &t);
|
if (!GREEDY_REALLOC(ret, allocated, n + !first + DNS_LABEL_ESCAPED_MAX)) {
|
||||||
if (r < 0)
|
|
||||||
goto fail;
|
|
||||||
|
|
||||||
if (!GREEDY_REALLOC0(ret, allocated, n + !first + strlen(t) + 1)) {
|
|
||||||
r = -ENOMEM;
|
r = -ENOMEM;
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!first)
|
if (first)
|
||||||
ret[n++] = '.';
|
|
||||||
else
|
|
||||||
first = false;
|
first = false;
|
||||||
|
else
|
||||||
|
ret[n++] = '.';
|
||||||
|
|
||||||
|
r = dns_label_escape(label, c, ret + n, DNS_LABEL_ESCAPED_MAX);
|
||||||
|
if (r < 0)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
memcpy(ret + n, t, r);
|
|
||||||
n += r;
|
n += r;
|
||||||
continue;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
|
@ -1145,7 +1145,6 @@ int dns_packet_read_name(
|
|||||||
/* End of name */
|
/* End of name */
|
||||||
break;
|
break;
|
||||||
else if (c <= 63) {
|
else if (c <= 63) {
|
||||||
_cleanup_free_ char *t = NULL;
|
|
||||||
const char *label;
|
const char *label;
|
||||||
|
|
||||||
/* Literal label */
|
/* Literal label */
|
||||||
@ -1153,21 +1152,20 @@ int dns_packet_read_name(
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
r = dns_label_escape(label, c, &t);
|
if (!GREEDY_REALLOC(ret, allocated, n + !first + DNS_LABEL_ESCAPED_MAX)) {
|
||||||
if (r < 0)
|
|
||||||
goto fail;
|
|
||||||
|
|
||||||
if (!GREEDY_REALLOC(ret, allocated, n + !first + strlen(t) + 1)) {
|
|
||||||
r = -ENOMEM;
|
r = -ENOMEM;
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!first)
|
if (first)
|
||||||
ret[n++] = '.';
|
|
||||||
else
|
|
||||||
first = false;
|
first = false;
|
||||||
|
else
|
||||||
|
ret[n++] = '.';
|
||||||
|
|
||||||
|
r = dns_label_escape(label, c, ret + n, DNS_LABEL_ESCAPED_MAX);
|
||||||
|
if (r < 0)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
memcpy(ret + n, t, r);
|
|
||||||
n += r;
|
n += r;
|
||||||
continue;
|
continue;
|
||||||
} else if (allow_compression && (c & 0xc0) == 0xc0) {
|
} else if (allow_compression && (c & 0xc0) == 0xc0) {
|
||||||
|
@ -351,7 +351,7 @@ static int determine_hostname(char **llmnr_hostname, char **mdns_hostname) {
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = dns_label_escape(label, r, &n);
|
r = dns_label_escape_new(label, r, &n);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to escape host name: %m");
|
return log_error_errno(r, "Failed to escape host name: %m");
|
||||||
|
|
||||||
|
@ -182,30 +182,31 @@ int dns_label_unescape_suffix(const char *name, const char **label_terminal, cha
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
int dns_label_escape(const char *p, size_t l, char **ret) {
|
int dns_label_escape(const char *p, size_t l, char *dest, size_t sz) {
|
||||||
_cleanup_free_ char *s = NULL;
|
|
||||||
char *q;
|
char *q;
|
||||||
int r;
|
|
||||||
|
|
||||||
assert(p);
|
|
||||||
assert(ret);
|
|
||||||
|
|
||||||
if (l > DNS_LABEL_MAX)
|
if (l > DNS_LABEL_MAX)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
if (sz < 1)
|
||||||
|
return -ENOSPC;
|
||||||
|
|
||||||
s = malloc(l * 4 + 1);
|
assert(p);
|
||||||
if (!s)
|
assert(dest);
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
q = s;
|
q = dest;
|
||||||
while (l > 0) {
|
while (l > 0) {
|
||||||
|
|
||||||
if (*p == '.' || *p == '\\') {
|
if (*p == '.' || *p == '\\') {
|
||||||
|
|
||||||
|
if (sz < 3)
|
||||||
|
return -ENOSPC;
|
||||||
|
|
||||||
/* Dot or backslash */
|
/* Dot or backslash */
|
||||||
*(q++) = '\\';
|
*(q++) = '\\';
|
||||||
*(q++) = *p;
|
*(q++) = *p;
|
||||||
|
|
||||||
|
sz -= 2;
|
||||||
|
|
||||||
} else if (*p == '_' ||
|
} else if (*p == '_' ||
|
||||||
*p == '-' ||
|
*p == '-' ||
|
||||||
(*p >= '0' && *p <= '9') ||
|
(*p >= '0' && *p <= '9') ||
|
||||||
@ -213,15 +214,27 @@ int dns_label_escape(const char *p, size_t l, char **ret) {
|
|||||||
(*p >= 'A' && *p <= 'Z')) {
|
(*p >= 'A' && *p <= 'Z')) {
|
||||||
|
|
||||||
/* Proper character */
|
/* Proper character */
|
||||||
|
|
||||||
|
if (sz < 2)
|
||||||
|
return -ENOSPC;
|
||||||
|
|
||||||
*(q++) = *p;
|
*(q++) = *p;
|
||||||
|
sz -= 1;
|
||||||
|
|
||||||
} else if ((uint8_t) *p >= (uint8_t) ' ' && *p != 127) {
|
} else if ((uint8_t) *p >= (uint8_t) ' ' && *p != 127) {
|
||||||
|
|
||||||
/* Everything else */
|
/* Everything else */
|
||||||
|
|
||||||
|
if (sz < 5)
|
||||||
|
return -ENOSPC;
|
||||||
|
|
||||||
*(q++) = '\\';
|
*(q++) = '\\';
|
||||||
*(q++) = '0' + (char) ((uint8_t) *p / 100);
|
*(q++) = '0' + (char) ((uint8_t) *p / 100);
|
||||||
*(q++) = '0' + (char) (((uint8_t) *p / 10) % 10);
|
*(q++) = '0' + (char) (((uint8_t) *p / 10) % 10);
|
||||||
*(q++) = '0' + (char) ((uint8_t) *p % 10);
|
*(q++) = '0' + (char) ((uint8_t) *p % 10);
|
||||||
|
|
||||||
|
sz -= 4;
|
||||||
|
|
||||||
} else
|
} else
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
@ -230,8 +243,28 @@ int dns_label_escape(const char *p, size_t l, char **ret) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
*q = 0;
|
*q = 0;
|
||||||
|
return (int) (q - dest);
|
||||||
|
}
|
||||||
|
|
||||||
|
int dns_label_escape_new(const char *p, size_t l, char **ret) {
|
||||||
|
_cleanup_free_ char *s = NULL;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
assert(p);
|
||||||
|
assert(ret);
|
||||||
|
|
||||||
|
if (l > DNS_LABEL_MAX)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
s = new(char, DNS_LABEL_ESCAPED_MAX);
|
||||||
|
if (!s)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
r = dns_label_escape(p, l, s, DNS_LABEL_ESCAPED_MAX);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
*ret = s;
|
*ret = s;
|
||||||
r = q - s;
|
|
||||||
s = NULL;
|
s = NULL;
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
@ -351,28 +384,32 @@ int dns_name_concat(const char *a, const char *b, char **_ret) {
|
|||||||
if (k > 0)
|
if (k > 0)
|
||||||
r = k;
|
r = k;
|
||||||
|
|
||||||
r = dns_label_escape(label, r, &t);
|
|
||||||
if (r < 0)
|
|
||||||
return r;
|
|
||||||
|
|
||||||
if (_ret) {
|
if (_ret) {
|
||||||
if (!GREEDY_REALLOC(ret, allocated, n + !first + strlen(t) + 1))
|
if (!GREEDY_REALLOC(ret, allocated, n + !first + DNS_LABEL_ESCAPED_MAX))
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
if (!first)
|
r = dns_label_escape(label, r, ret + n + !first, DNS_LABEL_ESCAPED_MAX);
|
||||||
ret[n++] = '.';
|
if (r < 0)
|
||||||
else
|
return r;
|
||||||
first = false;
|
|
||||||
|
|
||||||
memcpy(ret + n, t, r);
|
if (!first)
|
||||||
|
ret[n] = '.';
|
||||||
|
} else {
|
||||||
|
char escaped[DNS_LABEL_ESCAPED_MAX];
|
||||||
|
|
||||||
|
r = dns_label_escape(label, r, escaped, sizeof(escaped));
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!first)
|
||||||
|
n++;
|
||||||
|
else
|
||||||
|
first = false;
|
||||||
|
|
||||||
n += r;
|
n += r;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (n > DNS_NAME_MAX)
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
if (_ret) {
|
if (_ret) {
|
||||||
if (!GREEDY_REALLOC(ret, allocated, n + 1))
|
if (!GREEDY_REALLOC(ret, allocated, n + 1))
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
@ -892,7 +929,8 @@ bool dns_service_name_is_valid(const char *name) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int dns_service_join(const char *name, const char *type, const char *domain, char **ret) {
|
int dns_service_join(const char *name, const char *type, const char *domain, char **ret) {
|
||||||
_cleanup_free_ char *escaped = NULL, *n = NULL;
|
char escaped[DNS_LABEL_ESCAPED_MAX];
|
||||||
|
_cleanup_free_ char *n = NULL;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert(type);
|
assert(type);
|
||||||
@ -908,7 +946,7 @@ int dns_service_join(const char *name, const char *type, const char *domain, cha
|
|||||||
if (!dns_service_name_is_valid(name))
|
if (!dns_service_name_is_valid(name))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
r = dns_label_escape(name, strlen(name), &escaped);
|
r = dns_label_escape(name, strlen(name), escaped, sizeof(escaped));
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
@ -26,11 +26,12 @@
|
|||||||
#include "in-addr-util.h"
|
#include "in-addr-util.h"
|
||||||
|
|
||||||
#define DNS_LABEL_MAX 63
|
#define DNS_LABEL_MAX 63
|
||||||
#define DNS_NAME_MAX 255
|
#define DNS_LABEL_ESCAPED_MAX (DNS_LABEL_MAX*4+1)
|
||||||
|
|
||||||
int dns_label_unescape(const char **name, char *dest, size_t sz);
|
int dns_label_unescape(const char **name, char *dest, size_t sz);
|
||||||
int dns_label_unescape_suffix(const char *name, const char **label_end, char *dest, size_t sz);
|
int dns_label_unescape_suffix(const char *name, const char **label_end, char *dest, size_t sz);
|
||||||
int dns_label_escape(const char *p, size_t l, char **ret);
|
int dns_label_escape(const char *p, size_t l, char *dest, size_t sz);
|
||||||
|
int dns_label_escape_new(const char *p, size_t l, char **ret);
|
||||||
|
|
||||||
int dns_label_apply_idna(const char *encoded, size_t encoded_size, char *decoded, size_t decoded_max);
|
int dns_label_apply_idna(const char *encoded, size_t encoded_size, char *decoded, size_t decoded_max);
|
||||||
int dns_label_undo_idna(const char *encoded, size_t encoded_size, char *decoded, size_t decoded_max);
|
int dns_label_undo_idna(const char *encoded, size_t encoded_size, char *decoded, size_t decoded_max);
|
||||||
|
@ -126,7 +126,7 @@ static void test_dns_label_escape_one(const char *what, size_t l, const char *ex
|
|||||||
_cleanup_free_ char *t = NULL;
|
_cleanup_free_ char *t = NULL;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
r = dns_label_escape(what, l, &t);
|
r = dns_label_escape_new(what, l, &t);
|
||||||
assert_se(r == ret);
|
assert_se(r == ret);
|
||||||
|
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user