1 /*
2 ** Copyright (C) 2007-2020 by Carnegie Mellon University.
3 **
4 ** @OPENSOURCE_LICENSE_START@
5 ** See license information in ../../LICENSE.txt
6 ** @OPENSOURCE_LICENSE_END@
7 */
8
9 /*
10 ** Python wrappers
11 **
12 */
13
14 #define PY_SSIZE_T_CLEAN /* "s#" "y#" formats must use ssize_t */
15 #include <Python.h> /* Must be included before any system
16 headers */
17 #include <silk/silk.h>
18
19 RCSIDENT("$SiLK: pysilk.c 01d273aa43de 2020-04-16 15:57:54Z mthomas $");
20
21 #include <silk/rwrec.h>
22 #include <silk/skbag.h>
23 #include <silk/skcountry.h>
24 #include <silk/skipaddr.h>
25 #include <silk/skipset.h>
26 #include <silk/skprefixmap.h>
27 #include <silk/sksite.h>
28 #include <silk/skstream.h>
29 #include <silk/skvector.h>
30 #include <silk/utils.h>
31 #include <datetime.h>
32 #include <structmember.h>
33 #include "pysilk_common.h"
34
35 SK_DIAGNOSTIC_IGNORE_PUSH("-Wwrite-strings")
36 SK_DIAGNOSTIC_IGNORE_PUSH("-Wcast-function-type")
37
38
39 /* LOCAL DEFINES AND TYPEDEFS */
40
41 #define MAX_EPOCH (((INT64_C(1) << 31)-1)*1000) /* Tue Jan 19 03:14:07 2038 */
42
43 #define XSTR(s) #s
44 #define STR(s) XSTR(s)
45
46
47 /* In Python 2.4, length()-type functions are 'inquiry's that return
48 * int. In Python 2.5, they are 'lenfunc's that return Py_ssize_t. */
49 #if PY_VERSION_HEX < 0x02050000
50 #define Py_ssize_t int
51 #define PY_SSIZE_T_MAX INT_MAX
52 #endif
53
54 #define NOT_SET -9999
55
56 #if SK_ENABLE_IPV6
57 #define UNUSED_NOv6(x) x
58 #else
59 #define UNUSED_NOv6(x) UNUSED(x)
60 #endif
61
62
63 #define CHECK_SITE(err) \
64 do { \
65 if (init_site(NULL)) { \
66 return err; \
67 } \
68 } while(0)
69
70
71 /*
72 * ASSERT_RESULT(ar_func_args, ar_type, ar_expected);
73 *
74 * ar_func_args -- is a function and any arguments it requires
75 * ar_type -- is the type that ar_func_args returns
76 * ar_expected -- is the expected return value from ar_func_args
77 *
78 * If assert() is disabled, simply call 'ar_func_args'.
79 *
80 * If assert() is enabled, call 'ar_func_args', capture its result,
81 * and assert() that its result is 'ar_expected'.
82 */
83 #ifdef NDEBUG
84 /* asserts are disabled; just call the function */
85 #define ASSERT_RESULT(ar_func_args, ar_type, ar_expected) ar_func_args
86 #else
87 #define ASSERT_RESULT(ar_func_args, ar_type, ar_expected) \
88 do { \
89 ar_type ar_rv = (ar_func_args); \
90 assert(ar_rv == (ar_expected)); \
91 } while(0)
92 #endif
93
94
95 typedef skBagErr_t (*silkBagModFn)(
96 skBag_t *,
97 const skBagTypedKey_t *,
98 const skBagTypedCounter_t *,
99 skBagTypedCounter_t *);
100
101 typedef struct silkpy_globals_st {
102 PyObject *silkmod;
103 PyObject *timedelta;
104 PyObject *datetime;
105 PyObject *maxelapsed;
106 PyObject *minelapsed;
107 PyObject *epochtime;
108 PyObject *maxtime;
109 PyObject *thousand;
110 PyObject *havesite;
111 PyObject *sensors;
112 PyObject *classes;
113 PyObject *flowtypes;
114 PyObject *newrawrec;
115 PyObject *maxintipv4;
116 #if SK_ENABLE_IPV6
117 PyObject *maxintipv6;
118 #endif
119 int site_configured;
120 } silkpy_globals_t;
121
122
123 /* LOCAL VARIABLE DEFINITIONS */
124
125 static char error_buffer[1024];
126
127 #if PY_MAJOR_VERSION >= 3
128 /* Global state for 3.0 Python is found by searching for this
129 * module */
130 static struct PyModuleDef *pysilk_module = NULL;
131
132 #define GLOBALS \
133 ((silkpy_globals_t*)PyModule_GetState(PyState_FindModule(pysilk_module)))
134
135 #else
136
137 /* Global state for Pre-3.0 Python */
138 static silkpy_globals_t silkpy_globals_static;
139
140 #define GLOBALS (&silkpy_globals_static)
141
142 #endif /* #else of #if PY_MAJOR_VERSION >= 3 */
143
144 /* A pointer to pass as the closure to C functions that implement
145 * multiple Python functions where some of the Python function
146 * names are deprecated. */
147 static const char deprecated_true_str[] = "1";
148
149 /* Cast away the const */
150 #define deprecated_true ((void*)deprecated_true_str)
151
152
153 /* LOCAL FUNCTION PROTOTYPES */
154
155 /* basic support functions */
156 static PyObject *
157 any_obj_error(
158 PyObject *exc,
159 const char *format,
160 PyObject *obj);
161 #ifdef TEST_PRINTF_FORMATS
162 #define error_printf printf
163 #else /* TEST_PRINTF_FORMATS */
164 static int
165 error_printf(
166 const char *fmt,
167 ...)
168 SK_CHECK_PRINTF(1, 2);
169 #endif
170 static int init_classes(void);
171 static int init_flowtypes(void);
172 static int init_sensors(void);
173 static int
174 init_silkfile_module(
175 PyObject *mod);
176 static int
177 init_site(
178 const char *site_file);
179 static PyObject *
180 initpysilkbase(
181 char* name);
182 static PyObject *
183 iter_iter(
184 PyObject *self);
185 static void
186 obj_dealloc(
187 PyObject *obj);
188 static PyObject *
189 obj_error(
190 const char *format,
191 PyObject *obj);
192 static skstream_t *
193 open_silkfile_write(
194 PyObject *args,
195 PyObject *kwds);
196 static PyObject *
197 reduce_error(
198 PyObject *self);
199 static int
200 silkPyDatetimeToSktime(
201 sktime_t *silktime,
202 PyObject *datetime);
203 #if !SK_ENABLE_IPV6
204 static PyObject *
205 silkPyNotImplemented(
206 PyObject UNUSED(*self),
207 PyObject UNUSED(*args),
208 PyObject UNUSED(*kwds));
209 #endif
210
211
212 /* FUNCTION DEFINITIONS */
213
214
215 /*
216 *************************************************************************
217 * IPAddr
218 *************************************************************************
219 */
220
221 typedef struct silkPyIPAddr_st {
222 PyObject_HEAD
223 skipaddr_t addr;
224 } silkPyIPAddr;
225
226 /* function prototypes */
227 static PyObject *
228 silkPyIPAddr_country_code(
229 silkPyIPAddr *self);
230 static long
231 silkPyIPAddr_hash(
232 silkPyIPAddr *obj);
233 static PyObject *
234 silkPyIPAddr_int(
235 silkPyIPAddr *obj);
236 static PyObject *
237 silkPyIPAddr_is_ipv6(
238 silkPyIPAddr UNUSED_NOv6(*self));
239 static PyObject *
240 silkPyIPAddr_isipv6_deprecated(
241 silkPyIPAddr *self);
242 static PyObject *
243 silkPyIPAddr_mask(
244 silkPyIPAddr *self,
245 PyObject *mask);
246 static PyObject *
247 silkPyIPAddr_mask_prefix(
248 silkPyIPAddr *self,
249 PyObject *prefix);
250 static PyObject *
251 silkPyIPAddr_new(
252 PyTypeObject *type,
253 PyObject *args,
254 PyObject *kwds);
255 static PyObject *
256 silkPyIPAddr_octets(
257 silkPyIPAddr *self);
258 static PyObject *
259 silkPyIPAddr_padded(
260 silkPyIPAddr *obj);
261 static PyObject *
262 silkPyIPAddr_repr(
263 silkPyIPAddr *obj);
264 static PyObject *
265 silkPyIPAddr_richcompare(
266 silkPyIPAddr *self,
267 PyObject *obj,
268 int cmp);
269 static int
270 silkPyIPAddr_setup(
271 PyObject *mod);
272 static PyObject *
273 silkPyIPAddr_str(
274 silkPyIPAddr *obj);
275 static PyObject *
276 silkPyIPAddr_to_ipv4(
277 PyObject *self);
278 #if SK_ENABLE_IPV6
279 static PyObject *
280 silkPyIPAddr_to_ipv6(
281 PyObject *self);
282 #endif
283 static int
284 silkPyIPv4Addr_init(
285 silkPyIPAddr *self,
286 PyObject *args,
287 PyObject *kwds);
288 static PyObject *
289 silkPyIPv4Addr_new(
290 PyTypeObject *type,
291 PyObject *args,
292 PyObject *kwds);
293 static int
294 silkPyIPv6Addr_init(
295 silkPyIPAddr *self,
296 PyObject *args,
297 PyObject *kwds);
298 #if SK_ENABLE_IPV6
299 static PyObject *
300 silkPyIPv6Addr_new(
301 PyTypeObject *type,
302 PyObject *args,
303 PyObject *kwds);
304 #endif
305 static PyObject *
306 silkPyIPvXAddr_new(
307 PyTypeObject *basetype,
308 PyTypeObject *type,
309 PyObject *args,
310 PyObject *kwds);
311
312 /* define docs and methods */
313 #define silkPyIPAddr_doc \
314 "IPAddr(string) -> ip address\n" \
315 "IPAddr(ipaddr) -> copy of ip address"
316
317 #define silkPyIPv4Addr_doc \
318 "IPv4Addr(string) -> IPv4 address\n" \
319 "IPv4Addr(int) -> IPv4 address\n" \
320 "IPv4Addr(IPV6Addr) -> IPv4 from IPv4 in IPv6 address\n" \
321 "IPv4Addr(IPv4Addr) -> copy of ip address"
322
323 #define silkPyIPv6Addr_doc \
324 "IPv6Addr(string) -> IPv6 address\n" \
325 "IPv6Addr(int) -> IPv6 address\n" \
326 "IPv6Addr(IPV4Addr) -> IPv4 in IPv6 address\n" \
327 "IPv6Addr(IPv6Addr) -> copy of ip address"
328
329 static PyNumberMethods silkPyIPAddr_number_methods;
330
331 static PyMethodDef silkPyIPAddr_methods[] = {
332 {"__reduce__", (PyCFunction)reduce_error, METH_NOARGS, ""},
333 {"isipv6", (PyCFunction)silkPyIPAddr_isipv6_deprecated, METH_NOARGS,
334 ("addr.isipv6() -> bool -- return whether addr is an IPv6 address."
335 " DEPRECATED Use addr.is_ipv6() instead.")},
336 {"is_ipv6", (PyCFunction)silkPyIPAddr_is_ipv6, METH_NOARGS,
337 "addr.is_ipv6() -> bool -- return whether addr is an IPv6 address"},
338 {"to_ipv6", (PyCFunction)
339 #if SK_ENABLE_IPV6
340 silkPyIPAddr_to_ipv6, METH_NOARGS,
341 #else
342 silkPyNotImplemented, METH_VARARGS | METH_KEYWORDS,
343 #endif
344 "addr.to_ipv6() -- return addr converted to an IPv6 address"},
345 {"to_ipv4", (PyCFunction)silkPyIPAddr_to_ipv4, METH_NOARGS,
346 "addr.to_ipv4() -- return addr converted to an IPv4 address"},
347 {"padded", (PyCFunction)silkPyIPAddr_padded, METH_NOARGS,
348 "addr.padded() -> str -- return zero-padded IP string"},
349 {"mask", (PyCFunction)silkPyIPAddr_mask, METH_O,
350 "addr.mask(addr2) -> addr3 -- return addr masked by addr2"},
351 {"mask_prefix", (PyCFunction)silkPyIPAddr_mask_prefix, METH_O,
352 ("addr.mask(prefix) -> addr2 -- "
353 "return addr masked by the top prefix bits")},
354 {"country_code", (PyCFunction)silkPyIPAddr_country_code, METH_NOARGS,
355 "addr.country_code() -> string -- 2-character country code"},
356 {"octets", (PyCFunction)silkPyIPAddr_octets, METH_NOARGS,
357 ("addr.octets() = (o1, o2 ...) -- "
358 "return the octets of addr as a tuple")},
359 {NULL, NULL, 0, NULL} /* Sentinel */
360 };
361
362 /* define the object types */
363 static PyTypeObject silkPyIPAddrType = {
364 PyVarObject_HEAD_INIT(NULL, 0)
365 "silk.IPAddr", /* tp_name */
366 sizeof(silkPyIPAddr), /* tp_basicsize */
367 0, /* tp_itemsize */
368 obj_dealloc, /* tp_dealloc */
369 0, /* tp_vectorcall_offset (Py 3.8) */
370 0, /* tp_getattr */
371 0, /* tp_setattr */
372 0, /* tp_as_async (tp_compare in Py2.x) */
373 (reprfunc)silkPyIPAddr_repr, /* tp_repr */
374 &silkPyIPAddr_number_methods, /* tp_as_number */
375 0, /* tp_as_sequence */
376 0, /* tp_as_mapping */
377 (hashfunc)silkPyIPAddr_hash, /* tp_hash */
378 0, /* tp_call */
379 (reprfunc)silkPyIPAddr_str, /* tp_str */
380 0, /* tp_getattro */
381 0, /* tp_setattro */
382 0, /* tp_as_buffer */
383 #if PY_MAJOR_VERSION < 3
384 Py_TPFLAGS_HAVE_RICHCOMPARE |
385 #endif
386 Py_TPFLAGS_DEFAULT, /* tp_flags */
387 silkPyIPAddr_doc, /* tp_doc */
388 0, /* tp_traverse */
389 0, /* tp_clear */
390 (richcmpfunc)silkPyIPAddr_richcompare, /* tp_richcompare */
391 0, /* tp_weaklistoffset */
392 0, /* tp_iter */
393 0, /* tp_iternext */
394 silkPyIPAddr_methods, /* tp_methods */
395 0, /* tp_members */
396 0, /* tp_getset */
397 0, /* tp_base */
398 0, /* tp_dict */
399 0, /* tp_descr_get */
400 0, /* tp_descr_set */
401 0, /* tp_dictoffset */
402 0, /* tp_init */
403 0, /* tp_alloc */
404 silkPyIPAddr_new, /* tp_new */
405 0, /* tp_free */
406 0, /* tp_is_gc */
407 0, /* tp_bases */
408 0, /* tp_mro */
409 0, /* tp_cache */
410 0, /* tp_subclasses */
411 0, /* tp_weaklist */
412 0 /* tp_del */
413 #if PY_VERSION_HEX >= 0x02060000
414 ,0 /* tp_version_tag */
415 #endif
416 #if PY_VERSION_HEX >= 0x03040000
417 ,0 /* tp_finalize */
418 #endif
419 #if PY_VERSION_HEX >= 0x03080000
420 ,0 /* tp_vectorcall */
421 ,0 /* tp_print */
422 #endif
423 };
424
425 static PyTypeObject silkPyIPv4AddrType = {
426 PyVarObject_HEAD_INIT(NULL, 0)
427 "silk.IPv4Addr", /* tp_name */
428 0, /* tp_basicsize */
429 0, /* tp_itemsize */
430 0, /* tp_dealloc */
431 0, /* tp_vectorcall_offset (Py 3.8) */
432 0, /* tp_getattr */
433 0, /* tp_setattr */
434 0, /* tp_as_async (tp_compare in Py2.x) */
435 0, /* tp_repr */
436 0, /* tp_as_number */
437 0, /* tp_as_sequence */
438 0, /* tp_as_mapping */
439 0, /* tp_hash */
440 0, /* tp_call */
441 0, /* tp_str */
442 0, /* tp_getattro */
443 0, /* tp_setattro */
444 0, /* tp_as_buffer */
445 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
446 silkPyIPv4Addr_doc, /* tp_doc */
447 0, /* tp_traverse */
448 0, /* tp_clear */
449 0, /* tp_richcompare */
450 0, /* tp_weaklistoffset */
451 0, /* tp_iter */
452 0, /* tp_iternext */
453 0, /* tp_methods */
454 0, /* tp_members */
455 0, /* tp_getset */
456 &silkPyIPAddrType, /* tp_base */
457 0, /* tp_dict */
458 0, /* tp_descr_get */
459 0, /* tp_descr_set */
460 0, /* tp_dictoffset */
461 (initproc)silkPyIPv4Addr_init, /* tp_init */
462 0, /* tp_alloc */
463 silkPyIPv4Addr_new, /* tp_new */
464 0, /* tp_free */
465 0, /* tp_is_gc */
466 0, /* tp_bases */
467 0, /* tp_mro */
468 0, /* tp_cache */
469 0, /* tp_subclasses */
470 0, /* tp_weaklist */
471 0 /* tp_del */
472 #if PY_VERSION_HEX >= 0x02060000
473 ,0 /* tp_version_tag */
474 #endif
475 #if PY_VERSION_HEX >= 0x03040000
476 ,0 /* tp_finalize */
477 #endif
478 #if PY_VERSION_HEX >= 0x03080000
479 ,0 /* tp_vectorcall */
480 ,0 /* tp_print */
481 #endif
482 };
483
484 static PyTypeObject silkPyIPv6AddrType = {
485 PyVarObject_HEAD_INIT(NULL, 0)
486 "silk.IPv6Addr", /* tp_name */
487 0, /* tp_basicsize */
488 0, /* tp_itemsize */
489 0, /* tp_dealloc */
490 0, /* tp_vectorcall_offset (Py 3.8) */
491 0, /* tp_getattr */
492 0, /* tp_setattr */
493 0, /* tp_as_async (tp_compare in Py2.x) */
494 0, /* tp_repr */
495 0, /* tp_as_number */
496 0, /* tp_as_sequence */
497 0, /* tp_as_mapping */
498 0, /* tp_hash */
499 0, /* tp_call */
500 0, /* tp_str */
501 0, /* tp_getattro */
502 0, /* tp_setattro */
503 0, /* tp_as_buffer */
504 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
505 silkPyIPv6Addr_doc, /* tp_doc */
506 0, /* tp_traverse */
507 0, /* tp_clear */
508 0, /* tp_richcompare */
509 0, /* tp_weaklistoffset */
510 0, /* tp_iter */
511 0, /* tp_iternext */
512 0, /* tp_methods */
513 0, /* tp_members */
514 0, /* tp_getset */
515 &silkPyIPAddrType, /* tp_base */
516 0, /* tp_dict */
517 0, /* tp_descr_get */
518 0, /* tp_descr_set */
519 0, /* tp_dictoffset */
520 (initproc)silkPyIPv6Addr_init, /* tp_init */
521 0, /* tp_alloc */
522 #if SK_ENABLE_IPV6
523 silkPyIPv6Addr_new, /* tp_new */
524 #else
525 (newfunc)silkPyNotImplemented, /* tp_new */
526 #endif
527 0, /* tp_free */
528 0, /* tp_is_gc */
529 0, /* tp_bases */
530 0, /* tp_mro */
531 0, /* tp_cache */
532 0, /* tp_subclasses */
533 0, /* tp_weaklist */
534 0 /* tp_del */
535 #if PY_VERSION_HEX >= 0x02060000
536 ,0 /* tp_version_tag */
537 #endif
538 #if PY_VERSION_HEX >= 0x03040000
539 ,0 /* tp_finalize */
540 #endif
541 #if PY_VERSION_HEX >= 0x03080000
542 ,0 /* tp_vectorcall */
543 ,0 /* tp_print */
544 #endif
545 };
546
547 /* macro and function defintions */
548 #define silkPyIPAddr_Check(op) \
549 PyObject_TypeCheck(op, &silkPyIPAddrType)
550 #define silkPyIPv4Addr_Check(op) \
551 PyObject_TypeCheck(op, &silkPyIPv4AddrType)
552 #define silkPyIPv6Addr_Check(op) \
553 PyObject_TypeCheck(op, &silkPyIPv6AddrType)
554
555 static PyObject *
silkPyIPAddr_country_code(silkPyIPAddr * self)556 silkPyIPAddr_country_code(
557 silkPyIPAddr *self)
558 {
559 char name[3];
560 sk_countrycode_t code;
561 int rv;
562
563 rv = skCountrySetup(NULL, error_printf);
564 if (rv != 0) {
565 PyErr_SetString(PyExc_RuntimeError, error_buffer);
566 return NULL;
567 }
568
569 code = skCountryLookupCode(&self->addr);
570 if (code == SK_COUNTRYCODE_INVALID) {
571 Py_RETURN_NONE;
572 }
573
574 return PyUnicode_FromString(skCountryCodeToName(code, name, sizeof(name)));
575 }
576
577 static long
silkPyIPAddr_hash(silkPyIPAddr * obj)578 silkPyIPAddr_hash(
579 silkPyIPAddr *obj)
580 {
581 long retval;
582 #if SK_ENABLE_IPV6
583 if (skipaddrIsV6(&obj->addr)) {
584 uint8_t v6[16];
585 skipaddrGetAsV6(&obj->addr, v6);
586 #if SK_SIZEOF_LONG == 8
587 retval = *(long*)(&v6[8]);
588 #else /* SK_SIZEOF_LONG */
589 /* Assume long is 4 bytes */
590 retval = *(long*)(&v6[12]);
591 #endif /* SK_SIZEOF_LONG */
592 return retval;
593 }
594 #endif /* SK_ENABLE_IPV6 */
595 retval = skipaddrGetV4(&obj->addr);
596 if (retval == -1) {
597 retval = 0;
598 }
599 return retval;
600 }
601
602 static PyObject *
silkPyIPAddr_int(silkPyIPAddr * obj)603 silkPyIPAddr_int(
604 silkPyIPAddr *obj)
605 {
606 PyObject *result;
607
608 #if SK_ENABLE_IPV6
609 if (skipaddrIsV6(&obj->addr)) {
610 char buf[33];
611 char *p;
612 int i;
613 uint32_t *v6;
614
615 p = buf;
616 v6 = (uint32_t*)obj->addr.ip_ip.ipu_ipv6;
617 for (i = 0; i < 4; i++) {
618 sprintf(p, "%08" PRIx32, ntohl(*v6));
619 p += 8;
620 ++v6;
621 }
622 result = PyLong_FromString(buf, NULL, 16);
623 } else
624 #endif /* SK_ENABLE_IPV6 */
625 {
626 result = PyLong_FromUnsignedLong(skipaddrGetV4(&obj->addr));
627 }
628
629 return result;
630 }
631
632 static PyObject *
silkPyIPAddr_is_ipv6(silkPyIPAddr UNUSED_NOv6 (* self))633 silkPyIPAddr_is_ipv6(
634 silkPyIPAddr UNUSED_NOv6(*self))
635 {
636 #if SK_ENABLE_IPV6
637 return PyBool_FromLong(skipaddrIsV6(&self->addr));
638 #else
639 Py_RETURN_FALSE;
640 #endif
641 }
642
643 static PyObject *
silkPyIPAddr_isipv6_deprecated(silkPyIPAddr * self)644 silkPyIPAddr_isipv6_deprecated(
645 silkPyIPAddr *self)
646 {
647 /* deprecated in SiLK-2.2.0 */
648 PyErr_Warn(PyExc_DeprecationWarning,
649 ("IPAddr.isipv6() is deprecated. "
650 "Use IPAddr.is_ipv6() instead."));
651 return silkPyIPAddr_is_ipv6(self);
652 }
653
654 static PyObject *
silkPyIPAddr_mask(silkPyIPAddr * self,PyObject * mask)655 silkPyIPAddr_mask(
656 silkPyIPAddr *self,
657 PyObject *mask)
658 {
659 silkPyIPAddr *retval;
660 skipaddr_t addr;
661 PyTypeObject *type;
662
663 if (!silkPyIPAddr_Check(mask)) {
664 PyErr_SetString(PyExc_TypeError, "Argument must be an IPAddr");
665 return NULL;
666 }
667
668 skipaddrCopy(&addr, &self->addr);
669 skipaddrMask(&addr, &((silkPyIPAddr*)mask)->addr);
670 #if SK_ENABLE_IPV6
671 if (skipaddrIsV6(&addr)) {
672 type = &silkPyIPv6AddrType;
673 } else
674 #endif
675 {
676 type = &silkPyIPv4AddrType;
677 }
678 retval = PyObject_New(silkPyIPAddr, type);
679 if (retval == NULL) {
680 return NULL;
681 }
682 skipaddrCopy(&retval->addr, &addr);
683
684 return (PyObject*)retval;
685 }
686
687 static PyObject *
silkPyIPAddr_mask_prefix(silkPyIPAddr * self,PyObject * prefix)688 silkPyIPAddr_mask_prefix(
689 silkPyIPAddr *self,
690 PyObject *prefix)
691 {
692 silkPyIPAddr *retval;
693 PyTypeObject *type;
694 long p;
695 int max;
696
697 if (!IS_INT(prefix)) {
698 PyErr_SetString(PyExc_TypeError, "Prefix must be an integer");
699 return NULL;
700 }
701
702 #if SK_ENABLE_IPV6
703 if (skipaddrIsV6(&self->addr)) {
704 type = &silkPyIPv6AddrType;
705 max = 128;
706 } else
707 #endif
708 {
709 type = &silkPyIPv4AddrType;
710 max = 32;
711 }
712
713 p = PyInt_AsLong(prefix);
714 if (PyErr_Occurred()) {
715 return NULL;
716 }
717
718 if (p < 0 || p > max) {
719 return PyErr_Format(PyExc_ValueError,
720 "Prefix must be between 0 and %d", max);
721 }
722
723 retval = PyObject_New(silkPyIPAddr, type);
724 if (retval == NULL) {
725 return NULL;
726 }
727
728 skipaddrCopy(&retval->addr, &self->addr);
729 skipaddrApplyCIDR(&retval->addr, p);
730
731 return (PyObject*)retval;
732 }
733
734 static PyObject *
silkPyIPAddr_new(PyTypeObject * type,PyObject * args,PyObject * kwds)735 silkPyIPAddr_new(
736 PyTypeObject *type,
737 PyObject *args,
738 PyObject *kwds)
739 {
740 static char *kwlist[] = {"address", NULL};
741 silkPyIPAddr *self;
742 PyObject *o;
743
744 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O", kwlist, &o)) {
745 return NULL;
746 }
747
748 if (Py_TYPE(o) == &silkPyIPv4AddrType ||
749 Py_TYPE(o) == &silkPyIPv6AddrType)
750 {
751 /* IPv{4,6}Addr objects are immutable, so just incref*/
752 Py_INCREF(o);
753 return o;
754 }
755 if (silkPyIPAddr_Check(o)) {
756 /* Unknown subclass of IPAddr, do a real copy */
757 if (type == &silkPyIPAddrType) {
758 #if SK_ENABLE_IPV6
759 if (skipaddrIsV6(&((silkPyIPAddr*)o)->addr)) {
760 type = &silkPyIPv6AddrType;
761 } else
762 #endif
763 {
764 type = &silkPyIPv4AddrType;
765 }
766 }
767 } else if (IS_STRING(o)) {
768 PyObject *bytes = bytes_from_string(o);
769 const char *straddr;
770 const char *c;
771
772 if (bytes == NULL) {
773 return NULL;
774 }
775
776 straddr = PyBytes_AS_STRING(bytes);
777 c = strchr(straddr, ':');
778 if (c) {
779 type = &silkPyIPv6AddrType;
780 } else {
781 type = &silkPyIPv4AddrType;
782 }
783 Py_DECREF(bytes);
784 } else if (IS_INT(o)) {
785 /* The IPAddr(int) constructor is deprecated as of SiLK 2.2.0 */
786 int rv = PyErr_Warn(PyExc_DeprecationWarning,
787 ("IPAddr(int) is deprecated. Use IPv4Addr(int) "
788 "or IPv6Addr(int) instead."));
789 if (rv) {
790 return NULL;
791 }
792 type = &silkPyIPv4AddrType;
793
794 } else {
795 return PyErr_Format(PyExc_TypeError, "Must be a string or IPAddr");
796 }
797
798 /* Allocate the object */
799 self = (silkPyIPAddr*)type->tp_alloc(type, 0);
800 if (self == NULL) {
801 return NULL;
802 }
803
804 return (PyObject*)self;
805 }
806
807 static PyObject *
silkPyIPAddr_octets(silkPyIPAddr * self)808 silkPyIPAddr_octets(
809 silkPyIPAddr *self)
810 {
811 PyObject *retval;
812 PyObject *octet;
813 int i;
814
815 #if SK_ENABLE_IPV6
816 if (skipaddrIsV6(&self->addr)) {
817 uint8_t v6[16];
818 retval = PyTuple_New(16);
819 if (retval == NULL) {
820 return NULL;
821 }
822 skipaddrGetV6(&self->addr, v6);
823
824 for (i = 0; i < 16; i++) {
825 octet = PyInt_FromLong(v6[i]);
826 if (octet == NULL) {
827 Py_DECREF(retval);
828 return NULL;
829 }
830 PyTuple_SET_ITEM(retval, i, octet);
831 }
832 } else
833 #endif
834 {
835 uint32_t v4 = skipaddrGetV4(&self->addr);
836 retval = PyTuple_New(4);
837 if (retval == NULL) {
838 return NULL;
839 }
840
841 for (i = 3; i >= 0; i--) {
842 octet = PyInt_FromLong(v4 & 0xff);
843 if (octet == NULL) {
844 Py_DECREF(retval);
845 return NULL;
846 }
847 PyTuple_SET_ITEM(retval, i, octet);
848 v4 >>= 8;
849 }
850 }
851
852 return retval;
853 }
854
855 static PyObject *
silkPyIPAddr_padded(silkPyIPAddr * obj)856 silkPyIPAddr_padded(
857 silkPyIPAddr *obj)
858 {
859 char buf[SKIPADDR_STRLEN];
860
861 skipaddrString(buf, &obj->addr, SKIPADDR_ZEROPAD);
862 return PyUnicode_FromString(buf);
863 }
864
865 static PyObject *
silkPyIPAddr_repr(silkPyIPAddr * obj)866 silkPyIPAddr_repr(
867 silkPyIPAddr *obj)
868 {
869 char buf[SKIPADDR_STRLEN];
870 PyTypeObject *type;
871
872 type = Py_TYPE(obj);
873 if (type == NULL) {
874 return NULL;
875 }
876
877 skipaddrString(buf, &obj->addr, SKIPADDR_CANONICAL);
878 return PyUnicode_FromFormat("%s('%s')", type->tp_name, buf);
879 }
880
881 static PyObject *
silkPyIPAddr_richcompare(silkPyIPAddr * self,PyObject * obj,int cmp)882 silkPyIPAddr_richcompare(
883 silkPyIPAddr *self,
884 PyObject *obj,
885 int cmp)
886 {
887 int rv;
888 silkPyIPAddr *other;
889
890 if (!silkPyIPAddr_Check(obj)) {
891 PyErr_SetString(PyExc_TypeError, "Expected silk.IPAddr");
892 return NULL;
893 }
894 other = (silkPyIPAddr*)obj;
895 rv = skipaddrCompare(&self->addr, &other->addr);
896 if (rv < 0) {
897 return PyBool_FromLong(cmp == Py_LT || cmp == Py_LE || cmp == Py_NE);
898 }
899 if (rv > 0) {
900 return PyBool_FromLong(cmp == Py_GT || cmp == Py_GE || cmp == Py_NE);
901 }
902 return PyBool_FromLong(cmp == Py_EQ || cmp == Py_LE || cmp == Py_GE);
903 }
904
905 static int
silkPyIPAddr_setup(PyObject * mod)906 silkPyIPAddr_setup(
907 PyObject *mod)
908 {
909 /* Setup number methods */
910 memset(&silkPyIPAddr_number_methods, 0,
911 sizeof(silkPyIPAddr_number_methods));
912 silkPyIPAddr_number_methods.nb_int = (unaryfunc)silkPyIPAddr_int;
913 #if PY_MAJOR_VERSION < 3
914 silkPyIPAddr_number_methods.nb_long = (unaryfunc)silkPyIPAddr_int;
915 #endif
916
917 /* Initialize type and add to module */
918 if (PyType_Ready(&silkPyIPAddrType) < 0) {
919 return -1;
920 }
921 return PyModule_AddObject(mod, "IPAddr", (PyObject*)&silkPyIPAddrType);
922 }
923
924 static PyObject *
silkPyIPAddr_str(silkPyIPAddr * obj)925 silkPyIPAddr_str(
926 silkPyIPAddr *obj)
927 {
928 char buf[SKIPADDR_STRLEN];
929
930 skipaddrString(buf, &obj->addr, SKIPADDR_CANONICAL);
931 return PyUnicode_FromString(buf);
932 }
933
934 static PyObject *
silkPyIPAddr_to_ipv4(PyObject * self)935 silkPyIPAddr_to_ipv4(
936 PyObject *self)
937 {
938 #if SK_ENABLE_IPV6
939 PyObject *obj;
940
941 obj = PyObject_CallFunctionObjArgs((PyObject*)&silkPyIPv4AddrType,
942 self, NULL);
943 if (obj == NULL) {
944 if (PyErr_ExceptionMatches(PyExc_ValueError)) {
945 PyErr_Clear();
946 Py_RETURN_NONE;
947 }
948 }
949
950 return obj;
951 #else /* SK_ENABLE_IPV6 */
952 Py_INCREF(self);
953 return self;
954 #endif /* SK_ENABLE_IPV6 */
955 }
956
957 #if SK_ENABLE_IPV6
958 static PyObject *
silkPyIPAddr_to_ipv6(PyObject * self)959 silkPyIPAddr_to_ipv6(
960 PyObject *self)
961 {
962 return PyObject_CallFunctionObjArgs((PyObject*)&silkPyIPv6AddrType,
963 self, NULL);
964 }
965 #endif /* SK_ENABLE_IPV6 */
966
967 static int
silkPyIPv4Addr_init(silkPyIPAddr * self,PyObject * args,PyObject * kwds)968 silkPyIPv4Addr_init(
969 silkPyIPAddr *self,
970 PyObject *args,
971 PyObject *kwds)
972 {
973 static char *kwlist[] = {"address", NULL};
974 PyObject *addr;
975 int rv;
976
977 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O", kwlist, &addr)) {
978 return -1;
979 }
980
981 if (addr == (PyObject*)self) {
982 /* We were initialized by new */
983 return 0;
984 }
985
986 if (IS_STRING(addr)) {
987 PyObject *bytes;
988 bytes = bytes_from_string(addr);
989 if (bytes == NULL) {
990 return -1;
991 }
992 rv = skStringParseIP(&self->addr, PyBytes_AS_STRING(bytes));
993 Py_DECREF(bytes);
994 if (rv != 0) {
995 PyErr_SetString(PyExc_ValueError,
996 "String is not a valid IP address");
997 return -1;
998 }
999 #if SK_ENABLE_IPV6
1000 if (skipaddrIsV6(&self->addr)) {
1001 PyErr_SetString(PyExc_ValueError,
1002 "String is not a valid IPv4 address");
1003 return -1;
1004 }
1005 #endif
1006 } else if (IS_INT(addr)) {
1007 uint32_t value;
1008 PyObject *num;
1009
1010 num = PyLong_FromLong(0);
1011 rv = PyObject_RichCompareBool(addr, num, Py_LT);
1012 Py_DECREF(num);
1013 if (rv) {
1014 /* Negative */
1015 PyErr_SetString(PyExc_ValueError,
1016 "Illegal IPv4 address (negative)");
1017 return -1;
1018 }
1019 rv = PyObject_RichCompareBool(addr, GLOBALS->maxintipv4, Py_GT);
1020 if (rv) {
1021 PyErr_SetString(PyExc_ValueError,
1022 "Illegal IPv4 address (integer too large)");
1023 return -1;
1024 }
1025
1026 value = PyLong_AsUnsignedLong(addr);
1027 skipaddrSetV4(&self->addr, &value);
1028
1029 #if SK_ENABLE_IPV6
1030 } else if (silkPyIPv6Addr_Check(addr)) {
1031 /* Convert to v4 */
1032 silkPyIPAddr *v6addr = (silkPyIPAddr*)addr;
1033
1034 if (skipaddrV6toV4(&v6addr->addr, &self->addr)) {
1035 PyErr_SetString(PyExc_ValueError,
1036 "IP address not convertable to IPv4.");
1037 return -1;
1038 }
1039 #endif /* SK_ENABLE_IPV6 */
1040
1041 } else if (silkPyIPv4Addr_Check(addr)) {
1042 /* Copy */
1043 skipaddrCopy(&self->addr, &((silkPyIPAddr*)addr)->addr);
1044 } else {
1045 PyErr_SetString(PyExc_TypeError, "Must be a string or integer");
1046 return -1;
1047 }
1048
1049 return 0;
1050 }
1051
1052 static PyObject *
silkPyIPv4Addr_new(PyTypeObject * type,PyObject * args,PyObject * kwds)1053 silkPyIPv4Addr_new(
1054 PyTypeObject *type,
1055 PyObject *args,
1056 PyObject *kwds)
1057 {
1058 return silkPyIPvXAddr_new(&silkPyIPv4AddrType, type, args, kwds);
1059 }
1060
1061 static int
silkPyIPv6Addr_init(silkPyIPAddr * self,PyObject * args,PyObject * kwds)1062 silkPyIPv6Addr_init(
1063 silkPyIPAddr *self,
1064 PyObject *args,
1065 PyObject *kwds)
1066 {
1067 #if !SK_ENABLE_IPV6
1068 silkPyNotImplemented((PyObject*)self, args, kwds);
1069 return -1;
1070 #else /* if SK_ENABLE_IPV6 */
1071 static char *kwlist[] = {"address", NULL};
1072 PyObject *addr;
1073 int rv;
1074
1075 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O", kwlist, &addr)) {
1076 return -1;
1077 }
1078
1079 if (addr == (PyObject*)self) {
1080 /* We were initialized by new */
1081 return 0;
1082 }
1083
1084 if (IS_STRING(addr)) {
1085 PyObject *bytes = bytes_from_string(addr);
1086 if (bytes == NULL) {
1087 return -1;
1088 }
1089 rv = skStringParseIP(&self->addr, PyBytes_AS_STRING(bytes));
1090 Py_DECREF(bytes);
1091 if (rv != 0) {
1092 PyErr_SetString(PyExc_ValueError,
1093 "String is not a valid IP address");
1094 return -1;
1095 }
1096 if (!skipaddrIsV6(&self->addr)) {
1097 PyErr_SetString(PyExc_ValueError,
1098 "String is not a valid IPv6 address");
1099 return -1;
1100 }
1101 } else if (IS_INT(addr)) {
1102 uint8_t v6[16];
1103 uint32_t *v6_32;
1104 PyObject *next;
1105 PyObject *shift;
1106 PyObject *num;
1107 int i;
1108
1109 num = PyLong_FromLong(0);
1110 rv = PyObject_RichCompareBool(addr, num, Py_LT);
1111 Py_DECREF(num);
1112 if (rv) {
1113 /* Negative */
1114 PyErr_SetString(PyExc_ValueError,
1115 "Illegal IPv6 address (negative)");
1116 return -1;
1117 }
1118 rv = PyObject_RichCompareBool(addr, GLOBALS->maxintipv6, Py_GT);
1119 if (rv) {
1120 PyErr_SetString(PyExc_ValueError,
1121 "Illegal IPv6 address (integer too large)");
1122 return -1;
1123 }
1124
1125 /* Set IP */
1126 shift = PyLong_FromLong(32);
1127 v6_32 = (uint32_t*)v6 + 3;
1128
1129 next = addr;
1130 Py_INCREF(next);
1131 for (i = 0; i < 4; i++, v6_32--) {
1132 PyObject *tmp;
1133
1134 tmp = PyNumber_And(next, GLOBALS->maxintipv4);
1135 *v6_32 = htonl(PyLong_AsUnsignedLong(tmp));
1136 Py_DECREF(tmp);
1137 tmp = next;
1138 next = PyNumber_Rshift(tmp, shift);
1139 Py_DECREF(tmp);
1140 }
1141 Py_DECREF(next);
1142 Py_DECREF(shift);
1143 skipaddrSetV6(&self->addr, v6);
1144
1145 } else if (silkPyIPv4Addr_Check(addr)) {
1146 /* Convert to v6 */
1147 silkPyIPAddr *v4addr = (silkPyIPAddr*)addr;
1148
1149 if (skipaddrIsV6(&v4addr->addr)) {
1150 skipaddrCopy(&self->addr, &v4addr->addr);
1151 } else {
1152 skipaddrV4toV6(&v4addr->addr, &self->addr);
1153 }
1154
1155 } else if (silkPyIPv6Addr_Check(addr)) {
1156 /* Copy */
1157 skipaddrCopy(&self->addr, &((silkPyIPAddr*)addr)->addr);
1158 } else {
1159 PyErr_SetString(PyExc_TypeError, "Must be a string or integer");
1160 return -1;
1161 }
1162
1163 return 0;
1164 #endif /* else of !SK_ENABLE_IPV6 */
1165 }
1166
1167 #if SK_ENABLE_IPV6
1168 static PyObject *
silkPyIPv6Addr_new(PyTypeObject * type,PyObject * args,PyObject * kwds)1169 silkPyIPv6Addr_new(
1170 PyTypeObject *type,
1171 PyObject *args,
1172 PyObject *kwds)
1173 {
1174 return silkPyIPvXAddr_new(&silkPyIPv6AddrType, type, args, kwds);
1175 }
1176 #endif /* SK_ENABLE_IPV6 */
1177
1178 static PyObject *
silkPyIPvXAddr_new(PyTypeObject * basetype,PyTypeObject * type,PyObject * args,PyObject * kwds)1179 silkPyIPvXAddr_new(
1180 PyTypeObject *basetype,
1181 PyTypeObject *type,
1182 PyObject *args,
1183 PyObject *kwds)
1184 {
1185 static char *kwlist[] = {"address", NULL};
1186 PyObject *self;
1187 PyObject *o;
1188
1189 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O", kwlist, &o)) {
1190 return NULL;
1191 }
1192
1193 if (type == basetype && Py_TYPE(o) == basetype) {
1194 Py_INCREF(o);
1195 return o;
1196 }
1197
1198 self = type->tp_alloc(type, 0);
1199 return self;
1200 }
1201
1202
1203 /*
1204 *************************************************************************
1205 * IPWildcard
1206 *************************************************************************
1207 */
1208
1209 typedef struct silkPyIPWildcard_st {
1210 PyObject_HEAD
1211 skIPWildcard_t wildcard;
1212 PyObject *name;
1213 } silkPyIPWildcard;
1214
1215 typedef struct silkPyIPWildcardIter_st {
1216 PyObject_HEAD
1217 silkPyIPWildcard *wildcard;
1218 skIPWildcardIterator_t iter;
1219 } silkPyIPWildcardIter;
1220
1221 /* function prototypes */
1222 static void
1223 silkPyIPWildcardIter_dealloc(
1224 silkPyIPWildcardIter *self);
1225 static PyObject *
1226 silkPyIPWildcardIter_iternext(
1227 silkPyIPWildcardIter *self);
1228 static int
1229 silkPyIPWildcard_contains(
1230 silkPyIPWildcard *self,
1231 PyObject *obj);
1232 static void
1233 silkPyIPWildcard_dealloc(
1234 silkPyIPWildcard *obj);
1235 static PyObject *
1236 silkPyIPWildcard_is_ipv6(
1237 silkPyIPWildcard UNUSED_NOv6(*self));
1238 static PyObject *
1239 silkPyIPWildcard_isipv6_deprecated(
1240 silkPyIPWildcard *self);
1241 static PyObject *
1242 silkPyIPWildcard_iter(
1243 silkPyIPWildcard *self);
1244 static PyObject *
1245 silkPyIPWildcard_new(
1246 PyTypeObject *type,
1247 PyObject *args,
1248 PyObject *kwds);
1249 static PyObject *
1250 silkPyIPWildcard_repr(
1251 silkPyIPWildcard *obj);
1252 static PyObject *
1253 silkPyIPWildcard_str(
1254 silkPyIPWildcard *obj);
1255
1256 /* define docs and methods */
1257 #define silkPyIPWildcard_doc \
1258 "IPWildcard(string) -> IP Wildcard address"
1259
1260 static PyMethodDef silkPyIPWildcard_methods[] = {
1261 {"__reduce__", (PyCFunction)reduce_error, METH_NOARGS, ""},
1262 {"isipv6", (PyCFunction)silkPyIPWildcard_isipv6_deprecated, METH_NOARGS,
1263 ("wild.isipv6() -> bool -- return whether wild is an IPv6 wildcard."
1264 " DEPRECATED Use wild.is_ipv6() instead.")},
1265 {"is_ipv6", (PyCFunction)silkPyIPWildcard_is_ipv6, METH_NOARGS,
1266 "wild.is_ipv6() -> bool -- return whether wild is an IPv6 wildcard"},
1267 {NULL, NULL, 0, NULL} /* Sentinel */
1268 };
1269
1270 static PySequenceMethods silkPyIPWildcard_sequence_methods = {
1271 0, /* sq_length */
1272 0, /* sq_concat */
1273 0, /* sq_repeat */
1274 0, /* sq_item */
1275 0, /* sq_slice */
1276 0, /* sq_ass_item */
1277 0, /* sq_ass_slice */
1278 (objobjproc)silkPyIPWildcard_contains, /* sq_contains */
1279 0, /* sq_inplace_concat */
1280 0 /* sq_inplace_repeat */
1281 };
1282
1283 /* define the object types */
1284 static PyTypeObject silkPyIPWildcardType = {
1285 PyVarObject_HEAD_INIT(NULL, 0)
1286 "silk.IPWildcard", /* tp_name */
1287 sizeof(silkPyIPWildcard), /* tp_basicsize */
1288 0, /* tp_itemsize */
1289 (destructor)silkPyIPWildcard_dealloc, /* tp_dealloc */
1290 0, /* tp_vectorcall_offset (Py 3.8) */
1291 0, /* tp_getattr */
1292 0, /* tp_setattr */
1293 0, /* tp_as_async (tp_compare in Py2.x) */
1294 (reprfunc)silkPyIPWildcard_repr, /* tp_repr */
1295 0, /* tp_as_number */
1296 &silkPyIPWildcard_sequence_methods, /* tp_as_sequence */
1297 0, /* tp_as_mapping */
1298 0, /* tp_hash */
1299 0, /* tp_call */
1300 (reprfunc)silkPyIPWildcard_str, /* tp_str */
1301 0, /* tp_getattro */
1302 0, /* tp_setattro */
1303 0, /* tp_as_buffer */
1304 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
1305 /* tp_flags */
1306 silkPyIPWildcard_doc, /* tp_doc */
1307 0, /* tp_traverse */
1308 0, /* tp_clear */
1309 0, /* tp_richcompare */
1310 0, /* tp_weaklistoffset */
1311 (getiterfunc)silkPyIPWildcard_iter, /* tp_iter */
1312 0, /* tp_iternext */
1313 silkPyIPWildcard_methods, /* tp_methods */
1314 0, /* tp_members */
1315 0, /* tp_getset */
1316 0, /* tp_base */
1317 0, /* tp_dict */
1318 0, /* tp_descr_get */
1319 0, /* tp_descr_set */
1320 0, /* tp_dictoffset */
1321 0, /* tp_init */
1322 0, /* tp_alloc */
1323 silkPyIPWildcard_new, /* tp_new */
1324 0, /* tp_free */
1325 0, /* tp_is_gc */
1326 0, /* tp_bases */
1327 0, /* tp_mro */
1328 0, /* tp_cache */
1329 0, /* tp_subclasses */
1330 0, /* tp_weaklist */
1331 0 /* tp_del */
1332 #if PY_VERSION_HEX >= 0x02060000
1333 ,0 /* tp_version_tag */
1334 #endif
1335 #if PY_VERSION_HEX >= 0x03040000
1336 ,0 /* tp_finalize */
1337 #endif
1338 #if PY_VERSION_HEX >= 0x03080000
1339 ,0 /* tp_vectorcall */
1340 ,0 /* tp_print */
1341 #endif
1342 };
1343
1344 static PyTypeObject silkPyIPWildcardIterType = {
1345 PyVarObject_HEAD_INIT(NULL, 0)
1346 "silk.pysilk.IPWildcardIter", /* tp_name */
1347 sizeof(silkPyIPWildcardIter), /* tp_basicsize */
1348 0, /* tp_itemsize */
1349 (destructor)silkPyIPWildcardIter_dealloc, /* tp_dealloc */
1350 0, /* tp_vectorcall_offset (Py 3.8) */
1351 0, /* tp_getattr */
1352 0, /* tp_setattr */
1353 0, /* tp_as_async (tp_compare in Py2.x) */
1354 0, /* tp_repr */
1355 0, /* tp_as_number */
1356 0, /* tp_as_sequence */
1357 0, /* tp_as_mapping */
1358 0, /* tp_hash */
1359 0, /* tp_call */
1360 0, /* tp_str */
1361 0, /* tp_getattro */
1362 0, /* tp_setattro */
1363 0, /* tp_as_buffer */
1364 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
1365 "IP Wildcard iterator object", /* tp_doc */
1366 0, /* tp_traverse */
1367 0, /* tp_clear */
1368 0, /* tp_richcompare */
1369 0, /* tp_weaklistoffset */
1370 iter_iter, /* tp_iter */
1371 (iternextfunc)silkPyIPWildcardIter_iternext, /* tp_iternext */
1372 0, /* tp_methods */
1373 0, /* tp_members */
1374 0, /* tp_getset */
1375 0, /* tp_base */
1376 0, /* tp_dict */
1377 0, /* tp_descr_get */
1378 0, /* tp_descr_set */
1379 0, /* tp_dictoffset */
1380 0, /* tp_init */
1381 0, /* tp_alloc */
1382 0, /* tp_new */
1383 0, /* tp_free */
1384 0, /* tp_is_gc */
1385 0, /* tp_bases */
1386 0, /* tp_mro */
1387 0, /* tp_cache */
1388 0, /* tp_subclasses */
1389 0, /* tp_weaklist */
1390 0 /* tp_del */
1391 #if PY_VERSION_HEX >= 0x02060000
1392 ,0 /* tp_version_tag */
1393 #endif
1394 #if PY_VERSION_HEX >= 0x03040000
1395 ,0 /* tp_finalize */
1396 #endif
1397 #if PY_VERSION_HEX >= 0x03080000
1398 ,0 /* tp_vectorcall */
1399 ,0 /* tp_print */
1400 #endif
1401 };
1402
1403 /* macro and function defintions */
1404 #define silkPyIPWildcard_Check(op) \
1405 PyObject_TypeCheck(op, &silkPyIPWildcardType)
1406 #define silkPyIPWildcardIter_Check(op) \
1407 PyObject_TypeCheck(op, &silkPyIPWildcardIterType)
1408
1409 static void
silkPyIPWildcardIter_dealloc(silkPyIPWildcardIter * self)1410 silkPyIPWildcardIter_dealloc(
1411 silkPyIPWildcardIter *self)
1412 {
1413 Py_XDECREF(self->wildcard);
1414 Py_TYPE(self)->tp_free((PyObject*)self);
1415 }
1416
1417 static PyObject *
silkPyIPWildcardIter_iternext(silkPyIPWildcardIter * self)1418 silkPyIPWildcardIter_iternext(
1419 silkPyIPWildcardIter *self)
1420 {
1421 silkPyIPAddr *addr;
1422 skIteratorStatus_t rv;
1423 skipaddr_t raw_addr;
1424
1425 rv = skIPWildcardIteratorNext(&self->iter, &raw_addr);
1426 if (rv == SK_ITERATOR_NO_MORE_ENTRIES) {
1427 PyErr_SetNone(PyExc_StopIteration);
1428 return NULL;
1429 }
1430 addr = (silkPyIPAddr*)silkPyIPv4AddrType.tp_alloc(&silkPyIPv4AddrType, 0);
1431 if (addr == NULL) {
1432 return NULL;
1433 }
1434 addr->addr = raw_addr;
1435
1436 return (PyObject*)addr;
1437 }
1438
1439 static int
silkPyIPWildcard_contains(silkPyIPWildcard * self,PyObject * obj)1440 silkPyIPWildcard_contains(
1441 silkPyIPWildcard *self,
1442 PyObject *obj)
1443 {
1444 int retval;
1445 silkPyIPAddr *silkaddr;
1446
1447 if (IS_STRING(obj)) {
1448 obj = PyObject_CallFunctionObjArgs((PyObject*)&silkPyIPAddrType,
1449 obj, NULL);
1450 if (obj == NULL) {
1451 return -1;
1452 }
1453 } else if (silkPyIPAddr_Check(obj)) {
1454 Py_INCREF(obj);
1455 } else {
1456 PyErr_SetString(PyExc_TypeError, "Must be a string or silk.IPAddr");
1457 return -1;
1458 }
1459
1460 silkaddr = (silkPyIPAddr*)obj;
1461 retval = skIPWildcardCheckIp(&self->wildcard, &silkaddr->addr);
1462 Py_DECREF(obj);
1463
1464 return retval ? 1 : 0;
1465 }
1466
1467 static void
silkPyIPWildcard_dealloc(silkPyIPWildcard * obj)1468 silkPyIPWildcard_dealloc(
1469 silkPyIPWildcard *obj)
1470 {
1471 Py_XDECREF(obj->name);
1472 Py_TYPE(obj)->tp_free((PyObject*)obj);
1473 }
1474
1475 static PyObject *
silkPyIPWildcard_is_ipv6(silkPyIPWildcard UNUSED_NOv6 (* self))1476 silkPyIPWildcard_is_ipv6(
1477 silkPyIPWildcard UNUSED_NOv6(*self))
1478 {
1479 #if SK_ENABLE_IPV6
1480 return PyBool_FromLong(skIPWildcardIsV6(&self->wildcard));
1481 #else
1482 Py_RETURN_FALSE;
1483 #endif
1484 }
1485
1486 static PyObject *
silkPyIPWildcard_isipv6_deprecated(silkPyIPWildcard * self)1487 silkPyIPWildcard_isipv6_deprecated(
1488 silkPyIPWildcard *self)
1489 {
1490 /* deprecated in SiLK 3.0.0. Function is undocumented. */
1491 PyErr_Warn(PyExc_DeprecationWarning,
1492 ("IPWildcard.isipv6() is deprecated. "
1493 "Use IPWildcard.is_ipv6() instead."));
1494 return silkPyIPWildcard_is_ipv6(self);
1495 }
1496
1497 static PyObject *
silkPyIPWildcard_iter(silkPyIPWildcard * self)1498 silkPyIPWildcard_iter(
1499 silkPyIPWildcard *self)
1500 {
1501 silkPyIPWildcardIter *iter;
1502
1503 iter = (silkPyIPWildcardIter*)silkPyIPWildcardIterType.tp_alloc(
1504 &silkPyIPWildcardIterType, 0);
1505 if (iter) {
1506 ASSERT_RESULT(skIPWildcardIteratorBind(&iter->iter, &self->wildcard),
1507 int, 0);
1508 Py_INCREF(self);
1509 iter->wildcard = self;
1510 }
1511 return (PyObject*)iter;
1512 }
1513
1514 static PyObject *
silkPyIPWildcard_new(PyTypeObject * type,PyObject * args,PyObject * kwds)1515 silkPyIPWildcard_new(
1516 PyTypeObject *type,
1517 PyObject *args,
1518 PyObject *kwds)
1519 {
1520 static char *kwlist[] = {"wildcard", NULL};
1521 silkPyIPWildcard *self;
1522
1523 if (PyArg_ParseTupleAndKeywords(args, kwds, "O!", kwlist,
1524 &silkPyIPWildcardType, &self))
1525 {
1526 Py_INCREF(self);
1527 return (PyObject*)self;
1528 } else {
1529 PyErr_Clear();
1530 }
1531
1532 self = (silkPyIPWildcard*)type->tp_alloc(type, 0);
1533 if (self != NULL) {
1534 Py_ssize_t len;
1535 const char *wildcard;
1536 int rv;
1537
1538 if (!PyArg_ParseTupleAndKeywords(args, kwds, "s#", kwlist,
1539 &wildcard, &len))
1540 {
1541 Py_DECREF(self);
1542 return NULL;
1543 }
1544 rv = skStringParseIPWildcard(&self->wildcard, wildcard);
1545 if (rv != 0) {
1546 Py_DECREF(self);
1547 return PyErr_Format(PyExc_ValueError,
1548 "Illegal IP wildcard: %s", wildcard);
1549 }
1550 self->name = PyUnicode_DecodeASCII(wildcard, len, "strict");
1551 if (self->name == NULL) {
1552 Py_DECREF(self);
1553 return NULL;
1554 }
1555 }
1556
1557 return (PyObject*)self;
1558 }
1559
1560 static PyObject *
silkPyIPWildcard_repr(silkPyIPWildcard * obj)1561 silkPyIPWildcard_repr(
1562 silkPyIPWildcard *obj)
1563 {
1564 PyObject *format;
1565 PyObject *arg;
1566 PyObject *retval;
1567
1568 format = PyUnicode_FromString("silk.IPWildcard(\"%s\")");
1569 if (format == NULL) {
1570 return NULL;
1571 }
1572 arg = Py_BuildValue("(O)", obj->name);
1573 if (arg == NULL) {
1574 Py_DECREF(format);
1575 return NULL;
1576 }
1577 retval = PyUnicode_Format(format, arg);
1578 Py_DECREF(format);
1579 Py_DECREF(arg);
1580
1581 return retval;
1582 }
1583
1584 static PyObject *
silkPyIPWildcard_str(silkPyIPWildcard * obj)1585 silkPyIPWildcard_str(
1586 silkPyIPWildcard *obj)
1587 {
1588 Py_INCREF(obj->name);
1589 return obj->name;
1590 }
1591
1592
1593 /*
1594 *************************************************************************
1595 * IPSet
1596 *************************************************************************
1597 */
1598
1599 typedef struct silkPyIPSet_st {
1600 PyObject_HEAD
1601 skipset_t *ipset;
1602 } silkPyIPSet;
1603
1604 typedef struct silkPyIPSetIter_st {
1605 PyObject_HEAD
1606 silkPyIPSet *set;
1607 skipset_iterator_t iter;
1608 unsigned is_cidr : 1;
1609 } silkPyIPSetIter;
1610
1611 /* function prototypes */
1612 static void
1613 silkPyIPSetIter_dealloc(
1614 silkPyIPSetIter *self);
1615 static PyObject *
1616 silkPyIPSetIter_iternext(
1617 silkPyIPSetIter *self);
1618 static PyObject *
1619 silkPyIPSet_add(
1620 silkPyIPSet *self,
1621 PyObject *obj);
1622 static PyObject *
1623 silkPyIPSet_add_range(
1624 silkPyIPSet *self,
1625 PyObject *args,
1626 PyObject *kwds);
1627 static PyObject *
1628 silkPyIPSet_cardinality(
1629 silkPyIPSet *self);
1630 static PyObject *
1631 silkPyIPSet_cidr_iter(
1632 silkPyIPSet *self);
1633 static PyObject *
1634 silkPyIPSet_clear(
1635 silkPyIPSet *self);
1636 static int
1637 silkPyIPSet_contains(
1638 silkPyIPSet *self,
1639 PyObject *obj);
1640 static PyObject *
1641 silkPyIPSet_convert(
1642 silkPyIPSet *self,
1643 PyObject *obj);
1644 static void
1645 silkPyIPSet_dealloc(
1646 silkPyIPSet *obj);
1647 static PyObject *
1648 silkPyIPSet_difference_update(
1649 silkPyIPSet *self,
1650 silkPyIPSet *obj);
1651 static PyObject *
1652 silkPyIPSet_discard(
1653 silkPyIPSet *self,
1654 PyObject *obj);
1655 static int
1656 silkPyIPSet_init(
1657 silkPyIPSet *self,
1658 PyObject *args,
1659 PyObject *kwds);
1660 static PyObject *
1661 silkPyIPSet_intersection_update(
1662 silkPyIPSet *self,
1663 silkPyIPSet *obj);
1664 static PyObject *
1665 silkPyIPSet_isdisjoint(
1666 silkPyIPSet *self,
1667 PyObject *obj);
1668 static PyObject *
1669 silkPyIPSet_is_ipv6(
1670 silkPyIPSet *self);
1671 static PyObject *
1672 silkPyIPSet_iter(
1673 silkPyIPSet *self);
1674 static Py_ssize_t
1675 silkPyIPSet_len(
1676 silkPyIPSet *self);
1677 static PyObject *
1678 silkPyIPSet_save(
1679 silkPyIPSet *self,
1680 PyObject *args,
1681 PyObject *kwds);
1682 static PyObject *
1683 silkPyIPSet_union_update(
1684 silkPyIPSet *self,
1685 silkPyIPSet *obj);
1686
1687 /* define docs and methods */
1688 #define silkPyIPSet_doc \
1689 "IPSetBase() -> empty IPset\n" \
1690 "IPSetBase(filename) -> IPset from file"
1691
1692 static PyMethodDef silkPyIPSet_methods[] = {
1693 {"__reduce__", (PyCFunction)reduce_error, METH_NOARGS, ""},
1694 {"cardinality", (PyCFunction)silkPyIPSet_cardinality, METH_NOARGS,
1695 "ipset.cardinality() -> long -- number of IP Addresses in the IPSet"},
1696 {"intersection_update", (PyCFunction)silkPyIPSet_intersection_update,
1697 METH_O,
1698 ("Return the intersection of two IPSets as a new IPSet.\n"
1699 "\n"
1700 "(i.e. all elements that are in both IPSets.)")},
1701 {"update", (PyCFunction)silkPyIPSet_union_update,
1702 METH_O,
1703 ("Update the IPSet with the union of itself and another.")},
1704 {"difference_update", (PyCFunction)silkPyIPSet_difference_update,
1705 METH_O,
1706 ("Remove all elements of another IPSet from this IPSet.")},
1707 {"clear", (PyCFunction)silkPyIPSet_clear, METH_NOARGS,
1708 ("Remove all elements from this IPSet.")},
1709 {"save", (PyCFunction)silkPyIPSet_save, METH_KEYWORDS | METH_VARARGS,
1710 "ipset.save(filename[, compression]) -- Saves the set to a file."},
1711 {"cidr_iter", (PyCFunction)silkPyIPSet_cidr_iter, METH_NOARGS,
1712 "Return an iterator over IPAddr/prefix tuples."},
1713 {"add", (PyCFunction)silkPyIPSet_add, METH_O,
1714 ("Add an element to an IPSet. The element may be an IP address, an\n"
1715 "IP wildcard, or the string representation of either.\n"
1716 "\n"
1717 "This has no effect for any element already present.")},
1718 {"add_range", (PyCFunction)silkPyIPSet_add_range,
1719 METH_KEYWORDS | METH_VARARGS,
1720 ("Add all IPs between start and end, inclusive, to an IPSet. Each\n"
1721 "argument may be an IP address or the string representation of an\n"
1722 "IP address\n"
1723 "\n"
1724 "This has no effect when all elements are already present.")},
1725 {"discard", (PyCFunction)silkPyIPSet_discard, METH_O,
1726 ("Discard an element to an IPSet. The element may be an IP address, an\n"
1727 "IP wildcard, or the string representation of either.\n"
1728 "\n"
1729 "This has no effect for any element not present in the IPset.")},
1730 {"isdisjoint", (PyCFunction)silkPyIPSet_isdisjoint, METH_O,
1731 "Return whether the IPSet has any elements in common with the argument"},
1732 {"is_ipv6", (PyCFunction)silkPyIPSet_is_ipv6, METH_NOARGS,
1733 "Return whether the IPSet is an IPv6 set."},
1734 {"convert", (PyCFunction)silkPyIPSet_convert, METH_VARARGS,
1735 ("Convert the current IPSet to IPv4 or IPv6 if the argument is 4 or 6.\n"
1736 "Converting an IPv6 set to IPv4 will throw a ValueError if there are\n"
1737 "addresses in the set that cannot be represented in IPv4.")},
1738 {NULL, NULL, 0, NULL} /* Sentinel */
1739 };
1740
1741 static PySequenceMethods silkPyIPSet_sequence_methods = {
1742 #if PY_VERSION_HEX < 0x02050000
1743 (inquiry)silkPyIPSet_len, /* sq_length */
1744 #else
1745 (lenfunc)silkPyIPSet_len, /* sq_length */
1746 #endif
1747 0, /* sq_concat */
1748 0, /* sq_repeat */
1749 0, /* sq_item */
1750 0, /* sq_slice */
1751 0, /* sq_ass_item */
1752 0, /* sq_ass_slice */
1753 (objobjproc)silkPyIPSet_contains, /* sq_contains */
1754 0, /* sq_inplace_concat */
1755 0 /* sq_inplace_repeat */
1756 };
1757
1758 /* define the object types */
1759 static PyTypeObject silkPyIPSetType = {
1760 PyVarObject_HEAD_INIT(NULL, 0)
1761 "silk.pysilk.IPSetBase", /* tp_name */
1762 sizeof(silkPyIPSet), /* tp_basicsize */
1763 0, /* tp_itemsize */
1764 (destructor)silkPyIPSet_dealloc, /* tp_dealloc */
1765 0, /* tp_vectorcall_offset (Py 3.8) */
1766 0, /* tp_getattr */
1767 0, /* tp_setattr */
1768 0, /* tp_as_async (tp_compare in Py2.x) */
1769 0, /* tp_repr */
1770 0, /* tp_as_number */
1771 &silkPyIPSet_sequence_methods, /* tp_as_sequence */
1772 0, /* tp_as_mapping */
1773 0, /* tp_hash */
1774 0, /* tp_call */
1775 0, /* tp_str */
1776 0, /* tp_getattro */
1777 0, /* tp_setattro */
1778 0, /* tp_as_buffer */
1779 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
1780 silkPyIPSet_doc, /* tp_doc */
1781 0, /* tp_traverse */
1782 0, /* tp_clear */
1783 0, /* tp_richcompare */
1784 0, /* tp_weaklistoffset */
1785 (getiterfunc)silkPyIPSet_iter, /* tp_iter */
1786 0, /* tp_iternext */
1787 silkPyIPSet_methods, /* tp_methods */
1788 0, /* tp_members */
1789 0, /* tp_getset */
1790 0, /* tp_base */
1791 0, /* tp_dict */
1792 0, /* tp_descr_get */
1793 0, /* tp_descr_set */
1794 0, /* tp_dictoffset */
1795 (initproc)silkPyIPSet_init, /* tp_init */
1796 0, /* tp_alloc */
1797 0, /* tp_new */
1798 0, /* tp_free */
1799 0, /* tp_is_gc */
1800 0, /* tp_bases */
1801 0, /* tp_mro */
1802 0, /* tp_cache */
1803 0, /* tp_subclasses */
1804 0, /* tp_weaklist */
1805 0 /* tp_del */
1806 #if PY_VERSION_HEX >= 0x02060000
1807 ,0 /* tp_version_tag */
1808 #endif
1809 #if PY_VERSION_HEX >= 0x03040000
1810 ,0 /* tp_finalize */
1811 #endif
1812 #if PY_VERSION_HEX >= 0x03080000
1813 ,0 /* tp_vectorcall */
1814 ,0 /* tp_print */
1815 #endif
1816 };
1817
1818 static PyTypeObject silkPyIPSetIterType = {
1819 PyVarObject_HEAD_INIT(NULL, 0)
1820 "silk.pysilk.IPSetIter", /* tp_name */
1821 sizeof(silkPyIPSetIter), /* tp_basicsize */
1822 0, /* tp_itemsize */
1823 (destructor)silkPyIPSetIter_dealloc, /* tp_dealloc */
1824 0, /* tp_vectorcall_offset (Py 3.8) */
1825 0, /* tp_getattr */
1826 0, /* tp_setattr */
1827 0, /* tp_as_async (tp_compare in Py2.x) */
1828 0, /* tp_repr */
1829 0, /* tp_as_number */
1830 0, /* tp_as_sequence */
1831 0, /* tp_as_mapping */
1832 0, /* tp_hash */
1833 0, /* tp_call */
1834 0, /* tp_str */
1835 0, /* tp_getattro */
1836 0, /* tp_setattro */
1837 0, /* tp_as_buffer */
1838 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
1839 "IP Set iterator object", /* tp_doc */
1840 0, /* tp_traverse */
1841 0, /* tp_clear */
1842 0, /* tp_richcompare */
1843 0, /* tp_weaklistoffset */
1844 iter_iter, /* tp_iter */
1845 (iternextfunc)silkPyIPSetIter_iternext, /* tp_iternext */
1846 0, /* tp_methods */
1847 0, /* tp_members */
1848 0, /* tp_getset */
1849 0, /* tp_base */
1850 0, /* tp_dict */
1851 0, /* tp_descr_get */
1852 0, /* tp_descr_set */
1853 0, /* tp_dictoffset */
1854 0, /* tp_init */
1855 0, /* tp_alloc */
1856 0, /* tp_new */
1857 0, /* tp_free */
1858 0, /* tp_is_gc */
1859 0, /* tp_bases */
1860 0, /* tp_mro */
1861 0, /* tp_cache */
1862 0, /* tp_subclasses */
1863 0, /* tp_weaklist */
1864 0 /* tp_del */
1865 #if PY_VERSION_HEX >= 0x02060000
1866 ,0 /* tp_version_tag */
1867 #endif
1868 #if PY_VERSION_HEX >= 0x03040000
1869 ,0 /* tp_finalize */
1870 #endif
1871 #if PY_VERSION_HEX >= 0x03080000
1872 ,0 /* tp_vectorcall */
1873 ,0 /* tp_print */
1874 #endif
1875 };
1876
1877
1878 /* macro and function defintions */
1879 #define silkPyIPSet_Check(op) \
1880 PyObject_TypeCheck(op, &silkPyIPSetType)
1881 #define silkPyIPSetIter_Check(op) \
1882 PyObject_TypeCheck(op, &silkPyIPSetIterType)
1883
1884 static void
silkPyIPSetIter_dealloc(silkPyIPSetIter * self)1885 silkPyIPSetIter_dealloc(
1886 silkPyIPSetIter *self)
1887 {
1888 Py_XDECREF(self->set);
1889 Py_TYPE(self)->tp_free((PyObject*)self);
1890 }
1891
1892 static PyObject *
silkPyIPSetIter_iternext(silkPyIPSetIter * self)1893 silkPyIPSetIter_iternext(
1894 silkPyIPSetIter *self)
1895 {
1896 silkPyIPAddr *addr;
1897 int rv;
1898 PyObject *retval;
1899 skipaddr_t raw_addr;
1900 uint32_t raw_prefix;
1901
1902 rv = skIPSetIteratorNext(&self->iter, &raw_addr, &raw_prefix);
1903 if (rv == SK_ITERATOR_NO_MORE_ENTRIES) {
1904 PyErr_SetNone(PyExc_StopIteration);
1905 return NULL;
1906 }
1907
1908 addr = (silkPyIPAddr*)silkPyIPAddrType.tp_alloc(&silkPyIPAddrType, 0);
1909 if (addr == NULL) {
1910 return NULL;
1911 }
1912 addr->addr = raw_addr;
1913
1914 if (!self->is_cidr) {
1915 retval = (PyObject*)addr;
1916 } else {
1917 PyObject *pair;
1918 PyObject *len;
1919
1920 len = PyInt_FromLong(raw_prefix);
1921 if (len == NULL) {
1922 Py_DECREF(addr);
1923 return NULL;
1924 }
1925 pair = PyTuple_New(2);
1926 if (pair == NULL) {
1927 Py_DECREF(addr);
1928 Py_DECREF(len);
1929 }
1930 PyTuple_SET_ITEM(pair, 0, (PyObject*)addr);
1931 PyTuple_SET_ITEM(pair, 1, len);
1932
1933 retval = pair;
1934 }
1935
1936 return retval;
1937 }
1938
1939 static PyObject *
silkPyIPSet_add(silkPyIPSet * self,PyObject * obj)1940 silkPyIPSet_add(
1941 silkPyIPSet *self,
1942 PyObject *obj)
1943 {
1944 int rv;
1945
1946 if (silkPyIPAddr_Check(obj)) {
1947 silkPyIPAddr *addr = (silkPyIPAddr*)obj;
1948
1949 rv = skIPSetInsertAddress(self->ipset, &addr->addr, 0);
1950 } else if (silkPyIPWildcard_Check(obj)) {
1951 silkPyIPWildcard *wild;
1952
1953 assert(silkPyIPWildcard_Check(obj));
1954
1955 wild = (silkPyIPWildcard*)obj;
1956
1957 rv = skIPSetInsertIPWildcard(self->ipset, &wild->wildcard);
1958 } else {
1959 PyErr_SetString(PyExc_TypeError,
1960 "Must be a silk.IPAddr or a silk.IPWildcard");
1961 return NULL;
1962 }
1963
1964 if (rv == SKIPSET_ERR_ALLOC) {
1965 return PyErr_NoMemory();
1966 }
1967 if (rv == SKIPSET_ERR_IPV6) {
1968 PyErr_SetString(PyExc_ValueError,
1969 "Must only include IPv4 addresses");
1970 return NULL;
1971 }
1972 assert(rv == SKIPSET_OK);
1973
1974 Py_INCREF(self);
1975 return (PyObject*)self;
1976 }
1977
1978 static PyObject *
silkPyIPSet_add_range(silkPyIPSet * self,PyObject * args,PyObject * kwds)1979 silkPyIPSet_add_range(
1980 silkPyIPSet *self,
1981 PyObject *args,
1982 PyObject *kwds)
1983 {
1984 static char *kwlist[] = {"start", "end", NULL};
1985 PyObject *start_obj;
1986 PyObject *end_obj;
1987 silkPyIPAddr *start_addr;
1988 silkPyIPAddr *end_addr;
1989 int rv;
1990
1991 if (!PyArg_ParseTupleAndKeywords(args, kwds, "OO", kwlist,
1992 &start_obj, &end_obj))
1993 {
1994 return NULL;
1995 }
1996 if (!silkPyIPAddr_Check(start_obj)) {
1997 PyErr_SetString(PyExc_TypeError,
1998 "The start argument must be a silk.IPAddr");
1999 return NULL;
2000 }
2001 if (!silkPyIPAddr_Check(end_obj)) {
2002 PyErr_SetString(PyExc_TypeError,
2003 "The end argument must be a silk.IPAddr");
2004 return NULL;
2005 }
2006
2007 start_addr = (silkPyIPAddr*)start_obj;
2008 end_addr = (silkPyIPAddr*)end_obj;
2009
2010 rv = skIPSetInsertRange(self->ipset, &start_addr->addr, &end_addr->addr);
2011 if (rv == SKIPSET_ERR_ALLOC) {
2012 return PyErr_NoMemory();
2013 }
2014 if (rv == SKIPSET_ERR_IPV6) {
2015 PyErr_SetString(PyExc_ValueError,
2016 "Must only include IPv4 addresses");
2017 return NULL;
2018 }
2019 if (rv == SKIPSET_ERR_BADINPUT) {
2020 PyErr_SetString(PyExc_ValueError,
2021 "The start of range must not be greater than the end");
2022 return NULL;
2023 }
2024 assert(rv == SKIPSET_OK);
2025
2026 Py_INCREF(self);
2027 return (PyObject*)self;
2028 }
2029
2030 static PyObject *
silkPyIPSet_cardinality(silkPyIPSet * self)2031 silkPyIPSet_cardinality(
2032 silkPyIPSet *self)
2033 {
2034 uint64_t count;
2035 double count_d;
2036
2037 skIPSetClean(self->ipset);
2038 count = skIPSetCountIPs(self->ipset, &count_d);
2039 if (count == UINT64_MAX) {
2040 return PyLong_FromDouble(count_d);
2041 }
2042 return PyLong_FromUnsignedLongLong(count);
2043 }
2044
2045 static PyObject *
silkPyIPSet_cidr_iter(silkPyIPSet * self)2046 silkPyIPSet_cidr_iter(
2047 silkPyIPSet *self)
2048 {
2049 silkPyIPSetIter *iter;
2050
2051 iter = (silkPyIPSetIter*)silkPyIPSetIterType.tp_alloc(
2052 &silkPyIPSetIterType, 0);
2053 if (iter) {
2054 skIPSetClean(self->ipset);
2055 if (skIPSetIteratorBind(&iter->iter, self->ipset, 1,SK_IPV6POLICY_MIX))
2056 {
2057 Py_DECREF(iter);
2058 return PyErr_NoMemory();
2059 }
2060 Py_INCREF(self);
2061 iter->set = self;
2062 iter->is_cidr = 1;
2063 }
2064 return (PyObject*)iter;
2065 }
2066
2067 static PyObject *
silkPyIPSet_clear(silkPyIPSet * self)2068 silkPyIPSet_clear(
2069 silkPyIPSet *self)
2070 {
2071 skIPSetRemoveAll(self->ipset);
2072
2073 Py_INCREF(self);
2074 return (PyObject*)self;
2075 }
2076
2077 static int
silkPyIPSet_contains(silkPyIPSet * self,PyObject * obj)2078 silkPyIPSet_contains(
2079 silkPyIPSet *self,
2080 PyObject *obj)
2081 {
2082 int retval;
2083 silkPyIPAddr *silkaddr;
2084
2085 if (IS_STRING(obj)) {
2086 obj = PyObject_CallFunctionObjArgs((PyObject*)&silkPyIPAddrType,
2087 obj, NULL);
2088 if (obj == NULL) {
2089 return -1;
2090 }
2091 } else if (silkPyIPAddr_Check(obj)) {
2092 Py_INCREF(obj);
2093 } else {
2094 PyErr_SetString(PyExc_TypeError, "Must be a string or silk.IPAddr");
2095 return -1;
2096 }
2097
2098 silkaddr = (silkPyIPAddr*)obj;
2099 retval = skIPSetCheckAddress(self->ipset, &silkaddr->addr);
2100 Py_DECREF(obj);
2101
2102 return retval ? 1 : 0;
2103 }
2104
2105 static PyObject *
silkPyIPSet_convert(silkPyIPSet * self,PyObject * args)2106 silkPyIPSet_convert(
2107 silkPyIPSet *self,
2108 PyObject *args)
2109 {
2110 int rv;
2111 int version;
2112
2113 if (!PyArg_ParseTuple(args, "i", &version)) {
2114 return NULL;
2115 }
2116 if (version != 4 && version != 6) {
2117 PyErr_SetString(PyExc_ValueError, "Version must be 4 or 6");
2118 return NULL;
2119 }
2120
2121 rv = skIPSetConvert(self->ipset, version);
2122 if (rv == 0) {
2123 Py_INCREF(self);
2124 return (PyObject*)self;
2125 }
2126 if (rv == SKIPSET_ERR_IPV6) {
2127 #if SK_ENABLE_IPV6
2128 PyErr_SetString(
2129 PyExc_ValueError,
2130 "IPSet cannot be converted to v4, as it contains v6 addresses");
2131 #else
2132 PyErr_SetString(PyExc_ValueError,
2133 "This build of SiLK does not support IPv6");
2134 #endif
2135 return NULL;
2136 }
2137 return PyErr_Format(PyExc_RuntimeError,
2138 "Unexpected error converting IPSet: %d", rv);
2139 }
2140
2141 static void
silkPyIPSet_dealloc(silkPyIPSet * obj)2142 silkPyIPSet_dealloc(
2143 silkPyIPSet *obj)
2144 {
2145 if (obj->ipset) {
2146 skIPSetDestroy(&obj->ipset);
2147 }
2148 Py_TYPE(obj)->tp_free((PyObject*)obj);
2149 }
2150
2151 static PyObject *
silkPyIPSet_difference_update(silkPyIPSet * self,silkPyIPSet * obj)2152 silkPyIPSet_difference_update(
2153 silkPyIPSet *self,
2154 silkPyIPSet *obj)
2155 {
2156 if (!silkPyIPSet_Check(obj)) {
2157 PyErr_SetString(PyExc_NotImplementedError,
2158 "Argument must be a silk.IPSet");
2159 return NULL;
2160 }
2161
2162 skIPSetClean(self->ipset);
2163 skIPSetClean(obj->ipset);
2164 skIPSetSubtract(self->ipset, obj->ipset);
2165
2166 Py_INCREF(self);
2167 return (PyObject*)self;
2168 }
2169
2170 static PyObject *
silkPyIPSet_discard(silkPyIPSet * self,PyObject * obj)2171 silkPyIPSet_discard(
2172 silkPyIPSet *self,
2173 PyObject *obj)
2174 {
2175 int rv;
2176
2177 if (silkPyIPAddr_Check(obj)) {
2178 silkPyIPAddr *addr = (silkPyIPAddr*)obj;
2179
2180 rv = skIPSetRemoveAddress(self->ipset, &addr->addr, 0);
2181 } else if (silkPyIPWildcard_Check(obj)) {
2182 silkPyIPWildcard *wild;
2183
2184 assert(silkPyIPWildcard_Check(obj));
2185
2186 wild = (silkPyIPWildcard*)obj;
2187
2188 rv = skIPSetRemoveIPWildcard(self->ipset, &wild->wildcard);
2189 } else {
2190 PyErr_SetString(PyExc_TypeError,
2191 "Must be a silk.IPAddr or a silk.IPWildcard");
2192 return NULL;
2193 }
2194
2195 if (rv == SKIPSET_ERR_ALLOC) {
2196 return PyErr_NoMemory();
2197 }
2198 assert(rv == SKIPSET_OK);
2199
2200 Py_INCREF(self);
2201 return (PyObject*)self;
2202 }
2203
2204 static int
silkPyIPSet_init(silkPyIPSet * self,PyObject * args,PyObject * kwds)2205 silkPyIPSet_init(
2206 silkPyIPSet *self,
2207 PyObject *args,
2208 PyObject *kwds)
2209 {
2210 static char *kwlist[] = {"filename", NULL};
2211 char errbuf[2 * PATH_MAX];
2212 skstream_t *stream = NULL;
2213 char *fname = NULL;
2214 int rv;
2215
2216 if (!PyArg_ParseTupleAndKeywords(args, kwds, "|et", kwlist,
2217 Py_FileSystemDefaultEncoding, &fname))
2218 {
2219 return -1;
2220 }
2221
2222 if (fname) {
2223 if ((rv = skStreamCreate(&stream, SK_IO_READ, SK_CONTENT_SILK))
2224 || (rv = skStreamBind(stream, fname))
2225 || (rv = skStreamOpen(stream)))
2226 {
2227 skStreamLastErrMessage(stream, rv, errbuf, sizeof(errbuf));
2228 PyErr_Format(PyExc_IOError, "Unable to read IPSet from %s: %s",
2229 fname, errbuf);
2230 skStreamDestroy(&stream);
2231 PyMem_Free(fname);
2232 return -1;
2233 }
2234 rv = skIPSetRead(&self->ipset, stream);
2235 if (rv) {
2236 if (SKIPSET_ERR_FILEIO == rv) {
2237 skStreamLastErrMessage(stream,
2238 skStreamGetLastReturnValue(stream),
2239 errbuf, sizeof(errbuf));
2240 } else {
2241 strncpy(errbuf, skIPSetStrerror(rv), sizeof(errbuf));
2242 }
2243 PyErr_Format(PyExc_IOError, "Unable to read IPSet from %s: %s",
2244 fname, errbuf);
2245 skStreamDestroy(&stream);
2246 PyMem_Free(fname);
2247 return -1;
2248 }
2249 skStreamDestroy(&stream);
2250 PyMem_Free(fname);
2251 } else {
2252 rv = skIPSetCreate(&self->ipset, 0);
2253 if (rv == SKIPSET_ERR_ALLOC) {
2254 PyErr_NoMemory();
2255 return -1;
2256 }
2257 assert(rv == SKIPSET_OK);
2258 }
2259
2260 return 0;
2261 }
2262
2263 static PyObject *
silkPyIPSet_is_ipv6(silkPyIPSet * self)2264 silkPyIPSet_is_ipv6(
2265 silkPyIPSet *self)
2266 {
2267 return PyBool_FromLong(skIPSetIsV6(self->ipset));
2268 }
2269
2270 static PyObject *
silkPyIPSet_intersection_update(silkPyIPSet * self,silkPyIPSet * obj)2271 silkPyIPSet_intersection_update(
2272 silkPyIPSet *self,
2273 silkPyIPSet *obj)
2274 {
2275 if (!silkPyIPSet_Check(obj)) {
2276 PyErr_SetString(PyExc_NotImplementedError,
2277 "Argument must be a silk.IPSet");
2278 return NULL;
2279 }
2280
2281 skIPSetClean(self->ipset);
2282 skIPSetClean(obj->ipset);
2283 skIPSetIntersect(self->ipset, obj->ipset);
2284
2285 Py_INCREF(self);
2286 return (PyObject*)self;
2287 }
2288
2289 static PyObject *
silkPyIPSet_isdisjoint(silkPyIPSet * self,PyObject * obj)2290 silkPyIPSet_isdisjoint(
2291 silkPyIPSet *self,
2292 PyObject *obj)
2293 {
2294 int disjoint;
2295
2296 if (silkPyIPSet_Check(obj)) {
2297 disjoint = !skIPSetCheckIPSet(
2298 self->ipset, ((silkPyIPSet*)obj)->ipset);
2299 } else if (silkPyIPWildcard_Check(obj)) {
2300 disjoint = !skIPSetCheckIPWildcard(
2301 self->ipset, &((silkPyIPWildcard*)obj)->wildcard);
2302 } else {
2303 PyErr_SetString(PyExc_TypeError, "Expected an IPSet or an IPWildcard");
2304 return NULL;
2305 }
2306 if (disjoint) {
2307 Py_RETURN_TRUE;
2308 }
2309 Py_RETURN_FALSE;
2310 }
2311
2312 static PyObject *
silkPyIPSet_iter(silkPyIPSet * self)2313 silkPyIPSet_iter(
2314 silkPyIPSet *self)
2315 {
2316 silkPyIPSetIter *iter;
2317
2318 iter = (silkPyIPSetIter*)silkPyIPSetIterType.tp_alloc(
2319 &silkPyIPSetIterType, 0);
2320 if (iter) {
2321 skIPSetClean(self->ipset);
2322 if (skIPSetIteratorBind(&iter->iter, self->ipset, 0,SK_IPV6POLICY_MIX))
2323 {
2324 Py_DECREF(iter);
2325 return PyErr_NoMemory();
2326 }
2327 Py_INCREF(self);
2328 iter->set = self;
2329 }
2330 return (PyObject*)iter;
2331 }
2332
2333 static Py_ssize_t
silkPyIPSet_len(silkPyIPSet * self)2334 silkPyIPSet_len(
2335 silkPyIPSet *self)
2336 {
2337 uint64_t count;
2338 double count_d;
2339
2340 skIPSetClean(self->ipset);
2341 count = skIPSetCountIPs(self->ipset, &count_d);
2342 if (count > PY_SSIZE_T_MAX) {
2343 PyErr_SetString(PyExc_OverflowError, "IPSet too long for integer");
2344 return -1;
2345 }
2346 return (Py_ssize_t)count;
2347 }
2348
2349 static PyObject *
silkPyIPSet_save(silkPyIPSet * self,PyObject * args,PyObject * kwds)2350 silkPyIPSet_save(
2351 silkPyIPSet *self,
2352 PyObject *args,
2353 PyObject *kwds)
2354 {
2355 int rv;
2356 skstream_t *stream;
2357
2358 if ((stream = open_silkfile_write(args, kwds)) == NULL) {
2359 return NULL;
2360 }
2361
2362 skIPSetClean(self->ipset);
2363 rv = skIPSetWrite(self->ipset, stream);
2364 skStreamDestroy(&stream);
2365 if (rv != SKIPSET_OK) {
2366 PyErr_SetString(PyExc_IOError, skIPSetStrerror(rv));
2367 return NULL;
2368 }
2369
2370 Py_RETURN_NONE;
2371 }
2372
2373 static PyObject *
silkPyIPSet_union_update(silkPyIPSet * self,silkPyIPSet * obj)2374 silkPyIPSet_union_update(
2375 silkPyIPSet *self,
2376 silkPyIPSet *obj)
2377 {
2378 int rv;
2379
2380 if (!silkPyIPSet_Check(obj)) {
2381 PyErr_SetString(PyExc_NotImplementedError,
2382 "Argument must be a silk.IPSet");
2383 return NULL;
2384 }
2385
2386 skIPSetClean(self->ipset);
2387 skIPSetClean(obj->ipset);
2388 rv = skIPSetUnion(self->ipset, obj->ipset);
2389 if (rv != 0) {
2390 return PyErr_NoMemory();
2391 }
2392
2393 Py_INCREF(self);
2394 return (PyObject*)self;
2395 }
2396
2397
2398 /* *************************************************************************
2399 * Prefix Map
2400 *************************************************************************
2401 */
2402
2403 typedef struct silkPyPmap_st {
2404 PyObject_HEAD
2405 skPrefixMap_t *map;
2406 } silkPyPmap;
2407
2408 typedef struct silkPyPmapIter_st {
2409 PyObject_HEAD
2410 silkPyPmap *map;
2411 skPrefixMapIterator_t iter;
2412 } silkPyPmapIter;
2413
2414 /* function prototypes */
2415 static void
2416 silkPyPmapIter_dealloc(
2417 silkPyPmapIter *self);
2418 static PyObject *
2419 silkPyPmapIter_iternext(
2420 silkPyPmapIter *self);
2421 static void
2422 silkPyPmap_dealloc(
2423 silkPyPmap *obj);
2424 static PyObject *
2425 silkPyPmap_get_content(
2426 silkPyPmap *self,
2427 void UNUSED(*cbdata));
2428 static PyObject *
2429 silkPyPmap_get_name(
2430 silkPyPmap *self,
2431 void UNUSED(*cbdata));
2432 static PyObject *
2433 silkPyPmap_get_num_values(
2434 silkPyPmap *self,
2435 void UNUSED(*cbdata));
2436 static PyObject *
2437 silkPyPmap_get_value_string(
2438 silkPyPmap *self,
2439 PyObject *value);
2440 static int
2441 silkPyPmap_init(
2442 silkPyPmap *self,
2443 PyObject *args,
2444 PyObject *kwds);
2445 static PyObject *
2446 silkPyPmap_iter(
2447 silkPyPmap *self);
2448 static PyObject *
2449 silkPyPmap_subscript(
2450 silkPyPmap *self,
2451 PyObject *sub);
2452
2453 /* define docs and methods */
2454 #define silkPyPmap_doc \
2455 "PMapBase(filename) -> Prefix map from file"
2456
2457 static PyMethodDef silkPyPmap_methods[] = {
2458 {"__reduce__", (PyCFunction)reduce_error, METH_NOARGS, ""},
2459 {"get_value_string", (PyCFunction)silkPyPmap_get_value_string, METH_O,
2460 ("Get the string associated with an integer value")},
2461 {NULL, NULL, 0, NULL} /* Sentinel */
2462 };
2463
2464 static PyGetSetDef silkPyPmap_getsetters[] = {
2465 {"content", (getter)silkPyPmap_get_content, NULL, "Content type", NULL},
2466 {"name", (getter)silkPyPmap_get_name, NULL, "Prefix map name", NULL},
2467 {"num_values", (getter)silkPyPmap_get_num_values, NULL,
2468 "Prefix map number of values", NULL},
2469 {NULL, NULL, NULL, NULL, NULL}
2470 };
2471
2472 static PyMappingMethods silkPyPmap_mapping_methods = {
2473 0,
2474 (binaryfunc)silkPyPmap_subscript,
2475 0
2476 };
2477
2478 /* define the object types */
2479 static PyTypeObject silkPyPmapType = {
2480 PyVarObject_HEAD_INIT(NULL, 0)
2481 "silk.pysilk.PMapBase", /* tp_name */
2482 sizeof(silkPyPmap), /* tp_basicsize */
2483 0, /* tp_itemsize */
2484 (destructor)silkPyPmap_dealloc, /* tp_dealloc */
2485 0, /* tp_vectorcall_offset (Py 3.8) */
2486 0, /* tp_getattr */
2487 0, /* tp_setattr */
2488 0, /* tp_as_async (tp_compare in Py2.x) */
2489 0, /* tp_repr */
2490 0, /* tp_as_number */
2491 0, /* tp_as_sequence */
2492 &silkPyPmap_mapping_methods, /* tp_as_mapping */
2493 0, /* tp_hash */
2494 0, /* tp_call */
2495 0, /* tp_str */
2496 0, /* tp_getattro */
2497 0, /* tp_setattro */
2498 0, /* tp_as_buffer */
2499 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
2500 silkPyPmap_doc, /* tp_doc */
2501 0, /* tp_traverse */
2502 0, /* tp_clear */
2503 0, /* tp_richcompare */
2504 0, /* tp_weaklistoffset */
2505 (getiterfunc)silkPyPmap_iter, /* tp_iter */
2506 0, /* tp_iternext */
2507 silkPyPmap_methods, /* tp_methods */
2508 0, /* tp_members */
2509 silkPyPmap_getsetters, /* tp_getset */
2510 0, /* tp_base */
2511 0, /* tp_dict */
2512 0, /* tp_descr_get */
2513 0, /* tp_descr_set */
2514 0, /* tp_dictoffset */
2515 (initproc)silkPyPmap_init, /* tp_init */
2516 0, /* tp_alloc */
2517 0, /* tp_new */
2518 0, /* tp_free */
2519 0, /* tp_is_gc */
2520 0, /* tp_bases */
2521 0, /* tp_mro */
2522 0, /* tp_cache */
2523 0, /* tp_subclasses */
2524 0, /* tp_weaklist */
2525 0 /* tp_del */
2526 #if PY_VERSION_HEX >= 0x02060000
2527 ,0 /* tp_version_tag */
2528 #endif
2529 #if PY_VERSION_HEX >= 0x03040000
2530 ,0 /* tp_finalize */
2531 #endif
2532 #if PY_VERSION_HEX >= 0x03080000
2533 ,0 /* tp_vectorcall */
2534 ,0 /* tp_print */
2535 #endif
2536 };
2537
2538 static PyTypeObject silkPyPmapIterType = {
2539 PyVarObject_HEAD_INIT(NULL, 0)
2540 "silk.pysilk.PMapBaseIter", /* tp_name */
2541 sizeof(silkPyPmapIterType), /* tp_basicsize */
2542 0, /* tp_itemsize */
2543 (destructor)silkPyPmapIter_dealloc, /* tp_dealloc */
2544 0, /* tp_vectorcall_offset (Py 3.8) */
2545 0, /* tp_getattr */
2546 0, /* tp_setattr */
2547 0, /* tp_as_async (tp_compare in Py2.x) */
2548 0, /* tp_repr */
2549 0, /* tp_as_number */
2550 0, /* tp_as_sequence */
2551 0, /* tp_as_mapping */
2552 0, /* tp_hash */
2553 0, /* tp_call */
2554 0, /* tp_str */
2555 0, /* tp_getattro */
2556 0, /* tp_setattro */
2557 0, /* tp_as_buffer */
2558 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
2559 "Prefix map iterator object", /* tp_doc */
2560 0, /* tp_traverse */
2561 0, /* tp_clear */
2562 0, /* tp_richcompare */
2563 0, /* tp_weaklistoffset */
2564 iter_iter, /* tp_iter */
2565 (iternextfunc)silkPyPmapIter_iternext, /* tp_iternext */
2566 0, /* tp_methods */
2567 0, /* tp_members */
2568 0, /* tp_getset */
2569 0, /* tp_base */
2570 0, /* tp_dict */
2571 0, /* tp_descr_get */
2572 0, /* tp_descr_set */
2573 0, /* tp_dictoffset */
2574 0, /* tp_init */
2575 0, /* tp_alloc */
2576 0, /* tp_new */
2577 0, /* tp_free */
2578 0, /* tp_is_gc */
2579 0, /* tp_bases */
2580 0, /* tp_mro */
2581 0, /* tp_cache */
2582 0, /* tp_subclasses */
2583 0, /* tp_weaklist */
2584 0 /* tp_del */
2585 #if PY_VERSION_HEX >= 0x02060000
2586 ,0 /* tp_version_tag */
2587 #endif
2588 #if PY_VERSION_HEX >= 0x03040000
2589 ,0 /* tp_finalize */
2590 #endif
2591 #if PY_VERSION_HEX >= 0x03080000
2592 ,0 /* tp_vectorcall */
2593 ,0 /* tp_print */
2594 #endif
2595 };
2596
2597 /* macro and function defintions */
2598 #define silkPyPmap_Check(op) \
2599 PyObject_TypeCheck(op, &silkPyPmapType)
2600 #define silkPyPmapIter_Check(op) \
2601 PyObject_TypeCheck(op, &silkPyPmapIterType)
2602
2603 static void
silkPyPmapIter_dealloc(silkPyPmapIter * self)2604 silkPyPmapIter_dealloc(
2605 silkPyPmapIter *self)
2606 {
2607 Py_XDECREF(self->map);
2608 Py_TYPE(self)->tp_free((PyObject*)self);
2609 }
2610
2611 static PyObject *
silkPyPmapIter_iternext(silkPyPmapIter * self)2612 silkPyPmapIter_iternext(
2613 silkPyPmapIter *self)
2614 {
2615 skIteratorStatus_t rv;
2616 PyObject *retval;
2617 PyObject *startval = NULL;
2618 PyObject *endval = NULL;
2619 union {
2620 skipaddr_t addr;
2621 skPrefixMapProtoPort_t pp;
2622 } start, end;
2623 uint32_t value;
2624 skPrefixMapContent_t content;
2625
2626 rv = skPrefixMapIteratorNext(&self->iter, &start, &end, &value);
2627 if (rv == SK_ITERATOR_NO_MORE_ENTRIES) {
2628 PyErr_SetNone(PyExc_StopIteration);
2629 return NULL;
2630 }
2631
2632 content = skPrefixMapGetContentType(self->map->map);
2633 switch (content) {
2634 case SKPREFIXMAP_CONT_ADDR_V4:
2635 case SKPREFIXMAP_CONT_ADDR_V6:
2636 {
2637 PyTypeObject *type =
2638 (content == SKPREFIXMAP_CONT_ADDR_V4) ?
2639 &silkPyIPv4AddrType : &silkPyIPv6AddrType;
2640
2641 startval = type->tp_alloc(type, 0);
2642 if (startval == NULL) {
2643 return NULL;
2644 }
2645 endval = type->tp_alloc(type, 0);
2646 if (endval == NULL) {
2647 Py_DECREF(startval);
2648 return NULL;
2649 }
2650 skipaddrCopy(&((silkPyIPAddr*)startval)->addr, &start.addr);
2651 skipaddrCopy(&((silkPyIPAddr*)endval)->addr, &end.addr);
2652 }
2653 break;
2654 case SKPREFIXMAP_CONT_PROTO_PORT:
2655 {
2656 startval = Py_BuildValue("BH", start.pp.proto, start.pp.port);
2657 if (startval == NULL) {
2658 return NULL;
2659 }
2660 endval = Py_BuildValue("BH", end.pp.proto, end.pp.port);
2661 if (endval == NULL) {
2662 Py_DECREF(startval);
2663 return NULL;
2664 }
2665 }
2666 break;
2667 }
2668 assert(startval && endval);
2669
2670 retval = Py_BuildValue("NNk", startval, endval, value);
2671 if (retval == NULL) {
2672 Py_DECREF(startval);
2673 Py_DECREF(endval);
2674 }
2675
2676 return retval;
2677 }
2678
2679 static void
silkPyPmap_dealloc(silkPyPmap * obj)2680 silkPyPmap_dealloc(
2681 silkPyPmap *obj)
2682 {
2683 if (obj->map) {
2684 skPrefixMapDelete(obj->map);
2685 }
2686 Py_TYPE(obj)->tp_free((PyObject*)obj);
2687 }
2688
2689 static PyObject *
silkPyPmap_get_content(silkPyPmap * self,void UNUSED (* cbdata))2690 silkPyPmap_get_content(
2691 silkPyPmap *self,
2692 void UNUSED(*cbdata))
2693 {
2694 return PyUnicode_FromString(skPrefixMapGetContentName(
2695 skPrefixMapGetContentType(self->map)));
2696 }
2697
2698 static PyObject *
silkPyPmap_get_name(silkPyPmap * self,void UNUSED (* cbdata))2699 silkPyPmap_get_name(
2700 silkPyPmap *self,
2701 void UNUSED(*cbdata))
2702 {
2703 const char *name = skPrefixMapGetMapName(self->map);
2704 if (name == NULL) {
2705 Py_RETURN_NONE;
2706 }
2707
2708 return PyUnicode_FromString(name);
2709 }
2710
2711 static PyObject *
silkPyPmap_get_num_values(silkPyPmap * self,void UNUSED (* cbdata))2712 silkPyPmap_get_num_values(
2713 silkPyPmap *self,
2714 void UNUSED(*cbdata))
2715 {
2716 return PyInt_FromLong(skPrefixMapDictionaryGetWordCount(self->map));
2717 }
2718
2719 static PyObject *
silkPyPmap_get_value_string(silkPyPmap * self,PyObject * value)2720 silkPyPmap_get_value_string(
2721 silkPyPmap *self,
2722 PyObject *value)
2723 {
2724 uint32_t val;
2725 uint32_t size;
2726 char *buf;
2727 int rv;
2728 PyObject *retval;
2729
2730 if (!IS_INT(value)) {
2731 PyErr_SetString(PyExc_TypeError, "Expected an integer");
2732 return NULL;
2733 }
2734
2735 val = PyLong_AsUnsignedLong(value);
2736 if (PyErr_Occurred()) {
2737 return NULL;
2738 }
2739
2740 size = skPrefixMapDictionaryGetMaxWordSize(self->map) + 1;
2741 buf = (char*)malloc(size);
2742 if (buf == NULL) {
2743 return PyErr_NoMemory();
2744 }
2745
2746 rv = skPrefixMapDictionaryGetEntry(self->map, val, buf, size);
2747 assert(rv < (int32_t)size);
2748
2749 retval = PyUnicode_DecodeASCII(buf, rv, "strict");
2750 free(buf);
2751
2752 return retval;
2753 }
2754
2755 static int
silkPyPmap_init(silkPyPmap * self,PyObject * args,PyObject * kwds)2756 silkPyPmap_init(
2757 silkPyPmap *self,
2758 PyObject *args,
2759 PyObject *kwds)
2760 {
2761 static char *kwlist[] = {"filename", NULL};
2762 char errbuf[2 * PATH_MAX];
2763 skstream_t *stream = NULL;
2764 char *fname;
2765 int rv;
2766
2767 if (!PyArg_ParseTupleAndKeywords(args, kwds, "et", kwlist,
2768 Py_FileSystemDefaultEncoding, &fname))
2769 {
2770 return -1;
2771 }
2772
2773 if ((rv = skStreamCreate(&stream, SK_IO_READ, SK_CONTENT_SILK))
2774 || (rv = skStreamBind(stream, fname))
2775 || (rv = skStreamOpen(stream)))
2776 {
2777 skStreamLastErrMessage(stream, rv, errbuf, sizeof(errbuf));
2778 PyErr_Format(PyExc_IOError, "Unable to read prefix map from %s: %s",
2779 fname, errbuf);
2780 skStreamDestroy(&stream);
2781 PyMem_Free(fname);
2782 return -1;
2783 }
2784 rv = (int)skPrefixMapRead(&self->map, stream);
2785 if (rv) {
2786 if (SKPREFIXMAP_ERR_IO == rv) {
2787 skStreamLastErrMessage(stream,
2788 skStreamGetLastReturnValue(stream),
2789 errbuf, sizeof(errbuf));
2790 } else {
2791 strncpy(errbuf, skPrefixMapStrerror(rv), sizeof(errbuf));
2792 }
2793 PyErr_Format(PyExc_IOError, "Unable to read prefix map from %s: %s",
2794 fname, errbuf);
2795 skStreamDestroy(&stream);
2796 PyMem_Free(fname);
2797 return -1;
2798 }
2799 skStreamDestroy(&stream);
2800 PyMem_Free(fname);
2801
2802 return 0;
2803 }
2804
2805 static PyObject *
silkPyPmap_iter(silkPyPmap * self)2806 silkPyPmap_iter(
2807 silkPyPmap *self)
2808 {
2809 int rv;
2810 silkPyPmapIter *iter;
2811
2812 iter = (silkPyPmapIter*)silkPyPmapIterType.tp_alloc(
2813 &silkPyPmapIterType, 0);
2814 if (iter) {
2815 rv = skPrefixMapIteratorBind(&iter->iter, self->map);
2816 if (rv != 0) {
2817 Py_DECREF(iter);
2818 PyErr_SetString(PyExc_RuntimeError,
2819 "Failed to create prefix map iterator");
2820 return NULL;
2821 }
2822 Py_INCREF(self);
2823 iter->map = self;
2824 }
2825 return (PyObject*)iter;
2826 }
2827
2828 static PyObject *
silkPyPmap_subscript(silkPyPmap * self,PyObject * sub)2829 silkPyPmap_subscript(
2830 silkPyPmap *self,
2831 PyObject *sub)
2832 {
2833 void *key = NULL;
2834 uint32_t value;
2835 skPrefixMapProtoPort_t protoport;
2836 skPrefixMapContent_t content;
2837 PyObject *tuple;
2838 int32_t i32;
2839 int rv;
2840
2841 content = skPrefixMapGetContentType(self->map);
2842
2843 switch (content) {
2844 case SKPREFIXMAP_CONT_ADDR_V4:
2845 case SKPREFIXMAP_CONT_ADDR_V6:
2846 if (!silkPyIPAddr_Check(sub)) {
2847 PyErr_SetString(PyExc_TypeError, "Expected an IPAddr");
2848 return NULL;
2849 }
2850 key = &((silkPyIPAddr*)sub)->addr;
2851 break;
2852 case SKPREFIXMAP_CONT_PROTO_PORT:
2853 if (!PySequence_Check(sub) || PySequence_Size(sub) != 2) {
2854 PyErr_SetString(PyExc_TypeError, "Expected a (proto, port) pair");
2855 return NULL;
2856 }
2857 tuple = PySequence_Tuple(sub);
2858 if (tuple == NULL) {
2859 return NULL;
2860 }
2861 rv = PyArg_ParseTuple(tuple, "bi;Expected a (proto, port) pair",
2862 &protoport.proto, &i32);
2863 Py_DECREF(tuple);
2864 if (!rv) {
2865 return NULL;
2866 }
2867 if (i32 < 0 || i32 > 0xFFFF) {
2868 PyErr_SetString(PyExc_ValueError, "Port is out of bounds");
2869 return NULL;
2870 }
2871 protoport.port = i32;
2872 key = &protoport;
2873 break;
2874 }
2875
2876 value = skPrefixMapFindValue(self->map, key);
2877
2878 return PyLong_FromUnsignedLong(value);
2879 }
2880
2881
2882 /*
2883 *************************************************************************
2884 * Bag
2885 *************************************************************************
2886 */
2887
2888 typedef struct silkPyBag_st {
2889 PyObject_HEAD
2890 skBag_t *bag;
2891 unsigned is_ipaddr : 1;
2892 } silkPyBag;
2893
2894 typedef struct silkPyBagIter_st {
2895 PyObject_HEAD
2896 silkPyBag *bag;
2897 skBagIterator_t *iter;
2898 unsigned ipaddr : 1;
2899 } silkPyBagIter;
2900
2901 /* function prototypes */
2902 static void
2903 silkPyBagIter_dealloc(
2904 silkPyBagIter *self);
2905 static PyObject *
2906 silkPyBagIter_iternext(
2907 silkPyBagIter *self);
2908 static PyObject *
2909 silkPyBag__get_custom_type(
2910 PyObject UNUSED(*self));
2911 static PyObject *
2912 silkPyBag__get_ipv4_type(
2913 PyObject UNUSED(*self));
2914 static PyObject *
2915 silkPyBag__get_ipv6_type(
2916 PyObject UNUSED(*self));
2917 static int
2918 silkPyBag_ass_subscript(
2919 silkPyBag *self,
2920 PyObject *sub,
2921 PyObject *value);
2922 static PyObject *
2923 silkPyBag_clear(
2924 silkPyBag *self);
2925 static Py_ssize_t
2926 silkPyBag_count(
2927 silkPyBag *self);
2928 static void
2929 silkPyBag_dealloc(
2930 silkPyBag *obj);
2931 static PyObject *
2932 silkPyBag_decr(
2933 silkPyBag *self,
2934 PyObject *args,
2935 PyObject *kwds);
2936 static PyObject *
2937 silkPyBag_field_types(
2938 PyObject UNUSED(*self));
2939 static PyObject *
2940 silkPyBag_get_info(
2941 silkPyBag *self);
2942 static PyObject *
2943 silkPyBag_iadd(
2944 silkPyBag *self,
2945 silkPyBag *other);
2946 #if 0
2947 static skBagErr_t
2948 silkPyBag_iadd_bounds(
2949 const skBagTypedKey_t UNUSED(*key),
2950 skBagTypedCounter_t *in_out_counter,
2951 const skBagTypedCounter_t UNUSED(*in_counter),
2952 void UNUSED(*cb_data));
2953 #endif
2954 static PyObject *
2955 silkPyBag_incr(
2956 silkPyBag *self,
2957 PyObject *args,
2958 PyObject *kwds);
2959 static int
2960 silkPyBag_init(
2961 silkPyBag *self,
2962 PyObject *args,
2963 PyObject *kwds);
2964 static PyObject *
2965 silkPyBag_iter(
2966 silkPyBag *self);
2967 static PyObject *
2968 silkPyBag_iter_helper(
2969 silkPyBag *self,
2970 int sorted);
2971 static int
2972 silkPyBag_modify(
2973 silkPyBag *self,
2974 PyObject *sub,
2975 PyObject *value,
2976 silkBagModFn fn);
2977 static PyObject *
2978 silkPyBag_save(
2979 silkPyBag *self,
2980 PyObject *args,
2981 PyObject *kwds);
2982 static PyObject *
2983 silkPyBag_set_info(
2984 silkPyBag *self,
2985 PyObject *args,
2986 PyObject *kwds);
2987 static int
2988 silkPyBag_setup(
2989 PyObject *mod);
2990 static PyObject *
2991 silkPyBag_sorted_iter(
2992 silkPyBag *self);
2993 static PyObject *
2994 silkPyBag_subscript(
2995 silkPyBag *self,
2996 PyObject *sub);
2997 static PyObject *
2998 silkPyBag_type_merge(
2999 PyObject UNUSED(*self),
3000 PyObject *args);
3001
3002 /* define docs and methods */
3003 #define silkPyBag_doc \
3004 "BagBase(filename) -> Bag from file"
3005
3006 static PyNumberMethods silkPyBag_number_methods;
3007
3008 static PyMappingMethods silkPyBag_mapping_methods = {
3009 #if PY_VERSION_HEX < 0x02050000
3010 (inquiry)silkPyBag_count, /* mp_length */
3011 #else
3012 (lenfunc)silkPyBag_count, /* mp_length */
3013 #endif
3014 (binaryfunc)silkPyBag_subscript, /* mp_subscript */
3015 (objobjargproc)silkPyBag_ass_subscript /* mp_ass_subscript */
3016 };
3017
3018 static PyMethodDef silkPyBag_methods[] = {
3019 {"__reduce__", (PyCFunction)reduce_error, METH_NOARGS, ""},
3020 {"incr", (PyCFunction)silkPyBag_incr, METH_KEYWORDS | METH_VARARGS,
3021 ("bag.incr(key, value) -- increments bag[key] by value")},
3022 {"decr", (PyCFunction)silkPyBag_decr, METH_KEYWORDS | METH_VARARGS,
3023 ("bag.decr(key, value) -- decrements bag[key] by value")},
3024 {"save", (PyCFunction)silkPyBag_save, METH_KEYWORDS | METH_VARARGS,
3025 "bag.save(filename[, compression]) -- saves the bag to a file"},
3026 {"clear", (PyCFunction)silkPyBag_clear, METH_NOARGS,
3027 "bag.clear() -- empties the bag"},
3028 {"sorted_iter", (PyCFunction)silkPyBag_sorted_iter, METH_NOARGS,
3029 ("bag.sorted_iter() -- returns an iterator whose values are "
3030 "sorted by key")},
3031 {"get_info", (PyCFunction)silkPyBag_get_info, METH_NOARGS,
3032 "get_info() -- returns (key_type, key_len, counter_type, counter_len)"},
3033 {"set_info", (PyCFunction)silkPyBag_set_info,
3034 METH_KEYWORDS | METH_VARARGS,
3035 ("set_info([key_type][, key_len][, counter_type][, counter_len]) --\n\t"
3036 "returns the result of bag.get_info()")},
3037 {"field_types", (PyCFunction)silkPyBag_field_types,
3038 METH_NOARGS | METH_STATIC,
3039 "field_types() -> Tuple of valid field types for Bag keys and counters"},
3040 {"type_merge", (PyCFunction)silkPyBag_type_merge,
3041 METH_VARARGS | METH_STATIC,
3042 "type_merge(keytype_a, keytype_b) -> key_type of merged output"},
3043 {"_get_custom_type", (PyCFunction)silkPyBag__get_custom_type,
3044 METH_NOARGS | METH_STATIC, NULL},
3045 {"_get_ipv4_type", (PyCFunction)silkPyBag__get_ipv4_type,
3046 METH_NOARGS | METH_STATIC, NULL},
3047 {"_get_ipv6_type", (PyCFunction)silkPyBag__get_ipv6_type,
3048 METH_NOARGS | METH_STATIC, NULL},
3049 {NULL, NULL, 0, NULL} /* Sentinel */
3050 };
3051
3052
3053 /* define the object types */
3054 static PyTypeObject silkPyBagType = {
3055 PyVarObject_HEAD_INIT(NULL, 0)
3056 "silk.pysilk.BagBase", /* tp_name */
3057 sizeof(silkPyBag), /* tp_basicsize */
3058 0, /* tp_itemsize */
3059 (destructor)silkPyBag_dealloc, /* tp_dealloc */
3060 0, /* tp_vectorcall_offset (Py 3.8) */
3061 0, /* tp_getattr */
3062 0, /* tp_setattr */
3063 0, /* tp_as_async (tp_compare in Py2.x) */
3064 0, /* tp_repr */
3065 &silkPyBag_number_methods, /* tp_as_number */
3066 0, /* tp_as_sequence */
3067 &silkPyBag_mapping_methods, /* tp_as_mapping */
3068 0, /* tp_hash */
3069 0, /* tp_call */
3070 0, /* tp_str */
3071 0, /* tp_getattro */
3072 0, /* tp_setattro */
3073 0, /* tp_as_buffer */
3074 #if PY_MAJOR_VERSION < 3
3075 Py_TPFLAGS_CHECKTYPES |
3076 #endif
3077 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
3078 silkPyBag_doc, /* tp_doc */
3079 0, /* tp_traverse */
3080 0, /* tp_clear */
3081 0, /* tp_richcompare */
3082 0, /* tp_weaklistoffset */
3083 (getiterfunc)silkPyBag_iter, /* tp_iter */
3084 0, /* tp_iternext */
3085 silkPyBag_methods, /* tp_methods */
3086 0, /* tp_members */
3087 0, /* tp_getset */
3088 0, /* tp_base */
3089 0, /* tp_dict */
3090 0, /* tp_descr_get */
3091 0, /* tp_descr_set */
3092 0, /* tp_dictoffset */
3093 (initproc)silkPyBag_init, /* tp_init */
3094 0, /* tp_alloc */
3095 0, /* tp_new */
3096 0, /* tp_free */
3097 0, /* tp_is_gc */
3098 0, /* tp_bases */
3099 0, /* tp_mro */
3100 0, /* tp_cache */
3101 0, /* tp_subclasses */
3102 0, /* tp_weaklist */
3103 0 /* tp_del */
3104 #if PY_VERSION_HEX >= 0x02060000
3105 ,0 /* tp_version_tag */
3106 #endif
3107 #if PY_VERSION_HEX >= 0x03040000
3108 ,0 /* tp_finalize */
3109 #endif
3110 #if PY_VERSION_HEX >= 0x03080000
3111 ,0 /* tp_vectorcall */
3112 ,0 /* tp_print */
3113 #endif
3114 };
3115
3116 static PyTypeObject silkPyBagIterType = {
3117 PyVarObject_HEAD_INIT(NULL, 0)
3118 "silk.pysilk.BagBaseIter", /* tp_name */
3119 sizeof(silkPyBagIterType), /* tp_basicsize */
3120 0, /* tp_itemsize */
3121 (destructor)silkPyBagIter_dealloc, /* tp_dealloc */
3122 0, /* tp_vectorcall_offset (Py 3.8) */
3123 0, /* tp_getattr */
3124 0, /* tp_setattr */
3125 0, /* tp_as_async (tp_compare in Py2.x) */
3126 0, /* tp_repr */
3127 0, /* tp_as_number */
3128 0, /* tp_as_sequence */
3129 0, /* tp_as_mapping */
3130 0, /* tp_hash */
3131 0, /* tp_call */
3132 0, /* tp_str */
3133 0, /* tp_getattro */
3134 0, /* tp_setattro */
3135 0, /* tp_as_buffer */
3136 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
3137 "Bag iterator object", /* tp_doc */
3138 0, /* tp_traverse */
3139 0, /* tp_clear */
3140 0, /* tp_richcompare */
3141 0, /* tp_weaklistoffset */
3142 iter_iter, /* tp_iter */
3143 (iternextfunc)silkPyBagIter_iternext, /* tp_iternext */
3144 0, /* tp_methods */
3145 0, /* tp_members */
3146 0, /* tp_getset */
3147 0, /* tp_base */
3148 0, /* tp_dict */
3149 0, /* tp_descr_get */
3150 0, /* tp_descr_set */
3151 0, /* tp_dictoffset */
3152 0, /* tp_init */
3153 0, /* tp_alloc */
3154 0, /* tp_new */
3155 0, /* tp_free */
3156 0, /* tp_is_gc */
3157 0, /* tp_bases */
3158 0, /* tp_mro */
3159 0, /* tp_cache */
3160 0, /* tp_subclasses */
3161 0, /* tp_weaklist */
3162 0 /* tp_del */
3163 #if PY_VERSION_HEX >= 0x02060000
3164 ,0 /* tp_version_tag */
3165 #endif
3166 #if PY_VERSION_HEX >= 0x03040000
3167 ,0 /* tp_finalize */
3168 #endif
3169 #if PY_VERSION_HEX >= 0x03080000
3170 ,0 /* tp_vectorcall */
3171 ,0 /* tp_print */
3172 #endif
3173 };
3174
3175 /* macro and function defintions */
3176 #define silkPyBag_Check(op) \
3177 PyObject_TypeCheck(op, &silkPyBagType)
3178 #define silkPyBagIter_Check(op) \
3179 PyObject_TypeCheck(op, &silkPyBagIterType)
3180
3181 #define IS_IPV4_KEY(k) \
3182 ((k) == SKBAG_FIELD_SIPv4 \
3183 || (k) == SKBAG_FIELD_DIPv4 \
3184 || (k) == SKBAG_FIELD_NHIPv4 \
3185 || (k) == SKBAG_FIELD_ANY_IPv4)
3186
3187 #define IS_IPV6_KEY(k) \
3188 ((k) == SKBAG_FIELD_SIPv6 \
3189 || (k) == SKBAG_FIELD_DIPv6 \
3190 || (k) == SKBAG_FIELD_NHIPv6 \
3191 || (k) == SKBAG_FIELD_ANY_IPv6)
3192
3193 #define IS_IP_KEY(k) (IS_IPV4_KEY(k) || IS_IPV6_KEY(k))
3194
3195 static void
silkPyBagIter_dealloc(silkPyBagIter * self)3196 silkPyBagIter_dealloc(
3197 silkPyBagIter *self)
3198 {
3199 Py_XDECREF(self->bag);
3200 skBagIteratorDestroy(self->iter);
3201 Py_TYPE(self)->tp_free((PyObject*)self);
3202 }
3203
3204 static PyObject *
silkPyBagIter_iternext(silkPyBagIter * self)3205 silkPyBagIter_iternext(
3206 silkPyBagIter *self)
3207 {
3208 skBagErr_t rv;
3209 PyObject *retkey;
3210 PyObject *retval;
3211 skBagTypedKey_t key;
3212 skBagTypedCounter_t counter;
3213
3214 counter.type = SKBAG_COUNTER_U64;
3215 key.type = self->ipaddr ? SKBAG_KEY_IPADDR : SKBAG_KEY_U32;
3216
3217 rv = skBagIteratorNextTyped(self->iter, &key, &counter);
3218 if (rv == SKBAG_ERR_KEY_NOT_FOUND) {
3219 PyErr_SetNone(PyExc_StopIteration);
3220 return NULL;
3221 }
3222 if (rv == SKBAG_ERR_MODIFIED) {
3223 PyErr_SetString(PyExc_RuntimeError,
3224 "Underlying Bag changed during iteration");
3225 return NULL;
3226 }
3227 if (self->ipaddr) {
3228 PyTypeObject *type = (skipaddrIsV6(&key.val.addr)
3229 ? &silkPyIPv6AddrType : &silkPyIPv4AddrType);
3230 retkey = type->tp_alloc(type, 0);
3231 if (retkey == NULL) {
3232 return NULL;
3233 }
3234 skipaddrCopy(&((silkPyIPAddr*)retkey)->addr, &key.val.addr);
3235 } else {
3236 retkey = PyLong_FromUnsignedLong(key.val.u32);
3237 if (retkey == NULL) {
3238 return NULL;
3239 }
3240 }
3241
3242 retval = Py_BuildValue("OK", retkey, counter.val.u64);
3243 Py_DECREF(retkey);
3244 return retval;
3245 }
3246
3247 static PyObject *
silkPyBag__get_custom_type(PyObject UNUSED (* self))3248 silkPyBag__get_custom_type(
3249 PyObject UNUSED(*self))
3250 {
3251 char buf[SKBAG_MAX_FIELD_BUFLEN];
3252
3253 skBagFieldTypeAsString(SKBAG_FIELD_CUSTOM, buf, sizeof(buf));
3254 return PyUnicode_FromString(buf);
3255 }
3256
3257 static PyObject *
silkPyBag__get_ipv4_type(PyObject UNUSED (* self))3258 silkPyBag__get_ipv4_type(
3259 PyObject UNUSED(*self))
3260 {
3261 char buf[SKBAG_MAX_FIELD_BUFLEN];
3262
3263 skBagFieldTypeAsString(SKBAG_FIELD_ANY_IPv4, buf, sizeof(buf));
3264 return PyUnicode_FromString(buf);
3265 }
3266
3267 static PyObject *
silkPyBag__get_ipv6_type(PyObject UNUSED (* self))3268 silkPyBag__get_ipv6_type(
3269 PyObject UNUSED(*self))
3270 {
3271 char buf[SKBAG_MAX_FIELD_BUFLEN];
3272
3273 skBagFieldTypeAsString(SKBAG_FIELD_ANY_IPv6, buf, sizeof(buf));
3274 return PyUnicode_FromString(buf);
3275 }
3276
3277 static int
silkPyBag_ass_subscript(silkPyBag * self,PyObject * sub,PyObject * value)3278 silkPyBag_ass_subscript(
3279 silkPyBag *self,
3280 PyObject *sub,
3281 PyObject *value)
3282 {
3283 /* skBagCounterSet will ignore the extra NULL passed to it */
3284 return silkPyBag_modify(self, sub, value, (silkBagModFn)skBagCounterSet);
3285 }
3286
3287 static PyObject *
silkPyBag_clear(silkPyBag * self)3288 silkPyBag_clear(
3289 silkPyBag *self)
3290 {
3291 skBagErr_t rv;
3292 skBagFieldType_t key, value;
3293 size_t keylen, valuelen;
3294 skBag_t *bag;
3295
3296 key = skBagKeyFieldType(self->bag);
3297 keylen = skBagKeyFieldLength(self->bag);
3298 value = skBagCounterFieldType(self->bag);
3299 valuelen = skBagCounterFieldLength(self->bag);
3300
3301 rv = skBagCreateTyped(&bag, key, value, keylen, valuelen);
3302 if (rv == SKBAG_ERR_MEMORY) {
3303 return PyErr_NoMemory();
3304 }
3305 assert(rv == SKBAG_OK);
3306 skBagAutoConvertDisable(bag);
3307
3308 skBagDestroy(&self->bag);
3309 self->bag = bag;
3310
3311 Py_RETURN_NONE;
3312 }
3313
3314 static Py_ssize_t
silkPyBag_count(silkPyBag * self)3315 silkPyBag_count(
3316 silkPyBag *self)
3317 {
3318 uint64_t count = skBagCountKeys(self->bag);
3319 return (Py_ssize_t)count;
3320 }
3321
3322 static void
silkPyBag_dealloc(silkPyBag * obj)3323 silkPyBag_dealloc(
3324 silkPyBag *obj)
3325 {
3326 if (obj->bag) {
3327 skBagDestroy(&obj->bag);
3328 }
3329 Py_TYPE(obj)->tp_free((PyObject*)obj);
3330 }
3331
3332 static PyObject *
silkPyBag_decr(silkPyBag * self,PyObject * args,PyObject * kwds)3333 silkPyBag_decr(
3334 silkPyBag *self,
3335 PyObject *args,
3336 PyObject *kwds)
3337 {
3338 static char *kwlist[] = {"key", "value", NULL};
3339 PyObject *sub;
3340 PyObject *value;
3341
3342 if (!PyArg_ParseTupleAndKeywords(args, kwds, "OO", kwlist, &sub, &value)) {
3343 return NULL;
3344 }
3345
3346 if (silkPyBag_modify(self, sub, value, skBagCounterSubtract)) {
3347 return NULL;
3348 }
3349
3350 Py_RETURN_NONE;
3351 }
3352
3353 static PyObject *
silkPyBag_field_types(PyObject UNUSED (* self))3354 silkPyBag_field_types(
3355 PyObject UNUSED(*self))
3356 {
3357 char buf[SKBAG_MAX_FIELD_BUFLEN];
3358 skBagFieldTypeIterator_t iter;
3359 Py_ssize_t count;
3360 PyObject *retval;
3361
3362 /* First, count thee types */
3363 skBagFieldTypeIteratorBind(&iter);
3364 count = 0;
3365 while (skBagFieldTypeIteratorNext(&iter, NULL, NULL, NULL, 0) == SKBAG_OK)
3366 {
3367 count++;
3368 }
3369
3370 /* Create the tuple */
3371 retval = PyTuple_New(count);
3372 if (retval == NULL) {
3373 return NULL;
3374 }
3375
3376 /* Then fill in the tuple */
3377 skBagFieldTypeIteratorReset(&iter);
3378 count = 0;
3379 while (skBagFieldTypeIteratorNext(&iter, NULL, NULL, buf, sizeof(buf))
3380 == SKBAG_OK)
3381 {
3382 PyObject *name = PyUnicode_InternFromString(buf);
3383 if (name == NULL) {
3384 Py_DECREF(retval);
3385 return NULL;
3386 }
3387 PyTuple_SET_ITEM(retval, count, name);
3388 count++;
3389 }
3390
3391 return retval;
3392 }
3393
3394 static PyObject *
silkPyBag_get_info(silkPyBag * self)3395 silkPyBag_get_info(
3396 silkPyBag *self)
3397 {
3398 char buf[80];
3399 unsigned int key_len;
3400 unsigned int counter_len;
3401 PyObject *key_name;
3402 PyObject *counter_name;
3403
3404 skBagKeyFieldName(self->bag, buf, sizeof(buf));
3405 key_len = skBagKeyFieldLength(self->bag);
3406 key_name = PyUnicode_FromString(buf);
3407 if (key_name == NULL) {
3408 return NULL;
3409 }
3410 skBagCounterFieldName(self->bag, buf, sizeof(buf));
3411 counter_len = skBagCounterFieldLength(self->bag);
3412 counter_name = PyUnicode_FromString(buf);
3413 if (counter_name == NULL) {
3414 Py_DECREF(key_name);
3415 return NULL;
3416 }
3417 return Py_BuildValue("{sN sI sN sI}",
3418 "key_type", key_name, "key_len", key_len,
3419 "counter_type", counter_name,
3420 "counter_len", counter_len);
3421 }
3422
3423 static PyObject *
silkPyBag_iadd(silkPyBag * self,silkPyBag * other)3424 silkPyBag_iadd(
3425 silkPyBag *self,
3426 silkPyBag *other)
3427 {
3428 skBagErr_t rv;
3429
3430 if (!silkPyBag_Check(self) || !silkPyBag_Check(other)) {
3431 Py_INCREF(Py_NotImplemented);
3432 return Py_NotImplemented;
3433 }
3434
3435 rv = skBagAddBag(self->bag, other->bag, NULL, NULL);
3436 switch (rv) {
3437 case SKBAG_OK:
3438 break;
3439 case SKBAG_ERR_MEMORY:
3440 PyErr_NoMemory();
3441 return NULL;
3442 case SKBAG_ERR_OP_BOUNDS:
3443 PyErr_SetString(PyExc_ValueError, skBagStrerror(rv));
3444 return NULL;
3445 case SKBAG_ERR_KEY_RANGE:
3446 PyErr_SetString(PyExc_ValueError, skBagStrerror(rv));
3447 return NULL;
3448 case SKBAG_ERR_INPUT:
3449 case SKBAG_ERR_KEY_NOT_FOUND:
3450 /* Fall through */
3451 default:
3452 skAbortBadCase(rv);
3453 }
3454 self->is_ipaddr = (skBagKeyFieldLength(self->bag) == 16
3455 || IS_IP_KEY(skBagKeyFieldType(self->bag)));
3456
3457 Py_INCREF(self);
3458 return (PyObject*)self;
3459 }
3460
3461 #if 0
3462 /* Clamp bag values for iadd to SKBAG_COUNTER_MAX without errors. */
3463 static skBagErr_t
3464 silkPyBag_iadd_bounds(
3465 const skBagTypedKey_t UNUSED(*key),
3466 skBagTypedCounter_t *in_out_counter,
3467 const skBagTypedCounter_t UNUSED(*in_counter),
3468 void UNUSED(*cb_data))
3469 {
3470 in_out_counter->type = SKBAG_COUNTER_U64;
3471 in_out_counter->val.u64 = SKBAG_COUNTER_MAX;
3472 return SKBAG_OK;
3473 }
3474 #endif
3475
3476 static PyObject *
silkPyBag_incr(silkPyBag * self,PyObject * args,PyObject * kwds)3477 silkPyBag_incr(
3478 silkPyBag *self,
3479 PyObject *args,
3480 PyObject *kwds)
3481 {
3482 static char *kwlist[] = {"key", "value", NULL};
3483 PyObject *sub;
3484 PyObject *value;
3485
3486 if (!PyArg_ParseTupleAndKeywords(args, kwds, "OO", kwlist, &sub, &value)) {
3487 return NULL;
3488 }
3489
3490 if (silkPyBag_modify(self, sub, value, skBagCounterAdd)) {
3491 return NULL;
3492 }
3493
3494 Py_RETURN_NONE;
3495 }
3496
3497 static int
silkPyBag_init(silkPyBag * self,PyObject * args,PyObject * kwds)3498 silkPyBag_init(
3499 silkPyBag *self,
3500 PyObject *args,
3501 PyObject *kwds)
3502 {
3503 static char *kwlist[] = {"copy", "filename", "key_type", "counter_type",
3504 "key_len", "counter_len", NULL};
3505 char errbuf[2 * PATH_MAX];
3506 skstream_t *stream = NULL;
3507 char *fname = NULL;
3508 silkPyBag *copy = NULL;
3509 char *key = NULL;
3510 char *counter = NULL;
3511 unsigned int key_size = 0;
3512 unsigned int counter_size = 0;
3513 skBagErr_t bagerr;
3514 int rv;
3515
3516 if (!PyArg_ParseTupleAndKeywords(
3517 args, kwds, "|O!etssII", kwlist, &silkPyBagType,
3518 (PyObject*)©, Py_FileSystemDefaultEncoding, &fname,
3519 &key, &counter, &key_size, &counter_size))
3520 {
3521 return -1;
3522 }
3523
3524 if ((copy && fname)
3525 || (copy && (key || counter))
3526 || (fname && (key || counter)))
3527 {
3528 PyErr_SetString(PyExc_ValueError, "Illegal argument combination");
3529 return -1;
3530 }
3531
3532 if (fname) {
3533 if ((rv = skStreamCreate(&stream, SK_IO_READ, SK_CONTENT_SILK))
3534 || (rv = skStreamBind(stream, fname))
3535 || (rv = skStreamOpen(stream)))
3536 {
3537 skStreamLastErrMessage(stream, rv, errbuf, sizeof(errbuf));
3538 PyErr_Format(PyExc_IOError, "Unable to read Bag from %s: %s",
3539 fname, errbuf);
3540 skStreamDestroy(&stream);
3541 PyMem_Free(fname);
3542 return -1;
3543 }
3544 bagerr = skBagRead(&self->bag, stream);
3545 if (bagerr) {
3546 if (SKBAG_ERR_READ == bagerr) {
3547 skStreamLastErrMessage(stream,
3548 skStreamGetLastReturnValue(stream),
3549 errbuf, sizeof(errbuf));
3550 } else {
3551 strncpy(errbuf, skBagStrerror(bagerr), sizeof(errbuf));
3552 }
3553 PyErr_Format(PyExc_IOError, "Unable to read Bag from %s: %s",
3554 fname, errbuf);
3555 skStreamDestroy(&stream);
3556 PyMem_Free(fname);
3557 return -1;
3558 }
3559 skStreamDestroy(&stream);
3560 PyMem_Free(fname);
3561 self->is_ipaddr = skBagKeyFieldLength(self->bag) == 16
3562 || IS_IP_KEY(skBagKeyFieldType(self->bag));
3563 } else if (copy) {
3564 bagerr = skBagCopy(&self->bag, copy->bag);
3565 self->is_ipaddr = copy->is_ipaddr;
3566 } else {
3567 skBagFieldType_t key_type, counter_type;
3568 if (!key) {
3569 key_type = SKBAG_FIELD_CUSTOM;
3570 } else {
3571 bagerr = skBagFieldTypeLookup(key, &key_type, NULL);
3572 if (bagerr != SKBAG_OK) {
3573 PyErr_Format(PyExc_ValueError,
3574 "'%s' is not a valid key type", key);
3575 return -1;
3576 }
3577 }
3578 if (key_type == SKBAG_FIELD_CUSTOM && key_size == 0) {
3579 key_size = 4;
3580 }
3581 if (!counter) {
3582 counter_type = SKBAG_FIELD_CUSTOM;
3583 } else {
3584 bagerr = skBagFieldTypeLookup(counter, &counter_type, NULL);
3585 if (bagerr != SKBAG_OK) {
3586 PyErr_Format(PyExc_ValueError,
3587 "'%s' is not a valid counter type", counter);
3588 return -1;
3589 }
3590 }
3591 if (counter_type == SKBAG_FIELD_CUSTOM && counter_size == 0) {
3592 counter_size = 8;
3593 }
3594
3595 bagerr = skBagCreateTyped(&self->bag, key_type, counter_type,
3596 key_size, counter_size);
3597 if (bagerr == SKBAG_ERR_INPUT) {
3598 PyErr_Format(PyExc_ValueError,
3599 "Illegal arguments to Bag constructor");
3600 return -1;
3601 }
3602 skBagAutoConvertDisable(self->bag);
3603 self->is_ipaddr = (counter_size == 16 || IS_IP_KEY(key_type));
3604 }
3605
3606 if (bagerr == SKBAG_ERR_MEMORY) {
3607 PyErr_NoMemory();
3608 return -1;
3609 }
3610 assert(bagerr == SKBAG_OK);
3611
3612 return 0;
3613 }
3614
3615 static PyObject *
silkPyBag_iter(silkPyBag * self)3616 silkPyBag_iter(
3617 silkPyBag *self)
3618 {
3619 return silkPyBag_iter_helper(self, 0);
3620 }
3621
3622 static PyObject *
silkPyBag_iter_helper(silkPyBag * self,int sorted)3623 silkPyBag_iter_helper(
3624 silkPyBag *self,
3625 int sorted)
3626 {
3627 skBagErr_t rv;
3628 silkPyBagIter *iter;
3629
3630 iter = (silkPyBagIter*)silkPyBagIterType.tp_alloc(
3631 &silkPyBagIterType, 0);
3632 if (iter) {
3633 if (sorted) {
3634 rv = skBagIteratorCreate(self->bag, &iter->iter);
3635 } else {
3636 rv = skBagIteratorCreateUnsorted(self->bag, &iter->iter);
3637 }
3638 if (rv == SKBAG_ERR_MEMORY) {
3639 Py_DECREF(iter);
3640 return PyErr_NoMemory();
3641 }
3642 if (rv != SKBAG_OK) {
3643 Py_DECREF(iter);
3644 PyErr_SetString(PyExc_RuntimeError,
3645 "Failed to create bag iterator");
3646 return NULL;
3647 }
3648 Py_INCREF(self);
3649 iter->bag = self;
3650 iter->ipaddr = self->is_ipaddr;
3651 }
3652 return (PyObject*)iter;
3653 }
3654
3655 static int
silkPyBag_modify(silkPyBag * self,PyObject * sub,PyObject * value,silkBagModFn fn)3656 silkPyBag_modify(
3657 silkPyBag *self,
3658 PyObject *sub,
3659 PyObject *value,
3660 silkBagModFn fn)
3661 {
3662 skBagTypedCounter_t bagvalue;
3663 skBagTypedKey_t key;
3664 skBagErr_t rv;
3665
3666 if (!IS_INT(value)) {
3667 PyErr_SetString(PyExc_TypeError, "Expected an integer value");
3668 return -1;
3669 }
3670 bagvalue.val.u64 = LONG_AS_UNSIGNED_LONGLONG(value);
3671 if (PyErr_Occurred()) {
3672 return -1;
3673 }
3674 bagvalue.type = SKBAG_COUNTER_U64;
3675
3676 if (IS_INT(sub)) {
3677 if (self->is_ipaddr) {
3678 PyErr_SetString(PyExc_TypeError, "Expected an IPAddr index");
3679 return -1;
3680 }
3681 /* long long is 64-bits on 32 and 64-bit arches, so use it for
3682 * consistency. */
3683 key.val.u64 = LONG_AS_UNSIGNED_LONGLONG(sub);
3684 if (PyErr_Occurred()) {
3685 if (PyErr_ExceptionMatches(PyExc_OverflowError)) {
3686 PyErr_Clear();
3687 PyErr_SetString(PyExc_IndexError, "Index out of range");
3688 }
3689 return -1;
3690 }
3691 if (key.val.u64 > 0xffffffff) {
3692 PyErr_SetString(PyExc_IndexError, "Index out of range");
3693 return -1;
3694 }
3695 key.val.u32 = key.val.u64;
3696 key.type = SKBAG_KEY_U32;
3697 } else if (silkPyIPAddr_Check(sub)) {
3698 silkPyIPAddr *addr;
3699 if (!self->is_ipaddr) {
3700 PyErr_SetString(PyExc_TypeError, "Expected an integer index");
3701 return -1;
3702 }
3703 addr = (silkPyIPAddr*)sub;
3704 skipaddrCopy(&key.val.addr, &addr->addr);
3705 key.type = SKBAG_KEY_IPADDR;
3706 } else {
3707 PyErr_SetString(PyExc_TypeError, "Expected an integer or IP address");
3708 return -1;
3709 }
3710
3711 rv = fn(self->bag, &key, &bagvalue, NULL);
3712 switch (rv) {
3713 case SKBAG_OK:
3714 break;
3715 case SKBAG_ERR_INPUT:
3716 case SKBAG_ERR_KEY_RANGE:
3717 PyErr_SetString(PyExc_IndexError, "Address out of range");
3718 return -1;
3719 case SKBAG_ERR_MEMORY:
3720 PyErr_NoMemory();
3721 return -1;
3722 case SKBAG_ERR_OP_BOUNDS:
3723 PyErr_SetString(PyExc_ValueError, skBagStrerror(rv));
3724 return -1;
3725 case SKBAG_ERR_KEY_NOT_FOUND:
3726 /* Fall through */
3727 default:
3728 skAbortBadCase(rv);
3729 }
3730
3731 return 0;
3732 }
3733
3734 static PyObject *
silkPyBag_save(silkPyBag * self,PyObject * args,PyObject * kwds)3735 silkPyBag_save(
3736 silkPyBag *self,
3737 PyObject *args,
3738 PyObject *kwds)
3739 {
3740 skBagErr_t rv;
3741 skstream_t *stream;
3742
3743 if ((stream = open_silkfile_write(args, kwds)) == NULL) {
3744 return NULL;
3745 }
3746
3747 rv = skBagWrite(self->bag, stream);
3748 skStreamDestroy(&stream);
3749 if (rv != SKBAG_OK) {
3750 PyErr_SetString(PyExc_IOError, skBagStrerror(rv));
3751 return NULL;
3752 }
3753
3754 Py_RETURN_NONE;
3755 }
3756
3757 static PyObject *
silkPyBag_set_info(silkPyBag * self,PyObject * args,PyObject * kwds)3758 silkPyBag_set_info(
3759 silkPyBag *self,
3760 PyObject *args,
3761 PyObject *kwds)
3762 {
3763 static char *kwlist[] = {"key_type", "key_len",
3764 "counter_type", "counter_len", NULL};
3765 size_t key_len = SKBAG_OCTETS_NO_CHANGE;
3766 size_t counter_len = SKBAG_OCTETS_NO_CHANGE;
3767 unsigned int key_len_tmp = UINT_MAX;
3768 unsigned int counter_len_tmp = UINT_MAX;
3769 char *key_name = NULL;
3770 char *counter_name = NULL;
3771 skBagFieldType_t key_type;
3772 skBagFieldType_t counter_type;
3773 skBagErr_t err;
3774
3775 if (!PyArg_ParseTupleAndKeywords(args, kwds, "|sIsI", kwlist,
3776 &key_name, &key_len_tmp,
3777 &counter_name, &counter_len_tmp))
3778 {
3779 return NULL;
3780 }
3781
3782 /* key_len_tmp and counter_len_tmp are unsigned ints, since there
3783 * were no conversion functions to size_t until Python 2.6 */
3784 if (key_len_tmp != UINT_MAX) {
3785 key_len = key_len_tmp;
3786 }
3787 if (counter_len_tmp != UINT_MAX) {
3788 counter_len = counter_len_tmp;
3789 }
3790 if (key_name) {
3791 err = skBagFieldTypeLookup(key_name, &key_type, NULL);
3792 if (err != SKBAG_OK) {
3793 assert(err == SKBAG_ERR_INPUT);
3794 return PyErr_Format(PyExc_ValueError,
3795 "'%s' is not a valid key type", key_name);
3796 }
3797 } else {
3798 key_type = skBagKeyFieldType(self->bag);
3799 }
3800
3801 if (counter_name) {
3802 err = skBagFieldTypeLookup(counter_name, &counter_type, NULL);
3803 if (err != SKBAG_OK) {
3804 assert(err == SKBAG_ERR_INPUT);
3805 return PyErr_Format(PyExc_ValueError,
3806 "'%s' is not a valid counter type",
3807 counter_name);
3808 }
3809 } else {
3810 counter_type = skBagCounterFieldType(self->bag);
3811 }
3812
3813 err = skBagModify(self->bag, key_type, counter_type,
3814 key_len, counter_len);
3815 if (err != SKBAG_OK) {
3816 PyErr_SetString(PyExc_ValueError,
3817 "Illegal value was passed to Bag.set_info");
3818 return NULL;
3819 }
3820
3821 self->is_ipaddr = (counter_len == 16 || IS_IP_KEY(key_type));
3822
3823 return silkPyBag_get_info(self);
3824 }
3825
3826 static int
silkPyBag_setup(PyObject * mod)3827 silkPyBag_setup(
3828 PyObject *mod)
3829 {
3830 /* Setup number methods */
3831 memset(&silkPyBag_number_methods, 0, sizeof(silkPyBag_number_methods));
3832 silkPyBag_number_methods.nb_inplace_add = (binaryfunc)silkPyBag_iadd;
3833
3834 /* Initialize type and add to module */
3835 silkPyBagType.tp_new = PyType_GenericNew;
3836 if (PyType_Ready(&silkPyBagType) < 0) {
3837 return -1;
3838 }
3839 return PyModule_AddObject(mod, "BagBase", (PyObject*)&silkPyBagType);
3840 }
3841
3842 static PyObject *
silkPyBag_sorted_iter(silkPyBag * self)3843 silkPyBag_sorted_iter(
3844 silkPyBag *self)
3845 {
3846 return silkPyBag_iter_helper(self, 1);
3847 }
3848
3849 static PyObject *
silkPyBag_subscript(silkPyBag * self,PyObject * sub)3850 silkPyBag_subscript(
3851 silkPyBag *self,
3852 PyObject *sub)
3853 {
3854 skBagTypedKey_t key;
3855 skBagTypedCounter_t value;
3856 skBagErr_t rv;
3857
3858 if (IS_INT(sub)) {
3859 if (self->is_ipaddr) {
3860 PyErr_SetString(PyExc_TypeError, "Expected an IPAddr index");
3861 return NULL;
3862 }
3863 /* long long is 64-bits on 32 and 64-bit arches, so use it for
3864 * consistency. */
3865 key.val.u64 = LONG_AS_UNSIGNED_LONGLONG(sub);
3866 if (PyErr_Occurred()) {
3867 if (PyErr_ExceptionMatches(PyExc_OverflowError)) {
3868 PyErr_Clear();
3869 PyErr_SetString(PyExc_IndexError, "Index out of range");
3870 }
3871 return NULL;
3872 }
3873 if (key.val.u64 > 0xffffffff) {
3874 PyErr_SetString(PyExc_IndexError, "Index out of range");
3875 return NULL;
3876 }
3877 key.val.u32 = key.val.u64;
3878 key.type = SKBAG_KEY_U32;
3879 } else if (silkPyIPAddr_Check(sub)) {
3880 silkPyIPAddr *addr;
3881 if (!self->is_ipaddr) {
3882 PyErr_SetString(PyExc_TypeError, "Expected an integer index");
3883 return NULL;
3884 }
3885 addr = (silkPyIPAddr*)sub;
3886 skipaddrCopy(&key.val.addr, &addr->addr);
3887 key.type = SKBAG_KEY_IPADDR;
3888 } else {
3889 PyErr_SetString(PyExc_TypeError, "Expected an integer or IP address");
3890 return NULL;
3891 }
3892
3893 value.type = SKBAG_COUNTER_U64;
3894 rv = skBagCounterGet(self->bag, &key, &value);
3895
3896 assert(rv != SKBAG_ERR_KEY_NOT_FOUND);
3897 if (rv == SKBAG_ERR_KEY_RANGE) {
3898 PyErr_SetString(PyExc_IndexError, "Index out of range");
3899 return NULL;
3900 }
3901 if (rv != SKBAG_OK) {
3902 PyErr_SetString(PyExc_ValueError, skBagStrerror(rv));
3903 return NULL;
3904 }
3905 assert(value.type == SKBAG_COUNTER_U64);
3906
3907 return PyLong_FromUnsignedLongLong(value.val.u64);
3908 }
3909
3910 static PyObject *
silkPyBag_type_merge(PyObject UNUSED (* self),PyObject * args)3911 silkPyBag_type_merge(
3912 PyObject UNUSED(*self),
3913 PyObject *args)
3914 {
3915 char *a, *b;
3916 skBagFieldType_t a_type, b_type, c_type;
3917 skBagErr_t rv;
3918 char buf[SKBAG_MAX_FIELD_BUFLEN];
3919
3920 if (!PyArg_ParseTuple(args, "ss", &a, &b)) {
3921 return NULL;
3922 }
3923 rv = skBagFieldTypeLookup(a, &a_type, NULL);
3924 if (rv != SKBAG_OK) {
3925 PyErr_Format(PyExc_ValueError, "'%s' is not a valid key type", a);
3926 }
3927 rv = skBagFieldTypeLookup(b, &b_type, NULL);
3928 if (rv != SKBAG_OK) {
3929 PyErr_Format(PyExc_ValueError, "'%s' is not a valid key type", b);
3930 }
3931 c_type = skBagFieldTypeMerge(a_type, b_type);
3932 skBagFieldTypeAsString(c_type, buf, sizeof(buf));
3933 return PyUnicode_FromString(buf);
3934 }
3935
3936
3937 /*
3938 *************************************************************************
3939 * TCP Flags
3940 *************************************************************************
3941 */
3942
3943 typedef struct silkPyTCPFlags_st {
3944 PyObject_HEAD
3945 uint8_t val;
3946 } silkPyTCPFlags;
3947
3948 /* function prototypes */
3949 static PyObject *
3950 silkPyTCPFlags_and(
3951 silkPyTCPFlags *a,
3952 silkPyTCPFlags *b);
3953 static PyObject *
3954 silkPyTCPFlags_getflag(
3955 silkPyTCPFlags *obj,
3956 void *bit);
3957 static PyObject *
3958 silkPyTCPFlags_getflag_deprecated(
3959 silkPyTCPFlags *obj,
3960 void *bit);
3961 static long
3962 silkPyTCPFlags_hash(
3963 silkPyTCPFlags *obj);
3964 static int
3965 silkPyTCPFlags_init(
3966 silkPyTCPFlags *self,
3967 PyObject *args,
3968 PyObject *kwds);
3969 static PyObject *
3970 silkPyTCPFlags_int(
3971 silkPyTCPFlags *obj);
3972 static silkPyTCPFlags *
3973 silkPyTCPFlags_invert(
3974 silkPyTCPFlags *obj);
3975 static PyObject *
3976 silkPyTCPFlags_matches(
3977 silkPyTCPFlags *self,
3978 PyObject *arg);
3979 static PyObject *
3980 silkPyTCPFlags_new(
3981 PyTypeObject *type,
3982 PyObject UNUSED(*args),
3983 PyObject UNUSED(*kwds));
3984 static int
3985 silkPyTCPFlags_nonzero(
3986 silkPyTCPFlags *a);
3987 static PyObject *
3988 silkPyTCPFlags_or(
3989 silkPyTCPFlags *a,
3990 silkPyTCPFlags *b);
3991 static PyObject *
3992 silkPyTCPFlags_padded(
3993 silkPyTCPFlags *obj);
3994 static PyObject *
3995 silkPyTCPFlags_repr(
3996 silkPyTCPFlags *obj);
3997 static PyObject *
3998 silkPyTCPFlags_richcompare(
3999 silkPyTCPFlags *self,
4000 PyObject *obj,
4001 int cmp);
4002 static int
4003 silkPyTCPFlags_setup(
4004 PyObject *mod);
4005 static PyObject *
4006 silkPyTCPFlags_str(
4007 silkPyTCPFlags *obj);
4008 static PyObject *
4009 silkPyTCPFlags_xor(
4010 silkPyTCPFlags *a,
4011 silkPyTCPFlags *b);
4012
4013 /* define docs and methods */
4014 #define silkPyTCPFlags_doc \
4015 "TCPFlags(string) -> TCPFlags based on flag string\n" \
4016 "TCPFlags(int) -> TCPFlags based on integer representation\n" \
4017 "TCPFlags(TCPFlags) -> Copy of TCPFlags"
4018
4019 static PyNumberMethods silkPyTCPFlags_number_methods;
4020
4021 static PyMethodDef silkPyTCPFlags_methods[] = {
4022 {"__reduce__", (PyCFunction)reduce_error, METH_NOARGS, ""},
4023 {"matches", (PyCFunction)silkPyTCPFlags_matches, METH_O,
4024 "Return whether the flags match the high/mask flagstring"},
4025 {"padded", (PyCFunction)silkPyTCPFlags_padded, METH_NOARGS,
4026 "Returns the flags string padded with spaces, so flags line up"},
4027 {NULL, NULL, 0, NULL} /* Sentinel */
4028 };
4029
4030 static uint8_t flags_array[] = {
4031 FIN_FLAG, SYN_FLAG, RST_FLAG, PSH_FLAG,
4032 ACK_FLAG, URG_FLAG, ECE_FLAG, CWR_FLAG};
4033
4034 static PyGetSetDef silkPyTCPFlags_getsetters[] = {
4035 {"fin", (getter)silkPyTCPFlags_getflag, NULL,
4036 "True if the FIN flag is set; False otherwise", (void*)&flags_array[0]},
4037 {"syn", (getter)silkPyTCPFlags_getflag, NULL,
4038 "True if the SYN flag is set; False otherwise", (void*)&flags_array[1]},
4039 {"rst", (getter)silkPyTCPFlags_getflag, NULL,
4040 "True if the RST flag is set; False otherwise", (void*)&flags_array[2]},
4041 {"psh", (getter)silkPyTCPFlags_getflag, NULL,
4042 "True if the PSH flag is set; False otherwise", (void*)&flags_array[3]},
4043 {"ack", (getter)silkPyTCPFlags_getflag, NULL,
4044 "True if the ACK flag is set; False otherwise", (void*)&flags_array[4]},
4045 {"urg", (getter)silkPyTCPFlags_getflag, NULL,
4046 "True if the URG flag is set; False otherwise", (void*)&flags_array[5]},
4047 {"ece", (getter)silkPyTCPFlags_getflag, NULL,
4048 "True if the ECE flag is set; False otherwise", (void*)&flags_array[6]},
4049 {"cwr", (getter)silkPyTCPFlags_getflag, NULL,
4050 "True if the CWR flag is set; False otherwise", (void*)&flags_array[7]},
4051
4052 {"FIN", (getter)silkPyTCPFlags_getflag_deprecated, NULL,
4053 ("True if the FIN flag is set; False otherwise."
4054 " DEPRECATED Use flag.fin instead"), (void*)&flags_array[0]},
4055 {"SYN", (getter)silkPyTCPFlags_getflag_deprecated, NULL,
4056 ("True if the SYN flag is set; False otherwise."
4057 " DEPRECATED Use flag.syn instead"), (void*)&flags_array[1]},
4058 {"RST", (getter)silkPyTCPFlags_getflag_deprecated, NULL,
4059 ("True if the RST flag is set; False otherwise."
4060 " DEPRECATED Use flag.rst instead"), (void*)&flags_array[2]},
4061 {"PSH", (getter)silkPyTCPFlags_getflag_deprecated, NULL,
4062 ("True if the PSH flag is set; False otherwise."
4063 " DEPRECATED Use flag.psh instead"), (void*)&flags_array[3]},
4064 {"ACK", (getter)silkPyTCPFlags_getflag_deprecated, NULL,
4065 ("True if the ACK flag is set; False otherwise."
4066 " DEPRECATED Use flag.ack instead"), (void*)&flags_array[4]},
4067 {"URG", (getter)silkPyTCPFlags_getflag_deprecated, NULL,
4068 ("True if the URG flag is set; False otherwise."
4069 " DEPRECATED Use flag.urg instead"), (void*)&flags_array[5]},
4070 {"ECE", (getter)silkPyTCPFlags_getflag_deprecated, NULL,
4071 ("True if the ECE flag is set; False otherwise."
4072 " DEPRECATED Use flag.ece instead"), (void*)&flags_array[6]},
4073 {"CWR", (getter)silkPyTCPFlags_getflag_deprecated, NULL,
4074 ("True if the CWR flag is set; False otherwise."
4075 " DEPRECATED Use flag.cwr instead"), (void*)&flags_array[7]},
4076 {NULL, NULL, NULL, NULL, NULL}
4077 };
4078
4079 /* define the object types */
4080 static PyTypeObject silkPyTCPFlagsType = {
4081 PyVarObject_HEAD_INIT(NULL, 0)
4082 "silk.TCPFlags", /* tp_name */
4083 sizeof(silkPyTCPFlags), /* tp_basicsize */
4084 0, /* tp_itemsize */
4085 obj_dealloc, /* tp_dealloc */
4086 0, /* tp_vectorcall_offset (Py 3.8) */
4087 0, /* tp_getattr */
4088 0, /* tp_setattr */
4089 0, /* tp_as_async (tp_compare in Py2.x) */
4090 (reprfunc)silkPyTCPFlags_repr, /* tp_repr */
4091 &silkPyTCPFlags_number_methods, /* tp_as_number */
4092 0, /* tp_as_sequence */
4093 0, /* tp_as_mapping */
4094 (hashfunc)silkPyTCPFlags_hash, /* tp_hash */
4095 0, /* tp_call */
4096 (reprfunc)silkPyTCPFlags_str, /* tp_str */
4097 0, /* tp_getattro */
4098 0, /* tp_setattro */
4099 0, /* tp_as_buffer */
4100 #if PY_MAJOR_VERSION < 3
4101 Py_TPFLAGS_CHECKTYPES | Py_TPFLAGS_HAVE_RICHCOMPARE |
4102 #endif
4103 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
4104 silkPyTCPFlags_doc, /* tp_doc */
4105 0, /* tp_traverse */
4106 0, /* tp_clear */
4107 (richcmpfunc)silkPyTCPFlags_richcompare, /* tp_richcompare */
4108 0, /* tp_weaklistoffset */
4109 0, /* tp_iter */
4110 0, /* tp_iternext */
4111 silkPyTCPFlags_methods, /* tp_methods */
4112 0, /* tp_members */
4113 silkPyTCPFlags_getsetters, /* tp_getset */
4114 0, /* tp_base */
4115 0, /* tp_dict */
4116 0, /* tp_descr_get */
4117 0, /* tp_descr_set */
4118 0, /* tp_dictoffset */
4119 (initproc)silkPyTCPFlags_init, /* tp_init */
4120 0, /* tp_alloc */
4121 silkPyTCPFlags_new, /* tp_new */
4122 0, /* tp_free */
4123 0, /* tp_is_gc */
4124 0, /* tp_bases */
4125 0, /* tp_mro */
4126 0, /* tp_cache */
4127 0, /* tp_subclasses */
4128 0, /* tp_weaklist */
4129 0 /* tp_del */
4130 #if PY_VERSION_HEX >= 0x02060000
4131 ,0 /* tp_version_tag */
4132 #endif
4133 #if PY_VERSION_HEX >= 0x03040000
4134 ,0 /* tp_finalize */
4135 #endif
4136 #if PY_VERSION_HEX >= 0x03080000
4137 ,0 /* tp_vectorcall */
4138 ,0 /* tp_print */
4139 #endif
4140 };
4141
4142 /* macro and function defintions */
4143 #define silkPyTCPFlags_Check(op) \
4144 PyObject_TypeCheck(op, &silkPyTCPFlagsType)
4145
4146 static PyObject *
silkPyTCPFlags_and(silkPyTCPFlags * a,silkPyTCPFlags * b)4147 silkPyTCPFlags_and(
4148 silkPyTCPFlags *a,
4149 silkPyTCPFlags *b)
4150 {
4151 PyObject *new_obj;
4152
4153 if (!silkPyTCPFlags_Check(a) || !silkPyTCPFlags_Check(b)) {
4154 Py_INCREF(Py_NotImplemented);
4155 return Py_NotImplemented;
4156 }
4157
4158 new_obj = silkPyTCPFlagsType.tp_alloc(&silkPyTCPFlagsType, 0);
4159 if (new_obj != NULL) {
4160 ((silkPyTCPFlags*)new_obj)->val = a->val & b->val;
4161 }
4162 return new_obj;
4163 }
4164
4165 static PyObject *
silkPyTCPFlags_getflag(silkPyTCPFlags * obj,void * bit)4166 silkPyTCPFlags_getflag(
4167 silkPyTCPFlags *obj,
4168 void *bit)
4169 {
4170 return PyBool_FromLong(obj->val & *(uint8_t*)bit);
4171 }
4172
4173 static PyObject *
silkPyTCPFlags_getflag_deprecated(silkPyTCPFlags * obj,void * bit)4174 silkPyTCPFlags_getflag_deprecated(
4175 silkPyTCPFlags *obj,
4176 void *bit)
4177 {
4178 /* Deprecated as of SiLK 3.0.0. */
4179 PyErr_Warn(PyExc_DeprecationWarning,
4180 ("Use of upper-case flag check attributes for "
4181 "TCPFlags is deprecated"));
4182 return PyBool_FromLong(obj->val & *(uint8_t*)bit);
4183 }
4184
4185 static long
silkPyTCPFlags_hash(silkPyTCPFlags * obj)4186 silkPyTCPFlags_hash(
4187 silkPyTCPFlags *obj)
4188 {
4189 return obj->val;
4190 }
4191
4192 static int
silkPyTCPFlags_init(silkPyTCPFlags * self,PyObject * args,PyObject * kwds)4193 silkPyTCPFlags_init(
4194 silkPyTCPFlags *self,
4195 PyObject *args,
4196 PyObject *kwds)
4197 {
4198 static char *kwlist[] = {"value", NULL};
4199 PyObject *val;
4200
4201 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O", kwlist, &val)) {
4202 return -1;
4203 }
4204
4205 if (silkPyTCPFlags_Check(val)) {
4206 silkPyTCPFlags *oflags = (silkPyTCPFlags*)val;
4207 self->val = oflags->val;
4208 } else if (IS_INT(val)) {
4209 long intval = PyLong_AsLong(val);
4210 if (intval < 0 || intval > (long)UINT8_MAX) {
4211 PyErr_Format(PyExc_ValueError,
4212 "Illegal TCP flag value: %ld", intval);
4213 return -1;
4214 }
4215 self->val = intval;
4216 } else if (IS_STRING(val)) {
4217 PyObject *bytes = bytes_from_string(val);
4218 char *strval;
4219
4220 if (bytes == NULL) {
4221 return -1;
4222 }
4223 strval = PyBytes_AS_STRING(bytes);
4224 if (skStringParseTCPFlags(&self->val, strval)) {
4225 PyErr_Format(PyExc_ValueError,
4226 "Illegal TCP flag value: %s", strval);
4227 Py_DECREF(bytes);
4228 return -1;
4229 }
4230 Py_DECREF(bytes);
4231 } else {
4232 obj_error("Illegal value: %s", val);
4233 return -1;
4234 }
4235
4236 return 0;
4237 }
4238
4239 static PyObject *
silkPyTCPFlags_int(silkPyTCPFlags * obj)4240 silkPyTCPFlags_int(
4241 silkPyTCPFlags *obj)
4242 {
4243 return PyInt_FromLong(obj->val);
4244 }
4245
4246 static silkPyTCPFlags *
silkPyTCPFlags_invert(silkPyTCPFlags * obj)4247 silkPyTCPFlags_invert(
4248 silkPyTCPFlags *obj)
4249 {
4250 silkPyTCPFlags *new_obj =
4251 (silkPyTCPFlags*)silkPyTCPFlagsType.tp_alloc(&silkPyTCPFlagsType, 0);
4252
4253 if (new_obj != NULL) {
4254 new_obj->val = ~obj->val;
4255 }
4256 return new_obj;
4257 }
4258
4259 static PyObject *
silkPyTCPFlags_matches(silkPyTCPFlags * self,PyObject * arg)4260 silkPyTCPFlags_matches(
4261 silkPyTCPFlags *self,
4262 PyObject *arg)
4263 {
4264 char *repr;
4265 PyObject *bytes;
4266 uint8_t high, mask;
4267 int rv;
4268
4269 if (!IS_STRING(arg)) {
4270 PyErr_SetString(PyExc_TypeError, "Expected string");
4271 return NULL;
4272 }
4273
4274 bytes = bytes_from_string(arg);
4275 repr = PyBytes_AS_STRING(bytes);
4276 rv = skStringParseTCPFlagsHighMask(&high, &mask, repr);
4277 Py_DECREF(bytes);
4278 if (rv == SKUTILS_ERR_SHORT) {
4279 mask = high;
4280 } else if (rv != 0) {
4281 PyErr_SetString(PyExc_ValueError, "Illegal flag/mask");
4282 return NULL;
4283 }
4284
4285 return PyBool_FromLong((self->val & mask) == high);
4286 }
4287
4288 static PyObject *
silkPyTCPFlags_new(PyTypeObject * type,PyObject UNUSED (* args),PyObject UNUSED (* kwds))4289 silkPyTCPFlags_new(
4290 PyTypeObject *type,
4291 PyObject UNUSED(*args),
4292 PyObject UNUSED(*kwds))
4293 {
4294 silkPyTCPFlags *self;
4295
4296 self = (silkPyTCPFlags*)type->tp_alloc(type, 0);
4297
4298 if (self != NULL) {
4299 self->val = 0;
4300 }
4301
4302 return (PyObject*)self;
4303 }
4304
4305 static int
silkPyTCPFlags_nonzero(silkPyTCPFlags * a)4306 silkPyTCPFlags_nonzero(
4307 silkPyTCPFlags *a)
4308 {
4309 return a->val ? 1 : 0;
4310 }
4311
4312 static PyObject *
silkPyTCPFlags_or(silkPyTCPFlags * a,silkPyTCPFlags * b)4313 silkPyTCPFlags_or(
4314 silkPyTCPFlags *a,
4315 silkPyTCPFlags *b)
4316 {
4317 PyObject *new_obj;
4318
4319 if (!silkPyTCPFlags_Check(a) || !silkPyTCPFlags_Check(b)) {
4320 Py_INCREF(Py_NotImplemented);
4321 return Py_NotImplemented;
4322 }
4323
4324 new_obj = silkPyTCPFlagsType.tp_alloc(&silkPyTCPFlagsType, 0);
4325 if (new_obj != NULL) {
4326 ((silkPyTCPFlags*)new_obj)->val = a->val | b->val;
4327 }
4328 return new_obj;
4329 }
4330
4331 static PyObject *
silkPyTCPFlags_padded(silkPyTCPFlags * obj)4332 silkPyTCPFlags_padded(
4333 silkPyTCPFlags *obj)
4334 {
4335 char flags[SK_TCPFLAGS_STRLEN];
4336
4337 skTCPFlagsString(obj->val, flags, SK_PADDED_FLAGS);
4338
4339 return PyUnicode_FromString(flags);
4340 }
4341
4342 static PyObject *
silkPyTCPFlags_repr(silkPyTCPFlags * obj)4343 silkPyTCPFlags_repr(
4344 silkPyTCPFlags *obj)
4345 {
4346 char flags[SK_TCPFLAGS_STRLEN];
4347
4348 skTCPFlagsString(obj->val, flags, SK_PADDED_FLAGS);
4349
4350 return PyUnicode_FromFormat("silk.TCPFlags('%s')", flags);
4351 }
4352
4353 static PyObject *
silkPyTCPFlags_richcompare(silkPyTCPFlags * self,PyObject * obj,int cmp)4354 silkPyTCPFlags_richcompare(
4355 silkPyTCPFlags *self,
4356 PyObject *obj,
4357 int cmp)
4358 {
4359 if (cmp != Py_EQ && cmp != Py_NE) {
4360 Py_INCREF(Py_NotImplemented);
4361 return Py_NotImplemented;
4362 }
4363
4364 if (!silkPyTCPFlags_Check(obj)) {
4365 PyErr_SetString(PyExc_TypeError, "Expected silk.TCPFlags");
4366 return NULL;
4367 }
4368
4369 if (self->val == ((silkPyTCPFlags*)obj)->val) {
4370 if (cmp == Py_EQ) {
4371 Py_RETURN_TRUE;
4372 } else {
4373 Py_RETURN_FALSE;
4374 }
4375 }
4376 if (cmp == Py_NE) {
4377 Py_RETURN_TRUE;
4378 }
4379
4380 Py_RETURN_FALSE;
4381 }
4382
4383 static int
silkPyTCPFlags_setup(PyObject * mod)4384 silkPyTCPFlags_setup(
4385 PyObject *mod)
4386 {
4387 /* Setup number methods */
4388 memset(&silkPyTCPFlags_number_methods, 0,
4389 sizeof(silkPyTCPFlags_number_methods));
4390 #if PY_MAJOR_VERSION >= 3
4391 silkPyTCPFlags_number_methods.nb_bool =
4392 (inquiry)silkPyTCPFlags_nonzero;
4393 #else
4394 silkPyTCPFlags_number_methods.nb_nonzero =
4395 (inquiry)silkPyTCPFlags_nonzero;
4396 #endif
4397 silkPyTCPFlags_number_methods.nb_invert =
4398 (unaryfunc)silkPyTCPFlags_invert;
4399 silkPyTCPFlags_number_methods.nb_and = (binaryfunc)silkPyTCPFlags_and;
4400 silkPyTCPFlags_number_methods.nb_xor = (binaryfunc)silkPyTCPFlags_xor;
4401 silkPyTCPFlags_number_methods.nb_or = (binaryfunc)silkPyTCPFlags_or;
4402 silkPyTCPFlags_number_methods.nb_int = (unaryfunc)silkPyTCPFlags_int;
4403
4404 /* Initialize type and add to module */
4405 if (PyType_Ready(&silkPyTCPFlagsType) < 0) {
4406 return -1;
4407 }
4408 return PyModule_AddObject(mod, "TCPFlags",
4409 (PyObject*)&silkPyTCPFlagsType);
4410 }
4411
4412 static PyObject *
silkPyTCPFlags_str(silkPyTCPFlags * obj)4413 silkPyTCPFlags_str(
4414 silkPyTCPFlags *obj)
4415 {
4416 char flags[SK_TCPFLAGS_STRLEN];
4417
4418 skTCPFlagsString(obj->val, flags, 0);
4419
4420 return PyUnicode_FromString(flags);
4421 }
4422
4423 static PyObject *
silkPyTCPFlags_xor(silkPyTCPFlags * a,silkPyTCPFlags * b)4424 silkPyTCPFlags_xor(
4425 silkPyTCPFlags *a,
4426 silkPyTCPFlags *b)
4427 {
4428 PyObject *new_obj;
4429
4430 if (!silkPyTCPFlags_Check(a) || !silkPyTCPFlags_Check(b)) {
4431 Py_INCREF(Py_NotImplemented);
4432 return Py_NotImplemented;
4433 }
4434
4435 new_obj = silkPyTCPFlagsType.tp_alloc(&silkPyTCPFlagsType, 0);
4436 if (new_obj != NULL) {
4437 ((silkPyTCPFlags*)new_obj)->val = a->val ^ b->val;
4438 }
4439 return new_obj;
4440 }
4441
4442
4443 /*
4444 *************************************************************************
4445 * RWRec
4446 *************************************************************************
4447 */
4448
4449 typedef struct silkPyRawRWRec_st {
4450 PyObject_HEAD
4451 rwRec rec;
4452 } silkPyRawRWRec;
4453
4454 typedef struct silkPyRWRec_st {
4455 PyObject_HEAD
4456 silkPyRawRWRec *raw;
4457 } silkPyRWRec;
4458
4459 /* function prototypes */
4460 static PyObject *
4461 silkPyRWRec_application_get(
4462 silkPyRWRec *obj,
4463 void UNUSED(*closure));
4464 static int
4465 silkPyRWRec_application_set(
4466 silkPyRWRec *obj,
4467 PyObject *value,
4468 void UNUSED(*closure));
4469 static PyObject *
4470 silkPyRWRec_bytes_get(
4471 silkPyRWRec *obj,
4472 void UNUSED(*closure));
4473 static int
4474 silkPyRWRec_bytes_set(
4475 silkPyRWRec *obj,
4476 PyObject *value,
4477 void UNUSED(*closure));
4478 static PyObject *
4479 silkPyRWRec_classname_get(
4480 silkPyRWRec *obj,
4481 void UNUSED(*closure));
4482 static PyObject *
4483 silkPyRWRec_classtype_get(
4484 silkPyRWRec *obj,
4485 void UNUSED(*closure));
4486 static PyObject *
4487 silkPyRWRec_classtype_id_get(
4488 silkPyRWRec *obj,
4489 void UNUSED(*closure));
4490 static int
4491 silkPyRWRec_classtype_id_set(
4492 silkPyRWRec *obj,
4493 PyObject *value,
4494 void UNUSED(*closure));
4495 static int
4496 silkPyRWRec_classtype_set(
4497 silkPyRWRec *obj,
4498 PyObject *value,
4499 void UNUSED(*closure));
4500 static void
4501 silkPyRWRec_dealloc(
4502 silkPyRWRec *obj);
4503 static PyObject *
4504 silkPyRWRec_dip_get(
4505 silkPyRWRec *obj,
4506 void UNUSED(*closure));
4507 static int
4508 silkPyRWRec_dip_set(
4509 silkPyRWRec *obj,
4510 PyObject *value,
4511 void UNUSED(*closure));
4512 static PyObject *
4513 silkPyRWRec_dport_get(
4514 silkPyRWRec *obj,
4515 void UNUSED(*closure));
4516 static int
4517 silkPyRWRec_dport_set(
4518 silkPyRWRec *obj,
4519 PyObject *value,
4520 void UNUSED(*closure));
4521 static PyObject *
4522 silkPyRWRec_duration_get(
4523 silkPyRWRec *obj,
4524 void UNUSED(*closure));
4525 static PyObject *
4526 silkPyRWRec_duration_secs_get(
4527 silkPyRWRec *obj,
4528 void UNUSED(*closure));
4529 static int
4530 silkPyRWRec_duration_secs_set(
4531 silkPyRWRec *obj,
4532 PyObject *value,
4533 void UNUSED(*closure));
4534 static int
4535 silkPyRWRec_duration_set(
4536 silkPyRWRec *obj,
4537 PyObject *value,
4538 void UNUSED(*closure));
4539 static PyObject *
4540 silkPyRWRec_etime_epoch_secs_get(
4541 silkPyRWRec *obj,
4542 void UNUSED(*closure));
4543 static int
4544 silkPyRWRec_etime_epoch_secs_set(
4545 silkPyRWRec *obj,
4546 PyObject *value,
4547 void UNUSED(*closure));
4548 static PyObject *
4549 silkPyRWRec_etime_get(
4550 silkPyRWRec *obj,
4551 void UNUSED(*closure));
4552 static int
4553 silkPyRWRec_etime_set(
4554 silkPyRWRec *obj,
4555 PyObject *value,
4556 void UNUSED(*closure));
4557 static PyObject *
4558 silkPyRWRec_finnoack_get(
4559 silkPyRWRec *obj,
4560 void UNUSED(*closure));
4561 static int
4562 silkPyRWRec_finnoack_set(
4563 silkPyRWRec *obj,
4564 PyObject *value,
4565 void UNUSED(*closure));
4566 static PyObject *
4567 silkPyRWRec_icmpcode_get(
4568 silkPyRWRec *obj,
4569 void UNUSED(*closure));
4570 static int
4571 silkPyRWRec_icmpcode_set(
4572 silkPyRWRec *obj,
4573 PyObject *value,
4574 void UNUSED(*closure));
4575 static PyObject *
4576 silkPyRWRec_icmptype_get(
4577 silkPyRWRec *obj,
4578 void UNUSED(*closure));
4579 static int
4580 silkPyRWRec_icmptype_set(
4581 silkPyRWRec *obj,
4582 PyObject *value,
4583 void UNUSED(*closure));
4584 static PyObject *
4585 silkPyRWRec_new(
4586 PyTypeObject *type,
4587 PyObject *args,
4588 PyObject *kwds);
4589 static int
4590 silkPyRWRec_init(
4591 silkPyRWRec *self,
4592 PyObject *args,
4593 PyObject *kwds);
4594 static PyObject *
4595 silkPyRWRec_initial_tcpflags_get(
4596 silkPyRWRec *obj,
4597 void *deprecated);
4598 static int
4599 silkPyRWRec_initial_tcpflags_set(
4600 silkPyRWRec *obj,
4601 PyObject *value,
4602 void *deprecated);
4603 static PyObject *
4604 silkPyRWRec_input_get(
4605 silkPyRWRec *obj,
4606 void UNUSED(*closure));
4607 static int
4608 silkPyRWRec_input_set(
4609 silkPyRWRec *obj,
4610 PyObject *value,
4611 void UNUSED(*closure));
4612 static PyObject *
4613 silkPyRWRec_is_icmp(
4614 silkPyRWRec *obj);
4615 static PyObject *
4616 silkPyRWRec_is_ipv6(
4617 silkPyRWRec UNUSED_NOv6(*obj));
4618 static PyObject *
4619 silkPyRWRec_is_web(
4620 silkPyRWRec *obj);
4621 static PyObject *
4622 silkPyRWRec_nhip_get(
4623 silkPyRWRec *obj,
4624 void UNUSED(*closure));
4625 static int
4626 silkPyRWRec_nhip_set(
4627 silkPyRWRec *obj,
4628 PyObject *value,
4629 void UNUSED(*closure));
4630 static PyObject *
4631 silkPyRWRec_output_get(
4632 silkPyRWRec *obj,
4633 void UNUSED(*closure));
4634 static int
4635 silkPyRWRec_output_set(
4636 silkPyRWRec *obj,
4637 PyObject *value,
4638 void UNUSED(*closure));
4639 static PyObject *
4640 silkPyRWRec_packets_get(
4641 silkPyRWRec *obj,
4642 void UNUSED(*closure));
4643 static int
4644 silkPyRWRec_packets_set(
4645 silkPyRWRec *obj,
4646 PyObject *value,
4647 void UNUSED(*closure));
4648 static PyObject *
4649 silkPyRWRec_protocol_get(
4650 silkPyRWRec *obj,
4651 void UNUSED(*closure));
4652 static int
4653 silkPyRWRec_protocol_set(
4654 silkPyRWRec *obj,
4655 PyObject *value,
4656 void UNUSED(*closure));
4657 static PyObject *
4658 silkPyRWRec_richcompare(
4659 silkPyRWRec *self,
4660 PyObject *obj,
4661 int cmp);
4662 static PyObject *
4663 silkPyRWRec_sensor_get(
4664 silkPyRWRec *obj,
4665 void UNUSED(*closure));
4666 static PyObject *
4667 silkPyRWRec_sensor_id_get(
4668 silkPyRWRec *obj,
4669 void UNUSED(*closure));
4670 static PyObject *
4671 silkPyRWRec_to_ipv4(
4672 silkPyRWRec *obj);
4673 #if SK_ENABLE_IPV6
4674 static PyObject *
4675 silkPyRWRec_to_ipv6(
4676 silkPyRWRec *obj);
4677 #endif
4678 static int
4679 silkPyRWRec_sensor_id_set(
4680 silkPyRWRec *obj,
4681 PyObject *value,
4682 void UNUSED(*closure));
4683 static int
4684 silkPyRWRec_sensor_set(
4685 silkPyRWRec *obj,
4686 PyObject *value,
4687 void UNUSED(*closure));
4688 static PyObject *
4689 silkPyRWRec_session_tcpflags_get(
4690 silkPyRWRec *obj,
4691 void *deprecated);
4692 static int
4693 silkPyRWRec_session_tcpflags_set(
4694 silkPyRWRec *obj,
4695 PyObject *value,
4696 void *deprecated);
4697 static PyObject *
4698 silkPyRWRec_sip_get(
4699 silkPyRWRec *obj,
4700 void UNUSED(*closure));
4701 static int
4702 silkPyRWRec_sip_set(
4703 silkPyRWRec *obj,
4704 PyObject *value,
4705 void UNUSED(*closure));
4706 static PyObject *
4707 silkPyRWRec_sport_get(
4708 silkPyRWRec *obj,
4709 void UNUSED(*closure));
4710 static int
4711 silkPyRWRec_sport_set(
4712 silkPyRWRec *obj,
4713 PyObject *value,
4714 void UNUSED(*closure));
4715 static PyObject *
4716 silkPyRWRec_stime_epoch_secs_get(
4717 silkPyRWRec *obj,
4718 void UNUSED(*closure));
4719 static int
4720 silkPyRWRec_stime_epoch_secs_set(
4721 silkPyRWRec *obj,
4722 PyObject *value,
4723 void UNUSED(*closure));
4724 static PyObject *
4725 silkPyRWRec_stime_get(
4726 silkPyRWRec *obj,
4727 void UNUSED(*closure));
4728 static int
4729 silkPyRWRec_stime_set(
4730 silkPyRWRec *obj,
4731 PyObject *value,
4732 void UNUSED(*closure));
4733 static PyObject *
4734 silkPyRWRec_tcpflags_get(
4735 silkPyRWRec *obj,
4736 void UNUSED(*closure));
4737 static int
4738 silkPyRWRec_tcpflags_set(
4739 silkPyRWRec *obj,
4740 PyObject *value,
4741 void UNUSED(*closure));
4742 static PyObject *
4743 silkPyRWRec_timeout_killed_get(
4744 silkPyRWRec *obj,
4745 void UNUSED(*closure));
4746 static int
4747 silkPyRWRec_timeout_killed_set(
4748 silkPyRWRec *obj,
4749 PyObject *value,
4750 void UNUSED(*closure));
4751 static PyObject *
4752 silkPyRWRec_timeout_started_get(
4753 silkPyRWRec *obj,
4754 void UNUSED(*closure));
4755 static int
4756 silkPyRWRec_timeout_started_set(
4757 silkPyRWRec *obj,
4758 PyObject *value,
4759 void UNUSED(*closure));
4760 static PyObject *
4761 silkPyRWRec_typename_get(
4762 silkPyRWRec *obj,
4763 void UNUSED(*closure));
4764 static PyObject *
4765 silkPyRWRec_uniform_packets_get(
4766 silkPyRWRec *obj,
4767 void UNUSED(*closure));
4768 static int
4769 silkPyRWRec_uniform_packets_set(
4770 silkPyRWRec *obj,
4771 PyObject *value,
4772 void UNUSED(*closure));
4773 static int
4774 silkPyRawRWRec_init(
4775 silkPyRawRWRec *self,
4776 PyObject *args,
4777 PyObject *kwds);
4778 static PyObject *
4779 silkPyRawRWRec_new(
4780 PyTypeObject *type,
4781 PyObject UNUSED(*args),
4782 PyObject UNUSED(*kwds));
4783
4784 /* define docs and methods */
4785 static PyMethodDef silkPyRWRec_methods[] = {
4786 {"__reduce__", (PyCFunction)reduce_error, METH_NOARGS, ""},
4787 {"is_icmp", (PyCFunction)silkPyRWRec_is_icmp, METH_NOARGS,
4788 "Returns whether the record is an ICMP record"},
4789 {"is_ipv6", (PyCFunction)silkPyRWRec_is_ipv6, METH_NOARGS,
4790 "Returns whether record uses IPv6 addresses"},
4791 {"is_web", (PyCFunction)silkPyRWRec_is_web, METH_NOARGS,
4792 "Returns whether record can be stored in a SiLK WWW file format"},
4793 {"to_ipv4", (PyCFunction)silkPyRWRec_to_ipv4, METH_NOARGS,
4794 "Returns a new raw copy of the record converted to IPv4"},
4795 {"to_ipv6", (PyCFunction)
4796 #if SK_ENABLE_IPV6
4797 silkPyRWRec_to_ipv6, METH_NOARGS,
4798 #else
4799 silkPyNotImplemented, METH_VARARGS | METH_KEYWORDS,
4800 #endif
4801 "Returns a new raw copy of the record converted to IPv6"},
4802 {NULL, NULL, 0, NULL} /* Sentinel */
4803 };
4804
4805 static PyGetSetDef silkPyRWRec_getseters[] = {
4806 {"application",
4807 (getter)silkPyRWRec_application_get, (setter)silkPyRWRec_application_set,
4808 "\"service\" port set by the collector", NULL},
4809 {"bytes",
4810 (getter)silkPyRWRec_bytes_get, (setter)silkPyRWRec_bytes_set,
4811 "Count of bytes", NULL},
4812 {"classname",
4813 (getter)silkPyRWRec_classname_get, NULL,
4814 "class name (read-only)", NULL},
4815 {"classtype",
4816 (getter)silkPyRWRec_classtype_get, (setter)silkPyRWRec_classtype_set,
4817 "class name, type name pair", NULL},
4818 {"classtype_id",
4819 (getter)silkPyRWRec_classtype_id_get,(setter)silkPyRWRec_classtype_id_set,
4820 "class, type pair ID", NULL},
4821 {"dip",
4822 (getter)silkPyRWRec_dip_get, (setter)silkPyRWRec_dip_set,
4823 "destination IP", NULL},
4824 {"dport",
4825 (getter)silkPyRWRec_dport_get, (setter)silkPyRWRec_dport_set,
4826 "Destination port", NULL},
4827 {"duration",
4828 (getter)silkPyRWRec_duration_get, (setter)silkPyRWRec_duration_set,
4829 "duration of flow as datetime.timedelta", NULL},
4830 {"duration_secs",
4831 (getter)silkPyRWRec_duration_secs_get,
4832 (setter)silkPyRWRec_duration_secs_set,
4833 "duration of flow in seconds", NULL},
4834 {"etime",
4835 (getter)silkPyRWRec_etime_get, (setter)silkPyRWRec_etime_set,
4836 "end time of flow as datetime.timedelta", NULL},
4837 {"etime_epoch_secs",
4838 (getter)silkPyRWRec_etime_epoch_secs_get,
4839 (setter)silkPyRWRec_etime_epoch_secs_set,
4840 "end time of flow as a number of seconds since the epoch time", NULL},
4841 {"finnoack",
4842 (getter)silkPyRWRec_finnoack_get, (setter)silkPyRWRec_finnoack_set,
4843 "FIN followed by not ACK", NULL},
4844 {"icmpcode",
4845 (getter)silkPyRWRec_icmpcode_get, (setter)silkPyRWRec_icmpcode_set,
4846 "ICMP code", NULL},
4847 {"icmptype",
4848 (getter)silkPyRWRec_icmptype_get, (setter)silkPyRWRec_icmptype_set,
4849 "ICMP type", NULL},
4850 {"initflags", /* Deprecated in SiLK 3.0.0 */
4851 (getter)silkPyRWRec_initial_tcpflags_get,
4852 (setter)silkPyRWRec_initial_tcpflags_set,
4853 "TCP flags of first packet. DEPRECATED Use initial_tcpflags instead",
4854 deprecated_true},
4855 {"initial_tcpflags",
4856 (getter)silkPyRWRec_initial_tcpflags_get,
4857 (setter)silkPyRWRec_initial_tcpflags_set,
4858 "TCP flags of first packet", NULL},
4859 {"input",
4860 (getter)silkPyRWRec_input_get, (setter)silkPyRWRec_input_set,
4861 "router incoming SNMP interface", NULL},
4862 {"nhip",
4863 (getter)silkPyRWRec_nhip_get, (setter)silkPyRWRec_nhip_set,
4864 "router next hop IP", NULL},
4865 {"output",
4866 (getter)silkPyRWRec_output_get, (setter)silkPyRWRec_output_set,
4867 "router outgoing SNMP interface", NULL},
4868 {"packets",
4869 (getter)silkPyRWRec_packets_get, (setter)silkPyRWRec_packets_set,
4870 "count of packets", NULL},
4871 {"protocol",
4872 (getter)silkPyRWRec_protocol_get, (setter)silkPyRWRec_protocol_set,
4873 "IP protocol", NULL},
4874 {"restflags", /* Deprecated,SiLK 3.0.0 */
4875 (getter)silkPyRWRec_session_tcpflags_get,
4876 (setter)silkPyRWRec_session_tcpflags_set,
4877 ("TCP flags on non-initial packets."
4878 " DEPRECATED Use session_tcpflags instead"), deprecated_true},
4879 {"sensor",
4880 (getter)silkPyRWRec_sensor_get, (setter)silkPyRWRec_sensor_set,
4881 "sensor name", NULL},
4882 {"sensor_id",
4883 (getter)silkPyRWRec_sensor_id_get, (setter)silkPyRWRec_sensor_id_set,
4884 "sensor ID", NULL},
4885 {"session_tcpflags",
4886 (getter)silkPyRWRec_session_tcpflags_get,
4887 (setter)silkPyRWRec_session_tcpflags_set,
4888 "TCP flags on non-initial packets", NULL},
4889 {"sip",
4890 (getter)silkPyRWRec_sip_get, (setter)silkPyRWRec_sip_set,
4891 "source IP", NULL},
4892 {"sport",
4893 (getter)silkPyRWRec_sport_get, (setter)silkPyRWRec_sport_set,
4894 "source port", NULL},
4895 {"stime",
4896 (getter)silkPyRWRec_stime_get, (setter)silkPyRWRec_stime_set,
4897 "start time of flow as datetime.datetime", NULL},
4898 {"stime_epoch_secs",
4899 (getter)silkPyRWRec_stime_epoch_secs_get,
4900 (setter)silkPyRWRec_stime_epoch_secs_set,
4901 "start time of flow as a number of seconds since the epoch time", NULL},
4902 {"tcpflags",
4903 (getter)silkPyRWRec_tcpflags_get, (setter)silkPyRWRec_tcpflags_set,
4904 "OR of all tcpflags", NULL},
4905 {"timeout_killed",
4906 (getter)silkPyRWRec_timeout_killed_get,
4907 (setter)silkPyRWRec_timeout_killed_set,
4908 "flow ended prematurely due to timeout by the collector", NULL},
4909 {"timeout_started",
4910 (getter)silkPyRWRec_timeout_started_get,
4911 (setter)silkPyRWRec_timeout_started_set,
4912 "flow is a continuation of a flow timed-out by the collector", NULL},
4913 {"typename",
4914 (getter)silkPyRWRec_typename_get, NULL,
4915 "type name (read-only)", NULL},
4916 {"uniform_packets",
4917 (getter)silkPyRWRec_uniform_packets_get,
4918 (setter)silkPyRWRec_uniform_packets_set,
4919 "flow contained only packets of uniform size", NULL},
4920 {NULL, NULL, NULL, NULL, NULL}
4921 };
4922
4923 /* define the object types */
4924 static PyTypeObject silkPyRawRWRecType = {
4925 PyVarObject_HEAD_INIT(NULL, 0)
4926 "silk.pysilk.RWRawRec", /* tp_name */
4927 sizeof(silkPyRawRWRec), /* tp_basicsize */
4928 0, /* tp_itemsize */
4929 obj_dealloc, /* tp_dealloc */
4930 0, /* tp_vectorcall_offset (Py 3.8) */
4931 0, /* tp_getattr */
4932 0, /* tp_setattr */
4933 0, /* tp_as_async (tp_compare in Py2.x) */
4934 0, /* tp_repr */
4935 0, /* tp_as_number */
4936 0, /* tp_as_sequence */
4937 0, /* tp_as_mapping */
4938 0, /* tp_hash */
4939 0, /* tp_call */
4940 0, /* tp_str */
4941 0, /* tp_getattro */
4942 0, /* tp_setattro */
4943 0, /* tp_as_buffer */
4944 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
4945 "Raw RW Record", /* tp_doc */
4946 0, /* tp_traverse */
4947 0, /* tp_clear */
4948 0, /* tp_richcompare */
4949 0, /* tp_weaklistoffset */
4950 0, /* tp_iter */
4951 0, /* tp_iternext */
4952 0, /* tp_methods */
4953 0, /* tp_members */
4954 0, /* tp_getset */
4955 0, /* tp_base */
4956 0, /* tp_dict */
4957 0, /* tp_descr_get */
4958 0, /* tp_descr_set */
4959 0, /* tp_dictoffset */
4960 (initproc)silkPyRawRWRec_init, /* tp_init */
4961 0, /* tp_alloc */
4962 silkPyRawRWRec_new, /* tp_new */
4963 0, /* tp_free */
4964 0, /* tp_is_gc */
4965 0, /* tp_bases */
4966 0, /* tp_mro */
4967 0, /* tp_cache */
4968 0, /* tp_subclasses */
4969 0, /* tp_weaklist */
4970 0 /* tp_del */
4971 #if PY_VERSION_HEX >= 0x02060000
4972 ,0 /* tp_version_tag */
4973 #endif
4974 #if PY_VERSION_HEX >= 0x03040000
4975 ,0 /* tp_finalize */
4976 #endif
4977 #if PY_VERSION_HEX >= 0x03080000
4978 ,0 /* tp_vectorcall */
4979 ,0 /* tp_print */
4980 #endif
4981 };
4982
4983 static PyTypeObject silkPyRWRecType = {
4984 PyVarObject_HEAD_INIT(NULL, 0)
4985 "silk.pysilk.RWRecBase", /* tp_name */
4986 sizeof(silkPyRWRec), /* tp_basicsize */
4987 0, /* tp_itemsize */
4988 (destructor)silkPyRWRec_dealloc, /* tp_dealloc */
4989 0, /* tp_vectorcall_offset (Py 3.8) */
4990 0, /* tp_getattr */
4991 0, /* tp_setattr */
4992 0, /* tp_as_async (tp_compare in Py2.x) */
4993 0, /* tp_repr */
4994 0, /* tp_as_number */
4995 0, /* tp_as_sequence */
4996 0, /* tp_as_mapping */
4997 0, /* tp_hash */
4998 0, /* tp_call */
4999 0, /* tp_str */
5000 0, /* tp_getattro */
5001 0, /* tp_setattro */
5002 0, /* tp_as_buffer */
5003 #if PY_MAJOR_VERSION < 3
5004 Py_TPFLAGS_HAVE_RICHCOMPARE |
5005 #endif
5006 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
5007 "Base RW Record", /* tp_doc */
5008 0, /* tp_traverse */
5009 0, /* tp_clear */
5010 (richcmpfunc)silkPyRWRec_richcompare, /* tp_richcompare */
5011 0, /* tp_weaklistoffset */
5012 0, /* tp_iter */
5013 0, /* tp_iternext */
5014 silkPyRWRec_methods, /* tp_methods */
5015 0, /* tp_members */
5016 silkPyRWRec_getseters, /* tp_getset */
5017 0, /* tp_base */
5018 0, /* tp_dict */
5019 0, /* tp_descr_get */
5020 0, /* tp_descr_set */
5021 0, /* tp_dictoffset */
5022 (initproc)silkPyRWRec_init, /* tp_init */
5023 0, /* tp_alloc */
5024 silkPyRWRec_new, /* tp_new */
5025 0, /* tp_free */
5026 0, /* tp_is_gc */
5027 0, /* tp_bases */
5028 0, /* tp_mro */
5029 0, /* tp_cache */
5030 0, /* tp_subclasses */
5031 0, /* tp_weaklist */
5032 0 /* tp_del */
5033 #if PY_VERSION_HEX >= 0x02060000
5034 ,0 /* tp_version_tag */
5035 #endif
5036 #if PY_VERSION_HEX >= 0x03040000
5037 ,0 /* tp_finalize */
5038 #endif
5039 #if PY_VERSION_HEX >= 0x03080000
5040 ,0 /* tp_vectorcall */
5041 ,0 /* tp_print */
5042 #endif
5043 };
5044
5045 /* macro and function defintions */
5046 #define silkPyRawRWRec_Check(op) \
5047 PyObject_TypeCheck(op, &silkPyRawRWRecType)
5048 #define silkPyRWRec_Check(op) \
5049 PyObject_TypeCheck(op, &silkPyRWRecType)
5050
5051 static PyObject *
silkPyRWRec_application_get(silkPyRWRec * obj,void UNUSED (* closure))5052 silkPyRWRec_application_get(
5053 silkPyRWRec *obj,
5054 void UNUSED(*closure))
5055 {
5056 return PyInt_FromLong(rwRecGetApplication(&obj->raw->rec));
5057 }
5058
5059 static int
silkPyRWRec_application_set(silkPyRWRec * obj,PyObject * value,void UNUSED (* closure))5060 silkPyRWRec_application_set(
5061 silkPyRWRec *obj,
5062 PyObject *value,
5063 void UNUSED(*closure))
5064 {
5065 long val;
5066
5067 if (!IS_INT(value)) {
5068 PyErr_SetString(PyExc_TypeError, "Expected an integer");
5069 return -1;
5070 }
5071
5072 val = PyLong_AsLong(value);
5073 if (PyErr_Occurred() || val < 0 || val > (long)UINT16_MAX) {
5074 PyErr_SetString(PyExc_ValueError,
5075 "The application value must be a 16-bit integer");
5076 return -1;
5077 }
5078
5079 rwRecSetApplication(&obj->raw->rec, val);
5080 return 0;
5081 }
5082
5083 static PyObject *
silkPyRWRec_to_ipv4(silkPyRWRec * obj)5084 silkPyRWRec_to_ipv4(
5085 silkPyRWRec *obj)
5086 {
5087 silkPyRawRWRec *copy = (silkPyRawRWRec*)PyObject_CallFunctionObjArgs(
5088 (PyObject *)&silkPyRawRWRecType, obj->raw, NULL);
5089 if (copy == NULL) {
5090 return NULL;
5091 }
5092 #if SK_ENABLE_IPV6
5093 if (rwRecIsIPv6(©->rec) && rwRecConvertToIPv4(©->rec)) {
5094 Py_DECREF(copy);
5095 Py_RETURN_NONE;
5096 }
5097 #endif /* SK_ENABLE_IPV6 */
5098 return (PyObject *)copy;
5099 }
5100
5101 #if SK_ENABLE_IPV6
5102 static PyObject *
silkPyRWRec_to_ipv6(silkPyRWRec * obj)5103 silkPyRWRec_to_ipv6(
5104 silkPyRWRec *obj)
5105 {
5106 silkPyRawRWRec *copy = (silkPyRawRWRec*)PyObject_CallFunctionObjArgs(
5107 (PyObject *)&silkPyRawRWRecType, obj->raw, NULL);
5108 if (copy == NULL) {
5109 return NULL;
5110 }
5111 rwRecConvertToIPv6(©->rec);
5112 return (PyObject *)copy;
5113 }
5114 #endif /* SK_ENABLE_IPV6 */
5115
5116 static PyObject *
silkPyRWRec_bytes_get(silkPyRWRec * obj,void UNUSED (* closure))5117 silkPyRWRec_bytes_get(
5118 silkPyRWRec *obj,
5119 void UNUSED(*closure))
5120 {
5121 return PyLong_FromUnsignedLong(rwRecGetBytes(&obj->raw->rec));
5122 }
5123
5124 static int
silkPyRWRec_bytes_set(silkPyRWRec * obj,PyObject * value,void UNUSED (* closure))5125 silkPyRWRec_bytes_set(
5126 silkPyRWRec *obj,
5127 PyObject *value,
5128 void UNUSED(*closure))
5129 {
5130 unsigned long val;
5131
5132 if (!IS_INT(value)) {
5133 PyErr_SetString(PyExc_TypeError, "Expected an integer");
5134 return -1;
5135 }
5136
5137 val = PyLong_AsUnsignedLong(value);
5138 if (PyErr_Occurred() || val > UINT32_MAX) {
5139 PyErr_SetString(PyExc_ValueError,
5140 "The bytes value must be a 32-bit integer");
5141 return -1;
5142 }
5143
5144 rwRecSetBytes(&obj->raw->rec, val);
5145 return 0;
5146 }
5147
5148 static PyObject *
silkPyRWRec_classname_get(silkPyRWRec * obj,void UNUSED (* closure))5149 silkPyRWRec_classname_get(
5150 silkPyRWRec *obj,
5151 void UNUSED(*closure))
5152 {
5153 char class_name[SK_MAX_STRLEN_FLOWTYPE+1];
5154 sk_flowtype_id_t flowtype = rwRecGetFlowType(&obj->raw->rec);
5155
5156 CHECK_SITE(NULL);
5157
5158 sksiteFlowtypeGetClass(class_name, sizeof(class_name), flowtype);
5159
5160 return PyUnicode_InternFromString(class_name);
5161 }
5162
5163 static PyObject *
silkPyRWRec_classtype_get(silkPyRWRec * obj,void UNUSED (* closure))5164 silkPyRWRec_classtype_get(
5165 silkPyRWRec *obj,
5166 void UNUSED(*closure))
5167 {
5168 char class_name[SK_MAX_STRLEN_FLOWTYPE+1];
5169 char type_name[SK_MAX_STRLEN_FLOWTYPE+1];
5170 sk_flowtype_id_t flowtype = rwRecGetFlowType(&obj->raw->rec);
5171 PyObject *pair = PyTuple_New(2);
5172
5173 if (pair == NULL) {
5174 return NULL;
5175 }
5176
5177 CHECK_SITE(NULL);
5178
5179 sksiteFlowtypeGetClass(class_name, sizeof(class_name), flowtype);
5180 sksiteFlowtypeGetType(type_name, sizeof(type_name), flowtype);
5181
5182 PyTuple_SET_ITEM(pair, 0, PyUnicode_InternFromString(class_name));
5183 PyTuple_SET_ITEM(pair, 1, PyUnicode_InternFromString(type_name));
5184
5185 return pair;
5186 }
5187
5188 static PyObject *
silkPyRWRec_classtype_id_get(silkPyRWRec * obj,void UNUSED (* closure))5189 silkPyRWRec_classtype_id_get(
5190 silkPyRWRec *obj,
5191 void UNUSED(*closure))
5192 {
5193 return PyInt_FromLong(rwRecGetFlowType(&obj->raw->rec));
5194 }
5195
5196 static int
silkPyRWRec_classtype_id_set(silkPyRWRec * obj,PyObject * value,void UNUSED (* closure))5197 silkPyRWRec_classtype_id_set(
5198 silkPyRWRec *obj,
5199 PyObject *value,
5200 void UNUSED(*closure))
5201 {
5202 long val;
5203
5204 if (!IS_INT(value)) {
5205 PyErr_SetString(PyExc_TypeError, "Expected an integer");
5206 return -1;
5207 }
5208
5209 val = PyLong_AsLong(value);
5210 if (PyErr_Occurred() || val < 0 || val > (long)UINT8_MAX) {
5211 PyErr_SetString(PyExc_ValueError,
5212 "The classtype_id value must be an 8-bit integer");
5213 return -1;
5214 }
5215
5216 rwRecSetFlowType(&obj->raw->rec, val);
5217 return 0;
5218 }
5219
5220 static int
silkPyRWRec_classtype_set(silkPyRWRec * obj,PyObject * value,void UNUSED (* closure))5221 silkPyRWRec_classtype_set(
5222 silkPyRWRec *obj,
5223 PyObject *value,
5224 void UNUSED(*closure))
5225 {
5226 char *class_name, *type_name;
5227 sk_flowtype_id_t flowtype;
5228
5229
5230 if (!PyArg_ParseTuple(value, "ss", &class_name, &type_name)) {
5231 return -1;
5232 }
5233
5234 CHECK_SITE(-1);
5235
5236 flowtype = sksiteFlowtypeLookupByClassType(class_name, type_name);
5237
5238 if (flowtype == SK_INVALID_FLOWTYPE) {
5239 PyErr_SetString(PyExc_ValueError, "Invalid (class_name, type) pair");
5240 return -1;
5241 }
5242
5243 rwRecSetFlowType(&obj->raw->rec, flowtype);
5244 return 0;
5245 }
5246
5247 static void
silkPyRWRec_dealloc(silkPyRWRec * obj)5248 silkPyRWRec_dealloc(
5249 silkPyRWRec *obj)
5250 {
5251 Py_XDECREF((PyObject*)obj->raw);
5252 Py_TYPE(obj)->tp_free(obj);
5253 }
5254
5255 static PyObject *
silkPyRWRec_dip_get(silkPyRWRec * obj,void UNUSED (* closure))5256 silkPyRWRec_dip_get(
5257 silkPyRWRec *obj,
5258 void UNUSED(*closure))
5259 {
5260 silkPyIPAddr *addr;
5261 PyTypeObject *type;
5262
5263 #if SK_ENABLE_IPV6
5264 if (rwRecIsIPv6(&obj->raw->rec)) {
5265 type = &silkPyIPv6AddrType;
5266 } else
5267 #endif
5268 {
5269 type = &silkPyIPv4AddrType;
5270 }
5271
5272 addr = PyObject_New(silkPyIPAddr, type);
5273 if (addr != NULL) {
5274 rwRecMemGetDIP(&obj->raw->rec, &addr->addr);
5275 }
5276
5277 return (PyObject*)addr;
5278 }
5279
5280 static int
silkPyRWRec_dip_set(silkPyRWRec * obj,PyObject * value,void UNUSED (* closure))5281 silkPyRWRec_dip_set(
5282 silkPyRWRec *obj,
5283 PyObject *value,
5284 void UNUSED(*closure))
5285 {
5286 if (IS_STRING(value)) {
5287 skipaddr_t addr;
5288 PyObject *bytes;
5289 char *repr;
5290 int rv;
5291
5292 bytes = bytes_from_string(value);
5293 if (bytes == NULL) {
5294 return -1;
5295 }
5296 repr = PyBytes_AS_STRING(bytes);
5297 rv = skStringParseIP(&addr, repr);
5298 if (rv != 0) {
5299 PyErr_Format(PyExc_ValueError, "Illegal IP address: %s", repr);
5300 Py_DECREF(bytes);
5301 return -1;
5302 }
5303 Py_DECREF(bytes);
5304 rwRecMemSetDIP(&obj->raw->rec, &addr);
5305 return 0;
5306 }
5307
5308 if (silkPyIPAddr_Check(value)) {
5309 silkPyIPAddr *addr = (silkPyIPAddr*)value;
5310 rwRecMemSetDIP(&obj->raw->rec, &addr->addr);
5311 return 0;
5312 }
5313
5314 PyErr_SetString(PyExc_TypeError, "The dip must be a valid IP address");
5315 return -1;
5316 }
5317
5318 static PyObject *
silkPyRWRec_dport_get(silkPyRWRec * obj,void UNUSED (* closure))5319 silkPyRWRec_dport_get(
5320 silkPyRWRec *obj,
5321 void UNUSED(*closure))
5322 {
5323 return PyInt_FromLong(rwRecGetDPort(&obj->raw->rec));
5324 }
5325
5326 static int
silkPyRWRec_dport_set(silkPyRWRec * obj,PyObject * value,void UNUSED (* closure))5327 silkPyRWRec_dport_set(
5328 silkPyRWRec *obj,
5329 PyObject *value,
5330 void UNUSED(*closure))
5331 {
5332 long val;
5333
5334 if (!IS_INT(value)) {
5335 PyErr_SetString(PyExc_TypeError, "Expected an integer");
5336 return -1;
5337 }
5338
5339 val = PyLong_AsLong(value);
5340 if (PyErr_Occurred() || val < 0 || val > (long)UINT16_MAX) {
5341 PyErr_SetString(PyExc_ValueError,
5342 "The dport value must be a 16-bit integer");
5343 return -1;
5344 }
5345
5346 rwRecSetDPort(&obj->raw->rec, val);
5347 return 0;
5348 }
5349
5350 static PyObject *
silkPyRWRec_duration_get(silkPyRWRec * obj,void UNUSED (* closure))5351 silkPyRWRec_duration_get(
5352 silkPyRWRec *obj,
5353 void UNUSED(*closure))
5354 {
5355 return PyObject_CallFunction(GLOBALS->timedelta, "IIII", 0, 0, 0,
5356 rwRecGetElapsed(&obj->raw->rec));
5357 }
5358
5359 static PyObject *
silkPyRWRec_duration_secs_get(silkPyRWRec * obj,void UNUSED (* closure))5360 silkPyRWRec_duration_secs_get(
5361 silkPyRWRec *obj,
5362 void UNUSED(*closure))
5363 {
5364 double elapsed = ((double)rwRecGetElapsed(&obj->raw->rec)) / 1.0e3;
5365
5366 return PyFloat_FromDouble(elapsed);
5367 }
5368
5369 static int
silkPyRWRec_duration_secs_set(silkPyRWRec * obj,PyObject * value,void UNUSED (* closure))5370 silkPyRWRec_duration_secs_set(
5371 silkPyRWRec *obj,
5372 PyObject *value,
5373 void UNUSED(*closure))
5374 {
5375 const char *errstr = ("The duration_secs value must be a positive "
5376 "number not greater than 4294967.295");
5377 PyObject *pyfloat_val;
5378 PyObject *pyint_val;
5379 int64_t long_val;
5380
5381 if (!PyNumber_Check(value)) {
5382 PyErr_SetString(PyExc_TypeError, errstr);
5383 return -1;
5384 }
5385
5386 pyfloat_val = PyNumber_Multiply(value, GLOBALS->thousand);
5387 if (pyfloat_val == NULL) {
5388 return -1;
5389 }
5390
5391 pyint_val = PyNumber_Long(pyfloat_val);
5392 Py_DECREF(pyfloat_val);
5393 if (pyint_val == NULL) {
5394 return -1;
5395 }
5396 long_val = PyLong_AsLongLong(pyint_val);
5397 Py_DECREF(pyint_val);
5398 if (long_val < 0) {
5399 PyErr_SetString(PyExc_ValueError, errstr);
5400 return -1;
5401 }
5402
5403 if (long_val > UINT32_MAX) {
5404 PyErr_SetString(PyExc_ValueError,
5405 ("The total duration must be not greater than "
5406 "4294967.295 seconds"));
5407 return -1;
5408 }
5409
5410 rwRecSetElapsed(&obj->raw->rec, long_val);
5411 return 0;
5412 }
5413
5414 static int
silkPyRWRec_duration_set(silkPyRWRec * obj,PyObject * value,void UNUSED (* closure))5415 silkPyRWRec_duration_set(
5416 silkPyRWRec *obj,
5417 PyObject *value,
5418 void UNUSED(*closure))
5419 {
5420 PyObject *days;
5421 PyObject *secs;
5422 PyObject *usecs;
5423 uint32_t millisecs;
5424
5425 if (!PyDelta_Check(value)) {
5426 PyErr_SetString(PyExc_TypeError,
5427 "The duration value must be a datetime.timedelta");
5428 return -1;
5429 }
5430 if (PyObject_RichCompareBool(value, GLOBALS->minelapsed, Py_LT) ||
5431 PyObject_RichCompareBool(value, GLOBALS->maxelapsed, Py_GT))
5432 {
5433 PyErr_SetString(PyExc_ValueError,
5434 ("The duration must be in the range [0,4294967295] "
5435 "milliseconds"));
5436 return -1;
5437 }
5438 days = PyObject_GetAttrString(value, "days");
5439 secs = PyObject_GetAttrString(value, "seconds");
5440 usecs = PyObject_GetAttrString(value, "microseconds");
5441 millisecs = PyLong_AsLong(days) * 1000 * 3600 * 24 +
5442 PyLong_AsLong(secs) * 1000 +
5443 PyLong_AsLong(usecs) / 1000;
5444 Py_DECREF(secs);
5445 Py_DECREF(usecs);
5446
5447 rwRecSetElapsed(&obj->raw->rec, millisecs);
5448 return 0;
5449 }
5450
5451 static PyObject *
silkPyRWRec_etime_epoch_secs_get(silkPyRWRec * obj,void UNUSED (* closure))5452 silkPyRWRec_etime_epoch_secs_get(
5453 silkPyRWRec *obj,
5454 void UNUSED(*closure))
5455 {
5456 double duration = (double)(rwRecGetStartTime(&obj->raw->rec) +
5457 rwRecGetElapsed(&obj->raw->rec)) / 1.0e3;
5458
5459 return PyFloat_FromDouble(duration);
5460 }
5461
5462 static int
silkPyRWRec_etime_epoch_secs_set(silkPyRWRec * obj,PyObject * value,void UNUSED (* closure))5463 silkPyRWRec_etime_epoch_secs_set(
5464 silkPyRWRec *obj,
5465 PyObject *value,
5466 void UNUSED(*closure))
5467 {
5468 PyObject *s_time, *dur;
5469 int retval;
5470
5471 s_time = silkPyRWRec_stime_epoch_secs_get(obj, NULL);
5472 if (s_time == NULL) {
5473 return -1;
5474 }
5475
5476 if (PyObject_RichCompareBool(value, s_time, Py_LT)) {
5477 PyErr_SetString(PyExc_ValueError,
5478 "etime may not be less than stime");
5479 Py_DECREF(s_time);
5480 return -1;
5481 }
5482 dur = PyNumber_Subtract(value, s_time);
5483 Py_DECREF(s_time);
5484 if (dur == NULL) {
5485 return -1;
5486 }
5487
5488 retval = silkPyRWRec_duration_secs_set(obj, dur, NULL);
5489 Py_DECREF(dur);
5490
5491 return retval;
5492 }
5493
5494 static PyObject *
silkPyRWRec_etime_get(silkPyRWRec * obj,void UNUSED (* closure))5495 silkPyRWRec_etime_get(
5496 silkPyRWRec *obj,
5497 void UNUSED(*closure))
5498 {
5499 PyObject *s_time, *dur;
5500 PyObject *retval;
5501
5502 s_time = silkPyRWRec_stime_get(obj, NULL);
5503 if (s_time == NULL) {
5504 return NULL;
5505 }
5506 dur = silkPyRWRec_duration_get(obj, NULL);
5507 if (dur == NULL) {
5508 Py_DECREF(s_time);
5509 return NULL;
5510 }
5511
5512 retval = PyNumber_Add(s_time, dur);
5513
5514 Py_DECREF(s_time);
5515 Py_DECREF(dur);
5516
5517 return retval;
5518 }
5519
5520 static int
silkPyRWRec_etime_set(silkPyRWRec * obj,PyObject * value,void UNUSED (* closure))5521 silkPyRWRec_etime_set(
5522 silkPyRWRec *obj,
5523 PyObject *value,
5524 void UNUSED(*closure))
5525 {
5526 PyObject *s_time, *dur;
5527 int retval;
5528
5529 s_time = silkPyRWRec_stime_get(obj, NULL);
5530 if (s_time == NULL) {
5531 return -1;
5532 }
5533
5534 if (PyObject_RichCompareBool(value, s_time, Py_LT)) {
5535 PyErr_SetString(PyExc_ValueError,
5536 "etime may not be less than stime");
5537 Py_DECREF(s_time);
5538 return -1;
5539 }
5540 dur = PyNumber_Subtract(value, s_time);
5541 Py_DECREF(s_time);
5542 if (dur == NULL) {
5543 return -1;
5544 }
5545
5546 retval = silkPyRWRec_duration_set(obj, dur, NULL);
5547 Py_DECREF(dur);
5548
5549 return retval;
5550 }
5551
5552 static PyObject *
silkPyRWRec_finnoack_get(silkPyRWRec * obj,void UNUSED (* closure))5553 silkPyRWRec_finnoack_get(
5554 silkPyRWRec *obj,
5555 void UNUSED(*closure))
5556 {
5557 uint8_t state;
5558
5559 state = rwRecGetTcpState(&obj->raw->rec);
5560 return PyBool_FromLong(state & SK_TCPSTATE_FIN_FOLLOWED_NOT_ACK);
5561 }
5562
5563 static int
silkPyRWRec_finnoack_set(silkPyRWRec * obj,PyObject * value,void UNUSED (* closure))5564 silkPyRWRec_finnoack_set(
5565 silkPyRWRec *obj,
5566 PyObject *value,
5567 void UNUSED(*closure))
5568 {
5569 int rv;
5570 uint8_t state;
5571
5572 rv = PyObject_IsTrue(value);
5573 if (rv == -1) {
5574 return -1;
5575 }
5576 state = rwRecGetTcpState(&obj->raw->rec);
5577 if (rv) {
5578 state |= SK_TCPSTATE_FIN_FOLLOWED_NOT_ACK;
5579 } else {
5580 state &= ~SK_TCPSTATE_FIN_FOLLOWED_NOT_ACK;
5581 }
5582 rwRecSetTcpState(&obj->raw->rec, state);
5583
5584 return 0;
5585 }
5586
5587 static PyObject *
silkPyRWRec_icmpcode_get(silkPyRWRec * obj,void UNUSED (* closure))5588 silkPyRWRec_icmpcode_get(
5589 silkPyRWRec *obj,
5590 void UNUSED(*closure))
5591 {
5592 return PyInt_FromLong(rwRecGetIcmpCode(&obj->raw->rec));
5593 }
5594
5595 static int
silkPyRWRec_icmpcode_set(silkPyRWRec * obj,PyObject * value,void UNUSED (* closure))5596 silkPyRWRec_icmpcode_set(
5597 silkPyRWRec *obj,
5598 PyObject *value,
5599 void UNUSED(*closure))
5600 {
5601 long val;
5602
5603 if (!IS_INT(value)) {
5604 PyErr_SetString(PyExc_TypeError, "Expected an integer");
5605 return -1;
5606 }
5607
5608 val = PyLong_AsLong(value);
5609 if (PyErr_Occurred() || val < 0 || val > (long)UINT8_MAX) {
5610 PyErr_SetString(PyExc_ValueError,
5611 "The icmpcode value must be a 8-bit integer");
5612 return -1;
5613 }
5614
5615 rwRecSetIcmpCode(&obj->raw->rec, (uint8_t)val);
5616 return 0;
5617 }
5618
5619 static PyObject *
silkPyRWRec_icmptype_get(silkPyRWRec * obj,void UNUSED (* closure))5620 silkPyRWRec_icmptype_get(
5621 silkPyRWRec *obj,
5622 void UNUSED(*closure))
5623 {
5624 return PyInt_FromLong(rwRecGetIcmpType(&obj->raw->rec));
5625 }
5626
5627 static int
silkPyRWRec_icmptype_set(silkPyRWRec * obj,PyObject * value,void UNUSED (* closure))5628 silkPyRWRec_icmptype_set(
5629 silkPyRWRec *obj,
5630 PyObject *value,
5631 void UNUSED(*closure))
5632 {
5633 long val;
5634
5635 if (!IS_INT(value)) {
5636 PyErr_SetString(PyExc_TypeError, "Expected an integer");
5637 return -1;
5638 }
5639
5640 val = PyLong_AsLong(value);
5641 if (PyErr_Occurred() || val < 0 || val > (long)UINT8_MAX) {
5642 PyErr_SetString(PyExc_ValueError,
5643 "The icmptype value must be a 8-bit integer");
5644 return -1;
5645 }
5646
5647 rwRecSetIcmpType(&obj->raw->rec, (uint8_t)val);
5648 return 0;
5649 }
5650
5651 static PyObject *
silkPyRWRec_new(PyTypeObject * type,PyObject UNUSED (* args),PyObject UNUSED (* kwds))5652 silkPyRWRec_new(
5653 PyTypeObject *type,
5654 PyObject UNUSED(*args),
5655 PyObject UNUSED(*kwds))
5656 {
5657 silkPyRWRec *self;
5658 PyObject *newrawrec = GLOBALS->newrawrec;
5659
5660 self = (silkPyRWRec *)type->tp_alloc(type, 0);
5661 if (self != NULL) {
5662 self->raw = (silkPyRawRWRec *)newrawrec;
5663 Py_INCREF(newrawrec);
5664 }
5665 return (PyObject *)self;
5666 }
5667
5668 static int
silkPyRWRec_init(silkPyRWRec * self,PyObject * args,PyObject * kwds)5669 silkPyRWRec_init(
5670 silkPyRWRec *self,
5671 PyObject *args,
5672 PyObject *kwds)
5673 {
5674 static char *kwlist[] = {"clone", "copy", NULL};
5675 silkPyRawRWRec *clne = NULL;
5676 silkPyRWRec *copy = NULL;
5677
5678 if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O!O!", kwlist,
5679 &silkPyRawRWRecType, (PyObject **)&clne,
5680 &silkPyRWRecType, (PyObject **)©))
5681 {
5682 return -1;
5683 }
5684
5685 if (clne && copy) {
5686 PyErr_SetString(PyExc_RuntimeError, "Cannot clone and copy");
5687 return -1;
5688 }
5689
5690 Py_XDECREF((PyObject*)self->raw);
5691 if (clne) {
5692 Py_INCREF(clne);
5693 self->raw = clne;
5694 } else if (copy) {
5695 self->raw = (silkPyRawRWRec*)PyObject_CallFunctionObjArgs(
5696 (PyObject*)&silkPyRawRWRecType, copy->raw, NULL);
5697 } else {
5698 self->raw = (silkPyRawRWRec*)PyObject_CallFunctionObjArgs(
5699 (PyObject*)&silkPyRawRWRecType, NULL);
5700 }
5701
5702 if (self->raw == NULL) {
5703 return -1;
5704 }
5705
5706 return 0;
5707 }
5708
5709 static PyObject *
silkPyRWRec_initial_tcpflags_get(silkPyRWRec * obj,void * deprecated)5710 silkPyRWRec_initial_tcpflags_get(
5711 silkPyRWRec *obj,
5712 void *deprecated)
5713 {
5714 silkPyTCPFlags *flags;
5715
5716 if (deprecated == deprecated_true) {
5717 /* Deprecated in SiLK 3.0.0 */
5718 int rv = PyErr_Warn(PyExc_DeprecationWarning,
5719 ("'initflags' is deprecated in favor of"
5720 " 'initial_tcpflags'."));
5721 if (rv) {
5722 return NULL;
5723 }
5724 }
5725
5726 if (!(rwRecGetTcpState(&obj->raw->rec) & SK_TCPSTATE_EXPANDED)) {
5727 Py_RETURN_NONE;
5728 }
5729 flags = (silkPyTCPFlags*)silkPyTCPFlagsType.tp_alloc(&silkPyTCPFlagsType,
5730 0);
5731 if (flags != NULL) {
5732 flags->val = rwRecGetInitFlags(&obj->raw->rec);
5733 }
5734
5735 return (PyObject*)flags;
5736 }
5737
5738 static int
silkPyRWRec_initial_tcpflags_set(silkPyRWRec * obj,PyObject * value,void * deprecated)5739 silkPyRWRec_initial_tcpflags_set(
5740 silkPyRWRec *obj,
5741 PyObject *value,
5742 void *deprecated)
5743 {
5744 uint8_t state;
5745 uint8_t flagval;
5746 silkPyTCPFlags *flags;
5747
5748 if (deprecated == deprecated_true) {
5749 /* Deprecated in SiLK 3.0.0 */
5750 int rv = PyErr_Warn(PyExc_DeprecationWarning,
5751 ("'initflags' is deprecated in favor of"
5752 " 'initial_tcpflags'."));
5753 if (rv) {
5754 return -1;
5755 }
5756 }
5757
5758 if (rwRecGetProto(&obj->raw->rec) != IPPROTO_TCP) {
5759 PyErr_SetString(
5760 PyExc_AttributeError,
5761 "Cannot set initial_tcpflags when protocol is not TCP");
5762 return -1;
5763 }
5764
5765 flags = (silkPyTCPFlags *)PyObject_CallFunctionObjArgs(
5766 (PyObject *)&silkPyTCPFlagsType, value, NULL);
5767 if (flags == NULL) {
5768 return -1;
5769 }
5770 flagval = flags->val;
5771 Py_DECREF(flags);
5772
5773 state = rwRecGetTcpState(&obj->raw->rec);
5774 rwRecSetInitFlags(&obj->raw->rec, flagval);
5775 if (! (state & SK_TCPSTATE_EXPANDED)) {
5776 rwRecSetTcpState(&obj->raw->rec, state | SK_TCPSTATE_EXPANDED);
5777 rwRecSetRestFlags(&obj->raw->rec, 0);
5778 }
5779 rwRecSetFlags(&obj->raw->rec, rwRecGetRestFlags(&obj->raw->rec) | flagval);
5780 return 0;
5781 }
5782
5783 static PyObject *
silkPyRWRec_input_get(silkPyRWRec * obj,void UNUSED (* closure))5784 silkPyRWRec_input_get(
5785 silkPyRWRec *obj,
5786 void UNUSED(*closure))
5787 {
5788 return PyInt_FromLong(rwRecGetInput(&obj->raw->rec));
5789 }
5790
5791 static int
silkPyRWRec_input_set(silkPyRWRec * obj,PyObject * value,void UNUSED (* closure))5792 silkPyRWRec_input_set(
5793 silkPyRWRec *obj,
5794 PyObject *value,
5795 void UNUSED(*closure))
5796 {
5797 long val;
5798
5799 if (!IS_INT(value)) {
5800 PyErr_SetString(PyExc_TypeError, "Expected an integer");
5801 return -1;
5802 }
5803
5804 val = PyLong_AsLong(value);
5805 if (PyErr_Occurred() || val < 0 || val > (long)UINT16_MAX) {
5806 PyErr_SetString(PyExc_ValueError,
5807 "The input value must be a 16-bit integer");
5808 return -1;
5809 }
5810
5811 rwRecSetInput(&obj->raw->rec, val);
5812 return 0;
5813 }
5814
5815 static PyObject *
silkPyRWRec_is_icmp(silkPyRWRec * obj)5816 silkPyRWRec_is_icmp(
5817 silkPyRWRec *obj)
5818 {
5819 return PyBool_FromLong(rwRecIsICMP(&obj->raw->rec));
5820 }
5821
5822 static PyObject *
silkPyRWRec_is_ipv6(silkPyRWRec UNUSED_NOv6 (* obj))5823 silkPyRWRec_is_ipv6(
5824 silkPyRWRec UNUSED_NOv6(*obj))
5825 {
5826 return PyBool_FromLong(rwRecIsIPv6(&obj->raw->rec));
5827 }
5828
5829 static PyObject *
silkPyRWRec_is_web(silkPyRWRec * obj)5830 silkPyRWRec_is_web(
5831 silkPyRWRec *obj)
5832 {
5833 return PyBool_FromLong(rwRecIsWeb(&obj->raw->rec));
5834 }
5835
5836 static PyObject *
silkPyRWRec_nhip_get(silkPyRWRec * obj,void UNUSED (* closure))5837 silkPyRWRec_nhip_get(
5838 silkPyRWRec *obj,
5839 void UNUSED(*closure))
5840 {
5841 silkPyIPAddr *addr;
5842 PyTypeObject *type;
5843
5844 #if SK_ENABLE_IPV6
5845 if (rwRecIsIPv6(&obj->raw->rec)) {
5846 type = &silkPyIPv6AddrType;
5847 } else
5848 #endif
5849 {
5850 type = &silkPyIPv4AddrType;
5851 }
5852
5853 addr = PyObject_New(silkPyIPAddr, type);
5854 if (addr != NULL) {
5855 rwRecMemGetNhIP(&obj->raw->rec, &addr->addr);
5856 }
5857 return (PyObject*)addr;
5858 }
5859
5860 static int
silkPyRWRec_nhip_set(silkPyRWRec * obj,PyObject * value,void UNUSED (* closure))5861 silkPyRWRec_nhip_set(
5862 silkPyRWRec *obj,
5863 PyObject *value,
5864 void UNUSED(*closure))
5865 {
5866 if (IS_STRING(value)) {
5867 skipaddr_t addr;
5868 PyObject *bytes;
5869 char *repr;
5870 int rv;
5871
5872 bytes = bytes_from_string(value);
5873 if (bytes == NULL) {
5874 return -1;
5875 }
5876 repr = PyBytes_AS_STRING(bytes);
5877 rv = skStringParseIP(&addr, repr);
5878 if (rv != 0) {
5879 PyErr_Format(PyExc_ValueError, "Illegal IP address: %s", repr);
5880 Py_DECREF(bytes);
5881 return -1;
5882 }
5883 Py_DECREF(bytes);
5884 rwRecMemSetNhIP(&obj->raw->rec, &addr);
5885 return 0;
5886 }
5887
5888 if (silkPyIPAddr_Check(value)) {
5889 silkPyIPAddr *addr = (silkPyIPAddr*)value;
5890 rwRecMemSetNhIP(&obj->raw->rec, &addr->addr);
5891 return 0;
5892 }
5893
5894 PyErr_SetString(PyExc_TypeError, "The nhip must be a valid IP address");
5895 return -1;
5896 }
5897
5898 static PyObject *
silkPyRWRec_output_get(silkPyRWRec * obj,void UNUSED (* closure))5899 silkPyRWRec_output_get(
5900 silkPyRWRec *obj,
5901 void UNUSED(*closure))
5902 {
5903 return PyInt_FromLong(rwRecGetOutput(&obj->raw->rec));
5904 }
5905
5906 static int
silkPyRWRec_output_set(silkPyRWRec * obj,PyObject * value,void UNUSED (* closure))5907 silkPyRWRec_output_set(
5908 silkPyRWRec *obj,
5909 PyObject *value,
5910 void UNUSED(*closure))
5911 {
5912 long val;
5913
5914 if (!IS_INT(value)) {
5915 PyErr_SetString(PyExc_TypeError, "Expected an integer");
5916 return -1;
5917 }
5918
5919 val = PyLong_AsLong(value);
5920 if (PyErr_Occurred() || val < 0 || val > (long)UINT16_MAX) {
5921 PyErr_SetString(PyExc_ValueError,
5922 "The output value must be a 16-bit integer");
5923 return -1;
5924 }
5925
5926 rwRecSetOutput(&obj->raw->rec, val);
5927 return 0;
5928 }
5929
5930 static PyObject *
silkPyRWRec_packets_get(silkPyRWRec * obj,void UNUSED (* closure))5931 silkPyRWRec_packets_get(
5932 silkPyRWRec *obj,
5933 void UNUSED(*closure))
5934 {
5935 return PyLong_FromUnsignedLong(rwRecGetPkts(&obj->raw->rec));
5936 }
5937
5938 static int
silkPyRWRec_packets_set(silkPyRWRec * obj,PyObject * value,void UNUSED (* closure))5939 silkPyRWRec_packets_set(
5940 silkPyRWRec *obj,
5941 PyObject *value,
5942 void UNUSED(*closure))
5943 {
5944 unsigned long val;
5945
5946 if (!IS_INT(value)) {
5947 PyErr_SetString(PyExc_TypeError, "Expected an integer");
5948 return -1;
5949 }
5950
5951 val = PyLong_AsUnsignedLong(value);
5952 if (PyErr_Occurred() || val > UINT32_MAX) {
5953 PyErr_SetString(PyExc_ValueError,
5954 "The packets value must be a 32-bit integer");
5955 return -1;
5956 }
5957
5958 rwRecSetPkts(&obj->raw->rec, val);
5959 return 0;
5960 }
5961
5962 static PyObject *
silkPyRWRec_protocol_get(silkPyRWRec * obj,void UNUSED (* closure))5963 silkPyRWRec_protocol_get(
5964 silkPyRWRec *obj,
5965 void UNUSED(*closure))
5966 {
5967 return PyInt_FromLong(rwRecGetProto(&obj->raw->rec));
5968 }
5969
5970 static int
silkPyRWRec_protocol_set(silkPyRWRec * obj,PyObject * value,void UNUSED (* closure))5971 silkPyRWRec_protocol_set(
5972 silkPyRWRec *obj,
5973 PyObject *value,
5974 void UNUSED(*closure))
5975 {
5976 long val;
5977
5978 if (!IS_INT(value)) {
5979 PyErr_SetString(PyExc_TypeError, "Expected an integer");
5980 return -1;
5981 }
5982
5983 val = PyLong_AsLong(value);
5984 if (PyErr_Occurred() || val < 0 || val > (long)UINT8_MAX) {
5985 PyErr_SetString(PyExc_ValueError,
5986 "The protocol value must be an 8-bit integer");
5987 return -1;
5988 }
5989
5990 rwRecSetProto(&obj->raw->rec, val);
5991 if (val != IPPROTO_TCP) {
5992 /* Initial and session flags are not allowed for non-TCP. */
5993 uint8_t state = rwRecGetTcpState(&obj->raw->rec);
5994 rwRecSetTcpState(&obj->raw->rec, state & ~SK_TCPSTATE_EXPANDED);
5995 rwRecSetInitFlags(&obj->raw->rec, 0);
5996 rwRecSetRestFlags(&obj->raw->rec, 0);
5997 }
5998 return 0;
5999 }
6000
6001 static PyObject *
silkPyRWRec_richcompare(silkPyRWRec * self,PyObject * obj,int cmp)6002 silkPyRWRec_richcompare(
6003 silkPyRWRec *self,
6004 PyObject *obj,
6005 int cmp)
6006 {
6007 int rv;
6008
6009 if ((cmp != Py_EQ && cmp != Py_NE) ||
6010 !silkPyRWRec_Check(obj))
6011 {
6012 Py_INCREF(Py_NotImplemented);
6013 return Py_NotImplemented;
6014 }
6015
6016 rv = memcmp(&self->raw->rec, &((silkPyRWRec*)obj)->raw->rec,
6017 sizeof(self->raw->rec));
6018 rv = (rv == 0) ? 1 : 0;
6019 if (cmp == Py_NE) {
6020 rv = !rv;
6021 }
6022
6023 return PyBool_FromLong(rv);
6024 }
6025
6026 static PyObject *
silkPyRWRec_sensor_get(silkPyRWRec * obj,void UNUSED (* closure))6027 silkPyRWRec_sensor_get(
6028 silkPyRWRec *obj,
6029 void UNUSED(*closure))
6030 {
6031 char name[SK_MAX_STRLEN_SENSOR+1];
6032
6033 CHECK_SITE(NULL);
6034
6035 sksiteSensorGetName(name, sizeof(name), rwRecGetSensor(&obj->raw->rec));
6036 return PyUnicode_InternFromString(name);
6037 }
6038
6039 static PyObject *
silkPyRWRec_sensor_id_get(silkPyRWRec * obj,void UNUSED (* closure))6040 silkPyRWRec_sensor_id_get(
6041 silkPyRWRec *obj,
6042 void UNUSED(*closure))
6043 {
6044 return PyInt_FromLong(rwRecGetSensor(&obj->raw->rec));
6045 }
6046
6047 static int
silkPyRWRec_sensor_id_set(silkPyRWRec * obj,PyObject * value,void UNUSED (* closure))6048 silkPyRWRec_sensor_id_set(
6049 silkPyRWRec *obj,
6050 PyObject *value,
6051 void UNUSED(*closure))
6052 {
6053 long val;
6054
6055 if (!IS_INT(value)) {
6056 PyErr_SetString(PyExc_TypeError, "Expected an integer");
6057 return -1;
6058 }
6059
6060 val = PyLong_AsLong(value);
6061 if (PyErr_Occurred() || val < 0 || val > (long)UINT16_MAX) {
6062 PyErr_SetString(PyExc_ValueError,
6063 "The sensor_id value must be a 16-bit integer");
6064 return -1;
6065 }
6066
6067 rwRecSetSensor(&obj->raw->rec, val);
6068 return 0;
6069 }
6070
6071 static int
silkPyRWRec_sensor_set(silkPyRWRec * obj,PyObject * value,void UNUSED (* closure))6072 silkPyRWRec_sensor_set(
6073 silkPyRWRec *obj,
6074 PyObject *value,
6075 void UNUSED(*closure))
6076 {
6077 char *repr;
6078 sk_sensor_id_t sensor;
6079 PyObject *bytes;
6080
6081 bytes = bytes_from_string(value);
6082 if (bytes == NULL) {
6083 PyErr_SetString(PyExc_TypeError, "The sensor value must be a string");
6084 return -1;
6085 }
6086 repr = PyBytes_AS_STRING(bytes);
6087
6088 if (init_site(NULL)) {
6089 Py_DECREF(bytes);
6090 return -1;
6091 }
6092
6093 sensor = sksiteSensorLookup(repr);
6094 Py_DECREF(bytes);
6095 if (sensor == SK_INVALID_SENSOR) {
6096 PyErr_SetString(PyExc_ValueError, "Invalid sensor name");
6097 return -1;
6098 }
6099
6100 rwRecSetSensor(&obj->raw->rec, sensor);
6101 return 0;
6102 }
6103
6104 static PyObject *
silkPyRWRec_session_tcpflags_get(silkPyRWRec * obj,void * deprecated)6105 silkPyRWRec_session_tcpflags_get(
6106 silkPyRWRec *obj,
6107 void *deprecated)
6108 {
6109 silkPyTCPFlags *flags;
6110
6111 if (deprecated == deprecated_true) {
6112 /* Deprecated in SiLK 3.0.0 */
6113 int rv = PyErr_Warn(PyExc_DeprecationWarning,
6114 ("'restflags' is deprecated in favor of"
6115 " 'session_tcpflags'."));
6116 if (rv) {
6117 return NULL;
6118 }
6119 }
6120
6121 if (!(rwRecGetTcpState(&obj->raw->rec) & SK_TCPSTATE_EXPANDED)) {
6122 Py_RETURN_NONE;
6123 }
6124 flags = (silkPyTCPFlags*)silkPyTCPFlagsType.tp_alloc(&silkPyTCPFlagsType,
6125 0);
6126 if (flags != NULL) {
6127 flags->val = rwRecGetRestFlags(&obj->raw->rec);
6128 }
6129
6130 return (PyObject*)flags;
6131 }
6132
6133 static int
silkPyRWRec_session_tcpflags_set(silkPyRWRec * obj,PyObject * value,void * deprecated)6134 silkPyRWRec_session_tcpflags_set(
6135 silkPyRWRec *obj,
6136 PyObject *value,
6137 void *deprecated)
6138 {
6139 uint8_t state;
6140 uint8_t flagval;
6141 silkPyTCPFlags *flags;
6142
6143 if (deprecated == deprecated_true) {
6144 /* Deprecated in SiLK 3.0.0 */
6145 int rv = PyErr_Warn(PyExc_DeprecationWarning,
6146 ("'restflags' is deprecated in favor of"
6147 " 'session_tcpflags'."));
6148 if (rv) {
6149 return -1;
6150 }
6151 }
6152
6153 if (rwRecGetProto(&obj->raw->rec) != IPPROTO_TCP) {
6154 PyErr_SetString(
6155 PyExc_AttributeError,
6156 "Cannot set session_tcpflags when protocol is not TCP");
6157 return -1;
6158 }
6159
6160 flags = (silkPyTCPFlags *)PyObject_CallFunctionObjArgs(
6161 (PyObject *)&silkPyTCPFlagsType, value, NULL);
6162 if (flags == NULL) {
6163 return -1;
6164 }
6165 flagval = flags->val;
6166 Py_DECREF(flags);
6167
6168 state = rwRecGetTcpState(&obj->raw->rec);
6169 rwRecSetRestFlags(&obj->raw->rec, flagval);
6170 if (! (state & SK_TCPSTATE_EXPANDED)) {
6171 rwRecSetTcpState(&obj->raw->rec, state | SK_TCPSTATE_EXPANDED);
6172 rwRecSetInitFlags(&obj->raw->rec, 0);
6173 }
6174 rwRecSetFlags(&obj->raw->rec, rwRecGetInitFlags(&obj->raw->rec) | flagval);
6175 return 0;
6176 }
6177
6178 static PyObject *
silkPyRWRec_sip_get(silkPyRWRec * obj,void UNUSED (* closure))6179 silkPyRWRec_sip_get(
6180 silkPyRWRec *obj,
6181 void UNUSED(*closure))
6182 {
6183 silkPyIPAddr *addr;
6184 PyTypeObject *type;
6185
6186 #if SK_ENABLE_IPV6
6187 if (rwRecIsIPv6(&obj->raw->rec)) {
6188 type = &silkPyIPv6AddrType;
6189 } else
6190 #endif
6191 {
6192 type = &silkPyIPv4AddrType;
6193 }
6194
6195 addr = PyObject_New(silkPyIPAddr, type);
6196 if (addr != NULL) {
6197 rwRecMemGetSIP(&obj->raw->rec, &addr->addr);
6198 }
6199 return (PyObject*)addr;
6200 }
6201
6202 static int
silkPyRWRec_sip_set(silkPyRWRec * obj,PyObject * value,void UNUSED (* closure))6203 silkPyRWRec_sip_set(
6204 silkPyRWRec *obj,
6205 PyObject *value,
6206 void UNUSED(*closure))
6207 {
6208 if (IS_STRING(value)) {
6209 skipaddr_t addr;
6210 PyObject *bytes;
6211 char *repr;
6212 int rv;
6213
6214 bytes = bytes_from_string(value);
6215 if (bytes == NULL) {
6216 return -1;
6217 }
6218 repr = PyBytes_AS_STRING(bytes);
6219 rv = skStringParseIP(&addr, repr);
6220 if (rv != 0) {
6221 PyErr_Format(PyExc_ValueError, "Illegal IP address: %s", repr);
6222 Py_DECREF(bytes);
6223 return -1;
6224 }
6225 Py_DECREF(bytes);
6226 rwRecMemSetSIP(&obj->raw->rec, &addr);
6227 return 0;
6228 }
6229
6230 if (silkPyIPAddr_Check(value)) {
6231 silkPyIPAddr *addr = (silkPyIPAddr*)value;
6232 rwRecMemSetSIP(&obj->raw->rec, &addr->addr);
6233 return 0;
6234 }
6235
6236 PyErr_SetString(PyExc_TypeError, "The sip must be a valid IP address");
6237 return -1;
6238 }
6239
6240 static PyObject *
silkPyRWRec_sport_get(silkPyRWRec * obj,void UNUSED (* closure))6241 silkPyRWRec_sport_get(
6242 silkPyRWRec *obj,
6243 void UNUSED(*closure))
6244 {
6245 return PyInt_FromLong(rwRecGetSPort(&obj->raw->rec));
6246 }
6247
6248 static int
silkPyRWRec_sport_set(silkPyRWRec * obj,PyObject * value,void UNUSED (* closure))6249 silkPyRWRec_sport_set(
6250 silkPyRWRec *obj,
6251 PyObject *value,
6252 void UNUSED(*closure))
6253 {
6254 long val;
6255
6256 if (!IS_INT(value)) {
6257 PyErr_SetString(PyExc_TypeError, "Expected an integer");
6258 return -1;
6259 }
6260
6261 val = PyLong_AsLong(value);
6262 if (PyErr_Occurred() || val < 0 || val > (long)UINT16_MAX) {
6263 PyErr_SetString(PyExc_ValueError,
6264 "The sport value must be a 16-bit integer");
6265 return -1;
6266 }
6267
6268 rwRecSetSPort(&obj->raw->rec, val);
6269 return 0;
6270 }
6271
6272 static PyObject *
silkPyRWRec_stime_epoch_secs_get(silkPyRWRec * obj,void UNUSED (* closure))6273 silkPyRWRec_stime_epoch_secs_get(
6274 silkPyRWRec *obj,
6275 void UNUSED(*closure))
6276 {
6277 double s_time = ((double)rwRecGetStartTime(&obj->raw->rec)) / 1.0e3;
6278
6279 return PyFloat_FromDouble(s_time);
6280 }
6281
6282 static int
silkPyRWRec_stime_epoch_secs_set(silkPyRWRec * obj,PyObject * value,void UNUSED (* closure))6283 silkPyRWRec_stime_epoch_secs_set(
6284 silkPyRWRec *obj,
6285 PyObject *value,
6286 void UNUSED(*closure))
6287 {
6288 const char *errstr = ("The stime_epoch_secs value must be a "
6289 "positive number");
6290 PyObject *pyfloat_val;
6291 PyObject *pyint_val;
6292 int64_t long_val;
6293
6294 if (!PyNumber_Check(value)) {
6295 PyErr_SetString(PyExc_TypeError, errstr);
6296 return -1;
6297 }
6298
6299 pyfloat_val = PyNumber_Multiply(value, GLOBALS->thousand);
6300 if (pyfloat_val == NULL) {
6301 return -1;
6302 }
6303
6304 pyint_val = PyNumber_Long(pyfloat_val);
6305 Py_DECREF(pyfloat_val);
6306 if (pyint_val == NULL) {
6307 PyErr_SetString(PyExc_TypeError, errstr);
6308 return -1;
6309 }
6310 long_val = PyLong_AsLongLong(pyint_val);
6311 Py_DECREF(pyint_val);
6312 if (long_val < 0) {
6313 PyErr_SetString(PyExc_ValueError, errstr);
6314 return -1;
6315 }
6316 if (long_val > MAX_EPOCH) {
6317 PyErr_SetString(PyExc_ValueError,
6318 "Maximum stime is 03:14:07, Jan 19, 2038");
6319 return -1;
6320 }
6321
6322 rwRecSetStartTime(&obj->raw->rec, long_val);
6323 return 0;
6324 }
6325
6326 static PyObject *
silkPyRWRec_stime_get(silkPyRWRec * obj,void UNUSED (* closure))6327 silkPyRWRec_stime_get(
6328 silkPyRWRec *obj,
6329 void UNUSED(*closure))
6330 {
6331 PyObject *delta;
6332 PyObject *final;
6333 imaxdiv_t d = imaxdiv(rwRecGetStartTime(&obj->raw->rec), 1000);
6334
6335 delta = PyObject_CallFunction(GLOBALS->timedelta, "ILIL",
6336 0, d.quot, 0, d.rem);
6337 if (delta == NULL) {
6338 return NULL;
6339 }
6340 final = PyNumber_Add(GLOBALS->epochtime, delta);
6341 Py_DECREF(delta);
6342 return final;
6343 }
6344
6345 static int
silkPyRWRec_stime_set(silkPyRWRec * obj,PyObject * value,void UNUSED (* closure))6346 silkPyRWRec_stime_set(
6347 silkPyRWRec *obj,
6348 PyObject *value,
6349 void UNUSED(*closure))
6350 {
6351 sktime_t t;
6352 int rv;
6353
6354 rv = silkPyDatetimeToSktime(&t, value);
6355
6356 if (rv == 0) {
6357 rwRecSetStartTime(&obj->raw->rec, t);
6358 }
6359 return rv;
6360 }
6361
6362 static PyObject *
silkPyRWRec_tcpflags_get(silkPyRWRec * obj,void UNUSED (* closure))6363 silkPyRWRec_tcpflags_get(
6364 silkPyRWRec *obj,
6365 void UNUSED(*closure))
6366 {
6367 silkPyTCPFlags *flags;
6368
6369 flags = (silkPyTCPFlags*)silkPyTCPFlagsType.tp_alloc(&silkPyTCPFlagsType,
6370 0);
6371 if (flags != NULL) {
6372 flags->val = rwRecGetFlags(&obj->raw->rec);
6373 }
6374
6375 return (PyObject*)flags;
6376 }
6377
6378 static int
silkPyRWRec_tcpflags_set(silkPyRWRec * obj,PyObject * value,void UNUSED (* closure))6379 silkPyRWRec_tcpflags_set(
6380 silkPyRWRec *obj,
6381 PyObject *value,
6382 void UNUSED(*closure))
6383 {
6384 uint8_t flagval;
6385 uint8_t state;
6386 silkPyTCPFlags *flags;
6387
6388 state = rwRecGetTcpState(&obj->raw->rec) & ~SK_TCPSTATE_EXPANDED;
6389
6390 flags = (silkPyTCPFlags *)PyObject_CallFunctionObjArgs(
6391 (PyObject *)&silkPyTCPFlagsType, value, NULL);
6392 if (flags == NULL) {
6393 return -1;
6394 }
6395 flagval = flags->val;
6396 Py_DECREF(flags);
6397
6398 rwRecSetFlags(&obj->raw->rec, flagval);
6399 rwRecSetInitFlags(&obj->raw->rec, 0);
6400 rwRecSetInitFlags(&obj->raw->rec, 0);
6401 rwRecSetTcpState(&obj->raw->rec, state);
6402 return 0;
6403 }
6404
6405 static PyObject *
silkPyRWRec_timeout_killed_get(silkPyRWRec * obj,void UNUSED (* closure))6406 silkPyRWRec_timeout_killed_get(
6407 silkPyRWRec *obj,
6408 void UNUSED(*closure))
6409 {
6410 uint8_t state;
6411
6412 state = rwRecGetTcpState(&obj->raw->rec);
6413 return PyBool_FromLong(state & SK_TCPSTATE_TIMEOUT_KILLED);
6414 }
6415
6416 static int
silkPyRWRec_timeout_killed_set(silkPyRWRec * obj,PyObject * value,void UNUSED (* closure))6417 silkPyRWRec_timeout_killed_set(
6418 silkPyRWRec *obj,
6419 PyObject *value,
6420 void UNUSED(*closure))
6421 {
6422 int rv;
6423 uint8_t state;
6424
6425 rv = PyObject_IsTrue(value);
6426 if (rv == -1) {
6427 return -1;
6428 }
6429 state = rwRecGetTcpState(&obj->raw->rec);
6430 if (rv) {
6431 state |= SK_TCPSTATE_TIMEOUT_KILLED;
6432 } else {
6433 state &= ~SK_TCPSTATE_TIMEOUT_KILLED;
6434 }
6435 rwRecSetTcpState(&obj->raw->rec, state);
6436
6437 return 0;
6438 }
6439
6440 static PyObject *
silkPyRWRec_timeout_started_get(silkPyRWRec * obj,void UNUSED (* closure))6441 silkPyRWRec_timeout_started_get(
6442 silkPyRWRec *obj,
6443 void UNUSED(*closure))
6444 {
6445 uint8_t state;
6446
6447 state = rwRecGetTcpState(&obj->raw->rec);
6448 return PyBool_FromLong(state & SK_TCPSTATE_TIMEOUT_STARTED);
6449 }
6450
6451 static int
silkPyRWRec_timeout_started_set(silkPyRWRec * obj,PyObject * value,void UNUSED (* closure))6452 silkPyRWRec_timeout_started_set(
6453 silkPyRWRec *obj,
6454 PyObject *value,
6455 void UNUSED(*closure))
6456 {
6457 int rv;
6458 uint8_t state;
6459
6460 rv = PyObject_IsTrue(value);
6461 if (rv == -1) {
6462 return -1;
6463 }
6464 state = rwRecGetTcpState(&obj->raw->rec);
6465 if (rv) {
6466 state |= SK_TCPSTATE_TIMEOUT_STARTED;
6467 } else {
6468 state &= ~SK_TCPSTATE_TIMEOUT_STARTED;
6469 }
6470 rwRecSetTcpState(&obj->raw->rec, state);
6471
6472 return 0;
6473 }
6474
6475 static PyObject *
silkPyRWRec_typename_get(silkPyRWRec * obj,void UNUSED (* closure))6476 silkPyRWRec_typename_get(
6477 silkPyRWRec *obj,
6478 void UNUSED(*closure))
6479 {
6480 char type_name[SK_MAX_STRLEN_FLOWTYPE+1];
6481 sk_flowtype_id_t flowtype = rwRecGetFlowType(&obj->raw->rec);
6482
6483 CHECK_SITE(NULL);
6484
6485 sksiteFlowtypeGetType(type_name, sizeof(type_name), flowtype);
6486 return PyUnicode_InternFromString(type_name);
6487 }
6488
6489 static PyObject *
silkPyRWRec_uniform_packets_get(silkPyRWRec * obj,void UNUSED (* closure))6490 silkPyRWRec_uniform_packets_get(
6491 silkPyRWRec *obj,
6492 void UNUSED(*closure))
6493 {
6494 uint8_t state;
6495
6496 state = rwRecGetTcpState(&obj->raw->rec);
6497 return PyBool_FromLong(state & SK_TCPSTATE_UNIFORM_PACKET_SIZE);
6498 }
6499
6500 static int
silkPyRWRec_uniform_packets_set(silkPyRWRec * obj,PyObject * value,void UNUSED (* closure))6501 silkPyRWRec_uniform_packets_set(
6502 silkPyRWRec *obj,
6503 PyObject *value,
6504 void UNUSED(*closure))
6505 {
6506 int rv;
6507 uint8_t state;
6508
6509 rv = PyObject_IsTrue(value);
6510 if (rv == -1) {
6511 return -1;
6512 }
6513 state = rwRecGetTcpState(&obj->raw->rec);
6514 if (rv) {
6515 state |= SK_TCPSTATE_UNIFORM_PACKET_SIZE;
6516 } else {
6517 state &= ~SK_TCPSTATE_UNIFORM_PACKET_SIZE;
6518 }
6519 rwRecSetTcpState(&obj->raw->rec, state);
6520
6521 return 0;
6522 }
6523
6524 static int
silkPyRawRWRec_init(silkPyRawRWRec * self,PyObject * args,PyObject * kwds)6525 silkPyRawRWRec_init(
6526 silkPyRawRWRec *self,
6527 PyObject *args,
6528 PyObject *kwds)
6529 {
6530 static char *kwlist[] = {"rec", NULL};
6531 PyObject *copy = NULL;
6532
6533 if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O!", kwlist,
6534 &silkPyRawRWRecType, ©))
6535 {
6536 return -1;
6537 }
6538
6539 if (copy) {
6540 RWREC_COPY(&self->rec, &((silkPyRawRWRec*)copy)->rec);
6541 }
6542 return 0;
6543 }
6544
6545 static PyObject *
silkPyRawRWRec_new(PyTypeObject * type,PyObject UNUSED (* args),PyObject UNUSED (* kwds))6546 silkPyRawRWRec_new(
6547 PyTypeObject *type,
6548 PyObject UNUSED(*args),
6549 PyObject UNUSED(*kwds))
6550 {
6551 silkPyRawRWRec *self;
6552
6553 self = (silkPyRawRWRec*)type->tp_alloc(type, 0);
6554
6555 if (self != NULL) {
6556 RWREC_CLEAR(&self->rec);
6557 }
6558
6559 return (PyObject*)self;
6560 }
6561
6562
6563 /*
6564 *************************************************************************
6565 * SiLK File
6566 *************************************************************************
6567 */
6568
6569 typedef struct silkPySilkFile_st {
6570 PyObject_HEAD
6571 skstream_t *io;
6572 } silkPySilkFile;
6573
6574 /* function prototypes */
6575 static PyObject *
6576 silkPySilkFile_close(
6577 silkPySilkFile *obj);
6578 static void
6579 silkPySilkFile_dealloc(
6580 silkPySilkFile *obj);
6581 static PyObject *
6582 silkPySilkFile_get_mode(
6583 silkPySilkFile *obj,
6584 void UNUSED(*closure));
6585 static PyObject *
6586 silkPySilkFile_get_name(
6587 silkPySilkFile *obj,
6588 void UNUSED(*closure));
6589 static int
6590 silkPySilkFile_init(
6591 silkPySilkFile *self,
6592 PyObject *args,
6593 PyObject *kwds);
6594 static PyObject *
6595 silkPySilkFile_invocations(
6596 silkPySilkFile *obj);
6597 static PyObject *
6598 silkPySilkFile_notes(
6599 silkPySilkFile *obj);
6600 static PyObject *
6601 silkPySilkFile_read(
6602 silkPySilkFile *obj);
6603 static PyObject *
6604 silkPySilkFile_write(
6605 silkPySilkFile *obj,
6606 PyObject *rec);
6607 static PyObject *
6608 silkPySilkFile_skip(
6609 silkPySilkFile *obj,
6610 PyObject *value);
6611
6612 /* define docs and methods */
6613 static PyMethodDef silkPySilkFile_methods[] = {
6614 {"__reduce__", (PyCFunction)reduce_error, METH_NOARGS, ""},
6615 {"read", (PyCFunction)silkPySilkFile_read, METH_NOARGS,
6616 "Read a RWRec from a RW File"},
6617 {"write", (PyCFunction)silkPySilkFile_write, METH_O,
6618 "Write a RWRec to a RW File"},
6619 {"skip", (PyCFunction)silkPySilkFile_skip, METH_O,
6620 "Skip some number of RWRecs in a RW File;"
6621 " return number of records skipped"},
6622 {"close", (PyCFunction)silkPySilkFile_close, METH_NOARGS,
6623 "Close an RW File"},
6624 {"notes", (PyCFunction)silkPySilkFile_notes, METH_NOARGS,
6625 "Get the file's annotations"},
6626 {"invocations", (PyCFunction)silkPySilkFile_invocations, METH_NOARGS,
6627 "Get the file's invocations"},
6628 {NULL, NULL, 0, NULL} /* Sentinel */
6629 };
6630
6631 static PyGetSetDef silkPySilkFile_getseters[] = {
6632 {"name", (getter)silkPySilkFile_get_name, NULL,
6633 "name of file associated with SilkFile", NULL},
6634 {"mode", (getter)silkPySilkFile_get_mode, NULL,
6635 "mode associated with SilkFile", NULL},
6636 {NULL, NULL, NULL, NULL, NULL} /* Sentinel */
6637 };
6638
6639 /* define the object types */
6640 static PyTypeObject silkPySilkFileType = {
6641 PyVarObject_HEAD_INIT(NULL, 0)
6642 "silk.pysilk.SilkFileBase", /* tp_name */
6643 sizeof(silkPySilkFile), /* tp_basicsize */
6644 0, /* tp_itemsize */
6645 (destructor)silkPySilkFile_dealloc, /* tp_dealloc */
6646 0, /* tp_vectorcall_offset (Py 3.8) */
6647 0, /* tp_getattr */
6648 0, /* tp_setattr */
6649 0, /* tp_as_async (tp_compare in Py2.x) */
6650 0, /* tp_repr */
6651 0, /* tp_as_number */
6652 0, /* tp_as_sequence */
6653 0, /* tp_as_mapping */
6654 0, /* tp_hash */
6655 0, /* tp_call */
6656 0, /* tp_str */
6657 0, /* tp_getattro */
6658 0, /* tp_setattro */
6659 0, /* tp_as_buffer */
6660 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
6661 "Base Silk File", /* tp_doc */
6662 0, /* tp_traverse */
6663 0, /* tp_clear */
6664 0, /* tp_richcompare */
6665 0, /* tp_weaklistoffset */
6666 0, /* tp_iter */
6667 0, /* tp_iternext */
6668 silkPySilkFile_methods, /* tp_methods */
6669 0, /* tp_members */
6670 silkPySilkFile_getseters, /* tp_getset */
6671 0, /* tp_base */
6672 0, /* tp_dict */
6673 0, /* tp_descr_get */
6674 0, /* tp_descr_set */
6675 0, /* tp_dictoffset */
6676 (initproc)silkPySilkFile_init, /* tp_init */
6677 0, /* tp_alloc */
6678 0, /* tp_new */
6679 0, /* tp_free */
6680 0, /* tp_is_gc */
6681 0, /* tp_bases */
6682 0, /* tp_mro */
6683 0, /* tp_cache */
6684 0, /* tp_subclasses */
6685 0, /* tp_weaklist */
6686 0 /* tp_del */
6687 #if PY_VERSION_HEX >= 0x02060000
6688 ,0 /* tp_version_tag */
6689 #endif
6690 #if PY_VERSION_HEX >= 0x03040000
6691 ,0 /* tp_finalize */
6692 #endif
6693 #if PY_VERSION_HEX >= 0x03080000
6694 ,0 /* tp_vectorcall */
6695 ,0 /* tp_print */
6696 #endif
6697 };
6698
6699 /* macro and function defintions */
6700 #define silkPySilkFile_Check(op) \
6701 PyObject_TypeCheck(op, &silkPySilkFileType)
6702
6703 static PyObject *
throw_ioerror(silkPySilkFile * obj,int errcode)6704 throw_ioerror(
6705 silkPySilkFile *obj,
6706 int errcode)
6707 {
6708 skStreamPrintLastErr(obj->io, errcode, error_printf);
6709 PyErr_SetString(PyExc_IOError, error_buffer);
6710 return NULL;
6711 }
6712
6713 static PyObject *
silkPySilkFile_close(silkPySilkFile * obj)6714 silkPySilkFile_close(
6715 silkPySilkFile *obj)
6716 {
6717 int rv;
6718
6719 rv = skStreamClose(obj->io);
6720 if (rv == 0) {
6721 Py_RETURN_NONE;
6722 }
6723
6724 return throw_ioerror(obj, rv);
6725 }
6726
6727 static void
silkPySilkFile_dealloc(silkPySilkFile * obj)6728 silkPySilkFile_dealloc(
6729 silkPySilkFile *obj)
6730 {
6731 if (obj->io) {
6732 skStreamDestroy(&obj->io);
6733 }
6734 Py_TYPE(obj)->tp_free(obj);
6735 }
6736
6737 static PyObject *
silkPySilkFile_get_mode(silkPySilkFile * obj,void UNUSED (* closure))6738 silkPySilkFile_get_mode(
6739 silkPySilkFile *obj,
6740 void UNUSED(*closure))
6741 {
6742 return PyInt_FromLong(skStreamGetMode(obj->io));
6743 }
6744
6745 static PyObject *
silkPySilkFile_get_name(silkPySilkFile * obj,void UNUSED (* closure))6746 silkPySilkFile_get_name(
6747 silkPySilkFile *obj,
6748 void UNUSED(*closure))
6749 {
6750 const char *name = skStreamGetPathname(obj->io);
6751 if (name) {
6752 return PyUnicode_FromString(name);
6753 }
6754 Py_RETURN_NONE;
6755 }
6756
6757 static int
silkPySilkFile_init(silkPySilkFile * self,PyObject * args,PyObject * kwds)6758 silkPySilkFile_init(
6759 silkPySilkFile *self,
6760 PyObject *args,
6761 PyObject *kwds)
6762 {
6763 char *filename;
6764 int mode;
6765 int format = NOT_SET;
6766 int policy = NOT_SET;
6767 int compr = NOT_SET;
6768 int file_des = NOT_SET;
6769 PyObject *annotations = NULL;
6770 PyObject *invocations = NULL;
6771 sk_file_header_t *hdr;
6772 int rv;
6773
6774 static char *kwlist[] = {"filename", "mode", "compression",
6775 "format", "policy", "invocations",
6776 "notes", "_fileno", NULL};
6777
6778 if (!PyArg_ParseTupleAndKeywords(args, kwds, "si|iiiO!O!i", kwlist,
6779 &filename, &mode, &compr,
6780 &format, &policy,
6781 &PyList_Type, &invocations,
6782 &PyList_Type, &annotations,
6783 &file_des))
6784 {
6785 return -1;
6786 }
6787
6788 if (mode != SK_IO_READ && mode != SK_IO_WRITE && mode != SK_IO_APPEND) {
6789 PyErr_SetString(PyExc_ValueError, "Illegal mode");
6790 Py_DECREF(self);
6791 return -1;
6792 }
6793 if (self->io) {
6794 skStreamDestroy(&self->io);
6795 }
6796 rv = skStreamCreate(&self->io, (skstream_mode_t)mode,SK_CONTENT_SILK_FLOW);
6797 if (rv != 0) {
6798 throw_ioerror(self, rv);
6799 return -1;
6800 }
6801
6802 rv = skStreamBind(self->io, filename);
6803 if (rv != 0) {
6804 throw_ioerror(self, rv);
6805 return -1;
6806 }
6807
6808 hdr = skStreamGetSilkHeader(self->io);
6809
6810 if (policy != NOT_SET) {
6811 rv = skStreamSetIPv6Policy(self->io, (sk_ipv6policy_t)policy);
6812 if (rv != 0) {
6813 throw_ioerror(self, rv);
6814 return -1;
6815 }
6816 }
6817
6818 if (compr != NOT_SET) {
6819 if (mode != SK_IO_WRITE) {
6820 PyErr_SetString(PyExc_ValueError,
6821 "Cannot set compression unless in WRITE mode");
6822 return -1;
6823 }
6824 rv = skHeaderSetCompressionMethod(hdr, compr);
6825 if (rv != 0) {
6826 throw_ioerror(self, rv);
6827 return -1;
6828 }
6829 }
6830
6831 if (format != NOT_SET) {
6832 if (mode != SK_IO_WRITE) {
6833 PyErr_SetString(PyExc_ValueError,
6834 "Cannot set file format unless in WRITE mode");
6835 return -1;
6836 }
6837 rv = skHeaderSetFileFormat(hdr, format);
6838 if (rv != 0) {
6839 throw_ioerror(self, rv);
6840 return -1;
6841 }
6842 }
6843
6844 if (annotations != NULL) {
6845 if (mode != SK_IO_WRITE) {
6846 PyErr_SetString(PyExc_ValueError,
6847 "Cannot set annotations unless in WRITE mode");
6848 return -1;
6849 }
6850 if (hdr != NULL) {
6851 ssize_t len = PyList_GET_SIZE(annotations);
6852 ssize_t i;
6853
6854 for (i = 0; i < len; i++) {
6855 PyObject *bytes;
6856 PyObject *item = PyList_GET_ITEM(annotations, i);
6857
6858 if (!IS_STRING(item)) {
6859 PyErr_SetString(PyExc_TypeError,
6860 "Annotation was not a string");
6861 return -1;
6862 }
6863 bytes = bytes_from_string(item);
6864 if (bytes == NULL) {
6865 return -1;
6866 }
6867
6868 rv = skHeaderAddAnnotation(hdr, PyBytes_AS_STRING(bytes));
6869 Py_DECREF(bytes);
6870 if (rv != 0) {
6871 throw_ioerror(self, rv);
6872 }
6873 }
6874 }
6875 }
6876
6877 if (invocations != NULL) {
6878 if (mode != SK_IO_WRITE) {
6879 PyErr_SetString(PyExc_ValueError,
6880 "Cannot set invocations unless in WRITE mode");
6881 return -1;
6882 }
6883 if (hdr != NULL) {
6884 ssize_t len = PyList_GET_SIZE(invocations);
6885 ssize_t i;
6886
6887 for (i = 0; i < len; i++) {
6888 PyObject *item = PyList_GET_ITEM(invocations, i);
6889 char *value;
6890 PyObject *bytes;
6891
6892 if (!IS_STRING(item)) {
6893 PyErr_SetString(PyExc_TypeError,
6894 "Invocation was not a string");
6895 return -1;
6896 }
6897
6898 bytes = bytes_from_string(item);
6899 if (bytes == NULL) {
6900 return -1;
6901 }
6902 value = PyBytes_AS_STRING(bytes);
6903 rv = skHeaderAddInvocation(hdr, 0, 1, &value);
6904 Py_DECREF(bytes);
6905 if (rv != 0) {
6906 throw_ioerror(self, rv);
6907 }
6908 }
6909 }
6910 }
6911
6912 if (file_des == NOT_SET) {
6913 rv = skStreamOpen(self->io);
6914 } else {
6915 rv = skStreamFDOpen(self->io, file_des);
6916 }
6917 if (rv != 0) {
6918 throw_ioerror(self, rv);
6919 return -1;
6920 }
6921
6922 if (mode == SK_IO_WRITE) {
6923 rv = skStreamWriteSilkHeader(self->io);
6924 if (rv != 0) {
6925 throw_ioerror(self, rv);
6926 return -1;
6927 }
6928 } else {
6929 rv = skStreamReadSilkHeader(self->io, NULL);
6930 if (rv != 0) {
6931 throw_ioerror(self, rv);
6932 return -1;
6933 }
6934 }
6935
6936 return 0;
6937 }
6938
6939 static PyObject *
silkPySilkFile_invocations(silkPySilkFile * obj)6940 silkPySilkFile_invocations(
6941 silkPySilkFile *obj)
6942 {
6943 sk_file_header_t *hdr;
6944 sk_header_entry_t *entry;
6945 sk_hentry_iterator_t iter;
6946 PyObject *list;
6947 PyObject *invoc;
6948 int rv;
6949
6950 list = PyList_New(0);
6951 if (list == NULL) {
6952 return NULL;
6953 }
6954 hdr = skStreamGetSilkHeader(obj->io);
6955 if (hdr != NULL) {
6956 skHeaderIteratorBindType(&iter, hdr, SK_HENTRY_INVOCATION_ID);
6957 while ((entry = skHeaderIteratorNext(&iter)) != NULL) {
6958 invoc = PyUnicode_FromString(
6959 skHentryInvocationGetInvocation(entry));
6960 if (invoc == NULL) {
6961 Py_DECREF(list);
6962 return NULL;
6963 }
6964 rv = PyList_Append(list, invoc);
6965 Py_DECREF(invoc);
6966 if (rv != 0) {
6967 Py_DECREF(list);
6968 return NULL;
6969 }
6970 }
6971 }
6972
6973 return list;
6974 }
6975
6976 static PyObject *
silkPySilkFile_notes(silkPySilkFile * obj)6977 silkPySilkFile_notes(
6978 silkPySilkFile *obj)
6979 {
6980 sk_file_header_t *hdr;
6981 sk_header_entry_t *entry;
6982 sk_hentry_iterator_t iter;
6983 PyObject *list;
6984 PyObject *annot;
6985 int rv;
6986
6987 list = PyList_New(0);
6988 if (list == NULL) {
6989 return NULL;
6990 }
6991 hdr = skStreamGetSilkHeader(obj->io);
6992 if (hdr != NULL) {
6993 skHeaderIteratorBindType(&iter, hdr, SK_HENTRY_ANNOTATION_ID);
6994 while ((entry = skHeaderIteratorNext(&iter)) != NULL) {
6995 annot = PyUnicode_FromString(
6996 skHentryAnnotationGetNote(entry));
6997 if (annot == NULL) {
6998 Py_DECREF(list);
6999 return NULL;
7000 }
7001 rv = PyList_Append(list, annot);
7002 Py_DECREF(annot);
7003 if (rv != 0) {
7004 Py_DECREF(list);
7005 return NULL;
7006 }
7007 }
7008 }
7009
7010 return list;
7011 }
7012
7013 static PyObject *
silkPySilkFile_read(silkPySilkFile * obj)7014 silkPySilkFile_read(
7015 silkPySilkFile *obj)
7016 {
7017 PyObject *pyrec;
7018 int rv;
7019
7020 pyrec = silkPyRawRWRecType.tp_alloc(&silkPyRawRWRecType, 0);
7021 if (pyrec == NULL) {
7022 return NULL;
7023 }
7024
7025 rv = skStreamReadRecord(obj->io, &((silkPyRawRWRec*)pyrec)->rec);
7026 if (rv != 0) {
7027 Py_DECREF(pyrec);
7028 if (rv == SKSTREAM_ERR_EOF) {
7029 Py_RETURN_NONE;
7030 }
7031 return throw_ioerror(obj, rv);
7032 }
7033
7034 return pyrec;
7035 }
7036
7037 static PyObject *
silkPySilkFile_write(silkPySilkFile * obj,PyObject * rec)7038 silkPySilkFile_write(
7039 silkPySilkFile *obj,
7040 PyObject *rec)
7041 {
7042 int rv;
7043
7044 if (!silkPyRWRec_Check(rec)) {
7045 PyErr_SetString(PyExc_TypeError, "Argument not a RWRec");
7046 return NULL;
7047 }
7048
7049 rv = skStreamWriteRecord(obj->io, &((silkPyRWRec*)rec)->raw->rec);
7050 if (rv == 0) {
7051 Py_RETURN_NONE;
7052 }
7053
7054 return throw_ioerror(obj, rv);
7055 }
7056
7057 static PyObject *
silkPySilkFile_skip(silkPySilkFile * obj,PyObject * value)7058 silkPySilkFile_skip(
7059 silkPySilkFile *obj,
7060 PyObject *value)
7061 {
7062 size_t skipped = 0;
7063 uint64_t val;
7064 int rv;
7065
7066 if (!IS_INT(value)) {
7067 PyErr_SetString(PyExc_TypeError, "Expected an integer");
7068 return NULL;
7069 }
7070
7071 val = LONG_AS_UNSIGNED_LONGLONG(value);
7072 if (PyErr_Occurred()) {
7073 return NULL;
7074 }
7075
7076 rv = skStreamSkipRecords(obj->io, val, &skipped);
7077 if (rv == 0 || rv == SKSTREAM_ERR_EOF) {
7078 return PyLong_FromUnsignedLongLong(skipped);
7079 }
7080
7081 return throw_ioerror(obj, rv);
7082 }
7083
7084
7085 /*
7086 *************************************************************************
7087 * RepoIter
7088 *************************************************************************
7089 */
7090
7091 typedef struct silkPyRepoIter_st {
7092 PyObject_HEAD
7093 sksite_repo_iter_t *iter;
7094 } silkPyRepoIter;
7095
7096 /* function prototypes */
7097 static void
7098 silkPyRepoIter_dealloc(
7099 silkPyRepoIter *self);
7100 static int
7101 silkPyRepoIter_init(
7102 silkPyRepoIter *self,
7103 PyObject *args,
7104 PyObject *kwds);
7105 static PyObject *
7106 silkPyRepoIter_iternext(
7107 silkPyRepoIter *self);
7108
7109 /* define the object types */
7110 static PyTypeObject silkPyRepoIterType ={
7111 PyVarObject_HEAD_INIT(NULL, 0)
7112 "silk.pysilk.RepoIter", /* tp_name */
7113 sizeof(silkPyRepoIterType), /* tp_basicsize */
7114 0, /* tp_itemsize */
7115 (destructor)silkPyRepoIter_dealloc, /* tp_dealloc */
7116 0, /* tp_vectorcall_offset (Py 3.8) */
7117 0, /* tp_getattr */
7118 0, /* tp_setattr */
7119 0, /* tp_as_async (tp_compare in Py2.x) */
7120 0, /* tp_repr */
7121 0, /* tp_as_number */
7122 0, /* tp_as_sequence */
7123 0, /* tp_as_mapping */
7124 0, /* tp_hash */
7125 0, /* tp_call */
7126 0, /* tp_str */
7127 0, /* tp_getattro */
7128 0, /* tp_setattro */
7129 0, /* tp_as_buffer */
7130 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
7131 "SiLK repo file iterator object", /* tp_doc */
7132 0, /* tp_traverse */
7133 0, /* tp_clear */
7134 0, /* tp_richcompare */
7135 0, /* tp_weaklistoffset */
7136 iter_iter, /* tp_iter */
7137 (iternextfunc)silkPyRepoIter_iternext, /* tp_iternext */
7138 0, /* tp_methods */
7139 0, /* tp_members */
7140 0, /* tp_getset */
7141 0, /* tp_base */
7142 0, /* tp_dict */
7143 0, /* tp_descr_get */
7144 0, /* tp_descr_set */
7145 0, /* tp_dictoffset */
7146 (initproc)silkPyRepoIter_init, /* tp_init */
7147 0, /* tp_alloc */
7148 0, /* tp_new */
7149 0, /* tp_free */
7150 0, /* tp_is_gc */
7151 0, /* tp_bases */
7152 0, /* tp_mro */
7153 0, /* tp_cache */
7154 0, /* tp_subclasses */
7155 0, /* tp_weaklist */
7156 0 /* tp_del */
7157 #if PY_VERSION_HEX >= 0x02060000
7158 ,0 /* tp_version_tag */
7159 #endif
7160 #if PY_VERSION_HEX >= 0x03040000
7161 ,0 /* tp_finalize */
7162 #endif
7163 #if PY_VERSION_HEX >= 0x03080000
7164 ,0 /* tp_vectorcall */
7165 ,0 /* tp_print */
7166 #endif
7167 };
7168
7169 /* macro and function defintions */
7170 #define silkPyRepoIter_Check(op) \
7171 PyObject_TypeCheck(op, &silkPyRepoIterType)
7172
7173 static void
silkPyRepoIter_dealloc(silkPyRepoIter * self)7174 silkPyRepoIter_dealloc(
7175 silkPyRepoIter *self)
7176 {
7177 sksiteRepoIteratorDestroy(&self->iter);
7178 Py_TYPE(self)->tp_free((PyObject*)self);
7179 }
7180
7181 static int
silkPyRepoIter_init(silkPyRepoIter * self,PyObject * args,PyObject * kwds)7182 silkPyRepoIter_init(
7183 silkPyRepoIter *self,
7184 PyObject *args,
7185 PyObject *kwds)
7186 {
7187 static char *kwlist[] = {"start", "end", "flowtypes",
7188 "sensors", "missing", NULL};
7189 PyObject *start = NULL;
7190 PyObject *end = NULL;
7191 PyObject *flowtypes = NULL;
7192 PyObject *sensors = NULL;
7193 PyObject *missing = NULL;
7194 PyObject *fast = NULL;
7195 sk_vector_t *ft_vec = NULL;
7196 sk_vector_t *sensor_vec = NULL;
7197 sktime_t starttime, endtime;
7198 sk_flowtype_iter_t ft_iter;
7199 sk_flowtype_id_t ft;
7200 uint32_t flags;
7201 unsigned int start_precision;
7202 unsigned int end_precision;
7203 int rv;
7204
7205 CHECK_SITE(-1);
7206
7207 ft_vec = skVectorNew(sizeof(sk_flowtype_id_t));
7208 if (ft_vec == NULL) {
7209 PyErr_NoMemory();
7210 return -1;
7211 }
7212
7213 if (!PyArg_ParseTupleAndKeywords(args, kwds, "OO|OOO", kwlist,
7214 &start, &end, &flowtypes,
7215 &sensors, &missing))
7216 {
7217 goto error;
7218 }
7219
7220 /* Calculate starttime */
7221 if (PyDate_Check(start)) {
7222 rv = silkPyDatetimeToSktime(&starttime, start);
7223 if (rv != 0) {
7224 goto error;
7225 }
7226 start_precision = (PyDateTime_Check(start)
7227 ? SK_PARSED_DATETIME_HOUR
7228 : SK_PARSED_DATETIME_DAY);
7229 } else if (IS_STRING(start)) {
7230 PyObject *bytes = bytes_from_string(start);
7231 if (bytes == NULL) {
7232 goto error;
7233 }
7234 rv = skStringParseDatetime(&starttime, PyBytes_AS_STRING(bytes),
7235 &start_precision);
7236 Py_DECREF(bytes);
7237 if (rv != 0) {
7238 PyErr_SetString(PyExc_ValueError, skStringParseStrerror(rv));
7239 goto error;
7240 }
7241 } else {
7242 PyErr_SetString(PyExc_TypeError,
7243 "start must be a string or a "
7244 "datetime.date[time] object");
7245 goto error;
7246 }
7247 starttime -= starttime % 3600000;
7248
7249 /* Calculate endtime */
7250 if (end == NULL || end == Py_None) {
7251 end = NULL;
7252 } else if (PyDate_Check(end)) {
7253 rv = silkPyDatetimeToSktime(&endtime, end);
7254 if (rv != 0) {
7255 goto error;
7256 }
7257 end_precision = (PyDateTime_Check(end)
7258 ? SK_PARSED_DATETIME_HOUR
7259 : SK_PARSED_DATETIME_DAY);
7260 } else if (IS_STRING(end)) {
7261 PyObject *bytes = bytes_from_string(end);
7262 if (bytes == NULL) {
7263 goto error;
7264 }
7265 rv = skStringParseDatetime(&endtime, PyBytes_AS_STRING(bytes),
7266 &end_precision);
7267 Py_DECREF(bytes);
7268 if (rv != 0) {
7269 PyErr_SetString(PyExc_ValueError, skStringParseStrerror(rv));
7270 goto error;
7271 }
7272 } else {
7273 PyErr_SetString(PyExc_TypeError,
7274 "end must be a string or a "
7275 "datetime.date[time] object");
7276 goto error;
7277 }
7278
7279 /* End-time mashup */
7280 if (end) {
7281 if (end_precision & SK_PARSED_DATETIME_EPOCH) {
7282 /* when end-time is specified as an epoch, use it as-is */
7283
7284 } else if (SK_PARSED_DATETIME_GET_PRECISION(start_precision)
7285 == SK_PARSED_DATETIME_DAY)
7286 {
7287 /* when no starting hour given, we look at the full days,
7288 * regardless of the precision of the ending time; go to
7289 * the last hour of the ending day. */
7290 if (skDatetimeCeiling(&endtime, &endtime, start_precision)) {
7291 PyErr_SetString(PyExc_ValueError,
7292 "Could not determine end time");
7293 goto error;
7294 }
7295 endtime -= endtime % 3600000;
7296 } else if (SK_PARSED_DATETIME_GET_PRECISION(end_precision)
7297 < SK_PARSED_DATETIME_HOUR)
7298 {
7299 /* starting time has an hour but ending time does not; use
7300 * same hour for ending time */
7301 #if SK_ENABLE_LOCALTIME
7302 time_t t;
7303 struct tm work_tm;
7304 int work_hour;
7305
7306 /* get starting hour */
7307 t = starttime / 1000;
7308 localtime_r(&t, &work_tm);
7309 work_hour = work_tm.tm_hour;
7310 /* break apart end time */
7311 t = endtime / 1000;
7312 localtime_r(&t, &work_tm);
7313 /* set end hour to start hour and re-combine */
7314 work_tm.tm_hour = work_hour;
7315 t = mktime(&work_tm);
7316 endtime = sktimeCreate((t - (t % 3600)), 0);
7317 #else
7318 endtime = endtime - (endtime % 86400000) + (starttime % 86400000);
7319 #endif
7320 } else {
7321 endtime -= endtime % 3600000;
7322 }
7323
7324 } else if ((SK_PARSED_DATETIME_GET_PRECISION(start_precision)
7325 >= SK_PARSED_DATETIME_HOUR)
7326 || (start_precision & SK_PARSED_DATETIME_EPOCH))
7327 {
7328 /* no ending time was given and the starting time contains an
7329 * hour or the starting time was expressed as epoch seconds;
7330 * we only look at that single hour */
7331 endtime = starttime;
7332
7333 } else {
7334 /* no ending time was given and the starting time was to the
7335 * day; look at that entire day */
7336 if (skDatetimeCeiling(&endtime, &starttime, start_precision)) {
7337 PyErr_SetString(PyExc_ValueError,
7338 "Could not determine end time");
7339 goto error;
7340 }
7341 endtime -= endtime % 3600000;
7342 }
7343
7344 if (starttime > endtime) {
7345 PyErr_SetString(PyExc_ValueError,
7346 "start must be less or equal to end");
7347 goto error;
7348 }
7349
7350 /* Calculate flowtypes */
7351 if (flowtypes == NULL || flowtypes == Py_None) {
7352 sksiteFlowtypeIterator(&ft_iter);
7353 while (sksiteFlowtypeIteratorNext(&ft_iter, &ft)) {
7354 rv = skVectorAppendValue(ft_vec, &ft);
7355 if (rv != 0) {
7356 PyErr_NoMemory();
7357 goto error;
7358 }
7359 }
7360 } else if (PySequence_Check(flowtypes)) {
7361 Py_ssize_t len;
7362 PyObject **items;
7363 fast = PySequence_Fast(flowtypes, "flowtypes must be a sequence");
7364 if (fast == NULL) {
7365 goto error;
7366 }
7367 len = PySequence_Fast_GET_SIZE(fast);
7368 items = PySequence_Fast_ITEMS(fast);
7369 for (/*empty*/; len; len--, items++) {
7370 const char *class_name, *type_name;
7371 if (!PyArg_ParseTuple(*items, "ss", &class_name, &type_name)) {
7372 goto error;
7373 }
7374 ft = sksiteFlowtypeLookupByClassType(class_name, type_name);
7375 if (ft == SK_INVALID_FLOWTYPE) {
7376 PyErr_Format(PyExc_ValueError,
7377 "Invalid (class, type) pair ('%s', '%s')",
7378 class_name, type_name);
7379 return -1;
7380 }
7381 rv = skVectorAppendValue(ft_vec, &ft);
7382 if (rv != 0) {
7383 PyErr_NoMemory();
7384 goto error;
7385 }
7386 }
7387 Py_CLEAR(fast);
7388 } else {
7389 PyErr_SetString(
7390 PyExc_TypeError,
7391 "flowtypes should be a sequence of (class, type) pairs");
7392 goto error;
7393 }
7394
7395 /* Calculate sensors */
7396 if (sensors && PySequence_Check(sensors)) {
7397 Py_ssize_t len;
7398 PyObject **items;
7399 sk_sensor_id_t sensor;
7400
7401 sensor_vec = skVectorNew(sizeof(sk_sensor_id_t));
7402 if (sensor_vec == NULL) {
7403 PyErr_NoMemory();
7404 goto error;
7405 }
7406
7407 fast = PySequence_Fast(sensors, "sensors must be a sequence");
7408 if (fast == NULL) {
7409 goto error;
7410 }
7411 len = PySequence_Fast_GET_SIZE(fast);
7412 items = PySequence_Fast_ITEMS(fast);
7413 for (/*empty*/; len; len--, items++) {
7414 PyObject *bytes;
7415 if (!IS_STRING(*items)) {
7416 PyErr_SetString(PyExc_TypeError,
7417 "sensors must be strings");
7418 goto error;
7419 }
7420 bytes = bytes_from_string(*items);
7421 if (bytes == NULL) {
7422 goto error;
7423 }
7424 sensor = sksiteSensorLookup(PyBytes_AS_STRING(bytes));
7425 if (sensor == SK_INVALID_SENSOR) {
7426 PyErr_SetString(PyExc_ValueError, "Invalid sensor name");
7427 goto error;
7428 }
7429 rv = skVectorAppendValue(sensor_vec, &sensor);
7430 if (rv != 0) {
7431 PyErr_NoMemory();
7432 goto error;
7433 }
7434 }
7435 Py_CLEAR(fast);
7436 } else if (sensors != NULL && sensors != Py_None) {
7437 PyErr_SetString(PyExc_TypeError,
7438 "sensors should be a sequence of strings");
7439 goto error;
7440 }
7441
7442 if (missing && PyObject_IsTrue(missing)) {
7443 flags = RETURN_MISSING;
7444 } else {
7445 flags = 0;
7446 }
7447
7448 rv = sksiteRepoIteratorCreate(
7449 &self->iter, ft_vec, sensor_vec, starttime, endtime, flags);
7450 if (rv != 0) {
7451 PyErr_NoMemory();
7452 goto error;
7453 }
7454
7455 rv = 0;
7456
7457 cleanup:
7458 Py_XDECREF(fast);
7459 if (ft_vec) {
7460 skVectorDestroy(ft_vec);
7461 }
7462 if (sensor_vec) {
7463 skVectorDestroy(sensor_vec);
7464 }
7465
7466 return rv;
7467
7468 error:
7469 rv = -1;
7470 goto cleanup;
7471 }
7472
7473 static PyObject *
silkPyRepoIter_iternext(silkPyRepoIter * self)7474 silkPyRepoIter_iternext(
7475 silkPyRepoIter *self)
7476 {
7477 char path[PATH_MAX];
7478 int missing;
7479 int rv;
7480
7481 rv = sksiteRepoIteratorNextPath(self->iter, path, sizeof(path), &missing);
7482 if (rv == SK_ITERATOR_NO_MORE_ENTRIES) {
7483 PyErr_SetNone(PyExc_StopIteration);
7484 return NULL;
7485 }
7486
7487 return Py_BuildValue("sO", path, missing ? Py_False : Py_True);
7488 }
7489
7490
7491 /*
7492 *************************************************************************
7493 * Misc Globals
7494 *************************************************************************
7495 */
7496
7497 /* function prototypes */
7498 static PyObject *silk_class_info(void);
7499 static PyObject *silk_flowtype_info(void);
7500 static PyObject *silk_get_rootdir(void);
7501 static PyObject *silk_get_siteconf(void);
7502 static PyObject *silk_have_site_config(void);
7503 static PyObject *
7504 silk_init_country_codes(
7505 PyObject UNUSED(*self),
7506 PyObject *args);
7507 static int
7508 silk_init_set_envvar(
7509 const char *value,
7510 const char *envvar);
7511 static PyObject *
7512 silk_init_site(
7513 PyObject UNUSED(*self),
7514 PyObject *args,
7515 PyObject *kwds);
7516 static PyObject *silk_get_compression_methods(void);
7517 static PyObject *silk_get_timezone_support(void);
7518 static PyObject *silk_initial_tcpflags_enabled(void);
7519 static PyObject *silk_ipset_supports_ipv6(void);
7520 static PyObject *silk_ipv6_enabled(void);
7521 static silkPyRawRWRec *
7522 silk_raw_rwrec_copy(
7523 PyObject UNUSED(*self),
7524 PyObject *c_rec);
7525 static PyObject *silk_sensor_info(void);
7526 static PyObject *
7527 silk_set_rootdir(
7528 PyObject UNUSED(*self),
7529 PyObject *args);
7530 static PyObject *silk_version(void);
7531
7532 static PyMethodDef silk_methods[] = {
7533 {"get_compression_methods", (PyCFunction)silk_get_compression_methods,
7534 METH_NOARGS,
7535 ("Return a list of strings containing the compression methods"
7536 " enabled at compile-time")},
7537 {"get_timezone_support", (PyCFunction)silk_get_timezone_support,
7538 METH_NOARGS,
7539 ("Return whether \"UTC\" or the \"local\" timezone was selected"
7540 " at compile-time")},
7541 {"ipv6_enabled", (PyCFunction)silk_ipv6_enabled,
7542 METH_NOARGS,
7543 ("Return whether IPv6 was enabled at compile-time")},
7544 {"ipset_supports_ipv6", (PyCFunction)silk_ipset_supports_ipv6,
7545 METH_NOARGS,
7546 ("Return whether IPv6-support for IPsets was enabled at compile-time")},
7547 {"initial_tcpflags_enabled", (PyCFunction)silk_initial_tcpflags_enabled,
7548 METH_NOARGS,
7549 ("Return whether initial tcpflags were enabled at compile-time")},
7550 {"init_site", (PyCFunction)silk_init_site,
7551 METH_VARARGS | METH_KEYWORDS,
7552 ("init_site([siteconf][, rootdir])\n"
7553 "Initialize the silk site.\n"
7554 "When siteconf is None, PySiLK uses the file named by the environment\n"
7555 "variable " SILK_CONFIG_FILE_ENVAR ", if available, or the file\n"
7556 "'silk.conf' in the rootdir, the directories '$SILK_PATH/share/silk/'\n"
7557 "and '$SILK_PATH/share/', and the 'share/silk/' and 'share/'\n"
7558 "directories parallel to the application's directory.\n"
7559 "When rootdir is not supplied, SiLK's default value is used.\n"
7560 "Throw an exception if the site is already initialized.")},
7561 {"have_site_config", (PyCFunction)silk_have_site_config,
7562 METH_NOARGS,
7563 ("Return whether the site configuration file has been loaded")},
7564 {"get_site_config", (PyCFunction)silk_get_siteconf,
7565 METH_NOARGS,
7566 ("Return the current site configuration file; None if not set")},
7567 {"set_data_rootdir", (PyCFunction)silk_set_rootdir,
7568 METH_VARARGS,
7569 ("Change the data root directory to the given path")},
7570 {"get_data_rootdir", (PyCFunction)silk_get_rootdir,
7571 METH_NOARGS,
7572 ("Return the current root directory")},
7573 {"sensor_info", (PyCFunction)silk_sensor_info,
7574 METH_NOARGS,
7575 ("Returns a list of information for configured sensors")},
7576 {"class_info", (PyCFunction)silk_class_info,
7577 METH_NOARGS,
7578 ("Return a list of information for configured classes")},
7579 {"flowtype_info", (PyCFunction)silk_flowtype_info,
7580 METH_NOARGS,
7581 ("Return a list of information for configured flowtypes")},
7582 {"silk_version", (PyCFunction)silk_version,
7583 METH_NOARGS,
7584 ("Return the version of SiLK that PySilk was linked against")},
7585 {"init_country_codes", (PyCFunction)silk_init_country_codes,
7586 METH_VARARGS,
7587 ("Initialize the country codes from the given file (can be left blank)")},
7588 {"_raw_rwrec_copy", (PyCFunction)silk_raw_rwrec_copy,
7589 METH_O,
7590 ("Create a RawRWRec from a C rwrec PyCObject, copying the value")},
7591 {NULL, NULL, 0, NULL} /* Sentinel */
7592 };
7593
7594 static PyObject *
silk_class_info(void)7595 silk_class_info(
7596 void)
7597 {
7598 CHECK_SITE(NULL);
7599
7600 Py_INCREF(GLOBALS->classes);
7601 return GLOBALS->classes;
7602 }
7603
7604 static PyObject *
silk_flowtype_info(void)7605 silk_flowtype_info(
7606 void)
7607 {
7608 CHECK_SITE(NULL);
7609
7610 Py_INCREF(GLOBALS->flowtypes);
7611 return GLOBALS->flowtypes;
7612 }
7613
7614 static PyObject *
silk_get_rootdir(void)7615 silk_get_rootdir(
7616 void)
7617 {
7618 char rootdir[PATH_MAX];
7619
7620 sksiteGetRootDir(rootdir, sizeof(rootdir));
7621 return PyUnicode_InternFromString(rootdir);
7622 }
7623
7624 static PyObject *
silk_get_siteconf(void)7625 silk_get_siteconf(
7626 void)
7627 {
7628 char siteconf[PATH_MAX];
7629
7630 sksiteGetConfigPath(siteconf, sizeof(siteconf));
7631 return PyUnicode_InternFromString(siteconf);
7632 }
7633
7634 static PyObject *
silk_have_site_config(void)7635 silk_have_site_config(
7636 void)
7637 {
7638 Py_INCREF(GLOBALS->havesite);
7639 return GLOBALS->havesite;
7640 }
7641
7642 static PyObject *
silk_init_country_codes(PyObject UNUSED (* self),PyObject * args)7643 silk_init_country_codes(
7644 PyObject UNUSED(*self),
7645 PyObject *args)
7646 {
7647 int rv;
7648 char *filename = NULL;
7649
7650 rv = PyArg_ParseTuple(args, "|et",
7651 Py_FileSystemDefaultEncoding, &filename);
7652 if (!rv) {
7653 return NULL;
7654 }
7655
7656 skCountryTeardown();
7657 rv = skCountrySetup(filename, error_printf);
7658 PyMem_Free(filename);
7659 if (rv != 0) {
7660 PyErr_SetString(PyExc_RuntimeError, error_buffer);
7661 return NULL;
7662 }
7663
7664 Py_RETURN_NONE;
7665 }
7666
7667 static int
silk_init_set_envvar(const char * value,const char * envvar)7668 silk_init_set_envvar(
7669 const char *value,
7670 const char *envvar)
7671 {
7672 static char env_buf[101 + PATH_MAX];
7673 PyObject *os;
7674 int rv;
7675
7676 if (value == NULL) {
7677 return 0;
7678 }
7679
7680 /* setenv() does not exist on Solaris 9, so we use putenv()
7681 * instead */
7682 rv = snprintf(env_buf, sizeof(env_buf),
7683 "%s=%s", envvar, value);
7684 if (rv >= (int)sizeof(env_buf) || putenv(env_buf) != 0) {
7685 PyErr_SetString(PyExc_RuntimeError,
7686 ("Could not set " SILK_CONFIG_FILE_ENVAR));
7687 return -1;
7688 }
7689
7690 /* Attempt to add the environment variable to Python's
7691 * environment list as well */
7692 os = PyImport_ImportModule("os");
7693 if (os != NULL) {
7694 PyObject *env = PyObject_GetAttrString(os, "environ");
7695 if (env != NULL) {
7696 PyObject *s = PyUnicode_Decode(value,
7697 strlen(value),
7698 Py_FileSystemDefaultEncoding,
7699 "strict");
7700 if (s != NULL) {
7701 PyMapping_SetItemString(env, (char*)envvar, s);
7702 Py_DECREF(s);
7703 }
7704 Py_DECREF(env);
7705 }
7706 Py_DECREF(os);
7707 }
7708
7709 return 0;
7710 }
7711
7712 static PyObject *
silk_init_site(PyObject UNUSED (* self),PyObject * args,PyObject * kwds)7713 silk_init_site(
7714 PyObject UNUSED(*self),
7715 PyObject *args,
7716 PyObject *kwds)
7717 {
7718 static char *kwlist[] = {"siteconf", "rootdir", NULL};
7719 char *siteconf = NULL;
7720 char *rootdir = NULL;
7721 int rv;
7722
7723 rv = PyArg_ParseTupleAndKeywords(args, kwds, "|etet", kwlist,
7724 Py_FileSystemDefaultEncoding, &siteconf,
7725 Py_FileSystemDefaultEncoding, &rootdir);
7726 if (!rv) {
7727 goto error;
7728 }
7729
7730 if (GLOBALS->site_configured) {
7731 PyErr_SetString(PyExc_RuntimeError, "Site already initialized");
7732 goto error;
7733 }
7734
7735 if (siteconf) {
7736 ASSERT_RESULT(sksiteSetConfigPath(siteconf), int, 0);
7737 }
7738
7739 if (rootdir) {
7740 if (!skDirExists(rootdir)) {
7741 PyErr_Format(PyExc_IOError,
7742 "The directory %s does not exist", rootdir);
7743 goto error;
7744 }
7745 rv = sksiteSetRootDir(rootdir);
7746 if (rv != 0) {
7747 PyErr_SetString(PyExc_ValueError, "Illegal root directory");
7748 goto error;
7749 }
7750 }
7751
7752 if (init_site(siteconf) != 0) {
7753 goto error;
7754 }
7755
7756 /* These are needed for subprocess calls to silk */
7757 if (silk_init_set_envvar(siteconf, SILK_CONFIG_FILE_ENVAR)) {
7758 goto error;
7759 }
7760 if (silk_init_set_envvar(rootdir, SILK_DATA_ROOTDIR_ENVAR)) {
7761 goto error;
7762 }
7763
7764 Py_INCREF(GLOBALS->havesite);
7765 return GLOBALS->havesite;
7766
7767 error:
7768 PyMem_Free(siteconf);
7769 PyMem_Free(rootdir);
7770
7771 return NULL;
7772 }
7773
7774 static PyObject *
silk_initial_tcpflags_enabled(void)7775 silk_initial_tcpflags_enabled(
7776 void)
7777 {
7778 Py_RETURN_TRUE;
7779 }
7780
7781 static PyObject *
silk_ipset_supports_ipv6(void)7782 silk_ipset_supports_ipv6(
7783 void)
7784 {
7785 #if SK_ENABLE_IPV6
7786 Py_RETURN_TRUE;
7787 #else
7788 Py_RETURN_FALSE;
7789 #endif
7790 }
7791
7792 static PyObject *
silk_ipv6_enabled(void)7793 silk_ipv6_enabled(
7794 void)
7795 {
7796 #if SK_ENABLE_IPV6
7797 Py_RETURN_TRUE;
7798 #else
7799 Py_RETURN_FALSE;
7800 #endif
7801 }
7802
7803 static PyObject *
silk_get_timezone_support(void)7804 silk_get_timezone_support(
7805 void)
7806 {
7807 #if SK_ENABLE_LOCALTIME
7808 return STRING_FROM_STRING("local");
7809 #else
7810 return STRING_FROM_STRING("UTC");
7811 #endif
7812 }
7813
7814 static PyObject *
silk_get_compression_methods(void)7815 silk_get_compression_methods(
7816 void)
7817 {
7818 const char *compmethods[] = {
7819 "NO_COMPRESSION",
7820 #if SK_ENABLE_ZLIB
7821 "ZLIB",
7822 #endif
7823 #if SK_ENABLE_LZO
7824 "LZO1X",
7825 #endif
7826 #if SK_ENABLE_SNAPPY
7827 "SNAPPY",
7828 #endif
7829 NULL
7830 };
7831 PyObject *list;
7832 PyObject *val;
7833 size_t i;
7834 int rv;
7835
7836 list = PyList_New(0);
7837 if (NULL == list) {
7838 return NULL;
7839 }
7840
7841 for (i = 0; compmethods[i] != NULL; ++i) {
7842 val = STRING_FROM_STRING(compmethods[i]);
7843 if (NULL == val) {
7844 goto ERROR;
7845 }
7846 rv = PyList_Append(list, val);
7847 Py_DECREF(val);
7848 if (rv != 0) {
7849 goto ERROR;
7850 }
7851 }
7852
7853 return list;
7854
7855 ERROR:
7856 Py_DECREF(list);
7857 return NULL;
7858 }
7859
7860 static silkPyRawRWRec *
silk_raw_rwrec_copy(PyObject UNUSED (* self),PyObject * c_rec)7861 silk_raw_rwrec_copy(
7862 PyObject UNUSED(*self),
7863 PyObject *c_rec)
7864 {
7865 silkPyRawRWRec *pyrec;
7866 rwRec *rec;
7867
7868 if (!COBJ_CHECK(c_rec)) {
7869 PyErr_SetString(PyExc_TypeError, "Illegal argument type");
7870 return NULL;
7871 }
7872
7873 pyrec = (silkPyRawRWRec*)silkPyRawRWRecType.tp_alloc(
7874 &silkPyRawRWRecType, 0);
7875 if (pyrec != NULL) {
7876 rec = (rwRec*)COBJ_PTR(c_rec);
7877 if (rec != NULL) {
7878 RWREC_COPY(&pyrec->rec, rec);
7879 }
7880 }
7881
7882 return pyrec;
7883 }
7884
7885 static PyObject *
silk_sensor_info(void)7886 silk_sensor_info(
7887 void)
7888 {
7889 CHECK_SITE(NULL);
7890
7891 Py_INCREF(GLOBALS->sensors);
7892 return GLOBALS->sensors;
7893 }
7894
7895 static PyObject *
silk_set_rootdir(PyObject UNUSED (* self),PyObject * args)7896 silk_set_rootdir(
7897 PyObject UNUSED(*self),
7898 PyObject *args)
7899 {
7900 int rv;
7901 char *rootdir = NULL;
7902
7903 CHECK_SITE(NULL);
7904
7905 rv = PyArg_ParseTuple(args, "|et",
7906 Py_FileSystemDefaultEncoding, &rootdir);
7907 if (!rv) {
7908 return NULL;
7909 }
7910 if (!skDirExists(rootdir)) {
7911 PyErr_Format(PyExc_IOError,
7912 "The directory %s does not exist", rootdir);
7913 PyMem_Free(rootdir);
7914 return NULL;
7915 }
7916 rv = sksiteSetRootDir(rootdir);
7917 PyMem_Free(rootdir);
7918 if (rv != 0) {
7919 PyErr_SetString(PyExc_ValueError, "Illegal root directory");
7920 return NULL;
7921 }
7922
7923 Py_RETURN_NONE;
7924 }
7925
7926 static PyObject *
silk_version(void)7927 silk_version(
7928 void)
7929 {
7930 return PyUnicode_InternFromString(SK_PACKAGE_VERSION);
7931 }
7932
7933
7934 /*
7935 *************************************************************************
7936 * SUPPORT FUNCTIONS
7937 *************************************************************************
7938 */
7939
7940 static PyObject *
any_obj_error(PyObject * exc,const char * format,PyObject * obj)7941 any_obj_error(
7942 PyObject *exc,
7943 const char *format,
7944 PyObject *obj)
7945 {
7946 PyObject *pformat = PyUnicode_FromString(format);
7947 PyObject *msg = PyUnicode_Format(pformat, obj);
7948 PyErr_SetObject(exc, msg);
7949 Py_DECREF(pformat);
7950 Py_DECREF(msg);
7951 return NULL;
7952 }
7953
7954 #ifndef TEST_PRINTF_FORMATS
7955 static int
error_printf(const char * fmt,...)7956 error_printf(
7957 const char *fmt,
7958 ...)
7959 {
7960 int rv;
7961
7962 va_list args;
7963 va_start(args, fmt);
7964 rv = vsnprintf(error_buffer, sizeof(error_buffer), fmt, args);
7965 error_buffer[sizeof(error_buffer) - 1] = '\0';
7966 va_end(args);
7967
7968 return rv;
7969 }
7970 #endif /* TEST_PRINTF_FORMATS */
7971
7972
7973 static int
init_classes(void)7974 init_classes(
7975 void)
7976 {
7977 sk_class_iter_t iter;
7978 sk_class_id_t class_id;
7979 char name[SK_MAX_STRLEN_FLOWTYPE+1];
7980 PyObject *list;
7981 PyObject *dict;
7982 PyObject *classes;
7983 PyObject *val;
7984 PyObject *class_data;
7985 int rv;
7986
7987 classes = PyDict_New();
7988 if (classes == NULL) {
7989 goto error;
7990 }
7991 class_id = sksiteClassGetDefault();
7992 if (class_id == SK_INVALID_CLASS) {
7993 val = Py_None;
7994 Py_INCREF(val);
7995 } else {
7996 val = PyInt_FromLong(sksiteClassGetDefault());
7997 if (val == NULL) {
7998 goto error;
7999 }
8000 }
8001 rv = PyDict_SetItemString(classes, "default", val);
8002 Py_DECREF(val);
8003 if (rv != 0) {
8004 goto error;
8005 }
8006
8007 class_data = PyDict_New();
8008 if (class_data == NULL) {
8009 goto error;
8010 }
8011 rv = PyDict_SetItemString(classes, "data", class_data);
8012 Py_DECREF(class_data);
8013 if (rv != 0) {
8014 goto error;
8015 }
8016
8017 sksiteClassIterator(&iter);
8018 while (sksiteClassIteratorNext(&iter, &class_id)) {
8019 sk_sensor_iter_t sensor_iter;
8020 sk_sensor_id_t sensor;
8021 sk_flowtype_iter_t flowtype_iter;
8022 sk_flowtype_id_t flowtype;
8023
8024 dict = PyDict_New();
8025 if (dict == NULL) {
8026 goto error;
8027 }
8028 val = PyInt_FromLong(class_id);
8029 if (val == NULL) {
8030 Py_DECREF(dict);
8031 goto error;
8032 }
8033 rv = PyDict_SetItem(class_data, val, dict);
8034 Py_DECREF(dict);
8035 if (rv != 0) {
8036 Py_DECREF(val);
8037 goto error;
8038 }
8039 rv = PyDict_SetItemString(dict, "id", val);
8040 Py_DECREF(val);
8041 if (rv != 0) {
8042 goto error;
8043 }
8044
8045 sksiteClassGetName(name, sizeof(name), class_id);
8046 val = PyUnicode_InternFromString(name);
8047 if (val == NULL) {
8048 goto error;
8049 }
8050 rv = PyDict_SetItemString(dict, "name", val);
8051 Py_DECREF(val);
8052 if (rv != 0) {
8053 goto error;
8054 }
8055
8056 list = PyList_New(0);
8057 if (list == NULL) {
8058 goto error;
8059 }
8060 rv = PyDict_SetItemString(dict, "sensors", list);
8061 Py_DECREF(list);
8062 if (rv != 0) {
8063 goto error;
8064 }
8065 sksiteClassSensorIterator(class_id, &sensor_iter);
8066 while (sksiteSensorIteratorNext(&sensor_iter, &sensor)) {
8067 val = PyInt_FromLong(sensor);
8068 if (val == NULL) {
8069 goto error;
8070 }
8071 rv = PyList_Append(list, val);
8072 Py_DECREF(val);
8073 if (rv != 0) {
8074 goto error;
8075 }
8076 }
8077
8078 list = PyList_New(0);
8079 if (list == NULL) {
8080 goto error;
8081 }
8082 rv = PyDict_SetItemString(dict, "flowtypes", list);
8083 Py_DECREF(list);
8084 if (rv != 0) {
8085 goto error;
8086 }
8087 sksiteClassFlowtypeIterator(class_id, &flowtype_iter);
8088 while (sksiteFlowtypeIteratorNext(&flowtype_iter, &flowtype)) {
8089 val = PyInt_FromLong(flowtype);
8090 if (val == NULL) {
8091 goto error;
8092 }
8093 rv = PyList_Append(list, val);
8094 Py_DECREF(val);
8095 if (rv != 0) {
8096 goto error;
8097 }
8098 }
8099
8100 list = PyList_New(0);
8101 if (list == NULL) {
8102 goto error;
8103 }
8104 rv = PyDict_SetItemString(dict, "default_flowtypes", list);
8105 Py_DECREF(list);
8106 if (rv != 0) {
8107 goto error;
8108 }
8109 sksiteClassDefaultFlowtypeIterator(class_id, &flowtype_iter);
8110 while (sksiteFlowtypeIteratorNext(&flowtype_iter, &flowtype)) {
8111 val = PyInt_FromLong(flowtype);
8112 if (val == NULL) {
8113 goto error;
8114 }
8115 rv = PyList_Append(list, val);
8116 Py_DECREF(val);
8117 if (rv != 0) {
8118 goto error;
8119 }
8120 }
8121 }
8122
8123 GLOBALS->classes = classes;
8124 return 0;
8125
8126 error:
8127 Py_XDECREF(classes);
8128
8129 return -1;
8130 }
8131
8132 static int
init_flowtypes(void)8133 init_flowtypes(
8134 void)
8135 {
8136 sk_flowtype_iter_t flowtype_iter;
8137 sk_flowtype_id_t flowtype;
8138 char name[SK_MAX_STRLEN_SENSOR+1];
8139 PyObject *dict;
8140 PyObject *flowtypes;
8141 int rv;
8142
8143 flowtypes = PyDict_New();
8144 if (flowtypes == NULL) {
8145 goto error;
8146 }
8147
8148 sksiteFlowtypeIterator(&flowtype_iter);
8149 while (sksiteFlowtypeIteratorNext(&flowtype_iter, &flowtype)) {
8150 sk_class_id_t class_id;
8151 PyObject *val;
8152
8153 dict = PyDict_New();
8154 if (dict == NULL) {
8155 goto error;
8156 }
8157 val = PyInt_FromLong(flowtype);
8158 if (val == NULL) {
8159 Py_DECREF(dict);
8160 goto error;
8161 }
8162 rv = PyDict_SetItem(flowtypes, val, dict);
8163 Py_DECREF(dict);
8164 if (rv != 0) {
8165 Py_DECREF(val);
8166 goto error;
8167 }
8168 rv = PyDict_SetItemString(dict, "id", val);
8169 Py_DECREF(val);
8170 if (rv != 0) {
8171 goto error;
8172 }
8173
8174 sksiteFlowtypeGetName(name, sizeof(name), flowtype);
8175 val = PyUnicode_InternFromString(name);
8176 if (val == NULL) {
8177 goto error;
8178 }
8179 rv = PyDict_SetItemString(dict, "name", val);
8180 Py_DECREF(val);
8181 if (rv != 0) {
8182 goto error;
8183 }
8184
8185 sksiteFlowtypeGetType(name, sizeof(name), flowtype);
8186 val = PyUnicode_InternFromString(name);
8187 if (val == NULL) {
8188 goto error;
8189 }
8190 rv = PyDict_SetItemString(dict, "type", val);
8191 Py_DECREF(val);
8192 if (rv != 0) {
8193 goto error;
8194 }
8195
8196 class_id = sksiteFlowtypeGetClassID(flowtype);
8197 val = PyInt_FromLong(class_id);
8198 if (val == NULL) {
8199 goto error;
8200 }
8201 rv = PyDict_SetItemString(dict, "class", val);
8202 Py_DECREF(val);
8203 if (rv != 0) {
8204 goto error;
8205 }
8206 }
8207
8208 GLOBALS->flowtypes = flowtypes;
8209 return 0;
8210
8211 error:
8212 Py_XDECREF(flowtypes);
8213
8214 return -1;
8215 }
8216
8217 static int
init_sensors(void)8218 init_sensors(
8219 void)
8220 {
8221 sk_sensor_iter_t sensor_iter;
8222 sk_sensor_id_t sensor;
8223 char name[SK_MAX_STRLEN_SENSOR+1];
8224 PyObject *list;
8225 PyObject *dict;
8226 PyObject *sensors;
8227 int rv;
8228
8229 sensors = PyDict_New();
8230 if (sensors == NULL) {
8231 goto error;
8232 }
8233
8234 sksiteSensorIterator(&sensor_iter);
8235 while (sksiteSensorIteratorNext(&sensor_iter, &sensor)) {
8236 sk_class_iter_t class_iter;
8237 sk_class_id_t class_id;
8238 PyObject *val;
8239 const char *desc;
8240
8241 dict = PyDict_New();
8242 if (dict == NULL) {
8243 goto error;
8244 }
8245 val = PyInt_FromLong(sensor);
8246 if (val == NULL) {
8247 Py_DECREF(dict);
8248 goto error;
8249 }
8250 rv = PyDict_SetItem(sensors, val, dict);
8251 Py_DECREF(dict);
8252 if (rv != 0) {
8253 Py_DECREF(val);
8254 goto error;
8255 }
8256 rv = PyDict_SetItemString(dict, "id", val);
8257 Py_DECREF(val);
8258 if (rv != 0) {
8259 goto error;
8260 }
8261
8262 sksiteSensorGetName(name, sizeof(name), sensor);
8263 val = PyUnicode_InternFromString(name);
8264 if (val == NULL) {
8265 goto error;
8266 }
8267 rv = PyDict_SetItemString(dict, "name", val);
8268 Py_DECREF(val);
8269 if (rv != 0) {
8270 goto error;
8271 }
8272
8273 desc = sksiteSensorGetDescription(sensor);
8274 if (desc) {
8275 val = PyUnicode_FromString(desc);
8276 if (val == NULL) {
8277 goto error;
8278 }
8279 rv = PyDict_SetItemString(dict, "description", val);
8280 Py_DECREF(val);
8281 if (rv != 0) {
8282 goto error;
8283 }
8284 }
8285
8286 list = PyList_New(0);
8287 if (list == NULL) {
8288 goto error;
8289 }
8290 rv = PyDict_SetItemString(dict, "classes", list);
8291 Py_DECREF(list);
8292 if (rv != 0) {
8293 goto error;
8294 }
8295 sksiteSensorClassIterator(sensor, &class_iter);
8296 while (sksiteClassIteratorNext(&class_iter, &class_id)) {
8297 val = PyInt_FromLong(class_id);
8298 if (val == NULL) {
8299 goto error;
8300 }
8301 rv = PyList_Append(list, val);
8302 Py_DECREF(val);
8303 if (rv != 0) {
8304 goto error;
8305 }
8306 }
8307 }
8308
8309 GLOBALS->sensors = sensors;
8310 return 0;
8311
8312 error:
8313 Py_XDECREF(sensors);
8314
8315 return -1;
8316 }
8317
8318 static int
init_silkfile_module(PyObject * mod)8319 init_silkfile_module(
8320 PyObject *mod)
8321 {
8322 int rv;
8323
8324 PyModule_AddIntConstant(mod, "IGNORE", SK_IPV6POLICY_IGNORE);
8325 PyModule_AddIntConstant(mod, "ASV4", SK_IPV6POLICY_ASV4);
8326 PyModule_AddIntConstant(mod, "MIX", SK_IPV6POLICY_MIX);
8327 PyModule_AddIntConstant(mod, "FORCE", SK_IPV6POLICY_FORCE);
8328 PyModule_AddIntConstant(mod, "ONLY", SK_IPV6POLICY_ONLY);
8329
8330 PyModule_AddIntConstant(mod, "READ", SK_IO_READ);
8331 PyModule_AddIntConstant(mod, "WRITE", SK_IO_WRITE);
8332 PyModule_AddIntConstant(mod, "APPEND", SK_IO_APPEND);
8333
8334 PyModule_AddIntConstant(mod, "DEFAULT", NOT_SET);
8335 PyModule_AddIntConstant(mod, "NO_COMPRESSION", SK_COMPMETHOD_NONE);
8336 PyModule_AddIntConstant(mod, "ZLIB", SK_COMPMETHOD_ZLIB);
8337 PyModule_AddIntConstant(mod, "LZO1X", SK_COMPMETHOD_LZO1X);
8338 PyModule_AddIntConstant(mod, "SNAPPY", SK_COMPMETHOD_SNAPPY);
8339
8340 PyModule_AddObject(mod, "BAG_COUNTER_MAX",
8341 PyLong_FromUnsignedLongLong(SKBAG_COUNTER_MAX));
8342
8343 silkPySilkFileType.tp_new = PyType_GenericNew;
8344 if (PyType_Ready(&silkPySilkFileType) < 0) {
8345 return -1;
8346 }
8347 rv = PyModule_AddObject(mod, "SilkFileBase",
8348 (PyObject*)&silkPySilkFileType);
8349 if (rv != 0) {
8350 return -1;
8351 }
8352
8353 return 0;
8354 }
8355
8356 static int
init_site(const char * site_file)8357 init_site(
8358 const char *site_file)
8359 {
8360 int rv;
8361 int siterv;
8362 int retval = 0;
8363
8364 if (GLOBALS->site_configured) {
8365 return 0;
8366 }
8367
8368 siterv = sksiteConfigure(0);
8369 if (siterv == 0) {
8370 GLOBALS->havesite = Py_True;
8371 } else if (siterv == -2) {
8372 GLOBALS->havesite = Py_False;
8373 if (site_file) {
8374 Py_INCREF(GLOBALS->havesite);
8375 PyErr_Format(PyExc_IOError,
8376 "could not read site file %s", site_file);
8377 retval = -1;
8378 }
8379 } else {
8380 GLOBALS->havesite = Py_False;
8381 PyErr_SetString(PyExc_RuntimeError,
8382 "error parsing site configuration file");
8383 retval = -1;
8384 }
8385 Py_INCREF(GLOBALS->havesite);
8386 rv = PyModule_AddObject(GLOBALS->silkmod, "_havesite", GLOBALS->havesite);
8387 if (rv != 0) {
8388 return -1;
8389 }
8390
8391 rv = init_sensors();
8392 if (rv != 0) {
8393 return -1;
8394 }
8395 rv = PyModule_AddObject(GLOBALS->silkmod, "_sensors", GLOBALS->sensors);
8396 if (rv != 0) {
8397 return -1;
8398 }
8399
8400 rv = init_classes();
8401 if (rv != 0) {
8402 return -1;
8403 }
8404 rv = PyModule_AddObject(GLOBALS->silkmod, "_classes", GLOBALS->classes);
8405 if (rv != 0) {
8406 return -1;
8407 }
8408
8409 rv = init_flowtypes();
8410 if (rv != 0) {
8411 return -1;
8412 }
8413 rv = PyModule_AddObject(GLOBALS->silkmod, "_flowtypes",
8414 GLOBALS->flowtypes);
8415 if (rv != 0) {
8416 return -1;
8417 }
8418
8419 if (siterv == 0) {
8420 GLOBALS->site_configured = 1;
8421 }
8422
8423 return retval;
8424 }
8425
8426 static PyObject *
iter_iter(PyObject * self)8427 iter_iter(
8428 PyObject *self)
8429 {
8430 Py_INCREF(self);
8431 return self;
8432 }
8433
8434 static void
obj_dealloc(PyObject * obj)8435 obj_dealloc(
8436 PyObject *obj)
8437 {
8438 Py_TYPE(obj)->tp_free(obj);
8439 }
8440
8441 static PyObject *
obj_error(const char * format,PyObject * obj)8442 obj_error(
8443 const char *format,
8444 PyObject *obj)
8445 {
8446 return any_obj_error(PyExc_ValueError, format, obj);
8447 }
8448
8449 static skstream_t *
open_silkfile_write(PyObject * args,PyObject * kwds)8450 open_silkfile_write(
8451 PyObject *args,
8452 PyObject *kwds)
8453 {
8454 static char *kwlist[] = {"filename", "compression", NULL};
8455
8456 PyObject *name;
8457 PyObject *bytes;
8458 char errbuf[2 * PATH_MAX];
8459 skstream_t *stream = NULL;
8460 int compr = NOT_SET;
8461 const char *fname;
8462 sk_file_header_t *hdr;
8463 int rv;
8464
8465 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|i", kwlist,
8466 &name, &compr))
8467 {
8468 return NULL;
8469 }
8470
8471 if (!IS_STRING(name)) {
8472 PyErr_SetString(PyExc_TypeError, "Filename required");
8473 return NULL;
8474 }
8475 #if PY_MAJOR_VERSION < 3
8476 if (PyBytes_Check(name)) {
8477 bytes = name;
8478 Py_INCREF(bytes);
8479 } else
8480 #endif
8481 {
8482 bytes = PyUnicode_AsEncodedString(name, Py_FileSystemDefaultEncoding,
8483 "strict");
8484 if (bytes == NULL) {
8485 return NULL;
8486 }
8487 }
8488
8489 fname = PyBytes_AS_STRING(bytes);
8490 if ((rv = skStreamCreate(&stream, SK_IO_WRITE, SK_CONTENT_SILK))
8491 || (rv = skStreamBind(stream, fname))
8492 || (rv = skStreamOpen(stream)))
8493 {
8494 skStreamLastErrMessage(stream, rv, errbuf, sizeof(errbuf));
8495 PyErr_Format(PyExc_IOError, "Unable to open %s for writing: %s",
8496 fname, errbuf);
8497 skStreamDestroy(&stream);
8498 Py_DECREF(bytes);
8499 return NULL;
8500 }
8501
8502 if (compr != NOT_SET) {
8503 hdr = skStreamGetSilkHeader(stream);
8504 rv = skHeaderSetCompressionMethod(hdr, compr);
8505 if (rv != 0) {
8506 skStreamLastErrMessage(stream, rv, errbuf, sizeof(errbuf));
8507 PyErr_Format(PyExc_IOError,
8508 "Unable to open set compression on %s: %s",
8509 fname, errbuf);
8510 skStreamDestroy(&stream);
8511 Py_DECREF(bytes);
8512 return NULL;
8513 }
8514 }
8515
8516 Py_DECREF(bytes);
8517
8518 return stream;
8519 }
8520
8521 static PyObject *
reduce_error(PyObject * obj)8522 reduce_error(
8523 PyObject *obj)
8524 {
8525 if (Py_TYPE(obj) && Py_TYPE(obj)->tp_name) {
8526 PyErr_Format(PyExc_TypeError, "can't pickle %s objects",
8527 Py_TYPE(obj)->tp_name);
8528 } else {
8529 PyErr_SetString(PyExc_TypeError, "This object cannot be pickled");
8530 }
8531 return NULL;
8532 }
8533
8534 static int
silkPyDatetimeToSktime(sktime_t * silktime,PyObject * datetime)8535 silkPyDatetimeToSktime(
8536 sktime_t *silktime,
8537 PyObject *datetime)
8538 {
8539 PyObject *delta = NULL;
8540 PyObject *days = NULL;
8541 PyObject *secs = NULL;
8542 PyObject *usecs = NULL;
8543 int64_t millisecs;
8544 int retval = -1;
8545
8546 if (!PyDateTime_Check(datetime)) {
8547 if (PyDate_Check(datetime)) {
8548 datetime = PyDateTime_FromDateAndTime(
8549 PyDateTime_GET_YEAR(datetime),
8550 PyDateTime_GET_MONTH(datetime),
8551 PyDateTime_GET_DAY(datetime),
8552 0, 0, 0, 0);
8553 if (datetime == NULL) {
8554 return -1;
8555 }
8556 } else {
8557 PyErr_SetString(PyExc_TypeError, "Expected a datetime.date");
8558 return -1;
8559 }
8560 } else {
8561 Py_INCREF(datetime);
8562 }
8563 if (PyObject_RichCompareBool(datetime, GLOBALS->epochtime, Py_LT)) {
8564 PyErr_SetString(PyExc_ValueError, "Minimum time is Jan 1, 1970");
8565 Py_DECREF(datetime);
8566 return -1;
8567 }
8568 if (PyObject_RichCompareBool(datetime, GLOBALS->maxtime, Py_GT)) {
8569 PyErr_SetString(PyExc_ValueError,
8570 "Maximum time is 03:14:07, Jan 19, 2038");
8571 Py_DECREF(datetime);
8572 return -1;
8573 }
8574 delta = PyNumber_Subtract(datetime, GLOBALS->epochtime);
8575 Py_DECREF(datetime);
8576 days = PyObject_GetAttrString(delta, "days");
8577 secs = PyObject_GetAttrString(delta, "seconds");
8578 usecs = PyObject_GetAttrString(delta, "microseconds");
8579 millisecs = (int64_t)PyLong_AsLong(days) * 1000 * 24 * 3600 +
8580 (int64_t)PyLong_AsLong(secs) * 1000 +
8581 PyLong_AsLong(usecs) / 1000;
8582 if (!PyErr_Occurred()) {
8583 *silktime = millisecs;
8584 retval = 0;
8585 }
8586 Py_XDECREF(delta);
8587 Py_XDECREF(days);
8588 Py_XDECREF(secs);
8589 Py_XDECREF(usecs);
8590
8591 return retval;
8592 }
8593
8594 #if !SK_ENABLE_IPV6
8595 static PyObject *
silkPyNotImplemented(PyObject UNUSED (* self),PyObject UNUSED (* args),PyObject UNUSED (* kwds))8596 silkPyNotImplemented(
8597 PyObject UNUSED(*self),
8598 PyObject UNUSED(*args),
8599 PyObject UNUSED(*kwds))
8600 {
8601 return PyErr_Format(PyExc_NotImplementedError,
8602 "SiLK was not built with IPv6 support.");
8603 }
8604 #endif /* !SK_ENABLE_IPV6 */
8605
8606
8607 static PyObject *
initpysilkbase(char * name)8608 initpysilkbase(
8609 char* name)
8610 {
8611 #if PY_MAJOR_VERSION >= 3
8612 /* Module information for Python 3.0 */
8613 static struct PyModuleDef pysilk_module_static = {
8614 PyModuleDef_HEAD_INIT,
8615 NULL, /* m_name */
8616 NULL, /* m_doc */
8617 sizeof(silkpy_globals_t), /* m_size */
8618 silk_methods, /* m_methods */
8619 NULL, /* m_reaload (unused) */
8620 NULL, /* m_traverse */
8621 NULL, /* m_clear */
8622 NULL /* m_free */
8623 };
8624 #endif
8625
8626 PyObject *silkmod;
8627 PyObject *tmp;
8628 silkpy_globals_t *globals;
8629
8630 PyDateTime_IMPORT;
8631
8632 #if PY_MAJOR_VERSION >= 3
8633 pysilk_module = &pysilk_module_static;
8634 pysilk_module->m_name = name;
8635 silkmod = PyModule_Create(pysilk_module);
8636 if (silkmod == NULL) {
8637 skAppPrintErr("Could not create module silk");
8638 goto err;
8639 }
8640 globals = (silkpy_globals_t*)PyModule_GetState(silkmod);
8641 #else
8642 /* Globals are in the static global variable */
8643 globals = &silkpy_globals_static;
8644 silkmod = Py_InitModule3(name, silk_methods, "SiLK extension module");
8645 if (silkmod == NULL) {
8646 skAppPrintErr("Could not create module silk");
8647 goto err;
8648 }
8649 #endif /* #else of #if PY_MAJOR_VERSION >= 3 */
8650
8651 memset(globals, 0, sizeof(*globals));
8652 globals->silkmod = silkmod;
8653 globals->havesite = Py_False;
8654 Py_INCREF(globals->havesite);
8655
8656 if (init_silkfile_module(silkmod)) {
8657 goto err;
8658 }
8659
8660 if (silkPyIPAddr_setup(silkmod) != 0) {
8661 goto err;
8662 }
8663
8664 if (PyType_Ready(&silkPyIPv4AddrType) < 0) {
8665 goto err;
8666 }
8667 ASSERT_RESULT(PyModule_AddObject(silkmod, "IPv4Addr",
8668 (PyObject*)&silkPyIPv4AddrType),
8669 int, 0);
8670
8671 if (PyType_Ready(&silkPyIPv6AddrType) < 0) {
8672 goto err;
8673 }
8674 ASSERT_RESULT(PyModule_AddObject(silkmod, "IPv6Addr",
8675 (PyObject*)&silkPyIPv6AddrType),
8676 int, 0);
8677
8678 if (PyType_Ready(&silkPyIPWildcardType) < 0) {
8679 goto err;
8680 }
8681 ASSERT_RESULT(PyModule_AddObject(silkmod, "IPWildcard",
8682 (PyObject*)&silkPyIPWildcardType),
8683 int, 0);
8684
8685 silkPyIPWildcardIterType.tp_new = PyType_GenericNew;
8686 if (PyType_Ready(&silkPyIPWildcardIterType) < 0) {
8687 goto err;
8688 }
8689 ASSERT_RESULT(PyModule_AddObject(silkmod, "IPWildcardIter",
8690 (PyObject*)&silkPyIPWildcardIterType),
8691 int, 0);
8692
8693 silkPyIPSetType.tp_new = PyType_GenericNew;
8694 if (PyType_Ready(&silkPyIPSetType) < 0) {
8695 goto err;
8696 }
8697 ASSERT_RESULT(PyModule_AddObject(silkmod, "IPSetBase",
8698 (PyObject*)&silkPyIPSetType),
8699 int, 0);
8700
8701 silkPyIPSetIterType.tp_new = PyType_GenericNew;
8702 if (PyType_Ready(&silkPyIPSetIterType) < 0) {
8703 goto err;
8704 }
8705 ASSERT_RESULT(PyModule_AddObject(silkmod, "IPSetIter",
8706 (PyObject*)&silkPyIPSetIterType),
8707 int, 0);
8708
8709 silkPyPmapType.tp_new = PyType_GenericNew;
8710 if (PyType_Ready(&silkPyPmapType) < 0) {
8711 goto err;
8712 }
8713 ASSERT_RESULT(PyModule_AddObject(silkmod, "PMapBase",
8714 (PyObject*)&silkPyPmapType),
8715 int, 0);
8716
8717 silkPyPmapIterType.tp_new = PyType_GenericNew;
8718 if (PyType_Ready(&silkPyPmapIterType) < 0) {
8719 goto err;
8720 }
8721 ASSERT_RESULT(PyModule_AddObject(silkmod, "PMapBaseIter",
8722 (PyObject*)&silkPyPmapIterType),
8723 int, 0);
8724
8725 if (silkPyBag_setup(silkmod) != 0) {
8726 goto err;
8727 }
8728
8729 silkPyBagIterType.tp_new = PyType_GenericNew;
8730 if (PyType_Ready(&silkPyBagIterType) < 0) {
8731 goto err;
8732 }
8733 ASSERT_RESULT(PyModule_AddObject(silkmod, "BagBaseIter",
8734 (PyObject*)&silkPyBagIterType),
8735 int, 0);
8736
8737 silkPyRepoIterType.tp_new = PyType_GenericNew;
8738 if (PyType_Ready(&silkPyRepoIterType) < 0) {
8739 goto err;
8740 }
8741 ASSERT_RESULT(PyModule_AddObject(silkmod, "RepoIter",
8742 (PyObject*)&silkPyRepoIterType),
8743 int, 0);
8744
8745 if (silkPyTCPFlags_setup(silkmod)) {
8746 goto err;
8747 }
8748
8749 if (PyType_Ready(&silkPyRawRWRecType) < 0) {
8750 goto err;
8751 }
8752 ASSERT_RESULT(PyModule_AddObject(silkmod, "RawRWRec",
8753 (PyObject*)&silkPyRawRWRecType),
8754 int, 0);
8755
8756 silkPyRWRecType.tp_new = PyType_GenericNew;
8757 if (PyType_Ready(&silkPyRWRecType) < 0) {
8758 goto err;
8759 }
8760 ASSERT_RESULT(PyModule_AddObject(silkmod, "RWRecBase",
8761 (PyObject*)&silkPyRWRecType),
8762 int, 0);
8763
8764 tmp = PyImport_ImportModule("datetime");
8765 if (tmp == NULL) {
8766 skAppPrintErr("Failed to import datetime module");
8767 goto err;
8768 }
8769
8770 globals->timedelta = PyObject_GetAttrString(tmp, "timedelta");
8771 assert(globals->timedelta != NULL);
8772 ASSERT_RESULT(PyModule_AddObject(silkmod, "_timedelta", globals->timedelta),
8773 int, 0);
8774
8775 globals->datetime = PyObject_GetAttrString(tmp, "datetime");
8776 assert(globals->datetime != NULL);
8777 ASSERT_RESULT(PyModule_AddObject(silkmod, "_datetime", globals->datetime),
8778 int, 0);
8779
8780 Py_DECREF(tmp);
8781
8782 globals->maxelapsed = PyObject_CallFunction(globals->timedelta,
8783 "iiik", 0, 0, 0, UINT32_MAX);
8784 assert(globals->maxelapsed != NULL);
8785 ASSERT_RESULT(PyModule_AddObject(silkmod, "_maxelapsed",
8786 globals->maxelapsed),
8787 int, 0);
8788
8789 globals->minelapsed = PyObject_CallObject(globals->timedelta, NULL);
8790 assert(globals->minelapsed != NULL);
8791 ASSERT_RESULT(PyModule_AddObject(silkmod, "_minelapsed",
8792 globals->minelapsed),
8793 int, 0);
8794
8795 globals->epochtime = PyObject_CallFunction(globals->datetime, "iii",
8796 1970, 1, 1);
8797 assert(globals->epochtime != NULL);
8798 ASSERT_RESULT(PyModule_AddObject(silkmod, "_epochtime",
8799 globals->epochtime),
8800 int, 0);
8801
8802 globals->maxtime = PyObject_CallFunction(
8803 globals->datetime, "iiiiii", 2038, 1, 19, 3, 14, 7);
8804 assert(globals->maxtime != NULL);
8805 ASSERT_RESULT(PyModule_AddObject(silkmod, "_maxtime",
8806 globals->maxtime),
8807 int, 0);
8808
8809 globals->thousand = PyFloat_FromDouble(1000.0);
8810 assert(globals->thousand != NULL);
8811 ASSERT_RESULT(PyModule_AddObject(silkmod, "_thousand", globals->thousand),
8812 int, 0);
8813
8814 globals->maxintipv4 = PyLong_FromString("0xffffffff", NULL, 0);
8815 assert(globals->maxintipv4 != NULL);
8816 ASSERT_RESULT(PyModule_AddObject(globals->silkmod, "_maxintipv4",
8817 globals->maxintipv4),
8818 int, 0);
8819
8820 #if SK_ENABLE_IPV6
8821 globals->maxintipv6 =
8822 PyLong_FromString("0xffffffffffffffffffffffffffffffff", NULL, 0);
8823 assert(globals->maxintipv6 != NULL);
8824 ASSERT_RESULT(PyModule_AddObject(silkmod, "_maxintipv6",
8825 globals->maxintipv6),
8826 int, 0);
8827 #endif /* SK_ENABLE_IPV6 */
8828
8829 globals->newrawrec = PyObject_CallFunctionObjArgs(
8830 (PyObject *)&silkPyRawRWRecType, NULL);
8831 ASSERT_RESULT(PyModule_AddObject(silkmod, "_newrawrec",
8832 globals->newrawrec),
8833 int, 0);
8834
8835 return silkmod;
8836
8837 err:
8838 if (silkmod) {
8839 Py_DECREF(silkmod);
8840 }
8841 #if PY_MAJOR_VERSION >= 3
8842 return NULL;
8843 #else /* PY_MAJOR_VERSION < 3 */
8844 if (PyErr_Occurred()) {
8845 PyErr_Print();
8846 }
8847 exit(EXIT_FAILURE);
8848 #endif /* PY_MAJOR_VERSION */
8849 }
8850
8851 PyMODINIT_FUNC
PYSILK_INIT(void)8852 PYSILK_INIT(
8853 void)
8854 {
8855 PyObject *nameobj;
8856
8857 nameobj = BYTES_FROM_XCHAR(Py_GetProgramName());
8858
8859 if (nameobj == NULL) {
8860 skAppRegister("PySiLK_program");
8861 } else {
8862 skAppRegister(PyBytes_AS_STRING(nameobj));
8863 Py_DECREF(nameobj);
8864 }
8865 INIT_RETURN(initpysilkbase(STR(PYSILK_NAME)));
8866 }
8867
8868 PyMODINIT_FUNC
PYSILK_PIN_INIT(void)8869 PYSILK_PIN_INIT(
8870 void)
8871 {
8872 INIT_RETURN(initpysilkbase("silk." STR(PYSILK_PIN_NAME)));
8873 }
8874
8875
8876 /*
8877 ** Local Variables:
8878 ** mode:c
8879 ** indent-tabs-mode:nil
8880 ** c-basic-offset:4
8881 ** End:
8882 */
8883