Implement basic introspection into what is passed.

master
LEdoian 9 months ago
parent d2980cf789
commit 68b09cdb8c

@ -9,6 +9,7 @@ import selectors
from dataclasses import dataclass
import logging as log
import math
import termcolor # external dep, TODO
# Note: get/setrlimit are in resource module
def setup_logging():
@ -36,9 +37,30 @@ def hexdump(data: bytes) -> list[str]: # We will be prefixing the lines with sig
result.append(line)
return result
# fd types from inode(7)
fdtypes = {
S_IFSOCK: 'socket',
S_IFLNK: 'symlink',
S_IFREG: 'regular file',
S_IFBLK: 'blockdev',
S_IFDIR: 'directory',
S_IFCHR: 'chardev',
S_IFIFO: 'fifo',
}
def fdinfo(fd: int) -> str:
result = []
stat = os.fstat(fd)
# TODO: return something
type = S_IFMT(stat.st_mode)
result.append(f'type: {fdtypes.get(type, f"UNKNOWN: {type}")}')
if S_ISREG(stat.st_mode):
result.append(f'size: {stat.st_size}')
orig_offset = os.lseek(fd, 0, os.SEEK_CUR)
os.lseek(fd, 0, os.SEEK_SET)
head = os.read(fd, 256)
result.extend(hexdump(head))
os.lseek(fd, orig_offset, os.SEEK_SET)
return result
def fd_readlink(fd: int, pid: int | None =None) -> str:
if pid is None:
@ -49,12 +71,66 @@ def fd_readlink(fd: int, pid: int | None =None) -> str:
except OSError as e:
return f"Could not read {fd_link}: {e.strerror} (errno {e.errno})"
def dirprintlines(dir: Direction, lines, file=sys.stdout, indent=''):
if isinstance(lines, str): lines = [lines]
lines_to_print = [f'{dir.sigil} {indent}{line}' for line in lines]
if True or COLOR:
lines_to_print = [termcolor.colored(line, dir.color) for line in lines_to_print]
print(*lines_to_print, sep='\n', file=file)
def show_fd(dir, fd, /, indent=' '):
# Here we decide what to show and format it. We leave any particular
# decisions on other functions.
dirprintlines(dir, f'link: {fd_readlink(fd)}', indent=indent)
dirprintlines(dir, fdinfo(fd), indent=indent)
# Maps from integers to symbolic names, acc to unix(7)
sockopts = {getattr(sk, name): name for name in(
'SO_PASSCRED',
'SO_PASSSEC',
# 'SO_PEEK_OFF', # wtf python does not have this
'SO_PEERCRED',
'SO_PEERSEC',
)}
anclevels = {getattr(sk, name): name for name in(
'SOL_SOCKET',
)}
anctypes = {getattr(sk, name): name for name in(
'SCM_RIGHTS',
'SCM_CREDENTIALS',
# 'SCM_SECURITY', # wtf python does not have this
)}
def show_anc(dir, a, /, indent=' ') -> list[int]:
"returns a possible list of file descriptors"
result = []
level, type, data = a
if level == sk.SOL_SOCKET and type == sk.SCM_RIGHTS:
# A file descriptor
fds = array('i')
fds.frombytes(data)
dirprintlines(dir, f'Received {len(fds)} file descriptor{"s"*(len(fds)!=1)}', indent=indent)
result = list(fds)
for fd in fds:
show_fd(dir, fd, indent=2*indent)
else:
dirprintlines(dir, 'Cannot show details.', indent=indent)
return result
def fwd_traffic(frm: sk.socket, to: sk.socket, dir: Direction):
print(f'{dir.sigil} there be data from {frm}')
chunk_size = 640*1024 # … idk, ought to be enough for anyone…
data, anc, flags, _addr = frm.recvmsg(chunk_size, chunk_size)
# TODO: inspect
fds = [] # potential fds
data, anc, flags, addr = frm.recvmsg(chunk_size, chunk_size)
dirprintlines(dir, f'Forwarding {len(data)} bytes and {len(anc)} ancillary from {addr} to {to}')
dirprintlines(dir, hexdump(data), indent=' ')
for i,a in enumerate(anc):
anclevel, anctype, _ancdata = a
dirprintlines(dir, f'Ancillary #{i}: level {anclevels[anclevel]}, type {anctypes[anctype]}')
fds = show_anc(dir, a)
to.sendmsg([data], anc, flags)
if fds: log.debug(f'Closing fds: {fds}')
for fd in fds: os.close(fd)
def main():
setup_logging()

Loading…
Cancel
Save