return knot_pkt_reserve(pkt, len);
}
+static inline size_t edns_padding_option_size(int32_t tls_padding)
+{
+ if (tls_padding == -1)
+ /* FIXME: we do not know how to reserve space for the
+ * default padding policy, since we can't predict what
+ * it will select. So i'm just guessing :/ */
+ return KNOT_EDNS_OPTION_HDRLEN + 512;
+ if (tls_padding >= 2)
+ return KNOT_EDNS_OPTION_HDRLEN + tls_padding;
+
+ return 0;
+}
+
static int edns_create(knot_pkt_t *pkt, const struct kr_request *req)
{
pkt->opt_rr = knot_rrset_copy(req->ctx->upstream_opt_rr, &pkt->mm);
}
#endif /* ENABLE_COOKIES */
if (req->qsource.flags.tls) {
- if (req->ctx->tls_padding == -1)
- /* FIXME: we do not know how to reserve space for the
- * default padding policy, since we can't predict what
- * it will select. So i'm just guessing :/ */
- wire_size += KNOT_EDNS_OPTION_HDRLEN + 512;
- if (req->ctx->tls_padding >= 2)
- wire_size += KNOT_EDNS_OPTION_HDRLEN + req->ctx->tls_padding;
+ wire_size += edns_padding_option_size(req->ctx->tls_padding);
}
return knot_pkt_reserve(pkt, wire_size);
}
return err;
}
-/** @internal Add an EDNS padding RR into the answer if requested and required. */
-static int answer_padding(struct kr_request *request)
+static int pkt_padding(knot_pkt_t *packet, int32_t padding)
{
- if (kr_fails_assert(request && request->answer && request->ctx))
- return kr_error(EINVAL);
- if (!request->qsource.flags.tls) {
- /* Not meaningful to pad without encryption. */
- return kr_ok();
- }
- int32_t padding = request->ctx->tls_padding;
- knot_pkt_t *answer = request->answer;
- knot_rrset_t *opt_rr = answer->opt_rr;
+ knot_rrset_t *opt_rr = packet->opt_rr;
int32_t pad_bytes = -1;
if (padding == -1) { /* use the default padding policy from libknot */
- pad_bytes = knot_pkt_default_padding_size(answer, opt_rr);
+ pad_bytes = knot_pkt_default_padding_size(packet, opt_rr);
}
if (padding >= 2) {
- int32_t max_pad_bytes = knot_edns_get_payload(opt_rr) - (answer->size + knot_rrset_size(opt_rr));
- pad_bytes = MIN(knot_edns_alignment_size(answer->size, knot_rrset_size(opt_rr), padding),
+ int32_t max_pad_bytes = knot_edns_get_payload(opt_rr) - (packet->size + knot_rrset_size(opt_rr));
+ pad_bytes = MIN(knot_edns_alignment_size(packet->size, knot_rrset_size(opt_rr), padding),
max_pad_bytes);
}
uint8_t zeros[MAX(1, pad_bytes)];
memset(zeros, 0, sizeof(zeros));
int r = knot_edns_add_option(opt_rr, KNOT_EDNS_OPTION_PADDING,
- pad_bytes, zeros, &answer->mm);
+ pad_bytes, zeros, &packet->mm);
if (r != KNOT_EOK) {
- knot_rrset_clear(opt_rr, &answer->mm);
+ knot_rrset_clear(opt_rr, &packet->mm);
return kr_error(r);
}
}
return kr_ok();
}
+/** @internal Add an EDNS padding RR into the answer if requested and required. */
+static int answer_padding(struct kr_request *request)
+{
+ if (kr_fails_assert(request && request->answer && request->ctx))
+ return kr_error(EINVAL);
+ if (!request->qsource.flags.tls) {
+ /* Not meaningful to pad without encryption. */
+ return kr_ok();
+ }
+ return pkt_padding(request->answer, request->ctx->tls_padding);
+}
+
/* Make a clean SERVFAIL answer. */
static void answer_fail(struct kr_request *request)
{
/* Write down OPT unless in safemode */
if (!(qry->flags.NO_EDNS)) {
+ /* TLS padding */
+ if (transport->protocol == KR_TRANSPORT_TLS) {
+ size_t padding_size = edns_padding_option_size(request->ctx->tls_padding);
+ ret = knot_pkt_reserve(packet, padding_size);
+ if (ret)
+ return kr_error(EINVAL);
+ ret = pkt_padding(packet, request->ctx->tls_padding);
+ if (ret)
+ return kr_error(EINVAL);
+ }
+
ret = edns_put(packet, true);
if (ret != 0) {
return kr_error(EINVAL);