BIND 10 master, updated. 6dc0f0ecc269c2b59f78bc0dbd9176214b3266a3 [master] Added a ChangeLog entry for #2157.
BIND 10 source code commits
bind10-changes at lists.isc.org
Thu Feb 21 02:22:40 UTC 2013
The branch, master has been updated
via 6dc0f0ecc269c2b59f78bc0dbd9176214b3266a3 (commit)
via e653adac032f871cbd66cd500c37407a56d14589 (commit)
via 8131da32a67a248150d55280f94c01ce0c377272 (commit)
via 946c4e8afa9647ee9a3e4481e66760512ce556e0 (commit)
via e5e511b58b6ad59b3d79f19c2f7d18b0a6843273 (commit)
via 0147b8cb625f27bf57438b9e1af25bbd9f597f01 (commit)
via bd35b30808c5093ee41aea3f8289f691befb8219 (commit)
via 5a6d38e1f78650477176b1cd8424227382621c7a (commit)
via b9be907e65b56003803b87a8886d37196c53741b (commit)
via a6a1bf6c90da7fc59eaf094762eb1410f14b8658 (commit)
via 2af2991a8d5e0a5f6debff5f9105fd215803b6db (commit)
via 1c470ce95278e5a67b3babfb4e7adec849053e6b (commit)
via 93b27668a1fc63da7fd0527a04691dcd00c9e310 (commit)
via 5b479207c875b0c09d3e2fc92e05ccf0e46a8773 (commit)
via 9430b068ddc62ed1a31ec72b3012aa87d8a743f4 (commit)
via cddeabfcf7ae30d053f82952310377186b91d2e4 (commit)
via ba2d4df266cd44d44175260cf16bf2d22a4e1f12 (commit)
via 7f69bab21e2bfc6656a1926348f2ea4920301b61 (commit)
via dc6a6a9ef65b75bdb4cc79a67a83c04645657055 (commit)
via 7d28f0a9b596bd3a4580372c93408904d8f2d8a5 (commit)
via fb2a1a9621d321c1db03bd3c4184d14e77f9d276 (commit)
via 2755265bad7544bdaacfeed81e71ae590f043866 (commit)
via 722fbab9dc7891a6d4270d9e8fac453791fb0c51 (commit)
via 1954d8d1d6b4b57c3f66443585cbe6aff51b4342 (commit)
via 810a54ae8ffc10a282796b9ba64594c629010580 (commit)
via 20255f329b3db92930f8914c3a10f06de26d8fa5 (commit)
via bfad7cb107492b6459df53f79875c3225096e67e (commit)
via f3710cc1ce7bdd800176c5b70f22710bda652ddc (commit)
via 59d2798eeb72f4b81dd0c7ee380794da67b96424 (commit)
via a1705370803388f15833e588db710fe520fda751 (commit)
via 10a2897883c51ec83247ddcfe137a19807f41a69 (commit)
via 5d31621e52c2f2be062284f71a589218ab9a4d0a (commit)
via 819407f4b51521da995e893f022c06853a6f40cd (commit)
via f91f95678f03873d47480a9589dae1936423cff7 (commit)
via 3476033eb79b246bbf0904085f4cab3805d5eddd (commit)
via d792272541407b25dcda463321416d61315d785f (commit)
via f1b061b42a6ea0257f09d45de0243d064497609b (commit)
via ed014f274ce18bcbdb8c79c3ea856a88af23f8e2 (commit)
via daccf2d63231865ce3c5498a4bde4e895f047cd7 (commit)
via dbf019c34b50e415fae366e062bdaa353d873412 (commit)
via 9aaf0f9883c7a67ff2acd8be43afd91e235f7164 (commit)
via ce5cf26e3637a7faf5901debecaf542cdacf69cc (commit)
via c0fa34d5aa68b4d189cfb606373856e6fceb1388 (commit)
via ab9c7fa4343ba35decbf47b765d81ffa785c7638 (commit)
via 702c844a645dd91379d0e6b6896566863291d96f (commit)
via a2cb2c80637696d1268f87660508c6aa8e0e14ec (commit)
via 825e49f101bf3a00de47d0c6e388f00e265f5658 (commit)
via 9cbc650016910ad14ded2b0a4a7fb18f8275085a (commit)
via e3fb3a101e6874ca1c93e46916ab53f278c55642 (commit)
via 826d0c45b072ba36bbd60dc71fe3097cd604de74 (commit)
via 89cc0b54c0de3bac967e2ae8135aad6d654edfe1 (commit)
via acc630c2e40165f605aad3dde959bc2f3871ea6b (commit)
via c7c532323f9f5f9d98050c0728a87e04800d7144 (commit)
via 7f75e58b7f26fc36c457b74770f8bdc0043a1618 (commit)
via 3d3d75ab559780b95a325c9890364e2c80c480a1 (commit)
via b3804a1036a254bf6ba00bae3182cc0486ddf7ff (commit)
via ba18b3b37595da5364dd82adfb880d3cb5d916d2 (commit)
via bd6e48f80ca1eb587ef1895b1614554865b85fa5 (commit)
via 98fd407e255aadf68b0e1ba7c89b0f65619373ad (commit)
via 644541309f301c6f86495db3982eb5ba69b40529 (commit)
via 76759ae07db6edb36cc063ef1f89e247d910275a (commit)
via cb24062bb3a9d55e5a22098f526172f130a50d60 (commit)
via 370c09f6e3b2d4141ed573bfbab6e39302d670b7 (commit)
via 7eb39cf5f50a31ccd80d6373074301f5caeb088c (commit)
via 566a0c71ebbdeee3981152aa0d98e53a4eba102a (commit)
via 9d1691533c1bbce4518ddbe617b6e2b24ff532ea (commit)
via 3eb8564cd9f9dc2b05b25da7d837a742acb7a860 (commit)
via c7de383107b3644fb0fb941341b369f8693e9382 (commit)
via d4e61c261d0af6db6da47bba2b1cac1ecf4ce002 (commit)
via 56e8f3e3e99557bacd0f4d4a2694f42b2c2f63ef (commit)
via 9371828a3aae06b6a5de33743864bcf3e20162f4 (commit)
via 72e963ce027a56e814d5404feee00aa0b4a45b15 (commit)
via 0f4c8ad79bcdf9810013fa667dd04bf0e67c21b5 (commit)
via 261d1e5735e818cbf12cd6d004faf0ccc86bdaf4 (commit)
via cbc4276308e412d456a20e5eaf816af86ecac82a (commit)
via b0b2c34b61603f6a2676f139d5ad328ac1f3cdc5 (commit)
via acd0cdbbc9e3e261cfc0e0f8589bff184a2f2e8b (commit)
via 40f93b0c0d8957a55fb668c12a20f90d4ac9b9d3 (commit)
via 47378a9cbd7221316b4c760e63d04076e30c73e3 (commit)
via 3c564a11e1f20def92a19c61b7af3451eb5401f7 (commit)
via 988a0f092329316e2b371a28f2a1d23424bf9faf (commit)
via 494784a813b1abdaa08e0bb3826ba72d0da5d15e (commit)
via 8cdb5d8c29af3be627e3c7bd5898d08392da4b35 (commit)
via f04b2ebeb31bc3ff1b8866be4b426bfbbb423803 (commit)
via dd62fb425882a361673e52f264b24d2455d9b335 (commit)
via c2165222deb85cb2ff99a7146b28c659624edc24 (commit)
via 2afe3383ec01875950b489b7702b2ec2c3281d64 (commit)
via 9e0f9e4df2927c9ae7173053b2efc57ec8dd82ee (commit)
via e930663b459bf75063193ed08cb3d455adaaccae (commit)
via 36f21c21868230dc6dbf60b898607cca53fceaf4 (commit)
via 9284859b4ab4af8670ecf1cd6de999a04cd4285b (commit)
via 1e68893cbfb6d4742e1d9def9ca2960935c7e2b9 (commit)
via 74a034d57525026cb30591f3e89c49be2f2787ec (commit)
via 12ca269d63653d1db9280920717554f3d06f885f (commit)
via b65007a6a4dbc4b192f78dece6ba84eb32e0b3bc (commit)
via 8de2a109e5827ed6bac158e8a12c453d90a23f26 (commit)
via f3e3dc930b7de63dd8842b61a7ec042ac99c235c (commit)
via bb6e5acc09639be9a9009f3d266435aee2b0fce2 (commit)
via 2ac23d0d571713a390d154263040c1f1290bba89 (commit)
via bce2a3f58dd9c95985a53c6235835aa9fb4c719d (commit)
via 4c3dc79c413854edcf660874f8bd58d626b808c8 (commit)
via 9b47527a3fd00d3504dbdecc5e6b073834825c66 (commit)
via db2a410da1fb7553909b47ddbc7ce34456081f47 (commit)
via efbe16c46b234712eaa7629ffda12b1a906542af (commit)
via 4d9785cd658ba91b5f01c90c1855d239596c5f53 (commit)
via 7d02b9cc8837e089433be66f7973ba578e72ee39 (commit)
via 91a81c3b9a1ed47103c00e50fe3d141a2e9929b9 (commit)
via ab7f77f9ea18ce289ccc7484c4a40dc73548bca0 (commit)
via cb5a5f6e3c043b2f94884f5cb9101b661a084fc6 (commit)
via d5d8fa746c2cb23166e93f76423ae7ca645ef6a3 (commit)
via 3e2516ee09187b5c9af57e0cd6552bb298ebf02d (commit)
via 8c169e9a6032d69dd852f49d567eda1ecd7de706 (commit)
via a1107af9f039334d628220553229476beb41143f (commit)
via a0f35ebd59dee9b3f9b87c6b16d9185766f1d1be (commit)
via 6f61065e702d8ccd5b3b2da2c5e07803270ed120 (commit)
via a44025da797abe06f2d1b1a7de98f68b37e0c5d4 (commit)
via 34dd2565e959d9307cd17a1664d514ba76b68e24 (commit)
via 50c6b204fe5c51af7bed0f5538b8d6817b654a24 (commit)
via 5abc52b3f407f042b7fd189aa42a6a23228c0be7 (commit)
via 92cf23f15e80e32f2983eb69d7c5ca13c336ebc4 (commit)
via 7a821cf7fe79d72a294053865a65fe52b29394ee (commit)
via 24cecc6e6249e1805160c7c6d1ed121ae57a451f (commit)
via 0e784ad2b33879f2cfcb40921a891fb73714be68 (commit)
via c30ebf9ecc8b18a7b2e6ae57f6e8db582acb00c7 (commit)
via 7dd1d39f9711ec039988a527eff33dc5912b4721 (commit)
via 0382951b17dfa9647f4f1b4c55d021f51138aa1e (commit)
via d24fcdc5998f904c5b81de311066935906566ff2 (commit)
via 01cec039d9326d4d29e501109aa3bf5b28896786 (commit)
via 16a7ef79d27c65f25a72908244b088fd8488c729 (commit)
via 7791af176bda3e99caffe8ca2aa2fc69d92a95dc (commit)
via 1603af4c983f4fbebc4731177680c8c9549b4c60 (commit)
via fb246fec83de75f41171b48f48c314b985a985de (commit)
via 081f73d83d9afee393283514afc4398b8515f6a3 (commit)
via 5b92e04d29ae21a217b8ce01fe3487ccd4ca180b (commit)
via eeb6dd5d64907846387b886cd2aa20e018e4234e (commit)
via 52598eb44e5c7fca9f1902be4c1e54e786b13d3b (commit)
via b9b6e36c4e5201c5ffb5f405ee7c4e18ee787d1d (commit)
via ea7ef4dac89ff14aaa752ca10ad0a1ec965ea0f4 (commit)
via b08a456d702942de353ae57529bdbe2d1ba22d07 (commit)
via f9b1652469debfcc2974149219b4098019458649 (commit)
via 425b14dc49047c29338e415f6360a15c81b4f48c (commit)
via b2d762a14ce55201967f0d38e2216289b98955fd (commit)
via 401f99d8ce662e361c4aa067e758e03b8c0a78e0 (commit)
via fc44d8a5b5084a60cf7d7cddf7cfe537191d14af (commit)
via 82896b534152bc5c29d8db5939965c073e283dd4 (commit)
via 72c2349d91de8ab45839a701b6befe30f04d542b (commit)
via 859bfb0777fc4ef95de9dcc396b8ca5e98d91760 (commit)
via 131b376fc16fbe7bee9dc8753daba0dc04171cff (commit)
via 4f7957ecd5a7995dac7662569c2e4dd7d86c7d77 (commit)
via 1bd6030873ee6e27cddcbb6437ef15ca84ee9cfa (commit)
via 9aea53afbe639d939b04df9307bdb48e2952148b (commit)
via c8c8c8358a7602094b6177b5336d39b9de172b87 (commit)
via 5d108ef3a0b5b5d9fe322ceb478c36077deedfd4 (commit)
via bc6378d402e5977beac587dc87b73351609f01a5 (commit)
via 2edfabb40d94f795923f8dbbd135e20c9c19f8ad (commit)
via 05d4686ef8b343fc4ca4ea0bfd6c62fe4b73ef84 (commit)
via d597f938295cdfaf4670308558f692523d0857f0 (commit)
via 68f0ecce4c8ec9f5b2fb16fd56fdc0dd89dd2101 (commit)
via 577a426b8734d7f77e4dceae80fe0c344ab15330 (commit)
via 415e9b6a2c8544882c71e3cb91d47bb768e41a9f (commit)
via 1b616670c801a181c8ba5718710bdeb6573e3e4b (commit)
via 2f912a5d91267471e059ad8bc3e9f0377de2f487 (commit)
from 54e52000440917a5d9e3dfb0862262e2748c07e0 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 6dc0f0ecc269c2b59f78bc0dbd9176214b3266a3
Author: Yoshitaka Aharen <aharen at jprs.co.jp>
Date: Thu Feb 21 11:04:13 2013 +0900
[master] Added a ChangeLog entry for #2157.
commit e653adac032f871cbd66cd500c37407a56d14589
Merge: 54e5200 8131da3
Author: Yoshitaka Aharen <aharen at jprs.co.jp>
Date: Thu Feb 21 11:03:16 2013 +0900
Merge branch 'trac2157_merge'
Conflicts:
ChangeLog
-----------------------------------------------------------------------
Summary of changes:
ChangeLog | 8 +
configure.ac | 1 +
src/bin/auth/Makefile.am | 28 +-
src/bin/auth/auth.spec.pre.in | 218 +-----
src/bin/auth/auth_srv.cc | 175 +++--
src/bin/auth/auth_srv.h | 5 +-
src/bin/auth/{b10-auth.xml => b10-auth.xml.pre} | 62 +-
src/bin/auth/gen-statisticsitems.py.pre.in | 385 +++++++++++
src/bin/auth/statistics.cc | 284 --------
src/bin/auth/statistics.cc.pre | 277 ++++++++
src/bin/auth/statistics.h | 365 ++++++----
src/bin/auth/statistics_items.h | 609 -----------------
src/bin/auth/statistics_items.h.pre | 53 ++
src/bin/auth/statistics_msg_items.def | 48 ++
src/bin/auth/tests/Makefile.am | 11 +-
src/bin/auth/tests/auth_srv_unittest.cc | 476 ++++++++-----
src/bin/auth/tests/gen-statisticsitems_test.py | 90 +++
src/bin/auth/tests/statistics_unittest.cc | 123 ----
src/bin/auth/tests/statistics_unittest.cc.pre | 714 ++++++++++++++++++++
src/bin/auth/tests/statistics_util.cc | 75 ++
.../auth/tests/statistics_util.h} | 24 +-
src/lib/statistics/counter.h | 21 +-
src/lib/statistics/counter_dict.h | 87 ++-
src/lib/testutils/testdata/example.com | 8 +
src/lib/testutils/testdata/example.sqlite3 | Bin 15360 -> 15360 bytes
.../configurations/example.org.inmem.config | 4 +
tests/lettuce/features/queries.feature | 192 +++++-
tests/lettuce/features/terrain/bind10_control.py | 64 +-
tests/system/bindctl/tests.sh | 109 ++-
29 files changed, 2740 insertions(+), 1776 deletions(-)
rename src/bin/auth/{b10-auth.xml => b10-auth.xml.pre} (89%)
create mode 100755 src/bin/auth/gen-statisticsitems.py.pre.in
delete mode 100644 src/bin/auth/statistics.cc
create mode 100644 src/bin/auth/statistics.cc.pre
delete mode 100644 src/bin/auth/statistics_items.h
create mode 100644 src/bin/auth/statistics_items.h.pre
create mode 100644 src/bin/auth/statistics_msg_items.def
create mode 100644 src/bin/auth/tests/gen-statisticsitems_test.py
delete mode 100644 src/bin/auth/tests/statistics_unittest.cc
create mode 100644 src/bin/auth/tests/statistics_unittest.cc.pre
create mode 100644 src/bin/auth/tests/statistics_util.cc
copy src/{lib/python/isc/datasrc/zone_loader_python.h => bin/auth/tests/statistics_util.h} (65%)
-----------------------------------------------------------------------
diff --git a/ChangeLog b/ChangeLog
index ed0c50b..fa50a5d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+581. [func]* y-aharen
+ Added statistics items in b10-auth based on
+ http://bind10.isc.org/wiki/StatisticsItems. Qtype counters are
+ dropped as it requires further spec design discussion.
+ (Trac #2154, Trac #2155,
+ git 61d7c3959eb991b22bc1c0ef8f4ecb96b65d9325)
+ (Trac #2157, git e653adac032f871cbd66cd500c37407a56d14589)
+
bind10-1.0.0-rc released on February 14, 2013
580. [func]* muks
diff --git a/configure.ac b/configure.ac
index 5195c24..e7e028f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1359,6 +1359,7 @@ AC_OUTPUT([doc/version.ent
src/bin/auth/tests/testdata/example.zone
src/bin/auth/tests/testdata/example-base.zone
src/bin/auth/tests/testdata/example-nsec3.zone
+ src/bin/auth/gen-statisticsitems.py.pre
src/bin/dhcp4/spec_config.h.pre
src/bin/dhcp6/spec_config.h.pre
src/bin/tests/process_rename_test.py
diff --git a/src/bin/auth/Makefile.am b/src/bin/auth/Makefile.am
index 7d29fcc..1bb5ee9 100644
--- a/src/bin/auth/Makefile.am
+++ b/src/bin/auth/Makefile.am
@@ -18,6 +18,9 @@ pkglibexecdir = $(libexecdir)/@PACKAGE@
CLEANFILES = *.gcno *.gcda auth.spec spec_config.h
CLEANFILES += auth_messages.h auth_messages.cc
+CLEANFILES += gen-statisticsitems.py
+# auto-generated by gen-statisticsitems.py
+CLEANFILES += statistics.cc statistics_items.h b10-auth.xml tests/statistics_unittest.cc
man_MANS = b10-auth.8
DISTCLEANFILES = $(man_MANS)
@@ -26,7 +29,7 @@ EXTRA_DIST = $(man_MANS) b10-auth.xml
if GENERATE_DOCS
b10-auth.8: b10-auth.xml
- @XSLTPROC@ --novalid --xinclude --nonet -o $@ http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl $(srcdir)/b10-auth.xml
+ @XSLTPROC@ --novalid --xinclude --nonet -o $@ http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl $(builddir)/b10-auth.xml
else
@@ -36,8 +39,18 @@ $(man_MANS):
endif
-auth.spec: auth.spec.pre
- $(SED) -e "s|@@LOCALSTATEDIR@@|$(localstatedir)|" auth.spec.pre >$@
+auth.spec: auth.spec.pre statistics_msg_items.def
+b10-auth.xml: b10-auth.xml.pre statistics_msg_items.def
+statistics_items.h: statistics_items.h.pre statistics_msg_items.def
+statistics.cc: statistics.cc.pre statistics_msg_items.def
+tests/statistics_unittest.cc: tests/statistics_unittest.cc.pre statistics_msg_items.def
+
+gen-statisticsitems.py: gen-statisticsitems.py.pre
+ $(SED) -e "s|@@LOCALSTATEDIR@@|$(localstatedir)|" gen-statisticsitems.py.pre >$@
+ chmod +x $@
+
+auth.spec b10-auth.xml statistics_items.h statistics.cc tests/statistics_unittest.cc: Makefile gen-statisticsitems.py
+ ./gen-statisticsitems.py
spec_config.h: spec_config.h.pre
$(SED) -e "s|@@LOCALSTATEDIR@@|$(localstatedir)|" spec_config.h.pre >$@
@@ -46,6 +59,8 @@ auth_messages.h auth_messages.cc: auth_messages.mes
$(top_builddir)/src/lib/log/compiler/message $(top_srcdir)/src/bin/auth/auth_messages.mes
BUILT_SOURCES = spec_config.h auth_messages.h auth_messages.cc
+# auto-generated by gen-statisticsitems.py
+BUILT_SOURCES += statistics_items.h statistics.cc
pkglibexec_PROGRAMS = b10-auth
b10_auth_SOURCES = query.cc query.h
@@ -54,13 +69,18 @@ b10_auth_SOURCES += auth_log.cc auth_log.h
b10_auth_SOURCES += auth_config.cc auth_config.h
b10_auth_SOURCES += command.cc command.h
b10_auth_SOURCES += common.h common.cc
-b10_auth_SOURCES += statistics.cc statistics.h statistics_items.h
+b10_auth_SOURCES += statistics.h
b10_auth_SOURCES += datasrc_clients_mgr.h
b10_auth_SOURCES += datasrc_config.h datasrc_config.cc
b10_auth_SOURCES += main.cc
nodist_b10_auth_SOURCES = auth_messages.h auth_messages.cc
+nodist_b10_auth_SOURCES += statistics.cc statistics_items.h
EXTRA_DIST += auth_messages.mes
+EXTRA_DIST += statistics_msg_items.def
+EXTRA_DIST += b10-auth.xml.pre
+EXTRA_DIST += statistics_items.h.pre statistics.cc.pre
+EXTRA_DIST += tests/statistics_unittest.cc.pre
b10_auth_LDADD = $(top_builddir)/src/lib/datasrc/libb10-datasrc.la
b10_auth_LDADD += $(top_builddir)/src/lib/dns/libb10-dns++.la
diff --git a/src/bin/auth/auth.spec.pre.in b/src/bin/auth/auth.spec.pre.in
index 30a455d..a235da3 100644
--- a/src/bin/auth/auth.spec.pre.in
+++ b/src/bin/auth/auth.spec.pre.in
@@ -122,7 +122,7 @@
"item_name": "class", "item_type": "string",
"item_optional": true, "item_default": "IN"
},
- {
+ {
"item_name": "origin", "item_type": "string",
"item_optional": false, "item_default": ""
}
@@ -140,222 +140,6 @@
}
],
"statistics": [
- {
- "item_name": "queries.tcp",
- "item_type": "integer",
- "item_optional": false,
- "item_default": 0,
- "item_title": "Queries TCP",
- "item_description": "A number of total query counts which all auth servers receive over TCP since they started initially"
- },
- {
- "item_name": "queries.udp",
- "item_type": "integer",
- "item_optional": false,
- "item_default": 0,
- "item_title": "Queries UDP",
- "item_description": "A number of total query counts which all auth servers receive over UDP since they started initially"
- },
- {
- "item_name": "opcode.query",
- "item_type": "integer",
- "item_optional": true,
- "item_default": 0,
- "item_title": "Received query requests",
- "item_description": "The number of total request counts whose opcode is query"
- },
- {
- "item_name": "opcode.iquery",
- "item_type": "integer",
- "item_optional": true,
- "item_default": 0,
- "item_title": "Received inverse query requests",
- "item_description": "The number of total request counts whose opcode is inverse query"
- },
- {
- "item_name": "opcode.status",
- "item_type": "integer",
- "item_optional": true,
- "item_default": 0,
- "item_title": "Received status requests",
- "item_description": "The number of total request counts whose opcode is status"
- },
- {
- "item_name": "opcode.notify",
- "item_type": "integer",
- "item_optional": true,
- "item_default": 0,
- "item_title": "Received notify requests",
- "item_description": "The number of total request counts whose opcode is notify"
- },
- {
- "item_name": "opcode.update",
- "item_type": "integer",
- "item_optional": true,
- "item_default": 0,
- "item_title": "Received update requests",
- "item_description": "The number of total request counts whose opcode is update"
- },
- {
- "item_name": "opcode.other",
- "item_type": "integer",
- "item_optional": true,
- "item_default": 0,
- "item_title": "Received requests opcode other",
- "item_description": "The number of total request counts whose opcode is other (not well-known)"
- },
- {
- "item_name": "rcode.noerror",
- "item_type": "integer",
- "item_optional": true,
- "item_default": 0,
- "item_title": "Sent success response",
- "item_description": "The number of total responses with rcode 0 (NOERROR)"
- },
- {
- "item_name": "rcode.formerr",
- "item_type": "integer",
- "item_optional": true,
- "item_default": 0,
- "item_title": "Sent 'format error' response",
- "item_description": "The number of total responses with rcode 1 (FORMERR)"
- },
- {
- "item_name": "rcode.servfail",
- "item_type": "integer",
- "item_optional": true,
- "item_default": 0,
- "item_title": "Sent 'server failure' response",
- "item_description": "The number of total responses with rcode 2 (SERVFAIL)"
- },
- {
- "item_name": "rcode.nxdomain",
- "item_type": "integer",
- "item_optional": true,
- "item_default": 0,
- "item_title": "Sent 'name error' response",
- "item_description": "The number of total responses with rcode 3 (NXDOMAIN)"
- },
- {
- "item_name": "rcode.notimp",
- "item_type": "integer",
- "item_optional": true,
- "item_default": 0,
- "item_title": "Sent 'not implemented' response",
- "item_description": "The number of total responses with rcode 4 (NOTIMP)"
- },
- {
- "item_name": "rcode.refused",
- "item_type": "integer",
- "item_optional": true,
- "item_default": 0,
- "item_title": "Sent 'refused' response",
- "item_description": "The number of total responses with rcode 5 (REFUSED)"
- },
- {
- "item_name": "rcode.yxdomain",
- "item_type": "integer",
- "item_optional": true,
- "item_default": 0,
- "item_title": "Sent 'name unexpectedly exists' response",
- "item_description": "The number of total responses with rcode 6 (YXDOMAIN)"
- },
- {
- "item_name": "rcode.yxrrset",
- "item_type": "integer",
- "item_optional": true,
- "item_default": 0,
- "item_title": "Sent 'rrset unexpectedly exists' response",
- "item_description": "The number of total responses with rcode 7 (YXRRSET)"
- },
- {
- "item_name": "rcode.nxrrset",
- "item_type": "integer",
- "item_optional": true,
- "item_default": 0,
- "item_title": "Sent 'no such rrset' response",
- "item_description": "The number of total responses with rcode 8 (NXRRSET)"
- },
- {
- "item_name": "rcode.notauth",
- "item_type": "integer",
- "item_optional": true,
- "item_default": 0,
- "item_title": "Sent 'not authoritative' response",
- "item_description": "The number of total responses with rcode 9 (NOTAUTH)"
- },
- {
- "item_name": "rcode.notzone",
- "item_type": "integer",
- "item_optional": true,
- "item_default": 0,
- "item_title": "Sent 'name not in zone' response",
- "item_description": "The number of total responses with rcode 10 (NOTZONE)"
- },
- {
- "item_name": "rcode.badsigvers",
- "item_type": "integer",
- "item_optional": true,
- "item_default": 0,
- "item_title": "Sent 'EDNS version not implemented' response",
- "item_description": "The number of total responses with rcode 16 (BADVERS)"
- },
- {
- "item_name": "rcode.badkey",
- "item_type": "integer",
- "item_optional": true,
- "item_default": 0,
- "item_title": "Sent 'Key not recognized' response",
- "item_description": "The number of total responses with rcode 17 (BADKEY)"
- },
- {
- "item_name": "rcode.badtime",
- "item_type": "integer",
- "item_optional": true,
- "item_default": 0,
- "item_title": "Sent 'Signature out of time window' response",
- "item_description": "The number of total responses with rcode 18 (BADTIME)"
- },
- {
- "item_name": "rcode.badmode",
- "item_type": "integer",
- "item_optional": true,
- "item_default": 0,
- "item_title": "Sent 'Bad TKEY Mode' response",
- "item_description": "The number of total responses with rcode 19 (BADMODE)"
- },
- {
- "item_name": "rcode.badname",
- "item_type": "integer",
- "item_optional": true,
- "item_default": 0,
- "item_title": "Sent 'Duplicate key name' response",
- "item_description": "The number of total responses with rcode 20 (BADNAME)"
- },
- {
- "item_name": "rcode.badalg",
- "item_type": "integer",
- "item_optional": true,
- "item_default": 0,
- "item_title": "Sent 'Algorithm not supported' response",
- "item_description": "The number of total responses with rcode 21 (BADALG)"
- },
- {
- "item_name": "rcode.badtrunc",
- "item_type": "integer",
- "item_optional": true,
- "item_default": 0,
- "item_title": "Sent 'Bad Truncation' response",
- "item_description": "The number of total responses with rcode 22 (BADTRUNC)"
- },
- {
- "item_name": "rcode.other",
- "item_type": "integer",
- "item_optional": true,
- "item_default": 0,
- "item_title": "Sent responses with rcode other",
- "item_description": "The number of total responses with rcode other (not well-known)"
- }
]
}
}
diff --git a/src/bin/auth/auth_srv.cc b/src/bin/auth/auth_srv.cc
index ca323e0..30875e5 100644
--- a/src/bin/auth/auth_srv.cc
+++ b/src/bin/auth/auth_srv.cc
@@ -86,6 +86,7 @@ using namespace isc::asiolink;
using namespace isc::asiodns;
using namespace isc::server_common::portconfig;
using isc::auth::statistics::Counters;
+using isc::auth::statistics::MessageAttributes;
namespace {
// A helper class for cleaning up message renderer.
@@ -102,17 +103,21 @@ namespace {
// user of this class, so we hide it within the implementation.
class RendererHolder {
public:
- RendererHolder(MessageRenderer& renderer, OutputBuffer* buffer) :
- renderer_(renderer)
+ RendererHolder(MessageRenderer& renderer, OutputBuffer* buffer,
+ MessageAttributes& stats_attrs) :
+ renderer_(renderer),
+ stats_attrs_(stats_attrs)
{
renderer.setBuffer(buffer);
}
~RendererHolder() {
+ stats_attrs_.setResponseTruncated(renderer_.isTruncated());
renderer_.setBuffer(NULL);
renderer_.clear();
}
private:
MessageRenderer& renderer_;
+ MessageAttributes& stats_attrs_;
};
// Similar to Renderer holder, this is a very basic RAII-style class
@@ -239,15 +244,19 @@ public:
BaseSocketSessionForwarder& ddns_forwarder);
~AuthSrvImpl();
- bool processNormalQuery(const IOMessage& io_message, Message& message,
+ bool processNormalQuery(const IOMessage& io_message,
+ ConstEDNSPtr remote_edns, Message& message,
OutputBuffer& buffer,
- auto_ptr<TSIGContext> tsig_context);
+ auto_ptr<TSIGContext> tsig_context,
+ MessageAttributes& stats_attrs);
bool processXfrQuery(const IOMessage& io_message, Message& message,
OutputBuffer& buffer,
- auto_ptr<TSIGContext> tsig_context);
+ auto_ptr<TSIGContext> tsig_context,
+ MessageAttributes& stats_attrs);
bool processNotify(const IOMessage& io_message, Message& message,
OutputBuffer& buffer,
- auto_ptr<TSIGContext> tsig_context);
+ auto_ptr<TSIGContext> tsig_context,
+ MessageAttributes& stats_attrs);
bool processUpdate(const IOMessage& io_message);
IOService io_service_;
@@ -272,10 +281,6 @@ public:
/// The data source client list manager
auth::DataSrcClientsMgr datasrc_clients_mgr_;
- /// Bind the ModuleSpec object in config_session_ with
- /// isc:config::ModuleSpec::validateStatistics.
- void registerStatisticsValidator();
-
/// Socket session forwarder for dynamic update requests
BaseSocketSessionForwarder& ddns_base_forwarder_;
@@ -293,25 +298,17 @@ public:
///
/// \param server The DNSServer as passed to processMessage()
/// \param message The response as constructed by processMessage()
- /// \param stats_attrs Query/response attributes for statistics which is
- /// not in \p messsage.
- /// Note: This parameter is modified inside this method
- /// to store whether the answer has been sent and
- /// the response is truncated.
/// \param done If true, it indicates there is a response.
/// this value will be passed to server->resume(bool)
void resumeServer(isc::asiodns::DNSServer* server,
isc::dns::Message& message,
- statistics::QRAttributes& stats_attrs,
+ MessageAttributes& stats_attrs,
const bool done);
private:
bool xfrout_connected_;
AbstractXfroutClient& xfrout_client_;
- // validateStatistics
- bool validateStatistics(isc::data::ConstElementPtr data) const;
-
auth::Query query_;
};
@@ -423,6 +420,7 @@ public:
void
makeErrorMessage(MessageRenderer& renderer, Message& message,
OutputBuffer& buffer, const Rcode& rcode,
+ MessageAttributes& stats_attrs,
std::auto_ptr<TSIGContext> tsig_context =
std::auto_ptr<TSIGContext>())
{
@@ -455,9 +453,10 @@ makeErrorMessage(MessageRenderer& renderer, Message& message,
message.setRcode(rcode);
- RendererHolder holder(renderer, &buffer);
+ RendererHolder holder(renderer, &buffer, stats_attrs);
if (tsig_context.get() != NULL) {
message.toWire(renderer, *tsig_context);
+ stats_attrs.setResponseTSIG(true);
} else {
message.toWire(renderer);
}
@@ -484,7 +483,6 @@ AuthSrv::setXfrinSession(AbstractSession* xfrin_session) {
void
AuthSrv::setConfigSession(ModuleCCSession* config_session) {
impl_->config_session_ = config_session;
- impl_->registerStatisticsValidator();
}
ModuleCCSession*
@@ -497,11 +495,11 @@ AuthSrv::processMessage(const IOMessage& io_message, Message& message,
OutputBuffer& buffer, DNSServer* server)
{
InputBuffer request_buffer(io_message.getData(), io_message.getDataSize());
- statistics::QRAttributes stats_attrs;
+ MessageAttributes stats_attrs;
- // statistics: check transport carrying the message (IP, transport)
- stats_attrs.setQueryIPVersion(io_message.getRemoteEndpoint().getFamily());
- stats_attrs.setQueryTransportProtocol(
+ stats_attrs.setRequestIPVersion(
+ io_message.getRemoteEndpoint().getFamily());
+ stats_attrs.setRequestTransportProtocol(
io_message.getRemoteEndpoint().getProtocol());
// First, check the header part. If we fail even for the base header,
@@ -522,19 +520,26 @@ AuthSrv::processMessage(const IOMessage& io_message, Message& message,
return;
}
+ const Opcode& opcode = message.getOpcode();
+ // Get opcode at this point; for all requests regardless of message body
+ // sanity check.
+ stats_attrs.setRequestOpCode(opcode);
+
try {
// Parse the message.
message.fromWire(request_buffer);
} catch (const DNSProtocolError& error) {
LOG_DEBUG(auth_logger, DBG_AUTH_DETAIL, AUTH_PACKET_PROTOCOL_FAILURE)
.arg(error.getRcode().toText()).arg(error.what());
- makeErrorMessage(impl_->renderer_, message, buffer, error.getRcode());
+ makeErrorMessage(impl_->renderer_, message, buffer, error.getRcode(),
+ stats_attrs);
impl_->resumeServer(server, message, stats_attrs, true);
return;
} catch (const Exception& ex) {
LOG_DEBUG(auth_logger, DBG_AUTH_DETAIL, AUTH_PACKET_PARSE_FAILED)
.arg(ex.what());
- makeErrorMessage(impl_->renderer_, message, buffer, Rcode::SERVFAIL());
+ makeErrorMessage(impl_->renderer_, message, buffer, Rcode::SERVFAIL(),
+ stats_attrs);
impl_->resumeServer(server, message, stats_attrs, true);
return;
} // other exceptions will be handled at a higher layer.
@@ -558,85 +563,82 @@ AuthSrv::processMessage(const IOMessage& io_message, Message& message,
**impl_->keyring_));
tsig_error = tsig_context->verify(tsig_record, io_message.getData(),
io_message.getDataSize());
- // statistics: check TSIG attributes
- // SIG(0) is currently not implemented in Auth, but it is implemented
- // in BIND 9. At the point we support it, the code to check if the
- // signature is valid would be around here.
- stats_attrs.setQuerySig(true, false,
- tsig_error == TSIGError::NOERROR());
+ stats_attrs.setRequestTSIG(true, tsig_error != TSIGError::NOERROR());
}
if (tsig_error != TSIGError::NOERROR()) {
makeErrorMessage(impl_->renderer_, message, buffer,
- tsig_error.toRcode(), tsig_context);
+ tsig_error.toRcode(), stats_attrs, tsig_context);
impl_->resumeServer(server, message, stats_attrs, true);
return;
}
- const Opcode opcode = message.getOpcode();
bool send_answer = true;
try {
- // statistics: check EDNS
- // note: This can only be reliable after TSIG check succeeds.
+ // note: This can only be reliable after TSIG check succeeds.
ConstEDNSPtr edns = message.getEDNS();
- if (edns != NULL) {
- stats_attrs.setQueryEDNS(true, edns->getVersion() == 0);
- stats_attrs.setQueryDO(edns->getDNSSECAwareness());
+ if (edns) {
+ stats_attrs.setRequestEDNS0(true);
+ stats_attrs.setRequestDO(edns->getDNSSECAwareness());
}
- // statistics: check OpCode
- // note: This can only be reliable after TSIG check succeeds.
- stats_attrs.setQueryOpCode(opcode.getCode());
-
+ // note: This can only be reliable after TSIG check succeeds.
if (opcode == Opcode::NOTIFY()) {
send_answer = impl_->processNotify(io_message, message, buffer,
- tsig_context);
+ tsig_context, stats_attrs);
} else if (opcode == Opcode::UPDATE()) {
if (impl_->ddns_forwarder_) {
send_answer = impl_->processUpdate(io_message);
} else {
makeErrorMessage(impl_->renderer_, message, buffer,
- Rcode::NOTIMP(), tsig_context);
+ Rcode::NOTIMP(), stats_attrs, tsig_context);
}
} else if (opcode != Opcode::QUERY()) {
LOG_DEBUG(auth_logger, DBG_AUTH_DETAIL, AUTH_UNSUPPORTED_OPCODE)
.arg(message.getOpcode().toText());
makeErrorMessage(impl_->renderer_, message, buffer,
- Rcode::NOTIMP(), tsig_context);
+ Rcode::NOTIMP(), stats_attrs, tsig_context);
} else if (message.getRRCount(Message::SECTION_QUESTION) != 1) {
makeErrorMessage(impl_->renderer_, message, buffer,
- Rcode::FORMERR(), tsig_context);
+ Rcode::FORMERR(), stats_attrs, tsig_context);
} else {
ConstQuestionPtr question = *message.beginQuestion();
const RRType& qtype = question->getType();
if (qtype == RRType::AXFR()) {
send_answer = impl_->processXfrQuery(io_message, message,
- buffer, tsig_context);
+ buffer, tsig_context,
+ stats_attrs);
} else if (qtype == RRType::IXFR()) {
send_answer = impl_->processXfrQuery(io_message, message,
- buffer, tsig_context);
+ buffer, tsig_context,
+ stats_attrs);
} else {
- send_answer = impl_->processNormalQuery(io_message, message,
- buffer, tsig_context);
+ send_answer = impl_->processNormalQuery(io_message, edns,
+ message, buffer,
+ tsig_context,
+ stats_attrs);
}
}
} catch (const std::exception& ex) {
LOG_DEBUG(auth_logger, DBG_AUTH_DETAIL, AUTH_RESPONSE_FAILURE)
.arg(ex.what());
- makeErrorMessage(impl_->renderer_, message, buffer, Rcode::SERVFAIL());
+ makeErrorMessage(impl_->renderer_, message, buffer, Rcode::SERVFAIL(),
+ stats_attrs);
} catch (...) {
LOG_DEBUG(auth_logger, DBG_AUTH_DETAIL, AUTH_RESPONSE_FAILURE_UNKNOWN);
- makeErrorMessage(impl_->renderer_, message, buffer, Rcode::SERVFAIL());
+ makeErrorMessage(impl_->renderer_, message, buffer, Rcode::SERVFAIL(),
+ stats_attrs);
}
impl_->resumeServer(server, message, stats_attrs, send_answer);
}
bool
-AuthSrvImpl::processNormalQuery(const IOMessage& io_message, Message& message,
+AuthSrvImpl::processNormalQuery(const IOMessage& io_message,
+ ConstEDNSPtr remote_edns, Message& message,
OutputBuffer& buffer,
- auto_ptr<TSIGContext> tsig_context)
+ auto_ptr<TSIGContext> tsig_context,
+ MessageAttributes& stats_attrs)
{
- ConstEDNSPtr remote_edns = message.getEDNS();
const bool dnssec_ok = remote_edns && remote_edns->getDNSSECAwareness();
const uint16_t remote_bufsize = remote_edns ? remote_edns->getUDPSize() :
Message::DEFAULT_MAX_UDPSIZE;
@@ -666,21 +668,24 @@ AuthSrvImpl::processNormalQuery(const IOMessage& io_message, Message& message,
const Name& qname = question->getName();
query_.process(*list, qname, qtype, message, dnssec_ok);
} else {
- makeErrorMessage(renderer_, message, buffer, Rcode::REFUSED());
+ makeErrorMessage(renderer_, message, buffer, Rcode::REFUSED(),
+ stats_attrs);
return (true);
}
} catch (const Exception& ex) {
LOG_ERROR(auth_logger, AUTH_PROCESS_FAIL).arg(ex.what());
- makeErrorMessage(renderer_, message, buffer, Rcode::SERVFAIL());
+ makeErrorMessage(renderer_, message, buffer, Rcode::SERVFAIL(),
+ stats_attrs);
return (true);
}
- RendererHolder holder(renderer_, &buffer);
+ RendererHolder holder(renderer_, &buffer, stats_attrs);
const bool udp_buffer =
(io_message.getSocket().getProtocol() == IPPROTO_UDP);
renderer_.setLengthLimit(udp_buffer ? remote_bufsize : 65535);
if (tsig_context.get() != NULL) {
message.toWire(renderer_, *tsig_context);
+ stats_attrs.setResponseTSIG(true);
} else {
message.toWire(renderer_);
}
@@ -697,12 +702,13 @@ AuthSrvImpl::processNormalQuery(const IOMessage& io_message, Message& message,
bool
AuthSrvImpl::processXfrQuery(const IOMessage& io_message, Message& message,
OutputBuffer& buffer,
- auto_ptr<TSIGContext> tsig_context)
+ auto_ptr<TSIGContext> tsig_context,
+ MessageAttributes& stats_attrs)
{
if (io_message.getSocket().getProtocol() == IPPROTO_UDP) {
LOG_DEBUG(auth_logger, DBG_AUTH_DETAIL, AUTH_AXFR_UDP);
makeErrorMessage(renderer_, message, buffer, Rcode::FORMERR(),
- tsig_context);
+ stats_attrs, tsig_context);
return (true);
}
@@ -728,7 +734,7 @@ AuthSrvImpl::processXfrQuery(const IOMessage& io_message, Message& message,
LOG_DEBUG(auth_logger, DBG_AUTH_DETAIL, AUTH_AXFR_PROBLEM)
.arg(err.what());
makeErrorMessage(renderer_, message, buffer, Rcode::SERVFAIL(),
- tsig_context);
+ stats_attrs, tsig_context);
return (true);
}
@@ -738,7 +744,8 @@ AuthSrvImpl::processXfrQuery(const IOMessage& io_message, Message& message,
bool
AuthSrvImpl::processNotify(const IOMessage& io_message, Message& message,
OutputBuffer& buffer,
- std::auto_ptr<TSIGContext> tsig_context)
+ std::auto_ptr<TSIGContext> tsig_context,
+ MessageAttributes& stats_attrs)
{
// The incoming notify must contain exactly one question for SOA of the
// zone name.
@@ -746,7 +753,7 @@ AuthSrvImpl::processNotify(const IOMessage& io_message, Message& message,
LOG_DEBUG(auth_logger, DBG_AUTH_DETAIL, AUTH_NOTIFY_QUESTIONS)
.arg(message.getRRCount(Message::SECTION_QUESTION));
makeErrorMessage(renderer_, message, buffer, Rcode::FORMERR(),
- tsig_context);
+ stats_attrs, tsig_context);
return (true);
}
ConstQuestionPtr question = *message.beginQuestion();
@@ -754,7 +761,7 @@ AuthSrvImpl::processNotify(const IOMessage& io_message, Message& message,
LOG_DEBUG(auth_logger, DBG_AUTH_DETAIL, AUTH_NOTIFY_RRTYPE)
.arg(question->getType().toText());
makeErrorMessage(renderer_, message, buffer, Rcode::FORMERR(),
- tsig_context);
+ stats_attrs, tsig_context);
return (true);
}
@@ -812,9 +819,10 @@ AuthSrvImpl::processNotify(const IOMessage& io_message, Message& message,
message.setHeaderFlag(Message::HEADERFLAG_AA);
message.setRcode(Rcode::NOERROR());
- RendererHolder holder(renderer_, &buffer);
+ RendererHolder holder(renderer_, &buffer, stats_attrs);
if (tsig_context.get() != NULL) {
message.toWire(renderer_, *tsig_context);
+ stats_attrs.setResponseTSIG(true);
} else {
message.toWire(renderer_);
}
@@ -822,7 +830,8 @@ AuthSrvImpl::processNotify(const IOMessage& io_message, Message& message,
}
bool
-AuthSrvImpl::processUpdate(const IOMessage& io_message) {
+AuthSrvImpl::processUpdate(const IOMessage& io_message)
+{
// Push the update request to a separate process via the forwarder.
// On successful push, the request shouldn't be responded from b10-auth,
// so we return false.
@@ -831,31 +840,10 @@ AuthSrvImpl::processUpdate(const IOMessage& io_message) {
}
void
-AuthSrvImpl::registerStatisticsValidator() {
- counters_.registerStatisticsValidator(
- boost::bind(&AuthSrvImpl::validateStatistics, this, _1));
-}
-
-bool
-AuthSrvImpl::validateStatistics(isc::data::ConstElementPtr data) const {
- if (config_session_ == NULL) {
- return (false);
- }
- return (
- config_session_->getModuleSpec().validateStatistics(
- data, true));
-}
-
-void
AuthSrvImpl::resumeServer(DNSServer* server, Message& message,
- statistics::QRAttributes& stats_attrs,
+ MessageAttributes& stats_attrs,
const bool done) {
- if (done) {
- stats_attrs.answerWasSent();
- // isTruncated from MessageRenderer
- stats_attrs.setResponseTruncated(renderer_.isTruncated());
- }
- counters_.inc(stats_attrs, message);
+ counters_.inc(stats_attrs, message, done);
server->resume(done);
}
@@ -875,7 +863,7 @@ AuthSrv::updateConfig(ConstElementPtr new_config) {
}
ConstElementPtr AuthSrv::getStatistics() const {
- return (impl_->counters_.getStatistics());
+ return (impl_->counters_.get());
}
const AddressList&
@@ -905,7 +893,8 @@ void
AuthSrv::createDDNSForwarder() {
LOG_DEBUG(auth_logger, DBG_AUTH_OPS, AUTH_START_DDNS_FORWARDER);
impl_->ddns_forwarder_.reset(
- new SocketSessionForwarderHolder("update", impl_->ddns_base_forwarder_));
+ new SocketSessionForwarderHolder("update",
+ impl_->ddns_base_forwarder_));
}
void
diff --git a/src/bin/auth/auth_srv.h b/src/bin/auth/auth_srv.h
index ebd3034..107e2e6 100644
--- a/src/bin/auth/auth_srv.h
+++ b/src/bin/auth/auth_srv.h
@@ -41,9 +41,6 @@
#include <boost/shared_ptr.hpp>
-#include <map>
-#include <string>
-
namespace isc {
namespace util {
namespace io {
@@ -222,7 +219,7 @@ public:
/// \brief Returns statistics data
///
/// This function can throw an exception from
- /// Counters::getStatistics().
+ /// Counters::get().
///
/// \return JSON format statistics data.
isc::data::ConstElementPtr getStatistics() const;
diff --git a/src/bin/auth/b10-auth.xml b/src/bin/auth/b10-auth.xml
deleted file mode 100644
index 00ff42e..0000000
--- a/src/bin/auth/b10-auth.xml
+++ /dev/null
@@ -1,306 +0,0 @@
-<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
- "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"
- [<!ENTITY mdash "—">]>
-<!--
- - Copyright (C) 2010-2012 Internet Systems Consortium, Inc. ("ISC")
- -
- - Permission to use, copy, modify, and/or distribute this software for any
- - purpose with or without fee is hereby granted, provided that the above
- - copyright notice and this permission notice appear in all copies.
- -
- - THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
- - REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
- - AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
- - INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
- - LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
- - OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- - PERFORMANCE OF THIS SOFTWARE.
--->
-
-<refentry>
-
- <refentryinfo>
- <date>December 18, 2012</date>
- </refentryinfo>
-
- <refmeta>
- <refentrytitle>b10-auth</refentrytitle>
- <manvolnum>8</manvolnum>
- <refmiscinfo>BIND10</refmiscinfo>
- </refmeta>
-
- <refnamediv>
- <refname>b10-auth</refname>
- <refpurpose>Authoritative DNS server</refpurpose>
- </refnamediv>
-
- <docinfo>
- <copyright>
- <year>2010-2012</year>
- <holder>Internet Systems Consortium, Inc. ("ISC")</holder>
- </copyright>
- </docinfo>
-
- <refsynopsisdiv>
- <cmdsynopsis>
- <command>b10-auth</command>
- <arg><option>-v</option></arg>
- </cmdsynopsis>
- </refsynopsisdiv>
-
- <refsect1>
- <title>DESCRIPTION</title>
- <para>The <command>b10-auth</command> daemon provides the BIND 10
- authoritative DNS server.
- Normally it is started by the
- <citerefentry><refentrytitle>b10-init</refentrytitle><manvolnum>8</manvolnum></citerefentry>
- process.
- </para>
-
- <para>
- This daemon communicates with other BIND 10 components over a
- <citerefentry><refentrytitle>b10-msgq</refentrytitle><manvolnum>8</manvolnum></citerefentry>
- C-Channel connection. If this connection is not established,
- <command>b10-auth</command> will exit.
-<!-- TODO what if msgq connection closes later, will b10-auth exit? -->
- It receives its configurations from
-<citerefentry><refentrytitle>b10-cfgmgr</refentrytitle><manvolnum>8</manvolnum></citerefentry>.
-
- </para>
-
-<!-- TODO: mention xfrin, xfrout, zonemgr ? -->
-
- </refsect1>
-
- <refsect1>
- <title>OPTIONS</title>
-
- <para>The arguments are as follows:</para>
-
- <variablelist>
- <varlistentry>
- <term><option>-v</option></term>
- <listitem><para>
- Enable verbose logging mode. This enables logging of
- diagnostic messages at the maximum debug level.
- </para></listitem>
- </varlistentry>
-
- </variablelist>
-
- </refsect1>
-
- <refsect1>
- <title>CONFIGURATION AND COMMANDS</title>
- <para>
- The configurable settings are:
- </para>
-
- <para>
- <varname>database_file</varname> defines the path to the
- SQLite3 zone file when using the sqlite datasource.
- The default is
- <filename>/usr/local/var/bind10/zone.sqlite3</filename>.
- </para>
-
- <para>
- <varname>datasources</varname> configures data sources.
- The list items include:
- <varname>type</varname> to define the required data source type
- (such as <quote>memory</quote>);
- <varname>class</varname> to optionally select the class
- (it defaults to <quote>IN</quote>);
- and
- <varname>zones</varname> to define the
- <varname>file</varname> path name,
- <varname>origin</varname> (default domain), and optional
- <varname>filetype</varname>.
- By default, <varname>zones</varname> is empty.
- For the in-memory data source (i.e., the <varname>type</varname>
- is <quote>memory</quote>), the optional <varname>filetype</varname>
- configuration item for <varname>zones</varname> can be
- specified so the in-memory zone data can be built from another
- data source that is based on a database backend (in practice
- with current implementation, it would be an SQLite3 database
- file for the SQLite3 data source).
- See the <citetitle>BIND 10 Guide</citetitle> for configuration
- details.
-
- <note><simpara>
- Only the IN class is supported at this time.
- By default, the memory data source is disabled.
- Also, currently the zone file must be canonical such as
- generated by <command>named-compilezone -D</command>.
- </simpara></note>
- </para>
-
- <para>
- <varname>listen_on</varname> is a list of addresses and ports for
- <command>b10-auth</command> to listen on.
- The list items are the <varname>address</varname> string
- and <varname>port</varname> number.
- By default, <command>b10-auth</command> listens on port 53
- on the IPv6 (::) and IPv4 (0.0.0.0) wildcard addresses.
- </para>
-
- <para>
- <varname>statistics-interval</varname> is the timer interval
- in seconds for <command>b10-auth</command> to share its
- statistics information to
- <citerefentry><refentrytitle>b10-stats</refentrytitle><manvolnum>8</manvolnum></citerefentry>.
- Statistics updates can be disabled by setting this to 0.
- The default is 60.
- </para>
-
- <para>
- <varname>tcp_recv_timeout</varname> is the timeout used on
- incoming TCP connections, in milliseconds. If the query
- is not sent within this time, the connection is closed.
- Setting this to 0 will disable TCP timeouts completely.
- The default is 5000 (five seconds).
- </para>
-
-<!-- TODO: formating -->
- <para>
- The configuration commands are:
- </para>
-
- <para>
- <command>getstats</command> tells <command>b10-auth</command>
- to report its defined statistics data in JSON format.
- It will not report about unused counters.
- This is used by the
- <citerefentry><refentrytitle>b10-stats</refentrytitle><manvolnum>8</manvolnum></citerefentry> daemon.
- (The <command>sendstats</command> command is deprecated.)
- </para>
-
- <para>
- <command>loadzone</command> tells <command>b10-auth</command>
- to load or reload a zone file. The arguments include:
- <varname>class</varname> which optionally defines the class
- (it defaults to <quote>IN</quote>);
- <varname>origin</varname> is the domain name of the zone;
- and
- <varname>datasrc</varname> optionally defines the type of datasource
- (it defaults to <quote>memory</quote>).
-
- <note><simpara>
- In this development version, currently this only supports the
- IN class and the memory data source.
- </simpara></note>
- </para>
-
- <para>
- <command>shutdown</command> exits <command>b10-auth</command>.
- This has an optional <varname>pid</varname> argument to
- select the process ID to stop.
- (Note that the b10-init process may restart this service
- if configured.)
- </para>
-
- <para>
- <command>start_ddns_forwarder</command> starts (or restarts) the
- internal forwarding of DDNS Update messages.
- This is used by the
- <citerefentry><refentrytitle>b10-ddns</refentrytitle><manvolnum>8</manvolnum></citerefentry>
- daemon to tell <command>b10-auth</command> that DDNS Update
- messages can be forwarded.
- <note><simpara>This is not expected to be called by administrators;
- it will be removed as a public command in the future.</simpara></note>
- </para>
-
- <para>
- <command>stop_ddns_forwarder</command> stops the internal
- forwarding of DDNS Update messages.
- This is used by the
- <citerefentry><refentrytitle>b10-ddns</refentrytitle><manvolnum>8</manvolnum></citerefentry>
- daemon to tell <command>b10-auth</command> that DDNS Update
- messages should not be forwarded.
- <note><simpara>This is not expected to be called by administrators;
- it will be removed as a public command in the future.</simpara></note>
- </para>
-
- </refsect1>
-
- <refsect1>
- <title>STATISTICS DATA</title>
-
- <para>
- The statistics data collected by the <command>b10-stats</command>
- daemon for <quote>Auth</quote> include:
- </para>
-
- <variablelist>
-
- <varlistentry>
- <term>queries.tcp</term>
- <listitem><simpara>Total count of queries received by the
- <command>b10-auth</command> server over TCP since startup.
- </simpara></listitem>
- </varlistentry>
-
- <varlistentry>
- <term>queries.udp</term>
- <listitem><simpara>Total count of queries received by the
- <command>b10-auth</command> server over UDP since startup.
- </simpara></listitem>
- </varlistentry>
-
- </variablelist>
-
-<!-- TODO: missing stats docs. See ticket #1721 -->
-
- </refsect1>
-
- <refsect1>
- <title>FILES</title>
- <para>
- <filename>/usr/local/var/bind10/zone.sqlite3</filename>
- — Location for the SQLite3 zone database
- when <emphasis>database_file</emphasis> configuration is not
- defined.
- </para>
- </refsect1>
-
- <refsect1>
- <title>SEE ALSO</title>
- <para>
- <citerefentry>
- <refentrytitle>b10-cfgmgr</refentrytitle><manvolnum>8</manvolnum>
- </citerefentry>,
- <citerefentry>
- <refentrytitle>b10-ddns</refentrytitle><manvolnum>8</manvolnum>
- </citerefentry>,
- <citerefentry>
- <refentrytitle>b10-init</refentrytitle><manvolnum>8</manvolnum>
- </citerefentry>,
- <citerefentry>
- <refentrytitle>b10-loadzone</refentrytitle><manvolnum>8</manvolnum>
- </citerefentry>,
- <citerefentry>
- <refentrytitle>b10-msgq</refentrytitle><manvolnum>8</manvolnum>
- </citerefentry>,
- <citerefentry>
- <refentrytitle>b10-stats</refentrytitle><manvolnum>8</manvolnum>
- </citerefentry>,
- <citerefentry>
- <refentrytitle>b10-zonemgr</refentrytitle><manvolnum>8</manvolnum>
- </citerefentry>,
- <citerefentry>
- <refentrytitle>bind10</refentrytitle><manvolnum>8</manvolnum>
- </citerefentry>,
- <citetitle>BIND 10 Guide</citetitle>.
- </para>
- </refsect1>
-
- <refsect1>
- <title>HISTORY</title>
- <para>
- The <command>b10-auth</command> daemon was first coded in October 2009.
- </para>
- </refsect1>
-</refentry><!--
- - Local variables:
- - mode: sgml
- - End:
--->
diff --git a/src/bin/auth/b10-auth.xml.pre b/src/bin/auth/b10-auth.xml.pre
new file mode 100644
index 0000000..db5be3e
--- /dev/null
+++ b/src/bin/auth/b10-auth.xml.pre
@@ -0,0 +1,306 @@
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"
+ [<!ENTITY mdash "—">]>
+<!--
+ - Copyright (C) 2010-2012 Internet Systems Consortium, Inc. ("ISC")
+ -
+ - Permission to use, copy, modify, and/or distribute this software for any
+ - purpose with or without fee is hereby granted, provided that the above
+ - copyright notice and this permission notice appear in all copies.
+ -
+ - THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ - REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ - AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ - INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ - LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ - OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ - PERFORMANCE OF THIS SOFTWARE.
+-->
+
+<refentry>
+
+ <refentryinfo>
+ <date>February 5, 2013</date>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle>b10-auth</refentrytitle>
+ <manvolnum>8</manvolnum>
+ <refmiscinfo>BIND10</refmiscinfo>
+ </refmeta>
+
+ <refnamediv>
+ <refname>b10-auth</refname>
+ <refpurpose>Authoritative DNS server</refpurpose>
+ </refnamediv>
+
+ <docinfo>
+ <copyright>
+ <year>2010-2012</year>
+ <holder>Internet Systems Consortium, Inc. ("ISC")</holder>
+ </copyright>
+ </docinfo>
+
+ <refsynopsisdiv>
+ <cmdsynopsis>
+ <command>b10-auth</command>
+ <arg><option>-v</option></arg>
+ </cmdsynopsis>
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>DESCRIPTION</title>
+ <para>The <command>b10-auth</command> daemon provides the BIND 10
+ authoritative DNS server.
+ Normally it is started by the
+ <citerefentry><refentrytitle>b10-init</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+ process.
+ </para>
+
+ <para>
+ This daemon communicates with other BIND 10 components over a
+ <citerefentry><refentrytitle>b10-msgq</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+ C-Channel connection. If this connection is not established,
+ <command>b10-auth</command> will exit.
+<!-- TODO what if msgq connection closes later, will b10-auth exit? -->
+ It receives its configurations from
+<citerefentry><refentrytitle>b10-cfgmgr</refentrytitle><manvolnum>8</manvolnum></citerefentry>.
+
+ </para>
+
+<!-- TODO: mention xfrin, xfrout, zonemgr ? -->
+
+ </refsect1>
+
+ <refsect1>
+ <title>OPTIONS</title>
+
+ <para>The arguments are as follows:</para>
+
+ <variablelist>
+ <varlistentry>
+ <term><option>-v</option></term>
+ <listitem><para>
+ Enable verbose logging mode. This enables logging of
+ diagnostic messages at the maximum debug level.
+ </para></listitem>
+ </varlistentry>
+
+ </variablelist>
+
+ </refsect1>
+
+ <refsect1>
+ <title>CONFIGURATION AND COMMANDS</title>
+ <para>
+ The configurable settings are:
+ </para>
+
+ <para>
+ <varname>database_file</varname> defines the path to the
+ SQLite3 zone file when using the sqlite datasource.
+ The default is
+ <filename>@@LOCALSTATEDIR@@/bind10/zone.sqlite3</filename>.
+ </para>
+
+ <para>
+ <varname>datasources</varname> configures data sources.
+ The list items include:
+ <varname>type</varname> to define the required data source type
+ (such as <quote>memory</quote>);
+ <varname>class</varname> to optionally select the class
+ (it defaults to <quote>IN</quote>);
+ and
+ <varname>zones</varname> to define the
+ <varname>file</varname> path name,
+ <varname>origin</varname> (default domain), and optional
+ <varname>filetype</varname>.
+ By default, <varname>zones</varname> is empty.
+ For the in-memory data source (i.e., the <varname>type</varname>
+ is <quote>memory</quote>), the optional <varname>filetype</varname>
+ configuration item for <varname>zones</varname> can be
+ specified so the in-memory zone data can be built from another
+ data source that is based on a database backend (in practice
+ with current implementation, it would be an SQLite3 database
+ file for the SQLite3 data source).
+ See the <citetitle>BIND 10 Guide</citetitle> for configuration
+ details.
+
+ <note><simpara>
+ Only the IN class is supported at this time.
+ By default, the memory data source is disabled.
+ Also, currently the zone file must be canonical such as
+ generated by <command>named-compilezone -D</command>.
+ </simpara></note>
+ </para>
+
+ <para>
+ <varname>listen_on</varname> is a list of addresses and ports for
+ <command>b10-auth</command> to listen on.
+ The list items are the <varname>address</varname> string
+ and <varname>port</varname> number.
+ By default, <command>b10-auth</command> listens on port 53
+ on the IPv6 (::) and IPv4 (0.0.0.0) wildcard addresses.
+ </para>
+
+ <para>
+ <varname>tcp_recv_timeout</varname> is the timeout used on
+ incoming TCP connections, in milliseconds. If the query
+ is not sent within this time, the connection is closed.
+ Setting this to 0 will disable TCP timeouts completely.
+ The default is 5000 (five seconds).
+ </para>
+
+<!-- TODO: formating -->
+ <para>
+ The configuration commands are:
+ </para>
+
+ <para>
+ <command>getstats</command> tells <command>b10-auth</command>
+ to report its defined statistics data in JSON format.
+ It will not report about unused counters.
+ This is used by the
+ <citerefentry><refentrytitle>b10-stats</refentrytitle><manvolnum>8</manvolnum></citerefentry> daemon.
+ (The <command>sendstats</command> command is deprecated.)
+ </para>
+
+ <para>
+ <command>loadzone</command> tells <command>b10-auth</command>
+ to load or reload a zone file. The arguments include:
+ <varname>class</varname> which optionally defines the class
+ (it defaults to <quote>IN</quote>);
+ <varname>origin</varname> is the domain name of the zone;
+ and
+ <varname>datasrc</varname> optionally defines the type of datasource
+ (it defaults to <quote>memory</quote>).
+
+ <note><simpara>
+ In this development version, currently this only supports the
+ IN class and the memory data source.
+ </simpara></note>
+ </para>
+
+ <para>
+ <command>getstats</command> tells <command>b10-auth</command>
+ to send its statistics data.
+ </para>
+
+ <para>
+ <command>shutdown</command> exits <command>b10-auth</command>.
+ This has an optional <varname>pid</varname> argument to
+ select the process ID to stop.
+ (Note that the b10-init process may restart this service
+ if configured.)
+ </para>
+
+ <para>
+ <command>start_ddns_forwarder</command> starts (or restarts) the
+ internal forwarding of DDNS Update messages.
+ This is used by the
+ <citerefentry><refentrytitle>b10-ddns</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+ daemon to tell <command>b10-auth</command> that DDNS Update
+ messages can be forwarded.
+ <note><simpara>This is not expected to be called by administrators;
+ it will be removed as a public command in the future.</simpara></note>
+ </para>
+
+ <para>
+ <command>stop_ddns_forwarder</command> stops the internal
+ forwarding of DDNS Update messages.
+ This is used by the
+ <citerefentry><refentrytitle>b10-ddns</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+ daemon to tell <command>b10-auth</command> that DDNS Update
+ messages should not be forwarded.
+ <note><simpara>This is not expected to be called by administrators;
+ it will be removed as a public command in the future.</simpara></note>
+ </para>
+
+ </refsect1>
+
+ <refsect1>
+ <title>STATISTICS DATA</title>
+
+ <para>
+ The statistics data collected by the <command>b10-stats</command>
+ daemon for <quote>Auth</quote> include:
+ </para>
+
+<!-- ### STATISTICS DATA PLACEHOLDER ### -->
+
+ <note>
+ <para>
+ Opcode of a request message will not be counted if:
+ <itemizedlist>
+ <listitem><para>
+ The request message is too short to parse the message header
+ </para></listitem>
+ <listitem><para>
+ The request message is a response (i.e. QR bit is set)
+ </para></listitem>
+ </itemizedlist>
+ </para>
+
+ <para>
+ Request attributes except for opcode will not be counted if TSIG
+ validation failed as they are not reliable.
+ We always count opcode mainly for compatibility with BIND 9,
+ but remember that if there's any error related to TSIG, some
+ of the counted opcode may not be trustworthy.
+ </para>
+ </note>
+
+ </refsect1>
+
+ <refsect1>
+ <title>FILES</title>
+ <para>
+ <filename>@@LOCALSTATEDIR@@/bind10/zone.sqlite3</filename>
+ — Location for the SQLite3 zone database
+ when <emphasis>database_file</emphasis> configuration is not
+ defined.
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>SEE ALSO</title>
+ <para>
+ <citerefentry>
+ <refentrytitle>b10-cfgmgr</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>b10-ddns</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>b10-init</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>b10-loadzone</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>b10-msgq</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>b10-stats</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>b10-zonemgr</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>bind10</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>,
+ <citetitle>BIND 10 Guide</citetitle>.
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>HISTORY</title>
+ <para>
+ The <command>b10-auth</command> daemon was first coded in October 2009.
+ </para>
+ </refsect1>
+</refentry><!--
+ - Local variables:
+ - mode: sgml
+ - End:
+-->
diff --git a/src/bin/auth/gen-statisticsitems.py.pre.in b/src/bin/auth/gen-statisticsitems.py.pre.in
new file mode 100755
index 0000000..e2d1623
--- /dev/null
+++ b/src/bin/auth/gen-statisticsitems.py.pre.in
@@ -0,0 +1,385 @@
+#!@PYTHON@
+
+# Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC")
+#
+# Permission to use, copy, modify, and/or distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+# PERFORMANCE OF THIS SOFTWARE.
+
+"""\
+This script generates spec file, docbook XML and some part of statistics code
+from statistics_msg_items.def.
+"""
+
+import os
+import re
+import sys
+import json
+from xml.etree import ElementTree
+
+item_list = []
+localstatedir = '@@LOCALSTATEDIR@@'
+builddir = '@builddir@'
+srcdir = '@srcdir@'
+pre_suffix = '.pre'
+
+xmldocument_command_name = 'b10-auth'
+
+def need_generate(filepath, prepath, mtime):
+ '''Check if we need to generate the specified file.
+
+ To avoid unnecessary compilation, we skip (re)generating the file when
+ the file already exists and newer than the base file, and definition file
+ specified with mtime.
+ '''
+ if os.path.exists(filepath) and\
+ (os.path.getmtime(filepath) > mtime and
+ os.path.getmtime(filepath) > os.path.getmtime(prepath)):
+ return False
+ return True
+
+def import_definitions():
+ '''Load statsitics items definitions from statistics_msg_items.def.
+
+ statistics_msg_items.def defines a tree of message statistics items.
+ Syntax:
+ Each line describes a node; branch node for subset of counters,
+ leaf node for a counter item.
+ Each fields are separated with one or more field separator (Tab).
+ Field separator in the head of a line is ignored.
+
+ branch node:
+ (item name)\t+(internal branch name)\t+(description of the item)\t+'='
+ leaf node:
+ (item name)\t+(internal item counter name)\t+(description of the item)
+
+ Branch nodes contain leaf nodes and/or branch nodes. The end of
+ a branch node is indicated with ';' as item name (first column).
+
+ Internal branch name and internal item counter name must be unique.
+
+ Returns mtime of statistics_msg_items.def. It will be used to check
+ auto-generated files need to be regenerated.
+ '''
+ global item_list
+
+ items_definition_file = srcdir + os.sep + 'statistics_msg_items.def'
+ with open(items_definition_file, 'r') as item_definition:
+ re_splitter = re.compile('\t+')
+ l = item_list
+ lp = None
+ for line in item_definition.readlines():
+ element = re_splitter.split(line.rstrip())
+ # pop first element if it is empty to skip indent
+ if element[0] == '':
+ element.pop(0)
+
+ # last element is '=': a branch node definition.
+ if element[-1] == '=':
+ l.append({'name': element[0], 'child': [], 'index': element[1],
+ 'description': element[2], 'parent': lp})
+ lp = l
+ l = l[-1]['child']
+ # last element is ';': end of a branch node.
+ elif element[-1] == ';':
+ l = lp
+ lp = l[-1]['parent']
+ # otherwise, a leaf node definition.
+ else:
+ l.append({'name': element[0], 'child': None,
+ 'index': element[1], 'description': element[2],
+ 'parent': lp})
+ return os.path.getmtime(items_definition_file)
+
+def generate_specfile(specfile, def_mtime):
+ '''Generate spec in specfile from skeleton (specfille+'.pre').
+ If the specfile is newer than both skeleton and def_mtime, file generation
+ will be skipped.
+
+ This method reads the content of skeleton and appends statistics items
+ definition into { "module_spec": { "statistics": } }.
+ LOCALSTATEDIR is also expanded.
+
+ Returns nothing.
+ '''
+
+ def convert_list(items, prefix=''):
+ spec_list = []
+ default_map = {}
+ for item in items:
+ full_item_name = prefix + item['name']
+ if item['child'] is None:
+ default_map[item['name']] = 0
+ spec_list.append({
+ 'item_name': item['name'],
+ 'item_optional': False,
+ 'item_type': 'integer',
+ 'item_default': 0,
+ 'item_title': full_item_name,
+ 'item_description': item['description'],
+ })
+ else:
+ child_spec_list, child_default_map = \
+ convert_list(item['child'], full_item_name + '.')
+ spec_list.append({
+ 'item_name': item['name'],
+ 'item_type': 'map',
+ 'item_optional': False,
+ 'item_title': full_item_name,
+ 'item_description': item['description'],
+ 'item_default': child_default_map,
+ 'map_item_spec': child_spec_list,
+ })
+ default_map[item['name']] = child_default_map
+ return spec_list, default_map
+
+ item_spec_list, item_default_map = convert_list(item_list)
+
+ statistics_spec_list = [{
+ 'item_name': 'zones',
+ 'item_type': 'named_set',
+ 'item_optional': False,
+ 'item_title': 'Zone statistics',
+ 'item_description':
+ 'Zone statistics items. ' +
+ "Items for all zones are stored in '_SERVER_'.",
+ 'item_default': { '_SERVER_': item_default_map },
+ 'named_set_item_spec': {
+ 'item_name': 'zone',
+ 'item_type': 'map',
+ 'item_optional': False,
+ 'item_default': {},
+ 'map_item_spec': item_spec_list,
+ },
+ }]
+
+ if need_generate(builddir+os.sep+specfile,
+ builddir+os.sep+specfile+pre_suffix, def_mtime):
+ with open(builddir+os.sep+specfile+pre_suffix, 'r') as stats_pre:
+ # split LOCALSTATEDIR to avoid substitution
+ stats_pre_json = \
+ json.loads(stats_pre.read().replace('@@LOCAL'+'STATEDIR@@',
+ localstatedir))
+ stats_pre_json['module_spec']['statistics'] = statistics_spec_list
+ statistics_spec_json = json.dumps(stats_pre_json, sort_keys=True,
+ indent=2)
+ with open(builddir+os.sep+specfile, 'w') as stats_spec:
+ stats_spec.write(statistics_spec_json)
+ else:
+ print('skip generating ' + specfile)
+ return
+
+def generate_docfile(docfile, def_mtime):
+ '''Generate docbook XML in docfile from skeleton (docfile+'.pre').
+ If the docfile is newer than both skeleton and def_mtime, file generation
+ will be skipped.
+
+ This method reads the content of skeleton and replaces
+ <!-- ### STATISTICS DATA PLACEHOLDER ### --> with statistics items
+ definition. LOCALSTATEDIR is also expanded.
+
+ Returns nothing.
+ '''
+ def convert_list(items, tree, prefix=''):
+ '''
+ Build XML tree from items.
+ <varlistentry>
+ <term>##item_full_name##</term>
+ <listitem><simpara>##item_description##</simpara></listitem>
+ </varlistentry>
+ xmldocument_command_name in item_description is put inside <command>
+ element.
+ '''
+ for item in items:
+ full_item_name = prefix + item['name']
+ if item['child'] is None:
+ # the item is a leaf node: build varlistentry
+ child_element = ElementTree.SubElement(tree, 'varlistentry')
+ term = ElementTree.SubElement(child_element, 'term')
+ term.text = full_item_name
+ list_item = ElementTree.SubElement(child_element, 'listitem')
+ sim_para = ElementTree.SubElement(list_item, 'simpara')
+ sim_para.text = ''
+ prev = None
+ # put xmldocument_command_name in <command> node
+ for word in item['description'].split():
+ if word == xmldocument_command_name:
+ command = ElementTree.SubElement(sim_para, 'command')
+ command.text = word
+ # at this point command.tail is None
+ # append a space as trailing text for the next word
+ # so it can be concatenated with trailing words
+ command.tail = ' '
+ prev = command
+ else:
+ if prev is None:
+ sim_para.text += word + ' '
+ else:
+ prev.tail += word + ' '
+ # remove trailing whitespaces at the end of the description
+ if prev is None:
+ sim_para.text = sim_para.text.rstrip()
+ else:
+ prev.tail = prev.tail.rstrip()
+ else:
+ # the item is a branch node: call myself for child nodes
+ convert_list(item['child'], tree, full_item_name + '.')
+ return
+
+ if need_generate(builddir+os.sep+docfile,
+ srcdir+os.sep+docfile+pre_suffix, def_mtime):
+ with open(srcdir+os.sep+docfile+pre_suffix, 'r') as doc_pre:
+ # split LOCALSTATEDIR to avoid substitution
+ doc_pre_xml = doc_pre.read().replace('@@LOCAL'+'STATEDIR@@',
+ localstatedir)
+
+ variable_tree = ElementTree.Element('variablelist')
+ convert_list(item_list, variable_tree)
+ pretty_xml = ElementTree.tostring(variable_tree)
+ if not isinstance(pretty_xml, str):
+ pretty_xml = pretty_xml.decode('utf-8')
+ # put newline around <variablelist> and <varlistentry> element
+ pretty_xml = \
+ re.sub(r'(</?var(?:iablelist|listentry)>)', r'\1\n', pretty_xml)
+ # indent <term> and <listitem>
+ pretty_xml = \
+ re.sub(r'(<(?:term|listitem)>)', r' \1', pretty_xml)
+ # put newline after </term> and </listitem>
+ pretty_xml = \
+ re.sub(r'(</(?:term|listitem)>)', r'\1\n', pretty_xml)
+
+ with open(builddir+os.sep+docfile, 'w') as doc:
+ doc.write(doc_pre_xml.replace(
+ '<!-- ### STATISTICS DATA PLACEHOLDER ### -->',
+ pretty_xml))
+ else:
+ print('skip generating ' + docfile)
+ return
+
+def generate_cxx(itemsfile, ccfile, utfile, def_mtime):
+ '''Generate some part of statistics code in itemsfile, ccfile, utfile from
+ skeleton (itemsfile+'.pre', ccfile+'.pre', utfile+'.pre').
+ If the file is newer than both skeleton and def_mtime, file generation
+ will be skipped.
+
+ This method reads the content of skeleton and replaces
+ // ### STATISTICS ITEMS DEFINITION ### with statistics items definition in
+ ccfile and utfile,
+ // ### STATISTICS ITEMS DECLARATION ### with statistics items declaration
+ in itemsfile.
+
+ Returns nothing.
+ '''
+ msg_counter_types = ['enum MSGCounterType {']
+ item_names = ['// using -1 as counter_id to state it is not a '
+ + 'counter item']
+ item_names += ['const int NOT_ITEM = -1;', '']
+
+ def convert_list(items, item_head, msg_counter_types, item_names):
+ '''Convert item tree to a set of C++ code fragment in given lists.
+
+ This method recursively builds two lists:
+ - msg_counter_types consists of strings for all leaf items, each
+ defines one enum element with a comment, e.g.
+ COUNTER_ITEM, ///< item's descriptin
+ - item_names consists of tuples of three elements, depending on
+ whether it's a leaf element (no child from it) or not:
+ (leaf) ( "item_name", NULL, COUNTER_ITEM )
+ (branch) ( "item_name", CHILD_NAME, NOT_ITEM )
+
+ Each single call to this function builds a C++ structure beginning
+ with the given item_head, which is a string that reads like
+ 'const struct CounterSpec some_counters[] = {'
+ followed by the item_names tuples corresponding to that level.
+ If some of the items of this level have a child, recursive calls
+ to this function extends msg_counter_types and item_names.
+ item_names for this level will be concatenated at the end end of
+ the given item_names.
+
+ '''
+ item_names_current = [item_head]
+ for item in items:
+ item_spec = ' { "' + item['name'] + '", '
+ if item['child'] is None:
+ item_spec += 'NULL, ' + item['index']
+ msg_counter_types.append(' ' + item['index'] + ', ' +
+ '///< ' + item['description'])
+ else:
+ item_spec += item['index'] + ', NOT_ITEM'
+ child_head = 'const struct CounterSpec ' + \
+ item['index'] + '[] = {'
+ convert_list(item['child'], child_head,
+ msg_counter_types, item_names)
+ item_names_current.append(item_spec + ' },')
+
+ item_names_current.append(' { NULL, NULL, NOT_ITEM }\n};')
+ item_names.extend(item_names_current)
+
+ convert_list(item_list, 'const struct CounterSpec msg_counter_tree[] = {',
+ msg_counter_types, item_names)
+ msg_counter_types.extend([
+ ' // End of counter types',
+ ' MSG_COUNTER_TYPES ///< The number of defined counters',
+ '};'])
+
+ item_decls = '\n'.join(msg_counter_types)
+ item_defs = '\n'.join(item_names)
+
+ if need_generate(builddir+os.sep+itemsfile,
+ srcdir+os.sep+itemsfile+pre_suffix, def_mtime):
+ with open(srcdir+os.sep+itemsfile+pre_suffix, 'r') \
+ as statistics_items_h_pre:
+ items_pre = statistics_items_h_pre.read()
+
+ with open(builddir+os.sep+itemsfile, 'w') as statistics_items_h:
+ statistics_items_h.write(items_pre.replace(
+ '// ### STATISTICS ITEMS DECLARATION ###', item_decls))
+ else:
+ print('skip generating ' + itemsfile)
+
+ if need_generate(builddir+os.sep+ccfile,
+ srcdir+os.sep+ccfile+pre_suffix, def_mtime):
+ with open(srcdir+os.sep+ccfile+pre_suffix, 'r') as statistics_cc_pre:
+ items_pre = statistics_cc_pre.read()
+
+ with open(builddir+os.sep+ccfile, 'w') as statistics_cc:
+ statistics_cc.write(items_pre.replace(
+ '// ### STATISTICS ITEMS DEFINITION ###', item_defs))
+ else:
+ print('skip generating ' + ccfile)
+
+ if need_generate(builddir+os.sep+utfile,
+ srcdir+os.sep+utfile+pre_suffix, def_mtime):
+ with open(srcdir+os.sep+utfile+pre_suffix, 'r') \
+ as statistics_ut_cc_pre:
+ items_pre = statistics_ut_cc_pre.read()
+
+ with open(builddir+os.sep+utfile, 'w') as statistics_ut_cc:
+ statistics_ut_cc.write(items_pre.replace(
+ '// ### STATISTICS ITEMS DEFINITION ###', item_defs))
+ else:
+ print('skip generating ' + utfile)
+
+ return
+
+if __name__ == "__main__":
+ try:
+ def_mtime = import_definitions()
+ generate_specfile('auth.spec', def_mtime)
+ generate_docfile('b10-auth.xml', def_mtime)
+ generate_cxx('statistics_items.h',
+ 'statistics.cc',
+ 'tests'+os.sep+'statistics_unittest.cc',
+ def_mtime)
+ except:
+ sys.stderr.write('File generation failed due to exception: %s\n' %
+ sys.exc_info()[1])
+ exit(1)
diff --git a/src/bin/auth/statistics.cc b/src/bin/auth/statistics.cc
deleted file mode 100644
index b310b23..0000000
--- a/src/bin/auth/statistics.cc
+++ /dev/null
@@ -1,284 +0,0 @@
-// Copyright (C) 2010 Internet Systems Consortium, Inc. ("ISC")
-//
-// Permission to use, copy, modify, and/or distribute this software for any
-// purpose with or without fee is hereby granted, provided that the above
-// copyright notice and this permission notice appear in all copies.
-//
-// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
-// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
-// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
-// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
-// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
-// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
-// PERFORMANCE OF THIS SOFTWARE.
-
-#include <auth/statistics.h>
-#include <auth/statistics_items.h>
-#include <auth/auth_log.h>
-
-#include <dns/opcode.h>
-#include <dns/rcode.h>
-
-#include <cc/data.h>
-#include <cc/session.h>
-
-#include <statistics/counter.h>
-#include <statistics/counter_dict.h>
-
-#include <algorithm>
-#include <cctype>
-#include <cassert>
-#include <string>
-#include <sstream>
-#include <iostream>
-
-#include <boost/noncopyable.hpp>
-
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <netdb.h>
-
-using namespace isc::dns;
-using namespace isc::auth;
-using namespace isc::statistics;
-
-namespace isc {
-namespace auth {
-namespace statistics {
-
-// TODO: Make use of wrappers like isc::dns::Opcode
-// for counter item type.
-
-class CountersImpl : boost::noncopyable {
-public:
- CountersImpl();
- ~CountersImpl();
- void inc(const QRAttributes& qrattrs, const Message& response);
- isc::data::ConstElementPtr getStatistics() const;
- void registerStatisticsValidator(Counters::validator_type validator);
-private:
- // counter for query/response
- Counter server_qr_counter_;
- // set of counters for zones
- CounterDictionary zone_qr_counters_;
- // validator
- Counters::validator_type validator_;
-};
-
-CountersImpl::CountersImpl() :
- // size of server_qr_counter_, zone_qr_counters_: QR_COUNTER_TYPES
- server_qr_counter_(QR_COUNTER_TYPES),
- zone_qr_counters_(QR_COUNTER_TYPES),
- validator_()
-{}
-
-CountersImpl::~CountersImpl()
-{}
-
-void
-CountersImpl::inc(const QRAttributes& qrattrs, const Message& response) {
- // protocols carrying request
- if (qrattrs.req_ip_version_ == AF_INET) {
- server_qr_counter_.inc(QR_REQUEST_IPV4);
- } else if (qrattrs.req_ip_version_ == AF_INET6) {
- server_qr_counter_.inc(QR_REQUEST_IPV6);
- }
- if (qrattrs.req_transport_protocol_ == IPPROTO_UDP) {
- server_qr_counter_.inc(QR_REQUEST_UDP);
- } else if (qrattrs.req_transport_protocol_ == IPPROTO_TCP) {
- server_qr_counter_.inc(QR_REQUEST_TCP);
- }
-
- // query TSIG
- if (qrattrs.req_is_tsig_) {
- server_qr_counter_.inc(QR_REQUEST_TSIG);
- }
- if (qrattrs.req_is_sig0_) {
- server_qr_counter_.inc(QR_REQUEST_SIG0);
- }
- if (qrattrs.req_is_badsig_) {
- server_qr_counter_.inc(QR_REQUEST_BADSIG);
- // If signature validation is failed, no other attributes are reliable
- return;
- }
-
- // query EDNS
- if (qrattrs.req_is_edns_0_) {
- server_qr_counter_.inc(QR_REQUEST_EDNS0);
- }
- if (qrattrs.req_is_edns_badver_) {
- server_qr_counter_.inc(QR_REQUEST_BADEDNSVER);
- }
-
- // query DNSSEC
- if (qrattrs.req_is_dnssec_ok_) {
- server_qr_counter_.inc(QR_REQUEST_DNSSEC_OK);
- }
-
- // QTYPE
- unsigned int qtype_type = QR_QTYPE_OTHER;
- const QuestionIterator qiter = response.beginQuestion();
- if (qiter != response.endQuestion()) {
- // get the first and only question section and
- // get the qtype code
- const unsigned int qtype = (*qiter)->getType().getCode();
- if (qtype < 258) {
- // qtype 0..257: lookup qtype-countertype table
- qtype_type = QRQTypeToQRCounterType[qtype];
- } else if (qtype < 32768) {
- // qtype 258..32767: (Unassigned)
- qtype_type = QR_QTYPE_OTHER;
- } else if (qtype < 32770) {
- // qtype 32768..32769: TA and DLV
- qtype_type = QR_QTYPE_TA + (qtype - 32768);
- } else {
- // qtype 32770..65535: (Unassigned, Private use, Reserved)
- qtype_type = QR_QTYPE_OTHER;
- }
- }
- server_qr_counter_.inc(qtype_type);
- // OPCODE
- server_qr_counter_.inc(QROpCodeToQRCounterType[qrattrs.req_opcode_]);
-
- // response
- if (qrattrs.answer_sent_) {
- // responded
- server_qr_counter_.inc(QR_RESPONSE);
-
- // response truncated
- if (qrattrs.res_is_truncated_) {
- server_qr_counter_.inc(QR_RESPONSE_TRUNCATED);
- }
-
- // response EDNS
- ConstEDNSPtr response_edns = response.getEDNS();
- if (response_edns != NULL && response_edns->getVersion() == 0) {
- server_qr_counter_.inc(QR_RESPONSE_EDNS0);
- }
-
- // response TSIG
- if (qrattrs.req_is_tsig_) {
- // assume response is TSIG signed if request is TSIG signed
- server_qr_counter_.inc(QR_RESPONSE_TSIG);
- }
-
- // response SIG(0) is currently not implemented
-
- // RCODE
- const unsigned int rcode = response.getRcode().getCode();
- unsigned int rcode_type = QR_RCODE_OTHER;
- if (rcode < 23) {
- // rcode 0..22: lookup rcode-countertype table
- rcode_type = QRRCodeToQRCounterType[rcode];
- } else {
- // opcode larger than 22 is reserved or unassigned
- rcode_type = QR_RCODE_OTHER;
- }
- server_qr_counter_.inc(rcode_type);
-
- // compound attributes
- const unsigned int answer_rrs =
- response.getRRCount(Message::SECTION_ANSWER);
- const bool is_aa_set = response.getHeaderFlag(Message::HEADERFLAG_AA);
-
- if (is_aa_set) {
- // QryAuthAns
- server_qr_counter_.inc(QR_QRYAUTHANS);
- } else {
- // QryNoAuthAns
- server_qr_counter_.inc(QR_QRYNOAUTHANS);
- }
-
- if (rcode == Rcode::NOERROR_CODE) {
- if (answer_rrs > 0) {
- // QrySuccess
- server_qr_counter_.inc(QR_QRYSUCCESS);
- } else {
- if (is_aa_set) {
- // QryNxrrset
- server_qr_counter_.inc(QR_QRYNXRRSET);
- } else {
- // QryReferral
- server_qr_counter_.inc(QR_QRYREFERRAL);
- }
- }
- } else if (rcode == Rcode::REFUSED_CODE) {
- // AuthRej
- server_qr_counter_.inc(QR_QRYREJECT);
- }
- }
-}
-
-isc::data::ConstElementPtr
-CountersImpl::getStatistics() const {
- std::stringstream statistics_string;
- statistics_string << "{ \"queries.udp\": "
- << server_qr_counter_.get(QR_REQUEST_UDP)
- << ", \"queries.tcp\": "
- << server_qr_counter_.get(QR_REQUEST_TCP);
- // Insert non 0 Opcode counters.
- for (int i = QR_OPCODE_QUERY; i <= QR_OPCODE_OTHER; ++i) {
- const Counter::Type counter = server_qr_counter_.get(i);
- if (counter != 0) {
- statistics_string << ", \"" << "opcode." <<
- QRCounterOpcode[i - QR_OPCODE_QUERY].name <<
- "\": " << counter;
- }
- }
- // Insert non 0 Rcode counters.
- for (int i = QR_RCODE_NOERROR; i <= QR_RCODE_OTHER; ++i) {
- const Counter::Type counter = server_qr_counter_.get(i);
- if (counter != 0) {
- statistics_string << ", \"" << "rcode." <<
- QRCounterRcode[i - QR_RCODE_NOERROR].name <<
- "\": " << counter;
- }
- }
- statistics_string << "}";
-
- isc::data::ConstElementPtr statistics_element =
- isc::data::Element::fromJSON(statistics_string);
- // validate the statistics data before send
- if (validator_) {
- if (!validator_(statistics_element)) {
- LOG_ERROR(auth_logger, AUTH_INVALID_STATISTICS_DATA);
- return (isc::data::ElementPtr());
- }
- }
- return (statistics_element);
-}
-
-void
-CountersImpl::registerStatisticsValidator
- (Counters::validator_type validator)
-{
- validator_ = validator;
-}
-
-Counters::Counters() : impl_(new CountersImpl())
-{}
-
-Counters::~Counters() {}
-
-void
-Counters::inc(const QRAttributes& qrattrs, const Message& response) {
- impl_->inc(qrattrs, response);
-}
-
-isc::data::ConstElementPtr
-Counters::getStatistics() const {
- return (impl_->getStatistics());
-}
-
-void
-Counters::registerStatisticsValidator
- (Counters::validator_type validator) const
-{
- return (impl_->registerStatisticsValidator(validator));
-}
-
-} // namespace statistics
-} // namespace auth
-} // namespace isc
diff --git a/src/bin/auth/statistics.cc.pre b/src/bin/auth/statistics.cc.pre
new file mode 100644
index 0000000..21141b0
--- /dev/null
+++ b/src/bin/auth/statistics.cc.pre
@@ -0,0 +1,277 @@
+// Copyright (C) 2010 Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#include <auth/statistics.h>
+#include <auth/statistics_items.h>
+#include <auth/auth_log.h>
+
+#include <cc/data.h>
+
+#include <dns/message.h>
+#include <dns/opcode.h>
+#include <dns/rcode.h>
+
+#include <statistics/counter.h>
+
+#include <boost/optional.hpp>
+
+using namespace isc::dns;
+using namespace isc::auth;
+using namespace isc::statistics;
+using namespace isc::auth::statistics;
+
+namespace {
+
+/// \brief Fill isc::data::ElementPtr with given counter.
+/// \param counter Counter which stores values to fill
+/// \param type_tree CounterSpec corresponding to counter for building item
+/// name
+/// \param trees isc::data::ElementPtr to be filled in; caller has ownership of
+/// isc::data::ElementPtr
+void
+fillNodes(const Counter& counter,
+ const struct isc::auth::statistics::CounterSpec type_tree[],
+ isc::data::ElementPtr& trees)
+{
+ using namespace isc::data;
+
+ for (int i = 0; type_tree[i].name != NULL; ++i) {
+ if (type_tree[i].sub_counters != NULL) {
+ isc::data::ElementPtr sub_counters = Element::createMap();
+ trees->set(type_tree[i].name, sub_counters);
+ fillNodes(counter, type_tree[i].sub_counters, sub_counters);
+ } else {
+ trees->set(type_tree[i].name,
+ Element::create(static_cast<long int>(
+ counter.get(type_tree[i].counter_id)))
+ );
+ }
+ }
+}
+
+// ### STATISTICS ITEMS DEFINITION ###
+
+} // anonymous namespace
+
+namespace isc {
+namespace auth {
+namespace statistics {
+
+// Note: opcode in this array must be start with 0 and be sequential
+const int opcode_to_msgcounter[] = {
+ MSG_OPCODE_QUERY, // Opcode = 0: Query
+ MSG_OPCODE_IQUERY, // Opcode = 1: IQuery
+ MSG_OPCODE_STATUS, // Opcode = 2: Status
+ MSG_OPCODE_OTHER, // Opcode = 3: (Unassigned)
+ MSG_OPCODE_NOTIFY, // Opcode = 4: Notify
+ MSG_OPCODE_UPDATE, // Opcode = 5: Update
+ MSG_OPCODE_OTHER, // Opcode = 6: (Unassigned)
+ MSG_OPCODE_OTHER, // Opcode = 7: (Unassigned)
+ MSG_OPCODE_OTHER, // Opcode = 8: (Unassigned)
+ MSG_OPCODE_OTHER, // Opcode = 9: (Unassigned)
+ MSG_OPCODE_OTHER, // Opcode = 10: (Unassigned)
+ MSG_OPCODE_OTHER, // Opcode = 11: (Unassigned)
+ MSG_OPCODE_OTHER, // Opcode = 12: (Unassigned)
+ MSG_OPCODE_OTHER, // Opcode = 13: (Unassigned)
+ MSG_OPCODE_OTHER, // Opcode = 14: (Unassigned)
+ MSG_OPCODE_OTHER // Opcode = 15: (Unassigned)
+};
+const size_t num_opcode_to_msgcounter =
+ sizeof(opcode_to_msgcounter) / sizeof(opcode_to_msgcounter[0]);
+
+// Note: rcode in this array must be start with 0 and be sequential
+const int rcode_to_msgcounter[] = {
+ MSG_RCODE_NOERROR, // Rcode = 0: NoError
+ MSG_RCODE_FORMERR, // Rcode = 1: FormErr
+ MSG_RCODE_SERVFAIL, // Rcode = 2: ServFail
+ MSG_RCODE_NXDOMAIN, // Rcode = 3: NXDomain
+ MSG_RCODE_NOTIMP, // Rcode = 4: NotImp
+ MSG_RCODE_REFUSED, // Rcode = 5: Refused
+ MSG_RCODE_YXDOMAIN, // Rcode = 6: YXDomain
+ MSG_RCODE_YXRRSET, // Rcode = 7: YXRRSet
+ MSG_RCODE_NXRRSET, // Rcode = 8: NXRRSet
+ MSG_RCODE_NOTAUTH, // Rcode = 9: NotAuth
+ MSG_RCODE_NOTZONE, // Rcode = 10: NotZone
+ MSG_RCODE_OTHER, // Rcode = 11: (Unassigned)
+ MSG_RCODE_OTHER, // Rcode = 12: (Unassigned)
+ MSG_RCODE_OTHER, // Rcode = 13: (Unassigned)
+ MSG_RCODE_OTHER, // Rcode = 14: (Unassigned)
+ MSG_RCODE_OTHER, // Rcode = 15: (Unassigned)
+ MSG_RCODE_BADVERS // Rcode = 16: BADVERS
+};
+const size_t num_rcode_to_msgcounter =
+ sizeof(rcode_to_msgcounter) / sizeof(rcode_to_msgcounter[0]);
+
+Counters::Counters() :
+ server_msg_counter_(MSG_COUNTER_TYPES)
+{}
+
+void
+Counters::incRequest(const MessageAttributes& msgattrs) {
+ // protocols carrying request
+ if (msgattrs.getRequestIPVersion() == AF_INET) {
+ server_msg_counter_.inc(MSG_REQUEST_IPV4);
+ } else if (msgattrs.getRequestIPVersion() == AF_INET6) {
+ server_msg_counter_.inc(MSG_REQUEST_IPV6);
+ }
+ if (msgattrs.getRequestTransportProtocol() == IPPROTO_UDP) {
+ server_msg_counter_.inc(MSG_REQUEST_UDP);
+ } else if (msgattrs.getRequestTransportProtocol() == IPPROTO_TCP) {
+ server_msg_counter_.inc(MSG_REQUEST_TCP);
+ }
+
+ // Opcode
+ const boost::optional<isc::dns::Opcode>& opcode =
+ msgattrs.getRequestOpCode();
+ // Increment opcode counter only if the opcode exists; opcode can be empty
+ // if a short message which does not contain DNS header is received, or
+ // a response message (i.e. QR bit is set) is received.
+ if (opcode) {
+ server_msg_counter_.inc(opcode_to_msgcounter[opcode.get().getCode()]);
+ }
+
+ // TSIG
+ if (msgattrs.requestHasTSIG()) {
+ server_msg_counter_.inc(MSG_REQUEST_TSIG);
+ }
+ if (msgattrs.requestHasBadSig()) {
+ server_msg_counter_.inc(MSG_REQUEST_BADSIG);
+ // If signature validation failed, no other request attributes (except
+ // for opcode) are reliable. Skip processing of the rest of request
+ // counters.
+ return;
+ }
+
+ // EDNS0
+ if (msgattrs.requestHasEDNS0()) {
+ server_msg_counter_.inc(MSG_REQUEST_EDNS0);
+ }
+
+ // DNSSEC OK bit
+ if (msgattrs.requestHasDO()) {
+ server_msg_counter_.inc(MSG_REQUEST_DNSSEC_OK);
+ }
+}
+
+void
+Counters::incResponse(const MessageAttributes& msgattrs,
+ const Message& response)
+{
+ // responded
+ server_msg_counter_.inc(MSG_RESPONSE);
+
+ // response truncated
+ if (msgattrs.responseIsTruncated()) {
+ server_msg_counter_.inc(MSG_RESPONSE_TRUNCATED);
+ }
+
+ // response EDNS
+ ConstEDNSPtr response_edns = response.getEDNS();
+ if (response_edns && response_edns->getVersion() == 0) {
+ server_msg_counter_.inc(MSG_RESPONSE_EDNS0);
+ }
+
+ // response TSIG
+ if (msgattrs.responseHasTSIG()) {
+ server_msg_counter_.inc(MSG_RESPONSE_TSIG);
+ }
+
+ // response SIG(0) is currently not implemented
+
+ // RCODE
+ const unsigned int rcode = response.getRcode().getCode();
+ const unsigned int rcode_type =
+ rcode < num_rcode_to_msgcounter ?
+ rcode_to_msgcounter[rcode] : MSG_RCODE_OTHER;
+ server_msg_counter_.inc(rcode_type);
+ // Unsupported EDNS version
+ if (rcode == Rcode::BADVERS().getCode()) {
+ server_msg_counter_.inc(MSG_REQUEST_BADEDNSVER);
+ }
+
+ const boost::optional<isc::dns::Opcode>& opcode =
+ msgattrs.getRequestOpCode();
+ if (!opcode) {
+ isc_throw(isc::Unexpected, "Opcode of the request is empty while it is"
+ " responded");
+ }
+ if (!msgattrs.requestHasBadSig() && opcode.get() == Opcode::QUERY()) {
+ // compound attributes
+ const unsigned int answer_rrs =
+ response.getRRCount(Message::SECTION_ANSWER);
+ const bool is_aa_set =
+ response.getHeaderFlag(Message::HEADERFLAG_AA);
+
+ if (is_aa_set) {
+ // QryAuthAns
+ server_msg_counter_.inc(MSG_QRYAUTHANS);
+ } else {
+ // QryNoAuthAns
+ server_msg_counter_.inc(MSG_QRYNOAUTHANS);
+ }
+
+ if (rcode == Rcode::NOERROR_CODE) {
+ if (answer_rrs > 0) {
+ // QrySuccess
+ server_msg_counter_.inc(MSG_QRYSUCCESS);
+ } else {
+ if (is_aa_set) {
+ // QryNxrrset
+ server_msg_counter_.inc(MSG_QRYNXRRSET);
+ } else {
+ // QryReferral
+ server_msg_counter_.inc(MSG_QRYREFERRAL);
+ }
+ }
+ } else if (rcode == Rcode::REFUSED_CODE) {
+ if (!response.getHeaderFlag(Message::HEADERFLAG_RD)) {
+ // AuthRej
+ server_msg_counter_.inc(MSG_QRYREJECT);
+ }
+ }
+ }
+}
+
+void
+Counters::inc(const MessageAttributes& msgattrs, const Message& response,
+ const bool done)
+{
+ // increment request counters
+ incRequest(msgattrs);
+
+ if (done) {
+ // increment response counters if answer was sent
+ incResponse(msgattrs, response);
+ }
+}
+
+Counters::ConstItemTreePtr
+Counters::get() const {
+ using namespace isc::data;
+
+ isc::data::ElementPtr item_tree = Element::createMap();
+
+ isc::data::ElementPtr zones = Element::createMap();
+ item_tree->set("zones", zones);
+
+ isc::data::ElementPtr server = Element::createMap();
+ fillNodes(server_msg_counter_, msg_counter_tree, server);
+ zones->set("_SERVER_", server);
+
+ return (item_tree);
+}
+
+} // namespace statistics
+} // namespace auth
+} // namespace isc
diff --git a/src/bin/auth/statistics.h b/src/bin/auth/statistics.h
index d60c681..52f9bad 100644
--- a/src/bin/auth/statistics.h
+++ b/src/bin/auth/statistics.h
@@ -15,208 +15,289 @@
#ifndef STATISTICS_H
#define STATISTICS_H 1
-#include <cc/session.h>
#include <cc/data.h>
#include <dns/message.h>
+#include <dns/opcode.h>
-#include <string>
+#include <statistics/counter.h>
+
+#include <boost/noncopyable.hpp>
+#include <boost/optional.hpp>
+
+#include <bitset>
#include <stdint.h>
-#include <boost/scoped_ptr.hpp>
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
namespace isc {
namespace auth {
namespace statistics {
-class CountersImpl;
-
-class QRAttributes {
-/// \brief Query/Response attributes for statistics.
+/// \brief DNS Message attributes for statistics.
///
-/// This class holds some attributes related to a query/response
+/// This class holds some attributes related to a DNS message
/// for statistics data collection.
-///
-/// This class does not have getter methods since it exposes private members
-/// to \c CountersImpl directly.
-friend class CountersImpl;
+class MessageAttributes {
+public:
+ /// \brief IP version of DNS message.
+ enum IPVersionType {
+ IP_VERSION_UNSPEC, // (initial value; internal use only)
+ IP_VERSION_IPV4, ///< IPv4 message
+ IP_VERSION_IPV6 ///< IPv6 message
+ };
+
+ /// \brief Transport protocol of DNS message.
+ enum TransportProtocolType {
+ TRANSPORT_UNSPEC, // (initial value; internal use only)
+ TRANSPORT_UDP, ///< UDP message
+ TRANSPORT_TCP ///< TCP message
+ };
private:
// request attributes
- int req_ip_version_; // IP version
+ int req_address_family_; // IP version
int req_transport_protocol_; // Transport layer protocol
- int req_opcode_; // OpCode
- bool req_is_edns_0_; // EDNS ver.0
- bool req_is_edns_badver_; // other EDNS version
- bool req_is_dnssec_ok_; // DO bit
- bool req_is_tsig_; // signed with valid TSIG
- bool req_is_sig0_; // signed with valid SIG(0)
- bool req_is_badsig_; // signed but bad signature
- // zone origin
- std::string zone_origin_; // zone origin
- // response attributes
- bool answer_sent_; // DNS message has sent
- bool res_is_truncated_; // DNS message is truncated
+ boost::optional<isc::dns::Opcode> req_opcode_; // OpCode
+ enum BitAttributes {
+ REQ_WITH_EDNS_0, // request with EDNS ver.0
+ REQ_WITH_DNSSEC_OK, // DNSSEC OK (DO) bit is set in request
+ REQ_TSIG_SIGNED, // request is signed with valid TSIG
+ REQ_BADSIG, // request is signed but bad signature
+ RES_IS_TRUNCATED, // response is truncated
+ RES_TSIG_SIGNED, // response is signed with TSIG
+ BIT_ATTRIBUTES_TYPES
+ };
+ std::bitset<BIT_ATTRIBUTES_TYPES> bit_attributes_;
public:
- /// The constructor.
+ /// \brief The constructor.
///
- /// This constructor is mostly exception free. But it may still throw
- /// a standard exception if memory allocation fails inside the method.
- ///
- QRAttributes() {
- reset();
- };
+ /// \throw None
+ MessageAttributes() : req_address_family_(0), req_transport_protocol_(0)
+ {}
- /// The destructor.
+ /// \brief Return opcode of the request.
///
- /// This method never throws an exception.
+ /// \return opcode of the request wrapped with boost::optional; it's
+ /// converted to false if Opcode hasn't been set.
+ /// \throw None
+ const boost::optional<isc::dns::Opcode>& getRequestOpCode() const {
+ return (req_opcode_);
+ }
+
+ /// \brief Set opcode of the request.
///
- ~QRAttributes() {};
- /// \brief Set query opcode.
+ /// \param opcode Opcode of the request
/// \throw None
- void setQueryOpCode(const int opcode) {
+ void setRequestOpCode(const isc::dns::Opcode& opcode) {
req_opcode_ = opcode;
- };
- /// \brief Set IP version carrying a query.
+ }
+
+ /// \brief Get IP version carrying a request.
+ ///
+ /// \return IP address family carrying a request (AF_INET or AF_INET6)
/// \throw None
- void setQueryIPVersion(const int ip_version) {
- req_ip_version_ = ip_version;
- };
- /// \brief Set transport protocol carrying a query.
+ int getRequestIPVersion() const {
+ return (req_address_family_);
+ }
+
+ /// \brief Set IP address family carrying a request.
+ ///
+ /// \param address_family AF_INET or AF_INET6
+ /// \throw None
+ void setRequestIPVersion(const int address_family) {
+ if (address_family != AF_INET && address_family != AF_INET6) {
+ isc_throw(isc::InvalidParameter, "Unknown address family");
+ }
+ req_address_family_ = address_family;
+ }
+
+ /// \brief Get transport protocol carrying a request.
+ ///
+ /// \return Transport protocol carrying a request
+ /// (IPPROTO_UDP or IPPROTO_TCP)
/// \throw None
- void setQueryTransportProtocol(const int transport_protocol) {
+ int getRequestTransportProtocol() const {
+ return (req_transport_protocol_);
+ }
+
+ /// \brief Set transport protocol carrying a request.
+ ///
+ /// \param transport_protocol IPPROTO_UDP or IPPROTO_TCP
+ /// \throw None
+ void setRequestTransportProtocol(const int transport_protocol) {
+ if (transport_protocol != IPPROTO_UDP &&
+ transport_protocol != IPPROTO_TCP)
+ {
+ isc_throw(isc::InvalidParameter, "Unknown transport protocol");
+ }
req_transport_protocol_ = transport_protocol;
- };
- /// \brief Set query EDNS attributes.
+ }
+
+ /// \brief Return whether EDNS version of the request is 0 or not.
+ ///
+ /// \return true if EDNS version of the request is 0
/// \throw None
- void setQueryEDNS(const bool is_edns_0, const bool is_edns_badver) {
- req_is_edns_0_ = is_edns_0;
- req_is_edns_badver_ = is_edns_badver;
- };
- /// \brief Set query DO bit.
+ bool requestHasEDNS0() const {
+ return (bit_attributes_[REQ_WITH_EDNS_0]);
+ }
+
+ /// \brief Set whether EDNS version of the request is 0 or not.
+ ///
+ /// \param with_edns_0 true if EDNS version of the request is 0
/// \throw None
- void setQueryDO(const bool is_dnssec_ok) {
- req_is_dnssec_ok_ = is_dnssec_ok;
- };
- /// \brief Set query TSIG attributes.
- /// \throw None
- void setQuerySig(const bool is_tsig, const bool is_sig0,
- const bool is_badsig)
- {
- req_is_tsig_ = is_tsig;
- req_is_sig0_ = is_sig0;
- req_is_badsig_ = is_badsig;
- };
- /// \brief Set zone origin.
+ void setRequestEDNS0(const bool with_edns_0) {
+ bit_attributes_[REQ_WITH_EDNS_0] = with_edns_0;
+ }
+
+ /// \brief Return DNSSEC OK (DO) bit of the request.
+ ///
+ /// \return true if DNSSEC OK (DO) bit of the request is set
/// \throw None
- void setOrigin(const std::string& origin) {
- zone_origin_ = origin;
- };
- /// \brief Set if the answer was sent.
+ bool requestHasDO() const {
+ return (bit_attributes_[REQ_WITH_DNSSEC_OK]);
+ }
+
+ /// \brief Set DNSSEC OK (DO) bit of the request.
+ ///
+ /// \param with_dnssec_ok true if DNSSEC OK (DO) bit of the request is set
/// \throw None
- void answerWasSent() {
- answer_sent_ = true;
- };
- /// \brief Set if the response is truncated.
+ void setRequestDO(const bool with_dnssec_ok) {
+ bit_attributes_[REQ_WITH_DNSSEC_OK] = with_dnssec_ok;
+ }
+
+ /// \brief Return whether the request is TSIG signed or not.
+ ///
+ /// \return true if the request is TSIG signed
+ /// \throw None
+ bool requestHasTSIG() const {
+ return (bit_attributes_[REQ_TSIG_SIGNED]);
+ }
+
+ /// \brief Return whether the signature of the request is bad or not.
+ ///
+ /// \return true if the signature of the request is bad
+ /// \throw None
+ bool requestHasBadSig() const {
+ return (bit_attributes_[REQ_BADSIG]);
+ }
+
+ /// \brief Set TSIG attributes of the request.
+ ///
+ /// \param signed_tsig true if the request is signed with TSIG
+ /// \param badsig true if the signature of the request is bad; it must not
+ // be true unless signed_tsig is true
+ /// \throw isc::InvalidParameter if badsig is true though the request is
+ /// not signed
+ void setRequestTSIG(const bool signed_tsig, const bool badsig) {
+ if (!signed_tsig && badsig) {
+ isc_throw(isc::InvalidParameter, "Message is not signed but badsig"
+ " is true");
+ }
+ bit_attributes_[REQ_TSIG_SIGNED] = signed_tsig;
+ bit_attributes_[REQ_BADSIG] = badsig;
+ }
+
+ /// \brief Return TC (truncated) bit of the response.
+ ///
+ /// \return true if the response is truncated
+ /// \throw None
+ bool responseIsTruncated() const {
+ return (bit_attributes_[RES_IS_TRUNCATED]);
+ }
+
+ /// \brief Set TC (truncated) bit of the response.
+ ///
+ /// \param is_truncated true if the response is truncated
/// \throw None
void setResponseTruncated(const bool is_truncated) {
- res_is_truncated_ = is_truncated;
- };
- /// \brief Reset attributes.
- /// \throw None
- void reset() {
- req_ip_version_ = 0;
- req_transport_protocol_ = 0;
- req_opcode_ = 0;
- req_is_edns_0_ = false;
- req_is_edns_badver_ = false;
- req_is_dnssec_ok_ = false;
- req_is_tsig_ = false;
- req_is_sig0_ = false;
- req_is_badsig_ = false;
- zone_origin_.clear();
- answer_sent_ = false;
- res_is_truncated_ = false;
- };
+ bit_attributes_[RES_IS_TRUNCATED] = is_truncated;
+ }
+
+ /// \brief Return whether the response is TSIG signed or not.
+ ///
+ /// \return true if the response is signed with TSIG
+ /// \throw None
+ bool responseHasTSIG() const {
+ return (bit_attributes_[RES_TSIG_SIGNED]);
+ }
+
+ /// \brief Set whether the response is TSIG signed or not.
+ ///
+ /// \param signed_tsig true if the response is signed with TSIG
+ /// \throw None
+ void setResponseTSIG(const bool signed_tsig) {
+ bit_attributes_[RES_TSIG_SIGNED] = signed_tsig;
+ }
};
-/// \brief Set of query counters.
+/// \brief Set of DNS message counters.
///
-/// \c Counters is set of query counters class. It holds query counters
-/// and provides an interface to increment the counter of specified type
-/// (e.g. UDP query, TCP query).
-///
-/// This class also provides a function to send statistics information to
-/// statistics module.
+/// \c Counters is a set of DNS message counters class. It holds DNS message
+/// counters and provides an interface to increment the counter of specified
+/// type (e.g. UDP message, TCP message).
///
/// This class is designed to be a part of \c AuthSrv.
-/// Call \c inc() to increment a counter for the query.
-/// Call \c getStatistics() to answer statistics information to statistics
-/// module with statistics_session, when the command \c getstats is received.
+/// Call \c inc() to increment a counter for the message.
+/// Call \c get() to get a set of DNS message counters.
///
/// We may eventually want to change the structure to hold values that are
/// not counters (such as concurrent TCP connections), or seperate generic
/// part to src/lib to share with the other modules.
///
-/// This class uses pimpl idiom and hides detailed implementation.
/// This class is constructed on startup of the server, so
/// construction overhead of this approach should be acceptable.
///
-/// \todo Hold counters for each query types (Notify, Axfr, Ixfr, Normal)
/// \todo Consider overhead of \c Counters::inc()
-class Counters {
+class Counters : boost::noncopyable {
private:
- boost::scoped_ptr<CountersImpl> impl_;
+ // counter for DNS message attributes
+ isc::statistics::Counter server_msg_counter_;
+ void incRequest(const MessageAttributes& msgattrs);
+ void incResponse(const MessageAttributes& msgattrs,
+ const isc::dns::Message& response);
public:
- /// The constructor.
+ /// \brief A type of statistics item tree in isc::data::MapElement.
+ /// \verbatim
+ /// {
+ /// zone_name => {
+ /// item_name => item_value,
+ /// item_name => item_value, ...
+ /// },
+ /// ...
+ /// }
+ /// item_name is a string seperated by '.'.
+ /// item_value is an integer.
+ /// \endverbatim
+ typedef isc::data::ConstElementPtr ConstItemTreePtr;
+
+ /// \brief The constructor.
///
/// This constructor is mostly exception free. But it may still throw
/// a standard exception if memory allocation fails inside the method.
- ///
Counters();
- /// The destructor.
- ///
- /// This method never throws an exception.
- ///
- ~Counters();
/// \brief Increment counters according to the parameters.
///
- /// \param qrattrs Query/Response attributes.
+ /// \param msgattrs DNS message attributes.
/// \param response DNS response message.
- ///
- /// \throw None
- ///
- void inc(const QRAttributes& qrattrs, const isc::dns::Message& response);
+ /// \param done DNS response was sent to the client.
+ /// \throw isc::Unexpected Internal condition check failed.
+ void inc(const MessageAttributes& msgattrs,
+ const isc::dns::Message& response, const bool done);
- /// \brief Answers statistics counters to statistics module.
+ /// \brief Get statistics counters.
///
- /// This method is mostly exception free (error conditions are
- /// represented via the return value). But it may still throw
- /// a standard exception if memory allocation fails inside the method.
+ /// This method is mostly exception free. But it may still throw a
+ /// standard exception if memory allocation fails inside the method.
///
/// \return statistics data
- ///
- isc::data::ConstElementPtr getStatistics() const;
-
- /// \brief A type of validation function for the specification in
- /// isc::config::ModuleSpec.
- ///
- /// This type might be useful for not only statistics
- /// specificatoin but also for config_data specification and for
- /// commnad.
- ///
- typedef boost::function<bool(const isc::data::ConstElementPtr&)>
- validator_type;
-
- /// \brief Register a function type of the statistics validation
- /// function for Counters.
- ///
- /// This method never throws an exception.
- ///
- /// \param validator A function type of the validation of
- /// statistics specification.
- ///
- void registerStatisticsValidator(Counters::validator_type validator) const;
+ /// \throw std::bad_alloc Internal resource allocation fails
+ ConstItemTreePtr get() const;
};
} // namespace statistics
diff --git a/src/bin/auth/statistics_items.h b/src/bin/auth/statistics_items.h
deleted file mode 100644
index 5839206..0000000
--- a/src/bin/auth/statistics_items.h
+++ /dev/null
@@ -1,609 +0,0 @@
-// Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC")
-//
-// Permission to use, copy, modify, and/or distribute this software for any
-// purpose with or without fee is hereby granted, provided that the above
-// copyright notice and this permission notice appear in all copies.
-//
-// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
-// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
-// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
-// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
-// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
-// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
-// PERFORMANCE OF THIS SOFTWARE.
-
-#ifndef __STATISTICS_ITEMS_H
-#define __STATISTICS_ITEMS_H 1
-
-/// This file defines a set of statistics items in Auth module for internal
-/// use. This file is intended to be included in statistics.cc.
-
-namespace {
-
-struct CounterTypeTree {
- const char* const name;
- const struct CounterTypeTree* const sub_tree;
- const int counter_id;
-};
-
-// enum for query/response counters
-enum QRCounterType {
- // Request Attributes
- QR_REQUEST_IPV4, ///< Number of IPv4 requests received
- QR_REQUEST_IPV6, ///< Number of IPv6 requests received
- QR_REQUEST_EDNS0, ///< Number of requests with EDNS(0) received
- QR_REQUEST_BADEDNSVER, ///< Number of requests with unsupported EDNS version received
- QR_REQUEST_TSIG, ///< Number of requests with TSIG received
- QR_REQUEST_SIG0, ///< Number of requests with SIG(0) received; not implemented in BIND 10
- QR_REQUEST_BADSIG, ///< Number of requests with invalid TSIG or SIG(0) signature received
- QR_REQUEST_UDP, ///< Number of UDP requests received
- QR_REQUEST_TCP, ///< Number of TCP requests received
- QR_REQUEST_DNSSEC_OK, ///< Number of requests with DO bit
- // Request Opcodes
- QR_OPCODE_QUERY, ///< Number of Opcode=QUERY requests received
- QR_OPCODE_IQUERY, ///< Number of Opcode=IQUERY requests received
- QR_OPCODE_STATUS, ///< Number of Opcode=STATUS requests received
- QR_OPCODE_NOTIFY, ///< Number of Opcode=NOTIFY requests received
- QR_OPCODE_UPDATE, ///< Number of Opcode=UPDATE requests received
- QR_OPCODE_OTHER, ///< Number of requests in other OpCode received
- // Query Types
- QR_QTYPE_A, ///< Number of QTYPE = A queries received
- QR_QTYPE_NS, ///< Number of QTYPE = NS queries received
- QR_QTYPE_MD, ///< Number of QTYPE = MD queries received
- QR_QTYPE_MF, ///< Number of QTYPE = MF queries received
- QR_QTYPE_CNAME, ///< Number of QTYPE = CNAME queries received
- QR_QTYPE_SOA, ///< Number of QTYPE = SOA queries received
- QR_QTYPE_MB, ///< Number of QTYPE = MB queries received
- QR_QTYPE_MG, ///< Number of QTYPE = MG queries received
- QR_QTYPE_MR, ///< Number of QTYPE = MR queries received
- QR_QTYPE_NULL, ///< Number of QTYPE = NULL queries received
- QR_QTYPE_WKS, ///< Number of QTYPE = WKS queries received
- QR_QTYPE_PTR, ///< Number of QTYPE = PTR queries received
- QR_QTYPE_HINFO, ///< Number of QTYPE = HINFO queries received
- QR_QTYPE_MINFO, ///< Number of QTYPE = MINFO queries received
- QR_QTYPE_MX, ///< Number of QTYPE = MX queries received
- QR_QTYPE_TXT, ///< Number of QTYPE = TXT queries received
- QR_QTYPE_RP, ///< Number of QTYPE = RP queries received
- QR_QTYPE_AFSDB, ///< Number of QTYPE = AFSDB queries received
- QR_QTYPE_X25, ///< Number of QTYPE = X25 queries received
- QR_QTYPE_ISDN, ///< Number of QTYPE = ISDN queries received
- QR_QTYPE_RT, ///< Number of QTYPE = RT queries received
- QR_QTYPE_NSAP, ///< Number of QTYPE = NSAP queries received
- QR_QTYPE_NSAP_PTR, ///< Number of QTYPE = NSAP-PTR queries received
- QR_QTYPE_SIG, ///< Number of QTYPE = SIG queries received
- QR_QTYPE_KEY, ///< Number of QTYPE = KEY queries received
- QR_QTYPE_PX, ///< Number of QTYPE = PX queries received
- QR_QTYPE_GPOS, ///< Number of QTYPE = GPOS queries received
- QR_QTYPE_AAAA, ///< Number of QTYPE = AAAA queries received
- QR_QTYPE_LOC, ///< Number of QTYPE = LOC queries received
- QR_QTYPE_NXT, ///< Number of QTYPE = NXT queries received
- QR_QTYPE_EID, ///< Number of QTYPE = EID queries received
- QR_QTYPE_NIMLOC, ///< Number of QTYPE = NIMLOC queries received
- QR_QTYPE_SRV, ///< Number of QTYPE = SRV queries received
- QR_QTYPE_ATMA, ///< Number of QTYPE = ATMA queries received
- QR_QTYPE_NAPTR, ///< Number of QTYPE = NAPTR queries received
- QR_QTYPE_KX, ///< Number of QTYPE = KX queries received
- QR_QTYPE_CERT, ///< Number of QTYPE = CERT queries received
- QR_QTYPE_A6, ///< Number of QTYPE = A6 queries received
- QR_QTYPE_DNAME, ///< Number of QTYPE = DNAME queries received
- QR_QTYPE_SINK, ///< Number of QTYPE = SINK queries received
- QR_QTYPE_OPT, ///< Number of QTYPE = OPT queries received
- QR_QTYPE_APL, ///< Number of QTYPE = APL queries received
- QR_QTYPE_DS, ///< Number of QTYPE = DS queries received
- QR_QTYPE_SSHFP, ///< Number of QTYPE = SSHFP queries received
- QR_QTYPE_IPSECKEY, ///< Number of QTYPE = IPSECKEY queries received
- QR_QTYPE_RRSIG, ///< Number of QTYPE = RRSIG queries received
- QR_QTYPE_NSEC, ///< Number of QTYPE = NSEC queries received
- QR_QTYPE_DNSKEY, ///< Number of QTYPE = DNSKEY queries received
- QR_QTYPE_DHCID, ///< Number of QTYPE = DHCID queries received
- QR_QTYPE_NSEC3, ///< Number of QTYPE = NSEC3 queries received
- QR_QTYPE_NSEC3PARAM, ///< Number of QTYPE = NSEC3PARAM queries received
- QR_QTYPE_HIP, ///< Number of QTYPE = HIP queries received
- QR_QTYPE_NINFO, ///< Number of QTYPE = NINFO queries received
- QR_QTYPE_RKEY, ///< Number of QTYPE = RKEY queries received
- QR_QTYPE_TALINK, ///< Number of QTYPE = TALINK queries received
- QR_QTYPE_SPF, ///< Number of QTYPE = SPF queries received
- QR_QTYPE_UINFO, ///< Number of QTYPE = UINFO queries received
- QR_QTYPE_UID, ///< Number of QTYPE = UID queries received
- QR_QTYPE_GID, ///< Number of QTYPE = GID queries received
- QR_QTYPE_UNSPEC, ///< Number of QTYPE = UNSPEC queries received
- QR_QTYPE_TKEY, ///< Number of QTYPE = TKEY queries received
- QR_QTYPE_TSIG, ///< Number of QTYPE = TSIG queries received
- QR_QTYPE_IXFR, ///< Number of QTYPE = IXFR queries received
- QR_QTYPE_AXFR, ///< Number of QTYPE = AXFR queries received
- QR_QTYPE_MAILB, ///< Number of QTYPE = MAILB queries received
- QR_QTYPE_MAILA, ///< Number of QTYPE = MAILA queries received
- QR_QTYPE_URI, ///< Number of QTYPE = URI queries received
- QR_QTYPE_CAA, ///< Number of QTYPE = CAA queries received
- QR_QTYPE_TA, ///< Number of QTYPE = TA queries received
- QR_QTYPE_DLV, ///< Number of QTYPE = DLV queries received
- QR_QTYPE_OTHER, ///< Number of queries in other QTYPE received
- // Respose Attributes
- QR_RESPONSE, ///< Number of responses sent
- QR_RESPONSE_TRUNCATED, ///< Number of truncated responses sent
- QR_RESPONSE_EDNS0, ///< Number of responses with EDNS0; not implemented in BIND 10
- QR_RESPONSE_TSIG, ///< Number of responses with TSIG
- QR_RESPONSE_SIG0, ///< Number of responses with SIG(0); not implemented in BIND 10
- QR_QRYSUCCESS, ///< Number of queries resulted in rcode = NOERROR and answer RR >= 1
- QR_QRYAUTHANS, ///< Number of queries resulted in authoritative answer
- QR_QRYNOAUTHANS, ///< Number of queries resulted in non-authoritative answer
- QR_QRYREFERRAL, ///< Number of queries resulted in referral answer
- QR_QRYNXRRSET, ///< Number of queries resulted in NOERROR but answer RR == 0
- QR_QRYREJECT, ///< Number of queries rejected
- // Response Rcodes
- QR_RCODE_NOERROR, ///< Number of queries resulted in RCODE = 0 (NoError)
- QR_RCODE_FORMERR, ///< Number of queries resulted in RCODE = 1 (FormErr)
- QR_RCODE_SERVFAIL, ///< Number of queries resulted in RCODE = 2 (ServFail)
- QR_RCODE_NXDOMAIN, ///< Number of queries resulted in RCODE = 3 (NXDomain)
- QR_RCODE_NOTIMP, ///< Number of queries resulted in RCODE = 4 (NotImp)
- QR_RCODE_REFUSED, ///< Number of queries resulted in RCODE = 5 (Refused)
- QR_RCODE_YXDOMAIN, ///< Number of queries resulted in RCODE = 6 (YXDomain)
- QR_RCODE_YXRRSET, ///< Number of queries resulted in RCODE = 7 (YXRRSet)
- QR_RCODE_NXRRSET, ///< Number of queries resulted in RCODE = 8 (NXRRSet)
- QR_RCODE_NOTAUTH, ///< Number of queries resulted in RCODE = 9 (NotAuth)
- QR_RCODE_NOTZONE, ///< Number of queries resulted in RCODE = 10 (NotZone)
- QR_RCODE_BADSIGVERS, ///< Number of queries resulted in RCODE = 16 (BADVERS, BADSIG)
- QR_RCODE_BADKEY, ///< Number of queries resulted in RCODE = 17 (BADKEY)
- QR_RCODE_BADTIME, ///< Number of queries resulted in RCODE = 18 (BADTIME)
- QR_RCODE_BADMODE, ///< Number of queries resulted in RCODE = 19 (BADMODE)
- QR_RCODE_BADNAME, ///< Number of queries resulted in RCODE = 20 (BADNAME)
- QR_RCODE_BADALG, ///< Number of queries resulted in RCODE = 21 (BADALG)
- QR_RCODE_BADTRUNC, ///< Number of queries resulted in RCODE = 22 (BADTRUNC)
- QR_RCODE_OTHER, ///< Number of queries resulted in other RCODEs
- // End of counter types
- QR_COUNTER_TYPES ///< The number of defined counters
-};
-
-// item names for query/response counters
-const struct CounterTypeTree QRCounterRequest[] = {
- { "v4", NULL, QR_REQUEST_IPV4 },
- { "v6", NULL, QR_REQUEST_IPV6 },
- { "edns0", NULL, QR_REQUEST_EDNS0 },
- { "badednsver", NULL, QR_REQUEST_BADEDNSVER },
- { "tsig", NULL, QR_REQUEST_TSIG },
- { "sig0", NULL, QR_REQUEST_SIG0 },
- { "badsig", NULL, QR_REQUEST_BADSIG },
- { "udp", NULL, QR_REQUEST_UDP },
- { "tcp", NULL, QR_REQUEST_TCP },
- { "dnssec_ok", NULL, QR_REQUEST_DNSSEC_OK },
- { NULL, NULL, -1 }
-};
-const struct CounterTypeTree QRCounterOpcode[] = {
- { "query", NULL, QR_OPCODE_QUERY },
- { "iquery", NULL, QR_OPCODE_IQUERY },
- { "status", NULL, QR_OPCODE_STATUS },
- { "notify", NULL, QR_OPCODE_NOTIFY },
- { "update", NULL, QR_OPCODE_UPDATE },
- { "other", NULL, QR_OPCODE_OTHER },
- { NULL, NULL, -1 }
-};
-const struct CounterTypeTree QRCounterQtype[] = {
- { "a", NULL, QR_QTYPE_A, },
- { "ns", NULL, QR_QTYPE_NS },
- { "md", NULL, QR_QTYPE_MD },
- { "mf", NULL, QR_QTYPE_MF },
- { "cname", NULL, QR_QTYPE_CNAME },
- { "soa", NULL, QR_QTYPE_SOA },
- { "mb", NULL, QR_QTYPE_MB },
- { "mg", NULL, QR_QTYPE_MG },
- { "mr", NULL, QR_QTYPE_MR },
- { "null", NULL, QR_QTYPE_NULL },
- { "wks", NULL, QR_QTYPE_WKS },
- { "ptr", NULL, QR_QTYPE_PTR },
- { "hinfo", NULL, QR_QTYPE_HINFO },
- { "minfo", NULL, QR_QTYPE_MINFO },
- { "mx", NULL, QR_QTYPE_MX },
- { "txt", NULL, QR_QTYPE_TXT },
- { "rp", NULL, QR_QTYPE_RP },
- { "afsdb", NULL, QR_QTYPE_AFSDB },
- { "x25", NULL, QR_QTYPE_X25 },
- { "isdn", NULL, QR_QTYPE_ISDN },
- { "rt", NULL, QR_QTYPE_RT },
- { "nsap", NULL, QR_QTYPE_NSAP },
- { "nsap-ptr", NULL, QR_QTYPE_NSAP_PTR },
- { "sig", NULL, QR_QTYPE_SIG },
- { "key", NULL, QR_QTYPE_KEY },
- { "px", NULL, QR_QTYPE_PX },
- { "gpos", NULL, QR_QTYPE_GPOS },
- { "aaaa", NULL, QR_QTYPE_AAAA },
- { "loc", NULL, QR_QTYPE_LOC },
- { "nxt", NULL, QR_QTYPE_NXT },
- { "eid", NULL, QR_QTYPE_EID },
- { "nimloc", NULL, QR_QTYPE_NIMLOC },
- { "srv", NULL, QR_QTYPE_SRV },
- { "atma", NULL, QR_QTYPE_ATMA },
- { "naptr", NULL, QR_QTYPE_NAPTR },
- { "kx", NULL, QR_QTYPE_KX },
- { "cert", NULL, QR_QTYPE_CERT },
- { "a6", NULL, QR_QTYPE_A6 },
- { "dname", NULL, QR_QTYPE_DNAME },
- { "sink", NULL, QR_QTYPE_SINK },
- { "opt", NULL, QR_QTYPE_OPT },
- { "apl", NULL, QR_QTYPE_APL },
- { "ds", NULL, QR_QTYPE_DS },
- { "sshfp", NULL, QR_QTYPE_SSHFP },
- { "ipseckey", NULL, QR_QTYPE_IPSECKEY },
- { "rrsig", NULL, QR_QTYPE_RRSIG },
- { "nsec", NULL, QR_QTYPE_NSEC },
- { "dnskey", NULL, QR_QTYPE_DNSKEY },
- { "dhcid", NULL, QR_QTYPE_DHCID },
- { "nsec3", NULL, QR_QTYPE_NSEC3 },
- { "nsec3param", NULL, QR_QTYPE_NSEC3PARAM },
- { "hip", NULL, QR_QTYPE_HIP },
- { "ninfo", NULL, QR_QTYPE_NINFO },
- { "rkey", NULL, QR_QTYPE_RKEY },
- { "talink", NULL, QR_QTYPE_TALINK },
- { "spf", NULL, QR_QTYPE_SPF },
- { "uinfo", NULL, QR_QTYPE_UINFO },
- { "uid", NULL, QR_QTYPE_UID },
- { "gid", NULL, QR_QTYPE_GID },
- { "unspec", NULL, QR_QTYPE_UNSPEC },
- { "tkey", NULL, QR_QTYPE_TKEY },
- { "tsig", NULL, QR_QTYPE_TSIG },
- { "ixfr", NULL, QR_QTYPE_IXFR },
- { "axfr", NULL, QR_QTYPE_AXFR },
- { "mailb", NULL, QR_QTYPE_MAILB },
- { "maila", NULL, QR_QTYPE_MAILA },
- { "uri", NULL, QR_QTYPE_URI },
- { "caa", NULL, QR_QTYPE_CAA },
- { "ta", NULL, QR_QTYPE_TA },
- { "dlv", NULL, QR_QTYPE_DLV },
- { "other", NULL, QR_QTYPE_OTHER },
- { NULL, NULL, -1 }
-};
-const struct CounterTypeTree QRCounterResponse[] = {
- { "truncated", NULL, QR_RESPONSE_TRUNCATED },
- { "edns0", NULL, QR_RESPONSE_EDNS0 },
- { "tsig", NULL, QR_RESPONSE_TSIG },
- { "sig0", NULL, QR_RESPONSE_SIG0 },
- { NULL, NULL, -1 }
-};
-const struct CounterTypeTree QRCounterRcode[] = {
- { "noerror", NULL, QR_RCODE_NOERROR },
- { "formerr", NULL, QR_RCODE_FORMERR },
- { "servfail", NULL, QR_RCODE_SERVFAIL },
- { "nxdomain", NULL, QR_RCODE_NXDOMAIN },
- { "notimp", NULL, QR_RCODE_NOTIMP },
- { "refused", NULL, QR_RCODE_REFUSED },
- { "yxdomain", NULL, QR_RCODE_YXDOMAIN },
- { "yxrrset", NULL, QR_RCODE_YXRRSET },
- { "nxrrset", NULL, QR_RCODE_NXRRSET },
- { "notauth", NULL, QR_RCODE_NOTAUTH },
- { "notzone", NULL, QR_RCODE_NOTZONE },
- { "badsigvers", NULL, QR_RCODE_BADSIGVERS },
- { "badkey", NULL, QR_RCODE_BADKEY },
- { "badtime", NULL, QR_RCODE_BADTIME },
- { "badmode", NULL, QR_RCODE_BADMODE },
- { "badname", NULL, QR_RCODE_BADNAME },
- { "badalg", NULL, QR_RCODE_BADALG },
- { "badtrunc", NULL, QR_RCODE_BADTRUNC },
- { "other", NULL, QR_RCODE_OTHER },
- { NULL, NULL, -1 }
-};
-const struct CounterTypeTree QRCounterTree[] = {
- { "request", QRCounterRequest, -1 },
- { "opcode", QRCounterOpcode, -1 },
- { "qtype", QRCounterQtype, -1 },
- { "responses", NULL, QR_RESPONSE },
- { "response", QRCounterResponse, -1 },
- { "qrysuccess", NULL, QR_QRYSUCCESS },
- { "qryauthans", NULL, QR_QRYAUTHANS },
- { "qrynoauthans", NULL, QR_QRYNOAUTHANS },
- { "qryreferral", NULL, QR_QRYREFERRAL },
- { "qrynxrrset", NULL, QR_QRYNXRRSET },
- { "authqryrej", NULL, QR_QRYREJECT },
- { "rcode", QRCounterRcode, -1 },
- { NULL, NULL, -1 }
-};
-
-const int QROpCodeToQRCounterType[16] = {
- QR_OPCODE_QUERY, // Opcode = 0: Query
- QR_OPCODE_IQUERY, // Opcode = 1: Iquery
- QR_OPCODE_STATUS, // Opcode = 2: STATUS
- QR_OPCODE_OTHER, // Opcode = 3: (Unassigned)
- QR_OPCODE_NOTIFY, // Opcode = 4: Notify
- QR_OPCODE_UPDATE, // Opcode = 5: Update
- QR_OPCODE_OTHER, // Opcode = 6: (Unassigned)
- QR_OPCODE_OTHER, // Opcode = 7: (Unassigned)
- QR_OPCODE_OTHER, // Opcode = 8: (Unassigned)
- QR_OPCODE_OTHER, // Opcode = 9: (Unassigned)
- QR_OPCODE_OTHER, // Opcode = 10: (Unassigned)
- QR_OPCODE_OTHER, // Opcode = 11: (Unassigned)
- QR_OPCODE_OTHER, // Opcode = 12: (Unassigned)
- QR_OPCODE_OTHER, // Opcode = 13: (Unassigned)
- QR_OPCODE_OTHER, // Opcode = 14: (Unassigned)
- QR_OPCODE_OTHER // Opcode = 15: (Unassigned)
-};
-const int QRQTypeToQRCounterType[258] = {
- QR_QTYPE_OTHER, // RRtype = 0: special use
- QR_QTYPE_A, // RRtype = 1: A
- QR_QTYPE_NS, // RRtype = 2: NS
- QR_QTYPE_MD, // RRtype = 3: MD
- QR_QTYPE_MF, // RRtype = 4: MF
- QR_QTYPE_CNAME, // RRtype = 5: CNAME
- QR_QTYPE_SOA, // RRtype = 6: SOA
- QR_QTYPE_MB, // RRtype = 7: MB
- QR_QTYPE_MG, // RRtype = 8: MG
- QR_QTYPE_MR, // RRtype = 9: MR
- QR_QTYPE_NULL, // RRtype = 10: NULL
- QR_QTYPE_WKS, // RRtype = 11: WKS
- QR_QTYPE_PTR, // RRtype = 12: PTR
- QR_QTYPE_HINFO, // RRtype = 13: HINFO
- QR_QTYPE_MINFO, // RRtype = 14: MINFO
- QR_QTYPE_MX, // RRtype = 15: MX
- QR_QTYPE_TXT, // RRtype = 16: TXT
- QR_QTYPE_RP, // RRtype = 17: RP
- QR_QTYPE_AFSDB, // RRtype = 18: AFSDB
- QR_QTYPE_X25, // RRtype = 19: X25
- QR_QTYPE_ISDN, // RRtype = 20: ISDN
- QR_QTYPE_RT, // RRtype = 21: RT
- QR_QTYPE_NSAP, // RRtype = 22: NSAP
- QR_QTYPE_NSAP_PTR, // RRtype = 23: NSAP-PTR
- QR_QTYPE_SIG, // RRtype = 24: SIG
- QR_QTYPE_KEY, // RRtype = 25: KEY
- QR_QTYPE_PX, // RRtype = 26: PX
- QR_QTYPE_GPOS, // RRtype = 27: GPOS
- QR_QTYPE_AAAA, // RRtype = 28: AAAA
- QR_QTYPE_LOC, // RRtype = 29: LOC
- QR_QTYPE_NXT, // RRtype = 30: NXT
- QR_QTYPE_EID, // RRtype = 31: EID
- QR_QTYPE_NIMLOC, // RRtype = 32: NIMLOC
- QR_QTYPE_SRV, // RRtype = 33: SRV
- QR_QTYPE_ATMA, // RRtype = 34: ATMA
- QR_QTYPE_NAPTR, // RRtype = 35: NAPTR
- QR_QTYPE_KX, // RRtype = 36: KX
- QR_QTYPE_CERT, // RRtype = 37: CERT
- QR_QTYPE_A6, // RRtype = 38: A6
- QR_QTYPE_DNAME, // RRtype = 39: DNAME
- QR_QTYPE_SINK, // RRtype = 40: SINK
- QR_QTYPE_OPT, // RRtype = 41: OPT
- QR_QTYPE_APL, // RRtype = 42: APL
- QR_QTYPE_DS, // RRtype = 43: DS
- QR_QTYPE_SSHFP, // RRtype = 44: SSHFP
- QR_QTYPE_IPSECKEY, // RRtype = 45: IPSECKEY
- QR_QTYPE_RRSIG, // RRtype = 46: RRSIG
- QR_QTYPE_NSEC, // RRtype = 47: NSEC
- QR_QTYPE_DNSKEY, // RRtype = 48: DNSKEY
- QR_QTYPE_DHCID, // RRtype = 49: DHCID
- QR_QTYPE_NSEC3, // RRtype = 50: NSEC3
- QR_QTYPE_NSEC3PARAM, // RRtype = 51: NSEC3PARAM
- QR_QTYPE_OTHER, // RRtype = 52: TLSA
- QR_QTYPE_OTHER, // RRtype = 53: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 54: (Unassigned)
- QR_QTYPE_HIP, // RRtype = 55: HIP
- QR_QTYPE_NINFO, // RRtype = 56: NINFO
- QR_QTYPE_RKEY, // RRtype = 57: RKEY
- QR_QTYPE_TALINK, // RRtype = 58: TALINK
- QR_QTYPE_OTHER, // RRtype = 59: CDS
- QR_QTYPE_OTHER, // RRtype = 60: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 61: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 62: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 63: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 64: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 65: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 66: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 67: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 68: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 69: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 70: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 71: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 72: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 73: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 74: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 75: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 76: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 77: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 78: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 79: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 80: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 81: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 82: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 83: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 84: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 85: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 86: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 87: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 88: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 89: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 90: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 91: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 92: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 93: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 94: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 95: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 96: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 97: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 98: (Unassigned)
- QR_QTYPE_SPF, // RRtype = 99: SPF
- QR_QTYPE_UINFO, // RRtype = 100: UINFO
- QR_QTYPE_UID, // RRtype = 101: UID
- QR_QTYPE_GID, // RRtype = 102: GID
- QR_QTYPE_UNSPEC, // RRtype = 103: UNSPEC
- QR_QTYPE_OTHER, // RRtype = 104: NID
- QR_QTYPE_OTHER, // RRtype = 105: L32
- QR_QTYPE_OTHER, // RRtype = 106: L64
- QR_QTYPE_OTHER, // RRtype = 107: LP
- QR_QTYPE_OTHER, // RRtype = 108: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 109: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 110: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 111: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 112: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 113: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 114: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 115: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 116: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 117: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 118: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 119: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 120: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 121: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 122: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 123: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 124: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 125: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 126: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 127: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 128: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 129: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 130: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 131: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 132: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 133: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 134: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 135: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 136: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 137: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 138: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 139: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 140: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 141: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 142: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 143: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 144: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 145: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 146: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 147: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 148: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 149: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 150: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 151: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 152: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 153: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 154: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 155: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 156: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 157: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 158: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 159: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 160: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 161: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 162: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 163: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 164: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 165: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 166: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 167: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 168: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 169: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 170: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 171: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 172: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 173: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 174: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 175: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 176: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 177: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 178: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 179: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 180: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 181: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 182: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 183: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 184: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 185: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 186: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 187: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 188: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 189: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 190: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 191: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 192: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 193: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 194: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 195: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 196: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 197: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 198: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 199: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 200: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 201: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 202: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 203: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 204: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 205: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 206: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 207: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 208: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 209: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 210: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 211: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 212: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 213: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 214: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 215: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 216: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 217: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 218: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 219: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 220: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 221: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 222: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 223: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 224: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 225: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 226: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 227: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 228: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 229: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 230: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 231: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 232: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 233: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 234: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 235: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 236: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 237: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 238: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 239: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 240: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 241: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 242: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 243: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 244: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 245: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 246: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 247: (Unassigned)
- QR_QTYPE_OTHER, // RRtype = 248: (Unassigned)
- QR_QTYPE_TKEY, // RRtype = 249: TKEY
- QR_QTYPE_TSIG, // RRtype = 250: TSIG
- QR_QTYPE_IXFR, // RRtype = 251: IXFR
- QR_QTYPE_AXFR, // RRtype = 252: AXFR
- QR_QTYPE_MAILB, // RRtype = 253: MAILB
- QR_QTYPE_MAILA, // RRtype = 254: MAILA
- QR_QTYPE_OTHER, // RRtype = 255: for All records
- QR_QTYPE_URI, // RRtype = 256: URI
- QR_QTYPE_CAA // RRtype = 257: CAA
-};
-const int QRRCodeToQRCounterType[23] = {
- QR_RCODE_NOERROR, // Rcode = 0: NoError
- QR_RCODE_FORMERR, // Rcode = 1: FormErr
- QR_RCODE_SERVFAIL, // Rcode = 2: ServFail
- QR_RCODE_NXDOMAIN, // Rcode = 3: NXDomain
- QR_RCODE_NOTIMP, // Rcode = 4: NotImp
- QR_RCODE_REFUSED, // Rcode = 5: Refused
- QR_RCODE_YXDOMAIN, // Rcode = 6: YXDomain
- QR_RCODE_YXRRSET, // Rcode = 7: YXRRSet
- QR_RCODE_NXRRSET, // Rcode = 8: NXRRSet
- QR_RCODE_NOTAUTH, // Rcode = 9: NotAuth
- QR_RCODE_NOTZONE, // Rcode = 10: NotZone
- QR_RCODE_OTHER, // Rcode = 11: (Unassigned)
- QR_RCODE_OTHER, // Rcode = 12: (Unassigned)
- QR_RCODE_OTHER, // Rcode = 13: (Unassigned)
- QR_RCODE_OTHER, // Rcode = 14: (Unassigned)
- QR_RCODE_OTHER, // Rcode = 15: (Unassigned)
- QR_RCODE_BADSIGVERS, // Rcode = 16: BADVERS, BADSIG
- QR_RCODE_BADKEY, // Rcode = 17: BADKEY
- QR_RCODE_BADTIME, // Rcode = 18: BADTIME
- QR_RCODE_BADMODE, // Rcode = 19: BADMODE
- QR_RCODE_BADNAME, // Rcode = 20: BADNAME
- QR_RCODE_BADALG, // Rcode = 21: BADALG
- QR_RCODE_BADTRUNC // Rcode = 22: BADTRUNC
-};
-
-} // anonymous namespace
-
-#endif // __STATISTICS_ITEMS_H
-
-// Local Variables:
-// mode: c++
-// End:
diff --git a/src/bin/auth/statistics_items.h.pre b/src/bin/auth/statistics_items.h.pre
new file mode 100644
index 0000000..80317c0
--- /dev/null
+++ b/src/bin/auth/statistics_items.h.pre
@@ -0,0 +1,53 @@
+// Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#ifndef __STATISTICS_ITEMS_H
+#define __STATISTICS_ITEMS_H 1
+
+/// This file declares a set of statistics items in Auth module for internal
+/// use. This file is intended to be included in statistics.cc and unittests.
+
+namespace isc {
+namespace auth {
+namespace statistics {
+
+struct CounterSpec {
+ /// \brief name Name of this node. This appears in the spec file.
+ const char* const name;
+ /// \brief sub_counters If this is a branch node, sub_counters points to
+ /// CounterSpec which contains child nodes. Otherwise,
+ /// for leaf nodes, sub_counters is NULL.
+ const struct CounterSpec* const sub_counters;
+ /// \brief counter_id If this is a leaf node, counter_id is an enumerator
+ /// of this item. Otherwise, for branch nodes, counter_id
+ /// is NOT_ITEM.
+ const int counter_id;
+};
+
+// ### STATISTICS ITEMS DECLARATION ###
+
+extern const int opcode_to_msgcounter[];
+extern const size_t num_opcode_to_msgcounter;
+extern const int rcode_to_msgcounter[];
+extern const size_t num_rcode_to_msgcounter;
+
+} // namespace statistics
+} // namespace auth
+} // namespace isc
+
+#endif // __STATISTICS_ITEMS_H
+
+// Local Variables:
+// mode: c++
+// End:
diff --git a/src/bin/auth/statistics_msg_items.def b/src/bin/auth/statistics_msg_items.def
new file mode 100644
index 0000000..d8d3597
--- /dev/null
+++ b/src/bin/auth/statistics_msg_items.def
@@ -0,0 +1,48 @@
+request msg_counter_request Request statistics =
+ v4 MSG_REQUEST_IPV4 Number of IPv4 requests received by the b10-auth server.
+ v6 MSG_REQUEST_IPV6 Number of IPv6 requests received by the b10-auth server.
+ edns0 MSG_REQUEST_EDNS0 Number of requests with EDNS0 received by the b10-auth server.
+ badednsver MSG_REQUEST_BADEDNSVER Number of requests with unsupported EDNS version received by the b10-auth server.
+ tsig MSG_REQUEST_TSIG Number of requests with TSIG received by the b10-auth server.
+ sig0 MSG_REQUEST_SIG0 Number of requests with SIG(0) received by the b10-auth server; currently not implemented in BIND 10.
+ badsig MSG_REQUEST_BADSIG Number of requests with invalid TSIG or SIG(0) signature received by the b10-auth server.
+ udp MSG_REQUEST_UDP Number of UDP requests received by the b10-auth server.
+ tcp MSG_REQUEST_TCP Number of TCP requests received by the b10-auth server.
+ dnssec_ok MSG_REQUEST_DNSSEC_OK Number of requests with "DNSSEC OK" (DO) bit was set received by the b10-auth server.
+ ;
+opcode msg_counter_opcode OpCode statistics =
+ query MSG_OPCODE_QUERY Number of OpCode=Query requests received by the b10-auth server.
+ iquery MSG_OPCODE_IQUERY Number of OpCode=IQuery requests received by the b10-auth server.
+ status MSG_OPCODE_STATUS Number of OpCode=Status requests received by the b10-auth server.
+ notify MSG_OPCODE_NOTIFY Number of OpCode=Notify requests received by the b10-auth server.
+ update MSG_OPCODE_UPDATE Number of OpCode=Update requests received by the b10-auth server.
+ other MSG_OPCODE_OTHER Number of requests in other OpCode received by the b10-auth server.
+ ;
+responses MSG_RESPONSE Number of responses sent by the b10-auth server.
+response msg_counter_response Response statistics =
+ truncated MSG_RESPONSE_TRUNCATED Number of truncated responses sent by the b10-auth server.
+ edns0 MSG_RESPONSE_EDNS0 Number of responses with EDNS0 sent by the b10-auth server.
+ tsig MSG_RESPONSE_TSIG Number of responses with TSIG sent by the b10-auth server.
+ sig0 MSG_RESPONSE_SIG0 Number of responses with SIG(0) sent by the b10-auth server; currently not implemented in BIND 10.
+ ;
+qrysuccess MSG_QRYSUCCESS Number of queries received by the b10-auth server resulted in rcode = NoError and the number of answer RR >= 1.
+qryauthans MSG_QRYAUTHANS Number of queries received by the b10-auth server resulted in authoritative answer.
+qrynoauthans MSG_QRYNOAUTHANS Number of queries received by the b10-auth server resulted in non-authoritative answer.
+qryreferral MSG_QRYREFERRAL Number of queries received by the b10-auth server resulted in referral answer.
+qrynxrrset MSG_QRYNXRRSET Number of queries received by the b10-auth server resulted in NoError and AA bit is set in the response, but the number of answer RR == 0.
+authqryrej MSG_QRYREJECT Number of authoritative queries rejected by the b10-auth server.
+rcode msg_counter_rcode Rcode statistics =
+ noerror MSG_RCODE_NOERROR Number of requests received by the b10-auth server resulted in RCODE = 0 (NoError).
+ formerr MSG_RCODE_FORMERR Number of requests received by the b10-auth server resulted in RCODE = 1 (FormErr).
+ servfail MSG_RCODE_SERVFAIL Number of requests received by the b10-auth server resulted in RCODE = 2 (ServFail).
+ nxdomain MSG_RCODE_NXDOMAIN Number of requests received by the b10-auth server resulted in RCODE = 3 (NXDomain).
+ notimp MSG_RCODE_NOTIMP Number of requests received by the b10-auth server resulted in RCODE = 4 (NotImp).
+ refused MSG_RCODE_REFUSED Number of requests received by the b10-auth server resulted in RCODE = 5 (Refused).
+ yxdomain MSG_RCODE_YXDOMAIN Number of requests received by the b10-auth server resulted in RCODE = 6 (YXDomain).
+ yxrrset MSG_RCODE_YXRRSET Number of requests received by the b10-auth server resulted in RCODE = 7 (YXRRSet).
+ nxrrset MSG_RCODE_NXRRSET Number of requests received by the b10-auth server resulted in RCODE = 8 (NXRRSet).
+ notauth MSG_RCODE_NOTAUTH Number of requests received by the b10-auth server resulted in RCODE = 9 (NotAuth).
+ notzone MSG_RCODE_NOTZONE Number of requests received by the b10-auth server resulted in RCODE = 10 (NotZone).
+ badvers MSG_RCODE_BADVERS Number of requests received by the b10-auth server resulted in RCODE = 16 (BADVERS).
+ other MSG_RCODE_OTHER Number of requests received by the b10-auth server resulted in other RCODEs.
+ ;
diff --git a/src/bin/auth/tests/Makefile.am b/src/bin/auth/tests/Makefile.am
index d1bde4d..8fbdb4c 100644
--- a/src/bin/auth/tests/Makefile.am
+++ b/src/bin/auth/tests/Makefile.am
@@ -34,6 +34,9 @@ TESTS_ENVIRONMENT = \
TESTS =
if HAVE_GTEST
+# auto-generated by statistics_items.py
+BUILT_SOURCES = statistics_unittest.cc
+
run_unittests_SOURCES = $(top_srcdir)/src/lib/dns/tests/unittest_util.h
run_unittests_SOURCES += $(top_srcdir)/src/lib/dns/tests/unittest_util.cc
run_unittests_SOURCES += ../auth_srv.h ../auth_srv.cc
@@ -45,13 +48,13 @@ run_unittests_SOURCES += ../common.h ../common.cc
run_unittests_SOURCES += ../statistics.h ../statistics.cc ../statistics_items.h
run_unittests_SOURCES += ../datasrc_config.h ../datasrc_config.cc
run_unittests_SOURCES += datasrc_util.h datasrc_util.cc
+run_unittests_SOURCES += statistics_util.h statistics_util.cc
run_unittests_SOURCES += auth_srv_unittest.cc
run_unittests_SOURCES += config_unittest.cc
run_unittests_SOURCES += config_syntax_unittest.cc
run_unittests_SOURCES += command_unittest.cc
run_unittests_SOURCES += common_unittest.cc
run_unittests_SOURCES += query_unittest.cc
-run_unittests_SOURCES += statistics_unittest.cc
run_unittests_SOURCES += test_datasrc_clients_mgr.h test_datasrc_clients_mgr.cc
run_unittests_SOURCES += datasrc_clients_builder_unittest.cc
run_unittests_SOURCES += datasrc_clients_mgr_unittest.cc
@@ -59,6 +62,7 @@ run_unittests_SOURCES += datasrc_config_unittest.cc
run_unittests_SOURCES += run_unittests.cc
nodist_run_unittests_SOURCES = ../auth_messages.h ../auth_messages.cc
+nodist_run_unittests_SOURCES += statistics_unittest.cc
run_unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES)
run_unittests_LDFLAGS = $(AM_LDFLAGS) $(GTEST_LDFLAGS)
@@ -83,7 +87,7 @@ run_unittests_LDADD += $(SQLITE_LIBS)
# The following are definitions for auto-generating test data for query
# tests.
-BUILT_SOURCES = example_base_inc.cc example_nsec3_inc.cc
+BUILT_SOURCES += example_base_inc.cc example_nsec3_inc.cc
BUILT_SOURCES += testdata/example-base.sqlite3
BUILT_SOURCES += testdata/example-nsec3.sqlite3
@@ -114,8 +118,11 @@ testdata/example-nsec3.sqlite3: testdata/example-nsec3.zone testdata/example-com
-c "{\"database_file\": \"$(builddir)/testdata/example-nsec3.sqlite3\"}" \
example.com testdata/example-nsec3.zone
+EXTRA_DIST += gen-statisticsitems_test.py
+
check-local:
B10_FROM_BUILD=${abs_top_builddir} ./run_unittests
+ $(PYTHON) $(srcdir)/gen-statisticsitems_test.py $(top_builddir)/src/bin/auth/b10-auth.xml
noinst_PROGRAMS = run_unittests
diff --git a/src/bin/auth/tests/auth_srv_unittest.cc b/src/bin/auth/tests/auth_srv_unittest.cc
index f58d0e0..0a77a11 100644
--- a/src/bin/auth/tests/auth_srv_unittest.cc
+++ b/src/bin/auth/tests/auth_srv_unittest.cc
@@ -45,6 +45,8 @@
#include <testutils/portconfig.h>
#include <testutils/socket_request.h>
+#include "statistics_util.h"
+
#include <gtest/gtest.h>
#include <boost/lexical_cast.hpp>
@@ -73,6 +75,7 @@ using namespace isc::asiodns;
using namespace isc::asiolink;
using namespace isc::testutils;
using namespace isc::server_common::portconfig;
+using namespace isc::auth::unittest;
using isc::datasrc::memory::ZoneTableSegment;
using isc::UnitTestUtil;
using boost::scoped_ptr;
@@ -90,7 +93,8 @@ const char* const STATIC_DSRC_FILE = DSRC_DIR "/static.zone";
// This is a configuration that uses the in-memory data source containing
// a signed example zone.
-const char* const CONFIG_INMEMORY_EXAMPLE = TEST_DATA_DIR "/rfc5155-example.zone.signed";
+const char* const CONFIG_INMEMORY_EXAMPLE =
+ TEST_DATA_DIR "/rfc5155-example.zone.signed";
// shortcut commonly used in tests
typedef boost::shared_ptr<ConfigurableClientList> ListPtr;
@@ -108,6 +112,7 @@ protected:
server.setDNSService(dnss_);
server.setXfrinSession(¬ify_session);
server.createDDNSForwarder();
+ checkCountersAreInitialized();
}
~AuthSrvTest() {
@@ -124,7 +129,8 @@ protected:
// Helper for checking Rcode statistic counters;
// Checks for one specific Rcode statistics counter value
- void checkRcodeCounter(const std::string& rcode_name, const int rcode_value,
+ void checkRcodeCounter(const std::string& rcode_name,
+ const int rcode_value,
const int expected_value) const
{
EXPECT_EQ(expected_value, rcode_value) <<
@@ -133,38 +139,26 @@ protected:
rcode_value;
}
- // Checks whether all Rcode counters are set to zero
- void checkAllRcodeCountersZero() const {
- // with checking NOERROR == 0 and the others are 0
- checkAllRcodeCountersZeroExcept(Rcode::NOERROR(), 0);
- }
-
// Checks whether all Rcode counters are set to zero except the given
// rcode (it is checked to be set to 'value')
void checkAllRcodeCountersZeroExcept(const Rcode& rcode, int value) const {
std::string target_rcode_name = rcode.toText();
std::transform(target_rcode_name.begin(), target_rcode_name.end(),
target_rcode_name.begin(), ::tolower);
- // rcode 16 is registered as both BADVERS and BADSIG
- if (target_rcode_name == "badvers") {
- target_rcode_name = "badsigvers";
- }
const std::map<std::string, ConstElementPtr>
- stats_map(server.getStatistics()->mapValue());
+ stats_map(server.getStatistics()->get("zones")->get("_SERVER_")->
+ get("rcode")->mapValue());
- const std::string rcode_prefix("rcode.");
for (std::map<std::string, ConstElementPtr>::const_iterator
i = stats_map.begin(), e = stats_map.end();
i != e;
++i)
{
- if (i->first.compare(0, rcode_prefix.size(), rcode_prefix) == 0) {
- if (i->first.compare(rcode_prefix + target_rcode_name) == 0) {
- checkRcodeCounter(i->first, i->second->intValue(), value);
- } else {
- checkRcodeCounter(i->first, i->second->intValue(), 0);
- }
+ if (i->first.compare(target_rcode_name) == 0) {
+ checkRcodeCounter(i->first, i->second->intValue(), value);
+ } else {
+ checkRcodeCounter(i->first, i->second->intValue(), 0);
}
}
}
@@ -199,6 +193,15 @@ protected:
&dnsserv);
}
+ // Check if the counters exist and are initialized to 0.
+ void
+ checkCountersAreInitialized() {
+ const std::map<std::string, int> expect;
+ ConstElementPtr stats = server.getStatistics()->
+ get("zones")->get("_SERVER_");
+ checkStatisticsCounters(stats, expect);
+ }
+
MockDNSService dnss_;
MockXfroutClient xfrout;
MockSocketSessionForwarder ddns_forwarder;
@@ -241,29 +244,6 @@ createBuiltinVersionResponse(const qid_t qid, vector<uint8_t>& data) {
renderer.getLength());
}
-// Check if the item has expected value.
-// Before reading the item, check the item exists.
-void
-expectCounterItem(ConstElementPtr stats,
- const std::string& item, const int expected) {
- ConstElementPtr value(Element::create(0));
- if (item == "queries.udp" || item == "queries.tcp" || expected != 0) {
- // if the value of the item is not zero, the item exists and has
- // expected value
- // item "queries.udp" and "queries.tcp" exists whether the value
- // is zero or nonzero
- ASSERT_TRUE(stats->find(item, value)) << " Item: " << item;
- // Get the value of the item with another method because of API bug
- // (ticket #2302)
- value = stats->find(item);
- EXPECT_EQ(expected, value->intValue()) << " Item: " << item;
- } else {
- // otherwise the item does not exist
- ASSERT_FALSE(stats->find(item, value)) << " Item: " << item <<
- std::endl << " Value: " << value->intValue();
- }
-}
-
// We did not configure any client lists. Therefore it should be REFUSED
TEST_F(AuthSrvTest, noClientList) {
UnitTestUtil::createRequestMessage(request_message, Opcode::QUERY(),
@@ -276,6 +256,18 @@ TEST_F(AuthSrvTest, noClientList) {
EXPECT_TRUE(dnsserv.hasAnswer());
headerCheck(*parse_message, default_qid, Rcode::REFUSED(),
opcode.getCode(), QR_FLAG, 1, 0, 0, 0);
+
+ ConstElementPtr stats_after = server.getStatistics()->get("zones")->
+ get("_SERVER_");
+ std::map<std::string, int> expect;
+ expect["request.v4"] = 1;
+ expect["request.udp"] = 1;
+ expect["opcode.query"] = 1;
+ expect["responses"] = 1;
+ expect["qrynoauthans"] = 1;
+ expect["authqryrej"] = 1;
+ expect["rcode.refused"] = 1;
+ checkStatisticsCounters(stats_after, expect);
}
// Unsupported requests. Should result in NOTIMP.
@@ -295,32 +287,74 @@ TEST_F(AuthSrvTest, multiQuestion) {
// dropped.
TEST_F(AuthSrvTest, shortMessage) {
shortMessage();
- checkAllRcodeCountersZero();
+
+ ConstElementPtr stats_after = server.getStatistics()->get("zones")->
+ get("_SERVER_");
+ std::map<std::string, int> expect;
+ expect["request.v4"] = 1;
+ expect["request.udp"] = 1;
+ checkStatisticsCounters(stats_after, expect);
}
// Response messages. Must be silently dropped, whether it's a valid response
// or malformed or could otherwise cause a protocol error.
TEST_F(AuthSrvTest, response) {
+ // isc::testutils::SrvTestBase::response() processes 3 messages.
response();
- checkAllRcodeCountersZero();
+
+ ConstElementPtr stats_after = server.getStatistics()->get("zones")->
+ get("_SERVER_");
+ std::map<std::string, int> expect;
+ expect["request.v4"] = 3;
+ expect["request.udp"] = 3;
+ checkStatisticsCounters(stats_after, expect);
}
// Query with a broken question
TEST_F(AuthSrvTest, shortQuestion) {
shortQuestion();
- checkAllRcodeCountersZeroExcept(Rcode::FORMERR(), 1);
+ ConstElementPtr stats_after = server.getStatistics()->get("zones")->
+ get("_SERVER_");
+ std::map<std::string, int> expect;
+ expect["request.v4"] = 1;
+ expect["request.udp"] = 1;
+ expect["opcode.query"] = 1;
+ expect["responses"] = 1;
+ expect["rcode.formerr"] = 1;
+ expect["qrynoauthans"] = 1;
+ checkStatisticsCounters(stats_after, expect);
}
// Query with a broken answer section
TEST_F(AuthSrvTest, shortAnswer) {
shortAnswer();
- checkAllRcodeCountersZeroExcept(Rcode::FORMERR(), 1);
+ ConstElementPtr stats_after = server.getStatistics()->get("zones")->
+ get("_SERVER_");
+ std::map<std::string, int> expect;
+ expect["request.v4"] = 1;
+ expect["request.udp"] = 1;
+ expect["opcode.query"] = 1;
+ expect["responses"] = 1;
+ expect["rcode.formerr"] = 1;
+ expect["qrynoauthans"] = 1;
+ checkStatisticsCounters(stats_after, expect);
}
// Query with unsupported version of EDNS.
TEST_F(AuthSrvTest, ednsBadVers) {
ednsBadVers();
- checkAllRcodeCountersZeroExcept(Rcode::BADVERS(), 1);
+
+ ConstElementPtr stats_after = server.getStatistics()->get("zones")->
+ get("_SERVER_");
+ std::map<std::string, int> expect;
+ expect["request.v4"] = 1;
+ expect["request.badednsver"] = 1;
+ expect["request.udp"] = 1;
+ expect["opcode.query"] = 1;
+ expect["responses"] = 1;
+ expect["rcode.badvers"] = 1;
+ expect["qrynoauthans"] = 1;
+ checkStatisticsCounters(stats_after, expect);
}
TEST_F(AuthSrvTest, AXFROverUDP) {
@@ -339,7 +373,14 @@ TEST_F(AuthSrvTest, AXFRSuccess) {
&dnsserv);
EXPECT_FALSE(dnsserv.hasAnswer());
EXPECT_TRUE(xfrout.isConnected());
- checkAllRcodeCountersZero();
+
+ ConstElementPtr stats_after = server.getStatistics()->get("zones")->
+ get("_SERVER_");
+ std::map<std::string, int> expect;
+ expect["request.v4"] = 1;
+ expect["request.tcp"] = 1;
+ expect["opcode.query"] = 1;
+ checkStatisticsCounters(stats_after, expect);
}
// Give the server a signed request, but don't give it the key. It will
@@ -373,7 +414,20 @@ TEST_F(AuthSrvTest, TSIGSignedBadKey) {
EXPECT_EQ(0, tsig->getRdata().getMACSize()) <<
"It should be unsigned with this error";
+ // check Rcode counters and TSIG counters
checkAllRcodeCountersZeroExcept(Rcode::NOTAUTH(), 1);
+ ConstElementPtr stats_after = server.getStatistics()->get("zones")->
+ get("_SERVER_");
+ std::map<std::string, int> expect;
+ expect["request.v4"] = 1;
+ expect["request.tsig"] = 1;
+ expect["request.badsig"] = 1;
+ expect["request.udp"] = 1;
+ expect["opcode.query"] = 1;
+ expect["responses"] = 1;
+ expect["response.tsig"] = 1;
+ expect["rcode.notauth"] = 1;
+ checkStatisticsCounters(stats_after, expect);
}
// Give the server a signed request, but signed by a different key
@@ -408,7 +462,18 @@ TEST_F(AuthSrvTest, TSIGBadSig) {
EXPECT_EQ(0, tsig->getRdata().getMACSize()) <<
"It should be unsigned with this error";
- checkAllRcodeCountersZeroExcept(Rcode::NOTAUTH(), 1);
+ ConstElementPtr stats_after = server.getStatistics()->get("zones")->
+ get("_SERVER_");
+ std::map<std::string, int> expect;
+ expect["request.v4"] = 1;
+ expect["request.tsig"] = 1;
+ expect["request.badsig"] = 1;
+ expect["request.udp"] = 1;
+ expect["opcode.query"] = 1;
+ expect["responses"] = 1;
+ expect["response.tsig"] = 1;
+ expect["rcode.notauth"] = 1;
+ checkStatisticsCounters(stats_after, expect);
}
// Give the server a signed unsupported request with a bad signature.
@@ -445,13 +510,19 @@ TEST_F(AuthSrvTest, TSIGCheckFirst) {
EXPECT_EQ(TSIGError::BAD_SIG_CODE, tsig->getRdata().getError());
EXPECT_EQ(0, tsig->getRdata().getMACSize()) <<
"It should be unsigned with this error";
- // TSIG should have failed, and so the per opcode counter shouldn't be
- // incremented.
- ConstElementPtr stats = server.getStatistics();
- expectCounterItem(stats, "opcode.normal", 0);
- expectCounterItem(stats, "opcode.other", 0);
- checkAllRcodeCountersZeroExcept(Rcode::NOTAUTH(), 1);
+ ConstElementPtr stats_after = server.getStatistics()->get("zones")->
+ get("_SERVER_");
+ std::map<std::string, int> expect;
+ expect["request.v4"] = 1;
+ expect["request.tsig"] = 1;
+ expect["request.badsig"] = 1;
+ expect["request.udp"] = 1;
+ expect["opcode.other"] = 1;
+ expect["responses"] = 1;
+ expect["response.tsig"] = 1;
+ expect["rcode.notauth"] = 1;
+ checkStatisticsCounters(stats_after, expect);
}
TEST_F(AuthSrvTest, AXFRConnectFail) {
@@ -589,7 +660,8 @@ TEST_F(AuthSrvTest, notify) {
// external module. Check them.
EXPECT_EQ("Zonemgr", notify_session.getMessageDest());
EXPECT_EQ("notify",
- notify_session.getSentMessage()->get("command")->get(0)->stringValue());
+ notify_session.getSentMessage()->get("command")->get(0)->
+ stringValue());
ConstElementPtr notify_args =
notify_session.getSentMessage()->get("command")->get(1);
EXPECT_EQ("example.com.", notify_args->get("zone_name")->stringValue());
@@ -607,7 +679,15 @@ TEST_F(AuthSrvTest, notify) {
EXPECT_EQ(RRClass::IN(), question->getClass());
EXPECT_EQ(RRType::SOA(), question->getType());
- checkAllRcodeCountersZeroExcept(Rcode::NOERROR(), 1);
+ ConstElementPtr stats_after = server.getStatistics()->get("zones")->
+ get("_SERVER_");
+ std::map<std::string, int> expect;
+ expect["request.v4"] = 1;
+ expect["request.udp"] = 1;
+ expect["opcode.notify"] = 1;
+ expect["responses"] = 1;
+ expect["rcode.noerror"] = 1;
+ checkStatisticsCounters(stats_after, expect);
}
TEST_F(AuthSrvTest, notifyForCHClass) {
@@ -626,6 +706,16 @@ TEST_F(AuthSrvTest, notifyForCHClass) {
ConstElementPtr notify_args =
notify_session.getSentMessage()->get("command")->get(1);
EXPECT_EQ("CH", notify_args->get("zone_class")->stringValue());
+
+ ConstElementPtr stats_after = server.getStatistics()->get("zones")->
+ get("_SERVER_");
+ std::map<std::string, int> expect;
+ expect["request.v4"] = 1;
+ expect["request.udp"] = 1;
+ expect["opcode.notify"] = 1;
+ expect["responses"] = 1;
+ expect["rcode.noerror"] = 1;
+ checkStatisticsCounters(stats_after, expect);
}
TEST_F(AuthSrvTest, notifyEmptyQuestion) {
@@ -641,6 +731,16 @@ TEST_F(AuthSrvTest, notifyEmptyQuestion) {
EXPECT_TRUE(dnsserv.hasAnswer());
headerCheck(*parse_message, default_qid, Rcode::FORMERR(),
Opcode::NOTIFY().getCode(), QR_FLAG, 0, 0, 0, 0);
+
+ ConstElementPtr stats_after = server.getStatistics()->get("zones")->
+ get("_SERVER_");
+ std::map<std::string, int> expect;
+ expect["request.v4"] = 1;
+ expect["request.udp"] = 1;
+ expect["opcode.notify"] = 1;
+ expect["responses"] = 1;
+ expect["rcode.formerr"] = 1;
+ checkStatisticsCounters(stats_after, expect);
}
TEST_F(AuthSrvTest, notifyMultiQuestions) {
@@ -854,6 +954,19 @@ TEST_F(AuthSrvTest, TSIGSigned) {
"The server signed the response, but it doesn't seem to be valid";
checkAllRcodeCountersZeroExcept(Rcode::NOERROR(), 1);
+ ConstElementPtr stats_after = server.getStatistics()->get("zones")->
+ get("_SERVER_");
+ std::map<std::string, int> expect;
+ expect["request.v4"] = 1;
+ expect["request.tsig"] = 1;
+ expect["request.udp"] = 1;
+ expect["opcode.query"] = 1;
+ expect["responses"] = 1;
+ expect["response.tsig"] = 1;
+ expect["qrysuccess"] = 1;
+ expect["qryauthans"] = 1;
+ expect["rcode.noerror"] = 1;
+ checkStatisticsCounters(stats_after, expect);
}
// Same test emulating the UDPServer class behavior (defined in libasiolink).
@@ -954,8 +1067,8 @@ TEST_F(AuthSrvTest, updateConfig) {
server.processMessage(*io_message, *parse_message, *response_obuffer,
&dnsserv);
EXPECT_TRUE(dnsserv.hasAnswer());
- headerCheck(*parse_message, default_qid, Rcode::NOERROR(), opcode.getCode(),
- QR_FLAG | AA_FLAG, 1, 1, 1, 0);
+ headerCheck(*parse_message, default_qid, Rcode::NOERROR(),
+ opcode.getCode(), QR_FLAG | AA_FLAG, 1, 1, 1, 0);
}
#ifdef USE_STATIC_LINK
@@ -975,6 +1088,18 @@ TEST_F(AuthSrvTest, datasourceFail) {
EXPECT_TRUE(dnsserv.hasAnswer());
headerCheck(*parse_message, default_qid, Rcode::SERVFAIL(),
opcode.getCode(), QR_FLAG, 1, 0, 0, 0);
+
+ checkAllRcodeCountersZeroExcept(Rcode::SERVFAIL(), 1);
+ ConstElementPtr stats = server.getStatistics()->get("zones")->
+ get("_SERVER_");
+ std::map<std::string, int> expect;
+ expect["request.v4"] = 1;
+ expect["request.udp"] = 1;
+ expect["opcode.query"] = 1;
+ expect["responses"] = 1;
+ expect["qrynoauthans"] = 1;
+ expect["rcode.servfail"] = 1;
+ checkStatisticsCounters(stats, expect);
}
#ifdef USE_STATIC_LINK
@@ -1083,14 +1208,39 @@ TEST_F(AuthSrvTest,
opcode.getCode(), QR_FLAG | AA_FLAG, 1, 1, 1, 0);
}
+#ifdef USE_STATIC_LINK
+TEST_F(AuthSrvTest, DISABLED_queryCounterTruncTest) {
+#else
+TEST_F(AuthSrvTest, queryCounterTruncTest) {
+#endif
+ // use CONFIG_TESTDB for large-rdata.example.com.
+ updateDatabase(server, CONFIG_TESTDB);
+
+ // Create UDP message and process.
+ // large-rdata.example.com. TXT; expect it exceeds 512 octet
+ UnitTestUtil::createRequestMessage(request_message, Opcode::QUERY(),
+ default_qid,
+ Name("large-rdata.example.com."),
+ RRClass::IN(), RRType::TXT());
+ createRequestPacket(request_message, IPPROTO_UDP);
+ server.processMessage(*io_message, *parse_message, *response_obuffer,
+ &dnsserv);
+
+ ConstElementPtr stats_after = server.getStatistics()->
+ get("zones")->get("_SERVER_");
+ std::map<std::string, int> expect;
+ expect["request.v4"] = 1;
+ expect["request.udp"] = 1;
+ expect["opcode.query"] = 1;
+ expect["responses"] = 1;
+ expect["response.truncated"] = 1;
+ expect["qrysuccess"] = 1;
+ expect["qryauthans"] = 1;
+ expect["rcode.noerror"] = 1;
+ checkStatisticsCounters(stats_after, expect);
+}
// Submit UDP normal query and check query counter
TEST_F(AuthSrvTest, queryCounterUDPNormal) {
- // The counters should be initialized to 0.
- ConstElementPtr stats_init = server.getStatistics();
- expectCounterItem(stats_init, "queries.udp", 0);
- expectCounterItem(stats_init, "queries.tcp", 0);
- expectCounterItem(stats_init, "opcode.query", 0);
- expectCounterItem(stats_init, "rcode.refused", 0);
// Create UDP message and process.
UnitTestUtil::createRequestMessage(request_message, Opcode::QUERY(),
default_qid, Name("example.com"),
@@ -1098,25 +1248,50 @@ TEST_F(AuthSrvTest, queryCounterUDPNormal) {
createRequestPacket(request_message, IPPROTO_UDP);
server.processMessage(*io_message, *parse_message, *response_obuffer,
&dnsserv);
- // After processing the UDP query, these counters should be incremented:
- // queries.udp, opcode.query, rcode.refused
- // and these counters should not be incremented:
- // queries.tcp
- ConstElementPtr stats_after = server.getStatistics();
- expectCounterItem(stats_after, "queries.udp", 1);
- expectCounterItem(stats_after, "queries.tcp", 0);
- expectCounterItem(stats_after, "opcode.query", 1);
- expectCounterItem(stats_after, "rcode.refused", 1);
+
+ ConstElementPtr stats_after = server.getStatistics()->
+ get("zones")->get("_SERVER_");
+ std::map<std::string, int> expect;
+ expect["request.v4"] = 1;
+ expect["request.udp"] = 1;
+ expect["opcode.query"] = 1;
+ expect["responses"] = 1;
+ expect["qrynoauthans"] = 1;
+ expect["authqryrej"] = 1;
+ expect["rcode.refused"] = 1;
+ checkStatisticsCounters(stats_after, expect);
+}
+
+// Submit UDP normal query with DNSSEC and check query counter
+TEST_F(AuthSrvTest, queryCounterUDPNormalWithDNSSEC) {
+ // Create UDP message and process.
+ UnitTestUtil::createDNSSECRequestMessage(request_message, Opcode::QUERY(),
+ default_qid, Name("example.com"),
+ RRClass::IN(), RRType::NS());
+ createRequestPacket(request_message, IPPROTO_UDP);
+ server.processMessage(*io_message, *parse_message, *response_obuffer,
+ &dnsserv);
+
+ ConstElementPtr stats_after = server.getStatistics()->
+ get("zones")->get("_SERVER_");
+ std::map<std::string, int> expect;
+ expect["request.v4"] = 1;
+ expect["request.edns0"] = 1;
+ expect["request.udp"] = 1;
+ expect["request.dnssec_ok"] = 1;
+ expect["opcode.query"] = 1;
+ expect["responses"] = 1;
+ expect["qrynoauthans"] = 1;
+ expect["authqryrej"] = 1;
+ expect["rcode.refused"] = 1;
+ // XXX: with the current implementation, EDNS0 is omitted in
+ // makeErrorMessage.
+ expect["response.edns0"] = 0;
+ checkStatisticsCounters(stats_after, expect);
}
// Submit TCP normal query and check query counter
TEST_F(AuthSrvTest, queryCounterTCPNormal) {
- // The counters should be initialized to 0.
- ConstElementPtr stats_init = server.getStatistics();
- expectCounterItem(stats_init, "queries.udp", 0);
- expectCounterItem(stats_init, "queries.tcp", 0);
- expectCounterItem(stats_init, "opcode.query", 0);
- expectCounterItem(stats_init, "rcode.refused", 0);
// Create TCP message and process.
UnitTestUtil::createRequestMessage(request_message, Opcode::QUERY(),
default_qid, Name("example.com"),
@@ -1124,24 +1299,22 @@ TEST_F(AuthSrvTest, queryCounterTCPNormal) {
createRequestPacket(request_message, IPPROTO_TCP);
server.processMessage(*io_message, *parse_message, *response_obuffer,
&dnsserv);
- // After processing the TCP query, these counters should be incremented:
- // queries.tcp, opcode.query, rcode.refused
- // and these counters should not be incremented:
- // queries.udp
- ConstElementPtr stats_after = server.getStatistics();
- expectCounterItem(stats_after, "queries.udp", 0);
- expectCounterItem(stats_after, "queries.tcp", 1);
- expectCounterItem(stats_after, "opcode.query", 1);
- expectCounterItem(stats_after, "rcode.refused", 1);
+
+ ConstElementPtr stats_after = server.getStatistics()->
+ get("zones")->get("_SERVER_");
+ std::map<std::string, int> expect;
+ expect["request.v4"] = 1;
+ expect["request.tcp"] = 1;
+ expect["opcode.query"] = 1;
+ expect["responses"] = 1;
+ expect["qrynoauthans"] = 1;
+ expect["authqryrej"] = 1;
+ expect["rcode.refused"] = 1;
+ checkStatisticsCounters(stats_after, expect);
}
// Submit TCP AXFR query and check query counter
TEST_F(AuthSrvTest, queryCounterTCPAXFR) {
- // The counters should be initialized to 0.
- ConstElementPtr stats_init = server.getStatistics();
- expectCounterItem(stats_init, "queries.udp", 0);
- expectCounterItem(stats_init, "queries.tcp", 0);
- expectCounterItem(stats_init, "opcode.query", 0);
UnitTestUtil::createRequestMessage(request_message, opcode, default_qid,
Name("example.com"), RRClass::IN(), RRType::AXFR());
createRequestPacket(request_message, IPPROTO_TCP);
@@ -1150,24 +1323,18 @@ TEST_F(AuthSrvTest, queryCounterTCPAXFR) {
server.processMessage(*io_message, *parse_message, *response_obuffer,
&dnsserv);
EXPECT_FALSE(dnsserv.hasAnswer());
- // After processing the TCP AXFR query, these counters should be
- // incremented:
- // queries.tcp, opcode.query
- // and these counters should not be incremented:
- // queries.udp
- ConstElementPtr stats_after = server.getStatistics();
- expectCounterItem(stats_after, "queries.udp", 0);
- expectCounterItem(stats_after, "queries.tcp", 1);
- expectCounterItem(stats_after, "opcode.query", 1);
+
+ ConstElementPtr stats_after = server.getStatistics()->
+ get("zones")->get("_SERVER_");
+ std::map<std::string, int> expect;
+ expect["request.v4"] = 1;
+ expect["request.tcp"] = 1;
+ expect["opcode.query"] = 1;
+ checkStatisticsCounters(stats_after, expect);
}
// Submit TCP IXFR query and check query counter
TEST_F(AuthSrvTest, queryCounterTCPIXFR) {
- // The counters should be initialized to 0.
- ConstElementPtr stats_init = server.getStatistics();
- expectCounterItem(stats_init, "queries.udp", 0);
- expectCounterItem(stats_init, "queries.tcp", 0);
- expectCounterItem(stats_init, "opcode.query", 0);
UnitTestUtil::createRequestMessage(request_message, opcode, default_qid,
Name("example.com"), RRClass::IN(), RRType::IXFR());
createRequestPacket(request_message, IPPROTO_TCP);
@@ -1176,27 +1343,38 @@ TEST_F(AuthSrvTest, queryCounterTCPIXFR) {
server.processMessage(*io_message, *parse_message, *response_obuffer,
&dnsserv);
EXPECT_FALSE(dnsserv.hasAnswer());
- // After processing the TCP IXFR query, these counters should be
- // incremented:
- // queries.tcp, opcode.query
- // and these counters should not be incremented:
- // queries.udp
- ConstElementPtr stats_after = server.getStatistics();
- expectCounterItem(stats_after, "queries.udp", 0);
- expectCounterItem(stats_after, "queries.tcp", 1);
- expectCounterItem(stats_after, "opcode.query", 1);
+
+ ConstElementPtr stats_after = server.getStatistics()->
+ get("zones")->get("_SERVER_");
+ std::map<std::string, int> expect;
+ expect["request.v4"] = 1;
+ expect["request.tcp"] = 1;
+ expect["opcode.query"] = 1;
+ checkStatisticsCounters(stats_after, expect);
}
TEST_F(AuthSrvTest, queryCounterOpcodes) {
- // Check for 0..2, 3(=other), 4..5
- // The counter should be initialized to 0.
- for (int i = 0; i < 6; ++i) {
- // The counter should be initialized to 0.
- expectCounterItem(server.getStatistics(),
- std::string("opcode.") +
- QRCounterOpcode[QROpCodeToQRCounterType[i] -
- QR_OPCODE_QUERY].name,
- 0);
+ int other_expected = 0;
+ for (int i = 0; i < isc::auth::statistics::num_opcode_to_msgcounter; ++i) {
+ std::string item_name;
+ int expected;
+ if (isc::auth::statistics::opcode_to_msgcounter[i] ==
+ isc::auth::statistics::MSG_OPCODE_OTHER)
+ {
+ item_name = "OTHER";
+ other_expected += i + 1;
+ expected = other_expected;
+ } else {
+ item_name = Opcode(i).toText();
+ expected = i + 1;
+ }
+ std::transform(item_name.begin(), item_name.end(), item_name.begin(),
+ ::tolower);
+
+ // The counter should be initialized to expected value.
+ EXPECT_EQ(expected - (i + 1),
+ server.getStatistics()->get("zones")->get("_SERVER_")->
+ get("opcode")->get(item_name)->intValue());
// For each possible opcode, create a request message and send it
UnitTestUtil::createRequestMessage(request_message, Opcode(i),
@@ -1214,45 +1392,11 @@ TEST_F(AuthSrvTest, queryCounterOpcodes) {
}
// Confirm the counter.
- expectCounterItem(server.getStatistics(),
- std::string("opcode.") +
- QRCounterOpcode[QROpCodeToQRCounterType[i] -
- QR_OPCODE_QUERY].name,
- i + 1);
- }
- // Check for 6..15
- // they are treated as the 'other' opcode
- // the 'other' opcode counter is 4 at this point
- int expected = 4;
- for (int i = 6; i < 16; ++i) {
- // The counter should be initialized to 0.
- expectCounterItem(server.getStatistics(),
- std::string("opcode.") +
- QRCounterOpcode[QROpCodeToQRCounterType[i] -
- QR_OPCODE_QUERY].name,
- expected);
-
- // For each possible opcode, create a request message and send it
- UnitTestUtil::createRequestMessage(request_message, Opcode(i),
- default_qid, Name("example.com"),
- RRClass::IN(), RRType::NS());
- createRequestPacket(request_message, IPPROTO_UDP);
-
- // "send" the request once
- parse_message->clear(Message::PARSE);
- server.processMessage(*io_message, *parse_message,
- *response_obuffer,
- &dnsserv);
-
- // the 'other' opcode counter should be incremented
- ++expected;
-
- // Confirm the counter.
- expectCounterItem(server.getStatistics(),
- std::string("opcode.") +
- QRCounterOpcode[QROpCodeToQRCounterType[i] -
- QR_OPCODE_QUERY].name,
- expected);
+ // This test only checks for opcodes; some part of the other items
+ // depends on the opcode.
+ EXPECT_EQ(expected,
+ server.getStatistics()->get("zones")->get("_SERVER_")->
+ get("opcode")->get(item_name)->intValue());
}
}
diff --git a/src/bin/auth/tests/gen-statisticsitems_test.py b/src/bin/auth/tests/gen-statisticsitems_test.py
new file mode 100644
index 0000000..0cc7bcf
--- /dev/null
+++ b/src/bin/auth/tests/gen-statisticsitems_test.py
@@ -0,0 +1,90 @@
+# Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC")
+#
+# Permission to use, copy, modify, and/or distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+# PERFORMANCE OF THIS SOFTWARE.
+
+"""\
+This script checks output of gen-statisticsitems.py.
+
+This script checks XML file. Spec file, C++ code and header files syntax is
+checked in the other unittests or system tests.
+"""
+
+import os
+import sys
+from xml.etree import ElementTree
+
+"""\
+User-defined exception for parse error. It is thrown if a file is not
+formatted as expected.
+"""
+class ParseError(Exception):
+ pass
+
+"""\
+Test XML file.
+
+It should have <refsect1> which has <title>STATISTICS DATA</title>.
+Inside the section, it should have one or more <varlistentry> of each item
+inside <variablelist>.
+Each <varlistentry> should have <term> for item name and <simpara> inside
+<listitem> for item description.
+
+Example:
+ <refsect1>
+ <title>STATISTICS DATA</title>
+ <variablelist>
+ <varlistentry>
+ <term>item1</term>
+ <listitem><simpara>statistics item</simpara></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>item2</term>
+ <listitem><simpara>another statistics item</simpara></listitem>
+ </varlistentry>
+ </variablelist>
+ </refsect1>
+"""
+def test_xml_file(xmlfilepath):
+ xmltree = ElementTree.parse(xmlfilepath)
+ root = xmltree.getroot()
+ # find <refsect1> which has <title> of 'STATISTICS DATA'
+ stats_node = [t for t in root.findall('./refsect1')
+ if t.find('./title').text == 'STATISTICS DATA']
+ if not stats_node:
+ raise ParseError('Statistics data section does not exist')
+ # find all <varlistentry> inside <variablelist>
+ entries = stats_node[0].find('./variablelist').findall('./varlistentry')
+ if not entries:
+ raise ParseError('<varlistentry> does not exist inside section')
+ for entry in entries:
+ # find <term> for item name
+ name = entry.find('./term')
+ if name is None or name.text == '':
+ raise ParseError('<term> for item name does not exist')
+ # find <simpara> inside <listitem> for item description
+ description = entry.find('./listitem/simpara')
+ if description is None or description.text == '':
+ raise ParseError('<listitem> nor <simpara> for item description'
+ ' does not exist')
+ return
+
+if __name__ == "__main__":
+ xmlfilepath = sys.argv[1]
+ try:
+ test_xml_file(xmlfilepath)
+ except ImportError:
+ # pyexpat library is required for ElementTree.parse() but it is
+ # missing in some environment. Just skip this test.
+ print ("Required library is missing, skipping this test.")
+ print ("Detailed information:")
+ print (sys.exc_info()[1])
diff --git a/src/bin/auth/tests/statistics_unittest.cc b/src/bin/auth/tests/statistics_unittest.cc
deleted file mode 100644
index 052a70e..0000000
--- a/src/bin/auth/tests/statistics_unittest.cc
+++ /dev/null
@@ -1,123 +0,0 @@
-// Copyright (C) 2010 Internet Systems Consortium, Inc. ("ISC")
-//
-// Permission to use, copy, modify, and/or distribute this software for any
-// purpose with or without fee is hereby granted, provided that the above
-// copyright notice and this permission notice appear in all copies.
-//
-// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
-// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
-// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
-// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
-// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
-// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
-// PERFORMANCE OF THIS SOFTWARE.
-
-#include <config.h>
-
-#include <string>
-
-#include <gtest/gtest.h>
-
-#include <boost/bind.hpp>
-
-#include <dns/opcode.h>
-#include <dns/rcode.h>
-
-#include <cc/data.h>
-#include <cc/session.h>
-
-#include <auth/statistics.h>
-#include <auth/statistics_items.h>
-
-#include <dns/tests/unittest_util.h>
-
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <netdb.h>
-
-using namespace std;
-using namespace isc::cc;
-using namespace isc::dns;
-using namespace isc::data;
-using isc::auth::statistics::Counters;
-using isc::auth::statistics::QRAttributes;
-
-namespace {
-
-class CountersTest : public ::testing::Test {
-protected:
- CountersTest() : counters() {}
- ~CountersTest() {}
- Counters counters;
-};
-
-// Test if the values of the counters are all zero except for the items
-// specified in except_for.
-void
-checkCountersAllZeroExcept(const isc::data::ConstElementPtr counters,
- const std::set<std::string>& except_for) {
- std::map<std::string, ConstElementPtr> stats_map = counters->mapValue();
-
- for (std::map<std::string, ConstElementPtr>::const_iterator
- i = stats_map.begin(), e = stats_map.end();
- i != e;
- ++i)
- {
- int expect = 0;
- if (except_for.count(i->first) != 0) {
- expect = 1;
- }
- EXPECT_EQ(expect, i->second->intValue()) << "Expected counter "
- << i->first << " = " << expect << ", actual: "
- << i->second->intValue();
- }
-}
-
-TEST_F(CountersTest, incrementNormalQuery) {
- Message response(Message::RENDER);
- QRAttributes qrattrs;
- std::set<std::string> expect_nonzero;
-
- expect_nonzero.clear();
- checkCountersAllZeroExcept(counters.getStatistics(), expect_nonzero);
-
- qrattrs.setQueryIPVersion(AF_INET6);
- qrattrs.setQueryTransportProtocol(IPPROTO_UDP);
- qrattrs.setQueryOpCode(Opcode::QUERY_CODE);
- qrattrs.setQueryEDNS(true, false);
- qrattrs.setQueryDO(true);
- qrattrs.answerWasSent();
-
- response.setRcode(Rcode::REFUSED());
- response.addQuestion(Question(Name("example.com"),
- RRClass::IN(), RRType::AAAA()));
-
- counters.inc(qrattrs, response);
-
- expect_nonzero.clear();
- expect_nonzero.insert("opcode.query");
- expect_nonzero.insert("queries.udp");
- expect_nonzero.insert("rcode.refused");
- checkCountersAllZeroExcept(counters.getStatistics(), expect_nonzero);
-}
-
-int
-countTreeElements(const struct CounterTypeTree* tree) {
- int count = 0;
- for (int i = 0; tree[i].name != NULL; ++i) {
- if (tree[i].sub_tree == NULL) {
- ++count;
- } else {
- count += countTreeElements(tree[i].sub_tree);
- }
- }
- return count;
-}
-
-TEST(StatisticsItemsTest, QRItemNamesCheck) {
- EXPECT_EQ(QR_COUNTER_TYPES, countTreeElements(QRCounterTree));
-}
-
-}
diff --git a/src/bin/auth/tests/statistics_unittest.cc.pre b/src/bin/auth/tests/statistics_unittest.cc.pre
new file mode 100644
index 0000000..cf6f29a
--- /dev/null
+++ b/src/bin/auth/tests/statistics_unittest.cc.pre
@@ -0,0 +1,714 @@
+// Copyright (C) 2010 Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#include <config.h>
+
+#include <gtest/gtest.h>
+
+#include <boost/bind.hpp>
+
+#include <dns/opcode.h>
+#include <dns/rcode.h>
+#include <dns/rrttl.h>
+
+#include <cc/data.h>
+
+#include <auth/statistics.h>
+#include <auth/statistics_items.h>
+
+#include <dns/tests/unittest_util.h>
+
+#include "statistics_util.h"
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+
+using namespace std;
+using namespace isc::dns;
+using namespace isc::data;
+using namespace isc::auth::statistics;
+using namespace isc::auth::unittest;
+
+namespace {
+
+// ### STATISTICS ITEMS DEFINITION ###
+
+class CountersTest : public ::testing::Test {
+protected:
+ CountersTest() : counters() {}
+ ~CountersTest() {}
+ Counters counters;
+};
+
+void
+buildSkeletonMessage(MessageAttributes& msgattrs) {
+ msgattrs.setRequestIPVersion(AF_INET);
+ msgattrs.setRequestTransportProtocol(IPPROTO_UDP);
+ msgattrs.setRequestOpCode(Opcode::QUERY());
+ msgattrs.setRequestEDNS0(true);
+ msgattrs.setRequestDO(true);
+}
+
+TEST_F(CountersTest, invalidParameterForSetRequestIPVersion) {
+ MessageAttributes msgattrs;
+
+ // It should not throw if the parameter is AF_INET or AF_INET6.
+ EXPECT_NO_THROW(msgattrs.setRequestIPVersion(AF_INET));
+ EXPECT_NO_THROW(msgattrs.setRequestIPVersion(AF_INET6));
+
+ // It should throw isc::InvalidParameter if the parameter is not AF_INET
+ // nor AF_INET6.
+ EXPECT_THROW(msgattrs.setRequestIPVersion(AF_UNIX), isc::InvalidParameter);
+}
+
+TEST_F(CountersTest, invalidParameterForSetRequestTransportProtocol) {
+ MessageAttributes msgattrs;
+
+ // It should not throw if the parameter is IPPROTO_UDP or IPPROTO_TCP.
+ EXPECT_NO_THROW(msgattrs.setRequestTransportProtocol(IPPROTO_UDP));
+ EXPECT_NO_THROW(msgattrs.setRequestTransportProtocol(IPPROTO_TCP));
+
+ // It should throw isc::InvalidParameter if the parameter is not
+ // IPPROTO_UDP nor IPPROTO_TCP.
+ EXPECT_THROW(msgattrs.setRequestTransportProtocol(IPPROTO_IP),
+ isc::InvalidParameter);
+}
+
+TEST_F(CountersTest, invalidOperationForGetRequestOpCode) {
+ MessageAttributes msgattrs;
+
+ // getRequestOpCode() should return boost::none when called before
+ // opcode is set with setRequestOpCode().
+ EXPECT_FALSE(msgattrs.getRequestOpCode());
+
+ msgattrs.setRequestOpCode(Opcode::QUERY());
+ // getRequestOpCode() should be Opcode::QUERY.
+ EXPECT_EQ(Opcode::QUERY(), msgattrs.getRequestOpCode().get());
+}
+
+TEST_F(CountersTest, invalidParameterForSetRequestTSIG) {
+ MessageAttributes msgattrs;
+
+ // These patterns should not throw:
+ // request signature badsig
+ // --------------------------
+ // (none) false
+ // TSIG false
+ // TSIG true
+ EXPECT_NO_THROW(msgattrs.setRequestTSIG(false, false));
+ EXPECT_NO_THROW(msgattrs.setRequestTSIG(true, false));
+ EXPECT_NO_THROW(msgattrs.setRequestTSIG(true, true));
+
+ // It should throw isc::InvalidParameter if a message is not signed but
+ // badsig is true
+ EXPECT_THROW(msgattrs.setRequestTSIG(false, true), isc::InvalidParameter);
+}
+
+TEST_F(CountersTest, incrementResponse) {
+ Message response(Message::RENDER);
+ MessageAttributes msgattrs;
+ std::map<std::string, int> expect;
+
+ // Test response counters are incremented only if responded == true.
+ for (int i = 0; i < 2; ++i) {
+ const bool responded = i & 1;
+
+ buildSkeletonMessage(msgattrs);
+
+ response.setRcode(Rcode::REFUSED());
+ response.addQuestion(Question(Name("example.com"),
+ RRClass::IN(), RRType::AAAA()));
+ response.setHeaderFlag(Message::HEADERFLAG_QR);
+
+ counters.inc(msgattrs, response, responded);
+
+ expect.clear();
+ expect["opcode.query"] = i+1;
+ expect["request.v4"] = i+1;
+ expect["request.udp"] = i+1;
+ expect["request.edns0"] = i+1;
+ expect["request.badednsver"] = 0;
+ expect["request.dnssec_ok"] = i+1;
+ expect["responses"] = responded ? 1 : 0;
+ expect["qrynoauthans"] = responded ? 1 : 0;
+ expect["rcode.refused"] = responded ? 1 : 0;
+ expect["authqryrej"] = responded ? 1 : 0;
+ checkStatisticsCounters(counters.get()->get("zones")->get("_SERVER_"),
+ expect);
+ }
+}
+
+TEST_F(CountersTest, incrementProtocolType) {
+ Message response(Message::RENDER);
+ MessageAttributes msgattrs;
+ std::map<std::string, int> expect;
+
+ // Test these patterns:
+ // af proto
+ // -----------------
+ // ipv6 tcp
+ // ipv4 tcp
+ // ipv6 udp
+ // ipv4 udp
+ int count_v4 = 0, count_v6 = 0, count_udp = 0, count_tcp = 0;
+ for (int i = 0; i < 4; ++i) {
+ const int af = i & 1 ? AF_INET : AF_INET6;
+ const int proto = i & 2 ? IPPROTO_UDP : IPPROTO_TCP;
+
+ buildSkeletonMessage(msgattrs);
+ msgattrs.setRequestIPVersion(af);
+ msgattrs.setRequestTransportProtocol(proto);
+
+ response.setRcode(Rcode::REFUSED());
+ response.addQuestion(Question(Name("example.com"),
+ RRClass::IN(), RRType::AAAA()));
+ response.setHeaderFlag(Message::HEADERFLAG_QR);
+
+ counters.inc(msgattrs, response, true);
+
+ if (af == AF_INET) {
+ ++count_v4;
+ } else {
+ ++count_v6;
+ }
+ if (proto == IPPROTO_UDP) {
+ ++count_udp;
+ } else {
+ ++count_tcp;
+ }
+
+ expect.clear();
+ expect["opcode.query"] = i+1;
+ expect["request.v4"] = count_v4;
+ expect["request.v6"] = count_v6;
+ expect["request.udp"] = count_udp;
+ expect["request.tcp"] = count_tcp;
+ expect["request.edns0"] = i+1;
+ expect["request.badednsver"] = 0;
+ expect["request.dnssec_ok"] = i+1;
+ expect["responses"] = i+1;
+ expect["qrynoauthans"] = i+1;
+ expect["rcode.refused"] = i+1;
+ expect["authqryrej"] = i+1;
+ checkStatisticsCounters(counters.get()->get("zones")->get("_SERVER_"),
+ expect);
+ }
+}
+
+TEST_F(CountersTest, incrementDO) {
+ Message response(Message::RENDER);
+ MessageAttributes msgattrs;
+ std::map<std::string, int> expect;
+
+ // Test these patterns:
+ // DNSSEC OK
+ // -----------
+ // false
+ // true
+ for (int i = 0; i < 2; ++i) {
+ const bool is_dnssec_ok = i & 1;
+ buildSkeletonMessage(msgattrs);
+ msgattrs.setRequestDO(is_dnssec_ok);
+
+ response.setRcode(Rcode::REFUSED());
+ response.addQuestion(Question(Name("example.com"),
+ RRClass::IN(), RRType::AAAA()));
+ response.setHeaderFlag(Message::HEADERFLAG_QR);
+
+ counters.inc(msgattrs, response, true);
+
+ expect.clear();
+ expect["opcode.query"] = i+1;
+ expect["request.v4"] = i+1;
+ expect["request.udp"] = i+1;
+ expect["request.edns0"] = i+1;
+ expect["request.badednsver"] = 0;
+ expect["request.dnssec_ok"] = i & 1;
+ expect["responses"] = i+1;
+ expect["qrynoauthans"] = i+1;
+ expect["rcode.refused"] = i+1;
+ expect["authqryrej"] = i+1;
+ checkStatisticsCounters(counters.get()->get("zones")->get("_SERVER_"),
+ expect);
+ }
+}
+
+TEST_F(CountersTest, incrementEDNS) {
+ Message response(Message::RENDER);
+ MessageAttributes msgattrs;
+ std::map<std::string, int> expect;
+
+ // Test these patterns:
+ // request edns0 response edns0
+ // --------------------------------
+ // false true
+ // true false
+ //
+ // They can't be both true since edns0 and badednsver are exclusive.
+ int count_req_edns0 = 0, count_res_edns0 = 0;
+ for (int i = 0; i < 2; ++i) {
+ const bool is_edns0 = i & 1;
+ buildSkeletonMessage(msgattrs);
+ msgattrs.setRequestEDNS0(is_edns0);
+
+ if (!is_edns0) {
+ ConstEDNSPtr edns = EDNSPtr(new EDNS(0));
+ response.setEDNS(edns);
+ } else {
+ response.setEDNS(EDNSPtr());
+ }
+ response.setRcode(Rcode::REFUSED());
+ response.addQuestion(Question(Name("example.com"),
+ RRClass::IN(), RRType::AAAA()));
+ response.setHeaderFlag(Message::HEADERFLAG_QR);
+
+ counters.inc(msgattrs, response, true);
+
+ if (is_edns0) {
+ ++count_req_edns0;
+ } else {
+ ++count_res_edns0;
+ }
+
+ expect.clear();
+ expect["opcode.query"] = i+1;
+ expect["request.v4"] = i+1;
+ expect["request.udp"] = i+1;
+ expect["request.edns0"] = count_req_edns0;
+ expect["response.edns0"] = count_res_edns0;
+ expect["request.badednsver"] = 0;
+ expect["request.dnssec_ok"] = i+1;
+ expect["responses"] = i+1;
+ expect["qrynoauthans"] = i+1;
+ expect["rcode.refused"] = i+1;
+ expect["authqryrej"] = i+1;
+ checkStatisticsCounters(counters.get()->get("zones")->get("_SERVER_"),
+ expect);
+ }
+}
+
+TEST_F(CountersTest, incrementTSIG) {
+ Message response(Message::RENDER);
+ MessageAttributes msgattrs;
+ std::map<std::string, int> expect;
+
+ // Test these patterns:
+ // request signature badsig response signature
+ // -----------------------------------------------
+ // (none) false (none)
+ // TSIG false TSIG
+ // TSIG true (none)
+ //
+ // badsig can't be true if the message does not have signature.
+ int count_req_tsig = 0, count_res_tsig = 0, count_badsig = 0;
+ for (int i = 0; i < 3; ++i) {
+ const bool is_req_tsig = (i == 2) ? true : (i & 1) != 0;
+ const bool is_res_tsig = (i & 1) != 0;
+ const bool is_badsig = (i & 2) != 0;
+ buildSkeletonMessage(msgattrs);
+ msgattrs.setRequestTSIG(is_req_tsig, is_badsig);
+ msgattrs.setResponseTSIG(is_res_tsig);
+
+ response.setRcode(Rcode::REFUSED());
+ response.addQuestion(Question(Name("example.com"),
+ RRClass::IN(), RRType::AAAA()));
+ response.setHeaderFlag(Message::HEADERFLAG_QR);
+
+ // don't increment response counters if signature is bad
+ counters.inc(msgattrs, response, !is_badsig);
+
+ if (is_req_tsig) {
+ ++count_req_tsig;
+ }
+ if (is_res_tsig) {
+ ++count_res_tsig;
+ }
+ if (is_badsig) {
+ ++count_badsig;
+ }
+
+ expect.clear();
+ expect["request.v4"] = i+1;
+ expect["request.udp"] = i+1;
+ expect["opcode.query"] = i+1;
+ expect["request.edns0"] = i+1 - count_badsig;
+ expect["request.badednsver"] = 0;
+ expect["request.dnssec_ok"] = i+1 - count_badsig;
+ expect["request.tsig"] = count_req_tsig;
+ expect["response.tsig"] = count_res_tsig;
+ expect["request.sig0"] = 0;
+ expect["request.badsig"] = count_badsig;
+ expect["responses"] = i+1 - count_badsig;
+ expect["qrynoauthans"] = i+1 - count_badsig;
+ expect["rcode.refused"] = i+1 - count_badsig;
+ expect["authqryrej"] = i+1 - count_badsig;
+ checkStatisticsCounters(counters.get()->get("zones")->get("_SERVER_"),
+ expect);
+ }
+}
+
+TEST_F(CountersTest, incrementOpcode) {
+ Message response(Message::RENDER);
+ MessageAttributes msgattrs;
+ std::map<std::string, int> expect;
+
+ // Test all opcodes (QUERY..RESERVED15)
+ int count_all = 0, count_opcode_other = 0;
+ for (uint8_t i = Opcode::QUERY().getCode(),
+ e = Opcode::RESERVED15().getCode();
+ i <= e;
+ ++i)
+ {
+ buildSkeletonMessage(msgattrs);
+ msgattrs.setRequestOpCode(Opcode(i));
+ msgattrs.setRequestTSIG(false, false);
+
+ response.setRcode(Rcode::REFUSED());
+ response.addQuestion(Question(Name("example.com"),
+ RRClass::IN(), RRType::AAAA()));
+ response.setHeaderFlag(Message::HEADERFLAG_QR);
+
+ for (uint8_t j = 0; j < i; ++j) {
+ // count up i times for i-th opcode to identify counters
+ counters.inc(msgattrs, response, true);
+ ++count_all;
+ }
+
+ expect.clear();
+ expect["request.v4"] = count_all;
+ expect["request.udp"] = count_all;
+ expect["request.edns0"] = count_all;
+ expect["request.badednsver"] = 0;
+ expect["request.dnssec_ok"] = count_all;
+ expect["request.tsig"] = 0;
+ expect["request.sig0"] = 0;
+ expect["request.badsig"] = 0;
+ expect["responses"] = count_all;
+ expect["rcode.refused"] = count_all;
+ if (opcode_to_msgcounter[i] == MSG_OPCODE_OTHER) {
+ count_opcode_other += i;
+ }
+ for (uint8_t j = 0; j <= i; ++j) {
+ if (opcode_to_msgcounter[j] == MSG_OPCODE_OTHER) {
+ expect["opcode.other"] = count_opcode_other;
+ } else {
+ std::string code_text = Opcode(j).toText();
+ std::transform(code_text.begin(), code_text.end(),
+ code_text.begin(), ::tolower);
+ expect["opcode."+code_text] = j;
+ }
+ }
+ checkStatisticsCounters(counters.get()->get("zones")->get("_SERVER_"),
+ expect);
+ }
+}
+
+TEST_F(CountersTest, incrementRcode) {
+ Message response(Message::RENDER);
+ MessageAttributes msgattrs;
+ std::map<std::string, int> expect;
+
+ // Test all rcodes (NOERROR..BADVERS)
+ int count_all = 0, count_rcode_other = 0, count_ednsbadver = 0;
+ for (uint16_t i = Rcode::NOERROR().getCode(),
+ e = Rcode::BADVERS().getCode();
+ i <= e;
+ ++i)
+ {
+ buildSkeletonMessage(msgattrs);
+ msgattrs.setRequestOpCode(Opcode::IQUERY());
+ msgattrs.setRequestTSIG(false, false);
+
+ response.setRcode(Rcode(i));
+ response.addQuestion(Question(Name("example.com"),
+ RRClass::IN(), RRType::AAAA()));
+ response.setHeaderFlag(Message::HEADERFLAG_QR);
+
+ for (uint16_t j = 0; j < i; ++j) {
+ // count up i times for i-th rcode to identify counters
+ counters.inc(msgattrs, response, true);
+ ++count_all;
+ }
+
+ expect.clear();
+ expect["opcode.iquery"] = count_all;
+ expect["request.v4"] = count_all;
+ expect["request.udp"] = count_all;
+ expect["request.edns0"] = count_all;
+ expect["request.dnssec_ok"] = count_all;
+ expect["request.tsig"] = 0;
+ expect["request.sig0"] = 0;
+ expect["request.badsig"] = 0;
+ expect["responses"] = count_all;
+ if (rcode_to_msgcounter[i] == MSG_RCODE_OTHER) {
+ count_rcode_other += i;
+ }
+ // "request.badednsver" counts for Rcode == BADVERS
+ if (rcode_to_msgcounter[i] == MSG_RCODE_BADVERS) {
+ count_ednsbadver += i;
+ }
+ expect["request.badednsver"] = count_ednsbadver;
+ for (uint16_t j = 0; j <= i; ++j) {
+ if (rcode_to_msgcounter[j] == MSG_RCODE_OTHER) {
+ expect["rcode.other"] = count_rcode_other;
+ } else {
+ std::string code_text = Rcode(j).toText();
+ std::transform(code_text.begin(), code_text.end(),
+ code_text.begin(), ::tolower);
+ expect["rcode."+code_text] = j;
+ }
+ }
+ checkStatisticsCounters(counters.get()->get("zones")->get("_SERVER_"),
+ expect);
+ }
+}
+
+TEST_F(CountersTest, incrementTruncated) {
+ Message response(Message::RENDER);
+ MessageAttributes msgattrs;
+ std::map<std::string, int> expect;
+
+ // Test these patterns:
+ // truncated
+ // -----------
+ // false
+ // true
+ int count_truncated = 0;
+ for (int i = 0; i < 2; ++i) {
+ const bool is_truncated = i & 1;
+ buildSkeletonMessage(msgattrs);
+ msgattrs.setRequestOpCode(Opcode::IQUERY());
+ msgattrs.setRequestTSIG(false, false);
+ msgattrs.setResponseTruncated(is_truncated);
+
+ response.setRcode(Rcode::SERVFAIL());
+ response.addQuestion(Question(Name("example.com"),
+ RRClass::IN(), RRType::TXT()));
+ response.setHeaderFlag(Message::HEADERFLAG_QR);
+
+ counters.inc(msgattrs, response, true);
+
+ if (is_truncated) {
+ ++count_truncated;
+ }
+
+ expect.clear();
+ expect["opcode.iquery"] = i+1;
+ expect["request.v4"] = i+1;
+ expect["request.udp"] = i+1;
+ expect["request.edns0"] = i+1;
+ expect["request.dnssec_ok"] = i+1;
+ expect["responses"] = i+1;
+ expect["rcode.servfail"] = i+1;
+ expect["response.truncated"] = count_truncated;
+ checkStatisticsCounters(counters.get()->get("zones")->get("_SERVER_"),
+ expect);
+ }
+}
+
+TEST_F(CountersTest, incrementQryAuthAnsAndNoAuthAns) {
+ Message response(Message::RENDER);
+ MessageAttributes msgattrs;
+ std::map<std::string, int> expect;
+
+ // Opcode = QUERY, ANCOUNT = 0 (don't care), Rcode = SERVFAIL (don't care)
+ // Test these patterns:
+ // AA flag
+ // -----------------------
+ // false -> QryNoAuthAns
+ // true -> QryAuthAns
+ int count_authans = 0, count_noauthans = 0;
+ for (int i = 0; i < 2; ++i) {
+ const bool is_aa_set = i & 1;
+ buildSkeletonMessage(msgattrs);
+ msgattrs.setRequestTSIG(false, false);
+
+ response.setRcode(Rcode::SERVFAIL());
+ response.addQuestion(Question(Name("example.com"),
+ RRClass::IN(), RRType::TXT()));
+ response.setHeaderFlag(Message::HEADERFLAG_QR);
+ if (is_aa_set) {
+ response.setHeaderFlag(Message::HEADERFLAG_AA);
+ ++count_authans;
+ } else {
+ ++count_noauthans;
+ }
+
+ counters.inc(msgattrs, response, true);
+
+ expect.clear();
+ expect["opcode.query"] = i+1;
+ expect["request.v4"] = i+1;
+ expect["request.udp"] = i+1;
+ expect["request.edns0"] = i+1;
+ expect["request.dnssec_ok"] = i+1;
+ expect["responses"] = i+1;
+ expect["rcode.servfail"] = i+1;
+ expect["qryauthans"] = count_authans;
+ expect["qrynoauthans"] = count_noauthans;
+ checkStatisticsCounters(counters.get()->get("zones")->get("_SERVER_"),
+ expect);
+ }
+}
+
+TEST_F(CountersTest, incrementQrySuccess) {
+ Message response(Message::RENDER);
+ MessageAttributes msgattrs;
+ std::map<std::string, int> expect;
+
+ // Opcode = QUERY, Rcode = NOERROR, ANCOUNT > 0
+ msgattrs.setRequestIPVersion(AF_INET);
+ msgattrs.setRequestTransportProtocol(IPPROTO_UDP);
+ msgattrs.setRequestOpCode(Opcode::QUERY());
+ msgattrs.setRequestEDNS0(true);
+ msgattrs.setRequestDO(true);
+ msgattrs.setRequestTSIG(false, false);
+
+ response.setRcode(Rcode::NOERROR());
+ response.addQuestion(Question(Name("example.com"),
+ RRClass::IN(), RRType::TXT()));
+ RRsetPtr answer_rrset(new RRset(Name("example.com"),
+ RRClass::IN(), RRType::TXT(),
+ RRTTL(3600)));
+ answer_rrset->addRdata(rdata::createRdata(RRType::TXT(),
+ RRClass::IN(),
+ "Answer"));
+ response.addRRset(Message::SECTION_ANSWER, answer_rrset);
+ response.setHeaderFlag(Message::HEADERFLAG_QR);
+
+ counters.inc(msgattrs, response, true);
+
+ expect.clear();
+ expect["opcode.query"] = 1;
+ expect["request.v4"] = 1;
+ expect["request.udp"] = 1;
+ expect["request.edns0"] = 1;
+ expect["request.dnssec_ok"] = 1;
+ expect["responses"] = 1;
+ expect["rcode.noerror"] = 1;
+ expect["qrysuccess"] = 1;
+ // noauthans is also incremented
+ expect["qrynoauthans"] = 1;
+ checkStatisticsCounters(counters.get()->get("zones")->get("_SERVER_"),
+ expect);
+}
+
+TEST_F(CountersTest, incrementQryReferralAndNxrrset) {
+ Message response(Message::RENDER);
+ MessageAttributes msgattrs;
+ std::map<std::string, int> expect;
+
+ // Opcode = QUERY, Rcode = NOERROR, ANCOUNT = 0
+ // Test these patterns:
+ // AA flag
+ // ----------------------
+ // false -> QryReferral
+ // true -> QryNxrrset
+ int count_referral = 0, count_nxrrset = 0;
+ for (int i = 0; i < 2; ++i) {
+ const bool is_aa_set = i & 1;
+ msgattrs.setRequestIPVersion(AF_INET);
+ msgattrs.setRequestTransportProtocol(IPPROTO_UDP);
+ msgattrs.setRequestOpCode(Opcode::QUERY());
+ msgattrs.setRequestEDNS0(true);
+ msgattrs.setRequestDO(true);
+ msgattrs.setRequestTSIG(false, false);
+
+ response.setRcode(Rcode::NOERROR());
+ response.addQuestion(Question(Name("example.com"),
+ RRClass::IN(), RRType::TXT()));
+ response.setHeaderFlag(Message::HEADERFLAG_QR);
+ if (is_aa_set) {
+ response.setHeaderFlag(Message::HEADERFLAG_AA);
+ ++count_nxrrset;
+ } else {
+ ++count_referral;
+ }
+
+ counters.inc(msgattrs, response, true);
+
+ expect.clear();
+ expect["opcode.query"] = i+1;
+ expect["request.v4"] = i+1;
+ expect["request.udp"] = i+1;
+ expect["request.edns0"] = i+1;
+ expect["request.dnssec_ok"] = i+1;
+ expect["responses"] = i+1;
+ expect["rcode.noerror"] = i+1;
+ expect["qrynxrrset"] = count_nxrrset;
+ expect["qryreferral"] = count_referral;
+ // qryauthans or qrynoauthans is also incremented
+ expect["qryauthans"] = count_nxrrset;
+ expect["qrynoauthans"] = count_referral;
+ checkStatisticsCounters(counters.get()->get("zones")->get("_SERVER_"),
+ expect);
+ }
+}
+
+TEST_F(CountersTest, incrementAuthQryRej) {
+ Message response(Message::RENDER);
+ MessageAttributes msgattrs;
+ std::map<std::string, int> expect;
+
+ // Opcode = QUERY, Rcode = REFUSED, ANCOUNT = 0 (don't care)
+ msgattrs.setRequestIPVersion(AF_INET);
+ msgattrs.setRequestTransportProtocol(IPPROTO_UDP);
+ msgattrs.setRequestOpCode(Opcode::QUERY());
+ msgattrs.setRequestEDNS0(true);
+ msgattrs.setRequestDO(true);
+ msgattrs.setRequestTSIG(false, false);
+
+ response.setRcode(Rcode::REFUSED());
+ response.addQuestion(Question(Name("example.com"),
+ RRClass::IN(), RRType::TXT()));
+ response.setHeaderFlag(Message::HEADERFLAG_QR);
+
+ counters.inc(msgattrs, response, true);
+
+ expect.clear();
+ expect["opcode.query"] = 1;
+ expect["request.v4"] = 1;
+ expect["request.udp"] = 1;
+ expect["request.edns0"] = 1;
+ expect["request.dnssec_ok"] = 1;
+ expect["responses"] = 1;
+ expect["rcode.refused"] = 1;
+ expect["authqryrej"] = 1;
+ // noauthans is also incremented since AA bit is not set
+ expect["qrynoauthans"] = 1;
+ checkStatisticsCounters(counters.get()->get("zones")->get("_SERVER_"),
+ expect);
+}
+
+int
+countTreeElements(const struct CounterSpec* tree) {
+ int count = 0;
+ for (int i = 0; tree[i].name != NULL; ++i) {
+ if (tree[i].sub_counters == NULL) {
+ ++count;
+ } else {
+ count += countTreeElements(tree[i].sub_counters);
+ }
+ }
+ return (count);
+}
+
+TEST(StatisticsItemsTest, MSGItemNamesCheck) {
+ EXPECT_EQ(MSG_COUNTER_TYPES, countTreeElements(msg_counter_tree));
+}
+
+}
diff --git a/src/bin/auth/tests/statistics_util.cc b/src/bin/auth/tests/statistics_util.cc
new file mode 100644
index 0000000..bb2cd5c
--- /dev/null
+++ b/src/bin/auth/tests/statistics_util.cc
@@ -0,0 +1,75 @@
+// Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#include "statistics_util.h"
+
+#include <gtest/gtest.h>
+
+#include <string>
+#include <map>
+
+namespace {
+void
+flatten(std::map<std::string, int>& flat_map, const std::string& prefix,
+ const isc::data::ConstElementPtr map_element)
+{
+ std::map<std::string, isc::data::ConstElementPtr> map =
+ map_element->mapValue();
+ for (std::map<std::string, isc::data::ConstElementPtr>::const_iterator
+ i = map.begin(), e = map.end();
+ i != e;
+ ++i)
+ {
+ switch (i->second->getType()) {
+ case isc::data::Element::map:
+ flatten(flat_map, i->first + ".", i->second);
+ break;
+ case isc::data::Element::integer:
+ flat_map[prefix + i->first] = i->second->intValue();
+ break;
+ default:
+ FAIL() << "Element Parse Error";
+ }
+ }
+}
+}
+
+namespace isc {
+namespace auth {
+namespace unittest {
+
+void
+checkStatisticsCounters(const isc::data::ConstElementPtr counters,
+ const std::map<std::string, int>& expect)
+{
+ std::map<std::string, int> stats_map;
+ flatten(stats_map, "", counters);
+
+ for (std::map<std::string, int>::const_iterator
+ i = stats_map.begin(), e = stats_map.end();
+ i != e;
+ ++i)
+ {
+ const int value =
+ expect.find(i->first) == expect.end() ?
+ 0 : expect.find(i->first)->second;
+ EXPECT_EQ(value, i->second) << "Expected counter "
+ << i->first << " = " << value << ", actual: "
+ << i->second;
+ }
+}
+
+} // end of unittest
+} // end of auth
+} // end of isc
diff --git a/src/bin/auth/tests/statistics_util.h b/src/bin/auth/tests/statistics_util.h
new file mode 100644
index 0000000..b01a016
--- /dev/null
+++ b/src/bin/auth/tests/statistics_util.h
@@ -0,0 +1,38 @@
+// Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#ifndef __AUTH_STATISTICS_UTIL_H
+#define __AUTH_STATISTICS_UTIL_H 1
+
+#include <cc/data.h>
+
+namespace isc {
+namespace auth {
+namespace unittest {
+
+// Test if the counters has expected values specified in expect and the others
+// are zero.
+void
+checkStatisticsCounters(const isc::data::ConstElementPtr counters,
+ const std::map<std::string, int>& expect);
+
+} // end of unittest
+} // end of auth
+} // end of isc
+
+#endif // __AUTH_STATISTICS_UTIL_H
+
+// Local Variables:
+// mode: c++
+// End:
diff --git a/src/lib/statistics/counter.h b/src/lib/statistics/counter.h
index af52da4..b0d31e9 100644
--- a/src/lib/statistics/counter.h
+++ b/src/lib/statistics/counter.h
@@ -22,10 +22,6 @@
#include <vector>
-namespace {
-const unsigned int InitialValue = 0;
-} // anonymous namespace
-
namespace isc {
namespace statistics {
@@ -40,24 +36,19 @@ private:
public:
/// The constructor.
///
- /// This constructor is mostly exception free. But it may still throw
- /// a standard exception if memory allocation fails inside the method.
+ /// This constructor prepares a set of counters which has \a items
+ /// elements. The counters will be initialized with 0.
///
/// \param items A number of counter items to hold (greater than 0)
///
/// \throw isc::InvalidParameter \a items is 0
explicit Counter(const size_t items) :
- counters_(items, InitialValue)
+ counters_(items, 0)
{
if (items == 0) {
isc_throw(isc::InvalidParameter, "Items must not be 0");
}
- };
-
- /// The destructor.
- ///
- /// This method never throws an exception.
- ~Counter() {};
+ }
/// \brief Increment a counter item specified with \a type.
///
@@ -70,7 +61,7 @@ public:
}
++counters_.at(type);
return;
- };
+ }
/// \brief Get the value of a counter item specified with \a type.
///
@@ -82,7 +73,7 @@ public:
isc_throw(isc::OutOfRange, "Counter type is out of range");
}
return (counters_.at(type));
- };
+ }
};
} // namespace statistics
diff --git a/src/lib/statistics/counter_dict.h b/src/lib/statistics/counter_dict.h
index e288dfe..6c87bec 100644
--- a/src/lib/statistics/counter_dict.h
+++ b/src/lib/statistics/counter_dict.h
@@ -26,28 +26,34 @@
#include <cassert>
#include <stdexcept>
#include <string>
-#include <vector>
#include <map>
#include <iterator>
#include <utility>
-namespace {
-typedef boost::shared_ptr<isc::statistics::Counter> CounterPtr;
-typedef std::map<std::string, CounterPtr> DictionaryMap;
-}
namespace isc {
namespace statistics {
class CounterDictionary : boost::noncopyable {
private:
+ typedef boost::shared_ptr<isc::statistics::Counter> CounterPtr;
+ typedef std::map<std::string, CounterPtr> DictionaryMap;
DictionaryMap dictionary_;
- std::vector<std::string> elements_;
const size_t items_;
// Default constructor is forbidden; number of counter items must be
// specified at the construction of this class.
CounterDictionary();
public:
+ /// The constructor.
+ ///
+ /// This constructor prepares a dictionary of set of counters.
+ /// Initially the dictionary is empty.
+ /// Each counter has \a items elements. The counters will be initialized
+ /// with 0.
+ ///
+ /// \param items A number of counter items to hold (greater than 0)
+ ///
+ /// \throw isc::InvalidParameter \a items is 0
explicit CounterDictionary(const size_t items) :
items_(items)
{
@@ -55,11 +61,17 @@ public:
if (items == 0) {
isc_throw(isc::InvalidParameter, "Items must not be 0");
}
- };
- ~CounterDictionary() {};
+ }
+
+ /// \brief Add an element which has a key \a name to the dictionary.
+ ///
+ /// \param name A key of the element to add
+ ///
+ /// \throw isc::InvalidParameter an element which has \a name as key
+ /// already exists
void addElement(const std::string& name) {
// throw if the element already exists
- if (dictionary_.count(name) != 0) {
+ if (dictionary_.find(name) != dictionary_.end()) {
isc_throw(isc::InvalidParameter,
"Element " << name << " already exists");
}
@@ -67,16 +79,30 @@ public:
// Create a new Counter and add to the map
dictionary_.insert(
DictionaryMap::value_type(name, CounterPtr(new Counter(items_))));
- };
+ }
+
+ /// \brief Delete the element which has a key \a name from the dictionary.
+ ///
+ /// \param name A key of the element to delete
+ ///
+ /// \throw isc::OutOfRange an element which has \a name as key does not
+ /// exist
void deleteElement(const std::string& name) {
- size_t result = dictionary_.erase(name);
+ const size_t result = dictionary_.erase(name);
if (result != 1) {
// If an element with specified name does not exist, throw
// isc::OutOfRange.
isc_throw(isc::OutOfRange,
"Element " << name << " does not exist");
}
- };
+ }
+
+ /// \brief Get a reference to a %Counter which has \a name as key
+ ///
+ /// \param name A key of the element
+ ///
+ /// \throw isc::OutOfRange an element which has \a name as key does not
+ /// exist
Counter& getElement(const std::string& name) {
DictionaryMap::const_iterator i = dictionary_.find(name);
if (i != dictionary_.end()) {
@@ -88,10 +114,13 @@ public:
isc_throw(isc::OutOfRange,
"Element " << name << " does not exist");
}
- };
+ }
+
+ /// \brief Same as \c getElement()
Counter& operator[](const std::string& name) {
return (getElement(name));
- };
+ }
+
/// \brief \c ConstIterator is a constant iterator that provides an
/// interface for enumerating name of zones stored in CounterDictionary.
///
@@ -107,35 +136,28 @@ public:
boost::forward_traversal_tag>
{
public:
- /// The constructor.
- ///
- /// This constructor is mostly exception free. But it may still
- /// throw a standard exception if memory allocation fails
- /// inside the method.
+ /// \brief The constructor.
ConstIterator() {}
- /// The destructor.
- ///
- /// This method never throws an exception.
- ~ConstIterator() {}
- /// Constructor from implementation detail DictionaryMap::const_iterator
- ConstIterator(
- DictionaryMap::const_iterator iterator) :
+
+ /// \brief Constructor from implementation detail
+ /// DictionaryMap::const_iterator
+ ConstIterator(DictionaryMap::const_iterator iterator) :
iterator_(iterator)
{}
private:
- /// \brief An internal method to increment this iterator.
+ // An internal method to increment this iterator.
void increment() {
++iterator_;
return;
}
- /// \brief An internal method to check equality.
+ // An internal method to check equality.
bool equal(const ConstIterator& other) const {
return (iterator_ == other.iterator_);
}
- /// \brief An internal method to dereference this iterator.
+ // An internal method to dereference this iterator.
const value_type& dereference() const {
return (iterator_->first);
}
@@ -145,12 +167,15 @@ public:
DictionaryMap::const_iterator iterator_;
};
+ /// \brief Get an iterator for the beginning of the dictionary.
ConstIterator begin() const {
return (CounterDictionary::ConstIterator(dictionary_.begin()));
- };
+ }
+
+ /// \brief Get an iterator for the end of the dictionary.
ConstIterator end() const {
return (CounterDictionary::ConstIterator(dictionary_.end()));
- };
+ }
typedef ConstIterator const_iterator;
};
diff --git a/src/lib/testutils/testdata/example.com b/src/lib/testutils/testdata/example.com
index 5e0e079..24ce218 100644
--- a/src/lib/testutils/testdata/example.com
+++ b/src/lib/testutils/testdata/example.com
@@ -6,3 +6,11 @@ ns.example.com. A 192.0.2.1
;; bogus RDATA for CNAME RR, but the loadzone tool accepts it. looking up this
;; record will trigger an exception.
broken.example.com. CNAME 0123456789012345678901234567890123456789012345678901234567890123456789.example.com.
+
+;; very large RDATA. it exceeds 512 octets.
+large-rdata.example.com. TXT "0-1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"
+large-rdata.example.com. TXT "1-1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"
+large-rdata.example.com. TXT "2-1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"
+large-rdata.example.com. TXT "3-1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"
+large-rdata.example.com. TXT "4-1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"
+large-rdata.example.com. TXT "5-1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"
diff --git a/src/lib/testutils/testdata/example.sqlite3 b/src/lib/testutils/testdata/example.sqlite3
index 0f6ee02..032e7c7 100644
Binary files a/src/lib/testutils/testdata/example.sqlite3 and b/src/lib/testutils/testdata/example.sqlite3 differ
diff --git a/tests/lettuce/configurations/example.org.inmem.config b/tests/lettuce/configurations/example.org.inmem.config
index 7ec921d..2e9ca41 100644
--- a/tests/lettuce/configurations/example.org.inmem.config
+++ b/tests/lettuce/configurations/example.org.inmem.config
@@ -26,9 +26,13 @@
]
}
},
+ "Stats": {
+ "poll-interval": 1
+ },
"Init": {
"components": {
"b10-auth": { "kind": "needed", "special": "auth" },
+ "b10-stats": { "address": "Stats", "kind": "dispensable" },
"b10-cmdctl": { "special": "cmdctl", "kind": "needed" }
}
}
diff --git a/tests/lettuce/features/queries.feature b/tests/lettuce/features/queries.feature
index 7ae2284..8a66d1c 100644
--- a/tests/lettuce/features/queries.feature
+++ b/tests/lettuce/features/queries.feature
@@ -8,15 +8,27 @@ Feature: Querying feature
And wait for bind10 stderr message BIND10_STARTED_CC
And wait for bind10 stderr message CMDCTL_STARTED
And wait for bind10 stderr message AUTH_SERVER_STARTED
+ And wait for bind10 stderr message STATS_STARTING
bind10 module Auth should be running
+ And bind10 module Stats should be running
And bind10 module Resolver should not be running
And bind10 module Xfrout should not be running
And bind10 module Zonemgr should not be running
And bind10 module Xfrin should not be running
- And bind10 module Stats should not be running
And bind10 module StatsHttpd should not be running
+ When I wait for new bind10 stderr message STATS_SEND_STATISTICS_REQUEST
+ # make sure Auth module receives a command
+ And wait for new bind10 stderr message AUTH_RECEIVED_COMMAND
+ # make sure Auth module replied to the command
+ And wait for new bind10 stderr message CC_REPLY
+ # make sure the response is for 'getstats'
+ And wait for new bind10 stderr message v4
+ Then I query statistics zones of bind10 module Auth
+ And last bindctl output should not contain "error"
+ The statistics counters are 0 in category .Auth.zones._SERVER_
+
A query for www.example.org should have rcode NOERROR
The last query response should have flags qr aa rd
The last query response should have ancount 1
@@ -38,6 +50,26 @@ Feature: Querying feature
ns2.example.org. 3600 IN A 192.0.2.4
"""
+ When I wait for new bind10 stderr message STATS_SEND_STATISTICS_REQUEST
+ # make sure Auth module receives a command
+ And wait for new bind10 stderr message AUTH_RECEIVED_COMMAND
+ # make sure Auth module replied to the command
+ And wait for new bind10 stderr message CC_REPLY
+ # make sure the response is for 'getstats'
+ And wait for new bind10 stderr message v4
+ Then I query statistics zones of bind10 module Auth
+ And last bindctl output should not contain "error"
+ The statistics counters are 0 in category .Auth.zones._SERVER_ except for the following items
+ | item_name | item_value |
+ | request.v4 | 1 |
+ | request.udp | 1 |
+ | opcode.query | 1 |
+ | responses | 1 |
+ | qrysuccess | 1 |
+ | qryauthans | 1 |
+ | rcode.noerror | 1 |
+
+
# Repeat of the above
A query for www.example.org should have rcode NOERROR
The last query response should have flags qr aa rd
@@ -60,6 +92,25 @@ Feature: Querying feature
ns2.example.org. 3600 IN A 192.0.2.4
"""
+ When I wait for new bind10 stderr message STATS_SEND_STATISTICS_REQUEST
+ # make sure Auth module receives a command
+ And wait for new bind10 stderr message AUTH_RECEIVED_COMMAND
+ # make sure Auth module replied to the command
+ And wait for new bind10 stderr message CC_REPLY
+ # make sure the response is for 'getstats'
+ And wait for new bind10 stderr message v4
+ Then I query statistics zones of bind10 module Auth
+ And last bindctl output should not contain "error"
+ The statistics counters are 0 in category .Auth.zones._SERVER_ except for the following items
+ | item_name | item_value |
+ | request.v4 | 2 |
+ | request.udp | 2 |
+ | opcode.query | 2 |
+ | responses | 2 |
+ | qrysuccess | 2 |
+ | qryauthans | 2 |
+ | rcode.noerror | 2 |
+
# And now query something completely different
A query for nosuchname.example.org should have rcode NXDOMAIN
The last query response should have flags qr aa rd
@@ -71,6 +122,26 @@ Feature: Querying feature
example.org. 3600 IN SOA ns1.example.org. admin.example.org. 1234 3600 1800 2419200 7200
"""
+ When I wait for new bind10 stderr message STATS_SEND_STATISTICS_REQUEST
+ # make sure Auth module receives a command
+ And wait for new bind10 stderr message AUTH_RECEIVED_COMMAND
+ # make sure Auth module replied to the command
+ And wait for new bind10 stderr message CC_REPLY
+ # make sure the response is for 'getstats'
+ And wait for new bind10 stderr message v4
+ Then I query statistics zones of bind10 module Auth
+ And last bindctl output should not contain "error"
+ The statistics counters are 0 in category .Auth.zones._SERVER_ except for the following items
+ | item_name | item_value |
+ | request.v4 | 3 |
+ | request.udp | 3 |
+ | opcode.query | 3 |
+ | responses | 3 |
+ | qrysuccess | 2 |
+ | qryauthans | 3 |
+ | rcode.noerror | 2 |
+ | rcode.nxdomain | 1 |
+
Scenario: ANY query
Given I have bind10 running with configuration example.org.inmem.config
And wait for bind10 stderr message BIND10_STARTED_CC
@@ -78,13 +149,24 @@ Feature: Querying feature
And wait for bind10 stderr message AUTH_SERVER_STARTED
bind10 module Auth should be running
+ And bind10 module Stats should be running
And bind10 module Resolver should not be running
And bind10 module Xfrout should not be running
And bind10 module Zonemgr should not be running
And bind10 module Xfrin should not be running
- And bind10 module Stats should not be running
And bind10 module StatsHttpd should not be running
+ When I wait for new bind10 stderr message STATS_SEND_STATISTICS_REQUEST
+ # make sure Auth module receives a command
+ And wait for new bind10 stderr message AUTH_RECEIVED_COMMAND
+ # make sure Auth module replied to the command
+ And wait for new bind10 stderr message CC_REPLY
+ # make sure the response is for 'getstats'
+ And wait for new bind10 stderr message v4
+ Then I query statistics zones of bind10 module Auth
+ And last bindctl output should not contain "error"
+ The statistics counters are 0 in category .Auth.zones._SERVER_
+
A query for example.org type ANY should have rcode NOERROR
The last query response should have flags qr aa rd
The last query response should have ancount 4
@@ -104,11 +186,42 @@ Feature: Querying feature
mail.example.org. 3600 IN A 192.0.2.10
"""
+ When I wait for new bind10 stderr message STATS_SEND_STATISTICS_REQUEST
+ # make sure Auth module receives a command
+ And wait for new bind10 stderr message AUTH_RECEIVED_COMMAND
+ # make sure Auth module replied to the command
+ And wait for new bind10 stderr message CC_REPLY
+ # make sure the response is for 'getstats'
+ And wait for new bind10 stderr message v4
+ Then I query statistics zones of bind10 module Auth
+ And last bindctl output should not contain "error"
+ The statistics counters are 0 in category .Auth.zones._SERVER_ except for the following items
+ | item_name | item_value |
+ | request.v4 | 1 |
+ | request.udp | 1 |
+ | opcode.query | 1 |
+ | responses | 1 |
+ | qrysuccess | 1 |
+ | qryauthans | 1 |
+ | rcode.noerror | 1 |
+
Scenario: Delegation query for unsigned child zone
Given I have bind10 running with configuration example.org.inmem.config
And wait for bind10 stderr message BIND10_STARTED_CC
And wait for bind10 stderr message CMDCTL_STARTED
And wait for bind10 stderr message AUTH_SERVER_STARTED
+
+ When I wait for new bind10 stderr message STATS_SEND_STATISTICS_REQUEST
+ # make sure Auth module receives a command
+ And wait for new bind10 stderr message AUTH_RECEIVED_COMMAND
+ # make sure Auth module replied to the command
+ And wait for new bind10 stderr message CC_REPLY
+ # make sure the response is for 'getstats'
+ And wait for new bind10 stderr message v4
+ Then I query statistics zones of bind10 module Auth
+ And last bindctl output should not contain "error"
+ The statistics counters are 0 in category .Auth.zones._SERVER_
+
A dnssec query for www.sub.example.org type AAAA should have rcode NOERROR
The last query response should have flags qr rd
The last query response should have edns_flags do
@@ -124,6 +237,28 @@ Feature: Querying feature
ns.sub.example.org. 3600 IN A 192.0.2.101
"""
+ When I wait for new bind10 stderr message STATS_SEND_STATISTICS_REQUEST
+ # make sure Auth module receives a command
+ And wait for new bind10 stderr message AUTH_RECEIVED_COMMAND
+ # make sure Auth module replied to the command
+ And wait for new bind10 stderr message CC_REPLY
+ # make sure the response is for 'getstats'
+ And wait for new bind10 stderr message v4
+ Then I query statistics zones of bind10 module Auth
+ And last bindctl output should not contain "error"
+ The statistics counters are 0 in category .Auth.zones._SERVER_ except for the following items
+ | item_name | item_value |
+ | request.v4 | 1 |
+ | request.udp | 1 |
+ | request.edns0 | 1 |
+ | request.dnssec_ok | 1 |
+ | opcode.query | 1 |
+ | responses | 1 |
+ | response.edns0 | 1 |
+ | qrynoauthans | 1 |
+ | qryreferral | 1 |
+ | rcode.noerror | 1 |
+
Scenario: SSHFP query
# We are testing one more RR type for a normal successful case
Given I have bind10 running with configuration example.org.inmem.config
@@ -132,18 +267,69 @@ Feature: Querying feature
And wait for bind10 stderr message AUTH_SERVER_STARTED
bind10 module Auth should be running
+ And bind10 module Stats should be running
And bind10 module Resolver should not be running
And bind10 module Xfrout should not be running
And bind10 module Zonemgr should not be running
And bind10 module Xfrin should not be running
- And bind10 module Stats should not be running
And bind10 module StatsHttpd should not be running
+ When I wait for new bind10 stderr message STATS_SEND_STATISTICS_REQUEST
+ # make sure Auth module receives a command
+ And wait for new bind10 stderr message AUTH_RECEIVED_COMMAND
+ # make sure Auth module replied to the command
+ And wait for new bind10 stderr message CC_REPLY
+ # make sure the response is for 'getstats'
+ And wait for new bind10 stderr message v4
+ Then I query statistics zones of bind10 module Auth
+ And last bindctl output should not contain "error"
+ The statistics counters are 0 in category .Auth.zones._SERVER_
+
A query for example.org type SSHFP should have rcode NOERROR
The last query response should have ancount 0
+
+ When I wait for new bind10 stderr message STATS_SEND_STATISTICS_REQUEST
+ # make sure Auth module receives a command
+ And wait for new bind10 stderr message AUTH_RECEIVED_COMMAND
+ # make sure Auth module replied to the command
+ And wait for new bind10 stderr message CC_REPLY
+ # make sure the response is for 'getstats'
+ And wait for new bind10 stderr message v4
+ Then I query statistics zones of bind10 module Auth
+ And last bindctl output should not contain "error"
+ The statistics counters are 0 in category .Auth.zones._SERVER_ except for the following items
+ | item_name | item_value |
+ | request.v4 | 1 |
+ | request.udp | 1 |
+ | opcode.query | 1 |
+ | responses | 1 |
+ | qryauthans | 1 |
+ | qrynxrrset | 1 |
+ | rcode.noerror | 1 |
+
A query for shell.example.org type SSHFP should have rcode NOERROR
The last query response should have ancount 1
The answer section of the last query response should be
"""
shell.example.org. 3600 IN SSHFP 2 1 123456789abcdef67890123456789abcdef67890
"""
+
+ When I wait for new bind10 stderr message STATS_SEND_STATISTICS_REQUEST
+ # make sure Auth module receives a command
+ And wait for new bind10 stderr message AUTH_RECEIVED_COMMAND
+ # make sure Auth module replied to the command
+ And wait for new bind10 stderr message CC_REPLY
+ # make sure the response is for 'getstats'
+ And wait for new bind10 stderr message v4
+ Then I query statistics zones of bind10 module Auth
+ And last bindctl output should not contain "error"
+ The statistics counters are 0 in category .Auth.zones._SERVER_ except for the following items
+ | item_name | item_value |
+ | request.v4 | 2 |
+ | request.udp | 2 |
+ | opcode.query | 2 |
+ | responses | 2 |
+ | qrysuccess | 1 |
+ | qryauthans | 2 |
+ | qrynxrrset | 1 |
+ | rcode.noerror | 2 |
diff --git a/tests/lettuce/features/terrain/bind10_control.py b/tests/lettuce/features/terrain/bind10_control.py
index 7cc7d3e..9426d8c 100644
--- a/tests/lettuce/features/terrain/bind10_control.py
+++ b/tests/lettuce/features/terrain/bind10_control.py
@@ -391,14 +391,16 @@ def find_value(dictionary, key):
for v in dictionary.values():
return find_value(v, key)
- at step('the statistics counter (\S+)(?: for the zone (\S+))? should be' + \
+ at step('the statistics counter (\S+)(?: in the category (\S+))?'+ \
+ '(?: for the zone (\S+))? should be' + \
'(?:( greater than| less than| between))? (\-?\d+)(?: and (\-?\d+))?')
-def check_statistics(step, counter, zone, gtltbt, number, upper):
+def check_statistics(step, counter, category, zone, gtltbt, number, upper):
"""
check the output of bindctl for statistics of specified counter
and zone.
Parameters:
counter ('counter <counter>'): The counter name of statistics.
+ category ('category <category>', optional): The category of counter.
zone ('zone <zone>', optional): The zone name.
gtltbt (' greater than'|' less than'|' between', optional): greater than
<number> or less than <number> or between <number> and <upper>.
@@ -409,14 +411,21 @@ def check_statistics(step, counter, zone, gtltbt, number, upper):
"""
output = parse_bindctl_output_as_data_structure()
found = None
+ category_str = ""
zone_str = ""
+ depth = []
+ if category:
+ depth.insert(0, category)
+ category_str = " for category %s" % category
if zone:
- found = find_value(find_value(output, zone), counter)
+ depth.insert(0, zone)
zone_str = " for zone %s" % zone
- else:
- found = find_value(output, counter)
+ for level in depth:
+ output = find_value(output, level)
+ found = find_value(output, counter)
assert found is not None, \
- 'Not found statistics counter %s%s' % (counter, zone_str)
+ 'Not found statistics counter %s%s%s' % \
+ (counter, category_str, zone_str)
msg = "Got %s, expected%s %s as counter %s%s" % \
(found, gtltbt, number, counter, zone_str)
if gtltbt and 'between' in gtltbt and upper:
@@ -430,3 +439,46 @@ def check_statistics(step, counter, zone, gtltbt, number, upper):
assert int(found) < int(number), msg
else:
assert int(found) == int(number), msg
+
+ at step('statistics counters are 0 in category (\S+)( except for the' + \
+ ' following items)?')
+def check_statistics_items(step, category, has_except_for):
+ """
+ check the output of bindctl for statistics of specified counter.
+ Parameters:
+ category ('category <category>'): The category of counter.
+ has_except_for ('except for the following items'): checks values of items
+ with the multiline part.
+
+ Expected values of items are taken from the multiline part of the step in
+ the scenario. The multiline part has two columns: item_name and item_value.
+ item_name is a relative name to category. item_value is an expected value
+ for item_name.
+ """
+
+ def flatten(dictionary, prefix=''):
+ h = {}
+ for k, v in dictionary.items():
+ if type(v) is dict:
+ h.update(flatten(v, prefix+'.'+k))
+ else:
+ h[prefix+'.'+k] = v
+ return h
+
+ stats = flatten(parse_bindctl_output_as_data_structure())
+ if has_except_for:
+ # fetch step tables in the scnario as hashes
+ for item in step.hashes:
+ name = category+'.'+item['item_name']
+ value = item['item_value']
+ assert stats.has_key(name), \
+ 'Statistics item %s was not found' % (name)
+ found = stats[name]
+ assert int(found) == int(value), \
+ 'Statistics item %s has unexpected value %s (expect %s)' % \
+ (name, found, value)
+ del(stats[name])
+ for name, found in stats.items():
+ assert int(found) == 0, \
+ 'Statistics item %s has unexpected value %s (expect %s)' % \
+ (name, found, 0)
diff --git a/tests/system/bindctl/tests.sh b/tests/system/bindctl/tests.sh
index ca58240..e1e533a 100755
--- a/tests/system/bindctl/tests.sh
+++ b/tests/system/bindctl/tests.sh
@@ -25,12 +25,66 @@ status=0
n=0
# TODO: consider consistency with statistics definition in auth.spec
-cnt_name1="\<queries\.tcp\>"
-cnt_name2="\<queries\.udp\>"
-cnt_name3="\<opcode\.query\>"
-cnt_value1=0
-cnt_value2=0
-cnt_value3=0
+
+# flatten JSON
+awk_flatten_json='
+function join(ary, len) {
+ ret = "";
+ for (i = 1; i <= len; ++i) {
+ ret = ret""ary[i];
+ }
+ return ret;
+}
+BEGIN {
+ depth = 0;
+}
+/.+{$/ {
+ label[++depth] = $1;
+ next;
+}
+/},?/ {
+ --depth;
+ next;
+}
+/:/ {
+ print join(label,depth)""$1" "$2;
+}
+'
+# Check the counters have expected values given with 1st argument.
+# This function tests only these counters will be incremented in every checks
+# since the content of datasource and requests are not changed in this test.
+test_counters () {
+ status=0
+ $AWK "$awk_flatten_json" bindctl.out.$n | \
+ grep '"Auth":"zones":"_SERVER_":"request":"v4": '$1 > \
+ /dev/null || status=1
+ $AWK "$awk_flatten_json" bindctl.out.$n | \
+ grep '"Auth":"zones":"_SERVER_":"request":"v6": '0 > \
+ /dev/null || status=1
+ $AWK "$awk_flatten_json" bindctl.out.$n | \
+ grep '"Auth":"zones":"_SERVER_":"request":"udp": '$1 > \
+ /dev/null || status=1
+ $AWK "$awk_flatten_json" bindctl.out.$n | \
+ grep '"Auth":"zones":"_SERVER_":"request":"tcp": '0 > \
+ /dev/null || status=1
+ $AWK "$awk_flatten_json" bindctl.out.$n | \
+ grep '"Auth":"zones":"_SERVER_":"opcode":"query": '$1 > \
+ /dev/null || status=1
+ $AWK "$awk_flatten_json" bindctl.out.$n | \
+ grep '"Auth":"zones":"_SERVER_":"responses": '$1 > \
+ /dev/null || status=1
+ $AWK "$awk_flatten_json" bindctl.out.$n | \
+ grep '"Auth":"zones":"_SERVER_":"rcode":"noerror": '$1 > \
+ /dev/null || status=1
+ $AWK "$awk_flatten_json" bindctl.out.$n | \
+ grep '"Auth":"zones":"_SERVER_":"qrysuccess": '$1 > \
+ /dev/null || status=1
+ $AWK "$awk_flatten_json" bindctl.out.$n | \
+ grep '"Auth":"zones":"_SERVER_":"qryauthans": '$1 > \
+ /dev/null || status=1
+ return $status
+}
+expected_count=0
echo "I:Checking b10-auth is disabled by default ($n)"
$DIG +norec @10.53.0.1 -p 53210 ns.example.com. A > /dev/null && status=1
@@ -56,15 +110,10 @@ sleep 2
echo 'Stats show
' | $RUN_BINDCTL \
--csv-file-dir=$BINDCTL_CSV_DIR > bindctl.out.$n || status=1
-# the server should have received 1 UDP and 0 TCP queries (the server
-# startup script no longer sends any TCP queries)
-cnt_value1=`expr $cnt_value1 + 0`
-cnt_value2=`expr $cnt_value2 + 1`
-cnt_value3=`expr $cnt_value1 + $cnt_value2`
-grep $cnt_name1".*\<"$cnt_value1"\>" bindctl.out.$n > /dev/null || status=1
-grep $cnt_name2".*\<"$cnt_value2"\>" bindctl.out.$n > /dev/null || status=1
-grep $cnt_name3".*\<"$cnt_value3"\>" bindctl.out.$n > /dev/null || status=1
-if [ $status != 0 ]; then echo "I:failed"; fi
+# the server should have received 1 request
+expected_count=`expr $expected_count + 1`
+test_counters $expected_count
+if [ $? != 0 ]; then echo "I:failed"; fi
n=`expr $n + 1`
echo "I:Stopping b10-auth and checking that ($n)"
@@ -102,13 +151,9 @@ echo 'Stats show
# auth sent. Then it cumulates them and new counts which the living
# auth sends. This note assumes that the issue would have been
# resolved : "#1941 stats lossage (multiple auth servers)".
-cnt_value1=`expr $cnt_value1 + 0`
-cnt_value2=`expr $cnt_value2 + 1`
-cnt_value3=`expr $cnt_value1 + $cnt_value2`
-grep $cnt_name1".*\<"$cnt_value1"\>" bindctl.out.$n > /dev/null || status=1
-grep $cnt_name2".*\<"$cnt_value2"\>" bindctl.out.$n > /dev/null || status=1
-grep $cnt_name3".*\<"$cnt_value3"\>" bindctl.out.$n > /dev/null || status=1
-if [ $status != 0 ]; then echo "I:failed"; fi
+expected_count=`expr $expected_count + 1`
+test_counters $expected_count
+if [ $? != 0 ]; then echo "I:failed"; fi
n=`expr $n + 1`
echo "I:Changing the data source from sqlite3 to in-memory ($n)"
@@ -131,13 +176,9 @@ echo 'Stats show
' | $RUN_BINDCTL \
--csv-file-dir=$BINDCTL_CSV_DIR > bindctl.out.$n || status=1
# The statistics counters shouldn't be reset due to hot-swapping datasource.
-cnt_value1=`expr $cnt_value1 + 0`
-cnt_value2=`expr $cnt_value2 + 1`
-cnt_value3=`expr $cnt_value1 + $cnt_value2`
-grep $cnt_name1".*\<"$cnt_value1"\>" bindctl.out.$n > /dev/null || status=1
-grep $cnt_name2".*\<"$cnt_value2"\>" bindctl.out.$n > /dev/null || status=1
-grep $cnt_name3".*\<"$cnt_value3"\>" bindctl.out.$n > /dev/null || status=1
-if [ $status != 0 ]; then echo "I:failed"; fi
+expected_count=`expr $expected_count + 1`
+test_counters $expected_count
+if [ $? != 0 ]; then echo "I:failed"; fi
n=`expr $n + 1`
echo "I:Starting more b10-auths and checking that ($n)"
@@ -158,9 +199,7 @@ n=`expr $n + 1`
echo "I:Rechecking BIND 10 statistics consistency after a pause ($n)"
sleep 2
-cnt_value1=`expr $cnt_value1 + 0`
-cnt_value2=`expr $cnt_value2 + 1`
-cnt_value3=`expr $cnt_value1 + $cnt_value2`
+expected_count=`expr $expected_count + 1`
# Rechecking some times
for i in 1 2 3 4
do
@@ -170,10 +209,8 @@ do
# The statistics counters should keep being consistent even while
# multiple b10-auths are running.
- grep $cnt_name1".*\<"$cnt_value1"\>" bindctl.out.$n > /dev/null || status=1
- grep $cnt_name2".*\<"$cnt_value2"\>" bindctl.out.$n > /dev/null || status=1
- grep $cnt_name3".*\<"$cnt_value3"\>" bindctl.out.$n > /dev/null || status=1
- if [ $status != 0 ]; then echo "I:failed "; break ; fi
+ test_counters $expected_count
+ if [ $? != 0 ]; then echo "I:failed "; break ; fi
done
n=`expr $n + 1`
More information about the bind10-changes
mailing list