Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
Adam Osuchowski
Kea
Commits
f1e9ef1f
Commit
f1e9ef1f
authored
Jan 04, 2013
by
JINMEI Tatuya
Browse files
[2437] supported python wrapper of checkZone().
parent
96e05eca
Changes
7
Hide whitespace changes
Inline
Side-by-side
src/lib/dns/python/Makefile.am
View file @
f1e9ef1f
...
...
@@ -27,6 +27,7 @@ libb10_pydnspp_la_SOURCES += edns_python.cc edns_python.h
libb10_pydnspp_la_SOURCES
+=
message_python.cc message_python.h
libb10_pydnspp_la_SOURCES
+=
rrset_collection_python.cc
libb10_pydnspp_la_SOURCES
+=
rrset_collection_python.h
libb10_pydnspp_la_SOURCES
+=
zone_checker_python.cc zone_checker_python.h
libb10_pydnspp_la_CPPFLAGS
=
$(AM_CPPFLAGS)
$(PYTHON_INCLUDES)
libb10_pydnspp_la_CXXFLAGS
=
$(AM_CXXFLAGS)
$(PYTHON_CXXFLAGS)
...
...
src/lib/dns/python/pydnspp.cc
View file @
f1e9ef1f
...
...
@@ -57,6 +57,9 @@
#include "tsig_python.h"
#include "tsig_rdata_python.h"
#include "tsigrecord_python.h"
#include "zone_checker_python.h"
#include "zone_checker_python_inc.cc"
using
namespace
isc
::
dns
;
using
namespace
isc
::
dns
::
python
;
...
...
@@ -729,6 +732,11 @@ initModulePart_TSIGRecord(PyObject* mod) {
return
(
true
);
}
PyMethodDef
methods
[]
=
{
{
"check_zone"
,
internal
::
pyCheckZone
,
METH_VARARGS
,
dns_checkZone_doc
},
{
NULL
,
NULL
,
0
,
NULL
}
};
PyModuleDef
pydnspp
=
{
{
PyObject_HEAD_INIT
(
NULL
)
NULL
,
0
,
NULL
},
"pydnspp"
,
...
...
@@ -738,13 +746,13 @@ PyModuleDef pydnspp = {
"and OutputBuffer for instance), and others may be necessary, but "
"were not up to now."
,
-
1
,
NULL
,
methods
,
NULL
,
NULL
,
NULL
,
NULL
};
}
}
// unnamed namespace
PyMODINIT_FUNC
PyInit_pydnspp
(
void
)
{
...
...
src/lib/dns/python/tests/Makefile.am
View file @
f1e9ef1f
...
...
@@ -19,6 +19,7 @@ PYTESTS += tsig_rdata_python_test.py
PYTESTS
+=
tsigerror_python_test.py
PYTESTS
+=
tsigkey_python_test.py
PYTESTS
+=
tsigrecord_python_test.py
PYTESTS
+=
zone_checker_python_test.py
EXTRA_DIST
=
$(PYTESTS)
EXTRA_DIST
+=
testutil.py
...
...
src/lib/dns/python/tests/zone_checker_python_test.py
0 → 100644
View file @
f1e9ef1f
# 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
unittest
import
sys
from
pydnspp
import
*
# A separate exception class raised from some tests to see if it's propagated.
class
FakeException
(
Exception
):
pass
class
ZoneCheckerTest
(
unittest
.
TestCase
):
def
__callback
(
self
,
reason
,
reasons
):
# Issue callback for check_zone(). It simply records the given reason
# string in the given list.
reasons
.
append
(
reason
)
def
test_check
(
self
):
errors
=
[]
warns
=
[]
# A successful case with no warning.
rrsets
=
RRsetCollection
(
b
'example.org. 0 SOA . . 0 0 0 0 0
\n
'
+
b
'example.org. 0 NS ns.example.org.
\n
'
+
b
'ns.example.org. 0 A 192.0.2.1
\n
'
,
Name
(
'example.org'
),
RRClass
.
IN
())
self
.
assertTrue
(
check_zone
(
Name
(
'example.org'
),
RRClass
.
IN
(),
rrsets
,
(
lambda
r
:
self
.
__callback
(
r
,
errors
),
lambda
r
:
self
.
__callback
(
r
,
warns
))))
self
.
assertEqual
([],
errors
)
self
.
assertEqual
([],
warns
)
# Check fails and one additional warning.
rrsets
=
RRsetCollection
(
b
'example.org. 0 NS ns.example.org.'
,
Name
(
'example.org'
),
RRClass
.
IN
())
self
.
assertFalse
(
check_zone
(
Name
(
'example.org'
),
RRClass
.
IN
(),
rrsets
,
(
lambda
r
:
self
.
__callback
(
r
,
errors
),
lambda
r
:
self
.
__callback
(
r
,
warns
))))
self
.
assertEqual
([
'zone example.org/IN: has 0 SOA records'
],
errors
)
self
.
assertEqual
([
'zone example.org/IN: NS has no address records '
+
'(A or AAAA)'
],
warns
)
# Same RRset collection, suppressing callbacks
errors
=
[]
warns
=
[]
self
.
assertFalse
(
check_zone
(
Name
(
'example.org'
),
RRClass
.
IN
(),
rrsets
,
(
None
,
None
)))
self
.
assertEqual
([],
errors
)
self
.
assertEqual
([],
warns
)
def
test_check_badarg
(
self
):
rrsets
=
RRsetCollection
()
# Bad types
self
.
assertRaises
(
TypeError
,
check_zone
,
1
,
RRClass
.
IN
(),
rrsets
,
(
None
,
None
))
self
.
assertRaises
(
TypeError
,
check_zone
,
Name
(
'example'
),
1
,
rrsets
,
(
None
,
None
))
self
.
assertRaises
(
TypeError
,
check_zone
,
Name
(
'example'
),
RRClass
.
IN
(),
1
,
(
None
,
None
))
self
.
assertRaises
(
TypeError
,
check_zone
,
Name
(
'example'
),
RRClass
.
IN
(),
rrsets
,
1
)
# Bad callbacks
self
.
assertRaises
(
TypeError
,
check_zone
,
Name
(
'example'
),
RRClass
.
IN
(),
rrsets
,
(
None
,
None
,
None
))
self
.
assertRaises
(
TypeError
,
check_zone
,
Name
(
'example'
),
RRClass
.
IN
(),
rrsets
,
(
1
,
None
))
self
.
assertRaises
(
TypeError
,
check_zone
,
Name
(
'example'
),
RRClass
.
IN
(),
rrsets
,
(
None
,
1
))
# Extra/missing args
self
.
assertRaises
(
TypeError
,
check_zone
,
Name
(
'example'
),
RRClass
.
IN
(),
rrsets
,
(
None
,
None
),
1
)
self
.
assertRaises
(
TypeError
,
check_zone
,
Name
(
'example'
),
RRClass
.
IN
(),
rrsets
)
check_zone
(
Name
(
'example'
),
RRClass
.
IN
(),
rrsets
,
(
None
,
None
))
def
test_check_callback_fail
(
self
):
# Let the call raise a Python exception. It should be propagated to
# the top level.
def
__bad_callback
(
reason
):
raise
FakeException
(
'error in callback'
)
# Using an empty collection, triggering an error callback.
self
.
assertRaises
(
FakeException
,
check_zone
,
Name
(
'example.org'
),
RRClass
.
IN
(),
RRsetCollection
(),
(
__bad_callback
,
None
))
# An unusual case: the callback is expected to return None, but if it
# returns an actual object it shouldn't cause leak inside the callback.
class
RefChecker
:
pass
def
__callback
(
reason
,
checker
):
return
checker
ref_checker
=
RefChecker
()
orig_refcnt
=
sys
.
getrefcount
(
ref_checker
)
check_zone
(
Name
(
'example.org'
),
RRClass
.
IN
(),
RRsetCollection
(),
(
lambda
r
:
__callback
(
r
,
ref_checker
),
None
))
self
.
assertEqual
(
orig_refcnt
,
sys
.
getrefcount
(
ref_checker
))
def
test_check_custom_collection
(
self
):
# Test if check_zone() works with pure-Python RRsetCollection.
class
FakeRRsetCollection
(
RRsetCollectionBase
):
# This is the Python-only collection class. Its find() makes
# the check pass by default, by returning hardcoded RRsets.
# If raise_on_find is set to True, find() raises an exception.
# If find_result is set to something other than False, find()
# returns that specified value.
def
__init__
(
self
,
raise_on_find
=
False
,
find_result
=
False
):
self
.
__raise_on_find
=
raise_on_find
self
.
__find_result
=
find_result
def
find
(
self
,
name
,
rrclass
,
rrtype
):
if
self
.
__raise_on_find
:
raise
FakeException
(
'find error'
)
if
self
.
__find_result
is
not
False
:
return
self
.
__find_result
if
rrtype
==
RRType
.
SOA
():
soa
=
RRset
(
Name
(
'example'
),
RRClass
.
IN
(),
rrtype
,
RRTTL
(
0
))
soa
.
add_rdata
(
Rdata
(
RRType
.
SOA
(),
RRClass
.
IN
(),
'. . 0 0 0 0 0'
))
return
soa
if
rrtype
==
RRType
.
NS
():
ns
=
RRset
(
Name
(
'example'
),
RRClass
.
IN
(),
rrtype
,
RRTTL
(
0
))
ns
.
add_rdata
(
Rdata
(
RRType
.
NS
(),
RRClass
.
IN
(),
'example.org'
))
return
ns
return
None
# A successful case. Just checking it works in that case.
rrsets
=
FakeRRsetCollection
()
self
.
assertTrue
(
check_zone
(
Name
(
'example'
),
RRClass
.
IN
(),
rrsets
,
(
None
,
None
)))
# Likewise, normal case but zone check fails.
rrsets
=
FakeRRsetCollection
(
False
,
None
)
self
.
assertFalse
(
check_zone
(
Name
(
'example'
),
RRClass
.
IN
(),
rrsets
,
(
None
,
None
)))
# Our find() returns a bad type of result.
rrsets
=
FakeRRsetCollection
(
False
,
1
)
self
.
assertRaises
(
TypeError
,
check_zone
,
Name
(
'example'
),
RRClass
.
IN
(),
rrsets
,
(
None
,
None
))
# Our find() returns an empty SOA RRset. C++ zone checker code
# throws, which results in IscException.
rrsets
=
FakeRRsetCollection
(
False
,
RRset
(
Name
(
'example'
),
RRClass
.
IN
(),
RRType
.
SOA
(),
RRTTL
(
0
)))
self
.
assertRaises
(
IscException
,
check_zone
,
Name
(
'example'
),
RRClass
.
IN
(),
rrsets
,
(
None
,
None
))
# Our find() raises an exception. That exception is propagated to
# the top level.
rrsets
=
FakeRRsetCollection
(
True
)
self
.
assertRaises
(
FakeException
,
check_zone
,
Name
(
'example'
),
RRClass
.
IN
(),
rrsets
,
(
None
,
None
))
if
__name__
==
'__main__'
:
unittest
.
main
()
src/lib/dns/python/zone_checker_python.cc
0 → 100644
View file @
f1e9ef1f
// 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.
// Enable this if you use s# variants with PyArg_ParseTuple(), see
// http://docs.python.org/py3k/c-api/arg.html#strings-and-buffers
#define PY_SSIZE_T_CLEAN
// Python.h needs to be placed at the head of the program file, see:
// http://docs.python.org/py3k/extending/extending.html#a-simple-example
#include <Python.h>
#include <util/python/pycppwrapper_util.h>
#include <dns/python/name_python.h>
#include <dns/python/rrclass_python.h>
#include <dns/python/rrtype_python.h>
#include <dns/python/rrset_python.h>
#include <dns/python/rrset_collection_python.h>
#include <dns/python/zone_checker_python.h>
#include <dns/python/pydnspp_common.h>
#include <exceptions/exceptions.h>
#include <dns/name.h>
#include <dns/rrclass.h>
#include <dns/rrtype.h>
#include <dns/rrset.h>
#include <dns/rrset_collection_base.h>
#include <dns/zone_checker.h>
#include <boost/bind.hpp>
#include <cstring>
#include <string>
#include <stdexcept>
using
std
::
string
;
using
isc
::
util
::
python
::
PyObjectContainer
;
using
namespace
isc
::
dns
;
namespace
{
// This is a template for a common pattern of type mismatch error handling,
// provided to save typing and repeating the mostly identical patterns.
PyObject
*
setTypeError
(
PyObject
*
pobj
,
const
char
*
var_name
,
const
char
*
type_name
)
{
PyErr_Format
(
PyExc_TypeError
,
"%s must be a %s, not %.200s"
,
var_name
,
type_name
,
pobj
->
ob_type
->
tp_name
);
return
(
NULL
);
}
}
namespace
isc
{
namespace
dns
{
namespace
python
{
namespace
internal
{
namespace
{
// This is used to abort check_zone() and go back to the top level.
// We use a separate exception so it won't be caught in the middle.
class
InternalException
:
public
std
::
exception
{
};
// This is a "wrapper" RRsetCollection subclass. It's constructed with
// a Python RRsetCollection object, and its find() calls the Python version
// of RRsetCollection.find(). This way, the check_zone() wrapper will work
// for pure-Python RRsetCollection classes, too.
class
PyRRsetCollection
:
public
RRsetCollectionBase
{
public:
PyRRsetCollection
(
PyObject
*
po_rrsets
)
:
po_rrsets_
(
po_rrsets
)
{}
virtual
ConstRRsetPtr
find
(
const
Name
&
name
,
const
RRClass
&
rrclass
,
const
RRType
&
rrtype
)
const
{
try
{
// Convert C++ args to Python objects, and builds argument tuple
// to the Python method. This should basically succeed.
PyObjectContainer
poc_name
(
createNameObject
(
name
));
PyObjectContainer
poc_rrclass
(
createRRClassObject
(
rrclass
));
PyObjectContainer
poc_rrtype
(
createRRTypeObject
(
rrtype
));
PyObjectContainer
poc_args
(
Py_BuildValue
(
"(OOOO)"
,
po_rrsets_
,
poc_name
.
get
(),
poc_rrclass
.
get
(),
poc_rrtype
.
get
()));
// Call the Python method.
// PyObject_CallMethod is dirty and requires mutable C-string for
// method name and arguments. While it's unlikely for these to
// be modified, we err on the side of caution and make copies.
char
method_name
[
sizeof
(
"find"
)];
char
method_args
[
sizeof
(
"(OOO)"
)];
std
::
strcpy
(
method_name
,
"find"
);
std
::
strcpy
(
method_args
,
"(OOO)"
);
PyObjectContainer
poc_result
(
PyObject_CallMethod
(
po_rrsets_
,
method_name
,
method_args
,
poc_name
.
get
(),
poc_rrclass
.
get
(),
poc_rrtype
.
get
()));
PyObject
*
const
po_result
=
poc_result
.
get
();
if
(
po_result
==
Py_None
)
{
return
(
ConstRRsetPtr
());
}
else
if
(
PyRRset_Check
(
po_result
))
{
return
(
PyRRset_ToRRsetPtr
(
po_result
));
}
else
{
PyErr_SetString
(
PyExc_TypeError
,
"invalid type for "
"RRsetCollection.find(): must be None "
"or RRset"
);
throw
InternalException
();
}
}
catch
(
const
isc
::
util
::
python
::
PyCPPWrapperException
&
ex
)
{
// This normally means the method call fails. Propagate the
// already-set Python error to the top level. Other C++ exceptions
// are really unexpected, so we also (implicitly) propagate it
// to the top level and recognize it as "unexpected failure".
throw
InternalException
();
}
}
virtual
IterPtr
getBeginning
()
{
isc_throw
(
NotImplemented
,
"iterator support is not yet available"
);
}
virtual
IterPtr
getEnd
()
{
isc_throw
(
NotImplemented
,
"iterator support is not yet available"
);
}
private:
PyObject
*
const
po_rrsets_
;
};
void
callback
(
const
string
&
reason
,
PyObject
*
obj
)
{
PyObjectContainer
poc_args
(
Py_BuildValue
(
"(s#)"
,
reason
.
c_str
(),
reason
.
size
()));
PyObject
*
po_result
=
PyObject_CallObject
(
obj
,
poc_args
.
get
());
if
(
po_result
==
NULL
)
{
throw
InternalException
();
}
Py_DECREF
(
po_result
);
}
ZoneCheckerCallbacks
::
IssueCallback
PyCallable_ToCallback
(
PyObject
*
obj
)
{
if
(
obj
==
Py_None
)
{
return
(
NULL
);
}
return
(
boost
::
bind
(
callback
,
_1
,
obj
));
}
}
PyObject
*
pyCheckZone
(
PyObject
*
,
PyObject
*
args
)
{
try
{
PyObject
*
po_name
;
PyObject
*
po_rrclass
;
PyObject
*
po_rrsets
;
PyObject
*
po_error
;
PyObject
*
po_warn
;
if
(
PyArg_ParseTuple
(
args
,
"OOO(OO)"
,
&
po_name
,
&
po_rrclass
,
&
po_rrsets
,
&
po_error
,
&
po_warn
))
{
if
(
!
PyName_Check
(
po_name
))
{
return
(
setTypeError
(
po_name
,
"zone_name"
,
"Name"
));
}
if
(
!
PyRRClass_Check
(
po_rrclass
))
{
return
(
setTypeError
(
po_rrclass
,
"zone_rrclass"
,
"RRClass"
));
}
if
(
!
PyObject_TypeCheck
(
po_rrsets
,
&
rrset_collection_base_type
))
{
return
(
setTypeError
(
po_rrsets
,
"zone_rrsets"
,
"RRsetCollectionBase"
));
}
if
(
po_error
!=
Py_None
&&
PyCallable_Check
(
po_error
)
==
0
)
{
return
(
setTypeError
(
po_error
,
"error"
,
"callable or None"
));
}
if
(
po_warn
!=
Py_None
&&
PyCallable_Check
(
po_warn
)
==
0
)
{
return
(
setTypeError
(
po_warn
,
"warn"
,
"callable or None"
));
}
PyRRsetCollection
py_rrsets
(
po_rrsets
);
if
(
checkZone
(
PyName_ToName
(
po_name
),
PyRRClass_ToRRClass
(
po_rrclass
),
py_rrsets
,
ZoneCheckerCallbacks
(
PyCallable_ToCallback
(
po_error
),
PyCallable_ToCallback
(
po_warn
))))
{
Py_RETURN_TRUE
;
}
else
{
Py_RETURN_FALSE
;
}
}
}
catch
(
const
InternalException
&
ex
)
{
// Normally, error string should have been set already. For some
// rare cases such as memory allocation failure, we set the last-resort
// error string.
if
(
PyErr_Occurred
()
==
NULL
)
{
PyErr_SetString
(
PyExc_SystemError
,
"Unexpected failure in check_zone()"
);
}
return
(
NULL
);
}
catch
(
const
std
::
exception
&
ex
)
{
const
string
ex_what
=
"Unexpected failure in check_zone(): "
+
string
(
ex
.
what
());
PyErr_SetString
(
po_IscException
,
ex_what
.
c_str
());
return
(
NULL
);
}
catch
(...)
{
PyErr_SetString
(
PyExc_SystemError
,
"Unexpected C++ exception"
);
return
(
NULL
);
}
return
(
NULL
);
}
}
// namespace internal
}
// namespace python
}
// namespace dns
}
// namespace isc
src/lib/dns/python/zone_checker_python.h
0 → 100644
View file @
f1e9ef1f
// 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 PYTHON_ZONE_CHECKER_H
#define PYTHON_ZONE_CHECKER_H 1
#include <Python.h>
namespace
isc
{
namespace
dns
{
namespace
python
{
namespace
internal
{
PyObject
*
pyCheckZone
(
PyObject
*
self
,
PyObject
*
args
);
}
// namespace python
}
// namespace python
}
// namespace dns
}
// namespace isc
#endif // PYTHON_ZONE_CHECKER_H
// Local Variables:
// mode: c++
// End:
src/lib/dns/python/zone_checker_python_inc.cc
0 → 100644
View file @
f1e9ef1f
namespace
{
// Modifications
// - callbacks => (error, warn)
// - recover paragraph before itemization (it's a bug of convert script)
// - correct broken format for nested items (another bug of script)
// - true/false => True/False
// - removed Exception section (for simplicity)
const
char
*
const
dns_checkZone_doc
=
"\
check_zone(zone_name, zone_class, zone_rrsets, (error, warn)) -> bool
\n
\
\n
\
Perform basic integrity checks on zone RRsets.
\n
\
\n
\
This function performs some lightweight checks on zone's SOA and
\n
\
(apex) NS records. Here, lightweight means it doesn't require
\n
\
traversing the entire zone, and should be expected to complete
\n
\
reasonably quickly regardless of the size of the zone.
\n
\
\n
\
It distinguishes
\"
critical
\"
errors and other undesirable issues: the
\n
\
former should be interpreted as the resulting zone shouldn't be used
\n
\
further, e.g, by an authoritative server implementation; the latter
\n
\
means the issues are better to be addressed but are not necessarily
\n
\
considered to make the zone invalid. Critical errors are reported via
\n
\
the error() function, and non critical issues are reported via warn().
\n
\
\n
\
Specific checks performed by this function is as follows. Failure of
\n
\
a check is considered a critical error unless noted otherwise:
\n
\
\n
\
- There is exactly one SOA RR at the zone apex.
\n
\
- There is at least one NS RR at the zone apex.
\n
\
- For each apex NS record, if the NS name (the RDATA of the record) is
\n
\
in the zone (i.e., it's a subdomain of the zone origin and above any
\n
\
zone cut due to delegation), check the following:
\n
\
- the NS name should have an address record (AAAA or A). Failure of
\n
\
this check is considered a non critical issue.
\n
\
- the NS name does not have a CNAME. This is prohibited by Section
\n
\
10.3 of RFC 2181.
\n
\
- the NS name is not subject to DNAME substitution. This is prohibited
\n
\
by Section 4 of RFC 6672.
\n
\
\n
\
In addition, when the check is completed without any
\n
\
critical error, this function guarantees that RRsets for the SOA and
\n
\
(apex) NS stored in the passed RRset collection have the expected
\n
\
type of Rdata objects, i.e., generic.SOA and generic.NS,
\n
\
respectively. (This is normally expected to be the case, but not
\n
\
guaranteed by the API).
\n
\
\n
\
As for the check on the existence of AAAA or A records for NS names,
\n
\
it should be noted that BIND 9 treats this as a critical error. It's
\n
\
not clear whether it's an implementation dependent behavior or based
\n
\
on the protocol standard (it looks like the former), but to make it
\n
\
sure we need to confirm there is even no wildcard match for the names.
\n
\
This should be a very rare configuration, and more expensive to
\n
\
detect, so we do not check this condition, and treat this case as a
\n
\
non critical issue.
\n
\
\n
\
This function indicates the result of the checks (whether there is a
\n
\
critical error) via the return value: It returns True if there is no
\n
\
critical error and returns False otherwise. It doesn't throw an
\n
\
exception on encountering an error so that it can report as many
\n
\
errors as possible in a single call. If an exception is a better way
\n
\
to signal the error, the caller can pass a callable object as error()
\n
\
that throws.
\n
\
\n
\
This function can still throw an exception if it finds a really bogus
\n
\
condition that is most likely to be an implementation bug of the
\n
\
caller. Such cases include when an RRset contained in the RRset
\n
\
collection is empty.
\n
\
\n
\
Parameters:
\n
\
zone_name The name of the zone to be checked
\n
\
zone_class The RR class of the zone to be checked
\n
\
zone_rrsets The collection of RRsets of the zone
\n
\
error Callable object used to report errors
\n
\
warn Callable object used to report non-critical issues
\n
\
\n
\
Return Value(s): True if no critical errors are found; False
\n
\
otherwise.
\n
\
"
;
}
// unnamed namespace
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment