Branch data Line data Source code
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 : : #include <Python.h>
16 : :
17 : : #include <exceptions/exceptions.h>
18 : : #include <dns/rcode.h>
19 : : #include <util/python/pycppwrapper_util.h>
20 : :
21 : : #include "pydnspp_common.h"
22 : : #include "rcode_python.h"
23 : :
24 : : using namespace isc::dns;
25 : : using namespace isc::dns::python;
26 : : using namespace isc::util::python;
27 : :
28 : : namespace {
29 : : // The s_* Class simply covers one instantiation of the object.
30 : : //
31 : : // We added a helper variable static_code here
32 : : // Since we can create Rcodes dynamically with Rcode(int), but also
33 : : // use the static globals (Rcode::NOERROR() etc), we use this
34 : : // variable to see if the code came from one of the latter, in which
35 : : // case Rcode_destroy should not free it (the other option is to
36 : : // allocate new Rcodes for every use of the static ones, but this
37 : : // seems more efficient).
38 : : //
39 : : // Follow-up note: we don't have to use the proxy function in the python lib;
40 : : // we can just define class specific constants directly (see TSIGError).
41 : : // We should make this cleanup later.
42 : : class s_Rcode : public PyObject {
43 : : public:
44 : : s_Rcode() : cppobj(NULL), static_code(false) {};
45 : : const Rcode* cppobj;
46 : : bool static_code;
47 : : };
48 : :
49 : : typedef CPPPyObjectContainer<s_Rcode, Rcode> RcodeContainer;
50 : :
51 : : int Rcode_init(s_Rcode* const self, PyObject* args);
52 : : void Rcode_destroy(s_Rcode* const self);
53 : :
54 : : PyObject* Rcode_getCode(const s_Rcode* const self);
55 : : PyObject* Rcode_getExtendedCode(const s_Rcode* const self);
56 : : PyObject* Rcode_toText(const s_Rcode* const self);
57 : : PyObject* Rcode_str(PyObject* self);
58 : : PyObject* Rcode_NOERROR(const s_Rcode* self);
59 : : PyObject* Rcode_FORMERR(const s_Rcode* self);
60 : : PyObject* Rcode_SERVFAIL(const s_Rcode* self);
61 : : PyObject* Rcode_NXDOMAIN(const s_Rcode* self);
62 : : PyObject* Rcode_NOTIMP(const s_Rcode* self);
63 : : PyObject* Rcode_REFUSED(const s_Rcode* self);
64 : : PyObject* Rcode_YXDOMAIN(const s_Rcode* self);
65 : : PyObject* Rcode_YXRRSET(const s_Rcode* self);
66 : : PyObject* Rcode_NXRRSET(const s_Rcode* self);
67 : : PyObject* Rcode_NOTAUTH(const s_Rcode* self);
68 : : PyObject* Rcode_NOTZONE(const s_Rcode* self);
69 : : PyObject* Rcode_RESERVED11(const s_Rcode* self);
70 : : PyObject* Rcode_RESERVED12(const s_Rcode* self);
71 : : PyObject* Rcode_RESERVED13(const s_Rcode* self);
72 : : PyObject* Rcode_RESERVED14(const s_Rcode* self);
73 : : PyObject* Rcode_RESERVED15(const s_Rcode* self);
74 : : PyObject* Rcode_BADVERS(const s_Rcode* self);
75 : : PyObject* Rcode_richcmp(const s_Rcode* const self,
76 : : const s_Rcode* const other, int op);
77 : :
78 : : PyMethodDef Rcode_methods[] = {
79 : : { "get_code", reinterpret_cast<PyCFunction>(Rcode_getCode), METH_NOARGS,
80 : : "Returns the code value" },
81 : : { "get_extended_code",
82 : : reinterpret_cast<PyCFunction>(Rcode_getExtendedCode), METH_NOARGS,
83 : : "Returns the upper 8-bit part of the extended code value" },
84 : : { "to_text", reinterpret_cast<PyCFunction>(Rcode_toText), METH_NOARGS,
85 : : "Returns the text representation" },
86 : : { "NOERROR", reinterpret_cast<PyCFunction>(Rcode_NOERROR),
87 : : METH_NOARGS | METH_STATIC, "Creates a NOERROR Rcode" },
88 : : { "FORMERR", reinterpret_cast<PyCFunction>(Rcode_FORMERR),
89 : : METH_NOARGS | METH_STATIC, "Creates a FORMERR Rcode" },
90 : : { "SERVFAIL", reinterpret_cast<PyCFunction>(Rcode_SERVFAIL),
91 : : METH_NOARGS | METH_STATIC, "Creates a SERVFAIL Rcode" },
92 : : { "NXDOMAIN", reinterpret_cast<PyCFunction>(Rcode_NXDOMAIN),
93 : : METH_NOARGS | METH_STATIC, "Creates a NXDOMAIN Rcode" },
94 : : { "NOTIMP", reinterpret_cast<PyCFunction>(Rcode_NOTIMP),
95 : : METH_NOARGS | METH_STATIC, "Creates a NOTIMP Rcode" },
96 : : { "REFUSED", reinterpret_cast<PyCFunction>(Rcode_REFUSED),
97 : : METH_NOARGS | METH_STATIC, "Creates a REFUSED Rcode" },
98 : : { "YXDOMAIN", reinterpret_cast<PyCFunction>(Rcode_YXDOMAIN),
99 : : METH_NOARGS | METH_STATIC, "Creates a YXDOMAIN Rcode" },
100 : : { "YXRRSET", reinterpret_cast<PyCFunction>(Rcode_YXRRSET),
101 : : METH_NOARGS | METH_STATIC, "Creates a YYRRSET Rcode" },
102 : : { "NXRRSET", reinterpret_cast<PyCFunction>(Rcode_NXRRSET),
103 : : METH_NOARGS | METH_STATIC, "Creates a NXRRSET Rcode" },
104 : : { "NOTAUTH", reinterpret_cast<PyCFunction>(Rcode_NOTAUTH),
105 : : METH_NOARGS | METH_STATIC, "Creates a NOTAUTH Rcode" },
106 : : { "NOTZONE", reinterpret_cast<PyCFunction>(Rcode_NOTZONE),
107 : : METH_NOARGS | METH_STATIC, "Creates a NOTZONE Rcode" },
108 : : { "RESERVED11", reinterpret_cast<PyCFunction>(Rcode_RESERVED11),
109 : : METH_NOARGS | METH_STATIC, "Creates a RESERVED11 Rcode" },
110 : : { "RESERVED12", reinterpret_cast<PyCFunction>(Rcode_RESERVED12),
111 : : METH_NOARGS | METH_STATIC, "Creates a RESERVED12 Rcode" },
112 : : { "RESERVED13", reinterpret_cast<PyCFunction>(Rcode_RESERVED13),
113 : : METH_NOARGS | METH_STATIC, "Creates a RESERVED13 Rcode" },
114 : : { "RESERVED14", reinterpret_cast<PyCFunction>(Rcode_RESERVED14),
115 : : METH_NOARGS | METH_STATIC, "Creates a RESERVED14 Rcode" },
116 : : { "RESERVED15", reinterpret_cast<PyCFunction>(Rcode_RESERVED15),
117 : : METH_NOARGS | METH_STATIC, "Creates a RESERVED15 Rcode" },
118 : : { "BADVERS", reinterpret_cast<PyCFunction>(Rcode_BADVERS),
119 : : METH_NOARGS | METH_STATIC, "Creates a BADVERS Rcode" },
120 : : { NULL, NULL, 0, NULL }
121 : : };
122 : :
123 : : int
124 : 50 : Rcode_init(s_Rcode* const self, PyObject* args) {
125 : 50 : long code = 0;
126 : 50 : int ext_code = 0;
127 : :
128 [ + + ]: 50 : if (PyArg_ParseTuple(args, "l", &code)) {
129 [ + + ]: 40 : if (code < 0 || code > 0xffff) {
130 : 1 : PyErr_SetString(PyExc_ValueError, "Rcode out of range");
131 : 1 : return (-1);
132 : : }
133 : 39 : ext_code = -1;
134 [ + + ]: 10 : } else if (PyArg_ParseTuple(args, "li", &code, &ext_code)) {
135 [ + + ][ + - ]: 9 : if (code < 0 || code > 0xff || ext_code < 0 || ext_code > 0xff) {
[ + + ]
136 : 2 : PyErr_SetString(PyExc_ValueError, "Rcode out of range");
137 : 2 : return (-1);
138 : : }
139 : : } else {
140 : 1 : PyErr_Clear();
141 : : PyErr_SetString(PyExc_TypeError,
142 : 1 : "Invalid arguments to Rcode constructor");
143 : 1 : return (-1);
144 : : }
145 : : try {
146 [ + + ]: 46 : if (ext_code == -1) {
147 [ + - ][ + + ]: 39 : self->cppobj = new Rcode(code);
148 : : } else {
149 [ + - ][ + + ]: 7 : self->cppobj = new Rcode(code, ext_code);
150 : : }
151 : 43 : self->static_code = false;
152 : 6 : } catch (const isc::OutOfRange& ex) {
153 [ - + ]: 3 : PyErr_SetString(PyExc_OverflowError, ex.what());
154 : : return (-1);
155 [ + - ]: 3 : } catch (...) {
156 [ # # ]: 0 : PyErr_SetString(po_IscException, "Unexpected exception");
157 : : return (-1);
158 : : }
159 : 50 : return (0);
160 : : }
161 : :
162 : : void
163 : 923 : Rcode_destroy(s_Rcode* const self) {
164 : : // Depending on whether we created the rcode or are referring
165 : : // to a global one, we do or do not delete self->cppobj here
166 [ + + ]: 923 : if (!self->static_code) {
167 : 59 : delete self->cppobj;
168 : : }
169 : 923 : self->cppobj = NULL;
170 : 923 : Py_TYPE(self)->tp_free(self);
171 : 923 : }
172 : :
173 : : PyObject*
174 : 41 : Rcode_getCode(const s_Rcode* const self) {
175 : 41 : return (Py_BuildValue("I", self->cppobj->getCode()));
176 : : }
177 : :
178 : : PyObject*
179 : 9 : Rcode_getExtendedCode(const s_Rcode* const self) {
180 : 9 : return (Py_BuildValue("I", self->cppobj->getExtendedCode()));
181 : : }
182 : :
183 : : PyObject*
184 : 62 : Rcode_toText(const s_Rcode* const self) {
185 [ + - ]: 62 : return (Py_BuildValue("s", self->cppobj->toText().c_str()));
186 : : }
187 : :
188 : : PyObject*
189 : 4 : Rcode_str(PyObject* self) {
190 : : // Simply call the to_text method we already defined
191 : : return (PyObject_CallMethod(self, const_cast<char*>("to_text"),
192 : 4 : const_cast<char*>("")));
193 : : }
194 : :
195 : : PyObject*
196 : 659 : Rcode_createStatic(const Rcode& rcode) {
197 : 659 : s_Rcode* ret = PyObject_New(s_Rcode, &rcode_type);
198 [ + - ]: 659 : if (ret != NULL) {
199 : 659 : ret->cppobj = &rcode;
200 : 659 : ret->static_code = true;
201 : : }
202 : 659 : return (ret);
203 : : }
204 : :
205 : : PyObject*
206 : 546 : Rcode_NOERROR(const s_Rcode*) {
207 : 546 : return (Rcode_createStatic(Rcode::NOERROR()));
208 : : }
209 : :
210 : : PyObject*
211 : 14 : Rcode_FORMERR(const s_Rcode*) {
212 : 14 : return (Rcode_createStatic(Rcode::FORMERR()));
213 : : }
214 : :
215 : : PyObject*
216 : 16 : Rcode_SERVFAIL(const s_Rcode*) {
217 : 16 : return (Rcode_createStatic(Rcode::SERVFAIL()));
218 : : }
219 : :
220 : : PyObject*
221 : 1 : Rcode_NXDOMAIN(const s_Rcode*) {
222 : 1 : return (Rcode_createStatic(Rcode::NXDOMAIN()));
223 : : }
224 : :
225 : : PyObject*
226 : 2 : Rcode_NOTIMP(const s_Rcode*) {
227 : 2 : return (Rcode_createStatic(Rcode::NOTIMP()));
228 : : }
229 : :
230 : : PyObject*
231 : 33 : Rcode_REFUSED(const s_Rcode*) {
232 : 33 : return (Rcode_createStatic(Rcode::REFUSED()));
233 : : }
234 : :
235 : : PyObject*
236 : 1 : Rcode_YXDOMAIN(const s_Rcode*) {
237 : 1 : return (Rcode_createStatic(Rcode::YXDOMAIN()));
238 : : }
239 : :
240 : : PyObject*
241 : 2 : Rcode_YXRRSET(const s_Rcode*) {
242 : 2 : return (Rcode_createStatic(Rcode::YXRRSET()));
243 : : }
244 : :
245 : : PyObject*
246 : 1 : Rcode_NXRRSET(const s_Rcode*) {
247 : 1 : return (Rcode_createStatic(Rcode::NXRRSET()));
248 : : }
249 : :
250 : : PyObject*
251 : 29 : Rcode_NOTAUTH(const s_Rcode*) {
252 : 29 : return (Rcode_createStatic(Rcode::NOTAUTH()));
253 : : }
254 : :
255 : : PyObject*
256 : 1 : Rcode_NOTZONE(const s_Rcode*) {
257 : 1 : return (Rcode_createStatic(Rcode::NOTZONE()));
258 : : }
259 : :
260 : : PyObject*
261 : 1 : Rcode_RESERVED11(const s_Rcode*) {
262 : 1 : return (Rcode_createStatic(Rcode::RESERVED11()));
263 : : }
264 : :
265 : : PyObject*
266 : 1 : Rcode_RESERVED12(const s_Rcode*) {
267 : 1 : return (Rcode_createStatic(Rcode::RESERVED12()));
268 : : }
269 : :
270 : : PyObject*
271 : 1 : Rcode_RESERVED13(const s_Rcode*) {
272 : 1 : return (Rcode_createStatic(Rcode::RESERVED13()));
273 : : }
274 : :
275 : : PyObject*
276 : 1 : Rcode_RESERVED14(const s_Rcode*) {
277 : 1 : return (Rcode_createStatic(Rcode::RESERVED14()));
278 : : }
279 : :
280 : : PyObject*
281 : 2 : Rcode_RESERVED15(const s_Rcode*) {
282 : 2 : return (Rcode_createStatic(Rcode::RESERVED15()));
283 : : }
284 : :
285 : : PyObject*
286 : 7 : Rcode_BADVERS(const s_Rcode*) {
287 : 7 : return (Rcode_createStatic(Rcode::BADVERS()));
288 : : }
289 : :
290 : : PyObject*
291 : 230 : Rcode_richcmp(const s_Rcode* const self, const s_Rcode* const other,
292 : : const int op)
293 : : {
294 : 230 : bool c = false;
295 : :
296 : : // Check for null and if the types match. If different type,
297 : : // simply return False
298 [ + - ][ + + ]: 230 : if (!other || (self->ob_type != other->ob_type)) {
299 : 1 : Py_RETURN_FALSE;
300 : : }
301 : :
302 : : // Only equals and not equals here, unorderable type
303 [ + + + + : 229 : switch (op) {
+ + - ]
304 : : case Py_LT:
305 : 1 : PyErr_SetString(PyExc_TypeError, "Unorderable type; Rcode");
306 : 1 : return (NULL);
307 : : case Py_LE:
308 : 1 : PyErr_SetString(PyExc_TypeError, "Unorderable type; Rcode");
309 : 1 : return (NULL);
310 : : case Py_EQ:
311 : 120 : c = (*self->cppobj == *other->cppobj);
312 : 60 : break;
313 : : case Py_NE:
314 : 330 : c = (*self->cppobj != *other->cppobj);
315 : 165 : break;
316 : : case Py_GT:
317 : 1 : PyErr_SetString(PyExc_TypeError, "Unorderable type; Rcode");
318 : 1 : return (NULL);
319 : : case Py_GE:
320 : 1 : PyErr_SetString(PyExc_TypeError, "Unorderable type; Rcode");
321 : 1 : return (NULL);
322 : : }
323 [ + + ]: 225 : if (c)
324 : 51 : Py_RETURN_TRUE;
325 : : else
326 : 230 : Py_RETURN_FALSE;
327 : : }
328 : : } // end of unnamed namespace
329 : :
330 : : namespace isc {
331 : : namespace dns {
332 : : namespace python {
333 : : PyTypeObject rcode_type = {
334 : : PyVarObject_HEAD_INIT(NULL, 0)
335 : : "pydnspp.Rcode",
336 : : sizeof(s_Rcode), // tp_basicsize
337 : : 0, // tp_itemsize
338 : : (destructor)Rcode_destroy, // tp_dealloc
339 : : NULL, // tp_print
340 : : NULL, // tp_getattr
341 : : NULL, // tp_setattr
342 : : NULL, // tp_reserved
343 : : NULL, // tp_repr
344 : : NULL, // tp_as_number
345 : : NULL, // tp_as_sequence
346 : : NULL, // tp_as_mapping
347 : : NULL, // tp_hash
348 : : NULL, // tp_call
349 : : Rcode_str, // tp_str
350 : : NULL, // tp_getattro
351 : : NULL, // tp_setattro
352 : : NULL, // tp_as_buffer
353 : : Py_TPFLAGS_DEFAULT, // tp_flags
354 : : "The Rcode class objects represent standard RCODEs"
355 : : "of the header section of DNS messages.",
356 : : NULL, // tp_traverse
357 : : NULL, // tp_clear
358 : : reinterpret_cast<richcmpfunc>(Rcode_richcmp), // tp_richcompare
359 : : 0, // tp_weaklistoffset
360 : : NULL, // tp_iter
361 : : NULL, // tp_iternext
362 : : Rcode_methods, // tp_methods
363 : : NULL, // tp_members
364 : : NULL, // tp_getset
365 : : NULL, // tp_base
366 : : NULL, // tp_dict
367 : : NULL, // tp_descr_get
368 : : NULL, // tp_descr_set
369 : : 0, // tp_dictoffset
370 : : (initproc)Rcode_init, // tp_init
371 : : NULL, // tp_alloc
372 : : PyType_GenericNew, // tp_new
373 : : NULL, // tp_free
374 : : NULL, // tp_is_gc
375 : : NULL, // tp_bases
376 : : NULL, // tp_mro
377 : : NULL, // tp_cache
378 : : NULL, // tp_subclasses
379 : : NULL, // tp_weaklist
380 : : NULL, // tp_del
381 : : 0 // tp_version_tag
382 : : };
383 : :
384 : : PyObject*
385 : 215 : createRcodeObject(const Rcode& source) {
386 : 215 : RcodeContainer container(PyObject_New(s_Rcode, &rcode_type));
387 [ + - ][ + - ]: 215 : container.set(new Rcode(source));
388 : 215 : return (container.release());
389 : : }
390 : :
391 : : bool
392 : 0 : PyRcode_Check(PyObject* obj) {
393 [ # # ]: 0 : if (obj == NULL) {
394 [ # # ][ # # ]: 0 : isc_throw(PyCPPWrapperException, "obj argument NULL in typecheck");
395 : : }
396 [ # # ][ # # ]: 0 : return (PyObject_TypeCheck(obj, &rcode_type));
397 : : }
398 : :
399 : : const Rcode&
400 : 438 : PyRcode_ToRcode(const PyObject* rcode_obj) {
401 [ - + ]: 438 : if (rcode_obj == NULL) {
402 [ # # ][ # # ]: 0 : isc_throw(PyCPPWrapperException,
403 : : "obj argument NULL in Rcode PyObject conversion");
404 : : }
405 : 438 : const s_Rcode* rcode = static_cast<const s_Rcode*>(rcode_obj);
406 : 438 : return (*rcode->cppobj);
407 : : }
408 : :
409 : : } // namespace python
410 : : } // namespace dns
411 : 0 : } // namespace isc
|