BIND 10 trac2252, updated. 9d00667f84006fc001b04953519e78b1ee5f0010 [2252] update the note to more accurate one due to bug #2879
BIND 10 source code commits
bind10-changes at lists.isc.org
Fri Apr 5 04:43:37 UTC 2013
The branch, trac2252 has been updated
via 9d00667f84006fc001b04953519e78b1ee5f0010 (commit)
via d7885ecddb52be49de729021a70b42e60aca2cea (commit)
via 1f578c9b208b0fb2e58b101d537a9d07f66ad690 (commit)
via 4f63e23b7aac425bafd4e0c6e5c4099b157206c5 (commit)
via a4b1c8d4bb37b273c9027f41b00eeae54ad2f83d (commit)
via 4a8316ddc1bff361a289ed8c406bbe90fde79e16 (commit)
via 5c0c1cb8f090edf516c21cf03506075bd866915c (commit)
via e346959d031b0ce05939f801e83f653892757e49 (commit)
via 60b242c2d161e30a05236fb6dae3ff21daa0b6b8 (commit)
via 307e3c7a946a593945050b9ea8159df85f5cf28d (commit)
via 2e97db1d7db5a65bc19f6909269ae930d2e8da18 (commit)
via 4d5c20e29fd4a74db31024bdcdaa99d431af3219 (commit)
via 20df0b0ce702241ce8265690388483c5ece3eb16 (commit)
via ff8d95f4e0afc3d2b8fc5f3e75eb41edee1f969e (commit)
via 678965be5a2ca3ba12981884e48911028953f853 (commit)
via 836fabb60589aaf7b901176892b6c28ab464e8d6 (commit)
via b59d780f0b9fd66c06eb7d06082e41249b778f94 (commit)
via ad797b98b8ae4f0f003374c13649147aef3c1a83 (commit)
via 8802d414240a4b453b13573e1bbc381eb0d14343 (commit)
via b321b2e7708069b82bae12eb1b4461f4eb9e4a03 (commit)
via fe630ca4be50f0f0bd048eec264b8a21df9c6b38 (commit)
via 7f62c19c5d561e755570b8aeab625dd275ecae3a (commit)
via 4c90b6cf817c2087052ea8b22e91a3b7f8ae39f0 (commit)
via 0107d1f09fb6075c9fc2ea6a162c85d4a89a8e85 (commit)
via bcefe1e95cdd61ee4a09b20522c3c56b315a1acc (commit)
via 37583984483d4027f5e2fece88e3f7e12ac42fe8 (commit)
via ad11aede925c7307dd3a6528be0d1e8e4723d162 (commit)
via d72fddedb47c7dfae908e2c5bfc9c6ca1d574420 (commit)
via 37e3ef0278c0f52a2e211b72d9b39e7e25262b43 (commit)
via 75af5cd564de8cec47f2ed5ab3b5cb028acdd0ca (commit)
via 1073338ae5e5ea9fa385abf5b87ff3421f51ab97 (commit)
via 1450d8d486cba3bee8be46e8001d66898edd370c (commit)
via 451d16ebbbf619ad5b420b7a837bf95ec23ab686 (commit)
via 954430281cec4d8f6382285f761a1859ca9508f7 (commit)
via 93cb134fd8ff6fc6c9d63d0a9f6ca3defed43721 (commit)
via da42298dc1ad39a5073bb8b221e05ccf8fb5464c (commit)
via 94aade43c190a9dccca5469009b2604efb7c5664 (commit)
via f3507e17b575821adf1076236e2855c1d7be1f26 (commit)
via c5f8c4c31d08049b5b8b1e7ab43011d62293f18b (commit)
via d3a0ac2204c90e1bb6b3ccb474f7224f1154a0db (commit)
via b1a6659c841d75b8e918dc3a1e165188d97d56fe (commit)
via bc9d924de6ba3c7ddf25e3c77b2470b17667d068 (commit)
via 9181c52cd0d827a7c62538b1590e1a061a11c07f (commit)
via 89d7de8e2f809aef2184b450e7dee1bfec98ad14 (commit)
via 4660c86fe6aeb2c77427ca8cacd1b7f840d4e554 (commit)
via 946126b36db6b9cd21c194a84a61417dd6bd567c (commit)
via 8c6afd880d47f33174b656ed12a2e5e4c821e14b (commit)
via 22407c48db5999e77a6fbd6e4f42ba2a3fe36762 (commit)
via bc87d1113832e7900d3627663c0a1203c3e7b2da (commit)
via 6fadd98cb5a9beeb79c58ba0a2768d9ad895c210 (commit)
via 9a3d9604b0fd9dd3dcc5f00b06ebf08e4e4f68a5 (commit)
via 029681ebd000727c546f8d387df270e9c1415bd4 (commit)
via 9a551ccda02b841bf296ecbce5c0bbf04721024a (commit)
via 506fdf871f529b20b295c8b3a18286c5f295a806 (commit)
via 716006fe1be4edaf841b94d488cd1d8cbbda116e (commit)
via 459cdc4a0dd14c3c21a8ce1e51bd99fd53026a21 (commit)
via 11cdfbb065c969dc5638c8c146666da4b3195677 (commit)
via 522bc3b62d92f30094428d580392ff427725cb0c (commit)
via 43c537178a4024702196d28c6408917c611c3a66 (commit)
via 0b8dd6b36af411f1aac1f48b099e36282c51da98 (commit)
via 48054d5a0cbb379af956c32330f919467b9d6b23 (commit)
via b058641f53581df0131c18e0e521d74d71790a23 (commit)
via 08fbb8a87decb5d7b9cd1568e515eec22e17e5e3 (commit)
via af2ca1df688ca14a0f58bb7151b19ee7afb88776 (commit)
via 5b1c236c65180291b33f01b8a0f7f1bc46a4d1a3 (commit)
via db06972d3798e67c5d581234c673cb4b9cdffb7c (commit)
via 47b58321cd15762b9cdd0f09e66e9f5b29e67eec (commit)
via e1c60036dfd2d4e1fcd372807e4a3f0f201028cb (commit)
via 9bd788945d172e66939dc6d8fdb3016803696cee (commit)
via 2118111e02bb90ffc92e14d37681acf3c5f52b98 (commit)
via 7f6ff763142c2a503f06410eaf4f8fc8e9259f02 (commit)
via df1c5d5232a2ab551cd98b77ae388ad568a683ad (commit)
via d66a48434bce9de43f371bb37811c820634f9937 (commit)
via c178521c5c7133093866a8403b3d1d8af2cb6684 (commit)
via 60635a58548ae680058d67837e6ce1696c3b7faa (commit)
via 660990cbc4df062e7814f86040f7cf87662190c2 (commit)
via 8c4c6e96fb6289bbacc2e4d15b8a7b131c8fadd8 (commit)
via 27e9cf518daa0a9f668b744b56b57add5c4e10d5 (commit)
via 191f569b711f30366f584045e4cefd9211929ad8 (commit)
via f687f77020bc9c4619915e7bb1d7f5a7c6c90ccc (commit)
via 6e0725b08ad12bafcc939622daa5a2f7b734ecbe (commit)
via 8377d0dcf3c758cc50111a98a7a9dafdc3237c44 (commit)
via 5e9811640dc3e514ee012b16287522f7993ade46 (commit)
via d007842f66f874ad8ceacf664f8c0645d2ec4226 (commit)
via d25f0e1e01a6cc3991ae63f0957c61ec171395ce (commit)
via dfce83e671afebb518b21733bc67e3627320e568 (commit)
via 7a8781d9f723a1783f9e027909f4e117ce532a83 (commit)
via be9f19012418391c0652a7f76e3bd2eddf72a351 (commit)
via ba046cd24c29b6b91cb49492c4dafa72af9b4a18 (commit)
via 0be5bed016c3b12abf5e7049ab7b63d2d474efc0 (commit)
via 2e6d5f8d602a632d8a770c13d7ccbc09a25825ad (commit)
via 7642e09748501d041309b84de9d46b3aeab74a63 (commit)
via 9dd3b10a7ce79fb1b1289136987f82c2bf9c2310 (commit)
via 739735c08bb30957be78506bc4cf0d6c5f01745d (commit)
via 0eb1e5059c26a083708f6d765035aba8aa4c6d2d (commit)
via abf4296a7becc39021bc31594b29fa540a86efff (commit)
via 0840c03b4269e5fb478905cb98f0bb04a5555bb8 (commit)
via d3752093f7cca1ade17038ec16e52e9a86f31115 (commit)
via 3afd0a061c6c24433c858142c91746d2702f0d04 (commit)
via 4813e06cf4e0a9d9f453890557b639715e081eca (commit)
via 01e052f372b1878b9bc40bfcea80d37e408a58ca (commit)
via 25b99148984082fd818624cd74cde2d86d428c2b (commit)
via 97a7be5ddb8f5a89206912eae174bacf3d230a8e (commit)
via f37600d5ae721b626b9e9323dbff17a404908e46 (commit)
via b47eafefecf38d32013bc7377aa4eebf531c49f6 (commit)
via 0239399581611def5ec0029ff48babb818cc7eb8 (commit)
via 416bae7d607e43d00b3661a201c3162bfe7e8270 (commit)
via 50b124aea4fc6c367ee64acb81041384c169906e (commit)
via c8b7d82c25958cdae8bb02e3a93b2b8d6dd078d1 (commit)
via e8e45c21b3a6a6c8169259ea5d66d8d475bfbfa6 (commit)
via 16e8be506f32de668699e6954f5de60ca9d14ddf (commit)
via 3c243b229dd01343e387ee9a729bce54711c5a50 (commit)
via 3c1fc036f79481a10628e3f841666c35a0b7b823 (commit)
via 5e66a7a9ecddb8e00f5ed44fa22a94d02a177e8d (commit)
via 95218da8e5bfd78889639e7cac68b4afcd44d264 (commit)
via c32bfa79b248fb9351dafc853ecc0a18ca2e3a66 (commit)
via 6067533e5c4ebded8260ef4b97f2709868bb2799 (commit)
via 8d178815af6a1eda06930288f3bcb4b261e25bbd (commit)
via 77249210b9ea779e45b35271a915a50250e00a00 (commit)
via 72b8ac61724514b5b8b8807aac6d9e2c9da7268b (commit)
via a45069dffcd932ef9ed38935db9f1cd54188a093 (commit)
via be41be890f1349ae4c870a887f7acd99ba1eaac5 (commit)
via 282af2bfa3dacd3b8145460dfed2cd9ac294983e (commit)
via 1c004d95a8b715500af448683e4a07e9b66ea926 (commit)
via fb2e8b3a65c9e36b745c81766b8c3973c8bd5737 (commit)
via 9f0f84c089904c5e544a21bfb4f4def60c9eb0fe (commit)
via 17c0037b8ab08e7aaa1a9eee9e1a0753308b2ce2 (commit)
via b11b84e52dd4670259d7c0a59d2e7cee4550b16a (commit)
via 1090b92f9a37d021c445b046b9245861df6ca36f (commit)
via 38faa03d1c37053d1c4ffe5e689716d42191a59e (commit)
via d27e68b1e1a5f124be2c02e0e6976afaabf0520b (commit)
via e58c2fd32cb85d37cd96ff8bb6a7cdf0f653a5a1 (commit)
via 4700bdc96332953deebe6b6c4204177a994e4930 (commit)
via 157e22bdf89b15d1a6c20e6e87673fee503d8b44 (commit)
via 725dea7f0e4a4d455355153575307e2803d78ab1 (commit)
via 8bab20ff2358dfcc7d7f09520688b9a07bbc1ea3 (commit)
via b96a30b26a045cfaa8ad579b0a8bf84f5ed4e73f (commit)
via 4c3b2b24d863782742d49ed2bd60a38dba93d4bd (commit)
via 85a61f11135e898164d5e41e949bb6ba6929531b (commit)
via 0f0c175daf770bf863f32a4798657625704a0c54 (commit)
via bf86e0c9ea67c5ddd6e70ddec63a1f46d8c62630 (commit)
via 0860ae366d73314446d4886a093f4e86e94863d4 (commit)
via 25201656d56854345b11d4a3d553655da2a43bfa (commit)
via ca1da8aa5de24358d7d4e7e9a4625347457118cf (commit)
via 274ab7a8bd50c7d04214b97193c7461b99c2382e (commit)
via b48b9c7e0d0b51d399f248cb3387dbae770d157e (commit)
via 0a55e2f325a76a08c3feec9911c146bbf9e017a1 (commit)
via a2108be0aee261fe1046f96a94543c25937b55a4 (commit)
via 6ae0d625f0571efa6482618636629e8e210a7718 (commit)
via 835c041058405743d746a6cc02746018774540e4 (commit)
via e8757a6861d8328cf7f8f2bd815af3a6461cfdc9 (commit)
via dd41cb13ce276c055af55e486404773dfbf31154 (commit)
via f4d68d5f8042f235514afd7ce27ff7cf43785726 (commit)
via f8a24304737fef27da9f2f4f8a02c1a558d6a34e (commit)
via 6c4f943e65aad695443076065082d40cfddbfe83 (commit)
via 99fbbc37fe2c3e465af2e1e5990b89602b02e8d4 (commit)
via ee109e14bb0c0409c689ca73fb9ddd5f2435e29b (commit)
via 8ab5a4d30ab27be1f14082a2f40e2d7f53b5e512 (commit)
via 83d9d50018d7a2cf6b1850cfa732323e69c1d411 (commit)
via fc64e5bbe8b9f06f5073e461590e0013c184889c (commit)
via 6312ca7fc3a9cd0ed0a7b15583161a814162a7c4 (commit)
via 5d3ce61a456ae34baf4d16ed5eab7eb2b22251b3 (commit)
via efc0544bdf19f781e928c4cc6f764439ebc5e414 (commit)
via de8d385ff22a2e60e26667a2138dce54677b59e4 (commit)
via 83d8c2ef2fa7b9e4b9a71f9f7ad54c1fa945696d (commit)
via c1233a28b0dfd3f287897a17542a3874f5401ddb (commit)
via 1adbd6a03cb9827f87be0496d71718fb1c9b6cb2 (commit)
via a04f885fad995fb689bd064cf024ee60a71625de (commit)
via f23495620fafe83545866d6cdac59e3660365253 (commit)
via 28ebeea1c461508fbca3995e34509b2c63a102a2 (commit)
via e6750157521cadc40bbe57db8d1cdda8328effa9 (commit)
via f31569d8589dc7dbbcd46a423e67ba3ba9132e87 (commit)
via 5ace1ac933c66fea6c727d062c402677584c1f5b (commit)
via 20f4fc2b067a6c4969cfded667e6a0d7ad90e1dc (commit)
via e2e93cd2354580d7707c07f8f73e07e0e27f18c0 (commit)
via 60aa5f582f596951f0e14e73164f53edc4f8b8e7 (commit)
via 7c623395e4217f10a57a7c312c2e4066ac7c77bd (commit)
via 90251f717001cf297ea3e203777918b8614b2f0d (commit)
via 4ea6a9c51663de36095fa119698ded5f42d70690 (commit)
via 4246e4ed383f3178287eeac97807b52563592f2f (commit)
via 9925af3b3f4daa47ba8c2eb66f556b01ed6f0502 (commit)
via a09e9bd49e0dfa6f4eb9b50da0e1d8b7e76affa2 (commit)
via cfc683caf3aa9c700a7b10ab689d949ffae2d207 (commit)
via 4162a63acb076e595b004e862b4f117a184156b1 (commit)
via e3fec3af0e4ce88e51f52d9dd3388a63e78e0b90 (commit)
via b63f18150df8c3449b7b6b52b3228863e6104474 (commit)
via 27dc1e7a87eb35dfa6a67f44b8ddf2d66d26abab (commit)
via f75fcf0b19faa026baba075f8e76dc5aef4d31da (commit)
via ed259e05b0cef2364c20515f60bf464e5396b3d7 (commit)
via d3d28bdcd3444d16e1ccca67e5127fa732ad3b81 (commit)
via 54cbca7f405db2241d18cd93c63624d573eefb4a (commit)
via 5836dc544cdbe3180f8ce34788e2187824263ea8 (commit)
via 21dae0aa029e8d549c8ba4d5bffeb10ef341f17d (commit)
via 83966d1e3ede61d6e71a26d179e2d2d30b4655df (commit)
via 1e0c42db90fa4f02586da442501cf1669a93db04 (commit)
via e589380dcc531fb2c3d8bf87e0e2fed8ba09270f (commit)
via 7f486337fadd80b4529e927bed9ed809f8658cdf (commit)
via cdb634f118607f9730c7218cc15773fb35a7309a (commit)
via 44fab7f71b9e197762f3ce95bd79dc70cf4f7a47 (commit)
via d5b8d3d8ddea4161a63f0653d1a56dffe2297bdc (commit)
via 0da895c79de752795279c4babfb7578d409c6d72 (commit)
via cd98bdae788fd3871f568b99d9bda61b76879f7f (commit)
via 845ffd35d10646345dc1f534ad725cada568fa5c (commit)
via ce19b150c67834a91d7742f362a175904172a7d7 (commit)
via 01d2ac16e2edab2b81294cd8974938226dd76953 (commit)
via 80b1a680ca8b5ac8eda1b0b6ccb665e243e34182 (commit)
via 77af0818a39b800189928ae950839a43f3d8f2d9 (commit)
via e86811d1938f1f16fc7ecf44d09b08ad9058a756 (commit)
via 1e653cb517d99f96a7eed74a8ca457fe2332a15e (commit)
via 2b9c6a45464d5c064012984665bd3141c4aded27 (commit)
via 77520e9dda0fc9cac5bbd8bdf7225ecc52bd8ed5 (commit)
via 0abfd1c9e17568e36411cfc30e5e084fa84c92df (commit)
via 788685826e01b05cdb12c78bf367192d0139745c (commit)
via 221bb9df74bd6b827ea7dbc13cf07abb3ba939c9 (commit)
via ada6840f0a21dfb6368a22d59e2a24c815eaf997 (commit)
via e363285144493f03d8ba898cf762fc8bccf2f4a9 (commit)
via e1725e2609322cd2c87b0d90bf85b6c5b647dd66 (commit)
via 2133c6ae39aef257ad8c46bbffd0765de83bdce8 (commit)
via f597ce3956c82c48cd5c3623c18bfd01b506047c (commit)
via b6d51351a7935aeddcf3520e33dc5bf5e58a84a7 (commit)
via 544b01dd9fe18dd5ddb914239e5435854042b0d5 (commit)
via 10c4a13810da974778a046128414e392d9395d02 (commit)
via 97d4ccea5736cdc872913ba633154323c17a0e49 (commit)
via 21e0ea894b81e5b6ac02c369b89456b8d8bae9cb (commit)
via 2fb30723fa35fa5a9ffae03b0715650a76a5f20a (commit)
via b58a4e5e12ee86e6ece24e90bc2f1e854cd92527 (commit)
via 86ac11a23c5c1c50b3d8daf1932103476674c72c (commit)
via b377f3a03ff6d2ba7b1fc562ae75707ddff310c7 (commit)
via 6085d54e697681307b4a5f60d169c9e4110c8286 (commit)
via 0cbbce437ec709e5dde8056c0462d7bd501f65c9 (commit)
via e0c71421f186a8cf77f1bf7aba7aff072a9caff7 (commit)
via 532c36304e8b5caf9faf9e98a66967c1073f5353 (commit)
via 27b34684dc5476292dc1f35c430c4509847fd31e (commit)
from eb8aaf5c3b048047cd1cc138ee4951405bb59ce3 (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 9d00667f84006fc001b04953519e78b1ee5f0010
Author: Naoki Kambe <kambe at jprs.co.jp>
Date: Thu Apr 4 20:12:59 2013 +0900
[2252] update the note to more accurate one due to bug #2879
commit d7885ecddb52be49de729021a70b42e60aca2cea
Author: Naoki Kambe <kambe at jprs.co.jp>
Date: Thu Apr 4 14:13:15 2013 +0900
[2252] add an exceptional case when checking initial statistics of Xfrout
Sometime an unixdomain socket could be already opened at the first
time when stats daemon queries xfrout statistics.
commit 1f578c9b208b0fb2e58b101d537a9d07f66ad690
Author: Naoki Kambe <kambe at jprs.co.jp>
Date: Thu Apr 4 13:37:31 2013 +0900
[2252] parameterize for the domain name not to be contained in queried statistics
commit 4f63e23b7aac425bafd4e0c6e5c4099b157206c5
Author: Naoki Kambe <kambe at jprs.co.jp>
Date: Thu Apr 4 12:00:59 2013 +0900
[2252] correct the wrong number of columns to be mentioned
commit a4b1c8d4bb37b273c9027f41b00eeae54ad2f83d
Author: Naoki Kambe <kambe at jprs.co.jp>
Date: Mon Apr 1 22:47:09 2013 +0900
[2252] update case names and their docstrings according to the tested counters
commit 4a8316ddc1bff361a289ed8c406bbe90fde79e16
Author: Naoki Kambe <kambe at jprs.co.jp>
Date: Mon Apr 1 22:46:44 2013 +0900
[2252] update the test cases due to the previous change
test_do_soacheck_uptodate() and test_do_xfrin_uptodate() are updated
for a failure case. test_do_xfrin_fail() is removed for duplicate
cases.
commit 5c0c1cb8f090edf516c21cf03506075bd866915c
Author: Naoki Kambe <kambe at jprs.co.jp>
Date: Mon Apr 1 21:47:06 2013 +0900
[2252] change positions for counters to be counted
xfrsuccess is counted if requesting an xfr succeeds, otherwise xfrfail
is counted. also counters such as axfrreqv4, axfrreqv6, ixfrreqv4,
and ixfrreqv6 are counted before requesting an xfr.
commit e346959d031b0ce05939f801e83f653892757e49
Author: Naoki Kambe <kambe at jprs.co.jp>
Date: Mon Apr 1 19:37:09 2013 +0900
[2252] update datetime to always return fixed seconds
The datetime object is replaced with a fake one which always returns fixed
seconds. This produces a same result independent on an actual time frame.
commit 60b242c2d161e30a05236fb6dae3ff21daa0b6b8
Author: Naoki Kambe <kambe at jprs.co.jp>
Date: Fri Mar 29 17:38:02 2013 +0900
[2252] remove STATS_SEND_STATISTICS_REQUEST
It is not constant whether STATS_SEND_STATISTICS_REQUEST or
XFRIN_RECEIVED_COMMAND (XFROUT_RECEIVED_GETSTATS_COMMAND) comes
first. It is not reliable to check the former one prior to the latter
one. Eventually the latter one is an important event so the former
one is removed.
commit 307e3c7a946a593945050b9ea8159df85f5cf28d
Author: Naoki Kambe <kambe at jprs.co.jp>
Date: Thu Mar 28 19:41:41 2013 +0900
[2252] reorder by tools/reorder_message_file.py
commit 2e97db1d7db5a65bc19f6909269ae930d2e8da18
Author: Naoki Kambe <kambe at jprs.co.jp>
Date: Thu Mar 28 17:39:16 2013 +0900
[2252] correct a wrong word
commit 4d5c20e29fd4a74db31024bdcdaa99d431af3219
Author: Naoki Kambe <kambe at jprs.co.jp>
Date: Thu Mar 28 20:09:55 2013 +0900
[2252] update descriptions of last_*xfr_duration
about the case that a started timer is never stopped due to failure
commit 20df0b0ce702241ce8265690388483c5ece3eb16
Author: Naoki Kambe <kambe at jprs.co.jp>
Date: Fri Mar 29 13:14:26 2013 +0900
[2252] update descriptions of zonename
it doesn't distinguish zone classes.
commit ff8d95f4e0afc3d2b8fc5f3e75eb41edee1f969e
Author: Naoki Kambe <kambe at jprs.co.jp>
Date: Thu Mar 28 18:39:04 2013 +0900
[2252] update descriptions
consider an exceptional case that transferring is done in less than a
microsecond
commit 678965be5a2ca3ba12981884e48911028953f853
Author: Naoki Kambe <kambe at jprs.co.jp>
Date: Thu Mar 28 18:09:09 2013 +0900
[2252] change to better names; s/lastest/last/i
commit 836fabb60589aaf7b901176892b6c28ab464e8d6
Merge: eb8aaf5 b59d780
Author: Naoki Kambe <kambe at jprs.co.jp>
Date: Thu Mar 28 19:30:42 2013 +0900
[2252] Merge branch 'master' of git://git.bind10.isc.org/bind10 into trac2252
Conflicts:
tests/lettuce/features/xfrin_notify_handling.feature
-----------------------------------------------------------------------
Summary of changes:
AUTHORS | 1 +
ChangeLog | 95 ++
Makefile.am | 5 -
README | 6 +
configure.ac | 41 +-
doc/design/cc-protocol.txt | 377 ++---
doc/devel/01-dns.dox | 2 +-
doc/devel/02-dhcp.dox | 2 +-
examples/README | 2 +-
examples/host/host.cc | 2 +-
src/bin/auth/auth_messages.mes | 9 +-
src/bin/auth/auth_srv.cc | 26 +-
src/bin/auth/auth_srv.h | 2 +-
src/bin/auth/gen-statisticsitems.py.pre.in | 2 +-
src/bin/auth/query.cc | 2 +-
src/bin/auth/query.h | 4 +-
src/bin/auth/tests/auth_srv_unittest.cc | 182 ++-
src/bin/bind10/TODO | 2 +-
src/bin/bind10/init.py.in | 5 +-
src/bin/bind10/init_messages.mes | 6 +-
src/bin/bind10/tests/init_test.py.in | 10 +
src/bin/bindctl/README | 2 +-
src/bin/bindctl/bindcmd.py | 59 +-
src/bin/bindctl/tests/bindctl_test.py | 60 +-
src/bin/cfgmgr/plugins/datasrc.spec.pre.in | 5 +
src/bin/cfgmgr/plugins/tests/datasrc_test.py | 97 +-
src/bin/cfgmgr/plugins/tests/tsig_keys_test.py | 2 +-
src/bin/cmdctl/Makefile.am | 6 +-
src/bin/cmdctl/b10-certgen.cc | 6 +-
src/bin/cmdctl/cmdctl.py.in | 33 +-
src/bin/cmdctl/tests/Makefile.am | 2 +-
src/bin/cmdctl/tests/b10-certgen_test.py | 5 +-
src/bin/cmdctl/tests/cmdctl_test.py | 195 ++-
src/bin/dbutil/dbutil.py.in | 2 +-
src/bin/dbutil/tests/dbutil_test.sh.in | 44 +-
src/bin/ddns/ddns.py.in | 8 +-
src/bin/ddns/ddns_messages.mes | 2 +-
src/bin/ddns/tests/ddns_test.py | 8 +-
src/bin/dhcp4/ctrl_dhcp4_srv.cc | 2 +-
src/bin/dhcp4/ctrl_dhcp4_srv.h | 2 +-
src/bin/dhcp4/dhcp4.dox | 2 +-
src/bin/dhcp4/tests/config_parser_unittest.cc | 8 +-
src/bin/dhcp6/ctrl_dhcp6_srv.cc | 2 +-
src/bin/dhcp6/ctrl_dhcp6_srv.h | 2 +-
src/bin/dhcp6/dhcp6.dox | 2 +-
src/bin/dhcp6/dhcp6_srv.cc | 2 +-
src/bin/dhcp6/tests/config_parser_unittest.cc | 8 +-
src/bin/loadzone/tests/correct/correct_test.sh.in | 2 +-
src/bin/loadzone/tests/correct/ttlext.db | 2 +-
src/bin/loadzone/tests/loadzone_test.py | 2 +-
src/bin/msgq/Makefile.am | 1 +
src/bin/msgq/msgq.py.in | 31 +-
src/bin/msgq/run_msgq.sh.in | 2 +-
src/bin/msgq/tests/Makefile.am | 6 +-
src/bin/msgq/tests/msgq_run_test.py | 269 ++++
src/bin/resolver/response_scrubber.h | 4 +-
src/bin/sockcreator/README | 2 +-
src/bin/sockcreator/sockcreator.h | 2 +-
src/bin/sockcreator/tests/sockcreator_tests.cc | 2 +-
src/bin/stats/stats_httpd.py.in | 9 +-
src/bin/stats/stats_httpd_messages.mes | 4 +-
src/bin/stats/tests/b10-stats-httpd_test.py | 2 +-
src/bin/stats/tests/b10-stats_test.py | 4 +-
src/bin/stats/tests/test_utils.py | 2 +-
src/bin/usermgr/Makefile.am | 9 +-
src/bin/usermgr/b10-cmdctl-usermgr.py.in | 299 ++--
src/bin/usermgr/b10-cmdctl-usermgr.xml | 43 +-
src/bin/usermgr/run_b10-cmdctl-usermgr.sh.in | 3 +
src/bin/usermgr/tests/Makefile.am | 22 +
src/bin/usermgr/tests/b10-cmdctl-usermgr_test.py | 483 ++++++
src/bin/xfrin/b10-xfrin.xml | 18 +-
src/bin/xfrin/tests/xfrin_test.py | 100 +-
src/bin/xfrin/xfrin.py.in | 33 +-
src/bin/xfrin/xfrin.spec | 18 +-
src/bin/xfrin/xfrin_messages.mes | 6 +-
src/bin/xfrout/tests/xfrout_test.py.in | 2 +-
src/bin/xfrout/xfrout.py.in | 4 +-
src/bin/xfrout/xfrout_messages.mes | 2 +-
src/bin/zonemgr/tests/zonemgr_test.py | 71 +-
src/bin/zonemgr/zonemgr.py.in | 67 +-
src/bin/zonemgr/zonemgr_messages.mes | 17 +-
src/lib/asiodns/dns_answer.h | 2 +-
src/lib/asiodns/dns_server.h | 2 +-
src/lib/asiodns/io_fetch.h | 2 +-
src/lib/asiodns/sync_udp_server.cc | 8 +-
src/lib/asiodns/tests/dns_server_unittest.cc | 8 +-
src/lib/asiodns/udp_server.cc | 8 +-
src/lib/asiolink/io_asio_socket.h | 2 +-
src/lib/asiolink/tcp_endpoint.h | 2 +-
src/lib/asiolink/tests/tcp_socket_unittest.cc | 2 +-
src/lib/asiolink/tests/udp_socket_unittest.cc | 2 +-
src/lib/asiolink/udp_endpoint.h | 2 +-
src/lib/cc/cc_messages.mes | 2 +-
src/lib/cc/data.h | 4 +-
src/lib/cc/proto_defs.cc | 12 +-
src/lib/cc/session.cc | 52 +-
src/lib/cc/tests/session_unittests.cc | 4 +-
src/lib/config/ccsession.cc | 69 +-
src/lib/config/ccsession.h | 81 +-
src/lib/config/config_messages.mes | 4 +
src/lib/config/documentation.txt | 2 +-
src/lib/config/tests/ccsession_unittests.cc | 54 +-
src/lib/config/tests/fake_session.cc | 13 +-
src/lib/config/tests/fake_session.h | 3 +-
src/lib/datasrc/Makefile.am | 7 +-
src/lib/datasrc/client_list.cc | 38 +-
src/lib/datasrc/client_list.h | 85 +-
src/lib/datasrc/database.h | 2 +-
src/lib/datasrc/datasrc_messages.mes | 125 --
src/lib/datasrc/master_loader_callbacks.h | 2 +-
src/lib/datasrc/memory/domaintree.h | 2 +-
src/lib/datasrc/memory/rdata_serialization.h | 2 +-
src/lib/datasrc/memory/rdataset.h | 9 +-
src/lib/datasrc/memory/zone_data_loader.cc | 42 +-
src/lib/datasrc/memory/zone_data_updater.cc | 44 +-
src/lib/datasrc/memory/zone_finder.cc | 2 +-
src/lib/datasrc/sqlite3_accessor.cc | 3 +-
src/lib/datasrc/sqlite3_accessor_link.cc | 5 +
src/lib/datasrc/sqlite3_datasrc_messages.mes | 142 ++
src/lib/datasrc/tests/Makefile.am | 4 +-
src/lib/datasrc/tests/client_list_unittest.cc | 97 +-
src/lib/datasrc/tests/database_unittest.cc | 2 +-
.../datasrc/tests/memory/memory_client_unittest.cc | 64 +-
.../testdata/example.org-duplicate-type-bad.zone | 5 +-
.../tests/memory/zone_data_updater_unittest.cc | 10 +-
.../datasrc/tests/memory/zone_finder_unittest.cc | 2 +-
src/lib/datasrc/tests/testdata/rrset_toWire2 | 2 +-
src/lib/datasrc/zone_iterator.h | 2 +-
src/lib/dhcp/dhcp6.h | 2 +-
src/lib/dhcp/duid.cc | 4 +-
src/lib/dhcp/duid.h | 4 +-
src/lib/dhcp/libdhcp++.h | 2 +-
src/lib/dhcp/option.h | 4 +-
src/lib/dhcp/option_custom.h | 4 +-
src/lib/dhcp/option_data_types.h | 2 +-
src/lib/dhcp/option_definition.cc | 4 -
src/lib/dhcp/option_definition.h | 26 +-
src/lib/dhcp/option_int.h | 2 +-
src/lib/dhcp/option_int_array.h | 2 +-
src/lib/dhcp/pkt4.h | 2 +-
src/lib/dhcp/pkt6.h | 2 +-
src/lib/dhcp/tests/duid_unittest.cc | 2 +-
src/lib/dhcp/tests/iface_mgr_unittest.cc | 8 +-
src/lib/dhcp/tests/libdhcp++_unittest.cc | 12 +-
src/lib/dhcp/tests/option4_addrlst_unittest.cc | 4 +-
src/lib/dhcp/tests/option_custom_unittest.cc | 6 +-
src/lib/dhcp/tests/option_unittest.cc | 2 +-
src/lib/dhcpsrv/Makefile.am | 1 +
src/lib/dhcpsrv/alloc_engine.cc | 4 +-
src/lib/dhcpsrv/cfgmgr.h | 4 +-
src/lib/dhcpsrv/dbaccess_parser.h | 4 +-
src/lib/dhcpsrv/dhcp_config_parser.h | 2 +-
src/lib/dhcpsrv/dhcpsrv_messages.mes | 2 +-
src/lib/dhcpsrv/key_from_key.h | 82 ++
src/lib/dhcpsrv/lease_mgr.h | 4 +-
src/lib/dhcpsrv/memfile_lease_mgr.cc | 72 +-
src/lib/dhcpsrv/memfile_lease_mgr.h | 113 +-
src/lib/dhcpsrv/mysql_lease_mgr.cc | 32 +-
src/lib/dhcpsrv/mysql_lease_mgr.h | 57 +-
src/lib/dhcpsrv/pool.cc | 11 +-
src/lib/dhcpsrv/pool.h | 5 +-
src/lib/dhcpsrv/subnet.h | 58 +-
.../dhcpsrv/tests/lease_mgr_factory_unittest.cc | 2 +-
src/lib/dhcpsrv/tests/lease_mgr_unittest.cc | 2 +-
src/lib/dhcpsrv/tests/mysql_lease_mgr_unittest.cc | 22 +-
src/lib/dhcpsrv/tests/run_unittests.cc | 1 +
src/lib/dhcpsrv/tests/subnet_unittest.cc | 2 +-
src/lib/dns/gen-rdatacode.py.in | 3 +-
src/lib/dns/messagerenderer.cc | 2 +-
src/lib/dns/python/tests/message_python_test.py | 2 +-
.../python/tests/rrset_collection_python_test.py | 2 +-
src/lib/dns/rdata/generic/afsdb_18.cc | 67 +-
src/lib/dns/rdata/generic/afsdb_18.h | 4 +-
src/lib/dns/tests/rdata_afsdb_unittest.cc | 37 +-
src/lib/dns/tests/testdata/rrset_toWire2 | 2 +-
src/lib/log/logger_manager.cc | 12 +-
src/lib/log/logger_manager.h | 3 +
src/lib/log/logger_unittest_support.cc | 2 +-
src/lib/log/message_initializer.cc | 25 +-
src/lib/log/message_initializer.h | 16 +-
src/lib/log/tests/logger_example.cc | 2 +-
src/lib/log/tests/message_dictionary_unittest.cc | 5 +-
.../log/tests/message_initializer_1_unittest.cc | 34 +
src/lib/nsas/TODO | 2 +-
src/lib/nsas/address_request_callback.h | 2 +-
src/lib/nsas/nameserver_entry.h | 6 +-
src/lib/nsas/tests/hash_unittest.cc | 2 +-
src/lib/nsas/tests/zone_entry_unittest.cc | 4 +-
src/lib/nsas/zone_entry.h | 4 +-
src/lib/python/bind10_config.py.in | 5 +
src/lib/python/isc/bind10/sockcreator.py | 4 +-
src/lib/python/isc/bind10/tests/component_test.py | 2 +-
.../python/isc/bind10/tests/socket_cache_test.py | 4 +-
src/lib/python/isc/cc/Makefile.am | 1 +
src/lib/python/isc/cc/cc_generated/Makefile.am | 1 +
src/lib/python/isc/cc/data.py | 4 +-
src/lib/python/isc/cc/session.py | 43 +-
src/lib/python/isc/cc/tests/session_test.py | 6 +-
src/lib/python/isc/config/ccsession.py | 37 +-
src/lib/python/isc/config/cfgmgr.py | 7 +-
src/lib/python/isc/config/tests/ccsession_test.py | 4 +-
src/lib/python/isc/config/tests/cfgmgr_test.py | 2 +-
src/lib/python/isc/datasrc/datasrc.cc | 4 +
src/lib/python/isc/datasrc/tests/datasrc_test.py | 4 +-
src/lib/python/isc/notify/notify_out.py | 42 +-
src/lib/python/isc/notify/notify_out_messages.mes | 27 +-
src/lib/python/isc/server_common/dns_tcp.py | 4 +-
.../isc/server_common/tests/tsig_keyring_test.py | 2 +-
src/lib/python/isc/statistics/counters.py | 6 +-
.../python/isc/statistics/tests/counters_test.py | 4 +-
.../isc/statistics/tests/testdata/test_spec3.spec | 16 +-
src/lib/python/isc/util/Makefile.am | 3 +-
src/lib/python/isc/util/address_formatter.py | 82 ++
src/lib/python/isc/util/tests/Makefile.am | 3 +-
.../isc/util/tests/address_formatter_test.py | 68 +
src/lib/python/isc/xfrin/diff.py | 22 +-
src/lib/python/isc/xfrin/tests/diff_tests.py | 2 +-
src/lib/resolve/recursive_query.cc | 2 +-
src/lib/server_common/client.cc | 10 +-
src/lib/server_common/client.h | 2 +-
src/lib/server_common/portconfig.cc | 8 +-
src/lib/server_common/server_common_messages.mes | 2 +-
src/lib/server_common/tests/client_unittest.cc | 4 +-
.../server_common/tests/socket_requestor_test.cc | 2 +-
src/lib/util/encode/base16_from_binary.h | 2 +-
src/lib/util/encode/base32hex_from_binary.h | 2 +-
src/lib/util/encode/base_n.cc | 108 +-
src/lib/util/encode/binary_from_base16.h | 2 +-
src/lib/util/encode/binary_from_base32hex.h | 2 +-
src/lib/util/filename.h | 4 +-
src/lib/util/lru_list.h | 2 +-
src/lib/util/python/gen_wiredata.py.in | 4 +-
src/lib/util/tests/io_utilities_unittest.cc | 2 +-
src/lib/util/tests/lru_list_unittest.cc | 2 +-
src/lib/util/unittests/run_all.cc | 2 +-
tests/Makefile.am | 2 +-
tests/lettuce/README | 5 +
.../{no_db_file.config => glue.config} | 12 +-
...nons.conf.orig => retransfer_master_diffs.conf} | 7 +-
...slave.conf.orig => retransfer_slave_diffs.conf} | 12 +-
...tify.conf => retransfer_slave_notify.conf.orig} | 0
.../lettuce/data/glue.sqlite3 | Bin 13312 -> 17408 bytes
.../lettuce/data/xfrin-before-diffs.sqlite3.orig | Bin 15360 -> 15360 bytes
tests/lettuce/data/xfrin-diffs.sqlite3 | Bin 0 -> 407552 bytes
tests/lettuce/features/example.feature | 6 +-
tests/lettuce/features/queries.feature | 72 +
tests/lettuce/features/terrain/bind10_control.py | 28 +-
tests/lettuce/features/terrain/nsupdate.py | 2 +-
tests/lettuce/features/terrain/querying.py | 2 +-
tests/lettuce/features/terrain/steps.py | 12 +-
tests/lettuce/features/terrain/terrain.py | 81 +-
tests/lettuce/features/xfrin_bind10.feature | 57 +-
.../lettuce/features/xfrin_notify_handling.feature | 224 ++-
tests/system/.gitignore | 2 -
tests/system/Makefile.am | 16 -
tests/system/README | 64 -
tests/system/bindctl/clean.sh | 20 -
tests/system/bindctl/nsx1/.gitignore | 3 -
.../system/bindctl/nsx1/b10-config.db.template.in | 29 -
tests/system/bindctl/nsx1/example-normalized.db | 3 -
tests/system/bindctl/nsx1/root.db | 25 -
tests/system/bindctl/setup.sh | 26 -
tests/system/bindctl/tests.sh | 238 ---
tests/system/cleanall.sh | 36 -
tests/system/common/default_user.csv | 1 -
tests/system/common/rndc.conf | 25 -
tests/system/common/rndc.key | 22 -
tests/system/conf.sh.in | 73 -
tests/system/glue/.gitignore | 1 -
tests/system/glue/auth.good | 15 -
tests/system/glue/clean.sh | 23 -
tests/system/glue/example.good | 22 -
tests/system/glue/noglue.good | 14 -
tests/system/glue/nsx1/.gitignore | 3 -
tests/system/glue/nsx1/b10-config.db.in | 36 -
tests/system/glue/nsx1/com.db | 31 -
tests/system/glue/nsx1/net.db | 32 -
tests/system/glue/nsx1/root-servers.nil.db | 26 -
tests/system/glue/nsx1/root.db | 53 -
tests/system/glue/setup.sh.in | 25 -
tests/system/glue/test.good | 19 -
tests/system/glue/tests.sh | 68 -
tests/system/ifconfig.sh | 226 ---
tests/system/ixfr/.gitignore | 8 -
tests/system/ixfr/README | 86 --
tests/system/ixfr/b10-config.db.in | 51 -
tests/system/ixfr/clean_ns.sh | 28 -
tests/system/ixfr/common_tests.sh.in | 78 -
tests/system/ixfr/db.example.common | 1556 --------------------
tests/system/ixfr/db.example.n0.in | 29 -
tests/system/ixfr/db.example.n2.in | 28 -
tests/system/ixfr/db.example.n2.refresh.in | 28 -
tests/system/ixfr/db.example.n4.in | 31 -
tests/system/ixfr/db.example.n6.in | 29 -
tests/system/ixfr/in-1/.gitignore | 1 -
tests/system/ixfr/in-1/clean.sh | 1 -
tests/system/ixfr/in-1/ns1/README | 3 -
tests/system/ixfr/in-1/nsx2/README | 3 -
tests/system/ixfr/in-1/setup.sh.in | 30 -
tests/system/ixfr/in-1/tests.sh | 37 -
tests/system/ixfr/in-2/.gitignore | 1 -
tests/system/ixfr/in-2/clean.sh | 1 -
tests/system/ixfr/in-2/ns1/.gitignore | 1 -
tests/system/ixfr/in-2/ns1/README | 3 -
tests/system/ixfr/in-2/nsx2/.gitignore | 1 -
tests/system/ixfr/in-2/nsx2/README | 3 -
tests/system/ixfr/in-2/setup.sh.in | 29 -
tests/system/ixfr/in-2/tests.sh | 81 -
tests/system/ixfr/in-3/.gitignore | 1 -
tests/system/ixfr/in-3/clean.sh | 1 -
tests/system/ixfr/in-3/ns1/README | 3 -
tests/system/ixfr/in-3/nsx2/README | 3 -
tests/system/ixfr/in-3/setup.sh.in | 29 -
tests/system/ixfr/in-3/tests.sh | 66 -
tests/system/ixfr/in-4/.gitignore | 1 -
tests/system/ixfr/in-4/clean.sh | 1 -
tests/system/ixfr/in-4/ns1/README | 3 -
tests/system/ixfr/in-4/nsx2/README | 3 -
tests/system/ixfr/in-4/setup.sh.in | 30 -
tests/system/ixfr/in-4/tests.sh | 53 -
tests/system/ixfr/ixfr_init.sh.in | 330 -----
tests/system/ixfr/named_noixfr.conf | 42 -
tests/system/ixfr/named_nonotify.conf | 40 -
tests/system/ixfr/named_notify.conf | 41 -
tests/system/run.sh.in | 125 --
tests/system/runall.sh | 44 -
tests/system/start.pl | 229 ---
tests/system/stop.pl | 188 ---
tests/tools/badpacket/option_info.h | 2 +-
tests/tools/dhcp-ubench/benchmark.h | 2 +-
tests/tools/dhcp-ubench/dhcp-perf-guide.xml | 8 +-
tests/tools/perfdhcp/command_options.cc | 2 +-
tests/tools/perfdhcp/command_options.h | 2 +-
tests/tools/perfdhcp/stats_mgr.h | 8 +-
tests/tools/perfdhcp/test_control.cc | 2 +-
tests/tools/perfdhcp/test_control.h | 12 +-
.../tools/perfdhcp/tests/command_options_helper.h | 2 +-
.../perfdhcp/tests/command_options_unittest.cc | 2 +-
tests/tools/perfdhcp/tests/stats_mgr_unittest.cc | 2 +-
.../tools/perfdhcp/tests/test_control_unittest.cc | 2 +-
tools/query_cmp/src/lib/compare_rrset.py | 2 +-
tools/reorder_message_file.py | 2 +-
342 files changed, 4286 insertions(+), 6156 deletions(-)
create mode 100644 src/bin/msgq/tests/msgq_run_test.py
mode change 100644 => 100755 src/bin/usermgr/b10-cmdctl-usermgr.py.in
mode change 100644 => 100755 src/bin/usermgr/run_b10-cmdctl-usermgr.sh.in
create mode 100644 src/bin/usermgr/tests/Makefile.am
create mode 100644 src/bin/usermgr/tests/b10-cmdctl-usermgr_test.py
create mode 100644 src/lib/datasrc/sqlite3_datasrc_messages.mes
create mode 100644 src/lib/dhcpsrv/key_from_key.h
create mode 100644 src/lib/python/isc/util/address_formatter.py
create mode 100644 src/lib/python/isc/util/tests/address_formatter_test.py
copy tests/lettuce/configurations/{no_db_file.config => glue.config} (74%)
copy tests/lettuce/configurations/xfrin/{retransfer_master_nons.conf.orig => retransfer_master_diffs.conf} (81%)
copy tests/lettuce/configurations/xfrin/{retransfer_slave.conf.orig => retransfer_slave_diffs.conf} (71%)
rename tests/lettuce/configurations/xfrin/{retransfer_slave_notify.conf => retransfer_slave_notify.conf.orig} (100%)
copy src/bin/dbutil/tests/testdata/empty_version.sqlite3 => tests/lettuce/data/glue.sqlite3 (56%)
copy src/bin/dbutil/tests/testdata/v2_1.sqlite3 => tests/lettuce/data/xfrin-before-diffs.sqlite3.orig (72%)
create mode 100644 tests/lettuce/data/xfrin-diffs.sqlite3
delete mode 100644 tests/system/.gitignore
delete mode 100644 tests/system/Makefile.am
delete mode 100644 tests/system/README
delete mode 100755 tests/system/bindctl/clean.sh
delete mode 100644 tests/system/bindctl/nsx1/.gitignore
delete mode 100644 tests/system/bindctl/nsx1/b10-config.db.template.in
delete mode 100644 tests/system/bindctl/nsx1/example-normalized.db
delete mode 100644 tests/system/bindctl/nsx1/root.db
delete mode 100755 tests/system/bindctl/setup.sh
delete mode 100755 tests/system/bindctl/tests.sh
delete mode 100755 tests/system/cleanall.sh
delete mode 100644 tests/system/common/default_user.csv
delete mode 100644 tests/system/common/rndc.conf
delete mode 100644 tests/system/common/rndc.key
delete mode 100755 tests/system/conf.sh.in
delete mode 100644 tests/system/glue/.gitignore
delete mode 100644 tests/system/glue/auth.good
delete mode 100755 tests/system/glue/clean.sh
delete mode 100644 tests/system/glue/example.good
delete mode 100644 tests/system/glue/noglue.good
delete mode 100644 tests/system/glue/nsx1/.gitignore
delete mode 100644 tests/system/glue/nsx1/b10-config.db.in
delete mode 100644 tests/system/glue/nsx1/com.db
delete mode 100644 tests/system/glue/nsx1/net.db
delete mode 100644 tests/system/glue/nsx1/root-servers.nil.db
delete mode 100644 tests/system/glue/nsx1/root.db
delete mode 100755 tests/system/glue/setup.sh.in
delete mode 100644 tests/system/glue/test.good
delete mode 100755 tests/system/glue/tests.sh
delete mode 100755 tests/system/ifconfig.sh
delete mode 100644 tests/system/ixfr/.gitignore
delete mode 100644 tests/system/ixfr/README
delete mode 100644 tests/system/ixfr/b10-config.db.in
delete mode 100644 tests/system/ixfr/clean_ns.sh
delete mode 100644 tests/system/ixfr/common_tests.sh.in
delete mode 100644 tests/system/ixfr/db.example.common
delete mode 100644 tests/system/ixfr/db.example.n0.in
delete mode 100644 tests/system/ixfr/db.example.n2.in
delete mode 100644 tests/system/ixfr/db.example.n2.refresh.in
delete mode 100644 tests/system/ixfr/db.example.n4.in
delete mode 100644 tests/system/ixfr/db.example.n6.in
delete mode 100644 tests/system/ixfr/in-1/.gitignore
delete mode 120000 tests/system/ixfr/in-1/clean.sh
delete mode 100644 tests/system/ixfr/in-1/ns1/README
delete mode 100644 tests/system/ixfr/in-1/nsx2/README
delete mode 100644 tests/system/ixfr/in-1/setup.sh.in
delete mode 100644 tests/system/ixfr/in-1/tests.sh
delete mode 100644 tests/system/ixfr/in-2/.gitignore
delete mode 120000 tests/system/ixfr/in-2/clean.sh
delete mode 100644 tests/system/ixfr/in-2/ns1/.gitignore
delete mode 100644 tests/system/ixfr/in-2/ns1/README
delete mode 100644 tests/system/ixfr/in-2/nsx2/.gitignore
delete mode 100644 tests/system/ixfr/in-2/nsx2/README
delete mode 100644 tests/system/ixfr/in-2/setup.sh.in
delete mode 100644 tests/system/ixfr/in-2/tests.sh
delete mode 100644 tests/system/ixfr/in-3/.gitignore
delete mode 120000 tests/system/ixfr/in-3/clean.sh
delete mode 100644 tests/system/ixfr/in-3/ns1/README
delete mode 100644 tests/system/ixfr/in-3/nsx2/README
delete mode 100644 tests/system/ixfr/in-3/setup.sh.in
delete mode 100644 tests/system/ixfr/in-3/tests.sh
delete mode 100644 tests/system/ixfr/in-4/.gitignore
delete mode 120000 tests/system/ixfr/in-4/clean.sh
delete mode 100644 tests/system/ixfr/in-4/ns1/README
delete mode 100644 tests/system/ixfr/in-4/nsx2/README
delete mode 100644 tests/system/ixfr/in-4/setup.sh.in
delete mode 100644 tests/system/ixfr/in-4/tests.sh
delete mode 100644 tests/system/ixfr/ixfr_init.sh.in
delete mode 100644 tests/system/ixfr/named_noixfr.conf
delete mode 100644 tests/system/ixfr/named_nonotify.conf
delete mode 100644 tests/system/ixfr/named_notify.conf
delete mode 100755 tests/system/run.sh.in
delete mode 100755 tests/system/runall.sh
delete mode 100755 tests/system/start.pl
delete mode 100755 tests/system/stop.pl
-----------------------------------------------------------------------
diff --git a/AUTHORS b/AUTHORS
index 67cb090..b915e25 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -14,6 +14,7 @@ Michael Graff
Michal Vaner
Mukund Sivaraman
Naoki Kambe
+Paul Selkirk
Shane Kerr
Shen Tingting
Stephen Morris
diff --git a/ChangeLog b/ChangeLog
index d7af227..f2b742c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,98 @@
+594. [func] muks, pselkirk
+ libdns++: the NSEC, DS, DLV, and AFSDB Rdata classes now use the
+ generic lexer in constructors from text. This means that the name
+ fields in such RRs in a zone file can now be non-absolute (the
+ origin name in that context will be used), e.g., when loaded by
+ b10-loadzone.
+ (Trac #2386, git dc0f34afb1eccc574421a802557198e6cd2363fa)
+ (Trac #2391, git 1450d8d486cba3bee8be46e8001d66898edd370c)
+
+593. [func] jelte
+ Address + port output and logs is now consistent according to our
+ coding guidelines, e.g. <address>:<port> in the case of IPv4, and
+ [<address>]:<port> in the case of IPv6, instead of <address>#<port>
+ (Trac #1086, git bcefe1e95cdd61ee4a09b20522c3c56b315a1acc)
+
+592. [bug] jinmei
+ b10-auth and zonemgr now handle some uncommon NOTIFY messages more
+ gracefully: auth immediately returns a NOTAUTH response if the
+ server does not have authority for the zone (the behavior
+ compatible with BIND 9) without bothering zonemgr; zonemgr now
+ simply skips retransfer if the specified zone is not in its
+ secondary zone list, instead of producing noisy error logs.
+ (Trac #1938, git 89d7de8e2f809aef2184b450e7dee1bfec98ad14)
+
+591. [func] vorner
+ Ported the remaining tests from the old shell/perl based system to
+ lettuce. Make target `systest' is now gone. Currently, the lettuce
+ tests are in git only, not part of the release tarball.
+ (Trac #2624, git df1c5d5232a2ab551cd98b77ae388ad568a683ad)
+
+590. [bug] tmark
+ Modified "include" statements in DHCP MySQL lease manager code to
+ fix build problems if MySQL is installed in a non-standard location.
+ (Trac #2825, git 4813e06cf4e0a9d9f453890557b639715e081eca)
+
+589. [bug] jelte
+ b10-cmdctl now automatically re-reads the user accounts file when
+ it is updated.
+ (Trac #2710, git 16e8be506f32de668699e6954f5de60ca9d14ddf)
+
+588. [bug]* jreed
+ b10-xfrout: Log message id XFROUT_QUERY_QUOTA_EXCCEEDED
+ changed to XFROUT_QUERY_QUOTA_EXCEEDED.
+ (git be41be890f1349ae4c870a887f7acd99ba1eaac5)
+
+587. [bug] jelte
+ When used from python, the dynamic datasource factory now
+ explicitely loads the logging messages dictionary, so that correct
+ logging messages does not depend on incidental earlier import
+ statements. Also, the sqlite3-specific log messages have been moved
+ from the general datasource library to the sqlite3 datasource
+ (which also explicitely loads its messages).
+ (Trac 2746, git 1c004d95a8b715500af448683e4a07e9b66ea926)
+
+586. [func] marcin
+ libdhcp++: Removed unnecesary calls to the function which
+ validates option definitions used to create instances of options
+ being decoded in the received packets. Eliminating these calls
+ lowered the CPU utilization by the server by approximately 10%.
+ Also, added the composite search indexes on the container used to
+ store DHCP leases by Memfile backend. This resulted in the
+ significant performance rise when using this backend to store
+ leases.
+ (Trac #2701, git b96a30b26a045cfaa8ad579b0a8bf84f5ed4e73f)
+
+585. [func] jinmei, muks
+ The zone data loader now accepts RRs in any order during load.
+ Before it used to reject adding non-consecutive RRsets. It
+ expected records for a single owner name and its type to be
+ grouped together. These restrictions are now removed. It now also
+ suppresses any duplicate RRs in the zone file when loading them
+ into memory.
+ (Trac #2440, git 232307060189c47285121f696d4efb206f632432)
+ (Trac #2441, git 0860ae366d73314446d4886a093f4e86e94863d4)
+
+584. [bug] jinmei
+ Fixed build failure with Boost 1.53 (and probably higher) in the
+ internal utility library. Note that with -Werror it may still
+ fail, but it's due to a Boost bug that is reportedly fixed in their
+ development trunk. See https://svn.boost.org/trac/boost/ticket/8080
+ Until the fix is available in a released Boost version you may need
+ to specify the --without-werror configure option to build BIND 10.
+ (Trac #2764, git ca1da8aa5de24358d7d4e7e9a4625347457118cf)
+
+583. [func]* jelte
+ b10-cmdctl-usermgr has been updated and its options and arguments
+ have changed; it now defaults to the same accounts file as
+ b10-cmdctl defaults to. It can now be used to remove users from the
+ accounts file as well, and it now accepts command-line arguments to
+ specify the username and password to add or remove, in which case
+ it will not prompt for them.
+ Note that using a password on the command line is not recommended,
+ as this can be viewed by other users.
+ (Trac #2713, git 9925af3b3f4daa47ba8c2eb66f556b01ed6f0502)
+
582. [func] naokikambe
New statistics items related unixdomain sockets added into Xfrout :
open, openfail, close, bindfail, acceptfail, accept, senderr, and
diff --git a/Makefile.am b/Makefile.am
index fe995a7..8e01f4a 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -115,11 +115,6 @@ cppcheck:
--template '{file}:{line}: check_fail: {message} ({severity},{id})' \
src
-# system tests
-systest:
- cd tests/system; \
- sh $(abs_srcdir)/tests/system/runall.sh
-
### include tool to generate documentation from log message specifications
### in the distributed tarball:
EXTRA_DIST = tools/system_messages.py
diff --git a/README b/README
index 70c6bee..f9b24c5 100644
--- a/README
+++ b/README
@@ -25,6 +25,12 @@ 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
+NOTE: The API/ABI provided by libraries in BIND 10 may change in future
+point releases. So please do not assume currently that any code that you
+compile for a particular version of a BIND 10 library will work in
+future versions of the library. We aim to stabilize the public API/ABI
+interface of BIND 10 libraries in future releases.
+
Documentation is included with the source. See doc/guide/bind10-guide.txt
(or bind10-guide.html) for installation instructions. The
documentation is also available via the BIND 10 website at
diff --git a/configure.ac b/configure.ac
index f2bdf0b..eff05ec 100644
--- a/configure.ac
+++ b/configure.ac
@@ -323,9 +323,9 @@ if test -x ${PYTHON}-config; then
# so we only go through the flag if it's contained; also, protecting
# the output with [] seems necessary for environment to avoid getting
# an empty output accidentally.
- python_config_ldflags=[`${PYTHON}-config --ldflags | sed -ne 's/\([ \t]*-L\)[ ]*\([^ \t]*[ \t]*\)/\1\2/pg'`]
+ python_config_ldflags=[`${PYTHON}-config --ldflags | ${SED} -ne 's/\([ \t]*-L\)[ ]*\([^ \t]*[ \t]*\)/\1\2/gp'`]
for flag in $python_config_ldflags; do
- flag=`echo $flag | sed -ne 's/^\(\-L.*\)$/\1/p'`
+ flag=`echo $flag | ${SED} -ne 's/^\(\-L.*\)$/\1/p'`
if test "X${flag}" != X; then
PYTHON_LDFLAGS="$PYTHON_LDFLAGS ${flag}"
fi
@@ -351,7 +351,7 @@ fi
if test "x$ISC_RPATH_FLAG" != "x"; then
python_rpath=
for flag in ${PYTHON_LDFLAGS}; do
- python_rpath="${python_rpath} `echo $flag | sed -ne "s/^\(\-L\)/${ISC_RPATH_FLAG}/p"`"
+ python_rpath="${python_rpath} `echo $flag | ${SED} -ne "s/^\(\-L\)/${ISC_RPATH_FLAG}/p"`"
done
PYTHON_LDFLAGS="${PYTHON_LDFLAGS} ${python_rpath}"
fi
@@ -536,7 +536,7 @@ if test "$lcov" != "no"; then
AC_MSG_ERROR([Cannot find lcov.])
fi
# is genhtml always in the same directory?
- GENHTML=`echo "$LCOV" | sed s/lcov$/genhtml/`
+ GENHTML=`echo "$LCOV" | ${SED} s/lcov$/genhtml/`
if test ! -x $GENHTML; then
AC_MSG_ERROR([genhtml not found, needed for lcov])
fi
@@ -712,15 +712,15 @@ fi
BOTAN_LDFLAGS=
BOTAN_NEWLIBS=
for flag in ${BOTAN_LIBS}; do
- BOTAN_LDFLAGS="${BOTAN_LDFLAGS} `echo $flag | sed -ne '/^\(\-L\)/p'`"
- BOTAN_LIBS="${BOTAN_LIBS} `echo $flag | sed -ne '/^\(\-l\)/p'`"
+ BOTAN_LDFLAGS="${BOTAN_LDFLAGS} `echo $flag | ${SED} -ne '/^\(\-L\)/p'`"
+ BOTAN_LIBS="${BOTAN_LIBS} `echo $flag | ${SED} -ne '/^\(\-l\)/p'`"
done
# See python_rpath for some info on why we do this
if test "x$ISC_RPATH_FLAG" != "x"; then
BOTAN_RPATH=
for flag in ${BOTAN_LIBS}; do
- BOTAN_RPATH="${BOTAN_RPATH} `echo $flag | sed -ne "s/^\(\-L\)/${ISC_RPATH_FLAG}/p"`"
+ BOTAN_RPATH="${BOTAN_RPATH} `echo $flag | ${SED} -ne "s/^\(\-L\)/${ISC_RPATH_FLAG}/p"`"
done
AC_SUBST(BOTAN_RPATH)
@@ -1204,6 +1204,7 @@ AC_CONFIG_FILES([Makefile
src/bin/stats/tests/Makefile
src/bin/stats/tests/testdata/Makefile
src/bin/usermgr/Makefile
+ src/bin/usermgr/tests/Makefile
src/bin/tests/Makefile
src/lib/Makefile
src/lib/asiolink/Makefile
@@ -1304,7 +1305,6 @@ AC_CONFIG_FILES([Makefile
src/lib/statistics/Makefile
src/lib/statistics/tests/Makefile
tests/Makefile
- tests/system/Makefile
tests/tools/Makefile
tests/tools/badpacket/Makefile
tests/tools/badpacket/tests/Makefile
@@ -1388,23 +1388,6 @@ AC_OUTPUT([doc/version.ent
src/lib/util/python/gen_wiredata.py
src/lib/server_common/tests/data_path.h
tests/lettuce/setup_intree_bind10.sh
- tests/system/conf.sh
- tests/system/run.sh
- tests/system/glue/setup.sh
- tests/system/glue/nsx1/b10-config.db
- tests/system/bindctl/nsx1/b10-config.db.template
- tests/system/ixfr/db.example.n0
- tests/system/ixfr/db.example.n2
- tests/system/ixfr/db.example.n2.refresh
- tests/system/ixfr/db.example.n4
- tests/system/ixfr/db.example.n6
- tests/system/ixfr/ixfr_init.sh
- tests/system/ixfr/b10-config.db
- tests/system/ixfr/common_tests.sh
- tests/system/ixfr/in-1/setup.sh
- tests/system/ixfr/in-2/setup.sh
- tests/system/ixfr/in-3/setup.sh
- tests/system/ixfr/in-4/setup.sh
], [
chmod +x src/bin/cmdctl/run_b10-cmdctl.sh
chmod +x src/bin/xfrin/run_b10-xfrin.sh
@@ -1435,14 +1418,6 @@ AC_OUTPUT([doc/version.ent
chmod +x src/lib/util/python/mkpywrapper.py
chmod +x src/lib/util/python/gen_wiredata.py
chmod +x src/lib/python/isc/log/tests/log_console.py
- chmod +x tests/system/conf.sh
- chmod +x tests/system/run.sh
- chmod +x tests/system/ixfr/ixfr_init.sh
- chmod +x tests/system/ixfr/common_tests.sh
- chmod +x tests/system/ixfr/in-1/setup.sh
- chmod +x tests/system/ixfr/in-2/setup.sh
- chmod +x tests/system/ixfr/in-3/setup.sh
- chmod +x tests/system/ixfr/in-4/setup.sh
])
AC_OUTPUT
diff --git a/doc/design/cc-protocol.txt b/doc/design/cc-protocol.txt
index 0129530..15db9c1 100644
--- a/doc/design/cc-protocol.txt
+++ b/doc/design/cc-protocol.txt
@@ -1,296 +1,185 @@
-protocol version 0x536b616e
+The CC protocol
+===============
-DATA 0x01
-HASH 0x02
-LIST 0x03
-NULL 0x04
-TYPE_MASK 0x0f
+We use our home-grown protocol for IPC between modules. There's a
+central daemon routing the messages.
-LENGTH_32 0x00
-LENGTH_16 0x10
-LENGTH_8 0x20
-LENGTH_MASK 0xf0
-
-
-MESSAGE ENCODING
-----------------
-
-When decoding, the entire message length must be known. If this is
-transmitted over a raw stream such as TCP, this is usually encoded
-with a 4-byte length followed by the message itself. If some other
-wrapping is used (say as part of a different message structure) the
-length of the message must be preserved and included for decoding.
-
-The first 4 bytes of the message is the protocol version encoded
-directly as a 4-byte value. Immediately following this is a HASH
-element. The length of the hash element is the remainder of the
-message after subtracting 4 bytes for the protocol version.
-
-This initial HASH is intended to be used by the message routing system
-if one is in use.
-
-
-ITEM TYPES
+Addressing
----------
-There are four basic types encoded in this protocol. A simple data
-blob (DATA), a tag-value series (HASH), an ordered list (LIST), and
-a NULL type (which is used internally to encode DATA types which are
-empty and can be used to indicate existance without data in a hash.)
-
-Each item can be of any type, so a hash of hashes and hashes of lists
-are typical.
-
-All multi-byte integers which are encoded in binary are in network
-byte order.
-
-
-ITEM ENCODING
--------------
-
-Each item is preceeded by a single byte which describes that item.
-This byte contains the item type and item length encoding:
-
- Thing Length Description
- ---------------- -------- ------------------------------------
- TyLen 1 byte Item type and length encoding
- Length variable Item data blob length
- Item Data variable Item data blob
-
-The TyLen field includes both the item data type and the item's
-length. The length bytes are encoded depending on the length of data
-portion, and the smallest data encoding type supported should be
-used. Note that this length compression is used just for data
-compactness. It is wasteful to encode the most common length (8-bit
-length) as 4 bytes, so this method allows one byte to be used rather
-than 4, three of which are nearly always zero.
-
-
-HASH
-----
-
-This is a tag/value pair where each tag is an opaque unique blob and
-the data elements are of any type. Hashes are not encoded in any
-specific tag or item order.
-
-The length of the HASH's data area is processed for tag/value pairs
-until the entire area is consumed. Running out of data prematurely
-indicates an incorrectly encoded message.
-
-The data area consists of repeated items:
-
- Thing Length Description
- ---------------- -------- ------------------------------------
- Tag Length 1 byte The length of the tag.
- Tag Variable The tag name
- Item Variable Encoded item
-
-The Tag Length field is always one byte, which limits the tag name to
-255 bytes maximum. A tag length of zero is invalid.
-
-
-LIST
-----
-
-A LIST is a list of items encoded and decoded in a specific order.
-The order is chosen entirely by the source curing encoding.
-
-The length of the LIST's data is consumed by the ITEMs it contains.
-Running out of room prematurely indicates an incorrectly encoded
-message.
-
-The data area consists of repeated items:
+Each connected client gets an unique address, called ``l-name''. A
+message can be sent directly to such l-name, if it is known to the
+sender.
- Thing Length Description
- -------------- ------ ----------------------------------------
- Item Variable Encoded item
+A client may subscribe to a group of communication. A message can be
+broadcasted to a whole group instead of a single client. There's also
+an instance parameter to addressing, but we didn't find any actual use
+for it and it is not used for anything. It is left in the default `*`
+for most of our code and should be done so in any new code. It wasn't
+priority to remove it yet.
+Wire format
+-----------
-DATA
-----
+Each message on the wire looks like this:
-A DATA item is a simple blob of data. No further processing of this
-data is performed by this protocol on these elements.
+ <message length><header length><header><body>
-The data blob is the entire data area. The data area can be 0 or more
-bytes long.
+The message length is 4-byte unsigned integer in network byte order,
+specifying the number of bytes of the rest of the message (eg. header
+length, header and body put together).
-It is typical to encode integers as strings rather than binary
-integers. However, so long as both sender and recipient agree on the
-format of the data blob itself, any blob encoding may be used.
+The header length is 2-byte unsigned integer in network byte order,
+specifying the length of the header.
+The header is a string representation of single JSON object. It
+specifies the type of message and routing information.
-NULL
-----
+The body is the payload of the message. It takes the whole rest of
+size of the message (so its length is message length - 2 - header
+length). The content is not examined by the routing daemon, but the
+clients expect it to be valid JSON object.
-This data element indicates no data is actually present. This can be
-used to indicate that a tag is present in a HASH but no data is
-actually at that location, or in a LIST to indicate empty item
-positions.
+The body may be empty in case the message is not to be routed to
+client, but it is instruction for the routing daemon. See message
+types below.
-There is no data portion of this type, and the encoded length is
-ignored and is always zero.
+The message is sent in this format to the routing daemon, the daemon
+optionally modifies the headers and delivers it in the same format to
+the recipient(s).
-Note that this is different than a DATA element with a zero length.
+The headers
+-----------
+The header object can contain following information:
-EXAMPLE
--------
-
-This is Ruby syntax, but should be clear enough for anyone to read.
-
-Example data encoding:
-
-{
- "from" => "sender at host",
- "to" => "recipient at host",
- "seq" => 1234,
- "data" => {
- "list" => [ 1, 2, nil, "this" ],
- "description" => "Fun for all",
- },
-}
-
-
-Wire-format:
-
-In this format, strings are not shown in hex, but are included "like
-this." Descriptions are written (like this.)
-
-Message Length: 0x64 (100 bytes)
-Protocol Version: 0x53 0x6b 0x61 0x6e
-(remaining length: 96 bytes)
-
-0x04 "from" 0x21 0x0b "sender at host"
-0x02 "to" 0x21 0x0e "recipient at host"
-0x03 "seq" 0x21 0x04 "1234"
-0x04 "data" 0x22
- 0x04 "list" 0x23
- 0x21 0x01 "1"
- 0x21 0x01 "2"
- 0x04
- 0x21 0x04 "this"
- 0x0b "description" 0x0b "Fun for all"
-
-
-MESSAGE ROUTING
----------------
-
-The message routing daemon uses the top-level hash to contain routing
-instructions and additional control data. Not all of these are
-required for various control message types; see the individual
-descriptions for more information.
-
- Tag Description
- ------- ----------------------------------------
- msg Sender-supplied data
- from sender's identity
- group Group name this message is being sent to
- instance Instance in this group
- repl if present, this message is a reply.
- seq sequence number, used in replies
- to recipient or "*" for no specific receiver
- type "send" for a channel message
-
-
-"type" is a DATA element, which indicates to the message routing
-system what the purpose of this message is.
+|====================================================================================================
+|Name |type |Description
+|====================================================================================================
+|from |string|Sender's l-name
+|type |string|Type of the message. The routed message is "send".
+|group |string|The group to deliver to.
+|instance |string|Instance in the group. Purpose lost in history. Defaults to "*".
+|to |string|Override recipient (group/instance ignored).
+|seq |int |Tracking number of the message.
+|reply |int |If present, contains a seq number of message this is a reply to.
+|want_answer|bool |If present and true, the daemon generates error if there's no matching recipient.
+|====================================================================================================
+Types of messages
+-----------------
Get Local Name (type "getlname")
---------------------------------
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-Upon connection, this is the first message to be sent to the control
-daemon. It will return the local name of this client. Each
-connection gets its own unique local name, and local names are never
-repeated. They should be considered opaque strings, in a format
-useful only to the message routing system. They are used in replies
-or to send to a specific destination.
+Upon connection, this is the first message to be sent to the daemon.
+It will return the local name of this client. Each connection gets
+its own unique local name, and local names are never repeated. They
+should be considered opaque strings, in a format useful only to the
+message routing system. They are used in replies or to send to a
+specific destination.
To request the local name, the only element included is the
- "type" => "getlname"
+ {"type": "getlname"}
tuple. The response is also a simple, single tuple:
- "lname" => "UTF-8 encoded local name blob"
+ {"lname" => "Opaque utf-8 string"}
Until this message is sent, no other types of messages may be sent on
this connection.
-
Regular Group Messages (type "send")
-------------------------------------
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-When sending a message:
+Message routed to other client. This one expects the body to be
+non-empty.
-"msg" is the sender supplied data. It is encoded as per its type.
-It is a required field, but may be the NULL type if not needed.
-In OpenReg, this was another wire format message, stored as an
-ITEM_DATA. This was done to make it easy to decode the routing
-information without having to decode arbitrary application-supplied
-data, but rather treat this application data as an opaque blob.
+Expected headers are:
-"from" is a DATA element, and its value is a UTF-8 encoded sender
-identity. It MUST be the "local name" supplied by the message
-routing system upon connection. The message routing system will
-enforce this, but will not add it. It is a required field.
+* from
+* group
+* instance (set to "*" if no specific instance desired)
+* seq (should be unique for the sender)
+* to (set to "*" if not directed to specific client)
+* reply (optional, only if it is reply)
+* want_answer (optional, only when not a reply)
-"group" is a DATA element, and its value is the UTF-8 encoded group
-name this message is being transmitted to. It is a required field for
-all messages of type "send".
+A client does not see its own transmissions.
-"instance" is a DATA element, and its value is the UTF-8 encoded
-instance name, with "*" meaning all instances.
+Group Subscriptions (type "subscribe")
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-"repl" is the sequence number being replied to, if this is a reply.
+Indicates the sender wants to be included in the given group.
-"seq" is a unique identity per client. That is, the <lname, seq>
-tuple must be unique over the lifetime of the connection, or at least
-over the lifetime of the expected reply duration.
+Expected headers are:
-"to" is a DATA element, and its value is a UTF-8 encoded recipient
-identity. This must be a specific recipient name or "*" to indicate
-"all listeners on this channel." It is a required field.
+* group
+* instance (leave at "*" for default)
-When a message of type "send" is received by the client, all the data
-is used as above. This indicates a message of the given type was
-received.
+There is no response to this message and the client is subscribed to
+the given group and instance.
-A client does not see its own transmissions. (XXXMLG Need to check this)
+The group can be any utf-8 string and the group doesn't have to exist
+before (it is created when at least one client is in it). A client may
+be subscribed in multiple groups.
+Group Unsubscribe (type "unsubscribe")
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-Group Subscriptions (type "subscribe")
---------------------------------------
+The headers to be included are "group" and "instance" and have the same
+meaning as a "subscribe" message. Only, the client is removed from the
+group.
-A subscription requires the "group", "instance", and a flag to
-indicate the subscription type ("sybtype"). If instance is "*" the
-instance name will be ignored when decising to forward a message to
-this client or not.
+Transmitted messages
+--------------------
-"subtype" is a DATA element, and contains "normal" for normal channel
-subscriptions, "meonly" for only those messages on a channel with the
-recipient specified exactly as the local name, or "promisc" to receive
-all channel messages regardless of other filters. As its name
-implies, "normal" is for typical subscriptions, and "promisc" is
-intended for channel message debugging.
+These are the messages generally transmitted in the body of the
+message.
-There is no response to this message.
+Command
+~~~~~~~
+It is a command from one process to another, to do something or send
+some information. It is identified by a name and can optionally have
+parameters. It'd look like this:
-Group Unsubscribe (type "unsubscribe")
--------------------------------
+ {"command": ["name", <parameters>]}
+
+The parameters may be omitted (then the array is 1 element long). If
+present, it may be any JSON element. However, the most usual is an
+object with named parameter values.
+
+It is usually transmitted with the `want_answer` header turned on to
+cope with the situation the remote end doesn't exist, and sent to a
+group (eg. `to` with value of `*`).
+
+Success reply
+~~~~~~~~~~~~~
+
+When the command is successful, the other side answers by a reply of
+the following format:
+
+ {"result": [0, <result>]}
+
+The result is the return value of the command. It may be any JSON
+element and it may be omitted (for the case of ``void'' function).
-The fields to be included are "group" and "instance" and have the same
-meaning as a "subscribe" message.
+This is transmitted with the `reply` header set to the `seq` number of
+the original command. It is sent with the `to` header set.
-There is no response to this message.
+Error reply
+~~~~~~~~~~~
+In case something goes wrong, an error reply is sent. This is similar
+as throwing an exception from local function. The format is similar:
-Statistics (type "stats")
--------------------------
+ {"result": [ecode, "Error description"]}
-Request statistics from the message router. No other fields are
-inclued in the request.
+The `ecode` is non-zero error code. Most of the current code uses `1`
+for all errors. The string after that is mandatory and must contain a
+human-readable description of the error.
-The response contains a single element "stats" which is an opaque
-element. This is used mostly for debugging, and its format is
-specific to the message router. In general, some method to simply
-dump raw messages would produce something useful during debugging.
+The negative error codes are reserved for errors from the daemon.
+Currently, only `-1` is used and it is generated when a message with
+`reply` not included is sent, it has the `want_answer` header set to
+`true` and there's no recipient to deliver the message to. This
+usually means a command was sent to a non-existent recipient.
diff --git a/doc/devel/01-dns.dox b/doc/devel/01-dns.dox
index e72dbbd..ed76dea 100644
--- a/doc/devel/01-dns.dox
+++ b/doc/devel/01-dns.dox
@@ -8,7 +8,7 @@
*
* @section b10-cfgmgr b10-cfgmgr Overview
*
- * @todo: Descibe b10-cfgmgr here.
+ * @todo: Describe b10-cfgmgr here.
*
*
*/
diff --git a/doc/devel/02-dhcp.dox b/doc/devel/02-dhcp.dox
index b98920f..ddc5e23 100644
--- a/doc/devel/02-dhcp.dox
+++ b/doc/devel/02-dhcp.dox
@@ -21,7 +21,7 @@
*
* DHCPv4 server component is now integrated with the BIND10 message queue.
* The integration is performed by establishSession() and disconnectSession()
- * functions in isc::dhcp::ControlledDhcpv4Srv class. main() method deifined
+ * functions in isc::dhcp::ControlledDhcpv4Srv class. main() method defined
* in the src/bin/dhcp4/main.cc file instantiates isc::dhcp::ControlledDhcpv4Srv
* class that establishes connection with msgq and install necessary handlers
* for receiving commands and configuration updates. It is derived from
diff --git a/examples/README b/examples/README
index aa5f3c9..e8e7953 100644
--- a/examples/README
+++ b/examples/README
@@ -31,7 +31,7 @@ sinclude(m4/ax_boost_include.m4)
sinclude(m4/ax_isc_bind10.m4)
(and same for other m4 files as they are added under m4/)
-On some systems, espeically if you have installed the BIND 10
+On some systems, especially if you have installed the BIND 10
libraries in an uncommon path, programs linked with the BIND 10
library may not work at run time due to the "missing" shared library.
Normally, you should be able to avoid this problem by making sure
diff --git a/examples/host/host.cc b/examples/host/host.cc
index a5c6522..c5dd604 100644
--- a/examples/host/host.cc
+++ b/examples/host/host.cc
@@ -95,7 +95,7 @@ host_lookup(const char* const name, const char* const dns_class,
cout << "Name: " << server << "\n";
// TODO: I guess I have to do a lookup to get that address and aliases
// too
- //cout << "Address: " << address << "\n" ; // "#" << port << "\n";
+ //cout << "Address: " << address << "\n" ;
//cout << "Aliases: " << server << "\n";
}
diff --git a/src/bin/auth/auth_messages.mes b/src/bin/auth/auth_messages.mes
index 77b20b1..c9b167c 100644
--- a/src/bin/auth/auth_messages.mes
+++ b/src/bin/auth/auth_messages.mes
@@ -266,9 +266,16 @@ bug ticket for this issue.
This is a debug message issued when the authoritative server has received
a command on the command channel.
-% AUTH_RECEIVED_NOTIFY received incoming NOTIFY for zone name %1, zone class %2
+% AUTH_RECEIVED_NOTIFY received incoming NOTIFY for zone %1/%2 from %3
This is a debug message reporting that an incoming NOTIFY was received.
+% AUTH_RECEIVED_NOTIFY_NOTAUTH received bad NOTIFY for zone %1/%2 from %3
+The authoritative server received a NOTIFY message, but the specified zone
+doesn't match any of the zones served by the server. The server doesn't
+process the message further, and returns a response with the Rcode being
+NOTAUTH. Note: RFC 1996 does not specify the server behavior in this case;
+responding with Rcode of NOTAUTH follows BIND 9's behavior.
+
% AUTH_RESPONSE_FAILURE exception while building response to query: %1
This is a debug message, generated by the authoritative server when an
attempt to create a response to a received DNS packet has failed. The
diff --git a/src/bin/auth/auth_srv.cc b/src/bin/auth/auth_srv.cc
index 30875e5..927ffe8 100644
--- a/src/bin/auth/auth_srv.cc
+++ b/src/bin/auth/auth_srv.cc
@@ -747,6 +747,8 @@ AuthSrvImpl::processNotify(const IOMessage& io_message, Message& message,
std::auto_ptr<TSIGContext> tsig_context,
MessageAttributes& stats_attrs)
{
+ const IOEndpoint& remote_ep = io_message.getRemoteEndpoint(); // for logs
+
// The incoming notify must contain exactly one question for SOA of the
// zone name.
if (message.getRRCount(Message::SECTION_QUESTION) != 1) {
@@ -769,8 +771,23 @@ AuthSrvImpl::processNotify(const IOMessage& io_message, Message& message,
// on, but we don't check these conditions. This behavior is compatible
// with BIND 9.
- // TODO check with the conf-mgr whether current server is the auth of the
- // zone
+ // See if we have the specified zone in our data sources; if not return
+ // NOTAUTH, following BIND 9 (this is not specified in RFC 1996).
+ bool is_auth = false;
+ {
+ auth::DataSrcClientsMgr::Holder datasrc_holder(datasrc_clients_mgr_);
+ const shared_ptr<datasrc::ClientList> dsrc_clients =
+ datasrc_holder.findClientList(question->getClass());
+ is_auth = dsrc_clients &&
+ dsrc_clients->find(question->getName(), true, false).exact_match_;
+ }
+ if (!is_auth) {
+ LOG_DEBUG(auth_logger, DBG_AUTH_DETAIL, AUTH_RECEIVED_NOTIFY_NOTAUTH)
+ .arg(question->getName()).arg(question->getClass()).arg(remote_ep);
+ makeErrorMessage(renderer_, message, buffer, Rcode::NOTAUTH(),
+ stats_attrs, tsig_context);
+ return (true);
+ }
// In the code that follows, we simply ignore the notify if any internal
// error happens rather than returning (e.g.) SERVFAIL. RFC 1996 is
@@ -782,10 +799,9 @@ AuthSrvImpl::processNotify(const IOMessage& io_message, Message& message,
}
LOG_DEBUG(auth_logger, DBG_AUTH_DETAIL, AUTH_RECEIVED_NOTIFY)
- .arg(question->getName()).arg(question->getClass());
+ .arg(question->getName()).arg(question->getClass()).arg(remote_ep);
- const string remote_ip_address =
- io_message.getRemoteEndpoint().getAddress().toText();
+ const string remote_ip_address = remote_ep.getAddress().toText();
static const string command_template_start =
"{\"command\": [\"notify\", {\"zone_name\" : \"";
static const string command_template_master = "\", \"master\" : \"";
diff --git a/src/bin/auth/auth_srv.h b/src/bin/auth/auth_srv.h
index 107e2e6..8ad72be 100644
--- a/src/bin/auth/auth_srv.h
+++ b/src/bin/auth/auth_srv.h
@@ -228,7 +228,7 @@ public:
* \brief Set and get the addresses we listen on.
*/
void setListenAddresses(const isc::server_common::portconfig::AddressList&
- addreses);
+ addresses);
const isc::server_common::portconfig::AddressList& getListenAddresses()
const;
diff --git a/src/bin/auth/gen-statisticsitems.py.pre.in b/src/bin/auth/gen-statisticsitems.py.pre.in
index e2d1623..ca5e013 100755
--- a/src/bin/auth/gen-statisticsitems.py.pre.in
+++ b/src/bin/auth/gen-statisticsitems.py.pre.in
@@ -289,7 +289,7 @@ def generate_cxx(itemsfile, ccfile, utfile, def_mtime):
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
+ COUNTER_ITEM, ///< item's description
- 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 )
diff --git a/src/bin/auth/query.cc b/src/bin/auth/query.cc
index c5b9b16..770f624 100644
--- a/src/bin/auth/query.cc
+++ b/src/bin/auth/query.cc
@@ -373,7 +373,7 @@ Query::process(datasrc::ClientList& client_list,
// If we have no matching authoritative zone for the query name, return
// REFUSED. In short, this is to be compatible with BIND 9, but the
// background discussion is not that simple. See the relevant topic
- // at the BIND 10 developers's ML:
+ // at the BIND 10 developers' ML:
// https://lists.isc.org/mailman/htdig/bind10-dev/2010-December/001633.html
if (result.dsrc_client_ == NULL) {
// If we tried to find a "parent zone" for a DS query and failed,
diff --git a/src/bin/auth/query.h b/src/bin/auth/query.h
index 5af2361..2c08312 100644
--- a/src/bin/auth/query.h
+++ b/src/bin/auth/query.h
@@ -329,8 +329,8 @@ public:
/// \short Bad zone data encountered.
///
- /// This is thrown when process encounteres misconfigured zone in a way
- /// it can't continue. This throws, not sets the Rcode, because such
+ /// This is thrown when a process encounters a misconfigured zone in a
+ /// way it can't continue. This throws, not sets the Rcode, because such
/// misconfigured zone should not be present in the data source and
/// should have been rejected sooner.
struct BadZone : public isc::Exception {
diff --git a/src/bin/auth/tests/auth_srv_unittest.cc b/src/bin/auth/tests/auth_srv_unittest.cc
index 0a77a11..de148bc 100644
--- a/src/bin/auth/tests/auth_srv_unittest.cc
+++ b/src/bin/auth/tests/auth_srv_unittest.cc
@@ -244,6 +244,62 @@ createBuiltinVersionResponse(const qid_t qid, vector<uint8_t>& data) {
renderer.getLength());
}
+void
+installDataSrcClientLists(AuthSrv& server, ClientListMapPtr lists) {
+ // For now, we use explicit swap than reconfigure() because the latter
+ // involves a separate thread and cannot guarantee the new config is
+ // available for the subsequent test.
+ server.getDataSrcClientsMgr().setDataSrcClientLists(lists);
+}
+
+void
+updateDatabase(AuthSrv& server, const char* params) {
+ const ConstElementPtr config(Element::fromJSON("{"
+ "\"IN\": [{"
+ " \"type\": \"sqlite3\","
+ " \"params\": " + string(params) +
+ "}]}"));
+ installDataSrcClientLists(server, configureDataSource(config));
+}
+
+// Note: if with_static is set to true, the corresponding test should be
+// disabled in case of USE_STATIC_LINK.
+void
+updateInMemory(AuthSrv& server, const char* origin, const char* filename,
+ bool with_static = true)
+{
+ string spec_txt = "{"
+ "\"IN\": [{"
+ " \"type\": \"MasterFiles\","
+ " \"params\": {"
+ " \"" + string(origin) + "\": \"" + string(filename) + "\""
+ " },"
+ " \"cache-enable\": true"
+ "}]";
+ if (with_static) {
+ spec_txt += ", \"CH\": [{"
+ " \"type\": \"static\","
+ " \"params\": \"" + string(STATIC_DSRC_FILE) + "\""
+ "}]";
+ }
+ spec_txt += "}";
+
+ const ConstElementPtr config(Element::fromJSON(spec_txt));
+ installDataSrcClientLists(server, configureDataSource(config));
+}
+
+// Note: tests using this function should be disabled in case of
+// USE_STATIC_LINK.
+void
+updateBuiltin(AuthSrv& server) {
+ const ConstElementPtr config(Element::fromJSON("{"
+ "\"CH\": [{"
+ " \"type\": \"static\","
+ " \"params\": \"" + string(STATIC_DSRC_FILE) + "\""
+ "}]}"));
+ installDataSrcClientLists(server, configureDataSource(config));
+}
+
// We did not configure any client lists. Therefore it should be REFUSED
TEST_F(AuthSrvTest, noClientList) {
UnitTestUtil::createRequestMessage(request_message, Opcode::QUERY(),
@@ -647,8 +703,10 @@ TEST_F(AuthSrvTest, IXFRDisconnectFail) {
}
TEST_F(AuthSrvTest, notify) {
+ updateInMemory(server, "example.", CONFIG_INMEMORY_EXAMPLE, false);
+
UnitTestUtil::createRequestMessage(request_message, Opcode::NOTIFY(),
- default_qid, Name("example.com"),
+ default_qid, Name("example"),
RRClass::IN(), RRType::SOA());
request_message.setHeaderFlag(Message::HEADERFLAG_AA);
createRequestPacket(request_message, IPPROTO_UDP);
@@ -664,7 +722,7 @@ TEST_F(AuthSrvTest, notify) {
stringValue());
ConstElementPtr notify_args =
notify_session.getSentMessage()->get("command")->get(1);
- EXPECT_EQ("example.com.", notify_args->get("zone_name")->stringValue());
+ EXPECT_EQ("example.", notify_args->get("zone_name")->stringValue());
EXPECT_EQ(DEFAULT_REMOTE_ADDRESS,
notify_args->get("master")->stringValue());
EXPECT_EQ("IN", notify_args->get("zone_class")->stringValue());
@@ -675,7 +733,7 @@ TEST_F(AuthSrvTest, notify) {
// The question must be identical to that of the received notify
ConstQuestionPtr question = *parse_message->beginQuestion();
- EXPECT_EQ(Name("example.com"), question->getName());
+ EXPECT_EQ(Name("example"), question->getName());
EXPECT_EQ(RRClass::IN(), question->getClass());
EXPECT_EQ(RRType::SOA(), question->getType());
@@ -690,10 +748,17 @@ TEST_F(AuthSrvTest, notify) {
checkStatisticsCounters(stats_after, expect);
}
+#ifdef USE_STATIC_LINK
+TEST_F(AuthSrvTest, DISABLED_notifyForCHClass) {
+#else
TEST_F(AuthSrvTest, notifyForCHClass) {
- // Same as the previous test, but for the CH RRClass.
+#endif
+ // Same as the previous test, but for the CH RRClass (so we install the
+ // builtin (static) data source.
+ updateBuiltin(server);
+
UnitTestUtil::createRequestMessage(request_message, Opcode::NOTIFY(),
- default_qid, Name("example.com"),
+ default_qid, Name("bind"),
RRClass::CH(), RRType::SOA());
request_message.setHeaderFlag(Message::HEADERFLAG_AA);
createRequestPacket(request_message, IPPROTO_UDP);
@@ -773,9 +838,11 @@ TEST_F(AuthSrvTest, notifyNonSOAQuestion) {
}
TEST_F(AuthSrvTest, notifyWithoutAA) {
+ updateInMemory(server, "example.", CONFIG_INMEMORY_EXAMPLE, false);
+
// implicitly leave the AA bit off. our implementation will accept it.
UnitTestUtil::createRequestMessage(request_message, Opcode::NOTIFY(),
- default_qid, Name("example.com"),
+ default_qid, Name("example"),
RRClass::IN(), RRType::SOA());
createRequestPacket(request_message, IPPROTO_UDP);
server.processMessage(*io_message, *parse_message, *response_obuffer,
@@ -786,8 +853,10 @@ TEST_F(AuthSrvTest, notifyWithoutAA) {
}
TEST_F(AuthSrvTest, notifyWithErrorRcode) {
+ updateInMemory(server, "example.", CONFIG_INMEMORY_EXAMPLE, false);
+
UnitTestUtil::createRequestMessage(request_message, Opcode::NOTIFY(),
- default_qid, Name("example.com"),
+ default_qid, Name("example"),
RRClass::IN(), RRType::SOA());
request_message.setHeaderFlag(Message::HEADERFLAG_AA);
request_message.setRcode(Rcode::SERVFAIL());
@@ -800,10 +869,12 @@ TEST_F(AuthSrvTest, notifyWithErrorRcode) {
}
TEST_F(AuthSrvTest, notifyWithoutSession) {
+ updateInMemory(server, "example.", CONFIG_INMEMORY_EXAMPLE, false);
+
server.setXfrinSession(NULL);
UnitTestUtil::createRequestMessage(request_message, Opcode::NOTIFY(),
- default_qid, Name("example.com"),
+ default_qid, Name("example"),
RRClass::IN(), RRType::SOA());
request_message.setHeaderFlag(Message::HEADERFLAG_AA);
createRequestPacket(request_message, IPPROTO_UDP);
@@ -816,10 +887,12 @@ TEST_F(AuthSrvTest, notifyWithoutSession) {
}
TEST_F(AuthSrvTest, notifySendFail) {
+ updateInMemory(server, "example.", CONFIG_INMEMORY_EXAMPLE, false);
+
notify_session.disableSend();
UnitTestUtil::createRequestMessage(request_message, Opcode::NOTIFY(),
- default_qid, Name("example.com"),
+ default_qid, Name("example"),
RRClass::IN(), RRType::SOA());
request_message.setHeaderFlag(Message::HEADERFLAG_AA);
createRequestPacket(request_message, IPPROTO_UDP);
@@ -830,10 +903,12 @@ TEST_F(AuthSrvTest, notifySendFail) {
}
TEST_F(AuthSrvTest, notifyReceiveFail) {
+ updateInMemory(server, "example.", CONFIG_INMEMORY_EXAMPLE, false);
+
notify_session.disableReceive();
UnitTestUtil::createRequestMessage(request_message, Opcode::NOTIFY(),
- default_qid, Name("example.com"),
+ default_qid, Name("example"),
RRClass::IN(), RRType::SOA());
request_message.setHeaderFlag(Message::HEADERFLAG_AA);
createRequestPacket(request_message, IPPROTO_UDP);
@@ -843,10 +918,12 @@ TEST_F(AuthSrvTest, notifyReceiveFail) {
}
TEST_F(AuthSrvTest, notifyWithBogusSessionMessage) {
+ updateInMemory(server, "example.", CONFIG_INMEMORY_EXAMPLE, false);
+
notify_session.setMessage(Element::fromJSON("{\"foo\": 1}"));
UnitTestUtil::createRequestMessage(request_message, Opcode::NOTIFY(),
- default_qid, Name("example.com"),
+ default_qid, Name("example"),
RRClass::IN(), RRType::SOA());
request_message.setHeaderFlag(Message::HEADERFLAG_AA);
createRequestPacket(request_message, IPPROTO_UDP);
@@ -856,11 +933,13 @@ TEST_F(AuthSrvTest, notifyWithBogusSessionMessage) {
}
TEST_F(AuthSrvTest, notifyWithSessionMessageError) {
+ updateInMemory(server, "example.", CONFIG_INMEMORY_EXAMPLE, false);
+
notify_session.setMessage(
Element::fromJSON("{\"result\": [1, \"FAIL\"]}"));
UnitTestUtil::createRequestMessage(request_message, Opcode::NOTIFY(),
- default_qid, Name("example.com"),
+ default_qid, Name("example"),
RRClass::IN(), RRType::SOA());
request_message.setHeaderFlag(Message::HEADERFLAG_AA);
createRequestPacket(request_message, IPPROTO_UDP);
@@ -869,49 +948,50 @@ TEST_F(AuthSrvTest, notifyWithSessionMessageError) {
EXPECT_FALSE(dnsserv.hasAnswer());
}
-void
-installDataSrcClientLists(AuthSrv& server, ClientListMapPtr lists) {
- // For now, we use explicit swap than reconfigure() because the latter
- // involves a separate thread and cannot guarantee the new config is
- // available for the subsequent test.
- server.getDataSrcClientsMgr().setDataSrcClientLists(lists);
-}
+TEST_F(AuthSrvTest, notifyNotAuth) {
+ // If the server doesn't have authority of the specified zone in NOTIFY,
+ // it will return NOTAUTH
+ updateInMemory(server, "example.", CONFIG_INMEMORY_EXAMPLE, false);
-void
-updateDatabase(AuthSrv& server, const char* params) {
- const ConstElementPtr config(Element::fromJSON("{"
- "\"IN\": [{"
- " \"type\": \"sqlite3\","
- " \"params\": " + string(params) +
- "}]}"));
- installDataSrcClientLists(server, configureDataSource(config));
+ UnitTestUtil::createRequestMessage(request_message, Opcode::NOTIFY(),
+ default_qid, Name("example.com"),
+ RRClass::IN(), RRType::SOA());
+ request_message.setHeaderFlag(Message::HEADERFLAG_AA);
+ createRequestPacket(request_message, IPPROTO_UDP);
+ server.processMessage(*io_message, *parse_message, *response_obuffer,
+ &dnsserv);
+ EXPECT_TRUE(dnsserv.hasAnswer());
+ headerCheck(*parse_message, default_qid, Rcode::NOTAUTH(),
+ Opcode::NOTIFY().getCode(), QR_FLAG /* no AA */, 1, 0, 0, 0);
}
-void
-updateInMemory(AuthSrv& server, const char* origin, const char* filename) {
- const ConstElementPtr config(Element::fromJSON("{"
- "\"IN\": [{"
- " \"type\": \"MasterFiles\","
- " \"params\": {"
- " \"" + string(origin) + "\": \"" + string(filename) + "\""
- " },"
- " \"cache-enable\": true"
- "}],"
- "\"CH\": [{"
- " \"type\": \"static\","
- " \"params\": \"" + string(STATIC_DSRC_FILE) + "\""
- "}]}"));
- installDataSrcClientLists(server, configureDataSource(config));
+TEST_F(AuthSrvTest, notifyNotAuthSubDomain) {
+ // Similar to the previous case, but checking partial match doesn't confuse
+ // the processing.
+ updateInMemory(server, "example.", CONFIG_INMEMORY_EXAMPLE, false);
+
+ UnitTestUtil::createRequestMessage(request_message, Opcode::NOTIFY(),
+ default_qid, Name("child.example"),
+ RRClass::IN(), RRType::SOA());
+ createRequestPacket(request_message, IPPROTO_UDP);
+ server.processMessage(*io_message, *parse_message, *response_obuffer,
+ &dnsserv);
+ headerCheck(*parse_message, default_qid, Rcode::NOTAUTH(),
+ Opcode::NOTIFY().getCode(), QR_FLAG, 1, 0, 0, 0);
}
-void
-updateBuiltin(AuthSrv& server) {
- const ConstElementPtr config(Element::fromJSON("{"
- "\"CH\": [{"
- " \"type\": \"static\","
- " \"params\": \"" + string(STATIC_DSRC_FILE) + "\""
- "}]}"));
- installDataSrcClientLists(server, configureDataSource(config));
+TEST_F(AuthSrvTest, notifyNotAuthNoClass) {
+ // Likewise, and there's not even a data source in the specified class.
+ updateInMemory(server, "example.", CONFIG_INMEMORY_EXAMPLE, false);
+
+ UnitTestUtil::createRequestMessage(request_message, Opcode::NOTIFY(),
+ default_qid, Name("example"),
+ RRClass::CH(), RRType::SOA());
+ createRequestPacket(request_message, IPPROTO_UDP);
+ server.processMessage(*io_message, *parse_message, *response_obuffer,
+ &dnsserv);
+ headerCheck(*parse_message, default_qid, Rcode::NOTAUTH(),
+ Opcode::NOTIFY().getCode(), QR_FLAG, 1, 0, 0, 0);
}
// Try giving the server a TSIG signed request and see it can anwer signed as
@@ -1679,7 +1759,7 @@ public:
data_sources_.push_back(
DataSourceInfo(client.get(),
isc::datasrc::DataSourceClientContainerPtr(),
- false, RRClass::IN(), ztable_segment_));
+ false, RRClass::IN(), ztable_segment_, ""));
}
}
private:
diff --git a/src/bin/bind10/TODO b/src/bin/bind10/TODO
index 6f50dbd..82abdb1 100644
--- a/src/bin/bind10/TODO
+++ b/src/bin/bind10/TODO
@@ -6,7 +6,7 @@
- Stop a component
- Force-stop a component
- Mechanism to wait for child to start before continuing
-- Use .spec file to define comands
+- Use .spec file to define commands
- Rename "c-channel" stuff to msgq for clarity
- Reply to shutdown message?
- Some sort of group creation so termination signals can be sent to
diff --git a/src/bin/bind10/init.py.in b/src/bin/bind10/init.py.in
index f47de31..e57971a 100755
--- a/src/bin/bind10/init.py.in
+++ b/src/bin/bind10/init.py.in
@@ -38,6 +38,7 @@ __main__.
import sys; sys.path.append ('@@PYTHONPATH@@')
import os
+from isc.util.address_formatter import AddressFormatter
# If B10_FROM_SOURCE is set in the environment, we use data files
# from a directory relative to that, otherwise we use the ones
@@ -151,7 +152,7 @@ class ProcessInfo:
"""Function used before running a program that needs to run as a
different user."""
# First, put us into a separate process group so we don't get
- # SIGINT signals on Ctrl-C (b10-init will shut everthing down by
+ # SIGINT signals on Ctrl-C (b10-init will shut everything down by
# other means).
os.setpgrp()
@@ -428,7 +429,7 @@ class Init:
port)
else:
logger.info(BIND10_STARTING_PROCESS_PORT_ADDRESS,
- self.curproc, address, port)
+ self.curproc, AddressFormatter((address, port)))
def log_started(self, pid = None):
"""
diff --git a/src/bin/bind10/init_messages.mes b/src/bin/bind10/init_messages.mes
index 9cdb7ef..267790d 100644
--- a/src/bin/bind10/init_messages.mes
+++ b/src/bin/bind10/init_messages.mes
@@ -34,7 +34,7 @@ The named component is about to be started by the b10-init process.
% BIND10_COMPONENT_START_EXCEPTION component %1 failed to start: %2
An exception (mentioned in the message) happened during the startup of the
-named component. The componet is not considered started and further actions
+named component. The component is not considered started and further actions
will be taken about it.
% BIND10_COMPONENT_STOP component %1 is being stopped
@@ -285,9 +285,9 @@ The b10-init module is starting the given process.
The b10-init module is starting the given process, which will listen on the
given port number.
-% BIND10_STARTING_PROCESS_PORT_ADDRESS starting process %1 (to listen on %2#%3)
+% BIND10_STARTING_PROCESS_PORT_ADDRESS starting process %1 (to listen on %2)
The b10-init module is starting the given process, which will listen on the
-given address and port number (written as <address>#<port>).
+given address and port number (written as <address>:<port>).
% BIND10_STARTUP_COMPLETE BIND 10 started
All modules have been successfully started, and BIND 10 is now running.
diff --git a/src/bin/bind10/tests/init_test.py.in b/src/bin/bind10/tests/init_test.py.in
index 9a591ef..f384865 100644
--- a/src/bin/bind10/tests/init_test.py.in
+++ b/src/bin/bind10/tests/init_test.py.in
@@ -2339,6 +2339,16 @@ class SocketSrvTest(unittest.TestCase):
self.assertEqual({}, self.__b10_init._unix_sockets)
self.assertTrue(sock.closed)
+ def test_log_starting(self):
+ """
+ Checks the log_starting call doesn't raise any errors
+ (does not check actual log output)
+ """
+ self.__b10_init.log_starting("foo")
+ self.__b10_init.log_starting("foo", 1)
+ self.__b10_init.log_starting("foo", 1, "192.0.2.1")
+
+
class TestFunctions(unittest.TestCase):
def setUp(self):
self.lockfile_testpath = \
diff --git a/src/bin/bindctl/README b/src/bin/bindctl/README
index 8b98ff5..a9a185f 100644
--- a/src/bin/bindctl/README
+++ b/src/bin/bindctl/README
@@ -1,2 +1,2 @@
1. Start bindctl by run command "sh bindctl".
-2. Login to b10-cmdctld with the username and password. The username and password will be saved in file default_user.csv automatcally after logining successfully, so next time bindctl will login with the username and password saved in default_user.csv. For more usage information, please turn to "man bindctl".
\ No newline at end of file
+2. Login to b10-cmdctl with the username and password. The username and password will be saved in file default_user.csv automatically after logining successfully, so next time bindctl will login with the username and password saved in default_user.csv. For more usage information, please turn to "man bindctl".
diff --git a/src/bin/bindctl/bindcmd.py b/src/bin/bindctl/bindcmd.py
index f382e2a..5ae82a2 100644
--- a/src/bin/bindctl/bindcmd.py
+++ b/src/bin/bindctl/bindcmd.py
@@ -33,6 +33,7 @@ import inspect
import pprint
import ssl, socket
import os, time, random, re
+import os.path
import getpass
from hashlib import sha1
import csv
@@ -214,22 +215,16 @@ WARNING: Python readline module isn't available, so the command line editor
return True
- def __print_check_ssl_msg(self):
- self._print("Please check the logs of b10-cmdctl, there may "
- "be a problem accepting SSL connections, such "
- "as a permission problem on the server "
- "certificate file.")
-
def _try_login(self, username, password):
'''
- Attempts to log in to cmdctl by sending a POST with
- the given username and password.
- On success of the POST (mind, not the login, only the network
- operation), returns a tuple (response, data).
- On failure, raises a FailToLogin exception, and prints some
- information on the failure.
- This call is essentially 'private', but made 'protected' for
- easier testing.
+ Attempts to log into cmdctl by sending a POST with the given
+ username and password. On success of the POST (not the login,
+ but the network operation), it returns a tuple (response, data).
+ We check for some failures such as SSL errors and socket errors
+ which could happen due to the environment in which BIND 10 runs.
+ On failure, it raises a FailToLogin exception and prints some
+ information on the failure. This call is essentially 'private',
+ but made 'protected' for easier testing.
'''
param = {'username': username, 'password' : password}
try:
@@ -237,16 +232,8 @@ WARNING: Python readline module isn't available, so the command line editor
data = response.read().decode()
# return here (will raise error after try block)
return (response, data)
- except ssl.SSLError as err:
- self._print("SSL error while sending login information: ", err)
- if err.errno == ssl.SSL_ERROR_EOF:
- self.__print_check_ssl_msg()
- except socket.error as err:
- self._print("Socket error while sending login information: ", err)
- # An SSL setup error can also bubble up as a plain CONNRESET...
- # (on some systems it usually does)
- if err.errno == errno.ECONNRESET:
- self.__print_check_ssl_msg()
+ except (ssl.SSLError, socket.error) as err:
+ self._print('Error while sending login information:', err)
pass
raise FailToLogin()
@@ -270,9 +257,21 @@ WARNING: Python readline module isn't available, so the command line editor
# No valid logins were found, prompt the user for a username/password
count = 0
- self._print('No stored password file found, please see sections '
- '"Configuration specification for b10-cmdctl" and "bindctl '
- 'command-line options" of the BIND 10 guide.')
+ if not os.path.exists(self.csv_file_dir + CSV_FILE_NAME):
+ self._print('\nNo stored password file found.\n\n'
+ 'When the system is first set up you need to create '
+ 'at least one user account.\n'
+ 'For information on how to set up a BIND 10 system, '
+ 'please check see the\n'
+ 'BIND 10 Guide: \n\n'
+ 'http://bind10.isc.org/docs/bind10-guide.html#quick-start-auth-dns\n\n'
+
+ 'If a user account has been set up, please check the '
+ 'b10-cmdctl log for other\n'
+ 'information.\n')
+ else:
+ self._print('Login failed: either the user name or password is '
+ 'invalid.\n')
while True:
count = count + 1
if count > 3:
@@ -317,14 +316,14 @@ WARNING: Python readline module isn't available, so the command line editor
return {}
- def send_POST(self, url, post_param = None):
+ def send_POST(self, url, post_param=None):
'''Send POST request to cmdctl, session id is send with the name
'cookie' in header.
Format: /module_name/command_name
parameters of command is encoded as a map
'''
param = None
- if (len(post_param) != 0):
+ if post_param is not None and len(post_param) != 0:
param = json.dumps(post_param)
headers = {"cookie" : self.session_id}
@@ -938,5 +937,3 @@ WARNING: Python readline module isn't available, so the command line editor
if data != "" and data != "{}":
self._print(json.dumps(json.loads(data), sort_keys=True,
indent=4))
-
-
diff --git a/src/bin/bindctl/tests/bindctl_test.py b/src/bin/bindctl/tests/bindctl_test.py
index 0ec9b58..c3262e1 100644
--- a/src/bin/bindctl/tests/bindctl_test.py
+++ b/src/bin/bindctl/tests/bindctl_test.py
@@ -26,6 +26,7 @@ import http.client
import pwd
import getpass
import re
+import json
from optparse import OptionParser
from isc.config.config_data import ConfigData, MultiConfigData
from isc.config.module_spec import ModuleSpec
@@ -386,7 +387,7 @@ class TestConfigCommands(unittest.TestCase):
self.tool.send_POST = send_POST_raiseImmediately
self.assertRaises(FailToLogin, self.tool._try_login, "foo", "bar")
expected_printed_messages.append(
- 'Socket error while sending login information: test error')
+ 'Error while sending login information: test error')
self.__check_printed_messages(expected_printed_messages)
def create_send_POST_raiseOnRead(exception):
@@ -405,7 +406,7 @@ class TestConfigCommands(unittest.TestCase):
create_send_POST_raiseOnRead(socket.error("read error"))
self.assertRaises(FailToLogin, self.tool._try_login, "foo", "bar")
expected_printed_messages.append(
- 'Socket error while sending login information: read error')
+ 'Error while sending login information: read error')
self.__check_printed_messages(expected_printed_messages)
# connection reset
@@ -415,13 +416,7 @@ class TestConfigCommands(unittest.TestCase):
create_send_POST_raiseOnRead(exc)
self.assertRaises(FailToLogin, self.tool._try_login, "foo", "bar")
expected_printed_messages.append(
- 'Socket error while sending login information: '
- 'connection reset')
- expected_printed_messages.append(
- 'Please check the logs of b10-cmdctl, there may be a '
- 'problem accepting SSL connections, such as a permission '
- 'problem on the server certificate file.'
- )
+ 'Error while sending login information: connection reset')
self.__check_printed_messages(expected_printed_messages)
# 'normal' SSL error
@@ -430,7 +425,7 @@ class TestConfigCommands(unittest.TestCase):
create_send_POST_raiseOnRead(exc)
self.assertRaises(FailToLogin, self.tool._try_login, "foo", "bar")
expected_printed_messages.append(
- 'SSL error while sending login information: .*')
+ 'Error while sending login information: .*')
self.__check_printed_messages(expected_printed_messages)
# 'EOF' SSL error
@@ -440,12 +435,7 @@ class TestConfigCommands(unittest.TestCase):
create_send_POST_raiseOnRead(exc)
self.assertRaises(FailToLogin, self.tool._try_login, "foo", "bar")
expected_printed_messages.append(
- 'SSL error while sending login information: .*')
- expected_printed_messages.append(
- 'Please check the logs of b10-cmdctl, there may be a '
- 'problem accepting SSL connections, such as a permission '
- 'problem on the server certificate file.'
- )
+ 'Error while sending login information: .*')
self.__check_printed_messages(expected_printed_messages)
# any other exception should be passed through
@@ -457,6 +447,44 @@ class TestConfigCommands(unittest.TestCase):
finally:
self.tool.send_POST = orig_send_POST
+ def test_try_login_calls_cmdctl(self):
+ # Make sure _try_login() makes the right API call to cmdctl.
+ orig_conn = self.tool.conn
+ try:
+ class MyConn:
+ def __init__(self):
+ self.method = None
+ self.url = None
+ self.param = None
+ self.headers = None
+
+ def request(self, method, url, param, headers):
+ self.method = method
+ self.url = url
+ self.param = param
+ self.headers = headers
+
+ def getresponse(self):
+ class MyResponse:
+ def __init__(self):
+ self.status = http.client.OK
+ def read(self):
+ class MyData:
+ def decode(self):
+ return json.dumps(True)
+ return MyData()
+ return MyResponse()
+
+ self.tool.conn = MyConn()
+ self.assertTrue(self.tool._try_login('user32', 'pass64'))
+ self.assertEqual(self.tool.conn.method, 'POST')
+ self.assertEqual(self.tool.conn.url, '/login')
+ self.assertEqual(json.loads(self.tool.conn.param),
+ {"password": "pass64", "username": "user32"})
+ self.assertIn('cookie', self.tool.conn.headers)
+ finally:
+ self.tool.conn = orig_conn
+
def test_run(self):
def login_to_cmdctl():
return True
diff --git a/src/bin/cfgmgr/plugins/datasrc.spec.pre.in b/src/bin/cfgmgr/plugins/datasrc.spec.pre.in
index 6d5bd77..e7bc6ae 100644
--- a/src/bin/cfgmgr/plugins/datasrc.spec.pre.in
+++ b/src/bin/cfgmgr/plugins/datasrc.spec.pre.in
@@ -63,6 +63,11 @@
"item_optional": false,
"item_default": ""
}
+ },
+ {
+ "item_name": "name",
+ "item_type": "string",
+ "item_optional": true
}
]
}
diff --git a/src/bin/cfgmgr/plugins/tests/datasrc_test.py b/src/bin/cfgmgr/plugins/tests/datasrc_test.py
index f4381b4..3c714c6 100644
--- a/src/bin/cfgmgr/plugins/tests/datasrc_test.py
+++ b/src/bin/cfgmgr/plugins/tests/datasrc_test.py
@@ -142,7 +142,7 @@ class DatasrcTest(unittest.TestCase):
def test_no_such_file_mem(self):
"""
- We also check the existance of master files. Not the actual content,
+ We also check the existence of master files. Not the actual content,
though.
"""
self.reject({"IN": [{
@@ -153,6 +153,101 @@ class DatasrcTest(unittest.TestCase):
}
}]})
+ def test_names_present(self):
+ """
+ Test we don't choke on configuration with the "name" being present on
+ some items.
+ """
+ self.accept({"IN": [{
+ "type": "MasterFiles",
+ "cache-enable": True,
+ "params": {},
+ "name": "Whatever"
+ }]})
+
+ def test_names_default_classes(self):
+ """
+ Test we can have a client of the same type in different classes
+ without specified name. The defaults should be derived both from
+ the type and the class.
+ """
+ self.accept({
+ "IN": [{
+ "type": "MasterFiles",
+ "cache-enable": True,
+ "params": {}
+ }],
+ "CH": [{
+ "type": "MasterFiles",
+ "cache-enable": True,
+ "params": {}
+ }]})
+
+ def test_names_collision(self):
+ """
+ Reject when two names are the same.
+
+ Cases are:
+ - Explicit names.
+ - Two default names turn out to be the same (same type and class).
+ - One explicit is set to the same as the default one.
+ """
+ self.reject({"IN": [
+ {
+ "type": "MasterFiles",
+ "cache-enable": True,
+ "params": {},
+ "name": "Whatever"
+ },
+ {
+ "type": "MasterFiles",
+ "cache-enable": True,
+ "params": {},
+ "name": "Whatever"
+ }]})
+ # The same, but across different classes is allowed (we would
+ # identify the data source by class+name tuple)
+ self.accept({
+ "IN": [
+ {
+ "type": "MasterFiles",
+ "cache-enable": True,
+ "params": {},
+ "name": "Whatever"
+ }
+ ],
+ "CH": [
+ {
+ "type": "MasterFiles",
+ "cache-enable": True,
+ "params": {},
+ "name": "Whatever"
+ }
+ ]})
+ self.reject({"IN": [
+ {
+ "type": "MasterFiles",
+ "cache-enable": True,
+ "params": {}
+ },
+ {
+ "type": "MasterFiles",
+ "cache-enable": True,
+ "params": {}
+ }]})
+ self.reject({"IN": [
+ {
+ "type": "MasterFiles",
+ "cache-enable": True,
+ "params": {},
+ "name": "MasterFiles"
+ },
+ {
+ "type": "MasterFiles",
+ "cache-enable": True,
+ "params": {}
+ }]})
+
if __name__ == '__main__':
isc.log.init("bind10")
isc.log.resetUnitTestRootLogger()
diff --git a/src/bin/cfgmgr/plugins/tests/tsig_keys_test.py b/src/bin/cfgmgr/plugins/tests/tsig_keys_test.py
index 808f28a..8c1639c 100644
--- a/src/bin/cfgmgr/plugins/tests/tsig_keys_test.py
+++ b/src/bin/cfgmgr/plugins/tests/tsig_keys_test.py
@@ -86,7 +86,7 @@ class TSigKeysTest(unittest.TestCase):
self.assertEqual("TSIG: Invalid TSIG key string: invalid.key",
tsig_keys.check({'keys': ['invalid.key']}))
self.assertEqual(
- "TSIG: Unexpected end of input in BASE decoder",
+ "TSIG: Incomplete input for base64: 123",
tsig_keys.check({'keys': ['invalid.key:123']}))
def test_bad_format(self):
diff --git a/src/bin/cmdctl/Makefile.am b/src/bin/cmdctl/Makefile.am
index 8cadf89..72a400a 100644
--- a/src/bin/cmdctl/Makefile.am
+++ b/src/bin/cmdctl/Makefile.am
@@ -11,20 +11,18 @@ pylogmessagedir = $(pyexecdir)/isc/log_messages/
b10_cmdctldir = $(pkgdatadir)
-USERSFILES = cmdctl-accounts.csv
CERTFILES = cmdctl-keyfile.pem cmdctl-certfile.pem
b10_cmdctl_DATA = cmdctl.spec
-EXTRA_DIST = $(USERSFILES)
-
CLEANFILES= b10-cmdctl cmdctl.pyc cmdctl.spec
CLEANFILES += $(PYTHON_LOGMSGPKG_DIR)/work/cmdctl_messages.py
CLEANFILES += $(PYTHON_LOGMSGPKG_DIR)/work/cmdctl_messages.pyc
man_MANS = b10-cmdctl.8 b10-certgen.1
DISTCLEANFILES = $(man_MANS) cmdctl-certfile.pem cmdctl-keyfile.pem
-EXTRA_DIST += $(man_MANS) b10-certgen.xml b10-cmdctl.xml cmdctl_messages.mes
+EXTRA_DIST = $(man_MANS) b10-certgen.xml b10-cmdctl.xml cmdctl_messages.mes
+EXTRA_DIST += cmdctl-accounts.csv
if GENERATE_DOCS
diff --git a/src/bin/cmdctl/b10-certgen.cc b/src/bin/cmdctl/b10-certgen.cc
index 579ae60..59bba9e 100644
--- a/src/bin/cmdctl/b10-certgen.cc
+++ b/src/bin/cmdctl/b10-certgen.cc
@@ -62,7 +62,7 @@ usage() {
std::cout << "Options:" << std::endl;
std::cout << "-c, --certfile=FILE\t\tfile to read or store the certificate"
<< std::endl;
- std::cout << "-f, --force\t\t\toverwrite existing certficate even if it"
+ std::cout << "-f, --force\t\t\toverwrite existing certificate even if it"
<< std::endl <<"\t\t\t\tis valid" << std::endl;
std::cout << "-h, --help\t\t\tshow this help" << std::endl;
std::cout << "-k, --keyfile=FILE\t\tfile to store the generated private key"
@@ -194,7 +194,7 @@ public:
print("Creating certificate file " + cert_file_name);
- // The exact call changed aftert 1.8, adding the
+ // The exact call changed after 1.8, adding the
// hash function option
#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,9,0)
X509_Certificate cert =
@@ -229,7 +229,7 @@ public:
validateCertificate(const std::string& certfile) {
// Since we are dealing with a self-signed certificate here, we
// also use the certificate to check itself; i.e. we add it
- // as a trusted certificate, then validate the certficate itself.
+ // as a trusted certificate, then validate the certificate itself.
//const X509_Certificate cert(certfile);
try {
X509_Store store;
diff --git a/src/bin/cmdctl/cmdctl.py.in b/src/bin/cmdctl/cmdctl.py.in
index 457873b..219dc53 100755
--- a/src/bin/cmdctl/cmdctl.py.in
+++ b/src/bin/cmdctl/cmdctl.py.in
@@ -42,6 +42,7 @@ import random
import time
import signal
from isc.config import ccsession
+import isc.cc.proto_defs
import isc.util.process
import isc.net.parse
from optparse import OptionParser, OptionValueError
@@ -97,6 +98,11 @@ def check_file(file_name):
class SecureHTTPRequestHandler(http.server.BaseHTTPRequestHandler):
'''https connection request handler.
Currently only GET and POST are supported. '''
+ def __init__(self, request, client_address, server):
+ http.server.BaseHTTPRequestHandler.__init__(self, request,
+ client_address, server)
+ self.session_id = None
+
def do_GET(self):
'''The client should send its session id in header with
the name 'cookie'
@@ -121,7 +127,7 @@ class SecureHTTPRequestHandler(http.server.BaseHTTPRequestHandler):
return self.server.get_reply_data_for_GET(id, module)
def _is_session_valid(self):
- return self.session_id
+ return self.session_id is not None
def _is_user_logged_in(self):
login_time = self.server.user_sessions.get(self.session_id)
@@ -171,7 +177,7 @@ class SecureHTTPRequestHandler(http.server.BaseHTTPRequestHandler):
is_user_valid, error_info = self._check_user_name_and_pwd()
if is_user_valid:
self.server.save_user_session_id(self.session_id)
- return http.client.OK, ["login success "]
+ return http.client.OK, ["login success"]
else:
return http.client.UNAUTHORIZED, error_info
@@ -454,7 +460,8 @@ class CommandControl():
else:
return rcode, {}
else:
- errstr = str(answer['result'][1])
+ errstr = \
+ str(answer[isc.cc.proto_defs.CC_PAYLOAD_RESULT][1])
except ccsession.ModuleCCSessionError as mcse:
errstr = str("Error in ccsession answer:") + str(mcse)
@@ -502,12 +509,25 @@ class SecureHTTPServer(socketserver_mixin.NoPollMixIn,
self._verbose = verbose
self._lock = threading.Lock()
self._user_infos = {}
- self._accounts_file = None
+ self.__accounts_file = None
+ self.__accounts_file_mtime = 0
def _create_user_info(self, accounts_file):
'''Read all user's name and its' salt, hashed password
from accounts file.'''
- if (self._accounts_file == accounts_file) and (len(self._user_infos) > 0):
+
+ # If the file does not exist, set accounts to empty, and return
+ if not os.path.exists(accounts_file):
+ self._user_infos = {}
+ self.__accounts_file = None
+ self.__accounts_file_mtime = 0
+ return
+
+ # If the filename hasn't changed, and the file itself
+ # has neither, do nothing
+ accounts_file_mtime = os.stat(accounts_file).st_mtime
+ if self.__accounts_file == accounts_file and\
+ accounts_file_mtime <= self.__accounts_file_mtime:
return
with self._lock:
@@ -525,7 +545,8 @@ class SecureHTTPServer(socketserver_mixin.NoPollMixIn,
if csvfile:
csvfile.close()
- self._accounts_file = accounts_file
+ self.__accounts_file = accounts_file
+ self.__accounts_file_mtime = accounts_file_mtime
if len(self._user_infos) == 0:
logger.error(CMDCTL_NO_USER_ENTRIES_READ)
diff --git a/src/bin/cmdctl/tests/Makefile.am b/src/bin/cmdctl/tests/Makefile.am
index 74b801a..f24cf73 100644
--- a/src/bin/cmdctl/tests/Makefile.am
+++ b/src/bin/cmdctl/tests/Makefile.am
@@ -25,8 +25,8 @@ endif
echo Running test: $$pytest ; \
$(LIBRARY_PATH_PLACEHOLDER) \
PYTHONPATH=$(COMMON_PYTHON_PATH):$(abs_top_builddir)/src/bin/cmdctl \
- CMDCTL_BUILD_PATH=$(abs_top_builddir)/src/bin/cmdctl \
CMDCTL_SRC_PATH=$(abs_top_srcdir)/src/bin/cmdctl \
+ CMDCTL_BUILD_PATH=$(abs_top_builddir)/src/bin/cmdctl \
B10_LOCKFILE_DIR_FROM_BUILD=$(abs_top_builddir) \
$(PYCOVERAGE_RUN) $(abs_srcdir)/$$pytest || exit ; \
done
diff --git a/src/bin/cmdctl/tests/b10-certgen_test.py b/src/bin/cmdctl/tests/b10-certgen_test.py
index d54efa3..56630bc 100644
--- a/src/bin/cmdctl/tests/b10-certgen_test.py
+++ b/src/bin/cmdctl/tests/b10-certgen_test.py
@@ -172,10 +172,7 @@ class TestCertGenTool(unittest.TestCase):
"""
Tests a few pre-created certificates with the -c option
"""
- if ('CMDCTL_SRC_PATH' in os.environ):
- path = os.environ['CMDCTL_SRC_PATH'] + "/tests/testdata/"
- else:
- path = "testdata/"
+ path = os.environ['CMDCTL_SRC_PATH'] + '/tests/testdata/'
self.validate_certificate(10, path + 'expired-certfile.pem')
self.validate_certificate(100, path + 'mangled-certfile.pem')
self.validate_certificate(17, path + 'noca-certfile.pem')
diff --git a/src/bin/cmdctl/tests/cmdctl_test.py b/src/bin/cmdctl/tests/cmdctl_test.py
index ee44f45..dd1a6f2 100644
--- a/src/bin/cmdctl/tests/cmdctl_test.py
+++ b/src/bin/cmdctl/tests/cmdctl_test.py
@@ -17,6 +17,7 @@
import unittest
import socket
import tempfile
+import time
import stat
import sys
from cmdctl import *
@@ -33,7 +34,7 @@ BUILD_FILE_PATH = os.environ['CMDCTL_BUILD_PATH'] + os.sep
# Rewrite the class for unittest.
class MySecureHTTPRequestHandler(SecureHTTPRequestHandler):
def __init__(self):
- pass
+ self.session_id = None
def send_response(self, rcode):
self.rcode = rcode
@@ -41,19 +42,6 @@ class MySecureHTTPRequestHandler(SecureHTTPRequestHandler):
def end_headers(self):
pass
- def do_GET(self):
- self.wfile = open('tmp.file', 'wb')
- super().do_GET()
- self.wfile.close()
- os.remove('tmp.file')
-
- def do_POST(self):
- self.wfile = open("tmp.file", 'wb')
- super().do_POST()
- self.wfile.close()
- os.remove('tmp.file')
-
-
class FakeSecureHTTPServer(SecureHTTPServer):
def __init__(self):
self.user_sessions = {}
@@ -84,6 +72,26 @@ class UnreadableFile:
def __exit__(self, type, value, traceback):
os.chmod(self.file_name, self.orig_mode)
+class TmpTextFile:
+ """
+ Context class for temporarily creating a text file with some
+ lines of content.
+
+ The file is automatically deleted if the context is left, so
+ make sure to not use the path of an existing file!
+ """
+ def __init__(self, path, contents):
+ self.__path = path
+ self.__contents = contents
+
+ def __enter__(self):
+ with open(self.__path, 'w') as f:
+ f.write("\n".join(self.__contents) + "\n")
+
+ def __exit__(self, type, value, traceback):
+ os.unlink(self.__path)
+
+
class TestSecureHTTPRequestHandler(unittest.TestCase):
def setUp(self):
self.old_stdout = sys.stdout
@@ -93,13 +101,22 @@ class TestSecureHTTPRequestHandler(unittest.TestCase):
self.handler.server.user_sessions = {}
self.handler.server._user_infos = {}
self.handler.headers = {}
- self.handler.rfile = open("check.tmp", 'w+b')
+ self.handler.rfile = open('input.tmp', 'w+b')
+ self.handler.wfile = open('output.tmp', 'w+b')
def tearDown(self):
sys.stdout.close()
sys.stdout = self.old_stdout
+ self.handler.wfile.close()
+ os.remove('output.tmp')
self.handler.rfile.close()
- os.remove('check.tmp')
+ os.remove('input.tmp')
+
+ def test_is_session_valid(self):
+ self.assertIsNone(self.handler.session_id)
+ self.assertFalse(self.handler._is_session_valid())
+ self.handler.session_id = 4234
+ self.assertTrue(self.handler._is_session_valid())
def test_parse_request_path(self):
self.handler.path = ''
@@ -160,7 +177,7 @@ class TestSecureHTTPRequestHandler(unittest.TestCase):
self.handler.do_GET()
self.assertEqual(self.handler.rcode, http.client.OK)
- def test_user_logged_in(self):
+ def test_is_user_logged_in(self):
self.handler.server.user_sessions = {}
self.handler.session_id = 12345
self.assertTrue(self.handler._is_user_logged_in() == False)
@@ -294,6 +311,68 @@ class TestSecureHTTPRequestHandler(unittest.TestCase):
rcode, reply = self.handler._handle_post_request()
self.assertEqual(http.client.BAD_REQUEST, rcode)
+ def test_handle_login(self):
+ orig_is_user_logged_in = self.handler._is_user_logged_in
+ orig_check_user_name_and_pwd = self.handler._check_user_name_and_pwd
+ try:
+ def create_is_user_logged_in(status):
+ '''Create a replacement _is_user_logged_in() method.'''
+ def my_is_user_logged_in():
+ return status
+ return my_is_user_logged_in
+
+ # Check case where _is_user_logged_in() returns True
+ self.handler._is_user_logged_in = create_is_user_logged_in(True)
+ self.handler.headers['cookie'] = 12345
+ self.handler.path = '/login'
+ self.handler.do_POST()
+ self.assertEqual(self.handler.rcode, http.client.OK)
+ self.handler.wfile.seek(0, 0)
+ d = self.handler.wfile.read()
+ self.assertEqual(json.loads(d.decode()),
+ ['user has already login'])
+
+ # Clear the output
+ self.handler.wfile.seek(0, 0)
+ self.handler.wfile.truncate()
+
+ # Check case where _is_user_logged_in() returns False
+ self.handler._is_user_logged_in = create_is_user_logged_in(False)
+
+ def create_check_user_name_and_pwd(status, error_info=None):
+ '''Create a replacement _check_user_name_and_pwd() method.'''
+ def my_check_user_name_and_pwd():
+ return status, error_info
+ return my_check_user_name_and_pwd
+
+ # (a) Check case where _check_user_name_and_pwd() returns
+ # valid user status
+ self.handler._check_user_name_and_pwd = \
+ create_check_user_name_and_pwd(True)
+ self.handler.do_POST()
+ self.assertEqual(self.handler.rcode, http.client.OK)
+ self.handler.wfile.seek(0, 0)
+ d = self.handler.wfile.read()
+ self.assertEqual(json.loads(d.decode()), ['login success'])
+
+ # Clear the output
+ self.handler.wfile.seek(0, 0)
+ self.handler.wfile.truncate()
+
+ # (b) Check case where _check_user_name_and_pwd() returns
+ # invalid user status
+ self.handler._check_user_name_and_pwd = \
+ create_check_user_name_and_pwd(False, ['login failed'])
+ self.handler.do_POST()
+ self.assertEqual(self.handler.rcode, http.client.UNAUTHORIZED)
+ self.handler.wfile.seek(0, 0)
+ d = self.handler.wfile.read()
+ self.assertEqual(json.loads(d.decode()), ['login failed'])
+
+ finally:
+ self.handler._is_user_logged_in = orig_is_user_logged_in
+ self.handler._check_user_name_and_pwd = orig_check_user_name_and_pwd
+
class MyCommandControl(CommandControl):
def _get_modules_specification(self):
return {}
@@ -470,6 +549,88 @@ class TestSecureHTTPServer(unittest.TestCase):
self.assertEqual(1, len(self.server._user_infos))
self.assertTrue('root' in self.server._user_infos)
+ def test_get_user_info(self):
+ self.assertIsNone(self.server.get_user_info('root'))
+ self.server._create_user_info(SRC_FILE_PATH + 'cmdctl-accounts.csv')
+ self.assertIn('6f0c73bd33101a5ec0294b3ca39fec90ef4717fe',
+ self.server.get_user_info('root'))
+
+ # When the file is not changed calling _create_user_info() again
+ # should have no effect. In order to test this, we overwrite the
+ # user-infos that were just set and make sure it isn't touched by
+ # the call (so make sure it isn't set to some empty value)
+ fake_users_val = { 'notinfile': [] }
+ self.server._user_infos = fake_users_val
+ self.server._create_user_info(SRC_FILE_PATH + 'cmdctl-accounts.csv')
+ self.assertEqual(fake_users_val, self.server._user_infos)
+
+ def test_create_user_info_changing_file_time(self):
+ self.assertEqual(0, len(self.server._user_infos))
+
+ # Create a file
+ accounts_file = BUILD_FILE_PATH + 'new_file.csv'
+ with TmpTextFile(accounts_file, ['root,foo,bar']):
+ self.server._create_user_info(accounts_file)
+ self.assertEqual(1, len(self.server._user_infos))
+ self.assertTrue('root' in self.server._user_infos)
+
+ # Make sure re-reading is a noop if file was not modified
+ fake_users_val = { 'notinfile': [] }
+ self.server._user_infos = fake_users_val
+ self.server._create_user_info(accounts_file)
+ self.assertEqual(fake_users_val, self.server._user_infos)
+
+ # create the file again, this time read should not be a noop
+ with TmpTextFile(accounts_file, ['otherroot,foo,bar']):
+ # Set mtime in future
+ stat = os.stat(accounts_file)
+ os.utime(accounts_file, (stat.st_atime, stat.st_mtime + 10))
+ self.server._create_user_info(accounts_file)
+ self.assertEqual(1, len(self.server._user_infos))
+ self.assertTrue('otherroot' in self.server._user_infos)
+
+ def test_create_user_info_changing_file_name(self):
+ """
+ Check that the accounts file is re-read if the file name is different
+ """
+ self.assertEqual(0, len(self.server._user_infos))
+
+ # Create two files
+ accounts_file1 = BUILD_FILE_PATH + 'new_file.csv'
+ accounts_file2 = BUILD_FILE_PATH + 'new_file2.csv'
+ with TmpTextFile(accounts_file2, ['otherroot,foo,bar']):
+ with TmpTextFile(accounts_file1, ['root,foo,bar']):
+ self.server._create_user_info(accounts_file1)
+ self.assertEqual(1, len(self.server._user_infos))
+ self.assertTrue('root' in self.server._user_infos)
+
+ # Make sure re-reading is a noop if file was not modified
+ fake_users_val = { 'notinfile': [] }
+ self.server._user_infos = fake_users_val
+ self.server._create_user_info(accounts_file1)
+ self.assertEqual(fake_users_val, self.server._user_infos)
+
+ # But a different file should be read
+ self.server._create_user_info(accounts_file2)
+ self.assertEqual(1, len(self.server._user_infos))
+ self.assertTrue('otherroot' in self.server._user_infos)
+
+ def test_create_user_info_nonexistent_file(self):
+ # Even if there was data initially, if set to a nonexistent
+ # file it should result in no users
+ accounts_file = BUILD_FILE_PATH + 'new_file.csv'
+ self.assertFalse(os.path.exists(accounts_file))
+ fake_users_val = { 'notinfile': [] }
+ self.server._user_infos = fake_users_val
+ self.server._create_user_info(accounts_file)
+ self.assertEqual({}, self.server._user_infos)
+
+ # Should it now be created it should be read
+ with TmpTextFile(accounts_file, ['root,foo,bar']):
+ self.server._create_user_info(accounts_file)
+ self.assertEqual(1, len(self.server._user_infos))
+ self.assertTrue('root' in self.server._user_infos)
+
def test_check_file(self):
# Just some file that we know exists
file_name = BUILD_FILE_PATH + 'cmdctl-keyfile.pem'
diff --git a/src/bin/dbutil/dbutil.py.in b/src/bin/dbutil/dbutil.py.in
index 7a1469c..292a0ba 100755
--- a/src/bin/dbutil/dbutil.py.in
+++ b/src/bin/dbutil/dbutil.py.in
@@ -16,7 +16,7 @@
# WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
"""
- at file Dabase Utilities
+ at file Database Utilities
This file holds the "dbutil" program, a general utility program for doing
management of the BIND 10 database. There are two modes of operation:
diff --git a/src/bin/dbutil/tests/dbutil_test.sh.in b/src/bin/dbutil/tests/dbutil_test.sh.in
index 4bc9f85..f14c564 100755
--- a/src/bin/dbutil/tests/dbutil_test.sh.in
+++ b/src/bin/dbutil/tests/dbutil_test.sh.in
@@ -132,7 +132,7 @@ check_no_backup() {
# .schema command, with spaces removed and upper converted to lowercase.
#
# The database is copied before the schema is taken (and removed after)
-# as SQLite3 assummes a writeable database, which may not be the case if
+# as SQLite3 assumes a writeable database, which may not be the case if
# getting the schema from a reference copy.
#
# @param $1 Database for which the schema is required
@@ -161,7 +161,7 @@ get_schema() {
# @param $2 Expected backup file
upgrade_ok_test() {
copy_file $1 $tempfile
- ${SHELL} ../run_dbutil.sh --upgrade --noconfirm $tempfile
+ @SHELL@ ../run_dbutil.sh --upgrade --noconfirm $tempfile
if [ $? -eq 0 ]
then
# Compare schema with the reference
@@ -199,7 +199,7 @@ upgrade_ok_test() {
# @param $2 Expected backup file
upgrade_fail_test() {
copy_file $1 $tempfile
- ${SHELL} ../run_dbutil.sh --upgrade --noconfirm $tempfile
+ @SHELL@ ../run_dbutil.sh --upgrade --noconfirm $tempfile
failzero $?
check_backup $1 $backupfile
}
@@ -222,7 +222,7 @@ record_count_test() {
records_count=`sqlite3 $tempfile 'select count(*) from records'`
zones_count=`sqlite3 $tempfile 'select count(*) from zones'`
- ${SHELL} ../run_dbutil.sh --upgrade --noconfirm $tempfile
+ @SHELL@ ../run_dbutil.sh --upgrade --noconfirm $tempfile
if [ $? -ne 0 ]
then
# Reason for failure should already have been output
@@ -268,12 +268,12 @@ record_count_test() {
# @param $2 Expected version string
check_version() {
copy_file $1 $verfile
- ${SHELL} ../run_dbutil.sh --check $verfile
+ @SHELL@ ../run_dbutil.sh --check $verfile
if [ $? -gt 2 ]
then
fail "version check failed on database $1; return code $?"
else
- ${SHELL} ../run_dbutil.sh --check $verfile 2>&1 | grep "$2" > /dev/null
+ @SHELL@ ../run_dbutil.sh --check $verfile 2>&1 | grep "$2" > /dev/null
if [ $? -ne 0 ]
then
fail "database $1 not at expected version $2 (output: $?)"
@@ -293,7 +293,7 @@ check_version() {
# @param $2 Backup file
check_version_fail() {
copy_file $1 $verfile
- ${SHELL} ../run_dbutil.sh --check $verfile
+ @SHELL@ ../run_dbutil.sh --check $verfile
failzero $?
check_no_backup $tempfile $backupfile
}
@@ -310,12 +310,12 @@ sec=0
# Test: check that the utility fails if the database does not exist
sec=`expr $sec + 1`
echo $sec".1. Non-existent database - check"
-${SHELL} ../run_dbutil.sh --check $tempfile
+ at SHELL@ ../run_dbutil.sh --check $tempfile
failzero $?
check_no_backup $tempfile $backupfile
echo $sec".2. Non-existent database - upgrade"
-${SHELL} ../run_dbutil.sh --upgrade --noconfirm $tempfile
+ at SHELL@ ../run_dbutil.sh --upgrade --noconfirm $tempfile
failzero $?
check_no_backup $tempfile $backupfile
rm -f $tempfile $backupfile
@@ -330,7 +330,7 @@ rm -f $tempfile $backupfile
echo $sec".2. Database is an empty file - upgrade"
touch $tempfile
-${SHELL} ../run_dbutil.sh --upgrade --noconfirm $tempfile
+ at SHELL@ ../run_dbutil.sh --upgrade --noconfirm $tempfile
failzero $?
# A backup is performed before anything else, so the backup should exist.
check_backup $tempfile $backupfile
@@ -344,7 +344,7 @@ rm -f $tempfile $backupfile
echo $sec".2. Database is not an SQLite file - upgrade"
echo "This is not an sqlite3 database" > $tempfile
-${SHELL} ../run_dbutil.sh --upgrade --noconfirm $tempfile
+ at SHELL@ ../run_dbutil.sh --upgrade --noconfirm $tempfile
failzero $?
# ...and as before, a backup should have been created
check_backup $tempfile $backupfile
@@ -459,31 +459,31 @@ rm -f $tempfile $backupfile ${backupfile}-1 ${backupfile}-2
sec=`expr $sec + 1`
echo $sec".1 Command-line errors"
copy_file $testdata/old_v1.sqlite3 $tempfile
-${SHELL} ../run_dbutil.sh $tempfile
+ at SHELL@ ../run_dbutil.sh $tempfile
failzero $?
-${SHELL} ../run_dbutil.sh --upgrade --check $tempfile
+ at SHELL@ ../run_dbutil.sh --upgrade --check $tempfile
failzero $?
-${SHELL} ../run_dbutil.sh --noconfirm --check $tempfile
+ at SHELL@ ../run_dbutil.sh --noconfirm --check $tempfile
failzero $?
-${SHELL} ../run_dbutil.sh --check
+ at SHELL@ ../run_dbutil.sh --check
failzero $?
-${SHELL} ../run_dbutil.sh --upgrade --noconfirm
+ at SHELL@ ../run_dbutil.sh --upgrade --noconfirm
failzero $?
-${SHELL} ../run_dbutil.sh --check $tempfile $backupfile
+ at SHELL@ ../run_dbutil.sh --check $tempfile $backupfile
failzero $?
-${SHELL} ../run_dbutil.sh --upgrade --noconfirm $tempfile $backupfile
+ at SHELL@ ../run_dbutil.sh --upgrade --noconfirm $tempfile $backupfile
failzero $?
rm -f $tempfile $backupfile
echo $sec".2 verbose flag"
copy_file $testdata/old_v1.sqlite3 $tempfile
-${SHELL} ../run_dbutil.sh --upgrade --noconfirm --verbose $tempfile
+ at SHELL@ ../run_dbutil.sh --upgrade --noconfirm --verbose $tempfile
passzero $?
rm -f $tempfile $backupfile
echo $sec".3 Interactive prompt - yes"
copy_file $testdata/old_v1.sqlite3 $tempfile
-${SHELL} ../run_dbutil.sh --upgrade $tempfile << .
+ at SHELL@ ../run_dbutil.sh --upgrade $tempfile << .
Yes
.
passzero $?
@@ -492,7 +492,7 @@ rm -f $tempfile $backupfile
echo $sec".4 Interactive prompt - no"
copy_file $testdata/old_v1.sqlite3 $tempfile
-${SHELL} ../run_dbutil.sh --upgrade $tempfile << .
+ at SHELL@ ../run_dbutil.sh --upgrade $tempfile << .
no
.
passzero $?
@@ -502,7 +502,7 @@ rm -f $tempfile $backupfile
echo $sec".5 quiet flag"
copy_file $testdata/old_v1.sqlite3 $tempfile
-${SHELL} ../run_dbutil.sh --check --quiet $tempfile 2>&1 | grep .
+ at SHELL@ ../run_dbutil.sh --check --quiet $tempfile 2>&1 | grep .
failzero $?
rm -f $tempfile $backupfile
diff --git a/src/bin/ddns/ddns.py.in b/src/bin/ddns/ddns.py.in
index d382495..47f67ca 100755
--- a/src/bin/ddns/ddns.py.in
+++ b/src/bin/ddns/ddns.py.in
@@ -236,7 +236,7 @@ class DDNSServer:
'''Exception for internal errors in an update session.
This exception is expected to be caught within the server class,
- only used for controling the code flow.
+ only used for controlling the code flow.
'''
pass
@@ -354,7 +354,7 @@ class DDNSServer:
zname = Name(zone_spec['name'])
# class has the default value in case it's unspecified.
# ideally this should be merged within the config module, but
- # the current implementation doesn't esnure that, so we need to
+ # the current implementation doesn't ensure that, so we need to
# subsitute it ourselves.
if 'class' in zone_spec:
zclass = RRClass(zone_spec['class'])
@@ -510,8 +510,8 @@ class DDNSServer:
'''Send DDNS response to the client.
Right now, this is a straightforward subroutine of handle_request(),
- but is intended to be extended evetually so that it can handle more
- comlicated operations for TCP (which requires asynchronous write).
+ but is intended to be extended eventually so that it can handle more
+ complicated operations for TCP (which requires asynchronous write).
Further, when we support multiple requests over a single TCP
connection, this method may even be shared by multiple methods.
diff --git a/src/bin/ddns/ddns_messages.mes b/src/bin/ddns/ddns_messages.mes
index 7d440d9..c537ae4 100644
--- a/src/bin/ddns/ddns_messages.mes
+++ b/src/bin/ddns/ddns_messages.mes
@@ -141,7 +141,7 @@ logged.
% DDNS_RESPONSE_TCP_SOCKET_SEND_FAILED failed to complete sending update response to %1 over TCP
b10-ddns had tried to send an update response over TCP, and it hadn't
-been completed at that time, and a followup attempt to complete the
+been completed at that time, and a follow-up attempt to complete the
send operation failed due to some network I/O error. While a network
error can happen any time, this event is quite unexpected for two
reasons. First, since the size of a response to an update request
diff --git a/src/bin/ddns/tests/ddns_test.py b/src/bin/ddns/tests/ddns_test.py
index e7d2099..4cf31be 100755
--- a/src/bin/ddns/tests/ddns_test.py
+++ b/src/bin/ddns/tests/ddns_test.py
@@ -40,7 +40,7 @@ READ_ZONE_DB_FILE = TESTDATA_PATH + "rwtest.sqlite3" # original, to be copied
TEST_ZONE_NAME = Name('example.org')
TEST_ZONE_NAME_STR = TEST_ZONE_NAME.to_text()
UPDATE_RRTYPE = RRType.SOA
-TEST_QID = 5353 # arbitrary chosen
+TEST_QID = 5353 # arbitrarily chosen
TEST_RRCLASS = RRClass.IN
TEST_RRCLASS_STR = TEST_RRCLASS.to_text()
TEST_SERVER6 = ('2001:db8::53', 53, 0, 0)
@@ -53,7 +53,7 @@ TEST_ACL_CONTEXT = isc.acl.dns.RequestContext(
socket.IPPROTO_UDP, socket.AI_NUMERICHOST)[0][4])
# TSIG key for tests when needed. The key name is TEST_ZONE_NAME.
TEST_TSIG_KEY = TSIGKey("example.org:SFuWd/q99SzF8Yzd1QbB9g==")
-# TSIG keyring that contanins the test key
+# TSIG keyring that contains the test key
TEST_TSIG_KEYRING = TSIGKeyRing()
TEST_TSIG_KEYRING.add(TEST_TSIG_KEY)
# Another TSIG key not in the keyring, making verification fail
@@ -450,7 +450,7 @@ class TestDDNSServer(unittest.TestCase):
self.assertEqual(1, isc.config.parse_answer(answer)[0])
self.assertEqual({}, self.ddns_server._zone_config)
- # the first zone cofig is valid, but not the second. the first one
+ # the first zone config is valid, but not the second. the first one
# shouldn't be installed.
bad_config = { 'zones': [ { 'origin': TEST_ZONE_NAME_STR,
'class': TEST_RRCLASS_STR,
@@ -856,7 +856,7 @@ class TestDDNSServer(unittest.TestCase):
def test_select_multi_tcp(self):
'''Test continuation of sending a TCP response, multiple sockets.'''
# Check if the implementation still works with multiple outstanding
- # TCP contexts. We use three (arbitray choice), of which two will be
+ # TCP contexts. We use three (arbitrary choice), of which two will be
# writable after select and complete the send.
tcp_socks = []
for i in range(0, 3):
diff --git a/src/bin/dhcp4/ctrl_dhcp4_srv.cc b/src/bin/dhcp4/ctrl_dhcp4_srv.cc
index 8ac49d3..eb7d559 100644
--- a/src/bin/dhcp4/ctrl_dhcp4_srv.cc
+++ b/src/bin/dhcp4/ctrl_dhcp4_srv.cc
@@ -156,7 +156,7 @@ void ControlledDhcpv4Srv::establishSession() {
// Dumy configuration handler is internally invoked by the
// constructor and on success the constructor updates
// the current session with the configuration that had been
- // commited in the previous session. If we did not install
+ // committed in the previous session. If we did not install
// the dummy handler, the previous configuration would have
// been lost.
config_session_ = new ModuleCCSession(specfile, *cc_session_,
diff --git a/src/bin/dhcp4/ctrl_dhcp4_srv.h b/src/bin/dhcp4/ctrl_dhcp4_srv.h
index ac15c44..e45deff 100644
--- a/src/bin/dhcp4/ctrl_dhcp4_srv.h
+++ b/src/bin/dhcp4/ctrl_dhcp4_srv.h
@@ -136,7 +136,7 @@ protected:
/// @brief Helper session object that represents raw connection to msgq.
isc::cc::Session* cc_session_;
- /// @brief Session that receives configuation and commands
+ /// @brief Session that receives configuration and commands
isc::config::ModuleCCSession* config_session_;
};
diff --git a/src/bin/dhcp4/dhcp4.dox b/src/bin/dhcp4/dhcp4.dox
index c189c8a..86ae845 100644
--- a/src/bin/dhcp4/dhcp4.dox
+++ b/src/bin/dhcp4/dhcp4.dox
@@ -33,7 +33,7 @@ assigned is not implemented in IfaceMgr yet.
DHCPv4 server component is now integrated with BIND10 message queue.
The integration is performed by establishSession() and disconnectSession()
-functions in isc::dhcp::ControlledDhcpv4Srv class. main() method deifined
+functions in isc::dhcp::ControlledDhcpv4Srv class. main() method defined
in the src/bin/dhcp4/main.cc file instantiates isc::dhcp::ControlledDhcpv4Srv
class that establishes connection with msgq and install necessary handlers
for receiving commands and configuration updates. It is derived from
diff --git a/src/bin/dhcp4/tests/config_parser_unittest.cc b/src/bin/dhcp4/tests/config_parser_unittest.cc
index 9b3be51..80b304c 100644
--- a/src/bin/dhcp4/tests/config_parser_unittest.cc
+++ b/src/bin/dhcp4/tests/config_parser_unittest.cc
@@ -487,7 +487,7 @@ TEST_F(Dhcp4ParserTest, optionDefIpv4Address) {
EXPECT_TRUE(def->getEncapsulatedSpace().empty());
}
-// The goal of this test is to check whether an option definiiton
+// The goal of this test is to check whether an option definition
// that defines an option carrying a record of data fields can
// be created.
TEST_F(Dhcp4ParserTest, optionDefRecord) {
@@ -1060,7 +1060,7 @@ TEST_F(Dhcp4ParserTest, optionDataTwoSpaces) {
ASSERT_TRUE(status);
checkResult(status, 0);
- // Options should be now availabe for the subnet.
+ // Options should be now available for the subnet.
Subnet4Ptr subnet = CfgMgr::instance().getSubnet4(IOAddress("192.0.2.200"));
ASSERT_TRUE(subnet);
// Try to get the option from the space dhcp4.
@@ -1430,7 +1430,7 @@ TEST_F(Dhcp4ParserTest, optionDataInvalidChar) {
testInvalidOptionParam("01020R", "data");
}
-// Verify that option data containins '0x' prefix is rejected
+// Verify that option data containing '0x' prefix is rejected
// by the configuration.
TEST_F(Dhcp4ParserTest, optionDataUnexpectedPrefix) {
// Option code 0 is reserved and should not be accepted
@@ -1530,7 +1530,7 @@ TEST_F(Dhcp4ParserTest, stdOptionData) {
boost::shared_ptr<Option4AddrLst> option_addrs =
boost::dynamic_pointer_cast<Option4AddrLst>(option);
// If cast is unsuccessful than option returned was of a
- // differnt type than Option6IA. This is wrong.
+ // different type than Option6IA. This is wrong.
ASSERT_TRUE(option_addrs);
// Get addresses from the option.
diff --git a/src/bin/dhcp6/ctrl_dhcp6_srv.cc b/src/bin/dhcp6/ctrl_dhcp6_srv.cc
index e4e17f1..c3488e5 100644
--- a/src/bin/dhcp6/ctrl_dhcp6_srv.cc
+++ b/src/bin/dhcp6/ctrl_dhcp6_srv.cc
@@ -155,7 +155,7 @@ void ControlledDhcpv6Srv::establishSession() {
// Dumy configuration handler is internally invoked by the
// constructor and on success the constructor updates
// the current session with the configuration that had been
- // commited in the previous session. If we did not install
+ // committed in the previous session. If we did not install
// the dummy handler, the previous configuration would have
// been lost.
config_session_ = new ModuleCCSession(specfile, *cc_session_,
diff --git a/src/bin/dhcp6/ctrl_dhcp6_srv.h b/src/bin/dhcp6/ctrl_dhcp6_srv.h
index 0e699ce..908304d 100644
--- a/src/bin/dhcp6/ctrl_dhcp6_srv.h
+++ b/src/bin/dhcp6/ctrl_dhcp6_srv.h
@@ -134,7 +134,7 @@ protected:
/// @brief Helper session object that represents raw connection to msgq.
isc::cc::Session* cc_session_;
- /// @brief Session that receives configuation and commands
+ /// @brief Session that receives configuration and commands
isc::config::ModuleCCSession* config_session_;
};
diff --git a/src/bin/dhcp6/dhcp6.dox b/src/bin/dhcp6/dhcp6.dox
index 3a738ec..4376a2a 100644
--- a/src/bin/dhcp6/dhcp6.dox
+++ b/src/bin/dhcp6/dhcp6.dox
@@ -51,7 +51,7 @@
list of parsers for each received entry. Parser is an object that is derived
from a DhcpConfigParser class. Once a parser is created
(constructor), its value is set (using build() method). Once all parsers are
- build, the configuration is then applied ("commited") and commit() method is
+ build, the configuration is then applied ("committed") and commit() method is
called.
All parsers are defined in src/bin/dhcp6/config_parser.cc file. Some of them
diff --git a/src/bin/dhcp6/dhcp6_srv.cc b/src/bin/dhcp6/dhcp6_srv.cc
index 5f1580f..4c19e74 100644
--- a/src/bin/dhcp6/dhcp6_srv.cc
+++ b/src/bin/dhcp6/dhcp6_srv.cc
@@ -353,7 +353,7 @@ Dhcpv6Srv::generateServerID() {
}
// Some interfaces (like lo on Linux) report 6-bytes long
- // MAC adress 00:00:00:00:00:00. Let's not use such weird interfaces
+ // MAC address 00:00:00:00:00:00. Let's not use such weird interfaces
// to generate DUID.
if (isRangeZero(iface->getMac(), iface->getMac() + iface->getMacLen())) {
continue;
diff --git a/src/bin/dhcp6/tests/config_parser_unittest.cc b/src/bin/dhcp6/tests/config_parser_unittest.cc
index 4430cb2..63fc980 100644
--- a/src/bin/dhcp6/tests/config_parser_unittest.cc
+++ b/src/bin/dhcp6/tests/config_parser_unittest.cc
@@ -598,7 +598,7 @@ TEST_F(Dhcp6ParserTest, optionDefIpv6Address) {
EXPECT_EQ(OPT_IPV6_ADDRESS_TYPE, def->getType());
}
-// The goal of this test is to check whether an option definiiton
+// The goal of this test is to check whether an option definition
// that defines an option carrying a record of data fields can
// be created.
TEST_F(Dhcp6ParserTest, optionDefRecord) {
@@ -1176,7 +1176,7 @@ TEST_F(Dhcp6ParserTest, optionDataTwoSpaces) {
ASSERT_TRUE(status);
checkResult(status, 0);
- // Options should be now availabe for the subnet.
+ // Options should be now available for the subnet.
Subnet6Ptr subnet = CfgMgr::instance().getSubnet6(IOAddress("2001:db8:1::5"));
ASSERT_TRUE(subnet);
// Try to get the option from the space dhcp6.
@@ -1484,7 +1484,7 @@ TEST_F(Dhcp6ParserTest, optionDataInvalidChar) {
testInvalidOptionParam("01020R", "data");
}
-// Verify that option data containins '0x' prefix is rejected
+// Verify that option data containing '0x' prefix is rejected
// by the configuration.
TEST_F(Dhcp6ParserTest, optionDataUnexpectedPrefix) {
// Option code 0 is reserved and should not be accepted
@@ -1582,7 +1582,7 @@ TEST_F(Dhcp6ParserTest, stdOptionData) {
boost::shared_ptr<Option6IA> optionIA =
boost::dynamic_pointer_cast<Option6IA>(option);
// If cast is unsuccessful than option returned was of a
- // differnt type than Option6IA. This is wrong.
+ // different type than Option6IA. This is wrong.
ASSERT_TRUE(optionIA);
// If cast was successful we may use accessors exposed by
// Option6IA to validate that the content of this option
diff --git a/src/bin/loadzone/tests/correct/correct_test.sh.in b/src/bin/loadzone/tests/correct/correct_test.sh.in
index 505411c..627ec68 100755
--- a/src/bin/loadzone/tests/correct/correct_test.sh.in
+++ b/src/bin/loadzone/tests/correct/correct_test.sh.in
@@ -53,7 +53,7 @@ echo "I:test master file BIND 8 compatibility TTL and \$TTL semantics"
echo "I:test master file RFC1035 TTL and \$TTL semantics"
echo "I:test master file BIND8 compatibility and mixed \$INCLUDE with \$TTL semantics"
echo "I:test master file RFC1035 TTL and mixed \$INCLUDE with \$TTL semantics"
-echo "I:test master file BIND9 extenstion of TTL"
+echo "I:test master file BIND9 extension of TTL"
echo "I:test master file RFC1035 missing CLASS, TTL, NAME semantics"
echo "I:test master file comments"
diff --git a/src/bin/loadzone/tests/correct/ttlext.db b/src/bin/loadzone/tests/correct/ttlext.db
index f8b96ea..3aa37e8 100644
--- a/src/bin/loadzone/tests/correct/ttlext.db
+++ b/src/bin/loadzone/tests/correct/ttlext.db
@@ -11,7 +11,7 @@ ns A 10.53.0.1
a TXT "soa minttl 3"
b 2S TXT "explicit ttl 2"
c TXT "soa minttl 3"
-$TTL 10M ; bind9 extention ttl
+$TTL 10M ; bind9 extension ttl
d TXT "default ttl 600"
e 4 TXT "explicit ttl 4"
f TXT "default ttl 600"
diff --git a/src/bin/loadzone/tests/loadzone_test.py b/src/bin/loadzone/tests/loadzone_test.py
index 351bc59..16499ba 100755
--- a/src/bin/loadzone/tests/loadzone_test.py
+++ b/src/bin/loadzone/tests/loadzone_test.py
@@ -41,7 +41,7 @@ ORIG_SOA_TXT = 'example.org. 3600 IN SOA ns1.example.org. ' +\
'admin.example.org. 1234 3600 1800 2419200 7200\n'
NEW_SOA_TXT = 'example.org. 3600 IN SOA ns.example.org. ' +\
'admin.example.org. 1235 3600 1800 2419200 7200\n'
-# This is the brandnew SOA for a newly created zone
+# This is the brand new SOA for a newly created zone
ALT_NEW_SOA_TXT = 'example.com. 3600 IN SOA ns.example.com. ' +\
'admin.example.com. 1234 3600 1800 2419200 7200\n'
diff --git a/src/bin/msgq/Makefile.am b/src/bin/msgq/Makefile.am
index a49b125..185d47a 100644
--- a/src/bin/msgq/Makefile.am
+++ b/src/bin/msgq/Makefile.am
@@ -10,6 +10,7 @@ b10_msgq_DATA = msgq.spec
CLEANFILES = b10-msgq msgq.pyc
CLEANFILES += $(PYTHON_LOGMSGPKG_DIR)/work/msgq_messages.py
CLEANFILES += $(PYTHON_LOGMSGPKG_DIR)/work/msgq_messages.pyc
+CLEANFILES += $(PYTHON_LOGMSGPKG_DIR)/work/msgq_messages.pyo
man_MANS = b10-msgq.8
DISTCLEANFILES = $(man_MANS)
diff --git a/src/bin/msgq/msgq.py.in b/src/bin/msgq/msgq.py.in
index 63d008e..8cf6191 100755
--- a/src/bin/msgq/msgq.py.in
+++ b/src/bin/msgq/msgq.py.in
@@ -143,7 +143,7 @@ class SubscriptionManager:
this group, instance pair. This includes wildcard subscriptions."""
target = (group, instance)
partone = self.find_sub(group, instance)
- parttwo = self.find_sub(group, "*")
+ parttwo = self.find_sub(group, CC_INSTANCE_WILDCARD)
return list(set(partone + parttwo))
class MsgQ:
@@ -406,7 +406,7 @@ class MsgQ:
routing, data = self.read_packet(fd, sock)
except (MsgQReceiveError, MsgQCloseOnReceive) as err:
# If it's MsgQCloseOnReceive and that happens without reading
- # any data, it basically means the remote clinet has closed the
+ # any data, it basically means the remote client has closed the
# socket, so we log it as debug information. Otherwise, it's
# a somewhat unexpected event, so we consider it an "error".
if isinstance(err, MsgQCloseOnReceive) and not err.partial_read:
@@ -429,19 +429,19 @@ class MsgQ:
"""Process a single command. This will split out into one of the
other functions."""
logger.debug(TRACE_DETAIL, MSGQ_RECV_HDR, routing)
- cmd = routing["type"]
- if cmd == 'send':
+ cmd = routing[CC_HEADER_TYPE]
+ if cmd == CC_COMMAND_SEND:
self.process_command_send(sock, routing, data)
- elif cmd == 'subscribe':
+ elif cmd == CC_COMMAND_SUBSCRIBE:
self.process_command_subscribe(sock, routing, data)
- elif cmd == 'unsubscribe':
+ elif cmd == CC_COMMAND_UNSUBSCRIBE:
self.process_command_unsubscribe(sock, routing, data)
- elif cmd == 'getlname':
+ elif cmd == CC_COMMAND_GET_LNAME:
self.process_command_getlname(sock, routing, data)
- elif cmd == 'ping':
+ elif cmd == CC_COMMAND_PING:
# Command for testing purposes
self.process_command_ping(sock, routing, data)
- elif cmd == 'stop':
+ elif cmd == CC_COMMAND_STOP:
self.stop()
else:
logger.error(MSGQ_INVALID_CMD, cmd)
@@ -570,11 +570,12 @@ class MsgQ:
return "%x_%x@%s" % (time.time(), self.connection_counter, self.hostname)
def process_command_ping(self, sock, routing, data):
- self.sendmsg(sock, { "type" : "pong" }, data)
+ self.sendmsg(sock, { CC_HEADER_TYPE : CC_COMMAND_PONG }, data)
def process_command_getlname(self, sock, routing, data):
lname = [ k for k, v in self.lnames.items() if v == sock ][0]
- self.sendmsg(sock, { "type" : "getlname" }, { "lname" : lname })
+ self.sendmsg(sock, { CC_HEADER_TYPE : CC_COMMAND_GET_LNAME },
+ { CC_PAYLOAD_LNAME : lname })
def process_command_send(self, sock, routing, data):
group = routing[CC_HEADER_GROUP]
@@ -638,15 +639,15 @@ class MsgQ:
self.send_prepared_msg(sock, errmsg)
def process_command_subscribe(self, sock, routing, data):
- group = routing["group"]
- instance = routing["instance"]
+ group = routing[CC_HEADER_GROUP]
+ instance = routing[CC_HEADER_INSTANCE]
if group == None or instance == None:
return # ignore invalid packets entirely
self.subs.subscribe(group, instance, sock)
def process_command_unsubscribe(self, sock, routing, data):
- group = routing["group"]
- instance = routing["instance"]
+ group = routing[CC_HEADER_GROUP]
+ instance = routing[CC_HEADER_INSTANCE]
if group == None or instance == None:
return # ignore invalid packets entirely
self.subs.unsubscribe(group, instance, sock)
diff --git a/src/bin/msgq/run_msgq.sh.in b/src/bin/msgq/run_msgq.sh.in
index c9fef64..6b175d6 100644
--- a/src/bin/msgq/run_msgq.sh.in
+++ b/src/bin/msgq/run_msgq.sh.in
@@ -20,7 +20,7 @@ export PYTHON_EXEC
MYPATH_PATH=@abs_top_builddir@/src/bin/msgq
-PYTHONPATH=@abs_top_builddir@/src/lib/python/isc/log_messages:@abs_top_builddir@/src/lib/python/isc/cc:@abs_top_builddir@/src/lib/python:@abs_top_builddir@/src/lib/log/.libs
+PYTHONPATH=@abs_top_builddir@/src/lib/python/isc/log_messages:@abs_top_builddir@/src/lib/python/isc/cc:@abs_top_srcdir@/src/lib/python:@abs_top_builddir@/src/lib/python:@abs_top_builddir@/src/lib/dns/python/.libs
export PYTHONPATH
# If necessary (rare cases), explicitly specify paths to dynamic libraries
diff --git a/src/bin/msgq/tests/Makefile.am b/src/bin/msgq/tests/Makefile.am
index c9ef5d3..eca8c9b 100644
--- a/src/bin/msgq/tests/Makefile.am
+++ b/src/bin/msgq/tests/Makefile.am
@@ -1,5 +1,5 @@
-PYCOVERAGE_RUN = @PYCOVERAGE_RUN@
-PYTESTS = msgq_test.py
+PYCOVERAGE_RUN = @PYCOVERAGE_RUN@
+PYTESTS = msgq_test.py msgq_run_test.py
EXTRA_DIST = $(PYTESTS)
# If necessary (rare cases), explicitly specify paths to dynamic libraries
@@ -12,7 +12,7 @@ endif
# test using command-line arguments, so use check-local target instead of TESTS
check-local:
if ENABLE_PYTHON_COVERAGE
- touch $(abs_top_srcdir)/.coverage
+ touch $(abs_top_srcdir)/.coverage
rm -f .coverage
${LN_S} $(abs_top_srcdir)/.coverage .coverage
endif
diff --git a/src/bin/msgq/tests/msgq_run_test.py b/src/bin/msgq/tests/msgq_run_test.py
new file mode 100644
index 0000000..8e8cb65
--- /dev/null
+++ b/src/bin/msgq/tests/msgq_run_test.py
@@ -0,0 +1,269 @@
+# Copyright (C) 2013 Internet Systems Consortium.
+#
+# Permission to use, copy, modify, and 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 INTERNET SYSTEMS CONSORTIUM
+# DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+# INTERNET SYSTEMS CONSORTIUM 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.
+
+"""
+In this test file, we actually start msgq as a process and test it
+as a whole. It may be considered a system test instead of unit test,
+but apart from the terminology, we don't care much. We need to test
+the message queue works as expected, together with the libraries.
+
+In each test, we first start a timeout (because we do some waits
+for messages and if they wouldn't come, the test could block indefinitely).
+The timeout is long, because it is for the case the test fails.
+
+We then start the msgq and wait for the socket file to appear
+(that should indicate it is ready to receive connections). Then the
+actual test starts. After the test, we kill it and remove the test file.
+
+We also register signal handlers for many signals. Even in the case
+the test is interrupted or crashes, we should ensure the message queue
+itself is terminated.
+"""
+
+import unittest
+import os
+import signal
+import sys
+import subprocess
+import time
+
+import isc.log
+import isc.cc.session
+from isc.cc.proto_defs import *
+
+# Due to problems with too long path on build bots, we place the socket
+# into the top-level build directory. That is ugly, but works.
+SOCKET_PATH = os.path.abspath(os.environ['B10_FROM_BUILD'] + '/msgq.sock')
+MSGQ_PATH = os.environ['B10_FROM_BUILD'] + '/src/bin/msgq/run_msgq.sh'
+TIMEOUT = 15 # Some long time (seconds), for single test.
+
+class MsgqRunTest(unittest.TestCase):
+ def setUp(self):
+ """
+ As described above - check the socket file does not exist.
+ Then register signals and timeouts. Finally, launch msgq
+ and wait for it to start.
+ """
+ self.__msgq = None
+ self.__opened_connections = []
+ # A precondition check
+ self.assertFalse(os.path.exists(SOCKET_PATH))
+ signal.alarm(TIMEOUT)
+ self.__orig_signals = {}
+ # Register handlers for many signals. Most of them probably
+ # can't happen in python, but we register them anyway just to be
+ # safe.
+ for sig in [signal.SIGHUP, signal.SIGINT, signal.SIGQUIT,
+ signal.SIGILL, signal.SIGTRAP, signal.SIGABRT, signal.SIGBUS,
+ signal.SIGFPE, signal.SIGALRM, signal.SIGTERM]:
+ self.__orig_signals[sig] = signal.signal(sig, self.__signal)
+ # Start msgq
+ self.__msgq = subprocess.Popen([MSGQ_PATH, '-s', SOCKET_PATH],
+ close_fds=True)
+ # Wait for it to become ready (up to the alarm-set timeout)
+ while not os.path.exists(SOCKET_PATH):
+ # Just a short wait, so we don't hog CPU, but don't wait too long
+ time.sleep(0.01)
+ # Some testing data
+ self.__no_recpt = {"result": [-1, "No such recipient"]}
+
+ def __message(self, data):
+ """
+ Provide some testing message. The data will be included in it, so
+ several different messages can be created.
+ """
+ return {"Message": "Text", "Data": data}
+
+ def tearDown(self):
+ """
+ Perform cleanup after the test.
+ """
+ self.__cleanup()
+
+ def __signal(self, signal, frame):
+ """
+ Called from a signal handler. We perform some cleanup, output
+ a complain and terminate with error.
+ """
+ self.__cleanup()
+ sys.stderr.write("Test terminating from signal " + str(signal) +
+ " in " + str(frame) + "\n")
+ sys.exit(1)
+
+ def __cleanup(self):
+ """
+ Kill msgq (if running) and restore original signal handlers.
+ """
+ # Remove the socket (as we kill, msgq might not clean up)
+ for conn in self.__opened_connections:
+ conn.close()
+ self.__opened_connections = []
+ if self.__msgq:
+ self.__msgq.kill()
+ self.__msgq = None
+ if os.path.exists(SOCKET_PATH):
+ os.unlink(SOCKET_PATH)
+ for sig in self.__orig_signals:
+ signal.signal(sig, self.__orig_signals[sig])
+ # Cancel timeout (so someone else is not hit by it)
+ signal.alarm(0)
+
+ def __get_connection(self):
+ """
+ Create a connection to the daemon and make sure it is properly closed
+ at the end of the test.
+ """
+ connection = isc.cc.session.Session(SOCKET_PATH)
+ self.__opened_connections.append(connection)
+ return connection
+
+ def test_send_direct(self):
+ """
+ Connect twice to msgq, send a message from one to another using direct
+ l-name and see it comes.
+ """
+ # Create the connections
+ conn1 = self.__get_connection()
+ conn2 = self.__get_connection()
+ # Send the message
+ lname1 = conn1.lname
+ conn2.group_sendmsg(self.__message(1), "*", to=lname1)
+ # Receive the message and see it contains correct data
+ (msg, env) = conn1.group_recvmsg(nonblock=False)
+ self.assertEqual(self.__message(1), msg)
+ # We don't check there are no extra headers, just that none are missing
+ # or wrong.
+ self.assertEqual(lname1, env[CC_HEADER_TO])
+ self.assertEqual(conn2.lname, env[CC_HEADER_FROM])
+ self.assertEqual("*", env[CC_HEADER_GROUP])
+ self.assertEqual(CC_INSTANCE_WILDCARD, env[CC_HEADER_INSTANCE])
+ self.assertEqual(CC_COMMAND_SEND, env[CC_HEADER_TYPE])
+ self.assertFalse(env[CC_HEADER_WANT_ANSWER])
+
+ def __barrier(self, connections):
+ """
+ Make sure all previous commands on all supplied connections are
+ processed, by sending a ping and waiting for an answer.
+ """
+ for c in connections:
+ c.sendmsg({"type": "ping"})
+ for c in connections:
+ pong = c.recvmsg(nonblock=False)
+ self.assertEqual(({"type": "pong"}, None), pong)
+
+ def test_send_group(self):
+ """
+ Create several connections. First, try to send a message to a (empty)
+ group and see an error is bounced back. Then subscribe the others
+ to the group and send it again. Send to a different group and see it
+ bounced back. Unsubscribe and see it is bounced again.
+
+ Then the other connections answer (after unsubscribing, strange, but
+ legal). See both answers come.
+
+ Then, look there are no more waiting messages.
+ """
+ conn_a = self.__get_connection()
+ conn_b = []
+ for i in range(0, 10):
+ conn_b.append(self.__get_connection())
+ # Send a message to empty group and get an error answer
+ seq = conn_a.group_sendmsg(self.__message(1), "group",
+ want_answer=True)
+ (msg, env) = conn_a.group_recvmsg(nonblock=False, seq=seq)
+ self.assertEqual(self.__no_recpt, msg)
+ self.assertEqual(conn_a.lname, env[CC_HEADER_TO])
+ # Subscribe the two connections
+ for c in conn_b:
+ c.group_subscribe("group")
+ # The subscribe doesn't wait for answer, so make sure it is
+ # all processed before continuing.
+ self.__barrier(conn_b)
+ # Send a message to the group (this time not empty)
+ seq = conn_a.group_sendmsg(self.__message(2), "group",
+ want_answer=True)
+ envs = []
+ for c in conn_b:
+ (msg, env) = c.group_recvmsg(nonblock=False)
+ self.assertEqual(self.__message(2), msg)
+ self.assertEqual(conn_a.lname, env[CC_HEADER_FROM])
+ # The daemon does not mangle the headers. Is it OK?
+ self.assertEqual(CC_TO_WILDCARD, env[CC_HEADER_TO])
+ self.assertEqual("group", env[CC_HEADER_GROUP])
+ self.assertEqual(CC_INSTANCE_WILDCARD, env[CC_HEADER_INSTANCE])
+ self.assertEqual(CC_COMMAND_SEND, env[CC_HEADER_TYPE])
+ self.assertTrue(env[CC_HEADER_WANT_ANSWER])
+ envs.append(env)
+ # Send to non-existing group
+ seq_ne = conn_a.group_sendmsg(self.__message(3), "no-group",
+ want_answer=True)
+ (msg, env) = conn_a.group_recvmsg(nonblock=False, seq=seq_ne)
+ self.assertEqual(self.__no_recpt, msg)
+ self.assertEqual(conn_a.lname, env[CC_HEADER_TO])
+ # Unsubscribe the connections
+ for c in conn_b:
+ c.group_unsubscribe("group")
+ # Synchronize the unsubscriptions
+ self.__barrier(conn_b)
+ seq_ne = conn_a.group_sendmsg(self.__message(4), "group",
+ want_answer=True)
+ (msg, env) = conn_a.group_recvmsg(nonblock=False, seq=seq_ne)
+ self.assertEqual(self.__no_recpt, msg)
+ self.assertEqual(conn_a.lname, env[CC_HEADER_TO])
+ # Send answers for the original message that was delivered
+ lnames = set()
+ for (c, env) in zip(conn_b, envs):
+ c.group_reply(env, self.__message("Reply"))
+ lnames.add(c.lname)
+ # Check the both answers come
+ while lnames:
+ # While there are still connections we didn't get the answer from
+ # (the order is not guaranteed, therefore the juggling with set)
+ (msg, env) = conn_a.group_recvmsg(nonblock=False, seq=seq)
+ self.assertEqual(self.__message("Reply"), msg)
+ lname = env[CC_HEADER_FROM]
+ self.assertTrue(lname in lnames)
+ lnames.remove(lname)
+
+ # The barrier makes the msgq process everything we sent. As the
+ # processing is single-threaded in it, any stray message would have
+ # arrived before the barrier ends.
+ self.__barrier(conn_b)
+ self.__barrier([conn_a])
+ for c in conn_b:
+ self.assertEqual((None, None), c.group_recvmsg())
+ self.assertEqual((None, None), conn_a.group_recvmsg())
+
+ def test_conn_disconn(self):
+ """
+ Keep connecting and disconnecting, checking we can still send
+ and receive messages.
+ """
+ conn = self.__get_connection()
+ conn.group_subscribe("group")
+ for i in range(0, 50):
+ new = self.__get_connection()
+ new.group_subscribe("group")
+ self.__barrier([conn, new])
+ new.group_sendmsg(self.__message(i), "group")
+ (msg, env) = conn.group_recvmsg(nonblock=False)
+ self.assertEqual(self.__message(i), msg)
+ conn.close()
+ conn = new
+
+if __name__ == '__main__':
+ isc.log.init("msgq-tests")
+ isc.log.resetUnitTestRootLogger()
+ unittest.main()
diff --git a/src/bin/resolver/response_scrubber.h b/src/bin/resolver/response_scrubber.h
index cb80b26..af4bd97 100644
--- a/src/bin/resolver/response_scrubber.h
+++ b/src/bin/resolver/response_scrubber.h
@@ -25,7 +25,7 @@
/// unsigned data in a response is more of a problem. (Note that even data from
/// signed zones may be not be signed, e.g. delegations are not signed.) In
/// particular, how do we know that the server from which the response was
-/// received was authoritive for the data it returned?
+/// received was authoritative for the data it returned?
///
/// The part of the code that checks for this is the "Data Scrubbing" module.
/// Although it includes the checking of IP addresses and ports, it is called
@@ -219,7 +219,7 @@
/// referral been to the com nameservers, it would be a valid response; the com
/// zone could well be serving all the data for example.com. Having said that,
/// the A record for ns1.example.net would still be regarded as being out of
-/// bailiwick becase the nameserver is not authoritative for the .net zone.
+/// bailiwick because the nameserver is not authoritative for the .net zone.
///
/// \subsection DataScrubbingEx4 Example 4: Inconsistent Answer Section
/// Qu: www.example.com\n
diff --git a/src/bin/sockcreator/README b/src/bin/sockcreator/README
index e142d19..48b10dd 100644
--- a/src/bin/sockcreator/README
+++ b/src/bin/sockcreator/README
@@ -35,7 +35,7 @@ must be a socket, not pipe.
The answer to this is either 'S' directly followed by the socket (using
sendmsg) if it is successful. If it fails, 'E' is returned instead, followed
by either 'S' or 'B' (either socket() or bind() call failed). Then there is
- one int (architecture-dependent length and endianess), which is the errno
+ one int (architecture-dependent length and endianness), which is the errno
value after the failure.
The creator may also send these messages at any time (but not in the middle
diff --git a/src/bin/sockcreator/sockcreator.h b/src/bin/sockcreator/sockcreator.h
index 8e32c48..a05cf6a 100644
--- a/src/bin/sockcreator/sockcreator.h
+++ b/src/bin/sockcreator/sockcreator.h
@@ -85,7 +85,7 @@ typedef int (*close_t)(int);
/// \param type The type of socket to create (SOCK_STREAM, SOCK_DGRAM, etc).
/// \param bind_addr The address to bind.
/// \param addr_len The actual length of bind_addr.
-/// \param close_fun The furction used to close a socket if there's an error
+/// \param close_fun The function used to close a socket if there's an error
/// after the creation.
///
/// \return The file descriptor of the newly created socket, if everything
diff --git a/src/bin/sockcreator/tests/sockcreator_tests.cc b/src/bin/sockcreator/tests/sockcreator_tests.cc
index b834e1c..67fb53e 100644
--- a/src/bin/sockcreator/tests/sockcreator_tests.cc
+++ b/src/bin/sockcreator/tests/sockcreator_tests.cc
@@ -99,7 +99,7 @@ udpCheck(const int socknum) {
}
// The check function (tcpCheck/udpCheck) is passed as a parameter to the test
-// code, so provide a conveniet typedef.
+// code, so provide a convenient typedef.
typedef void (*socket_check_t)(const int);
// Address-family-specific scoket checks.
diff --git a/src/bin/stats/stats_httpd.py.in b/src/bin/stats/stats_httpd.py.in
index fd9ac93..82b9dcc 100755
--- a/src/bin/stats/stats_httpd.py.in
+++ b/src/bin/stats/stats_httpd.py.in
@@ -35,6 +35,7 @@ import re
import isc.cc
import isc.config
import isc.util.process
+from isc.util.address_formatter import AddressFormatter
import isc.log
from isc.log_messages.stats_httpd_messages import *
@@ -325,8 +326,8 @@ class StatsHttpd:
server_address, HttpHandler,
self.xml_handler, self.xsd_handler, self.xsl_handler,
self.write_log)
- logger.info(STATSHTTPD_STARTED, server_address[0],
- server_address[1])
+ logger.info(STATSHTTPD_STARTED,
+ AddressFormatter(server_address, address_family))
return httpd
except (socket.gaierror, socket.error,
OverflowError, TypeError) as err:
@@ -341,8 +342,8 @@ class StatsHttpd:
"""Closes sockets for HTTP"""
while len(self.httpd)>0:
ht = self.httpd.pop()
- logger.info(STATSHTTPD_CLOSING, ht.server_address[0],
- ht.server_address[1])
+ logger.info(STATSHTTPD_CLOSING,
+ AddressFormatter(ht.server_address))
ht.server_close()
def start(self):
diff --git a/src/bin/stats/stats_httpd_messages.mes b/src/bin/stats/stats_httpd_messages.mes
index 93491b6..930a745 100644
--- a/src/bin/stats/stats_httpd_messages.mes
+++ b/src/bin/stats/stats_httpd_messages.mes
@@ -24,7 +24,7 @@ The stats-httpd module was unable to connect to the BIND 10 command
and control bus. A likely problem is that the message bus daemon
(b10-msgq) is not running. The stats-httpd module will now shut down.
-% STATSHTTPD_CLOSING closing %1#%2
+% STATSHTTPD_CLOSING closing %1
The stats-httpd daemon will stop listening for requests on the given
address and port number.
@@ -80,7 +80,7 @@ and an error is sent back.
% STATSHTTPD_SHUTDOWN shutting down
The stats-httpd daemon is shutting down.
-% STATSHTTPD_STARTED listening on %1#%2
+% STATSHTTPD_STARTED listening on %1
The stats-httpd daemon will now start listening for requests on the
given address and port number.
diff --git a/src/bin/stats/tests/b10-stats-httpd_test.py b/src/bin/stats/tests/b10-stats-httpd_test.py
index 466e448..9a463ab 100644
--- a/src/bin/stats/tests/b10-stats-httpd_test.py
+++ b/src/bin/stats/tests/b10-stats-httpd_test.py
@@ -173,7 +173,7 @@ class TestItemNameList(unittest.TestCase):
stats_httpd.item_name_list({'a':[1,2,3]}, 'a'))
self.assertEqual(['a', 'a[0]', 'a[1]', 'a[2]'],
stats_httpd.item_name_list({'a':[1,2,3]}, ''))
- # for a list under adict under a dict
+ # for a list under a dict under a dict
self.assertEqual(['a', 'a/b', 'a/b[0]', 'a/b[1]', 'a/b[2]'],
stats_httpd.item_name_list({'a':{'b':[1,2,3]}}, 'a'))
self.assertEqual(['a', 'a/b', 'a/b[0]', 'a/b[1]', 'a/b[2]'],
diff --git a/src/bin/stats/tests/b10-stats_test.py b/src/bin/stats/tests/b10-stats_test.py
index 7732902..f807168 100644
--- a/src/bin/stats/tests/b10-stats_test.py
+++ b/src/bin/stats/tests/b10-stats_test.py
@@ -398,8 +398,8 @@ class TestStats(unittest.TestCase):
(0, "Stats is up. (PID " + str(os.getpid()) + ")"))
# 'showschema' command. update_modules() will be called, which
- # (implicitly) cofirms the correct method is called; further details
- # are tested seprately.
+ # (implicitly) confirms the correct method is called; further details
+ # are tested separately.
call_log = []
(rcode, value) = self.__send_command(__stats, 'showschema')
self.assertEqual([('update_module', ())], call_log)
diff --git a/src/bin/stats/tests/test_utils.py b/src/bin/stats/tests/test_utils.py
index bfabc13..45e9a17 100644
--- a/src/bin/stats/tests/test_utils.py
+++ b/src/bin/stats/tests/test_utils.py
@@ -48,7 +48,7 @@ class SignalHandler():
signal.signal(signal.SIGALRM, self.orig_handler)
def sig_handler(self, signal, frame):
- """envokes unittest.TestCase.fail as a signal handler"""
+ """invokes unittest.TestCase.fail as a signal handler"""
self.fail_handler("A deadlock might be detected")
def send_command(command_name, module_name, params=None):
diff --git a/src/bin/usermgr/Makefile.am b/src/bin/usermgr/Makefile.am
index ce7977f..d356d20 100644
--- a/src/bin/usermgr/Makefile.am
+++ b/src/bin/usermgr/Makefile.am
@@ -1,8 +1,11 @@
+SUBDIRS = tests
+
sbin_SCRIPTS = b10-cmdctl-usermgr
+noinst_SCRIPTS = run_b10-cmdctl-usermgr.sh
b10_cmdctl_usermgrdir = $(pkgdatadir)
-CLEANFILES= b10-cmdctl-usermgr
+CLEANFILES= b10-cmdctl-usermgr b10-cmdctl-usermgr.pyc
man_MANS = b10-cmdctl-usermgr.8
DISTCLEANFILES = $(man_MANS)
@@ -25,3 +28,7 @@ endif
b10-cmdctl-usermgr: b10-cmdctl-usermgr.py
$(SED) "s|@@PYTHONPATH@@|@pyexecdir@|" b10-cmdctl-usermgr.py >$@
chmod a+x $@
+
+CLEANDIRS = __pycache__
+clean-local:
+ rm -rf $(CLEANDIRS)
diff --git a/src/bin/usermgr/b10-cmdctl-usermgr.py.in b/src/bin/usermgr/b10-cmdctl-usermgr.py.in
old mode 100644
new mode 100755
index d62ad72..37be304
--- a/src/bin/usermgr/b10-cmdctl-usermgr.py.in
+++ b/src/bin/usermgr/b10-cmdctl-usermgr.py.in
@@ -11,115 +11,234 @@
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
# INTERNET SYSTEMS CONSORTIUM 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
+# FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN COMMAND OF CONTRACT,
+# NEGLIGENCE OR OTHER TORTIOUS COMMAND, ARISING OUT OF OR IN CONNECTION
# WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
'''
-This file implements user management program. The user name and
-its password is appended to csv file.
+This tool implements user management for b10-cmdctl. It is used to
+add and remove users from the accounts file.
'''
+import sys; sys.path.append ('@@PYTHONPATH@@')
+from bind10_config import SYSCONFPATH
+from collections import OrderedDict
import random
from hashlib import sha1
import csv
import getpass
-import getopt
-import sys; sys.path.append ('@@PYTHONPATH@@')
+from optparse import OptionParser, OptionValueError
+import os
import isc.util.process
isc.util.process.rename()
-VERSION_NUMBER = 'bind10'
-DEFAULT_FILE = 'cmdctl-accounts.csv'
-
-def gen_password_hash(password):
- salt = "".join(chr(random.randint(33, 127)) for x in range(64))
- saltedpwd = sha1((password + salt).encode()).hexdigest()
- return salt, saltedpwd
-
-def username_exist(name, filename):
- # The file may doesn't exist.
- exist = False
- csvfile = None
- try:
- csvfile = open(filename)
- reader = csv.reader(csvfile)
- for row in reader:
- if name == row[0]:
- exist = True
- break
- except Exception:
- pass
-
- if csvfile:
- csvfile.close()
- return exist
-
-def save_userinfo(username, pw, salt, filename):
- csvfile = open(filename, 'a')
- writer = csv.writer(csvfile)
- writer.writerow([username, pw, salt])
- csvfile.close()
- print("\n create new account successfully! \n")
-
-def usage():
- print('''Usage: usermgr [options]
- -h, --help \t Show this help message and exit
- -f, --file \t Specify the file to append user name and password
- -v, --version\t Get version number
- ''')
+VERSION_STRING = "b10-cmdctl-usermgr @PACKAGE_VERSION@"
+DEFAULT_FILE = SYSCONFPATH + "/cmdctl-accounts.csv"
-def main():
- filename = DEFAULT_FILE
- try:
- opts, args = getopt.getopt(sys.argv[1:], 'f:hv',
- ['file=', 'help', 'version'])
- except getopt.GetoptError as err:
- print(err)
- usage()
- sys.exit(2)
- for op, param in opts:
- if op in ('-h', '--help'):
- usage()
- sys.exit()
- elif op in ('-v', '--version'):
- print(VERSION_NUMBER)
- sys.exit()
- elif op in ('-f', "--file"):
- filename = param
- else:
- assert False, 'unknown option'
- usage()
-
- try:
- while True :
- name = input("Desired Login Name:")
- if name == '':
- print("error, user name can't be empty")
+# Actions that can be performed (used for argument parsing,
+# code paths, and output)
+COMMAND_ADD = "add"
+COMMAND_DELETE = "delete"
+
+# Non-zero return codes, used in tests
+BAD_ARGUMENTS = 1
+FILE_ERROR = 2
+USER_EXISTS = 3
+USER_DOES_NOT_EXIST = 4
+
+class UserManager:
+ def __init__(self, options, args):
+ self.options = options
+ self.args = args
+
+ def __print(self, msg):
+ if not self.options.quiet:
+ print(msg)
+
+ def __gen_password_hash(self, password):
+ salt = "".join(chr(random.randint(ord('!'), ord('~')))\
+ for x in range(64))
+ saltedpwd = sha1((password + salt).encode()).hexdigest()
+ return salt, saltedpwd
+
+ def __read_user_info(self):
+ """
+ Read the existing user info
+ Raises an IOError if the file can't be read
+ """
+ # Currently, this is done quite naively (there is no
+ # check that the file is modified between read and write)
+ # But taking multiple simultaneous users of this tool on the
+ # same file seems unnecessary at this point.
+ self.user_info = OrderedDict()
+ if os.path.exists(self.options.output_file):
+ # Just let any file read error bubble up; it will
+ # be caught in the run() method
+ with open(self.options.output_file, newline='') as csvfile:
+ reader = csv.reader(csvfile)
+ for row in reader:
+ self.user_info[row[0]] = row
+
+ def __save_user_info(self):
+ """
+ Write out the (modified) user info
+ Raises an IOError if the file can't be written
+ """
+ # Just let any file write error bubble up; it will
+ # be caught in the run() method
+ with open(self.options.output_file, 'w',
+ newline='') as csvfile:
+ writer = csv.writer(csvfile)
+ for row in self.user_info.values():
+ writer.writerow(row)
+
+ def __add_user(self, name, password):
+ """
+ Add the given username/password combination to the stored user_info.
+ First checks if the username exists, and returns False if so.
+ If not, it is added, and this method returns True.
+ """
+ if name in self.user_info:
+ return False
+ salt, pw = self.__gen_password_hash(password)
+ self.user_info[name] = [name, pw, salt]
+ return True
+
+ def __delete_user(self, name):
+ """
+ Removes the row with the given name from the stored user_info
+ First checks if the username exists, and returns False if not.
+ Otherwise, it is removed, and this mehtod returns True
+ """
+ if name not in self.user_info:
+ return False
+ del self.user_info[name]
+ return True
+
+ # overridable input() call, used in testing
+ def _input(self, prompt):
+ return input(prompt)
+
+ # in essence this is private, but made 'protected' for ease
+ # of testing
+ def _prompt_for_username(self, command):
+ # Note, direct prints here are intentional
+ while True:
+ name = self._input("Username to " + command + ": ")
+ if name == "":
+ print("Error username can't be empty")
continue
- if username_exist(name, filename):
- print("user name already exists!")
+ if command == COMMAND_ADD and name in self.user_info:
+ print("user already exists")
+ continue
+ elif command == COMMAND_DELETE and name not in self.user_info:
+ print("user does not exist")
continue
- while True:
- pwd1 = getpass.getpass("Choose a password:")
- pwd2 = getpass.getpass("Re-enter password:")
- if pwd1 != pwd2:
- print("password is not same, please input again")
+ return name
+
+ # in essence this is private, but made 'protected' for ease
+ # of testing
+ def _prompt_for_password(self):
+ # Note, direct prints here are intentional
+ while True:
+ pwd1 = getpass.getpass("Choose a password: ")
+ if pwd1 == "":
+ print("Error: password cannot be empty")
+ continue
+ pwd2 = getpass.getpass("Re-enter password: ")
+ if pwd1 != pwd2:
+ print("passwords do not match, try again")
+ continue
+ return pwd1
+
+ def __verify_options_and_args(self):
+ """
+ Basic sanity checks on command line arguments.
+ Returns False if there is a problem, True if everything seems OK.
+ """
+ if len(self.args) < 1:
+ self.__print("Error: no command specified")
+ return False
+ if len(self.args) > 3:
+ self.__print("Error: extraneous arguments")
+ return False
+ if self.args[0] not in [ COMMAND_ADD, COMMAND_DELETE ]:
+ self.__print("Error: command must be either add or delete")
+ return False
+ if self.args[0] == COMMAND_DELETE and len(self.args) > 2:
+ self.__print("Error: delete only needs username, not a password")
+ return False
+ return True
+
+ def run(self):
+ if not self.__verify_options_and_args():
+ return BAD_ARGUMENTS
+
+ try:
+ self.__print("Using accounts file: " + self.options.output_file)
+ self.__read_user_info()
+
+ command = self.args[0]
+
+ if len(self.args) > 1:
+ username = self.args[1]
+ else:
+ username = self._prompt_for_username(command)
+
+ if command == COMMAND_ADD:
+ if len(self.args) > 2:
+ password = self.args[2]
else:
- break;
-
- salt, pw = gen_password_hash(pwd1)
- save_userinfo(name, pw, salt, filename)
- inputdata = input('continue to create new account by input \'y\' or \'Y\':')
- if inputdata not in ['y', 'Y']:
- break
-
- except KeyboardInterrupt:
- pass
+ password = self._prompt_for_password()
+ if not self.__add_user(username, password):
+ print("Error: username exists")
+ return USER_EXISTS
+ elif command == COMMAND_DELETE:
+ if not self.__delete_user(username):
+ print("Error: username does not exist")
+ return USER_DOES_NOT_EXIST
+
+ self.__save_user_info()
+ return 0
+ except IOError as ioe:
+ self.__print("Error accessing " + ioe.filename +\
+ ": " + str(ioe.strerror))
+ return FILE_ERROR
+ except csv.Error as csve:
+ self.__print("Error parsing csv file: " + str(csve))
+ return FILE_ERROR
+
+def set_options(parser):
+ parser.add_option("-f", "--file",
+ dest="output_file", default=DEFAULT_FILE,
+ help="Accounts file to modify"
+ )
+ parser.add_option("-q", "--quiet",
+ dest="quiet", action="store_true", default=False,
+ help="Quiet mode, don't print any output"
+ )
+
+def main():
+ usage = "usage: %prog [options] <command> [username] [password]\n\n"\
+ "Arguments:\n"\
+ " command\t\teither 'add' or 'delete'\n"\
+ " username\t\tthe username to add or delete\n"\
+ " password\t\tthe password to set for the added user\n"\
+ "\n"\
+ "If username or password are not specified, %prog will\n"\
+ "prompt for them. It is recommended practice to let the\n"\
+ "tool prompt for the password, as command-line\n"\
+ "arguments can be visible through history or process\n"\
+ "viewers."
+ parser = OptionParser(usage=usage, version=VERSION_STRING)
+ set_options(parser)
+ (options, args) = parser.parse_args()
+ usermgr = UserManager(options, args)
+ return usermgr.run()
if __name__ == '__main__':
- main()
+ sys.exit(main())
diff --git a/src/bin/usermgr/b10-cmdctl-usermgr.xml b/src/bin/usermgr/b10-cmdctl-usermgr.xml
index 529a8db..26940d7 100644
--- a/src/bin/usermgr/b10-cmdctl-usermgr.xml
+++ b/src/bin/usermgr/b10-cmdctl-usermgr.xml
@@ -12,8 +12,8 @@
- 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
+ - LOSS OF USE, DATA OR PROFITS, WHETHER IN AN COMMAND OF CONTRACT, NEGLIGENCE
+ - OR OTHER TORTIOUS COMMAND, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- PERFORMANCE OF THIS SOFTWARE.
-->
@@ -47,10 +47,12 @@
<arg><option>-f <replaceable>filename</replaceable></option></arg>
<arg><option>-h</option></arg>
- <arg><option>-v</option></arg>
- <arg><option>--file <replaceable>filename</replaceable></option></arg>
+ <arg><option>--file=<replaceable>filename</replaceable></option></arg>
<arg><option>--help</option></arg>
<arg><option>--version</option></arg>
+ <arg choice="plain"><replaceable>command</replaceable></arg>
+ <arg><option>username</option></arg>
+ <arg><option>password</option></arg>
</cmdsynopsis>
</refsynopsisdiv>
@@ -58,24 +60,22 @@
<refsect1>
<title>DESCRIPTION</title>
<para>The <command>b10-cmdctl-usermgr</command> tool may be used
- to add accounts with passwords for the
+ to add and remove accounts with passwords for the
<citerefentry><refentrytitle>b10-cmdctl</refentrytitle><manvolnum>8</manvolnum></citerefentry>
daemon.
</para>
<para>
By default, the accounts are saved in the
- <filename>cmdctl-accounts.csv</filename> file in the current directory,
- unless the <option>--filename</option> switch is used.
- The entry is appended to the file.
-<!-- TODO: default should have full path? -->
+ <filename>cmdctl-accounts.csv</filename> file in the system config
+ directory, unless the <option>--filename</option> switch is used.
+ The entry is appended to or removed from the file.
</para>
<para>
- The tool can't remove or replace existing entries.
+ The tool can't replace existing entries, but this can easily be
+ accomplished by removing the entry and adding a new one.
</para>
-<!-- TODO: the tool can't remove or replace existing entries -->
-
</refsect1>
<refsect1>
@@ -83,6 +83,18 @@
<para>The arguments are as follows:</para>
+ <para>
+ command is either 'add' or 'delete', respectively to add or delete users.
+ </para>
+
+ <para>
+ If a username and password are given (or just a username in case of
+ deletion), these are used. Otherwise, the tool shall prompt for a
+ username and/or password. It is recommended practice to let the
+ tool prompt for the password, as command-line arguments can be
+ visible through history or process viewers.
+ </para>
+
<variablelist>
<varlistentry>
@@ -97,14 +109,13 @@
<term><option>-f <replaceable>filename</replaceable></option></term>
<term><option>--file <replaceable>filename</replaceable></option></term>
<listitem><para>
- Define the filename to append the account to. The default
- is <filename>cmdctl-accounts.csv</filename> in the current directory.
-<!-- TODO: default should have full path? -->
+ Specify the accounts file to update. The default is
+ <filename>cmdctl-accounts.csv</filename> in the system config
+ directory.
</para></listitem>
</varlistentry>
<varlistentry>
- <term><option>-v</option></term>
<term><option>--version</option></term>
<listitem><para>
Report the version and exit.
diff --git a/src/bin/usermgr/run_b10-cmdctl-usermgr.sh.in b/src/bin/usermgr/run_b10-cmdctl-usermgr.sh.in
old mode 100644
new mode 100755
index 5989205..8e8e743
--- a/src/bin/usermgr/run_b10-cmdctl-usermgr.sh.in
+++ b/src/bin/usermgr/run_b10-cmdctl-usermgr.sh.in
@@ -18,6 +18,9 @@
PYTHON_EXEC=${PYTHON_EXEC:- at PYTHON@}
export PYTHON_EXEC
+PYTHONPATH=@abs_top_builddir@/src/lib/python
+export PYTHONPATH
+
MYPATH_PATH=@abs_top_builddir@/src/bin/usermgr
BIND10_MSGQ_SOCKET_FILE=@abs_top_builddir@/msgq_socket
diff --git a/src/bin/usermgr/tests/Makefile.am b/src/bin/usermgr/tests/Makefile.am
new file mode 100644
index 0000000..230f164
--- /dev/null
+++ b/src/bin/usermgr/tests/Makefile.am
@@ -0,0 +1,22 @@
+PYCOVERAGE_RUN=@PYCOVERAGE_RUN@
+PYTESTS = b10-cmdctl-usermgr_test.py
+EXTRA_DIST = $(PYTESTS)
+
+CLEANFILES = *.csv
+
+# test using command-line arguments, so use check-local target instead of TESTS
+check-local:
+if ENABLE_PYTHON_COVERAGE
+ touch $(abs_top_srcdir)/.coverage
+ rm -f .coverage
+ ${LN_S} $(abs_top_srcdir)/.coverage .coverage
+endif
+ for pytest in $(PYTESTS) ; do \
+ echo Running test: $$pytest ; \
+ $(LIBRARY_PATH_PLACEHOLDER) \
+ PYTHONPATH=$(COMMON_PYTHON_PATH):$(abs_top_builddir)/src/bin/cmdctl \
+ CMDCTL_BUILD_PATH=$(abs_top_builddir)/src/bin/cmdctl \
+ CMDCTL_SRC_PATH=$(abs_top_srcdir)/src/bin/cmdctl \
+ B10_LOCKFILE_DIR_FROM_BUILD=$(abs_top_builddir) \
+ $(PYCOVERAGE_RUN) $(abs_srcdir)/$$pytest || exit ; \
+ done
diff --git a/src/bin/usermgr/tests/b10-cmdctl-usermgr_test.py b/src/bin/usermgr/tests/b10-cmdctl-usermgr_test.py
new file mode 100644
index 0000000..3d0d4af
--- /dev/null
+++ b/src/bin/usermgr/tests/b10-cmdctl-usermgr_test.py
@@ -0,0 +1,483 @@
+# Copyright (C) 2013 Internet Systems Consortium.
+#
+# Permission to use, copy, modify, and 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 INTERNET SYSTEMS CONSORTIUM
+# DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+# INTERNET SYSTEMS CONSORTIUM 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 COMMAND OF CONTRACT,
+# NEGLIGENCE OR OTHER TORTIOUS COMMAND, ARISING OUT OF OR IN CONNECTION
+# WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+import csv
+from hashlib import sha1
+import getpass
+import imp
+import os
+import subprocess
+import stat
+import sys
+import unittest
+from bind10_config import SYSCONFPATH
+
+class PrintCatcher:
+ def __init__(self):
+ self.stdout_lines = []
+
+ def __enter__(self):
+ self.__orig_stdout_write = sys.stdout.write
+ def new_write(line):
+ self.stdout_lines.append(line)
+
+ sys.stdout.write = new_write
+ return self
+
+ def __exit__(self, type, value, traceback):
+ sys.stdout.write = self.__orig_stdout_write
+
+class OverrideGetpass:
+ def __init__(self, new_getpass):
+ self.__new_getpass = new_getpass
+ self.__orig_getpass = getpass.getpass
+
+ def __enter__(self):
+ getpass.getpass = self.__new_getpass
+ return self
+
+ def __exit__(self, type, value, traceback):
+ getpass.getpass = self.__orig_getpass
+
+# input() is a built-in function and not easily overridable
+# so this one uses usermgr for that
+class OverrideInput:
+ def __init__(self, usermgr, new_getpass):
+ self.__usermgr = usermgr
+ self.__new_input = new_getpass
+ self.__orig_input = usermgr._input
+
+ def __enter__(self):
+ self.__usermgr._input = self.__new_input
+ return self
+
+ def __exit__(self, type, value, traceback):
+ self.__usermgr._input = self.__orig_input
+
+def run(command):
+ """
+ Small helper function that returns a tuple of (rcode, stdout, stderr)
+ after running the given command (an array of command and arguments, as
+ passed on to subprocess).
+ Parameters:
+ command: an array of command and argument strings, which will be
+ passed to subprocess.Popen()
+ """
+ subp = subprocess.Popen(command, stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE)
+ (stdout, stderr) = subp.communicate()
+ return (subp.returncode, stdout, stderr)
+
+class TestUserMgr(unittest.TestCase):
+ TOOL = '../b10-cmdctl-usermgr'
+ OUTPUT_FILE = 'test_users.csv'
+
+ def setUp(self):
+ self.delete_output_file()
+ # For access to the actual module, we load it directly
+ self.usermgr_module = imp.load_source('usermgr',
+ '../b10-cmdctl-usermgr.py')
+ # And instantiate 1 instance (with fake options/args)
+ self.usermgr = self.usermgr_module.UserManager(object(), object())
+
+ def tearDown(self):
+ self.delete_output_file()
+
+ def delete_output_file(self):
+ if os.path.exists(self.OUTPUT_FILE):
+ os.remove(self.OUTPUT_FILE)
+
+ def check_output_file(self, expected_content):
+ self.assertTrue(os.path.exists(self.OUTPUT_FILE))
+
+ csv_entries = []
+ with open(self.OUTPUT_FILE, newline='') as csvfile:
+ reader = csv.reader(csvfile)
+ csv_entries = [row for row in reader]
+
+ self.assertEqual(len(expected_content), len(csv_entries))
+ csv_entries.reverse()
+ for expected_entry in expected_content:
+ expected_name = expected_entry[0]
+ expected_pass = expected_entry[1]
+
+ csv_entry = csv_entries.pop()
+ entry_name = csv_entry[0]
+ entry_salt = csv_entry[2]
+ entry_hash = csv_entry[1]
+
+ self.assertEqual(expected_name, entry_name)
+ expected_hash =\
+ sha1((expected_pass + entry_salt).encode()).hexdigest()
+ self.assertEqual(expected_hash, entry_hash)
+
+ def run_check(self, expected_returncode, expected_stdout, expected_stderr,
+ command):
+ """
+ Runs the given command, and checks return code, and outputs (if provided).
+ Arguments:
+ expected_returncode, return code of the command
+ expected_stdout, (multiline) string that is checked against stdout.
+ May be None, in which case the check is skipped.
+ expected_stderr, (multiline) string that is checked against stderr.
+ May be None, in which case the check is skipped.
+ """
+ (returncode, stdout, stderr) = run(command)
+ if expected_stderr is not None:
+ self.assertEqual(expected_stderr, stderr.decode())
+ if expected_stdout is not None:
+ self.assertEqual(expected_stdout, stdout.decode())
+ self.assertEqual(expected_returncode, returncode, " ".join(command))
+
+ def test_help(self):
+ self.run_check(0,
+'''Usage: b10-cmdctl-usermgr [options] <command> [username] [password]
+
+Arguments:
+ command either 'add' or 'delete'
+ username the username to add or delete
+ password the password to set for the added user
+
+If username or password are not specified, b10-cmdctl-usermgr will
+prompt for them. It is recommended practice to let the
+tool prompt for the password, as command-line
+arguments can be visible through history or process
+viewers.
+
+Options:
+ --version show program's version number and exit
+ -h, --help show this help message and exit
+ -f OUTPUT_FILE, --file=OUTPUT_FILE
+ Accounts file to modify
+ -q, --quiet Quiet mode, don't print any output
+''',
+ '',
+ [self.TOOL, '-h'])
+
+ def test_add_delete_users_ok(self):
+ """
+ Test that a file is created, and users are added.
+ Also tests quiet mode for adding a user to an existing file.
+ """
+ # content is a list of (user, pass) tuples
+ expected_content = []
+
+ # Creating a file
+ self.run_check(0,
+ 'Using accounts file: test_users.csv\n',
+ '',
+ [ self.TOOL,
+ '-f', self.OUTPUT_FILE,
+ 'add', 'user1', 'pass1'
+ ])
+ expected_content.append(('user1', 'pass1'))
+ self.check_output_file(expected_content)
+
+ # Add to existing file
+ self.run_check(0,
+ 'Using accounts file: test_users.csv\n',
+ '',
+ [ self.TOOL,
+ '-f', self.OUTPUT_FILE,
+ 'add', 'user2', 'pass2'
+ ])
+ expected_content.append(('user2', 'pass2'))
+ self.check_output_file(expected_content)
+
+ # Quiet mode
+ self.run_check(0,
+ '',
+ '',
+ [ self.TOOL, '-q',
+ '-f', self.OUTPUT_FILE,
+ 'add', 'user3', 'pass3'
+ ])
+ expected_content.append(('user3', 'pass3'))
+ self.check_output_file(expected_content)
+
+ # Delete a user (let's pick the middle one)
+ self.run_check(0,
+ '',
+ '',
+ [ self.TOOL, '-q',
+ '-f', self.OUTPUT_FILE,
+ 'delete', 'user2'
+ ])
+ del expected_content[1]
+ self.check_output_file(expected_content)
+
+ def test_add_delete_users_bad(self):
+ """
+ More add/delete tests, this time for some error scenarios
+ """
+ # content is a list of (user, pass) tuples
+ expected_content = []
+ # First add one
+ self.run_check(0, None, None,
+ [ self.TOOL,
+ '-f', self.OUTPUT_FILE,
+ 'add', 'user', 'pass'
+ ])
+ expected_content.append(('user', 'pass'))
+ self.check_output_file(expected_content)
+
+ # Adding it again should error
+ self.run_check(3,
+ 'Using accounts file: test_users.csv\n'
+ 'Error: username exists\n',
+ '',
+ [ self.TOOL,
+ '-f', self.OUTPUT_FILE,
+ 'add', 'user', 'pass'
+ ])
+ self.check_output_file(expected_content)
+
+ # Deleting a non-existent one should fail too
+ self.run_check(4,
+ 'Using accounts file: test_users.csv\n'
+ 'Error: username does not exist\n',
+ '',
+ [ self.TOOL,
+ '-f', self.OUTPUT_FILE,
+ 'delete', 'nosuchuser'
+ ])
+ self.check_output_file(expected_content)
+
+ def test_bad_arguments(self):
+ """
+ Assorted tests with bad command-line arguments
+ """
+ self.run_check(1,
+ 'Error: no command specified\n',
+ '',
+ [ self.TOOL ])
+ self.run_check(1,
+ 'Error: command must be either add or delete\n',
+ '',
+ [ self.TOOL, 'foo' ])
+ self.run_check(1,
+ 'Error: extraneous arguments\n',
+ '',
+ [ self.TOOL, 'add', 'user', 'pass', 'toomuch' ])
+ self.run_check(1,
+ 'Error: delete only needs username, not a password\n',
+ '',
+ [ self.TOOL, 'delete', 'user', 'pass' ])
+
+ def test_default_file(self):
+ """
+ Check the default file is the correct one.
+ """
+ # Hardcoded path .. should be ok since this is run from make check
+ self.assertEqual(SYSCONFPATH + '/cmdctl-accounts.csv',
+ self.usermgr_module.DEFAULT_FILE)
+
+ def test_prompt_for_password_different(self):
+ """
+ Check that the method that prompts for a password verifies that
+ the same value is entered twice
+ """
+ # returns a different string (the representation of the number
+ # of times it has been called), until it has been called
+ # over 10 times, in which case it will always return "11"
+ getpass_different_called = 0
+ def getpass_different(question):
+ nonlocal getpass_different_called
+ getpass_different_called += 1
+ if getpass_different_called > 10:
+ return "11"
+ else:
+ return str(getpass_different_called)
+
+ with PrintCatcher() as pc:
+ with OverrideGetpass(getpass_different):
+ pwd = self.usermgr._prompt_for_password()
+ self.assertEqual(12, getpass_different_called)
+ self.assertEqual("11", pwd)
+ # stdout should be 5 times the no match string;
+ expected_output = "passwords do not match, try again\n"*5
+ self.assertEqual(expected_output, ''.join(pc.stdout_lines))
+
+ def test_prompt_for_password_empty(self):
+ """
+ Check that the method that prompts for a password verifies that
+ the value entered is not empty
+ """
+ # returns an empty string until it has been called over 10
+ # times
+ getpass_empty_called = 0
+ def getpass_empty(prompt):
+ nonlocal getpass_empty_called
+ getpass_empty_called += 1
+ if getpass_empty_called > 10:
+ return "nonempty"
+ else:
+ return ""
+
+ with PrintCatcher() as pc:
+ with OverrideGetpass(getpass_empty):
+ pwd = self.usermgr._prompt_for_password()
+ self.assertEqual("nonempty", pwd)
+ self.assertEqual(12, getpass_empty_called)
+ # stdout should be 10 times the 'cannot be empty' string
+ expected_output = "Error: password cannot be empty\n"*10
+ self.assertEqual(expected_output, ''.join(pc.stdout_lines))
+
+ def test_prompt_for_user(self):
+ """
+ Test that the method that prompts for a username verifies that
+ is not empty, and that it exists (or does not, depending on the
+ action that is specified)
+ """
+ new_input_called = 0
+ input_results = [ '', '', 'existinguser', 'nonexistinguser',
+ '', '', 'nonexistinguser', 'existinguser' ]
+ def new_input(prompt):
+ nonlocal new_input_called
+
+ if new_input_called < len(input_results):
+ result = input_results[new_input_called]
+ else:
+ result = 'empty'
+ new_input_called += 1
+ return result
+
+ # add fake user (value doesn't matter, method only checks for key)
+ self.usermgr.user_info = { 'existinguser': None }
+
+ expected_output = ''
+
+ with PrintCatcher() as pc:
+ with OverrideInput(self.usermgr, new_input):
+ # should skip the first three since empty or existing
+ # are not allowed, then return 'nonexistinguser'
+ username = self.usermgr._prompt_for_username(
+ self.usermgr_module.COMMAND_ADD)
+ self.assertEqual('nonexistinguser', username)
+ expected_output += "Error username can't be empty\n"*2
+ expected_output += "user already exists\n"
+ self.assertEqual(expected_output, ''.join(pc.stdout_lines))
+
+ # For delete, should again not accept empty (in a while true
+ # loop), and this time should not accept nonexisting users
+ username = self.usermgr._prompt_for_username(
+ self.usermgr_module.COMMAND_DELETE)
+ self.assertEqual('existinguser', username)
+ expected_output += "Error username can't be empty\n"*2
+ expected_output += "user does not exist\n"
+ self.assertEqual(expected_output, ''.join(pc.stdout_lines))
+
+ def test_bad_file(self):
+ """
+ Check for graceful handling of bad file argument
+ """
+ self.run_check(2,
+ 'Using accounts file: /\n'
+ 'Error accessing /: Is a directory\n',
+ '',
+ [ self.TOOL, '-f', '/', 'add', 'user', 'pass' ])
+
+ # Make sure we can initially write to the test file
+ self.run_check(0, None, None,
+ [ self.TOOL,
+ '-f', self.OUTPUT_FILE,
+ 'add', 'user1', 'pass1'
+ ])
+
+ # Make it non-writable (don't worry about cleanup, the
+ # file should be deleted after each test anyway
+ os.chmod(self.OUTPUT_FILE, stat.S_IRUSR)
+ self.run_check(2,
+ 'Using accounts file: test_users.csv\n'
+ 'Error accessing test_users.csv: Permission denied\n',
+ '',
+ [ self.TOOL,
+ '-f', self.OUTPUT_FILE,
+ 'add', 'user2', 'pass1'
+ ])
+
+ self.run_check(2,
+ 'Using accounts file: test_users.csv\n'
+ 'Error accessing test_users.csv: Permission denied\n',
+ '',
+ [ self.TOOL,
+ '-f', self.OUTPUT_FILE,
+ 'delete', 'user1'
+ ])
+
+ # Making it write-only should have the same effect
+ os.chmod(self.OUTPUT_FILE, stat.S_IWUSR)
+ self.run_check(2,
+ 'Using accounts file: test_users.csv\n'
+ 'Error accessing test_users.csv: Permission denied\n',
+ '',
+ [ self.TOOL,
+ '-f', self.OUTPUT_FILE,
+ 'add', 'user2', 'pass1'
+ ])
+
+ self.run_check(2,
+ 'Using accounts file: test_users.csv\n'
+ 'Error accessing test_users.csv: Permission denied\n',
+ '',
+ [ self.TOOL,
+ '-f', self.OUTPUT_FILE,
+ 'delete', 'user1'
+ ])
+
+ def test_missing_fields(self):
+ """
+ Test that an invalid csv file is handled gracefully
+ """
+ # Valid but incomplete csv; should be handled
+ # correctly
+ with open(self.OUTPUT_FILE, 'w', newline='') as f:
+ f.write('onlyuserfield\n')
+ f.write('userfield,saltfield\n')
+ f.write(',emptyuserfield,passwordfield\n')
+
+ self.run_check(0, None, None,
+ [ self.TOOL,
+ '-f', self.OUTPUT_FILE,
+ 'add', 'user1', 'pass1'
+ ])
+ self.run_check(0, None, None,
+ [ self.TOOL,
+ '-f', self.OUTPUT_FILE,
+ 'delete', 'onlyuserfield'
+ ])
+ self.run_check(0, None, None,
+ [ self.TOOL,
+ '-f', self.OUTPUT_FILE,
+ 'delete', ''
+ ])
+
+ def test_bad_data(self):
+ # I can only think of one invalid format, an unclosed string
+ with open(self.OUTPUT_FILE, 'w', newline='') as f:
+ f.write('a,"\n')
+ self.run_check(2,
+ 'Using accounts file: test_users.csv\n'
+ 'Error parsing csv file: newline inside string\n',
+ '',
+ [ self.TOOL,
+ '-f', self.OUTPUT_FILE,
+ 'add', 'user1', 'pass1'
+ ])
+
+
+if __name__== '__main__':
+ unittest.main()
+
diff --git a/src/bin/xfrin/b10-xfrin.xml b/src/bin/xfrin/b10-xfrin.xml
index 907c719..6cbe792 100644
--- a/src/bin/xfrin/b10-xfrin.xml
+++ b/src/bin/xfrin/b10-xfrin.xml
@@ -234,7 +234,9 @@ operation
<term><replaceable>zonename</replaceable></term>
<listitem><simpara>
An actual zone name or special zone name
- <quote>_SERVER_</quote> representing the entire server
+ <quote>_SERVER_</quote> representing the entire server.
+ Zone classes (IN, CH, HS) are mixed and counted so far. But
+ these will be distinguished in future release.
</simpara>
<variablelist>
@@ -295,16 +297,22 @@ operation
</varlistentry>
<varlistentry>
- <term>latest_ixfr_duration</term>
+ <term>last_ixfr_duration</term>
<listitem><simpara>
- Duration of the latest IXFR. 0.0 means no successful IXFR done.
+ Duration of the last IXFR. 0.0 means no successful IXFR done
+ in greater than or equal to a microsecond. If a started
+ timer is never stopped because of failure, start time of
+ duration will be reset next time.
</simpara></listitem>
</varlistentry>
<varlistentry>
- <term>latest_axfr_duration</term>
+ <term>last_axfr_duration</term>
<listitem><simpara>
- Duration of the latest AXFR. 0.0 means no successful AXFR done.
+ Duration of the last AXFR. 0.0 means no successful AXFR done
+ in greater than or equal to a microsecond. If a started
+ timer is never stopped because of failure, start time of
+ duration will be reset next time.
</simpara></listitem>
</varlistentry>
diff --git a/src/bin/xfrin/tests/xfrin_test.py b/src/bin/xfrin/tests/xfrin_test.py
index 507e986..ecd2bf5 100644
--- a/src/bin/xfrin/tests/xfrin_test.py
+++ b/src/bin/xfrin/tests/xfrin_test.py
@@ -608,7 +608,7 @@ class TestXfrinIXFRAdd(TestXfrinState):
# signed, rejecting it.
self.assertRaises(xfrin.XfrinProtocolError, self.state.handle_rr,
self.conn, end_soa_rrset)
- # No diffs were commited
+ # No diffs were committed
self.assertEqual([], self.conn._datasrc_client.committed_diffs)
def test_handle_out_of_sync(self):
@@ -2129,8 +2129,8 @@ class TestStatisticsXfrinConn(TestXfrinConnection):
('axfrreqv6', 0),
('ixfrreqv4', 0),
('ixfrreqv6', 0),
- ('latest_axfr_duration', 0.0),
- ('latest_ixfr_duration', 0.0),
+ ('last_axfr_duration', 0.0),
+ ('last_ixfr_duration', 0.0),
('soaoutv4', 0),
('soaoutv6', 0),
('xfrfail', 0),
@@ -2140,20 +2140,24 @@ class TestStatisticsXfrinConn(TestXfrinConnection):
super().setUp()
# clear all statistics counters before each test
self.conn._counters.clear_all()
+ # fake datetime
+ self._orig_datetime = isc.statistics.counters.datetime
+ self._orig_start_timer = isc.statistics.counters._start_timer
+ time1 = datetime(2000, 1, 1, 0, 0, 0, 0)
+ time2 = datetime(2000, 1, 1, 0, 0, 0, 1)
+ class fakedatatime:
+ @classmethod
+ def now(cls): return time2
+ isc.statistics.counters.datetime = fakedatatime
+ isc.statistics.counters._start_timer = lambda : time1
+ delta = time2 - time1
+ self._const_sec = round(delta.days * 86400 + delta.seconds +
+ delta.microseconds * 1E-6, 6)
- def _set_start_time(self):
- """sets _start_time to datetime of current time"""
- self._start_time = datetime.now()
-
- def _get_dur_time(self):
- """Returns duration time between _start_time and current. A
- returned value is float type as second. It is rounded at six
- decimal places. After all it deletes _start_time."""
- delta = datetime.now() - self._start_time
- ret = round(delta.days * 86400 + delta.seconds +
- delta.microseconds * 1E-6, 6)
- del self._start_time
- return ret
+ def tearDown(self):
+ super().tearDown()
+ isc.statistics.counters.datetime = self._orig_datetime
+ isc.statistics.counters._start_timer = self._orig_start_timer
def _check_init_statistics(self):
'''checks exception being raised if not incremented statistics
@@ -2174,44 +2178,50 @@ class TestStatisticsXfrinConn(TestXfrinConnection):
TEST_ZONE_NAME_STR,
name)
msg = '%s is expected %s but actually %s' % (name, exp, act)
- if name == 'latest_axfr_duration' \
- or name == 'latest_ixfr_duration':
- # compare at 3 decimal places
- self.assertAlmostEqual(exp, act, places=3, msg=msg)
- else:
- self.assertEqual(exp, act, msg=msg)
+ self.assertEqual(exp, act, msg=msg)
class TestStatisticsXfrinAXFRv4(TestStatisticsXfrinConn):
'''Xfrin AXFR tests for IPv4 to check statistics counters'''
ipver = 'v4'
- def test_soacheck(self):
+ def test_soaout(self):
+ '''tests that an soaoutv4 or soaoutv6 counter is incremented
+ when an soa query succeeds'''
self.conn.response_generator = self._create_soa_response_data
self._check_init_statistics()
self.assertEqual(self.conn._check_soa_serial(), XFRIN_OK)
self._check_updated_statistics({'soaout' + self.ipver: 1})
- def test_do_xfrin(self):
+ def test_axfrreq_xfrsuccess_last_axfr_duration(self):
+ '''tests that axfrreqv4 or axfrreqv6 and xfrsuccess counters
+ and last_axfr_duration timer are incremented when xfr succeeds'''
self.conn.response_generator = self._create_normal_response_data
self._check_init_statistics()
- self._set_start_time()
self.assertEqual(self.conn.do_xfrin(False), XFRIN_OK)
self._check_updated_statistics({'axfrreq' + self.ipver: 1,
'xfrsuccess': 1,
- 'latest_axfr_duration':
- self._get_dur_time()})
+ 'last_axfr_duration':
+ self._const_sec})
- def test_do_soacheck_uptodate(self):
+ def test_axfrreq_xfrfail(self):
+ '''tests that axfrreqv4 or axfrreqv6 and xfrfail counters are
+ incremented when xfr requesting fails'''
self.soa_response_params['answers'] = [begin_soa_rrset]
self.conn.response_generator = self._create_soa_response_data
+ self.conn._tsig_key = TSIG_KEY
+ self.conn._tsig_ctx_creator = \
+ lambda key: self.__create_mock_tsig(key, TSIGError.BAD_SIG)
+ self.conn.response_generator = self._create_normal_response_data
self._check_init_statistics()
- self.assertEqual(self.conn.do_xfrin(True), XFRIN_OK)
- self._check_updated_statistics({'soaout' + self.ipver: 1,
- 'xfrsuccess': 1})
+ self.assertEqual(self.conn.do_xfrin(False), XFRIN_FAIL)
+ self._check_updated_statistics({'axfrreq' + self.ipver: 1,
+ 'xfrfail': 1})
class TestStatisticsXfrinIXFRv4(TestStatisticsXfrinConn):
'''Xfrin IXFR tests for IPv4 to check statistics counters'''
ipver = 'v4'
- def test_do_xfrin(self):
+ def test_ixfrreq_xfrsuccess_last_ixfr_duration(self):
+ '''tests that ixfrreqv4 or ixfrreqv6 and xfrsuccess counters
+ and last_ixfr_duration timer are incremented when xfr succeeds'''
def create_ixfr_response():
self.conn.reply_data = self.conn.create_response_data(
questions=[Question(TEST_ZONE_NAME, TEST_RRCLASS,
@@ -2219,27 +2229,15 @@ class TestStatisticsXfrinIXFRv4(TestStatisticsXfrinConn):
answers=[soa_rrset, begin_soa_rrset, soa_rrset, soa_rrset])
self.conn.response_generator = create_ixfr_response
self._check_init_statistics()
- self._set_start_time()
self.assertEqual(XFRIN_OK, self.conn.do_xfrin(False, RRType.IXFR))
self._check_updated_statistics({'ixfrreq' + self.ipver: 1,
'xfrsuccess': 1,
- 'latest_ixfr_duration':
- self._get_dur_time()})
+ 'last_ixfr_duration':
+ self._const_sec})
- def test_do_xfrin_fail(self):
- def create_ixfr_response():
- self.conn.reply_data = self.conn.create_response_data(
- questions=[Question(TEST_ZONE_NAME, TEST_RRCLASS,
- RRType.IXFR)],
- answers=[soa_rrset, begin_soa_rrset, soa_rrset,
- self._create_soa('1235')])
- self.conn.response_generator = create_ixfr_response
- self._check_init_statistics()
- self.assertEqual(XFRIN_FAIL, self.conn.do_xfrin(False, RRType.IXFR))
- self._check_updated_statistics({'ixfrreq' + self.ipver: 1,
- 'xfrfail': 1})
-
- def test_do_xfrin_uptodate(self):
+ def test_ixfrreq_xfrfail(self):
+ '''tests that ixfrreqv4 or ixfrreqv6 and xfrfail counters
+ are incremented when xfr succeeds'''
def create_response():
self.conn.reply_data = self.conn.create_response_data(
questions=[Question(TEST_ZONE_NAME, TEST_RRCLASS,
@@ -2249,7 +2247,7 @@ class TestStatisticsXfrinIXFRv4(TestStatisticsXfrinConn):
self._check_init_statistics()
self.assertEqual(XFRIN_OK, self.conn.do_xfrin(False, RRType.IXFR))
self._check_updated_statistics({'ixfrreq' + self.ipver: 1,
- 'xfrsuccess': 1})
+ 'xfrfail': 1})
class TestStatisticsXfrinAXFRv6(TestStatisticsXfrinAXFRv4):
'''Same tests as TestStatisticsXfrinAXFRv4 for IPv6'''
@@ -2578,7 +2576,7 @@ class TestXfrin(unittest.TestCase):
# there can be one more outstanding transfer.
self.assertEqual(self.xfr.command_handler("retransfer",
self.args)['result'][0], 0)
- # make sure the # xfrs would excceed the quota
+ # make sure the # xfrs would exceed the quota
self.xfr.recorder.increment(Name(str(self.xfr._max_transfers_in) + TEST_ZONE_NAME_STR))
# this one should fail
self.assertEqual(self.xfr.command_handler("retransfer",
diff --git a/src/bin/xfrin/xfrin.py.in b/src/bin/xfrin/xfrin.py.in
index 377ef88..7250f34 100755
--- a/src/bin/xfrin/xfrin.py.in
+++ b/src/bin/xfrin/xfrin.py.in
@@ -433,7 +433,7 @@ class XfrinIXFRAdd(XfrinState):
if soa_serial == conn._end_serial:
# The final part is there. Finish the transfer by
# checking the last TSIG (if required), the zone data and
- # commiting.
+ # committing.
conn.finish_transfer()
self.set_xfrstate(conn, XfrinIXFREnd())
return True
@@ -624,7 +624,7 @@ class XfrinConnection(asyncore.dispatcher):
it if the constructor raises an exception after opening the socket.
'''
self.create_socket(self._master_addrinfo[0], self._master_addrinfo[1])
- self.setblocking(1)
+ self.socket.setblocking(1)
def _get_zone_soa(self):
'''Retrieve the current SOA RR of the zone to be transferred.
@@ -822,7 +822,7 @@ class XfrinConnection(asyncore.dispatcher):
def finish_transfer(self):
"""
Perform any necessary checks after a transfer. Then complete the
- transfer by commiting the transaction into the data source.
+ transfer by committing the transaction into the data source.
"""
self._check_response_tsig_last()
if not check_zone(self._zone_name, self._rrclass,
@@ -962,15 +962,24 @@ class XfrinConnection(asyncore.dispatcher):
# not yet stopped due to some error, the last start time
# is overwritten at this point.
self._counters.start_timer('zones', self._zone_name.to_text(),
- 'latest_' + req_str.lower() + '_duration')
+ 'last_' + req_str.lower() + '_duration')
logger.info(XFRIN_XFR_TRANSFER_STARTED, req_str, self.zone_str())
- self._send_query(self._request_type)
- # count AXFR/IXFR requests for statistics
+ # An AXFR or IXFR is being requested.
self._counters.inc('zones', self._zone_name.to_text(),
req_str.lower() + 'req' +
self._get_ipver_str())
- self.__state = XfrinInitialSOA()
- self._handle_xfrin_responses()
+ try:
+ self._send_query(self._request_type)
+ self.__state = XfrinInitialSOA()
+ self._handle_xfrin_responses()
+ except:
+ # The AXFR or IXFR request failed.
+ self._counters.inc('zones', self._zone_name.to_text(),
+ 'xfrfail')
+ raise
+ # The AXFR or IXFR request succeeded.
+ self._counters.inc('zones', self._zone_name.to_text(),
+ 'xfrsuccess')
# Depending what data was found, we log different status reports
# (In case of an AXFR-style IXFR, print the 'AXFR' message)
if self._transfer_stats.axfr_rr_count == 0:
@@ -996,7 +1005,7 @@ class XfrinConnection(asyncore.dispatcher):
)
# stop statistics timer
self._counters.stop_timer('zones', self._zone_name.to_text(),
- 'latest_' + req_str.lower() + '_duration')
+ 'last_' + req_str.lower() + '_duration')
except XfrinZoneUptodate:
# Eventually we'll probably have to treat this case as a trigger
@@ -1037,10 +1046,6 @@ class XfrinConnection(asyncore.dispatcher):
# (if not yet - possible in case of xfr-level exception) as soon
# as possible
self._diff = None
- counter_dict = {XFRIN_OK: 'xfrsuccess', XFRIN_FAIL: 'xfrfail'}
- self._counters.inc('zones', self._zone_name.to_text(),
- counter_dict[ret])
-
return ret
def _check_response_header(self, msg):
@@ -1129,7 +1134,7 @@ def __process_xfrin(server, zone_name, rrclass, db_file,
if db_file is not None:
# temporary hardcoded sqlite initialization. Once we decide on
# the config specification, we need to update this (TODO)
- # this may depend on #1207, or any followup ticket created for #1207
+ # this may depend on #1207, or any follow-up ticket created for #1207
datasrc_type = "sqlite3"
datasrc_config = "{ \"database_file\": \"" + db_file + "\"}"
datasrc_client = DataSourceClient(datasrc_type, datasrc_config)
diff --git a/src/bin/xfrin/xfrin.spec b/src/bin/xfrin/xfrin.spec
index 6071ada..b3e101a 100644
--- a/src/bin/xfrin/xfrin.spec
+++ b/src/bin/xfrin/xfrin.spec
@@ -110,8 +110,8 @@
"ixfrreqv6": 0,
"xfrsuccess": 0,
"xfrfail": 0,
- "latest_ixfr_duration": 0.0,
- "latest_axfr_duration": 0.0
+ "last_ixfr_duration": 0.0,
+ "last_axfr_duration": 0.0
}
},
"item_title": "Zone names",
@@ -122,7 +122,7 @@
"item_optional": false,
"item_default": {},
"item_title": "Zone name",
- "item_description": "An actual zone name or special zone name _SERVER_ representing the entire server",
+ "item_description": "An actual zone name or special zone name _SERVER_ representing the entire server. Zone classes (IN, CH, HS) are mixed and counted so far. But these will be distinguished in future release.",
"map_item_spec": [
{
"item_name": "soaoutv4",
@@ -189,20 +189,20 @@
"item_description": "Number of zone transfer requests failed"
},
{
- "item_name": "latest_ixfr_duration",
+ "item_name": "last_ixfr_duration",
"item_type": "real",
"item_optional": false,
"item_default": 0.0,
- "item_title": "Latest IXFR duration",
- "item_description": "Duration of the latest IXFR. 0.0 means no successful IXFR done."
+ "item_title": "Last IXFR duration",
+ "item_description": "Duration of the last IXFR. 0.0 means no successful IXFR done in greater than or equal to a microsecond. If a started timer is never stopped because of failure, start time of duration will be reset next time."
},
{
- "item_name": "latest_axfr_duration",
+ "item_name": "last_axfr_duration",
"item_type": "real",
"item_optional": false,
"item_default": 0.0,
- "item_title": "Latest AXFR duration",
- "item_description": "Duration of the latest AXFR. 0.0 means no successful AXFR done."
+ "item_title": "Last AXFR duration",
+ "item_description": "Duration of the last AXFR. 0.0 means no successful AXFR done in greater than or equal to a microsecond. If a started timer is never stopped because of failure, start time of duration will be reset next time."
}
]
}
diff --git a/src/bin/xfrin/xfrin_messages.mes b/src/bin/xfrin/xfrin_messages.mes
index 7160d17..eeddee9 100644
--- a/src/bin/xfrin/xfrin_messages.mes
+++ b/src/bin/xfrin/xfrin_messages.mes
@@ -135,6 +135,9 @@ from does not match the master address in the Xfrin configuration. The notify
is ignored. This may indicate that the configuration for the master is wrong,
that a wrong machine is sending notifies, or that fake notifies are being sent.
+% XFRIN_RECEIVED_COMMAND received command: %1
+The xfrin daemon received a command on the command channel.
+
% XFRIN_RETRANSFER_UNKNOWN_ZONE got notification to retransfer unknown zone %1
There was an internal command to retransfer the given zone, but the
zone is not known to the system. This may indicate that the configuration
@@ -274,6 +277,3 @@ The zone was received successfully, but when checking it, it was discovered
there's some issue with it. It might be correct, but it should be checked
and possibly fixed on the remote server. The problem is described in the
message. The problem does not stop the zone from being used.
-
-% XFRIN_RECEIVED_COMMAND received command: %1
-The xfrin daemon received a command on the command channel.
diff --git a/src/bin/xfrout/tests/xfrout_test.py.in b/src/bin/xfrout/tests/xfrout_test.py.in
index 2802ace..f663e55 100644
--- a/src/bin/xfrout/tests/xfrout_test.py.in
+++ b/src/bin/xfrout/tests/xfrout_test.py.in
@@ -191,7 +191,7 @@ class Dbserver:
self.transfer_counter -= 1
class TestXfroutSessionBase(unittest.TestCase):
- '''Base classs for tests related to xfrout sessions
+ '''Base class for tests related to xfrout sessions
This class defines common setup/teadown and utility methods. Actual
tests are delegated to subclasses.
diff --git a/src/bin/xfrout/xfrout.py.in b/src/bin/xfrout/xfrout.py.in
index d6ef360..1863ad0 100755
--- a/src/bin/xfrout/xfrout.py.in
+++ b/src/bin/xfrout/xfrout.py.in
@@ -186,7 +186,7 @@ class XfroutSession():
'''
# Check the xfrout quota. We do both increase/decrease in this
- # method so it's clear we always release it once acuired.
+ # method so it's clear we always release it once acquired.
quota_ok = self._server.increase_transfers_counter()
ex = None
try:
@@ -502,7 +502,7 @@ class XfroutSession():
return self._reply_query_with_error_rcode(msg, sock_fd,
Rcode.FORMERR)
elif not quota_ok:
- logger.warn(XFROUT_QUERY_QUOTA_EXCCEEDED, self._request_typestr,
+ logger.warn(XFROUT_QUERY_QUOTA_EXCEEDED, self._request_typestr,
format_addrinfo(self._remote),
self._server._max_transfers_out)
return self._reply_query_with_error_rcode(msg, sock_fd,
diff --git a/src/bin/xfrout/xfrout_messages.mes b/src/bin/xfrout/xfrout_messages.mes
index d49981d..505eb7c 100644
--- a/src/bin/xfrout/xfrout_messages.mes
+++ b/src/bin/xfrout/xfrout_messages.mes
@@ -131,7 +131,7 @@ given host. This is required by the ACLs. The %2 represents the IP
address and port of the peer requesting the transfer, and the %3
represents the zone name and class.
-% XFROUT_QUERY_QUOTA_EXCCEEDED %1 client %2: request denied due to quota (%3)
+% XFROUT_QUERY_QUOTA_EXCEEDED %1 client %2: request denied due to quota (%3)
The xfr request was rejected because the server was already handling
the maximum number of allowable transfers as specified in the transfers_out
configuration parameter, which is also shown in the log message. The
diff --git a/src/bin/zonemgr/tests/zonemgr_test.py b/src/bin/zonemgr/tests/zonemgr_test.py
index 81c5392..111d650 100644
--- a/src/bin/zonemgr/tests/zonemgr_test.py
+++ b/src/bin/zonemgr/tests/zonemgr_test.py
@@ -314,16 +314,22 @@ class TestZonemgrRefresh(unittest.TestCase):
sqlite3_ds.get_zone_soa = old_get_zone_soa
def test_zone_handle_notify(self):
- self.zone_refresh.zone_handle_notify(ZONE_NAME_CLASS1_IN,"127.0.0.1")
- notify_master = self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["notify_master"]
+ self.assertTrue(self.zone_refresh.zone_handle_notify(
+ ZONE_NAME_CLASS1_IN, "127.0.0.1"))
+ notify_master = self.zone_refresh.\
+ _zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["notify_master"]
self.assertEqual("127.0.0.1", notify_master)
- zone_timeout = self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["next_refresh_time"]
+ zone_timeout = self.zone_refresh.\
+ _zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["next_refresh_time"]
current_time = time.time()
self.assertTrue(zone_timeout <= current_time)
- self.assertRaises(ZonemgrException, self.zone_refresh.zone_handle_notify,\
- ZONE_NAME_CLASS3_CH, "127.0.0.1")
- self.assertRaises(ZonemgrException, self.zone_refresh.zone_handle_notify,\
- ZONE_NAME_CLASS3_IN, "127.0.0.1")
+
+ # If the specified zone does not in the configured secondary list,
+ # it should return False.
+ self.assertFalse(self.zone_refresh.zone_handle_notify(
+ ZONE_NAME_CLASS3_CH, "127.0.0.1"))
+ self.assertFalse(self.zone_refresh.zone_handle_notify(
+ ZONE_NAME_CLASS3_IN, "127.0.0.1"))
def test_zone_refresh_success(self):
soa_rdata = 'a.example.net. root.example.net. 2009073106 1800 900 2419200 21600'
@@ -607,6 +613,19 @@ class TestZonemgrRefresh(unittest.TestCase):
config, self.cc_session)
class MyZonemgr(Zonemgr):
+ class DummySocket:
+ """This dummy class simply steal send() to record any transmitted data.
+
+ """
+ def __init__(self):
+ self.sent_data = []
+
+ def send(self, data):
+ self.sent_data.append(data)
+
+ class DummyLock:
+ def __enter__(self): pass
+ def __exit__(self, type, value, traceback): pass
def __init__(self):
self._db_file = TEST_SQLITE3_DBFILE
@@ -621,6 +640,8 @@ class MyZonemgr(Zonemgr):
"reload_jitter" : 0.75,
"secondary_zones": []
}
+ self._lock = self.DummyLock()
+ self._master_socket = self.DummySocket()
def _start_zone_refresh_timer(self):
pass
@@ -672,15 +693,21 @@ class TestZonemgr(unittest.TestCase):
self.assertEqual(TEST_SQLITE3_DBFILE, self.zonemgr.get_db_file())
def test_parse_cmd_params(self):
- params1 = {"zone_name" : "example.com.", "zone_class" : "CH", "master" : "127.0.0.1"}
+ params1 = {"zone_name" : "example.com.", "zone_class" : "CH",
+ "master" : "127.0.0.1"}
answer1 = (ZONE_NAME_CLASS3_CH, "127.0.0.1")
- self.assertEqual(answer1, self.zonemgr._parse_cmd_params(params1, ZONE_NOTIFY_COMMAND))
+ self.assertEqual(answer1,
+ self.zonemgr._parse_cmd_params(params1,
+ ZONE_NOTIFY_COMMAND))
params2 = {"zone_name" : "example.com.", "zone_class" : "IN"}
answer2 = ZONE_NAME_CLASS3_IN
- self.assertEqual(answer2, self.zonemgr._parse_cmd_params(params2, notify_out.ZONE_NEW_DATA_READY_CMD))
- self.assertRaises(ZonemgrException, self.zonemgr._parse_cmd_params, params2, ZONE_NOTIFY_COMMAND)
+ self.assertEqual(answer2, self.zonemgr._parse_cmd_params(
+ params2, notify_out.ZONE_NEW_DATA_READY_CMD))
+ self.assertRaises(ZonemgrException, self.zonemgr._parse_cmd_params,
+ params2, ZONE_NOTIFY_COMMAND)
params1 = {"zone_class" : "CH"}
- self.assertRaises(ZonemgrException, self.zonemgr._parse_cmd_params, params2, ZONE_NOTIFY_COMMAND)
+ self.assertRaises(ZonemgrException, self.zonemgr._parse_cmd_params,
+ params2, ZONE_NOTIFY_COMMAND)
def test_config_data_check(self):
# jitter should not be bigger than half of the original value
@@ -697,6 +724,26 @@ class TestZonemgr(unittest.TestCase):
self.zonemgr.run()
self.assertTrue(self.zonemgr._module_cc.stopped)
+ def test_command_handler_notify(self):
+ """Check the result of NOTIFY command."""
+ self.zonemgr._zone_refresh = MyZonemgrRefresh()
+
+ # On successful case, the other thread will be notified via
+ # _master_socket.
+ self.zonemgr._zone_refresh.zone_handle_notify = lambda x, y: True
+ self.zonemgr.command_handler("notify", {"zone_name": "example.",
+ "zone_class": "IN",
+ "master": "192.0.2.1"})
+ self.assertEqual([b" "], self.zonemgr._master_socket.sent_data)
+
+ # If the specified is not found in the secondary list, it doesn't
+ # bother to wake the thread (sent_data shouldn't change)
+ self.zonemgr._zone_refresh.zone_handle_notify = lambda x, y: False
+ self.zonemgr.command_handler("notify", {"zone_name": "example.",
+ "zone_class": "IN",
+ "master": "192.0.2.1"})
+ self.assertEqual([b" "], self.zonemgr._master_socket.sent_data)
+
if __name__== "__main__":
isc.log.resetUnitTestRootLogger()
unittest.main()
diff --git a/src/bin/zonemgr/zonemgr.py.in b/src/bin/zonemgr/zonemgr.py.in
index 59900c4..619e017 100755
--- a/src/bin/zonemgr/zonemgr.py.in
+++ b/src/bin/zonemgr/zonemgr.py.in
@@ -191,14 +191,31 @@ class ZonemgrRefresh:
self._set_zone_retry_timer(zone_name_class)
def zone_handle_notify(self, zone_name_class, master):
- """Handle zone notify"""
- if (self._zone_not_exist(zone_name_class)):
- logger.error(ZONEMGR_UNKNOWN_ZONE_NOTIFIED, zone_name_class[0],
- zone_name_class[1], master)
- raise ZonemgrException("[b10-zonemgr] Notified zone (%s, %s) "
- "doesn't belong to zonemgr" % zone_name_class)
+ """Handle an incomding NOTIFY message via the Auth module.
+
+ It returns True if the specified zone matches one of the locally
+ configured list of secondary zones; otherwise returns False.
+ In the latter case it assumes the server is a primary (master) of the
+ zone; the Auth module should have rejected the case where it's not
+ even authoritative for the zone.
+
+ Note: to be more robust and less independent from other module's
+ behavior, it's probably safer to check the authority condition here,
+ too. But right now it uses SQLite3 specific API (to be deprecated),
+ so we rather rely on Auth.
+
+ Parameters:
+ zone_name_class (Name, RRClass): the notified zone name and class.
+ master (str): textual address of the NOTIFY sender.
+
+ """
+ if self._zone_not_exist(zone_name_class):
+ logger.debug(DBG_ZONEMGR_BASIC, ZONEMGR_ZONE_NOTIFY_NOT_SECONDARY,
+ zone_name_class[0], zone_name_class[1], master)
+ return False
self._set_zone_notifier_master(zone_name_class, master)
self._set_zone_notify_timer(zone_name_class)
+ return True
def zonemgr_reload_zone(self, zone_name_class):
""" Reload a zone."""
@@ -423,7 +440,7 @@ class ZonemgrRefresh:
# Ask the thread to stop
self._running = False
- self._write_sock.send(b'shutdown') # make self._read_sock readble
+ self._write_sock.send(b'shutdown') # make self._read_sock readable
# Wait for it to actually finnish
self._thread.join()
# Wipe out what we do not need
@@ -630,27 +647,33 @@ class Zonemgr:
""" Handle Auth notify command"""
# master is the source sender of the notify message.
zone_name_class, master = self._parse_cmd_params(args, command)
- logger.debug(DBG_ZONEMGR_COMMAND, ZONEMGR_RECEIVE_NOTIFY, zone_name_class[0], zone_name_class[1])
+ logger.debug(DBG_ZONEMGR_COMMAND, ZONEMGR_RECEIVE_NOTIFY,
+ zone_name_class[0], zone_name_class[1])
with self._lock:
- self._zone_refresh.zone_handle_notify(zone_name_class, master)
- # Send notification to zonemgr timer thread
- self._master_socket.send(b" ")# make self._slave_socket readble
+ need_refresh = self._zone_refresh.zone_handle_notify(
+ zone_name_class, master)
+ if need_refresh:
+ # Send notification to zonemgr timer thread by making
+ # self._slave_socket readable.
+ self._master_socket.send(b" ")
elif command == notify_out.ZONE_NEW_DATA_READY_CMD:
""" Handle xfrin success command"""
zone_name_class = self._parse_cmd_params(args, command)
- logger.debug(DBG_ZONEMGR_COMMAND, ZONEMGR_RECEIVE_XFRIN_SUCCESS, zone_name_class[0], zone_name_class[1])
+ logger.debug(DBG_ZONEMGR_COMMAND, ZONEMGR_RECEIVE_XFRIN_SUCCESS,
+ zone_name_class[0], zone_name_class[1])
with self._lock:
self._zone_refresh.zone_refresh_success(zone_name_class)
- self._master_socket.send(b" ")# make self._slave_socket readble
+ self._master_socket.send(b" ")# make self._slave_socket readable
elif command == notify_out.ZONE_XFRIN_FAILED:
""" Handle xfrin fail command"""
zone_name_class = self._parse_cmd_params(args, command)
- logger.debug(DBG_ZONEMGR_COMMAND, ZONEMGR_RECEIVE_XFRIN_FAILED, zone_name_class[0], zone_name_class[1])
+ logger.debug(DBG_ZONEMGR_COMMAND, ZONEMGR_RECEIVE_XFRIN_FAILED,
+ zone_name_class[0], zone_name_class[1])
with self._lock:
self._zone_refresh.zone_refresh_fail(zone_name_class)
- self._master_socket.send(b" ")# make self._slave_socket readble
+ self._master_socket.send(b" ")# make self._slave_socket readable
elif command == "shutdown":
logger.debug(DBG_ZONEMGR_COMMAND, ZONEMGR_RECEIVE_SHUTDOWN)
@@ -667,7 +690,19 @@ class Zonemgr:
self.running = True
try:
while not self._shutdown_event.is_set():
- self._module_cc.check_command(False)
+ fileno = self._module_cc.get_socket().fileno()
+ # Wait with select() until there is something to read,
+ # and then read it using a non-blocking read
+ # This may or may not be relevant data for this loop,
+ # but due to the way the zonemgr does threading, we
+ # can't have a blocking read loop here.
+ try:
+ (reads, _, _) = select.select([fileno], [], [])
+ except select.error as se:
+ if se.args[0] != errno.EINTR:
+ raise
+ if fileno in reads:
+ self._module_cc.check_command(True)
finally:
self._module_cc.send_stopping()
diff --git a/src/bin/zonemgr/zonemgr_messages.mes b/src/bin/zonemgr/zonemgr_messages.mes
index f67b5b9..0334858 100644
--- a/src/bin/zonemgr/zonemgr_messages.mes
+++ b/src/bin/zonemgr/zonemgr_messages.mes
@@ -138,14 +138,19 @@ zone, or, if this error appears without the administrator giving transfer
commands, it can indicate an error in the program, as it should not have
initiated transfers of unknown zones on its own.
-% ZONEMGR_UNKNOWN_ZONE_NOTIFIED notified zone %1/%2 from %3 is not known to the zone manager
-A NOTIFY was received but the zone that was the subject of the operation
-is not being managed by the zone manager. This may indicate an error
-in the program (as the operation should not have been initiated if this
-were the case). Please submit a bug report.
-
% ZONEMGR_UNKNOWN_ZONE_SUCCESS zone %1 (class %2) is not known to the zone manager
An XFRIN operation has succeeded but the zone received is not being
managed by the zone manager. This may indicate an error in the program
(as the operation should not have been initiated if this were the case).
Please submit a bug report.
+
+% ZONEMGR_ZONE_NOTIFY_NOT_SECONDARY notify for zone %1/%2 from %3 received but not in secondaries
+A NOTIFY was received but the zone is not listed in the configured
+secondary zones of the zone manager. The most common reason for this
+is that it's simply received by a primary server of the zone. Another
+possibility is a configuration error that it's not configured as a
+secondary while it should be. In either case, the zone manager does
+not take action in terms of zone management, and the authoritative
+server will respond to it like in the secondary case. If this is a
+configuration error, it will be noticed by the fact that the zone
+isn't updated even after a change is made in the primary server.
diff --git a/src/lib/asiodns/dns_answer.h b/src/lib/asiodns/dns_answer.h
index 4b4576b..89896da 100644
--- a/src/lib/asiodns/dns_answer.h
+++ b/src/lib/asiodns/dns_answer.h
@@ -32,7 +32,7 @@ namespace asiodns {
/// via its constructor.
///
/// A DNS Answer provider function takes answer data that has been obtained
-/// from a DNS Lookup provider functon and readies it to be sent to the
+/// from a DNS Lookup provider function and readies it to be sent to the
/// client. After it has run, the OutputBuffer object passed to it should
/// contain the answer to the query rendered into wire format.
class DNSAnswer {
diff --git a/src/lib/asiodns/dns_server.h b/src/lib/asiodns/dns_server.h
index 3b8758f..35811c0 100644
--- a/src/lib/asiodns/dns_server.h
+++ b/src/lib/asiodns/dns_server.h
@@ -71,7 +71,7 @@ public:
/// without losing access to derived class data.
///
//@{
- /// \brief The funtion operator
+ /// \brief The function operator
virtual void operator()(asio::error_code ec = asio::error_code(),
size_t length = 0)
{
diff --git a/src/lib/asiodns/io_fetch.h b/src/lib/asiodns/io_fetch.h
index c31ee09..0a03144 100644
--- a/src/lib/asiodns/io_fetch.h
+++ b/src/lib/asiodns/io_fetch.h
@@ -143,7 +143,7 @@ public:
/// \brief Constructor
/// This constructor has one parameter "query_message", which
/// is the shared_ptr to a full query message. It's different
- /// with above contructor which has only question section. All
+ /// with above constructor which has only question section. All
/// other parameters are same.
///
/// \param query_message the shared_ptr to a full query message
diff --git a/src/lib/asiodns/sync_udp_server.cc b/src/lib/asiodns/sync_udp_server.cc
index c3f5348..d5d2a7a 100644
--- a/src/lib/asiodns/sync_udp_server.cc
+++ b/src/lib/asiodns/sync_udp_server.cc
@@ -174,13 +174,13 @@ SyncUDPServer::operator()(asio::error_code, size_t) {
void
SyncUDPServer::stop() {
/// Using close instead of cancel, because cancel
- /// will only cancel the asynchornized event already submitted
+ /// will only cancel the asynchronized event already submitted
/// to io service, the events post to io service after
/// cancel still can be scheduled by io service, if
- /// the socket is cloesed, all the asynchronized event
+ /// the socket is closed, all the asynchronized event
/// for it won't be scheduled by io service not matter it is
- /// submit to io serice before or after close call. And we will
- //. get bad_descriptor error
+ /// submit to io service before or after close call. And we will
+ /// get bad_descriptor error.
socket_->close();
stopped_ = true;
}
diff --git a/src/lib/asiodns/tests/dns_server_unittest.cc b/src/lib/asiodns/tests/dns_server_unittest.cc
index c05a34b..51fb6b8 100644
--- a/src/lib/asiodns/tests/dns_server_unittest.cc
+++ b/src/lib/asiodns/tests/dns_server_unittest.cc
@@ -51,8 +51,8 @@
/// Before the server start to run
/// After we get the query and check whether it's valid
/// After we lookup the query
-/// After we compoisite the answer
-/// After user get the final result.
+/// After we compose the answer
+/// After user gets the final result.
/// The standard about whether we stop the server successfully or not
/// is based on the fact that if the server is still running, the io
@@ -83,7 +83,7 @@ const char* const server_port_str = "5553";
const char* const query_message = "BIND10 is awesome";
// \brief provide capacity to derived class the ability
-// to stop DNSServer at certern point
+// to stop DNSServer at certain point
class ServerStopper {
public:
ServerStopper() : server_to_stop_(NULL) {}
@@ -148,7 +148,7 @@ class SimpleAnswer : public DNSAnswer, public ServerStopper {
};
// \brief simple client, send one string to server and wait for response
-// in case, server stopped and client cann't get response, there is a timer wait
+// in case, server stopped and client can't get response, there is a timer wait
// for specified seconds (the value is just a estimate since server process logic is quite
// simple, and all the intercommunication is local) then cancel the waiting.
class SimpleClient : public ServerStopper {
diff --git a/src/lib/asiodns/udp_server.cc b/src/lib/asiodns/udp_server.cc
index cf4b1c4..f84a4d6 100644
--- a/src/lib/asiodns/udp_server.cc
+++ b/src/lib/asiodns/udp_server.cc
@@ -323,13 +323,13 @@ UDPServer::asyncLookup() {
void
UDPServer::stop() {
/// Using close instead of cancel, because cancel
- /// will only cancel the asynchornized event already submitted
+ /// will only cancel the asynchronized event already submitted
/// to io service, the events post to io service after
/// cancel still can be scheduled by io service, if
- /// the socket is cloesed, all the asynchronized event
+ /// the socket is closed, all the asynchronized event
/// for it won't be scheduled by io service not matter it is
- /// submit to io serice before or after close call. And we will
- //. get bad_descriptor error
+ /// submit to io service before or after close call. And we will
+ // get bad_descriptor error.
data_->socket_->close();
}
diff --git a/src/lib/asiolink/io_asio_socket.h b/src/lib/asiolink/io_asio_socket.h
index f6d64a0..a3f3f97 100644
--- a/src/lib/asiolink/io_asio_socket.h
+++ b/src/lib/asiolink/io_asio_socket.h
@@ -158,7 +158,7 @@ public:
/// (The reason there is a need to know is because the call to open() passes
/// in the state of the coroutine at the time the call is made. On an
/// asynchronous I/O, we need to set the state to point to the statement
- /// after the call to open() _before_ we pass the corouine to the open()
+ /// after the call to open() _before_ we pass the coroutine to the open()
/// call. Unfortunately, the macros that set the state of the coroutine
/// also yield control - which we don't want to do if the open is
/// synchronous. Hence we need to know before we make the call to open()
diff --git a/src/lib/asiolink/tcp_endpoint.h b/src/lib/asiolink/tcp_endpoint.h
index 3d6a87a..2fe64f3 100644
--- a/src/lib/asiolink/tcp_endpoint.h
+++ b/src/lib/asiolink/tcp_endpoint.h
@@ -100,7 +100,7 @@ public:
return (asio_endpoint_.protocol().family());
}
- // This is not part of the exosed IOEndpoint API but allows
+ // This is not part of the exposed IOEndpoint API but allows
// direct access to the ASIO implementation of the endpoint
inline const asio::ip::tcp::endpoint& getASIOEndpoint() const {
return (asio_endpoint_);
diff --git a/src/lib/asiolink/tests/tcp_socket_unittest.cc b/src/lib/asiolink/tests/tcp_socket_unittest.cc
index 20b6cd8..9de366c 100644
--- a/src/lib/asiolink/tests/tcp_socket_unittest.cc
+++ b/src/lib/asiolink/tests/tcp_socket_unittest.cc
@@ -14,7 +14,7 @@
/// \brief Test of TCPSocket
///
-/// Tests the fuctionality of a TCPSocket by working through an open-send-
+/// Tests the functionality of a TCPSocket by working through an open-send-
/// receive-close sequence and checking that the asynchronous notifications
/// work.
diff --git a/src/lib/asiolink/tests/udp_socket_unittest.cc b/src/lib/asiolink/tests/udp_socket_unittest.cc
index 1ab1a09..3d91874 100644
--- a/src/lib/asiolink/tests/udp_socket_unittest.cc
+++ b/src/lib/asiolink/tests/udp_socket_unittest.cc
@@ -14,7 +14,7 @@
/// \brief Test of UDPSocket
///
-/// Tests the fuctionality of a UDPSocket by working through an open-send-
+/// Tests the functionality of a UDPSocket by working through an open-send-
/// receive-close sequence and checking that the asynchronous notifications
/// work.
diff --git a/src/lib/asiolink/udp_endpoint.h b/src/lib/asiolink/udp_endpoint.h
index 34701b9..02e800d 100644
--- a/src/lib/asiolink/udp_endpoint.h
+++ b/src/lib/asiolink/udp_endpoint.h
@@ -100,7 +100,7 @@ public:
return (asio_endpoint_.protocol().family());
}
- // This is not part of the exosed IOEndpoint API but allows
+ // This is not part of the exposed IOEndpoint API but allows
// direct access to the ASIO implementation of the endpoint
inline const asio::ip::udp::endpoint& getASIOEndpoint() const {
return (asio_endpoint_);
diff --git a/src/lib/cc/cc_messages.mes b/src/lib/cc/cc_messages.mes
index b561784..9be9c7c 100644
--- a/src/lib/cc/cc_messages.mes
+++ b/src/lib/cc/cc_messages.mes
@@ -37,7 +37,7 @@ socket listed in the output.
This debug message indicates that the connection was successfully made, this
should follow CC_ESTABLISH.
-% CC_GROUP_RECEIVE trying to receive a message
+% CC_GROUP_RECEIVE trying to receive a message with seq %1
Debug message, noting that a message is expected to come over the command
channel.
diff --git a/src/lib/cc/data.h b/src/lib/cc/data.h
index db25d9f..d0e0d03 100644
--- a/src/lib/cc/data.h
+++ b/src/lib/cc/data.h
@@ -216,7 +216,7 @@ public:
//@{
/// Returns the ElementPtr at the given key
/// \param name The key of the Element to return
- /// \return The ElementPtr at the given key
+ /// \return The ElementPtr at the given key, or null if not present
virtual ConstElementPtr get(const std::string& name) const;
/// Sets the ElementPtr at the given key
@@ -504,7 +504,7 @@ public:
// find the Element at 'id', and store the element pointer in t
// returns true if found, or false if not found (either because
- // it doesnt exist or one of the elements in the path is not
+ // it doesn't exist or one of the elements in the path is not
// a MapElement)
bool find(const std::string& id, ConstElementPtr& t) const;
diff --git a/src/lib/cc/proto_defs.cc b/src/lib/cc/proto_defs.cc
index 5eb8575..8f7fb91 100644
--- a/src/lib/cc/proto_defs.cc
+++ b/src/lib/cc/proto_defs.cc
@@ -34,12 +34,22 @@ const char* const CC_HEADER_WANT_ANSWER = "want_answer";
const char* const CC_HEADER_REPLY = "reply";
// The commands in the "type" header
const char* const CC_COMMAND_SEND = "send";
+const char* const CC_COMMAND_SUBSCRIBE = "subscribe";
+const char* const CC_COMMAND_UNSUBSCRIBE = "unsubscribe";
+const char* const CC_COMMAND_GET_LNAME = "getlname";
+const char* const CC_COMMAND_PING = "ping";
+const char* const CC_COMMAND_PONG = "pong";
+const char* const CC_COMMAND_STOP = "stop";
// The wildcards of some headers
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;
+const int CC_REPLY_SUCCESS = 0;
+// Payload in the message
+const char *const CC_PAYLOAD_LNAME = "lname";
+const char *const CC_PAYLOAD_RESULT = "result";
+const char *const CC_PAYLOAD_COMMAND = "command";
}
}
diff --git a/src/lib/cc/session.cc b/src/lib/cc/session.cc
index da78bd4..cb1ca39 100644
--- a/src/lib/cc/session.cc
+++ b/src/lib/cc/session.cc
@@ -260,7 +260,7 @@ SessionImpl::getSocketDesc() {
/// @todo boost 1.42 uses native() method, but it is deprecated
/// in 1.49 and native_handle() is recommended instead
if (!socket_.is_open()) {
- isc_throw(InvalidOperation, "Can't return socket desciptor: no socket opened.");
+ isc_throw(InvalidOperation, "Can't return socket descriptor: no socket opened.");
}
return socket_.native();
}
@@ -325,14 +325,14 @@ Session::establish(const char* socket_file) {
//
// send a request for our local name, and wait for a response
//
- ConstElementPtr get_lname_msg =
- Element::fromJSON("{ \"type\": \"getlname\" }");
+ ElementPtr get_lname_msg(Element::createMap());
+ get_lname_msg->set(CC_HEADER_TYPE, Element::create(CC_COMMAND_GET_LNAME));
sendmsg(get_lname_msg);
ConstElementPtr routing, msg;
recvmsg(routing, msg, false);
- impl_->lname_ = msg->get("lname")->stringValue();
+ impl_->lname_ = msg->get(CC_PAYLOAD_LNAME)->stringValue();
LOG_DEBUG(logger, DBG_TRACE_DETAILED, CC_LNAME_RECEIVED).arg(impl_->lname_);
// At this point there's no risk of resource leak.
@@ -387,10 +387,10 @@ Session::recvmsg(ConstElementPtr& env, ConstElementPtr& msg,
for (size_t i = 0; i < impl_->queue_->size(); i++) {
q_el = impl_->queue_->get(i);
if (( seq == -1 &&
- !q_el->get(0)->contains("reply")
+ !q_el->get(0)->contains(CC_HEADER_REPLY)
) || (
- q_el->get(0)->contains("reply") &&
- q_el->get(0)->get("reply")->intValue() == seq
+ q_el->get(0)->contains(CC_HEADER_REPLY) &&
+ q_el->get(0)->get(CC_HEADER_REPLY)->intValue() == seq
)
) {
env = q_el->get(0);
@@ -429,10 +429,10 @@ Session::recvmsg(ConstElementPtr& env, ConstElementPtr& msg,
ConstElementPtr l_msg =
Element::fromWire(body_wire_stream, length - header_length);
if ((seq == -1 &&
- !l_env->contains("reply")
+ !l_env->contains(CC_HEADER_REPLY)
) || (
- l_env->contains("reply") &&
- l_env->get("reply")->intValue() == seq
+ l_env->contains(CC_HEADER_REPLY) &&
+ l_env->get(CC_HEADER_REPLY)->intValue() == seq
)
) {
env = l_env;
@@ -453,9 +453,9 @@ Session::subscribe(std::string group, std::string instance) {
LOG_DEBUG(logger, DBG_TRACE_DETAILED, CC_SUBSCRIBE).arg(group);
ElementPtr env = Element::createMap();
- env->set("type", Element::create("subscribe"));
- env->set("group", Element::create(group));
- env->set("instance", Element::create(instance));
+ env->set(CC_HEADER_TYPE, Element::create(CC_COMMAND_SUBSCRIBE));
+ env->set(CC_HEADER_GROUP, Element::create(group));
+ env->set(CC_HEADER_INSTANCE, Element::create(instance));
sendmsg(env);
}
@@ -465,9 +465,9 @@ Session::unsubscribe(std::string group, std::string instance) {
LOG_DEBUG(logger, DBG_TRACE_DETAILED, CC_UNSUBSCRIBE).arg(group);
ElementPtr env = Element::createMap();
- env->set("type", Element::create("unsubscribe"));
- env->set("group", Element::create(group));
- env->set("instance", Element::create(instance));
+ env->set(CC_HEADER_TYPE, Element::create(CC_COMMAND_UNSUBSCRIBE));
+ env->set(CC_HEADER_GROUP, Element::create(group));
+ env->set(CC_HEADER_INSTANCE, Element::create(instance));
sendmsg(env);
}
@@ -498,7 +498,7 @@ bool
Session::group_recvmsg(ConstElementPtr& envelope, ConstElementPtr& msg,
bool nonblock, int seq)
{
- LOG_DEBUG(logger, DBG_TRACE_DETAILED, CC_GROUP_RECEIVE);
+ LOG_DEBUG(logger, DBG_TRACE_DETAILED, CC_GROUP_RECEIVE).arg(seq);
bool result(recvmsg(envelope, msg, nonblock, seq));
if (result) {
LOG_DEBUG(logger, DBG_TRACE_DETAILED, CC_GROUP_RECEIVED).
@@ -516,13 +516,17 @@ Session::reply(ConstElementPtr envelope, ConstElementPtr newmsg) {
ElementPtr env = Element::createMap();
long int nseq = ++impl_->sequence_;
- env->set("type", Element::create("send"));
- env->set("from", Element::create(impl_->lname_));
- env->set("to", Element::create(envelope->get("from")->stringValue()));
- env->set("group", Element::create(envelope->get("group")->stringValue()));
- env->set("instance", Element::create(envelope->get("instance")->stringValue()));
- env->set("seq", Element::create(nseq));
- env->set("reply", Element::create(envelope->get("seq")->intValue()));
+ env->set(CC_HEADER_TYPE, Element::create(CC_COMMAND_SEND));
+ env->set(CC_HEADER_FROM, Element::create(impl_->lname_));
+ env->set(CC_HEADER_TO,
+ Element::create(envelope->get(CC_HEADER_FROM)->stringValue()));
+ env->set(CC_HEADER_GROUP,
+ Element::create(envelope->get(CC_HEADER_GROUP)->stringValue()));
+ env->set(CC_HEADER_INSTANCE,
+ Element::create(envelope->get(CC_HEADER_INSTANCE)->stringValue()));
+ env->set(CC_HEADER_SEQ, Element::create(nseq));
+ env->set(CC_HEADER_REPLY,
+ Element::create(envelope->get(CC_HEADER_SEQ)->intValue()));
sendmsg(env, newmsg);
diff --git a/src/lib/cc/tests/session_unittests.cc b/src/lib/cc/tests/session_unittests.cc
index fc6e538..2531ce1 100644
--- a/src/lib/cc/tests/session_unittests.cc
+++ b/src/lib/cc/tests/session_unittests.cc
@@ -46,7 +46,7 @@ TEST(AsioSession, establish) {
asio::io_service io_service_;
Session sess(io_service_);
- // can't return socket desciptor before session is established
+ // can't return socket descriptor before session is established
EXPECT_THROW(sess.getSocketDesc(), isc::InvalidOperation);
EXPECT_THROW(
@@ -293,7 +293,7 @@ TEST_F(SessionTest, run_with_handler_timeout) {
msg = isc::data::Element::fromJSON("{ \"a third\": \"message\" }");
tds->sendmsg(env, msg);
- // No followup message, should time out.
+ // No follow-up message, should time out.
ASSERT_THROW(my_io_service.run(), SessionTimeout);
}
diff --git a/src/lib/config/ccsession.cc b/src/lib/config/ccsession.cc
index 378f2b4..f65831d 100644
--- a/src/lib/config/ccsession.cc
+++ b/src/lib/config/ccsession.cc
@@ -32,7 +32,7 @@
#include <boost/foreach.hpp>
#include <cc/data.h>
-#include <module_spec.h>
+#include <config/module_spec.h>
#include <cc/session.h>
#include <exceptions/exceptions.h>
@@ -57,10 +57,10 @@ namespace config {
/// Creates a standard config/command protocol answer message
ConstElementPtr
createAnswer() {
- ElementPtr answer = Element::fromJSON("{\"result\": [] }");
+ ElementPtr answer = Element::createMap();
ElementPtr answer_content = Element::createList();
- answer_content->add(Element::create(0));
- answer->set("result", answer_content);
+ answer_content->add(Element::create(isc::cc::CC_REPLY_SUCCESS));
+ answer->set(isc::cc::CC_PAYLOAD_RESULT, answer_content);
return (answer);
}
@@ -70,22 +70,22 @@ createAnswer(const int rcode, ConstElementPtr arg) {
if (rcode != 0 && (!arg || arg->getType() != Element::string)) {
isc_throw(CCSessionError, "Bad or no argument for rcode != 0");
}
- ElementPtr answer = Element::fromJSON("{\"result\": [] }");
+ ElementPtr answer = Element::createMap();
ElementPtr answer_content = Element::createList();
answer_content->add(Element::create(rcode));
answer_content->add(arg);
- answer->set("result", answer_content);
+ answer->set(isc::cc::CC_PAYLOAD_RESULT, answer_content);
return (answer);
}
ConstElementPtr
createAnswer(const int rcode, const std::string& arg) {
- ElementPtr answer = Element::fromJSON("{\"result\": [] }");
+ ElementPtr answer = Element::createMap();
ElementPtr answer_content = Element::createList();
answer_content->add(Element::create(rcode));
answer_content->add(Element::create(arg));
- answer->set("result", answer_content);
+ answer->set(isc::cc::CC_PAYLOAD_RESULT, answer_content);
return (answer);
}
@@ -94,8 +94,8 @@ ConstElementPtr
parseAnswer(int &rcode, ConstElementPtr msg) {
if (msg &&
msg->getType() == Element::map &&
- msg->contains("result")) {
- ConstElementPtr result = msg->get("result");
+ msg->contains(isc::cc::CC_PAYLOAD_RESULT)) {
+ ConstElementPtr result = msg->get(isc::cc::CC_PAYLOAD_RESULT);
if (result->getType() != Element::list) {
isc_throw(CCSessionError, "Result element in answer message is not a list");
} else if (result->get(0)->getType() != Element::integer) {
@@ -133,7 +133,7 @@ createCommand(const std::string& command, ConstElementPtr arg) {
if (arg) {
cmd_parts->add(arg);
}
- cmd->set("command", cmd_parts);
+ cmd->set(isc::cc::CC_PAYLOAD_COMMAND, cmd_parts);
return (cmd);
}
@@ -141,8 +141,8 @@ std::string
parseCommand(ConstElementPtr& arg, ConstElementPtr command) {
if (command &&
command->getType() == Element::map &&
- command->contains("command")) {
- ConstElementPtr cmd = command->get("command");
+ command->contains(isc::cc::CC_PAYLOAD_COMMAND)) {
+ ConstElementPtr cmd = command->get(isc::cc::CC_PAYLOAD_COMMAND);
if (cmd->getType() == Element::list &&
cmd->size() > 0 &&
cmd->get(0)->getType() == Element::string) {
@@ -463,10 +463,13 @@ ModuleCCSession::ModuleCCSession(
isc_throw(CCSessionInitError, answer->str());
}
- setLocalConfig(Element::fromJSON("{}"));
+ setLocalConfig(Element::createMap());
// get any stored configuration from the manager
if (config_handler_) {
- ConstElementPtr cmd = Element::fromJSON("{ \"command\": [\"get_config\", {\"module_name\":\"" + module_name_ + "\"} ] }");
+ ConstElementPtr cmd =
+ createCommand("get_config",
+ Element::fromJSON("{\"module_name\":\"" +
+ module_name_ + "\"}"));
seq = session_.group_sendmsg(cmd, "ConfigManager");
session_.group_recvmsg(env, answer, false, seq);
ConstElementPtr new_config = parseAnswer(rcode, answer);
@@ -608,14 +611,16 @@ ModuleCCSession::checkCommand() {
/* ignore result messages (in case we're out of sync, to prevent
* pingpongs */
- if (data->getType() != Element::map || data->contains("result")) {
+ if (data->getType() != Element::map ||
+ data->contains(isc::cc::CC_PAYLOAD_RESULT)) {
return (0);
}
ConstElementPtr arg;
ConstElementPtr answer;
try {
std::string cmd_str = parseCommand(arg, data);
- std::string target_module = routing->get("group")->stringValue();
+ std::string target_module =
+ routing->get(isc::cc::CC_HEADER_GROUP)->stringValue();
if (cmd_str == "config_update") {
answer = checkConfigUpdateCommand(target_module, arg);
} else {
@@ -832,19 +837,19 @@ bool
ModuleCCSession::requestMatch(const AsyncRecvRequest& request,
const ConstElementPtr& envelope) const
{
- if (request.is_reply != envelope->contains("reply")) {
+ if (request.is_reply != envelope->contains(isc::cc::CC_HEADER_REPLY)) {
// Wrong type of message
return (false);
}
if (request.is_reply &&
(request.seq == -1 ||
- request.seq == envelope->get("reply")->intValue())) {
+ request.seq == envelope->get(isc::cc::CC_HEADER_REPLY)->intValue())) {
// This is the correct reply
return (true);
}
if (!request.is_reply &&
- (request.recipient.empty() ||
- request.recipient == envelope->get("group")->stringValue())) {
+ (request.recipient.empty() || request.recipient ==
+ envelope->get(isc::cc::CC_HEADER_GROUP)->stringValue())) {
// This is the correct command
return (true);
}
@@ -857,5 +862,27 @@ ModuleCCSession::cancelAsyncRecv(const AsyncRecvRequestID& id) {
async_recv_requests_.erase(id);
}
+ConstElementPtr
+ModuleCCSession::rpcCall(const std::string &command, const std::string &group,
+ const std::string &instance, const std::string &to,
+ const ConstElementPtr ¶ms)
+{
+ ConstElementPtr command_el(createCommand(command, params));
+ const int seq = groupSendMsg(command_el, group, instance, to, true);
+ ConstElementPtr env, answer;
+ LOG_DEBUG(config_logger, DBGLVL_TRACE_DETAIL, CONFIG_RPC_SEQ).arg(command).
+ arg(group).arg(seq);
+ groupRecvMsg(env, answer, true, seq);
+ int rcode;
+ const ConstElementPtr result(parseAnswer(rcode, answer));
+ if (rcode == isc::cc::CC_REPLY_NO_RECPT) {
+ isc_throw(RPCRecipientMissing, result);
+ } else if (rcode != isc::cc::CC_REPLY_SUCCESS) {
+ isc_throw_1(RPCError, result, rcode);
+ } else {
+ return (result);
+ }
+}
+
}
}
diff --git a/src/lib/config/ccsession.h b/src/lib/config/ccsession.h
index b4a44d0..bae25bc 100644
--- a/src/lib/config/ccsession.h
+++ b/src/lib/config/ccsession.h
@@ -20,6 +20,7 @@
#include <cc/session.h>
#include <cc/data.h>
+#include <cc/proto_defs.h>
#include <string>
#include <list>
@@ -146,6 +147,34 @@ public:
isc::Exception(file, line, what) {}
};
+/// \brief Exception thrown when there's a problem with the remote call.
+///
+/// This usually means either the command couldn't be called or the remote
+/// side sent an error as a response.
+class RPCError: public CCSessionError {
+public:
+ RPCError(const char* file, size_t line, const char* what, int rcode) :
+ CCSessionError(file, line, what),
+ rcode_(rcode)
+ {}
+
+ /// \brief The error code for the error.
+ int rcode() const {
+ return (rcode_);
+ }
+private:
+ const int rcode_;
+};
+
+/// \brief Specific version of RPCError for the case the recipient of command
+/// doesn't exist.
+class RPCRecipientMissing: public RPCError {
+public:
+ RPCRecipientMissing(const char* file, size_t line, const char* what) :
+ RPCError(file, line, what, isc::cc::CC_REPLY_NO_RECPT)
+ {}
+};
+
///
/// \brief This module keeps a connection to the command channel,
/// holds configuration information, and handles messages from
@@ -335,13 +364,15 @@ public:
* \param group see isc::cc::Session::group_sendmsg()
* \param instance see isc::cc::Session::group_sendmsg()
* \param to see isc::cc::Session::group_sendmsg()
+ * \param want_answer see isc::cc::Session::group_sendmsg()
* \return see isc::cc::Session::group_sendmsg()
*/
int groupSendMsg(isc::data::ConstElementPtr msg,
std::string group,
- std::string instance = "*",
- std::string to = "*") {
- return (session_.group_sendmsg(msg, group, instance, to));
+ std::string instance = isc::cc::CC_INSTANCE_WILDCARD,
+ std::string to = isc::cc::CC_TO_WILDCARD,
+ bool want_answer = false) {
+ return (session_.group_sendmsg(msg, group, instance, to, want_answer));
};
/**
@@ -361,6 +392,50 @@ public:
return (session_.group_recvmsg(envelope, msg, nonblock, seq));
};
+ /// \brief Send a command message and wait for the answer.
+ ///
+ /// This is mostly a convenience wrapper around groupSendMsg
+ /// and groupRecvMsg, with some error handling.
+ ///
+ /// \param command Name of the command to call.
+ /// \param group Name of the remote module to call the command on.
+ /// \param instance Instance part of recipient address.
+ /// \param to The lname to send it to. Can be used to override the
+ /// addressing and use a direct recipient.
+ /// \param params Parameters for the command. Can be left NULL if
+ /// no parameters are needed.
+ /// \return Return value of the successfull remote call. It can be
+ /// NULL if the remote command is void function (returns nothing).
+ /// \throw RPCError if the call fails (for example when the other
+ /// side responds with error code).
+ /// \throw RPCRecipientMissing if the recipient doesn't exist.
+ /// \throw CCSessionError if some lower-level error happens (eg.
+ /// the response was malformed).
+ isc::data::ConstElementPtr rpcCall(const std::string& command,
+ const std::string& group,
+ const std::string& instance =
+ isc::cc::CC_INSTANCE_WILDCARD,
+ const std::string& to =
+ isc::cc::CC_TO_WILDCARD,
+ const isc::data::ConstElementPtr&
+ params =
+ isc::data::ConstElementPtr());
+
+ /// \brief Convenience version of rpcCall
+ ///
+ /// This is exactly the same as the previous version of rpcCall, except
+ /// that the instance and to parameters are at their default. This
+ /// allows to sending a command with parameters to a named module
+ /// without long typing of the parameters.
+ isc::data::ConstElementPtr rpcCall(const std::string& command,
+ const std::string& group,
+ const isc::data::ConstElementPtr&
+ params)
+ {
+ return rpcCall(command, group, isc::cc::CC_INSTANCE_WILDCARD,
+ isc::cc::CC_TO_WILDCARD, params);
+ }
+
/// \brief Forward declaration of internal data structure.
///
/// This holds information about one asynchronous request to receive
diff --git a/src/lib/config/config_messages.mes b/src/lib/config/config_messages.mes
index 552256c..6735b16 100644
--- a/src/lib/config/config_messages.mes
+++ b/src/lib/config/config_messages.mes
@@ -94,3 +94,7 @@ manager.
% CONFIG_OPEN_FAIL error opening %1: %2
There was an error opening the given file. The reason for the failure
is included in the message.
+
+% CONFIG_RPC_SEQ RPC call %1 to %2 with seq %3
+Debug message, saying there's a RPC call of given command to given module. It
+has internal sequence number as listed in the message.
diff --git a/src/lib/config/documentation.txt b/src/lib/config/documentation.txt
index 67fe427..a934130 100644
--- a/src/lib/config/documentation.txt
+++ b/src/lib/config/documentation.txt
@@ -18,7 +18,7 @@ In order for this to work, it is important that all modules have a way of dynami
Overview
--------
-Central to the configuration part is the Configuraion Manager b10-cfgmgr. The configuration manager loads any existing configuration, receives configuration updates from user interfaces, and notifies modules about configuration updates.
+Central to the configuration part is the Configuration Manager b10-cfgmgr. The configuration manager loads any existing configuration, receives configuration updates from user interfaces, and notifies modules about configuration updates.
UI <---UIAPI---> Configuration Manager <---ModuleAPI---> Module
<---ModuleAPI---> Module
diff --git a/src/lib/config/tests/ccsession_unittests.cc b/src/lib/config/tests/ccsession_unittests.cc
index 2a5e758..c11cd24 100644
--- a/src/lib/config/tests/ccsession_unittests.cc
+++ b/src/lib/config/tests/ccsession_unittests.cc
@@ -53,11 +53,33 @@ protected:
// upon creation of a ModuleCCSession, the class
// sends its specification to the config manager.
- // it expects an ok answer back, so everytime we
+ // it expects an ok answer back, so every time we
// create a ModuleCCSession, we must set an initial
// ok answer.
session.getMessages()->add(createAnswer());
}
+ ConstElementPtr rpcCheck(const std::string& reply) {
+ ModuleCCSession mccs(ccspecfile("spec1.spec"), session, NULL, NULL,
+ false, false);
+ // Prepare the answer beforehand, it'll block until it gets one
+ const ConstElementPtr reply_el(el(reply));
+ session.getMessages()->add(reply_el);
+ const ConstElementPtr
+ result(mccs.rpcCall("test", "Spec2",
+ el("{\"param1\": \"Param 1\","
+ "\"param2\": \"Param 2\"}")));
+ const ConstElementPtr
+ request(el("[\"Spec2\", \"*\", {"
+ " \"command\": [\"test\", {"
+ " \"param1\": \"Param 1\","
+ " \"param2\": \"Param 2\""
+ "}]}, -1, true]"));
+ // The 0th one is from the initialization, to ConfigManager.
+ // our is the 1st.
+ EXPECT_TRUE(request->equals(*session.getMsgQueue()->get(1))) <<
+ session.getMsgQueue()->get(1)->toWire();
+ return (result);
+ }
~CCSessionTest() {
isc::log::setRootLoggerName(root_name);
}
@@ -65,6 +87,36 @@ protected:
const std::string root_name;
};
+// Test we can send an RPC (command) and get an answer. The answer is success
+// in this case.
+TEST_F(CCSessionTest, rpcCallSuccess) {
+ const ConstElementPtr result =
+ rpcCheck("{\"result\": [0, {\"Hello\": \"a\"}]}");
+ EXPECT_TRUE(el("{\"Hello\": \"a\"}")->equals(*result));
+}
+
+// Test success of RPC, but the answer is empty (eg. a void function on the
+// remote side).
+TEST_F(CCSessionTest, rpcCallSuccessNone) {
+ EXPECT_FALSE(rpcCheck("{\"result\": [0]}"));
+}
+
+// Test it successfully raises CCSessionError if the answer is malformed.
+TEST_F(CCSessionTest, rpcCallMalformedAnswer) {
+ EXPECT_THROW(rpcCheck("[\"Nonsense\"]"), CCSessionError);
+}
+
+// Test it raises exception when the remote side reports an error
+TEST_F(CCSessionTest, rpcCallError) {
+ EXPECT_THROW(rpcCheck("{\"result\": [1, \"Error\"]}"), RPCError);
+}
+
+// Test it raises exception when the remote side doesn't exist
+TEST_F(CCSessionTest, rpcNoRecpt) {
+ EXPECT_THROW(rpcCheck("{\"result\": [-1, \"Error\"]}"),
+ RPCRecipientMissing);
+}
+
TEST_F(CCSessionTest, createAnswer) {
ConstElementPtr answer;
answer = createAnswer();
diff --git a/src/lib/config/tests/fake_session.cc b/src/lib/config/tests/fake_session.cc
index 56a30d4..e6d569e 100644
--- a/src/lib/config/tests/fake_session.cc
+++ b/src/lib/config/tests/fake_session.cc
@@ -97,7 +97,7 @@ bool
FakeSession::recvmsg(ConstElementPtr& msg, bool nonblock, int) {
if (started_ && !nonblock) {
// This would schedule another read for length, leading to
- // corputed data
+ // corrupted data
isc_throw(DoubleRead, "Second read scheduled from recvmsg");
}
@@ -119,7 +119,7 @@ FakeSession::recvmsg(ConstElementPtr& env, ConstElementPtr& msg, bool nonblock,
{
if (started_ && !nonblock) {
// This would schedule another read for length, leading to
- // corputed data
+ // corrupted data
isc_throw(DoubleRead, "Second read scheduled from recvmsg");
}
@@ -183,12 +183,12 @@ FakeSession::unsubscribe(std::string group, std::string instance) {
int
FakeSession::group_sendmsg(ConstElementPtr msg, std::string group,
- std::string to, std::string, bool)
+ std::string to, std::string, bool want_answer)
{
if (throw_on_send_) {
isc_throw(Exception, "Throw on send is set in FakeSession");
}
- addMessage(msg, group, to);
+ addMessage(msg, group, to, -1, want_answer);
return (1);
}
@@ -231,13 +231,16 @@ FakeSession::getFirstMessage(std::string& group, std::string& to) const {
void
FakeSession::addMessage(ConstElementPtr msg, const std::string& group,
- const std::string& to, int seq)
+ const std::string& to, int seq, bool want_answer)
{
ElementPtr m_el = Element::createList();
m_el->add(Element::create(group));
m_el->add(Element::create(to));
m_el->add(msg);
m_el->add(Element::create(seq));
+ if (want_answer) {
+ m_el->add(Element::create(want_answer));
+ }
if (!msg_queue_) {
msg_queue_ = Element::createList();
}
diff --git a/src/lib/config/tests/fake_session.h b/src/lib/config/tests/fake_session.h
index 0dbaadb..8a564a8 100644
--- a/src/lib/config/tests/fake_session.h
+++ b/src/lib/config/tests/fake_session.h
@@ -75,7 +75,8 @@ public:
isc::data::ConstElementPtr getFirstMessage(std::string& group,
std::string& to) const;
void addMessage(isc::data::ConstElementPtr, const std::string& group,
- const std::string& to, int seq = -1);
+ const std::string& to, int seq = -1,
+ bool want_answer = false);
bool haveSubscription(const std::string& group,
const std::string& instance);
bool haveSubscription(const isc::data::ConstElementPtr group,
diff --git a/src/lib/datasrc/Makefile.am b/src/lib/datasrc/Makefile.am
index be79557..abc1e7d 100644
--- a/src/lib/datasrc/Makefile.am
+++ b/src/lib/datasrc/Makefile.am
@@ -19,6 +19,7 @@ static.zone: static.zone.pre $(top_builddir)/config.h $(top_srcdir)/AUTHORS
$(SED) -e 's/\(.*\)/AUTHORS.BIND. 0 CH TXT "\1"/' $(top_srcdir)/AUTHORS >>$@
CLEANFILES = *.gcno *.gcda datasrc_messages.h datasrc_messages.cc
+CLEANFILES += sqlite3_datasrc_messages.h sqlite3_datasrc_messages.cc
CLEANFILES += datasrc_config.h
CLEANFILES += static.zone
@@ -45,6 +46,7 @@ pkglib_LTLIBRARIES = sqlite3_ds.la static_ds.la
sqlite3_ds_la_SOURCES = sqlite3_accessor.h sqlite3_accessor.cc
sqlite3_ds_la_SOURCES += sqlite3_accessor_link.cc
+nodist_sqlite3_ds_la_SOURCES = sqlite3_datasrc_messages.h sqlite3_datasrc_messages.cc
sqlite3_ds_la_LDFLAGS = -module -avoid-version
sqlite3_ds_la_LDFLAGS += -no-undefined -version-info 1:0:0
sqlite3_ds_la_LIBADD = $(top_builddir)/src/lib/exceptions/libb10-exceptions.la
@@ -65,10 +67,13 @@ libb10_datasrc_la_LIBADD += $(top_builddir)/src/lib/datasrc/memory/libdatasrc_me
libb10_datasrc_la_LIBADD += $(SQLITE_LIBS)
BUILT_SOURCES = datasrc_config.h datasrc_messages.h datasrc_messages.cc
+BUILT_SOURCES += sqlite3_datasrc_messages.h sqlite3_datasrc_messages.cc
datasrc_messages.h datasrc_messages.cc: Makefile datasrc_messages.mes
$(top_builddir)/src/lib/log/compiler/message $(top_srcdir)/src/lib/datasrc/datasrc_messages.mes
+sqlite3_datasrc_messages.h sqlite3_datasrc_messages.cc: Makefile sqlite3_datasrc_messages.mes
+ $(top_builddir)/src/lib/log/compiler/message $(top_srcdir)/src/lib/datasrc/sqlite3_datasrc_messages.mes
-EXTRA_DIST = datasrc_messages.mes static.zone.pre
+EXTRA_DIST = datasrc_messages.mes sqlite3_datasrc_messages.mes static.zone.pre
zonedir = $(pkgdatadir)
zone_DATA = static.zone
diff --git a/src/lib/datasrc/client_list.cc b/src/lib/datasrc/client_list.cc
index 0750fb6..eb60a96 100644
--- a/src/lib/datasrc/client_list.cc
+++ b/src/lib/datasrc/client_list.cc
@@ -27,6 +27,7 @@
#include <util/memory_segment_local.h>
#include <memory>
+#include <set>
#include <boost/foreach.hpp>
#include <boost/bind.hpp>
@@ -47,9 +48,11 @@ namespace datasrc {
ConfigurableClientList::DataSourceInfo::DataSourceInfo(
DataSourceClient* data_src_client,
const DataSourceClientContainerPtr& container, bool has_cache,
- const RRClass& rrclass, const shared_ptr<ZoneTableSegment>& segment) :
+ const RRClass& rrclass, const shared_ptr<ZoneTableSegment>& segment,
+ const string& name) :
data_src_client_(data_src_client),
- container_(container)
+ container_(container),
+ name_(name)
{
if (has_cache) {
cache_.reset(new InMemoryClient(segment, rrclass));
@@ -59,8 +62,9 @@ ConfigurableClientList::DataSourceInfo::DataSourceInfo(
ConfigurableClientList::DataSourceInfo::DataSourceInfo(
const RRClass& rrclass, const shared_ptr<ZoneTableSegment>& segment,
- bool has_cache) :
- data_src_client_(NULL)
+ bool has_cache, const string& name) :
+ data_src_client_(NULL),
+ name_(name)
{
if (has_cache) {
cache_.reset(new InMemoryClient(segment, rrclass));
@@ -92,6 +96,7 @@ ConfigurableClientList::configure(const ConstElementPtr& config,
vector<DataSourceInfo> new_data_sources;
shared_ptr<ZoneTableSegment> ztable_segment(
ZoneTableSegment::create(*config, rrclass_));
+ set<string> used_names;
for (; i < config->size(); ++i) {
// Extract the parameters
const ConstElementPtr dconf(config->get(i));
@@ -108,6 +113,13 @@ ConfigurableClientList::configure(const ConstElementPtr& config,
const bool want_cache(allow_cache &&
dconf->contains("cache-enable") &&
dconf->get("cache-enable")->boolValue());
+ // Get the name (either explicit, or guess)
+ const ConstElementPtr name_elem(dconf->get("name"));
+ const string name(name_elem ? name_elem->stringValue() : type);
+ if (!used_names.insert(name).second) {
+ isc_throw(ConfigurationError, "Duplicit name in client list: "
+ << name);
+ }
if (type == "MasterFiles") {
// In case the cache is not allowed, we just skip the master
@@ -130,7 +142,7 @@ ConfigurableClientList::configure(const ConstElementPtr& config,
}
new_data_sources.push_back(DataSourceInfo(rrclass_,
ztable_segment,
- true));
+ true, name));
} else {
// Ask the factory to create the data source for us
const DataSourcePair ds(this->getDataSourceClient(type,
@@ -138,7 +150,8 @@ ConfigurableClientList::configure(const ConstElementPtr& config,
// And put it into the vector
new_data_sources.push_back(DataSourceInfo(ds.first, ds.second,
want_cache, rrclass_,
- ztable_segment));
+ ztable_segment,
+ name));
}
if (want_cache) {
@@ -462,5 +475,18 @@ ConfigurableClientList::getDataSourceClient(const string& type,
return (DataSourcePair(&container->getInstance(), container));
}
+vector<DataSourceStatus>
+ConfigurableClientList::getStatus() const {
+ vector<DataSourceStatus> result;
+ BOOST_FOREACH(const DataSourceInfo& info, data_sources_) {
+ // TODO: Once we support mapped cache, decide when we need the
+ // SEGMENT_WAITING.
+ result.push_back(DataSourceStatus(info.name_, info.cache_ ?
+ SEGMENT_INUSE : SEGMENT_UNUSED,
+ "local"));
+ }
+ return (result);
+}
+
}
}
diff --git a/src/lib/datasrc/client_list.h b/src/lib/datasrc/client_list.h
index d1a35b5..256ad36 100644
--- a/src/lib/datasrc/client_list.h
+++ b/src/lib/datasrc/client_list.h
@@ -46,6 +46,76 @@ class InMemoryClient;
class ZoneWriter;
}
+/// \brief Segment status of the cache
+///
+/// Describes the status in which the memory segment for the in-memory cache of
+// /given data source is.
+enum MemorySegmentState {
+ /// \brief No segment used for this data source.
+ ///
+ /// This is usually a result of the cache being disabled.
+ SEGMENT_UNUSED,
+
+ /// \brief It is a mapped segment and we wait for information how to map
+ /// it.
+ SEGMENT_WAITING,
+
+ /// \brief The segment is ready to be used.
+ SEGMENT_INUSE
+};
+
+/// \brief Status of one data source.
+///
+/// This indicates the status a data soure is in. It is used with segment
+/// and cache management, to discover the data sources that need external
+/// mapping or local loading.
+///
+/// In future, it may be extended for other purposes, such as performing an
+/// operation on named data source.
+class DataSourceStatus {
+public:
+ /// \brief Constructor
+ ///
+ /// Sets initial values. It doesn't matter what is provided for the type
+ /// if state is SEGMENT_UNUSED, the value is effectively ignored.
+ DataSourceStatus(const std::string& name, MemorySegmentState state,
+ const std::string& type) :
+ name_(name),
+ type_(type),
+ state_(state)
+ {}
+
+ /// \brief Get the segment state
+ MemorySegmentState getSegmentState() const {
+ return (state_);
+ }
+
+ /// \brief Get the segment type
+ ///
+ /// \note Specific values of the type are only meaningful for the
+ /// corresponding memory segment implementation and modules that
+ /// directly manage the segments. Other normal applications should
+ /// treat them as opaque identifiers.
+ ///
+ /// \throw isc::InvalidOperation if called and state is SEGMENT_UNUSED.
+ const std::string& getSegmentType() const {
+ if (getSegmentState() == SEGMENT_UNUSED) {
+ isc_throw(isc::InvalidOperation,
+ "No segment used, no type therefore.");
+ }
+ return (type_);
+ }
+
+ /// \brief Get the name.
+ const std::string& getName() const {
+ return (name_);
+ }
+private:
+ std::string name_;
+ std::string type_;
+ MemorySegmentState state_;
+};
+
/// \brief The list of data source clients.
///
/// The purpose of this class is to hold several data source clients and search
@@ -332,13 +402,14 @@ public:
const boost::shared_ptr
<isc::datasrc::memory::ZoneTableSegment>&
ztable_segment,
- bool has_cache = false);
+ bool has_cache = false,
+ const std::string& name = std::string());
DataSourceInfo(DataSourceClient* data_src_client,
const DataSourceClientContainerPtr& container,
bool has_cache, const dns::RRClass& rrclass,
const boost::shared_ptr
<isc::datasrc::memory::ZoneTableSegment>&
- ztable_segment);
+ ztable_segment, const std::string& name);
DataSourceClient* data_src_client_;
DataSourceClientContainerPtr container_;
@@ -350,6 +421,7 @@ public:
const DataSourceClient* getCacheClient() const;
boost::shared_ptr<memory::InMemoryClient> cache_;
boost::shared_ptr<memory::ZoneTableSegment> ztable_segment_;
+ std::string name_;
};
/// \brief The collection of data sources.
@@ -379,6 +451,15 @@ public:
virtual DataSourcePair getDataSourceClient(const std::string& type,
const data::ConstElementPtr&
configuration);
+
+ /// \brief Get status information of all internal data sources.
+ ///
+ /// Get a DataSourceStatus for current state of each data source client
+ /// in this list.
+ ///
+ /// This may throw standard exceptions, such as std::bad_alloc. Otherwise,
+ /// it is exception free.
+ std::vector<DataSourceStatus> getStatus() const;
public:
/// \brief Access to the data source clients.
///
diff --git a/src/lib/datasrc/database.h b/src/lib/datasrc/database.h
index 3302adf..19c28eb 100644
--- a/src/lib/datasrc/database.h
+++ b/src/lib/datasrc/database.h
@@ -228,7 +228,7 @@ public:
public:
/// \brief Destructor
///
- /// Virtual destructor, so any descendand class is destroyed correctly.
+ /// Virtual destructor, so any descendant class is destroyed correctly.
virtual ~IteratorContext() {}
/// \brief Function to provide next resource record
diff --git a/src/lib/datasrc/datasrc_messages.mes b/src/lib/datasrc/datasrc_messages.mes
index 2235df8..9f57904 100644
--- a/src/lib/datasrc/datasrc_messages.mes
+++ b/src/lib/datasrc/datasrc_messages.mes
@@ -550,131 +550,6 @@ given domain or record. The code is 1 for error and 2 for not implemented.
While processing a wildcard, a referral was met. But it wasn't possible to get
enough information for it. The code is 1 for error, 2 for not implemented.
-% DATASRC_SQLITE_CLOSE closing SQLite database
-Debug information. The SQLite data source is closing the database file.
-
-% DATASRC_SQLITE_COMPATIBLE_VERSION database schema V%1.%2 not up to date (expecting V%3.%4) but is compatible
-The version of the SQLite3 database schema used to hold the zone data
-is not the latest one - the current version of BIND 10 was written
-with a later schema version in mind. However, the database is
-compatible with the current version of BIND 10, and BIND 10 will run
-without any problems.
-
-Consult the release notes for your version of BIND 10. Depending on
-the changes made to the database schema, it is possible that improved
-performance could result if the database were upgraded.
-
-% DATASRC_SQLITE_CONNCLOSE Closing sqlite database
-The database file is no longer needed and is being closed.
-
-% DATASRC_SQLITE_CONNOPEN Opening sqlite database file '%1'
-The database file is being opened so it can start providing data.
-
-% DATASRC_SQLITE_CREATE SQLite data source created
-Debug information. An instance of SQLite data source is being created.
-
-% DATASRC_SQLITE_DESTROY SQLite data source destroyed
-Debug information. An instance of SQLite data source is being destroyed.
-
-% DATASRC_SQLITE_DROPCONN SQLite3Database is being deinitialized
-The object around a database connection is being destroyed.
-
-% DATASRC_SQLITE_ENCLOSURE looking for zone containing '%1'
-Debug information. The SQLite data source is trying to identify which zone
-should hold this domain.
-
-% DATASRC_SQLITE_ENCLOSURE_NOT_FOUND no zone contains '%1'
-Debug information. The last SQLITE_ENCLOSURE query was unsuccessful; there's
-no such zone in our data.
-
-% DATASRC_SQLITE_FIND looking for RRset '%1/%2'
-Debug information. The SQLite data source is looking up a resource record
-set.
-
-% DATASRC_SQLITE_FINDADDRS looking for A/AAAA addresses for '%1'
-Debug information. The data source is looking up the addresses for given
-domain name.
-
-% DATASRC_SQLITE_FINDADDRS_BAD_CLASS class mismatch looking for addresses ('%1' and '%2')
-The SQLite data source was looking up A/AAAA addresses, but the data source
-contains different class than the query was for.
-
-% DATASRC_SQLITE_FINDEXACT looking for exact RRset '%1/%2'
-Debug information. The SQLite data source is looking up an exact resource
-record.
-
-% DATASRC_SQLITE_FINDEXACT_BAD_CLASS class mismatch looking for an RRset ('%1' and '%2')
-The SQLite data source was looking up an exact RRset, but the data source
-contains different class than the query was for.
-
-% DATASRC_SQLITE_FINDREC looking for record '%1/%2'
-Debug information. The SQLite data source is looking up records of given name
-and type in the database.
-
-% DATASRC_SQLITE_FINDREF looking for referral at '%1'
-Debug information. The SQLite data source is identifying if this domain is
-a referral and where it goes.
-
-% DATASRC_SQLITE_FINDREF_BAD_CLASS class mismatch looking for referral ('%1' and '%2')
-The SQLite data source was trying to identify if there's a referral. But
-it contains different class than the query was for.
-
-% DATASRC_SQLITE_FIND_BAD_CLASS class mismatch looking for an RRset ('%1' and '%2')
-The SQLite data source was looking up an RRset, but the data source contains
-different class than the query was for.
-
-% DATASRC_SQLITE_FIND_NSEC3 looking for NSEC3 in zone '%1' for hash '%2'
-Debug information. We're trying to look up a NSEC3 record in the SQLite data
-source.
-
-% DATASRC_SQLITE_FIND_NSEC3_NO_ZONE no such zone '%1'
-The SQLite data source was asked to provide a NSEC3 record for given zone.
-But it doesn't contain that zone.
-
-% DATASRC_SQLITE_INCOMPATIBLE_VERSION database schema V%1.%2 incompatible with version (V%3.%4) expected
-The version of the SQLite3 database schema used to hold the zone data
-is incompatible with the version expected by BIND 10. As a result,
-BIND 10 is unable to run using the database file as the data source.
-
-The database should be updated using the means described in the BIND
-10 documentation.
-
-% DATASRC_SQLITE_NEWCONN SQLite3Database is being initialized
-A wrapper object to hold database connection is being initialized.
-
-% DATASRC_SQLITE_OPEN opening SQLite database '%1'
-Debug information. The SQLite data source is loading an SQLite database in
-the provided file.
-
-% DATASRC_SQLITE_PREVIOUS looking for name previous to '%1'
-This is a debug message. The name given was not found, so the program
-is searching for the next name higher up the hierarchy (e.g. if
-www.example.com were queried for and not found, the software searches
-for the "previous" name, example.com).
-
-% DATASRC_SQLITE_PREVIOUS_NO_ZONE no zone containing '%1'
-The name given was not found, so the program is searching for the next
-name higher up the hierarchy (e.g. if www.example.com were queried
-for and not found, the software searches for the "previous" name,
-example.com). However, this name is not contained in any zone in the
-data source. This is an error since it indicates a problem in the earlier
-processing of the query.
-
-% DATASRC_SQLITE_SETUP setting up new SQLite3 database in '%1'
-The database for SQLite data source was found empty. It is assumed this is the
-first run and it is being initialized with current schema. It'll still contain
-no data, but it will be ready for use. If this is indeed the first run of
-BIND 10, it is to be expected and completely harmless. If you just configured
-a data source to point to an existing file and you see this, you may have
-misspelled the file name.
-
-% DATASRC_SQLITE_SETUP_OLD_API setting up new SQLite database
-The database for SQLite data source was found empty. It is assumed this is the
-first run and it is being initialized with current schema. It'll still contain
-no data, but it will be ready for use. This is similar to DATASRC_SQLITE_SETUP
-message, but it is logged from the old API. You should never see it, since the
-API is deprecated.
-
% DATASRC_STATIC_CLASS_NOT_CH static data source can handle CH class only
An error message indicating that a query requesting a RR for a class other
that CH was sent to the static data source (which only handles CH queries).
diff --git a/src/lib/datasrc/master_loader_callbacks.h b/src/lib/datasrc/master_loader_callbacks.h
index ae827c9..e1d3a92 100644
--- a/src/lib/datasrc/master_loader_callbacks.h
+++ b/src/lib/datasrc/master_loader_callbacks.h
@@ -47,7 +47,7 @@ createMasterLoaderCallbacks(const isc::dns::Name& name,
/// loaded RRsets into a zone updater.
///
/// The zone updater should be opened in the replace mode no changes should
-/// have been done to it yet (but it is not checked). It is not commited
+/// have been done to it yet (but it is not checked). It is not committed
/// automatically and it is up to the caller to commit the changes (or not).
/// It must not be destroyed for the whole time of loading.
///
diff --git a/src/lib/datasrc/memory/domaintree.h b/src/lib/datasrc/memory/domaintree.h
index 4816452..6e8b062 100644
--- a/src/lib/datasrc/memory/domaintree.h
+++ b/src/lib/datasrc/memory/domaintree.h
@@ -42,7 +42,7 @@ namespace isc {
namespace datasrc {
namespace memory {
-/// Forward declare DomainTree class here is convinent for following
+/// Forward declare DomainTree class here is convenient for following
/// friend class declare inside DomainTreeNode and DomainTreeNodeChain
template <typename T>
class DomainTree;
diff --git a/src/lib/datasrc/memory/rdata_serialization.h b/src/lib/datasrc/memory/rdata_serialization.h
index e46786c..a6146a5 100644
--- a/src/lib/datasrc/memory/rdata_serialization.h
+++ b/src/lib/datasrc/memory/rdata_serialization.h
@@ -533,7 +533,7 @@ public:
}
}
- /// \brief Rewind the iterator to the beginnig of data.
+ /// \brief Rewind the iterator to the beginning of data.
///
/// The following next() and nextSig() will start iterating from the
/// beginning again.
diff --git a/src/lib/datasrc/memory/rdataset.h b/src/lib/datasrc/memory/rdataset.h
index 250af93..58201b1 100644
--- a/src/lib/datasrc/memory/rdataset.h
+++ b/src/lib/datasrc/memory/rdataset.h
@@ -121,12 +121,15 @@ public:
/// returns a pointer to it.
///
/// If the optional \c old_rdataset parameter is set to non NULL,
- /// The given \c RdataSet, RRset, RRSIG will be merged in the new
- /// \c Rdataset object: the new object contain the union set of all
+ /// the given \c RdataSet, RRset, RRSIG will be merged in the new
+ /// \c Rdataset object: the new object will contain the union set of all
/// RDATA and RRSIGs contained in these. Obviously \c old_rdataset
- /// was previously generated for the same RRClass and RRType as those
+ /// must be previously generated for the same RRClass and RRType as those
/// for the given RRsets; it's the caller's responsibility to ensure
/// this condition. If it's not met the result will be undefined.
+ /// No reference to \c old_rdataset is maintained in the newly
+ /// returned \c RdataSet, so if the caller does not need \c
+ /// old_rdataset anymore, it may be freed by the caller.
///
/// In both cases, this method ensures the stored RDATA and RRSIG are
/// unique. Any duplicate data (in the sense of the comparison in the
diff --git a/src/lib/datasrc/memory/zone_data_loader.cc b/src/lib/datasrc/memory/zone_data_loader.cc
index e3c9c3f..de3a749 100644
--- a/src/lib/datasrc/memory/zone_data_loader.cc
+++ b/src/lib/datasrc/memory/zone_data_loader.cc
@@ -50,14 +50,15 @@ typedef boost::function<void(isc::dns::ConstRRsetPtr)> LoadCallback;
// A helper internal class for \c loadZoneData(). make it non-copyable
// to avoid accidental copy.
//
-// The current internal implementation expects that both a normal
-// (non RRSIG) RRset and (when signed) its RRSIG are added at once.
-// Also in the current implementation, the input sequence of RRsets
-// are grouped with their owner name (so once a new owner name is encountered,
-// no subsequent RRset has the previous owner name), but the ordering
-// in the same group is not fixed. So we hold all RRsets of the same
-// owner name in node_rrsets_ and node_rrsigsets_, and add the matching
-// pairs of RRsets to the zone when we see a new owner name.
+// The current internal implementation no longer expects that both a
+// normal (non RRSIG) RRset and (when signed) its RRSIG are added at
+// once, but we do that here anyway to avoid merging RdataSets every
+// single time which can be inefficient.
+//
+// We hold all RRsets of the same owner name in node_rrsets_ and
+// node_rrsigsets_, and add the matching pairs of RRsets to the zone
+// when we see a new owner name. We do this to limit the size of
+// NodeRRsets below. However, RRsets can occur in any order.
//
// The caller is responsible for adding the RRsets of the last group
// in the input sequence by explicitly calling flushNodeRRsets() at the
@@ -86,6 +87,7 @@ private:
private:
NodeRRsets node_rrsets_;
NodeRRsets node_rrsigsets_;
+ std::vector<isc::dns::ConstRRsetPtr> non_consecutive_rrsets_;
ZoneDataUpdater updater_;
};
@@ -93,22 +95,20 @@ void
ZoneDataLoader::addFromLoad(const ConstRRsetPtr& rrset) {
// If we see a new name, flush the temporary holders, adding the
// pairs of RRsets and RRSIGs of the previous name to the zone.
- if ((!node_rrsets_.empty() || !node_rrsigsets_.empty()) &&
+ if ((!node_rrsets_.empty() || !node_rrsigsets_.empty() ||
+ !non_consecutive_rrsets_.empty()) &&
(getCurrentName() != rrset->getName())) {
flushNodeRRsets();
}
- // Store this RRset until it can be added to the zone. The current
- // implementation requires RRs of the same RRset should be added at
- // once, so we check the "duplicate" here.
+ // Store this RRset until it can be added to the zone. If an rrtype
+ // that's already been seen is found, queue it in a different vector
+ // to be merged later.
const bool is_rrsig = rrset->getType() == RRType::RRSIG();
NodeRRsets& node_rrsets = is_rrsig ? node_rrsigsets_ : node_rrsets_;
const RRType& rrtype = is_rrsig ? getCoveredType(rrset) : rrset->getType();
if (!node_rrsets.insert(NodeRRsetsVal(rrtype, rrset)).second) {
- isc_throw(ZoneDataUpdater::AddError,
- "Duplicate add of the same type of"
- << (is_rrsig ? " RRSIG" : "") << " RRset: "
- << rrset->getName() << "/" << rrtype);
+ non_consecutive_rrsets_.insert(non_consecutive_rrsets_.begin(), rrset);
}
if (rrset->getRRsig()) {
@@ -137,8 +137,18 @@ ZoneDataLoader::flushNodeRRsets() {
updater_.add(ConstRRsetPtr(), val.second);
}
+ // Add any non-consecutive rrsets too.
+ BOOST_FOREACH(ConstRRsetPtr rrset, non_consecutive_rrsets_) {
+ if (rrset->getType() == RRType::RRSIG()) {
+ updater_.add(ConstRRsetPtr(), rrset);
+ } else {
+ updater_.add(rrset, ConstRRsetPtr());
+ }
+ }
+
node_rrsets_.clear();
node_rrsigsets_.clear();
+ non_consecutive_rrsets_.clear();
}
const Name&
diff --git a/src/lib/datasrc/memory/zone_data_updater.cc b/src/lib/datasrc/memory/zone_data_updater.cc
index 5bde6d4..4d7e7e0 100644
--- a/src/lib/datasrc/memory/zone_data_updater.cc
+++ b/src/lib/datasrc/memory/zone_data_updater.cc
@@ -270,8 +270,12 @@ ZoneDataUpdater::addNSEC3(const Name& name, const ConstRRsetPtr rrset,
ZoneNode* node;
nsec3_data->insertName(mem_sgmt_, name, &node);
- RdataSet* rdataset = RdataSet::create(mem_sgmt_, encoder_, rrset, rrsig);
- RdataSet* old_rdataset = node->setData(rdataset);
+ // Create a new RdataSet, merging any existing NSEC3 data for this
+ // name.
+ RdataSet* old_rdataset = node->getData();
+ RdataSet* rdataset = RdataSet::create(mem_sgmt_, encoder_, rrset, rrsig,
+ old_rdataset);
+ old_rdataset = node->setData(rdataset);
if (old_rdataset != NULL) {
RdataSet::destroy(mem_sgmt_, old_rdataset, rrclass_);
}
@@ -298,16 +302,34 @@ ZoneDataUpdater::addRdataSet(const Name& name, const RRType& rrtype,
contextCheck(*rrset, rdataset_head);
}
- if (RdataSet::find(rdataset_head, rrtype, true) != NULL) {
- isc_throw(AddError,
- "RRset of the type already exists: "
- << name << " (type: " << rrtype << ")");
- }
-
+ // Create a new RdataSet, merging any existing data for this
+ // type.
+ RdataSet* old_rdataset = RdataSet::find(rdataset_head, rrtype, true);
RdataSet* rdataset_new = RdataSet::create(mem_sgmt_, encoder_,
- rrset, rrsig);
- rdataset_new->next = rdataset_head;
- node->setData(rdataset_new);
+ rrset, rrsig, old_rdataset);
+ if (old_rdataset == NULL) {
+ // There is no existing RdataSet. Prepend the new RdataSet
+ // to the list.
+ rdataset_new->next = rdataset_head;
+ node->setData(rdataset_new);
+ } else {
+ // Replace the old RdataSet in the list with the newly
+ // created one, and destroy the old one.
+ for (RdataSet* cur = rdataset_head, *prev = NULL;
+ cur != NULL;
+ prev = cur, cur = cur->getNext()) {
+ if (cur == old_rdataset) {
+ rdataset_new->next = cur->getNext();
+ if (prev == NULL) {
+ node->setData(rdataset_new);
+ } else {
+ prev->next = rdataset_new;
+ }
+ break;
+ }
+ }
+ RdataSet::destroy(mem_sgmt_, old_rdataset, rrclass_);
+ }
// Ok, we just put it in.
diff --git a/src/lib/datasrc/memory/zone_finder.cc b/src/lib/datasrc/memory/zone_finder.cc
index 5acc5be..4f9183e 100644
--- a/src/lib/datasrc/memory/zone_finder.cc
+++ b/src/lib/datasrc/memory/zone_finder.cc
@@ -144,7 +144,7 @@ struct FindState {
// These will be set to a domain node of the highest delegation point,
// if any. In fact, we could use a single variable instead of both.
- // But then we would need to distinquish these two cases by something
+ // But then we would need to distinguish these two cases by something
// else and it seemed little more confusing when this was written.
const ZoneNode* zonecut_node_;
const ZoneNode* dname_node_;
diff --git a/src/lib/datasrc/sqlite3_accessor.cc b/src/lib/datasrc/sqlite3_accessor.cc
index a858028..11a5eb5 100644
--- a/src/lib/datasrc/sqlite3_accessor.cc
+++ b/src/lib/datasrc/sqlite3_accessor.cc
@@ -23,6 +23,7 @@
#include <dns/name.h>
#include <datasrc/sqlite3_accessor.h>
+#include <datasrc/sqlite3_datasrc_messages.h>
#include <datasrc/logger.h>
#include <datasrc/data_source.h>
#include <datasrc/factory.h>
@@ -1068,7 +1069,7 @@ private:
/// \param serial Zone serial number for which an index is being sought.
/// \param diff Code to delete record additions or deletions
///
- /// \return int ID of the row in the difss table corresponding to the
+ /// \return int ID of the row in the diffs table corresponding to the
/// statement.
///
/// \exception TooLittleData Internal error, no result returned when one
diff --git a/src/lib/datasrc/sqlite3_accessor_link.cc b/src/lib/datasrc/sqlite3_accessor_link.cc
index 56e0c2f..6f38de4 100644
--- a/src/lib/datasrc/sqlite3_accessor_link.cc
+++ b/src/lib/datasrc/sqlite3_accessor_link.cc
@@ -19,6 +19,8 @@
#include <datasrc/sqlite3_accessor.h>
#include <datasrc/database.h>
+#include <log/message_initializer.h>
+
#include <string>
using namespace std;
@@ -77,6 +79,9 @@ checkConfig(ConstElementPtr config, ElementPtr errors) {
DataSourceClient *
createInstance(isc::data::ConstElementPtr config, std::string& error) {
+ // Initialize the logging dictionary
+ isc::log::MessageInitializer::loadDictionary(true);
+
ElementPtr errors(Element::createList());
if (!checkConfig(config, errors)) {
error = "Configuration error: " + errors->str();
diff --git a/src/lib/datasrc/sqlite3_datasrc_messages.mes b/src/lib/datasrc/sqlite3_datasrc_messages.mes
new file mode 100644
index 0000000..a462d43
--- /dev/null
+++ b/src/lib/datasrc/sqlite3_datasrc_messages.mes
@@ -0,0 +1,142 @@
+# Copyright (C) 2013 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.
+
+$NAMESPACE isc::datasrc
+
+# \brief Messages for the SQLITE3 data source backend
+
+% DATASRC_SQLITE_CLOSE closing SQLite database
+Debug information. The SQLite data source is closing the database file.
+
+% DATASRC_SQLITE_COMPATIBLE_VERSION database schema V%1.%2 not up to date (expecting V%3.%4) but is compatible
+The version of the SQLite3 database schema used to hold the zone data
+is not the latest one - the current version of BIND 10 was written
+with a later schema version in mind. However, the database is
+compatible with the current version of BIND 10, and BIND 10 will run
+without any problems.
+
+Consult the release notes for your version of BIND 10. Depending on
+the changes made to the database schema, it is possible that improved
+performance could result if the database were upgraded.
+
+% DATASRC_SQLITE_CONNCLOSE Closing sqlite database
+The database file is no longer needed and is being closed.
+
+% DATASRC_SQLITE_CONNOPEN Opening sqlite database file '%1'
+The database file is being opened so it can start providing data.
+
+% DATASRC_SQLITE_CREATE SQLite data source created
+Debug information. An instance of SQLite data source is being created.
+
+% DATASRC_SQLITE_DESTROY SQLite data source destroyed
+Debug information. An instance of SQLite data source is being destroyed.
+
+% DATASRC_SQLITE_DROPCONN SQLite3Database is being deinitialized
+The object around a database connection is being destroyed.
+
+% DATASRC_SQLITE_ENCLOSURE looking for zone containing '%1'
+Debug information. The SQLite data source is trying to identify which zone
+should hold this domain.
+
+% DATASRC_SQLITE_ENCLOSURE_NOT_FOUND no zone contains '%1'
+Debug information. The last SQLITE_ENCLOSURE query was unsuccessful; there's
+no such zone in our data.
+
+% DATASRC_SQLITE_FIND looking for RRset '%1/%2'
+Debug information. The SQLite data source is looking up a resource record
+set.
+
+% DATASRC_SQLITE_FINDADDRS looking for A/AAAA addresses for '%1'
+Debug information. The data source is looking up the addresses for given
+domain name.
+
+% DATASRC_SQLITE_FINDADDRS_BAD_CLASS class mismatch looking for addresses ('%1' and '%2')
+The SQLite data source was looking up A/AAAA addresses, but the data source
+contains different class than the query was for.
+
+% DATASRC_SQLITE_FINDEXACT looking for exact RRset '%1/%2'
+Debug information. The SQLite data source is looking up an exact resource
+record.
+
+% DATASRC_SQLITE_FINDEXACT_BAD_CLASS class mismatch looking for an RRset ('%1' and '%2')
+The SQLite data source was looking up an exact RRset, but the data source
+contains different class than the query was for.
+
+% DATASRC_SQLITE_FINDREC looking for record '%1/%2'
+Debug information. The SQLite data source is looking up records of given name
+and type in the database.
+
+% DATASRC_SQLITE_FINDREF looking for referral at '%1'
+Debug information. The SQLite data source is identifying if this domain is
+a referral and where it goes.
+
+% DATASRC_SQLITE_FINDREF_BAD_CLASS class mismatch looking for referral ('%1' and '%2')
+The SQLite data source was trying to identify if there's a referral. But
+it contains different class than the query was for.
+
+% DATASRC_SQLITE_FIND_BAD_CLASS class mismatch looking for an RRset ('%1' and '%2')
+The SQLite data source was looking up an RRset, but the data source contains
+different class than the query was for.
+
+% DATASRC_SQLITE_FIND_NSEC3 looking for NSEC3 in zone '%1' for hash '%2'
+Debug information. We're trying to look up a NSEC3 record in the SQLite data
+source.
+
+% DATASRC_SQLITE_FIND_NSEC3_NO_ZONE no such zone '%1'
+The SQLite data source was asked to provide a NSEC3 record for given zone.
+But it doesn't contain that zone.
+
+% DATASRC_SQLITE_INCOMPATIBLE_VERSION database schema V%1.%2 incompatible with version (V%3.%4) expected
+The version of the SQLite3 database schema used to hold the zone data
+is incompatible with the version expected by BIND 10. As a result,
+BIND 10 is unable to run using the database file as the data source.
+
+The database should be updated using the means described in the BIND
+10 documentation.
+
+% DATASRC_SQLITE_NEWCONN SQLite3Database is being initialized
+A wrapper object to hold database connection is being initialized.
+
+% DATASRC_SQLITE_OPEN opening SQLite database '%1'
+Debug information. The SQLite data source is loading an SQLite database in
+the provided file.
+
+% DATASRC_SQLITE_PREVIOUS looking for name previous to '%1'
+This is a debug message. The name given was not found, so the program
+is searching for the next name higher up the hierarchy (e.g. if
+www.example.com were queried for and not found, the software searches
+for the "previous" name, example.com).
+
+% DATASRC_SQLITE_PREVIOUS_NO_ZONE no zone containing '%1'
+The name given was not found, so the program is searching for the next
+name higher up the hierarchy (e.g. if www.example.com were queried
+for and not found, the software searches for the "previous" name,
+example.com). However, this name is not contained in any zone in the
+data source. This is an error since it indicates a problem in the earlier
+processing of the query.
+
+% DATASRC_SQLITE_SETUP setting up new SQLite3 database in '%1'
+The database for SQLite data source was found empty. It is assumed this is the
+first run and it is being initialized with current schema. It'll still contain
+no data, but it will be ready for use. If this is indeed the first run of
+BIND 10, it is to be expected and completely harmless. If you just configured
+a data source to point to an existing file and you see this, you may have
+misspelled the file name.
+
+% DATASRC_SQLITE_SETUP_OLD_API setting up new SQLite database
+The database for SQLite data source was found empty. It is assumed this is the
+first run and it is being initialized with current schema. It'll still contain
+no data, but it will be ready for use. This is similar to DATASRC_SQLITE_SETUP
+message, but it is logged from the old API. You should never see it, since the
+API is deprecated.
diff --git a/src/lib/datasrc/tests/Makefile.am b/src/lib/datasrc/tests/Makefile.am
index 7960963..fa1f01c 100644
--- a/src/lib/datasrc/tests/Makefile.am
+++ b/src/lib/datasrc/tests/Makefile.am
@@ -62,6 +62,8 @@ run_unittests_SOURCES += zone_loader_unittest.cc
# We need the actual module implementation in the tests (they are not part
# of libdatasrc)
run_unittests_SOURCES += $(top_srcdir)/src/lib/datasrc/sqlite3_accessor.cc
+# Also, as of #2746, sqlite3-specific log messages are in a separate file
+nodist_run_unittests_SOURCES = $(abs_top_builddir)/src/lib/datasrc/sqlite3_datasrc_messages.cc
run_unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES)
run_unittests_LDFLAGS = $(AM_LDFLAGS) $(GTEST_LDFLAGS)
@@ -71,7 +73,7 @@ run_unittests_LDADD = $(common_ldadd)
noinst_PROGRAMS+= $(TESTS)
# For the factory unit tests, we need to specify that we want
-# the loadable backend libraries from the build tree, and not from
+# the loadable backend libraries from the build tree, and not from
# the installation directory. Therefore we build it into a separate
# binary, and call that from check-local with B10_FROM_BUILD set.
# Also, we only want to do this when static building is not used,
diff --git a/src/lib/datasrc/tests/client_list_unittest.cc b/src/lib/datasrc/tests/client_list_unittest.cc
index 0838fb6..bc2d4f1 100644
--- a/src/lib/datasrc/tests/client_list_unittest.cc
+++ b/src/lib/datasrc/tests/client_list_unittest.cc
@@ -278,7 +278,7 @@ public:
ds_.push_back(ds);
ds_info_.push_back(ConfigurableClientList::DataSourceInfo(
ds.get(), DataSourceClientContainerPtr(),
- false, rrclass_, ztable_segment_));
+ false, rrclass_, ztable_segment_, ""));
}
}
@@ -512,12 +512,12 @@ TEST_F(ListTest, configureMulti) {
const ConstElementPtr elem(Element::fromJSON("["
"{"
" \"type\": \"type1\","
- " \"cache\": \"off\","
+ " \"cache-enable\": false,"
" \"params\": {}"
"},"
"{"
" \"type\": \"type2\","
- " \"cache\": \"off\","
+ " \"cache-enable\": false,"
" \"params\": {}"
"}]"
));
@@ -546,7 +546,7 @@ TEST_F(ListTest, configureParams) {
ConstElementPtr elem(Element::fromJSON(string("["
"{"
" \"type\": \"t\","
- " \"cache\": \"off\","
+ " \"cache-enable\": false,"
" \"params\": ") + *param +
"}]"));
list_->configure(elem, true);
@@ -555,6 +555,33 @@ TEST_F(ListTest, configureParams) {
}
}
+TEST_F(ListTest, status) {
+ EXPECT_TRUE(list_->getStatus().empty());
+ const ConstElementPtr elem(Element::fromJSON("["
+ "{"
+ " \"type\": \"type1\","
+ " \"cache-enable\": false,"
+ " \"params\": {}"
+ "},"
+ "{"
+ " \"type\": \"type2\","
+ " \"cache-enable\": true,"
+ " \"cache-zones\": [],"
+ " \"name\": \"Test name\","
+ " \"params\": {}"
+ "}]"
+ ));
+ list_->configure(elem, true);
+ const vector<DataSourceStatus> statuses(list_->getStatus());
+ ASSERT_EQ(2, statuses.size());
+ EXPECT_EQ("type1", statuses[0].getName());
+ EXPECT_EQ(SEGMENT_UNUSED, statuses[0].getSegmentState());
+ EXPECT_THROW(statuses[0].getSegmentType(), isc::InvalidOperation);
+ EXPECT_EQ("Test name", statuses[1].getName());
+ EXPECT_EQ(SEGMENT_INUSE, statuses[1].getSegmentState());
+ EXPECT_EQ("local", statuses[1].getSegmentType());
+}
+
TEST_F(ListTest, wrongConfig) {
const char* configs[] = {
// A lot of stuff missing from there
@@ -834,6 +861,54 @@ TEST_F(ListTest, masterFiles) {
EXPECT_EQ(0, list_->getDataSources().size());
}
+// Test the names are set correctly and collission is detected.
+TEST_F(ListTest, names) {
+ // Explicit name
+ const ConstElementPtr elem1(Element::fromJSON("["
+ "{"
+ " \"type\": \"MasterFiles\","
+ " \"cache-enable\": true,"
+ " \"params\": {"
+ " \".\": \"" TEST_DATA_DIR "/root.zone\""
+ " },"
+ " \"name\": \"Whatever\""
+ "}]"));
+ list_->configure(elem1, true);
+ EXPECT_EQ("Whatever", list_->getDataSources()[0].name_);
+
+ // Default name
+ const ConstElementPtr elem2(Element::fromJSON("["
+ "{"
+ " \"type\": \"MasterFiles\","
+ " \"cache-enable\": true,"
+ " \"params\": {"
+ " \".\": \"" TEST_DATA_DIR "/root.zone\""
+ " }"
+ "}]"));
+ list_->configure(elem2, true);
+ EXPECT_EQ("MasterFiles", list_->getDataSources()[0].name_);
+
+ // Collission
+ const ConstElementPtr elem3(Element::fromJSON("["
+ "{"
+ " \"type\": \"MasterFiles\","
+ " \"cache-enable\": true,"
+ " \"params\": {"
+ " \".\": \"" TEST_DATA_DIR "/root.zone\""
+ " }"
+ "},"
+ "{"
+ " \"type\": \"MasterFiles\","
+ " \"cache-enable\": true,"
+ " \"params\": {"
+ " \".\": \"" TEST_DATA_DIR "/root.zone\""
+ " },"
+ " \"name\": \"MasterFiles\""
+ "}]"));
+ EXPECT_THROW(list_->configure(elem3, true),
+ ConfigurableClientList::ConfigurationError);
+}
+
TEST_F(ListTest, BadMasterFile) {
// Configuration should succeed, and the good zones in the list
// below should be loaded. No bad zones should be loaded.
@@ -1003,7 +1078,7 @@ TYPED_TEST(ReloadTest, reloadNoSuchZone) {
TYPED_TEST(ReloadTest, reloadZoneGone) {
this->list_->configure(this->config_elem_, true);
const Name name("example.org");
- // We put in a cache for non-existant zone. This emulates being loaded
+ // We put in a cache for non-existent zone. This emulates being loaded
// and then the zone disappearing. We prefill the cache, so we can check
// it.
this->prepareCache(0, name);
@@ -1088,4 +1163,16 @@ TYPED_TEST(ReloadTest, reloadMasterFile) {
RRType::TXT())->code);
}
+// Check the status holds data
+TEST(DataSourceStatus, status) {
+ const DataSourceStatus status("Test", SEGMENT_INUSE, "local");
+ EXPECT_EQ("Test", status.getName());
+ EXPECT_EQ(SEGMENT_INUSE, status.getSegmentState());
+ EXPECT_EQ("local", status.getSegmentType());
+ const DataSourceStatus status_unused("Unused", SEGMENT_UNUSED, "");
+ EXPECT_EQ("Unused", status_unused.getName());
+ EXPECT_EQ(SEGMENT_UNUSED, status_unused.getSegmentState());
+ EXPECT_THROW(status_unused.getSegmentType(), isc::InvalidOperation);
+}
+
}
diff --git a/src/lib/datasrc/tests/database_unittest.cc b/src/lib/datasrc/tests/database_unittest.cc
index 83ff004..cac5e33 100644
--- a/src/lib/datasrc/tests/database_unittest.cc
+++ b/src/lib/datasrc/tests/database_unittest.cc
@@ -2566,7 +2566,7 @@ TEST_P(DatabaseClientTest, wildcard) {
doFindTest(*finder, isc::dns::Name("a.*.wild.example.org"),
qtype_, qtype_, rrttl_, ZoneFinder::NXDOMAIN,
expected_rdatas_, expected_sig_rdatas_);
- // These should be canceled, since it is below a domain which exitsts
+ // These should be canceled, since it is below a domain which exists
doFindTest(*finder, isc::dns::Name("nothing.here.wild.example.org"),
qtype_, qtype_, rrttl_, ZoneFinder::NXDOMAIN,
expected_rdatas_, expected_sig_rdatas_);
diff --git a/src/lib/datasrc/tests/memory/memory_client_unittest.cc b/src/lib/datasrc/tests/memory/memory_client_unittest.cc
index 74e7917..5984de5 100644
--- a/src/lib/datasrc/tests/memory/memory_client_unittest.cc
+++ b/src/lib/datasrc/tests/memory/memory_client_unittest.cc
@@ -74,6 +74,7 @@ const char* rrset_data[] = {
const char* rrset_data_separated[] = {
"example.org. 3600 IN SOA ns1.example.org. bugs.x.w.example.org. "
"68 3600 300 3600000 3600",
+ "example.org. 3600 IN NS ns1.example.org.",
"a.example.org. 3600 IN A 192.168.0.1", // these two belong to the same
"a.example.org. 3600 IN A 192.168.0.2", // RRset, but are separated.
NULL
@@ -83,6 +84,7 @@ const char* rrset_data_separated[] = {
const char* rrset_data_sigseparated[] = {
"example.org. 3600 IN SOA ns1.example.org. bugs.x.w.example.org. "
"68 3600 300 3600000 3600",
+ "example.org. 3600 IN NS ns1.example.org.",
"a.example.org. 3600 IN A 192.168.0.1",
"a.example.org. 3600 IN RRSIG A 5 3 3600 20150420235959 20051021000000 "
"40430 example.org. FAKEFAKE",
@@ -261,13 +263,13 @@ TEST_F(MemoryClientTest, loadFromIterator) {
EXPECT_TRUE(rrset);
EXPECT_EQ(RRType::NS(), rrset->getType());
- // RRType::MX() RRset
+ // RRType::A() RRset
rrset = iterator->getNextRRset();
EXPECT_TRUE(rrset);
EXPECT_EQ(RRType::MX(), rrset->getType());
EXPECT_EQ(1, rrset->getRRsigDataCount()); // this RRset is signed
- // RRType::A() RRset
+ // RRType::MX() RRset
rrset = iterator->getNextRRset();
EXPECT_TRUE(rrset);
EXPECT_EQ(RRType::A(), rrset->getType());
@@ -279,19 +281,17 @@ TEST_F(MemoryClientTest, loadFromIterator) {
// Iterating past the end should result in an exception
EXPECT_THROW(iterator->getNextRRset(), isc::Unexpected);
- // Loading the zone with an iterator separating RRs of the same RRset
- // will fail because the resulting sequence doesn't meet assumptions of
- // the (current) in-memory implementation.
- EXPECT_THROW(client_->load(Name("example.org"),
- *MockIterator::makeIterator(
- rrset_data_separated)),
- ZoneDataUpdater::AddError);
+ // Loading the zone with an iterator separating RRs of the same
+ // RRset should not fail. It is acceptable to load RRs of the same
+ // type again.
+ client_->load(Name("example.org"),
+ *MockIterator::makeIterator(
+ rrset_data_separated));
// Similar to the previous case, but with separated RRSIGs.
- EXPECT_THROW(client_->load(Name("example.org"),
- *MockIterator::makeIterator(
- rrset_data_sigseparated)),
- ZoneDataUpdater::AddError);
+ client_->load(Name("example.org"),
+ *MockIterator::makeIterator(
+ rrset_data_sigseparated));
// Emulating bogus iterator implementation that passes empty RRSIGs.
EXPECT_THROW(client_->load(Name("example.org"),
@@ -439,15 +439,41 @@ TEST_F(MemoryClientTest, loadReloadZone) {
}
TEST_F(MemoryClientTest, loadDuplicateType) {
- // This should not result in any exceptions:
+ // This should not result in any exceptions (multiple records of the
+ // same name, type are present, one after another in sequence).
client_->load(Name("example.org"),
TEST_DATA_DIR "/example.org-duplicate-type.zone");
- // This should throw:
- EXPECT_THROW(client_->load(Name("example.org"),
- TEST_DATA_DIR
- "/example.org-duplicate-type-bad.zone"),
- ZoneDataUpdater::AddError);
+ // This should not result in any exceptions (multiple records of the
+ // same name, type are present, but not one after another in
+ // sequence).
+ client_->load(Name("example.org"),
+ TEST_DATA_DIR
+ "/example.org-duplicate-type-bad.zone");
+
+ const ZoneData* zone_data =
+ client_->findZoneData(Name("example.org"));
+ EXPECT_NE(static_cast<const ZoneData*>(NULL), zone_data);
+
+ /* Check ns1.example.org */
+ const ZoneTree& tree = zone_data->getZoneTree();
+ const ZoneNode* node;
+ ZoneTree::Result zresult(tree.find(Name("ns1.example.org"), &node));
+ EXPECT_EQ(ZoneTree::EXACTMATCH, zresult);
+
+ const RdataSet* set = node->getData();
+ EXPECT_NE(static_cast<const RdataSet*>(NULL), set);
+ EXPECT_EQ(RRType::AAAA(), set->type);
+
+ set = set->getNext();
+ EXPECT_NE(static_cast<const RdataSet*>(NULL), set);
+ EXPECT_EQ(RRType::A(), set->type);
+ // 192.168.0.1 and 192.168.0.2
+ EXPECT_EQ(2, set->getRdataCount());
+
+ set = set->getNext();
+ EXPECT_EQ(static_cast<const RdataSet*>(NULL), set);
+
// Teardown checks for memory segment leaks
}
diff --git a/src/lib/datasrc/tests/memory/testdata/example.org-duplicate-type-bad.zone b/src/lib/datasrc/tests/memory/testdata/example.org-duplicate-type-bad.zone
index 06c7dff..1198934 100644
--- a/src/lib/datasrc/tests/memory/testdata/example.org-duplicate-type-bad.zone
+++ b/src/lib/datasrc/tests/memory/testdata/example.org-duplicate-type-bad.zone
@@ -1,4 +1,7 @@
-example.org. 3600 IN SOA ns1.example.org. bugs.x.w.example.org. 77 3600 300 3600000 3600
+example.org. 3600 IN SOA ns1.example.org. bugs.x.w.example.org. 78 3600 300 3600000 3600
+example.org. 3600 IN NS ns1.example.org.
+example.org. 3600 IN NS ns2.example.org.
ns1.example.org. 3600 IN A 192.168.0.1
ns1.example.org. 3600 IN AAAA ::1
+someother.example.org. 3600 IN AAAA ::1
ns1.example.org. 3600 IN A 192.168.0.2
diff --git a/src/lib/datasrc/tests/memory/zone_data_updater_unittest.cc b/src/lib/datasrc/tests/memory/zone_data_updater_unittest.cc
index 93ca0c9..6399923 100644
--- a/src/lib/datasrc/tests/memory/zone_data_updater_unittest.cc
+++ b/src/lib/datasrc/tests/memory/zone_data_updater_unittest.cc
@@ -111,12 +111,10 @@ TEST_F(ZoneDataUpdaterTest, rrsigOnly) {
EXPECT_EQ(0, rdset->getRdataCount());
EXPECT_EQ(1, rdset->getSigRdataCount());
- // The RRSIG covering A prohibits an actual A RRset from being added.
- // This should be loosened in future version, but we check the current
- // behavior.
- EXPECT_THROW(updater_->add(
- textToRRset("www.example.org. 3600 IN A 192.0.2.1"),
- ConstRRsetPtr()), ZoneDataUpdater::AddError);
+ // The RRSIG covering A must not prohibit an actual A RRset from
+ // being added later.
+ updater_->add(textToRRset("www.example.org. 3600 IN A 192.0.2.1"),
+ ConstRRsetPtr());
// The special "wildcarding" node mark should be added for the RRSIG-only
// case, too.
diff --git a/src/lib/datasrc/tests/memory/zone_finder_unittest.cc b/src/lib/datasrc/tests/memory/zone_finder_unittest.cc
index b1ebaf4..02c8a09 100644
--- a/src/lib/datasrc/tests/memory/zone_finder_unittest.cc
+++ b/src/lib/datasrc/tests/memory/zone_finder_unittest.cc
@@ -292,7 +292,7 @@ protected:
* \param zone_finder Check different InMemoryZoneFinder object than
* zone_finder_ (if NULL, uses zone_finder_)
* \param check_wild_answer Checks that the answer has the same RRs, type
- * class and TTL as the eqxpected answer and that the name corresponds
+ * class and TTL as the expected answer and that the name corresponds
* to the one searched. It is meant for checking answers for wildcard
* queries.
*/
diff --git a/src/lib/datasrc/tests/testdata/rrset_toWire2 b/src/lib/datasrc/tests/testdata/rrset_toWire2
index b9a6a15..743f968 100644
--- a/src/lib/datasrc/tests/testdata/rrset_toWire2
+++ b/src/lib/datasrc/tests/testdata/rrset_toWire2
@@ -18,7 +18,7 @@
# RDATA: 192.0.2.1
c0 00 02 01
#
-# 2nd RR: the owner name is compresed
+# 2nd RR: the owner name is compressed
c0 00
00 01 00 01
00 00 0e 10
diff --git a/src/lib/datasrc/zone_iterator.h b/src/lib/datasrc/zone_iterator.h
index e1c6929..bdf219a 100644
--- a/src/lib/datasrc/zone_iterator.h
+++ b/src/lib/datasrc/zone_iterator.h
@@ -27,7 +27,7 @@ namespace datasrc {
/**
* \brief Read-only iterator to a zone.
*
- * You can get an instance of (descendand of) ZoneIterator from
+ * You can get an instance of (descendant of) ZoneIterator from
* DataSourceClient::getIterator() method. The actual concrete implementation
* will be different depending on the actual data source used. This is the
* abstract interface.
diff --git a/src/lib/dhcp/dhcp6.h b/src/lib/dhcp/dhcp6.h
index 116019e..874ee46 100644
--- a/src/lib/dhcp/dhcp6.h
+++ b/src/lib/dhcp/dhcp6.h
@@ -134,7 +134,7 @@ extern const int dhcpv6_type_name_max;
#define LQ_QUERY_OFFSET 17
/*
- * DHCPv6 well-known multicast addressess, from section 5.1 of RFC 3315
+ * DHCPv6 well-known multicast addresses, from section 5.1 of RFC 3315
*/
#define ALL_DHCP_RELAY_AGENTS_AND_SERVERS "ff02::1:2"
#define ALL_DHCP_SERVERS "ff05::1:3"
diff --git a/src/lib/dhcp/duid.cc b/src/lib/dhcp/duid.cc
index f1c8866..e0df45d 100644
--- a/src/lib/dhcp/duid.cc
+++ b/src/lib/dhcp/duid.cc
@@ -41,7 +41,7 @@ DUID::DUID(const uint8_t* data, size_t len) {
duid_ = std::vector<uint8_t>(data, data + len);
}
-const std::vector<uint8_t> DUID::getDuid() const {
+std::vector<uint8_t> DUID::getDuid() const {
return (duid_);
}
@@ -91,7 +91,7 @@ ClientId::ClientId(const uint8_t *clientid, size_t len)
}
// Returns a copy of client-id data
-const std::vector<uint8_t> ClientId::getClientId() const {
+std::vector<uint8_t> ClientId::getClientId() const {
return (duid_);
}
diff --git a/src/lib/dhcp/duid.h b/src/lib/dhcp/duid.h
index 688885b..21c6b8f 100644
--- a/src/lib/dhcp/duid.h
+++ b/src/lib/dhcp/duid.h
@@ -58,7 +58,7 @@ class DUID {
/// returned it. In any case, this method should be used only sporadically.
/// If there are frequent uses, we must implement some other method
/// (e.g. storeSelf()) that will avoid data copying.
- const std::vector<uint8_t> getDuid() const;
+ std::vector<uint8_t> getDuid() const;
/// @brief Returns the DUID type
DUIDType getType() const;
@@ -105,7 +105,7 @@ public:
ClientId(const uint8_t* clientid, size_t len);
/// @brief Returns reference to the client-id data
- const std::vector<uint8_t> getClientId() const;
+ std::vector<uint8_t> getClientId() const;
/// @brief Returns textual representation of a DUID (e.g. 00:01:02:03:ff)
std::string toText() const;
diff --git a/src/lib/dhcp/libdhcp++.h b/src/lib/dhcp/libdhcp++.h
index c6594b9..c242611 100644
--- a/src/lib/dhcp/libdhcp++.h
+++ b/src/lib/dhcp/libdhcp++.h
@@ -61,7 +61,7 @@ public:
/// @param code option code.
///
/// @return true if the specified option is a standard option.
- /// @todo We arleady create option definitions for the subset if
+ /// @todo We already create option definitions for the subset if
/// standard options. We are aiming that this function checks
/// the presence of the standard option definition and if it finds
/// it, then the true value is returned. However, at this point
diff --git a/src/lib/dhcp/option.h b/src/lib/dhcp/option.h
index 553e825..28e65a9 100644
--- a/src/lib/dhcp/option.h
+++ b/src/lib/dhcp/option.h
@@ -128,7 +128,7 @@ public:
/// @brief Constructor, used for received options.
///
- /// This contructor is similar to the previous one, but it does not take
+ /// This constructor is similar to the previous one, but it does not take
/// the whole vector<uint8_t>, but rather subset of it.
///
/// @todo This can be templated to use different containers, not just
@@ -280,7 +280,7 @@ public:
///
/// Option will be resized to length of buffer.
///
- /// @param first iterator pointing begining of buffer to copy.
+ /// @param first iterator pointing to beginning of buffer to copy.
/// @param last iterator pointing to end of buffer to copy.
void setData(const OptionBufferConstIter first,
const OptionBufferConstIter last);
diff --git a/src/lib/dhcp/option_custom.h b/src/lib/dhcp/option_custom.h
index c25347b..5766cb4 100644
--- a/src/lib/dhcp/option_custom.h
+++ b/src/lib/dhcp/option_custom.h
@@ -205,7 +205,7 @@ public:
// is consistent with an option definition.
checkDataType<T>(index);
// When we created the buffer we have checked that it has a
- // valid size so this condition here should be always fulfiled.
+ // valid size so this condition here should be always fulfilled.
assert(buffers_[index].size() == OptionDataTypeTraits<T>::len);
// Read an integer value.
return (OptionDataTypeUtil::readInt<T>(buffers_[index]));
@@ -278,7 +278,7 @@ public:
///
/// Option will be resized to length of buffer.
///
- /// @param first iterator pointing begining of buffer to copy.
+ /// @param first iterator pointing to beginning of buffer to copy.
/// @param last iterator pointing to end of buffer to copy.
void setData(const OptionBufferConstIter first,
const OptionBufferConstIter last);
diff --git a/src/lib/dhcp/option_data_types.h b/src/lib/dhcp/option_data_types.h
index e53fa6e..94e7e9e 100644
--- a/src/lib/dhcp/option_data_types.h
+++ b/src/lib/dhcp/option_data_types.h
@@ -405,7 +405,7 @@ private:
///
/// This function is used by some of the public static functions
/// to create an instance of OptionDataTypeUtil class.
- /// When instance is called it calls the class'es constructor
+ /// When this instance is called it calls the classes constructor
/// and initializes some of the private data members.
///
/// @return instance of OptionDataTypeUtil singleton.
diff --git a/src/lib/dhcp/option_definition.cc b/src/lib/dhcp/option_definition.cc
index 59ff022..7f0d578 100644
--- a/src/lib/dhcp/option_definition.cc
+++ b/src/lib/dhcp/option_definition.cc
@@ -109,8 +109,6 @@ OptionPtr
OptionDefinition::optionFactory(Option::Universe u, uint16_t type,
OptionBufferConstIter begin,
OptionBufferConstIter end) const {
- validate();
-
try {
switch(type_) {
case OPT_EMPTY_TYPE:
@@ -200,8 +198,6 @@ OptionDefinition::optionFactory(Option::Universe u, uint16_t type,
OptionPtr
OptionDefinition::optionFactory(Option::Universe u, uint16_t type,
const std::vector<std::string>& values) const {
- validate();
-
OptionBuffer buf;
if (!array_type_ && type_ != OPT_RECORD_TYPE) {
if (values.empty()) {
diff --git a/src/lib/dhcp/option_definition.h b/src/lib/dhcp/option_definition.h
index df5def7..233f778 100644
--- a/src/lib/dhcp/option_definition.h
+++ b/src/lib/dhcp/option_definition.h
@@ -255,6 +255,13 @@ public:
/// @brief Check if the option definition is valid.
///
+ /// Note that it is a responsibility of the code that created
+ /// the OptionDefinition object to validate that it is valid.
+ /// This function will not be called internally anywhere in this
+ /// class to verify that the option definition is valid. Using
+ /// invalid option definition to create an instance of the
+ /// DHCP option leads to undefined behavior.
+ ///
/// @throw MalformedOptionDefinition option definition is invalid.
void validate() const;
@@ -274,13 +281,16 @@ public:
/// provided chunk of buffer. This function may be used to
/// create option which is to be sent in the outgoing packet.
///
+ /// @warning calling this function on invalid option definition
+ /// yields undefined behavior. Use \ref validate to test that
+ /// the option definition is valid.
+ ///
/// @param u option universe (V4 or V6).
/// @param type option type.
/// @param begin beginning of the option buffer.
/// @param end end of the option buffer.
///
/// @return instance of the DHCP option.
- /// @throw MalformedOptionDefinition if option definition is invalid.
/// @throw InvalidOptionValue if data for the option is invalid.
OptionPtr optionFactory(Option::Universe u, uint16_t type,
OptionBufferConstIter begin,
@@ -292,12 +302,15 @@ public:
/// whole provided buffer. This function may be used to
/// create option which is to be sent in the outgoing packet.
///
+ /// @warning calling this function on invalid option definition
+ /// yields undefined behavior. Use \ref validate to test that
+ /// the option definition is valid.
+ ///
/// @param u option universe (V4 or V6).
/// @param type option type.
/// @param buf option buffer.
///
/// @return instance of the DHCP option.
- /// @throw MalformedOptionDefinition if option definition is invalid.
/// @throw InvalidOptionValue if data for the option is invalid.
OptionPtr optionFactory(Option::Universe u, uint16_t type,
const OptionBuffer& buf = OptionBuffer()) const;
@@ -316,12 +329,15 @@ public:
/// must be tokenized into the vector of string values and this vector
/// can be supplied to this function.
///
+ /// @warning calling this function on invalid option definition
+ /// yields undefined behavior. Use \ref validate to test that
+ /// the option definition is valid.
+ ///
/// @param u option universe (V4 or V6).
/// @param type option type.
/// @param values a vector of values to be used to set data for an option.
///
/// @return instance of the DHCP option.
- /// @throw MalformedOptionDefinition if option definition is invalid.
/// @throw InvalidOptionValue if data for the option is invalid.
OptionPtr optionFactory(Option::Universe u, uint16_t type,
const std::vector<std::string>& values) const;
@@ -515,7 +531,7 @@ private:
/// using two indexes:
/// - sequenced: used to access elements in the order they have
/// been added to the container
-/// - option code: used to search defintions of options
+/// - option code: used to search definitions of options
/// with a specified option code (aka option type).
/// Note that this container can hold multiple options with the
/// same code. For this reason, the latter index can be used to
@@ -555,7 +571,7 @@ typedef boost::shared_ptr<OptionDefContainer> OptionDefContainerPtr;
typedef OptionDefContainer::nth_index<1>::type OptionDefContainerTypeIndex;
/// Pair of iterators to represent the range of options definitions
/// having the same option type value. The first element in this pair
-/// represents the begining of the range, the second element
+/// represents the beginning of the range, the second element
/// represents the end.
typedef std::pair<OptionDefContainerTypeIndex::const_iterator,
OptionDefContainerTypeIndex::const_iterator> OptionDefContainerTypeRange;
diff --git a/src/lib/dhcp/option_int.h b/src/lib/dhcp/option_int.h
index ebb1641..9a4cfb1 100644
--- a/src/lib/dhcp/option_int.h
+++ b/src/lib/dhcp/option_int.h
@@ -56,7 +56,7 @@ public:
/// @brief Constructor.
///
- /// This constructor creates option from a buffer. This construtor
+ /// This constructor creates option from a buffer. This constructor
/// may throw exception if \ref unpack function throws during buffer
/// parsing.
///
diff --git a/src/lib/dhcp/option_int_array.h b/src/lib/dhcp/option_int_array.h
index 1babee5..a87e9b5 100644
--- a/src/lib/dhcp/option_int_array.h
+++ b/src/lib/dhcp/option_int_array.h
@@ -102,7 +102,7 @@ public:
/// @brief Constructor.
///
- /// This constructor creates option from a buffer. This construtor
+ /// This constructor creates option from a buffer. This constructor
/// may throw exception if \ref unpack function throws during buffer
/// parsing.
///
diff --git a/src/lib/dhcp/pkt4.h b/src/lib/dhcp/pkt4.h
index 664686b..e7f33c5 100644
--- a/src/lib/dhcp/pkt4.h
+++ b/src/lib/dhcp/pkt4.h
@@ -441,7 +441,7 @@ protected:
/// @brief interface index
///
/// Each network interface has assigned unique ifindex. It is functional
- /// equvalent of name, but sometimes more useful, e.g. when using crazy
+ /// equivalent of name, but sometimes more useful, e.g. when using crazy
/// systems that allow spaces in interface names e.g. MS Windows)
uint32_t ifindex_;
diff --git a/src/lib/dhcp/pkt6.h b/src/lib/dhcp/pkt6.h
index 6ffea2b..afb85d2 100644
--- a/src/lib/dhcp/pkt6.h
+++ b/src/lib/dhcp/pkt6.h
@@ -365,7 +365,7 @@ protected:
/// @brief interface index
///
/// interface index (each network interface has assigned unique ifindex
- /// it is functional equvalent of name, but sometimes more useful, e.g.
+ /// it is functional equivalent of name, but sometimes more useful, e.g.
/// when using crazy systems that allow spaces in interface names
/// e.g. windows
int ifindex_;
diff --git a/src/lib/dhcp/tests/duid_unittest.cc b/src/lib/dhcp/tests/duid_unittest.cc
index de20e51..44aa561 100644
--- a/src/lib/dhcp/tests/duid_unittest.cc
+++ b/src/lib/dhcp/tests/duid_unittest.cc
@@ -146,7 +146,7 @@ TEST(ClientIdTest, constructor) {
uint8_t data1[] = {0, 1, 2, 3, 4, 5, 6};
vector<uint8_t> data2(data1, data1 + sizeof(data1));
- // checks for C-style construtor (uint8_t * + len)
+ // checks for C-style constructor (uint8_t * + len)
scoped_ptr<ClientId> id1(new ClientId(data1, sizeof(data1)));
vector<uint8_t> vecdata = id1->getClientId();
EXPECT_TRUE(data2 == vecdata);
diff --git a/src/lib/dhcp/tests/iface_mgr_unittest.cc b/src/lib/dhcp/tests/iface_mgr_unittest.cc
index d72ef9e..a7f338c 100644
--- a/src/lib/dhcp/tests/iface_mgr_unittest.cc
+++ b/src/lib/dhcp/tests/iface_mgr_unittest.cc
@@ -657,7 +657,7 @@ TEST_F(IfaceMgrTest, sendReceive6) {
// since we opened 2 sockets on the same interface and none of them is multicast,
// none is preferred over the other for sending data, so we really should not
- // assume the one or the other will always be choosen for sending data. Therefore
+ // assume the one or the other will always be chosen for sending data. Therefore
// we should accept both values as source ports.
EXPECT_TRUE((rcvPkt->getRemotePort() == 10546) || (rcvPkt->getRemotePort() == 10547));
@@ -749,7 +749,7 @@ TEST_F(IfaceMgrTest, sendReceive4) {
// since we opened 2 sockets on the same interface and none of them is multicast,
// none is preferred over the other for sending data, so we really should not
- // assume the one or the other will always be choosen for sending data. We should
+ // assume the one or the other will always be chosen for sending data. We should
// skip checking source port of sent address.
// try to receive data over the closed socket. Closed socket's descriptor is
@@ -952,7 +952,7 @@ TEST_F(IfaceMgrTest, socketInfo) {
/// @brief parses text representation of MAC address
///
/// This function parses text representation of a MAC address and stores
-/// it in binary format. Text format is expecte to be separate with
+/// it in binary format. Text format is expected to be separate with
/// semicolons, e.g. f4:6d:04:96:58:f2
///
/// TODO: IfaceMgr::Iface::mac_ uses uint8_t* type, should be vector<uint8_t>
@@ -967,7 +967,7 @@ size_t parse_mac(const std::string& textMac, uint8_t* mac, size_t macLen) {
tmp.flags(ios::hex);
int i = 0;
uint8_t octet = 0; // output octet
- uint8_t byte; // parsed charater from text representation
+ uint8_t byte; // parsed character from text representation
while (!tmp.eof()) {
tmp >> byte; // hex value
diff --git a/src/lib/dhcp/tests/libdhcp++_unittest.cc b/src/lib/dhcp/tests/libdhcp++_unittest.cc
index 1a87b13..dbab492 100644
--- a/src/lib/dhcp/tests/libdhcp++_unittest.cc
+++ b/src/lib/dhcp/tests/libdhcp++_unittest.cc
@@ -62,9 +62,9 @@ public:
/// option has been initialized correctly.
///
/// @param code option code.
- /// @param begin iterator pointing a begining of a buffer to
+ /// @param begin iterator pointing at beginning of a buffer to
/// be used to create option instance.
- /// @param end iterator pointing an end of a buffer to be
+ /// @param end iterator pointing at end of a buffer to be
/// used to create option instance.
/// @param expected_type type of the option created by the
/// factory function returned by the option definition.
@@ -86,9 +86,9 @@ public:
/// option has been initialized correctly.
///
/// @param code option code.
- /// @param begin iterator pointing a begining of a buffer to
+ /// @param begin iterator pointing at beginning of a buffer to
/// be used to create option instance.
- /// @param end iterator pointing an end of a buffer to be
+ /// @param end iterator pointing at end of a buffer to be
/// used to create option instance.
/// @param expected_type type of the option created by the
/// factory function returned by the option definition.
@@ -111,9 +111,9 @@ private:
/// option has been initialized correctly.
///
/// @param code option code.
- /// @param begin iterator pointing a begining of a buffer to
+ /// @param begin iterator pointing at beginning of a buffer to
/// be used to create option instance.
- /// @param end iterator pointing an end of a buffer to be
+ /// @param end iterator pointing at end of a buffer to be
/// used to create option instance.
/// @param expected_type type of the option created by the
/// factory function returned by the option definition.
diff --git a/src/lib/dhcp/tests/option4_addrlst_unittest.cc b/src/lib/dhcp/tests/option4_addrlst_unittest.cc
index 0c1d9e6..3a9f2e7 100644
--- a/src/lib/dhcp/tests/option4_addrlst_unittest.cc
+++ b/src/lib/dhcp/tests/option4_addrlst_unittest.cc
@@ -174,7 +174,7 @@ TEST_F(Option4AddrLstTest, assembly1) {
BadValue
);
if (opt) {
- // test failed. Execption was not thrown, but option was created instead.
+ // test failed. Exception was not thrown, but option was created instead.
delete opt;
}
}
@@ -218,7 +218,7 @@ TEST_F(Option4AddrLstTest, assembly4) {
BadValue
);
if (opt) {
- // test failed. Execption was not thrown, but option was created instead.
+ // test failed. Exception was not thrown, but option was created instead.
delete opt;
}
}
diff --git a/src/lib/dhcp/tests/option_custom_unittest.cc b/src/lib/dhcp/tests/option_custom_unittest.cc
index a34852b..e0ae727 100644
--- a/src/lib/dhcp/tests/option_custom_unittest.cc
+++ b/src/lib/dhcp/tests/option_custom_unittest.cc
@@ -310,7 +310,7 @@ TEST_F(OptionCustomTest, int32Data) {
}
// The purpose of this test is to verify that the option definition comprising
-// single IPv4 addres can be used to create an instance of custom option.
+// single IPv4 address can be used to create an instance of custom option.
TEST_F(OptionCustomTest, ipv4AddressData) {
OptionDefinition opt_def("OPTION_FOO", 231, "ipv4-address");
@@ -343,7 +343,7 @@ TEST_F(OptionCustomTest, ipv4AddressData) {
}
// The purpose of this test is to verify that the option definition comprising
-// single IPv6 addres can be used to create an instance of custom option.
+// single IPv6 address can be used to create an instance of custom option.
TEST_F(OptionCustomTest, ipv6AddressData) {
OptionDefinition opt_def("OPTION_FOO", 1000, "ipv6-address");
@@ -999,7 +999,7 @@ TEST_F(OptionCustomTest, setBooleanDataArray) {
EXPECT_TRUE(value2);
}
-// The purpose of this test is to verify that am option carying
+// The purpose of this test is to verify that am option carrying
// an array of 16-bit signed integer values can be created with
// no values initially and that the values can be later added to it.
TEST_F(OptionCustomTest, setUint16DataArray) {
diff --git a/src/lib/dhcp/tests/option_unittest.cc b/src/lib/dhcp/tests/option_unittest.cc
index 1fc49f1..2ce3bc6 100644
--- a/src/lib/dhcp/tests/option_unittest.cc
+++ b/src/lib/dhcp/tests/option_unittest.cc
@@ -220,7 +220,7 @@ TEST_F(OptionTest, v6_basic) {
);
}
-// tests contructor used in pkt reception
+// tests constructor used in pkt reception
// option contains actual data
TEST_F(OptionTest, v6_data1) {
for (int i = 0; i < 32; i++)
diff --git a/src/lib/dhcpsrv/Makefile.am b/src/lib/dhcpsrv/Makefile.am
index e721267..db82513 100644
--- a/src/lib/dhcpsrv/Makefile.am
+++ b/src/lib/dhcpsrv/Makefile.am
@@ -37,6 +37,7 @@ libb10_dhcpsrv_la_SOURCES += dbaccess_parser.cc dbaccess_parser.h
libb10_dhcpsrv_la_SOURCES += dhcpsrv_log.cc dhcpsrv_log.h
libb10_dhcpsrv_la_SOURCES += cfgmgr.cc cfgmgr.h
libb10_dhcpsrv_la_SOURCES += dhcp_config_parser.h
+libb10_dhcpsrv_la_SOURCES += key_from_key.h
libb10_dhcpsrv_la_SOURCES += lease_mgr.cc lease_mgr.h
libb10_dhcpsrv_la_SOURCES += lease_mgr_factory.cc lease_mgr_factory.h
libb10_dhcpsrv_la_SOURCES += memfile_lease_mgr.cc memfile_lease_mgr.h
diff --git a/src/lib/dhcpsrv/alloc_engine.cc b/src/lib/dhcpsrv/alloc_engine.cc
index bcb7851..a3df8e1 100644
--- a/src/lib/dhcpsrv/alloc_engine.cc
+++ b/src/lib/dhcpsrv/alloc_engine.cc
@@ -285,8 +285,9 @@ AllocEngine::allocateAddress4(const SubnetPtr& subnet,
}
// Check if there's existing lease for that subnet/clientid/hwaddr combination.
- Lease4Ptr existing = LeaseMgrFactory::instance().getLease4(hwaddr->hwaddr_, subnet->getID());
+ Lease4Ptr existing = LeaseMgrFactory::instance().getLease4(*hwaddr, subnet->getID());
if (existing) {
+ std::cout << "Got lease using HWADdr" << std::endl;
// We have a lease already. This is a returning client, probably after
// its reboot.
existing = renewLease4(subnet, clientid, hwaddr, existing, fake_allocation);
@@ -301,6 +302,7 @@ AllocEngine::allocateAddress4(const SubnetPtr& subnet,
if (clientid) {
existing = LeaseMgrFactory::instance().getLease4(*clientid, subnet->getID());
if (existing) {
+ std::cout << "Got lease using Clientid" << std::endl;
// we have a lease already. This is a returning client, probably after
// its reboot.
existing = renewLease4(subnet, clientid, hwaddr, existing, fake_allocation);
diff --git a/src/lib/dhcpsrv/cfgmgr.h b/src/lib/dhcpsrv/cfgmgr.h
index f4eecb5..00f7e25 100644
--- a/src/lib/dhcpsrv/cfgmgr.h
+++ b/src/lib/dhcpsrv/cfgmgr.h
@@ -40,7 +40,7 @@ namespace dhcp {
/// This singleton class holds the whole configuration for DHCPv4 and DHCPv6
/// servers. It currently holds information about zero or more subnets6.
/// Each subnet may contain zero or more pools. Pool4 and Pool6 is the most
-/// basic "chunk" of configuration. It contains a range of assigneable
+/// basic "chunk" of configuration. It contains a range of assignable
/// addresses.
///
/// Below is a sketch of configuration inheritance (not implemented yet).
@@ -248,7 +248,7 @@ protected:
/// purposes.
CfgMgr();
- /// @brief virtual desctructor
+ /// @brief virtual destructor
virtual ~CfgMgr();
/// @brief a container for IPv6 subnets.
diff --git a/src/lib/dhcpsrv/dbaccess_parser.h b/src/lib/dhcpsrv/dbaccess_parser.h
index 140f11d..53e3f81 100644
--- a/src/lib/dhcpsrv/dbaccess_parser.h
+++ b/src/lib/dhcpsrv/dbaccess_parser.h
@@ -41,7 +41,7 @@ public:
/// strings.
///
/// Only the "type" sub-element is mandatory: the remaining sub-elements
-/// depend on the datbase chosen.
+/// depend on the database chosen.
class DbAccessParser: public DhcpConfigParser {
public:
/// @brief Keyword and associated value
@@ -115,7 +115,7 @@ protected:
return (values_);
}
- /// @brief Construct dbtabase access string
+ /// @brief Construct database access string
///
/// Constructs the database access string from the stored parameters.
///
diff --git a/src/lib/dhcpsrv/dhcp_config_parser.h b/src/lib/dhcpsrv/dhcp_config_parser.h
index 44cf519..cb419f8 100644
--- a/src/lib/dhcpsrv/dhcp_config_parser.h
+++ b/src/lib/dhcpsrv/dhcp_config_parser.h
@@ -65,7 +65,7 @@ class DhcpConfigParser {
//@{
private:
- // Private construtor and assignment operator assures that nobody
+ // Private constructor and assignment operator assures that nobody
// will be able to copy or assign a parser. There are no defined
// bodies for them.
DhcpConfigParser(const DhcpConfigParser& source);
diff --git a/src/lib/dhcpsrv/dhcpsrv_messages.mes b/src/lib/dhcpsrv/dhcpsrv_messages.mes
index 21a7c79..9b8a0ce 100644
--- a/src/lib/dhcpsrv/dhcpsrv_messages.mes
+++ b/src/lib/dhcpsrv/dhcpsrv_messages.mes
@@ -215,7 +215,7 @@ with the specified address to the MySQL backend 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.
+the committal may not include a write to disk.
% DHCPSRV_MYSQL_DB opening MySQL lease database: %1
This informational message is logged when a DHCP server (either V4 or
diff --git a/src/lib/dhcpsrv/key_from_key.h b/src/lib/dhcpsrv/key_from_key.h
new file mode 100644
index 0000000..4fb9ddb
--- /dev/null
+++ b/src/lib/dhcpsrv/key_from_key.h
@@ -0,0 +1,82 @@
+// Copyright (C) 2013 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 KEY_FROM_KEY_H
+#define KEY_FROM_KEY_H
+
+#include <functional>
+
+namespace isc {
+namespace dhcp {
+
+/// @brief Utility class which cascades two key extractors.
+///
+/// The key extractor (a.k.a. key extraction class) is used by the
+/// key-based indices to obtain the indexing keys from the elements of
+/// a multi_index_container. The standard key extractors can be used
+/// to retrieve indexing key values by accessing members or methods
+/// exposed by the elements (objects or structures) stored in a
+/// multi_index_container. For example, if a container holds objects
+/// of type A, then the public members of object A or its accessors can
+/// be used by the standard extractor classes such as "member" or
+/// "const_mem_fun" respectively. Assume more complex scenario, where
+/// multi_index_container holds objects of a type A, object A exposes
+/// its public member B, which in turn exposes the accessor function
+/// returning object C. One may want to use the value C (e.g. integer)
+/// to index objects A in the container. This can't be solved by using
+/// standard key extractors because object C is nested in B and thus
+/// it is not directly accessible from A. However, it is possible
+/// to specify two distinct key extractors, one used to extract value
+/// C from B, another one to extract value B from A. These two extractors
+/// can be then wrapped by another key extractor which can be used
+/// to obtain index key C from object A. This key extractor is implemented
+/// as a functor class. The functor calls functors specified as
+/// template parameters to retrieve the index value from the cascaded
+/// structure.
+///
+/// @tparam KeyExtractor1 extractor used to extract the key value from
+/// the object containing it.
+/// @tparam KeyExtractor2 extractor used to extract the nested object
+/// containing a key.
+template<typename KeyExtractor1, typename KeyExtractor2>
+class KeyFromKeyExtractor {
+public:
+ typedef typename KeyExtractor1::result_type result_type;
+
+ /// @brief Constructor.
+ KeyFromKeyExtractor()
+ : key1_(KeyExtractor1()), key2_(KeyExtractor2()) { };
+
+ /// @brief Extract key value from the object hierarchy.
+ ///
+ /// @param arg the key value.
+ ///
+ /// @tparam key value type.
+ template<typename T>
+ result_type operator() (T& arg) const {
+ return (key1_(key2_(arg)));
+ }
+private:
+ /// Key Extractor used to extract the key value from the
+ /// object containing it.
+ KeyExtractor1 key1_;
+ /// Key Extractor used to extract the nested object
+ /// containing a key.
+ KeyExtractor2 key2_;
+};
+
+} // end of isc::dhcp namespace
+} // end of isc namespace
+
+#endif // KEY_FROM_KEY_H
diff --git a/src/lib/dhcpsrv/lease_mgr.h b/src/lib/dhcpsrv/lease_mgr.h
index e6aaa51..b6f7001 100644
--- a/src/lib/dhcpsrv/lease_mgr.h
+++ b/src/lib/dhcpsrv/lease_mgr.h
@@ -44,7 +44,7 @@
/// There are no intermediate plans to implement DHCPv4 failover
/// (draft-ietf-dhc-failover-12.txt). Currently (Oct. 2012) the DHCPv6 failover
/// is being defined in DHC WG in IETF (draft-ietf-dhcpv6-failover-requirements,
-/// draft-ietf-dhcpv6-dailover-design), but the work is not advanced enough
+/// draft-ietf-dhcpv6-failover-design), but the work is not advanced enough
/// for implementation plans yet. v4 failover requires additional parameters
/// to be kept with a lease. It is likely that v6 failover will require similar
/// fields. Such implementation will require database schema extension.
@@ -477,7 +477,7 @@ public:
/// @brief Returns existing IPv6 lease for a given IPv6 address.
///
/// For a given address, we assume that there will be only one lease.
- /// The assumtion here is that there will not be site or link-local
+ /// The assumption here is that there will not be site or link-local
/// addresses used, so there is no way of having address duplication.
///
/// @param addr address of the searched lease
diff --git a/src/lib/dhcpsrv/memfile_lease_mgr.cc b/src/lib/dhcpsrv/memfile_lease_mgr.cc
index e5846eb..713d625 100644
--- a/src/lib/dhcpsrv/memfile_lease_mgr.cc
+++ b/src/lib/dhcpsrv/memfile_lease_mgr.cc
@@ -56,7 +56,9 @@ Lease4Ptr Memfile_LeaseMgr::getLease4(const isc::asiolink::IOAddress& addr) cons
LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL,
DHCPSRV_MEMFILE_GET_ADDR4).arg(addr.toText());
- Lease4Storage::iterator l = storage4_.find(addr);
+ typedef Lease4Storage::nth_index<0>::type SearchIndex;
+ const SearchIndex& idx = storage4_.get<0>();
+ Lease4Storage::iterator l = idx.find(addr);
if (l == storage4_.end()) {
return (Lease4Ptr());
} else {
@@ -77,16 +79,22 @@ Lease4Ptr Memfile_LeaseMgr::getLease4(const HWAddr& hwaddr,
DHCPSRV_MEMFILE_GET_SUBID_HWADDR).arg(subnet_id)
.arg(hwaddr.toText());
- Lease4Storage::iterator l;
- for (l = storage4_.begin(); l != storage4_.end(); ++l) {
- if ( ((*l)->hwaddr_ == hwaddr.hwaddr_) &&
- ((*l)->subnet_id_ == subnet_id)) {
- return (*l);
- }
+ // We are going to use index #1 of the multi index container.
+ // We define SearchIndex locally in this function because
+ // currently only this function uses this index.
+ typedef Lease4Storage::nth_index<1>::type SearchIndex;
+ // Get the index.
+ const SearchIndex& idx = storage4_.get<1>();
+ // Try to find the lease using HWAddr and subnet id.
+ SearchIndex::const_iterator lease =
+ idx.find(boost::make_tuple(hwaddr.hwaddr_, subnet_id));
+ // Lease was not found. Return empty pointer to the caller.
+ if (lease == idx.end()) {
+ return Lease4Ptr();
}
- // not found
- return (Lease4Ptr());
+ // Lease was found. Return it to the caller.
+ return (*lease);
}
Lease4Collection Memfile_LeaseMgr::getLease4(const ClientId& clientid) const {
@@ -100,16 +108,22 @@ Lease4Ptr Memfile_LeaseMgr::getLease4(const ClientId& client_id,
LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL,
DHCPSRV_MEMFILE_GET_SUBID_CLIENTID).arg(subnet_id)
.arg(client_id.toText());
- Lease4Storage::iterator l;
- for (l = storage4_.begin(); l != storage4_.end(); ++l) {
- if ( (*(*l)->client_id_ == client_id) &&
- ((*l)->subnet_id_ == subnet_id)) {
- return (*l);
- }
- }
- // not found
- return (Lease4Ptr());
+ // We are going to use index #2 of the multi index container.
+ // We define SearchIndex locally in this function because
+ // currently only this function uses this index.
+ typedef Lease4Storage::nth_index<2>::type SearchIndex;
+ // Get the index.
+ const SearchIndex& idx = storage4_.get<2>();
+ // Try to get the lease using client id and subnet id.
+ SearchIndex::const_iterator lease =
+ idx.find(boost::make_tuple(client_id.getClientId(), subnet_id));
+ // Lease was not found. Return empty pointer to the caller.
+ if (lease == idx.end()) {
+ return Lease4Ptr();
+ }
+ // Lease was found. Return it to the caller.
+ return (*lease);
}
Lease6Ptr Memfile_LeaseMgr::getLease6(
@@ -139,15 +153,21 @@ Lease6Ptr Memfile_LeaseMgr::getLease6(const DUID& duid, uint32_t iaid,
DHCPSRV_MEMFILE_GET_IAID_SUBID_DUID)
.arg(iaid).arg(subnet_id).arg(duid.toText());
- /// @todo: Slow, naive implementation. Write it using additional indexes
- for (Lease6Storage::iterator l = storage6_.begin(); l != storage6_.end(); ++l) {
- if ( (*((*l)->duid_) == duid) &&
- ( (*l)->iaid_ == iaid) &&
- ( (*l)->subnet_id_ == subnet_id)) {
- return (*l);
- }
+ // We are going to use index #1 of the multi index container.
+ // We define SearchIndex locally in this function because
+ // currently only this function uses this index.
+ typedef Lease6Storage::nth_index<1>::type SearchIndex;
+ // Get the index.
+ const SearchIndex& idx = storage6_.get<1>();
+ // Try to get the lease using the DUID, IAID and Subnet ID.
+ SearchIndex::const_iterator lease =
+ idx.find(boost::make_tuple(duid.getDuid(), iaid, subnet_id));
+ // Lease was not found. Return empty pointer.
+ if (lease == idx.end()) {
+ return (Lease6Ptr());
}
- return (Lease6Ptr());
+ // Lease was found, return it to the caller.
+ return (*lease);
}
void Memfile_LeaseMgr::updateLease4(const Lease4Ptr& lease) {
diff --git a/src/lib/dhcpsrv/memfile_lease_mgr.h b/src/lib/dhcpsrv/memfile_lease_mgr.h
index 81e5fe3..4ac7536 100644
--- a/src/lib/dhcpsrv/memfile_lease_mgr.h
+++ b/src/lib/dhcpsrv/memfile_lease_mgr.h
@@ -1,4 +1,4 @@
-// Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2012-2013 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
@@ -16,12 +16,14 @@
#define MEMFILE_LEASE_MGR_H
#include <dhcp/hwaddr.h>
+#include <dhcpsrv/key_from_key.h>
#include <dhcpsrv/lease_mgr.h>
#include <boost/multi_index/indexed_by.hpp>
#include <boost/multi_index/member.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index_container.hpp>
+#include <boost/multi_index/composite_key.hpp>
namespace isc {
namespace dhcp {
@@ -220,29 +222,108 @@ public:
protected:
- typedef boost::multi_index_container< // this is a multi-index container...
- Lease6Ptr, // it will hold shared_ptr to leases6
- boost::multi_index::indexed_by< // and will be sorted by
- // IPv6 address that are unique. That particular key is a member
- // of the Lease6 structure, is of type IOAddress and can be accessed
- // by doing &Lease6::addr_
+ // This is a multi-index container, which holds elements that can
+ // be accessed using different search indexes.
+ typedef boost::multi_index_container<
+ // It holds pointers to Lease6 objects.
+ Lease6Ptr,
+ boost::multi_index::indexed_by<
+ // Specification of the first index starts here.
+ // This index sorts leases by IPv6 addresses represented as
+ // IOAddress objects.
boost::multi_index::ordered_unique<
boost::multi_index::member<Lease, isc::asiolink::IOAddress, &Lease::addr_>
+ >,
+
+ // Specification of the second index starts here.
+ boost::multi_index::ordered_unique<
+ // This is a composite index that will be used to search for
+ // the lease using three attributes: DUID, IAID, Subnet Id.
+ boost::multi_index::composite_key<
+ Lease6,
+ // The DUID value can't be directly accessed from the Lease6
+ // object because it is wrapped with the DUID object (actually
+ // pointer to this object). Therefore we need to use
+ // KeyFromKeyExtractor class to extract the DUID value from
+ // this cascaded structure.
+ KeyFromKeyExtractor<
+ // The value of the DUID is accessed by the getDuid() method
+ // from the DUID object.
+ boost::multi_index::const_mem_fun<DUID, std::vector<uint8_t>,
+ &DUID::getDuid>,
+ // The DUID object is stored in the duid_ member of the
+ // Lease6 object.
+ boost::multi_index::member<Lease6, DuidPtr, &Lease6::duid_>
+ >,
+ // The two other ingredients of this index are IAID and
+ // subnet id.
+ boost::multi_index::member<Lease6, uint32_t, &Lease6::iaid_>,
+ boost::multi_index::member<Lease, SubnetID, &Lease::subnet_id_>
+ >
>
>
- > Lease6Storage; // Let the whole contraption be called Lease6Storage.
-
- typedef boost::multi_index_container< // this is a multi-index container...
- Lease4Ptr, // it will hold shared_ptr to leases6
- boost::multi_index::indexed_by< // and will be sorted by
- // IPv6 address that are unique. That particular key is a member
- // of the Lease6 structure, is of type IOAddress and can be accessed
- // by doing &Lease6::addr_
+ > Lease6Storage; // Specify the type name of this container.
+
+ // This is a multi-index container, which holds elements that can
+ // be accessed using different search indexes.
+ typedef boost::multi_index_container<
+ // It holds pointers to Lease4 objects.
+ Lease4Ptr,
+ // Specification of search indexes starts here.
+ boost::multi_index::indexed_by<
+ // Specification of the first index starts here.
+ // This index sorts leases by IPv4 addresses represented as
+ // IOAddress objects.
boost::multi_index::ordered_unique<
+ // The IPv4 address are held in addr_ members that belong to
+ // Lease class.
boost::multi_index::member<Lease, isc::asiolink::IOAddress, &Lease::addr_>
+ >,
+
+ // Specification of the second index starts here.
+ boost::multi_index::ordered_unique<
+ // This is a composite index that combines two attributes of the
+ // Lease4 object: hardware address and subnet id.
+ boost::multi_index::composite_key<
+ Lease4,
+ // The hardware address is held in the hwaddr_ member of the
+ // Lease4 object.
+ boost::multi_index::member<Lease4, std::vector<uint8_t>,
+ &Lease4::hwaddr_>,
+ // The subnet id is held in the subnet_id_ member of Lease4
+ // class. Note that the subnet_id_ is defined in the base
+ // class (Lease) so we have to point to this class rather
+ // than derived class: Lease4.
+ boost::multi_index::member<Lease, SubnetID, &Lease::subnet_id_>
+ >
+ >,
+
+ // Specification of the third index starts here.
+ boost::multi_index::ordered_unique<
+ // This is a composite index that uses two values to search for a
+ // lease: client id and subnet id.
+ boost::multi_index::composite_key<
+ Lease4,
+ // The client id value is not directly accessible through the
+ // Lease4 object as it is wrapped with the ClientIdPtr object.
+ // Therefore we use the KeyFromKeyExtractor class to access
+ // client id through this cascaded structure. The client id
+ // is used as an index value.
+ KeyFromKeyExtractor<
+ // Specify that the vector holding client id value can be obtained
+ // from the ClientId object.
+ boost::multi_index::const_mem_fun<ClientId, std::vector<uint8_t>,
+ &ClientId::getClientId>,
+ // Specify that the ClientId object (actually pointer to it) can
+ // be accessed by the client_id_ member of Lease4 class.
+ boost::multi_index::member<Lease4, ClientIdPtr, &Lease4::client_id_>
+ >,
+ // The subnet id is accessed through the subnet_id_ member.
+ boost::multi_index::member<Lease, uint32_t, &Lease::subnet_id_>
+ >
>
>
- > Lease4Storage; // Let the whole contraption be called Lease6Storage.
+ > Lease4Storage; // Specify the type name for this container.
/// @brief stores IPv4 leases
Lease4Storage storage4_;
diff --git a/src/lib/dhcpsrv/mysql_lease_mgr.cc b/src/lib/dhcpsrv/mysql_lease_mgr.cc
index 6b6cde5..4b5c1e1 100644
--- a/src/lib/dhcpsrv/mysql_lease_mgr.cc
+++ b/src/lib/dhcpsrv/mysql_lease_mgr.cc
@@ -21,7 +21,7 @@
#include <dhcpsrv/mysql_lease_mgr.h>
#include <boost/static_assert.hpp>
-#include <mysql/mysqld_error.h>
+#include <mysqld_error.h>
#include <iostream>
#include <iomanip>
@@ -289,7 +289,7 @@ public:
memset(hwaddr_buffer_, 0, sizeof(hwaddr_buffer_));
memset(client_id_buffer_, 0, sizeof(client_id_buffer_));
std::fill(&error_[0], &error_[LEASE_COLUMNS], MLM_FALSE);
-
+
// Set the column names (for error messages)
columns_[0] = "address";
columns_[1] = "hwaddr";
@@ -536,7 +536,7 @@ public:
memset(addr6_buffer_, 0, sizeof(addr6_buffer_));
memset(duid_buffer_, 0, sizeof(duid_buffer_));
std::fill(&error_[0], &error_[LEASE_COLUMNS], MLM_FALSE);
-
+
// Set the column names (for error messages)
columns_[0] = "address";
columns_[1] = "duid";
@@ -809,7 +809,7 @@ private:
// schema.
// Note: arrays are declared fixed length for speed of creation
std::string addr6_; ///< String form of address
- char addr6_buffer_[ADDRESS6_TEXT_MAX_LEN + 1]; ///< Character
+ char addr6_buffer_[ADDRESS6_TEXT_MAX_LEN + 1]; ///< Character
///< array form of V6 address
unsigned long addr6_length_; ///< Length of the address
MYSQL_BIND bind_[LEASE_COLUMNS]; ///< Bind array
@@ -831,7 +831,7 @@ private:
/// @brief Fetch and Release MySQL Results
///
-/// When a MySQL statement is exected, to fetch the results the function
+/// When a MySQL statement is expected, to fetch the results the function
/// mysql_stmt_fetch() must be called. As well as getting data, this
/// allocates internal state. Subsequent calls to mysql_stmt_fetch can be
/// made, but when all the data is retrieved, mysql_stmt_free_result must be
@@ -870,17 +870,10 @@ private:
MYSQL_STMT* statement_; ///< Statement for which results are freed
};
-
// MySqlLeaseMgr Constructor and Destructor
-MySqlLeaseMgr::MySqlLeaseMgr(const LeaseMgr::ParameterMap& parameters)
- : LeaseMgr(parameters), mysql_(NULL) {
-
- // Allocate context for MySQL - it is destroyed in the destructor.
- mysql_ = mysql_init(NULL);
- if (mysql_ == NULL) {
- isc_throw(DbOpenError, "unable to initialize MySQL");
- }
+MySqlLeaseMgr::MySqlLeaseMgr(const LeaseMgr::ParameterMap& parameters)
+ : LeaseMgr(parameters) {
// Open the database.
openDatabase();
@@ -916,9 +909,8 @@ MySqlLeaseMgr::~MySqlLeaseMgr() {
}
}
- // Close the database
- mysql_close(mysql_);
- mysql_ = NULL;
+ // There is no need to close the database in this destructor: it is
+ // closed in the destructor of the mysql_ member variable.
}
@@ -970,7 +962,7 @@ MySqlLeaseMgr::convertFromDatabaseTime(const MYSQL_TIME& expire,
expire_tm.tm_hour = expire.hour;
expire_tm.tm_min = expire.minute;
expire_tm.tm_sec = expire.second;
- expire_tm.tm_isdst = -1; // Let the system work out about DST
+ expire_tm.tm_isdst = -1; // Let the system work out about DST
// Convert to local time
cltt = mktime(&expire_tm) - valid_lifetime;
@@ -1022,7 +1014,7 @@ MySqlLeaseMgr::openDatabase() {
}
// Set options for the connection:
- //
+ //
// Automatic reconnection: after a period of inactivity, the client will
// disconnect from the database. This option causes it to automatically
// reconnect when another operation is about to be done.
@@ -1088,7 +1080,7 @@ MySqlLeaseMgr::prepareStatements() {
// Allocate space for all statements
statements_.clear();
statements_.resize(NUM_STATEMENTS, NULL);
-
+
text_statements_.clear();
text_statements_.resize(NUM_STATEMENTS, std::string(""));
diff --git a/src/lib/dhcpsrv/mysql_lease_mgr.h b/src/lib/dhcpsrv/mysql_lease_mgr.h
index 62f4435..6d8eb8c 100644
--- a/src/lib/dhcpsrv/mysql_lease_mgr.h
+++ b/src/lib/dhcpsrv/mysql_lease_mgr.h
@@ -19,13 +19,62 @@
#include <dhcpsrv/lease_mgr.h>
#include <boost/scoped_ptr.hpp>
-#include <mysql/mysql.h>
+#include <boost/utility.hpp>
+#include <mysql.h>
#include <time.h>
namespace isc {
namespace dhcp {
+/// @brief MySQL Handle Holder
+///
+/// Small RAII object for safer initialization, will close the database
+/// connection upon destruction. This means that if an exception is thrown
+/// during database initialization, resources allocated to the database are
+/// guaranteed to be freed.
+///
+/// It makes no sense to copy an object of this class. After the copy, both
+/// objects would contain pointers to the same MySql context object. The
+/// destruction of one would invalid the context in the remaining object.
+/// For this reason, the class is declared noncopyable.
+class MySqlHolder : public boost::noncopyable {
+public:
+
+ /// @brief Constructor
+ ///
+ /// Initialize MySql and store the associated context object.
+ ///
+ /// @throw DbOpenError Unable to initialize MySql handle.
+ MySqlHolder() : mysql_(mysql_init(NULL)) {
+ if (mysql_ == NULL) {
+ isc_throw(DbOpenError, "unable to initialize MySQL");
+ }
+ }
+
+ /// @brief Destructor
+ ///
+ /// Frees up resources allocated by the initialization of MySql.
+ ~MySqlHolder() {
+ if (mysql_ != NULL) {
+ mysql_close(mysql_);
+ }
+ // The library itself shouldn't be needed anymore
+ mysql_library_end();
+ }
+
+ /// @brief Conversion Operator
+ ///
+ /// Allows the MySqlHolder object to be passed as the context argument to
+ /// mysql_xxx functions.
+ operator MYSQL*() const {
+ return (mysql_);
+ }
+
+private:
+ MYSQL* mysql_; ///< Initialization context
+};
+
// Define the current database schema values
const uint32_t CURRENT_VERSION_VERSION = 1;
@@ -192,7 +241,7 @@ public:
/// @brief Returns existing IPv6 lease for a given IPv6 address.
///
/// For a given address, we assume that there will be only one lease.
- /// The assumtion here is that there will not be site or link-local
+ /// The assumption here is that there will not be site or link-local
/// addresses used, so there is no way of having address duplication.
///
/// @param addr address of the searched lease
@@ -379,7 +428,7 @@ public:
/// @param cltt Reference to location where client last transmit time
/// is put.
static
- void convertFromDatabaseTime(const MYSQL_TIME& expire,
+ void convertFromDatabaseTime(const MYSQL_TIME& expire,
uint32_t valid_lifetime, time_t& cltt);
///@}
@@ -616,7 +665,7 @@ private:
/// declare them as "mutable".)
boost::scoped_ptr<MySqlLease4Exchange> exchange4_; ///< Exchange object
boost::scoped_ptr<MySqlLease6Exchange> exchange6_; ///< Exchange object
- MYSQL* mysql_; ///< MySQL context object
+ MySqlHolder mysql_;
std::vector<MYSQL_STMT*> statements_; ///< Prepared statements
std::vector<std::string> text_statements_; ///< Raw text of statements
};
diff --git a/src/lib/dhcpsrv/pool.cc b/src/lib/dhcpsrv/pool.cc
index 7b8a4ea..7104c61 100644
--- a/src/lib/dhcpsrv/pool.cc
+++ b/src/lib/dhcpsrv/pool.cc
@@ -1,4 +1,4 @@
-// Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2012-2013 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
@@ -64,7 +64,7 @@ Pool4::Pool4(const isc::asiolink::IOAddress& prefix,
Pool6::Pool6(Pool6Type type, const isc::asiolink::IOAddress& first,
const isc::asiolink::IOAddress& last)
- :Pool(first, last), type_(type), prefix_len_(0) {
+ :Pool(first, last), type_(type) {
// check if specified address boundaries are sane
if (!first.isV6() || !last.isV6()) {
@@ -95,16 +95,15 @@ Pool6::Pool6(Pool6Type type, const isc::asiolink::IOAddress& first,
Pool6::Pool6(Pool6Type type, const isc::asiolink::IOAddress& prefix,
uint8_t prefix_len)
:Pool(prefix, IOAddress("::")),
- type_(type), prefix_len_(prefix_len) {
+ type_(type) {
// check if the prefix is sane
if (!prefix.isV6()) {
isc_throw(BadValue, "Invalid Pool6 address boundaries: not IPv6");
}
- // 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) {
+ // check if the prefix length is sane
+ if (prefix_len == 0 || prefix_len > 128) {
isc_throw(BadValue, "Invalid prefix length");
}
diff --git a/src/lib/dhcpsrv/pool.h b/src/lib/dhcpsrv/pool.h
index e8dc3e3..e0a6f3c 100644
--- a/src/lib/dhcpsrv/pool.h
+++ b/src/lib/dhcpsrv/pool.h
@@ -1,4 +1,4 @@
-// Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2012-2013 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
@@ -168,9 +168,6 @@ private:
/// @brief defines a pool type
Pool6Type type_;
- /// @brief prefix length
- /// used by TYPE_PD only (zeroed for other types)
- uint8_t prefix_len_;
};
/// @brief a pointer an IPv6 Pool
diff --git a/src/lib/dhcpsrv/subnet.h b/src/lib/dhcpsrv/subnet.h
index cf29450..5a16647 100644
--- a/src/lib/dhcpsrv/subnet.h
+++ b/src/lib/dhcpsrv/subnet.h
@@ -24,6 +24,7 @@
#include <asiolink/io_address.h>
#include <dhcp/option.h>
+#include <dhcpsrv/key_from_key.h>
#include <dhcpsrv/option_space_container.h>
#include <dhcpsrv/pool.h>
#include <dhcpsrv/triplet.h>
@@ -82,55 +83,6 @@ public:
/// A pointer to option descriptor.
typedef boost::shared_ptr<OptionDescriptor> OptionDescriptorPtr;
- /// @brief Extractor class to extract key with another key.
- ///
- /// This class solves the problem of accessing index key values
- /// that are stored in objects nested in other objects.
- /// Each OptionDescriptor structure contains the OptionPtr object.
- /// The value retured by one of its accessors (getType) is used
- /// as an indexing value in the multi_index_container defined below.
- /// There is no easy way to mark that value returned by Option::getType
- /// should be an index of this multi_index_container. There are standard
- /// key extractors such as 'member' or 'mem_fun' but they are not
- /// sufficient here. The former can be used to mark that member of
- /// the structure that is held in the container should be used as an
- /// indexing value. The latter can be used if the indexing value is
- /// a product of the class being held in the container. In this complex
- /// scenario when the indexing value is a product of the function that
- /// is wrapped by the structure, this new extractor template has to be
- /// defined. The template class provides a 'chain' of two extractors
- /// to access the value returned by nested object and to use it as
- /// indexing value.
- /// For some more examples of complex keys see:
- /// http://www.cs.brown.edu/~jwicks/boost/libs/multi_index/doc/index.html
- ///
- /// @tparam KeyExtractor1 extractor used to access data in
- /// OptionDescriptor::option
- /// @tparam KeyExtractor2 extractor used to access
- /// OptionDescriptor::option member.
- template<typename KeyExtractor1, typename KeyExtractor2>
- class KeyFromKey {
- public:
- typedef typename KeyExtractor1::result_type result_type;
-
- /// @brief Constructor.
- KeyFromKey()
- : key1_(KeyExtractor1()), key2_(KeyExtractor2()) { };
-
- /// @brief Extract key with another key.
- ///
- /// @param arg the key value.
- ///
- /// @tparam key value type.
- template<typename T>
- result_type operator() (T& arg) const {
- return (key1_(key2_(arg)));
- }
- private:
- KeyExtractor1 key1_; ///< key 1.
- KeyExtractor2 key2_; ///< key 2.
- };
-
/// @brief Multi index container for DHCP option descriptors.
///
/// This container comprises three indexes to access option
@@ -169,10 +121,10 @@ public:
boost::multi_index::sequenced<>,
// Start definition of index #1.
boost::multi_index::hashed_non_unique<
- // KeyFromKey is the index key extractor that allows accessing
- // option type being held by the OptionPtr through
+ // KeyFromKeyExtractor is the index key extractor that allows
+ // accessing option type being held by the OptionPtr through
// OptionDescriptor structure.
- KeyFromKey<
+ KeyFromKeyExtractor<
// Use option type as the index key. The type is held
// in OptionPtr object so we have to call Option::getType
// to retrieve this key for each element.
@@ -208,7 +160,7 @@ public:
typedef OptionContainer::nth_index<1>::type OptionContainerTypeIndex;
/// Pair of iterators to represent the range of options having the
/// same option type value. The first element in this pair represents
- /// the begining of the range, the second element represents the end.
+ /// the beginning of the range, the second element represents the end.
typedef std::pair<OptionContainerTypeIndex::const_iterator,
OptionContainerTypeIndex::const_iterator> OptionContainerTypeRange;
/// Type of the index #2 - option persistency flag.
diff --git a/src/lib/dhcpsrv/tests/lease_mgr_factory_unittest.cc b/src/lib/dhcpsrv/tests/lease_mgr_factory_unittest.cc
index 9924476..e439c87 100644
--- a/src/lib/dhcpsrv/tests/lease_mgr_factory_unittest.cc
+++ b/src/lib/dhcpsrv/tests/lease_mgr_factory_unittest.cc
@@ -149,7 +149,7 @@ TEST_F(LeaseMgrFactoryTest, redactAccessStringEmptyPassword) {
/// @brief redactConfigString test - no password
///
/// Checks that the redacted configuration string excludes the password if there
-/// was no password to begion with.
+/// was no password to begin with.
TEST_F(LeaseMgrFactoryTest, redactAccessStringNoPassword) {
LeaseMgr::ParameterMap parameters =
diff --git a/src/lib/dhcpsrv/tests/lease_mgr_unittest.cc b/src/lib/dhcpsrv/tests/lease_mgr_unittest.cc
index 8d8c7f8..6103a96 100644
--- a/src/lib/dhcpsrv/tests/lease_mgr_unittest.cc
+++ b/src/lib/dhcpsrv/tests/lease_mgr_unittest.cc
@@ -474,7 +474,7 @@ TEST(Lease6, Lease6Constructor) {
/// is followed by the reverse check on operator!=().
TEST(Lease6, OperatorEquals) {
- // check a variety of addressemas with different bits set.
+ // check a variety of addresses with different bits set.
const IOAddress addr("2001:db8:1::456");
uint8_t duid_array[] = {0, 1, 2, 3, 4, 5, 6, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf};
DuidPtr duid(new DUID(duid_array, sizeof(duid_array)));
diff --git a/src/lib/dhcpsrv/tests/mysql_lease_mgr_unittest.cc b/src/lib/dhcpsrv/tests/mysql_lease_mgr_unittest.cc
index ddb2645..2ae6a49 100644
--- a/src/lib/dhcpsrv/tests/mysql_lease_mgr_unittest.cc
+++ b/src/lib/dhcpsrv/tests/mysql_lease_mgr_unittest.cc
@@ -118,21 +118,16 @@ validConnectionString() {
// There is no error checking in this code: if something fails, one of the
// tests will (should) fall over.
void destroySchema() {
- // Initialise
- MYSQL handle;
- (void) mysql_init(&handle);
+ MySqlHolder mysql;
// Open database
- (void) mysql_real_connect(&handle, "localhost", "keatest",
+ (void) mysql_real_connect(mysql, "localhost", "keatest",
"keatest", "keatest", 0, NULL, 0);
// Get rid of everything in it.
for (int i = 0; destroy_statement[i] != NULL; ++i) {
- (void) mysql_query(&handle, destroy_statement[i]);
+ (void) mysql_query(mysql, destroy_statement[i]);
}
-
- // ... and close
- (void) mysql_close(&handle);
}
// @brief Create the Schema
@@ -142,21 +137,16 @@ void destroySchema() {
// There is no error checking in this code: if it fails, one of the tests
// will fall over.
void createSchema() {
- // Initialise
- MYSQL handle;
- (void) mysql_init(&handle);
+ MySqlHolder mysql;
// Open database
- (void) mysql_real_connect(&handle, "localhost", "keatest",
+ (void) mysql_real_connect(mysql, "localhost", "keatest",
"keatest", "keatest", 0, NULL, 0);
// Execute creation statements.
for (int i = 0; create_statement[i] != NULL; ++i) {
- (void) mysql_query(&handle, create_statement[i]);
+ (void) mysql_query(mysql, create_statement[i]);
}
-
- // ... and close
- (void) mysql_close(&handle);
}
/// @brief Test fixture class for testing MySQL Lease Manager
diff --git a/src/lib/dhcpsrv/tests/run_unittests.cc b/src/lib/dhcpsrv/tests/run_unittests.cc
index d333a6f..dcc0204 100644
--- a/src/lib/dhcpsrv/tests/run_unittests.cc
+++ b/src/lib/dhcpsrv/tests/run_unittests.cc
@@ -12,6 +12,7 @@
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
+#include <config.h>
#include <log/logger_support.h>
#include <gtest/gtest.h>
diff --git a/src/lib/dhcpsrv/tests/subnet_unittest.cc b/src/lib/dhcpsrv/tests/subnet_unittest.cc
index 9f06c89..1f0ef8b 100644
--- a/src/lib/dhcpsrv/tests/subnet_unittest.cc
+++ b/src/lib/dhcpsrv/tests/subnet_unittest.cc
@@ -398,7 +398,7 @@ TEST(Subnet6Test, addPersistentOption) {
// those that server sends to clients regardless if they ask
// for them or not. We pick 3 out of 10 options and mark them
// non-persistent and 7 other options persistent.
- // Code values: 102, 105 and 108 are divisable by 3
+ // Code values: 102, 105 and 108 are divisible by 3
// and options with these codes will be flagged non-persistent.
// Options with other codes will be flagged persistent.
bool persistent = (code % 3) ? true : false;
diff --git a/src/lib/dns/gen-rdatacode.py.in b/src/lib/dns/gen-rdatacode.py.in
index 7ea2ae5..0d946b9 100755
--- a/src/lib/dns/gen-rdatacode.py.in
+++ b/src/lib/dns/gen-rdatacode.py.in
@@ -33,6 +33,7 @@ import sys
# Example:
# new_rdata_factory_users = [('a', 'in'), ('a', 'ch'), ('soa', 'generic')]
new_rdata_factory_users = [('a', 'in'), ('aaaa', 'in'),
+ ('afsdb', 'generic'),
('cname', 'generic'),
('dlv', 'generic'),
('dname', 'generic'),
@@ -186,7 +187,7 @@ def import_definitions(classcode2txt, typecode2txt, typeandclass):
# list is processed in the same order on all systems. The resulting
# files should compile regardless of the order in which the components
# are included but... Having a fixed order for the directories should
- # eliminate system-dependent problems. (Note that the drectory names
+ # eliminate system-dependent problems. (Note that the directory names
# in BIND 10 are ASCII, so the order should be locale-independent.)
dirlist = os.listdir('@srcdir@/rdata')
dirlist.sort()
diff --git a/src/lib/dns/messagerenderer.cc b/src/lib/dns/messagerenderer.cc
index 0cd11ce..bc11cb4 100644
--- a/src/lib/dns/messagerenderer.cc
+++ b/src/lib/dns/messagerenderer.cc
@@ -182,7 +182,7 @@ struct MessageRenderer::MessageRendererImpl {
size_t hash, bool case_sensitive) const
{
// Find a matching entry, if any. We use some heuristics here: often
- // the same name appers consecutively (like repeating the same owner
+ // the same name appears consecutively (like repeating the same owner
// name for a single RRset), so in case there's a collision in the
// bucket it will be more likely to find it in the tail side of the
// bucket.
diff --git a/src/lib/dns/python/tests/message_python_test.py b/src/lib/dns/python/tests/message_python_test.py
index bf39a83..996ef89 100644
--- a/src/lib/dns/python/tests/message_python_test.py
+++ b/src/lib/dns/python/tests/message_python_test.py
@@ -520,7 +520,7 @@ test.example.com. 3600 IN A 192.0.2.2
data = read_wire_data("message_fromWire22.wire")
self.assertRaises(DNSMessageFORMERR, self.p.from_wire, data[:-1])
- def test_from_wire_combind_rrs(self):
+ def test_from_wire_combined_rrs(self):
factoryFromFile(self.p, "message_fromWire19.wire")
rrset = self.p.get_section(Message.SECTION_ANSWER)[0]
self.assertEqual(RRType("A"), rrset.get_type())
diff --git a/src/lib/dns/python/tests/rrset_collection_python_test.py b/src/lib/dns/python/tests/rrset_collection_python_test.py
index 1bbbc80..20d147f 100644
--- a/src/lib/dns/python/tests/rrset_collection_python_test.py
+++ b/src/lib/dns/python/tests/rrset_collection_python_test.py
@@ -17,7 +17,7 @@ import os
import unittest
from pydnspp import *
-# This should refer to the testdata diretory for the C++ tests.
+# This should refer to the testdata directory for the C++ tests.
TESTDATA_DIR = os.environ["TESTDATA_PATH"].split(':')[0]
class RRsetCollectionBaseTest(unittest.TestCase):
diff --git a/src/lib/dns/rdata/generic/afsdb_18.cc b/src/lib/dns/rdata/generic/afsdb_18.cc
index ec76ee0..cf6a35c 100644
--- a/src/lib/dns/rdata/generic/afsdb_18.cc
+++ b/src/lib/dns/rdata/generic/afsdb_18.cc
@@ -1,4 +1,4 @@
-// Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2011-2013 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
@@ -25,9 +25,12 @@
#include <boost/lexical_cast.hpp>
+#include <dns/rdata/generic/detail/lexer_util.h>
+
using namespace std;
+using boost::lexical_cast;
using namespace isc::util;
-using namespace isc::util::str;
+using isc::dns::rdata::generic::detail::createNameFromLexer;
// BEGIN_ISC_NAMESPACE
// BEGIN_RDATA_NAMESPACE
@@ -52,24 +55,58 @@ using namespace isc::util::str;
AFSDB::AFSDB(const std::string& afsdb_str) :
subtype_(0), server_(Name::ROOT_NAME())
{
- istringstream iss(afsdb_str);
-
try {
- const uint32_t subtype = tokenToNum<int32_t, 16>(getToken(iss));
- const Name servername(getToken(iss));
+ std::istringstream ss(afsdb_str);
+ MasterLexer lexer;
+ lexer.pushSource(ss);
- if (!iss.eof()) {
- isc_throw(InvalidRdataText, "Unexpected input for AFSDB"
- "RDATA: " << afsdb_str);
+ createFromLexer(lexer, NULL);
+
+ if (lexer.getNextToken().getType() != MasterToken::END_OF_FILE) {
+ isc_throw(InvalidRdataText, "extra input text for AFSDB: "
+ << afsdb_str);
}
+ } catch (const MasterLexer::LexerError& ex) {
+ isc_throw(InvalidRdataText, "Failed to construct AFSDB from '" <<
+ afsdb_str << "': " << ex.what());
+ }
+}
- subtype_ = subtype;
- server_ = servername;
+/// \brief Constructor with a context of MasterLexer.
+///
+/// The \c lexer should point to the beginning of valid textual representation
+/// of an AFSDB RDATA. The SERVER field can be non-absolute if \c origin
+/// is non-NULL, in which case \c origin is used to make it absolute.
+/// It must not be represented as a quoted string.
+///
+/// The SUBTYPE field must be a valid decimal representation of an
+/// unsigned 16-bit integer.
+///
+/// \throw MasterLexer::LexerError General parsing error such as missing field.
+/// \throw Other Exceptions from the Name and RRTTL constructors if
+/// construction of textual fields as these objects fail.
+///
+/// \param lexer A \c MasterLexer object parsing a master file for the
+/// RDATA to be created
+/// \param origin If non NULL, specifies the origin of SERVER when it
+/// is non-absolute.
+AFSDB::AFSDB(MasterLexer& lexer, const Name* origin,
+ MasterLoader::Options, MasterLoaderCallbacks&) :
+ subtype_(0), server_(".")
+{
+ createFromLexer(lexer, origin);
+}
- } catch (const StringTokenError& ste) {
- isc_throw(InvalidRdataText, "Invalid AFSDB text: " <<
- ste.what() << ": " << afsdb_str);
+void
+AFSDB::createFromLexer(MasterLexer& lexer, const Name* origin)
+{
+ const uint32_t num = lexer.getNextToken(MasterToken::NUMBER).getNumber();
+ if (num > 65535) {
+ isc_throw(InvalidRdataText, "Invalid AFSDB subtype: " << num);
}
+ subtype_ = static_cast<uint16_t>(num);
+
+ server_ = createNameFromLexer(lexer, origin);
}
/// \brief Constructor from wire-format data.
@@ -111,7 +148,7 @@ AFSDB::operator=(const AFSDB& source) {
/// \return A \c string object that represents the \c AFSDB object.
string
AFSDB::toText() const {
- return (boost::lexical_cast<string>(subtype_) + " " + server_.toText());
+ return (lexical_cast<string>(subtype_) + " " + server_.toText());
}
/// \brief Render the \c AFSDB in the wire format without name compression.
diff --git a/src/lib/dns/rdata/generic/afsdb_18.h b/src/lib/dns/rdata/generic/afsdb_18.h
index 4a46775..359a6e4 100644
--- a/src/lib/dns/rdata/generic/afsdb_18.h
+++ b/src/lib/dns/rdata/generic/afsdb_18.h
@@ -1,4 +1,4 @@
-// Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2011-2013 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
@@ -61,6 +61,8 @@ public:
uint16_t getSubtype() const;
private:
+ void createFromLexer(MasterLexer& lexer, const Name* origin);
+
uint16_t subtype_;
Name server_;
};
diff --git a/src/lib/dns/tests/rdata_afsdb_unittest.cc b/src/lib/dns/tests/rdata_afsdb_unittest.cc
index 9bb64b7..9a628cd 100644
--- a/src/lib/dns/tests/rdata_afsdb_unittest.cc
+++ b/src/lib/dns/tests/rdata_afsdb_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2011-2013 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
@@ -34,7 +34,7 @@ using namespace isc::dns::rdata;
const char* const afsdb_text = "1 afsdb.example.com.";
const char* const afsdb_text2 = "0 root.example.com.";
const char* const too_long_label("012345678901234567890123456789"
- "0123456789012345678901234567890123");
+ "0123456789012345678901234567890123.");
namespace {
class Rdata_AFSDB_Test : public RdataTest {
@@ -68,9 +68,17 @@ TEST_F(Rdata_AFSDB_Test, badText) {
// number of fields (must be 2) is incorrect
EXPECT_THROW(const generic::AFSDB rdata_afsdb("10 afsdb. example.com."),
InvalidRdataText);
+ // No origin and relative
+ EXPECT_THROW(const generic::AFSDB rdata_afsdb("1 afsdb.example.com"),
+ MissingNameOrigin);
// bad name
EXPECT_THROW(const generic::AFSDB rdata_afsdb("1 afsdb.example.com." +
- string(too_long_label)), TooLongLabel);
+ string(too_long_label)), TooLongLabel);
+}
+
+TEST_F(Rdata_AFSDB_Test, copy) {
+ const generic::AFSDB rdata_afsdb2(rdata_afsdb);
+ EXPECT_EQ(0, rdata_afsdb.compare(rdata_afsdb2));
}
TEST_F(Rdata_AFSDB_Test, assignment) {
@@ -119,9 +127,24 @@ TEST_F(Rdata_AFSDB_Test, createFromLexer) {
*test::createRdataUsingLexer(RRType::AFSDB(), RRClass::IN(),
afsdb_text)));
+ // test::createRdataUsingLexer() constructs relative to
+ // "example.org." origin.
+ generic::AFSDB tmp = generic::AFSDB("1 afsdb2.example.org.");
+ EXPECT_EQ(0, tmp.compare(
+ *test::createRdataUsingLexer(RRType::AFSDB(), RRClass::IN(),
+ "1 afsdb2")));
+
// Exceptions cause NULL to be returned.
EXPECT_FALSE(test::createRdataUsingLexer(RRType::AFSDB(), RRClass::IN(),
"1root.example.com."));
+
+ // 65536 is larger than maximum possible subtype
+ EXPECT_FALSE(test::createRdataUsingLexer(RRType::AFSDB(), RRClass::IN(),
+ "65536 afsdb.example.com."));
+
+ // Extra text at end of line
+ EXPECT_FALSE(test::createRdataUsingLexer(RRType::AFSDB(), RRClass::IN(),
+ "1 afsdb.example.com. extra."));
}
TEST_F(Rdata_AFSDB_Test, toWireBuffer) {
@@ -197,9 +220,9 @@ TEST_F(Rdata_AFSDB_Test, compare) {
EXPECT_EQ(0, rdata_afsdb.compare(generic::AFSDB("1 "
"AFSDB.example.com.")));
- const generic::AFSDB small1("10 afsdb.example.com");
- const generic::AFSDB large1("65535 afsdb.example.com");
- const generic::AFSDB large2("256 afsdb.example.com");
+ const generic::AFSDB small1("10 afsdb.example.com.");
+ const generic::AFSDB large1("65535 afsdb.example.com.");
+ const generic::AFSDB large2("256 afsdb.example.com.");
// confirm these are compared as unsigned values
EXPECT_GT(0, rdata_afsdb.compare(large1));
@@ -210,7 +233,7 @@ TEST_F(Rdata_AFSDB_Test, compare) {
EXPECT_LT(0, large2.compare(small1));
// another AFSDB whose server name is larger than that of rdata_afsdb.
- const generic::AFSDB large3("256 zzzzz.example.com");
+ const generic::AFSDB large3("256 zzzzz.example.com.");
EXPECT_GT(0, large2.compare(large3));
EXPECT_LT(0, large3.compare(large2));
diff --git a/src/lib/dns/tests/testdata/rrset_toWire2 b/src/lib/dns/tests/testdata/rrset_toWire2
index 601de8b..ca6483f 100644
--- a/src/lib/dns/tests/testdata/rrset_toWire2
+++ b/src/lib/dns/tests/testdata/rrset_toWire2
@@ -18,7 +18,7 @@
# RDATA: 192.0.2.1
c0 00 02 01
#
-# 2nd RR: the owner name is compresed
+# 2nd RR: the owner name is compressed
c0 00
00 01 00 01
00 00 0e 10
diff --git a/src/lib/log/logger_manager.cc b/src/lib/log/logger_manager.cc
index 77893d0..c3e3125 100644
--- a/src/lib/log/logger_manager.cc
+++ b/src/lib/log/logger_manager.cc
@@ -121,19 +121,17 @@ LoggerManager::init(const std::string& root, isc::log::Severity severity,
// Check if there were any duplicate message IDs in the default dictionary
// and if so, log them. Log using the logging facility logger.
- vector<string>& duplicates = MessageInitializer::getDuplicates();
+ const vector<string>& duplicates = MessageInitializer::getDuplicates();
if (!duplicates.empty()) {
- // There are duplicates present. This will be listed in alphabetic
- // order of message ID, so they need to be sorted. This list itself may
- // contain duplicates; if so, the message ID is listed as many times as
+ // There are duplicates present. This list itself may contain
+ // duplicates; if so, the message ID is listed as many times as
// there are duplicates.
- sort(duplicates.begin(), duplicates.end());
- for (vector<string>::iterator i = duplicates.begin();
+ for (vector<string>::const_iterator i = duplicates.begin();
i != duplicates.end(); ++i) {
LOG_WARN(logger, LOG_DUPLICATE_MESSAGE_ID).arg(*i);
}
-
+ MessageInitializer::clearDuplicates();
}
// Replace any messages with local ones (if given)
diff --git a/src/lib/log/logger_manager.h b/src/lib/log/logger_manager.h
index da49ae4..a444aea 100644
--- a/src/lib/log/logger_manager.h
+++ b/src/lib/log/logger_manager.h
@@ -100,6 +100,9 @@ public:
/// an attempt is made to log a message before this is function is called,
/// the results will be dependent on the underlying logging package.
///
+ /// Any duplicate log IDs encountered are reported as warning, after which
+ /// the global duplicates vector is cleared
+ ///
/// \param root Name of the root logger. This should be set to the name of
/// the program.
/// \param severity Severity at which to log
diff --git a/src/lib/log/logger_unittest_support.cc b/src/lib/log/logger_unittest_support.cc
index 4f02b07..9dc90fd 100644
--- a/src/lib/log/logger_unittest_support.cc
+++ b/src/lib/log/logger_unittest_support.cc
@@ -43,7 +43,7 @@ b10LoggerSeverity(isc::log::Severity defseverity) {
return (defseverity);
}
-// Get the debug level. This is defined by the envornment variable
+// Get the debug level. This is defined by the environment variable
// B10_LOGGER_DBGLEVEL. If not defined, a default value passed to the function
// is returned.
int
diff --git a/src/lib/log/message_initializer.cc b/src/lib/log/message_initializer.cc
index 3dd5da7..3277047 100644
--- a/src/lib/log/message_initializer.cc
+++ b/src/lib/log/message_initializer.cc
@@ -42,7 +42,13 @@ size_t& getIndex() {
return (index);
}
+// Return the duplicates singleton version (non-const for local use)
+std::vector<std::string>&
+getNonConstDuplicates() {
+ static std::vector<std::string> duplicates;
+ return (duplicates);
}
+} // end unnamed namespace
namespace isc {
@@ -67,7 +73,7 @@ MessageInitializer::getPendingCount() {
// into the global dictionary.
void
-MessageInitializer::loadDictionary() {
+MessageInitializer::loadDictionary(bool ignore_duplicates) {
MessageDictionary& global = MessageDictionary::globalDictionary();
for (size_t i = 0; i < getIndex(); ++i) {
@@ -75,8 +81,8 @@ MessageInitializer::loadDictionary() {
// Append the IDs in the list just loaded (the "repeats") to the
// global list of duplicate IDs.
- if (!repeats.empty()) {
- std::vector<std::string>& duplicates = getDuplicates();
+ if (!ignore_duplicates && !repeats.empty()) {
+ std::vector<std::string>& duplicates = getNonConstDuplicates();
duplicates.insert(duplicates.end(), repeats.begin(),
repeats.end());
}
@@ -88,11 +94,16 @@ MessageInitializer::loadDictionary() {
getIndex() = 0;
}
-// Return reference to duplicate array
+// Return reference to duplicates vector
+const std::vector<std::string>&
+MessageInitializer::getDuplicates() {
+ return (getNonConstDuplicates());
+}
-std::vector<std::string>& MessageInitializer::getDuplicates() {
- static std::vector<std::string> duplicates;
- return (duplicates);
+// Clear the duplicates vector
+void
+MessageInitializer::clearDuplicates() {
+ getNonConstDuplicates().clear();
}
} // namespace log
diff --git a/src/lib/log/message_initializer.h b/src/lib/log/message_initializer.h
index 3be973d..ae67484 100644
--- a/src/lib/log/message_initializer.h
+++ b/src/lib/log/message_initializer.h
@@ -43,6 +43,9 @@ namespace log {
/// All that needed is for the module containing the definitions to be
/// included in the execution unit.
///
+/// Dynamically loaded modules should call the initializer as well on the
+/// moment they are instantiated.
+///
/// To avoid static initialization fiasco problems, the initialization is
/// carried out in two stages:
/// - The constructor adds a pointer to the values array to a pre-defined array
@@ -93,7 +96,11 @@ public:
/// Loops through the internal array of pointers to message arrays
/// and adds the messages to the internal dictionary. This is called
/// during run-time initialization.
- static void loadDictionary();
+ ///
+ /// \param ignore_duplicates If true, duplicate IDs, and IDs already
+ /// loaded, are ignored instead of stored in the global duplicates
+ /// vector.
+ static void loadDictionary(bool ignore_duplicates = false);
/// \brief Return Duplicates
///
@@ -102,7 +109,12 @@ public:
///
/// \return List of duplicate message IDs when the global dictionary was
/// loaded. Note that the duplicates list itself may contain duplicates.
- static std::vector<std::string>& getDuplicates();
+ static const std::vector<std::string>& getDuplicates();
+
+ /// \brief Clear the static duplicates vector
+ ///
+ /// Empties the vector returned by getDuplicates()
+ static void clearDuplicates();
};
} // namespace log
diff --git a/src/lib/log/tests/logger_example.cc b/src/lib/log/tests/logger_example.cc
index 08c9084..4b20429 100644
--- a/src/lib/log/tests/logger_example.cc
+++ b/src/lib/log/tests/logger_example.cc
@@ -134,7 +134,7 @@ int main(int argc, char** argv) {
// the parsing starts (console output for the BIND 10 root logger). This
// is included in the logging specifications UNLESS the first switch on
// the command line is a "-l" flag starting a new logger. To track this,
- // the "sw_found" flag is set when a switch is completey processed. The
+ // the "sw_found" flag is set when a switch is completely processed. The
// processing of "-l" will only add information for a previous logger to
// the list if this flag is set.
while ((option = getopt(argc, argv, "hc:d:f:l:m:s:y:z:")) != -1) {
diff --git a/src/lib/log/tests/message_dictionary_unittest.cc b/src/lib/log/tests/message_dictionary_unittest.cc
index b8bded3..065641a 100644
--- a/src/lib/log/tests/message_dictionary_unittest.cc
+++ b/src/lib/log/tests/message_dictionary_unittest.cc
@@ -189,9 +189,8 @@ TEST_F(MessageDictionaryTest, GlobalTest) {
// new symbol.
TEST_F(MessageDictionaryTest, GlobalLoadTest) {
- vector<string>& duplicates = MessageInitializer::getDuplicates();
- ASSERT_EQ(1, duplicates.size());
- EXPECT_EQ(string("LOG_DUPLICATE_NAMESPACE"), duplicates[0]);
+ // There were duplicates but the vector should be cleared in init() now
+ ASSERT_EQ(0, MessageInitializer::getDuplicates().size());
string text = MessageDictionary::globalDictionary().getText("NEWSYM");
EXPECT_EQ(string("new symbol added"), text);
diff --git a/src/lib/log/tests/message_initializer_1_unittest.cc b/src/lib/log/tests/message_initializer_1_unittest.cc
index 994174c..fea6033 100644
--- a/src/lib/log/tests/message_initializer_1_unittest.cc
+++ b/src/lib/log/tests/message_initializer_1_unittest.cc
@@ -77,3 +77,37 @@ TEST(MessageInitializerTest1, MessageTest) {
EXPECT_EQ(string("global message five"), global.getText("GLOBAL5"));
EXPECT_EQ(string("global message six"), global.getText("GLOBAL6"));
}
+
+TEST(MessageInitializerTest1, Duplicates) {
+ // Original set should not have dupes
+ ASSERT_EQ(0, MessageInitializer::getDuplicates().size());
+
+ // This just defines 1, but we'll add it a number of times
+ const char* dupe[] = {
+ "DUPE", "dupe",
+ NULL
+ };
+ const MessageInitializer init_message_initializer_unittest_1(dupe);
+ const MessageInitializer init_message_initializer_unittest_2(dupe);
+
+ MessageInitializer::loadDictionary();
+ // Should be a dupe now
+ ASSERT_EQ(1, MessageInitializer::getDuplicates().size());
+
+ // clear them
+ MessageInitializer::clearDuplicates();
+ ASSERT_EQ(0, MessageInitializer::getDuplicates().size());
+
+ // Do it again to make sure, let's explicitely provide false now
+ const MessageInitializer init_message_initializer_unittest_3(dupe);
+ MessageInitializer::loadDictionary(false);
+ ASSERT_EQ(1, MessageInitializer::getDuplicates().size());
+
+ // Loading with ignore_duplicates=true should result in no (reported)
+ // dupes
+ MessageInitializer::clearDuplicates();
+ ASSERT_EQ(0, MessageInitializer::getDuplicates().size());
+ const MessageInitializer init_message_initializer_unittest_4(dupe);
+ MessageInitializer::loadDictionary(true);
+ ASSERT_EQ(0, MessageInitializer::getDuplicates().size());
+}
diff --git a/src/lib/nsas/TODO b/src/lib/nsas/TODO
index 4a20690..92ca0bb 100644
--- a/src/lib/nsas/TODO
+++ b/src/lib/nsas/TODO
@@ -21,7 +21,7 @@ Long term:
tricky, though, because we need to be thread safe. There seems to be
solution to use weak_ptr inside the hash_table instead of shared_ptr and
catch the exception inside get() (and getOrAdd) and delete the dead pointer.
-* Better way to dispatch all calbacks in a list is needed. We take them out of
+* Better way to dispatch all callbacks in a list is needed. We take them out of
the list and dispatch them one by one. This is wrong because when an
exception happens inside the callback, we lose the ones not dispatched yet.
diff --git a/src/lib/nsas/address_request_callback.h b/src/lib/nsas/address_request_callback.h
index 457c587..e43dfe2 100644
--- a/src/lib/nsas/address_request_callback.h
+++ b/src/lib/nsas/address_request_callback.h
@@ -42,7 +42,7 @@ namespace nsas {
class AddressRequestCallback {
public:
- /// Default constructor, copy contructor and assignment operator
+ /// Default constructor, copy constructor and assignment operator
/// are implicitly present and are OK.
/// \brief Virtual Destructor
diff --git a/src/lib/nsas/nameserver_entry.h b/src/lib/nsas/nameserver_entry.h
index 77a640d..3ffdf10 100644
--- a/src/lib/nsas/nameserver_entry.h
+++ b/src/lib/nsas/nameserver_entry.h
@@ -168,8 +168,8 @@ public:
* \short Update RTT of an address.
*
* This is similar to updateAddressRTTAtIndex, but you pass the address,
- * not it's index. Passing the index might be unsafe, because the position
- * of the address or the cound of addresses may change in time.
+ * not its index. Passing the index might be unsafe, because the position
+ * of the address or the count of addresses may change in time.
*
* \param rtt Round-Trip Time
* \param address The address whose RTT should be updated.
@@ -235,7 +235,7 @@ public:
* \param resolver Who to ask.
* \param callback The callback.
* \param family Which addresses are interesting to the caller. This does
- * not change which adresses are requested, but the callback might
+ * not change which addresses are requested, but the callback might
* be executed when at last one requested type is available (eg. not
* waiting for the other one).
* \return The state the entry is currently in. It can return UNREACHABLE
diff --git a/src/lib/nsas/tests/hash_unittest.cc b/src/lib/nsas/tests/hash_unittest.cc
index 251e4b1..f71d4b3 100644
--- a/src/lib/nsas/tests/hash_unittest.cc
+++ b/src/lib/nsas/tests/hash_unittest.cc
@@ -76,7 +76,7 @@ TEST_F(HashTest, Algorithm) {
const int size = HASHTABLE_DEFAULT_SIZE; // Size of the hash table
Hash hash(size, 255, false);// Hashing algorithm object with seed
// randomisation disabled
- string base = "alphabeta"; // Base of the names to behashed
+ string base = "alphabeta"; // Base of the names to be hashed
vector<uint32_t> values; // Results stored here
// Generate hash values
diff --git a/src/lib/nsas/tests/zone_entry_unittest.cc b/src/lib/nsas/tests/zone_entry_unittest.cc
index 1982299..74b0c8a 100644
--- a/src/lib/nsas/tests/zone_entry_unittest.cc
+++ b/src/lib/nsas/tests/zone_entry_unittest.cc
@@ -101,7 +101,7 @@ protected:
/**
* \short Function returning a new zone.
*
- * Convenience funcion, just creating a new zone, to shorten the code.
+ * Convenience function, just creating a new zone, to shorten the code.
*/
boost::shared_ptr<InheritedZoneEntry> getZone() {
return (boost::shared_ptr<InheritedZoneEntry>(new InheritedZoneEntry(
@@ -372,7 +372,7 @@ TEST_F(ZoneEntryTest, CallbacksAOnly) {
EXPECT_TRUE(IOAddress("192.0.2.1").equals(
callback_->successes_[1].getAddress()));
EXPECT_EQ(1, callback_->unreachable_count_);
- // Everything arriwed, so we are ready
+ // Everything arrived, so we are ready
EXPECT_EQ(Fetchable::READY, zone->getState());
// Try asking something more and see it asks no more
zone->addCallback(callback_, V4_ONLY);
diff --git a/src/lib/nsas/zone_entry.h b/src/lib/nsas/zone_entry.h
index 7e5ab5b..b0c26c3 100644
--- a/src/lib/nsas/zone_entry.h
+++ b/src/lib/nsas/zone_entry.h
@@ -125,7 +125,7 @@ protected:
// Which nameservers didn't have any of our callbacks yet
std::set<NameserverPtr> nameservers_not_asked_;
/*
- * Callbacks. For each fimily type one vector, so we can process
+ * Callbacks. For each family type one vector, so we can process
* them separately.
*/
std::vector<boost::shared_ptr<AddressRequestCallback> >
@@ -139,7 +139,7 @@ private:
/**
* \short Process all the callbacks that can be processed
*
- * The purpose of this funtion is to ask all nameservers for their IP
+ * The purpose of this function is to ask all nameservers for their IP
* addresses and execute all callbacks that can be executed. It is
* called whenever new callback appears and there's a chance it could
* be answered or when new information is available (list of nameservers,
diff --git a/src/lib/python/bind10_config.py.in b/src/lib/python/bind10_config.py.in
index 9cd8d66..7ef660b 100644
--- a/src/lib/python/bind10_config.py.in
+++ b/src/lib/python/bind10_config.py.in
@@ -24,11 +24,13 @@ def reload():
global PLUGIN_PATHS
global PREFIX
global LIBEXECPATH
+ global SYSCONFPATH
BIND10_MSGQ_SOCKET_FILE = os.path.join("@localstatedir@",
"@PACKAGE_NAME@",
"msgq_socket").replace("${prefix}",
"@prefix@")
PREFIX = "@prefix@"
+ SYSCONFPATH="@sysconfdir@/@PACKAGE@".replace('${prefix}', PREFIX)
# B10_FROM_SOURCE is set in the environment for internal tests and
# an experimental run without installagion. In that case we need to
@@ -49,6 +51,9 @@ def reload():
# When "FROM_SOURCE", it lists the directories where the programs are
# built so that when BIND 10 is experimentally started on the source
# tree the programs in the tree (not installed ones) will be used.
+ # SYSCONFPATH: Path where the system-wide configuration files are
+ # stored (e.g. <prefix>/var/<package name>). This value is *not*
+ # overwritten if B10_FROM_SOURCE is specified.
#
# B10_FROM_SOURCE_LOCALSTATEDIR is specifically intended to be used for
# tests where we want to use various types of configuration within the test
diff --git a/src/lib/python/isc/bind10/sockcreator.py b/src/lib/python/isc/bind10/sockcreator.py
index db9e6c5..bb4250a 100644
--- a/src/lib/python/isc/bind10/sockcreator.py
+++ b/src/lib/python/isc/bind10/sockcreator.py
@@ -26,7 +26,7 @@ from libutil_io_python import recv_fd
logger = isc.log.Logger("init")
"""
-Module that comunicates with the privileged socket creator (b10-sockcreator).
+Module that communicates with the privileged socket creator (b10-sockcreator).
"""
class CreatorError(Exception):
@@ -251,7 +251,7 @@ class Creator(Parser):
"""Function used before running a program that needs to run as a
different user."""
# Put us into a separate process group so we don't get
- # SIGINT signals on Ctrl-C (b10-init will shut everthing down by
+ # SIGINT signals on Ctrl-C (b10-init will shut everything down by
# other means).
os.setpgrp()
diff --git a/src/lib/python/isc/bind10/tests/component_test.py b/src/lib/python/isc/bind10/tests/component_test.py
index adc035e..0fde13e 100644
--- a/src/lib/python/isc/bind10/tests/component_test.py
+++ b/src/lib/python/isc/bind10/tests/component_test.py
@@ -513,7 +513,7 @@ class ComponentTests(InitUtils, unittest.TestCase):
def test_pid_not_running(self):
"""
- Test that a componet that is not yet started doesn't have a PID.
+ Test that a component that is not yet started doesn't have a PID.
But it won't fail if asked for and return None.
"""
for component_type in [Component,
diff --git a/src/lib/python/isc/bind10/tests/socket_cache_test.py b/src/lib/python/isc/bind10/tests/socket_cache_test.py
index bbbf776..f713a5c 100644
--- a/src/lib/python/isc/bind10/tests/socket_cache_test.py
+++ b/src/lib/python/isc/bind10/tests/socket_cache_test.py
@@ -72,7 +72,7 @@ class SocketTest(Test):
"""
Check it closes the socket when removed.
"""
- # This should make the refcount 0 and call the descructor
+ # This should make the refcount 0 and call the destructor
# right away
self.__socket = None
self.assertEqual([42], self._closes)
@@ -357,7 +357,7 @@ class SocketCacheTest(Test):
}
self.__cache._live_tokens = set(['t1', 't2', 't3'])
self.assertEqual([], self._closes)
- # We cheat here little bit, the t3 doesn't exist enywhere else, but
+ # We cheat here little bit, the t3 doesn't exist anywhere else, but
# we need to check the app isn't removed too soon and it shouldn't
# matter anywhere else, so we just avoid the tiresome filling in
self.__cache._active_apps = {1: set(['t1', 't3']), 2: set(['t2'])}
diff --git a/src/lib/python/isc/cc/Makefile.am b/src/lib/python/isc/cc/Makefile.am
index f7c5b00..fe7d747 100644
--- a/src/lib/python/isc/cc/Makefile.am
+++ b/src/lib/python/isc/cc/Makefile.am
@@ -7,6 +7,7 @@ pylogmessagedir = $(pyexecdir)/isc/log_messages/
CLEANFILES = $(PYTHON_LOGMSGPKG_DIR)/work/pycc_messages.py
CLEANFILES += $(PYTHON_LOGMSGPKG_DIR)/work/pycc_messages.pyc
+CLEANFILES += $(PYTHON_LOGMSGPKG_DIR)/work/pycc_messages.pyo
EXTRA_DIST = pycc_messages.mes proto_defs.py
diff --git a/src/lib/python/isc/cc/cc_generated/Makefile.am b/src/lib/python/isc/cc/cc_generated/Makefile.am
index 87e49c1..bc8d478 100644
--- a/src/lib/python/isc/cc/cc_generated/Makefile.am
+++ b/src/lib/python/isc/cc/cc_generated/Makefile.am
@@ -26,6 +26,7 @@ CLEANDIRS = __pycache__
CLEANFILES = proto_defs.py __init__.py
CLEANFILES += proto_defs.pyc __init__.pyc
+CLEANFILES += proto_defs.pyo __init__.pyo
clean-local:
rm -rf $(CLEANDIRS)
diff --git a/src/lib/python/isc/cc/data.py b/src/lib/python/isc/cc/data.py
index 636e9a9..3411411 100644
--- a/src/lib/python/isc/cc/data.py
+++ b/src/lib/python/isc/cc/data.py
@@ -217,7 +217,7 @@ def set(element, identifier, value):
id, list_indices = split_identifier_list_indices(id_parts[-1])
if list_indices is None:
- # value can be an empty list or dict, so check for None eplicitely
+ # value can be an empty list or dict, so check for None explicitly
if value is not None:
cur_el[id] = value
else:
@@ -231,7 +231,7 @@ def set(element, identifier, value):
if len(cur_el) <= list_index:
raise DataNotFoundError("List index at " + identifier + " out of range")
cur_el = cur_el[list_index]
- # value can be an empty list or dict, so check for None eplicitely
+ # value can be an empty list or dict, so check for None explicitly
list_index = list_indices[-1]
if type(cur_el) != list:
raise DataTypeError("Element at " + identifier + " is not a list")
diff --git a/src/lib/python/isc/cc/session.py b/src/lib/python/isc/cc/session.py
index 036c078..fced424 100644
--- a/src/lib/python/isc/cc/session.py
+++ b/src/lib/python/isc/cc/session.py
@@ -57,11 +57,11 @@ class Session:
try:
self._socket = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
self._socket.connect(self.socket_file)
- self.sendmsg({ "type": "getlname" })
+ self.sendmsg({ CC_HEADER_TYPE: CC_COMMAND_GET_LNAME })
env, msg = self.recvmsg(False)
if not env:
raise ProtocolError("Could not get local name")
- self._lname = msg["lname"]
+ self._lname = msg[CC_PAYLOAD_LNAME]
if not self._lname:
raise ProtocolError("Could not get local name")
logger.debug(logger.DBGLVL_TRACE_BASIC, PYCC_LNAME_RECEIVED,
@@ -125,9 +125,10 @@ class Session:
if len(self._queue) > 0:
i = 0;
for env, msg in self._queue:
- if seq != None and "reply" in env and seq == env["reply"]:
+ if seq != None and CC_HEADER_REPLY in env and \
+ seq == env[CC_HEADER_REPLY]:
return self._queue.pop(i)
- elif seq == None and "reply" not in env:
+ elif seq == None and CC_HEADER_REPLY not in env:
return self._queue.pop(i)
else:
i = i + 1
@@ -141,7 +142,9 @@ class Session:
if data_length > 0:
env = isc.cc.message.from_wire(data[2:header_length+2])
msg = isc.cc.message.from_wire(data[header_length + 2:])
- if (seq == None and "reply" not in env) or (seq != None and "reply" in env and seq == env["reply"]):
+ if (seq == None and CC_HEADER_REPLY not in env) or \
+ (seq != None and CC_HEADER_REPLY in env and
+ seq == env[CC_HEADER_REPLY]):
return env, msg
else:
self._queue.append((env,msg))
@@ -248,18 +251,18 @@ class Session:
self._sequence += 1
return self._sequence
- def group_subscribe(self, group, instance = "*"):
+ def group_subscribe(self, group, instance=CC_INSTANCE_WILDCARD):
self.sendmsg({
- "type": "subscribe",
- "group": group,
- "instance": instance,
+ CC_HEADER_TYPE: CC_COMMAND_SUBSCRIBE,
+ CC_HEADER_GROUP: group,
+ CC_HEADER_INSTANCE: instance,
})
- def group_unsubscribe(self, group, instance = "*"):
+ def group_unsubscribe(self, group, instance=CC_INSTANCE_WILDCARD):
self.sendmsg({
- "type": "unsubscribe",
- "group": group,
- "instance": instance,
+ CC_HEADER_TYPE: CC_COMMAND_UNSUBSCRIBE,
+ CC_HEADER_GROUP: group,
+ CC_HEADER_INSTANCE: instance,
})
def group_sendmsg(self, msg, group, instance=CC_INSTANCE_WILDCARD,
@@ -308,13 +311,13 @@ class Session:
def group_reply(self, routing, msg):
seq = self._next_sequence()
self.sendmsg({
- "type": "send",
- "from": self._lname,
- "to": routing["from"],
- "group": routing["group"],
- "instance": routing["instance"],
- "seq": seq,
- "reply": routing["seq"],
+ CC_HEADER_TYPE: CC_COMMAND_SEND,
+ CC_HEADER_FROM: self._lname,
+ CC_HEADER_TO: routing[CC_HEADER_FROM],
+ CC_HEADER_GROUP: routing[CC_HEADER_GROUP],
+ CC_HEADER_INSTANCE: routing[CC_HEADER_INSTANCE],
+ CC_HEADER_SEQ: seq,
+ CC_HEADER_REPLY: routing[CC_HEADER_SEQ],
}, isc.cc.message.to_wire(msg))
return seq
diff --git a/src/lib/python/isc/cc/tests/session_test.py b/src/lib/python/isc/cc/tests/session_test.py
index 8de1e96..65afb6c 100644
--- a/src/lib/python/isc/cc/tests/session_test.py
+++ b/src/lib/python/isc/cc/tests/session_test.py
@@ -257,7 +257,7 @@ class testSession(unittest.TestCase):
self.assertEqual({"hello": "a"}, msg)
self.assertFalse(sess.has_queued_msgs())
- # ask for a differe sequence number reply (that doesn't exist)
+ # ask for a different sequence number reply (that doesn't exist)
# then ask for the one that is there
self.assertFalse(sess.has_queued_msgs())
sess._socket.addrecv({'to': 'someone', 'reply': 1}, {"hello": "a"})
@@ -270,7 +270,7 @@ class testSession(unittest.TestCase):
self.assertEqual({"hello": "a"}, msg)
self.assertFalse(sess.has_queued_msgs())
- # ask for a differe sequence number reply (that doesn't exist)
+ # ask for a different sequence number reply (that doesn't exist)
# then ask for any message
self.assertFalse(sess.has_queued_msgs())
sess._socket.addrecv({'to': 'someone', 'reply': 1}, {"hello": "a"})
@@ -285,7 +285,7 @@ class testSession(unittest.TestCase):
#print("sending message {'to': 'someone', 'reply': 1}, {'hello': 'a'}")
- # ask for a differe sequence number reply (that doesn't exist)
+ # ask for a different sequence number reply (that doesn't exist)
# send a new message, ask for specific message (get the first)
# then ask for any message (get the second)
self.assertFalse(sess.has_queued_msgs())
diff --git a/src/lib/python/isc/config/ccsession.py b/src/lib/python/isc/config/ccsession.py
index a5858a7..c6d9791 100644
--- a/src/lib/python/isc/config/ccsession.py
+++ b/src/lib/python/isc/config/ccsession.py
@@ -82,22 +82,22 @@ def parse_answer(msg):
containing an error message"""
if type(msg) != dict:
raise ModuleCCSessionError("Answer message is not a dict: " + str(msg))
- if 'result' not in msg:
+ if CC_PAYLOAD_RESULT not in msg:
raise ModuleCCSessionError("answer message does not contain 'result' element")
- elif type(msg['result']) != list:
+ elif type(msg[CC_PAYLOAD_RESULT]) != list:
raise ModuleCCSessionError("wrong result type in answer message")
- elif len(msg['result']) < 1:
+ elif len(msg[CC_PAYLOAD_RESULT]) < 1:
raise ModuleCCSessionError("empty result list in answer message")
- elif type(msg['result'][0]) != int:
+ elif type(msg[CC_PAYLOAD_RESULT][0]) != int:
raise ModuleCCSessionError("wrong rcode type in answer message")
else:
- if len(msg['result']) > 1:
- if (msg['result'][0] != CC_REPLY_SUCCESS and
- type(msg['result'][1]) != str):
+ if len(msg[CC_PAYLOAD_RESULT]) > 1:
+ if (msg[CC_PAYLOAD_RESULT][0] != CC_REPLY_SUCCESS and
+ type(msg[CC_PAYLOAD_RESULT][1]) != str):
raise ModuleCCSessionError("rcode in answer message is non-zero, value is not a string")
- return msg['result'][0], msg['result'][1]
+ return msg[CC_PAYLOAD_RESULT][0], msg[CC_PAYLOAD_RESULT][1]
else:
- return msg['result'][0], None
+ return msg[CC_PAYLOAD_RESULT][0], None
def create_answer(rcode, arg = None):
"""Creates an answer packet for config&commands. rcode must be an
@@ -109,9 +109,9 @@ def create_answer(rcode, arg = None):
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 ] }
+ return { CC_PAYLOAD_RESULT: [ rcode, arg ] }
else:
- return { 'result': [ rcode ] }
+ return { CC_PAYLOAD_RESULT: [ rcode ] }
# 'fixed' commands
"""Fixed names for command and configuration messages"""
@@ -133,7 +133,7 @@ def parse_command(msg):
string. If it is not, this function returns None, None"""
if type(msg) == dict and len(msg.items()) == 1:
cmd, value = msg.popitem()
- if cmd == "command" and type(value) == list:
+ if cmd == CC_PAYLOAD_COMMAND and type(value) == list:
if len(value) == 1 and type(value[0]) == str:
return value[0], None
elif len(value) > 1 and type(value[0]) == str:
@@ -150,7 +150,7 @@ def create_command(command_name, params = None):
cmd = [ command_name ]
if params:
cmd.append(params)
- msg = { 'command': cmd }
+ msg = { CC_PAYLOAD_COMMAND: cmd }
return msg
def default_logconfig_handler(new_config, config_data):
@@ -215,7 +215,7 @@ class ModuleCCSession(ConfigData):
self._session = Session(socket_file)
else:
self._session = cc_session
- self._session.group_subscribe(self._module_name, "*")
+ self._session.group_subscribe(self._module_name, CC_INSTANCE_WILDCARD)
self._remote_module_configs = {}
self._remote_module_callbacks = {}
@@ -228,7 +228,8 @@ class ModuleCCSession(ConfigData):
# If the CC Session obejct has been closed, it returns
# immediately.
if self._session._closed: return
- self._session.group_unsubscribe(self._module_name, "*")
+ self._session.group_unsubscribe(self._module_name,
+ CC_INSTANCE_WILDCARD)
for module_name in self._remote_module_configs:
self._session.group_unsubscribe(module_name)
@@ -294,10 +295,10 @@ class ModuleCCSession(ConfigData):
functions if present. Responds on the channel if the
handler returns a message."""
# should we default to an answer? success-by-default? unhandled error?
- if msg is not None and not 'result' in msg:
+ if msg is not None and not CC_PAYLOAD_RESULT in msg:
answer = None
try:
- module_name = env['group']
+ module_name = env[CC_HEADER_GROUP]
cmd, arg = isc.config.ccsession.parse_command(msg)
if cmd == COMMAND_CONFIG_UPDATE:
new_config = arg
@@ -529,7 +530,7 @@ class ModuleCCSession(ConfigData):
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)
+ # actually works)
reply, rheaders = self._session.group_recvmsg(nonblock=False, seq=seq)
code, value = parse_answer(reply)
if code == CC_REPLY_NO_RECPT:
diff --git a/src/lib/python/isc/config/cfgmgr.py b/src/lib/python/isc/config/cfgmgr.py
index bc24cbb..fe4924c 100644
--- a/src/lib/python/isc/config/cfgmgr.py
+++ b/src/lib/python/isc/config/cfgmgr.py
@@ -28,6 +28,7 @@ import tempfile
import json
import errno
from isc.cc import data
+from isc.cc.proto_defs import *
from isc.config import ccsession, config_data, module_spec
from isc.util.file import path_search
import bind10_config
@@ -221,7 +222,7 @@ class ConfigManagerData:
class ConfigManager:
"""Creates a configuration manager. The data_path is the path
- to the directory containing the configuraton file,
+ to the directory containing the configuration file,
database_filename points to the configuration file.
If session is set, this will be used as the communication
channel session. If not, a new session will be created.
@@ -443,7 +444,7 @@ class ConfigManager:
# (which is possible solution to the offline configuration problem)
# or when we solve the incorect behaviour here when a config is
# rejected (spying modules don't know it was rejected and some modules
- # might have been commited already).
+ # might have been committed already).
if module_name in self.virtual_modules:
# The module is virtual, so call it to get the answer
try:
@@ -603,7 +604,7 @@ class ConfigManager:
# ignore 'None' value (even though they should not occur)
# and messages that are answers to questions we did
# not ask
- if msg is not None and not 'result' in msg:
+ if msg is not None and not CC_PAYLOAD_RESULT in msg:
answer = self.handle_msg(msg);
# Only respond if there actually is something to respond with
if answer is not None:
diff --git a/src/lib/python/isc/config/tests/ccsession_test.py b/src/lib/python/isc/config/tests/ccsession_test.py
index 3c1c57e..2a2d790 100644
--- a/src/lib/python/isc/config/tests/ccsession_test.py
+++ b/src/lib/python/isc/config/tests/ccsession_test.py
@@ -734,7 +734,7 @@ class TestModuleCCSession(unittest.TestCase):
mccs.check_command()
self.assertEqual(len(fake_session.message_queue), 0)
- def test_ignore_commant_remote_module(self):
+ def test_ignore_command_remote_module(self):
"""
Test that commands for remote modules aren't handled.
Remote module specified by the spec file name.
@@ -742,7 +742,7 @@ class TestModuleCCSession(unittest.TestCase):
self._common_remote_module_test(
self._internal_ignore_command_remote_module)
- def test_ignore_commant_remote_module_by_name(self):
+ def test_ignore_command_remote_module_by_name(self):
"""
Test that commands for remote modules aren't handled.
Remote module specified by its name.
diff --git a/src/lib/python/isc/config/tests/cfgmgr_test.py b/src/lib/python/isc/config/tests/cfgmgr_test.py
index d99fb86..c1fe970 100644
--- a/src/lib/python/isc/config/tests/cfgmgr_test.py
+++ b/src/lib/python/isc/config/tests/cfgmgr_test.py
@@ -527,7 +527,7 @@ class TestConfigManager(unittest.TestCase):
self.fake_session.get_message("Cmdctl", None))
# but if the 'stopping' module is either unknown or not running,
- # no followup message should be sent
+ # no follow-up message should be sent
self._handle_msg_helper({ "command":
[ "stopping",
{ "module_name": "NoSuchModule" } ] },
diff --git a/src/lib/python/isc/datasrc/datasrc.cc b/src/lib/python/isc/datasrc/datasrc.cc
index c183af9..f2cbae3 100644
--- a/src/lib/python/isc/datasrc/datasrc.cc
+++ b/src/lib/python/isc/datasrc/datasrc.cc
@@ -23,6 +23,8 @@
#include <datasrc/sqlite3_accessor.h>
#include <datasrc/zone_loader.h>
+#include <log/message_initializer.h>
+
#include "datasrc.h"
#include "client_python.h"
#include "finder_python.h"
@@ -276,6 +278,8 @@ PyModuleDef iscDataSrc = {
PyMODINIT_FUNC
PyInit_datasrc(void) {
+ isc::log::MessageInitializer::loadDictionary();
+
PyObject* mod = PyModule_Create(&iscDataSrc);
if (mod == NULL) {
return (NULL);
diff --git a/src/lib/python/isc/datasrc/tests/datasrc_test.py b/src/lib/python/isc/datasrc/tests/datasrc_test.py
index abc9739..1ab2148 100644
--- a/src/lib/python/isc/datasrc/tests/datasrc_test.py
+++ b/src/lib/python/isc/datasrc/tests/datasrc_test.py
@@ -261,7 +261,7 @@ class DataSrcClient(unittest.TestCase):
rrets = dsc.get_iterator(isc.dns.Name("example.com"))
# there are more than 80 RRs in this zone... let's just count them
# (already did a full check of the smaller zone above)
- # There are 40 non-RRSIG RRsets and 32 dinstinct RRSIGs.
+ # There are 40 non-RRSIG RRsets and 32 distinct RRSIGs.
self.assertEqual(72, len(list(rrets)))
# same test, but now with explicit False argument for separate_rrs
@@ -593,7 +593,7 @@ class DataSrcUpdater(unittest.TestCase):
self.assertEqual(finder.NXDOMAIN, result)
def test_update_delete_abort(self):
- # we don't do enything with this one, just making sure loading two
+ # we don't do anything with this one, just making sure loading two
# datasources
dsc = isc.datasrc.DataSourceClient("sqlite3", WRITE_ZONE_DB_CONFIG)
diff --git a/src/lib/python/isc/notify/notify_out.py b/src/lib/python/isc/notify/notify_out.py
index d1ec2e9..7ae5665 100644
--- a/src/lib/python/isc/notify/notify_out.py
+++ b/src/lib/python/isc/notify/notify_out.py
@@ -26,6 +26,7 @@ from isc.net import addr
import isc
from isc.log_messages.notify_out_messages import *
from isc.statistics import Counters
+from isc.util.address_formatter import AddressFormatter
logger = isc.log.Logger("notify_out")
@@ -433,13 +434,13 @@ class NotifyOut:
self._notify_next_target(zone_notify_info)
elif event_type == _EVENT_TIMEOUT and zone_notify_info.notify_try_num > 0:
- logger.info(NOTIFY_OUT_TIMEOUT, tgt[0], tgt[1])
+ logger.info(NOTIFY_OUT_TIMEOUT, AddressFormatter(tgt))
tgt = zone_notify_info.get_current_notify_target()
if tgt:
zone_notify_info.notify_try_num += 1
if zone_notify_info.notify_try_num > _MAX_NOTIFY_TRY_NUM:
- logger.warn(NOTIFY_OUT_RETRY_EXCEEDED, tgt[0], tgt[1],
+ logger.warn(NOTIFY_OUT_RETRY_EXCEEDED, AddressFormatter(tgt),
_MAX_NOTIFY_TRY_NUM)
self._notify_next_target(zone_notify_info)
else:
@@ -487,15 +488,14 @@ class NotifyOut:
elif zone_notify_info.get_socket().family == socket.AF_INET6:
self._counters.inc('zones', zone_notify_info.zone_name,
'notifyoutv6')
- logger.info(NOTIFY_OUT_SENDING_NOTIFY, addrinfo[0],
- addrinfo[1])
+ logger.info(NOTIFY_OUT_SENDING_NOTIFY, AddressFormatter(addrinfo))
except (socket.error, addr.InvalidAddress) as err:
- logger.error(NOTIFY_OUT_SOCKET_ERROR, addrinfo[0],
- addrinfo[1], err)
+ logger.error(NOTIFY_OUT_SOCKET_ERROR, AddressFormatter(addrinfo),
+ err)
return False
except addr.InvalidAddress as iae:
- logger.error(NOTIFY_OUT_INVALID_ADDRESS, addrinfo[0],
- addrinfo[1], iae)
+ logger.error(NOTIFY_OUT_INVALID_ADDRESS,
+ AddressFormatter(addrinfo), iae)
return False
return True
@@ -544,40 +544,46 @@ class NotifyOut:
try:
msg.from_wire(msg_data)
if not msg.get_header_flag(Message.HEADERFLAG_QR):
- logger.warn(NOTIFY_OUT_REPLY_QR_NOT_SET, from_addr[0],
- from_addr[1])
+ logger.warn(NOTIFY_OUT_REPLY_QR_NOT_SET,
+ AddressFormatter(from_addr))
return _BAD_QR
if msg.get_qid() != zone_notify_info.notify_msg_id:
- logger.warn(NOTIFY_OUT_REPLY_BAD_QID, from_addr[0],
- from_addr[1], msg.get_qid(),
+ logger.warn(NOTIFY_OUT_REPLY_BAD_QID,
+ AddressFormatter(from_addr), msg.get_qid(),
zone_notify_info.notify_msg_id)
return _BAD_QUERY_ID
question = msg.get_question()[0]
if question.get_name() != Name(zone_notify_info.zone_name):
- logger.warn(NOTIFY_OUT_REPLY_BAD_QUERY_NAME, from_addr[0],
- from_addr[1], question.get_name().to_text(),
+ logger.warn(NOTIFY_OUT_REPLY_BAD_QUERY_NAME,
+ AddressFormatter(from_addr),
+ question.get_name().to_text(),
Name(zone_notify_info.zone_name).to_text())
return _BAD_QUERY_NAME
if msg.get_opcode() != Opcode.NOTIFY:
- logger.warn(NOTIFY_OUT_REPLY_BAD_OPCODE, from_addr[0],
- from_addr[1], msg.get_opcode().to_text())
+ logger.warn(NOTIFY_OUT_REPLY_BAD_OPCODE,
+ AddressFormatter(from_addr),
+ msg.get_opcode().to_text())
return _BAD_OPCODE
except Exception as err:
# We don't care what exception, just report it?
logger.error(NOTIFY_OUT_REPLY_UNCAUGHT_EXCEPTION, err)
return _BAD_REPLY_PACKET
+ logger.debug(logger.DBGLVL_TRACE_BASIC, NOTIFY_OUT_REPLY_RECEIVED,
+ zone_notify_info.zone_name, zone_notify_info.zone_class,
+ from_addr[0], from_addr[1], msg.get_rcode())
+
return _REPLY_OK
def _get_notify_reply(self, sock, tgt_addr):
try:
msg, addr = sock.recvfrom(512)
except socket.error as err:
- logger.error(NOTIFY_OUT_SOCKET_RECV_ERROR, tgt_addr[0],
- tgt_addr[1], err)
+ logger.error(NOTIFY_OUT_SOCKET_RECV_ERROR,
+ AddressFormatter(tgt_addr), err)
return None
return msg
diff --git a/src/lib/python/isc/notify/notify_out_messages.mes b/src/lib/python/isc/notify/notify_out_messages.mes
index 3bc0f38..30fb087 100644
--- a/src/lib/python/isc/notify/notify_out_messages.mes
+++ b/src/lib/python/isc/notify/notify_out_messages.mes
@@ -27,7 +27,7 @@ because notify_out first identifies a list of available zones before
this process. So this means some critical inconsistency in the data
source or software bug.
-% NOTIFY_OUT_INVALID_ADDRESS invalid address %1#%2: %3
+% NOTIFY_OUT_INVALID_ADDRESS invalid address %1: %2
The notify_out library tried to send a notify message to the given
address, but it appears to be an invalid address. The configuration
for secondary nameservers might contain a typographic error, or a
@@ -35,31 +35,36 @@ different BIND 10 module has forgotten to validate its data before
sending this module a notify command. As such, this should normally
not happen, and points to an oversight in a different module.
-% NOTIFY_OUT_REPLY_BAD_OPCODE bad opcode in notify reply from %1#%2: %3
+% NOTIFY_OUT_REPLY_BAD_OPCODE bad opcode in notify reply from %1: %2
The notify_out library sent a notify message to the nameserver at
the given address, but the response did not have the opcode set to
NOTIFY. The opcode in the response is printed. Since there was a
response, no more notifies will be sent to this server for this
notification event.
-% NOTIFY_OUT_REPLY_BAD_QID bad QID in notify reply from %1#%2: got %3, should be %4
+% NOTIFY_OUT_REPLY_BAD_QID bad QID in notify reply from %1: got %2, should be %3
The notify_out library sent a notify message to the nameserver at
the given address, but the query id in the response does not match
the one we sent. Since there was a response, no more notifies will
be sent to this server for this notification event.
-% NOTIFY_OUT_REPLY_BAD_QUERY_NAME bad query name in notify reply from %1#%2: got %3, should be %4
+% NOTIFY_OUT_REPLY_BAD_QUERY_NAME bad query name in notify reply from %1: got %2, should be %3
The notify_out library sent a notify message to the nameserver at
the given address, but the query name in the response does not match
the one we sent. Since there was a response, no more notifies will
be sent to this server for this notification event.
-% NOTIFY_OUT_REPLY_QR_NOT_SET QR flags set to 0 in reply to notify from %1#%2
+% NOTIFY_OUT_REPLY_QR_NOT_SET QR flags set to 0 in reply to notify from %1
The notify_out library sent a notify message to the namesever at the
given address, but the reply did not have the QR bit set to one.
Since there was a response, no more notifies will be sent to this
server for this notification event.
+% NOTIFY_OUT_REPLY_RECEIVED Zone %1/%2: notify response from %3:%4: %5
+The notify_out library sent a notify message to the nameserver at
+the given address, and received a response. Its Rcode will be shown,
+too.
+
% NOTIFY_OUT_REPLY_UNCAUGHT_EXCEPTION uncaught exception: %1
There was an uncaught exception in the handling of a notify reply
message, either in the message parser, or while trying to extract data
@@ -70,27 +75,27 @@ explicitly. Please file a bug report. Since there was a response,
no more notifies will be sent to this server for this notification
event.
-% NOTIFY_OUT_RETRY_EXCEEDED notify to %1#%2: number of retries (%3) exceeded
+% NOTIFY_OUT_RETRY_EXCEEDED notify to %1: number of retries (%2) exceeded
The maximum number of retries for the notify target has been exceeded.
Either the address of the secondary nameserver is wrong, or it is not
responding.
-% NOTIFY_OUT_SENDING_NOTIFY sending notify to %1#%2
+% NOTIFY_OUT_SENDING_NOTIFY sending notify to %1
A notify message is sent to the secondary nameserver at the given
address.
-% NOTIFY_OUT_SOCKET_ERROR socket error sending notify to %1#%2: %3
+% NOTIFY_OUT_SOCKET_ERROR socket error sending notify to %1: %2
There was a network error while trying to send a notify message to
the given address. The address might be unreachable. The socket
error is printed and should provide more information.
-% NOTIFY_OUT_SOCKET_RECV_ERROR socket error reading notify reply from %1#%2: %3
+% NOTIFY_OUT_SOCKET_RECV_ERROR socket error reading notify reply from %1: %2
There was a network error while trying to read a notify reply
message from the given address. The socket error is printed and should
provide more information.
-% NOTIFY_OUT_TIMEOUT retry notify to %1#%2
-The notify message to the given address (noted as address#port) has
+% NOTIFY_OUT_TIMEOUT retry notify to %1
+The notify message to the given address (noted as address:port) has
timed out, and the message will be resent until the max retry limit
is reached.
diff --git a/src/lib/python/isc/server_common/dns_tcp.py b/src/lib/python/isc/server_common/dns_tcp.py
index 9ce94fe..2ab5c8f 100644
--- a/src/lib/python/isc/server_common/dns_tcp.py
+++ b/src/lib/python/isc/server_common/dns_tcp.py
@@ -91,7 +91,7 @@ class DNSTCPSendBuffer:
A Python binary object that corresponds to a part of the TCP
DNS message data starting at the specified position. It may
or may not contain all remaining data from that position.
- If the given position is beyond the end of the enrire data,
+ If the given position is beyond the end of the entire data,
None will be returned.
'''
@@ -277,4 +277,4 @@ class DNSTCPContext:
if self.__sock is None:
return
self.__sock.close()
- self.__sock = None # prevent furhter operation
+ self.__sock = None # prevent further operation
diff --git a/src/lib/python/isc/server_common/tests/tsig_keyring_test.py b/src/lib/python/isc/server_common/tests/tsig_keyring_test.py
index e9a2174..6b9b75c 100644
--- a/src/lib/python/isc/server_common/tests/tsig_keyring_test.py
+++ b/src/lib/python/isc/server_common/tests/tsig_keyring_test.py
@@ -65,7 +65,7 @@ class TSIGKeyRingTest(unittest.TestCase):
def test_initialization(self):
"""
- Test we can initialize and deintialize the keyring. It also
+ Test we can initialize and deinitialize the keyring. It also
tests the interaction with the keyring() function.
"""
# The keyring function raises until initialized
diff --git a/src/lib/python/isc/statistics/counters.py b/src/lib/python/isc/statistics/counters.py
index a459573..279c14b 100644
--- a/src/lib/python/isc/statistics/counters.py
+++ b/src/lib/python/isc/statistics/counters.py
@@ -217,8 +217,8 @@ class Counters():
zones/example.com./ixfrreqv6
zones/example.com./xfrsuccess
zones/example.com./xfrfail
- zones/example.com./latest_ixfr_duration
- zones/example.com./latest_axfr_duration
+ zones/example.com./last_ixfr_duration
+ zones/example.com./last_axfr_duration
ixfr_running
axfr_running
socket/unixdomain/open
@@ -328,7 +328,7 @@ class Counters():
"""Starts a timer which is identified by args and keeps it
running until stop_timer() is called. It acquires a lock to
support multi-threaded use. If the specified timer is already
- started but not yet started, the last start time is
+ started but not yet stopped, the last start time is
overwritten."""
identifier = _concat(*args)
with self._rlock:
diff --git a/src/lib/python/isc/statistics/tests/counters_test.py b/src/lib/python/isc/statistics/tests/counters_test.py
index 6616ec3..5567dda 100644
--- a/src/lib/python/isc/statistics/tests/counters_test.py
+++ b/src/lib/python/isc/statistics/tests/counters_test.py
@@ -197,7 +197,7 @@ class BaseTestCounters():
# for per-zone counters
for name in self.counters._zones_item_list:
args = (self._perzone_prefix, TEST_ZONE_NAME_STR, name)
- if name.find('latest_') == 0 and name.endswith('_duration'):
+ if name.find('last_') == 0 and name.endswith('_duration'):
self.counters.start_timer(*args)
self.counters.stop_timer(*args)
self.assertGreaterEqual(self.counters.get(*args), 0.0)
@@ -278,7 +278,7 @@ class BaseTestCounters():
# setting all counters to zero
for name in self.counters._zones_item_list:
args = (self._perzone_prefix, TEST_ZONE_NAME_STR, name)
- if name.find('latest_') == 0 and name.endswith('_duration'):
+ if name.find('last_') == 0 and name.endswith('_duration'):
zero = 0.0
else:
zero = 0
diff --git a/src/lib/python/isc/statistics/tests/testdata/test_spec3.spec b/src/lib/python/isc/statistics/tests/testdata/test_spec3.spec
index 30f6b2f..6c06f69 100644
--- a/src/lib/python/isc/statistics/tests/testdata/test_spec3.spec
+++ b/src/lib/python/isc/statistics/tests/testdata/test_spec3.spec
@@ -19,8 +19,8 @@
"ixfrreqv6": 0,
"xfrsuccess": 0,
"xfrfail": 0,
- "latest_ixfr_duration": 0.0,
- "latest_axfr_duration": 0.0
+ "last_ixfr_duration": 0.0,
+ "last_axfr_duration": 0.0
}
},
"item_title": "Zone names",
@@ -98,20 +98,20 @@
"item_description": "Number of zone transfer requests failed"
},
{
- "item_name": "latest_ixfr_duration",
+ "item_name": "last_ixfr_duration",
"item_type": "real",
"item_optional": false,
"item_default": 0.0,
- "item_title": "Latest IXFR duration",
- "item_description": "Duration of the latest IXFR. 0.0 means no successful IXFR done."
+ "item_title": "Last IXFR duration",
+ "item_description": "Duration of the last IXFR. 0.0 means no successful IXFR done."
},
{
- "item_name": "latest_axfr_duration",
+ "item_name": "last_axfr_duration",
"item_type": "real",
"item_optional": false,
"item_default": 0.0,
- "item_title": "Latest AXFR duration",
- "item_description": "Duration of the latest AXFR. 0.0 means no successful AXFR done."
+ "item_title": "Last AXFR duration",
+ "item_description": "Duration of the last AXFR. 0.0 means no successful AXFR done."
}
]
}
diff --git a/src/lib/python/isc/util/Makefile.am b/src/lib/python/isc/util/Makefile.am
index 3eaaa12..eaeedd8 100644
--- a/src/lib/python/isc/util/Makefile.am
+++ b/src/lib/python/isc/util/Makefile.am
@@ -1,6 +1,7 @@
SUBDIRS = . cio tests
-python_PYTHON = __init__.py process.py socketserver_mixin.py file.py
+python_PYTHON = __init__.py process.py socketserver_mixin.py file.py
+python_PYTHON += address_formatter.py
pythondir = $(pyexecdir)/isc/util
diff --git a/src/lib/python/isc/util/address_formatter.py b/src/lib/python/isc/util/address_formatter.py
new file mode 100644
index 0000000..35c1e00
--- /dev/null
+++ b/src/lib/python/isc/util/address_formatter.py
@@ -0,0 +1,82 @@
+# Copyright (C) 2013 Internet Systems Consortium.
+#
+# Permission to use, copy, modify, and 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 INTERNET SYSTEMS CONSORTIUM
+# DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+# INTERNET SYSTEMS CONSORTIUM 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.
+
+import socket
+
+class AddressFormatter:
+ """
+ A utility class to convert an IP address with a port number to a
+ string.
+
+ It takes a tuple (or list) containing and address string and a port
+ number, and optionally a family.
+
+ If the family is IPv4, the __str__ output will be
+ <address>:<port>
+ If the family is IPv6, the __str__ output will be
+ [<address>]:<port>
+
+ If family is not given, the __str__ method will try to figure it out
+ itself, by checking for the ':' character in the address string.
+
+ This class is designed to delay the conversion until it's explicitly
+ requested, so the conversion doesn't happen if the corresponding log
+ message is suppressed because of its log level (which is often the case
+ for debug messages).
+
+ Note: this optimization comes with the cost of instantiating the
+ formatter object itself. It's not really clear which overhead is
+ heavier, and we may conclude it's actually better to just generate
+ the strings unconditionally. Alternatively, we can make the stored
+ address of this object replaceable so that this object can be reused.
+ Right now this is an open issue.
+
+ See also ClientFormatter in the ddns.logger code, which does something
+ similar but based on other criteria (and optional extra value).
+ """
+ def __init__(self, addr, family=None):
+ self.__addr = addr
+ self.__family = family
+
+ def __addr_v4(self):
+ return self.__addr[0] + ':' + str(self.__addr[1])
+
+ def __addr_v6(self):
+ return '[' + self.__addr[0] + ']:' + str(self.__addr[1])
+
+ def __format_addr(self):
+ # Some basic sanity checks, should we leave this out for efficiency?
+ # (especially strings produce unexpected results)
+ if isinstance(self.__addr, str) or\
+ not hasattr(self.__addr, "__getitem__"):
+ raise ValueError("Address must be a list or tuple")
+
+ if self.__family is not None:
+ if self.__family == socket.AF_INET6:
+ return self.__addr_v6()
+ elif self.__family == socket.AF_INET:
+ return self.__addr_v4()
+ else:
+ raise ValueError("Unknown address family: " +
+ str(self.__family))
+ else:
+ if self.__addr[0].find(':') >= 0:
+ return self.__addr_v6()
+ else:
+ return self.__addr_v4()
+
+ def __str__(self):
+ return self.__format_addr()
+
diff --git a/src/lib/python/isc/util/tests/Makefile.am b/src/lib/python/isc/util/tests/Makefile.am
index 3b882b4..e7995d8 100644
--- a/src/lib/python/isc/util/tests/Makefile.am
+++ b/src/lib/python/isc/util/tests/Makefile.am
@@ -1,5 +1,6 @@
PYCOVERAGE_RUN = @PYCOVERAGE_RUN@
PYTESTS = process_test.py socketserver_mixin_test.py file_test.py
+PYTESTS += address_formatter_test.py
EXTRA_DIST = $(PYTESTS)
# If necessary (rare cases), explicitly specify paths to dynamic libraries
@@ -12,7 +13,7 @@ endif
# test using command-line arguments, so use check-local target instead of TESTS
check-local:
if ENABLE_PYTHON_COVERAGE
- touch $(abs_top_srcdir)/.coverage
+ touch $(abs_top_srcdir)/.coverage
rm -f .coverage
${LN_S} $(abs_top_srcdir)/.coverage .coverage
endif
diff --git a/src/lib/python/isc/util/tests/address_formatter_test.py b/src/lib/python/isc/util/tests/address_formatter_test.py
new file mode 100644
index 0000000..295b7c3
--- /dev/null
+++ b/src/lib/python/isc/util/tests/address_formatter_test.py
@@ -0,0 +1,68 @@
+# Copyright (C) 2013 Internet Systems Consortium.
+#
+# Permission to use, copy, modify, and 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 INTERNET SYSTEMS CONSORTIUM
+# DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+# INTERNET SYSTEMS CONSORTIUM 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.
+
+import socket
+import unittest
+from isc.util.address_formatter import AddressFormatter
+
+class AddressFormatterTest(unittest.TestCase):
+ def test_v4(self):
+ self.assertEqual("127.0.0.1:123",
+ str(AddressFormatter(("127.0.0.1", 123))))
+ self.assertEqual("127.0.0.1:123",
+ str(AddressFormatter(("127.0.0.1", 123), None)))
+ self.assertEqual("192.0.2.1:1",
+ str(AddressFormatter(("192.0.2.1", 1))))
+
+ def test_v6(self):
+ self.assertEqual("[::1]:123",
+ str(AddressFormatter(("::1", 123))));
+ self.assertEqual("[::1]:123",
+ str(AddressFormatter(("::1", 123), None)))
+ self.assertEqual("[2001:db8::]:1",
+ str(AddressFormatter(("2001:db8::", 1))))
+
+ def test_force_family_good(self):
+ self.assertEqual("127.0.0.1:123",
+ str(AddressFormatter(("127.0.0.1", 123),
+ socket.AF_INET)))
+ self.assertEqual("[::1]:123",
+ str(AddressFormatter(("::1", 123),
+ socket.AF_INET6)))
+
+ def test_force_family_bad(self):
+ """
+ These results are 'bad' as in they don't return the value as
+ specified by our guidelines, since the internal check is skipped if
+ the family is given
+ """
+ self.assertEqual("[127.0.0.1]:123",
+ str(AddressFormatter(("127.0.0.1", 123),
+ socket.AF_INET6)))
+ self.assertEqual("::1:123",
+ str(AddressFormatter(("::1", 123),
+ socket.AF_INET)))
+
+ def test_bad_values(self):
+ self.assertRaises(ValueError, str, AddressFormatter("string"))
+ self.assertRaises(ValueError, str, AddressFormatter(None))
+ self.assertRaises(ValueError, str, AddressFormatter(1))
+ self.assertRaises(ValueError, str, AddressFormatter(("::1", 123), 1))
+ self.assertRaises(ValueError, str, AddressFormatter(("::1", 123), 1))
+
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/src/lib/python/isc/xfrin/diff.py b/src/lib/python/isc/xfrin/diff.py
index 4e06eea..31f5f25 100644
--- a/src/lib/python/isc/xfrin/diff.py
+++ b/src/lib/python/isc/xfrin/diff.py
@@ -31,7 +31,7 @@ from isc.log_messages.libxfrin_messages import *
class NoSuchZone(Exception):
"""
- This is raised if a diff for non-existant zone is being created.
+ This is raised if a diff for non-existent zone is being created.
"""
pass
@@ -52,10 +52,10 @@ class Diff:
"""
The class represents a diff against current state of datasource on
one zone. The usual way of working with it is creating it, then putting
- bunch of changes in and commiting at the end.
+ bunch of changes in and committing at the end.
If you change your mind, you can just stop using the object without
- really commiting it. In that case no changes will happen in the data
+ really committing it. In that case no changes will happen in the data
sounce.
The class works as a kind of a buffer as well, it does not direct
@@ -123,12 +123,12 @@ class Diff:
def __check_committed(self):
"""
- This checks if the diff is already commited or broken. If it is, it
+ This checks if the diff is already committed or broken. If it is, it
raises ValueError. This check is for methods that need to work only on
- yet uncommited diffs.
+ yet uncommitted diffs.
"""
if self.__updater is None:
- raise ValueError("The diff is already commited or it has raised " +
+ raise ValueError("The diff is already committed or it has raised " +
"an exception, you come late")
def __append_with_soa_check(self, buf, operation, rr):
@@ -200,7 +200,7 @@ class Diff:
Schedules addition of an RR into the zone in this diff.
The rr is of isc.dns.RRset type and it must contain only one RR.
- If this is not the case or if the diff was already commited, this
+ If this is not the case or if the diff was already committed, this
raises the ValueError exception.
The rr class must match the one of the datasource client. If
@@ -213,7 +213,7 @@ class Diff:
Schedules deleting an RR from the zone in this diff.
The rr is of isc.dns.RRset type and it must contain only one RR.
- If this is not the case or if the diff was already commited, this
+ If this is not the case or if the diff was already committed, this
raises the ValueError exception.
The rr class must match the one of the datasource client. If
@@ -287,7 +287,7 @@ class Diff:
This is called from time to time automatically, but you can call it
manually if you really want to.
- This raises ValueError if the diff was already commited.
+ This raises ValueError if the diff was already committed.
It also can raise isc.datasrc.Error. If that happens, you should stop
using this object and abort the modification.
@@ -344,7 +344,7 @@ class Diff:
self.__updater.commit()
finally:
# Remove the updater. That will free some resources for one, but
- # mark this object as already commited, so we can check
+ # mark this object as already committed, so we can check
# We delete it even in case the commit failed, as that makes us
# unusable.
@@ -594,6 +594,6 @@ class Diff:
This must not be called after a commit, or it'd throw ValueError.
'''
- # Apply itself will check it is not yet commited.
+ # Apply itself will check it is not yet committed.
self.apply()
return self.__updater.get_rrset_collection()
diff --git a/src/lib/python/isc/xfrin/tests/diff_tests.py b/src/lib/python/isc/xfrin/tests/diff_tests.py
index bb83340..ac04dc1 100644
--- a/src/lib/python/isc/xfrin/tests/diff_tests.py
+++ b/src/lib/python/isc/xfrin/tests/diff_tests.py
@@ -256,7 +256,7 @@ class DiffTest(unittest.TestCase):
"""
Try to add few items into the diff and see they are stored in there.
- Also try passing an rrset that has differnt amount of RRs than 1.
+ Also try passing an rrset that has different amount of RRs than 1.
"""
diff = Diff(self, Name('example.org.'))
self.__data_common(diff, diff.add_data, 'add')
diff --git a/src/lib/resolve/recursive_query.cc b/src/lib/resolve/recursive_query.cc
index 8d4ae58..55dc4da 100644
--- a/src/lib/resolve/recursive_query.cc
+++ b/src/lib/resolve/recursive_query.cc
@@ -930,7 +930,7 @@ private:
asio::deadline_timer client_timer;
asio::deadline_timer lookup_timer;
- // Make FowardQuery deletes itself safely. for more information see
+ // Make ForwardQuery deletes itself safely. for more information see
// the comments of outstanding_events in RunningQuery.
size_t outstanding_events_;
diff --git a/src/lib/server_common/client.cc b/src/lib/server_common/client.cc
index e6383d6..3cc2a07 100644
--- a/src/lib/server_common/client.cc
+++ b/src/lib/server_common/client.cc
@@ -57,8 +57,14 @@ Client::getRequestSourceIPAddress() const {
std::string
Client::toText() const {
std::stringstream ss;
- ss << impl_->request_.getRemoteEndpoint().getAddress().toText()
- << '#' << impl_->request_.getRemoteEndpoint().getPort();
+ const asiolink::IOAddress& addr =
+ impl_->request_.getRemoteEndpoint().getAddress();
+ if (addr.isV6()) {
+ ss << '[' << addr.toText() << ']';
+ } else {
+ ss << addr.toText();
+ }
+ ss << ':' << impl_->request_.getRemoteEndpoint().getPort();
return (ss.str());
}
diff --git a/src/lib/server_common/client.h b/src/lib/server_common/client.h
index 912e7a6..4e344f0 100644
--- a/src/lib/server_common/client.h
+++ b/src/lib/server_common/client.h
@@ -119,7 +119,7 @@ public:
///
/// (In the initial implementation) the format of the resulting string
/// is as follows:
- /// \code <IP address>#<port>
+ /// \code <IP address>:<port>
/// \endcode
/// The IP address is the textual representation of the client's IP
/// address, which is the source address of the request the client has
diff --git a/src/lib/server_common/portconfig.cc b/src/lib/server_common/portconfig.cc
index b214ef5..122c740 100644
--- a/src/lib/server_common/portconfig.cc
+++ b/src/lib/server_common/portconfig.cc
@@ -117,8 +117,14 @@ installListenAddresses(const AddressList& new_addresses,
try {
LOG_DEBUG(logger, DBG_TRACE_BASIC, SRVCOMM_SET_LISTEN);
BOOST_FOREACH(const AddressPair& addr, new_addresses) {
+ string addr_str;
+ if (addr.first.find(':') != string::npos) {
+ addr_str = "[" + addr.first + "]";
+ } else {
+ addr_str = addr.first;
+ }
LOG_DEBUG(logger, DBG_TRACE_VALUES, SRVCOMM_ADDRESS_VALUE).
- arg(addr.first).arg(addr.second);
+ arg(addr_str).arg(addr.second);
}
setAddresses(service, new_addresses, server_options);
address_store = new_addresses;
diff --git a/src/lib/server_common/server_common_messages.mes b/src/lib/server_common/server_common_messages.mes
index 22ce0f3..ba235c9 100644
--- a/src/lib/server_common/server_common_messages.mes
+++ b/src/lib/server_common/server_common_messages.mes
@@ -72,7 +72,7 @@ which it is running. The server will continue running to allow
reconfiguration, but will not be listening on any address or port until
an administrator does so.
-% SRVCOMM_ADDRESS_VALUE address to set: %1#%2
+% SRVCOMM_ADDRESS_VALUE address to set: %1:%2
Debug message. This lists one address and port value of the set of
addresses we are going to listen on (eg. there will be one log message
per pair). This appears only after SRVCOMM_SET_LISTEN, but might
diff --git a/src/lib/server_common/tests/client_unittest.cc b/src/lib/server_common/tests/client_unittest.cc
index 08c24ba..14f6fbc 100644
--- a/src/lib/server_common/tests/client_unittest.cc
+++ b/src/lib/server_common/tests/client_unittest.cc
@@ -92,8 +92,8 @@ TEST_F(ClientTest, constructIPv6) {
}
TEST_F(ClientTest, toText) {
- EXPECT_EQ("192.0.2.1#53214", client4->toText());
- EXPECT_EQ("2001:db8::1#53216", client6->toText());
+ EXPECT_EQ("192.0.2.1:53214", client4->toText());
+ EXPECT_EQ("[2001:db8::1]:53216", client6->toText());
}
// test operator<<. We simply confirm it appends the result of toText().
diff --git a/src/lib/server_common/tests/socket_requestor_test.cc b/src/lib/server_common/tests/socket_requestor_test.cc
index 8da545e..b5f6dfc 100644
--- a/src/lib/server_common/tests/socket_requestor_test.cc
+++ b/src/lib/server_common/tests/socket_requestor_test.cc
@@ -243,7 +243,7 @@ TEST_F(SocketRequestorTest, testBadRequestAnswers) {
const std::string max_len(sizeof(sock_un.sun_path) - 1, 'x');
addAnswer("foo", max_len);
// The failure should NOT contain 'too long'
- // (explicitly checking for existance of nonexistence of 'too long',
+ // (explicitly checking for existence of nonexistence of 'too long',
// as opposed to the actual error, since 'too long' is a value we set).
try {
doRequest();
diff --git a/src/lib/util/encode/base16_from_binary.h b/src/lib/util/encode/base16_from_binary.h
index 8606c61..7ac4fd1 100644
--- a/src/lib/util/encode/base16_from_binary.h
+++ b/src/lib/util/encode/base16_from_binary.h
@@ -83,7 +83,7 @@ class base16_from_binary :
> super_t;
public:
- // make composible buy using templated constructor
+ // make composable by using templated constructor
template<class T>
base16_from_binary(BOOST_PFTO_WRAPPER(T) start) :
super_t(
diff --git a/src/lib/util/encode/base32hex_from_binary.h b/src/lib/util/encode/base32hex_from_binary.h
index 5d16d04..be35c01 100644
--- a/src/lib/util/encode/base32hex_from_binary.h
+++ b/src/lib/util/encode/base32hex_from_binary.h
@@ -85,7 +85,7 @@ class base32hex_from_binary :
> super_t;
public:
- // make composible buy using templated constructor
+ // make composable by using templated constructor
template<class T>
base32hex_from_binary(BOOST_PFTO_WRAPPER(T) start) :
super_t(
diff --git a/src/lib/util/encode/base_n.cc b/src/lib/util/encode/base_n.cc
index c38f901..8c813c3 100644
--- a/src/lib/util/encode/base_n.cc
+++ b/src/lib/util/encode/base_n.cc
@@ -12,17 +12,6 @@
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
-#include <stdint.h>
-#include <cassert>
-#include <iterator>
-#include <string>
-#include <vector>
-
-#include <boost/archive/iterators/base64_from_binary.hpp>
-#include <boost/archive/iterators/binary_from_base64.hpp>
-#include <boost/archive/iterators/transform_width.hpp>
-#include <boost/math/common_factor.hpp>
-
#include <util/encode/base32hex_from_binary.h>
#include <util/encode/binary_from_base32hex.h>
#include <util/encode/base16_from_binary.h>
@@ -32,6 +21,18 @@
#include <exceptions/exceptions.h>
+#include <boost/archive/iterators/base64_from_binary.hpp>
+#include <boost/archive/iterators/binary_from_base64.hpp>
+#include <boost/archive/iterators/transform_width.hpp>
+#include <boost/math/common_factor.hpp>
+
+#include <stdint.h>
+#include <stdexcept>
+#include <cassert>
+#include <iterator>
+#include <string>
+#include <vector>
+
using namespace std;
using namespace boost::archive::iterators;
@@ -39,6 +40,15 @@ namespace isc {
namespace util {
namespace encode {
+// Some versions of clang cannot handle exceptions in unnamed namespaces
+// so this exception is defined in an 'internal' namespace
+namespace clang_unnamed_namespace_workaround {
+// An internally caught exception to unify a few possible cases of the same
+// error.
+class IncompleteBaseInput : public std::exception {
+};
+} // end namespace internal
+
// In the following anonymous namespace, we provide a generic framework
// to encode/decode baseN format. We use the following tools:
// - boost base64_from_binary/binary_from_base64: provide mapping table for
@@ -110,15 +120,15 @@ public:
const vector<uint8_t>::const_iterator& base_end) :
base_(base), base_end_(base_end), in_pad_(false)
{}
- EncodeNormalizer& operator++() {
- if (!in_pad_) {
- ++base_;
- }
- if (base_ == base_end_) {
- in_pad_ = true;
- }
+ EncodeNormalizer& operator++() { // prefix version
+ increment();
return (*this);
}
+ EncodeNormalizer operator++(int) { // postfix version
+ const EncodeNormalizer copy = *this;
+ increment();
+ return (copy);
+ }
const uint8_t& operator*() const {
if (in_pad_) {
return (BINARY_ZERO_CODE);
@@ -130,6 +140,14 @@ public:
return (base_ == other.base_);
}
private:
+ void increment() {
+ if (!in_pad_) {
+ ++base_;
+ }
+ if (base_ == base_end_) {
+ in_pad_ = true;
+ }
+ }
vector<uint8_t>::const_iterator base_;
const vector<uint8_t>::const_iterator base_end_;
bool in_pad_;
@@ -156,16 +174,20 @@ public:
DecodeNormalizer(const char base_zero_code,
const string::const_iterator& base,
const string::const_iterator& base_beginpad,
- const string::const_iterator& base_end) :
+ const string::const_iterator& base_end,
+ size_t* char_count) :
base_zero_code_(base_zero_code),
base_(base), base_beginpad_(base_beginpad), base_end_(base_end),
- in_pad_(false)
+ in_pad_(false), char_count_(char_count)
{
// Skip beginning spaces, if any. We need do it here because
// otherwise the first call to operator*() would be confused.
skipSpaces();
}
DecodeNormalizer& operator++() {
+ if (base_ < base_end_) {
+ ++*char_count_;
+ }
++base_;
skipSpaces();
if (base_ == base_beginpad_) {
@@ -188,15 +210,31 @@ public:
}
const char& operator*() const {
if (base_ == base_end_) {
- // binary_from_baseX calls this operator when it needs more bits
+ // binary_from_baseX can call this operator when it needs more bits
// even if the internal iterator (base_) has reached its end
// (if that happens it means the input is an incomplete baseX
// string and should be rejected). So this is the only point
// we can catch and reject this type of invalid input.
- isc_throw(BadValue, "Unexpected end of input in BASE decoder");
+ //
+ // More recent versions of Boost fixed the behavior and the
+ // out-of-range call to this operator doesn't happen. It's good,
+ // but in that case we need to catch incomplete baseX input in
+ // a different way. It's done via char_count_ and after the
+ // completion of decoding.
+
+ // throw this now and convert it
+ throw clang_unnamed_namespace_workaround::IncompleteBaseInput();
}
- if (in_pad_) {
- return (base_zero_code_);
+ if (*base_ == BASE_PADDING_CHAR) {
+ // Padding can only happen at the end of the input string. We can
+ // detect any violation of this by checking in_pad_, which is
+ // true iff we are on or after the first valid sequence of padding
+ // characters.
+ if (in_pad_) {
+ return (base_zero_code_);
+ } else {
+ isc_throw(BadValue, "Intermediate padding found");
+ }
} else {
return (*base_);
}
@@ -210,6 +248,9 @@ private:
const string::const_iterator base_beginpad_;
const string::const_iterator base_end_;
bool in_pad_;
+ // Store number of non-space decoded characters (incl. pad) here. Define
+ // it as a pointer so we can carry it over to any copied objects.
+ size_t* char_count_;
};
// BitsPerChunk: number of bits to be converted using the baseN mapping table.
@@ -331,10 +372,25 @@ BaseNTransformer<BitsPerChunk, BaseZeroCode, Encoder, Decoder>::decode(
const size_t padbytes = padbits / 8;
try {
+ size_t char_count = 0;
result.assign(Decoder(DecodeNormalizer(BaseZeroCode, input.begin(),
- srit.base(), input.end())),
+ srit.base(), input.end(),
+ &char_count)),
Decoder(DecodeNormalizer(BaseZeroCode, input.end(),
- input.end(), input.end())));
+ input.end(), input.end(),
+ NULL)));
+
+ // Number of bits of the conversion result including padding must be
+ // a multiple of 8; otherwise the decoder reaches the end of input
+ // with some incomplete bits of data, which is invalid.
+ if (((char_count * BitsPerChunk) % 8) != 0) {
+ // catch this immediately below
+ throw clang_unnamed_namespace_workaround::IncompleteBaseInput();
+ }
+ } catch (const clang_unnamed_namespace_workaround::IncompleteBaseInput&) {
+ // we unify error handling for incomplete input here.
+ isc_throw(BadValue, "Incomplete input for " << algorithm
+ << ": " << input);
} catch (const dataflow_exception& ex) {
// convert any boost exceptions into our local one.
isc_throw(BadValue, ex.what());
diff --git a/src/lib/util/encode/binary_from_base16.h b/src/lib/util/encode/binary_from_base16.h
index 50342f1..e9fdd27 100644
--- a/src/lib/util/encode/binary_from_base16.h
+++ b/src/lib/util/encode/binary_from_base16.h
@@ -91,7 +91,7 @@ class binary_from_base16 : public
Base
> super_t;
public:
- // make composible buy using templated constructor
+ // make composable by using templated constructor
template<class T>
binary_from_base16(BOOST_PFTO_WRAPPER(T) start) :
super_t(
diff --git a/src/lib/util/encode/binary_from_base32hex.h b/src/lib/util/encode/binary_from_base32hex.h
index 1d83f54..43b7d64 100644
--- a/src/lib/util/encode/binary_from_base32hex.h
+++ b/src/lib/util/encode/binary_from_base32hex.h
@@ -94,7 +94,7 @@ class binary_from_base32hex : public
Base
> super_t;
public:
- // make composible buy using templated constructor
+ // make composable by using templated constructor
template<class T>
binary_from_base32hex(BOOST_PFTO_WRAPPER(T) start) :
super_t(
diff --git a/src/lib/util/filename.h b/src/lib/util/filename.h
index a4ba47c..a265396 100644
--- a/src/lib/util/filename.h
+++ b/src/lib/util/filename.h
@@ -41,10 +41,10 @@ namespace util {
/// directory specification. Unless this class becomes more widely-used on
/// Windows, there is no point in adding redundant code.
///
-/// Name - everthing from the character after the last "/" up to but not
+/// Name - everything from the character after the last "/" up to but not
/// including the last ".".
///
-/// Extension - everthing from the right-most "." (after the right-most "/") to
+/// Extension - everything from the right-most "." (after the right-most "/") to
/// the end of the string. If there is no "." after the last "/", there is
/// no file extension.
///
diff --git a/src/lib/util/lru_list.h b/src/lib/util/lru_list.h
index e5db869..332f6ce 100644
--- a/src/lib/util/lru_list.h
+++ b/src/lib/util/lru_list.h
@@ -47,7 +47,7 @@ public:
/// When an object is dropped from the LRU list because it has not been
/// accessed for some time, it is possible that the action should trigger
/// some other functions. For this reason, it is possible to register
- /// a list-wide functor object to execute in this casee.
+ /// a list-wide functor object to execute in this case.
///
/// Note that the function does not execute as the result of a call to
/// remove() - that is an explicit call and it is assumed that the caller
diff --git a/src/lib/util/python/gen_wiredata.py.in b/src/lib/util/python/gen_wiredata.py.in
index 55724c9..c219e25 100755
--- a/src/lib/util/python/gen_wiredata.py.in
+++ b/src/lib/util/python/gen_wiredata.py.in
@@ -914,9 +914,9 @@ class NSECBASE(RR):
nbitmap = 1 # number of bitmaps
block = 0
maplen = None # default bitmap length, auto-calculate
- bitmap = '040000000003' # an arbtrarily chosen bitmap sample
+ bitmap = '040000000003' # an arbitrarily chosen bitmap sample
def dump(self, f):
- # first, construct the bitmpa data
+ # first, construct the bitmap data
block_list = []
maplen_list = []
bitmap_list = []
diff --git a/src/lib/util/tests/io_utilities_unittest.cc b/src/lib/util/tests/io_utilities_unittest.cc
index 4293c7e..8e0c232 100644
--- a/src/lib/util/tests/io_utilities_unittest.cc
+++ b/src/lib/util/tests/io_utilities_unittest.cc
@@ -14,7 +14,7 @@
/// \brief Test of asiolink utilties
///
-/// Tests the fuctionality of the asiolink utilities code by comparing them
+/// Tests the functionality of the asiolink utilities code by comparing them
/// with the equivalent methods in isc::dns::[Input/Output]Buffer.
#include <cstddef>
diff --git a/src/lib/util/tests/lru_list_unittest.cc b/src/lib/util/tests/lru_list_unittest.cc
index c0201ea..5f740e0 100644
--- a/src/lib/util/tests/lru_list_unittest.cc
+++ b/src/lib/util/tests/lru_list_unittest.cc
@@ -311,7 +311,7 @@ TEST_F(LruListTest, Touch) {
EXPECT_EQ(1, entry7_.use_count());
EXPECT_EQ(3, lru.size());
- // Now touch the entry agin to move it to the back of the list.
+ // Now touch the entry again to move it to the back of the list.
// This checks that the iterator stored in the entry as a result of the
// last touch operation is valid.
lru.touch(entry1_);
diff --git a/src/lib/util/unittests/run_all.cc b/src/lib/util/unittests/run_all.cc
index 5f50f77..0e3492b 100644
--- a/src/lib/util/unittests/run_all.cc
+++ b/src/lib/util/unittests/run_all.cc
@@ -31,7 +31,7 @@ run_all() {
// The catching of exceptions generated in tests is controlled by the
// B10TEST_CATCH_EXCEPTION environment variable. Setting this to
- // 1 enables the cacthing of exceptions; setting it to 0 disables it.
+ // 1 enables the catching of exceptions; setting it to 0 disables it.
// Anything else causes a message to be printed to stderr and the default
// taken. (The default is to catch exceptions if compiling with clang
// and false if not.)
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 570c0e2..9f1025b 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -1 +1 @@
-SUBDIRS = system tools
+SUBDIRS = tools
diff --git a/tests/lettuce/README b/tests/lettuce/README
index 94bf82b..a53c6e7 100644
--- a/tests/lettuce/README
+++ b/tests/lettuce/README
@@ -70,6 +70,11 @@ These files *will* be overwritten or deleted if the same scenarios are run
again, so if you want to inspect them after a failed test, either do so
immediately or move the files.
+If you want to keep these output files even for successful runs, you can
+specify the environment variable LETTUCE_KEEP_OUTPUT=1. The files will
+still be overwritten by subsequent runs, but they will not automatically be
+deleted.
+
Adding and extending tests
--------------------------
diff --git a/tests/lettuce/configurations/glue.config b/tests/lettuce/configurations/glue.config
new file mode 100644
index 0000000..fc301d3
--- /dev/null
+++ b/tests/lettuce/configurations/glue.config
@@ -0,0 +1,34 @@
+{
+ "version": 3,
+ "Logging": {
+ "loggers": [{
+ "severity": "DEBUG",
+ "name": "*",
+ "debuglevel": 99
+ }]
+ },
+ "Auth": {
+ "listen_on": [{
+ "port": 47806,
+ "address": "127.0.0.1"
+ }]
+ },
+ "data_sources": {
+ "classes": {
+ "IN": [
+ {
+ "type": "sqlite3",
+ "params": {
+ "database_file": "data/glue.sqlite3"
+ }
+ }
+ ]
+ }
+ },
+ "Init": {
+ "components": {
+ "b10-auth": { "kind": "needed", "special": "auth" },
+ "b10-cmdctl": { "special": "cmdctl", "kind": "needed" }
+ }
+ }
+}
diff --git a/tests/lettuce/configurations/xfrin/retransfer_master_diffs.conf b/tests/lettuce/configurations/xfrin/retransfer_master_diffs.conf
new file mode 100644
index 0000000..34d2d03
--- /dev/null
+++ b/tests/lettuce/configurations/xfrin/retransfer_master_diffs.conf
@@ -0,0 +1,47 @@
+{
+ "version": 3,
+ "Logging": {
+ "loggers": [ {
+ "debuglevel": 99,
+ "severity": "DEBUG",
+ "name": "*"
+ } ]
+ },
+ "Auth": {
+ "database_file": "data/xfrin-diffs.sqlite3",
+ "listen_on": [ {
+ "address": "::1",
+ "port": 47807
+ } ]
+ },
+ "data_sources": {
+ "classes": {
+ "IN": [{
+ "type": "sqlite3",
+ "params": {
+ "database_file": "data/xfrin-diffs.sqlite3"
+ }
+ }]
+ }
+ },
+ "Xfrout": {
+ "zone_config": [ {
+ "origin": "example."
+ } ],
+ "also_notify": [ {
+ "address": "::1",
+ "port": 47806
+ } ]
+ },
+ "Stats": {
+ "poll-interval": 1
+ },
+ "Init": {
+ "components": {
+ "b10-auth": { "kind": "needed", "special": "auth" },
+ "b10-xfrout": { "address": "Xfrout", "kind": "dispensable" },
+ "b10-zonemgr": { "address": "Zonemgr", "kind": "dispensable" },
+ "b10-cmdctl": { "special": "cmdctl", "kind": "needed" }
+ }
+ }
+}
diff --git a/tests/lettuce/configurations/xfrin/retransfer_slave_diffs.conf b/tests/lettuce/configurations/xfrin/retransfer_slave_diffs.conf
new file mode 100644
index 0000000..1bc6324
--- /dev/null
+++ b/tests/lettuce/configurations/xfrin/retransfer_slave_diffs.conf
@@ -0,0 +1,43 @@
+{
+ "version": 3,
+ "Logging": {
+ "loggers": [ {
+ "debuglevel": 99,
+ "severity": "DEBUG",
+ "name": "*"
+ } ]
+ },
+ "Auth": {
+ "database_file": "data/xfrin-before-diffs.sqlite3",
+ "listen_on": [ {
+ "address": "::1",
+ "port": 47806
+ } ]
+ },
+ "Xfrin": {
+ "zones": [ {
+ "name": "example",
+ "master_addr": "::1",
+ "master_port": 47807,
+ "use_ixfr": true
+ } ]
+ },
+ "data_sources": {
+ "classes": {
+ "IN": [{
+ "type": "sqlite3",
+ "params": {
+ "database_file": "data/xfrin-before-diffs.sqlite3"
+ }
+ }]
+ }
+ },
+ "Init": {
+ "components": {
+ "b10-auth": { "kind": "needed", "special": "auth" },
+ "b10-xfrin": { "address": "Xfrin", "kind": "dispensable" },
+ "b10-zonemgr": { "address": "Zonemgr", "kind": "dispensable" },
+ "b10-cmdctl": { "special": "cmdctl", "kind": "needed" }
+ }
+ }
+}
diff --git a/tests/lettuce/configurations/xfrin/retransfer_slave_notify.conf b/tests/lettuce/configurations/xfrin/retransfer_slave_notify.conf
deleted file mode 100644
index 3040b6c..0000000
--- a/tests/lettuce/configurations/xfrin/retransfer_slave_notify.conf
+++ /dev/null
@@ -1,49 +0,0 @@
-{
- "version": 3,
- "Logging": {
- "loggers": [ {
- "debuglevel": 99,
- "severity": "DEBUG",
- "name": "*"
- } ]
- },
- "Auth": {
- "database_file": "data/xfrin-notify.sqlite3",
- "listen_on": [ {
- "address": "::1",
- "port": 47806
- } ]
- },
- "data_sources": {
- "classes": {
- "IN": [{
- "type": "sqlite3",
- "params": {
- "database_file": "data/xfrin-notify.sqlite3"
- }
- }]
- }
- },
- "Xfrin": {
- "zones": [ {
- "name": "example.org",
- "master_addr": "::1",
- "master_port": 47807
- } ]
- },
- "Zonemgr": {
- "secondary_zones": [ {
- "name": "example.org",
- "class": "IN"
- } ]
- },
- "Init": {
- "components": {
- "b10-auth": { "kind": "needed", "special": "auth" },
- "b10-xfrin": { "address": "Xfrin", "kind": "dispensable" },
- "b10-zonemgr": { "address": "Zonemgr", "kind": "dispensable" },
- "b10-stats": { "address": "Stats", "kind": "dispensable" },
- "b10-cmdctl": { "special": "cmdctl", "kind": "needed" }
- }
- }
-}
diff --git a/tests/lettuce/configurations/xfrin/retransfer_slave_notify.conf.orig b/tests/lettuce/configurations/xfrin/retransfer_slave_notify.conf.orig
new file mode 100644
index 0000000..3040b6c
--- /dev/null
+++ b/tests/lettuce/configurations/xfrin/retransfer_slave_notify.conf.orig
@@ -0,0 +1,49 @@
+{
+ "version": 3,
+ "Logging": {
+ "loggers": [ {
+ "debuglevel": 99,
+ "severity": "DEBUG",
+ "name": "*"
+ } ]
+ },
+ "Auth": {
+ "database_file": "data/xfrin-notify.sqlite3",
+ "listen_on": [ {
+ "address": "::1",
+ "port": 47806
+ } ]
+ },
+ "data_sources": {
+ "classes": {
+ "IN": [{
+ "type": "sqlite3",
+ "params": {
+ "database_file": "data/xfrin-notify.sqlite3"
+ }
+ }]
+ }
+ },
+ "Xfrin": {
+ "zones": [ {
+ "name": "example.org",
+ "master_addr": "::1",
+ "master_port": 47807
+ } ]
+ },
+ "Zonemgr": {
+ "secondary_zones": [ {
+ "name": "example.org",
+ "class": "IN"
+ } ]
+ },
+ "Init": {
+ "components": {
+ "b10-auth": { "kind": "needed", "special": "auth" },
+ "b10-xfrin": { "address": "Xfrin", "kind": "dispensable" },
+ "b10-zonemgr": { "address": "Zonemgr", "kind": "dispensable" },
+ "b10-stats": { "address": "Stats", "kind": "dispensable" },
+ "b10-cmdctl": { "special": "cmdctl", "kind": "needed" }
+ }
+ }
+}
diff --git a/tests/lettuce/data/glue.sqlite3 b/tests/lettuce/data/glue.sqlite3
new file mode 100644
index 0000000..a527de8
Binary files /dev/null and b/tests/lettuce/data/glue.sqlite3 differ
diff --git a/tests/lettuce/data/xfrin-before-diffs.sqlite3.orig b/tests/lettuce/data/xfrin-before-diffs.sqlite3.orig
new file mode 100644
index 0000000..45bf77d
Binary files /dev/null and b/tests/lettuce/data/xfrin-before-diffs.sqlite3.orig differ
diff --git a/tests/lettuce/data/xfrin-diffs.sqlite3 b/tests/lettuce/data/xfrin-diffs.sqlite3
new file mode 100644
index 0000000..55b233d
Binary files /dev/null and b/tests/lettuce/data/xfrin-diffs.sqlite3 differ
diff --git a/tests/lettuce/features/example.feature b/tests/lettuce/features/example.feature
index ecfdcc3..f2df6d4 100644
--- a/tests/lettuce/features/example.feature
+++ b/tests/lettuce/features/example.feature
@@ -161,11 +161,13 @@ Feature: Example feature
A query for www.example.org should have rcode NOERROR
Wait for new bind10 stderr message AUTH_SEND_NORMAL_RESPONSE
Then set bind10 configuration data_sources/classes/IN[0]/params to {"database_file": "data/empty_db.sqlite3"}
- And wait for new bind10 stderr message DATASRC_SQLITE_CONNOPEN
+ # The 'not missing placeholder' check is for #2743
+ And wait for new bind10 stderr message DATASRC_SQLITE_CONNOPEN not Missing placeholder
A query for www.example.org should have rcode REFUSED
Wait for new bind10 stderr message AUTH_SEND_NORMAL_RESPONSE
Then set bind10 configuration data_sources/classes/IN[0]/params to {"database_file": "data/example.org.sqlite3"}
- And wait for new bind10 stderr message DATASRC_SQLITE_CONNOPEN
+ # The 'not missing placeholder' check is for #2743
+ And wait for new bind10 stderr message DATASRC_SQLITE_CONNOPEN not Missing placeholder
A query for www.example.org should have rcode NOERROR
Scenario: two bind10 instances
diff --git a/tests/lettuce/features/queries.feature b/tests/lettuce/features/queries.feature
index 8a66d1c..b0a6fac 100644
--- a/tests/lettuce/features/queries.feature
+++ b/tests/lettuce/features/queries.feature
@@ -3,6 +3,51 @@ Feature: Querying feature
for instance whether multiple queries in a row return consistent
answers.
+ Scenario: Glue
+ # Check the auth server returns the correct glue when asked for it.
+ Given I have bind10 running with configuration glue.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
+
+ # This query should result in a delegation with two NS; one in the
+ # delegated zone and one in a so called out-of-bailiwick zone for which
+ # the auth server has authority, too. For the former, the server
+ # should return glue in the parent zone. For the latter, BIND 9 and
+ # BIND 10 behave differently; BIND 9 uses "glue" in the parent zone
+ # (since this is the root zone everything can be considered a valid
+ # glue). BIND 10 (using sqlite3 data source) searches the other zone
+ # and uses the authoritative data in that zone (which is intentionally
+ # different from the glue in the root zone).
+ A query for foo.bar.example type A should have rcode NOERROR
+ The answer section of the last query response should be
+ """
+ """
+ The authority section of the last query response should be
+ """
+ example. 172800 IN NS NS1.example.COM.
+ example. 172800 IN NS NS.example.
+ """
+ The additional section of the last query response should be
+ """
+ NS.example. 172800 IN A 192.0.2.1
+ NS.example. 172800 IN A 192.0.2.2
+ NS1.example.COM. 172800 IN A 192.0.2.3
+ """
+ # Test we don't get out-of-zone glue
+ A query for example.net type A should have rcode NOERROR
+ The answer section of the last query response should be
+ """
+ """
+ The authority section of the last query response should be
+ """
+ example.net. 300 IN NS ns2.example.info.
+ example.net. 300 IN NS ns1.example.info.
+ """
+ The additional section of the last query response should be
+ """
+ """
+
Scenario: Repeated queries
Given I have bind10 running with configuration example.org.inmem.config
And wait for bind10 stderr message BIND10_STARTED_CC
@@ -50,6 +95,10 @@ Feature: Querying feature
ns2.example.org. 3600 IN A 192.0.2.4
"""
+ # Make sure handling statistics command handling checked below is
+ # after this query
+ And wait for bind10 stderr message AUTH_SEND_NORMAL_RESPONSE
+
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
@@ -92,6 +141,10 @@ Feature: Querying feature
ns2.example.org. 3600 IN A 192.0.2.4
"""
+ # Make sure handling statistics command handling checked below is
+ # after this query
+ And wait for new bind10 stderr message AUTH_SEND_NORMAL_RESPONSE
+
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
@@ -122,6 +175,10 @@ Feature: Querying feature
example.org. 3600 IN SOA ns1.example.org. admin.example.org. 1234 3600 1800 2419200 7200
"""
+ # Make sure handling statistics command handling checked below is
+ # after this query
+ And wait for new bind10 stderr message AUTH_SEND_NORMAL_RESPONSE
+
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
@@ -186,6 +243,10 @@ Feature: Querying feature
mail.example.org. 3600 IN A 192.0.2.10
"""
+ # Make sure handling statistics command handling checked below is
+ # after this query
+ And wait for bind10 stderr message AUTH_SEND_NORMAL_RESPONSE
+
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
@@ -237,6 +298,10 @@ Feature: Querying feature
ns.sub.example.org. 3600 IN A 192.0.2.101
"""
+ # Make sure handling statistics command handling checked below is
+ # after this query
+ And wait for bind10 stderr message AUTH_SEND_NORMAL_RESPONSE
+
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
@@ -288,6 +353,10 @@ Feature: Querying feature
A query for example.org type SSHFP should have rcode NOERROR
The last query response should have ancount 0
+ # Make sure handling statistics command handling checked below is
+ # after this query
+ And wait for bind10 stderr message AUTH_SEND_NORMAL_RESPONSE
+
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
@@ -313,6 +382,9 @@ Feature: Querying feature
"""
shell.example.org. 3600 IN SSHFP 2 1 123456789abcdef67890123456789abcdef67890
"""
+ # Make sure handling statistics command handling checked below is
+ # after this query
+ And wait for bind10 stderr message AUTH_SEND_NORMAL_RESPONSE
When I wait for new bind10 stderr message STATS_SEND_STATISTICS_REQUEST
# make sure Auth module receives a command
diff --git a/tests/lettuce/features/terrain/bind10_control.py b/tests/lettuce/features/terrain/bind10_control.py
index 5c22384..b155712 100644
--- a/tests/lettuce/features/terrain/bind10_control.py
+++ b/tests/lettuce/features/terrain/bind10_control.py
@@ -188,7 +188,7 @@ def parse_bindctl_output_as_data_structure():
If it is valid, it is parsed and returned as whatever data
structure it represented.
"""
- # strip any extra output after a charater that commonly terminates a valid
+ # strip any extra output after a character that commonly terminates a valid
# JSON expression, i.e., ']', '}' and '"'. (The extra output would
# contain 'Exit from bindctl' message, and depending on environment some
# other control-like characters...but why is this message even there?)
@@ -390,7 +390,7 @@ def check_statistics_items(step, category, has_except_for):
with the multiline part.
Expected values of items are taken from the multiline part of the step in
- the scenario. The multiline part has at most 5 columns: item_name,
+ the scenario. The multiline part has at most four columns: item_name,
item_value, min_value, and max_value. item_name is a relative name
to category. item_value is an expected value for
item_name. min_value and max_value are expected to be used when
@@ -438,21 +438,31 @@ def check_statistics_items(step, category, has_except_for):
'Statistics item %s has unexpected value %s (expect %s)' % \
(name, found, 0)
- at step('check initial statistics for (\S+)( with cmdctl port \d+)?')
-def check_init_statistics(step, name, cmdctl_port):
- """
- check the initial statistics for the module
+ at step('check initial statistics(?:( not)? containing (\S+))? for (\S+)'
+ '( with cmdctl port \d+)?( except for the following items)?')
+def check_init_statistics(step, notv, string, name, cmdctl_port, has_except_for):
+ """Checks the initial statistics for the module. Also checks a
+ string is contained or not contained in them. Statistics counters
+ other than zero can follow below.
Parameters:
+ notv ('not'): reverse the check (fail if string is found)
+ string ('containing <string>') string to look for
name ('module <name>'): The name of the module (case sensitive!)
cmdctl_port ('with cmdctl port <portnr>', optional): cmdctl port to send
the command to.
+ has_except_for ('except for the following items'): checks values of items
+ with the multiline part.
"""
query_str = 'query statistics of bind10 module ' + name
if cmdctl_port:
query_str = query_str + cmdctl_port
- notcontain_str = 'last bindctl output should not contain "%s"'
+ notcontain_str = 'last bindctl output should%s contain "%s"'
check_str = 'statistics counters are 0 in category .' + name
+ if has_except_for:
+ check_str = check_str + has_except_for + "\n" \
+ + step.represent_hashes()
step.given(query_str)
- step.given(notcontain_str % 'error')
- step.given(notcontain_str % 'example.org.')
+ step.given(notcontain_str % (' not', 'error'))
+ if string is not None:
+ step.given(notcontain_str % (notv, string))
step.given(check_str)
diff --git a/tests/lettuce/features/terrain/nsupdate.py b/tests/lettuce/features/terrain/nsupdate.py
index 946439d..26964f5 100644
--- a/tests/lettuce/features/terrain/nsupdate.py
+++ b/tests/lettuce/features/terrain/nsupdate.py
@@ -21,7 +21,7 @@ def run_nsupdate(commands):
"""Run nsupdate.
Parameters:
commands: a sequence of strings which will be sent.
- update_address: adress to send the update to
+ update_address: address to send the update to
update_port: port to send the update to
zone: zone to update
diff --git a/tests/lettuce/features/terrain/querying.py b/tests/lettuce/features/terrain/querying.py
index abd7c18..ae348fd 100644
--- a/tests/lettuce/features/terrain/querying.py
+++ b/tests/lettuce/features/terrain/querying.py
@@ -68,7 +68,7 @@ class QueryResult(object):
name: The domain name to query
qtype: The RR type to query. Defaults to A if it is None.
qclass: The RR class to query. Defaults to IN if it is None.
- address: The IP adress to send the query to.
+ address: The IP address to send the query to.
port: The port number to send the query to.
additional_args: List of additional arguments (e.g. '+dnssec').
All parameters must be either strings or have the correct string
diff --git a/tests/lettuce/features/terrain/steps.py b/tests/lettuce/features/terrain/steps.py
index e470acf..e41bb6d 100644
--- a/tests/lettuce/features/terrain/steps.py
+++ b/tests/lettuce/features/terrain/steps.py
@@ -37,8 +37,10 @@ def wait_for_stderr_message(step, times, new, process_name, message, not_message
output.
Parameter:
times: Check for the string this many times.
- new: (' new', optional): Only check the output printed since last time
- this step was used for this process.
+ new: (' new', optional): Only check the output from the process that has
+ not been covered in previous calls to this
+ function. See RunningProcess._wait_for_output_str
+ for details.
process_name ('<name> stderr'): Name of the process to check the output of.
message ('message <message>'): Output (part) to wait for.
not_message ('not <message>'): Output (part) to wait for, and fail
@@ -60,8 +62,10 @@ def wait_for_stdout_message(step, times, new, process_name, message, not_message
output.
Parameter:
times: Check for the string this many times.
- new: (' new', optional): Only check the output printed since last time
- this step was used for this process.
+ new: (' new', optional): Only check the output from the process that has
+ not been covered in previous calls to this
+ function. See RunningProcess._wait_for_output_str
+ for details.
process_name ('<name> stderr'): Name of the process to check the output of.
message ('message <message>'): Output (part) to wait for, and succeed.
not_message ('not <message>'): Output (part) to wait for, and fail
diff --git a/tests/lettuce/features/terrain/terrain.py b/tests/lettuce/features/terrain/terrain.py
index 22b1ec8..b861442 100644
--- a/tests/lettuce/features/terrain/terrain.py
+++ b/tests/lettuce/features/terrain/terrain.py
@@ -26,12 +26,16 @@
from lettuce import *
import subprocess
-import os.path
+import os
import shutil
import re
import sys
import time
+# lettuce cannot directly pass commands to the terrain, so we need to
+# use environment variables to influence behaviour
+KEEP_OUTPUT = 'LETTUCE_KEEP_OUTPUT'
+
# In order to make sure we start all tests with a 'clean' environment,
# We perform a number of initialization steps, like restoring configuration
# files, and removing generated data files.
@@ -70,8 +74,12 @@ copylist = [
"configurations/xfrin/retransfer_master_nons.conf"],
["configurations/xfrin/retransfer_slave.conf.orig",
"configurations/xfrin/retransfer_slave.conf"],
+ ["configurations/xfrin/retransfer_slave_notify.conf.orig",
+ "configurations/xfrin/retransfer_slave_notify.conf"],
["data/inmem-xfrin.sqlite3.orig",
"data/inmem-xfrin.sqlite3"],
+ ["data/xfrin-before-diffs.sqlite3.orig",
+ "data/xfrin-before-diffs.sqlite3"],
["data/xfrin-notify.sqlite3.orig",
"data/xfrin-notify.sqlite3"],
["data/ddns/example.org.sqlite3.orig",
@@ -107,11 +115,15 @@ class RunningProcess:
self.process = None
self.step = step
self.process_name = process_name
- self.remove_files_on_exit = True
+ self.remove_files_on_exit = (os.environ.get(KEEP_OUTPUT) != '1')
self._check_output_dir()
self._create_filenames()
self._start_process(args)
+ # used in _wait_for_output_str, map from (filename, (strings))
+ # to a file offset.
+ self.__file_offsets = {}
+
def _start_process(self, args):
"""
Start the process.
@@ -192,11 +204,29 @@ class RunningProcess:
os.remove(self.stderr_filename)
os.remove(self.stdout_filename)
- def _wait_for_output_str(self, filename, running_file, strings, only_new, matches = 1):
- """
- Wait for a line of output in this process. This will (if only_new is
- False) first check all previous output from the process, and if not
- found, check all output since the last time this method was called.
+ def _wait_for_output_str(self, filename, running_file, strings, only_new,
+ matches=1):
+ """
+ Wait for a line of output in this process. This will (if
+ only_new is False) check all output from the process including
+ that may have been checked before. If only_new is True, it
+ only checks output that has not been covered in previous calls
+ to this method for the file (if there was no such previous call to
+ this method, it works same as the case of only_new=False).
+
+ Care should be taken if only_new is to be set to True, as it may cause
+ counter-intuitive results. For example, assume the file is expected
+ to contain a line that has XXX and another line has YYY, but the
+ ordering is not predictable. If this method is called with XXX as
+ the search string, but the line containing YYY appears before the
+ target line, this method remembers the point in the file beyond
+ the line that has XXX. If a next call to this method specifies
+ YYY as the search string with only_new being True, the search will
+ fail. If the same string is expected to appear multiple times
+ and you want to catch the latest one, a more reliable way is to
+ specify the match number and set only_new to False, if the number
+ of matches is predictable.
+
For each line in the output, the given strings array is checked. If
any output lines checked contains one of the strings in the strings
array, that string (not the line!) is returned.
@@ -204,33 +234,34 @@ class RunningProcess:
filename: The filename to read previous output from, if applicable.
running_file: The open file to read new output from.
strings: Array of strings to look for.
- only_new: If true, only check output since last time this method was
- called. If false, first check earlier output.
+ only_new: See above.
matches: Check for the string this many times.
Returns a tuple containing the matched string, and the complete line
it was found in.
Fails if none of the strings was read after 10 seconds
(OUTPUT_WAIT_INTERVAL * OUTPUT_WAIT_MAX_INTERVALS).
"""
+ # Identify the start offset of search. if only_new=True, start from
+ # the farthest point we've reached in the file; otherwise start from
+ # the beginning.
+ if not filename in self.__file_offsets:
+ self.__file_offsets[filename] = 0
+ offset = self.__file_offsets[filename] if only_new else 0
+ running_file.seek(offset)
+
match_count = 0
- if not only_new:
- full_file = open(filename, "r")
- for line in full_file:
- for string in strings:
- if line.find(string) != -1:
- match_count += 1
- if match_count >= matches:
- full_file.close()
- return (string, line)
wait_count = 0
while wait_count < OUTPUT_WAIT_MAX_INTERVALS:
- where = running_file.tell()
line = running_file.readline()
+ where = running_file.tell()
if line:
for string in strings:
if line.find(string) != -1:
match_count += 1
if match_count >= matches:
+ # If we've gone further, update the recorded offset
+ if where > self.__file_offsets[filename]:
+ self.__file_offsets[filename] = where
return (string, line)
else:
wait_count += 1
@@ -243,8 +274,7 @@ class RunningProcess:
Wait for one of the given strings in this process's stderr output.
Parameters:
strings: Array of strings to look for.
- only_new: If true, only check output since last time this method was
- called. If false, first check earlier output.
+ only_new: See _wait_for_output_str.
matches: Check for the string this many times.
Returns a tuple containing the matched string, and the complete line
it was found in.
@@ -259,8 +289,7 @@ class RunningProcess:
Wait for one of the given strings in this process's stdout output.
Parameters:
strings: Array of strings to look for.
- only_new: If true, only check output since last time this method was
- called. If false, first check earlier output.
+ only_new: See _wait_for_output_str.
matches: Check for the string this many times.
Returns a tuple containing the matched string, and the complete line
it was found in.
@@ -340,8 +369,7 @@ class RunningProcesses:
Parameters:
process_name: The name of the process to check the stderr output of.
strings: Array of strings to look for.
- only_new: If true, only check output since last time this method was
- called. If false, first check earlier output.
+ only_new: See _wait_for_output_str.
matches: Check for the string this many times.
Returns the matched string.
Fails if none of the strings was read after 10 seconds
@@ -360,8 +388,7 @@ class RunningProcesses:
Parameters:
process_name: The name of the process to check the stdout output of.
strings: Array of strings to look for.
- only_new: If true, only check output since last time this method was
- called. If false, first check earlier output.
+ only_new: See _wait_for_output_str.
matches: Check for the string this many times.
Returns the matched string.
Fails if none of the strings was read after 10 seconds
diff --git a/tests/lettuce/features/xfrin_bind10.feature b/tests/lettuce/features/xfrin_bind10.feature
index 7ba1ca0..90a1144 100644
--- a/tests/lettuce/features/xfrin_bind10.feature
+++ b/tests/lettuce/features/xfrin_bind10.feature
@@ -33,7 +33,10 @@ Feature: Xfrin
And wait for new bind10 stderr message XFRIN_ZONE_WARN
# But after complaining, the zone data should be accepted.
Then wait for new bind10 stderr message XFRIN_TRANSFER_SUCCESS not XFRIN_XFR_PROCESS_FAILURE
- Then wait for new bind10 stderr message ZONEMGR_RECEIVE_XFRIN_SUCCESS
+ # there's no guarantee this is logged before XFRIN_TRANSFER_SUCCESS, so
+ # we can't reliably use 'wait for new'. In this case this should be the
+ # only occurrence of this message, so this should be okay.
+ Then wait for bind10 stderr message ZONEMGR_RECEIVE_XFRIN_SUCCESS
A query for www.example.org to [::1]:47806 should have rcode NOERROR
# The transferred zone should have 11 non-NSEC3 RRs and 1 NSEC3 RR.
@@ -56,7 +59,8 @@ Feature: Xfrin
Then I send bind10 the command Xfrin retransfer example.org IN ::1 47807
And wait for new bind10 stderr message XFRIN_ZONE_INVALID
And wait for new bind10 stderr message XFRIN_INVALID_ZONE_DATA
- Then wait for new bind10 stderr message ZONEMGR_RECEIVE_XFRIN_FAILED
+ # We can't use 'wait for new' here; see above.
+ Then wait for bind10 stderr message ZONEMGR_RECEIVE_XFRIN_FAILED
A query for example.org type NS to [::1]:47806 should have rcode NOERROR
And transfer result should have 13 rrs
@@ -82,7 +86,8 @@ Feature: Xfrin
# Make sure it is fully open
When I send bind10 the command Xfrin retransfer example.org
Then wait for new bind10 stderr message XFRIN_TRANSFER_SUCCESS not XFRIN_XFR_PROCESS_FAILURE
- And wait for new bind10 stderr message ZONEMGR_RECEIVE_XFRIN_SUCCESS
+ # this can't be 'wait for new'; see above.
+ And wait for bind10 stderr message ZONEMGR_RECEIVE_XFRIN_SUCCESS
# First to master, a transfer should then fail
When I send bind10 the following commands with cmdctl port 47804:
@@ -139,8 +144,52 @@ Feature: Xfrin
# zone is invalid and then reject it.
And wait for new bind10 stderr message XFRIN_ZONE_INVALID
And wait for new bind10 stderr message XFRIN_INVALID_ZONE_DATA
- Then wait for new bind10 stderr message ZONEMGR_RECEIVE_XFRIN_FAILED
+ # This can't be 'wait for new'
+ Then wait for bind10 stderr message ZONEMGR_RECEIVE_XFRIN_FAILED
# The zone still doesn't exist as it is rejected.
# FIXME: This step fails. Probably an empty zone is created in the data
# source :-|. This should be REFUSED, not SERVFAIL.
A query for www.example.org to [::1]:47806 should have rcode SERVFAIL
+
+ # TODO:
+ # * IXFR - generate an sqlite db that contains the journal. Check it was
+ # IXFR by logs.
+ # * IXFR->AXFR fallback if IXFR is not available (even rejected or
+ # something, not just the differences missing).
+ # * Retransfer with short refresh time (without notify).
+ Scenario: With differences
+ # We transfer from one bind10 to other, just like in the Retransfer command
+ # scenario. Just this time, the master contains the differences table
+ # and the slave has a previous version of the zone, so we use the IXFR.
+
+ Given I have bind10 running with configuration xfrin/retransfer_master_diffs.conf with cmdctl port 47804 as master
+ And wait for master stderr message BIND10_STARTED_CC
+ And wait for master stderr message CMDCTL_STARTED
+ And wait for master stderr message AUTH_SERVER_STARTED
+ And wait for master stderr message XFROUT_STARTED
+ And wait for master stderr message ZONEMGR_STARTED
+
+ And I have bind10 running with configuration xfrin/retransfer_slave_diffs.conf
+ 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 XFRIN_STARTED
+ And wait for bind10 stderr message ZONEMGR_STARTED
+
+ A query for example. type SOA to [::1]:47806 should have rcode NOERROR
+ The answer section of the last query response should be
+ """
+ example. 3600 IN SOA ns1.example. hostmaster.example. 94 3600 900 7200 300
+ """
+
+ When I send bind10 the command Xfrin retransfer example. IN ::1 47807
+ Then wait for new bind10 stderr message XFRIN_GOT_INCREMENTAL_RESP
+ Then wait for new bind10 stderr message XFRIN_IXFR_TRANSFER_SUCCESS not XFRIN_XFR_PROCESS_FAILURE
+ # This can't be 'wait for new'
+ Then wait for bind10 stderr message ZONEMGR_RECEIVE_XFRIN_SUCCESS
+
+ A query for example. type SOA to [::1]:47806 should have rcode NOERROR
+ The answer section of the last query response should be
+ """
+ example. 3600 IN SOA ns1.example. hostmaster.example. 100 3600 900 7200 300
+ """
diff --git a/tests/lettuce/features/xfrin_notify_handling.feature b/tests/lettuce/features/xfrin_notify_handling.feature
index e41aa05..9ceeb10 100644
--- a/tests/lettuce/features/xfrin_notify_handling.feature
+++ b/tests/lettuce/features/xfrin_notify_handling.feature
@@ -27,12 +27,16 @@ Feature: Xfrin incoming notify handling
#
# Test1 for Xfrout statistics
#
- check initial statistics for Xfrout with cmdctl port 47804
+ check initial statistics not containing example.org for Xfrout with cmdctl port 47804 except for the following items
+ | item_name | min_value | max_value |
+ | socket.unixdomain.open | 0 | 1 |
+ # Note: Sometime an unixdomain socket could be already opened at
+ # the first time when stats daemon queries xfrout statistics.
#
# Test2 for Xfrin statistics
#
- check initial statistics for Xfrin
+ check initial statistics not containing example.org for Xfrin
When I send bind10 with cmdctl port 47804 the command Xfrout notify example.org IN
Then wait for new master stderr message XFROUT_NOTIFY_COMMAND
@@ -54,7 +58,6 @@ Feature: Xfrin incoming notify handling
# wait until the last stats requesting is finished
When I query statistics zones of bind10 module Xfrout with cmdctl port 47804
- wait for new master stderr message STATS_SEND_STATISTICS_REQUEST
wait for new master stderr message XFROUT_RECEIVED_GETSTATS_COMMAND
last bindctl output should not contain "error"
@@ -80,21 +83,25 @@ Feature: Xfrin incoming notify handling
# wait until the last stats requesting is finished
When I query statistics zones of bind10 module Xfrin with cmdctl
- wait for new bind10 stderr message STATS_SEND_STATISTICS_REQUEST
wait for new bind10 stderr message XFRIN_RECEIVED_COMMAND
last bindctl output should not contain "error"
When I query statistics zones of bind10 module Xfrin with cmdctl
The statistics counters are 0 in category .Xfrin.zones except for the following items
- | item_name | item_value | min_value |
- | _SERVER_.soaoutv6 | 1 | |
- | _SERVER_.axfrreqv6 | 1 | |
- | _SERVER_.xfrsuccess | 1 | |
- | _SERVER_.latest_axfr_duration | | 0.0 |
- | example.org..soaoutv6 | 1 | |
- | example.org..axfrreqv6 | 1 | |
- | example.org..xfrsuccess | 1 | |
- | example.org..latest_axfr_duration | | 0.0 |
+ | item_name | item_value | min_value | max_value |
+ | _SERVER_.soaoutv6 | | | 3 |
+ | _SERVER_.axfrreqv6 | | | 3 |
+ | _SERVER_.xfrsuccess | 1 | | |
+ | _SERVER_.last_axfr_duration | | 0.0 | |
+ | example.org..soaoutv6 | | | 3 |
+ | example.org..axfrreqv6 | | | 3 |
+ | example.org..xfrsuccess | 1 | | |
+ | example.org..last_axfr_duration | | 0.0 | |
+ # Note: Originally the above soaoutv6 and axfrreqv6 should be
+ # expected to be 1. But due to a bug on notify_out.py, the result
+ # is sometimes increased up to 2 or more. So 3 is set to a maximum
+ # number so far. If the bug is fixed, please change it to a exact
+ # number (1). Please see #2879 for details about the bug.
#
# Test for handling incoming notify only in IPv4
@@ -120,23 +127,32 @@ Feature: Xfrin incoming notify handling
#
# Test1 for Xfrout statistics
#
- check initial statistics for Xfrout with cmdctl port 47804
+ check initial statistics not containing example.org for Xfrout with cmdctl port 47804 except for the following items
+ | item_name | min_value | max_value |
+ | socket.unixdomain.open | 0 | 1 |
+ # Note: Sometime an unixdomain socket could be already opened at
+ # the first time when stats daemon queries xfrout statistics.
#
# Test2 for Xfrin statistics
#
- check initial statistics for Xfrin
+ check initial statistics not containing example.org for Xfrin
When I send bind10 with cmdctl port 47804 the command Xfrout notify example.org IN
Then wait for new master stderr message XFROUT_NOTIFY_COMMAND
Then wait for new bind10 stderr message AUTH_RECEIVED_NOTIFY
- Then wait for new bind10 stderr message ZONEMGR_RECEIVE_NOTIFY
- Then wait for new bind10 stderr message XFRIN_XFR_TRANSFER_STARTED
- Then wait for new bind10 stderr message XFRIN_TRANSFER_SUCCESS not XFRIN_XFR_PROCESS_FAILURE
- Then wait for new bind10 stderr message ZONEMGR_RECEIVE_XFRIN_SUCCESS
- Then wait 5 times for new master stderr message NOTIFY_OUT_SENDING_NOTIFY
- Then wait for new master stderr message NOTIFY_OUT_RETRY_EXCEEDED
+ # From this point we can't reliably 'wait for new' because the ordering
+ # of logs from different processes is unpredictable. But these
+ # should be okay in this case.
+ Then wait for bind10 stderr message ZONEMGR_RECEIVE_NOTIFY
+ Then wait for bind10 stderr message XFRIN_XFR_TRANSFER_STARTED
+ Then wait for bind10 stderr message XFRIN_TRANSFER_SUCCESS not XFRIN_XFR_PROCESS_FAILURE
+ Then wait for bind10 stderr message ZONEMGR_RECEIVE_XFRIN_SUCCESS
+ Then wait for master stderr message NOTIFY_OUT_REPLY_RECEIVED
A query for www.example.org to 127.0.0.1:47806 should have rcode NOERROR
+ # Make sure handling statistics command handling checked below is
+ # after this query
+ And wait for bind10 stderr message AUTH_SEND_NORMAL_RESPONSE
#
# Test3 for Xfrout statistics
@@ -146,7 +162,9 @@ Feature: Xfrin incoming notify handling
# wait until the last stats requesting is finished
When I query statistics zones of bind10 module Xfrout with cmdctl port 47804
- wait for new master stderr message STATS_SEND_STATISTICS_REQUEST
+ # note that this does not 100% guarantee the stats updated Xfrout
+ # statistics. But there doesn't seem to be a better log message that
+ # suggests this event.
wait for new master stderr message XFROUT_RECEIVED_GETSTATS_COMMAND
last bindctl output should not contain "error"
@@ -172,21 +190,25 @@ Feature: Xfrin incoming notify handling
# wait until the last stats requesting is finished
When I query statistics zones of bind10 module Xfrin with cmdctl
- wait for new bind10 stderr message STATS_SEND_STATISTICS_REQUEST
wait for new bind10 stderr message XFRIN_RECEIVED_COMMAND
last bindctl output should not contain "error"
When I query statistics zones of bind10 module Xfrin with cmdctl
The statistics counters are 0 in category .Xfrin.zones except for the following items
- | item_name | item_value | min_value |
- | _SERVER_.soaoutv4 | 1 | |
- | _SERVER_.axfrreqv4 | 1 | |
- | _SERVER_.xfrsuccess | 1 | |
- | _SERVER_.latest_axfr_duration | | 0.0 |
- | example.org..soaoutv4 | 1 | |
- | example.org..axfrreqv4 | 1 | |
- | example.org..xfrsuccess | 1 | |
- | example.org..latest_axfr_duration | | 0.0 |
+ | item_name | item_value | min_value | max_value |
+ | _SERVER_.soaoutv4 | | | 3 |
+ | _SERVER_.axfrreqv4 | | | 3 |
+ | _SERVER_.xfrsuccess | 1 | | |
+ | _SERVER_.last_axfr_duration | | 0.0 | |
+ | example.org..soaoutv4 | | | 3 |
+ | example.org..axfrreqv4 | | | 3 |
+ | example.org..xfrsuccess | 1 | | |
+ | example.org..last_axfr_duration | | 0.0 | |
+ # Note: Originally the above soaoutv4 and axfrreqv4 should be
+ # expected to be 1. But due to a bug on notify_out.py, the result
+ # is sometimes increased up to 2 or more. So 3 is set to a maximum
+ # number so far. If the bug is fixed, please change it to a exact
+ # number (1). Please see #2879 for details about the bug.
#
# Test for Xfr request rejected
@@ -212,12 +234,16 @@ Feature: Xfrin incoming notify handling
#
# Test1 for Xfrout statistics
#
- check initial statistics for Xfrout with cmdctl port 47804
+ check initial statistics not containing example.org for Xfrout with cmdctl port 47804 except for the following items
+ | item_name | min_value | max_value |
+ | socket.unixdomain.open | 0 | 1 |
+ # Note: Sometime an unixdomain socket could be already opened at
+ # the first time when stats daemon queries xfrout statistics.
#
# Test2 for Xfrin statistics
#
- check initial statistics for Xfrin
+ check initial statistics not containing example.org for Xfrin
#
# set transfer_acl rejection
@@ -250,7 +276,6 @@ Feature: Xfrin incoming notify handling
# wait until the last stats requesting is finished
When I query statistics zones of bind10 module Xfrout with cmdctl port 47804
- wait for new master stderr message STATS_SEND_STATISTICS_REQUEST
wait for new master stderr message XFROUT_RECEIVED_GETSTATS_COMMAND
last bindctl output should not contain "error"
@@ -279,7 +304,6 @@ Feature: Xfrin incoming notify handling
# wait until the last stats requesting is finished
When I query statistics zones of bind10 module Xfrin with cmdctl
- wait for new bind10 stderr message STATS_SEND_STATISTICS_REQUEST
wait for new bind10 stderr message XFRIN_RECEIVED_COMMAND
last bindctl output should not contain "error"
@@ -292,9 +316,11 @@ Feature: Xfrin incoming notify handling
| example.org..soaoutv6 | 1 | 3 |
| example.org..axfrreqv6 | 1 | 3 |
| example.org..xfrfail | 1 | 3 |
- # Note: The above requests and failures would be done several
- # times depending on timing or environment. We expect here that
- # they would be 1 to 3.
+ # Note: Originally the above counters should be expected to be
+ # 1. But due to a bug on notify_out.py, the result is sometimes
+ # increased up to 2 or more. So 3 is set to a maximum number so
+ # far. If the bug is fixed, please change it to a exact number
+ # (1). Please see #2879 for details about the bug.
#
# Test for Xfr request rejected in IPv4
@@ -320,12 +346,16 @@ Feature: Xfrin incoming notify handling
#
# Test1 for Xfrout statistics
#
- check initial statistics for Xfrout with cmdctl port 47804
+ check initial statistics not containing example.org for Xfrout with cmdctl port 47804 except for the following items
+ | item_name | min_value | max_value |
+ | socket.unixdomain.open | 0 | 1 |
+ # Note: Sometime an unixdomain socket could be already opened at
+ # the first time when stats daemon queries xfrout statistics.
#
# Test2 for Xfrin statistics
#
- check initial statistics for Xfrin
+ check initial statistics not containing example.org for Xfrin
#
# set transfer_acl rejection
@@ -341,12 +371,12 @@ Feature: Xfrin incoming notify handling
When I send bind10 with cmdctl port 47804 the command Xfrout notify example.org IN
Then wait for new master stderr message XFROUT_NOTIFY_COMMAND
Then wait for new bind10 stderr message AUTH_RECEIVED_NOTIFY
- Then wait for new bind10 stderr message ZONEMGR_RECEIVE_NOTIFY
- Then wait for new bind10 stderr message XFRIN_XFR_TRANSFER_STARTED
- Then wait for new bind10 stderr message XFRIN_XFR_TRANSFER_PROTOCOL_VIOLATION not XFRIN_XFR_TRANSFER_STARTED
- Then wait for new bind10 stderr message ZONEMGR_RECEIVE_XFRIN_FAILED not ZONEMGR_RECEIVE_XFRIN_SUCCESS
- Then wait 5 times for new master stderr message NOTIFY_OUT_SENDING_NOTIFY
- Then wait for new master stderr message NOTIFY_OUT_RETRY_EXCEEDED
+ # can't use 'wait for new' below.
+ Then wait for bind10 stderr message ZONEMGR_RECEIVE_NOTIFY
+ Then wait for bind10 stderr message XFRIN_XFR_TRANSFER_STARTED
+ Then wait for bind10 stderr message XFRIN_XFR_TRANSFER_PROTOCOL_VIOLATION not XFRIN_TRANSFER_SUCCESS
+ Then wait for bind10 stderr message ZONEMGR_RECEIVE_XFRIN_FAILED not ZONEMGR_RECEIVE_XFRIN_SUCCESS
+ Then wait for master stderr message NOTIFY_OUT_REPLY_RECEIVED
A query for www.example.org to 127.0.0.1:47806 should have rcode NXDOMAIN
@@ -356,9 +386,8 @@ Feature: Xfrin incoming notify handling
# check statistics change
#
- # wait until the last stats requesting is finished
When I query statistics zones of bind10 module Xfrout with cmdctl port 47804
- wait for new master stderr message STATS_SEND_STATISTICS_REQUEST
+ # wait until stats request at least after NOTIFY_OUT_REPLY_RECEIVED
wait for new master stderr message XFROUT_RECEIVED_GETSTATS_COMMAND
last bindctl output should not contain "error"
@@ -387,7 +416,6 @@ Feature: Xfrin incoming notify handling
# wait until the last stats requesting is finished
When I query statistics zones of bind10 module Xfrin with cmdctl
- wait for new bind10 stderr message STATS_SEND_STATISTICS_REQUEST
wait for new bind10 stderr message XFRIN_RECEIVED_COMMAND
last bindctl output should not contain "error"
@@ -400,9 +428,11 @@ Feature: Xfrin incoming notify handling
| example.org..soaoutv4 | 1 | 3 |
| example.org..axfrreqv4 | 1 | 3 |
| example.org..xfrfail | 1 | 3 |
- # Note: The above requests and failures would be done several
- # times depending on timing or environment. We expect here that
- # they would be 1 to 3.
+ # Note: Originally the above counters should be expected to be
+ # 1. But due to a bug on notify_out.py, the result is sometimes
+ # increased up to 2 or more. So 3 is set to a maximum number so
+ # far. If the bug is fixed, please change it to a exact number
+ # (1). Please see #2879 for details about the bug.
#
# Test for unreachable slave
@@ -427,9 +457,8 @@ Feature: Xfrin incoming notify handling
# check statistics change
#
- # wait until the last stats requesting is finished
When I query statistics zones of bind10 module Xfrout with cmdctl port 47804
- wait for new master stderr message STATS_SEND_STATISTICS_REQUEST
+ # wait until stats request at least after NOTIFY_OUT_TIMEOUT
wait for new master stderr message XFROUT_RECEIVED_GETSTATS_COMMAND
last bindctl output should not contain "error"
@@ -443,3 +472,88 @@ Feature: Xfrin incoming notify handling
The statistics counters are 0 in category .Xfrout.socket.unixdomain except for the following items
| item_name | item_value |
| open | 1 |
+
+ #
+ # Test for NOTIFY that would result in NOTAUTH
+ #
+ Scenario: Handle incoming notify that does match authoritative zones
+ Given I have bind10 running with configuration xfrin/retransfer_master.conf with cmdctl port 47804 as master
+ And wait for master stderr message BIND10_STARTED_CC
+ And wait for master stderr message CMDCTL_STARTED
+ And wait for master stderr message AUTH_SERVER_STARTED
+ And wait for master stderr message XFROUT_STARTED
+ And wait for master stderr message ZONEMGR_STARTED
+ And wait for master stderr message STATS_STARTING
+
+ And I have bind10 running with configuration xfrin/retransfer_slave_notify.conf
+ 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 XFRIN_STARTED
+ And wait for bind10 stderr message ZONEMGR_STARTED
+
+ #
+ # replace master's data source with unmatched zone for slave's zone.
+ # we restart Xfrout to make it sure.
+ #
+ When I send bind10 the following commands with cmdctl port 47804
+ """
+ config set data_sources/classes/IN[0]/params/database_file data/ixfr-out/zones.sqlite3
+ config set Auth/database_file data/ixfr-out/zones.sqlite3
+ config set Xfrout/zone_config[0]/origin example.com
+ config commit
+ Xfrout shutdown
+ """
+ last bindctl output should not contain "error"
+ And wait for new master stderr message XFROUT_STARTED
+
+ A query for www.example.com to [::1]:47806 should have rcode REFUSED
+
+ When I send bind10 with cmdctl port 47804 the command Xfrout notify example.com IN
+ Then wait for new master stderr message XFROUT_NOTIFY_COMMAND
+ Then wait for new bind10 stderr message AUTH_RECEIVED_NOTIFY_NOTAUTH
+ Then wait for new master stderr message NOTIFY_OUT_REPLY_RECEIVED
+
+ A query for www.example.com to [::1]:47806 should have rcode REFUSED
+
+ #
+ # Test for NOTIFY that's not in the secondaries list
+ #
+ Scenario: Handle incoming notify that is not in the secondaries list
+ Given I have bind10 running with configuration xfrin/retransfer_master.conf with cmdctl port 47804 as master
+ And wait for master stderr message BIND10_STARTED_CC
+ And wait for master stderr message CMDCTL_STARTED
+ And wait for master stderr message AUTH_SERVER_STARTED
+ And wait for master stderr message XFROUT_STARTED
+ And wait for master stderr message ZONEMGR_STARTED
+ And wait for master stderr message STATS_STARTING
+
+ And I have bind10 running with configuration xfrin/retransfer_slave_notify.conf
+ 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 XFRIN_STARTED
+ And wait for bind10 stderr message ZONEMGR_STARTED
+
+ #
+ # Empty slave's secondaries list, and restart zonemgr to make it sure
+ #
+ When I send bind10 the following commands with cmdctl
+ """
+ config remove Zonemgr/secondary_zones[0]
+ config commit
+ Zonemgr shutdown
+ """
+ last bindctl output should not contain "error"
+ And wait for new bind10 stderr message ZONEMGR_STARTED
+
+ A query for www.example.org to [::1]:47806 should have rcode NXDOMAIN
+
+ When I send bind10 with cmdctl port 47804 the command Xfrout notify example.org IN
+ Then wait for new master stderr message XFROUT_NOTIFY_COMMAND
+ Then wait for new bind10 stderr message AUTH_RECEIVED_NOTIFY
+ Then wait for new bind10 stderr message ZONEMGR_RECEIVE_NOTIFY
+ Then wait for new bind10 stderr message ZONEMGR_ZONE_NOTIFY_NOT_SECONDARY
+ Then wait for new master stderr message NOTIFY_OUT_REPLY_RECEIVED
+
+ A query for www.example.org to [::1]:47806 should have rcode NXDOMAIN
diff --git a/tests/system/.gitignore b/tests/system/.gitignore
deleted file mode 100644
index 76f87fe..0000000
--- a/tests/system/.gitignore
+++ /dev/null
@@ -1,2 +0,0 @@
-/conf.sh
-/run.sh
diff --git a/tests/system/Makefile.am b/tests/system/Makefile.am
deleted file mode 100644
index aed1d79..0000000
--- a/tests/system/Makefile.am
+++ /dev/null
@@ -1,16 +0,0 @@
-systest:
- sh $(srcdir)/runall.sh
-
-distclean-local:
- sh $(srcdir)/cleanall.sh
-
-# Most of the files under this directory (including test subdirectories)
-# must be listed in EXTRA_DIST.
-EXTRA_DIST = README cleanall.sh ifconfig.sh start.pl stop.pl runall.sh
-EXTRA_DIST += common/default_user.csv
-EXTRA_DIST += glue/auth.good glue/example.good glue/noglue.good glue/test.good
-EXTRA_DIST += glue/tests.sh glue/clean.sh
-EXTRA_DIST += glue/nsx1/com.db glue/nsx1/net.db glue/nsx1/root-servers.nil.db
-EXTRA_DIST += glue/nsx1/root.db
-EXTRA_DIST += bindctl/tests.sh bindctl/clean.sh bindctl/setup.sh
-EXTRA_DIST += bindctl/nsx1/root.db bindctl/nsx1/example-normalized.db
diff --git a/tests/system/README b/tests/system/README
deleted file mode 100644
index a1c0a97..0000000
--- a/tests/system/README
+++ /dev/null
@@ -1,64 +0,0 @@
-Copyright (C) 2004, 2010, 2011 Internet Systems Consortium, Inc. ("ISC")
-Copyright (C) 2000, 2001 Internet Software Consortium.
-See COPYRIGHT in the source root or http://isc.org/copyright.html for terms.
-
-This is a simple test environment for running BIND 10 system tests
-involving multiple name servers. It was originally developed for BIND
-9, and has been ported to test BIND 10 implementations. Ideally we
-should share the same framework for both versions, so some part of the
-original setup are kept, even though they are BIND 9 specific and not
-currently used.
-
-Also, these tests generally rely on BIND 9 programs, most commonly
-its dig, and will sometimes be its name server (named). So, the test
-environment assumes that there's a source tree of BIND 9 where its
-programs are built, and that an environment variable "BIND9_TOP" is set
-to point to the top directory of the source tree.
-
-There are multiple test suites, each in a separate subdirectory and
-involving a different DNS setup. They are:
-
- bindctl/ Some basic management operations using the bindctl tool
- glue/ Glue handling tests
- ixfr/ Incremental transfer tests
-
-(the following tests are planned to be added soon)
- dnssec/ DNSSEC tests
- masterfile/ Master file parser
- axfr/ Full-transfer tests
-
-Typically each test suite sets up 2-5 instances of BIND 10 (or BIND 9
-named) and then performs one or more tests against them. Within the test
-suite subdirectory, each instance has a separate subdirectory containing
-its configuration data. By convention, these subdirectories are named
-"nsx1", "nsx2", etc for BIND 10 ("x" means BIND 10), and "ns1", "ns2",
-etc. for BIND 9.
-
-The tests are completely self-contained and do not require access to
-the real DNS. Generally, one of the test servers (ns[x]1) is set up as
-a root name server and is listed in the hints file of the others.
-
-To enable all servers to run on the same machine, they bind to separate
-virtual IP address on the loopback interface. ns[x]1 runs on 10.53.0.1,
-ns[x]2 on 10.53.0.2, etc. Before running any tests, you must set up
-these addresses by running "ifconfig.sh up" as root.
-
-Mac OS X:
-If you wish to make the interfaces survive across reboots copy
-org.isc.bind.system and org.isc.bind.system to /Library/LaunchDaemons
-then run "launchctl load /Library/LaunchDaemons/org.isc.bind.system.plist"
-as root.
-
-The servers use port 53210 instead of the usual port 53, so they can be
-run without root privileges once the interfaces have been set up.
-
-The tests can be run individually like this:
-
- sh run.sh xfer
- sh run.sh glue
- etc.
-
-To run all the tests, just type "make systest" either on this directory
-or on the top source directory. Note: currently these tests cannot be
-run when built under a separate build directory. Everything must be
-run within the original source tree.
diff --git a/tests/system/bindctl/clean.sh b/tests/system/bindctl/clean.sh
deleted file mode 100755
index f691512..0000000
--- a/tests/system/bindctl/clean.sh
+++ /dev/null
@@ -1,20 +0,0 @@
-#!/bin/sh
-#
-# Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
-# Copyright (C) 2000, 2001 Internet Software Consortium.
-#
-# 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.
-
-rm -f */b10-config.db
-rm -f dig.out.* bindctl.out.*
-rm -f */msgq_socket */zone.sqlite3
diff --git a/tests/system/bindctl/nsx1/.gitignore b/tests/system/bindctl/nsx1/.gitignore
deleted file mode 100644
index 4a8ce05..0000000
--- a/tests/system/bindctl/nsx1/.gitignore
+++ /dev/null
@@ -1,3 +0,0 @@
-/b10-config.db.template
-/bind10.run
-/bindctl.out
diff --git a/tests/system/bindctl/nsx1/b10-config.db.template.in b/tests/system/bindctl/nsx1/b10-config.db.template.in
deleted file mode 100644
index 4d6f287..0000000
--- a/tests/system/bindctl/nsx1/b10-config.db.template.in
+++ /dev/null
@@ -1,29 +0,0 @@
-{"version": 2,
- "Auth": {
- "listen_on": [{"address": "10.53.0.1", "port": 53210}],
- "database_file": "@abs_builddir@/zone.sqlite3"
- },
- "data_sources": {
- "classes": {
- "IN": [{
- "type": "sqlite3",
- "params": {
- "database_file": "@abs_builddir@/zone.sqlite3"
- }
- }]
- }
- },
- "Logging": {
- "loggers": [
- {
- "name": "*",
- "severity": "DEBUG",
- "output_options": [],
- "debuglevel": 99
- }
- ]
- },
- "Stats": {
- "poll-interval": 1
- }
-}
diff --git a/tests/system/bindctl/nsx1/example-normalized.db b/tests/system/bindctl/nsx1/example-normalized.db
deleted file mode 100644
index 7129522..0000000
--- a/tests/system/bindctl/nsx1/example-normalized.db
+++ /dev/null
@@ -1,3 +0,0 @@
-com. 300 IN SOA postmaster.example. ns.example.com. 2000042100 600 600 1200 600
-com. 300 IN NS ns.example.com.
-ns.example.com. 300 IN A 192.0.2.2
diff --git a/tests/system/bindctl/nsx1/root.db b/tests/system/bindctl/nsx1/root.db
deleted file mode 100644
index 31293de..0000000
--- a/tests/system/bindctl/nsx1/root.db
+++ /dev/null
@@ -1,25 +0,0 @@
-; Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
-; Copyright (C) 2000, 2001 Internet Software Consortium.
-;
-; 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.
-
-$TTL 300
-. IN SOA postmaster.example. a.root.servers.nil. (
- 2000042100 ; serial
- 600 ; refresh
- 600 ; retry
- 1200 ; expire
- 600 ; minimum
- )
-. NS ns.example.com.
-ns.example.com. A 192.0.2.1
diff --git a/tests/system/bindctl/setup.sh b/tests/system/bindctl/setup.sh
deleted file mode 100755
index 7a9a323..0000000
--- a/tests/system/bindctl/setup.sh
+++ /dev/null
@@ -1,26 +0,0 @@
-#!/bin/sh
-#
-# Copyright (C) 2011 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.
-
-SYSTEMTESTTOP=..
-. $SYSTEMTESTTOP/conf.sh
-
-SUBTEST_TOP=${TEST_TOP}/bindctl
-
-cp ${SUBTEST_TOP}/nsx1/b10-config.db.template ${SUBTEST_TOP}/nsx1/b10-config.db
-
-rm -f ${SUBTEST_TOP}/*/zone.sqlite3
-${B10_LOADZONE} -i 1 -c "{\"database_file\": \"${SUBTEST_TOP}/nsx1/zone.sqlite3\"}" \
- . ${SUBTEST_TOP}//nsx1/root.db
diff --git a/tests/system/bindctl/tests.sh b/tests/system/bindctl/tests.sh
deleted file mode 100755
index e1e533a..0000000
--- a/tests/system/bindctl/tests.sh
+++ /dev/null
@@ -1,238 +0,0 @@
-#!/bin/sh
-#
-# Copyright (C) 2011 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.
-
-SYSTEMTESTTOP=..
-. $SYSTEMTESTTOP/conf.sh
-
-#
-# Do bindctl tests.
-#
-
-status=0
-n=0
-
-# TODO: consider consistency with statistics definition in auth.spec
-
-# 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
-if [ $status != 0 ]; then echo "I:failed"; fi
-n=`expr $n + 1`
-
-echo "I:Starting b10-auth and checking that it works ($n)"
-echo 'config add Init/components b10-auth
-config set Init/components/b10-auth { "special": "auth", "kind": "needed" }
-config commit
-quit
-' | $RUN_BINDCTL \
- --csv-file-dir=$BINDCTL_CSV_DIR 2>&1 > /dev/null || status=1
-$DIG +norec @10.53.0.1 -p 53210 ns.example.com. A >dig.out.$n || status=1
-# perform a simple check on the output (digcomp would be too much for this)
-grep 192.0.2.1 dig.out.$n > /dev/null || status=1
-if [ $status != 0 ]; then echo "I:failed"; fi
-n=`expr $n + 1`
-
-echo "I:Checking BIND 10 statistics after a pause ($n)"
-# wait for 2sec to make sure b10-stats gets the latest statistics.
-sleep 2
-echo 'Stats show
-' | $RUN_BINDCTL \
- --csv-file-dir=$BINDCTL_CSV_DIR > bindctl.out.$n || status=1
-# 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)"
-echo 'config remove Init/components b10-auth
-config commit
-quit
-' | $RUN_BINDCTL \
- --csv-file-dir=$BINDCTL_CSV_DIR 2>&1 > /dev/null || status=1
-# dig should exit with a failure code.
-$DIG +tcp +norec @10.53.0.1 -p 53210 ns.example.com. A > /dev/null && status=1
-if [ $status != 0 ]; then echo "I:failed"; fi
-n=`expr $n + 1`
-
-echo "I:Restarting b10-auth and checking that ($n)"
-echo 'config add Init/components b10-auth
-config set Init/components/b10-auth { "special": "auth", "kind": "needed" }
-config commit
-quit
-' | $RUN_BINDCTL \
- --csv-file-dir=$BINDCTL_CSV_DIR 2>&1 > /dev/null || status=1
-sleep 2
-$DIG +norec @10.53.0.1 -p 53210 ns.example.com. A >dig.out.$n || status=1
-# perform a simple check on the output (digcomp would be too much for this)
-grep 192.0.2.1 dig.out.$n > /dev/null || status=1
-if [ $status != 0 ]; then echo "I:failed"; fi
-n=`expr $n + 1`
-
-echo "I:Rechecking BIND 10 statistics after a pause ($n)"
-sleep 2
-echo 'Stats show
-' | $RUN_BINDCTL \
- --csv-file-dir=$BINDCTL_CSV_DIR > bindctl.out.$n || status=1
-# The statistics counters can not be reset even after auth
-# restarts. Because stats preserves the query counts which the dying
-# 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)".
-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)"
-DATASRC_SPEC='{"type": "MasterFiles", "cache-enable": true, "params": {"com":'
-DATASRC_SPEC="${DATASRC_SPEC} \"${TEST_TOP}/bindctl/nsx1/example-normalized.db\"}}"
-echo "config set data_sources/classes/IN[0] ${DATASRC_SPEC}
-config commit
-quit
-" | $RUN_BINDCTL \
- --csv-file-dir=$BINDCTL_CSV_DIR > bindctl.out.$n || status=1
-sleep 2
-$DIG +norec @10.53.0.1 -p 53210 ns.example.com. A >dig.out.$n || status=1
-grep 192.0.2.2 dig.out.$n > /dev/null || status=1
-if [ $status != 0 ]; then echo "I:failed"; fi
-n=`expr $n + 1`
-
-echo "I:Rechecking BIND 10 statistics after changing the datasource ($n)"
-sleep 2
-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.
-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)"
-for i in 2 3
-do
- echo 'config add Init/components b10-auth-'$i'
-config set Init/components/b10-auth-'$i' { "special": "auth", "kind": "needed" }
-config commit
-quit
-' | $RUN_BINDCTL \
- --csv-file-dir=$BINDCTL_CSV_DIR 2>&1 > /dev/null || status=1
-done
-sleep 2
-$DIG +norec @10.53.0.1 -p 53210 ns.example.com. A >dig.out.$n || status=1
-grep 192.0.2.2 dig.out.$n > /dev/null || status=1
-if [ $status != 0 ]; then echo "I:failed"; fi
-n=`expr $n + 1`
-
-echo "I:Rechecking BIND 10 statistics consistency after a pause ($n)"
-sleep 2
-expected_count=`expr $expected_count + 1`
-# Rechecking some times
-for i in 1 2 3 4
-do
- echo 'Stats show
-' | $RUN_BINDCTL \
- --csv-file-dir=$BINDCTL_CSV_DIR > bindctl.out.$n || status=1
- # The statistics counters should keep being consistent even while
- # multiple b10-auths are running.
-
- test_counters $expected_count
- if [ $? != 0 ]; then echo "I:failed "; break ; fi
-done
-n=`expr $n + 1`
-
-echo "I:Stopping extra b10-auths and checking that ($n)"
-for i in 3 2
-do
- echo 'config remove Init/components b10-auth-'$i'
-config commit
-quit
-' | $RUN_BINDCTL \
- --csv-file-dir=$BINDCTL_CSV_DIR 2>&1 > /dev/null || status=1
-done
-sleep 2
-$DIG +norec @10.53.0.1 -p 53210 ns.example.com. A >dig.out.$n || status=1
-grep 192.0.2.2 dig.out.$n > /dev/null || status=1
-if [ $status != 0 ]; then echo "I:failed"; fi
-n=`expr $n + 1`
-
-# The statistics counters can not be rechecked here because the auth
-# instance seems to hang up after one of the multiple auth instances
-# was removed via bindctl. This reason seems to be the same reason as
-# #1703.
-
-echo "I:exit status: $status"
-exit $status
diff --git a/tests/system/cleanall.sh b/tests/system/cleanall.sh
deleted file mode 100755
index 434c6b1..0000000
--- a/tests/system/cleanall.sh
+++ /dev/null
@@ -1,36 +0,0 @@
-#!/bin/sh
-#
-# Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
-# Copyright (C) 2000, 2001 Internet Software Consortium.
-#
-# 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.
-
-#
-# Clean up after system tests.
-#
-
-find . -type f \( \
- -name 'K*' -o -name '*~' -o -name '*.core' -o -name '*.log' \
- -o -name '*.pid' -o -name '*.keyset' -o -name named.run \
- -o -name bind10.run -o -name lwresd.run -o -name ans.run \) -print | \
- xargs rm -f
-
-status=0
-
-for d in ./.* ./* ./*/*
-do
- case $d in ./.|./..) continue ;; esac
- test -d $d || continue
-
- test ! -f $d/clean.sh || ( cd $d && sh clean.sh )
-done
diff --git a/tests/system/common/default_user.csv b/tests/system/common/default_user.csv
deleted file mode 100644
index e13e194..0000000
--- a/tests/system/common/default_user.csv
+++ /dev/null
@@ -1 +0,0 @@
-root,bind10
diff --git a/tests/system/common/rndc.conf b/tests/system/common/rndc.conf
deleted file mode 100644
index a897548..0000000
--- a/tests/system/common/rndc.conf
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
- * Copyright (C) 2000, 2001 Internet Software Consortium.
- *
- * 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.
- */
-
-options {
- default-key "rndc_key";
-};
-
-key rndc_key {
- algorithm hmac-md5;
- secret "1234abcd8765";
-};
diff --git a/tests/system/common/rndc.key b/tests/system/common/rndc.key
deleted file mode 100644
index c2c3457..0000000
--- a/tests/system/common/rndc.key
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (C) 2011 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.
- */
-
-/* $Id: rndc.key,v 1.3 2011-03-12 04:59:47 tbox Exp $ */
-
-key rndc_key {
- secret "1234abcd8765";
- algorithm hmac-md5;
-};
diff --git a/tests/system/conf.sh.in b/tests/system/conf.sh.in
deleted file mode 100755
index 4948d63..0000000
--- a/tests/system/conf.sh.in
+++ /dev/null
@@ -1,73 +0,0 @@
-#!/bin/sh
-#
-# Copyright (C) 2004-2011 Internet Systems Consortium, Inc. ("ISC")
-# Copyright (C) 2000-2003 Internet Software Consortium.
-#
-# 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.
-
-#
-# Common configuration data for system tests, to be sourced into
-# other shell scripts.
-#
-
-# Prerequisite check
-if [ @srcdir@ != @builddir@ ]; then
- echo "Currently systest doesn't work for a separate build tree."
- echo "Rebuild BIND 10 on the source tree and run the tests."
- exit 1
-fi
-
-if [ -z $BIND9_TOP ]; then
- echo "systest assumes there's a compiled tree of BIND 9 which can be"
- echo "accessed via the BIND9_TOP environment variable."
- echo "Please make sure this assumption is met."
- exit 1
-fi
-
-# Find the top of the source and test trees.
-export TOP=@abs_top_srcdir@
-export TEST_TOP=@abs_builddir@
-
-# Programs
-export RUN_BIND10=$TOP/src/bin/bind10/run_bind10.sh
-export RUN_BINDCTL=$TOP/src/bin/bindctl/run_bindctl.sh
-export BINDCTL_CSV_DIR=@abs_srcdir@/common/
-export B10_LOADZONE=$TOP/src/bin/loadzone/run_loadzone.sh
-export BIND9_NAMED=$BIND9_TOP/bin/named/named
-export DIG=$BIND9_TOP/bin/dig/dig
-export RNDC=$BIND9_TOP/bin/rndc/rndc
-
-# Test tools borrowed from BIND 9's system test (without change).
-export TESTSOCK=$BIND9_TOP/bin/tests/system/testsock.pl
-export DIGCOMP=$BIND9_TOP/bin/tests/system/digcomp.pl
-
-# bindctl test doesn't work right now and is disabled (see #2568)
-#export SUBDIRS="bindctl glue ixfr/in-2"
-export SUBDIRS="glue ixfr/in-2"
-
-# Add appropriate subdirectories to the above statement as the tests become
-# available.
-#SUBDIRS="dnssec masterfile ixfr/in-1 ixfr/in-2 ixfr/in-4"
-
-# PERL will be an empty string if no perl interpreter was found. A similar
-# comment applies to AWK.
-export PERL=@PERL@
-export AWK=@AWK@
-
-# Other constants
-export RNDC_PORT=9953
-export DNS_PORT=53210
-
-export TESTS_TOP=$TOP/tests
-export SYSTEM_TOP=$TESTS_TOP/system
-export IXFR_TOP=$SYSTEM_TOP/ixfr
diff --git a/tests/system/glue/.gitignore b/tests/system/glue/.gitignore
deleted file mode 100644
index 87e08bf..0000000
--- a/tests/system/glue/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-/setup.sh
diff --git a/tests/system/glue/auth.good b/tests/system/glue/auth.good
deleted file mode 100644
index 2c619f6..0000000
--- a/tests/system/glue/auth.good
+++ /dev/null
@@ -1,15 +0,0 @@
-
-; <<>> DiG 9.0 <<>> +norec @10.53.0.1 -p 5300 foo.bar.example.org. a
-;; global options: printcmd
-;; Got answer:
-;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 41239
-;; flags: qr ad; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 1
-
-;; QUESTION SECTION:
-;foo.bar.example.org. IN A
-
-;; AUTHORITY SECTION:
-example.org. 172800 IN NS b.root-servers.nil.
-
-;; ADDITIONAL SECTION:
-b.root-servers.nil. 300 IN A 10.53.0.2
diff --git a/tests/system/glue/clean.sh b/tests/system/glue/clean.sh
deleted file mode 100755
index b2c1e02..0000000
--- a/tests/system/glue/clean.sh
+++ /dev/null
@@ -1,23 +0,0 @@
-#!/bin/sh
-#
-# Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
-# Copyright (C) 2000, 2001 Internet Software Consortium.
-#
-# 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.
-
-#
-# Clean up after glue tests.
-#
-
-rm -f dig.out.*
-rm -f */msgq_socket */zone.sqlite3
diff --git a/tests/system/glue/example.good b/tests/system/glue/example.good
deleted file mode 100644
index b6d5708..0000000
--- a/tests/system/glue/example.good
+++ /dev/null
@@ -1,22 +0,0 @@
-
-; <<>> DiG 9.0 <<>> +norec @10.53.0.1 -p 5300 foo.bar.example. A
-;; global options: printcmd
-;; Got answer:
-;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 58772
-;; flags: qr ad; QUERY: 1, ANSWER: 0, AUTHORITY: 6, ADDITIONAL: 7
-
-;; QUESTION SECTION:
-;foo.bar.example. IN A
-
-;; AUTHORITY SECTION:
-example. 172800 IN NS NS1.example.COM.
-example. 172800 IN NS NS.example.
-
-;; ADDITIONAL SECTION:
-NS.example. 172800 IN A 192.0.2.1
-NS.example. 172800 IN A 192.0.2.2
-NS1.example.COM. 172800 IN A 192.0.2.3
-;; These are not used now - they are in a different master file
-;; than the answer.
-; NS1.example.COM. 172800 IN A 192.0.2.101
-; NS1.example.COM. 172800 IN AAAA 2001:db8::1
diff --git a/tests/system/glue/noglue.good b/tests/system/glue/noglue.good
deleted file mode 100644
index 57a2211..0000000
--- a/tests/system/glue/noglue.good
+++ /dev/null
@@ -1,14 +0,0 @@
-
-; <<>> DiG 9.0 <<>> @10.53.0.1 -p 5300 example.net a
-;; global options: printcmd
-;; Got answer:
-;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 29409
-;; flags: qr rd ad; QUERY: 1, ANSWER: 0, AUTHORITY: 2, ADDITIONAL: 0
-
-;; QUESTION SECTION:
-;example.net. IN A
-
-;; AUTHORITY SECTION:
-example.net. 300 IN NS ns2.example.info.
-example.net. 300 IN NS ns1.example.info.
-
diff --git a/tests/system/glue/nsx1/.gitignore b/tests/system/glue/nsx1/.gitignore
deleted file mode 100644
index c0750b3..0000000
--- a/tests/system/glue/nsx1/.gitignore
+++ /dev/null
@@ -1,3 +0,0 @@
-/b10-config.db
-/bind10.run
-/bindctl.out
diff --git a/tests/system/glue/nsx1/b10-config.db.in b/tests/system/glue/nsx1/b10-config.db.in
deleted file mode 100644
index 6802c53..0000000
--- a/tests/system/glue/nsx1/b10-config.db.in
+++ /dev/null
@@ -1,36 +0,0 @@
-{"version": 2,
- "Auth": {
- "listen_on": [{"address": "10.53.0.1", "port": 53210}],
- "database_file": "@abs_builddir@/zone.sqlite3"
- },
- "data_sources": {
- "classes": {
- "IN": [{
- "type": "sqlite3",
- "params": {
- "database_file": "@abs_builddir@/zone.sqlite3"
- }
- }]
- }
- },
- "Logging": {
- "loggers": [
- {
- "name": "*",
- "severity": "DEBUG",
- "output_options": [],
- "debuglevel": 99
- }
- ]
- },
- "Init": {
- "components": {
- "b10-auth": {"kind": "needed", "special": "auth" },
- "b10-xfrin": { "address": "Xfrin", "kind": "dispensable" },
- "b10-xfrout": { "address": "Xfrout", "kind": "dispensable" },
- "b10-zonemgr": { "address": "Zonemgr", "kind": "dispensable" },
- "b10-stats": { "address": "Stats", "kind": "dispensable" },
- "b10-cmdctl": { "special": "cmdctl", "kind": "needed" }
- }
- }
-}
diff --git a/tests/system/glue/nsx1/com.db b/tests/system/glue/nsx1/com.db
deleted file mode 100644
index c4b94e1..0000000
--- a/tests/system/glue/nsx1/com.db
+++ /dev/null
@@ -1,31 +0,0 @@
-; Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
-; Copyright (C) 2000, 2001 Internet Software Consortium.
-;
-; 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.
-
-$ORIGIN com.
-$TTL 300
-@ IN SOA root.example.com. a.root.servers.nil. (
- 2000042100 ; serial
- 600 ; refresh
- 600 ; retry
- 1200 ; expire
- 600 ; minimum
- )
-@ NS a.root-servers.nil.
-
-example.com. NS ns1.example.com.
-example.com. NS ns2.example.com.
-ns1.example.com. 172800 IN A 192.0.2.101
-ns1.example.com. 172800 IN AAAA 2001:db8::1
-ns2.example.com. 172800 IN A 192.0.2.102
diff --git a/tests/system/glue/nsx1/net.db b/tests/system/glue/nsx1/net.db
deleted file mode 100644
index 8b66521..0000000
--- a/tests/system/glue/nsx1/net.db
+++ /dev/null
@@ -1,32 +0,0 @@
-; Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
-; Copyright (C) 2000, 2001 Internet Software Consortium.
-;
-; 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.
-
-$ORIGIN net.
-$TTL 300
-@ IN SOA root.example.net. a.root.servers.nil. (
- 2000042100 ; serial
- 600 ; refresh
- 600 ; retry
- 1200 ; expire
- 600 ; minimum
- )
-@ NS a.root-servers.nil.
-
-; Referral outside of server authority, but with glue records present.
-; Don't hand out the glue.
-example.net. NS ns1.example.info.
-example.net. NS ns2.example.info.
-ns1.example.info. 172800 IN A 192.0.2.101
-ns2.example.info. 172800 IN A 192.0.2.102
diff --git a/tests/system/glue/nsx1/root-servers.nil.db b/tests/system/glue/nsx1/root-servers.nil.db
deleted file mode 100644
index 45050a9..0000000
--- a/tests/system/glue/nsx1/root-servers.nil.db
+++ /dev/null
@@ -1,26 +0,0 @@
-; Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
-; Copyright (C) 2000, 2001 Internet Software Consortium.
-;
-; 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.
-
-$TTL 300
-@ IN SOA ns hostmaster (
- 1
- 3600
- 1800
- 1814400
- 3600
- )
- NS a
-a A 10.53.0.1
-b A 10.53.0.2
diff --git a/tests/system/glue/nsx1/root.db b/tests/system/glue/nsx1/root.db
deleted file mode 100644
index 271a4d8..0000000
--- a/tests/system/glue/nsx1/root.db
+++ /dev/null
@@ -1,53 +0,0 @@
-; Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
-; Copyright (C) 2000, 2001 Internet Software Consortium.
-;
-; 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.
-
-$TTL 300
-. IN SOA postmaster.example. a.root.servers.nil. (
- 2000042100 ; serial
- 600 ; refresh
- 600 ; retry
- 1200 ; expire
- 600 ; minimum
- )
-. NS a.root-servers.nil.
-
-root-servers.nil. NS a.root-servers.nil.
-a.root-servers.nil. A 10.53.0.1
-
-; Delegate some domains that contain name servers for the sample
-; ccTLDs below.
-com. 172800 IN NS a.root-servers.nil.
-
-;
-; A sample TLD
-;
-example. 172800 IN NS NS.example.
-example. 172800 IN NS NS1.example.COM.
-NS.example. 172800 IN A 192.0.2.1
-NS.example. 172800 IN A 192.0.2.2
-NS1.example.COM. 172800 IN A 192.0.2.3
-
-;
-;
-;
-test. 172800 IN NS ns.test.
-test. 172800 IN NS ns1.example.net.
-ns.test. 172800 IN A 192.0.2.200
-ns1.example.net. 172800 IN A 192.0.2.201
-
-;
-; A hypothetical ccTLD where we are authoritative for the NS glue.
-;
-example.org 172800 IN NS b.root-servers.nil.
diff --git a/tests/system/glue/setup.sh.in b/tests/system/glue/setup.sh.in
deleted file mode 100755
index 2f9f886..0000000
--- a/tests/system/glue/setup.sh.in
+++ /dev/null
@@ -1,25 +0,0 @@
-#!/bin/sh
-#
-# Copyright (C) 2011 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.
-
-SYSTEMTESTTOP=..
-. $SYSTEMTESTTOP/conf.sh
-
-rm -f */zone.sqlite3
-${B10_LOADZONE} -i 1 -c '{"database_file": "@builddir@/nsx1/zone.sqlite3"}' . @builddir@/nsx1/root.db
-${B10_LOADZONE} -i 1 -c '{"database_file": "@builddir@/nsx1/zone.sqlite3"}' root-servers.nil \
- @builddir@/nsx1/root-servers.nil.db
-${B10_LOADZONE} -i 1 -c '{"database_file": "@builddir@/nsx1/zone.sqlite3"}' com @builddir@/nsx1/com.db
-${B10_LOADZONE} -i 1 -c '{"database_file": "@builddir@/nsx1/zone.sqlite3"}' net @builddir@/nsx1/net.db
diff --git a/tests/system/glue/test.good b/tests/system/glue/test.good
deleted file mode 100644
index b9b4719..0000000
--- a/tests/system/glue/test.good
+++ /dev/null
@@ -1,19 +0,0 @@
-
-; <<>> DiG 9.8.0 <<>> @127.0.0.1 -p 5300 foo.bar.test
-; (1 server found)
-;; global options: +cmd
-;; Got answer:
-;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 55069
-;; flags: qr rd; QUERY: 1, ANSWER: 0, AUTHORITY: 2, ADDITIONAL: 2
-;; WARNING: recursion requested but not available
-
-;; QUESTION SECTION:
-;foo.bar.test. IN A
-
-;; AUTHORITY SECTION:
-test. 172800 IN NS ns.test.
-test. 172800 IN NS ns1.example.net.
-
-;; ADDITIONAL SECTION:
-ns.test. 172800 IN A 192.0.2.200
-ns1.example.net. 172800 IN A 192.0.2.201
diff --git a/tests/system/glue/tests.sh b/tests/system/glue/tests.sh
deleted file mode 100755
index dafb1ad..0000000
--- a/tests/system/glue/tests.sh
+++ /dev/null
@@ -1,68 +0,0 @@
-#!/bin/sh
-#
-# Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
-# Copyright (C) 2000, 2001, 2003 Internet Software Consortium.
-#
-# 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.
-
-SYSTEMTESTTOP=..
-. $SYSTEMTESTTOP/conf.sh
-
-#
-# Do glue tests.
-#
-
-status=0
-n=0
-
-# This query should result in a delegation with two NS; one in the delegated
-# zone and one in a so called out-of-bailiwick zone for which the auth server
-# has authority, too. For the former, the server should return glue in the
-# parent zone. For the latter, BIND 9 and BIND 10 behave differently; BIND 9
-# uses "glue" in the parent zone (since this is the root zone everything can
-# be considered a valid glue). BIND 10 (using sqlite3 data source) searches
-# the other zone and uses the authoritative data in that zone (which is
-# intentionally different from the glue in the root zone).
-echo "I:testing that a TLD referral gets a full glue set from the root zone ($n)"
-$DIG +norec @10.53.0.1 -p 53210 foo.bar.example. A >dig.out.$n || status=1
-$PERL $DIGCOMP example.good dig.out.$n || status=1
-n=`expr $n + 1`
-
-# Disabling this test, as it checks for looking up glue in a different zone
-# finder than the answer is from. This is not supported now.
-#echo "I:testing that we find glue A RRs we are authoritative for ($n)"
-#$DIG +norec @10.53.0.1 -p 53210 foo.bar.example.org. a >dig.out.$n || status=1
-#$PERL $DIGCOMP auth.good dig.out.$n || status=1
-#n=`expr $n + 1`
-
-# We cannot do this test for BIND 10 because b10-auth doesn't act as a
-# recursive (caching) server (by design)
-# echo "I:testing that we find glue A/AAAA RRs in the cache ($n)"
-# $DIG +norec @10.53.0.1 -p 53210 foo.bar.yy. a >dig.out.$n || status=1
-# $PERL $DIGCOMP yy.good dig.out.$n || status=1
-# n=`expr $n + 1`
-
-echo "I:testing that we don't find out-of-zone glue ($n)"
-$DIG +norec @10.53.0.1 -p 53210 example.net. a > dig.out.$n || status=1
-$PERL $DIGCOMP noglue.good dig.out.$n || status=1
-n=`expr $n + 1`
-
-# This test currently fails (additional section will be empty, which is
-# incorrect). See Trac ticket #646.
-#echo "I:testing that we are finding partial out-of-zone glue ($n)"
-#$DIG +norec @10.53.0.1 -p 53210 foo.bar.test. a >dig.out.$n || status=1
-#$PERL $DIGCOMP test.good dig.out.$n || status=1
-#n=`expr $n + 1`
-
-echo "I:exit status: $status"
-exit $status
diff --git a/tests/system/ifconfig.sh b/tests/system/ifconfig.sh
deleted file mode 100755
index 7c695e2..0000000
--- a/tests/system/ifconfig.sh
+++ /dev/null
@@ -1,226 +0,0 @@
-#!/bin/sh
-#
-# Copyright (C) 2004, 2007-2010 Internet Systems Consortium, Inc. ("ISC")
-# Copyright (C) 2000-2003 Internet Software Consortium.
-#
-# 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.
-
-#
-# Set up interface aliases for bind9 system tests.
-#
-# IPv4: 10.53.0.{1..7} RFC 1918
-# IPv6: fd92:7065:b8e:ffff::{1..7} ULA
-#
-
-config_guess=""
-for f in ./config.guess ../../config.guess
-do
- if test -f $f
- then
- config_guess=$f
- fi
-done
-
-if test "X$config_guess" = "X"
-then
- cat <<EOF >&2
-$0: must be run from the top level source directory or the
-bin/tests/system directory
-EOF
- exit 1
-fi
-
-# If running on hp-ux, don't even try to run config.guess.
-# It will try to create a temporary file in the current directory,
-# which fails when running as root with the current directory
-# on a NFS mounted disk.
-
-case `uname -a` in
- *HP-UX*) sys=hpux ;;
- *) sys=`sh $config_guess` ;;
-esac
-
-case "$2" in
-[0-9]|[1-9][0-9]|[1-9][0-9][0-9]) base=$2;;
-*) base=""
-esac
-
-case "$3" in
-[0-9]|[1-9][0-9]|[1-9][0-9][0-9]) base6=$2;;
-*) base6=""
-esac
-
-case "$1" in
-
- start|up)
- for ns in 1 2 3 4 5 6 7 8
- do
- if test -n "$base"
- then
- int=`expr $ns + $base - 1`
- else
- int=$ns
- fi
- if test -n "$base6"
- then
- int6=`expr $ns + $base6 - 1`
- else
- int6=$ns
- fi
- case "$sys" in
- *-pc-solaris2.5.1)
- ifconfig lo0:$int 10.53.0.$ns netmask 0xffffffff up
- ;;
- *-sun-solaris2.[6-7])
- ifconfig lo0:$int 10.53.0.$ns netmask 0xffffffff up
- ;;
- *-*-solaris2.[8-9]|*-*-solaris2.1[0-9])
- /sbin/ifconfig lo0:$int plumb
- /sbin/ifconfig lo0:$int 10.53.0.$ns up
- if test -n "$int6"
- then
- /sbin/ifconfig lo0:$int6 inet6 plumb
- /sbin/ifconfig lo0:$int6 \
- inet6 fd92:7065:b8e:ffff::$ns up
- fi
- ;;
- *-*-linux*)
- ifconfig lo:$int 10.53.0.$ns up netmask 255.255.255.0
- ifconfig lo inet6 add fd92:7065:b8e:ffff::$ns/64
- ;;
- *-unknown-freebsd*)
- ifconfig lo0 10.53.0.$ns alias netmask 0xffffffff
- ifconfig lo0 inet6 fd92:7065:b8e:ffff::$ns alias
- ;;
- *-unknown-netbsd*)
- ifconfig lo0 10.53.0.$ns alias netmask 255.255.255.0
- ifconfig lo0 inet6 fd92:7065:b8e:ffff::$ns alias
- ;;
- *-unknown-openbsd*)
- ifconfig lo0 10.53.0.$ns alias netmask 255.255.255.0
- ifconfig lo0 inet6 fd92:7065:b8e:ffff::$ns alias
- ;;
- *-*-bsdi[3-5].*)
- ifconfig lo0 add 10.53.0.$ns netmask 255.255.255.0
- ;;
- *-dec-osf[4-5].*)
- ifconfig lo0 alias 10.53.0.$ns
- ;;
- *-sgi-irix6.*)
- ifconfig lo0 alias 10.53.0.$ns
- ;;
- *-*-sysv5uw7*|*-*-sysv*UnixWare*|*-*-sysv*OpenUNIX*)
- ifconfig lo0 10.53.0.$ns alias netmask 0xffffffff
- ;;
- *-ibm-aix4.*|*-ibm-aix5.*)
- ifconfig lo0 alias 10.53.0.$ns
- ifconfig lo0 inet6 alias -dad fd92:7065:b8e:ffff::$ns/64
- ;;
- hpux)
- ifconfig lo0:$int 10.53.0.$ns netmask 255.255.255.0 up
- ifconfig lo0:$int inet6 fd92:7065:b8e:ffff::$ns up
- ;;
- *-sco3.2v*)
- ifconfig lo0 alias 10.53.0.$ns
- ;;
- *-darwin*)
- ifconfig lo0 alias 10.53.0.$ns
- ifconfig lo0 inet6 fd92:7065:b8e:ffff::$ns alias
- ;;
- *)
- echo "Don't know how to set up interface. Giving up."
- exit 1
- esac
- done
- ;;
-
- stop|down)
- for ns in 8 7 6 5 4 3 2 1
- do
- if test -n "$base"
- then
- int=`expr $ns + $base - 1`
- else
- int=$ns
- fi
- case "$sys" in
- *-pc-solaris2.5.1)
- ifconfig lo0:$int 0.0.0.0 down
- ;;
- *-sun-solaris2.[6-7])
- ifconfig lo0:$int 10.53.0.$ns down
- ;;
- *-*-solaris2.[8-9]|*-*-solaris2.1[0-9])
- ifconfig lo0:$int 10.53.0.$ns down
- ifconfig lo0:$int 10.53.0.$ns unplumb
- if test -n "$int6"
- then
- ifconfig lo0:$int6 inet6 down
- ifconfig lo0:$int6 inet6 unplumb
- fi
- ;;
- *-*-linux*)
- ifconfig lo:$int 10.53.0.$ns down
- ifconfig lo inet6 del fd92:7065:b8e:ffff::$ns/64
- ;;
- *-unknown-freebsd*)
- ifconfig lo0 10.53.0.$ns delete
- ifconfig lo0 inet6 fd92:7065:b8e:ffff::$ns delete
- ;;
- *-unknown-netbsd*)
- ifconfig lo0 10.53.0.$ns delete
- ifconfig lo0 inet6 fd92:7065:b8e:ffff::$ns delete
- ;;
- *-unknown-openbsd*)
- ifconfig lo0 10.53.0.$ns delete
- ifconfig lo0 inet6 fd92:7065:b8e:ffff::$ns delete
- ;;
- *-*-bsdi[3-5].*)
- ifconfig lo0 remove 10.53.0.$ns
- ;;
- *-dec-osf[4-5].*)
- ifconfig lo0 -alias 10.53.0.$ns
- ;;
- *-sgi-irix6.*)
- ifconfig lo0 -alias 10.53.0.$ns
- ;;
- *-*-sysv5uw7*|*-*-sysv*UnixWare*|*-*-sysv*OpenUNIX*)
- ifconfig lo0 -alias 10.53.0.$ns
- ;;
- *-ibm-aix4.*|*-ibm-aix5.*)
- ifconfig lo0 delete 10.53.0.$ns
- ifconfig lo0 delete inet6 fd92:7065:b8e:ffff::$ns/64
- ;;
- hpux)
- ifconfig lo0:$int 0.0.0.0
- ifconfig lo0:$int inet6 ::
- ;;
- *-sco3.2v*)
- ifconfig lo0 -alias 10.53.0.$ns
- ;;
- *darwin*)
- ifconfig lo0 -alias 10.53.0.$ns
- ifconfig lo0 inet6 fd92:7065:b8e:ffff::$ns delete
- ;;
- *)
- echo "Don't know how to destroy interface. Giving up."
- exit 1
- esac
- done
-
- ;;
-
- *)
- echo "Usage: $0 { up | down } [base]"
- exit 1
-esac
diff --git a/tests/system/ixfr/.gitignore b/tests/system/ixfr/.gitignore
deleted file mode 100644
index 027d45e..0000000
--- a/tests/system/ixfr/.gitignore
+++ /dev/null
@@ -1,8 +0,0 @@
-/b10-config.db
-/common_tests.sh
-/db.example.n0
-/db.example.n2
-/db.example.n2.refresh
-/db.example.n4
-/db.example.n6
-/ixfr_init.sh
diff --git a/tests/system/ixfr/README b/tests/system/ixfr/README
deleted file mode 100644
index 51cba8a..0000000
--- a/tests/system/ixfr/README
+++ /dev/null
@@ -1,86 +0,0 @@
-Introduction
-============
-The directories in-1 to in-4 implement the following tests of the IXFR-in
-capability of BIND 10.
-
-in-1: Check that BIND 10 can receive IXFR in a single UDP packet.
-in-2: Check that BIND 10 can receive IXFR via TCP.
-in-3: Check that BIND 10 will request AXFR if the server does not support IXFR.
-in-4: Check that BIND 10 will request IXFR when its SOA refresh times out
-
-The tests are described more fully in the document:
-
-http://bind10.isc.org/wiki/IxfrSystemTests
-
-Overview
-========
-All the tests use two nameservers:
-
-* A BIND 9 nameserver acting as the IXFR server (using the nomenclature
-of RFC 1995).
-* A BIND 10 nameserver acting at the IXFR client.
-
-In general, the tests attempt to set up the server and client independently.
-Communication is established between the systems by updating their
-configurations and a notification sent to the client. This should cause the
-client to request an IXFR from the server. (The exception is test 4, where the
-request is a result of the expiration of the SOA refresh time.)
-
-A check of zone files - or in these tests, of SOA serial number - can only
-reveal that a transfer has taken place. To check what has happened,
-e.g. whether the transfer was via UDP or whether a TCP request took place,
-the BIND 10 log file is searched for known message IDs.
-
-The searching of the log files for message IDs is one of the reasons that,
-unlike other system tests, the IXFR set of tests is broken up into separate
-tests that require the stopping and starting of nameservers (and tidying up of
-log files) between each test. Doing this means that only the existence of a
-particular message ID needs to be checked - there is no risk that another test
-produced it. The other reason is that the each IXFR test requires the
-nameservers to be in a specific state at the start of the test; this is easier
-to assure if they are not updating one another as the result of configuration
-settings established in the previous test.
-
-Test Files
-==========
-
-Data Files
-----------
-(All within tests/system/ixfr. Some .in files are processed to substitute
-for build variables in the build process to give the files listed here.)
-
-db.example.nX. These files hold the RRs for a zone for which should not
-fit within a single UDP packet. The files are different versions of the zone
-- the N-0 version (i.e. the latest version - "N" - the "-0" is present so
-that the files have a consistent name), N-2 etc. (See the full description
-of the tests for the meaning of N-2 etc.)
-
-db.example.common: A set of RRs to bulk out the zone to be larger than can
-be contained in a single UDP packet.
-
-db.example.n2.refresh: The N-2 version of the zone, but with a small SOA
-refresh time (for test 4).
-
-named_xxxx.conf: Various BIND 9 configuration files with NOTIFYs and/or
-IXFR enabled or disabled.
-
-Directories
------------
-The tests/system/ixfr directory holds the IXFR tests. Within that
-directory are subdirectories in-1 through in-4 for each test. And within
-each test directory are the directories ns1 (for the BIND 9 nameserver)
-and nsx2 (for the BIND 10 nameserver).
-
-Shell Scripts
--------------
-The IXFR tests use the same framework as the rest of the system tests,
-being based around shell scripts. Many have a ".in" form as they require
-substitution of build variables before they can be used, and so are
-listed in configure.ac. The files specific to the IXFR tests are:
-
-tests/system/ixfr/ixfr_init.sh.in: defines environment variables and shell
-subroutines used in the tests. (This references system/conf.sh.in which
-defines most of them.)
-
-tests/system/ixfr/common_tests.sh.in: tests in-1 and in-2 are virtually
-identical - this holds the common code.
diff --git a/tests/system/ixfr/b10-config.db.in b/tests/system/ixfr/b10-config.db.in
deleted file mode 100644
index a36117d..0000000
--- a/tests/system/ixfr/b10-config.db.in
+++ /dev/null
@@ -1,51 +0,0 @@
-{"version": 2,
- "Xfrin": {
- "zones": [{
- "master_addr": "10.53.0.1",
- "master_port": 53210,
- "name": "example.",
- "use_ixfr": true
- }]
- },
- "Auth": {
- "listen_on": [{
- "address": "10.53.0.2",
- "port": 53210
- }],
- "database_file": "@abs_builddir@/zone.sqlite3"
- },
- "data_sources": {
- "classes": {
- "IN": [{
- "type": "sqlite3",
- "params": {
- "database_file": "@abs_builddir@/zone.sqlite3"
- }
- }]
- }
- },
- "Logging": {
- "loggers": [{
- "name": "*",
- "severity": "DEBUG",
- "output_options": [],
- "debuglevel": 99
- }]
- },
- "Zonemgr": {
- "secondary_zones": [{
- "name": "example.",
- "class": "IN"
- }]
- },
- "Init": {
- "components": {
- "b10-auth": {"kind": "needed", "special": "auth" },
- "b10-xfrin": { "address": "Xfrin", "kind": "dispensable" },
- "b10-xfrout": { "address": "Xfrout", "kind": "dispensable" },
- "b10-zonemgr": { "address": "Zonemgr", "kind": "dispensable" },
- "b10-stats": { "address": "Stats", "kind": "dispensable" },
- "b10-cmdctl": { "special": "cmdctl", "kind": "needed" }
- }
- }
-}
diff --git a/tests/system/ixfr/clean_ns.sh b/tests/system/ixfr/clean_ns.sh
deleted file mode 100644
index 88f4ff1..0000000
--- a/tests/system/ixfr/clean_ns.sh
+++ /dev/null
@@ -1,28 +0,0 @@
-#!/bin/sh
-#
-# Copyright (C) 2011 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.
-
-# Clean up nameserver directories after zone transfer tests.
-
-rm -f ns1/named.conf
-rm -f ns1/db.example*
-rm -f ns1/named.memstats
-
-rm -f nsx2/bind10.run
-rm -f nsx2/b10-config.db
-rm -f ../zone.sqlite3
-
-rm -f client.dig
-rm -f server.dig
diff --git a/tests/system/ixfr/common_tests.sh.in b/tests/system/ixfr/common_tests.sh.in
deleted file mode 100644
index 90d0284..0000000
--- a/tests/system/ixfr/common_tests.sh.in
+++ /dev/null
@@ -1,78 +0,0 @@
-#!/bin/sh
-#
-# Copyright (C) 2011 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.
-
-# \file
-# This script is used in a couple of IXFR tests.
-#
-# Preconditions:\n
-# The BIND 9 nameserver (ns1, 10.53.0.1, acting as the IXFR server) is loaded
-# with the N-4 version of the zone. (It may hold prior versions as well.)
-# Notifications are disabled.
-#
-# The BIND 10 nameserver (nsx2, 10.53.0.2, acting as the IXFR client) is loaded
-# with an earlier (unspecified) version of the zone.
-#
-# Actions:\n
-# This script updates the IXFR server with the N-2 and N-0 versions of the zone.
-# It then updates the BIND 10 configuration so that it looks for IXFRs from
-# the IXFR server and causes the server to send the client a NOTIFY. After
-# waiting for the client to update from the server, it compares ther zones of
-# the two system, reporting an error if they are different.
-#
-# Caller Actions:\n
-# The caller can pre-load the BIND 10 IXFR client with whatever version of the
-# zone it requires. It can also load the BIND 9 IXFR server with zones earlier
-# than N-4.
-#
-# After this test has finished, it is up to the caller to check the logs
-# to see if they report the expected behavior.
-#
-# \return 0 if the script executed successfully, non-zero otherwise
-
-# Set up variables etc.
-. @abs_top_builddir@/tests/system/conf.sh
-. $IXFR_TOP/ixfr_init.sh
-
-set -e
-
-# Store the SOA serial number of the BIND 10 client for later use.
-old_client_serial=`$DIG_SOA @$CLIENT_IP | $AWK '{print $3}'`
-echo "I:$CLIENT_NAME SOA serial of IXFR client is $old_client_serial"
-
-# Load the BIND 9 system (the IXFR server) with the "n - 2" and "n" version of
-# the zones. With ixfr-from-differences set to "yes", the nameserver should
-# generate the differences between them.
-echo "I:$SERVER_NAME updating IXFR-server for ixfr-in tests"
-update_server_zone $SERVER_NAME $SERVER_IP $IXFR_TOP/db.example.n2
-
-# Wait a bit - it seems that if two updates are loaded in quick succession,
-# the second sometimes gets lost.
-sleep 5
-update_server_zone $SERVER_NAME $SERVER_IP $IXFR_TOP/db.example.n0
-
-echo "I:$CLIENT_NAME forcing IXFR client to retrieve new version of the zone"
-$RUN_BINDCTL << .
-Xfrin retransfer zone_name="example"
-.
-
-# Wait for the client to update itself.
-wait_for_update $CLIENT_NAME $CLIENT_IP $old_client_serial
-
-# Has updated, compare the client and server's versions of the zone s- they
-# should be the same.
-compare_zones $SERVER_NAME $SERVER_IP $CLIENT_NAME $CLIENT_IP
-
-set +e
diff --git a/tests/system/ixfr/db.example.common b/tests/system/ixfr/db.example.common
deleted file mode 100644
index 90435ce..0000000
--- a/tests/system/ixfr/db.example.common
+++ /dev/null
@@ -1,1556 +0,0 @@
-; Copyright (C) 2011 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 files holds a number of AAAA records to bulk out a zone file beyond
-; 16kB. It is used in tests where it is required that the contents of a zone
-; do not fit into a single UDP packet.
-
-aaaa-000 IN AAAA 2001:db8::0000
-aaaa-001 IN AAAA 2001:db8::0001
-aaaa-002 IN AAAA 2001:db8::0002
-aaaa-003 IN AAAA 2001:db8::0003
-aaaa-004 IN AAAA 2001:db8::0004
-aaaa-005 IN AAAA 2001:db8::0005
-aaaa-006 IN AAAA 2001:db8::0006
-aaaa-007 IN AAAA 2001:db8::0007
-aaaa-008 IN AAAA 2001:db8::0008
-aaaa-009 IN AAAA 2001:db8::0009
-aaaa-010 IN AAAA 2001:db8::000a
-aaaa-011 IN AAAA 2001:db8::000b
-aaaa-012 IN AAAA 2001:db8::000c
-aaaa-013 IN AAAA 2001:db8::000d
-aaaa-014 IN AAAA 2001:db8::000e
-aaaa-015 IN AAAA 2001:db8::000f
-aaaa-016 IN AAAA 2001:db8::0010
-aaaa-017 IN AAAA 2001:db8::0011
-aaaa-018 IN AAAA 2001:db8::0012
-aaaa-019 IN AAAA 2001:db8::0013
-aaaa-020 IN AAAA 2001:db8::0014
-aaaa-021 IN AAAA 2001:db8::0015
-aaaa-022 IN AAAA 2001:db8::0016
-aaaa-023 IN AAAA 2001:db8::0017
-aaaa-024 IN AAAA 2001:db8::0018
-aaaa-025 IN AAAA 2001:db8::0019
-aaaa-026 IN AAAA 2001:db8::001a
-aaaa-027 IN AAAA 2001:db8::001b
-aaaa-028 IN AAAA 2001:db8::001c
-aaaa-029 IN AAAA 2001:db8::001d
-aaaa-030 IN AAAA 2001:db8::001e
-aaaa-031 IN AAAA 2001:db8::001f
-aaaa-032 IN AAAA 2001:db8::0020
-aaaa-033 IN AAAA 2001:db8::0021
-aaaa-034 IN AAAA 2001:db8::0022
-aaaa-035 IN AAAA 2001:db8::0023
-aaaa-036 IN AAAA 2001:db8::0024
-aaaa-037 IN AAAA 2001:db8::0025
-aaaa-038 IN AAAA 2001:db8::0026
-aaaa-039 IN AAAA 2001:db8::0027
-aaaa-040 IN AAAA 2001:db8::0028
-aaaa-041 IN AAAA 2001:db8::0029
-aaaa-042 IN AAAA 2001:db8::002a
-aaaa-043 IN AAAA 2001:db8::002b
-aaaa-044 IN AAAA 2001:db8::002c
-aaaa-045 IN AAAA 2001:db8::002d
-aaaa-046 IN AAAA 2001:db8::002e
-aaaa-047 IN AAAA 2001:db8::002f
-aaaa-048 IN AAAA 2001:db8::0030
-aaaa-049 IN AAAA 2001:db8::0031
-aaaa-050 IN AAAA 2001:db8::0032
-aaaa-051 IN AAAA 2001:db8::0033
-aaaa-052 IN AAAA 2001:db8::0034
-aaaa-053 IN AAAA 2001:db8::0035
-aaaa-054 IN AAAA 2001:db8::0036
-aaaa-055 IN AAAA 2001:db8::0037
-aaaa-056 IN AAAA 2001:db8::0038
-aaaa-057 IN AAAA 2001:db8::0039
-aaaa-058 IN AAAA 2001:db8::003a
-aaaa-059 IN AAAA 2001:db8::003b
-aaaa-060 IN AAAA 2001:db8::003c
-aaaa-061 IN AAAA 2001:db8::003d
-aaaa-062 IN AAAA 2001:db8::003e
-aaaa-063 IN AAAA 2001:db8::003f
-aaaa-064 IN AAAA 2001:db8::0040
-aaaa-065 IN AAAA 2001:db8::0041
-aaaa-066 IN AAAA 2001:db8::0042
-aaaa-067 IN AAAA 2001:db8::0043
-aaaa-068 IN AAAA 2001:db8::0044
-aaaa-069 IN AAAA 2001:db8::0045
-aaaa-070 IN AAAA 2001:db8::0046
-aaaa-071 IN AAAA 2001:db8::0047
-aaaa-072 IN AAAA 2001:db8::0048
-aaaa-073 IN AAAA 2001:db8::0049
-aaaa-074 IN AAAA 2001:db8::004a
-aaaa-075 IN AAAA 2001:db8::004b
-aaaa-076 IN AAAA 2001:db8::004c
-aaaa-077 IN AAAA 2001:db8::004d
-aaaa-078 IN AAAA 2001:db8::004e
-aaaa-079 IN AAAA 2001:db8::004f
-aaaa-080 IN AAAA 2001:db8::0050
-aaaa-081 IN AAAA 2001:db8::0051
-aaaa-082 IN AAAA 2001:db8::0052
-aaaa-083 IN AAAA 2001:db8::0053
-aaaa-084 IN AAAA 2001:db8::0054
-aaaa-085 IN AAAA 2001:db8::0055
-aaaa-086 IN AAAA 2001:db8::0056
-aaaa-087 IN AAAA 2001:db8::0057
-aaaa-088 IN AAAA 2001:db8::0058
-aaaa-089 IN AAAA 2001:db8::0059
-aaaa-090 IN AAAA 2001:db8::005a
-aaaa-091 IN AAAA 2001:db8::005b
-aaaa-092 IN AAAA 2001:db8::005c
-aaaa-093 IN AAAA 2001:db8::005d
-aaaa-094 IN AAAA 2001:db8::005e
-aaaa-095 IN AAAA 2001:db8::005f
-aaaa-096 IN AAAA 2001:db8::0060
-aaaa-097 IN AAAA 2001:db8::0061
-aaaa-098 IN AAAA 2001:db8::0062
-aaaa-099 IN AAAA 2001:db8::0063
-aaaa-100 IN AAAA 2001:db8::0064
-aaaa-101 IN AAAA 2001:db8::0065
-aaaa-102 IN AAAA 2001:db8::0066
-aaaa-103 IN AAAA 2001:db8::0067
-aaaa-104 IN AAAA 2001:db8::0068
-aaaa-105 IN AAAA 2001:db8::0069
-aaaa-106 IN AAAA 2001:db8::006a
-aaaa-107 IN AAAA 2001:db8::006b
-aaaa-108 IN AAAA 2001:db8::006c
-aaaa-109 IN AAAA 2001:db8::006d
-aaaa-110 IN AAAA 2001:db8::006e
-aaaa-111 IN AAAA 2001:db8::006f
-aaaa-112 IN AAAA 2001:db8::0070
-aaaa-113 IN AAAA 2001:db8::0071
-aaaa-114 IN AAAA 2001:db8::0072
-aaaa-115 IN AAAA 2001:db8::0073
-aaaa-116 IN AAAA 2001:db8::0074
-aaaa-117 IN AAAA 2001:db8::0075
-aaaa-118 IN AAAA 2001:db8::0076
-aaaa-119 IN AAAA 2001:db8::0077
-aaaa-120 IN AAAA 2001:db8::0078
-aaaa-121 IN AAAA 2001:db8::0079
-aaaa-122 IN AAAA 2001:db8::007a
-aaaa-123 IN AAAA 2001:db8::007b
-aaaa-124 IN AAAA 2001:db8::007c
-aaaa-125 IN AAAA 2001:db8::007d
-aaaa-126 IN AAAA 2001:db8::007e
-aaaa-127 IN AAAA 2001:db8::007f
-aaaa-128 IN AAAA 2001:db8::0080
-aaaa-129 IN AAAA 2001:db8::0081
-aaaa-130 IN AAAA 2001:db8::0082
-aaaa-131 IN AAAA 2001:db8::0083
-aaaa-132 IN AAAA 2001:db8::0084
-aaaa-133 IN AAAA 2001:db8::0085
-aaaa-134 IN AAAA 2001:db8::0086
-aaaa-135 IN AAAA 2001:db8::0087
-aaaa-136 IN AAAA 2001:db8::0088
-aaaa-137 IN AAAA 2001:db8::0089
-aaaa-138 IN AAAA 2001:db8::008a
-aaaa-139 IN AAAA 2001:db8::008b
-aaaa-140 IN AAAA 2001:db8::008c
-aaaa-141 IN AAAA 2001:db8::008d
-aaaa-142 IN AAAA 2001:db8::008e
-aaaa-143 IN AAAA 2001:db8::008f
-aaaa-144 IN AAAA 2001:db8::0090
-aaaa-145 IN AAAA 2001:db8::0091
-aaaa-146 IN AAAA 2001:db8::0092
-aaaa-147 IN AAAA 2001:db8::0093
-aaaa-148 IN AAAA 2001:db8::0094
-aaaa-149 IN AAAA 2001:db8::0095
-aaaa-150 IN AAAA 2001:db8::0096
-aaaa-151 IN AAAA 2001:db8::0097
-aaaa-152 IN AAAA 2001:db8::0098
-aaaa-153 IN AAAA 2001:db8::0099
-aaaa-154 IN AAAA 2001:db8::009a
-aaaa-155 IN AAAA 2001:db8::009b
-aaaa-156 IN AAAA 2001:db8::009c
-aaaa-157 IN AAAA 2001:db8::009d
-aaaa-158 IN AAAA 2001:db8::009e
-aaaa-159 IN AAAA 2001:db8::009f
-aaaa-160 IN AAAA 2001:db8::00a0
-aaaa-161 IN AAAA 2001:db8::00a1
-aaaa-162 IN AAAA 2001:db8::00a2
-aaaa-163 IN AAAA 2001:db8::00a3
-aaaa-164 IN AAAA 2001:db8::00a4
-aaaa-165 IN AAAA 2001:db8::00a5
-aaaa-166 IN AAAA 2001:db8::00a6
-aaaa-167 IN AAAA 2001:db8::00a7
-aaaa-168 IN AAAA 2001:db8::00a8
-aaaa-169 IN AAAA 2001:db8::00a9
-aaaa-170 IN AAAA 2001:db8::00aa
-aaaa-171 IN AAAA 2001:db8::00ab
-aaaa-172 IN AAAA 2001:db8::00ac
-aaaa-173 IN AAAA 2001:db8::00ad
-aaaa-174 IN AAAA 2001:db8::00ae
-aaaa-175 IN AAAA 2001:db8::00af
-aaaa-176 IN AAAA 2001:db8::00b0
-aaaa-177 IN AAAA 2001:db8::00b1
-aaaa-178 IN AAAA 2001:db8::00b2
-aaaa-179 IN AAAA 2001:db8::00b3
-aaaa-180 IN AAAA 2001:db8::00b4
-aaaa-181 IN AAAA 2001:db8::00b5
-aaaa-182 IN AAAA 2001:db8::00b6
-aaaa-183 IN AAAA 2001:db8::00b7
-aaaa-184 IN AAAA 2001:db8::00b8
-aaaa-185 IN AAAA 2001:db8::00b9
-aaaa-186 IN AAAA 2001:db8::00ba
-aaaa-187 IN AAAA 2001:db8::00bb
-aaaa-188 IN AAAA 2001:db8::00bc
-aaaa-189 IN AAAA 2001:db8::00bd
-aaaa-190 IN AAAA 2001:db8::00be
-aaaa-191 IN AAAA 2001:db8::00bf
-aaaa-192 IN AAAA 2001:db8::00c0
-aaaa-193 IN AAAA 2001:db8::00c1
-aaaa-194 IN AAAA 2001:db8::00c2
-aaaa-195 IN AAAA 2001:db8::00c3
-aaaa-196 IN AAAA 2001:db8::00c4
-aaaa-197 IN AAAA 2001:db8::00c5
-aaaa-198 IN AAAA 2001:db8::00c6
-aaaa-199 IN AAAA 2001:db8::00c7
-aaaa-200 IN AAAA 2001:db8::00c8
-aaaa-201 IN AAAA 2001:db8::00c9
-aaaa-202 IN AAAA 2001:db8::00ca
-aaaa-203 IN AAAA 2001:db8::00cb
-aaaa-204 IN AAAA 2001:db8::00cc
-aaaa-205 IN AAAA 2001:db8::00cd
-aaaa-206 IN AAAA 2001:db8::00ce
-aaaa-207 IN AAAA 2001:db8::00cf
-aaaa-208 IN AAAA 2001:db8::00d0
-aaaa-209 IN AAAA 2001:db8::00d1
-aaaa-210 IN AAAA 2001:db8::00d2
-aaaa-211 IN AAAA 2001:db8::00d3
-aaaa-212 IN AAAA 2001:db8::00d4
-aaaa-213 IN AAAA 2001:db8::00d5
-aaaa-214 IN AAAA 2001:db8::00d6
-aaaa-215 IN AAAA 2001:db8::00d7
-aaaa-216 IN AAAA 2001:db8::00d8
-aaaa-217 IN AAAA 2001:db8::00d9
-aaaa-218 IN AAAA 2001:db8::00da
-aaaa-219 IN AAAA 2001:db8::00db
-aaaa-220 IN AAAA 2001:db8::00dc
-aaaa-221 IN AAAA 2001:db8::00dd
-aaaa-222 IN AAAA 2001:db8::00de
-aaaa-223 IN AAAA 2001:db8::00df
-aaaa-224 IN AAAA 2001:db8::00e0
-aaaa-225 IN AAAA 2001:db8::00e1
-aaaa-226 IN AAAA 2001:db8::00e2
-aaaa-227 IN AAAA 2001:db8::00e3
-aaaa-228 IN AAAA 2001:db8::00e4
-aaaa-229 IN AAAA 2001:db8::00e5
-aaaa-230 IN AAAA 2001:db8::00e6
-aaaa-231 IN AAAA 2001:db8::00e7
-aaaa-232 IN AAAA 2001:db8::00e8
-aaaa-233 IN AAAA 2001:db8::00e9
-aaaa-234 IN AAAA 2001:db8::00ea
-aaaa-235 IN AAAA 2001:db8::00eb
-aaaa-236 IN AAAA 2001:db8::00ec
-aaaa-237 IN AAAA 2001:db8::00ed
-aaaa-238 IN AAAA 2001:db8::00ee
-aaaa-239 IN AAAA 2001:db8::00ef
-aaaa-240 IN AAAA 2001:db8::00f0
-aaaa-241 IN AAAA 2001:db8::00f1
-aaaa-242 IN AAAA 2001:db8::00f2
-aaaa-243 IN AAAA 2001:db8::00f3
-aaaa-244 IN AAAA 2001:db8::00f4
-aaaa-245 IN AAAA 2001:db8::00f5
-aaaa-246 IN AAAA 2001:db8::00f6
-aaaa-247 IN AAAA 2001:db8::00f7
-aaaa-248 IN AAAA 2001:db8::00f8
-aaaa-249 IN AAAA 2001:db8::00f9
-aaaa-250 IN AAAA 2001:db8::00fa
-aaaa-251 IN AAAA 2001:db8::00fb
-aaaa-252 IN AAAA 2001:db8::00fc
-aaaa-253 IN AAAA 2001:db8::00fd
-aaaa-254 IN AAAA 2001:db8::00fe
-aaaa-255 IN AAAA 2001:db8::00ff
-aaaa-256 IN AAAA 2001:db8::0100
-aaaa-257 IN AAAA 2001:db8::0101
-aaaa-258 IN AAAA 2001:db8::0102
-aaaa-259 IN AAAA 2001:db8::0103
-aaaa-260 IN AAAA 2001:db8::0104
-aaaa-261 IN AAAA 2001:db8::0105
-aaaa-262 IN AAAA 2001:db8::0106
-aaaa-263 IN AAAA 2001:db8::0107
-aaaa-264 IN AAAA 2001:db8::0108
-aaaa-265 IN AAAA 2001:db8::0109
-aaaa-266 IN AAAA 2001:db8::010a
-aaaa-267 IN AAAA 2001:db8::010b
-aaaa-268 IN AAAA 2001:db8::010c
-aaaa-269 IN AAAA 2001:db8::010d
-aaaa-270 IN AAAA 2001:db8::010e
-aaaa-271 IN AAAA 2001:db8::010f
-aaaa-272 IN AAAA 2001:db8::0110
-aaaa-273 IN AAAA 2001:db8::0111
-aaaa-274 IN AAAA 2001:db8::0112
-aaaa-275 IN AAAA 2001:db8::0113
-aaaa-276 IN AAAA 2001:db8::0114
-aaaa-277 IN AAAA 2001:db8::0115
-aaaa-278 IN AAAA 2001:db8::0116
-aaaa-279 IN AAAA 2001:db8::0117
-aaaa-280 IN AAAA 2001:db8::0118
-aaaa-281 IN AAAA 2001:db8::0119
-aaaa-282 IN AAAA 2001:db8::011a
-aaaa-283 IN AAAA 2001:db8::011b
-aaaa-284 IN AAAA 2001:db8::011c
-aaaa-285 IN AAAA 2001:db8::011d
-aaaa-286 IN AAAA 2001:db8::011e
-aaaa-287 IN AAAA 2001:db8::011f
-aaaa-288 IN AAAA 2001:db8::0120
-aaaa-289 IN AAAA 2001:db8::0121
-aaaa-290 IN AAAA 2001:db8::0122
-aaaa-291 IN AAAA 2001:db8::0123
-aaaa-292 IN AAAA 2001:db8::0124
-aaaa-293 IN AAAA 2001:db8::0125
-aaaa-294 IN AAAA 2001:db8::0126
-aaaa-295 IN AAAA 2001:db8::0127
-aaaa-296 IN AAAA 2001:db8::0128
-aaaa-297 IN AAAA 2001:db8::0129
-aaaa-298 IN AAAA 2001:db8::012a
-aaaa-299 IN AAAA 2001:db8::012b
-aaaa-300 IN AAAA 2001:db8::012c
-aaaa-301 IN AAAA 2001:db8::012d
-aaaa-302 IN AAAA 2001:db8::012e
-aaaa-303 IN AAAA 2001:db8::012f
-aaaa-304 IN AAAA 2001:db8::0130
-aaaa-305 IN AAAA 2001:db8::0131
-aaaa-306 IN AAAA 2001:db8::0132
-aaaa-307 IN AAAA 2001:db8::0133
-aaaa-308 IN AAAA 2001:db8::0134
-aaaa-309 IN AAAA 2001:db8::0135
-aaaa-310 IN AAAA 2001:db8::0136
-aaaa-311 IN AAAA 2001:db8::0137
-aaaa-312 IN AAAA 2001:db8::0138
-aaaa-313 IN AAAA 2001:db8::0139
-aaaa-314 IN AAAA 2001:db8::013a
-aaaa-315 IN AAAA 2001:db8::013b
-aaaa-316 IN AAAA 2001:db8::013c
-aaaa-317 IN AAAA 2001:db8::013d
-aaaa-318 IN AAAA 2001:db8::013e
-aaaa-319 IN AAAA 2001:db8::013f
-aaaa-320 IN AAAA 2001:db8::0140
-aaaa-321 IN AAAA 2001:db8::0141
-aaaa-322 IN AAAA 2001:db8::0142
-aaaa-323 IN AAAA 2001:db8::0143
-aaaa-324 IN AAAA 2001:db8::0144
-aaaa-325 IN AAAA 2001:db8::0145
-aaaa-326 IN AAAA 2001:db8::0146
-aaaa-327 IN AAAA 2001:db8::0147
-aaaa-328 IN AAAA 2001:db8::0148
-aaaa-329 IN AAAA 2001:db8::0149
-aaaa-330 IN AAAA 2001:db8::014a
-aaaa-331 IN AAAA 2001:db8::014b
-aaaa-332 IN AAAA 2001:db8::014c
-aaaa-333 IN AAAA 2001:db8::014d
-aaaa-334 IN AAAA 2001:db8::014e
-aaaa-335 IN AAAA 2001:db8::014f
-aaaa-336 IN AAAA 2001:db8::0150
-aaaa-337 IN AAAA 2001:db8::0151
-aaaa-338 IN AAAA 2001:db8::0152
-aaaa-339 IN AAAA 2001:db8::0153
-aaaa-340 IN AAAA 2001:db8::0154
-aaaa-341 IN AAAA 2001:db8::0155
-aaaa-342 IN AAAA 2001:db8::0156
-aaaa-343 IN AAAA 2001:db8::0157
-aaaa-344 IN AAAA 2001:db8::0158
-aaaa-345 IN AAAA 2001:db8::0159
-aaaa-346 IN AAAA 2001:db8::015a
-aaaa-347 IN AAAA 2001:db8::015b
-aaaa-348 IN AAAA 2001:db8::015c
-aaaa-349 IN AAAA 2001:db8::015d
-aaaa-350 IN AAAA 2001:db8::015e
-aaaa-351 IN AAAA 2001:db8::015f
-aaaa-352 IN AAAA 2001:db8::0160
-aaaa-353 IN AAAA 2001:db8::0161
-aaaa-354 IN AAAA 2001:db8::0162
-aaaa-355 IN AAAA 2001:db8::0163
-aaaa-356 IN AAAA 2001:db8::0164
-aaaa-357 IN AAAA 2001:db8::0165
-aaaa-358 IN AAAA 2001:db8::0166
-aaaa-359 IN AAAA 2001:db8::0167
-aaaa-360 IN AAAA 2001:db8::0168
-aaaa-361 IN AAAA 2001:db8::0169
-aaaa-362 IN AAAA 2001:db8::016a
-aaaa-363 IN AAAA 2001:db8::016b
-aaaa-364 IN AAAA 2001:db8::016c
-aaaa-365 IN AAAA 2001:db8::016d
-aaaa-366 IN AAAA 2001:db8::016e
-aaaa-367 IN AAAA 2001:db8::016f
-aaaa-368 IN AAAA 2001:db8::0170
-aaaa-369 IN AAAA 2001:db8::0171
-aaaa-370 IN AAAA 2001:db8::0172
-aaaa-371 IN AAAA 2001:db8::0173
-aaaa-372 IN AAAA 2001:db8::0174
-aaaa-373 IN AAAA 2001:db8::0175
-aaaa-374 IN AAAA 2001:db8::0176
-aaaa-375 IN AAAA 2001:db8::0177
-aaaa-376 IN AAAA 2001:db8::0178
-aaaa-377 IN AAAA 2001:db8::0179
-aaaa-378 IN AAAA 2001:db8::017a
-aaaa-379 IN AAAA 2001:db8::017b
-aaaa-380 IN AAAA 2001:db8::017c
-aaaa-381 IN AAAA 2001:db8::017d
-aaaa-382 IN AAAA 2001:db8::017e
-aaaa-383 IN AAAA 2001:db8::017f
-aaaa-384 IN AAAA 2001:db8::0180
-aaaa-385 IN AAAA 2001:db8::0181
-aaaa-386 IN AAAA 2001:db8::0182
-aaaa-387 IN AAAA 2001:db8::0183
-aaaa-388 IN AAAA 2001:db8::0184
-aaaa-389 IN AAAA 2001:db8::0185
-aaaa-390 IN AAAA 2001:db8::0186
-aaaa-391 IN AAAA 2001:db8::0187
-aaaa-392 IN AAAA 2001:db8::0188
-aaaa-393 IN AAAA 2001:db8::0189
-aaaa-394 IN AAAA 2001:db8::018a
-aaaa-395 IN AAAA 2001:db8::018b
-aaaa-396 IN AAAA 2001:db8::018c
-aaaa-397 IN AAAA 2001:db8::018d
-aaaa-398 IN AAAA 2001:db8::018e
-aaaa-399 IN AAAA 2001:db8::018f
-aaaa-400 IN AAAA 2001:db8::0190
-aaaa-401 IN AAAA 2001:db8::0191
-aaaa-402 IN AAAA 2001:db8::0192
-aaaa-403 IN AAAA 2001:db8::0193
-aaaa-404 IN AAAA 2001:db8::0194
-aaaa-405 IN AAAA 2001:db8::0195
-aaaa-406 IN AAAA 2001:db8::0196
-aaaa-407 IN AAAA 2001:db8::0197
-aaaa-408 IN AAAA 2001:db8::0198
-aaaa-409 IN AAAA 2001:db8::0199
-aaaa-410 IN AAAA 2001:db8::019a
-aaaa-411 IN AAAA 2001:db8::019b
-aaaa-412 IN AAAA 2001:db8::019c
-aaaa-413 IN AAAA 2001:db8::019d
-aaaa-414 IN AAAA 2001:db8::019e
-aaaa-415 IN AAAA 2001:db8::019f
-aaaa-416 IN AAAA 2001:db8::01a0
-aaaa-417 IN AAAA 2001:db8::01a1
-aaaa-418 IN AAAA 2001:db8::01a2
-aaaa-419 IN AAAA 2001:db8::01a3
-aaaa-420 IN AAAA 2001:db8::01a4
-aaaa-421 IN AAAA 2001:db8::01a5
-aaaa-422 IN AAAA 2001:db8::01a6
-aaaa-423 IN AAAA 2001:db8::01a7
-aaaa-424 IN AAAA 2001:db8::01a8
-aaaa-425 IN AAAA 2001:db8::01a9
-aaaa-426 IN AAAA 2001:db8::01aa
-aaaa-427 IN AAAA 2001:db8::01ab
-aaaa-428 IN AAAA 2001:db8::01ac
-aaaa-429 IN AAAA 2001:db8::01ad
-aaaa-430 IN AAAA 2001:db8::01ae
-aaaa-431 IN AAAA 2001:db8::01af
-aaaa-432 IN AAAA 2001:db8::01b0
-aaaa-433 IN AAAA 2001:db8::01b1
-aaaa-434 IN AAAA 2001:db8::01b2
-aaaa-435 IN AAAA 2001:db8::01b3
-aaaa-436 IN AAAA 2001:db8::01b4
-aaaa-437 IN AAAA 2001:db8::01b5
-aaaa-438 IN AAAA 2001:db8::01b6
-aaaa-439 IN AAAA 2001:db8::01b7
-aaaa-440 IN AAAA 2001:db8::01b8
-aaaa-441 IN AAAA 2001:db8::01b9
-aaaa-442 IN AAAA 2001:db8::01ba
-aaaa-443 IN AAAA 2001:db8::01bb
-aaaa-444 IN AAAA 2001:db8::01bc
-aaaa-445 IN AAAA 2001:db8::01bd
-aaaa-446 IN AAAA 2001:db8::01be
-aaaa-447 IN AAAA 2001:db8::01bf
-aaaa-448 IN AAAA 2001:db8::01c0
-aaaa-449 IN AAAA 2001:db8::01c1
-aaaa-450 IN AAAA 2001:db8::01c2
-aaaa-451 IN AAAA 2001:db8::01c3
-aaaa-452 IN AAAA 2001:db8::01c4
-aaaa-453 IN AAAA 2001:db8::01c5
-aaaa-454 IN AAAA 2001:db8::01c6
-aaaa-455 IN AAAA 2001:db8::01c7
-aaaa-456 IN AAAA 2001:db8::01c8
-aaaa-457 IN AAAA 2001:db8::01c9
-aaaa-458 IN AAAA 2001:db8::01ca
-aaaa-459 IN AAAA 2001:db8::01cb
-aaaa-460 IN AAAA 2001:db8::01cc
-aaaa-461 IN AAAA 2001:db8::01cd
-aaaa-462 IN AAAA 2001:db8::01ce
-aaaa-463 IN AAAA 2001:db8::01cf
-aaaa-464 IN AAAA 2001:db8::01d0
-aaaa-465 IN AAAA 2001:db8::01d1
-aaaa-466 IN AAAA 2001:db8::01d2
-aaaa-467 IN AAAA 2001:db8::01d3
-aaaa-468 IN AAAA 2001:db8::01d4
-aaaa-469 IN AAAA 2001:db8::01d5
-aaaa-470 IN AAAA 2001:db8::01d6
-aaaa-471 IN AAAA 2001:db8::01d7
-aaaa-472 IN AAAA 2001:db8::01d8
-aaaa-473 IN AAAA 2001:db8::01d9
-aaaa-474 IN AAAA 2001:db8::01da
-aaaa-475 IN AAAA 2001:db8::01db
-aaaa-476 IN AAAA 2001:db8::01dc
-aaaa-477 IN AAAA 2001:db8::01dd
-aaaa-478 IN AAAA 2001:db8::01de
-aaaa-479 IN AAAA 2001:db8::01df
-aaaa-480 IN AAAA 2001:db8::01e0
-aaaa-481 IN AAAA 2001:db8::01e1
-aaaa-482 IN AAAA 2001:db8::01e2
-aaaa-483 IN AAAA 2001:db8::01e3
-aaaa-484 IN AAAA 2001:db8::01e4
-aaaa-485 IN AAAA 2001:db8::01e5
-aaaa-486 IN AAAA 2001:db8::01e6
-aaaa-487 IN AAAA 2001:db8::01e7
-aaaa-488 IN AAAA 2001:db8::01e8
-aaaa-489 IN AAAA 2001:db8::01e9
-aaaa-490 IN AAAA 2001:db8::01ea
-aaaa-491 IN AAAA 2001:db8::01eb
-aaaa-492 IN AAAA 2001:db8::01ec
-aaaa-493 IN AAAA 2001:db8::01ed
-aaaa-494 IN AAAA 2001:db8::01ee
-aaaa-495 IN AAAA 2001:db8::01ef
-aaaa-496 IN AAAA 2001:db8::01f0
-aaaa-497 IN AAAA 2001:db8::01f1
-aaaa-498 IN AAAA 2001:db8::01f2
-aaaa-499 IN AAAA 2001:db8::01f3
-aaaa-500 IN AAAA 2001:db8::01f4
-aaaa-501 IN AAAA 2001:db8::01f5
-aaaa-502 IN AAAA 2001:db8::01f6
-aaaa-503 IN AAAA 2001:db8::01f7
-aaaa-504 IN AAAA 2001:db8::01f8
-aaaa-505 IN AAAA 2001:db8::01f9
-aaaa-506 IN AAAA 2001:db8::01fa
-aaaa-507 IN AAAA 2001:db8::01fb
-aaaa-508 IN AAAA 2001:db8::01fc
-aaaa-509 IN AAAA 2001:db8::01fd
-aaaa-510 IN AAAA 2001:db8::01fe
-aaaa-511 IN AAAA 2001:db8::01ff
-
-bbbb-000 IN AAAA 2001:db8::1:0000
-bbbb-001 IN AAAA 2001:db8::1:0001
-bbbb-002 IN AAAA 2001:db8::1:0002
-bbbb-003 IN AAAA 2001:db8::1:0003
-bbbb-004 IN AAAA 2001:db8::1:0004
-bbbb-005 IN AAAA 2001:db8::1:0005
-bbbb-006 IN AAAA 2001:db8::1:0006
-bbbb-007 IN AAAA 2001:db8::1:0007
-bbbb-008 IN AAAA 2001:db8::1:0008
-bbbb-009 IN AAAA 2001:db8::1:0009
-bbbb-010 IN AAAA 2001:db8::1:000a
-bbbb-011 IN AAAA 2001:db8::1:000b
-bbbb-012 IN AAAA 2001:db8::1:000c
-bbbb-013 IN AAAA 2001:db8::1:000d
-bbbb-014 IN AAAA 2001:db8::1:000e
-bbbb-015 IN AAAA 2001:db8::1:000f
-bbbb-016 IN AAAA 2001:db8::1:0010
-bbbb-017 IN AAAA 2001:db8::1:0011
-bbbb-018 IN AAAA 2001:db8::1:0012
-bbbb-019 IN AAAA 2001:db8::1:0013
-bbbb-020 IN AAAA 2001:db8::1:0014
-bbbb-021 IN AAAA 2001:db8::1:0015
-bbbb-022 IN AAAA 2001:db8::1:0016
-bbbb-023 IN AAAA 2001:db8::1:0017
-bbbb-024 IN AAAA 2001:db8::1:0018
-bbbb-025 IN AAAA 2001:db8::1:0019
-bbbb-026 IN AAAA 2001:db8::1:001a
-bbbb-027 IN AAAA 2001:db8::1:001b
-bbbb-028 IN AAAA 2001:db8::1:001c
-bbbb-029 IN AAAA 2001:db8::1:001d
-bbbb-030 IN AAAA 2001:db8::1:001e
-bbbb-031 IN AAAA 2001:db8::1:001f
-bbbb-032 IN AAAA 2001:db8::1:0020
-bbbb-033 IN AAAA 2001:db8::1:0021
-bbbb-034 IN AAAA 2001:db8::1:0022
-bbbb-035 IN AAAA 2001:db8::1:0023
-bbbb-036 IN AAAA 2001:db8::1:0024
-bbbb-037 IN AAAA 2001:db8::1:0025
-bbbb-038 IN AAAA 2001:db8::1:0026
-bbbb-039 IN AAAA 2001:db8::1:0027
-bbbb-040 IN AAAA 2001:db8::1:0028
-bbbb-041 IN AAAA 2001:db8::1:0029
-bbbb-042 IN AAAA 2001:db8::1:002a
-bbbb-043 IN AAAA 2001:db8::1:002b
-bbbb-044 IN AAAA 2001:db8::1:002c
-bbbb-045 IN AAAA 2001:db8::1:002d
-bbbb-046 IN AAAA 2001:db8::1:002e
-bbbb-047 IN AAAA 2001:db8::1:002f
-bbbb-048 IN AAAA 2001:db8::1:0030
-bbbb-049 IN AAAA 2001:db8::1:0031
-bbbb-050 IN AAAA 2001:db8::1:0032
-bbbb-051 IN AAAA 2001:db8::1:0033
-bbbb-052 IN AAAA 2001:db8::1:0034
-bbbb-053 IN AAAA 2001:db8::1:0035
-bbbb-054 IN AAAA 2001:db8::1:0036
-bbbb-055 IN AAAA 2001:db8::1:0037
-bbbb-056 IN AAAA 2001:db8::1:0038
-bbbb-057 IN AAAA 2001:db8::1:0039
-bbbb-058 IN AAAA 2001:db8::1:003a
-bbbb-059 IN AAAA 2001:db8::1:003b
-bbbb-060 IN AAAA 2001:db8::1:003c
-bbbb-061 IN AAAA 2001:db8::1:003d
-bbbb-062 IN AAAA 2001:db8::1:003e
-bbbb-063 IN AAAA 2001:db8::1:003f
-bbbb-064 IN AAAA 2001:db8::1:0040
-bbbb-065 IN AAAA 2001:db8::1:0041
-bbbb-066 IN AAAA 2001:db8::1:0042
-bbbb-067 IN AAAA 2001:db8::1:0043
-bbbb-068 IN AAAA 2001:db8::1:0044
-bbbb-069 IN AAAA 2001:db8::1:0045
-bbbb-070 IN AAAA 2001:db8::1:0046
-bbbb-071 IN AAAA 2001:db8::1:0047
-bbbb-072 IN AAAA 2001:db8::1:0048
-bbbb-073 IN AAAA 2001:db8::1:0049
-bbbb-074 IN AAAA 2001:db8::1:004a
-bbbb-075 IN AAAA 2001:db8::1:004b
-bbbb-076 IN AAAA 2001:db8::1:004c
-bbbb-077 IN AAAA 2001:db8::1:004d
-bbbb-078 IN AAAA 2001:db8::1:004e
-bbbb-079 IN AAAA 2001:db8::1:004f
-bbbb-080 IN AAAA 2001:db8::1:0050
-bbbb-081 IN AAAA 2001:db8::1:0051
-bbbb-082 IN AAAA 2001:db8::1:0052
-bbbb-083 IN AAAA 2001:db8::1:0053
-bbbb-084 IN AAAA 2001:db8::1:0054
-bbbb-085 IN AAAA 2001:db8::1:0055
-bbbb-086 IN AAAA 2001:db8::1:0056
-bbbb-087 IN AAAA 2001:db8::1:0057
-bbbb-088 IN AAAA 2001:db8::1:0058
-bbbb-089 IN AAAA 2001:db8::1:0059
-bbbb-090 IN AAAA 2001:db8::1:005a
-bbbb-091 IN AAAA 2001:db8::1:005b
-bbbb-092 IN AAAA 2001:db8::1:005c
-bbbb-093 IN AAAA 2001:db8::1:005d
-bbbb-094 IN AAAA 2001:db8::1:005e
-bbbb-095 IN AAAA 2001:db8::1:005f
-bbbb-096 IN AAAA 2001:db8::1:0060
-bbbb-097 IN AAAA 2001:db8::1:0061
-bbbb-098 IN AAAA 2001:db8::1:0062
-bbbb-099 IN AAAA 2001:db8::1:0063
-bbbb-100 IN AAAA 2001:db8::1:0064
-bbbb-101 IN AAAA 2001:db8::1:0065
-bbbb-102 IN AAAA 2001:db8::1:0066
-bbbb-103 IN AAAA 2001:db8::1:0067
-bbbb-104 IN AAAA 2001:db8::1:0068
-bbbb-105 IN AAAA 2001:db8::1:0069
-bbbb-106 IN AAAA 2001:db8::1:006a
-bbbb-107 IN AAAA 2001:db8::1:006b
-bbbb-108 IN AAAA 2001:db8::1:006c
-bbbb-109 IN AAAA 2001:db8::1:006d
-bbbb-110 IN AAAA 2001:db8::1:006e
-bbbb-111 IN AAAA 2001:db8::1:006f
-bbbb-112 IN AAAA 2001:db8::1:0070
-bbbb-113 IN AAAA 2001:db8::1:0071
-bbbb-114 IN AAAA 2001:db8::1:0072
-bbbb-115 IN AAAA 2001:db8::1:0073
-bbbb-116 IN AAAA 2001:db8::1:0074
-bbbb-117 IN AAAA 2001:db8::1:0075
-bbbb-118 IN AAAA 2001:db8::1:0076
-bbbb-119 IN AAAA 2001:db8::1:0077
-bbbb-120 IN AAAA 2001:db8::1:0078
-bbbb-121 IN AAAA 2001:db8::1:0079
-bbbb-122 IN AAAA 2001:db8::1:007a
-bbbb-123 IN AAAA 2001:db8::1:007b
-bbbb-124 IN AAAA 2001:db8::1:007c
-bbbb-125 IN AAAA 2001:db8::1:007d
-bbbb-126 IN AAAA 2001:db8::1:007e
-bbbb-127 IN AAAA 2001:db8::1:007f
-bbbb-128 IN AAAA 2001:db8::1:0080
-bbbb-129 IN AAAA 2001:db8::1:0081
-bbbb-130 IN AAAA 2001:db8::1:0082
-bbbb-131 IN AAAA 2001:db8::1:0083
-bbbb-132 IN AAAA 2001:db8::1:0084
-bbbb-133 IN AAAA 2001:db8::1:0085
-bbbb-134 IN AAAA 2001:db8::1:0086
-bbbb-135 IN AAAA 2001:db8::1:0087
-bbbb-136 IN AAAA 2001:db8::1:0088
-bbbb-137 IN AAAA 2001:db8::1:0089
-bbbb-138 IN AAAA 2001:db8::1:008a
-bbbb-139 IN AAAA 2001:db8::1:008b
-bbbb-140 IN AAAA 2001:db8::1:008c
-bbbb-141 IN AAAA 2001:db8::1:008d
-bbbb-142 IN AAAA 2001:db8::1:008e
-bbbb-143 IN AAAA 2001:db8::1:008f
-bbbb-144 IN AAAA 2001:db8::1:0090
-bbbb-145 IN AAAA 2001:db8::1:0091
-bbbb-146 IN AAAA 2001:db8::1:0092
-bbbb-147 IN AAAA 2001:db8::1:0093
-bbbb-148 IN AAAA 2001:db8::1:0094
-bbbb-149 IN AAAA 2001:db8::1:0095
-bbbb-150 IN AAAA 2001:db8::1:0096
-bbbb-151 IN AAAA 2001:db8::1:0097
-bbbb-152 IN AAAA 2001:db8::1:0098
-bbbb-153 IN AAAA 2001:db8::1:0099
-bbbb-154 IN AAAA 2001:db8::1:009a
-bbbb-155 IN AAAA 2001:db8::1:009b
-bbbb-156 IN AAAA 2001:db8::1:009c
-bbbb-157 IN AAAA 2001:db8::1:009d
-bbbb-158 IN AAAA 2001:db8::1:009e
-bbbb-159 IN AAAA 2001:db8::1:009f
-bbbb-160 IN AAAA 2001:db8::1:00a0
-bbbb-161 IN AAAA 2001:db8::1:00a1
-bbbb-162 IN AAAA 2001:db8::1:00a2
-bbbb-163 IN AAAA 2001:db8::1:00a3
-bbbb-164 IN AAAA 2001:db8::1:00a4
-bbbb-165 IN AAAA 2001:db8::1:00a5
-bbbb-166 IN AAAA 2001:db8::1:00a6
-bbbb-167 IN AAAA 2001:db8::1:00a7
-bbbb-168 IN AAAA 2001:db8::1:00a8
-bbbb-169 IN AAAA 2001:db8::1:00a9
-bbbb-170 IN AAAA 2001:db8::1:00aa
-bbbb-171 IN AAAA 2001:db8::1:00ab
-bbbb-172 IN AAAA 2001:db8::1:00ac
-bbbb-173 IN AAAA 2001:db8::1:00ad
-bbbb-174 IN AAAA 2001:db8::1:00ae
-bbbb-175 IN AAAA 2001:db8::1:00af
-bbbb-176 IN AAAA 2001:db8::1:00b0
-bbbb-177 IN AAAA 2001:db8::1:00b1
-bbbb-178 IN AAAA 2001:db8::1:00b2
-bbbb-179 IN AAAA 2001:db8::1:00b3
-bbbb-180 IN AAAA 2001:db8::1:00b4
-bbbb-181 IN AAAA 2001:db8::1:00b5
-bbbb-182 IN AAAA 2001:db8::1:00b6
-bbbb-183 IN AAAA 2001:db8::1:00b7
-bbbb-184 IN AAAA 2001:db8::1:00b8
-bbbb-185 IN AAAA 2001:db8::1:00b9
-bbbb-186 IN AAAA 2001:db8::1:00ba
-bbbb-187 IN AAAA 2001:db8::1:00bb
-bbbb-188 IN AAAA 2001:db8::1:00bc
-bbbb-189 IN AAAA 2001:db8::1:00bd
-bbbb-190 IN AAAA 2001:db8::1:00be
-bbbb-191 IN AAAA 2001:db8::1:00bf
-bbbb-192 IN AAAA 2001:db8::1:00c0
-bbbb-193 IN AAAA 2001:db8::1:00c1
-bbbb-194 IN AAAA 2001:db8::1:00c2
-bbbb-195 IN AAAA 2001:db8::1:00c3
-bbbb-196 IN AAAA 2001:db8::1:00c4
-bbbb-197 IN AAAA 2001:db8::1:00c5
-bbbb-198 IN AAAA 2001:db8::1:00c6
-bbbb-199 IN AAAA 2001:db8::1:00c7
-bbbb-200 IN AAAA 2001:db8::1:00c8
-bbbb-201 IN AAAA 2001:db8::1:00c9
-bbbb-202 IN AAAA 2001:db8::1:00ca
-bbbb-203 IN AAAA 2001:db8::1:00cb
-bbbb-204 IN AAAA 2001:db8::1:00cc
-bbbb-205 IN AAAA 2001:db8::1:00cd
-bbbb-206 IN AAAA 2001:db8::1:00ce
-bbbb-207 IN AAAA 2001:db8::1:00cf
-bbbb-208 IN AAAA 2001:db8::1:00d0
-bbbb-209 IN AAAA 2001:db8::1:00d1
-bbbb-210 IN AAAA 2001:db8::1:00d2
-bbbb-211 IN AAAA 2001:db8::1:00d3
-bbbb-212 IN AAAA 2001:db8::1:00d4
-bbbb-213 IN AAAA 2001:db8::1:00d5
-bbbb-214 IN AAAA 2001:db8::1:00d6
-bbbb-215 IN AAAA 2001:db8::1:00d7
-bbbb-216 IN AAAA 2001:db8::1:00d8
-bbbb-217 IN AAAA 2001:db8::1:00d9
-bbbb-218 IN AAAA 2001:db8::1:00da
-bbbb-219 IN AAAA 2001:db8::1:00db
-bbbb-220 IN AAAA 2001:db8::1:00dc
-bbbb-221 IN AAAA 2001:db8::1:00dd
-bbbb-222 IN AAAA 2001:db8::1:00de
-bbbb-223 IN AAAA 2001:db8::1:00df
-bbbb-224 IN AAAA 2001:db8::1:00e0
-bbbb-225 IN AAAA 2001:db8::1:00e1
-bbbb-226 IN AAAA 2001:db8::1:00e2
-bbbb-227 IN AAAA 2001:db8::1:00e3
-bbbb-228 IN AAAA 2001:db8::1:00e4
-bbbb-229 IN AAAA 2001:db8::1:00e5
-bbbb-230 IN AAAA 2001:db8::1:00e6
-bbbb-231 IN AAAA 2001:db8::1:00e7
-bbbb-232 IN AAAA 2001:db8::1:00e8
-bbbb-233 IN AAAA 2001:db8::1:00e9
-bbbb-234 IN AAAA 2001:db8::1:00ea
-bbbb-235 IN AAAA 2001:db8::1:00eb
-bbbb-236 IN AAAA 2001:db8::1:00ec
-bbbb-237 IN AAAA 2001:db8::1:00ed
-bbbb-238 IN AAAA 2001:db8::1:00ee
-bbbb-239 IN AAAA 2001:db8::1:00ef
-bbbb-240 IN AAAA 2001:db8::1:00f0
-bbbb-241 IN AAAA 2001:db8::1:00f1
-bbbb-242 IN AAAA 2001:db8::1:00f2
-bbbb-243 IN AAAA 2001:db8::1:00f3
-bbbb-244 IN AAAA 2001:db8::1:00f4
-bbbb-245 IN AAAA 2001:db8::1:00f5
-bbbb-246 IN AAAA 2001:db8::1:00f6
-bbbb-247 IN AAAA 2001:db8::1:00f7
-bbbb-248 IN AAAA 2001:db8::1:00f8
-bbbb-249 IN AAAA 2001:db8::1:00f9
-bbbb-250 IN AAAA 2001:db8::1:00fa
-bbbb-251 IN AAAA 2001:db8::1:00fb
-bbbb-252 IN AAAA 2001:db8::1:00fc
-bbbb-253 IN AAAA 2001:db8::1:00fd
-bbbb-254 IN AAAA 2001:db8::1:00fe
-bbbb-255 IN AAAA 2001:db8::1:00ff
-bbbb-256 IN AAAA 2001:db8::1:0100
-bbbb-257 IN AAAA 2001:db8::1:0101
-bbbb-258 IN AAAA 2001:db8::1:0102
-bbbb-259 IN AAAA 2001:db8::1:0103
-bbbb-260 IN AAAA 2001:db8::1:0104
-bbbb-261 IN AAAA 2001:db8::1:0105
-bbbb-262 IN AAAA 2001:db8::1:0106
-bbbb-263 IN AAAA 2001:db8::1:0107
-bbbb-264 IN AAAA 2001:db8::1:0108
-bbbb-265 IN AAAA 2001:db8::1:0109
-bbbb-266 IN AAAA 2001:db8::1:010a
-bbbb-267 IN AAAA 2001:db8::1:010b
-bbbb-268 IN AAAA 2001:db8::1:010c
-bbbb-269 IN AAAA 2001:db8::1:010d
-bbbb-270 IN AAAA 2001:db8::1:010e
-bbbb-271 IN AAAA 2001:db8::1:010f
-bbbb-272 IN AAAA 2001:db8::1:0110
-bbbb-273 IN AAAA 2001:db8::1:0111
-bbbb-274 IN AAAA 2001:db8::1:0112
-bbbb-275 IN AAAA 2001:db8::1:0113
-bbbb-276 IN AAAA 2001:db8::1:0114
-bbbb-277 IN AAAA 2001:db8::1:0115
-bbbb-278 IN AAAA 2001:db8::1:0116
-bbbb-279 IN AAAA 2001:db8::1:0117
-bbbb-280 IN AAAA 2001:db8::1:0118
-bbbb-281 IN AAAA 2001:db8::1:0119
-bbbb-282 IN AAAA 2001:db8::1:011a
-bbbb-283 IN AAAA 2001:db8::1:011b
-bbbb-284 IN AAAA 2001:db8::1:011c
-bbbb-285 IN AAAA 2001:db8::1:011d
-bbbb-286 IN AAAA 2001:db8::1:011e
-bbbb-287 IN AAAA 2001:db8::1:011f
-bbbb-288 IN AAAA 2001:db8::1:0120
-bbbb-289 IN AAAA 2001:db8::1:0121
-bbbb-290 IN AAAA 2001:db8::1:0122
-bbbb-291 IN AAAA 2001:db8::1:0123
-bbbb-292 IN AAAA 2001:db8::1:0124
-bbbb-293 IN AAAA 2001:db8::1:0125
-bbbb-294 IN AAAA 2001:db8::1:0126
-bbbb-295 IN AAAA 2001:db8::1:0127
-bbbb-296 IN AAAA 2001:db8::1:0128
-bbbb-297 IN AAAA 2001:db8::1:0129
-bbbb-298 IN AAAA 2001:db8::1:012a
-bbbb-299 IN AAAA 2001:db8::1:012b
-bbbb-300 IN AAAA 2001:db8::1:012c
-bbbb-301 IN AAAA 2001:db8::1:012d
-bbbb-302 IN AAAA 2001:db8::1:012e
-bbbb-303 IN AAAA 2001:db8::1:012f
-bbbb-304 IN AAAA 2001:db8::1:0130
-bbbb-305 IN AAAA 2001:db8::1:0131
-bbbb-306 IN AAAA 2001:db8::1:0132
-bbbb-307 IN AAAA 2001:db8::1:0133
-bbbb-308 IN AAAA 2001:db8::1:0134
-bbbb-309 IN AAAA 2001:db8::1:0135
-bbbb-310 IN AAAA 2001:db8::1:0136
-bbbb-311 IN AAAA 2001:db8::1:0137
-bbbb-312 IN AAAA 2001:db8::1:0138
-bbbb-313 IN AAAA 2001:db8::1:0139
-bbbb-314 IN AAAA 2001:db8::1:013a
-bbbb-315 IN AAAA 2001:db8::1:013b
-bbbb-316 IN AAAA 2001:db8::1:013c
-bbbb-317 IN AAAA 2001:db8::1:013d
-bbbb-318 IN AAAA 2001:db8::1:013e
-bbbb-319 IN AAAA 2001:db8::1:013f
-bbbb-320 IN AAAA 2001:db8::1:0140
-bbbb-321 IN AAAA 2001:db8::1:0141
-bbbb-322 IN AAAA 2001:db8::1:0142
-bbbb-323 IN AAAA 2001:db8::1:0143
-bbbb-324 IN AAAA 2001:db8::1:0144
-bbbb-325 IN AAAA 2001:db8::1:0145
-bbbb-326 IN AAAA 2001:db8::1:0146
-bbbb-327 IN AAAA 2001:db8::1:0147
-bbbb-328 IN AAAA 2001:db8::1:0148
-bbbb-329 IN AAAA 2001:db8::1:0149
-bbbb-330 IN AAAA 2001:db8::1:014a
-bbbb-331 IN AAAA 2001:db8::1:014b
-bbbb-332 IN AAAA 2001:db8::1:014c
-bbbb-333 IN AAAA 2001:db8::1:014d
-bbbb-334 IN AAAA 2001:db8::1:014e
-bbbb-335 IN AAAA 2001:db8::1:014f
-bbbb-336 IN AAAA 2001:db8::1:0150
-bbbb-337 IN AAAA 2001:db8::1:0151
-bbbb-338 IN AAAA 2001:db8::1:0152
-bbbb-339 IN AAAA 2001:db8::1:0153
-bbbb-340 IN AAAA 2001:db8::1:0154
-bbbb-341 IN AAAA 2001:db8::1:0155
-bbbb-342 IN AAAA 2001:db8::1:0156
-bbbb-343 IN AAAA 2001:db8::1:0157
-bbbb-344 IN AAAA 2001:db8::1:0158
-bbbb-345 IN AAAA 2001:db8::1:0159
-bbbb-346 IN AAAA 2001:db8::1:015a
-bbbb-347 IN AAAA 2001:db8::1:015b
-bbbb-348 IN AAAA 2001:db8::1:015c
-bbbb-349 IN AAAA 2001:db8::1:015d
-bbbb-350 IN AAAA 2001:db8::1:015e
-bbbb-351 IN AAAA 2001:db8::1:015f
-bbbb-352 IN AAAA 2001:db8::1:0160
-bbbb-353 IN AAAA 2001:db8::1:0161
-bbbb-354 IN AAAA 2001:db8::1:0162
-bbbb-355 IN AAAA 2001:db8::1:0163
-bbbb-356 IN AAAA 2001:db8::1:0164
-bbbb-357 IN AAAA 2001:db8::1:0165
-bbbb-358 IN AAAA 2001:db8::1:0166
-bbbb-359 IN AAAA 2001:db8::1:0167
-bbbb-360 IN AAAA 2001:db8::1:0168
-bbbb-361 IN AAAA 2001:db8::1:0169
-bbbb-362 IN AAAA 2001:db8::1:016a
-bbbb-363 IN AAAA 2001:db8::1:016b
-bbbb-364 IN AAAA 2001:db8::1:016c
-bbbb-365 IN AAAA 2001:db8::1:016d
-bbbb-366 IN AAAA 2001:db8::1:016e
-bbbb-367 IN AAAA 2001:db8::1:016f
-bbbb-368 IN AAAA 2001:db8::1:0170
-bbbb-369 IN AAAA 2001:db8::1:0171
-bbbb-370 IN AAAA 2001:db8::1:0172
-bbbb-371 IN AAAA 2001:db8::1:0173
-bbbb-372 IN AAAA 2001:db8::1:0174
-bbbb-373 IN AAAA 2001:db8::1:0175
-bbbb-374 IN AAAA 2001:db8::1:0176
-bbbb-375 IN AAAA 2001:db8::1:0177
-bbbb-376 IN AAAA 2001:db8::1:0178
-bbbb-377 IN AAAA 2001:db8::1:0179
-bbbb-378 IN AAAA 2001:db8::1:017a
-bbbb-379 IN AAAA 2001:db8::1:017b
-bbbb-380 IN AAAA 2001:db8::1:017c
-bbbb-381 IN AAAA 2001:db8::1:017d
-bbbb-382 IN AAAA 2001:db8::1:017e
-bbbb-383 IN AAAA 2001:db8::1:017f
-bbbb-384 IN AAAA 2001:db8::1:0180
-bbbb-385 IN AAAA 2001:db8::1:0181
-bbbb-386 IN AAAA 2001:db8::1:0182
-bbbb-387 IN AAAA 2001:db8::1:0183
-bbbb-388 IN AAAA 2001:db8::1:0184
-bbbb-389 IN AAAA 2001:db8::1:0185
-bbbb-390 IN AAAA 2001:db8::1:0186
-bbbb-391 IN AAAA 2001:db8::1:0187
-bbbb-392 IN AAAA 2001:db8::1:0188
-bbbb-393 IN AAAA 2001:db8::1:0189
-bbbb-394 IN AAAA 2001:db8::1:018a
-bbbb-395 IN AAAA 2001:db8::1:018b
-bbbb-396 IN AAAA 2001:db8::1:018c
-bbbb-397 IN AAAA 2001:db8::1:018d
-bbbb-398 IN AAAA 2001:db8::1:018e
-bbbb-399 IN AAAA 2001:db8::1:018f
-bbbb-400 IN AAAA 2001:db8::1:0190
-bbbb-401 IN AAAA 2001:db8::1:0191
-bbbb-402 IN AAAA 2001:db8::1:0192
-bbbb-403 IN AAAA 2001:db8::1:0193
-bbbb-404 IN AAAA 2001:db8::1:0194
-bbbb-405 IN AAAA 2001:db8::1:0195
-bbbb-406 IN AAAA 2001:db8::1:0196
-bbbb-407 IN AAAA 2001:db8::1:0197
-bbbb-408 IN AAAA 2001:db8::1:0198
-bbbb-409 IN AAAA 2001:db8::1:0199
-bbbb-410 IN AAAA 2001:db8::1:019a
-bbbb-411 IN AAAA 2001:db8::1:019b
-bbbb-412 IN AAAA 2001:db8::1:019c
-bbbb-413 IN AAAA 2001:db8::1:019d
-bbbb-414 IN AAAA 2001:db8::1:019e
-bbbb-415 IN AAAA 2001:db8::1:019f
-bbbb-416 IN AAAA 2001:db8::1:01a0
-bbbb-417 IN AAAA 2001:db8::1:01a1
-bbbb-418 IN AAAA 2001:db8::1:01a2
-bbbb-419 IN AAAA 2001:db8::1:01a3
-bbbb-420 IN AAAA 2001:db8::1:01a4
-bbbb-421 IN AAAA 2001:db8::1:01a5
-bbbb-422 IN AAAA 2001:db8::1:01a6
-bbbb-423 IN AAAA 2001:db8::1:01a7
-bbbb-424 IN AAAA 2001:db8::1:01a8
-bbbb-425 IN AAAA 2001:db8::1:01a9
-bbbb-426 IN AAAA 2001:db8::1:01aa
-bbbb-427 IN AAAA 2001:db8::1:01ab
-bbbb-428 IN AAAA 2001:db8::1:01ac
-bbbb-429 IN AAAA 2001:db8::1:01ad
-bbbb-430 IN AAAA 2001:db8::1:01ae
-bbbb-431 IN AAAA 2001:db8::1:01af
-bbbb-432 IN AAAA 2001:db8::1:01b0
-bbbb-433 IN AAAA 2001:db8::1:01b1
-bbbb-434 IN AAAA 2001:db8::1:01b2
-bbbb-435 IN AAAA 2001:db8::1:01b3
-bbbb-436 IN AAAA 2001:db8::1:01b4
-bbbb-437 IN AAAA 2001:db8::1:01b5
-bbbb-438 IN AAAA 2001:db8::1:01b6
-bbbb-439 IN AAAA 2001:db8::1:01b7
-bbbb-440 IN AAAA 2001:db8::1:01b8
-bbbb-441 IN AAAA 2001:db8::1:01b9
-bbbb-442 IN AAAA 2001:db8::1:01ba
-bbbb-443 IN AAAA 2001:db8::1:01bb
-bbbb-444 IN AAAA 2001:db8::1:01bc
-bbbb-445 IN AAAA 2001:db8::1:01bd
-bbbb-446 IN AAAA 2001:db8::1:01be
-bbbb-447 IN AAAA 2001:db8::1:01bf
-bbbb-448 IN AAAA 2001:db8::1:01c0
-bbbb-449 IN AAAA 2001:db8::1:01c1
-bbbb-450 IN AAAA 2001:db8::1:01c2
-bbbb-451 IN AAAA 2001:db8::1:01c3
-bbbb-452 IN AAAA 2001:db8::1:01c4
-bbbb-453 IN AAAA 2001:db8::1:01c5
-bbbb-454 IN AAAA 2001:db8::1:01c6
-bbbb-455 IN AAAA 2001:db8::1:01c7
-bbbb-456 IN AAAA 2001:db8::1:01c8
-bbbb-457 IN AAAA 2001:db8::1:01c9
-bbbb-458 IN AAAA 2001:db8::1:01ca
-bbbb-459 IN AAAA 2001:db8::1:01cb
-bbbb-460 IN AAAA 2001:db8::1:01cc
-bbbb-461 IN AAAA 2001:db8::1:01cd
-bbbb-462 IN AAAA 2001:db8::1:01ce
-bbbb-463 IN AAAA 2001:db8::1:01cf
-bbbb-464 IN AAAA 2001:db8::1:01d0
-bbbb-465 IN AAAA 2001:db8::1:01d1
-bbbb-466 IN AAAA 2001:db8::1:01d2
-bbbb-467 IN AAAA 2001:db8::1:01d3
-bbbb-468 IN AAAA 2001:db8::1:01d4
-bbbb-469 IN AAAA 2001:db8::1:01d5
-bbbb-470 IN AAAA 2001:db8::1:01d6
-bbbb-471 IN AAAA 2001:db8::1:01d7
-bbbb-472 IN AAAA 2001:db8::1:01d8
-bbbb-473 IN AAAA 2001:db8::1:01d9
-bbbb-474 IN AAAA 2001:db8::1:01da
-bbbb-475 IN AAAA 2001:db8::1:01db
-bbbb-476 IN AAAA 2001:db8::1:01dc
-bbbb-477 IN AAAA 2001:db8::1:01dd
-bbbb-478 IN AAAA 2001:db8::1:01de
-bbbb-479 IN AAAA 2001:db8::1:01df
-bbbb-480 IN AAAA 2001:db8::1:01e0
-bbbb-481 IN AAAA 2001:db8::1:01e1
-bbbb-482 IN AAAA 2001:db8::1:01e2
-bbbb-483 IN AAAA 2001:db8::1:01e3
-bbbb-484 IN AAAA 2001:db8::1:01e4
-bbbb-485 IN AAAA 2001:db8::1:01e5
-bbbb-486 IN AAAA 2001:db8::1:01e6
-bbbb-487 IN AAAA 2001:db8::1:01e7
-bbbb-488 IN AAAA 2001:db8::1:01e8
-bbbb-489 IN AAAA 2001:db8::1:01e9
-bbbb-490 IN AAAA 2001:db8::1:01ea
-bbbb-491 IN AAAA 2001:db8::1:01eb
-bbbb-492 IN AAAA 2001:db8::1:01ec
-bbbb-493 IN AAAA 2001:db8::1:01ed
-bbbb-494 IN AAAA 2001:db8::1:01ee
-bbbb-495 IN AAAA 2001:db8::1:01ef
-bbbb-496 IN AAAA 2001:db8::1:01f0
-bbbb-497 IN AAAA 2001:db8::1:01f1
-bbbb-498 IN AAAA 2001:db8::1:01f2
-bbbb-499 IN AAAA 2001:db8::1:01f3
-bbbb-500 IN AAAA 2001:db8::1:01f4
-bbbb-501 IN AAAA 2001:db8::1:01f5
-bbbb-502 IN AAAA 2001:db8::1:01f6
-bbbb-503 IN AAAA 2001:db8::1:01f7
-bbbb-504 IN AAAA 2001:db8::1:01f8
-bbbb-505 IN AAAA 2001:db8::1:01f9
-bbbb-506 IN AAAA 2001:db8::1:01fa
-bbbb-507 IN AAAA 2001:db8::1:01fb
-bbbb-508 IN AAAA 2001:db8::1:01fc
-bbbb-509 IN AAAA 2001:db8::1:01fd
-bbbb-510 IN AAAA 2001:db8::1:01fe
-bbbb-511 IN AAAA 2001:db8::1:01ff
-
-cccc-000 IN AAAA 2001:db8::2:0000
-cccc-001 IN AAAA 2001:db8::2:0001
-cccc-002 IN AAAA 2001:db8::2:0002
-cccc-003 IN AAAA 2001:db8::2:0003
-cccc-004 IN AAAA 2001:db8::2:0004
-cccc-005 IN AAAA 2001:db8::2:0005
-cccc-006 IN AAAA 2001:db8::2:0006
-cccc-007 IN AAAA 2001:db8::2:0007
-cccc-008 IN AAAA 2001:db8::2:0008
-cccc-009 IN AAAA 2001:db8::2:0009
-cccc-010 IN AAAA 2001:db8::2:000a
-cccc-011 IN AAAA 2001:db8::2:000b
-cccc-012 IN AAAA 2001:db8::2:000c
-cccc-013 IN AAAA 2001:db8::2:000d
-cccc-014 IN AAAA 2001:db8::2:000e
-cccc-015 IN AAAA 2001:db8::2:000f
-cccc-016 IN AAAA 2001:db8::2:0010
-cccc-017 IN AAAA 2001:db8::2:0011
-cccc-018 IN AAAA 2001:db8::2:0012
-cccc-019 IN AAAA 2001:db8::2:0013
-cccc-020 IN AAAA 2001:db8::2:0014
-cccc-021 IN AAAA 2001:db8::2:0015
-cccc-022 IN AAAA 2001:db8::2:0016
-cccc-023 IN AAAA 2001:db8::2:0017
-cccc-024 IN AAAA 2001:db8::2:0018
-cccc-025 IN AAAA 2001:db8::2:0019
-cccc-026 IN AAAA 2001:db8::2:001a
-cccc-027 IN AAAA 2001:db8::2:001b
-cccc-028 IN AAAA 2001:db8::2:001c
-cccc-029 IN AAAA 2001:db8::2:001d
-cccc-030 IN AAAA 2001:db8::2:001e
-cccc-031 IN AAAA 2001:db8::2:001f
-cccc-032 IN AAAA 2001:db8::2:0020
-cccc-033 IN AAAA 2001:db8::2:0021
-cccc-034 IN AAAA 2001:db8::2:0022
-cccc-035 IN AAAA 2001:db8::2:0023
-cccc-036 IN AAAA 2001:db8::2:0024
-cccc-037 IN AAAA 2001:db8::2:0025
-cccc-038 IN AAAA 2001:db8::2:0026
-cccc-039 IN AAAA 2001:db8::2:0027
-cccc-040 IN AAAA 2001:db8::2:0028
-cccc-041 IN AAAA 2001:db8::2:0029
-cccc-042 IN AAAA 2001:db8::2:002a
-cccc-043 IN AAAA 2001:db8::2:002b
-cccc-044 IN AAAA 2001:db8::2:002c
-cccc-045 IN AAAA 2001:db8::2:002d
-cccc-046 IN AAAA 2001:db8::2:002e
-cccc-047 IN AAAA 2001:db8::2:002f
-cccc-048 IN AAAA 2001:db8::2:0030
-cccc-049 IN AAAA 2001:db8::2:0031
-cccc-050 IN AAAA 2001:db8::2:0032
-cccc-051 IN AAAA 2001:db8::2:0033
-cccc-052 IN AAAA 2001:db8::2:0034
-cccc-053 IN AAAA 2001:db8::2:0035
-cccc-054 IN AAAA 2001:db8::2:0036
-cccc-055 IN AAAA 2001:db8::2:0037
-cccc-056 IN AAAA 2001:db8::2:0038
-cccc-057 IN AAAA 2001:db8::2:0039
-cccc-058 IN AAAA 2001:db8::2:003a
-cccc-059 IN AAAA 2001:db8::2:003b
-cccc-060 IN AAAA 2001:db8::2:003c
-cccc-061 IN AAAA 2001:db8::2:003d
-cccc-062 IN AAAA 2001:db8::2:003e
-cccc-063 IN AAAA 2001:db8::2:003f
-cccc-064 IN AAAA 2001:db8::2:0040
-cccc-065 IN AAAA 2001:db8::2:0041
-cccc-066 IN AAAA 2001:db8::2:0042
-cccc-067 IN AAAA 2001:db8::2:0043
-cccc-068 IN AAAA 2001:db8::2:0044
-cccc-069 IN AAAA 2001:db8::2:0045
-cccc-070 IN AAAA 2001:db8::2:0046
-cccc-071 IN AAAA 2001:db8::2:0047
-cccc-072 IN AAAA 2001:db8::2:0048
-cccc-073 IN AAAA 2001:db8::2:0049
-cccc-074 IN AAAA 2001:db8::2:004a
-cccc-075 IN AAAA 2001:db8::2:004b
-cccc-076 IN AAAA 2001:db8::2:004c
-cccc-077 IN AAAA 2001:db8::2:004d
-cccc-078 IN AAAA 2001:db8::2:004e
-cccc-079 IN AAAA 2001:db8::2:004f
-cccc-080 IN AAAA 2001:db8::2:0050
-cccc-081 IN AAAA 2001:db8::2:0051
-cccc-082 IN AAAA 2001:db8::2:0052
-cccc-083 IN AAAA 2001:db8::2:0053
-cccc-084 IN AAAA 2001:db8::2:0054
-cccc-085 IN AAAA 2001:db8::2:0055
-cccc-086 IN AAAA 2001:db8::2:0056
-cccc-087 IN AAAA 2001:db8::2:0057
-cccc-088 IN AAAA 2001:db8::2:0058
-cccc-089 IN AAAA 2001:db8::2:0059
-cccc-090 IN AAAA 2001:db8::2:005a
-cccc-091 IN AAAA 2001:db8::2:005b
-cccc-092 IN AAAA 2001:db8::2:005c
-cccc-093 IN AAAA 2001:db8::2:005d
-cccc-094 IN AAAA 2001:db8::2:005e
-cccc-095 IN AAAA 2001:db8::2:005f
-cccc-096 IN AAAA 2001:db8::2:0060
-cccc-097 IN AAAA 2001:db8::2:0061
-cccc-098 IN AAAA 2001:db8::2:0062
-cccc-099 IN AAAA 2001:db8::2:0063
-cccc-100 IN AAAA 2001:db8::2:0064
-cccc-101 IN AAAA 2001:db8::2:0065
-cccc-102 IN AAAA 2001:db8::2:0066
-cccc-103 IN AAAA 2001:db8::2:0067
-cccc-104 IN AAAA 2001:db8::2:0068
-cccc-105 IN AAAA 2001:db8::2:0069
-cccc-106 IN AAAA 2001:db8::2:006a
-cccc-107 IN AAAA 2001:db8::2:006b
-cccc-108 IN AAAA 2001:db8::2:006c
-cccc-109 IN AAAA 2001:db8::2:006d
-cccc-110 IN AAAA 2001:db8::2:006e
-cccc-111 IN AAAA 2001:db8::2:006f
-cccc-112 IN AAAA 2001:db8::2:0070
-cccc-113 IN AAAA 2001:db8::2:0071
-cccc-114 IN AAAA 2001:db8::2:0072
-cccc-115 IN AAAA 2001:db8::2:0073
-cccc-116 IN AAAA 2001:db8::2:0074
-cccc-117 IN AAAA 2001:db8::2:0075
-cccc-118 IN AAAA 2001:db8::2:0076
-cccc-119 IN AAAA 2001:db8::2:0077
-cccc-120 IN AAAA 2001:db8::2:0078
-cccc-121 IN AAAA 2001:db8::2:0079
-cccc-122 IN AAAA 2001:db8::2:007a
-cccc-123 IN AAAA 2001:db8::2:007b
-cccc-124 IN AAAA 2001:db8::2:007c
-cccc-125 IN AAAA 2001:db8::2:007d
-cccc-126 IN AAAA 2001:db8::2:007e
-cccc-127 IN AAAA 2001:db8::2:007f
-cccc-128 IN AAAA 2001:db8::2:0080
-cccc-129 IN AAAA 2001:db8::2:0081
-cccc-130 IN AAAA 2001:db8::2:0082
-cccc-131 IN AAAA 2001:db8::2:0083
-cccc-132 IN AAAA 2001:db8::2:0084
-cccc-133 IN AAAA 2001:db8::2:0085
-cccc-134 IN AAAA 2001:db8::2:0086
-cccc-135 IN AAAA 2001:db8::2:0087
-cccc-136 IN AAAA 2001:db8::2:0088
-cccc-137 IN AAAA 2001:db8::2:0089
-cccc-138 IN AAAA 2001:db8::2:008a
-cccc-139 IN AAAA 2001:db8::2:008b
-cccc-140 IN AAAA 2001:db8::2:008c
-cccc-141 IN AAAA 2001:db8::2:008d
-cccc-142 IN AAAA 2001:db8::2:008e
-cccc-143 IN AAAA 2001:db8::2:008f
-cccc-144 IN AAAA 2001:db8::2:0090
-cccc-145 IN AAAA 2001:db8::2:0091
-cccc-146 IN AAAA 2001:db8::2:0092
-cccc-147 IN AAAA 2001:db8::2:0093
-cccc-148 IN AAAA 2001:db8::2:0094
-cccc-149 IN AAAA 2001:db8::2:0095
-cccc-150 IN AAAA 2001:db8::2:0096
-cccc-151 IN AAAA 2001:db8::2:0097
-cccc-152 IN AAAA 2001:db8::2:0098
-cccc-153 IN AAAA 2001:db8::2:0099
-cccc-154 IN AAAA 2001:db8::2:009a
-cccc-155 IN AAAA 2001:db8::2:009b
-cccc-156 IN AAAA 2001:db8::2:009c
-cccc-157 IN AAAA 2001:db8::2:009d
-cccc-158 IN AAAA 2001:db8::2:009e
-cccc-159 IN AAAA 2001:db8::2:009f
-cccc-160 IN AAAA 2001:db8::2:00a0
-cccc-161 IN AAAA 2001:db8::2:00a1
-cccc-162 IN AAAA 2001:db8::2:00a2
-cccc-163 IN AAAA 2001:db8::2:00a3
-cccc-164 IN AAAA 2001:db8::2:00a4
-cccc-165 IN AAAA 2001:db8::2:00a5
-cccc-166 IN AAAA 2001:db8::2:00a6
-cccc-167 IN AAAA 2001:db8::2:00a7
-cccc-168 IN AAAA 2001:db8::2:00a8
-cccc-169 IN AAAA 2001:db8::2:00a9
-cccc-170 IN AAAA 2001:db8::2:00aa
-cccc-171 IN AAAA 2001:db8::2:00ab
-cccc-172 IN AAAA 2001:db8::2:00ac
-cccc-173 IN AAAA 2001:db8::2:00ad
-cccc-174 IN AAAA 2001:db8::2:00ae
-cccc-175 IN AAAA 2001:db8::2:00af
-cccc-176 IN AAAA 2001:db8::2:00b0
-cccc-177 IN AAAA 2001:db8::2:00b1
-cccc-178 IN AAAA 2001:db8::2:00b2
-cccc-179 IN AAAA 2001:db8::2:00b3
-cccc-180 IN AAAA 2001:db8::2:00b4
-cccc-181 IN AAAA 2001:db8::2:00b5
-cccc-182 IN AAAA 2001:db8::2:00b6
-cccc-183 IN AAAA 2001:db8::2:00b7
-cccc-184 IN AAAA 2001:db8::2:00b8
-cccc-185 IN AAAA 2001:db8::2:00b9
-cccc-186 IN AAAA 2001:db8::2:00ba
-cccc-187 IN AAAA 2001:db8::2:00bb
-cccc-188 IN AAAA 2001:db8::2:00bc
-cccc-189 IN AAAA 2001:db8::2:00bd
-cccc-190 IN AAAA 2001:db8::2:00be
-cccc-191 IN AAAA 2001:db8::2:00bf
-cccc-192 IN AAAA 2001:db8::2:00c0
-cccc-193 IN AAAA 2001:db8::2:00c1
-cccc-194 IN AAAA 2001:db8::2:00c2
-cccc-195 IN AAAA 2001:db8::2:00c3
-cccc-196 IN AAAA 2001:db8::2:00c4
-cccc-197 IN AAAA 2001:db8::2:00c5
-cccc-198 IN AAAA 2001:db8::2:00c6
-cccc-199 IN AAAA 2001:db8::2:00c7
-cccc-200 IN AAAA 2001:db8::2:00c8
-cccc-201 IN AAAA 2001:db8::2:00c9
-cccc-202 IN AAAA 2001:db8::2:00ca
-cccc-203 IN AAAA 2001:db8::2:00cb
-cccc-204 IN AAAA 2001:db8::2:00cc
-cccc-205 IN AAAA 2001:db8::2:00cd
-cccc-206 IN AAAA 2001:db8::2:00ce
-cccc-207 IN AAAA 2001:db8::2:00cf
-cccc-208 IN AAAA 2001:db8::2:00d0
-cccc-209 IN AAAA 2001:db8::2:00d1
-cccc-210 IN AAAA 2001:db8::2:00d2
-cccc-211 IN AAAA 2001:db8::2:00d3
-cccc-212 IN AAAA 2001:db8::2:00d4
-cccc-213 IN AAAA 2001:db8::2:00d5
-cccc-214 IN AAAA 2001:db8::2:00d6
-cccc-215 IN AAAA 2001:db8::2:00d7
-cccc-216 IN AAAA 2001:db8::2:00d8
-cccc-217 IN AAAA 2001:db8::2:00d9
-cccc-218 IN AAAA 2001:db8::2:00da
-cccc-219 IN AAAA 2001:db8::2:00db
-cccc-220 IN AAAA 2001:db8::2:00dc
-cccc-221 IN AAAA 2001:db8::2:00dd
-cccc-222 IN AAAA 2001:db8::2:00de
-cccc-223 IN AAAA 2001:db8::2:00df
-cccc-224 IN AAAA 2001:db8::2:00e0
-cccc-225 IN AAAA 2001:db8::2:00e1
-cccc-226 IN AAAA 2001:db8::2:00e2
-cccc-227 IN AAAA 2001:db8::2:00e3
-cccc-228 IN AAAA 2001:db8::2:00e4
-cccc-229 IN AAAA 2001:db8::2:00e5
-cccc-230 IN AAAA 2001:db8::2:00e6
-cccc-231 IN AAAA 2001:db8::2:00e7
-cccc-232 IN AAAA 2001:db8::2:00e8
-cccc-233 IN AAAA 2001:db8::2:00e9
-cccc-234 IN AAAA 2001:db8::2:00ea
-cccc-235 IN AAAA 2001:db8::2:00eb
-cccc-236 IN AAAA 2001:db8::2:00ec
-cccc-237 IN AAAA 2001:db8::2:00ed
-cccc-238 IN AAAA 2001:db8::2:00ee
-cccc-239 IN AAAA 2001:db8::2:00ef
-cccc-240 IN AAAA 2001:db8::2:00f0
-cccc-241 IN AAAA 2001:db8::2:00f1
-cccc-242 IN AAAA 2001:db8::2:00f2
-cccc-243 IN AAAA 2001:db8::2:00f3
-cccc-244 IN AAAA 2001:db8::2:00f4
-cccc-245 IN AAAA 2001:db8::2:00f5
-cccc-246 IN AAAA 2001:db8::2:00f6
-cccc-247 IN AAAA 2001:db8::2:00f7
-cccc-248 IN AAAA 2001:db8::2:00f8
-cccc-249 IN AAAA 2001:db8::2:00f9
-cccc-250 IN AAAA 2001:db8::2:00fa
-cccc-251 IN AAAA 2001:db8::2:00fb
-cccc-252 IN AAAA 2001:db8::2:00fc
-cccc-253 IN AAAA 2001:db8::2:00fd
-cccc-254 IN AAAA 2001:db8::2:00fe
-cccc-255 IN AAAA 2001:db8::2:00ff
-cccc-256 IN AAAA 2001:db8::2:0100
-cccc-257 IN AAAA 2001:db8::2:0101
-cccc-258 IN AAAA 2001:db8::2:0102
-cccc-259 IN AAAA 2001:db8::2:0103
-cccc-260 IN AAAA 2001:db8::2:0104
-cccc-261 IN AAAA 2001:db8::2:0105
-cccc-262 IN AAAA 2001:db8::2:0106
-cccc-263 IN AAAA 2001:db8::2:0107
-cccc-264 IN AAAA 2001:db8::2:0108
-cccc-265 IN AAAA 2001:db8::2:0109
-cccc-266 IN AAAA 2001:db8::2:010a
-cccc-267 IN AAAA 2001:db8::2:010b
-cccc-268 IN AAAA 2001:db8::2:010c
-cccc-269 IN AAAA 2001:db8::2:010d
-cccc-270 IN AAAA 2001:db8::2:010e
-cccc-271 IN AAAA 2001:db8::2:010f
-cccc-272 IN AAAA 2001:db8::2:0110
-cccc-273 IN AAAA 2001:db8::2:0111
-cccc-274 IN AAAA 2001:db8::2:0112
-cccc-275 IN AAAA 2001:db8::2:0113
-cccc-276 IN AAAA 2001:db8::2:0114
-cccc-277 IN AAAA 2001:db8::2:0115
-cccc-278 IN AAAA 2001:db8::2:0116
-cccc-279 IN AAAA 2001:db8::2:0117
-cccc-280 IN AAAA 2001:db8::2:0118
-cccc-281 IN AAAA 2001:db8::2:0119
-cccc-282 IN AAAA 2001:db8::2:011a
-cccc-283 IN AAAA 2001:db8::2:011b
-cccc-284 IN AAAA 2001:db8::2:011c
-cccc-285 IN AAAA 2001:db8::2:011d
-cccc-286 IN AAAA 2001:db8::2:011e
-cccc-287 IN AAAA 2001:db8::2:011f
-cccc-288 IN AAAA 2001:db8::2:0120
-cccc-289 IN AAAA 2001:db8::2:0121
-cccc-290 IN AAAA 2001:db8::2:0122
-cccc-291 IN AAAA 2001:db8::2:0123
-cccc-292 IN AAAA 2001:db8::2:0124
-cccc-293 IN AAAA 2001:db8::2:0125
-cccc-294 IN AAAA 2001:db8::2:0126
-cccc-295 IN AAAA 2001:db8::2:0127
-cccc-296 IN AAAA 2001:db8::2:0128
-cccc-297 IN AAAA 2001:db8::2:0129
-cccc-298 IN AAAA 2001:db8::2:012a
-cccc-299 IN AAAA 2001:db8::2:012b
-cccc-300 IN AAAA 2001:db8::2:012c
-cccc-301 IN AAAA 2001:db8::2:012d
-cccc-302 IN AAAA 2001:db8::2:012e
-cccc-303 IN AAAA 2001:db8::2:012f
-cccc-304 IN AAAA 2001:db8::2:0130
-cccc-305 IN AAAA 2001:db8::2:0131
-cccc-306 IN AAAA 2001:db8::2:0132
-cccc-307 IN AAAA 2001:db8::2:0133
-cccc-308 IN AAAA 2001:db8::2:0134
-cccc-309 IN AAAA 2001:db8::2:0135
-cccc-310 IN AAAA 2001:db8::2:0136
-cccc-311 IN AAAA 2001:db8::2:0137
-cccc-312 IN AAAA 2001:db8::2:0138
-cccc-313 IN AAAA 2001:db8::2:0139
-cccc-314 IN AAAA 2001:db8::2:013a
-cccc-315 IN AAAA 2001:db8::2:013b
-cccc-316 IN AAAA 2001:db8::2:013c
-cccc-317 IN AAAA 2001:db8::2:013d
-cccc-318 IN AAAA 2001:db8::2:013e
-cccc-319 IN AAAA 2001:db8::2:013f
-cccc-320 IN AAAA 2001:db8::2:0140
-cccc-321 IN AAAA 2001:db8::2:0141
-cccc-322 IN AAAA 2001:db8::2:0142
-cccc-323 IN AAAA 2001:db8::2:0143
-cccc-324 IN AAAA 2001:db8::2:0144
-cccc-325 IN AAAA 2001:db8::2:0145
-cccc-326 IN AAAA 2001:db8::2:0146
-cccc-327 IN AAAA 2001:db8::2:0147
-cccc-328 IN AAAA 2001:db8::2:0148
-cccc-329 IN AAAA 2001:db8::2:0149
-cccc-330 IN AAAA 2001:db8::2:014a
-cccc-331 IN AAAA 2001:db8::2:014b
-cccc-332 IN AAAA 2001:db8::2:014c
-cccc-333 IN AAAA 2001:db8::2:014d
-cccc-334 IN AAAA 2001:db8::2:014e
-cccc-335 IN AAAA 2001:db8::2:014f
-cccc-336 IN AAAA 2001:db8::2:0150
-cccc-337 IN AAAA 2001:db8::2:0151
-cccc-338 IN AAAA 2001:db8::2:0152
-cccc-339 IN AAAA 2001:db8::2:0153
-cccc-340 IN AAAA 2001:db8::2:0154
-cccc-341 IN AAAA 2001:db8::2:0155
-cccc-342 IN AAAA 2001:db8::2:0156
-cccc-343 IN AAAA 2001:db8::2:0157
-cccc-344 IN AAAA 2001:db8::2:0158
-cccc-345 IN AAAA 2001:db8::2:0159
-cccc-346 IN AAAA 2001:db8::2:015a
-cccc-347 IN AAAA 2001:db8::2:015b
-cccc-348 IN AAAA 2001:db8::2:015c
-cccc-349 IN AAAA 2001:db8::2:015d
-cccc-350 IN AAAA 2001:db8::2:015e
-cccc-351 IN AAAA 2001:db8::2:015f
-cccc-352 IN AAAA 2001:db8::2:0160
-cccc-353 IN AAAA 2001:db8::2:0161
-cccc-354 IN AAAA 2001:db8::2:0162
-cccc-355 IN AAAA 2001:db8::2:0163
-cccc-356 IN AAAA 2001:db8::2:0164
-cccc-357 IN AAAA 2001:db8::2:0165
-cccc-358 IN AAAA 2001:db8::2:0166
-cccc-359 IN AAAA 2001:db8::2:0167
-cccc-360 IN AAAA 2001:db8::2:0168
-cccc-361 IN AAAA 2001:db8::2:0169
-cccc-362 IN AAAA 2001:db8::2:016a
-cccc-363 IN AAAA 2001:db8::2:016b
-cccc-364 IN AAAA 2001:db8::2:016c
-cccc-365 IN AAAA 2001:db8::2:016d
-cccc-366 IN AAAA 2001:db8::2:016e
-cccc-367 IN AAAA 2001:db8::2:016f
-cccc-368 IN AAAA 2001:db8::2:0170
-cccc-369 IN AAAA 2001:db8::2:0171
-cccc-370 IN AAAA 2001:db8::2:0172
-cccc-371 IN AAAA 2001:db8::2:0173
-cccc-372 IN AAAA 2001:db8::2:0174
-cccc-373 IN AAAA 2001:db8::2:0175
-cccc-374 IN AAAA 2001:db8::2:0176
-cccc-375 IN AAAA 2001:db8::2:0177
-cccc-376 IN AAAA 2001:db8::2:0178
-cccc-377 IN AAAA 2001:db8::2:0179
-cccc-378 IN AAAA 2001:db8::2:017a
-cccc-379 IN AAAA 2001:db8::2:017b
-cccc-380 IN AAAA 2001:db8::2:017c
-cccc-381 IN AAAA 2001:db8::2:017d
-cccc-382 IN AAAA 2001:db8::2:017e
-cccc-383 IN AAAA 2001:db8::2:017f
-cccc-384 IN AAAA 2001:db8::2:0180
-cccc-385 IN AAAA 2001:db8::2:0181
-cccc-386 IN AAAA 2001:db8::2:0182
-cccc-387 IN AAAA 2001:db8::2:0183
-cccc-388 IN AAAA 2001:db8::2:0184
-cccc-389 IN AAAA 2001:db8::2:0185
-cccc-390 IN AAAA 2001:db8::2:0186
-cccc-391 IN AAAA 2001:db8::2:0187
-cccc-392 IN AAAA 2001:db8::2:0188
-cccc-393 IN AAAA 2001:db8::2:0189
-cccc-394 IN AAAA 2001:db8::2:018a
-cccc-395 IN AAAA 2001:db8::2:018b
-cccc-396 IN AAAA 2001:db8::2:018c
-cccc-397 IN AAAA 2001:db8::2:018d
-cccc-398 IN AAAA 2001:db8::2:018e
-cccc-399 IN AAAA 2001:db8::2:018f
-cccc-400 IN AAAA 2001:db8::2:0190
-cccc-401 IN AAAA 2001:db8::2:0191
-cccc-402 IN AAAA 2001:db8::2:0192
-cccc-403 IN AAAA 2001:db8::2:0193
-cccc-404 IN AAAA 2001:db8::2:0194
-cccc-405 IN AAAA 2001:db8::2:0195
-cccc-406 IN AAAA 2001:db8::2:0196
-cccc-407 IN AAAA 2001:db8::2:0197
-cccc-408 IN AAAA 2001:db8::2:0198
-cccc-409 IN AAAA 2001:db8::2:0199
-cccc-410 IN AAAA 2001:db8::2:019a
-cccc-411 IN AAAA 2001:db8::2:019b
-cccc-412 IN AAAA 2001:db8::2:019c
-cccc-413 IN AAAA 2001:db8::2:019d
-cccc-414 IN AAAA 2001:db8::2:019e
-cccc-415 IN AAAA 2001:db8::2:019f
-cccc-416 IN AAAA 2001:db8::2:01a0
-cccc-417 IN AAAA 2001:db8::2:01a1
-cccc-418 IN AAAA 2001:db8::2:01a2
-cccc-419 IN AAAA 2001:db8::2:01a3
-cccc-420 IN AAAA 2001:db8::2:01a4
-cccc-421 IN AAAA 2001:db8::2:01a5
-cccc-422 IN AAAA 2001:db8::2:01a6
-cccc-423 IN AAAA 2001:db8::2:01a7
-cccc-424 IN AAAA 2001:db8::2:01a8
-cccc-425 IN AAAA 2001:db8::2:01a9
-cccc-426 IN AAAA 2001:db8::2:01aa
-cccc-427 IN AAAA 2001:db8::2:01ab
-cccc-428 IN AAAA 2001:db8::2:01ac
-cccc-429 IN AAAA 2001:db8::2:01ad
-cccc-430 IN AAAA 2001:db8::2:01ae
-cccc-431 IN AAAA 2001:db8::2:01af
-cccc-432 IN AAAA 2001:db8::2:01b0
-cccc-433 IN AAAA 2001:db8::2:01b1
-cccc-434 IN AAAA 2001:db8::2:01b2
-cccc-435 IN AAAA 2001:db8::2:01b3
-cccc-436 IN AAAA 2001:db8::2:01b4
-cccc-437 IN AAAA 2001:db8::2:01b5
-cccc-438 IN AAAA 2001:db8::2:01b6
-cccc-439 IN AAAA 2001:db8::2:01b7
-cccc-440 IN AAAA 2001:db8::2:01b8
-cccc-441 IN AAAA 2001:db8::2:01b9
-cccc-442 IN AAAA 2001:db8::2:01ba
-cccc-443 IN AAAA 2001:db8::2:01bb
-cccc-444 IN AAAA 2001:db8::2:01bc
-cccc-445 IN AAAA 2001:db8::2:01bd
-cccc-446 IN AAAA 2001:db8::2:01be
-cccc-447 IN AAAA 2001:db8::2:01bf
-cccc-448 IN AAAA 2001:db8::2:01c0
-cccc-449 IN AAAA 2001:db8::2:01c1
-cccc-450 IN AAAA 2001:db8::2:01c2
-cccc-451 IN AAAA 2001:db8::2:01c3
-cccc-452 IN AAAA 2001:db8::2:01c4
-cccc-453 IN AAAA 2001:db8::2:01c5
-cccc-454 IN AAAA 2001:db8::2:01c6
-cccc-455 IN AAAA 2001:db8::2:01c7
-cccc-456 IN AAAA 2001:db8::2:01c8
-cccc-457 IN AAAA 2001:db8::2:01c9
-cccc-458 IN AAAA 2001:db8::2:01ca
-cccc-459 IN AAAA 2001:db8::2:01cb
-cccc-460 IN AAAA 2001:db8::2:01cc
-cccc-461 IN AAAA 2001:db8::2:01cd
-cccc-462 IN AAAA 2001:db8::2:01ce
-cccc-463 IN AAAA 2001:db8::2:01cf
-cccc-464 IN AAAA 2001:db8::2:01d0
-cccc-465 IN AAAA 2001:db8::2:01d1
-cccc-466 IN AAAA 2001:db8::2:01d2
-cccc-467 IN AAAA 2001:db8::2:01d3
-cccc-468 IN AAAA 2001:db8::2:01d4
-cccc-469 IN AAAA 2001:db8::2:01d5
-cccc-470 IN AAAA 2001:db8::2:01d6
-cccc-471 IN AAAA 2001:db8::2:01d7
-cccc-472 IN AAAA 2001:db8::2:01d8
-cccc-473 IN AAAA 2001:db8::2:01d9
-cccc-474 IN AAAA 2001:db8::2:01da
-cccc-475 IN AAAA 2001:db8::2:01db
-cccc-476 IN AAAA 2001:db8::2:01dc
-cccc-477 IN AAAA 2001:db8::2:01dd
-cccc-478 IN AAAA 2001:db8::2:01de
-cccc-479 IN AAAA 2001:db8::2:01df
-cccc-480 IN AAAA 2001:db8::2:01e0
-cccc-481 IN AAAA 2001:db8::2:01e1
-cccc-482 IN AAAA 2001:db8::2:01e2
-cccc-483 IN AAAA 2001:db8::2:01e3
-cccc-484 IN AAAA 2001:db8::2:01e4
-cccc-485 IN AAAA 2001:db8::2:01e5
-cccc-486 IN AAAA 2001:db8::2:01e6
-cccc-487 IN AAAA 2001:db8::2:01e7
-cccc-488 IN AAAA 2001:db8::2:01e8
-cccc-489 IN AAAA 2001:db8::2:01e9
-cccc-490 IN AAAA 2001:db8::2:01ea
-cccc-491 IN AAAA 2001:db8::2:01eb
-cccc-492 IN AAAA 2001:db8::2:01ec
-cccc-493 IN AAAA 2001:db8::2:01ed
-cccc-494 IN AAAA 2001:db8::2:01ee
-cccc-495 IN AAAA 2001:db8::2:01ef
-cccc-496 IN AAAA 2001:db8::2:01f0
-cccc-497 IN AAAA 2001:db8::2:01f1
-cccc-498 IN AAAA 2001:db8::2:01f2
-cccc-499 IN AAAA 2001:db8::2:01f3
-cccc-500 IN AAAA 2001:db8::2:01f4
-cccc-501 IN AAAA 2001:db8::2:01f5
-cccc-502 IN AAAA 2001:db8::2:01f6
-cccc-503 IN AAAA 2001:db8::2:01f7
-cccc-504 IN AAAA 2001:db8::2:01f8
-cccc-505 IN AAAA 2001:db8::2:01f9
-cccc-506 IN AAAA 2001:db8::2:01fa
-cccc-507 IN AAAA 2001:db8::2:01fb
-cccc-508 IN AAAA 2001:db8::2:01fc
-cccc-509 IN AAAA 2001:db8::2:01fd
-cccc-510 IN AAAA 2001:db8::2:01fe
-cccc-511 IN AAAA 2001:db8::2:01ff
diff --git a/tests/system/ixfr/db.example.n0.in b/tests/system/ixfr/db.example.n0.in
deleted file mode 100644
index 92fa0b0..0000000
--- a/tests/system/ixfr/db.example.n0.in
+++ /dev/null
@@ -1,29 +0,0 @@
-; Copyright (C) 2011 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.
-
-$ORIGIN example.
-$TTL 3600
-
-@ IN SOA ns1.example. hostmaster.example. 100 3600 900 7200 300
-
- IN NS ns1.example.
- IN NS ns2.example.
-
-ns1 IN A 192.0.2.1
-ns2 IN A 192.0.2.2
-
-a-1 IN A 192.0.2.101
-b-1 IN A 192.0.2.201
-
-$INCLUDE @abs_top_builddir@/tests/system/ixfr/db.example.common
diff --git a/tests/system/ixfr/db.example.n2.in b/tests/system/ixfr/db.example.n2.in
deleted file mode 100644
index 6a999af..0000000
--- a/tests/system/ixfr/db.example.n2.in
+++ /dev/null
@@ -1,28 +0,0 @@
-; Copyright (C) 2011 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.
-
-$ORIGIN example.
-$TTL 3600
-
-@ IN SOA ns1.example. hostmaster.example. 98 3600 900 7200 300
-
- IN NS ns1.example.
- IN NS ns2.example.
-
-ns1 IN A 192.0.2.1
-ns2 IN A 192.0.2.2
-
-a-1 IN A 192.0.2.101
-
-$INCLUDE @abs_top_builddir@/tests/system/ixfr/db.example.common
diff --git a/tests/system/ixfr/db.example.n2.refresh.in b/tests/system/ixfr/db.example.n2.refresh.in
deleted file mode 100644
index 2c59416..0000000
--- a/tests/system/ixfr/db.example.n2.refresh.in
+++ /dev/null
@@ -1,28 +0,0 @@
-; Copyright (C) 2011 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.
-
-$ORIGIN example.
-$TTL 3600
-
-@ IN SOA ns1.example. hostmaster.example. 98 30 2 7200 300
-
- IN NS ns1.example.
- IN NS ns2.example.
-
-ns1 IN A 192.0.2.1
-ns2 IN A 192.0.2.2
-
-a-1 IN A 192.0.2.101
-
-$INCLUDE @abs_top_builddir@/tests/system/ixfr/db.example.common
diff --git a/tests/system/ixfr/db.example.n4.in b/tests/system/ixfr/db.example.n4.in
deleted file mode 100644
index ae15a54..0000000
--- a/tests/system/ixfr/db.example.n4.in
+++ /dev/null
@@ -1,31 +0,0 @@
-; Copyright (C) 2011 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.
-
-$ORIGIN example.
-$TTL 3600
-
-@ IN SOA ns1.example. hostmaster.example. 96 3600 900 7200 300
-
- IN NS ns1.example.
- IN NS ns2.example.
-
-ns1 IN A 192.0.2.1
-ns2 IN A 192.0.2.2
-
-a-1 IN A 192.0.2.101
-a-2 IN A 192.0.2.102
-b-1 IN A 192.0.2.201
-b-2 IN A 192.0.2.202
-
-$INCLUDE @abs_top_builddir@/tests/system/ixfr/db.example.common
diff --git a/tests/system/ixfr/db.example.n6.in b/tests/system/ixfr/db.example.n6.in
deleted file mode 100644
index 33a82a0..0000000
--- a/tests/system/ixfr/db.example.n6.in
+++ /dev/null
@@ -1,29 +0,0 @@
-; Copyright (C) 2011 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.
-
-$ORIGIN example.
-$TTL 3600
-
-@ IN SOA ns1.example. hostmaster.example. 94 3600 900 7200 300
-
- IN NS ns1.example.
- IN NS ns2.example.
-
-ns1 IN A 192.0.2.1
-ns2 IN A 192.0.2.2
-
-a-1 IN A 192.0.2.101
-a-2 IN A 192.0.2.102
-b-1 IN A 192.0.2.201
-b-2 IN A 192.0.2.202
diff --git a/tests/system/ixfr/in-1/.gitignore b/tests/system/ixfr/in-1/.gitignore
deleted file mode 100644
index 87e08bf..0000000
--- a/tests/system/ixfr/in-1/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-/setup.sh
diff --git a/tests/system/ixfr/in-1/clean.sh b/tests/system/ixfr/in-1/clean.sh
deleted file mode 120000
index 099bebd..0000000
--- a/tests/system/ixfr/in-1/clean.sh
+++ /dev/null
@@ -1 +0,0 @@
-../clean_ns.sh
\ No newline at end of file
diff --git a/tests/system/ixfr/in-1/ns1/README b/tests/system/ixfr/in-1/ns1/README
deleted file mode 100644
index aaa8a31..0000000
--- a/tests/system/ixfr/in-1/ns1/README
+++ /dev/null
@@ -1,3 +0,0 @@
-This directory should be empty. A README file is placed here to ensure git
-notes the directory's presence. It can be removed if other files are placed
-here.
diff --git a/tests/system/ixfr/in-1/nsx2/README b/tests/system/ixfr/in-1/nsx2/README
deleted file mode 100644
index aaa8a31..0000000
--- a/tests/system/ixfr/in-1/nsx2/README
+++ /dev/null
@@ -1,3 +0,0 @@
-This directory should be empty. A README file is placed here to ensure git
-notes the directory's presence. It can be removed if other files are placed
-here.
diff --git a/tests/system/ixfr/in-1/setup.sh.in b/tests/system/ixfr/in-1/setup.sh.in
deleted file mode 100644
index 4332930..0000000
--- a/tests/system/ixfr/in-1/setup.sh.in
+++ /dev/null
@@ -1,30 +0,0 @@
-#!/bin/sh
-#
-# Copyright (C) 2004, 2007, 2011 Internet Systems Consortium, Inc. ("ISC")
-# Copyright (C) 2001, 2002 Internet Software Consortium.
-#
-# 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.
-
-. @abs_top_builddir@/tests/system/conf.sh
-
-# Clean up from last time
-sh clean.sh
-
-# Set up the initial version of the IXFR server - load the n-4 version of the
-# zone. The configuration file enables IXFR and disabled notifies.
-cp -f $IXFR_TOP/named_nonotify.conf ns1/named.conf
-cp -f $IXFR_TOP/db.example.n4 ns1/db.example
-
-# Set up the IXFR client - load the same version of the zone.
-cp -f $IXFR_TOP/b10-config.db nsx2/b10-config.db
-${B10_LOADZONE} -c "{\"database_file\": \"$IXFR_TOP/zone.sqlite3\"}" example. $IXFR_TOP/db.example.n4
diff --git a/tests/system/ixfr/in-1/tests.sh b/tests/system/ixfr/in-1/tests.sh
deleted file mode 100644
index 2f49ddf..0000000
--- a/tests/system/ixfr/in-1/tests.sh
+++ /dev/null
@@ -1,37 +0,0 @@
-#!/bin/sh
-#
-# Copyright (C) 2011 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.
-
-# \file
-# This script performs the first IXFR-IN test. A BIND 9 nameserver (the
-# "server") contains a version of the zone (version N) and two previous
-# versions, N-2 and N-4. A BIND 10 nameserver (the "client") is loaded with
-# version N-4 of the zone. A NOTIFY is sent to it, and it is expected that
-# it will send an IXFR to the server and update itself with the latest version
-# of the zone. (The changes are such that the update should be in the form of
-# a single UDP packet.)
-#
-# The pre-requisites for this test are the same as for the common tests, so
-# we can execute that directly.
-
-. ../common_tests.sh
-status=$?
-
-# TODO: Check the BIND 10 log, looking for the IXFR messages that indicate that
-# it has initiated an IXFR and that it received the update within a single
-# packet.
-
-echo "I:exit status: $status"
-exit $status
diff --git a/tests/system/ixfr/in-2/.gitignore b/tests/system/ixfr/in-2/.gitignore
deleted file mode 100644
index 87e08bf..0000000
--- a/tests/system/ixfr/in-2/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-/setup.sh
diff --git a/tests/system/ixfr/in-2/clean.sh b/tests/system/ixfr/in-2/clean.sh
deleted file mode 120000
index 099bebd..0000000
--- a/tests/system/ixfr/in-2/clean.sh
+++ /dev/null
@@ -1 +0,0 @@
-../clean_ns.sh
\ No newline at end of file
diff --git a/tests/system/ixfr/in-2/ns1/.gitignore b/tests/system/ixfr/in-2/ns1/.gitignore
deleted file mode 100644
index 35ae1cb..0000000
--- a/tests/system/ixfr/in-2/ns1/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-/named.run
diff --git a/tests/system/ixfr/in-2/ns1/README b/tests/system/ixfr/in-2/ns1/README
deleted file mode 100644
index aaa8a31..0000000
--- a/tests/system/ixfr/in-2/ns1/README
+++ /dev/null
@@ -1,3 +0,0 @@
-This directory should be empty. A README file is placed here to ensure git
-notes the directory's presence. It can be removed if other files are placed
-here.
diff --git a/tests/system/ixfr/in-2/nsx2/.gitignore b/tests/system/ixfr/in-2/nsx2/.gitignore
deleted file mode 100644
index d31eb18..0000000
--- a/tests/system/ixfr/in-2/nsx2/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-/bindctl.out
diff --git a/tests/system/ixfr/in-2/nsx2/README b/tests/system/ixfr/in-2/nsx2/README
deleted file mode 100644
index aaa8a31..0000000
--- a/tests/system/ixfr/in-2/nsx2/README
+++ /dev/null
@@ -1,3 +0,0 @@
-This directory should be empty. A README file is placed here to ensure git
-notes the directory's presence. It can be removed if other files are placed
-here.
diff --git a/tests/system/ixfr/in-2/setup.sh.in b/tests/system/ixfr/in-2/setup.sh.in
deleted file mode 100644
index a210636..0000000
--- a/tests/system/ixfr/in-2/setup.sh.in
+++ /dev/null
@@ -1,29 +0,0 @@
-#!/bin/sh
-#
-# Copyright (C) 2011 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.
-
-. @abs_top_builddir@/tests/system/conf.sh
-
-# Clean up from last time
-sh clean.sh
-
-# Set up the initial version of the IXFR server - load the n-6 version of the
-# zone. The configuration file enables IXFR and disables notifies.
-cp -f $IXFR_TOP/named_nonotify.conf ns1/named.conf
-cp -f $IXFR_TOP/db.example.n6 ns1/db.example
-
-# Set up the IXFR client - load an earlier version of the zone
-cp -f $IXFR_TOP/b10-config.db nsx2/b10-config.db
-${B10_LOADZONE} -c "{\"database_file\": \"$IXFR_TOP/zone.sqlite3\"}" example. $IXFR_TOP/db.example.n6
diff --git a/tests/system/ixfr/in-2/tests.sh b/tests/system/ixfr/in-2/tests.sh
deleted file mode 100644
index 3050713..0000000
--- a/tests/system/ixfr/in-2/tests.sh
+++ /dev/null
@@ -1,81 +0,0 @@
-#!/bin/sh
-#
-# Copyright (C) 2011 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.
-
-# \file
-# This script performs the first IXFR-IN test. A BIND 9 nameserver (the
-# "server") contains a version of the zone (version N) and three previous
-# versions, N-2, N-4 and N-6. A BIND 10 nameserver (the "client") is loaded
-# with version N-6 of the zone. A NOTIFY is sent to it, and it is expected that
-# it will send an IXFR to the server and update itself with the latest version
-# of the zone. (The changes are such that the update will have to take place
-# over TCP.)
-
-. ../ixfr_init.sh
-
-# On entry, the IXFR server is at version N-6. The common tests assume that
-# it is an N-4, so update it.
-echo "I:$SERVER_NAME updating IXFR-server to suitable start version"
-update_server_zone $SERVER_NAME $SERVER_IP $IXFR_TOP/db.example.n4
-if [ $? -ne 0 ];
-then
- exit 1
-fi
-
-# The pre-requisites for this test are the same as for the common tests, so
-# we can execute that directly.
-. ../common_tests.sh
-if [ $? -ne 0 ];
-then
- exit 1
-fi
-
-# TEMPORARY: at the time of writing (October 2011) BIND 10 does not attempt
-# a UDP transfer first. Therefore just check for TCP transfer.
-
-# Check that the client initiated and completed an IXFR. Use a simple grep as
-# the syntax and capabilities of egrep may vary between systems.
-grep XFRIN_XFR_TRANSFER_STARTED nsx2/bind10.run | grep IXFR > /dev/null
-if [ $? -ne 0 ];
-then
- echo "R:$CLIENT_NAME FAIL no 'IXFR started' message in the BIND 10 log"
- exit 1
-fi
-
-grep XFRIN_IXFR_TRANSFER_SUCCESS nsx2/bind10.run | grep IXFR > /dev/null
-if [ $? -ne 0 ];
-then
- echo "R:$CLIENT_NAME FAIL no 'IXFR successful' message in the BIND 10 log"
- exit 1
-fi
-
-# Look in the named log file to see if a TCP IXFR was requested. Again use a
-# simple grep.
-grep "transfer of" ns1/named.run | grep "sending TCP message" > /dev/null
-if [ $? -ne 0 ];
-then
- echo "R:$SERVER_NAME FAIL no 'sending TCP' message in the BIND 9 log"
- exit 1
-fi
-
-grep "IXFR ended" ns1/named.run > /dev/null
-if [ $? -ne 0 ];
-then
- echo "R:$SERVER_NAME FAIL no 'IXFR ended' message in the BIND 9 log"
- exit 1
-fi
-
-echo "I:exit status: 0"
-exit 0
diff --git a/tests/system/ixfr/in-3/.gitignore b/tests/system/ixfr/in-3/.gitignore
deleted file mode 100644
index 87e08bf..0000000
--- a/tests/system/ixfr/in-3/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-/setup.sh
diff --git a/tests/system/ixfr/in-3/clean.sh b/tests/system/ixfr/in-3/clean.sh
deleted file mode 120000
index 099bebd..0000000
--- a/tests/system/ixfr/in-3/clean.sh
+++ /dev/null
@@ -1 +0,0 @@
-../clean_ns.sh
\ No newline at end of file
diff --git a/tests/system/ixfr/in-3/ns1/README b/tests/system/ixfr/in-3/ns1/README
deleted file mode 100644
index aaa8a31..0000000
--- a/tests/system/ixfr/in-3/ns1/README
+++ /dev/null
@@ -1,3 +0,0 @@
-This directory should be empty. A README file is placed here to ensure git
-notes the directory's presence. It can be removed if other files are placed
-here.
diff --git a/tests/system/ixfr/in-3/nsx2/README b/tests/system/ixfr/in-3/nsx2/README
deleted file mode 100644
index aaa8a31..0000000
--- a/tests/system/ixfr/in-3/nsx2/README
+++ /dev/null
@@ -1,3 +0,0 @@
-This directory should be empty. A README file is placed here to ensure git
-notes the directory's presence. It can be removed if other files are placed
-here.
diff --git a/tests/system/ixfr/in-3/setup.sh.in b/tests/system/ixfr/in-3/setup.sh.in
deleted file mode 100644
index 2a08c58..0000000
--- a/tests/system/ixfr/in-3/setup.sh.in
+++ /dev/null
@@ -1,29 +0,0 @@
-#!/bin/sh
-#
-# Copyright (C) 2011 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.
-
-. @abs_top_builddir@/tests/system/conf.sh
-# Clean up from last time
-
-sh clean.sh
-
-# Set up the initial version of the IXFR server - load the latest version of
-# the zone.
-cp -f $IXFR_TOP/named_noixfr.conf ns1/named.conf
-cp -f $IXFR_TOP/db.example.n0 ns1/db.example
-
-# Set up the IXFR client - load a previous version of the zone.
-cp -f $IXFR_TOP/b10-config.db nsx2/b10-config.db
-${B10_LOADZONE} -c "{\"database_file\": \"$IXFR_TOP/zone.sqlite3\"}" example. $IXFR_TOP/db.example.n2
diff --git a/tests/system/ixfr/in-3/tests.sh b/tests/system/ixfr/in-3/tests.sh
deleted file mode 100644
index d47a221..0000000
--- a/tests/system/ixfr/in-3/tests.sh
+++ /dev/null
@@ -1,66 +0,0 @@
-#!/bin/sh
-#
-# Copyright (C) 2011 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.
-
-# \file
-# This script performs the third IXFR-IN test. A BIND 9 nameserver (the
-# "server") contains a version of the zone (version N) and has IXFRs disabled.
-# A BIND 10 nameserver (the "client") is loaded with version N-2 of the zone.
-# A NOTIFY is sent to it, and it is expected that it will send an IXFR to the
-# server; the server should not respond to the request, so the client should
-# then send an AXFR request and receive the latest copy of the zone.
-
-# TODO It seems bind9 still allows IXFR even when provide-ixfr on;
-
-. ../ixfr_init.sh
-status=$?
-
-# Store the SOA serial number of the BIND 10 client for later use.
-old_client_serial=`$DIG_SOA @$CLIENT_IP | $AWK '{print $3}'`
-echo "I:SOA serial of IXFR client $CLIENT_NAME is $old_client_serial"
-
-# If required, get the IXFR server to notify the IXFR client of the new zone.
-# Do this by allowing notifies and then triggering a re-notification of the
-# server.
-echo "I:notifying IXFR-client $CLIENT_NAME of presence of new version of zone"
-do_rndc $SERVER_NAME $SERVER_IP notify example
-status=`expr $status + $?`
-
-# Wait for the client to update itself.
-wait_for_update $CLIENT_NAME $CLIENT_IP $old_client_serial
-status=`expr $status + $?`
-
-# Has updated, get the latest serial of the client and server - they
-# should be the same.
-compare_soa $SERVER_NAME $SERVER_IP $CLIENT_NAME $CLIENT_IP
-status=`expr $status + $?`
-
-# Check the log there's the IXFR and fallback
-grep XFRIN_XFR_TRANSFER_STARTED nsx2/bind10.run | grep IXFR
-if [ $? -ne 0 ];
-then
- echo "R:$CLIENT_NAME FAIL no 'IXFR started' message in the BIND 10 log"
- exit 1
-fi
-
-grep XFRIN_XFR_TRANSFER_FALLBACK nsx2/bind10.run
-if [ $? -ne 0 ];
-then
- echo "R:$CLIENT_NAME FAIL no fallback message in BIND10 log"
- exit 1
-fi
-
-echo "I:exit status: $status"
-exit $status
diff --git a/tests/system/ixfr/in-4/.gitignore b/tests/system/ixfr/in-4/.gitignore
deleted file mode 100644
index 87e08bf..0000000
--- a/tests/system/ixfr/in-4/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-/setup.sh
diff --git a/tests/system/ixfr/in-4/clean.sh b/tests/system/ixfr/in-4/clean.sh
deleted file mode 120000
index 099bebd..0000000
--- a/tests/system/ixfr/in-4/clean.sh
+++ /dev/null
@@ -1 +0,0 @@
-../clean_ns.sh
\ No newline at end of file
diff --git a/tests/system/ixfr/in-4/ns1/README b/tests/system/ixfr/in-4/ns1/README
deleted file mode 100644
index aaa8a31..0000000
--- a/tests/system/ixfr/in-4/ns1/README
+++ /dev/null
@@ -1,3 +0,0 @@
-This directory should be empty. A README file is placed here to ensure git
-notes the directory's presence. It can be removed if other files are placed
-here.
diff --git a/tests/system/ixfr/in-4/nsx2/README b/tests/system/ixfr/in-4/nsx2/README
deleted file mode 100644
index aaa8a31..0000000
--- a/tests/system/ixfr/in-4/nsx2/README
+++ /dev/null
@@ -1,3 +0,0 @@
-This directory should be empty. A README file is placed here to ensure git
-notes the directory's presence. It can be removed if other files are placed
-here.
diff --git a/tests/system/ixfr/in-4/setup.sh.in b/tests/system/ixfr/in-4/setup.sh.in
deleted file mode 100644
index 1c2e9c8..0000000
--- a/tests/system/ixfr/in-4/setup.sh.in
+++ /dev/null
@@ -1,30 +0,0 @@
-#!/bin/sh
-#
-# Copyright (C) 2011 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.
-
-. @abs_top_builddir@/tests/system/conf.sh
-# Clean up from last time
-
-sh clean.sh
-
-# Set up the initial version of the ixfr server - load the last-but-one version
-# of the zone.
-cp $IXFR_TOP/named_nonotify.conf ns1/named.conf
-cp -f $IXFR_TOP/db.example.n2.refresh ns1/db.example
-
-# Set up the IXFR client - load a previous version of the zone with a short
-# refresh time.
-cp -f $IXFR_TOP/b10-config.db nsx2/b10-config.db
-${B10_LOADZONE} -c "{\"database_file\": \"$IXFR_TOP/zone.sqlite3\"}" example. $IXFR_TOP/db.example.n2.refresh
diff --git a/tests/system/ixfr/in-4/tests.sh b/tests/system/ixfr/in-4/tests.sh
deleted file mode 100644
index 3024253..0000000
--- a/tests/system/ixfr/in-4/tests.sh
+++ /dev/null
@@ -1,53 +0,0 @@
-#!/bin/sh
-#
-# Copyright (C) 2011 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.
-
-# \file
-# This script performs the fourth IXFR-IN test. A BIND 9 nameserver (the
-# "server") contains a version of the zone (version N) and has IXFRs enabled.
-# A BIND 10 nameserver (the "client") is loaded with version N-2 of the zone
-# and a small refresh time. After this expires, the IXFR client should send
-# an IXFR request to the IXFR server.
-
-. ../ixfr_init.sh
-status=$?
-
-# Ensure the server has the latest copy of the zone. The implicit assumption
-# here is that starting the two systems and reloading the IXFR server takes
-# less time than the SOA refresh time set in the "db.example.n2.refresh" zone
-# file.
-cp $IXFR_TOP/db.example.n0 ns1/db.example
-do_rndc $SERVER_NAME $SERVER_IP reload
-
-# Store the SOA serial number of the BIND 10 client for later use.
-old_client_serial=`$DIG_SOA @$CLIENT_IP | $AWK '{print $3}'`
-echo "I:SOA serial of IXFR client $CLIENT_NAME is $old_client_serial"
-
-# Wait for the client to update itself. 30 seconds has been given as the
-# refresh interface and 2 seconds as the retry interval. The wait_for_update
-# function will check for up to a minute looking for the new serial.
-wait_for_update $CLIENT_NAME $CLIENT_IP $old_client_serial
-status=`expr $status + $?`
-
-# Has updated, get the latest serial of the client and server - they
-# should be the same.
-compare_soa $SERVER_NAME $SERVER_IP $CLIENT_NAME $CLIENT_IP
-status=`expr $status + $?`
-
-# TODO: Check the BIND 10 log, looking for the IXFR messages that indicate that
-# the client has initiated the IXFR.
-
-echo "I:exit status: $status"
-exit $status
diff --git a/tests/system/ixfr/ixfr_init.sh.in b/tests/system/ixfr/ixfr_init.sh.in
deleted file mode 100644
index ba6049e..0000000
--- a/tests/system/ixfr/ixfr_init.sh.in
+++ /dev/null
@@ -1,330 +0,0 @@
-#!/bin/sh
-#
-# Copyright (C) 2011 Internet Software Consortium.
-#
-# 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.
-
-# \file
-# This file should be run by all IXFR tests before doing anything else. It
-# includes the main configuration script to set the environment variables as
-# well as defining useful shell subroutines.
-
-. @abs_top_builddir@/tests/system/conf.sh
-
-# Useful symbols used in the IXFR tests.
-
-# Short-hand for getting SOA - just supply address of the server
-DIG_SOA="$DIG +norecurse +short -p $DNS_PORT example. SOA"
-
-# All IXFR tests use a BIND 9 server serving a BIND 10 client. These have the
-# smae name and use the same address in all tests.
-SERVER_NAME=ns1
-SERVER_IP=10.53.0.1 # BIND 9
-
-CLIENT_NAME=nsx2
-CLIENT_IP=10.53.0.2 # BIND 10
-
-# \brief Check Arguments
-#
-# Most functions take the name of nameserver as the first argument and its IP
-# address as the second. This function is passed "$*" and just checks that
-# both $1 and $2 are defined.
-#
-# \arg $* Arguments passed to caller
-#
-# \return status 0 => $1 and $2 are defined, 1 => they are not.
-check_name_ip() {
-
- if [ "$1" = "" ];
- then
- echo "R:FAIL name of server not supplied"
- return 1
- fi
-
- if [ "$2" = "" ];
- then
- echo "R:FAIL IP address of server not supplied"
- return 1
- fi
-
- return 0
-}
-
-
-# \brief Perform RNDC Command
-#
-# Controls the BIND 9 IXFR server. Called do_rndc (instead of rndc) to avoid
-# confusion if rndc itself is in the search path.
-#
-# \arg $1 - Name of the server (ns1, nsx2 etc.)
-# \arg $2 - IP address of the server
-# \arg $* - Command to execute (which may be multiple tokens)
-#
-# \return 0 on success, 1 on failure (in which case an error message will
-# have been output).
-do_rndc () {
-
- # If the following checks fail, the code is wrong.
-
- check_name_ip $*
- if [ $? -ne 0 ];
- then
- echo "R:FAIL do_rndc - name or ip address of server not supplied"
- return 1
- fi
-
- name=$1
- shift
- ip=$1
- shift
-
- if [ "$1" = "" ];
- then
- echo "R:FAIL do_rndc - rndc command not supplied"
- return 1
- fi
-
- $RNDC -c $SYSTEM_TOP/common/rndc.conf -s $ip -p $RNDC_PORT $* 2>&1 \
- | sed "s/^/I:$name /"
-}
-
-# \brief Wait for update
-#
-# Given a serial number and a server, poll the nameserver until the SOA serial
-# number is different from that given. The poll takes place every five seconds
-# for a minute.
-#
-# \arg $1 - Name of the server
-# \arg $2 - IP address of the server
-# \arg $3 - Serial number to check against
-#
-# \return 0 if the serial number is different (requires another poll to obtain
-# it), 1 if the serial number has not changed after one minute.
-wait_for_update() {
-
- # If the following checks fail, the code is wrong.
-
- check_name_ip $*
- if [ $? -ne 0 ];
- then
- echo "R:FAIL wait_for_update - name or ip address of system not supplied"
- return 1
-
- fi
-
- name=$1
- shift
- ip=$1
- shift
-
- serial=$1
- if [ "$serial" = "" ];
- then
- echo "R:FAIL wait_for_update - serial number not supplied"
- return 1
- fi
-
- # Now poll the server looking for the new serial number
-
- echo "I:$name waiting for SOA serial to change from $serial"
- for i in 1 2 3 4 5 6 7 8 9 10 11 12
- do
- if [ $i -gt 1 ];
- then
- sleep 5
- fi
-
- new_serial=`$DIG_SOA @$ip | $AWK '{print $3}'`
- if [ "$new_serial" != "$serial" ];
- then
- echo "I:$name SOA serial was at $serial, now at $new_serial"
- return 0
- fi
- done
-
- echo "R:$name FAIL serial number has not updated"
- return 1
-}
-
-
-
-# \brief Update server zone
-#
-# Reloads the example. zone in the BIND 9 IXFR server and waits a maximum of
-# one minute for it to be served.
-#
-# \arg $1 - Name of the server (ns1, nsx2 etc.)
-# \arg $2 - IP address of the server
-# \arg $3 - Zone file to load
-# \arg $* - Command to execute (which may be multiple tokens)
-#
-# \return 0 on success, 1 on failure (for which an error message will have
-# been output).
-update_server_zone() {
-
- # If the following checks fail, the code is wrong.
-
- check_name_ip $*
- if [ $? -ne 0 ];
- then
- echo "R:FAIL update_server_zone - name or ip address of server not supplied"
- return 1
- fi
-
- name=$1
- shift
- ip=$1
- shift
-
- file=$1
- shift
- if [ "$file" = "" ];
- then
- echo "R:FAIL update_server_zone - new zone file not supplied"
- return 1
- fi
-
- if [ ! -e $file ];
- then
- echo "R:FAIL update_server_zone - zone file does not exist: $file"
- return 1
- fi
-
- old_serial=`$DIG_SOA @$ip | $AWK '{print $3}'`
-
- echo "I:$name IXFR server loading $file"
- cp $file $name/db.example
- do_rndc $name $ip reload
- if [ $? -ne 0 ];
- then
- return 1 # Message will have already been output
- fi
-
- wait_for_update $name $ip $old_serial
- if [ $? -ne 0 ];
- then
- echo "R:$name FAIL IXFR server did not update zone after reload"
- return 1
- fi
- new_serial=`$DIG_SOA @$ip | $AWK '{print $3}'`
-
- return 0
-}
-
-# \brief Compare client and server SOAs
-#
-# Checks the SOAs of two systems and reports if they are not equal.
-#
-# \arg $1 Name of the IXFR server
-# \arg $2 IP of the IXFR server
-# \arg $3 Name of the IXFR client
-# \arg $4 IP of the IXFR client
-#
-# \return 0 if the systems have the same SOA, 1 if not. In the latter case,
-# an error will be output.
-compare_soa() {
-
- # If the following checks fail, the code is wrong.
-
- check_name_ip $*
- if [ $? -ne 0 ];
- then
- echo "R:FAIL compare_soa - name or ip address of server not supplied"
- return 1
- fi
-
- server_name=$1
- shift
- server_ip=$1
- shift
-
- check_name_ip $*
- if [ $? -ne 0 ];
- then
- echo "R:FAIL compare_soa - name or ip address of client not supplied"
- return 1
- fi
-
- client_name=$1
- shift
- client_ip=$1
- shift
-
- client_serial=`$DIG_SOA @$client_ip | $AWK '{print $3}'`
- server_serial=`$DIG_SOA @$server_ip | $AWK '{print $3}'`
- if [ "$client_serial" != "$server_serial" ];
- then
- echo "R:FAIL client $client_name serial $client_serial not same as server $server_name serial $server_serial"
- return 1
- fi
-
- return 0
-}
-
-# \brief Compare client and server zones
-#
-# Checks the zones of two systems and reports if they are not identical.
-#
-# The check is simplistic. Each zone is listed via "dig", after which comment
-# lines, blank lines and spaces/tabs are removed, and the result sorted. The
-# output from each system is then compared. They should be identical.
-#
-# \arg $1 Name of the IXFR server
-# \arg $2 IP of the IXFR server
-# \arg $3 Name of the IXFR client
-# \arg $4 IP of the IXFR client
-#
-# \return 0 if the zones are the same, 1 if not.
-compare_zones() {
-
- # If the following checks fail, the code is wrong.
-
- check_name_ip $*
- if [ $? -ne 0 ];
- then
- echo "R:FAIL compare_zones - name or ip address of server not supplied"
- return 1
- fi
-
- server_name=$1
- shift
- server_ip=$1
- shift
-
- check_name_ip $*
- if [ $? -ne 0 ];
- then
- echo "R:FAIL compare_zones - name or ip address of client not supplied"
- return 1
- fi
-
- client_name=$1
- shift
- client_ip=$1
- shift
-
- $DIG @$client_ip -p $DNS_PORT example. axfr | grep -v '^;' | grep -v '^$' \
- | sed -e 's/ //g' -e 's/\t//g' | sort > client.dig
- $DIG @$server_ip -p $DNS_PORT example. axfr | grep -v '^;' | grep -v '^$' \
- | sed -e 's/ //g' -e 's/\t//g' | sort > server.dig
- diff client.dig server.dig
- if [ $? -eq 0 ];
- then
- echo "I:client and server zones identical"
- else
- echo "R:FAIL client $client_name zone not same as server $server_name zone"
- return 1
- fi
-
- return 0
-}
diff --git a/tests/system/ixfr/named_noixfr.conf b/tests/system/ixfr/named_noixfr.conf
deleted file mode 100644
index d171876..0000000
--- a/tests/system/ixfr/named_noixfr.conf
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2004, 2007, 2011 Internet Systems Consortium, Inc. ("ISC")
- * Copyright (C) 2000, 2001 Internet Software Consortium.
- *
- * 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 "../../../common/rndc.key";
-
-controls {
- inet 10.53.0.1 port 9953 allow { any; } keys { rndc_key; };
-};
-
-options {
- query-source address 10.53.0.1;
- notify-source 10.53.0.1;
- transfer-source 10.53.0.1;
- port 53210;
- pid-file "named.pid";
- listen-on { 10.53.0.1; };
- listen-on-v6 { none; };
- recursion no;
- ixfr-from-differences no;
- notify explicit;
- also-notify { 10.53.0.2; };
- provide-ixfr no;
-};
-
-zone "example" {
- type master;
- file "db.example";
-};
diff --git a/tests/system/ixfr/named_nonotify.conf b/tests/system/ixfr/named_nonotify.conf
deleted file mode 100644
index c08c212..0000000
--- a/tests/system/ixfr/named_nonotify.conf
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2004, 2007, 2011 Internet Systems Consortium, Inc. ("ISC")
- * Copyright (C) 2000, 2001 Internet Software Consortium.
- *
- * 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 "../../../common/rndc.key";
-
-controls {
- inet 10.53.0.1 port 9953 allow { any; } keys { rndc_key; };
-};
-
-options {
- query-source address 10.53.0.1;
- notify-source 10.53.0.1;
- transfer-source 10.53.0.1;
- port 53210;
- pid-file "named.pid";
- listen-on { 10.53.0.1; };
- listen-on-v6 { none; };
- recursion no;
- ixfr-from-differences yes;
- notify no;
-};
-
-zone "example" {
- type master;
- file "db.example";
-};
diff --git a/tests/system/ixfr/named_notify.conf b/tests/system/ixfr/named_notify.conf
deleted file mode 100644
index df45e6f..0000000
--- a/tests/system/ixfr/named_notify.conf
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (C) 2004, 2007, 2011 Internet Systems Consortium, Inc. ("ISC")
- * Copyright (C) 2000, 2001 Internet Software Consortium.
- *
- * 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 "../../../common/rndc.key";
-
-controls {
- inet 10.53.0.1 port 9953 allow { any; } keys { rndc_key; };
-};
-
-options {
- query-source address 10.53.0.1;
- notify-source 10.53.0.1;
- transfer-source 10.53.0.1;
- port 53210;
- pid-file "named.pid";
- listen-on { 10.53.0.1; };
- listen-on-v6 { none; };
- recursion no;
- ixfr-from-differences yes;
- notify explicit;
- also-notify { 10.53.0.2; };
-};
-
-zone "example" {
- type master;
- file "db.example";
-};
diff --git a/tests/system/run.sh.in b/tests/system/run.sh.in
deleted file mode 100755
index 619b865..0000000
--- a/tests/system/run.sh.in
+++ /dev/null
@@ -1,125 +0,0 @@
-#!/bin/sh
-#
-# Copyright (C) 2004, 2007, 2010 Internet Systems Consortium, Inc. ("ISC")
-# Copyright (C) 2000, 2001 Internet Software Consortium.
-#
-# 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.
-
-#
-# Run a system test.
-#
-
-SYSTEMTOP=@abs_top_builddir@/tests/system
-. $SYSTEMTOP/conf.sh
-
-stopservers=true
-
-case $1 in
- --keep) stopservers=false; shift ;;
-esac
-
-test $# -gt 0 || { echo "usage: $0 [--keep] test-directory" >&2; exit 1; }
-
-test=$1
-shift
-
-test -d $test || { echo "$0: $test: no such test" >&2; exit 1; }
-
-echo "S:$test:`date`" >&2
-echo "T:$test:1:A" >&2
-echo "A:System test $test" >&2
-
-if [ x$PERL = x ]
-then
- echo "I:Perl not available. Skipping test." >&2
- echo "R:UNTESTED" >&2
- echo "E:$test:`date`" >&2
- exit 0;
-fi
-
-$PERL $TESTSOCK || {
- echo "I:Network interface aliases not set up. Skipping test." >&2;
- echo "R:UNTESTED" >&2;
- echo "E:$test:`date`" >&2;
- exit 0;
-}
-
-
-# Check for test-specific prerequisites.
-test ! -f $test/prereq.sh || ( cd $test && sh prereq.sh "$@" )
-result=$?
-
-if [ $result -eq 0 ]; then
- : prereqs ok
-else
- echo "I:Prerequisites for $test missing, skipping test." >&2
- [ $result -eq 255 ] && echo "R:SKIPPED" || echo "R:UNTESTED"
- echo "E:$test:`date`" >&2
- exit 0
-fi
-
-# Check for PKCS#11 support
-if
- test ! -f $test/usepkcs11 || sh cleanpkcs11.sh
-then
- : pkcs11 ok
-else
- echo "I:Need PKCS#11 for $test, skipping test." >&2
- echo "R:PKCS11ONLY" >&2
- echo "E:$test:`date`" >&2
- exit 0
-fi
-
-# Set up any dynamically generated test data
-if test -f $test/setup.sh
-then
- ( cd $test && sh setup.sh "$@" )
-fi
-
-# Start name servers running
-$PERL $SYSTEMTOP/start.pl $test || exit 1
-
-# Run the tests
-( cd $test ; sh tests.sh )
-
-status=$?
-
-if $stopservers
-then
- :
-else
- exit $status
-fi
-
-# Shutdown
-$PERL $SYSTEMTOP/stop.pl $test
-
-status=`expr $status + $?`
-
-if [ $status != 0 ]; then
- echo "R:FAIL"
- # Don't clean up - we need the evidence.
- find . -name core -exec chmod 0644 '{}' \;
-else
- echo "R:PASS"
-
- # Clean up.
- if test -f $test/clean.sh
- then
- ( cd $test && sh clean.sh "$@" )
- fi
-fi
-
-echo "E:$test:`date`"
-
-exit $status
diff --git a/tests/system/runall.sh b/tests/system/runall.sh
deleted file mode 100755
index 5d0fe9b..0000000
--- a/tests/system/runall.sh
+++ /dev/null
@@ -1,44 +0,0 @@
-#!/bin/sh
-#
-# Copyright (C) 2004, 2007, 2010 Internet Systems Consortium, Inc. ("ISC")
-# Copyright (C) 2000, 2001 Internet Software Consortium.
-#
-# 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.
-
-#
-# Run all the system tests.
-#
-
-SYSTEMTESTTOP=.
-. $SYSTEMTESTTOP/conf.sh
-
-status=0
-
-for d in $SUBDIRS
-do
- sh run.sh $d || status=1
-done
-
-$PERL $TESTSOCK || {
- cat <<EOF >&2
-I:
-I:NOTE: Many of the tests were skipped because they require that
-I: the IP addresses 10.53.0.1 through 10.53.0.7 are configured
-I: as alias addresses on the loopback interface. Please run
-I: "tests/system/ifconfig.sh up" as root to configure them
-I: and rerun the tests.
-EOF
- exit 0;
-}
-
-exit $status
diff --git a/tests/system/start.pl b/tests/system/start.pl
deleted file mode 100755
index 32284de..0000000
--- a/tests/system/start.pl
+++ /dev/null
@@ -1,229 +0,0 @@
-#!/usr/bin/perl -w
-#
-# Copyright (C) 2004-2008, 2010 Internet Systems Consortium, Inc. ("ISC")
-# Copyright (C) 2001 Internet Software Consortium.
-#
-# 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.
-
-# Framework for starting test servers.
-# Based on the type of server specified, check for port availability, remove
-# temporary files, start the server, and verify that the server is running.
-# If a server is specified, start it. Otherwise, start all servers for test.
-
-use strict;
-use Cwd 'abs_path';
-use Getopt::Long;
-
-# Option handling
-# --noclean test [server [options]]
-#
-# --noclean - Do not cleanup files in server directory
-# test - name of the test directory
-# server - name of the server directory
-# options - alternate options for the server
-
-my $usage = "usage: $0 [--noclean] test-directory [server-directory [server-options]]";
-my $noclean;
-GetOptions('noclean' => \$noclean);
-my $test = $ARGV[0];
-my $server = $ARGV[1];
-my $options = $ARGV[2];
-
-if (!$test) {
- print "$usage\n";
-}
-if (!-d $test) {
- print "No test directory: \"$test\"\n";
-}
-if ($server && !-d "$test/$server") {
- print "No server directory: \"$test/$server\"\n";
-}
-
-# Global variables
-my $topdir = abs_path("$test/..");
-my $testdir = abs_path("$test");
-my $RUN_BIND10 = $ENV{'RUN_BIND10'};
-my $RUN_BINDCTL = $ENV{'RUN_BINDCTL'};
-my $BINDCTL_CSV_DIR = $ENV{'BINDCTL_CSV_DIR'};
-my $NAMED = $ENV{'BIND9_NAMED'};
-my $LWRESD = $ENV{'LWRESD'};
-my $DIG = $ENV{'DIG'};
-my $PERL = $ENV{'PERL'};
-my $TESTSOCK = $ENV{'TESTSOCK'};
-
-# Start the server(s)
-
-if ($server) {
- if ($server =~ /^ns/) {
- &check_ports($server);
- }
- &start_server($server, $options);
- if ($server =~ /^ns/) {
- &verify_server($server);
- }
-} else {
- # Determine which servers need to be started for this test.
- opendir DIR, $testdir;
- my @files = sort readdir DIR;
- closedir DIR;
-
- my @ns = grep /^nsx?[0-9]*$/, @files;
- my @lwresd = grep /^lwresd[0-9]*$/, @files;
- my @ans = grep /^ans[0-9]*$/, @files;
-
- # Start the servers we found.
- &check_ports();
- foreach my $s (@ns, @lwresd, @ans) {
- &start_server($s);
- }
- foreach my $s (@ns) {
- &verify_server($s);
- }
-}
-
-# Subroutines
-
-sub check_ports {
- my $server = shift;
- my $options = "";
-
- if ($server && $server =~ /(\d+)$/) {
- $options = "-i $1";
- }
-
- my $tries = 0;
- while (1) {
- my $return = system("$PERL $TESTSOCK -p 53210 $options");
- last if ($return == 0);
- if (++$tries > 4) {
- print "$0: could not bind to server addresses, still running?\n";
- print "I:server sockets not available\n";
- print "R:FAIL\n";
- system("$PERL $topdir/stop.pl $testdir"); # Is this the correct behavior?
- exit 1;
- }
- print "I:Couldn't bind to socket (yet)\n";
- sleep 2;
- }
-}
-
-sub start_server {
- my $server = shift;
- my $options = shift;
-
- my $cleanup_files;
- my $command;
- my $pid_file;
-
- if ($server =~ /^nsx/) {
- $cleanup_files = "{bind10.run}";
- $command = "B10_FROM_SOURCE_LOCALSTATEDIR=$testdir/$server/ ";
- $command .= "$RUN_BIND10 ";
- if ($options) {
- $command .= "$options";
- } else {
- $command .= "--msgq-socket-file=$testdir/$server/msgq_socket ";
- $command .= "--pid-file=$testdir/$server/bind10.pid ";
- $command .= "-v";
- }
- $command .= " >bind10.run 2>&1 &";
- $pid_file = "bind10.pid";
- } elsif ($server =~ /^ns/) {
- $cleanup_files = "{*.jnl,*.bk,*.st,named.run}";
- $command = "$NAMED ";
- if ($options) {
- $command .= "$options";
- } else {
- $command .= "-m record,size,mctx ";
- $command .= "-T clienttest ";
- $command .= "-T nosoa "
- if (-e "$testdir/$server/named.nosoa");
- $command .= "-T noaa "
- if (-e "$testdir/$server/named.noaa");
- $command .= "-c named.conf -d 99 -g";
- }
- $command .= " >named.run 2>&1 &";
- $pid_file = "named.pid";
- } elsif ($server =~ /^lwresd/) {
- $cleanup_files = "{lwresd.run}";
- $command = "$LWRESD ";
- if ($options) {
- $command .= "$options";
- } else {
- $command .= "-m record,size,mctx ";
- $command .= "-T clienttest ";
- $command .= "-C resolv.conf -d 99 -g ";
- $command .= "-i lwresd.pid -P 9210 -p 53210";
- }
- $command .= " >lwresd.run 2>&1 &";
- $pid_file = "lwresd.pid";
- } elsif ($server =~ /^ans/) {
- $cleanup_files = "{ans.run}";
- $command = "$PERL ./ans.pl ";
- if ($options) {
- $command .= "$options";
- } else {
- $command .= "";
- }
- $command .= " >ans.run 2>&1 &";
- $pid_file = "ans.pid";
- } else {
- print "I:Unknown server type $server\n";
- print "R:FAIL\n";
- system "$PERL $topdir/stop.pl $testdir";
- exit 1;
- }
-
- print "I:starting server $server\n";
-
- chdir "$testdir/$server";
-
- unless ($noclean) {
- unlink glob $cleanup_files;
- }
-
- system "$command";
-
- my $tries = 0;
- while (!-f $pid_file) {
- if (++$tries > 14) {
- print "I:Couldn't start server $server\n";
- print "R:FAIL\n";
- system "$PERL $topdir/stop.pl $testdir";
- exit 1;
- }
- sleep 1;
- }
-}
-
-sub verify_server {
- my $server = shift;
- my $n = $server;
- $n =~ s/^nsx?//;
-
- my $tries = 0;
- while (1) {
- my $return = system("echo \"Stats show\" | $RUN_BINDCTL --csv-file-dir=$BINDCTL_CSV_DIR > bindctl.out");
- last if ($return == 0);
- if (++$tries >= 30) {
- print "I:no response from $server\n";
- print "R:FAIL\n";
- system("$PERL $topdir/stop.pl $testdir");
- exit 1;
- } else {
- print "I:no response from $server. retrying.\n";
- }
- sleep 2;
- }
- unlink "dig.out";
-}
diff --git a/tests/system/stop.pl b/tests/system/stop.pl
deleted file mode 100755
index a803f52..0000000
--- a/tests/system/stop.pl
+++ /dev/null
@@ -1,188 +0,0 @@
-#!/usr/bin/perl -w
-#
-# Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
-# Copyright (C) 2001 Internet Software Consortium.
-#
-# 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.
-
-# Framework for stopping test servers
-# Based on the type of server specified, signal the server to stop, wait
-# briefly for it to die, and then kill it if it is still alive.
-# If a server is specified, stop it. Otherwise, stop all servers for test.
-
-use strict;
-use Cwd 'abs_path';
-
-# Option handling
-# [--use-rndc] test [server]
-#
-# test - name of the test directory
-# server - name of the server directory
-
-my $usage = "usage: $0 [--use-rndc] test-directory [server-directory]";
-my $use_rndc;
-
-while (@ARGV && $ARGV[0] =~ /^-/) {
- my $opt = shift @ARGV;
- if ($opt eq '--use-rndc') {
- $use_rndc = 1;
- } else {
- die "$usage\n";
- }
-}
-
-my $test = $ARGV[0];
-my $server = $ARGV[1];
-
-my $errors = 0;
-
-die "$usage\n" unless defined($test);
-die "No test directory: \"$test\"\n" unless (-d $test);
-die "No server directory: \"$server\"\n" if (defined($server) && !-d "$test/$server");
-
-# Global variables
-my $testdir = abs_path($test);
-my @servers;
-
-
-# Determine which servers need to be stopped.
-if (defined $server) {
- @servers = ($server);
-} else {
- local *DIR;
- opendir DIR, $testdir or die "$testdir: $!\n";
- my @files = sort readdir DIR;
- closedir DIR;
-
- my @ns = grep /^nsx?[0-9]*$/, @files;
- my @lwresd = grep /^lwresd[0-9]*$/, @files;
- my @ans = grep /^ans[0-9]*$/, @files;
-
- push @servers, @ns, @lwresd, @ans;
-}
-
-
-# Stop the server(s), pass 1: rndc.
-if ($use_rndc) {
- foreach my $server (grep /^ns/, @servers) {
- stop_rndc($server);
- }
-
- wait_for_servers(30, grep /^ns/, @servers);
-}
-
-
-# Pass 2: SIGTERM
-foreach my $server (@servers) {
- stop_signal($server, "TERM");
-}
-
-wait_for_servers(60, @servers);
-
-# Pass 3: SIGABRT
-foreach my $server (@servers) {
- stop_signal($server, "ABRT");
-}
-
-exit($errors ? 1 : 0);
-
-# Subroutines
-
-# Return the full path to a given server's PID file.
-sub server_pid_file {
- my($server) = @_;
-
- my $pid_file;
- if ($server =~ /^nsx/) {
- $pid_file = "bind10.pid";
- } elsif ($server =~ /^ns/) {
- $pid_file = "named.pid";
- } elsif ($server =~ /^lwresd/) {
- $pid_file = "lwresd.pid";
- } elsif ($server =~ /^ans/) {
- $pid_file = "ans.pid";
- } else {
- print "I:Unknown server type $server\n";
- exit 1;
- }
- $pid_file = "$testdir/$server/$pid_file";
-}
-
-# Read a PID.
-sub read_pid {
- my($pid_file) = @_;
-
- local *FH;
- my $result = open FH, "< $pid_file";
- if (!$result) {
- print "I:$pid_file: $!\n";
- unlink $pid_file;
- return;
- }
-
- my $pid = <FH>;
- chomp($pid);
- return $pid;
-}
-
-# Stop a named process with rndc.
-sub stop_rndc {
- my($server) = @_;
-
- return unless ($server =~ /^ns(\d+)$/);
- my $ip = "10.53.0.$1";
-
- # Ugly, but should work.
- system("$ENV{RNDC} -c $testdir/../common/rndc.conf -s $ip -p 9953 stop | sed 's/^/I:$server /'");
- return;
-}
-
-# Stop a server by sending a signal to it.
-sub stop_signal {
- my($server, $sig) = @_;
-
- my $pid_file = server_pid_file($server);
- return unless -f $pid_file;
-
- my $pid = read_pid($pid_file);
- return unless defined($pid);
-
- if ($sig eq 'ABRT') {
- print "I:$server didn't die when sent a SIGTERM\n";
- $errors++;
- }
-
- my $result = kill $sig, $pid;
- if (!$result) {
- print "I:$server died before a SIG$sig was sent\n";
- unlink $pid_file;
- $errors++;
- }
-
- return;
-}
-
-sub wait_for_servers {
- my($timeout, @servers) = @_;
-
- my @pid_files = grep { defined($_) }
- map { server_pid_file($_) } @servers;
-
- while ($timeout > 0 && @pid_files > 0) {
- @pid_files = grep { -f $_ } @pid_files;
- sleep 1 if (@pid_files > 0);
- $timeout--;
- }
-
- return;
-}
diff --git a/tests/tools/badpacket/option_info.h b/tests/tools/badpacket/option_info.h
index aebeb66..944f60e 100644
--- a/tests/tools/badpacket/option_info.h
+++ b/tests/tools/badpacket/option_info.h
@@ -129,7 +129,7 @@ public:
///
/// \return The offset of the field corresponding to this option in the DNS
/// message flags field. The returned value is only valid for
- /// options that correpond to fields in the flags word.
+ /// options that correspond to fields in the flags word.
static int offset(int index);
/// \brief Return minimum allowed value of an option
diff --git a/tests/tools/dhcp-ubench/benchmark.h b/tests/tools/dhcp-ubench/benchmark.h
index 6001e81..fc33606 100644
--- a/tests/tools/dhcp-ubench/benchmark.h
+++ b/tests/tools/dhcp-ubench/benchmark.h
@@ -178,7 +178,7 @@ protected:
/// Number of operations (e.g. insert lease num times)
uint32_t num_;
- /// Synchronous or asynchonous mode?
+ /// Synchronous or asynchronous mode?
bool sync_;
/// Should the test print out extra information?
diff --git a/tests/tools/dhcp-ubench/dhcp-perf-guide.xml b/tests/tools/dhcp-ubench/dhcp-perf-guide.xml
index 583b155..417968d 100644
--- a/tests/tools/dhcp-ubench/dhcp-perf-guide.xml
+++ b/tests/tools/dhcp-ubench/dhcp-perf-guide.xml
@@ -172,7 +172,7 @@
<para>
The framework attempts to do the same amount of work for every
- backend thus allowing fair complarison between them.
+ backend thus allowing fair comparison between them.
</para>
</section>
@@ -898,7 +898,7 @@ SQLite version: 3.7.9sourceid version is 2011-11-01 00:52:41 c7c6050ef060877ebe7
</para>
<para>
- It should be emphaisized that obtained measurements indicate
+ It should be emphasized that obtained measurements indicate
only database performance and they cannot be directly
translated to expected leases per second or queries per second
performance by an actual server. The DHCP server must do much
@@ -1160,7 +1160,7 @@ The exit status is:
<para>
Currently, perfdhcp is seen from the server perspective as relay agent.
This simplifies its implementation: specifically there is no need to
- receive traffic sent to braodcast addresses. However, it does impose
+ receive traffic sent to broadcast addresses. However, it does impose
a requirement that the IPv4
address has to be set manually on the interface that will be used to
communicate with the server. For example, if the DHCPv4 server is listening
@@ -1384,7 +1384,7 @@ collected packets: 0
The content in template files is encoded as series of ASCII hexadecimal
digits (each byte represented by two ASCII chars 00..FF). Data in a
template file is laid in network byte order and it can be used on the
- systems with different endianess.
+ systems with different endianness.
perfdhcp forms the packet by replacing parts of the message buffer read
from the file with variable data such as elapsed time, hardware address, DUID
etc. The offsets where such variable data is placed is specific to the
diff --git a/tests/tools/perfdhcp/command_options.cc b/tests/tools/perfdhcp/command_options.cc
index 9433442..9169600 100644
--- a/tests/tools/perfdhcp/command_options.cc
+++ b/tests/tools/perfdhcp/command_options.cc
@@ -548,7 +548,7 @@ CommandOptions::decodeDuid(const std::string& base) {
} catch (isc::InvalidParameter&) {
isc_throw(isc::InvalidParameter,
"invalid characters in DUID provided,"
- " exepected hex digits");
+ " expected hex digits");
}
duid_template.push_back(static_cast<uint8_t>(ui));
}
diff --git a/tests/tools/perfdhcp/command_options.h b/tests/tools/perfdhcp/command_options.h
index 4b804dc..246fea3 100644
--- a/tests/tools/perfdhcp/command_options.h
+++ b/tests/tools/perfdhcp/command_options.h
@@ -443,7 +443,7 @@ private:
std::vector<int> xid_offset_;
/// Random value offset in templates. Random value offset
/// points to last octet of DUID. Up to 4 last octets of
- /// DUID are randomized to simulate differnt clients.
+ /// DUID are randomized to simulate different clients.
std::vector<int> rnd_offset_;
/// Offset of elapsed time option in template packet.
int elp_offset_;
diff --git a/tests/tools/perfdhcp/stats_mgr.h b/tests/tools/perfdhcp/stats_mgr.h
index 537e81d..5e143e6 100644
--- a/tests/tools/perfdhcp/stats_mgr.h
+++ b/tests/tools/perfdhcp/stats_mgr.h
@@ -104,7 +104,7 @@ public:
private:
/// \brief Default constructor.
///
- /// Default constrcutor is private because we don't want client
+ /// Default constructor is private because we don't want client
/// class to call it because we want client class to specify
/// counter's name.
CustomCounter() { };
@@ -494,7 +494,7 @@ public:
/// \return maximum delay between packets.
double getMaxDelay() const { return(max_delay_); }
- /// \brief Return avarage packet delay.
+ /// \brief Return average packet delay.
///
/// Method returns average packet delay. If no packets have been
/// received for this exchange avg delay can't be calculated and
@@ -668,7 +668,7 @@ public:
if (rcvd_packets_num_ == 0) {
std::cout << "Unavailable! No packets received." << std::endl;
}
- // We will be using boost::posix_time extensivelly here
+ // We will be using boost::posix_time extensively here
using namespace boost::posix_time;
// Iterate through all received packets.
@@ -988,7 +988,7 @@ public:
return(xchg_stats->getMaxDelay());
}
- /// \brief Return avarage packet delay.
+ /// \brief Return average packet delay.
///
/// Method returns average packet delay for specified
/// exchange type.
diff --git a/tests/tools/perfdhcp/test_control.cc b/tests/tools/perfdhcp/test_control.cc
index e51065f..4a3075a 100644
--- a/tests/tools/perfdhcp/test_control.cc
+++ b/tests/tools/perfdhcp/test_control.cc
@@ -1804,7 +1804,7 @@ TestControl::setDefaults4(const TestControlSocket& socket,
pkt->setRemotePort(DHCP4_SERVER_PORT);
// The remote server's name or IP.
pkt->setRemoteAddr(IOAddress(options.getServerName()));
- // Set local addresss.
+ // Set local address.
pkt->setLocalAddr(IOAddress(socket.addr_));
// Set relay (GIADDR) address to local address.
pkt->setGiaddr(IOAddress(socket.addr_));
diff --git a/tests/tools/perfdhcp/test_control.h b/tests/tools/perfdhcp/test_control.h
index 245cf6d..d3196f7 100644
--- a/tests/tools/perfdhcp/test_control.h
+++ b/tests/tools/perfdhcp/test_control.h
@@ -85,7 +85,7 @@ static const size_t DHCPV6_IA_NA_OFFSET = 40;
/// - calculate how many packets must be send to satisfy desired rate,
/// - receive incoming packets from the server,
/// - check the exit conditions - terminate the program if the exit criteria
-/// are fulfiled, e.g. reached maximum number of packet drops,
+/// are fulfilled, e.g. reached maximum number of packet drops,
/// - send the number of packets appropriate to satisfy the desired rate,
/// - optionally print intermediate reports,
/// - print statistics, e.g. achieved rate,
@@ -245,7 +245,7 @@ public:
/// throw exception.
///
/// \throw isc::InvalidOperation if command line options are not parsed.
- /// \throw isc::Unexpected if internal Test Controler error occured.
+ /// \throw isc::Unexpected if internal Test Controller error occured.
/// \return error_code, 3 if number of received packets is not equal
/// to number of sent packets, 0 if everything is ok.
int run();
@@ -282,14 +282,14 @@ protected:
/// \brief Check if test exit condtitions fulfilled.
///
- /// Method checks if the test exit conditions are fulfiled.
+ /// Method checks if the test exit conditions are fulfilled.
/// Exit conditions are checked periodically from the
/// main loop. Program should break the main loop when
/// this method returns true. It is calling function
/// responsibility to break main loop gracefully and
/// cleanup after test execution.
///
- /// \return true if any of the exit conditions is fulfiled.
+ /// \return true if any of the exit conditions is fulfilled.
bool checkExitConditions() const;
/// \brief Factory function to create DHCPv6 ELAPSED_TIME option.
@@ -483,7 +483,7 @@ protected:
/// \throw isc::BadValue if socket can't be created for given
/// interface, local address or remote address.
/// \throw isc::InvalidOperation if broadcast option can't be
- /// set for the v4 socket or if multicast option cat't be set
+ /// set for the v4 socket or if multicast option can't be set
/// for the v6 socket.
/// \throw isc::Unexpected if interal unexpected error occured.
/// \return socket descriptor.
@@ -643,7 +643,7 @@ protected:
/// \brief Send DHCPv4 DISCOVER message from template.
///
/// Method sends DHCPv4 DISCOVER message from template. The
- /// template data is exepcted to be in binary format. Provided
+ /// template data is expected to be in binary format. Provided
/// buffer is copied and parts of it are replaced with actual
/// data (e.g. MAC address, transaction id etc.).
/// Copy of sent packet is stored in the stats_mgr4_ object to
diff --git a/tests/tools/perfdhcp/tests/command_options_helper.h b/tests/tools/perfdhcp/tests/command_options_helper.h
index 7436bd7..253fe12 100644
--- a/tests/tools/perfdhcp/tests/command_options_helper.h
+++ b/tests/tools/perfdhcp/tests/command_options_helper.h
@@ -53,7 +53,7 @@ public:
/// \brief Destructor.
///
- /// Dealocates wrapped array of C-strings.
+ /// Deallocates wrapped array of C-strings.
~ArgvPtr() {
if (argv_ != NULL) {
for(int i = 0; i < argc_; ++i) {
diff --git a/tests/tools/perfdhcp/tests/command_options_unittest.cc b/tests/tools/perfdhcp/tests/command_options_unittest.cc
index 360178f..bda256f 100644
--- a/tests/tools/perfdhcp/tests/command_options_unittest.cc
+++ b/tests/tools/perfdhcp/tests/command_options_unittest.cc
@@ -546,7 +546,7 @@ TEST_F(CommandOptionsTest, Interface) {
// In order to make this test portable we need to know
// at least one interface name on OS where test is run.
// Interface Manager has ability to detect interfaces.
- // Altough we don't call initIsInterface explicitely
+ // Although we don't call initIsInterface explicitely
// here it is called by CommandOptions object interally
// so this function is covered by the test.
dhcp::IfaceMgr& iface_mgr = dhcp::IfaceMgr::instance();
diff --git a/tests/tools/perfdhcp/tests/stats_mgr_unittest.cc b/tests/tools/perfdhcp/tests/stats_mgr_unittest.cc
index 8a83cac..ebb4f34 100644
--- a/tests/tools/perfdhcp/tests/stats_mgr_unittest.cc
+++ b/tests/tools/perfdhcp/tests/stats_mgr_unittest.cc
@@ -262,7 +262,7 @@ TEST_F(StatsMgrTest, SendReceiveSimple) {
boost::shared_ptr<Pkt4> rcvd_packet(createPacket4(DHCPOFFER,
common_transid));
stats_mgr->addExchangeStats(StatsMgr4::XCHG_DO);
- // The following attempt is expected to pass becase the right
+ // The following attempt is expected to pass because the right
// exchange type is used.
ASSERT_NO_THROW(
stats_mgr->passSentPacket(StatsMgr4::XCHG_DO, sent_packet)
diff --git a/tests/tools/perfdhcp/tests/test_control_unittest.cc b/tests/tools/perfdhcp/tests/test_control_unittest.cc
index ae67e6e..f7666ae 100644
--- a/tests/tools/perfdhcp/tests/test_control_unittest.cc
+++ b/tests/tools/perfdhcp/tests/test_control_unittest.cc
@@ -263,7 +263,7 @@ public:
/// If number of clients is between 257 and 65536 they can differ
/// on two last positions so the returned value will be 2 and so on.
///
- /// \param clients_num number of simulated clinets
+ /// \param clients_num number of simulated clients
/// \return maximum mismatch position
int unequalOctetPosition(int clients_num) const {
if (!clients_num) {
diff --git a/tools/query_cmp/src/lib/compare_rrset.py b/tools/query_cmp/src/lib/compare_rrset.py
index 737d761..d7b3425 100755
--- a/tools/query_cmp/src/lib/compare_rrset.py
+++ b/tools/query_cmp/src/lib/compare_rrset.py
@@ -242,7 +242,7 @@ def resp_casecmp(msg1, msg2, num):
msg1.get_section(Message.SECTION_ADDITIONAL), \
msg2.get_section(Message.SECTION_ADDITIONAL))
- # If there are any differnt comparisons in the sections above, print the details
+ # If there are any different comparisons in the sections above, print the details
# contained in buf formattedly.
if not res_hdr or not res_ques or not res_ans or not res_auth or not res_addi:
print('=' * 30, ' BEGIN QUERY %s ' % num, '=' * 30, sep='')
diff --git a/tools/reorder_message_file.py b/tools/reorder_message_file.py
index 2ba4d7c..ce5934f 100644
--- a/tools/reorder_message_file.py
+++ b/tools/reorder_message_file.py
@@ -142,7 +142,7 @@ def print_dict(dictionary):
Prints the dictionary with a blank line between entries.
Parameters:
- dicitionary - Map holding the message dictionary
+ dictionary - Map holding the message dictionary
"""
count = 0
for msgid in sorted(dictionary):
More information about the bind10-changes
mailing list