/gen-rdatacode.py
-/rdataclass.cc
-/rdataclass.h
-/rrclass.h
-/rrparamregistry.cc
-/rrtype.h
/s-rdatacode
-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
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
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
$(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 = \
+++ /dev/null
-/rrclass_constants_inc.cc
-/rrtype_constants_inc.cc
-/pydnspp_config.h
+++ /dev/null
-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)
+++ /dev/null
-
-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_<C++-name> (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_<C++ class name>.
-
-Then we declare (but not define!) all methods we will export to
-python. These are named <C++ class name>_<C++ method name>.
-
-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 <lowercase C++ class 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_<c++ class name>, 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.
+++ /dev/null
-
-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)
+++ /dev/null
-// 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 <Python.h>
-
-#include <cassert>
-
-#include <dns/edns.h>
-#include <dns/exceptions.h>
-#include <dns/messagerenderer.h>
-#include <util/python/pycppwrapper_util.h>
-
-#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<s_EDNS, EDNS> 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<PyCFunction>(EDNS_toText), METH_NOARGS,
- "Returns the string representation" },
- { "to_wire", reinterpret_cast<PyCFunction>(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<PyCFunction>(EDNS_getVersion), METH_NOARGS,
- "Returns the version of EDNS." },
- { "get_dnssec_awareness",
- reinterpret_cast<PyCFunction>(EDNS_getDNSSECAwareness), METH_NOARGS,
- "Returns whether the message sender is DNSSEC aware." },
- { "set_dnssec_awareness",
- reinterpret_cast<PyCFunction>(EDNS_setDNSSECAwareness), METH_VARARGS,
- "Specifies whether the sender of the message containing this "
- "EDNS is DNSSEC aware." },
- { "get_udp_size",
- reinterpret_cast<PyCFunction>(EDNS_getUDPSize), METH_NOARGS,
- "Return the maximum buffer size of UDP messages for the sender "
- "of the message." },
- { "set_udp_size",
- reinterpret_cast<PyCFunction>(EDNS_setUDPSize), METH_VARARGS,
- "Specify the maximum buffer size of UDP messages that use this EDNS." },
- { "create_from_rr",
- reinterpret_cast<PyCFunction>(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<char*>("to_text"),
- const_cast<char*>("")));
-}
-
-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<const char*>(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<const s_EDNS*>(edns_obj);
- return (*edns->cppobj);
-}
-
-} // end namespace python
-} // end namespace dns
-} // end namespace isc
+++ /dev/null
-// 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 <Python.h>
-
-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:
+++ /dev/null
-// 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 <Python.h>
-
-#include <exceptions/exceptions.h>
-#include <util/python/pycppwrapper_util.h>
-#include <dns/message.h>
-#include <dns/rcode.h>
-#include <dns/tsig.h>
-#include <dns/exceptions.h>
-#include <dns/messagerenderer.h>
-
-#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<PyCFunction>(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<PyCFunction>(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<PyCFunction>(Message_getQid), METH_NOARGS,
- "Returns the query id" },
- { "set_qid", reinterpret_cast<PyCFunction>(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<PyCFunction>(Message_getRcode), METH_NOARGS,
- "Returns the message Response code (an Rcode object)" },
- { "set_rcode", reinterpret_cast<PyCFunction>(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<PyCFunction>(Message_getOpcode), METH_NOARGS,
- "Returns the message opcode (an Opcode object)" },
- { "set_opcode", reinterpret_cast<PyCFunction>(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<PyCFunction>(Message_getEDNS), METH_NOARGS,
- "Return, if any, the EDNS associated with the message."
- },
- { "set_edns", reinterpret_cast<PyCFunction>(Message_setEDNS), METH_VARARGS,
- "Set EDNS for the message."
- },
- { "get_tsig_record",
- reinterpret_cast<PyCFunction>(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<PyCFunction>(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<PyCFunction>(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<PyCFunction>(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<PyCFunction>(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<PyCFunction>(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<PyCFunction>(Message_toText), METH_NOARGS,
- "Returns the string representation of the message" },
- { "to_wire", reinterpret_cast<PyCFunction>(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<Message::HeaderFlag>(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<Message::HeaderFlag>(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<Message::Section>(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 <typename ItemType, typename CreatorParamType>
-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<ConstQuestionPtr, Question> QuestionInserter;
-typedef SectionInserter<ConstRRsetPtr, AbstractRRset> 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<s_Message*>(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<s_Message*>(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<Message::Section>(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<Message::Section>(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<s_Message*>(pyself);
- int section;
-
- if (!PyArg_ParseTuple(args, "i", §ion)) {
- return (NULL);
- }
- try {
- self->cppobj->clearSection(static_cast<Message::Section>(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<char*>("to_text"),
- const_cast<char*>("")));
-}
-
-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<s_Message*>(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<Message::ParseOptions>(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
+++ /dev/null
-// 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 <Python.h>
-
-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:
+++ /dev/null
-// 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
+++ /dev/null
-// 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 <Python.h>
-
-#include <util/buffer.h>
-
-#include <dns/messagerenderer.h>
-#include <util/python/pycppwrapper_util.h>
-
-#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<PyCFunction>(MessageRenderer_getData), METH_NOARGS,
- "Returns the data as a bytes() object" },
- { "get_length", reinterpret_cast<PyCFunction>(MessageRenderer_getLength), METH_NOARGS,
- "Returns the length of the data" },
- { "is_truncated", reinterpret_cast<PyCFunction>(MessageRenderer_isTruncated), METH_NOARGS,
- "Returns True if the data is truncated" },
- { "get_length_limit", reinterpret_cast<PyCFunction>(MessageRenderer_getLengthLimit), METH_NOARGS,
- "Returns the length limit of the data" },
- { "get_compress_mode", reinterpret_cast<PyCFunction>(MessageRenderer_getCompressMode), METH_NOARGS,
- "Returns the current compression mode" },
- { "set_truncated", reinterpret_cast<PyCFunction>(MessageRenderer_setTruncated), METH_NOARGS,
- "Sets truncated to true" },
- { "set_length_limit", reinterpret_cast<PyCFunction>(MessageRenderer_setLengthLimit), METH_VARARGS,
- "Sets the length limit of the data to the given number" },
- { "set_compress_mode", reinterpret_cast<PyCFunction>(MessageRenderer_setCompressMode), METH_VARARGS,
- "Sets the compression mode of the MessageRenderer" },
- { "clear", reinterpret_cast<PyCFunction>(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<s_MessageRenderer*>(messagerenderer_obj);
- return (*messagerenderer->cppobj);
-}
-
-
-} // namespace python
-} // namespace dns
-} // namespace isc
+++ /dev/null
-// 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 <Python.h>
-
-#include <util/buffer.h>
-
-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:
+++ /dev/null
-// 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 <Python.h>
-
-#include <util/buffer.h>
-#include <util/python/pycppwrapper_util.h>
-
-#include <dns/exceptions.h>
-#include <dns/messagerenderer.h>
-#include <dns/name.h>
-#include <dns/labelsequence.h>
-
-#include "pydnspp_common.h"
-#include "messagerenderer_python.h"
-#include "name_python.h"
-
-#include <iostream>
-
-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<PyCFunction>(NameComparisonResult_getOrder), METH_NOARGS,
- "Returns the order" },
- { "get_common_labels", reinterpret_cast<PyCFunction>(NameComparisonResult_getCommonLabels), METH_NOARGS,
- "Returns the number of common labels" },
- { "get_relation", reinterpret_cast<PyCFunction>(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<s_Name, Name> 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<PyCFunction>(Name_at), METH_VARARGS,
- "Returns the integer value of the name data at the specified position" },
- { "get_length", reinterpret_cast<PyCFunction>(Name_getLength), METH_NOARGS,
- "Returns the length" },
- { "get_labelcount", reinterpret_cast<PyCFunction>(Name_getLabelCount), METH_NOARGS,
- "Returns the number of labels" },
- { "to_text", reinterpret_cast<PyCFunction>(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<PyCFunction>(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<PyCFunction>(Name_compare), METH_VARARGS,
- "Returns a NameComparisonResult object. The argument must be another Name object" },
- { "equals", reinterpret_cast<PyCFunction>(Name_equals), METH_VARARGS,
- "Returns true if the given Name object is equal to this one" },
- { "split", reinterpret_cast<PyCFunction>(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<PyCFunction>(Name_reverse), METH_NOARGS,
- "Returns a new Name object that is the reverse of this one" },
- { "concatenate", reinterpret_cast<PyCFunction>(Name_concatenate), METH_VARARGS,
- "Concatenates the given Name object to this one and returns the "
- "result as a new Name object" },
- { "downcase", reinterpret_cast<PyCFunction>(Name_downcase), METH_NOARGS,
- "Downcases this name object (in-place). Returns a new reference to the Name." },
- { "is_wildcard", reinterpret_cast<PyCFunction>(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<char*>("to_text"),
- const_cast<char*>("")));
-}
-
-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<const char*>(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<s_Name*>(pyself);
- return (convertToPyHash<size_t>(
- 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<const s_Name*>(name_obj);
- return (*name->cppobj);
-}
-
-
-} // namespace python
-} // namespace dns
-} // namespace isc
+++ /dev/null
-// 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 <Python.h>
-
-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:
+++ /dev/null
-// 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 <Python.h>
-
-#include <string>
-#include <stdexcept>
-
-#include <util/python/pycppwrapper_util.h>
-
-#include <dns/nsec3hash.h>
-#include <dns/rdataclass.h>
-
-#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<s_NSEC3Hash*>(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<const generic::NSEC3PARAM*>(&rdata);
- const generic::NSEC3* nsec3 =
- dynamic_cast<const generic::NSEC3*>(&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<s_NSEC3Hash*>(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<s_NSEC3Hash*>(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<s_NSEC3Hash*>(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<const generic::NSEC3PARAM*>(&rdata);
- const generic::NSEC3* nsec3 =
- dynamic_cast<const generic::NSEC3*>(&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<PyObject*>(p)) < 0) {
- return (false);
- }
- Py_INCREF(&nsec3hash_type);
-
- return (true);
-}
-} // namespace python
-} // namespace dns
-} // namespace isc
+++ /dev/null
-// 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 <Python.h>
-
-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:
+++ /dev/null
-// 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
+++ /dev/null
-// 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 <Python.h>
-
-#include <dns/opcode.h>
-#include <util/python/pycppwrapper_util.h>
-
-#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<s_Opcode, Opcode> 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<PyCFunction>(Opcode_getCode), METH_NOARGS,
- "Returns the code value" },
- { "to_text", reinterpret_cast<PyCFunction>(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<char*>("to_text"),
- const_cast<char*>("")));
-}
-
-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<const s_Opcode*>(opcode_obj);
- return (*opcode->cppobj);
-}
-
-} // end python namespace
-} // end dns namespace
-} // end isc namespace
+++ /dev/null
-// 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 <Python.h>
-
-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:
+++ /dev/null
-// 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_<name>, 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 <Python.h>
-#include <structmember.h>
-
-#include <dns/exceptions.h>
-#include <dns/message.h>
-#include <dns/opcode.h>
-#include <dns/tsig.h>
-#include <util/python/pycppwrapper_util.h>
-
-#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 <dns/python/rrclass_constants_inc.cc>
- } 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 <dns/python/rrtype_constants_inc.cc>
- } 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);
-}
+++ /dev/null
-// 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 <Python.h>
-
-#include <exceptions/exceptions.h>
-
-#include <util/buffer.h>
-
-#include <dns/exceptions.h>
-#include <dns/name.h>
-#include <dns/messagerenderer.h>
-
-#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<uint8_t>(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<PyObject*>(p)) < 0) {
- return (false);
- }
- Py_INCREF(&type);
- return (true);
-}
-
-}
-}
-}
+++ /dev/null
-// 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 <dns/python/pydnspp_config.h>
-
-#include <Python.h>
-
-#include <boost/static_assert.hpp>
-
-#include <climits> // for CHAR_BIT
-#include <stdexcept>
-#include <string>
-
-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 <typename HashvalType>
-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<Py_hash_t>(-1) << hash_val_bits);
- return (static_cast<Py_hash_t>(val) & mask);
- } else {
- // Clear the highest bit of the original hash so the conversion is
- // safe and avoids -1.
- HashvalType mask = ~(static_cast<HashvalType>(1) <<
- (hash_val_bits - 1));
- return (val & mask);
- }
-}
-} // namespace python
-} // namespace dns
-} // namespace isc
-#endif // LIBDNS_PYTHON_COMMON_H
-
-// Local Variables:
-// mode: c++
-// End:
+++ /dev/null
-// 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
+++ /dev/null
-// 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 <Python.h>
-
-#include <stdexcept>
-#include <string>
-
-#include <dns/messagerenderer.h>
-
-#include <util/buffer.h>
-#include <util/python/pycppwrapper_util.h>
-
-#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 <typename CPPCLASS>
-struct ToWireCallVoid {
- ToWireCallVoid(CPPCLASS& cppobj) : cppobj_(cppobj) {}
- int operator()(AbstractMessageRenderer& renderer) const {
- cppobj_.toWire(renderer);
- return (0);
- }
- const CPPCLASS& cppobj_;
-};
-
-template <typename CPPCLASS>
-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<CPPCLASS> or
-// ToWireCallInt<CPPCLASS>, 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 <typename PYSTRUCT, typename CPPCLASS, typename TOWIRECALLER>
-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<const char*>(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:
+++ /dev/null
-// 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 <Python.h>
-#include <dns/question.h>
-#include <dns/messagerenderer.h>
-#include <dns/exceptions.h>
-#include <util/buffer.h>
-#include <util/python/pycppwrapper_util.h>
-
-#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<PyCFunction>(Question_getName), METH_NOARGS,
- "Returns the Name" },
- { "get_type", reinterpret_cast<PyCFunction>(Question_getType), METH_NOARGS,
- "Returns the RRType" },
- { "get_class", reinterpret_cast<PyCFunction>(Question_getClass), METH_NOARGS,
- "Returns the RRClass" },
- { "to_text", reinterpret_cast<PyCFunction>(Question_toText), METH_NOARGS,
- "Returns the string representation" },
- { "to_wire", reinterpret_cast<PyCFunction>(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<char*>("to_text"),
- const_cast<char*>("")));
-}
-
-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<const char*>(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<s_Question*>(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<const s_Question*>(question_obj);
- return (*question->cppobj);
-}
-
-} // end python namespace
-} // end dns namespace
-} // end isc namespace
+++ /dev/null
-// 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 <Python.h>
-
-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:
+++ /dev/null
-// 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 <Python.h>
-
-#include <exceptions/exceptions.h>
-#include <dns/rcode.h>
-#include <util/python/pycppwrapper_util.h>
-
-#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<s_Rcode, Rcode> 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<PyCFunction>(Rcode_getCode), METH_NOARGS,
- "Returns the code value" },
- { "get_extended_code",
- reinterpret_cast<PyCFunction>(Rcode_getExtendedCode), METH_NOARGS,
- "Returns the upper 8-bit part of the extended code value" },
- { "to_text", reinterpret_cast<PyCFunction>(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<char*>("to_text"),
- const_cast<char*>("")));
-}
-
-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<richcmpfunc>(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<const s_Rcode*>(rcode_obj);
- return (*rcode->cppobj);
-}
-
-} // namespace python
-} // namespace dns
-} // namespace isc
+++ /dev/null
-// 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 <Python.h>
-
-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:
+++ /dev/null
-// 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 <Python.h>
-#include <dns/rdata.h>
-#include <dns/messagerenderer.h>
-#include <dns/exceptions.h>
-#include <util/buffer.h>
-#include <util/python/pycppwrapper_util.h>
-
-#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<s_Rdata, Rdata> 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<s_Rdata*>(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<s_Rdata*>(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<const s_Rdata*>(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<char*>("to_text"),
- const_cast<char*>("")));
-}
-
-PyObject*
-Rdata_toWire_internal(PyObject* self_p, PyObject* args) {
- PyObject* bytes;
- PyObject* mr;
- const s_Rdata* self(static_cast<const s_Rdata*>(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<const char*>(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<const s_Rdata*>(self_p)),
- * other(static_cast<const s_Rdata*>(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<s_Rdata*>(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<const s_Rdata*>(rdata_obj);
- return (*rdata->cppobj);
-}
-
-} // end python namespace
-} // end dns namespace
-} // end isc namespace
+++ /dev/null
-// 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 <Python.h>
-
-#include <dns/rdata.h>
-
-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:
+++ /dev/null
-// 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 <Python.h>
-
-#include <dns/rrclass.h>
-#include <dns/messagerenderer.h>
-#include <util/buffer.h>
-#include <util/python/pycppwrapper_util.h>
-
-#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<s_RRClass, RRClass> 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<PyCFunction>(RRClass_toText), METH_NOARGS,
- "Returns the string representation" },
- { "to_wire", reinterpret_cast<PyCFunction>(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<PyCFunction>(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<char*>("to_text"),
- const_cast<char*>("")));
-}
-
-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<const char*>(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<s_RRClass*>(pyself);
- return (convertToPyHash<uint16_t>(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<const s_RRClass*>(rrclass_obj);
- return (*rrclass->cppobj);
-}
-
-} // end namespace python
-} // end namespace dns
-} // end namespace isc
+++ /dev/null
-// 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 <Python.h>
-
-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:
+++ /dev/null
-// Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC")
-//
-// Permission to use, copy, modify, and/or distribute this software for any
-// purpose with or without fee is hereby granted, provided that the above
-// copyright notice and this permission notice appear in all copies.
-//
-// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
-// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
-// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
-// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
-// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
-// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
-// PERFORMANCE OF THIS SOFTWARE.
-
-// Enable this if you use s# variants with PyArg_ParseTuple(), see
-// http://docs.python.org/py3k/c-api/arg.html#strings-and-buffers
-//#define PY_SSIZE_T_CLEAN
-
-// Python.h needs to be placed at the head of the program file, see:
-// http://docs.python.org/py3k/extending/extending.html#a-simple-example
-#include <Python.h>
-
-#include <exceptions/exceptions.h>
-
-#include <dns/python/rrset_collection_python.h>
-#include <dns/python/name_python.h>
-#include <dns/python/rrtype_python.h>
-#include <dns/python/rrclass_python.h>
-#include <dns/python/rrset_python.h>
-#include <dns/python/pydnspp_common.h>
-
-#include <dns/rrset_collection_base.h>
-#include <dns/rrset_collection.h>
-
-#include <string>
-#include <sstream>
-#include <stdexcept>
-
-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<s_RRsetCollection*>(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<s_RRsetCollection*>(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<s_RRsetCollection, RRsetCollection> RRsetCollectionContainer;
-
-int
-RRsetCollection_init(PyObject* po_self, PyObject* args, PyObject*) {
- s_RRsetCollection* self = static_cast<s_RRsetCollection*>(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<const char*>(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<s_RRsetCollection*>(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<s_RRsetCollection*>(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<RRsetCollection*>(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<s_RRsetCollection*>(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<RRsetCollection*>(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
+++ /dev/null
-// 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 <Python.h>
-
-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:
+++ /dev/null
-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
+++ /dev/null
-// 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 <Python.h>
-
-#include <util/python/pycppwrapper_util.h>
-
-#include <dns/rrset.h>
-#include <dns/name.h>
-#include <dns/messagerenderer.h>
-
-#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<const s_RRset*>(self)->cppobj->
- getRdataCount()));
-}
-
-PyObject*
-RRset_getLength(PyObject* self, PyObject*) {
- try {
- return (Py_BuildValue("H", static_cast<const s_RRset*>(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<const s_RRset*>(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<const s_RRset*>(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<const s_RRset*>(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<const s_RRset*>(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<s_RRset*>(self)->cppobj->setTTL(PyRRTTL_ToRRTTL(rrttl));
- Py_RETURN_NONE;
-}
-
-PyObject*
-RRset_toText(PyObject* self, PyObject*) {
- try {
- return (Py_BuildValue("s", static_cast<const s_RRset*>(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<char*>("to_text"),
- const_cast<char*>("")));
-}
-
-PyObject*
-RRset_toWire(PyObject* self_p, PyObject* args) {
- PyObject* bytes;
- PyObject* mr;
-
- try {
- const s_RRset* self = static_cast<const s_RRset*>(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<const char*>(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<s_RRset*>(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<s_RRset*>(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<s_RRset*>(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<s_RRset*>(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<s_RRset*>(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<s_RRset*>(rrset_obj);
- return (rrset->cppobj);
-}
-
-
-} // end python namespace
-} // end dns namespace
-} // end isc namespace
+++ /dev/null
-// 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 <Python.h>
-
-#include <dns/rrset.h>
-
-#include <util/python/pycppwrapper_util.h>
-
-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:
+++ /dev/null
-// 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 <Python.h>
-#include <vector>
-
-#include <dns/rrttl.h>
-#include <dns/messagerenderer.h>
-#include <util/buffer.h>
-#include <util/python/pycppwrapper_util.h>
-
-#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<s_RRTTL, RRTTL> 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<PyCFunction>(RRTTL_toText), METH_NOARGS,
- "Returns the string representation" },
- { "to_wire", reinterpret_cast<PyCFunction>(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<PyCFunction>(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<uint8_t> 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<char*>("to_text"),
- const_cast<char*>("")));
-}
-
-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<const char*>(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<const s_RRTTL*>(rrttl_obj);
- return (*rrttl->cppobj);
-}
-
-} // namespace python
-} // namespace dns
-} // namespace isc
+++ /dev/null
-// 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 <Python.h>
-
-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:
+++ /dev/null
-// 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 <Python.h>
-#include <vector>
-
-#include <dns/rrtype.h>
-#include <dns/messagerenderer.h>
-#include <util/python/pycppwrapper_util.h>
-
-#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<s_RRType, RRType> 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<PyCFunction>(RRType_toText), METH_NOARGS,
- "Returns the string representation" },
- { "to_wire", reinterpret_cast<PyCFunction>(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<PyCFunction>(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<uint8_t> 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<char*>("to_text"),
- const_cast<char*>("")));
-}
-
-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<const char*>(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<s_RRType*>(pyself);
- return (convertToPyHash<uint16_t>(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<const s_RRType*>(rrtype_obj);
- return (*rrtype->cppobj);
-}
-
-
-} // end namespace python
-} // end namespace dns
-} // end namespace isc
+++ /dev/null
-// 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 <Python.h>
-
-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:
+++ /dev/null
-// 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 <Python.h>
-
-#include <dns/serial.h>
-#include <util/python/pycppwrapper_util.h>
-
-#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<s_Serial, Serial> 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<PyCFunction>(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<s_Serial*>(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<const s_Serial*>(serial_obj);
- return (*serial->cppobj);
-}
-
-} // namespace python
-} // namespace dns
-} // namespace isc
+++ /dev/null
-// 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 <Python.h>
-
-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:
+++ /dev/null
-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)
+++ /dev/null
-# 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()
+++ /dev/null
-# 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()
+++ /dev/null
-# 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()
+++ /dev/null
-# 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()
+++ /dev/null
-# 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()
+++ /dev/null
-# 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()
+++ /dev/null
-# 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()
+++ /dev/null
-# 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()
+++ /dev/null
-# 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()
+++ /dev/null
-# 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()
+++ /dev/null
-# 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()
+++ /dev/null
-# 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()
+++ /dev/null
-# 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()
+++ /dev/null
-# 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()
+++ /dev/null
-# 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()
+++ /dev/null
-# 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()
+++ /dev/null
-# 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")
+++ /dev/null
-# 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()
+++ /dev/null
-# 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()
+++ /dev/null
-# 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()
+++ /dev/null
-# 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()
+++ /dev/null
-# 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()
+++ /dev/null
-# 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()
+++ /dev/null
-// 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 <Python.h>
-
-#include <string>
-#include <stdexcept>
-
-#include <exceptions/exceptions.h>
-
-#include <util/python/pycppwrapper_util.h>
-
-#include <dns/tsig.h>
-
-#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<s_TSIGContext, TSIGContext> 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<PyCFunction>(TSIGContext_getState),
- METH_NOARGS,
- "Return the current state of the context (mainly for tests)" },
- { "get_error", reinterpret_cast<PyCFunction>(TSIGContext_getError),
- METH_NOARGS,
- "Return the TSIG error as a result of the latest verification" },
- { "sign",
- reinterpret_cast<PyCFunction>(TSIGContext_sign), METH_VARARGS,
- "Sign a DNS message." },
- { "verify",
- reinterpret_cast<PyCFunction>(TSIGContext_verify), METH_VARARGS,
- "Verify a DNS message." },
- { "last_had_signature",
- reinterpret_cast<PyCFunction>(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<destructor>(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<initproc>(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<s_TSIGContext*>(tsigcontext_obj);
- return (tsigcontext->cppobj);
-}
-
-} // namespace python
-} // namespace dns
-} // namespace isc
+++ /dev/null
-// 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 <Python.h>
-
-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:
+++ /dev/null
-// 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 <Python.h>
-
-#include <string>
-#include <stdexcept>
-
-#include <util/python/pycppwrapper_util.h>
-
-#include <dns/rdataclass.h>
-
-#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<s_TSIG, any::TSIG> 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<PyCFunction>(TSIG_getAlgorithm),
- METH_NOARGS,
- "Return the algorithm name." },
- { "get_timesigned", reinterpret_cast<PyCFunction>(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<PyCFunction>(TSIG_getFudge),
- METH_NOARGS,
- "Return the value of the Fudge field." },
- { "get_original_id", reinterpret_cast<PyCFunction>(TSIG_getOriginalID),
- METH_NOARGS,
- "Return the value of the Original ID field." },
- { "get_error", reinterpret_cast<PyCFunction>(TSIG_getError),
- METH_NOARGS,
- "Return the value of the Error field." },
- { "get_mac", reinterpret_cast<PyCFunction>(TSIG_getMAC),
- METH_NOARGS,
- "Return the value of the MAC field."
- "If it's empty, return None." },
- { "get_other_data", reinterpret_cast<PyCFunction>(TSIG_getOtherData),
- METH_NOARGS,
- "Return the value of the Other Data field."
- "If it's empty, return None." },
- { "to_text", reinterpret_cast<PyCFunction>(TSIG_toText), METH_NOARGS,
- "Returns the text representation" },
- { "to_wire", reinterpret_cast<PyCFunction>(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<char*>("to_text"),
- const_cast<char*>("")));
-}
-
-PyObject*
-TSIG_toWire(const s_TSIG* const self, PyObject* args) {
- typedef any::TSIG TSIGRdata;
- return (toWireWrapper<s_TSIG, TSIGRdata, ToWireCallVoid<const TSIGRdata> >(
- 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<destructor>(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<richcmpfunc>(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<initproc>(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<const s_TSIG*>(tsig_obj);
- return (*tsig->cppobj);
-}
-
-} // namespace python
-} // namespace dns
-} // namespace isc
+++ /dev/null
-// 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 <Python.h>
-
-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:
+++ /dev/null
-// 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 <Python.h>
-
-#include <string>
-#include <stdexcept>
-
-#include <util/python/pycppwrapper_util.h>
-
-#include <dns/tsigerror.h>
-
-#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<s_TSIGError, TSIGError> 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<PyCFunction>(TSIGError_getCode),
- METH_NOARGS,
- TSIGError_getCode_doc },
- { "to_text", reinterpret_cast<PyCFunction>(TSIGError_toText), METH_NOARGS,
- TSIGError_toText_doc },
- { "to_rcode", reinterpret_cast<PyCFunction>(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<char*>("to_text"),
- const_cast<char*>("")));
-}
-
-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<destructor>(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<richcmpfunc>(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<initproc>(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
+++ /dev/null
-// 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 <Python.h>
-
-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:
+++ /dev/null
-// 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\
-";
-}
+++ /dev/null
-// 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 <Python.h>
-
-#include <stdexcept>
-
-#include <util/python/pycppwrapper_util.h>
-
-#include <dns/name.h>
-#include <dns/tsigkey.h>
-#include <dns/rdata.h>
-
-#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<PyCFunction>(TSIGKey_getKeyName), METH_NOARGS,
- "Return the key name." },
- { "get_algorithm_name",
- reinterpret_cast<PyCFunction>(TSIGKey_getAlgorithmName), METH_NOARGS,
- "Return the algorithm name." },
- { "get_secret",
- reinterpret_cast<PyCFunction>(TSIGKey_getSecret), METH_NOARGS,
- "Return the value of the TSIG secret." },
- { "to_text", reinterpret_cast<PyCFunction>(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<const s_TSIGKey*>(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<PyCFunction>(TSIGKeyRing_size), METH_NOARGS,
- "Return the number of keys stored in the TSIGKeyRing." },
- { "add", reinterpret_cast<PyCFunction>(TSIGKeyRing_add), METH_VARARGS,
- "Add a TSIGKey to the TSIGKeyRing." },
- { "remove", reinterpret_cast<PyCFunction>(TSIGKeyRing_remove),
- METH_VARARGS,
- "Remove a TSIGKey for the given name from the TSIGKeyRing." },
- { "find", reinterpret_cast<PyCFunction>(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<const s_TSIGKeyRing*>(tsigkeyring_obj);
- return (*tsigkeyring->cppobj);
-}
-
-} // namespace python
-} // namespace dns
-} // namespace isc
+++ /dev/null
-// 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 <Python.h>
-
-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:
+++ /dev/null
-// 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 <Python.h>
-
-#include <string>
-#include <stdexcept>
-
-#include <util/python/pycppwrapper_util.h>
-
-#include <dns/tsigrecord.h>
-
-#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<s_TSIGRecord, TSIGRecord> 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<PyCFunction>(TSIGRecord_getName),
- METH_NOARGS,
- "Return the owner name of the TSIG RR, which is the TSIG key name" },
- { "get_length", reinterpret_cast<PyCFunction>(TSIGRecord_getLength),
- METH_NOARGS,
- "Return the length of the TSIG record" },
- { "get_rdata", reinterpret_cast<PyCFunction>(TSIGRecord_getRdata),
- METH_NOARGS,
- "Return the RDATA of the TSIG RR" },
- { "to_text", reinterpret_cast<PyCFunction>(TSIGRecord_toText), METH_NOARGS,
- "Returns the text representation" },
- { "to_wire", reinterpret_cast<PyCFunction>(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<char*>("to_text"),
- const_cast<char*>("")));
-}
-
-PyObject*
-TSIGRecord_toWire(const s_TSIGRecord* const self, PyObject* args) {
- typedef ToWireCallInt<const TSIGRecord> ToWireCall;
- PyObject* (*towire_fn)(const s_TSIGRecord* const, PyObject*) =
- toWireWrapper<s_TSIGRecord, TSIGRecord, ToWireCall>;
- 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<destructor>(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<initproc>(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<s_TSIGRecord*>(tsigrecord_obj);
- return (*tsigrecord->cppobj);
-}
-
-
-} // namespace python
-} // namespace dns
-} // namespace isc
+++ /dev/null
-// 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 <Python.h>
-
-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:
+++ /dev/null
-// Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC")
-//
-// Permission to use, copy, modify, and/or distribute this software for any
-// purpose with or without fee is hereby granted, provided that the above
-// copyright notice and this permission notice appear in all copies.
-//
-// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
-// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
-// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
-// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
-// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
-// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
-// PERFORMANCE OF THIS SOFTWARE.
-
-// Enable this if you use s# variants with PyArg_ParseTuple(), see
-// http://docs.python.org/py3k/c-api/arg.html#strings-and-buffers
-#define PY_SSIZE_T_CLEAN
-
-// Python.h needs to be placed at the head of the program file, see:
-// http://docs.python.org/py3k/extending/extending.html#a-simple-example
-#include <Python.h>
-
-#include <util/python/pycppwrapper_util.h>
-
-#include <dns/python/name_python.h>
-#include <dns/python/rrclass_python.h>
-#include <dns/python/rrtype_python.h>
-#include <dns/python/rrset_python.h>
-#include <dns/python/rrset_collection_python.h>
-#include <dns/python/zone_checker_python.h>
-#include <dns/python/pydnspp_common.h>
-
-#include <exceptions/exceptions.h>
-
-#include <dns/name.h>
-#include <dns/rrclass.h>
-#include <dns/rrtype.h>
-#include <dns/rrset.h>
-#include <dns/rrset_collection_base.h>
-#include <dns/zone_checker.h>
-
-#include <boost/bind.hpp>
-
-#include <cstring>
-#include <string>
-#include <stdexcept>
-
-using std::string;
-using isc::util::python::PyObjectContainer;
-using namespace isc::dns;
-
-namespace {
-// This is a template for a common pattern of type mismatch error handling,
-// provided to save typing and repeating the mostly identical patterns.
-PyObject*
-setTypeError(PyObject* pobj, const char* var_name, const char* type_name) {
- PyErr_Format(PyExc_TypeError, "%s must be a %s, not %.200s",
- var_name, type_name, pobj->ob_type->tp_name);
- return (NULL);
-}
-}
-
-namespace isc {
-namespace dns {
-namespace python {
-namespace internal {
-
-// 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
+++ /dev/null
-// Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC")
-//
-// Permission to use, copy, modify, and/or distribute this software for any
-// purpose with or without fee is hereby granted, provided that the above
-// copyright notice and this permission notice appear in all copies.
-//
-// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
-// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
-// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
-// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
-// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
-// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
-// PERFORMANCE OF THIS SOFTWARE.
-
-#ifndef PYTHON_ZONE_CHECKER_H
-#define PYTHON_ZONE_CHECKER_H 1
-
-#include <Python.h>
-
-namespace isc {
-namespace dns {
-namespace python {
-namespace internal {
-
-PyObject* pyCheckZone(PyObject* self, PyObject* args);
-
-} // namespace python
-} // namespace python
-} // namespace dns
-} // namespace isc
-#endif // PYTHON_ZONE_CHECKER_H
-
-// Local Variables:
-// mode: c++
-// End:
+++ /dev/null
-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
--- /dev/null
+///////////////
+///////////////
+/////////////// 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 <string>
+#include <sstream>
+#include <vector>
+
+#include <boost/lexical_cast.hpp>
+
+#include <util/buffer.h>
+#include <util/encode/base64.h>
+
+#include <dns/messagerenderer.h>
+#include <dns/name.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+#include <dns/rcode.h>
+#include <dns/tsigkey.h>
+#include <dns/tsigerror.h>
+#include <dns/rdata/generic/detail/lexer_util.h>
+
+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<uint8_t>& mac, uint16_t original_id, uint16_t error,
+ vector<uint8_t>& 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<const uint8_t*>(mac),
+ static_cast<const uint8_t*>(mac) + macsize),
+ original_id_(original_id), error_(error),
+ other_data_(static_cast<const uint8_t*>(other_data),
+ static_cast<const uint8_t*>(other_data) + other_len)
+ {}
+ template <typename Output>
+ void toWireCommon(Output& output) const;
+
+ const Name algorithm_;
+ const uint64_t time_signed_;
+ const uint16_t fudge_;
+ const vector<uint8_t> mac_;
+ const uint16_t original_id_;
+ const uint16_t error_;
+ const vector<uint8_t> 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<uint64_t>(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<uint8_t> 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<uint32_t>(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<uint8_t> 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 <Algorithm Name> <Time Signed> <Fudge> <MAC Size> [<MAC>]
+/// <Original ID> <Error> <Other Len> [<Other Data>]
+/// \endcode
+///
+/// Note that, since the Algorithm Name field is defined to be "in domain name
+/// syntax", but it is not actually a domain name, it does not have to be
+/// fully qualified.
+///
+/// The Error field is an unsigned 16-bit decimal integer or a valid mnemonic
+/// as specified in RFC2845. Currently, "NOERROR", "BADSIG", "BADKEY", and
+/// "BADTIME" are supported (case sensitive). In future versions other
+/// representations that are compatible with the DNS RCODE may be supported.
+///
+/// The MAC and Other Data fields are base-64 encoded strings that do not
+/// contain space characters.
+/// If the MAC Size field is 0, the MAC field must not appear in \c tsig_str.
+/// If the Other Len field is 0, the Other Data field must not appear in
+/// \c tsig_str.
+/// The decoded data of the MAC field is MAC Size bytes of binary stream.
+/// The decoded data of the Other Data field is Other Len bytes of binary
+/// stream.
+///
+/// An example of valid string is:
+/// \code "hmac-sha256. 853804800 300 3 AAAA 2845 0 0" \endcode
+/// In this example Other Data is missing because Other Len is 0.
+///
+/// Note that RFC2845 does not define the standard presentation format
+/// of %TSIG RR, so the above syntax is implementation specific.
+/// This is, however, compatible with the format acceptable to BIND 9's
+/// RDATA parser.
+///
+/// \throw Others Exception from the Name constructors.
+/// \throw InvalidRdataText if any fields are out of their valid range,
+/// or are incorrect.
+/// \throw BadValue if MAC or Other Data is not validly encoded in base-64.
+///
+/// \param tsig_str A string containing the RDATA to be created
+TSIG::TSIG(const std::string& tsig_str) : impl_(NULL) {
+ // We use auto_ptr here because if there is an exception in this
+ // constructor, the destructor is not called and there could be a
+ // leak of the TSIGImpl that constructFromLexer() returns.
+ std::auto_ptr<TSIGImpl> impl_ptr(NULL);
+
+ try {
+ std::istringstream ss(tsig_str);
+ MasterLexer lexer;
+ lexer.pushSource(ss);
+
+ impl_ptr.reset(constructFromLexer(lexer, NULL));
+
+ if (lexer.getNextToken().getType() != MasterToken::END_OF_FILE) {
+ isc_throw(InvalidRdataText,
+ "Extra input text for TSIG: " << tsig_str);
+ }
+ } catch (const MasterLexer::LexerError& ex) {
+ isc_throw(InvalidRdataText,
+ "Failed to construct TSIG from '" << tsig_str << "': "
+ << ex.what());
+ }
+
+ impl_ = impl_ptr.release();
+}
+
+/// \brief Constructor with a context of MasterLexer.
+///
+/// The \c lexer should point to the beginning of valid textual
+/// representation of an TSIG RDATA.
+///
+/// See \c TSIG::TSIG(const std::string&) for description of the
+/// expected RDATA fields.
+///
+/// \throw MasterLexer::LexerError General parsing error such as
+/// missing field.
+/// \throw InvalidRdataText if any fields are out of their valid range,
+/// or are incorrect.
+///
+/// \param lexer A \c MasterLexer object parsing a master file for the
+/// RDATA to be created
+TSIG::TSIG(MasterLexer& lexer, const Name* origin,
+ MasterLoader::Options, MasterLoaderCallbacks&) :
+ impl_(constructFromLexer(lexer, origin))
+{
+}
+
+/// \brief Constructor from wire-format data.
+///
+/// When a read operation on \c buffer fails (e.g., due to a corrupted
+/// message) a corresponding exception from the \c InputBuffer class will
+/// be thrown.
+/// If the wire-format data does not begin with a valid domain name,
+/// a corresponding exception from the \c Name class will be thrown.
+/// In addition, this constructor internally involves resource allocation,
+/// and if it fails a corresponding standard exception will be thrown.
+///
+/// According to RFC3597, the Algorithm field must be a non compressed form
+/// of domain name. But this implementation accepts a %TSIG RR even if that
+/// field is compressed.
+///
+/// \param buffer A buffer storing the wire format data.
+/// \param rdata_len The length of the RDATA in bytes, normally expected
+/// to be the value of the RDLENGTH field of the corresponding RR.
+/// But this constructor does not use this parameter; if necessary, the caller
+/// must check consistency between the length parameter and the actual
+/// RDATA length.
+TSIG::TSIG(InputBuffer& buffer, size_t) :
+ impl_(NULL)
+{
+ Name algorithm(buffer);
+
+ uint8_t time_signed_buf[6];
+ buffer.readData(time_signed_buf, sizeof(time_signed_buf));
+ const uint64_t time_signed =
+ (static_cast<uint64_t>(time_signed_buf[0]) << 40 |
+ static_cast<uint64_t>(time_signed_buf[1]) << 32 |
+ static_cast<uint64_t>(time_signed_buf[2]) << 24 |
+ static_cast<uint64_t>(time_signed_buf[3]) << 16 |
+ static_cast<uint64_t>(time_signed_buf[4]) << 8 |
+ static_cast<uint64_t>(time_signed_buf[5]));
+
+ const uint16_t fudge = buffer.readUint16();
+
+ const uint16_t mac_size = buffer.readUint16();
+ vector<uint8_t> mac(mac_size);
+ if (mac_size > 0) {
+ buffer.readData(&mac[0], mac_size);
+ }
+
+ const uint16_t original_id = buffer.readUint16();
+ const uint16_t error = buffer.readUint16();
+
+ const uint16_t other_len = buffer.readUint16();
+ vector<uint8_t> other_data(other_len);
+ if (other_len > 0) {
+ buffer.readData(&other_data[0], other_len);
+ }
+
+ const Name& canonical_algorithm_name =
+ (algorithm == TSIGKey::HMACMD5_SHORT_NAME()) ?
+ TSIGKey::HMACMD5_NAME() : algorithm;
+ impl_ = new TSIGImpl(canonical_algorithm_name, time_signed, fudge, mac,
+ original_id, error, other_data);
+}
+
+TSIG::TSIG(const Name& algorithm, uint64_t time_signed, uint16_t fudge,
+ uint16_t mac_size, const void* mac, uint16_t original_id,
+ uint16_t error, uint16_t other_len, const void* other_data) :
+ impl_(NULL)
+{
+ // Time Signed is a 48-bit value.
+ if ((time_signed >> 48) != 0) {
+ isc_throw(OutOfRange, "TSIG Time Signed is too large: " <<
+ time_signed);
+ }
+ if ((mac_size == 0 && mac != NULL) || (mac_size > 0 && mac == NULL)) {
+ isc_throw(InvalidParameter, "TSIG MAC size and data inconsistent");
+ }
+ if ((other_len == 0 && other_data != NULL) ||
+ (other_len > 0 && other_data == NULL)) {
+ isc_throw(InvalidParameter,
+ "TSIG Other data length and data inconsistent");
+ }
+ const Name& canonical_algorithm_name =
+ (algorithm == TSIGKey::HMACMD5_SHORT_NAME()) ?
+ TSIGKey::HMACMD5_NAME() : algorithm;
+ impl_ = new TSIGImpl(canonical_algorithm_name, time_signed, fudge, mac_size,
+ mac, original_id, error, other_len, other_data);
+}
+
+/// \brief The copy constructor.
+///
+/// It internally allocates a resource, and if it fails a corresponding
+/// standard exception will be thrown.
+/// This constructor never throws an exception otherwise.
+TSIG::TSIG(const TSIG& source) : Rdata(), impl_(new TSIGImpl(*source.impl_))
+{}
+
+TSIG&
+TSIG::operator=(const TSIG& source) {
+ if (this == &source) {
+ return (*this);
+ }
+
+ TSIGImpl* newimpl = new TSIGImpl(*source.impl_);
+ delete impl_;
+ impl_ = newimpl;
+
+ return (*this);
+}
+
+TSIG::~TSIG() {
+ delete impl_;
+}
+
+/// \brief Convert the \c TSIG to a string.
+///
+/// The output of this method is formatted as described in the "from string"
+/// constructor (\c TSIG(const std::string&))).
+///
+/// If internal resource allocation fails, a corresponding
+/// standard exception will be thrown.
+///
+/// \return A \c string object that represents the \c TSIG object.
+std::string
+TSIG::toText() const {
+ string result;
+
+ result += impl_->algorithm_.toText() + " " +
+ lexical_cast<string>(impl_->time_signed_) + " " +
+ lexical_cast<string>(impl_->fudge_) + " " +
+ lexical_cast<string>(impl_->mac_.size()) + " ";
+ if (!impl_->mac_.empty()) {
+ result += encodeBase64(impl_->mac_) + " ";
+ }
+ result += lexical_cast<string>(impl_->original_id_) + " ";
+ result += TSIGError(impl_->error_).toText() + " ";
+ result += lexical_cast<string>(impl_->other_data_.size());
+ if (!impl_->other_data_.empty()) {
+ result += " " + encodeBase64(impl_->other_data_);
+ }
+
+ return (result);
+}
+
+// Common sequence of toWire() operations used for the two versions of
+// toWire().
+template <typename Output>
+void
+TSIGImpl::toWireCommon(Output& output) const {
+ output.writeUint16(time_signed_ >> 32);
+ output.writeUint32(time_signed_ & 0xffffffff);
+ output.writeUint16(fudge_);
+ const uint16_t mac_size = mac_.size();
+ output.writeUint16(mac_size);
+ if (mac_size > 0) {
+ output.writeData(&mac_[0], mac_size);
+ }
+ output.writeUint16(original_id_);
+ output.writeUint16(error_);
+ const uint16_t other_len = other_data_.size();
+ output.writeUint16(other_len);
+ if (other_len > 0) {
+ output.writeData(&other_data_[0], other_len);
+ }
+}
+
+/// \brief Render the \c TSIG in the wire format without name compression.
+///
+/// If internal resource allocation fails, a corresponding
+/// standard exception will be thrown.
+/// This method never throws an exception otherwise.
+///
+/// \param buffer An output buffer to store the wire data.
+void
+TSIG::toWire(OutputBuffer& buffer) const {
+ impl_->algorithm_.toWire(buffer);
+ impl_->toWireCommon<OutputBuffer>(buffer);
+}
+
+/// \brief Render the \c TSIG in the wire format with taking into account
+/// compression.
+///
+/// As specified in RFC3597, the Algorithm field (a domain name) will not
+/// be compressed. However, the domain name could be a target of compression
+/// of other compressible names (though pretty unlikely), the offset
+/// information of the algorithm name may be recorded in \c renderer.
+///
+/// If internal resource allocation fails, a corresponding
+/// standard exception will be thrown.
+/// This method never throws an exception otherwise.
+///
+/// \param renderer DNS message rendering context that encapsulates the
+/// output buffer and name compression information.
+void
+TSIG::toWire(AbstractMessageRenderer& renderer) const {
+ renderer.writeName(impl_->algorithm_, false);
+ impl_->toWireCommon<AbstractMessageRenderer>(renderer);
+}
+
+// A helper function commonly used for TSIG::compare().
+int
+vectorComp(const vector<uint8_t>& v1, const vector<uint8_t>& v2) {
+ const size_t this_size = v1.size();
+ const size_t other_size = v2.size();
+ if (this_size != other_size) {
+ return (this_size < other_size ? -1 : 1);
+ }
+ if (this_size > 0) {
+ return (memcmp(&v1[0], &v2[0], this_size));
+ }
+ return (0);
+}
+
+/// \brief Compare two instances of \c TSIG RDATA.
+///
+/// This method compares \c this and the \c other \c TSIG objects
+/// in terms of the DNSSEC sorting order as defined in RFC4034, and returns
+/// the result as an integer.
+///
+/// This method is expected to be used in a polymorphic way, and the
+/// parameter to compare against is therefore of the abstract \c Rdata class.
+/// However, comparing two \c Rdata objects of different RR types
+/// is meaningless, and \c other must point to a \c TSIG object;
+/// otherwise, the standard \c bad_cast exception will be thrown.
+/// This method never throws an exception otherwise.
+///
+/// \param other the right-hand operand to compare against.
+/// \return < 0 if \c this would be sorted before \c other.
+/// \return 0 if \c this is identical to \c other in terms of sorting order.
+/// \return > 0 if \c this would be sorted after \c other.
+int
+TSIG::compare(const Rdata& other) const {
+ const TSIG& other_tsig = dynamic_cast<const TSIG&>(other);
+
+ const int ncmp = compareNames(impl_->algorithm_,
+ other_tsig.impl_->algorithm_);
+ if (ncmp != 0) {
+ return (ncmp);
+ }
+
+ if (impl_->time_signed_ != other_tsig.impl_->time_signed_) {
+ return (impl_->time_signed_ < other_tsig.impl_->time_signed_ ? -1 : 1);
+ }
+ if (impl_->fudge_ != other_tsig.impl_->fudge_) {
+ return (impl_->fudge_ < other_tsig.impl_->fudge_ ? -1 : 1);
+ }
+ const int vcmp = vectorComp(impl_->mac_, other_tsig.impl_->mac_);
+ if (vcmp != 0) {
+ return (vcmp);
+ }
+ if (impl_->original_id_ != other_tsig.impl_->original_id_) {
+ return (impl_->original_id_ < other_tsig.impl_->original_id_ ? -1 : 1);
+ }
+ if (impl_->error_ != other_tsig.impl_->error_) {
+ return (impl_->error_ < other_tsig.impl_->error_ ? -1 : 1);
+ }
+ return (vectorComp(impl_->other_data_, other_tsig.impl_->other_data_));
+}
+
+const Name&
+TSIG::getAlgorithm() const {
+ return (impl_->algorithm_);
+}
+
+uint64_t
+TSIG::getTimeSigned() const {
+ return (impl_->time_signed_);
+}
+
+uint16_t
+TSIG::getFudge() const {
+ return (impl_->fudge_);
+}
+
+uint16_t
+TSIG::getMACSize() const {
+ return (impl_->mac_.size());
+}
+
+const void*
+TSIG::getMAC() const {
+ if (!impl_->mac_.empty()) {
+ return (&impl_->mac_[0]);
+ } else {
+ return (NULL);
+ }
+}
+
+uint16_t
+TSIG::getOriginalID() const {
+ return (impl_->original_id_);
+}
+
+uint16_t
+TSIG::getError() const {
+ return (impl_->error_);
+}
+
+uint16_t
+TSIG::getOtherLen() const {
+ return (impl_->other_data_.size());
+}
+
+const void*
+TSIG::getOtherData() const {
+ if (!impl_->other_data_.empty()) {
+ return (&impl_->other_data_[0]);
+ } else {
+ return (NULL);
+ }
+}
+
+} // end of namespace "any"
+} // end of namespace "rdata"
+} // end of namespace "dns"
+} // end of namespace "isc"
+// 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 <string>
+
+#include <exceptions/exceptions.h>
+
+#include <util/buffer.h>
+#include <dns/messagerenderer.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+
+using namespace std;
+using namespace isc::util;
+
+namespace isc {
+namespace dns {
+namespace rdata {
+namespace ch {
+
+A::A(const std::string&) {
+ // TBD
+}
+
+A::A(MasterLexer&, const Name*,
+ MasterLoader::Options, MasterLoaderCallbacks&)
+{
+ // TBD
+}
+
+A::A(InputBuffer&, size_t) {
+ // TBD
+}
+
+A::A(const A&) : Rdata() {
+ // TBD
+}
+
+void
+A::toWire(OutputBuffer&) const {
+ // TBD
+}
+
+void
+A::toWire(AbstractMessageRenderer&) const {
+ // TBD
+}
+
+string
+A::toText() const {
+ // TBD
+ isc_throw(InvalidRdataText, "Not implemented yet");
+}
+
+int
+A::compare(const Rdata&) const {
+ return (0); // dummy. TBD
+}
+
+} // end of namespace "ch"
+} // end of namespace "rdata"
+} // end of namespace "dns"
+} // end of namespace "isc"
+// Copyright (C) 2011-2013 Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// 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 <string>
+#include <sstream>
+
+#include <util/buffer.h>
+#include <util/strutil.h>
+
+#include <dns/name.h>
+#include <dns/messagerenderer.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+
+#include <boost/lexical_cast.hpp>
+
+#include <dns/rdata/generic/detail/lexer_util.h>
+
+using namespace std;
+using boost::lexical_cast;
+using namespace isc::util;
+using isc::dns::rdata::generic::detail::createNameFromLexer;
+
+namespace isc {
+namespace dns {
+namespace rdata {
+namespace generic {
+
+/// \brief Constructor from string.
+///
+/// \c afsdb_str must be formatted as follows:
+/// \code <subtype> <server name>
+/// \endcode
+/// where server name field must represent a valid domain name.
+///
+/// An example of valid string is:
+/// \code "1 server.example.com." \endcode
+///
+/// <b>Exceptions</b>
+///
+/// \exception InvalidRdataText The number of RDATA fields (must be 2) is
+/// incorrect.
+/// \exception std::bad_alloc Memory allocation fails.
+/// \exception Other The constructor of the \c Name class will throw if the
+/// names in the string is invalid.
+AFSDB::AFSDB(const std::string& afsdb_str) :
+ subtype_(0), server_(Name::ROOT_NAME())
+{
+ try {
+ std::istringstream ss(afsdb_str);
+ MasterLexer lexer;
+ lexer.pushSource(ss);
+
+ createFromLexer(lexer, NULL);
+
+ if (lexer.getNextToken().getType() != MasterToken::END_OF_FILE) {
+ isc_throw(InvalidRdataText, "extra input text for AFSDB: "
+ << afsdb_str);
+ }
+ } catch (const MasterLexer::LexerError& ex) {
+ isc_throw(InvalidRdataText, "Failed to construct AFSDB from '" <<
+ afsdb_str << "': " << ex.what());
+ }
+}
+
+/// \brief Constructor with a context of MasterLexer.
+///
+/// The \c lexer should point to the beginning of valid textual representation
+/// of an AFSDB RDATA. The SERVER field can be non-absolute if \c origin
+/// is non-NULL, in which case \c origin is used to make it absolute.
+/// It must not be represented as a quoted string.
+///
+/// The SUBTYPE field must be a valid decimal representation of an
+/// unsigned 16-bit integer.
+///
+/// \throw MasterLexer::LexerError General parsing error such as missing field.
+/// \throw Other Exceptions from the Name and RRTTL constructors if
+/// construction of textual fields as these objects fail.
+///
+/// \param lexer A \c MasterLexer object parsing a master file for the
+/// RDATA to be created
+/// \param origin If non NULL, specifies the origin of SERVER when it
+/// is non-absolute.
+AFSDB::AFSDB(MasterLexer& lexer, const Name* origin,
+ MasterLoader::Options, MasterLoaderCallbacks&) :
+ subtype_(0), server_(".")
+{
+ createFromLexer(lexer, origin);
+}
+
+void
+AFSDB::createFromLexer(MasterLexer& lexer, const Name* origin)
+{
+ const uint32_t num = lexer.getNextToken(MasterToken::NUMBER).getNumber();
+ if (num > 65535) {
+ isc_throw(InvalidRdataText, "Invalid AFSDB subtype: " << num);
+ }
+ subtype_ = static_cast<uint16_t>(num);
+
+ server_ = createNameFromLexer(lexer, origin);
+}
+
+/// \brief Constructor from wire-format data.
+///
+/// This constructor doesn't check the validity of the second parameter (rdata
+/// length) for parsing.
+/// If necessary, the caller will check consistency.
+///
+/// \exception std::bad_alloc Memory allocation fails.
+/// \exception Other The constructor of the \c Name class will throw if the
+/// names in the wire is invalid.
+AFSDB::AFSDB(InputBuffer& buffer, size_t) :
+ subtype_(buffer.readUint16()), server_(buffer)
+{}
+
+/// \brief Copy constructor.
+///
+/// \exception std::bad_alloc Memory allocation fails in copying internal
+/// member variables (this should be very rare).
+AFSDB::AFSDB(const AFSDB& other) :
+ Rdata(), subtype_(other.subtype_), server_(other.server_)
+{}
+
+AFSDB&
+AFSDB::operator=(const AFSDB& source) {
+ subtype_ = source.subtype_;
+ server_ = source.server_;
+
+ return (*this);
+}
+
+/// \brief Convert the \c AFSDB to a string.
+///
+/// The output of this method is formatted as described in the "from string"
+/// constructor (\c AFSDB(const std::string&))).
+///
+/// \exception std::bad_alloc Internal resource allocation fails.
+///
+/// \return A \c string object that represents the \c AFSDB object.
+string
+AFSDB::toText() const {
+ return (lexical_cast<string>(subtype_) + " " + server_.toText());
+}
+
+/// \brief Render the \c AFSDB in the wire format without name compression.
+///
+/// \exception std::bad_alloc Internal resource allocation fails.
+///
+/// \param buffer An output buffer to store the wire data.
+void
+AFSDB::toWire(OutputBuffer& buffer) const {
+ buffer.writeUint16(subtype_);
+ server_.toWire(buffer);
+}
+
+/// \brief Render the \c AFSDB in the wire format with taking into account
+/// compression.
+///
+/// As specified in RFC3597, TYPE AFSDB is not "well-known", the server
+/// field (domain name) will not be compressed.
+///
+/// \exception std::bad_alloc Internal resource allocation fails.
+///
+/// \param renderer DNS message rendering context that encapsulates the
+/// output buffer and name compression information.
+void
+AFSDB::toWire(AbstractMessageRenderer& renderer) const {
+ renderer.writeUint16(subtype_);
+ renderer.writeName(server_, false);
+}
+
+/// \brief Compare two instances of \c AFSDB RDATA.
+///
+/// See documentation in \c Rdata.
+int
+AFSDB::compare(const Rdata& other) const {
+ const AFSDB& other_afsdb = dynamic_cast<const AFSDB&>(other);
+ if (subtype_ < other_afsdb.subtype_) {
+ return (-1);
+ } else if (subtype_ > other_afsdb.subtype_) {
+ return (1);
+ }
+
+ return (compareNames(server_, other_afsdb.server_));
+}
+
+const Name&
+AFSDB::getServer() const {
+ return (server_);
+}
+
+uint16_t
+AFSDB::getSubtype() const {
+ return (subtype_);
+}
+
+} // end of namespace "generic"
+} // end of namespace "rdata"
+} // end of namespace "dns"
+} // end of namespace "isc"
+// 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.
+
+#include <config.h>
+
+#include <boost/lexical_cast.hpp>
+#include <boost/algorithm/string.hpp>
+
+#include <exceptions/exceptions.h>
+
+#include <util/buffer.h>
+#include <dns/name.h>
+#include <dns/messagerenderer.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+
+#include <dns/rdata/generic/detail/char_string.h>
+
+using namespace std;
+using boost::lexical_cast;
+using namespace isc::util;
+
+namespace isc {
+namespace dns {
+namespace rdata {
+namespace generic {
+
+struct CAAImpl {
+ // straightforward representation of CAA RDATA fields
+ CAAImpl(uint8_t flags, const std::string& tag,
+ const detail::CharStringData& value) :
+ flags_(flags),
+ tag_(tag),
+ value_(value)
+ {
+ if ((sizeof(flags) + 1 + tag_.size() + value_.size()) > 65535) {
+ isc_throw(InvalidRdataLength,
+ "CAA Value field is too large: " << value_.size());
+ }
+ }
+
+ uint8_t flags_;
+ const std::string tag_;
+ const detail::CharStringData value_;
+};
+
+// helper function for string and lexer constructors
+CAAImpl*
+CAA::constructFromLexer(MasterLexer& lexer) {
+ const uint32_t flags =
+ lexer.getNextToken(MasterToken::NUMBER).getNumber();
+ if (flags > 255) {
+ isc_throw(InvalidRdataText,
+ "CAA flags field out of range");
+ }
+
+ // Tag field must not be empty.
+ const std::string tag =
+ lexer.getNextToken(MasterToken::STRING).getString();
+ if (tag.empty()) {
+ isc_throw(InvalidRdataText, "CAA tag field is empty");
+ } else if (tag.size() > 255) {
+ isc_throw(InvalidRdataText,
+ "CAA tag field is too large: " << tag.size());
+ }
+
+ // Value field may be empty.
+ detail::CharStringData value;
+ MasterToken token = lexer.getNextToken(MasterToken::QSTRING, true);
+ if ((token.getType() != MasterToken::END_OF_FILE) &&
+ (token.getType() != MasterToken::END_OF_LINE))
+ {
+ detail::stringToCharStringData(token.getStringRegion(), value);
+ }
+
+ return (new CAAImpl(flags, tag, value));
+}
+
+/// \brief Constructor from string.
+///
+/// The given string must represent a valid CAA 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.
+///
+/// The Flags, Tag and Value fields must be within their valid ranges,
+/// but are not constrained to the values defined in RFC6844. The Tag
+/// field must not be empty.
+///
+/// \throw InvalidRdataText if any fields are missing, out of their
+/// valid ranges, incorrect, or empty.
+///
+/// \param caa_str A string containing the RDATA to be created
+CAA::CAA(const string& caa_str) :
+ impl_(NULL)
+{
+ // We use auto_ptr here because if there is an exception in this
+ // constructor, the destructor is not called and there could be a
+ // leak of the CAAImpl that constructFromLexer() returns.
+ std::auto_ptr<CAAImpl> impl_ptr(NULL);
+
+ try {
+ std::istringstream ss(caa_str);
+ MasterLexer lexer;
+ lexer.pushSource(ss);
+
+ impl_ptr.reset(constructFromLexer(lexer));
+
+ if (lexer.getNextToken().getType() != MasterToken::END_OF_FILE) {
+ isc_throw(InvalidRdataText, "extra input text for CAA: "
+ << caa_str);
+ }
+ } catch (const MasterLexer::LexerError& ex) {
+ isc_throw(InvalidRdataText, "Failed to construct CAA from '" <<
+ caa_str << "': " << ex.what());
+ }
+
+ impl_ = impl_ptr.release();
+}
+
+/// \brief Constructor with a context of MasterLexer.
+///
+/// The \c lexer should point to the beginning of valid textual
+/// representation of an CAA RDATA.
+///
+/// \throw MasterLexer::LexerError General parsing error such as missing
+/// field.
+/// \throw InvalidRdataText Fields are out of their valid ranges,
+/// incorrect, or empty.
+///
+/// \param lexer A \c MasterLexer object parsing a master file for the
+/// RDATA to be created
+CAA::CAA(MasterLexer& lexer, const Name*,
+ MasterLoader::Options, MasterLoaderCallbacks&) :
+ impl_(constructFromLexer(lexer))
+{
+}
+
+/// \brief Constructor from InputBuffer.
+///
+/// The passed buffer must contain a valid CAA RDATA.
+///
+/// The Flags, Tag and Value fields must be within their valid ranges,
+/// but are not constrained to the values defined in RFC6844. The Tag
+/// field must not be empty.
+CAA::CAA(InputBuffer& buffer, size_t rdata_len) {
+ if (rdata_len < 2) {
+ isc_throw(InvalidRdataLength, "CAA record too short");
+ }
+
+ const uint8_t flags = buffer.readUint8();
+ const uint8_t tag_length = buffer.readUint8();
+ rdata_len -= 2;
+ if (tag_length == 0) {
+ isc_throw(InvalidRdataText, "CAA tag field is empty");
+ }
+
+ if (rdata_len < tag_length) {
+ isc_throw(InvalidRdataLength,
+ "RDATA is too short for CAA tag field");
+ }
+
+ std::vector<uint8_t> tag_vec(tag_length);
+ buffer.readData(&tag_vec[0], tag_length);
+ std::string tag(tag_vec.begin(), tag_vec.end());
+ rdata_len -= tag_length;
+
+ detail::CharStringData value;
+ value.resize(rdata_len);
+ if (rdata_len > 0) {
+ buffer.readData(&value[0], rdata_len);
+ }
+
+ impl_ = new CAAImpl(flags, tag, value);
+}
+
+CAA::CAA(uint8_t flags, const std::string& tag, const std::string& value) :
+ impl_(NULL)
+{
+ if (tag.empty()) {
+ isc_throw(isc::InvalidParameter,
+ "CAA tag field is empty");
+ } else if (tag.size() > 255) {
+ isc_throw(isc::InvalidParameter,
+ "CAA tag field is too large: " << tag.size());
+ }
+
+ MasterToken::StringRegion region;
+ region.beg = &value[0]; // note std ensures this works even if str is empty
+ region.len = value.size();
+
+ detail::CharStringData value_vec;
+ detail::stringToCharStringData(region, value_vec);
+
+ impl_ = new CAAImpl(flags, tag, value_vec);
+}
+
+CAA::CAA(const CAA& other) :
+ Rdata(), impl_(new CAAImpl(*other.impl_))
+{}
+
+CAA&
+CAA::operator=(const CAA& source) {
+ if (this == &source) {
+ return (*this);
+ }
+
+ CAAImpl* newimpl = new CAAImpl(*source.impl_);
+ delete impl_;
+ impl_ = newimpl;
+
+ return (*this);
+}
+
+CAA::~CAA() {
+ delete impl_;
+}
+
+void
+CAA::toWire(OutputBuffer& buffer) const {
+ buffer.writeUint8(impl_->flags_);
+
+ // The constructors must ensure that the tag field is not empty.
+ assert(!impl_->tag_.empty());
+ buffer.writeUint8(impl_->tag_.size());
+ buffer.writeData(&impl_->tag_[0], impl_->tag_.size());
+
+ if (!impl_->value_.empty()) {
+ buffer.writeData(&impl_->value_[0],
+ impl_->value_.size());
+ }
+}
+
+void
+CAA::toWire(AbstractMessageRenderer& renderer) const {
+ renderer.writeUint8(impl_->flags_);
+
+ // The constructors must ensure that the tag field is not empty.
+ assert(!impl_->tag_.empty());
+ renderer.writeUint8(impl_->tag_.size());
+ renderer.writeData(&impl_->tag_[0], impl_->tag_.size());
+
+ if (!impl_->value_.empty()) {
+ renderer.writeData(&impl_->value_[0],
+ impl_->value_.size());
+ }
+}
+
+std::string
+CAA::toText() const {
+ std::string result;
+
+ result = lexical_cast<std::string>(static_cast<int>(impl_->flags_));
+ result += " " + impl_->tag_;
+ result += " \"" + detail::charStringDataToString(impl_->value_) + "\"";
+
+ return (result);
+}
+
+int
+CAA::compare(const Rdata& other) const {
+ const CAA& other_caa = dynamic_cast<const CAA&>(other);
+
+ if (impl_->flags_ < other_caa.impl_->flags_) {
+ return (-1);
+ } else if (impl_->flags_ > other_caa.impl_->flags_) {
+ return (1);
+ }
+
+ // Do a case-insensitive compare of the tag strings.
+ const int result = boost::ilexicographical_compare
+ <std::string, std::string>(impl_->tag_, other_caa.impl_->tag_);
+ if (result != 0) {
+ return (result);
+ }
+
+ return (detail::compareCharStringDatas(impl_->value_,
+ other_caa.impl_->value_));
+}
+
+uint8_t
+CAA::getFlags() const {
+ return (impl_->flags_);
+}
+
+const std::string&
+CAA::getTag() const {
+ return (impl_->tag_);
+}
+
+const std::vector<uint8_t>&
+CAA::getValue() const {
+ return (impl_->value_);
+}
+
+} // end of namespace "generic"
+} // end of namespace "rdata"
+} // end of namespace "dns"
+} // end of namespace "isc"
+// 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 <config.h>
+
+#include <string>
+
+#include <util/buffer.h>
+#include <dns/name.h>
+#include <dns/messagerenderer.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+
+#include <dns/rdata/generic/detail/lexer_util.h>
+
+using namespace std;
+using namespace isc::util;
+using isc::dns::rdata::generic::detail::createNameFromLexer;
+
+namespace isc {
+namespace dns {
+namespace rdata {
+namespace generic {
+
+/// \brief Constructor from string.
+///
+/// The given string must represent a valid CNAME 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.
+///
+/// The CNAME must be absolute since there's no parameter that specifies
+/// the origin name; if it is not absolute, \c MissingNameOrigin
+/// exception will be thrown. These must not be represented as a quoted
+/// string.
+///
+/// \throw Others Exception from the Name and RRTTL constructors.
+/// \throw InvalidRdataText Other general syntax errors.
+CNAME::CNAME(const std::string& namestr) :
+ // Fill in dummy name and replace it soon below.
+ cname_(Name::ROOT_NAME())
+{
+ try {
+ std::istringstream ss(namestr);
+ MasterLexer lexer;
+ lexer.pushSource(ss);
+
+ cname_ = createNameFromLexer(lexer, NULL);
+
+ if (lexer.getNextToken().getType() != MasterToken::END_OF_FILE) {
+ isc_throw(InvalidRdataText, "extra input text for CNAME: "
+ << namestr);
+ }
+ } catch (const MasterLexer::LexerError& ex) {
+ isc_throw(InvalidRdataText, "Failed to construct CNAME from '" <<
+ namestr << "': " << ex.what());
+ }
+}
+
+CNAME::CNAME(InputBuffer& buffer, size_t) :
+ Rdata(), cname_(buffer)
+{
+ // we don't need rdata_len for parsing. if necessary, the caller will
+ // check consistency.
+}
+
+/// \brief Constructor with a context of MasterLexer.
+///
+/// The \c lexer should point to the beginning of valid textual
+/// representation of a CNAME RDATA. The CNAME field can be
+/// non-absolute if \c origin is non-NULL, in which case \c origin is
+/// used to make it absolute. It must not be represented as a quoted
+/// string.
+///
+/// \throw MasterLexer::LexerError General parsing error such as missing field.
+/// \throw Other Exceptions from the Name and RRTTL constructors if
+/// construction of textual fields as these objects fail.
+///
+/// \param lexer A \c MasterLexer object parsing a master file for the
+/// RDATA to be created
+/// \param origin If non NULL, specifies the origin of CNAME when it
+/// is non-absolute.
+CNAME::CNAME(MasterLexer& lexer, const Name* origin,
+ MasterLoader::Options, MasterLoaderCallbacks&) :
+ cname_(createNameFromLexer(lexer, origin))
+{}
+
+CNAME::CNAME(const CNAME& other) :
+ Rdata(), cname_(other.cname_)
+{}
+
+CNAME::CNAME(const Name& cname) :
+ cname_(cname)
+{}
+
+void
+CNAME::toWire(OutputBuffer& buffer) const {
+ cname_.toWire(buffer);
+}
+
+void
+CNAME::toWire(AbstractMessageRenderer& renderer) const {
+ renderer.writeName(cname_);
+}
+
+string
+CNAME::toText() const {
+ return (cname_.toText());
+}
+
+int
+CNAME::compare(const Rdata& other) const {
+ const CNAME& other_cname = dynamic_cast<const CNAME&>(other);
+
+ return (compareNames(cname_, other_cname.cname_));
+}
+
+const Name&
+CNAME::getCname() const {
+ return (cname_);
+}
+
+} // end of namespace "generic"
+} // end of namespace "rdata"
+} // end of namespace "dns"
+} // end of namespace "isc"
+// 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 <string>
+
+#include <util/buffer.h>
+#include <util/encode/hex.h>
+
+#include <dns/messagerenderer.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+
+#include <dns/rdata/generic/detail/ds_like.h>
+
+using namespace std;
+using namespace isc::util;
+using namespace isc::util::encode;
+using namespace isc::dns::rdata::generic::detail;
+
+namespace isc {
+namespace dns {
+namespace rdata {
+namespace generic {
+
+/// \brief Constructor from string.
+///
+/// A copy of the implementation object is allocated and constructed.
+DLV::DLV(const std::string& ds_str) :
+ impl_(new DLVImpl(ds_str))
+{}
+
+/// \brief Constructor from wire-format data.
+///
+/// A copy of the implementation object is allocated and constructed.
+DLV::DLV(InputBuffer& buffer, size_t rdata_len) :
+ impl_(new DLVImpl(buffer, rdata_len))
+{}
+
+DLV::DLV(MasterLexer& lexer, const Name* origin, MasterLoader::Options options,
+ MasterLoaderCallbacks& callbacks) :
+ impl_(new DLVImpl(lexer, origin, options, callbacks))
+{}
+
+/// \brief Copy constructor
+///
+/// A copy of the implementation object is allocated and constructed.
+DLV::DLV(const DLV& source) :
+ Rdata(), impl_(new DLVImpl(*source.impl_))
+{}
+
+/// \brief Assignment operator
+///
+/// PIMPL-induced logic
+DLV&
+DLV::operator=(const DLV& source) {
+ if (this == &source) {
+ return (*this);
+ }
+
+ DLVImpl* newimpl = new DLVImpl(*source.impl_);
+ delete impl_;
+ impl_ = newimpl;
+
+ return (*this);
+}
+
+/// \brief Destructor
+///
+/// Deallocates an internal resource.
+DLV::~DLV() {
+ delete impl_;
+}
+
+/// \brief Convert the \c DLV to a string.
+///
+/// A pass-thru to the corresponding implementation method.
+string
+DLV::toText() const {
+ return (impl_->toText());
+}
+
+/// \brief Render the \c DLV in the wire format to a OutputBuffer object
+///
+/// A pass-thru to the corresponding implementation method.
+void
+DLV::toWire(OutputBuffer& buffer) const {
+ impl_->toWire(buffer);
+}
+
+/// \brief Render the \c DLV in the wire format to a AbstractMessageRenderer
+/// object
+///
+/// A pass-thru to the corresponding implementation method.
+void
+DLV::toWire(AbstractMessageRenderer& renderer) const {
+ impl_->toWire(renderer);
+}
+
+/// \brief Compare two instances of \c DLV RDATA.
+///
+/// The type check is performed here. Otherwise, a pass-thru to the
+/// corresponding implementation method.
+int
+DLV::compare(const Rdata& other) const {
+ const DLV& other_ds = dynamic_cast<const DLV&>(other);
+
+ return (impl_->compare(*other_ds.impl_));
+}
+
+/// \brief Tag accessor
+uint16_t
+DLV::getTag() const {
+ return (impl_->getTag());
+}
+
+} // end of namespace "generic"
+} // end of namespace "rdata"
+} // end of namespace "dns"
+} // end of namespace "isc"
+// 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 <config.h>
+
+#include <string>
+
+#include <util/buffer.h>
+#include <dns/name.h>
+#include <dns/messagerenderer.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+
+#include <dns/rdata/generic/detail/lexer_util.h>
+
+using namespace std;
+using namespace isc::util;
+using isc::dns::rdata::generic::detail::createNameFromLexer;
+
+namespace isc {
+namespace dns {
+namespace rdata {
+namespace generic {
+
+/// \brief Constructor from string.
+///
+/// The given string must represent a valid DNAME 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.
+///
+/// The TARGET must be absolute since there's no parameter that specifies
+/// the origin name; if it is not absolute, \c MissingNameOrigin
+/// exception will be thrown. These must not be represented as a quoted
+/// string.
+///
+/// \throw Others Exception from the Name and RRTTL constructors.
+/// \throw InvalidRdataText Other general syntax errors.
+DNAME::DNAME(const std::string& namestr) :
+ // Fill in dummy name and replace it soon below.
+ dname_(Name::ROOT_NAME())
+{
+ try {
+ std::istringstream ss(namestr);
+ MasterLexer lexer;
+ lexer.pushSource(ss);
+
+ dname_ = createNameFromLexer(lexer, NULL);
+
+ if (lexer.getNextToken().getType() != MasterToken::END_OF_FILE) {
+ isc_throw(InvalidRdataText, "extra input text for DNAME: "
+ << namestr);
+ }
+ } catch (const MasterLexer::LexerError& ex) {
+ isc_throw(InvalidRdataText, "Failed to construct DNAME from '" <<
+ namestr << "': " << ex.what());
+ }
+}
+
+DNAME::DNAME(InputBuffer& buffer, size_t) :
+ dname_(buffer)
+{
+ // we don't need rdata_len for parsing. if necessary, the caller will
+ // check consistency.
+}
+
+/// \brief Constructor with a context of MasterLexer.
+///
+/// The \c lexer should point to the beginning of valid textual
+/// representation of a DNAME RDATA. The TARGET field can be
+/// non-absolute if \c origin is non-NULL, in which case \c origin is
+/// used to make it absolute. It must not be represented as a quoted
+/// string.
+///
+/// \throw MasterLexer::LexerError General parsing error such as missing field.
+/// \throw Other Exceptions from the Name and RRTTL constructors if
+/// construction of textual fields as these objects fail.
+///
+/// \param lexer A \c MasterLexer object parsing a master file for the
+/// RDATA to be created
+/// \param origin If non NULL, specifies the origin of TARGET when it
+/// is non-absolute.
+DNAME::DNAME(MasterLexer& lexer, const Name* origin,
+ MasterLoader::Options, MasterLoaderCallbacks&) :
+ dname_(createNameFromLexer(lexer, origin))
+{}
+
+DNAME::DNAME(const DNAME& other) :
+ Rdata(), dname_(other.dname_)
+{}
+
+DNAME::DNAME(const Name& dname) :
+ dname_(dname)
+{}
+
+void
+DNAME::toWire(OutputBuffer& buffer) const {
+ dname_.toWire(buffer);
+}
+
+void
+DNAME::toWire(AbstractMessageRenderer& renderer) const {
+ // Type DNAME is not "well-known", and name compression must be disabled
+ // per RFC3597.
+ renderer.writeName(dname_, false);
+}
+
+string
+DNAME::toText() const {
+ return (dname_.toText());
+}
+
+int
+DNAME::compare(const Rdata& other) const {
+ const DNAME& other_dname = dynamic_cast<const DNAME&>(other);
+
+ return (compareNames(dname_, other_dname.dname_));
+}
+
+const Name&
+DNAME::getDname() const {
+ return (dname_);
+}
+
+} // end of namespace "generic"
+} // end of namespace "rdata"
+} // end of namespace "dns"
+} // end of namespace "isc"
+// 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 <iostream>
+#include <string>
+#include <sstream>
+#include <vector>
+
+#include <boost/lexical_cast.hpp>
+#include <boost/foreach.hpp>
+
+#include <util/encode/base64.h>
+#include <util/buffer.h>
+#include <dns/messagerenderer.h>
+#include <dns/name.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+
+#include <memory>
+
+#include <stdio.h>
+#include <time.h>
+
+using namespace std;
+using namespace isc::util;
+using namespace isc::util::encode;
+
+namespace isc {
+namespace dns {
+namespace rdata {
+namespace generic {
+
+struct DNSKEYImpl {
+ // straightforward representation of DNSKEY RDATA fields
+ DNSKEYImpl(uint16_t flags, uint8_t protocol, uint8_t algorithm,
+ const vector<uint8_t>& keydata) :
+ flags_(flags), protocol_(protocol), algorithm_(algorithm),
+ keydata_(keydata)
+ {}
+
+ uint16_t flags_;
+ uint8_t protocol_;
+ uint8_t algorithm_;
+ const vector<uint8_t> keydata_;
+};
+
+/// \brief Constructor from string.
+///
+/// The given string must represent a valid DNSKEY 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.
+///
+/// The Protocol and Algorithm fields must be within their valid
+/// ranges. The Public Key field must be present and must contain a
+/// Base64 encoding of the public key. Whitespace is allowed within the
+/// Base64 text.
+///
+/// It is okay for the key data to be missing. Note: BIND 9 also accepts
+/// DNSKEY missing key data. While the RFC is silent in this case, and it
+/// may be debatable what an implementation should do, but since this field
+/// is algorithm dependent and this implementations doesn't reject unknown
+/// algorithms, it's lenient here.
+///
+/// \throw InvalidRdataText if any fields are out of their valid range,
+/// or are incorrect.
+///
+/// \param dnskey_str A string containing the RDATA to be created
+DNSKEY::DNSKEY(const std::string& dnskey_str) :
+ impl_(NULL)
+{
+ // We use auto_ptr here because if there is an exception in this
+ // constructor, the destructor is not called and there could be a
+ // leak of the DNSKEYImpl that constructFromLexer() returns.
+ std::auto_ptr<DNSKEYImpl> impl_ptr(NULL);
+
+ try {
+ std::istringstream ss(dnskey_str);
+ MasterLexer lexer;
+ lexer.pushSource(ss);
+
+ impl_ptr.reset(constructFromLexer(lexer));
+
+ if (lexer.getNextToken().getType() != MasterToken::END_OF_FILE) {
+ isc_throw(InvalidRdataText,
+ "Extra input text for DNSKEY: " << dnskey_str);
+ }
+ } catch (const MasterLexer::LexerError& ex) {
+ isc_throw(InvalidRdataText,
+ "Failed to construct DNSKEY from '" << dnskey_str << "': "
+ << ex.what());
+ }
+
+ impl_ = impl_ptr.release();
+}
+
+/// \brief Constructor from InputBuffer.
+///
+/// The passed buffer must contain a valid DNSKEY RDATA.
+///
+/// The Protocol and Algorithm fields are not checked for unknown
+/// values. It is okay for the key data to be missing (see the description
+/// of the constructor from string).
+DNSKEY::DNSKEY(InputBuffer& buffer, size_t rdata_len) :
+ impl_(NULL)
+{
+ if (rdata_len < 4) {
+ isc_throw(InvalidRdataLength, "DNSKEY too short: " << rdata_len);
+ }
+
+ const uint16_t flags = buffer.readUint16();
+ const uint16_t protocol = buffer.readUint8();
+ const uint16_t algorithm = buffer.readUint8();
+
+ rdata_len -= 4;
+
+ vector<uint8_t> keydata;
+ // If key data is missing, it's OK. See the API documentation of the
+ // constructor.
+ if (rdata_len > 0) {
+ keydata.resize(rdata_len);
+ buffer.readData(&keydata[0], rdata_len);
+ }
+
+ impl_ = new DNSKEYImpl(flags, protocol, algorithm, keydata);
+}
+
+/// \brief Constructor with a context of MasterLexer.
+///
+/// The \c lexer should point to the beginning of valid textual
+/// representation of an DNSKEY RDATA.
+///
+/// See \c DNSKEY::DNSKEY(const std::string&) for description of the
+/// expected RDATA fields.
+///
+/// \throw MasterLexer::LexerError General parsing error such as
+/// missing field.
+/// \throw InvalidRdataText if any fields are out of their valid range,
+/// or are incorrect.
+///
+/// \param lexer A \c MasterLexer object parsing a master file for the
+/// RDATA to be created
+DNSKEY::DNSKEY(MasterLexer& lexer, const Name*,
+ MasterLoader::Options, MasterLoaderCallbacks&) :
+ impl_(NULL)
+{
+ impl_ = constructFromLexer(lexer);
+}
+
+DNSKEYImpl*
+DNSKEY::constructFromLexer(MasterLexer& lexer) {
+ const uint32_t flags = lexer.getNextToken(MasterToken::NUMBER).getNumber();
+ if (flags > 0xffff) {
+ isc_throw(InvalidRdataText,
+ "DNSKEY flags out of range: " << flags);
+ }
+
+ const uint32_t protocol =
+ lexer.getNextToken(MasterToken::NUMBER).getNumber();
+ if (protocol > 0xff) {
+ isc_throw(InvalidRdataText,
+ "DNSKEY protocol out of range: " << protocol);
+ }
+
+ const uint32_t algorithm =
+ lexer.getNextToken(MasterToken::NUMBER).getNumber();
+ if (algorithm > 0xff) {
+ isc_throw(InvalidRdataText,
+ "DNSKEY algorithm out of range: " << algorithm);
+ }
+
+ std::string keydata_str;
+ std::string keydata_substr;
+ while (true) {
+ const MasterToken& token =
+ lexer.getNextToken(MasterToken::STRING, true);
+ if ((token.getType() == MasterToken::END_OF_FILE) ||
+ (token.getType() == MasterToken::END_OF_LINE)) {
+ break;
+ }
+
+ // token is now assured to be of type STRING.
+
+ token.getString(keydata_substr);
+ keydata_str.append(keydata_substr);
+ }
+
+ lexer.ungetToken();
+
+ vector<uint8_t> keydata;
+ // If key data is missing, it's OK. See the API documentation of the
+ // constructor.
+ if (keydata_str.size() > 0) {
+ decodeBase64(keydata_str, keydata);
+ }
+
+ return (new DNSKEYImpl(flags, protocol, algorithm, keydata));
+}
+
+DNSKEY::DNSKEY(const DNSKEY& source) :
+ Rdata(), impl_(new DNSKEYImpl(*source.impl_))
+{}
+
+DNSKEY&
+DNSKEY::operator=(const DNSKEY& source) {
+ if (this == &source) {
+ return (*this);
+ }
+
+ DNSKEYImpl* newimpl = new DNSKEYImpl(*source.impl_);
+ delete impl_;
+ impl_ = newimpl;
+
+ return (*this);
+}
+
+DNSKEY::~DNSKEY() {
+ delete impl_;
+}
+
+string
+DNSKEY::toText() const {
+ return (boost::lexical_cast<string>(static_cast<int>(impl_->flags_)) +
+ " " + boost::lexical_cast<string>(static_cast<int>(impl_->protocol_)) +
+ " " + boost::lexical_cast<string>(static_cast<int>(impl_->algorithm_)) +
+ " " + encodeBase64(impl_->keydata_));
+}
+
+void
+DNSKEY::toWire(OutputBuffer& buffer) const {
+ buffer.writeUint16(impl_->flags_);
+ buffer.writeUint8(impl_->protocol_);
+ buffer.writeUint8(impl_->algorithm_);
+ buffer.writeData(&impl_->keydata_[0], impl_->keydata_.size());
+}
+
+void
+DNSKEY::toWire(AbstractMessageRenderer& renderer) const {
+ renderer.writeUint16(impl_->flags_);
+ renderer.writeUint8(impl_->protocol_);
+ renderer.writeUint8(impl_->algorithm_);
+ renderer.writeData(&impl_->keydata_[0], impl_->keydata_.size());
+}
+
+int
+DNSKEY::compare(const Rdata& other) const {
+ const DNSKEY& other_dnskey = dynamic_cast<const DNSKEY&>(other);
+
+ if (impl_->flags_ != other_dnskey.impl_->flags_) {
+ return (impl_->flags_ < other_dnskey.impl_->flags_ ? -1 : 1);
+ }
+ if (impl_->protocol_ != other_dnskey.impl_->protocol_) {
+ return (impl_->protocol_ < other_dnskey.impl_->protocol_ ? -1 : 1);
+ }
+ if (impl_->algorithm_ != other_dnskey.impl_->algorithm_) {
+ return (impl_->algorithm_ < other_dnskey.impl_->algorithm_ ? -1 : 1);
+ }
+
+ const size_t this_len = impl_->keydata_.size();
+ const size_t other_len = other_dnskey.impl_->keydata_.size();
+ const size_t cmplen = min(this_len, other_len);
+ const int cmp = memcmp(&impl_->keydata_[0],
+ &other_dnskey.impl_->keydata_[0], cmplen);
+ if (cmp != 0) {
+ return (cmp);
+ } else {
+ return ((this_len == other_len) ? 0 : (this_len < other_len) ? -1 : 1);
+ }
+}
+
+uint16_t
+DNSKEY::getTag() const {
+ if (impl_->algorithm_ == 1) {
+ // See RFC 4034 appendix B.1 for why the key data must contain
+ // at least 4 bytes with RSA/MD5: 3 trailing bytes to extract
+ // the tag from, and 1 byte of exponent length subfield before
+ // modulus.
+ const int len = impl_->keydata_.size();
+ if (len < 4) {
+ isc_throw(isc::OutOfRange,
+ "DNSKEY keydata too short for tag extraction");
+ }
+
+ return ((impl_->keydata_[len - 3] << 8) + impl_->keydata_[len - 2]);
+ }
+
+ uint32_t ac = impl_->flags_;
+ ac += (impl_->protocol_ << 8);
+ ac += impl_->algorithm_;
+
+ const size_t size = impl_->keydata_.size();
+ for (size_t i = 0; i < size; i ++) {
+ ac += (i & 1) ? impl_->keydata_[i] : (impl_->keydata_[i] << 8);
+ }
+ ac += (ac >> 16) & 0xffff;
+ return (ac & 0xffff);
+}
+
+uint16_t
+DNSKEY::getFlags() const {
+ return (impl_->flags_);
+}
+
+uint8_t
+DNSKEY::getAlgorithm() const {
+ return (impl_->algorithm_);
+}
+
+} // end of namespace "generic"
+} // end of namespace "rdata"
+} // end of namespace "dns"
+} // end of namespace "isc"
+// 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 <string>
+
+#include <util/buffer.h>
+#include <util/encode/hex.h>
+
+#include <dns/messagerenderer.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+
+#include <dns/rdata/generic/detail/ds_like.h>
+
+using namespace std;
+using namespace isc::util;
+using namespace isc::util::encode;
+using namespace isc::dns::rdata::generic::detail;
+
+namespace isc {
+namespace dns {
+namespace rdata {
+namespace generic {
+
+DS::DS(const std::string& ds_str) :
+ impl_(new DSImpl(ds_str))
+{}
+
+DS::DS(InputBuffer& buffer, size_t rdata_len) :
+ impl_(new DSImpl(buffer, rdata_len))
+{}
+
+DS::DS(MasterLexer& lexer, const Name* origin, MasterLoader::Options options,
+ MasterLoaderCallbacks& callbacks) :
+ impl_(new DSImpl(lexer, origin, options, callbacks))
+{}
+
+DS::DS(const DS& source) :
+ Rdata(), impl_(new DSImpl(*source.impl_))
+{}
+
+DS&
+DS::operator=(const DS& source) {
+ if (this == &source) {
+ return (*this);
+ }
+
+ DSImpl* newimpl = new DSImpl(*source.impl_);
+ delete impl_;
+ impl_ = newimpl;
+
+ return (*this);
+}
+
+DS::~DS() {
+ delete impl_;
+}
+
+string
+DS::toText() const {
+ return (impl_->toText());
+}
+
+void
+DS::toWire(OutputBuffer& buffer) const {
+ impl_->toWire(buffer);
+}
+
+void
+DS::toWire(AbstractMessageRenderer& renderer) const {
+ impl_->toWire(renderer);
+}
+
+int
+DS::compare(const Rdata& other) const {
+ const DS& other_ds = dynamic_cast<const DS&>(other);
+
+ return (impl_->compare(*other_ds.impl_));
+}
+
+uint16_t
+DS::getTag() const {
+ return (impl_->getTag());
+}
+
+} // end of namespace "generic"
+} // end of namespace "rdata"
+} // end of namespace "dns"
+} // end of namespace "isc"
+// 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 <config.h>
+
+#include <exceptions/exceptions.h>
+#include <dns/exceptions.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+#include <dns/rdata/generic/detail/char_string.h>
+#include <util/buffer.h>
+
+using namespace std;
+using namespace isc::util;
+using namespace isc::dns;
+
+namespace isc {
+namespace dns {
+namespace rdata {
+namespace generic {
+
+class HINFOImpl {
+public:
+ HINFOImpl(const std::string& hinfo_str) {
+ std::istringstream ss(hinfo_str);
+ MasterLexer lexer;
+ lexer.pushSource(ss);
+
+ try {
+ parseHINFOData(lexer);
+ // Should be at end of data now
+ if (lexer.getNextToken(MasterToken::QSTRING, true).getType() !=
+ MasterToken::END_OF_FILE) {
+ isc_throw(InvalidRdataText,
+ "Invalid HINFO text format: too many fields.");
+ }
+ } catch (const MasterLexer::LexerError& ex) {
+ isc_throw(InvalidRdataText, "Failed to construct HINFO RDATA from "
+ << hinfo_str << "': " << ex.what());
+ }
+ }
+
+ HINFOImpl(InputBuffer& buffer, size_t rdata_len) {
+ rdata_len -= detail::bufferToCharString(buffer, rdata_len, cpu);
+ rdata_len -= detail::bufferToCharString(buffer, rdata_len, os);
+ if (rdata_len != 0) {
+ isc_throw(isc::dns::DNSMessageFORMERR, "Error in parsing " <<
+ "HINFO RDATA: bytes left at end: " <<
+ static_cast<int>(rdata_len));
+ }
+ }
+
+ HINFOImpl(MasterLexer& lexer)
+ {
+ parseHINFOData(lexer);
+ }
+
+private:
+ void
+ parseHINFOData(MasterLexer& lexer) {
+ MasterToken token = lexer.getNextToken(MasterToken::QSTRING);
+ stringToCharString(token.getStringRegion(), cpu);
+ token = lexer.getNextToken(MasterToken::QSTRING);
+ stringToCharString(token.getStringRegion(), os);
+ }
+
+public:
+ detail::CharString cpu;
+ detail::CharString os;
+};
+
+HINFO::HINFO(const std::string& hinfo_str) : impl_(new HINFOImpl(hinfo_str))
+{}
+
+
+HINFO::HINFO(InputBuffer& buffer, size_t rdata_len) :
+ impl_(new HINFOImpl(buffer, rdata_len))
+{}
+
+HINFO::HINFO(const HINFO& source):
+ Rdata(), impl_(new HINFOImpl(*source.impl_))
+{
+}
+
+HINFO::HINFO(MasterLexer& lexer, const Name*,
+ MasterLoader::Options, MasterLoaderCallbacks&) :
+ impl_(new HINFOImpl(lexer))
+{}
+
+HINFO&
+HINFO::operator=(const HINFO& source)
+{
+ impl_.reset(new HINFOImpl(*source.impl_));
+ return (*this);
+}
+
+HINFO::~HINFO() {
+}
+
+std::string
+HINFO::toText() const {
+ string result;
+ result += "\"";
+ result += detail::charStringToString(impl_->cpu);
+ result += "\" \"";
+ result += detail::charStringToString(impl_->os);
+ result += "\"";
+ return (result);
+}
+
+void
+HINFO::toWire(OutputBuffer& buffer) const {
+ toWireHelper(buffer);
+}
+
+void
+HINFO::toWire(AbstractMessageRenderer& renderer) const {
+ toWireHelper(renderer);
+}
+
+int
+HINFO::compare(const Rdata& other) const {
+ const HINFO& other_hinfo = dynamic_cast<const HINFO&>(other);
+
+ const int cmp = compareCharStrings(impl_->cpu, other_hinfo.impl_->cpu);
+ if (cmp != 0) {
+ return (cmp);
+ }
+ return (compareCharStrings(impl_->os, other_hinfo.impl_->os));
+}
+
+const std::string
+HINFO::getCPU() const {
+ return (detail::charStringToString(impl_->cpu));
+}
+
+const std::string
+HINFO::getOS() const {
+ return (detail::charStringToString(impl_->os));
+}
+
+template <typename T>
+void
+HINFO::toWireHelper(T& outputer) const {
+ outputer.writeData(&impl_->cpu[0], impl_->cpu.size());
+ outputer.writeData(&impl_->os[0], impl_->os.size());
+}
+
+} // end of namespace "generic"
+} // end of namespace "rdata"
+} // end of namespace "dns"
+} // end of namespace "isc"
+// Copyright (C) 2011-2013 Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// 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 <string>
+#include <sstream>
+
+#include <util/buffer.h>
+
+#include <dns/messagerenderer.h>
+#include <dns/name.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+#include <dns/rdata/generic/detail/lexer_util.h>
+
+using namespace std;
+using namespace isc::dns;
+using namespace isc::util;
+using isc::dns::rdata::generic::detail::createNameFromLexer;
+
+namespace isc {
+namespace dns {
+namespace rdata {
+namespace generic {
+
+/// \brief Constructor from string.
+///
+/// \c minfo_str must be formatted as follows:
+/// \code <rmailbox name> <emailbox name>
+/// \endcode
+/// where both fields must represent a valid domain name.
+///
+/// An example of valid string is:
+/// \code "rmail.example.com. email.example.com." \endcode
+///
+/// \throw InvalidRdataText The number of RDATA fields (must be 2) is
+/// incorrect.
+/// \throw std::bad_alloc Memory allocation for names fails.
+/// \throw Other The constructor of the \c Name class will throw if the
+/// names in the string is invalid.
+MINFO::MINFO(const std::string& minfo_str) :
+ // We cannot construct both names in the initialization list due to the
+ // necessary text processing, so we have to initialize them with a dummy
+ // name and replace them later.
+ rmailbox_(Name::ROOT_NAME()), emailbox_(Name::ROOT_NAME())
+{
+ try {
+ std::istringstream ss(minfo_str);
+ MasterLexer lexer;
+ lexer.pushSource(ss);
+
+ rmailbox_ = createNameFromLexer(lexer, NULL);
+ emailbox_ = createNameFromLexer(lexer, NULL);
+
+ if (lexer.getNextToken().getType() != MasterToken::END_OF_FILE) {
+ isc_throw(InvalidRdataText, "extra input text for MINFO: "
+ << minfo_str);
+ }
+ } catch (const MasterLexer::LexerError& ex) {
+ isc_throw(InvalidRdataText, "Failed to construct MINFO from '" <<
+ minfo_str << "': " << ex.what());
+ }
+}
+
+/// \brief Constructor with a context of MasterLexer.
+///
+/// The \c lexer should point to the beginning of valid textual representation
+/// of an MINFO RDATA. The RMAILBOX and EMAILBOX fields can be non-absolute
+/// if \c origin is non-NULL, in which case \c origin is used to make them
+/// absolute.
+///
+/// \throw MasterLexer::LexerError General parsing error such as missing field.
+/// \throw Other Exceptions from the Name and constructors if construction of
+/// textual fields as these objects fail.
+///
+/// \param lexer A \c MasterLexer object parsing a master file for the
+/// RDATA to be created
+/// \param origin If non NULL, specifies the origin of SERVER when it
+/// is non-absolute.
+MINFO::MINFO(MasterLexer& lexer, const Name* origin,
+ MasterLoader::Options, MasterLoaderCallbacks&) :
+ rmailbox_(createNameFromLexer(lexer, origin)),
+ emailbox_(createNameFromLexer(lexer, origin))
+{
+}
+
+/// \brief Constructor from wire-format data.
+///
+/// This constructor doesn't check the validity of the second parameter (rdata
+/// length) for parsing.
+/// If necessary, the caller will check consistency.
+///
+/// \throw std::bad_alloc Memory allocation for names fails.
+/// \throw Other The constructor of the \c Name class will throw if the
+/// names in the wire is invalid.
+MINFO::MINFO(InputBuffer& buffer, size_t) :
+ rmailbox_(buffer), emailbox_(buffer)
+{}
+
+/// \brief Copy constructor.
+///
+/// \throw std::bad_alloc Memory allocation fails in copying internal
+/// member variables (this should be very rare).
+MINFO::MINFO(const MINFO& other) :
+ Rdata(), rmailbox_(other.rmailbox_), emailbox_(other.emailbox_)
+{}
+
+/// \brief Convert the \c MINFO to a string.
+///
+/// The output of this method is formatted as described in the "from string"
+/// constructor (\c MINFO(const std::string&))).
+///
+/// \throw std::bad_alloc Internal resource allocation fails.
+///
+/// \return A \c string object that represents the \c MINFO object.
+std::string
+MINFO::toText() const {
+ return (rmailbox_.toText() + " " + emailbox_.toText());
+}
+
+/// \brief Render the \c MINFO in the wire format without name compression.
+///
+/// \throw std::bad_alloc Internal resource allocation fails.
+///
+/// \param buffer An output buffer to store the wire data.
+void
+MINFO::toWire(OutputBuffer& buffer) const {
+ rmailbox_.toWire(buffer);
+ emailbox_.toWire(buffer);
+}
+
+MINFO&
+MINFO::operator=(const MINFO& source) {
+ rmailbox_ = source.rmailbox_;
+ emailbox_ = source.emailbox_;
+
+ return (*this);
+}
+
+/// \brief Render the \c MINFO in the wire format with taking into account
+/// compression.
+///
+/// As specified in RFC3597, TYPE MINFO is "well-known", the rmailbox and
+/// emailbox fields (domain names) will be compressed.
+///
+/// \throw std::bad_alloc Internal resource allocation fails.
+///
+/// \param renderer DNS message rendering context that encapsulates the
+/// output buffer and name compression information.
+void
+MINFO::toWire(AbstractMessageRenderer& renderer) const {
+ renderer.writeName(rmailbox_);
+ renderer.writeName(emailbox_);
+}
+
+/// \brief Compare two instances of \c MINFO RDATA.
+///
+/// See documentation in \c Rdata.
+int
+MINFO::compare(const Rdata& other) const {
+ const MINFO& other_minfo = dynamic_cast<const MINFO&>(other);
+
+ const int cmp = compareNames(rmailbox_, other_minfo.rmailbox_);
+ if (cmp != 0) {
+ return (cmp);
+ }
+ return (compareNames(emailbox_, other_minfo.emailbox_));
+}
+
+} // end of namespace "generic"
+} // end of namespace "rdata"
+} // end of namespace "dns"
+} // end of namespace "isc"
+// 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 <config.h>
+
+#include <string>
+
+#include <boost/lexical_cast.hpp>
+
+#include <exceptions/exceptions.h>
+
+#include <util/buffer.h>
+#include <dns/name.h>
+#include <dns/messagerenderer.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+
+#include <dns/rdata/generic/detail/lexer_util.h>
+
+using namespace std;
+using boost::lexical_cast;
+using namespace isc::util;
+using isc::dns::rdata::generic::detail::createNameFromLexer;
+
+namespace isc {
+namespace dns {
+namespace rdata {
+namespace generic {
+
+MX::MX(InputBuffer& buffer, size_t) :
+ preference_(buffer.readUint16()), mxname_(buffer)
+{
+ // we don't need rdata_len for parsing. if necessary, the caller will
+ // check consistency.
+}
+
+/// \brief Constructor from string.
+///
+/// The given string must represent a valid MX 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.
+///
+/// The EXCHANGE name must be absolute since there's no parameter that
+/// specifies the origin name; if it is not absolute, \c MissingNameOrigin
+/// exception will be thrown. It must not be represented as a quoted
+/// string.
+///
+/// See the construction that takes \c MasterLexer for other fields.
+///
+/// \throw Others Exception from the Name and RRTTL constructors.
+/// \throw InvalidRdataText Other general syntax errors.
+MX::MX(const std::string& mx_str) :
+ // Fill in dummy name and replace them soon below.
+ preference_(0), mxname_(Name::ROOT_NAME())
+{
+ try {
+ std::istringstream ss(mx_str);
+ MasterLexer lexer;
+ lexer.pushSource(ss);
+
+ constructFromLexer(lexer, NULL);
+
+ if (lexer.getNextToken().getType() != MasterToken::END_OF_FILE) {
+ isc_throw(InvalidRdataText, "extra input text for MX: "
+ << mx_str);
+ }
+ } catch (const MasterLexer::LexerError& ex) {
+ isc_throw(InvalidRdataText, "Failed to construct MX from '" <<
+ mx_str << "': " << ex.what());
+ }
+}
+
+/// \brief Constructor with a context of MasterLexer.
+///
+/// The \c lexer should point to the beginning of valid textual representation
+/// of an MX RDATA. The EXCHANGE field can be non-absolute if \c origin
+/// is non-NULL, in which case \c origin is used to make it absolute.
+/// It must not be represented as a quoted string.
+///
+/// The PREFERENCE field must be a valid decimal representation of an
+/// unsigned 16-bit integer.
+///
+/// \throw MasterLexer::LexerError General parsing error such as missing field.
+/// \throw Other Exceptions from the Name and RRTTL constructors if
+/// construction of textual fields as these objects fail.
+///
+/// \param lexer A \c MasterLexer object parsing a master file for the
+/// RDATA to be created
+/// \param origin If non NULL, specifies the origin of EXCHANGE when it
+/// is non-absolute.
+MX::MX(MasterLexer& lexer, const Name* origin,
+ MasterLoader::Options, MasterLoaderCallbacks&) :
+ preference_(0), mxname_(Name::ROOT_NAME())
+{
+ constructFromLexer(lexer, origin);
+}
+
+void
+MX::constructFromLexer(MasterLexer& lexer, const Name* origin) {
+ const uint32_t num = lexer.getNextToken(MasterToken::NUMBER).getNumber();
+ if (num > 65535) {
+ isc_throw(InvalidRdataText, "Invalid MX preference: " << num);
+ }
+ preference_ = static_cast<uint16_t>(num);
+
+ mxname_ = createNameFromLexer(lexer, origin);
+}
+
+MX::MX(uint16_t preference, const Name& mxname) :
+ preference_(preference), mxname_(mxname)
+{}
+
+MX::MX(const MX& other) :
+ Rdata(), preference_(other.preference_), mxname_(other.mxname_)
+{}
+
+void
+MX::toWire(OutputBuffer& buffer) const {
+ buffer.writeUint16(preference_);
+ mxname_.toWire(buffer);
+}
+
+void
+MX::toWire(AbstractMessageRenderer& renderer) const {
+ renderer.writeUint16(preference_);
+ renderer.writeName(mxname_);
+}
+
+string
+MX::toText() const {
+ return (lexical_cast<string>(preference_) + " " + mxname_.toText());
+}
+
+int
+MX::compare(const Rdata& other) const {
+ const MX& other_mx = dynamic_cast<const MX&>(other);
+
+ if (preference_ < other_mx.preference_) {
+ return (-1);
+ } else if (preference_ > other_mx.preference_) {
+ return (1);
+ }
+
+ return (compareNames(mxname_, other_mx.mxname_));
+}
+
+const Name&
+MX::getMXName() const {
+ return (mxname_);
+}
+
+uint16_t
+MX::getMXPref() const {
+ return (preference_);
+}
+
+} // end of namespace "generic"
+} // end of namespace "rdata"
+} // end of namespace "dns"
+} // end of namespace "isc"
+// 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 <config.h>
+
+#include <dns/name.h>
+#include <dns/messagerenderer.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+#include <dns/rdata/generic/detail/char_string.h>
+#include <exceptions/exceptions.h>
+
+#include <string>
+#include <boost/lexical_cast.hpp>
+
+using namespace std;
+using boost::lexical_cast;
+using namespace isc::util;
+using namespace isc::dns;
+
+namespace isc {
+namespace dns {
+namespace rdata {
+namespace generic {
+
+class NAPTRImpl {
+public:
+ NAPTRImpl() : replacement(".") {}
+
+ NAPTRImpl(InputBuffer& buffer, size_t rdata_len) : replacement(".") {
+ if (rdata_len < 4 || buffer.getLength() - buffer.getPosition() < 4) {
+ isc_throw(isc::dns::DNSMessageFORMERR, "Error in parsing "
+ "NAPTR RDATA wire format: insufficient length ");
+ }
+ order = buffer.readUint16();
+ preference = buffer.readUint16();
+ rdata_len -= 4;
+
+ rdata_len -= detail::bufferToCharString(buffer, rdata_len, flags);
+ rdata_len -= detail::bufferToCharString(buffer, rdata_len, services);
+ rdata_len -= detail::bufferToCharString(buffer, rdata_len, regexp);
+ replacement = Name(buffer);
+ if (rdata_len < 1) {
+ isc_throw(isc::dns::DNSMessageFORMERR, "Error in parsing "
+ "NAPTR RDATA wire format: missing replacement name");
+ }
+ rdata_len -= replacement.getLength();
+
+ if (rdata_len != 0) {
+ isc_throw(isc::dns::DNSMessageFORMERR, "Error in parsing " <<
+ "NAPTR RDATA: bytes left at end: " <<
+ static_cast<int>(rdata_len));
+ }
+ }
+
+ NAPTRImpl(const std::string& naptr_str) : replacement(".") {
+ std::istringstream ss(naptr_str);
+ MasterLexer lexer;
+ lexer.pushSource(ss);
+
+ try {
+ parseNAPTRData(lexer);
+ // Should be at end of data now
+ if (lexer.getNextToken(MasterToken::QSTRING, true).getType() !=
+ MasterToken::END_OF_FILE) {
+ isc_throw(InvalidRdataText,
+ "Invalid NAPTR text format: too many fields.");
+ }
+ } catch (const MasterLexer::LexerError& ex) {
+ isc_throw(InvalidRdataText, "Failed to construct NAPTR RDATA from "
+ << naptr_str << "': " << ex.what());
+ }
+ }
+
+ NAPTRImpl(MasterLexer& lexer) : replacement(".")
+ {
+ parseNAPTRData(lexer);
+ }
+
+private:
+ void
+ parseNAPTRData(MasterLexer& lexer) {
+ MasterToken token = lexer.getNextToken(MasterToken::NUMBER);
+ if (token.getNumber() > 65535) {
+ isc_throw(InvalidRdataText,
+ "Invalid NAPTR text format: order out of range: "
+ << token.getNumber());
+ }
+ order = token.getNumber();
+ token = lexer.getNextToken(MasterToken::NUMBER);
+ if (token.getNumber() > 65535) {
+ isc_throw(InvalidRdataText,
+ "Invalid NAPTR text format: preference out of range: "
+ << token.getNumber());
+ }
+ preference = token.getNumber();
+
+ token = lexer.getNextToken(MasterToken::QSTRING);
+ stringToCharString(token.getStringRegion(), flags);
+ token = lexer.getNextToken(MasterToken::QSTRING);
+ stringToCharString(token.getStringRegion(), services);
+ token = lexer.getNextToken(MasterToken::QSTRING);
+ stringToCharString(token.getStringRegion(), regexp);
+
+ token = lexer.getNextToken(MasterToken::STRING);
+ replacement = Name(token.getString());
+ }
+
+
+public:
+ uint16_t order;
+ uint16_t preference;
+ detail::CharString flags;
+ detail::CharString services;
+ detail::CharString regexp;
+ Name replacement;
+};
+
+NAPTR::NAPTR(InputBuffer& buffer, size_t rdata_len) :
+ impl_(new NAPTRImpl(buffer, rdata_len))
+{}
+
+NAPTR::NAPTR(const std::string& naptr_str) : impl_(new NAPTRImpl(naptr_str))
+{}
+
+NAPTR::NAPTR(MasterLexer& lexer, const Name*,
+ MasterLoader::Options, MasterLoaderCallbacks&) :
+ impl_(new NAPTRImpl(lexer))
+{}
+
+NAPTR::NAPTR(const NAPTR& naptr) : Rdata(),
+ impl_(new NAPTRImpl(*naptr.impl_))
+{}
+
+NAPTR&
+NAPTR::operator=(const NAPTR& source)
+{
+ impl_.reset(new NAPTRImpl(*source.impl_));
+ return (*this);
+}
+
+NAPTR::~NAPTR() {
+}
+
+void
+NAPTR::toWire(OutputBuffer& buffer) const {
+ toWireHelper(buffer);
+ impl_->replacement.toWire(buffer);
+}
+
+void
+NAPTR::toWire(AbstractMessageRenderer& renderer) const {
+ toWireHelper(renderer);
+ // Type NAPTR is not "well-known", and name compression must be disabled
+ // per RFC3597.
+ renderer.writeName(impl_->replacement, false);
+}
+
+string
+NAPTR::toText() const {
+ string result;
+ result += lexical_cast<string>(impl_->order);
+ result += " ";
+ result += lexical_cast<string>(impl_->preference);
+ result += " \"";
+ result += detail::charStringToString(impl_->flags);
+ result += "\" \"";
+ result += detail::charStringToString(impl_->services);
+ result += "\" \"";
+ result += detail::charStringToString(impl_->regexp);
+ result += "\" ";
+ result += impl_->replacement.toText();
+ return (result);
+}
+
+int
+NAPTR::compare(const Rdata& other) const {
+ const NAPTR other_naptr = dynamic_cast<const NAPTR&>(other);
+
+ if (impl_->order < other_naptr.impl_->order) {
+ return (-1);
+ } else if (impl_->order > other_naptr.impl_->order) {
+ return (1);
+ }
+
+ if (impl_->preference < other_naptr.impl_->preference) {
+ return (-1);
+ } else if (impl_->preference > other_naptr.impl_->preference) {
+ return (1);
+ }
+
+ const int fcmp = detail::compareCharStrings(impl_->flags,
+ other_naptr.impl_->flags);
+ if (fcmp != 0) {
+ return (fcmp);
+ }
+
+ const int scmp = detail::compareCharStrings(impl_->services,
+ other_naptr.impl_->services);
+ if (scmp != 0) {
+ return (scmp);
+ }
+
+ const int rcmp = detail::compareCharStrings(impl_->regexp,
+ other_naptr.impl_->regexp);
+ if (rcmp != 0) {
+ return (rcmp);
+ }
+
+ return (compareNames(impl_->replacement, other_naptr.impl_->replacement));
+}
+
+uint16_t
+NAPTR::getOrder() const {
+ return (impl_->order);
+}
+
+uint16_t
+NAPTR::getPreference() const {
+ return (impl_->preference);
+}
+
+const std::string
+NAPTR::getFlags() const {
+ return (detail::charStringToString(impl_->flags));
+}
+
+const std::string
+NAPTR::getServices() const {
+ return (detail::charStringToString(impl_->services));
+}
+
+const std::string
+NAPTR::getRegexp() const {
+ return (detail::charStringToString(impl_->regexp));
+}
+
+const Name&
+NAPTR::getReplacement() const {
+ return (impl_->replacement);
+}
+
+template <typename T>
+void
+NAPTR::toWireHelper(T& outputer) const {
+ outputer.writeUint16(impl_->order);
+ outputer.writeUint16(impl_->preference);
+
+ outputer.writeData(&impl_->flags[0], impl_->flags.size());
+ outputer.writeData(&impl_->services[0], impl_->services.size());
+ outputer.writeData(&impl_->regexp[0], impl_->regexp.size());
+}
+
+} // end of namespace "generic"
+} // end of namespace "rdata"
+} // end of namespace "dns"
+} // end of namespace "isc"
+// 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 <config.h>
+
+#include <string>
+
+#include <util/buffer.h>
+#include <dns/name.h>
+#include <dns/messagerenderer.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+
+#include <dns/rdata/generic/detail/lexer_util.h>
+
+using namespace std;
+using namespace isc::util;
+using isc::dns::rdata::generic::detail::createNameFromLexer;
+
+namespace isc {
+namespace dns {
+namespace rdata {
+namespace generic {
+
+/// \brief Constructor from string.
+///
+/// The given string must represent a valid NS 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.
+///
+/// The NSDNAME must be absolute since there's no parameter that
+/// specifies the origin name; if it is not absolute, \c
+/// MissingNameOrigin exception will be thrown. These must not be
+/// represented as a quoted string.
+///
+/// \throw Others Exception from the Name and RRTTL constructors.
+/// \throw InvalidRdataText Other general syntax errors.
+NS::NS(const std::string& namestr) :
+ // Fill in dummy name and replace them soon below.
+ nsname_(Name::ROOT_NAME())
+{
+ try {
+ std::istringstream ss(namestr);
+ MasterLexer lexer;
+ lexer.pushSource(ss);
+
+ nsname_ = createNameFromLexer(lexer, NULL);
+
+ if (lexer.getNextToken().getType() != MasterToken::END_OF_FILE) {
+ isc_throw(InvalidRdataText, "extra input text for NS: "
+ << namestr);
+ }
+ } catch (const MasterLexer::LexerError& ex) {
+ isc_throw(InvalidRdataText, "Failed to construct NS from '" <<
+ namestr << "': " << ex.what());
+ }
+}
+
+NS::NS(InputBuffer& buffer, size_t) :
+ nsname_(buffer)
+{
+ // we don't need rdata_len for parsing. if necessary, the caller will
+ // check consistency.
+}
+
+/// \brief Constructor with a context of MasterLexer.
+///
+/// The \c lexer should point to the beginning of valid textual
+/// representation of an NS RDATA. The NSDNAME field can be
+/// non-absolute if \c origin is non-NULL, in which case \c origin is
+/// used to make it absolute. It must not be represented as a quoted
+/// string.
+///
+/// \throw MasterLexer::LexerError General parsing error such as missing field.
+/// \throw Other Exceptions from the Name and RRTTL constructors if
+/// construction of textual fields as these objects fail.
+///
+/// \param lexer A \c MasterLexer object parsing a master file for the
+/// RDATA to be created
+/// \param origin If non NULL, specifies the origin of NSDNAME when it
+/// is non-absolute.
+NS::NS(MasterLexer& lexer, const Name* origin,
+ MasterLoader::Options, MasterLoaderCallbacks&) :
+ nsname_(createNameFromLexer(lexer, origin))
+{}
+
+NS::NS(const NS& other) :
+ Rdata(), nsname_(other.nsname_)
+{}
+
+void
+NS::toWire(OutputBuffer& buffer) const {
+ nsname_.toWire(buffer);
+}
+
+void
+NS::toWire(AbstractMessageRenderer& renderer) const {
+ renderer.writeName(nsname_);
+}
+
+string
+NS::toText() const {
+ return (nsname_.toText());
+}
+
+int
+NS::compare(const Rdata& other) const {
+ const NS& other_ns = dynamic_cast<const NS&>(other);
+
+ return (compareNames(nsname_, other_ns.nsname_));
+}
+
+const Name&
+NS::getNSName() const {
+ return (nsname_);
+}
+
+} // end of namespace "generic"
+} // end of namespace "rdata"
+} // end of namespace "dns"
+} // end of namespace "isc"
+// 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 <iostream>
+#include <iomanip>
+#include <string>
+#include <sstream>
+#include <vector>
+#include <cassert>
+
+#include <boost/lexical_cast.hpp>
+
+#include <util/encode/base32hex.h>
+#include <util/encode/hex.h>
+#include <util/buffer.h>
+
+#include <dns/exceptions.h>
+#include <dns/messagerenderer.h>
+#include <dns/name.h>
+#include <dns/rrtype.h>
+#include <dns/rrttl.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+#include <dns/rdata/generic/detail/nsec_bitmap.h>
+#include <dns/rdata/generic/detail/nsec3param_common.h>
+
+#include <memory>
+
+#include <stdio.h>
+#include <time.h>
+
+using namespace std;
+using namespace isc::dns::rdata::generic::detail::nsec;
+using namespace isc::dns::rdata::generic::detail::nsec3;
+using namespace isc::util::encode;
+using namespace isc::util;
+
+namespace isc {
+namespace dns {
+namespace rdata {
+namespace generic {
+
+struct NSEC3Impl {
+ // straightforward representation of NSEC3 RDATA fields
+ NSEC3Impl(uint8_t hashalg, uint8_t flags, uint16_t iterations,
+ vector<uint8_t>salt, vector<uint8_t>next,
+ vector<uint8_t> typebits) :
+ hashalg_(hashalg), flags_(flags), iterations_(iterations),
+ salt_(salt), next_(next), typebits_(typebits)
+ {}
+
+ const uint8_t hashalg_;
+ const uint8_t flags_;
+ const uint16_t iterations_;
+ const vector<uint8_t> salt_;
+ const vector<uint8_t> next_;
+ const vector<uint8_t> typebits_;
+};
+
+/// \brief Constructor from string.
+///
+/// The given string must represent a valid NSEC3 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.
+///
+/// The Hash Algorithm, Flags and Iterations fields must be within their
+/// valid ranges. The Salt field may contain "-" to indicate that the
+/// salt is of length 0. The Salt field must not contain any whitespace.
+/// The type mnemonics must be valid, and separated by whitespace. If
+/// any invalid mnemonics are found, InvalidRdataText exception is
+/// thrown.
+///
+/// \throw InvalidRdataText if any fields are out of their valid range,
+/// or are incorrect.
+///
+/// \param nsec3_str A string containing the RDATA to be created
+NSEC3::NSEC3(const std::string& nsec3_str) :
+ impl_(NULL)
+{
+ // We use auto_ptr here because if there is an exception in this
+ // constructor, the destructor is not called and there could be a
+ // leak of the NSEC3Impl that constructFromLexer() returns.
+ std::auto_ptr<NSEC3Impl> impl_ptr(NULL);
+
+ try {
+ std::istringstream ss(nsec3_str);
+ MasterLexer lexer;
+ lexer.pushSource(ss);
+
+ impl_ptr.reset(constructFromLexer(lexer));
+
+ if (lexer.getNextToken().getType() != MasterToken::END_OF_FILE) {
+ isc_throw(InvalidRdataText,
+ "Extra input text for NSEC3: " << nsec3_str);
+ }
+ } catch (const MasterLexer::LexerError& ex) {
+ isc_throw(InvalidRdataText,
+ "Failed to construct NSEC3 from '" << nsec3_str << "': "
+ << ex.what());
+ }
+
+ impl_ = impl_ptr.release();
+}
+
+/// \brief Constructor with a context of MasterLexer.
+///
+/// The \c lexer should point to the beginning of valid textual
+/// representation of an NSEC3 RDATA.
+///
+/// See \c NSEC3::NSEC3(const std::string&) for description of the
+/// expected RDATA fields.
+///
+/// \throw MasterLexer::LexerError General parsing error such as
+/// missing field.
+/// \throw InvalidRdataText if any fields are out of their valid range,
+/// or are incorrect.
+///
+/// \param lexer A \c MasterLexer object parsing a master file for the
+/// RDATA to be created
+NSEC3::NSEC3(MasterLexer& lexer, const Name*, MasterLoader::Options,
+ MasterLoaderCallbacks&) :
+ impl_(NULL)
+{
+ impl_ = constructFromLexer(lexer);
+}
+
+NSEC3Impl*
+NSEC3::constructFromLexer(MasterLexer& lexer) {
+ vector<uint8_t> salt;
+ const ParseNSEC3ParamResult params =
+ parseNSEC3ParamFromLexer("NSEC3", lexer, salt);
+
+ const string& nexthash =
+ lexer.getNextToken(MasterToken::STRING).getString();
+ if (*nexthash.rbegin() == '=') {
+ isc_throw(InvalidRdataText, "NSEC3 hash has padding: " << nexthash);
+ }
+
+ vector<uint8_t> next;
+ decodeBase32Hex(nexthash, next);
+ if (next.size() > 255) {
+ isc_throw(InvalidRdataText, "NSEC3 hash is too long: "
+ << next.size() << " bytes");
+ }
+
+ vector<uint8_t> typebits;
+ // For NSEC3 empty bitmap is possible and allowed.
+ buildBitmapsFromLexer("NSEC3", lexer, typebits, true);
+ return (new NSEC3Impl(params.algorithm, params.flags, params.iterations,
+ salt, next, typebits));
+}
+
+NSEC3::NSEC3(InputBuffer& buffer, size_t rdata_len) :
+ impl_(NULL)
+{
+ vector<uint8_t> salt;
+ const ParseNSEC3ParamResult params =
+ parseNSEC3ParamWire("NSEC3", buffer, rdata_len, salt);
+
+ if (rdata_len < 1) {
+ isc_throw(DNSMessageFORMERR, "NSEC3 too short to contain hash length, "
+ "length: " << rdata_len + salt.size() + 5);
+ }
+ const uint8_t nextlen = buffer.readUint8();
+ --rdata_len;
+ if (nextlen == 0 || rdata_len < nextlen) {
+ isc_throw(DNSMessageFORMERR, "NSEC3 invalid hash length: " <<
+ static_cast<unsigned int>(nextlen));
+ }
+
+ vector<uint8_t> next(nextlen);
+ buffer.readData(&next[0], nextlen);
+ rdata_len -= nextlen;
+
+ vector<uint8_t> typebits(rdata_len);
+ if (rdata_len > 0) {
+ // Read and parse the bitmaps only when they exist; empty bitmap
+ // is possible for NSEC3.
+ buffer.readData(&typebits[0], rdata_len);
+ checkRRTypeBitmaps("NSEC3", typebits);
+ }
+
+ impl_ = new NSEC3Impl(params.algorithm, params.flags, params.iterations,
+ salt, next, typebits);
+}
+
+NSEC3::NSEC3(const NSEC3& source) :
+ Rdata(), impl_(new NSEC3Impl(*source.impl_))
+{}
+
+NSEC3&
+NSEC3::operator=(const NSEC3& source) {
+ if (this == &source) {
+ return (*this);
+ }
+
+ NSEC3Impl* newimpl = new NSEC3Impl(*source.impl_);
+ delete impl_;
+ impl_ = newimpl;
+
+ return (*this);
+}
+
+NSEC3::~NSEC3() {
+ delete impl_;
+}
+
+string
+NSEC3::toText() const {
+ ostringstream s;
+ bitmapsToText(impl_->typebits_, s);
+
+ using boost::lexical_cast;
+ return (lexical_cast<string>(static_cast<int>(impl_->hashalg_)) +
+ " " + lexical_cast<string>(static_cast<int>(impl_->flags_)) +
+ " " + lexical_cast<string>(static_cast<int>(impl_->iterations_)) +
+ " " + (impl_->salt_.empty() ? "-" : encodeHex(impl_->salt_)) +
+ " " + encodeBase32Hex(impl_->next_) + s.str());
+}
+
+template <typename OUTPUT_TYPE>
+void
+toWireHelper(const NSEC3Impl& impl, OUTPUT_TYPE& output) {
+ output.writeUint8(impl.hashalg_);
+ output.writeUint8(impl.flags_);
+ output.writeUint16(impl.iterations_);
+ output.writeUint8(impl.salt_.size());
+ if (!impl.salt_.empty()) {
+ output.writeData(&impl.salt_[0], impl.salt_.size());
+ }
+ assert(!impl.next_.empty());
+ output.writeUint8(impl.next_.size());
+ output.writeData(&impl.next_[0], impl.next_.size());
+ if (!impl.typebits_.empty()) {
+ output.writeData(&impl.typebits_[0], impl.typebits_.size());
+ }
+}
+
+void
+NSEC3::toWire(OutputBuffer& buffer) const {
+ toWireHelper(*impl_, buffer);
+}
+
+void
+NSEC3::toWire(AbstractMessageRenderer& renderer) const {
+ toWireHelper(*impl_, renderer);
+}
+
+namespace {
+// This is a helper subroutine for compare(). It compares two binary
+// data stored in vector<uint8_t> objects based on the "Canonical RR Ordering"
+// as defined in Section 6.3 of RFC4034, that is, the data are treated
+// "as a left-justified unsigned octet sequence in which the absence of an
+// octet sorts before a zero octet."
+//
+// If check_length_first is true, it treats the compared data as if they
+// began with a single-octet "length" field whose value is the size of the
+// corresponding vector. In this case, if the sizes of the two vectors are
+// different the shorter one is always considered the "smaller"; the contents
+// of the vector don't matter.
+//
+// This function returns:
+// -1 if v1 is considered smaller than v2
+// 1 if v1 is considered larger than v2
+// 0 otherwise
+int
+compareVectors(const vector<uint8_t>& v1, const vector<uint8_t>& v2,
+ bool check_length_first = true)
+{
+ const size_t len1 = v1.size();
+ const size_t len2 = v2.size();
+ if (check_length_first && len1 != len2) {
+ return (len1 - len2);
+ }
+ const size_t cmplen = min(len1, len2);
+ const int cmp = cmplen == 0 ? 0 : memcmp(&v1.at(0), &v2.at(0), cmplen);
+ if (cmp != 0) {
+ return (cmp);
+ } else {
+ return (len1 - len2);
+ }
+}
+}
+
+int
+NSEC3::compare(const Rdata& other) const {
+ const NSEC3& other_nsec3 = dynamic_cast<const NSEC3&>(other);
+
+ if (impl_->hashalg_ != other_nsec3.impl_->hashalg_) {
+ return (impl_->hashalg_ < other_nsec3.impl_->hashalg_ ? -1 : 1);
+ }
+ if (impl_->flags_ != other_nsec3.impl_->flags_) {
+ return (impl_->flags_ < other_nsec3.impl_->flags_ ? -1 : 1);
+ }
+ if (impl_->iterations_ != other_nsec3.impl_->iterations_) {
+ return (impl_->iterations_ < other_nsec3.impl_->iterations_ ? -1 : 1);
+ }
+
+ int cmp = compareVectors(impl_->salt_, other_nsec3.impl_->salt_);
+ if (cmp != 0) {
+ return (cmp);
+ }
+ cmp = compareVectors(impl_->next_, other_nsec3.impl_->next_);
+ if (cmp != 0) {
+ return (cmp);
+ }
+ // Note that bitmap doesn't have a dedicated length field, so we shouldn't
+ // terminate the comparison just because the lengths are different.
+ return (compareVectors(impl_->typebits_, other_nsec3.impl_->typebits_,
+ false));
+}
+
+uint8_t
+NSEC3::getHashalg() const {
+ return (impl_->hashalg_);
+}
+
+uint8_t
+NSEC3::getFlags() const {
+ return (impl_->flags_);
+}
+
+uint16_t
+NSEC3::getIterations() const {
+ return (impl_->iterations_);
+}
+
+const vector<uint8_t>&
+NSEC3::getSalt() const {
+ return (impl_->salt_);
+}
+
+const vector<uint8_t>&
+NSEC3::getNext() const {
+ return (impl_->next_);
+}
+
+} // end of namespace "generic"
+} // end of namespace "rdata"
+} // end of namespace "dns"
+} // end of namespace "isc"
+// 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 <util/buffer.h>
+#include <util/encode/hex.h>
+
+#include <dns/messagerenderer.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+#include <dns/rdata/generic/detail/nsec3param_common.h>
+
+#include <boost/lexical_cast.hpp>
+
+#include <memory>
+#include <string>
+#include <sstream>
+#include <vector>
+
+using namespace std;
+using namespace isc::util;
+using namespace isc::util::encode;
+
+namespace isc {
+namespace dns {
+namespace rdata {
+namespace generic {
+
+struct NSEC3PARAMImpl {
+ // straightforward representation of NSEC3PARAM RDATA fields
+ NSEC3PARAMImpl(uint8_t hashalg, uint8_t flags, uint16_t iterations,
+ const vector<uint8_t>& salt) :
+ hashalg_(hashalg), flags_(flags), iterations_(iterations), salt_(salt)
+ {}
+
+ const uint8_t hashalg_;
+ const uint8_t flags_;
+ const uint16_t iterations_;
+ const vector<uint8_t> salt_;
+};
+
+/// \brief Constructor from string.
+///
+/// The given string must represent a valid NSEC3PARAM 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.
+///
+/// The Hash Algorithm, Flags and Iterations fields must be within their
+/// valid ranges. The Salt field may contain "-" to indicate that the
+/// salt is of length 0. The Salt field must not contain any whitespace.
+///
+/// \throw InvalidRdataText if any fields are out of their valid range,
+/// or are incorrect.
+///
+/// \param nsec3param_str A string containing the RDATA to be created
+NSEC3PARAM::NSEC3PARAM(const std::string& nsec3param_str) :
+ impl_(NULL)
+{
+ // We use auto_ptr here because if there is an exception in this
+ // constructor, the destructor is not called and there could be a
+ // leak of the NSEC3PARAMImpl that constructFromLexer() returns.
+ std::auto_ptr<NSEC3PARAMImpl> impl_ptr(NULL);
+
+ try {
+ std::istringstream ss(nsec3param_str);
+ MasterLexer lexer;
+ lexer.pushSource(ss);
+
+ impl_ptr.reset(constructFromLexer(lexer));
+
+ if (lexer.getNextToken().getType() != MasterToken::END_OF_FILE) {
+ isc_throw(InvalidRdataText,
+ "Extra input text for NSEC3PARAM: " << nsec3param_str);
+ }
+ } catch (const MasterLexer::LexerError& ex) {
+ isc_throw(InvalidRdataText,
+ "Failed to construct NSEC3PARAM from '" << nsec3param_str
+ << "': " << ex.what());
+ }
+
+ impl_ = impl_ptr.release();
+}
+
+/// \brief Constructor with a context of MasterLexer.
+///
+/// The \c lexer should point to the beginning of valid textual
+/// representation of an NSEC3PARAM RDATA.
+///
+/// See \c NSEC3PARAM::NSEC3PARAM(const std::string&) for description of
+/// the expected RDATA fields.
+///
+/// \throw MasterLexer::LexerError General parsing error such as
+/// missing field.
+/// \throw InvalidRdataText if any fields are out of their valid range,
+/// or are incorrect.
+///
+/// \param lexer A \c MasterLexer object parsing a master file for the
+/// RDATA to be created
+NSEC3PARAM::NSEC3PARAM(MasterLexer& lexer, const Name*, MasterLoader::Options,
+ MasterLoaderCallbacks&) :
+ impl_(NULL)
+{
+ impl_ = constructFromLexer(lexer);
+}
+
+NSEC3PARAMImpl*
+NSEC3PARAM::constructFromLexer(MasterLexer& lexer) {
+ vector<uint8_t> salt;
+ const ParseNSEC3ParamResult params =
+ parseNSEC3ParamFromLexer("NSEC3PARAM", lexer, salt);
+
+ return (new NSEC3PARAMImpl(params.algorithm, params.flags,
+ params.iterations, salt));
+}
+
+NSEC3PARAM::NSEC3PARAM(InputBuffer& buffer, size_t rdata_len) :
+ impl_(NULL)
+{
+ vector<uint8_t> salt;
+ const ParseNSEC3ParamResult params =
+ parseNSEC3ParamWire("NSEC3PARAM", buffer, rdata_len, salt);
+
+ impl_ = new NSEC3PARAMImpl(params.algorithm, params.flags,
+ params.iterations, salt);
+}
+
+NSEC3PARAM::NSEC3PARAM(const NSEC3PARAM& source) :
+ Rdata(), impl_(new NSEC3PARAMImpl(*source.impl_))
+{}
+
+NSEC3PARAM&
+NSEC3PARAM::operator=(const NSEC3PARAM& source) {
+ if (this == &source) {
+ return (*this);
+ }
+
+ NSEC3PARAMImpl* newimpl = new NSEC3PARAMImpl(*source.impl_);
+ delete impl_;
+ impl_ = newimpl;
+
+ return (*this);
+}
+
+NSEC3PARAM::~NSEC3PARAM() {
+ delete impl_;
+}
+
+string
+NSEC3PARAM::toText() const {
+ using boost::lexical_cast;
+ return (lexical_cast<string>(static_cast<int>(impl_->hashalg_)) +
+ " " + lexical_cast<string>(static_cast<int>(impl_->flags_)) +
+ " " + lexical_cast<string>(static_cast<int>(impl_->iterations_)) +
+ " " + (impl_->salt_.empty() ? "-" : encodeHex(impl_->salt_)));
+}
+
+template <typename OUTPUT_TYPE>
+void
+toWireHelper(const NSEC3PARAMImpl& impl, OUTPUT_TYPE& output) {
+ output.writeUint8(impl.hashalg_);
+ output.writeUint8(impl.flags_);
+ output.writeUint16(impl.iterations_);
+ output.writeUint8(impl.salt_.size());
+ if (!impl.salt_.empty()) {
+ output.writeData(&impl.salt_[0], impl.salt_.size());
+ }
+}
+
+void
+NSEC3PARAM::toWire(OutputBuffer& buffer) const {
+ toWireHelper(*impl_, buffer);
+}
+
+void
+NSEC3PARAM::toWire(AbstractMessageRenderer& renderer) const {
+ toWireHelper(*impl_, renderer);
+}
+
+int
+NSEC3PARAM::compare(const Rdata& other) const {
+ const NSEC3PARAM& other_param = dynamic_cast<const NSEC3PARAM&>(other);
+
+ if (impl_->hashalg_ != other_param.impl_->hashalg_) {
+ return (impl_->hashalg_ < other_param.impl_->hashalg_ ? -1 : 1);
+ }
+ if (impl_->flags_ != other_param.impl_->flags_) {
+ return (impl_->flags_ < other_param.impl_->flags_ ? -1 : 1);
+ }
+ if (impl_->iterations_ != other_param.impl_->iterations_) {
+ return (impl_->iterations_ < other_param.impl_->iterations_ ? -1 : 1);
+ }
+
+ const size_t this_len = impl_->salt_.size();
+ const size_t other_len = other_param.impl_->salt_.size();
+ if (this_len != other_len) {
+ return (this_len - other_len);
+ }
+ const size_t cmplen = min(this_len, other_len);
+ const int cmp = (cmplen == 0) ? 0 :
+ memcmp(&impl_->salt_.at(0), &other_param.impl_->salt_.at(0), cmplen);
+ if (cmp != 0) {
+ return (cmp);
+ } else {
+ return (this_len - other_len);
+ }
+}
+
+uint8_t
+NSEC3PARAM::getHashalg() const {
+ return (impl_->hashalg_);
+}
+
+uint8_t
+NSEC3PARAM::getFlags() const {
+ return (impl_->flags_);
+}
+
+uint16_t
+NSEC3PARAM::getIterations() const {
+ return (impl_->iterations_);
+}
+
+const vector<uint8_t>&
+NSEC3PARAM::getSalt() const {
+ return (impl_->salt_);
+}
+
+} // end of namespace "generic"
+} // end of namespace "rdata"
+} // end of namespace "dns"
+} // end of namespace "isc"
+// 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 <iostream>
+#include <string>
+#include <sstream>
+#include <vector>
+
+#include <util/encode/base64.h>
+#include <util/buffer.h>
+#include <dns/exceptions.h>
+#include <dns/messagerenderer.h>
+#include <dns/name.h>
+#include <dns/rrtype.h>
+#include <dns/rrttl.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+#include <dns/rdata/generic/detail/nsec_bitmap.h>
+#include <dns/rdata/generic/detail/lexer_util.h>
+
+#include <stdio.h>
+#include <time.h>
+
+using namespace std;
+using namespace isc::util;
+using namespace isc::util::encode;
+using namespace isc::dns::rdata::generic::detail::nsec;
+using isc::dns::rdata::generic::detail::createNameFromLexer;
+
+namespace isc {
+namespace dns {
+namespace rdata {
+namespace generic {
+
+struct NSECImpl {
+ // straightforward representation of NSEC RDATA fields
+ NSECImpl(const Name& next, vector<uint8_t> typebits) :
+ nextname_(next), typebits_(typebits)
+ {}
+
+ Name nextname_;
+ vector<uint8_t> typebits_;
+};
+
+/// \brief Constructor from string.
+///
+/// The given string must represent a valid NSEC 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.
+///
+/// The Next Domain Name field must be absolute since there's no
+/// parameter that specifies the origin name; if it is not absolute,
+/// \c MissingNameOrigin exception will be thrown. This must not be
+/// represented as a quoted string.
+///
+/// The type mnemonics must be valid, and separated by whitespace. If
+/// any invalid mnemonics are found, InvalidRdataText exception is
+/// thrown.
+///
+/// \throw MissingNameOrigin Thrown when the Next Domain Name is not absolute.
+/// \throw InvalidRdataText if any fields are out of their valid range.
+///
+/// \param nsec_str A string containing the RDATA to be created
+NSEC::NSEC(const std::string& nsec_str) :
+ impl_(NULL)
+{
+ try {
+ std::istringstream ss(nsec_str);
+ MasterLexer lexer;
+ lexer.pushSource(ss);
+
+ const Name origin_name(createNameFromLexer(lexer, NULL));
+
+ vector<uint8_t> typebits;
+ buildBitmapsFromLexer("NSEC", lexer, typebits);
+
+ impl_ = new NSECImpl(origin_name, typebits);
+
+ if (lexer.getNextToken().getType() != MasterToken::END_OF_FILE) {
+ isc_throw(InvalidRdataText,
+ "Extra input text for NSEC: " << nsec_str);
+ }
+ } catch (const MasterLexer::LexerError& ex) {
+ isc_throw(InvalidRdataText,
+ "Failed to construct NSEC from '" << nsec_str << "': "
+ << ex.what());
+ }
+}
+
+NSEC::NSEC(InputBuffer& buffer, size_t rdata_len) {
+ const size_t pos = buffer.getPosition();
+ const Name nextname(buffer);
+
+ // rdata_len must be sufficiently large to hold non empty bitmap.
+ if (rdata_len <= buffer.getPosition() - pos) {
+ isc_throw(DNSMessageFORMERR,
+ "NSEC RDATA from wire too short: " << rdata_len << "bytes");
+ }
+ rdata_len -= (buffer.getPosition() - pos);
+
+ vector<uint8_t> typebits(rdata_len);
+ buffer.readData(&typebits[0], rdata_len);
+ checkRRTypeBitmaps("NSEC", typebits);
+
+ impl_ = new NSECImpl(nextname, typebits);
+}
+
+/// \brief Constructor with a context of MasterLexer.
+///
+/// The \c lexer should point to the beginning of valid textual
+/// representation of an NSEC RDATA.
+///
+/// The Next Domain Name field can be non-absolute if \c origin is
+/// non-NULL, in which case \c origin is used to make it absolute. It
+/// must not be represented as a quoted string.
+///
+/// The type mnemonics must be valid, and separated by whitespace. If
+/// any invalid mnemonics are found, InvalidRdataText exception is
+/// thrown.
+///
+/// \throw MasterLexer::LexerError General parsing error such as
+/// missing field.
+/// \throw MissingNameOrigin Thrown when the Next Domain Name is not
+/// absolute and \c origin is NULL.
+/// \throw InvalidRdataText if any fields are out of their valid range.
+///
+/// \param lexer A \c MasterLexer object parsing a master file for the
+/// RDATA to be created
+/// \param origin The origin to use with a relative Next Domain Name
+/// field
+NSEC::NSEC(MasterLexer& lexer, const Name* origin, MasterLoader::Options,
+ MasterLoaderCallbacks&)
+{
+ const Name next_name(createNameFromLexer(lexer, origin));
+
+ vector<uint8_t> typebits;
+ buildBitmapsFromLexer("NSEC", lexer, typebits);
+
+ impl_ = new NSECImpl(next_name, typebits);
+}
+
+NSEC::NSEC(const NSEC& source) :
+ Rdata(), impl_(new NSECImpl(*source.impl_))
+{}
+
+NSEC&
+NSEC::operator=(const NSEC& source) {
+ if (this == &source) {
+ return (*this);
+ }
+
+ NSECImpl* newimpl = new NSECImpl(*source.impl_);
+ delete impl_;
+ impl_ = newimpl;
+
+ return (*this);
+}
+
+NSEC::~NSEC() {
+ delete impl_;
+}
+
+string
+NSEC::toText() const {
+ ostringstream s;
+ s << impl_->nextname_;
+ bitmapsToText(impl_->typebits_, s);
+ return (s.str());
+}
+
+void
+NSEC::toWire(OutputBuffer& buffer) const {
+ impl_->nextname_.toWire(buffer);
+ buffer.writeData(&impl_->typebits_[0], impl_->typebits_.size());
+}
+
+void
+NSEC::toWire(AbstractMessageRenderer& renderer) const {
+ // Type NSEC is not "well-known", and name compression must be disabled
+ // per RFC3597.
+ renderer.writeName(impl_->nextname_, false);
+ renderer.writeData(&impl_->typebits_[0], impl_->typebits_.size());
+}
+
+const Name&
+NSEC::getNextName() const {
+ return (impl_->nextname_);
+}
+
+int
+NSEC::compare(const Rdata& other) const {
+ const NSEC& other_nsec = dynamic_cast<const NSEC&>(other);
+
+ int cmp = compareNames(impl_->nextname_, other_nsec.impl_->nextname_);
+ if (cmp != 0) {
+ return (cmp);
+ }
+
+ const size_t this_len = impl_->typebits_.size();
+ const size_t other_len = other_nsec.impl_->typebits_.size();
+ const size_t cmplen = min(this_len, other_len);
+ cmp = memcmp(&impl_->typebits_[0], &other_nsec.impl_->typebits_[0],
+ cmplen);
+ if (cmp != 0) {
+ return (cmp);
+ } else {
+ return ((this_len == other_len) ? 0 : (this_len < other_len) ? -1 : 1);
+ }
+}
+
+} // end of namespace "generic"
+} // end of namespace "rdata"
+} // end of namespace "dns"
+} // end of namespace "isc"
+// 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 <config.h>
+
+#include <util/buffer.h>
+#include <dns/messagerenderer.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+
+#include <boost/foreach.hpp>
+
+#include <string>
+#include <string.h>
+
+using namespace std;
+using namespace isc::util;
+
+namespace isc {
+namespace dns {
+namespace rdata {
+namespace generic {
+
+/// \brief Constructor.
+OPT::PseudoRR::PseudoRR(uint16_t code,
+ boost::shared_ptr<std::vector<uint8_t> >& data) :
+ code_(code),
+ data_(data)
+{
+}
+
+uint16_t
+OPT::PseudoRR::getCode() const {
+ return (code_);
+}
+
+const uint8_t*
+OPT::PseudoRR::getData() const {
+ return (&(*data_)[0]);
+}
+
+uint16_t
+OPT::PseudoRR::getLength() const {
+ return (data_->size());
+}
+
+struct OPTImpl {
+ OPTImpl() :
+ rdlength_(0)
+ {}
+
+ uint16_t rdlength_;
+ std::vector<OPT::PseudoRR> pseudo_rrs_;
+};
+
+/// \brief Default constructor.
+OPT::OPT() :
+ impl_(new OPTImpl)
+{
+}
+
+/// \brief Constructor from string.
+///
+/// This constructor cannot be used, and always throws an exception.
+///
+/// \throw InvalidRdataText OPT RR cannot be constructed from text.
+OPT::OPT(const std::string&) :
+ impl_(NULL)
+{
+ isc_throw(InvalidRdataText, "OPT RR cannot be constructed from text");
+}
+
+/// \brief Constructor with a context of MasterLexer.
+///
+/// This constructor cannot be used, and always throws an exception.
+///
+/// \throw InvalidRdataText OPT RR cannot be constructed from text.
+OPT::OPT(MasterLexer&, const Name*,
+ MasterLoader::Options, MasterLoaderCallbacks&) :
+ impl_(NULL)
+{
+ isc_throw(InvalidRdataText, "OPT RR cannot be constructed from text");
+}
+
+OPT::OPT(InputBuffer& buffer, size_t rdata_len) :
+ impl_(NULL)
+{
+ std::auto_ptr<OPTImpl> impl_ptr(new OPTImpl);
+
+ while (true) {
+ if (rdata_len == 0) {
+ break;
+ }
+
+ if (rdata_len < 4) {
+ isc_throw(InvalidRdataLength,
+ "Pseudo OPT RR record too short: "
+ << rdata_len << " bytes");
+ }
+
+ const uint16_t option_code = buffer.readUint16();
+ const uint16_t option_length = buffer.readUint16();
+ rdata_len -= 4;
+
+ if (static_cast<uint16_t>(impl_ptr->rdlength_ + option_length) <
+ impl_ptr->rdlength_)
+ {
+ isc_throw(InvalidRdataText,
+ "Option length " << option_length
+ << " would overflow OPT RR RDLEN (currently "
+ << impl_ptr->rdlength_ << ").");
+ }
+
+ if (rdata_len < option_length) {
+ isc_throw(InvalidRdataLength, "Corrupt pseudo OPT RR record");
+ }
+
+ boost::shared_ptr<std::vector<uint8_t> >
+ option_data(new std::vector<uint8_t>(option_length));
+ buffer.readData(&(*option_data)[0], option_length);
+ impl_ptr->pseudo_rrs_.push_back(PseudoRR(option_code, option_data));
+ impl_ptr->rdlength_ += option_length;
+ rdata_len -= option_length;
+ }
+
+ impl_ = impl_ptr.release();
+}
+
+OPT::OPT(const OPT& other) :
+ Rdata(), impl_(new OPTImpl(*other.impl_))
+{
+}
+
+OPT&
+OPT::operator=(const OPT& source) {
+ if (this == &source) {
+ return (*this);
+ }
+
+ OPTImpl* newimpl = new OPTImpl(*source.impl_);
+ delete impl_;
+ impl_ = newimpl;
+
+ return (*this);
+}
+
+OPT::~OPT() {
+ delete impl_;
+}
+
+std::string
+OPT::toText() const {
+ isc_throw(isc::InvalidOperation,
+ "OPT RRs do not have a presentation format");
+}
+
+void
+OPT::toWire(OutputBuffer& buffer) const {
+ BOOST_FOREACH(const PseudoRR& pseudo_rr, impl_->pseudo_rrs_) {
+ buffer.writeUint16(pseudo_rr.getCode());
+ const uint16_t length = pseudo_rr.getLength();
+ buffer.writeUint16(length);
+ if (length > 0) {
+ buffer.writeData(pseudo_rr.getData(), length);
+ }
+ }
+}
+
+void
+OPT::toWire(AbstractMessageRenderer& renderer) const {
+ BOOST_FOREACH(const PseudoRR& pseudo_rr, impl_->pseudo_rrs_) {
+ renderer.writeUint16(pseudo_rr.getCode());
+ const uint16_t length = pseudo_rr.getLength();
+ renderer.writeUint16(length);
+ if (length > 0) {
+ renderer.writeData(pseudo_rr.getData(), length);
+ }
+ }
+}
+
+int
+OPT::compare(const Rdata&) const {
+ isc_throw(isc::InvalidOperation,
+ "It is meaningless to compare a set of OPT pseudo RRs; "
+ "they have unspecified order");
+ return (0);
+}
+
+void
+OPT::appendPseudoRR(uint16_t code, const uint8_t* data, uint16_t length) {
+ // See if it overflows 16-bit length field. We only worry about the
+ // pseudo-RR length here, not the whole message length (which should
+ // be checked and enforced elsewhere).
+ if (static_cast<uint16_t>(impl_->rdlength_ + length) <
+ impl_->rdlength_)
+ {
+ isc_throw(isc::InvalidParameter,
+ "Option length " << length
+ << " would overflow OPT RR RDLEN (currently "
+ << impl_->rdlength_ << ").");
+ }
+
+ boost::shared_ptr<std::vector<uint8_t> >
+ option_data(new std::vector<uint8_t>(length));
+ std::memcpy(&(*option_data)[0], data, length);
+ impl_->pseudo_rrs_.push_back(PseudoRR(code, option_data));
+ impl_->rdlength_ += length;
+}
+
+const std::vector<OPT::PseudoRR>&
+OPT::getPseudoRRs() const {
+ return (impl_->pseudo_rrs_);
+}
+
+} // end of namespace "generic"
+} // end of namespace "rdata"
+} // end of namespace "dns"
+} // end of namespace "isc"
+// 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 <config.h>
+
+#include <string>
+
+#include <util/buffer.h>
+#include <dns/name.h>
+#include <dns/messagerenderer.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+
+#include <dns/rdata/generic/detail/lexer_util.h>
+
+using namespace std;
+using namespace isc::util;
+using isc::dns::rdata::generic::detail::createNameFromLexer;
+
+namespace isc {
+namespace dns {
+namespace rdata {
+namespace generic {
+
+/// \brief Constructor from string.
+///
+/// The given string must represent a valid PTR 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.
+///
+/// The PTRDNAME must be absolute since there's no parameter that
+/// specifies the origin name; if it is not absolute, \c
+/// MissingNameOrigin exception will be thrown. These must not be
+/// represented as a quoted string.
+///
+/// \throw Others Exception from the Name and RRTTL constructors.
+/// \throw InvalidRdataText Other general syntax errors.
+PTR::PTR(const std::string& type_str) :
+ // Fill in dummy name and replace them soon below.
+ ptr_name_(Name::ROOT_NAME())
+{
+ try {
+ std::istringstream ss(type_str);
+ MasterLexer lexer;
+ lexer.pushSource(ss);
+
+ ptr_name_ = createNameFromLexer(lexer, NULL);
+
+ if (lexer.getNextToken().getType() != MasterToken::END_OF_FILE) {
+ isc_throw(InvalidRdataText, "extra input text for PTR: "
+ << type_str);
+ }
+ } catch (const MasterLexer::LexerError& ex) {
+ isc_throw(InvalidRdataText, "Failed to construct PTR from '" <<
+ type_str << "': " << ex.what());
+ }
+}
+
+PTR::PTR(InputBuffer& buffer, size_t) :
+ ptr_name_(buffer)
+{
+ // we don't need rdata_len for parsing. if necessary, the caller will
+ // check consistency.
+}
+
+/// \brief Constructor with a context of MasterLexer.
+///
+/// The \c lexer should point to the beginning of valid textual
+/// representation of a PTR RDATA. The PTRDNAME field can be
+/// non-absolute if \c origin is non-NULL, in which case \c origin is
+/// used to make it absolute. It must not be represented as a quoted
+/// string.
+///
+/// \throw MasterLexer::LexerError General parsing error such as missing field.
+/// \throw Other Exceptions from the Name and RRTTL constructors if
+/// construction of textual fields as these objects fail.
+///
+/// \param lexer A \c MasterLexer object parsing a master file for the
+/// RDATA to be created
+/// \param origin If non NULL, specifies the origin of PTRDNAME when it
+/// is non-absolute.
+PTR::PTR(MasterLexer& lexer, const Name* origin,
+ MasterLoader::Options, MasterLoaderCallbacks&) :
+ ptr_name_(createNameFromLexer(lexer, origin))
+{}
+
+PTR::PTR(const PTR& source) :
+ Rdata(), ptr_name_(source.ptr_name_)
+{}
+
+std::string
+PTR::toText() const {
+ return (ptr_name_.toText());
+}
+
+void
+PTR::toWire(OutputBuffer& buffer) const {
+ ptr_name_.toWire(buffer);
+}
+
+void
+PTR::toWire(AbstractMessageRenderer& renderer) const {
+ renderer.writeName(ptr_name_);
+}
+
+int
+PTR::compare(const Rdata& other) const {
+ // The compare method normally begins with this dynamic cast.
+ const PTR& other_ptr = dynamic_cast<const PTR&>(other);
+
+ return (compareNames(ptr_name_, other_ptr.ptr_name_));
+
+}
+
+const Name&
+PTR::getPTRName() const {
+ return (ptr_name_);
+}
+
+} // end of namespace "generic"
+} // end of namespace "rdata"
+} // end of namespace "dns"
+} // end of namespace "isc"
+// Copyright (C) 2011-2013 Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// 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 <string>
+#include <sstream>
+
+#include <util/buffer.h>
+
+#include <dns/messagerenderer.h>
+#include <dns/name.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+#include <dns/rdata/generic/detail/lexer_util.h>
+
+using namespace std;
+using namespace isc::dns;
+using namespace isc::util;
+using isc::dns::rdata::generic::detail::createNameFromLexer;
+
+namespace isc {
+namespace dns {
+namespace rdata {
+namespace generic {
+
+/// \brief Constructor from string.
+///
+/// \c rp_str must be formatted as follows:
+/// \code <mailbox name> <text name>
+/// \endcode
+/// where both fields must represent a valid domain name.
+///
+/// \throw InvalidRdataText The number of RDATA fields (must be 2) is
+/// incorrect.
+/// \throw std::bad_alloc Memory allocation for names fails.
+/// \throw Other The constructor of the \c Name class will throw if the
+/// given name is invalid.
+RP::RP(const std::string& rp_str) :
+ // We cannot construct both names in the initialization list due to the
+ // necessary text processing, so we have to initialize them with a dummy
+ // name and replace them later.
+ mailbox_(Name::ROOT_NAME()), text_(Name::ROOT_NAME())
+{
+ try {
+ std::istringstream ss(rp_str);
+ MasterLexer lexer;
+ lexer.pushSource(ss);
+
+ mailbox_ = createNameFromLexer(lexer, NULL);
+ text_ = createNameFromLexer(lexer, NULL);
+
+ if (lexer.getNextToken().getType() != MasterToken::END_OF_FILE) {
+ isc_throw(InvalidRdataText, "extra input text for RP: "
+ << rp_str);
+ }
+ } catch (const MasterLexer::LexerError& ex) {
+ isc_throw(InvalidRdataText, "Failed to construct RP from '" <<
+ rp_str << "': " << ex.what());
+ }
+}
+
+/// \brief Constructor with a context of MasterLexer.
+///
+/// The \c lexer should point to the beginning of valid textual representation
+/// of an RP RDATA. The MAILBOX and TEXT fields can be non-absolute if \c
+/// origin is non-NULL, in which case \c origin is used to make them absolute.
+///
+/// \throw MasterLexer::LexerError General parsing error such as missing field.
+/// \throw Other Exceptions from the Name and constructors if construction of
+/// textual fields as these objects fail.
+///
+/// \param lexer A \c MasterLexer object parsing a master file for the
+/// RDATA to be created
+/// \param origin If non NULL, specifies the origin of SERVER when it
+/// is non-absolute.
+RP::RP(MasterLexer& lexer, const Name* origin,
+ MasterLoader::Options, MasterLoaderCallbacks&) :
+ mailbox_(createNameFromLexer(lexer, origin)),
+ text_(createNameFromLexer(lexer, origin))
+{
+}
+
+/// \brief Constructor from wire-format data.
+///
+/// This constructor doesn't check the validity of the second parameter (rdata
+/// length) for parsing.
+/// If necessary, the caller will check consistency.
+///
+/// \throw std::bad_alloc Memory allocation for names fails.
+/// \throw Other The constructor of the \c Name class will throw if the
+/// names in the wire is invalid.
+RP::RP(InputBuffer& buffer, size_t) : mailbox_(buffer), text_(buffer) {
+}
+
+/// \brief Copy constructor.
+///
+/// \throw std::bad_alloc Memory allocation fails in copying internal
+/// member variables (this should be very rare).
+RP::RP(const RP& other) :
+ Rdata(), mailbox_(other.mailbox_), text_(other.text_)
+{}
+
+/// \brief Convert the \c RP to a string.
+///
+/// The output of this method is formatted as described in the "from string"
+/// constructor (\c RP(const std::string&))).
+///
+/// \throw std::bad_alloc Internal resource allocation fails.
+///
+/// \return A \c string object that represents the \c RP object.
+std::string
+RP::toText() const {
+ return (mailbox_.toText() + " " + text_.toText());
+}
+
+/// \brief Render the \c RP in the wire format without name compression.
+///
+/// \throw std::bad_alloc Internal resource allocation fails.
+///
+/// \param buffer An output buffer to store the wire data.
+void
+RP::toWire(OutputBuffer& buffer) const {
+ mailbox_.toWire(buffer);
+ text_.toWire(buffer);
+}
+
+/// \brief Render the \c RP in the wire format with taking into account
+/// compression.
+///
+// Type RP is not "well-known", and name compression must be disabled
+// per RFC3597.
+///
+/// \throw std::bad_alloc Internal resource allocation fails.
+///
+/// \param renderer DNS message rendering context that encapsulates the
+/// output buffer and name compression information.
+void
+RP::toWire(AbstractMessageRenderer& renderer) const {
+ renderer.writeName(mailbox_, false);
+ renderer.writeName(text_, false);
+}
+
+/// \brief Compare two instances of \c RP RDATA.
+///
+/// See documentation in \c Rdata.
+int
+RP::compare(const Rdata& other) const {
+ const RP& other_rp = dynamic_cast<const RP&>(other);
+
+ const int cmp = compareNames(mailbox_, other_rp.mailbox_);
+ if (cmp != 0) {
+ return (cmp);
+ }
+ return (compareNames(text_, other_rp.text_));
+}
+
+} // end of namespace "generic"
+} // end of namespace "rdata"
+} // end of namespace "dns"
+} // end of namespace "isc"
+// 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 <string>
+#include <iomanip>
+#include <iostream>
+#include <sstream>
+#include <vector>
+
+#include <boost/lexical_cast.hpp>
+
+#include <util/encode/base64.h>
+#include <util/buffer.h>
+#include <util/time_utilities.h>
+#include <dns/messagerenderer.h>
+#include <dns/name.h>
+#include <dns/rrtype.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+#include <dns/rdata/generic/detail/lexer_util.h>
+
+#include <stdio.h>
+#include <time.h>
+
+using namespace std;
+using namespace isc::util;
+using namespace isc::util::encode;
+using isc::dns::rdata::generic::detail::createNameFromLexer;
+
+namespace isc {
+namespace dns {
+namespace rdata {
+namespace generic {
+
+namespace {
+// This is the minimum necessary length of all wire-format RRSIG RDATA:
+// - two 8-bit fields (algorithm and labels)
+// - two 16-bit fields (covered and tag)
+// - three 32-bit fields (original TTL, expire and inception)
+const size_t RRSIG_MINIMUM_LEN = 2 * sizeof(uint8_t) + 2 * sizeof(uint16_t) +
+ 3 * sizeof(uint32_t);
+}
+
+struct RRSIGImpl {
+ // straightforward representation of RRSIG RDATA fields
+ RRSIGImpl(const RRType& covered, uint8_t algorithm, uint8_t labels,
+ uint32_t originalttl, uint32_t timeexpire,
+ uint32_t timeinception, uint16_t tag, const Name& signer,
+ const vector<uint8_t>& signature) :
+ covered_(covered), algorithm_(algorithm), labels_(labels),
+ originalttl_(originalttl), timeexpire_(timeexpire),
+ timeinception_(timeinception), tag_(tag), signer_(signer),
+ signature_(signature)
+ {}
+
+ const RRType covered_;
+ uint8_t algorithm_;
+ uint8_t labels_;
+ uint32_t originalttl_;
+ uint32_t timeexpire_;
+ uint32_t timeinception_;
+ uint16_t tag_;
+ const Name signer_;
+ const vector<uint8_t> signature_;
+};
+
+// helper function for string and lexer constructors
+RRSIGImpl*
+RRSIG::constructFromLexer(MasterLexer& lexer, const Name* origin) {
+ const RRType covered(lexer.getNextToken(MasterToken::STRING).getString());
+ const uint32_t algorithm =
+ lexer.getNextToken(MasterToken::NUMBER).getNumber();
+ if (algorithm > 0xff) {
+ isc_throw(InvalidRdataText, "RRSIG algorithm out of range");
+ }
+ const uint32_t labels =
+ lexer.getNextToken(MasterToken::NUMBER).getNumber();
+ if (labels > 0xff) {
+ isc_throw(InvalidRdataText, "RRSIG labels out of range");
+ }
+ const uint32_t originalttl =
+ lexer.getNextToken(MasterToken::NUMBER).getNumber();
+ const uint32_t timeexpire =
+ timeFromText32(lexer.getNextToken(MasterToken::STRING).getString());
+ const uint32_t timeinception =
+ timeFromText32(lexer.getNextToken(MasterToken::STRING).getString());
+ const uint32_t tag =
+ lexer.getNextToken(MasterToken::NUMBER).getNumber();
+ if (tag > 0xffff) {
+ isc_throw(InvalidRdataText, "RRSIG key tag out of range");
+ }
+ const Name& signer = createNameFromLexer(lexer, origin);
+
+ string signature_txt;
+ string signature_part;
+ // Whitespace is allowed within base64 text, so read to the end of input.
+ while (true) {
+ const MasterToken& token =
+ lexer.getNextToken(MasterToken::STRING, true);
+ if ((token.getType() == MasterToken::END_OF_FILE) ||
+ (token.getType() == MasterToken::END_OF_LINE)) {
+ break;
+ }
+ token.getString(signature_part);
+ signature_txt.append(signature_part);
+ }
+ lexer.ungetToken();
+
+ vector<uint8_t> signature;
+ // missing signature is okay
+ if (signature_txt.size() > 0) {
+ decodeBase64(signature_txt, signature);
+ }
+
+ return (new RRSIGImpl(covered, algorithm, labels,
+ originalttl, timeexpire, timeinception,
+ static_cast<uint16_t>(tag), signer, signature));
+}
+
+/// \brief Constructor from string.
+///
+/// The given string must represent a valid RRSIG 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.
+///
+/// The Signer's Name must be absolute since there's no parameter that
+/// specifies the origin name; if this is not absolute, \c MissingNameOrigin
+/// exception will be thrown. This must not be represented as a quoted
+/// string.
+///
+/// See the construction that takes \c MasterLexer for other fields.
+///
+/// \throw Others Exception from the Name constructor.
+/// \throw InvalidRdataText Other general syntax errors.
+RRSIG::RRSIG(const std::string& rrsig_str) :
+ impl_(NULL)
+{
+ // We use auto_ptr here because if there is an exception in this
+ // constructor, the destructor is not called and there could be a
+ // leak of the RRSIGImpl that constructFromLexer() returns.
+ std::auto_ptr<RRSIGImpl> impl_ptr(NULL);
+
+ try {
+ std::istringstream iss(rrsig_str);
+ MasterLexer lexer;
+ lexer.pushSource(iss);
+
+ impl_ptr.reset(constructFromLexer(lexer, NULL));
+
+ if (lexer.getNextToken().getType() != MasterToken::END_OF_FILE) {
+ isc_throw(InvalidRdataText, "extra input text for RRSIG: "
+ << rrsig_str);
+ }
+ } catch (const MasterLexer::LexerError& ex) {
+ isc_throw(InvalidRdataText, "Failed to construct RRSIG from '" <<
+ rrsig_str << "': " << ex.what());
+ }
+
+ impl_ = impl_ptr.release();
+}
+
+/// \brief Constructor with a context of MasterLexer.
+///
+/// The \c lexer should point to the beginning of valid textual representation
+/// of an RRSIG RDATA. The Signer's Name fields can be non absolute if \c
+/// origin is non NULL, in which case \c origin is used to make it absolute.
+/// This must not be represented as a quoted string.
+///
+/// The Original TTL field is a valid decimal representation of an unsigned
+/// 32-bit integer. Note that alternate textual representations of \c RRTTL,
+/// such as "1H" for 3600 seconds, are not allowed here.
+///
+/// \throw MasterLexer::LexerError General parsing error such as missing field.
+/// \throw Other Exceptions from the Name constructor if
+/// construction of textual fields as these objects fail.
+///
+/// \param lexer A \c MasterLexer object parsing a master file for the
+/// RDATA to be created
+/// \param origin If non NULL, specifies the origin of Signer's Name when
+/// it is non absolute.
+RRSIG::RRSIG(MasterLexer& lexer, const Name* origin,
+ MasterLoader::Options, MasterLoaderCallbacks&) :
+ impl_(constructFromLexer(lexer, origin))
+{
+}
+
+RRSIG::RRSIG(InputBuffer& buffer, size_t rdata_len) {
+ size_t pos = buffer.getPosition();
+
+ if (rdata_len < RRSIG_MINIMUM_LEN) {
+ isc_throw(InvalidRdataLength, "RRSIG too short");
+ }
+
+ RRType covered(buffer);
+ uint8_t algorithm = buffer.readUint8();
+ uint8_t labels = buffer.readUint8();
+ uint32_t originalttl = buffer.readUint32();
+ uint32_t timeexpire = buffer.readUint32();
+ uint32_t timeinception = buffer.readUint32();
+ uint16_t tag = buffer.readUint16();
+ Name signer(buffer);
+
+ // rdata_len must be sufficiently large to hold non empty signature data.
+ if (rdata_len <= buffer.getPosition() - pos) {
+ isc_throw(InvalidRdataLength, "RRSIG too short");
+ }
+ rdata_len -= (buffer.getPosition() - pos);
+
+ vector<uint8_t> signature(rdata_len);
+ buffer.readData(&signature[0], rdata_len);
+
+ impl_ = new RRSIGImpl(covered, algorithm, labels,
+ originalttl, timeexpire, timeinception, tag,
+ signer, signature);
+}
+
+RRSIG::RRSIG(const RRSIG& source) :
+ Rdata(), impl_(new RRSIGImpl(*source.impl_))
+{}
+
+RRSIG&
+RRSIG::operator=(const RRSIG& source) {
+ if (this == &source) {
+ return (*this);
+ }
+
+ RRSIGImpl* newimpl = new RRSIGImpl(*source.impl_);
+ delete impl_;
+ impl_ = newimpl;
+
+ return (*this);
+}
+
+RRSIG::~RRSIG() {
+ delete impl_;
+}
+
+string
+RRSIG::toText() const {
+ return (impl_->covered_.toText() +
+ " " + boost::lexical_cast<string>(static_cast<int>(impl_->algorithm_))
+ + " " + boost::lexical_cast<string>(static_cast<int>(impl_->labels_))
+ + " " + boost::lexical_cast<string>(impl_->originalttl_)
+ + " " + timeToText32(impl_->timeexpire_)
+ + " " + timeToText32(impl_->timeinception_)
+ + " " + boost::lexical_cast<string>(impl_->tag_)
+ + " " + impl_->signer_.toText()
+ + " " + encodeBase64(impl_->signature_));
+}
+
+void
+RRSIG::toWire(OutputBuffer& buffer) const {
+ impl_->covered_.toWire(buffer);
+ buffer.writeUint8(impl_->algorithm_);
+ buffer.writeUint8(impl_->labels_);
+ buffer.writeUint32(impl_->originalttl_);
+ buffer.writeUint32(impl_->timeexpire_);
+ buffer.writeUint32(impl_->timeinception_);
+ buffer.writeUint16(impl_->tag_);
+ impl_->signer_.toWire(buffer);
+ buffer.writeData(&impl_->signature_[0], impl_->signature_.size());
+}
+
+void
+RRSIG::toWire(AbstractMessageRenderer& renderer) const {
+ impl_->covered_.toWire(renderer);
+ renderer.writeUint8(impl_->algorithm_);
+ renderer.writeUint8(impl_->labels_);
+ renderer.writeUint32(impl_->originalttl_);
+ renderer.writeUint32(impl_->timeexpire_);
+ renderer.writeUint32(impl_->timeinception_);
+ renderer.writeUint16(impl_->tag_);
+ renderer.writeName(impl_->signer_, false);
+ renderer.writeData(&impl_->signature_[0], impl_->signature_.size());
+}
+
+int
+RRSIG::compare(const Rdata& other) const {
+ const RRSIG& other_rrsig = dynamic_cast<const RRSIG&>(other);
+
+ if (impl_->covered_.getCode() != other_rrsig.impl_->covered_.getCode()) {
+ return (impl_->covered_.getCode() <
+ other_rrsig.impl_->covered_.getCode() ? -1 : 1);
+ }
+ if (impl_->algorithm_ != other_rrsig.impl_->algorithm_) {
+ return (impl_->algorithm_ < other_rrsig.impl_->algorithm_ ? -1 : 1);
+ }
+ if (impl_->labels_ != other_rrsig.impl_->labels_) {
+ return (impl_->labels_ < other_rrsig.impl_->labels_ ? -1 : 1);
+ }
+ if (impl_->originalttl_ != other_rrsig.impl_->originalttl_) {
+ return (impl_->originalttl_ < other_rrsig.impl_->originalttl_ ?
+ -1 : 1);
+ }
+ if (impl_->timeexpire_ != other_rrsig.impl_->timeexpire_) {
+ return (impl_->timeexpire_ < other_rrsig.impl_->timeexpire_ ?
+ -1 : 1);
+ }
+ if (impl_->timeinception_ != other_rrsig.impl_->timeinception_) {
+ return (impl_->timeinception_ < other_rrsig.impl_->timeinception_ ?
+ -1 : 1);
+ }
+ if (impl_->tag_ != other_rrsig.impl_->tag_) {
+ return (impl_->tag_ < other_rrsig.impl_->tag_ ? -1 : 1);
+ }
+
+ int cmp = compareNames(impl_->signer_, other_rrsig.impl_->signer_);
+ if (cmp != 0) {
+ return (cmp);
+ }
+
+ size_t this_len = impl_->signature_.size();
+ size_t other_len = other_rrsig.impl_->signature_.size();
+ size_t cmplen = min(this_len, other_len);
+ cmp = memcmp(&impl_->signature_[0], &other_rrsig.impl_->signature_[0],
+ cmplen);
+ if (cmp != 0) {
+ return (cmp);
+ } else {
+ return ((this_len == other_len) ? 0 : (this_len < other_len) ? -1 : 1);
+ }
+}
+
+const RRType&
+RRSIG::typeCovered() const {
+ return (impl_->covered_);
+}
+
+} // end of namespace "generic"
+} // end of namespace "rdata"
+} // end of namespace "dns"
+} // end of namespace "isc"
+// 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 <config.h>
+
+#include <exceptions/exceptions.h>
+
+#include <util/buffer.h>
+#include <dns/name.h>
+#include <dns/master_lexer.h>
+#include <dns/master_loader.h>
+#include <dns/master_loader_callbacks.h>
+#include <dns/messagerenderer.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+
+#include <dns/rdata/generic/detail/lexer_util.h>
+
+#include <boost/static_assert.hpp>
+#include <boost/lexical_cast.hpp>
+
+#include <string>
+#include <sstream>
+
+using namespace std;
+using boost::lexical_cast;
+using namespace isc::util;
+using isc::dns::rdata::generic::detail::createNameFromLexer;
+
+namespace isc {
+namespace dns {
+namespace rdata {
+namespace generic {
+
+SOA::SOA(InputBuffer& buffer, size_t) :
+ mname_(buffer), rname_(buffer)
+{
+ // we don't need rdata_len for parsing. if necessary, the caller will
+ // check consistency.
+ buffer.readData(numdata_, sizeof(numdata_));
+}
+
+namespace {
+void
+fillParameters(MasterLexer& lexer, uint8_t numdata[20]) {
+ // Copy serial, refresh, retry, expire, minimum. We accept the extended
+ // TTL-compatible style for the latter four.
+ OutputBuffer buffer(20);
+ buffer.writeUint32(lexer.getNextToken(MasterToken::NUMBER).getNumber());
+ for (int i = 0; i < 4; ++i) {
+ buffer.writeUint32(RRTTL(lexer.getNextToken(MasterToken::STRING).
+ getString()).getValue());
+ }
+ memcpy(numdata, buffer.getData(), buffer.getLength());
+}
+}
+
+/// \brief Constructor from string.
+///
+/// The given string must represent a valid SOA 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.
+///
+/// The MNAME and RNAME must be absolute since there's no parameter that
+/// specifies the origin name; if these are not absolute, \c MissingNameOrigin
+/// exception will be thrown. These must not be represented as a quoted
+/// string.
+///
+/// See the construction that takes \c MasterLexer for other fields.
+///
+/// \throw Others Exception from the Name and RRTTL constructors.
+/// \throw InvalidRdataText Other general syntax errors.
+SOA::SOA(const std::string& soastr) :
+ // Fill in dummy name and replace them soon below.
+ mname_(Name::ROOT_NAME()), rname_(Name::ROOT_NAME())
+{
+ try {
+ std::istringstream ss(soastr);
+ MasterLexer lexer;
+ lexer.pushSource(ss);
+
+ mname_ = createNameFromLexer(lexer, NULL);
+ rname_ = createNameFromLexer(lexer, NULL);
+ fillParameters(lexer, numdata_);
+
+ if (lexer.getNextToken().getType() != MasterToken::END_OF_FILE) {
+ isc_throw(InvalidRdataText, "extra input text for SOA: "
+ << soastr);
+ }
+ } catch (const MasterLexer::LexerError& ex) {
+ isc_throw(InvalidRdataText, "Failed to construct SOA from '" <<
+ soastr << "': " << ex.what());
+ }
+}
+
+/// \brief Constructor with a context of MasterLexer.
+///
+/// The \c lexer should point to the beginning of valid textual representation
+/// of an SOA RDATA. The MNAME and RNAME fields can be non absolute if
+/// \c origin is non NULL, in which case \c origin is used to make them
+/// absolute. These must not be represented as a quoted string.
+///
+/// The REFRESH, RETRY, EXPIRE, and MINIMUM fields can be either a valid
+/// decimal representation of an unsigned 32-bit integer or other
+/// valid textual representation of \c RRTTL such as "1H" (which means 3600).
+///
+/// \throw MasterLexer::LexerError General parsing error such as missing field.
+/// \throw Other Exceptions from the Name and RRTTL constructors if
+/// construction of textual fields as these objects fail.
+///
+/// \param lexer A \c MasterLexer object parsing a master file for the
+/// RDATA to be created
+/// \param origin If non NULL, specifies the origin of MNAME and RNAME when
+/// they are non absolute.
+SOA::SOA(MasterLexer& lexer, const Name* origin,
+ MasterLoader::Options, MasterLoaderCallbacks&) :
+ mname_(createNameFromLexer(lexer, origin)),
+ rname_(createNameFromLexer(lexer, origin))
+{
+ fillParameters(lexer, numdata_);
+}
+
+SOA::SOA(const Name& mname, const Name& rname, uint32_t serial,
+ uint32_t refresh, uint32_t retry, uint32_t expire, uint32_t minimum) :
+ mname_(mname), rname_(rname)
+{
+ OutputBuffer b(20);
+ b.writeUint32(serial);
+ b.writeUint32(refresh);
+ b.writeUint32(retry);
+ b.writeUint32(expire);
+ b.writeUint32(minimum);
+ assert(b.getLength() == sizeof(numdata_));
+ memcpy(numdata_, b.getData(), sizeof(numdata_));
+}
+
+SOA::SOA(const SOA& other) :
+ Rdata(), mname_(other.mname_), rname_(other.rname_)
+{
+ memcpy(numdata_, other.numdata_, sizeof(numdata_));
+}
+
+void
+SOA::toWire(OutputBuffer& buffer) const {
+ mname_.toWire(buffer);
+ rname_.toWire(buffer);
+ buffer.writeData(numdata_, sizeof(numdata_));
+}
+
+void
+SOA::toWire(AbstractMessageRenderer& renderer) const {
+ renderer.writeName(mname_);
+ renderer.writeName(rname_);
+ renderer.writeData(numdata_, sizeof(numdata_));
+}
+
+Serial
+SOA::getSerial() const {
+ InputBuffer b(numdata_, sizeof(numdata_));
+ return (Serial(b.readUint32()));
+}
+
+uint32_t
+SOA::getMinimum() const {
+ // Make sure the buffer access is safe.
+ BOOST_STATIC_ASSERT(sizeof(numdata_) ==
+ sizeof(uint32_t) * 4 + sizeof(uint32_t));
+
+ InputBuffer b(&numdata_[sizeof(uint32_t) * 4], sizeof(uint32_t));
+ return (b.readUint32());
+}
+
+string
+SOA::toText() const {
+ InputBuffer b(numdata_, sizeof(numdata_));
+ uint32_t serial = b.readUint32();
+ uint32_t refresh = b.readUint32();
+ uint32_t retry = b.readUint32();
+ uint32_t expire = b.readUint32();
+ uint32_t minimum = b.readUint32();
+
+ return (mname_.toText() + " " + rname_.toText() + " " +
+ lexical_cast<string>(serial) + " " +
+ lexical_cast<string>(refresh) + " " +
+ lexical_cast<string>(retry) + " " +
+ lexical_cast<string>(expire) + " " +
+ lexical_cast<string>(minimum));
+}
+
+int
+SOA::compare(const Rdata& other) const {
+ const SOA& other_soa = dynamic_cast<const SOA&>(other);
+
+ int order = compareNames(mname_, other_soa.mname_);
+ if (order != 0) {
+ return (order);
+ }
+
+ order = compareNames(rname_, other_soa.rname_);
+ if (order != 0) {
+ return (order);
+ }
+
+ return (memcmp(numdata_, other_soa.numdata_, sizeof(numdata_)));
+}
+
+} // end of namespace "generic"
+} // end of namespace "rdata"
+} // end of namespace "dns"
+} // end of namespace "isc"
+// 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 <stdint.h>
+#include <string.h>
+
+#include <string>
+#include <vector>
+
+#include <util/buffer.h>
+#include <dns/exceptions.h>
+#include <dns/messagerenderer.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+
+/// This class implements the basic interfaces inherited from the abstract
+/// \c rdata::Rdata class. The semantics of the class is provided by
+/// a copy of instantiated TXTLikeImpl class common to both TXT and SPF.
+#include <dns/rdata/generic/detail/txt_like.h>
+
+using namespace std;
+using namespace isc::util;
+
+namespace isc {
+namespace dns {
+namespace rdata {
+namespace generic {
+
+/// \brief The assignment operator
+///
+/// It internally allocates a resource, and if it fails a corresponding
+/// standard exception will be thrown.
+/// This method never throws an exception otherwise.
+SPF&
+SPF::operator=(const SPF& source) {
+ if (this == &source) {
+ return (*this);
+ }
+
+ SPFImpl* newimpl = new SPFImpl(*source.impl_);
+ delete impl_;
+ impl_ = newimpl;
+
+ return (*this);
+}
+
+/// \brief The destructor
+SPF::~SPF() {
+ delete impl_;
+}
+
+/// \brief Constructor from wire-format data.
+///
+/// It internally allocates a resource, and if it fails a corresponding
+/// standard exception will be thrown.
+SPF::SPF(InputBuffer& buffer, size_t rdata_len) :
+ impl_(new SPFImpl(buffer, rdata_len))
+{}
+
+/// \brief Constructor using the master lexer.
+///
+/// This implementation only uses the \c lexer parameters; others are
+/// ignored.
+///
+/// \throw CharStringTooLong the parameter string length exceeds maximum.
+/// \throw InvalidRdataText the method cannot process the parameter data
+///
+/// \param lexer A \c MasterLexer object parsing a master file for this
+/// RDATA.
+SPF::SPF(MasterLexer& lexer, const Name*, MasterLoader::Options,
+ MasterLoaderCallbacks&) :
+ impl_(new SPFImpl(lexer))
+{}
+
+/// \brief Constructor from string.
+///
+/// It internally allocates a resource, and if it fails a corresponding
+/// standard exception will be thrown.
+SPF::SPF(const std::string& txtstr) :
+ impl_(new SPFImpl(txtstr))
+{}
+
+/// \brief Copy constructor
+///
+/// It internally allocates a resource, and if it fails a corresponding
+/// standard exception will be thrown.
+SPF::SPF(const SPF& other) :
+ Rdata(), impl_(new SPFImpl(*other.impl_))
+{}
+
+/// \brief Render the \c SPF in the wire format to a OutputBuffer object
+///
+/// \return is the return of the corresponding implementation method.
+void
+SPF::toWire(OutputBuffer& buffer) const {
+ impl_->toWire(buffer);
+}
+
+/// \brief Render the \c SPF in the wire format to an AbstractMessageRenderer
+/// object
+///
+/// \return is the return of the corresponding implementation method.
+void
+SPF::toWire(AbstractMessageRenderer& renderer) const {
+ impl_->toWire(renderer);
+}
+
+/// \brief Convert the \c SPF to a string.
+///
+/// \return is the return of the corresponding implementation method.
+string
+SPF::toText() const {
+ return (impl_->toText());
+}
+
+/// \brief Compare two instances of \c SPF RDATA.
+///
+/// This method compares \c this and the \c other \c SPF objects.
+///
+/// This method is expected to be used in a polymorphic way, and the
+/// parameter to compare against is therefore of the abstract \c Rdata class.
+/// However, comparing two \c Rdata objects of different RR types
+/// is meaningless, and \c other must point to a \c SPF object;
+/// otherwise, the standard \c bad_cast exception will be thrown.
+///
+/// \param other the right-hand operand to compare against.
+/// \return is the return of the corresponding implementation method.
+int
+SPF::compare(const Rdata& other) const {
+ const SPF& other_txt = dynamic_cast<const SPF&>(other);
+
+ return (impl_->compare(*other_txt.impl_));
+}
+
+} // end of namespace "generic"
+} // end of namespace "rdata"
+} // end of namespace "dns"
+} // end of namespace "isc"
+// Copyright (C) 2012-2013 Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// 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 <config.h>
+
+#include <boost/lexical_cast.hpp>
+
+#include <exceptions/exceptions.h>
+
+#include <util/buffer.h>
+#include <util/encode/hex.h>
+#include <dns/name.h>
+#include <dns/messagerenderer.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+
+using namespace std;
+using boost::lexical_cast;
+using namespace isc::util;
+using namespace isc::util::encode;
+
+namespace isc {
+namespace dns {
+namespace rdata {
+namespace generic {
+
+struct SSHFPImpl {
+ // straightforward representation of SSHFP RDATA fields
+ SSHFPImpl(uint8_t algorithm, uint8_t fingerprint_type,
+ const vector<uint8_t>& fingerprint) :
+ algorithm_(algorithm),
+ fingerprint_type_(fingerprint_type),
+ fingerprint_(fingerprint)
+ {}
+
+ uint8_t algorithm_;
+ uint8_t fingerprint_type_;
+ const vector<uint8_t> fingerprint_;
+};
+
+// helper function for string and lexer constructors
+SSHFPImpl*
+SSHFP::constructFromLexer(MasterLexer& lexer) {
+ const uint32_t algorithm =
+ lexer.getNextToken(MasterToken::NUMBER).getNumber();
+ if (algorithm > 255) {
+ isc_throw(InvalidRdataText, "SSHFP algorithm number out of range");
+ }
+
+ const uint32_t fingerprint_type =
+ lexer.getNextToken(MasterToken::NUMBER).getNumber();
+ if (fingerprint_type > 255) {
+ isc_throw(InvalidRdataText, "SSHFP fingerprint type out of range");
+ }
+
+ std::string fingerprint_str;
+ std::string fingerprint_substr;
+ while (true) {
+ const MasterToken& token =
+ lexer.getNextToken(MasterToken::STRING, true);
+ if ((token.getType() == MasterToken::END_OF_FILE) ||
+ (token.getType() == MasterToken::END_OF_LINE)) {
+ break;
+ }
+ token.getString(fingerprint_substr);
+ fingerprint_str.append(fingerprint_substr);
+ }
+ lexer.ungetToken();
+
+ vector<uint8_t> fingerprint;
+ // If fingerprint is missing, it's OK. See the API documentation of the
+ // constructor.
+ if (fingerprint_str.size() > 0) {
+ try {
+ decodeHex(fingerprint_str, fingerprint);
+ } catch (const isc::BadValue& e) {
+ isc_throw(InvalidRdataText, "Bad SSHFP fingerprint: " << e.what());
+ }
+ }
+
+ return (new SSHFPImpl(algorithm, fingerprint_type, fingerprint));
+}
+
+/// \brief Constructor from string.
+///
+/// The given string must represent a valid SSHFP 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.
+///
+/// The Algorithm and Fingerprint Type fields must be within their valid
+/// ranges, but are not constrained to the values defined in RFC4255.
+///
+/// The Fingerprint field may be absent, but if present it must contain a
+/// valid hex encoding of the fingerprint. For compatibility with BIND 9,
+/// whitespace is allowed in the hex text (RFC4255 is silent on the matter).
+///
+/// \throw InvalidRdataText if any fields are missing, are out of their
+/// valid ranges or are incorrect, or if the fingerprint is not a valid
+/// hex string.
+///
+/// \param sshfp_str A string containing the RDATA to be created
+SSHFP::SSHFP(const string& sshfp_str) :
+ impl_(NULL)
+{
+ // We use auto_ptr here because if there is an exception in this
+ // constructor, the destructor is not called and there could be a
+ // leak of the SSHFPImpl that constructFromLexer() returns.
+ std::auto_ptr<SSHFPImpl> impl_ptr(NULL);
+
+ try {
+ std::istringstream ss(sshfp_str);
+ MasterLexer lexer;
+ lexer.pushSource(ss);
+
+ impl_ptr.reset(constructFromLexer(lexer));
+
+ if (lexer.getNextToken().getType() != MasterToken::END_OF_FILE) {
+ isc_throw(InvalidRdataText, "extra input text for SSHFP: "
+ << sshfp_str);
+ }
+ } catch (const MasterLexer::LexerError& ex) {
+ isc_throw(InvalidRdataText, "Failed to construct SSHFP from '" <<
+ sshfp_str << "': " << ex.what());
+ }
+
+ impl_ = impl_ptr.release();
+}
+
+/// \brief Constructor with a context of MasterLexer.
+///
+/// The \c lexer should point to the beginning of valid textual representation
+/// of an SSHFP RDATA.
+///
+/// \throw MasterLexer::LexerError General parsing error such as missing field.
+/// \throw InvalidRdataText Fields are out of their valid range or are
+/// incorrect, or if the fingerprint is not a valid hex string.
+///
+/// \param lexer A \c MasterLexer object parsing a master file for the
+/// RDATA to be created
+SSHFP::SSHFP(MasterLexer& lexer, const Name*,
+ MasterLoader::Options, MasterLoaderCallbacks&) :
+ impl_(constructFromLexer(lexer))
+{
+}
+
+/// \brief Constructor from InputBuffer.
+///
+/// The passed buffer must contain a valid SSHFP RDATA.
+///
+/// The Algorithm and Fingerprint Type fields are not checked for unknown
+/// values. It is okay for the fingerprint data to be missing (see the
+/// description of the constructor from string).
+SSHFP::SSHFP(InputBuffer& buffer, size_t rdata_len) {
+ if (rdata_len < 2) {
+ isc_throw(InvalidRdataLength, "SSHFP record too short");
+ }
+
+ const uint8_t algorithm = buffer.readUint8();
+ const uint8_t fingerprint_type = buffer.readUint8();
+
+ vector<uint8_t> fingerprint;
+ rdata_len -= 2;
+ if (rdata_len > 0) {
+ fingerprint.resize(rdata_len);
+ buffer.readData(&fingerprint[0], rdata_len);
+ }
+
+ impl_ = new SSHFPImpl(algorithm, fingerprint_type, fingerprint);
+}
+
+SSHFP::SSHFP(uint8_t algorithm, uint8_t fingerprint_type,
+ const string& fingerprint_txt) :
+ impl_(NULL)
+{
+ vector<uint8_t> fingerprint;
+ try {
+ decodeHex(fingerprint_txt, fingerprint);
+ } catch (const isc::BadValue& e) {
+ isc_throw(InvalidRdataText, "Bad SSHFP fingerprint: " << e.what());
+ }
+
+ impl_ = new SSHFPImpl(algorithm, fingerprint_type, fingerprint);
+}
+
+SSHFP::SSHFP(const SSHFP& other) :
+ Rdata(), impl_(new SSHFPImpl(*other.impl_))
+{}
+
+SSHFP&
+SSHFP::operator=(const SSHFP& source) {
+ if (this == &source) {
+ return (*this);
+ }
+
+ SSHFPImpl* newimpl = new SSHFPImpl(*source.impl_);
+ delete impl_;
+ impl_ = newimpl;
+
+ return (*this);
+}
+
+SSHFP::~SSHFP() {
+ delete impl_;
+}
+
+void
+SSHFP::toWire(OutputBuffer& buffer) const {
+ buffer.writeUint8(impl_->algorithm_);
+ buffer.writeUint8(impl_->fingerprint_type_);
+
+ if (!impl_->fingerprint_.empty()) {
+ buffer.writeData(&impl_->fingerprint_[0],
+ impl_->fingerprint_.size());
+ }
+}
+
+void
+SSHFP::toWire(AbstractMessageRenderer& renderer) const {
+ renderer.writeUint8(impl_->algorithm_);
+ renderer.writeUint8(impl_->fingerprint_type_);
+
+ if (!impl_->fingerprint_.empty()) {
+ renderer.writeData(&impl_->fingerprint_[0],
+ impl_->fingerprint_.size());
+ }
+}
+
+string
+SSHFP::toText() const {
+ return (lexical_cast<string>(static_cast<int>(impl_->algorithm_)) + " " +
+ lexical_cast<string>(static_cast<int>(impl_->fingerprint_type_)) +
+ (impl_->fingerprint_.empty() ? "" :
+ " " + encodeHex(impl_->fingerprint_)));
+}
+
+int
+SSHFP::compare(const Rdata& other) const {
+ const SSHFP& other_sshfp = dynamic_cast<const SSHFP&>(other);
+
+ if (impl_->algorithm_ < other_sshfp.impl_->algorithm_) {
+ return (-1);
+ } else if (impl_->algorithm_ > other_sshfp.impl_->algorithm_) {
+ return (1);
+ }
+
+ if (impl_->fingerprint_type_ < other_sshfp.impl_->fingerprint_type_) {
+ return (-1);
+ } else if (impl_->fingerprint_type_ >
+ other_sshfp.impl_->fingerprint_type_) {
+ return (1);
+ }
+
+ const size_t this_len = impl_->fingerprint_.size();
+ const size_t other_len = other_sshfp.impl_->fingerprint_.size();
+ const size_t cmplen = min(this_len, other_len);
+
+ if (cmplen > 0) {
+ const int cmp = memcmp(&impl_->fingerprint_[0],
+ &other_sshfp.impl_->fingerprint_[0],
+ cmplen);
+ if (cmp != 0) {
+ return (cmp);
+ }
+ }
+
+ if (this_len == other_len) {
+ return (0);
+ } else if (this_len < other_len) {
+ return (-1);
+ } else {
+ return (1);
+ }
+}
+
+uint8_t
+SSHFP::getAlgorithmNumber() const {
+ return (impl_->algorithm_);
+}
+
+uint8_t
+SSHFP::getFingerprintType() const {
+ return (impl_->fingerprint_type_);
+}
+
+const std::vector<uint8_t>&
+SSHFP::getFingerprint() const {
+ return (impl_->fingerprint_);
+}
+
+size_t
+SSHFP::getFingerprintLength() const {
+ return (impl_->fingerprint_.size());
+}
+
+} // end of namespace "generic"
+} // end of namespace "rdata"
+} // end of namespace "dns"
+} // end of namespace "isc"
+// 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.
+
+#include <config.h>
+
+#include <boost/lexical_cast.hpp>
+
+#include <exceptions/exceptions.h>
+
+#include <util/buffer.h>
+#include <util/encode/hex.h>
+#include <dns/name.h>
+#include <dns/messagerenderer.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+#include <dns/rdata_pimpl_holder.h>
+
+using namespace std;
+using boost::lexical_cast;
+using namespace isc::util;
+using namespace isc::util::encode;
+
+namespace isc {
+namespace dns {
+namespace rdata {
+namespace generic {
+
+struct TLSAImpl {
+ // straightforward representation of TLSA RDATA fields
+ TLSAImpl(uint8_t certificate_usage, uint8_t selector,
+ uint8_t matching_type, const vector<uint8_t>& data) :
+ certificate_usage_(certificate_usage),
+ selector_(selector),
+ matching_type_(matching_type),
+ data_(data)
+ {}
+
+ uint8_t certificate_usage_;
+ uint8_t selector_;
+ uint8_t matching_type_;
+ const vector<uint8_t> data_;
+};
+
+// helper function for string and lexer constructors
+TLSAImpl*
+TLSA::constructFromLexer(MasterLexer& lexer) {
+ const uint32_t certificate_usage =
+ lexer.getNextToken(MasterToken::NUMBER).getNumber();
+ if (certificate_usage > 255) {
+ isc_throw(InvalidRdataText,
+ "TLSA certificate usage field out of range");
+ }
+
+ const uint32_t selector =
+ lexer.getNextToken(MasterToken::NUMBER).getNumber();
+ if (selector > 255) {
+ isc_throw(InvalidRdataText,
+ "TLSA selector field out of range");
+ }
+
+ const uint32_t matching_type =
+ lexer.getNextToken(MasterToken::NUMBER).getNumber();
+ if (matching_type > 255) {
+ isc_throw(InvalidRdataText,
+ "TLSA matching type field out of range");
+ }
+
+ std::string certificate_assoc_data;
+ std::string data_substr;
+ while (true) {
+ const MasterToken& token =
+ lexer.getNextToken(MasterToken::STRING, true);
+ if ((token.getType() == MasterToken::END_OF_FILE) ||
+ (token.getType() == MasterToken::END_OF_LINE)) {
+ break;
+ }
+
+ token.getString(data_substr);
+ certificate_assoc_data.append(data_substr);
+ }
+ lexer.ungetToken();
+
+ if (certificate_assoc_data.empty()) {
+ isc_throw(InvalidRdataText, "Empty TLSA certificate association data");
+ }
+
+ vector<uint8_t> data;
+ try {
+ decodeHex(certificate_assoc_data, data);
+ } catch (const isc::BadValue& e) {
+ isc_throw(InvalidRdataText,
+ "Bad TLSA certificate association data: " << e.what());
+ }
+
+ return (new TLSAImpl(certificate_usage, selector, matching_type, data));
+}
+
+/// \brief Constructor from string.
+///
+/// The given string must represent a valid TLSA 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.
+///
+/// The Certificate Usage, Selector and Matching Type fields must be
+/// within their valid ranges, but are not constrained to the values
+/// defined in RFC6698.
+///
+/// The Certificate Association Data Field field may be absent, but if
+/// present it must contain a valid hex encoding of the data. Whitespace
+/// is allowed in the hex text.
+///
+/// \throw InvalidRdataText if any fields are missing, out of their
+/// valid ranges, or are incorrect, or Certificate Association Data is
+/// not a valid hex string.
+///
+/// \param tlsa_str A string containing the RDATA to be created
+TLSA::TLSA(const string& tlsa_str) :
+ impl_(NULL)
+{
+ // We use a smart pointer here because if there is an exception in
+ // this constructor, the destructor is not called and there could be
+ // a leak of the TLSAImpl that constructFromLexer() returns.
+ RdataPimplHolder<TLSAImpl> impl_ptr;
+
+ try {
+ std::istringstream ss(tlsa_str);
+ MasterLexer lexer;
+ lexer.pushSource(ss);
+
+ impl_ptr.reset(constructFromLexer(lexer));
+
+ if (lexer.getNextToken().getType() != MasterToken::END_OF_FILE) {
+ isc_throw(InvalidRdataText, "extra input text for TLSA: "
+ << tlsa_str);
+ }
+ } catch (const MasterLexer::LexerError& ex) {
+ isc_throw(InvalidRdataText, "Failed to construct TLSA from '" <<
+ tlsa_str << "': " << ex.what());
+ }
+
+ impl_ = impl_ptr.release();
+}
+
+/// \brief Constructor with a context of MasterLexer.
+///
+/// The \c lexer should point to the beginning of valid textual representation
+/// of an TLSA RDATA.
+///
+/// \throw MasterLexer::LexerError General parsing error such as missing field.
+/// \throw InvalidRdataText Fields are out of their valid range, or are
+/// incorrect, or Certificate Association Data is not a valid hex string.
+///
+/// \param lexer A \c MasterLexer object parsing a master file for the
+/// RDATA to be created
+TLSA::TLSA(MasterLexer& lexer, const Name*,
+ MasterLoader::Options, MasterLoaderCallbacks&) :
+ impl_(constructFromLexer(lexer))
+{
+}
+
+/// \brief Constructor from InputBuffer.
+///
+/// The passed buffer must contain a valid TLSA RDATA.
+///
+/// The Certificate Usage, Selector and Matching Type fields must be
+/// within their valid ranges, but are not constrained to the values
+/// defined in RFC6698. It is okay for the certificate association data
+/// to be missing (see the description of the constructor from string).
+TLSA::TLSA(InputBuffer& buffer, size_t rdata_len) {
+ if (rdata_len < 3) {
+ isc_throw(InvalidRdataLength, "TLSA record too short");
+ }
+
+ const uint8_t certificate_usage = buffer.readUint8();
+ const uint8_t selector = buffer.readUint8();
+ const uint8_t matching_type = buffer.readUint8();
+
+ vector<uint8_t> data;
+ rdata_len -= 3;
+
+ if (rdata_len == 0) {
+ isc_throw(InvalidRdataLength,
+ "Empty TLSA certificate association data");
+ }
+
+ data.resize(rdata_len);
+ buffer.readData(&data[0], rdata_len);
+
+ impl_ = new TLSAImpl(certificate_usage, selector, matching_type, data);
+}
+
+TLSA::TLSA(uint8_t certificate_usage, uint8_t selector,
+ uint8_t matching_type, const std::string& certificate_assoc_data) :
+ impl_(NULL)
+{
+ if (certificate_assoc_data.empty()) {
+ isc_throw(InvalidRdataText, "Empty TLSA certificate association data");
+ }
+
+ vector<uint8_t> data;
+ try {
+ decodeHex(certificate_assoc_data, data);
+ } catch (const isc::BadValue& e) {
+ isc_throw(InvalidRdataText,
+ "Bad TLSA certificate association data: " << e.what());
+ }
+
+ impl_ = new TLSAImpl(certificate_usage, selector, matching_type, data);
+}
+
+TLSA::TLSA(const TLSA& other) :
+ Rdata(), impl_(new TLSAImpl(*other.impl_))
+{}
+
+TLSA&
+TLSA::operator=(const TLSA& source) {
+ if (this == &source) {
+ return (*this);
+ }
+
+ TLSAImpl* newimpl = new TLSAImpl(*source.impl_);
+ delete impl_;
+ impl_ = newimpl;
+
+ return (*this);
+}
+
+TLSA::~TLSA() {
+ delete impl_;
+}
+
+void
+TLSA::toWire(OutputBuffer& buffer) const {
+ buffer.writeUint8(impl_->certificate_usage_);
+ buffer.writeUint8(impl_->selector_);
+ buffer.writeUint8(impl_->matching_type_);
+
+ // The constructors must ensure that the certificate association
+ // data field is not empty.
+ assert(!impl_->data_.empty());
+ buffer.writeData(&impl_->data_[0], impl_->data_.size());
+}
+
+void
+TLSA::toWire(AbstractMessageRenderer& renderer) const {
+ renderer.writeUint8(impl_->certificate_usage_);
+ renderer.writeUint8(impl_->selector_);
+ renderer.writeUint8(impl_->matching_type_);
+
+ // The constructors must ensure that the certificate association
+ // data field is not empty.
+ assert(!impl_->data_.empty());
+ renderer.writeData(&impl_->data_[0], impl_->data_.size());
+}
+
+string
+TLSA::toText() const {
+ // The constructors must ensure that the certificate association
+ // data field is not empty.
+ assert(!impl_->data_.empty());
+
+ return (lexical_cast<string>(static_cast<int>(impl_->certificate_usage_)) + " " +
+ lexical_cast<string>(static_cast<int>(impl_->selector_)) + " " +
+ lexical_cast<string>(static_cast<int>(impl_->matching_type_)) + " " +
+ encodeHex(impl_->data_));
+}
+
+int
+TLSA::compare(const Rdata& other) const {
+ const TLSA& other_tlsa = dynamic_cast<const TLSA&>(other);
+
+ if (impl_->certificate_usage_ < other_tlsa.impl_->certificate_usage_) {
+ return (-1);
+ } else if (impl_->certificate_usage_ >
+ other_tlsa.impl_->certificate_usage_) {
+ return (1);
+ }
+
+ if (impl_->selector_ < other_tlsa.impl_->selector_) {
+ return (-1);
+ } else if (impl_->selector_ > other_tlsa.impl_->selector_) {
+ return (1);
+ }
+
+ if (impl_->matching_type_ < other_tlsa.impl_->matching_type_) {
+ return (-1);
+ } else if (impl_->matching_type_ >
+ other_tlsa.impl_->matching_type_) {
+ return (1);
+ }
+
+ const size_t this_len = impl_->data_.size();
+ const size_t other_len = other_tlsa.impl_->data_.size();
+ const size_t cmplen = min(this_len, other_len);
+
+ if (cmplen > 0) {
+ const int cmp = memcmp(&impl_->data_[0],
+ &other_tlsa.impl_->data_[0],
+ cmplen);
+ if (cmp != 0) {
+ return (cmp);
+ }
+ }
+
+ if (this_len == other_len) {
+ return (0);
+ } else if (this_len < other_len) {
+ return (-1);
+ } else {
+ return (1);
+ }
+}
+
+uint8_t
+TLSA::getCertificateUsage() const {
+ return (impl_->certificate_usage_);
+}
+
+uint8_t
+TLSA::getSelector() const {
+ return (impl_->selector_);
+}
+
+uint8_t
+TLSA::getMatchingType() const {
+ return (impl_->matching_type_);
+}
+
+const std::vector<uint8_t>&
+TLSA::getData() const {
+ return (impl_->data_);
+}
+
+size_t
+TLSA::getDataLength() const {
+ return (impl_->data_.size());
+}
+
+} // end of namespace "generic"
+} // end of namespace "rdata"
+} // end of namespace "dns"
+} // end of namespace "isc"
+// 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 <stdint.h>
+#include <string.h>
+
+#include <string>
+#include <vector>
+
+#include <util/buffer.h>
+#include <dns/exceptions.h>
+#include <dns/messagerenderer.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+#include <dns/rdata/generic/detail/txt_like.h>
+
+using namespace std;
+using namespace isc::util;
+
+namespace isc {
+namespace dns {
+namespace rdata {
+namespace generic {
+
+TXT&
+TXT::operator=(const TXT& source) {
+ if (this == &source) {
+ return (*this);
+ }
+
+ TXTImpl* newimpl = new TXTImpl(*source.impl_);
+ delete impl_;
+ impl_ = newimpl;
+
+ return (*this);
+}
+
+TXT::~TXT() {
+ delete impl_;
+}
+
+TXT::TXT(InputBuffer& buffer, size_t rdata_len) :
+ impl_(new TXTImpl(buffer, rdata_len))
+{}
+
+/// \brief Constructor using the master lexer.
+///
+/// This implementation only uses the \c lexer parameters; others are
+/// ignored.
+///
+/// \throw CharStringTooLong the parameter string length exceeds maximum.
+/// \throw InvalidRdataText the method cannot process the parameter data
+///
+/// \param lexer A \c MasterLexer object parsing a master file for this
+/// RDATA.
+TXT::TXT(MasterLexer& lexer, const Name*, MasterLoader::Options,
+ MasterLoaderCallbacks&) :
+ impl_(new TXTImpl(lexer))
+{}
+
+TXT::TXT(const std::string& txtstr) :
+ impl_(new TXTImpl(txtstr))
+{}
+
+TXT::TXT(const TXT& other) :
+ Rdata(), impl_(new TXTImpl(*other.impl_))
+{}
+
+void
+TXT::toWire(OutputBuffer& buffer) const {
+ impl_->toWire(buffer);
+}
+
+void
+TXT::toWire(AbstractMessageRenderer& renderer) const {
+ impl_->toWire(renderer);
+}
+
+string
+TXT::toText() const {
+ return (impl_->toText());
+}
+
+int
+TXT::compare(const Rdata& other) const {
+ const TXT& other_txt = dynamic_cast<const TXT&>(other);
+
+ return (impl_->compare(*other_txt.impl_));
+}
+
+} // end of namespace "generic"
+} // end of namespace "rdata"
+} // end of namespace "dns"
+} // end of namespace "isc"
+// 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 <string>
+
+#include <exceptions/exceptions.h>
+
+#include <util/buffer.h>
+#include <dns/messagerenderer.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+
+using namespace std;
+using namespace isc::util;
+
+namespace isc {
+namespace dns {
+namespace rdata {
+namespace hs {
+
+A::A(const std::string&) {
+ // TBD
+}
+
+A::A(MasterLexer&, const Name*,
+ MasterLoader::Options, MasterLoaderCallbacks&)
+{
+ // TBD
+}
+
+A::A(InputBuffer&, size_t) {
+ // TBD
+}
+
+A::A(const A&) : Rdata() {
+ // TBD
+}
+
+void
+A::toWire(OutputBuffer&) const {
+ // TBD
+}
+
+void
+A::toWire(AbstractMessageRenderer&) const {
+ // TBD
+}
+
+string
+A::toText() const {
+ // TBD
+ isc_throw(InvalidRdataText, "Not implemented yet");
+}
+
+int
+A::compare(const Rdata&) const {
+ return (0); // dummy. TBD
+}
+
+} // end of namespace "hs"
+} // end of namespace "rdata"
+} // end of namespace "dns"
+} // end of namespace "isc"
+// 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 <stdint.h>
+#include <string.h>
+
+#include <cerrno>
+#include <cstring>
+#include <string>
+
+#include <arpa/inet.h> // XXX: for inet_pton/ntop(), not exist in C++ standards
+#include <sys/socket.h> // for AF_INET/AF_INET6
+
+#include <exceptions/exceptions.h>
+
+#include <util/buffer.h>
+
+#include <dns/exceptions.h>
+#include <dns/messagerenderer.h>
+#include <dns/master_lexer.h>
+#include <dns/master_loader_callbacks.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+
+using namespace std;
+using namespace isc::util;
+
+namespace isc {
+namespace dns {
+namespace rdata {
+namespace in {
+
+namespace {
+void
+convertToIPv4Addr(const char* src, size_t src_len, uint32_t* dst) {
+ // This check specifically rejects invalid input that begins with valid
+ // address text followed by a nul character (and possibly followed by
+ // further garbage). It cannot be detected by inet_pton().
+ //
+ // Note that this is private subroutine of the in::A constructors, which
+ // pass std::string.size() or StringRegion::len as src_len, so it should
+ // be equal to strlen() unless there's an intermediate nul character.
+ if (src_len != strlen(src)) {
+ isc_throw(InvalidRdataText,
+ "Bad IN/A RDATA text: unexpected nul in string: '"
+ << src << "'");
+ }
+ const int result = inet_pton(AF_INET, src, dst);
+ if (result == 0) {
+ isc_throw(InvalidRdataText, "Bad IN/A RDATA text: '" << src << "'");
+ } else if (result < 0) {
+ isc_throw(isc::Unexpected,
+ "Unexpected failure in parsing IN/A RDATA text: '"
+ << src << "': " << std::strerror(errno));
+ }
+}
+}
+
+/// \brief Constructor from string.
+///
+/// The given string must be a valid textual representation of an IPv4
+/// address as specified in RFC1035, that is, four decimal numbers separated
+/// by dots without any embedded spaces. Note that it excludes abbreviated
+/// forms such as "10.1" to mean "10.0.0.1".
+///
+/// Internally, this implementation uses the standard inet_pton() library
+/// function for the AF_INET family to parse and convert the textual
+/// representation. While standard compliant implementations of this function
+/// should accept exactly what this constructor expects, specific
+/// implementation may behave differently, in which case this constructor
+/// will simply accept the result of inet_pton(). In any case, the user of
+/// the class shouldn't assume such specific implementation behavior of
+/// inet_pton().
+///
+/// No extra character should be contained in \c addrstr other than the
+/// textual address. These include spaces and the nul character.
+///
+/// \throw InvalidRdata The text extracted by the lexer isn't recognized as
+/// a valid IPv4 address.
+/// \throw Unexpected Unexpected system error in conversion (this should be
+/// very rare).
+///
+/// \param addrstr Textual representation of IPv4 address to be used as the
+/// RDATA.
+A::A(const std::string& addrstr) {
+ convertToIPv4Addr(addrstr.c_str(), addrstr.size(), &addr_);
+}
+
+/// \brief Constructor with a context of MasterLexer.
+///
+/// The \c lexer should point to the beginning of valid textual representation
+/// of a class IN A RDATA.
+///
+/// The acceptable form of the textual address is generally the same as the
+/// string version of the constructor, but this version accepts beginning
+/// spaces and trailing spaces or other characters. Trailing non space
+/// characters would be considered an invalid form in an RR representation,
+/// but handling such errors is not the responsibility of this constructor.
+/// It also accepts other unusual syntax that would be considered valid
+/// in the context of DNS master file; for example, it accepts an IPv4
+/// address surrounded by parentheses, such as "(192.0.2.1)", although it's
+/// very unlikely to be used for this type of RDATA.
+///
+/// \throw MasterLexer::LexerError General parsing error such as missing field.
+/// \throw InvalidRdata The text extracted by the lexer isn't recognized as
+/// a valid IPv4 address.
+/// \throw Unexpected Unexpected system error in conversion (this should be
+/// very rare).
+///
+/// \param lexer A \c MasterLexer object parsing a master file for the
+/// RDATA to be created
+A::A(MasterLexer& lexer, const Name*,
+ MasterLoader::Options, MasterLoaderCallbacks&)
+{
+ const MasterToken& token = lexer.getNextToken(MasterToken::STRING);
+ convertToIPv4Addr(token.getStringRegion().beg, token.getStringRegion().len,
+ &addr_);
+}
+
+A::A(InputBuffer& buffer, size_t rdata_len) {
+ if (rdata_len != sizeof(addr_)) {
+ isc_throw(DNSMessageFORMERR,
+ "IN/A RDATA construction from wire failed: Invalid length: "
+ << rdata_len);
+ }
+ if (buffer.getLength() - buffer.getPosition() < sizeof(addr_)) {
+ isc_throw(DNSMessageFORMERR,
+ "IN/A RDATA construction from wire failed: "
+ "insufficient buffer length: "
+ << buffer.getLength() - buffer.getPosition());
+ }
+ buffer.readData(&addr_, sizeof(addr_));
+}
+
+/// \brief Copy constructor.
+A::A(const A& other) : Rdata(), addr_(other.addr_)
+{}
+
+void
+A::toWire(OutputBuffer& buffer) const {
+ buffer.writeData(&addr_, sizeof(addr_));
+}
+
+void
+A::toWire(AbstractMessageRenderer& renderer) const {
+ renderer.writeData(&addr_, sizeof(addr_));
+}
+
+/// \brief Return a textual form of the underlying IPv4 address of the RDATA.
+string
+A::toText() const {
+ char addr_string[sizeof("255.255.255.255")];
+
+ if (inet_ntop(AF_INET, &addr_, addr_string, sizeof(addr_string)) == NULL) {
+ isc_throw(Unexpected,
+ "Failed to convert IN/A RDATA to textual IPv4 address");
+ }
+
+ return (addr_string);
+}
+
+/// \brief Compare two in::A RDATAs.
+///
+/// In effect, it compares the two RDATA as an unsigned 32-bit integer.
+int
+A::compare(const Rdata& other) const {
+ const A& other_a = dynamic_cast<const A&>(other);
+ return (memcmp(&addr_, &other_a.addr_, sizeof(addr_)));
+}
+} // end of namespace "in"
+} // end of namespace "rdata"
+} // end of namespace "dns"
+} // end of namespace "isc"
+// 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 <exceptions/exceptions.h>
+#include <util/buffer.h>
+#include <dns/exceptions.h>
+#include <dns/messagerenderer.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+#include <dns/master_lexer.h>
+#include <dns/master_loader.h>
+
+#include <stdint.h>
+#include <string.h>
+
+#include <cerrno>
+#include <cstring>
+#include <string>
+
+#include <arpa/inet.h> // XXX: for inet_pton/ntop(), not exist in C++ standards
+#include <sys/socket.h> // for AF_INET/AF_INET6
+
+using namespace std;
+using namespace isc::util;
+
+namespace isc {
+namespace dns {
+namespace rdata {
+namespace in {
+
+namespace {
+void
+convertToIPv6Addr(const char* src, size_t src_len, void* dst) {
+ // See a_1.cc for this check.
+ if (src_len != strlen(src)) {
+ isc_throw(InvalidRdataText,
+ "Bad IN/AAAA RDATA text: unexpected nul in string: '"
+ << src << "'");
+ }
+ const int result = inet_pton(AF_INET6, src, dst);
+ if (result == 0) {
+ isc_throw(InvalidRdataText, "Bad IN/AAAA RDATA text: '" << src << "'");
+ } else if (result < 0) {
+ isc_throw(isc::Unexpected,
+ "Unexpected failure in parsing IN/AAAA RDATA text: '"
+ << src << "': " << std::strerror(errno));
+ }
+}
+}
+
+/// \brief Constructor from string.
+///
+/// The given string must be a valid textual representation of an IPv6
+/// address as specified in RFC1886.
+///
+/// No extra character should be contained in \c addrstr other than the
+/// textual address. These include spaces and the nul character.
+///
+/// \throw InvalidRdata The text extracted by the lexer isn't recognized as
+/// a valid IPv6 address.
+/// \throw Unexpected Unexpected system error in conversion (this should be
+/// very rare).
+///
+/// \param addrstr Textual representation of IPv6 address to be used as the
+/// RDATA.
+AAAA::AAAA(const std::string& addrstr) {
+ convertToIPv6Addr(addrstr.c_str(), addrstr.size(), addr_);
+}
+
+/// \brief Constructor with a context of MasterLexer.
+///
+/// The \c lexer should point to the beginning of valid textual representation
+/// of a class IN AAAA RDATA.
+///
+/// The acceptable form of the textual address is generally the same as the
+/// string version of the constructor, but this version is slightly more
+/// flexible. See the similar constructor of \c in::A class; the same
+/// notes apply here.
+///
+/// \throw MasterLexer::LexerError General parsing error such as missing field.
+/// \throw InvalidRdata The text extracted by the lexer isn't recognized as
+/// a valid IPv6 address.
+/// \throw Unexpected Unexpected system error in conversion (this should be
+/// very rare).
+///
+/// \param lexer A \c MasterLexer object parsing a master file for the
+/// RDATA to be created
+AAAA::AAAA(MasterLexer& lexer, const Name*,
+ MasterLoader::Options, MasterLoaderCallbacks&)
+{
+ const MasterToken& token = lexer.getNextToken(MasterToken::STRING);
+ convertToIPv6Addr(token.getStringRegion().beg, token.getStringRegion().len,
+ addr_);
+}
+
+/// \brief Copy constructor.
+AAAA::AAAA(InputBuffer& buffer, size_t rdata_len) {
+ if (rdata_len != sizeof(addr_)) {
+ isc_throw(DNSMessageFORMERR,
+ "IN/AAAA RDATA construction from wire failed: "
+ "Invalid length: " << rdata_len);
+ }
+ if (buffer.getLength() - buffer.getPosition() < sizeof(addr_)) {
+ isc_throw(DNSMessageFORMERR,
+ "IN/AAAA RDATA construction from wire failed: "
+ "insufficient buffer length: "
+ << buffer.getLength() - buffer.getPosition());
+ }
+ buffer.readData(&addr_, sizeof(addr_));
+}
+
+AAAA::AAAA(const AAAA& other) : Rdata() {
+ memcpy(addr_, other.addr_, sizeof(addr_));
+}
+
+/// \brief Return a textual form of the underlying IPv6 address of the RDATA.
+void
+AAAA::toWire(OutputBuffer& buffer) const {
+ buffer.writeData(&addr_, sizeof(addr_));
+}
+
+void
+AAAA::toWire(AbstractMessageRenderer& renderer) const {
+ renderer.writeData(&addr_, sizeof(addr_));
+}
+
+string
+AAAA::toText() const {
+ char addr_string[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
+
+ if (inet_ntop(AF_INET6, &addr_, addr_string, sizeof(addr_string))
+ == NULL) {
+ isc_throw(Unexpected,
+ "Failed to convert IN/AAAA RDATA to textual IPv6 address");
+ }
+
+ return (string(addr_string));
+}
+
+/// \brief Compare two in::AAAA RDATAs.
+///
+/// In effect, it compares the two RDATA as an unsigned 128-bit integer.
+int
+AAAA::compare(const Rdata& other) const {
+ const AAAA& other_a = dynamic_cast<const AAAA&>(other);
+ return (memcmp(&addr_, &other_a.addr_, sizeof(addr_)));
+}
+
+} // end of namespace "in"
+} // end of namespace "rdata"
+} // end of namespace "dns"
+} // end of namespace "isc"
+// Copyright (C) 2011-2013 Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// 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 <stdint.h>
+#include <string.h>
+
+#include <exceptions/exceptions.h>
+
+#include <util/buffer.h>
+#include <util/encode/base64.h>
+#include <dns/exceptions.h>
+#include <dns/messagerenderer.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+
+using namespace std;
+using namespace isc::util;
+using namespace isc::util::encode;
+
+namespace isc {
+namespace dns {
+namespace rdata {
+namespace in {
+
+void
+DHCID::constructFromLexer(MasterLexer& lexer) {
+ string digest_txt = lexer.getNextToken(MasterToken::STRING).getString();
+
+ // Whitespace is allowed within base64 text, so read to the end of input.
+ string digest_part;
+ while (true) {
+ const MasterToken& token =
+ lexer.getNextToken(MasterToken::STRING, true);
+ if ((token.getType() == MasterToken::END_OF_FILE) ||
+ (token.getType() == MasterToken::END_OF_LINE)) {
+ break;
+ }
+ token.getString(digest_part);
+ digest_txt.append(digest_part);
+ }
+ lexer.ungetToken();
+
+ decodeBase64(digest_txt, digest_);
+}
+
+/// \brief Constructor from string.
+///
+/// \param dhcid_str A base-64 representation of the DHCID binary data.
+///
+/// \throw InvalidRdataText if the string could not be parsed correctly.
+DHCID::DHCID(const std::string& dhcid_str) {
+ try {
+ std::istringstream iss(dhcid_str);
+ MasterLexer lexer;
+ lexer.pushSource(iss);
+
+ constructFromLexer(lexer);
+
+ if (lexer.getNextToken().getType() != MasterToken::END_OF_FILE) {
+ isc_throw(InvalidRdataText, "extra input text for DHCID: "
+ << dhcid_str);
+ }
+ } catch (const MasterLexer::LexerError& ex) {
+ isc_throw(InvalidRdataText, "Failed to construct DHCID from '" <<
+ dhcid_str << "': " << ex.what());
+ }
+}
+
+/// \brief Constructor with a context of MasterLexer.
+///
+/// The \c lexer should point to the beginning of valid textual representation
+/// of a DHCID RDATA.
+///
+/// \throw BadValue if the text is not valid base-64.
+/// \throw MasterLexer::LexerError General parsing error such as missing field.
+///
+/// \param lexer A \c MasterLexer object parsing a master file for the
+/// RDATA to be created
+DHCID::DHCID(MasterLexer& lexer, const Name*,
+ MasterLoader::Options, MasterLoaderCallbacks&) {
+ constructFromLexer(lexer);
+}
+
+/// \brief Constructor from wire-format data.
+///
+/// \param buffer A buffer storing the wire format data.
+/// \param rdata_len The length of the RDATA in bytes
+DHCID::DHCID(InputBuffer& buffer, size_t rdata_len) {
+ if (rdata_len == 0) {
+ isc_throw(InvalidRdataLength, "Missing DHCID rdata");
+ }
+
+ digest_.resize(rdata_len);
+ buffer.readData(&digest_[0], rdata_len);
+}
+
+/// \brief The copy constructor.
+///
+/// This trivial copy constructor never throws an exception.
+DHCID::DHCID(const DHCID& other) : Rdata(), digest_(other.digest_)
+{}
+
+/// \brief Render the \c DHCID in the wire format.
+///
+/// \param buffer An output buffer to store the wire data.
+void
+DHCID::toWire(OutputBuffer& buffer) const {
+ buffer.writeData(&digest_[0], digest_.size());
+}
+
+/// \brief Render the \c DHCID in the wire format into a
+/// \c MessageRenderer object.
+///
+/// \param renderer DNS message rendering context that encapsulates the
+/// output buffer in which the \c DHCID is to be stored.
+void
+DHCID::toWire(AbstractMessageRenderer& renderer) const {
+ renderer.writeData(&digest_[0], digest_.size());
+}
+
+/// \brief Convert the \c DHCID to a string.
+///
+/// This method returns a \c std::string object representing the \c DHCID.
+///
+/// \return A string representation of \c DHCID.
+string
+DHCID::toText() const {
+ return (encodeBase64(digest_));
+}
+
+/// \brief Compare two instances of \c DHCID RDATA.
+///
+/// See documentation in \c Rdata.
+int
+DHCID::compare(const Rdata& other) const {
+ const DHCID& other_dhcid = dynamic_cast<const DHCID&>(other);
+
+ size_t this_len = digest_.size();
+ size_t other_len = other_dhcid.digest_.size();
+ size_t cmplen = min(this_len, other_len);
+ int cmp = memcmp(&digest_[0], &other_dhcid.digest_[0], cmplen);
+ if (cmp != 0) {
+ return (cmp);
+ } else {
+ return ((this_len == other_len) ? 0 : (this_len < other_len) ? -1 : 1);
+ }
+}
+
+/// \brief Accessor method to get the DHCID digest
+///
+/// \return A reference to the binary DHCID data
+const std::vector<uint8_t>&
+DHCID::getDigest() const {
+ return (digest_);
+}
+
+} // end of namespace "in"
+} // end of namespace "rdata"
+} // end of namespace "dns"
+} // end of namespace "isc"
+// 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 <iostream>
+#include <sstream>
+
+#include <boost/lexical_cast.hpp>
+
+#include <util/buffer.h>
+#include <util/strutil.h>
+
+#include <dns/messagerenderer.h>
+#include <dns/name.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+
+#include <dns/rdata/generic/detail/lexer_util.h>
+
+using namespace std;
+using namespace isc::util;
+using namespace isc::util::str;
+using isc::dns::rdata::generic::detail::createNameFromLexer;
+
+namespace isc {
+namespace dns {
+namespace rdata {
+namespace in {
+
+struct SRVImpl {
+ // straightforward representation of SRV RDATA fields
+ SRVImpl(uint16_t priority, uint16_t weight, uint16_t port,
+ const Name& target) :
+ priority_(priority), weight_(weight), port_(port),
+ target_(target)
+ {}
+
+ uint16_t priority_;
+ uint16_t weight_;
+ uint16_t port_;
+ Name target_;
+};
+
+/// \brief Constructor from string.
+///
+/// The given string must represent a valid SRV 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.
+///
+/// The TARGET name must be absolute since there's no parameter that
+/// specifies the origin name; if it is not absolute, \c MissingNameOrigin
+/// exception will be thrown. It must not be represented as a quoted
+/// string.
+///
+/// See the construction that takes \c MasterLexer for other fields.
+///
+/// \throw Others Exception from the Name and RRTTL constructors.
+/// \throw InvalidRdataText Other general syntax errors.
+SRV::SRV(const std::string& srv_str) :
+ impl_(NULL)
+{
+ try {
+ std::istringstream ss(srv_str);
+ MasterLexer lexer;
+ lexer.pushSource(ss);
+
+ uint32_t num = lexer.getNextToken(MasterToken::NUMBER).getNumber();
+ if (num > 65535) {
+ isc_throw(InvalidRdataText, "Invalid SRV priority in: " << srv_str);
+ }
+ const uint16_t priority = static_cast<uint16_t>(num);
+
+ num = lexer.getNextToken(MasterToken::NUMBER).getNumber();
+ if (num > 65535) {
+ isc_throw(InvalidRdataText, "Invalid SRV weight in: " << srv_str);
+ }
+ const uint16_t weight = static_cast<uint16_t>(num);
+
+ num = lexer.getNextToken(MasterToken::NUMBER).getNumber();
+ if (num > 65535) {
+ isc_throw(InvalidRdataText, "Invalid SRV port in: " << srv_str);
+ }
+ const uint16_t port = static_cast<uint16_t>(num);
+
+ const Name targetname = createNameFromLexer(lexer, NULL);
+
+ if (lexer.getNextToken().getType() != MasterToken::END_OF_FILE) {
+ isc_throw(InvalidRdataText, "extra input text for SRV: "
+ << srv_str);
+ }
+
+ impl_ = new SRVImpl(priority, weight, port, targetname);
+ } catch (const MasterLexer::LexerError& ex) {
+ isc_throw(InvalidRdataText, "Failed to construct SRV from '" <<
+ srv_str << "': " << ex.what());
+ }
+}
+
+/// \brief Constructor from wire-format data.
+///
+/// When a read operation on \c buffer fails (e.g., due to a corrupted
+/// message) a corresponding exception from the \c InputBuffer class will
+/// be thrown.
+/// If the wire-format data does not end with a valid domain name,
+/// a corresponding exception from the \c Name class will be thrown.
+/// In addition, this constructor internally involves resource allocation,
+/// and if it fails a corresponding standard exception will be thrown.
+///
+/// According to RFC2782, the Target field must be a non compressed form
+/// of domain name. But this implementation accepts a %SRV RR even if that
+/// field is compressed as suggested in RFC3597.
+///
+/// \param buffer A buffer storing the wire format data.
+/// \param rdata_len The length of the RDATA in bytes, normally expected
+/// to be the value of the RDLENGTH field of the corresponding RR.
+SRV::SRV(InputBuffer& buffer, size_t rdata_len) {
+ if (rdata_len < 6) {
+ isc_throw(InvalidRdataLength, "SRV too short");
+ }
+
+ const uint16_t priority = buffer.readUint16();
+ const uint16_t weight = buffer.readUint16();
+ const uint16_t port = buffer.readUint16();
+ const Name targetname(buffer);
+
+ impl_ = new SRVImpl(priority, weight, port, targetname);
+}
+
+/// \brief Constructor with a context of MasterLexer.
+///
+/// The \c lexer should point to the beginning of valid textual representation
+/// of an SRV RDATA. The TARGET field can be non-absolute if \c origin
+/// is non-NULL, in which case \c origin is used to make it absolute.
+/// It must not be represented as a quoted string.
+///
+/// The PRIORITY, WEIGHT and PORT fields must each be a valid decimal
+/// representation of an unsigned 16-bit integers respectively.
+///
+/// \throw MasterLexer::LexerError General parsing error such as missing field.
+/// \throw Other Exceptions from the Name and RRTTL constructors if
+/// construction of textual fields as these objects fail.
+///
+/// \param lexer A \c MasterLexer object parsing a master file for the
+/// RDATA to be created
+/// \param origin If non NULL, specifies the origin of TARGET when it
+/// is non-absolute.
+SRV::SRV(MasterLexer& lexer, const Name* origin,
+ MasterLoader::Options, MasterLoaderCallbacks&)
+{
+ uint32_t num = lexer.getNextToken(MasterToken::NUMBER).getNumber();
+ if (num > 65535) {
+ isc_throw(InvalidRdataText, "Invalid SRV priority: " << num);
+ }
+ const uint16_t priority = static_cast<uint16_t>(num);
+
+ num = lexer.getNextToken(MasterToken::NUMBER).getNumber();
+ if (num > 65535) {
+ isc_throw(InvalidRdataText, "Invalid SRV weight: " << num);
+ }
+ const uint16_t weight = static_cast<uint16_t>(num);
+
+ num = lexer.getNextToken(MasterToken::NUMBER).getNumber();
+ if (num > 65535) {
+ isc_throw(InvalidRdataText, "Invalid SRV port: " << num);
+ }
+ const uint16_t port = static_cast<uint16_t>(num);
+
+ const Name targetname = createNameFromLexer(lexer, origin);
+
+ impl_ = new SRVImpl(priority, weight, port, targetname);
+}
+
+/// \brief The copy constructor.
+///
+/// It internally allocates a resource, and if it fails a corresponding
+/// standard exception will be thrown.
+/// This constructor never throws an exception otherwise.
+SRV::SRV(const SRV& source) :
+ Rdata(), impl_(new SRVImpl(*source.impl_))
+{}
+
+SRV&
+SRV::operator=(const SRV& source) {
+ if (this == &source) {
+ return (*this);
+ }
+
+ SRVImpl* newimpl = new SRVImpl(*source.impl_);
+ delete impl_;
+ impl_ = newimpl;
+
+ return (*this);
+}
+
+SRV::~SRV() {
+ delete impl_;
+}
+
+/// \brief Convert the \c SRV to a string.
+///
+/// The output of this method is formatted as described in the "from string"
+/// constructor (\c SRV(const std::string&))).
+///
+/// If internal resource allocation fails, a corresponding
+/// standard exception will be thrown.
+///
+/// \return A \c string object that represents the \c SRV object.
+string
+SRV::toText() const {
+ using boost::lexical_cast;
+ return (lexical_cast<string>(impl_->priority_) +
+ " " + lexical_cast<string>(impl_->weight_) +
+ " " + lexical_cast<string>(impl_->port_) +
+ " " + impl_->target_.toText());
+}
+
+/// \brief Render the \c SRV in the wire format without name compression.
+///
+/// If internal resource allocation fails, a corresponding
+/// standard exception will be thrown.
+/// This method never throws an exception otherwise.
+///
+/// \param buffer An output buffer to store the wire data.
+void
+SRV::toWire(OutputBuffer& buffer) const {
+ buffer.writeUint16(impl_->priority_);
+ buffer.writeUint16(impl_->weight_);
+ buffer.writeUint16(impl_->port_);
+ impl_->target_.toWire(buffer);
+}
+
+/// \brief Render the \c SRV in the wire format with taking into account
+/// compression.
+///
+/// As specified in RFC2782, the Target field (a domain name) will not be
+/// compressed. However, the domain name could be a target of compression
+/// of other compressible names (though pretty unlikely), the offset
+/// information of the algorithm name may be recorded in \c renderer.
+///
+/// If internal resource allocation fails, a corresponding
+/// standard exception will be thrown.
+/// This method never throws an exception otherwise.
+///
+/// \param renderer DNS message rendering context that encapsulates the
+/// output buffer and name compression information.
+void
+SRV::toWire(AbstractMessageRenderer& renderer) const {
+ renderer.writeUint16(impl_->priority_);
+ renderer.writeUint16(impl_->weight_);
+ renderer.writeUint16(impl_->port_);
+ renderer.writeName(impl_->target_, false);
+}
+
+/// \brief Compare two instances of \c SRV RDATA.
+///
+/// See documentation in \c Rdata.
+int
+SRV::compare(const Rdata& other) const {
+ const SRV& other_srv = dynamic_cast<const SRV&>(other);
+
+ if (impl_->priority_ != other_srv.impl_->priority_) {
+ return (impl_->priority_ < other_srv.impl_->priority_ ? -1 : 1);
+ }
+ if (impl_->weight_ != other_srv.impl_->weight_) {
+ return (impl_->weight_ < other_srv.impl_->weight_ ? -1 : 1);
+ }
+ if (impl_->port_ != other_srv.impl_->port_) {
+ return (impl_->port_ < other_srv.impl_->port_ ? -1 : 1);
+ }
+
+ return (compareNames(impl_->target_, other_srv.impl_->target_));
+}
+
+uint16_t
+SRV::getPriority() const {
+ return (impl_->priority_);
+}
+
+uint16_t
+SRV::getWeight() const {
+ return (impl_->weight_);
+}
+
+uint16_t
+SRV::getPort() const {
+ return (impl_->port_);
+}
+
+const Name&
+SRV::getTarget() const {
+ return (impl_->target_);
+}
+
+} // end of namespace "in"
+} // end of namespace "rdata"
+} // end of namespace "dns"
+} // end of namespace "isc"
--- /dev/null
+///////////////
+///////////////
+/////////////// THIS FILE IS AUTOMATICALLY GENERATED BY gen-rdatacode.py.
+/////////////// DO NOT EDIT!
+///////////////
+///////////////
+
+
+#ifndef DNS_RDATACLASS_H
+#define DNS_RDATACLASS_H 1
+
+#include <dns/master_loader.h>
+
+namespace isc {
+namespace dns {
+class Name;
+class MasterLexer;
+class MasterLoaderCallbacks;
+}
+}
+// 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.
+
+#ifndef ANY_TSIG_250_H
+#define ANY_TSIG_250_H 1
+
+#include <stdint.h>
+
+#include <string>
+
+#include <dns/name.h>
+#include <dns/rdata.h>
+
+namespace isc {
+namespace util {
+
+class InputBuffer;
+class OutputBuffer;
+}
+
+namespace dns {
+
+// BEGIN_COMMON_DECLARATIONS
+
+class AbstractMessageRenderer;
+
+// END_COMMON_DECLARATIONS
+
+namespace rdata {
+namespace any {
+
+struct TSIGImpl;
+
+/// \brief \c rdata::TSIG class represents the TSIG RDATA as defined %in
+/// RFC2845.
+///
+/// This class implements the basic interfaces inherited from the abstract
+/// \c rdata::Rdata class, and provides trivial accessors specific to the
+/// TSIG RDATA.
+class TSIG : public Rdata {
+public:
+ // BEGIN_COMMON_MEMBERS
+
+ explicit TSIG(const std::string& type_str);
+ TSIG(isc::util::InputBuffer& buffer, size_t rdata_len);
+ TSIG(const TSIG& other);
+ TSIG(
+ MasterLexer& lexer, const Name* name,
+ MasterLoader::Options options, MasterLoaderCallbacks& callbacks);
+ virtual std::string toText() const;
+ virtual void toWire(isc::util::OutputBuffer& buffer) const;
+ virtual void toWire(AbstractMessageRenderer& renderer) const;
+ virtual int compare(const Rdata& other) const;
+
+ // END_COMMON_MEMBERS
+
+ /// \brief Constructor from RDATA field parameters.
+ ///
+ /// The parameters are a straightforward mapping of %TSIG RDATA
+ /// fields as defined %in RFC2845, but there are some implementation
+ /// specific notes as follows.
+ ///
+ /// \c algorithm is a \c Name object that specifies the algorithm.
+ /// For example, if the algorithm is HMAC-SHA256, \c algorithm would be
+ /// \c Name("hmac-sha256").
+ ///
+ /// \c time_signed corresponds to the Time Signed field, which is of
+ /// 48-bit unsigned integer type, and therefore cannot exceed 2^48-1;
+ /// otherwise, an exception of type \c OutOfRange will be thrown.
+ ///
+ /// \c mac_size and \c mac correspond to the MAC Size and MAC fields,
+ /// respectively. When the MAC field is empty, \c mac must be NULL.
+ /// \c mac_size and \c mac must be consistent %in that \c mac_size is 0 if
+ /// and only if \c mac is NULL; otherwise an exception of type
+ /// InvalidParameter will be thrown.
+ ///
+ /// The same restriction applies to \c other_len and \c other_data,
+ /// which correspond to the Other Len and Other Data fields, respectively.
+ ///
+ /// This constructor internally involves resource allocation, and if
+ /// it fails, a corresponding standard exception will be thrown.
+ TSIG(const Name& algorithm, uint64_t time_signed, uint16_t fudge,
+ uint16_t mac_size, const void* mac, uint16_t original_id,
+ uint16_t error, uint16_t other_len, const void* other_data);
+
+ /// \brief Assignment operator.
+ ///
+ /// It internally allocates a resource, and if it fails a corresponding
+ /// standard exception will be thrown.
+ /// This operator never throws an exception otherwise.
+ ///
+ /// This operator provides the strong exception guarantee: When an
+ /// exception is thrown the content of the assignment target will be
+ /// intact.
+ TSIG& operator=(const TSIG& source);
+
+ /// \brief The destructor.
+ ~TSIG();
+
+ /// \brief Return the algorithm name.
+ ///
+ /// This method never throws an exception.
+ const Name& getAlgorithm() const;
+
+ /// \brief Return the value of the Time Signed field.
+ ///
+ /// The returned value does not exceed 2^48-1.
+ ///
+ /// This method never throws an exception.
+ uint64_t getTimeSigned() const;
+
+ /// \brief Return the value of the Fudge field.
+ ///
+ /// This method never throws an exception.
+ uint16_t getFudge() const;
+
+ /// \brief Return the value of the MAC Size field.
+ ///
+ /// This method never throws an exception.
+ uint16_t getMACSize() const;
+
+ /// \brief Return the value of the MAC field.
+ ///
+ /// If the MAC field is empty, it returns NULL.
+ /// Otherwise, the memory region beginning at the address returned by
+ /// this method is valid up to the bytes specified by the return value
+ /// of \c getMACSize().
+ /// The memory region is only valid while the corresponding \c TSIG
+ /// object is valid. The caller must hold the \c TSIG object while
+ /// it needs to refer to the region or it must make a local copy of the
+ /// region.
+ ///
+ /// This method never throws an exception.
+ const void* getMAC() const;
+
+ /// \brief Return the value of the Original ID field.
+ ///
+ /// This method never throws an exception.
+ uint16_t getOriginalID() const;
+
+ /// \brief Return the value of the Error field.
+ ///
+ /// This method never throws an exception.
+ uint16_t getError() const;
+
+ /// \brief Return the value of the Other Len field.
+ ///
+ /// This method never throws an exception.
+ uint16_t getOtherLen() const;
+
+ /// \brief Return the value of the Other Data field.
+ ///
+ /// The same note as \c getMAC() applies.
+ ///
+ /// This method never throws an exception.
+ const void* getOtherData() const;
+private:
+ TSIGImpl* constructFromLexer(MasterLexer& lexer, const Name* origin);
+
+ TSIGImpl* impl_;
+};
+
+} // end of namespace "any"
+} // end of namespace "rdata"
+} // end of namespace "dns"
+} // end of namespace "isc"
+#endif // ANY_TSIG_250_H
+
+// 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 CH_A_1_H
+#define CH_A_1_H 1
+
+#include <string>
+
+#include <dns/rdata.h>
+
+namespace isc {
+namespace util {
+
+class InputBuffer;
+class OutputBuffer;
+}
+
+namespace dns {
+
+// BEGIN_COMMON_DECLARATIONS
+
+class AbstractMessageRenderer;
+
+// END_COMMON_DECLARATIONS
+
+namespace rdata {
+namespace ch {
+
+class A : public Rdata {
+public:
+ // BEGIN_COMMON_MEMBERS
+
+ explicit A(const std::string& type_str);
+ A(isc::util::InputBuffer& buffer, size_t rdata_len);
+ A(const A& other);
+ A(
+ MasterLexer& lexer, const Name* name,
+ MasterLoader::Options options, MasterLoaderCallbacks& callbacks);
+ virtual std::string toText() const;
+ virtual void toWire(isc::util::OutputBuffer& buffer) const;
+ virtual void toWire(AbstractMessageRenderer& renderer) const;
+ virtual int compare(const Rdata& other) const;
+
+ // END_COMMON_MEMBERS
+};
+
+} // end of namespace "ch"
+} // end of namespace "rdata"
+} // end of namespace "dns"
+} // end of namespace "isc"
+#endif // CH_A_1_H
+
+// Copyright (C) 2011-2013 Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// 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 GENERIC_AFSDB_18_H
+#define GENERIC_AFSDB_18_H 1
+
+#include <stdint.h>
+
+#include <string>
+
+#include <dns/name.h>
+#include <dns/rdata.h>
+
+namespace isc {
+namespace util {
+
+class InputBuffer;
+class OutputBuffer;
+}
+
+namespace dns {
+
+// BEGIN_COMMON_DECLARATIONS
+
+class AbstractMessageRenderer;
+
+// END_COMMON_DECLARATIONS
+
+namespace rdata {
+namespace generic {
+
+/// \brief \c rdata::AFSDB class represents the AFSDB RDATA as defined %in
+/// RFC1183.
+///
+/// This class implements the basic interfaces inherited from the abstract
+/// \c rdata::Rdata class, and provides trivial accessors specific to the
+/// AFSDB RDATA.
+class AFSDB : public Rdata {
+public:
+ // BEGIN_COMMON_MEMBERS
+
+ explicit AFSDB(const std::string& type_str);
+ AFSDB(isc::util::InputBuffer& buffer, size_t rdata_len);
+ AFSDB(const AFSDB& other);
+ AFSDB(
+ MasterLexer& lexer, const Name* name,
+ MasterLoader::Options options, MasterLoaderCallbacks& callbacks);
+ virtual std::string toText() const;
+ virtual void toWire(isc::util::OutputBuffer& buffer) const;
+ virtual void toWire(AbstractMessageRenderer& renderer) const;
+ virtual int compare(const Rdata& other) const;
+
+ // END_COMMON_MEMBERS
+
+ /// \brief Assignment operator.
+ ///
+ /// This method never throws an exception.
+ AFSDB& operator=(const AFSDB& source);
+ ///
+ /// Specialized methods
+ ///
+
+ /// \brief Return the value of the server field.
+ ///
+ /// \return A reference to a \c Name class object corresponding to the
+ /// internal server name.
+ ///
+ /// This method never throws an exception.
+ const Name& getServer() const;
+
+ /// \brief Return the value of the subtype field.
+ ///
+ /// This method never throws an exception.
+ uint16_t getSubtype() const;
+
+private:
+ void createFromLexer(MasterLexer& lexer, const Name* origin);
+
+ uint16_t subtype_;
+ Name server_;
+};
+
+} // end of namespace "generic"
+} // end of namespace "rdata"
+} // end of namespace "dns"
+} // end of namespace "isc"
+#endif // GENERIC_AFSDB_18_H
+
+// 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 GENERIC_CAA_257_H
+#define GENERIC_CAA_257_H 1
+
+#include <stdint.h>
+
+#include <dns/name.h>
+#include <dns/rdata.h>
+
+#include <string>
+#include <vector>
+
+namespace isc {
+namespace util {
+
+class InputBuffer;
+class OutputBuffer;
+}
+
+namespace dns {
+
+// BEGIN_COMMON_DECLARATIONS
+
+class AbstractMessageRenderer;
+
+// END_COMMON_DECLARATIONS
+
+namespace rdata {
+namespace generic {
+
+struct CAAImpl;
+
+class CAA : public Rdata {
+public:
+ // BEGIN_COMMON_MEMBERS
+
+ explicit CAA(const std::string& type_str);
+ CAA(isc::util::InputBuffer& buffer, size_t rdata_len);
+ CAA(const CAA& other);
+ CAA(
+ MasterLexer& lexer, const Name* name,
+ MasterLoader::Options options, MasterLoaderCallbacks& callbacks);
+ virtual std::string toText() const;
+ virtual void toWire(isc::util::OutputBuffer& buffer) const;
+ virtual void toWire(AbstractMessageRenderer& renderer) const;
+ virtual int compare(const Rdata& other) const;
+
+ // END_COMMON_MEMBERS
+
+ CAA(uint8_t flags, const std::string& tag, const std::string& value);
+ CAA& operator=(const CAA& source);
+ ~CAA();
+
+ ///
+ /// Specialized methods
+ ///
+
+ /// \brief Return the Flags field of the CAA RDATA.
+ uint8_t getFlags() const;
+
+ /// \brief Return the Tag field of the CAA RDATA.
+ const std::string& getTag() const;
+
+ /// \brief Return the Value field of the CAA RDATA.
+ ///
+ /// Note: The const reference which is returned is valid only during
+ /// the lifetime of this \c generic::CAA object. It should not be
+ /// used afterwards.
+ const std::vector<uint8_t>& getValue() const;
+
+private:
+ CAAImpl* constructFromLexer(MasterLexer& lexer);
+
+ CAAImpl* impl_;
+};
+
+} // end of namespace "generic"
+} // end of namespace "rdata"
+} // end of namespace "dns"
+} // end of namespace "isc"
+#endif // GENERIC_CAA_257_H
+
+// 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 GENERIC_CNAME_5_H
+#define GENERIC_CNAME_5_H 1
+
+#include <string>
+
+#include <dns/name.h>
+#include <dns/rdata.h>
+
+namespace isc {
+namespace util {
+
+class InputBuffer;
+class OutputBuffer;
+}
+
+namespace dns {
+
+// BEGIN_COMMON_DECLARATIONS
+
+class AbstractMessageRenderer;
+
+// END_COMMON_DECLARATIONS
+
+namespace rdata {
+namespace generic {
+
+class CNAME : public Rdata {
+public:
+ // BEGIN_COMMON_MEMBERS
+
+ explicit CNAME(const std::string& type_str);
+ CNAME(isc::util::InputBuffer& buffer, size_t rdata_len);
+ CNAME(const CNAME& other);
+ CNAME(
+ MasterLexer& lexer, const Name* name,
+ MasterLoader::Options options, MasterLoaderCallbacks& callbacks);
+ virtual std::string toText() const;
+ virtual void toWire(isc::util::OutputBuffer& buffer) const;
+ virtual void toWire(AbstractMessageRenderer& renderer) const;
+ virtual int compare(const Rdata& other) const;
+
+ // END_COMMON_MEMBERS
+
+ // CNAME specific methods
+ CNAME(const Name& cname);
+ const Name& getCname() const;
+private:
+ Name cname_;
+};
+
+} // end of namespace "generic"
+} // end of namespace "rdata"
+} // end of namespace "dns"
+} // end of namespace "isc"
+#endif // GENERIC_CNAME_5_H
+
+// 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 GENERIC_DLV_32769_H
+#define GENERIC_DLV_32769_H 1
+
+#include <stdint.h>
+
+#include <string>
+
+#include <dns/name.h>
+#include <dns/rrtype.h>
+#include <dns/rrttl.h>
+#include <dns/rdata.h>
+
+namespace isc {
+namespace util {
+
+class InputBuffer;
+class OutputBuffer;
+}
+
+namespace dns {
+
+// BEGIN_COMMON_DECLARATIONS
+
+class AbstractMessageRenderer;
+
+// END_COMMON_DECLARATIONS
+
+namespace rdata {
+namespace generic {
+
+namespace detail {
+template <class Type, uint16_t typeCode> class DSLikeImpl;
+}
+
+/// \brief \c rdata::generic::DLV class represents the DLV RDATA as defined in
+/// RFC4431.
+///
+/// This class implements the basic interfaces inherited from the abstract
+/// \c rdata::Rdata class, and provides trivial accessors specific to the
+/// DLV RDATA.
+class DLV : public Rdata {
+public:
+ // BEGIN_COMMON_MEMBERS
+
+ explicit DLV(const std::string& type_str);
+ DLV(isc::util::InputBuffer& buffer, size_t rdata_len);
+ DLV(const DLV& other);
+ DLV(
+ MasterLexer& lexer, const Name* name,
+ MasterLoader::Options options, MasterLoaderCallbacks& callbacks);
+ virtual std::string toText() const;
+ virtual void toWire(isc::util::OutputBuffer& buffer) const;
+ virtual void toWire(AbstractMessageRenderer& renderer) const;
+ virtual int compare(const Rdata& other) const;
+
+ // END_COMMON_MEMBERS
+
+ /// \brief Assignment operator.
+ ///
+ /// It internally allocates a resource, and if it fails a corresponding
+ /// standard exception will be thrown.
+ /// This operator never throws an exception otherwise.
+ ///
+ /// This operator provides the strong exception guarantee: When an
+ /// exception is thrown the content of the assignment target will be
+ /// intact.
+ DLV& operator=(const DLV& source);
+
+ /// \brief The destructor.
+ ~DLV();
+
+ /// \brief Return the value of the Tag field.
+ ///
+ /// This method never throws an exception.
+ uint16_t getTag() const;
+private:
+ typedef detail::DSLikeImpl<DLV, 32769> DLVImpl;
+ DLVImpl* impl_;
+};
+
+} // end of namespace "generic"
+} // end of namespace "rdata"
+} // end of namespace "dns"
+} // end of namespace "isc"
+#endif // GENERIC_DLV_32769_H
+
+// 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 GENERIC_DNAME_39_H
+#define GENERIC_DNAME_39_H 1
+
+#include <string>
+
+#include <dns/name.h>
+#include <dns/rdata.h>
+
+namespace isc {
+namespace util {
+
+class InputBuffer;
+class OutputBuffer;
+}
+
+namespace dns {
+
+// BEGIN_COMMON_DECLARATIONS
+
+class AbstractMessageRenderer;
+
+// END_COMMON_DECLARATIONS
+
+namespace rdata {
+namespace generic {
+
+class DNAME : public Rdata {
+public:
+ // BEGIN_COMMON_MEMBERS
+
+ explicit DNAME(const std::string& type_str);
+ DNAME(isc::util::InputBuffer& buffer, size_t rdata_len);
+ DNAME(const DNAME& other);
+ DNAME(
+ MasterLexer& lexer, const Name* name,
+ MasterLoader::Options options, MasterLoaderCallbacks& callbacks);
+ virtual std::string toText() const;
+ virtual void toWire(isc::util::OutputBuffer& buffer) const;
+ virtual void toWire(AbstractMessageRenderer& renderer) const;
+ virtual int compare(const Rdata& other) const;
+
+ // END_COMMON_MEMBERS
+
+ // DNAME specific methods
+ DNAME(const Name& dname);
+ const Name& getDname() const;
+private:
+ Name dname_;
+};
+
+} // end of namespace "generic"
+} // end of namespace "rdata"
+} // end of namespace "dns"
+} // end of namespace "isc"
+#endif // GENERIC_DNAME_39_H
+
+// 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 <stdint.h>
+
+#include <string>
+
+#include <dns/name.h>
+#include <dns/rrtype.h>
+#include <dns/rrttl.h>
+#include <dns/rdata.h>
+#include <dns/master_lexer.h>
+
+#ifndef GENERIC_DNSKEY_48_H
+#define GENERIC_DNSKEY_48_H 1
+
+namespace isc {
+namespace util {
+
+class InputBuffer;
+class OutputBuffer;
+}
+
+namespace dns {
+
+// BEGIN_COMMON_DECLARATIONS
+
+class AbstractMessageRenderer;
+
+// END_COMMON_DECLARATIONS
+
+namespace rdata {
+namespace generic {
+
+struct DNSKEYImpl;
+
+class DNSKEY : public Rdata {
+public:
+ // BEGIN_COMMON_MEMBERS
+
+ explicit DNSKEY(const std::string& type_str);
+ DNSKEY(isc::util::InputBuffer& buffer, size_t rdata_len);
+ DNSKEY(const DNSKEY& other);
+ DNSKEY(
+ MasterLexer& lexer, const Name* name,
+ MasterLoader::Options options, MasterLoaderCallbacks& callbacks);
+ virtual std::string toText() const;
+ virtual void toWire(isc::util::OutputBuffer& buffer) const;
+ virtual void toWire(AbstractMessageRenderer& renderer) const;
+ virtual int compare(const Rdata& other) const;
+
+ // END_COMMON_MEMBERS
+ DNSKEY& operator=(const DNSKEY& source);
+ ~DNSKEY();
+
+ ///
+ /// Specialized methods
+ ///
+
+ /// \brief Returns the key tag
+ ///
+ /// \throw isc::OutOfRange if the key data for RSA/MD5 is too short
+ /// to support tag extraction.
+ uint16_t getTag() const;
+
+ uint16_t getFlags() const;
+ uint8_t getAlgorithm() const;
+
+private:
+ DNSKEYImpl* constructFromLexer(isc::dns::MasterLexer& lexer);
+
+ DNSKEYImpl* impl_;
+};
+
+} // end of namespace "generic"
+} // end of namespace "rdata"
+} // end of namespace "dns"
+} // end of namespace "isc"
+#endif // GENERIC_DNSKEY_48_H
+
+// 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 GENERIC_DS_43_H
+#define GENERIC_DS_43_H 1
+
+#include <stdint.h>
+
+#include <string>
+
+#include <dns/name.h>
+#include <dns/rrtype.h>
+#include <dns/rrttl.h>
+#include <dns/rdata.h>
+
+namespace isc {
+namespace util {
+
+class InputBuffer;
+class OutputBuffer;
+}
+
+namespace dns {
+
+// BEGIN_COMMON_DECLARATIONS
+
+class AbstractMessageRenderer;
+
+// END_COMMON_DECLARATIONS
+
+namespace rdata {
+namespace generic {
+
+namespace detail {
+template <class Type, uint16_t typeCode> class DSLikeImpl;
+}
+
+/// \brief \c rdata::generic::DS class represents the DS RDATA as defined in
+/// RFC3658.
+///
+/// This class implements the basic interfaces inherited from the abstract
+/// \c rdata::Rdata class, and provides trivial accessors specific to the
+/// DS RDATA.
+class DS : public Rdata {
+public:
+ // BEGIN_COMMON_MEMBERS
+
+ explicit DS(const std::string& type_str);
+ DS(isc::util::InputBuffer& buffer, size_t rdata_len);
+ DS(const DS& other);
+ DS(
+ MasterLexer& lexer, const Name* name,
+ MasterLoader::Options options, MasterLoaderCallbacks& callbacks);
+ virtual std::string toText() const;
+ virtual void toWire(isc::util::OutputBuffer& buffer) const;
+ virtual void toWire(AbstractMessageRenderer& renderer) const;
+ virtual int compare(const Rdata& other) const;
+
+ // END_COMMON_MEMBERS
+
+ /// \brief Assignment operator.
+ ///
+ /// It internally allocates a resource, and if it fails a corresponding
+ /// standard exception will be thrown.
+ /// This operator never throws an exception otherwise.
+ ///
+ /// This operator provides the strong exception guarantee: When an
+ /// exception is thrown the content of the assignment target will be
+ /// intact.
+ DS& operator=(const DS& source);
+
+ /// \brief The destructor.
+ ~DS();
+
+ /// \brief Return the value of the Tag field.
+ ///
+ /// This method never throws an exception.
+ uint16_t getTag() const;
+private:
+ typedef detail::DSLikeImpl<DS, 43> DSImpl;
+ DSImpl* impl_;
+};
+
+} // end of namespace "generic"
+} // end of namespace "rdata"
+} // end of namespace "dns"
+} // end of namespace "isc"
+#endif // GENERIC_DS_43_H
+
+// 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 GENERIC_HINFO_13_H
+#define GENERIC_HINFO_13_H 1
+#include <stdint.h>
+
+#include <string>
+
+#include <boost/scoped_ptr.hpp>
+#include <boost/noncopyable.hpp>
+
+#include <dns/name.h>
+#include <dns/rdata.h>
+#include <util/buffer.h>
+
+namespace isc {
+namespace util {
+
+class InputBuffer;
+class OutputBuffer;
+}
+
+namespace dns {
+
+// BEGIN_COMMON_DECLARATIONS
+
+class AbstractMessageRenderer;
+
+// END_COMMON_DECLARATIONS
+
+namespace rdata {
+namespace generic {
+
+class HINFOImpl;
+
+/// \brief \c HINFO class represents the HINFO rdata defined in
+/// RFC1034, RFC1035
+///
+/// This class implements the basic interfaces inherited from the
+/// \c rdata::Rdata class, and provides accessors specific to the
+/// HINFO rdata.
+class HINFO : public Rdata {
+public:
+ // BEGIN_COMMON_MEMBERS
+
+ explicit HINFO(const std::string& type_str);
+ HINFO(isc::util::InputBuffer& buffer, size_t rdata_len);
+ HINFO(const HINFO& other);
+ HINFO(
+ MasterLexer& lexer, const Name* name,
+ MasterLoader::Options options, MasterLoaderCallbacks& callbacks);
+ virtual std::string toText() const;
+ virtual void toWire(isc::util::OutputBuffer& buffer) const;
+ virtual void toWire(AbstractMessageRenderer& renderer) const;
+ virtual int compare(const Rdata& other) const;
+
+ // END_COMMON_MEMBERS
+
+ // HINFO specific methods
+ ~HINFO();
+
+ HINFO& operator=(const HINFO&);
+
+ const std::string getCPU() const;
+ const std::string getOS() const;
+
+private:
+ /// Helper template function for toWire()
+ ///
+ /// \param outputer Where to write data in
+ template <typename T>
+ void toWireHelper(T& outputer) const;
+
+ boost::scoped_ptr<HINFOImpl> impl_;
+};
+
+
+} // end of namespace "generic"
+} // end of namespace "rdata"
+} // end of namespace "dns"
+} // end of namespace "isc"
+#endif // GENERIC_HINFO_13_H
+
+// Copyright (C) 2011-2013 Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// 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 GENERIC_MINFO_14_H
+#define GENERIC_MINFO_14_H 1
+
+#include <string>
+
+#include <dns/name.h>
+#include <dns/rdata.h>
+
+namespace isc {
+namespace util {
+
+class InputBuffer;
+class OutputBuffer;
+}
+
+namespace dns {
+
+// BEGIN_COMMON_DECLARATIONS
+
+class AbstractMessageRenderer;
+
+// END_COMMON_DECLARATIONS
+
+namespace rdata {
+namespace generic {
+
+/// \brief \c rdata::generic::MINFO class represents the MINFO RDATA as
+/// defined in RFC1035.
+///
+/// This class implements the basic interfaces inherited from the abstract
+/// \c rdata::Rdata class, and provides trivial accessors specific to the
+/// MINFO RDATA.
+class MINFO : public Rdata {
+public:
+ // BEGIN_COMMON_MEMBERS
+
+ explicit MINFO(const std::string& type_str);
+ MINFO(isc::util::InputBuffer& buffer, size_t rdata_len);
+ MINFO(const MINFO& other);
+ MINFO(
+ MasterLexer& lexer, const Name* name,
+ MasterLoader::Options options, MasterLoaderCallbacks& callbacks);
+ virtual std::string toText() const;
+ virtual void toWire(isc::util::OutputBuffer& buffer) const;
+ virtual void toWire(AbstractMessageRenderer& renderer) const;
+ virtual int compare(const Rdata& other) const;
+
+ // END_COMMON_MEMBERS
+
+ /// \brief Define the assignment operator.
+ ///
+ /// \exception std::bad_alloc Memory allocation fails in copying
+ /// internal member variables (this should be very rare).
+ MINFO& operator=(const MINFO& source);
+
+ /// \brief Return the value of the rmailbox field.
+ ///
+ /// \throw std::bad_alloc If resource allocation for the returned
+ /// \c Name fails.
+ ///
+ /// \note
+ /// Unlike the case of some other RDATA classes (such as
+ /// \c NS::getNSName()), this method constructs a new \c Name object
+ /// and returns it, instead of returning a reference to a \c Name object
+ /// internally maintained in the class (which is a private member).
+ /// This is based on the observation that this method will be rarely
+ /// used and even when it's used it will not be in a performance context
+ /// (for example, a recursive resolver won't need this field in its
+ /// resolution process). By returning a new object we have flexibility
+ /// of changing the internal representation without the risk of changing
+ /// the interface or method property.
+ /// The same note applies to the \c getEmailbox() method.
+ Name getRmailbox() const { return (rmailbox_); }
+
+ /// \brief Return the value of the emailbox field.
+ ///
+ /// \throw std::bad_alloc If resource allocation for the returned
+ /// \c Name fails.
+ Name getEmailbox() const { return (emailbox_); }
+
+private:
+ Name rmailbox_;
+ Name emailbox_;
+};
+
+} // end of namespace "generic"
+} // end of namespace "rdata"
+} // end of namespace "dns"
+} // end of namespace "isc"
+#endif // GENERIC_MINFO_14_H
+
+// 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 GENERIC_MX_15_H
+#define GENERIC_MX_15_H 1
+
+#include <stdint.h>
+
+#include <string>
+
+#include <dns/name.h>
+#include <dns/rdata.h>
+
+namespace isc {
+namespace util {
+
+class InputBuffer;
+class OutputBuffer;
+}
+
+namespace dns {
+
+// BEGIN_COMMON_DECLARATIONS
+
+class AbstractMessageRenderer;
+
+// END_COMMON_DECLARATIONS
+
+namespace rdata {
+namespace generic {
+
+class MX : public Rdata {
+public:
+ // BEGIN_COMMON_MEMBERS
+
+ explicit MX(const std::string& type_str);
+ MX(isc::util::InputBuffer& buffer, size_t rdata_len);
+ MX(const MX& other);
+ MX(
+ MasterLexer& lexer, const Name* name,
+ MasterLoader::Options options, MasterLoaderCallbacks& callbacks);
+ virtual std::string toText() const;
+ virtual void toWire(isc::util::OutputBuffer& buffer) const;
+ virtual void toWire(AbstractMessageRenderer& renderer) const;
+ virtual int compare(const Rdata& other) const;
+
+ // END_COMMON_MEMBERS
+
+ MX(uint16_t preference, const Name& mxname);
+
+ ///
+ /// Specialized methods
+ ///
+ const Name& getMXName() const;
+ uint16_t getMXPref() const;
+
+private:
+ void constructFromLexer(isc::dns::MasterLexer& lexer,
+ const isc::dns::Name* origin);
+
+ /// Note: this is a prototype version; we may reconsider
+ /// this representation later.
+ uint16_t preference_;
+ Name mxname_;
+};
+
+} // end of namespace "generic"
+} // end of namespace "rdata"
+} // end of namespace "dns"
+} // end of namespace "isc"
+#endif // GENERIC_MX_15_H
+
+// 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 GENERIC_NAPTR_35_H
+#define GENERIC_NAPTR_35_H 1
+
+#include <string>
+
+#include <boost/scoped_ptr.hpp>
+
+#include <dns/name.h>
+#include <dns/rdata.h>
+#include <util/buffer.h>
+
+namespace isc {
+namespace util {
+
+class InputBuffer;
+class OutputBuffer;
+}
+
+namespace dns {
+
+// BEGIN_COMMON_DECLARATIONS
+
+class AbstractMessageRenderer;
+
+// END_COMMON_DECLARATIONS
+
+namespace rdata {
+namespace generic {
+
+class NAPTRImpl;
+
+/// \brief \c NAPTR class represents the NAPTR rdata defined in
+/// RFC2915, RFC2168 and RFC3403
+///
+/// This class implements the basic interfaces inherited from the
+/// \c rdata::Rdata class, and provides accessors specific to the
+/// NAPTR rdata.
+class NAPTR : public Rdata {
+public:
+ // BEGIN_COMMON_MEMBERS
+
+ explicit NAPTR(const std::string& type_str);
+ NAPTR(isc::util::InputBuffer& buffer, size_t rdata_len);
+ NAPTR(const NAPTR& other);
+ NAPTR(
+ MasterLexer& lexer, const Name* name,
+ MasterLoader::Options options, MasterLoaderCallbacks& callbacks);
+ virtual std::string toText() const;
+ virtual void toWire(isc::util::OutputBuffer& buffer) const;
+ virtual void toWire(AbstractMessageRenderer& renderer) const;
+ virtual int compare(const Rdata& other) const;
+
+ // END_COMMON_MEMBERS
+
+ // NAPTR specific methods
+ ~NAPTR();
+
+ NAPTR& operator=(const NAPTR& source);
+
+ uint16_t getOrder() const;
+ uint16_t getPreference() const;
+ const std::string getFlags() const;
+ const std::string getServices() const;
+ const std::string getRegexp() const;
+ const Name& getReplacement() const;
+private:
+ /// Helper template function for toWire()
+ ///
+ /// \param outputer Where to write data in
+ template <typename T>
+ void toWireHelper(T& outputer) const;
+
+ boost::scoped_ptr<NAPTRImpl> impl_;
+};
+
+} // end of namespace "generic"
+} // end of namespace "rdata"
+} // end of namespace "dns"
+} // end of namespace "isc"
+#endif // GENERIC_NAPTR_35_H
+
+// 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 GENERIC_NS_2_H
+#define GENERIC_NS_2_H 1
+
+#include <string>
+
+#include <dns/name.h>
+#include <dns/rdata.h>
+
+namespace isc {
+namespace util {
+
+class InputBuffer;
+class OutputBuffer;
+}
+
+namespace dns {
+
+// BEGIN_COMMON_DECLARATIONS
+
+class AbstractMessageRenderer;
+
+// END_COMMON_DECLARATIONS
+
+namespace rdata {
+namespace generic {
+
+class NS : public Rdata {
+public:
+ // BEGIN_COMMON_MEMBERS
+
+ explicit NS(const std::string& type_str);
+ NS(isc::util::InputBuffer& buffer, size_t rdata_len);
+ NS(const NS& other);
+ NS(
+ MasterLexer& lexer, const Name* name,
+ MasterLoader::Options options, MasterLoaderCallbacks& callbacks);
+ virtual std::string toText() const;
+ virtual void toWire(isc::util::OutputBuffer& buffer) const;
+ virtual void toWire(AbstractMessageRenderer& renderer) const;
+ virtual int compare(const Rdata& other) const;
+
+ // END_COMMON_MEMBERS
+ ///
+ /// Specialized constructor
+ ///
+ explicit NS(const Name& nsname) : nsname_(nsname) {}
+ ///
+ /// Specialized methods
+ ///
+ const Name& getNSName() const;
+private:
+ Name nsname_;
+};
+
+} // end of namespace "generic"
+} // end of namespace "rdata"
+} // end of namespace "dns"
+} // end of namespace "isc"
+#endif // GENERIC_NS_2_H
+
+// 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 <stdint.h>
+
+#include <string>
+#include <vector>
+
+#include <dns/name.h>
+#include <dns/rrtype.h>
+#include <dns/rrttl.h>
+#include <dns/rdata.h>
+#include <dns/master_lexer.h>
+
+#ifndef GENERIC_NSEC3_50_H
+#define GENERIC_NSEC3_50_H 1
+
+namespace isc {
+namespace util {
+
+class InputBuffer;
+class OutputBuffer;
+}
+
+namespace dns {
+
+// BEGIN_COMMON_DECLARATIONS
+
+class AbstractMessageRenderer;
+
+// END_COMMON_DECLARATIONS
+
+namespace rdata {
+namespace generic {
+
+struct NSEC3Impl;
+
+class NSEC3 : public Rdata {
+public:
+ // BEGIN_COMMON_MEMBERS
+
+ explicit NSEC3(const std::string& type_str);
+ NSEC3(isc::util::InputBuffer& buffer, size_t rdata_len);
+ NSEC3(const NSEC3& other);
+ NSEC3(
+ MasterLexer& lexer, const Name* name,
+ MasterLoader::Options options, MasterLoaderCallbacks& callbacks);
+ virtual std::string toText() const;
+ virtual void toWire(isc::util::OutputBuffer& buffer) const;
+ virtual void toWire(AbstractMessageRenderer& renderer) const;
+ virtual int compare(const Rdata& other) const;
+
+ // END_COMMON_MEMBERS
+ NSEC3& operator=(const NSEC3& source);
+ ~NSEC3();
+
+ uint8_t getHashalg() const;
+ uint8_t getFlags() const;
+ uint16_t getIterations() const;
+ const std::vector<uint8_t>& getSalt() const;
+ const std::vector<uint8_t>& getNext() const;
+
+private:
+ NSEC3Impl* constructFromLexer(isc::dns::MasterLexer& lexer);
+
+ NSEC3Impl* impl_;
+};
+
+} // end of namespace "generic"
+} // end of namespace "rdata"
+} // end of namespace "dns"
+} // end of namespace "isc"
+#endif // GENERIC_NSEC3_50_H
+
+// 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 <stdint.h>
+
+#include <string>
+#include <vector>
+
+#include <dns/name.h>
+#include <dns/rrtype.h>
+#include <dns/rrttl.h>
+#include <dns/rdata.h>
+#include <dns/master_lexer.h>
+
+#ifndef GENERIC_NSEC3PARAM_51_H
+#define GENERIC_NSEC3PARAM_51_H 1
+
+namespace isc {
+namespace util {
+
+class InputBuffer;
+class OutputBuffer;
+}
+
+namespace dns {
+
+// BEGIN_COMMON_DECLARATIONS
+
+class AbstractMessageRenderer;
+
+// END_COMMON_DECLARATIONS
+
+namespace rdata {
+namespace generic {
+
+struct NSEC3PARAMImpl;
+
+class NSEC3PARAM : public Rdata {
+public:
+ // BEGIN_COMMON_MEMBERS
+
+ explicit NSEC3PARAM(const std::string& type_str);
+ NSEC3PARAM(isc::util::InputBuffer& buffer, size_t rdata_len);
+ NSEC3PARAM(const NSEC3PARAM& other);
+ NSEC3PARAM(
+ MasterLexer& lexer, const Name* name,
+ MasterLoader::Options options, MasterLoaderCallbacks& callbacks);
+ virtual std::string toText() const;
+ virtual void toWire(isc::util::OutputBuffer& buffer) const;
+ virtual void toWire(AbstractMessageRenderer& renderer) const;
+ virtual int compare(const Rdata& other) const;
+
+ // END_COMMON_MEMBERS
+ NSEC3PARAM& operator=(const NSEC3PARAM& source);
+ ~NSEC3PARAM();
+
+ ///
+ /// Specialized methods
+ ///
+ uint8_t getHashalg() const;
+ uint8_t getFlags() const;
+ uint16_t getIterations() const;
+ const std::vector<uint8_t>& getSalt() const;
+
+private:
+ NSEC3PARAMImpl* constructFromLexer(isc::dns::MasterLexer& lexer);
+
+ NSEC3PARAMImpl* impl_;
+};
+
+} // end of namespace "generic"
+} // end of namespace "rdata"
+} // end of namespace "dns"
+} // end of namespace "isc"
+#endif // GENERIC_NSEC3PARAM_51_H
+
+// 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 <stdint.h>
+
+#include <string>
+
+#include <dns/name.h>
+#include <dns/rrtype.h>
+#include <dns/rrttl.h>
+#include <dns/rdata.h>
+
+#ifndef GENERIC_NSEC_47_H
+#define GENERIC_NSEC_47_H 1
+
+namespace isc {
+namespace util {
+
+class InputBuffer;
+class OutputBuffer;
+}
+
+namespace dns {
+
+// BEGIN_COMMON_DECLARATIONS
+
+class AbstractMessageRenderer;
+
+// END_COMMON_DECLARATIONS
+
+namespace rdata {
+namespace generic {
+
+struct NSECImpl;
+
+class NSEC : public Rdata {
+public:
+ // BEGIN_COMMON_MEMBERS
+
+ explicit NSEC(const std::string& type_str);
+ NSEC(isc::util::InputBuffer& buffer, size_t rdata_len);
+ NSEC(const NSEC& other);
+ NSEC(
+ MasterLexer& lexer, const Name* name,
+ MasterLoader::Options options, MasterLoaderCallbacks& callbacks);
+ virtual std::string toText() const;
+ virtual void toWire(isc::util::OutputBuffer& buffer) const;
+ virtual void toWire(AbstractMessageRenderer& renderer) const;
+ virtual int compare(const Rdata& other) const;
+
+ // END_COMMON_MEMBERS
+ NSEC& operator=(const NSEC& source);
+ ~NSEC();
+
+ // specialized methods
+
+ /// Return the next domain name.
+ ///
+ /// \exception std::bad_alloc Resource allocation failure in name copy.
+ ///
+ /// \return The next domain name field in the form of \c Name object.
+ const Name& getNextName() const;
+
+private:
+ NSECImpl* impl_;
+};
+
+} // end of namespace "generic"
+} // end of namespace "rdata"
+} // end of namespace "dns"
+} // end of namespace "isc"
+#endif // GENERIC_NSEC_47_H
+
+// 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 GENERIC_OPT_41_H
+#define GENERIC_OPT_41_H 1
+
+#include <string>
+
+#include <dns/rdata.h>
+
+#include <boost/shared_ptr.hpp>
+
+#include <vector>
+
+namespace isc {
+namespace util {
+
+class InputBuffer;
+class OutputBuffer;
+}
+
+namespace dns {
+
+// BEGIN_COMMON_DECLARATIONS
+
+class AbstractMessageRenderer;
+
+// END_COMMON_DECLARATIONS
+
+namespace rdata {
+namespace generic {
+
+struct OPTImpl;
+
+class OPT : public Rdata {
+public:
+ // BEGIN_COMMON_MEMBERS
+
+ explicit OPT(const std::string& type_str);
+ OPT(isc::util::InputBuffer& buffer, size_t rdata_len);
+ OPT(const OPT& other);
+ OPT(
+ MasterLexer& lexer, const Name* name,
+ MasterLoader::Options options, MasterLoaderCallbacks& callbacks);
+ virtual std::string toText() const;
+ virtual void toWire(isc::util::OutputBuffer& buffer) const;
+ virtual void toWire(AbstractMessageRenderer& renderer) const;
+ virtual int compare(const Rdata& other) const;
+
+ // END_COMMON_MEMBERS
+
+ // The default constructor makes sense for OPT as it can be empty.
+ OPT();
+ OPT& operator=(const OPT& source);
+ ~OPT();
+
+ /// \brief A class representing a pseudo RR (or option) within an
+ /// OPT RR (see RFC 6891).
+ class PseudoRR {
+ public:
+ /// \brief Constructor.
+ /// \param code The OPTION-CODE field of the pseudo RR.
+ /// \param data The OPTION-DATA field of the pseudo
+ /// RR. OPTION-LENGTH is set to the length of this vector.
+ PseudoRR(uint16_t code,
+ boost::shared_ptr<std::vector<uint8_t> >& data);
+
+ /// \brief Return the option code of this pseudo RR.
+ uint16_t getCode() const;
+
+ /// \brief Return the option data of this pseudo RR.
+ const uint8_t* getData() const;
+
+ /// \brief Return the length of the option data of this
+ /// pseudo RR.
+ uint16_t getLength() const;
+
+ private:
+ uint16_t code_;
+ boost::shared_ptr<std::vector<uint8_t> > data_;
+ };
+
+ /// \brief Append a pseudo RR (option) in this OPT RR.
+ ///
+ /// \param code The OPTION-CODE field of the pseudo RR.
+ /// \param data The OPTION-DATA field of the pseudo RR.
+ /// \param length The size of the \c data argument. OPTION-LENGTH is
+ /// set to this size.
+ /// \throw \c isc::InvalidParameter if this pseudo RR would cause
+ /// the OPT RDATA to overflow its RDLENGTH.
+ void appendPseudoRR(uint16_t code, const uint8_t* data, uint16_t length);
+
+ /// \brief Return a vector of the pseudo RRs (options) in this
+ /// OPT RR.
+ ///
+ /// Note: The returned reference is only valid during the lifetime
+ /// of this \c generic::OPT object. It should not be used
+ /// afterwards.
+ const std::vector<PseudoRR>& getPseudoRRs() const;
+
+private:
+ OPTImpl* impl_;
+};
+
+} // end of namespace "generic"
+} // end of namespace "rdata"
+} // end of namespace "dns"
+} // end of namespace "isc"
+#endif // GENERIC_OPT_41_H
+
+// 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 GENERIC_PTR_12_H
+#define GENERIC_PTR_12_H 1
+
+#include <string>
+
+#include <dns/name.h>
+#include <dns/rdata.h>
+
+namespace isc {
+namespace util {
+
+class InputBuffer;
+class OutputBuffer;
+}
+
+namespace dns {
+
+// BEGIN_COMMON_DECLARATIONS
+
+class AbstractMessageRenderer;
+
+// END_COMMON_DECLARATIONS
+
+namespace rdata {
+namespace generic {
+
+class PTR : public Rdata {
+public:
+ // BEGIN_COMMON_MEMBERS
+
+ explicit PTR(const std::string& type_str);
+ PTR(isc::util::InputBuffer& buffer, size_t rdata_len);
+ PTR(const PTR& other);
+ PTR(
+ MasterLexer& lexer, const Name* name,
+ MasterLoader::Options options, MasterLoaderCallbacks& callbacks);
+ virtual std::string toText() const;
+ virtual void toWire(isc::util::OutputBuffer& buffer) const;
+ virtual void toWire(AbstractMessageRenderer& renderer) const;
+ virtual int compare(const Rdata& other) const;
+
+ // END_COMMON_MEMBERS
+
+ ///
+ /// Specialized constructor
+ ///
+ explicit PTR(const Name& ptr_name) : ptr_name_(ptr_name) {}
+ ///
+ /// Specialized methods
+ ///
+ const Name& getPTRName() const;
+private:
+ Name ptr_name_;
+};
+
+} // end of namespace "generic"
+} // end of namespace "rdata"
+} // end of namespace "dns"
+} // end of namespace "isc"
+#endif // GENERIC_PTR_12_H
+
+// Copyright (C) 2011-2013 Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// 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 GENERIC_RP_17_H
+#define GENERIC_RP_17_H 1
+
+#include <string>
+
+#include <dns/name.h>
+#include <dns/rdata.h>
+
+namespace isc {
+namespace util {
+
+class InputBuffer;
+class OutputBuffer;
+}
+
+namespace dns {
+
+// BEGIN_COMMON_DECLARATIONS
+
+class AbstractMessageRenderer;
+
+// END_COMMON_DECLARATIONS
+
+namespace rdata {
+namespace generic {
+
+/// \brief \c rdata::generic::RP class represents the RP RDATA as defined in
+/// RFC1183.
+///
+/// This class implements the basic interfaces inherited from the abstract
+/// \c rdata::Rdata class, and provides trivial accessors specific to the
+/// RP RDATA.
+class RP : public Rdata {
+public:
+ // BEGIN_COMMON_MEMBERS
+
+ explicit RP(const std::string& type_str);
+ RP(isc::util::InputBuffer& buffer, size_t rdata_len);
+ RP(const RP& other);
+ RP(
+ MasterLexer& lexer, const Name* name,
+ MasterLoader::Options options, MasterLoaderCallbacks& callbacks);
+ virtual std::string toText() const;
+ virtual void toWire(isc::util::OutputBuffer& buffer) const;
+ virtual void toWire(AbstractMessageRenderer& renderer) const;
+ virtual int compare(const Rdata& other) const;
+
+ // END_COMMON_MEMBERS
+
+ /// We use the default copy constructor and assignment operator.
+
+ /// \brief Constructor from RDATA field parameters.
+ ///
+ /// The parameters are a straightforward mapping of %RP RDATA
+ /// fields as defined in RFC1183.
+ RP(const Name& mailbox, const Name& text) :
+ mailbox_(mailbox), text_(text)
+ {}
+
+ /// \brief Return the value of the mailbox field.
+ ///
+ /// \throw std::bad_alloc If resource allocation for the returned
+ /// \c Name fails.
+ ///
+ /// \note
+ /// Unlike the case of some other RDATA classes (such as
+ /// \c NS::getNSName()), this method constructs a new \c Name object
+ /// and returns it, instead of returning a reference to a \c Name object
+ /// internally maintained in the class (which is a private member).
+ /// This is based on the observation that this method will be rarely used
+ /// and even when it's used it will not be in a performance context
+ /// (for example, a recursive resolver won't need this field in its
+ /// resolution process). By returning a new object we have flexibility of
+ /// changing the internal representation without the risk of changing
+ /// the interface or method property.
+ /// The same note applies to the \c getText() method.
+ Name getMailbox() const { return (mailbox_); }
+
+ /// \brief Return the value of the text field.
+ ///
+ /// \throw std::bad_alloc If resource allocation for the returned
+ /// \c Name fails.
+ Name getText() const { return (text_); }
+
+private:
+ Name mailbox_;
+ Name text_;
+};
+
+} // end of namespace "generic"
+} // end of namespace "rdata"
+} // end of namespace "dns"
+} // end of namespace "isc"
+#endif // GENERIC_RP_17_H
+
+// 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 <stdint.h>
+
+#include <string>
+
+#include <dns/name.h>
+#include <dns/rrtype.h>
+#include <dns/rdata.h>
+
+#ifndef GENERIC_RRSIG_46_H
+#define GENERIC_RRSIG_46_H 1
+
+namespace isc {
+namespace util {
+
+class InputBuffer;
+class OutputBuffer;
+}
+
+namespace dns {
+
+// BEGIN_COMMON_DECLARATIONS
+
+class AbstractMessageRenderer;
+
+// END_COMMON_DECLARATIONS
+
+namespace rdata {
+namespace generic {
+
+struct RRSIGImpl;
+
+/// \brief \c rdata::RRSIG class represents the RRSIG RDATA as defined %in
+/// RFC4034.
+///
+/// This class implements the basic interfaces inherited from the abstract
+/// \c rdata::Rdata class, and provides trivial accessors specific to the
+/// RRSIG RDATA.
+class RRSIG : public Rdata {
+public:
+ // BEGIN_COMMON_MEMBERS
+
+ explicit RRSIG(const std::string& type_str);
+ RRSIG(isc::util::InputBuffer& buffer, size_t rdata_len);
+ RRSIG(const RRSIG& other);
+ RRSIG(
+ MasterLexer& lexer, const Name* name,
+ MasterLoader::Options options, MasterLoaderCallbacks& callbacks);
+ virtual std::string toText() const;
+ virtual void toWire(isc::util::OutputBuffer& buffer) const;
+ virtual void toWire(AbstractMessageRenderer& renderer) const;
+ virtual int compare(const Rdata& other) const;
+
+ // END_COMMON_MEMBERS
+ RRSIG& operator=(const RRSIG& source);
+ ~RRSIG();
+
+ // specialized methods
+ const RRType& typeCovered() const;
+private:
+ // helper function for string and lexer constructors
+ RRSIGImpl* constructFromLexer(MasterLexer& lexer, const Name* origin);
+
+ RRSIGImpl* impl_;
+};
+
+} // end of namespace "generic"
+} // end of namespace "rdata"
+} // end of namespace "dns"
+} // end of namespace "isc"
+#endif // GENERIC_RRSIG_46_H
+
+// 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 GENERIC_SOA_6_H
+#define GENERIC_SOA_6_H 1
+
+#include <string>
+
+#include <dns/name.h>
+#include <dns/rdata.h>
+#include <dns/serial.h>
+
+namespace isc {
+namespace util {
+
+class InputBuffer;
+class OutputBuffer;
+}
+
+namespace dns {
+
+// BEGIN_COMMON_DECLARATIONS
+
+class AbstractMessageRenderer;
+
+// END_COMMON_DECLARATIONS
+
+namespace rdata {
+namespace generic {
+
+class SOA : public Rdata {
+public:
+ // BEGIN_COMMON_MEMBERS
+
+ explicit SOA(const std::string& type_str);
+ SOA(isc::util::InputBuffer& buffer, size_t rdata_len);
+ SOA(const SOA& other);
+ SOA(
+ MasterLexer& lexer, const Name* name,
+ MasterLoader::Options options, MasterLoaderCallbacks& callbacks);
+ virtual std::string toText() const;
+ virtual void toWire(isc::util::OutputBuffer& buffer) const;
+ virtual void toWire(AbstractMessageRenderer& renderer) const;
+ virtual int compare(const Rdata& other) const;
+
+ // END_COMMON_MEMBERS
+
+ SOA(const Name& mname, const Name& rname, uint32_t serial,
+ uint32_t refresh, uint32_t retry, uint32_t expire,
+ uint32_t minimum);
+
+ /// \brief Returns the serial stored in the SOA.
+ Serial getSerial() const;
+
+ /// brief Returns the minimum TTL field value of the SOA.
+ uint32_t getMinimum() const;
+private:
+ /// Note: this is a prototype version; we may reconsider
+ /// this representation later.
+ Name mname_;
+ Name rname_;
+ /// serial, refresh, retry, expire, minimum, stored in network byte order
+ uint8_t numdata_[20];
+};
+
+} // end of namespace "generic"
+} // end of namespace "rdata"
+} // end of namespace "dns"
+} // end of namespace "isc"
+#endif // GENERIC_SOA_6_H
+
+// 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 GENERIC_SPF_99_H
+#define GENERIC_SPF_99_H 1
+
+#include <stdint.h>
+
+#include <string>
+#include <vector>
+
+#include <dns/rdata.h>
+
+namespace isc {
+namespace util {
+
+class InputBuffer;
+class OutputBuffer;
+}
+
+namespace dns {
+
+// BEGIN_COMMON_DECLARATIONS
+
+class AbstractMessageRenderer;
+
+// END_COMMON_DECLARATIONS
+
+namespace rdata {
+namespace generic {
+
+namespace detail {
+template<class Type, uint16_t typeCode> class TXTLikeImpl;
+}
+
+/// \brief \c rdata::SPF class represents the SPF RDATA as defined %in
+/// RFC4408.
+///
+/// This class implements the basic interfaces inherited from the abstract
+/// \c rdata::Rdata class. The semantics of the class is provided by
+/// a copy of instantiated TXTLikeImpl class common to both TXT and SPF.
+class SPF : public Rdata {
+public:
+ // BEGIN_COMMON_MEMBERS
+
+ explicit SPF(const std::string& type_str);
+ SPF(isc::util::InputBuffer& buffer, size_t rdata_len);
+ SPF(const SPF& other);
+ SPF(
+ MasterLexer& lexer, const Name* name,
+ MasterLoader::Options options, MasterLoaderCallbacks& callbacks);
+ virtual std::string toText() const;
+ virtual void toWire(isc::util::OutputBuffer& buffer) const;
+ virtual void toWire(AbstractMessageRenderer& renderer) const;
+ virtual int compare(const Rdata& other) const;
+
+ // END_COMMON_MEMBERS
+
+ /// \brief Assignment operator.
+ ///
+ /// It internally allocates a resource, and if it fails a corresponding
+ /// standard exception will be thrown.
+ /// This operator never throws an exception otherwise.
+ ///
+ /// This operator provides the strong exception guarantee: When an
+ /// exception is thrown the content of the assignment target will be
+ /// intact.
+ SPF& operator=(const SPF& source);
+
+ /// \brief The destructor.
+ ~SPF();
+
+ ///
+ /// Specialized methods
+ ///
+
+ /// \brief Return a reference to the data strings
+ ///
+ /// This method never throws an exception.
+ const std::vector<std::vector<uint8_t> >& getString() const;
+
+private:
+ typedef isc::dns::rdata::generic::detail::TXTLikeImpl<SPF, 99> SPFImpl;
+ SPFImpl* impl_;
+};
+
+} // end of namespace "generic"
+} // end of namespace "rdata"
+} // end of namespace "dns"
+} // end of namespace "isc"
+#endif // GENERIC_SPF_99_H
+
+// Copyright (C) 2012-2013 Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// 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 GENERIC_SSHFP_44_H
+#define GENERIC_SSHFP_44_H 1
+
+#include <stdint.h>
+
+#include <string>
+#include <vector>
+
+#include <dns/name.h>
+#include <dns/rdata.h>
+
+namespace isc {
+namespace util {
+
+class InputBuffer;
+class OutputBuffer;
+}
+
+namespace dns {
+
+// BEGIN_COMMON_DECLARATIONS
+
+class AbstractMessageRenderer;
+
+// END_COMMON_DECLARATIONS
+
+namespace rdata {
+namespace generic {
+
+struct SSHFPImpl;
+
+class SSHFP : public Rdata {
+public:
+ // BEGIN_COMMON_MEMBERS
+
+ explicit SSHFP(const std::string& type_str);
+ SSHFP(isc::util::InputBuffer& buffer, size_t rdata_len);
+ SSHFP(const SSHFP& other);
+ SSHFP(
+ MasterLexer& lexer, const Name* name,
+ MasterLoader::Options options, MasterLoaderCallbacks& callbacks);
+ virtual std::string toText() const;
+ virtual void toWire(isc::util::OutputBuffer& buffer) const;
+ virtual void toWire(AbstractMessageRenderer& renderer) const;
+ virtual int compare(const Rdata& other) const;
+
+ // END_COMMON_MEMBERS
+
+ SSHFP(uint8_t algorithm, uint8_t fingerprint_type,
+ const std::string& fingerprint);
+ SSHFP& operator=(const SSHFP& source);
+ ~SSHFP();
+
+ ///
+ /// Specialized methods
+ ///
+ uint8_t getAlgorithmNumber() const;
+ uint8_t getFingerprintType() const;
+ const std::vector<uint8_t>& getFingerprint() const;
+ size_t getFingerprintLength() const;
+
+private:
+ SSHFPImpl* constructFromLexer(MasterLexer& lexer);
+
+ SSHFPImpl* impl_;
+};
+
+} // end of namespace "generic"
+} // end of namespace "rdata"
+} // end of namespace "dns"
+} // end of namespace "isc"
+#endif // GENERIC_SSHFP_44_H
+
+// 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 GENERIC_TLSA_52_H
+#define GENERIC_TLSA_52_H 1
+
+#include <stdint.h>
+
+#include <dns/name.h>
+#include <dns/rdata.h>
+
+#include <string>
+#include <vector>
+
+namespace isc {
+namespace util {
+
+class InputBuffer;
+class OutputBuffer;
+}
+
+namespace dns {
+
+// BEGIN_COMMON_DECLARATIONS
+
+class AbstractMessageRenderer;
+
+// END_COMMON_DECLARATIONS
+
+namespace rdata {
+namespace generic {
+
+struct TLSAImpl;
+
+class TLSA : public Rdata {
+public:
+ // BEGIN_COMMON_MEMBERS
+
+ explicit TLSA(const std::string& type_str);
+ TLSA(isc::util::InputBuffer& buffer, size_t rdata_len);
+ TLSA(const TLSA& other);
+ TLSA(
+ MasterLexer& lexer, const Name* name,
+ MasterLoader::Options options, MasterLoaderCallbacks& callbacks);
+ virtual std::string toText() const;
+ virtual void toWire(isc::util::OutputBuffer& buffer) const;
+ virtual void toWire(AbstractMessageRenderer& renderer) const;
+ virtual int compare(const Rdata& other) const;
+
+ // END_COMMON_MEMBERS
+
+ TLSA(uint8_t certificate_usage, uint8_t selector,
+ uint8_t matching_type, const std::string& certificate_assoc_data);
+ TLSA& operator=(const TLSA& source);
+ ~TLSA();
+
+ ///
+ /// Specialized methods
+ ///
+ uint8_t getCertificateUsage() const;
+ uint8_t getSelector() const;
+ uint8_t getMatchingType() const;
+ const std::vector<uint8_t>& getData() const;
+ size_t getDataLength() const;
+
+private:
+ TLSAImpl* constructFromLexer(MasterLexer& lexer);
+
+ TLSAImpl* impl_;
+};
+
+} // end of namespace "generic"
+} // end of namespace "rdata"
+} // end of namespace "dns"
+} // end of namespace "isc"
+#endif // GENERIC_TLSA_52_H
+
+// 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 GENERIC_TXT_16_H
+#define GENERIC_TXT_16_H 1
+
+#include <stdint.h>
+
+#include <string>
+#include <vector>
+
+#include <dns/rdata.h>
+
+namespace isc {
+namespace util {
+
+class InputBuffer;
+class OutputBuffer;
+}
+
+namespace dns {
+
+// BEGIN_COMMON_DECLARATIONS
+
+class AbstractMessageRenderer;
+
+// END_COMMON_DECLARATIONS
+
+namespace rdata {
+namespace generic {
+
+namespace detail {
+template<class Type, uint16_t typeCode> class TXTLikeImpl;
+}
+
+class TXT : public Rdata {
+public:
+ // BEGIN_COMMON_MEMBERS
+
+ explicit TXT(const std::string& type_str);
+ TXT(isc::util::InputBuffer& buffer, size_t rdata_len);
+ TXT(const TXT& other);
+ TXT(
+ MasterLexer& lexer, const Name* name,
+ MasterLoader::Options options, MasterLoaderCallbacks& callbacks);
+ virtual std::string toText() const;
+ virtual void toWire(isc::util::OutputBuffer& buffer) const;
+ virtual void toWire(AbstractMessageRenderer& renderer) const;
+ virtual int compare(const Rdata& other) const;
+
+ // END_COMMON_MEMBERS
+
+ TXT& operator=(const TXT& source);
+ ~TXT();
+
+private:
+ typedef isc::dns::rdata::generic::detail::TXTLikeImpl<TXT, 16> TXTImpl;
+ TXTImpl* impl_;
+};
+
+} // end of namespace "generic"
+} // end of namespace "rdata"
+} // end of namespace "dns"
+} // end of namespace "isc"
+#endif // GENERIC_TXT_16_H
+
+// 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 HS_A_1_H
+#define HS_A_1_H 1
+
+#include <string>
+
+#include <dns/rdata.h>
+
+namespace isc {
+namespace util {
+
+class InputBuffer;
+class OutputBuffer;
+}
+
+namespace dns {
+
+// BEGIN_COMMON_DECLARATIONS
+
+class AbstractMessageRenderer;
+
+// END_COMMON_DECLARATIONS
+
+namespace rdata {
+namespace hs {
+
+class A : public Rdata {
+public:
+ // BEGIN_COMMON_MEMBERS
+
+ explicit A(const std::string& type_str);
+ A(isc::util::InputBuffer& buffer, size_t rdata_len);
+ A(const A& other);
+ A(
+ MasterLexer& lexer, const Name* name,
+ MasterLoader::Options options, MasterLoaderCallbacks& callbacks);
+ virtual std::string toText() const;
+ virtual void toWire(isc::util::OutputBuffer& buffer) const;
+ virtual void toWire(AbstractMessageRenderer& renderer) const;
+ virtual int compare(const Rdata& other) const;
+
+ // END_COMMON_MEMBERS
+};
+
+} // end of namespace "hs"
+} // end of namespace "rdata"
+} // end of namespace "dns"
+} // end of namespace "isc"
+#endif // HS_A_1_H
+
+// 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 IN_A_1_H
+#define IN_A_1_H 1
+
+#include <string>
+
+#include <dns/rdata.h>
+
+namespace isc {
+namespace util {
+
+class InputBuffer;
+class OutputBuffer;
+}
+
+namespace dns {
+
+// BEGIN_COMMON_DECLARATIONS
+
+class AbstractMessageRenderer;
+
+// END_COMMON_DECLARATIONS
+
+namespace rdata {
+namespace in {
+
+class A : public Rdata {
+public:
+ // BEGIN_COMMON_MEMBERS
+
+ explicit A(const std::string& type_str);
+ A(isc::util::InputBuffer& buffer, size_t rdata_len);
+ A(const A& other);
+ A(
+ MasterLexer& lexer, const Name* name,
+ MasterLoader::Options options, MasterLoaderCallbacks& callbacks);
+ virtual std::string toText() const;
+ virtual void toWire(isc::util::OutputBuffer& buffer) const;
+ virtual void toWire(AbstractMessageRenderer& renderer) const;
+ virtual int compare(const Rdata& other) const;
+
+ // END_COMMON_MEMBERS
+
+ //We can use the default destructor.
+ //virtual ~A() {}
+ // notyet:
+ //const struct in_addr& getAddress() const { return (addr_); }
+private:
+ uint32_t addr_; // raw IPv4 address (network byte order)
+};
+} // end of namespace "in"
+} // end of namespace "rdata"
+} // end of namespace "dns"
+} // end of namespace "isc"
+#endif // IN_A_1_H
+
+// 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 IN_AAAA_28_H
+#define IN_AAAA_28_H 1
+
+#include <stdint.h>
+
+#include <string>
+
+#include <dns/rdata.h>
+
+namespace isc {
+namespace util {
+
+class InputBuffer;
+class OutputBuffer;
+}
+
+namespace dns {
+
+// BEGIN_COMMON_DECLARATIONS
+
+class AbstractMessageRenderer;
+
+// END_COMMON_DECLARATIONS
+
+namespace rdata {
+namespace in {
+
+class AAAA : public Rdata {
+public:
+ // BEGIN_COMMON_MEMBERS
+
+ explicit AAAA(const std::string& type_str);
+ AAAA(isc::util::InputBuffer& buffer, size_t rdata_len);
+ AAAA(const AAAA& other);
+ AAAA(
+ MasterLexer& lexer, const Name* name,
+ MasterLoader::Options options, MasterLoaderCallbacks& callbacks);
+ virtual std::string toText() const;
+ virtual void toWire(isc::util::OutputBuffer& buffer) const;
+ virtual void toWire(AbstractMessageRenderer& renderer) const;
+ virtual int compare(const Rdata& other) const;
+
+ // END_COMMON_MEMBERS
+ // notyet:
+ //const struct in6_addr& getAddress() const { return (addr_); }
+private:
+ uint8_t addr_[16]; // raw IPv6 address (network byte order)
+};
+
+} // end of namespace "in"
+} // end of namespace "rdata"
+} // end of namespace "dns"
+} // end of namespace "isc"
+#endif // IN_AAAA_28_H
+
+// Copyright (C) 2011-2013 Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// 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 IN_DHCID_49_H
+#define IN_DHCID_49_H 1
+
+#include <string>
+#include <vector>
+
+#include <dns/rdata.h>
+
+namespace isc {
+namespace util {
+
+class InputBuffer;
+class OutputBuffer;
+}
+
+namespace dns {
+
+// BEGIN_COMMON_DECLARATIONS
+
+class AbstractMessageRenderer;
+
+// END_COMMON_DECLARATIONS
+
+namespace rdata {
+namespace in {
+
+/// \brief \c rdata::DHCID class represents the DHCID RDATA as defined %in
+/// RFC4701.
+///
+/// This class implements the basic interfaces inherited from the abstract
+/// \c rdata::Rdata class, and provides trivial accessors specific to the
+/// DHCID RDATA.
+class DHCID : public Rdata {
+public:
+ // BEGIN_COMMON_MEMBERS
+
+ explicit DHCID(const std::string& type_str);
+ DHCID(isc::util::InputBuffer& buffer, size_t rdata_len);
+ DHCID(const DHCID& other);
+ DHCID(
+ MasterLexer& lexer, const Name* name,
+ MasterLoader::Options options, MasterLoaderCallbacks& callbacks);
+ virtual std::string toText() const;
+ virtual void toWire(isc::util::OutputBuffer& buffer) const;
+ virtual void toWire(AbstractMessageRenderer& renderer) const;
+ virtual int compare(const Rdata& other) const;
+
+ // END_COMMON_MEMBERS
+
+ /// \brief Return the digest.
+ ///
+ /// This method never throws an exception.
+ const std::vector<uint8_t>& getDigest() const;
+
+private:
+ // helper for string and lexer constructors
+ void constructFromLexer(MasterLexer& lexer);
+
+ /// \brief Private data representation
+ ///
+ /// Opaque data at least 3 octets long as per RFC4701.
+ ///
+ std::vector<uint8_t> digest_;
+};
+} // end of namespace "in"
+} // end of namespace "rdata"
+} // end of namespace "dns"
+} // end of namespace "isc"
+#endif // IN_DHCID_49_H
+
+// 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 IN_SRV_33_H
+#define IN_SRV_33_H 1
+
+#include <stdint.h>
+
+#include <dns/name.h>
+#include <dns/rdata.h>
+
+namespace isc {
+namespace util {
+
+class InputBuffer;
+class OutputBuffer;
+}
+
+namespace dns {
+
+// BEGIN_COMMON_DECLARATIONS
+
+class AbstractMessageRenderer;
+
+// END_COMMON_DECLARATIONS
+
+namespace rdata {
+namespace in {
+
+struct SRVImpl;
+
+/// \brief \c rdata::SRV class represents the SRV RDATA as defined %in
+/// RFC2782.
+///
+/// This class implements the basic interfaces inherited from the abstract
+/// \c rdata::Rdata class, and provides trivial accessors specific to the
+/// SRV RDATA.
+class SRV : public Rdata {
+public:
+ // BEGIN_COMMON_MEMBERS
+
+ explicit SRV(const std::string& type_str);
+ SRV(isc::util::InputBuffer& buffer, size_t rdata_len);
+ SRV(const SRV& other);
+ SRV(
+ MasterLexer& lexer, const Name* name,
+ MasterLoader::Options options, MasterLoaderCallbacks& callbacks);
+ virtual std::string toText() const;
+ virtual void toWire(isc::util::OutputBuffer& buffer) const;
+ virtual void toWire(AbstractMessageRenderer& renderer) const;
+ virtual int compare(const Rdata& other) const;
+
+ // END_COMMON_MEMBERS
+
+ /// \brief Assignment operator.
+ ///
+ /// It internally allocates a resource, and if it fails a corresponding
+ /// standard exception will be thrown.
+ /// This operator never throws an exception otherwise.
+ ///
+ /// This operator provides the strong exception guarantee: When an
+ /// exception is thrown the content of the assignment target will be
+ /// intact.
+ SRV& operator=(const SRV& source);
+
+ /// \brief The destructor.
+ ~SRV();
+
+ ///
+ /// Specialized methods
+ ///
+
+ /// \brief Return the value of the priority field.
+ ///
+ /// This method never throws an exception.
+ uint16_t getPriority() const;
+
+ /// \brief Return the value of the weight field.
+ ///
+ /// This method never throws an exception.
+ uint16_t getWeight() const;
+
+ /// \brief Return the value of the port field.
+ ///
+ /// This method never throws an exception.
+ uint16_t getPort() const;
+
+ /// \brief Return the value of the target field.
+ ///
+ /// \return A reference to a \c Name class object corresponding to the
+ /// internal target name.
+ ///
+ /// This method never throws an exception.
+ const Name& getTarget() const;
+
+private:
+ SRVImpl* impl_;
+};
+
+} // end of namespace "in"
+} // end of namespace "rdata"
+} // end of namespace "dns"
+} // end of namespace "isc"
+#endif // IN_SRV_33_H
+
+
+#endif // DNS_RDATACLASS_H
+
+// Local Variables:
+// mode: c++
+// End:
--- /dev/null
+///////////////
+///////////////
+/////////////// THIS FILE IS AUTOMATICALLY GENERATED BY gen-rdatacode.py.
+/////////////// DO NOT EDIT!
+///////////////
+///////////////
+
+// 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 RRCLASS_H
+#define RRCLASS_H 1
+
+#include <stdint.h>
+
+#include <string>
+#include <ostream>
+
+#include <dns/exceptions.h>
+
+#include <boost/optional.hpp>
+
+namespace isc {
+namespace util {
+class InputBuffer;
+class OutputBuffer;
+}
+
+namespace dns {
+
+// forward declarations
+class AbstractMessageRenderer;
+
+///
+/// \brief A standard DNS module exception that is thrown if an RRClass object
+/// is being constructed from an unrecognized string.
+///
+class InvalidRRClass : public DNSTextError {
+public:
+ InvalidRRClass(const char* file, size_t line, const char* what) :
+ DNSTextError(file, line, what) {}
+};
+
+///
+/// \brief A standard DNS module exception that is thrown if an RRClass object
+/// is being constructed from a incomplete (too short) wire-format data.
+///
+class IncompleteRRClass : public isc::dns::Exception {
+public:
+ IncompleteRRClass(const char* file, size_t line, const char* what) :
+ isc::dns::Exception(file, line, what) {}
+};
+
+///
+/// The \c RRClass class encapsulates DNS resource record classes.
+///
+/// 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".
+///
+/// This class consults a helper \c RRParamRegistry class, which is a registry
+/// of RR related parameters and has the singleton object. This registry
+/// provides a mapping between RR class codes and their "well-known" textual
+/// representations.
+/// Parameters of RR classes defined by DNS protocol standards are automatically
+/// registered at initialization time and are ensured to be always available for
+/// applications unless the application explicitly modifies the registry.
+///
+/// For convenience, this class defines constant class objects corresponding to
+/// standard RR classes. These are generally referred to as the form of
+/// <code>RRClass::{class-text}()</code>.
+/// For example, \c RRClass::IN() is an \c RRClass object corresponding to the
+/// IN class (class code 1).
+/// Note that these constants are used through a "proxy" function.
+/// This is because they may be used to initialize another non-local (e.g.
+/// global or namespace-scope) static object as follows:
+///
+/// \code
+/// namespace foo {
+/// const RRClass default_class = RRClass::IN();
+/// } \endcode
+///
+/// In order to ensure that the constant RRClass object has been initialized
+/// before the initialization for \c default_class, we need help from
+/// the proxy function.
+///
+/// Note to developers: same note as \c RRType applies.
+class RRClass {
+public:
+ ///
+ /// \name Constructors and Destructor
+ ///
+ //@{
+ /// Constructor from an integer class code.
+ ///
+ /// This constructor never throws an exception.
+ ///
+ /// \param classcode An 16-bit integer code corresponding to the RRClass.
+ explicit RRClass(uint16_t classcode) : classcode_(classcode) {}
+ ///
+ /// A valid string is one of "well-known" textual class representations
+ /// such as "IN" or "CH", or in the standard format for "unknown"
+ /// classes as defined in RFC3597, i.e., "CLASSnnnn".
+ ///
+ /// More precisely, the "well-known" representations are the ones stored
+ /// in the \c RRParamRegistry registry (see the class description).
+ ///
+ /// As for the format of "CLASSnnnn", "nnnn" must represent a valid 16-bit
+ /// unsigned integer, which may contain leading 0's as long as it consists
+ /// of at most 5 characters (inclusive).
+ /// For example, "CLASS1" and "CLASSS001" are valid and represent the same
+ /// class, but "CLASS65536" and "CLASS000001" are invalid.
+ /// A "CLASSnnnn" representation is valid even if the corresponding class
+ /// code is registered in the \c RRParamRegistry object. For example, both
+ /// "IN" and "CLASS1" are valid and represent the same class.
+ ///
+ /// All of these representations are case insensitive; "IN" and "in", and
+ /// "CLASS1" and "class1" are all valid and represent the same classes,
+ /// respectively.
+ ///
+ /// If the given string is not recognized as a valid representation of
+ /// an RR class, an exception of class \c InvalidRRClass will be thrown.
+ ///
+ /// \param class_str A string representation of the \c RRClass
+ explicit RRClass(const std::string& class_str);
+ /// Constructor from wire-format data.
+ ///
+ /// The \c buffer parameter normally stores a complete DNS message
+ /// containing the RRClass to be constructed. The current read position of
+ /// the buffer points to the head of the class.
+ ///
+ /// If the given data does not large enough to contain a 16-bit integer,
+ /// an exception of class \c IncompleteRRClass will be thrown.
+ ///
+ /// \param buffer A buffer storing the wire format data.
+ explicit RRClass(isc::util::InputBuffer& buffer);
+
+ /// A separate factory of RRClass from text.
+ ///
+ /// This static method is similar to the constructor that takes a
+ /// string object, but works as a factory and reports parsing
+ /// failure in the form of the return value. Normally the
+ /// constructor version should suffice, but in some cases the caller
+ /// may have to expect mixture of valid and invalid input, and may
+ /// want to minimize the overhead of possible exception handling.
+ /// This version is provided for such purpose.
+ ///
+ /// For the format of the \c class_str argument, see the
+ /// <code>RRClass(const std::string&)</code> constructor.
+ ///
+ /// If the given text represents a valid RRClass, it returns a
+ /// pointer to a new \c RRClass object. If the given text does not
+ /// represent a valid RRClass, it returns \c NULL.
+ ///
+ /// One main purpose of this function is to minimize the overhead
+ /// when the given text does not represent a valid RR class. For
+ /// this reason this function intentionally omits the capability of
+ /// delivering a detailed reason for the parse failure, such as in the
+ /// \c want() string when exception is thrown from the constructor
+ /// (it will internally require a creation of string object, which
+ /// is relatively expensive). If such detailed information is
+ /// necessary, the constructor version should be used to catch the
+ /// resulting exception.
+ ///
+ /// This function never throws the \c InvalidRRClass exception.
+ ///
+ /// \param class_str A string representation of the \c RRClass.
+ /// \return A new RRClass object for the given text or a \c NULL
+ /// value.
+ static RRClass* createFromText(const std::string& class_str);
+
+ ///
+ /// We use the default copy constructor intentionally.
+ //@}
+ /// We use the default copy assignment operator intentionally.
+ ///
+
+ ///
+ /// \name Converter methods
+ ///
+ //@{
+ /// \brief Convert the \c RRClass to a string.
+ ///
+ /// If a "well known" textual representation for the class code is
+ /// registered in the RR parameter registry (see the class description),
+ /// that will be used as the return value of this method. Otherwise, this
+ /// method creates a new string for an "unknown" class in the format defined
+ /// in RFC3597, i.e., "CLASSnnnn", and returns it.
+ ///
+ /// If resource allocation for the string fails, a corresponding standard
+ /// exception will be thrown.
+ ///
+ /// \return A string representation of the \c RRClass.
+ const std::string toText() const;
+ /// \brief Render the \c RRClass in the wire format.
+ ///
+ /// This method renders the class code in network byte order via
+ /// \c renderer, which encapsulates output buffer and other rendering
+ /// contexts.
+ ///
+ /// If resource allocation in rendering process fails, a corresponding
+ /// standard exception will be thrown.
+ ///
+ /// \param buffer An output buffer to store the wire data.
+ void toWire(AbstractMessageRenderer& renderer) const;
+ /// \brief Render the \c RRClass in the wire format.
+ ///
+ /// This method renders the class code in network byte order into the
+ /// \c buffer.
+ ///
+ /// If resource allocation in rendering process fails, a corresponding
+ /// standard exception will be thrown.
+ ///
+ /// \param renderer DNS message rendering context that encapsulates the
+ /// output buffer in which the RRClass is to be stored.
+ void toWire(isc::util::OutputBuffer& buffer) const;
+ //@}
+
+ ///
+ /// \name Getter Methods
+ ///
+ //@{
+ /// \brief Returns the RR class code as a 16-bit unsigned integer.
+ ///
+ /// This method never throws an exception.
+ ///
+ /// \return An 16-bit integer code corresponding to the RRClass.
+ uint16_t getCode() const { return (classcode_); }
+ //@}
+
+ ///
+ /// \name Comparison methods
+ ///
+ //@{
+ /// \brief Return true iff two RRClasses are equal.
+ ///
+ /// Two RRClasses are equal iff their class codes are equal.
+ ///
+ /// This method never throws an exception.
+ ///
+ /// \param other the \c RRClass object to compare against.
+ /// \return true if the two RRClasses are equal; otherwise false.
+ bool equals(const RRClass& other) const
+ { return (classcode_ == other.classcode_); }
+ /// \brief Same as \c equals().
+ bool operator==(const RRClass& other) const { return (equals(other)); }
+
+ /// \brief Return true iff two RRClasses are not equal.
+ ///
+ /// This method never throws an exception.
+ ///
+ /// \param other the \c RRClass object to compare against.
+ /// \return true if the two RRClasses are not equal; otherwise false.
+ bool nequals(const RRClass& other) const
+ { return (classcode_ != other.classcode_); }
+ /// \brief Same as \c nequals().
+ bool operator!=(const RRClass& other) const { return (nequals(other)); }
+
+ /// \brief Less-than comparison for RRClass against \c other
+ ///
+ /// We define the less-than relationship based on their class codes;
+ /// one RRClass is less than the other iff the code of the former is less
+ /// than that of the other as unsigned integers.
+ /// The relationship is meaningless in terms of DNS protocol; the only
+ /// reason we define this method is that RRClass objects can be stored in
+ /// STL containers without requiring user-defined less-than relationship.
+ /// We therefore don't define other comparison operators.
+ ///
+ /// This method never throws an exception.
+ ///
+ /// \param other the \c RRClass object to compare against.
+ /// \return true if \c this RRClass is less than the \c other; otherwise
+ /// false.
+ bool operator<(const RRClass& other) const
+ { return (classcode_ < other.classcode_); }
+
+ // BEGIN_WELL_KNOWN_CLASS_DECLARATIONS
+ static const RRClass& HS();
+ static const RRClass& NONE();
+ static const RRClass& ANY();
+ static const RRClass& CH();
+ static const RRClass& IN();
+ // END_WELL_KNOWN_CLASS_DECLARATIONS
+
+private:
+ uint16_t classcode_;
+};
+
+// BEGIN_WELL_KNOWN_CLASS_DEFINITIONS
+inline const RRClass&
+RRClass::HS() {
+ static RRClass rrclass(4);
+ return (rrclass);
+}
+
+inline const RRClass&
+RRClass::NONE() {
+ static RRClass rrclass(254);
+ return (rrclass);
+}
+
+inline const RRClass&
+RRClass::ANY() {
+ static RRClass rrclass(255);
+ return (rrclass);
+}
+
+inline const RRClass&
+RRClass::CH() {
+ static RRClass rrclass(3);
+ return (rrclass);
+}
+
+inline const RRClass&
+RRClass::IN() {
+ static RRClass rrclass(1);
+ return (rrclass);
+}
+
+// END_WELL_KNOWN_CLASS_DEFINITIONS
+
+///
+/// \brief Insert the \c RRClass as a string into stream.
+///
+/// This method convert the \c rrclass into a string and inserts it into the
+/// output stream \c os.
+///
+/// This function overloads the global operator<< to behave as described in
+/// ostream::operator<< but applied to \c RRClass objects.
+///
+/// \param os A \c std::ostream object on which the insertion operation is
+/// performed.
+/// \param rrclass The \c RRClass object output by the operation.
+/// \return A reference to the same \c std::ostream object referenced by
+/// parameter \c os after the insertion operation.
+std::ostream&
+operator<<(std::ostream& os, const RRClass& rrclass);
+}
+}
+#endif // RRCLASS_H
+
+// Local Variables:
+// mode: c++
+// End:
--- /dev/null
+///////////////
+///////////////
+/////////////// 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 <cassert>
+#include <algorithm>
+#include <cctype>
+#include <functional>
+#include <map>
+#include <string>
+#include <sstream>
+#include <utility>
+
+#include <stdint.h>
+
+#include <boost/shared_ptr.hpp>
+
+#include <exceptions/exceptions.h>
+
+#include <dns/rrparamregistry.h>
+#include <dns/rrclass.h>
+#include <dns/rrtype.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+
+using namespace std;
+
+using namespace isc::util;
+using namespace isc::dns::rdata;
+
+namespace isc {
+namespace dns {
+
+namespace {
+///
+/// The following function and class are a helper to define case-insensitive
+/// equivalence relationship on strings. They are used in the mapping
+/// containers below.
+///
+bool
+CICharLess(char c1, char c2) {
+ return (tolower(static_cast<unsigned char>(c1)) <
+ tolower(static_cast<unsigned char>(c2)));
+}
+
+struct CIStringLess :
+ public binary_function<string, string, bool>
+{
+ bool operator()(const string& s1, const string& s2) const
+ {
+ return (lexicographical_compare(s1.begin(), s1.end(),
+ s2.begin(), s2.end(), CICharLess));
+ }
+};
+
+struct RRTypeParam {
+ RRTypeParam(const string& code_string, uint16_t code) :
+ code_string_(code_string), code_(code) {}
+ string code_string_;
+ uint16_t code_;
+
+ /// magic constants
+ static const unsigned int MAX_CODE = 0xffff;
+ static const string& UNKNOWN_PREFIX();
+ static size_t UNKNOWN_PREFIXLEN();
+ static const string& UNKNOWN_MAX();
+ static size_t UNKNOWN_MAXLEN();
+};
+
+typedef boost::shared_ptr<RRTypeParam> RRTypeParamPtr;
+typedef map<string, RRTypeParamPtr, CIStringLess> StrRRTypeMap;
+typedef map<uint16_t, RRTypeParamPtr> CodeRRTypeMap;
+
+inline const string&
+RRTypeParam::UNKNOWN_PREFIX() {
+ static const string p("TYPE");
+ return (p);
+}
+
+inline size_t
+RRTypeParam::UNKNOWN_PREFIXLEN() {
+ static size_t plen = UNKNOWN_PREFIX().size();
+ return (plen);
+}
+
+inline const string&
+RRTypeParam::UNKNOWN_MAX() {
+ static const string p("TYPE65535");
+ return (p);
+}
+
+inline size_t
+RRTypeParam::UNKNOWN_MAXLEN() {
+ static size_t plen = UNKNOWN_MAX().size();
+ return (plen);
+}
+
+struct RRClassParam {
+ RRClassParam(const string& code_string, uint16_t code) :
+ code_string_(code_string), code_(code) {}
+ string code_string_;
+ uint16_t code_;
+
+ /// magic constants
+ static const unsigned int MAX_CODE = 0xffff;
+ static const string& UNKNOWN_PREFIX();
+ static size_t UNKNOWN_PREFIXLEN();
+ static const string& UNKNOWN_MAX();
+ static size_t UNKNOWN_MAXLEN();
+};
+
+typedef boost::shared_ptr<RRClassParam> RRClassParamPtr;
+typedef map<string, RRClassParamPtr, CIStringLess> StrRRClassMap;
+typedef map<uint16_t, RRClassParamPtr> CodeRRClassMap;
+
+inline const string&
+RRClassParam::UNKNOWN_PREFIX() {
+ static const string p("CLASS");
+ return (p);
+}
+
+inline size_t
+RRClassParam::UNKNOWN_PREFIXLEN() {
+ static size_t plen = UNKNOWN_PREFIX().size();
+ return (plen);
+}
+
+inline const string&
+RRClassParam::UNKNOWN_MAX() {
+ static const string p("CLASS65535");
+ return (p);
+}
+
+inline size_t
+RRClassParam::UNKNOWN_MAXLEN() {
+ static size_t plen = UNKNOWN_MAX().size();
+ return (plen);
+}
+} // end of anonymous namespace
+
+/// Note: the element ordering in the type/class pair is intentional.
+/// The standard library will perform inequality comparison (i.e, '<')
+/// in the way that the second elements (RRClass) are compared only when
+/// the first elements are equivalent.
+/// In practice, when we compare two pairs of RRType and RRClass, RRClass
+/// would be the same (and, in particular, be class IN) in the majority of
+/// cases. So this comparison ordering should be more efficient in common
+/// cases.
+typedef pair<RRType, RRClass> RRTypeClass;
+typedef map<RRTypeClass, RdataFactoryPtr> RdataFactoryMap;
+typedef map<RRType, RdataFactoryPtr> GenericRdataFactoryMap;
+
+template <typename T>
+class RdataFactory : public AbstractRdataFactory {
+public:
+ virtual RdataPtr create(const string& rdata_str) const
+ {
+ return (RdataPtr(new T(rdata_str)));
+ }
+
+ virtual RdataPtr create(InputBuffer& buffer, size_t rdata_len) const
+ {
+ return (RdataPtr(new T(buffer, rdata_len)));
+ }
+
+ virtual RdataPtr create(const Rdata& source) const
+ {
+ return (RdataPtr(new T(dynamic_cast<const T&>(source))));
+ }
+
+ virtual RdataPtr create(MasterLexer& lexer, const Name* origin,
+ MasterLoader::Options options,
+ MasterLoaderCallbacks& callbacks) const
+ {
+ return (RdataPtr(new T(lexer, origin, options, callbacks)));
+ }
+};
+
+///
+/// \brief The \c RRParamRegistryImpl class is the actual implementation of
+/// \c RRParamRegistry.
+///
+/// The implementation is hidden from applications. We can refer to specific
+/// members of this class only within the implementation source file.
+///
+struct RRParamRegistryImpl {
+ /// Mappings from RR type codes to textual representations.
+ StrRRTypeMap str2typemap;
+ /// Mappings from textual representations of RR types to integer codes.
+ CodeRRTypeMap code2typemap;
+ /// Mappings from RR class codes to textual representations.
+ StrRRClassMap str2classmap;
+ /// Mappings from textual representations of RR classes to integer codes.
+ CodeRRClassMap code2classmap;
+ RdataFactoryMap rdata_factories;
+ GenericRdataFactoryMap genericrdata_factories;
+};
+
+RRParamRegistry::RRParamRegistry() {
+ impl_ = new RRParamRegistryImpl;
+
+ // set up parameters for well-known RRs
+ try {
+ // BEGIN_WELL_KNOWN_PARAMS
+ add("A", 1, "IN", 1, RdataFactoryPtr(new RdataFactory<in::A>()));
+ add("NS", 2, "IN", 1, RdataFactoryPtr(new RdataFactory<generic::NS>()));
+ add("CNAME", 5, "IN", 1, RdataFactoryPtr(new RdataFactory<generic::CNAME>()));
+ add("SOA", 6, "IN", 1, RdataFactoryPtr(new RdataFactory<generic::SOA>()));
+ add("PTR", 12, "IN", 1, RdataFactoryPtr(new RdataFactory<generic::PTR>()));
+ add("HINFO", 13, "IN", 1, RdataFactoryPtr(new RdataFactory<generic::HINFO>()));
+ add("MINFO", 14, "IN", 1, RdataFactoryPtr(new RdataFactory<generic::MINFO>()));
+ add("MX", 15, "IN", 1, RdataFactoryPtr(new RdataFactory<generic::MX>()));
+ add("TXT", 16, "IN", 1, RdataFactoryPtr(new RdataFactory<generic::TXT>()));
+ add("RP", 17, "IN", 1, RdataFactoryPtr(new RdataFactory<generic::RP>()));
+ add("AFSDB", 18, "IN", 1, RdataFactoryPtr(new RdataFactory<generic::AFSDB>()));
+ add("AAAA", 28, "IN", 1, RdataFactoryPtr(new RdataFactory<in::AAAA>()));
+ add("SRV", 33, "IN", 1, RdataFactoryPtr(new RdataFactory<in::SRV>()));
+ add("NAPTR", 35, "IN", 1, RdataFactoryPtr(new RdataFactory<generic::NAPTR>()));
+ add("DNAME", 39, "IN", 1, RdataFactoryPtr(new RdataFactory<generic::DNAME>()));
+ add("OPT", 41, "IN", 1, RdataFactoryPtr(new RdataFactory<generic::OPT>()));
+ add("DS", 43, "IN", 1, RdataFactoryPtr(new RdataFactory<generic::DS>()));
+ add("SSHFP", 44, "IN", 1, RdataFactoryPtr(new RdataFactory<generic::SSHFP>()));
+ add("RRSIG", 46, "IN", 1, RdataFactoryPtr(new RdataFactory<generic::RRSIG>()));
+ add("NSEC", 47, "IN", 1, RdataFactoryPtr(new RdataFactory<generic::NSEC>()));
+ add("DNSKEY", 48, "IN", 1, RdataFactoryPtr(new RdataFactory<generic::DNSKEY>()));
+ add("DHCID", 49, "IN", 1, RdataFactoryPtr(new RdataFactory<in::DHCID>()));
+ add("NSEC3", 50, "IN", 1, RdataFactoryPtr(new RdataFactory<generic::NSEC3>()));
+ add("NSEC3PARAM", 51, "IN", 1, RdataFactoryPtr(new RdataFactory<generic::NSEC3PARAM>()));
+ add("TLSA", 52, "IN", 1, RdataFactoryPtr(new RdataFactory<generic::TLSA>()));
+ add("SPF", 99, "IN", 1, RdataFactoryPtr(new RdataFactory<generic::SPF>()));
+ add("CAA", 257, "IN", 1, RdataFactoryPtr(new RdataFactory<generic::CAA>()));
+ add("DLV", 32769, "IN", 1, RdataFactoryPtr(new RdataFactory<generic::DLV>()));
+ add("A", 1, "CH", 3, RdataFactoryPtr(new RdataFactory<ch::A>()));
+ add("A", 1, "HS", 4, RdataFactoryPtr(new RdataFactory<hs::A>()));
+ add("TSIG", 250, "ANY", 255, RdataFactoryPtr(new RdataFactory<any::TSIG>()));
+ add("NS", 2, RdataFactoryPtr(new RdataFactory<generic::NS>()));
+ add("CNAME", 5, RdataFactoryPtr(new RdataFactory<generic::CNAME>()));
+ add("SOA", 6, RdataFactoryPtr(new RdataFactory<generic::SOA>()));
+ add("PTR", 12, RdataFactoryPtr(new RdataFactory<generic::PTR>()));
+ add("HINFO", 13, RdataFactoryPtr(new RdataFactory<generic::HINFO>()));
+ add("MINFO", 14, RdataFactoryPtr(new RdataFactory<generic::MINFO>()));
+ add("MX", 15, RdataFactoryPtr(new RdataFactory<generic::MX>()));
+ add("TXT", 16, RdataFactoryPtr(new RdataFactory<generic::TXT>()));
+ add("RP", 17, RdataFactoryPtr(new RdataFactory<generic::RP>()));
+ add("AFSDB", 18, RdataFactoryPtr(new RdataFactory<generic::AFSDB>()));
+ add("NAPTR", 35, RdataFactoryPtr(new RdataFactory<generic::NAPTR>()));
+ add("DNAME", 39, RdataFactoryPtr(new RdataFactory<generic::DNAME>()));
+ add("OPT", 41, RdataFactoryPtr(new RdataFactory<generic::OPT>()));
+ add("DS", 43, RdataFactoryPtr(new RdataFactory<generic::DS>()));
+ add("SSHFP", 44, RdataFactoryPtr(new RdataFactory<generic::SSHFP>()));
+ add("RRSIG", 46, RdataFactoryPtr(new RdataFactory<generic::RRSIG>()));
+ add("NSEC", 47, RdataFactoryPtr(new RdataFactory<generic::NSEC>()));
+ add("DNSKEY", 48, RdataFactoryPtr(new RdataFactory<generic::DNSKEY>()));
+ add("NSEC3", 50, RdataFactoryPtr(new RdataFactory<generic::NSEC3>()));
+ add("NSEC3PARAM", 51, RdataFactoryPtr(new RdataFactory<generic::NSEC3PARAM>()));
+ add("TLSA", 52, RdataFactoryPtr(new RdataFactory<generic::TLSA>()));
+ add("SPF", 99, RdataFactoryPtr(new RdataFactory<generic::SPF>()));
+ add("CAA", 257, RdataFactoryPtr(new RdataFactory<generic::CAA>()));
+ add("DLV", 32769, RdataFactoryPtr(new RdataFactory<generic::DLV>()));
+ // Meta and non-implemented RR types
+ addType("IPSECKEY", 45);
+ addType("L32", 105);
+ addType("NID", 104);
+ addType("LP", 107);
+ addType("L64", 106);
+ addType("KX", 36);
+ addType("UNSPEC", 103);
+ addType("MAILA", 254);
+ addType("MAILB", 253);
+ addType("HIP", 55);
+ addType("LOC", 29);
+ addType("URI", 256);
+ addType("APL", 42);
+ addType("GPOS", 27);
+ addType("TKEY", 249);
+ addType("MG", 8);
+ addType("MR", 9);
+ addType("IXFR", 251);
+ addType("MB", 7);
+ addType("MF", 4);
+ addType("AXFR", 252);
+ addType("ANY", 255);
+ addType("MD", 3);
+ addType("CERT", 37);
+ addType("KEY", 25);
+ addType("SIG", 24);
+ addType("A6", 38);
+ addType("PX", 26);
+ addType("RT", 21);
+ addType("X25", 19);
+ addType("NSAP-PTR", 23);
+ addType("NSAP", 22);
+ addType("NXT", 30);
+ addType("NULL", 10);
+ addType("WKS", 11);
+ addType("ISDN", 20);
+ // Meta classes
+ addClass("NONE", 254);
+ // END_WELL_KNOWN_PARAMS
+ } catch (...) {
+ delete impl_;
+ throw;
+ }
+}
+
+RRParamRegistry::~RRParamRegistry() {
+ delete impl_;
+}
+
+RRParamRegistry&
+RRParamRegistry::getRegistry() {
+ static RRParamRegistry registry;
+
+ return (registry);
+}
+
+void
+RRParamRegistry::add(const std::string& typecode_string, uint16_t typecode,
+ RdataFactoryPtr rdata_factory)
+{
+ bool type_added = false;
+ try {
+ type_added = addType(typecode_string, typecode);
+ impl_->genericrdata_factories.insert(pair<RRType, RdataFactoryPtr>(
+ RRType(typecode),
+ rdata_factory));
+ } catch (...) {
+ if (type_added) {
+ removeType(typecode);
+ }
+ throw;
+ }
+}
+
+void
+RRParamRegistry::add(const std::string& typecode_string, uint16_t typecode,
+ const std::string& classcode_string, uint16_t classcode,
+ RdataFactoryPtr rdata_factory)
+{
+ // Rollback logic on failure is complicated. If adding the new type or
+ // class fails, we should revert to the original state, cleaning up
+ // intermediate state. But we need to make sure that we don't remove
+ // existing data. addType()/addClass() will simply ignore an attempt to
+ // add the same data, so the cleanup should be performed only when we add
+ // something new but we fail in other part of the process.
+ bool type_added = false;
+ bool class_added = false;
+
+ try {
+ type_added = addType(typecode_string, typecode);
+ class_added = addClass(classcode_string, classcode);
+ impl_->rdata_factories.insert(pair<RRTypeClass, RdataFactoryPtr>(
+ RRTypeClass(RRType(typecode),
+ RRClass(classcode)),
+ rdata_factory));
+ } catch (...) {
+ if (type_added) {
+ removeType(typecode);
+ }
+ if (class_added) {
+ removeClass(classcode);
+ }
+ throw;
+ }
+}
+
+bool
+RRParamRegistry::removeRdataFactory(const RRType& rrtype,
+ const RRClass& rrclass)
+{
+ RdataFactoryMap::iterator found =
+ impl_->rdata_factories.find(RRTypeClass(rrtype, rrclass));
+ if (found != impl_->rdata_factories.end()) {
+ impl_->rdata_factories.erase(found);
+ return (true);
+ }
+
+ return (false);
+}
+
+bool
+RRParamRegistry::removeRdataFactory(const RRType& rrtype) {
+ GenericRdataFactoryMap::iterator found =
+ impl_->genericrdata_factories.find(rrtype);
+ if (found != impl_->genericrdata_factories.end()) {
+ impl_->genericrdata_factories.erase(found);
+ return (true);
+ }
+
+ return (false);
+}
+
+namespace {
+///
+/// These are helper functions to implement case-insensitive string comparison.
+/// This could be simplified using strncasecmp(), but unfortunately it's not
+/// included in <cstring>. To be as much as portable within the C++ standard
+/// we take the "in house" approach here.
+///
+bool CICharEqual(char c1, char c2) {
+ return (tolower(static_cast<unsigned char>(c1)) ==
+ tolower(static_cast<unsigned char>(c2)));
+}
+
+bool
+caseStringEqual(const string& s1, const string& s2, size_t n) {
+ assert(s1.size() >= n && s2.size() >= n);
+
+ return (mismatch(s1.begin(), s1.begin() + n, s2.begin(), CICharEqual).first
+ == s1.begin() + n);
+}
+
+/// Code logic for RRTypes and RRClasses is mostly common except (C++) type and
+/// member names. So we define type-independent templates to describe the
+/// common logic and let concrete classes use it to avoid code duplicates.
+/// The following summarize template parameters used in the set of template
+/// functions:
+/// PT: parameter type, either RRTypeParam or RRClassParam
+/// MC: type of mapping class from code: either CodeRRTypeMap or CodeRRClassMap
+/// MS: type of mapping class from string: either StrRRTypeMap or StrRRClassMap
+/// ET: exception type for error handling: either InvalidRRType or
+/// InvalidRRClass
+template <typename PT, typename MC, typename MS, typename ET>
+inline bool
+addParam(const string& code_string, uint16_t code, MC& codemap, MS& stringmap)
+{
+ // Duplicate type check
+ typename MC::const_iterator found = codemap.find(code);
+ if (found != codemap.end()) {
+ if (found->second->code_string_ != code_string) {
+ isc_throw(ET, "Duplicate RR parameter registration");
+ }
+ return (false);
+ }
+
+ typedef boost::shared_ptr<PT> ParamPtr;
+ typedef pair<string, ParamPtr> StrParamPair;
+ typedef pair<uint16_t, ParamPtr> CodeParamPair;
+ ParamPtr param = ParamPtr(new PT(code_string, code));
+ try {
+ stringmap.insert(StrParamPair(code_string, param));
+ codemap.insert(CodeParamPair(code, param));
+ } catch (...) {
+ // Rollback to the previous state: not all of the erase operations will
+ // find the entry, but we don't care.
+ stringmap.erase(code_string);
+ codemap.erase(code);
+ throw;
+ }
+
+ return (true);
+}
+
+template <typename MC, typename MS>
+inline bool
+removeParam(uint16_t code, MC& codemap, MS& stringmap) {
+ typename MC::iterator found = codemap.find(code);
+
+ if (found != codemap.end()) {
+ size_t erased = stringmap.erase(found->second->code_string_);
+ // We must have a corresponding entry of the str2 map exists
+ assert(erased == 1);
+
+ codemap.erase(found);
+
+ return (true);
+ }
+
+ return (false);
+}
+
+template <typename PT, typename MS>
+inline bool
+textToCode(const string& code_str, MS& stringmap, uint16_t& ret_code) {
+ typename MS::const_iterator found;
+
+ found = stringmap.find(code_str);
+ if (found != stringmap.end()) {
+ ret_code = found->second->code_;
+ return (true);
+ }
+
+ size_t l = code_str.size();
+ if (l > PT::UNKNOWN_PREFIXLEN() &&
+ l <= PT::UNKNOWN_MAXLEN() &&
+ caseStringEqual(code_str, PT::UNKNOWN_PREFIX(),
+ PT::UNKNOWN_PREFIXLEN())) {
+ unsigned int code;
+ istringstream iss(code_str.substr(PT::UNKNOWN_PREFIXLEN(),
+ l - PT::UNKNOWN_PREFIXLEN()));
+ iss >> dec >> code;
+ if (iss.rdstate() == ios::eofbit && code <= PT::MAX_CODE) {
+ ret_code = code;
+ return (true);
+ }
+ }
+
+ return (false);
+}
+
+template <typename PT, typename MC>
+inline string
+codeToText(uint16_t code, MC& codemap) {
+ typename MC::const_iterator found;
+
+ found = codemap.find(code);
+ if (found != codemap.end()) {
+ return (found->second->code_string_);
+ }
+
+ ostringstream ss;
+ ss << code;
+ return (PT::UNKNOWN_PREFIX() + ss.str());
+}
+}
+
+bool
+RRParamRegistry::addType(const string& type_string, uint16_t code) {
+ return (addParam<RRTypeParam, CodeRRTypeMap, StrRRTypeMap, RRTypeExists>
+ (type_string, code, impl_->code2typemap, impl_->str2typemap));
+}
+
+bool
+RRParamRegistry::removeType(uint16_t code) {
+ return (removeParam<CodeRRTypeMap, StrRRTypeMap>(code, impl_->code2typemap,
+ impl_->str2typemap));
+}
+
+bool
+RRParamRegistry::textToTypeCode(const string& type_string,
+ uint16_t& type_code) const
+{
+ return (textToCode<RRTypeParam, StrRRTypeMap>
+ (type_string, impl_->str2typemap, type_code));
+}
+
+string
+RRParamRegistry::codeToTypeText(uint16_t code) const {
+ return (codeToText<RRTypeParam, CodeRRTypeMap>(code, impl_->code2typemap));
+}
+
+bool
+RRParamRegistry::addClass(const string& class_string, uint16_t code) {
+ return (addParam<RRClassParam, CodeRRClassMap, StrRRClassMap, RRClassExists>
+ (class_string, code, impl_->code2classmap, impl_->str2classmap));
+}
+
+bool
+RRParamRegistry::removeClass(uint16_t code) {
+ return (removeParam<CodeRRClassMap, StrRRClassMap>(code,
+ impl_->code2classmap,
+ impl_->str2classmap));
+}
+
+bool
+RRParamRegistry::textToClassCode(const string& class_string,
+ uint16_t& class_code) const
+{
+ return (textToCode<RRClassParam, StrRRClassMap>
+ (class_string, impl_->str2classmap, class_code));
+}
+
+string
+RRParamRegistry::codeToClassText(uint16_t code) const {
+ return (codeToText<RRClassParam, CodeRRClassMap>(code,
+ impl_->code2classmap));
+}
+
+namespace {
+inline const AbstractRdataFactory*
+findRdataFactory(RRParamRegistryImpl* reg_impl,
+ const RRType& rrtype, const RRClass& rrclass)
+{
+ RdataFactoryMap::const_iterator found;
+ found = reg_impl->rdata_factories.find(RRTypeClass(rrtype, rrclass));
+ if (found != reg_impl->rdata_factories.end()) {
+ return (found->second.get());
+ }
+
+ GenericRdataFactoryMap::const_iterator genfound =
+ reg_impl->genericrdata_factories.find(rrtype);
+ if (genfound != reg_impl->genericrdata_factories.end()) {
+ return (genfound->second.get());
+ }
+
+ return (NULL);
+}
+}
+
+RdataPtr
+RRParamRegistry::createRdata(const RRType& rrtype, const RRClass& rrclass,
+ const std::string& rdata_string)
+{
+ // If the text indicates that it's rdata of an "unknown" type (beginning
+ // with '\# n'), parse it that way. (TBD)
+
+ const AbstractRdataFactory* factory =
+ findRdataFactory(impl_, rrtype, rrclass);
+ if (factory != NULL) {
+ return (factory->create(rdata_string));
+ }
+
+ return (RdataPtr(new generic::Generic(rdata_string)));
+}
+
+RdataPtr
+RRParamRegistry::createRdata(const RRType& rrtype, const RRClass& rrclass,
+ InputBuffer& buffer, size_t rdata_len)
+{
+ const AbstractRdataFactory* factory =
+ findRdataFactory(impl_, rrtype, rrclass);
+ if (factory != NULL) {
+ return (factory->create(buffer, rdata_len));
+ }
+
+ return (RdataPtr(new generic::Generic(buffer, rdata_len)));
+}
+
+RdataPtr
+RRParamRegistry::createRdata(const RRType& rrtype, const RRClass& rrclass,
+ const Rdata& source)
+{
+ const AbstractRdataFactory* factory =
+ findRdataFactory(impl_, rrtype, rrclass);
+ if (factory != NULL) {
+ return (factory->create(source));
+ }
+
+ return (RdataPtr(new rdata::generic::Generic(
+ dynamic_cast<const generic::Generic&>(source))));
+}
+
+RdataPtr
+RRParamRegistry::createRdata(const RRType& rrtype, const RRClass& rrclass,
+ MasterLexer& lexer, const Name* name,
+ MasterLoader::Options options,
+ MasterLoaderCallbacks& callbacks)
+{
+ const AbstractRdataFactory* factory =
+ findRdataFactory(impl_, rrtype, rrclass);
+ if (factory != NULL) {
+ return (factory->create(lexer, name, options, callbacks));
+ }
+
+ return (RdataPtr(new generic::Generic(lexer, name, options, callbacks)));
+}
+}
+}
--- /dev/null
+///////////////
+///////////////
+/////////////// THIS FILE IS AUTOMATICALLY GENERATED BY gen-rdatacode.py.
+/////////////// DO NOT EDIT!
+///////////////
+///////////////
+
+// 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 RRTYPE_H
+#define RRTYPE_H 1
+
+#include <stdint.h>
+
+#include <string>
+#include <ostream>
+
+#include <dns/exceptions.h>
+
+// Solaris x86 defines DS in <sys/regset.h>, which gets pulled in by Boost
+#if defined(__sun) && defined(DS)
+# undef DS
+#endif
+
+namespace isc {
+namespace util {
+class InputBuffer;
+class OutputBuffer;
+}
+
+namespace dns {
+
+// forward declarations
+class AbstractMessageRenderer;
+
+///
+/// \brief A standard DNS module exception that is thrown if an RRType object
+/// is being constructed from an unrecognized string.
+///
+class InvalidRRType : public DNSTextError {
+public:
+ InvalidRRType(const char* file, size_t line, const char* what) :
+ DNSTextError(file, line, what) {}
+};
+
+///
+/// \brief A standard DNS module exception that is thrown if an RRType object
+/// is being constructed from a incomplete (too short) wire-format data.
+///
+class IncompleteRRType : public isc::dns::Exception {
+public:
+ IncompleteRRType(const char* file, size_t line, const char* what) :
+ isc::dns::Exception(file, line, what) {}
+};
+
+///
+/// The \c RRType class encapsulates DNS resource record types.
+///
+/// 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".
+///
+/// This class consults a helper \c RRParamRegistry class, which is a registry
+/// of RR related parameters and has the singleton object. This registry
+/// provides a mapping between RR type codes and their "well-known" textual
+/// representations.
+/// Parameters of RR types defined by DNS protocol standards are automatically
+/// registered at initialization time and are ensured to be always available for
+/// applications unless the application explicitly modifies the registry.
+///
+/// For convenience, this class defines constant class objects corresponding to
+/// standard RR types. These are generally referred to as the form of
+/// <code>RRType::{type-text}()</code>.
+/// For example, \c RRType::NS() is an \c RRType object corresponding to the NS
+/// resource record (type code 2).
+/// Note that these constants are used through a "proxy" function.
+/// This is because they may be used to initialize another non-local (e.g.
+/// global or namespace-scope) static object as follows:
+///
+/// \code
+/// namespace foo {
+/// const RRType default_type = RRType::A();
+/// } \endcode
+///
+/// In order to ensure that the constant RRType object has been initialized
+/// before the initialization for \c default_type, we need help from
+/// the proxy function.
+///
+/// In the current implementation, the initialization of the well-known
+/// static objects is not thread safe. The same consideration as the
+/// \c RRParamRegistry class applies. We may extend the implementation so
+/// that the initialization is ensured to be thread safe in a future version.
+///
+/// Note to developers: since it's expected that some of these constant
+/// \c RRType objects are frequently used in a performance sensitive path,
+/// we define these proxy functions as inline. This makes sense only when
+/// the corresponding static objects are defined only once even if they used
+/// in different source files. Sufficiently modern compilers should meet
+/// this assumption, but if we encounter memory bloat due to this problem with
+/// particular compilers we need to revisit the design or think about
+/// workaround.
+class RRType {
+public:
+ ///
+ /// \name Constructors and Destructor
+ ///
+ //@{
+ /// Constructor from an integer type code.
+ ///
+ /// This constructor never throws an exception.
+ ///
+ /// \param typecode An 16-bit integer code corresponding to the RRType.
+ explicit RRType(uint16_t typecode) : typecode_(typecode) {}
+ /// Constructor from a string.
+ ///
+ /// A valid string is one of "well-known" textual type representations
+ /// such as "A", "AAAA", or "NS", or in the standard format for "unknown"
+ /// RR types as defined in RFC3597, i.e., "TYPEnnnn".
+ ///
+ /// More precisely, the "well-known" representations are the ones stored
+ /// in the \c RRParamRegistry registry (see the class description).
+ ///
+ /// As for the format of "TYPEnnnn", "nnnn" must represent a valid 16-bit
+ /// unsigned integer, which may contain leading 0's as long as it consists
+ /// of at most 5 characters (inclusive).
+ /// For example, "TYPE1" and "TYPE001" are valid and represent the same
+ /// RR type, but "TYPE65536" and "TYPE000001" are invalid.
+ /// A "TYPEnnnn" representation is valid even if the corresponding type code
+ /// is registered in the \c RRParamRegistry object. For example, both
+ /// "A" and "TYPE1" are valid and represent the same RR type.
+ ///
+ /// All of these representations are case insensitive; "NS" and "ns", and
+ /// "TYPE1" and "type1" are all valid and represent the same RR types,
+ /// respectively.
+ ///
+ /// If the given string is not recognized as a valid representation of
+ /// an RR type, an exception of class \c InvalidRRType will be thrown.
+ ///
+ /// \param typestr A string representation of the \c RRType
+ explicit RRType(const std::string& typestr);
+ /// Constructor from wire-format data.
+ ///
+ /// The \c buffer parameter normally stores a complete DNS message
+ /// containing the RRType to be constructed. The current read position of
+ /// the buffer points to the head of the type.
+ ///
+ /// If the given data does not large enough to contain a 16-bit integer,
+ /// an exception of class \c IncompleteRRType will be thrown.
+ ///
+ /// \param buffer A buffer storing the wire format data.
+ explicit RRType(isc::util::InputBuffer& buffer);
+ ///
+ /// We use the default copy constructor intentionally.
+ //@}
+ /// We use the default copy assignment operator intentionally.
+ ///
+
+ ///
+ /// \name Converter methods
+ ///
+ //@{
+ /// \brief Convert the \c RRType to a string.
+ ///
+ /// If a "well known" textual representation for the type code is registered
+ /// in the RR parameter registry (see the class description), that will be
+ /// used as the return value of this method. Otherwise, this method creates
+ /// a new string for an "unknown" RR type in the format defined in RFC3597,
+ /// i.e., "TYPEnnnn", and returns it.
+ ///
+ /// If resource allocation for the string fails, a corresponding standard
+ /// exception will be thrown.
+ ///
+ /// \return A string representation of the \c RRType.
+ const std::string toText() const;
+ /// \brief Render the \c RRType in the wire format.
+ ///
+ /// This method renders the type code in network byte order via \c renderer,
+ /// which encapsulates output buffer and other rendering contexts.
+ ///
+ /// If resource allocation in rendering process fails, a corresponding
+ /// standard exception will be thrown.
+ ///
+ /// \param buffer An output buffer to store the wire data.
+ void toWire(AbstractMessageRenderer& renderer) const;
+ /// \brief Render the \c RRType in the wire format.
+ ///
+ /// This method renders the type code in network byte order into the
+ /// \c buffer.
+ ///
+ /// If resource allocation in rendering process fails, a corresponding
+ /// standard exception will be thrown.
+ ///
+ /// \param renderer DNS message rendering context that encapsulates the
+ /// output buffer in which the RRType is to be stored.
+ void toWire(isc::util::OutputBuffer& buffer) const;
+ //@}
+
+ ///
+ /// \name Getter Methods
+ ///
+ //@{
+ /// \brief Returns the RR type code as a 16-bit unsigned integer.
+ ///
+ /// This method never throws an exception.
+ ///
+ /// \return An 16-bit integer code corresponding to the RRType.
+ uint16_t getCode() const { return (typecode_); }
+ //@}
+
+ ///
+ /// \name Comparison methods
+ ///
+ //@{
+ /// \brief Return true iff two RRTypes are equal.
+ ///
+ /// Two RRTypes are equal iff their type codes are equal.
+ ///
+ /// This method never throws an exception.
+ ///
+ /// \param other the \c RRType object to compare against.
+ /// \return true if the two RRTypes are equal; otherwise false.
+ bool equals(const RRType& other) const
+ { return (typecode_ == other.typecode_); }
+ /// \brief Same as \c equals().
+ bool operator==(const RRType& other) const { return (equals(other)); }
+
+ /// \brief Return true iff two RRTypes are not equal.
+ ///
+ /// This method never throws an exception.
+ ///
+ /// \param other the \c RRType object to compare against.
+ /// \return true if the two RRTypes are not equal; otherwise false.
+ bool nequals(const RRType& other) const
+ { return (typecode_ != other.typecode_); }
+ /// \brief Same as \c nequals().
+ bool operator!=(const RRType& other) const { return (nequals(other)); }
+
+ /// \brief Less-than comparison for RRType against \c other
+ ///
+ /// We define the less-than relationship based on their type codes;
+ /// one RRType is less than the other iff the code of the former is less
+ /// than that of the other as unsigned integers.
+ /// The relationship is meaningless in terms of DNS protocol; the only
+ /// reason we define this method is that RRType objects can be stored in
+ /// STL containers without requiring user-defined less-than relationship.
+ /// We therefore don't define other comparison operators.
+ ///
+ /// This method never throws an exception.
+ ///
+ /// \param other the \c RRType object to compare against.
+ /// \return true if \c this RRType is less than the \c other; otherwise
+ /// false.
+ bool operator<(const RRType& other) const
+ { return (typecode_ < other.typecode_); }
+ //@}
+
+ // BEGIN_WELL_KNOWN_TYPE_DECLARATIONS
+ static const RRType& L32();
+ static const RRType& NID();
+ static const RRType& LP();
+ static const RRType& L64();
+ static const RRType& UNSPEC();
+ static const RRType& IXFR();
+ static const RRType& TSIG();
+ static const RRType& MAILB();
+ static const RRType& AXFR();
+ static const RRType& ANY();
+ static const RRType& MAILA();
+ static const RRType& CAA();
+ static const RRType& URI();
+ static const RRType& KEY();
+ static const RRType& SIG();
+ static const RRType& GPOS();
+ static const RRType& PX();
+ static const RRType& RT();
+ static const RRType& ISDN();
+ static const RRType& NSAP_PTR();
+ static const RRType& NSAP();
+ static const RRType& LOC();
+ static const RRType& AAAA();
+ static const RRType& SPF();
+ static const RRType& MG();
+ static const RRType& SOA();
+ static const RRType& MF();
+ static const RRType& NS();
+ static const RRType& NSEC3();
+ static const RRType& NSEC3PARAM();
+ static const RRType& TLSA();
+ static const RRType& AFSDB();
+ static const RRType& HIP();
+ static const RRType& MINFO();
+ static const RRType& MX();
+ static const RRType& TXT();
+ static const RRType& RP();
+ static const RRType& Null();
+ static const RRType& WKS();
+ static const RRType& PTR();
+ static const RRType& HINFO();
+ static const RRType& DLV();
+ static const RRType& DS();
+ static const RRType& APL();
+ static const RRType& OPT();
+ static const RRType& NSEC();
+ static const RRType& RRSIG();
+ static const RRType& IPSECKEY();
+ static const RRType& SSHFP();
+ static const RRType& DHCID();
+ static const RRType& DNSKEY();
+ static const RRType& X25();
+ static const RRType& TKEY();
+ static const RRType& MR();
+ static const RRType& MB();
+ static const RRType& CNAME();
+ static const RRType& MD();
+ static const RRType& A();
+ static const RRType& A6();
+ static const RRType& DNAME();
+ static const RRType& SRV();
+ static const RRType& NXT();
+ static const RRType& KX();
+ static const RRType& CERT();
+ static const RRType& NAPTR();
+ // END_WELL_KNOWN_TYPE_DECLARATIONS
+
+private:
+ uint16_t typecode_;
+};
+
+// BEGIN_WELL_KNOWN_TYPE_DEFINITIONS
+inline const RRType&
+RRType::L32() {
+ static RRType rrtype(105);
+ return (rrtype);
+}
+
+inline const RRType&
+RRType::NID() {
+ static RRType rrtype(104);
+ return (rrtype);
+}
+
+inline const RRType&
+RRType::LP() {
+ static RRType rrtype(107);
+ return (rrtype);
+}
+
+inline const RRType&
+RRType::L64() {
+ static RRType rrtype(106);
+ return (rrtype);
+}
+
+inline const RRType&
+RRType::UNSPEC() {
+ static RRType rrtype(103);
+ return (rrtype);
+}
+
+inline const RRType&
+RRType::IXFR() {
+ static RRType rrtype(251);
+ return (rrtype);
+}
+
+inline const RRType&
+RRType::TSIG() {
+ static RRType rrtype(250);
+ return (rrtype);
+}
+
+inline const RRType&
+RRType::MAILB() {
+ static RRType rrtype(253);
+ return (rrtype);
+}
+
+inline const RRType&
+RRType::AXFR() {
+ static RRType rrtype(252);
+ return (rrtype);
+}
+
+inline const RRType&
+RRType::ANY() {
+ static RRType rrtype(255);
+ return (rrtype);
+}
+
+inline const RRType&
+RRType::MAILA() {
+ static RRType rrtype(254);
+ return (rrtype);
+}
+
+inline const RRType&
+RRType::CAA() {
+ static RRType rrtype(257);
+ return (rrtype);
+}
+
+inline const RRType&
+RRType::URI() {
+ static RRType rrtype(256);
+ return (rrtype);
+}
+
+inline const RRType&
+RRType::KEY() {
+ static RRType rrtype(25);
+ return (rrtype);
+}
+
+inline const RRType&
+RRType::SIG() {
+ static RRType rrtype(24);
+ return (rrtype);
+}
+
+inline const RRType&
+RRType::GPOS() {
+ static RRType rrtype(27);
+ return (rrtype);
+}
+
+inline const RRType&
+RRType::PX() {
+ static RRType rrtype(26);
+ return (rrtype);
+}
+
+inline const RRType&
+RRType::RT() {
+ static RRType rrtype(21);
+ return (rrtype);
+}
+
+inline const RRType&
+RRType::ISDN() {
+ static RRType rrtype(20);
+ return (rrtype);
+}
+
+inline const RRType&
+RRType::NSAP_PTR() {
+ static RRType rrtype(23);
+ return (rrtype);
+}
+
+inline const RRType&
+RRType::NSAP() {
+ static RRType rrtype(22);
+ return (rrtype);
+}
+
+inline const RRType&
+RRType::LOC() {
+ static RRType rrtype(29);
+ return (rrtype);
+}
+
+inline const RRType&
+RRType::AAAA() {
+ static RRType rrtype(28);
+ return (rrtype);
+}
+
+inline const RRType&
+RRType::SPF() {
+ static RRType rrtype(99);
+ return (rrtype);
+}
+
+inline const RRType&
+RRType::MG() {
+ static RRType rrtype(8);
+ return (rrtype);
+}
+
+inline const RRType&
+RRType::SOA() {
+ static RRType rrtype(6);
+ return (rrtype);
+}
+
+inline const RRType&
+RRType::MF() {
+ static RRType rrtype(4);
+ return (rrtype);
+}
+
+inline const RRType&
+RRType::NS() {
+ static RRType rrtype(2);
+ return (rrtype);
+}
+
+inline const RRType&
+RRType::NSEC3() {
+ static RRType rrtype(50);
+ return (rrtype);
+}
+
+inline const RRType&
+RRType::NSEC3PARAM() {
+ static RRType rrtype(51);
+ return (rrtype);
+}
+
+inline const RRType&
+RRType::TLSA() {
+ static RRType rrtype(52);
+ return (rrtype);
+}
+
+inline const RRType&
+RRType::AFSDB() {
+ static RRType rrtype(18);
+ return (rrtype);
+}
+
+inline const RRType&
+RRType::HIP() {
+ static RRType rrtype(55);
+ return (rrtype);
+}
+
+inline const RRType&
+RRType::MINFO() {
+ static RRType rrtype(14);
+ return (rrtype);
+}
+
+inline const RRType&
+RRType::MX() {
+ static RRType rrtype(15);
+ return (rrtype);
+}
+
+inline const RRType&
+RRType::TXT() {
+ static RRType rrtype(16);
+ return (rrtype);
+}
+
+inline const RRType&
+RRType::RP() {
+ static RRType rrtype(17);
+ return (rrtype);
+}
+
+inline const RRType&
+RRType::Null() {
+ static RRType rrtype(10);
+ return (rrtype);
+}
+
+inline const RRType&
+RRType::WKS() {
+ static RRType rrtype(11);
+ return (rrtype);
+}
+
+inline const RRType&
+RRType::PTR() {
+ static RRType rrtype(12);
+ return (rrtype);
+}
+
+inline const RRType&
+RRType::HINFO() {
+ static RRType rrtype(13);
+ return (rrtype);
+}
+
+inline const RRType&
+RRType::DLV() {
+ static RRType rrtype(32769);
+ return (rrtype);
+}
+
+inline const RRType&
+RRType::DS() {
+ static RRType rrtype(43);
+ return (rrtype);
+}
+
+inline const RRType&
+RRType::APL() {
+ static RRType rrtype(42);
+ return (rrtype);
+}
+
+inline const RRType&
+RRType::OPT() {
+ static RRType rrtype(41);
+ return (rrtype);
+}
+
+inline const RRType&
+RRType::NSEC() {
+ static RRType rrtype(47);
+ return (rrtype);
+}
+
+inline const RRType&
+RRType::RRSIG() {
+ static RRType rrtype(46);
+ return (rrtype);
+}
+
+inline const RRType&
+RRType::IPSECKEY() {
+ static RRType rrtype(45);
+ return (rrtype);
+}
+
+inline const RRType&
+RRType::SSHFP() {
+ static RRType rrtype(44);
+ return (rrtype);
+}
+
+inline const RRType&
+RRType::DHCID() {
+ static RRType rrtype(49);
+ return (rrtype);
+}
+
+inline const RRType&
+RRType::DNSKEY() {
+ static RRType rrtype(48);
+ return (rrtype);
+}
+
+inline const RRType&
+RRType::X25() {
+ static RRType rrtype(19);
+ return (rrtype);
+}
+
+inline const RRType&
+RRType::TKEY() {
+ static RRType rrtype(249);
+ return (rrtype);
+}
+
+inline const RRType&
+RRType::MR() {
+ static RRType rrtype(9);
+ return (rrtype);
+}
+
+inline const RRType&
+RRType::MB() {
+ static RRType rrtype(7);
+ return (rrtype);
+}
+
+inline const RRType&
+RRType::CNAME() {
+ static RRType rrtype(5);
+ return (rrtype);
+}
+
+inline const RRType&
+RRType::MD() {
+ static RRType rrtype(3);
+ return (rrtype);
+}
+
+inline const RRType&
+RRType::A() {
+ static RRType rrtype(1);
+ return (rrtype);
+}
+
+inline const RRType&
+RRType::A6() {
+ static RRType rrtype(38);
+ return (rrtype);
+}
+
+inline const RRType&
+RRType::DNAME() {
+ static RRType rrtype(39);
+ return (rrtype);
+}
+
+inline const RRType&
+RRType::SRV() {
+ static RRType rrtype(33);
+ return (rrtype);
+}
+
+inline const RRType&
+RRType::NXT() {
+ static RRType rrtype(30);
+ return (rrtype);
+}
+
+inline const RRType&
+RRType::KX() {
+ static RRType rrtype(36);
+ return (rrtype);
+}
+
+inline const RRType&
+RRType::CERT() {
+ static RRType rrtype(37);
+ return (rrtype);
+}
+
+inline const RRType&
+RRType::NAPTR() {
+ static RRType rrtype(35);
+ return (rrtype);
+}
+
+// END_WELL_KNOWN_TYPE_DEFINITIONS
+
+///
+/// \brief Insert the \c RRType as a string into stream.
+///
+/// This method convert the \c rrtype into a string and inserts it into the
+/// output stream \c os.
+///
+/// This function overloads the global operator<< to behave as described in
+/// ostream::operator<< but applied to \c RRType objects.
+///
+/// \param os A \c std::ostream object on which the insertion operation is
+/// performed.
+/// \param rrtype The \c RRType object output by the operation.
+/// \return A reference to the same \c std::ostream object referenced by
+/// parameter \c os after the insertion operation.
+std::ostream&
+operator<<(std::ostream& os, const RRType& rrtype);
+}
+}
+#endif // RRTYPE_H
+
+// Local Variables:
+// mode: c++
+// End: