Add run_socket, which uses socket.recv so that gevent can monkeypatch it. Fixes #5
This commit is contained in:
parent
2960dc3401
commit
ccb353011a
28
README.rst
28
README.rst
|
@ -29,6 +29,26 @@ it. ::
|
|||
|
||||
nfqueue.unbind()
|
||||
|
||||
You can also make your own socket so that it can be used with gevent, for example. ::
|
||||
|
||||
from netfilterqueue import NetfilterQueue
|
||||
import socket
|
||||
|
||||
def print_and_accept(pkt):
|
||||
print(pkt)
|
||||
pkt.accept()
|
||||
|
||||
nfqueue = NetfilterQueue()
|
||||
nfqueue.bind(1, print_and_accept)
|
||||
s = socket.fromfd(nfqueue.get_fd(), socket.AF_UNIX, socket.SOCK_STREAM)
|
||||
try:
|
||||
nfqueue.run_socket(s)
|
||||
except KeyboardInterrupt:
|
||||
print('')
|
||||
|
||||
s.close()
|
||||
nfqueue.unbind()
|
||||
|
||||
To send packets destined for your LAN to the script, type something like::
|
||||
|
||||
iptables -I INPUT -d 192.168.0.0/24 -j NFQUEUE --queue-num 1
|
||||
|
@ -107,6 +127,12 @@ a call to ``bind``, then start receiving packets with a call to ``run``.
|
|||
block=False to let your thread continue. You can get the file descriptor
|
||||
of the socket with the ``get_fd`` method.
|
||||
|
||||
``QueueHandler.run_socket(socket)``
|
||||
Send packets to your callback, but use the supplied socket instead of
|
||||
recv, so that, for example, gevent can monkeypatch it. You can make a
|
||||
socket with ``socket.fromfd(nfqueue.get_fd(), socket.AF_UNIX, socket.SOCK_STREAM)``
|
||||
and optionally make it non-blocking with ``socket.setblocking(False)``.
|
||||
|
||||
Packet objects
|
||||
--------------
|
||||
|
||||
|
@ -191,8 +217,6 @@ The fields are:
|
|||
Limitations
|
||||
===========
|
||||
|
||||
More details coming soon...
|
||||
|
||||
* Compiled with a 4096-byte buffer for packets, so it probably won't work on
|
||||
loopback or Ethernet with jumbo packets. If this is a problem, either lower
|
||||
MTU on your loopback, disable jumbo packets, or get Cython,
|
||||
|
|
1159
netfilterqueue.c
1159
netfilterqueue.c
File diff suppressed because it is too large
Load Diff
|
@ -8,6 +8,8 @@ cdef extern from "<errno.h>":
|
|||
|
||||
# dummy defines from asm-generic/errno.h:
|
||||
cdef enum:
|
||||
EAGAIN = 11 # Try again
|
||||
EWOULDBLOCK = EAGAIN
|
||||
ENOBUFS = 105 # No buffer space available
|
||||
|
||||
cdef extern from "netinet/ip.h":
|
||||
|
|
|
@ -24,6 +24,7 @@ DEF SockCopySize = MaxCopySize + SockOverhead
|
|||
# Socket queue should hold max number of packets of copysize bytes
|
||||
DEF SockRcvSize = DEFAULT_MAX_QUEUELEN * SockCopySize / 2
|
||||
|
||||
import socket
|
||||
cimport cpython.version
|
||||
|
||||
cdef int global_callback(nfq_q_handle *qh, nfgenmsg *nfmsg,
|
||||
|
@ -31,7 +32,6 @@ cdef int global_callback(nfq_q_handle *qh, nfgenmsg *nfmsg,
|
|||
"""Create a Packet and pass it to appropriate callback."""
|
||||
cdef NetfilterQueue nfqueue = <NetfilterQueue>data
|
||||
cdef object user_callback = <object>nfqueue.user_callback
|
||||
|
||||
packet = Packet()
|
||||
packet.set_nfq_data(qh, nfa)
|
||||
user_callback(packet)
|
||||
|
@ -195,8 +195,8 @@ cdef class NetfilterQueue:
|
|||
return nfq_fd(self.h)
|
||||
|
||||
def run(self, block=True):
|
||||
"""Begin accepting packets."""
|
||||
cdef int fd = nfq_fd(self.h)
|
||||
"""Accept packets using recv."""
|
||||
cdef int fd = self.get_fd()
|
||||
cdef char buf[BufferSize]
|
||||
cdef int rv
|
||||
cdef int recv_flags
|
||||
|
@ -211,6 +211,26 @@ cdef class NetfilterQueue:
|
|||
if errno != ENOBUFS:
|
||||
break
|
||||
|
||||
def run_socket(self, s):
|
||||
"""Accept packets using socket.recv so that, for example, gevent can monkeypatch it."""
|
||||
try:
|
||||
while True:
|
||||
buf = s.recv(BufferSize)
|
||||
rv = len(buf)
|
||||
if rv >= 0:
|
||||
nfq_handle_packet(self.h, buf, rv)
|
||||
else:
|
||||
break
|
||||
except socket.error as e:
|
||||
err = e.args[0]
|
||||
if err == EAGAIN or err == EWOULDBLOCK:
|
||||
# This should only happen with a non-blocking socket, and the
|
||||
# app should call run_socket again when more data is available.
|
||||
pass
|
||||
else:
|
||||
# This is bad. Let the caller handle it.
|
||||
raise e
|
||||
|
||||
PROTOCOLS = {
|
||||
0: "HOPOPT",
|
||||
1: "ICMP",
|
||||
|
|
Loading…
Reference in New Issue