Ejemplo n.º 1
0
class PCap(object):
    @staticmethod
    def get_devices():
        def ip(addr):
            if addr is None: return None
            return IPAddr(addr, networkOrder=True)

        def link(addr):
            if addr is None: return None
            if len(addr) != 6: return None
            return EthAddr(addr)

        devs = pcapc.findalldevs()
        out = {}
        for d in devs:
            addrs = {}
            n = {'desc': d[1], 'addrs': addrs}
            out[d[0]] = n
            for a in d[2]:
                if a[0] == 'AF_INET':
                    na = {}
                    addrs[a[0]] = na
                    na['addr'] = ip(a[1])
                    na['netmask'] = ip(a[2])
                    na['broadaddr'] = ip(a[3])
                    na['dstaddr'] = ip(a[4])
                elif a[0] == 'AF_LINK':
                    na = {}
                    addrs[a[0]] = na
                    na['addr'] = link(a[1])
                    na['netmask'] = link(a[2])
                    na['broadaddr'] = link(a[3])
                    na['dstaddr'] = link(a[4])
                elif a[0] == 'AF_PACKET':
                    addrs[a[0]] = {'addr': link(a[1])}
                elif a[0] == 'ethernet':
                    addrs[a[0]] = {'addr': link(a[1])}
        return out

    @staticmethod
    def get_device_names():
        return [d[0] for d in pcapc.findalldevs()]

    def __init__(self,
                 device=None,
                 promiscuous=True,
                 period=10,
                 start=True,
                 callback=None,
                 filter=None,
                 use_bytearray=False,
                 **kw):
        """
    Initialize this instance

    use_bytearray: specifies capturing to bytearray buffers instead of bytes
    """

        if filter is not None:
            self.deferred_filter = (filter, )
        else:
            self.deferred_filter = None
        self.packets_received = 0
        self.packets_dropped = 0
        self._thread = None
        self.pcap = None
        self.promiscuous = promiscuous
        self.device = None
        self.use_bytearray = use_bytearray
        self.period = period
        self.netmask = IPAddr("0.0.0.0")
        self._quitting = False
        self.addresses = {}
        if callback is None:
            self.callback = self.__class__._handle_rx
        else:
            self.callback = callback

        for k, v in kw.items():
            assert not hasattr(self, k)
            setattr(self, k, v)

        if device is not None:
            self.open(device)
        if self.pcap is not None:
            if start:
                self.start()

    def _handle_rx(self, data, sec, usec, length):
        pass

    def open(self,
             device,
             promiscuous=None,
             period=None,
             incoming=True,
             outgoing=False):
        assert self.device is None
        self.addresses = self.get_devices()[device]['addrs']
        if 'AF_INET' in self.addresses:
            self.netmask = self.addresses['AF_INET'].get('netmask')
            if self.netmask is None: self.netmask = IPAddr("0.0.0.0")
        #print "NM:",self.netmask
        #print self.addresses['AF_LINK']['addr']
        self.device = device
        if period is not None:
            self.period = period
        if promiscuous is not None:
            self.promiscuous = promiscuous
        self.pcap = pcapc.open_live(device, 65535,
                                    1 if self.promiscuous else 0, self.period)
        pcapc.setdirection(self.pcap, incoming, outgoing)
        self.packets_received = 0
        self.packets_dropped = 0
        if self.deferred_filter is not None:
            self.set_filter(*self.deferred_filter)
            self.deferred_filter = None

    def set_direction(self, incoming, outgoing):
        pcapc.setdirection(self.pcap, incoming, outgoing)

    def _thread_func(self):
        while not self._quitting:
            pcapc.dispatch(self.pcap, 100, self.callback, self,
                           bool(self.use_bytearray))
            self.packets_received, self.packets_dropped = pcapc.stats(
                self.pcap)

        self._quitting = False
        self._thread = None

    def _handle_GoingDownEvent(self, event):
        self.close()

    def start(self):
        assert self._thread is None
        from pox.core import core
        core.addListeners(self, weak=True)
        self._thread = Thread(target=self._thread_func)
        #self._thread.daemon = True
        self._thread.start()

    def stop(self):
        t = self._thread
        if t is not None:
            self._quitting = True
            pcapc.breakloop(self.pcap)
            t.join()

    def close(self):
        if self.pcap is None: return
        self.stop()
        pcapc.close(self.pcap)
        self.pcap = None

    def __del__(self):
        self.close()

    def inject(self, data):
        if isinstance(data, pkt.ethernet):
            data = data.pack()
        if not isinstance(data, (bytes, bytearray)):
            data = bytes(data)  # Give it a try...
        return pcapc.inject(self.pcap, data)

    def set_filter(self, filter, optimize=True):
        if self.pcap is None:
            self.deferred_filter = (filter, optimize)
            return

        if isinstance(filter, str):
            filter = Filter(filter,
                            optimize,
                            self.netmask.toSignedN(),
                            pcap_obj=self)
        elif isinstance(filter, Filter):
            pass
        else:
            raise RuntimeError("Filter must be string or Filter object")

        pcapc.setfilter(self.pcap, filter._pprogram)
class PCap(object):
    use_select = False  # Falls back to non-select

    @staticmethod
    def get_devices():
        def ip(addr):
            if addr is None:
                return None
            return IPAddr(addr, networkOrder=True)

        def ip6(addr):
            if addr is None:
                return None
            return IPAddr6.from_raw(addr)

        def link(addr):
            if addr is None:
                return None
            if len(addr) != 6:
                return None
            return EthAddr(addr)

        devs = pcapc.findalldevs()
        out = {}
        for d in devs:
            addrs = {}
            n = {"desc": d[1], "addrs": addrs}
            out[d[0]] = n
            for a in d[2]:
                if a[0] == "AF_INET":
                    na = {}
                    addrs[a[0]] = na
                    na["addr"] = ip(a[1])
                    na["netmask"] = ip(a[2])
                    na["broadaddr"] = ip(a[3])
                    na["dstaddr"] = ip(a[4])
                elif a[0] == "AF_INET6":
                    na = {}
                    addrs[a[0]] = na
                    na["addr"] = ip6(a[1])
                    na["netmask"] = ip6(a[2])
                    na["broadaddr"] = ip6(a[3])
                    na["dstaddr"] = ip6(a[4])
                elif a[0] == "AF_LINK":
                    na = {}
                    addrs[a[0]] = na
                    na["addr"] = link(a[1])
                    na["netmask"] = link(a[2])
                    na["broadaddr"] = link(a[3])
                    na["dstaddr"] = link(a[4])
                elif a[0] == "AF_PACKET":
                    addrs[a[0]] = {"addr": link(a[1])}
                elif a[0] == "ethernet":
                    addrs[a[0]] = {"addr": link(a[1])}
        return out

    @staticmethod
    def get_device_names():
        return [d[0] for d in pcapc.findalldevs()]

    def __init__(
        self,
        device=None,
        promiscuous=True,
        period=10,
        start=True,
        callback=None,
        filter=None,
        use_bytearray=False,
        **kw
    ):
        """
    Initialize this instance

    use_bytearray: specifies capturing to bytearray buffers instead of bytes
    """

        if filter is not None:
            self.deferred_filter = (filter,)
        else:
            self.deferred_filter = None
        self.packets_received = 0
        self.packets_dropped = 0
        self._thread = None
        self.pcap = None
        self.promiscuous = promiscuous
        self.device = None
        self.use_bytearray = use_bytearray
        self.period = period
        self.netmask = IPAddr("0.0.0.0")
        self._quitting = False
        self.addresses = {}
        if callback is None:
            self.callback = self.__class__._handle_rx
        else:
            self.callback = callback

        for k, v in kw.items():
            assert not hasattr(self, k)
            setattr(self, k, v)

        if device is not None:
            self.open(device)
        if self.pcap is not None:
            if start:
                self.start()

    def _handle_rx(self, data, sec, usec, length):
        pass

    def open(self, device, promiscuous=None, period=None, incoming=True, outgoing=False):
        assert self.device is None
        self.addresses = self.get_devices()[device]["addrs"]
        if "AF_INET" in self.addresses:
            self.netmask = self.addresses["AF_INET"].get("netmask")
            if self.netmask is None:
                self.netmask = IPAddr("0.0.0.0")
        # print "NM:",self.netmask
        # print self.addresses['AF_LINK']['addr']
        self.device = device
        if period is not None:
            self.period = period
        if promiscuous is not None:
            self.promiscuous = promiscuous
        self.pcap = pcapc.open_live(device, 65535, 1 if self.promiscuous else 0, self.period)
        pcapc.setdirection(self.pcap, incoming, outgoing)
        self.packets_received = 0
        self.packets_dropped = 0
        if self.deferred_filter is not None:
            self.set_filter(*self.deferred_filter)
            self.deferred_filter = None

    def set_direction(self, incoming, outgoing):
        pcapc.setdirection(self._pcap, incoming, outgoing)

    def set_nonblocking(self, nonblocking=True):
        pcapc.setnonblock(self._pcap, 1 if nonblocking else 0)

    def set_blocking(self, blocking=True):
        self.set_nonblocking(nonblocking=not blocking)

    @property
    def blocking(self):
        return False if pcapc.getnonblock(self._pcap) else True

    @blocking.setter
    def blocking(self, value):
        self.set_blocking(value)

    def next_packet(self, allow_threads=True):
        """
    Get next packet

    Returns tuple with:
      data, timestamp_seconds, timestamp_useconds, total length, and
      the pcap_next_ex return value -- 1 is success
    """
        return pcapc.next_ex(self._pcap, bool(self.use_bytearray), allow_threads)

    def _select_thread_func(self):
        try:
            import select

            fd = [self.fileno()]
        except:
            # Fall back
            self._thread_func()
            return

        self.blocking = False

        while not self._quitting:
            rr, ww, xx = select.select(fd, [], fd, 2)

            if xx:
                # Apparently we're done here.
                break
            if rr:
                r = self.next_packet(allow_threads=False)
                if r[-1] == 0:
                    continue
                if r[-1] == 1:
                    self.callback(self, r[0], r[1], r[2], r[3])
                else:
                    break

        self._quitting = False
        self._thread = None

    def _thread_func(self):
        while not self._quitting:
            pcapc.dispatch(self.pcap, 100, self.callback, self, bool(self.use_bytearray), True)
            self.packets_received, self.packets_dropped = pcapc.stats(self.pcap)

        self._quitting = False
        self._thread = None

    def _handle_GoingDownEvent(self, event):
        self.close()

    def start(self):
        assert self._thread is None
        from pox.core import core

        core.addListeners(self, weak=True)

        if self.use_select:
            self._thread = Thread(target=self._select_thread_func)
        else:
            self._thread = Thread(target=self._thread_func)
        # self._thread.daemon = True
        self._thread.start()

    def stop(self):
        t = self._thread
        if t is not None:
            self._quitting = True
            pcapc.breakloop(self.pcap)
            t.join()

    def close(self):
        if self.pcap is None:
            return
        self.stop()
        pcapc.close(self.pcap)
        self.pcap = None

    def __del__(self):
        self.close()

    @property
    def _pcap(self):
        if self.pcap is None:
            raise RuntimeError("PCap object not open")
        return self.pcap

    def inject(self, data):
        if isinstance(data, pkt.ethernet):
            data = data.pack()
        if not isinstance(data, (bytes, bytearray)):
            data = bytes(data)  # Give it a try...
        return pcapc.inject(self.pcap, data)

    def set_filter(self, filter, optimize=True):
        if self.pcap is None:
            self.deferred_filter = (filter, optimize)
            return

        if isinstance(filter, str):
            filter = Filter(filter, optimize, self.netmask.toSignedN(), pcap_obj=self)
        elif isinstance(filter, Filter):
            pass
        else:
            raise RuntimeError("Filter must be string or Filter object")

        pcapc.setfilter(self.pcap, filter._pprogram)

    def fileno(self):
        if self.pcap is None:
            raise RuntimeError("PCap object not open")
        r = pcapc.get_selectable_fd(self.pcap)
        if r == -1:
            raise RuntimeError("Selectable FD not available")
        return r

    def __str__(self):
        return "PCap(device=%s)" % (self.device)
Ejemplo n.º 3
0
class PCap (object):
  @staticmethod
  def get_devices ():
    def ip (addr):
      if addr is None: return None
      return IPAddr(addr, networkOrder=True)
    def link (addr):
      if addr is None: return None
      if len(addr) != 6: return None
      return EthAddr(addr)
    devs = pcapc.findalldevs()
    out = {}
    for d in devs:
      addrs = {}
      n = {'desc':d[1],'addrs':addrs}
      out[d[0]] = n
      for a in d[2]:
        if a[0] == 'AF_INET':
          na = {}
          addrs[a[0]] = na
          na['addr'] = ip(a[1])
          na['netmask'] = ip(a[2])
          na['broadaddr'] = ip(a[3])
          na['dstaddr'] = ip(a[4])
        elif a[0] == 'AF_LINK':
          na = {}
          addrs[a[0]] = na
          na['addr'] = link(a[1])
          na['netmask'] = link(a[2])
          na['broadaddr'] = link(a[3])
          na['dstaddr'] = link(a[4])
        elif a[0] == 'AF_PACKET':
          addrs[a[0]] = {'addr':link(a[1])}
        elif a[0] == 'ethernet':
          addrs[a[0]] = {'addr':link(a[1])}
    return out

  @staticmethod
  def get_device_names ():
    return [d[0] for d in pcapc.findalldevs()]

  def __init__ (self, device = None, promiscuous = True, period = 10,
                start = True, callback = None, filter = None):
    if filter is not None:
      self.deferred_filter = (filter,)
    else:
      self.deferred_filter = None
    self.packets_received = 0
    self.packets_dropped = 0
    self._thread = None
    self.pcap = None
    self.promiscuous = promiscuous
    self.device = None
    self.period = period
    self.netmask = IPAddr("0.0.0.0")
    self._quitting = False
    self.addresses = {}
    if callback is None:
      self.callback = self.__class__._handle_rx
    else:
      self.callback = callback
    if device is not None:
      self.open(device)
    if self.pcap is not None:
      if start:
        self.start()

  def _handle_rx (self, data, sec, usec, length):
    pass

  def open (self, device, promiscuous = None, period = None,
            incoming = True, outgoing = False):
    assert self.device is None
    self.addresses = self.get_devices()[device]['addrs']
    if 'AF_INET' in self.addresses:
      self.netmask = self.addresses['AF_INET'].get('netmask')
      if self.netmask is None: self.netmask = IPAddr("0.0.0.0")
    #print "NM:",self.netmask
    #print self.addresses['AF_LINK']['addr']
    self.device = device
    if period is not None:
      self.period = period
    if promiscuous is not None:
      self.promiscuous = promiscuous
    self.pcap = pcapc.open_live(device, 65535,
                                1 if self.promiscuous else 0, self.period)
    pcapc.setdirection(self.pcap, incoming, outgoing)
    self.packets_received = 0
    self.packets_dropped = 0
    if self.deferred_filter is not None:
      self.set_filter(*self.deferred_filter)
      self.deferred_filter = None

  def set_direction (self, incoming, outgoing):
    pcapc.setdirection(self.pcap, incoming, outgoing)

  def _thread_func (self):
    while not self._quitting:
      pcapc.dispatch(self.pcap,100,self.callback,self)
      self.packets_received,self.packets_dropped = pcapc.stats(self.pcap)

    self._quitting = False
    self._thread = None

  def _handle_GoingDownEvent (self, event):
    self.close()

  def start (self):
    assert self._thread is None
    from pox.core import core
    core.addListeners(self, weak=True)
    self._thread = Thread(target=self._thread_func)
    #self._thread.daemon = True
    self._thread.start()

  def stop (self):
    t = self._thread
    if t is not None:
      self._quitting = True
      pcapc.breakloop(self.pcap)
      t.join()

  def close (self):
    if self.pcap is None: return
    self.stop()
    pcapc.close(self.pcap)
    self.pcap = None

  def __del__ (self):
    self.close()

  def inject (self, data):
    if isinstance(data, pkt.ethernet):
      data = data.pack()
    if not isinstance(data, bytes):
      data = bytes(data) # Give it a try...
    return pcapc.inject(self.pcap, data)

  def set_filter (self, filter, optimize = True):
    if self.pcap is None:
      self.deferred_filter = (filter, optimize)
      return

    if isinstance(filter, str):
      filter = Filter(filter, optimize, self.netmask.toSignedN(),
                      pcap_obj=self)
    elif isinstance(filter, Filter):
      pass
    else:
      raise RuntimeError("Filter must be string or Filter object")

    pcapc.setfilter(self.pcap, filter._pprogram)
Ejemplo n.º 4
0
class PCap(object):
    use_select = True  # Falls back to non-select

    @staticmethod
    def get_devices():
        def ip(addr):
            if addr is None: return None
            return IPAddr(addr, networkOrder=True)

        def ip6(addr):
            if addr is None: return None
            return IPAddr6.from_raw(addr)

        def link(addr):
            if addr is None: return None
            if len(addr) != 6: return None
            return EthAddr(addr)

        devs = pcapc.findalldevs()
        out = {}
        for d in devs:
            addrs = {}
            n = {'desc': d[1], 'addrs': addrs}
            out[d[0]] = n
            for a in d[2]:
                if a[0] == 'AF_INET':
                    na = {}
                    addrs[a[0]] = na
                    na['addr'] = ip(a[1])
                    na['netmask'] = ip(a[2])
                    na['broadaddr'] = ip(a[3])
                    na['dstaddr'] = ip(a[4])
                elif a[0] == 'AF_INET6':
                    na = {}
                    addrs[a[0]] = na
                    na['addr'] = ip6(a[1])
                    na['netmask'] = ip6(a[2])
                    na['broadaddr'] = ip6(a[3])
                    na['dstaddr'] = ip6(a[4])
                elif a[0] == 'AF_LINK':
                    na = {}
                    addrs[a[0]] = na
                    na['addr'] = link(a[1])
                    na['netmask'] = link(a[2])
                    na['broadaddr'] = link(a[3])
                    na['dstaddr'] = link(a[4])
                elif a[0] == 'AF_PACKET':
                    addrs[a[0]] = {'addr': link(a[1])}
                elif a[0] == 'ethernet':
                    addrs[a[0]] = {'addr': link(a[1])}
        return out

    @staticmethod
    def get_device_names():
        return [d[0] for d in pcapc.findalldevs()]

    def __init__(self,
                 device=None,
                 promiscuous=True,
                 period=10,
                 start=True,
                 callback=None,
                 filter=None,
                 use_bytearray=False,
                 **kw):
        """
    Initialize this instance

    use_bytearray: specifies capturing to bytearray buffers instead of bytes
    """

        if filter is not None:
            self.deferred_filter = (filter, )
        else:
            self.deferred_filter = None
        self.packets_received = 0
        self.packets_dropped = 0
        self._thread = None
        self._stop_semaphore = None  # Used when use_select=True
        self.pcap = None
        self.promiscuous = promiscuous
        self.device = None
        self.use_bytearray = use_bytearray
        self.period = period
        self.netmask = IPAddr("0.0.0.0")
        self._quitting = False
        self.addresses = {}
        if callback is None:
            self.callback = self.__class__._handle_rx
        else:
            self.callback = callback

        for k, v in kw.items():
            assert not hasattr(self, k)
            setattr(self, k, v)

        if device is not None:
            self.open(device)
        if self.pcap is not None:
            if start:
                self.start()

    def _handle_rx(self, data, sec, usec, length):
        pass

    def open(self,
             device,
             promiscuous=None,
             period=None,
             incoming=True,
             outgoing=False):
        assert self.device is None
        self.addresses = self.get_devices()[device]['addrs']
        if 'AF_INET' in self.addresses:
            self.netmask = self.addresses['AF_INET'].get('netmask')
            if self.netmask is None: self.netmask = IPAddr("0.0.0.0")
        #print "NM:",self.netmask
        #print self.addresses['AF_LINK']['addr']
        self.device = device
        if period is not None:
            self.period = period
        if promiscuous is not None:
            self.promiscuous = promiscuous
        self.pcap = pcapc.open_live(device, 65535,
                                    1 if self.promiscuous else 0, self.period)
        pcapc.setdirection(self.pcap, incoming, outgoing)
        self.packets_received = 0
        self.packets_dropped = 0
        if self.deferred_filter is not None:
            self.set_filter(*self.deferred_filter)
            self.deferred_filter = None

    def set_direction(self, incoming, outgoing):
        pcapc.setdirection(self._pcap, incoming, outgoing)

    def set_nonblocking(self, nonblocking=True):
        pcapc.setnonblock(self._pcap, 1 if nonblocking else 0)

    def set_blocking(self, blocking=True):
        self.set_nonblocking(nonblocking=not blocking)

    @property
    def blocking(self):
        return False if pcapc.getnonblock(self._pcap) else True

    @blocking.setter
    def blocking(self, value):
        self.set_blocking(value)

    def next_packet(self, allow_threads=True):
        """
    Get next packet

    Returns tuple with:
      data, timestamp_seconds, timestamp_useconds, total length, and
      the pcap_next_ex return value -- 1 is success
    """
        return pcapc.next_ex(self._pcap, bool(self.use_bytearray),
                             allow_threads)

    def _thread_func(self):
        while not self._quitting:
            pcapc.dispatch(self.pcap, 100, self.callback, self,
                           bool(self.use_bytearray), True)
            self.packets_received, self.packets_dropped = pcapc.stats(
                self.pcap)

        self._quitting = False
        self._thread = None

    def _handle_GoingDownEvent(self, event):
        self.close()

    def start(self):
        assert self._thread is None
        from pox.core import core
        core.addListeners(self, weak=True)

        if self.use_select:
            try:
                import select
            except:
                # Fall back
                self.use_select = False
                # Log warning?

        if self.use_select:
            self.blocking = False
            self._thread = pcap_select_loop.add(self)
        else:
            self._thread = Thread(target=self._thread_func)
            self._thread.start()

    def stop(self):
        t = self._thread
        if t is not None:
            if self.use_select:
                self._quitting = True
                self._stop_semaphore = Semaphore(0)
                pcap_select_loop.remove(self)
                pcapc.breakloop(self.pcap)
                self._stop_semaphore.acquire()
                self._stop_semaphore = None
            else:
                self._quitting = True
                pcapc.breakloop(self.pcap)
                t.join()
            self._thread = None

    def _notify_quit(self):
        if self._stop_semaphore:
            self._stop_semaphore.release()

    def close(self):
        if self.pcap is None: return
        self.stop()
        pcapc.close(self.pcap)
        self.pcap = None

    def __del__(self):
        self.close()

    @property
    def _pcap(self):
        if self.pcap is None:
            raise RuntimeError("PCap object not open")
        return self.pcap

    def inject(self, data):
        if isinstance(data, pkt.ethernet):
            data = data.pack()
        if not isinstance(data, (bytes, bytearray)):
            data = bytes(data)  # Give it a try...
        return pcapc.inject(self.pcap, data)

    def set_filter(self, filter, optimize=True):
        if self.pcap is None:
            self.deferred_filter = (filter, optimize)
            return

        if isinstance(filter, str):
            filter = Filter(filter,
                            optimize,
                            self.netmask.toSignedN(),
                            pcap_obj=self)
        elif isinstance(filter, Filter):
            pass
        else:
            raise RuntimeError("Filter must be string or Filter object")

        pcapc.setfilter(self.pcap, filter._pprogram)

    def fileno(self):
        if self.pcap is None:
            raise RuntimeError("PCap object not open")
        r = pcapc.get_selectable_fd(self.pcap)
        if r == -1:
            raise RuntimeError("Selectable FD not available")
        return r

    def __str__(self):
        return "PCap(device=%s)" % (self.device)