Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions dname.c
Original file line number Diff line number Diff line change
Expand Up @@ -717,3 +717,41 @@ dname_make_from_packet_buffered(struct dname_buffer* dname,
assert(wirelen == dname->dname.name_size);
return wirelen;
}

dname_type*
label_plus_dname(const char* label, const dname_type* dname)
{
static struct {
dname_type dname;
uint8_t bytes[MAXDOMAINLEN + 128 /* max number of labels */];
} ATTR_PACKED name;
size_t i, ll;

if (!label || !dname || dname->label_count > 127)
return NULL;
ll = strlen(label);
if ((int)dname->name_size + ll + 1 > MAXDOMAINLEN)
return NULL;

/* In reversed order and first copy with memmove, so we can nest.
* i.e. label_plus_dname(label1, label_plus_dname(label2, dname))
*/
memmove(name.bytes + dname->label_count
+ 1 /* label_count increases by one */
+ 1 /* label type/length byte for label */ + ll,
((char*)dname) + sizeof(dname_type) + dname->label_count,
dname->name_size);
memcpy(name.bytes + dname->label_count
+ 1 /* label_count increases by one */
+ 1 /* label type/length byte for label */, label, ll);
name.bytes[dname->label_count + 1] = ll; /* label type/length byte */
name.bytes[dname->label_count] = 0; /* first label follows last
* label_offsets element */
for (i = 0; i < dname->label_count; i++)
name.bytes[i] = ((uint8_t*)(void*)dname)[sizeof(dname_type)+i]
+ 1 /* label type/length byte for label */ + ll;
name.dname.label_count = dname->label_count + 1 /* label_count incr. */;
name.dname.name_size = dname->name_size + ll
+ 1 /* label length */;
return &name.dname;
}
3 changes: 3 additions & 0 deletions dname.h
Original file line number Diff line number Diff line change
Expand Up @@ -448,4 +448,7 @@ int dname_make_buffered(struct dname_buffer* dname, uint8_t *name,
int dname_make_from_packet_buffered(struct dname_buffer* dname,
buffer_type *packet, int allow_pointers, int normalize);

/** return (static) dname with label prepended to dname */
dname_type* label_plus_dname(const char* label,const dname_type* dname);

#endif /* DNAME_H */
2 changes: 2 additions & 0 deletions edns.c
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ edns_init_record(edns_record_type *edns)
edns->dnssec_ok = 0;
edns->nsid = 0;
edns->zoneversion = 0;
edns->backend_version_rr = NULL;
edns->backend_version_len = 0;
edns->padding = 0;
edns->cookie_status = COOKIE_NOT_PRESENT;
edns->cookie_len = 0;
Expand Down
6 changes: 5 additions & 1 deletion edns.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include "buffer.h"
struct nsd;
struct query;
struct rr;

#define OPT_LEN 9U /* Length of the NSD EDNS response record minus 2 */
#define OPT_RDATA 2 /* holds the rdata length comes after OPT_LEN */
Expand All @@ -25,7 +26,8 @@ struct query;
#define DNSSEC_OK_MASK 0x8000U /* do bit mask */

/* https://iana.org/assignments/dns-parameters/#zoneversion-type-values */
#define ZONEVERSION_SOA_SERIAL 0
#define ZONEVERSION_SOA_SERIAL 0
#define ZONEVERSION_BACKEND_SERIAL 247 /* BACKEND-SERIAL ZONEVERSION type */

/* See RFC 8467 */
#define PADDING_BLOCK_SZ 468
Expand Down Expand Up @@ -68,6 +70,8 @@ struct edns_record
int dnssec_ok;
int nsid;
int zoneversion;
struct rr* backend_version_rr;
size_t backend_version_len;
int padding;
cookie_status_type cookie_status;
size_t cookie_len;
Expand Down
74 changes: 64 additions & 10 deletions query.c
Original file line number Diff line number Diff line change
Expand Up @@ -1813,6 +1813,8 @@ void
query_add_optional(query_type *q, nsd_type *nsd, uint32_t *now_p)
{
struct edns_data *edns = &nsd->edns_ipv4;
domain_type *match, *closest_encloser;
rrset_type *rrset;
#if defined(INET6)
if (q->client_addr.ss_family == AF_INET6) {
edns = &nsd->edns_ipv6;
Expand All @@ -1836,11 +1838,42 @@ query_add_optional(query_type *q, nsd_type *nsd, uint32_t *now_p)
6 + ( q->edns.ede_text_len
? q->edns.ede_text_len : 0);

if(q->edns.zoneversion
&& q->zone
&& q->zone->soa_rrset
&& q->zone->soa_rrset->rr_count >= 1
&& q->zone->soa_rrset->rrs[0]->rdlength >= 20 /* 5x 32bit numbers */ +2*sizeof(void*) /* two pointers to domain names */)
if(!q->edns.zoneversion || !q->zone)
; /* pass */
else if(namedb_lookup( nsd->db
, label_plus_dname("_backend-version"
, domain_dname_const(q->zone->apex))
, &match, &closest_encloser)
&& (rrset = domain_find_rrset(match, q->zone, TYPE_TXT))
&& rrset->rr_count == 1) {
uint8_t *rdp = rrset->rrs[0]->rdata;
uint8_t *eo_rd = rrset->rrs[0]->rdata
+ rrset->rrs[0]->rdlength;
while (rdp < eo_rd) {
q->edns.backend_version_len += *rdp;
rdp += *rdp + 1;
}
if(rdp == eo_rd) {
q->edns.backend_version_rr = rrset->rrs[0];
q->edns.opt_reserved_space += sizeof(uint16_t)
+ sizeof(uint16_t)
+ sizeof(uint8_t)
+ sizeof(uint8_t)
+ q->edns.backend_version_len;

} else if(q->zone->soa_rrset
&& q->zone->soa_rrset->rr_count >= 1
&& q->zone->soa_rrset->rrs[0]->rdlength >= 20+2*sizeof(void*)) {
q->edns.opt_reserved_space += sizeof(uint16_t)
+ sizeof(uint16_t)
+ sizeof(uint8_t)
+ sizeof(uint8_t)
+ sizeof(uint32_t);
}
}
else if(q->zone->soa_rrset
&& q->zone->soa_rrset->rr_count >= 1
&& q->zone->soa_rrset->rrs[0]->rdlength >= 20 /* 5x 32bit numbers */ +2*sizeof(void*) /* two pointers to domain names */)
q->edns.opt_reserved_space += sizeof(uint16_t)
+ sizeof(uint16_t)
+ sizeof(uint8_t)
Expand Down Expand Up @@ -1875,11 +1908,32 @@ query_add_optional(query_type *q, nsd_type *nsd, uint32_t *now_p)
/* nsid payload */
buffer_write(q->packet, nsd->nsid, nsd->nsid_len);
}
if(q->edns.zoneversion
&& q->zone
&& q->zone->soa_rrset
&& q->zone->soa_rrset->rr_count >= 1
&& q->zone->soa_rrset->rrs[0]->rdlength >= 20+2*sizeof(void*) /* 5x4 bytes and 2 pointers to domains */ ) {
if(!q->edns.zoneversion || !q->zone)
; /* pass */
else if(q->edns.backend_version_rr) {
uint8_t *rdp = q->edns.backend_version_rr->rdata;
uint8_t *eo_rd = q->edns.backend_version_rr->rdata
+ q->edns.backend_version_rr->rdlength;

buffer_write_u16(q->packet, ZONEVERSION_CODE);
buffer_write_u16( q->packet
, sizeof(uint8_t)
+ sizeof(uint8_t)
+ q->edns.backend_version_len);
buffer_write_u8(q->packet,
domain_dname(q->zone->apex)->label_count - 1);
buffer_write_u8( q->packet
, ZONEVERSION_BACKEND_SERIAL);
while (rdp < eo_rd) {
buffer_write(q->packet, rdp+1, *rdp);
q->edns.backend_version_len += *rdp;
rdp += *rdp + 1;
}
assert(rdp == eo_rd);

} else if(q->zone->soa_rrset
&& q->zone->soa_rrset->rr_count >= 1
&& q->zone->soa_rrset->rrs[0]->rdlength >= 20+2*sizeof(void*) /* 5x4 bytes and 2 pointers to domains */ ) {
uint32_t serial = 0;
buffer_write_u16(q->packet, ZONEVERSION_CODE);
buffer_write_u16( q->packet
Expand Down
41 changes: 0 additions & 41 deletions xfrd-catalog-zones.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,6 @@ static void vmake_catalog_consumer_invalid(
struct xfrd_catalog_consumer_zone *consumer_zone,
const char *format, va_list args);

/** return (static) dname with label prepended to dname */
static dname_type* label_plus_dname(const char* label,const dname_type* dname);

/** delete the catalog member zone */
static void catalog_del_consumer_member_zone(
struct xfrd_catalog_consumer_zone* consumer_zone,
Expand Down Expand Up @@ -304,44 +301,6 @@ make_catalog_consumer_valid(struct xfrd_catalog_consumer_zone *consumer_zone)
}
}

static dname_type*
label_plus_dname(const char* label, const dname_type* dname)
{
static struct {
dname_type dname;
uint8_t bytes[MAXDOMAINLEN + 128 /* max number of labels */];
} ATTR_PACKED name;
size_t i, ll;

if (!label || !dname || dname->label_count > 127)
return NULL;
ll = strlen(label);
if ((int)dname->name_size + ll + 1 > MAXDOMAINLEN)
return NULL;

/* In reversed order and first copy with memmove, so we can nest.
* i.e. label_plus_dname(label1, label_plus_dname(label2, dname))
*/
memmove(name.bytes + dname->label_count
+ 1 /* label_count increases by one */
+ 1 /* label type/length byte for label */ + ll,
((char*)dname) + sizeof(dname_type) + dname->label_count,
dname->name_size);
memcpy(name.bytes + dname->label_count
+ 1 /* label_count increases by one */
+ 1 /* label type/length byte for label */, label, ll);
name.bytes[dname->label_count + 1] = ll; /* label type/length byte */
name.bytes[dname->label_count] = 0; /* first label follows last
* label_offsets element */
for (i = 0; i < dname->label_count; i++)
name.bytes[i] = ((uint8_t*)(void*)dname)[sizeof(dname_type)+i]
+ 1 /* label type/length byte for label */ + ll;
name.dname.label_count = dname->label_count + 1 /* label_count incr. */;
name.dname.name_size = dname->name_size + ll
+ 1 /* label length */;
return &name.dname;
}

static void
catalog_del_consumer_member_zone(
struct xfrd_catalog_consumer_zone* consumer_zone,
Expand Down
Loading