name_python.cc 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707
  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. //
  15. // Declaration of the custom exceptions
  16. // Initialization and addition of these go in the module init at the
  17. // end
  18. //
  19. static PyObject* po_EmptyLabel;
  20. static PyObject* po_TooLongName;
  21. static PyObject* po_TooLongLabel;
  22. static PyObject* po_BadLabelType;
  23. static PyObject* po_BadEscape;
  24. static PyObject* po_IncompleteName;
  25. static PyObject* po_InvalidBufferPosition;
  26. static PyObject* po_DNSMessageFORMERR;
  27. //
  28. // Declaration of enums
  29. // Initialization and addition of these go in the module init at the
  30. // end
  31. //
  32. static PyObject* po_NameRelation;
  33. //
  34. // Definition of the classes
  35. //
  36. // For each class, we need a struct, a helper functions (init, destroy,
  37. // and static wrappers around the methods we export), a list of methods,
  38. // and a type description
  39. using namespace isc::dns;
  40. // NameComparisonResult
  41. class s_NameComparisonResult : public PyObject {
  42. public:
  43. isc::dns::NameComparisonResult* ncr;
  44. };
  45. static int NameComparisonResult_init(s_NameComparisonResult*, PyObject*);
  46. static void NameComparisonResult_destroy(s_NameComparisonResult* self);
  47. static PyObject* NameComparisonResult_getOrder(s_NameComparisonResult* self);
  48. static PyObject* NameComparisonResult_getCommonLabels(s_NameComparisonResult* self);
  49. static PyObject* NameComparisonResult_getRelation(s_NameComparisonResult* self);
  50. static PyMethodDef NameComparisonResult_methods[] = {
  51. { "get_order", reinterpret_cast<PyCFunction>(NameComparisonResult_getOrder), METH_NOARGS,
  52. "Returns the order" },
  53. { "get_common_labels", reinterpret_cast<PyCFunction>(NameComparisonResult_getCommonLabels), METH_NOARGS,
  54. "Returns the number of common labels" },
  55. { "get_relation", reinterpret_cast<PyCFunction>(NameComparisonResult_getRelation), METH_NOARGS,
  56. "Returns the relation" },
  57. { NULL, NULL, 0, NULL }
  58. };
  59. static PyTypeObject name_comparison_result_type = {
  60. PyVarObject_HEAD_INIT(NULL, 0)
  61. "pydnspp.NameComparisonResult",
  62. sizeof(s_NameComparisonResult), // tp_basicsize
  63. 0, // tp_itemsize
  64. (destructor)NameComparisonResult_destroy, // tp_dealloc
  65. NULL, // tp_print
  66. NULL, // tp_getattr
  67. NULL, // tp_setattr
  68. NULL, // tp_reserved
  69. NULL, // tp_repr
  70. NULL, // tp_as_number
  71. NULL, // tp_as_sequence
  72. NULL, // tp_as_mapping
  73. NULL, // tp_hash
  74. NULL, // tp_call
  75. NULL, // tp_str
  76. NULL, // tp_getattro
  77. NULL, // tp_setattro
  78. NULL, // tp_as_buffer
  79. Py_TPFLAGS_DEFAULT, // tp_flags
  80. "This is a supplemental class used only as a return value of Name.compare(). "
  81. "It encapsulate a tuple of the comparison: ordering, number of common labels, "
  82. "and relationship as follows:\n"
  83. "- ordering: relative ordering under the DNSSEC order relation\n"
  84. "- labels: the number of common significant labels of the two names being"
  85. " compared\n"
  86. "- relationship: see NameComparisonResult.NameRelation\n",
  87. NULL, // tp_traverse
  88. NULL, // tp_clear
  89. NULL, // tp_richcompare
  90. 0, // tp_weaklistoffset
  91. NULL, // tp_iter
  92. NULL, // tp_iternext
  93. NameComparisonResult_methods, // tp_methods
  94. NULL, // tp_members
  95. NULL, // tp_getset
  96. NULL, // tp_base
  97. NULL, // tp_dict
  98. NULL, // tp_descr_get
  99. NULL, // tp_descr_set
  100. 0, // tp_dictoffset
  101. (initproc)NameComparisonResult_init, // tp_init
  102. NULL, // tp_alloc
  103. PyType_GenericNew, // tp_new
  104. NULL, // tp_free
  105. NULL, // tp_is_gc
  106. NULL, // tp_bases
  107. NULL, // tp_mro
  108. NULL, // tp_cache
  109. NULL, // tp_subclasses
  110. NULL, // tp_weaklist
  111. NULL, // tp_del
  112. 0 // tp_version_tag
  113. };
  114. static int
  115. NameComparisonResult_init(s_NameComparisonResult*, PyObject*) {
  116. PyErr_SetString(PyExc_NotImplementedError,
  117. "NameComparisonResult can't be built directly");
  118. return (-1);
  119. }
  120. static void
  121. NameComparisonResult_destroy(s_NameComparisonResult* self) {
  122. delete self->ncr;
  123. self->ncr = NULL;
  124. Py_TYPE(self)->tp_free(self);
  125. }
  126. static PyObject*
  127. NameComparisonResult_getOrder(s_NameComparisonResult* self) {
  128. return (Py_BuildValue("i", self->ncr->getOrder()));
  129. }
  130. static PyObject*
  131. NameComparisonResult_getCommonLabels(s_NameComparisonResult* self) {
  132. return (Py_BuildValue("I", self->ncr->getCommonLabels()));
  133. }
  134. static PyObject*
  135. NameComparisonResult_getRelation(s_NameComparisonResult* self) {
  136. return (Py_BuildValue("I", self->ncr->getRelation()));
  137. }
  138. // end of NameComparisonResult
  139. // Name
  140. class s_Name : public PyObject {
  141. public:
  142. isc::dns::Name* name;
  143. size_t position;
  144. };
  145. static int Name_init(s_Name* self, PyObject* args);
  146. static void Name_destroy(s_Name* self);
  147. static PyObject* Name_toWire(s_Name* self, PyObject* args);
  148. static PyObject* Name_toText(s_Name* self);
  149. static PyObject* Name_str(PyObject* self);
  150. static PyObject* Name_getLabelCount(s_Name* self);
  151. static PyObject* Name_at(s_Name* self, PyObject* args);
  152. static PyObject* Name_getLength(s_Name* self);
  153. static PyObject* Name_compare(s_Name* self, PyObject* args);
  154. static PyObject* Name_equals(s_Name* self, PyObject* args);
  155. static PyObject* Name_richcmp(s_Name* self, s_Name* other, int op);
  156. static PyObject* Name_split(s_Name* self, PyObject* args);
  157. static PyObject* Name_reverse(s_Name* self);
  158. static PyObject* Name_concatenate(s_Name* self, PyObject* args);
  159. static PyObject* Name_downcase(s_Name* self);
  160. static PyObject* Name_isWildCard(s_Name* self);
  161. static PyMethodDef Name_methods[] = {
  162. { "at", reinterpret_cast<PyCFunction>(Name_at), METH_VARARGS,
  163. "Returns the integer value of the name data at the specified position" },
  164. { "get_length", reinterpret_cast<PyCFunction>(Name_getLength), METH_NOARGS,
  165. "Returns the length" },
  166. { "get_labelcount", reinterpret_cast<PyCFunction>(Name_getLabelCount), METH_NOARGS,
  167. "Returns the number of labels" },
  168. { "to_text", reinterpret_cast<PyCFunction>(Name_toText), METH_NOARGS,
  169. "Returns the string representation" },
  170. { "to_wire", reinterpret_cast<PyCFunction>(Name_toWire), METH_VARARGS,
  171. "Converts the Name object to wire format.\n"
  172. "The argument can be either a MessageRenderer or an object that "
  173. "implements the sequence interface. If the object is mutable "
  174. "(for instance a bytearray()), the wire data is added in-place.\n"
  175. "If it is not (for instance a bytes() object), a new object is "
  176. "returned" },
  177. { "compare", reinterpret_cast<PyCFunction>(Name_compare), METH_VARARGS,
  178. "Returns a NameComparisonResult object. The argument must be another Name object" },
  179. { "equals", reinterpret_cast<PyCFunction>(Name_equals), METH_VARARGS,
  180. "Returns true if the given Name object is equal to this one" },
  181. { "split", reinterpret_cast<PyCFunction>(Name_split), METH_VARARGS,
  182. "Splits the name, takes two arguments, the first is an integer "
  183. "specifying the first label to place in the result. The second "
  184. "is an integer specifying the number of labels to put in the "
  185. "result. Returns a new Name object" },
  186. { "reverse", reinterpret_cast<PyCFunction>(Name_reverse), METH_NOARGS,
  187. "Returns a new Name object that is the reverse of this one" },
  188. { "concatenate", reinterpret_cast<PyCFunction>(Name_concatenate), METH_VARARGS,
  189. "Concatenates the given Name object to this one and returns the "
  190. "result as a new Name object" },
  191. { "downcase", reinterpret_cast<PyCFunction>(Name_downcase), METH_NOARGS,
  192. "Downcases this name object (in-place). Returns a new reference to the Name." },
  193. { "is_wildcard", reinterpret_cast<PyCFunction>(Name_isWildCard), METH_NOARGS,
  194. "Returns True if the Name object represents a wildcard name." },
  195. { NULL, NULL, 0, NULL }
  196. };
  197. static PyTypeObject name_type = {
  198. PyVarObject_HEAD_INIT(NULL, 0)
  199. "pydnspp.Name",
  200. sizeof(s_Name), // tp_basicsize
  201. 0, // tp_itemsize
  202. (destructor)Name_destroy, // tp_dealloc
  203. NULL, // tp_print
  204. NULL, // tp_getattr
  205. NULL, // tp_setattr
  206. NULL, // tp_reserved
  207. NULL, // tp_repr
  208. NULL, // tp_as_number
  209. NULL, // tp_as_sequence
  210. NULL, // tp_as_mapping
  211. NULL, // tp_hash
  212. NULL, // tp_call
  213. Name_str, // tp_str
  214. NULL, // tp_getattro
  215. NULL, // tp_setattro
  216. NULL, // tp_as_buffer
  217. Py_TPFLAGS_DEFAULT, // tp_flags
  218. "The Name class encapsulates DNS names.\n"
  219. "It provides interfaces to construct a name from string or wire-format data, "
  220. "transform a name into a string or wire-format data, compare two names, get "
  221. "access to various properties of a name, etc.",
  222. NULL, // tp_traverse
  223. NULL, // tp_clear
  224. (richcmpfunc)Name_richcmp, // tp_richcompare
  225. 0, // tp_weaklistoffset
  226. NULL, // tp_iter
  227. NULL, // tp_iternext
  228. Name_methods, // tp_methods
  229. NULL, // tp_members
  230. NULL, // tp_getset
  231. NULL, // tp_base
  232. NULL, // tp_dict
  233. NULL, // tp_descr_get
  234. NULL, // tp_descr_set
  235. 0, // tp_dictoffset
  236. (initproc)Name_init, // tp_init
  237. NULL, // tp_alloc
  238. PyType_GenericNew, // tp_new
  239. NULL, // tp_free
  240. NULL, // tp_is_gc
  241. NULL, // tp_bases
  242. NULL, // tp_mro
  243. NULL, // tp_cache
  244. NULL, // tp_subclasses
  245. NULL, // tp_weaklist
  246. // Note: not sure if the following are correct. Added them just to
  247. // make the compiler happy.
  248. NULL, // tp_del
  249. 0 // tp_version_tag
  250. };
  251. static int
  252. Name_init(s_Name* self, PyObject* args) {
  253. const char* s;
  254. PyObject* downcase = Py_False;
  255. // Depending on the arguments in *args, we decide which of the
  256. // constructors is meant. If the first argument is of type string,
  257. // we use the string-based constructor. If it is a bytes object,
  258. // we use the wire-based one.
  259. if (PyArg_ParseTuple(args, "s|O!", &s, &PyBool_Type, &downcase)) {
  260. try {
  261. const std::string n(s);
  262. self->name = new Name(n, downcase == Py_True);
  263. self->position = 0;
  264. } catch (const EmptyLabel&) {
  265. PyErr_SetString(po_EmptyLabel, "EmptyLabel");
  266. return (-1);
  267. } catch (const TooLongLabel&) {
  268. PyErr_SetString(po_TooLongLabel, "TooLongLabel");
  269. return (-1);
  270. } catch (const BadLabelType&) {
  271. PyErr_SetString(po_BadLabelType, "BadLabelType");
  272. return (-1);
  273. } catch (const BadEscape&) {
  274. PyErr_SetString(po_BadEscape, "BadEscape");
  275. return (-1);
  276. } catch (const TooLongName&) {
  277. PyErr_SetString(po_TooLongName, "TooLongName");
  278. return (-1);
  279. } catch (const IncompleteName&) {
  280. PyErr_SetString(po_IncompleteName, "IncompleteName");
  281. return (-1);
  282. #ifdef CATCHMEMERR
  283. } catch (const std::bad_alloc&) {
  284. PyErr_NoMemory();
  285. return (-1);
  286. #endif
  287. } catch (...) {
  288. PyErr_SetString(po_IscException, "Unexpected?!");
  289. return (-1);
  290. }
  291. return (0);
  292. }
  293. PyErr_Clear();
  294. PyObject* bytes_obj;
  295. const char* bytes;
  296. Py_ssize_t len;
  297. long position = 0;
  298. // It was not a string (see comment above), so try bytes, and
  299. // create with buffer object
  300. if (PyArg_ParseTuple(args, "O|lO!", &bytes_obj, &position,
  301. &PyBool_Type, &downcase) &&
  302. PyObject_AsCharBuffer(bytes_obj, &bytes, &len) != -1) {
  303. try {
  304. if (position < 0) {
  305. // Throw IndexError here since name index should be unsigned
  306. PyErr_SetString(PyExc_IndexError,
  307. "Name index shouldn't be negative");
  308. return (-1);
  309. }
  310. InputBuffer buffer(bytes, len);
  311. buffer.setPosition(position);
  312. self->name = new Name(buffer, downcase == Py_True);
  313. self->position = buffer.getPosition();
  314. } catch (const InvalidBufferPosition&) {
  315. PyErr_SetString(po_InvalidBufferPosition,
  316. "InvalidBufferPosition");
  317. return (-1);
  318. } catch (const DNSMessageFORMERR&) {
  319. PyErr_SetString(po_DNSMessageFORMERR, "DNSMessageFORMERR");
  320. return (-1);
  321. } catch (...) {
  322. PyErr_SetString(po_IscException, "Unexpected?!");
  323. return (-1);
  324. }
  325. return (0);
  326. }
  327. PyErr_Clear();
  328. PyErr_SetString(PyExc_TypeError,
  329. "No valid types in Name constructor (should be string or sequence and offset");
  330. return (-1);
  331. }
  332. static void
  333. Name_destroy(s_Name* self) {
  334. delete self->name;
  335. self->name = NULL;
  336. Py_TYPE(self)->tp_free(self);
  337. }
  338. static PyObject*
  339. Name_at(s_Name* self, PyObject* args) {
  340. int pos;
  341. if (!PyArg_ParseTuple(args, "i", &pos)) {
  342. return (NULL);
  343. }
  344. if (pos < 0) {
  345. // Throw IndexError here since name index should be unsigned
  346. PyErr_SetString(PyExc_IndexError,
  347. "name index shouldn't be negative");
  348. return (NULL);
  349. }
  350. try {
  351. return (Py_BuildValue("I", self->name->at(pos)));
  352. } catch (const isc::OutOfRange&) {
  353. PyErr_SetString(PyExc_IndexError,
  354. "name index out of range");
  355. return (NULL);
  356. }
  357. }
  358. static PyObject*
  359. Name_getLength(s_Name* self) {
  360. return (Py_BuildValue("i", self->name->getLength()));
  361. }
  362. static PyObject*
  363. Name_getLabelCount(s_Name* self) {
  364. return (Py_BuildValue("i", self->name->getLabelCount()));
  365. }
  366. static PyObject*
  367. Name_toText(s_Name* self) {
  368. return (Py_BuildValue("s", self->name->toText().c_str()));
  369. }
  370. static PyObject*
  371. Name_str(PyObject* self) {
  372. // Simply call the to_text method we already defined
  373. // str() is not defined in the c++ version, only to_text
  374. // and we already have a wrapper for that one.
  375. return (PyObject_CallMethod(self,
  376. const_cast<char*>("to_text"),
  377. const_cast<char*>("")));
  378. }
  379. static PyObject*
  380. Name_toWire(s_Name* self, PyObject* args) {
  381. PyObject* bytes;
  382. s_MessageRenderer* mr;
  383. if (PyArg_ParseTuple(args, "O", &bytes) && PySequence_Check(bytes)) {
  384. PyObject* bytes_o = bytes;
  385. OutputBuffer buffer(Name::MAX_WIRE);
  386. self->name->toWire(buffer);
  387. PyObject* name_bytes = PyBytes_FromStringAndSize(static_cast<const char*>(buffer.getData()), buffer.getLength());
  388. PyObject* result = PySequence_InPlaceConcat(bytes_o, name_bytes);
  389. // We need to release the object we temporarily created here
  390. // to prevent memory leak
  391. Py_DECREF(name_bytes);
  392. return (result);
  393. } else if (PyArg_ParseTuple(args, "O!", &messagerenderer_type, &mr)) {
  394. self->name->toWire(*mr->messagerenderer);
  395. // If we return NULL it is seen as an error, so use this for
  396. // None returns
  397. Py_RETURN_NONE;
  398. }
  399. PyErr_Clear();
  400. PyErr_SetString(PyExc_TypeError,
  401. "toWire argument must be a sequence object or a MessageRenderer");
  402. return (NULL);
  403. }
  404. static PyObject*
  405. Name_compare(s_Name* self, PyObject* args) {
  406. s_Name* other;
  407. if (!PyArg_ParseTuple(args, "O!", &name_type, &other))
  408. return (NULL);
  409. s_NameComparisonResult* ret = PyObject_New(s_NameComparisonResult, &name_comparison_result_type);
  410. if (ret != NULL) {
  411. ret->ncr = new NameComparisonResult(
  412. self->name->compare(*other->name));
  413. }
  414. return (ret);
  415. }
  416. static PyObject*
  417. Name_equals(s_Name* self, PyObject* args) {
  418. s_Name* other;
  419. if (!PyArg_ParseTuple(args, "O!", &name_type, &other))
  420. return (NULL);
  421. if (self->name->equals(*other->name))
  422. Py_RETURN_TRUE;
  423. else
  424. Py_RETURN_FALSE;
  425. }
  426. static PyObject*
  427. Name_split(s_Name* self, PyObject* args) {
  428. int first, n;
  429. s_Name* ret = NULL;
  430. if (PyArg_ParseTuple(args, "ii", &first, &n)) {
  431. if (first < 0 || n < 0) {
  432. // Throw IndexError here since name index should be unsigned
  433. PyErr_SetString(PyExc_IndexError,
  434. "name index shouldn't be negative");
  435. return (NULL);
  436. }
  437. ret = PyObject_New(s_Name, &name_type);
  438. if (ret != NULL) {
  439. ret->name = NULL;
  440. try {
  441. ret->name = new Name(self->name->split(first, n));
  442. } catch(const isc::OutOfRange& oor) {
  443. PyErr_SetString(PyExc_IndexError, oor.what());
  444. ret->name = NULL;
  445. }
  446. if (ret->name == NULL) {
  447. Py_DECREF(ret);
  448. return (NULL);
  449. }
  450. }
  451. } else if (PyArg_ParseTuple(args, "i", &n)) {
  452. PyErr_Clear();
  453. if (n < 0) {
  454. // Throw IndexError here since name index should be unsigned
  455. PyErr_SetString(PyExc_IndexError,
  456. "name index shouldn't be negative");
  457. return (NULL);
  458. }
  459. ret = PyObject_New(s_Name, &name_type);
  460. if (ret != NULL) {
  461. ret->name = NULL;
  462. try {
  463. ret->name = new Name(self->name->split(n));
  464. } catch(const isc::OutOfRange& oor) {
  465. PyErr_SetString(PyExc_IndexError, oor.what());
  466. ret->name = NULL;
  467. }
  468. if (ret->name == NULL) {
  469. Py_DECREF(ret);
  470. return (NULL);
  471. }
  472. }
  473. }
  474. PyErr_Clear();
  475. PyErr_SetString(PyExc_TypeError,
  476. "No valid type in split argument");
  477. return (ret);
  478. }
  479. #include <iostream>
  480. //
  481. // richcmp defines the ==, !=, >, <, >= and <= operators in python
  482. // It is translated to a function that gets 3 arguments, an object,
  483. // an object to compare to, and an operator.
  484. //
  485. static PyObject*
  486. Name_richcmp(s_Name* self, s_Name* other, int op) {
  487. bool c;
  488. // Check for null and if the types match. If different type,
  489. // simply return False
  490. if (!other || (self->ob_type != other->ob_type)) {
  491. Py_RETURN_FALSE;
  492. }
  493. switch (op) {
  494. case Py_LT:
  495. c = *self->name < *other->name;
  496. break;
  497. case Py_LE:
  498. c = *self->name <= *other->name;
  499. break;
  500. case Py_EQ:
  501. c = *self->name == *other->name;
  502. break;
  503. case Py_NE:
  504. c = *self->name != *other->name;
  505. break;
  506. case Py_GT:
  507. c = *self->name > *other->name;
  508. break;
  509. case Py_GE:
  510. c = *self->name >= *other->name;
  511. break;
  512. default:
  513. PyErr_SetString(PyExc_IndexError,
  514. "Unhandled rich comparison operator");
  515. return (NULL);
  516. }
  517. if (c) {
  518. Py_RETURN_TRUE;
  519. } else {
  520. Py_RETURN_FALSE;
  521. }
  522. }
  523. static PyObject*
  524. Name_reverse(s_Name* self) {
  525. s_Name* ret = PyObject_New(s_Name, &name_type);
  526. if (ret != NULL) {
  527. ret->name = new Name(self->name->reverse());
  528. if (ret->name == NULL) {
  529. Py_DECREF(ret);
  530. return (NULL);
  531. }
  532. }
  533. return (ret);
  534. }
  535. static PyObject*
  536. Name_concatenate(s_Name* self, PyObject* args) {
  537. s_Name* other;
  538. if (!PyArg_ParseTuple(args, "O!", &name_type, &other))
  539. return (NULL);
  540. s_Name* ret = PyObject_New(s_Name, &name_type);
  541. if (ret != NULL) {
  542. try {
  543. ret->name = new Name(self->name->concatenate(*other->name));
  544. } catch (const TooLongName& tln) {
  545. PyErr_SetString(po_TooLongName, tln.what());
  546. return (NULL);
  547. }
  548. }
  549. return (ret);
  550. }
  551. static PyObject*
  552. Name_downcase(s_Name* self) {
  553. self->name->downcase();
  554. Py_INCREF(self);
  555. return (self);
  556. }
  557. static PyObject*
  558. Name_isWildCard(s_Name* self) {
  559. if (self->name->isWildcard()) {
  560. Py_RETURN_TRUE;
  561. } else {
  562. Py_RETURN_FALSE;
  563. }
  564. }
  565. // end of Name
  566. // Module Initialization, all statics are initialized here
  567. bool
  568. initModulePart_Name(PyObject* mod) {
  569. // Add the classes to the module
  570. // We initialize the static description object with PyType_Ready(),
  571. // then add it to the module
  572. //
  573. // NameComparisonResult
  574. //
  575. if (PyType_Ready(&name_comparison_result_type) < 0) {
  576. return (false);
  577. }
  578. Py_INCREF(&name_comparison_result_type);
  579. // Add the enums to the module
  580. po_NameRelation = Py_BuildValue("{i:s,i:s,i:s,i:s}",
  581. NameComparisonResult::SUPERDOMAIN, "SUPERDOMAIN",
  582. NameComparisonResult::SUBDOMAIN, "SUBDOMAIN",
  583. NameComparisonResult::EQUAL, "EQUAL",
  584. NameComparisonResult::COMMONANCESTOR, "COMMONANCESTOR");
  585. addClassVariable(name_comparison_result_type, "NameRelation", po_NameRelation);
  586. PyModule_AddObject(mod, "NameComparisonResult",
  587. reinterpret_cast<PyObject*>(&name_comparison_result_type));
  588. //
  589. // Name
  590. //
  591. if (PyType_Ready(&name_type) < 0) {
  592. return (false);
  593. }
  594. Py_INCREF(&name_type);
  595. // Add the constants to the module
  596. addClassVariable(name_type, "MAX_WIRE", Py_BuildValue("I", Name::MAX_WIRE));
  597. addClassVariable(name_type, "MAX_LABELS", Py_BuildValue("I", Name::MAX_LABELS));
  598. addClassVariable(name_type, "MAX_LABELLEN", Py_BuildValue("I", Name::MAX_LABELLEN));
  599. addClassVariable(name_type, "MAX_COMPRESS_POINTER", Py_BuildValue("I", Name::MAX_COMPRESS_POINTER));
  600. addClassVariable(name_type, "COMPRESS_POINTER_MARK8", Py_BuildValue("I", Name::COMPRESS_POINTER_MARK8));
  601. addClassVariable(name_type, "COMPRESS_POINTER_MARK16", Py_BuildValue("I", Name::COMPRESS_POINTER_MARK16));
  602. s_Name* root_name = PyObject_New(s_Name, &name_type);
  603. root_name->name = new Name(Name::ROOT_NAME());
  604. PyObject* po_ROOT_NAME = root_name;
  605. addClassVariable(name_type, "ROOT_NAME", po_ROOT_NAME);
  606. PyModule_AddObject(mod, "Name",
  607. reinterpret_cast<PyObject*>(&name_type));
  608. // Add the exceptions to the module
  609. po_EmptyLabel = PyErr_NewException("pydnspp.EmptyLabel", NULL, NULL);
  610. PyModule_AddObject(mod, "EmptyLabel", po_EmptyLabel);
  611. po_TooLongName = PyErr_NewException("pydnspp.TooLongName", NULL, NULL);
  612. PyModule_AddObject(mod, "TooLongName", po_TooLongName);
  613. po_TooLongLabel = PyErr_NewException("pydnspp.TooLongLabel", NULL, NULL);
  614. PyModule_AddObject(mod, "TooLongLabel", po_TooLongLabel);
  615. po_BadLabelType = PyErr_NewException("pydnspp.BadLabelType", NULL, NULL);
  616. PyModule_AddObject(mod, "BadLabelType", po_BadLabelType);
  617. po_BadEscape = PyErr_NewException("pydnspp.BadEscape", NULL, NULL);
  618. PyModule_AddObject(mod, "BadEscape", po_BadEscape);
  619. po_IncompleteName = PyErr_NewException("pydnspp.IncompleteName", NULL, NULL);
  620. PyModule_AddObject(mod, "IncompleteName", po_IncompleteName);
  621. po_InvalidBufferPosition = PyErr_NewException("pydnspp.InvalidBufferPosition", NULL, NULL);
  622. PyModule_AddObject(mod, "InvalidBufferPosition", po_InvalidBufferPosition);
  623. // This one could have gone into the message_python.cc file, but is
  624. // already needed here.
  625. po_DNSMessageFORMERR = PyErr_NewException("pydnspp.DNSMessageFORMERR", NULL, NULL);
  626. PyModule_AddObject(mod, "DNSMessageFORMERR", po_DNSMessageFORMERR);
  627. return (true);
  628. }