Commit bfcd0225 authored by Stephen Morris's avatar Stephen Morris
Browse files

Merge branch 'master' into trac1071

parents e3d273a6 2c936393
266. [func] Multiple developers
Convert various error messages, debugging and other output
to the new logging interface, including for b10-resolver,
the resolver library, the CC library, b10-auth, b10-cfgmgr,
b10-xfrin, and b10-xfrout. This includes a lot of new
documentation describing the new log messages.
(Trac #738, #739, #742, #746, #759, #761, #762)
265. [func]* jinmei
b10-resolver: Introduced ACL on incoming queries. By default the
resolver accepts queries from ::1 and 127.0.0.1 and rejects all
......@@ -52,7 +60,7 @@
Now builds and runs with Python 3.2
(Trac #710, git dae1d2e24f993e1eef9ab429326652f40a006dfb)
257. [bug] y-aharen
257. [bug] y-aharen
Fixed a bug an instance of IntervalTimerImpl may be destructed
while deadline_timer is holding the handler. This fix addresses
occasional failure of IntervalTimerTest.destructIntervalTimer.
......@@ -61,25 +69,25 @@
256. [bug] jerry
src/bin/xfrin: update xfrin to check TSIG before other part of
incoming message.
(Trac955, git 261450e93af0b0406178e9ef121f81e721e0855c)
(Trac #955, git 261450e93af0b0406178e9ef121f81e721e0855c)
255. [func] zhang likun
src/lib/cache: remove empty code in lib/cache and the corresponding
suppression rule in src/cppcheck-suppress.lst.
(Trac639, git 4f714bac4547d0a025afd314c309ca5cb603e212)
(Trac #639, git 4f714bac4547d0a025afd314c309ca5cb603e212)
254. [bug] jinmei
b10-xfrout: failed to send notifies over IPv6 correctly.
(Trac964, git 3255c92714737bb461fb67012376788530f16e40)
(Trac #964, git 3255c92714737bb461fb67012376788530f16e40)
253. [func] jelte
253. [func] jelte
Add configuration options for logging through the virtual module
Logging.
(Trac 736, git 9fa2a95177265905408c51d13c96e752b14a0824)
(Trac #736, git 9fa2a95177265905408c51d13c96e752b14a0824)
252. [func] stephen
252. [func] stephen
Add syslog as destination for logging.
(Trac976, git 31a30f5485859fd3df2839fc309d836e3206546e)
(Trac #976, git 31a30f5485859fd3df2839fc309d836e3206546e)
251. [bug]* jinmei
Make sure bindctl private files are non readable to anyone except
......@@ -88,38 +96,38 @@
group will have to be adjusted. Also note that this change is
only effective for a fresh install; if these files already exist,
their permissions must be adjusted by hand (if necessary).
(Trac870, git 461fc3cb6ebabc9f3fa5213749956467a14ebfd4)
(Trac #870, git 461fc3cb6ebabc9f3fa5213749956467a14ebfd4)
250. [bug] ocean
250. [bug] ocean
src/lib/util/encode, in some conditions, the DecodeNormalizer's
iterator may reach the end() and when later being dereferenced
it will cause crash on some platform.
(Trac838, git 83e33ec80c0c6485d8b116b13045b3488071770f)
(Trac #838, git 83e33ec80c0c6485d8b116b13045b3488071770f)
249. [func] jerry
249. [func] jerry
xfrout: add support for TSIG verification.
(Trac816, git 3b2040e2af2f8139c1c319a2cbc429035d93f217)
(Trac #816, git 3b2040e2af2f8139c1c319a2cbc429035d93f217)
248. [func] stephen
248. [func] stephen
Add file and stderr as destinations for logging.
(Trac555, git 38b3546867425bd64dbc5920111a843a3330646b)
(Trac #555, git 38b3546867425bd64dbc5920111a843a3330646b)
247. [func] jelte
247. [func] jelte
Upstream queries from the resolver now set EDNS0 buffer size.
(Trac834, git 48e10c2530fe52c9bde6197db07674a851aa0f5d)
(Trac #834, git 48e10c2530fe52c9bde6197db07674a851aa0f5d)
246. [func] stephen
246. [func] stephen
Implement logging using log4cplus (http://log4cplus.sourceforge.net)
(Trac899, git 31d3f525dc01638aecae460cb4bc2040c9e4df10)
(Trac #899, git 31d3f525dc01638aecae460cb4bc2040c9e4df10)
245. [func] vorner
245. [func] vorner
Authoritative server can now sign the answers using TSIG
(configured in tsig_keys/keys, list of strings like
"name:<base64-secret>:sha1-hmac"). It doesn't use them for
ACL yet, only verifies them and signs if the request is signed.
(Trac875, git fe5e7003544e4e8f18efa7b466a65f336d8c8e4d)
(Trac #875, git fe5e7003544e4e8f18efa7b466a65f336d8c8e4d)
244. [func] stephen
244. [func] stephen
In unit tests, allow the choice of whether unhandled exceptions are
caught in the unit test program (and details printed) or allowed to
propagate to the default exception handler. See the bind10-dev thread
......@@ -129,7 +137,7 @@
243. [func]* feng
Add optional hmac algorithm SHA224/384/812.
(Trac#782, git 77d792c9d7c1a3f95d3e6a8b721ac79002cd7db1)
(Trac #782, git 77d792c9d7c1a3f95d3e6a8b721ac79002cd7db1)
bind10-devel-20110519 released on May 19, 2011
......@@ -176,7 +184,7 @@ bind10-devel-20110519 released on May 19, 2011
stats module and stats-httpd module, and maybe with other
statistical modules in future. "stats.spec" has own configuration
and commands of stats module, if it requires.
(Trac#719, git a234b20dc6617392deb8a1e00eb0eed0ff353c0a)
(Trac #719, git a234b20dc6617392deb8a1e00eb0eed0ff353c0a)
236. [func] jelte
C++ client side of configuration now uses BIND10 logging system.
......@@ -219,13 +227,13 @@ bind10-devel-20110519 released on May 19, 2011
instead of '%s,%d', which allows us to cope better with
mismatched placeholders and allows reordering of them in
case of translation.
(Trac901, git 4903410e45670b30d7283f5d69dc28c2069237d6)
(Trac #901, git 4903410e45670b30d7283f5d69dc28c2069237d6)
230. [bug] naokikambe
Removed too repeated verbose messages in two cases of:
- when auth sends statistics data to stats
- when stats receives statistics data from other modules
(Trac#620, git 0ecb807011196eac01f281d40bc7c9d44565b364)
(Trac #620, git 0ecb807011196eac01f281d40bc7c9d44565b364)
229. [doc] jreed
Add manual page for b10-host.
......
......@@ -5,6 +5,23 @@
<!ENTITY % version SYSTEM "version.ent">
%version;
]>
<!--
- Copyright (C) 2010-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.
-->
<book>
<?xml-stylesheet href="bind10-guide.css" type="text/css"?>
......
......@@ -188,7 +188,7 @@ accepting queries.
The authoritative server has encountered a fatal error and is terminating. The
reason for the failure is included in the message.
% AUTH_SERVER_STARTED server stated
% AUTH_SERVER_STARTED server started
Initialization of the authoritative server has completed successfully
and it is entering the main loop, waiting for queries to arrive.
......
......@@ -3,6 +3,7 @@ SUBDIRS = . tests
pkglibexecdir = $(libexecdir)/@PACKAGE@
pkglibexec_SCRIPTS = b10-cmdctl
pyexec_DATA = cmdctl_messages.py
b10_cmdctldir = $(pkgdatadir)
......@@ -18,10 +19,10 @@ b10_cmdctl_DATA += cmdctl.spec
EXTRA_DIST = $(CMDCTL_CONFIGURATIONS)
CLEANFILES= b10-cmdctl cmdctl.pyc cmdctl.spec
CLEANFILES= b10-cmdctl cmdctl.pyc cmdctl.spec cmdctl_messages.py cmdctl_messages.pyc
man_MANS = b10-cmdctl.8
EXTRA_DIST += $(man_MANS) b10-cmdctl.xml
EXTRA_DIST += $(man_MANS) b10-cmdctl.xml cmdctl_messages.mes
if ENABLE_MAN
......@@ -33,8 +34,11 @@ endif
cmdctl.spec: cmdctl.spec.pre
$(SED) -e "s|@@SYSCONFDIR@@|$(sysconfdir)|" cmdctl.spec.pre >$@
cmdctl_messages.py: cmdctl_messages.mes
$(top_builddir)/src/lib/log/compiler/message -p $(top_srcdir)/src/bin/cmdctl/cmdctl_messages.mes
# this is done here since configure.ac AC_OUTPUT doesn't expand exec_prefix
b10-cmdctl: cmdctl.py
b10-cmdctl: cmdctl.py cmdctl_messages.py
$(SED) "s|@@PYTHONPATH@@|@pyexecdir@|" cmdctl.py >$@
chmod a+x $@
......
......@@ -47,6 +47,18 @@ import isc.net.parse
from optparse import OptionParser, OptionValueError
from hashlib import sha1
from isc.util import socketserver_mixin
from cmdctl_messages import *
# TODO: these debug-levels are hard-coded here; we are planning on
# creating a general set of debug levels, see ticket #1074. When done,
# we should remove these values and use the general ones in the
# logger.debug calls
# Debug level for communication with BIND10
DBG_CMDCTL_MESSAGING = 30
isc.log.init("b10-cmdctl")
logger = isc.log.Logger("cmdctl")
try:
import threading
......@@ -173,7 +185,8 @@ class SecureHTTPRequestHandler(http.server.BaseHTTPRequestHandler):
if not user_name:
return False, ["need user name"]
if not self.server.get_user_info(user_name):
return False, ["user doesn't exist"]
logger.info(CMDCTL_NO_SUCH_USER, user_name)
return False, ["username or password error"]
user_pwd = user_info.get('password')
if not user_pwd:
......@@ -181,7 +194,8 @@ class SecureHTTPRequestHandler(http.server.BaseHTTPRequestHandler):
local_info = self.server.get_user_info(user_name)
pwd_hashval = sha1((user_pwd + local_info[1]).encode())
if pwd_hashval.hexdigest() != local_info[0]:
return False, ["password doesn't match"]
logger.info(CMDCTL_BAD_PASSWORD, user_name)
return False, ["username or password error"]
return True, None
......@@ -238,7 +252,8 @@ class CommandControl():
self._cc = isc.cc.Session()
self._module_cc = isc.config.ModuleCCSession(SPECFILE_LOCATION,
self.config_handler,
self.command_handler)
self.command_handler,
None, True)
self._module_name = self._module_cc.get_module_spec().get_module_name()
self._cmdctl_config_data = self._module_cc.get_full_config()
self._module_cc.start()
......@@ -281,7 +296,7 @@ class CommandControl():
errstr = 'unknown config item: ' + key
if errstr != None:
self.log_info('Fail to apply config data, ' + errstr)
logger.error(CMDCTL_BAD_CONFIG_DATA, errstr);
return ccsession.create_answer(1, errstr)
return ccsession.create_answer(0)
......@@ -387,8 +402,8 @@ class CommandControl():
'''Send the command from bindctl to proper module. '''
errstr = 'unknown error'
answer = None
if self._verbose:
self.log_info("Begin send command '%s' to module '%s'" %(command_name, module_name))
logger.debug(DBG_CMDCTL_MESSAGING, CMDCTL_SEND_COMMAND,
command_name, module_name)
if module_name == self._module_name:
# Process the command sent to cmdctl directly.
......@@ -396,15 +411,14 @@ class CommandControl():
else:
msg = ccsession.create_command(command_name, params)
seq = self._cc.group_sendmsg(msg, module_name)
logger.debug(DBG_CMDCTL_MESSAGING, CMDCTL_COMMAND_SENT,
command_name, module_name)
#TODO, it may be blocked, msqg need to add a new interface waiting in timeout.
try:
answer, env = self._cc.group_recvmsg(False, seq)
except isc.cc.session.SessionTimeout:
errstr = "Module '%s' not responding" % module_name
if self._verbose:
self.log_info("Finish send command '%s' to module '%s'" % (command_name, module_name))
if answer:
try:
rcode, arg = ccsession.parse_answer(answer)
......@@ -415,16 +429,13 @@ class CommandControl():
else:
return rcode, {}
else:
# TODO: exception
errstr = str(answer['result'][1])
except ccsession.ModuleCCSessionError as mcse:
errstr = str("Error in ccsession answer:") + str(mcse)
self.log_info(errstr)
logger.error(CMDCTL_COMMAND_ERROR, command_name, module_name, errstr)
return 1, {'error': errstr}
def log_info(self, msg):
sys.stdout.write("[b10-cmdctl] %s\n" % str(msg))
def get_cmdctl_config_data(self):
''' If running in source code tree, use keyfile, certificate
and user accounts file in source code. '''
......@@ -481,14 +492,15 @@ class SecureHTTPServer(socketserver_mixin.NoPollMixIn,
for row in reader:
self._user_infos[row[0]] = [row[1], row[2]]
except (IOError, IndexError) as e:
self.log_info("Fail to read user database, %s" % e)
logger.error(CMDCTL_USER_DATABASE_READ_ERROR,
accounts_file, e)
finally:
if csvfile:
csvfile.close()
self._accounts_file = accounts_file
if len(self._user_infos) == 0:
self.log_info("Fail to get user information, will deny any user")
logger.error(CMDCTL_NO_USER_ENTRIES_READ)
def get_user_info(self, username):
'''Get user's salt and hashed string. If the user
......@@ -520,7 +532,7 @@ class SecureHTTPServer(socketserver_mixin.NoPollMixIn,
ssl_version = ssl.PROTOCOL_SSLv23)
return ssl_sock
except (ssl.SSLError, CmdctlException) as err :
self.log_info("Deny client's connection because %s" % str(err))
logger.info(CMDCTL_SSL_SETUP_FAILURE_USER_DENIED, err)
self.close_request(sock)
# raise socket error to finish the request
raise socket.error
......@@ -547,9 +559,6 @@ class SecureHTTPServer(socketserver_mixin.NoPollMixIn,
def send_command_to_module(self, module_name, command_name, params):
return self.cmdctl.send_command_with_check(module_name, command_name, params)
def log_info(self, msg):
sys.stdout.write("[b10-cmdctl] %s\n" % str(msg))
httpd = None
def signal_handler(signal, frame):
......@@ -607,15 +616,13 @@ if __name__ == '__main__':
run(options.addr, options.port, options.idle_timeout, options.verbose)
result = 0
except isc.cc.SessionError as err:
sys.stderr.write("[b10-cmdctl] Error creating b10-cmdctl, "
"is the command channel daemon running?\n")
logger.fatal(CMDCTL_CC_SESSION_ERROR, err)
except isc.cc.SessionTimeout:
sys.stderr.write("[b10-cmdctl] Error creating b10-cmdctl, "
"is the configuration manager running?\n")
logger.fatal(CMDCTL_CC_SESSION_TIMEOUT)
except KeyboardInterrupt:
sys.stderr.write("[b10-cmdctl] exit from Cmdctl\n")
logger.info(CMDCTL_STOPPED_BY_KEYBOARD)
except CmdctlException as err:
sys.stderr.write("[b10-cmdctl] " + str(err) + "\n")
logger.fatal(CMDCTL_UNCAUGHT_EXCEPTION, err);
if httpd:
httpd.shutdown()
......
# 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.
# No namespace declaration - these constants go in the global namespace
# of the cmdctl_messages python module.
% CMDCTL_BAD_CONFIG_DATA error in config data: %1
There was an error reading the updated configuration data. The specific
error is printed.
% CMDCTL_BAD_PASSWORD bad password for user: %1
A login attempt was made to b10-cmdctl, but the password was wrong.
Users can be managed with the tool b10-cmdctl-usermgr.
% CMDCTL_CC_SESSION_ERROR error reading from cc channel: %1
There was a problem reading from the command and control channel. The
most likely cause is that the message bus daemon is not running.
% CMDCTL_CC_SESSION_TIMEOUT timeout on cc channel
A timeout occurred when waiting for essential data from the cc session.
This usually occurs when b10-cfgmgr is not running or not responding.
Since we are waiting for essential information, this is a fatal error,
and the cmdctl daemon will now shut down.
% CMDCTL_COMMAND_ERROR error in command %1 to module %2: %3
An error was encountered sending the given command to the given module.
Either there was a communication problem with the module, or the module
was not able to process the command, and sent back an error. The
specific error is printed in the message.
% CMDCTL_COMMAND_SENT command '%1' to module '%2' was sent
This debug message indicates that the given command has been sent to
the given module.
% CMDCTL_NO_SUCH_USER username not found in user database: %1
A login attempt was made to b10-cmdctl, but the username was not known.
Users can be added with the tool b10-cmdctl-usermgr.
% CMDCTL_NO_USER_ENTRIES_READ failed to read user information, all users will be denied
The b10-cmdctl daemon was unable to find any user data in the user
database file. Either it was unable to read the file (in which case
this message follows a message CMDCTL_USER_DATABASE_READ_ERROR
containing a specific error), or the file was empty. Users can be added
with the tool b10-cmdctl-usermgr.
% CMDCTL_SEND_COMMAND sending command %1 to module %2
This debug message indicates that the given command is being sent to
the given module.
% CMDCTL_SSL_SETUP_FAILURE_USER_DENIED failed to create an SSL connection (user denied): %1
The user was denied because the SSL connection could not successfully
be set up. The specific error is given in the log message. Possible
causes may be that the ssl request itself was bad, or the local key or
certificate file could not be read.
% CMDCTL_STOPPED_BY_KEYBOARD keyboard interrupt, shutting down
There was a keyboard interrupt signal to stop the cmdctl daemon. The
daemon will now shut down.
% CMDCTL_UNCAUGHT_EXCEPTION uncaught exception: %1
The b10-cdmctl daemon encountered an uncaught exception and
will now shut down. This is indicative of a programming error and
should not happen under normal circumstances. The exception message
is printed.
% CMDCTL_USER_DATABASE_READ_ERROR failed to read user database file %1: %2
The b10-cmdctl daemon was unable to read the user database file. The
file may be unreadable for the daemon, or it may be corrupted. In the
latter case, it can be recreated with b10-cmdctl-usermgr. The specific
error is printed in the log message.
......@@ -173,7 +173,7 @@ class TestSecureHTTPRequestHandler(unittest.TestCase):
self.handler.server._user_infos['root'] = ['aa', 'aaa']
ret, msg = self.handler._check_user_name_and_pwd()
self.assertFalse(ret)
self.assertEqual(msg, ['password doesn\'t match'])
self.assertEqual(msg, ['username or password error'])
def test_check_user_name_and_pwd_2(self):
user_info = {'username':'root', 'password':'abc123'}
......@@ -214,7 +214,7 @@ class TestSecureHTTPRequestHandler(unittest.TestCase):
ret, msg = self.handler._check_user_name_and_pwd()
self.assertFalse(ret)
self.assertEqual(msg, ['user doesn\'t exist'])
self.assertEqual(msg, ['username or password error'])
def test_do_POST(self):
self.handler.headers = {}
......
......@@ -210,10 +210,14 @@ query in the form of <Source IP address>#<source port>.
% RESOLVER_QUERY_REJECTED query rejected: '%1/%2/%3' from %4
An informational message that indicates an incoming query is rejected
in terms of the query ACL. This results in a response with an RCODE of
REFUSED. See QUERYACCEPTED for the information given in the message.
REFUSED. The log message shows the query in the form of <query
name>/<query type>/<query class>, and the client that sends the
query in the form of <Source IP address>#<source port>.
% RESOLVER_QUERY_DROPPED query dropped: '%1/%2/%3' from %4
An informational message that indicates an incoming query is dropped
in terms of the query ACL. Unlike the QUERYREJECTED case, the server does
not return any response. See QUERYACCEPTED for the information given in
the message.
in terms of the query ACL. Unlike the RESOLVER_QUERY_REJECTED
case, the server does not return any response. The log message
shows the query in the form of <query name>/<query type>/<query
class>, and the client that sends the query in the form of <Source
IP address>#<source port>.
......@@ -81,7 +81,7 @@ public:
* or if it doesn't contain one of the accepted values.
*
* \param action The JSON representation of the action. It must be a string
* and contain one of "ACCEPT", "REJECT" or "DENY".
* and contain one of "ACCEPT", "REJECT" or "DROP.
* \note We could define different names or add aliases if needed.
*/
BasicAction defaultActionLoader(data::ConstElementPtr action);
......
......@@ -20,3 +20,10 @@ Some of the classes defined here--for example, IOSocket, IOEndpoint,
and IOAddress--are to be used by BIND 10 modules as wrappers around
ASIO-specific classes.
Logging
-------
At this point, nothing is logged by this low-level library. We may
revisit that in the future, if we find suitable messages to log, but
right now there are also no loggers initialized or called.
......@@ -447,7 +447,9 @@ from_stringstream_map(std::istream &in, const std::string& file, int& line,
ElementPtr map = Element::createMap();
skip_chars(in, " \t\n", line, pos);
char c = in.peek();
if (c == '}') {
if (c == EOF) {
throwJSONError(std::string("Unterminated map, <string> or } expected"), file, line, pos);
} else if (c == '}') {
// empty map, skip closing curly
c = in.get();
} else {
......
......@@ -396,9 +396,24 @@ TEST(Element, to_and_from_wire) {
EXPECT_EQ("1", Element::fromWire(ss, 1)->str());
// Some malformed JSON input
EXPECT_THROW(Element::fromJSON("{ "), isc::data::JSONError);
EXPECT_THROW(Element::fromJSON("{ \"a\" "), isc::data::JSONError);
EXPECT_THROW(Element::fromJSON("{ \"a\": "), isc::data::JSONError);
EXPECT_THROW(Element::fromJSON("{ \"a\": \"b\""), isc::data::JSONError);
EXPECT_THROW(Element::fromJSON("{ \"a\": {"), isc::data::JSONError);
EXPECT_THROW(Element::fromJSON("{ \"a\": {}"), isc::data::JSONError);
EXPECT_THROW(Element::fromJSON("{ \"a\": []"), isc::data::JSONError);
EXPECT_THROW(Element::fromJSON("{ \"a\": [ }"), isc::data::JSONError);
EXPECT_THROW(Element::fromJSON("{\":"), isc::data::JSONError);
EXPECT_THROW(Element::fromJSON("]"), isc::data::JSONError);
EXPECT_THROW(Element::fromJSON("[ 1, 2, }"), isc::data::JSONError);
EXPECT_THROW(Element::fromJSON("[ 1, 2, {}"), isc::data::JSONError);
EXPECT_THROW(Element::fromJSON("[ 1, 2, { ]"), isc::data::JSONError);
EXPECT_THROW(Element::fromJSON("[ "), isc::data::JSONError);
EXPECT_THROW(Element::fromJSON("{{}}"), isc::data::JSONError);
EXPECT_THROW(Element::fromJSON("{[]}"), isc::data::JSONError);
EXPECT_THROW(Element::fromJSON("{ \"a\", \"b\" }"), isc::data::JSONError);
EXPECT_THROW(Element::fromJSON("[ \"a\": \"b\" ]"), isc::data::JSONError);
}
ConstElementPtr
......
......@@ -945,7 +945,7 @@ tryWildcard(Query& q, QueryTaskPtr task, ZoneInfo& zoneinfo, bool& found) {
void
DataSrc::doQuery(Query& q) {
LOG_DEBUG(logger, DBG_TRACE_BASIC, DATASRC_QUERY_PROCESS).arg(q.qname()).
arg(q.qclass());
arg(q.qtype()).arg(q.qclass());
Message& m = q.message();
vector<RRsetPtr> additional;
......
......@@ -225,10 +225,13 @@ struct MemoryZone::MemoryZoneImpl {
*/
// Implementation of MemoryZone::add
result::Result add(const ConstRRsetPtr& rrset, DomainTree* domains) {
// Sanitize input. This will cause an exception to be thrown
// if the input RRset is empty.
addValidation(rrset);
// OK, can add the RRset.
LOG_DEBUG(logger, DBG_TRACE_DATA, DATASRC_MEM_ADD_RRSET).
arg(rrset->getName()).arg(rrset->getType()).arg(origin_);
// Sanitize input
addValidation(rrset);
// Add wildcards possibly contained in the owner name to the domain
// tree.
......
......@@ -163,6 +163,8 @@ public:
}
/// \brief String version of arg.
///
/// \param arg The text to place into the placeholder.
Formatter& arg(const std::string& arg) {
if (logger_) {
// Note that this method does a replacement and returns the
......@@ -179,7 +181,6 @@ public:
}
return (*this);
}
};
}
......
......@@ -35,7 +35,7 @@ def from_wire(data):
Raises an AttributeError if the given object has no decode()
method (which should return a string).
'''
return json.loads(data.decode('utf8'))
return json.loads(data.decode('utf8'), strict=False)
if __name__ == "__main__":
import doctest
......
......@@ -93,6 +93,19 @@ class Session:
self._socket.send(msg)
def recvmsg(self, nonblock = True, seq = None):
"""Reads a message. If nonblock is true, and there is no
message to read, it returns (None, None).
If seq is not None, it should be a value as returned by
group_sendmsg(), in which case only the response to
that message is returned, and others will be queued until
the next call to this method.
If seq is None, only messages that are *not* responses
will be returned, and responses will be queued.
The queue is checked for relevant messages before data
is read from the socket.
Raises a SessionError if there is a JSON decode problem in
the message that is read, or if the session has been closed
prior to the call of recvmsg()"""
with self._lock:
if len(self._queue) > 0:
i = 0;
......@@ -109,16 +122,22 @@ class Session:
if data and len(data) > 2:
header_length = struct.unpack('>H', data[0:2])[0]
data_length = len(data) - 2 - header_length
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"]):
return env, msg
try:
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"]):
return env, msg
else: