aboutsummaryrefslogtreecommitdiff
path: root/util/data/msgencode.c
diff options
context:
space:
mode:
Diffstat (limited to 'util/data/msgencode.c')
-rw-r--r--util/data/msgencode.c63
1 files changed, 50 insertions, 13 deletions
diff --git a/util/data/msgencode.c b/util/data/msgencode.c
index 1746cfbb8fab..5f297b551bfb 100644
--- a/util/data/msgencode.c
+++ b/util/data/msgencode.c
@@ -454,6 +454,7 @@ packed_rrset_encode(struct ub_packed_rrset_key* key, sldns_buffer* pkt,
size_t i, j, owner_pos;
int r, owner_labs;
uint16_t owner_ptr = 0;
+ time_t adjust = 0;
struct packed_rrset_data* data = (struct packed_rrset_data*)
key->entry.data;
@@ -464,9 +465,12 @@ packed_rrset_encode(struct ub_packed_rrset_key* key, sldns_buffer* pkt,
owner_labs = dname_count_labels(key->rk.dname);
owner_pos = sldns_buffer_position(pkt);
- /* For an rrset with a fixed TTL, use the rrset's TTL as given */
+ /** Determine relative time adjustment for TTL values.
+ * For an rrset with a fixed TTL, use the rrset's TTL as given. */
if((key->rk.flags & PACKED_RRSET_FIXEDTTL) != 0)
- timenow = 0;
+ adjust = 0;
+ else
+ adjust = SERVE_ORIGINAL_TTL ? data->ttl_add : timenow;
if(do_data) {
const sldns_rr_descriptor* c = type_rdata_compressable(key);
@@ -479,11 +483,10 @@ packed_rrset_encode(struct ub_packed_rrset_key* key, sldns_buffer* pkt,
return r;
sldns_buffer_write(pkt, &key->rk.type, 2);
sldns_buffer_write(pkt, &key->rk.rrset_class, 2);
- if(data->rr_ttl[j] < timenow)
+ if(data->rr_ttl[j] < adjust)
sldns_buffer_write_u32(pkt,
SERVE_EXPIRED?SERVE_EXPIRED_REPLY_TTL:0);
- else sldns_buffer_write_u32(pkt,
- data->rr_ttl[j]-timenow);
+ else sldns_buffer_write_u32(pkt, data->rr_ttl[j]-adjust);
if(c) {
if((r=compress_rdata(pkt, data->rr_data[j],
data->rr_len[j], region, tree, c))
@@ -517,11 +520,10 @@ packed_rrset_encode(struct ub_packed_rrset_key* key, sldns_buffer* pkt,
}
sldns_buffer_write_u16(pkt, LDNS_RR_TYPE_RRSIG);
sldns_buffer_write(pkt, &key->rk.rrset_class, 2);
- if(data->rr_ttl[i] < timenow)
+ if(data->rr_ttl[i] < adjust)
sldns_buffer_write_u32(pkt,
SERVE_EXPIRED?SERVE_EXPIRED_REPLY_TTL:0);
- else sldns_buffer_write_u32(pkt,
- data->rr_ttl[i]-timenow);
+ else sldns_buffer_write_u32(pkt, data->rr_ttl[i]-adjust);
/* rrsig rdata cannot be compressed, perform 100+ byte
* memcopy. */
sldns_buffer_write(pkt, data->rr_data[i],
@@ -801,14 +803,14 @@ calc_edns_field_size(struct edns_data* edns)
return 1 + 2 + 2 + 4 + 2 + rdatalen;
}
-void
-attach_edns_record(sldns_buffer* pkt, struct edns_data* edns)
+static void
+attach_edns_record_max_msg_sz(sldns_buffer* pkt, struct edns_data* edns,
+ uint16_t max_msg_sz)
{
size_t len;
size_t rdatapos;
struct edns_option* opt;
- if(!edns || !edns->edns_present)
- return;
+ struct edns_option* padding_option = NULL;
/* inc additional count */
sldns_buffer_write_u16_at(pkt, 10,
sldns_buffer_read_u16_at(pkt, 10) + 1);
@@ -826,17 +828,52 @@ attach_edns_record(sldns_buffer* pkt, struct edns_data* edns)
sldns_buffer_write_u16(pkt, 0); /* rdatalen */
/* write rdata */
for(opt=edns->opt_list; opt; opt=opt->next) {
+ if (opt->opt_code == LDNS_EDNS_PADDING) {
+ padding_option = opt;
+ continue;
+ }
sldns_buffer_write_u16(pkt, opt->opt_code);
sldns_buffer_write_u16(pkt, opt->opt_len);
if(opt->opt_len != 0)
sldns_buffer_write(pkt, opt->opt_data, opt->opt_len);
}
+ if (padding_option && edns->padding_block_size ) {
+ size_t pad_pos = sldns_buffer_position(pkt);
+ size_t msg_sz = ((pad_pos + 3) / edns->padding_block_size + 1)
+ * edns->padding_block_size;
+ size_t pad_sz;
+
+ if (msg_sz > max_msg_sz)
+ msg_sz = max_msg_sz;
+
+ /* By use of calc_edns_field_size, calling functions should
+ * have made sure that there is enough space for at least a
+ * zero sized padding option.
+ */
+ log_assert(pad_pos + 4 <= msg_sz);
+
+ pad_sz = msg_sz - pad_pos - 4;
+ sldns_buffer_write_u16(pkt, LDNS_EDNS_PADDING);
+ sldns_buffer_write_u16(pkt, pad_sz);
+ if (pad_sz) {
+ memset(sldns_buffer_current(pkt), 0, pad_sz);
+ sldns_buffer_skip(pkt, pad_sz);
+ }
+ }
if(edns->opt_list)
sldns_buffer_write_u16_at(pkt, rdatapos,
sldns_buffer_position(pkt)-rdatapos-2);
sldns_buffer_flip(pkt);
}
+void
+attach_edns_record(sldns_buffer* pkt, struct edns_data* edns)
+{
+ if(!edns || !edns->edns_present)
+ return;
+ attach_edns_record_max_msg_sz(pkt, edns, edns->udp_size);
+}
+
int
reply_info_answer_encode(struct query_info* qinf, struct reply_info* rep,
uint16_t id, uint16_t qflags, sldns_buffer* pkt, time_t timenow,
@@ -885,7 +922,7 @@ reply_info_answer_encode(struct query_info* qinf, struct reply_info* rep,
}
if(attach_edns && sldns_buffer_capacity(pkt) >=
sldns_buffer_limit(pkt)+attach_edns)
- attach_edns_record(pkt, edns);
+ attach_edns_record_max_msg_sz(pkt, edns, udpsize+attach_edns);
return 1;
}