-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathnflog.c
208 lines (176 loc) · 5.72 KB
/
nflog.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
#include <Python.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <netinet/in.h>
#include <net/if.h>
#include <libnetfilter_log/libnetfilter_log.h>
static bool nflog_running = false;
static int nflog_group_id = 0;
static int nflog_nf_fd = -1;
struct nflog_handle *nflog_h;
struct nflog_g_handle *nflog_qh;
static PyObject *nflog_py_cb = NULL;
static PyObject *nflog_nflog_setgroup(PyObject *self, PyObject *args)
{
if (!PyArg_ParseTuple(args, "i", &nflog_group_id))
{
PyErr_SetString(PyExc_TypeError, "Wrong type, needs integer input.");
return NULL;
}
if (nflog_running)
{
PyErr_SetString(PyExc_RuntimeError, "Can not change group when started.");
return NULL;
}
PyObject *ret = Py_BuildValue("z", NULL);
return ret;
}
static PyObject *nflog_nflog_getfd(PyObject *self, PyObject *args)
{
if (nflog_nf_fd < 0) {
PyObject *ret = Py_BuildValue("z", NULL);
return ret;
}
PyObject *ret = Py_BuildValue("i", nflog_nf_fd);
return ret;
}
static PyObject *nflog_nflog_getgroup(PyObject *self, PyObject *args)
{
PyObject *ret = Py_BuildValue("i", nflog_group_id);
return ret;
}
static PyObject *nflog_nflog_setcb(PyObject *dummy, PyObject *args)
{
PyObject *result = NULL;
PyObject *temp;
if (PyArg_ParseTuple(args, "O:set_callback", &temp)) {
if (!PyCallable_Check(temp)) {
PyErr_SetString(PyExc_TypeError, "parameter must be callable");
return NULL;
}
Py_XINCREF(temp);
Py_XDECREF(nflog_py_cb);
nflog_py_cb = temp;
Py_INCREF(Py_None);
result = Py_None;
}
return result;
}
static int cb(struct nflog_g_handle *gh, struct nfgenmsg *nfmsg,
struct nflog_data *nfa, void *data)
{
struct nfulnl_msg_packet_hdr *ph = nflog_get_msg_packet_hdr(nfa);
u_int32_t indev = nflog_get_indev(nfa);
u_int32_t outdev = nflog_get_outdev(nfa);
char *payload;
int payload_len;
char ifname[20] = {0};
u_int16_t proto = 0;
payload_len = nflog_get_payload(nfa, &payload);
char *hwll_hdr = nflog_get_msg_packet_hwhdr(nfa);
int hwll_hdr_len = nflog_get_msg_packet_hwhdrlen(nfa);
if (ph) {
proto = ntohs(ph->hw_protocol);
}
if (indev > 0)
if_indextoname(indev, ifname);
if (outdev > 0)
if_indextoname(outdev, ifname);
PyObject *arglist = Py_BuildValue("(iisiiy#iy#)",
indev, // i
outdev, // i
ifname, // s
proto, // i
payload_len, // i
payload, // y#
payload_len, // ^^
hwll_hdr_len, // i
hwll_hdr, // y#
hwll_hdr_len // ^^
);
PyObject_CallObject(nflog_py_cb, arglist);
Py_DECREF(arglist);
return 0;
}
static PyObject *nflog_nflog_start(PyObject *self, PyObject *args)
{
nflog_h = nflog_open();
if (!nflog_h) {
PyErr_SetString(PyExc_PermissionError, "Unable to open nflog.");
return NULL;
}
if (nflog_unbind_pf(nflog_h, AF_INET) < 0) {
PyErr_SetString(PyExc_PermissionError, "Unable to unbind pf.");
return NULL;
}
if (nflog_bind_pf(nflog_h, AF_INET) < 0) {
PyErr_SetString(PyExc_PermissionError, "Unable to bind pf.");
return NULL;
}
nflog_qh = nflog_bind_group(nflog_h, nflog_group_id);
if (!nflog_qh) {
PyErr_SetString(PyExc_LookupError, "No handle for nf group.");
return NULL;
}
if (nflog_set_mode(nflog_qh, NFULNL_COPY_PACKET, 0xffff) < 0) {
PyErr_SetString(PyExc_PermissionError, "Can't set packet copy mode.");
return NULL;
}
nflog_nf_fd = nflog_fd(nflog_h);
nflog_callback_register(nflog_qh, &cb, NULL);
nflog_running = true;
PyObject *ret = Py_BuildValue("z", NULL);
return ret;
}
static PyObject *nflog_nflog_handle(PyObject *self, PyObject *args)
{
char buf[4096];
int rv = recv(nflog_nf_fd, buf, sizeof(buf), 0);
if (rv >= 0) {
nflog_handle_packet(nflog_h, buf, rv);
}
PyObject *ret = Py_BuildValue("i", rv);
return ret;
}
static PyObject *nflog_nflog_stop(PyObject *self, PyObject *args)
{
nflog_unbind_group(nflog_qh);
nflog_close(nflog_h);
nflog_running = false;
PyObject *ret = Py_BuildValue("z", NULL);
return ret;
}
static PyMethodDef nflogMethods[] = {
{"getfd", nflog_nflog_getfd, METH_NOARGS,
"Get the fd for nflog. This should only be used with poll or select, "
"to check if there is new data. This function will return the fd as "
"an int, or None if run before nflog.start()"},
{"setgroup", nflog_nflog_setgroup, METH_VARARGS,
"Set the nflog group num."},
{"getgroup", nflog_nflog_getgroup, METH_NOARGS,
"Returns the nflog group num."},
{"setcb", nflog_nflog_setcb, METH_VARARGS,
"Set callback method that sould actually handle the incomeing packet."
"\nThe method must have 7 parameters:\n def callback(indev, ifname, "
"proto, payload_len, payload, hwll_hdr_len, hwll_hdr):\n pass"},
{"start", nflog_nflog_start, METH_NOARGS,
"Start the nflog listener."},
{"handle", nflog_nflog_handle, METH_NOARGS,
"Read from internal buffer, and handle with CB."},
{"stop", nflog_nflog_stop, METH_NOARGS,
"Stop the nflog reading."},
{NULL, NULL, 0, NULL}
};
static struct PyModuleDef nflogmodule = {
PyModuleDef_HEAD_INIT,
"nflog",
"Interface for accessing nflog.",
-1, //TODO: May need to change the state size later...
nflogMethods
};
PyMODINIT_FUNC PyInit_nflog(void)
{
return PyModule_Create(&nflogmodule);
}