00001
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
00016
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
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
00060
00061
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:
00091 self._descr = Capture._CaptureDescriptor(self, *self._args, **self._kwargs)
00092 else:
00093
00094
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
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
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159 reactor.run()
00160
00161
00162