max\-ipv4\-udp\-payload: SIZE
max\-ipv6\-udp\-payload: SIZE
edns\-client\-subnet: BOOL
+ answer\-rotation: BOOL
listen: ADDR[@INT] ...
.ft P
.fi
\fIDefault:\fP 4096
.SS edns\-client\-subnet
.sp
-Enable or disable EDNS Client Subnet support. If enabled, responses to queries containing the EDNS Client Subnet option
+Enable or disable EDNS Client Subnet support. If enabled, responses to queries
+containing the EDNS Client Subnet option
always contain a valid EDNS Client Subnet option according to \fI\%RFC 7871\fP\&.
.sp
\fIDefault:\fP off
+.SS answer\-rotation
+.sp
+Enable or disable sorted\-rrset rotation in the answer section of normal replies.
+The rotation shift is simply determined by a query ID.
+.sp
+\fIDefault:\fP off
.SS listen
.sp
One or more IP addresses where the server listens for incoming queries.
max-ipv4-udp-payload: SIZE
max-ipv6-udp-payload: SIZE
edns-client-subnet: BOOL
+ answer-rotation: BOOL
listen: ADDR[@INT] ...
.. _server_identity:
edns-client-subnet
------------------
-Enable or disable EDNS Client Subnet support. If enabled, responses to queries containing the EDNS Client Subnet option
+Enable or disable EDNS Client Subnet support. If enabled, responses to queries
+containing the EDNS Client Subnet option
always contain a valid EDNS Client Subnet option according to :rfc:`7871`.
*Default:* off
+.. _server_answer-rotation:
+
+answer-rotation
+---------------
+
+Enable or disable sorted-rrset rotation in the answer section of normal replies.
+The rotation shift is simply determined by a query ID.
+
+*Default:* off
+
.. _server_listen:
listen
val = conf_get(conf, C_SRV, C_ECS);
conf->cache.use_ecs = conf_bool(&val);
+
+ val = conf_get(conf, C_SRV, C_ANS_ROTATION);
+ conf->cache.srv_ans_rotate = conf_bool(&val);
}
int conf_new(
int32_t ctl_timeout;
conf_val_t srv_nsid;
bool use_ecs;
+ bool srv_ans_rotate;
} cache;
/*! List of dynamically loaded modules. */
{ C_LISTEN, YP_TADDR, YP_VADDR = { 53 }, YP_FMULTI },
{ C_COMMENT, YP_TSTR, YP_VNONE },
{ C_ECS, YP_TBOOL, YP_VNONE },
+ { C_ANS_ROTATION, YP_TBOOL, YP_VNONE },
{ NULL }
};
#define C_ACTION "\x06""action"
#define C_ADDR "\x07""address"
#define C_ALG "\x09""algorithm"
+#define C_ANS_ROTATION "\x0F""answer-rotation"
#define C_ANY "\x03""any"
#define C_APPEND "\x06""append"
#define C_ASYNC_START "\x0B""async-start"
to_add = *rr;
}
+ uint16_t rotate = conf()->cache.srv_ans_rotate ? knot_wire_get_id(qdata->query->wire) : 0;
uint16_t prev_count = pkt->rrset_count;
- ret = knot_pkt_put(pkt, compr_hint, &to_add, flags);
+ ret = knot_pkt_put_rotate(pkt, compr_hint, &to_add, rotate, flags);
if (ret != KNOT_EOK && (flags & KNOT_PF_FREE)) {
knot_rrset_clear(&to_add, &pkt->mm);
return ret;
"server.max-udp-payload\n"
"server.max-ipv4-udp-payload\n"
"server.max-ipv6-udp-payload\n"
- "server.edns-client-subnet";
+ "server.edns-client-subnet\n"
+ "server.answer-rotation";
ok(strcmp(ref, out) == 0, "compare result");
}
{ C_MAX_IPV4_UDP_PAYLOAD, YP_TINT, YP_VNONE },
{ C_MAX_IPV6_UDP_PAYLOAD, YP_TINT, YP_VNONE },
{ C_ECS, YP_TBOOL, YP_VNONE },
+ { C_ANS_ROTATION, YP_TBOOL, YP_VNONE },
{ NULL }
};