message_python.cc 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848
  1. // Copyright (C) 2010 Internet Systems Consortium, Inc. ("ISC")
  2. //
  3. // Permission to use, copy, modify, and/or distribute this software for any
  4. // purpose with or without fee is hereby granted, provided that the above
  5. // copyright notice and this permission notice appear in all copies.
  6. //
  7. // THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
  8. // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  9. // AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
  10. // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  11. // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  12. // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  13. // PERFORMANCE OF THIS SOFTWARE.
  14. #define PY_SSIZE_T_CLEAN
  15. #include <Python.h>
  16. #include <exceptions/exceptions.h>
  17. #include <util/python/pycppwrapper_util.h>
  18. #include <dns/message.h>
  19. #include <dns/rcode.h>
  20. #include <dns/tsig.h>
  21. #include <dns/exceptions.h>
  22. #include <dns/messagerenderer.h>
  23. #include "name_python.h"
  24. #include "question_python.h"
  25. #include "edns_python.h"
  26. #include "rcode_python.h"
  27. #include "opcode_python.h"
  28. #include "rrset_python.h"
  29. #include "message_python.h"
  30. #include "messagerenderer_python.h"
  31. #include "tsig_python.h"
  32. #include "tsigrecord_python.h"
  33. #include "pydnspp_common.h"
  34. using namespace std;
  35. using namespace isc::dns;
  36. using namespace isc::dns::python;
  37. using namespace isc::util;
  38. using namespace isc::util::python;
  39. // Import pydoc text
  40. #include "message_python_inc.cc"
  41. namespace {
  42. class s_Message : public PyObject {
  43. public:
  44. isc::dns::Message* cppobj;
  45. };
  46. int Message_init(s_Message* self, PyObject* args);
  47. void Message_destroy(s_Message* self);
  48. PyObject* Message_getHeaderFlag(s_Message* self, PyObject* args);
  49. PyObject* Message_setHeaderFlag(s_Message* self, PyObject* args);
  50. PyObject* Message_getQid(s_Message* self);
  51. PyObject* Message_setQid(s_Message* self, PyObject* args);
  52. PyObject* Message_getRcode(s_Message* self);
  53. PyObject* Message_setRcode(s_Message* self, PyObject* args);
  54. PyObject* Message_getOpcode(s_Message* self);
  55. PyObject* Message_setOpcode(s_Message* self, PyObject* args);
  56. PyObject* Message_getEDNS(s_Message* self);
  57. PyObject* Message_setEDNS(s_Message* self, PyObject* args);
  58. PyObject* Message_getTSIGRecord(s_Message* self);
  59. PyObject* Message_getRRCount(s_Message* self, PyObject* args);
  60. // use direct iterators for these? (or simply lists for now?)
  61. PyObject* Message_getQuestion(PyObject* self, PyObject*);
  62. PyObject* Message_getSection(PyObject* self, PyObject* args);
  63. //static PyObject* Message_beginQuestion(s_Message* self, PyObject* args);
  64. //static PyObject* Message_endQuestion(s_Message* self, PyObject* args);
  65. //static PyObject* Message_beginSection(s_Message* self, PyObject* args);
  66. //static PyObject* Message_endSection(s_Message* self, PyObject* args);
  67. PyObject* Message_addQuestion(s_Message* self, PyObject* args);
  68. PyObject* Message_addRRset(s_Message* self, PyObject* args);
  69. PyObject* Message_clear(s_Message* self, PyObject* args);
  70. PyObject* Message_clearSection(PyObject* pyself, PyObject* args);
  71. PyObject* Message_makeResponse(s_Message* self);
  72. PyObject* Message_toText(s_Message* self);
  73. PyObject* Message_str(PyObject* self);
  74. PyObject* Message_toWire(s_Message* self, PyObject* args);
  75. PyObject* Message_fromWire(PyObject* pyself, PyObject* args);
  76. // This list contains the actual set of functions we have in
  77. // python. Each entry has
  78. // 1. Python method name
  79. // 2. Our static function here
  80. // 3. Argument type
  81. // 4. Documentation
  82. PyMethodDef Message_methods[] = {
  83. { "get_header_flag", reinterpret_cast<PyCFunction>(Message_getHeaderFlag),
  84. METH_VARARGS,
  85. "Return whether the specified header flag bit is set in the "
  86. "header section. Takes a MessageFlag object as the only argument." },
  87. { "set_header_flag",
  88. reinterpret_cast<PyCFunction>(Message_setHeaderFlag), METH_VARARGS,
  89. "Sets the specified header flag bit to 1. The message must be in "
  90. "RENDER mode. If not, an InvalidMessageOperation is raised. "
  91. "Takes a MessageFlag object as the only argument." },
  92. { "get_qid", reinterpret_cast<PyCFunction>(Message_getQid), METH_NOARGS,
  93. "Returns the query id" },
  94. { "set_qid", reinterpret_cast<PyCFunction>(Message_setQid), METH_VARARGS,
  95. "Sets the query id. If the message is not in RENDER mode, an "
  96. "InvalidMessageOperation is raised.\n"
  97. "The argument must be an integer" },
  98. { "get_rcode", reinterpret_cast<PyCFunction>(Message_getRcode), METH_NOARGS,
  99. "Returns the message Response code (an Rcode object)" },
  100. { "set_rcode", reinterpret_cast<PyCFunction>(Message_setRcode), METH_VARARGS,
  101. "Sets the message Response code (an Rcode object).\n"
  102. "If the message is not in RENDER mode, an "
  103. "InvalidMessageOperation is raised."},
  104. { "get_opcode", reinterpret_cast<PyCFunction>(Message_getOpcode), METH_NOARGS,
  105. "Returns the message opcode (an Opcode object)" },
  106. { "set_opcode", reinterpret_cast<PyCFunction>(Message_setOpcode), METH_VARARGS,
  107. "Sets the message opcode (an Opcode object).\n"
  108. "If the message is not in RENDER mode, an "
  109. "InvalidMessageOperation is raised."},
  110. { "get_edns", reinterpret_cast<PyCFunction>(Message_getEDNS), METH_NOARGS,
  111. "Return, if any, the EDNS associated with the message."
  112. },
  113. { "set_edns", reinterpret_cast<PyCFunction>(Message_setEDNS), METH_VARARGS,
  114. "Set EDNS for the message."
  115. },
  116. { "get_tsig_record",
  117. reinterpret_cast<PyCFunction>(Message_getTSIGRecord), METH_NOARGS,
  118. "Return, if any, the TSIG record contained in the received message. "
  119. "If no TSIG RR is set in the message, None will be returned."
  120. },
  121. { "get_rr_count", reinterpret_cast<PyCFunction>(Message_getRRCount), METH_VARARGS,
  122. "Returns the number of RRs contained in the given section." },
  123. { "get_question", Message_getQuestion, METH_NOARGS,
  124. "Returns a list of all Question objects in the message "
  125. "(should be either 0 or 1)" },
  126. { "get_section", Message_getSection, METH_VARARGS,
  127. "Returns a list of all RRset objects in the given section of the message\n"
  128. "The argument must be of type Section" },
  129. { "add_question", reinterpret_cast<PyCFunction>(Message_addQuestion), METH_VARARGS,
  130. "Add a Question to the message."
  131. "If the message is not in RENDER mode, an "
  132. "InvalidMessageOperation is raised."},
  133. { "add_rrset", reinterpret_cast<PyCFunction>(Message_addRRset), METH_VARARGS,
  134. "Add an RRset to the given section of the message.\n"
  135. "The first argument is of type Section\n"
  136. "The second is of type RRset"},
  137. { "clear", reinterpret_cast<PyCFunction>(Message_clear), METH_VARARGS,
  138. "Clears the message content (if any) and reinitialize the "
  139. "message in the given mode\n"
  140. "The argument must be either Message.PARSE or Message.RENDER"},
  141. { "clear_section", Message_clearSection, METH_VARARGS,
  142. Message_clearSection_doc },
  143. { "make_response", reinterpret_cast<PyCFunction>(Message_makeResponse), METH_NOARGS,
  144. "Prepare for making a response from a request.\n"
  145. "This will clear the DNS header except those fields that should be kept "
  146. "for the response, and clear answer and the following sections. "
  147. "See also dns_message_reply() of BIND9."},
  148. { "to_text", reinterpret_cast<PyCFunction>(Message_toText), METH_NOARGS,
  149. "Returns the string representation of the message" },
  150. { "to_wire", reinterpret_cast<PyCFunction>(Message_toWire), METH_VARARGS,
  151. "Render the message in wire format.\n"
  152. "The argument must be a MessageRenderer.\n"
  153. "If the given message is not in RENDER mode, an "
  154. "InvalidMessageOperation is raised.\n"
  155. },
  156. { "from_wire", Message_fromWire, METH_VARARGS, Message_fromWire_doc },
  157. { NULL, NULL, 0, NULL }
  158. };
  159. int
  160. Message_init(s_Message* self, PyObject* args) {
  161. int i;
  162. if (PyArg_ParseTuple(args, "i", &i)) {
  163. PyErr_Clear();
  164. if (i == Message::PARSE) {
  165. self->cppobj = new Message(Message::PARSE);
  166. return (0);
  167. } else if (i == Message::RENDER) {
  168. self->cppobj = new Message(Message::RENDER);
  169. return (0);
  170. } else {
  171. PyErr_SetString(PyExc_TypeError, "Message mode must be Message.PARSE or Message.RENDER");
  172. return (-1);
  173. }
  174. }
  175. PyErr_Clear();
  176. PyErr_SetString(PyExc_TypeError,
  177. "no valid type in constructor argument");
  178. return (-1);
  179. }
  180. void
  181. Message_destroy(s_Message* self) {
  182. delete self->cppobj;
  183. self->cppobj = NULL;
  184. Py_TYPE(self)->tp_free(self);
  185. }
  186. PyObject*
  187. Message_getHeaderFlag(s_Message* self, PyObject* args) {
  188. unsigned int messageflag;
  189. if (!PyArg_ParseTuple(args, "I", &messageflag)) {
  190. PyErr_Clear();
  191. PyErr_SetString(PyExc_TypeError,
  192. "no valid type in get_header_flag argument");
  193. return (NULL);
  194. }
  195. try {
  196. if (self->cppobj->getHeaderFlag(
  197. static_cast<Message::HeaderFlag>(messageflag))) {
  198. Py_RETURN_TRUE;
  199. } else {
  200. Py_RETURN_FALSE;
  201. }
  202. } catch (const isc::InvalidParameter& ip) {
  203. PyErr_Clear();
  204. PyErr_SetString(po_InvalidParameter, ip.what());
  205. } catch (const exception& ex) {
  206. const string ex_what = "Error in Message.get_header_flag(): " + string(ex.what());
  207. PyErr_SetString(po_IscException, ex_what.c_str());
  208. } catch (...) {
  209. PyErr_SetString(po_IscException,
  210. "Unexpected exception in Message.get_header_flag()");
  211. }
  212. return (NULL);
  213. }
  214. PyObject*
  215. Message_setHeaderFlag(s_Message* self, PyObject* args) {
  216. long messageflag;
  217. PyObject *on = Py_True;
  218. if (!PyArg_ParseTuple(args, "l|O!", &messageflag, &PyBool_Type, &on)) {
  219. PyErr_Clear();
  220. PyErr_SetString(PyExc_TypeError,
  221. "no valid type in set_header_flag argument");
  222. return (NULL);
  223. }
  224. if (messageflag < 0 || messageflag > 0xffff) {
  225. PyErr_SetString(PyExc_ValueError, "Message header flag out of range");
  226. return (NULL);
  227. }
  228. try {
  229. self->cppobj->setHeaderFlag(
  230. static_cast<Message::HeaderFlag>(messageflag), on == Py_True);
  231. Py_RETURN_NONE;
  232. } catch (const InvalidMessageOperation& imo) {
  233. PyErr_Clear();
  234. PyErr_SetString(po_InvalidMessageOperation, imo.what());
  235. } catch (const isc::InvalidParameter& ip) {
  236. PyErr_Clear();
  237. PyErr_SetString(po_InvalidParameter, ip.what());
  238. } catch (const exception& ex) {
  239. const string ex_what = "Error in Message.set_header_flag(): " + string(ex.what());
  240. PyErr_SetString(po_IscException, ex_what.c_str());
  241. } catch (...) {
  242. PyErr_SetString(po_IscException,
  243. "Unexpected exception in Message.set_header_flag()");
  244. }
  245. return (NULL);
  246. }
  247. PyObject*
  248. Message_getQid(s_Message* self) {
  249. return (Py_BuildValue("I", self->cppobj->getQid()));
  250. }
  251. PyObject*
  252. Message_setQid(s_Message* self, PyObject* args) {
  253. long id;
  254. if (!PyArg_ParseTuple(args, "l", &id)) {
  255. PyErr_Clear();
  256. PyErr_SetString(PyExc_TypeError,
  257. "no valid type in set_qid argument");
  258. return (NULL);
  259. }
  260. if (id < 0 || id > 0xffff) {
  261. PyErr_SetString(PyExc_ValueError,
  262. "Message id out of range");
  263. return (NULL);
  264. }
  265. try {
  266. self->cppobj->setQid(id);
  267. Py_RETURN_NONE;
  268. } catch (const InvalidMessageOperation& imo) {
  269. PyErr_SetString(po_InvalidMessageOperation, imo.what());
  270. } catch (const exception& ex) {
  271. const string ex_what = "Error in Message.get_qid(): " + string(ex.what());
  272. PyErr_SetString(po_IscException, ex_what.c_str());
  273. } catch (...) {
  274. PyErr_SetString(po_IscException,
  275. "Unexpected exception in Message.set_qid()");
  276. }
  277. return (NULL);
  278. }
  279. PyObject*
  280. Message_getRcode(s_Message* self) {
  281. try {
  282. return (createRcodeObject(self->cppobj->getRcode()));
  283. } catch (const InvalidMessageOperation& imo) {
  284. PyErr_SetString(po_InvalidMessageOperation, imo.what());
  285. } catch (const exception& ex) {
  286. const string ex_what = "Error in Message.get_rcode(): " + string(ex.what());
  287. PyErr_SetString(po_IscException, ex_what.c_str());
  288. } catch (...) {
  289. PyErr_SetString(po_IscException,
  290. "Unexpected exception in Message.get_rcode()");
  291. }
  292. return (NULL);
  293. }
  294. PyObject*
  295. Message_setRcode(s_Message* self, PyObject* args) {
  296. PyObject* rcode;
  297. if (!PyArg_ParseTuple(args, "O!", &rcode_type, &rcode)) {
  298. return (NULL);
  299. }
  300. try {
  301. self->cppobj->setRcode(PyRcode_ToRcode(rcode));
  302. Py_RETURN_NONE;
  303. } catch (const InvalidMessageOperation& imo) {
  304. PyErr_SetString(po_InvalidMessageOperation, imo.what());
  305. } catch (const exception& ex) {
  306. const string ex_what = "Error in Message.set_rcode(): " + string(ex.what());
  307. PyErr_SetString(po_IscException, ex_what.c_str());
  308. } catch (...) {
  309. PyErr_SetString(po_IscException,
  310. "Unexpected exception in Message.set_rcode()");
  311. }
  312. return (NULL);
  313. }
  314. PyObject*
  315. Message_getOpcode(s_Message* self) {
  316. try {
  317. return (createOpcodeObject(self->cppobj->getOpcode()));
  318. } catch (const InvalidMessageOperation& imo) {
  319. PyErr_SetString(po_InvalidMessageOperation, imo.what());
  320. } catch (const exception& ex) {
  321. const string ex_what = "Error in Message.get_opcode(): " + string(ex.what());
  322. PyErr_SetString(po_IscException, ex_what.c_str());
  323. } catch (...) {
  324. PyErr_SetString(po_IscException,
  325. "Unexpected exception in Message.get_opcode()");
  326. }
  327. return (NULL);
  328. }
  329. PyObject*
  330. Message_setOpcode(s_Message* self, PyObject* args) {
  331. PyObject* opcode;
  332. if (!PyArg_ParseTuple(args, "O!", &opcode_type, &opcode)) {
  333. return (NULL);
  334. }
  335. try {
  336. self->cppobj->setOpcode(PyOpcode_ToOpcode(opcode));
  337. Py_RETURN_NONE;
  338. } catch (const InvalidMessageOperation& imo) {
  339. PyErr_SetString(po_InvalidMessageOperation, imo.what());
  340. } catch (const exception& ex) {
  341. const string ex_what = "Error in Message.set_opcode(): " + string(ex.what());
  342. PyErr_SetString(po_IscException, ex_what.c_str());
  343. } catch (...) {
  344. PyErr_SetString(po_IscException,
  345. "Unexpected exception in Message.set_opcode()");
  346. }
  347. return (NULL);
  348. }
  349. PyObject*
  350. Message_getEDNS(s_Message* self) {
  351. ConstEDNSPtr src = self->cppobj->getEDNS();
  352. if (!src) {
  353. Py_RETURN_NONE;
  354. }
  355. try {
  356. return (createEDNSObject(*src));
  357. } catch (const exception& ex) {
  358. const string ex_what = "Error in Message.get_edns(): " + string(ex.what());
  359. PyErr_SetString(po_IscException, ex_what.c_str());
  360. } catch (...) {
  361. PyErr_SetString(PyExc_SystemError,
  362. "Unexpected exception in Message.get_edns()");
  363. }
  364. return (NULL);
  365. }
  366. PyObject*
  367. Message_setEDNS(s_Message* self, PyObject* args) {
  368. PyObject* edns;
  369. if (!PyArg_ParseTuple(args, "O!", &edns_type, &edns)) {
  370. return (NULL);
  371. }
  372. try {
  373. self->cppobj->setEDNS(EDNSPtr(new EDNS(PyEDNS_ToEDNS(edns))));
  374. Py_RETURN_NONE;
  375. } catch (const InvalidMessageOperation& imo) {
  376. PyErr_SetString(po_InvalidMessageOperation, imo.what());
  377. } catch (const exception& ex) {
  378. const string ex_what = "Error in Message.set_edns(): " + string(ex.what());
  379. PyErr_SetString(po_IscException, ex_what.c_str());
  380. } catch (...) {
  381. PyErr_SetString(po_IscException,
  382. "Unexpected exception in Message.set_edns()");
  383. }
  384. return (NULL);
  385. }
  386. PyObject*
  387. Message_getTSIGRecord(s_Message* self) {
  388. try {
  389. const TSIGRecord* tsig_record = self->cppobj->getTSIGRecord();
  390. if (tsig_record == NULL) {
  391. Py_RETURN_NONE;
  392. } else {
  393. return (createTSIGRecordObject(*tsig_record));
  394. }
  395. } catch (const InvalidMessageOperation& ex) {
  396. PyErr_SetString(po_InvalidMessageOperation, ex.what());
  397. } catch (const exception& ex) {
  398. const string ex_what = "Error in Message.get_tsig_record(): " + string(ex.what());
  399. PyErr_SetString(po_IscException, ex_what.c_str());
  400. } catch (...) {
  401. PyErr_SetString(po_IscException,
  402. "Unexpected exception in Message.get_tsig_record()");
  403. }
  404. return (NULL);
  405. }
  406. PyObject*
  407. Message_getRRCount(s_Message* self, PyObject* args) {
  408. unsigned int section;
  409. if (!PyArg_ParseTuple(args, "I", &section)) {
  410. PyErr_Clear();
  411. PyErr_SetString(PyExc_TypeError,
  412. "no valid type in get_rr_count argument");
  413. return (NULL);
  414. }
  415. try {
  416. return (Py_BuildValue("I", self->cppobj->getRRCount(
  417. static_cast<Message::Section>(section))));
  418. } catch (const isc::OutOfRange& ex) {
  419. PyErr_SetString(PyExc_OverflowError, ex.what());
  420. } catch (const exception& ex) {
  421. const string ex_what = "Error in Message.get_rr_count(): " + string(ex.what());
  422. PyErr_SetString(po_IscException, ex_what.c_str());
  423. } catch (...) {
  424. PyErr_SetString(po_IscException,
  425. "Unexpected exception in Message.get_rr_count()");
  426. }
  427. return (NULL);
  428. }
  429. // This is a helper templated class commonly used for getQuestion and
  430. // getSection in order to build a list of Message section items.
  431. template <typename ItemType, typename CreatorParamType>
  432. class SectionInserter {
  433. typedef PyObject* (*creator_t)(const CreatorParamType&);
  434. public:
  435. SectionInserter(PyObject* pylist, creator_t creator) :
  436. pylist_(pylist), creator_(creator)
  437. {}
  438. void operator()(ItemType item) {
  439. if (PyList_Append(pylist_, PyObjectContainer(creator_(*item)).get())
  440. == -1) {
  441. isc_throw(PyCPPWrapperException, "PyList_Append failed, "
  442. "probably due to short memory");
  443. }
  444. }
  445. private:
  446. PyObject* pylist_;
  447. creator_t creator_;
  448. };
  449. typedef SectionInserter<ConstQuestionPtr, Question> QuestionInserter;
  450. typedef SectionInserter<ConstRRsetPtr, AbstractRRset> RRsetInserter;
  451. // TODO use direct iterators for these? (or simply lists for now?)
  452. PyObject*
  453. Message_getQuestion(PyObject* po_self, PyObject*) {
  454. const s_Message* const self = static_cast<s_Message*>(po_self);
  455. try {
  456. PyObjectContainer list_container(PyList_New(0));
  457. for_each(self->cppobj->beginQuestion(),
  458. self->cppobj->endQuestion(),
  459. QuestionInserter(list_container.get(), createQuestionObject));
  460. return (list_container.release());
  461. } catch (const InvalidMessageSection& ex) {
  462. PyErr_SetString(po_InvalidMessageSection, ex.what());
  463. } catch (const exception& ex) {
  464. const string ex_what = "Error in Message.get_question(): " + string(ex.what());
  465. PyErr_SetString(po_IscException, ex_what.c_str());
  466. } catch (...) {
  467. PyErr_SetString(po_IscException,
  468. "Unexpected exception in Message.get_question()");
  469. }
  470. return (NULL);
  471. }
  472. PyObject*
  473. Message_getSection(PyObject* po_self, PyObject* args) {
  474. const s_Message* const self = static_cast<s_Message*>(po_self);
  475. unsigned int section;
  476. if (!PyArg_ParseTuple(args, "I", &section)) {
  477. PyErr_Clear();
  478. PyErr_SetString(PyExc_TypeError,
  479. "no valid type in get_section argument");
  480. return (NULL);
  481. }
  482. try {
  483. PyObjectContainer list_container(PyList_New(0));
  484. const Message::Section msgsection =
  485. static_cast<Message::Section>(section);
  486. for_each(self->cppobj->beginSection(msgsection),
  487. self->cppobj->endSection(msgsection),
  488. RRsetInserter(list_container.get(), createRRsetObject));
  489. return (list_container.release());
  490. } catch (const isc::OutOfRange& ex) {
  491. PyErr_SetString(PyExc_OverflowError, ex.what());
  492. } catch (const InvalidMessageSection& ex) {
  493. PyErr_SetString(po_InvalidMessageSection, ex.what());
  494. } catch (const exception& ex) {
  495. const string ex_what = "Error in Message.get_section(): " + string(ex.what());
  496. PyErr_SetString(po_IscException, ex_what.c_str());
  497. } catch (...) {
  498. PyErr_SetString(po_IscException,
  499. "Unexpected exception in Message.get_section()");
  500. }
  501. return (NULL);
  502. }
  503. //static PyObject* Message_beginQuestion(s_Message* self, PyObject* args);
  504. //static PyObject* Message_endQuestion(s_Message* self, PyObject* args);
  505. //static PyObject* Message_beginSection(s_Message* self, PyObject* args);
  506. //static PyObject* Message_endSection(s_Message* self, PyObject* args);
  507. //static PyObject* Message_addQuestion(s_Message* self, PyObject* args);
  508. PyObject*
  509. Message_addQuestion(s_Message* self, PyObject* args) {
  510. PyObject* question;
  511. if (!PyArg_ParseTuple(args, "O!", &question_type, &question)) {
  512. return (NULL);
  513. }
  514. try {
  515. self->cppobj->addQuestion(PyQuestion_ToQuestion(question));
  516. Py_RETURN_NONE;
  517. } catch (const InvalidMessageOperation& imo) {
  518. PyErr_Clear();
  519. PyErr_SetString(po_InvalidMessageOperation, imo.what());
  520. } catch (const exception& ex) {
  521. const string ex_what = "Error in Message.add_question(): " + string(ex.what());
  522. PyErr_SetString(po_IscException, ex_what.c_str());
  523. } catch (...) {
  524. PyErr_SetString(po_IscException,
  525. "Unexpected exception in Message.add_question()");
  526. }
  527. return (NULL);
  528. }
  529. PyObject*
  530. Message_addRRset(s_Message* self, PyObject* args) {
  531. int section;
  532. PyObject* rrset;
  533. if (!PyArg_ParseTuple(args, "iO!", &section, &rrset_type, &rrset)) {
  534. return (NULL);
  535. }
  536. try {
  537. self->cppobj->addRRset(static_cast<Message::Section>(section),
  538. PyRRset_ToRRsetPtr(rrset));
  539. Py_RETURN_NONE;
  540. } catch (const InvalidMessageOperation& imo) {
  541. PyErr_SetString(po_InvalidMessageOperation, imo.what());
  542. } catch (const isc::OutOfRange& ex) {
  543. PyErr_SetString(PyExc_OverflowError, ex.what());
  544. } catch (const exception& ex) {
  545. const string ex_what = "Error in Message.add_rrset(): " + string(ex.what());
  546. PyErr_SetString(po_IscException, ex_what.c_str());
  547. } catch (...) {
  548. PyErr_SetString(po_IscException,
  549. "Unexpected exception in Message.add_rrset()");
  550. }
  551. return (NULL);
  552. }
  553. PyObject*
  554. Message_clear(s_Message* self, PyObject* args) {
  555. int i;
  556. try {
  557. if (PyArg_ParseTuple(args, "i", &i)) {
  558. PyErr_Clear();
  559. if (i == Message::PARSE) {
  560. self->cppobj->clear(Message::PARSE);
  561. Py_RETURN_NONE;
  562. } else if (i == Message::RENDER) {
  563. self->cppobj->clear(Message::RENDER);
  564. Py_RETURN_NONE;
  565. } else {
  566. PyErr_SetString(PyExc_TypeError,
  567. "Message mode must be Message.PARSE or Message.RENDER");
  568. return (NULL);
  569. }
  570. }
  571. } catch (const exception& ex) {
  572. const string ex_what = "Error in Message.clear(): " + string(ex.what());
  573. PyErr_SetString(po_IscException, ex_what.c_str());
  574. } catch (...) {
  575. PyErr_SetString(po_IscException,
  576. "Unexpected exception in Message.clear()");
  577. }
  578. return (NULL);
  579. }
  580. PyObject*
  581. Message_clearSection(PyObject* pyself, PyObject* args) {
  582. s_Message* const self = static_cast<s_Message*>(pyself);
  583. int section;
  584. if (!PyArg_ParseTuple(args, "i", &section)) {
  585. return (NULL);
  586. }
  587. try {
  588. self->cppobj->clearSection(static_cast<Message::Section>(section));
  589. Py_RETURN_NONE;
  590. } catch (const InvalidMessageOperation& imo) {
  591. PyErr_SetString(po_InvalidMessageOperation, imo.what());
  592. } catch (const isc::OutOfRange& ex) {
  593. PyErr_SetString(PyExc_OverflowError, ex.what());
  594. } catch (const exception& ex) {
  595. const string ex_what = "Error in Message.clear_section(): " + string(ex.what());
  596. PyErr_SetString(po_IscException, ex_what.c_str());
  597. } catch (...) {
  598. PyErr_SetString(po_IscException,
  599. "Unexpected exception in Message.clear_section()");
  600. }
  601. return (NULL);
  602. }
  603. PyObject*
  604. Message_makeResponse(s_Message* self) {
  605. try {
  606. self->cppobj->makeResponse();
  607. Py_RETURN_NONE;
  608. } catch (const InvalidMessageOperation& imo) {
  609. PyErr_Clear();
  610. PyErr_SetString(po_InvalidMessageOperation, imo.what());
  611. } catch (const exception& ex) {
  612. const string ex_what = "Error in Message.make_response(): " + string(ex.what());
  613. PyErr_SetString(po_IscException, ex_what.c_str());
  614. } catch (...) {
  615. PyErr_SetString(po_IscException,
  616. "Unexpected exception in Message.make_response()");
  617. }
  618. return (NULL);
  619. }
  620. PyObject*
  621. Message_toText(s_Message* self) {
  622. // Py_BuildValue makes python objects from native data
  623. try {
  624. return (Py_BuildValue("s", self->cppobj->toText().c_str()));
  625. } catch (const InvalidMessageOperation& imo) {
  626. PyErr_Clear();
  627. PyErr_SetString(po_InvalidMessageOperation, imo.what());
  628. } catch (const exception& ex) {
  629. const string ex_what = "Error in Message.to_text(): " + string(ex.what());
  630. PyErr_SetString(po_IscException, ex_what.c_str());
  631. } catch (...) {
  632. PyErr_SetString(po_IscException,
  633. "Unexpected exception in Message.to_text()");
  634. }
  635. return (NULL);
  636. }
  637. PyObject*
  638. Message_str(PyObject* self) {
  639. // Simply call the to_text method we already defined
  640. return (PyObject_CallMethod(self,
  641. const_cast<char*>("to_text"),
  642. const_cast<char*>("")));
  643. }
  644. PyObject*
  645. Message_toWire(s_Message* self, PyObject* args) {
  646. PyObject* mr;
  647. PyObject* tsig_ctx = NULL;
  648. if (PyArg_ParseTuple(args, "O!|O", &messagerenderer_type, &mr,
  649. &tsig_ctx)) {
  650. try {
  651. if ((tsig_ctx == NULL) || (tsig_ctx == Py_None)) {
  652. self->cppobj->toWire(PyMessageRenderer_ToMessageRenderer(mr));
  653. } else {
  654. self->cppobj->toWire(PyMessageRenderer_ToMessageRenderer(mr),
  655. PyTSIGContext_ToTSIGContext(tsig_ctx));
  656. }
  657. // If we return NULL it is seen as an error, so use this for
  658. // None returns
  659. Py_RETURN_NONE;
  660. } catch (const InvalidMessageOperation& imo) {
  661. PyErr_Clear();
  662. PyErr_SetString(po_InvalidMessageOperation, imo.what());
  663. } catch (const TSIGContextError& ex) {
  664. // toWire() with a TSIG context can fail due to this if the
  665. // python program has a bug.
  666. PyErr_SetString(po_TSIGContextError, ex.what());
  667. } catch (const exception& ex) {
  668. const string ex_what = "Error in Message.to_wire(): " + string(ex.what());
  669. PyErr_SetString(po_TSIGContextError, ex_what.c_str());
  670. } catch (...) {
  671. PyErr_SetString(po_IscException,
  672. "Unexpected exception in Message.to_wire()");
  673. }
  674. return (NULL);
  675. }
  676. PyErr_Clear();
  677. PyErr_SetString(PyExc_TypeError,
  678. "Bad to_wire() arguments were passed");
  679. return (NULL);
  680. }
  681. PyObject*
  682. Message_fromWire(PyObject* pyself, PyObject* args) {
  683. s_Message* const self = static_cast<s_Message*>(pyself);
  684. const char* b;
  685. Py_ssize_t len;
  686. unsigned int options = Message::PARSE_DEFAULT;
  687. if (PyArg_ParseTuple(args, "y#", &b, &len) ||
  688. PyArg_ParseTuple(args, "y#I", &b, &len, &options)) {
  689. // We need to clear the error in case the first call to ParseTuple
  690. // fails.
  691. PyErr_Clear();
  692. InputBuffer inbuf(b, len);
  693. try {
  694. self->cppobj->fromWire(
  695. inbuf, static_cast<Message::ParseOptions>(options));
  696. Py_RETURN_NONE;
  697. } catch (const InvalidMessageOperation& imo) {
  698. PyErr_SetString(po_InvalidMessageOperation, imo.what());
  699. } catch (const DNSMessageFORMERR& dmfe) {
  700. PyErr_SetString(po_DNSMessageFORMERR, dmfe.what());
  701. } catch (const DNSMessageBADVERS& dmfe) {
  702. PyErr_SetString(po_DNSMessageBADVERS, dmfe.what());
  703. } catch (const MessageTooShort& mts) {
  704. PyErr_SetString(po_MessageTooShort, mts.what());
  705. } catch (const InvalidBufferPosition& ex) {
  706. PyErr_SetString(po_DNSMessageFORMERR, ex.what());
  707. } catch (const exception& ex) {
  708. const string ex_what = "Error in Message.from_wire(): " + string(ex.what());
  709. PyErr_SetString(po_IscException, ex_what.c_str());
  710. } catch (...) {
  711. PyErr_SetString(po_IscException,
  712. "Unexpected exception in Message.from_wire()");
  713. }
  714. return (NULL);
  715. }
  716. PyErr_SetString(PyExc_TypeError,
  717. "from_wire() arguments must be a byte object and "
  718. "(optional) parse options");
  719. return (NULL);
  720. }
  721. } // end of unnamed namespace
  722. namespace isc {
  723. namespace dns {
  724. namespace python {
  725. //
  726. // Declaration of the custom exceptions
  727. // Initialization and addition of these go in the initModulePart
  728. // function in pydnspp.cc
  729. //
  730. PyObject* po_MessageTooShort;
  731. PyObject* po_InvalidMessageSection;
  732. PyObject* po_InvalidMessageOperation;
  733. PyObject* po_InvalidMessageUDPSize;
  734. // This defines the complete type for reflection in python and
  735. // parsing of PyObject* to s_Message
  736. // Most of the functions are not actually implemented and NULL here.
  737. PyTypeObject message_type = {
  738. PyVarObject_HEAD_INIT(NULL, 0)
  739. "pydnspp.Message",
  740. sizeof(s_Message), // tp_basicsize
  741. 0, // tp_itemsize
  742. (destructor)Message_destroy, // tp_dealloc
  743. NULL, // tp_print
  744. NULL, // tp_getattr
  745. NULL, // tp_setattr
  746. NULL, // tp_reserved
  747. NULL, // tp_repr
  748. NULL, // tp_as_number
  749. NULL, // tp_as_sequence
  750. NULL, // tp_as_mapping
  751. NULL, // tp_hash
  752. NULL, // tp_call
  753. Message_str, // tp_str
  754. NULL, // tp_getattro
  755. NULL, // tp_setattro
  756. NULL, // tp_as_buffer
  757. Py_TPFLAGS_DEFAULT, // tp_flags
  758. "The Message class encapsulates a standard DNS message.",
  759. NULL, // tp_traverse
  760. NULL, // tp_clear
  761. NULL, // tp_richcompare
  762. 0, // tp_weaklistoffset
  763. NULL, // tp_iter
  764. NULL, // tp_iternext
  765. Message_methods, // tp_methods
  766. NULL, // tp_members
  767. NULL, // tp_getset
  768. NULL, // tp_base
  769. NULL, // tp_dict
  770. NULL, // tp_descr_get
  771. NULL, // tp_descr_set
  772. 0, // tp_dictoffset
  773. (initproc)Message_init, // tp_init
  774. NULL, // tp_alloc
  775. PyType_GenericNew, // tp_new
  776. NULL, // tp_free
  777. NULL, // tp_is_gc
  778. NULL, // tp_bases
  779. NULL, // tp_mro
  780. NULL, // tp_cache
  781. NULL, // tp_subclasses
  782. NULL, // tp_weaklist
  783. NULL, // tp_del
  784. 0 // tp_version_tag
  785. };
  786. } // end python namespace
  787. } // end dns namespace
  788. } // end isc namespace