|
- # git+https://github.com/secdev/scapy.git
-
- import fcntl
- import os
- import struct
- import sys
-
- from scapy.all import *
- from scapy.arch.bpf.consts import BIOCGBLEN, BIOCGDLT, BIOCSDLT, BIOCSETIF, BIOCIMMEDIATE
-
- from ctypes import Structure, c_char, c_long, c_int, c_uint, c_ushort, c_uint16, c_uint32, sizeof
-
- class ReprStructureMixin:
- def format_field(self, k):
- try:
- bits = getattr(self, '_bits_%s' % k)
- return str(makebits(getattr(self, k), bits))
- except AttributeError:
- return repr(getattr(self, k))
-
- def __repr__(self):
- args = tuple(self.format_field(x[0]) for x in self._fields_)
- return '%s(%s)' % (self.__class__.__name__, ', '.join(args))
-
- class Timeval(Structure, ReprStructureMixin):
- _fields_ = [
- ('tv_sec', c_long),
- ('tv_usec', c_long),
- ]
-
- class bpf_hdr(Structure, ReprStructureMixin):
- _fields_ = [
- ('bh_tstamp', Timeval),
- ('bh_caplen', c_uint32),
- ('bh_datalen', c_uint32),
- ('bh_hdrlen', c_ushort),
- ]
-
- pkthdrbits = { 1: 'CSUM', 2: 'VLAN_TAG', 4: 'TSTMP' }
- # awk '{ print $3 ": '"'"'" $2 "'"'"'," }'
- csumflagbits = {
- 0x00000001: 'CSUM_IP',
- 0x00000002: 'CSUM_IP_UDP',
- 0x00000004: 'CSUM_IP_TCP',
- 0x00000008: 'CSUM_IP_SCTP',
- 0x00000010: 'CSUM_IP_TSO',
- 0x00000020: 'CSUM_IP_ISCSI',
- 0x00000040: 'CSUM_INNER_IP6_UDP',
- 0x00000080: 'CSUM_INNER_IP6_TCP',
- 0x00000100: 'CSUM_INNER_IP6_TSO',
- 0x00000200: 'CSUM_IP6_UDP',
- 0x00000400: 'CSUM_IP6_TCP',
- 0x00000800: 'CSUM_IP6_SCTP',
- 0x00001000: 'CSUM_IP6_TSO',
- 0x00002000: 'CSUM_IP6_ISCSI',
- 0x00004000: 'CSUM_INNER_IP',
- 0x00008000: 'CSUM_INNER_IP_UDP',
- 0x00010000: 'CSUM_INNER_IP_TCP',
- 0x00020000: 'CSUM_INNER_IP_TSO',
- 0x00040000: 'CSUM_ENCAP_VXLAN',
- 0x00080000: 'CSUM_ENCAP_RSVD1',
- 0x00100000: 'CSUM_INNER_L3_CALC',
- 0x00200000: 'CSUM_INNER_L3_VALID',
- 0x00400000: 'CSUM_INNER_L4_CALC',
- 0x00800000: 'CSUM_INNER_L4_VALID',
- 0x01000000: 'CSUM_L3_CALC',
- 0x02000000: 'CSUM_L3_VALID',
- 0x04000000: 'CSUM_L4_CALC',
- 0x08000000: 'CSUM_L4_VALID',
- 0x10000000: 'CSUM_L5_CALC',
- 0x20000000: 'CSUM_L5_VALID',
- 0x40000000: 'CSUM_COALESCED',
- 0x80000000: 'CSUM_SND_TAG',
- }
-
- class fbsdpkthdr(Structure, ReprStructureMixin):
- _bits_fph_bits = pkthdrbits
- _bits_fph_csum_flags = csumflagbits
- _fields_ = [
- ('fph_magic', c_char * 4),
- ('fph_hdrlen', c_uint32),
- ('fph_recvif', c_char * 16),
- ('fph_bits', c_uint32),
- ('fph_flowid', c_uint32),
- ('fph_csum_flags', c_uint32),
- ('fph_csum_data', c_uint32),
- ('fph_vlan_tag', c_uint16),
- ]
-
- class BPF:
- def __init__(self, iface):
- f = self._fp = os.open('/dev/bpf', os.O_RDONLY)
- l = fcntl.ioctl(f, BIOCGBLEN, b'\x00'*4, True)
- sz = c_int.from_buffer_copy(l)
-
- self._blen = sz.value
-
- fcntl.ioctl(f, BIOCIMMEDIATE, struct.pack('I', 1))
- fcntl.ioctl(f, BIOCSETIF, struct.pack('16s16x', iface.encode()))
- fcntl.ioctl(f, BIOCSDLT, struct.pack('I', 154))
-
- def getpkt(self):
- bytes = os.read(self._fp, self._blen)
-
- bpfhdr = bpf_hdr.from_buffer_copy(bytes)
-
- off = bpfhdr.bh_hdrlen
- fbsdhdr = fbsdpkthdr.from_buffer_copy(bytes, off)
- off += fbsdhdr.fph_hdrlen
- pkt = bytes[off:]
-
- return fbsdhdr, pkt
-
- def makebits(val, bits):
- r = [ v for k, v in bits.items() if k & val ]
-
- if not r:
- return 0
-
- return '|'.join(r)
-
- if __name__ == '__main__':
- bpf = BPF(sys.argv[1])
-
- while True:
- hdr, pkt = bpf.getpkt()
- print(repr(hdr))
- #pkthdr = struct.unpack(fbsdpkthdr, pkt[hdrlen:hdrlen + fbsdpkthdrlen])
- #pkthdr = list(pkthdr)
- #pkthdr[2] = pkthdr[2].strip(b'\x00').decode('us-ascii')
- #print(repr(pkthdr), fbsdpkthdrlen)
- if hdr.fph_magic != b'FBSD':
- print('magic wrong')
- continue
- # XXX calcsize is wrong here
- if sizeof(hdr) != hdr.fph_hdrlen:
- print('length mismatch')
- continue
- print(repr(Ether(pkt))[:300])
|