Merge branch 'lilydjwg-master'
This commit is contained in:
commit
61cfb3d342
868
netfilterqueue.c
868
netfilterqueue.c
File diff suppressed because it is too large
Load Diff
|
@ -47,6 +47,7 @@ cdef enum:
|
|||
IPPROTO_MAX
|
||||
|
||||
cdef extern from "Python.h":
|
||||
object PyBytes_FromStringAndSize(char *s, Py_ssize_t len)
|
||||
object PyString_FromStringAndSize(char *s, Py_ssize_t len)
|
||||
|
||||
cdef extern from "sys/time.h":
|
||||
|
@ -78,7 +79,7 @@ cdef extern from "libnetfilter_queue/linux_nfnetlink_queue.h":
|
|||
u_int32_t packet_id
|
||||
u_int16_t hw_protocol
|
||||
u_int8_t hook
|
||||
|
||||
|
||||
cdef extern from "libnetfilter_queue/libnetfilter_queue.h":
|
||||
struct nfq_handle:
|
||||
pass
|
||||
|
@ -88,10 +89,10 @@ cdef extern from "libnetfilter_queue/libnetfilter_queue.h":
|
|||
pass
|
||||
struct nfqnl_msg_packet_hw:
|
||||
u_int8_t hw_addr[8]
|
||||
|
||||
|
||||
nfq_handle *nfq_open()
|
||||
int nfq_close(nfq_handle *h)
|
||||
|
||||
|
||||
int nfq_bind_pf(nfq_handle *h, u_int16_t pf)
|
||||
int nfq_unbind_pf(nfq_handle *h, u_int16_t pf)
|
||||
ctypedef int *nfq_callback(nfq_q_handle *gh, nfgenmsg *nfmsg,
|
||||
|
@ -101,21 +102,21 @@ cdef extern from "libnetfilter_queue/libnetfilter_queue.h":
|
|||
nfq_callback *cb,
|
||||
void *data)
|
||||
int nfq_destroy_queue(nfq_q_handle *qh)
|
||||
|
||||
|
||||
int nfq_handle_packet(nfq_handle *h, char *buf, int len)
|
||||
|
||||
|
||||
int nfq_set_mode(nfq_q_handle *qh,
|
||||
u_int8_t mode, unsigned int len)
|
||||
|
||||
|
||||
q_set_queue_maxlen(nfq_q_handle *qh,
|
||||
u_int32_t queuelen)
|
||||
|
||||
|
||||
int nfq_set_verdict(nfq_q_handle *qh,
|
||||
u_int32_t id,
|
||||
u_int32_t verdict,
|
||||
u_int32_t data_len,
|
||||
unsigned char *buf) nogil
|
||||
|
||||
|
||||
int nfq_set_verdict_mark(nfq_q_handle *qh,
|
||||
u_int32_t id,
|
||||
u_int32_t verdict,
|
||||
|
@ -130,7 +131,7 @@ cdef extern from "libnetfilter_queue/libnetfilter_queue.h":
|
|||
int nfq_get_timestamp(nfq_data *nfad, timeval *tv)
|
||||
nfqnl_msg_packet_hw *nfq_get_packet_hw(nfq_data *nfad)
|
||||
int nfq_get_nfmark (nfq_data *nfad)
|
||||
|
||||
|
||||
# Dummy defines from linux/socket.h:
|
||||
cdef enum: # Protocol families, same as address families.
|
||||
PF_INET = 2
|
||||
|
@ -138,7 +139,7 @@ cdef enum: # Protocol families, same as address families.
|
|||
|
||||
cdef extern from "sys/socket.h":
|
||||
ssize_t recv(int __fd, void *__buf, size_t __n, int __flags) nogil
|
||||
|
||||
|
||||
# Dummy defines from linux/netfilter.h
|
||||
cdef enum:
|
||||
NF_DROP
|
||||
|
@ -153,18 +154,18 @@ cdef class Packet:
|
|||
cdef nfq_q_handle *_qh
|
||||
cdef nfq_data *_nfa
|
||||
cdef nfqnl_msg_packet_hdr *_hdr
|
||||
cdef bint _verdict_is_set # True if verdict has been issued,
|
||||
cdef bint _verdict_is_set # True if verdict has been issued,
|
||||
# false otherwise
|
||||
cdef bint _mark_is_set # True if a mark has been given, false otherwise
|
||||
cdef u_int32_t _given_mark # Mark given to packet
|
||||
cdef bytes _given_payload # New payload of packet, or null
|
||||
|
||||
|
||||
# From NFQ packet header:
|
||||
cdef readonly u_int32_t id
|
||||
cdef readonly u_int16_t hw_protocol
|
||||
cdef readonly u_int8_t hook
|
||||
cdef readonly u_int32_t mark
|
||||
|
||||
|
||||
# Packet details:
|
||||
cdef Py_ssize_t payload_len
|
||||
cdef readonly char *payload
|
||||
|
@ -176,7 +177,7 @@ cdef class Packet:
|
|||
#cdef readonly u_int32_t physindev
|
||||
#cdef readonly u_int32_t outdev
|
||||
#cdef readonly u_int32_t physoutdev
|
||||
|
||||
|
||||
cdef set_nfq_data(self, nfq_q_handle *qh, nfq_data *nfa)
|
||||
cdef void verdict(self, u_int8_t verdict)
|
||||
cpdef Py_ssize_t get_payload_len(self)
|
||||
|
@ -187,11 +188,11 @@ cdef class Packet:
|
|||
cpdef accept(self)
|
||||
cpdef drop(self)
|
||||
cpdef repeat(self)
|
||||
|
||||
|
||||
cdef class NetfilterQueue:
|
||||
cdef object user_callback # User callback
|
||||
cdef nfq_handle *h # Handle to NFQueue library
|
||||
cdef nfq_q_handle *qh # A handle to the queue
|
||||
cdef u_int16_t af # Address family
|
||||
cdef packet_copy_size # Amount of packet metadata + data copied to buffer
|
||||
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
"""
|
||||
Bind to a Linux netfilter queue. Send packets to a user-specified callback
|
||||
Bind to a Linux netfilter queue. Send packets to a user-specified callback
|
||||
function.
|
||||
|
||||
Copyright: (c) 2011, Kerkhoff Technologies Inc.
|
||||
|
@ -20,7 +20,9 @@ DEF BufferSize = 4096
|
|||
DEF MetadataSize = 80
|
||||
DEF MaxCopySize = BufferSize - MetadataSize
|
||||
|
||||
cdef int global_callback(nfq_q_handle *qh, nfgenmsg *nfmsg,
|
||||
cimport cpython.version
|
||||
|
||||
cdef int global_callback(nfq_q_handle *qh, nfgenmsg *nfmsg,
|
||||
nfq_data *nfa, void *data) with gil:
|
||||
"""Create a Packet and pass it to appropriate callback."""
|
||||
cdef NetfilterQueue nfqueue = <NetfilterQueue>data
|
||||
|
@ -37,29 +39,29 @@ cdef class Packet:
|
|||
self._verdict_is_set = False
|
||||
self._mark_is_set = False
|
||||
self._given_payload = None
|
||||
|
||||
|
||||
def __str__(self):
|
||||
cdef iphdr *hdr = <iphdr*>self.payload
|
||||
protocol = PROTOCOLS.get(hdr.protocol, "Unknown protocol")
|
||||
return "%s packet, %s bytes" % (protocol, self.payload_len)
|
||||
|
||||
|
||||
cdef set_nfq_data(self, nfq_q_handle *qh, nfq_data *nfa):
|
||||
"""
|
||||
Assign a packet from NFQ to this object. Parse the header and load
|
||||
Assign a packet from NFQ to this object. Parse the header and load
|
||||
local values.
|
||||
"""
|
||||
self._qh = qh
|
||||
self._nfa = nfa
|
||||
self._hdr = nfq_get_msg_packet_hdr(nfa)
|
||||
|
||||
|
||||
self.id = ntohl(self._hdr.packet_id)
|
||||
self.hw_protocol = ntohs(self._hdr.hw_protocol)
|
||||
self.hook = self._hdr.hook
|
||||
|
||||
|
||||
self.payload_len = nfq_get_payload(self._nfa, &self.payload)
|
||||
if self.payload_len < 0:
|
||||
raise OSError("Failed to get payload of packet.")
|
||||
|
||||
|
||||
nfq_get_timestamp(self._nfa, &self.timestamp)
|
||||
self.mark = nfq_get_nfmark(nfa)
|
||||
|
||||
|
@ -69,7 +71,7 @@ cdef class Packet:
|
|||
raise RuntimeWarning("Verdict already given for this packet.")
|
||||
|
||||
cdef u_int32_t modified_payload_len = 0
|
||||
cdef unsigned char *modified_payload = NULL
|
||||
cdef unsigned char *modified_payload = NULL
|
||||
if self._given_payload:
|
||||
modified_payload_len = len(self._given_payload)
|
||||
modified_payload = self._given_payload
|
||||
|
@ -90,23 +92,28 @@ cdef class Packet:
|
|||
modified_payload)
|
||||
|
||||
self._verdict_is_set = True
|
||||
|
||||
|
||||
def get_payload(self):
|
||||
"""Return payload as Python string."""
|
||||
cdef object py_string = PyString_FromStringAndSize(self.payload,
|
||||
self.payload_len)
|
||||
cdef object py_string
|
||||
if cpython.version.PY_MAJOR_VERSION >= 3:
|
||||
py_string = PyBytes_FromStringAndSize(
|
||||
self.payload, self.payload_len)
|
||||
else:
|
||||
py_string = PyString_FromStringAndSize(
|
||||
self.payload, self.payload_len)
|
||||
return py_string
|
||||
|
||||
|
||||
cpdef Py_ssize_t get_payload_len(self):
|
||||
return self.payload_len
|
||||
|
||||
|
||||
cpdef double get_timestamp(self):
|
||||
return self.timestamp.tv_sec + (self.timestamp.tv_usec/1000000.0)
|
||||
|
||||
|
||||
cpdef set_payload(self, bytes payload):
|
||||
"""Set the new payload of this packet."""
|
||||
self._given_payload = payload
|
||||
|
||||
|
||||
cpdef set_mark(self, u_int32_t mark):
|
||||
self._given_mark = mark
|
||||
self._mark_is_set = True
|
||||
|
@ -115,11 +122,11 @@ cdef class Packet:
|
|||
if self._mark_is_set:
|
||||
return self._given_mark
|
||||
return self.mark
|
||||
|
||||
|
||||
cpdef accept(self):
|
||||
"""Accept the packet."""
|
||||
self.verdict(NF_ACCEPT)
|
||||
|
||||
|
||||
cpdef drop(self):
|
||||
"""Drop the packet."""
|
||||
self.verdict(NF_DROP)
|
||||
|
@ -136,20 +143,20 @@ cdef class NetfilterQueue:
|
|||
self.h = nfq_open()
|
||||
if self.h == NULL:
|
||||
raise OSError("Failed to open NFQueue.")
|
||||
nfq_unbind_pf(self.h, self.af) # This does NOT kick out previous
|
||||
nfq_unbind_pf(self.h, self.af) # This does NOT kick out previous
|
||||
# running queues
|
||||
if nfq_bind_pf(self.h, self.af) < 0:
|
||||
raise OSError("Failed to bind family %s. Are you root?" % self.af)
|
||||
|
||||
|
||||
def __dealloc__(self):
|
||||
if self.qh != NULL:
|
||||
nfq_destroy_queue(self.qh)
|
||||
# Don't call nfq_unbind_pf unless you want to disconnect any other
|
||||
# Don't call nfq_unbind_pf unless you want to disconnect any other
|
||||
# processes using this libnetfilter_queue on this protocol family!
|
||||
nfq_close(self.h)
|
||||
|
||||
def bind(self, int queue_num, object user_callback,
|
||||
u_int32_t max_len=DEFAULT_MAX_QUEUELEN,
|
||||
u_int32_t max_len=DEFAULT_MAX_QUEUELEN,
|
||||
u_int8_t mode=NFQNL_COPY_PACKET,
|
||||
u_int32_t range=MaxPacketSize):
|
||||
"""Create and bind to a new queue."""
|
||||
|
@ -158,21 +165,21 @@ cdef class NetfilterQueue:
|
|||
<nfq_callback*>global_callback, <void*>self)
|
||||
if self.qh == NULL:
|
||||
raise OSError("Failed to create queue %s." % queue_num)
|
||||
|
||||
|
||||
if range > MaxCopySize:
|
||||
range = MaxCopySize
|
||||
if nfq_set_mode(self.qh, mode, range) < 0:
|
||||
raise OSError("Failed to set packet copy mode.")
|
||||
|
||||
|
||||
nfq_set_queue_maxlen(self.qh, max_len)
|
||||
|
||||
|
||||
def unbind(self):
|
||||
"""Destroy the queue."""
|
||||
if self.qh != NULL:
|
||||
nfq_destroy_queue(self.qh)
|
||||
self.qh = NULL
|
||||
# See warning about nfq_unbind_pf in __dealloc__ above.
|
||||
|
||||
|
||||
def run(self):
|
||||
"""Begin accepting packets."""
|
||||
cdef int fd = nfq_fd(self.h)
|
||||
|
|
Loading…
Reference in New Issue