24 RCSID(
"$Id: c5acb20d5c786f9f491ae5b6a97b24abc2acbee9 $")
26 #include <freeradius-devel/util/misc.h>
27 #include <freeradius-devel/util/strerror.h>
28 #include <freeradius-devel/util/value.h>
29 #include <freeradius-devel/util/dns.h>
30 #include <freeradius-devel/util/proto.h>
32 #define MAX_OFFSET (1 << 14)
36 size_t offset, size = end - start;
48 offset = start - lb->
start;
60 if (lb->
max == 1)
return 0;
77 if (block->
end == offset) {
86 if (lb->
num == lb->
max)
return -1;
91 block->
start = offset;
92 block->
end = offset + size;
100 if (!lb || !lb->
mark)
return;
113 if (!lb)
return true;
115 if (lb->
mark)
return (lb->
mark[offset] != 0);
122 for (i = 0; i < lb->
num; i++) {
126 if (offset < lb->blocks[i].start)
return false;
128 if (offset < lb->blocks[i].end)
return true;
142 for (; len > 0; len--) {
154 if (!(((*a >=
'a') && (*a <=
'z')) || ((*a >=
'A') && (*a <=
'Z'))))
return false;
155 if (!(((*b >=
'a') && (*b <=
'z')) || ((*b >=
'A') && (*b <=
'Z'))))
return false;
161 if (((*a)^(*b)) != 0x20) {
270 uint8_t const *q, *ptr, *suffix, *search;
272 bool compressed =
false;
277 if (!*label || (*label > 63)) {
285 next = label + *label + 1;
304 search = *new_search;
375 if (ptr > end)
return false;
401 if ((q - packet) > (1 << 14))
return false;
407 if (!
labelcmp(q + 1, label + 1, *label)) {
421 offset = (q - packet);
422 label[0] = (offset >> 8) | 0xc0;
423 label[1] = offset & 0xff;
424 *label_end = label + 2;
425 if (new_search) *new_search = search;
457 suffix = packet + ((
next[0] & ~0xc0) << 8) +
next[1];
509 if (ptr > end)
return compressed;
538 if ((ptr[0] !=
next[0]) ||
539 (ptr[1] !=
next[1])) {
557 if ((q - packet) > (1 << 14))
return compressed;
563 if (!
labelcmp(q + 1, label + 1, *label)) {
577 offset = (q - packet);
578 label[0] = (offset >> 8) | 0xc0;
579 label[1] = offset & 0xff;
580 *label_end = label + 2;
581 if (new_search) *new_search = search;
610 if (slen < 0)
return 0;
612 if (slen == 0)
return -need;
643 uint8_t const *end = buf + buf_len;
644 uint8_t const *q, *strend, *last;
646 bool underscore =
true;
648 if (!buf || !buf_len || !where || !
value) {
656 if (!((where >= buf) && (where < (buf + buf_len)))) {
675 if ((
value->vb_length == 0) ||
676 ((
value->vb_length == 1) && (
value->vb_strvalue[0] ==
'.'))) {
690 strend = q +
value->vb_length;
708 if (*q ==
'_')
goto next;
717 if ((q + 1) == strend) {
734 }
else if (!((*q ==
'-') || ((*q >=
'0') && (*q <=
'9')) ||
735 ((*q >=
'A') && (*q <=
'Z')) || ((*q >=
'a') && (*q <=
'z')))) {
743 if ((q - last) > 63) {
759 if ((where + (strend - q) + 2) > end) {
760 if (need) *need = (where + (strend - q) + 2) - buf;
806 if (compression && ((
data - where) > 2)) {
832 for (i = 0; i < lb->
num; i++) {
836 value->vb_strvalue, i,
844 if (*(where + *where + 1) >= 0xc0) {
852 }
else if (buf != where) {
886 uint8_t const *p, *q, *end, *label_end;
889 bool at_first_label, already_set_next;
891 if (!packet || !buf || (buf_len == 0) || !
next) {
901 if (!((start >= packet) && (start < (buf + buf_len)))) {
909 at_first_label =
true;
910 already_set_next =
false;
926 if (at_first_label) length++;
935 already_set_next =
true;
946 if ((p + 1) >= end)
goto overflow;
951 if ((*p > 63) && (*p < 0xc0)) {
953 return -(p - packet);
965 return -(p - packet);
969 offset += ((*p & ~0xc0) << 8);
992 if (offset >= (p - packet)) {
994 offset, (
int) (p - packet));
995 return -(p - packet);
1013 offset, (
int) (p - packet));
1014 return -(p - packet);
1023 offset, (
int) (p - packet));
1024 return -(p - packet);
1033 fr_strerror_printf(
"Pointer %04x at offset %04x does not point to the start of a label",
1034 offset, (
int) (p - packet));
1035 return -(p - packet);
1043 (
int) (p - packet));
1044 return -(p - packet);
1055 already_set_next =
true;
1065 if ((p + *p + 1) > end)
goto overflow;
1076 if (!at_first_label) length++;
1077 at_first_label =
false;
1085 return -(p - packet);
1100 while (q < label_end) {
1101 if (!((*q ==
'-') || ((*q >=
'0') && (*q <=
'9')) ||
1102 ((*q >=
'A') && (*q <=
'Z')) || ((*q >=
'a') && (*q <=
'z')))) {
1104 return -(q - packet);
1116 if (!already_set_next) *
next = p;
1141 uint8_t const *end = buf + buf_len;
1143 while (label < end) {
1144 if (*label == 0x00) {
1150 if (slen <= 0)
return slen;
1162 if (end == packet)
return -1;
1175 if ((end - packet) < 2) {
1176 return -(p - packet);
1180 offset += ((*p & ~0xc0) << 8);
1182 q = packet + offset;
1184 return -(p - packet);
1192 if (*p > 63)
return -(p - packet);
1194 if ((p + *p + 1) > end) {
1195 return -(p - packet);
1233 uint8_t const *end = packet + len;
1237 if (!len)
return -1;
1243 if ((label < src) || (label >= end))
return -1;
1249 if (lb) packet = lb->
start;
1257 FR_PROTO_TRACE(
"dns_label_to_value_box - Failed getting length");
1270 return after - label;
1288 if (slen < 0)
return slen;
1294 if ((p + slen) > (
uint8_t *) q) {
1295 FR_PROTO_TRACE(
"dns_label_to_value_box - length %zd Failed at %d", slen, __LINE__);
1306 if (p != (
uint8_t const *) dst->vb_strvalue) {
1328 FR_PROTO_TRACE(
"dns_label_to_value_box - Failed at %d", __LINE__);
1338 return after - label;
#define fr_dbuff_advance(_dbuff_or_marker, _len)
Advance 'current' position in dbuff or marker by _len bytes.
#define fr_dbuff_remaining(_dbuff_or_marker)
Return the number of bytes remaining between the dbuff or marker and the end of the buffer.
fr_dcursor_iter_t void * current
ssize_t fr_dns_label_uncompressed_length(uint8_t const *packet, uint8_t const *buf, size_t buf_len, uint8_t const **next, fr_dns_labels_t *lb)
Get the uncompressed length of a DNS label in a network buffer.
ssize_t fr_dns_label_from_value_box_dbuff(fr_dbuff_t *dbuff, bool compression, fr_value_box_t const *value, fr_dns_labels_t *lb)
Encode a single value box of type string, serializing its contents to a dns label in a dbuff.
ssize_t fr_dns_label_from_value_box(size_t *need, uint8_t *buf, size_t buf_len, uint8_t *where, bool compression, fr_value_box_t const *value, fr_dns_labels_t *lb)
Encode a single value box of type string, serializing its contents to a dns label.
static void dns_label_mark(fr_dns_labels_t *lb, uint8_t const *p)
ssize_t fr_dns_labels_network_verify(uint8_t const *packet, uint8_t const *buf, size_t buf_len, uint8_t const *start, fr_dns_labels_t *lb)
Verify that a network buffer contains valid DNS labels.
static int dns_label_add(fr_dns_labels_t *lb, uint8_t const *start, uint8_t const *end)
ssize_t fr_dns_label_to_value_box(TALLOC_CTX *ctx, fr_value_box_t *dst, uint8_t const *src, size_t len, uint8_t const *label, bool tainted, fr_dns_labels_t *lb)
Decode a fr_value_box_t from one DNS label.
static bool dns_label_compress(uint8_t const *packet, uint8_t const *start, uint8_t const *end, uint8_t const **new_search, uint8_t *label, uint8_t **label_end)
Compress "label" by looking at the label recursively.
static bool dns_pointer_valid(fr_dns_labels_t *lb, uint16_t offset)
static ssize_t dns_label_decode(uint8_t const *packet, uint8_t const *end, uint8_t const **start, uint8_t const **next)
static bool labelcmp(uint8_t const *a, uint8_t const *b, size_t len)
Compare two labels in a case-insensitive fashion.
uint8_t const * start
start of packet
uint8_t const * end
end of the packet
fr_dns_block_t * blocks
maximum number of labels
uint8_t * mark
markup buffer used for decoding.
int num
number of used labels
@ FR_TYPE_STRING
String of printable characters.
#define FR_PROTO_TRACE(_fmt,...)
#define fr_strerror_printf(_fmt,...)
Log to thread local error buffer.
#define fr_strerror_const(_msg)
int fr_value_box_bstr_alloc(TALLOC_CTX *ctx, char **out, fr_value_box_t *dst, fr_dict_attr_t const *enumv, size_t len, bool tainted)
Alloc and assign an empty \0 terminated string to a fr_value_box_t.
void fr_value_box_clear(fr_value_box_t *data)
Clear/free any existing value and metadata.
#define fr_value_box_init_null(_vb)
Initialise an empty/null box that will be filled later.