Commit d7308b71 authored by Lubos Slovak's avatar Lubos Slovak

Merge branch 'master' into libknot-cleanup

parents 0448ac6c c8351bbc
......@@ -6,6 +6,7 @@ Features:
Improvements:
* Transfer sizes logged in bytes if needed
* Logging outgoing NOTIFY messages
* Logging unauthorized incoming NOTIFYs
Bugfixes:
* Zone flush planning after bootstrap
* Incorrect incoming AXFR message sizes
......
......@@ -128,37 +128,39 @@ int zone_load_post(zone_contents_t *contents, zone_t *zone, uint32_t *dnssec_ref
int ret = KNOT_EOK;
const conf_zone_t *conf = zone->conf;
changesets_t *diff_change = changesets_create(1);
if (diff_change == NULL) {
return KNOT_ENOMEM;
}
/* Sign zone using DNSSEC (if configured). */
if (conf->dnssec_enable) {
assert(conf->build_diffs);
changesets_t *dnssec_change = changesets_create(1);
if (dnssec_change == NULL) {
return KNOT_ENOMEM;
}
ret = knot_dnssec_zone_sign(contents, conf,
changesets_get_last(dnssec_change),
changesets_get_last(diff_change),
KNOT_SOA_SERIAL_UPDATE,
dnssec_refresh);
if (ret != KNOT_EOK) {
changesets_free(&dnssec_change, NULL);
changesets_free(&diff_change, NULL);
return ret;
}
/* Apply DNSSEC changes. */
ret = zone_change_commit(contents, dnssec_change);
update_cleanup(dnssec_change);
changesets_free(&dnssec_change, NULL);
ret = zone_change_commit(contents, diff_change);
update_cleanup(diff_change);
if (ret != KNOT_EOK) {
changesets_free(&diff_change, NULL);
return ret;
}
}
/* Calculate IXFR from differences (if configured). */
const bool contents_changed = zone->contents && (contents != zone->contents);
changesets_t *diff_change = NULL;
if (contents_changed && conf->build_diffs) {
/* Replace changes from zone signing, the resulting diff will cover
* those changes as well. */
changesets_free(&diff_change, NULL);
diff_change = changesets_create(1);
if (diff_change == NULL) {
return KNOT_ENOMEM;
......@@ -188,14 +190,15 @@ int zone_load_post(zone_contents_t *contents, zone_t *zone, uint32_t *dnssec_ref
}
}
/* Write changes (DNSSEC and diff both) to journal if all went well. */
if (diff_change) {
/* Write changes (DNSSEC, diff, or both) to journal if all went well. */
if (!changesets_empty(diff_change)) {
ret = zone_change_store(zone, diff_change);
changesets_free(&diff_change, NULL);
return ret;
}
// No-op.
changesets_free(&diff_change, NULL);
return KNOT_EOK;
}
......
......@@ -13,7 +13,7 @@ def update_zone(master, slave, zone, changes, change_serial=False, serials=None)
master.update_zonefile(zone, version=i)
if change_serial:
# update zone serial to one given in the 'serials' list
master.zones[zone[0].name].zfile.update_serial(serials[i])
master.zones[zone[0].name].zfile.update_soa(serial=serials[i])
serial = serials[i]
else:
serials.append(serial)
......
......@@ -7,7 +7,7 @@ import random, threading, socket
from dnstest.utils import *
from dnstest.test import Test
FLOOD_COUNT = 20
FLOOD_COUNT = 16
UPDATE_SIZE = 24
chars="qwertyuiopasdfghjklzxcvbnm123456789"
......@@ -58,7 +58,7 @@ last_rr = flood(master, zone)
master.reload()
#wait for update processing
t.sleep(5)
t.sleep(10)
#dig for last change
resp = master.dig(last_rr[0], "TXT")
......
......@@ -6,65 +6,75 @@ from dnstest.utils import *
from dnstest.test import Test
import os
FLUSH_SLEEP = 5
FLUSH_SLEEP = 5.5
t = Test()
master = t.server("bind")
slave = t.server("knot")
slave.zonefile_sync = "4s"
slave.zonefile_sync = "5s"
zone = t.zone("example.")
zone_path = slave.dir + "/slave/" + zone[0].file_name
t.link(zone, master, slave)
t.start()
slave.stop()
try:
os.remove(zone_path)
except:
pass
slave.start()
slave.zone_wait(zone)
#check that the zone file has not been flushed
zone_path = slave.dir + "/slave/" + zone[0].file_name
if os.path.exists(zone_path):
detail_log("Zonefile created too soon: " + str(os.stat(zone_path).st_ctime))
check_log("Zonefile created too soon: " + str(os.stat(zone_path).st_ctime))
set_err("SOON FLUSH")
t.sleep(FLUSH_SLEEP)
t.sleep(FLUSH_SLEEP) #point of first flush ~ 5s
#check that the zone file has been flushed
if not os.path.exists(zone_path):
detail_log("Zonefile not created")
check_log("Zonefile not created")
set_err("NOT FLUSHED")
prev_mtime = os.stat(zone_path).st_mtime
master.update_zonefile(zone, random=True)
master.reload()
t.sleep(FLUSH_SLEEP)
t.sleep(FLUSH_SLEEP) #point of second flush ~ 10s
last_mtime = os.stat(zone_path).st_mtime
#check that the zone file has been flushed after transfer
if prev_mtime == last_mtime:
detail_log("Did not flush after transfer")
check_log("Did not flush after transfer")
set_err("NO POST-TRANSFER FLUSH")
#set the zonefile-sync parameter to 20s and update master - should not flush
slave.zonefile_sync = "20s"
#set the zonefile-sync parameter to 60s and update master - should not flush
slave.zonefile_sync = "60s"
slave.gen_confile()
slave.reload()
t.sleep(FLUSH_SLEEP) # ~ 15s wait for master to start
master.update_zonefile(zone, random=True)
master.reload()
t.sleep(FLUSH_SLEEP)
t.sleep(FLUSH_SLEEP) # ~ 20s
if os.stat(zone_path).st_mtime != last_mtime:
detail_log("Flushed too soon: " + str(os.stat(zone_path).st_mtime) + " vs. " + str(last_mtime))
set_err("SOON FLUSH")
check_log("Flushed too soon: " + str(os.stat(zone_path).st_mtime) + " vs. " + str(last_mtime))
set_err("SOON POST-RELOAD FLUSH")
#set the zonefile-sync parameter to 1s - should flush
slave.zonefile_sync = "1s"
slave.gen_confile()
slave.reload()
t.sleep(1)
if os.stat(zone_path).st_mtime == last_mtime:
detail_log("Did not flush after config change")
check_log("Did not flush after config change")
set_err("NO POST-CHANGE FLUSH")
# ~ 31s
t.stop()
......@@ -130,7 +130,7 @@ class ZoneFile(object):
with open(self.path, "a") as file:
file.write("@ 0 NSEC3PARAM 1 0 %i %s" % (iters, salt))
self.update_serial()
self.update_soa()
def disable_nsec3(self):
'''Remove NSEC3PARAM record if any.'''
......@@ -145,7 +145,7 @@ class ZoneFile(object):
os.remove(old_name)
self.update_serial()
self.update_soa()
def backup(self):
'''Make a backup copy of the actual zone file.'''
......@@ -156,21 +156,33 @@ class ZoneFile(object):
except:
raise Exception("Can't make a copy of zone file '%s'" % self.path)
def update_serial(self, new_serial=None):
'''Change SOA serial.'''
serial = None
first = False
def update_soa(self, serial=None, refresh=None, retry=None, expire=None,
minimum=None):
'''Update SOA rdata numbers (serial, timers). The serial is just
incremented if not specified.'''
old_name = self.path + ".old"
os.rename(self.path, old_name)
first = False
with open(old_name) as old_file, open(self.path, 'w') as new_file:
for line in old_file:
if "SOA" in line and not first:
items = line.split()
serial = int(items[-5])
items[-5] = str(serial + 1) if not new_serial else str(new_serial)
old_serial = int(items[-5])
items[-5] = str(serial) if serial else str(old_serial + 1)
if refresh:
items[-4] = str(refresh)
if retry:
items[-3] = str(retry)
if expire:
items[-2] = str(expire)
if minimum:
items[-1] = str(minimum)
new_file.write(str.join(" ", items))
new_file.write("\n")
first = True
......@@ -185,7 +197,7 @@ class ZoneFile(object):
dnssec = False
nsec3 = False
self.update_serial()
self.update_soa()
old_name = self.path + ".old"
os.rename(self.path, old_name)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment