Exemple #1
0
def pid_connections(pid: int, kind: str) -> Iterator[Connection]:
    allowed_combos = _util.conn_kind_to_combos(kind)
    if not allowed_combos:
        return

    for kfile in _list_kinfo_files(pid):
        if kfile.fd_fd < 0 or kfile.f_type != DTYPE_SOCKET:
            continue

        family = socket.AddressFamily(kfile.so_family)  # pylint: disable=no-member
        stype = socket.SocketKind(kfile.so_type)  # pylint: disable=no-member
        if (family, stype) not in allowed_combos:
            continue

        laddr: Union[Tuple[str, int], str]
        raddr: Union[Tuple[str, int], str]
        if family == socket.AF_INET:
            laddr = _util.decode_inet4_full(
                kfile.inp_laddru[0],
                _util.cvt_endian_ntoh(kfile.inp_lport,
                                      ctypes.sizeof(ctypes.c_uint16)),
            )
            raddr = _util.decode_inet4_full(
                kfile.inp_faddru[0],
                _util.cvt_endian_ntoh(kfile.inp_fport,
                                      ctypes.sizeof(ctypes.c_uint16)),
            )

        elif family == socket.AF_INET6:
            laddr = _util.decode_inet6_full(
                _pack_addr6(kfile.inp_laddru),
                _util.cvt_endian_ntoh(kfile.inp_lport,
                                      ctypes.sizeof(ctypes.c_uint16)),
            )
            raddr = _util.decode_inet6_full(
                _pack_addr6(kfile.inp_faddru),
                _util.cvt_endian_ntoh(kfile.inp_fport,
                                      ctypes.sizeof(ctypes.c_uint16)),
            )

        elif family == socket.AF_UNIX:
            laddr = os.fsdecode(kfile.unp_path)
            raddr = ""
        else:
            # We shouldn't get here
            continue

        status = None
        if stype == socket.SOCK_STREAM and family != socket.AF_UNIX:
            status = _TCP_STATES[kfile.t_state]

        yield Connection(
            family=family,
            type=stype,
            laddr=laddr,
            raddr=raddr,
            status=status,
            fd=kfile.fd_fd,
            pid=kfile.p_pid,
        )
def socktype_to_enum(num):
    """Convert a numeric socket type value to an IntEnum member.
    If it's not a known member, return the numeric value itself.
    """
    if enum is None:
        return num
    else:  # pragma: no cover
        try:
            return socket.SocketKind(num)
        except ValueError:
            return num
Exemple #3
0
def pid_connections(pid: int, kind: str) -> Iterator[Connection]:
    allowed_combos = _util.conn_kind_to_combos(kind)
    if not allowed_combos:
        return

    kfiles = {
        kfile.ki_fdata: (kfile.ki_pid, kfile.ki_fd)
        for kfile in _list_kinfo_files(pid)
        if kfile.ki_fd >= 0 and kfile.ki_ftype == DTYPE_SOCKET
    }
    if not kfiles:
        return

    for (family, stype) in allowed_combos:
        base_mib = _bsd.sysctlnametomib(
            "net.{}.pcblist".format(_SOCK_TYPES[family][stype]),
            maxlen=4,
        )

        mib = [
            *base_mib,
            PCB_ALL,
            0,
            ctypes.sizeof(KinfoPcb),
            1000000,
        ]

        kinfo_pcb_data = _bsd.sysctl_bytes_retry(mib, None)
        for kpcb in (KinfoPcb *
                     (len(kinfo_pcb_data) // ctypes.sizeof(KinfoPcb))
                     ).from_buffer_copy(kinfo_pcb_data):
            try:
                pid, fd = kfiles.pop(kpcb.ki_sockaddr)
            except KeyError:
                continue

            yield Connection(
                family=socket.AddressFamily(kpcb.ki_family),  # pylint: disable=no-member
                type=socket.SocketKind(kpcb.ki_type),  # pylint: disable=no-member
                laddr=kpcb.ki_s.to_addr(kpcb.ki_family),
                raddr=kpcb.ki_d.to_addr(kpcb.ki_family),
                status=(_TCP_STATES[kpcb.ki_tstate]
                        if kpcb.ki_type == socket.SOCK_STREAM
                        and kpcb.ki_family != socket.AF_UNIX else None),
                fd=fd,
                pid=pid,
            )

            if not kfiles:
                return
Exemple #4
0
    def __init__(self, network_manager, domain, sock_type, protocol):
        """
        Initialize a socket of the specified type. Raises an exception
        if the socket type is not supported.

        Args:
            network_manager: A reference to the `Network` object.
            domain: socket domain (as defined in python `socket`).
            type: socket type (as defined in python `socket`).
            protocol: socket protocol (as defined in python `socket`).
        """
        if not hasattr(socket, "SOCK_CLOEXEC"):
            # Windows support
            socket.SOCK_CLOEXEC = 0x80000
            socket.SOCK_NONBLOCK = 0x800
            socket.AF_UNIX = 0x1

        sock_type &= ~(socket.SOCK_CLOEXEC | socket.SOCK_NONBLOCK)
        sock_type = socket.SocketKind(sock_type)

        self._errno = 0
        self.network = network_manager
        self.domain = domain
        self.type = sock_type
        self.protocol = protocol
        self.host_and_port = (None, None)
        self._is_nonblock = True

        self.history = defaultdict(list)
        self.sock = None

        if domain == socket.AF_UNIX:
            raise Exception("[BaseSocket] AF_UNIX domain not supported.")

        if sock_type == socket.SOCK_RAW:
            self.sock = RawSocketSimulator(self.domain)
    def __init__(self, log_ts, start_ts, hb):
        self._log_timestamp = log_ts  # timestamp when the logevent occurred on the test system
        self._sut_timestamp = hb[
            'ts']  # timestamp of the event on the system under test
        self._sut_start_ts = start_ts
        self._pid = hb[
            'pid']  # TODO: should never change, still required here?
        # self._process_name = hb['name']   # should never change
        self._status = hb['status']
        # self._username = hb['username']   # should never change
        self._cpu_percent = hb['cpu_percent']
        self._mem_percent = hb['memory_percent']
        self._num_threads = hb['num_threads']
        self._num_fds = hb['num_fds']

        # network connections
        # https://psutil.readthedocs.io/en/latest/#psutil.Process.connections
        self._connections = list()
        for con in hb['connections']:
            fd = con[0]

            # fix: psutils encodes AF_INET6 with 10, corresponds with 30 in socket.AddressFamily
            af_inet_idx = con[1] if (con[1] != 10) else 30
            address_family = socket.AddressFamily(af_inet_idx).name
            socket_kind = socket.SocketKind(con[2]).name

            listen_addr = con[3]
            if len(listen_addr) > 0:
                laddr = {'ip': listen_addr[0], 'port': listen_addr[1]}
            else:
                laddr = {'ip': '', 'port': ''}

            remote_addr = con[4]
            if len(remote_addr) > 0:
                raddr = {'ip': remote_addr[0], 'port': remote_addr[1]}
            else:
                raddr = {'ip': '', 'port': ''}

            status = con[5]

            con_dict = {
                'fd': fd,
                'family': address_family,
                'type': socket_kind,
                'laddr': laddr,
                'raddr': raddr,
                'status': status
            }
            self._connections.append(con_dict)

        # Memory consumption
        # https://psutil.readthedocs.io/en/latest/#psutil.Process.memory_full_info
        # http://grodola.blogspot.com/2016/02/psutil-4-real-process-memory-and-environ.html
        mem_info = hb['memory_info']
        mem_rss = mem_info[0] / (1024 * 1024)
        mem_vms = mem_info[1] / (1024 * 1024)
        mem_shared = mem_info[2] / (1024 * 1024)
        mem_text = mem_info[3] / (1024 * 1024)
        mem_lib = mem_info[4] / (1024 * 1024)
        mem_data = mem_info[5] / (1024 * 1024)
        mem_dirty = mem_info[6] / (1024 * 1024)
        self._memory = {
            'rss': mem_rss,
            'vms': mem_vms,
            'shared': mem_shared,
            'text': mem_text,
            'lib': mem_lib,
            'data': mem_data,
            'dirty': mem_dirty
        }

        # I/O
        # https://psutil.readthedocs.io/en/latest/#psutil.Process.io_counters
        io_counters = hb['io_counters']
        io_read_count = io_counters[0]
        io_write_count = io_counters[1]
        io_read_chars = io_counters[4]  # bytes read via syscalls
        io_write_chars = io_counters[5]  # bytes written via syscalls
        self._io_counters = {
            'read_count': io_read_count,
            'write_count': io_write_count,
            'read_chars': io_read_chars,
            'write_chars': io_write_chars
        }

        # CPU times
        # https://psutil.readthedocs.io/en/latest/#psutil.Process.cpu_times
        cpu_times = hb['cpu_times']
        self._cpu_times = {
            'user': cpu_times[0],
            'system': cpu_times[1],
            'children_user': cpu_times[2],
            'children_system': cpu_times[3]
        }

        # Context switches
        # https://psutil.readthedocs.io/en/latest/#psutil.Process.num_ctx_switches
        ctx_switches = hb['num_ctx_switches']
        self._ctx_switches = {
            'voluntary': ctx_switches[0],
            'involuntary': ctx_switches[1]
        }

        # Open files
        # https://psutil.readthedocs.io/en/latest/#psutil.Process.open_files
        open_files = hb['open_files']
        self._open_files = list()
        for f in open_files:
            self._open_files.append({
                'path': f[0],
                'fd': f[1],
                'pos': f[2],
                'mode': f[3],
                'flags': f[4]
            })