mirror of
https://github.com/NLnetLabs/unbound.git
synced 2025-12-20 23:00:56 -05:00
- With ./configure --with-pyunbound --with-pythonmodule
PYTHON_VERSION=3.6 or with 2.7 unbound can compile and unit tests succeed for the python module. - pythonmod logs the python error and traceback on failure. git-svn-id: file:///svn/unbound/trunk@4966 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
parent
022d5131b3
commit
5853f90076
9 changed files with 323 additions and 65 deletions
|
|
@ -482,9 +482,9 @@ doc:
|
||||||
if test -n "$(doxygen)"; then \
|
if test -n "$(doxygen)"; then \
|
||||||
$(doxygen) $(srcdir)/doc/unbound.doxygen; fi
|
$(doxygen) $(srcdir)/doc/unbound.doxygen; fi
|
||||||
if test "$(WITH_PYUNBOUND)" = "yes" -o "$(WITH_PYTHONMODULE)" = "yes"; \
|
if test "$(WITH_PYUNBOUND)" = "yes" -o "$(WITH_PYTHONMODULE)" = "yes"; \
|
||||||
then if test -x "`which sphinx-build 2>&1`"; then \
|
then if test -x "`which sphinx-build-$(PY_MAJOR_VERSION) 2>&1`"; then \
|
||||||
sphinx-build -b html pythonmod/doc doc/html/pythonmod; \
|
sphinx-build-$(PY_MAJOR_VERSION) -b html pythonmod/doc doc/html/pythonmod; \
|
||||||
sphinx-build -b html libunbound/python/doc doc/html/pyunbound;\
|
sphinx-build-$(PY_MAJOR_VERSION) -b html libunbound/python/doc doc/html/pyunbound;\
|
||||||
fi ;\
|
fi ;\
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,9 @@
|
||||||
|
22 November 2018: Wouter
|
||||||
|
- With ./configure --with-pyunbound --with-pythonmodule
|
||||||
|
PYTHON_VERSION=3.6 or with 2.7 unbound can compile and unit tests
|
||||||
|
succeed for the python module.
|
||||||
|
- pythonmod logs the python error and traceback on failure.
|
||||||
|
|
||||||
21 November 2018: Wouter
|
21 November 2018: Wouter
|
||||||
- Scrub NS records from NODATA responses as well.
|
- Scrub NS records from NODATA responses as well.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -612,17 +612,21 @@ RECURSIVE = YES
|
||||||
|
|
||||||
EXCLUDE = ./build \
|
EXCLUDE = ./build \
|
||||||
./compat \
|
./compat \
|
||||||
|
./contrib \
|
||||||
util/configparser.c \
|
util/configparser.c \
|
||||||
util/configparser.h \
|
util/configparser.h \
|
||||||
util/configlexer.c \
|
util/configlexer.c \
|
||||||
util/locks.h \
|
util/locks.h \
|
||||||
|
pythonmod/doc \
|
||||||
|
pythonmod/examples \
|
||||||
pythonmod/unboundmodule.py \
|
pythonmod/unboundmodule.py \
|
||||||
pythonmod/interface.h \
|
pythonmod/interface.h \
|
||||||
pythonmod/examples/resgen.py \
|
pythonmod/ubmodule-msg.py \
|
||||||
pythonmod/examples/resmod.py \
|
pythonmod/ubmodule-tst.py \
|
||||||
pythonmod/examples/resip.py \
|
|
||||||
libunbound/python/unbound.py \
|
libunbound/python/unbound.py \
|
||||||
libunbound/python/libunbound_wrap.c \
|
libunbound/python/libunbound_wrap.c \
|
||||||
|
libunbound/python/doc \
|
||||||
|
libunbound/python/examples \
|
||||||
./ldns-src \
|
./ldns-src \
|
||||||
doc/control_proto_spec.txt \
|
doc/control_proto_spec.txt \
|
||||||
doc/requirements.txt
|
doc/requirements.txt
|
||||||
|
|
|
||||||
|
|
@ -45,15 +45,20 @@
|
||||||
|
|
||||||
i = 0;
|
i = 0;
|
||||||
while (i < len) {
|
while (i < len) {
|
||||||
i += name[i] + 1;
|
i += ((unsigned int)name[i]) + 1;
|
||||||
cnt++;
|
cnt++;
|
||||||
}
|
}
|
||||||
|
|
||||||
list = PyList_New(cnt);
|
list = PyList_New(cnt);
|
||||||
i = 0; cnt = 0;
|
i = 0; cnt = 0;
|
||||||
while (i < len) {
|
while (i < len) {
|
||||||
PyList_SetItem(list, cnt, PyBytes_FromStringAndSize(name + i + 1, name[i]));
|
char buf[LDNS_MAX_LABELLEN+1];
|
||||||
i += name[i] + 1;
|
if(((unsigned int)name[i])+1 <= (int)sizeof(buf)) {
|
||||||
|
memmove(buf, name + i + 1, (unsigned int)name[i]);
|
||||||
|
buf[(unsigned int)name[i]] = 0;
|
||||||
|
PyList_SetItem(list, cnt, PyString_FromString(buf));
|
||||||
|
}
|
||||||
|
i += ((unsigned int)name[i]) + 1;
|
||||||
cnt++;
|
cnt++;
|
||||||
}
|
}
|
||||||
return list;
|
return list;
|
||||||
|
|
@ -161,11 +166,11 @@ struct query_info {
|
||||||
%}
|
%}
|
||||||
|
|
||||||
%inline %{
|
%inline %{
|
||||||
PyObject* dnameAsStr(const char* dname) {
|
PyObject* dnameAsStr(PyObject* dname) {
|
||||||
char buf[LDNS_MAX_DOMAINLEN+1];
|
char buf[LDNS_MAX_DOMAINLEN+1];
|
||||||
buf[0] = '\0';
|
buf[0] = '\0';
|
||||||
dname_str((uint8_t*)dname, buf);
|
dname_str((uint8_t*)PyBytes_AsString(dname), buf);
|
||||||
return PyBytes_FromString(buf);
|
return PyString_FromString(buf);
|
||||||
}
|
}
|
||||||
%}
|
%}
|
||||||
|
|
||||||
|
|
@ -1211,7 +1216,7 @@ int checkList(PyObject *l)
|
||||||
for (i=0; i < PyList_Size(l); i++)
|
for (i=0; i < PyList_Size(l); i++)
|
||||||
{
|
{
|
||||||
item = PyList_GetItem(l, i);
|
item = PyList_GetItem(l, i);
|
||||||
if (!PyBytes_Check(item))
|
if (!PyBytes_Check(item) && !PyUnicode_Check(item))
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
|
|
@ -1226,23 +1231,40 @@ int pushRRList(sldns_buffer* qb, PyObject *l, uint32_t default_ttl, int qsec,
|
||||||
PyObject* item;
|
PyObject* item;
|
||||||
int i;
|
int i;
|
||||||
size_t len;
|
size_t len;
|
||||||
|
char* s;
|
||||||
|
PyObject* ascstr;
|
||||||
|
|
||||||
for (i=0; i < PyList_Size(l); i++)
|
for (i=0; i < PyList_Size(l); i++)
|
||||||
{
|
{
|
||||||
|
ascstr = NULL;
|
||||||
item = PyList_GetItem(l, i);
|
item = PyList_GetItem(l, i);
|
||||||
|
if(PyObject_TypeCheck(item, &PyBytes_Type)) {
|
||||||
|
s = PyBytes_AsString(item);
|
||||||
|
} else {
|
||||||
|
ascstr = PyUnicode_AsASCIIString(item);
|
||||||
|
s = PyBytes_AsString(ascstr);
|
||||||
|
}
|
||||||
|
|
||||||
len = sldns_buffer_remaining(qb);
|
len = sldns_buffer_remaining(qb);
|
||||||
if(qsec) {
|
if(qsec) {
|
||||||
if(sldns_str2wire_rr_question_buf(PyBytes_AsString(item),
|
if(sldns_str2wire_rr_question_buf(s,
|
||||||
sldns_buffer_current(qb), &len, NULL, NULL, 0, NULL, 0)
|
sldns_buffer_current(qb), &len, NULL, NULL, 0, NULL, 0)
|
||||||
!= 0)
|
!= 0) {
|
||||||
return 0;
|
if(ascstr)
|
||||||
} else {
|
Py_DECREF(ascstr);
|
||||||
if(sldns_str2wire_rr_buf(PyBytes_AsString(item),
|
|
||||||
sldns_buffer_current(qb), &len, NULL, default_ttl,
|
|
||||||
NULL, 0, NULL, 0) != 0)
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
if(sldns_str2wire_rr_buf(s,
|
||||||
|
sldns_buffer_current(qb), &len, NULL, default_ttl,
|
||||||
|
NULL, 0, NULL, 0) != 0) {
|
||||||
|
if(ascstr)
|
||||||
|
Py_DECREF(ascstr);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(ascstr)
|
||||||
|
Py_DECREF(ascstr);
|
||||||
sldns_buffer_skip(qb, len);
|
sldns_buffer_skip(qb, len);
|
||||||
|
|
||||||
sldns_buffer_write_u16_at(qb, count_offset,
|
sldns_buffer_write_u16_at(qb, count_offset,
|
||||||
|
|
|
||||||
|
|
@ -110,6 +110,128 @@ struct pythonmod_qstate {
|
||||||
#include "pythonmod/interface.h"
|
#include "pythonmod/interface.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/** log python error */
|
||||||
|
static void
|
||||||
|
log_py_err(void)
|
||||||
|
{
|
||||||
|
char *result = NULL;
|
||||||
|
PyObject *modStringIO = NULL;
|
||||||
|
PyObject *modTB = NULL;
|
||||||
|
PyObject *obFuncStringIO = NULL;
|
||||||
|
PyObject *obStringIO = NULL;
|
||||||
|
PyObject *obFuncTB = NULL;
|
||||||
|
PyObject *argsTB = NULL;
|
||||||
|
PyObject *obResult = NULL;
|
||||||
|
PyObject *ascstr = NULL;
|
||||||
|
PyObject *exc_typ, *exc_val, *exc_tb;
|
||||||
|
|
||||||
|
/* Fetch the error state now before we cruch it */
|
||||||
|
/* exc val contains the error message
|
||||||
|
* exc tb contains stack traceback and other info. */
|
||||||
|
PyErr_Fetch(&exc_typ, &exc_val, &exc_tb);
|
||||||
|
PyErr_NormalizeException(&exc_typ, &exc_val, &exc_tb);
|
||||||
|
|
||||||
|
/* Import the modules we need - cStringIO and traceback */
|
||||||
|
modStringIO = PyImport_ImportModule("cStringIO");
|
||||||
|
if (modStringIO==NULL) /* python 1.4 and before */
|
||||||
|
modStringIO = PyImport_ImportModule("StringIO");
|
||||||
|
if (modStringIO==NULL) /* python 3 */
|
||||||
|
modStringIO = PyImport_ImportModule("io");
|
||||||
|
if (modStringIO==NULL) {
|
||||||
|
log_err("pythonmod: cannot print exception, "
|
||||||
|
"cannot ImportModule cStringIO or StringIO");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
modTB = PyImport_ImportModule("traceback");
|
||||||
|
if (modTB==NULL) {
|
||||||
|
log_err("pythonmod: cannot print exception, "
|
||||||
|
"cannot ImportModule traceback");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Construct a cStringIO object */
|
||||||
|
obFuncStringIO = PyObject_GetAttrString(modStringIO, "StringIO");
|
||||||
|
if (obFuncStringIO==NULL) {
|
||||||
|
log_err("pythonmod: cannot print exception, "
|
||||||
|
"cannot GetAttrString cStringIO.StringIO");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
obStringIO = PyObject_CallObject(obFuncStringIO, NULL);
|
||||||
|
if (obStringIO==NULL) {
|
||||||
|
log_err("pythonmod: cannot print exception, "
|
||||||
|
"cannot cStringIO.StringIO()");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get the traceback.print_exception function, and call it. */
|
||||||
|
obFuncTB = PyObject_GetAttrString(modTB, "print_exception");
|
||||||
|
if (obFuncTB==NULL) {
|
||||||
|
log_err("pythonmod: cannot print exception, "
|
||||||
|
"cannot GetAttrString traceback.print_exception");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
argsTB = Py_BuildValue("OOOOO", (exc_typ ? exc_typ : Py_None),
|
||||||
|
(exc_val ? exc_val : Py_None), (exc_tb ? exc_tb : Py_None),
|
||||||
|
Py_None, obStringIO);
|
||||||
|
if (argsTB==NULL) {
|
||||||
|
log_err("pythonmod: cannot print exception, "
|
||||||
|
"cannot BuildValue for print_exception");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
obResult = PyObject_CallObject(obFuncTB, argsTB);
|
||||||
|
if (obResult==NULL) {
|
||||||
|
PyErr_Print();
|
||||||
|
log_err("pythonmod: cannot print exception, "
|
||||||
|
"call traceback.print_exception() failed");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now call the getvalue() method in the StringIO instance */
|
||||||
|
Py_DECREF(obFuncStringIO);
|
||||||
|
obFuncStringIO = PyObject_GetAttrString(obStringIO, "getvalue");
|
||||||
|
if (obFuncStringIO==NULL) {
|
||||||
|
log_err("pythonmod: cannot print exception, "
|
||||||
|
"cannot GetAttrString cStringIO.getvalue");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
Py_DECREF(obResult);
|
||||||
|
obResult = PyObject_CallObject(obFuncStringIO, NULL);
|
||||||
|
if (obResult==NULL) {
|
||||||
|
log_err("pythonmod: cannot print exception, "
|
||||||
|
"call cStringIO.getvalue() failed");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* And it should be a string all ready to go - duplicate it. */
|
||||||
|
if (!PyString_Check(obResult) && !PyUnicode_Check(obResult)) {
|
||||||
|
log_err("pythonmod: cannot print exception, "
|
||||||
|
"cStringIO.getvalue() result did not String_Check");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
if(PyString_Check(obResult)) {
|
||||||
|
result = PyString_AsString(obResult);
|
||||||
|
} else {
|
||||||
|
ascstr = PyUnicode_AsASCIIString(obResult);
|
||||||
|
result = PyBytes_AsString(ascstr);
|
||||||
|
}
|
||||||
|
log_err("pythonmod: python error: %s", result);
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
Py_XDECREF(modStringIO);
|
||||||
|
Py_XDECREF(modTB);
|
||||||
|
Py_XDECREF(obFuncStringIO);
|
||||||
|
Py_XDECREF(obStringIO);
|
||||||
|
Py_XDECREF(obFuncTB);
|
||||||
|
Py_XDECREF(argsTB);
|
||||||
|
Py_XDECREF(obResult);
|
||||||
|
Py_XDECREF(ascstr);
|
||||||
|
|
||||||
|
/* clear the exception, by not restoring it */
|
||||||
|
/* Restore the exception state */
|
||||||
|
/* PyErr_Restore(exc_typ, exc_val, exc_tb); */
|
||||||
|
}
|
||||||
|
|
||||||
int pythonmod_init(struct module_env* env, int id)
|
int pythonmod_init(struct module_env* env, int id)
|
||||||
{
|
{
|
||||||
/* Initialize module */
|
/* Initialize module */
|
||||||
|
|
@ -193,13 +315,26 @@ int pythonmod_init(struct module_env* env, int id)
|
||||||
|
|
||||||
/* TODO: deallocation of pe->... if an error occurs */
|
/* TODO: deallocation of pe->... if an error occurs */
|
||||||
|
|
||||||
if (PyRun_SimpleFile(script_py, pe->fname) < 0)
|
if (PyRun_SimpleFile(script_py, pe->fname) < 0) {
|
||||||
{
|
|
||||||
log_err("pythonmod: can't parse Python script %s", pe->fname);
|
log_err("pythonmod: can't parse Python script %s", pe->fname);
|
||||||
|
/* print the error to logs too, run it again */
|
||||||
|
fseek(script_py, 0, SEEK_SET);
|
||||||
|
/* we don't run the file, like this, because then side-effects
|
||||||
|
* s = PyRun_File(script_py, pe->fname, Py_file_input,
|
||||||
|
* PyModule_GetDict(PyImport_AddModule("__main__")), pe->dict);
|
||||||
|
* could happen (again). Instead we parse the file again to get
|
||||||
|
* the error string in the logs, for when the daemon has stderr
|
||||||
|
* removed. SimpleFile run already printed to stderr, for then
|
||||||
|
* this is called from unbound-checkconf or unbound -dd the user
|
||||||
|
* has a nice formatted error.
|
||||||
|
*/
|
||||||
|
/* ignore the NULL return of _node, it is NULL due to the parse failure
|
||||||
|
* that we are expecting */
|
||||||
|
(void)PyParser_SimpleParseFile(script_py, pe->fname, Py_file_input);
|
||||||
|
log_py_err();
|
||||||
PyGILState_Release(gil);
|
PyGILState_Release(gil);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
fclose(script_py);
|
fclose(script_py);
|
||||||
|
|
||||||
if ((pe->func_init = PyDict_GetItemString(pe->dict, "init_standard")) == NULL)
|
if ((pe->func_init = PyDict_GetItemString(pe->dict, "init_standard")) == NULL)
|
||||||
|
|
@ -244,7 +379,7 @@ int pythonmod_init(struct module_env* env, int id)
|
||||||
if (PyErr_Occurred())
|
if (PyErr_Occurred())
|
||||||
{
|
{
|
||||||
log_err("pythonmod: Exception occurred in function init");
|
log_err("pythonmod: Exception occurred in function init");
|
||||||
PyErr_Print();
|
log_py_err();
|
||||||
Py_XDECREF(res);
|
Py_XDECREF(res);
|
||||||
Py_XDECREF(py_init_arg);
|
Py_XDECREF(py_init_arg);
|
||||||
PyGILState_Release(gil);
|
PyGILState_Release(gil);
|
||||||
|
|
@ -274,7 +409,7 @@ void pythonmod_deinit(struct module_env* env, int id)
|
||||||
res = PyObject_CallFunction(pe->func_deinit, "i", id);
|
res = PyObject_CallFunction(pe->func_deinit, "i", id);
|
||||||
if (PyErr_Occurred()) {
|
if (PyErr_Occurred()) {
|
||||||
log_err("pythonmod: Exception occurred in function deinit");
|
log_err("pythonmod: Exception occurred in function deinit");
|
||||||
PyErr_Print();
|
log_py_err();
|
||||||
}
|
}
|
||||||
/* Free result if any */
|
/* Free result if any */
|
||||||
Py_XDECREF(res);
|
Py_XDECREF(res);
|
||||||
|
|
@ -312,7 +447,7 @@ void pythonmod_inform_super(struct module_qstate* qstate, int id, struct module_
|
||||||
if (PyErr_Occurred())
|
if (PyErr_Occurred())
|
||||||
{
|
{
|
||||||
log_err("pythonmod: Exception occurred in function inform_super");
|
log_err("pythonmod: Exception occurred in function inform_super");
|
||||||
PyErr_Print();
|
log_py_err();
|
||||||
qstate->ext_state[id] = module_error;
|
qstate->ext_state[id] = module_error;
|
||||||
}
|
}
|
||||||
else if ((res == NULL) || (!PyObject_IsTrue(res)))
|
else if ((res == NULL) || (!PyObject_IsTrue(res)))
|
||||||
|
|
@ -353,7 +488,7 @@ void pythonmod_operate(struct module_qstate* qstate, enum module_ev event,
|
||||||
if (PyErr_Occurred())
|
if (PyErr_Occurred())
|
||||||
{
|
{
|
||||||
log_err("pythonmod: Exception occurred in function operate, event: %s", strmodulevent(event));
|
log_err("pythonmod: Exception occurred in function operate, event: %s", strmodulevent(event));
|
||||||
PyErr_Print();
|
log_py_err();
|
||||||
qstate->ext_state[id] = module_error;
|
qstate->ext_state[id] = module_error;
|
||||||
}
|
}
|
||||||
else if ((res == NULL) || (!PyObject_IsTrue(res)))
|
else if ((res == NULL) || (!PyObject_IsTrue(res)))
|
||||||
|
|
|
||||||
6
testdata/pylib.tdir/pylib.test
vendored
6
testdata/pylib.tdir/pylib.test
vendored
|
|
@ -19,9 +19,13 @@ fi
|
||||||
#echo export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:../../.libs:."
|
#echo export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:../../.libs:."
|
||||||
#export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:../../.libs:."
|
#export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:../../.libs:."
|
||||||
|
|
||||||
|
if grep "PY_MAJOR_VERSION=3" $PRE/Makefile; then
|
||||||
|
PYTHON="python3"; else PYTHON="python2"; fi
|
||||||
|
if test ! -x `which $PYTHON` 2>&1; then PYTHON="python"; fi
|
||||||
|
|
||||||
# do the test
|
# do the test
|
||||||
echo "> pylib.lookup.py www.example.com."
|
echo "> pylib.lookup.py www.example.com."
|
||||||
./pylib.lookup.py www.example.com. | tee outfile
|
$PYTHON pylib.lookup.py www.example.com. | tee outfile
|
||||||
|
|
||||||
echo "> cat logfiles"
|
echo "> cat logfiles"
|
||||||
cat fwd.log
|
cat fwd.log
|
||||||
|
|
|
||||||
36
testdata/pymod.tdir/pymod.py
vendored
36
testdata/pymod.tdir/pymod.py
vendored
|
|
@ -59,12 +59,15 @@ def setTTL(qstate, ttl):
|
||||||
|
|
||||||
def dataHex(data, prefix=""):
|
def dataHex(data, prefix=""):
|
||||||
res = ""
|
res = ""
|
||||||
for i in range(0, (len(data)+15)/16):
|
for i in range(0, int((len(data)+15)/16)):
|
||||||
res += "%s0x%02X | " % (prefix, i*16)
|
res += "%s0x%02X | " % (prefix, i*16)
|
||||||
|
if type(data[0]) == type(1):
|
||||||
|
d = map(lambda x:int(x), data[i*16:i*16+17])
|
||||||
|
else:
|
||||||
d = map(lambda x:ord(x), data[i*16:i*16+17])
|
d = map(lambda x:ord(x), data[i*16:i*16+17])
|
||||||
for ch in d:
|
for ch in d:
|
||||||
res += "%02X " % ch
|
res += "%02X " % ch
|
||||||
for i in range(0,17-len(d)):
|
for i in range(0,17-len(data[i*16:i*16+17])):
|
||||||
res += " "
|
res += " "
|
||||||
res += "| "
|
res += "| "
|
||||||
for ch in d:
|
for ch in d:
|
||||||
|
|
@ -76,35 +79,35 @@ def dataHex(data, prefix=""):
|
||||||
return res
|
return res
|
||||||
|
|
||||||
def printReturnMsg(qstate):
|
def printReturnMsg(qstate):
|
||||||
print "Return MSG rep :: flags: %04X, QDcount: %d, Security:%d, TTL=%d" % (qstate.return_msg.rep.flags, qstate.return_msg.rep.qdcount,qstate.return_msg.rep.security, qstate.return_msg.rep.ttl)
|
print ("Return MSG rep :: flags: %04X, QDcount: %d, Security:%d, TTL=%d" % (qstate.return_msg.rep.flags, qstate.return_msg.rep.qdcount, qstate.return_msg.rep.security, qstate.return_msg.rep.ttl))
|
||||||
print " qinfo :: qname:",qstate.return_msg.qinfo.qname_list, qstate.return_msg.qinfo.qname_str, "type:",qstate.return_msg.qinfo.qtype_str, "class:",qstate.return_msg.qinfo.qclass_str
|
print (" qinfo :: qname:",qstate.return_msg.qinfo.qname_list, qstate.return_msg.qinfo.qname_str, "type:",qstate.return_msg.qinfo.qtype_str, "class:",qstate.return_msg.qinfo.qclass_str)
|
||||||
if (qstate.return_msg.rep):
|
if (qstate.return_msg.rep):
|
||||||
print "RRSets:",qstate.return_msg.rep.rrset_count
|
print ("RRSets:",qstate.return_msg.rep.rrset_count)
|
||||||
prevkey = None
|
prevkey = None
|
||||||
for i in range(0,qstate.return_msg.rep.rrset_count):
|
for i in range(0,qstate.return_msg.rep.rrset_count):
|
||||||
r = qstate.return_msg.rep.rrsets[i]
|
r = qstate.return_msg.rep.rrsets[i]
|
||||||
rk = r.rk
|
rk = r.rk
|
||||||
print i,":",rk.dname_list, rk.dname_str, "flags: %04X" % rk.flags,
|
print (i,":",rk.dname_list, rk.dname_str, "flags: %04X" % rk.flags)
|
||||||
print "type:",rk.type_str,"(%d)" % ntohs(rk.type), "class:",rk.rrset_class_str,"(%d)" % ntohs(rk.rrset_class)
|
print ("type:",rk.type_str,"(%d)" % ntohs(rk.type), "class:",rk.rrset_class_str,"(%d)" % ntohs(rk.rrset_class))
|
||||||
|
|
||||||
d = r.entry.data
|
d = r.entry.data
|
||||||
print " RRDatas:",d.count+d.rrsig_count
|
print (" RRDatas:",d.count+d.rrsig_count)
|
||||||
for j in range(0,d.count+d.rrsig_count):
|
for j in range(0,d.count+d.rrsig_count):
|
||||||
print " ",j,":","TTL=",d.rr_ttl[j],"RR data:"
|
print (" ",j,":","TTL=",d.rr_ttl[j],"RR data:")
|
||||||
print dataHex(d.rr_data[j]," ")
|
print (dataHex(d.rr_data[j]," "))
|
||||||
|
|
||||||
|
|
||||||
def operate(id, event, qstate, qdata):
|
def operate(id, event, qstate, qdata):
|
||||||
log_info("pythonmod: operate called, id: %d, event:%s" % (id, strmodulevent(event)))
|
log_info("pythonmod: operate called, id: %d, event:%s" % (id, strmodulevent(event)))
|
||||||
#print "pythonmod: per query data", qdata
|
#print ("pythonmod: per query data", qdata)
|
||||||
|
|
||||||
print "Query:", ''.join(map(lambda x:chr(max(32,ord(x))),qstate.qinfo.qname)), qstate.qinfo.qname_list, qstate.qinfo.qname_str,
|
print ("Query:", qstate.qinfo.qname, qstate.qinfo.qname_list, qstate.qinfo.qname_str)
|
||||||
print "Type:",qstate.qinfo.qtype_str,"(%d)" % qstate.qinfo.qtype,
|
print ("Type:",qstate.qinfo.qtype_str,"(%d)" % qstate.qinfo.qtype)
|
||||||
print "Class:",qstate.qinfo.qclass_str,"(%d)" % qstate.qinfo.qclass
|
print ("Class:",qstate.qinfo.qclass_str,"(%d)" % qstate.qinfo.qclass)
|
||||||
print
|
print ()
|
||||||
|
|
||||||
if (event == MODULE_EVENT_NEW or event == MODULE_EVENT_PASS) and (qstate.qinfo.qname_str.endswith("www2.example.com.")):
|
if (event == MODULE_EVENT_NEW or event == MODULE_EVENT_PASS) and (qstate.qinfo.qname_str.endswith("www2.example.com.")):
|
||||||
print qstate.qinfo.qname_str
|
print (qstate.qinfo.qname_str)
|
||||||
|
|
||||||
qstate.ext_state[id] = MODULE_FINISHED
|
qstate.ext_state[id] = MODULE_FINISHED
|
||||||
|
|
||||||
|
|
@ -121,6 +124,7 @@ def operate(id, event, qstate, qdata):
|
||||||
if (qstate.qinfo.qtype == RR_TYPE_TXT) or (qstate.qinfo.qtype == RR_TYPE_ANY):
|
if (qstate.qinfo.qtype == RR_TYPE_TXT) or (qstate.qinfo.qtype == RR_TYPE_ANY):
|
||||||
msg.answer.append("%s 10 IN TXT path=/" % qstate.qinfo.qname_str)
|
msg.answer.append("%s 10 IN TXT path=/" % qstate.qinfo.qname_str)
|
||||||
|
|
||||||
|
print(msg.answer)
|
||||||
if not msg.set_return_msg(qstate):
|
if not msg.set_return_msg(qstate):
|
||||||
qstate.ext_state[id] = MODULE_ERROR
|
qstate.ext_state[id] = MODULE_ERROR
|
||||||
return True
|
return True
|
||||||
|
|
|
||||||
37
testdata/pymod_thread.tdir/pymod_thread.py
vendored
37
testdata/pymod_thread.tdir/pymod_thread.py
vendored
|
|
@ -59,12 +59,15 @@ def setTTL(qstate, ttl):
|
||||||
|
|
||||||
def dataHex(data, prefix=""):
|
def dataHex(data, prefix=""):
|
||||||
res = ""
|
res = ""
|
||||||
for i in range(0, (len(data)+15)/16):
|
for i in range(0, int((len(data)+15)/16)):
|
||||||
res += "%s0x%02X | " % (prefix, i*16)
|
res += "%s0x%02X | " % (prefix, i*16)
|
||||||
|
if type(data[0]) == type(1):
|
||||||
|
d = map(lambda x:int(x), data[i*16:i*16+17])
|
||||||
|
else:
|
||||||
d = map(lambda x:ord(x), data[i*16:i*16+17])
|
d = map(lambda x:ord(x), data[i*16:i*16+17])
|
||||||
for ch in d:
|
for ch in d:
|
||||||
res += "%02X " % ch
|
res += "%02X " % int(ch)
|
||||||
for i in range(0,17-len(d)):
|
for i in range(0,17-len(data[i*16:i*16+17])):
|
||||||
res += " "
|
res += " "
|
||||||
res += "| "
|
res += "| "
|
||||||
for ch in d:
|
for ch in d:
|
||||||
|
|
@ -76,35 +79,35 @@ def dataHex(data, prefix=""):
|
||||||
return res
|
return res
|
||||||
|
|
||||||
def printReturnMsg(qstate):
|
def printReturnMsg(qstate):
|
||||||
print "Return MSG rep :: flags: %04X, QDcount: %d, Security:%d, TTL=%d" % (qstate.return_msg.rep.flags, qstate.return_msg.rep.qdcount,qstate.return_msg.rep.security, qstate.return_msg.rep.ttl)
|
print ("Return MSG rep :: flags: %04X, QDcount: %d, Security:%d, TTL=%d" % (qstate.return_msg.rep.flags, qstate.return_msg.rep.qdcount, qstate.return_msg.rep.security, qstate.return_msg.rep.ttl))
|
||||||
print " qinfo :: qname:",qstate.return_msg.qinfo.qname_list, qstate.return_msg.qinfo.qname_str, "type:",qstate.return_msg.qinfo.qtype_str, "class:",qstate.return_msg.qinfo.qclass_str
|
print (" qinfo :: qname:",qstate.return_msg.qinfo.qname_list, qstate.return_msg.qinfo.qname_str, "type:",qstate.return_msg.qinfo.qtype_str, "class:",qstate.return_msg.qinfo.qclass_str)
|
||||||
if (qstate.return_msg.rep):
|
if (qstate.return_msg.rep):
|
||||||
print "RRSets:",qstate.return_msg.rep.rrset_count
|
print ("RRSets:",qstate.return_msg.rep.rrset_count)
|
||||||
prevkey = None
|
prevkey = None
|
||||||
for i in range(0,qstate.return_msg.rep.rrset_count):
|
for i in range(0,qstate.return_msg.rep.rrset_count):
|
||||||
r = qstate.return_msg.rep.rrsets[i]
|
r = qstate.return_msg.rep.rrsets[i]
|
||||||
rk = r.rk
|
rk = r.rk
|
||||||
print i,":",rk.dname_list, rk.dname_str, "flags: %04X" % rk.flags,
|
print (i,":",rk.dname_list, rk.dname_str, "flags: %04X" % rk.flags)
|
||||||
print "type:",rk.type_str,"(%d)" % ntohs(rk.type), "class:",rk.rrset_class_str,"(%d)" % ntohs(rk.rrset_class)
|
print ("type:",rk.type_str,"(%d)" % ntohs(rk.type), "class:",rk.rrset_class_str,"(%d)" % ntohs(rk.rrset_class))
|
||||||
|
|
||||||
d = r.entry.data
|
d = r.entry.data
|
||||||
print " RRDatas:",d.count+d.rrsig_count
|
print (" RRDatas:",d.count+d.rrsig_count)
|
||||||
for j in range(0,d.count+d.rrsig_count):
|
for j in range(0,d.count+d.rrsig_count):
|
||||||
print " ",j,":","TTL=",d.rr_ttl[j],"RR data:"
|
print (" ",j,":","TTL=",d.rr_ttl[j],"RR data:")
|
||||||
print dataHex(d.rr_data[j]," ")
|
print (dataHex(d.rr_data[j]," "))
|
||||||
|
|
||||||
|
|
||||||
def operate(id, event, qstate, qdata):
|
def operate(id, event, qstate, qdata):
|
||||||
log_info("pythonmod: operate called, id: %d, event:%s" % (id, strmodulevent(event)))
|
log_info("pythonmod: operate called, id: %d, event:%s" % (id, strmodulevent(event)))
|
||||||
#print "pythonmod: per query data", qdata
|
#print ("pythonmod: per query data", qdata)
|
||||||
|
|
||||||
print "Query:", ''.join(map(lambda x:chr(max(32,ord(x))),qstate.qinfo.qname)), qstate.qinfo.qname_list, qstate.qinfo.qname_str,
|
print ("Query:", qstate.qinfo.qname, qstate.qinfo.qname_list, qstate.qinfo.qname_str)
|
||||||
print "Type:",qstate.qinfo.qtype_str,"(%d)" % qstate.qinfo.qtype,
|
print ("Type:",qstate.qinfo.qtype_str,"(%d)" % qstate.qinfo.qtype)
|
||||||
print "Class:",qstate.qinfo.qclass_str,"(%d)" % qstate.qinfo.qclass
|
print ("Class:",qstate.qinfo.qclass_str,"(%d)" % qstate.qinfo.qclass)
|
||||||
print
|
print ()
|
||||||
|
|
||||||
if (event == MODULE_EVENT_NEW or event == MODULE_EVENT_PASS) and (qstate.qinfo.qname_str.endswith("example.com.")):
|
if (event == MODULE_EVENT_NEW or event == MODULE_EVENT_PASS) and (qstate.qinfo.qname_str.endswith("example.com.")):
|
||||||
print qstate.qinfo.qname_str
|
print (qstate.qinfo.qname_str)
|
||||||
|
|
||||||
qstate.ext_state[id] = MODULE_FINISHED
|
qstate.ext_state[id] = MODULE_FINISHED
|
||||||
|
|
||||||
|
|
|
||||||
80
testdata/pymod_thread.tdir/pymod_thread.testns
vendored
80
testdata/pymod_thread.tdir/pymod_thread.testns
vendored
|
|
@ -22,3 +22,83 @@ SECTION ANSWER
|
||||||
www2 IN A 10.20.30.40
|
www2 IN A 10.20.30.40
|
||||||
ENTRY_END
|
ENTRY_END
|
||||||
|
|
||||||
|
ENTRY_BEGIN
|
||||||
|
MATCH opcode qtype qname
|
||||||
|
REPLY QR AA NOERROR
|
||||||
|
ADJUST copy_id
|
||||||
|
SECTION QUESTION
|
||||||
|
www3 IN A
|
||||||
|
SECTION ANSWER
|
||||||
|
www3 IN A 10.20.30.40
|
||||||
|
ENTRY_END
|
||||||
|
|
||||||
|
ENTRY_BEGIN
|
||||||
|
MATCH opcode qtype qname
|
||||||
|
REPLY QR AA NOERROR
|
||||||
|
ADJUST copy_id
|
||||||
|
SECTION QUESTION
|
||||||
|
www4 IN A
|
||||||
|
SECTION ANSWER
|
||||||
|
www4 IN A 10.20.30.40
|
||||||
|
ENTRY_END
|
||||||
|
|
||||||
|
ENTRY_BEGIN
|
||||||
|
MATCH opcode qtype qname
|
||||||
|
REPLY QR AA NOERROR
|
||||||
|
ADJUST copy_id
|
||||||
|
SECTION QUESTION
|
||||||
|
www5 IN A
|
||||||
|
SECTION ANSWER
|
||||||
|
www5 IN A 10.20.30.40
|
||||||
|
ENTRY_END
|
||||||
|
|
||||||
|
ENTRY_BEGIN
|
||||||
|
MATCH opcode qtype qname
|
||||||
|
REPLY QR AA NXDOMAIN
|
||||||
|
ADJUST copy_id
|
||||||
|
SECTION QUESTION
|
||||||
|
www6 IN A
|
||||||
|
SECTION AUTHORITY
|
||||||
|
example.com. 3600 IN SOA a. b. 2018100719 7200 3600 1209600 3600
|
||||||
|
ENTRY_END
|
||||||
|
|
||||||
|
ENTRY_BEGIN
|
||||||
|
MATCH opcode qtype qname
|
||||||
|
REPLY QR AA NXDOMAIN
|
||||||
|
ADJUST copy_id
|
||||||
|
SECTION QUESTION
|
||||||
|
www7 IN A
|
||||||
|
SECTION AUTHORITY
|
||||||
|
example.com. 3600 IN SOA a. b. 2018100719 7200 3600 1209600 3600
|
||||||
|
ENTRY_END
|
||||||
|
|
||||||
|
ENTRY_BEGIN
|
||||||
|
MATCH opcode qtype qname
|
||||||
|
REPLY QR AA NXDOMAIN
|
||||||
|
ADJUST copy_id
|
||||||
|
SECTION QUESTION
|
||||||
|
www8 IN A
|
||||||
|
SECTION AUTHORITY
|
||||||
|
example.com. 3600 IN SOA a. b. 2018100719 7200 3600 1209600 3600
|
||||||
|
ENTRY_END
|
||||||
|
|
||||||
|
ENTRY_BEGIN
|
||||||
|
MATCH opcode qtype qname
|
||||||
|
REPLY QR AA NXDOMAIN
|
||||||
|
ADJUST copy_id
|
||||||
|
SECTION QUESTION
|
||||||
|
www9 IN A
|
||||||
|
SECTION AUTHORITY
|
||||||
|
example.com. 3600 IN SOA a. b. 2018100719 7200 3600 1209600 3600
|
||||||
|
ENTRY_END
|
||||||
|
|
||||||
|
ENTRY_BEGIN
|
||||||
|
MATCH opcode qtype qname
|
||||||
|
REPLY QR AA NXDOMAIN
|
||||||
|
ADJUST copy_id
|
||||||
|
SECTION QUESTION
|
||||||
|
www10 IN A
|
||||||
|
SECTION AUTHORITY
|
||||||
|
example.com. 3600 IN SOA a. b. 2018100719 7200 3600 1209600 3600
|
||||||
|
ENTRY_END
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue