Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
Sebastian Schrader
Kea
Commits
c874cb05
Commit
c874cb05
authored
Sep 30, 2011
by
JINMEI Tatuya
Browse files
[master] Merge branch 'trac1258' with fixing conflict in Changelog.
parents
c430e464
12fd115d
Changes
13
Hide whitespace changes
Inline
Side-by-side
src/lib/dns/message.cc
View file @
c874cb05
...
...
@@ -124,10 +124,12 @@ public:
void
setOpcode
(
const
Opcode
&
opcode
);
void
setRcode
(
const
Rcode
&
rcode
);
int
parseQuestion
(
InputBuffer
&
buffer
);
int
parseSection
(
const
Message
::
Section
section
,
InputBuffer
&
buffer
);
int
parseSection
(
const
Message
::
Section
section
,
InputBuffer
&
buffer
,
Message
::
ParseOptions
options
);
void
addRR
(
Message
::
Section
section
,
const
Name
&
name
,
const
RRClass
&
rrclass
,
const
RRType
&
rrtype
,
const
RRTTL
&
ttl
,
ConstRdataPtr
rdata
);
const
RRTTL
&
ttl
,
ConstRdataPtr
rdata
,
Message
::
ParseOptions
options
);
void
addEDNS
(
Message
::
Section
section
,
const
Name
&
name
,
const
RRClass
&
rrclass
,
const
RRType
&
rrtype
,
const
RRTTL
&
ttl
,
const
Rdata
&
rdata
);
...
...
@@ -614,7 +616,7 @@ Message::parseHeader(InputBuffer& buffer) {
}
void
Message
::
fromWire
(
InputBuffer
&
buffer
)
{
Message
::
fromWire
(
InputBuffer
&
buffer
,
ParseOptions
options
)
{
if
(
impl_
->
mode_
!=
Message
::
PARSE
)
{
isc_throw
(
InvalidMessageOperation
,
"Message parse attempted in non parse mode"
);
...
...
@@ -626,11 +628,11 @@ Message::fromWire(InputBuffer& buffer) {
impl_
->
counts_
[
SECTION_QUESTION
]
=
impl_
->
parseQuestion
(
buffer
);
impl_
->
counts_
[
SECTION_ANSWER
]
=
impl_
->
parseSection
(
SECTION_ANSWER
,
buffer
);
impl_
->
parseSection
(
SECTION_ANSWER
,
buffer
,
options
);
impl_
->
counts_
[
SECTION_AUTHORITY
]
=
impl_
->
parseSection
(
SECTION_AUTHORITY
,
buffer
);
impl_
->
parseSection
(
SECTION_AUTHORITY
,
buffer
,
options
);
impl_
->
counts_
[
SECTION_ADDITIONAL
]
=
impl_
->
parseSection
(
SECTION_ADDITIONAL
,
buffer
);
impl_
->
parseSection
(
SECTION_ADDITIONAL
,
buffer
,
options
);
}
int
...
...
@@ -706,7 +708,7 @@ struct MatchRR : public unary_function<RRsetPtr, bool> {
// is hardcoded here.
int
MessageImpl
::
parseSection
(
const
Message
::
Section
section
,
InputBuffer
&
buffer
)
InputBuffer
&
buffer
,
Message
::
ParseOptions
options
)
{
assert
(
section
<
MessageImpl
::
NUM_SECTIONS
);
...
...
@@ -738,7 +740,7 @@ MessageImpl::parseSection(const Message::Section section,
addTSIG
(
section
,
count
,
buffer
,
start_position
,
name
,
rrclass
,
ttl
,
*
rdata
);
}
else
{
addRR
(
section
,
name
,
rrclass
,
rrtype
,
ttl
,
rdata
);
addRR
(
section
,
name
,
rrclass
,
rrtype
,
ttl
,
rdata
,
options
);
++
added
;
}
}
...
...
@@ -749,19 +751,22 @@ MessageImpl::parseSection(const Message::Section section,
void
MessageImpl
::
addRR
(
Message
::
Section
section
,
const
Name
&
name
,
const
RRClass
&
rrclass
,
const
RRType
&
rrtype
,
const
RRTTL
&
ttl
,
ConstRdataPtr
rdata
)
const
RRTTL
&
ttl
,
ConstRdataPtr
rdata
,
Message
::
ParseOptions
options
)
{
vector
<
RRsetPtr
>::
iterator
it
=
find_if
(
rrsets_
[
section
].
begin
(),
rrsets_
[
section
].
end
(),
MatchRR
(
name
,
rrtype
,
rrclass
));
if
(
it
!=
rrsets_
[
section
].
end
())
{
(
*
it
)
->
setTTL
(
min
((
*
it
)
->
getTTL
(),
ttl
));
(
*
it
)
->
addRdata
(
rdata
);
}
else
{
RRsetPtr
rrset
(
new
RRset
(
name
,
rrclass
,
rrtype
,
ttl
));
rrset
->
addRdata
(
rdata
);
rrsets_
[
section
].
push_back
(
rrset
);
if
((
options
&
Message
::
PRESERVE_ORDER
)
==
0
)
{
vector
<
RRsetPtr
>::
iterator
it
=
find_if
(
rrsets_
[
section
].
begin
(),
rrsets_
[
section
].
end
(),
MatchRR
(
name
,
rrtype
,
rrclass
));
if
(
it
!=
rrsets_
[
section
].
end
())
{
(
*
it
)
->
setTTL
(
min
((
*
it
)
->
getTTL
(),
ttl
));
(
*
it
)
->
addRdata
(
rdata
);
return
;
}
}
RRsetPtr
rrset
(
new
RRset
(
name
,
rrclass
,
rrtype
,
ttl
));
rrset
->
addRdata
(
rdata
);
rrsets_
[
section
].
push_back
(
rrset
);
}
void
...
...
src/lib/dns/message.h
View file @
c874cb05
...
...
@@ -581,11 +581,58 @@ public:
/// message
void
toWire
(
AbstractMessageRenderer
&
renderer
,
TSIGContext
&
tsig_ctx
);
/// Parse options.
///
/// describe PRESERVE_ORDER: note doesn't affect EDNS or TSIG.
///
/// The option values are used as a parameter for \c fromWire().
/// These are values of a bitmask type. Bitwise operations can be
/// performed on these values to express compound options.
enum
ParseOptions
{
PARSE_DEFAULT
=
0
,
///< The default options
PRESERVE_ORDER
=
1
///< Preserve RR order and don't combine them
};
/// \brief Parse the header section of the \c Message.
void
parseHeader
(
isc
::
util
::
InputBuffer
&
buffer
);
/// \brief Parse the \c Message.
void
fromWire
(
isc
::
util
::
InputBuffer
&
buffer
);
/// \brief (Re)build a \c Message object from wire-format data.
///
/// This method parses the given wire format data to build a
/// complete Message object. On success, the values of the header section
/// fields can be accessible via corresponding get methods, and the
/// question and following sections can be accessible via the
/// corresponding iterators. If the message contains an EDNS or TSIG,
/// they can be accessible via \c getEDNS() and \c getTSIGRecord(),
/// respectively.
///
/// This \c Message must be in the \c PARSE mode.
///
/// This method performs strict validation on the given message based
/// on the DNS protocol specifications. If the given message data is
/// invalid, this method throws an exception (see the exception list).
///
/// By default, this method combines RRs of the same name, RR type and
/// RR class in a section into a single RRset, even if they are interleaved
/// with a different type of RR (though it would be a rare case in
/// practice). If the \c PRESERVE_ORDER option is specified, it handles
/// each RR separately, in the appearing order, and converts it to a
/// separate RRset (so this RRset should contain exactly one Rdata).
/// This mode will be necessary when the higher level protocol is
/// ordering conscious. For example, in AXFR and IXFR, the position of
/// the SOA RRs are crucial.
///
/// \exception InvalidMessageOperation \c Message is in the RENDER mode
/// \exception DNSMessageFORMERR The given message data is syntactically
/// \exception MessageTooShort The given data is shorter than a valid
/// header section
/// \exception std::bad_alloc Memory allocation failure
/// \exception Others \c Name, \c Rdata, and \c EDNS classes can also throw
///
/// \param buffer A input buffer object that stores the wire data
/// \param options Parse options
void
fromWire
(
isc
::
util
::
InputBuffer
&
buffer
,
ParseOptions
options
=
PARSE_DEFAULT
);
///
/// \name Protocol constants
...
...
@@ -629,6 +676,6 @@ std::ostream& operator<<(std::ostream& os, const Message& message);
}
#endif // __MESSAGE_H
// Local Variables:
// Local Variables:
// mode: c++
// End:
// End:
src/lib/dns/python/Makefile.am
View file @
c874cb05
...
...
@@ -39,6 +39,7 @@ pydnspp_la_CXXFLAGS = $(AM_CXXFLAGS) $(PYTHON_CXXFLAGS)
pydnspp_la_LDFLAGS
=
$(PYTHON_LDFLAGS)
EXTRA_DIST
=
tsigerror_python_inc.cc
EXTRA_DIST
+=
message_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.
...
...
src/lib/dns/python/message_python.cc
View file @
c874cb05
...
...
@@ -39,6 +39,9 @@ using namespace isc::dns;
using
namespace
isc
::
dns
::
python
;
using
namespace
isc
::
util
;
// Import pydoc text
#include "message_python_inc.cc"
namespace
{
class
s_Message
:
public
PyObject
{
public:
...
...
@@ -75,7 +78,7 @@ 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
(
s_Message
*
self
,
PyObject
*
args
);
PyObject
*
Message_fromWire
(
PyObject
*
const
py
self
,
PyObject
*
args
);
// This list contains the actual set of functions we have in
// python. Each entry has
...
...
@@ -157,14 +160,7 @@ PyMethodDef Message_methods[] = {
"If the given message is not in RENDER mode, an "
"InvalidMessageOperation is raised.
\n
"
},
{
"from_wire"
,
reinterpret_cast
<
PyCFunction
>
(
Message_fromWire
),
METH_VARARGS
,
"Parses the given wire format to a Message object.
\n
"
"The first argument is a Message to parse the data into.
\n
"
"The second argument must implement the buffer interface.
\n
"
"If the given message is not in PARSE mode, an "
"InvalidMessageOperation is raised.
\n
"
"Raises MessageTooShort, DNSMessageFORMERR or DNSMessageBADVERS "
" if there is a problem parsing the message."
},
{
"from_wire"
,
Message_fromWire
,
METH_VARARGS
,
Message_fromWire_doc
},
{
NULL
,
NULL
,
0
,
NULL
}
};
...
...
@@ -646,30 +642,54 @@ Message_toWire(s_Message* self, PyObject* args) {
}
PyObject
*
Message_fromWire
(
s_Message
*
self
,
PyObject
*
args
)
{
Message_fromWire
(
PyObject
*
const
pyself
,
PyObject
*
args
)
{
s_Message
*
self
=
static_cast
<
s_Message
*>
(
pyself
);
const
char
*
b
;
Py_ssize_t
len
;
if
(
!
PyArg_ParseTuple
(
args
,
"y#"
,
&
b
,
&
len
))
{
return
(
NULL
);
}
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
);
Py_RETURN_NONE
;
}
catch
(
const
InvalidMessageOperation
&
imo
)
{
PyErr_SetString
(
po_InvalidMessageOperation
,
imo
.
what
());
return
(
NULL
);
}
catch
(
const
DNSMessageFORMERR
&
dmfe
)
{
PyErr_SetString
(
po_DNSMessageFORMERR
,
dmfe
.
what
());
return
(
NULL
);
}
catch
(
const
DNSMessageBADVERS
&
dmfe
)
{
PyErr_SetString
(
po_DNSMessageBADVERS
,
dmfe
.
what
());
return
(
NULL
);
}
catch
(
const
MessageTooShort
&
mts
)
{
PyErr_SetString
(
po_MessageTooShort
,
mts
.
what
());
return
(
NULL
);
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
());
return
(
NULL
);
}
catch
(
const
DNSMessageFORMERR
&
dmfe
)
{
PyErr_SetString
(
po_DNSMessageFORMERR
,
dmfe
.
what
());
return
(
NULL
);
}
catch
(
const
DNSMessageBADVERS
&
dmfe
)
{
PyErr_SetString
(
po_DNSMessageBADVERS
,
dmfe
.
what
());
return
(
NULL
);
}
catch
(
const
MessageTooShort
&
mts
)
{
PyErr_SetString
(
po_MessageTooShort
,
mts
.
what
());
return
(
NULL
);
}
catch
(
const
InvalidBufferPosition
&
ex
)
{
PyErr_SetString
(
po_DNSMessageFORMERR
,
ex
.
what
());
return
(
NULL
);
}
catch
(
const
exception
&
ex
)
{
const
string
ex_what
=
"Error in Message.from_wire: "
+
string
(
ex
.
what
());
PyErr_SetString
(
PyExc_RuntimeError
,
ex_what
.
c_str
());
return
(
NULL
);
}
catch
(...)
{
PyErr_SetString
(
PyExc_RuntimeError
,
"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
...
...
src/lib/dns/python/message_python_inc.cc
0 → 100644
View file @
c874cb05
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
\
"
;
}
// unnamed namespace
src/lib/dns/python/pydnspp.cc
View file @
c874cb05
...
...
@@ -89,64 +89,91 @@ initModulePart_Message(PyObject* mod) {
if
(
PyType_Ready
(
&
message_type
)
<
0
)
{
return
(
false
);
}
void
*
p
=
&
message_type
;
if
(
PyModule_AddObject
(
mod
,
"Message"
,
static_cast
<
PyObject
*>
(
p
))
<
0
)
{
return
(
false
);
}
Py_INCREF
(
&
message_type
);
// Class variables
// These are added to the tp_dict of the type object
//
addClassVariable
(
message_type
,
"PARSE"
,
Py_BuildValue
(
"I"
,
Message
::
PARSE
));
addClassVariable
(
message_type
,
"RENDER"
,
Py_BuildValue
(
"I"
,
Message
::
RENDER
));
addClassVariable
(
message_type
,
"HEADERFLAG_QR"
,
Py_BuildValue
(
"I"
,
Message
::
HEADERFLAG_QR
));
addClassVariable
(
message_type
,
"HEADERFLAG_AA"
,
Py_BuildValue
(
"I"
,
Message
::
HEADERFLAG_AA
));
addClassVariable
(
message_type
,
"HEADERFLAG_TC"
,
Py_BuildValue
(
"I"
,
Message
::
HEADERFLAG_TC
));
addClassVariable
(
message_type
,
"HEADERFLAG_RD"
,
Py_BuildValue
(
"I"
,
Message
::
HEADERFLAG_RD
));
addClassVariable
(
message_type
,
"HEADERFLAG_RA"
,
Py_BuildValue
(
"I"
,
Message
::
HEADERFLAG_RA
));
addClassVariable
(
message_type
,
"HEADERFLAG_AD"
,
Py_BuildValue
(
"I"
,
Message
::
HEADERFLAG_AD
));
addClassVariable
(
message_type
,
"HEADERFLAG_CD"
,
Py_BuildValue
(
"I"
,
Message
::
HEADERFLAG_CD
));
addClassVariable
(
message_type
,
"SECTION_QUESTION"
,
Py_BuildValue
(
"I"
,
Message
::
SECTION_QUESTION
));
addClassVariable
(
message_type
,
"SECTION_ANSWER"
,
Py_BuildValue
(
"I"
,
Message
::
SECTION_ANSWER
));
addClassVariable
(
message_type
,
"SECTION_AUTHORITY"
,
Py_BuildValue
(
"I"
,
Message
::
SECTION_AUTHORITY
));
addClassVariable
(
message_type
,
"SECTION_ADDITIONAL"
,
Py_BuildValue
(
"I"
,
Message
::
SECTION_ADDITIONAL
));
addClassVariable
(
message_type
,
"DEFAULT_MAX_UDPSIZE"
,
Py_BuildValue
(
"I"
,
Message
::
DEFAULT_MAX_UDPSIZE
));
/* Class-specific exceptions */
po_MessageTooShort
=
PyErr_NewException
(
"pydnspp.MessageTooShort"
,
NULL
,
NULL
);
PyModule_AddObject
(
mod
,
"MessageTooShort"
,
po_MessageTooShort
);
po_InvalidMessageSection
=
PyErr_NewException
(
"pydnspp.InvalidMessageSection"
,
NULL
,
NULL
);
PyModule_AddObject
(
mod
,
"InvalidMessageSection"
,
po_InvalidMessageSection
);
po_InvalidMessageOperation
=
PyErr_NewException
(
"pydnspp.InvalidMessageOperation"
,
NULL
,
NULL
);
PyModule_AddObject
(
mod
,
"InvalidMessageOperation"
,
po_InvalidMessageOperation
);
po_InvalidMessageUDPSize
=
PyErr_NewException
(
"pydnspp.InvalidMessageUDPSize"
,
NULL
,
NULL
);
PyModule_AddObject
(
mod
,
"InvalidMessageUDPSize"
,
po_InvalidMessageUDPSize
);
po_DNSMessageBADVERS
=
PyErr_NewException
(
"pydnspp.DNSMessageBADVERS"
,
NULL
,
NULL
);
PyModule_AddObject
(
mod
,
"DNSMessageBADVERS"
,
po_DNSMessageBADVERS
);
PyModule_AddObject
(
mod
,
"Message"
,
reinterpret_cast
<
PyObject
*>
(
&
message_type
));
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_DNSMessageBADVERS
=
PyErr_NewException
(
"pydnspp.DNSMessageBADVERS"
,
NULL
,
NULL
);
PyObjectContainer
(
po_DNSMessageBADVERS
).
installToModule
(
mod
,
"DNSMessageBADVERS"
);
}
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
);
}
...
...
src/lib/dns/python/tests/message_python_test.py
View file @
c874cb05
...
...
@@ -29,9 +29,9 @@ if "TESTDATA_PATH" in os.environ:
else
:
testdata_path
=
"../tests/testdata"
def
factoryFromFile
(
message
,
file
):
def
factoryFromFile
(
message
,
file
,
parse_options
=
Message
.
PARSE_DEFAULT
):
data
=
read_wire_data
(
file
)
message
.
from_wire
(
data
)
message
.
from_wire
(
data
,
parse_options
)
return
data
# we don't have direct comparison for rrsets right now (should we?
...
...
@@ -466,6 +466,54 @@ test.example.com. 3600 IN A 192.0.2.2
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_combind_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
)
...
...
src/lib/dns/tests/message_unittest.cc
View file @
c874cb05
...
...
@@ -118,16 +118,20 @@ protected:
vector
<
unsigned
char
>
received_data
;
vector
<
unsigned
char
>
expected_data
;
void
factoryFromFile
(
Message
&
message
,
const
char
*
datafile
);
void
factoryFromFile
(
Message
&
message
,
const
char
*
datafile
,
Message
::
ParseOptions
options
=
Message
::
PARSE_DEFAULT
);
};
void
MessageTest
::
factoryFromFile
(
Message
&
message
,
const
char
*
datafile
)
{
MessageTest
::
factoryFromFile
(
Message
&
message
,
const
char
*
datafile
,
Message
::
ParseOptions
options
)
{
received_data
.
clear
();
UnitTestUtil
::
readWireData
(
datafile
,
received_data
);
InputBuffer
buffer
(
&
received_data
[
0
],
received_data
.
size
());
message
.
fromWire
(
buffer
);
message
.
fromWire
(
buffer
,
options
);
}
TEST_F
(
MessageTest
,
headerFlag
)
{
...
...
@@ -175,7 +179,6 @@ TEST_F(MessageTest, headerFlag) {
EXPECT_THROW
(
message_parse
.
setHeaderFlag
(
Message
::
HEADERFLAG_QR
),
InvalidMessageOperation
);
}
TEST_F
(
MessageTest
,
getEDNS
)
{
EXPECT_FALSE
(
message_parse
.
getEDNS
());
// by default EDNS isn't set
...
...
@@ -532,7 +535,46 @@ TEST_F(MessageTest, appendSection) {
}
TEST_F
(
MessageTest
,
parseHeader
)
{
received_data
.
clear
();
UnitTestUtil
::
readWireData
(
"message_fromWire1"
,
received_data
);
// parseHeader() isn't allowed in the render mode.
InputBuffer
buffer
(
&
received_data
[
0
],
received_data
.
size
());
EXPECT_THROW
(
message_render
.
parseHeader
(
buffer
),
InvalidMessageOperation
);
message_parse
.
parseHeader
(
buffer
);
EXPECT_EQ
(
0x1035
,
message_parse
.
getQid
());
EXPECT_EQ
(
Opcode
::
QUERY
(),
message_parse
.
getOpcode
());
EXPECT_EQ
(
Rcode
::
NOERROR
(),
message_parse
.
getRcode
());
EXPECT_TRUE
(
message_parse
.
getHeaderFlag
(
Message
::
HEADERFLAG_QR
));
EXPECT_TRUE
(
message_parse
.
getHeaderFlag
(
Message
::
HEADERFLAG_AA
));
EXPECT_FALSE
(
message_parse
.
getHeaderFlag
(
Message
::
HEADERFLAG_TC
));
EXPECT_TRUE
(
message_parse
.
getHeaderFlag
(
Message
::
HEADERFLAG_RD
));
EXPECT_FALSE
(
message_parse
.
getHeaderFlag
(
Message
::
HEADERFLAG_RA
));
EXPECT_FALSE
(
message_parse
.
getHeaderFlag
(
Message
::
HEADERFLAG_AD
));
EXPECT_FALSE
(
message_parse
.
getHeaderFlag
(
Message
::
HEADERFLAG_CD
));
EXPECT_EQ
(
1
,
message_parse
.
getRRCount
(
Message
::
SECTION_QUESTION
));
EXPECT_EQ
(
2
,
message_parse
.
getRRCount
(
Message
::
SECTION_ANSWER
));
EXPECT_EQ
(
0
,
message_parse
.
getRRCount
(
Message
::
SECTION_AUTHORITY
));
EXPECT_EQ
(
0
,
message_parse
.
getRRCount
(
Message
::
SECTION_ADDITIONAL
));
// Only the header part should have been examined.
EXPECT_EQ
(
12
,
buffer
.
getPosition
());
// 12 = size of the header section
EXPECT_TRUE
(
message_parse
.
beginQuestion
()
==
message_parse
.
endQuestion
());
EXPECT_TRUE
(
message_parse
.
beginSection
(
Message
::
SECTION_ANSWER
)
==
message_parse
.
endSection
(
Message
::
SECTION_ANSWER
));