summaryrefslogtreecommitdiff
path: root/src/resolve/resolved-dns-packet.c
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2015-12-02 20:58:51 +0100
committerLennart Poettering <lennart@poettering.net>2015-12-02 22:50:11 +0100
commita8812dd7f161a3e459c1730ac92ff2bbc9986ff1 (patch)
treec48b5b2d7e71894d01ecb35479342598f9a97986 /src/resolve/resolved-dns-packet.c
parent9551c15505e283f9e5e43635c2920bfdfc584c30 (diff)
resolved: add code to generate the wire format for a single RR
This adds dns_resource_record_to_wire_format() that generates the raw wire-format of a single DnsResourceRecord object, and caches it in the object, optionally in DNSSEC canonical form. This call is used later to generate the RR serialization of RRs to verify. This adds four new fields to DnsResourceRecord objects: - wire_format points to the buffer with the wire-format version of the RR - wire_format_size stores the size of that buffer - wire_format_rdata_offset specifies the index into the buffer where the RDATA of the RR begins (i.e. the size of the key part of the RR). - wire_format_canonical is a boolean that stores whether the cached wire format is in DNSSEC canonical form or not. Note that this patch adds a mode where a DnsPacket is allocated on the stack (instead of on the heap), so that it is cheaper to reuse the DnsPacket object for generating this wire format. After all we reuse the DnsPacket object for this, since it comes with all the dynamic memory management, and serialization calls we need anyway.
Diffstat (limited to 'src/resolve/resolved-dns-packet.c')
-rw-r--r--src/resolve/resolved-dns-packet.c40
1 files changed, 33 insertions, 7 deletions
diff --git a/src/resolve/resolved-dns-packet.c b/src/resolve/resolved-dns-packet.c
index 06464324d2..75f31b80f6 100644
--- a/src/resolve/resolved-dns-packet.c
+++ b/src/resolve/resolved-dns-packet.c
@@ -108,6 +108,8 @@ DnsPacket *dns_packet_ref(DnsPacket *p) {
if (!p)
return NULL;
+ assert(!p->on_stack);
+
assert(p->n_ref > 0);
p->n_ref++;
return p;
@@ -126,7 +128,9 @@ static void dns_packet_free(DnsPacket *p) {
hashmap_free(p->names);
free(p->_data);
- free(p);
+
+ if (!p->on_stack)
+ free(p);
}
DnsPacket *dns_packet_unref(DnsPacket *p) {
@@ -380,7 +384,7 @@ int dns_packet_append_raw_string(DnsPacket *p, const void *s, size_t size, size_
}
int dns_packet_append_label(DnsPacket *p, const char *d, size_t l, size_t *start) {
- void *w;
+ uint8_t *w;
int r;
assert(p);
@@ -389,12 +393,29 @@ int dns_packet_append_label(DnsPacket *p, const char *d, size_t l, size_t *start
if (l > DNS_LABEL_MAX)
return -E2BIG;
- r = dns_packet_extend(p, 1 + l, &w, start);
+ r = dns_packet_extend(p, 1 + l, (void**) &w, start);
if (r < 0)
return r;
- ((uint8_t*) w)[0] = (uint8_t) l;
- memcpy(((uint8_t*) w) + 1, d, l);
+ *(w++) = (uint8_t) l;
+
+ if (p->canonical_form) {
+ size_t i;
+
+ /* Generate in canonical form, as defined by DNSSEC
+ * RFC 4034, Section 6.2, i.e. all lower-case. */
+
+ for (i = 0; i < l; i++) {
+ if (d[i] >= 'A' && d[i] <= 'Z')
+ w[i] = (uint8_t) (d[i] - 'A' + 'a');
+ else
+ w[i] = (uint8_t) d[i];
+ }
+ } else
+ /* Otherwise, just copy the string unaltered. This is
+ * essential for DNS-SD, where the casing of labels
+ * matters and needs to be retained. */
+ memcpy(w, d, l);
return 0;
}
@@ -647,8 +668,8 @@ fail:
return r;
}
-int dns_packet_append_rr(DnsPacket *p, const DnsResourceRecord *rr, size_t *start) {
- size_t saved_size, rdlength_offset, end, rdlength;
+int dns_packet_append_rr(DnsPacket *p, const DnsResourceRecord *rr, size_t *start, size_t *rdata_start) {
+ size_t saved_size, rdlength_offset, end, rdlength, rds;
int r;
assert(p);
@@ -669,6 +690,8 @@ int dns_packet_append_rr(DnsPacket *p, const DnsResourceRecord *rr, size_t *star
if (r < 0)
goto fail;
+ rds = p->size - saved_size;
+
switch (rr->unparseable ? _DNS_TYPE_INVALID : rr->key->type) {
case DNS_TYPE_SRV:
@@ -947,6 +970,9 @@ int dns_packet_append_rr(DnsPacket *p, const DnsResourceRecord *rr, size_t *star
if (start)
*start = saved_size;
+ if (rdata_start)
+ *rdata_start = rds;
+
return 0;
fail: