$search
00001 #! /usr/bin/env python 00002 00003 from __future__ import with_statement 00004 00005 from twisted.internet import reactor 00006 import pcap 00007 import event 00008 import threading 00009 import socket 00010 00011 class AlreadyClosed(Exception): 00012 pass 00013 00014 def RawSocket(iface): 00015 # We use this convoluted method so that we can have a filter 00016 # that rejects all packets set. 00017 p = pcap.pcapObject() 00018 p.open_live(iface, 1, 0, 0) 00019 p.setfilter("less 0", 1, 0) 00020 p.setnonblock(True) 00021 import os 00022 #return os.fdopen(p.fileno(),'w',0) 00023 s = socket.fromfd(p.fileno(), socket.PF_PACKET, socket.SOCK_RAW) 00024 p.open_dead(0, 0) 00025 return s 00026 00027 class Capture(event.Event): 00028 class _CaptureDescriptor: 00029 def __init__(self, parent, iface = 'any', filter = None, snaplen = 65535, promisc = False, timeout = 10): 00030 self.parent = parent 00031 self.pcap = pcap.pcapObject() 00032 self.pcap.open_live(iface, snaplen, promisc, 0) 00033 if filter is not None: 00034 self.pcap.setfilter(filter, 1, 0) 00035 self.pcap.setnonblock(True) 00036 reactor.addReader(self) 00037 00038 def fileno(self): 00039 if self.pcap is None: 00040 return -1 00041 return self.pcap.fileno() 00042 00043 def connectionLost(self, reason): 00044 if self.parent: 00045 self.parent.trigger(None, None, None) 00046 00047 def logPrefix(self): 00048 return "" 00049 00050 def _cb(self, *args): 00051 self._got_pkt = True 00052 self.parent.trigger(*args) 00053 00054 def doRead(self): 00055 print "doRead" 00056 if self.parent: 00057 self._got_pkt = False 00058 self.pcap.dispatch(-1, self._cb) 00059 # If the interface goes down, then the socket will always 00060 # be readable, but never contain any data. We catch that 00061 # case, and assume that it means the socket is closed. 00062 if not self._got_pkt: 00063 self.parent.trigger(None, None, None) 00064 self.close() 00065 00066 def close(self): 00067 print "Closing descriptor." 00068 reactor.removeReader(self) 00069 self.pcap.open_dead(0, 0) 00070 self.pcap = None 00071 self.parent = None 00072 00073 def __init__(self, *args, **kwargs): 00074 self._descr = None 00075 self._args = args 00076 self._kwargs = kwargs 00077 self._sub_change_lock = threading.Lock() 00078 event.Event.__init__(self) 00079 00080 def _subscription_change(self): 00081 with self._sub_change_lock: 00082 has_descr = self._descr is not None 00083 has_subs = len(self._subscribers) != 0 00084 if has_descr and not has_subs: 00085 print "No more subscribers!" 00086 self._descr.close() 00087 self._descr = None 00088 elif not has_descr and has_subs: 00089 print "Subscribers added!" 00090 if self._args != None: # We are not closed. 00091 self._descr = Capture._CaptureDescriptor(self, *self._args, **self._kwargs) 00092 else: 00093 # There is a race that lets a subscribe slip through 00094 # just after close does its unsubscribe_all. This case patches it. 00095 self.unsubscribe_all(blocking = False) 00096 00097 def subscribe(self, *args, **kwargs): 00098 if self._args is None: 00099 raise AlreadyClosed("Attempted to subscribe to a closed Capture object.") 00100 return event.Event.subscribe(self, *args, **kwargs) 00101 00102 def close(self): 00103 with self._sub_change_lock: 00104 self._args = None 00105 self._kwargs = None 00106 self.unsubscribe_all(blocking = False) 00107 00108 def __enter__(self): 00109 pass 00110 00111 def __exit__(self, *args): 00112 self.close() 00113 00114 if __name__ == "__main__": 00115 import scapy.layers.l2 00116 import scapy.layers.inet 00117 00118 def print_pkt(iface, len, data, time): 00119 print time, iface, len, repr(scapy.layers.l2.Ether(data).payload.payload) 00120 00121 import gc 00122 def hasPcapObj(): 00123 count = 0 00124 for obj in gc.get_objects(): 00125 #t = type(obj) 00126 if isinstance(obj, pcap.pcapObject) or \ 00127 isinstance(obj, event.EventCallbackHandle) or \ 00128 isinstance(obj, Capture._CaptureDescriptor) or \ 00129 isinstance(obj, Capture): 00130 if isinstance(obj, Capture): 00131 print obj, gc.get_referents(gc.get_referents(obj)) 00132 count += 1 00133 print "objects found:", count 00134 00135 class DeathReporter: 00136 def __init__(self, name): 00137 self.name = name 00138 00139 def __del__(self, *args): 00140 print "I'm dead!", self.name 00141 00142 hasPcapObj() 00143 c1 = Capture('lo', 'icmp') 00144 h = c1.subscribe_repeating(print_pkt, 'lo') 00145 #reactor.callLater(1, hasPcapObj) 00146 #reactor.callLater(2, h.unsubscribe) 00147 #reactor.callLater(3, hasPcapObj) 00148 #reactor.callLater(4, c1.subscribe_repeating, print_pkt, 'lo') 00149 #reactor.callLater(5, hasPcapObj) 00150 #reactor.callLater(6, c1.close) 00151 #reactor.callLater(7, hasPcapObj) 00152 #reactor.callLater(8, c1.subscribe_repeating, print_pkt, 'lo') 00153 #reactor.callLater(9, hasPcapObj) 00154 #print type(h) 00155 #print type(c1) 00156 #print c1.__class__, Capture 00157 #del c1 00158 #del h 00159 reactor.run() 00160 #hasPcapObj() 00161 00162