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
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
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] })