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