• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1## This file is part of Scapy
2## See http://www.secdev.org/projects/scapy for more informations
3## Copyright (C) Philippe Biondi <phil@secdev.org>
4## This program is published under a GPLv2 license
5
6"""
7Functions common to different architectures
8"""
9
10import socket
11from fcntl import ioctl
12import os, struct, ctypes
13from ctypes import POINTER, Structure
14from ctypes import c_uint, c_uint32, c_ushort, c_ubyte
15from scapy.config import conf
16import scapy.modules.six as six
17
18def get_if(iff, cmd):
19    """Ease SIOCGIF* ioctl calls"""
20
21    sck = socket.socket()
22    ifreq = ioctl(sck, cmd, struct.pack("16s16x", iff.encode("utf8")))
23    sck.close()
24    return ifreq
25
26class bpf_insn(Structure):
27    """"The BPF instruction data structure"""
28    _fields_ = [("code", c_ushort),
29                ("jt", c_ubyte),
30                ("jf", c_ubyte),
31                ("k", c_uint32)]
32
33
34class bpf_program(Structure):
35    """"Structure for BIOCSETF"""
36    _fields_ = [("bf_len", c_uint),
37                ("bf_insns", POINTER(bpf_insn))]
38
39def _legacy_bpf_pointer(tcpdump_lines):
40    """Get old-format BPF Pointer. Deprecated"""
41    X86_64 = os.uname()[4] in ['x86_64', 'aarch64']
42    size = int(tcpdump_lines[0])
43    bpf = ""
44    for l in tcpdump_lines[1:]:
45        bpf += struct.pack("HBBI",*map(long,l.split()))
46
47    # Thanks to http://www.netprojects.de/scapy-with-pypy-solved/ for the pypy trick
48    if conf.use_pypy and six.PY2:
49        str_buffer = ctypes.create_string_buffer(bpf)
50        return struct.pack('HL', size, ctypes.addressof(str_buffer))
51    else:
52        # XXX. Argl! We need to give the kernel a pointer on the BPF,
53        # Python object header seems to be 20 bytes. 36 bytes for x86 64bits arch.
54        if X86_64:
55            return struct.pack("HL", size, id(bpf)+36)
56        else:
57            return struct.pack("HI", size, id(bpf)+20)
58
59def get_bpf_pointer(tcpdump_lines):
60    """Create a BPF Pointer for TCPDump filter"""
61    if conf.use_pypy and six.PY2:
62        return _legacy_bpf_pointer(tcpdump_lines)
63
64    # Allocate BPF instructions
65    size = int(tcpdump_lines[0])
66    bpf_insn_a = bpf_insn * size
67    bip = bpf_insn_a()
68
69    # Fill the BPF instruction structures with the byte code
70    tcpdump_lines = tcpdump_lines[1:]
71    i = 0
72    for line in tcpdump_lines:
73        values = [int(v) for v in line.split()]
74        bip[i].code = c_ushort(values[0])
75        bip[i].jt = c_ubyte(values[1])
76        bip[i].jf = c_ubyte(values[2])
77        bip[i].k = c_uint(values[3])
78        i += 1
79
80    # Create the BPF program
81    return bpf_program(size, bip)
82