BIND 10 trac2689, updated. d6e34fc0d99e325ccd5f253abdbb1abd27b21935 [2689] a bit of cleanup: rename some internal methods and add comments.
BIND 10 source code commits
bind10-changes at lists.isc.org
Mon Feb 25 15:39:47 UTC 2013
The branch, trac2689 has been updated
via d6e34fc0d99e325ccd5f253abdbb1abd27b21935 (commit)
via 6ffab5a7aa42d2f1210d3036658dcf4398c6ff99 (commit)
via 3fa16c71cbffab13bcdeb311a1e81a29f107d647 (commit)
via 808dcdccc72caa04645c15af4493a76bacbd838f (commit)
via 4df19b60af5ade5f1705fbb76a90fbca0e6b7fba (commit)
via 563843956a6102cc3da274eb79413dc6b0d411c4 (commit)
via 1c1d2c888dbadc9cf707b8f49ced2403e864cd8c (commit)
via 7a34e78976f20bec3f0e8287cb44a4ed7e351924 (commit)
via 9afaf171e6bd58b74e4ae89b394b51f5e8bc6fb4 (commit)
via 77d49bfce9ba4ef3bcd39529b1cd0148381044cf (commit)
via 6dc0f0ecc269c2b59f78bc0dbd9176214b3266a3 (commit)
via e653adac032f871cbd66cd500c37407a56d14589 (commit)
via 54e52000440917a5d9e3dfb0862262e2748c07e0 (commit)
via 6f119e40e88a7fc07e1b3bd1a3e26c3e46b9dfab (commit)
via 0735f72f09fc04cb01aa4df9912ecd265b4f8a05 (commit)
via 5958767f0f9b18aa1d0fa7336ca2bcf12daf1bb2 (commit)
via e4aaeac97a46220f8f333ae8e1e5b39611995786 (commit)
via 75862a73a3498055dc8333ab25edb7130a5d492d (commit)
via 8131da32a67a248150d55280f94c01ce0c377272 (commit)
via 30aa2837a02a8926103dd73668a2572d70555658 (commit)
via 3ddbe715a140ddcd4d6c2cdea1401ec0e28ea89d (commit)
via f0ecf9503468cce0ddcf776adf143b46c821994c (commit)
via 3bec0f1f82f1bbc2a296cb40999047421abcba94 (commit)
via e4688c06e8217659cf1c1c72adacba12ef9e8974 (commit)
via 2d286d766980909cda293cd10fe80c8acc7cfe46 (commit)
via 7da8c5f511ba519a582e5c9828b74de03651f701 (commit)
via 10cbf4c33a915a6287bc8b32b5b3f521b4ced50b (commit)
via 59651a74809b06c0228d2b39202335fffaee048e (commit)
via 4d5d7d6e423cb6e46a9f4acfde4e8ebf434951d2 (commit)
via cee365b41dfe5e24b62d02d21a2f52749bb19688 (commit)
via f5ba7aa63517eaada091025d8ec61a34b797a743 (commit)
via 2e5d462ccc30e3c63f82ced6aa9a3c4732562188 (commit)
via 1b746a6a6ab6eaa92aa9ba913b690dad4c930378 (commit)
via 773d25dc86682595c2af983b7c349deea9abb0b6 (commit)
via f29f0653f27ce5e551039d544b07acefd6e1275e (commit)
via b459be530b5b159af7de708fe653f5b500a9745f (commit)
via 3d8d88cb37a6423b9f1b969e8ab3342e8116cf83 (commit)
via 12027383143fceba912caded72cdef8451a37021 (commit)
via ab159f505de08729862904b1412d9dede8138013 (commit)
via de4ecfcd4827e8e0002c426e11e5ad36e7e14da3 (commit)
via 24503d327ec68c528cfc19e3228223718f1487c9 (commit)
via 462f0ff4fbef6bdf657f4833c2d8f0e2cce1cd41 (commit)
via c8870e86d867789bf2e8dedf6f5e960dc47faaee (commit)
via cd2d3c39ebcba3fb50822fba492c41c6a4bfce25 (commit)
via 09af4e2b9e9b2840dd475ef112d485e3476badd1 (commit)
via 9d00b71c14e4e1eb7e390c78b40e015f960595af (commit)
via 2b0ef32a8eb90122efa930c31147ca6e56df5716 (commit)
via 104a04b32d7705a95d5e9492dce82469aff21a0e (commit)
via ff2215ffb7e7149c50764841e00d8d9186a81294 (commit)
via bc2a0da61893dc52ab49851360c23c5fbe18dfe6 (commit)
via 6667c5c3485db2ec1da350d4b90896b871e07bad (commit)
via 488d42f3ae5c7f97ef144370036b5c9b7736a9d1 (commit)
via 4b678e1d42ea66fae49f2248b4c4cfeb32fe0a09 (commit)
via ce03b1032e086e7f2cb038068dfbbdb5eac61645 (commit)
via 50bea9582f85b0684aa17a7cea7fb9d2405896c0 (commit)
via 7725df2d751443bf37be18f1640c5c86a8a9df79 (commit)
via 39a8fecdf3bbeb905f6716c3b42ae250e9215542 (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 ba2982025bc36dbf61f1268a6c0c884b2a669127 (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 d6e34fc0d99e325ccd5f253abdbb1abd27b21935
Author: JINMEI Tatuya <jinmei at isc.org>
Date: Fri Feb 22 10:38:37 2013 -0800
[2689] a bit of cleanup: rename some internal methods and add comments.
"check" in __check_group_recvmsg was added for a historical reason and
is not really appropriate any more (it doesn't do any check internally)
commit 6ffab5a7aa42d2f1210d3036658dcf4398c6ff99
Author: JINMEI Tatuya <jinmei at isc.org>
Date: Fri Feb 22 10:22:23 2013 -0800
[2689] adjusted some tests to adapt to recent changes to config module.
mostly on the introduction of 'want_answer" and the rpc_call method.
should be essentially trivial, but still require some amount of change.
some tests still fail.
commit 3fa16c71cbffab13bcdeb311a1e81a29f107d647
Author: JINMEI Tatuya <jinmei at isc.org>
Date: Fri Feb 22 10:29:34 2013 -0800
[2689] corrected conflict resolution on merge.
I kept the wrong version of the code.
commit 808dcdccc72caa04645c15af4493a76bacbd838f
Merge: ba29820 4df19b6
Author: JINMEI Tatuya <jinmei at isc.org>
Date: Fri Feb 22 10:08:15 2013 -0800
[2689] Merge branch 'master' into trac2689
fixed Conflicts:
src/bin/stats/stats.py.in
(some tests current fail; will fix them)
-----------------------------------------------------------------------
Summary of changes:
ChangeLog | 8 +
README | 5 +-
configure.ac | 9 +-
doc/guide/bind10-guide.xml | 7 +
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/bin/auth/tests/testdata/Makefile.am | 1 -
src/bin/cmdctl/cmdctl.py.in | 7 +-
src/bin/ddns/ddns.py.in | 61 +-
src/bin/ddns/ddns_messages.mes | 44 +-
src/bin/ddns/tests/ddns_test.py | 5 +-
src/bin/loadzone/tests/correct/correct_test.sh.in | 3 -
src/bin/stats/stats.py.in | 104 +--
src/bin/stats/stats_httpd.py.in | 28 +-
src/bin/stats/tests/b10-stats_test.py | 44 +-
src/bin/stats/tests/test_utils.py | 19 +-
src/bin/xfrin/tests/xfrin_test.py | 2 +-
src/bin/xfrin/xfrin.py.in | 22 +-
src/bin/zonemgr/tests/zonemgr_test.py | 24 +-
src/bin/zonemgr/zonemgr.py.in | 19 +-
src/lib/asiodns/sync_udp_server.cc | 2 +-
src/lib/asiodns/sync_udp_server.h | 2 -
src/lib/asiolink/tests/tcp_socket_unittest.cc | 7 +-
src/lib/cache/local_zone_data.h | 9 +-
src/lib/cc/proto_defs.cc | 1 +
src/lib/dhcpsrv/dhcpsrv_messages.mes | 4 +-
src/lib/dhcpsrv/pool.cc | 5 +-
src/lib/python/isc/config/ccsession.py | 69 +-
src/lib/python/isc/config/tests/ccsession_test.py | 61 ++
.../isc/config/tests/unittest_fakesession.py | 10 +-
src/lib/python/isc/server_common/auth_command.py | 14 +-
.../server_common/tests/socket_requestor_test.cc | 139 ++--
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
src/lib/util/tests/fd_share_tests.cc | 78 ++-
src/lib/util/tests/fd_tests.cc | 34 +-
.../util/tests/interprocess_sync_file_unittest.cc | 145 ++--
src/lib/util/threads/tests/condvar_unittest.cc | 29 +-
src/lib/util/threads/tests/lock_unittest.cc | 56 +-
src/lib/util/threads/tests/thread_unittest.cc | 49 +-
src/lib/util/unittests/check_valgrind.h | 5 +
src/lib/util/unittests/fork.cc | 2 +
.../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 ++-
tests/tools/perfdhcp/test_control.cc | 23 +-
66 files changed, 3398 insertions(+), 2265 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/README b/README
index 618e89d..70c6bee 100644
--- a/README
+++ b/README
@@ -20,7 +20,10 @@ of concept recursive or forwarding DNS server, b10-resolver.)
BIND 10 also provides experimental DHCPv4 and DHCPv6 servers,
b10-dhcp4 and b10-dhcp6, a portable DHCP library, libdhcp++, and
-a DHCP benchmarking tool, perfdhcp.
+a DHCP benchmarking tool, perfdhcp. In this release of BIND 10,
+the DHCPv4 and DHCPv6 servers must be considered experimental.
+Limitations and known issues with this DHCP release can be found
+at http://bind10.isc.org/wiki/KeaKnownIssues
Documentation is included with the source. See doc/guide/bind10-guide.txt
(or bind10-guide.html) for installation instructions. The
diff --git a/configure.ac b/configure.ac
index 5195c24..f2bdf0b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2,7 +2,7 @@
# Process this file with autoconf to produce a configure script.
AC_PREREQ([2.59])
-AC_INIT(bind10, 20130213, bind10-dev at isc.org)
+AC_INIT(bind10, 20130221, bind10-dev at isc.org)
AC_CONFIG_SRCDIR(README)
# serial-tests is not available in automake version before 1.13. In
# automake 1.13 and higher, AM_PROG_INSTALL is undefined, so we'll check
@@ -161,8 +161,10 @@ if test $with_werror = 1; then
CXXFLAGS_SAVED="$CXXFLAGS"
CXXFLAGS="$CXXFLAGS $B10_CXXFLAGS -Werror"
AC_MSG_CHECKING(for in-TU anonymous namespace breakage)
- AC_TRY_COMPILE([namespace { class Foo {}; }
- namespace isc {class Bar {Foo foo_;};} ],,
+ # We use struct, not class, here, because some compilers complain about
+ # "unused private members", causing a false positive.
+ AC_TRY_COMPILE([namespace { struct Foo {}; }
+ namespace isc {struct Bar {Foo foo_;};} ],,
[AC_MSG_RESULT(no)
werror_ok=1
B10_CXXFLAGS="$B10_CXXFLAGS -Werror"],
@@ -1359,6 +1361,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/doc/guide/bind10-guide.xml b/doc/guide/bind10-guide.xml
index cea70c2..583ee60 100644
--- a/doc/guide/bind10-guide.xml
+++ b/doc/guide/bind10-guide.xml
@@ -3372,6 +3372,13 @@ then change those defaults with config set Resolver/forward_addresses[0]/address
while those details specific to DHCPv6 are described in <xref linkend="dhcp6"/>
</para>
+ <note>
+ <simpara>
+ In this release of BIND 10, the DHCPv4 and DHCPv6 servers
+ must be considered experimental.
+ </simpara>
+ </note>
+
<section id="dhcp-install-configure">
<title>DHCP Database Installation and Configuration</title>
<para>
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/bin/auth/tests/testdata/Makefile.am b/src/bin/auth/tests/testdata/Makefile.am
index fed498a..ebde800 100644
--- a/src/bin/auth/tests/testdata/Makefile.am
+++ b/src/bin/auth/tests/testdata/Makefile.am
@@ -23,7 +23,6 @@ EXTRA_DIST += simpleresponse_fromWire.spec
EXTRA_DIST += spec.spec
EXTRA_DIST += example.com
-EXTRA_DIST += example.zone
EXTRA_DIST += example.sqlite3
EXTRA_DIST += example-base-inc.zone example-nsec3-inc.zone
diff --git a/src/bin/cmdctl/cmdctl.py.in b/src/bin/cmdctl/cmdctl.py.in
index 15a41ec..457873b 100755
--- a/src/bin/cmdctl/cmdctl.py.in
+++ b/src/bin/cmdctl/cmdctl.py.in
@@ -429,8 +429,13 @@ class CommandControl():
# Process the command sent to cmdctl directly.
answer = self.command_handler(command_name, params)
else:
+ # FIXME: Due to the fact that we use a separate session
+ # from the module one (due to threads and blocking), and
+ # because the plain cc session does not have the high-level
+ # rpc-call method, we use the low-level way and create the
+ # command ourselves.
msg = ccsession.create_command(command_name, params)
- seq = self._cc.group_sendmsg(msg, module_name)
+ seq = self._cc.group_sendmsg(msg, module_name, want_answer=True)
logger.debug(DBG_CMDCTL_MESSAGING, CMDCTL_COMMAND_SENT,
command_name, module_name)
#TODO, it may be blocked, msqg need to add a new interface waiting in timeout.
diff --git a/src/bin/ddns/ddns.py.in b/src/bin/ddns/ddns.py.in
index d7fcab7..d382495 100755
--- a/src/bin/ddns/ddns.py.in
+++ b/src/bin/ddns/ddns.py.in
@@ -32,7 +32,8 @@ import isc.util.cio.socketsession
import isc.server_common.tsig_keyring
from isc.server_common.dns_tcp import DNSTCPContext
from isc.datasrc import DataSourceClient
-from isc.server_common.auth_command import auth_loadzone_command
+from isc.server_common.auth_command import AUTH_LOADZONE_COMMAND, \
+ auth_loadzone_params
import select
import time
import errno
@@ -544,42 +545,38 @@ class DDNSServer:
def __notify_start_forwarder(self):
'''Notify auth that DDNS Update messages can now be forwarded'''
try:
- seq = self._cc._session.group_sendmsg(create_command(
- "start_ddns_forwarder"), AUTH_MODULE_NAME)
- answer, _ = self._cc._session.group_recvmsg(False, seq)
- rcode, error_msg = parse_answer(answer)
- if rcode != 0:
- logger.error(DDNS_START_FORWARDER_ERROR, error_msg)
- except (SessionTimeout, SessionError, ProtocolError) as ex:
+ self._cc.rpc_call("start_ddns_forwarder", AUTH_MODULE_NAME)
+ except (SessionTimeout, SessionError, ProtocolError,
+ RPCRecipientMissing) as ex:
logger.error(DDNS_START_FORWARDER_FAIL, ex)
+ except RPCError as e:
+ logger.error(DDNS_START_FORWARDER_ERROR, e)
def __notify_stop_forwarder(self):
'''Notify auth that DDNS Update messages should no longer be forwarded.
'''
try:
- seq = self._cc._session.group_sendmsg(create_command(
- "stop_ddns_forwarder"), AUTH_MODULE_NAME)
- answer, _ = self._cc._session.group_recvmsg(False, seq)
- rcode, error_msg = parse_answer(answer)
- if rcode != 0:
- logger.error(DDNS_STOP_FORWARDER_ERROR, error_msg)
- except (SessionTimeout, SessionError, ProtocolError) as ex:
+ self._cc.rpc_call("stop_ddns_forwarder", AUTH_MODULE_NAME)
+ except (SessionTimeout, SessionError, ProtocolError,
+ RPCRecipientMissing) as ex:
logger.error(DDNS_STOP_FORWARDER_FAIL, ex)
+ except RPCError as e:
+ logger.error(DDNS_STOP_FORWARDER_ERROR, e)
def __notify_auth(self, zname, zclass):
'''Notify auth of the update, if necessary.'''
- msg = auth_loadzone_command(self._cc, zname, zclass)
- if msg is not None:
- self.__notify_update(AUTH_MODULE_NAME, msg, zname, zclass)
+ self.__notify_update(AUTH_MODULE_NAME, AUTH_LOADZONE_COMMAND,
+ auth_loadzone_params(zname, zclass), zname,
+ zclass)
def __notify_xfrout(self, zname, zclass):
'''Notify xfrout of the update.'''
param = {'zone_name': zname.to_text(), 'zone_class': zclass.to_text()}
- msg = create_command('notify', param)
- self.__notify_update(XFROUT_MODULE_NAME, msg, zname, zclass)
+ self.__notify_update(XFROUT_MODULE_NAME, 'notify', param, zname,
+ zclass)
- def __notify_update(self, modname, msg, zname, zclass):
+ def __notify_update(self, modname, command, params, zname, zclass):
'''Notify other module of the update.
Note that we use blocking communication here. While the internal
@@ -590,27 +587,17 @@ class DDNSServer:
For a longer term we'll need to switch to asynchronous communication,
but for now we rely on the blocking operation.
- Note also that we directly refer to the "protected" member of
- ccsession (_cc._session) rather than creating a separate channel.
- It's probably not the best practice, but hopefully we can introduce
- a cleaner way when we support asynchronous communication.
- At the moment we prefer the brevity with the use of internal channel
- of the cc session.
-
'''
try:
- seq = self._cc._session.group_sendmsg(msg, modname)
- answer, _ = self._cc._session.group_recvmsg(False, seq)
- rcode, error_msg = parse_answer(answer)
- except (SessionTimeout, SessionError, ProtocolError) as ex:
- rcode = 1
- error_msg = str(ex)
- if rcode == 0:
+ # FIXME? Is really rpc_call the correct one? What if there are more
+ # than one recipient of the given kind? What if none? We need to
+ # think of some kind of notification/broadcast mechanism.
+ self._cc.rpc_call(command, modname, params=params)
logger.debug(TRACE_BASIC, DDNS_UPDATE_NOTIFY, modname,
ZoneFormatter(zname, zclass))
- else:
+ except (SessionTimeout, SessionError, ProtocolError, RPCError) as ex:
logger.error(DDNS_UPDATE_NOTIFY_FAIL, modname,
- ZoneFormatter(zname, zclass), error_msg)
+ ZoneFormatter(zname, zclass), ex)
def handle_session(self, fileno):
"""Handle incoming session on the socket with given fileno.
diff --git a/src/bin/ddns/ddns_messages.mes b/src/bin/ddns/ddns_messages.mes
index cdc7b4d..7d440d9 100644
--- a/src/bin/ddns/ddns_messages.mes
+++ b/src/bin/ddns/ddns_messages.mes
@@ -69,7 +69,7 @@ it's just a timing issue. The number of total failed attempts is also
logged. If it reaches an internal threshold b10-ddns considers it a
fatal error and terminates. Even in that case, if b10-ddns is
configured as a "dispensable" component (which is the default), the
-parent bind10 process will restart it, and there will be another
+parent ("init") process will restart it, and there will be another
chance of getting the remote configuration successfully. These are
not the optimal behavior, but it's believed to be sufficient in
practice (there would normally be no failure in the first place). If
@@ -253,29 +253,19 @@ notify messages to secondary servers.
b10-ddns has made updates to a zone based on an update request and
tried to notify an external component of the updates, but the
notification fails. One possible cause of this is that the external
-component is not really running and it times out in waiting for the
-response, although it will be less likely to happen in practice
-because these components will normally be configured to run when the
-server provides the authoritative DNS service; ddns is rather optional
-among them. If this happens, however, it will suspend b10-ddns for a
-few seconds during which it cannot handle new requests (some may be
-delayed, some may be dropped, depending on the volume of the incoming
-requests). This is obviously bad, and if this error happens due to
-this reason, the administrator should make sure the component in
-question should be configured to run. For a longer term, b10-ddns
-should be more robust about this case such as by making this
-notification asynchronously and/or detecting the existence of the
-external components to avoid hopeless notification in the first place.
-Severity of this error for the receiving components depends on the
-type of the component. If it's b10-xfrout, this means DNS notify
-messages won't be sent to secondary servers of the zone. It's
-suboptimal, but not necessarily critical as the secondary servers will
-try to check the zone's status periodically. If it's b10-auth and the
-notification was needed to have it reload the corresponding zone, it's
-more serious because b10-auth won't be able to serve the new version
-of the zone unless some explicit recovery action is taken. So the
-administrator needs to examine this message and takes an appropriate
-action. In either case, this notification is generally expected to
-succeed; so the fact it fails itself means there's something wrong in
-the BIND 10 system, and it would be advisable to check other log
-messages.
+component is not really running, although it will be less likely to
+happen in practice because these components will normally be
+configured to run when the server provides the authoritative DNS
+service; ddns is rather optional among them. Severity of this error
+for the receiving components depends on the type of the component. If
+it's b10-xfrout, this means DNS notify messages won't be sent to
+secondary servers of the zone. It's suboptimal, but not necessarily
+critical as the secondary servers will try to check the zone's status
+periodically. If it's b10-auth and the notification was needed to
+have it reload the corresponding zone, it's more serious because
+b10-auth won't be able to serve the new version of the zone unless
+some explicit recovery action is taken. So the administrator needs to
+examine this message and takes an appropriate action. In either case,
+this notification is generally expected to succeed; so the fact it
+fails itself means there's something wrong in the BIND 10 system, and
+it would be advisable to check other log messages.
diff --git a/src/bin/ddns/tests/ddns_test.py b/src/bin/ddns/tests/ddns_test.py
index d366f09..e7d2099 100755
--- a/src/bin/ddns/tests/ddns_test.py
+++ b/src/bin/ddns/tests/ddns_test.py
@@ -191,7 +191,7 @@ class FakeKeyringModule:
'''Simply return the predefined TSIG keyring unconditionally.'''
return TEST_TSIG_KEYRING
-class MyCCSession(isc.config.ConfigData):
+class MyCCSession(isc.config.ModuleCCSession):
'''Fake session with minimal interface compliance.'''
# faked CC sequence used in group_send/recvmsg
@@ -276,7 +276,8 @@ class MyCCSession(isc.config.ConfigData):
'secondary_zones')
return seczone_default, True
- def group_sendmsg(self, msg, group):
+ def group_sendmsg(self, msg, group, instance='*', to='*',
+ want_answer=False):
# remember the passed parameter, and return dummy sequence
self._sent_msg.append((msg, group))
if self._sendmsg_exception is not None:
diff --git a/src/bin/loadzone/tests/correct/correct_test.sh.in b/src/bin/loadzone/tests/correct/correct_test.sh.in
index 9b90d13..505411c 100755
--- a/src/bin/loadzone/tests/correct/correct_test.sh.in
+++ b/src/bin/loadzone/tests/correct/correct_test.sh.in
@@ -18,9 +18,6 @@
PYTHON_EXEC=${PYTHON_EXEC:- at PYTHON@}
export PYTHON_EXEC
-PYTHONPATH=@abs_top_builddir@/src/lib/python/isc/log_messages:@abs_top_srcdir@/src/lib/python:@abs_top_builddir@/src/lib/python:$PYTHONPATH
-export PYTHONPATH
-
LOADZONE_PATH=@abs_top_builddir@/src/bin/loadzone
TEST_FILE_PATH=@abs_top_srcdir@/src/bin/loadzone/tests/correct
TEST_OUTPUT_PATH=@abs_top_builddir@/src/bin/loadzone//tests/correct
diff --git a/src/bin/stats/stats.py.in b/src/bin/stats/stats.py.in
index cfd7ad8..577afe6 100755
--- a/src/bin/stats/stats.py.in
+++ b/src/bin/stats/stats.py.in
@@ -267,40 +267,45 @@ class Stats:
# It counts the number of instances of same module by
# examining the third value from the array result of
# 'show_processes' of Init
- seq = self.cc_session.group_sendmsg(
- isc.config.ccsession.create_command("show_processes"), 'Init')
- (answer, env) = self.cc_session.group_recvmsg(False, seq)
+ try:
+ value = self.mccs.rpc_call('show_processes', 'Init')
+ except isc.config.RPCRecipientMissing:
+ # This has been SessionTimeout before, so we keep the original
+ # behavior.
+ raise
+ except isc.config.RPCError:
+ # TODO: Is it OK to just pass? As part of refactoring, preserving
+ # the original behaviour.
+ value = None
modules = []
- if answer:
- (rcode, value) = isc.config.ccsession.parse_answer(answer)
- if rcode == 0 and type(value) is list:
- # NOTE: For example, the "show_processes" command
- # of Init is assumed to return the response in this
- # format:
- # [
- # ...
- # [
- # 20061,
- # "b10-auth",
- # "Auth"
- # ],
- # [
- # 20103,
- # "b10-auth-2",
- # "Auth"
- # ]
- # ...
- # ]
- # If multiple instances of the same module are
- # running, the address names of them, which are at the
- # third element, must be also same. Thus, the value of
- # the third element of each outer element is read here
- # for counting multiple instances. This is a
- # workaround for counting the instances. This should
- # be fixed in another proper way in the future
- # release.
- modules = [ v[2] if type(v) is list and len(v) > 2 \
- else None for v in value ]
+ if type(value) is list:
+ # NOTE: For example, the "show_processes" command
+ # of Init is assumed to return the response in this
+ # format:
+ # [
+ # ...
+ # [
+ # 20061,
+ # "b10-auth",
+ # "Auth"
+ # ],
+ # [
+ # 20103,
+ # "b10-auth-2",
+ # "Auth"
+ # ]
+ # ...
+ # ]
+ # If multiple instances of the same module are
+ # running, the address names of them, which are at the
+ # third element, must be also same. Thus, the value of
+ # the third element of each outer element is read here
+ # for counting multiple instances. This is a
+ # workaround for counting the instances. This should
+ # be fixed in another proper way in the future
+ # release.
+ modules = [ v[2] if type(v) is list and len(v) > 2 \
+ else None for v in value ]
# start requesting each module to collect statistics data
sequences = []
for (module_name, data) in self.get_statistics_data().items():
@@ -311,7 +316,12 @@ class Stats:
module_name)
cmd = isc.config.ccsession.create_command(
"getstats", None) # no argument
- seq = self.cc_session.group_sendmsg(cmd, module_name)
+ # Not using rpc_call here. We first send a bunch of commands, then
+ # collect all the answers. This eliminates some of the round-trip
+ # times. Unfortunately, rpc_call is not flexible enough to allow
+ # this, though the future rpc_call_async could.
+ seq = self.cc_session.group_sendmsg(cmd, module_name,
+ want_answer=True)
sequences.append((module_name, seq))
cnt = modules.count(module_name)
if cnt > 1:
@@ -438,21 +448,17 @@ class Stats:
raises StatsError.
"""
modules = {}
- seq = self.cc_session.group_sendmsg(
- isc.config.ccsession.create_command(
- isc.config.ccsession.COMMAND_GET_STATISTICS_SPEC),
- 'ConfigManager')
- (answer, env) = self.cc_session.group_recvmsg(False, seq)
- if answer:
- (rcode, value) = isc.config.ccsession.parse_answer(answer)
- if rcode == 0:
- for mod in value:
- spec = { "module_name" : mod }
- if value[mod] and type(value[mod]) is list:
- spec["statistics"] = value[mod]
- modules[mod] = isc.config.module_spec.ModuleSpec(spec)
- else:
- raise StatsError("Updating module spec fails: " + str(value))
+ try:
+ value = self.mccs.rpc_call(isc.config.ccsession. \
+ COMMAND_GET_STATISTICS_SPEC,
+ 'ConfigManager')
+ except isc.config.RPCError as e:
+ raise StatsError("Updating module spec fails: " + str(e))
+ for mod in value:
+ spec = { "module_name" : mod }
+ if value[mod] and type(value[mod]) is list:
+ spec["statistics"] = value[mod]
+ modules[mod] = isc.config.module_spec.ModuleSpec(spec)
modules[self.module_name] = self.mccs.get_module_spec()
self.modules = modules
diff --git a/src/bin/stats/stats_httpd.py.in b/src/bin/stats/stats_httpd.py.in
index 367f56e..fd9ac93 100755
--- a/src/bin/stats/stats_httpd.py.in
+++ b/src/bin/stats/stats_httpd.py.in
@@ -459,20 +459,14 @@ class StatsHttpd:
if name is not None:
param['name'] = name
try:
- seq = self.cc_session.group_sendmsg(
- isc.config.ccsession.create_command('show', param), 'Stats')
- (answer, env) = self.cc_session.group_recvmsg(False, seq)
- if answer:
- (rcode, value) = isc.config.ccsession.parse_answer(answer)
+ return self.mccs.rpc_call('show', 'Stats', params=param)
except (isc.cc.session.SessionTimeout,
- isc.cc.session.SessionError) as err:
+ isc.cc.session.SessionError,
+ isc.config.RPCRecipientMissing) as err:
raise StatsHttpdError("%s: %s" %
(err.__class__.__name__, err))
- else:
- if rcode == 0:
- return value
- else:
- raise StatsHttpdDataError("Stats module: %s" % str(value))
+ except isc.config.RPCError as e:
+ raise StatsHttpdDataError("Stats module: %s" % str(e))
def get_stats_spec(self, owner=None, name=None):
"""Requests statistics data to the Stats daemon and returns
@@ -493,15 +487,9 @@ class StatsHttpd:
if name is not None:
param['name'] = name
try:
- seq = self.cc_session.group_sendmsg(
- isc.config.ccsession.create_command('showschema', param), 'Stats')
- (answer, env) = self.cc_session.group_recvmsg(False, seq)
- if answer:
- (rcode, value) = isc.config.ccsession.parse_answer(answer)
- if rcode == 0:
- return value
- else:
- raise StatsHttpdDataError("Stats module: %s" % str(value))
+ return self.mccs.rpc_call('showschema', 'Stats', params=param)
+ except isc.config.RPCError as e:
+ raise StatsHttpdDataError("Stats module: %s" % str(e))
except (isc.cc.session.SessionTimeout,
isc.cc.session.SessionError) as err:
raise StatsHttpdError("%s: %s" %
diff --git a/src/bin/stats/tests/b10-stats_test.py b/src/bin/stats/tests/b10-stats_test.py
index 56678d7..7732902 100644
--- a/src/bin/stats/tests/b10-stats_test.py
+++ b/src/bin/stats/tests/b10-stats_test.py
@@ -417,33 +417,24 @@ class TestStats(unittest.TestCase):
"""
- def __check_group_sendmsg(command, destination):
- self.assertEqual('ConfigManager', destination)
- cmd, value = isc.config.ccsession.parse_command(command)
- self.assertEqual(cmd,
+ def __check_rpc_call(command, group):
+ self.assertEqual('ConfigManager', group)
+ self.assertEqual(command,
isc.config.ccsession.COMMAND_GET_STATISTICS_SPEC)
- self.assertEqual(None, value)
- return 42 # faked seq number
-
- def __check_group_recvmsg(nonblocking, seq):
- self.assertFalse(nonblocking)
- self.assertEqual(42, seq) # should be the one returned above
- answer = isc.config.ccsession.create_answer(
- 0, {'Init': [{
- "item_name": "boot_time",
- "item_type": "string",
- "item_optional": False,
- # Use a different default so we can check it below
- "item_default": "2013-01-01T00:00:01Z",
- "item_title": "Boot time",
- "item_description": "dummy desc",
- "item_format": "date-time"
- }]})
- return answer, None
+ answer_value = {'Init': [{
+ "item_name": "boot_time",
+ "item_type": "string",
+ "item_optional": False,
+ # Use a different default so we can check it below
+ "item_default": "2013-01-01T00:00:01Z",
+ "item_title": "Boot time",
+ "item_description": "dummy desc",
+ "item_format": "date-time"
+ }]}
+ return answer_value
self.stats = SimpleStats()
- self.stats.cc_session.group_sendmsg = __check_group_sendmsg
- self.stats.cc_session.group_recvmsg = __check_group_recvmsg
+ self.stats.cc_session.rpc_call = __check_rpc_call
self.stats.update_modules()
@@ -475,10 +466,11 @@ class TestStats(unittest.TestCase):
"2013-01-01T00:00:01Z")
# Error case
+ def __raise_on_rpc_call(x, y):
+ raise isc.config.RPCError(99, 'error')
orig_parse_answer = stats.isc.config.ccsession.parse_answer
- stats.isc.config.ccsession.parse_answer = lambda x: (99, 'error')
+ self.stats.cc_session.rpc_call = __raise_on_rpc_call
self.assertRaises(stats.StatsError, self.stats.update_modules)
- stats.isc.config.ccsession.parse_answer = orig_parse_answer
def test_get_statistics_data(self):
"""Confirm the behavior of Stats.get_statistics_data().
diff --git a/src/bin/stats/tests/test_utils.py b/src/bin/stats/tests/test_utils.py
index 5794f7d..bfabc13 100644
--- a/src/bin/stats/tests/test_utils.py
+++ b/src/bin/stats/tests/test_utils.py
@@ -522,8 +522,9 @@ class SimpleStats(stats.Stats):
# _init_statistics_data. This will get the Stats module info from
# the file directly and some amount information about the Init and
# Auth modules (hardcoded below).
- self.cc_session.group_sendmsg = self.__check_group_sendmsg
- self.cc_session.group_recvmsg = self.__check_group_recvmsg
+ self.cc_session.group_sendmsg = self.__group_sendmsg
+ self.cc_session.group_recvmsg = self.__group_recvmsg
+ self.cc_session.rpc_call = self.__rpc_call
stats.Stats._init_statistics_data(self)
def __init_auth_stat(self):
@@ -555,7 +556,7 @@ class SimpleStats(stats.Stats):
# initialization until we are ready.
pass
- def __check_group_sendmsg(self, command, destination):
+ def __group_sendmsg(self, command, destination, want_answer=False):
"""Faked ModuleCCSession.group_sendmsg for tests.
Skipping actual network communication, and just returning an internally
@@ -565,7 +566,7 @@ class SimpleStats(stats.Stats):
self.__seq += 1
return self.__seq
- def __check_group_recvmsg(self, nonblocking, seq):
+ def __group_recvmsg(self, nonblocking, seq):
"""Faked ModuleCCSession.group_recvmsg for tests.
Skipping actual network communication, and returning an internally
@@ -578,6 +579,16 @@ class SimpleStats(stats.Stats):
return self.__default_answer, {'from': 'no-matter'}
return self._answers.pop(0)
+ def __rpc_call(self, command, group):
+ """Faked ModuleCCSession.rpc_call for tests.
+
+ At the moment we don't have to cover failure cases, so this is a
+ simple wrapper for the faked group_recvmsg().
+
+ """
+ answer, _ = self.__group_recvmsg(None, None)
+ return isc.config.ccsession.parse_answer(answer)[1]
+
class MyStats(stats.Stats):
stats._BASETIME = CONST_BASETIME
diff --git a/src/bin/xfrin/tests/xfrin_test.py b/src/bin/xfrin/tests/xfrin_test.py
index a1714de..272124b 100644
--- a/src/bin/xfrin/tests/xfrin_test.py
+++ b/src/bin/xfrin/tests/xfrin_test.py
@@ -2909,7 +2909,7 @@ class TestXfrinProcessMockCCSession:
self.recv_called = False
self.recv_called_correctly = False
- def group_sendmsg(self, msg, module):
+ def group_sendmsg(self, msg, module, want_answer=False):
self.send_called = True
if module == 'Auth' and msg['command'][0] == 'loadzone':
self.send_called_correctly = True
diff --git a/src/bin/xfrin/xfrin.py.in b/src/bin/xfrin/xfrin.py.in
index 55d9818..011d995 100755
--- a/src/bin/xfrin/xfrin.py.in
+++ b/src/bin/xfrin/xfrin.py.in
@@ -982,7 +982,6 @@ class XfrinConnection(asyncore.dispatcher):
format_addrinfo(self._master_addrinfo))
ret = XFRIN_FAIL
except XfrinProtocolError as e:
- # FIXME: Why is this .info? Even the messageID contains "ERROR".
logger.info(XFRIN_XFR_TRANSFER_PROTOCOL_VIOLATION, req_str,
self.zone_str(),
format_addrinfo(self._master_addrinfo), str(e))
@@ -1324,7 +1323,8 @@ def _do_auth_loadzone(server, zone_name, zone_class):
param = msg['command'][1]
logger.debug(DBG_XFRIN_TRACE, XFRIN_AUTH_LOADZONE, param["origin"],
param["class"])
- seq = server._send_cc_session.group_sendmsg(msg, AUTH_MODULE_NAME)
+ seq = server._send_cc_session.group_sendmsg(msg, AUTH_MODULE_NAME,
+ want_answer=True)
answer, env = server._send_cc_session.group_recvmsg(False, seq)
class Xfrin:
@@ -1630,18 +1630,29 @@ class Xfrin:
param = {'zone_name': zone_name.to_text(),
'zone_class': zone_class.to_text()}
if xfr_result == XFRIN_OK:
+ # FIXME: Due to the hack with two different CC sessions
+ # (see the _cc_setup comment) and the fact the rpc_call
+ # is a high-level call present only at ModuleCCSession,
+ # we are forced to use the primitive way of manually
+ # calling group_sendmsg and the group_recvmsg. Also, why
+ # do we do group_recvmsg when we don't need the answer?
+ # And why is this direct RPC call if a notification would
+ # be more appropriate?
_do_auth_loadzone(self, zone_name, zone_class)
msg = create_command(notify_out.ZONE_NEW_DATA_READY_CMD, param)
# catch the exception, in case msgq has been killed.
try:
seq = self._send_cc_session.group_sendmsg(msg,
- XFROUT_MODULE_NAME)
+ XFROUT_MODULE_NAME,
+ want_answer=True)
try:
answer, env = self._send_cc_session.group_recvmsg(False,
seq)
except isc.cc.session.SessionTimeout:
pass # for now we just ignore the failure
- seq = self._send_cc_session.group_sendmsg(msg, ZONE_MANAGER_MODULE_NAME)
+ seq = self._send_cc_session.group_sendmsg(msg,
+ ZONE_MANAGER_MODULE_NAME,
+ want_answer=True)
try:
answer, env = self._send_cc_session.group_recvmsg(False,
seq)
@@ -1654,7 +1665,8 @@ class Xfrin:
msg = create_command(notify_out.ZONE_XFRIN_FAILED, param)
# catch the exception, in case msgq has been killed.
try:
- seq = self._send_cc_session.group_sendmsg(msg, ZONE_MANAGER_MODULE_NAME)
+ seq = self._send_cc_session.group_sendmsg(msg, ZONE_MANAGER_MODULE_NAME,
+ want_answer=True)
try:
answer, env = self._send_cc_session.group_recvmsg(False,
seq)
diff --git a/src/bin/zonemgr/tests/zonemgr_test.py b/src/bin/zonemgr/tests/zonemgr_test.py
index 42ed679..81c5392 100644
--- a/src/bin/zonemgr/tests/zonemgr_test.py
+++ b/src/bin/zonemgr/tests/zonemgr_test.py
@@ -41,23 +41,16 @@ TEST_SQLITE3_DBFILE = os.getenv("TESTDATAOBJDIR") + '/initdb.file'
class ZonemgrTestException(Exception):
pass
-class MySession():
- def __init__(self):
- pass
-
- def group_sendmsg(self, msg, module_name):
- if module_name not in ("Auth", "Xfrin"):
- raise ZonemgrTestException("module name not exist")
-
- def group_recvmsg(self, nonblock, seq):
- return None, None
-
class FakeCCSession(isc.config.ConfigData, MockModuleCCSession):
def __init__(self):
module_spec = isc.config.module_spec_from_file(SPECFILE_LOCATION)
ConfigData.__init__(self, module_spec)
MockModuleCCSession.__init__(self)
+ def rpc_call(self, command, module, instance="*", to="*", params=None):
+ if module not in ("Auth", "Xfrin"):
+ raise ZonemgrTestException("module name not exist")
+
def get_remote_config_value(self, module_name, identifier):
if module_name == "Auth" and identifier == "database_file":
return TEST_SQLITE3_DBFILE, False
@@ -84,8 +77,8 @@ class MyZonemgrRefresh(ZonemgrRefresh):
return None
sqlite3_ds.get_zone_soa = get_zone_soa
- ZonemgrRefresh.__init__(self, MySession(), TEST_SQLITE3_DBFILE,
- self._slave_socket, FakeCCSession())
+ ZonemgrRefresh.__init__(self, TEST_SQLITE3_DBFILE, self._slave_socket,
+ FakeCCSession())
current_time = time.time()
self._zonemgr_refresh_info = {
('example.net.', 'IN'): {
@@ -619,7 +612,6 @@ class MyZonemgr(Zonemgr):
self._db_file = TEST_SQLITE3_DBFILE
self._zone_refresh = None
self._shutdown_event = threading.Event()
- self._cc = MySession()
self._module_cc = FakeCCSession()
self._config_data = {
"lowerbound_refresh" : 10,
@@ -664,8 +656,8 @@ class TestZonemgr(unittest.TestCase):
self.zonemgr.config_handler(config_data3)
self.assertEqual(0.5, self.zonemgr._config_data.get("refresh_jitter"))
# The zone doesn't exist in database, simply skip loading soa for it and log an warning
- self.zonemgr._zone_refresh = ZonemgrRefresh(None, TEST_SQLITE3_DBFILE,
- None, FakeCCSession())
+ self.zonemgr._zone_refresh = ZonemgrRefresh(TEST_SQLITE3_DBFILE, None,
+ FakeCCSession())
config_data1["secondary_zones"] = [{"name": "nonexistent.example",
"class": "IN"}]
self.assertEqual(self.zonemgr.config_handler(config_data1),
diff --git a/src/bin/zonemgr/zonemgr.py.in b/src/bin/zonemgr/zonemgr.py.in
index 40bfa39..59900c4 100755
--- a/src/bin/zonemgr/zonemgr.py.in
+++ b/src/bin/zonemgr/zonemgr.py.in
@@ -103,8 +103,8 @@ class ZonemgrRefresh:
can be stopped by calling shutdown() in another thread.
"""
- def __init__(self, cc, db_file, slave_socket, module_cc_session):
- self._cc = cc
+ def __init__(self, db_file, slave_socket, module_cc_session):
+ self._mccs = module_cc_session
self._check_sock = slave_socket
self._db_file = db_file
self._zonemgr_refresh_info = {}
@@ -277,15 +277,15 @@ class ZonemgrRefresh:
def _send_command(self, module_name, command_name, params):
"""Send command between modules."""
- msg = create_command(command_name, params)
try:
- seq = self._cc.group_sendmsg(msg, module_name)
- try:
- answer, env = self._cc.group_recvmsg(False, seq)
- except isc.cc.session.SessionTimeout:
- pass # for now we just ignore the failure
+ self._mccs.rpc_call(command_name, module_name, params=params)
except socket.error:
+ # FIXME: WTF? Where does socket.error come from? And how do we ever
+ # dare ignore such serious error? It can only be broken link to
+ # msgq, we need to terminate then.
logger.error(ZONEMGR_SEND_FAIL, module_name)
+ except (isc.cc.session.SessionTimeout, isc.config.RPCError):
+ pass # for now we just ignore the failure
def _find_need_do_refresh_zone(self):
"""Find the first zone need do refresh, if no zone need
@@ -525,7 +525,7 @@ class Zonemgr:
self._db_file = self.get_db_file()
# Create socket pair for communicating between main thread and zonemgr timer thread
self._master_socket, self._slave_socket = socket.socketpair(socket.AF_UNIX, socket.SOCK_STREAM)
- self._zone_refresh = ZonemgrRefresh(self._cc, self._db_file, self._slave_socket, self._module_cc)
+ self._zone_refresh = ZonemgrRefresh(self._db_file, self._slave_socket, self._module_cc)
self._zone_refresh.run_timer()
self._lock = threading.Lock()
@@ -536,7 +536,6 @@ class Zonemgr:
"""Setup two sessions for zonemgr, one(self._module_cc) is used for receiving
commands and config data sent from other modules, another one (self._cc)
is used to send commands to proper modules."""
- self._cc = isc.cc.Session()
self._module_cc = isc.config.ModuleCCSession(SPECFILE_LOCATION,
self.config_handler,
self.command_handler)
diff --git a/src/lib/asiodns/sync_udp_server.cc b/src/lib/asiodns/sync_udp_server.cc
index 95e1c72..c3f5348 100644
--- a/src/lib/asiodns/sync_udp_server.cc
+++ b/src/lib/asiodns/sync_udp_server.cc
@@ -44,7 +44,7 @@ SyncUDPServer::SyncUDPServer(asio::io_service& io_service, const int fd,
output_buffer_(new isc::util::OutputBuffer(0)),
query_(new isc::dns::Message(isc::dns::Message::PARSE)),
answer_(new isc::dns::Message(isc::dns::Message::RENDER)),
- io_(io_service), checkin_callback_(checkin), lookup_callback_(lookup),
+ checkin_callback_(checkin), lookup_callback_(lookup),
answer_callback_(answer), stopped_(false)
{
if (af != AF_INET && af != AF_INET6) {
diff --git a/src/lib/asiodns/sync_udp_server.h b/src/lib/asiodns/sync_udp_server.h
index ddac1f9..14ec42a 100644
--- a/src/lib/asiodns/sync_udp_server.h
+++ b/src/lib/asiodns/sync_udp_server.h
@@ -118,8 +118,6 @@ private:
isc::dns::MessagePtr query_, answer_;
// The socket used for the communication
std::auto_ptr<asio::ip::udp::socket> socket_;
- // The event loop we use
- asio::io_service& io_;
// Place the socket puts the sender of a packet when it is received
asio::ip::udp::endpoint sender_;
// Callbacks
diff --git a/src/lib/asiolink/tests/tcp_socket_unittest.cc b/src/lib/asiolink/tests/tcp_socket_unittest.cc
index 538cf48..20b6cd8 100644
--- a/src/lib/asiolink/tests/tcp_socket_unittest.cc
+++ b/src/lib/asiolink/tests/tcp_socket_unittest.cc
@@ -82,7 +82,7 @@ public:
struct PrivateData {
PrivateData() :
error_code_(), length_(0), cumulative_(0), expected_(0), offset_(0),
- name_(""), queued_(NONE), called_(NONE)
+ name_(""), queued_(NONE), called_(NONE), data_(MIN_SIZE, 0)
{}
asio::error_code error_code_; ///< Completion error code
@@ -93,8 +93,7 @@ public:
std::string name_; ///< Which of the objects this is
Operation queued_; ///< Queued operation
Operation called_; ///< Which callback called
- uint8_t data_[MIN_SIZE]; ///< Receive buffer
-
+ std::vector<uint8_t> data_; ///< Receive buffer
};
/// \brief Constructor
@@ -169,7 +168,7 @@ public:
/// \brief Get data member
uint8_t* data() {
- return (ptr_->data_);
+ return (&ptr_->data_[0]);
}
/// \brief Get flag to say what was queued
diff --git a/src/lib/cache/local_zone_data.h b/src/lib/cache/local_zone_data.h
index 4bfdb94..fd76a1b 100644
--- a/src/lib/cache/local_zone_data.h
+++ b/src/lib/cache/local_zone_data.h
@@ -29,8 +29,12 @@ namespace cache {
/// in the zone.
class LocalZoneData {
public:
- LocalZoneData(uint16_t rrset_class) : class_(rrset_class)
- {}
+ /// \brief Constructor.
+ ///
+ /// The passed parameter is expected to be an RR class value, but is not
+ /// currently unused. And this library will be quite likely to
+ /// deprecated anyway, so we don't touch it heavily.
+ LocalZoneData(uint16_t) {}
/// \brief Look up one rrset.
///
@@ -51,7 +55,6 @@ public:
private:
std::map<std::string, isc::dns::RRsetPtr> rrsets_map_; // RRsets of the zone
- uint16_t class_; // The class of the zone
};
typedef boost::shared_ptr<LocalZoneData> LocalZoneDataPtr;
diff --git a/src/lib/cc/proto_defs.cc b/src/lib/cc/proto_defs.cc
index 24d9650..5eb8575 100644
--- a/src/lib/cc/proto_defs.cc
+++ b/src/lib/cc/proto_defs.cc
@@ -38,6 +38,7 @@ const char* const CC_COMMAND_SEND = "send";
const char* const CC_TO_WILDCARD = "*";
const char* const CC_INSTANCE_WILDCARD = "*";
// Reply codes
+const int CC_REPLY_SUCCESS = 0;
const int CC_REPLY_NO_RECPT = -1;
}
diff --git a/src/lib/dhcpsrv/dhcpsrv_messages.mes b/src/lib/dhcpsrv/dhcpsrv_messages.mes
index 2ac0333..21a7c79 100644
--- a/src/lib/dhcpsrv/dhcpsrv_messages.mes
+++ b/src/lib/dhcpsrv/dhcpsrv_messages.mes
@@ -128,7 +128,7 @@ with the specified address to the memory file backend database.
A debug message issued when the server is about to add an IPv6 lease
with the specified address to the memory file backend database.
-% DHCPSRV_MEMFILE_COMMIT commiting to memory file database
+% DHCPSRV_MEMFILE_COMMIT committing to memory file database
The code has issued a commit call. For the memory file database, this is
a no-op.
@@ -212,7 +212,7 @@ with the specified address to the MySQL backend database.
A debug message issued when the server is about to add an IPv6 lease
with the specified address to the MySQL backend database.
-% DHCPSRV_MYSQL_COMMIT commiting to MySQl database
+% DHCPSRV_MYSQL_COMMIT committing to MySQL database
The code has issued a commit call. All outstanding transactions will be
committed to the database. Note that depending on the MySQL settings,
the commital may not include a write to disk.
diff --git a/src/lib/dhcpsrv/pool.cc b/src/lib/dhcpsrv/pool.cc
index 3548762..7b8a4ea 100644
--- a/src/lib/dhcpsrv/pool.cc
+++ b/src/lib/dhcpsrv/pool.cc
@@ -102,8 +102,9 @@ Pool6::Pool6(Pool6Type type, const isc::asiolink::IOAddress& prefix,
isc_throw(BadValue, "Invalid Pool6 address boundaries: not IPv6");
}
- // check if the prefix length is sane
- if (prefix_len == 0 || prefix_len > 128) {
+ // check if the prefix length is sane (we use the member variable only
+ // for silencing some compilers; see #2705 and #2789).
+ if (prefix_len_ == 0 || prefix_len_ > 128) {
isc_throw(BadValue, "Invalid prefix length");
}
diff --git a/src/lib/python/isc/config/ccsession.py b/src/lib/python/isc/config/ccsession.py
index 8464a01..a5858a7 100644
--- a/src/lib/python/isc/config/ccsession.py
+++ b/src/lib/python/isc/config/ccsession.py
@@ -37,6 +37,7 @@
"""
from isc.cc import Session
+from isc.cc.proto_defs import *
from isc.config.config_data import ConfigData, MultiConfigData, BIND10_CONFIG_DATA_VERSION
import isc.config.module_spec
import isc
@@ -50,6 +51,31 @@ logger = isc.log.Logger("config")
class ModuleCCSessionError(Exception): pass
+class RPCError(ModuleCCSessionError):
+ """
+ An exception raised by rpc_call in case the remote side reports
+ an error. It can be used to distinguish remote errors from protocol errors.
+ Also, it holds the code as well as the error message.
+ """
+ def __init__(self, code, message):
+ ModuleCCSessionError.__init__(self, message)
+ self.__code = code
+
+ def code(self):
+ """
+ The code as sent over the CC.
+ """
+ return self.__code
+
+class RPCRecipientMissing(RPCError):
+ """
+ Special version of the RPCError, for cases the recipient of the call
+ isn't connected to the bus. The code is always
+ isc.cc.proto_defs.CC_REPLY_NO_RECPT.
+ """
+ def __init__(self, message):
+ RPCError.__init__(self, CC_REPLY_NO_RECPT, message)
+
def parse_answer(msg):
"""Returns a tuple (rcode, value), where value depends on the
command that was called. If rcode != 0, value is a string
@@ -66,7 +92,8 @@ def parse_answer(msg):
raise ModuleCCSessionError("wrong rcode type in answer message")
else:
if len(msg['result']) > 1:
- if (msg['result'][0] != 0 and type(msg['result'][1]) != str):
+ if (msg['result'][0] != CC_REPLY_SUCCESS and
+ type(msg['result'][1]) != str):
raise ModuleCCSessionError("rcode in answer message is non-zero, value is not a string")
return msg['result'][0], msg['result'][1]
else:
@@ -79,7 +106,7 @@ def create_answer(rcode, arg = None):
a string containing an error message"""
if type(rcode) != int:
raise ModuleCCSessionError("rcode in create_answer() must be an integer")
- if rcode != 0 and type(arg) != str:
+ if rcode != CC_REPLY_SUCCESS and type(arg) != str:
raise ModuleCCSessionError("arg in create_answer for rcode != 0 must be a string describing the error")
if arg != None:
return { 'result': [ rcode, arg ] }
@@ -299,7 +326,7 @@ class ModuleCCSession(ConfigData):
isc.cc.data.remove_identical(new_config, self.get_local_config())
answer = self._config_handler(new_config)
rcode, val = parse_answer(answer)
- if rcode == 0:
+ if rcode == CC_REPLY_SUCCESS:
newc = self.get_local_config()
isc.cc.data.merge(newc, new_config)
self.set_local_config(newc)
@@ -474,6 +501,42 @@ class ModuleCCSession(ConfigData):
except isc.cc.SessionTimeout:
raise ModuleCCSessionError("CC Session timeout waiting for configuration manager")
+ def rpc_call(self, command, group, instance=CC_INSTANCE_WILDCARD,
+ to=CC_TO_WILDCARD, params=None):
+ """
+ Create a command with the given name and parameters. Send it to a
+ recipient, wait for the answer and parse it.
+
+ This is a wrapper around the group_sendmsg and group_recvmsg on the CC
+ session. It exists mostly for convenience.
+
+ Params:
+ - command: Name of the command to call on the remote side.
+ - group, instance, to: Address specification of the recipient.
+ - params: Parameters to pass to the command (as keyword arguments).
+
+ Return: The return value of the remote call (just the value, no status
+ code or anything). May be None.
+
+ Raise:
+ - RPCRecipientMissing if the given recipient doesn't exist.
+ - RPCError if the other side sent an error response. The error string
+ is in the exception.
+ - ModuleCCSessionError in case of protocol errors, like malformed
+ answer.
+ """
+ cmd = create_command(command, params)
+ seq = self._session.group_sendmsg(cmd, group, instance=instance,
+ to=to, want_answer=True)
+ # For non-blocking, we'll have rpc_call_async (once the nonblock
+ # actualy works)
+ reply, rheaders = self._session.group_recvmsg(nonblock=False, seq=seq)
+ code, value = parse_answer(reply)
+ if code == CC_REPLY_NO_RECPT:
+ raise RPCRecipientMissing(value)
+ elif code != CC_REPLY_SUCCESS:
+ raise RPCError(code, value)
+ return value
class UIModuleCCSession(MultiConfigData):
"""This class is used in a configuration user interface. It contains
diff --git a/src/lib/python/isc/config/tests/ccsession_test.py b/src/lib/python/isc/config/tests/ccsession_test.py
index ad364ac..3c1c57e 100644
--- a/src/lib/python/isc/config/tests/ccsession_test.py
+++ b/src/lib/python/isc/config/tests/ccsession_test.py
@@ -289,6 +289,67 @@ class TestModuleCCSession(unittest.TestCase):
fake_session.close()
mccs.__del__() # with closed fake_session
+ def rpc_check(self, reply):
+ fake_session = FakeModuleCCSession()
+ mccs = self.create_session("spec1.spec", None, None, fake_session)
+ fake_session.message_queue = [
+ ["Spec1", None, reply, False]
+ ]
+ exception = None
+ try:
+ result = mccs.rpc_call("test", "Spec2", params={
+ "param1": "Param 1",
+ "param2": "Param 2"
+ })
+ except Exception as e:
+ # We first want to check the value sent, raise the exception
+ # afterwards. So store it for a short while.
+ exception = e
+ self.assertEqual([
+ ["Spec2", "*", {"command": ["test", {
+ "param1": "Param 1",
+ "param2": "Param 2"
+ }]}, True]
+ ], fake_session.message_queue)
+ if exception is not None:
+ raise exception
+ return result
+
+ def test_rpc_call_success(self):
+ """
+ Test we can send an RPC (command) and get an answer. The answer is
+ success in this case.
+ """
+ result = self.rpc_check({"result": [0, {"Hello": "a"}]})
+ self.assertEqual({"Hello": "a"}, result)
+
+ def test_rpc_call_success_none(self):
+ """
+ Test the success case of RPC command, but the answer is empty
+ (eg. a "void" function on the remote side).
+ """
+ self.assertIsNone(self.rpc_check({"result": [0]}))
+
+ def test_rpc_call_malformed_answer(self):
+ """
+ Test it successfully raises ModuleCCSessionError when a malformed
+ reply is sent.
+ """
+ self.assertRaises(ModuleCCSessionError, self.rpc_check, ["Nonsense"])
+
+ def test_rpc_call_error(self):
+ """
+ Test it raises an exception when the remote side reports an error.
+ """
+ self.assertRaises(RPCError, self.rpc_check, {"result": [1, "Error"]})
+
+ def test_rpc_call_no_recpt(self):
+ """
+ Test RPC raises an error when the recipient is not there.
+ """
+ self.assertRaises(RPCRecipientMissing, self.rpc_check,
+ {"result": [-1, "Error"]})
+
def my_config_handler_ok(self, new_config):
return isc.config.ccsession.create_answer(0)
diff --git a/src/lib/python/isc/config/tests/unittest_fakesession.py b/src/lib/python/isc/config/tests/unittest_fakesession.py
index 1641ec0..7043683 100644
--- a/src/lib/python/isc/config/tests/unittest_fakesession.py
+++ b/src/lib/python/isc/config/tests/unittest_fakesession.py
@@ -28,7 +28,7 @@ class WouldBlockForever(Exception):
class FakeModuleCCSession:
def __init__(self):
self.subscriptions = {}
- # each entry is of the form [ channel, instance, message ]
+ # each entry is of the form [ channel, instance, message, want_answer ]
self.message_queue = []
self._socket = "ok we just need something not-None here atm"
# if self.timeout is set to anything other than 0, and
@@ -68,12 +68,14 @@ class FakeModuleCCSession:
else:
return False
- def group_sendmsg(self, msg, channel, target = None):
- self.message_queue.append([ channel, target, msg ])
+ def group_sendmsg(self, msg, group, instance=None, to=None,
+ want_answer=False):
+ self.message_queue.append([ group, instance, msg, want_answer ])
+ return 42
def group_reply(self, env, msg):
if 'group' in env:
- self.message_queue.append([ env['group'], None, msg])
+ self.message_queue.append([ env['group'], None, msg, False])
def group_recvmsg(self, nonblock=True, seq = None):
for qm in self.message_queue:
diff --git a/src/lib/python/isc/server_common/auth_command.py b/src/lib/python/isc/server_common/auth_command.py
index 493d5fb..5b7635a 100644
--- a/src/lib/python/isc/server_common/auth_command.py
+++ b/src/lib/python/isc/server_common/auth_command.py
@@ -22,6 +22,13 @@ from isc.log_messages.server_common_messages import *
from isc.server_common.logger import logger
AUTH_MODULE_NAME = 'Auth'
+AUTH_LOADZONE_COMMAND = 'loadzone'
+
+def auth_loadzone_params(zone_name, zone_class):
+ return {
+ "origin": zone_name.to_text(),
+ "class": zone_class.to_text()
+ }
def auth_loadzone_command(module_cc, zone_name, zone_class):
'''Create a 'loadzone' command with a given zone for Auth server.
@@ -50,8 +57,5 @@ def auth_loadzone_command(module_cc, zone_name, zone_class):
# to notification-driven approach, at which point the function would
# be changed a lot.
- param = {
- "origin": zone_name.to_text(),
- "class": zone_class.to_text()
- }
- return create_command("loadzone", param)
+ return create_command(AUTH_LOADZONE_COMMAND,
+ auth_loadzone_params(zone_name, zone_class))
diff --git a/src/lib/server_common/tests/socket_requestor_test.cc b/src/lib/server_common/tests/socket_requestor_test.cc
index 9085ba9..8da545e 100644
--- a/src/lib/server_common/tests/socket_requestor_test.cc
+++ b/src/lib/server_common/tests/socket_requestor_test.cc
@@ -35,6 +35,7 @@
#include <util/io/fd.h>
#include <util/io/fd_share.h>
+#include <util/unittests/check_valgrind.h>
using namespace isc::data;
using namespace isc::config;
@@ -509,81 +510,83 @@ private:
};
TEST_F(SocketRequestorTest, testSocketPassing) {
- TestSocket ts;
- std::vector<std::pair<std::string, int> > data;
- data.push_back(std::pair<std::string, int>("foo\n", 1));
- data.push_back(std::pair<std::string, int>("bar\n", 2));
- data.push_back(std::pair<std::string, int>("foo\n", 3));
- data.push_back(std::pair<std::string, int>("foo\n", 1));
- data.push_back(std::pair<std::string, int>("foo\n", -1));
- data.push_back(std::pair<std::string, int>("foo\n", -2));
-
- // run() returns true iff we can specify read timeout so we avoid a
- // deadlock. Unless there's a bug the test should succeed even without the
- // timeout, but we don't want to make the test hang up in case with an
- // unexpected bug, so we'd rather skip most of the tests in that case.
- const bool timo_ok = ts.run(data);
- SocketRequestor::SocketID socket_id;
- if (timo_ok) {
- // 1 should be ok
- addAnswer("foo", ts.getPath());
- socket_id = doRequest();
- EXPECT_EQ("foo", socket_id.second);
- EXPECT_EQ(0, close(socket_id.first));
-
- // 2 should be ok too
- addAnswer("bar", ts.getPath());
- socket_id = doRequest();
- EXPECT_EQ("bar", socket_id.second);
- EXPECT_EQ(0, close(socket_id.first));
-
- // 3 should be ok too (reuse earlier token)
- addAnswer("foo", ts.getPath());
- socket_id = doRequest();
- EXPECT_EQ("foo", socket_id.second);
- EXPECT_EQ(0, close(socket_id.first));
- }
- // Create a second socket server, to test that multiple different
- // domains sockets would work as well (even though we don't actually
- // use that feature)
- TestSocket ts2;
- std::vector<std::pair<std::string, int> > data2;
- data2.push_back(std::pair<std::string, int>("foo\n", 1));
- const bool timo_ok2 = ts2.run(data2);
-
- if (timo_ok2) {
- // 1 should be ok
- addAnswer("foo", ts2.getPath());
- socket_id = doRequest();
- EXPECT_EQ("foo", socket_id.second);
- EXPECT_EQ(0, close(socket_id.first));
- }
+ if (!isc::util::unittests::runningOnValgrind()) {
+ TestSocket ts;
+ std::vector<std::pair<std::string, int> > data;
+ data.push_back(std::pair<std::string, int>("foo\n", 1));
+ data.push_back(std::pair<std::string, int>("bar\n", 2));
+ data.push_back(std::pair<std::string, int>("foo\n", 3));
+ data.push_back(std::pair<std::string, int>("foo\n", 1));
+ data.push_back(std::pair<std::string, int>("foo\n", -1));
+ data.push_back(std::pair<std::string, int>("foo\n", -2));
+
+ // run() returns true iff we can specify read timeout so we avoid a
+ // deadlock. Unless there's a bug the test should succeed even without the
+ // timeout, but we don't want to make the test hang up in case with an
+ // unexpected bug, so we'd rather skip most of the tests in that case.
+ const bool timo_ok = ts.run(data);
+ SocketRequestor::SocketID socket_id;
+ if (timo_ok) {
+ // 1 should be ok
+ addAnswer("foo", ts.getPath());
+ socket_id = doRequest();
+ EXPECT_EQ("foo", socket_id.second);
+ EXPECT_EQ(0, close(socket_id.first));
+
+ // 2 should be ok too
+ addAnswer("bar", ts.getPath());
+ socket_id = doRequest();
+ EXPECT_EQ("bar", socket_id.second);
+ EXPECT_EQ(0, close(socket_id.first));
+
+ // 3 should be ok too (reuse earlier token)
+ addAnswer("foo", ts.getPath());
+ socket_id = doRequest();
+ EXPECT_EQ("foo", socket_id.second);
+ EXPECT_EQ(0, close(socket_id.first));
+ }
+ // Create a second socket server, to test that multiple different
+ // domains sockets would work as well (even though we don't actually
+ // use that feature)
+ TestSocket ts2;
+ std::vector<std::pair<std::string, int> > data2;
+ data2.push_back(std::pair<std::string, int>("foo\n", 1));
+ const bool timo_ok2 = ts2.run(data2);
+
+ if (timo_ok2) {
+ // 1 should be ok
+ addAnswer("foo", ts2.getPath());
+ socket_id = doRequest();
+ EXPECT_EQ("foo", socket_id.second);
+ EXPECT_EQ(0, close(socket_id.first));
+ }
- if (timo_ok) {
- // Now use first socket again
- addAnswer("foo", ts.getPath());
- socket_id = doRequest();
- EXPECT_EQ("foo", socket_id.second);
- EXPECT_EQ(0, close(socket_id.first));
+ if (timo_ok) {
+ // Now use first socket again
+ addAnswer("foo", ts.getPath());
+ socket_id = doRequest();
+ EXPECT_EQ("foo", socket_id.second);
+ EXPECT_EQ(0, close(socket_id.first));
+
+ // -1 is a "normal" error
+ addAnswer("foo", ts.getPath());
+ EXPECT_THROW(doRequest(), SocketRequestor::SocketError);
+
+ // -2 is an unexpected error. After this point it's not guaranteed the
+ // connection works as intended.
+ addAnswer("foo", ts.getPath());
+ EXPECT_THROW(doRequest(), SocketRequestor::SocketError);
+ }
- // -1 is a "normal" error
+ // Vector is of first socket is now empty, so the socket should be gone
addAnswer("foo", ts.getPath());
EXPECT_THROW(doRequest(), SocketRequestor::SocketError);
- // -2 is an unexpected error. After this point it's not guaranteed the
- // connection works as intended.
- addAnswer("foo", ts.getPath());
+ // Vector is of second socket is now empty too, so the socket should be
+ // gone
+ addAnswer("foo", ts2.getPath());
EXPECT_THROW(doRequest(), SocketRequestor::SocketError);
}
-
- // Vector is of first socket is now empty, so the socket should be gone
- addAnswer("foo", ts.getPath());
- EXPECT_THROW(doRequest(), SocketRequestor::SocketError);
-
- // Vector is of second socket is now empty too, so the socket should be
- // gone
- addAnswer("foo", ts2.getPath());
- EXPECT_THROW(doRequest(), SocketRequestor::SocketError);
}
}
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/src/lib/util/tests/fd_share_tests.cc b/src/lib/util/tests/fd_share_tests.cc
index cc92e47..b8000e1 100644
--- a/src/lib/util/tests/fd_share_tests.cc
+++ b/src/lib/util/tests/fd_share_tests.cc
@@ -15,6 +15,7 @@
#include <util/io/fd.h>
#include <util/io/fd_share.h>
+#include <util/unittests/check_valgrind.h>
#include <util/unittests/fork.h>
#include <gtest/gtest.h>
@@ -30,44 +31,47 @@ namespace {
// We test that we can transfer a pipe over other pipe
TEST(FDShare, transfer) {
- // Get a pipe and fork
- int pipes[2];
- ASSERT_NE(-1, socketpair(AF_UNIX, SOCK_STREAM, 0, pipes));
- pid_t sender(fork());
- ASSERT_NE(-1, sender);
- if(sender) { // We are in parent
- // Close the other side of pipe, we want only writible one
- EXPECT_NE(-1, close(pipes[0]));
- // Get a process to check data
- int fd(0);
- pid_t checker(check_output(&fd, "data", 4));
- ASSERT_NE(-1, checker);
- // Now, send the file descriptor, close it and close the pipe
- EXPECT_NE(-1, send_fd(pipes[1], fd));
- EXPECT_NE(-1, close(pipes[1]));
- EXPECT_NE(-1, close(fd));
- // Check both subprocesses ended well
- EXPECT_TRUE(process_ok(sender));
- EXPECT_TRUE(process_ok(checker));
- } else { // We are in child. We do not use ASSERT here
- // Close the write end, we only read
- if(close(pipes[1])) {
- exit(1);
- }
- // Get the file descriptor
- int fd(recv_fd(pipes[0]));
- if(fd == -1) {
- exit(1);
- }
- // This pipe is not needed
- if(close(pipes[0])) {
- exit(1);
- }
- // Send "data" trough the received fd, close it and be done
- if(!write_data(fd, "data", 4) || close(fd) == -1) {
- exit(1);
+
+ if (!isc::util::unittests::runningOnValgrind()) {
+ // Get a pipe and fork
+ int pipes[2];
+ ASSERT_NE(-1, socketpair(AF_UNIX, SOCK_STREAM, 0, pipes));
+ const pid_t sender(fork());
+ ASSERT_NE(-1, sender);
+ if (sender) { // We are in parent
+ // Close the other side of pipe, we want only writible one
+ EXPECT_NE(-1, close(pipes[0]));
+ // Get a process to check data
+ int fd(0);
+ const pid_t checker(check_output(&fd, "data", 4));
+ ASSERT_NE(-1, checker);
+ // Now, send the file descriptor, close it and close the pipe
+ EXPECT_NE(-1, send_fd(pipes[1], fd));
+ EXPECT_NE(-1, close(pipes[1]));
+ EXPECT_NE(-1, close(fd));
+ // Check both subprocesses ended well
+ EXPECT_TRUE(process_ok(sender));
+ EXPECT_TRUE(process_ok(checker));
+ } else { // We are in child. We do not use ASSERT here
+ // Close the write end, we only read
+ if (close(pipes[1])) {
+ exit(1);
+ }
+ // Get the file descriptor
+ const int fd(recv_fd(pipes[0]));
+ if (fd == -1) {
+ exit(1);
+ }
+ // This pipe is not needed
+ if (close(pipes[0])) {
+ exit(1);
+ }
+ // Send "data" trough the received fd, close it and be done
+ if (!write_data(fd, "data", 4) || close(fd) == -1) {
+ exit(1);
+ }
+ exit(0);
}
- exit(0);
}
}
diff --git a/src/lib/util/tests/fd_tests.cc b/src/lib/util/tests/fd_tests.cc
index b709405..1a1d3ee 100644
--- a/src/lib/util/tests/fd_tests.cc
+++ b/src/lib/util/tests/fd_tests.cc
@@ -12,6 +12,8 @@
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
+#include <util/unittests/check_valgrind.h>
+
#include <util/io/fd.h>
#include <util/unittests/fork.h>
@@ -45,24 +47,28 @@ class FDTest : public ::testing::Test {
// Test we read what was sent
TEST_F(FDTest, read) {
- int read_pipe(0);
- buffer = new unsigned char[TEST_DATA_SIZE];
- pid_t feeder(provide_input(&read_pipe, data, TEST_DATA_SIZE));
- ASSERT_GE(feeder, 0);
- ssize_t received(read_data(read_pipe, buffer, TEST_DATA_SIZE));
- EXPECT_TRUE(process_ok(feeder));
- EXPECT_EQ(TEST_DATA_SIZE, received);
- EXPECT_EQ(0, memcmp(data, buffer, received));
+ if (!isc::util::unittests::runningOnValgrind()) {
+ int read_pipe(0);
+ buffer = new unsigned char[TEST_DATA_SIZE];
+ pid_t feeder(provide_input(&read_pipe, data, TEST_DATA_SIZE));
+ ASSERT_GE(feeder, 0);
+ ssize_t received(read_data(read_pipe, buffer, TEST_DATA_SIZE));
+ EXPECT_TRUE(process_ok(feeder));
+ EXPECT_EQ(TEST_DATA_SIZE, received);
+ EXPECT_EQ(0, memcmp(data, buffer, received));
+ }
}
// Test we write the correct thing
TEST_F(FDTest, write) {
- int write_pipe(0);
- pid_t checker(check_output(&write_pipe, data, TEST_DATA_SIZE));
- ASSERT_GE(checker, 0);
- EXPECT_TRUE(write_data(write_pipe, data, TEST_DATA_SIZE));
- EXPECT_EQ(0, close(write_pipe));
- EXPECT_TRUE(process_ok(checker));
+ if (!isc::util::unittests::runningOnValgrind()) {
+ int write_pipe(0);
+ pid_t checker(check_output(&write_pipe, data, TEST_DATA_SIZE));
+ ASSERT_GE(checker, 0);
+ EXPECT_TRUE(write_data(write_pipe, data, TEST_DATA_SIZE));
+ EXPECT_EQ(0, close(write_pipe));
+ EXPECT_TRUE(process_ok(checker));
+ }
}
}
diff --git a/src/lib/util/tests/interprocess_sync_file_unittest.cc b/src/lib/util/tests/interprocess_sync_file_unittest.cc
index 9a1b025..6f23558 100644
--- a/src/lib/util/tests/interprocess_sync_file_unittest.cc
+++ b/src/lib/util/tests/interprocess_sync_file_unittest.cc
@@ -13,6 +13,8 @@
// PERFORMANCE OF THIS SOFTWARE.
#include "util/interprocess_sync_file.h"
+
+#include <util/unittests/check_valgrind.h>
#include <gtest/gtest.h>
#include <unistd.h>
@@ -53,59 +55,62 @@ parentReadLockedState (int fd) {
}
TEST(InterprocessSyncFileTest, TestLock) {
- InterprocessSyncFile sync("test");
- InterprocessSyncLocker locker(sync);
+ InterprocessSyncFile sync("test");
+ InterprocessSyncLocker locker(sync);
- EXPECT_FALSE(locker.isLocked());
- EXPECT_TRUE(locker.lock());
- EXPECT_TRUE(locker.isLocked());
+ EXPECT_FALSE(locker.isLocked());
+ EXPECT_TRUE(locker.lock());
+ EXPECT_TRUE(locker.isLocked());
- int fds[2];
+ if (!isc::util::unittests::runningOnValgrind()) {
- // Here, we check that a lock has been taken by forking and
- // checking from the child that a lock exists. This has to be
- // done from a separate process as we test by trying to lock the
- // range again on the lock file. The lock attempt would pass if
- // done from the same process for the granted range. The lock
- // attempt must fail to pass our check.
+ int fds[2];
- EXPECT_EQ(0, pipe(fds));
+ // Here, we check that a lock has been taken by forking and
+ // checking from the child that a lock exists. This has to be
+ // done from a separate process as we test by trying to lock the
+ // range again on the lock file. The lock attempt would pass if
+ // done from the same process for the granted range. The lock
+ // attempt must fail to pass our check.
- if (fork() == 0) {
- unsigned char locked = 0;
- // Child writes to pipe
- close(fds[0]);
+ EXPECT_EQ(0, pipe(fds));
- InterprocessSyncFile sync2("test");
- InterprocessSyncLocker locker2(sync2);
+ if (fork() == 0) {
+ unsigned char locked = 0;
+ // Child writes to pipe
+ close(fds[0]);
- if (!locker2.tryLock()) {
- EXPECT_FALSE(locker2.isLocked());
- locked = 1;
- } else {
- EXPECT_TRUE(locker2.isLocked());
- }
+ InterprocessSyncFile sync2("test");
+ InterprocessSyncLocker locker2(sync2);
- ssize_t bytes_written = write(fds[1], &locked, sizeof(locked));
- EXPECT_EQ(sizeof(locked), bytes_written);
+ if (!locker2.tryLock()) {
+ EXPECT_FALSE(locker2.isLocked());
+ locked = 1;
+ } else {
+ EXPECT_TRUE(locker2.isLocked());
+ }
- close(fds[1]);
- exit(0);
- } else {
- // Parent reads from pipe
- close(fds[1]);
+ ssize_t bytes_written = write(fds[1], &locked, sizeof(locked));
+ EXPECT_EQ(sizeof(locked), bytes_written);
- const unsigned char locked = parentReadLockedState(fds[0]);
+ close(fds[1]);
+ exit(0);
+ } else {
+ // Parent reads from pipe
+ close(fds[1]);
- close(fds[0]);
+ const unsigned char locked = parentReadLockedState(fds[0]);
- EXPECT_EQ(1, locked);
- }
+ close(fds[0]);
- EXPECT_TRUE(locker.unlock());
- EXPECT_FALSE(locker.isLocked());
+ EXPECT_EQ(1, locked);
+ }
+ }
+
+ EXPECT_TRUE(locker.unlock());
+ EXPECT_FALSE(locker.isLocked());
- EXPECT_EQ (0, unlink(TEST_DATA_TOPBUILDDIR "/test_lockfile"));
+ EXPECT_EQ (0, unlink(TEST_DATA_TOPBUILDDIR "/test_lockfile"));
}
TEST(InterprocessSyncFileTest, TestMultipleFilesDirect) {
@@ -126,49 +131,53 @@ TEST(InterprocessSyncFileTest, TestMultipleFilesDirect) {
}
TEST(InterprocessSyncFileTest, TestMultipleFilesForked) {
- InterprocessSyncFile sync("test1");
- InterprocessSyncLocker locker(sync);
+ InterprocessSyncFile sync("test1");
+ InterprocessSyncLocker locker(sync);
- EXPECT_TRUE(locker.lock());
+ EXPECT_TRUE(locker.lock());
- int fds[2];
+ if (!isc::util::unittests::runningOnValgrind()) {
- EXPECT_EQ(0, pipe(fds));
+ int fds[2];
- if (fork() == 0) {
- unsigned char locked = 0xff;
- // Child writes to pipe
- close(fds[0]);
+ EXPECT_EQ(0, pipe(fds));
- InterprocessSyncFile sync2("test2");
- InterprocessSyncLocker locker2(sync2);
+ if (fork() == 0) {
+ unsigned char locked = 0xff;
+ // Child writes to pipe
+ close(fds[0]);
- if (locker2.tryLock()) {
- locked = 0;
- }
+ InterprocessSyncFile sync2("test2");
+ InterprocessSyncLocker locker2(sync2);
- ssize_t bytes_written = write(fds[1], &locked, sizeof(locked));
- EXPECT_EQ(sizeof(locked), bytes_written);
+ if (locker2.tryLock()) {
+ locked = 0;
+ }
- close(fds[1]);
- exit(0);
- } else {
- // Parent reads from pipe
- close(fds[1]);
+ ssize_t bytes_written = write(fds[1], &locked, sizeof(locked));
+ EXPECT_EQ(sizeof(locked), bytes_written);
- const unsigned char locked = parentReadLockedState(fds[0]);
+ close(fds[1]);
+ exit(0);
+ } else {
+ // Parent reads from pipe
+ close(fds[1]);
- close(fds[0]);
+ const unsigned char locked = parentReadLockedState(fds[0]);
- EXPECT_EQ(0, locked);
- }
+ close(fds[0]);
- EXPECT_TRUE(locker.unlock());
+ EXPECT_EQ(0, locked);
+ }
- EXPECT_EQ (0, unlink(TEST_DATA_TOPBUILDDIR "/test1_lockfile"));
- EXPECT_EQ (0, unlink(TEST_DATA_TOPBUILDDIR "/test2_lockfile"));
-}
+ EXPECT_EQ (0, unlink(TEST_DATA_TOPBUILDDIR "/test2_lockfile"));
+ }
+
+ EXPECT_TRUE(locker.unlock());
+
+ EXPECT_EQ (0, unlink(TEST_DATA_TOPBUILDDIR "/test1_lockfile"));
}
+} // anonymous namespace
} // namespace util
} // namespace isc
diff --git a/src/lib/util/threads/tests/condvar_unittest.cc b/src/lib/util/threads/tests/condvar_unittest.cc
index 1e04efa..3bb7230 100644
--- a/src/lib/util/threads/tests/condvar_unittest.cc
+++ b/src/lib/util/threads/tests/condvar_unittest.cc
@@ -15,6 +15,7 @@
#include <config.h>
#include <exceptions/exceptions.h>
+#include <util/unittests/check_valgrind.h>
#include <util/threads/sync.h>
#include <util/threads/thread.h>
@@ -84,12 +85,14 @@ ringSignal(CondVar* condvar, Mutex* mutex, int* arg) {
// A simple wait-signal operation on a condition variable.
TEST_F(CondVarTest, waitAndSignal) {
- Mutex::Locker locker(mutex_);
- int shared_var = 0; // let the other thread increment this
- Thread t(boost::bind(&ringSignal, &condvar_, &mutex_, &shared_var));
- condvar_.wait(mutex_);
- t.wait();
- EXPECT_EQ(1, shared_var);
+ if (!isc::util::unittests::runningOnValgrind()) {
+ Mutex::Locker locker(mutex_);
+ int shared_var = 0; // let the other thread increment this
+ Thread t(boost::bind(&ringSignal, &condvar_, &mutex_, &shared_var));
+ condvar_.wait(mutex_);
+ t.wait();
+ EXPECT_EQ(1, shared_var);
+ }
}
// Thread's main code for the next test
@@ -143,12 +146,14 @@ signalAndWait(CondVar* condvar, Mutex* mutex) {
TEST_F(CondVarTest, destroyWhileWait) {
// We'll destroy a CondVar object while the thread is still waiting
// on it. This will trigger an assertion failure.
- EXPECT_DEATH_IF_SUPPORTED({
- CondVar cond;
- Mutex::Locker locker(mutex_);
- Thread t(boost::bind(&signalAndWait, &cond, &mutex_));
- cond.wait(mutex_);
- }, "");
+ if (!isc::util::unittests::runningOnValgrind()) {
+ EXPECT_DEATH_IF_SUPPORTED({
+ CondVar cond;
+ Mutex::Locker locker(mutex_);
+ Thread t(boost::bind(&signalAndWait, &cond, &mutex_));
+ cond.wait(mutex_);
+ }, "");
+ }
}
#endif // !HAS_UNDEFINED_PTHREAD_BEHAVIOR
diff --git a/src/lib/util/threads/tests/lock_unittest.cc b/src/lib/util/threads/tests/lock_unittest.cc
index 1abc3fa..4c4f831 100644
--- a/src/lib/util/threads/tests/lock_unittest.cc
+++ b/src/lib/util/threads/tests/lock_unittest.cc
@@ -94,33 +94,35 @@ void
noHandler(int) {}
TEST(MutexTest, swarm) {
- // Create a timeout in case something got stuck here
- struct sigaction ignored, original;
- memset(&ignored, 0, sizeof(ignored));
- ignored.sa_handler = noHandler;
- if (sigaction(SIGALRM, &ignored, &original)) {
- FAIL() << "Couldn't set alarm";
- }
- alarm(10);
- // This type has a low chance of being atomic itself, further raising
- // the chance of problems appearing.
- double canary = 0;
- Mutex mutex;
- // Run two parallel threads
- bool ready1 = false;
- bool ready2 = false;
- Thread t1(boost::bind(&performIncrement, &canary, &ready1, &ready2,
- &mutex));
- Thread t2(boost::bind(&performIncrement, &canary, &ready2, &ready1,
- &mutex));
- t1.wait();
- t2.wait();
- // Check it the sum is the expected value.
- EXPECT_EQ(iterations * 2, canary) << "Threads are badly synchronized";
- // Cancel the alarm and return the original handler
- alarm(0);
- if (sigaction(SIGALRM, &original, NULL)) {
- FAIL() << "Couldn't restore alarm";
+ if (!isc::util::unittests::runningOnValgrind()) {
+ // Create a timeout in case something got stuck here
+ struct sigaction ignored, original;
+ memset(&ignored, 0, sizeof(ignored));
+ ignored.sa_handler = noHandler;
+ if (sigaction(SIGALRM, &ignored, &original)) {
+ FAIL() << "Couldn't set alarm";
+ }
+ alarm(10);
+ // This type has a low chance of being atomic itself, further raising
+ // the chance of problems appearing.
+ double canary = 0;
+ Mutex mutex;
+ // Run two parallel threads
+ bool ready1 = false;
+ bool ready2 = false;
+ Thread t1(boost::bind(&performIncrement, &canary, &ready1, &ready2,
+ &mutex));
+ Thread t2(boost::bind(&performIncrement, &canary, &ready2, &ready1,
+ &mutex));
+ t1.wait();
+ t2.wait();
+ // Check it the sum is the expected value.
+ EXPECT_EQ(iterations * 2, canary) << "Threads are badly synchronized";
+ // Cancel the alarm and return the original handler
+ alarm(0);
+ if (sigaction(SIGALRM, &original, NULL)) {
+ FAIL() << "Couldn't restore alarm";
+ }
}
}
diff --git a/src/lib/util/threads/tests/thread_unittest.cc b/src/lib/util/threads/tests/thread_unittest.cc
index 5afdf3f..0a8df41 100644
--- a/src/lib/util/threads/tests/thread_unittest.cc
+++ b/src/lib/util/threads/tests/thread_unittest.cc
@@ -13,6 +13,7 @@
// PERFORMANCE OF THIS SOFTWARE.
#include <util/threads/thread.h>
+#include <util/unittests/check_valgrind.h>
#include <boost/bind.hpp>
@@ -41,9 +42,11 @@ doSomething(int*) { }
// We just test that we can forget about the thread and nothing
// bad will happen on our side.
TEST(ThreadTest, detached) {
- int x;
- for (size_t i = 0; i < detached_iterations; ++i) {
- Thread thread(boost::bind(&doSomething, &x));
+ if (!isc::util::unittests::runningOnValgrind()) {
+ int x;
+ for (size_t i = 0; i < detached_iterations; ++i) {
+ Thread thread(boost::bind(&doSomething, &x));
+ }
}
}
@@ -55,13 +58,15 @@ markRun(bool* mark) {
// Wait for a thread to end first. The variable must be set at the time.
TEST(ThreadTest, wait) {
- for (size_t i = 0; i < iterations; ++i) {
- bool mark = false;
- Thread thread(boost::bind(markRun, &mark));
- thread.wait();
- ASSERT_TRUE(mark) << "Not finished yet in " << i << "th iteration";
- // Can't wait second time
- ASSERT_THROW(thread.wait(), isc::InvalidOperation);
+ if (!isc::util::unittests::runningOnValgrind()) {
+ for (size_t i = 0; i < iterations; ++i) {
+ bool mark = false;
+ Thread thread(boost::bind(markRun, &mark));
+ thread.wait();
+ ASSERT_TRUE(mark) << "Not finished yet in " << i << "th iteration";
+ // Can't wait second time
+ ASSERT_THROW(thread.wait(), isc::InvalidOperation);
+ }
}
}
@@ -77,21 +82,25 @@ throwException() {
// Exception in the thread we forget about should not do anything to us
TEST(ThreadTest, detachedException) {
- for (size_t i = 0; i < detached_iterations; ++i) {
- Thread thread(throwSomething);
- }
- for (size_t i = 0; i < detached_iterations; ++i) {
- Thread thread(throwException);
+ if (!isc::util::unittests::runningOnValgrind()) {
+ for (size_t i = 0; i < detached_iterations; ++i) {
+ Thread thread(throwSomething);
+ }
+ for (size_t i = 0; i < detached_iterations; ++i) {
+ Thread thread(throwException);
+ }
}
}
// An uncaught exception in the thread should propagate through wait
TEST(ThreadTest, exception) {
- for (size_t i = 0; i < iterations; ++i) {
- Thread thread(throwSomething);
- Thread thread2(throwException);
- ASSERT_THROW(thread.wait(), Thread::UncaughtException);
- ASSERT_THROW(thread2.wait(), Thread::UncaughtException);
+ if (!isc::util::unittests::runningOnValgrind()) {
+ for (size_t i = 0; i < iterations; ++i) {
+ Thread thread(throwSomething);
+ Thread thread2(throwException);
+ ASSERT_THROW(thread.wait(), Thread::UncaughtException);
+ ASSERT_THROW(thread2.wait(), Thread::UncaughtException);
+ }
}
}
diff --git a/src/lib/util/unittests/check_valgrind.h b/src/lib/util/unittests/check_valgrind.h
index 80f1f85..3837b10 100644
--- a/src/lib/util/unittests/check_valgrind.h
+++ b/src/lib/util/unittests/check_valgrind.h
@@ -38,6 +38,11 @@ namespace unittests {
/// \brief Check if the program is run in valgrind
///
+/// This is used to check for valgrind and skip (parts of) tests that fork,
+/// such as death tests, and general forking tests, and some threading tests;
+/// These tend to cause valgrind to report errors, which would hide other
+/// potential valgrind reports.
+///
/// \return true if valgrind headers are available, and valgrind is running,
/// false if the headers are not available, or if valgrind is not
/// running
diff --git a/src/lib/util/unittests/fork.cc b/src/lib/util/unittests/fork.cc
index 7ed22f8..2d5efb0 100644
--- a/src/lib/util/unittests/fork.cc
+++ b/src/lib/util/unittests/fork.cc
@@ -77,6 +77,7 @@ provide_input(int *read_pipe, const void *input, const size_t length)
return -1;
}
*read_pipe = pipes[0];
+
pid_t pid(fork());
if (pid) { // We are in the parent
return pid;
@@ -91,6 +92,7 @@ provide_input(int *read_pipe, const void *input, const size_t length)
}
}
+
/*
* This creates a pipe, forks and reads the pipe and compares it
* with given data. Used to check output of run in an asynchronous way.
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`
diff --git a/tests/tools/perfdhcp/test_control.cc b/tests/tools/perfdhcp/test_control.cc
index f7f4978..e51065f 100644
--- a/tests/tools/perfdhcp/test_control.cc
+++ b/tests/tools/perfdhcp/test_control.cc
@@ -13,27 +13,28 @@
// PERFORMANCE OF THIS SOFTWARE.
-#include <fstream>
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include <unistd.h>
-#include <signal.h>
-#include <sys/wait.h>
-
-#include <boost/date_time/posix_time/posix_time.hpp>
-
#include <exceptions/exceptions.h>
#include <asiolink/io_address.h>
#include <dhcp/libdhcp++.h>
#include <dhcp/iface_mgr.h>
#include <dhcp/dhcp4.h>
#include <dhcp/option6_ia.h>
+#include <util/unittests/check_valgrind.h>
#include "test_control.h"
#include "command_options.h"
#include "perf_pkt4.h"
#include "perf_pkt6.h"
+#include <fstream>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <signal.h>
+#include <sys/wait.h>
+
+#include <boost/date_time/posix_time/posix_time.hpp>
+
using namespace std;
using namespace boost::posix_time;
using namespace isc;
@@ -724,7 +725,7 @@ TestControl::printDiagnostics() const {
std::cout << "Set MAC to " << vector2Hex(options.getMacTemplate(), "::")
<< std::endl;
if (options.getDuidTemplate().size() > 0) {
- std::cout << "Set DUID to " << vector2Hex(options.getDuidTemplate()) << std::endl;
+ std::cout << "Set DUID to " << vector2Hex(options.getDuidTemplate()) << std::endl;
}
}
}
More information about the bind10-changes
mailing list