message_python.cc 40 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086
  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. // $Id$
  15. #include <dns/message.h>
  16. using namespace isc::dns;
  17. //
  18. // Declaration of the custom exceptions
  19. // Initialization and addition of these go in the initModulePart
  20. // function at the end of this file
  21. //
  22. static PyObject* po_MessageTooShort;
  23. static PyObject* po_InvalidMessageSection;
  24. static PyObject* po_InvalidMessageOperation;
  25. static PyObject* po_InvalidMessageUDPSize;
  26. static PyObject* po_DNSMessageBADVERS;
  27. //
  28. // Definition of the classes
  29. //
  30. // For each class, we need a struct, a helper functions (init, destroy,
  31. // and static wrappers around the methods we export), a list of methods,
  32. // and a type description
  33. //
  34. // MessageFlag
  35. //
  36. class s_MessageFlag : public PyObject {
  37. public:
  38. const MessageFlag* messageflag;
  39. };
  40. static int MessageFlag_init(s_MessageFlag* self, PyObject* args);
  41. static void MessageFlag_destroy(s_MessageFlag* self);
  42. static PyObject* MessageFlag_getBit(s_MessageFlag* self);
  43. static PyObject* MessageFlag_QR(s_MessageFlag* self);
  44. static PyObject* MessageFlag_AA(s_MessageFlag* self);
  45. static PyObject* MessageFlag_TC(s_MessageFlag* self);
  46. static PyObject* MessageFlag_RD(s_MessageFlag* self);
  47. static PyObject* MessageFlag_RA(s_MessageFlag* self);
  48. static PyObject* MessageFlag_AD(s_MessageFlag* self);
  49. static PyObject* MessageFlag_CD(s_MessageFlag* self);
  50. static PyMethodDef MessageFlag_methods[] = {
  51. { "get_bit", reinterpret_cast<PyCFunction>(MessageFlag_getBit), METH_NOARGS, "Returns the flag bit" },
  52. { "QR", reinterpret_cast<PyCFunction>(MessageFlag_QR), METH_NOARGS | METH_STATIC, "Creates a QR MessageFlag" },
  53. { "AA", reinterpret_cast<PyCFunction>(MessageFlag_AA), METH_NOARGS | METH_STATIC, "Creates a AA MessageFlag" },
  54. { "TC", reinterpret_cast<PyCFunction>(MessageFlag_TC), METH_NOARGS | METH_STATIC, "Creates a TC MessageFlag" },
  55. { "RD", reinterpret_cast<PyCFunction>(MessageFlag_RD), METH_NOARGS | METH_STATIC, "Creates a RD MessageFlag" },
  56. { "RA", reinterpret_cast<PyCFunction>(MessageFlag_RA), METH_NOARGS | METH_STATIC, "Creates a RA MessageFlag" },
  57. { "AD", reinterpret_cast<PyCFunction>(MessageFlag_AD), METH_NOARGS | METH_STATIC, "Creates a AD MessageFlag" },
  58. { "CD", reinterpret_cast<PyCFunction>(MessageFlag_CD), METH_NOARGS | METH_STATIC, "Creates a CD MessageFlag" },
  59. { NULL, NULL, 0, NULL }
  60. };
  61. static PyTypeObject messageflag_type = {
  62. PyVarObject_HEAD_INIT(NULL, 0)
  63. "pydnspp.MessageFlag",
  64. sizeof(s_MessageFlag), // tp_basicsize
  65. 0, // tp_itemsize
  66. (destructor)MessageFlag_destroy, // tp_dealloc
  67. NULL, // tp_print
  68. NULL, // tp_getattr
  69. NULL, // tp_setattr
  70. NULL, // tp_reserved
  71. NULL, // tp_repr
  72. NULL, // tp_as_number
  73. NULL, // tp_as_sequence
  74. NULL, // tp_as_mapping
  75. NULL, // tp_hash
  76. NULL, // tp_call
  77. NULL, // tp_str
  78. NULL, // tp_getattro
  79. NULL, // tp_setattro
  80. NULL, // tp_as_buffer
  81. Py_TPFLAGS_DEFAULT, // tp_flags
  82. "The MessageFlag class objects represent standard "
  83. "flag bits of the header section of DNS messages.",
  84. NULL, // tp_traverse
  85. NULL, // tp_clear
  86. NULL, // tp_richcompare
  87. 0, // tp_weaklistoffset
  88. NULL, // tp_iter
  89. NULL, // tp_iternext
  90. MessageFlag_methods, // tp_methods
  91. NULL, // tp_members
  92. NULL, // tp_getset
  93. NULL, // tp_base
  94. NULL, // tp_dict
  95. NULL, // tp_descr_get
  96. NULL, // tp_descr_set
  97. 0, // tp_dictoffset
  98. (initproc)MessageFlag_init, // tp_init
  99. NULL, // tp_alloc
  100. PyType_GenericNew, // tp_new
  101. NULL, // tp_free
  102. NULL, // tp_is_gc
  103. NULL, // tp_bases
  104. NULL, // tp_mro
  105. NULL, // tp_cache
  106. NULL, // tp_subclasses
  107. NULL, // tp_weaklist
  108. NULL, // tp_del
  109. 0 // tp_version_tag
  110. };
  111. static int
  112. MessageFlag_init(s_MessageFlag* self UNUSED_PARAM,
  113. PyObject* args UNUSED_PARAM)
  114. {
  115. PyErr_SetString(PyExc_NotImplementedError,
  116. "MessageFlag can't be built directly");
  117. return (-1);
  118. }
  119. static void
  120. MessageFlag_destroy(s_MessageFlag* self) {
  121. // We only use the consts from MessageFlag, so don't
  122. // delete self->messageflag here
  123. self->messageflag = NULL;
  124. Py_TYPE(self)->tp_free(self);
  125. }
  126. static PyObject*
  127. MessageFlag_getBit(s_MessageFlag* self) {
  128. return (Py_BuildValue("I", self->messageflag->getBit()));
  129. }
  130. static PyObject*
  131. MessageFlag_createStatic(const MessageFlag& flag) {
  132. s_MessageFlag* ret = PyObject_New(s_MessageFlag, &messageflag_type);
  133. if (ret != NULL) {
  134. ret->messageflag = &flag;
  135. }
  136. return (ret);
  137. }
  138. static PyObject*
  139. MessageFlag_QR(s_MessageFlag* self UNUSED_PARAM) {
  140. return (MessageFlag_createStatic(MessageFlag::QR()));
  141. }
  142. static PyObject*
  143. MessageFlag_AA(s_MessageFlag* self UNUSED_PARAM) {
  144. return (MessageFlag_createStatic(MessageFlag::AA()));
  145. }
  146. static PyObject*
  147. MessageFlag_TC(s_MessageFlag* self UNUSED_PARAM) {
  148. return (MessageFlag_createStatic(MessageFlag::TC()));
  149. }
  150. static PyObject*
  151. MessageFlag_RD(s_MessageFlag* self UNUSED_PARAM) {
  152. return (MessageFlag_createStatic(MessageFlag::RD()));
  153. }
  154. static PyObject*
  155. MessageFlag_RA(s_MessageFlag* self UNUSED_PARAM) {
  156. return (MessageFlag_createStatic(MessageFlag::RA()));
  157. }
  158. static PyObject*
  159. MessageFlag_AD(s_MessageFlag* self UNUSED_PARAM) {
  160. return (MessageFlag_createStatic(MessageFlag::AD()));
  161. }
  162. static PyObject*
  163. MessageFlag_CD(s_MessageFlag* self UNUSED_PARAM) {
  164. return (MessageFlag_createStatic(MessageFlag::CD()));
  165. }
  166. //
  167. // End of MessageFlag wrapper
  168. //
  169. //
  170. // Section
  171. //
  172. // TODO: iterator?
  173. class s_Section : public PyObject {
  174. public:
  175. const Section* section;
  176. };
  177. static int Section_init(s_Section* self, PyObject* args);
  178. static void Section_destroy(s_Section* self);
  179. static PyObject* Section_getCode(s_Section* self);
  180. static PyObject* Section_QUESTION(s_Section* self);
  181. static PyObject* Section_ANSWER(s_Section* self);
  182. static PyObject* Section_AUTHORITY(s_Section* self);
  183. static PyObject* Section_ADDITIONAL(s_Section* self);
  184. static PyObject* Section_richcmp(s_Section* self, s_Section* other, int op);
  185. static PyMethodDef Section_methods[] = {
  186. { "get_code", reinterpret_cast<PyCFunction>(Section_getCode), METH_NOARGS, "Returns the code value" },
  187. { "QUESTION", reinterpret_cast<PyCFunction>(Section_QUESTION), METH_NOARGS | METH_STATIC, "Creates a QUESTION Section" },
  188. { "ANSWER", reinterpret_cast<PyCFunction>(Section_ANSWER), METH_NOARGS | METH_STATIC, "Creates an ANSWER Section" },
  189. { "AUTHORITY", reinterpret_cast<PyCFunction>(Section_AUTHORITY), METH_NOARGS | METH_STATIC, "Creates an AUTHORITY Section" },
  190. { "ADDITIONAL", reinterpret_cast<PyCFunction>(Section_ADDITIONAL), METH_NOARGS | METH_STATIC, "Creates an ADDITIONAL Section" },
  191. { NULL, NULL, 0, NULL }
  192. };
  193. static PyTypeObject section_type = {
  194. PyVarObject_HEAD_INIT(NULL, 0)
  195. "pydnspp.Section",
  196. sizeof(s_Section), // tp_basicsize
  197. 0, // tp_itemsize
  198. (destructor)Section_destroy, // tp_dealloc
  199. NULL, // tp_print
  200. NULL, // tp_getattr
  201. NULL, // tp_setattr
  202. NULL, // tp_reserved
  203. NULL, // tp_repr
  204. NULL, // tp_as_number
  205. NULL, // tp_as_sequence
  206. NULL, // tp_as_mapping
  207. NULL, // tp_hash
  208. NULL, // tp_call
  209. NULL, // tp_str
  210. NULL, // tp_getattro
  211. NULL, // tp_setattro
  212. NULL, // tp_as_buffer
  213. Py_TPFLAGS_DEFAULT, // tp_flags
  214. "The Section class objects represent DNS message sections such "
  215. "as the header, question, or answer.",
  216. NULL, // tp_traverse
  217. NULL, // tp_clear
  218. (richcmpfunc)Section_richcmp, // tp_richcompare
  219. 0, // tp_weaklistoffset
  220. NULL, // tp_iter
  221. NULL, // tp_iternext
  222. Section_methods, // tp_methods
  223. NULL, // tp_members
  224. NULL, // tp_getset
  225. NULL, // tp_base
  226. NULL, // tp_dict
  227. NULL, // tp_descr_get
  228. NULL, // tp_descr_set
  229. 0, // tp_dictoffset
  230. (initproc)Section_init, // tp_init
  231. NULL, // tp_alloc
  232. PyType_GenericNew, // tp_new
  233. NULL, // tp_free
  234. NULL, // tp_is_gc
  235. NULL, // tp_bases
  236. NULL, // tp_mro
  237. NULL, // tp_cache
  238. NULL, // tp_subclasses
  239. NULL, // tp_weaklist
  240. NULL, // tp_del
  241. 0 // tp_version_tag
  242. };
  243. static int
  244. Section_init(s_Section* self UNUSED_PARAM,
  245. PyObject* args UNUSED_PARAM)
  246. {
  247. PyErr_SetString(PyExc_NotImplementedError,
  248. "Section can't be built directly");
  249. return (-1);
  250. }
  251. static void
  252. Section_destroy(s_Section* self) {
  253. // We only use the consts from Section, so don't
  254. // delete self->section here
  255. self->section = NULL;
  256. Py_TYPE(self)->tp_free(self);
  257. }
  258. static PyObject*
  259. Section_getCode(s_Section* self) {
  260. return (Py_BuildValue("I", self->section->getCode()));
  261. }
  262. static PyObject*
  263. Section_createStatic(const Section& section) {
  264. s_Section* ret = PyObject_New(s_Section, &section_type);
  265. if (ret != NULL) {
  266. ret->section = &section;
  267. }
  268. return (ret);
  269. }
  270. static PyObject*
  271. Section_QUESTION(s_Section* self UNUSED_PARAM) {
  272. return (Section_createStatic(Section::QUESTION()));
  273. }
  274. static PyObject*
  275. Section_ANSWER(s_Section* self UNUSED_PARAM) {
  276. return (Section_createStatic(Section::ANSWER()));
  277. }
  278. static PyObject*
  279. Section_AUTHORITY(s_Section* self UNUSED_PARAM) {
  280. return (Section_createStatic(Section::AUTHORITY()));
  281. }
  282. static PyObject*
  283. Section_ADDITIONAL(s_Section* self UNUSED_PARAM) {
  284. return (Section_createStatic(Section::ADDITIONAL()));
  285. }
  286. static PyObject*
  287. Section_richcmp(s_Section* self, s_Section* other, int op) {
  288. bool c = false;
  289. // Check for null and if the types match. If different type,
  290. // simply return False
  291. if (!other || (self->ob_type != other->ob_type)) {
  292. Py_RETURN_FALSE;
  293. }
  294. // Only equals and not equals here, unorderable type
  295. switch (op) {
  296. case Py_LT:
  297. PyErr_SetString(PyExc_TypeError, "Unorderable type; Section");
  298. return (NULL);
  299. break;
  300. case Py_LE:
  301. PyErr_SetString(PyExc_TypeError, "Unorderable type; Section");
  302. return (NULL);
  303. break;
  304. case Py_EQ:
  305. c = (*self->section == *other->section);
  306. break;
  307. case Py_NE:
  308. c = (*self->section != *other->section);
  309. break;
  310. case Py_GT:
  311. PyErr_SetString(PyExc_TypeError, "Unorderable type; Section");
  312. return (NULL);
  313. break;
  314. case Py_GE:
  315. PyErr_SetString(PyExc_TypeError, "Unorderable type; Section");
  316. return (NULL);
  317. break;
  318. }
  319. if (c)
  320. Py_RETURN_TRUE;
  321. else
  322. Py_RETURN_FALSE;
  323. }
  324. //
  325. // End of Section wrapper
  326. //
  327. //
  328. // Message
  329. //
  330. // The s_* Class simply coverst one instantiation of the object
  331. class s_Message : public PyObject {
  332. public:
  333. Message* message;
  334. };
  335. //
  336. // We declare the functions here, the definitions are below
  337. // the type definition of the object, since both can use the other
  338. //
  339. // General creation and destruction
  340. static int Message_init(s_Message* self, PyObject* args);
  341. static void Message_destroy(s_Message* self);
  342. static PyObject* Message_getHeaderFlag(s_Message* self, PyObject* args);
  343. static PyObject* Message_setHeaderFlag(s_Message* self, PyObject* args);
  344. static PyObject* Message_clearHeaderFlag(s_Message* self, PyObject* args);
  345. static PyObject* Message_isDNSSECSupported(s_Message* self);
  346. static PyObject* Message_setDNSSECSupported(s_Message* self, PyObject* args);
  347. static PyObject* Message_getUDPSize(s_Message* self);
  348. static PyObject* Message_setUDPSize(s_Message* self, PyObject* args);
  349. static PyObject* Message_getQid(s_Message* self);
  350. static PyObject* Message_setQid(s_Message* self, PyObject* args);
  351. static PyObject* Message_getRcode(s_Message* self);
  352. static PyObject* Message_setRcode(s_Message* self, PyObject* args);
  353. static PyObject* Message_getOpcode(s_Message* self);
  354. static PyObject* Message_setOpcode(s_Message* self, PyObject* args);
  355. static PyObject* Message_getRRCount(s_Message* self, PyObject* args);
  356. // use direct iterators for these? (or simply lists for now?)
  357. static PyObject* Message_getQuestion(s_Message* self);
  358. static PyObject* Message_getSection(s_Message* self, PyObject* args);
  359. //static PyObject* Message_beginQuestion(s_Message* self, PyObject* args);
  360. //static PyObject* Message_endQuestion(s_Message* self, PyObject* args);
  361. //static PyObject* Message_beginSection(s_Message* self, PyObject* args);
  362. //static PyObject* Message_endSection(s_Message* self, PyObject* args);
  363. static PyObject* Message_addQuestion(s_Message* self, PyObject* args);
  364. static PyObject* Message_addRRset(s_Message* self, PyObject* args);
  365. static PyObject* Message_clear(s_Message* self, PyObject* args);
  366. static PyObject* Message_makeResponse(s_Message* self);
  367. static PyObject* Message_toText(s_Message* self);
  368. static PyObject* Message_str(PyObject* self);
  369. static PyObject* Message_toWire(s_Message* self, PyObject* args);
  370. static PyObject* Message_fromWire(s_Message* self, PyObject* args);
  371. // This list contains the actual set of functions we have in
  372. // python. Each entry has
  373. // 1. Python method name
  374. // 2. Our static function here
  375. // 3. Argument type
  376. // 4. Documentation
  377. static PyMethodDef Message_methods[] = {
  378. { "get_header_flag", reinterpret_cast<PyCFunction>(Message_getHeaderFlag), METH_VARARGS,
  379. "Return whether the specified header flag bit is set in the "
  380. "header section. Takes a MessageFlag object as the only argument." },
  381. { "set_header_flag", reinterpret_cast<PyCFunction>(Message_setHeaderFlag), METH_VARARGS,
  382. "Sets the specified header flag bit to 1. The message must be in "
  383. "RENDER mode. If not, an InvalidMessageOperation is raised. "
  384. "Takes a MessageFlag object as the only argument." },
  385. { "clear_header_flag", reinterpret_cast<PyCFunction>(Message_clearHeaderFlag), METH_VARARGS,
  386. "Sets the specified header flag bit to 0. The message must be in "
  387. "RENDER mode. If not, an InvalidMessageOperation is raised. "
  388. "Takes a MessageFlag object as the only argument." },
  389. { "is_dnssec_supported", reinterpret_cast<PyCFunction>(Message_isDNSSECSupported), METH_NOARGS,
  390. "Returns True if the message sender indicates DNSSEC is supported. "
  391. "If EDNS is included, this corresponds to the value of the DO bit. "
  392. "Otherwise, DNSSEC is considered not supported." },
  393. { "set_dnssec_supported", reinterpret_cast<PyCFunction>(Message_setDNSSECSupported), METH_VARARGS,
  394. "Specify whether DNSSEC is supported in the message. "
  395. "The message must be in RENDER mode. If not, an "
  396. "InvalidMessageOperation is raised."
  397. "If EDNS is included in the message, the DO bit is set or cleared "
  398. "according to given argument (True or False) of this method."},
  399. { "get_udp_size", reinterpret_cast<PyCFunction>(Message_getUDPSize), METH_NOARGS,
  400. "Return the maximum buffer size of UDP messages for the sender "
  401. "of the message.\n\n"
  402. "The semantics of this value is different based on the mode:\n"
  403. "In the PARSE mode, it means the buffer size of the remote node;\n"
  404. "in the RENDER mode, it means the buffer size of the local node.\n\n"
  405. "In either case, its value is the value of the UDP payload size field "
  406. "of EDNS (when it's included) or DEFAULT_MAX_UDPSIZE." },
  407. { "set_udp_size", reinterpret_cast<PyCFunction>(Message_setUDPSize), METH_VARARGS,
  408. "Specify the maximum buffer size of UDP messages of the local "
  409. "node. If the message is not in RENDER mode, an "
  410. "InvalidMessageOperation is raised.\n\n"
  411. "If EDNS OPT RR is included in the message, its UDP payload size field "
  412. "will be set to the specified value.\n"
  413. "Unless explicitly specified, DEFAULT_MAX_UDPSIZE will be assumed "
  414. "for the maximum buffer size, regardless of whether EDNS OPT RR is "
  415. "included or not. This means if an application wants to send a message "
  416. "with an EDNS OPT RR for specifying a larger UDP size, it must explicitly "
  417. "specify the value using this method. "},
  418. { "get_qid", reinterpret_cast<PyCFunction>(Message_getQid), METH_NOARGS,
  419. "Returns the query id" },
  420. { "set_qid", reinterpret_cast<PyCFunction>(Message_setQid), METH_VARARGS,
  421. "Sets the query id. If the message is not in RENDER mode, an "
  422. "InvalidMessageOperation is raised.\n"
  423. "The argument must be an integer" },
  424. { "get_rcode", reinterpret_cast<PyCFunction>(Message_getRcode), METH_NOARGS,
  425. "Returns the message Response code (an Rcode object)" },
  426. { "set_rcode", reinterpret_cast<PyCFunction>(Message_setRcode), METH_VARARGS,
  427. "Sets the message Response code (an Rcode object).\n"
  428. "If the message is not in RENDER mode, an "
  429. "InvalidMessageOperation is raised."},
  430. { "get_opcode", reinterpret_cast<PyCFunction>(Message_getOpcode), METH_NOARGS,
  431. "Returns the message opcode (an Opcode object)" },
  432. { "set_opcode", reinterpret_cast<PyCFunction>(Message_setOpcode), METH_VARARGS,
  433. "Sets the message opcode (an Opcode object).\n"
  434. "If the message is not in RENDER mode, an "
  435. "InvalidMessageOperation is raised."},
  436. { "get_rr_count", reinterpret_cast<PyCFunction>(Message_getRRCount), METH_VARARGS,
  437. "Returns the number of RRs contained in the given section." },
  438. { "get_question", reinterpret_cast<PyCFunction>(Message_getQuestion), METH_NOARGS,
  439. "Returns a list of all Question objects in the message "
  440. "(should be either 0 or 1)" },
  441. { "get_section", reinterpret_cast<PyCFunction>(Message_getSection), METH_VARARGS,
  442. "Returns a list of all RRset objects in the given section of the message\n"
  443. "The argument must be of type Section" },
  444. { "add_question", reinterpret_cast<PyCFunction>(Message_addQuestion), METH_VARARGS,
  445. "Add a Question to the message."
  446. "If the message is not in RENDER mode, an "
  447. "InvalidMessageOperation is raised."},
  448. { "add_rrset", reinterpret_cast<PyCFunction>(Message_addRRset), METH_VARARGS,
  449. "Add an RRset to the given section of the message.\n"
  450. "The first argument is of type Section\n"
  451. "The second is of type RRset\n"
  452. "The third argument is an optional Boolean specifying whether "
  453. "the RRset is signed"},
  454. { "clear", reinterpret_cast<PyCFunction>(Message_clear), METH_VARARGS,
  455. "Clears the message content (if any) and reinitialize the "
  456. "message in the given mode\n"
  457. "The argument must be either Message.PARSE or Message.RENDER"},
  458. { "make_response", reinterpret_cast<PyCFunction>(Message_makeResponse), METH_NOARGS,
  459. "Prepare for making a response from a request.\n"
  460. "This will clear the DNS header except those fields that should be kept "
  461. "for the response, and clear answer and the following sections. "
  462. "See also dns_message_reply() of BIND9."},
  463. { "to_text", reinterpret_cast<PyCFunction>(Message_toText), METH_NOARGS,
  464. "Returns the string representation of the message" },
  465. { "to_wire", reinterpret_cast<PyCFunction>(Message_toWire), METH_VARARGS,
  466. "Render the message in wire format.\n"
  467. "The argument must be a MessageRenderer.\n"
  468. "If the given message is not in RENDER mode, an "
  469. "InvalidMessageOperation is raised.\n"
  470. },
  471. { "from_wire", reinterpret_cast<PyCFunction>(Message_fromWire), METH_VARARGS,
  472. "Parses the given wire format to a Message object.\n"
  473. "The first argument is a Message to parse the data into.\n"
  474. "The second argument must implement the buffer interface.\n"
  475. "If the given message is not in PARSE mode, an "
  476. "InvalidMessageOperation is raised.\n"
  477. "Raises MessageTooShort, DNSMessageFORMERR or DNSMessageBADVERS "
  478. " if there is a problem parsing the message." },
  479. { NULL, NULL, 0, NULL }
  480. };
  481. // This defines the complete type for reflection in python and
  482. // parsing of PyObject* to s_Message
  483. // Most of the functions are not actually implemented and NULL here.
  484. static PyTypeObject message_type = {
  485. PyVarObject_HEAD_INIT(NULL, 0)
  486. "pydnspp.Message",
  487. sizeof(s_Message), // tp_basicsize
  488. 0, // tp_itemsize
  489. (destructor)Message_destroy, // tp_dealloc
  490. NULL, // tp_print
  491. NULL, // tp_getattr
  492. NULL, // tp_setattr
  493. NULL, // tp_reserved
  494. NULL, // tp_repr
  495. NULL, // tp_as_number
  496. NULL, // tp_as_sequence
  497. NULL, // tp_as_mapping
  498. NULL, // tp_hash
  499. NULL, // tp_call
  500. Message_str, // tp_str
  501. NULL, // tp_getattro
  502. NULL, // tp_setattro
  503. NULL, // tp_as_buffer
  504. Py_TPFLAGS_DEFAULT, // tp_flags
  505. "The Message class encapsulates a standard DNS message.",
  506. NULL, // tp_traverse
  507. NULL, // tp_clear
  508. NULL, // tp_richcompare
  509. 0, // tp_weaklistoffset
  510. NULL, // tp_iter
  511. NULL, // tp_iternext
  512. Message_methods, // tp_methods
  513. NULL, // tp_members
  514. NULL, // tp_getset
  515. NULL, // tp_base
  516. NULL, // tp_dict
  517. NULL, // tp_descr_get
  518. NULL, // tp_descr_set
  519. 0, // tp_dictoffset
  520. (initproc)Message_init, // tp_init
  521. NULL, // tp_alloc
  522. PyType_GenericNew, // tp_new
  523. NULL, // tp_free
  524. NULL, // tp_is_gc
  525. NULL, // tp_bases
  526. NULL, // tp_mro
  527. NULL, // tp_cache
  528. NULL, // tp_subclasses
  529. NULL, // tp_weaklist
  530. NULL, // tp_del
  531. 0 // tp_version_tag
  532. };
  533. static int
  534. Message_init(s_Message* self, PyObject* args) {
  535. unsigned int i;
  536. // The constructor argument can be a string ("IN"), an integer (1),
  537. // or a sequence of numbers between 0 and 255 (wire code)
  538. if (PyArg_ParseTuple(args, "I", &i)) {
  539. PyErr_Clear();
  540. if (i == Message::PARSE) {
  541. self->message = new Message(Message::PARSE);
  542. return (0);
  543. } else if (i == Message::RENDER) {
  544. self->message = new Message(Message::RENDER);
  545. return (0);
  546. } else {
  547. PyErr_SetString(PyExc_TypeError, "Message mode must be Message.PARSE or Message.RENDER");
  548. return (-1);
  549. }
  550. }
  551. PyErr_Clear();
  552. PyErr_SetString(PyExc_TypeError,
  553. "no valid type in constructor argument");
  554. return (-1);
  555. }
  556. static void
  557. Message_destroy(s_Message* self) {
  558. delete self->message;
  559. self->message = NULL;
  560. Py_TYPE(self)->tp_free(self);
  561. }
  562. static PyObject*
  563. Message_getHeaderFlag(s_Message* self, PyObject* args) {
  564. s_MessageFlag* messageflag;
  565. if (!PyArg_ParseTuple(args, "O!", &messageflag_type, &messageflag)) {
  566. return (NULL);
  567. }
  568. if (self->message->getHeaderFlag(*messageflag->messageflag)) {
  569. Py_RETURN_TRUE;
  570. } else {
  571. Py_RETURN_FALSE;
  572. }
  573. }
  574. static PyObject*
  575. Message_setHeaderFlag(s_Message* self, PyObject* args) {
  576. s_MessageFlag* messageflag;
  577. if (!PyArg_ParseTuple(args, "O!", &messageflag_type, &messageflag)) {
  578. return (NULL);
  579. }
  580. try {
  581. self->message->setHeaderFlag(*messageflag->messageflag);
  582. Py_RETURN_NONE;
  583. } catch (const InvalidMessageOperation& imo) {
  584. PyErr_Clear();
  585. PyErr_SetString(po_InvalidMessageOperation, imo.what());
  586. return (NULL);
  587. }
  588. }
  589. static PyObject*
  590. Message_clearHeaderFlag(s_Message* self, PyObject* args) {
  591. s_MessageFlag* messageflag;
  592. if (!PyArg_ParseTuple(args, "O!", &messageflag_type, &messageflag)) {
  593. return (NULL);
  594. }
  595. try {
  596. self->message->clearHeaderFlag(*messageflag->messageflag);
  597. Py_RETURN_NONE;
  598. } catch (const InvalidMessageOperation& imo) {
  599. PyErr_Clear();
  600. PyErr_SetString(po_InvalidMessageOperation, imo.what());
  601. return (NULL);
  602. }
  603. Py_RETURN_NONE;
  604. }
  605. static PyObject*
  606. Message_isDNSSECSupported(s_Message* self) {
  607. if (self->message->isDNSSECSupported()) {
  608. Py_RETURN_TRUE;
  609. } else {
  610. Py_RETURN_FALSE;
  611. }
  612. }
  613. static PyObject*
  614. Message_setDNSSECSupported(s_Message* self, PyObject* args) {
  615. PyObject *b;
  616. if (!PyArg_ParseTuple(args, "O!", &PyBool_Type, &b)) {
  617. return (NULL);
  618. }
  619. try {
  620. if (b == Py_True) {
  621. self->message->setDNSSECSupported(true);
  622. } else {
  623. self->message->setDNSSECSupported(false);
  624. }
  625. Py_RETURN_NONE;
  626. } catch (const InvalidMessageOperation& imo) {
  627. PyErr_SetString(po_InvalidMessageOperation, imo.what());
  628. return (NULL);
  629. }
  630. }
  631. static PyObject*
  632. Message_getUDPSize(s_Message* self) {
  633. return (Py_BuildValue("I", self->message->getUDPSize()));
  634. }
  635. static PyObject*
  636. Message_setUDPSize(s_Message* self, PyObject* args) {
  637. uint16_t size;
  638. if (!PyArg_ParseTuple(args, "H", &size)) {
  639. return (NULL);
  640. }
  641. try {
  642. self->message->setUDPSize(size);
  643. Py_RETURN_NONE;
  644. } catch (const InvalidMessageUDPSize& imus) {
  645. PyErr_SetString(po_InvalidMessageUDPSize, imus.what());
  646. return (NULL);
  647. } catch (const InvalidMessageOperation& imo) {
  648. PyErr_SetString(po_InvalidMessageOperation, imo.what());
  649. return (NULL);
  650. }
  651. }
  652. static PyObject*
  653. Message_getQid(s_Message* self) {
  654. return (Py_BuildValue("I", self->message->getQid()));
  655. }
  656. static PyObject*
  657. Message_setQid(s_Message* self, PyObject* args) {
  658. uint16_t id;
  659. if (!PyArg_ParseTuple(args, "H", &id)) {
  660. return (NULL);
  661. }
  662. try {
  663. self->message->setQid(id);
  664. Py_RETURN_NONE;
  665. } catch (const InvalidMessageOperation& imo) {
  666. PyErr_SetString(po_InvalidMessageOperation, imo.what());
  667. return (NULL);
  668. }
  669. }
  670. static PyObject*
  671. Message_getRcode(s_Message* self) {
  672. s_Rcode* rcode;
  673. rcode = static_cast<s_Rcode*>(rcode_type.tp_alloc(&rcode_type, 0));
  674. if (rcode != NULL) {
  675. rcode->rcode = NULL;
  676. try {
  677. rcode->rcode = new Rcode(self->message->getRcode());
  678. } catch (const InvalidMessageOperation& imo) {
  679. PyErr_SetString(po_InvalidMessageOperation, imo.what());
  680. } catch (...) {
  681. PyErr_SetString(po_IscException, "Unexpected exception");
  682. }
  683. if (rcode->rcode == NULL) {
  684. Py_DECREF(rcode);
  685. return (NULL);
  686. }
  687. }
  688. return (rcode);
  689. }
  690. static PyObject*
  691. Message_setRcode(s_Message* self, PyObject* args) {
  692. s_Rcode* rcode;
  693. if (!PyArg_ParseTuple(args, "O!", &rcode_type, &rcode)) {
  694. return (NULL);
  695. }
  696. try {
  697. self->message->setRcode(*rcode->rcode);
  698. Py_RETURN_NONE;
  699. } catch (const InvalidMessageOperation& imo) {
  700. PyErr_SetString(po_InvalidMessageOperation, imo.what());
  701. return (NULL);
  702. }
  703. }
  704. static PyObject*
  705. Message_getOpcode(s_Message* self) {
  706. s_Opcode* opcode;
  707. opcode = static_cast<s_Opcode*>(opcode_type.tp_alloc(&opcode_type, 0));
  708. if (opcode != NULL) {
  709. opcode->opcode = NULL;
  710. try {
  711. opcode->opcode = new Opcode(self->message->getOpcode());
  712. } catch (const InvalidMessageOperation& imo) {
  713. PyErr_SetString(po_InvalidMessageOperation, imo.what());
  714. } catch (...) {
  715. PyErr_SetString(po_IscException, "Unexpected exception");
  716. }
  717. if (opcode->opcode == NULL) {
  718. Py_DECREF(opcode);
  719. return (NULL);
  720. }
  721. }
  722. return (opcode);
  723. }
  724. static PyObject*
  725. Message_setOpcode(s_Message* self, PyObject* args) {
  726. s_Opcode* opcode;
  727. if (!PyArg_ParseTuple(args, "O!", &opcode_type, &opcode)) {
  728. return (NULL);
  729. }
  730. try {
  731. self->message->setOpcode(*opcode->opcode);
  732. Py_RETURN_NONE;
  733. } catch (const InvalidMessageOperation& imo) {
  734. PyErr_SetString(po_InvalidMessageOperation, imo.what());
  735. return (NULL);
  736. }
  737. }
  738. static PyObject*
  739. Message_getRRCount(s_Message* self, PyObject* args) {
  740. s_Section *section;
  741. if (!PyArg_ParseTuple(args, "O!", &section_type, &section)) {
  742. return (NULL);
  743. }
  744. return (Py_BuildValue("I", self->message->getRRCount(*section->section)));
  745. }
  746. // TODO use direct iterators for these? (or simply lists for now?)
  747. static PyObject*
  748. Message_getQuestion(s_Message* self) {
  749. PyObject* list = PyList_New(0);
  750. for (QuestionIterator qi = self->message->beginQuestion();
  751. qi != self->message->endQuestion();
  752. ++qi) {
  753. s_Question *question = static_cast<s_Question*>(question_type.tp_alloc(&question_type, 0));
  754. if (question != NULL) {
  755. question->question = *qi;
  756. if (question->question == NULL)
  757. {
  758. Py_DECREF(question);
  759. return (NULL);
  760. }
  761. }
  762. PyList_Append(list, question);
  763. }
  764. return (list);
  765. }
  766. static PyObject*
  767. Message_getSection(s_Message* self, PyObject* args) {
  768. s_Section *section;
  769. if (!PyArg_ParseTuple(args, "O!", &section_type, &section)) {
  770. return (NULL);
  771. }
  772. PyObject* list = PyList_New(0);
  773. for (RRsetIterator rrsi = self->message->beginSection(*section->section);
  774. rrsi != self->message->endSection(*section->section);
  775. ++rrsi) {
  776. s_RRset *rrset = static_cast<s_RRset*>(rrset_type.tp_alloc(&rrset_type, 0));
  777. if (rrset != NULL) {
  778. rrset->rrset = *rrsi;
  779. if (rrset->rrset == NULL)
  780. {
  781. Py_DECREF(rrset);
  782. Py_DECREF(list);
  783. return (NULL);
  784. }
  785. }
  786. PyList_Append(list, rrset);
  787. // PyList_Append increases refcount, so we remove ours since
  788. // we don't need it anymore
  789. Py_DECREF(rrset);
  790. }
  791. return (list);
  792. }
  793. //static PyObject* Message_beginQuestion(s_Message* self, PyObject* args);
  794. //static PyObject* Message_endQuestion(s_Message* self, PyObject* args);
  795. //static PyObject* Message_beginSection(s_Message* self, PyObject* args);
  796. //static PyObject* Message_endSection(s_Message* self, PyObject* args);
  797. //static PyObject* Message_addQuestion(s_Message* self, PyObject* args);
  798. static PyObject*
  799. Message_addQuestion(s_Message* self, PyObject* args) {
  800. s_Question *question;
  801. if (!PyArg_ParseTuple(args, "O!", &question_type, &question)) {
  802. return (NULL);
  803. }
  804. self->message->addQuestion(question->question);
  805. Py_RETURN_NONE;
  806. }
  807. static PyObject*
  808. Message_addRRset(s_Message* self, PyObject* args) {
  809. PyObject *sign = Py_False;
  810. s_Section* section;
  811. s_RRset* rrset;
  812. if (!PyArg_ParseTuple(args, "O!O!|O!", &section_type, &section,
  813. &rrset_type, &rrset,
  814. &PyBool_Type, &sign)) {
  815. return (NULL);
  816. }
  817. try {
  818. if (sign == Py_True) {
  819. self->message->addRRset(*section->section, rrset->rrset, true);
  820. } else {
  821. self->message->addRRset(*section->section, rrset->rrset, false);
  822. }
  823. Py_RETURN_NONE;
  824. } catch (const InvalidMessageOperation& imo) {
  825. PyErr_SetString(po_InvalidMessageOperation, imo.what());
  826. return (NULL);
  827. }
  828. }
  829. static PyObject*
  830. Message_clear(s_Message* self, PyObject* args) {
  831. unsigned int i;
  832. // The constructor argument can be a string ("IN"), an integer (1),
  833. // or a sequence of numbers between 0 and 255 (wire code)
  834. if (PyArg_ParseTuple(args, "I", &i)) {
  835. PyErr_Clear();
  836. if (i == Message::PARSE) {
  837. self->message->clear(Message::PARSE);
  838. Py_RETURN_NONE;
  839. } else if (i == Message::RENDER) {
  840. self->message->clear(Message::RENDER);
  841. Py_RETURN_NONE;
  842. } else {
  843. PyErr_SetString(PyExc_TypeError, "Message mode must be Message.PARSE or Message.RENDER");
  844. return (NULL);
  845. }
  846. } else {
  847. return (NULL);
  848. }
  849. }
  850. static PyObject*
  851. Message_makeResponse(s_Message* self) {
  852. self->message->makeResponse();
  853. Py_RETURN_NONE;
  854. }
  855. static PyObject*
  856. Message_toText(s_Message* self) {
  857. // Py_BuildValue makes python objects from native data
  858. try {
  859. return (Py_BuildValue("s", self->message->toText().c_str()));
  860. } catch (const InvalidMessageOperation& imo) {
  861. PyErr_Clear();
  862. PyErr_SetString(po_InvalidMessageOperation, imo.what());
  863. return (NULL);
  864. } catch (...) {
  865. PyErr_SetString(po_IscException, "Unexpected exception");
  866. return (NULL);
  867. }
  868. }
  869. static PyObject*
  870. Message_str(PyObject* self) {
  871. // Simply call the to_text method we already defined
  872. return (PyObject_CallMethod(self,
  873. const_cast<char*>("to_text"),
  874. const_cast<char*>("")));
  875. }
  876. static PyObject*
  877. Message_toWire(s_Message* self, PyObject* args) {
  878. s_MessageRenderer* mr;
  879. if (PyArg_ParseTuple(args, "O!", &messagerenderer_type, &mr)) {
  880. try {
  881. self->message->toWire(*mr->messagerenderer);
  882. // If we return NULL it is seen as an error, so use this for
  883. // None returns
  884. Py_RETURN_NONE;
  885. } catch (const InvalidMessageOperation& imo) {
  886. PyErr_Clear();
  887. PyErr_SetString(po_InvalidMessageOperation, imo.what());
  888. return (NULL);
  889. }
  890. }
  891. PyErr_Clear();
  892. PyErr_SetString(PyExc_TypeError,
  893. "toWire argument must be a MessageRenderer");
  894. return (NULL);
  895. }
  896. static PyObject*
  897. Message_fromWire(s_Message* self, PyObject* args) {
  898. const char* b;
  899. Py_ssize_t len;
  900. if (!PyArg_ParseTuple(args, "y#", &b, &len)) {
  901. return (NULL);
  902. }
  903. InputBuffer inbuf(b, len);
  904. try {
  905. self->message->fromWire(inbuf);
  906. Py_RETURN_NONE;
  907. } catch (const InvalidMessageOperation& imo) {
  908. PyErr_SetString(po_InvalidMessageOperation, imo.what());
  909. return (NULL);
  910. } catch (const DNSMessageFORMERR& dmfe) {
  911. PyErr_SetString(po_DNSMessageFORMERR, dmfe.what());
  912. return (NULL);
  913. } catch (const DNSMessageBADVERS& dmfe) {
  914. PyErr_SetString(po_DNSMessageBADVERS, dmfe.what());
  915. return (NULL);
  916. } catch (const MessageTooShort& mts) {
  917. PyErr_SetString(po_MessageTooShort, mts.what());
  918. return (NULL);
  919. }
  920. }
  921. // Module Initialization, all statics are initialized here
  922. bool
  923. initModulePart_Message(PyObject* mod) {
  924. // add methods to class
  925. if (PyType_Ready(&messageflag_type) < 0) {
  926. return (false);
  927. }
  928. Py_INCREF(&messageflag_type);
  929. PyModule_AddObject(mod, "MessageFlag",
  930. reinterpret_cast<PyObject*>(&messageflag_type));
  931. if (PyType_Ready(&opcode_type) < 0) {
  932. return (false);
  933. }
  934. Py_INCREF(&opcode_type);
  935. PyModule_AddObject(mod, "Opcode",
  936. reinterpret_cast<PyObject*>(&opcode_type));
  937. if (PyType_Ready(&rcode_type) < 0) {
  938. return (false);
  939. }
  940. Py_INCREF(&rcode_type);
  941. PyModule_AddObject(mod, "Rcode",
  942. reinterpret_cast<PyObject*>(&rcode_type));
  943. if (PyType_Ready(&section_type) < 0) {
  944. return (false);
  945. }
  946. Py_INCREF(&section_type);
  947. PyModule_AddObject(mod, "Section",
  948. reinterpret_cast<PyObject*>(&section_type));
  949. if (PyType_Ready(&message_type) < 0) {
  950. return (false);
  951. }
  952. // Class variables
  953. // These are added to the tp_dict of the type object
  954. //
  955. addClassVariable(message_type, "PARSE", Py_BuildValue("I", Message::PARSE));
  956. addClassVariable(message_type, "RENDER", Py_BuildValue("I", Message::RENDER));
  957. addClassVariable(message_type, "DEFAULT_MAX_UDPSIZE", Py_BuildValue("I", Message::DEFAULT_MAX_UDPSIZE));
  958. /* Class-specific exceptions */
  959. po_MessageTooShort = PyErr_NewException("pydnspp.MessageTooShort", NULL, NULL);
  960. PyModule_AddObject(mod, "MessageTooShort", po_MessageTooShort);
  961. po_InvalidMessageSection = PyErr_NewException("pydnspp.InvalidMessageSection", NULL, NULL);
  962. PyModule_AddObject(mod, "InvalidMessageSection", po_InvalidMessageSection);
  963. po_InvalidMessageOperation = PyErr_NewException("pydnspp.InvalidMessageOperation", NULL, NULL);
  964. PyModule_AddObject(mod, "InvalidMessageOperation", po_InvalidMessageOperation);
  965. po_InvalidMessageUDPSize = PyErr_NewException("pydnspp.InvalidMessageUDPSize", NULL, NULL);
  966. PyModule_AddObject(mod, "InvalidMessageUDPSize", po_InvalidMessageUDPSize);
  967. po_DNSMessageBADVERS = PyErr_NewException("pydnspp.DNSMessageBADVERS", NULL, NULL);
  968. PyModule_AddObject(mod, "DNSMessageBADVERS", po_DNSMessageBADVERS);
  969. Py_INCREF(&message_type);
  970. PyModule_AddObject(mod, "Message",
  971. reinterpret_cast<PyObject*>(&message_type));
  972. return (true);
  973. }