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 451rrset.cache.count=4 452total.num.cachemiss=1 453total.num.dns_error_reports=1 454total.num.queries=1 455total.num.recursivereplies=1" 456 457 458### 459# 460# Bring the discard-timeout, wait-limit configured Unbound up 461# 462bring_up_alternate_configuration ub_discard_wait_limit.conf 463# 464### 465 466 467teststep "Check discard-timeout and wait-limit" 468echo "> dig www.unresponsive" 469dig @127.0.0.1 -p $UNBOUND_PORT +retry=2 +timeout=1 www.unresponsive. | tee outfile 470echo "> check answer" 471if grep "no servers could be reached" outfile; then 472 echo "OK" 473else 474 end 1 475fi 476check_stats "\ 477infra.cache.count=1 478msg.cache.count=1 479num.query.class.IN=3 480num.query.edns.present=3 481num.query.flags.AD=3 482num.query.flags.RD=3 483num.query.opcode.QUERY=3 484num.query.type.A=3 485num.query.udpout=1 486total.num.cachemiss=3 487total.num.queries=3 488total.num.queries_discard_timeout=2 489total.num.queries_wait_limit=1" 490 491 492### 493# 494# Bring the downstream DNS Cookies configured Unbound up 495# 496bring_up_alternate_configuration ub_downstream_cookies.conf 497# 498### 499 500 501teststep "Get a DNS Cookie." 502echo "> dig www.local.zone +tcp $nocookie +ednsopt=10:0102030405060708" 503dig @127.0.0.1 -p $UNBOUND_PORT +tcp $nocookie +ednsopt=10:0102030405060708 +retry=0 +time=1 www.local.zone. | tee outfile 504echo "> check answer" 505if grep "192.0.2.1" outfile; then 506 echo "OK" 507else 508 end 1 509fi 510# Save valid cookie 511valid_cookie=`grep "COOKIE: " outfile | cut -d ' ' -f 3` 512invalid_cookie=`echo $valid_cookie | tr '0' '4'` 513check_stats "\ 514total.num.queries=1 515total.num.queries_cookie_client=1 516total.num.cachehits=1 517num.query.type.A=1 518num.query.class.IN=1 519num.query.opcode.QUERY=1 520num.query.flags.RD=1 521num.query.flags.AD=1 522num.query.edns.present=1 523num.query.tcp=1 524num.answer.rcode.NOERROR=1" 525 526 527teststep "Present the valid DNS Cookie." 528echo "> dig www.local.zone $nocookie +ednsopt=10:valid_cookie" 529dig @127.0.0.1 -p $UNBOUND_PORT $nocookie +ednsopt=10:$valid_cookie +retry=0 +time=1 www.local.zone. | tee outfile 530echo "> check answer" 531if grep "192.0.2.1" outfile; then 532 echo "OK" 533else 534 end 1 535fi 536check_stats "\ 537total.num.queries=1 538total.num.queries_cookie_valid=1 539total.num.cachehits=1 540num.query.type.A=1 541num.query.class.IN=1 542num.query.opcode.QUERY=1 543num.query.flags.RD=1 544num.query.flags.AD=1 545num.query.edns.present=1 546num.answer.rcode.NOERROR=1" 547 548 549teststep "Present an invalid DNS Cookie." 550echo "> dig www.local.zone $nocookie +ednsopt=10:invalid_cookie" 551dig @127.0.0.1 -p $UNBOUND_PORT $nocookie +ednsopt=10:$invalid_cookie +retry=0 +time=1 www.local.zone. | tee outfile 552echo "> check answer" 553if grep "192.0.2.1" outfile; then 554 end 1 555else 556 echo "OK" 557fi 558# A lot of stats are missing since BADCOOKIE error response is before 559# those stat calculations. 560# BADCOOKIE is an extended error code; we record YXRRSET below. 561check_stats "\ 562total.num.queries=1 563total.num.queries_cookie_invalid=1 564total.num.cachehits=1 565num.answer.rcode.YXRRSET=1" 566 567 568teststep "Present no DNS Cookie." 569echo "> dig www.local.zone +ignore" 570dig @127.0.0.1 -p $UNBOUND_PORT +ignore $nocookie +retry=0 +time=1 www.local.zone. | tee outfile 571echo "> check answer" 572if grep "192.0.2.1" outfile; then 573 end 1 574else 575 echo "OK" 576fi 577# A lot of stats are missing since REFUSED error response because of no DNS 578# Cookie is before those stat calculations. 579check_stats "\ 580total.num.queries=1 581total.num.cachehits=1 582num.answer.rcode.REFUSED=1" 583 584if test x$USE_CACHEDB = "x1"; then 585 586 587### 588# 589# Bring the cachedb configured Unbound up 590# 591bring_up_alternate_configuration ub_cachedb.conf 592# 593### 594 595 596teststep "Check cachedb cache miss." 597echo "> dig www.example.com." 598dig @127.0.0.1 +ednsopt=65534 -p $UNBOUND_PORT www.example.com. | tee outfile 599echo "> check answer" 600if grep "10.20.30.40" outfile; then 601 echo "OK" 602else 603 end 1 604fi 605check_stats "\ 606total.num.queries=1 607total.num.cachemiss=1 608total.num.cachehits=0 609total.num.recursivereplies=1 610num.query.type.A=1 611num.query.class.IN=1 612num.query.opcode.QUERY=1 613num.query.flags.RD=1 614num.query.flags.AD=1 615num.query.edns.present=1 616num.query.udpout=1 617num.query.cachedb=0 618msg.cache.count=1 619rrset.cache.count=1 620infra.cache.count=1 621num.answer.rcode.NOERROR=1" 622 623 624teststep "Check cachedb cache hit." 625echo "> dig www.example.com." 626dig @127.0.0.1 +ednsopt=65534 -p $UNBOUND_PORT www.example.com. | tee outfile 627echo "> check answer" 628if grep "10.20.30.40" outfile; then 629 echo "OK" 630else 631 end 1 632fi 633check_stats "\ 634total.num.queries=1 635total.num.cachemiss=1 636total.num.cachehits=0 637total.num.recursivereplies=1 638num.query.type.A=1 639num.query.class.IN=1 640num.query.opcode.QUERY=1 641num.query.flags.RD=1 642num.query.flags.AD=1 643num.query.edns.present=1 644num.query.udpout=0 645num.query.cachedb=1 646msg.cache.count=1 647rrset.cache.count=1 648infra.cache.count=1 649num.answer.rcode.NOERROR=1" 650 651 652teststep "Check cachedb cache hit with stat reset." 653echo "> dig www.example.com." 654dig @127.0.0.1 +ednsopt=65534 -p $UNBOUND_PORT www.example.com. | tee outfile 655echo "> check answer" 656if grep "10.20.30.40" outfile; then 657 echo "OK" 658else 659 end 1 660fi 661check_stats "\ 662total.num.queries=1 663total.num.cachemiss=1 664total.num.cachehits=0 665total.num.recursivereplies=1 666num.query.type.A=1 667num.query.class.IN=1 668num.query.opcode.QUERY=1 669num.query.flags.RD=1 670num.query.flags.AD=1 671num.query.edns.present=1 672num.query.cachedb=1 673msg.cache.count=1 674rrset.cache.count=1 675infra.cache.count=1 676num.answer.rcode.NOERROR=1" 677 678fi # USE_CACHEDB 679 680end 0 681