From 86a43d850c60d48108836734a7ba7493dd95212c Mon Sep 17 00:00:00 2001 From: gpotter2 <gabriel@potter.fr> Date: Mon, 18 Sep 2017 21:38:08 +0200 Subject: [PATCH] Unify BPF pointers generation --- scapy/arch/bpf/core.py | 36 ++++-------------------------------- scapy/arch/common.py | 36 ++++++++++++++++++++++++++++++++++++ scapy/arch/linux.py | 19 +++++-------------- 3 files changed, 45 insertions(+), 46 deletions(-) diff --git a/scapy/arch/bpf/core.py b/scapy/arch/bpf/core.py index 19225454..8d749dd8 100644 --- a/scapy/arch/bpf/core.py +++ b/scapy/arch/bpf/core.py @@ -8,7 +8,7 @@ from __future__ import absolute_import from scapy.config import conf from scapy.error import Scapy_Exception, warning from scapy.data import ARPHDR_LOOPBACK, ARPHDR_ETHER -from scapy.arch.common import get_if +from scapy.arch.common import get_if, get_bpf_pointer from scapy.consts import LOOPBACK_NAME from scapy.arch.bpf.consts import * @@ -19,7 +19,7 @@ import fcntl import struct from ctypes import cdll, cast, pointer, POINTER, Structure -from ctypes import c_uint, c_uint32, c_int, c_ulong, c_char_p, c_ushort, c_ubyte +from ctypes import c_int, c_ulong, c_char_p from ctypes.util import find_library from scapy.modules.six.moves import range @@ -31,20 +31,6 @@ LIBC.ioctl.argtypes = [c_int, c_ulong, c_char_p] LIBC.ioctl.restype = c_int -class bpf_insn(Structure): - """"The BPF instruction data structure""" - _fields_ = [("code", c_ushort), - ("jt", c_ubyte), - ("jf", c_ubyte), - ("k", c_uint32)] - - -class bpf_program(Structure): - """"Structure for BIOCSETF""" - _fields_ = [("bf_len", c_uint), - ("bf_insns", POINTER(bpf_insn))] - - # Addresses manipulation functions def get_if_raw_addr(ifname): @@ -127,22 +113,8 @@ def attach_filter(fd, iface, bpf_filter_string): if lines == []: raise Scapy_Exception("Got an empty BPF filter from tcpdump !") - # Allocate BPF instructions - size = int(lines[0]) - bpf_insn_a = bpf_insn * size - bip = bpf_insn_a() - - # Fill the BPF instruction structures with the byte code - lines = lines[1:] - for i in range(len(lines)): - values = [int(v) for v in lines[i].split()] - bip[i].code = c_ushort(values[0]) - bip[i].jt = c_ubyte(values[1]) - bip[i].jf = c_ubyte(values[2]) - bip[i].k = c_uint(values[3]) - - # Create the BPF program and assign it to the interface - bp = bpf_program(size, bip) + bp = get_bpf_pointer(lines) + # Assign the BPF program to the interface ret = LIBC.ioctl(c_int(fd), BIOCSETF, cast(pointer(bp), c_char_p)) if ret < 0: raise Scapy_Exception("Can't attach the BPF filter !") diff --git a/scapy/arch/common.py b/scapy/arch/common.py index 6b309c7a..c0113701 100644 --- a/scapy/arch/common.py +++ b/scapy/arch/common.py @@ -10,6 +10,8 @@ Functions common to different architectures import socket from fcntl import ioctl import struct +from ctypes import POINTER, Structure +from ctypes import c_uint, c_uint32, c_ushort, c_ubyte def get_if(iff, cmd): """Ease SIOCGIF* ioctl calls""" @@ -18,3 +20,37 @@ def get_if(iff, cmd): ifreq = ioctl(sck, cmd, struct.pack("16s16x", iff.encode("utf8"))) sck.close() return ifreq + +class bpf_insn(Structure): + """"The BPF instruction data structure""" + _fields_ = [("code", c_ushort), + ("jt", c_ubyte), + ("jf", c_ubyte), + ("k", c_uint32)] + + +class bpf_program(Structure): + """"Structure for BIOCSETF""" + _fields_ = [("bf_len", c_uint), + ("bf_insns", POINTER(bpf_insn))] + +def get_bpf_pointer(tcpdump_lines): + """Create a BPF Pointer for TCPDump filter""" + # Allocate BPF instructions + size = int(tcpdump_lines[0]) + bpf_insn_a = bpf_insn * size + bip = bpf_insn_a() + + # Fill the BPF instruction structures with the byte code + tcpdump_lines = tcpdump_lines[1:] + i = 0 + for line in tcpdump_lines: + values = [int(v) for v in line.split()] + bip[i].code = c_ushort(values[0]) + bip[i].jt = c_ubyte(values[1]) + bip[i].jf = c_ubyte(values[2]) + bip[i].k = c_uint(values[3]) + i += 1 + + # Create the BPF program + return bpf_program(size, bip) diff --git a/scapy/arch/linux.py b/scapy/arch/linux.py index 9a3820a0..b44b3f02 100644 --- a/scapy/arch/linux.py +++ b/scapy/arch/linux.py @@ -8,7 +8,7 @@ Linux specific functions. """ from __future__ import absolute_import -import sys,os,struct,socket,time +import sys, os, struct, socket, time from select import select from fcntl import ioctl import array, ctypes @@ -23,7 +23,7 @@ from scapy.data import * from scapy.supersocket import SuperSocket import scapy.arch from scapy.error import warning, Scapy_Exception, log_interactive, log_loading -from scapy.arch.common import get_if +from scapy.arch.common import get_if, get_bpf_pointer from scapy.modules.six.moves import range @@ -152,18 +152,9 @@ def attach_filter(s, bpf_filter, iface): "Failed to attach filter: tcpdump returned %d", ret ) return - nb = int(lines[0]) - bpf = b"" - for l in lines[1:]: - bpf += struct.pack("HBBI", *(int(e) for e in l.split())) - - # XXX. Argl! We need to give the kernel a pointer on the BPF - bpf_buf = ctypes.create_string_buffer(bpf) - class BpfPointer(ctypes.Structure): - _fields_ = [ ("bf_len", ctypes.c_int), - ("bf_insn", ctypes.POINTER(type(bpf_buf))) ] - bpfh = BpfPointer(nb, ctypes.pointer(bpf_buf)) - s.setsockopt(SOL_SOCKET, SO_ATTACH_FILTER, bpfh) + + bp = get_bpf_pointer(lines) + s.setsockopt(SOL_SOCKET, SO_ATTACH_FILTER, bp) def set_promisc(s,iff,val=1): mreq = struct.pack("IHH8s", get_if_index(iff), PACKET_MR_PROMISC, 0, b"") -- GitLab