#!/usr/bin/env python # # Copyright (c) 2009 Andrew Grigorev # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. # import sys from ctypes import * from threading import Thread nfct = CDLL('libnetfilter_conntrack.so') libc = CDLL('libc.so.6') NFCT_CALLBACK = CFUNCTYPE(c_int, c_int, c_void_p, c_void_p) # conntrack CONNTRACK = 1 EXPECT = 2 # netlink groups NF_NETLINK_CONNTRACK_NEW = 0x00000001 NF_NETLINK_CONNTRACK_UPDATE = 0x00000002 NF_NETLINK_CONNTRACK_DESTROY = 0x00000004 NF_NETLINK_CONNTRACK_EXP_NEW = 0x00000008 NF_NETLINK_CONNTRACK_EXP_UPDATE = 0x00000010 NF_NETLINK_CONNTRACK_EXP_DESTROY = 0x00000020 NFCT_ALL_CT_GROUPS = (NF_NETLINK_CONNTRACK_NEW | NF_NETLINK_CONNTRACK_UPDATE \ | NF_NETLINK_CONNTRACK_DESTROY) # nfct_*printf output format NFCT_O_PLAIN = 0 NFCT_O_DEFAULT = NFCT_O_PLAIN NFCT_O_XML = 1 NFCT_O_MAX = 2 # output flags NFCT_OF_SHOW_LAYER3_BIT = 0 NFCT_OF_SHOW_LAYER3 = (1 << NFCT_OF_SHOW_LAYER3_BIT) NFCT_OF_TIME_BIT = 1 NFCT_OF_TIME = (1 << NFCT_OF_TIME_BIT) NFCT_OF_ID_BIT = 2 NFCT_OF_ID = (1 << NFCT_OF_ID_BIT) # callback return code NFCT_CB_FAILURE = -1 # failure NFCT_CB_STOP = 0 # stop the query NFCT_CB_CONTINUE = 1 # keep iterating through data NFCT_CB_STOLEN = 2 # like continue, but ct is not freed # message type NFCT_T_UNKNOWN = 0 NFCT_T_NEW_BIT = 0 NFCT_T_NEW = (1 << NFCT_T_NEW_BIT) NFCT_T_UPDATE_BIT = 1 NFCT_T_UPDATE = (1 << NFCT_T_UPDATE_BIT) NFCT_T_DESTROY_BIT = 2 NFCT_T_DESTROY = (1 << NFCT_T_DESTROY_BIT) NFCT_T_ALL = NFCT_T_NEW | NFCT_T_UPDATE | NFCT_T_DESTROY NFCT_T_ERROR_BIT = 31 NFCT_T_ERROR = (1 << NFCT_T_ERROR_BIT) class ConntrackEventListener(Thread): def __init__(self, callback, msg_types=NFCT_T_NEW|NFCT_T_DESTROY): Thread.__init__(self) self.h = nfct.nfct_open(CONNTRACK, NFCT_ALL_CT_GROUPS) if self.h == 0: libc.perror("nfct_open") raise Exception("nfct_open failed!") buf = create_string_buffer(1024) self._stop = False def event_callback_closure(type, ct, data): nfct.nfct_snprintf(buf, 1024, ct, type, NFCT_O_XML, NFCT_OF_TIME) callback(buf.value) if self._stop: return NFCT_CB_STOP return NFCT_CB_CONTINUE self.cb = NFCT_CALLBACK(event_callback_closure) nfct.nfct_callback_register(self.h, msg_types, self.cb, 0) def run(self): ret = nfct.nfct_catch(self.h) nfct.nfct_callback_unregister(self.h) nfct.nfct_close(self.h) if ret == -1: libc.perror("nfct_catch") raise Exception("nfct_catch failed!") def stop(self): self._stop = True __all__ = ["ConntrackEventListener", "NFCT_T_NEW", "NFCT_T_UPDATE", "NFCT_T_DESTROY", "NFCT_T_ERROR"] if __name__ == "__main__": l = ConntrackEventListener(lambda x: sys.stdout.write("%s\n" % x)) l.start() try: input() except: pass sys.stdout.write("Terminating (waiting for last event...)\n") l.stop() l.join()