Home | History | Annotate | Line # | Download | only in cacheclean
      1      1.1  christos #!/bin/sh
      2  1.1.1.5  christos 
      3      1.1  christos # Copyright (C) Internet Systems Consortium, Inc. ("ISC")
      4      1.1  christos #
      5  1.1.1.5  christos # SPDX-License-Identifier: MPL-2.0
      6  1.1.1.5  christos #
      7      1.1  christos # This Source Code Form is subject to the terms of the Mozilla Public
      8  1.1.1.5  christos # License, v. 2.0.  If a copy of the MPL was not distributed with this
      9  1.1.1.4  christos # file, you can obtain one at https://mozilla.org/MPL/2.0/.
     10      1.1  christos #
     11      1.1  christos # See the COPYRIGHT file distributed with this work for additional
     12      1.1  christos # information regarding copyright ownership.
     13      1.1  christos 
     14  1.1.1.7  christos set -e
     15  1.1.1.7  christos 
     16  1.1.1.7  christos . ../conf.sh
     17      1.1  christos 
     18      1.1  christos status=0
     19      1.1  christos n=0
     20      1.1  christos 
     21  1.1.1.7  christos RNDCOPTS="-c ../_common/rndc.conf -s 10.53.0.2 -p ${CONTROLPORT}"
     22      1.1  christos DIGOPTS="+nosea +nocomm +nocmd +noquest +noadd +noauth +nocomm \
     23      1.1  christos          +nostat @10.53.0.2 -p ${PORT}"
     24      1.1  christos 
     25      1.1  christos # fill the cache with nodes from flushtest.example zone
     26  1.1.1.7  christos load_cache() {
     27  1.1.1.7  christos   # empty all existing cache data
     28  1.1.1.7  christos   $RNDC $RNDCOPTS flush
     29      1.1  christos 
     30  1.1.1.7  christos   # load the positive cache entries
     31  1.1.1.7  christos   $DIG $DIGOPTS -f - <<EOF >/dev/null 2>&1
     32      1.1  christos txt top1.flushtest.example
     33      1.1  christos txt second1.top1.flushtest.example
     34      1.1  christos txt third1.second1.top1.flushtest.example
     35      1.1  christos txt third2.second1.top1.flushtest.example
     36      1.1  christos txt second2.top1.flushtest.example
     37      1.1  christos txt second3.top1.flushtest.example
     38      1.1  christos txt second1.top2.flushtest.example
     39      1.1  christos txt second2.top2.flushtest.example
     40      1.1  christos txt second3.top2.flushtest.example
     41      1.1  christos txt top3.flushtest.example
     42      1.1  christos txt second1.top3.flushtest.example
     43      1.1  christos txt third1.second1.top3.flushtest.example
     44      1.1  christos txt third2.second1.top3.flushtest.example
     45      1.1  christos txt third1.second2.top3.flushtest.example
     46      1.1  christos txt third2.second2.top3.flushtest.example
     47      1.1  christos txt second3.top3.flushtest.example
     48      1.1  christos EOF
     49      1.1  christos 
     50  1.1.1.7  christos   # load the negative cache entries
     51  1.1.1.7  christos   # nxrrset:
     52  1.1.1.7  christos   $DIG $DIGOPTS a third1.second1.top1.flushtest.example >/dev/null
     53  1.1.1.7  christos   # nxdomain:
     54  1.1.1.7  christos   $DIG $DIGOPTS txt top4.flushtest.example >/dev/null
     55  1.1.1.7  christos   # empty nonterminal:
     56  1.1.1.7  christos   $DIG $DIGOPTS txt second2.top3.flushtest.example >/dev/null
     57  1.1.1.7  christos 
     58  1.1.1.7  christos   # sleep 2 seconds ensure the TTLs will be lower on cached data
     59  1.1.1.7  christos   sleep 2
     60  1.1.1.7  christos }
     61  1.1.1.7  christos 
     62  1.1.1.7  christos dump_cache() {
     63  1.1.1.7  christos   rndc_dumpdb ns2 -cache _default
     64  1.1.1.7  christos }
     65  1.1.1.7  christos 
     66  1.1.1.7  christos clear_cache() {
     67  1.1.1.7  christos   $RNDC $RNDCOPTS flush
     68  1.1.1.7  christos }
     69  1.1.1.7  christos 
     70  1.1.1.7  christos in_cache() {
     71  1.1.1.7  christos   ttl=$($DIG $DIGOPTS "$@" | awk '{print $2}')
     72  1.1.1.7  christos   [ -z "$ttl" ] && {
     73  1.1.1.7  christos     ttl=$($DIG $DIGOPTS +noanswer +auth "$@" | awk '{print $2}')
     74  1.1.1.7  christos     [ "$ttl" -ge 3599 ] && return 1
     75  1.1.1.7  christos     return 0
     76  1.1.1.7  christos   }
     77  1.1.1.7  christos   [ "$ttl" -ge 3599 ] && return 1
     78  1.1.1.7  christos   return 0
     79      1.1  christos }
     80      1.1  christos 
     81  1.1.1.2  christos # Extract records at and below name "$1" from the cache dump in file "$2".
     82  1.1.1.7  christos filter_tree() {
     83  1.1.1.7  christos   tree="$1"
     84  1.1.1.7  christos   file="$2"
     85  1.1.1.7  christos   perl -n -e '
     86  1.1.1.2  christos 		next if /^;/;
     87  1.1.1.2  christos 		if (/'"$tree"'/ || (/^\t/ && $print)) {
     88  1.1.1.2  christos 			$print = 1;
     89  1.1.1.2  christos 		} else {
     90  1.1.1.2  christos 			$print = 0;
     91  1.1.1.2  christos 		}
     92  1.1.1.2  christos 		print if $print;
     93  1.1.1.2  christos 	' "$file"
     94  1.1.1.2  christos }
     95  1.1.1.2  christos 
     96  1.1.1.7  christos n=$((n + 1))
     97      1.1  christos echo_i "check correctness of routine cache cleaning ($n)"
     98  1.1.1.7  christos $DIG $DIGOPTS +tcp +keepopen -b 10.53.0.7 -f dig.batch >dig.out.ns2 || status=1
     99      1.1  christos 
    100      1.1  christos digcomp --lc dig.out.ns2 knowngood.dig.out || status=1
    101      1.1  christos 
    102  1.1.1.7  christos n=$((n + 1))
    103      1.1  christos echo_i "only one tcp socket was used ($n)"
    104  1.1.1.7  christos tcpclients=$(awk '$3 == "client" && $5 ~ /10.53.0.7#[0-9]*:/ {print $5}' ns2/named.run | sort | uniq -c | wc -l)
    105      1.1  christos 
    106  1.1.1.7  christos test $tcpclients -eq 1 || {
    107  1.1.1.7  christos   status=1
    108  1.1.1.7  christos   echo_i "failed"
    109  1.1.1.7  christos }
    110      1.1  christos 
    111  1.1.1.7  christos n=$((n + 1))
    112      1.1  christos echo_i "reset and check that records are correctly cached initially ($n)"
    113      1.1  christos ret=0
    114      1.1  christos load_cache
    115      1.1  christos dump_cache
    116  1.1.1.7  christos nrecords=$(filter_tree flushtest.example ns2/named_dump.db.test$n | grep -E '(TXT|ANY)' | wc -l)
    117  1.1.1.7  christos [ $nrecords -eq 18 ] || {
    118  1.1.1.7  christos   ret=1
    119  1.1.1.7  christos   echo_i "found $nrecords records expected 18"
    120  1.1.1.7  christos }
    121      1.1  christos if [ $ret != 0 ]; then echo_i "failed"; fi
    122  1.1.1.7  christos status=$((status + ret))
    123      1.1  christos 
    124  1.1.1.7  christos n=$((n + 1))
    125      1.1  christos echo_i "check flushing of the full cache ($n)"
    126      1.1  christos ret=0
    127      1.1  christos clear_cache
    128      1.1  christos dump_cache
    129  1.1.1.7  christos nrecords=$(filter_tree flushtest.example ns2/named_dump.db.test$n | wc -l)
    130      1.1  christos [ $nrecords -eq 0 ] || ret=1
    131      1.1  christos if [ $ret != 0 ]; then echo_i "failed"; fi
    132  1.1.1.7  christos status=$((status + ret))
    133      1.1  christos 
    134  1.1.1.7  christos n=$((n + 1))
    135      1.1  christos echo_i "check flushing of individual nodes (interior node) ($n)"
    136      1.1  christos ret=0
    137      1.1  christos clear_cache
    138      1.1  christos load_cache
    139      1.1  christos # interior node
    140      1.1  christos in_cache txt top1.flushtest.example || ret=1
    141      1.1  christos $RNDC $RNDCOPTS flushname top1.flushtest.example
    142      1.1  christos in_cache txt top1.flushtest.example && ret=1
    143      1.1  christos if [ $ret != 0 ]; then echo_i "failed"; fi
    144  1.1.1.7  christos status=$((status + ret))
    145      1.1  christos 
    146  1.1.1.7  christos n=$((n + 1))
    147      1.1  christos echo_i "check flushing of individual nodes (leaf node, under the interior node) ($n)"
    148      1.1  christos ret=0
    149      1.1  christos # leaf node, under the interior node (should still exist)
    150      1.1  christos in_cache txt third2.second1.top1.flushtest.example || ret=1
    151      1.1  christos $RNDC $RNDCOPTS flushname third2.second1.top1.flushtest.example
    152      1.1  christos in_cache txt third2.second1.top1.flushtest.example && ret=1
    153      1.1  christos if [ $ret != 0 ]; then echo_i "failed"; fi
    154  1.1.1.7  christos status=$((status + ret))
    155      1.1  christos 
    156  1.1.1.7  christos n=$((n + 1))
    157      1.1  christos echo_i "check flushing of individual nodes (another leaf node, with both positive and negative cache entries) ($n)"
    158      1.1  christos ret=0
    159      1.1  christos # another leaf node, with both positive and negative cache entries
    160      1.1  christos in_cache a third1.second1.top1.flushtest.example || ret=1
    161      1.1  christos in_cache txt third1.second1.top1.flushtest.example || ret=1
    162      1.1  christos $RNDC $RNDCOPTS flushname third1.second1.top1.flushtest.example
    163      1.1  christos in_cache a third1.second1.top1.flushtest.example && ret=1
    164      1.1  christos in_cache txt third1.second1.top1.flushtest.example && ret=1
    165      1.1  christos if [ $ret != 0 ]; then echo_i "failed"; fi
    166  1.1.1.7  christos status=$((status + ret))
    167      1.1  christos 
    168  1.1.1.7  christos n=$((n + 1))
    169      1.1  christos echo_i "check flushing a nonexistent name ($n)"
    170      1.1  christos ret=0
    171      1.1  christos $RNDC $RNDCOPTS flushname fake.flushtest.example || ret=1
    172      1.1  christos if [ $ret != 0 ]; then echo_i "failed"; fi
    173  1.1.1.7  christos status=$((status + ret))
    174      1.1  christos 
    175  1.1.1.7  christos n=$((n + 1))
    176      1.1  christos echo_i "check flushing of namespaces ($n)"
    177      1.1  christos ret=0
    178      1.1  christos clear_cache
    179      1.1  christos load_cache
    180      1.1  christos # flushing leaf node should leave the interior node:
    181      1.1  christos in_cache txt third1.second1.top1.flushtest.example || ret=1
    182      1.1  christos in_cache txt top1.flushtest.example || ret=1
    183      1.1  christos $RNDC $RNDCOPTS flushtree third1.second1.top1.flushtest.example
    184      1.1  christos in_cache txt third1.second1.top1.flushtest.example && ret=1
    185      1.1  christos in_cache txt top1.flushtest.example || ret=1
    186      1.1  christos in_cache txt second1.top1.flushtest.example || ret=1
    187      1.1  christos in_cache txt third2.second1.top1.flushtest.example || ret=1
    188      1.1  christos $RNDC $RNDCOPTS flushtree second1.top1.flushtest.example
    189      1.1  christos in_cache txt top1.flushtest.example || ret=1
    190      1.1  christos in_cache txt second1.top1.flushtest.example && ret=1
    191      1.1  christos in_cache txt third2.second1.top1.flushtest.example && ret=1
    192      1.1  christos 
    193      1.1  christos # flushing from an empty node should still remove all its children
    194      1.1  christos in_cache txt second1.top2.flushtest.example || ret=1
    195      1.1  christos $RNDC $RNDCOPTS flushtree top2.flushtest.example
    196      1.1  christos in_cache txt second1.top2.flushtest.example && ret=1
    197      1.1  christos in_cache txt second2.top2.flushtest.example && ret=1
    198      1.1  christos in_cache txt second3.top2.flushtest.example && ret=1
    199      1.1  christos if [ $ret != 0 ]; then echo_i "failed"; fi
    200  1.1.1.7  christos status=$((status + ret))
    201      1.1  christos 
    202  1.1.1.7  christos n=$((n + 1))
    203      1.1  christos echo_i "check flushing a nonexistent namespace ($n)"
    204      1.1  christos ret=0
    205      1.1  christos $RNDC $RNDCOPTS flushtree fake.flushtest.example || ret=1
    206      1.1  christos if [ $ret != 0 ]; then echo_i "failed"; fi
    207  1.1.1.7  christos status=$((status + ret))
    208      1.1  christos 
    209  1.1.1.7  christos n=$((n + 1))
    210      1.1  christos echo_i "check the number of cached records remaining ($n)"
    211      1.1  christos ret=0
    212      1.1  christos dump_cache
    213  1.1.1.7  christos nrecords=$(filter_tree flushtest.example ns2/named_dump.db.test$n | grep -v '^;' | grep -E '(TXT|ANY)' | wc -l)
    214  1.1.1.7  christos [ $nrecords -eq 17 ] || {
    215  1.1.1.7  christos   ret=1
    216  1.1.1.7  christos   echo_i "found $nrecords records expected 17"
    217  1.1.1.7  christos }
    218      1.1  christos if [ $ret != 0 ]; then echo_i "failed"; fi
    219  1.1.1.7  christos status=$((status + ret))
    220      1.1  christos 
    221  1.1.1.7  christos n=$((n + 1))
    222      1.1  christos echo_i "check the check that flushname of a partial match works ($n)"
    223      1.1  christos ret=0
    224      1.1  christos in_cache txt second2.top1.flushtest.example || ret=1
    225      1.1  christos $RNDC $RNDCOPTS flushtree example
    226      1.1  christos in_cache txt second2.top1.flushtest.example && ret=1
    227      1.1  christos if [ $ret != 0 ]; then echo_i "failed"; fi
    228  1.1.1.7  christos status=$((status + ret))
    229      1.1  christos 
    230  1.1.1.7  christos n=$((n + 1))
    231      1.1  christos echo_i "check the number of cached records remaining ($n)"
    232      1.1  christos ret=0
    233      1.1  christos dump_cache
    234  1.1.1.7  christos nrecords=$(filter_tree flushtest.example ns2/named_dump.db.test$n | grep -E '(TXT|ANY)' | wc -l)
    235  1.1.1.7  christos [ $nrecords -eq 1 ] || {
    236  1.1.1.7  christos   ret=1
    237  1.1.1.7  christos   echo_i "found $nrecords records expected 1"
    238  1.1.1.7  christos }
    239      1.1  christos if [ $ret != 0 ]; then echo_i "failed"; fi
    240  1.1.1.7  christos status=$((status + ret))
    241      1.1  christos 
    242  1.1.1.7  christos n=$((n + 1))
    243      1.1  christos echo_i "check flushtree clears adb correctly ($n)"
    244      1.1  christos ret=0
    245      1.1  christos load_cache
    246      1.1  christos dump_cache
    247  1.1.1.3  christos mv ns2/named_dump.db.test$n ns2/named_dump.db.test$n.a
    248      1.1  christos sed -n '/plain success\/timeout/,/Unassociated entries/p' \
    249  1.1.1.7  christos   ns2/named_dump.db.test$n.a >sed.out.$n.a
    250  1.1.1.7  christos grep 'plain success/timeout' sed.out.$n.a >/dev/null 2>&1 || ret=1
    251  1.1.1.7  christos grep 'ns.flushtest.example' sed.out.$n.a >/dev/null 2>&1 || ret=1
    252      1.1  christos $RNDC $RNDCOPTS flushtree flushtest.example || ret=1
    253      1.1  christos dump_cache
    254  1.1.1.3  christos mv ns2/named_dump.db.test$n ns2/named_dump.db.test$n.b
    255      1.1  christos sed -n '/plain success\/timeout/,/Unassociated entries/p' \
    256  1.1.1.7  christos   ns2/named_dump.db.test$n.b >sed.out.$n.b
    257  1.1.1.7  christos grep 'plain success/timeout' sed.out.$n.b >/dev/null 2>&1 || ret=1
    258  1.1.1.7  christos grep 'ns.flushtest.example' sed.out.$n.b >/dev/null 2>&1 && ret=1
    259      1.1  christos if [ $ret != 0 ]; then echo_i "failed"; fi
    260  1.1.1.7  christos status=$((status + ret))
    261      1.1  christos 
    262  1.1.1.7  christos n=$((n + 1))
    263  1.1.1.4  christos echo_i "check expire option returned from primary zone ($n)"
    264      1.1  christos ret=0
    265  1.1.1.7  christos $DIG @10.53.0.1 -p ${PORT} +expire soa expire-test >dig.out.expire || ret=1
    266  1.1.1.7  christos grep EXPIRE: dig.out.expire >/dev/null || ret=1
    267      1.1  christos if [ $ret != 0 ]; then echo_i "failed"; fi
    268  1.1.1.7  christos status=$((status + ret))
    269      1.1  christos 
    270  1.1.1.7  christos n=$((n + 1))
    271  1.1.1.4  christos echo_i "check expire option returned from secondary zone ($n)"
    272      1.1  christos ret=0
    273  1.1.1.7  christos $DIG @10.53.0.2 -p ${PORT} +expire soa expire-test >dig.out.expire || ret=1
    274  1.1.1.7  christos grep EXPIRE: dig.out.expire >/dev/null || ret=1
    275      1.1  christos if [ $ret != 0 ]; then echo_i "failed"; fi
    276  1.1.1.7  christos status=$((status + ret))
    277      1.1  christos 
    278      1.1  christos echo_i "exit status: $status"
    279      1.1  christos [ $status -eq 0 ] || exit 1
    280