diff --git a/netfilterqueue/_impl.pxd b/netfilterqueue/_impl.pxd index 54c2fa3..8a9eba6 100644 --- a/netfilterqueue/_impl.pxd +++ b/netfilterqueue/_impl.pxd @@ -154,6 +154,8 @@ 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) + u_int8_t nfq_get_indev(nfq_data *nfad) + u_int8_t nfq_get_outdev(nfq_data *nfad) nfnl_handle *nfq_nfnlh(nfq_handle *h) # Dummy defines from linux/socket.h: @@ -193,6 +195,8 @@ cdef class Packet: cdef bytes _given_payload # New payload of packet, or null cdef bytes _owned_payload + cdef nfq_data *_nfa + # From NFQ packet header: cdef readonly u_int32_t id cdef readonly u_int16_t hw_protocol @@ -215,6 +219,8 @@ cdef class Packet: cdef set_nfq_data(self, NetfilterQueue queue, nfq_data *nfa) cdef drop_refs(self) cdef int verdict(self, u_int8_t verdict) except -1 + cpdef get_indev(self, bint name=*) + cpdef get_outdev(self, bint name=*) cpdef Py_ssize_t get_payload_len(self) cpdef double get_timestamp(self) cpdef bytes get_payload(self) diff --git a/netfilterqueue/_impl.pyi b/netfilterqueue/_impl.pyi index 3cba8fc..f8e4628 100644 --- a/netfilterqueue/_impl.pyi +++ b/netfilterqueue/_impl.pyi @@ -12,6 +12,8 @@ class Packet: id: int mark: int def get_hw(self) -> Optional[bytes]: ... + def get_indev(self, name: bool = False): ... + def get_outdev(self, name: bool = False): ... def get_payload(self) -> bytes: ... def get_payload_len(self) -> int: ... def get_timestamp(self) -> float: ... diff --git a/netfilterqueue/_impl.pyx b/netfilterqueue/_impl.pyx index d656d5b..94fcb52 100644 --- a/netfilterqueue/_impl.pyx +++ b/netfilterqueue/_impl.pyx @@ -4,9 +4,16 @@ function. Copyright: (c) 2011, Kerkhoff Technologies Inc. License: MIT; see LICENSE.txt + +Expanded features and performance improvements from downstream development +of DNXFIREWALL. + - DOWRIGHT @ Wright Network Solutions, LLC. """ # Constants for module users +import Cython +import socket + COPY_NONE = 0 COPY_META = 1 COPY_PACKET = 2 @@ -41,7 +48,9 @@ cdef int global_callback(nfq_q_handle *qh, nfgenmsg *nfmsg, # so just ignore the packet. The kernel will drop it once we # unbind. return 1 - packet = Packet() + + # skipping call to __init__. + packet = Packet.__new__(Packet) packet.set_nfq_data(nfqueue, nfa) try: user_callback(packet) @@ -49,6 +58,8 @@ cdef int global_callback(nfq_q_handle *qh, nfgenmsg *nfmsg, packet.drop_refs() return 1 +# pre allocated memory for Packet object. +@Cython.freelist(8) cdef class Packet: """A packet received from NetfilterQueue.""" def __cinit__(self): @@ -69,6 +80,8 @@ cdef class Packet: cdef nfqnl_msg_packet_hw *hw cdef nfqnl_msg_packet_hdr *hdr + self._nfa = nfa + hdr = nfq_get_msg_packet_hdr(nfa) self._queue = queue self.id = ntohl(hdr.packet_id) @@ -129,6 +142,46 @@ cdef class Packet: self._verdict_is_set = True + cpdef get_indev(self, bint name=False): + """Returns the index of the inbound interface of the packet. If the packet + sourced from localhost or the input interface is not known, 0/unknown will + be returned respectively. + + if name=True, socket.if_indextoname() will be returned. + """ + cdef object in_interface_name + + in_interface = nfq_get_indev(self._nfa) + if not name: + return in_interface + + try: + in_interface_name = socket.if_indextoname(in_interface) + except OSError: + in_interface_name = 'unknown' + + return in_interface_name + + cpdef get_outdev(self, bint name=False): + """Returns the index of the outbound interface of the packet. If the packet + sourced from localhost or the input interface is not known, 0/unknown will + be returned respectively. + + if name=True, socket.if_indextoname() will be returned. + """ + cdef object out_interface_name + + out_interface = nfq_get_outdev(self._nfa) + if not name: + return out_interface + + try: + out_interface_name = socket.if_indextoname(out_interface) + except OSError: + out_interface_name = 'unknown' + + return out_interface_name + def get_hw(self): """Return the packet's source MAC address as a Python bytestring, or None if it's not available.