along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include <ctype.h>
#include <sys/time.h>
#include <libknot/descriptor.h>
return qname;
}
-/* Randomize QNAME letter case.
- * This adds 32 bits of randomness at maximum, but that's more than an average domain name length.
- * https://tools.ietf.org/html/draft-vixie-dnsext-dns0x20-00
- */
-static void randomized_qname_case(knot_dname_t *qname, unsigned secret)
-{
- unsigned k = 0;
- while (*qname != '\0') {
- for (unsigned i = *qname; i--;) {
- int chr = qname[i + 1];
- if (isalpha(chr)) {
- if (secret & (1 << k)) {
- qname[i + 1] ^= 0x20;
- }
- k = (k + 1) % (sizeof(secret) * CHAR_BIT);
- }
- }
- qname = (uint8_t *)knot_wire_next_label(qname, NULL);
- }
-}
-
/** Answer is paired to query. */
static bool is_paired_to_query(const knot_pkt_t *answer, struct kr_query *query)
{
uint16_t qtype = query->stype;
- const knot_dname_t *qname_min = minimized_qname(query, &qtype);
-
- /* Construct expected randomized QNAME */
- uint8_t qname[KNOT_DNAME_MAXLEN];
- knot_dname_to_wire(qname, qname_min, sizeof(qname));
- if (!(query->flags & (QUERY_CACHED|QUERY_SAFEMODE))) {
- randomized_qname_case(qname, query->secret);
- }
+ const knot_dname_t *qname = minimized_qname(query, &qtype);
return query->id == knot_wire_get_id(answer->wire) &&
(query->sclass == KNOT_CLASS_ANY || query->sclass == knot_pkt_qclass(answer)) &&
return ret;
}
- /* Randomize query case (if not in safemode) */
- query->secret = (query->flags & QUERY_SAFEMODE) ? 0 : kr_rand_uint(UINT32_MAX);
- knot_dname_t *qname_raw = (knot_dname_t *)knot_pkt_qname(pkt);
- randomized_qname_case(qname_raw, query->secret);
-
/* Query built, expect answer. */
query->id = kr_rand_uint(UINT16_MAX);
knot_wire_set_id(pkt->wire, query->id);
return KNOT_STATE_DONE;
}
- /* Packet cleared, normalize QNAME. */
- knot_dname_t *qname_raw = (knot_dname_t *)knot_pkt_qname(pkt);
- knot_dname_to_lower(qname_raw);
-
/* Check response code. */
#ifndef NDEBUG
lookup_table_t *rcode = lookup_by_id(knot_rcode_names, knot_wire_get_rcode(pkt->wire));
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <ctype.h>
#include <stdio.h>
#include <fcntl.h>
#include <libknot/rrtype/rdname.h>
#define DEBUG_MSG(fmt...) QRDEBUG(kr_rplan_current(rplan), "resl", fmt)
+/* Randomize QNAME letter case.
+ * This adds 32 bits of randomness at maximum, but that's more than an average domain name length.
+ * https://tools.ietf.org/html/draft-vixie-dnsext-dns0x20-00
+ */
+static void randomized_qname_case(knot_dname_t *qname, unsigned secret)
+{
+ unsigned k = 0;
+ while (*qname != '\0') {
+ for (unsigned i = *qname; i--;) {
+ int chr = qname[i + 1];
+ if (isalpha(chr)) {
+ if (secret & (1 << k)) {
+ qname[i + 1] ^= 0x20;
+ }
+ k = (k + 1) % (sizeof(secret) * CHAR_BIT);
+ }
+ }
+ qname = (uint8_t *)knot_wire_next_label(qname, NULL);
+ }
+}
+
/** @internal Subtract time (best effort) */
float time_diff(struct timeval *begin, struct timeval *end)
{
static int query_finalize(struct kr_request *request, knot_pkt_t *pkt)
{
- int ret = 0;
+ /* Randomize query case (if not in safemode) */
struct kr_query *qry = kr_rplan_current(&request->rplan);
+ qry->secret = (qry->flags & QUERY_SAFEMODE) ? 0 : kr_rand_uint(UINT32_MAX);
+ knot_dname_t *qname_raw = (knot_dname_t *)knot_pkt_qname(pkt);
+ randomized_qname_case(qname_raw, qry->secret);
+
+ int ret = 0;
knot_pkt_begin(pkt, KNOT_ADDITIONAL);
if (!(qry->flags & QUERY_SAFEMODE)) {
ret = edns_create(pkt, request->answer);
return KNOT_STATE_CONSUME; /* Try again */
}
} else {
+ /* Packet cleared, derandomize QNAME. */
+ knot_dname_t *qname_raw = (knot_dname_t *)knot_pkt_qname(packet);
+ if (qname_raw && qry->secret != 0) {
+ randomized_qname_case(qname_raw, qry->secret);
+ }
state = knot_overlay_consume(&request->overlay, packet);
}
int state = knot_overlay_produce(&request->overlay, packet);
if (state != KNOT_STATE_FAIL && knot_wire_get_qr(packet->wire)) {
/* Produced an answer, consume it. */
+ qry->secret = 0;
request->overlay.state = KNOT_STATE_CONSUME;
state = knot_overlay_consume(&request->overlay, packet);
}
return KNOT_STATE_PRODUCE;
}
+ /* Prepare additional query */
+ int ret = query_finalize(request, packet);
+ if (ret != 0) {
+ return KNOT_STATE_FAIL;
+ }
+
#ifndef NDEBUG
char qname_str[KNOT_DNAME_MAXLEN], zonecut_str[KNOT_DNAME_MAXLEN], ns_str[SOCKADDR_STRLEN];
knot_dname_to_str(qname_str, knot_pkt_qname(packet), sizeof(qname_str));
DEBUG_MSG("=> querying: '%s' score: %u zone cut: '%s' m12n: '%s'\n", ns_str, qry->ns.score, zonecut_str, qname_str);
#endif
- /* Prepare additional query */
- int ret = query_finalize(request, packet);
- if (ret != 0) {
- return KNOT_STATE_FAIL;
- }
gettimeofday(&qry->timestamp, NULL);
*dst = &qry->ns.addr.ip;
*type = (qry->flags & QUERY_TCP) ? SOCK_STREAM : SOCK_DGRAM;