From: Tomek Mrugalski Date: Tue, 3 Jun 2014 09:58:35 +0000 (+0200) Subject: [3413] libdns++ is now less python dependent X-Git-Tag: trac3473_base~11^2~11 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=70ea2e6d4d870cdd480d1d19f7d3cf596421969e;p=thirdparty%2Fkea.git [3413] libdns++ is now less python dependent - no longer builds src/lib/dns/python directory - gen-rdatacode.py is no longer necessary for build --- diff --git a/src/lib/dns/.gitignore b/src/lib/dns/.gitignore index 9606daca0b..fa14fe18b4 100644 --- a/src/lib/dns/.gitignore +++ b/src/lib/dns/.gitignore @@ -1,7 +1,2 @@ /gen-rdatacode.py -/rdataclass.cc -/rdataclass.h -/rrclass.h -/rrparamregistry.cc -/rrtype.h /s-rdatacode diff --git a/src/lib/dns/Makefile.am b/src/lib/dns/Makefile.am index 3190209388..76e5125ebb 100644 --- a/src/lib/dns/Makefile.am +++ b/src/lib/dns/Makefile.am @@ -1,4 +1,4 @@ -SUBDIRS = . tests python +SUBDIRS = . tests AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_builddir)/src/lib AM_CPPFLAGS += -I$(top_srcdir)/src/lib/dns -I$(top_builddir)/src/lib/dns @@ -7,7 +7,7 @@ AM_CPPFLAGS += $(BOOST_INCLUDES) AM_CXXFLAGS = $(B10_CXXFLAGS) CLEANFILES = *.gcno *.gcda -CLEANFILES += rrclass.h rrtype.h rrparamregistry.cc rdataclass.h rdataclass.cc s-rdatacode +CLEANFILES += s-rdatacode # These two are created with rrtype/class.h, so not explicitly listed in # BUILT_SOURCES. CLEANFILES += python/rrtype_constants_inc.cc @@ -156,8 +156,10 @@ libkea_dns___la_CPPFLAGS = $(AM_CPPFLAGS) libkea_dns___la_LIBADD = $(top_builddir)/src/lib/cryptolink/libkea-cryptolink.la libkea_dns___la_LIBADD += $(top_builddir)/src/lib/util/libkea-util.la -nodist_libdns___include_HEADERS = rdataclass.h rrclass.h rrtype.h -nodist_libkea_dns___la_SOURCES = rdataclass.cc rrparamregistry.cc +# The following files used to be generated, but they are now part of the git tree: +# rrclass.h rrtype.h rrparamregistry.cc rdataclass.h rdataclass.cc +libkea_dns___la_SOURCES += rdataclass.h rrclass.h rrtype.h +libkea_dns___la_SOURCES += rdataclass.cc rrparamregistry.cc rrclass.h: rrclass-placeholder.h rrtype.h: rrtype-placeholder.h @@ -167,7 +169,12 @@ s-rdatacode: Makefile $(EXTRA_DIST) $(PYTHON) ./gen-rdatacode.py touch $@ -rrclass.h rrtype.h rrparamregistry.cc rdataclass.h rdataclass.cc: s-rdatacode +# In ticket #3413 we removed the whole BIND10/Bundy framework. We also want +# to not require Python3, hence instead of generating the code every time, +# we added the generated files to our repo. It is still possible to regenerate +# those files, but that step is no longer required for successful compilation. + +#rrclass.h rrtype.h rrparamregistry.cc rdataclass.h rdataclass.cc: s-rdatacode libdns___includedir = $(includedir)/$(PACKAGE_NAME)/dns libdns___include_HEADERS = \ diff --git a/src/lib/dns/python/.gitignore b/src/lib/dns/python/.gitignore deleted file mode 100644 index 0713cf8c8f..0000000000 --- a/src/lib/dns/python/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -/rrclass_constants_inc.cc -/rrtype_constants_inc.cc -/pydnspp_config.h diff --git a/src/lib/dns/python/Makefile.am b/src/lib/dns/python/Makefile.am deleted file mode 100644 index 383191076f..0000000000 --- a/src/lib/dns/python/Makefile.am +++ /dev/null @@ -1,66 +0,0 @@ -SUBDIRS = . tests - -AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_builddir)/src/lib -AM_CPPFLAGS += $(BOOST_INCLUDES) -AM_CXXFLAGS = $(B10_CXXFLAGS) - -# There is a build problem with python3.4 (a new field tp_finalize) has been -# added and now compiler complains about it not being properly initialized in -# construtor. Since the whole python thing goes away, it's counter-productive -# to spend any time on making this work on both python3.3 and 3.4, so -# ingoring the warning seems the way to go. -AM_CXXFLAGS += -Wno-error - -lib_LTLIBRARIES = libkea-pydnspp.la -libkea_pydnspp_la_SOURCES = pydnspp_common.cc pydnspp_common.h -libkea_pydnspp_la_SOURCES += pydnspp_config.h pydnspp_towire.h -libkea_pydnspp_la_SOURCES += name_python.cc name_python.h -libkea_pydnspp_la_SOURCES += nsec3hash_python.cc nsec3hash_python.h -libkea_pydnspp_la_SOURCES += rrset_python.cc rrset_python.h -libkea_pydnspp_la_SOURCES += rrclass_python.cc rrclass_python.h -libkea_pydnspp_la_SOURCES += rrtype_python.cc rrtype_python.h -libkea_pydnspp_la_SOURCES += rrttl_python.cc rrttl_python.h -libkea_pydnspp_la_SOURCES += rdata_python.cc rdata_python.h -libkea_pydnspp_la_SOURCES += serial_python.cc serial_python.h -libkea_pydnspp_la_SOURCES += messagerenderer_python.cc messagerenderer_python.h -libkea_pydnspp_la_SOURCES += rcode_python.cc rcode_python.h -libkea_pydnspp_la_SOURCES += opcode_python.cc opcode_python.h -libkea_pydnspp_la_SOURCES += question_python.cc question_python.h -libkea_pydnspp_la_SOURCES += tsigkey_python.cc tsigkey_python.h -libkea_pydnspp_la_SOURCES += tsigerror_python.cc tsigerror_python.h -libkea_pydnspp_la_SOURCES += tsig_rdata_python.cc tsig_rdata_python.h -libkea_pydnspp_la_SOURCES += tsigrecord_python.cc tsigrecord_python.h -libkea_pydnspp_la_SOURCES += tsig_python.cc tsig_python.h -libkea_pydnspp_la_SOURCES += edns_python.cc edns_python.h -libkea_pydnspp_la_SOURCES += message_python.cc message_python.h -libkea_pydnspp_la_SOURCES += rrset_collection_python.cc -libkea_pydnspp_la_SOURCES += rrset_collection_python.h -libkea_pydnspp_la_SOURCES += zone_checker_python.cc zone_checker_python.h - -libkea_pydnspp_la_CPPFLAGS = $(AM_CPPFLAGS) $(PYTHON_INCLUDES) -libkea_pydnspp_la_CXXFLAGS = $(AM_CXXFLAGS) $(PYTHON_CXXFLAGS) -libkea_pydnspp_la_LDFLAGS = $(PYTHON_LDFLAGS) - - - -pyexec_LTLIBRARIES = pydnspp.la -pydnspp_la_SOURCES = pydnspp.cc -pydnspp_la_CPPFLAGS = $(AM_CPPFLAGS) $(PYTHON_INCLUDES) -# Note: PYTHON_CXXFLAGS may have some -Wno... workaround, which must be -# placed after -Wextra defined in AM_CXXFLAGS -pydnspp_la_CXXFLAGS = $(AM_CXXFLAGS) $(PYTHON_CXXFLAGS) -pydnspp_la_LDFLAGS = $(PYTHON_LDFLAGS) - -EXTRA_DIST = tsigerror_python_inc.cc -EXTRA_DIST += message_python_inc.cc -EXTRA_DIST += nsec3hash_python_inc.cc -EXTRA_DIST += rrset_collection_python_inc.cc -EXTRA_DIST += zone_checker_python_inc.cc - -# Python prefers .so, while some OSes (specifically MacOS) use a different -# suffix for dynamic objects. -module is necessary to work this around. -pydnspp_la_LDFLAGS += -module -avoid-version -pydnspp_la_LIBADD = $(top_builddir)/src/lib/dns/libkea-dns++.la -pydnspp_la_LIBADD += $(top_builddir)/src/lib/exceptions/libkea-exceptions.la -pydnspp_la_LIBADD += libkea-pydnspp.la -pydnspp_la_LIBADD += $(PYTHON_LIB) diff --git a/src/lib/dns/python/README b/src/lib/dns/python/README deleted file mode 100644 index fe423753a9..0000000000 --- a/src/lib/dns/python/README +++ /dev/null @@ -1,94 +0,0 @@ - -This is an implementation of the python wrappers for isc::dns. - -When compiled the module is called pydnspp. If we -decide to always need it we can add a default import under -lib/python/isc. - -To use it from the source tree, you must add src/lib/dns/python/.libs -to your PYTHONPATH environment variable. Within python you can then use -> import pydnspp -> rrc = pydnspp.RRClass("IN") -etc. - -Notes: - -this implementation is not a complete 1-to-1 mapping of the C++ API; -some of the functionality is not needed the way we use it in Python. - -For instance, we did not implement the buffer classes; -everywhere in the API where buffers are used, you can pass a bytearray -object. - -We also (currently) left out some 'lowlevel' wrappers, for instance for -specific Rdata types. - -If you have specific functionality you do need, please ask for it and we -will add it. - -The 'main' module is defined in pydnspp.cc. -There is a pydnspp_common.[cc|h] for helper functions. - -Implementation notes: - -Writing wrappers for a lot of classes is mostly a case of repetition. -There are a lot of things one must do, and that is why nearly everyone -immediately and continually has the urge to make generators for this. - -We have added a little more documentation than is strictly necessary to -rrclass.h, for reference to new readers. - -To keep it maintainable as the original API changes, we use two -techniques; - -1. Full unittests. Or at least as full as possible. These unit tests - test the *wrapper* code, not necessarily the underlying c++ code, - which has its own unit tests. There is of course some overlap. -2. Structure. I have tried to structure the wrapper files as much as - possible, see below. - -Structure: - -Since we are moving a lot of wrappers into one module, the specific -classes are split over several files, each one having the name of the -original header file they are wrapping (e.g. the wrapper for name.h -becomes name_python.cc). - -At the top we first declare any exceptions, constants, and enums. These -are all called po_ (the actual python name will be set once -they are added to the module in the module inialization function). - -Each class needs a struct that contains a pointer to an instance of the -object (and any helper data). We call these structs s_. - -Then we declare (but not define!) all methods we will export to -python. These are named _. - -We will also need an _init and _destroy function for all of these. - -After the function declarations we define the method array; this -contains the name of the methods as they appear in python, the wrapping -function here, and documentation strings. - -Next is the type description; this is used for the wrapper code to -convert native classes from and to python objects, and defines -type-specific pointers (for instance to the method table mentioned above, -but also to a __str__ function should one be defined, how the object -should behave when it is used as a Sequence, etc.). For most classes, -almost all values here shall be NULL. -This has the name _type. - -After that we define the exported functions we defined earlier. In some -cases these need the type we just defined, and the type needed the -function names, so for consistency, all functions are defined after, -but declared before the type. - -This is repeated for every class we export. - -Finally we define the function to add the class, constants, exceptions, -and enums to the module. This function is called from the init function -in pydnspp.cc, has the name -initModulePart_, returns a boolean -(true on success, false on failure), and takes the module as a -PyObject*. There is a convenience function called addClassVariable to -add constants and enums to classes. diff --git a/src/lib/dns/python/TODO b/src/lib/dns/python/TODO deleted file mode 100644 index 27dcf621a5..0000000000 --- a/src/lib/dns/python/TODO +++ /dev/null @@ -1,15 +0,0 @@ - -add statics for RRClass::IN() (RRClass.IN()) etc. -(and replace RRClass("IN") in tests with those) - -same for RRType? (xfrout.py.in line 256) - -creating a render message and not setting opcode/rcode results in a segfault later (nullpointer) -(is this cpp or python problem?) - -The function set wrapped is not complete; for instance, in -MessageRenderer, we really only provide the high-level readout -functions. Do we need access to the writers? (there is one set() right -now). - -segfault when comparing with bad type like int (at least for Name and Rcode, but probably for the rest too) diff --git a/src/lib/dns/python/edns_python.cc b/src/lib/dns/python/edns_python.cc deleted file mode 100644 index e9d54c1a26..0000000000 --- a/src/lib/dns/python/edns_python.cc +++ /dev/null @@ -1,392 +0,0 @@ -// Copyright (C) 2010 Internet Systems Consortium, Inc. ("ISC") -// -// Permission to use, copy, modify, and/or distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -// PERFORMANCE OF THIS SOFTWARE. - -#include - -#include - -#include -#include -#include -#include - -#include "edns_python.h" -#include "name_python.h" -#include "rrclass_python.h" -#include "rrtype_python.h" -#include "rrttl_python.h" -#include "rdata_python.h" -#include "messagerenderer_python.h" -#include "pydnspp_common.h" - -using namespace isc::dns; -using namespace isc::dns::rdata; -using namespace isc::dns::python; -using namespace isc::util; -using namespace isc::util::python; - -namespace { - -class s_EDNS : public PyObject { -public: - EDNS* cppobj; -}; - -typedef CPPPyObjectContainer EDNSContainer; - -// General creation and destruction -int EDNS_init(s_EDNS* self, PyObject* args); -void EDNS_destroy(s_EDNS* self); - -// These are the functions we export -PyObject* EDNS_toText(const s_EDNS* self); -// This is a second version of toText, we need one where the argument -// is a PyObject*, for the str() function in python. -PyObject* EDNS_str(PyObject* self); -PyObject* EDNS_toWire(const s_EDNS* self, PyObject* args); -PyObject* EDNS_getVersion(const s_EDNS* self); -PyObject* EDNS_getDNSSECAwareness(const s_EDNS* self); -PyObject* EDNS_setDNSSECAwareness(s_EDNS* self, PyObject* args); -PyObject* EDNS_getUDPSize(const s_EDNS* self); -PyObject* EDNS_setUDPSize(s_EDNS* self, PyObject* args); -PyObject* EDNS_createFromRR(const s_EDNS* null_self, PyObject* args); - -// This list contains the actual set of functions we have in -// python. Each entry has -// 1. Python method name -// 2. Our static function here -// 3. Argument type -// 4. Documentation -PyMethodDef EDNS_methods[] = { - { "to_text", reinterpret_cast(EDNS_toText), METH_NOARGS, - "Returns the string representation" }, - { "to_wire", reinterpret_cast(EDNS_toWire), METH_VARARGS, - "Converts the EDNS object to wire format.\n" - "The argument can be either a MessageRenderer or an object that " - "implements the sequence interface. If the object is mutable " - "(for instance a bytearray()), the wire data is added in-place.\n" - "If it is not (for instance a bytes() object), a new object is " - "returned" }, - { "get_version", - reinterpret_cast(EDNS_getVersion), METH_NOARGS, - "Returns the version of EDNS." }, - { "get_dnssec_awareness", - reinterpret_cast(EDNS_getDNSSECAwareness), METH_NOARGS, - "Returns whether the message sender is DNSSEC aware." }, - { "set_dnssec_awareness", - reinterpret_cast(EDNS_setDNSSECAwareness), METH_VARARGS, - "Specifies whether the sender of the message containing this " - "EDNS is DNSSEC aware." }, - { "get_udp_size", - reinterpret_cast(EDNS_getUDPSize), METH_NOARGS, - "Return the maximum buffer size of UDP messages for the sender " - "of the message." }, - { "set_udp_size", - reinterpret_cast(EDNS_setUDPSize), METH_VARARGS, - "Specify the maximum buffer size of UDP messages that use this EDNS." }, - { "create_from_rr", - reinterpret_cast(EDNS_createFromRR), - METH_VARARGS | METH_STATIC, - "Create a new EDNS object from a set of RR parameters, also providing " - "the extended RCODE value." }, - { NULL, NULL, 0, NULL } -}; - -EDNS* -createFromRR(const Name& name, const RRClass& rrclass, const RRType& rrtype, - const RRTTL& rrttl, const Rdata& rdata, uint8_t& extended_rcode) -{ - try { - return (createEDNSFromRR(name, rrclass, rrtype, rrttl, rdata, - extended_rcode)); - } catch (const isc::InvalidParameter& ex) { - PyErr_SetString(po_InvalidParameter, ex.what()); - } catch (const DNSMessageFORMERR& ex) { - PyErr_SetString(po_DNSMessageFORMERR, ex.what()); - } catch (const DNSMessageBADVERS& ex) { - PyErr_SetString(po_DNSMessageBADVERS, ex.what()); - } catch (...) { - PyErr_SetString(po_IscException, "Unexpected exception"); - } - - return (NULL); -} -int -EDNS_init(s_EDNS* self, PyObject* args) { - uint8_t version = EDNS::SUPPORTED_VERSION; - const PyObject* name; - const PyObject* rrclass; - const PyObject* rrtype; - const PyObject* rrttl; - const PyObject* rdata; - - if (PyArg_ParseTuple(args, "|b", &version)) { - try { - self->cppobj = new EDNS(version); - } catch (const isc::InvalidParameter& ex) { - PyErr_SetString(po_InvalidParameter, ex.what()); - return (-1); - } catch (...) { - PyErr_SetString(po_IscException, "Unexpected exception"); - return (-1); - } - return (0); - } else if (PyArg_ParseTuple(args, "O!O!O!O!O!", &name_type, &name, - &rrclass_type, &rrclass, &rrtype_type, &rrtype, - &rrttl_type, &rrttl, &rdata_type, &rdata)) { - // We use createFromRR() even if we don't need to know extended_rcode - // in this context so that we can share the try-catch logic with - // EDNS_createFromRR() (see below). - uint8_t extended_rcode; - self->cppobj = createFromRR(PyName_ToName(name), - PyRRClass_ToRRClass(rrclass), - PyRRType_ToRRType(rrtype), - PyRRTTL_ToRRTTL(rrttl), - PyRdata_ToRdata(rdata), extended_rcode); - return (self->cppobj != NULL ? 0 : -1); - } - - PyErr_Clear(); - PyErr_SetString(PyExc_TypeError, "Invalid arguments to EDNS constructor"); - - return (-1); -} - -void -EDNS_destroy(s_EDNS* const self) { - delete self->cppobj; - self->cppobj = NULL; - Py_TYPE(self)->tp_free(self); -} - -PyObject* -EDNS_toText(const s_EDNS* const self) { - // Py_BuildValue makes python objects from native data - return (Py_BuildValue("s", self->cppobj->toText().c_str())); -} - -PyObject* -EDNS_str(PyObject* self) { - // Simply call the to_text method we already defined - return (PyObject_CallMethod(self, - const_cast("to_text"), - const_cast(""))); -} - -PyObject* -EDNS_toWire(const s_EDNS* const self, PyObject* args) { - PyObject* bytes; - uint8_t extended_rcode; - PyObject* renderer; - - if (PyArg_ParseTuple(args, "Ob", &bytes, &extended_rcode) && - PySequence_Check(bytes)) { - PyObject* bytes_o = bytes; - - OutputBuffer buffer(0); - self->cppobj->toWire(buffer, extended_rcode); - PyObject* rd_bytes = PyBytes_FromStringAndSize( - static_cast(buffer.getData()), buffer.getLength()); - PyObject* result = PySequence_InPlaceConcat(bytes_o, rd_bytes); - // We need to release the object we temporarily created here - // to prevent memory leak - Py_DECREF(rd_bytes); - return (result); - } else if (PyArg_ParseTuple(args, "O!b", &messagerenderer_type, - &renderer, &extended_rcode)) { - const unsigned int n = self->cppobj->toWire( - PyMessageRenderer_ToMessageRenderer(renderer), extended_rcode); - - return (Py_BuildValue("I", n)); - } - PyErr_Clear(); - PyErr_SetString(PyExc_TypeError, "Incorrect arguments for EDNS.to_wire()"); - return (NULL); -} - -PyObject* -EDNS_getVersion(const s_EDNS* const self) { - return (Py_BuildValue("B", self->cppobj->getVersion())); -} - -PyObject* -EDNS_getDNSSECAwareness(const s_EDNS* const self) { - if (self->cppobj->getDNSSECAwareness()) { - Py_RETURN_TRUE; - } else { - Py_RETURN_FALSE; - } -} - -PyObject* -EDNS_setDNSSECAwareness(s_EDNS* self, PyObject* args) { - const PyObject *b; - if (!PyArg_ParseTuple(args, "O!", &PyBool_Type, &b)) { - return (NULL); - } - self->cppobj->setDNSSECAwareness(b == Py_True); - Py_RETURN_NONE; -} - -PyObject* -EDNS_getUDPSize(const s_EDNS* const self) { - return (Py_BuildValue("I", self->cppobj->getUDPSize())); -} - -PyObject* -EDNS_setUDPSize(s_EDNS* self, PyObject* args) { - long size; - if (!PyArg_ParseTuple(args, "l", &size)) { - PyErr_Clear(); - PyErr_SetString(PyExc_TypeError, - "No valid type in set_udp_size argument"); - return (NULL); - } - if (size < 0 || size > 0xffff) { - PyErr_SetString(PyExc_ValueError, - "UDP size is not an unsigned 16-bit integer"); - return (NULL); - } - self->cppobj->setUDPSize(size); - Py_RETURN_NONE; -} - -PyObject* -EDNS_createFromRR(const s_EDNS* null_self, PyObject* args) { - const PyObject* name; - const PyObject* rrclass; - const PyObject* rrtype; - const PyObject* rrttl; - const PyObject* rdata; - - assert(null_self == NULL); - - if (PyArg_ParseTuple(args, "O!O!O!O!O!", &name_type, &name, - &rrclass_type, &rrclass, &rrtype_type, &rrtype, - &rrttl_type, &rrttl, &rdata_type, &rdata)) { - uint8_t extended_rcode; - s_EDNS* edns_obj = PyObject_New(s_EDNS, &edns_type); - if (edns_obj == NULL) { - return (NULL); - } - - edns_obj->cppobj = createFromRR(PyName_ToName(name), - PyRRClass_ToRRClass(rrclass), - PyRRType_ToRRType(rrtype), - PyRRTTL_ToRRTTL(rrttl), - PyRdata_ToRdata(rdata), - extended_rcode); - if (edns_obj->cppobj != NULL) { - PyObject* extrcode_obj = Py_BuildValue("B", extended_rcode); - return (Py_BuildValue("OO", edns_obj, extrcode_obj)); - } - - Py_DECREF(edns_obj); - return (NULL); - } - - PyErr_Clear(); - PyErr_SetString(PyExc_TypeError, - "Incorrect arguments for EDNS.create_from_rr()"); - return (NULL); -} - -} // end of anonymous namespace - -namespace isc { -namespace dns { -namespace python { - -// This defines the complete type for reflection in python and -// parsing of PyObject* to s_EDNS -// Most of the functions are not actually implemented and NULL here. -PyTypeObject edns_type = { - PyVarObject_HEAD_INIT(NULL, 0) - "pydnspp.EDNS", - sizeof(s_EDNS), // tp_basicsize - 0, // tp_itemsize - (destructor)EDNS_destroy, // tp_dealloc - NULL, // tp_print - NULL, // tp_getattr - NULL, // tp_setattr - NULL, // tp_reserved - NULL, // tp_repr - NULL, // tp_as_number - NULL, // tp_as_sequence - NULL, // tp_as_mapping - NULL, // tp_hash - NULL, // tp_call - EDNS_str, // tp_str - NULL, // tp_getattro - NULL, // tp_setattro - NULL, // tp_as_buffer - Py_TPFLAGS_DEFAULT, // tp_flags - "The EDNS class encapsulates DNS extensions " - "provided by the EDNSx protocol.", - NULL, // tp_traverse - NULL, // tp_clear - NULL, // tp_richcompare - 0, // tp_weaklistoffset - NULL, // tp_iter - NULL, // tp_iternext - EDNS_methods, // tp_methods - NULL, // tp_members - NULL, // tp_getset - NULL, // tp_base - NULL, // tp_dict - NULL, // tp_descr_get - NULL, // tp_descr_set - 0, // tp_dictoffset - (initproc)EDNS_init, // tp_init - NULL, // tp_alloc - PyType_GenericNew, // tp_new - NULL, // tp_free - NULL, // tp_is_gc - NULL, // tp_bases - NULL, // tp_mro - NULL, // tp_cache - NULL, // tp_subclasses - NULL, // tp_weaklist - NULL, // tp_del - 0 // tp_version_tag -}; - -PyObject* -createEDNSObject(const EDNS& source) { - EDNSContainer container(PyObject_New(s_EDNS, &edns_type)); - container.set(new EDNS(source)); - return (container.release()); -} - -bool -PyEDNS_Check(PyObject* obj) { - if (obj == NULL) { - isc_throw(PyCPPWrapperException, "obj argument NULL in typecheck"); - } - return (PyObject_TypeCheck(obj, &edns_type)); -} - -const EDNS& -PyEDNS_ToEDNS(const PyObject* edns_obj) { - if (edns_obj == NULL) { - isc_throw(PyCPPWrapperException, - "obj argument NULL in EDNS PyObject conversion"); - } - const s_EDNS* edns = static_cast(edns_obj); - return (*edns->cppobj); -} - -} // end namespace python -} // end namespace dns -} // end namespace isc diff --git a/src/lib/dns/python/edns_python.h b/src/lib/dns/python/edns_python.h deleted file mode 100644 index 2106b227f4..0000000000 --- a/src/lib/dns/python/edns_python.h +++ /dev/null @@ -1,64 +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. - -#ifndef PYTHON_EDNS_H -#define PYTHON_EDNS_H 1 - -#include - -namespace isc { -namespace dns { -class EDNS; - -namespace python { - -extern PyTypeObject edns_type; - -/// This is a simple shortcut to create a python EDNS object (in the -/// form of a pointer to PyObject) with minimal exception safety. -/// On success, it returns a valid pointer to PyObject with a reference -/// counter of 1; if something goes wrong it throws an exception (it never -/// returns a NULL pointer). -/// This function is expected to be called within a try block -/// followed by necessary setup for python exception. -PyObject* createEDNSObject(const EDNS& source); - -/// \brief Checks if the given python object is a EDNS object -/// -/// \exception PyCPPWrapperException if obj is NULL -/// -/// \param obj The object to check the type of -/// \return true if the object is of type EDNS, false otherwise -bool PyEDNS_Check(PyObject* obj); - -/// \brief Returns a reference to the EDNS object contained within the given -/// Python object. -/// -/// \note The given object MUST be of type EDNS; this can be checked with -/// either the right call to ParseTuple("O!"), or with PyEDNS_Check() -/// -/// \note This is not a copy; if the EDNS is needed when the PyObject -/// may be destroyed, the caller must copy it itself. -/// -/// \param edns_obj The edns object to convert -const EDNS& PyEDNS_ToEDNS(const PyObject* edns_obj); - -} // namespace python -} // namespace dns -} // namespace isc -#endif // PYTHON_EDNS_H - -// Local Variables: -// mode: c++ -// End: diff --git a/src/lib/dns/python/message_python.cc b/src/lib/dns/python/message_python.cc deleted file mode 100644 index d86754b8e8..0000000000 --- a/src/lib/dns/python/message_python.cc +++ /dev/null @@ -1,848 +0,0 @@ -// Copyright (C) 2010 Internet Systems Consortium, Inc. ("ISC") -// -// Permission to use, copy, modify, and/or distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -// PERFORMANCE OF THIS SOFTWARE. - -#define PY_SSIZE_T_CLEAN -#include - -#include -#include -#include -#include -#include -#include -#include - -#include "name_python.h" -#include "question_python.h" -#include "edns_python.h" -#include "rcode_python.h" -#include "opcode_python.h" -#include "rrset_python.h" -#include "message_python.h" -#include "messagerenderer_python.h" -#include "tsig_python.h" -#include "tsigrecord_python.h" -#include "pydnspp_common.h" - -using namespace std; -using namespace isc::dns; -using namespace isc::dns::python; -using namespace isc::util; -using namespace isc::util::python; - -// Import pydoc text -#include "message_python_inc.cc" - -namespace { -class s_Message : public PyObject { -public: - isc::dns::Message* cppobj; -}; - -int Message_init(s_Message* self, PyObject* args); -void Message_destroy(s_Message* self); - -PyObject* Message_getHeaderFlag(s_Message* self, PyObject* args); -PyObject* Message_setHeaderFlag(s_Message* self, PyObject* args); -PyObject* Message_getQid(s_Message* self); -PyObject* Message_setQid(s_Message* self, PyObject* args); -PyObject* Message_getRcode(s_Message* self); -PyObject* Message_setRcode(s_Message* self, PyObject* args); -PyObject* Message_getOpcode(s_Message* self); -PyObject* Message_setOpcode(s_Message* self, PyObject* args); -PyObject* Message_getEDNS(s_Message* self); -PyObject* Message_setEDNS(s_Message* self, PyObject* args); -PyObject* Message_getTSIGRecord(s_Message* self); -PyObject* Message_getRRCount(s_Message* self, PyObject* args); -// use direct iterators for these? (or simply lists for now?) -PyObject* Message_getQuestion(PyObject* self, PyObject*); -PyObject* Message_getSection(PyObject* self, PyObject* args); -//static PyObject* Message_beginQuestion(s_Message* self, PyObject* args); -//static PyObject* Message_endQuestion(s_Message* self, PyObject* args); -//static PyObject* Message_beginSection(s_Message* self, PyObject* args); -//static PyObject* Message_endSection(s_Message* self, PyObject* args); - -PyObject* Message_addQuestion(s_Message* self, PyObject* args); -PyObject* Message_addRRset(s_Message* self, PyObject* args); -PyObject* Message_clear(s_Message* self, PyObject* args); -PyObject* Message_clearSection(PyObject* pyself, PyObject* args); -PyObject* Message_makeResponse(s_Message* self); -PyObject* Message_toText(s_Message* self); -PyObject* Message_str(PyObject* self); -PyObject* Message_toWire(s_Message* self, PyObject* args); -PyObject* Message_fromWire(PyObject* pyself, PyObject* args); - -// This list contains the actual set of functions we have in -// python. Each entry has -// 1. Python method name -// 2. Our static function here -// 3. Argument type -// 4. Documentation -PyMethodDef Message_methods[] = { - { "get_header_flag", reinterpret_cast(Message_getHeaderFlag), - METH_VARARGS, - "Return whether the specified header flag bit is set in the " - "header section. Takes a MessageFlag object as the only argument." }, - { "set_header_flag", - reinterpret_cast(Message_setHeaderFlag), METH_VARARGS, - "Sets the specified header flag bit to 1. The message must be in " - "RENDER mode. If not, an InvalidMessageOperation is raised. " - "Takes a MessageFlag object as the only argument." }, - { "get_qid", reinterpret_cast(Message_getQid), METH_NOARGS, - "Returns the query id" }, - { "set_qid", reinterpret_cast(Message_setQid), METH_VARARGS, - "Sets the query id. If the message is not in RENDER mode, an " - "InvalidMessageOperation is raised.\n" - "The argument must be an integer" }, - { "get_rcode", reinterpret_cast(Message_getRcode), METH_NOARGS, - "Returns the message Response code (an Rcode object)" }, - { "set_rcode", reinterpret_cast(Message_setRcode), METH_VARARGS, - "Sets the message Response code (an Rcode object).\n" - "If the message is not in RENDER mode, an " - "InvalidMessageOperation is raised."}, - { "get_opcode", reinterpret_cast(Message_getOpcode), METH_NOARGS, - "Returns the message opcode (an Opcode object)" }, - { "set_opcode", reinterpret_cast(Message_setOpcode), METH_VARARGS, - "Sets the message opcode (an Opcode object).\n" - "If the message is not in RENDER mode, an " - "InvalidMessageOperation is raised."}, - { "get_edns", reinterpret_cast(Message_getEDNS), METH_NOARGS, - "Return, if any, the EDNS associated with the message." - }, - { "set_edns", reinterpret_cast(Message_setEDNS), METH_VARARGS, - "Set EDNS for the message." - }, - { "get_tsig_record", - reinterpret_cast(Message_getTSIGRecord), METH_NOARGS, - "Return, if any, the TSIG record contained in the received message. " - "If no TSIG RR is set in the message, None will be returned." - }, - { "get_rr_count", reinterpret_cast(Message_getRRCount), METH_VARARGS, - "Returns the number of RRs contained in the given section." }, - { "get_question", Message_getQuestion, METH_NOARGS, - "Returns a list of all Question objects in the message " - "(should be either 0 or 1)" }, - { "get_section", Message_getSection, METH_VARARGS, - "Returns a list of all RRset objects in the given section of the message\n" - "The argument must be of type Section" }, - { "add_question", reinterpret_cast(Message_addQuestion), METH_VARARGS, - "Add a Question to the message." - "If the message is not in RENDER mode, an " - "InvalidMessageOperation is raised."}, - { "add_rrset", reinterpret_cast(Message_addRRset), METH_VARARGS, - "Add an RRset to the given section of the message.\n" - "The first argument is of type Section\n" - "The second is of type RRset"}, - { "clear", reinterpret_cast(Message_clear), METH_VARARGS, - "Clears the message content (if any) and reinitialize the " - "message in the given mode\n" - "The argument must be either Message.PARSE or Message.RENDER"}, - { "clear_section", Message_clearSection, METH_VARARGS, - Message_clearSection_doc }, - { "make_response", reinterpret_cast(Message_makeResponse), METH_NOARGS, - "Prepare for making a response from a request.\n" - "This will clear the DNS header except those fields that should be kept " - "for the response, and clear answer and the following sections. " - "See also dns_message_reply() of BIND9."}, - { "to_text", reinterpret_cast(Message_toText), METH_NOARGS, - "Returns the string representation of the message" }, - { "to_wire", reinterpret_cast(Message_toWire), METH_VARARGS, - "Render the message in wire format.\n" - "The argument must be a MessageRenderer.\n" - "If the given message is not in RENDER mode, an " - "InvalidMessageOperation is raised.\n" - }, - { "from_wire", Message_fromWire, METH_VARARGS, Message_fromWire_doc }, - { NULL, NULL, 0, NULL } -}; - -int -Message_init(s_Message* self, PyObject* args) { - int i; - - if (PyArg_ParseTuple(args, "i", &i)) { - PyErr_Clear(); - if (i == Message::PARSE) { - self->cppobj = new Message(Message::PARSE); - return (0); - } else if (i == Message::RENDER) { - self->cppobj = new Message(Message::RENDER); - return (0); - } else { - PyErr_SetString(PyExc_TypeError, "Message mode must be Message.PARSE or Message.RENDER"); - return (-1); - } - } - PyErr_Clear(); - PyErr_SetString(PyExc_TypeError, - "no valid type in constructor argument"); - return (-1); -} - -void -Message_destroy(s_Message* self) { - delete self->cppobj; - self->cppobj = NULL; - Py_TYPE(self)->tp_free(self); -} - -PyObject* -Message_getHeaderFlag(s_Message* self, PyObject* args) { - unsigned int messageflag; - if (!PyArg_ParseTuple(args, "I", &messageflag)) { - PyErr_Clear(); - PyErr_SetString(PyExc_TypeError, - "no valid type in get_header_flag argument"); - return (NULL); - } - - try { - if (self->cppobj->getHeaderFlag( - static_cast(messageflag))) { - Py_RETURN_TRUE; - } else { - Py_RETURN_FALSE; - } - } catch (const isc::InvalidParameter& ip) { - PyErr_Clear(); - PyErr_SetString(po_InvalidParameter, ip.what()); - } catch (const exception& ex) { - const string ex_what = "Error in Message.get_header_flag(): " + string(ex.what()); - PyErr_SetString(po_IscException, ex_what.c_str()); - } catch (...) { - PyErr_SetString(po_IscException, - "Unexpected exception in Message.get_header_flag()"); - } - return (NULL); -} - -PyObject* -Message_setHeaderFlag(s_Message* self, PyObject* args) { - long messageflag; - PyObject *on = Py_True; - - if (!PyArg_ParseTuple(args, "l|O!", &messageflag, &PyBool_Type, &on)) { - PyErr_Clear(); - PyErr_SetString(PyExc_TypeError, - "no valid type in set_header_flag argument"); - return (NULL); - } - if (messageflag < 0 || messageflag > 0xffff) { - PyErr_SetString(PyExc_ValueError, "Message header flag out of range"); - return (NULL); - } - - try { - self->cppobj->setHeaderFlag( - static_cast(messageflag), on == Py_True); - Py_RETURN_NONE; - } catch (const InvalidMessageOperation& imo) { - PyErr_Clear(); - PyErr_SetString(po_InvalidMessageOperation, imo.what()); - } catch (const isc::InvalidParameter& ip) { - PyErr_Clear(); - PyErr_SetString(po_InvalidParameter, ip.what()); - } catch (const exception& ex) { - const string ex_what = "Error in Message.set_header_flag(): " + string(ex.what()); - PyErr_SetString(po_IscException, ex_what.c_str()); - } catch (...) { - PyErr_SetString(po_IscException, - "Unexpected exception in Message.set_header_flag()"); - } - return (NULL); -} - -PyObject* -Message_getQid(s_Message* self) { - return (Py_BuildValue("I", self->cppobj->getQid())); -} - -PyObject* -Message_setQid(s_Message* self, PyObject* args) { - long id; - if (!PyArg_ParseTuple(args, "l", &id)) { - PyErr_Clear(); - PyErr_SetString(PyExc_TypeError, - "no valid type in set_qid argument"); - return (NULL); - } - if (id < 0 || id > 0xffff) { - PyErr_SetString(PyExc_ValueError, - "Message id out of range"); - return (NULL); - } - - try { - self->cppobj->setQid(id); - Py_RETURN_NONE; - } catch (const InvalidMessageOperation& imo) { - PyErr_SetString(po_InvalidMessageOperation, imo.what()); - } catch (const exception& ex) { - const string ex_what = "Error in Message.get_qid(): " + string(ex.what()); - PyErr_SetString(po_IscException, ex_what.c_str()); - } catch (...) { - PyErr_SetString(po_IscException, - "Unexpected exception in Message.set_qid()"); - } - return (NULL); -} - -PyObject* -Message_getRcode(s_Message* self) { - try { - return (createRcodeObject(self->cppobj->getRcode())); - } catch (const InvalidMessageOperation& imo) { - PyErr_SetString(po_InvalidMessageOperation, imo.what()); - } catch (const exception& ex) { - const string ex_what = "Error in Message.get_rcode(): " + string(ex.what()); - PyErr_SetString(po_IscException, ex_what.c_str()); - } catch (...) { - PyErr_SetString(po_IscException, - "Unexpected exception in Message.get_rcode()"); - } - return (NULL); -} - -PyObject* -Message_setRcode(s_Message* self, PyObject* args) { - PyObject* rcode; - if (!PyArg_ParseTuple(args, "O!", &rcode_type, &rcode)) { - return (NULL); - } - try { - self->cppobj->setRcode(PyRcode_ToRcode(rcode)); - Py_RETURN_NONE; - } catch (const InvalidMessageOperation& imo) { - PyErr_SetString(po_InvalidMessageOperation, imo.what()); - } catch (const exception& ex) { - const string ex_what = "Error in Message.set_rcode(): " + string(ex.what()); - PyErr_SetString(po_IscException, ex_what.c_str()); - } catch (...) { - PyErr_SetString(po_IscException, - "Unexpected exception in Message.set_rcode()"); - } - return (NULL); -} - -PyObject* -Message_getOpcode(s_Message* self) { - try { - return (createOpcodeObject(self->cppobj->getOpcode())); - } catch (const InvalidMessageOperation& imo) { - PyErr_SetString(po_InvalidMessageOperation, imo.what()); - } catch (const exception& ex) { - const string ex_what = "Error in Message.get_opcode(): " + string(ex.what()); - PyErr_SetString(po_IscException, ex_what.c_str()); - } catch (...) { - PyErr_SetString(po_IscException, - "Unexpected exception in Message.get_opcode()"); - } - return (NULL); -} - -PyObject* -Message_setOpcode(s_Message* self, PyObject* args) { - PyObject* opcode; - if (!PyArg_ParseTuple(args, "O!", &opcode_type, &opcode)) { - return (NULL); - } - try { - self->cppobj->setOpcode(PyOpcode_ToOpcode(opcode)); - Py_RETURN_NONE; - } catch (const InvalidMessageOperation& imo) { - PyErr_SetString(po_InvalidMessageOperation, imo.what()); - } catch (const exception& ex) { - const string ex_what = "Error in Message.set_opcode(): " + string(ex.what()); - PyErr_SetString(po_IscException, ex_what.c_str()); - } catch (...) { - PyErr_SetString(po_IscException, - "Unexpected exception in Message.set_opcode()"); - } - return (NULL); -} - -PyObject* -Message_getEDNS(s_Message* self) { - ConstEDNSPtr src = self->cppobj->getEDNS(); - if (!src) { - Py_RETURN_NONE; - } - try { - return (createEDNSObject(*src)); - } catch (const exception& ex) { - const string ex_what = "Error in Message.get_edns(): " + string(ex.what()); - PyErr_SetString(po_IscException, ex_what.c_str()); - } catch (...) { - PyErr_SetString(PyExc_SystemError, - "Unexpected exception in Message.get_edns()"); - } - return (NULL); -} - -PyObject* -Message_setEDNS(s_Message* self, PyObject* args) { - PyObject* edns; - if (!PyArg_ParseTuple(args, "O!", &edns_type, &edns)) { - return (NULL); - } - try { - self->cppobj->setEDNS(EDNSPtr(new EDNS(PyEDNS_ToEDNS(edns)))); - Py_RETURN_NONE; - } catch (const InvalidMessageOperation& imo) { - PyErr_SetString(po_InvalidMessageOperation, imo.what()); - } catch (const exception& ex) { - const string ex_what = "Error in Message.set_edns(): " + string(ex.what()); - PyErr_SetString(po_IscException, ex_what.c_str()); - } catch (...) { - PyErr_SetString(po_IscException, - "Unexpected exception in Message.set_edns()"); - } - return (NULL); -} - -PyObject* -Message_getTSIGRecord(s_Message* self) { - try { - const TSIGRecord* tsig_record = self->cppobj->getTSIGRecord(); - - if (tsig_record == NULL) { - Py_RETURN_NONE; - } else { - return (createTSIGRecordObject(*tsig_record)); - } - } catch (const InvalidMessageOperation& ex) { - PyErr_SetString(po_InvalidMessageOperation, ex.what()); - } catch (const exception& ex) { - const string ex_what = "Error in Message.get_tsig_record(): " + string(ex.what()); - PyErr_SetString(po_IscException, ex_what.c_str()); - } catch (...) { - PyErr_SetString(po_IscException, - "Unexpected exception in Message.get_tsig_record()"); - } - return (NULL); -} - -PyObject* -Message_getRRCount(s_Message* self, PyObject* args) { - unsigned int section; - if (!PyArg_ParseTuple(args, "I", §ion)) { - PyErr_Clear(); - PyErr_SetString(PyExc_TypeError, - "no valid type in get_rr_count argument"); - return (NULL); - } - try { - return (Py_BuildValue("I", self->cppobj->getRRCount( - static_cast(section)))); - } catch (const isc::OutOfRange& ex) { - PyErr_SetString(PyExc_OverflowError, ex.what()); - } catch (const exception& ex) { - const string ex_what = "Error in Message.get_rr_count(): " + string(ex.what()); - PyErr_SetString(po_IscException, ex_what.c_str()); - } catch (...) { - PyErr_SetString(po_IscException, - "Unexpected exception in Message.get_rr_count()"); - } - return (NULL); -} - -// This is a helper templated class commonly used for getQuestion and -// getSection in order to build a list of Message section items. -template -class SectionInserter { - typedef PyObject* (*creator_t)(const CreatorParamType&); -public: - SectionInserter(PyObject* pylist, creator_t creator) : - pylist_(pylist), creator_(creator) - {} - void operator()(ItemType item) { - if (PyList_Append(pylist_, PyObjectContainer(creator_(*item)).get()) - == -1) { - isc_throw(PyCPPWrapperException, "PyList_Append failed, " - "probably due to short memory"); - } - } -private: - PyObject* pylist_; - creator_t creator_; -}; - -typedef SectionInserter QuestionInserter; -typedef SectionInserter RRsetInserter; - -// TODO use direct iterators for these? (or simply lists for now?) -PyObject* -Message_getQuestion(PyObject* po_self, PyObject*) { - const s_Message* const self = static_cast(po_self); - - try { - PyObjectContainer list_container(PyList_New(0)); - for_each(self->cppobj->beginQuestion(), - self->cppobj->endQuestion(), - QuestionInserter(list_container.get(), createQuestionObject)); - return (list_container.release()); - } catch (const InvalidMessageSection& ex) { - PyErr_SetString(po_InvalidMessageSection, ex.what()); - } catch (const exception& ex) { - const string ex_what = "Error in Message.get_question(): " + string(ex.what()); - PyErr_SetString(po_IscException, ex_what.c_str()); - } catch (...) { - PyErr_SetString(po_IscException, - "Unexpected exception in Message.get_question()"); - } - return (NULL); -} - -PyObject* -Message_getSection(PyObject* po_self, PyObject* args) { - const s_Message* const self = static_cast(po_self); - - unsigned int section; - if (!PyArg_ParseTuple(args, "I", §ion)) { - PyErr_Clear(); - PyErr_SetString(PyExc_TypeError, - "no valid type in get_section argument"); - return (NULL); - } - - try { - PyObjectContainer list_container(PyList_New(0)); - const Message::Section msgsection = - static_cast(section); - for_each(self->cppobj->beginSection(msgsection), - self->cppobj->endSection(msgsection), - RRsetInserter(list_container.get(), createRRsetObject)); - return (list_container.release()); - } catch (const isc::OutOfRange& ex) { - PyErr_SetString(PyExc_OverflowError, ex.what()); - } catch (const InvalidMessageSection& ex) { - PyErr_SetString(po_InvalidMessageSection, ex.what()); - } catch (const exception& ex) { - const string ex_what = "Error in Message.get_section(): " + string(ex.what()); - PyErr_SetString(po_IscException, ex_what.c_str()); - } catch (...) { - PyErr_SetString(po_IscException, - "Unexpected exception in Message.get_section()"); - } - return (NULL); -} - -//static PyObject* Message_beginQuestion(s_Message* self, PyObject* args); -//static PyObject* Message_endQuestion(s_Message* self, PyObject* args); -//static PyObject* Message_beginSection(s_Message* self, PyObject* args); -//static PyObject* Message_endSection(s_Message* self, PyObject* args); -//static PyObject* Message_addQuestion(s_Message* self, PyObject* args); -PyObject* -Message_addQuestion(s_Message* self, PyObject* args) { - PyObject* question; - - if (!PyArg_ParseTuple(args, "O!", &question_type, &question)) { - return (NULL); - } - - try { - self->cppobj->addQuestion(PyQuestion_ToQuestion(question)); - Py_RETURN_NONE; - } catch (const InvalidMessageOperation& imo) { - PyErr_Clear(); - PyErr_SetString(po_InvalidMessageOperation, imo.what()); - } catch (const exception& ex) { - const string ex_what = "Error in Message.add_question(): " + string(ex.what()); - PyErr_SetString(po_IscException, ex_what.c_str()); - } catch (...) { - PyErr_SetString(po_IscException, - "Unexpected exception in Message.add_question()"); - } - return (NULL); -} - -PyObject* -Message_addRRset(s_Message* self, PyObject* args) { - int section; - PyObject* rrset; - if (!PyArg_ParseTuple(args, "iO!", §ion, &rrset_type, &rrset)) { - return (NULL); - } - - try { - self->cppobj->addRRset(static_cast(section), - PyRRset_ToRRsetPtr(rrset)); - Py_RETURN_NONE; - } catch (const InvalidMessageOperation& imo) { - PyErr_SetString(po_InvalidMessageOperation, imo.what()); - } catch (const isc::OutOfRange& ex) { - PyErr_SetString(PyExc_OverflowError, ex.what()); - } catch (const exception& ex) { - const string ex_what = "Error in Message.add_rrset(): " + string(ex.what()); - PyErr_SetString(po_IscException, ex_what.c_str()); - } catch (...) { - PyErr_SetString(po_IscException, - "Unexpected exception in Message.add_rrset()"); - } - return (NULL); -} - -PyObject* -Message_clear(s_Message* self, PyObject* args) { - int i; - - try { - if (PyArg_ParseTuple(args, "i", &i)) { - PyErr_Clear(); - if (i == Message::PARSE) { - self->cppobj->clear(Message::PARSE); - Py_RETURN_NONE; - } else if (i == Message::RENDER) { - self->cppobj->clear(Message::RENDER); - Py_RETURN_NONE; - } else { - PyErr_SetString(PyExc_TypeError, - "Message mode must be Message.PARSE or Message.RENDER"); - return (NULL); - } - } - } catch (const exception& ex) { - const string ex_what = "Error in Message.clear(): " + string(ex.what()); - PyErr_SetString(po_IscException, ex_what.c_str()); - } catch (...) { - PyErr_SetString(po_IscException, - "Unexpected exception in Message.clear()"); - } - return (NULL); -} - -PyObject* -Message_clearSection(PyObject* pyself, PyObject* args) { - s_Message* const self = static_cast(pyself); - int section; - - if (!PyArg_ParseTuple(args, "i", §ion)) { - return (NULL); - } - try { - self->cppobj->clearSection(static_cast(section)); - Py_RETURN_NONE; - } catch (const InvalidMessageOperation& imo) { - PyErr_SetString(po_InvalidMessageOperation, imo.what()); - } catch (const isc::OutOfRange& ex) { - PyErr_SetString(PyExc_OverflowError, ex.what()); - } catch (const exception& ex) { - const string ex_what = "Error in Message.clear_section(): " + string(ex.what()); - PyErr_SetString(po_IscException, ex_what.c_str()); - } catch (...) { - PyErr_SetString(po_IscException, - "Unexpected exception in Message.clear_section()"); - } - return (NULL); -} - -PyObject* -Message_makeResponse(s_Message* self) { - try { - self->cppobj->makeResponse(); - Py_RETURN_NONE; - } catch (const InvalidMessageOperation& imo) { - PyErr_Clear(); - PyErr_SetString(po_InvalidMessageOperation, imo.what()); - } catch (const exception& ex) { - const string ex_what = "Error in Message.make_response(): " + string(ex.what()); - PyErr_SetString(po_IscException, ex_what.c_str()); - } catch (...) { - PyErr_SetString(po_IscException, - "Unexpected exception in Message.make_response()"); - } - return (NULL); -} - -PyObject* -Message_toText(s_Message* self) { - // Py_BuildValue makes python objects from native data - try { - return (Py_BuildValue("s", self->cppobj->toText().c_str())); - } catch (const InvalidMessageOperation& imo) { - PyErr_Clear(); - PyErr_SetString(po_InvalidMessageOperation, imo.what()); - } catch (const exception& ex) { - const string ex_what = "Error in Message.to_text(): " + string(ex.what()); - PyErr_SetString(po_IscException, ex_what.c_str()); - } catch (...) { - PyErr_SetString(po_IscException, - "Unexpected exception in Message.to_text()"); - } - return (NULL); -} - -PyObject* -Message_str(PyObject* self) { - // Simply call the to_text method we already defined - return (PyObject_CallMethod(self, - const_cast("to_text"), - const_cast(""))); -} - -PyObject* -Message_toWire(s_Message* self, PyObject* args) { - PyObject* mr; - PyObject* tsig_ctx = NULL; - - if (PyArg_ParseTuple(args, "O!|O", &messagerenderer_type, &mr, - &tsig_ctx)) { - try { - if ((tsig_ctx == NULL) || (tsig_ctx == Py_None)) { - self->cppobj->toWire(PyMessageRenderer_ToMessageRenderer(mr)); - } else { - self->cppobj->toWire(PyMessageRenderer_ToMessageRenderer(mr), - PyTSIGContext_ToTSIGContext(tsig_ctx)); - } - // If we return NULL it is seen as an error, so use this for - // None returns - Py_RETURN_NONE; - } catch (const InvalidMessageOperation& imo) { - PyErr_Clear(); - PyErr_SetString(po_InvalidMessageOperation, imo.what()); - } catch (const TSIGContextError& ex) { - // toWire() with a TSIG context can fail due to this if the - // python program has a bug. - PyErr_SetString(po_TSIGContextError, ex.what()); - } catch (const exception& ex) { - const string ex_what = "Error in Message.to_wire(): " + string(ex.what()); - PyErr_SetString(po_TSIGContextError, ex_what.c_str()); - } catch (...) { - PyErr_SetString(po_IscException, - "Unexpected exception in Message.to_wire()"); - } - return (NULL); - } - PyErr_Clear(); - PyErr_SetString(PyExc_TypeError, - "Bad to_wire() arguments were passed"); - return (NULL); -} - -PyObject* -Message_fromWire(PyObject* pyself, PyObject* args) { - s_Message* const self = static_cast(pyself); - const char* b; - Py_ssize_t len; - unsigned int options = Message::PARSE_DEFAULT; - - if (PyArg_ParseTuple(args, "y#", &b, &len) || - PyArg_ParseTuple(args, "y#I", &b, &len, &options)) { - // We need to clear the error in case the first call to ParseTuple - // fails. - PyErr_Clear(); - - InputBuffer inbuf(b, len); - try { - self->cppobj->fromWire( - inbuf, static_cast(options)); - Py_RETURN_NONE; - } catch (const InvalidMessageOperation& imo) { - PyErr_SetString(po_InvalidMessageOperation, imo.what()); - } catch (const DNSMessageFORMERR& dmfe) { - PyErr_SetString(po_DNSMessageFORMERR, dmfe.what()); - } catch (const DNSMessageBADVERS& dmfe) { - PyErr_SetString(po_DNSMessageBADVERS, dmfe.what()); - } catch (const MessageTooShort& mts) { - PyErr_SetString(po_MessageTooShort, mts.what()); - } catch (const InvalidBufferPosition& ex) { - PyErr_SetString(po_DNSMessageFORMERR, ex.what()); - } catch (const exception& ex) { - const string ex_what = "Error in Message.from_wire(): " + string(ex.what()); - PyErr_SetString(po_IscException, ex_what.c_str()); - } catch (...) { - PyErr_SetString(po_IscException, - "Unexpected exception in Message.from_wire()"); - } - return (NULL); - } - - PyErr_SetString(PyExc_TypeError, - "from_wire() arguments must be a byte object and " - "(optional) parse options"); - return (NULL); -} - -} // end of unnamed namespace - -namespace isc { -namespace dns { -namespace python { - -// -// Declaration of the custom exceptions -// Initialization and addition of these go in the initModulePart -// function in pydnspp.cc -// -PyObject* po_MessageTooShort; -PyObject* po_InvalidMessageSection; -PyObject* po_InvalidMessageOperation; -PyObject* po_InvalidMessageUDPSize; - -// This defines the complete type for reflection in python and -// parsing of PyObject* to s_Message -// Most of the functions are not actually implemented and NULL here. -PyTypeObject message_type = { - PyVarObject_HEAD_INIT(NULL, 0) - "pydnspp.Message", - sizeof(s_Message), // tp_basicsize - 0, // tp_itemsize - (destructor)Message_destroy, // tp_dealloc - NULL, // tp_print - NULL, // tp_getattr - NULL, // tp_setattr - NULL, // tp_reserved - NULL, // tp_repr - NULL, // tp_as_number - NULL, // tp_as_sequence - NULL, // tp_as_mapping - NULL, // tp_hash - NULL, // tp_call - Message_str, // tp_str - NULL, // tp_getattro - NULL, // tp_setattro - NULL, // tp_as_buffer - Py_TPFLAGS_DEFAULT, // tp_flags - "The Message class encapsulates a standard DNS message.", - NULL, // tp_traverse - NULL, // tp_clear - NULL, // tp_richcompare - 0, // tp_weaklistoffset - NULL, // tp_iter - NULL, // tp_iternext - Message_methods, // tp_methods - NULL, // tp_members - NULL, // tp_getset - NULL, // tp_base - NULL, // tp_dict - NULL, // tp_descr_get - NULL, // tp_descr_set - 0, // tp_dictoffset - (initproc)Message_init, // tp_init - NULL, // tp_alloc - PyType_GenericNew, // tp_new - NULL, // tp_free - NULL, // tp_is_gc - NULL, // tp_bases - NULL, // tp_mro - NULL, // tp_cache - NULL, // tp_subclasses - NULL, // tp_weaklist - NULL, // tp_del - 0 // tp_version_tag -}; - -} // end python namespace -} // end dns namespace -} // end isc namespace diff --git a/src/lib/dns/python/message_python.h b/src/lib/dns/python/message_python.h deleted file mode 100644 index f3c1488e0a..0000000000 --- a/src/lib/dns/python/message_python.h +++ /dev/null @@ -1,40 +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. - -#ifndef PYTHON_MESSAGE_H -#define PYTHON_MESSAGE_H 1 - -#include - -namespace isc { -namespace dns { -class Message; - -namespace python { - -extern PyObject* po_MessageTooShort; -extern PyObject* po_InvalidMessageSection; -extern PyObject* po_InvalidMessageOperation; -extern PyObject* po_InvalidMessageUDPSize; - -extern PyTypeObject message_type; - -} // namespace python -} // namespace dns -} // namespace isc -#endif // PYTHON_MESSAGE_H - -// Local Variables: -// mode: c++ -// End: diff --git a/src/lib/dns/python/message_python_inc.cc b/src/lib/dns/python/message_python_inc.cc deleted file mode 100644 index 5472695fc8..0000000000 --- a/src/lib/dns/python/message_python_inc.cc +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright (C) 2011-2012 Internet Systems Consortium, Inc. ("ISC") -// -// Permission to use, copy, modify, and/or distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -// PERFORMANCE OF THIS SOFTWARE. - -namespace { -const char* const Message_fromWire_doc = "\ -from_wire(data, options=PARSE_DEFAULT)\n\ -\n\ -(Re)build a Message object from wire-format data.\n\ -\n\ -This method parses the given wire format data to build a complete\n\ -Message object. On success, the values of the header section fields\n\ -can be accessible via corresponding get methods, and the question and\n\ -following sections can be accessible via the corresponding iterators.\n\ -If the message contains an EDNS or TSIG, they can be accessible via\n\ -get_edns() and get_tsig_record(), respectively.\n\ -\n\ -This Message must be in the PARSE mode.\n\ -\n\ -This method performs strict validation on the given message based on\n\ -the DNS protocol specifications. If the given message data is invalid,\n\ -this method throws an exception (see the exception list).\n\ -\n\ -By default, this method combines RRs of the same name, RR type and RR\n\ -class in a section into a single RRset, even if they are interleaved\n\ -with a different type of RR (though it would be a rare case in\n\ -practice). If the PRESERVE_ORDER option is specified, it handles each\n\ -RR separately, in the appearing order, and converts it to a separate\n\ -RRset (so this RRset should contain exactly one Rdata). This mode will\n\ -be necessary when the higher level protocol is ordering conscious. For\n\ -example, in AXFR and IXFR, the position of the SOA RRs are crucial.\n\ -\n\ -Exceptions:\n\ - InvalidMessageOperation Message is in the RENDER mode\n\ - DNSMessageFORMERR The given message data is syntactically\n\ - MessageTooShort The given data is shorter than a valid header\n\ - section\n\ - Others Name, Rdata, and EDNS classes can also throw\n\ -\n\ -Parameters:\n\ - data A byte object of the wire data\n\ - options Parse options\n\ -\n\ -"; - -const char* const Message_clearSection_doc = "\ -clear_section(section) -> void\n\ -\n\ -Remove all RRSets from the given Section.\n\ -\n\ -This method is only allowed in the RENDER mode, and the given section\n\ -must be valid.\n\ -\n\ -Exceptions:\n\ - InvalidMessageOperation Message is not in the RENDER mode\n\ - OverflowError The specified section is not valid\n\ -\n\ -Parameters:\n\ - section Section to remove all rrsets from\n\ -\n\ -"; -} // unnamed namespace diff --git a/src/lib/dns/python/messagerenderer_python.cc b/src/lib/dns/python/messagerenderer_python.cc deleted file mode 100644 index 5561c12c34..0000000000 --- a/src/lib/dns/python/messagerenderer_python.cc +++ /dev/null @@ -1,263 +0,0 @@ -// Copyright (C) 2010 Internet Systems Consortium, Inc. ("ISC") -// -// Permission to use, copy, modify, and/or distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -// PERFORMANCE OF THIS SOFTWARE. - -#include - -#include - -#include -#include - -#include "pydnspp_common.h" -#include "messagerenderer_python.h" - -using namespace isc::dns; -using namespace isc::dns::python; -using namespace isc::util; -using namespace isc::util::python; - -namespace { -// The s_* Class simply covers one instantiation of the object. -// -// since we don't use *Buffer in the python version (but work with -// the already existing bytearray type where we use these custom buffers -// in C++, we need to keep track of one here. -class s_MessageRenderer : public PyObject { -public: - s_MessageRenderer(); - MessageRenderer* cppobj; -}; - -int MessageRenderer_init(s_MessageRenderer* self); -void MessageRenderer_destroy(s_MessageRenderer* self); - -PyObject* MessageRenderer_getData(s_MessageRenderer* self); -PyObject* MessageRenderer_getLength(s_MessageRenderer* self); -PyObject* MessageRenderer_isTruncated(s_MessageRenderer* self); -PyObject* MessageRenderer_getLengthLimit(s_MessageRenderer* self); -PyObject* MessageRenderer_getCompressMode(s_MessageRenderer* self); -PyObject* MessageRenderer_setTruncated(s_MessageRenderer* self); -PyObject* MessageRenderer_setLengthLimit(s_MessageRenderer* self, PyObject* args); -PyObject* MessageRenderer_setCompressMode(s_MessageRenderer* self, PyObject* args); -PyObject* MessageRenderer_clear(s_MessageRenderer* self); - -PyMethodDef MessageRenderer_methods[] = { - { "get_data", reinterpret_cast(MessageRenderer_getData), METH_NOARGS, - "Returns the data as a bytes() object" }, - { "get_length", reinterpret_cast(MessageRenderer_getLength), METH_NOARGS, - "Returns the length of the data" }, - { "is_truncated", reinterpret_cast(MessageRenderer_isTruncated), METH_NOARGS, - "Returns True if the data is truncated" }, - { "get_length_limit", reinterpret_cast(MessageRenderer_getLengthLimit), METH_NOARGS, - "Returns the length limit of the data" }, - { "get_compress_mode", reinterpret_cast(MessageRenderer_getCompressMode), METH_NOARGS, - "Returns the current compression mode" }, - { "set_truncated", reinterpret_cast(MessageRenderer_setTruncated), METH_NOARGS, - "Sets truncated to true" }, - { "set_length_limit", reinterpret_cast(MessageRenderer_setLengthLimit), METH_VARARGS, - "Sets the length limit of the data to the given number" }, - { "set_compress_mode", reinterpret_cast(MessageRenderer_setCompressMode), METH_VARARGS, - "Sets the compression mode of the MessageRenderer" }, - { "clear", reinterpret_cast(MessageRenderer_clear), - METH_NOARGS, - "Clear the internal buffer and other internal resources." }, - { NULL, NULL, 0, NULL } -}; - -int -MessageRenderer_init(s_MessageRenderer* self) { - self->cppobj = new MessageRenderer; - return (0); -} - -void -MessageRenderer_destroy(s_MessageRenderer* self) { - delete self->cppobj; - self->cppobj = NULL; - Py_TYPE(self)->tp_free(self); -} - -PyObject* -MessageRenderer_getData(s_MessageRenderer* self) { - return (Py_BuildValue("y#", - self->cppobj->getData(), - self->cppobj->getLength())); -} - -PyObject* -MessageRenderer_getLength(s_MessageRenderer* self) { - return (Py_BuildValue("I", self->cppobj->getLength())); -} - -PyObject* -MessageRenderer_isTruncated(s_MessageRenderer* self) { - if (self->cppobj->isTruncated()) { - Py_RETURN_TRUE; - } else { - Py_RETURN_FALSE; - } -} - -PyObject* -MessageRenderer_getLengthLimit(s_MessageRenderer* self) { - return (Py_BuildValue("I", self->cppobj->getLengthLimit())); -} - -PyObject* -MessageRenderer_getCompressMode(s_MessageRenderer* self) { - return (Py_BuildValue("I", self->cppobj->getCompressMode())); -} - -PyObject* -MessageRenderer_setTruncated(s_MessageRenderer* self) { - self->cppobj->setTruncated(); - Py_RETURN_NONE; -} - -PyObject* -MessageRenderer_setLengthLimit(s_MessageRenderer* self, - PyObject* args) -{ - long lengthlimit; - if (!PyArg_ParseTuple(args, "l", &lengthlimit)) { - PyErr_Clear(); - PyErr_SetString(PyExc_TypeError, - "No valid type in set_length_limit argument"); - return (NULL); - } - if (lengthlimit < 0) { - PyErr_SetString(PyExc_ValueError, - "MessageRenderer length limit out of range"); - return (NULL); - } - self->cppobj->setLengthLimit(lengthlimit); - Py_RETURN_NONE; -} - -PyObject* -MessageRenderer_setCompressMode(s_MessageRenderer* self, - PyObject* args) -{ - int mode; - if (!PyArg_ParseTuple(args, "i", &mode)) { - return (NULL); - } - - if (mode == MessageRenderer::CASE_INSENSITIVE) { - self->cppobj->setCompressMode(MessageRenderer::CASE_INSENSITIVE); - // If we return NULL it is seen as an error, so use this for - // None returns, it also applies to CASE_SENSITIVE. - Py_RETURN_NONE; - } else if (mode == MessageRenderer::CASE_SENSITIVE) { - self->cppobj->setCompressMode(MessageRenderer::CASE_SENSITIVE); - Py_RETURN_NONE; - } else { - PyErr_SetString(PyExc_TypeError, - "MessageRenderer compress mode must be MessageRenderer.CASE_INSENSITIVE" - "or MessageRenderer.CASE_SENSITIVE"); - return (NULL); - } -} - -PyObject* -MessageRenderer_clear(s_MessageRenderer* self) { - self->cppobj->clear(); - Py_RETURN_NONE; -} -} // end of unnamed namespace - -namespace isc { -namespace dns { -namespace python { -PyTypeObject messagerenderer_type = { - PyVarObject_HEAD_INIT(NULL, 0) - "pydnspp.MessageRenderer", - sizeof(s_MessageRenderer), // tp_basicsize - 0, // tp_itemsize - (destructor)MessageRenderer_destroy,// tp_dealloc - NULL, // tp_print - NULL, // tp_getattr - NULL, // tp_setattr - NULL, // tp_reserved - NULL, // tp_repr - NULL, // tp_as_number - NULL, // tp_as_sequence - NULL, // tp_as_mapping - NULL, // tp_hash - NULL, // tp_call - NULL, // tp_str - NULL, // tp_getattro - NULL, // tp_setattro - NULL, // tp_as_buffer - Py_TPFLAGS_DEFAULT, // tp_flags - "The MessageRenderer class encapsulates implementation details " - "of rendering a DNS message into a buffer in wire format. " - "In effect, it's simply responsible for name compression at least in the " - "current implementation. A MessageRenderer class object manages the " - "positions of names rendered in a buffer and uses that information to render " - "subsequent names with compression.", - NULL, // tp_traverse - NULL, // tp_clear - NULL, // tp_richcompare - 0, // tp_weaklistoffset - NULL, // tp_iter - NULL, // tp_iternext - MessageRenderer_methods, // tp_methods - NULL, // tp_members - NULL, // tp_getset - NULL, // tp_base - NULL, // tp_dict - NULL, // tp_descr_get - NULL, // tp_descr_set - 0, // tp_dictoffset - (initproc)MessageRenderer_init, // tp_init - NULL, // tp_alloc - PyType_GenericNew, // tp_new - NULL, // tp_free - NULL, // tp_is_gc - NULL, // tp_bases - NULL, // tp_mro - NULL, // tp_cache - NULL, // tp_subclasses - NULL, // tp_weaklist - NULL, // tp_del - 0 // tp_version_tag -}; - -// If we need a createMessageRendererObject(), should we copy? can we? -// copy the existing buffer into a new one, then create a new renderer with -// that buffer? - -bool -PyMessageRenderer_Check(PyObject* obj) { - if (obj == NULL) { - isc_throw(PyCPPWrapperException, "obj argument NULL in typecheck"); - } - return (PyObject_TypeCheck(obj, &messagerenderer_type)); -} - -MessageRenderer& -PyMessageRenderer_ToMessageRenderer(PyObject* messagerenderer_obj) { - if (messagerenderer_obj == NULL) { - isc_throw(PyCPPWrapperException, - "obj argument NULL in MessageRenderer PyObject conversion"); - } - s_MessageRenderer* messagerenderer = static_cast(messagerenderer_obj); - return (*messagerenderer->cppobj); -} - - -} // namespace python -} // namespace dns -} // namespace isc diff --git a/src/lib/dns/python/messagerenderer_python.h b/src/lib/dns/python/messagerenderer_python.h deleted file mode 100644 index f6ea922745..0000000000 --- a/src/lib/dns/python/messagerenderer_python.h +++ /dev/null @@ -1,57 +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. - -#ifndef PYTHON_MESSAGERENDERER_H -#define PYTHON_MESSAGERENDERER_H 1 - -#include - -#include - -namespace isc { -namespace dns { -class MessageRenderer; - -namespace python { - -extern PyTypeObject messagerenderer_type; - -/// \brief Checks if the given python object is a MessageRenderer object -/// -/// \exception PyCPPWrapperException if obj is NULL -/// -/// \param obj The object to check the type of -/// \return true if the object is of type MessageRenderer, false otherwise -bool PyMessageRenderer_Check(PyObject* obj); - -/// \brief Returns a reference to the MessageRenderer object contained within the given -/// Python object. -/// -/// \note The given object MUST be of type MessageRenderer; this can be checked with -/// either the right call to ParseTuple("O!"), or with PyMessageRenderer_Check() -/// -/// \note This is not a copy; if the MessageRenderer is needed when the PyObject -/// may be destroyed, the caller must copy it itself. -/// -/// \param messagerenderer_obj The messagerenderer object to convert -MessageRenderer& PyMessageRenderer_ToMessageRenderer(PyObject* messagerenderer_obj); - -} // namespace python -} // namespace dns -} // namespace isc -#endif // PYTHON_MESSAGERENDERER_H - -// Local Variables: -// mode: c++ -// End: diff --git a/src/lib/dns/python/name_python.cc b/src/lib/dns/python/name_python.cc deleted file mode 100644 index ecdae841c3..0000000000 --- a/src/lib/dns/python/name_python.cc +++ /dev/null @@ -1,695 +0,0 @@ -// Copyright (C) 2010 Internet Systems Consortium, Inc. ("ISC") -// -// Permission to use, copy, modify, and/or distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -// PERFORMANCE OF THIS SOFTWARE. - -#include - -#include -#include - -#include -#include -#include -#include - -#include "pydnspp_common.h" -#include "messagerenderer_python.h" -#include "name_python.h" - -#include - -using namespace isc::dns; -using namespace isc::dns::python; -using namespace isc::util; -using namespace isc::util::python; - -namespace { -// The s_* Class simply covers one instantiation of the object. -class s_NameComparisonResult : public PyObject { -public: - s_NameComparisonResult() : cppobj(NULL) {} - NameComparisonResult* cppobj; -}; - -class s_Name : public PyObject { -public: - s_Name() : cppobj(NULL), position(0) {} - Name* cppobj; - size_t position; -}; - -int NameComparisonResult_init(s_NameComparisonResult*, PyObject*); -void NameComparisonResult_destroy(s_NameComparisonResult* self); -PyObject* NameComparisonResult_getOrder(s_NameComparisonResult* self); -PyObject* NameComparisonResult_getCommonLabels(s_NameComparisonResult* self); -PyObject* NameComparisonResult_getRelation(s_NameComparisonResult* self); - -PyMethodDef NameComparisonResult_methods[] = { - { "get_order", reinterpret_cast(NameComparisonResult_getOrder), METH_NOARGS, - "Returns the order" }, - { "get_common_labels", reinterpret_cast(NameComparisonResult_getCommonLabels), METH_NOARGS, - "Returns the number of common labels" }, - { "get_relation", reinterpret_cast(NameComparisonResult_getRelation), METH_NOARGS, - "Returns the relation" }, - { NULL, NULL, 0, NULL } -}; - -int -NameComparisonResult_init(s_NameComparisonResult*, PyObject*) { - PyErr_SetString(PyExc_NotImplementedError, - "NameComparisonResult can't be built directly"); - return (-1); -} - -void -NameComparisonResult_destroy(s_NameComparisonResult* self) { - delete self->cppobj; - self->cppobj = NULL; - Py_TYPE(self)->tp_free(self); -} - -PyObject* -NameComparisonResult_getOrder(s_NameComparisonResult* self) { - return (Py_BuildValue("i", self->cppobj->getOrder())); -} - -PyObject* -NameComparisonResult_getCommonLabels(s_NameComparisonResult* self) { - return (Py_BuildValue("I", self->cppobj->getCommonLabels())); -} - -PyObject* -NameComparisonResult_getRelation(s_NameComparisonResult* self) { - return (Py_BuildValue("I", self->cppobj->getRelation())); -} - -// Shortcut type which would be convenient for adding class variables safely. -typedef CPPPyObjectContainer NameContainer; - -int Name_init(s_Name* self, PyObject* args); -void Name_destroy(s_Name* self); - -PyObject* Name_toWire(s_Name* self, PyObject* args); -PyObject* Name_toText(s_Name* self, PyObject* args); -PyObject* Name_str(PyObject* self); -PyObject* Name_getLabelCount(s_Name* self); -PyObject* Name_at(s_Name* self, PyObject* args); -PyObject* Name_getLength(s_Name* self); - -PyObject* Name_compare(s_Name* self, PyObject* args); -PyObject* Name_equals(s_Name* self, PyObject* args); - -PyObject* Name_richcmp(s_Name* self, s_Name* other, int op); -PyObject* Name_split(s_Name* self, PyObject* args); -PyObject* Name_reverse(s_Name* self); -PyObject* Name_concatenate(s_Name* self, PyObject* args); -PyObject* Name_downcase(s_Name* self); -PyObject* Name_isWildCard(s_Name* self); -Py_hash_t Name_hash(PyObject* py_self); - -PyMethodDef Name_methods[] = { - { "at", reinterpret_cast(Name_at), METH_VARARGS, - "Returns the integer value of the name data at the specified position" }, - { "get_length", reinterpret_cast(Name_getLength), METH_NOARGS, - "Returns the length" }, - { "get_labelcount", reinterpret_cast(Name_getLabelCount), METH_NOARGS, - "Returns the number of labels" }, - { "to_text", reinterpret_cast(Name_toText), METH_VARARGS, - "Returns the string representation. The optional argument must be either" - "True of False. If True, the final dot will be omitted." }, - { "to_wire", reinterpret_cast(Name_toWire), METH_VARARGS, - "Converts the Name object to wire format.\n" - "The argument can be either a MessageRenderer or an object that " - "implements the sequence interface. If the object is mutable " - "(for instance a bytearray()), the wire data is added in-place.\n" - "If it is not (for instance a bytes() object), a new object is " - "returned" }, - { "compare", reinterpret_cast(Name_compare), METH_VARARGS, - "Returns a NameComparisonResult object. The argument must be another Name object" }, - { "equals", reinterpret_cast(Name_equals), METH_VARARGS, - "Returns true if the given Name object is equal to this one" }, - { "split", reinterpret_cast(Name_split), METH_VARARGS, - "Splits the name, takes two arguments, the first is an integer " - "specifying the first label to place in the result. The second " - "is an integer specifying the number of labels to put in the " - "result. Returns a new Name object" }, - { "reverse", reinterpret_cast(Name_reverse), METH_NOARGS, - "Returns a new Name object that is the reverse of this one" }, - { "concatenate", reinterpret_cast(Name_concatenate), METH_VARARGS, - "Concatenates the given Name object to this one and returns the " - "result as a new Name object" }, - { "downcase", reinterpret_cast(Name_downcase), METH_NOARGS, - "Downcases this name object (in-place). Returns a new reference to the Name." }, - { "is_wildcard", reinterpret_cast(Name_isWildCard), METH_NOARGS, - "Returns True if the Name object represents a wildcard name." }, - { NULL, NULL, 0, NULL } -}; - -int -Name_init(s_Name* self, PyObject* args) { - const char* s; - PyObject* downcase = Py_False; - - // Depending on the arguments in *args, we decide which of the - // constructors is meant. If the first argument is of type string, - // we use the string-based constructor. If it is a bytes object, - // we use the wire-based one. - if (PyArg_ParseTuple(args, "s|O!", &s, &PyBool_Type, &downcase)) { - try { - const std::string n(s); - - self->cppobj = new Name(n, downcase == Py_True); - self->position = 0; - } catch (const EmptyLabel&) { - PyErr_SetString(po_EmptyLabel, "EmptyLabel"); - return (-1); - } catch (const TooLongLabel&) { - PyErr_SetString(po_TooLongLabel, "TooLongLabel"); - return (-1); - } catch (const BadLabelType&) { - PyErr_SetString(po_BadLabelType, "BadLabelType"); - return (-1); - } catch (const BadEscape&) { - PyErr_SetString(po_BadEscape, "BadEscape"); - return (-1); - } catch (const TooLongName&) { - PyErr_SetString(po_TooLongName, "TooLongName"); - return (-1); - } catch (const IncompleteName&) { - PyErr_SetString(po_IncompleteName, "IncompleteName"); - return (-1); -#ifdef CATCHMEMERR - } catch (const std::bad_alloc&) { - PyErr_NoMemory(); - return (-1); -#endif - } catch (...) { - PyErr_SetString(po_IscException, "Unexpected?!"); - return (-1); - } - return (0); - } - PyErr_Clear(); - - PyObject* bytes_obj; - const char* bytes; - Py_ssize_t len; - long position = 0; - - // It was not a string (see comment above), so try bytes, and - // create with buffer object - if (PyArg_ParseTuple(args, "O|lO!", &bytes_obj, &position, - &PyBool_Type, &downcase) && - PyObject_AsCharBuffer(bytes_obj, &bytes, &len) != -1) { - try { - if (position < 0) { - // Throw IndexError here since name index should be unsigned - PyErr_SetString(PyExc_IndexError, - "Name index shouldn't be negative"); - return (-1); - } - InputBuffer buffer(bytes, len); - - buffer.setPosition(position); - self->cppobj = new Name(buffer, downcase == Py_True); - self->position = buffer.getPosition(); - } catch (const InvalidBufferPosition&) { - PyErr_SetString(po_InvalidBufferPosition, - "InvalidBufferPosition"); - return (-1); - } catch (const DNSMessageFORMERR&) { - PyErr_SetString(po_DNSMessageFORMERR, "DNSMessageFORMERR"); - return (-1); - } catch (...) { - PyErr_SetString(po_IscException, "Unexpected?!"); - return (-1); - } - return (0); - } - - PyErr_Clear(); - PyErr_SetString(PyExc_TypeError, - "No valid types in Name constructor (should be string or sequence and offset"); - return (-1); -} - -void -Name_destroy(s_Name* self) { - delete self->cppobj; - self->cppobj = NULL; - Py_TYPE(self)->tp_free(self); -} - -PyObject* -Name_at(s_Name* self, PyObject* args) { - int pos; - if (!PyArg_ParseTuple(args, "i", &pos)) { - return (NULL); - } - if (pos < 0) { - // Throw IndexError here since name index should be unsigned - PyErr_SetString(PyExc_IndexError, - "name index shouldn't be negative"); - return (NULL); - } - - try { - return (Py_BuildValue("I", self->cppobj->at(pos))); - } catch (const isc::OutOfRange&) { - PyErr_SetString(PyExc_IndexError, - "name index out of range"); - return (NULL); - } -} - -PyObject* -Name_getLength(s_Name* self) { - return (Py_BuildValue("i", self->cppobj->getLength())); -} - -PyObject* -Name_getLabelCount(s_Name* self) { - return (Py_BuildValue("i", self->cppobj->getLabelCount())); -} - -PyObject* -Name_toText(s_Name* self, PyObject* args) { - PyObject* omit_final_dot_obj = NULL; - if (PyArg_ParseTuple(args, "|O", &omit_final_dot_obj)) { - bool omit_final_dot = false; - if (omit_final_dot_obj != NULL) { - if (PyBool_Check(omit_final_dot_obj) != 0) { - omit_final_dot = (omit_final_dot_obj == Py_True); - } else { - PyErr_SetString(PyExc_TypeError, - "Optional argument 1 of to_text() should be True of False"); - return (NULL); - } - } - return (Py_BuildValue("s", - self->cppobj->toText(omit_final_dot).c_str())); - } else { - return (NULL); - } -} - -PyObject* -Name_str(PyObject* self) { - // Simply call the to_text method we already defined - // str() is not defined in the c++ version, only to_text - // and we already have a wrapper for that one. - return (PyObject_CallMethod(self, - const_cast("to_text"), - const_cast(""))); -} - -PyObject* -Name_toWire(s_Name* self, PyObject* args) { - PyObject* bytes; - PyObject* mr; - - if (PyArg_ParseTuple(args, "O", &bytes) && PySequence_Check(bytes)) { - PyObject* bytes_o = bytes; - - OutputBuffer buffer(Name::MAX_WIRE); - self->cppobj->toWire(buffer); - PyObject* name_bytes = PyBytes_FromStringAndSize(static_cast(buffer.getData()), buffer.getLength()); - PyObject* result = PySequence_InPlaceConcat(bytes_o, name_bytes); - // We need to release the object we temporarily created here - // to prevent memory leak - Py_DECREF(name_bytes); - return (result); - } else if (PyArg_ParseTuple(args, "O!", &messagerenderer_type, &mr)) { - self->cppobj->toWire(PyMessageRenderer_ToMessageRenderer(mr)); - // If we return NULL it is seen as an error, so use this for - // None returns - Py_RETURN_NONE; - } - PyErr_Clear(); - PyErr_SetString(PyExc_TypeError, - "toWire argument must be a sequence object or a MessageRenderer"); - return (NULL); -} - -PyObject* -Name_compare(s_Name* self, PyObject* args) { - s_Name* other; - - if (!PyArg_ParseTuple(args, "O!", &name_type, &other)) - return (NULL); - - s_NameComparisonResult* ret = PyObject_New(s_NameComparisonResult, &name_comparison_result_type); - if (ret != NULL) { - ret->cppobj = new NameComparisonResult( - self->cppobj->compare(*other->cppobj)); - } - return (ret); -} - -PyObject* -Name_equals(s_Name* self, PyObject* args) { - s_Name* other; - - if (!PyArg_ParseTuple(args, "O!", &name_type, &other)) - return (NULL); - - if (self->cppobj->equals(*other->cppobj)) - Py_RETURN_TRUE; - else - Py_RETURN_FALSE; -} - -PyObject* -Name_split(s_Name* self, PyObject* args) { - int first, n; - s_Name* ret = NULL; - - if (PyArg_ParseTuple(args, "ii", &first, &n)) { - if (first < 0 || n < 0) { - // Throw IndexError here since name index should be unsigned - PyErr_SetString(PyExc_IndexError, - "name index shouldn't be negative"); - return (NULL); - } - ret = PyObject_New(s_Name, &name_type); - if (ret != NULL) { - ret->cppobj = NULL; - try { - ret->cppobj = new Name(self->cppobj->split(first, n)); - } catch (const isc::OutOfRange& oor) { - PyErr_SetString(PyExc_IndexError, oor.what()); - ret->cppobj = NULL; - } - if (ret->cppobj == NULL) { - Py_DECREF(ret); - return (NULL); - } - } - } else if (PyArg_ParseTuple(args, "i", &n)) { - PyErr_Clear(); - if (n < 0) { - // Throw IndexError here since name index should be unsigned - PyErr_SetString(PyExc_IndexError, - "name index shouldn't be negative"); - return (NULL); - } - ret = PyObject_New(s_Name, &name_type); - if (ret != NULL) { - ret->cppobj = NULL; - try { - ret->cppobj = new Name(self->cppobj->split(n)); - } catch (const isc::OutOfRange& oor) { - PyErr_SetString(PyExc_IndexError, oor.what()); - ret->cppobj = NULL; - } - if (ret->cppobj == NULL) { - Py_DECREF(ret); - return (NULL); - } - } - } else { - PyErr_Clear(); - PyErr_SetString(PyExc_TypeError, "No valid type in split argument"); - } - return (ret); -} - -// -// richcmp defines the ==, !=, >, <, >= and <= operators in python -// It is translated to a function that gets 3 arguments, an object, -// an object to compare to, and an operator. -// -PyObject* -Name_richcmp(s_Name* self, s_Name* other, int op) { - bool c; - - // Check for null and if the types match. If different type, - // simply return False - if (!other || (self->ob_type != other->ob_type)) { - Py_RETURN_FALSE; - } - - switch (op) { - case Py_LT: - c = *self->cppobj < *other->cppobj; - break; - case Py_LE: - c = *self->cppobj <= *other->cppobj; - break; - case Py_EQ: - c = *self->cppobj == *other->cppobj; - break; - case Py_NE: - c = *self->cppobj != *other->cppobj; - break; - case Py_GT: - c = *self->cppobj > *other->cppobj; - break; - case Py_GE: - c = *self->cppobj >= *other->cppobj; - break; - default: - PyErr_SetString(PyExc_IndexError, - "Unhandled rich comparison operator"); - return (NULL); - } - if (c) { - Py_RETURN_TRUE; - } else { - Py_RETURN_FALSE; - } -} - -PyObject* -Name_reverse(s_Name* self) { - s_Name* ret = PyObject_New(s_Name, &name_type); - - if (ret != NULL) { - ret->cppobj = new Name(self->cppobj->reverse()); - if (ret->cppobj == NULL) { - Py_DECREF(ret); - return (NULL); - } - } - return (ret); -} - -PyObject* -Name_concatenate(s_Name* self, PyObject* args) { - s_Name* other; - - if (!PyArg_ParseTuple(args, "O!", &name_type, &other)) - return (NULL); - - s_Name* ret = PyObject_New(s_Name, &name_type); - if (ret != NULL) { - try { - ret->cppobj = new Name(self->cppobj->concatenate(*other->cppobj)); - } catch (const TooLongName& tln) { - PyErr_SetString(po_TooLongName, tln.what()); - return (NULL); - } - } - return (ret); -} - -PyObject* -Name_downcase(s_Name* self) { - self->cppobj->downcase(); - Py_INCREF(self); - return (self); -} - -PyObject* -Name_isWildCard(s_Name* self) { - if (self->cppobj->isWildcard()) { - Py_RETURN_TRUE; - } else { - Py_RETURN_FALSE; - } -} - -Py_hash_t -Name_hash(PyObject* pyself) { - const s_Name* const self = static_cast(pyself); - return (convertToPyHash( - LabelSequence(*self->cppobj).getHash(false))); -} - -} // end of unnamed namespace - -namespace isc { -namespace dns { -namespace python { - -// -// Definition of the custom exceptions -// Initialization and addition of these go in the module init at the -// end -// -PyObject* po_NameParserException; -PyObject* po_EmptyLabel; -PyObject* po_TooLongName; -PyObject* po_TooLongLabel; -PyObject* po_BadLabelType; -PyObject* po_BadEscape; -PyObject* po_IncompleteName; -PyObject* po_InvalidBufferPosition; - -// -// Definition of enums -// Initialization and addition of these go in the module init at the -// end -// -PyObject* po_NameRelation; - -PyTypeObject name_comparison_result_type = { - PyVarObject_HEAD_INIT(NULL, 0) - "pydnspp.NameComparisonResult", - sizeof(s_NameComparisonResult), // tp_basicsize - 0, // tp_itemsize - (destructor)NameComparisonResult_destroy, // tp_dealloc - NULL, // tp_print - NULL, // tp_getattr - NULL, // tp_setattr - NULL, // tp_reserved - NULL, // tp_repr - NULL, // tp_as_number - NULL, // tp_as_sequence - NULL, // tp_as_mapping - NULL, // tp_hash - NULL, // tp_call - NULL, // tp_str - NULL, // tp_getattro - NULL, // tp_setattro - NULL, // tp_as_buffer - Py_TPFLAGS_DEFAULT, // tp_flags - "This is a supplemental class used only as a return value of Name.compare(). " - "It encapsulate a tuple of the comparison: ordering, number of common labels, " - "and relationship as follows:\n" - "- ordering: relative ordering under the DNSSEC order relation\n" - "- labels: the number of common significant labels of the two names being" - " compared\n" - "- relationship: see NameComparisonResult.NameRelation\n", - NULL, // tp_traverse - NULL, // tp_clear - NULL, // tp_richcompare - 0, // tp_weaklistoffset - NULL, // tp_iter - NULL, // tp_iternext - NameComparisonResult_methods, // tp_methods - NULL, // tp_members - NULL, // tp_getset - NULL, // tp_base - NULL, // tp_dict - NULL, // tp_descr_get - NULL, // tp_descr_set - 0, // tp_dictoffset - (initproc)NameComparisonResult_init, // tp_init - NULL, // tp_alloc - PyType_GenericNew, // tp_new - NULL, // tp_free - NULL, // tp_is_gc - NULL, // tp_bases - NULL, // tp_mro - NULL, // tp_cache - NULL, // tp_subclasses - NULL, // tp_weaklist - NULL, // tp_del - 0 // tp_version_tag -}; - -PyTypeObject name_type = { - PyVarObject_HEAD_INIT(NULL, 0) - "pydnspp.Name", - sizeof(s_Name), // tp_basicsize - 0, // tp_itemsize - (destructor)Name_destroy, // tp_dealloc - NULL, // tp_print - NULL, // tp_getattr - NULL, // tp_setattr - NULL, // tp_reserved - NULL, // tp_repr - NULL, // tp_as_number - NULL, // tp_as_sequence - NULL, // tp_as_mapping - Name_hash, // tp_hash - NULL, // tp_call - Name_str, // tp_str - NULL, // tp_getattro - NULL, // tp_setattro - NULL, // tp_as_buffer - Py_TPFLAGS_DEFAULT, // tp_flags - "The Name class encapsulates DNS names.\n" - "It provides interfaces to construct a name from string or wire-format data, " - "transform a name into a string or wire-format data, compare two names, get " - "access to various properties of a name, etc.", - NULL, // tp_traverse - NULL, // tp_clear - (richcmpfunc)Name_richcmp, // tp_richcompare - 0, // tp_weaklistoffset - NULL, // tp_iter - NULL, // tp_iternext - Name_methods, // tp_methods - NULL, // tp_members - NULL, // tp_getset - NULL, // tp_base - NULL, // tp_dict - NULL, // tp_descr_get - NULL, // tp_descr_set - 0, // tp_dictoffset - (initproc)Name_init, // tp_init - NULL, // tp_alloc - PyType_GenericNew, // tp_new - NULL, // tp_free - NULL, // tp_is_gc - NULL, // tp_bases - NULL, // tp_mro - NULL, // tp_cache - NULL, // tp_subclasses - NULL, // tp_weaklist - // Note: not sure if the following are correct. Added them just to - // make the compiler happy. - NULL, // tp_del - 0 // tp_version_tag -}; - -PyObject* -createNameObject(const Name& source) { - NameContainer container(PyObject_New(s_Name, &name_type)); - container.set(new Name(source)); - return (container.release()); -} - -bool -PyName_Check(PyObject* obj) { - if (obj == NULL) { - isc_throw(PyCPPWrapperException, "obj argument NULL in typecheck"); - } - return (PyObject_TypeCheck(obj, &name_type)); -} - -const Name& -PyName_ToName(const PyObject* name_obj) { - if (name_obj == NULL) { - isc_throw(PyCPPWrapperException, - "obj argument NULL in Name PyObject conversion"); - } - const s_Name* name = static_cast(name_obj); - return (*name->cppobj); -} - - -} // namespace python -} // namespace dns -} // namespace isc diff --git a/src/lib/dns/python/name_python.h b/src/lib/dns/python/name_python.h deleted file mode 100644 index 2cce9994cc..0000000000 --- a/src/lib/dns/python/name_python.h +++ /dev/null @@ -1,81 +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. - -#ifndef PYTHON_NAME_H -#define PYTHON_NAME_H 1 - -#include - -namespace isc { -namespace dns { -class Name; - -namespace python { - -extern PyObject* po_NameParserException; -extern PyObject* po_EmptyLabel; -extern PyObject* po_TooLongName; -extern PyObject* po_TooLongLabel; -extern PyObject* po_BadLabelType; -extern PyObject* po_BadEscape; -extern PyObject* po_IncompleteName; -extern PyObject* po_InvalidBufferPosition; - -// -// Declaration of enums -// Initialization and addition of these go in the module init at the -// end -// -extern PyObject* po_NameRelation; - -extern PyTypeObject name_comparison_result_type; -extern PyTypeObject name_type; - -/// This is A simple shortcut to create a python Name object (in the -/// form of a pointer to PyObject) with minimal exception safety. -/// On success, it returns a valid pointer to PyObject with a reference -/// counter of 1; if something goes wrong it throws an exception (it never -/// returns a NULL pointer). -/// This function is expected to be called with in a try block -/// followed by necessary setup for python exception. -PyObject* createNameObject(const Name& source); - -/// \brief Checks if the given python object is a Name object -/// -/// \exception PyCPPWrapperException if obj is NULL -/// -/// \param obj The object to check the type of -/// \return true if the object is of type Name, false otherwise -bool PyName_Check(PyObject* obj); - -/// \brief Returns a reference to the Name object contained within the given -/// Python object. -/// -/// \note The given object MUST be of type Name; this can be checked with -/// either the right call to ParseTuple("O!"), or with PyName_Check() -/// -/// \note This is not a copy; if the Name is needed when the PyObject -/// may be destroyed, the caller must copy it itself. -/// -/// \param name_obj The name object to convert -const Name& PyName_ToName(const PyObject* name_obj); - -} // namespace python -} // namespace dns -} // namespace isc -#endif // PYTHON_NAME_H - -// Local Variables: -// mode: c++ -// End: diff --git a/src/lib/dns/python/nsec3hash_python.cc b/src/lib/dns/python/nsec3hash_python.cc deleted file mode 100644 index 01e8ae5b4e..0000000000 --- a/src/lib/dns/python/nsec3hash_python.cc +++ /dev/null @@ -1,271 +0,0 @@ -// Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC") -// -// Permission to use, copy, modify, and/or distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -// PERFORMANCE OF THIS SOFTWARE. - -// 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 - -#include -#include - -#include - -#include -#include - -#include "pydnspp_common.h" -#include "name_python.h" -#include "nsec3hash_python.h" -#include "rdata_python.h" - -using namespace std; -using namespace isc::util::python; -using namespace isc::dns; -using namespace isc::dns::rdata; -using namespace isc::dns::python; - -// Import pydoc text -#include "nsec3hash_python_inc.cc" - -// Trivial constructor. -s_NSEC3Hash::s_NSEC3Hash() : cppobj(NULL) { -} - -namespace { -int -NSEC3Hash_init(PyObject* po_self, PyObject* args, PyObject*) { - s_NSEC3Hash* const self = static_cast(po_self); - try { - PyObject* po_rdata; - if (PyArg_ParseTuple(args, "O", &po_rdata)) { - if (!PyRdata_Check(po_rdata)) { - PyErr_Format(PyExc_TypeError, - "param must be an Rdata of type NSEC3/NSEC3PARAM," - " not %.200s", po_rdata->ob_type->tp_name); - return (-1); - } - const Rdata& rdata = PyRdata_ToRdata(po_rdata); - const generic::NSEC3PARAM* nsec3param = - dynamic_cast(&rdata); - const generic::NSEC3* nsec3 = - dynamic_cast(&rdata); - if (nsec3param != NULL) { - self->cppobj = NSEC3Hash::create(*nsec3param); - } else if (nsec3 != NULL) { - self->cppobj = NSEC3Hash::create(*nsec3); - } else { - PyErr_Format(PyExc_TypeError, - "param must be an Rdata of type NSEC3/NSEC3HASH"); - return (-1); - } - return (0); - } - } catch (const UnknownNSEC3HashAlgorithm& ex) { - PyErr_SetString(po_UnknownNSEC3HashAlgorithm, ex.what()); - return (-1); - } catch (const exception& ex) { - const string ex_what = "Failed to construct NSEC3Hash object: " + - string(ex.what()); - PyErr_SetString(po_IscException, ex_what.c_str()); - return (-1); - } catch (...) { - PyErr_SetString(PyExc_SystemError, "Unexpected C++ exception"); - return (-1); - } - - return (-1); -} - -void -NSEC3Hash_destroy(PyObject* po_self) { - s_NSEC3Hash* self = static_cast(po_self); - delete self->cppobj; - self->cppobj = NULL; - Py_TYPE(self)->tp_free(self); -} - -PyObject* -NSEC3Hash_calculate(PyObject* po_self, PyObject* args) { - s_NSEC3Hash* const self = static_cast(po_self); - - try { - PyObject* po_name; - if (PyArg_ParseTuple(args, "O", &po_name)) { - if (!PyName_Check(po_name)) { - PyErr_Format(PyExc_TypeError, - "name must be a Name, not %.200s", - po_name->ob_type->tp_name); - return (NULL); - } - const string hash = - self->cppobj->calculate(PyName_ToName(po_name)); - return (Py_BuildValue("s", hash.c_str())); - } - } catch (const exception& ex) { - const string ex_what = "Unexpected failure in NSEC3Hash.calculate: " + - 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); -} - -PyObject* -NSEC3Hash_match(PyObject* po_self, PyObject* args) { - s_NSEC3Hash* const self = static_cast(po_self); - - try { - PyObject* po_rdata; - if (PyArg_ParseTuple(args, "O", &po_rdata)) { - if (!PyRdata_Check(po_rdata)) { - PyErr_Format(PyExc_TypeError, - "param must be an Rdata of type NSEC3/NSEC3PARAM," - " not %.200s", po_rdata->ob_type->tp_name); - return (NULL); - } - const Rdata& rdata = PyRdata_ToRdata(po_rdata); - const generic::NSEC3PARAM* nsec3param = - dynamic_cast(&rdata); - const generic::NSEC3* nsec3 = - dynamic_cast(&rdata); - bool matched; - if (nsec3param != NULL) { - matched = self->cppobj->match(*nsec3param); - } else if (nsec3 != NULL) { - matched = self->cppobj->match(*nsec3); - } else { - PyErr_Format(PyExc_TypeError, - "param must be an Rdata of type NSEC3/NSEC3HASH"); - return (NULL); - } - PyObject* ret = matched ? Py_True : Py_False; - Py_INCREF(ret); - return (ret); - } - } catch (const exception& ex) { - const string ex_what = "Unexpected failure in NSEC3Hash.match: " + - 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); -} - -// This list contains the actual set of functions we have in -// python. Each entry has -// 1. Python method name -// 2. Our static function here -// 3. Argument type -// 4. Documentation -PyMethodDef NSEC3Hash_methods[] = { - { "calculate", NSEC3Hash_calculate, METH_VARARGS, NSEC3Hash_calculate_doc }, - { "match", NSEC3Hash_match, METH_VARARGS, NSEC3Hash_match_doc }, - { NULL, NULL, 0, NULL } -}; -} // end of unnamed namespace - -namespace isc { -namespace dns { -namespace python { -// -// Declaration of the custom exceptions -// Initialization and addition of these go in pydnspp.cc -// -PyObject* po_UnknownNSEC3HashAlgorithm; - -// This defines the complete type for reflection in python and -// parsing of PyObject* to s_NSEC3Hash -// Most of the functions are not actually implemented and NULL here. -PyTypeObject nsec3hash_type = { - PyVarObject_HEAD_INIT(NULL, 0) - "dns.NSEC3Hash", - sizeof(s_NSEC3Hash), // tp_basicsize - 0, // tp_itemsize - NSEC3Hash_destroy, // tp_dealloc - NULL, // tp_print - NULL, // tp_getattr - NULL, // tp_setattr - NULL, // tp_reserved - NULL, // tp_repr - NULL, // tp_as_number - NULL, // tp_as_sequence - NULL, // tp_as_mapping - NULL, // tp_hash - NULL, // tp_call - NULL, // tp_str - NULL, // tp_getattro - NULL, // tp_setattro - NULL, // tp_as_buffer - Py_TPFLAGS_DEFAULT, // tp_flags - NSEC3Hash_doc, - NULL, // tp_traverse - NULL, // tp_clear - NULL, // tp_richcompare - 0, // tp_weaklistoffset - NULL, // tp_iter - NULL, // tp_iternext - NSEC3Hash_methods, // tp_methods - NULL, // tp_members - NULL, // tp_getset - NULL, // tp_base - NULL, // tp_dict - NULL, // tp_descr_get - NULL, // tp_descr_set - 0, // tp_dictoffset - NSEC3Hash_init, // tp_init - NULL, // tp_alloc - PyType_GenericNew, // tp_new - NULL, // tp_free - NULL, // tp_is_gc - NULL, // tp_bases - NULL, // tp_mro - NULL, // tp_cache - NULL, // tp_subclasses - NULL, // tp_weaklist - NULL, // tp_del - 0 // tp_version_tag -}; - -// Module Initialization, all statics (nothing right now) are initialized here -bool -initModulePart_NSEC3Hash(PyObject* mod) { - // We initialize the static description object with PyType_Ready(), - // then add it to the module. This is not just a check! (leaving - // this out results in segmentation faults) - if (PyType_Ready(&nsec3hash_type) < 0) { - return (false); - } - void* p = &nsec3hash_type; - if (PyModule_AddObject(mod, "NSEC3Hash", static_cast(p)) < 0) { - return (false); - } - Py_INCREF(&nsec3hash_type); - - return (true); -} -} // namespace python -} // namespace dns -} // namespace isc diff --git a/src/lib/dns/python/nsec3hash_python.h b/src/lib/dns/python/nsec3hash_python.h deleted file mode 100644 index 51a5fdea9a..0000000000 --- a/src/lib/dns/python/nsec3hash_python.h +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC") -// -// Permission to use, copy, modify, and/or distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -// PERFORMANCE OF THIS SOFTWARE. - -#ifndef PYTHON_NSEC3HASH_H -#define PYTHON_NSEC3HASH_H 1 - -#include - -namespace isc { -namespace dns { -class NSEC3Hash; - -namespace python { - -// The s_* Class simply covers one instantiation of the object -class s_NSEC3Hash : public PyObject { -public: - s_NSEC3Hash(); - NSEC3Hash* cppobj; -}; - -extern PyTypeObject nsec3hash_type; - -// Public exception object. -extern PyObject* po_UnknownNSEC3HashAlgorithm; - -bool initModulePart_NSEC3Hash(PyObject* mod); - -} // namespace python -} // namespace dns -} // namespace isc -#endif // PYTHON_NSEC3HASH_H - -// Local Variables: -// mode: c++ -// End: diff --git a/src/lib/dns/python/nsec3hash_python_inc.cc b/src/lib/dns/python/nsec3hash_python_inc.cc deleted file mode 100644 index 576be7509b..0000000000 --- a/src/lib/dns/python/nsec3hash_python_inc.cc +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC") -// -// Permission to use, copy, modify, and/or distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -// PERFORMANCE OF THIS SOFTWARE. - -namespace { -// Modifications -// - removed intermediate details note, mainly for brevity -// - removed std::bad_alloc -const char* const NSEC3Hash_doc = "\ -A calculator of NSEC3 hashes.\n\ -\n\ -This is a simple class that encapsulates the algorithm of calculating\n\ -NSEC3 hash values as defined in RFC5155.\n\ -\n\ -NSEC3Hash(param)\n\ -\n\ - Constructor.\n\ -\n\ - The hash algorithm given via param must be known to the\n\ - implementation. Otherwise UnknownNSEC3HashAlgorithm exception will\n\ - be thrown.\n\ -\n\ - Exceptions:\n\ - UnknownNSEC3HashAlgorithm The specified algorithm in param is\n\ - unknown.\n\ -\n\ - Parameters:\n\ - param NSEC3PARAM or NSEC3 Rdata object whose parameters are\n\ - to be used for subsequent calculation.\n\ -\n\ -"; - -const char* const NSEC3Hash_calculate_doc = "\ -calculate(name) -> string\n\ -\n\ -Calculate the NSEC3 hash.\n\ -\n\ -This method calculates the NSEC3 hash value for the given name with\n\ -the hash parameters (algorithm, iterations and salt) given at\n\ -construction, and returns the value in a base32hex-encoded string\n\ -(without containing any white spaces). All US-ASCII letters in the\n\ -string will be upper cased.\n\ -\n\ -Parameters:\n\ - name The domain name for which the hash value is to be\n\ - calculated.\n\ -\n\ -Return Value(s): Base32hex-encoded string of the hash value.\n\ -"; - -const char* const NSEC3Hash_match_doc = "\ -match(rdata) -> bool\n \ -\n\ -Match given NSEC3 or NSEC3PARAM parameters with that of the hash.\n\ -\n\ -This method compares NSEC3 parameters used for hash calculation in the\n\ -object with those in the given RDATA, and return true iff they\n\ -completely match. In the current implementation only the algorithm,\n\ -iterations and salt are compared; the flags are ignored (as they don't\n\ -affect hash calculation per RFC5155).\n\ -\n\ -Exceptions:\n\ - None\n\ -\n\ -Parameters:\n\ - rdata An NSEC3 or NSEC3PARAM Rdata object whose hash parameters\n\ - are to be matched\n\ -\n\ -Return Value(s): true If the given parameters match the local ones;\n\ -false otherwise.\n\ -"; -} // unnamed namespace diff --git a/src/lib/dns/python/opcode_python.cc b/src/lib/dns/python/opcode_python.cc deleted file mode 100644 index 8d40d9dd6f..0000000000 --- a/src/lib/dns/python/opcode_python.cc +++ /dev/null @@ -1,231 +0,0 @@ -// Copyright (C) 2010 Internet Systems Consortium, Inc. ("ISC") -// -// Permission to use, copy, modify, and/or distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -// PERFORMANCE OF THIS SOFTWARE. - -#include - -#include -#include - -#include "pydnspp_common.h" -#include "opcode_python.h" -#include "edns_python.h" - -using namespace isc::dns; -using namespace isc::dns::python; -using namespace isc::util; -using namespace isc::util::python; - -namespace { - -class s_Opcode : public PyObject { -public: - s_Opcode() : cppobj(NULL), static_code(false) {} - const isc::dns::Opcode* cppobj; - bool static_code; -}; - -typedef CPPPyObjectContainer OpcodeContainer; - -int Opcode_init(s_Opcode* const self, PyObject* args); -void Opcode_destroy(s_Opcode* const self); - -PyObject* Opcode_getCode(const s_Opcode* const self); -PyObject* Opcode_toText(const s_Opcode* const self); -PyObject* Opcode_str(PyObject* self); - -PyMethodDef Opcode_methods[] = { - { "get_code", reinterpret_cast(Opcode_getCode), METH_NOARGS, - "Returns the code value" }, - { "to_text", reinterpret_cast(Opcode_toText), METH_NOARGS, - "Returns the text representation" }, - { NULL, NULL, 0, NULL } -}; - - -int -Opcode_init(s_Opcode* const self, PyObject* args) { - uint8_t code = 0; - if (PyArg_ParseTuple(args, "b", &code)) { - try { - self->cppobj = new Opcode(code); - self->static_code = false; - } catch (const isc::OutOfRange& ex) { - PyErr_SetString(PyExc_OverflowError, ex.what()); - return (-1); - } catch (...) { - PyErr_SetString(po_IscException, "Unexpected exception"); - return (-1); - } - return (0); - } - - PyErr_Clear(); - PyErr_SetString(PyExc_TypeError, "Invalid arguments to Opcode constructor"); - - return (-1); -} - -void -Opcode_destroy(s_Opcode* const self) { - // Depending on whether we created the rcode or are referring - // to a global static one, we do or do not delete self->cppobj here - if (!self->static_code) { - delete self->cppobj; - } - self->cppobj = NULL; - Py_TYPE(self)->tp_free(self); -} - -PyObject* -Opcode_getCode(const s_Opcode* const self) { - return (Py_BuildValue("I", self->cppobj->getCode())); -} - -PyObject* -Opcode_toText(const s_Opcode* const self) { - return (Py_BuildValue("s", self->cppobj->toText().c_str())); -} - -PyObject* -Opcode_str(PyObject* self) { - // Simply call the to_text method we already defined - return (PyObject_CallMethod(self, - const_cast("to_text"), - const_cast(""))); -} - -PyObject* -Opcode_richcmp(const s_Opcode* const self, const s_Opcode* const other, - const int op) -{ - bool c = false; - - // Check for null and if the types match. If different type, - // simply return False - if (!other || (self->ob_type != other->ob_type)) { - Py_RETURN_FALSE; - } - - // Only equals and not equals here, unorderable type - switch (op) { - case Py_LT: - PyErr_SetString(PyExc_TypeError, "Unorderable type; Opcode"); - return (NULL); - case Py_LE: - PyErr_SetString(PyExc_TypeError, "Unorderable type; Opcode"); - return (NULL); - case Py_EQ: - c = (*self->cppobj == *other->cppobj); - break; - case Py_NE: - c = (*self->cppobj != *other->cppobj); - break; - case Py_GT: - PyErr_SetString(PyExc_TypeError, "Unorderable type; Opcode"); - return (NULL); - case Py_GE: - PyErr_SetString(PyExc_TypeError, "Unorderable type; Opcode"); - return (NULL); - } - if (c) - Py_RETURN_TRUE; - else - Py_RETURN_FALSE; -} - -} // end of unnamed namespace - -namespace isc { -namespace dns { -namespace python { - -PyTypeObject opcode_type = { - PyVarObject_HEAD_INIT(NULL, 0) - "pydnspp.Opcode", - sizeof(s_Opcode), // tp_basicsize - 0, // tp_itemsize - (destructor)Opcode_destroy, // tp_dealloc - NULL, // tp_print - NULL, // tp_getattr - NULL, // tp_setattr - NULL, // tp_reserved - NULL, // tp_repr - NULL, // tp_as_number - NULL, // tp_as_sequence - NULL, // tp_as_mapping - NULL, // tp_hash - NULL, // tp_call - Opcode_str, // tp_str - NULL, // tp_getattro - NULL, // tp_setattro - NULL, // tp_as_buffer - Py_TPFLAGS_DEFAULT, // tp_flags - "The Opcode class objects represent standard OPCODEs " - "of the header section of DNS messages.", - NULL, // tp_traverse - NULL, // tp_clear - (richcmpfunc)Opcode_richcmp, // tp_richcompare - 0, // tp_weaklistoffset - NULL, // tp_iter - NULL, // tp_iternext - Opcode_methods, // tp_methods - NULL, // tp_members - NULL, // tp_getset - NULL, // tp_base - NULL, // tp_dict - NULL, // tp_descr_get - NULL, // tp_descr_set - 0, // tp_dictoffset - (initproc)Opcode_init, // tp_init - NULL, // tp_alloc - PyType_GenericNew, // tp_new - NULL, // tp_free - NULL, // tp_is_gc - NULL, // tp_bases - NULL, // tp_mro - NULL, // tp_cache - NULL, // tp_subclasses - NULL, // tp_weaklist - NULL, // tp_del - 0 // tp_version_tag -}; - -PyObject* -createOpcodeObject(const Opcode& source) { - OpcodeContainer container(PyObject_New(s_Opcode, &opcode_type)); - container.set(new Opcode(source)); - return (container.release()); -} - -bool -PyOpcode_Check(PyObject* obj) { - if (obj == NULL) { - isc_throw(PyCPPWrapperException, "obj argument NULL in typecheck"); - } - return (PyObject_TypeCheck(obj, &opcode_type)); -} - -const Opcode& -PyOpcode_ToOpcode(const PyObject* opcode_obj) { - if (opcode_obj == NULL) { - isc_throw(PyCPPWrapperException, - "obj argument NULL in Opcode PyObject conversion"); - } - const s_Opcode* opcode = static_cast(opcode_obj); - return (*opcode->cppobj); -} - -} // end python namespace -} // end dns namespace -} // end isc namespace diff --git a/src/lib/dns/python/opcode_python.h b/src/lib/dns/python/opcode_python.h deleted file mode 100644 index 6e9967eeef..0000000000 --- a/src/lib/dns/python/opcode_python.h +++ /dev/null @@ -1,64 +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. - -#ifndef PYTHON_OPCODE_H -#define PYTHON_OPCODE_H 1 - -#include - -namespace isc { -namespace dns { -class Opcode; - -namespace python { - -extern PyTypeObject opcode_type; - -/// This is a simple shortcut to create a python Opcode object (in the -/// form of a pointer to PyObject) with minimal exception safety. -/// On success, it returns a valid pointer to PyObject with a reference -/// counter of 1; if something goes wrong it throws an exception (it never -/// returns a NULL pointer). -/// This function is expected to be called within a try block -/// followed by necessary setup for python exception. -PyObject* createOpcodeObject(const Opcode& source); - -/// \brief Checks if the given python object is a Opcode object -/// -/// \exception PyCPPWrapperException if obj is NULL -/// -/// \param obj The object to check the type of -/// \return true if the object is of type Opcode, false otherwise -bool PyOpcode_Check(PyObject* obj); - -/// \brief Returns a reference to the Opcode object contained within the given -/// Python object. -/// -/// \note The given object MUST be of type Opcode; this can be checked with -/// either the right call to ParseTuple("O!"), or with PyOpcode_Check() -/// -/// \note This is not a copy; if the Opcode is needed when the PyObject -/// may be destroyed, the caller must copy it itself. -/// -/// \param opcode_obj The opcode object to convert -const Opcode& PyOpcode_ToOpcode(const PyObject* opcode_obj); - -} // namespace python -} // namespace dns -} // namespace isc -#endif // PYTHON_OPCODE_H - -// Local Variables: -// mode: c++ -// End: diff --git a/src/lib/dns/python/pydnspp.cc b/src/lib/dns/python/pydnspp.cc deleted file mode 100644 index b0bda22c4b..0000000000 --- a/src/lib/dns/python/pydnspp.cc +++ /dev/null @@ -1,1011 +0,0 @@ -// Copyright (C) 2010 Internet Systems Consortium, Inc. ("ISC") -// -// Permission to use, copy, modify, and/or distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -// PERFORMANCE OF THIS SOFTWARE. - - -// We want a lot of different parts of the DNS API in the python -// module, but not one big 10000-line file. -// So we split it up in several 'mini-modules' -// These would be the same as a single module, except for -// the init function, which has to be modified to a unique -// name initModulePart_, and return true/false instead of -// NULL/*mod -// -// The big init function is split up into a separate initModulePart function -// for each class we add. - -#define PY_SSIZE_T_CLEAN -#include -#include - -#include -#include -#include -#include -#include - -#include "pydnspp_common.h" - -#include "edns_python.h" -#include "message_python.h" -#include "messagerenderer_python.h" -#include "name_python.h" -#include "nsec3hash_python.h" -#include "opcode_python.h" -#include "pydnspp_common.h" -#include "pydnspp_towire.h" -#include "question_python.h" -#include "rcode_python.h" -#include "rdata_python.h" -#include "rrclass_python.h" -#include "rrset_python.h" -#include "rrttl_python.h" -#include "rrtype_python.h" -#include "rrset_collection_python.h" -#include "serial_python.h" -#include "tsigerror_python.h" -#include "tsigkey_python.h" -#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; -using namespace isc::util::python; - -namespace { - -bool -initModulePart_EDNS(PyObject* mod) { - // After the type has been initialized, we initialize any exceptions - // that are defined in the wrapper for this class, and add constants - // to the type, if any - - if (!initClass(edns_type, "EDNS", mod)) { - return (false); - } - addClassVariable(edns_type, "SUPPORTED_VERSION", - Py_BuildValue("B", EDNS::SUPPORTED_VERSION)); - - return (true); -} - -bool -initModulePart_Message(PyObject* mod) { - if (!initClass(message_type, "Message", mod)) { - return (false); - } - - try { - // - // Constant class variables - // - - // Parse mode - installClassVariable(message_type, "PARSE", - Py_BuildValue("I", Message::PARSE)); - installClassVariable(message_type, "RENDER", - Py_BuildValue("I", Message::RENDER)); - - // Parse options - installClassVariable(message_type, "PARSE_DEFAULT", - Py_BuildValue("I", Message::PARSE_DEFAULT)); - installClassVariable(message_type, "PRESERVE_ORDER", - Py_BuildValue("I", Message::PRESERVE_ORDER)); - - // Header flags - installClassVariable(message_type, "HEADERFLAG_QR", - Py_BuildValue("I", Message::HEADERFLAG_QR)); - installClassVariable(message_type, "HEADERFLAG_AA", - Py_BuildValue("I", Message::HEADERFLAG_AA)); - installClassVariable(message_type, "HEADERFLAG_TC", - Py_BuildValue("I", Message::HEADERFLAG_TC)); - installClassVariable(message_type, "HEADERFLAG_RD", - Py_BuildValue("I", Message::HEADERFLAG_RD)); - installClassVariable(message_type, "HEADERFLAG_RA", - Py_BuildValue("I", Message::HEADERFLAG_RA)); - installClassVariable(message_type, "HEADERFLAG_AD", - Py_BuildValue("I", Message::HEADERFLAG_AD)); - installClassVariable(message_type, "HEADERFLAG_CD", - Py_BuildValue("I", Message::HEADERFLAG_CD)); - - // Sections - installClassVariable(message_type, "SECTION_QUESTION", - Py_BuildValue("I", Message::SECTION_QUESTION)); - installClassVariable(message_type, "SECTION_ANSWER", - Py_BuildValue("I", Message::SECTION_ANSWER)); - installClassVariable(message_type, "SECTION_AUTHORITY", - Py_BuildValue("I", Message::SECTION_AUTHORITY)); - installClassVariable(message_type, "SECTION_ADDITIONAL", - Py_BuildValue("I", Message::SECTION_ADDITIONAL)); - - // Protocol constant - installClassVariable(message_type, "DEFAULT_MAX_UDPSIZE", - Py_BuildValue("I", Message::DEFAULT_MAX_UDPSIZE)); - - /* Class-specific exceptions */ - po_MessageTooShort = - PyErr_NewException("pydnspp.MessageTooShort", NULL, NULL); - PyObjectContainer(po_MessageTooShort).installToModule( - mod, "MessageTooShort"); - po_InvalidMessageSection = - PyErr_NewException("pydnspp.InvalidMessageSection", NULL, NULL); - PyObjectContainer(po_InvalidMessageSection).installToModule( - mod, "InvalidMessageSection"); - po_InvalidMessageOperation = - PyErr_NewException("pydnspp.InvalidMessageOperation", NULL, NULL); - PyObjectContainer(po_InvalidMessageOperation).installToModule( - mod, "InvalidMessageOperation"); - po_InvalidMessageUDPSize = - PyErr_NewException("pydnspp.InvalidMessageUDPSize", NULL, NULL); - PyObjectContainer(po_InvalidMessageUDPSize).installToModule( - mod, "InvalidMessageUDPSize"); - po_DNSMessageFORMERR = - PyErr_NewException("pydnspp.DNSMessageFORMERR", - po_DNSProtocolError, NULL); - PyObjectContainer(po_DNSMessageFORMERR).installToModule( - mod, "DNSMessageFORMERR"); - po_DNSMessageBADVERS = - PyErr_NewException("pydnspp.DNSMessageBADVERS", - po_DNSProtocolError, NULL); - PyObjectContainer(po_DNSMessageBADVERS).installToModule( - mod, "DNSMessageBADVERS"); - po_UnknownNSEC3HashAlgorithm = - PyErr_NewException("pydnspp.UnknownNSEC3HashAlgorithm", NULL, NULL); - PyObjectContainer(po_UnknownNSEC3HashAlgorithm).installToModule( - mod, "UnknownNSEC3HashAlgorithm"); - } catch (const std::exception& ex) { - const std::string ex_what = - "Unexpected failure in Message initialization: " + - std::string(ex.what()); - PyErr_SetString(po_IscException, ex_what.c_str()); - return (false); - } catch (...) { - PyErr_SetString(PyExc_SystemError, - "Unexpected failure in Message initialization"); - return (false); - } - - return (true); -} - -bool -initModulePart_MessageRenderer(PyObject* mod) { - if (!initClass(messagerenderer_type, "MessageRenderer", mod)) { - return (false); - } - - addClassVariable(messagerenderer_type, "CASE_INSENSITIVE", - Py_BuildValue("I", MessageRenderer::CASE_INSENSITIVE)); - addClassVariable(messagerenderer_type, "CASE_SENSITIVE", - Py_BuildValue("I", MessageRenderer::CASE_SENSITIVE)); - - - return (true); -} - -bool -initModulePart_NameComparisonResult(PyObject* mod) { - if (!initClass(name_comparison_result_type, - "NameComparisonResult", mod)) { - return (false); - } - - // Add the enums to the module - po_NameRelation = Py_BuildValue("{i:s,i:s,i:s,i:s}", - NameComparisonResult::SUPERDOMAIN, "SUPERDOMAIN", - NameComparisonResult::SUBDOMAIN, "SUBDOMAIN", - NameComparisonResult::EQUAL, "EQUAL", - NameComparisonResult::COMMONANCESTOR, "COMMONANCESTOR"); - addClassVariable(name_comparison_result_type, "NameRelation", - po_NameRelation); - // Add the constants themselves too - addClassVariable(name_comparison_result_type, "SUPERDOMAIN", - Py_BuildValue("I", NameComparisonResult::SUPERDOMAIN)); - addClassVariable(name_comparison_result_type, "SUBDOMAIN", - Py_BuildValue("I", NameComparisonResult::SUBDOMAIN)); - addClassVariable(name_comparison_result_type, "EQUAL", - Py_BuildValue("I", NameComparisonResult::EQUAL)); - addClassVariable(name_comparison_result_type, "COMMONANCESTOR", - Py_BuildValue("I", NameComparisonResult::COMMONANCESTOR)); - - return (true); -} - -bool -initModulePart_Name(PyObject* mod) { - if (!initClass(name_type, "Name", mod)) { - return (false); - } - - // Add the constants to the module - addClassVariable(name_type, "MAX_WIRE", - Py_BuildValue("I", Name::MAX_WIRE)); - addClassVariable(name_type, "MAX_LABELS", - Py_BuildValue("I", Name::MAX_LABELS)); - addClassVariable(name_type, "MAX_LABELLEN", - Py_BuildValue("I", Name::MAX_LABELLEN)); - addClassVariable(name_type, "MAX_COMPRESS_POINTER", - Py_BuildValue("I", Name::MAX_COMPRESS_POINTER)); - addClassVariable(name_type, "COMPRESS_POINTER_MARK8", - Py_BuildValue("I", Name::COMPRESS_POINTER_MARK8)); - addClassVariable(name_type, "COMPRESS_POINTER_MARK16", - Py_BuildValue("I", Name::COMPRESS_POINTER_MARK16)); - - addClassVariable(name_type, "ROOT_NAME", - createNameObject(Name::ROOT_NAME())); - - // Add the exceptions to the module - try { - po_NameParserException = - PyErr_NewException("pydnspp.NameParserException", - po_DNSTextError, NULL); - PyObjectContainer(po_NameParserException) - .installToModule(mod, "NameParserException"); - - po_EmptyLabel = PyErr_NewException("pydnspp.EmptyLabel", - po_NameParserException, NULL); - PyObjectContainer(po_EmptyLabel).installToModule(mod, "EmptyLabel"); - - po_TooLongName = PyErr_NewException("pydnspp.TooLongName", - po_NameParserException, NULL); - PyObjectContainer(po_TooLongName).installToModule(mod, "TooLongName"); - - po_TooLongLabel = PyErr_NewException("pydnspp.TooLongLabel", - po_NameParserException, NULL); - PyObjectContainer(po_TooLongLabel).installToModule(mod, "TooLongLabel"); - - po_BadLabelType = PyErr_NewException("pydnspp.BadLabelType", - po_NameParserException, NULL); - PyObjectContainer(po_BadLabelType).installToModule(mod, "BadLabelType"); - - po_BadEscape = PyErr_NewException("pydnspp.BadEscape", - po_NameParserException, NULL); - PyObjectContainer(po_BadEscape).installToModule(mod, "BadEscape"); - - po_IncompleteName = PyErr_NewException("pydnspp.IncompleteName", - po_NameParserException, NULL); - PyObjectContainer(po_IncompleteName).installToModule(mod, "IncompleteName"); - - po_InvalidBufferPosition = - PyErr_NewException("pydnspp.InvalidBufferPosition", NULL, NULL); - PyObjectContainer(po_InvalidBufferPosition).installToModule( - mod, "InvalidBufferPosition"); - } catch (const std::exception& ex) { - const std::string ex_what = - "Unexpected failure in Name initialization: " + - std::string(ex.what()); - PyErr_SetString(po_IscException, ex_what.c_str()); - return (false); - } catch (...) { - PyErr_SetString(PyExc_SystemError, - "Unexpected failure in Name initialization"); - return (false); - } - - return (true); -} - -bool -initModulePart_Opcode(PyObject* mod) { - if (!initClass(opcode_type, "Opcode", mod)) { - return (false); - } - - try { - installClassVariable(opcode_type, "QUERY_CODE", - Py_BuildValue("h", Opcode::QUERY_CODE)); - installClassVariable(opcode_type, "IQUERY_CODE", - Py_BuildValue("h", Opcode::IQUERY_CODE)); - installClassVariable(opcode_type, "STATUS_CODE", - Py_BuildValue("h", Opcode::STATUS_CODE)); - installClassVariable(opcode_type, "RESERVED3_CODE", - Py_BuildValue("h", Opcode::RESERVED3_CODE)); - installClassVariable(opcode_type, "NOTIFY_CODE", - Py_BuildValue("h", Opcode::NOTIFY_CODE)); - installClassVariable(opcode_type, "UPDATE_CODE", - Py_BuildValue("h", Opcode::UPDATE_CODE)); - installClassVariable(opcode_type, "RESERVED6_CODE", - Py_BuildValue("h", Opcode::RESERVED6_CODE)); - installClassVariable(opcode_type, "RESERVED7_CODE", - Py_BuildValue("h", Opcode::RESERVED7_CODE)); - installClassVariable(opcode_type, "RESERVED8_CODE", - Py_BuildValue("h", Opcode::RESERVED8_CODE)); - installClassVariable(opcode_type, "RESERVED9_CODE", - Py_BuildValue("h", Opcode::RESERVED9_CODE)); - installClassVariable(opcode_type, "RESERVED10_CODE", - Py_BuildValue("h", Opcode::RESERVED10_CODE)); - installClassVariable(opcode_type, "RESERVED11_CODE", - Py_BuildValue("h", Opcode::RESERVED11_CODE)); - installClassVariable(opcode_type, "RESERVED12_CODE", - Py_BuildValue("h", Opcode::RESERVED12_CODE)); - installClassVariable(opcode_type, "RESERVED13_CODE", - Py_BuildValue("h", Opcode::RESERVED13_CODE)); - installClassVariable(opcode_type, "RESERVED14_CODE", - Py_BuildValue("h", Opcode::RESERVED14_CODE)); - installClassVariable(opcode_type, "RESERVED15_CODE", - Py_BuildValue("h", Opcode::RESERVED15_CODE)); - - installClassVariable(opcode_type, "QUERY", - createOpcodeObject(Opcode::QUERY())); - installClassVariable(opcode_type, "IQUERY", - createOpcodeObject(Opcode::IQUERY())); - installClassVariable(opcode_type, "STATUS", - createOpcodeObject(Opcode::STATUS())); - installClassVariable(opcode_type, "RESERVED3", - createOpcodeObject(Opcode::RESERVED3())); - installClassVariable(opcode_type, "NOTIFY", - createOpcodeObject(Opcode::NOTIFY())); - installClassVariable(opcode_type, "UPDATE", - createOpcodeObject(Opcode::UPDATE())); - installClassVariable(opcode_type, "RESERVED6", - createOpcodeObject(Opcode::RESERVED6())); - installClassVariable(opcode_type, "RESERVED7", - createOpcodeObject(Opcode::RESERVED7())); - installClassVariable(opcode_type, "RESERVED8", - createOpcodeObject(Opcode::RESERVED8())); - installClassVariable(opcode_type, "RESERVED9", - createOpcodeObject(Opcode::RESERVED9())); - installClassVariable(opcode_type, "RESERVED10", - createOpcodeObject(Opcode::RESERVED10())); - installClassVariable(opcode_type, "RESERVED11", - createOpcodeObject(Opcode::RESERVED11())); - installClassVariable(opcode_type, "RESERVED12", - createOpcodeObject(Opcode::RESERVED12())); - installClassVariable(opcode_type, "RESERVED13", - createOpcodeObject(Opcode::RESERVED13())); - installClassVariable(opcode_type, "RESERVED14", - createOpcodeObject(Opcode::RESERVED14())); - installClassVariable(opcode_type, "RESERVED15", - createOpcodeObject(Opcode::RESERVED15())); - } catch (const std::exception& ex) { - const std::string ex_what = - "Unexpected failure in Opcode initialization: " + - std::string(ex.what()); - PyErr_SetString(po_IscException, ex_what.c_str()); - return (false); - } catch (...) { - PyErr_SetString(PyExc_SystemError, - "Unexpected failure in Opcode initialization"); - return (false); - } - - return (true); -} - -bool -initModulePart_Question(PyObject* mod) { - return (initClass(question_type, "Question", mod)); -} - -bool -initModulePart_Rcode(PyObject* mod) { - if (!initClass(rcode_type, "Rcode", mod)) { - return (false); - } - - try { - installClassVariable(rcode_type, "NOERROR_CODE", - Py_BuildValue("h", Rcode::NOERROR_CODE)); - installClassVariable(rcode_type, "FORMERR_CODE", - Py_BuildValue("h", Rcode::FORMERR_CODE)); - installClassVariable(rcode_type, "SERVFAIL_CODE", - Py_BuildValue("h", Rcode::SERVFAIL_CODE)); - installClassVariable(rcode_type, "NXDOMAIN_CODE", - Py_BuildValue("h", Rcode::NXDOMAIN_CODE)); - installClassVariable(rcode_type, "NOTIMP_CODE", - Py_BuildValue("h", Rcode::NOTIMP_CODE)); - installClassVariable(rcode_type, "REFUSED_CODE", - Py_BuildValue("h", Rcode::REFUSED_CODE)); - installClassVariable(rcode_type, "YXDOMAIN_CODE", - Py_BuildValue("h", Rcode::YXDOMAIN_CODE)); - installClassVariable(rcode_type, "YXRRSET_CODE", - Py_BuildValue("h", Rcode::YXRRSET_CODE)); - installClassVariable(rcode_type, "NXRRSET_CODE", - Py_BuildValue("h", Rcode::NXRRSET_CODE)); - installClassVariable(rcode_type, "NOTAUTH_CODE", - Py_BuildValue("h", Rcode::NOTAUTH_CODE)); - installClassVariable(rcode_type, "NOTZONE_CODE", - Py_BuildValue("h", Rcode::NOTZONE_CODE)); - installClassVariable(rcode_type, "RESERVED11_CODE", - Py_BuildValue("h", Rcode::RESERVED11_CODE)); - installClassVariable(rcode_type, "RESERVED12_CODE", - Py_BuildValue("h", Rcode::RESERVED12_CODE)); - installClassVariable(rcode_type, "RESERVED13_CODE", - Py_BuildValue("h", Rcode::RESERVED13_CODE)); - installClassVariable(rcode_type, "RESERVED14_CODE", - Py_BuildValue("h", Rcode::RESERVED14_CODE)); - installClassVariable(rcode_type, "RESERVED15_CODE", - Py_BuildValue("h", Rcode::RESERVED15_CODE)); - installClassVariable(rcode_type, "BADVERS_CODE", - Py_BuildValue("h", Rcode::BADVERS_CODE)); - - installClassVariable(rcode_type, "NOERROR", - createRcodeObject(Rcode::NOERROR())); - installClassVariable(rcode_type, "FORMERR", - createRcodeObject(Rcode::FORMERR())); - installClassVariable(rcode_type, "SERVFAIL", - createRcodeObject(Rcode::SERVFAIL())); - installClassVariable(rcode_type, "NXDOMAIN", - createRcodeObject(Rcode::NXDOMAIN())); - installClassVariable(rcode_type, "NOTIMP", - createRcodeObject(Rcode::NOTIMP())); - installClassVariable(rcode_type, "REFUSED", - createRcodeObject(Rcode::REFUSED())); - installClassVariable(rcode_type, "YXDOMAIN", - createRcodeObject(Rcode::YXDOMAIN())); - installClassVariable(rcode_type, "YXRRSET", - createRcodeObject(Rcode::YXRRSET())); - installClassVariable(rcode_type, "NXRRSET", - createRcodeObject(Rcode::NXRRSET())); - installClassVariable(rcode_type, "NOTAUTH", - createRcodeObject(Rcode::NOTAUTH())); - installClassVariable(rcode_type, "NOTZONE", - createRcodeObject(Rcode::NOTZONE())); - installClassVariable(rcode_type, "RESERVED11", - createRcodeObject(Rcode::RESERVED11())); - installClassVariable(rcode_type, "RESERVED12", - createRcodeObject(Rcode::RESERVED12())); - installClassVariable(rcode_type, "RESERVED13", - createRcodeObject(Rcode::RESERVED13())); - installClassVariable(rcode_type, "RESERVED14", - createRcodeObject(Rcode::RESERVED14())); - installClassVariable(rcode_type, "RESERVED15", - createRcodeObject(Rcode::RESERVED15())); - installClassVariable(rcode_type, "BADVERS", - createRcodeObject(Rcode::BADVERS())); - } catch (const std::exception& ex) { - const std::string ex_what = - "Unexpected failure in Rcode initialization: " + - std::string(ex.what()); - PyErr_SetString(po_IscException, ex_what.c_str()); - return (false); - } catch (...) { - PyErr_SetString(PyExc_SystemError, - "Unexpected failure in Rcode initialization"); - return (false); - } - - return (true); -} - -bool -initModulePart_Rdata(PyObject* mod) { - if (!initClass(rdata_type, "Rdata", mod)) { - return (false); - } - - // Add the exceptions to the class - try { - po_InvalidRdataLength = - PyErr_NewException("pydnspp.InvalidRdataLength", NULL, NULL); - PyObjectContainer(po_InvalidRdataLength).installToModule( - mod, "InvalidRdataLength"); - - po_InvalidRdataText = PyErr_NewException("pydnspp.InvalidRdataText", - NULL, NULL); - PyObjectContainer(po_InvalidRdataText).installToModule( - mod, "InvalidRdataText"); - - po_CharStringTooLong = PyErr_NewException("pydnspp.CharStringTooLong", - NULL, NULL); - PyObjectContainer(po_CharStringTooLong).installToModule( - mod, "CharStringTooLong"); - } catch (const std::exception& ex) { - const std::string ex_what = - "Unexpected failure in Rdata initialization: " + - std::string(ex.what()); - PyErr_SetString(po_IscException, ex_what.c_str()); - return (false); - } catch (...) { - PyErr_SetString(PyExc_SystemError, - "Unexpected failure in Rdata initialization"); - return (false); - } - - return (true); -} - -bool -initModulePart_RRClass(PyObject* mod) { - if (!initClass(rrclass_type, "RRClass", mod)) { - return (false); - } - - try { - po_InvalidRRClass = PyErr_NewException("pydnspp.InvalidRRClass", - NULL, NULL); - PyObjectContainer(po_InvalidRRClass).installToModule( - mod, "InvalidRRClass"); - - po_IncompleteRRClass = PyErr_NewException("pydnspp.IncompleteRRClass", - NULL, NULL); - PyObjectContainer(po_IncompleteRRClass).installToModule( - mod, "IncompleteRRClass"); - - // Incorporate auto-generated RRClass constants -#include - } catch (const std::exception& ex) { - const std::string ex_what = - "Unexpected failure in RRClass initialization: " + - std::string(ex.what()); - PyErr_SetString(po_IscException, ex_what.c_str()); - return (false); - } catch (...) { - PyErr_SetString(PyExc_SystemError, - "Unexpected failure in RRClass initialization"); - return (false); - } - - return (true); -} - -bool -initModulePart_RRset(PyObject* mod) { - if (!initClass(rrset_type, "RRset", mod)) { - return (false); - } - - try { - po_EmptyRRset = PyErr_NewException("pydnspp.EmptyRRset", NULL, NULL); - PyObjectContainer(po_EmptyRRset).installToModule(mod, "EmptyRRset"); - } catch (const std::exception& ex) { - const std::string ex_what = - "Unexpected failure in RRset initialization: " + - std::string(ex.what()); - PyErr_SetString(po_IscException, ex_what.c_str()); - return (false); - } catch (...) { - PyErr_SetString(PyExc_SystemError, - "Unexpected failure in RRset initialization"); - return (false); - } - - return (true); -} - -bool -initModulePart_RRTTL(PyObject* mod) { - if (!initClass(rrttl_type, "RRTTL", mod)) { - return (false); - } - - try { - po_InvalidRRTTL = PyErr_NewException("pydnspp.InvalidRRTTL", - NULL, NULL); - PyObjectContainer(po_InvalidRRTTL).installToModule(mod, - "InvalidRRTTL"); - - po_IncompleteRRTTL = PyErr_NewException("pydnspp.IncompleteRRTTL", - NULL, NULL); - PyObjectContainer(po_IncompleteRRTTL).installToModule( - mod, "IncompleteRRTTL"); - } catch (const std::exception& ex) { - const std::string ex_what = - "Unexpected failure in RRTTL initialization: " + - std::string(ex.what()); - PyErr_SetString(po_IscException, ex_what.c_str()); - return (false); - } catch (...) { - PyErr_SetString(PyExc_SystemError, - "Unexpected failure in RRTTL initialization"); - return (false); - } - - return (true); -} - -bool -initModulePart_RRType(PyObject* mod) { - if (!initClass(rrtype_type, "RRType", mod)) { - return (false); - } - - try { - po_InvalidRRType = PyErr_NewException("pydnspp.InvalidRRType", - NULL, NULL); - PyObjectContainer(po_InvalidRRType).installToModule(mod, - "InvalidRRType"); - - po_IncompleteRRType = PyErr_NewException("pydnspp.IncompleteRRType", - NULL, NULL); - PyObjectContainer(po_IncompleteRRType).installToModule( - mod, "IncompleteRRType"); - - // Incorporate auto-generated RRType constants -#include - } catch (const std::exception& ex) { - const std::string ex_what = - "Unexpected failure in RRType initialization: " + - std::string(ex.what()); - PyErr_SetString(po_IscException, ex_what.c_str()); - return (false); - } catch (...) { - PyErr_SetString(PyExc_SystemError, - "Unexpected failure in RRType initialization"); - return (false); - } - - return (true); -} - -bool -initModulePart_Serial(PyObject* mod) { - return (initClass(serial_type, "Serial", mod)); -} - -bool -initModulePart_TSIGError(PyObject* mod) { - if (!initClass(tsigerror_type, "TSIGError", mod)) { - return (false); - } - - try { - // Constant class variables - // Error codes (bare values) - installClassVariable(tsigerror_type, "BAD_SIG_CODE", - Py_BuildValue("H", TSIGError::BAD_SIG_CODE)); - installClassVariable(tsigerror_type, "BAD_KEY_CODE", - Py_BuildValue("H", TSIGError::BAD_KEY_CODE)); - installClassVariable(tsigerror_type, "BAD_TIME_CODE", - Py_BuildValue("H", TSIGError::BAD_TIME_CODE)); - - // Error codes (constant objects) - installClassVariable(tsigerror_type, "NOERROR", - createTSIGErrorObject(TSIGError::NOERROR())); - installClassVariable(tsigerror_type, "FORMERR", - createTSIGErrorObject(TSIGError::FORMERR())); - installClassVariable(tsigerror_type, "SERVFAIL", - createTSIGErrorObject(TSIGError::SERVFAIL())); - installClassVariable(tsigerror_type, "NXDOMAIN", - createTSIGErrorObject(TSIGError::NXDOMAIN())); - installClassVariable(tsigerror_type, "NOTIMP", - createTSIGErrorObject(TSIGError::NOTIMP())); - installClassVariable(tsigerror_type, "REFUSED", - createTSIGErrorObject(TSIGError::REFUSED())); - installClassVariable(tsigerror_type, "YXDOMAIN", - createTSIGErrorObject(TSIGError::YXDOMAIN())); - installClassVariable(tsigerror_type, "YXRRSET", - createTSIGErrorObject(TSIGError::YXRRSET())); - installClassVariable(tsigerror_type, "NXRRSET", - createTSIGErrorObject(TSIGError::NXRRSET())); - installClassVariable(tsigerror_type, "NOTAUTH", - createTSIGErrorObject(TSIGError::NOTAUTH())); - installClassVariable(tsigerror_type, "NOTZONE", - createTSIGErrorObject(TSIGError::NOTZONE())); - installClassVariable(tsigerror_type, "RESERVED11", - createTSIGErrorObject(TSIGError::RESERVED11())); - installClassVariable(tsigerror_type, "RESERVED12", - createTSIGErrorObject(TSIGError::RESERVED12())); - installClassVariable(tsigerror_type, "RESERVED13", - createTSIGErrorObject(TSIGError::RESERVED13())); - installClassVariable(tsigerror_type, "RESERVED14", - createTSIGErrorObject(TSIGError::RESERVED14())); - installClassVariable(tsigerror_type, "RESERVED15", - createTSIGErrorObject(TSIGError::RESERVED15())); - installClassVariable(tsigerror_type, "BAD_SIG", - createTSIGErrorObject(TSIGError::BAD_SIG())); - installClassVariable(tsigerror_type, "BAD_KEY", - createTSIGErrorObject(TSIGError::BAD_KEY())); - installClassVariable(tsigerror_type, "BAD_TIME", - createTSIGErrorObject(TSIGError::BAD_TIME())); - } catch (const std::exception& ex) { - const std::string ex_what = - "Unexpected failure in TSIGError initialization: " + - std::string(ex.what()); - PyErr_SetString(po_IscException, ex_what.c_str()); - return (false); - } catch (...) { - PyErr_SetString(PyExc_SystemError, - "Unexpected failure in TSIGError initialization"); - return (false); - } - - return (true); -} - -bool -initModulePart_TSIGKey(PyObject* mod) { - if (!initClass(tsigkey_type, "TSIGKey", mod)) { - return (false); - } - - try { - // Constant class variables - installClassVariable(tsigkey_type, "HMACMD5_NAME", - createNameObject(TSIGKey::HMACMD5_NAME())); - installClassVariable(tsigkey_type, "HMACSHA1_NAME", - createNameObject(TSIGKey::HMACSHA1_NAME())); - installClassVariable(tsigkey_type, "HMACSHA256_NAME", - createNameObject(TSIGKey::HMACSHA256_NAME())); - installClassVariable(tsigkey_type, "HMACSHA224_NAME", - createNameObject(TSIGKey::HMACSHA224_NAME())); - installClassVariable(tsigkey_type, "HMACSHA384_NAME", - createNameObject(TSIGKey::HMACSHA384_NAME())); - installClassVariable(tsigkey_type, "HMACSHA512_NAME", - createNameObject(TSIGKey::HMACSHA512_NAME())); - } catch (const std::exception& ex) { - const std::string ex_what = - "Unexpected failure in TSIGKey initialization: " + - std::string(ex.what()); - PyErr_SetString(po_IscException, ex_what.c_str()); - return (false); - } catch (...) { - PyErr_SetString(PyExc_SystemError, - "Unexpected failure in TSIGKey initialization"); - return (false); - } - - return (true); -} - -bool -initModulePart_TSIGKeyRing(PyObject* mod) { - if (!initClass(tsigkeyring_type, "TSIGKeyRing", mod)) { - return (false); - } - - addClassVariable(tsigkeyring_type, "SUCCESS", - Py_BuildValue("I", TSIGKeyRing::SUCCESS)); - addClassVariable(tsigkeyring_type, "EXIST", - Py_BuildValue("I", TSIGKeyRing::EXIST)); - addClassVariable(tsigkeyring_type, "NOTFOUND", - Py_BuildValue("I", TSIGKeyRing::NOTFOUND)); - - return (true); -} - -bool -initModulePart_TSIGContext(PyObject* mod) { - if (!initClass(tsigcontext_type, "TSIGContext", mod)) { - return (false); - } - - try { - // Class specific exceptions - po_TSIGContextError = PyErr_NewException("pydnspp.TSIGContextError", - po_IscException, NULL); - PyObjectContainer(po_TSIGContextError).installToModule( - mod, "TSIGContextError"); - - // Constant class variables - installClassVariable(tsigcontext_type, "STATE_INIT", - Py_BuildValue("I", TSIGContext::INIT)); - installClassVariable(tsigcontext_type, "STATE_SENT_REQUEST", - Py_BuildValue("I", TSIGContext::SENT_REQUEST)); - installClassVariable(tsigcontext_type, "STATE_RECEIVED_REQUEST", - Py_BuildValue("I", TSIGContext::RECEIVED_REQUEST)); - installClassVariable(tsigcontext_type, "STATE_SENT_RESPONSE", - Py_BuildValue("I", TSIGContext::SENT_RESPONSE)); - installClassVariable(tsigcontext_type, "STATE_VERIFIED_RESPONSE", - Py_BuildValue("I", - TSIGContext::VERIFIED_RESPONSE)); - - installClassVariable(tsigcontext_type, "DEFAULT_FUDGE", - Py_BuildValue("H", TSIGContext::DEFAULT_FUDGE)); - } catch (const std::exception& ex) { - const std::string ex_what = - "Unexpected failure in TSIGContext initialization: " + - std::string(ex.what()); - PyErr_SetString(po_IscException, ex_what.c_str()); - return (false); - } catch (...) { - PyErr_SetString(PyExc_SystemError, - "Unexpected failure in TSIGContext initialization"); - return (false); - } - - return (true); -} - -bool -initModulePart_TSIG(PyObject* mod) { - return (initClass(tsig_type, "TSIG", mod)); -} - -bool -initModulePart_TSIGRecord(PyObject* mod) { - if (!initClass(tsigrecord_type, "TSIGRecord", mod)) { - return (false); - } - - try { - // Constant class variables - installClassVariable(tsigrecord_type, "TSIG_TTL", - Py_BuildValue("I", 0)); - } catch (const std::exception& ex) { - const std::string ex_what = - "Unexpected failure in TSIGRecord initialization: " + - std::string(ex.what()); - PyErr_SetString(po_IscException, ex_what.c_str()); - return (false); - } catch (...) { - PyErr_SetString(PyExc_SystemError, - "Unexpected failure in TSIGRecord initialization"); - return (false); - } - - 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", - "Python bindings for the classes in the isc::dns namespace.\n\n" - "These bindings match the original C++ API as closely as possible, " - "but are not complete. Some classes are unnecessary (InputBuffer " - "and OutputBuffer for instance), and others may be necessary, but " - "were not up to now.", - -1, - methods, - NULL, - NULL, - NULL, - NULL -}; -} // unnamed namespace - -PyMODINIT_FUNC -PyInit_pydnspp(void) { - PyObject* mod = PyModule_Create(&pydnspp); - if (mod == NULL) { - return (NULL); - } - - try { - // Add the exceptions to the class - po_IscException = PyErr_NewException("pydnspp.IscException", NULL, NULL); - PyObjectContainer(po_IscException).installToModule(mod, "IscException"); - - po_InvalidOperation = PyErr_NewException("pydnspp.InvalidOperation", - po_IscException, NULL); - PyObjectContainer(po_InvalidOperation) - .installToModule(mod, "InvalidOperation"); - - po_InvalidParameter = PyErr_NewException("pydnspp.InvalidParameter", - po_IscException, NULL); - PyObjectContainer(po_InvalidParameter) - .installToModule(mod, "InvalidParameter"); - - // Add DNS exceptions - po_DNSException = PyErr_NewException("pydnspp.DNSException", - po_IscException, NULL); - PyObjectContainer(po_DNSException) - .installToModule(mod, "DNSException"); - - po_DNSTextError = PyErr_NewException("pydnspp.DNSTextError", - po_DNSException, NULL); - PyObjectContainer(po_DNSTextError) - .installToModule(mod, "DNSTextError"); - - po_DNSProtocolError = PyErr_NewException("pydnspp.DNSProtocolError", - po_DNSException, NULL); - PyObjectContainer(po_DNSProtocolError) - .installToModule(mod, "DNSProtocolError"); - - } catch (const std::exception& ex) { - const std::string ex_what = - "Unexpected failure in pydnspp initialization: " + - std::string(ex.what()); - PyErr_SetString(po_IscException, ex_what.c_str()); - return (NULL); - } catch (...) { - PyErr_SetString(PyExc_SystemError, - "Unexpected failure in pydnspp initialization"); - return (NULL); - } - - // for each part included above, we call its specific initializer - - if (!initModulePart_NameComparisonResult(mod)) { - return (NULL); - } - - if (!initModulePart_Name(mod)) { - return (NULL); - } - - if (!initModulePart_MessageRenderer(mod)) { - return (NULL); - } - - if (!initModulePart_NSEC3Hash(mod)) { - return (NULL); - } - - if (!initModulePart_RRClass(mod)) { - return (NULL); - } - - if (!initModulePart_RRType(mod)) { - return (NULL); - } - - if (!initModulePart_RRTTL(mod)) { - return (NULL); - } - - if (!initModulePart_Rdata(mod)) { - return (NULL); - } - - if (!initModulePart_RRset(mod)) { - return (NULL); - } - - if (!initModulePart_Question(mod)) { - return (NULL); - } - - if (!initModulePart_Opcode(mod)) { - return (NULL); - } - - if (!initModulePart_Rcode(mod)) { - return (NULL); - } - - if (!initModulePart_Message(mod)) { - return (NULL); - } - - if (!initModulePart_EDNS(mod)) { - return (NULL); - } - - if (!initModulePart_Serial(mod)) { - return (NULL); - } - - if (!initModulePart_TSIGKey(mod)) { - return (NULL); - } - - if (!initModulePart_TSIGKeyRing(mod)) { - return (NULL); - } - - if (!initModulePart_TSIG(mod)) { - return (NULL); - } - - if (!initModulePart_TSIGError(mod)) { - return (NULL); - } - - if (!initModulePart_TSIGRecord(mod)) { - return (NULL); - } - - if (!initModulePart_TSIGContext(mod)) { - return (NULL); - } - - if (!initModulePart_RRsetCollectionBase(mod)) { - return (NULL); - } - - if (!initModulePart_RRsetCollection(mod)) { - return (NULL); - } - - return (mod); -} diff --git a/src/lib/dns/python/pydnspp_common.cc b/src/lib/dns/python/pydnspp_common.cc deleted file mode 100644 index c95f87765e..0000000000 --- a/src/lib/dns/python/pydnspp_common.cc +++ /dev/null @@ -1,116 +0,0 @@ -// Copyright (C) 2010 Internet Systems Consortium, Inc. ("ISC") -// -// Permission to use, copy, modify, and/or distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -// PERFORMANCE OF THIS SOFTWARE. - -#include - -#include - -#include - -#include -#include -#include - -#include "pydnspp_common.h" -#include "messagerenderer_python.h" -#include "name_python.h" -#include "rdata_python.h" -#include "rrclass_python.h" -#include "rrtype_python.h" -#include "rrttl_python.h" -#include "rrset_python.h" -#include "rcode_python.h" -#include "opcode_python.h" -#include "tsigkey_python.h" -#include "tsig_rdata_python.h" -#include "tsigerror_python.h" -#include "tsigrecord_python.h" -#include "tsig_python.h" -#include "question_python.h" -#include "message_python.h" - -using namespace isc::dns::python; - -namespace isc { -namespace dns { -namespace python { -// For our 'general' isc::Exceptions -PyObject* po_IscException; -PyObject* po_InvalidOperation; -PyObject* po_InvalidParameter; - -// For DNS exceptions -PyObject* po_DNSException; -PyObject* po_DNSTextError; -PyObject* po_DNSProtocolError; -PyObject* po_DNSMessageFORMERR; -PyObject* po_DNSMessageBADVERS; - - -int -readDataFromSequence(uint8_t *data, size_t len, PyObject* sequence) { - for (size_t i = 0; i < len; i++) { - PyObject *el = PySequence_GetItem(sequence, i); - if (!el) { - PyErr_SetString(PyExc_TypeError, - "sequence too short"); - return (-1); - } - if (PyLong_Check(el)) { - long l = PyLong_AsLong(el); - if (l < 0 || l > 255) { - PyErr_SetString(PyExc_TypeError, - "number in fromWire sequence not between 0 and 255"); - return (-1); - } - data[i] = static_cast(PyLong_AsLong(el)); - } else { - PyErr_SetString(PyExc_TypeError, - "not a number in fromWire sequence"); - return (-1); - } - } - PySequence_DelSlice(sequence, 0, len); - return (0); -} - - -int -addClassVariable(PyTypeObject& c, const char* name, PyObject* obj) { - if (obj == NULL) { - PyErr_SetString(PyExc_ValueError, - "NULL object is specified for a class variable"); - return (-1); - } - return (PyDict_SetItemString(c.tp_dict, name, obj)); -} - -bool -initClass(PyTypeObject& type, const char* name, PyObject* mod) { - // We initialize the static description object with PyType_Ready(), - // then add it to the module. This is not just a check! (leaving - // this out results in segmentation faults) - // - void* p = &type; - if (PyType_Ready(&type) < 0 || - PyModule_AddObject(mod, name, static_cast(p)) < 0) { - return (false); - } - Py_INCREF(&type); - return (true); -} - -} -} -} diff --git a/src/lib/dns/python/pydnspp_common.h b/src/lib/dns/python/pydnspp_common.h deleted file mode 100644 index 77191dc576..0000000000 --- a/src/lib/dns/python/pydnspp_common.h +++ /dev/null @@ -1,127 +0,0 @@ -// Copyright (C) 2010 Internet Systems Consortium, Inc. ("ISC") -// -// Permission to use, copy, modify, and/or distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -// PERFORMANCE OF THIS SOFTWARE. - -#ifndef LIBDNS_PYTHON_COMMON_H -#define LIBDNS_PYTHON_COMMON_H 1 - -#include - -#include - -#include - -#include // for CHAR_BIT -#include -#include - -namespace isc { -namespace dns { -namespace python { -// For our 'general' isc::Exceptions -extern PyObject* po_IscException; -extern PyObject* po_InvalidOperation; -extern PyObject* po_InvalidParameter; - -// For our own isc::dns::Exception -extern PyObject* po_DNSException; -extern PyObject* po_DNSTextError; -extern PyObject* po_DNSProtocolError; -extern PyObject* po_DNSMessageFORMERR; -extern PyObject* po_DNSMessageBADVERS; - -// This function reads 'bytes' from a sequence -// This sequence can be anything that implements the Sequence interface, -// but must consist of Numbers between 0 and 255 for every value. -// -// The data is stored in *data. -// Data must be allocated and have at least len bytes available. -// -// The current implementation removes read items from the -// head of the sequence, unless it fails (and returns -1), in which -// case nothing is removed -int readDataFromSequence(uint8_t *data, size_t len, PyObject* sequence); - -int addClassVariable(PyTypeObject& c, const char* name, PyObject* obj); - -/// \brief Initialize a wrapped class type, and add to module -/// -/// The type object is initialized, and its refcount is increased after -/// successful addition to the module. -/// -/// \param type The type object to initialize -/// \param name The python name of the class to add -/// \param mod The python module to add the class to -/// -/// \return true on success, false on failure -bool initClass(PyTypeObject& type, const char* name, PyObject* mod); - -/// \brief Convert a hash value of arbitrary type to a Python hash value. -/// -/// This templated function is a convenient wrapper to produce a valid hash -/// value of type Py_hash_t, which is expected to be used as the return value -/// of a PyTypeObject.tp_hash implementation. Py_hash_t is a signed integer -/// the same size as Py_ssize_t. -/// -/// The major concern is that -1 means an error in tp_hash and so we need to -/// ensure that this value is never returned. -/// -/// If the size of the original hash type is small enough, we convert -/// the original hash value to a value of Py_hash_t, resetting all higher bits -/// to 0. Due to the assumption on the sizes, the conversion to HashvalType -/// is safe, and (after clearing the higher bits) results in a valid positive -/// value. -/// -/// If the size of the input and return types is the same, we clear the -/// highest bit of the original hash so the resulting value will be in a valid -/// positive range of Py_hash_t. If the original type is unsigned, there's -/// probably no better conversion than this because otherwise the conversion -/// to Py_hash_t could result in an undefined behavior. If the original type -/// is signed, this conversion reduces the effective value range of the -/// original hash. If this is not desired, the caller should convert it -/// by itself (note that -1 should be still avoided). -/// -/// This function does not support the case where the size of the original -/// hash type is larger than that of Py_hash_t. -template -Py_hash_t -convertToPyHash(HashvalType val) { - BOOST_STATIC_ASSERT(sizeof(HashvalType) <= sizeof(Py_hash_t)); - - // Some versions of g++ doesn't ignore the impossible case of if/else - // below (depending on the size of HashvalType) and triggers a false - // warning. - // To work around it we use an intermediate mutable variable. - // See Trac #1883 for details. - size_t hash_val_bits = CHAR_BIT * sizeof(HashvalType); - - if (sizeof(HashvalType) < sizeof(Py_hash_t)) { - // The original hash type is small enough. Do trivial conversion. - const Py_hash_t mask = ~(static_cast(-1) << hash_val_bits); - return (static_cast(val) & mask); - } else { - // Clear the highest bit of the original hash so the conversion is - // safe and avoids -1. - HashvalType mask = ~(static_cast(1) << - (hash_val_bits - 1)); - return (val & mask); - } -} -} // namespace python -} // namespace dns -} // namespace isc -#endif // LIBDNS_PYTHON_COMMON_H - -// Local Variables: -// mode: c++ -// End: diff --git a/src/lib/dns/python/pydnspp_config.h.in b/src/lib/dns/python/pydnspp_config.h.in deleted file mode 100644 index 6326e8cb51..0000000000 --- a/src/lib/dns/python/pydnspp_config.h.in +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright (C) 2014 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 LIBDNS_PYTHON_CONFIG_H -#define LIBDNS_PYTHON_CONFIG_H 1 - -// Short term workaround for unifying the return type of tp_hash. -// Remove this test (and associated changes in configure.ac) when we -// require Python 3.2. -#if (!(@HAVE_PY_HASH_T@)) -typedef long Py_hash_t; -#endif - -#endif // LIBDNS_PYTHON_CONFIG_H diff --git a/src/lib/dns/python/pydnspp_towire.h b/src/lib/dns/python/pydnspp_towire.h deleted file mode 100644 index 7ad70cdcef..0000000000 --- a/src/lib/dns/python/pydnspp_towire.h +++ /dev/null @@ -1,127 +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. - -#ifndef LIBDNS_PYTHON_TOWIRE_H -#define LIBDNS_PYTHON_TOWIRE_H 1 - -#include - -#include -#include - -#include - -#include -#include - -#include "messagerenderer_python.h" - -namespace isc { -namespace dns { -namespace python { - -// The following two templated structures are a helper to use the same -// toWire() template implementation for two types of toWire() methods: -// return an integer or have no return value. -template -struct ToWireCallVoid { - ToWireCallVoid(CPPCLASS& cppobj) : cppobj_(cppobj) {} - int operator()(AbstractMessageRenderer& renderer) const { - cppobj_.toWire(renderer); - return (0); - } - const CPPCLASS& cppobj_; -}; - -template -struct ToWireCallInt { - ToWireCallInt(CPPCLASS& cppobj) : cppobj_(cppobj) {} - int operator()(AbstractMessageRenderer& renderer) const { - return (cppobj_.toWire(renderer)); - } - const CPPCLASS& cppobj_; -}; - -// This templated function gives a common implementation of the toWire() -// wrapper for various libdns++ classes. PYSTRUCT and CPPCLASS are -// (C++ binding of) python and (pure) C++ classes (e.g., s_Name and Name), -// and TOWIRECALLER is either ToWireCallVoid or -// ToWireCallInt, depending on the toWire() method of the class -// returns a value or not. -// -// See, e.g., tsigrecord_python.cc for how to use it. -// -// This should be able to be used without modification for most classes that -// have toWire(). But if the underlying toWire() has an extra argument, the -// definition will need to be adjusted accordingly. -template -PyObject* -toWireWrapper(const PYSTRUCT* const self, PyObject* args) { - try { - // To OutputBuffer version - PyObject* bytes; // this won't have own reference, no risk of leak. - if (PyArg_ParseTuple(args, "O", &bytes) && PySequence_Check(bytes)) { - // render the object into a buffer (this can throw) - isc::util::OutputBuffer buffer(0); - self->cppobj->toWire(buffer); - - // convert the rendered data into PyObject. This could leak later, - // so we need to store it in a container. - PyObject* rd_bytes = PyBytes_FromStringAndSize( - static_cast(buffer.getData()), - buffer.getLength()); - isc::util::python::PyObjectContainer rd_bytes_container(rd_bytes); - - // concat the latest data to the given existing sequence. concat - // operation could fail, so we use a container to clean it up - // safely should that happen. - PyObject* result = PySequence_InPlaceConcat(bytes, rd_bytes); - isc::util::python::PyObjectContainer result_container(result); - - return (result_container.release()); - } - - // To MessageRenderer version - PyObject* renderer; - if (PyArg_ParseTuple(args, "O!", &messagerenderer_type, &renderer)) { - const unsigned int n = TOWIRECALLER(*self->cppobj)( - PyMessageRenderer_ToMessageRenderer(renderer)); - - return (Py_BuildValue("I", n)); - } - } catch (const std::exception& ex) { - const std::string ex_what = - "Failed to render an libdns++ object wire-format: " - + std::string(ex.what()); - PyErr_SetString(po_IscException, ex_what.c_str()); - return (NULL); - } catch (...) { - PyErr_SetString(po_IscException, "Unexpectedly failed to render an " - "libdns++ object wire-format."); - return (NULL); - } - - PyErr_Clear(); - PyErr_SetString(PyExc_TypeError, - "Incorrect arguments for a to_wire() method"); - return (NULL); -} -} // namespace python -} // namespace dns -} // namespace isc -#endif // LIBDNS_PYTHON_TOWIRE_H - -// Local Variables: -// mode: c++ -// End: diff --git a/src/lib/dns/python/question_python.cc b/src/lib/dns/python/question_python.cc deleted file mode 100644 index 44d68a2047..0000000000 --- a/src/lib/dns/python/question_python.cc +++ /dev/null @@ -1,321 +0,0 @@ -// Copyright (C) 2010 Internet Systems Consortium, Inc. ("ISC") -// -// Permission to use, copy, modify, and/or distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -// PERFORMANCE OF THIS SOFTWARE. - -#define PY_SSIZE_T_CLEAN -#include -#include -#include -#include -#include -#include - -#include "pydnspp_common.h" -#include "question_python.h" -#include "name_python.h" -#include "rrclass_python.h" -#include "rrtype_python.h" -#include "messagerenderer_python.h" - -using namespace std; -using namespace isc::dns; -using namespace isc::dns::python; -using namespace isc::util; -using namespace isc::util::python; -using namespace isc; - -namespace { -class s_Question : public PyObject { -public: - isc::dns::QuestionPtr cppobj; -}; - -static int Question_init(s_Question* self, PyObject* args); -static void Question_destroy(s_Question* self); - -// These are the functions we export -static PyObject* Question_getName(s_Question* self); -static PyObject* Question_getType(s_Question* self); -static PyObject* Question_getClass(s_Question* self); -static PyObject* Question_toText(s_Question* self); -// This is a second version of toText, we need one where the argument -// is a PyObject*, for the str() function in python. -static PyObject* Question_str(PyObject* self); -static PyObject* Question_toWire(s_Question* self, PyObject* args); - -// This list contains the actual set of functions we have in -// python. Each entry has -// 1. Python method name -// 2. Our static function here -// 3. Argument type -// 4. Documentation -static PyMethodDef Question_methods[] = { - { "get_name", reinterpret_cast(Question_getName), METH_NOARGS, - "Returns the Name" }, - { "get_type", reinterpret_cast(Question_getType), METH_NOARGS, - "Returns the RRType" }, - { "get_class", reinterpret_cast(Question_getClass), METH_NOARGS, - "Returns the RRClass" }, - { "to_text", reinterpret_cast(Question_toText), METH_NOARGS, - "Returns the string representation" }, - { "to_wire", reinterpret_cast(Question_toWire), METH_VARARGS, - "Converts the Question object to wire format.\n" - "The argument can be either a MessageRenderer or an object that " - "implements the sequence interface. If the object is mutable " - "(for instance a bytearray()), the wire data is added in-place.\n" - "If it is not (for instance a bytes() object), a new object is " - "returned" }, - { NULL, NULL, 0, NULL } -}; - -static int -Question_init(s_Question* self, PyObject* args) { - // Try out the various combinations of arguments to call the - // correct cpp constructor. - // Note that PyArg_ParseType can set PyError, and we need to clear - // that if we try several like here. Otherwise the *next* python - // call will suddenly appear to throw an exception. - // (the way to do exceptions is to set PyErr and return -1) - PyObject* name; - PyObject* rrclass; - PyObject* rrtype; - - const char* b; - Py_ssize_t len; - unsigned int position = 0; - - try { - if (PyArg_ParseTuple(args, "O!O!O!", &name_type, &name, - &rrclass_type, &rrclass, - &rrtype_type, &rrtype - )) { - self->cppobj = QuestionPtr(new Question(PyName_ToName(name), - PyRRClass_ToRRClass(rrclass), - PyRRType_ToRRType(rrtype))); - return (0); - } else if (PyArg_ParseTuple(args, "y#|I", &b, &len, &position)) { - PyErr_Clear(); - InputBuffer inbuf(b, len); - inbuf.setPosition(position); - self->cppobj = QuestionPtr(new Question(inbuf)); - return (0); - } - } catch (const DNSMessageFORMERR& dmfe) { - PyErr_Clear(); - PyErr_SetString(po_DNSMessageFORMERR, dmfe.what()); - return (-1); - } catch (const IncompleteRRClass& irc) { - PyErr_Clear(); - PyErr_SetString(po_IncompleteRRClass, irc.what()); - return (-1); - } catch (const IncompleteRRType& irt) { - PyErr_Clear(); - PyErr_SetString(po_IncompleteRRType, irt.what()); - return (-1); - } - - self->cppobj = QuestionPtr(); - - PyErr_Clear(); - PyErr_SetString(PyExc_TypeError, - "no valid type in constructor argument"); - return (-1); -} - -static void -Question_destroy(s_Question* self) { - self->cppobj.reset(); - Py_TYPE(self)->tp_free(self); -} - -static PyObject* -Question_getName(s_Question* self) { - try { - return (createNameObject(self->cppobj->getName())); - } catch (const exception& ex) { - const string ex_what = - "Unexpected failure getting question Name: " + - string(ex.what()); - PyErr_SetString(po_IscException, ex_what.c_str()); - } catch (...) { - PyErr_SetString(PyExc_SystemError, - "Unexpected failure getting question Name"); - } - return (NULL); -} - -static PyObject* -Question_getType(s_Question* self) { - try { - return (createRRTypeObject(self->cppobj->getType())); - } catch (const exception& ex) { - const string ex_what = - "Unexpected failure getting question RRType: " + - string(ex.what()); - PyErr_SetString(po_IscException, ex_what.c_str()); - } catch (...) { - PyErr_SetString(PyExc_SystemError, - "Unexpected failure getting question RRType"); - } - return (NULL); -} - -static PyObject* -Question_getClass(s_Question* self) { - try { - return (createRRClassObject(self->cppobj->getClass())); - } catch (const exception& ex) { - const string ex_what = - "Unexpected failure getting question RRClass: " + - string(ex.what()); - PyErr_SetString(po_IscException, ex_what.c_str()); - } catch (...) { - PyErr_SetString(PyExc_SystemError, - "Unexpected failure getting question RRClass"); - } - return (NULL); -} - -static PyObject* -Question_toText(s_Question* self) { - // Py_BuildValue makes python objects from native data - return (Py_BuildValue("s", self->cppobj->toText().c_str())); -} - -static PyObject* -Question_str(PyObject* self) { - // Simply call the to_text method we already defined - return (PyObject_CallMethod(self, - const_cast("to_text"), - const_cast(""))); -} - -static PyObject* -Question_toWire(s_Question* self, PyObject* args) { - PyObject* bytes; - PyObject* mr; - - if (PyArg_ParseTuple(args, "O", &bytes) && PySequence_Check(bytes)) { - PyObject* bytes_o = bytes; - - // Max length is Name::MAX_WIRE + rrclass (2) + rrtype (2) - OutputBuffer buffer(Name::MAX_WIRE + 4); - self->cppobj->toWire(buffer); - PyObject* n = PyBytes_FromStringAndSize(static_cast(buffer.getData()), - buffer.getLength()); - PyObject* result = PySequence_InPlaceConcat(bytes_o, n); - // We need to release the object we temporarily created here - // to prevent memory leak - Py_DECREF(n); - return (result); - } else if (PyArg_ParseTuple(args, "O!", &messagerenderer_type, &mr)) { - self->cppobj->toWire(PyMessageRenderer_ToMessageRenderer(mr)); - // If we return NULL it is seen as an error, so use this for - // None returns - Py_RETURN_NONE; - } - PyErr_Clear(); - PyErr_SetString(PyExc_TypeError, - "toWire argument must be a sequence object or a MessageRenderer"); - return (NULL); -} - -} // end of unnamed namespace - -namespace isc { -namespace dns { -namespace python { - -// This defines the complete type for reflection in python and -// parsing of PyObject* to s_Question -// Most of the functions are not actually implemented and NULL here. -PyTypeObject question_type = { - PyVarObject_HEAD_INIT(NULL, 0) - "pydnspp.Question", - sizeof(s_Question), // tp_basicsize - 0, // tp_itemsize - (destructor)Question_destroy, // tp_dealloc - NULL, // tp_print - NULL, // tp_getattr - NULL, // tp_setattr - NULL, // tp_reserved - NULL, // tp_repr - NULL, // tp_as_number - NULL, // tp_as_sequence - NULL, // tp_as_mapping - NULL, // tp_hash - NULL, // tp_call - Question_str, // tp_str - NULL, // tp_getattro - NULL, // tp_setattro - NULL, // tp_as_buffer - Py_TPFLAGS_DEFAULT, // tp_flags - "The Question class encapsulates the common search key of DNS" - "lookup, consisting of owner name, RR type and RR class.", - NULL, // tp_traverse - NULL, // tp_clear - NULL, // tp_richcompare - 0, // tp_weaklistoffset - NULL, // tp_iter - NULL, // tp_iternext - Question_methods, // tp_methods - NULL, // tp_members - NULL, // tp_getset - NULL, // tp_base - NULL, // tp_dict - NULL, // tp_descr_get - NULL, // tp_descr_set - 0, // tp_dictoffset - (initproc)Question_init, // tp_init - NULL, // tp_alloc - PyType_GenericNew, // tp_new - NULL, // tp_free - NULL, // tp_is_gc - NULL, // tp_bases - NULL, // tp_mro - NULL, // tp_cache - NULL, // tp_subclasses - NULL, // tp_weaklist - NULL, // tp_del - 0 // tp_version_tag -}; - -PyObject* -createQuestionObject(const Question& source) { - s_Question* question = - static_cast(question_type.tp_alloc(&question_type, 0)); - question->cppobj = QuestionPtr(new Question(source)); - return (question); -} - -bool -PyQuestion_Check(PyObject* obj) { - if (obj == NULL) { - isc_throw(PyCPPWrapperException, "obj argument NULL in typecheck"); - } - return (PyObject_TypeCheck(obj, &question_type)); -} - -const Question& -PyQuestion_ToQuestion(const PyObject* question_obj) { - if (question_obj == NULL) { - isc_throw(PyCPPWrapperException, - "obj argument NULL in Question PyObject conversion"); - } - const s_Question* question = static_cast(question_obj); - return (*question->cppobj); -} - -} // end python namespace -} // end dns namespace -} // end isc namespace diff --git a/src/lib/dns/python/question_python.h b/src/lib/dns/python/question_python.h deleted file mode 100644 index 99b37c77a1..0000000000 --- a/src/lib/dns/python/question_python.h +++ /dev/null @@ -1,66 +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. - -#ifndef PYTHON_QUESTION_H -#define PYTHON_QUESTION_H 1 - -#include - -namespace isc { -namespace dns { -class Question; - -namespace python { - -extern PyObject* po_EmptyQuestion; - -extern PyTypeObject question_type; - -/// This is a simple shortcut to create a python Question object (in the -/// form of a pointer to PyObject) with minimal exception safety. -/// On success, it returns a valid pointer to PyObject with a reference -/// counter of 1; if something goes wrong it throws an exception (it never -/// returns a NULL pointer). -/// This function is expected to be called within a try block -/// followed by necessary setup for python exception. -PyObject* createQuestionObject(const Question& source); - -/// \brief Checks if the given python object is a Question object -/// -/// \exception PyCPPWrapperException if obj is NULL -/// -/// \param obj The object to check the type of -/// \return true if the object is of type Question, false otherwise -bool PyQuestion_Check(PyObject* obj); - -/// \brief Returns a reference to the Question object contained within the given -/// Python object. -/// -/// \note The given object MUST be of type Question; this can be checked with -/// either the right call to ParseTuple("O!"), or with PyQuestion_Check() -/// -/// \note This is not a copy; if the Question is needed when the PyObject -/// may be destroyed, the caller must copy it itself. -/// -/// \param question_obj The question object to convert -const Question& PyQuestion_ToQuestion(const PyObject* question_obj); - -} // namespace python -} // namespace dns -} // namespace isc -#endif // PYTHON_QUESTION_H - -// Local Variables: -// mode: c++ -// End: diff --git a/src/lib/dns/python/rcode_python.cc b/src/lib/dns/python/rcode_python.cc deleted file mode 100644 index 67b45e7f84..0000000000 --- a/src/lib/dns/python/rcode_python.cc +++ /dev/null @@ -1,265 +0,0 @@ -// Copyright (C) 2010 Internet Systems Consortium, Inc. ("ISC") -// -// Permission to use, copy, modify, and/or distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -// PERFORMANCE OF THIS SOFTWARE. - -#include - -#include -#include -#include - -#include "pydnspp_common.h" -#include "rcode_python.h" - -using namespace isc::dns; -using namespace isc::dns::python; -using namespace isc::util::python; - -namespace { -// The s_* Class simply covers one instantiation of the object. -// -// We added a helper variable static_code here -// Since we can create Rcodes dynamically with Rcode(int), but also -// use the static globals (Rcode::NOERROR() etc), we use this -// variable to see if the code came from one of the latter, in which -// case Rcode_destroy should not free it (the other option is to -// allocate new Rcodes for every use of the static ones, but this -// seems more efficient). -// -// Follow-up note: we don't have to use the proxy function in the python lib; -// we can just define class specific constants directly (see TSIGError). -// We should make this cleanup later. -class s_Rcode : public PyObject { -public: - s_Rcode() : cppobj(NULL), static_code(false) {}; - const Rcode* cppobj; - bool static_code; -}; - -typedef CPPPyObjectContainer RcodeContainer; - -int Rcode_init(s_Rcode* const self, PyObject* args); -void Rcode_destroy(s_Rcode* const self); - -PyObject* Rcode_getCode(const s_Rcode* const self); -PyObject* Rcode_getExtendedCode(const s_Rcode* const self); -PyObject* Rcode_toText(const s_Rcode* const self); -PyObject* Rcode_str(PyObject* self); -PyObject* Rcode_richcmp(const s_Rcode* const self, - const s_Rcode* const other, int op); - -PyMethodDef Rcode_methods[] = { - { "get_code", reinterpret_cast(Rcode_getCode), METH_NOARGS, - "Returns the code value" }, - { "get_extended_code", - reinterpret_cast(Rcode_getExtendedCode), METH_NOARGS, - "Returns the upper 8-bit part of the extended code value" }, - { "to_text", reinterpret_cast(Rcode_toText), METH_NOARGS, - "Returns the text representation" }, - { NULL, NULL, 0, NULL } -}; - -int -Rcode_init(s_Rcode* const self, PyObject* args) { - long code = 0; - int ext_code = 0; - - if (PyArg_ParseTuple(args, "l", &code)) { - if (code < 0 || code > 0xffff) { - PyErr_SetString(PyExc_ValueError, "Rcode out of range"); - return (-1); - } - ext_code = -1; - } else if (PyArg_ParseTuple(args, "li", &code, &ext_code)) { - if (code < 0 || code > 0xff || ext_code < 0 || ext_code > 0xff) { - PyErr_SetString(PyExc_ValueError, "Rcode out of range"); - return (-1); - } - } else { - PyErr_Clear(); - PyErr_SetString(PyExc_TypeError, - "Invalid arguments to Rcode constructor"); - return (-1); - } - try { - if (ext_code == -1) { - self->cppobj = new Rcode(code); - } else { - self->cppobj = new Rcode(code, ext_code); - } - self->static_code = false; - } catch (const isc::OutOfRange& ex) { - PyErr_SetString(PyExc_OverflowError, ex.what()); - return (-1); - } catch (...) { - PyErr_SetString(po_IscException, "Unexpected exception"); - return (-1); - } - return (0); -} - -void -Rcode_destroy(s_Rcode* const self) { - // Depending on whether we created the rcode or are referring - // to a global one, we do or do not delete self->cppobj here - if (!self->static_code) { - delete self->cppobj; - } - self->cppobj = NULL; - Py_TYPE(self)->tp_free(self); -} - -PyObject* -Rcode_getCode(const s_Rcode* const self) { - return (Py_BuildValue("I", self->cppobj->getCode())); -} - -PyObject* -Rcode_getExtendedCode(const s_Rcode* const self) { - return (Py_BuildValue("I", self->cppobj->getExtendedCode())); -} - -PyObject* -Rcode_toText(const s_Rcode* const self) { - return (Py_BuildValue("s", self->cppobj->toText().c_str())); -} - -PyObject* -Rcode_str(PyObject* self) { - // Simply call the to_text method we already defined - return (PyObject_CallMethod(self, const_cast("to_text"), - const_cast(""))); -} - -PyObject* -Rcode_richcmp(const s_Rcode* const self, const s_Rcode* const other, - const int op) -{ - bool c = false; - - // Check for null and if the types match. If different type, - // simply return False - if (!other || (self->ob_type != other->ob_type)) { - Py_RETURN_FALSE; - } - - // Only equals and not equals here, unorderable type - switch (op) { - case Py_LT: - PyErr_SetString(PyExc_TypeError, "Unorderable type; Rcode"); - return (NULL); - case Py_LE: - PyErr_SetString(PyExc_TypeError, "Unorderable type; Rcode"); - return (NULL); - case Py_EQ: - c = (*self->cppobj == *other->cppobj); - break; - case Py_NE: - c = (*self->cppobj != *other->cppobj); - break; - case Py_GT: - PyErr_SetString(PyExc_TypeError, "Unorderable type; Rcode"); - return (NULL); - case Py_GE: - PyErr_SetString(PyExc_TypeError, "Unorderable type; Rcode"); - return (NULL); - } - if (c) - Py_RETURN_TRUE; - else - Py_RETURN_FALSE; -} -} // end of unnamed namespace - -namespace isc { -namespace dns { -namespace python { -PyTypeObject rcode_type = { - PyVarObject_HEAD_INIT(NULL, 0) - "pydnspp.Rcode", - sizeof(s_Rcode), // tp_basicsize - 0, // tp_itemsize - (destructor)Rcode_destroy, // tp_dealloc - NULL, // tp_print - NULL, // tp_getattr - NULL, // tp_setattr - NULL, // tp_reserved - NULL, // tp_repr - NULL, // tp_as_number - NULL, // tp_as_sequence - NULL, // tp_as_mapping - NULL, // tp_hash - NULL, // tp_call - Rcode_str, // tp_str - NULL, // tp_getattro - NULL, // tp_setattro - NULL, // tp_as_buffer - Py_TPFLAGS_DEFAULT, // tp_flags - "The Rcode class objects represent standard RCODEs" - "of the header section of DNS messages.", - NULL, // tp_traverse - NULL, // tp_clear - reinterpret_cast(Rcode_richcmp), // tp_richcompare - 0, // tp_weaklistoffset - NULL, // tp_iter - NULL, // tp_iternext - Rcode_methods, // tp_methods - NULL, // tp_members - NULL, // tp_getset - NULL, // tp_base - NULL, // tp_dict - NULL, // tp_descr_get - NULL, // tp_descr_set - 0, // tp_dictoffset - (initproc)Rcode_init, // tp_init - NULL, // tp_alloc - PyType_GenericNew, // tp_new - NULL, // tp_free - NULL, // tp_is_gc - NULL, // tp_bases - NULL, // tp_mro - NULL, // tp_cache - NULL, // tp_subclasses - NULL, // tp_weaklist - NULL, // tp_del - 0 // tp_version_tag -}; - -PyObject* -createRcodeObject(const Rcode& source) { - RcodeContainer container(PyObject_New(s_Rcode, &rcode_type)); - container.set(new Rcode(source)); - return (container.release()); -} - -bool -PyRcode_Check(PyObject* obj) { - if (obj == NULL) { - isc_throw(PyCPPWrapperException, "obj argument NULL in typecheck"); - } - return (PyObject_TypeCheck(obj, &rcode_type)); -} - -const Rcode& -PyRcode_ToRcode(const PyObject* rcode_obj) { - if (rcode_obj == NULL) { - isc_throw(PyCPPWrapperException, - "obj argument NULL in Rcode PyObject conversion"); - } - const s_Rcode* rcode = static_cast(rcode_obj); - return (*rcode->cppobj); -} - -} // namespace python -} // namespace dns -} // namespace isc diff --git a/src/lib/dns/python/rcode_python.h b/src/lib/dns/python/rcode_python.h deleted file mode 100644 index 704821a2ab..0000000000 --- a/src/lib/dns/python/rcode_python.h +++ /dev/null @@ -1,64 +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. - -#ifndef PYTHON_RCODE_H -#define PYTHON_RCODE_H 1 - -#include - -namespace isc { -namespace dns { -class Rcode; - -namespace python { - -extern PyTypeObject rcode_type; - -/// This is a simple shortcut to create a python Rcode object (in the -/// form of a pointer to PyObject) with minimal exception safety. -/// On success, it returns a valid pointer to PyObject with a reference -/// counter of 1; if something goes wrong it throws an exception (it never -/// returns a NULL pointer). -/// This function is expected to be called within a try block -/// followed by necessary setup for python exception. -PyObject* createRcodeObject(const Rcode& source); - -/// \brief Checks if the given python object is a Rcode object -/// -/// \exception PyCPPWrapperException if obj is NULL -/// -/// \param obj The object to check the type of -/// \return true if the object is of type Rcode, false otherwise -bool PyRcode_Check(PyObject* obj); - -/// \brief Returns a reference to the Rcode object contained within the given -/// Python object. -/// -/// \note The given object MUST be of type Rcode; this can be checked with -/// either the right call to ParseTuple("O!"), or with PyRcode_Check() -/// -/// \note This is not a copy; if the Rcode is needed when the PyObject -/// may be destroyed, the caller must copy it itself. -/// -/// \param rcode_obj The rcode object to convert -const Rcode& PyRcode_ToRcode(const PyObject* rcode_obj); - -} // namespace python -} // namespace dns -} // namespace isc -#endif // PYTHON_RCODE_H - -// Local Variables: -// mode: c++ -// End: diff --git a/src/lib/dns/python/rdata_python.cc b/src/lib/dns/python/rdata_python.cc deleted file mode 100644 index 4b5200255f..0000000000 --- a/src/lib/dns/python/rdata_python.cc +++ /dev/null @@ -1,378 +0,0 @@ -// Copyright (C) 2010 Internet Systems Consortium, Inc. ("ISC") -// -// Permission to use, copy, modify, and/or distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -// PERFORMANCE OF THIS SOFTWARE. - -#define PY_SSIZE_T_CLEAN -#include -#include -#include -#include -#include -#include - -#include "rdata_python.h" -#include "rrtype_python.h" -#include "rrclass_python.h" -#include "messagerenderer_python.h" -#include "name_python.h" -#include "pydnspp_common.h" - -using namespace isc::dns; -using namespace isc::dns::python; -using namespace isc::util; -using namespace isc::util::python; -using namespace isc::dns::rdata; - -namespace { - -typedef PyObject* method(PyObject* self, PyObject* args); - -// Wrap a method into an exception handling, converting C++ exceptions -// to python ones. The params and return value is just passed through. -PyObject* -exception_wrap(method* method, PyObject* self, PyObject* args) { - try { - return (method(self, args)); - } catch (const std::exception& ex) { - // FIXME: These exceptions are not tested, I don't know how or if - // at all they can be triggered. But they are caught just in the case. - PyErr_SetString(PyExc_Exception, (std::string("Unknown exception: ") + - ex.what()).c_str()); - return (NULL); - } catch (...) { - PyErr_SetString(PyExc_Exception, "Unknown exception"); - return (NULL); - } -} - -class s_Rdata : public PyObject { -public: - isc::dns::rdata::ConstRdataPtr cppobj; -}; - -typedef CPPPyObjectContainer RdataContainer; - -// -// We declare the functions here, the definitions are below -// the type definition of the object, since both can use the other -// - -// General creation and destruction -int Rdata_init(PyObject* self, PyObject* args, PyObject*); -void Rdata_destroy(PyObject* self); - -// These are the functions we export -PyObject* Rdata_toText(PyObject* self, PyObject*); -// This is a second version of toText, we need one where the argument -// is a PyObject*, for the str() function in python. -PyObject* Rdata_str(PyObject* self); -PyObject* Rdata_toWire(PyObject* self, PyObject* args); -PyObject* RData_richcmp(PyObject* self, PyObject* other, int op); - -// This list contains the actual set of functions we have in -// python. Each entry has -// 1. Python method name -// 2. Our static function here -// 3. Argument type -// 4. Documentation -PyMethodDef Rdata_methods[] = { - { "to_text", Rdata_toText, METH_NOARGS, - "Returns the string representation" }, - { "to_wire", Rdata_toWire, METH_VARARGS, - "Converts the Rdata object to wire format.\n" - "The argument can be either a MessageRenderer or an object that " - "implements the sequence interface. If the object is mutable " - "(for instance a bytearray()), the wire data is added in-place.\n" - "If it is not (for instance a bytes() object), a new object is " - "returned" }, - { NULL, NULL, 0, NULL } -}; - -int -Rdata_init(PyObject* self_p, PyObject* args, PyObject*) { - PyObject* rrtype; - PyObject* rrclass; - const char* s; - const char* data; - Py_ssize_t len; - try { - s_Rdata* self = static_cast(self_p); - - // Create from string - if (PyArg_ParseTuple(args, "O!O!s", &rrtype_type, &rrtype, - &rrclass_type, &rrclass, - &s)) { - self->cppobj = createRdata(PyRRType_ToRRType(rrtype), - PyRRClass_ToRRClass(rrclass), s); - return (0); - } else if (PyArg_ParseTuple(args, "O!O!y#", &rrtype_type, &rrtype, - &rrclass_type, &rrclass, &data, &len)) { - PyErr_Clear(); - InputBuffer input_buffer(data, len); - self->cppobj = createRdata(PyRRType_ToRRType(rrtype), - PyRRClass_ToRRClass(rrclass), - input_buffer, len); - return (0); - } - } catch (const isc::dns::rdata::InvalidRdataText& irdt) { - PyErr_SetString(po_InvalidRdataText, irdt.what()); - return (-1); - } catch (const isc::dns::rdata::InvalidRdataLength& irdl) { - PyErr_SetString(po_InvalidRdataLength, irdl.what()); - return (-1); - } catch (const isc::dns::rdata::CharStringTooLong& cstl) { - PyErr_SetString(po_CharStringTooLong, cstl.what()); - return (-1); - } catch (const isc::dns::DNSMessageFORMERR& dmfe) { - PyErr_SetString(po_DNSMessageFORMERR, dmfe.what()); - return (-1); - } catch (const std::exception& ex) { - // FIXME: These exceptions are not tested, I don't know how or if - // at all they can be triggered. But they are caught just in the case. - PyErr_SetString(PyExc_Exception, (std::string("Unknown exception: ") + - ex.what()).c_str()); - return (-1); - } catch (...) { - PyErr_SetString(PyExc_Exception, "Unknown exception"); - return (-1); - } - - return (-1); -} - -void -Rdata_destroy(PyObject* self) { - // Clear the shared_ptr so that its reference count is zero - // before we call tp_free() (there is no direct release()) - static_cast(self)->cppobj.reset(); - Py_TYPE(self)->tp_free(self); -} - -PyObject* -Rdata_toText_internal(PyObject* self, PyObject*) { - // Py_BuildValue makes python objects from native data - return (Py_BuildValue("s", static_cast(self)->cppobj-> - toText().c_str())); -} - -PyObject* -Rdata_toText(PyObject* self, PyObject* args) { - return (exception_wrap(&Rdata_toText_internal, self, args)); -} - -PyObject* -Rdata_str(PyObject* self) { - // Simply call the to_text method we already defined - return (PyObject_CallMethod(self, - const_cast("to_text"), - const_cast(""))); -} - -PyObject* -Rdata_toWire_internal(PyObject* self_p, PyObject* args) { - PyObject* bytes; - PyObject* mr; - const s_Rdata* self(static_cast(self_p)); - - if (PyArg_ParseTuple(args, "O", &bytes) && PySequence_Check(bytes)) { - PyObject* bytes_o = bytes; - - OutputBuffer buffer(4); - self->cppobj->toWire(buffer); - PyObject* rd_bytes = PyBytes_FromStringAndSize(static_cast(buffer.getData()), buffer.getLength()); - // Make sure exceptions from here are propagated. - // The exception is already set, so we just return NULL - if (rd_bytes == NULL) { - return (NULL); - } - PyObject* result = PySequence_InPlaceConcat(bytes_o, rd_bytes); - // We need to release the object we temporarily created here - // to prevent memory leak - Py_DECREF(rd_bytes); - return (result); - } else if (PyArg_ParseTuple(args, "O!", &messagerenderer_type, &mr)) { - self->cppobj->toWire(PyMessageRenderer_ToMessageRenderer(mr)); - // If we return NULL it is seen as an error, so use this for - // None returns - Py_RETURN_NONE; - } - PyErr_Clear(); - PyErr_SetString(PyExc_TypeError, - "toWire argument must be a sequence object or a MessageRenderer"); - return (NULL); -} - -PyObject* -Rdata_toWire(PyObject* self, PyObject* args) { - return (exception_wrap(&Rdata_toWire_internal, self, args)); -} - -PyObject* -RData_richcmp(PyObject* self_p, PyObject* other_p, int op) { - try { - bool c; - const s_Rdata* self(static_cast(self_p)), - * other(static_cast(other_p)); - - // Check for null and if the types match. If different type, - // simply return False - if (!other || (self->ob_type != other->ob_type)) { - Py_RETURN_FALSE; - } - - switch (op) { - case Py_LT: - c = self->cppobj->compare(*other->cppobj) < 0; - break; - case Py_LE: - c = self->cppobj->compare(*other->cppobj) < 0 || - self->cppobj->compare(*other->cppobj) == 0; - break; - case Py_EQ: - c = self->cppobj->compare(*other->cppobj) == 0; - break; - case Py_NE: - c = self->cppobj->compare(*other->cppobj) != 0; - break; - case Py_GT: - c = self->cppobj->compare(*other->cppobj) > 0; - break; - case Py_GE: - c = self->cppobj->compare(*other->cppobj) > 0 || - self->cppobj->compare(*other->cppobj) == 0; - break; - default: - PyErr_SetString(PyExc_IndexError, - "Unhandled rich comparison operator"); - return (NULL); - } - if (c) { - Py_RETURN_TRUE; - } else { - Py_RETURN_FALSE; - } - } catch (const std::exception& ex) { - // FIXME: These exceptions are not tested, I don't know how or if - // at all they can be triggered. But they are caught just in the case. - PyErr_SetString(PyExc_Exception, (std::string("Unknown exception: ") + - ex.what()).c_str()); - return (NULL); - } catch (...) { - PyErr_SetString(PyExc_Exception, "Unknown exception"); - return (NULL); - } -} - -} // end of unnamed namespace - -namespace isc { -namespace dns { -namespace python { - - -// -// Declaration of the custom exceptions -// Initialization and addition of these go in the initModulePart -// function in pydnspp -// -PyObject* po_InvalidRdataLength; -PyObject* po_InvalidRdataText; -PyObject* po_CharStringTooLong; - -// This defines the complete type for reflection in python and -// parsing of PyObject* to s_Rdata -// Most of the functions are not actually implemented and NULL here. -PyTypeObject rdata_type = { - PyVarObject_HEAD_INIT(NULL, 0) - "pydnspp.Rdata", - sizeof(s_Rdata), // tp_basicsize - 0, // tp_itemsize - Rdata_destroy, // tp_dealloc - NULL, // tp_print - NULL, // tp_getattr - NULL, // tp_setattr - NULL, // tp_reserved - NULL, // tp_repr - NULL, // tp_as_number - NULL, // tp_as_sequence - NULL, // tp_as_mapping - NULL, // tp_hash - NULL, // tp_call - Rdata_str, // tp_str - NULL, // tp_getattro - NULL, // tp_setattro - NULL, // tp_as_buffer - Py_TPFLAGS_DEFAULT, // tp_flags - "The Rdata class is an abstract base class that provides " - "a set of common interfaces to manipulate concrete RDATA objects.", - NULL, // tp_traverse - NULL, // tp_clear - RData_richcmp, // tp_richcompare - 0, // tp_weaklistoffset - NULL, // tp_iter - NULL, // tp_iternext - Rdata_methods, // tp_methods - NULL, // tp_members - NULL, // tp_getset - NULL, // tp_base - NULL, // tp_dict - NULL, // tp_descr_get - NULL, // tp_descr_set - 0, // tp_dictoffset - Rdata_init, // tp_init - NULL, // tp_alloc - PyType_GenericNew, // tp_new - NULL, // tp_free - NULL, // tp_is_gc - NULL, // tp_bases - NULL, // tp_mro - NULL, // tp_cache - NULL, // tp_subclasses - NULL, // tp_weaklist - NULL, // tp_del - 0 // tp_version_tag -}; - -PyObject* -createRdataObject(ConstRdataPtr source) { - s_Rdata* py_rdata = - static_cast(rdata_type.tp_alloc(&rdata_type, 0)); - if (py_rdata == NULL) { - isc_throw(PyCPPWrapperException, "Unexpected NULL C++ object, " - "probably due to short memory"); - } - py_rdata->cppobj = source; - return (py_rdata); -} - -bool -PyRdata_Check(PyObject* obj) { - if (obj == NULL) { - isc_throw(PyCPPWrapperException, "obj argument NULL in typecheck"); - } - return (PyObject_TypeCheck(obj, &rdata_type)); -} - -const Rdata& -PyRdata_ToRdata(const PyObject* rdata_obj) { - if (rdata_obj == NULL) { - isc_throw(PyCPPWrapperException, - "obj argument NULL in Rdata PyObject conversion"); - } - const s_Rdata* rdata = static_cast(rdata_obj); - return (*rdata->cppobj); -} - -} // end python namespace -} // end dns namespace -} // end isc namespace diff --git a/src/lib/dns/python/rdata_python.h b/src/lib/dns/python/rdata_python.h deleted file mode 100644 index 6fa6631b7f..0000000000 --- a/src/lib/dns/python/rdata_python.h +++ /dev/null @@ -1,68 +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. - -#ifndef PYTHON_RDATA_H -#define PYTHON_RDATA_H 1 - -#include - -#include - -namespace isc { -namespace dns { -namespace python { - -extern PyObject* po_InvalidRdataLength; -extern PyObject* po_InvalidRdataText; -extern PyObject* po_CharStringTooLong; - -extern PyTypeObject rdata_type; - -/// This is a simple shortcut to create a python Rdata object (in the -/// form of a pointer to PyObject) with minimal exception safety. -/// On success, it returns a valid pointer to PyObject with a reference -/// counter of 1; if something goes wrong it throws an exception (it never -/// returns a NULL pointer). -/// This function is expected to be called within a try block -/// followed by necessary setup for python exception. -PyObject* createRdataObject(isc::dns::rdata::ConstRdataPtr source); - -/// \brief Checks if the given python object is a Rdata object -/// -/// \exception PyCPPWrapperException if obj is NULL -/// -/// \param obj The object to check the type of -/// \return true if the object is of type Rdata, false otherwise -bool PyRdata_Check(PyObject* obj); - -/// \brief Returns a reference to the Rdata object contained within the given -/// Python object. -/// -/// \note The given object MUST be of type Rdata; this can be checked with -/// either the right call to ParseTuple("O!"), or with PyRdata_Check() -/// -/// \note This is not a copy; if the Rdata is needed when the PyObject -/// may be destroyed, the caller must copy it itself. -/// -/// \param rdata_obj The rdata object to convert -const isc::dns::rdata::Rdata& PyRdata_ToRdata(const PyObject* rdata_obj); - -} // namespace python -} // namespace dns -} // namespace isc -#endif // PYTHON_RDATA_H - -// Local Variables: -// mode: c++ -// End: diff --git a/src/lib/dns/python/rrclass_python.cc b/src/lib/dns/python/rrclass_python.cc deleted file mode 100644 index d62c88dfe6..0000000000 --- a/src/lib/dns/python/rrclass_python.cc +++ /dev/null @@ -1,330 +0,0 @@ -// Copyright (C) 2010 Internet Systems Consortium, Inc. ("ISC") -// -// Permission to use, copy, modify, and/or distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -// PERFORMANCE OF THIS SOFTWARE. -#include - -#include -#include -#include -#include - -#include "rrclass_python.h" -#include "messagerenderer_python.h" -#include "pydnspp_common.h" - - -using namespace isc::dns; -using namespace isc::dns::python; -using namespace isc::util; -using namespace isc::util::python; -namespace { -// The s_* Class simply covers one instantiation of the object -class s_RRClass : public PyObject { -public: - s_RRClass() : cppobj(NULL) {}; - RRClass* cppobj; -}; - -// -// We declare the functions here, the definitions are below -// the type definition of the object, since both can use the other -// - -// General creation and destruction -int RRClass_init(s_RRClass* self, PyObject* args); -void RRClass_destroy(s_RRClass* self); - -// These are the functions we export -PyObject* RRClass_toText(s_RRClass* self); -// This is a second version of toText, we need one where the argument -// is a PyObject*, for the str() function in python. -PyObject* RRClass_str(PyObject* self); -PyObject* RRClass_toWire(s_RRClass* self, PyObject* args); -PyObject* RRClass_getCode(s_RRClass* self); -PyObject* RRClass_richcmp(s_RRClass* self, s_RRClass* other, int op); -Py_hash_t RRClass_hash(PyObject* pyself); - -typedef CPPPyObjectContainer RRClassContainer; - -// This list contains the actual set of functions we have in -// python. Each entry has -// 1. Python method name -// 2. Our static function here -// 3. Argument type -// 4. Documentation -PyMethodDef RRClass_methods[] = { - { "to_text", reinterpret_cast(RRClass_toText), METH_NOARGS, - "Returns the string representation" }, - { "to_wire", reinterpret_cast(RRClass_toWire), METH_VARARGS, - "Converts the RRClass object to wire format.\n" - "The argument can be either a MessageRenderer or an object that " - "implements the sequence interface. If the object is mutable " - "(for instance a bytearray()), the wire data is added in-place.\n" - "If it is not (for instance a bytes() object), a new object is " - "returned" }, - { "get_code", reinterpret_cast(RRClass_getCode), METH_NOARGS, - "Returns the class code as an integer" }, - { NULL, NULL, 0, NULL } -}; - -int -RRClass_init(s_RRClass* self, PyObject* args) { - const char* s; - long i; - PyObject* bytes = NULL; - // The constructor argument can be a string ("IN"), an integer (1), - // or a sequence of numbers between 0 and 65535 (wire code) - - // Note that PyArg_ParseType can set PyError, and we need to clear - // that if we try several like here. Otherwise the *next* python - // call will suddenly appear to throw an exception. - // (the way to do exceptions is to set PyErr and return -1) - try { - if (PyArg_ParseTuple(args, "s", &s)) { - self->cppobj = new RRClass(s); - return (0); - } else if (PyArg_ParseTuple(args, "l", &i)) { - if (i < 0 || i > 0xffff) { - PyErr_Clear(); - PyErr_SetString(PyExc_ValueError, - "RR class number out of range"); - return (-1); - } - self->cppobj = new RRClass(i); - return (0); - } else if (PyArg_ParseTuple(args, "O", &bytes) && PySequence_Check(bytes)) { - uint8_t data[2]; - int result = readDataFromSequence(data, 2, bytes); - if (result != 0) { - return (result); - } - InputBuffer ib(data, 2); - self->cppobj = new RRClass(ib); - PyErr_Clear(); - return (0); - } - // Incomplete is never thrown, a type error would have already been raised - //when we try to read the 2 bytes above - } catch (const InvalidRRClass& ic) { - PyErr_Clear(); - PyErr_SetString(po_InvalidRRClass, ic.what()); - return (-1); - } - PyErr_Clear(); - PyErr_SetString(PyExc_TypeError, - "no valid type in constructor argument"); - return (-1); -} - -void -RRClass_destroy(s_RRClass* self) { - delete self->cppobj; - self->cppobj = NULL; - Py_TYPE(self)->tp_free(self); -} - -PyObject* -RRClass_toText(s_RRClass* self) { - // Py_BuildValue makes python objects from native data - return (Py_BuildValue("s", self->cppobj->toText().c_str())); -} - -PyObject* -RRClass_str(PyObject* self) { - // Simply call the to_text method we already defined - return (PyObject_CallMethod(self, - const_cast("to_text"), - const_cast(""))); -} - -PyObject* -RRClass_toWire(s_RRClass* self, PyObject* args) { - PyObject* bytes; - PyObject* mr; - - if (PyArg_ParseTuple(args, "O", &bytes) && PySequence_Check(bytes)) { - PyObject* bytes_o = bytes; - - OutputBuffer buffer(2); - self->cppobj->toWire(buffer); - PyObject* n = PyBytes_FromStringAndSize(static_cast(buffer.getData()), buffer.getLength()); - PyObject* result = PySequence_InPlaceConcat(bytes_o, n); - // We need to release the object we temporarily created here - // to prevent memory leak - Py_DECREF(n); - return (result); - } else if (PyArg_ParseTuple(args, "O!", &messagerenderer_type, &mr)) { - self->cppobj->toWire(PyMessageRenderer_ToMessageRenderer(mr)); - // If we return NULL it is seen as an error, so use this for - // None returns - Py_RETURN_NONE; - } - PyErr_Clear(); - PyErr_SetString(PyExc_TypeError, - "toWire argument must be a sequence object or a MessageRenderer"); - return (NULL); -} - -PyObject* -RRClass_getCode(s_RRClass* self) { - return (Py_BuildValue("I", self->cppobj->getCode())); -} - -PyObject* -RRClass_richcmp(s_RRClass* self, s_RRClass* other, int op) { - bool c; - - // Check for null and if the types match. If different type, - // simply return False - if (!other || (self->ob_type != other->ob_type)) { - Py_RETURN_FALSE; - } - - switch (op) { - case Py_LT: - c = *self->cppobj < *other->cppobj; - break; - case Py_LE: - c = *self->cppobj < *other->cppobj || - *self->cppobj == *other->cppobj; - break; - case Py_EQ: - c = *self->cppobj == *other->cppobj; - break; - case Py_NE: - c = *self->cppobj != *other->cppobj; - break; - case Py_GT: - c = *other->cppobj < *self->cppobj; - break; - case Py_GE: - c = *other->cppobj < *self->cppobj || - *self->cppobj == *other->cppobj; - break; - default: - PyErr_SetString(PyExc_IndexError, - "Unhandled rich comparison operator"); - return (NULL); - } - if (c) - Py_RETURN_TRUE; - else - Py_RETURN_FALSE; -} - -Py_hash_t -RRClass_hash(PyObject* pyself) { - const s_RRClass* const self = static_cast(pyself); - return (convertToPyHash(self->cppobj->getCode())); -} - -} // end anonymous namespace - -namespace isc { -namespace dns { -namespace python { - -// -// Declaration of the custom exceptions -// Initialization and addition of these go in the initModulePart -// function in pydnspp.cc -// -PyObject* po_InvalidRRClass; -PyObject* po_IncompleteRRClass; - - -// This defines the complete type for reflection in python and -// parsing of PyObject* to s_RRClass -// Most of the functions are not actually implemented and NULL here. -PyTypeObject rrclass_type = { - PyVarObject_HEAD_INIT(NULL, 0) - "pydnspp.RRClass", - sizeof(s_RRClass), // tp_basicsize - 0, // tp_itemsize - (destructor)RRClass_destroy, // tp_dealloc - NULL, // tp_print - NULL, // tp_getattr - NULL, // tp_setattr - NULL, // tp_reserved - NULL, // tp_repr - NULL, // tp_as_number - NULL, // tp_as_sequence - NULL, // tp_as_mapping - RRClass_hash, // tp_hash - NULL, // tp_call - RRClass_str, // tp_str - NULL, // tp_getattro - NULL, // tp_setattro - NULL, // tp_as_buffer - Py_TPFLAGS_DEFAULT, // tp_flags - "The RRClass class encapsulates DNS resource record classes.\n" - "This class manages the 16-bit integer class codes in quite a straightforward" - "way. The only non trivial task is to handle textual representations of" - "RR classes, such as \"IN\", \"CH\", or \"CLASS65534\".", - NULL, // tp_traverse - NULL, // tp_clear - (richcmpfunc)RRClass_richcmp, // tp_richcompare - 0, // tp_weaklistoffset - NULL, // tp_iter - NULL, // tp_iternext - RRClass_methods, // tp_methods - NULL, // tp_members - NULL, // tp_getset - NULL, // tp_base - NULL, // tp_dict - NULL, // tp_descr_get - NULL, // tp_descr_set - 0, // tp_dictoffset - (initproc)RRClass_init, // tp_init - NULL, // tp_alloc - PyType_GenericNew, // tp_new - NULL, // tp_free - NULL, // tp_is_gc - NULL, // tp_bases - NULL, // tp_mro - NULL, // tp_cache - NULL, // tp_subclasses - NULL, // tp_weaklist - NULL, // tp_del - 0 // tp_version_tag -}; - -PyObject* -createRRClassObject(const RRClass& source) { - RRClassContainer container(PyObject_New(s_RRClass, &rrclass_type)); - container.set(new RRClass(source)); - return (container.release()); -} - - -bool -PyRRClass_Check(PyObject* obj) { - if (obj == NULL) { - isc_throw(PyCPPWrapperException, "obj argument NULL in typecheck"); - } - return (PyObject_TypeCheck(obj, &rrclass_type)); -} - -const RRClass& -PyRRClass_ToRRClass(const PyObject* rrclass_obj) { - if (rrclass_obj == NULL) { - isc_throw(PyCPPWrapperException, - "obj argument NULL in RRClass PyObject conversion"); - } - const s_RRClass* rrclass = static_cast(rrclass_obj); - return (*rrclass->cppobj); -} - -} // end namespace python -} // end namespace dns -} // end namespace isc diff --git a/src/lib/dns/python/rrclass_python.h b/src/lib/dns/python/rrclass_python.h deleted file mode 100644 index df5ca703ca..0000000000 --- a/src/lib/dns/python/rrclass_python.h +++ /dev/null @@ -1,68 +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. - -#ifndef PYTHON_RRCLASS_H -#define PYTHON_RRCLASS_H 1 - -#include - -namespace isc { -namespace dns { -class RRClass; - -namespace python { - -extern PyObject* po_InvalidRRClass; -extern PyObject* po_IncompleteRRClass; - -extern PyTypeObject rrclass_type; - -/// This is a simple shortcut to create a python RRClass object (in the -/// form of a pointer to PyObject) with minimal exception safety. -/// On success, it returns a valid pointer to PyObject with a reference -/// counter of 1; if something goes wrong it throws an exception (it never -/// returns a NULL pointer). -/// This function is expected to be called within a try block -/// followed by necessary setup for python exception. -PyObject* createRRClassObject(const RRClass& source); - -/// \brief Checks if the given python object is a RRClass object -/// -/// \exception PyCPPWrapperException if obj is NULL -/// -/// \param obj The object to check the type of -/// \return true if the object is of type RRClass, false otherwise -bool PyRRClass_Check(PyObject* obj); - -/// \brief Returns a reference to the RRClass object contained within the given -/// Python object. -/// -/// \note The given object MUST be of type RRClass; this can be checked with -/// either the right call to ParseTuple("O!"), or with PyRRClass_Check() -/// -/// \note This is not a copy; if the RRClass is needed when the PyObject -/// may be destroyed, the caller must copy it itself. -/// -/// \param rrclass_obj The rrclass object to convert -const RRClass& PyRRClass_ToRRClass(const PyObject* rrclass_obj); - - -} // namespace python -} // namespace dns -} // namespace isc -#endif // PYTHON_RRCLASS_H - -// Local Variables: -// mode: c++ -// End: diff --git a/src/lib/dns/python/rrset_collection_python.cc b/src/lib/dns/python/rrset_collection_python.cc deleted file mode 100644 index cfdcdae2ad..0000000000 --- a/src/lib/dns/python/rrset_collection_python.cc +++ /dev/null @@ -1,453 +0,0 @@ -// 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 - -#include - -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include - -using namespace std; -using namespace isc::util::python; -using namespace isc::dns; -using namespace isc::dns::python; - -// Import pydoc text -#include "rrset_collection_python_inc.cc" - -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); -} -} - -// RRsetCollectionBase: the base RRsetCollection class in Python. -// -// Any derived RRsetCollection class is supposed to be inherited from this -// class: -// - If the derived class is implemented via a C++ wrapper (associated with -// a C++ implementation of RRsetCollection), its PyTypeObject should -// specify rrset_collection_base_type for tp_base. Its C/C++-representation -// of objects should be compatible with s_RRsetCollection, and the wrapper -// should set its cppobj member to point to the corresponding C++ -// RRsetCollection object. Normally it doesn't have to provide Python -// wrapper of find(); the Python interpreter will then call find() on -// the base class, which ensures that the corresponding C++ version of -// find() will be used. -// - If the derived class is implemented purely in Python, it must implement -// find() in Python within the class. As explained in the first bullet, -// the base class method is generally expected to be used only for C++ -// wrapper of RRsetCollection derived class. -namespace { -int -RRsetCollectionBase_init(PyObject*, PyObject*, PyObject*) { - PyErr_SetString(PyExc_TypeError, - "RRsetCollectionBase cannot be instantiated directly"); - return (-1); -} - -void -RRsetCollectionBase_destroy(PyObject* po_self) { - s_RRsetCollection* self = static_cast(po_self); - - // Any C++-wrapper of derived RRsetCollection class should have its own - // destroy function (as it may manage cppobj in its own way); - // Python-only derived classes shouldn't set cppobj (which is - // 0-initialized). So this assertion must hold. - assert(self->cppobj == NULL); - - Py_TYPE(self)->tp_free(self); -} - -PyObject* -RRsetCollectionBase_find(PyObject* po_self, PyObject* args) { - s_RRsetCollection* self = static_cast(po_self); - - // If this function is called with cppobj being NULL, this means - // a pure-Python derived class skips implementing its own find(). - // This is an error (see general description above). - if (self->cppobj == NULL) { - PyErr_Format(PyExc_TypeError, "find() is not implemented in the " - "derived RRsetCollection class"); - return (NULL); - } - - try { - PyObject* po_name; - PyObject* po_rrclass; - PyObject* po_rrtype; - - if (PyArg_ParseTuple(args, "OOO", &po_name, &po_rrclass, &po_rrtype)) { - if (!PyName_Check(po_name)) { - return (setTypeError(po_name, "name", "Name")); - } - if (!PyRRClass_Check(po_rrclass)) { - return (setTypeError(po_rrclass, "rrclass", "RRClass")); - } - if (!PyRRType_Check(po_rrtype)) { - return (setTypeError(po_rrtype, "rrtype", "RRType")); - } - ConstRRsetPtr found_rrset = self->cppobj->find( - PyName_ToName(po_name), PyRRClass_ToRRClass(po_rrclass), - PyRRType_ToRRType(po_rrtype)); - if (found_rrset) { - return (createRRsetObject(*found_rrset)); - } - Py_RETURN_NONE; - } - } catch (const RRsetCollectionError& ex) { - PyErr_SetString(po_RRsetCollectionError, ex.what()); - return (NULL); - } catch (const std::exception& ex) { - const string ex_what = "Unexpected failure in " - "RRsetCollectionBase.find: " + 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); -} - -// This list contains the actual set of functions we have in -// python. Each entry has -// 1. Python method name -// 2. Our static function here -// 3. Argument type -// 4. Documentation -PyMethodDef RRsetCollectionBase_methods[] = { - { "find", RRsetCollectionBase_find, METH_VARARGS, - RRsetCollectionBase_find_doc }, - { NULL, NULL, 0, NULL } -}; -} // end of unnamed namespace - -namespace isc { -namespace dns { -namespace python { -// Definition of class specific exception(s) -PyObject* po_RRsetCollectionError; - -// This defines the complete type for reflection in python and -// parsing of PyObject* to s_RRsetCollection -// Most of the functions are not actually implemented and NULL here. -PyTypeObject rrset_collection_base_type = { - PyVarObject_HEAD_INIT(NULL, 0) - "dns.RRsetCollectionBase", - sizeof(s_RRsetCollection), // tp_basicsize - 0, // tp_itemsize - RRsetCollectionBase_destroy, // tp_dealloc - NULL, // tp_print - NULL, // tp_getattr - NULL, // tp_setattr - NULL, // tp_reserved - NULL, // tp_repr - NULL, // tp_as_number - NULL, // tp_as_sequence - NULL, // tp_as_mapping - NULL, // tp_hash - NULL, // tp_call - NULL, // tp_str - NULL, // tp_getattro - NULL, // tp_setattro - NULL, // tp_as_buffer - Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, // tp_flags (it's inheritable) - RRsetCollectionBase_doc, - NULL, // tp_traverse - NULL, // tp_clear - NULL, // tp_richcompare - 0, // tp_weaklistoffset - NULL, // tp_iter - NULL, // tp_iternext - RRsetCollectionBase_methods, // tp_methods - NULL, // tp_members - NULL, // tp_getset - NULL, // tp_base - NULL, // tp_dict - NULL, // tp_descr_get - NULL, // tp_descr_set - 0, // tp_dictoffset - RRsetCollectionBase_init, // tp_init - NULL, // tp_alloc - PyType_GenericNew, // tp_new - NULL, // tp_free - NULL, // tp_is_gc - NULL, // tp_bases - NULL, // tp_mro - NULL, // tp_cache - NULL, // tp_subclasses - NULL, // tp_weaklist - NULL, // tp_del - 0 // tp_version_tag -}; - -// Module Initialization, all statics are initialized here -bool -initModulePart_RRsetCollectionBase(PyObject* mod) { - if (!initClass(rrset_collection_base_type, "RRsetCollectionBase", mod)) { - return (false); - } - - try { - po_RRsetCollectionError = - PyErr_NewException("dns.RRsetCollectionError", - po_IscException, NULL); - PyObjectContainer(po_RRsetCollectionError).installToModule( - mod, "RRsetCollectionError"); - } catch (const std::exception& ex) { - const std::string ex_what = - "Unexpected failure in RRsetCollectionBase initialization: " + - std::string(ex.what()); - PyErr_SetString(po_IscException, ex_what.c_str()); - return (false); - } catch (...) { - PyErr_SetString(PyExc_SystemError, "Unexpected failure in " - "RRsetCollectionBase initialization"); - return (false); - } - - return (true); -} - -// -// RRsetCollection -// - -namespace { -// Shortcut type which would be convenient for adding class variables safely. -typedef CPPPyObjectContainer RRsetCollectionContainer; - -int -RRsetCollection_init(PyObject* po_self, PyObject* args, PyObject*) { - s_RRsetCollection* self = static_cast(po_self); - try { - const char* filename; - PyObject* po_name; - PyObject* po_rrclass; - Py_buffer py_buf; - - if (PyArg_ParseTuple(args, "sO!O!", &filename, &name_type, &po_name, - &rrclass_type, &po_rrclass)) { - self->cppobj = - new RRsetCollection(filename, PyName_ToName(po_name), - PyRRClass_ToRRClass(po_rrclass)); - return (0); - } else if (PyArg_ParseTuple(args, "y*O!O!", &py_buf, &name_type, - &po_name,&rrclass_type, &po_rrclass)) { - PyErr_Clear(); // clear the error for the first ParseTuple - const char* const cp = static_cast(py_buf.buf); - std::istringstream iss(string(cp, cp + py_buf.len)); - self->cppobj = - new RRsetCollection(iss, PyName_ToName(po_name), - PyRRClass_ToRRClass(po_rrclass)); - return (0); - } else if (PyArg_ParseTuple(args, "")) { - PyErr_Clear(); // clear the error for the second ParseTuple - self->cppobj = new RRsetCollection; - return (0); - } - } catch (const exception& ex) { - const string ex_what = "Failed to construct RRsetCollection object: " + - string(ex.what()); - PyErr_SetString(po_IscException, ex_what.c_str()); - return (-1); - } catch (...) { - PyErr_SetString(PyExc_SystemError, "Unexpected C++ exception"); - return (-1); - } - - // Default error string isn't helpful when it takes multiple combinations - // of args. We provide our own. - PyErr_SetString(PyExc_TypeError, "Invalid argument(s) to RRsetCollection " - "constructor; see pydoc"); - - return (-1); -} - -void -RRsetCollection_destroy(PyObject* po_self) { - s_RRsetCollection* self = static_cast(po_self); - delete self->cppobj; - self->cppobj = NULL; - Py_TYPE(self)->tp_free(self); -} - -PyObject* -RRsetCollection_addRRset(PyObject* po_self, PyObject* args) { - s_RRsetCollection* self = static_cast(po_self); - try { - PyObject* po_rrset; - if (PyArg_ParseTuple(args, "O", &po_rrset)) { - if (!PyRRset_Check(po_rrset)) { - return (setTypeError(po_rrset, "rrset", "RRset")); - } - static_cast(self->cppobj)->addRRset( - PyRRset_ToRRsetPtr(po_rrset)); - Py_RETURN_NONE; - } - } catch (const InvalidParameter& ex) { // duplicate add - PyErr_SetString(PyExc_ValueError, ex.what()); - return (NULL); - } catch (const std::exception& ex) { - const string ex_what = "Unexpected failure in " - "RRsetCollection.add_rrset: " + 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); -} - -PyObject* -RRsetCollection_removeRRset(PyObject* po_self, PyObject* args) { - s_RRsetCollection* self = static_cast(po_self); - try { - PyObject* po_name; - PyObject* po_rrclass; - PyObject* po_rrtype; - - if (PyArg_ParseTuple(args, "OOO", &po_name, &po_rrclass, &po_rrtype)) { - if (!PyName_Check(po_name)) { - return (setTypeError(po_name, "name", "Name")); - } - if (!PyRRClass_Check(po_rrclass)) { - return (setTypeError(po_rrclass, "rrclass", "RRClass")); - } - if (!PyRRType_Check(po_rrtype)) { - return (setTypeError(po_rrtype, "rrtype", "RRType")); - } - const bool result = - static_cast(self->cppobj)->removeRRset( - PyName_ToName(po_name), PyRRClass_ToRRClass(po_rrclass), - PyRRType_ToRRType(po_rrtype)); - if (result) { - Py_RETURN_TRUE; - } else { - Py_RETURN_FALSE; - } - } - } catch (...) {} - - return (NULL); -} - -// This list contains the actual set of functions we have in -// python. Each entry has -// 1. Python method name -// 2. Our static function here -// 3. Argument type -// 4. Documentation -PyMethodDef RRsetCollection_methods[] = { - { "add_rrset", RRsetCollection_addRRset, METH_VARARGS, - RRsetCollection_addRRset_doc }, - { "remove_rrset", RRsetCollection_removeRRset, METH_VARARGS, - RRsetCollection_removeRRset_doc }, - { NULL, NULL, 0, NULL } -}; -} // end of unnamed namespace - -// This defines the complete type for reflection in python and -// parsing of PyObject* to s_RRsetCollection -// Most of the functions are not actually implemented and NULL here. -PyTypeObject rrset_collection_type = { - PyVarObject_HEAD_INIT(NULL, 0) - "dns.RRsetCollection", - sizeof(s_RRsetCollection), // tp_basicsize - 0, // tp_itemsize - RRsetCollection_destroy, // tp_dealloc - NULL, // tp_print - NULL, // tp_getattr - NULL, // tp_setattr - NULL, // tp_reserved - NULL, // tp_repr - NULL, // tp_as_number - NULL, // tp_as_sequence - NULL, // tp_as_mapping - NULL, // tp_hash - NULL, // tp_call - NULL, // tp_str - NULL, // tp_getattro - NULL, // tp_setattro - NULL, // tp_as_buffer - Py_TPFLAGS_DEFAULT, // tp_flags - RRsetCollection_doc, - NULL, // tp_traverse - NULL, // tp_clear - NULL, // tp_richcompare - 0, // tp_weaklistoffset - NULL, // tp_iter - NULL, // tp_iternext - RRsetCollection_methods, // tp_methods - NULL, // tp_members - NULL, // tp_getset - &rrset_collection_base_type, // tp_base - NULL, // tp_dict - NULL, // tp_descr_get - NULL, // tp_descr_set - 0, // tp_dictoffset - RRsetCollection_init, // tp_init - NULL, // tp_alloc - PyType_GenericNew, // tp_new - NULL, // tp_free - NULL, // tp_is_gc - NULL, // tp_bases - NULL, // tp_mro - NULL, // tp_cache - NULL, // tp_subclasses - NULL, // tp_weaklist - NULL, // tp_del - 0 // tp_version_tag -}; - -// Module Initialization, all statics are initialized here -bool -initModulePart_RRsetCollection(PyObject* mod) { - if (!initClass(rrset_collection_type, "RRsetCollection", mod)) { - return (false); - } - - return (true); -} - -} // namespace python -} // namespace dns -} // namespace isc diff --git a/src/lib/dns/python/rrset_collection_python.h b/src/lib/dns/python/rrset_collection_python.h deleted file mode 100644 index ea442bb4ca..0000000000 --- a/src/lib/dns/python/rrset_collection_python.h +++ /dev/null @@ -1,58 +0,0 @@ -// 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_RRSETCOLLECTION_H -#define PYTHON_RRSETCOLLECTION_H 1 - -#include - -namespace isc { -namespace dns { -class RRsetCollectionBase; - -namespace python { - -// The s_* Class simply covers one instantiation of the object. -// This structure will be commonly used for all derived classes of -// RRsetCollectionBase. cppobj will point to an instance of the specific -// derived class of (C++) RRsetCollectionBase. -// -// A C++ wrapper for Python version of RRsetCollection should set this -// variable, and skip the implementation of C++ wrapper of find() method. -class s_RRsetCollection : public PyObject { -public: - s_RRsetCollection() : cppobj(NULL) {} - RRsetCollectionBase* cppobj; -}; - -// Python type information for RRsetCollectionBase -extern PyTypeObject rrset_collection_base_type; - -// Python type information for dns.RRsetCollection -extern PyTypeObject rrset_collection_type; - -// Class specific exceptions -extern PyObject* po_RRsetCollectionError; - -bool initModulePart_RRsetCollectionBase(PyObject* mod); -bool initModulePart_RRsetCollection(PyObject* mod); - -} // namespace python -} // namespace dns -} // namespace isc -#endif // PYTHON_RRSETCOLLECTION_H - -// Local Variables: -// mode: c++ -// End: diff --git a/src/lib/dns/python/rrset_collection_python_inc.cc b/src/lib/dns/python/rrset_collection_python_inc.cc deleted file mode 100644 index baf8ec83b0..0000000000 --- a/src/lib/dns/python/rrset_collection_python_inc.cc +++ /dev/null @@ -1,183 +0,0 @@ -namespace { -// Modifications -// - libdns++ => isc.dns, libdatasrc => isc.datasrc -// - note about the direct construction. -// - add note about iteration -const char* const RRsetCollectionBase_doc = "\ -Generic class to represent a set of RRsets.\n\ -\n\ -This is a generic container and the stored set of RRsets does not\n\ -necessarily form a valid zone (e.g. there doesn't necessarily have to\n\ -be an SOA at the \"origin\"). Instead, it will be used to represent a\n\ -single zone for the purpose of zone loading/checking. It provides a\n\ -simple find() method to find an RRset for the given name and type (and\n\ -maybe class) and a way to iterate over all RRsets.\n\ -\n\ - Note: in the initial version, iteration is not yet supported.\n\ -\n\ -See RRsetCollection for a simple isc.dns implementation. Other modules\n\ -such as isc.datasrc will have another implementation.\n\ -\n\ -This base class cannot be directly instantiated. Such an attempt will\n\ -result in a TypeError exception.\n\ -\n\ -"; - -// Modifications -// - ConstRRset => RRset -// - NULL => None -// - added types of params -const char* const RRsetCollectionBase_find_doc = "\ -find(name, rrclass, rrtype) -> isc.dns.RRset\n\ -\n\ -Find a matching RRset in the collection.\n\ -\n\ -Returns the RRset in the collection that exactly matches the given\n\ -name, rrclass and rrtype. If no matching RRset is found, None is\n\ -returned.\n\ -\n\ -This method's implementations currently are not specified to handle\n\ -RRTypes such as RRSIG and NSEC3. This interface may be refined to\n\ -clarify this point in the future, and perhaps, provide additional API\n\ -for these RRType.\n\ -\n\ -As for RRSIG, there are some fundamental open questions. For example,\n\ -it's not clear whether we want to return all RRSIGs of the given name\n\ -covering any RR types (in which case, we need to figure out how), or\n\ -we need to extend the interface so we can specify the covered type. A\n\ -specific derived implementation may return something if type RRSIG is\n\ -specified, but this is not specified here at the base class level. So,\n\ -for RRSIGs the behavior should be assumed as undefined.\n\ -\n\ -As for NSEC3, it's not clear whether owner names (which included\n\ -hashed labels) are the best choice of search key, because in many\n\ -cases, what the application wants to find is an NSEC3 that has the\n\ -hash of some particular \"normal\" domain names. Also, if the\n\ -underlying implementation encapsulates a single zone, NSEC3 records\n\ -conceptually belong to a separate name space, which may cause\n\ -implementation difficulty.\n\ -\n\ -Behavior with meta types such as ANY and AXFR are also undefined. A\n\ -specific implementation may return something for these. But, unlike\n\ -the case of RRSIGs, these types of RRsets are not expected to be added\n\ -to any implementation of collection in the first place (by the\n\ -definition of \"meta types\"), so querying for such types is\n\ -basically an invalid operation. The API doesn't require\n\ -implementations to check this condition and reject it, so the behavior\n\ -is undefined. This interface will not be refined in future versions\n\ -for these meta types.\n\ -\n\ -Exceptions:\n\ - RRsetCollectionError if find() results in some implementation-\n\ - specific error.\n\ -\n\ -Parameters:\n\ - name (isc.dns.Name) The name of the RRset to search for.\n\ - rrtype (isc.dns.RRType) The type of the RRset to search for.\n\ - rrclass (isc.dns.RRClass) The class of the RRset to search for.\n\ -\n\ -Return Value(s): The RRset if found, None otherwise.\n\ -"; - - -// Modifications -// - libdns++ => isc.dns -// - remove STL -// - MasterLoaderError => IscException -// - added types of params -// - input_stream => input, stream => bytes -const char* const RRsetCollection_doc = "\ -Derived class implementation of RRsetCollectionBase for isc.dns module.\n\ -\n\ -RRsetCollection()\n\ -\n\ - Constructor.\n\ -\n\ - This constructor creates an empty collection without any data in\n\ - it. RRsets can be added to the collection with the add_rrset()\n\ - method.\n\ -\n\ -RRsetCollection(filename, origin, rrclass)\n\ -\n\ - Constructor.\n\ -\n\ - The origin and rrclass arguments are required for the zone\n\ - loading, but RRsetCollection itself does not do any validation,\n\ - and the collection of RRsets does not have to form a valid zone.\n\ - The constructor throws IscException if there is an error\n\ - during loading.\n\ -\n\ - Parameters:\n\ - filename (str) Name of a file containing a collection of RRs in the\n\ - master file format (which may or may not form a valid\n\ - zone).\n\ - origin (isc.dns.Name) The zone origin.\n\ - rrclass (isc.dns.RRClass) The zone class.\n\ -\n\ -RRsetCollection(input, origin, rrclass)\n\ -\n\ - Constructor.\n\ -\n\ - This constructor is similar to the previous one, but instead of\n\ - taking a filename to load a zone from, it takes a bytes object,\n\ - representing the zone contents in text.\n\ - The constructor throws IscException if there is an error\n\ - during loading.\n\ -\n\ - Parameters:\n\ - input (bytes) Textual representation of the zone.\n\ - origin (isc.dns.Name) The zone origin.\n\ - rrclass (isc.dns.RRClass) The zone class.\n\ -\n\ -"; - -// Modifications -// - void => None -// - InvalidParameter => ValueError -// - remove ownership related points (doesn't apply here) -const char* const RRsetCollection_addRRset_doc = "\ -add_rrset(rrset) -> None\n\ -\n\ -Add an RRset to the collection.\n\ -\n\ -Does not do any validation whether rrset belongs to a particular zone\n\ -or not.\n\ -\n\ -It throws a ValueError exception if an rrset with the same\n\ -class, type and name already exists.\n\ -\n\ -"; - -// Modifications -// - ConstRRset => RRset -const char* const RRsetCollection_find_doc = "\ -find(name, rrclass, rrtype) -> isc.dns.RRset\n\ -\n\ -Find a matching RRset in the collection.\n\ -\n\ -Returns the RRset in the collection that exactly matches the given\n\ -name, rrclass and rrtype. If no matching RRset is found, None is\n\ -returned.\n\ -\n\ -Parameters:\n\ - name The name of the RRset to search for.\n\ - rrclass The class of the RRset to search for.\n\ - rrtype The type of the RRset to search for.\n\ -\n\ -Return Value(s): The RRset if found, None otherwise.\n\ -"; - -// Modifications -// // - true/false => True/False -const char* const RRsetCollection_removeRRset_doc = "\ -remove_rrset(name, rrclass, rrtype) -> bool\n\ -\n\ -Remove an RRset from the collection.\n\ -\n\ -RRset(s) matching the name, rrclass and rrtype are removed from the\n\ -collection.\n\ -\n\ -True if a matching RRset was deleted, False if no such RRset exists.\n\ -\n\ -"; -} // unnamed namespace diff --git a/src/lib/dns/python/rrset_python.cc b/src/lib/dns/python/rrset_python.cc deleted file mode 100644 index 4d864d1d8a..0000000000 --- a/src/lib/dns/python/rrset_python.cc +++ /dev/null @@ -1,482 +0,0 @@ -// Copyright (C) 2010 Internet Systems Consortium, Inc. ("ISC") -// -// Permission to use, copy, modify, and/or distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -// PERFORMANCE OF THIS SOFTWARE. - -#include - -#include - -#include -#include -#include - -#include "name_python.h" -#include "pydnspp_common.h" -#include "rrset_python.h" -#include "rrclass_python.h" -#include "rrtype_python.h" -#include "rrttl_python.h" -#include "rdata_python.h" -#include "messagerenderer_python.h" - -using namespace std; -using namespace isc::dns; -using namespace isc::dns::python; -using namespace isc::util; -using namespace isc::util::python; - -namespace { - -// The s_* Class simply coverst one instantiation of the object - -// Using a shared_ptr here should not really be necessary (PyObject -// is already reference-counted), however internally on the cpp side, -// not doing so might result in problems, since we can't copy construct -// rdata field, adding them to rrsets results in a problem when the -// rrset is destroyed later -class s_RRset : public PyObject { -public: - isc::dns::RRsetPtr cppobj; -}; - -int RRset_init(s_RRset* self, PyObject* args); -void RRset_destroy(s_RRset* self); - -PyObject* RRset_getRdataCount(PyObject* self, PyObject* args); -PyObject* RRset_getLength(PyObject* self, PyObject* args); -PyObject* RRset_getName(PyObject* self, PyObject* args); -PyObject* RRset_getClass(PyObject* self, PyObject* args); -PyObject* RRset_getType(PyObject* self, PyObject* args); -PyObject* RRset_getTTL(PyObject* self, PyObject* args); -PyObject* RRset_setTTL(PyObject* self, PyObject* args); -PyObject* RRset_toText(PyObject* self, PyObject* args); -PyObject* RRset_str(PyObject* self); -PyObject* RRset_toWire(PyObject* self, PyObject* args); -PyObject* RRset_addRdata(PyObject* self, PyObject* args); -PyObject* RRset_getRdata(PyObject* po_self, PyObject* args); -PyObject* RRset_removeRRsig(PyObject* self, PyObject* args); - -// TODO: iterator? - -PyMethodDef RRset_methods[] = { - { "get_rdata_count", RRset_getRdataCount, METH_NOARGS, - "Returns the number of rdata fields." }, - { "get_length", RRset_getLength, METH_NOARGS, - "Returns the wire format length of the RRset." }, - { "get_name", RRset_getName, METH_NOARGS, - "Returns the name of the RRset, as a Name object." }, - { "get_class", RRset_getClass, METH_NOARGS, - "Returns the class of the RRset as an RRClass object." }, - { "get_type", RRset_getType, METH_NOARGS, - "Returns the type of the RRset as an RRType object." }, - { "get_ttl", RRset_getTTL, METH_NOARGS, - "Returns the TTL of the RRset as an RRTTL object." }, - { "set_ttl", RRset_setTTL, METH_VARARGS, - "Sets the TTL of the RRset.\nTakes an RRTTL object as an argument." }, - { "to_text", RRset_toText, METH_NOARGS, - "Returns the text representation of the RRset as a string" }, - { "to_wire", RRset_toWire, METH_VARARGS, - "Converts the RRset object to wire format.\n" - "The argument can be either a MessageRenderer or an object that " - "implements the sequence interface. If the object is mutable " - "(for instance a bytearray()), the wire data is added in-place.\n" - "If it is not (for instance a bytes() object), a new object is " - "returned" }, - { "add_rdata", RRset_addRdata, METH_VARARGS, - "Adds the rdata for one RR to the RRset.\nTakes an Rdata object as an argument" }, - { "get_rdata", RRset_getRdata, METH_NOARGS, - "Returns a List containing all Rdata elements" }, - { "remove_rrsig", RRset_removeRRsig, METH_NOARGS, - "Clears the list of RRsigs for this RRset" }, - { NULL, NULL, 0, NULL } -}; - -int -RRset_init(s_RRset* self, PyObject* args) { - PyObject* name; - PyObject* rrclass; - PyObject* rrtype; - PyObject* rrttl; - - if (PyArg_ParseTuple(args, "O!O!O!O!", &name_type, &name, - &rrclass_type, &rrclass, - &rrtype_type, &rrtype, - &rrttl_type, &rrttl - )) { - self->cppobj = RRsetPtr(new RRset(PyName_ToName(name), - PyRRClass_ToRRClass(rrclass), - PyRRType_ToRRType(rrtype), - PyRRTTL_ToRRTTL(rrttl))); - return (0); - } - - self->cppobj = RRsetPtr(); - return (-1); -} - -void -RRset_destroy(s_RRset* self) { - // Clear the shared_ptr so that its reference count is zero - // before we call tp_free() (there is no direct release()) - self->cppobj.reset(); - Py_TYPE(self)->tp_free(self); -} - -PyObject* -RRset_getRdataCount(PyObject* self, PyObject*) { - return (Py_BuildValue("I", static_cast(self)->cppobj-> - getRdataCount())); -} - -PyObject* -RRset_getLength(PyObject* self, PyObject*) { - try { - return (Py_BuildValue("H", static_cast(self)->cppobj-> - getLength())); - } catch (const EmptyRRset& ers) { - PyErr_Clear(); - PyErr_SetString(po_EmptyRRset, ers.what()); - return (NULL); - } -} - -PyObject* -RRset_getName(PyObject* self, PyObject*) { - try { - return (createNameObject(static_cast(self)->cppobj-> - getName())); - } catch (const exception& ex) { - const string ex_what = - "Unexpected failure getting rrset Name: " + - string(ex.what()); - PyErr_SetString(po_IscException, ex_what.c_str()); - } catch (...) { - PyErr_SetString(PyExc_SystemError, - "Unexpected failure getting rrset Name"); - } - return (NULL); -} - -PyObject* -RRset_getClass(PyObject* self, PyObject*) { - try { - return (createRRClassObject(static_cast(self)->cppobj-> - getClass())); - } catch (const exception& ex) { - const string ex_what = - "Unexpected failure getting question RRClass: " + - string(ex.what()); - PyErr_SetString(po_IscException, ex_what.c_str()); - } catch (...) { - PyErr_SetString(PyExc_SystemError, - "Unexpected failure getting question RRClass"); - } - return (NULL); -} - -PyObject* -RRset_getType(PyObject* self, PyObject*) { - try { - return (createRRTypeObject(static_cast(self)->cppobj-> - getType())); - } catch (const exception& ex) { - const string ex_what = - "Unexpected failure getting question RRType: " + - string(ex.what()); - PyErr_SetString(po_IscException, ex_what.c_str()); - } catch (...) { - PyErr_SetString(PyExc_SystemError, - "Unexpected failure getting question RRType"); - } - return (NULL); -} - -PyObject* -RRset_getTTL(PyObject* self, PyObject*) { - try { - return (createRRTTLObject(static_cast(self)->cppobj-> - getTTL())); - } catch (const exception& ex) { - const string ex_what = - "Unexpected failure getting question TTL: " + - string(ex.what()); - PyErr_SetString(po_IscException, ex_what.c_str()); - } catch (...) { - PyErr_SetString(PyExc_SystemError, - "Unexpected failure getting question TTL"); - } - return (NULL); -} - -PyObject* -RRset_setTTL(PyObject* self, PyObject* args) { - PyObject* rrttl; - if (!PyArg_ParseTuple(args, "O!", &rrttl_type, &rrttl)) { - return (NULL); - } - static_cast(self)->cppobj->setTTL(PyRRTTL_ToRRTTL(rrttl)); - Py_RETURN_NONE; -} - -PyObject* -RRset_toText(PyObject* self, PyObject*) { - try { - return (Py_BuildValue("s", static_cast(self)->cppobj-> - toText().c_str())); - } catch (const EmptyRRset& ers) { - PyErr_SetString(po_EmptyRRset, ers.what()); - return (NULL); - } -} - -PyObject* -RRset_str(PyObject* self) { - // Simply call the to_text method we already defined - return (PyObject_CallMethod(self, - const_cast("to_text"), - const_cast(""))); -} - -PyObject* -RRset_toWire(PyObject* self_p, PyObject* args) { - PyObject* bytes; - PyObject* mr; - - try { - const s_RRset* self = static_cast(self_p); - if (PyArg_ParseTuple(args, "O", &bytes) && PySequence_Check(bytes)) { - PyObject* bytes_o = bytes; - - OutputBuffer buffer(4096); - self->cppobj->toWire(buffer); - PyObject* n = PyBytes_FromStringAndSize(static_cast(buffer.getData()), buffer.getLength()); - PyObject* result = PySequence_InPlaceConcat(bytes_o, n); - // We need to release the object we temporarily created here - // to prevent memory leak - Py_DECREF(n); - return (result); - } else if (PyArg_ParseTuple(args, "O!", &messagerenderer_type, &mr)) { - self->cppobj->toWire(PyMessageRenderer_ToMessageRenderer(mr)); - // If we return NULL it is seen as an error, so use this for - // None returns - Py_RETURN_NONE; - } - } catch (const EmptyRRset& ers) { - PyErr_Clear(); - PyErr_SetString(po_EmptyRRset, ers.what()); - return (NULL); - } - PyErr_Clear(); - PyErr_SetString(PyExc_TypeError, - "toWire argument must be a sequence object or a MessageRenderer"); - return (NULL); -} - -PyObject* -RRset_addRdata(PyObject* self, PyObject* args) { - PyObject* rdata; - if (!PyArg_ParseTuple(args, "O!", &rdata_type, &rdata)) { - return (NULL); - } - try { - static_cast(self)->cppobj->addRdata(PyRdata_ToRdata(rdata)); - Py_RETURN_NONE; - } catch (const std::bad_cast&) { - PyErr_Clear(); - PyErr_SetString(PyExc_TypeError, - "Rdata type to add must match type of RRset"); - } catch (const exception& ex) { - const string ex_what = - "Unexpected failure adding rrset Rdata: " + - string(ex.what()); - PyErr_SetString(po_IscException, ex_what.c_str()); - } catch (...) { - PyErr_SetString(PyExc_SystemError, - "Unexpected failure adding rrset Rdata"); - } - return (NULL); -} - -PyObject* -RRset_getRdata(PyObject* po_self, PyObject*) { - const s_RRset* const self = static_cast(po_self); - - try { - PyObjectContainer list_container(PyList_New(0)); - - for (RdataIteratorPtr it = self->cppobj->getRdataIterator(); - !it->isLast(); it->next()) { - if (PyList_Append(list_container.get(), - PyObjectContainer( - createRdataObject( - createRdata(self->cppobj->getType(), - self->cppobj->getClass(), - it->getCurrent()))).get()) - == -1) { - isc_throw(PyCPPWrapperException, "PyList_Append failed, " - "probably due to short memory"); - } - } - return (list_container.release()); - } catch (const exception& ex) { - const string ex_what = - "Unexpected failure getting rrset Rdata: " + - string(ex.what()); - PyErr_SetString(po_IscException, ex_what.c_str()); - } catch (...) { - PyErr_SetString(PyExc_SystemError, - "Unexpected failure getting rrset Rdata"); - } - return (NULL); -} - -PyObject* -RRset_removeRRsig(PyObject* self, PyObject*) { - static_cast(self)->cppobj->removeRRsig(); - Py_RETURN_NONE; -} - -} // end of unnamed namespace - -namespace isc { -namespace dns { -namespace python { - -// -// Declaration of the custom exceptions -// Initialization and addition of these go in the module init at the -// end -// -PyObject* po_EmptyRRset; - -PyTypeObject rrset_type = { - PyVarObject_HEAD_INIT(NULL, 0) - "pydnspp.RRset", - sizeof(s_RRset), // tp_basicsize - 0, // tp_itemsize - (destructor)RRset_destroy, // tp_dealloc - NULL, // tp_print - NULL, // tp_getattr - NULL, // tp_setattr - NULL, // tp_reserved - NULL, // tp_repr - NULL, // tp_as_number - NULL, // tp_as_sequence - NULL, // tp_as_mapping - NULL, // tp_hash - NULL, // tp_call - RRset_str, // tp_str - NULL, // tp_getattro - NULL, // tp_setattro - NULL, // tp_as_buffer - Py_TPFLAGS_DEFAULT, // tp_flags - "The AbstractRRset class is an abstract base class that " - "models a DNS RRset.\n\n" - "An object of (a specific derived class of) AbstractRRset " - "models an RRset as described in the DNS standard:\n" - "A set of DNS resource records (RRs) of the same type and class. " - "The standard requires the TTL of all RRs in an RRset be the same; " - "this class follows that requirement.\n\n" - "Note about duplicate RDATA: RFC2181 states that it's meaningless that an " - "RRset contains two identical RRs and that name servers should suppress " - "such duplicates.\n" - "This class is not responsible for ensuring this requirement: For example, " - "addRdata() method doesn't check if there's already RDATA identical " - "to the one being added.\n" - "This is because such checks can be expensive, and it's often easy to " - "ensure the uniqueness requirement at the %data preparation phase " - "(e.g. when loading a zone).", - NULL, // tp_traverse - NULL, // tp_clear - NULL, // tp_richcompare - 0, // tp_weaklistoffset - NULL, // tp_iter - NULL, // tp_iternext - RRset_methods, // tp_methods - NULL, // tp_members - NULL, // tp_getset - NULL, // tp_base - NULL, // tp_dict - NULL, // tp_descr_get - NULL, // tp_descr_set - 0, // tp_dictoffset - (initproc)RRset_init, // tp_init - NULL, // tp_alloc - PyType_GenericNew, // tp_new - NULL, // tp_free - NULL, // tp_is_gc - NULL, // tp_bases - NULL, // tp_mro - NULL, // tp_cache - NULL, // tp_subclasses - NULL, // tp_weaklist - NULL, // tp_del - 0 // tp_version_tag -}; - -PyObject* -createRRsetObject(const AbstractRRset& source) { - - // RRsets are noncopyable, so as a workaround we recreate a new one - // and copy over all content - RRsetPtr new_rrset = isc::dns::RRsetPtr( - new isc::dns::RRset(source.getName(), source.getClass(), - source.getType(), source.getTTL())); - - isc::dns::RdataIteratorPtr rdata_it(source.getRdataIterator()); - for (rdata_it->first(); !rdata_it->isLast(); rdata_it->next()) { - new_rrset->addRdata(rdata_it->getCurrent()); - } - - isc::dns::RRsetPtr sigs = source.getRRsig(); - if (sigs) { - new_rrset->addRRsig(sigs); - } - s_RRset* py_rrset = - static_cast(rrset_type.tp_alloc(&rrset_type, 0)); - if (py_rrset == NULL) { - isc_throw(PyCPPWrapperException, "Unexpected NULL C++ object, " - "probably due to short memory"); - } - py_rrset->cppobj = new_rrset; - return (py_rrset); -} - -bool -PyRRset_Check(PyObject* obj) { - if (obj == NULL) { - isc_throw(PyCPPWrapperException, "obj argument NULL in typecheck"); - } - return (PyObject_TypeCheck(obj, &rrset_type)); -} - -AbstractRRset& -PyRRset_ToRRset(PyObject* rrset_obj) { - s_RRset* rrset = static_cast(rrset_obj); - return (*rrset->cppobj); -} - -RRsetPtr -PyRRset_ToRRsetPtr(PyObject* rrset_obj) { - if (rrset_obj == NULL) { - isc_throw(PyCPPWrapperException, - "obj argument NULL in RRset PyObject conversion"); - } - s_RRset* rrset = static_cast(rrset_obj); - return (rrset->cppobj); -} - - -} // end python namespace -} // end dns namespace -} // end isc namespace diff --git a/src/lib/dns/python/rrset_python.h b/src/lib/dns/python/rrset_python.h deleted file mode 100644 index 9faac954f0..0000000000 --- a/src/lib/dns/python/rrset_python.h +++ /dev/null @@ -1,78 +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. - -#ifndef PYTHON_RRSET_H -#define PYTHON_RRSET_H 1 - -#include - -#include - -#include - -namespace isc { -namespace dns { -namespace python { - -extern PyObject* po_EmptyRRset; - -extern PyTypeObject rrset_type; - -/// This is a simple shortcut to create a python RRset object (in the -/// form of a pointer to PyObject) with minimal exception safety. -/// On success, it returns a valid pointer to PyObject with a reference -/// counter of 1; if something goes wrong it throws an exception (it never -/// returns a NULL pointer). -/// This function is expected to be called within a try block -/// followed by necessary setup for python exception. -PyObject* createRRsetObject(const AbstractRRset& source); - -/// \brief Checks if the given python object is a RRset object -/// -/// \exception PyCPPWrapperException if obj is NULL -/// -/// \param obj The object to check the type of -/// \return true if the object is of type RRset, false otherwise -bool PyRRset_Check(PyObject* obj); - -/// \brief Returns a reference to the RRset object contained within the given -/// Python object. -/// -/// \note The given object MUST be of type RRset; this can be checked with -/// either the right call to ParseTuple("O!"), or with PyRRset_Check() -/// -/// \note This is not a copy; if the RRset is needed when the PyObject -/// may be destroyed, the caller must copy it itself. -/// -/// \param rrset_obj The rrset object to convert -AbstractRRset& PyRRset_ToRRset(PyObject* rrset_obj); - -/// \brief Returns the shared_ptr of the RRset object contained within the -/// given Python object. -/// -/// \note The given object MUST be of type RRset; this can be checked with -/// either the right call to ParseTuple("O!"), or with PyRRset_Check() -/// -/// \param rrset_obj The rrset object to convert -RRsetPtr PyRRset_ToRRsetPtr(PyObject* rrset_obj); - - -} // namespace python -} // namespace dns -} // namespace isc -#endif // PYTHON_RRSET_H - -// Local Variables: -// mode: c++ -// End: diff --git a/src/lib/dns/python/rrttl_python.cc b/src/lib/dns/python/rrttl_python.cc deleted file mode 100644 index 3a3f067755..0000000000 --- a/src/lib/dns/python/rrttl_python.cc +++ /dev/null @@ -1,321 +0,0 @@ -// Copyright (C) 2010 Internet Systems Consortium, Inc. ("ISC") -// -// Permission to use, copy, modify, and/or distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -// PERFORMANCE OF THIS SOFTWARE. - -#include -#include - -#include -#include -#include -#include - -#include "rrttl_python.h" -#include "pydnspp_common.h" -#include "messagerenderer_python.h" - -using namespace std; -using namespace isc::dns; -using namespace isc::dns::python; -using namespace isc::util; -using namespace isc::util::python; - -namespace { -// The s_* Class simply covers one instantiation of the object -class s_RRTTL : public PyObject { -public: - s_RRTTL() : cppobj(NULL) {}; - isc::dns::RRTTL* cppobj; -}; - -typedef CPPPyObjectContainer RRTTLContainer; - -PyObject* RRTTL_toText(s_RRTTL* self); -// This is a second version of toText, we need one where the argument -// is a PyObject*, for the str() function in python. -PyObject* RRTTL_str(PyObject* self); -PyObject* RRTTL_toWire(s_RRTTL* self, PyObject* args); -PyObject* RRTTL_getValue(s_RRTTL* self); -PyObject* RRTTL_richcmp(s_RRTTL* self, s_RRTTL* other, int op); - -// This list contains the actual set of functions we have in -// python. Each entry has -// 1. Python method name -// 2. Our static function here -// 3. Argument type -// 4. Documentation -PyMethodDef RRTTL_methods[] = { - { "to_text", reinterpret_cast(RRTTL_toText), METH_NOARGS, - "Returns the string representation" }, - { "to_wire", reinterpret_cast(RRTTL_toWire), METH_VARARGS, - "Converts the RRTTL object to wire format.\n" - "The argument can be either a MessageRenderer or an object that " - "implements the sequence interface. If the object is mutable " - "(for instance a bytearray()), the wire data is added in-place.\n" - "If it is not (for instance a bytes() object), a new object is " - "returned" }, - { "get_value", reinterpret_cast(RRTTL_getValue), METH_NOARGS, - "Returns the TTL as an integer" }, - { NULL, NULL, 0, NULL } -}; - -int -RRTTL_init(s_RRTTL* self, PyObject* args) { - const char* s; - long long i; - PyObject* bytes = NULL; - // The constructor argument can be a string ("1234"), an integer (1), - // or a sequence of numbers between 0 and 255 (wire code) - - // Note that PyArg_ParseType can set PyError, and we need to clear - // that if we try several like here. Otherwise the *next* python - // call will suddenly appear to throw an exception. - // (the way to do exceptions is to set PyErr and return -1) - try { - if (PyArg_ParseTuple(args, "s", &s)) { - self->cppobj = new RRTTL(s); - return (0); - } else if (PyArg_ParseTuple(args, "L", &i)) { - PyErr_Clear(); - if (i < 0 || i > 0xffffffff) { - PyErr_SetString(PyExc_ValueError, "RR TTL number out of range"); - return (-1); - } - self->cppobj = new RRTTL(i); - return (0); - } else if (PyArg_ParseTuple(args, "O", &bytes) && - PySequence_Check(bytes)) { - Py_ssize_t size = PySequence_Size(bytes); - vector data(size); - int result = readDataFromSequence(&data[0], size, bytes); - if (result != 0) { - return (result); - } - InputBuffer ib(&data[0], size); - self->cppobj = new RRTTL(ib); - PyErr_Clear(); - return (0); - } - } catch (const IncompleteRRTTL& icc) { - // Ok so one of our functions has thrown a C++ exception. - // We need to translate that to a Python Exception - // First clear any existing error that was set - PyErr_Clear(); - // Now set our own exception - PyErr_SetString(po_IncompleteRRTTL, icc.what()); - // And return negative - return (-1); - } catch (const InvalidRRTTL& ic) { - PyErr_Clear(); - PyErr_SetString(po_InvalidRRTTL, ic.what()); - return (-1); - } - PyErr_Clear(); - PyErr_SetString(PyExc_TypeError, - "no valid type in constructor argument"); - return (-1); -} - -void -RRTTL_destroy(s_RRTTL* self) { - delete self->cppobj; - self->cppobj = NULL; - Py_TYPE(self)->tp_free(self); -} - -PyObject* -RRTTL_toText(s_RRTTL* self) { - // Py_BuildValue makes python objects from native data - return (Py_BuildValue("s", self->cppobj->toText().c_str())); -} - -PyObject* -RRTTL_str(PyObject* self) { - // Simply call the to_text method we already defined - return (PyObject_CallMethod(self, - const_cast("to_text"), - const_cast(""))); -} - -PyObject* -RRTTL_toWire(s_RRTTL* self, PyObject* args) { - PyObject* bytes; - PyObject* mr; - - if (PyArg_ParseTuple(args, "O", &bytes) && PySequence_Check(bytes)) { - PyObject* bytes_o = bytes; - - OutputBuffer buffer(4); - self->cppobj->toWire(buffer); - PyObject* n = PyBytes_FromStringAndSize(static_cast(buffer.getData()), - buffer.getLength()); - PyObject* result = PySequence_InPlaceConcat(bytes_o, n); - // We need to release the object we temporarily created here - // to prevent memory leak - Py_DECREF(n); - return (result); - } else if (PyArg_ParseTuple(args, "O!", &messagerenderer_type, &mr)) { - self->cppobj->toWire(PyMessageRenderer_ToMessageRenderer(mr)); - // If we return NULL it is seen as an error, so use this for - // None returns - Py_RETURN_NONE; - } - PyErr_Clear(); - PyErr_SetString(PyExc_TypeError, - "toWire argument must be a sequence object or a MessageRenderer"); - return (NULL); -} - -PyObject* -RRTTL_getValue(s_RRTTL* self) { - return (Py_BuildValue("I", self->cppobj->getValue())); -} - -PyObject* -RRTTL_richcmp(s_RRTTL* self, s_RRTTL* other, int op) { - bool c = false; - - // Check for null and if the types match. If different type, - // simply return False - if (!other || (self->ob_type != other->ob_type)) { - Py_RETURN_FALSE; - } - - switch (op) { - case Py_LT: - c = *self->cppobj < *other->cppobj; - break; - case Py_LE: - c = *self->cppobj < *other->cppobj || - *self->cppobj == *other->cppobj; - break; - case Py_EQ: - c = *self->cppobj == *other->cppobj; - break; - case Py_NE: - c = *self->cppobj != *other->cppobj; - break; - case Py_GT: - c = *other->cppobj < *self->cppobj; - break; - case Py_GE: - c = *other->cppobj < *self->cppobj || - *self->cppobj == *other->cppobj; - break; - } - if (c) - Py_RETURN_TRUE; - else - Py_RETURN_FALSE; -} - -} // end anonymous namespace - -namespace isc { -namespace dns { -namespace python { - -// -// Declaration of the custom exceptions -// Initialization and addition of these go in the initModulePart -// function in pydnspp.cc -// -PyObject* po_InvalidRRTTL; -PyObject* po_IncompleteRRTTL; - -// This defines the complete type for reflection in python and -// parsing of PyObject* to s_RRTTL -// Most of the functions are not actually implemented and NULL here. -PyTypeObject rrttl_type = { - PyVarObject_HEAD_INIT(NULL, 0) - "pydnspp.RRTTL", - sizeof(s_RRTTL), // tp_basicsize - 0, // tp_itemsize - (destructor)RRTTL_destroy, // tp_dealloc - NULL, // tp_print - NULL, // tp_getattr - NULL, // tp_setattr - NULL, // tp_reserved - NULL, // tp_repr - NULL, // tp_as_number - NULL, // tp_as_sequence - NULL, // tp_as_mapping - NULL, // tp_hash - NULL, // tp_call - RRTTL_str, // tp_str - NULL, // tp_getattro - NULL, // tp_setattro - NULL, // tp_as_buffer - Py_TPFLAGS_DEFAULT, // tp_flags - "The RRTTL class encapsulates TTLs used in DNS resource records.\n\n" - "This is a straightforward class; an RRTTL object simply maintains a " - "32-bit unsigned integer corresponding to the TTL value. The main purpose " - "of this class is to provide convenient interfaces to convert a textual " - "representation into the integer TTL value and vice versa, and to handle " - "wire-format representations.", - NULL, // tp_traverse - NULL, // tp_clear - (richcmpfunc)RRTTL_richcmp, // tp_richcompare - 0, // tp_weaklistoffset - NULL, // tp_iter - NULL, // tp_iternext - RRTTL_methods, // tp_methods - NULL, // tp_members - NULL, // tp_getset - NULL, // tp_base - NULL, // tp_dict - NULL, // tp_descr_get - NULL, // tp_descr_set - 0, // tp_dictoffset - (initproc)RRTTL_init, // tp_init - NULL, // tp_alloc - PyType_GenericNew, // tp_new - NULL, // tp_free - NULL, // tp_is_gc - NULL, // tp_bases - NULL, // tp_mro - NULL, // tp_cache - NULL, // tp_subclasses - NULL, // tp_weaklist - NULL, // tp_del - 0 // tp_version_tag -}; - -PyObject* -createRRTTLObject(const RRTTL& source) { - RRTTLContainer container(PyObject_New(s_RRTTL, &rrttl_type)); - container.set(new RRTTL(source)); - return (container.release()); -} - -bool -PyRRTTL_Check(PyObject* obj) { - if (obj == NULL) { - isc_throw(PyCPPWrapperException, "obj argument NULL in typecheck"); - } - return (PyObject_TypeCheck(obj, &rrttl_type)); -} - -const RRTTL& -PyRRTTL_ToRRTTL(const PyObject* rrttl_obj) { - if (rrttl_obj == NULL) { - isc_throw(PyCPPWrapperException, - "obj argument NULL in RRTTL PyObject conversion"); - } - const s_RRTTL* rrttl = static_cast(rrttl_obj); - return (*rrttl->cppobj); -} - -} // namespace python -} // namespace dns -} // namespace isc diff --git a/src/lib/dns/python/rrttl_python.h b/src/lib/dns/python/rrttl_python.h deleted file mode 100644 index 9ad904feda..0000000000 --- a/src/lib/dns/python/rrttl_python.h +++ /dev/null @@ -1,67 +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. - -#ifndef PYTHON_RRTTL_H -#define PYTHON_RRTTL_H 1 - -#include - -namespace isc { -namespace dns { -class RRTTL; - -namespace python { - -extern PyObject* po_InvalidRRTTL; -extern PyObject* po_IncompleteRRTTL; - -extern PyTypeObject rrttl_type; - -/// This is a simple shortcut to create a python RRTTL object (in the -/// form of a pointer to PyObject) with minimal exception safety. -/// On success, it returns a valid pointer to PyObject with a reference -/// counter of 1; if something goes wrong it throws an exception (it never -/// returns a NULL pointer). -/// This function is expected to be called within a try block -/// followed by necessary setup for python exception. -PyObject* createRRTTLObject(const RRTTL& source); - -/// \brief Checks if the given python object is a RRTTL object -/// -/// \exception PyCPPWrapperException if obj is NULL -/// -/// \param obj The object to check the type of -/// \return true if the object is of type RRTTL, false otherwise -bool PyRRTTL_Check(PyObject* obj); - -/// \brief Returns a reference to the RRTTL object contained within the given -/// Python object. -/// -/// \note The given object MUST be of type RRTTL; this can be checked with -/// either the right call to ParseTuple("O!"), or with PyRRTTL_Check() -/// -/// \note This is not a copy; if the RRTTL is needed when the PyObject -/// may be destroyed, the caller must copy it itself. -/// -/// \param rrttl_obj The rrttl object to convert -const RRTTL& PyRRTTL_ToRRTTL(const PyObject* rrttl_obj); - -} // namespace python -} // namespace dns -} // namespace isc -#endif // PYTHON_RRTTL_H - -// Local Variables: -// mode: c++ -// End: diff --git a/src/lib/dns/python/rrtype_python.cc b/src/lib/dns/python/rrtype_python.cc deleted file mode 100644 index bf705ccb5d..0000000000 --- a/src/lib/dns/python/rrtype_python.cc +++ /dev/null @@ -1,326 +0,0 @@ -// Copyright (C) 2010 Internet Systems Consortium, Inc. ("ISC") -// -// Permission to use, copy, modify, and/or distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -// PERFORMANCE OF THIS SOFTWARE. - -#include -#include - -#include -#include -#include - -#include "rrtype_python.h" -#include "messagerenderer_python.h" -#include "pydnspp_common.h" - -using namespace std; -using namespace isc::dns; -using namespace isc::dns::python; -using namespace isc::util; -using namespace isc::util::python; - -namespace { -// The s_* Class simply covers one instantiation of the object -class s_RRType : public PyObject { -public: - const RRType* cppobj; -}; - -// General creation and destruction -int RRType_init(s_RRType* self, PyObject* args); -void RRType_destroy(s_RRType* self); - -// These are the functions we export -PyObject* -RRType_toText(s_RRType* self); -// This is a second version of toText, we need one where the argument -// is a PyObject*, for the str() function in python. -PyObject* RRType_str(PyObject* self); -PyObject* RRType_toWire(s_RRType* self, PyObject* args); -PyObject* RRType_getCode(s_RRType* self); -PyObject* RRType_richcmp(s_RRType* self, s_RRType* other, int op); -Py_hash_t RRType_hash(PyObject* pyself); - -typedef CPPPyObjectContainer RRTypeContainer; - -// This list contains the actual set of functions we have in -// python. Each entry has -// 1. Python method name -// 2. Our static function here -// 3. Argument type -// 4. Documentation -PyMethodDef RRType_methods[] = { - { "to_text", reinterpret_cast(RRType_toText), METH_NOARGS, - "Returns the string representation" }, - { "to_wire", reinterpret_cast(RRType_toWire), METH_VARARGS, - "Converts the RRType object to wire format.\n" - "The argument can be either a MessageRenderer or an object that " - "implements the sequence interface. If the object is mutable " - "(for instance a bytearray()), the wire data is added in-place.\n" - "If it is not (for instance a bytes() object), a new object is " - "returned" }, - { "get_code", reinterpret_cast(RRType_getCode), METH_NOARGS, - "Returns the type code as an integer" }, - { NULL, NULL, 0, NULL } -}; - -int -RRType_init(s_RRType* self, PyObject* args) { - const char* s; - long i; - PyObject* bytes = NULL; - // The constructor argument can be a string ("A"), an integer (1), - // or a sequence of numbers between 0 and 65535 (wire code) - - // Note that PyArg_ParseType can set PyError, and we need to clear - // that if we try several like here. Otherwise the *next* python - // call will suddenly appear to throw an exception. - // (the way to do exceptions is to set PyErr and return -1) - try { - if (PyArg_ParseTuple(args, "s", &s)) { - self->cppobj = new RRType(s); - return (0); - } else if (PyArg_ParseTuple(args, "l", &i)) { - PyErr_Clear(); - if (i < 0 || i > 0xffff) { - PyErr_SetString(PyExc_ValueError, "RR Type number out of range"); - return (-1); - } - self->cppobj = new RRType(i); - return (0); - } else if (PyArg_ParseTuple(args, "O", &bytes) && PySequence_Check(bytes)) { - Py_ssize_t size = PySequence_Size(bytes); - vector data(size); - int result = readDataFromSequence(&data[0], size, bytes); - if (result != 0) { - return (result); - } - InputBuffer ib(&data[0], size); - self->cppobj = new RRType(ib); - PyErr_Clear(); - return (0); - } - } catch (const IncompleteRRType& icc) { - // Ok so one of our functions has thrown a C++ exception. - // We need to translate that to a Python Exception - // First clear any existing error that was set - PyErr_Clear(); - // Now set our own exception - PyErr_SetString(po_IncompleteRRType, icc.what()); - // And return negative - return (-1); - } catch (const InvalidRRType& ic) { - PyErr_Clear(); - PyErr_SetString(po_InvalidRRType, ic.what()); - return (-1); - } - PyErr_Clear(); - PyErr_SetString(PyExc_TypeError, - "no valid type in constructor argument"); - return (-1); -} - -void -RRType_destroy(s_RRType* self) { - delete self->cppobj; - self->cppobj = NULL; - Py_TYPE(self)->tp_free(self); -} - -PyObject* -RRType_toText(s_RRType* self) { - // Py_BuildValue makes python objects from native data - return (Py_BuildValue("s", self->cppobj->toText().c_str())); -} - -PyObject* -RRType_str(PyObject* self) { - // Simply call the to_text method we already defined - return (PyObject_CallMethod(self, const_cast("to_text"), - const_cast(""))); -} - -PyObject* -RRType_toWire(s_RRType* self, PyObject* args) { - PyObject* bytes; - PyObject* mr; - - if (PyArg_ParseTuple(args, "O", &bytes) && PySequence_Check(bytes)) { - PyObject* bytes_o = bytes; - - OutputBuffer buffer(2); - self->cppobj->toWire(buffer); - PyObject* n = PyBytes_FromStringAndSize(static_cast(buffer.getData()), buffer.getLength()); - PyObject* result = PySequence_InPlaceConcat(bytes_o, n); - // We need to release the object we temporarily created here - // to prevent memory leak - Py_DECREF(n); - return (result); - } else if (PyArg_ParseTuple(args, "O!", &messagerenderer_type, &mr)) { - self->cppobj->toWire(PyMessageRenderer_ToMessageRenderer(mr)); - // If we return NULL it is seen as an error, so use this for - // None returns - Py_RETURN_NONE; - } - PyErr_Clear(); - PyErr_SetString(PyExc_TypeError, - "toWire argument must be a sequence object or a MessageRenderer"); - return (NULL); -} - -PyObject* -RRType_getCode(s_RRType* self) { - return (Py_BuildValue("I", self->cppobj->getCode())); -} - -PyObject* -RRType_richcmp(s_RRType* self, s_RRType* other, int op) { - bool c; - - // Check for null and if the types match. If different type, - // simply return False - if (!other || (self->ob_type != other->ob_type)) { - Py_RETURN_FALSE; - } - - switch (op) { - case Py_LT: - c = *self->cppobj < *other->cppobj; - break; - case Py_LE: - c = *self->cppobj < *other->cppobj || - *self->cppobj == *other->cppobj; - break; - case Py_EQ: - c = *self->cppobj == *other->cppobj; - break; - case Py_NE: - c = *self->cppobj != *other->cppobj; - break; - case Py_GT: - c = *other->cppobj < *self->cppobj; - break; - case Py_GE: - c = *other->cppobj < *self->cppobj || - *self->cppobj == *other->cppobj; - break; - default: - PyErr_SetString(PyExc_IndexError, - "Unhandled rich comparison operator"); - return (NULL); - } - if (c) - Py_RETURN_TRUE; - else - Py_RETURN_FALSE; -} - -Py_hash_t -RRType_hash(PyObject* pyself) { - const s_RRType* const self = static_cast(pyself); - return (convertToPyHash(self->cppobj->getCode())); -} -} // end anonymous namespace - -namespace isc { -namespace dns { -namespace python { - -PyObject* po_InvalidRRType; -PyObject* po_IncompleteRRType; - -// This defines the complete type for reflection in python and -// parsing of PyObject* to s_RRType -// Most of the functions are not actually implemented and NULL here. -PyTypeObject rrtype_type = { - PyVarObject_HEAD_INIT(NULL, 0) - "pydnspp.RRType", - sizeof(s_RRType), // tp_basicsize - 0, // tp_itemsize - (destructor)RRType_destroy, // tp_dealloc - NULL, // tp_print - NULL, // tp_getattr - NULL, // tp_setattr - NULL, // tp_reserved - NULL, // tp_repr - NULL, // tp_as_number - NULL, // tp_as_sequence - NULL, // tp_as_mapping - RRType_hash, // tp_hash - NULL, // tp_call - RRType_str, // tp_str - NULL, // tp_getattro - NULL, // tp_setattro - NULL, // tp_as_buffer - Py_TPFLAGS_DEFAULT, // tp_flags - "The RRType class encapsulates DNS resource record types.\n\n" - "This class manages the 16-bit integer type codes in quite a straightforward " - "way. The only non trivial task is to handle textual representations of " - "RR types, such as \"A\", \"AAAA\", or \"TYPE65534\".", - NULL, // tp_traverse - NULL, // tp_clear - (richcmpfunc)RRType_richcmp, // tp_richcompare - 0, // tp_weaklistoffset - NULL, // tp_iter - NULL, // tp_iternext - RRType_methods, // tp_methods - NULL, // tp_members - NULL, // tp_getset - NULL, // tp_base - NULL, // tp_dict - NULL, // tp_descr_get - NULL, // tp_descr_set - 0, // tp_dictoffset - (initproc)RRType_init, // tp_init - NULL, // tp_alloc - PyType_GenericNew, // tp_new - NULL, // tp_free - NULL, // tp_is_gc - NULL, // tp_bases - NULL, // tp_mro - NULL, // tp_cache - NULL, // tp_subclasses - NULL, // tp_weaklist - NULL, // tp_del - 0 // tp_version_tag -}; - -PyObject* -createRRTypeObject(const RRType& source) { - RRTypeContainer container(PyObject_New(s_RRType, &rrtype_type)); - container.set(new RRType(source)); - return (container.release()); -} - -bool -PyRRType_Check(PyObject* obj) { - if (obj == NULL) { - isc_throw(PyCPPWrapperException, "obj argument NULL in typecheck"); - } - return (PyObject_TypeCheck(obj, &rrtype_type)); -} - -const RRType& -PyRRType_ToRRType(const PyObject* rrtype_obj) { - if (rrtype_obj == NULL) { - isc_throw(PyCPPWrapperException, - "obj argument NULL in RRType PyObject conversion"); - } - const s_RRType* rrtype = static_cast(rrtype_obj); - return (*rrtype->cppobj); -} - - -} // end namespace python -} // end namespace dns -} // end namespace isc diff --git a/src/lib/dns/python/rrtype_python.h b/src/lib/dns/python/rrtype_python.h deleted file mode 100644 index 3595952d0c..0000000000 --- a/src/lib/dns/python/rrtype_python.h +++ /dev/null @@ -1,68 +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. - -#ifndef PYTHON_RRTYPE_H -#define PYTHON_RRTYPE_H 1 - -#include - -namespace isc { -namespace dns { -class RRType; - -namespace python { - -extern PyObject* po_InvalidRRType; -extern PyObject* po_IncompleteRRType; - -extern PyTypeObject rrtype_type; - -/// This is a simple shortcut to create a python RRType object (in the -/// form of a pointer to PyObject) with minimal exception safety. -/// On success, it returns a valid pointer to PyObject with a reference -/// counter of 1; if something goes wrong it throws an exception (it never -/// returns a NULL pointer). -/// This function is expected to be called within a try block -/// followed by necessary setup for python exception. -PyObject* createRRTypeObject(const RRType& source); - -/// \brief Checks if the given python object is a RRType object -/// -/// \exception PyCPPWrapperException if obj is NULL -/// -/// \param obj The object to check the type of -/// \return true if the object is of type RRType, false otherwise -bool PyRRType_Check(PyObject* obj); - -/// \brief Returns a reference to the RRType object contained within the given -/// Python object. -/// -/// \note The given object MUST be of type RRType; this can be checked with -/// either the right call to ParseTuple("O!"), or with PyRRType_Check() -/// -/// \note This is not a copy; if the RRType is needed when the PyObject -/// may be destroyed, the caller must copy it itself. -/// -/// \param rrtype_obj The rrtype object to convert -const RRType& PyRRType_ToRRType(const PyObject* rrtype_obj); - - -} // namespace python -} // namespace dns -} // namespace isc -#endif // PYTHON_RRTYPE_H - -// Local Variables: -// mode: c++ -// End: diff --git a/src/lib/dns/python/serial_python.cc b/src/lib/dns/python/serial_python.cc deleted file mode 100644 index f4f4720df5..0000000000 --- a/src/lib/dns/python/serial_python.cc +++ /dev/null @@ -1,273 +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. - -#include - -#include -#include - -#include "serial_python.h" -#include "pydnspp_common.h" - -using namespace std; -using namespace isc::dns; -using namespace isc::dns::python; -using namespace isc::util; -using namespace isc::util::python; - -namespace { -// The s_* Class simply covers one instantiation of the object -class s_Serial : public PyObject { -public: - s_Serial() : cppobj(NULL) {}; - isc::dns::Serial* cppobj; -}; - -typedef CPPPyObjectContainer SerialContainer; - -PyObject* Serial_str(PyObject* self); -PyObject* Serial_getValue(s_Serial* self); -PyObject* Serial_richcmp(s_Serial* self, s_Serial* other, int op); -PyObject* Serial_add(PyObject *right, PyObject *left); - -// This list contains the actual set of functions we have in -// python. Each entry has -// 1. Python method name -// 2. Our static function here -// 3. Argument type -// 4. Documentation -PyMethodDef Serial_methods[] = { - { "get_value", reinterpret_cast(Serial_getValue), METH_NOARGS, - "Returns the Serial value as an integer" }, - { NULL, NULL, 0, NULL } -}; - -// For overriding the + operator. We do not define any other operators for -// this type. -PyNumberMethods Serial_NumberMethods = { - Serial_add, //nb_add; - NULL, //nb_subtract; - NULL, //nb_multiply; - NULL, //nb_remainder; - NULL, //nb_divmod; - NULL, //nb_power; - NULL, //nb_negative; - NULL, //nb_positive; - NULL, //nb_absolute; - NULL, //nb_bool; - NULL, //nb_invert; - NULL, //nb_lshift; - NULL, //nb_rshift; - NULL, //nb_and; - NULL, //nb_xor; - NULL, //nb_or; - NULL, //nb_int; - NULL, //nb_reserved; - NULL, //nb_float; - - NULL, //nb_inplace_add; - NULL, //nb_inplace_subtract; - NULL, //nb_inplace_multiply; - NULL, //nb_inplace_remainder; - NULL, //nb_inplace_power; - NULL, //nb_inplace_lshift; - NULL, //nb_inplace_rshift; - NULL, //nb_inplace_and; - NULL, //nb_inplace_xor; - NULL, //nb_inplace_or; - - NULL, //nb_floor_divide; - NULL, //nb_true_divide; - NULL, //nb_inplace_floor_divide; - NULL, //nb_inplace_true_divide; - - NULL, //nb_index; -}; - -int -Serial_init(s_Serial* self, PyObject* args) { - long long i; - if (PyArg_ParseTuple(args, "L", &i)) { - PyErr_Clear(); - if (i < 0 || i > 0xffffffff) { - PyErr_SetString(PyExc_ValueError, "Serial number out of range"); - return (-1); - } - self->cppobj = new Serial(i); - return (0); - } else { - return (-1); - } -} - -void -Serial_destroy(s_Serial* self) { - delete self->cppobj; - self->cppobj = NULL; - Py_TYPE(self)->tp_free(self); -} - -PyObject* -Serial_getValue(s_Serial* self) { - return (Py_BuildValue("I", self->cppobj->getValue())); -} - -PyObject* -Serial_str(PyObject* po_self) { - const s_Serial* const self = static_cast(po_self); - return (PyUnicode_FromFormat("%u", self->cppobj->getValue())); -} - -PyObject* -Serial_richcmp(s_Serial* self, s_Serial* other, int op) { - bool c = false; - - // Check for null and if the types match. If different type, - // simply return False - if (!other || (self->ob_type != other->ob_type)) { - Py_RETURN_FALSE; - } - - switch (op) { - case Py_LT: - c = *self->cppobj < *other->cppobj; - break; - case Py_LE: - c = *self->cppobj <= *other->cppobj; - break; - case Py_EQ: - c = *self->cppobj == *other->cppobj; - break; - case Py_NE: - c = *self->cppobj != *other->cppobj; - break; - case Py_GT: - c = *self->cppobj > *other->cppobj; - break; - case Py_GE: - c = *self->cppobj >= *other->cppobj; - break; - } - if (c) { - Py_RETURN_TRUE; - } else { - Py_RETURN_FALSE; - } -} - -PyObject * -Serial_add(PyObject *left, PyObject *right) { - // Either can be either a serial or a long, as long as one of them is a - // serial - if (PySerial_Check(left) && PySerial_Check(right)) { - return (createSerialObject(PySerial_ToSerial(left) + - PySerial_ToSerial(right))); - } else if (PySerial_Check(left) && PyLong_Check(right)) { - return (createSerialObject(PySerial_ToSerial(left) + - PyLong_AsLong(right))); - } else if (PyLong_Check(left) && PySerial_Check(right)) { - return (createSerialObject(PySerial_ToSerial(right) + - PyLong_AsLong(left))); - } else { - Py_INCREF(Py_NotImplemented); - return Py_NotImplemented; - } -} - -} // end anonymous namespace - -namespace isc { -namespace dns { -namespace python { -// This defines the complete type for reflection in python and -// parsing of PyObject* to s_Serial -// Most of the functions are not actually implemented and NULL here. -PyTypeObject serial_type = { - PyVarObject_HEAD_INIT(NULL, 0) - "pydnspp.Serial", - sizeof(s_Serial), // tp_basicsize - 0, // tp_itemsize - (destructor)Serial_destroy, // tp_dealloc - NULL, // tp_print - NULL, // tp_getattr - NULL, // tp_setattr - NULL, // tp_reserved - NULL, // tp_repr - &Serial_NumberMethods, // tp_as_number - NULL, // tp_as_sequence - NULL, // tp_as_mapping - NULL, // tp_hash - NULL, // tp_call - Serial_str, // tp_str - NULL, // tp_getattro - NULL, // tp_setattro - NULL, // tp_as_buffer - Py_TPFLAGS_DEFAULT, // tp_flags - "The Serial class encapsulates Serials used in DNS SOA records.\n\n" - "This is a straightforward class; an Serial object simply maintains a " - "32-bit unsigned integer corresponding to the SOA SERIAL value. The " - "main purpose of this class is to provide serial number arithmetic, as " - "described in RFC 1892. Objects of this type can be compared and added " - "to each other, as described in RFC 1892. Apart from str(), get_value(), " - "comparison operators, and the + operator, no other operations are " - "defined for this type.", - NULL, // tp_traverse - NULL, // tp_clear - (richcmpfunc)Serial_richcmp, // tp_richcompare - 0, // tp_weaklistoffset - NULL, // tp_iter - NULL, // tp_iternext - Serial_methods, // tp_methods - NULL, // tp_members - NULL, // tp_getset - NULL, // tp_base - NULL, // tp_dict - NULL, // tp_descr_get - NULL, // tp_descr_set - 0, // tp_dictoffset - (initproc)Serial_init, // tp_init - NULL, // tp_alloc - PyType_GenericNew, // tp_new - NULL, // tp_free - NULL, // tp_is_gc - NULL, // tp_bases - NULL, // tp_mro - NULL, // tp_cache - NULL, // tp_subclasses - NULL, // tp_weaklist - NULL, // tp_del - 0 // tp_version_tag -}; - -PyObject* -createSerialObject(const Serial& source) { - SerialContainer container(PyObject_New(s_Serial, &serial_type)); - container.set(new Serial(source)); - return (container.release()); -} - -bool -PySerial_Check(PyObject* obj) { - return (PyObject_TypeCheck(obj, &serial_type)); -} - -const Serial& -PySerial_ToSerial(const PyObject* serial_obj) { - const s_Serial* serial = static_cast(serial_obj); - return (*serial->cppobj); -} - -} // namespace python -} // namespace dns -} // namespace isc diff --git a/src/lib/dns/python/serial_python.h b/src/lib/dns/python/serial_python.h deleted file mode 100644 index 9a495be5be..0000000000 --- a/src/lib/dns/python/serial_python.h +++ /dev/null @@ -1,64 +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. - -#ifndef PYTHON_SERIAL_H -#define PYTHON_SERIAL_H 1 - -#include - -namespace isc { -namespace dns { -class Serial; - -namespace python { - -extern PyTypeObject serial_type; - -/// This is a simple shortcut to create a python Serial object (in the -/// form of a pointer to PyObject) with minimal exception safety. -/// On success, it returns a valid pointer to PyObject with a reference -/// counter of 1; if something goes wrong it throws an exception (it never -/// returns a NULL pointer). -/// This function is expected to be called within a try block -/// followed by necessary setup for python exception. -PyObject* createSerialObject(const Serial& source); - -/// \brief Checks if the given python object is a Serial object -/// -/// \exception PyCPPWrapperException if obj is NULL -/// -/// \param obj The object to check the type of -/// \return true if the object is of type Serial, false otherwise -bool PySerial_Check(PyObject* obj); - -/// \brief Returns a reference to the Serial object contained within the given -/// Python object. -/// -/// \note The given object MUST be of type Serial; this can be checked with -/// either the right call to ParseTuple("O!"), or with PySerial_Check() -/// -/// \note This is not a copy; if the Serial is needed when the PyObject -/// may be destroyed, the caller must copy it itself. -/// -/// \param Serial_obj The Serial object to convert -const Serial& PySerial_ToSerial(const PyObject* Serial_obj); - -} // namespace python -} // namespace dns -} // namespace isc -#endif // PYTHON_SERIAL_H - -// Local Variables: -// mode: c++ -// End: diff --git a/src/lib/dns/python/tests/Makefile.am b/src/lib/dns/python/tests/Makefile.am deleted file mode 100644 index 8fe8bb7667..0000000000 --- a/src/lib/dns/python/tests/Makefile.am +++ /dev/null @@ -1,53 +0,0 @@ -PYCOVERAGE_RUN = @PYCOVERAGE_RUN@ -PYTESTS = edns_python_test.py -PYTESTS += message_python_test.py -PYTESTS += messagerenderer_python_test.py -PYTESTS += name_python_test.py -PYTESTS += nsec3hash_python_test.py -PYTESTS += question_python_test.py -PYTESTS += opcode_python_test.py -PYTESTS += pydnspp_python_test.py -PYTESTS += rcode_python_test.py -PYTESTS += rdata_python_test.py -PYTESTS += rrclass_python_test.py -PYTESTS += rrset_python_test.py -PYTESTS += rrttl_python_test.py -PYTESTS += rrtype_python_test.py -PYTESTS += rrset_collection_python_test.py -PYTESTS += serial_python_test.py -PYTESTS += tsig_python_test.py -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 - -# If necessary (rare cases), explicitly specify paths to dynamic libraries -# required by loadable python modules. -LIBRARY_PATH_PLACEHOLDER = -if SET_ENV_LIBRARY_PATH -LIBRARY_PATH_PLACEHOLDER += $(ENV_LIBRARY_PATH)=$(abs_top_builddir)/src/lib/dns/.libs:$(abs_top_builddir)/src/lib/dns/python/.libs:$(abs_top_builddir)/src/lib/cryptolink/.libs:$(abs_top_builddir)/src/lib/util/.libs:$(abs_top_builddir)/src/lib/util/threads/.libs:$(abs_top_builddir)/src/lib/exceptions/.libs:$$$(ENV_LIBRARY_PATH) -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 - rm -f .coverage - ${LN_S} $(abs_top_srcdir)/.coverage .coverage -endif - for pytest in $(PYTESTS) ; do \ - echo Running test: $$pytest ; \ - env PYTHONPATH=$(abs_top_builddir)/src/lib/util/pyunittests/.libs:$(abs_top_srcdir)/src/lib/dns/.libs:$(abs_top_srcdir)/src/lib/python:$(abs_top_builddir)/src/lib/python:$(abs_top_builddir)/src/lib/dns/python/.libs \ - TESTDATA_PATH=$(abs_top_srcdir)/src/lib/dns/tests/testdata:$(abs_top_builddir)/src/lib/dns/tests/testdata \ - $(LIBRARY_PATH_PLACEHOLDER) \ - $(PYCOVERAGE_RUN) $(abs_srcdir)/$$pytest || exit ; \ - done - -CLEANDIRS = __pycache__ - -clean-local: - rm -rf $(CLEANDIRS) diff --git a/src/lib/dns/python/tests/edns_python_test.py b/src/lib/dns/python/tests/edns_python_test.py deleted file mode 100644 index 150dfd6f0b..0000000000 --- a/src/lib/dns/python/tests/edns_python_test.py +++ /dev/null @@ -1,177 +0,0 @@ -# Copyright (C) 2010 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 os -from pydnspp import * -from testutil import * - -class EDNSTest(unittest.TestCase): - - def setUp(self): - self.rrtype = RRType("OPT") - self.rrclass = RRClass(4096) - self.rrttl_do_on = RRTTL(0x00008000) - self.rrttl_do_off = RRTTL(0) - self.rrttl_badver = RRTTL(0x00018000) - self.opt_rdata = Rdata(self.rrtype, self.rrclass, bytes()) - self.edns_base = EDNS(Name.ROOT_NAME, self.rrclass, self.rrtype, - self.rrttl_do_off, self.opt_rdata) - - def test_badver_construct(self): - self.assertRaises(InvalidParameter, EDNS, 1) - self.assertRaises(TypeError, EDNS, 1, 2) # signature mismatch - self.assertRaises(TypeError, EDNS, 256) # invalid arguments - - def test_dnssec_dobit(self): - edns = EDNS(Name.ROOT_NAME, self.rrclass, self.rrtype, - self.rrttl_do_on, self.opt_rdata) - self.assertTrue(edns.get_dnssec_awareness()) - - edns = EDNS(Name.ROOT_NAME, self.rrclass, self.rrtype, - self.rrttl_do_off, self.opt_rdata) - self.assertFalse(edns.get_dnssec_awareness()) - - edns = EDNS() - self.assertFalse(edns.get_dnssec_awareness()) - edns.set_dnssec_awareness(True) - self.assertTrue(edns.get_dnssec_awareness()) - edns.set_dnssec_awareness(False); - self.assertFalse(edns.get_dnssec_awareness()) - - self.assertRaises(TypeError, edns.set_dnssec_awareness, "wrong") - self.assertRaises(TypeError, edns.set_dnssec_awareness, 1) - - def test_udpsize(self): - edns = EDNS(Name.ROOT_NAME, self.rrclass, self.rrtype, - self.rrttl_do_on, self.opt_rdata) - self.assertEqual(4096, edns.get_udp_size()) - - edns = EDNS() - edns.set_udp_size(511) - self.assertEqual(511, edns.get_udp_size()) - self.assertRaises(TypeError, edns.set_udp_size, "wrong") - - # Range check. We need to do this at the binding level, so we need - # explicit tests for it. - edns.set_udp_size(0) - self.assertEqual(0, edns.get_udp_size()) - edns.set_udp_size(65535) - self.assertEqual(65535, edns.get_udp_size()) - self.assertRaises(ValueError, edns.set_udp_size, 0x10000) - self.assertRaises(ValueError, edns.set_udp_size, -1) - - def test_get_version(self): - self.assertEqual(EDNS.SUPPORTED_VERSION, EDNS().get_version()) - - def test_bad_wiredata(self): - self.assertRaises(InvalidParameter, EDNS, Name.ROOT_NAME, - self.rrclass, RRType("A"), - self.rrttl_do_on, self.opt_rdata) - self.assertRaises(DNSMessageFORMERR, EDNS, Name("example.com"), - self.rrclass, self.rrtype, self.rrttl_do_on, - self.opt_rdata) - self.assertRaises(DNSMessageBADVERS, EDNS, Name.ROOT_NAME, - self.rrclass, self.rrtype, self.rrttl_badver, - self.opt_rdata) - - def test_to_text(self): - edns = EDNS() - edns.set_udp_size(4096) - expected_str = "; EDNS: version: 0, flags:; udp: 4096\n" - self.assertEqual(expected_str, edns.to_text()) - self.assertEqual(expected_str, str(edns)) - - edns.set_dnssec_awareness(True) - self.assertEqual("; EDNS: version: 0, flags: do; udp: 4096\n", - edns.to_text()) - - self.assertEqual("; EDNS: version: 0, flags: do; udp: 4096\n", - EDNS(Name.ROOT_NAME, self.rrclass, self.rrtype, - RRTTL(0x01008000), self.opt_rdata).to_text()) - - self.assertEqual("; EDNS: version: 0, flags: do; udp: 4096\n", - EDNS(Name.ROOT_NAME, self.rrclass, self.rrtype, - RRTTL(0x00008001), self.opt_rdata).to_text()) - - def test_towire_renderer(self): - renderer = MessageRenderer() - extrcode_noerror = Rcode.NOERROR.get_extended_code() - extrcode_badvers = Rcode.BADVERS.get_extended_code() - - self.assertEqual(1, self.edns_base.to_wire(renderer, extrcode_noerror)) - wiredata = read_wire_data("edns_toWire1.wire") - self.assertEqual(wiredata, renderer.get_data()) - - renderer.clear() - self.edns_base.set_dnssec_awareness(True) - self.assertEqual(1, self.edns_base.to_wire(renderer, extrcode_noerror)) - wiredata = read_wire_data("edns_toWire2.wire") - self.assertEqual(wiredata, renderer.get_data()) - - renderer.clear() - self.edns_base.set_dnssec_awareness(True) - self.assertEqual(1, self.edns_base.to_wire(renderer, extrcode_badvers)) - wiredata = read_wire_data("edns_toWire3.wire") - self.assertEqual(wiredata, renderer.get_data()) - - renderer.clear() - self.edns_base.set_dnssec_awareness(True) - self.edns_base.set_udp_size(511) - self.assertEqual(1, self.edns_base.to_wire(renderer, extrcode_noerror)) - wiredata = read_wire_data("edns_toWire4.wire") - self.assertEqual(wiredata, renderer.get_data()) - - renderer.clear() - edns = EDNS(Name.ROOT_NAME, self.rrclass, self.rrtype, - RRTTL(0x00008001), self.opt_rdata) - self.assertEqual(1, edns.to_wire(renderer, extrcode_noerror)) - wiredata = read_wire_data("edns_toWire2.wire") - self.assertEqual(wiredata, renderer.get_data()) - - renderer.clear() - renderer.set_length_limit(10) - self.edns_base.set_dnssec_awareness(True) - self.assertEqual(0, self.edns_base.to_wire(renderer, extrcode_noerror)) - self.assertEqual(0, renderer.get_length()) - - def test_towire_buffer(self): - extrcode_noerror = Rcode.NOERROR.get_extended_code() - - obuffer = bytes() - obuffer = self.edns_base.to_wire(obuffer, extrcode_noerror) - wiredata = read_wire_data("edns_toWire1.wire") - self.assertEqual(wiredata, obuffer) - - def test_create_from_rr(self): - (edns, extrcode) = EDNS.create_from_rr(Name.ROOT_NAME, self.rrclass, - self.rrtype, self.rrttl_do_on, - self.opt_rdata) - self.assertEqual(EDNS.SUPPORTED_VERSION, edns.get_version()) - self.assertTrue(edns.get_dnssec_awareness()) - self.assertEqual(4096, edns.get_udp_size()) - self.assertEqual(0, extrcode) - - (edns, extrcode) = EDNS.create_from_rr(Name.ROOT_NAME, self.rrclass, - self.rrtype, RRTTL(0x01008000), - self.opt_rdata) - self.assertEqual(1, extrcode) - - self.assertRaises(DNSMessageBADVERS, EDNS.create_from_rr, - Name.ROOT_NAME, self.rrclass, self.rrtype, - self.rrttl_badver, self.opt_rdata) - -if __name__ == '__main__': - unittest.main() diff --git a/src/lib/dns/python/tests/message_python_test.py b/src/lib/dns/python/tests/message_python_test.py deleted file mode 100644 index 6f017dfec3..0000000000 --- a/src/lib/dns/python/tests/message_python_test.py +++ /dev/null @@ -1,669 +0,0 @@ -# Copyright (C) 2010 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. - -# -# Tests for the message part of the pydnspp module -# - -import sys -import unittest -import os -from pydnspp import * -from testutil import * -from pyunittests_util import fix_current_time - -# helper functions for tests taken from c++ unittests -if "TESTDATA_PATH" in os.environ: - testdata_path = os.environ["TESTDATA_PATH"] -else: - testdata_path = "../tests/testdata" - -def factoryFromFile(message, file, parse_options=Message.PARSE_DEFAULT): - data = read_wire_data(file) - message.from_wire(data, parse_options) - return data - -# we don't have direct comparison for rrsets right now (should we? -# should go in the cpp version first then), so also no direct list -# comparison. Created a helper function -def compare_rrset_list(list1, list2): - if len(list1) != len(list2): - return False - for i in range(0, len(list1)): - if str(list1[i]) != str(list2[i]): - return False - return True - -# These are used for TSIG + TC tests -LONG_TXT1 = "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcde"; - -LONG_TXT2 = "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456"; - -LONG_TXT3 = "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef01"; - -LONG_TXT4 = "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0"; - -# a complete message taken from cpp tests, for testing towire and totext -def create_message(): - message_render = Message(Message.RENDER) - message_render.set_qid(0x1035) - message_render.set_opcode(Opcode.QUERY) - message_render.set_rcode(Rcode.NOERROR) - message_render.set_header_flag(Message.HEADERFLAG_QR) - message_render.set_header_flag(Message.HEADERFLAG_RD) - message_render.set_header_flag(Message.HEADERFLAG_AA) - message_render.add_question(Question(Name("test.example.com"), - RRClass("IN"), RRType("A"))) - rrset = RRset(Name("test.example.com"), RRClass("IN"), - RRType("A"), RRTTL(3600)) - rrset.add_rdata(Rdata(RRType("A"), RRClass("IN"), "192.0.2.1")) - rrset.add_rdata(Rdata(RRType("A"), RRClass("IN"), "192.0.2.2")) - message_render.add_rrset(Message.SECTION_ANSWER, rrset) - return message_render - -class MessageTest(unittest.TestCase): - - def setUp(self): - # make sure we don't use faked time unless explicitly do so in tests - fix_current_time(None) - - self.p = Message(Message.PARSE) - self.r = Message(Message.RENDER) - - self.rrset_a = RRset(Name("example.com"), RRClass("IN"), RRType("A"), - RRTTL(3600)) - self.rrset_a.add_rdata(Rdata(RRType("A"), RRClass("IN"), "192.0.2.1")) - self.rrset_a.add_rdata(Rdata(RRType("A"), RRClass("IN"), "192.0.2.2")) - - self.rrset_aaaa = RRset(Name("example.com"), RRClass("IN"), - RRType("AAAA"), RRTTL(3600)) - self.rrset_aaaa.add_rdata(Rdata(RRType("AAAA"), RRClass("IN"), - "2001:db8::134")) - - self.bogus_section = Message.SECTION_ADDITIONAL + 1 - self.bogus_below_section = Message.SECTION_QUESTION - 1 - self.tsig_key = TSIGKey("www.example.com:SFuWd/q99SzF8Yzd1QbB9g==") - self.tsig_ctx = TSIGContext(self.tsig_key) - - def tearDown(self): - # reset any faked current time setting (it would affect other tests) - fix_current_time(None) - - def test_init(self): - self.assertRaises(TypeError, Message, -1) - self.assertRaises(TypeError, Message, 3) - self.assertRaises(TypeError, Message, "wrong") - - def test_header_flag(self): # set and get methods - self.assertRaises(TypeError, self.p.get_header_flag, "wrong") - self.assertRaises(TypeError, self.r.set_header_flag, "wrong") - - self.assertFalse(self.r.get_header_flag(Message.HEADERFLAG_QR)) - self.assertFalse(self.r.get_header_flag(Message.HEADERFLAG_AA)) - self.assertFalse(self.r.get_header_flag(Message.HEADERFLAG_TC)) - self.assertFalse(self.r.get_header_flag(Message.HEADERFLAG_RD)) - self.assertFalse(self.r.get_header_flag(Message.HEADERFLAG_RA)) - self.assertFalse(self.r.get_header_flag(Message.HEADERFLAG_AD)) - self.assertFalse(self.r.get_header_flag(Message.HEADERFLAG_CD)) - - # 0 passed as flag should raise - self.assertRaises(InvalidParameter, self.r.get_header_flag, 0) - # unused bit - self.assertRaises(InvalidParameter, self.r.get_header_flag, 0x80000000) - - self.r.set_header_flag(Message.HEADERFLAG_QR) - self.assertTrue(self.r.get_header_flag(Message.HEADERFLAG_QR)) - - self.r.set_header_flag(Message.HEADERFLAG_AA, True) - self.assertTrue(self.r.get_header_flag(Message.HEADERFLAG_AA)) - - self.r.set_header_flag(Message.HEADERFLAG_AA, False) - self.assertFalse(self.r.get_header_flag(Message.HEADERFLAG_AA)) - - self.assertRaises(InvalidParameter, self.r.set_header_flag, 0) - self.assertRaises(InvalidParameter, self.r.set_header_flag, 0x7000) - self.assertRaises(InvalidParameter, self.r.set_header_flag, 0x0800) - self.assertRaises(InvalidMessageOperation, - self.p.set_header_flag, Message.HEADERFLAG_AA) - - # Range check. We need to do this at the binding level, so we need - # explicit tests for it. - self.assertRaises(ValueError, self.r.set_header_flag, 0x10000) - self.assertRaises(ValueError, self.r.set_header_flag, -1) - - def test_set_qid(self): - self.assertRaises(TypeError, self.r.set_qid, "wrong") - self.assertRaises(InvalidMessageOperation, - self.p.set_qid, 123) - self.r.set_qid(1234) - self.assertEqual(1234, self.r.get_qid()) - # Range check. We need to do this at the binding level, so we need - # explicit tests for it. - self.r.set_qid(0) - self.assertEqual(0, self.r.get_qid()) - self.r.set_qid(0xffff) - self.assertEqual(0xffff, self.r.get_qid()) - self.assertRaises(ValueError, self.r.set_qid, -1) - self.assertRaises(ValueError, self.r.set_qid, 0x10000) - - def test_set_rcode(self): - self.assertRaises(TypeError, self.r.set_rcode, "wrong") - - rcode = Rcode.BADVERS - self.r.set_rcode(rcode) - self.assertEqual(rcode, self.r.get_rcode()) - - self.assertRaises(InvalidMessageOperation, - self.p.set_rcode, rcode) - - self.assertRaises(InvalidMessageOperation, self.p.get_rcode) - - def test_set_opcode(self): - self.assertRaises(TypeError, self.r.set_opcode, "wrong") - - opcode = Opcode.IQUERY - self.r.set_opcode(opcode) - self.assertEqual(opcode, self.r.get_opcode()) - - self.assertRaises(InvalidMessageOperation, - self.p.set_opcode, opcode) - - self.assertRaises(InvalidMessageOperation, self.p.get_opcode) - - def test_get_edns(self): - self.assertEqual(None, self.p.get_edns()) - - message_parse = Message(Message.PARSE) - factoryFromFile(message_parse, "message_fromWire10.wire") - edns = message_parse.get_edns() - self.assertEqual(0, edns.get_version()) - self.assertEqual(4096, edns.get_udp_size()) - self.assertTrue(edns.get_dnssec_awareness()) - - def test_set_edns(self): - self.assertRaises(InvalidMessageOperation, self.p.set_edns, EDNS()) - - edns = EDNS() - edns.set_udp_size(1024) - self.r.set_edns(edns) - self.assertEqual(1024, self.r.get_edns().get_udp_size()) - - def test_get_rr_count(self): - # counts also tested in add_section - self.assertEqual(0, self.r.get_rr_count(Message.SECTION_QUESTION)) - self.assertEqual(0, self.r.get_rr_count(Message.SECTION_ANSWER)) - self.assertEqual(0, self.r.get_rr_count(Message.SECTION_AUTHORITY)) - self.assertEqual(0, self.r.get_rr_count(Message.SECTION_ADDITIONAL)) - - self.r.add_question(Question(Name("example.com"), RRClass("IN"), - RRType("A"))) - self.assertEqual(1, self.r.get_rr_count(Message.SECTION_QUESTION)) - - self.r.add_rrset(Message.SECTION_ANSWER, self.rrset_a) - self.assertEqual(2, self.r.get_rr_count(Message.SECTION_ANSWER)) - - factoryFromFile(self.p, "message_fromWire11.wire") - self.assertEqual(1, self.r.get_rr_count(Message.SECTION_QUESTION)) - self.assertEqual(0, self.r.get_rr_count(Message.SECTION_ADDITIONAL)) - - self.assertRaises(OverflowError, self.r.get_rr_count, - self.bogus_section) - self.assertRaises(TypeError, self.r.get_rr_count, "wrong") - - def test_get_section(self): - self.assertRaises(TypeError, self.r.get_section, "wrong") - - section_rrset = [self.rrset_a] - - self.assertRaises(InvalidMessageOperation, self.p.add_rrset, - Message.SECTION_ANSWER, self.rrset_a) - - self.assertFalse(compare_rrset_list(section_rrset, self.r.get_section(Message.SECTION_ANSWER))) - self.assertEqual(0, self.r.get_rr_count(Message.SECTION_ANSWER)) - self.r.add_rrset(Message.SECTION_ANSWER, self.rrset_a) - self.assertTrue(compare_rrset_list(section_rrset, self.r.get_section(Message.SECTION_ANSWER))) - self.assertEqual(2, self.r.get_rr_count(Message.SECTION_ANSWER)) - - # We always make a new deep copy in get_section(), so the reference - # count of the returned list and its each item should be 1; otherwise - # they would leak. - self.assertEqual(1, sys.getrefcount(self.r.get_section( - Message.SECTION_ANSWER))) - self.assertEqual(1, sys.getrefcount(self.r.get_section( - Message.SECTION_ANSWER)[0])) - - self.assertFalse(compare_rrset_list(section_rrset, self.r.get_section(Message.SECTION_AUTHORITY))) - self.assertEqual(0, self.r.get_rr_count(Message.SECTION_AUTHORITY)) - self.r.add_rrset(Message.SECTION_AUTHORITY, self.rrset_a) - self.assertTrue(compare_rrset_list(section_rrset, self.r.get_section(Message.SECTION_AUTHORITY))) - self.assertEqual(2, self.r.get_rr_count(Message.SECTION_AUTHORITY)) - - self.assertFalse(compare_rrset_list(section_rrset, self.r.get_section(Message.SECTION_ADDITIONAL))) - self.assertEqual(0, self.r.get_rr_count(Message.SECTION_ADDITIONAL)) - self.r.add_rrset(Message.SECTION_ADDITIONAL, self.rrset_a) - self.assertTrue(compare_rrset_list(section_rrset, self.r.get_section(Message.SECTION_ADDITIONAL))) - self.assertEqual(2, self.r.get_rr_count(Message.SECTION_ADDITIONAL)) - - def test_add_and_get_question(self): - self.assertRaises(TypeError, self.r.add_question, "wrong", "wrong") - q = Question(Name("example.com"), RRClass("IN"), RRType("A")) - qs = [q] - self.assertFalse(compare_rrset_list(qs, self.r.get_question())) - self.assertEqual(0, self.r.get_rr_count(Message.SECTION_QUESTION)) - self.r.add_question(q) - self.assertTrue(compare_rrset_list(qs, self.r.get_question())) - self.assertEqual(1, self.r.get_rr_count(Message.SECTION_QUESTION)) - - # We always make a new deep copy in get_section(), so the reference - # count of the returned list and its each item should be 1; otherwise - # they would leak. - self.assertEqual(1, sys.getrefcount(self.r.get_question())) - self.assertEqual(1, sys.getrefcount(self.r.get_question()[0])) - - # Message.add_question() called in non-RENDER mode should assert - self.r.clear(Message.PARSE) - self.assertRaises(InvalidMessageOperation, self.r.add_question, q) - - def test_make_response(self): - # Message.make_response() called in non-PARSE mode should assert - self.r.clear(Message.RENDER) - self.assertRaises(InvalidMessageOperation, self.r.make_response) - - def test_add_rrset(self): - self.assertRaises(TypeError, self.r.add_rrset, "wrong") - self.assertRaises(TypeError, self.r.add_rrset) - - # we can currently only test the no-sign case. - self.r.add_rrset(Message.SECTION_ANSWER, self.rrset_a) - self.assertEqual(2, self.r.get_rr_count(Message.SECTION_ANSWER)) - - def test_bad_add_rrset(self): - self.assertRaises(InvalidMessageOperation, self.p.add_rrset, - Message.SECTION_ANSWER, self.rrset_a) - self.assertRaises(OverflowError, self.r.add_rrset, - self.bogus_section, self.rrset_a) - self.assertRaises(OverflowError, self.r.add_rrset, - self.bogus_below_section, self.rrset_a) - - def test_clear(self): - self.assertEqual(None, self.r.clear(Message.PARSE)) - self.assertEqual(None, self.r.clear(Message.RENDER)) - self.assertRaises(TypeError, self.r.clear, "wrong") - self.assertRaises(TypeError, self.r.clear, 3) - - def test_clear_question_section(self): - self.r.add_question(Question(Name("www.example.com"), RRClass.IN, - RRType.A)) - self.assertEqual(1, self.r.get_rr_count(Message.SECTION_QUESTION)) - self.r.clear_section(Message.SECTION_QUESTION) - self.assertEqual(0, self.r.get_rr_count(Message.SECTION_QUESTION)) - self.assertEqual(0, len(self.r.get_question())) - - def test_clear_section(self): - for section in [Message.SECTION_ANSWER, Message.SECTION_AUTHORITY, - Message.SECTION_ADDITIONAL]: - self.r.add_rrset(section, self.rrset_a) - self.assertEqual(2, self.r.get_rr_count(section)) - self.r.clear_section(section) - self.assertEqual(0, self.r.get_rr_count(section)) - - self.assertRaises(InvalidMessageOperation, self.p.clear_section, - Message.SECTION_ANSWER) - self.assertRaises(OverflowError, self.r.clear_section, - self.bogus_section) - - def test_to_wire(self): - self.assertRaises(TypeError, self.r.to_wire, 1) - self.assertRaises(InvalidMessageOperation, - self.p.to_wire, MessageRenderer()) - - message_render = create_message() - renderer = MessageRenderer() - message_render.to_wire(renderer) - self.assertEqual(b'\x105\x85\x00\x00\x01\x00\x02\x00\x00\x00\x00\x04test\x07example\x03com\x00\x00\x01\x00\x01\xc0\x0c\x00\x01\x00\x01\x00\x00\x0e\x10\x00\x04\xc0\x00\x02\x01\xc0\x0c\x00\x01\x00\x01\x00\x00\x0e\x10\x00\x04\xc0\x00\x02\x02', - renderer.get_data()) - - def test_to_wire_without_opcode(self): - self.r.set_rcode(Rcode.NOERROR) - self.assertRaises(InvalidMessageOperation, self.r.to_wire, - MessageRenderer()) - - def test_to_wire_without_rcode(self): - self.r.set_opcode(Opcode.QUERY) - self.assertRaises(InvalidMessageOperation, self.r.to_wire, - MessageRenderer()) - - def __common_tsigmessage_setup(self, flags=[Message.HEADERFLAG_RD], - rrtype=RRType("A"), answer_data=None): - self.r.set_opcode(Opcode.QUERY) - self.r.set_rcode(Rcode.NOERROR) - for flag in flags: - self.r.set_header_flag(flag) - if answer_data is not None: - rrset = RRset(Name("www.example.com"), RRClass("IN"), - rrtype, RRTTL(86400)) - for rdata in answer_data: - rrset.add_rdata(Rdata(rrtype, RRClass("IN"), rdata)) - self.r.add_rrset(Message.SECTION_ANSWER, rrset) - self.r.add_question(Question(Name("www.example.com"), - RRClass("IN"), rrtype)) - - def __common_tsig_checks(self, expected_file): - renderer = MessageRenderer() - self.r.to_wire(renderer, self.tsig_ctx) - self.assertEqual(read_wire_data(expected_file), renderer.get_data()) - - def test_to_wire_with_tsig(self): - fix_current_time(0x4da8877a) - self.r.set_qid(0x2d65) - self.__common_tsigmessage_setup() - self.__common_tsig_checks("message_toWire2.wire") - - def test_to_wire_with_tsig_none(self): - message_render = create_message() - renderer = MessageRenderer() - message_render.to_wire(renderer, None) - self.assertEqual(b'\x105\x85\x00\x00\x01\x00\x02\x00\x00\x00\x00\x04test\x07example\x03com\x00\x00\x01\x00\x01\xc0\x0c\x00\x01\x00\x01\x00\x00\x0e\x10\x00\x04\xc0\x00\x02\x01\xc0\x0c\x00\x01\x00\x01\x00\x00\x0e\x10\x00\x04\xc0\x00\x02\x02', - renderer.get_data()) - - def test_to_wire_with_edns_tsig(self): - fix_current_time(0x4db60d1f) - self.r.set_qid(0x6cd) - self.__common_tsigmessage_setup() - edns = EDNS() - edns.set_udp_size(4096) - self.r.set_edns(edns) - self.__common_tsig_checks("message_toWire3.wire") - - def test_to_wire_tsig_truncation(self): - fix_current_time(0x4e179212) - data = factoryFromFile(self.p, "message_fromWire17.wire") - self.assertEqual(TSIGError.NOERROR, - self.tsig_ctx.verify(self.p.get_tsig_record(), data)) - self.r.set_qid(0x22c2) - self.__common_tsigmessage_setup([Message.HEADERFLAG_QR, - Message.HEADERFLAG_AA, - Message.HEADERFLAG_RD], - RRType("TXT"), - [LONG_TXT1, LONG_TXT2]) - self.__common_tsig_checks("message_toWire4.wire") - - def test_to_wire_tsig_truncation2(self): - fix_current_time(0x4e179212) - data = factoryFromFile(self.p, "message_fromWire17.wire") - self.assertEqual(TSIGError.NOERROR, - self.tsig_ctx.verify(self.p.get_tsig_record(), data)) - self.r.set_qid(0x22c2) - self.__common_tsigmessage_setup([Message.HEADERFLAG_QR, - Message.HEADERFLAG_AA, - Message.HEADERFLAG_RD], - RRType("TXT"), - [LONG_TXT1, LONG_TXT3]) - self.__common_tsig_checks("message_toWire4.wire") - - def test_to_wire_tsig_truncation3(self): - self.r.set_opcode(Opcode.QUERY) - self.r.set_rcode(Rcode.NOERROR) - for i in range(1, 68): - self.r.add_question(Question(Name("www.example.com"), - RRClass("IN"), RRType(i))) - renderer = MessageRenderer() - self.r.to_wire(renderer, self.tsig_ctx) - - self.p.from_wire(renderer.get_data()) - self.assertTrue(self.p.get_header_flag(Message.HEADERFLAG_TC)) - self.assertEqual(66, self.p.get_rr_count(Message.SECTION_QUESTION)) - self.assertNotEqual(None, self.p.get_tsig_record()) - - def test_to_wire_tsig_no_truncation(self): - fix_current_time(0x4e17b38d) - data = factoryFromFile(self.p, "message_fromWire18.wire") - self.assertEqual(TSIGError.NOERROR, - self.tsig_ctx.verify(self.p.get_tsig_record(), data)) - self.r.set_qid(0xd6e2) - self.__common_tsigmessage_setup([Message.HEADERFLAG_QR, - Message.HEADERFLAG_AA, - Message.HEADERFLAG_RD], - RRType("TXT"), - [LONG_TXT1, LONG_TXT4]) - self.__common_tsig_checks("message_toWire5.wire") - - def test_to_wire_tsig_length_errors(self): - renderer = MessageRenderer() - renderer.set_length_limit(84) # 84 = expected TSIG length - 1 - self.__common_tsigmessage_setup() - self.assertRaises(TSIGContextError, - self.r.to_wire, renderer, self.tsig_ctx) - - renderer.clear() - self.r.clear(Message.RENDER) - renderer.set_length_limit(86) # 86 = expected TSIG length + 1 - self.__common_tsigmessage_setup() - self.assertRaises(TSIGContextError, - self.r.to_wire, renderer, self.tsig_ctx) - - # skip the last test of the corresponding C++ test: it requires - # subclassing MessageRenderer, which is (currently) not possible - # for python. In any case, it's very unlikely to happen in practice. - - def test_to_text(self): - message_render = create_message() - - msg_str =\ -""";; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 4149 -;; flags: qr aa rd; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 0 - -;; QUESTION SECTION: -;test.example.com. IN A - -;; ANSWER SECTION: -test.example.com. 3600 IN A 192.0.2.1 -test.example.com. 3600 IN A 192.0.2.2 -""" - self.assertEqual(msg_str, message_render.to_text()) - self.assertEqual(msg_str, str(message_render)) - - def test_to_text_without_opcode(self): - self.r.set_rcode(Rcode.NOERROR) - self.assertRaises(InvalidMessageOperation, self.r.to_text) - - def test_to_text_without_rcode(self): - self.r.set_opcode(Opcode.QUERY) - self.assertRaises(InvalidMessageOperation, self.r.to_text) - - def test_from_wire(self): - self.assertRaises(TypeError, self.r.from_wire, 1) - self.assertRaises(InvalidMessageOperation, - Message.from_wire, self.r, bytes()) - self.assertRaises(MessageTooShort, - Message.from_wire, self.p, bytes()) - - test_name = Name("test.example.com"); - - message_parse = Message(0) - factoryFromFile(message_parse, "message_fromWire1") - self.assertEqual(0x1035, message_parse.get_qid()) - self.assertEqual(Opcode.QUERY, message_parse.get_opcode()) - self.assertEqual(Rcode.NOERROR, message_parse.get_rcode()) - self.assertTrue(message_parse.get_header_flag(Message.HEADERFLAG_QR)) - self.assertTrue(message_parse.get_header_flag(Message.HEADERFLAG_RD)) - self.assertTrue(message_parse.get_header_flag(Message.HEADERFLAG_AA)) - - #QuestionPtr q = *message_parse.beginQuestion() - q = message_parse.get_question()[0] - self.assertEqual(test_name, q.get_name()) - self.assertEqual(RRType("A"), q.get_type()) - self.assertEqual(RRClass("IN"), q.get_class()) - self.assertEqual(1, message_parse.get_rr_count(Message.SECTION_QUESTION)) - self.assertEqual(2, message_parse.get_rr_count(Message.SECTION_ANSWER)) - self.assertEqual(0, message_parse.get_rr_count(Message.SECTION_AUTHORITY)) - self.assertEqual(0, message_parse.get_rr_count(Message.SECTION_ADDITIONAL)) - - #RRsetPtr rrset = *message_parse.beginSection(Message.SECTION_ANSWER) - rrset = message_parse.get_section(Message.SECTION_ANSWER)[0] - self.assertEqual(test_name, rrset.get_name()) - self.assertEqual(RRType("A"), rrset.get_type()) - self.assertEqual(RRClass("IN"), rrset.get_class()) - ## TTL should be 3600, even though that of the 2nd RR is 7200 - self.assertEqual(RRTTL(3600), rrset.get_ttl()) - rdata = rrset.get_rdata(); - self.assertEqual("192.0.2.1", rdata[0].to_text()) - self.assertEqual("192.0.2.2", rdata[1].to_text()) - self.assertEqual(2, len(rdata)) - - def test_from_wire_short_buffer(self): - data = read_wire_data("message_fromWire22.wire") - self.assertRaises(DNSMessageFORMERR, self.p.from_wire, data[:-1]) - - 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()) - self.assertEqual(2, len(rrset.get_rdata())) - - rrset = self.p.get_section(Message.SECTION_ANSWER)[1] - self.assertEqual(RRType("AAAA"), rrset.get_type()) - self.assertEqual(1, len(rrset.get_rdata())) - - def check_preserve_rrs(self, message, section): - rrset = message.get_section(section)[0] - self.assertEqual(RRType("A"), rrset.get_type()) - rdata = rrset.get_rdata() - self.assertEqual(1, len(rdata)) - self.assertEqual('192.0.2.1', rdata[0].to_text()) - - rrset = message.get_section(section)[1] - self.assertEqual(RRType("AAAA"), rrset.get_type()) - rdata = rrset.get_rdata() - self.assertEqual(1, len(rdata)) - self.assertEqual('2001:db8::1', rdata[0].to_text()) - - rrset = message.get_section(section)[2] - self.assertEqual(RRType("A"), rrset.get_type()) - rdata = rrset.get_rdata() - self.assertEqual(1, len(rdata)) - self.assertEqual('192.0.2.2', rdata[0].to_text()) - - def test_from_wire_preserve_answer(self): - factoryFromFile(self.p, "message_fromWire19.wire", - Message.PRESERVE_ORDER) - self.check_preserve_rrs(self.p, Message.SECTION_ANSWER) - - def test_from_wire_preserve_authority(self): - factoryFromFile(self.p, "message_fromWire20.wire", - Message.PRESERVE_ORDER) - self.check_preserve_rrs(self.p, Message.SECTION_AUTHORITY) - - def test_from_wire_preserve_additional(self): - factoryFromFile(self.p, "message_fromWire21.wire", - Message.PRESERVE_ORDER) - self.check_preserve_rrs(self.p, Message.SECTION_ADDITIONAL) - - def test_EDNS0ExtCode(self): - # Extended Rcode = BADVERS - message_parse = Message(Message.PARSE) - factoryFromFile(message_parse, "message_fromWire10.wire") - self.assertEqual(Rcode.BADVERS, message_parse.get_rcode()) - - # Maximum extended Rcode - message_parse.clear(Message.PARSE) - factoryFromFile(message_parse, "message_fromWire11.wire") - self.assertEqual(0xfff, message_parse.get_rcode().get_code()) - - def test_BadEDNS0(self): - message_parse = Message(Message.PARSE) - # OPT RR in the answer section - self.assertRaises(DNSMessageFORMERR, - factoryFromFile, - message_parse, - "message_fromWire4") - - # multiple OPT RRs (in the additional section) - message_parse.clear(Message.PARSE) - self.assertRaises(DNSMessageFORMERR, - factoryFromFile, - message_parse, - "message_fromWire5") - - ## OPT RR of a non root name - message_parse.clear(Message.PARSE) - self.assertRaises(DNSMessageFORMERR, - factoryFromFile, - message_parse, - "message_fromWire6") - - # Compressed owner name of OPT RR points to a root name. - # Not necessarily bogus, but very unusual and mostly pathological. - # We accept it, but is it okay? - message_parse.clear(Message.PARSE) - factoryFromFile(message_parse, "message_fromWire7") - - # Unsupported Version - message_parse.clear(Message.PARSE) - self.assertRaises(DNSMessageBADVERS, - factoryFromFile, - message_parse, - "message_fromWire9") - - def test_from_wire_with_tsig(self): - # Initially there should be no TSIG - self.assertEqual(None, self.p.get_tsig_record()) - - # getTSIGRecord() is only valid in the parse mode. - self.assertRaises(InvalidMessageOperation, self.r.get_tsig_record) - - factoryFromFile(self.p, "message_toWire2.wire") - tsig_rr = self.p.get_tsig_record() - self.assertEqual(Name("www.example.com"), tsig_rr.get_name()) - self.assertEqual(85, tsig_rr.get_length()) - self.assertEqual(TSIGKey.HMACMD5_NAME, - tsig_rr.get_rdata().get_algorithm()) - - # If we clear the message for reuse, the recorded TSIG will be cleared. - self.p.clear(Message.PARSE) - self.assertEqual(None, self.p.get_tsig_record()) - - def test_from_wire_with_tsigcompressed(self): - # Mostly same as fromWireWithTSIG, but the TSIG owner name is - # compressed. - factoryFromFile(self.p, "message_fromWire12.wire"); - tsig_rr = self.p.get_tsig_record() - self.assertEqual(Name("www.example.com"), tsig_rr.get_name()) - # len(www.example.com) = 17, but when fully compressed, the length is - # 2 bytes. So the length of the record should be 15 bytes shorter. - self.assertEqual(70, tsig_rr.get_length()) - - def test_from_wire_with_badtsig(self): - # Multiple TSIG RRs - self.assertRaises(DNSMessageFORMERR, factoryFromFile, - self.p, "message_fromWire13.wire") - self.p.clear(Message.PARSE) - - # TSIG in the answer section (must be in additional) - self.assertRaises(DNSMessageFORMERR, factoryFromFile, - self.p, "message_fromWire14.wire") - self.p.clear(Message.PARSE) - - # TSIG is not the last record. - self.assertRaises(DNSMessageFORMERR, factoryFromFile, - self.p, "message_fromWire15.wire") - self.p.clear(Message.PARSE) - - # Unexpected RR Class (this will fail in constructing TSIGRecord) - self.assertRaises(DNSMessageFORMERR, factoryFromFile, - self.p, "message_fromWire16.wire") - -if __name__ == '__main__': - unittest.main() diff --git a/src/lib/dns/python/tests/messagerenderer_python_test.py b/src/lib/dns/python/tests/messagerenderer_python_test.py deleted file mode 100644 index 8d5f26faa3..0000000000 --- a/src/lib/dns/python/tests/messagerenderer_python_test.py +++ /dev/null @@ -1,120 +0,0 @@ -# Copyright (C) 2010 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. - -# -# Tests for the messagerenderer part of the pydnspp module -# - -import unittest -import os -from pydnspp import * - -class MessageRendererTest(unittest.TestCase): - - def setUp(self): - name = Name("example.com") - c = RRClass("IN") - t = RRType("A") - ttl = RRTTL("3600") - - message = Message(Message.RENDER) - message.set_qid(123) - message.set_opcode(Opcode.QUERY) - message.set_rcode(Rcode.NOERROR) - message.add_question(Question(name, c, t)) - - self.message1 = message - message = Message(Message.RENDER) - message.set_qid(123) - message.set_header_flag(Message.HEADERFLAG_AA, True) - message.set_header_flag(Message.HEADERFLAG_QR, True) - message.set_opcode(Opcode.QUERY) - message.set_rcode(Rcode.NOERROR) - message.add_question(Question(name, c, t)) - rrset = RRset(name, c, t, ttl) - rrset.add_rdata(Rdata(t, c, "192.0.2.98")) - rrset.add_rdata(Rdata(t, c, "192.0.2.99")) - message.add_rrset(Message.SECTION_AUTHORITY, rrset) - self.message2 = message - - self.renderer1 = MessageRenderer() - self.renderer2 = MessageRenderer() - self.renderer3 = MessageRenderer() - self.renderer3.set_length_limit(50) - self.message1.to_wire(self.renderer1) - self.message2.to_wire(self.renderer2) - self.message2.to_wire(self.renderer3) - - - def test_messagerenderer_get_data(self): - data1 = b'\x00{\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x07example\x03com\x00\x00\x01\x00\x01' - self.assertEqual(data1, self.renderer1.get_data()) - data2 = b'\x00{\x84\x00\x00\x01\x00\x00\x00\x02\x00\x00\x07example\x03com\x00\x00\x01\x00\x01\xc0\x0c\x00\x01\x00\x01\x00\x00\x0e\x10\x00\x04\xc0\x00\x02b\xc0\x0c\x00\x01\x00\x01\x00\x00\x0e\x10\x00\x04\xc0\x00\x02c' - self.assertEqual(data2, self.renderer2.get_data()) - - def test_messagerenderer_get_length(self): - self.assertEqual(29, self.renderer1.get_length()) - self.assertEqual(61, self.renderer2.get_length()) - self.assertEqual(45, self.renderer3.get_length()) - - def test_messagerenderer_is_truncated(self): - self.assertFalse(self.renderer1.is_truncated()) - self.assertFalse(self.renderer2.is_truncated()) - self.assertTrue(self.renderer3.is_truncated()) - - def test_messagerenderer_get_length_limit(self): - self.assertEqual(512, self.renderer1.get_length_limit()) - self.assertEqual(512, self.renderer2.get_length_limit()) - self.assertEqual(50, self.renderer3.get_length_limit()) - - def test_messagerenderer_get_compress_mode(self): - self.assertEqual(MessageRenderer.CASE_INSENSITIVE, - self.renderer1.get_compress_mode()) - self.assertEqual(MessageRenderer.CASE_INSENSITIVE, - self.renderer2.get_compress_mode()) - self.assertEqual(MessageRenderer.CASE_INSENSITIVE, - self.renderer3.get_compress_mode()) - - def test_messagerenderer_set_truncated(self): - self.assertFalse(self.renderer1.is_truncated()) - self.renderer1.set_truncated() - self.assertTrue(self.renderer1.is_truncated()) - - def test_messagerenderer_set_length_limit(self): - renderer = MessageRenderer() - self.assertEqual(512, renderer.get_length_limit()) - renderer.set_length_limit(1024) - self.assertEqual(1024, renderer.get_length_limit()) - self.assertRaises(TypeError, renderer.set_length_limit, "wrong") - # Range check. We need to do this at the binding level, so we need - # explicit tests for it. - renderer.set_length_limit(0) - self.assertEqual(0, renderer.get_length_limit()) - self.assertRaises(ValueError, renderer.set_length_limit, -1) - - def test_messagerenderer_set_compress_mode(self): - renderer = MessageRenderer() - self.assertEqual(MessageRenderer.CASE_INSENSITIVE, - renderer.get_compress_mode()) - renderer.set_compress_mode(MessageRenderer.CASE_SENSITIVE) - self.assertEqual(MessageRenderer.CASE_SENSITIVE, - renderer.get_compress_mode()) - renderer.set_compress_mode(MessageRenderer.CASE_INSENSITIVE) - self.assertEqual(MessageRenderer.CASE_INSENSITIVE, - renderer.get_compress_mode()) - self.assertRaises(TypeError, renderer.set_compress_mode, "wrong") - -if __name__ == '__main__': - unittest.main() diff --git a/src/lib/dns/python/tests/name_python_test.py b/src/lib/dns/python/tests/name_python_test.py deleted file mode 100644 index 8160716896..0000000000 --- a/src/lib/dns/python/tests/name_python_test.py +++ /dev/null @@ -1,254 +0,0 @@ -# Copyright (C) 2010 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. - -# -# Tests for the name part of the pydnspp module -# - -import unittest -import os -from pydnspp import * - -class NameComparisonTest(unittest.TestCase): - def setUp(self): - self.name1 = Name("aaaa.example.com") - self.name2 = Name("bbbb.example.com") - self.name3 = Name("cccc.example.com") - self.name4 = Name("aaaa.example.com") - self.name5 = Name("something.completely.different") - - self.ncr12 = self.name1.compare(self.name2) - self.ncr13 = self.name1.compare(self.name3) - self.ncr23 = self.name2.compare(self.name3) - self.ncr21 = self.name2.compare(self.name1) - self.ncr32 = self.name3.compare(self.name2) - self.ncr31 = self.name3.compare(self.name1) - self.ncr14 = self.name1.compare(self.name4) - self.ncr15 = self.name1.compare(self.name5) - - def test_init(self): - self.assertRaises(NotImplementedError, NameComparisonResult) - - def test_get_order(self): - self.assertEqual(-1, self.ncr12.get_order()) - self.assertEqual(-2, self.ncr13.get_order()) - self.assertEqual(-1, self.ncr23.get_order()) - self.assertEqual(1, self.ncr21.get_order()) - self.assertEqual(1, self.ncr32.get_order()) - self.assertEqual(2, self.ncr31.get_order()) - self.assertEqual(0, self.ncr14.get_order()) - - def test_get_common_labels(self): - self.assertEqual(3, self.ncr12.get_common_labels()) - self.assertEqual(1, self.ncr15.get_common_labels()) - - def test_get_relation(self): - self.assertEqual("COMMONANCESTOR", NameComparisonResult.NameRelation[self.ncr12.get_relation()]) - self.assertEqual("COMMONANCESTOR", NameComparisonResult.NameRelation[self.ncr15.get_relation()]) - - superdomain = Name("com") - relation = superdomain.compare(self.name1) - self.assertEqual("SUPERDOMAIN", NameComparisonResult.NameRelation[relation.get_relation()]) - - subdomain = Name("sub.aaaa.example.com") - relation = subdomain.compare(self.name1) - self.assertEqual("SUBDOMAIN", NameComparisonResult.NameRelation[relation.get_relation()]) - - same = Name("aaaa.example.com") - relation = same.compare(self.name1) - self.assertEqual("EQUAL", NameComparisonResult.NameRelation[relation.get_relation()]) - -class NameTest(unittest.TestCase): - def setUp(self): - self.name1 = Name("example.com") - self.name2 = Name(".") - self.name3 = Name("something.completely.different") - self.name4 = Name("EXAMPLE.com") - self.name5 = Name("*.example.com") - - def test_init(self): - self.assertRaises(EmptyLabel, Name, "example..com") - self.assertRaises(TooLongLabel, Name, "a"*64 + ".example.com") - self.assertRaises(BadLabelType, Name, "\[asdf.example.com") - self.assertRaises(BadEscape, Name, "\\999") - self.assertRaises(TooLongName, Name, "example."*32 + "com") - self.assertRaises(IncompleteName, Name, "\\") - self.assertRaises(TypeError, Name, 1) - - b = bytearray() - self.name1.to_wire(b) - self.assertEqual(self.name1, Name(b)) - self.assertEqual(self.name1, Name(b, 0)) - self.assertRaises(InvalidBufferPosition, Name, b, 100) - b = bytearray() - b += b'\x07example'*32 + b'\x03com\x00' - self.assertRaises(DNSMessageFORMERR, Name, b, 0) - self.assertRaises(IndexError, Name, b, -1) - - def test_exception_hierarchy(self): - self.assertTrue(isinstance(EmptyLabel(), NameParserException)) - self.assertTrue(isinstance(TooLongLabel(), NameParserException)) - self.assertTrue(isinstance(BadLabelType(), NameParserException)) - self.assertTrue(isinstance(BadEscape(), NameParserException)) - self.assertTrue(isinstance(TooLongName(), NameParserException)) - self.assertTrue(isinstance(IncompleteName(), NameParserException)) - - self.assertTrue(isinstance(NameParserException(), DNSTextError)) - - def test_at(self): - self.assertEqual(7, self.name1.at(0)) - self.assertEqual(101, self.name1.at(1)) - self.assertRaises(IndexError, self.name1.at, 100) - self.assertRaises(IndexError, self.name1.at, 0x10000) - self.assertRaises(IndexError, self.name1.at, -1) - self.assertRaises(TypeError, self.name1.at, "wrong") - - def test_get_length(self): - self.assertEqual(13, self.name1.get_length()) - self.assertEqual(1, self.name2.get_length()) - self.assertEqual(32, self.name3.get_length()) - - def test_get_labelcount(self): - self.assertEqual(3, self.name1.get_labelcount()) - self.assertEqual(1, self.name2.get_labelcount()) - self.assertEqual(4, self.name3.get_labelcount()) - - def test_to_text(self): - self.assertEqual("example.com.", self.name1.to_text()) - self.assertEqual(".", self.name2.to_text()) - self.assertEqual(".", str(self.name2)) - self.assertEqual("something.completely.different.", self.name3.to_text()) - - self.assertEqual("example.com.", self.name1.to_text(False)) - self.assertEqual("example.com", self.name1.to_text(True)) - - # make sure it does not behave unexpectedly on wrong arguments - self.assertRaises(TypeError, self.name1.to_text, True, 1) - self.assertRaises(TypeError, self.name1.to_text, 1) - self.assertRaises(TypeError, self.name1.to_text, []) - self.assertRaises(TypeError, self.name1.to_text, "foo") - - def test_to_wire(self): - b1 = bytearray() - self.name1.to_wire(b1) - self.assertEqual(bytearray(b'\x07example\x03com\x00'), b1) - b2 = bytearray() - self.name2.to_wire(b2) - self.assertEqual(bytearray(b'\x00'), b2) - - mr = MessageRenderer() - self.name1.to_wire(mr) - self.assertEqual(b'\x07example\x03com\x00', mr.get_data()) - - self.assertRaises(TypeError, self.name1.to_wire, "wrong") - self.assertRaises(TypeError, self.name1.to_wire, 1) - - def test_compare(self): - # tested in comparison class above - pass - - def test_equals(self): - self.assertFalse(self.name1.equals(self.name2)) - self.assertFalse(self.name1.equals(self.name3)) - self.assertTrue(self.name1.equals(self.name4)) - - def test_split(self): - s = self.name1.split(1,1) - self.assertEqual("com.", s.to_text()) - s = self.name1.split(0,1) - self.assertEqual("example.", s.to_text()) - s = self.name3.split(1,2) - self.assertEqual("completely.different.", s.to_text()) - self.assertRaises(TypeError, self.name1.split, "wrong", 1) - self.assertRaises(TypeError, self.name1.split, 1, "wrong") - - s = self.name1.split(1) - self.assertEqual("com.", s.to_text()) - - # Range check. We need to do this at the binding level, so we need - # explicit tests for it. - self.assertRaises(IndexError, self.name1.split, 123, 1) - self.assertRaises(IndexError, self.name1.split, 1, 123) - self.assertRaises(IndexError, self.name1.split, 0x10000, 5) - self.assertRaises(IndexError, self.name1.split, -1, -1) - self.assertRaises(IndexError, self.name1.split, 0, -1) - self.assertRaises(IndexError, self.name1.split, -1, 0x10000) - - s = self.name1.split(0) - self.assertEqual("example.com.", s.to_text()) - self.assertRaises(IndexError, self.name1.split, 123) - self.assertRaises(IndexError, self.name1.split, 0x10000) - self.assertRaises(IndexError, self.name1.split, -123) - self.assertRaises(TypeError, self.name1.split, -1) - - def test_reverse(self): - self.assertEqual("com.example.", self.name1.reverse().to_text()) - self.assertEqual(".", self.name2.reverse().to_text()) - - def test_concatenate(self): - self.assertEqual("example.com.", self.name1.concatenate(self.name2).to_text()) - self.assertEqual("example.com.example.com.", self.name1.concatenate(self.name1).to_text()) - self.assertRaises(TypeError, self.name1.concatenate, "wrong") - self.assertRaises(TooLongName, self.name1.concatenate, Name("example."*31)) - - def test_downcase(self): - self.assertEqual("EXAMPLE.com.", self.name4.to_text()) - self.name4.downcase() - self.assertEqual("example.com.", self.name4.to_text()) - - def test_is_wildcard(self): - self.assertFalse(self.name1.is_wildcard()) - self.assertTrue(self.name5.is_wildcard()) - - def test_richcmp(self): - self.assertTrue(self.name1 > self.name2) - self.assertFalse(self.name1 < self.name2) - self.assertFalse(self.name2 > self.name1) - self.assertTrue(self.name2 < self.name1) - self.assertTrue(self.name1 == self.name4) - self.assertFalse(self.name1 != self.name4) - self.assertTrue(self.name1 != self.name2) - self.assertFalse(self.name1 == self.name2) - self.assertTrue(self.name1 <= self.name4) - self.assertTrue(self.name1 >= self.name4) - self.assertFalse(self.name1 <= self.name2) - self.assertTrue(self.name4 >= self.name1) - self.assertTrue(self.name4 <= self.name1) - self.assertFalse(self.name2 >= self.name1) - - def test_hash(self): - # The same name should have the same hash value. - self.assertEqual(hash(Name('example.com')), hash(Name('example.com'))) - # Hash is case insensitive. - self.assertEqual(hash(Name('example.com')), hash(Name('EXAMPLE.COM'))) - - # These pairs happen to be known to have different hashes. - # It may be naive to assume the hash value is always the same (we use - # an external library and it depends on its internal details). If - # it turns out that this assumption isn't always held, we should - # disable this test. - self.assertNotEqual(hash(Name('example.com')), - hash(Name('example.org'))) - - # Check insensitiveness for the case of inequality. - # Based on the assumption above, this 'if' should be true and - # we'll always test the case inside it. We'll still keep the if in - # case we end up disabling the above test. - if hash(Name('example.com')) != hash(Name('example.org')): - self.assertNotEqual(hash(Name('example.com')), - hash(Name('EXAMPLE.ORG'))) - -if __name__ == '__main__': - unittest.main() diff --git a/src/lib/dns/python/tests/nsec3hash_python_test.py b/src/lib/dns/python/tests/nsec3hash_python_test.py deleted file mode 100644 index f3d1cfbd79..0000000000 --- a/src/lib/dns/python/tests/nsec3hash_python_test.py +++ /dev/null @@ -1,128 +0,0 @@ -# Copyright (C) 2012 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 -from pydnspp import * - -class NSEC3HashTest(unittest.TestCase): - '''These tests are mostly straightforward conversion of C++ tests - except for python specific type checks. - - ''' - - def setUp(self): - self.nsec3_common = "2T7B4G4VSA5SMI47K61MV5BV1A22BOJR A RRSIG" - self.test_hash = NSEC3Hash(Rdata(RRType.NSEC3PARAM, RRClass.IN, - "1 0 12 aabbccdd")) - self.test_hash_nsec3 = NSEC3Hash(Rdata(RRType.NSEC3, RRClass.IN, - "1 0 12 aabbccdd " + - self.nsec3_common)) - def test_bad_construct(self): - # missing parameter - self.assertRaises(TypeError, NSEC3Hash) - - # invalid type of argument - self.assertRaises(TypeError, NSEC3Hash, "1 0 12 aabbccdd") - - # additional parameter - self.assertRaises(TypeError, NSEC3Hash, Rdata(RRType.NSEC3PARAM, - RRClass.IN, - "1 0 12 aabbccdd"), 1) - - # Invalid type of RDATA - self.assertRaises(TypeError, NSEC3Hash, Rdata(RRType.A, RRClass.IN, - "192.0.2.1")) - - def test_unknown_algorithm(self): - self.assertRaises(UnknownNSEC3HashAlgorithm, NSEC3Hash, - Rdata(RRType.NSEC3PARAM, RRClass.IN, - "2 0 12 aabbccdd")) - self.assertRaises(UnknownNSEC3HashAlgorithm, NSEC3Hash, - Rdata(RRType.NSEC3, RRClass.IN, - "2 0 12 aabbccdd " + self.nsec3_common)) - - def calculate_check(self, hash): - # A couple of normal cases from the RFC5155 example. - self.assertEqual("0P9MHAVEQVM6T7VBL5LOP2U3T2RP3TOM", - hash.calculate(Name("example"))) - self.assertEqual("35MTHGPGCU1QG68FAB165KLNSNK3DPVL", - hash.calculate(Name("a.example"))) - - # Check case-insensitiveness - self.assertEqual("0P9MHAVEQVM6T7VBL5LOP2U3T2RP3TOM", - hash.calculate(Name("EXAMPLE"))) - - - def test_calculate(self): - self.calculate_check(self.test_hash) - self.calculate_check(self.test_hash_nsec3) - - # Using unusually large iterations, something larger than the 8-bit - #range. (expected hash value generated by BIND 9's dnssec-signzone) - self.test_hash = NSEC3Hash(Rdata(RRType.NSEC3PARAM, - RRClass.IN, "1 0 256 AABBCCDD")) - self.assertEqual("COG6A52MJ96MNMV3QUCAGGCO0RHCC2Q3", - self.test_hash.calculate(Name("example.org"))) - - # Some boundary cases: 0-iteration and empty salt. Borrowed from the - # .com zone data. - self.test_hash = NSEC3Hash(Rdata(RRType.NSEC3PARAM, - RRClass.IN,"1 0 0 -")) - self.assertEqual("CK0POJMG874LJREF7EFN8430QVIT8BSM", - self.test_hash.calculate(Name("com"))) - - def test_calculate_badparam(self): - self.assertRaises(TypeError, self.test_hash.calculate, "example") - self.assertRaises(TypeError, self.test_hash.calculate) - self.assertRaises(TypeError, self.test_hash.calculate, Name("."), 1) - - def check_match(self, hash, rrtype, postfix): - # If all parameters match, it's considered to be matched. - self.assertTrue(hash.match(Rdata(rrtype, RRClass.IN, - "1 0 12 aabbccdd" + postfix))) - # Algorithm doesn't match - self.assertFalse(hash.match(Rdata(rrtype, RRClass.IN, - "2 0 12 aabbccdd" + postfix))) - # Iterations doesn't match - self.assertFalse(hash.match(Rdata(rrtype, RRClass.IN, - "1 0 1 aabbccdd" + postfix))) - # Salt doesn't match - self.assertFalse(hash.match(Rdata(rrtype, RRClass.IN, - "1 0 12 aabbccde" + postfix))) - # Salt doesn't match: the other has an empty salt - self.assertFalse(hash.match(Rdata(rrtype, RRClass.IN, - "1 0 12 -" + postfix))) - # Flag doesn't matter - self.assertTrue(hash.match(Rdata(rrtype, RRClass.IN, - "1 1 12 aabbccdd" + postfix))) - - def test_match(self): - self.check_match(self.test_hash, RRType.NSEC3, - " " + self.nsec3_common) - self.check_match(self.test_hash_nsec3, RRType.NSEC3, - " " + self.nsec3_common) - self.check_match(self.test_hash, RRType.NSEC3PARAM, "") - self.check_match(self.test_hash_nsec3, RRType.NSEC3PARAM, "") - - # bad parameter checks - self.assertRaises(TypeError, self.test_hash.match, 1) - self.assertRaises(TypeError, self.test_hash.match, - Rdata(RRType.NSEC3, RRClass.IN, - "1 0 12 aabbccdd " + self.nsec3_common), 1) - self.assertRaises(TypeError, self.test_hash.match, - Rdata(RRType.A, RRClass.IN, "192.0.2.1")) - -if __name__ == '__main__': - unittest.main() diff --git a/src/lib/dns/python/tests/opcode_python_test.py b/src/lib/dns/python/tests/opcode_python_test.py deleted file mode 100644 index d938aa6a77..0000000000 --- a/src/lib/dns/python/tests/opcode_python_test.py +++ /dev/null @@ -1,112 +0,0 @@ -# Copyright (C) 2010 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. - -# -# Tests for the opcode part of the pydnspp module -# - -import unittest -from pydnspp import * - -class OpcodeTest(unittest.TestCase): - def test_init(self): - self.assertRaises(TypeError, Opcode, "wrong") - self.assertEqual(Rcode(0).get_code(), 0) - self.assertEqual(Rcode(Opcode.RESERVED15_CODE).get_code(), 15) - self.assertRaises(OverflowError, Opcode, 16) - - def test_constants(self): - self.assertEqual(Opcode.QUERY_CODE, Opcode(0).get_code()) - self.assertEqual(Opcode.IQUERY_CODE, Opcode(1).get_code()) - self.assertEqual(Opcode.NOTIFY_CODE, Opcode(4).get_code()) - self.assertEqual(Opcode.UPDATE_CODE, Opcode(5).get_code()) - self.assertEqual(Opcode.RESERVED15_CODE, Opcode(15).get_code()) - - self.assertEqual(Opcode.QUERY_CODE, Opcode.QUERY.get_code()) - self.assertEqual(Opcode.IQUERY_CODE, Opcode.IQUERY.get_code()) - self.assertEqual(Opcode.NOTIFY_CODE, Opcode.NOTIFY.get_code()) - self.assertEqual(Opcode.UPDATE_CODE, Opcode.UPDATE.get_code()) - self.assertEqual(Opcode.RESERVED15_CODE, Opcode.RESERVED15.get_code()) - - def test_get_code(self): - self.assertEqual(0, Opcode.QUERY.get_code()) - self.assertEqual(1, Opcode.IQUERY.get_code()) - self.assertEqual(2, Opcode.STATUS.get_code()) - self.assertEqual(3, Opcode.RESERVED3.get_code()) - self.assertEqual(4, Opcode.NOTIFY.get_code()) - self.assertEqual(5, Opcode.UPDATE.get_code()) - self.assertEqual(6, Opcode.RESERVED6.get_code()) - self.assertEqual(7, Opcode.RESERVED7.get_code()) - self.assertEqual(8, Opcode.RESERVED8.get_code()) - self.assertEqual(9, Opcode.RESERVED9.get_code()) - self.assertEqual(10, Opcode.RESERVED10.get_code()) - self.assertEqual(11, Opcode.RESERVED11.get_code()) - self.assertEqual(12, Opcode.RESERVED12.get_code()) - self.assertEqual(13, Opcode.RESERVED13.get_code()) - self.assertEqual(14, Opcode.RESERVED14.get_code()) - self.assertEqual(15, Opcode.RESERVED15.get_code()) - - def test_to_text(self): - self.assertEqual("QUERY", Opcode.QUERY.to_text()) - self.assertEqual("QUERY", str(Opcode.QUERY)) - self.assertEqual("IQUERY", Opcode.IQUERY.to_text()) - self.assertEqual("STATUS", Opcode.STATUS.to_text()) - self.assertEqual("RESERVED3", Opcode.RESERVED3.to_text()) - self.assertEqual("NOTIFY", Opcode.NOTIFY.to_text()) - self.assertEqual("UPDATE", Opcode.UPDATE.to_text()) - self.assertEqual("RESERVED6", Opcode.RESERVED6.to_text()) - self.assertEqual("RESERVED7", Opcode.RESERVED7.to_text()) - self.assertEqual("RESERVED8", Opcode.RESERVED8.to_text()) - self.assertEqual("RESERVED9", Opcode.RESERVED9.to_text()) - self.assertEqual("RESERVED10", Opcode.RESERVED10.to_text()) - self.assertEqual("RESERVED11", Opcode.RESERVED11.to_text()) - self.assertEqual("RESERVED12", Opcode.RESERVED12.to_text()) - self.assertEqual("RESERVED13", Opcode.RESERVED13.to_text()) - self.assertEqual("RESERVED14", Opcode.RESERVED14.to_text()) - self.assertEqual("RESERVED15", Opcode.RESERVED15.to_text()) - - def test_richcmp(self): - o1 = Opcode.QUERY - o2 = Opcode.NOTIFY - o3 = Opcode.NOTIFY - self.assertTrue(o2 == o3) - self.assertFalse(o2 != o3) - self.assertTrue(o1 != o2) - self.assertFalse(o1 == 1) - self.assertFalse(o1 == o2) - # can't use assertRaises here... - try: - o1 < o2 - self.fail("operation that should have raised an error unexpectedly succeeded") - except Exception as err: - self.assertEqual(TypeError, type(err)) - try: - o1 <= o2 - self.fail("operation that should have raised an error unexpectedly succeeded") - except Exception as err: - self.assertEqual(TypeError, type(err)) - try: - o1 > o2 - self.fail("operation that should have raised an error unexpectedly succeeded") - except Exception as err: - self.assertEqual(TypeError, type(err)) - try: - o1 >= o2 - self.fail("operation that should have raised an error unexpectedly succeeded") - except Exception as err: - self.assertEqual(TypeError, type(err)) - -if __name__ == '__main__': - unittest.main() diff --git a/src/lib/dns/python/tests/pydnspp_python_test.py b/src/lib/dns/python/tests/pydnspp_python_test.py deleted file mode 100644 index 574fc00e00..0000000000 --- a/src/lib/dns/python/tests/pydnspp_python_test.py +++ /dev/null @@ -1,34 +0,0 @@ -# Copyright (C) 2014 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. - -# -# Tests for the common part of the pydnspp module -# - -import unittest -import os -from pydnspp import * - -class CommonTest(unittest.TestCase): - def test_exception_hierarchy(self): - self.assertTrue(isinstance(InvalidOperation(), IscException)) - self.assertTrue(isinstance(InvalidParameter(), IscException)) - - self.assertTrue(isinstance(DNSException(), IscException)) - self.assertTrue(isinstance(DNSTextError(), DNSException)) - self.assertTrue(isinstance(DNSProtocolError(), DNSException)) - -if __name__ == '__main__': - unittest.main() diff --git a/src/lib/dns/python/tests/question_python_test.py b/src/lib/dns/python/tests/question_python_test.py deleted file mode 100644 index 43b80d3604..0000000000 --- a/src/lib/dns/python/tests/question_python_test.py +++ /dev/null @@ -1,101 +0,0 @@ -# Copyright (C) 2010 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. - -# -# Tests for the rrtype part of the pydnspp module -# - -import unittest -import os -from pydnspp import * -from testutil import * - -if "TESTDATA_PATH" in os.environ: - testdata_path = os.environ["TESTDATA_PATH"] -else: - testdata_path = "../tests/testdata" - -def question_from_wire(file, position = 0): - data = read_wire_data(file) - return Question(data, position) - - -class QuestionTest(unittest.TestCase): - def setUp(self): - self.example_name1 = Name("foo.example.com") - self.example_name2 = Name("bar.example.com") - self.test_question1 = Question(self.example_name1, RRClass("IN"), RRType("NS")) - self.test_question2 = Question(self.example_name2, RRClass("CH"), RRType("A")) - - def test_init(self): - self.assertRaises(TypeError, Question, "wrong") - - # tests below based on cpp unit tests - # also tests get_name, get_class and get_type - def test_from_wire(self): - - q = question_from_wire("question_fromWire") - - self.assertEqual(self.example_name1, q.get_name()) - self.assertEqual(RRClass("IN"), q.get_class()) - self.assertEqual(RRType("NS"), q.get_type()) - - # owner name of the second Question is compressed. It's uncommon - # (to have multiple questions), but isn't prohibited by the protocol. - q = question_from_wire("question_fromWire", 21) - self.assertEqual(self.example_name2, q.get_name()) - self.assertEqual(RRClass("CH"), q.get_class()) - self.assertEqual(RRType("A"), q.get_type()) - - # Pathological cases: Corresponding exceptions will be thrown from - # the underlying parser. - self.assertRaises(DNSMessageFORMERR, - question_from_wire, - "question_fromWire", 31) - self.assertRaises(IncompleteRRClass, - question_from_wire, - "question_fromWire", 36) - - def test_to_text(self): - - self.assertEqual("foo.example.com. IN NS", self.test_question1.to_text()) - self.assertEqual("foo.example.com. IN NS", str(self.test_question1)) - self.assertEqual("bar.example.com. CH A", self.test_question2.to_text()) - - def test_to_wire_buffer(self): - obuffer = bytes() - obuffer = self.test_question1.to_wire(obuffer) - obuffer = self.test_question2.to_wire(obuffer) - wiredata = read_wire_data("question_toWire1") - self.assertEqual(obuffer, wiredata) - - def test_to_wire_renderer(self): - renderer = MessageRenderer() - self.test_question1.to_wire(renderer) - self.test_question2.to_wire(renderer) - wiredata = read_wire_data("question_toWire2") - self.assertEqual(renderer.get_data(), wiredata) - self.assertRaises(TypeError, self.test_question1.to_wire, 1) - - def test_to_wire_truncated(self): - renderer = MessageRenderer() - renderer.set_length_limit(self.example_name1.get_length()) - self.assertFalse(renderer.is_truncated()) - self.test_question1.to_wire(renderer) - self.assertTrue(renderer.is_truncated()) - self.assertEqual(0, renderer.get_length()) - -if __name__ == '__main__': - unittest.main() diff --git a/src/lib/dns/python/tests/rcode_python_test.py b/src/lib/dns/python/tests/rcode_python_test.py deleted file mode 100644 index c4a8067df6..0000000000 --- a/src/lib/dns/python/tests/rcode_python_test.py +++ /dev/null @@ -1,144 +0,0 @@ -# Copyright (C) 2010 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. - -# -# Tests for the rcode part of the pydnspp module -# - -import unittest -from pydnspp import * - -class RcodeTest(unittest.TestCase): - def test_init(self): - self.assertRaises(TypeError, Rcode, "wrong") - self.assertEqual(0xfff, Rcode(0xfff).get_code()) # possible max code - - # should fail on attempt of construction with an out of range code - self.assertRaises(OverflowError, Rcode, 0x1000) - self.assertRaises(OverflowError, Rcode, 0xffff) - - # constructor with a pair of code portions - self.assertEqual(3, Rcode(Rcode.NXDOMAIN_CODE, 0).get_code()) - self.assertEqual(Rcode.BADVERS_CODE, Rcode(0, 1).get_code()) - self.assertEqual(0xfff, Rcode(0xf, 0xff).get_code()) - self.assertRaises(OverflowError, Rcode, 0x10, 0xff) - - # Range check. We need to do this at the binding level, so we need - # explicit tests for it. - self.assertEqual(Rcode(0).get_code(), 0) - self.assertEqual(Rcode(4095).get_code(), 4095) - self.assertEqual(Rcode(0, 0).get_code(), 0) - self.assertEqual(Rcode(0, 0).get_extended_code(), 0) - self.assertEqual(Rcode(15, 255).get_code(), 4095) - self.assertRaises(ValueError, Rcode, 65536) - self.assertRaises(ValueError, Rcode, 0x10, 0x100) - self.assertRaises(ValueError, Rcode, 0x100, 0x10) - - def test_constants(self): - self.assertEqual(Rcode.NOERROR_CODE, Rcode(0).get_code()) - self.assertEqual(Rcode.FORMERR_CODE, Rcode(1).get_code()) - self.assertEqual(Rcode.NOTIMP_CODE, Rcode(4).get_code()) - self.assertEqual(Rcode.REFUSED_CODE, Rcode(5).get_code()) - self.assertEqual(Rcode.RESERVED15_CODE, Rcode(15).get_code()) - self.assertEqual(Rcode.BADVERS_CODE, Rcode(16).get_code()) - - self.assertEqual(Rcode.NOERROR_CODE, Rcode.NOERROR.get_code()) - self.assertEqual(Rcode.FORMERR_CODE, Rcode.FORMERR.get_code()) - self.assertEqual(Rcode.NOTIMP_CODE, Rcode.NOTIMP.get_code()) - self.assertEqual(Rcode.REFUSED_CODE, Rcode.REFUSED.get_code()) - self.assertEqual(Rcode.RESERVED15_CODE, Rcode.RESERVED15.get_code()) - self.assertEqual(Rcode.BADVERS_CODE, Rcode.BADVERS.get_code()) - - def test_get_code(self): - self.assertEqual(0, Rcode.NOERROR.get_code()) - self.assertEqual(1, Rcode.FORMERR.get_code()) - self.assertEqual(2, Rcode.SERVFAIL.get_code()) - self.assertEqual(3, Rcode.NXDOMAIN.get_code()) - self.assertEqual(4, Rcode.NOTIMP.get_code()) - self.assertEqual(5, Rcode.REFUSED.get_code()) - self.assertEqual(6, Rcode.YXDOMAIN.get_code()) - self.assertEqual(7, Rcode.YXRRSET.get_code()) - self.assertEqual(8, Rcode.NXRRSET.get_code()) - self.assertEqual(9, Rcode.NOTAUTH.get_code()) - self.assertEqual(10, Rcode.NOTZONE.get_code()) - self.assertEqual(11, Rcode.RESERVED11.get_code()) - self.assertEqual(12, Rcode.RESERVED12.get_code()) - self.assertEqual(13, Rcode.RESERVED13.get_code()) - self.assertEqual(14, Rcode.RESERVED14.get_code()) - self.assertEqual(15, Rcode.RESERVED15.get_code()) - self.assertEqual(16, Rcode.BADVERS.get_code()) - - def test_get_extended_code(self): - self.assertEqual(0, Rcode.NOERROR.get_extended_code()) - self.assertEqual(0, Rcode.YXRRSET.get_extended_code()) - self.assertEqual(1, Rcode.BADVERS.get_extended_code()) - self.assertEqual(0xab, Rcode(0xabf).get_extended_code()) - self.assertEqual(0xff, Rcode(0xfff).get_extended_code()) - - def test_to_text(self): - self.assertEqual("NOERROR", Rcode(0).to_text()) - self.assertEqual("NOERROR", str(Rcode(0))) - self.assertEqual("FORMERR", Rcode(1).to_text()) - self.assertEqual("SERVFAIL", Rcode(2).to_text()) - self.assertEqual("NXDOMAIN", Rcode(3).to_text()) - self.assertEqual("NOTIMP", Rcode(4).to_text()) - self.assertEqual("REFUSED", Rcode(5).to_text()) - self.assertEqual("YXDOMAIN", Rcode(6).to_text()) - self.assertEqual("YXRRSET", Rcode(7).to_text()) - self.assertEqual("NXRRSET", Rcode(8).to_text()) - self.assertEqual("NOTAUTH", Rcode(9).to_text()) - self.assertEqual("NOTZONE", Rcode(10).to_text()) - self.assertEqual("RESERVED11", Rcode(11).to_text()) - self.assertEqual("RESERVED12", Rcode(12).to_text()) - self.assertEqual("RESERVED13", Rcode(13).to_text()) - self.assertEqual("RESERVED14", Rcode(14).to_text()) - self.assertEqual("RESERVED15", Rcode(15).to_text()) - self.assertEqual("BADVERS", Rcode(16).to_text()) - - self.assertEqual("17", Rcode(Rcode.BADVERS.get_code() + 1).to_text()) - self.assertEqual("4095", Rcode(0xfff).to_text()) - - def test_richcmp(self): - r1 = Rcode.NOERROR - r2 = Rcode.FORMERR - r3 = Rcode.FORMERR - self.assertTrue(r2 == r3) - self.assertTrue(r1 != r2) - self.assertFalse(r1 == r2) - self.assertFalse(r1 != 1) - # can't use assertRaises here... - try: - r1 < r2 - self.fail("operation that should have raised an error unexpectedly succeeded") - except Exception as err: - self.assertEqual(TypeError, type(err)) - try: - r1 <= r2 - self.fail("operation that should have raised an error unexpectedly succeeded") - except Exception as err: - self.assertEqual(TypeError, type(err)) - try: - r1 > r2 - self.fail("operation that should have raised an error unexpectedly succeeded") - except Exception as err: - self.assertEqual(TypeError, type(err)) - try: - r1 >= r2 - self.fail("operation that should have raised an error unexpectedly succeeded") - except Exception as err: - self.assertEqual(TypeError, type(err)) - -if __name__ == '__main__': - unittest.main() diff --git a/src/lib/dns/python/tests/rdata_python_test.py b/src/lib/dns/python/tests/rdata_python_test.py deleted file mode 100644 index 3b8f9ad312..0000000000 --- a/src/lib/dns/python/tests/rdata_python_test.py +++ /dev/null @@ -1,95 +0,0 @@ -# Copyright (C) 2010 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. - -# -# Tests for the rdata part of the pydnspp module -# - -import unittest -import os -from pydnspp import * - -class RdataTest(unittest.TestCase): - def setUp(self): - c = RRClass("IN") - t = RRType("A") - self.rdata1 = Rdata(t, c, "192.0.2.98") - self.rdata2 = Rdata(t, c, "192.0.2.99") - t = RRType("TXT") - self.rdata3 = Rdata(t, c, "asdfasdfasdf") - self.rdata4 = Rdata(t, c, "foo") - - def test_init(self): - self.assertRaises(TypeError, Rdata, "wrong", RRClass("IN"), "192.0.2.99") - self.assertRaises(TypeError, Rdata, RRType("A"), "wrong", "192.0.2.99") - self.assertRaises(TypeError, Rdata, RRType("A"), RRClass("IN"), 1) - self.assertRaises(InvalidRdataText, Rdata, RRType("A"), RRClass("IN"), - "Invalid Rdata Text") - self.assertRaises(CharStringTooLong, Rdata, RRType("TXT"), - RRClass("IN"), 'x' * 256) - self.assertRaises(InvalidRdataLength, Rdata, RRType("TXT"), - RRClass("IN"), bytes(65536)) - self.assertRaises(DNSMessageFORMERR, Rdata, RRType("TXT"), - RRClass("IN"), b"\xff") - - def test_rdata_to_wire(self): - b = bytearray() - self.rdata1.to_wire(b) - self.assertEqual(b'\xc0\x00\x02b', b) - b = bytearray() - self.rdata2.to_wire(b) - self.assertEqual(b'\xc0\x00\x02c', b) - b = bytearray() - self.rdata3.to_wire(b) - self.assertEqual(b'\x0casdfasdfasdf', b) - b = bytearray() - self.rdata4.to_wire(b) - self.assertEqual(b'\x03foo', b) - self.assertRaises(TypeError, self.rdata1.to_wire, 1) - - renderer = MessageRenderer() - self.rdata1.to_wire(renderer) - self.assertEqual(b'\xc0\x00\x02b', renderer.get_data()) - - renderer = MessageRenderer() - self.rdata3.to_wire(renderer) - self.assertEqual(b'\x0casdfasdfasdf', renderer.get_data()) - - def test_rdata_to_text(self): - self.assertEqual("192.0.2.98", self.rdata1.to_text()) - self.assertEqual("192.0.2.99", self.rdata2.to_text()) - self.assertEqual("\"asdfasdfasdf\"", self.rdata3.to_text()) - self.assertEqual("\"foo\"", self.rdata4.to_text()) - self.assertEqual("\"foo\"", str(self.rdata4)) - - def test_richcmp(self): - self.assertTrue(self.rdata1 < self.rdata2); - self.assertTrue(self.rdata1 <= self.rdata2); - self.assertFalse(self.rdata1 > self.rdata2); - self.assertFalse(self.rdata1 >= self.rdata2); - self.assertTrue(self.rdata3 != self.rdata4) - other_rdata = Rdata(RRType("TXT"), RRClass("IN"), "foo") - self.assertTrue(self.rdata4 == other_rdata) - - self.assertFalse(self.rdata1 > self.rdata2); - self.assertFalse(self.rdata1 >= self.rdata2); - self.assertTrue(self.rdata1 < self.rdata2); - self.assertTrue(self.rdata1 <= self.rdata2); - self.assertFalse(self.rdata3 == self.rdata4) - self.assertFalse(self.rdata4 != other_rdata) - - -if __name__ == '__main__': - unittest.main() diff --git a/src/lib/dns/python/tests/rrclass_python_test.py b/src/lib/dns/python/tests/rrclass_python_test.py deleted file mode 100644 index 880e33115b..0000000000 --- a/src/lib/dns/python/tests/rrclass_python_test.py +++ /dev/null @@ -1,97 +0,0 @@ -# Copyright (C) 2010 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. - -# -# Tests for the rrclass part of the pydnspp module -# - -import unittest -import os -from pydnspp import * - -class RRClassTest(unittest.TestCase): - def setUp(self): - self.c1 = RRClass.IN - self.c2 = RRClass.CH - - def test_init(self): - self.assertRaises(InvalidRRClass, RRClass, "wrong") - self.assertRaises(TypeError, RRClass, Exception()) - b = bytearray(1) - b[0] = 123 - self.assertRaises(TypeError, RRClass, b) - self.assertEqual(self.c1, RRClass(1)) - b = bytearray() - self.c1.to_wire(b) - self.assertEqual(self.c1, RRClass(b)) - # Range check. We need to do this at the binding level, so we need - # explicit tests for it. - self.assertRaises(ValueError, RRClass, 65536) - self.assertRaises(TypeError, RRClass, -1) - self.assertEqual(RRClass(65535).get_code(), 65535) - self.assertEqual(RRClass(0).get_code(), 0) - - def test_rrclass_to_text(self): - self.assertEqual("IN", self.c1.to_text()) - self.assertEqual("IN", str(self.c1)) - self.assertEqual("CH", self.c2.to_text()) - - def test_rrclass_to_wire(self): - b = bytearray() - self.c1.to_wire(b) - self.assertEqual(b'\x00\x01', b) - b = bytearray() - self.c2.to_wire(b) - self.assertEqual(b'\x00\x03', b) - - mr = MessageRenderer() - self.c1.to_wire(mr) - self.assertEqual(b'\x00\x01', mr.get_data()) - - self.assertRaises(TypeError, self.c1.to_wire, "wrong") - - def test_richcmp(self): - self.assertTrue(self.c1 != self.c2) - self.assertTrue(self.c1 < self.c2) - self.assertTrue(self.c1 <= self.c2) - self.assertFalse(self.c1 > self.c2) - self.assertFalse(self.c1 >= self.c2) - other_rrclass = RRClass("IN") - self.assertTrue(self.c1 == other_rrclass) - - self.assertFalse(self.c1 == self.c2) - self.assertFalse(self.c1 > self.c2) - self.assertFalse(self.c1 >= self.c2) - self.assertTrue(self.c1 < self.c2) - self.assertTrue(self.c1 <= self.c2) - self.assertFalse(self.c1 != other_rrclass) - - def test_hash(self): - # Exploiting the knowledge that the hash value is the numeric class - # value, we can predict the comparison result. - self.assertEqual(hash(RRClass.IN), hash(RRClass("IN"))) - self.assertEqual(hash(RRClass("in")), hash(RRClass("IN"))) - self.assertNotEqual(hash(RRClass.IN), hash(RRClass.CH)) - self.assertNotEqual(hash(RRClass.IN), hash(RRClass("CLASS65535"))) - - def test_statics(self): - self.assertEqual(RRClass.IN, RRClass("IN")) - self.assertEqual(RRClass.CH, RRClass("CH")) - self.assertEqual(RRClass.HS, RRClass("HS")) - self.assertEqual(254, RRClass.NONE.get_code()) - self.assertEqual(255, RRClass.ANY.get_code()) - -if __name__ == '__main__': - unittest.main() diff --git a/src/lib/dns/python/tests/rrset_collection_python_test.py b/src/lib/dns/python/tests/rrset_collection_python_test.py deleted file mode 100644 index 20d147f244..0000000000 --- a/src/lib/dns/python/tests/rrset_collection_python_test.py +++ /dev/null @@ -1,140 +0,0 @@ -# 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 os -import unittest -from pydnspp import * - -# This should refer to the testdata directory for the C++ tests. -TESTDATA_DIR = os.environ["TESTDATA_PATH"].split(':')[0] - -class RRsetCollectionBaseTest(unittest.TestCase): - def test_init(self): - # direct instantiation of the base class is prohibited. - self.assertRaises(TypeError, RRsetCollectionBase) - -class RRsetCollectionTest(unittest.TestCase): - def test_init_fail(self): - # check various failure cases on construction (other normal cases are - # covered as part of other tests) - - # bad args - self.assertRaises(TypeError, RRsetCollection, 1) - self.assertRaises(TypeError, RRsetCollection, # extra arg - b'example. 0 A 192.0.2.1', - Name('example'), RRClass.IN, 1) - self.assertRaises(TypeError, RRsetCollection, # incorrect order - b'example. 0 A 192.0.2.1', RRClass.IN, - Name('example')) - - # constructor will result in C++ exception. - self.assertRaises(IscException, RRsetCollection, - TESTDATA_DIR + '/no_such_file', Name('example.org'), - RRClass.IN) - - def check_find_result(self, rrsets): - # Commonly used check pattern - found = rrsets.find(Name('www.example.org'), RRClass.IN, RRType.A) - self.assertNotEqual(None, found) - self.assertEqual(Name('www.example.org'), found.get_name()) - self.assertEqual(RRClass.IN, found.get_class()) - self.assertEqual(RRType.A, found.get_type()) - self.assertEqual('192.0.2.1', found.get_rdata()[0].to_text()) - - def test_find(self): - # Checking the underlying find() is called as intended, both for - # success and failure cases, and with two different constructors. - rrsets = RRsetCollection(TESTDATA_DIR + '/example.org', - Name('example.org'), RRClass.IN) - self.check_find_result(rrsets) - self.assertEqual(None, rrsets.find(Name('example.org'), RRClass.IN, - RRType.A)) - - rrsets = RRsetCollection(b'www.example.org. 3600 IN A 192.0.2.1', - Name('example.org'), RRClass.IN) - self.check_find_result(rrsets) - self.assertEqual(None, rrsets.find(Name('example.org'), RRClass.IN, - RRType.A)) - - def test_find_badargs(self): - rrsets = RRsetCollection() - - # Check bad arguments: bad types - self.assertRaises(TypeError, rrsets.find, 1, RRClass.IN, RRType.A) - self.assertRaises(TypeError, rrsets.find, Name('example'), 1, - RRType.A) - self.assertRaises(TypeError, rrsets.find, Name('example'), 1, - RRType.A) - self.assertRaises(TypeError, rrsets.find, Name('example'), - RRClass.IN, 1) - self.assertRaises(TypeError, rrsets.find, Name('example'), RRType.A, - RRClass.IN) - - # Check bad arguments: too many/few arguments - self.assertRaises(TypeError, rrsets.find, Name('example'), - RRClass.IN, RRType.A, 0) - self.assertRaises(TypeError, rrsets.find, Name('example'), - RRClass.IN) - - def test_add_remove_rrset(self): - name = Name('www.example.org') - rrclass = RRClass.IN - rrtype = RRType.A - - # Create a collection with no RRsets - rrsets = RRsetCollection() - self.assertEqual(None, rrsets.find(name, rrclass, rrtype)) - - # add the record, then it should be found - rrset = RRset(name, rrclass, rrtype, RRTTL(60)) - rrset.add_rdata(Rdata(rrtype, rrclass, '192.0.2.1')) - self.assertEqual(None, rrsets.add_rrset(rrset)) - self.check_find_result(rrsets) - - # duplicate add is (at least currently) rejected - self.assertRaises(ValueError, rrsets.add_rrset, rrset) - - # remove it, then we cannot find it any more. - self.assertTrue(rrsets.remove_rrset(name, rrclass, rrtype)) - self.assertEqual(None, rrsets.find(name, rrclass, rrtype)) - - # duplicate remove (specified RRset doesn't exist) reulsts in False - self.assertFalse(rrsets.remove_rrset(name, rrclass, rrtype)) - - # Checking bad args - self.assertRaises(TypeError, rrsets.add_rrset, 1) - self.assertRaises(TypeError, rrsets.add_rrset, rrset, 1) - self.assertRaises(TypeError, rrsets.add_rrset) - - self.assertRaises(TypeError, rrsets.remove_rrset, 1, rrclass, rrtype) - self.assertRaises(TypeError, rrsets.remove_rrset, name, 1, rrtype) - self.assertRaises(TypeError, rrsets.remove_rrset, name, rrclass, 1) - self.assertRaises(TypeError, rrsets.remove_rrset, name, rrtype, - rrclass) - self.assertRaises(TypeError, rrsets.remove_rrset, name, rrclass) - self.assertRaises(TypeError, rrsets.remove_rrset, name, rrclass, - rrtype, 1) - - def test_empty_class(self): - # A user defined collection class shouldn't cause disruption. - class EmptyRRsetCollection(RRsetCollectionBase): - def __init__(self): - pass - rrsets = EmptyRRsetCollection() - self.assertRaises(TypeError, rrsets.find, Name('www.example.org'), - RRClass.IN, RRType.A) - -if __name__ == '__main__': - unittest.main() diff --git a/src/lib/dns/python/tests/rrset_python_test.py b/src/lib/dns/python/tests/rrset_python_test.py deleted file mode 100644 index d848d278b6..0000000000 --- a/src/lib/dns/python/tests/rrset_python_test.py +++ /dev/null @@ -1,149 +0,0 @@ -# Copyright (C) 2010 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. - -# -# Tests for the rrtype part of the pydnspp module -# - -import sys -import unittest -import os -from pydnspp import * - -class TestModuleSpec(unittest.TestCase): - - def setUp(self): - self.test_name = Name("test.example.com") - self.test_domain = Name("example.com") - self.test_nsname = Name("ns.example.com") - self.rrset_a = RRset(self.test_name, RRClass("IN"), RRType("A"), RRTTL(3600)) - self.rrset_a_empty = RRset(self.test_name, RRClass("IN"), RRType("A"), RRTTL(3600)) - self.rrset_any_a_empty = RRset(self.test_name, RRClass("ANY"), RRType("A"), RRTTL(3600)) - self.rrset_ns = RRset(self.test_domain, RRClass("IN"), RRType("NS"), RRTTL(86400)) - self.rrset_ch_txt = RRset(self.test_domain, RRClass("CH"), RRType("TXT"), RRTTL(0)) - self.MAX_RDATA_COUNT = 100 - self.rrset_a.add_rdata(Rdata(RRType("A"), RRClass("IN"), "192.0.2.1")); - self.rrset_a.add_rdata(Rdata(RRType("A"), RRClass("IN"), "192.0.2.2")); - - def test_init(self): - self.assertRaises(TypeError, RRset) - - def test_get_rdata_count(self): - for i in range(0, self.MAX_RDATA_COUNT): - self.assertEqual(i, self.rrset_a_empty.get_rdata_count()) - self.rrset_a_empty.add_rdata(Rdata(RRType("A"), RRClass("IN"), "192.0.2.1")) - - def test_get_length(self): - # Empty RRset should throw - self.assertRaises(EmptyRRset, self.rrset_a_empty.get_length); - - # Unless it is type ANY or NONE: - # test.example.com = 1 + 4 + 1 + 7 + 1 + 3 + 1 = 18 octets - # TYPE field = 2 octets - # CLASS field = 2 octets - # TTL field = 4 octets - # RDLENGTH field = 2 octets - # Total = 18 + 2 + 2 + 4 + 2 = 28 octets - self.assertEqual(28, self.rrset_any_a_empty.get_length()) - - # Single A RR: - # 28 octets (above) + 4 octets (A RDATA) = 32 octets - # With 2 A RRs: - self.assertEqual(32 + 32, self.rrset_a.get_length()) - - def test_get_name(self): - self.assertEqual(self.test_name, self.rrset_a.get_name()) - self.assertEqual(self.test_domain, self.rrset_ns.get_name()) - - def test_get_class(self): - self.assertEqual(RRClass("IN"), self.rrset_a.get_class()); - self.assertEqual(RRClass("CH"), self.rrset_ch_txt.get_class()); - - def test_get_type(self): - self.assertEqual(RRType("A"), self.rrset_a.get_type()); - self.assertEqual(RRType("NS"), self.rrset_ns.get_type()); - self.assertEqual(RRType("TXT"), self.rrset_ch_txt.get_type()); - - def test_get_ttl(self): - self.assertEqual(RRTTL(3600), self.rrset_a.get_ttl()); - self.assertEqual(RRTTL(86400), self.rrset_ns.get_ttl()); - self.assertEqual(RRTTL(0), self.rrset_ch_txt.get_ttl()); - - def test_set_ttl(self): - self.rrset_a.set_ttl(RRTTL(86400)); - self.assertEqual(RRTTL(86400), self.rrset_a.get_ttl()); - self.rrset_a.set_ttl(RRTTL(0)); - self.assertEqual(RRTTL(0), self.rrset_a.get_ttl()); - self.assertRaises(TypeError, self.rrset_a.set_ttl, 1) - - def test_add_rdata(self): - # no iterator to read out yet (TODO: add addition test once implemented) - - # This should result in TypeError, but FreeBSD 9.1 cannot correctly - # catch the expected internal C++ exception, resulting in SystemError. - # In general it's not a good practice to weaken the test condition for - # a limited set of buggy environment, but this seems to be the only - # case it could fail this way, so we'd live with it. See #2887. - self.assertRaises((TypeError, SystemError), self.rrset_a.add_rdata, - Rdata(RRType("NS"), RRClass("IN"), "test.name.")) - - def test_to_text(self): - self.assertEqual("test.example.com. 3600 IN A 192.0.2.1\n" - "test.example.com. 3600 IN A 192.0.2.2\n", - self.rrset_a.to_text()); - self.assertEqual("test.example.com. 3600 IN A 192.0.2.1\n" - "test.example.com. 3600 IN A 192.0.2.2\n", - str(self.rrset_a)); - - self.assertRaises(EmptyRRset, self.rrset_a_empty.to_text) - - self.assertEqual("test.example.com. 3600 ANY A\n", - self.rrset_any_a_empty.to_text()) - - def test_to_wire_buffer(self): - exp_buffer = bytearray(b'\x04test\x07example\x03com\x00\x00\x01\x00\x01\x00\x00\x0e\x10\x00\x04\xc0\x00\x02\x01\x04test\x07example\x03com\x00\x00\x01\x00\x01\x00\x00\x0e\x10\x00\x04\xc0\x00\x02\x02') - buffer = bytearray() - self.rrset_a.to_wire(buffer) - self.assertEqual(exp_buffer, buffer) - - self.assertRaises(EmptyRRset, self.rrset_a_empty.to_wire, buffer); - self.assertRaises(TypeError, self.rrset_a.to_wire, 1) - - exp_buffer = bytearray(b'\x04test\x07example\x03com\x00\x00\x01\x00\xff\x00\x00\x0e\x10\x00\x00') - buffer = bytearray() - self.rrset_any_a_empty.to_wire(buffer) - self.assertEqual(exp_buffer, buffer) - - def test_to_wire_renderer(self): - exp_buffer = bytearray(b'\x04test\x07example\x03com\x00\x00\x01\x00\x01\x00\x00\x0e\x10\x00\x04\xc0\x00\x02\x01\xc0\x00\x00\x01\x00\x01\x00\x00\x0e\x10\x00\x04\xc0\x00\x02\x02') - mr = MessageRenderer() - self.rrset_a.to_wire(mr) - self.assertEqual(exp_buffer, mr.get_data()) - - def test_get_rdata(self): - rdata = [ Rdata(RRType("A"), RRClass("IN"), "192.0.2.1"), - Rdata(RRType("A"), RRClass("IN"), "192.0.2.2") - ] - self.assertEqual(rdata, self.rrset_a.get_rdata()) - self.assertEqual([], self.rrset_a_empty.get_rdata()) - - # We always make a new deep copy in get_rdata(), so the reference - # count of the returned list and its each item should be 1; otherwise - # they would leak. - self.assertEqual(1, sys.getrefcount(self.rrset_a.get_rdata())) - self.assertEqual(1, sys.getrefcount(self.rrset_a.get_rdata()[0])) - -if __name__ == '__main__': - unittest.main() diff --git a/src/lib/dns/python/tests/rrttl_python_test.py b/src/lib/dns/python/tests/rrttl_python_test.py deleted file mode 100644 index aa4a34d5aa..0000000000 --- a/src/lib/dns/python/tests/rrttl_python_test.py +++ /dev/null @@ -1,83 +0,0 @@ -# Copyright (C) 2010 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. - -# -# Tests for the rrttl part of the pydnspp module -# - -import unittest -import os -from pydnspp import * - -class RRTTLTest(unittest.TestCase): - def setUp(self): - self.t1 = RRTTL(1) - self.t2 = RRTTL(3600) - - def test_init(self): - self.assertRaises(InvalidRRTTL, RRTTL, "wrong") - self.assertRaises(TypeError, RRTTL, Exception()) - b = bytearray(1) - b[0] = 123 - self.assertRaises(IncompleteRRTTL, RRTTL, b) - self.assertRaises(InvalidRRTTL, RRTTL, "4294967296") - b = bytearray(4) - b[0] = 0 - b[1] = 0 - b[2] = 0 - b[3] = 15 - self.assertEqual(15, RRTTL(b).get_value()) - # Range check. We need to do this at the binding level, so we need - # explicit tests for it. - self.assertRaises(TypeError, RRTTL, -1) - self.assertRaises(ValueError, RRTTL, 4294967296) - self.assertEqual(0, RRTTL(0).get_value()) - self.assertEqual(4294967295, RRTTL(4294967295).get_value()) - - def test_rrttl_to_text(self): - self.assertEqual("1", self.t1.to_text()) - self.assertEqual("1", str(self.t1)) - self.assertEqual("3600", self.t2.to_text()) - - def test_rrttl_to_wire(self): - b = bytearray() - self.t1.to_wire(b) - self.assertEqual(b'\x00\x00\x00\x01', b) - b = bytearray() - self.t2.to_wire(b) - self.assertEqual(b'\x00\x00\x0e\x10', b) - mr = MessageRenderer() - self.t2.to_wire(mr) - self.assertEqual(b'\x00\x00\x0e\x10', mr.get_data()) - self.assertRaises(TypeError, self.t1.to_wire, 1) - - def test_rrttl_richcmp(self): - self.assertTrue(self.t1 == RRTTL(1)) - self.assertFalse(self.t1 != RRTTL(1)) - self.assertFalse(self.t1 == 1) - self.assertTrue(self.t1 < self.t2) - self.assertTrue(self.t1 <= self.t2) - self.assertFalse(self.t1 > self.t2) - self.assertFalse(self.t1 >= self.t2) - - self.assertFalse(self.t1 != RRTTL(1)) - self.assertTrue(self.t1 == RRTTL(1)) - self.assertFalse(self.t1 > self.t2) - self.assertFalse(self.t1 >= self.t2) - self.assertTrue(self.t1 < self.t2) - self.assertTrue(self.t1 <= self.t2) - -if __name__ == '__main__': - unittest.main() diff --git a/src/lib/dns/python/tests/rrtype_python_test.py b/src/lib/dns/python/tests/rrtype_python_test.py deleted file mode 100644 index 7d20136e54..0000000000 --- a/src/lib/dns/python/tests/rrtype_python_test.py +++ /dev/null @@ -1,153 +0,0 @@ -# Copyright (C) 2010 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. - -# -# Tests for the rrtype part of the pydnspp module -# - -import unittest -import os -from pydnspp import * - -class TestModuleSpec(unittest.TestCase): - - rrtype_1 = RRType(1) - rrtype_0x80 = RRType(0x80); - rrtype_0x800 = RRType(0x800); - rrtype_0x8000 = RRType(0x8000); - rrtype_max = RRType(0xffff); - wiredata = bytearray(b'\x00\x01\x00\x80\x08\x00\x80\x00\xff\xff'); - - - def test_init(self): - b = bytearray(b'\x00\x01') - self.assertEqual(RRType("A"), RRType(b)) - b = bytearray(b'\x01') - self.assertRaises(IncompleteRRType, RRType, b) - self.assertRaises(TypeError, RRType, Exception) - # Range check. We need to do this at the binding level, so we need - # explicit tests for it. - self.assertRaises(ValueError, RRType, 65536) - self.assertRaises(TypeError, RRType, -1) - self.assertEqual("TYPE65535", RRType(65535).to_text()); - self.assertEqual("TYPE0", RRType(0).to_text()); - - def test_init_from_text(self): - self.assertEqual("A", RRType("A").to_text()) - self.assertEqual("NS", RRType("NS").to_text()); - self.assertEqual("NS", str(RRType("NS"))); - self.assertEqual("TYPE65535", RRType("TYPE65535").to_text()); - - self.assertEqual(53, RRType("TYPE00053").get_code()); - - self.assertRaises(InvalidRRType, RRType, "TYPE000053"); - - self.assertRaises(InvalidRRType, RRType, "TYPE"); - self.assertRaises(InvalidRRType, RRType, "TYPE-1"); - self.assertRaises(InvalidRRType, RRType, "TYPExxx"); - self.assertRaises(InvalidRRType, RRType, "TYPE65536"); - self.assertRaises(InvalidRRType, RRType, "TYPE6500x"); - self.assertRaises(InvalidRRType, RRType, "TYPE65000 "); - - def test_case_construct(self): - self.assertEqual("A", RRType("a").to_text()); - self.assertEqual("NS", RRType("ns").to_text()); - self.assertEqual("TYPE65535", RRType("type65535").to_text()); - - def test_to_text(self): - self.assertEqual("A", RRType(1).to_text()); - self.assertEqual("A", str(RRType(1))); - self.assertEqual("TYPE65000", RRType(65000).to_text()); - - def test_to_wire_buffer(self): - obuffer = bytearray() - self.rrtype_1.to_wire(obuffer); - self.rrtype_0x80.to_wire(obuffer); - self.rrtype_0x800.to_wire(obuffer); - self.rrtype_0x8000.to_wire(obuffer); - self.rrtype_max.to_wire(obuffer); - - self.assertEqual(self.wiredata, obuffer) - - def test_to_wire_renderer(self): - mr = MessageRenderer() - self.rrtype_1.to_wire(mr); - self.rrtype_0x80.to_wire(mr); - self.rrtype_0x800.to_wire(mr); - self.rrtype_0x8000.to_wire(mr); - self.rrtype_max.to_wire(mr); - - self.assertEqual(self.wiredata, mr.get_data()) - - def test_to_wire_bad(self): - self.assertRaises(TypeError, self.rrtype_1.to_wire, "wrong") - - def test_compare(self): - self.assertTrue(RRType(1) == RRType("A")); - #self.assertTrue(RRType(1).equals(RRType("A"))); - self.assertTrue(RRType(0) != RRType("A")); - #self.assertTrue(RRType(0).nequals(RRType("A"))); - - self.assertTrue(RRType("A") < RRType("NS")); - self.assertTrue(RRType("A") <= RRType("NS")); - self.assertTrue(RRType(100) < RRType(65535)); - self.assertFalse(RRType(100) > RRType(65535)); - self.assertFalse(RRType(100) >= RRType(65535)); - - self.assertFalse(RRType(1) != RRType("A")); - self.assertFalse(RRType(0) == RRType("A")); - self.assertFalse(RRType("A") > RRType("NS")); - self.assertFalse(RRType("A") >= RRType("NS")); - self.assertFalse(RRType(100) > RRType(65535)); - self.assertTrue(RRType(100) < RRType(65535)); - self.assertTrue(RRType(100) <= RRType(65535)); - - self.assertFalse(self.rrtype_1 == 1) - - def test_hash(self): - # Exploiting the knowledge that the hash value is the numeric class - # value, we can predict the comparison result. - self.assertEqual(hash(RRType.AAAA), hash(RRType("AAAA"))) - self.assertEqual(hash(RRType("aaaa")), hash(RRType("AAAA"))) - self.assertEqual(hash(RRType(28)), hash(RRType("AAAA"))) - self.assertNotEqual(hash(RRType.A), hash(RRType.NS)) - self.assertNotEqual(hash(RRType.AAAA), hash(RRType("Type65535"))) - - def test_statics(self): - self.assertEqual(RRType("NSEC3PARAM"), RRType.NSEC3PARAM) - self.assertEqual(RRType("DNAME"), RRType.DNAME) - self.assertEqual(RRType("PTR"), RRType.PTR) - self.assertEqual(RRType("MX"), RRType.MX) - self.assertEqual(RRType("DNSKEY"), RRType.DNSKEY) - self.assertEqual(RRType("TXT"), RRType.TXT) - self.assertEqual(RRType("RRSIG"), RRType.RRSIG) - self.assertEqual(RRType("NSEC"), RRType.NSEC) - self.assertEqual(RRType("AAAA"), RRType.AAAA) - self.assertEqual(RRType("DS"), RRType.DS) - self.assertEqual(RRType("OPT"), RRType.OPT) - self.assertEqual(RRType("A"), RRType.A) - self.assertEqual(RRType("NS"), RRType.NS) - self.assertEqual(RRType("CNAME"), RRType.CNAME) - self.assertEqual(RRType("SOA"), RRType.SOA) - self.assertEqual(RRType("NSEC3"), RRType.NSEC3) - - # these can't be built with string input - # (see the original cpp TODO) - self.assertEqual(251, RRType.IXFR.get_code()) - self.assertEqual(252, RRType.AXFR.get_code()) - self.assertEqual(255, RRType.ANY.get_code()) - -if __name__ == '__main__': - unittest.main() diff --git a/src/lib/dns/python/tests/serial_python_test.py b/src/lib/dns/python/tests/serial_python_test.py deleted file mode 100644 index 0ca08c2ffd..0000000000 --- a/src/lib/dns/python/tests/serial_python_test.py +++ /dev/null @@ -1,111 +0,0 @@ -# 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. - -# -# Tests for the rrttl part of the pydnspp module -# - -import unittest -import os -from pydnspp import * - -class SerialTest(unittest.TestCase): - def setUp(self): - self.one = Serial(1) - self.one_2 = Serial(1) - self.two = Serial(2) - self.date_zero = Serial(1980120100) - self.date_one = Serial(1980120101) - self.zero = Serial(0) - self.highest = Serial(4294967295) - self.number_low = Serial(12345) - self.number_medium = Serial(2000000000) - self.number_high = Serial(4000000000) - - def test_init(self): - self.assertRaises(ValueError, Serial, -1) - self.assertRaises(ValueError, Serial, 4294967296) - self.assertRaises(ValueError, Serial, 4294967297) - self.assertRaises(ValueError, Serial, 100000000000) - - def test_get_value(self): - self.assertEqual(1, self.one.get_value()) - self.assertNotEqual(2, self.one_2.get_value()) - self.assertEqual(2, self.two.get_value()) - self.assertEqual(1980120100, self.date_zero.get_value()) - self.assertEqual(1980120101, self.date_one.get_value()) - self.assertEqual(0, self.zero.get_value()) - self.assertEqual(4294967295, self.highest.get_value()) - self.assertEqual(12345, self.number_low.get_value()) - self.assertEqual(2000000000, self.number_medium.get_value()) - self.assertEqual(4000000000, self.number_high.get_value()) - - def test_str(self): - self.assertEqual('1', str(self.one)) - self.assertNotEqual('2', str(self.one_2)) - self.assertEqual('2', str(self.two)) - self.assertEqual('1980120100', str(self.date_zero)) - self.assertEqual('1980120101', str(self.date_one)) - self.assertEqual('0', str(self.zero)) - self.assertEqual('4294967295', str(self.highest)) - self.assertEqual('12345', str(self.number_low)) - self.assertEqual('2000000000', str(self.number_medium)) - self.assertEqual('4000000000', str(self.number_high)) - - def test_equals(self): - self.assertEqual(self.one, self.one) - self.assertEqual(self.one, self.one_2) - self.assertNotEqual(self.one, self.two) - self.assertNotEqual(self.two, self.one) - self.assertEqual(Serial(12345), self.number_low) - self.assertNotEqual(Serial(12346), self.number_low) - - def test_compare(self): - # These should be true/false even without serial arithmetic - self.assertLessEqual(self.one, self.one) - self.assertLessEqual(self.one, self.one_2) - self.assertLess(self.one, self.two) - self.assertLessEqual(self.one, self.one) - self.assertLessEqual(self.one, self.two) - self.assertGreater(self.two, self.one) - self.assertGreaterEqual(self.two, self.two) - self.assertGreaterEqual(self.two, self.one) - self.assertLess(self.one, self.number_low) - self.assertLess(self.number_low, self.number_medium) - self.assertLess(self.number_medium, self.number_high) - - # These should 'wrap' - self.assertGreater(self.zero, self.highest) - self.assertLess(self.highest, self.one) - self.assertLess(self.number_high, self.number_low) - - def test_addition(self): - self.assertEqual(self.two, self.one + self.one) - self.assertEqual(self.two, self.one + self.one_2) - self.assertEqual(self.highest, self.highest + self.zero) - self.assertEqual(self.zero, self.highest + self.one) - self.assertEqual(self.one, self.highest + self.two) - self.assertEqual(self.one, self.highest + self.one + self.one) - self.assertEqual(self.one + 100, self.highest + 102) - self.assertEqual(100 + self.one, self.highest + 102) - self.assertEqual(self.zero + 2147483645, self.highest + 2147483646) - - # using lambda so the error doesn't get thrown on initial evaluation - self.assertRaises(TypeError, lambda: self.zero + "bad") - self.assertRaises(TypeError, lambda: self.zero + None) - self.assertRaises(TypeError, lambda: "bad" + self.zero) - -if __name__ == '__main__': - unittest.main() diff --git a/src/lib/dns/python/tests/testutil.py b/src/lib/dns/python/tests/testutil.py deleted file mode 100644 index 6a1397f075..0000000000 --- a/src/lib/dns/python/tests/testutil.py +++ /dev/null @@ -1,43 +0,0 @@ -# Copyright (C) 2010 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. - -# -# helper functions for tests taken from C++ unittests -# - -import os - -if "TESTDATA_PATH" in os.environ: - testdata_path = os.environ["TESTDATA_PATH"] -else: - testdata_path = "../tests/testdata" - -def read_wire_data(filename): - data = bytes() - for path in testdata_path.split(":"): - try: - with open(path + os.sep + filename, "r") as f: - for line in f: - line = line.strip() - if line == "" or line.startswith("#"): - pass - else: - cur_data = bytes.fromhex(line) - data += cur_data - - return data - except IOError: - pass - raise ValueError("Data file " + filename + "cannot be found") diff --git a/src/lib/dns/python/tests/tsig_python_test.py b/src/lib/dns/python/tests/tsig_python_test.py deleted file mode 100644 index 282431c34f..0000000000 --- a/src/lib/dns/python/tests/tsig_python_test.py +++ /dev/null @@ -1,563 +0,0 @@ -# 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. - -import base64, sys, time, unittest -from pydnspp import * -from testutil import * -from pyunittests_util import fix_current_time - -# bit-wise constant flags to configure DNS header flags for test -# messages. -QR_FLAG = 0x1 -AA_FLAG = 0x2 -RD_FLAG = 0x4 - -COMMON_EXPECTED_MAC = b"\x22\x70\x26\xad\x29\x7b\xee\xe7\x21\xce\x6c\x6f\xff\x1e\x9e\xf3" -DUMMY_DATA = b"\xdd" * 100 - -class TSIGContextTest(unittest.TestCase): - tsig_key = TSIGKey('www.example.com:SFuWd/q99SzF8Yzd1QbB9g==') - - def setUp(self): - # make sure we don't use faked time unless explicitly do so in tests - fix_current_time(None) - self.qid = 0x2d65 - self.test_name = Name("www.example.com") - self.tsig_ctx = TSIGContext(self.tsig_key) - self.tsig_verify_ctx = TSIGContext(self.tsig_key) - self.keyring = TSIGKeyRing() - self.message = Message(Message.RENDER) - self.renderer = MessageRenderer() - self.test_class = RRClass.IN - self.test_ttl = RRTTL(86400) - self.secret = base64.b64decode(b"SFuWd/q99SzF8Yzd1QbB9g==") - self.tsig_ctx = TSIGContext(TSIGKey(self.test_name, - TSIGKey.HMACMD5_NAME, - self.secret)) - self.badkey_name = Name("badkey.example.com") - self.dummy_record = TSIGRecord(self.badkey_name, - TSIG("hmac-md5.sig-alg.reg.int. " + \ - "1302890362 300 0 11621 " + \ - "0 0")) - - def tearDown(self): - # reset any faked current time setting (it would affect other tests) - fix_current_time(None) - - # Note: intentionally use camelCase so that we can easily copy-paste - # corresponding C++ tests. - def createMessageAndSign(self, id, qname, ctx, message_flags=RD_FLAG, - qtype=RRType.A, answer_data=None, - answer_type=None, add_question=True, - rcode=Rcode.NOERROR): - self.message.clear(Message.RENDER) - self.message.set_qid(id) - self.message.set_opcode(Opcode.QUERY) - self.message.set_rcode(rcode) - if (message_flags & QR_FLAG) != 0: - self.message.set_header_flag(Message.HEADERFLAG_QR) - if (message_flags & AA_FLAG) != 0: - self.message.set_header_flag(Message.HEADERFLAG_AA) - if (message_flags & RD_FLAG) != 0: - self.message.set_header_flag(Message.HEADERFLAG_RD) - if add_question: - self.message.add_question(Question(qname, self.test_class, qtype)) - if answer_data is not None: - if answer_type is None: - answer_type = qtype - answer_rrset = RRset(qname, self.test_class, answer_type, - self.test_ttl) - answer_rrset.add_rdata(Rdata(answer_type, self.test_class, - answer_data)) - self.message.add_rrset(Message.SECTION_ANSWER, answer_rrset) - self.renderer.clear() - self.message.to_wire(self.renderer) - - if ctx.get_state() == TSIGContext.STATE_INIT: - expected_new_state = TSIGContext.STATE_SENT_REQUEST - else: - expected_new_state = TSIGContext.STATE_SENT_RESPONSE - tsig = ctx.sign(id, self.renderer.get_data()) - - return tsig - - # Note: intentionally use camelCase so that we can easily copy-paste - # corresponding C++ tests. - def createMessageFromFile(self, file): - self.message.clear(Message.PARSE) - self.received_data = read_wire_data(file) - self.message.from_wire(self.received_data) - - # Note: intentionally use camelCase so that we can easily copy-paste - # corresponding C++ tests. - def commonSignChecks(self, tsig, expected_qid, expected_timesigned, - expected_mac, expected_error=0, - expected_otherdata=None, - expected_algorithm=TSIGKey.HMACMD5_NAME): - tsig_rdata = tsig.get_rdata() - self.assertEqual(expected_algorithm, tsig_rdata.get_algorithm()) - self.assertEqual(expected_timesigned, tsig_rdata.get_timesigned()) - self.assertEqual(300, tsig_rdata.get_fudge()) - self.assertEqual(expected_mac, tsig_rdata.get_mac()) - self.assertEqual(expected_qid, tsig_rdata.get_original_id()) - self.assertEqual(expected_error, tsig_rdata.get_error()) - self.assertEqual(expected_otherdata, tsig_rdata.get_other_data()) - - def test_initial_state(self): - # Until signing or verifying, the state should be INIT - self.assertEqual(TSIGContext.STATE_INIT, self.tsig_ctx.get_state()) - - # And there should be no error code. - self.assertEqual(TSIGError(Rcode.NOERROR), self.tsig_ctx.get_error()) - - # No message signed yet - self.assertRaises(TSIGContextError, self.tsig_ctx.last_had_signature) - - # Note: intentionally use camelCase so that we can easily copy-paste - # corresponding C++ tests. - def commonVerifyChecks(self, ctx, record, data, expected_error, - expected_new_state=\ - TSIGContext.STATE_VERIFIED_RESPONSE, - last_should_throw=False): - self.assertEqual(expected_error, ctx.verify(record, data)) - self.assertEqual(expected_error, ctx.get_error()) - self.assertEqual(expected_new_state, ctx.get_state()) - if last_should_throw: - self.assertRaises(TSIGContextError, ctx.last_had_signature) - else: - self.assertEqual(record is not None, - ctx.last_had_signature()) - def test_from_keyring(self): - # Construct a TSIG context with an empty key ring. Key shouldn't be - # found, and the BAD_KEY error should be recorded. - ctx = TSIGContext(self.test_name, TSIGKey.HMACMD5_NAME, self.keyring) - self.assertEqual(TSIGContext.STATE_INIT, ctx.get_state()) - self.assertEqual(TSIGError.BAD_KEY, ctx.get_error()) - # check get_error() doesn't cause ref leak. Note: we can't - # realiably do this check for get_state(), as it returns an integer - # object, which could have many references - self.assertEqual(1, sys.getrefcount(ctx.get_error())) - - # Add a matching key (we don't use the secret so leave it empty), and - # construct it again. This time it should be constructed with a valid - # key. - self.keyring.add(TSIGKey(self.test_name, TSIGKey.HMACMD5_NAME, b"")) - ctx = TSIGContext(self.test_name, TSIGKey.HMACMD5_NAME, self.keyring) - self.assertEqual(TSIGContext.STATE_INIT, ctx.get_state()) - self.assertEqual(TSIGError.NOERROR, ctx.get_error()) - - # Similar to the first case except that the key ring isn't empty but - # it doesn't contain a matching key. - ctx = TSIGContext(self.test_name, TSIGKey.HMACSHA1_NAME, self.keyring) - self.assertEqual(TSIGContext.STATE_INIT, ctx.get_state()) - self.assertEqual(TSIGError.BAD_KEY, ctx.get_error()) - - ctx = TSIGContext(Name("different-key.example"), - TSIGKey.HMACMD5_NAME, self.keyring) - self.assertEqual(TSIGContext.STATE_INIT, ctx.get_state()) - self.assertEqual(TSIGError.BAD_KEY, ctx.get_error()) - - # "Unknown" algorithm name will result in BADKEY, too. - ctx = TSIGContext(self.test_name, Name("unknown.algorithm"), - self.keyring) - self.assertEqual(TSIGContext.STATE_INIT, ctx.get_state()) - self.assertEqual(TSIGError.BAD_KEY, ctx.get_error()) - - def test_sign(self): - fix_current_time(0x4da8877a) - tsig = self.createMessageAndSign(self.qid, self.test_name, - self.tsig_ctx) - self.commonSignChecks(tsig, self.qid, 0x4da8877a, COMMON_EXPECTED_MAC) - - # Same test as sign, but specifying the key name with upper-case (i.e. - # non canonical) characters. The digest must be the same. It should - # actually be ensured at the level of TSIGKey, but we confirm that at - # this level, too. - def test_sign_using_uppercase_keyname(self): - fix_current_time(0x4da8877a) - cap_ctx = TSIGContext(TSIGKey(Name("WWW.EXAMPLE.COM"), - TSIGKey.HMACMD5_NAME, self.secret)) - tsig = self.createMessageAndSign(self.qid, self.test_name, cap_ctx) - self.commonSignChecks(tsig, self.qid, 0x4da8877a, COMMON_EXPECTED_MAC) - - # Same as the previous test, but for the algorithm name. - def test_sign_using_uppercase_algorithm_name(self): - fix_current_time(0x4da8877a) - cap_ctx = TSIGContext(TSIGKey(self.test_name, - Name("HMAC-md5.SIG-alg.REG.int"), - self.secret)) - tsig = self.createMessageAndSign(self.qid, self.test_name, cap_ctx) - self.commonSignChecks(tsig, self.qid, 0x4da8877a, COMMON_EXPECTED_MAC) - - # Sign the message using the actual time, and check the accuracy of it. - # We cannot reasonably predict the expected MAC, so don't bother to - # check it. - def test_sign_at_actual_time(self): - now = int(time.time()) - tsig = self.createMessageAndSign(self.qid, self.test_name, - self.tsig_ctx) - tsig_rdata = tsig.get_rdata() - - # Check the resulted time signed is in the range of [now, now + 5] - self.assertTrue(now <= tsig_rdata.get_timesigned()) - self.assertTrue(now + 5 >= tsig_rdata.get_timesigned()) - - def test_bad_data(self): - self.assertRaises(TypeError, self.tsig_ctx.sign, None, 10) - - def test_verify_bad_data(self): - # the data must at least hold the DNS message header and the specified - # TSIG. - bad_len = 12 + self.dummy_record.get_length() - 1 - self.assertRaises(InvalidParameter, self.tsig_ctx.verify, - self.dummy_record, DUMMY_DATA[:bad_len]) - - def test_sign_using_hmacsha1(self): - fix_current_time(0x4dae7d5f) - - secret = base64.b64decode(b"MA+QDhXbyqUak+qnMFyTyEirzng=") - sha1_ctx = TSIGContext(TSIGKey(self.test_name, TSIGKey.HMACSHA1_NAME, - secret)) - qid = 0x0967 - expected_mac = b"\x41\x53\x40\xc7\xda\xf8\x24\xed\x68\x4e\xe5\x86" + \ - b"\xf7\xb5\xa6\x7a\x2f\xeb\xc0\xd3" - tsig = self.createMessageAndSign(qid, self.test_name, sha1_ctx) - self.commonSignChecks(tsig, qid, 0x4dae7d5f, expected_mac, - 0, None, TSIGKey.HMACSHA1_NAME) - - def test_verify_then_sign_response(self): - fix_current_time(0x4da8877a) - - self.createMessageFromFile("message_toWire2.wire") - self.commonVerifyChecks(self.tsig_verify_ctx, - self.message.get_tsig_record(), - self.received_data, TSIGError.NOERROR, - TSIGContext.STATE_RECEIVED_REQUEST) - - tsig = self.createMessageAndSign(self.qid, self.test_name, - self.tsig_verify_ctx, - QR_FLAG|AA_FLAG|RD_FLAG, - RRType.A, "192.0.2.1") - - expected_mac = b"\x8f\xcd\xa6\x6a\x7c\xd1\xa3\xb9\x94\x8e\xb1\x86" + \ - b"\x9d\x38\x4a\x9f" - self.commonSignChecks(tsig, self.qid, 0x4da8877a, expected_mac) - - def test_verify_uppercase_names(self): - fix_current_time(0x4da8877a) - - self.createMessageFromFile("tsig_verify9.wire") - self.commonVerifyChecks(self.tsig_verify_ctx, - self.message.get_tsig_record(), - self.received_data, TSIGError.NOERROR, - TSIGContext.STATE_RECEIVED_REQUEST) - - def test_verify_forward_message(self): - fix_current_time(0x4da8877a) - - self.createMessageFromFile("tsig_verify6.wire") - self.commonVerifyChecks(self.tsig_verify_ctx, - self.message.get_tsig_record(), - self.received_data, TSIGError.NOERROR, - TSIGContext.STATE_RECEIVED_REQUEST) - - def test_sign_continuation(self): - fix_current_time(0x4da8e951) - - axfr_qid = 0x3410 - zone_name = Name("example.com") - - tsig = self.createMessageAndSign(axfr_qid, zone_name, self.tsig_ctx, - 0, RRType.AXFR) - - received_data = read_wire_data("tsig_verify1.wire") - self.commonVerifyChecks(self.tsig_verify_ctx, tsig, received_data, - TSIGError.NOERROR, - TSIGContext.STATE_RECEIVED_REQUEST) - - tsig = self.createMessageAndSign(axfr_qid, zone_name, - self.tsig_verify_ctx, - AA_FLAG|QR_FLAG, RRType.AXFR, - "ns.example.com. root.example.com." +\ - " 2011041503 7200 3600 2592000 1200", - RRType.SOA) - - received_data = read_wire_data("tsig_verify2.wire") - self.commonVerifyChecks(self.tsig_ctx, tsig, received_data, - TSIGError.NOERROR) - - expected_mac = b"\x10\x24\x58\xf7\xf6\x2d\xdd\x7d\x63\x8d\x74" +\ - b"\x60\x34\x13\x09\x68" - tsig = self.createMessageAndSign(axfr_qid, zone_name, - self.tsig_verify_ctx, - AA_FLAG|QR_FLAG, RRType.AXFR, - "ns.example.com.", RRType.NS, - False) - self.commonSignChecks(tsig, axfr_qid, 0x4da8e951, expected_mac) - - received_data = read_wire_data("tsig_verify3.wire") - self.commonVerifyChecks(self.tsig_ctx, tsig, received_data, - TSIGError.NOERROR) - - def test_badtime_response(self): - fix_current_time(0x4da8b9d6) - - test_qid = 0x7fc4 - tsig = self.createMessageAndSign(test_qid, self.test_name, - self.tsig_ctx, 0, RRType.SOA) - - # "advance the clock" and try validating, which should fail due to - # BADTIME - fix_current_time(0x4da8be86) - self.commonVerifyChecks(self.tsig_verify_ctx, tsig, DUMMY_DATA, - TSIGError.BAD_TIME, - TSIGContext.STATE_RECEIVED_REQUEST) - - # make and sign a response in the context of TSIG error. - tsig = self.createMessageAndSign(test_qid, self.test_name, - self.tsig_verify_ctx, - QR_FLAG, RRType.SOA, None, None, - True, Rcode.NOTAUTH) - - expected_otherdata = b"\x00\x00\x4d\xa8\xbe\x86" - expected_mac = b"\xd4\xb0\x43\xf6\xf4\x44\x95\xec\x8a\x01\x26" +\ - b"\x0e\x39\x15\x9d\x76" - - self.commonSignChecks(tsig, self.message.get_qid(), 0x4da8b9d6, - expected_mac, - 18, # error: BADTIME - expected_otherdata) - - def test_badtime_response2(self): - fix_current_time(0x4da8b9d6) - - tsig = self.createMessageAndSign(self.qid, self.test_name, - self.tsig_ctx, 0, RRType.SOA) - - # "rewind the clock" and try validating, which should fail due to - # BADTIME - fix_current_time(0x4da8b9d6 - 600) - self.commonVerifyChecks(self.tsig_verify_ctx, tsig, DUMMY_DATA, - TSIGError.BAD_TIME, - TSIGContext.STATE_RECEIVED_REQUEST) - - # Test various boundary conditions. We intentionally use the magic - # number of 300 instead of the constant variable for testing. - # In the okay cases, signature is not correct, but it's sufficient to - # check the error code isn't BADTIME for the purpose of this test. - def test_badtime_boundaries(self): - fix_current_time(0x4da8b9d6) - - tsig = self.createMessageAndSign(self.qid, self.test_name, - self.tsig_ctx, 0, RRType.SOA) - - fix_current_time(0x4da8b9d6 + 301) - self.assertEqual(TSIGError.BAD_TIME, - self.tsig_verify_ctx.verify(tsig, DUMMY_DATA)) - - fix_current_time(0x4da8b9d6 + 300) - self.assertNotEqual(TSIGError.BAD_TIME, - self.tsig_verify_ctx.verify(tsig, DUMMY_DATA)) - - fix_current_time(0x4da8b9d6 - 301) - self.assertEqual(TSIGError.BAD_TIME, - self.tsig_verify_ctx.verify(tsig, DUMMY_DATA)) - - fix_current_time(0x4da8b9d6 - 300) - self.assertNotEqual(TSIGError.BAD_TIME, - self.tsig_verify_ctx.verify(tsig, DUMMY_DATA)) - - def test_badtime_overflow(self): - fix_current_time(200) - tsig = self.createMessageAndSign(self.qid, self.test_name, - self.tsig_ctx, 0, RRType.SOA) - - # This should be in the okay range, but since "200 - fudge" overflows - # and we compare them as 64-bit unsigned integers, it results in a - # false positive (we intentionally accept that). - fix_current_time(100) - self.assertEqual(TSIGError.BAD_TIME, - self.tsig_verify_ctx.verify(tsig, DUMMY_DATA)) - - def test_badsig_response(self): - fix_current_time(0x4da8877a) - - # Try to sign a simple message with bogus secret. It should fail - # with BADSIG. - self.createMessageFromFile("message_toWire2.wire") - bad_ctx = TSIGContext(TSIGKey(self.test_name, TSIGKey.HMACMD5_NAME, - DUMMY_DATA)) - self.commonVerifyChecks(bad_ctx, self.message.get_tsig_record(), - self.received_data, TSIGError.BAD_SIG, - TSIGContext.STATE_RECEIVED_REQUEST) - - # Sign the same message (which doesn't matter for this test) with the - # context of "checked state". - tsig = self.createMessageAndSign(self.qid, self.test_name, bad_ctx) - self.commonSignChecks(tsig, self.message.get_qid(), 0x4da8877a, None, - 16) # 16: BADSIG - - def test_badkey_response(self): - # A similar test as badsigResponse but for BADKEY - fix_current_time(0x4da8877a) - tsig_ctx = TSIGContext(self.badkey_name, TSIGKey.HMACMD5_NAME, - self.keyring) - self.commonVerifyChecks(tsig_ctx, self.dummy_record, DUMMY_DATA, - TSIGError.BAD_KEY, - TSIGContext.STATE_RECEIVED_REQUEST) - - sig = self.createMessageAndSign(self.qid, self.test_name, tsig_ctx) - self.assertEqual(self.badkey_name, sig.get_name()) - self.commonSignChecks(sig, self.qid, 0x4da8877a, None, 17) # 17: BADKEY - - def test_badkey_for_response(self): - # "BADKEY" case for a response to a signed message - self.createMessageAndSign(self.qid, self.test_name, self.tsig_ctx) - self.commonVerifyChecks(self.tsig_ctx, self.dummy_record, DUMMY_DATA, - TSIGError.BAD_KEY, - TSIGContext.STATE_SENT_REQUEST) - - # A similar case with a different algorithm - dummy_record = TSIGRecord(self.test_name, - TSIG("hmac-sha1. 1302890362 300 0 " - "11621 0 0")) - self.commonVerifyChecks(self.tsig_ctx, dummy_record, DUMMY_DATA, - TSIGError.BAD_KEY, - TSIGContext.STATE_SENT_REQUEST) - - # According to RFC2845 4.6, if TSIG verification fails the client - # should discard that message and wait for another signed response. - # This test emulates that situation. - def test_badsig_then_validate(self): - fix_current_time(0x4da8877a) - - self.createMessageAndSign(self.qid, self.test_name, self.tsig_ctx) - self.createMessageFromFile("tsig_verify4.wire") - - self.commonVerifyChecks(self.tsig_ctx, self.message.get_tsig_record(), - self.received_data, TSIGError.BAD_SIG, - TSIGContext.STATE_SENT_REQUEST) - - self.createMessageFromFile("tsig_verify5.wire") - self.commonVerifyChecks(self.tsig_ctx, self.message.get_tsig_record(), - self.received_data, TSIGError.NOERROR, - TSIGContext.STATE_VERIFIED_RESPONSE) - - # Similar to the previous test, but the first response doesn't contain - # TSIG. - def test_nosig_then_validate(self): - fix_current_time(0x4da8877a) - self.createMessageAndSign(self.qid, self.test_name, self.tsig_ctx) - - self.commonVerifyChecks(self.tsig_ctx, None, DUMMY_DATA, - TSIGError.FORMERR, TSIGContext.STATE_SENT_REQUEST, - True) - - self.createMessageFromFile("tsig_verify5.wire") - self.commonVerifyChecks(self.tsig_ctx, self.message.get_tsig_record(), - self.received_data, TSIGError.NOERROR, - TSIGContext.STATE_VERIFIED_RESPONSE) - - # Similar to the previous test, but the first response results in BADTIME. - def test_badtime_then_validate(self): - fix_current_time(0x4da8877a) - tsig = self.createMessageAndSign(self.qid, self.test_name, - self.tsig_ctx) - - # "advance the clock" and try validating, which should fail due to - # BADTIME - fix_current_time(0x4da8877a + 600) - self.commonVerifyChecks(self.tsig_ctx, tsig, DUMMY_DATA, - TSIGError.BAD_TIME, TSIGContext.STATE_SENT_REQUEST) - - # revert the clock again. - fix_current_time(0x4da8877a) - self.createMessageFromFile("tsig_verify5.wire") - self.commonVerifyChecks(self.tsig_ctx, self.message.get_tsig_record(), - self.received_data, TSIGError.NOERROR, - TSIGContext.STATE_VERIFIED_RESPONSE) - - # We don't allow empty MAC unless the TSIG error is BADSIG or BADKEY. - def test_empty_mac(self): - fix_current_time(0x4da8877a) - - self.createMessageFromFile("tsig_verify7.wire") - - self.commonVerifyChecks(self.tsig_verify_ctx, - self.message.get_tsig_record(), - self.received_data, - TSIGError.BAD_SIG, - TSIGContext.STATE_RECEIVED_REQUEST) - - # If the empty MAC comes with a BADKEY error, the error is passed - # transparently. - self.createMessageFromFile("tsig_verify8.wire") - self.commonVerifyChecks(self.tsig_verify_ctx, - self.message.get_tsig_record(), - self.received_data, - TSIGError.BAD_KEY, - TSIGContext.STATE_RECEIVED_REQUEST) - - # Once the context is used for sending a signed response, it shouldn't - # be used for further verification. - def test_verify_after_sendresponse(self): - fix_current_time(0x4da8877a) - - self.createMessageFromFile("message_toWire2.wire") - self.tsig_verify_ctx.verify(self.message.get_tsig_record(), - self.received_data) - self.assertEqual(TSIGContext.STATE_RECEIVED_REQUEST, - self.tsig_verify_ctx.get_state()) - self.createMessageAndSign(self.qid, self.test_name, - self.tsig_verify_ctx, - QR_FLAG|AA_FLAG|RD_FLAG, RRType.A, - "192.0.2.1") - self.assertEqual(TSIGContext.STATE_SENT_RESPONSE, - self.tsig_verify_ctx.get_state()) - - # Now trying further verification. - self.createMessageFromFile("message_toWire2.wire") - self.assertRaises(TSIGContextError, self.tsig_verify_ctx.verify, - self.message.get_tsig_record(), self.received_data) - - # Likewise, once the context verifies a response, it shouldn't for - # signing any more. - def test_sign_after_verified(self): - fix_current_time(0x4da8877a) - - self.createMessageAndSign(self.qid, self.test_name, self.tsig_ctx) - self.createMessageFromFile("tsig_verify5.wire") - self.tsig_ctx.verify(self.message.get_tsig_record(), - self.received_data) - self.assertEqual(TSIGContext.STATE_VERIFIED_RESPONSE, - self.tsig_ctx.get_state()) - - # Now trying further signing. - self.assertRaises(TSIGContextError, self.createMessageAndSign, - self.qid, self.test_name, self.tsig_ctx) - - # Too short MAC should be rejected. - # Note: when we implement RFC4635-based checks, the error code will - # (probably) be FORMERR. - def test_too_short_mac(self): - fix_current_time(0x4da8877a) - self.createMessageFromFile("tsig_verify10.wire") - self.commonVerifyChecks(self.tsig_verify_ctx, - self.message.get_tsig_record(), - self.received_data, TSIGError.BAD_SIG, - TSIGContext.STATE_RECEIVED_REQUEST) - -if __name__ == '__main__': - unittest.main() diff --git a/src/lib/dns/python/tests/tsig_rdata_python_test.py b/src/lib/dns/python/tests/tsig_rdata_python_test.py deleted file mode 100644 index 7b861d6ca5..0000000000 --- a/src/lib/dns/python/tests/tsig_rdata_python_test.py +++ /dev/null @@ -1,30 +0,0 @@ -# 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. - -import unittest -import sys -from pydnspp import * - -class TSIGRdataTest(unittest.TestCase): - VALID_TEXT1 = "hmac-md5.sig-alg.reg.int. 1286779327 300 0 16020 BADKEY 0" - def test_from_string(self): - tsig = TSIG(self.VALID_TEXT1) - self.assertEqual(Name("hmac-md5.sig-alg.reg.int"), - tsig.get_algorithm()) - # check there's no leak in creating the name object: - self.assertEqual(1, sys.getrefcount(tsig.get_algorithm())) - -if __name__ == '__main__': - unittest.main() diff --git a/src/lib/dns/python/tests/tsigerror_python_test.py b/src/lib/dns/python/tests/tsigerror_python_test.py deleted file mode 100644 index 01860d3616..0000000000 --- a/src/lib/dns/python/tests/tsigerror_python_test.py +++ /dev/null @@ -1,97 +0,0 @@ -# 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. - -import unittest -import sys -from pydnspp import * - -class TSIGErrorTest(unittest.TestCase): - def test_from_code(self): - self.assertEqual(0, TSIGError(0).get_code()) - self.assertEqual(18, TSIGError(18).get_code()) - self.assertEqual(65535, TSIGError(65535).get_code()) - self.assertRaises(ValueError, TSIGError, 65536) - self.assertRaises(ValueError, TSIGError, -1) - self.assertRaises(TypeError, TSIGError, "not yet supported") - - def test_from_rcode(self): - # We use RCODE for code values from 0-15. - self.assertEqual(0, TSIGError(Rcode.NOERROR).get_code()) - self.assertEqual(15, TSIGError(Rcode(15)).get_code()) - - # From error code 16 TSIG errors define a separate space, so passing - # corresponding RCODE for such code values should be prohibited. - self.assertRaises(ValueError, TSIGError, Rcode(16)) - - def test_constants(self): - # We'll only test arbitrarily chosen subsets of the codes. - # This class is quite simple, so it should be suffice. - self.assertEqual(TSIGError.BAD_SIG_CODE, TSIGError(16).get_code()) - self.assertEqual(TSIGError.BAD_KEY_CODE, TSIGError(17).get_code()) - self.assertEqual(TSIGError.BAD_TIME_CODE, TSIGError(18).get_code()) - - self.assertEqual(0, TSIGError.NOERROR.get_code()) - self.assertEqual(9, TSIGError.NOTAUTH.get_code()) - self.assertEqual(14, TSIGError.RESERVED14.get_code()) - self.assertEqual(TSIGError.BAD_SIG_CODE, TSIGError.BAD_SIG.get_code()) - self.assertEqual(TSIGError.BAD_KEY_CODE, TSIGError.BAD_KEY.get_code()) - self.assertEqual(TSIGError.BAD_TIME_CODE, TSIGError.BAD_TIME.get_code()) - - def test_equal(self): - self.assertTrue(TSIGError.NOERROR == TSIGError(Rcode.NOERROR)) - self.assertTrue(TSIGError(Rcode.NOERROR) == TSIGError.NOERROR) - - self.assertTrue(TSIGError.BAD_SIG == TSIGError(16)) - self.assertTrue(TSIGError(16) == TSIGError.BAD_SIG) - - def test_nequal(self): - self.assertTrue(TSIGError.BAD_KEY != TSIGError(Rcode.NOERROR)) - self.assertTrue(TSIGError(Rcode.NOERROR) != TSIGError.BAD_KEY) - - def test_to_text(self): - # TSIGError derived from the standard Rcode - self.assertEqual("NOERROR", TSIGError(Rcode.NOERROR).to_text()) - - # Well known TSIG errors - self.assertEqual("BADSIG", TSIGError.BAD_SIG.to_text()) - self.assertEqual("BADKEY", TSIGError.BAD_KEY.to_text()) - self.assertEqual("BADTIME", TSIGError.BAD_TIME.to_text()) - - # Unknown (or not yet supported) codes. Simply converted as numeric. - self.assertEqual("19", TSIGError(19).to_text()); - self.assertEqual("65535", TSIGError(65535).to_text()); - - # also check str() works same way - self.assertEqual("NOERROR", str(TSIGError(Rcode.NOERROR))) - self.assertEqual("BADSIG", str(TSIGError.BAD_SIG)) - - def test_to_rcode(self): - # TSIGError derived from the standard Rcode - self.assertEqual(Rcode.NOERROR, TSIGError(Rcode.NOERROR).to_rcode()) - - # Well known TSIG errors - self.assertEqual(Rcode.NOTAUTH, TSIGError.BAD_SIG.to_rcode()) - self.assertEqual(Rcode.NOTAUTH, TSIGError.BAD_KEY.to_rcode()) - self.assertEqual(Rcode.NOTAUTH, TSIGError.BAD_TIME.to_rcode()) - - # Unknown (or not yet supported) codes are treated as SERVFAIL. - self.assertEqual(Rcode.SERVFAIL, TSIGError(19).to_rcode()) - self.assertEqual(Rcode.SERVFAIL, TSIGError(65535).to_rcode()) - - # Check there's no redundant refcount (which would cause leak) - self.assertEqual(1, sys.getrefcount(TSIGError.BAD_SIG.to_rcode())) - -if __name__ == '__main__': - unittest.main() diff --git a/src/lib/dns/python/tests/tsigkey_python_test.py b/src/lib/dns/python/tests/tsigkey_python_test.py deleted file mode 100644 index ca7a61ec62..0000000000 --- a/src/lib/dns/python/tests/tsigkey_python_test.py +++ /dev/null @@ -1,218 +0,0 @@ -# Copyright (C) 2010 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 -from pydnspp import * - -class TSIGKeyTest(unittest.TestCase): - key_name = Name('example.com') - secret = b'anotherRandomData' - - def test_algorithm_names(self): - self.assertEqual(Name('hmac-md5.sig-alg.reg.int'), - TSIGKey.HMACMD5_NAME) - self.assertEqual(Name('hmac-sha1'), TSIGKey.HMACSHA1_NAME) - self.assertEqual(Name('hmac-sha256'), TSIGKey.HMACSHA256_NAME) - self.assertEqual(Name('hmac-sha224'), TSIGKey.HMACSHA224_NAME) - self.assertEqual(Name('hmac-sha384'), TSIGKey.HMACSHA384_NAME) - self.assertEqual(Name('hmac-sha512'), TSIGKey.HMACSHA512_NAME) - - def test_init(self): - key = TSIGKey(self.key_name, TSIGKey.HMACMD5_NAME, self.secret) - self.assertEqual(self.key_name, key.get_key_name()) - self.assertEqual(Name('hmac-md5.sig-alg.reg.int'), - key.get_algorithm_name()) - self.assertEqual(self.secret, key.get_secret()) - - self.assertRaises(InvalidParameter, TSIGKey, self.key_name, - Name('unknown-alg'), self.secret) - - self.assertEqual('hmac-sha1.', - TSIGKey(self.key_name, TSIGKey.HMACSHA1_NAME, - self.secret).get_algorithm_name().to_text()) - - self.assertRaises(TypeError, TSIGKey, self.key_name, - TSIGKey.HMACMD5_NAME, - 'should be binary') # signature mismatch - - def test_str(self): - k1 = TSIGKey('test.example:CwsLCwsLCwsLCwsLCwsLCw==:hmac-md5.sig-alg.reg.int') - self.assertEqual(Name('test.example.'), k1.get_key_name()) - self.assertEqual(Name('hmac-md5.sig-alg.reg.int.'), k1.get_algorithm_name()) - self.assertEqual(b'\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b', - k1.get_secret()) - self.assertEqual('test.example.:CwsLCwsLCwsLCwsLCwsLCw==:hmac-md5.sig-alg.reg.int.', - k1.to_text()) - - self.assertRaises(InvalidParameter, TSIGKey, - 'test.example:CwsLCwsLCwsLCwsLCwsLCw==:unsupported') - self.assertRaises(InvalidParameter, TSIGKey, - '::') - self.assertRaises(InvalidParameter, TSIGKey, - 'test.example:') - self.assertRaises(InvalidParameter, TSIGKey, - 'test.example:%bad_base_64%') - self.assertRaises(InvalidParameter, TSIGKey, - 'test.example:CwsLCwsLCwsLCwsLCwsLCw==:') - self.assertRaises(InvalidParameter, TSIGKey, - 'test.:example:CwsLCwsLCwsLCwsLCwsLCw==') - -class TSIGKeyRingTest(unittest.TestCase): - key_name = Name('example.com') - md5_name = Name('hmac-md5.sig-alg.reg.int') - sha1_name = Name('hmac-sha1') - sha256_name = Name('hmac-sha256') - secret = b'someRandomData' - - def setUp(self): - self.keyring = TSIGKeyRing() - - def test_init(self): - self.assertEqual(0, self.keyring.size()) - self.assertRaises(TypeError, TSIGKeyRing, 1) - self.assertRaises(TypeError, TSIGKeyRing, 'there should not be arg') - - def test_add(self): - self.assertEqual(TSIGKeyRing.SUCCESS, - self.keyring.add(TSIGKey(self.key_name, - TSIGKey.HMACSHA256_NAME, - self.secret))) - self.assertEqual(1, self.keyring.size()) - self.assertEqual(TSIGKeyRing.EXIST, - self.keyring.add(TSIGKey(self.key_name, - TSIGKey.HMACSHA256_NAME, - self.secret))) - self.assertEqual(TSIGKeyRing.EXIST, - self.keyring.add(TSIGKey(self.key_name, - TSIGKey.HMACSHA1_NAME, - self.secret))) - self.assertEqual(TSIGKeyRing.EXIST, - self.keyring.add(TSIGKey(Name('EXAMPLE.COM'), - TSIGKey.HMACSHA1_NAME, - self.secret))) - self.assertEqual(1, self.keyring.size()) - - def test_add_more(self): - self.assertEqual(TSIGKeyRing.SUCCESS, - self.keyring.add(TSIGKey(self.key_name, - TSIGKey.HMACSHA256_NAME, - self.secret))) - self.assertEqual(TSIGKeyRing.SUCCESS, - self.keyring.add(TSIGKey(Name('another.example'), - TSIGKey.HMACMD5_NAME, - self.secret))) - self.assertEqual(TSIGKeyRing.SUCCESS, - self.keyring.add(TSIGKey(Name('more.example'), - TSIGKey.HMACSHA1_NAME, - self.secret))) - self.assertEqual(3, self.keyring.size()) - - self.assertRaises(TypeError, self.keyring.add, 1) - self.assertRaises(TypeError, self.keyring.add, 'invalid arg') - - def test_remove(self): - self.assertEqual(TSIGKeyRing.SUCCESS, - self.keyring.add(TSIGKey(self.key_name, - TSIGKey.HMACSHA256_NAME, - self.secret))) - self.assertEqual(TSIGKeyRing.SUCCESS, - self.keyring.remove(self.key_name)) - self.assertEqual(TSIGKeyRing.NOTFOUND, - self.keyring.remove(self.key_name)) - - self.assertRaises(TypeError, self.keyring.add, 1) - self.assertRaises(TypeError, self.keyring.add, 'invalid arg') - self.assertRaises(TypeError, self.keyring.add, self.key_name, 0) - - def test_remove_from_some(self): - self.assertEqual(TSIGKeyRing.SUCCESS, - self.keyring.add(TSIGKey(self.key_name, - TSIGKey.HMACSHA256_NAME, - self.secret))) - self.assertEqual(TSIGKeyRing.SUCCESS, - self.keyring.add(TSIGKey(Name('another.example'), - TSIGKey.HMACMD5_NAME, - self.secret))) - self.assertEqual(TSIGKeyRing.SUCCESS, - self.keyring.add(TSIGKey(Name('more.example'), - TSIGKey.HMACSHA1_NAME, - self.secret))) - - self.assertEqual(TSIGKeyRing.SUCCESS, - self.keyring.remove(Name('another.example'))) - self.assertEqual(TSIGKeyRing.NOTFOUND, - self.keyring.remove(Name('noexist.example'))) - self.assertEqual(2, self.keyring.size()) - - def test_find(self): - self.assertEqual((TSIGKeyRing.NOTFOUND, None), - self.keyring.find(self.key_name, self.md5_name)) - - self.assertEqual(TSIGKeyRing.SUCCESS, - self.keyring.add(TSIGKey(self.key_name, - self.sha256_name, - self.secret))) - (code, key) = self.keyring.find(self.key_name, self.sha256_name) - self.assertEqual(TSIGKeyRing.SUCCESS, code) - self.assertEqual(self.key_name, key.get_key_name()) - self.assertEqual(TSIGKey.HMACSHA256_NAME, key.get_algorithm_name()) - self.assertEqual(self.secret, key.get_secret()) - - (code, key) = self.keyring.find(self.key_name) - self.assertEqual(TSIGKeyRing.SUCCESS, code) - self.assertEqual(self.key_name, key.get_key_name()) - self.assertEqual(TSIGKey.HMACSHA256_NAME, key.get_algorithm_name()) - self.assertEqual(self.secret, key.get_secret()) - - (code, key) = self.keyring.find(Name('different-key.example'), - self.sha256_name) - self.assertEqual(TSIGKeyRing.NOTFOUND, code) - self.assertEqual(None, key) - (code, key) = self.keyring.find(self.key_name, self.md5_name) - self.assertEqual(TSIGKeyRing.NOTFOUND, code) - self.assertEqual(None, key) - - self.assertRaises(TypeError, self.keyring.find, 1) - self.assertRaises(TypeError, self.keyring.find, 'should be a name') - self.assertRaises(TypeError, self.keyring.find, self.key_name, 0) - - def test_find_from_some(self): - self.assertEqual(TSIGKeyRing.SUCCESS, - self.keyring.add(TSIGKey(self.key_name, - self.sha256_name, - self.secret))) - self.assertEqual(TSIGKeyRing.SUCCESS, - self.keyring.add(TSIGKey(Name('another.example'), - self.md5_name, - self.secret))) - self.assertEqual(TSIGKeyRing.SUCCESS, - self.keyring.add(TSIGKey(Name('more.example'), - self.sha1_name, - self.secret))) - - (code, key) = self.keyring.find(Name('another.example'), self.md5_name) - self.assertEqual(TSIGKeyRing.SUCCESS, code) - self.assertEqual(Name('another.example'), key.get_key_name()) - self.assertEqual(TSIGKey.HMACMD5_NAME, key.get_algorithm_name()) - - self.assertEqual((TSIGKeyRing.NOTFOUND, None), - self.keyring.find(Name('noexist.example'), - self.sha1_name)) - self.assertEqual((TSIGKeyRing.NOTFOUND, None), - self.keyring.find(Name('another.example'), - self.sha1_name)) - -if __name__ == '__main__': - unittest.main() diff --git a/src/lib/dns/python/tests/tsigrecord_python_test.py b/src/lib/dns/python/tests/tsigrecord_python_test.py deleted file mode 100644 index 813a23b144..0000000000 --- a/src/lib/dns/python/tests/tsigrecord_python_test.py +++ /dev/null @@ -1,44 +0,0 @@ -# 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. - -import unittest -import sys -from pydnspp import * - -class TSIGRecordTest(unittest.TestCase): - def setUp(self): - self.test_name = Name("www.example.com") - self.test_rdata = TSIG("hmac-md5.sig-alg.reg.int. 1302890362 " + \ - "300 16 2tra2tra2tra2tra2tra2g== " + \ - "11621 0 0") - self.test_record = TSIGRecord(self.test_name, self.test_rdata) - - def test_getname(self): - self.assertEqual(self.test_name, self.test_record.get_name()) - self.assertEqual(1, sys.getrefcount(self.test_record.get_name())) - - def test_get_length(self): - # see the C++ test for the magic number - self.assertEqual(85, self.test_record.get_length()) - - def test_to_text(self): - expected_text = "www.example.com. 0 ANY TSIG " + \ - "hmac-md5.sig-alg.reg.int. 1302890362 300 16 " + \ - "2tra2tra2tra2tra2tra2g== 11621 NOERROR 0\n" - self.assertEqual(expected_text, self.test_record.to_text()) - self.assertEqual(expected_text, str(self.test_record)) - -if __name__ == '__main__': - unittest.main() diff --git a/src/lib/dns/python/tests/zone_checker_python_test.py b/src/lib/dns/python/tests/zone_checker_python_test.py deleted file mode 100644 index dc7d2586f0..0000000000 --- a/src/lib/dns/python/tests/zone_checker_python_test.py +++ /dev/null @@ -1,176 +0,0 @@ -# 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 'use_default' - # (as a string), find() returns that specified value (note that - # it can be None). - - def __init__(self, raise_on_find=False, find_result='use_default'): - 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 'use_default': - 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() diff --git a/src/lib/dns/python/tsig_python.cc b/src/lib/dns/python/tsig_python.cc deleted file mode 100644 index c5b5421dcc..0000000000 --- a/src/lib/dns/python/tsig_python.cc +++ /dev/null @@ -1,356 +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. - -#define PY_SSIZE_T_CLEAN // need for "y#" below -#include - -#include -#include - -#include - -#include - -#include - -#include "pydnspp_common.h" -#include "name_python.h" -#include "tsigkey_python.h" -#include "tsigerror_python.h" -#include "tsigrecord_python.h" -#include "tsig_python.h" - -using namespace std; -using namespace isc; -using namespace isc::util::python; -using namespace isc::dns; -using namespace isc::dns::python; - -// For each class, we need a struct, a helper functions (init, destroy, -// and static wrappers around the methods we export), a list of methods, -// and a type description - -namespace { -// The s_* Class simply covers one instantiation of the object -class s_TSIGContext : public PyObject { -public: - s_TSIGContext() : cppobj(NULL) {}; - TSIGContext* cppobj; -}; - -// Shortcut type which would be convenient for adding class variables safely. -typedef CPPPyObjectContainer TSIGContextContainer; - -// -// We declare the functions here, the definitions are below -// the type definition of the object, since both can use the other -// - -// General creation and destruction -int TSIGContext_init(s_TSIGContext* self, PyObject* args); -void TSIGContext_destroy(s_TSIGContext* self); - -// Class specific methods -PyObject* TSIGContext_getState(s_TSIGContext* self); -PyObject* TSIGContext_getError(s_TSIGContext* self); -PyObject* TSIGContext_sign(s_TSIGContext* self, PyObject* args); -PyObject* TSIGContext_verify(s_TSIGContext* self, PyObject* args); -PyObject* TSIGContext_lastHadSignature(s_TSIGContext* self); - -// These are the functions we export -// For a minimal support, we don't need them. - -// This list contains the actual set of functions we have in -// python. Each entry has -// 1. Python method name -// 2. Our static function here -// 3. Argument type -// 4. Documentation -PyMethodDef TSIGContext_methods[] = { - { "get_state", reinterpret_cast(TSIGContext_getState), - METH_NOARGS, - "Return the current state of the context (mainly for tests)" }, - { "get_error", reinterpret_cast(TSIGContext_getError), - METH_NOARGS, - "Return the TSIG error as a result of the latest verification" }, - { "sign", - reinterpret_cast(TSIGContext_sign), METH_VARARGS, - "Sign a DNS message." }, - { "verify", - reinterpret_cast(TSIGContext_verify), METH_VARARGS, - "Verify a DNS message." }, - { "last_had_signature", - reinterpret_cast(TSIGContext_lastHadSignature), METH_NOARGS, - "Return True if the last verified message contained a signature" }, - { NULL, NULL, 0, NULL } -}; - -int -TSIGContext_init(s_TSIGContext* self, PyObject* args) { - try { - // "From key" constructor - const PyObject* tsigkey_obj; - if (PyArg_ParseTuple(args, "O!", &tsigkey_type, &tsigkey_obj)) { - self->cppobj = new TSIGContext(PyTSIGKey_ToTSIGKey(tsigkey_obj)); - return (0); - } - - // "From key param + keyring" constructor - PyErr_Clear(); - const PyObject* keyname_obj; - const PyObject* algname_obj; - const PyObject* keyring_obj; - if (PyArg_ParseTuple(args, "O!O!O!", &name_type, &keyname_obj, - &name_type, &algname_obj, &tsigkeyring_type, - &keyring_obj)) { - self->cppobj = new TSIGContext(PyName_ToName(keyname_obj), - PyName_ToName(algname_obj), - PyTSIGKeyRing_ToTSIGKeyRing(keyring_obj)); - return (0); - } - } catch (const exception& ex) { - const string ex_what = "Failed to construct TSIGContext object: " + - string(ex.what()); - PyErr_SetString(po_IscException, ex_what.c_str()); - return (-1); - } catch (...) { - PyErr_SetString(po_IscException, - "Unexpected exception in constructing TSIGContext"); - return (-1); - } - - PyErr_SetString(PyExc_TypeError, - "Invalid arguments to TSIGContext constructor"); - - return (-1); -} - -void -TSIGContext_destroy(s_TSIGContext* const self) { - delete self->cppobj; - self->cppobj = NULL; - Py_TYPE(self)->tp_free(self); -} - -PyObject* -TSIGContext_getState(s_TSIGContext* self) { - return (Py_BuildValue("I", self->cppobj->getState())); -} - -PyObject* -TSIGContext_getError(s_TSIGContext* self) { - try { - PyObjectContainer container(createTSIGErrorObject( - self->cppobj->getError())); - return (Py_BuildValue("O", container.get())); - } catch (const exception& ex) { - const string ex_what = - "Unexpectedly failed to get TSIGContext error: " + - string(ex.what()); - PyErr_SetString(po_IscException, ex_what.c_str()); - } catch (...) { - PyErr_SetString(po_IscException, - "Unexpected exception in TSIGContext.get_error"); - } - return (NULL); -} - -PyObject* -TSIGContext_sign(s_TSIGContext* self, PyObject* args) { - long qid = 0; - const char* mac; - Py_ssize_t mac_size; - - if (PyArg_ParseTuple(args, "ly#", &qid, &mac, &mac_size)) { - if (qid < 0 || qid > 0xffff) { - PyErr_SetString(PyExc_ValueError, - "TSIGContext.sign: QID out of range"); - return (NULL); - } - - try { - ConstTSIGRecordPtr record = self->cppobj->sign(qid, mac, mac_size); - return (createTSIGRecordObject(*record)); - } catch (const TSIGContextError& ex) { - PyErr_SetString(po_TSIGContextError, ex.what()); - } catch (const exception& ex) { - const string ex_what = "Unexpected failure in TSIG sign: " + - string(ex.what()); - PyErr_SetString(po_IscException, ex_what.c_str()); - } catch (...) { - PyErr_SetString(PyExc_SystemError, - "Unexpected failure in TSIG sign"); - } - } else { - PyErr_SetString(PyExc_TypeError, - "Invalid arguments to TSIGContext.sign"); - } - - return (NULL); -} - -PyObject* -TSIGContext_verify(s_TSIGContext* self, PyObject* args) { - const char* data; - Py_ssize_t data_len; - PyObject* py_record; - PyObject* py_maybe_none; - const TSIGRecord* record; - - if (PyArg_ParseTuple(args, "O!y#", &tsigrecord_type, &py_record, - &data, &data_len)) { - record = &PyTSIGRecord_ToTSIGRecord(py_record); - } else if (PyArg_ParseTuple(args, "Oy#", &py_maybe_none, &data, - &data_len)) { - record = NULL; - } else { - PyErr_SetString(PyExc_TypeError, - "Invalid arguments to TSIGContext.verify"); - return (NULL); - } - PyErr_Clear(); - - try { - const TSIGError error = self->cppobj->verify(record, data, data_len); - return (createTSIGErrorObject(error)); - } catch (const TSIGContextError& ex) { - PyErr_SetString(po_TSIGContextError, ex.what()); - } catch (const InvalidParameter& ex) { - PyErr_SetString(po_InvalidParameter, ex.what()); - } catch (const exception& ex) { - const string ex_what = "Unexpected failure in TSIG verify: " + - string(ex.what()); - PyErr_SetString(po_IscException, ex_what.c_str()); - } catch (...) { - PyErr_SetString(PyExc_SystemError, "Unexpected failure in TSIG verify"); - } - - return (NULL); -} - -PyObject* -TSIGContext_lastHadSignature(s_TSIGContext* self) { - try { - long result = self->cppobj->lastHadSignature(); - return (PyBool_FromLong(result)); - } catch (const TSIGContextError& ex) { - PyErr_SetString(po_TSIGContextError, ex.what()); - } catch (const exception& ex) { - const string ex_what = - "Unexpected failure in TSIG lastHadSignature: " + - string(ex.what()); - PyErr_SetString(po_IscException, ex_what.c_str()); - } catch (...) { - PyErr_SetString(PyExc_SystemError, - "Unexpected failure in TSIG lastHadSignature"); - } - - return (NULL); -} -} // end of unnamed namespace - -namespace isc { -namespace dns { -namespace python { -// Definition of class specific exception(s) -PyObject* po_TSIGContextError; - -// This defines the complete type for reflection in python and -// parsing of PyObject* to s_TSIGContext -// Most of the functions are not actually implemented and NULL here. -PyTypeObject tsigcontext_type = { - PyVarObject_HEAD_INIT(NULL, 0) - "pydnspp.TSIGContext", - sizeof(s_TSIGContext), // tp_basicsize - 0, // tp_itemsize - reinterpret_cast(TSIGContext_destroy), // tp_dealloc - NULL, // tp_print - NULL, // tp_getattr - NULL, // tp_setattr - NULL, // tp_reserved - NULL, // tp_repr - NULL, // tp_as_number - NULL, // tp_as_sequence - NULL, // tp_as_mapping - NULL, // tp_hash - NULL, // tp_call - NULL, // tp_str - NULL, // tp_getattro - NULL, // tp_setattro - NULL, // tp_as_buffer - - // We allow the python version of TSIGContext to act as a base class. - // From pure design point of view, this is wrong because it's not intended - // to be inherited. However, cryptographic operations are generally - // difficult to test, so it would be very advantageous if we can define - // a mock context class. - Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, // tp_flags - - "The TSIGContext class objects is...(COMPLETE THIS)", - NULL, // tp_traverse - NULL, // tp_clear - NULL, // tp_richcompare - 0, // tp_weaklistoffset - NULL, // tp_iter - NULL, // tp_iternext - TSIGContext_methods, // tp_methods - NULL, // tp_members - NULL, // tp_getset - NULL, // tp_base - NULL, // tp_dict - NULL, // tp_descr_get - NULL, // tp_descr_set - 0, // tp_dictoffset - reinterpret_cast(TSIGContext_init), // tp_init - NULL, // tp_alloc - PyType_GenericNew, // tp_new - NULL, // tp_free - NULL, // tp_is_gc - NULL, // tp_bases - NULL, // tp_mro - NULL, // tp_cache - NULL, // tp_subclasses - NULL, // tp_weaklist - NULL, // tp_del - 0 // tp_version_tag -}; - -bool -PyTSIGContext_Check(PyObject* obj) { - if (obj == NULL) { - isc_throw(PyCPPWrapperException, "obj argument NULL in typecheck"); - } - return (PyObject_TypeCheck(obj, &tsigcontext_type)); -} - -TSIGContext* -PyTSIGContext_ToTSIGContext(PyObject* tsigcontext_obj) { - if (tsigcontext_obj == NULL) { - isc_throw(PyCPPWrapperException, - "obj argument NULL in TSIGContext PyObject conversion"); - } - - if (!PyTSIGContext_Check(tsigcontext_obj)) { - isc_throw(TSIGContextError, - "obj argument is of wrong type in TSIGContext " - "PyObject conversion"); - } - - s_TSIGContext* tsigcontext = static_cast(tsigcontext_obj); - return (tsigcontext->cppobj); -} - -} // namespace python -} // namespace dns -} // namespace isc diff --git a/src/lib/dns/python/tsig_python.h b/src/lib/dns/python/tsig_python.h deleted file mode 100644 index bbef56be10..0000000000 --- a/src/lib/dns/python/tsig_python.h +++ /dev/null @@ -1,59 +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. - -#ifndef PYTHON_TSIGCONTEXT_H -#define PYTHON_TSIGCONTEXT_H 1 - -#include - -namespace isc { -namespace dns { -class TSIGContext; - -namespace python { - -extern PyTypeObject tsigcontext_type; - -// Class specific exceptions -extern PyObject* po_TSIGContextError; - -/// \brief Checks if the given python object is a TSIGContext object -/// -/// \exception PyCPPWrapperException if obj is NULL -/// -/// \param obj The object to check the type of -/// \return true if the object is of type TSIGContext, false otherwise -bool PyTSIGContext_Check(PyObject* obj); - -/// \brief Returns a pointer to the TSIGContext object contained within -/// the given Python object. -/// -/// \note The given object MUST be of type TSIGContext; this can be checked with -/// either the right call to ParseTuple("O!"), or with PyTSIGContext_Check() -/// -/// \note This is not a copy; if the TSIGContext is needed when the PyObject -/// may be destroyed, the caller must copy it itself. -/// -/// \param tsigcontext_obj The tsigcontext object to convert -TSIGContext* PyTSIGContext_ToTSIGContext(PyObject* tsigcontext_obj); - - -} // namespace python -} // namespace dns -} // namespace isc -#endif // PYTHON_TSIGCONTEXT_H - -// Local Variables: -// mode: c++ -// End: diff --git a/src/lib/dns/python/tsig_rdata_python.cc b/src/lib/dns/python/tsig_rdata_python.cc deleted file mode 100644 index 6ec0f0999f..0000000000 --- a/src/lib/dns/python/tsig_rdata_python.cc +++ /dev/null @@ -1,367 +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. - -#define PY_SSIZE_T_CLEAN -#include - -#include -#include - -#include - -#include - -#include "pydnspp_common.h" -#include "pydnspp_towire.h" -#include "name_python.h" -#include "tsig_rdata_python.h" - -using namespace std; -using namespace isc::util::python; -using namespace isc::dns; -using namespace isc::dns::rdata; -using namespace isc::dns::python; - -// For each class, we need a struct, a helper functions (init, destroy, -// and static wrappers around the methods we export), a list of methods, -// and a type description - -namespace { -// The s_* Class simply covers one instantiation of the object -class s_TSIG : public PyObject { -public: - s_TSIG() : cppobj(NULL) {}; - const rdata::any::TSIG* cppobj; -}; - - -// Shortcut type which would be convenient for adding class variables safely. -typedef CPPPyObjectContainer TSIGContainer; - -// -// We declare the functions here, the definitions are below -// the type definition of the object, since both can use the other -// - -// General creation and destruction -int TSIG_init(s_TSIG* self, PyObject* args); -void TSIG_destroy(s_TSIG* self); - -// These are the functions we export -// ADD/REMOVE/MODIFY THE FOLLOWING AS APPROPRIATE FOR THE ACTUAL CLASS. -// -PyObject* TSIG_toText(const s_TSIG* const self); -PyObject* TSIG_getAlgorithm(const s_TSIG* const self); -PyObject* TSIG_getTimeSigned(const s_TSIG* const self); -PyObject* TSIG_getFudge(const s_TSIG* const self); -PyObject* TSIG_getOriginalID(const s_TSIG* const self); -PyObject* TSIG_getError(const s_TSIG* const self); -PyObject* TSIG_getMAC(const s_TSIG* const self); -PyObject* TSIG_getOtherData(const s_TSIG* const self); -PyObject* TSIG_str(PyObject* self); -PyObject* TSIG_richcmp(const s_TSIG* const self, - const s_TSIG* const other, int op); -PyObject* TSIG_toWire(const s_TSIG* self, PyObject* args); - -// These are the functions we export -// For a minimal support, we don't need them. - -// This list contains the actual set of functions we have in -// python. Each entry has -// 1. Python method name -// 2. Our static function here -// 3. Argument type -// 4. Documentation -PyMethodDef TSIG_methods[] = { - { "get_algorithm", reinterpret_cast(TSIG_getAlgorithm), - METH_NOARGS, - "Return the algorithm name." }, - { "get_timesigned", reinterpret_cast(TSIG_getTimeSigned), - METH_NOARGS, - "Return the value of the Time Signed field. " - "The returned value does not exceed 2^48-1." - }, - { "get_fudge", reinterpret_cast(TSIG_getFudge), - METH_NOARGS, - "Return the value of the Fudge field." }, - { "get_original_id", reinterpret_cast(TSIG_getOriginalID), - METH_NOARGS, - "Return the value of the Original ID field." }, - { "get_error", reinterpret_cast(TSIG_getError), - METH_NOARGS, - "Return the value of the Error field." }, - { "get_mac", reinterpret_cast(TSIG_getMAC), - METH_NOARGS, - "Return the value of the MAC field." - "If it's empty, return None." }, - { "get_other_data", reinterpret_cast(TSIG_getOtherData), - METH_NOARGS, - "Return the value of the Other Data field." - "If it's empty, return None." }, - { "to_text", reinterpret_cast(TSIG_toText), METH_NOARGS, - "Returns the text representation" }, - { "to_wire", reinterpret_cast(TSIG_toWire), METH_VARARGS, - "Converts the TSIG object to wire format.\n" - "The argument can be either a MessageRenderer or an object that " - "implements the sequence interface. If the object is mutable " - "(for instance a bytearray()), the wire data is added in-place.\n" - "If it is not (for instance a bytes() object), a new object is " - "returned" }, - { NULL, NULL, 0, NULL } -}; - -int -TSIG_init(s_TSIG* self, PyObject* args) { - try { - // constructor from string - const char* rdata_str; - if (PyArg_ParseTuple(args, "s", &rdata_str)) { - self->cppobj = new any::TSIG(string(rdata_str)); - return (0); - } - } catch (const exception& ex) { - const string ex_what = "Failed to construct TSIG object: " + - string(ex.what()); - PyErr_SetString(po_IscException, ex_what.c_str()); - return (-1); - } catch (...) { - PyErr_SetString(po_IscException, - "Unexpected exception in constructing TSIG"); - return (-1); - } - - PyErr_SetString(PyExc_TypeError, - "Invalid arguments to TSIG constructor"); - - return (-1); -} - -void -TSIG_destroy(s_TSIG* const self) { - delete self->cppobj; - self->cppobj = NULL; - Py_TYPE(self)->tp_free(self); -} - -PyObject* -TSIG_getAlgorithm(const s_TSIG* const self) { - try { - return (createNameObject(self->cppobj->getAlgorithm())); - } catch (const exception& ex) { - const string ex_what = - "Failed to get TSIG algorithm: " + string(ex.what()); - PyErr_SetString(po_IscException, ex_what.c_str()); - } catch (...) { - PyErr_SetString(PyExc_SystemError, "Unexpected failure in " - "getting TSIG algorithm"); - } - return (NULL); -} - -PyObject* -TSIG_getTimeSigned(const s_TSIG* const self) { - return (Py_BuildValue("K", self->cppobj->getTimeSigned())); -} - -PyObject* -TSIG_getFudge(const s_TSIG* const self) { - return (Py_BuildValue("H", self->cppobj->getFudge())); -} - -PyObject* -TSIG_getOriginalID(const s_TSIG* const self) { - return (Py_BuildValue("H", self->cppobj->getOriginalID())); -} - -PyObject* -TSIG_getError(const s_TSIG* const self) { - return (Py_BuildValue("H", self->cppobj->getError())); -} - -PyObject* -TSIG_getMAC(const s_TSIG* const self) { - return (Py_BuildValue("y#", self->cppobj->getMAC(), - self->cppobj->getMACSize())); -} - -PyObject* -TSIG_getOtherData(const s_TSIG* const self) { - return (Py_BuildValue("y#", self->cppobj->getOtherData(), - self->cppobj->getOtherLen())); -} - -PyObject* -TSIG_toText(const s_TSIG* const self) { - try { - // toText() could throw, so we need to catch any exceptions below. - return (Py_BuildValue("s", self->cppobj->toText().c_str())); - } catch (const exception& ex) { - const string ex_what = - "Failed to convert TSIG object to text: " + - string(ex.what()); - PyErr_SetString(po_IscException, ex_what.c_str()); - } catch (...) { - PyErr_SetString(PyExc_SystemError, "Unexpected failure in " - "converting TSIG object to text"); - } - return (NULL); -} - -PyObject* -TSIG_str(PyObject* self) { - // Simply call the to_text method we already defined - return (PyObject_CallMethod(self, const_cast("to_text"), - const_cast(""))); -} - -PyObject* -TSIG_toWire(const s_TSIG* const self, PyObject* args) { - typedef any::TSIG TSIGRdata; - return (toWireWrapper >( - self, args)); -} - -PyObject* -TSIG_richcmp(const s_TSIG* const self, - const s_TSIG* const other, - const int op) -{ - bool c = false; - - // Check for null and if the types match. If different type, - // simply return False - if (other == NULL || (self->ob_type != other->ob_type)) { - Py_RETURN_FALSE; - } - - // Only equals and not equals here, unorderable type - const int cmp = self->cppobj->compare(*other->cppobj); - switch (op) { - case Py_EQ: - c = (cmp == 0); - break; - case Py_NE: - c = (cmp != 0); - break; - case Py_GT: - c = (cmp > 0); - break; - case Py_GE: - c = (cmp >= 0); - break; - case Py_LT: - c = (cmp < 0); - break; - case Py_LE: - c = (cmp <= 0); - break; - default: - PyErr_SetString(PyExc_IndexError, - "Unhandled rich comparison operator for TSIG"); - return (NULL); - } - if (c) { - Py_RETURN_TRUE; - } else { - Py_RETURN_FALSE; - } -} -} // end of unnamed namespace - -namespace isc { -namespace dns { -namespace python { -// This defines the complete type for reflection in python and -// parsing of PyObject* to s_TSIG -// Most of the functions are not actually implemented and NULL here. -PyTypeObject tsig_type = { - PyVarObject_HEAD_INIT(NULL, 0) - "pydnspp.TSIG", - sizeof(s_TSIG), // tp_basicsize - 0, // tp_itemsize - reinterpret_cast(TSIG_destroy), // tp_dealloc - NULL, // tp_print - NULL, // tp_getattr - NULL, // tp_setattr - NULL, // tp_reserved - NULL, // tp_repr - NULL, // tp_as_number - NULL, // tp_as_sequence - NULL, // tp_as_mapping - NULL, // tp_hash - NULL, // tp_call - TSIG_str, // tp_str - NULL, // tp_getattro - NULL, // tp_setattro - NULL, // tp_as_buffer - Py_TPFLAGS_DEFAULT, // tp_flags - "The TSIG class objects represents the TSIG RDATA as defined in RFC2845.", - NULL, // tp_traverse - NULL, // tp_clear - reinterpret_cast(TSIG_richcmp), // tp_richcompare - 0, // tp_weaklistoffset - NULL, // tp_iter - NULL, // tp_iternext - TSIG_methods, // tp_methods - NULL, // tp_members - NULL, // tp_getset - // At the moment, we leave tp_base NULL as we won't use this class - // in a polymorphic way for our immediate need. - NULL, // tp_base - NULL, // tp_dict - NULL, // tp_descr_get - NULL, // tp_descr_set - 0, // tp_dictoffset - reinterpret_cast(TSIG_init), // tp_init - NULL, // tp_alloc - PyType_GenericNew, // tp_new - NULL, // tp_free - NULL, // tp_is_gc - NULL, // tp_bases - NULL, // tp_mro - NULL, // tp_cache - NULL, // tp_subclasses - NULL, // tp_weaklist - NULL, // tp_del - 0 // tp_version_tag -}; - -PyObject* -createTSIGObject(const any::TSIG& source) { - TSIGContainer container(PyObject_New(s_TSIG, &tsig_type)); - container.set(new any::TSIG(source)); - return (container.release()); -} - -bool -PyTSIG_Check(PyObject* obj) { - if (obj == NULL) { - isc_throw(PyCPPWrapperException, "obj argument NULL in typecheck"); - } - return (PyObject_TypeCheck(obj, &tsig_type)); -} - -const any::TSIG& -PyTSIG_ToTSIG(const PyObject* tsig_obj) { - if (tsig_obj == NULL) { - isc_throw(PyCPPWrapperException, - "obj argument NULL in TSIG PyObject conversion"); - } - const s_TSIG* tsig = static_cast(tsig_obj); - return (*tsig->cppobj); -} - -} // namespace python -} // namespace dns -} // namespace isc diff --git a/src/lib/dns/python/tsig_rdata_python.h b/src/lib/dns/python/tsig_rdata_python.h deleted file mode 100644 index 85dd3660cf..0000000000 --- a/src/lib/dns/python/tsig_rdata_python.h +++ /dev/null @@ -1,68 +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. - -#ifndef PYTHON_TSIG_H -#define PYTHON_TSIG_H 1 - -#include - -namespace isc { -namespace dns { -namespace rdata { -namespace any { -class TSIG; -} -} - -namespace python { - -extern PyTypeObject tsig_type; - -/// This is A simple shortcut to create a python TSIG object (in the -/// form of a pointer to PyObject) with minimal exception safety. -/// On success, it returns a valid pointer to PyObject with a reference -/// counter of 1; if something goes wrong it throws an exception (it never -/// returns a NULL pointer). -/// This function is expected to be called with in a try block -/// followed by necessary setup for python exception. -PyObject* createTSIGObject(const rdata::any::TSIG& source); - -/// \brief Checks if the given python object is a TSIG object -/// -/// \exception PyCPPWrapperException if obj is NULL -/// -/// \param obj The object to check the type of -/// \return true if the object is of type TSIG, false otherwise -bool PyTSIG_Check(PyObject* obj); - -/// \brief Returns a reference to the TSIG object contained within the given -/// Python object. -/// -/// \note The given object MUST be of type TSIG; this can be checked with -/// either the right call to ParseTuple("O!"), or with PyTSIG_Check() -/// -/// \note This is not a copy; if the TSIG is needed when the PyObject -/// may be destroyed, the caller must copy it itself. -/// -/// \param tsig_obj The tsig object to convert -const rdata::any::TSIG& PyTSIG_ToTSIG(const PyObject* tsig_obj); - -} // namespace python -} // namespace dns -} // namespace isc -#endif // PYTHON_TSIG_H - -// Local Variables: -// mode: c++ -// End: diff --git a/src/lib/dns/python/tsigerror_python.cc b/src/lib/dns/python/tsigerror_python.cc deleted file mode 100644 index 7a0217e3a1..0000000000 --- a/src/lib/dns/python/tsigerror_python.cc +++ /dev/null @@ -1,291 +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. - -#include - -#include -#include - -#include - -#include - -#include "pydnspp_common.h" -#include "rcode_python.h" -#include "tsigerror_python.h" - -using namespace std; -using namespace isc::util::python; -using namespace isc::dns; -using namespace isc::dns::python; - -// For each class, we need a struct, a helper functions (init, destroy, -// and static wrappers around the methods we export), a list of methods, -// and a type description - -// Import pydoc text -#include "tsigerror_python_inc.cc" - -namespace { -// The s_* Class simply covers one instantiation of the object -class s_TSIGError : public PyObject { -public: - s_TSIGError() : cppobj(NULL) {}; - const TSIGError* cppobj; -}; - -// Shortcut type which would be convenient for adding class variables safely. -typedef CPPPyObjectContainer TSIGErrorContainer; - -// -// We declare the functions here, the definitions are below -// the type definition of the object, since both can use the other -// - -// General creation and destruction -int TSIGError_init(s_TSIGError* self, PyObject* args); -void TSIGError_destroy(s_TSIGError* self); - -// These are the functions we export -PyObject* TSIGError_getCode(const s_TSIGError* const self); -PyObject* TSIGError_toText(const s_TSIGError* const self); -PyObject* TSIGError_toRcode(const s_TSIGError* const self); -PyObject* TSIGError_str(PyObject* self); -PyObject* TSIGError_richcmp(const s_TSIGError* const self, - const s_TSIGError* const other, int op); - -// These are the functions we export -// For a minimal support, we don't need them. - -// This list contains the actual set of functions we have in -// python. Each entry has -// 1. Python method name -// 2. Our static function here -// 3. Argument type -// 4. Documentation -PyMethodDef TSIGError_methods[] = { - { "get_code", reinterpret_cast(TSIGError_getCode), - METH_NOARGS, - TSIGError_getCode_doc }, - { "to_text", reinterpret_cast(TSIGError_toText), METH_NOARGS, - TSIGError_toText_doc }, - { "to_rcode", reinterpret_cast(TSIGError_toRcode), - METH_NOARGS, - TSIGError_toRcode_doc }, - { NULL, NULL, 0, NULL } -}; - -int -TSIGError_init(s_TSIGError* self, PyObject* args) { - try { - // Constructor from the code value - long code = 0; - if (PyArg_ParseTuple(args, "l", &code)) { - if (code < 0 || code > 0xffff) { - PyErr_SetString(PyExc_ValueError, "TSIG error out of range"); - return (-1); - } - self->cppobj = new TSIGError(code); - return (0); - } - - // Constructor from Rcode - PyErr_Clear(); - PyObject* py_rcode; - if (PyArg_ParseTuple(args, "O!", &rcode_type, &py_rcode)) { - self->cppobj = new TSIGError(PyRcode_ToRcode(py_rcode)); - return (0); - } - } catch (const isc::OutOfRange& ex) { - const string ex_what = "Failed to construct TSIGError object: " + - string(ex.what()); - PyErr_SetString(PyExc_ValueError, ex_what.c_str()); - return (-1); - } catch (const exception& ex) { - const string ex_what = "Failed to construct TSIGError object: " + - string(ex.what()); - PyErr_SetString(po_IscException, ex_what.c_str()); - return (-1); - } catch (...) { - PyErr_SetString(po_IscException, - "Unexpected exception in constructing TSIGError"); - return (-1); - } - - PyErr_SetString(PyExc_TypeError, - "Invalid arguments to TSIGError constructor"); - - return (-1); -} - -void -TSIGError_destroy(s_TSIGError* const self) { - delete self->cppobj; - self->cppobj = NULL; - Py_TYPE(self)->tp_free(self); -} - -PyObject* -TSIGError_getCode(const s_TSIGError* const self) { - return (Py_BuildValue("I", self->cppobj->getCode())); -} - -PyObject* -TSIGError_toText(const s_TSIGError* const self) { - try { - // toText() could throw, so we need to catch any exceptions below. - return (Py_BuildValue("s", self->cppobj->toText().c_str())); - } catch (const exception& ex) { - const string ex_what = - "Failed to convert TSIGError object to text: " + - string(ex.what()); - PyErr_SetString(po_IscException, ex_what.c_str()); - } catch (...) { - PyErr_SetString(PyExc_SystemError, "Unexpected failure in " - "converting TSIGError object to text"); - } - return (NULL); -} - -PyObject* -TSIGError_str(PyObject* self) { - // Simply call the to_text method we already defined - return (PyObject_CallMethod(self, const_cast("to_text"), - const_cast(""))); -} - -PyObject* -TSIGError_toRcode(const s_TSIGError* const self) { - try { - return (createRcodeObject(self->cppobj->toRcode())); - } catch (const exception& ex) { - const string ex_what = - "Failed to convert TSIGError to Rcode: " + string(ex.what()); - PyErr_SetString(po_IscException, ex_what.c_str()); - } catch (...) { - PyErr_SetString(PyExc_SystemError, "Unexpected failure in " - "converting TSIGError to Rcode"); - } - return (NULL); -} - -PyObject* -TSIGError_richcmp(const s_TSIGError* const self, - const s_TSIGError* const other, - const int op) -{ - bool c = false; - - // Check for null and if the types match. If different type, - // simply return False - if (other == NULL || (self->ob_type != other->ob_type)) { - Py_RETURN_FALSE; - } - - // Only equals and not equals here, unorderable type - switch (op) { - case Py_LT: - PyErr_SetString(PyExc_TypeError, "Unorderable type; TSIGError"); - return (NULL); - case Py_LE: - PyErr_SetString(PyExc_TypeError, "Unorderable type; TSIGError"); - return (NULL); - case Py_EQ: - c = (*self->cppobj == *other->cppobj); - break; - case Py_NE: - c = (*self->cppobj != *other->cppobj); - break; - case Py_GT: - PyErr_SetString(PyExc_TypeError, "Unorderable type; TSIGError"); - return (NULL); - case Py_GE: - PyErr_SetString(PyExc_TypeError, "Unorderable type; TSIGError"); - return (NULL); - } - if (c) { - Py_RETURN_TRUE; - } else { - Py_RETURN_FALSE; - } -} -} // end of unnamed namespace - -namespace isc { -namespace dns { -namespace python { -// This defines the complete type for reflection in python and -// parsing of PyObject* to s_TSIGError -// Most of the functions are not actually implemented and NULL here. -PyTypeObject tsigerror_type = { - PyVarObject_HEAD_INIT(NULL, 0) - "pydnspp.TSIGError", - sizeof(s_TSIGError), // tp_basicsize - 0, // tp_itemsize - reinterpret_cast(TSIGError_destroy), // tp_dealloc - NULL, // tp_print - NULL, // tp_getattr - NULL, // tp_setattr - NULL, // tp_reserved - NULL, // tp_repr - NULL, // tp_as_number - NULL, // tp_as_sequence - NULL, // tp_as_mapping - NULL, // tp_hash - NULL, // tp_call - // THIS MAY HAVE TO BE CHANGED TO NULL: - TSIGError_str, // tp_str - NULL, // tp_getattro - NULL, // tp_setattro - NULL, // tp_as_buffer - Py_TPFLAGS_DEFAULT, // tp_flags - TSIGError_doc, - NULL, // tp_traverse - NULL, // tp_clear - // THIS MAY HAVE TO BE CHANGED TO NULL: - reinterpret_cast(TSIGError_richcmp), // tp_richcompare - 0, // tp_weaklistoffset - NULL, // tp_iter - NULL, // tp_iternext - TSIGError_methods, // tp_methods - NULL, // tp_members - NULL, // tp_getset - NULL, // tp_base - NULL, // tp_dict - NULL, // tp_descr_get - NULL, // tp_descr_set - 0, // tp_dictoffset - reinterpret_cast(TSIGError_init), // tp_init - NULL, // tp_alloc - PyType_GenericNew, // tp_new - NULL, // tp_free - NULL, // tp_is_gc - NULL, // tp_bases - NULL, // tp_mro - NULL, // tp_cache - NULL, // tp_subclasses - NULL, // tp_weaklist - NULL, // tp_del - 0 // tp_version_tag -}; - -PyObject* -createTSIGErrorObject(const TSIGError& source) { - TSIGErrorContainer container(PyObject_New(s_TSIGError, &tsigerror_type)); - container.set(new TSIGError(source)); - return (container.release()); -} -} // namespace python -} // namespace dns -} // namespace isc diff --git a/src/lib/dns/python/tsigerror_python.h b/src/lib/dns/python/tsigerror_python.h deleted file mode 100644 index 6258ab3d8e..0000000000 --- a/src/lib/dns/python/tsigerror_python.h +++ /dev/null @@ -1,44 +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. - -#ifndef PYTHON_TSIGERROR_H -#define PYTHON_TSIGERROR_H 1 - -#include - -namespace isc { -namespace dns { -class TSIGError; - -namespace python { - -extern PyTypeObject tsigerror_type; - -/// This is A simple shortcut to create a python TSIGError object (in the -/// form of a pointer to PyObject) with minimal exception safety. -/// On success, it returns a valid pointer to PyObject with a reference -/// counter of 1; if something goes wrong it throws an exception (it never -/// returns a NULL pointer). -/// This function is expected to be called with in a try block -/// followed by necessary setup for python exception. -PyObject* createTSIGErrorObject(const TSIGError& source); - -} // namespace python -} // namespace dns -} // namespace isc -#endif // PYTHON_TSIGERROR_H - -// Local Variables: -// mode: c++ -// End: diff --git a/src/lib/dns/python/tsigerror_python_inc.cc b/src/lib/dns/python/tsigerror_python_inc.cc deleted file mode 100644 index a98a9b0e0f..0000000000 --- a/src/lib/dns/python/tsigerror_python_inc.cc +++ /dev/null @@ -1,97 +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. - -namespace { -const char* const TSIGError_doc = "\n\ -TSIG errors.\n\ -\n\ -\n\ -The TSIGError class objects represent standard errors related to TSIG\n\ -protocol operations as defined in related specifications, mainly in\n\ -RFC2845.\n\ -\n\ -TSIGError(error_code)\n\ -\n\ -Constructor from the code value.\n\ -\n\ -Exceptions:\n\ - None: \n\ -\n\ -Parameters:\n\ - error_code: The underlying 16-bit error code value of the TSIGError.\n\ -\n\ -TSIGError(rcode)\n\ -\n\ -Constructor from Rcode.\n\ -\n\ -As defined in RFC2845, error code values from 0 to 15 (inclusive) are\n\ -derived from the DNS RCODEs, which are represented via the Rcode class\n\ -in this library. This constructor works as a converter from these\n\ -RCODEs to corresponding TSIGError objects.\n\ -\n\ -Exceptions:\n\ - ValueError: Given rcode is not convertible to TSIGErrors.\n\ -\n\ -Parameters:\n\ - rcode: the Rcode from which the TSIGError should be derived.\n\ -\n\ -"; -const char* const TSIGError_getCode_doc = "get_code() -> integer\n\ -\n\ -Returns the TSIGCode error code value.\n\ -\n\ -Exceptions:\n\ - None: \n\ -\n\ -Return Value(s):\n\ - The underlying code value corresponding to the TSIGError.\n\ -"; -const char* const TSIGError_toText_doc = "to_text() -> string\n\ -\n\ -Convert the TSIGError to a string.\n\ -\n\ -For codes derived from RCODEs up to 15, this method returns the same\n\ -string as Rcode.to_text() for the corresponding code. For other pre-\n\ -defined code values (see TSIGError.CodeValue), this method returns a\n\ -string representation of the \"mnemonic' used for the enum and\n\ -constant objects as defined in RFC2845. For example, the string for\n\ -code value 16 is \"BADSIG\", etc. For other code values it returns a\n\ -string representation of the decimal number of the value, e.g. \"32\",\n\ -\"100\", etc.\n\ -\n\ -Exceptions:\n\ - None\n\ -\n\ -Return Value(s):\n\ - A string representation of the TSIGError.\n\ -"; -const char* const TSIGError_toRcode_doc = "to_rcode() -> Rcode\n\ -\n\ -Convert the TSIGError to a Rcode.\n\ -\n\ -This method returns an Rcode object that is corresponding to the TSIG\n\ -error. The returned Rcode is expected to be used by a verifying server\n\ -to specify the RCODE of a response when TSIG verification fails.\n\ -\n\ -Specifically, this method returns Rcode.NOTAUTH() for the TSIG\n\ -specific errors, BADSIG, BADKEY, BADTIME, as described in RFC2845. For\n\ -errors derived from the standard Rcode (code 0-15), it returns the\n\ -corresponding Rcode. For others, this method returns Rcode.SERVFAIL()\n\ -as a last resort.\n\ -\n\ -Exceptions:\n\ - None: \n\ -\n\ -"; -} diff --git a/src/lib/dns/python/tsigkey_python.cc b/src/lib/dns/python/tsigkey_python.cc deleted file mode 100644 index bcab59ce86..0000000000 --- a/src/lib/dns/python/tsigkey_python.cc +++ /dev/null @@ -1,473 +0,0 @@ -// Copyright (C) 2010 Internet Systems Consortium, Inc. ("ISC") -// -// Permission to use, copy, modify, and/or distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -// PERFORMANCE OF THIS SOFTWARE. - -#include - -#include - -#include - -#include -#include -#include - -#include "pydnspp_common.h" -#include "name_python.h" -#include "tsigkey_python.h" - -using namespace std; -using namespace isc::util::python; -using namespace isc::dns; -using namespace isc::dns::python; - -// For each class, we need a struct, a helper functions (init, destroy, -// and static wrappers around the methods we export), a list of methods, -// and a type description - -// -// TSIGKey -// - -namespace { -// The s_* Class simply covers one instantiation of the object -class s_TSIGKey : public PyObject { -public: - s_TSIGKey() : cppobj(NULL) {}; - TSIGKey* cppobj; -}; - -// -// We declare the functions here, the definitions are below -// the type definition of the object, since both can use the other -// - -// General creation and destruction -int TSIGKey_init(s_TSIGKey* self, PyObject* args); -void TSIGKey_destroy(s_TSIGKey* self); - -// These are the functions we export -// This is a second version of toText, we need one where the argument -// is a PyObject*, for the str() function in python. -PyObject* TSIGKey_getKeyName(const s_TSIGKey* self); -PyObject* TSIGKey_getAlgorithmName(const s_TSIGKey* self); -PyObject* TSIGKey_getSecret(const s_TSIGKey* self); -PyObject* TSIGKey_toText(const s_TSIGKey* self); - -// This list contains the actual set of functions we have in -// python. Each entry has -// 1. Python method name -// 2. Our static function here -// 3. Argument type -// 4. Documentation -PyMethodDef TSIGKey_methods[] = { - { "get_key_name", - reinterpret_cast(TSIGKey_getKeyName), METH_NOARGS, - "Return the key name." }, - { "get_algorithm_name", - reinterpret_cast(TSIGKey_getAlgorithmName), METH_NOARGS, - "Return the algorithm name." }, - { "get_secret", - reinterpret_cast(TSIGKey_getSecret), METH_NOARGS, - "Return the value of the TSIG secret." }, - { "to_text", reinterpret_cast(TSIGKey_toText), METH_NOARGS, - "Returns the string representation (name:secret:algorithm)" }, - { NULL, NULL, 0, NULL } -}; - -int -TSIGKey_init(s_TSIGKey* self, PyObject* args) { - try { - const char* str; - if (PyArg_ParseTuple(args, "s", &str)) { - self->cppobj = new TSIGKey(str); - return (0); - } - - PyErr_Clear(); - const PyObject* key_name; - const PyObject* algorithm_name; - PyObject* bytes_obj; - const char* secret; - Py_ssize_t secret_len; - if (PyArg_ParseTuple(args, "O!O!O", &name_type, &key_name, - &name_type, &algorithm_name, &bytes_obj) && - PyObject_AsCharBuffer(bytes_obj, &secret, &secret_len) == 0) { - if (secret_len == 0) { - secret = NULL; - } - self->cppobj = new TSIGKey(PyName_ToName(key_name), - PyName_ToName(algorithm_name), - secret, secret_len); - return (0); - } - } catch (const isc::InvalidParameter& ex) { - PyErr_SetString(po_InvalidParameter, ex.what()); - return (-1); - } catch (...) { - PyErr_SetString(po_IscException, "Unexpected exception"); - return (-1); - } - - PyErr_Clear(); - PyErr_SetString(PyExc_TypeError, - "Invalid arguments to TSIGKey constructor"); - - return (-1); -} - -void -TSIGKey_destroy(s_TSIGKey* const self) { - delete self->cppobj; - self->cppobj = NULL; - Py_TYPE(self)->tp_free(self); -} - -PyObject* -TSIGKey_getKeyName(const s_TSIGKey* const self) { - try { - return (createNameObject(self->cppobj->getKeyName())); - } catch (const exception& ex) { - const string ex_what = - "Failed to get key name of TSIGKey: " + string(ex.what()); - PyErr_SetString(po_IscException, ex_what.c_str()); - } catch (...) { - PyErr_SetString(PyExc_SystemError, "Unexpected failure in " - "getting key name of TSIGKey"); - } - return (NULL); -} - -PyObject* -TSIGKey_getAlgorithmName(const s_TSIGKey* const self) { - try { - return (createNameObject(self->cppobj->getAlgorithmName())); - } catch (const exception& ex) { - const string ex_what = - "Failed to get algorithm name of TSIGKey: " + string(ex.what()); - PyErr_SetString(po_IscException, ex_what.c_str()); - } catch (...) { - PyErr_SetString(PyExc_SystemError, "Unexpected failure in " - "getting algorithm name of TSIGKey"); - } - return (NULL); -} - -PyObject* -TSIGKey_getSecret(const s_TSIGKey* const self) { - return (Py_BuildValue("y#", self->cppobj->getSecret(), - self->cppobj->getSecretLength())); -} - -PyObject* -TSIGKey_toText(const s_TSIGKey* self) { - return (Py_BuildValue("s", self->cppobj->toText().c_str())); -} -} // end of unnamed namespace - -namespace isc { -namespace dns { -namespace python { -// This defines the complete type for reflection in python and -// parsing of PyObject* to s_EDNS -// Most of the functions are not actually implemented and NULL here. -PyTypeObject tsigkey_type = { - PyVarObject_HEAD_INIT(NULL, 0) - "pydnspp.TSIGKey", - sizeof(s_TSIGKey), // tp_basicsize - 0, // tp_itemsize - (destructor)TSIGKey_destroy, // tp_dealloc - NULL, // tp_print - NULL, // tp_getattr - NULL, // tp_setattr - NULL, // tp_reserved - NULL, // tp_repr - NULL, // tp_as_number - NULL, // tp_as_sequence - NULL, // tp_as_mapping - NULL, // tp_hash - NULL, // tp_call - NULL, // tp_str - NULL, // tp_getattro - NULL, // tp_setattro - NULL, // tp_as_buffer - Py_TPFLAGS_DEFAULT, // tp_flags - "The TSIGKey class holds a TSIG key along with some related attributes as " - "defined in RFC2845.", - NULL, // tp_traverse - NULL, // tp_clear - NULL, // tp_richcompare - 0, // tp_weaklistoffset - NULL, // tp_iter - NULL, // tp_iternext - TSIGKey_methods, // tp_methods - NULL, // tp_members - NULL, // tp_getset - NULL, // tp_base - NULL, // tp_dict - NULL, // tp_descr_get - NULL, // tp_descr_set - 0, // tp_dictoffset - (initproc)TSIGKey_init, // tp_init - NULL, // tp_alloc - PyType_GenericNew, // tp_new - NULL, // tp_free - NULL, // tp_is_gc - NULL, // tp_bases - NULL, // tp_mro - NULL, // tp_cache - NULL, // tp_subclasses - NULL, // tp_weaklist - NULL, // tp_del - 0 // tp_version_tag -}; - -bool -PyTSIGKey_Check(PyObject* obj) { - if (obj == NULL) { - isc_throw(PyCPPWrapperException, "obj argument NULL in typecheck"); - } - return (PyObject_TypeCheck(obj, &tsigkey_type)); -} - -const TSIGKey& -PyTSIGKey_ToTSIGKey(const PyObject* tsigkey_obj) { - const s_TSIGKey* tsigkey = static_cast(tsigkey_obj); - return (*tsigkey->cppobj); -} - -} // namespace python -} // namespace dns -} // namespace isc -// -// End of TSIGKey -// - -// -// TSIGKeyRing -// - -namespace { -// The s_* Class simply covers one instantiation of the object -class s_TSIGKeyRing : public PyObject { -public: - s_TSIGKeyRing() : cppobj(NULL) {}; - TSIGKeyRing* cppobj; -}; - -// -// We declare the functions here, the definitions are below -// the type definition of the object, since both can use the other -// - -int TSIGKeyRing_init(s_TSIGKeyRing* self, PyObject* args); -void TSIGKeyRing_destroy(s_TSIGKeyRing* self); - -PyObject* TSIGKeyRing_size(const s_TSIGKeyRing* self); -PyObject* TSIGKeyRing_add(const s_TSIGKeyRing* self, PyObject* args); -PyObject* TSIGKeyRing_remove(const s_TSIGKeyRing* self, PyObject* args); -PyObject* TSIGKeyRing_find(const s_TSIGKeyRing* self, PyObject* args); - -PyMethodDef TSIGKeyRing_methods[] = { - { "size", reinterpret_cast(TSIGKeyRing_size), METH_NOARGS, - "Return the number of keys stored in the TSIGKeyRing." }, - { "add", reinterpret_cast(TSIGKeyRing_add), METH_VARARGS, - "Add a TSIGKey to the TSIGKeyRing." }, - { "remove", reinterpret_cast(TSIGKeyRing_remove), - METH_VARARGS, - "Remove a TSIGKey for the given name from the TSIGKeyRing." }, - { "find", reinterpret_cast(TSIGKeyRing_find), METH_VARARGS, - "Find a TSIGKey for the given name in the TSIGKeyRing. Optional " - "second argument is an algorithm, in which case it only returns " - "a key if both match.\n" - "It returns a tuple of (result_code, key)." }, - { NULL, NULL, 0, NULL } -}; - -int -TSIGKeyRing_init(s_TSIGKeyRing* self, PyObject* args) { - if (!PyArg_ParseTuple(args, "")) { - PyErr_Clear(); - PyErr_SetString(PyExc_TypeError, - "Invalid arguments to TSIGKeyRing constructor"); - return (-1); - } - - self->cppobj = new(nothrow) TSIGKeyRing(); - if (self->cppobj == NULL) { - PyErr_SetString(po_IscException, "Allocating TSIGKeyRing failed"); - return (-1); - } - - return (0); -} - -void -TSIGKeyRing_destroy(s_TSIGKeyRing* self) { - delete self->cppobj; - self->cppobj = NULL; - Py_TYPE(self)->tp_free(self); -} - -PyObject* -TSIGKeyRing_size(const s_TSIGKeyRing* const self) { - return (Py_BuildValue("I", self->cppobj->size())); -} - -PyObject* -TSIGKeyRing_add(const s_TSIGKeyRing* const self, PyObject* args) { - s_TSIGKey* tsigkey; - - if (PyArg_ParseTuple(args, "O!", &tsigkey_type, &tsigkey)) { - try { - const TSIGKeyRing::Result result = - self->cppobj->add(*tsigkey->cppobj); - return (Py_BuildValue("I", result)); - } catch (...) { - PyErr_SetString(po_IscException, "Unexpected exception"); - return (NULL); - } - } - - PyErr_Clear(); - PyErr_SetString(PyExc_TypeError, "Invalid arguments to TSIGKeyRing.add"); - - return (NULL); -} - -PyObject* -TSIGKeyRing_remove(const s_TSIGKeyRing* self, PyObject* args) { - PyObject* key_name; - - if (PyArg_ParseTuple(args, "O!", &name_type, &key_name)) { - const TSIGKeyRing::Result result = - self->cppobj->remove(PyName_ToName(key_name)); - return (Py_BuildValue("I", result)); - } - - PyErr_Clear(); - PyErr_SetString(PyExc_TypeError, "Invalid arguments to TSIGKeyRing.add"); - - return (NULL); -} - -PyObject* -TSIGKeyRing_find(const s_TSIGKeyRing* self, PyObject* args) { - PyObject* key_name; - PyObject* algorithm_name = NULL; - - if (PyArg_ParseTuple(args, "O!|O!", &name_type, &key_name, - &name_type, &algorithm_name)) { - // Can't init TSIGKeyRing::FindResult without actual result, - // so use ternary operator - TSIGKeyRing::FindResult result = (algorithm_name == NULL) ? - self->cppobj->find(PyName_ToName(key_name)) : - self->cppobj->find(PyName_ToName(key_name), - PyName_ToName(algorithm_name)); - if (result.key != NULL) { - s_TSIGKey* key = PyObject_New(s_TSIGKey, &tsigkey_type); - if (key == NULL) { - return (NULL); - } - key->cppobj = new(nothrow) TSIGKey(*result.key); - if (key->cppobj == NULL) { - Py_DECREF(key); - PyErr_SetString(po_IscException, - "Allocating TSIGKey object failed"); - return (NULL); - } - return (Py_BuildValue("IN", result.code, key)); - } else { - return (Py_BuildValue("Is", result.code, NULL)); - } - } - - return (NULL); -} -} // end of unnamed namespace - -namespace isc { -namespace dns { -namespace python { -PyTypeObject tsigkeyring_type = { - PyVarObject_HEAD_INIT(NULL, 0) - "pydnspp.TSIGKeyRing", - sizeof(s_TSIGKeyRing), // tp_basicsize - 0, // tp_itemsize - (destructor)TSIGKeyRing_destroy, // tp_dealloc - NULL, // tp_print - NULL, // tp_getattr - NULL, // tp_setattr - NULL, // tp_reserved - NULL, // tp_repr - NULL, // tp_as_number - NULL, // tp_as_sequence - NULL, // tp_as_mapping - NULL, // tp_hash - NULL, // tp_call - NULL, // tp_str - NULL, // tp_getattro - NULL, // tp_setattro - NULL, // tp_as_buffer - Py_TPFLAGS_DEFAULT, // tp_flags - "A simple repository of a set of TSIGKey objects.", - NULL, // tp_traverse - NULL, // tp_clear - NULL, // tp_richcompare - 0, // tp_weaklistoffset - NULL, // tp_iter - NULL, // tp_iternext - TSIGKeyRing_methods, // tp_methods - NULL, // tp_members - NULL, // tp_getset - NULL, // tp_base - NULL, // tp_dict - NULL, // tp_descr_get - NULL, // tp_descr_set - 0, // tp_dictoffset - (initproc)TSIGKeyRing_init, // tp_init - NULL, // tp_alloc - PyType_GenericNew, // tp_new - NULL, // tp_free - NULL, // tp_is_gc - NULL, // tp_bases - NULL, // tp_mro - NULL, // tp_cache - NULL, // tp_subclasses - NULL, // tp_weaklist - NULL, // tp_del - 0 // tp_version_tag -}; - -bool -PyTSIGKeyRing_Check(PyObject* obj) { - if (obj == NULL) { - isc_throw(PyCPPWrapperException, "obj argument NULL in typecheck"); - } - return (PyObject_TypeCheck(obj, &tsigkeyring_type)); -} - -const TSIGKeyRing& -PyTSIGKeyRing_ToTSIGKeyRing(const PyObject* tsigkeyring_obj) { - if (tsigkeyring_obj == NULL) { - isc_throw(PyCPPWrapperException, - "obj argument NULL in TSIGKeyRing PyObject conversion"); - } - const s_TSIGKeyRing* tsigkeyring = - static_cast(tsigkeyring_obj); - return (*tsigkeyring->cppobj); -} - -} // namespace python -} // namespace dns -} // namespace isc diff --git a/src/lib/dns/python/tsigkey_python.h b/src/lib/dns/python/tsigkey_python.h deleted file mode 100644 index ec09e2c2ad..0000000000 --- a/src/lib/dns/python/tsigkey_python.h +++ /dev/null @@ -1,75 +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. - -#ifndef PYTHON_TSIGKEY_H -#define PYTHON_TSIGKEY_H 1 - -#include - -namespace isc { -namespace dns { -class TSIGKey; -class TSIGKeyRing; - -namespace python { - -extern PyTypeObject tsigkey_type; -extern PyTypeObject tsigkeyring_type; - -/// \brief Checks if the given python object is a TSIGKey object -/// -/// \exception PyCPPWrapperException if obj is NULL -/// -/// \param obj The object to check the type of -/// \return true if the object is of type TSIGKey, false otherwise -bool PyTSIGKey_Check(PyObject* obj); - -/// \brief Returns a reference to the TSIGKey object contained within the given -/// Python object. -/// -/// \note The given object MUST be of type TSIGKey; this can be checked with -/// either the right call to ParseTuple("O!"), or with PyTSIGKey_Check() -/// -/// \note This is not a copy; if the TSIGKey is needed when the PyObject -/// may be destroyed, the caller must copy it itself. -/// -/// \param tsigkey_obj The tsigkey object to convert -const TSIGKey& PyTSIGKey_ToTSIGKey(const PyObject* tsigkey_obj); - -/// \brief Checks if the given python object is a TSIGKeyRing object -/// -/// \param obj The object to check the type of -/// \return true if the object is of type TSIGKeyRing, false otherwise -bool PyTSIGKeyRing_Check(PyObject* obj); - -/// \brief Returns a reference to the TSIGKeyRing object contained within the given -/// Python object. -/// -/// \note The given object MUST be of type TSIGKeyRing; this can be checked with -/// either the right call to ParseTuple("O!"), or with PyTSIGKeyRing_Check() -/// -/// \note This is not a copy; if the TSIGKeyRing is needed when the PyObject -/// may be destroyed, the caller must copy it itself. -/// -/// \param tsigkeyring_obj The tsigkeyring object to convert -const TSIGKeyRing& PyTSIGKeyRing_ToTSIGKeyRing(const PyObject* tsigkeyring_obj); - -} // namespace python -} // namespace dns -} // namespace isc -#endif // PYTHON_TSIGKEY_H - -// Local Variables: -// mode: c++ -// End: diff --git a/src/lib/dns/python/tsigrecord_python.cc b/src/lib/dns/python/tsigrecord_python.cc deleted file mode 100644 index c754dd2c82..0000000000 --- a/src/lib/dns/python/tsigrecord_python.cc +++ /dev/null @@ -1,293 +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. - -#include - -#include -#include - -#include - -#include - -#include "pydnspp_common.h" -#include "pydnspp_towire.h" -#include "name_python.h" -#include "tsig_rdata_python.h" -#include "tsigrecord_python.h" - -using namespace std; -using namespace isc::util::python; -using namespace isc::dns; -using namespace isc::dns::python; - -// For each class, we need a struct, a helper functions (init, destroy, -// and static wrappers around the methods we export), a list of methods, -// and a type description - -// -// TSIGRecord -// - -namespace { -// The s_* Class simply covers one instantiation of the object -class s_TSIGRecord : public PyObject { -public: - s_TSIGRecord() : cppobj(NULL) {}; - TSIGRecord* cppobj; -}; - -// Shortcut type which would be convenient for adding class variables safely. -typedef CPPPyObjectContainer TSIGRecordContainer; - -// -// We declare the functions here, the definitions are below -// the type definition of the object, since both can use the other -// - -// General creation and destruction -int TSIGRecord_init(s_TSIGRecord* self, PyObject* args); -void TSIGRecord_destroy(s_TSIGRecord* self); -PyObject* TSIGRecord_toText(const s_TSIGRecord* const self); -PyObject* TSIGRecord_str(PyObject* self); -PyObject* TSIGRecord_toWire(const s_TSIGRecord* self, PyObject* args); -PyObject* TSIGRecord_getName(const s_TSIGRecord* self); -PyObject* TSIGRecord_getLength(const s_TSIGRecord* self); -PyObject* TSIGRecord_getRdata(const s_TSIGRecord* self); - -// These are the functions we export -// For a minimal support, we don't need them. - -// This list contains the actual set of functions we have in -// python. Each entry has -// 1. Python method name -// 2. Our static function here -// 3. Argument type -// 4. Documentation -PyMethodDef TSIGRecord_methods[] = { - { "get_name", reinterpret_cast(TSIGRecord_getName), - METH_NOARGS, - "Return the owner name of the TSIG RR, which is the TSIG key name" }, - { "get_length", reinterpret_cast(TSIGRecord_getLength), - METH_NOARGS, - "Return the length of the TSIG record" }, - { "get_rdata", reinterpret_cast(TSIGRecord_getRdata), - METH_NOARGS, - "Return the RDATA of the TSIG RR" }, - { "to_text", reinterpret_cast(TSIGRecord_toText), METH_NOARGS, - "Returns the text representation" }, - { "to_wire", reinterpret_cast(TSIGRecord_toWire), - METH_VARARGS, - "Converts the TSIGRecord object to wire format.\n" - "The argument can be either a MessageRenderer or an object that " - "implements the sequence interface. If the object is mutable " - "(for instance a bytearray()), the wire data is added in-place.\n" - "If it is not (for instance a bytes() object), a new object is " - "returned" }, - { NULL, NULL, 0, NULL } -}; - -int -TSIGRecord_init(s_TSIGRecord* self, PyObject* args) { - try { - const PyObject* py_name; - const PyObject* py_tsig; - if (PyArg_ParseTuple(args, "O!O!", &name_type, &py_name, - &tsig_type, &py_tsig)) { - self->cppobj = new TSIGRecord(PyName_ToName(py_name), - PyTSIG_ToTSIG(py_tsig)); - return (0); - } - } catch (const exception& ex) { - const string ex_what = "Failed to construct TSIGRecord object: " + - string(ex.what()); - PyErr_SetString(po_IscException, ex_what.c_str()); - return (-1); - } catch (...) { - PyErr_SetString(po_IscException, - "Unexpected exception in constructing TSIGRecord"); - return (-1); - } - - PyErr_SetString(PyExc_TypeError, - "Invalid arguments to TSIGRecord constructor"); - - return (-1); -} - -// This is a template of typical code logic of python object destructor. -// In many cases you can use it without modification, but check that carefully. -void -TSIGRecord_destroy(s_TSIGRecord* const self) { - delete self->cppobj; - self->cppobj = NULL; - Py_TYPE(self)->tp_free(self); -} - -// This should be able to be used without modification as long as the -// underlying C++ class has toText(). -PyObject* -TSIGRecord_toText(const s_TSIGRecord* const self) { - try { - // toText() could throw, so we need to catch any exceptions below. - return (Py_BuildValue("s", self->cppobj->toText().c_str())); - } catch (const exception& ex) { - const string ex_what = - "Failed to convert TSIGRecord object to text: " + - string(ex.what()); - PyErr_SetString(po_IscException, ex_what.c_str()); - } catch (...) { - PyErr_SetString(PyExc_SystemError, "Unexpected failure in " - "converting TSIGRecord object to text"); - } - return (NULL); -} - -PyObject* -TSIGRecord_str(PyObject* self) { - // Simply call the to_text method we already defined - return (PyObject_CallMethod(self, const_cast("to_text"), - const_cast(""))); -} - -PyObject* -TSIGRecord_toWire(const s_TSIGRecord* const self, PyObject* args) { - typedef ToWireCallInt ToWireCall; - PyObject* (*towire_fn)(const s_TSIGRecord* const, PyObject*) = - toWireWrapper; - return (towire_fn(self, args)); -} - -PyObject* -TSIGRecord_getName(const s_TSIGRecord* const self) { - try { - return (createNameObject(self->cppobj->getName())); - } catch (const exception& ex) { - const string ex_what = - "Failed to get TSIGRecord name: " + string(ex.what()); - PyErr_SetString(po_IscException, ex_what.c_str()); - } catch (...) { - PyErr_SetString(PyExc_SystemError, "Unexpected failure in " - "getting TSIGRecord name"); - } - return (NULL); -} - -PyObject* -TSIGRecord_getLength(const s_TSIGRecord* const self) { - return (Py_BuildValue("H", self->cppobj->getLength())); -} - -PyObject* -TSIGRecord_getRdata(const s_TSIGRecord* const self) { - try { - return (createTSIGObject(self->cppobj->getRdata())); - } catch (const exception& ex) { - const string ex_what = - "Failed to get TSIGRecord RDATA: " + string(ex.what()); - PyErr_SetString(po_IscException, ex_what.c_str()); - } catch (...) { - PyErr_SetString(PyExc_SystemError, "Unexpected failure in " - "getting TSIGRecord RDATA"); - } - return (NULL); -} - -} // end of unnamed namespace - -namespace isc { -namespace dns { -namespace python { -// This defines the complete type for reflection in python and -// parsing of PyObject* to s_TSIGRecord -// Most of the functions are not actually implemented and NULL here. -PyTypeObject tsigrecord_type = { - PyVarObject_HEAD_INIT(NULL, 0) - "pydnspp.TSIGRecord", - sizeof(s_TSIGRecord), // tp_basicsize - 0, // tp_itemsize - reinterpret_cast(TSIGRecord_destroy), // tp_dealloc - NULL, // tp_print - NULL, // tp_getattr - NULL, // tp_setattr - NULL, // tp_reserved - NULL, // tp_repr - NULL, // tp_as_number - NULL, // tp_as_sequence - NULL, // tp_as_mapping - NULL, // tp_hash - NULL, // tp_call - TSIGRecord_str, // tp_str - NULL, // tp_getattro - NULL, // tp_setattro - NULL, // tp_as_buffer - Py_TPFLAGS_DEFAULT, // tp_flags - "The TSIGRecord class objects is...(COMPLETE THIS)", - NULL, // tp_traverse - NULL, // tp_clear - NULL, // tp_richcompare - 0, // tp_weaklistoffset - NULL, // tp_iter - NULL, // tp_iternext - TSIGRecord_methods, // tp_methods - NULL, // tp_members - NULL, // tp_getset - NULL, // tp_base - NULL, // tp_dict - NULL, // tp_descr_get - NULL, // tp_descr_set - 0, // tp_dictoffset - reinterpret_cast(TSIGRecord_init), // tp_init - NULL, // tp_alloc - PyType_GenericNew, // tp_new - NULL, // tp_free - NULL, // tp_is_gc - NULL, // tp_bases - NULL, // tp_mro - NULL, // tp_cache - NULL, // tp_subclasses - NULL, // tp_weaklist - NULL, // tp_del - 0 // tp_version_tag -}; - -PyObject* -createTSIGRecordObject(const TSIGRecord& source) { - TSIGRecordContainer container(PyObject_New(s_TSIGRecord, &tsigrecord_type)); - container.set(new TSIGRecord(source)); - return (container.release()); -} - -bool -PyTSIGRecord_Check(PyObject* obj) { - if (obj == NULL) { - isc_throw(PyCPPWrapperException, "obj argument NULL in typecheck"); - } - return (PyObject_TypeCheck(obj, &tsigrecord_type)); -} - -const TSIGRecord& -PyTSIGRecord_ToTSIGRecord(PyObject* tsigrecord_obj) { - if (tsigrecord_obj == NULL) { - isc_throw(PyCPPWrapperException, - "obj argument NULL in TSIGRecord PyObject conversion"); - } - s_TSIGRecord* tsigrecord = static_cast(tsigrecord_obj); - return (*tsigrecord->cppobj); -} - - -} // namespace python -} // namespace dns -} // namespace isc diff --git a/src/lib/dns/python/tsigrecord_python.h b/src/lib/dns/python/tsigrecord_python.h deleted file mode 100644 index ec505f7999..0000000000 --- a/src/lib/dns/python/tsigrecord_python.h +++ /dev/null @@ -1,65 +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. - -#ifndef PYTHON_TSIGRECORD_H -#define PYTHON_TSIGRECORD_H 1 - -#include - -namespace isc { -namespace dns { -class TSIGRecord; - -namespace python { - - -extern PyTypeObject tsigrecord_type; - -/// This is A simple shortcut to create a python TSIGRecord object (in the -/// form of a pointer to PyObject) with minimal exception safety. -/// On success, it returns a valid pointer to PyObject with a reference -/// counter of 1; if something goes wrong it throws an exception (it never -/// returns a NULL pointer). -/// This function is expected to be called with in a try block -/// followed by necessary setup for python exception. -PyObject* createTSIGRecordObject(const TSIGRecord& source); - -/// \brief Checks if the given python object is a TSIGRecord object -/// -/// \exception PyCPPWrapperException if obj is NULL -/// -/// \param obj The object to check the type of -/// \return true if the object is of type TSIGRecord, false otherwise -bool PyTSIGRecord_Check(PyObject* obj); - -/// \brief Returns a reference to the TSIGRecord object contained within the given -/// Python object. -/// -/// \note The given object MUST be of type TSIGRecord; this can be checked with -/// either the right call to ParseTuple("O!"), or with PyTSIGRecord_Check() -/// -/// \note This is not a copy; if the TSIGRecord is needed when the PyObject -/// may be destroyed, the caller must copy it itself. -/// -/// \param rrtype_obj The rrtype object to convert -const TSIGRecord& PyTSIGRecord_ToTSIGRecord(PyObject* tsigrecord_obj); - -} // namespace python -} // namespace dns -} // namespace isc -#endif // PYTHON_TSIGRECORD_H - -// Local Variables: -// mode: c++ -// End: diff --git a/src/lib/dns/python/zone_checker_python.cc b/src/lib/dns/python/zone_checker_python.cc deleted file mode 100644 index eaad72d274..0000000000 --- a/src/lib/dns/python/zone_checker_python.cc +++ /dev/null @@ -1,229 +0,0 @@ -// 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 - -#include - -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include - -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 { - -// Place the exception class in a named namespace to avoid weird run time -// failure with clang++. See isc.log Python wrapper. -namespace clang_unnamed_namespace_workaround { -// 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 { -}; -} -using namespace clang_unnamed_namespace_workaround; - -namespace { -// 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 diff --git a/src/lib/dns/python/zone_checker_python.h b/src/lib/dns/python/zone_checker_python.h deleted file mode 100644 index 63168fdb19..0000000000 --- a/src/lib/dns/python/zone_checker_python.h +++ /dev/null @@ -1,35 +0,0 @@ -// 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 - -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: diff --git a/src/lib/dns/python/zone_checker_python_inc.cc b/src/lib/dns/python/zone_checker_python_inc.cc deleted file mode 100644 index c99042e66e..0000000000 --- a/src/lib/dns/python/zone_checker_python_inc.cc +++ /dev/null @@ -1,79 +0,0 @@ -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 diff --git a/src/lib/dns/rdataclass.cc b/src/lib/dns/rdataclass.cc new file mode 100644 index 0000000000..53ef6a8c02 --- /dev/null +++ b/src/lib/dns/rdataclass.cc @@ -0,0 +1,6658 @@ +/////////////// +/////////////// +/////////////// THIS FILE IS AUTOMATICALLY GENERATED BY gen-rdatacode.py. +/////////////// DO NOT EDIT! +/////////////// +/////////////// + +// Copyright (C) 2010-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. + +#include +#include +#include + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace std; +using boost::lexical_cast; +using namespace isc::util; +using namespace isc::util::encode; +using namespace isc::dns; +using isc::dns::rdata::generic::detail::createNameFromLexer; + +namespace isc { +namespace dns { +namespace rdata { +namespace any { + +// straightforward representation of TSIG RDATA fields +struct TSIGImpl { + TSIGImpl(const Name& algorithm, uint64_t time_signed, uint16_t fudge, + vector& mac, uint16_t original_id, uint16_t error, + vector& other_data) : + algorithm_(algorithm), time_signed_(time_signed), fudge_(fudge), + mac_(mac), original_id_(original_id), error_(error), + other_data_(other_data) + {} + TSIGImpl(const Name& algorithm, uint64_t time_signed, uint16_t fudge, + size_t macsize, const void* mac, uint16_t original_id, + uint16_t error, size_t other_len, const void* other_data) : + algorithm_(algorithm), time_signed_(time_signed), fudge_(fudge), + mac_(static_cast(mac), + static_cast(mac) + macsize), + original_id_(original_id), error_(error), + other_data_(static_cast(other_data), + static_cast(other_data) + other_len) + {} + template + void toWireCommon(Output& output) const; + + const Name algorithm_; + const uint64_t time_signed_; + const uint16_t fudge_; + const vector mac_; + const uint16_t original_id_; + const uint16_t error_; + const vector other_data_; +}; + +// helper function for string and lexer constructors +TSIGImpl* +TSIG::constructFromLexer(MasterLexer& lexer, const Name* origin) { + const Name& algorithm = + createNameFromLexer(lexer, origin ? origin : &Name::ROOT_NAME()); + const Name& canonical_algorithm_name = + (algorithm == TSIGKey::HMACMD5_SHORT_NAME()) ? + TSIGKey::HMACMD5_NAME() : algorithm; + + const string& time_txt = + lexer.getNextToken(MasterToken::STRING).getString(); + uint64_t time_signed; + try { + time_signed = boost::lexical_cast(time_txt); + } catch (const boost::bad_lexical_cast&) { + isc_throw(InvalidRdataText, "Invalid TSIG Time"); + } + if ((time_signed >> 48) != 0) { + isc_throw(InvalidRdataText, "TSIG Time out of range"); + } + + const uint32_t fudge = lexer.getNextToken(MasterToken::NUMBER).getNumber(); + if (fudge > 0xffff) { + isc_throw(InvalidRdataText, "TSIG Fudge out of range"); + } + const uint32_t macsize = + lexer.getNextToken(MasterToken::NUMBER).getNumber(); + if (macsize > 0xffff) { + isc_throw(InvalidRdataText, "TSIG MAC Size out of range"); + } + + const string& mac_txt = (macsize > 0) ? + lexer.getNextToken(MasterToken::STRING).getString() : ""; + vector mac; + decodeBase64(mac_txt, mac); + if (mac.size() != macsize) { + isc_throw(InvalidRdataText, "TSIG MAC Size and data are inconsistent"); + } + + const uint32_t orig_id = + lexer.getNextToken(MasterToken::NUMBER).getNumber(); + if (orig_id > 0xffff) { + isc_throw(InvalidRdataText, "TSIG Original ID out of range"); + } + + const string& error_txt = + lexer.getNextToken(MasterToken::STRING).getString(); + uint32_t error = 0; + // XXX: In the initial implementation we hardcode the mnemonics. + // We'll soon generalize this. + if (error_txt == "NOERROR") { + error = Rcode::NOERROR_CODE; + } else if (error_txt == "BADSIG") { + error = TSIGError::BAD_SIG_CODE; + } else if (error_txt == "BADKEY") { + error = TSIGError::BAD_KEY_CODE; + } else if (error_txt == "BADTIME") { + error = TSIGError::BAD_TIME_CODE; + } else { + /// we cast to uint32_t and range-check, because casting directly to + /// uint16_t will convert negative numbers to large positive numbers + try { + error = boost::lexical_cast(error_txt); + } catch (const boost::bad_lexical_cast&) { + isc_throw(InvalidRdataText, "Invalid TSIG Error"); + } + if (error > 0xffff) { + isc_throw(InvalidRdataText, "TSIG Error out of range"); + } + } + + const uint32_t otherlen = + lexer.getNextToken(MasterToken::NUMBER).getNumber(); + if (otherlen > 0xffff) { + isc_throw(InvalidRdataText, "TSIG Other Len out of range"); + } + const string otherdata_txt = (otherlen > 0) ? + lexer.getNextToken(MasterToken::STRING).getString() : ""; + vector other_data; + decodeBase64(otherdata_txt, other_data); + if (other_data.size() != otherlen) { + isc_throw(InvalidRdataText, + "TSIG Other Data length does not match Other Len"); + } + // RFC2845 says Other Data is "empty unless Error == BADTIME". + // However, we don't enforce that. + + return (new TSIGImpl(canonical_algorithm_name, time_signed, fudge, mac, + orig_id, error, other_data)); +} + +/// \brief Constructor from string. +/// +/// The given string must represent a valid TSIG RDATA. There can be extra +/// space characters at the beginning or end of the text (which are simply +/// ignored), but other extra text, including a new line, will make the +/// construction fail with an exception. +/// +/// \c tsig_str must be formatted as follows: +/// \code