summaryrefslogtreecommitdiff
path: root/mypcap.py
blob: 9a3b3c412a32f250950f55953b25eb01d6c25295 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
#!/usr/bin/python

from time import time
import logging
from ctypes import (cdll, c_char_p, create_string_buffer, Structure, byref
    , c_int32, c_long, pointer, POINTER, c_char)

logger = logging.getLogger('mypcap')
pcap = cdll.LoadLibrary('libpcap.so')
PCAP_ERRBUF_SIZE = 1000 # bogus
DATA_SIZE = 2000000
for f in "pcap_next pcap_create pcap_set_snaplen pcap_set_buffer_size pcap_activate pcap_next_ex pcap_perror".split():
    if len(f) > 0:
        globals()[f] = getattr(pcap, f)

time_t = c_long
class timeval(Structure):
    _fields_ = [('tv_sec',  time_t),
               ('tv_usec', c_long)]

class  pcap_pkthdr(Structure):
    _fields_ = [('ts', timeval),    # time stamp
                ('caplen', c_int32), # length of portion present
                ('len', c_int32)]   # length this packet (off wire)

PCAP_ERROR          = -1  # generic error code
PCAP_ERROR_BREAK        = -2  # loop terminated by pcap_breakloop
PCAP_ERROR_NOT_ACTIVATED    = -3  # the capture needs to be activated
PCAP_ERROR_ACTIVATED        = -4  # the operation can't be performed on already activated captures
PCAP_ERROR_NO_SUCH_DEVICE   = -5  # no such device exists
PCAP_ERROR_RFMON_NOTSUP     = -6  # this device doesn't support rfmon (monitor) mode
PCAP_ERROR_NOT_RFMON        = -7  # operation supported only in monitor mode
PCAP_ERROR_PERM_DENIED      = -8  # no permission to open the device
PCAP_ERROR_IFACE_NOT_UP     = -9  # interface isn't up

PCAP_WARNING            = 1   # generic warning code
PCAP_WARNING_PROMISC_NOTSUP = 2   # this device doesn't support promiscuous mode

pcap_errors = [PCAP_ERROR_ACTIVATED
                ,PCAP_ERROR_NO_SUCH_DEVICE
                ,PCAP_ERROR_PERM_DENIED
                ,PCAP_ERROR_RFMON_NOTSUP
                ,PCAP_ERROR_IFACE_NOT_UP
                ,PCAP_ERROR]

pcap_next.restype = POINTER(c_char)

class PCAPError(Exception):
    pass

class PCAP(object):
    def __init__(self, dev):
        self.errbuf = create_string_buffer(PCAP_ERRBUF_SIZE)
        self.hdr = pcap_pkthdr()
        self.hdrp = pointer(self.hdr)
        self.pcap = pcap_create(dev, self.errbuf)
        if self.pcap == 0:
            raise PCAPError("error: %s" % self.errbuf.value)
        if pcap_set_snaplen(self.pcap, 65536) != 0:
            raise PCAPError("error: set snaplen failed")
        if pcap_set_buffer_size(self.pcap, DATA_SIZE) != 0:
            raise PCAPError("error: set buffer size failed")
        ret = pcap_activate(self.pcap)
        if ret in [PCAP_WARNING_PROMISC_NOTSUP, PCAP_WARNING]:
            logger.warning("pcap_activate returned a warning - %d" % ret)
        elif ret in pcap_errors:
            pcap_perror(self.pcap, "")
            raise PCAPError('pcap_activate failed')

    def __iter__(self):
        i_pkt = 0
        hdr = self.hdr
        total = 0
        while True:
            data = pcap_next(self.pcap, self.hdrp)
            #ret = pcap_next_ex(self.pcap, byref(hdrp), byref(data));
            ret = 1
            if ret == 1:
                total += hdr.len
                i_pkt += 1
                secs = float(hdr.ts.tv_sec) + float(hdr.ts.tv_usec)/1000000
                logger.debug("%3d: %5.3f, %d, %d| %d" % (
                    i_pkt, secs, hdr.caplen, hdr.len, total))
                yield secs, data[:hdr.len] # if data is NULL?
            elif ret == 0:
                logger.debug("%3d: timeout" % i_pkt)
            elif ret == -1:
                pcap_perror(self.pcap, "")
                raise PCAPError("pcap_next errored")
            else:
                raise PCAPError("error: unexpected return %d" % ret)

pcap = PCAP

def main():
    cap_2 = 10
    cap = 2*cap_2
    total = 0
    start = time()
    for secs, data in pcap('lo'):
        if len(data) > cap:
            r = data[:cap_2] + ('...%s...' % (len(data) - cap)) + data[-cap_2:]
        else:
            r = data
        total += len(data)
        print '%7.3f %12d %10d %s' % (secs, total, len(data), repr(r))

if __name__ == '__main__':
    import sys
    sys.exit(main())