1# #-- stat_values.test --# 2# source the master var file when it's there 3[ -f ../.tpkg.var.master ] && source ../.tpkg.var.master 4# use .tpkg.var.test for in test variable passing 5[ -f .tpkg.var.test ] && source .tpkg.var.test 6. ../common.sh 7 8PRE="../.." 9 10# Individual thread stats. 11STATS_IGNORE_THREAD="\ 12^thread" 13 14# Histogram stats. 15STATS_IGNORE_HISTOGRAM="\ 16^histogram" 17 18# Time dependent stats. 19STATS_IGNORE_TIME_SPECIFIC="\ 20^total.recursion.time.avg= 21^total.recursion.time.median= 22^time.now= 23^time.up= 24^time.elapsed=" 25 26# Usage dependent stats. 27STATS_IGNORE_USAGE_SPECIFIC="\ 28^total.requestlist.avg= 29^total.requestlist.max= 30^total.requestlist.overwritten= 31^total.requestlist.exceeded= 32^total.requestlist.current.all= 33^total.requestlist.current.user= 34^total.tcpusage= 35^mem\." 36 37# Stats to ignore by default. 38STATS_IGNORE_DEFAULT="\ 39$STATS_IGNORE_THREAD 40$STATS_IGNORE_HISTOGRAM 41$STATS_IGNORE_TIME_SPECIFIC 42$STATS_IGNORE_USAGE_SPECIFIC" 43 44# Various files to be used while testing. 45STATS_FILE=stats.$$ 46EXPECTED_STATS_FILE=expected_stats.$$ 47IGNORE_REGEX_FILE=ignore_regex.$$ 48FILTERED_STATS_FILE=filtered_stats.$$ 49FOUND_STATS_FILE=found_stats.$$ 50REST_STATS_FILE=rest_stats.$$ 51 52DEBUG=0 53 54if dig -h 2>&1 | grep "cookie" >/dev/null; then 55 nocookie="+nocookie" 56else 57 nocookie="" 58fi 59 60# Write stats to $STATS_FILE. 61# Call this when you want to get stats from unbound. 62get_stats () { 63 echo "> Getting stats" 64 echo "$PRE/unbound-control -c ub.conf stats" 65 $PRE/unbound-control -c ub.conf stats > $STATS_FILE 66 if test $? -ne 0; then 67 echo "wrong exit value after success" 68 exit 1 69 fi 70} 71 72# Set the expected stat values by writing to $EXPECTED_STATS_FILE. 73# sort is used for proper diff later. 74set_expected_stats () { 75 echo "$1" | sort > $EXPECTED_STATS_FILE 76} 77 78# Set the regex to ignore stats by writing to $IGNORE_REGEX_FILE. 79set_ignore_regex_stats () { 80 echo "$1" > $IGNORE_REGEX_FILE 81} 82 83# Filter the stats by removing any matched regex from $IGNORE_REGEX_FILE, 84# sorts and writes the left over stats to $FILTERED_STATS_FILE. 85filter_stats () { 86 grep -v -f $IGNORE_REGEX_FILE $STATS_FILE | sort > $FILTERED_STATS_FILE 87} 88 89# Check that the stats in $FILTERED_STATS_FILE include the expected stats in 90# $EXPECTED_STATS_FILE. 91check_expected_stats () { 92 echo "> Checking expected stats" 93 grep -F -x -f $EXPECTED_STATS_FILE $FILTERED_STATS_FILE > $FOUND_STATS_FILE 94 if test $DEBUG -ne 0; then 95 echo "Found:" 96 cat $FOUND_STATS_FILE 97 fi 98 if diff $EXPECTED_STATS_FILE $FOUND_STATS_FILE; then 99 echo "OK" 100 else 101 echo "! bad expected stats:" 102 cat $FILTERED_STATS_FILE 103 end 1 104 fi 105} 106 107# Check that the rest (unspecified) stats are all 0 (no surprises). 108check_rest_stats () { 109 echo "> Checking rest stats" 110 grep -F -x -v -f $EXPECTED_STATS_FILE $FILTERED_STATS_FILE > $REST_STATS_FILE 111 if test $DEBUG -ne 0; then 112 echo "Rest:" 113 cat $REST_STATS_FILE 114 fi 115 if grep -v "=0$" $REST_STATS_FILE; then 116 echo "! bad rest stats" 117 end 1 118 else 119 echo "OK" 120 fi 121} 122 123# Main function to check stats by: 124# - Getting stats from unbound 125# - Filtering out the stats we are not interested in 126# - Checking that the expected stats are part of the filtered stats 127# - The rest of the stats have 0 values. 128check_stats () { 129 set_expected_stats "$1" 130 if test $DEBUG -ne 0; then 131 echo "Expected:" 132 cat $EXPECTED_STATS_FILE 133 fi 134 get_stats 135 filter_stats 136 if test $DEBUG -ne 0; then 137 echo "Filtered:" 138 cat $FILTERED_STATS_FILE 139 fi 140 check_expected_stats 141 check_rest_stats 142} 143 144# Convenient function to set an option through unbound-control. 145set_ub_option () { 146 name=$1 147 value=$2 148 echo "$PRE/unbound-control -c ub.conf set_option $name: $value" 149 $PRE/unbound-control -c ub.conf set_option $name: $value 150 if test $? -ne 0; then 151 echo "wrong exit value after success" 152 exit 1 153 fi 154} 155 156# Convenient function to kill current Unbound and bring up one with an alternate configuration. 157bring_up_alternate_configuration () { 158 conf_file=$1 159 kill_pid $UNBOUND_PID # kill current Unbound 160 echo "" 161 cat unbound.log 162 echo "" 163 $PRE/unbound -d -c $conf_file >unbound.log 2>&1 & 164 UNBOUND_PID=$! 165 echo "UNBOUND_PID=$UNBOUND_PID" >> .tpkg.var.test 166 wait_unbound_up unbound.log 167} 168 169# Convenient function to exit the test. 170end () { 171 echo "> cat logfiles" 172 cat fwd.log 173 cat unbound.log 174 if test $1 -eq 1; then 175 echo "Not OK" 176 else 177 echo "> OK" 178 fi 179 exit $1 180} 181 182# Ignore all run specific stats. 183set_ignore_regex_stats "$STATS_IGNORE_DEFAULT" 184 185# Check if the server is up. 186echo "> dig 1ttl.example.com." 187dig @127.0.0.1 -p $UNBOUND_PORT 1ttl.example.com. | tee outfile 188echo "> check answer" 189if grep "1.1.1.1" outfile; then 190 echo "OK" 191else 192 end 1 193fi 194 195 196teststep "Check initial stats based on first query." 197check_stats "\ 198total.num.queries=1 199total.num.cachemiss=1 200total.num.recursivereplies=1 201num.query.type.A=1 202num.query.class.IN=1 203num.query.opcode.QUERY=1 204num.query.flags.RD=1 205num.query.flags.AD=1 206num.query.edns.present=1 207num.query.udpout=1 208msg.cache.count=1 209rrset.cache.count=1 210infra.cache.count=1 211num.answer.rcode.NOERROR=1" 212 213 214teststep "Check stat reset." 215check_stats "\ 216msg.cache.count=1 217rrset.cache.count=1 218infra.cache.count=1" 219 220 221teststep "Enable serve-expired and check." 222set_ub_option serve-expired yes 223sleep 2 # make sure the TTL has expired. 224echo "> dig 1ttl.example.com." 225dig @127.0.0.1 -p $UNBOUND_PORT 1ttl.example.com. | tee outfile 226echo "> check answer" 227if grep "1.1.1.1" outfile; then 228 echo "OK" 229else 230 end 1 231fi 232check_stats "\ 233total.num.queries=1 234total.num.expired=1 235total.num.cachehits=1 236total.num.prefetch=1 237num.answer.rcode.NOERROR=1 238num.query.class.IN=1 239num.query.edns.present=1 240num.query.flags.AD=1 241num.query.flags.RD=1 242num.query.opcode.QUERY=1 243num.query.type.A=1 244num.query.udpout=1 245msg.cache.count=1 246rrset.cache.count=1 247infra.cache.count=1" 248 249 250teststep "Enable serve-expired-client-timeout and check." 251set_ub_option serve-expired-client-timeout 1 252echo "> dig servfail.expired." 253dig @127.0.0.1 -p $UNBOUND_PORT servfail.expired. | tee outfile 254echo "> check answer" 255if grep "192.0.2.1" outfile; then 256 echo "OK" 257else 258 end 1 259fi 260check_stats "\ 261total.num.queries=1 262total.num.cachemiss=1 263total.num.recursivereplies=1 264num.query.type.A=1 265num.query.class.IN=1 266num.query.opcode.QUERY=1 267num.query.flags.RD=1 268num.query.flags.AD=1 269num.query.edns.present=1 270num.query.udpout=1 271msg.cache.count=2 272rrset.cache.count=2 273infra.cache.count=2 274num.answer.rcode.NOERROR=1" 275kill_pid $FWD_EXPIRED_PID # kill the expired forwarder to force a servfail from upstream. 276sleep 2 # make sure the TTL has expired. 277echo "> dig servfail.expired." 278dig @127.0.0.1 -p $UNBOUND_PORT servfail.expired. | tee outfile 279echo "> check answer" 280if grep "192.0.2.1" outfile; then 281 echo "OK" 282else 283 end 1 284fi 285sleep 1 # make sure the outgoing UDP (and no edns1xx0 retry because not a smaller buffer size) are accounted for. 286check_stats "\ 287total.num.queries=1 288total.num.expired=1 289total.num.recursivereplies=1 290num.answer.rcode.NOERROR=1 291num.query.class.IN=1 292num.query.edns.present=1 293num.query.flags.AD=1 294num.query.flags.RD=1 295num.query.opcode.QUERY=1 296num.query.type.A=1 297num.query.udpout=1 298total.num.cachemiss=1 299msg.cache.count=2 300rrset.cache.count=2 301infra.cache.count=2" 302 303 304# Disable serve-expired 305set_ub_option serve-expired no 306 307 308teststep "Check REFUSED; try without RD flag." 309echo "> dig somethingelse.example.com." 310dig @127.0.0.1 -p $UNBOUND_PORT +nordflag somethingelse.example.com. | tee outfile 311echo "> check answer" 312if grep "REFUSED" outfile; then 313 echo "OK" 314else 315 end 1 316fi 317check_stats "\ 318num.answer.rcode.REFUSED=1 319total.num.cachehits=1 320num.query.class.IN=1 321num.query.edns.present=1 322num.query.flags.AD=1 323num.query.opcode.QUERY=1 324num.query.type.A=1 325total.num.queries=1 326msg.cache.count=2 327rrset.cache.count=2 328infra.cache.count=2" 329 330 331teststep "Check the AD flag." 332echo "> dig www.example.com." 333dig @127.0.0.1 -p $UNBOUND_PORT +noadflag www.example.com. | tee outfile 334echo "> check answer" 335if grep "10.20.30.40" outfile; then 336 echo "OK" 337else 338 end 1 339fi 340check_stats "\ 341num.query.flags.AD=0 342total.num.cachemiss=1 343num.answer.rcode.NOERROR=1 344num.query.class.IN=1 345num.query.edns.present=1 346num.query.flags.RD=1 347num.query.opcode.QUERY=1 348num.query.type.A=1 349num.query.udpout=1 350total.num.queries=1 351total.num.recursivereplies=1 352msg.cache.count=3 353rrset.cache.count=3 354infra.cache.count=2" 355 356 357teststep "Check local zone." 358echo "> dig www.local.zone." 359dig @127.0.0.1 -p $UNBOUND_PORT www.local.zone. | tee outfile 360echo "> check answer" 361if grep "192.0.2.1" outfile; then 362 echo "OK" 363else 364 end 1 365fi 366check_stats "\ 367num.answer.rcode.NOERROR=1 368total.num.cachehits=1 369num.query.class.IN=1 370num.query.edns.present=1 371num.query.flags.AD=1 372num.query.flags.RD=1 373num.query.opcode.QUERY=1 374num.query.type.A=1 375total.num.queries=1 376msg.cache.count=3 377rrset.cache.count=3 378infra.cache.count=2" 379 380 381teststep "Check NXDOMAIN (with local data)." 382echo "> dig mail.local.zone." 383dig @127.0.0.1 -p $UNBOUND_PORT mail.local.zone. | tee outfile 384echo "> check answer" 385if grep "NXDOMAIN" outfile; then 386 echo "OK" 387else 388 end 1 389fi 390check_stats "\ 391num.answer.rcode.NXDOMAIN=1 392total.num.cachehits=1 393num.query.class.IN=1 394num.query.edns.present=1 395num.query.flags.AD=1 396num.query.flags.RD=1 397num.query.opcode.QUERY=1 398num.query.type.A=1 399total.num.queries=1 400msg.cache.count=3 401rrset.cache.count=3 402infra.cache.count=2" 403 404 405teststep "Check CHAOS." 406echo "> dig id.server. ch txt" 407dig @127.0.0.1 -p $UNBOUND_PORT id.server. ch txt | tee outfile 408echo "> check answer" 409if grep "stat_values" outfile; then 410 echo "OK" 411else 412 end 1 413fi 414check_stats "\ 415num.query.class.CH=1 416total.num.cachehits=1 417num.answer.rcode.NOERROR=1 418num.query.edns.present=1 419num.query.flags.AD=1 420num.query.flags.RD=1 421num.query.opcode.QUERY=1 422num.query.type.TXT=1 423total.num.queries=1 424msg.cache.count=3 425rrset.cache.count=3 426infra.cache.count=2" 427 428 429teststep "Check dns-error-reporting." 430echo "> dig www.bogusdnssec." 431dig @127.0.0.1 -p $UNBOUND_PORT www.bogusdnssec. | tee outfile 432echo "> check answer" 433if grep "SERVFAIL" outfile; then 434 echo "OK" 435else 436 end 1 437fi 438check_stats "\ 439infra.cache.count=4 440key.cache.count=1 441msg.cache.count=7 442num.answer.bogus=1 443num.answer.rcode.SERVFAIL=1 444num.query.class.IN=1 445num.query.edns.present=1 446num.query.flags.AD=1 447num.query.flags.RD=1 448num.query.opcode.QUERY=1 449num.query.type.A=1 450num.query.udpout=9 451num.valops=6 452rrset.cache.count=5 453total.num.cachemiss=1 454total.num.dns_error_reports=1 455total.num.queries=1 456total.num.recursivereplies=1" 457 458 459### 460# 461# Bring the discard-timeout, wait-limit configured Unbound up 462# 463bring_up_alternate_configuration ub_discard_wait_limit.conf 464# 465### 466 467 468teststep "Check discard-timeout and wait-limit" 469echo "> dig www.unresponsive" 470dig @127.0.0.1 -p $UNBOUND_PORT +retry=2 +timeout=1 www.unresponsive. | tee outfile 471echo "> check answer" 472if grep "no servers could be reached" outfile; then 473 echo "OK" 474else 475 end 1 476fi 477check_stats "\ 478infra.cache.count=1 479msg.cache.count=1 480num.query.class.IN=3 481num.query.edns.present=3 482num.query.flags.AD=3 483num.query.flags.RD=3 484num.query.opcode.QUERY=3 485num.query.type.A=3 486num.query.udpout=1 487total.num.cachemiss=3 488total.num.queries=3 489total.num.queries_discard_timeout=2 490total.num.queries_wait_limit=1" 491 492 493### 494# 495# Bring the downstream DNS Cookies configured Unbound up 496# 497bring_up_alternate_configuration ub_downstream_cookies.conf 498# 499### 500 501 502teststep "Get a DNS Cookie." 503echo "> dig www.local.zone +tcp $nocookie +ednsopt=10:0102030405060708" 504dig @127.0.0.1 -p $UNBOUND_PORT +tcp $nocookie +ednsopt=10:0102030405060708 +retry=0 +time=1 www.local.zone. | tee outfile 505echo "> check answer" 506if grep "192.0.2.1" outfile; then 507 echo "OK" 508else 509 end 1 510fi 511# Save valid cookie 512valid_cookie=`grep "COOKIE: " outfile | cut -d ' ' -f 3` 513invalid_cookie=`echo $valid_cookie | tr '0' '4'` 514check_stats "\ 515total.num.queries=1 516total.num.queries_cookie_client=1 517total.num.cachehits=1 518num.query.type.A=1 519num.query.class.IN=1 520num.query.opcode.QUERY=1 521num.query.flags.RD=1 522num.query.flags.AD=1 523num.query.edns.present=1 524num.query.tcp=1 525num.answer.rcode.NOERROR=1" 526 527 528teststep "Present the valid DNS Cookie." 529echo "> dig www.local.zone $nocookie +ednsopt=10:valid_cookie" 530dig @127.0.0.1 -p $UNBOUND_PORT $nocookie +ednsopt=10:$valid_cookie +retry=0 +time=1 www.local.zone. | tee outfile 531echo "> check answer" 532if grep "192.0.2.1" outfile; then 533 echo "OK" 534else 535 end 1 536fi 537check_stats "\ 538total.num.queries=1 539total.num.queries_cookie_valid=1 540total.num.cachehits=1 541num.query.type.A=1 542num.query.class.IN=1 543num.query.opcode.QUERY=1 544num.query.flags.RD=1 545num.query.flags.AD=1 546num.query.edns.present=1 547num.answer.rcode.NOERROR=1" 548 549 550teststep "Present an invalid DNS Cookie." 551echo "> dig www.local.zone $nocookie +ednsopt=10:invalid_cookie" 552dig @127.0.0.1 -p $UNBOUND_PORT $nocookie +ednsopt=10:$invalid_cookie +retry=0 +time=1 www.local.zone. | tee outfile 553echo "> check answer" 554if grep "192.0.2.1" outfile; then 555 end 1 556else 557 echo "OK" 558fi 559# A lot of stats are missing since BADCOOKIE error response is before 560# those stat calculations. 561# BADCOOKIE is an extended error code; we record YXRRSET below. 562check_stats "\ 563total.num.queries=1 564total.num.queries_cookie_invalid=1 565total.num.cachehits=1 566num.answer.rcode.YXRRSET=1" 567 568 569teststep "Present no DNS Cookie." 570echo "> dig www.local.zone +ignore" 571dig @127.0.0.1 -p $UNBOUND_PORT +ignore $nocookie +retry=0 +time=1 www.local.zone. | tee outfile 572echo "> check answer" 573if grep "192.0.2.1" outfile; then 574 end 1 575else 576 echo "OK" 577fi 578# A lot of stats are missing since REFUSED error response because of no DNS 579# Cookie is before those stat calculations. 580check_stats "\ 581total.num.queries=1 582total.num.cachehits=1 583num.answer.rcode.REFUSED=1" 584 585if test x$USE_CACHEDB = "x1"; then 586 587 588### 589# 590# Bring the cachedb configured Unbound up 591# 592bring_up_alternate_configuration ub_cachedb.conf 593# 594### 595 596 597teststep "Check cachedb cache miss." 598echo "> dig www.example.com." 599dig @127.0.0.1 +ednsopt=65534 -p $UNBOUND_PORT www.example.com. | tee outfile 600echo "> check answer" 601if grep "10.20.30.40" outfile; then 602 echo "OK" 603else 604 end 1 605fi 606check_stats "\ 607total.num.queries=1 608total.num.cachemiss=1 609total.num.cachehits=0 610total.num.recursivereplies=1 611num.query.type.A=1 612num.query.class.IN=1 613num.query.opcode.QUERY=1 614num.query.flags.RD=1 615num.query.flags.AD=1 616num.query.edns.present=1 617num.query.udpout=1 618num.query.cachedb=0 619msg.cache.count=1 620rrset.cache.count=1 621infra.cache.count=1 622num.answer.rcode.NOERROR=1" 623 624 625teststep "Check cachedb cache hit." 626echo "> dig www.example.com." 627dig @127.0.0.1 +ednsopt=65534 -p $UNBOUND_PORT www.example.com. | tee outfile 628echo "> check answer" 629if grep "10.20.30.40" outfile; then 630 echo "OK" 631else 632 end 1 633fi 634check_stats "\ 635total.num.queries=1 636total.num.cachemiss=1 637total.num.cachehits=0 638total.num.recursivereplies=1 639num.query.type.A=1 640num.query.class.IN=1 641num.query.opcode.QUERY=1 642num.query.flags.RD=1 643num.query.flags.AD=1 644num.query.edns.present=1 645num.query.udpout=0 646num.query.cachedb=1 647msg.cache.count=1 648rrset.cache.count=1 649infra.cache.count=1 650num.answer.rcode.NOERROR=1" 651 652 653teststep "Check cachedb cache hit with stat reset." 654echo "> dig www.example.com." 655dig @127.0.0.1 +ednsopt=65534 -p $UNBOUND_PORT www.example.com. | tee outfile 656echo "> check answer" 657if grep "10.20.30.40" outfile; then 658 echo "OK" 659else 660 end 1 661fi 662check_stats "\ 663total.num.queries=1 664total.num.cachemiss=1 665total.num.cachehits=0 666total.num.recursivereplies=1 667num.query.type.A=1 668num.query.class.IN=1 669num.query.opcode.QUERY=1 670num.query.flags.RD=1 671num.query.flags.AD=1 672num.query.edns.present=1 673num.query.cachedb=1 674msg.cache.count=1 675rrset.cache.count=1 676infra.cache.count=1 677num.answer.rcode.NOERROR=1" 678 679fi # USE_CACHEDB 680 681end 0 682