2 #include "structmember.h"
9 auparse functions explicitly not exported in this binding and why:
11 auparse_destroy: because this is handled by python object management
12 auparse_get_time: because AuEvent provides this as an attribute
13 auparse_get_milli: because AuEvent provides this as an attribute
14 auparse_get_serial: because AuEvent provides this as an attribute
15 auparse_get_node: because AuEvent provides this as an attribute
16 auparse_timestamp_compare: because AuEvent calls this via the cmp operator
20 #if PY_MAJOR_VERSION > 2
22 #define MODINITERROR return NULL
23 #define PYNUM_FROMLONG PyLong_FromLong
24 #define PYSTR_CHECK PyUnicode_Check
25 #define PYSTR_FROMSTRING PyUnicode_FromString
26 #define PYSTR_ASSTRING PyUnicode_AsUTF8
27 #define PYFILE_ASFILE(f) fdopen(PyObject_AsFileDescriptor(f), "r")
28 int PyFile_Check(PyObject *f) {
30 if (!(io = PyImport_ImportModule("io"))) {
33 if (!(base = PyObject_GetAttrString(io, "TextIOBase"))) {
36 return PyObject_IsInstance(f, base);
41 #define MODINITERROR return
42 #define PYNUM_FROMLONG PyInt_FromLong
43 #define PYSTR_CHECK PyString_Check
44 #define PYSTR_FROMSTRING PyString_FromString
45 #define PYSTR_ASSTRING PyString_AsString
46 #define PYFILE_ASFILE(f) PyFile_AsFile(f)
50 static PyObject *NoParserError = NULL;
52 /*===========================================================================
54 *===========================================================================*/
66 AuEvent_dealloc(AuEvent* self)
68 Py_XDECREF(self->sec);
69 Py_XDECREF(self->milli);
70 Py_XDECREF(self->serial);
71 Py_XDECREF(self->host);
72 Py_TYPE(self)->tp_free((PyObject*)self);
76 AuEvent_compare(PyObject *obj1, PyObject *obj2)
78 AuEvent *au_event1 = (AuEvent *) obj1;
79 AuEvent *au_event2 = (AuEvent *) obj2;
81 return auparse_timestamp_compare(&au_event1->event, &au_event2->event);
85 AuEvent_get_sec(AuEvent *self, void *closure)
87 if (self->sec == NULL) {
88 if ((self->sec = PYNUM_FROMLONG(self->event.sec)) == NULL) return NULL;
95 AuEvent_get_milli(AuEvent *self, void *closure)
97 if (self->milli == NULL) {
98 if ((self->milli = PYNUM_FROMLONG(self->event.milli)) == NULL) return NULL;
100 Py_INCREF(self->milli);
105 AuEvent_get_serial(AuEvent *self, void *closure)
107 if (self->serial == NULL) {
108 if ((self->serial = PYNUM_FROMLONG(self->event.serial)) == NULL) return NULL;
110 Py_INCREF(self->serial);
115 AuEvent_get_host(AuEvent *self, void *closure)
117 if (self->event.host == NULL) {
120 if (self->host == NULL) {
121 if ((self->host = PYSTR_FROMSTRING(self->event.host)) == NULL) return NULL;
123 Py_INCREF(self->host);
128 static PyGetSetDef AuEvent_getseters[] = {
129 {"sec", (getter)AuEvent_get_sec, (setter)NULL, "Event seconds", NULL},
130 {"milli", (getter)AuEvent_get_milli, (setter)NULL, "millisecond of the timestamp", NULL},
131 {"serial", (getter)AuEvent_get_serial, (setter)NULL, "Serial number of the event", NULL},
132 {"host", (getter)AuEvent_get_host, (setter)NULL, "Machine's name", NULL},
133 {NULL} /* Sentinel */
136 static PyMemberDef AuEvent_members[] = {
137 {NULL} /* Sentinel */
141 fmt_event(time_t seconds, unsigned int milli, unsigned long serial, const char *host)
143 static char buf1[200], buf2[200];
144 char fmt[] = "%a %b %d %H:%M:%S.%%ld %Y serial=%%ld host=%%s";
147 tmp = localtime(&seconds);
149 sprintf(buf2, "localtime error");
153 if (strftime(buf1, sizeof(buf1), fmt, tmp) == 0) {
154 sprintf(buf2, "strftime returned 0");
158 snprintf(buf2, sizeof(buf2), buf1, milli, serial, host, sizeof(buf2));
163 AuEvent_str(PyObject * obj)
165 AuEvent *event = (AuEvent *) obj;
166 return PYSTR_FROMSTRING(fmt_event(event->event.sec, event->event.milli, event->event.serial, event->event.host));
170 static PyMethodDef AuEvent_methods[] = {
171 {NULL} /* Sentinel */
174 PyDoc_STRVAR(AuEvent_doc,
175 "An internal object which encapsulates the timestamp, serial number\n\
176 and host information of an audit event. The object cannot be\n\
177 instantiated from python code, rather it is returned from the\n\
178 audit parsing API.");
180 static PyTypeObject AuEventType = {
181 PyVarObject_HEAD_INIT(NULL, 0)
182 "auparse.AuEvent", /*tp_name*/
183 sizeof(AuEvent), /*tp_basicsize*/
185 (destructor)AuEvent_dealloc, /*tp_dealloc*/
189 AuEvent_compare, /*tp_compare*/
192 0, /*tp_as_sequence*/
196 AuEvent_str, /*tp_str*/
200 Py_TPFLAGS_DEFAULT, /*tp_flags*/
201 AuEvent_doc, /* tp_doc */
204 0, /* tp_richcompare */
205 0, /* tp_weaklistoffset */
208 AuEvent_methods, /* tp_methods */
209 AuEvent_members, /* tp_members */
210 AuEvent_getseters, /* tp_getset */
213 0, /* tp_descr_get */
214 0, /* tp_descr_set */
215 0, /* tp_dictoffset */
222 AuEvent_new_from_struct(au_event_t const *event_ptr)
226 self = (AuEvent *)AuEventType.tp_alloc(&AuEventType, 0);
228 self->event = *event_ptr;
231 return (PyObject *)self;
234 /*===========================================================================
236 *===========================================================================*/
238 #define PARSER_CHECK \
239 if (self->au == NULL) { \
240 PyErr_SetString(NoParserError, "object has no parser associated with it"); \
250 AuParser *py_AuParser;
255 void callback_data_destroy(void *user_data)
257 CallbackData *cb = (CallbackData *)user_data;
259 if (debug) printf("<< callback_data_destroy\n");
262 Py_XDECREF(cb->user_data);
267 static void auparse_callback(auparse_state_t *au, auparse_cb_event_t cb_event_type, void *user_data)
269 CallbackData *cb = (CallbackData *)user_data;
273 arglist = Py_BuildValue("OiO", cb->py_AuParser, cb_event_type, cb->user_data);
274 result = PyEval_CallObject(cb->func, arglist);
280 AuParser_dealloc(AuParser* self)
282 if (debug) printf("<< AuParser_dealloc: self=%p au=%p\n", self, self->au);
283 if (self->au != NULL) {
284 auparse_destroy(self->au);
286 Py_TYPE(self)->tp_free((PyObject*)self);
290 AuParser_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
294 self = (AuParser *)type->tp_alloc(type, 0);
298 return (PyObject *)self;
301 /********************************
303 ********************************/
305 AuParser_init(AuParser *self, PyObject *args, PyObject *kwds)
307 static char *kwlist[] = {"source_type", "source", NULL};
308 int source_type = -1;
309 PyObject *source=Py_None;
311 if (self->au != NULL) {
312 auparse_destroy(self->au);
316 if (! PyArg_ParseTupleAndKeywords(args, kwds, "|iO", kwlist, &source_type, &source)) return -1;
318 switch (source_type) {
319 case AUSOURCE_LOGS: {
320 if (source != Py_None) {
321 PyErr_SetString(PyExc_ValueError, "source must be None or not passed as a parameter when source_type is AUSOURCE_LOGS");
324 if ((self->au = auparse_init(source_type, NULL)) == NULL) {
325 PyErr_SetFromErrno(PyExc_IOError);
329 case AUSOURCE_FILE: {
330 char *filename = NULL;
332 if (!PYSTR_CHECK(source)) {
333 PyErr_SetString(PyExc_ValueError, "source must be a string when source_type is AUSOURCE_FILE");
336 if ((filename = PYSTR_ASSTRING(source)) == NULL) return -1;
337 if ((self->au = auparse_init(source_type, filename)) == NULL) {
338 PyErr_SetFromErrnoWithFilename(PyExc_IOError, filename);
342 case AUSOURCE_FILE_ARRAY: {
344 PyObject *item = NULL;
347 if (PySequence_Check(source)) {
348 n = PySequence_Size(source);
349 if ((files = PyMem_New(char *, n+1)) == NULL) {
353 for (i = 0; i < n; i++) {
354 item = PySequence_GetItem(source, i);
355 if ((files[i] = PYSTR_ASSTRING(item)) == NULL) {
356 PyErr_SetString(PyExc_ValueError, "members of source sequence must be a string when source_type is AUSOURCE_FILE_ARRAY");
366 PyErr_SetString(PyExc_ValueError, "source must be a sequence when source_type is AUSOURCE_FILE_ARRAY");
370 if ((self->au = auparse_init(source_type, files)) == NULL) {
371 PyErr_SetFromErrno(PyExc_IOError);
377 case AUSOURCE_BUFFER: {
379 if ((buf = PYSTR_ASSTRING(source)) == NULL) return -1;
380 if ((self->au = auparse_init(source_type, buf)) == NULL) {
381 PyErr_SetFromErrno(PyExc_EnvironmentError);
385 case AUSOURCE_BUFFER_ARRAY: {
387 PyObject *item = NULL;
388 char **buffers = NULL;
390 if (PySequence_Check(source)) {
391 n = PySequence_Size(source);
392 if ((buffers = PyMem_New(char *, n+1)) == NULL) {
396 for (i = 0; i < n; i++) {
397 item = PySequence_GetItem(source, i);
398 if ((buffers[i] = PYSTR_ASSTRING(item)) == NULL) {
399 PyErr_SetString(PyExc_ValueError, "members of source sequence must be a string when source_type is AUSOURCE_BUFFER_ARRAY");
409 PyErr_SetString(PyExc_ValueError, "source must be a sequence when source_type is AUSOURCE_FILE_ARRAY");
413 if ((self->au = auparse_init(source_type, buffers)) == NULL) {
414 PyErr_SetFromErrno(PyExc_EnvironmentError);
420 case AUSOURCE_DESCRIPTOR: {
422 fd = PyObject_AsFileDescriptor(source);
424 PyErr_SetString(PyExc_ValueError, "source must be resolvable to a file descriptor when source_type is AUSOURCE_DESCRIPTOR");
428 case AUSOURCE_FILE_POINTER: {
431 if (!PyFile_Check(source)) {
432 PyErr_SetString(PyExc_ValueError, "source must be a file object when source_type is AUSOURCE_FILE_POINTER");
435 if ((fp = PYFILE_ASFILE(source)) == NULL) {
436 PyErr_SetString(PyExc_TypeError, "source must be open file when source_type is AUSOURCE_FILE_POINTER");
439 if ((self->au = auparse_init(source_type, fp)) == NULL) {
440 //char *filename = PYSTR_ASSTRING(PyFile_Name(source));
441 char *filename = "TODO";
442 PyErr_SetFromErrnoWithFilename(PyExc_IOError, filename);
446 case AUSOURCE_FEED: {
447 if (source != Py_None) {
448 PyErr_SetString(PyExc_ValueError, "source must be None when source_type is AUSOURCE_FEED");
451 if ((self->au = auparse_init(source_type, NULL)) == NULL) {
452 PyErr_SetFromErrno(PyExc_EnvironmentError);
457 PyErr_SetString(PyExc_ValueError, "Invalid source type");
462 if (debug) printf(">> AuParser_init: self=%p au=%p\n", self, self->au);
466 /********************************
468 ********************************/
469 PyDoc_STRVAR(feed_doc,
470 "feed(data) supplies new data for the parser to consume.\n\
472 AuParser() must have been called with a source type of AUSOURCE_FEED.\n\
473 The parser consumes as much data as it can invoking a user supplied\n\
474 callback specified with add_callback() with a cb_event_type of\n\
475 AUPARSE_CB_EVENT_READY each time the parser recognizes a complete event\n\
476 in the data stream. Data not fully parsed will persist and be prepended\n\
477 to the next feed data. After all data has been feed to the parser flush_feed()\n\
478 should be called to signal the end of input data and flush any pending\n\
479 parse data through the parsing system.\n\
482 Raises exception (EnvironmentError) on error\n\
485 AuParser_feed(AuParser *self, PyObject *args)
491 if (!PyArg_ParseTuple(args, "s#:feed", &data, &data_len)) return NULL;
493 result = auparse_feed(self->au, data, data_len);
494 if (result == 0) Py_RETURN_NONE;
495 PyErr_SetFromErrno(PyExc_EnvironmentError);
499 /********************************
501 ********************************/
502 PyDoc_STRVAR(flush_feed_doc,
503 "flush_feed() flush any unconsumed feed data through parser\n\
505 flush_feed() should be called to signal the end of feed input data\n\
506 and flush any pending parse data through the parsing system.\n\
509 Raises exception (EnvironmentError) on error\n\
512 AuParser_flush_feed(AuParser *self)
517 result = auparse_flush_feed(self->au);
518 if (result == 0) Py_RETURN_NONE;
519 PyErr_SetFromErrno(PyExc_EnvironmentError);
523 /********************************
524 * auparse_add_callback
525 ********************************/
526 PyDoc_STRVAR(add_callback_doc,
527 "add_callback(callback, user_data) add a callback handler for notifications.\n\
529 auparse_add_callback adds a callback function to the parse state which\n\
530 is invoked to notify the application of parsing events.\n\
532 The signature of the callback is:\n\
534 callback(au, cb_event_type,user_data)\n\
536 When the callback is invoked it is passed:\n\
537 au: the AuParser object\n\
538 cb_event_type: enumerated value indicating the reason why the callback was invoked\n\
539 user_data: user supplied private data\n\
541 The cb_event_type argument indicates why the callback was invoked.\n\
542 It's possible values are:\n\
544 AUPARSE_CB_EVENT_READY\n\
545 A complete event has been parsed and is ready to be examined.\n\
546 This is logically equivalent to the parse state immediately following\n\
547 auparse_next_event()\n\
550 Raises exception (EnvironmentError) on error\n\
553 AuParser_add_callback(AuParser *self, PyObject *args)
558 if (!PyArg_ParseTuple(args, "O|O:add_callback", &func, &user_data)) return NULL;
559 if (!PyFunction_Check(func)) {
560 PyErr_SetString(PyExc_ValueError, "callback must be a function");
568 cb = PyMem_New(CallbackData, 1);
570 return PyErr_NoMemory();
571 cb->py_AuParser = self;
573 cb->user_data = user_data;
575 Py_XINCREF(cb->user_data);
576 auparse_add_callback(self->au, auparse_callback, cb, callback_data_destroy);
582 /********************************
584 ********************************/
585 PyDoc_STRVAR(reset_doc,
586 "reset() Reset audit parser instance\n\
588 reset resets all internal cursors to the beginning.\n\
589 It closes files and descriptors.\n\
592 Raises exception (EnvironmentError) on error\n\
595 AuParser_reset(AuParser *self)
600 result = auparse_reset(self->au);
601 if (result == 0) Py_RETURN_NONE;
602 PyErr_SetFromErrno(PyExc_EnvironmentError);
606 /********************************
607 * ausearch_add_expression
608 ********************************/
609 PyDoc_STRVAR(search_add_expression_doc,
610 "search_add_expression(expression, how) Build up search expression\n\
613 ausearch_add_item adds an expression to the current audit search\n\
614 expression. The search conditions can then be used to scan logs,\n\
615 files, or buffers for something of interest. The expression parameter\n\
616 contains an expression, as specified in ausearch-expression(5).\n\
618 The how parameter determines how this search expression will affect the\n\
619 existing search expression, if one is already defined. The possible\n\
622 AUSEARCH_RULE_CLEAR:\n\
623 Clear the current search expression, if any, and use only this search\n\
628 If a search expression E is already configured, replace it by\n\
629 (E || this_search_expression).\n\
631 AUSEARCH_RULE_AND:\n\
632 If a search expression E is already configured, replace it by\n\
633 (E && this_search_expression).\n\
635 No Return value, raises exception (EnvironmentError) on error.\n\
638 AuParser_search_add_expression(AuParser *self, PyObject *args)
640 const char *expression;
645 if (!PyArg_ParseTuple(args, "si", &expression, &how)) return NULL;
648 result = ausearch_add_expression(self->au, expression, &error, how);
649 if (result == 0) Py_RETURN_NONE;
651 PyErr_SetFromErrno(PyExc_EnvironmentError);
653 PyErr_SetString(PyExc_EnvironmentError, error);
659 /********************************
661 ********************************/
662 PyDoc_STRVAR(search_add_item_doc,
663 "search_add_item(field, op, value, how) Build up search rule\n\
666 search_add_item() adds one search condition to the current audit search\n\
667 expression. The search conditions can then be used to scan logs, files, or\n\
668 buffers for something of interest. The field value is the field name\n\
669 that the value will be checked for. The op variable describes what\n\
670 kind of check is to be done. Legal op values are:\n\
673 Just check that a field name exists\n\
676 locate the field name and check that the value associated with it\n\
677 is equal to the value given in this rule.\n\
680 locate the field name and check that the value associated with\n\
681 it is NOT equal to the value given in this rule.\n\
683 The value parameter is compared to the uninterpreted field value.\n\
685 The how parameter determines how this search expression will affect the\n\
686 existing search expression, if one is already defined. The possible\n\
689 AUSEARCH_RULE_CLEAR:\n\
690 Clear the current search expression, if any, and use only this search\n\
695 If a search expression E is already configured, replace it by\n\
696 (E || this_search_expression).\n\
698 AUSEARCH_RULE_AND:\n\
699 If a search expression E is already configured, replace it by\n\
700 (E && this_search_expression).\n\
702 No Return value, raises exception (EnvironmentError) on error.\n\
706 AuParser_search_add_item(AuParser *self, PyObject *args)
714 if (!PyArg_ParseTuple(args, "sssi", &field, &op, &value, &how)) return NULL;
717 result = ausearch_add_item(self->au, field, op, value, how);
718 if (result == 0) Py_RETURN_NONE;
719 PyErr_SetFromErrno(PyExc_EnvironmentError);
723 /********************************
724 * ausearch_add_interpreted_item
725 ********************************/
726 PyDoc_STRVAR(search_add_interpreted_item_doc,
727 "search_add_interpreted_item(field, op, value, how) Build up search rule\n\
730 search_add_interpreted_item() adds one search condition to the current audit\n\
731 search expression. The search conditions can then be used to scan logs,\n\
732 files, or buffers for something of interest. The field value is the field\n\
733 name that the value will be checked for. The op variable describes what\n\
734 kind of check is to be done. Legal op values are:\n\
737 Just check that a field name exists\n\
740 locate the field name and check that the value associated with it\n\
741 is equal to the value given in this rule.\n\
744 locate the field name and check that the value associated with\n\
745 it is NOT equal to the value given in this rule.\n\
747 The value parameter is compared to the interpreted field value (the value\n\
748 that would be returned by AuParser.interpret_field).\n\
750 The how parameter determines how this search expression will affect the\n\
751 existing search expression, if one is already defined. The possible\n\
754 AUSEARCH_RULE_CLEAR:\n\
755 Clear the current search expression, if any, and use only this search\n\
760 If a search expression E is already configured, replace it by\n\
761 (E || this_search_expression).\n\
763 AUSEARCH_RULE_AND:\n\
764 If a search expression E is already configured, replace it by\n\
765 (E && this_search_expression).\n\
767 No Return value, raises exception (EnvironmentError) on error.\n\
771 AuParser_search_add_interpreted_item(AuParser *self, PyObject *args)
779 if (!PyArg_ParseTuple(args, "sssi", &field, &op, &value, &how)) return NULL;
782 result = ausearch_add_interpreted_item(self->au, field, op, value, how);
783 if (result == 0) Py_RETURN_NONE;
784 PyErr_SetFromErrno(PyExc_EnvironmentError);
788 /********************************
789 * ausearch_add_timestamp_item
790 ********************************/
791 PyDoc_STRVAR(search_add_timestamp_item_doc,
792 "search_add_timestamp_item(op, sec, milli, how) Build up search rule\n\
795 search_add_timestamp_item adds an event time condition to the current audit\n\
796 search expression. The search conditions can then be used to scan logs,\n\
797 files, or buffers for something of interest. The op parameter specifies the\n\
798 desired comparison. Legal op values are \"<\", \"<=\", \">=\", \">\" and\n\
799 \"=\". The left operand of the comparison operator is the timestamp of the\n\
800 examined event, the right operand is specified by the sec and milli\n\
803 The how parameter determines how this search expression will affect the\n\
804 existing search expression, if one is already defined. The possible\n\
807 AUSEARCH_RULE_CLEAR:\n\
808 Clear the current search expression, if any, and use only this search\n\
813 If a search expression E is already configured, replace it by\n\
814 (E || this_search_expression).\n\
816 AUSEARCH_RULE_AND:\n\
817 If a search expression E is already configured, replace it by\n\
818 (E && this_search_expression).\n\
820 No Return value, raises exception (EnvironmentError) on error.\n\
824 AuParser_search_add_timestamp_item(AuParser *self, PyObject *args)
832 /* There's no completely portable way to handle time_t values from Python;
833 note that time_t might even be a floating-point type! PY_LONG_LONG
834 is at least enough not to worry about year 2038.
836 milli is int because Python's 'I' format does no overflow checking.
837 Negative milli values will wrap to values > 1000 and
838 ausearch_add_timestamp_item will reject them. */
839 if (!PyArg_ParseTuple(args, "sLii", &op, &sec, &milli, &how))
843 result = ausearch_add_timestamp_item(self->au, op, sec, (unsigned)milli,
847 PyErr_SetFromErrno(PyExc_EnvironmentError);
851 /********************************
852 * ausearch_add_timestamp_item_ex
853 ********************************/
854 PyDoc_STRVAR(search_add_timestamp_item_ex_doc,
855 "search_add_timestamp_item_ex(op, sec, milli, serial, how) Build up search rule\n\
856 search_add_timestamp_item_ex adds an event time condition to the current audit\n\
857 search expression. Its similar to search_add_timestamp_item except it adds\n\
858 the event serial number.\n\
862 AuParser_search_add_timestamp_item_ex(AuParser *self, PyObject *args)
871 /* There's no completely portable way to handle time_t values from Python;
872 note that time_t might even be a floating-point type! PY_LONG_LONG
873 is at least enough not to worry about year 2038.
875 milli is int because Python's 'I' format does no overflow checking.
876 Negative milli values will wrap to values > 1000 and
877 ausearch_add_timestamp_item will reject them. */
878 if (!PyArg_ParseTuple(args, "sLiiii", &op, &sec, &milli, &serial, &how))
882 result = ausearch_add_timestamp_item_ex(self->au, op, sec, (unsigned)milli,
883 (unsigned)serial, how);
886 PyErr_SetFromErrno(PyExc_EnvironmentError);
890 /********************************
892 ********************************/
893 PyDoc_STRVAR(search_add_regex_doc,
894 "search_add_regex(regexp) Add a regular expression to the search criteria.\n\
896 No Return value, raises exception (EnvironmentError) on error.\n\
899 AuParser_search_add_regex(AuParser *self, PyObject *args)
904 if (!PyArg_ParseTuple(args, "s", ®exp)) return NULL;
906 result = ausearch_add_regex(self->au, regexp);
907 if (result == 0) Py_RETURN_NONE;
908 PyErr_SetFromErrno(PyExc_EnvironmentError);
912 /********************************
914 ********************************/
915 PyDoc_STRVAR(search_set_stop_doc,
916 "search_set_stop(where) Set where cursor is positioned on search match.\n\
918 search_set_stop() determines where the internal cursor will stop when\n\
919 a search condition is met. The possible values are:\n\
921 AUSEARCH_STOP_EVENT:\n\
922 This one repositions the cursors to the first field of the first\n\
923 record of the event con- taining the items searched for.\n\
925 AUSEARCH_STOP_RECORD:\n\
926 This one repositions the cursors to the first field of the record\n\
927 containing the items searched for.\n\
929 AUSEARCH_STOP_FIELD:\n\
930 This one simply stops on the current field when the evaluation of the\n\
931 rules becomes true.\n\
933 No Return value, raises exception (ValueError) on error.\n\
936 AuParser_search_set_stop(AuParser *self, PyObject *args)
941 if (!PyArg_ParseTuple(args, "i", &where)) return NULL;
943 result = ausearch_set_stop(self->au, where);
944 if (result == 0) Py_RETURN_NONE;
945 PyErr_SetFromErrno(PyExc_ValueError);
949 /********************************
951 ********************************/
952 PyDoc_STRVAR(search_clear_doc,
953 "search_clear() Clear search parameters.\n\
955 ausearch_clear clears any search parameters stored in the parser\n\
956 instance and frees memory associated with it.\n\
961 AuParser_search_clear(AuParser *self)
964 ausearch_clear(self->au);
968 /********************************
969 * ausearch_next_event
970 ********************************/
971 PyDoc_STRVAR(search_next_event_doc,
972 "search_next_event() Find the next event that meets search criteria.\n\
974 search_next_event() will scan the input source and evaluate whether\n\
975 any record in an event contains the data being searched\n\
976 for. Evaluation is done at the record level.\n\
978 Returns True if a match was found\n\
979 Returns False if a match was not found.\n\
981 Raises exception (EnvironmentError) on error\n\
984 AuParser_search_next_event(AuParser *self)
989 result = ausearch_next_event(self->au);
990 if (result > 0) Py_RETURN_TRUE;
991 if (result == 0) Py_RETURN_FALSE;
992 PyErr_SetFromErrno(PyExc_EnvironmentError);
996 /********************************
998 ********************************/
999 PyDoc_STRVAR(parse_next_event_doc,
1000 "parse_next_event() Advance the parser to the next event.\n\
1002 parse_next_event() will position the cursors at the first field of the first\n\
1003 record of the next event in a file or buffer. It does not skip events\n\
1004 or honor any search criteria that may be stored.\n\
1006 Returns True if parser advances to next event.\n\
1007 Returns False if there are no more events to parse\n\
1009 Raises exception (EnvironmentError) on error\n\
1012 AuParser_parse_next_event(AuParser *self)
1017 result = auparse_next_event(self->au);
1018 if (result > 0) Py_RETURN_TRUE;
1019 if (result == 0) Py_RETURN_FALSE;
1020 PyErr_SetFromErrno(PyExc_EnvironmentError);
1024 /********************************
1025 * auparse_get_timestamp
1026 ********************************/
1027 PyDoc_STRVAR(get_timestamp_doc,
1028 "get_timestamp() Return current event's timestamp.\n\
1030 Returns the current event's timestamp info as an AuEvent object.\n\
1031 No Return value, raises exception (EnvironmentError) on error.\n\
1034 AuParser_get_timestamp(AuParser *self)
1036 const au_event_t *event_ptr;
1040 event_ptr = auparse_get_timestamp(self->au);
1042 if (event_ptr == NULL) {
1044 PyErr_SetFromErrno(PyExc_EnvironmentError);
1050 py_event = AuEvent_new_from_struct(event_ptr);
1051 Py_INCREF(py_event); /* FIXME: should we be bumping the ref count? */
1055 /********************************
1056 * auparse_get_num_records
1057 ********************************/
1058 PyDoc_STRVAR(get_num_records_doc,
1059 "get_num_records() Get the number of records.\n\
1061 Returns the number of records in the current event.\n\
1062 Raises exception (EnvironmentError) on error.\n\
1065 AuParser_get_num_records(AuParser *self)
1070 num_records = auparse_get_num_records(self->au);
1071 if (num_records == 0) {
1072 PyErr_SetFromErrno(PyExc_EnvironmentError);
1075 return Py_BuildValue("i", num_records);
1078 /********************************
1079 * auparse_first_record
1080 ********************************/
1081 PyDoc_STRVAR(first_record_doc,
1082 "first_record() Reposition record cursor.\n\
1084 first_record() repositions the internal cursors of the parsing library\n\
1085 to point to the first record in the current event.\n\
1087 Return True for success, False if there is no event data.\n\
1088 Raises exception (EnvironmentError) on error.\n\
1091 AuParser_first_record(AuParser *self)
1096 result = auparse_first_record(self->au);
1097 if (result > 0) Py_RETURN_TRUE;
1098 if (result == 0) Py_RETURN_FALSE;
1099 PyErr_SetFromErrno(PyExc_EnvironmentError);
1103 /********************************
1104 * auparse_next_record
1105 ********************************/
1106 PyDoc_STRVAR(next_record_doc,
1107 "next_record() Advance record cursor.\n\
1109 next_record() will move the internal library cursors to point to the\n\
1110 next record of the current event.\n\
1112 Returns True on success, False if no more records in current event\n\
1113 Raises exception (EnvironmentError) on error.\n\
1116 AuParser_next_record(AuParser *self)
1121 result = auparse_next_record(self->au);
1123 if (result > 0) Py_RETURN_TRUE;
1124 if (result == 0) Py_RETURN_FALSE;
1125 PyErr_SetFromErrno(PyExc_EnvironmentError);
1129 /********************************
1130 * auparse_goto_record_num
1131 ********************************/
1132 PyDoc_STRVAR(goto_record_num_doc,
1133 "goto_record_num() Move record cursor to specific position.\n\
1135 goto_record_num() will move the internal library cursors to point\n\
1136 to a specific physical record number. Records within the same event are\n\
1137 numbered starting from 0. This is generally not needed but there are\n\
1138 some cases where one may want precise control over the exact record\n\
1141 Returns True on success, False if no more records in current event\n\
1142 Raises exception (EnvironmentError) on error.\n\
1145 AuParser_goto_record_num(AuParser *self, PyObject *args)
1150 if (!PyArg_ParseTuple(args, "i", &num)) return NULL;
1152 result = auparse_goto_record_num(self->au, num);
1154 if (result > 0) Py_RETURN_TRUE;
1155 if (result == 0) Py_RETURN_FALSE;
1156 PyErr_SetFromErrno(PyExc_EnvironmentError);
1160 /********************************
1162 ********************************/
1163 PyDoc_STRVAR(get_type_doc,
1164 "get_type() Get record’s type.\n\
1166 get_type() will return the integer value for the current record of the\n\
1169 Returns record type.\n\
1170 Raises exception (LookupError) on error.\n\
1173 AuParser_get_type(AuParser *self)
1178 value = auparse_get_type(self->au);
1181 PyErr_SetString(PyExc_LookupError, "Not found");
1184 return Py_BuildValue("i", value);
1187 /********************************
1188 * auparse_get_type_name
1189 ********************************/
1190 PyDoc_STRVAR(get_type_name_doc,
1191 "get_type_name() Get current record’s type name.\n\
1193 get_type_name() allows access to the current record type name in the\n\
1196 Returns None if the record type name is unavailable.\n\
1199 AuParser_get_type_name(AuParser *self)
1201 const char *name = NULL;
1204 name = auparse_get_type_name(self->au);
1205 return Py_BuildValue("s", name);
1208 /********************************
1209 * auparse_get_line_number
1210 ********************************/
1211 PyDoc_STRVAR(get_line_number_doc,
1212 "auparse_get_line_number() get line number where record was found\n\
1214 get_line_number will return the source input line number for\n\
1215 the current record of the current event. Line numbers start at 1. If\n\
1216 the source input type is AUSOURCE_FILE_ARRAY the line numbering will\n\
1217 reset back to 1 each time a new life in the file array is opened.\n\
1220 AuParser_get_line_number(AuParser *self)
1225 value = auparse_get_line_number(self->au);
1226 return Py_BuildValue("I", value);
1229 /********************************
1230 * auparse_get_filename
1231 ********************************/
1232 PyDoc_STRVAR(get_filename_doc,
1233 "auparse_get_filename() get the filename where record was found\n\
1234 get_filename() will return the name of the source file where the\n\
1235 record was found if the source type is AUSOURCE_FILE or\n\
1236 AUSOURCE_FILE_ARRAY. For other source types the return value will be\n\
1240 AuParser_get_filename(AuParser *self)
1245 value = auparse_get_filename(self->au);
1247 if (value == NULL) Py_RETURN_NONE;
1248 return Py_BuildValue("s", value);
1251 /********************************
1252 * auparse_first_field
1253 ********************************/
1254 PyDoc_STRVAR(first_field_doc,
1255 "first_field() Reposition field cursor.\n\
1257 Returns True on success, False if there is no event data\n\
1260 AuParser_first_field(AuParser *self)
1265 result = auparse_first_field(self->au);
1267 if (result == 0) Py_RETURN_FALSE;
1271 /********************************
1272 * auparse_next_field
1273 ********************************/
1274 PyDoc_STRVAR(next_field_doc,
1275 "next_field() Advance the field cursor.\n\
1277 next_field() moves the library’s internal cursor to point to the next\n\
1278 field in the current record of the current event.\n\
1280 Returns True on success, False if there is no more fields exist\n\
1283 AuParser_next_field(AuParser *self)
1288 result = auparse_next_field(self->au);
1290 if (result == 0) Py_RETURN_FALSE;
1294 /********************************
1295 * auparse_get_num_fields
1296 ********************************/
1297 PyDoc_STRVAR(get_num_fields_doc,
1298 "get_num_fields() Get the number of fields.\n\
1300 Returns the number of fields in the current event.\n\
1301 Raises exception (EnvironmentError) on error.\n\
1304 AuParser_get_num_fields(AuParser *self)
1309 num_fields = auparse_get_num_fields(self->au);
1310 if (num_fields == 0) {
1311 PyErr_SetFromErrno(PyExc_EnvironmentError);
1314 return Py_BuildValue("i", num_fields);
1317 /********************************
1318 * auparse_get_record_text
1319 ********************************/
1320 PyDoc_STRVAR(get_record_text_doc,
1321 "get_record_text() Return unparsed record data\n\
1323 get_record_text() returns the full unparsed record.\n\
1324 Raises exception (EnvironmentError) on error.\n\
1327 AuParser_get_record_text(AuParser *self)
1332 text = auparse_get_record_text(self->au);
1335 PyErr_SetFromErrno(PyExc_EnvironmentError);
1338 return Py_BuildValue("s", text);
1341 /********************************
1342 * auparse_find_field
1343 ********************************/
1344 PyDoc_STRVAR(find_field_doc,
1345 "find_field(name) Search for field name.\n\
1347 find_field() will scan all records in an event to find the first\n\
1348 occurance of the field name passed to it. Searching begins from the\n\
1349 cursor’s current position. The field name is stored for subsequent\n\
1352 Returns value associated with field or None if not found.\n\
1355 AuParser_find_field(AuParser *self, PyObject *args)
1360 if (!PyArg_ParseTuple(args, "s:find_field", &name)) return NULL;
1362 if ((value =auparse_find_field(self->au, name)) == NULL) {
1364 PyErr_SetFromErrno(PyExc_EnvironmentError);
1370 return Py_BuildValue("s", value);
1373 const char *auparse_find_field_next(auparse_state_t *au);
1374 /********************************
1375 * auparse_find_field_next
1376 ********************************/
1377 PyDoc_STRVAR(find_field_next_doc,
1378 "find_field_next() Get next occurrance of field name\n\
1380 find_field_next() returns the value associated next occurrance of field name.\n\
1381 Returns value associated with field or None if there is no next field.\n\
1382 Raises exception (EnvironmentError) on error.\n\
1385 AuParser_find_field_next(AuParser *self)
1390 if ((value = auparse_find_field_next(self->au)) == NULL) {
1392 PyErr_SetFromErrno(PyExc_EnvironmentError);
1398 return Py_BuildValue("s", value);
1401 /********************************
1402 * auparse_get_field_name
1403 ********************************/
1404 PyDoc_STRVAR(get_field_name_doc,
1405 "get_field_name() Get current field’s name.\n\
1407 get_field_name() allows access to the current field name of the\n\
1408 current record in the current event.\n\
1410 Returns None if the field value is unavailable.\n\
1413 AuParser_get_field_name(AuParser *self)
1415 const char *name = NULL;
1418 name = auparse_get_field_name(self->au);
1419 return Py_BuildValue("s", name);
1422 /********************************
1423 * auparse_get_field_str
1424 ********************************/
1425 PyDoc_STRVAR(get_field_str_doc,
1426 "get_field_str() get current field’s value\n\
1428 get_field_str() allows access to the value in the current field of the\n\
1429 current record in the current event.\n\
1431 Returns None if the field value is unavailable.\n\
1434 AuParser_get_field_str(AuParser *self)
1436 const char *value = NULL;
1439 value = auparse_get_field_str(self->au);
1440 return Py_BuildValue("s", value);
1443 /********************************
1444 * auparse_get_field_type
1445 ********************************/
1446 PyDoc_STRVAR(get_field_type_doc,
1447 "get_field_type() Get current field’s data type value.\n\
1449 get_field_type() returns a value from the auparse_type_t enum that\n\
1450 describes the kind of data in the current field of the current record\n\
1451 in the current event.\n\
1453 Returns AUPARSE_TYPE_UNCLASSIFIED if the field’s data type has no\n\
1454 known description or is an integer. Otherwise it returns another enum.\n\
1455 Fields with the type AUPARSE_TYPE_ESCAPED must be interpretted to access\n\
1456 their value since those field’s raw value is encoded.\n\
1459 AuParser_get_field_type(AuParser *self)
1464 value = auparse_get_field_type(self->au);
1465 return Py_BuildValue("i", value);
1468 /********************************
1469 * auparse_get_field_int
1470 ********************************/
1471 PyDoc_STRVAR(get_field_int_doc,
1472 "get_field_int() Get current field’s value as an integer.\n\
1474 get_field_int() allows access to the value as an int of the current\n\
1475 field of the current record in the current event.\n\
1477 Returns None if the field value is unavailable.\n\
1480 AuParser_get_field_int(AuParser *self)
1485 value = auparse_get_field_int(self->au);
1486 if (errno == 0) return Py_BuildValue("i", value);
1490 // FIXME: can't tell if interpret is succesful, always returns some string in somewhat arbitrary format.
1491 PyDoc_STRVAR(interpret_field_doc,
1492 "interpret_field() Return an interpretation of the current field as a string.\n\
1494 If the field cannot be interpreted the field is returned unmodified.\n\
1495 Returns None if the field value is unavailable.\n\
1498 AuParser_interpret_field(AuParser *self)
1500 const char *value = NULL;
1503 value = auparse_interpret_field(self->au);
1504 return Py_BuildValue("s", value);
1508 PyGetSetDef AuParser_getseters[] = {
1509 {NULL} /* Sentinel */
1513 PyMemberDef AuParser_members[] = {
1514 {NULL} /* Sentinel */
1517 static PyMethodDef AuParser_methods[] = {
1518 {"feed", (PyCFunction)AuParser_feed, METH_VARARGS, feed_doc},
1519 {"flush_feed", (PyCFunction)AuParser_flush_feed, METH_NOARGS, flush_feed_doc},
1520 {"add_callback", (PyCFunction)AuParser_add_callback, METH_VARARGS, add_callback_doc},
1521 {"reset", (PyCFunction)AuParser_reset, METH_NOARGS, reset_doc},
1522 {"search_add_expression", (PyCFunction)AuParser_search_add_expression, METH_VARARGS, search_add_expression_doc},
1523 {"search_add_item", (PyCFunction)AuParser_search_add_item, METH_VARARGS, search_add_item_doc},
1524 {"search_add_interpreted_item", (PyCFunction)AuParser_search_add_interpreted_item, METH_VARARGS, search_add_interpreted_item_doc},
1525 {"search_add_timestamp_item", (PyCFunction)AuParser_search_add_timestamp_item, METH_VARARGS, search_add_timestamp_item_doc},
1526 {"search_add_timestamp_item_ex", (PyCFunction)AuParser_search_add_timestamp_item_ex, METH_VARARGS, search_add_timestamp_item_ex_doc},
1527 {"search_add_regex", (PyCFunction)AuParser_search_add_regex, METH_VARARGS, search_add_regex_doc},
1528 {"search_set_stop", (PyCFunction)AuParser_search_set_stop, METH_VARARGS, search_set_stop_doc},
1529 {"search_clear", (PyCFunction)AuParser_search_clear, METH_NOARGS, search_clear_doc},
1530 {"search_next_event", (PyCFunction)AuParser_search_next_event, METH_NOARGS, search_next_event_doc},
1531 {"parse_next_event", (PyCFunction)AuParser_parse_next_event, METH_NOARGS, parse_next_event_doc},
1532 {"get_timestamp", (PyCFunction)AuParser_get_timestamp, METH_NOARGS, get_timestamp_doc},
1533 {"get_num_records", (PyCFunction)AuParser_get_num_records, METH_NOARGS, get_num_records_doc},
1534 {"first_record", (PyCFunction)AuParser_first_record, METH_NOARGS, first_record_doc},
1535 {"next_record", (PyCFunction)AuParser_next_record, METH_NOARGS, next_record_doc},
1536 {"goto_record_num", (PyCFunction)AuParser_goto_record_num, METH_VARARGS, goto_record_num_doc},
1537 {"get_type", (PyCFunction)AuParser_get_type, METH_NOARGS, get_type_doc},
1538 {"get_type_name", (PyCFunction)AuParser_get_type_name, METH_NOARGS, get_type_name_doc},
1539 {"get_line_number", (PyCFunction)AuParser_get_line_number, METH_NOARGS, get_line_number_doc},
1540 {"get_filename", (PyCFunction)AuParser_get_filename, METH_NOARGS, get_filename_doc},
1541 {"first_field", (PyCFunction)AuParser_first_field, METH_NOARGS, first_field_doc},
1542 {"next_field", (PyCFunction)AuParser_next_field, METH_NOARGS, next_field_doc},
1543 {"get_num_fields", (PyCFunction)AuParser_get_num_fields, METH_NOARGS, get_num_fields_doc},
1544 {"get_record_text", (PyCFunction)AuParser_get_record_text, METH_NOARGS, get_record_text_doc},
1545 {"find_field_next", (PyCFunction)AuParser_find_field_next, METH_NOARGS, find_field_next_doc},
1546 {"find_field", (PyCFunction)AuParser_find_field, METH_VARARGS, find_field_doc},
1547 {"get_field_name", (PyCFunction)AuParser_get_field_name, METH_NOARGS, get_field_name_doc},
1548 {"get_field_str", (PyCFunction)AuParser_get_field_str, METH_NOARGS, get_field_str_doc},
1549 {"get_field_type", (PyCFunction)AuParser_get_field_type, METH_NOARGS, get_field_type_doc},
1550 {"get_field_int", (PyCFunction)AuParser_get_field_int, METH_NOARGS, get_field_int_doc},
1551 {"interpret_field", (PyCFunction)AuParser_interpret_field, METH_NOARGS, interpret_field_doc},
1552 {NULL, NULL} /* Sentinel */
1555 PyDoc_STRVAR(AuParser_doc,
1556 "AuParser(source_type, source)\n\
1558 Construct a new audit parser object and bind it to input data.\n\
1559 source_type: one of the AUSOURCE_* constants.\n\
1560 source: the input data, dependent on the source_type as follows:\n\
1562 AUSOURCE_LOGS: None (system log files will be parsed)\n\
1563 AUSOURCE_FILE: string containing file path name\n\
1564 AUSOURCE_FILE_ARRAY: list or tuple of strings each containing a file path name\n\
1565 AUSOURCE_BUFFER: string containing audit data to parse\n\
1566 AUSOURCE_BUFFER_ARRAY: list or tuple of strings each containing audit data to parse\n\
1567 AUSOURCE_DESCRIPTOR: integer file descriptor (e.g. fileno)\n\
1568 AUSOURCE_FILE_POINTER: file object (e.g. types.FileType)\n\
1569 AUSOURCE_FEED: None (data supplied via feed()\n\
1572 static PyTypeObject AuParserType = {
1573 PyVarObject_HEAD_INIT(NULL, 0)
1574 "auparse.AuParser", /*tp_name*/
1575 sizeof(AuParser), /*tp_basicsize*/
1577 (destructor)AuParser_dealloc, /*tp_dealloc*/
1584 0, /*tp_as_sequence*/
1585 0, /*tp_as_mapping*/
1592 Py_TPFLAGS_DEFAULT, /*tp_flags*/
1593 AuParser_doc, /* tp_doc */
1594 0, /* tp_traverse */
1596 0, /* tp_richcompare */
1597 0, /* tp_weaklistoffset */
1599 0, /* tp_iternext */
1600 AuParser_methods, /* tp_methods */
1601 AuParser_members, /* tp_members */
1602 AuParser_getseters, /* tp_getset */
1605 0, /* tp_descr_get */
1606 0, /* tp_descr_set */
1607 0, /* tp_dictoffset */
1608 (initproc)AuParser_init, /* tp_init */
1610 AuParser_new, /* tp_new */
1615 /*===========================================================================
1617 *===========================================================================*/
1619 PyDoc_STRVAR(auparse_doc,
1620 "Parsing library for audit messages.\n\
1622 The module defines the following exceptions:\n\
1624 NoParser: Raised if the underlying C code parser is not bound to the AuParser object.\n\
1627 static PyMethodDef module_methods[] = {
1628 {NULL} /* Sentinel */
1632 static struct PyModuleDef auparse_def = {
1633 PyModuleDef_HEAD_INIT,
1645 PyInit_auparse(void)
1653 if (PyType_Ready(&AuEventType) < 0) MODINITERROR;
1654 if (PyType_Ready(&AuParserType) < 0) MODINITERROR;
1657 m = PyModule_Create(&auparse_def);
1659 m = Py_InitModule3("auparse", module_methods, auparse_doc);
1665 Py_INCREF(&AuParserType);
1666 PyModule_AddObject(m, "AuParser", (PyObject *)&AuParserType);
1668 Py_INCREF(&AuEventType);
1669 PyModule_AddObject(m, "AuEvent", (PyObject *)&AuEventType);
1672 NoParserError = PyErr_NewException("auparse.NoParser", NULL, NULL);
1673 Py_INCREF(NoParserError);
1674 PyModule_AddObject(m, "NoParser", NoParserError);
1677 PyModule_AddIntConstant(m, "AUSOURCE_LOGS", AUSOURCE_LOGS);
1678 PyModule_AddIntConstant(m, "AUSOURCE_FILE", AUSOURCE_FILE);
1679 PyModule_AddIntConstant(m, "AUSOURCE_FILE_ARRAY", AUSOURCE_FILE_ARRAY);
1680 PyModule_AddIntConstant(m, "AUSOURCE_BUFFER", AUSOURCE_BUFFER);
1681 PyModule_AddIntConstant(m, "AUSOURCE_BUFFER_ARRAY", AUSOURCE_BUFFER_ARRAY);
1682 PyModule_AddIntConstant(m, "AUSOURCE_DESCRIPTOR", AUSOURCE_DESCRIPTOR);
1683 PyModule_AddIntConstant(m, "AUSOURCE_FILE_POINTER", AUSOURCE_FILE_POINTER);
1684 PyModule_AddIntConstant(m, "AUSOURCE_FEED", AUSOURCE_FEED);
1687 PyModule_AddIntConstant(m, "AUSEARCH_UNSET", AUSEARCH_UNSET);
1688 PyModule_AddIntConstant(m, "AUSEARCH_EXISTS", AUSEARCH_EXISTS);
1689 PyModule_AddIntConstant(m, "AUSEARCH_EQUAL", AUSEARCH_EQUAL);
1690 PyModule_AddIntConstant(m, "AUSEARCH_NOT_EQUAL", AUSEARCH_NOT_EQUAL);
1693 PyModule_AddIntConstant(m, "AUSEARCH_STOP_EVENT", AUSEARCH_STOP_EVENT);
1694 PyModule_AddIntConstant(m, "AUSEARCH_STOP_RECORD", AUSEARCH_STOP_RECORD);
1695 PyModule_AddIntConstant(m, "AUSEARCH_STOP_FIELD", AUSEARCH_STOP_FIELD);
1697 /* ausearch_rule_t */
1698 PyModule_AddIntConstant(m, "AUSEARCH_RULE_CLEAR", AUSEARCH_RULE_CLEAR);
1699 PyModule_AddIntConstant(m, "AUSEARCH_RULE_OR", AUSEARCH_RULE_OR);
1700 PyModule_AddIntConstant(m, "AUSEARCH_RULE_AND", AUSEARCH_RULE_AND);
1701 PyModule_AddIntConstant(m, "AUSEARCH_RULE_REGEX", AUSEARCH_RULE_REGEX);
1703 /* auparse_cb_event_t */
1704 PyModule_AddIntConstant(m, "AUPARSE_CB_EVENT_READY", AUPARSE_CB_EVENT_READY);
1705 /* auparse_type_t */
1706 PyModule_AddIntConstant(m, "AUPARSE_TYPE_UNCLASSIFIED", AUPARSE_TYPE_UNCLASSIFIED);
1707 PyModule_AddIntConstant(m, "AUPARSE_TYPE_UID", AUPARSE_TYPE_UID);
1708 PyModule_AddIntConstant(m, "AUPARSE_TYPE_GID", AUPARSE_TYPE_GID);
1709 PyModule_AddIntConstant(m, "AUPARSE_TYPE_SYSCALL", AUPARSE_TYPE_SYSCALL);
1710 PyModule_AddIntConstant(m, "AUPARSE_TYPE_ARCH", AUPARSE_TYPE_ARCH);
1711 PyModule_AddIntConstant(m, "AUPARSE_TYPE_EXIT", AUPARSE_TYPE_EXIT);
1712 PyModule_AddIntConstant(m, "AUPARSE_TYPE_ESCAPED", AUPARSE_TYPE_ESCAPED);
1713 PyModule_AddIntConstant(m, "AUPARSE_TYPE_PERM", AUPARSE_TYPE_PERM);
1714 PyModule_AddIntConstant(m, "AUPARSE_TYPE_MODE", AUPARSE_TYPE_MODE);
1715 PyModule_AddIntConstant(m, "AUPARSE_TYPE_SOCKADDR", AUPARSE_TYPE_SOCKADDR);
1716 PyModule_AddIntConstant(m, "AUPARSE_TYPE_FLAGS", AUPARSE_TYPE_FLAGS);
1717 PyModule_AddIntConstant(m, "AUPARSE_TYPE_PROMISC", AUPARSE_TYPE_PROMISC);
1718 PyModule_AddIntConstant(m, "AUPARSE_TYPE_CAPABILITY", AUPARSE_TYPE_CAPABILITY);
1719 PyModule_AddIntConstant(m, "AUPARSE_TYPE_SUCCESS", AUPARSE_TYPE_SUCCESS);
1720 PyModule_AddIntConstant(m, "AUPARSE_TYPE_A0", AUPARSE_TYPE_A0);
1721 PyModule_AddIntConstant(m, "AUPARSE_TYPE_A1", AUPARSE_TYPE_A1);
1722 PyModule_AddIntConstant(m, "AUPARSE_TYPE_A2", AUPARSE_TYPE_A2);
1723 PyModule_AddIntConstant(m, "AUPARSE_TYPE_SIGNAL", AUPARSE_TYPE_SIGNAL);
1724 PyModule_AddIntConstant(m, "AUPARSE_TYPE_LIST", AUPARSE_TYPE_LIST);