Add Packet accessors for interface indices
This commit is contained in:
parent
0bb948d2c1
commit
49e16812f7
|
@ -15,13 +15,14 @@ jobs:
|
|||
fail-fast: false
|
||||
matrix:
|
||||
python:
|
||||
- '3.6'
|
||||
- '3.7'
|
||||
- '3.8'
|
||||
- '3.9'
|
||||
- '3.10'
|
||||
- '3.11'
|
||||
- 'pypy-3.7'
|
||||
- 'pypy-3.8'
|
||||
- 'pypy-3.9'
|
||||
check_lint: ['0']
|
||||
extra_name: ['']
|
||||
include:
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
v1.1.0, unreleased
|
||||
Add Packet accessors for {indev, outdev, physindev, physoutdev} interface indices
|
||||
|
||||
v1.0.0, 14 Jan 2022
|
||||
Propagate exceptions raised by the user's packet callback
|
||||
Avoid calls to the packet callback during queue unbinding
|
||||
|
|
12
README.rst
12
README.rst
|
@ -217,6 +217,18 @@ Objects of this type are passed to your callback.
|
|||
into our queue. Values 0 through 4 correspond to PREROUTING, INPUT,
|
||||
FORWARD, OUTPUT, and POSTROUTING respectively.
|
||||
|
||||
``Packet.indev``, ``Packet.outdev``, ``Packet.physindev``, ``Packet.physoutdev``
|
||||
The interface indices on which the packet arrived (``indev``) or is slated
|
||||
to depart (``outdev``). These are integers, which can be converted to
|
||||
names like "eth0" by using ``socket.if_indextoname()``. Zero means
|
||||
no interface is applicable, either because the packet was locally generated
|
||||
or locally received, or because the interface information wasn't available
|
||||
when the packet was queued (for example, ``PREROUTING`` rules don't yet
|
||||
know the ``outdev``). If the ``indev`` or ``outdev`` refers to a bridge
|
||||
device, then the corresponding ``physindev`` or ``physoutdev`` will name
|
||||
the bridge member on which the actual traffic occurred; otherwise
|
||||
``physindev`` and ``physoutdev`` will be zero.
|
||||
|
||||
``Packet.retain()``
|
||||
Allocate a copy of the packet payload for use after the callback
|
||||
has returned. ``get_payload()`` will raise an exception at that
|
||||
|
|
|
@ -153,7 +153,11 @@ cdef extern from "libnetfilter_queue/libnetfilter_queue.h":
|
|||
int nfq_get_payload(nfq_data *nfad, unsigned char **data)
|
||||
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)
|
||||
int nfq_get_nfmark(nfq_data *nfad)
|
||||
u_int32_t nfq_get_indev(nfq_data *nfad)
|
||||
u_int32_t nfq_get_outdev(nfq_data *nfad)
|
||||
u_int32_t nfq_get_physindev(nfq_data *nfad)
|
||||
u_int32_t nfq_get_physoutdev(nfq_data *nfad)
|
||||
nfnl_handle *nfq_nfnlh(nfq_handle *h)
|
||||
|
||||
# Dummy defines from linux/socket.h:
|
||||
|
@ -184,8 +188,7 @@ cdef class NetfilterQueue:
|
|||
|
||||
cdef class Packet:
|
||||
cdef NetfilterQueue _queue
|
||||
cdef bint _verdict_is_set # True if verdict has been issued,
|
||||
# false otherwise
|
||||
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 bint _hwaddr_is_set
|
||||
cdef bint _timestamp_is_set
|
||||
|
@ -204,13 +207,10 @@ cdef class Packet:
|
|||
cdef unsigned char *payload
|
||||
cdef timeval timestamp
|
||||
cdef u_int8_t hw_addr[8]
|
||||
|
||||
# TODO: implement these
|
||||
#cdef readonly u_int32_t nfmark
|
||||
#cdef readonly u_int32_t indev
|
||||
#cdef readonly u_int32_t physindev
|
||||
#cdef readonly u_int32_t outdev
|
||||
#cdef readonly u_int32_t physoutdev
|
||||
cdef readonly u_int32_t indev
|
||||
cdef readonly u_int32_t physindev
|
||||
cdef readonly u_int32_t outdev
|
||||
cdef readonly u_int32_t physoutdev
|
||||
|
||||
cdef set_nfq_data(self, NetfilterQueue queue, nfq_data *nfa)
|
||||
cdef drop_refs(self)
|
||||
|
|
|
@ -11,6 +11,11 @@ class Packet:
|
|||
hw_protocol: int
|
||||
id: int
|
||||
mark: int
|
||||
# These are ifindexes, pass to socket.if_indextoname() to get names:
|
||||
indev: int
|
||||
outdev: int
|
||||
physindev: int
|
||||
physoutdev: int
|
||||
def get_hw(self) -> Optional[bytes]: ...
|
||||
def get_payload(self) -> bytes: ...
|
||||
def get_payload_len(self) -> int: ...
|
||||
|
|
|
@ -99,6 +99,10 @@ cdef class Packet:
|
|||
|
||||
nfq_get_timestamp(nfa, &self.timestamp)
|
||||
self.mark = nfq_get_nfmark(nfa)
|
||||
self.indev = nfq_get_indev(nfa)
|
||||
self.outdev = nfq_get_outdev(nfa)
|
||||
self.physindev = nfq_get_physindev(nfa)
|
||||
self.physoutdev = nfq_get_physoutdev(nfa)
|
||||
|
||||
cdef drop_refs(self):
|
||||
"""
|
||||
|
|
|
@ -119,11 +119,13 @@ async def test_mark_repeat(harness):
|
|||
assert t0 < timestamps[0] < t1
|
||||
|
||||
|
||||
async def test_hwaddr(harness):
|
||||
async def test_hwaddr_and_inoutdev(harness):
|
||||
hwaddrs = []
|
||||
inoutdevs = []
|
||||
|
||||
def cb(pkt):
|
||||
hwaddrs.append((pkt.get_hw(), pkt.hook, pkt.get_payload()[28:]))
|
||||
inoutdevs.append((pkt.indev, pkt.outdev))
|
||||
pkt.accept()
|
||||
|
||||
queue_num, nfq = harness.bind_queue(cb)
|
||||
|
@ -162,6 +164,20 @@ async def test_hwaddr(harness):
|
|||
(None, OUTPUT, b"four"),
|
||||
]
|
||||
|
||||
if sys.implementation.name != "pypy":
|
||||
# pypy doesn't appear to provide if_nametoindex()
|
||||
iface1 = socket.if_nametoindex("veth1")
|
||||
iface2 = socket.if_nametoindex("veth2")
|
||||
else:
|
||||
iface1, iface2 = inoutdevs[0]
|
||||
assert 0 != iface1 != iface2 != 0
|
||||
assert inoutdevs == [
|
||||
(iface1, iface2),
|
||||
(iface1, iface2),
|
||||
(0, iface2),
|
||||
(0, iface2),
|
||||
]
|
||||
|
||||
|
||||
async def test_errors(harness):
|
||||
with pytest.warns(RuntimeWarning, match="rcvbuf limit is") as record:
|
||||
|
|
Loading…
Reference in New Issue