[Opendnssec-commits] [svn.opendnssec.org/svn/dnssec] r6096 - trunk/OpenDNSSEC/signer/src/wire

matthijs at nlnetlabs.nl matthijs at nlnetlabs.nl
Wed Jan 25 16:47:05 CET 2012


Author: matthijs
Date: 2012-01-25 16:47:05 +0100 (Wed, 25 Jan 2012)
New Revision: 6096

Modified:
   trunk/OpenDNSSEC/signer/src/wire/axfr.c
   trunk/OpenDNSSEC/signer/src/wire/query.c
   trunk/OpenDNSSEC/signer/src/wire/query.h
Log:
OPENDNSSEC-149: IXFR (as part of DNS Output Adapter)
- read serial from ixfr request and return correct ixfr



Modified: trunk/OpenDNSSEC/signer/src/wire/axfr.c
===================================================================
--- trunk/OpenDNSSEC/signer/src/wire/axfr.c	2012-01-25 09:45:06 UTC (rev 6095)
+++ trunk/OpenDNSSEC/signer/src/wire/axfr.c	2012-01-25 15:47:05 UTC (rev 6096)
@@ -35,6 +35,7 @@
 #include "adapter/addns.h"
 #include "adapter/adutil.h"
 #include "shared/file.h"
+#include "shared/util.h"
 #include "wire/axfr.h"
 #include "wire/buffer.h"
 #include "wire/query.h"
@@ -246,6 +247,9 @@
     unsigned l = 0;
     long fpos = 0;
     size_t bufpos = 0;
+    uint32_t new_serial = 0;
+    unsigned del_mode = 0;
+    unsigned soa_found = 0;
     ods_log_assert(q);
     ods_log_assert(q->buffer);
     ods_log_assert(engine);
@@ -301,7 +305,11 @@
             buffer_pkt_set_rcode(q->buffer, LDNS_RCODE_SERVFAIL);
             return QUERY_PROCESSED;
         }
+        /* newest serial */
+        new_serial = ldns_rdf2native_int32(
+            ldns_rr_rdf(rr, SE_SOA_RDATA_SERIAL));
         /* does it fit? */
+        buffer_set_position(q->buffer, q->startpos);
         if (buffer_write_rr(q->buffer, rr)) {
             ods_log_debug("[%s] set soa in ixfr zone %s", axfr_str,
                 q->zone->name);
@@ -318,6 +326,9 @@
             buffer_pkt_set_rcode(q->buffer, LDNS_RCODE_SERVFAIL);
             return QUERY_PROCESSED;
         }
+        if (util_serial_gt(q->serial, new_serial)) {
+            goto axfr_fallback;
+        }
     } else if (q->tcp) {
         /* subsequent ixfr packets */
         ods_log_debug("[%s] subsequent ixfr packet zone %s", axfr_str,
@@ -331,6 +342,7 @@
     fpos = ftell(q->axfr_fd);
     while ((rr = addns_read_rr(q->axfr_fd, line, &orig, &prev, &ttl,
         &status, &l)) != NULL) {
+        ods_log_deeebug("[%s] read rr at line %d", axfr_str, l);
         if (status != LDNS_STATUS_OK) {
             ldns_rr_free(rr);
             rr = NULL;
@@ -338,18 +350,34 @@
                 axfr_str, l, ldns_get_errorstr_by_id(status), line);
             goto axfr_fallback;
         }
+        if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_SOA) {
+            del_mode = !del_mode;
+        }
+        if (!soa_found) {
+            if (del_mode && ldns_rr_get_type(rr) == LDNS_RR_TYPE_SOA &&
+                q->serial == ldns_rdf2native_int32(
+                ldns_rr_rdf(rr, SE_SOA_RDATA_SERIAL))) {
+                soa_found = 1;
+            } else {
+                ods_log_deeebug("[%s] soa not found for rr at line %d",
+                    axfr_str, l);
+                continue;
+            }
+        }
         /* does it fit? */
         if (buffer_write_rr(q->buffer, rr)) {
+            ods_log_deeebug("[%s] add rr at line %d", axfr_str, l);
             fpos = ftell(q->axfr_fd);
             buffer_pkt_set_ancount(q->buffer, buffer_pkt_ancount(q->buffer)+1);
             total_added++;
             ldns_rr_free(rr);
             rr = NULL;
         } else {
+            ods_log_deeebug("[%s] rr at line %d does not fit", axfr_str, l);
             ldns_rr_free(rr);
             rr = NULL;
             if (fseek(q->axfr_fd, fpos, SEEK_SET) != 0) {
-                ods_log_error("[%s] unable to reset file position in axfr "
+                ods_log_error("[%s] unable to reset file position in ixfr "
                     "file: fseek() failed (%s)", axfr_str, strerror(errno));
                 buffer_pkt_set_rcode(q->buffer, LDNS_RCODE_SERVFAIL);
                 return QUERY_PROCESSED;
@@ -360,6 +388,9 @@
             }
         }
     }
+    if (!soa_found) {
+        goto axfr_fallback;
+    }
     ods_log_debug("[%s] ixfr zone %s is done", axfr_str, q->zone->name);
     q->tsig_sign_it = 1; /* sign last packet */
     q->axfr_is_done = 1;
@@ -380,6 +411,7 @@
     return QUERY_IXFR;
 
 axfr_fallback:
+    buffer_set_position(q->buffer, q->startpos);
     if (q->tcp) {
         ods_log_info("[%s] axfr fallback zone %s", axfr_str, q->zone->name);
         if (q->axfr_fd) {

Modified: trunk/OpenDNSSEC/signer/src/wire/query.c
===================================================================
--- trunk/OpenDNSSEC/signer/src/wire/query.c	2012-01-25 09:45:06 UTC (rev 6095)
+++ trunk/OpenDNSSEC/signer/src/wire/query.c	2012-01-25 15:47:05 UTC (rev 6096)
@@ -102,6 +102,8 @@
     /* domain, opcode, cname count, delegation, compression, temp */
     q->axfr_is_done = 0;
     q->axfr_fd = NULL;
+    q->serial = 0;
+    q->startpos = 0;
     return;
 }
 
@@ -354,6 +356,48 @@
 
 
 /**
+ * IXFR.
+ *
+ */
+static query_state
+query_process_ixfr(query_type* q)
+{
+    uint16_t count = 0;
+    uint16_t rrcount = 0;
+    ods_log_assert(q);
+    ods_log_assert(q->buffer);
+    ods_log_assert(buffer_pkt_qdcount(q->buffer) == 1);
+    /* skip header and question section */
+    buffer_skip(q->buffer, BUFFER_PKT_HEADER_SIZE);
+    if (!buffer_skip_rr(q->buffer, 1)) {
+        ods_log_error("[%s] dropped packet: zone %s received bad ixfr "
+            "request (bad question section)", query_str, q->zone->name);
+        return QUERY_DISCARDED;
+    }
+    /* answer section is empty */
+    ods_log_assert(buffer_pkt_ancount(q->buffer) == 0);
+    /* examine auth section */
+    q->startpos = buffer_position(q->buffer);
+    count = buffer_pkt_nscount(q->buffer);
+    if (count) {
+        if (!buffer_skip_dname(q->buffer) ||
+            !query_parse_soa(q->buffer, &(q->serial))) {
+            ods_log_error("[%s] dropped packet: zone %s received bad ixfr "
+                "request (bad soa in auth section)", query_str, q->zone->name);
+            return QUERY_DISCARDED;
+        }
+        ods_log_debug("[%s] found ixfr request zone %s serial=%u", query_str,
+            q->zone->name, q->serial);
+        return QUERY_PROCESSED;
+    }
+    ods_log_debug("[%s] ixfr request zone %s has no auth section", query_str,
+        q->zone->name);
+    q->serial = 0;
+    return QUERY_PROCESSED;
+}
+
+
+/**
  * Add RRset to response.
  *
  */
@@ -559,15 +603,20 @@
     if (!acl_find(dnsout->provide_xfr, &q->addr, q->tsig_rr)) {
         return query_refused(q);
     }
-    /* prepare */
-    query_prepare(q);
     /* ixfr? */
     if (qtype == LDNS_RR_TYPE_IXFR) {
+        if (query_process_ixfr(q) != QUERY_PROCESSED) {
+            buffer_pkt_set_flags(q->buffer, 0);
+            return query_formerr(q);
+        }
+        query_prepare(q);
         ods_log_assert(q->zone->name);
-        ods_log_debug("[%s] incoming ixfr request for zone %s",
-            query_str, q->zone->name);
+        ods_log_debug("[%s] incoming ixfr request serial=%u for zone %s",
+            query_str, q->serial, q->zone->name);
         return ixfr(q, engine);
     }
+
+    query_prepare(q);
     /* axfr? */
     if (qtype == LDNS_RR_TYPE_AXFR) {
         ods_log_assert(q->zone->name);

Modified: trunk/OpenDNSSEC/signer/src/wire/query.h
===================================================================
--- trunk/OpenDNSSEC/signer/src/wire/query.h	2012-01-25 09:45:06 UTC (rev 6095)
+++ trunk/OpenDNSSEC/signer/src/wire/query.h	2012-01-25 15:47:05 UTC (rev 6096)
@@ -81,6 +81,7 @@
     /* AXFR IXFR */
     FILE* axfr_fd;
     uint32_t serial;
+    size_t startpos;
     /* Bits */
     unsigned axfr_is_done : 1;
     unsigned tsig_prepare_it : 1;




More information about the Opendnssec-commits mailing list