Commit 901c9eed authored by JINMEI Tatuya's avatar JINMEI Tatuya
Browse files

Revert "maintenance commit"

This reverts commit a669db43.

The reverted commit was introduced due to misoperation possibly with
git-new-workdir, and actually reverted previous changes made on master.
By reverting it we now recover these lost changes.
parent a7724f03
......@@ -57,11 +57,10 @@ using namespace asiolink;
namespace {
static bool verbose_mode = false;
bool verbose_mode = false;
// Default port current 5300 for testing purposes
static const string PROGRAM = "Auth";
static const char* DNSPORT = "5300";
const char* DNSPORT = "5300";
// Note: this value must be greater than 0.
// TODO: make it configurable via command channel.
......@@ -70,9 +69,9 @@ const uint32_t STATISTICS_SEND_INTERVAL_SEC = 60;
/* need global var for config/command handlers.
* todo: turn this around, and put handlers in the authserver
* class itself? */
static AuthSrv *auth_server;
AuthSrv *auth_server;
static IOService io_service;
IOService io_service;
ConstElementPtr
my_config_handler(ConstElementPtr new_config) {
......
......@@ -217,16 +217,24 @@ class BindCmdInterpreter(Cmd):
for module_name in self.config_data.get_config_item_list():
self._prepare_module_commands(self.config_data.get_module_spec(module_name))
def _send_message(self, url, body):
headers = {"cookie" : self.session_id}
self.conn.request('GET', url, body, headers)
res = self.conn.getresponse()
return res.status, res.read()
def send_GET(self, url, body = None):
'''Send GET request to cmdctl, session id is send with the name
'cookie' in header.
'''
headers = {"cookie" : self.session_id}
self.conn.request('GET', url, body, headers)
res = self.conn.getresponse()
reply_msg = res.read()
status, reply_msg = self._send_message(url, body)
if status == http.client.UNAUTHORIZED:
if self.login_to_cmdctl():
# successful, so try send again
status, reply_msg = self._send_message(url, body)
if reply_msg:
return json.loads(reply_msg.decode())
return json.loads(reply_msg.decode())
else:
return {}
......@@ -622,9 +630,11 @@ class BindCmdInterpreter(Cmd):
if (len(cmd.params) != 0):
cmd_params = json.dumps(cmd.params)
print("send the command to cmd-ctrld")
reply = self.send_POST(url, cmd.params)
data = reply.read().decode()
print("received reply:", data)
# The reply is a string containing JSON data,
# parse it, then prettyprint
if data != "" and data != "{}":
print(json.dumps(json.loads(data), sort_keys=True, indent=4))
......@@ -260,6 +260,7 @@ public:
Message incoming(Message::PARSE);
InputBuffer ibuf(buffer->getData(), buffer->getLength());
incoming.fromWire(ibuf);
message->setRcode(incoming.getRcode());
for_each(incoming.beginSection(Message::SECTION_ANSWER),
incoming.endSection(Message::SECTION_ANSWER),
SectionInserter(message, Message::SECTION_ANSWER));
......
......@@ -215,36 +215,38 @@ class TestXfroutSession(unittest.TestCase):
rrset_soa = self.xfrsess._create_rrset_from_db_record(self.soa_record)
self.assertEqual(82, get_rrset_len(rrset_soa))
def test_zone_is_empty(self):
def test_zone_has_soa(self):
global sqlite3_ds
def mydb1(zone, file):
return True
sqlite3_ds.get_zone_soa = mydb1
self.assertEqual(self.xfrsess._zone_is_empty(""), False)
self.assertTrue(self.xfrsess._zone_has_soa(""))
def mydb2(zone, file):
return False
sqlite3_ds.get_zone_soa = mydb2
self.assertEqual(self.xfrsess._zone_is_empty(""), True)
self.assertFalse(self.xfrsess._zone_has_soa(""))
def test_zone_exist(self):
global sqlite3_ds
def zone_soa(zone, file):
def zone_exist(zone, file):
return zone
sqlite3_ds.get_zone_soa = zone_soa
self.assertEqual(self.xfrsess._zone_exist(True), True)
self.assertEqual(self.xfrsess._zone_exist(False), False)
sqlite3_ds.zone_exist = zone_exist
self.assertTrue(self.xfrsess._zone_exist(True))
self.assertFalse(self.xfrsess._zone_exist(False))
def test_check_xfrout_available(self):
def zone_exist(zone):
return zone
def zone_has_soa(zone):
return (not zone)
self.xfrsess._zone_exist = zone_exist
self.xfrsess._zone_is_empty = zone_exist
self.xfrsess._zone_has_soa = zone_has_soa
self.assertEqual(self.xfrsess._check_xfrout_available(False).to_text(), "NOTAUTH")
self.assertEqual(self.xfrsess._check_xfrout_available(True).to_text(), "SERVFAIL")
def zone_empty(zone):
return not zone
self.xfrsess._zone_is_empty = zone_empty
return zone
self.xfrsess._zone_has_soa = zone_empty
def false_func():
return False
self.xfrsess.server.increase_transfers_counter = false_func
......
......@@ -193,30 +193,41 @@ class XfroutSession(BaseRequestHandler):
self._send_message(sock_fd, msg)
def _zone_is_empty(self, zone):
def _zone_has_soa(self, zone):
'''Judge if the zone has an SOA record.'''
# In some sense, the SOA defines a zone.
# If the current name server has authority for the
# specific zone, we need to judge if the zone has an SOA record;
# if not, we consider the zone has incomplete data, so xfrout can't
# serve for it.
if sqlite3_ds.get_zone_soa(zone, self.server.get_db_file()):
return False
return True
def _zone_exist(self, zonename):
# Find zone in datasource, should this works? maybe should ask
# config manager.
soa = sqlite3_ds.get_zone_soa(zonename, self.server.get_db_file())
if soa:
return True
return False
def _zone_exist(self, zonename):
'''Judge if the zone is configured by config manager.'''
# Currently, if we find the zone in datasource successfully, we
# consider the zone is configured, and the current name server has
# authority for the specific zone.
# TODO: should get zone's configuration from cfgmgr or other place
# in future.
return sqlite3_ds.zone_exist(zonename, self.server.get_db_file())
def _check_xfrout_available(self, zone_name):
'''Check if xfr request can be responsed.
TODO, Get zone's configuration from cfgmgr or some other place
eg. check allow_transfer setting,
'''
# If the current name server does not have authority for the
# zone, xfrout can't serve for it, return rcode NOTAUTH.
if not self._zone_exist(zone_name):
return Rcode.NOTAUTH()
if self._zone_is_empty(zone_name):
# If we are an authoritative name server for the zone, but fail
# to find the zone's SOA record in datasource, xfrout can't
# provide zone transfer for it.
if not self._zone_has_soa(zone_name):
return Rcode.SERVFAIL()
#TODO, check allow_transfer
......
......@@ -25,25 +25,24 @@ RR_NAME_INDEX = 2
RR_TTL_INDEX = 4
RR_RDATA_INDEX = 7
#########################################################################
# define exceptions
#########################################################################
class Sqlite3DSError(Exception):
""" Define exceptions."""
pass
#########################################################################
# create: set up schema for a newly created zones/records database
#########################################################################
def create(cur):
"""Create new zone database"""
""" Set up schema for a newly created zones/records database.
Arguments:
cur - sqlite3 cursor.
"""
cur.execute("CREATE TABLE schema_version (version INTEGER NOT NULL)")
cur.execute("INSERT INTO schema_version VALUES (1)")
cur.execute("""CREATE TABLE zones (id INTEGER PRIMARY KEY,
cur.execute("""CREATE TABLE zones (id INTEGER PRIMARY KEY,
name STRING NOT NULL COLLATE NOCASE,
rdclass STRING NOT NULL COLLATE NOCASE DEFAULT 'IN',
rdclass STRING NOT NULL COLLATE NOCASE DEFAULT 'IN',
dnssec BOOLEAN NOT NULL DEFAULT 0)""")
cur.execute("CREATE INDEX zones_byname ON zones (name)")
cur.execute("""CREATE TABLE records (id INTEGER PRIMARY KEY,
cur.execute("""CREATE TABLE records (id INTEGER PRIMARY KEY,
zone_id INTEGER NOT NULL,
name STRING NOT NULL COLLATE NOCASE,
rname STRING NOT NULL COLLATE NOCASE,
......@@ -53,7 +52,7 @@ def create(cur):
rdata STRING NOT NULL)""")
cur.execute("CREATE INDEX records_byname ON records (name)")
cur.execute("CREATE INDEX records_byrname ON records (rname)")
cur.execute("""CREATE TABLE nsec3 (id INTEGER PRIMARY KEY,
cur.execute("""CREATE TABLE nsec3 (id INTEGER PRIMARY KEY,
zone_id INTEGER NOT NULL,
hash STRING NOT NULL COLLATE NOCASE,
owner STRING NOT NULL COLLATE NOCASE,
......@@ -62,17 +61,17 @@ def create(cur):
rdata STRING NOT NULL)""")
cur.execute("CREATE INDEX nsec3_byhash ON nsec3 (hash)")
#########################################################################
# open: open a database. if the database is not yet set up,
# call create to do so.
# input:
# dbfile - the filename for the sqlite3 database
# returns:
# sqlite3 connection, sqlite3 cursor
#########################################################################
def open(dbfile):
"""Open the database file. If necessary, set it up"""
try:
""" Open a database, if the database is not yet set up, call create
to do so. It may raise Sqlite3DSError if failed to open sqlite3
database file or find bad database schema version in the database.
Arguments:
dbfile - the filename for the sqlite3 database.
Return sqlite3 connection, sqlite3 cursor.
"""
try:
conn = sqlite3.connect(dbfile)
cur = conn.cursor()
except Exception as e:
......@@ -93,12 +92,15 @@ def open(dbfile):
return conn, cur
#########################################################################
# get_zone_datas
# a generator function producing an iterable set of
# the records in the zone with the given zone name.
#########################################################################
def get_zone_datas(zonename, dbfile):
""" A generator function producing an iterable set of
the records in the zone with the given zone name.
Arguments:
zonename - the zone's origin name.
dbfile - the filename for the sqlite3 database.
"""
conn, cur = open(dbfile)
zone_id = get_zoneid(zonename, cur)
......@@ -112,12 +114,14 @@ def get_zone_datas(zonename, dbfile):
conn.close()
#########################################################################
# get_zone_soa
# returns the soa record of the zone with the given zone name.
# If the zone doesn't exist, return None.
#########################################################################
def get_zone_soa(zonename, dbfile):
"""Return the soa record of the zone with the given zone name.
If the zone doesn't exist, return None.
Arguments:
zonename - the zone's origin name.
dbfile - the filename for the sqlite3 database.
"""
conn, cur = open(dbfile)
id = get_zoneid(zonename, cur)
cur.execute("SELECT * FROM records WHERE zone_id = ? and rdtype = ?", [id, 'SOA'])
......@@ -128,16 +132,20 @@ def get_zone_soa(zonename, dbfile):
return datas
#########################################################################
# get_zone_rrset
# returns the rrset of the zone with the given zone name, rrset name
# and given rd type.
# If the zone doesn't exist or rd type doesn't exist, return an empty list.
#########################################################################
def get_zone_rrset(zonename, rr_name, rdtype, dbfile):
"""Return the rrset of the zone with the given zone name, rrset
name and given RR type. If the zone doesn't exist or RR type
doesn't exist, return an empty list.
Arguments:
zonename - the zone's origin name.
rr_name - rr name.
rdtype - RR type.
dbfile - the filename for the sqlite3 database.
"""
conn, cur = open(dbfile)
id = get_zoneid(zonename, cur)
cur.execute("SELECT * FROM records WHERE name = ? and zone_id = ? and rdtype = ?",
cur.execute("SELECT * FROM records WHERE name = ? and zone_id = ? and rdtype = ?",
[rr_name, id, rdtype])
datas = cur.fetchall()
cur.close()
......@@ -145,12 +153,13 @@ def get_zone_rrset(zonename, rr_name, rdtype, dbfile):
return datas
#########################################################################
# get_zones_info:
# returns all the zones' information.
#########################################################################
def get_zones_info(db_file):
conn, cur = open(db_file)
def get_zones_info(dbfile):
""" Return all the zones' information in the database.
Arguments:
dbfile - the filename for the sqlite3 database.
"""
conn, cur = open(dbfile)
cur.execute("SELECT name, rdclass FROM zones")
info = cur.fetchone()
while info:
......@@ -160,44 +169,69 @@ def get_zones_info(db_file):
cur.close()
conn.close()
#########################################################################
# get_zoneid:
# returns the zone_id for a given zone name, or an empty
# string if the zone is not found
#########################################################################
def get_zoneid(zone, cur):
cur.execute("SELECT id FROM zones WHERE name = ?", [zone])
def get_zoneid(zonename, cur):
""" Get the zone_id for a given zone name.
Arguments:
zonename - the zone's origin name.
cur - sqlite3 cursor.
Return zone id for the given zone name, or an empty string if the
zone is not found.
"""
cur.execute("SELECT id FROM zones WHERE name = ?", [zonename])
row = cur.fetchone()
if row:
return row[0]
else:
return ''
#########################################################################
# reverse_name:
# reverse the labels of a DNS name. (for example,
# "bind10.isc.org." would become "org.isc.bind10.")
#########################################################################
def zone_exist(zonename, dbfile):
""" Search for the zone with the given zone name in databse. This
method may throw a Sqlite3DSError exception because its underlying
method open() can throw that exception.
Arguments:
zonename - the zone's origin name.
dbfile - the filename for the sqlite3 database.
Return True if the zone is found, otherwise False.
"""
conn, cur = open(dbfile)
zoneid = get_zoneid(zonename, cur)
cur.close()
conn.close()
if zoneid:
return True
return False
def reverse_name(name):
"""Reverse the labels of a domain name; for example,
given 'www.isc.org.', return 'org.isc.www.' This is needed
for DNSSEC sort order."""
given 'www.example.org.', return 'org.example.www.' This is needed
for DNSSEC sort order.
Arguments:
name - the DNS name will be reversed.
"""
new = name.split('.')
new.reverse()
if new[0] == '':
new.pop(0)
return '.'.join(new)+'.'
#########################################################################
# load:
# load a zone into the SQL database.
# input:
# dbfile: the sqlite3 database fileanme
# zone: the zone origin
# reader: a generator function producing an iterable set of
# name/ttl/class/rrtype/rdata-text tuples
#########################################################################
def load(dbfile, zone, reader):
""" Load a zone into the SQL database.
Arguments:
dbfile - the sqlite3 database filename
zone - the zone origin
reader - a generator function producing an iterable set of
name/ttl/class/rrtype/rdata-text tuples.
"""
# if the zone name doesn't contain the trailing dot, automatically add it.
if zone[-1] != '.':
zone += '.'
......
PYCOVERAGE_RUN = @PYCOVERAGE_RUN@
PYTESTS = master_test.py
PYTESTS = master_test.py sqlite3_ds_test.py
EXTRA_DIST = $(PYTESTS)
EXTRA_DIST += testdata/brokendb.sqlite3
EXTRA_DIST += testdata/example.com.sqlite3
# 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
for pytest in $(PYTESTS) ; do \
echo Running test: $$pytest ; \
env PYTHONPATH=$(abs_top_srcdir)/src/lib/python:$(abs_top_builddir)/src/lib/python:$(abs_top_builddir)/src/lib/python/isc/log \
TESTDATA_PATH=$(abs_srcdir)/testdata \
$(PYCOVERAGE_RUN) $(abs_srcdir)/$$pytest || exit ; \
done
# Copyright (C) 2011 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.
from isc.datasrc import sqlite3_ds
import os
import socket
import unittest
TESTDATA_PATH = os.environ['TESTDATA_PATH'] + os.sep
class TestSqlite3_ds(unittest.TestCase):
def test_zone_exist(self):
# The following file must be non existent and must be non
# "creatable"; the sqlite3 library will try to create a new
# DB file if it doesn't exist, so to test a failure case the
# create operation should also fail. The "nodir", a non
# existent directory, is inserted for this purpose.
nodir = "/nodir/notexist"
self.assertRaises(sqlite3_ds.Sqlite3DSError,
sqlite3_ds.zone_exist, "example.com", nodir)
# Open a broken database file
self.assertRaises(sqlite3_ds.Sqlite3DSError,
sqlite3_ds.zone_exist, "example.com",
TESTDATA_PATH + "brokendb.sqlite3")
self.assertTrue(sqlite3_ds.zone_exist("example.com.",
TESTDATA_PATH + "example.com.sqlite3"))
self.assertFalse(sqlite3_ds.zone_exist("example.org.",
TESTDATA_PATH + "example.com.sqlite3"))
if __name__ == '__main__':
unittest.main()
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment