message_python.cc 27 KB

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