예제 #1
0
def get_if_raw_addr(ifname):
    """Returns the IPv4 address configured on 'ifname', packed with inet_pton."""  # noqa: E501

    ifname = network_name(ifname)

    # Get ifconfig output
    subproc = subprocess.Popen(
        [conf.prog.ifconfig, ifname],
        close_fds=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE
    )
    stdout, stderr = subproc.communicate()
    if subproc.returncode:
        warning("Failed to execute ifconfig: (%s)", plain_str(stderr).strip())
        return b"\0\0\0\0"

    # Get IPv4 addresses
    addresses = [
        line.strip() for line in plain_str(stdout).splitlines()
        if "inet " in line
    ]

    if not addresses:
        warning("No IPv4 address found on %s !", ifname)
        return b"\0\0\0\0"

    # Pack the first address
    address = addresses[0].split(' ')[1]
    if '/' in address:  # NetBSD 8.0
        address = address.split("/")[0]
    return socket.inet_pton(socket.AF_INET, address)
def sendpfast(x, pps=None, mbps=None, realtime=None, loop=0, file_cache=False, iface=None, replay_args=None,  # noqa: E501
              parse_results=False):
    """Send packets at layer 2 using tcpreplay for performance

    :param pps:  packets per second
    :param mpbs: MBits per second
    :param realtime: use packet's timestamp, bending time with real-time value
    :param loop: number of times to process the packet list
    :param file_cache: cache packets in RAM instead of reading from
        disk at each iteration
    :param iface: output interface
    :param replay_args: List of additional tcpreplay args (List[str])
    :param parse_results: Return a dictionary of information
        outputted by tcpreplay (default=False)
    :returns: stdout, stderr, command used
    """
    if iface is None:
        iface = conf.iface
    argv = [conf.prog.tcpreplay, "--intf1=%s" % network_name(iface)]
    if pps is not None:
        argv.append("--pps=%i" % pps)
    elif mbps is not None:
        argv.append("--mbps=%f" % mbps)
    elif realtime is not None:
        argv.append("--multiplier=%f" % realtime)
    else:
        argv.append("--topspeed")

    if loop:
        argv.append("--loop=%i" % loop)
    if file_cache:
        argv.append("--preload-pcap")

    # Check for any additional args we didn't cover.
    if replay_args is not None:
        argv.extend(replay_args)

    f = get_temp_file()
    argv.append(f)
    wrpcap(f, x)
    results = None
    with ContextManagerSubprocess(conf.prog.tcpreplay):
        try:
            cmd = subprocess.Popen(argv, stdout=subprocess.PIPE,
                                   stderr=subprocess.PIPE)
        except KeyboardInterrupt:
            log_interactive.info("Interrupted by user")
        except Exception:
            os.unlink(f)
            raise
        else:
            stdout, stderr = cmd.communicate()
            if stderr:
                log_runtime.warning(stderr.decode())
            if parse_results:
                results = _parse_tcpreplay_result(stdout, stderr, argv)
            elif conf.verb > 2:
                log_runtime.info(stdout.decode())
    os.unlink(f)
    return results
예제 #3
0
def get_if_raw_hwaddr(ifname):
    """Returns the packed MAC address configured on 'ifname'."""

    NULL_MAC_ADDRESS = b'\x00' * 6

    ifname = network_name(ifname)
    # Handle the loopback interface separately
    if ifname == conf.loopback_name:
        return (ARPHDR_LOOPBACK, NULL_MAC_ADDRESS)

    # Get ifconfig output
    subproc = subprocess.Popen([conf.prog.ifconfig, ifname],
                               close_fds=True,
                               stdout=subprocess.PIPE,
                               stderr=subprocess.PIPE)
    stdout, stderr = subproc.communicate()
    if subproc.returncode:
        raise Scapy_Exception("Failed to execute ifconfig: (%s)" %
                              plain_str(stderr).strip())

    # Get MAC addresses
    addresses = [
        line.strip() for line in plain_str(stdout).splitlines()
        if ("ether" in line or "lladdr" in line or "address" in line)
    ]
    if not addresses:
        raise Scapy_Exception("No MAC address found on %s !" % ifname)

    # Pack and return the MAC address
    mac = addresses[0].split(' ')[1]
    mac = [chr(int(b, 16)) for b in mac.split(':')]
    return (ARPHDR_ETHER, ''.join(mac))
예제 #4
0
 def send(self, x):
     # type: (Packet) -> int
     iff = x.route()[0]
     if iff is None:
         iff = network_name(conf.iface)
     sdto = (iff, self.type)
     self.outs.bind(sdto)
     sn = self.outs.getsockname()
     ll = lambda x: x  # type: Callable[[Packet], Packet]
     type_x = type(x)
     if type_x in conf.l3types:
         sdto = (iff, conf.l3types.layer2num[type_x])
     if sn[3] in conf.l2types:
         ll = lambda x: conf.l2types.num2layer[sn[3]]() / x
     if self.lvl == 3 and type_x != self.LL:
         warning("Incompatible L3 types detected using %s instead of %s !",
                 type_x, self.LL)
         self.LL = type_x
     sx = raw(ll(x))
     x.sent_time = time.time()
     try:
         return self.outs.sendto(sx, sdto)
     except socket.error as msg:
         if msg.errno == 22 and len(sx) < conf.min_pkt_size:
             return self.outs.send(sx + b"\x00" *
                                   (conf.min_pkt_size - len(sx)))
         elif conf.auto_fragment and msg.errno == 90:
             i = 0
             for p in x.fragment():
                 i += self.outs.sendto(raw(ll(p)), sdto)
             return i
         else:
             raise
예제 #5
0
 def __init__(
         self,
         iface=None,  # type: Optional[_GlobInterfaceType]
         promisc=False,  # type: bool
         filter=None,  # type: Optional[str]
         nofilter=False,  # type: bool
         prog=None,  # type: Optional[str]
         *arg,  # type: Any
         **karg  # type: Any
 ):
     # type: (...) -> None
     self.outs = None
     args = ['-w', '-', '-s', '65535']
     if iface is None and (WINDOWS or DARWIN):
         iface = conf.iface
     self.iface = iface
     if iface is not None:
         args.extend(['-i', network_name(iface)])
     if not promisc:
         args.append('-p')
     if not nofilter:
         if conf.except_filter:
             if filter:
                 filter = "(%s) and not (%s)" % (filter, conf.except_filter)
             else:
                 filter = "not (%s)" % conf.except_filter
     if filter is not None:
         args.append(filter)
     self.tcpdump_proc = tcpdump(None, prog=prog, args=args, getproc=True)
     self.reader = PcapReader(self.tcpdump_proc.stdout)
     self.ins = self.reader  # type: ignore
예제 #6
0
def _read_routes_c_v1():
    """Retrieve Windows routes through a GetIpForwardTable call.

    This is compatible with XP but won't get IPv6 routes."""
    def _extract_ip(obj):
        return inet_ntop(socket.AF_INET, struct.pack("<I", obj))

    routes = []
    for route in GetIpForwardTable():
        ifIndex = route['ForwardIfIndex']
        dest = route['ForwardDest']
        netmask = route['ForwardMask']
        nexthop = _extract_ip(route['ForwardNextHop'])
        metric = route['ForwardMetric1']
        # Build route
        try:
            iface = dev_from_index(ifIndex)
            if not iface.ip or iface.ip == "0.0.0.0":
                continue
        except ValueError:
            continue
        ip = iface.ip
        netw = network_name(iface)
        # RouteMetric + InterfaceMetric
        metric = metric + iface.ipv4_metric
        routes.append((dest, netmask, nexthop, netw, ip, metric))
    return routes
예제 #7
0
 def __init__(
         self,
         type=ETH_P_IP,  # type: int
         filter=None,  # type: Optional[str]
         iface=None,  # type: Optional[_GlobInterfaceType]
         promisc=None,  # type: Optional[bool]
         nofilter=0  # type: int
 ):
     # type: (...) -> None
     self.outs = socket.socket(socket.AF_INET, socket.SOCK_RAW,
                               socket.IPPROTO_RAW)  # noqa: E501
     self.outs.setsockopt(socket.SOL_IP, socket.IP_HDRINCL, 1)
     self.ins = socket.socket(socket.AF_PACKET, socket.SOCK_RAW,
                              socket.htons(type))  # noqa: E501
     self.iface = iface
     if iface is not None:
         iface = network_name(iface)
         self.ins.bind((iface, type))
     if not six.PY2:
         try:
             # Receive Auxiliary Data (VLAN tags)
             self.ins.setsockopt(SOL_PACKET, PACKET_AUXDATA, 1)
             self.ins.setsockopt(socket.SOL_SOCKET, SO_TIMESTAMPNS, 1)
             self.auxdata_available = True
         except OSError:
             # Note: Auxiliary Data is only supported since
             #       Linux 2.6.21
             msg = "Your Linux Kernel does not support Auxiliary Data!"
             log_runtime.info(msg)
예제 #8
0
        def __init__(self, device, snaplen, promisc, to_ms, monitor=None):
            device = network_name(device)
            self.errbuf = create_string_buffer(PCAP_ERRBUF_SIZE)
            self.iface = create_string_buffer(device.encode("utf8"))
            self.dtl = None
            if monitor:
                if WINDOWS and not conf.use_npcap:
                    raise OSError("On Windows, this feature requires NPcap !")
                # Npcap-only functions
                from scapy.libs.winpcapy import pcap_create, \
                    pcap_set_snaplen, pcap_set_promisc, \
                    pcap_set_timeout, pcap_set_rfmon, pcap_activate
                self.pcap = pcap_create(self.iface, self.errbuf)
                pcap_set_snaplen(self.pcap, snaplen)
                pcap_set_promisc(self.pcap, promisc)
                pcap_set_timeout(self.pcap, to_ms)
                if pcap_set_rfmon(self.pcap, 1) != 0:
                    log_runtime.error("Could not set monitor mode")
                if pcap_activate(self.pcap) != 0:
                    raise OSError("Could not activate the pcap handler")
            else:
                self.pcap = pcap_open_live(self.iface, snaplen, promisc, to_ms,
                                           self.errbuf)
                error = bytes(bytearray(self.errbuf)).strip(b"\x00")
                if error:
                    raise OSError(error)

            if WINDOWS:
                # Winpcap/Npcap exclusive: make every packet to be instantly
                # returned, and not buffered within Winpcap/Npcap
                pcap_setmintocopy(self.pcap, 0)

            self.header = POINTER(pcap_pkthdr)()
            self.pkt_data = POINTER(c_ubyte)()
            self.bpf_program = bpf_program()
예제 #9
0
 def __init__(self,
              iface=None,
              promisc=None,
              filter=None,
              nofilter=False,
              prog=None,
              *arg,
              **karg):
     self.outs = None
     args = ['-w', '-', '-s', '65535']
     if iface is None and (WINDOWS or DARWIN):
         iface = conf.iface
     self.iface = iface
     if iface is not None:
         args.extend(['-i', network_name(iface)])
     if not promisc:
         args.append('-p')
     if not nofilter:
         if conf.except_filter:
             if filter:
                 filter = "(%s) and not (%s)" % (filter, conf.except_filter)
             else:
                 filter = "not (%s)" % conf.except_filter
     if filter is not None:
         args.append(filter)
     self.tcpdump_proc = tcpdump(None, prog=prog, args=args, getproc=True)
     self.ins = PcapReader(self.tcpdump_proc.stdout)
예제 #10
0
def get_if(iff, cmd):
    """Ease SIOCGIF* ioctl calls"""

    iff = network_name(iff)
    sck = socket.socket()
    try:
        return ioctl(sck, cmd, struct.pack("16s16x", iff.encode("utf8")))
    finally:
        sck.close()
예제 #11
0
def get_if(iff, cmd):
    # type: (Union[NetworkInterface, str], int) -> bytes
    """Ease SIOCGIF* ioctl calls"""

    iff = network_name(iff)
    sck = socket.socket()
    try:
        return ioctl(sck, cmd, struct.pack("16s16x", iff.encode("utf8")))
    finally:
        sck.close()
예제 #12
0
파일: common.py 프로젝트: polybassa/scapy-1
def compile_filter(
        filter_exp,  # type: str
        iface=None,  # type: Optional[Union[str, 'scapy.interfaces.NetworkInterface']]  # noqa: E501
        linktype=None,  # type: Optional[int]
        promisc=False  # type: bool
):
    # type: (...) -> bpf_program
    """Asks libpcap to parse the filter, then build the matching
    BPF bytecode.

    :param iface: if provided, use the interface to compile
    :param linktype: if provided, use the linktype to compile
    """
    try:
        from scapy.libs.winpcapy import (PCAP_ERRBUF_SIZE, pcap_open_live,
                                         pcap_compile, pcap_compile_nopcap,
                                         pcap_close)
    except OSError:
        raise ImportError("libpcap is not available. Cannot compile filter !")
    from ctypes import create_string_buffer
    bpf = bpf_program()
    bpf_filter = create_string_buffer(filter_exp.encode("utf8"))
    if not linktype:
        # Try to guess linktype to avoid root
        if not iface:
            if not conf.iface:
                raise Scapy_Exception(
                    "Please provide an interface or linktype!")
            iface = conf.iface
        # Try to guess linktype to avoid requiring root
        try:
            arphd = get_if_raw_hwaddr(iface)[0]
            linktype = ARPHRD_TO_DLT.get(arphd)
        except Exception:
            # Failed to use linktype: use the interface
            pass
        if not linktype and conf.use_bpf:
            linktype = ARPHDR_ETHER
    if linktype is not None:
        ret = pcap_compile_nopcap(MTU, linktype, ctypes.byref(bpf), bpf_filter,
                                  0, -1)
    elif iface:
        err = create_string_buffer(PCAP_ERRBUF_SIZE)
        iface_b = create_string_buffer(network_name(iface).encode("utf8"))
        pcap = pcap_open_live(iface_b, MTU, promisc, 0, err)
        error = bytes(bytearray(err)).strip(b"\x00")
        if error:
            raise OSError(error)
        ret = pcap_compile(pcap, ctypes.byref(bpf), bpf_filter, 0, -1)
        pcap_close(pcap)
    if ret == -1:
        raise Scapy_Exception("Failed to compile filter expression %s (%s)" %
                              (filter_exp, ret))
    return bpf
예제 #13
0
파일: supersocket.py 프로젝트: tedbe/scapy
    def send(self, pkt):
        """Send a packet"""
        from scapy.layers.l2 import Loopback

        # Use the routing table to find the output interface
        iff = pkt.route()[0]
        if iff is None:
            iff = network_name(conf.iface)

        # Assign the network interface to the BPF handle
        if self.assigned_interface != iff:
            try:
                fcntl.ioctl(self.outs, BIOCSETIF,
                            struct.pack("16s16x", iff.encode()))  # noqa: E501
            except IOError:
                raise Scapy_Exception("BIOCSETIF failed on %s" % iff)
            self.assigned_interface = iff

        # Build the frame
        #
        # LINKTYPE_NULL / DLT_NULL (Loopback) is a special case. From the
        # bpf(4) man page (from macOS/Darwin, but also for BSD):
        #
        # "A packet can be sent out on the network by writing to a bpf file
        # descriptor. [...] Currently only writes to Ethernets and SLIP links
        # are supported."
        #
        # Headers are only mentioned for reads, not writes, and it has the
        # name "NULL" and id=0.
        #
        # The _correct_ behaviour appears to be that one should add a BSD
        # Loopback header to every sent packet. This is needed by FreeBSD's
        # if_lo, and Darwin's if_lo & if_utun.
        #
        # tuntaposx appears to have interpreted "NULL" as "no headers".
        # Thankfully its interfaces have a different name (tunX) to Darwin's
        # if_utun interfaces (utunX).
        #
        # There might be other drivers which make the same mistake as
        # tuntaposx, but these are typically provided with VPN software, and
        # Apple are breaking these kexts in a future version of macOS... so
        # the problem will eventually go away. They already don't work on Macs
        # with Apple Silicon (M1).
        if DARWIN and iff.startswith('tun') and self.guessed_cls == Loopback:
            frame = raw(pkt)
        else:
            frame = raw(self.guessed_cls() / pkt)

        pkt.sent_time = time.time()

        # Send the frame
        L2bpfSocket.send(self, frame)
예제 #14
0
파일: usb.py 프로젝트: polybassa/scapy-1
 def __init__(self, iface=None, *args, **karg):
     _usbpcap_check()
     if iface is None:
         warning("Available interfaces: [%s]",
                 " ".join(x[0] for x in get_usbpcap_interfaces()))
         raise NameError("No interface specified !"
                         " See get_usbpcap_interfaces()")
     iface = network_name(iface)
     self.outs = None
     args = ['-d', iface, '-b', '134217728', '-A', '-o', '-']
     self.usbpcap_proc = subprocess.Popen([conf.prog.usbpcapcmd] + args,
                                          stdout=subprocess.PIPE,
                                          stderr=subprocess.PIPE)
     self.ins = PcapReader(self.usbpcap_proc.stdout)
예제 #15
0
def _read_routes_c(ipv6=False):
    """Retrieve Windows routes through a GetIpForwardTable2 call.

    This is not available on Windows XP !"""
    af = socket.AF_INET6 if ipv6 else socket.AF_INET
    sock_addr_name = 'Ipv6' if ipv6 else 'Ipv4'
    sin_addr_name = 'sin6_addr' if ipv6 else 'sin_addr'
    metric_name = 'ipv6_metric' if ipv6 else 'ipv4_metric'
    if ipv6:
        lifaddr = in6_getifaddr()
    routes = []

    def _extract_ip(obj):
        ip = obj[sock_addr_name][sin_addr_name]
        ip = bytes(bytearray(ip['byte']))
        # Build IP
        ip = inet_ntop(af, ip)
        return ip

    for route in GetIpForwardTable2(af):
        # Extract data
        ifIndex = route['InterfaceIndex']
        dest = _extract_ip(route['DestinationPrefix']['Prefix'])
        netmask = route['DestinationPrefix']['PrefixLength']
        nexthop = _extract_ip(route['NextHop'])
        metric = route['Metric']
        # Build route
        try:
            iface = dev_from_index(ifIndex)
            if not iface.ip or iface.ip == "0.0.0.0":
                continue
        except ValueError:
            continue
        ip = iface.ip
        netw = network_name(iface)
        # RouteMetric + InterfaceMetric
        metric = metric + getattr(iface, metric_name)
        if ipv6:
            _append_route6(routes, dest, netmask, nexthop, netw, lifaddr,
                           metric)
        else:
            routes.append(
                (atol(dest), itom(int(netmask)), nexthop, netw, ip, metric))
    return routes
예제 #16
0
 def __init__(
         self,
         iface=None,  # type: Optional[Union[str, NetworkInterface]]
         type=ETH_P_ALL,  # type: int
         promisc=None,  # type: Optional[Any]
         filter=None,  # type: Optional[Any]
         nofilter=0,  # type: int
         monitor=None,  # type: Optional[Any]
 ):
     # type: (...) -> None
     self.iface = network_name(iface or conf.iface)
     self.type = type
     self.promisc = conf.sniff_promisc if promisc is None else promisc
     self.ins = socket.socket(socket.AF_PACKET, socket.SOCK_RAW,
                              socket.htons(type))
     self.ins.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 0)
     if not nofilter:
         if conf.except_filter:
             if filter:
                 filter = "(%s) and not (%s)" % (filter, conf.except_filter)
             else:
                 filter = "not (%s)" % conf.except_filter
         if filter is not None:
             try:
                 attach_filter(self.ins, filter, self.iface)
             except (ImportError, Scapy_Exception) as ex:
                 log_runtime.error("Cannot set filter: %s", ex)
     if self.promisc:
         set_promisc(self.ins, self.iface)
     self.ins.bind((self.iface, type))
     _flush_fd(self.ins.fileno())
     self.ins.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, conf.bufsize)
     if not six.PY2:
         # Receive Auxiliary Data (VLAN tags)
         try:
             self.ins.setsockopt(SOL_PACKET, PACKET_AUXDATA, 1)
             self.ins.setsockopt(socket.SOL_SOCKET, SO_TIMESTAMPNS, 1)
             self.auxdata_available = True
         except OSError:
             # Note: Auxiliary Data is only supported since
             #       Linux 2.6.21
             msg = "Your Linux Kernel does not support Auxiliary Data!"
             log_runtime.info(msg)
     if not isinstance(self, L2ListenSocket):
         self.outs = self.ins  # type: socket.socket
         self.outs.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF,
                              conf.bufsize)
     else:
         self.outs = None  # type: ignore
     sa_ll = self.ins.getsockname()
     if sa_ll[3] in conf.l2types:
         self.LL = conf.l2types.num2layer[sa_ll[3]]
         self.lvl = 2
     elif sa_ll[1] in conf.l3types:
         self.LL = conf.l3types.num2layer[sa_ll[1]]
         self.lvl = 3
     else:
         self.LL = conf.default_l2
         self.lvl = 2
         warning(
             "Unable to guess type (interface=%s protocol=%#x family=%i). Using %s",
             sa_ll[0], sa_ll[1], sa_ll[3], self.LL.name)  # noqa: E501
예제 #17
0
 def __init__(self, iface=None, type=ETH_P_ALL, promisc=None, filter=None,
              nofilter=0, monitor=None):
     self.iface = network_name(iface or conf.iface)
     self.type = type
     self.promisc = conf.sniff_promisc if promisc is None else promisc
     if monitor is not None:
         log_runtime.info(
             "The 'monitor' argument has no effect on native linux sockets."
         )
     self.ins = socket.socket(
         socket.AF_PACKET, socket.SOCK_RAW, socket.htons(type))
     if not nofilter:
         if conf.except_filter:
             if filter:
                 filter = "(%s) and not (%s)" % (filter, conf.except_filter)
             else:
                 filter = "not (%s)" % conf.except_filter
         if filter is not None:
             try:
                 attach_filter(self.ins, filter, iface)
             except ImportError as ex:
                 log_runtime.error("Cannot set filter: %s", ex)
     if self.promisc:
         set_promisc(self.ins, self.iface)
     self.ins.bind((self.iface, type))
     _flush_fd(self.ins)
     self.ins.setsockopt(
         socket.SOL_SOCKET,
         socket.SO_RCVBUF,
         conf.bufsize
     )
     if not six.PY2:
         # Receive Auxiliary Data (VLAN tags)
         try:
             self.ins.setsockopt(SOL_PACKET, PACKET_AUXDATA, 1)
             self.ins.setsockopt(
                 socket.SOL_SOCKET,
                 SO_TIMESTAMPNS,
                 1
             )
             self.auxdata_available = True
         except OSError:
             # Note: Auxiliary Data is only supported since
             #       Linux 2.6.21
             msg = "Your Linux Kernel does not support Auxiliary Data!"
             log_runtime.info(msg)
     if isinstance(self, L2ListenSocket):
         self.outs = None
     else:
         self.outs = self.ins
         self.outs.setsockopt(
             socket.SOL_SOCKET,
             socket.SO_SNDBUF,
             conf.bufsize
         )
     sa_ll = self.ins.getsockname()
     if sa_ll[3] in conf.l2types:
         self.LL = conf.l2types[sa_ll[3]]
         self.lvl = 2
     elif sa_ll[1] in conf.l3types:
         self.LL = conf.l3types[sa_ll[1]]
         self.lvl = 3
     else:
         self.LL = conf.default_l2
         self.lvl = 2
         warning("Unable to guess type (interface=%s protocol=%#x family=%i). Using %s", sa_ll[0], sa_ll[1], sa_ll[3], self.LL.name)  # noqa: E501
예제 #18
0
def compile_filter(filter_exp, iface=None, linktype=None,
                   promisc=False):
    """Asks libpcap to parse the filter, then build the matching
    BPF bytecode.

    :param iface: if provided, use the interface to compile
    :param linktype: if provided, use the linktype to compile
    """
    try:
        from scapy.libs.winpcapy import (
            PCAP_ERRBUF_SIZE,
            pcap_open_live,
            pcap_compile,
            pcap_compile_nopcap,
            pcap_close
        )
        from scapy.libs.structures import bpf_program
    except OSError:
        raise ImportError(
            "libpcap is not available. Cannot compile filter !"
        )
    from ctypes import create_string_buffer
    bpf = bpf_program()
    bpf_filter = create_string_buffer(filter_exp.encode("utf8"))
    if not linktype:
        # Try to guess linktype to avoid root
        if not iface:
            if not conf.iface:
                raise Scapy_Exception(
                    "Please provide an interface or linktype!"
                )
            iface = conf.iface
        # Try to guess linktype to avoid requiring root
        try:
            arphd = get_if_raw_hwaddr(iface)[0]
            linktype = ARPHRD_TO_DLT.get(arphd)
        except Exception:
            # Failed to use linktype: use the interface
            pass
    if linktype is not None:
        ret = pcap_compile_nopcap(
            MTU, linktype, ctypes.byref(bpf), bpf_filter, 0, -1
        )
    elif iface:
        err = create_string_buffer(PCAP_ERRBUF_SIZE)
        iface = network_name(iface)
        iface = create_string_buffer(iface.encode("utf8"))
        pcap = pcap_open_live(
            iface, MTU, promisc, 0, err
        )
        error = bytes(bytearray(err)).strip(b"\x00")
        if error:
            raise OSError(error)
        ret = pcap_compile(
            pcap, ctypes.byref(bpf), bpf_filter, 0, -1
        )
        pcap_close(pcap)
    if ret == -1:
        raise Scapy_Exception(
            "Failed to compile filter expression %s (%s)" % (filter_exp, ret)
        )
    if conf.use_pypy and sys.pypy_version_info <= (7, 3, 2):
        # PyPy < 7.3.2 has a broken behavior
        # https://foss.heptapod.net/pypy/pypy/-/issues/3298
        return struct.pack(
            'HL',
            bpf.bf_len, ctypes.addressof(bpf.bf_insns.contents)
        )
    return bpf
예제 #19
0
    def __init__(self, iface=None, type=ETH_P_ALL, promisc=None, filter=None,
                 nofilter=0, monitor=False):
        self.fd_flags = None
        self.assigned_interface = None

        # SuperSocket mandatory variables
        if promisc is None:
            self.promisc = conf.sniff_promisc
        else:
            self.promisc = promisc

        self.iface = network_name(iface or conf.iface)

        # Get the BPF handle
        self.ins = None
        (self.ins, self.dev_bpf) = get_dev_bpf()
        self.outs = self.ins

        # Set the BPF buffer length
        try:
            fcntl.ioctl(self.ins, BIOCSBLEN, struct.pack('I', BPF_BUFFER_LENGTH))  # noqa: E501
        except IOError:
            raise Scapy_Exception("BIOCSBLEN failed on /dev/bpf%i" %
                                  self.dev_bpf)

        # Assign the network interface to the BPF handle
        try:
            fcntl.ioctl(self.ins, BIOCSETIF, struct.pack("16s16x", self.iface.encode()))  # noqa: E501
        except IOError:
            raise Scapy_Exception("BIOCSETIF failed on %s" % self.iface)
        self.assigned_interface = self.iface

        # Set the interface into promiscuous
        if self.promisc:
            self.set_promisc(1)

        # Set the interface to monitor mode
        # Note: - trick from libpcap/pcap-bpf.c - monitor_mode()
        #       - it only works on OS X 10.5 and later
        if DARWIN and monitor:
            dlt_radiotap = struct.pack('I', DLT_IEEE802_11_RADIO)
            try:
                fcntl.ioctl(self.ins, BIOCSDLT, dlt_radiotap)
            except IOError:
                raise Scapy_Exception("Can't set %s into monitor mode!" %
                                      self.iface)

        # Don't block on read
        try:
            fcntl.ioctl(self.ins, BIOCIMMEDIATE, struct.pack('I', 1))
        except IOError:
            raise Scapy_Exception("BIOCIMMEDIATE failed on /dev/bpf%i" %
                                  self.dev_bpf)

        # Scapy will provide the link layer source address
        # Otherwise, it is written by the kernel
        try:
            fcntl.ioctl(self.ins, BIOCSHDRCMPLT, struct.pack('i', 1))
        except IOError:
            raise Scapy_Exception("BIOCSHDRCMPLT failed on /dev/bpf%i" %
                                  self.dev_bpf)

        # Configure the BPF filter
        if not nofilter:
            if conf.except_filter:
                if filter:
                    filter = "(%s) and not (%s)" % (filter, conf.except_filter)
                else:
                    filter = "not (%s)" % conf.except_filter
            if filter is not None:
                try:
                    attach_filter(self.ins, filter, self.iface)
                except ImportError as ex:
                    warning("Cannot set filter: %s" % ex)

        # Set the guessed packet class
        self.guessed_cls = self.guess_cls()
예제 #20
0
    def __init__(self,
                 iface=None,
                 mode_tun=None,
                 default_read_size=MTU,
                 strip_packet_info=True,
                 *args,
                 **kwargs):
        self.iface = bytes_encode(
            network_name(conf.iface if iface is None else iface))

        self.mode_tun = mode_tun
        if self.mode_tun is None:
            if self.iface.startswith(b"tun"):
                self.mode_tun = True
            elif self.iface.startswith(b"tap"):
                self.mode_tun = False
            else:
                raise ValueError(
                    "Could not determine interface type for %r; set "
                    "`mode_tun` explicitly." % (self.iface, ))

        self.strip_packet_info = bool(strip_packet_info)

        # This is non-zero when there is some kernel-specific packet info.
        # We add this to any MTU value passed to recv(), and use it to
        # remove leading bytes when strip_packet_info=True.
        self.mtu_overhead = 0

        # The TUN packet specification sends raw IP at us, and doesn't specify
        # which version.
        self.kernel_packet_class = IPv46 if self.mode_tun else Ether

        if LINUX:
            devname = b"/dev/net/tun"

            # Having an EtherType always helps on Linux, then we don't need
            # to use auto-detection of IP version.
            if self.mode_tun:
                self.kernel_packet_class = LinuxTunPacketInfo
                self.mtu_overhead = 4  # len(LinuxTunPacketInfo)
            else:
                warning("tap devices on Linux do not include packet info!")
                self.strip_packet_info = True

            if len(self.iface) > LINUX_IFNAMSIZ:
                warning("Linux interface names are limited to %d bytes, "
                        "truncating!" % (LINUX_IFNAMSIZ, ))
                self.iface = self.iface[:LINUX_IFNAMSIZ]

        elif BSD:  # also DARWIN
            if not (self.iface.startswith(b"tap")
                    or self.iface.startswith(b"tun")):
                raise ValueError("Interface names must start with `tun` or "
                                 "`tap` on BSD and Darwin")
            devname = b"/dev/" + self.iface
            if not self.strip_packet_info:
                warning("tun/tap devices on BSD and Darwin never include "
                        "packet info!")
                self.strip_packet_info = True
        else:
            raise NotImplementedError("TunTapInterface is not supported on "
                                      "this platform!")

        sock = open(devname, "r+b", buffering=0)

        if LINUX:
            if self.mode_tun:
                flags = LINUX_IFF_TUN
            else:
                # Linux can send us LinuxTunPacketInfo for TAP interfaces, but
                # the kernel sends the wrong information!
                #
                # Instead of type=1 (Ether), it sends that of the payload
                # (eg: 0x800 for IPv4 or 0x86dd for IPv6).
                #
                # tap interfaces always send Ether frames, which include a
                # type parameter for the IPv4/v6/etc. payload, so we set
                # IFF_NO_PI.
                flags = LINUX_IFF_TAP | LINUX_IFF_NO_PI

            tsetiff = raw(LinuxTunIfReq(ifrn_name=self.iface,
                                        ifru_flags=flags))

            ioctl(sock, LINUX_TUNSETIFF, tsetiff)

        self.closed = False
        self.default_read_size = default_read_size
        super(TunTapInterface, self).__init__(sock)
예제 #21
0
파일: supersocket.py 프로젝트: tedbe/scapy
    def __init__(self,
                 iface=None,
                 type=ETH_P_ALL,
                 promisc=None,
                 filter=None,
                 nofilter=0,
                 monitor=False):
        self.fd_flags = None
        self.assigned_interface = None

        # SuperSocket mandatory variables
        if promisc is None:
            self.promisc = conf.sniff_promisc
        else:
            self.promisc = promisc

        self.iface = network_name(iface or conf.iface)

        # Get the BPF handle
        self.ins = None
        (self.ins, self.dev_bpf) = get_dev_bpf()
        self.outs = self.ins

        # Set the BPF buffer length
        try:
            fcntl.ioctl(self.ins, BIOCSBLEN,
                        struct.pack('I', BPF_BUFFER_LENGTH))  # noqa: E501
        except IOError:
            raise Scapy_Exception("BIOCSBLEN failed on /dev/bpf%i" %
                                  self.dev_bpf)

        # Assign the network interface to the BPF handle
        try:
            fcntl.ioctl(self.ins, BIOCSETIF,
                        struct.pack("16s16x",
                                    self.iface.encode()))  # noqa: E501
        except IOError:
            raise Scapy_Exception("BIOCSETIF failed on %s" % self.iface)
        self.assigned_interface = self.iface

        # Set the interface into promiscuous
        if self.promisc:
            self.set_promisc(1)

        # Set the interface to monitor mode
        # Note: - trick from libpcap/pcap-bpf.c - monitor_mode()
        #       - it only works on OS X 10.5 and later
        if DARWIN and monitor:
            # Convert macOS version to an integer
            try:
                tmp_mac_version = platform.mac_ver()[0].split(".")
                tmp_mac_version = [int(num) for num in tmp_mac_version]
                macos_version = tmp_mac_version[0] * 10000
                macos_version += tmp_mac_version[1] * 100 + tmp_mac_version[2]
            except (IndexError, ValueError):
                warning("Could not determine your macOS version!")
                macos_version = sys.maxint

            # Disable 802.11 monitoring on macOS Catalina (aka 10.15) and upper
            if macos_version < 101500:
                dlt_radiotap = struct.pack('I', DLT_IEEE802_11_RADIO)
                try:
                    fcntl.ioctl(self.ins, BIOCSDLT, dlt_radiotap)
                except IOError:
                    raise Scapy_Exception("Can't set %s into monitor mode!" %
                                          self.iface)
            else:
                warning("Scapy won't activate 802.11 monitoring, "
                        "as it will crash your macOS kernel!")

        # Don't block on read
        try:
            fcntl.ioctl(self.ins, BIOCIMMEDIATE, struct.pack('I', 1))
        except IOError:
            raise Scapy_Exception("BIOCIMMEDIATE failed on /dev/bpf%i" %
                                  self.dev_bpf)

        # Scapy will provide the link layer source address
        # Otherwise, it is written by the kernel
        try:
            fcntl.ioctl(self.ins, BIOCSHDRCMPLT, struct.pack('i', 1))
        except IOError:
            raise Scapy_Exception("BIOCSHDRCMPLT failed on /dev/bpf%i" %
                                  self.dev_bpf)

        # Configure the BPF filter
        filter_attached = False
        if not nofilter:
            if conf.except_filter:
                if filter:
                    filter = "(%s) and not (%s)" % (filter, conf.except_filter)
                else:
                    filter = "not (%s)" % conf.except_filter
            if filter is not None:
                try:
                    attach_filter(self.ins, filter, self.iface)
                    filter_attached = True
                except ImportError as ex:
                    warning("Cannot set filter: %s" % ex)
        if NETBSD and filter_attached is False:
            # On NetBSD, a filter must be attached to an interface, otherwise
            # no frame will be received by os.read(). When no filter has been
            # configured, Scapy uses a simple tcpdump filter that does nothing
            # more than ensuring the length frame is not null.
            filter = "greater 0"
            try:
                attach_filter(self.ins, filter, self.iface)
            except ImportError as ex:
                warning("Cannot set filter: %s" % ex)

        # Set the guessed packet class
        self.guessed_cls = self.guess_cls()